13#include "mlir/Dialect/OpenACC/OpenACCOpsDialect.h.inc"
14#include "mlir/Dialect/OpenMP/OpenMPOpsDialect.h.inc"
15#include "mlir/IR/PatternMatch.h"
16#include "mlir/Interfaces/DataLayoutInterfaces.h"
17#include "mlir/Pass/Pass.h"
18#include "mlir/Transforms/DialectConversion.h"
28#include "llvm/ADT/TypeSwitch.h"
34#define GEN_PASS_DEF_CXXABILOWERING
35#include "clang/CIR/Dialect/Passes.h.inc"
42bool isCXXABIAttributeLegal(
const mlir::TypeConverter &tc,
43 mlir::Attribute
attr) {
50 if (isa<mlir::acc::OpenACCDialect, mlir::omp::OpenMPDialect>(
56 if (
isa<mlir::DenseArrayAttr, mlir::FloatAttr, mlir::UnitAttr,
57 mlir::StringAttr, mlir::IntegerAttr, mlir::SymbolRefAttr,
58 cir::AnnotationAttr>(
attr))
64#include
"clang/CIR/Dialect/IR/CIRLowering.inc"
71 if (isa<mlir::DistinctAttr>(
attr))
75 if (isa<cir::DataMemberAttr, cir::DataMemberOffsetAttr, cir::MethodAttr>(
79 return llvm::TypeSwitch<mlir::Attribute, bool>(
attr)
82 [&tc](cir::ZeroAttr za) {
return tc.isLegal(za.getType()); })
83 .Case<cir::PoisonAttr>(
84 [&tc](cir::PoisonAttr pa) {
return tc.isLegal(pa.getType()); })
85 .Case<cir::UndefAttr>(
86 [&tc](cir::UndefAttr uda) {
return tc.isLegal(uda.getType()); })
87 .Case<mlir::TypeAttr>(
88 [&tc](mlir::TypeAttr ta) {
return tc.isLegal(ta.getValue()); })
89 .Case<cir::ConstPtrAttr>(
90 [&tc](cir::ConstPtrAttr cpa) {
return tc.isLegal(cpa.getType()); })
91 .Case<cir::CXXCtorAttr>(
92 [&tc](cir::CXXCtorAttr ca) {
return tc.isLegal(ca.getType()); })
93 .Case<cir::CXXDtorAttr>(
94 [&tc](cir::CXXDtorAttr da) {
return tc.isLegal(da.getType()); })
95 .Case<cir::CXXAssignAttr>(
96 [&tc](cir::CXXAssignAttr aa) {
return tc.isLegal(aa.getType()); })
100 .Case<mlir::ArrayAttr>([&tc](mlir::ArrayAttr array) {
101 return llvm::all_of(array.getValue(), [&tc](mlir::Attribute
attr) {
102 return isCXXABIAttributeLegal(tc, attr);
105 .Case<mlir::DictionaryAttr>([&tc](mlir::DictionaryAttr dict) {
106 return llvm::all_of(dict.getValue(), [&tc](mlir::NamedAttribute na) {
107 return isCXXABIAttributeLegal(tc, na.getValue());
111 .Case<cir::ConstArrayAttr>([&tc](cir::ConstArrayAttr array) {
112 return tc.isLegal(array.getType()) &&
113 isCXXABIAttributeLegal(tc, array.getElts());
115 .Case<cir::GlobalViewAttr>([&tc](cir::GlobalViewAttr gva) {
116 return tc.isLegal(gva.getType()) &&
117 isCXXABIAttributeLegal(tc, gva.getIndices());
119 .Case<cir::GlobalOffsetAttr>([&tc](cir::GlobalOffsetAttr goa) {
120 return tc.isLegal(goa.getType());
122 .Case<cir::VTableAttr>([&tc](cir::VTableAttr vta) {
123 return tc.isLegal(vta.getType()) &&
124 isCXXABIAttributeLegal(tc, vta.getData());
126 .Case<cir::TypeInfoAttr>([&tc](cir::TypeInfoAttr tia) {
127 return tc.isLegal(tia.getType()) &&
128 isCXXABIAttributeLegal(tc, tia.getData());
130 .Case<cir::DynamicCastInfoAttr>([&tc](cir::DynamicCastInfoAttr dcia) {
131 return isCXXABIAttributeLegal(tc, dcia.getSrcRtti()) &&
132 isCXXABIAttributeLegal(tc, dcia.getDestRtti()) &&
133 isCXXABIAttributeLegal(tc, dcia.getRuntimeFunc()) &&
134 isCXXABIAttributeLegal(tc, dcia.getBadCastFunc());
136 .Case<cir::ConstRecordAttr>([&tc](cir::ConstRecordAttr cra) {
137 return tc.isLegal(cra.getType()) &&
138 isCXXABIAttributeLegal(tc, cra.getMembers());
149mlir::Attribute rewriteAttribute(
const mlir::TypeConverter &tc,
150 mlir::MLIRContext *ctx, mlir::Attribute attr) {
153 if (isCXXABIAttributeLegal(tc, attr))
161 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(attr)
163 .Case<cir::ZeroAttr>([&tc](cir::ZeroAttr za) {
164 return cir::ZeroAttr::get(tc.convertType(za.getType()));
166 .Case<cir::PoisonAttr>([&tc](cir::PoisonAttr pa) {
167 return cir::PoisonAttr::get(tc.convertType(pa.getType()));
169 .Case<cir::UndefAttr>([&tc](cir::UndefAttr uda) {
170 return cir::UndefAttr::get(tc.convertType(uda.getType()));
172 .Case<mlir::TypeAttr>([&tc](mlir::TypeAttr ta) {
173 return mlir::TypeAttr::get(tc.convertType(ta.getValue()));
175 .Case<cir::ConstPtrAttr>([&tc](cir::ConstPtrAttr cpa) {
176 return cir::ConstPtrAttr::get(tc.convertType(cpa.getType()),
179 .Case<cir::CXXCtorAttr>([&tc](cir::CXXCtorAttr ca) {
180 return cir::CXXCtorAttr::get(tc.convertType(ca.getType()),
181 ca.getCtorKind(), ca.getIsTrivial());
183 .Case<cir::CXXDtorAttr>([&tc](cir::CXXDtorAttr da) {
184 return cir::CXXDtorAttr::get(tc.convertType(da.getType()),
187 .Case<cir::CXXAssignAttr>([&tc](cir::CXXAssignAttr aa) {
188 return cir::CXXAssignAttr::get(tc.convertType(aa.getType()),
189 aa.getAssignKind(), aa.getIsTrivial());
193 .Case<mlir::ArrayAttr>([&tc, ctx](mlir::ArrayAttr array) {
195 for (mlir::Attribute a : array.getValue())
196 elts.push_back(rewriteAttribute(tc, ctx, a));
197 return mlir::ArrayAttr::get(ctx, elts);
199 .Case<mlir::DictionaryAttr>([&tc, ctx](mlir::DictionaryAttr dict) {
201 for (mlir::NamedAttribute na : dict.getValue())
202 elts.emplace_back(na.getName(),
203 rewriteAttribute(tc, ctx, na.getValue()));
205 return mlir::DictionaryAttr::get(ctx, elts);
208 .Case<cir::ConstArrayAttr>([&tc, ctx](cir::ConstArrayAttr array) {
209 return cir::ConstArrayAttr::get(
210 ctx, tc.convertType(array.getType()),
211 rewriteAttribute(tc, ctx, array.getElts()),
212 array.getTrailingZerosNum());
214 .Case<cir::GlobalViewAttr>([&tc, ctx](cir::GlobalViewAttr gva) {
215 return cir::GlobalViewAttr::get(
216 tc.convertType(gva.getType()), gva.getSymbol(),
217 mlir::cast<mlir::ArrayAttr>(
218 rewriteAttribute(tc, ctx, gva.getIndices())),
219 gva.getAddressPoint());
221 .Case<cir::GlobalOffsetAttr>([&tc](cir::GlobalOffsetAttr goa) {
222 return cir::GlobalOffsetAttr::get(tc.convertType(goa.getType()),
223 goa.getSymbol(), goa.getOffset());
225 .Case<cir::VTableAttr>([&tc, ctx](cir::VTableAttr vta) {
226 return cir::VTableAttr::get(
227 tc.convertType(vta.getType()),
228 mlir::cast<mlir::ArrayAttr>(
229 rewriteAttribute(tc, ctx, vta.getData())));
231 .Case<cir::TypeInfoAttr>([&tc, ctx](cir::TypeInfoAttr tia) {
232 return cir::TypeInfoAttr::get(
233 tc.convertType(tia.getType()),
234 mlir::cast<mlir::ArrayAttr>(
235 rewriteAttribute(tc, ctx, tia.getData())));
237 .Case<cir::DynamicCastInfoAttr>([&tc,
238 ctx](cir::DynamicCastInfoAttr dcia) {
239 return cir::DynamicCastInfoAttr::get(
240 mlir::cast<cir::GlobalViewAttr>(
241 rewriteAttribute(tc, ctx, dcia.getSrcRtti())),
242 mlir::cast<cir::GlobalViewAttr>(
243 rewriteAttribute(tc, ctx, dcia.getDestRtti())),
244 dcia.getRuntimeFunc(), dcia.getBadCastFunc(), dcia.getOffsetHint());
246 .Case<cir::ConstRecordAttr>([&tc, ctx](cir::ConstRecordAttr cra) {
247 return cir::ConstRecordAttr::get(
248 ctx, tc.convertType(cra.getType()),
249 mlir::cast<mlir::ArrayAttr>(
250 rewriteAttribute(tc, ctx, cra.getMembers())));
252 .DefaultUnreachable(
"unrewritten illegal attribute kind");
255bool areCXXABIInherentAttrsLegal(mlir::Operation *op,
256 const mlir::TypeConverter &typeConverter) {
258 op->getName().walkInherentAttrs(
259 op, [&](llvm::StringRef, mlir::Attribute &attr) {
260 legal &= isCXXABIAttributeLegal(typeConverter, attr);
265#define GET_ABI_LOWERING_PATTERNS
266#include "clang/CIR/Dialect/IR/CIRLowering.inc"
267#undef GET_ABI_LOWERING_PATTERNS
269struct CXXABILoweringPass
270 :
public impl::CXXABILoweringBase<CXXABILoweringPass> {
271 CXXABILoweringPass() =
default;
272 void runOnOperation()
override;
280class CIRGenericCXXABILoweringPattern :
public mlir::ConversionPattern {
282 CIRGenericCXXABILoweringPattern(mlir::MLIRContext *context,
283 const mlir::TypeConverter &typeConverter)
284 : mlir::ConversionPattern(typeConverter, MatchAnyOpTypeTag(),
288 matchAndRewrite(mlir::Operation *op, llvm::ArrayRef<mlir::Value> operands,
289 mlir::ConversionPatternRewriter &rewriter)
const override {
291 if (llvm::isa<cir::AllocaOp, cir::BaseDataMemberOp, cir::BaseMethodOp,
292 cir::CastOp, cir::CmpOp, cir::ConstantOp, cir::DeleteArrayOp,
293 cir::DerivedDataMemberOp, cir::DerivedMethodOp, cir::FuncOp,
294 cir::GetMethodOp, cir::GetRuntimeMemberOp, cir::GlobalOp>(op))
295 return mlir::failure();
297 const mlir::TypeConverter *typeConverter = getTypeConverter();
298 assert(typeConverter &&
299 "CIRGenericCXXABILoweringPattern requires a type converter");
300 bool operandsAndResultsLegal = typeConverter->isLegal(op);
302 std::all_of(op->getRegions().begin(), op->getRegions().end(),
303 [typeConverter](mlir::Region ®ion) {
304 return typeConverter->isLegal(®ion);
306 bool attrsLegal = areCXXABIInherentAttrsLegal(op, *typeConverter);
308 if (operandsAndResultsLegal && regionsLegal && attrsLegal) {
311 return mlir::failure();
314 mlir::OperationState loweredOpState(op->getLoc(), op->getName());
315 loweredOpState.addOperands(operands);
316 loweredOpState.addSuccessors(op->getSuccessors());
319 loweredOpState.propertiesAttr = op->getPropertiesAsAttribute();
320 loweredOpState.addAttributes(op->getDiscardableAttrDictionary().getValue());
323 llvm::SmallVector<mlir::Type> loweredResultTypes;
324 loweredResultTypes.reserve(op->getNumResults());
325 for (mlir::Type result : op->getResultTypes())
326 loweredResultTypes.push_back(typeConverter->convertType(result));
327 loweredOpState.addTypes(loweredResultTypes);
330 for (mlir::Region ®ion : op->getRegions()) {
332 rewriter.convertRegionTypes(®ion, *getTypeConverter())))
333 return mlir::failure();
335 for (mlir::Region ®ion : op->getRegions()) {
336 mlir::Region *loweredRegion = loweredOpState.addRegion();
337 rewriter.inlineRegionBefore(region, *loweredRegion, loweredRegion->end());
341 mlir::Operation *loweredOp = rewriter.create(loweredOpState);
342 loweredOp->getName().walkInherentAttrs(
343 loweredOp, [&](llvm::StringRef, mlir::Attribute &attr) {
344 attr = rewriteAttribute(*typeConverter, op->getContext(), attr);
347 rewriter.replaceOp(op, loweredOp);
348 return mlir::success();
354mlir::LogicalResult CIRAllocaOpABILowering::matchAndRewrite(
355 cir::AllocaOp op, OpAdaptor adaptor,
356 mlir::ConversionPatternRewriter &rewriter)
const {
357 mlir::Type allocaPtrTy = op.getType();
358 mlir::Type loweredAllocaPtrTy = getTypeConverter()->convertType(allocaPtrTy);
360 cir::AllocaOp loweredOp = cir::AllocaOp::create(
361 rewriter, op.getLoc(), loweredAllocaPtrTy, op.getName(),
362 op.getAlignmentAttr(), adaptor.getDynAllocSize());
363 loweredOp.setInit(op.getInit());
364 loweredOp.setConstant(op.getConstant());
365 loweredOp.setAnnotationsAttr(op.getAnnotationsAttr());
367 rewriter.replaceOp(op, loweredOp);
368 return mlir::success();
371mlir::LogicalResult CIRCastOpABILowering::matchAndRewrite(
372 cir::CastOp op, OpAdaptor adaptor,
373 mlir::ConversionPatternRewriter &rewriter)
const {
374 mlir::Type srcTy = op.getSrc().getType();
376 if (mlir::isa<cir::DataMemberType, cir::MethodType>(srcTy)) {
377 switch (op.getKind()) {
378 case cir::CastKind::bitcast: {
379 mlir::Type destTy = getTypeConverter()->convertType(op.getType());
380 mlir::Value loweredResult;
381 if (mlir::isa<cir::DataMemberType>(srcTy))
382 loweredResult = lowerModule->getCXXABI().lowerDataMemberBitcast(
383 op, destTy, adaptor.getSrc(), rewriter);
385 loweredResult = lowerModule->getCXXABI().lowerMethodBitcast(
386 op, destTy, adaptor.getSrc(), rewriter);
387 rewriter.replaceOp(op, loweredResult);
388 return mlir::success();
390 case cir::CastKind::member_ptr_to_bool: {
391 mlir::Value loweredResult;
392 if (mlir::isa<cir::DataMemberType>(srcTy))
393 loweredResult = lowerModule->getCXXABI().lowerDataMemberToBoolCast(
394 op, adaptor.getSrc(), rewriter);
396 loweredResult = lowerModule->getCXXABI().lowerMethodToBoolCast(
397 op, adaptor.getSrc(), rewriter);
398 rewriter.replaceOp(op, loweredResult);
399 return mlir::success();
406 mlir::Value loweredResult = cir::CastOp::create(
407 rewriter, op.getLoc(), getTypeConverter()->convertType(op.getType()),
408 adaptor.getKind(), adaptor.getSrc());
409 rewriter.replaceOp(op, loweredResult);
410 return mlir::success();
415 const mlir::DataLayout &layout,
416 const mlir::TypeConverter &tc,
418 mlir::Attribute initVal) {
419 if (mlir::isa_and_present<cir::UndefAttr>(initVal))
420 return cir::UndefAttr::get(tc.convertType(ty));
422 if (mlir::isa_and_present<cir::PoisonAttr>(initVal))
423 return cir::PoisonAttr::get(tc.convertType(ty));
425 if (mlir::isa<cir::DataMemberType>(ty)) {
429 mlir::dyn_cast_if_present<cir::DataMemberOffsetAttr>(initVal))
432 auto dataMemberVal = mlir::cast_if_present<cir::DataMemberAttr>(initVal);
436 if (mlir::isa<cir::MethodType>(ty)) {
437 auto methodVal = mlir::cast_if_present<cir::MethodAttr>(initVal);
441 if (
auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty)) {
442 auto loweredArrTy = mlir::cast<cir::ArrayType>(tc.convertType(arrTy));
447 if (
auto zeroVal = mlir::dyn_cast_if_present<cir::ZeroAttr>(initVal))
448 return cir::ZeroAttr::get(loweredArrTy);
450 auto arrayVal = mlir::cast<cir::ConstArrayAttr>(initVal);
456 if (mlir::isa<mlir::StringAttr>(arrayVal.getElts())) {
457 assert(loweredArrTy == arrTy &&
458 "string-literal array type should not change under CXX ABI");
462 auto arrayElts = mlir::cast<ArrayAttr>(arrayVal.getElts());
464 loweredElements.reserve(arrTy.getSize());
465 for (
const mlir::Attribute &attr : arrayElts) {
466 auto typedAttr = cast<mlir::TypedAttr>(attr);
468 lowerModule, layout, tc, typedAttr.getType(), typedAttr));
471 return cir::ConstArrayAttr::get(
472 loweredArrTy, mlir::ArrayAttr::get(ty.getContext(), loweredElements),
473 arrayVal.getTrailingZerosNum());
476 if (
auto recordTy = mlir::dyn_cast<cir::RecordType>(ty)) {
478 mlir::dyn_cast<cir::RecordType>(tc.convertType(recordTy));
482 if (
auto recVal = mlir::dyn_cast_if_present<cir::ZeroAttr>(initVal))
483 return cir::ZeroAttr::get(convertedTy);
486 mlir::dyn_cast_if_present<cir::ConstRecordAttr>(initVal)) {
487 auto recordMembers = mlir::cast<ArrayAttr>(recVal.getMembers());
490 loweredMembers.reserve(recordMembers.size());
492 for (
const mlir::Attribute &attr : recordMembers) {
493 auto typedAttr = cast<mlir::TypedAttr>(attr);
495 lowerModule, layout, tc, typedAttr.getType(), typedAttr));
498 return cir::ConstRecordAttr::get(
499 convertedTy, mlir::ArrayAttr::get(ty.getContext(), loweredMembers));
502 assert(!initVal &&
"Record init val type not handled");
507 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty)) {
508 auto convertedTy = mlir::cast<cir::PointerType>(tc.convertType(ptrTy));
511 if (
auto gva = mlir::dyn_cast_if_present<cir::GlobalViewAttr>(initVal))
512 return cir::GlobalViewAttr::get(convertedTy, gva.getSymbol(),
513 gva.getIndices(), gva.getAddressPoint());
515 if (
auto goa = mlir::dyn_cast_if_present<cir::GlobalOffsetAttr>(initVal))
516 return cir::GlobalOffsetAttr::get(convertedTy, goa.getSymbol(),
520 mlir::dyn_cast_if_present<cir::BlockAddrInfoAttr>(initVal)) {
521 assert(convertedTy == ptrTy &&
"BlockAddrInfo type should not change");
525 auto constPtr = mlir::cast_if_present<cir::ConstPtrAttr>(initVal);
528 return cir::ConstPtrAttr::get(convertedTy, constPtr.getValue());
531 assert(ty == tc.convertType(ty) &&
532 "cir.global or constant operand is not an CXXABI-dependent type");
535 return cast<mlir::TypedAttr>(initVal);
538mlir::LogicalResult CIRConstantOpABILowering::matchAndRewrite(
539 cir::ConstantOp op, OpAdaptor adaptor,
540 mlir::ConversionPatternRewriter &rewriter)
const {
542 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
544 lowerModule, layout, *getTypeConverter(), op.getType(), op.getValue());
545 rewriter.replaceOpWithNewOp<ConstantOp>(op, newValue);
546 return mlir::success();
549mlir::LogicalResult CIRCmpOpABILowering::matchAndRewrite(
550 cir::CmpOp op, OpAdaptor adaptor,
551 mlir::ConversionPatternRewriter &rewriter)
const {
552 mlir::Type type = op.getLhs().getType();
554 mlir::Value loweredResult;
555 if (mlir::isa<cir::DataMemberType>(type))
556 loweredResult = lowerModule->getCXXABI().lowerDataMemberCmp(
557 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
558 else if (mlir::isa<cir::MethodType>(type))
559 loweredResult = lowerModule->getCXXABI().lowerMethodCmp(
560 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
562 loweredResult = cir::CmpOp::create(
563 rewriter, op.getLoc(), getTypeConverter()->convertType(op.getType()),
564 adaptor.getKind(), adaptor.getLhs(), adaptor.getRhs());
566 rewriter.replaceOp(op, loweredResult);
567 return mlir::success();
570mlir::LogicalResult CIRFuncOpABILowering::matchAndRewrite(
571 cir::FuncOp op, OpAdaptor adaptor,
572 mlir::ConversionPatternRewriter &rewriter)
const {
573 cir::FuncType opFuncType = op.getFunctionType();
574 mlir::TypeConverter::SignatureConversion signatureConversion(
575 opFuncType.getNumInputs());
577 for (
const auto &[i, argType] : llvm::enumerate(opFuncType.getInputs())) {
578 mlir::Type loweredArgType = getTypeConverter()->convertType(argType);
580 return mlir::failure();
581 signatureConversion.addInputs(i, loweredArgType);
584 mlir::Type loweredResultType =
585 getTypeConverter()->convertType(opFuncType.getReturnType());
586 if (!loweredResultType)
587 return mlir::failure();
589 auto loweredFuncType =
590 cir::FuncType::get(signatureConversion.getConvertedTypes(),
591 loweredResultType, opFuncType.isVarArg());
594 if (mlir::failed(rewriter.convertRegionTypes(
595 &op.getBody(), *getTypeConverter(), &signatureConversion)))
596 return mlir::failure();
599 cir::FuncOp loweredFuncOp = rewriter.cloneWithoutRegions(op);
600 loweredFuncOp.setFunctionType(loweredFuncType);
602 loweredFuncOp->getName().walkInherentAttrs(
603 loweredFuncOp, [&](llvm::StringRef, mlir::Attribute &attr) {
604 attr = rewriteAttribute(*getTypeConverter(), op->getContext(), attr);
606 rewriter.inlineRegionBefore(op.getBody(), loweredFuncOp.getBody(),
607 loweredFuncOp.end());
609 rewriter.eraseOp(op);
610 return mlir::success();
613mlir::LogicalResult CIRGlobalOpABILowering::matchAndRewrite(
614 cir::GlobalOp op, OpAdaptor adaptor,
615 mlir::ConversionPatternRewriter &rewriter)
const {
616 mlir::Type ty = op.getSymType();
617 mlir::Type loweredTy = getTypeConverter()->convertType(ty);
619 return mlir::failure();
621 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
624 lowerModule, layout, *getTypeConverter(), ty, op.getInitialValueAttr());
626 cir::GlobalOp newOp = rewriter.cloneWithoutRegions(op);
627 newOp.setInitialValueAttr(loweredInit);
628 newOp.setSymType(loweredTy);
632 rewriter.inlineRegionBefore(op.getCtorRegion(), newOp.getCtorRegion(),
633 newOp.getCtorRegion().end());
634 rewriter.inlineRegionBefore(op.getDtorRegion(), newOp.getDtorRegion(),
635 newOp.getDtorRegion().end());
636 rewriter.replaceOp(op, newOp);
637 return mlir::success();
640mlir::LogicalResult CIRBaseDataMemberOpABILowering::matchAndRewrite(
641 cir::BaseDataMemberOp op, OpAdaptor adaptor,
642 mlir::ConversionPatternRewriter &rewriter)
const {
643 mlir::Value loweredResult = lowerModule->getCXXABI().lowerBaseDataMember(
644 op, adaptor.getSrc(), rewriter);
645 rewriter.replaceOp(op, loweredResult);
646 return mlir::success();
649mlir::LogicalResult CIRBaseMethodOpABILowering::matchAndRewrite(
650 cir::BaseMethodOp op, OpAdaptor adaptor,
651 mlir::ConversionPatternRewriter &rewriter)
const {
652 mlir::Value loweredResult =
653 lowerModule->getCXXABI().lowerBaseMethod(op, adaptor.getSrc(), rewriter);
654 rewriter.replaceOp(op, loweredResult);
655 return mlir::success();
658mlir::LogicalResult CIRDeleteArrayOpABILowering::matchAndRewrite(
659 cir::DeleteArrayOp op, OpAdaptor adaptor,
660 mlir::ConversionPatternRewriter &rewriter)
const {
661 mlir::FlatSymbolRefAttr deleteFn = op.getDeleteFnAttr();
662 mlir::Location loc = op->getLoc();
663 mlir::Value loweredAddress = adaptor.getAddress();
665 cir::UsualDeleteParamsAttr deleteParams = op.getDeleteParamsAttr();
667 deleteParams = cir::UsualDeleteParamsAttr::get(op.getContext(),
false,
668 std::nullopt,
false,
false);
669 bool cookieRequired = deleteParams.getSize() || op.getElementDtorAttr();
671 assert(!deleteParams.getDestroyingDelete() &&
672 "destroying delete not legal on arrays");
673 assert(!deleteParams.getTypeAwareDelete() &&
674 "type-aware delete not legal on arrays");
676 const CIRCXXABI &cxxABI = lowerModule->getCXXABI();
685 mlir::Value deletePtr;
686 mlir::Value numElements;
687 auto ptrTy = mlir::cast<cir::PointerType>(loweredAddress.getType());
689 mlir::DataLayout dl(op->getParentOfType<mlir::ModuleOp>());
692 cir::IntType sizeTy = cirBuilder.getUIntNTy(ptrWidth);
694 if (cookieRequired) {
697 cxxABI.
readArrayCookie(loc, loweredAddress, elementAlign, dl, cirBuilder,
698 numElements, deletePtr, cookieSize);
700 deletePtr = cir::CastOp::create(
701 rewriter, loc, cirBuilder.getVoidPtrTy(ptrTy.getAddrSpace()),
702 cir::CastKind::bitcast, loweredAddress);
712 mlir::FlatSymbolRefAttr dtorFn = op.getElementDtorAttr();
715 auto getCalleeCallingConv = [&](mlir::FlatSymbolRefAttr callee) {
717 mlir::SymbolTable::lookupNearestSymbolFrom<cir::FuncOp>(op, callee))
718 return fn.getCallingConv();
719 return cir::CallingConv::C;
722 cir::CleanupKind cleanupKind =
723 op.getDtorMayThrow() ? cir::CleanupKind::All : cir::CleanupKind::Normal;
724 cir::CleanupScopeOp::create(
725 rewriter, loc, cleanupKind,
727 [&](mlir::OpBuilder &b, mlir::Location l) {
729 auto arrayDtor = cir::ArrayDtor::create(
730 b, l, loweredAddress, numElements,
731 [&](mlir::OpBuilder &bb, mlir::Location ll) {
733 bb.getInsertionBlock()->addArgument(ptrTy, ll);
734 auto dtorCall = cir::CallOp::create(
735 bb, ll, dtorFn, cir::VoidType(), mlir::ValueRange{
arg});
736 dtorCall.setCallingConv(getCalleeCallingConv(dtorFn));
737 if (!op.getDtorMayThrow())
738 dtorCall.setNothrowAttr(bb.getUnitAttr());
739 cir::YieldOp::create(bb, ll);
741 if (op.getDtorMayThrow())
742 arrayDtor.setDtorMayThrow(
true);
744 cir::YieldOp::create(b, l);
747 [&](mlir::OpBuilder &b, mlir::Location l) {
750 if (deleteParams.getSize()) {
751 uint64_t eltSizeBytes = dl.getTypeSizeInBits(ptrTy.getPointee()) / 8;
752 auto eltSizeVal = cir::ConstantOp::create(
753 b, l, cir::IntAttr::get(sizeTy, eltSizeBytes));
754 mlir::Value allocSize =
755 cir::MulOp::create(b, l, sizeTy, eltSizeVal, numElements);
756 auto cookieSizeVal = cir::ConstantOp::create(
757 b, l, cir::IntAttr::get(sizeTy, cookieSize.
getQuantity()));
759 cir::AddOp::create(b, l, sizeTy, allocSize, cookieSizeVal);
762 if (deleteParams.getAlignment()) {
763 auto alignVal = cir::ConstantOp::create(
764 b, l, cir::IntAttr::get(sizeTy, *deleteParams.getAlignment()));
769 cir::CallOp::create(b, l, deleteFn, cir::VoidType(), callArgs);
770 deleteCall.setCallingConv(getCalleeCallingConv(deleteFn));
773 deleteCall.setNothrowAttr(b.getUnitAttr());
774 cir::YieldOp::create(b, l);
777 rewriter.eraseOp(op);
778 return mlir::success();
781mlir::LogicalResult CIRDerivedDataMemberOpABILowering::matchAndRewrite(
782 cir::DerivedDataMemberOp op, OpAdaptor adaptor,
783 mlir::ConversionPatternRewriter &rewriter)
const {
784 mlir::Value loweredResult = lowerModule->getCXXABI().lowerDerivedDataMember(
785 op, adaptor.getSrc(), rewriter);
786 rewriter.replaceOp(op, loweredResult);
787 return mlir::success();
790mlir::LogicalResult CIRDerivedMethodOpABILowering::matchAndRewrite(
791 cir::DerivedMethodOp op, OpAdaptor adaptor,
792 mlir::ConversionPatternRewriter &rewriter)
const {
793 mlir::Value loweredResult = lowerModule->getCXXABI().lowerDerivedMethod(
794 op, adaptor.getSrc(), rewriter);
795 rewriter.replaceOp(op, loweredResult);
796 return mlir::success();
799mlir::LogicalResult CIRDynamicCastOpABILowering::matchAndRewrite(
800 cir::DynamicCastOp op, OpAdaptor adaptor,
801 mlir::ConversionPatternRewriter &rewriter)
const {
802 mlir::Value loweredResult =
803 lowerModule->getCXXABI().lowerDynamicCast(op, rewriter);
804 rewriter.replaceOp(op, loweredResult);
805 return mlir::success();
808mlir::LogicalResult CIRGetMethodOpABILowering::matchAndRewrite(
809 cir::GetMethodOp op, OpAdaptor adaptor,
810 mlir::ConversionPatternRewriter &rewriter)
const {
813 lowerModule->getCXXABI().lowerGetMethod(
814 op, callee, thisArg, adaptor.getMethod(), adaptor.getObject(), rewriter);
815 rewriter.replaceOp(op, {callee, thisArg});
816 return mlir::success();
819mlir::LogicalResult CIRGetRuntimeMemberOpABILowering::matchAndRewrite(
820 cir::GetRuntimeMemberOp op, OpAdaptor adaptor,
821 mlir::ConversionPatternRewriter &rewriter)
const {
822 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
823 mlir::Operation *newOp = lowerModule->getCXXABI().lowerGetRuntimeMember(
824 op, resTy, adaptor.getAddr(), adaptor.getMember(), rewriter);
825 rewriter.replaceOp(op, newOp);
826 return mlir::success();
829mlir::LogicalResult CIRVTableGetTypeInfoOpABILowering::matchAndRewrite(
830 cir::VTableGetTypeInfoOp op, OpAdaptor adaptor,
831 mlir::ConversionPatternRewriter &rewriter)
const {
832 mlir::Value loweredResult =
833 lowerModule->getCXXABI().lowerVTableGetTypeInfo(op, rewriter);
834 rewriter.replaceOp(op, loweredResult);
835 return mlir::success();
844 CIRABITypeConverter(mlir::MLIRContext &ctx, mlir::DataLayout &dataLayout,
845 cir::LowerModule &lowerModule)
846 : RecordRewritingTypeConverter(ctx) {
847 addConversion([&](cir::DataMemberType type) -> mlir::Type {
850 return convertType(abiType);
852 addConversion([&](cir::MethodType type) -> mlir::Type {
854 return convertType(abiType);
861 bool typeMayChange(mlir::Type type)
const override {
862 return mlir::isa<cir::DataMemberType, cir::MethodType>(type);
869 const mlir::TypeConverter &typeConverter) {
870 target.addLegalOp<mlir::ModuleOp>();
875 target.addDynamicallyLegalDialect<cir::CIRDialect>(
876 [&typeConverter](mlir::Operation *op) {
877 if (!typeConverter.isLegal(op))
880 bool attrs = areCXXABIInherentAttrsLegal(op, typeConverter);
883 std::all_of(op->getRegions().begin(), op->getRegions().end(),
884 [&typeConverter](mlir::Region ®ion) {
885 return typeConverter.isLegal(®ion);
889 target.addDynamicallyLegalDialect<mlir::acc::OpenACCDialect>(
890 [&typeConverter](mlir::Operation *op) {
891 if (!typeConverter.isLegal(op))
894 bool attrs = areCXXABIInherentAttrsLegal(op, typeConverter);
897 std::all_of(op->getRegions().begin(), op->getRegions().end(),
898 [&typeConverter](mlir::Region ®ion) {
899 return typeConverter.isLegal(®ion);
905 target.addDynamicallyLegalOp<cir::CastOp>([&typeConverter](cir::CastOp op) {
906 if (op.getSrc().getType() == op.getType()) {
907 switch (op.getKind()) {
908 case cir::CastKind::bitcast:
909 case cir::CastKind::address_space:
910 case cir::CastKind::float_complex:
911 case cir::CastKind::int_complex:
917 if (!typeConverter.isLegal(op.getOperation()))
921 return areCXXABIInherentAttrsLegal(op, typeConverter);
925 target.addDynamicallyLegalOp<cir::FuncOp>([&typeConverter](cir::FuncOp op) {
926 bool attrs = areCXXABIInherentAttrsLegal(op, typeConverter);
928 return attrs && typeConverter.isLegal(op.getFunctionType());
930 target.addDynamicallyLegalOp<cir::GlobalOp>(
931 [&typeConverter](cir::GlobalOp op) {
932 return typeConverter.isLegal(op.getSymType());
936 target.addIllegalOp<cir::DeleteArrayOp>();
937 target.addIllegalOp<cir::DynamicCastOp>();
938 target.addIllegalOp<cir::VTableGetTypeInfoOp>();
945void CXXABILoweringPass::runOnOperation() {
946 auto mod = mlir::cast<mlir::ModuleOp>(getOperation());
947 mlir::MLIRContext *ctx = mod.getContext();
950 assert(lowerModule &&
"LowerModule shouldn't be null");
951 if (!lowerModule->hasTarget()) {
952 mod.emitError() <<
getArgument() <<
" requires a module with a supported '"
953 << cir::CIRDialect::getTripleAttrName() <<
"' attribute";
954 return signalPassFailure();
957 if (!lowerModule->hasCXXABI()) {
958 mod.emitError() <<
"C++ ABI '"
960 lowerModule->getCXXABIKind())
961 <<
"' is not yet supported by CIR";
962 return signalPassFailure();
965 mlir::DataLayout dataLayout(mod);
966 CIRABITypeConverter typeConverter(*ctx, dataLayout, *lowerModule);
968 mlir::RewritePatternSet patterns(ctx);
969 patterns.add<CIRGenericCXXABILoweringPattern>(patterns.getContext(),
972#define GET_ABI_LOWERING_PATTERNS_LIST
973#include "clang/CIR/Dialect/IR/CIRLowering.inc"
974#undef GET_ABI_LOWERING_PATTERNS_LIST
975 >(patterns.getContext(), typeConverter, dataLayout, *lowerModule);
977 mlir::ConversionTarget target(*ctx);
980 llvm::SmallVector<mlir::Operation *> ops;
986 mlir::ConversionConfig config;
987 config.allowPatternRollback =
false;
988 if (failed(mlir::applyPartialConversion(ops, target, std::move(patterns),
992 typeConverter.restoreRecordTypeNames();
996 return std::make_unique<CXXABILoweringPass>();
#define CXX_ABI_ALWAYS_LEGAL_ATTRS
static void populateCXXABIConversionTarget(mlir::ConversionTarget &target, const mlir::TypeConverter &typeConverter)
static mlir::TypedAttr lowerInitialValue(const LowerModule *lowerModule, const mlir::DataLayout &layout, const mlir::TypeConverter &tc, mlir::Type ty, mlir::Attribute initVal)
static const TemplateArgument & getArgument(const TemplateArgument &A)
virtual mlir::Type lowerMethodType(cir::MethodType type, const mlir::TypeConverter &typeConverter) const =0
Lower the given member function pointer type to its ABI type.
virtual mlir::TypedAttr lowerDataMemberConstant(cir::DataMemberAttr attr, const mlir::DataLayout &layout, const mlir::TypeConverter &typeConverter) const =0
Lower the given data member pointer constant to a constant of the ABI type.
virtual mlir::TypedAttr lowerDataMemberOffsetConstant(cir::DataMemberOffsetAttr attr, const mlir::DataLayout &layout, const mlir::TypeConverter &typeConverter) const =0
Lower the given by-offset data member pointer constant (used for members with no CIR field index,...
virtual mlir::TypedAttr lowerMethodConstant(cir::MethodAttr attr, const mlir::DataLayout &layout, const mlir::TypeConverter &typeConverter) const =0
Lower the given member function pointer constant to a constant of the ABI type.
virtual mlir::Type lowerDataMemberType(cir::DataMemberType type, const mlir::TypeConverter &typeConverter) const =0
Lower the given data member pointer type to its ABI type.
void readArrayCookie(mlir::Location loc, mlir::Value elementPtr, clang::CharUnits elementAlign, const mlir::DataLayout &dataLayout, CIRBaseBuilderTy &builder, mlir::Value &numElements, mlir::Value &allocPtr, clang::CharUnits &cookieSize) const
Read the array cookie for a dynamically-allocated array whose first element is at elementPtr.
CIRCXXABI & getCXXABI() const
A type converter that converts the types nested in pointers, arrays, functions and records.
This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
static CharUnits fromQuantity(QuantityType Quantity)
Construct a CharUnits quantity from a raw integer type.
static const auto & getSpelling(Kind ABIKind)
void collectUnreachable(mlir::Operation *parent, llvm::SmallVectorImpl< mlir::Operation * > &ops)
Collect ops in blocks that are unreachable from their region's entry, appending them to ops.
std::unique_ptr< LowerModule > createLowerModule(mlir::ModuleOp module)
const internal::VariadicAllOfMatcher< Attr > attr
bool isa(CodeGen::Address addr)
@ Default
Set to the current date and time.
std::unique_ptr< Pass > createCXXABILoweringPass()
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)