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"
70 if (isa<cir::DataMemberAttr, cir::DataMemberOffsetAttr, cir::MethodAttr>(
74 return llvm::TypeSwitch<mlir::Attribute, bool>(
attr)
77 [&tc](cir::ZeroAttr za) {
return tc.isLegal(za.getType()); })
78 .Case<cir::PoisonAttr>(
79 [&tc](cir::PoisonAttr pa) {
return tc.isLegal(pa.getType()); })
80 .Case<cir::UndefAttr>(
81 [&tc](cir::UndefAttr uda) {
return tc.isLegal(uda.getType()); })
82 .Case<mlir::TypeAttr>(
83 [&tc](mlir::TypeAttr ta) {
return tc.isLegal(ta.getValue()); })
84 .Case<cir::ConstPtrAttr>(
85 [&tc](cir::ConstPtrAttr cpa) {
return tc.isLegal(cpa.getType()); })
86 .Case<cir::CXXCtorAttr>(
87 [&tc](cir::CXXCtorAttr ca) {
return tc.isLegal(ca.getType()); })
88 .Case<cir::CXXDtorAttr>(
89 [&tc](cir::CXXDtorAttr da) {
return tc.isLegal(da.getType()); })
90 .Case<cir::CXXAssignAttr>(
91 [&tc](cir::CXXAssignAttr aa) {
return tc.isLegal(aa.getType()); })
95 .Case<mlir::ArrayAttr>([&tc](mlir::ArrayAttr array) {
96 return llvm::all_of(array.getValue(), [&tc](mlir::Attribute
attr) {
97 return isCXXABIAttributeLegal(tc, attr);
100 .Case<mlir::DictionaryAttr>([&tc](mlir::DictionaryAttr dict) {
101 return llvm::all_of(dict.getValue(), [&tc](mlir::NamedAttribute na) {
102 return isCXXABIAttributeLegal(tc, na.getValue());
106 .Case<cir::ConstArrayAttr>([&tc](cir::ConstArrayAttr array) {
107 return tc.isLegal(array.getType()) &&
108 isCXXABIAttributeLegal(tc, array.getElts());
110 .Case<cir::GlobalViewAttr>([&tc](cir::GlobalViewAttr gva) {
111 return tc.isLegal(gva.getType()) &&
112 isCXXABIAttributeLegal(tc, gva.getIndices());
114 .Case<cir::GlobalOffsetAttr>([&tc](cir::GlobalOffsetAttr goa) {
115 return tc.isLegal(goa.getType());
117 .Case<cir::VTableAttr>([&tc](cir::VTableAttr vta) {
118 return tc.isLegal(vta.getType()) &&
119 isCXXABIAttributeLegal(tc, vta.getData());
121 .Case<cir::TypeInfoAttr>([&tc](cir::TypeInfoAttr tia) {
122 return tc.isLegal(tia.getType()) &&
123 isCXXABIAttributeLegal(tc, tia.getData());
125 .Case<cir::DynamicCastInfoAttr>([&tc](cir::DynamicCastInfoAttr dcia) {
126 return isCXXABIAttributeLegal(tc, dcia.getSrcRtti()) &&
127 isCXXABIAttributeLegal(tc, dcia.getDestRtti()) &&
128 isCXXABIAttributeLegal(tc, dcia.getRuntimeFunc()) &&
129 isCXXABIAttributeLegal(tc, dcia.getBadCastFunc());
131 .Case<cir::ConstRecordAttr>([&tc](cir::ConstRecordAttr cra) {
132 return tc.isLegal(cra.getType()) &&
133 isCXXABIAttributeLegal(tc, cra.getMembers());
144mlir::Attribute rewriteAttribute(
const mlir::TypeConverter &tc,
145 mlir::MLIRContext *ctx, mlir::Attribute attr) {
148 if (isCXXABIAttributeLegal(tc, attr))
156 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(attr)
158 .Case<cir::ZeroAttr>([&tc](cir::ZeroAttr za) {
159 return cir::ZeroAttr::get(tc.convertType(za.getType()));
161 .Case<cir::PoisonAttr>([&tc](cir::PoisonAttr pa) {
162 return cir::PoisonAttr::get(tc.convertType(pa.getType()));
164 .Case<cir::UndefAttr>([&tc](cir::UndefAttr uda) {
165 return cir::UndefAttr::get(tc.convertType(uda.getType()));
167 .Case<mlir::TypeAttr>([&tc](mlir::TypeAttr ta) {
168 return mlir::TypeAttr::get(tc.convertType(ta.getValue()));
170 .Case<cir::ConstPtrAttr>([&tc](cir::ConstPtrAttr cpa) {
171 return cir::ConstPtrAttr::get(tc.convertType(cpa.getType()),
174 .Case<cir::CXXCtorAttr>([&tc](cir::CXXCtorAttr ca) {
175 return cir::CXXCtorAttr::get(tc.convertType(ca.getType()),
176 ca.getCtorKind(), ca.getIsTrivial());
178 .Case<cir::CXXDtorAttr>([&tc](cir::CXXDtorAttr da) {
179 return cir::CXXDtorAttr::get(tc.convertType(da.getType()),
182 .Case<cir::CXXAssignAttr>([&tc](cir::CXXAssignAttr aa) {
183 return cir::CXXAssignAttr::get(tc.convertType(aa.getType()),
184 aa.getAssignKind(), aa.getIsTrivial());
188 .Case<mlir::ArrayAttr>([&tc, ctx](mlir::ArrayAttr array) {
190 for (mlir::Attribute a : array.getValue())
191 elts.push_back(rewriteAttribute(tc, ctx, a));
192 return mlir::ArrayAttr::get(ctx, elts);
194 .Case<mlir::DictionaryAttr>([&tc, ctx](mlir::DictionaryAttr dict) {
196 for (mlir::NamedAttribute na : dict.getValue())
197 elts.emplace_back(na.getName(),
198 rewriteAttribute(tc, ctx, na.getValue()));
200 return mlir::DictionaryAttr::get(ctx, elts);
203 .Case<cir::ConstArrayAttr>([&tc, ctx](cir::ConstArrayAttr array) {
204 return cir::ConstArrayAttr::get(
205 ctx, tc.convertType(array.getType()),
206 rewriteAttribute(tc, ctx, array.getElts()),
207 array.getTrailingZerosNum());
209 .Case<cir::GlobalViewAttr>([&tc, ctx](cir::GlobalViewAttr gva) {
210 return cir::GlobalViewAttr::get(
211 tc.convertType(gva.getType()), gva.getSymbol(),
212 mlir::cast<mlir::ArrayAttr>(
213 rewriteAttribute(tc, ctx, gva.getIndices())),
214 gva.getAddressPoint());
216 .Case<cir::GlobalOffsetAttr>([&tc](cir::GlobalOffsetAttr goa) {
217 return cir::GlobalOffsetAttr::get(tc.convertType(goa.getType()),
218 goa.getSymbol(), goa.getOffset());
220 .Case<cir::VTableAttr>([&tc, ctx](cir::VTableAttr vta) {
221 return cir::VTableAttr::get(
222 tc.convertType(vta.getType()),
223 mlir::cast<mlir::ArrayAttr>(
224 rewriteAttribute(tc, ctx, vta.getData())));
226 .Case<cir::TypeInfoAttr>([&tc, ctx](cir::TypeInfoAttr tia) {
227 return cir::TypeInfoAttr::get(
228 tc.convertType(tia.getType()),
229 mlir::cast<mlir::ArrayAttr>(
230 rewriteAttribute(tc, ctx, tia.getData())));
232 .Case<cir::DynamicCastInfoAttr>([&tc,
233 ctx](cir::DynamicCastInfoAttr dcia) {
234 return cir::DynamicCastInfoAttr::get(
235 mlir::cast<cir::GlobalViewAttr>(
236 rewriteAttribute(tc, ctx, dcia.getSrcRtti())),
237 mlir::cast<cir::GlobalViewAttr>(
238 rewriteAttribute(tc, ctx, dcia.getDestRtti())),
239 dcia.getRuntimeFunc(), dcia.getBadCastFunc(), dcia.getOffsetHint());
241 .Case<cir::ConstRecordAttr>([&tc, ctx](cir::ConstRecordAttr cra) {
242 return cir::ConstRecordAttr::get(
243 ctx, tc.convertType(cra.getType()),
244 mlir::cast<mlir::ArrayAttr>(
245 rewriteAttribute(tc, ctx, cra.getMembers())));
247 .DefaultUnreachable(
"unrewritten illegal attribute kind");
250bool areCXXABIInherentAttrsLegal(mlir::Operation *op,
251 const mlir::TypeConverter &typeConverter) {
253 op->getName().walkInherentAttrs(
254 op, [&](llvm::StringRef, mlir::Attribute &attr) {
255 legal &= isCXXABIAttributeLegal(typeConverter, attr);
260#define GET_ABI_LOWERING_PATTERNS
261#include "clang/CIR/Dialect/IR/CIRLowering.inc"
262#undef GET_ABI_LOWERING_PATTERNS
264struct CXXABILoweringPass
265 :
public impl::CXXABILoweringBase<CXXABILoweringPass> {
266 CXXABILoweringPass() =
default;
267 void runOnOperation()
override;
275class CIRGenericCXXABILoweringPattern :
public mlir::ConversionPattern {
277 CIRGenericCXXABILoweringPattern(mlir::MLIRContext *context,
278 const mlir::TypeConverter &typeConverter)
279 : mlir::ConversionPattern(typeConverter, MatchAnyOpTypeTag(),
283 matchAndRewrite(mlir::Operation *op, llvm::ArrayRef<mlir::Value> operands,
284 mlir::ConversionPatternRewriter &rewriter)
const override {
286 if (llvm::isa<cir::AllocaOp, cir::BaseDataMemberOp, cir::BaseMethodOp,
287 cir::CastOp, cir::CmpOp, cir::ConstantOp, cir::DeleteArrayOp,
288 cir::DerivedDataMemberOp, cir::DerivedMethodOp, cir::FuncOp,
289 cir::GetMethodOp, cir::GetRuntimeMemberOp, cir::GlobalOp>(op))
290 return mlir::failure();
292 const mlir::TypeConverter *typeConverter = getTypeConverter();
293 assert(typeConverter &&
294 "CIRGenericCXXABILoweringPattern requires a type converter");
295 bool operandsAndResultsLegal = typeConverter->isLegal(op);
297 std::all_of(op->getRegions().begin(), op->getRegions().end(),
298 [typeConverter](mlir::Region ®ion) {
299 return typeConverter->isLegal(®ion);
301 bool attrsLegal = areCXXABIInherentAttrsLegal(op, *typeConverter);
303 if (operandsAndResultsLegal && regionsLegal && attrsLegal) {
306 return mlir::failure();
309 mlir::OperationState loweredOpState(op->getLoc(), op->getName());
310 loweredOpState.addOperands(operands);
311 loweredOpState.addSuccessors(op->getSuccessors());
314 loweredOpState.propertiesAttr = op->getPropertiesAsAttribute();
315 loweredOpState.addAttributes(op->getDiscardableAttrDictionary().getValue());
318 llvm::SmallVector<mlir::Type> loweredResultTypes;
319 loweredResultTypes.reserve(op->getNumResults());
320 for (mlir::Type result : op->getResultTypes())
321 loweredResultTypes.push_back(typeConverter->convertType(result));
322 loweredOpState.addTypes(loweredResultTypes);
325 for (mlir::Region ®ion : op->getRegions()) {
326 mlir::Region *loweredRegion = loweredOpState.addRegion();
327 rewriter.inlineRegionBefore(region, *loweredRegion, loweredRegion->end());
329 rewriter.convertRegionTypes(loweredRegion, *getTypeConverter())))
330 return mlir::failure();
334 mlir::Operation *loweredOp = rewriter.create(loweredOpState);
335 loweredOp->getName().walkInherentAttrs(
336 loweredOp, [&](llvm::StringRef, mlir::Attribute &attr) {
337 attr = rewriteAttribute(*typeConverter, op->getContext(), attr);
340 rewriter.replaceOp(op, loweredOp);
341 return mlir::success();
347mlir::LogicalResult CIRAllocaOpABILowering::matchAndRewrite(
348 cir::AllocaOp op, OpAdaptor adaptor,
349 mlir::ConversionPatternRewriter &rewriter)
const {
350 mlir::Type allocaPtrTy = op.getType();
351 mlir::Type loweredAllocaPtrTy = getTypeConverter()->convertType(allocaPtrTy);
353 cir::AllocaOp loweredOp = cir::AllocaOp::create(
354 rewriter, op.getLoc(), loweredAllocaPtrTy, op.getName(),
355 op.getAlignmentAttr(), adaptor.getDynAllocSize());
356 loweredOp.setInit(op.getInit());
357 loweredOp.setConstant(op.getConstant());
358 loweredOp.setAnnotationsAttr(op.getAnnotationsAttr());
360 rewriter.replaceOp(op, loweredOp);
361 return mlir::success();
364mlir::LogicalResult CIRCastOpABILowering::matchAndRewrite(
365 cir::CastOp op, OpAdaptor adaptor,
366 mlir::ConversionPatternRewriter &rewriter)
const {
367 mlir::Type srcTy = op.getSrc().getType();
369 if (mlir::isa<cir::DataMemberType, cir::MethodType>(srcTy)) {
370 switch (op.getKind()) {
371 case cir::CastKind::bitcast: {
372 mlir::Type destTy = getTypeConverter()->convertType(op.getType());
373 mlir::Value loweredResult;
374 if (mlir::isa<cir::DataMemberType>(srcTy))
375 loweredResult = lowerModule->getCXXABI().lowerDataMemberBitcast(
376 op, destTy, adaptor.getSrc(), rewriter);
378 loweredResult = lowerModule->getCXXABI().lowerMethodBitcast(
379 op, destTy, adaptor.getSrc(), rewriter);
380 rewriter.replaceOp(op, loweredResult);
381 return mlir::success();
383 case cir::CastKind::member_ptr_to_bool: {
384 mlir::Value loweredResult;
385 if (mlir::isa<cir::DataMemberType>(srcTy))
386 loweredResult = lowerModule->getCXXABI().lowerDataMemberToBoolCast(
387 op, adaptor.getSrc(), rewriter);
389 loweredResult = lowerModule->getCXXABI().lowerMethodToBoolCast(
390 op, adaptor.getSrc(), rewriter);
391 rewriter.replaceOp(op, loweredResult);
392 return mlir::success();
399 mlir::Value loweredResult = cir::CastOp::create(
400 rewriter, op.getLoc(), getTypeConverter()->convertType(op.getType()),
401 adaptor.getKind(), adaptor.getSrc());
402 rewriter.replaceOp(op, loweredResult);
403 return mlir::success();
408 const mlir::DataLayout &layout,
409 const mlir::TypeConverter &tc,
411 mlir::Attribute initVal) {
412 if (mlir::isa_and_present<cir::UndefAttr>(initVal))
413 return cir::UndefAttr::get(tc.convertType(ty));
415 if (mlir::isa_and_present<cir::PoisonAttr>(initVal))
416 return cir::PoisonAttr::get(tc.convertType(ty));
418 if (mlir::isa<cir::DataMemberType>(ty)) {
422 mlir::dyn_cast_if_present<cir::DataMemberOffsetAttr>(initVal))
425 auto dataMemberVal = mlir::cast_if_present<cir::DataMemberAttr>(initVal);
429 if (mlir::isa<cir::MethodType>(ty)) {
430 auto methodVal = mlir::cast_if_present<cir::MethodAttr>(initVal);
434 if (
auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty)) {
435 auto loweredArrTy = mlir::cast<cir::ArrayType>(tc.convertType(arrTy));
440 if (
auto zeroVal = mlir::dyn_cast_if_present<cir::ZeroAttr>(initVal))
441 return cir::ZeroAttr::get(loweredArrTy);
443 auto arrayVal = mlir::cast<cir::ConstArrayAttr>(initVal);
449 if (mlir::isa<mlir::StringAttr>(arrayVal.getElts())) {
450 assert(loweredArrTy == arrTy &&
451 "string-literal array type should not change under CXX ABI");
455 auto arrayElts = mlir::cast<ArrayAttr>(arrayVal.getElts());
457 loweredElements.reserve(arrTy.getSize());
458 for (
const mlir::Attribute &attr : arrayElts) {
459 auto typedAttr = cast<mlir::TypedAttr>(attr);
461 lowerModule, layout, tc, typedAttr.getType(), typedAttr));
464 return cir::ConstArrayAttr::get(
465 loweredArrTy, mlir::ArrayAttr::get(ty.getContext(), loweredElements),
466 arrayVal.getTrailingZerosNum());
469 if (
auto recordTy = mlir::dyn_cast<cir::RecordType>(ty)) {
471 mlir::dyn_cast<cir::RecordType>(tc.convertType(recordTy));
475 if (
auto recVal = mlir::dyn_cast_if_present<cir::ZeroAttr>(initVal))
476 return cir::ZeroAttr::get(convertedTy);
479 mlir::dyn_cast_if_present<cir::ConstRecordAttr>(initVal)) {
480 auto recordMembers = mlir::cast<ArrayAttr>(recVal.getMembers());
483 loweredMembers.reserve(recordMembers.size());
485 for (
const mlir::Attribute &attr : recordMembers) {
486 auto typedAttr = cast<mlir::TypedAttr>(attr);
488 lowerModule, layout, tc, typedAttr.getType(), typedAttr));
491 return cir::ConstRecordAttr::get(
492 convertedTy, mlir::ArrayAttr::get(ty.getContext(), loweredMembers));
495 assert(!initVal &&
"Record init val type not handled");
500 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty)) {
501 auto convertedTy = mlir::cast<cir::PointerType>(tc.convertType(ptrTy));
504 if (
auto gva = mlir::dyn_cast_if_present<cir::GlobalViewAttr>(initVal))
505 return cir::GlobalViewAttr::get(convertedTy, gva.getSymbol(),
506 gva.getIndices(), gva.getAddressPoint());
508 if (
auto goa = mlir::dyn_cast_if_present<cir::GlobalOffsetAttr>(initVal))
509 return cir::GlobalOffsetAttr::get(convertedTy, goa.getSymbol(),
513 mlir::dyn_cast_if_present<cir::BlockAddrInfoAttr>(initVal)) {
514 assert(convertedTy == ptrTy &&
"BlockAddrInfo type should not change");
518 auto constPtr = mlir::cast_if_present<cir::ConstPtrAttr>(initVal);
521 return cir::ConstPtrAttr::get(convertedTy, constPtr.getValue());
524 assert(ty == tc.convertType(ty) &&
525 "cir.global or constant operand is not an CXXABI-dependent type");
528 return cast<mlir::TypedAttr>(initVal);
531mlir::LogicalResult CIRConstantOpABILowering::matchAndRewrite(
532 cir::ConstantOp op, OpAdaptor adaptor,
533 mlir::ConversionPatternRewriter &rewriter)
const {
535 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
537 lowerModule, layout, *getTypeConverter(), op.getType(), op.getValue());
538 rewriter.replaceOpWithNewOp<ConstantOp>(op, newValue);
539 return mlir::success();
542mlir::LogicalResult CIRCmpOpABILowering::matchAndRewrite(
543 cir::CmpOp op, OpAdaptor adaptor,
544 mlir::ConversionPatternRewriter &rewriter)
const {
545 mlir::Type type = op.getLhs().getType();
547 mlir::Value loweredResult;
548 if (mlir::isa<cir::DataMemberType>(type))
549 loweredResult = lowerModule->getCXXABI().lowerDataMemberCmp(
550 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
551 else if (mlir::isa<cir::MethodType>(type))
552 loweredResult = lowerModule->getCXXABI().lowerMethodCmp(
553 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
555 loweredResult = cir::CmpOp::create(
556 rewriter, op.getLoc(), getTypeConverter()->convertType(op.getType()),
557 adaptor.getKind(), adaptor.getLhs(), adaptor.getRhs());
559 rewriter.replaceOp(op, loweredResult);
560 return mlir::success();
563mlir::LogicalResult CIRFuncOpABILowering::matchAndRewrite(
564 cir::FuncOp op, OpAdaptor adaptor,
565 mlir::ConversionPatternRewriter &rewriter)
const {
566 cir::FuncType opFuncType = op.getFunctionType();
567 mlir::TypeConverter::SignatureConversion signatureConversion(
568 opFuncType.getNumInputs());
570 for (
const auto &[i, argType] : llvm::enumerate(opFuncType.getInputs())) {
571 mlir::Type loweredArgType = getTypeConverter()->convertType(argType);
573 return mlir::failure();
574 signatureConversion.addInputs(i, loweredArgType);
577 mlir::Type loweredResultType =
578 getTypeConverter()->convertType(opFuncType.getReturnType());
579 if (!loweredResultType)
580 return mlir::failure();
582 auto loweredFuncType =
583 cir::FuncType::get(signatureConversion.getConvertedTypes(),
584 loweredResultType, opFuncType.isVarArg());
587 cir::FuncOp loweredFuncOp = rewriter.cloneWithoutRegions(op);
588 loweredFuncOp.setFunctionType(loweredFuncType);
590 loweredFuncOp->getName().walkInherentAttrs(
591 loweredFuncOp, [&](llvm::StringRef, mlir::Attribute &attr) {
592 attr = rewriteAttribute(*getTypeConverter(), op->getContext(), attr);
594 rewriter.inlineRegionBefore(op.getBody(), loweredFuncOp.getBody(),
595 loweredFuncOp.end());
596 if (mlir::failed(rewriter.convertRegionTypes(
597 &loweredFuncOp.getBody(), *getTypeConverter(), &signatureConversion)))
598 return mlir::failure();
600 rewriter.eraseOp(op);
601 return mlir::success();
604mlir::LogicalResult CIRGlobalOpABILowering::matchAndRewrite(
605 cir::GlobalOp op, OpAdaptor adaptor,
606 mlir::ConversionPatternRewriter &rewriter)
const {
607 mlir::Type ty = op.getSymType();
608 mlir::Type loweredTy = getTypeConverter()->convertType(ty);
610 return mlir::failure();
612 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
615 lowerModule, layout, *getTypeConverter(), ty, op.getInitialValueAttr());
617 cir::GlobalOp newOp = rewriter.cloneWithoutRegions(op);
618 newOp.setInitialValueAttr(loweredInit);
619 newOp.setSymType(loweredTy);
623 rewriter.inlineRegionBefore(op.getCtorRegion(), newOp.getCtorRegion(),
624 newOp.getCtorRegion().end());
625 rewriter.inlineRegionBefore(op.getDtorRegion(), newOp.getDtorRegion(),
626 newOp.getDtorRegion().end());
627 rewriter.replaceOp(op, newOp);
628 return mlir::success();
631mlir::LogicalResult CIRBaseDataMemberOpABILowering::matchAndRewrite(
632 cir::BaseDataMemberOp op, OpAdaptor adaptor,
633 mlir::ConversionPatternRewriter &rewriter)
const {
634 mlir::Value loweredResult = lowerModule->getCXXABI().lowerBaseDataMember(
635 op, adaptor.getSrc(), rewriter);
636 rewriter.replaceOp(op, loweredResult);
637 return mlir::success();
640mlir::LogicalResult CIRBaseMethodOpABILowering::matchAndRewrite(
641 cir::BaseMethodOp op, OpAdaptor adaptor,
642 mlir::ConversionPatternRewriter &rewriter)
const {
643 mlir::Value loweredResult =
644 lowerModule->getCXXABI().lowerBaseMethod(op, adaptor.getSrc(), rewriter);
645 rewriter.replaceOp(op, loweredResult);
646 return mlir::success();
649mlir::LogicalResult CIRDeleteArrayOpABILowering::matchAndRewrite(
650 cir::DeleteArrayOp op, OpAdaptor adaptor,
651 mlir::ConversionPatternRewriter &rewriter)
const {
652 mlir::FlatSymbolRefAttr deleteFn = op.getDeleteFnAttr();
653 mlir::Location loc = op->getLoc();
654 mlir::Value loweredAddress = adaptor.getAddress();
656 cir::UsualDeleteParamsAttr deleteParams = op.getDeleteParamsAttr();
658 deleteParams = cir::UsualDeleteParamsAttr::get(op.getContext(),
false,
659 std::nullopt,
false,
false);
660 bool cookieRequired = deleteParams.getSize() || op.getElementDtorAttr();
662 assert(!deleteParams.getDestroyingDelete() &&
663 "destroying delete not legal on arrays");
664 assert(!deleteParams.getTypeAwareDelete() &&
665 "type-aware delete not legal on arrays");
667 const CIRCXXABI &cxxABI = lowerModule->getCXXABI();
676 mlir::Value deletePtr;
677 mlir::Value numElements;
678 cir::PointerType ptrTy;
680 mlir::DataLayout dl(op->getParentOfType<mlir::ModuleOp>());
683 cir::IntType sizeTy = cirBuilder.getUIntNTy(ptrWidth);
685 if (cookieRequired) {
686 ptrTy = mlir::cast<cir::PointerType>(loweredAddress.getType());
689 cxxABI.
readArrayCookie(loc, loweredAddress, elementAlign, dl, cirBuilder,
690 numElements, deletePtr, cookieSize);
692 deletePtr = cir::CastOp::create(rewriter, loc, cirBuilder.getVoidPtrTy(),
693 cir::CastKind::bitcast, loweredAddress);
703 mlir::FlatSymbolRefAttr dtorFn = op.getElementDtorAttr();
706 auto getCalleeCallingConv = [&](mlir::FlatSymbolRefAttr callee) {
708 mlir::SymbolTable::lookupNearestSymbolFrom<cir::FuncOp>(op, callee))
709 return fn.getCallingConv();
710 return cir::CallingConv::C;
713 cir::CleanupKind cleanupKind =
714 op.getDtorMayThrow() ? cir::CleanupKind::All : cir::CleanupKind::Normal;
715 cir::CleanupScopeOp::create(
716 rewriter, loc, cleanupKind,
718 [&](mlir::OpBuilder &b, mlir::Location l) {
720 auto eltPtrTy = cir::PointerType::get(ptrTy.getPointee());
721 auto arrayDtor = cir::ArrayDtor::create(
722 b, l, loweredAddress, numElements,
723 [&](mlir::OpBuilder &bb, mlir::Location ll) {
725 bb.getInsertionBlock()->addArgument(eltPtrTy, ll);
726 auto dtorCall = cir::CallOp::create(
727 bb, ll, dtorFn, cir::VoidType(), mlir::ValueRange{
arg});
728 dtorCall.setCallingConv(getCalleeCallingConv(dtorFn));
729 if (!op.getDtorMayThrow())
730 dtorCall.setNothrowAttr(bb.getUnitAttr());
731 cir::YieldOp::create(bb, ll);
733 if (op.getDtorMayThrow())
734 arrayDtor.setDtorMayThrow(
true);
736 cir::YieldOp::create(b, l);
739 [&](mlir::OpBuilder &b, mlir::Location l) {
742 if (deleteParams.getSize()) {
743 uint64_t eltSizeBytes = dl.getTypeSizeInBits(ptrTy.getPointee()) / 8;
744 auto eltSizeVal = cir::ConstantOp::create(
745 b, l, cir::IntAttr::get(sizeTy, eltSizeBytes));
746 mlir::Value allocSize =
747 cir::MulOp::create(b, l, sizeTy, eltSizeVal, numElements);
748 auto cookieSizeVal = cir::ConstantOp::create(
749 b, l, cir::IntAttr::get(sizeTy, cookieSize.
getQuantity()));
751 cir::AddOp::create(b, l, sizeTy, allocSize, cookieSizeVal);
754 if (deleteParams.getAlignment()) {
755 auto alignVal = cir::ConstantOp::create(
756 b, l, cir::IntAttr::get(sizeTy, *deleteParams.getAlignment()));
761 cir::CallOp::create(b, l, deleteFn, cir::VoidType(), callArgs);
762 deleteCall.setCallingConv(getCalleeCallingConv(deleteFn));
765 deleteCall.setNothrowAttr(b.getUnitAttr());
766 cir::YieldOp::create(b, l);
769 rewriter.eraseOp(op);
770 return mlir::success();
773mlir::LogicalResult CIRDerivedDataMemberOpABILowering::matchAndRewrite(
774 cir::DerivedDataMemberOp op, OpAdaptor adaptor,
775 mlir::ConversionPatternRewriter &rewriter)
const {
776 mlir::Value loweredResult = lowerModule->getCXXABI().lowerDerivedDataMember(
777 op, adaptor.getSrc(), rewriter);
778 rewriter.replaceOp(op, loweredResult);
779 return mlir::success();
782mlir::LogicalResult CIRDerivedMethodOpABILowering::matchAndRewrite(
783 cir::DerivedMethodOp op, OpAdaptor adaptor,
784 mlir::ConversionPatternRewriter &rewriter)
const {
785 mlir::Value loweredResult = lowerModule->getCXXABI().lowerDerivedMethod(
786 op, adaptor.getSrc(), rewriter);
787 rewriter.replaceOp(op, loweredResult);
788 return mlir::success();
791mlir::LogicalResult CIRDynamicCastOpABILowering::matchAndRewrite(
792 cir::DynamicCastOp op, OpAdaptor adaptor,
793 mlir::ConversionPatternRewriter &rewriter)
const {
794 mlir::Value loweredResult =
795 lowerModule->getCXXABI().lowerDynamicCast(op, rewriter);
796 rewriter.replaceOp(op, loweredResult);
797 return mlir::success();
800mlir::LogicalResult CIRGetMethodOpABILowering::matchAndRewrite(
801 cir::GetMethodOp op, OpAdaptor adaptor,
802 mlir::ConversionPatternRewriter &rewriter)
const {
805 lowerModule->getCXXABI().lowerGetMethod(
806 op, callee, thisArg, adaptor.getMethod(), adaptor.getObject(), rewriter);
807 rewriter.replaceOp(op, {callee, thisArg});
808 return mlir::success();
811mlir::LogicalResult CIRGetRuntimeMemberOpABILowering::matchAndRewrite(
812 cir::GetRuntimeMemberOp op, OpAdaptor adaptor,
813 mlir::ConversionPatternRewriter &rewriter)
const {
814 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
815 mlir::Operation *newOp = lowerModule->getCXXABI().lowerGetRuntimeMember(
816 op, resTy, adaptor.getAddr(), adaptor.getMember(), rewriter);
817 rewriter.replaceOp(op, newOp);
818 return mlir::success();
821mlir::LogicalResult CIRVTableGetTypeInfoOpABILowering::matchAndRewrite(
822 cir::VTableGetTypeInfoOp op, OpAdaptor adaptor,
823 mlir::ConversionPatternRewriter &rewriter)
const {
824 mlir::Value loweredResult =
825 lowerModule->getCXXABI().lowerVTableGetTypeInfo(op, rewriter);
826 rewriter.replaceOp(op, loweredResult);
827 return mlir::success();
836 CIRABITypeConverter(mlir::MLIRContext &ctx, mlir::DataLayout &dataLayout,
837 cir::LowerModule &lowerModule)
838 : RecordRewritingTypeConverter(ctx) {
839 addConversion([&](cir::DataMemberType type) -> mlir::Type {
842 return convertType(abiType);
844 addConversion([&](cir::MethodType type) -> mlir::Type {
846 return convertType(abiType);
853 bool typeMayChange(mlir::Type type)
const override {
854 return mlir::isa<cir::DataMemberType, cir::MethodType>(type);
861 const mlir::TypeConverter &typeConverter) {
862 target.addLegalOp<mlir::ModuleOp>();
867 target.addDynamicallyLegalDialect<cir::CIRDialect>(
868 [&typeConverter](mlir::Operation *op) {
869 if (!typeConverter.isLegal(op))
872 bool attrs = areCXXABIInherentAttrsLegal(op, typeConverter);
875 std::all_of(op->getRegions().begin(), op->getRegions().end(),
876 [&typeConverter](mlir::Region ®ion) {
877 return typeConverter.isLegal(®ion);
881 target.addDynamicallyLegalDialect<mlir::acc::OpenACCDialect>(
882 [&typeConverter](mlir::Operation *op) {
883 if (!typeConverter.isLegal(op))
886 bool attrs = areCXXABIInherentAttrsLegal(op, typeConverter);
889 std::all_of(op->getRegions().begin(), op->getRegions().end(),
890 [&typeConverter](mlir::Region ®ion) {
891 return typeConverter.isLegal(®ion);
897 target.addDynamicallyLegalOp<cir::CastOp>([&typeConverter](cir::CastOp op) {
898 if (op.getSrc().getType() == op.getType()) {
899 switch (op.getKind()) {
900 case cir::CastKind::bitcast:
901 case cir::CastKind::address_space:
902 case cir::CastKind::float_complex:
903 case cir::CastKind::int_complex:
909 if (!typeConverter.isLegal(op.getOperation()))
913 return areCXXABIInherentAttrsLegal(op, typeConverter);
917 target.addDynamicallyLegalOp<cir::FuncOp>([&typeConverter](cir::FuncOp op) {
918 bool attrs = areCXXABIInherentAttrsLegal(op, typeConverter);
920 return attrs && typeConverter.isLegal(op.getFunctionType());
922 target.addDynamicallyLegalOp<cir::GlobalOp>(
923 [&typeConverter](cir::GlobalOp op) {
924 return typeConverter.isLegal(op.getSymType());
928 target.addIllegalOp<cir::DeleteArrayOp>();
929 target.addIllegalOp<cir::DynamicCastOp>();
930 target.addIllegalOp<cir::VTableGetTypeInfoOp>();
937void CXXABILoweringPass::runOnOperation() {
938 auto mod = mlir::cast<mlir::ModuleOp>(getOperation());
939 mlir::MLIRContext *ctx = mod.getContext();
944 mod.emitWarning(
"Cannot create a CIR lower module, skipping the ")
949 mlir::DataLayout dataLayout(mod);
950 CIRABITypeConverter typeConverter(*ctx, dataLayout, *lowerModule);
952 mlir::RewritePatternSet patterns(ctx);
953 patterns.add<CIRGenericCXXABILoweringPattern>(patterns.getContext(),
956#define GET_ABI_LOWERING_PATTERNS_LIST
957#include "clang/CIR/Dialect/IR/CIRLowering.inc"
958#undef GET_ABI_LOWERING_PATTERNS_LIST
959 >(patterns.getContext(), typeConverter, dataLayout, *lowerModule);
961 mlir::ConversionTarget target(*ctx);
964 llvm::SmallVector<mlir::Operation *> ops;
968 if (failed(mlir::applyPartialConversion(ops, target, std::move(patterns))))
971 typeConverter.restoreRecordTypeNames();
975 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)
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.
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
StringRef getName(const HeaderType T)
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)