12#include "mlir/Dialect/OpenACC/OpenACCOpsDialect.h.inc"
13#include "mlir/Dialect/OpenMP/OpenMPOpsDialect.h.inc"
14#include "mlir/IR/PatternMatch.h"
15#include "mlir/Interfaces/DataLayoutInterfaces.h"
16#include "mlir/Pass/Pass.h"
17#include "mlir/Transforms/DialectConversion.h"
27#include "llvm/ADT/ScopeExit.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())));
215 .Case<cir::GlobalOffsetAttr>([&tc](cir::GlobalOffsetAttr goa) {
216 return cir::GlobalOffsetAttr::get(tc.convertType(goa.getType()),
217 goa.getSymbol(), goa.getOffset());
219 .Case<cir::VTableAttr>([&tc, ctx](cir::VTableAttr vta) {
220 return cir::VTableAttr::get(
221 tc.convertType(vta.getType()),
222 mlir::cast<mlir::ArrayAttr>(
223 rewriteAttribute(tc, ctx, vta.getData())));
225 .Case<cir::TypeInfoAttr>([&tc, ctx](cir::TypeInfoAttr tia) {
226 return cir::TypeInfoAttr::get(
227 tc.convertType(tia.getType()),
228 mlir::cast<mlir::ArrayAttr>(
229 rewriteAttribute(tc, ctx, tia.getData())));
231 .Case<cir::DynamicCastInfoAttr>([&tc,
232 ctx](cir::DynamicCastInfoAttr dcia) {
233 return cir::DynamicCastInfoAttr::get(
234 mlir::cast<cir::GlobalViewAttr>(
235 rewriteAttribute(tc, ctx, dcia.getSrcRtti())),
236 mlir::cast<cir::GlobalViewAttr>(
237 rewriteAttribute(tc, ctx, dcia.getDestRtti())),
238 dcia.getRuntimeFunc(), dcia.getBadCastFunc(), dcia.getOffsetHint());
240 .Case<cir::ConstRecordAttr>([&tc, ctx](cir::ConstRecordAttr cra) {
241 return cir::ConstRecordAttr::get(
242 ctx, tc.convertType(cra.getType()),
243 mlir::cast<mlir::ArrayAttr>(
244 rewriteAttribute(tc, ctx, cra.getMembers())));
246 .DefaultUnreachable(
"unrewritten illegal attribute kind");
249#define GET_ABI_LOWERING_PATTERNS
250#include "clang/CIR/Dialect/IR/CIRLowering.inc"
251#undef GET_ABI_LOWERING_PATTERNS
253struct CXXABILoweringPass
254 :
public impl::CXXABILoweringBase<CXXABILoweringPass> {
255 CXXABILoweringPass() =
default;
256 void runOnOperation()
override;
264class CIRGenericCXXABILoweringPattern :
public mlir::ConversionPattern {
266 CIRGenericCXXABILoweringPattern(mlir::MLIRContext *context,
267 const mlir::TypeConverter &typeConverter)
268 : mlir::ConversionPattern(typeConverter, MatchAnyOpTypeTag(),
272 matchAndRewrite(mlir::Operation *op, llvm::ArrayRef<mlir::Value> operands,
273 mlir::ConversionPatternRewriter &rewriter)
const override {
275 if (llvm::isa<cir::AllocaOp, cir::BaseDataMemberOp, cir::BaseMethodOp,
276 cir::CastOp, cir::CmpOp, cir::ConstantOp, cir::DeleteArrayOp,
277 cir::DerivedDataMemberOp, cir::DerivedMethodOp, cir::FuncOp,
278 cir::GetMethodOp, cir::GetRuntimeMemberOp, cir::GlobalOp>(op))
279 return mlir::failure();
281 const mlir::TypeConverter *typeConverter = getTypeConverter();
282 assert(typeConverter &&
283 "CIRGenericCXXABILoweringPattern requires a type converter");
284 bool operandsAndResultsLegal = typeConverter->isLegal(op);
286 std::all_of(op->getRegions().begin(), op->getRegions().end(),
287 [typeConverter](mlir::Region ®ion) {
288 return typeConverter->isLegal(®ion);
291 llvm::all_of(op->getAttrs(), [typeConverter](mlir::NamedAttribute na) {
292 return isCXXABIAttributeLegal(*typeConverter, na.getValue());
295 if (operandsAndResultsLegal && regionsLegal && attrsLegal) {
298 return mlir::failure();
301 mlir::OperationState loweredOpState(op->getLoc(), op->getName());
302 loweredOpState.addOperands(operands);
303 loweredOpState.addSuccessors(op->getSuccessors());
306 llvm::SmallVector<mlir::NamedAttribute> attrs;
307 for (
const mlir::NamedAttribute &na : op->getAttrs())
310 rewriteAttribute(*typeConverter, op->getContext(), na.getValue())});
311 loweredOpState.addAttributes(attrs);
314 llvm::SmallVector<mlir::Type> loweredResultTypes;
315 loweredResultTypes.reserve(op->getNumResults());
316 for (mlir::Type result : op->getResultTypes())
317 loweredResultTypes.push_back(typeConverter->convertType(result));
318 loweredOpState.addTypes(loweredResultTypes);
321 for (mlir::Region ®ion : op->getRegions()) {
322 mlir::Region *loweredRegion = loweredOpState.addRegion();
323 rewriter.inlineRegionBefore(region, *loweredRegion, loweredRegion->end());
325 rewriter.convertRegionTypes(loweredRegion, *getTypeConverter())))
326 return mlir::failure();
330 mlir::Operation *loweredOp = rewriter.create(loweredOpState);
332 rewriter.replaceOp(op, loweredOp);
333 return mlir::success();
339mlir::LogicalResult CIRAllocaOpABILowering::matchAndRewrite(
340 cir::AllocaOp op, OpAdaptor adaptor,
341 mlir::ConversionPatternRewriter &rewriter)
const {
342 mlir::Type allocaPtrTy = op.getType();
343 mlir::Type loweredAllocaPtrTy = getTypeConverter()->convertType(allocaPtrTy);
345 cir::AllocaOp loweredOp = cir::AllocaOp::create(
346 rewriter, op.getLoc(), loweredAllocaPtrTy, op.getName(),
347 op.getAlignmentAttr(), adaptor.getDynAllocSize());
348 loweredOp.setInit(op.getInit());
349 loweredOp.setConstant(op.getConstant());
350 loweredOp.setAnnotationsAttr(op.getAnnotationsAttr());
352 rewriter.replaceOp(op, loweredOp);
353 return mlir::success();
356mlir::LogicalResult CIRCastOpABILowering::matchAndRewrite(
357 cir::CastOp op, OpAdaptor adaptor,
358 mlir::ConversionPatternRewriter &rewriter)
const {
359 mlir::Type srcTy = op.getSrc().getType();
361 if (mlir::isa<cir::DataMemberType, cir::MethodType>(srcTy)) {
362 switch (op.getKind()) {
363 case cir::CastKind::bitcast: {
364 mlir::Type destTy = getTypeConverter()->convertType(op.getType());
365 mlir::Value loweredResult;
366 if (mlir::isa<cir::DataMemberType>(srcTy))
367 loweredResult = lowerModule->getCXXABI().lowerDataMemberBitcast(
368 op, destTy, adaptor.getSrc(), rewriter);
370 loweredResult = lowerModule->getCXXABI().lowerMethodBitcast(
371 op, destTy, adaptor.getSrc(), rewriter);
372 rewriter.replaceOp(op, loweredResult);
373 return mlir::success();
375 case cir::CastKind::member_ptr_to_bool: {
376 mlir::Value loweredResult;
377 if (mlir::isa<cir::DataMemberType>(srcTy))
378 loweredResult = lowerModule->getCXXABI().lowerDataMemberToBoolCast(
379 op, adaptor.getSrc(), rewriter);
381 loweredResult = lowerModule->getCXXABI().lowerMethodToBoolCast(
382 op, adaptor.getSrc(), rewriter);
383 rewriter.replaceOp(op, loweredResult);
384 return mlir::success();
391 mlir::Value loweredResult = cir::CastOp::create(
392 rewriter, op.getLoc(), getTypeConverter()->convertType(op.getType()),
393 adaptor.getKind(), adaptor.getSrc());
394 rewriter.replaceOp(op, loweredResult);
395 return mlir::success();
400 const mlir::DataLayout &layout,
401 const mlir::TypeConverter &tc,
403 mlir::Attribute initVal) {
404 if (mlir::isa<cir::DataMemberType>(ty)) {
408 mlir::dyn_cast_if_present<cir::DataMemberOffsetAttr>(initVal))
411 auto dataMemberVal = mlir::cast_if_present<cir::DataMemberAttr>(initVal);
415 if (mlir::isa<cir::MethodType>(ty)) {
416 auto methodVal = mlir::cast_if_present<cir::MethodAttr>(initVal);
420 if (
auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty)) {
421 auto loweredArrTy = mlir::cast<cir::ArrayType>(tc.convertType(arrTy));
426 if (
auto zeroVal = mlir::dyn_cast_if_present<cir::ZeroAttr>(initVal))
427 return cir::ZeroAttr::get(loweredArrTy);
429 auto arrayVal = mlir::cast<cir::ConstArrayAttr>(initVal);
435 if (mlir::isa<mlir::StringAttr>(arrayVal.getElts())) {
436 assert(loweredArrTy == arrTy &&
437 "string-literal array type should not change under CXX ABI");
441 auto arrayElts = mlir::cast<ArrayAttr>(arrayVal.getElts());
443 loweredElements.reserve(arrTy.getSize());
444 for (
const mlir::Attribute &attr : arrayElts) {
445 auto typedAttr = cast<mlir::TypedAttr>(attr);
447 lowerModule, layout, tc, typedAttr.getType(), typedAttr));
450 return cir::ConstArrayAttr::get(
451 loweredArrTy, mlir::ArrayAttr::get(ty.getContext(), loweredElements),
452 arrayVal.getTrailingZerosNum());
455 if (
auto recordTy = mlir::dyn_cast<cir::RecordType>(ty)) {
457 mlir::dyn_cast<cir::RecordType>(tc.convertType(recordTy));
461 if (
auto recVal = mlir::dyn_cast_if_present<cir::ZeroAttr>(initVal))
462 return cir::ZeroAttr::get(convertedTy);
464 if (
auto undefVal = mlir::dyn_cast_if_present<cir::UndefAttr>(initVal))
465 return cir::UndefAttr::get(convertedTy);
469 if (
auto poisonVal = mlir::dyn_cast_if_present<cir::PoisonAttr>(initVal))
470 return cir::PoisonAttr::get(convertedTy);
473 mlir::dyn_cast_if_present<cir::ConstRecordAttr>(initVal)) {
474 auto recordMembers = mlir::cast<ArrayAttr>(recVal.getMembers());
477 loweredMembers.reserve(recordMembers.size());
479 for (
const mlir::Attribute &attr : recordMembers) {
480 auto typedAttr = cast<mlir::TypedAttr>(attr);
482 lowerModule, layout, tc, typedAttr.getType(), typedAttr));
485 return cir::ConstRecordAttr::get(
486 convertedTy, mlir::ArrayAttr::get(ty.getContext(), loweredMembers));
489 assert(!initVal &&
"Record init val type not handled");
494 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty)) {
495 auto convertedTy = mlir::cast<cir::PointerType>(tc.convertType(ptrTy));
498 if (
auto gva = mlir::dyn_cast_if_present<cir::GlobalViewAttr>(initVal))
499 return cir::GlobalViewAttr::get(convertedTy, gva.getSymbol(),
502 if (
auto goa = mlir::dyn_cast_if_present<cir::GlobalOffsetAttr>(initVal))
503 return cir::GlobalOffsetAttr::get(convertedTy, goa.getSymbol(),
507 mlir::dyn_cast_if_present<cir::BlockAddrInfoAttr>(initVal)) {
508 assert(convertedTy == ptrTy &&
"BlockAddrInfo type should not change");
512 auto constPtr = mlir::cast_if_present<cir::ConstPtrAttr>(initVal);
515 return cir::ConstPtrAttr::get(convertedTy, constPtr.getValue());
518 assert(ty == tc.convertType(ty) &&
519 "cir.global or constant operand is not an CXXABI-dependent type");
522 return cast<mlir::TypedAttr>(initVal);
525mlir::LogicalResult CIRConstantOpABILowering::matchAndRewrite(
526 cir::ConstantOp op, OpAdaptor adaptor,
527 mlir::ConversionPatternRewriter &rewriter)
const {
529 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
531 lowerModule, layout, *getTypeConverter(), op.getType(), op.getValue());
532 rewriter.replaceOpWithNewOp<ConstantOp>(op, newValue);
533 return mlir::success();
536mlir::LogicalResult CIRCmpOpABILowering::matchAndRewrite(
537 cir::CmpOp op, OpAdaptor adaptor,
538 mlir::ConversionPatternRewriter &rewriter)
const {
539 mlir::Type type = op.getLhs().getType();
541 mlir::Value loweredResult;
542 if (mlir::isa<cir::DataMemberType>(type))
543 loweredResult = lowerModule->getCXXABI().lowerDataMemberCmp(
544 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
545 else if (mlir::isa<cir::MethodType>(type))
546 loweredResult = lowerModule->getCXXABI().lowerMethodCmp(
547 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
549 loweredResult = cir::CmpOp::create(
550 rewriter, op.getLoc(), getTypeConverter()->convertType(op.getType()),
551 adaptor.getKind(), adaptor.getLhs(), adaptor.getRhs());
553 rewriter.replaceOp(op, loweredResult);
554 return mlir::success();
557mlir::LogicalResult CIRFuncOpABILowering::matchAndRewrite(
558 cir::FuncOp op, OpAdaptor adaptor,
559 mlir::ConversionPatternRewriter &rewriter)
const {
560 cir::FuncType opFuncType = op.getFunctionType();
561 mlir::TypeConverter::SignatureConversion signatureConversion(
562 opFuncType.getNumInputs());
564 for (
const auto &[i, argType] : llvm::enumerate(opFuncType.getInputs())) {
565 mlir::Type loweredArgType = getTypeConverter()->convertType(argType);
567 return mlir::failure();
568 signatureConversion.addInputs(i, loweredArgType);
571 mlir::Type loweredResultType =
572 getTypeConverter()->convertType(opFuncType.getReturnType());
573 if (!loweredResultType)
574 return mlir::failure();
576 auto loweredFuncType =
577 cir::FuncType::get(signatureConversion.getConvertedTypes(),
578 loweredResultType, opFuncType.isVarArg());
581 cir::FuncOp loweredFuncOp = rewriter.cloneWithoutRegions(op);
582 loweredFuncOp.setFunctionType(loweredFuncType);
585 for (
const mlir::NamedAttribute &na : op->getAttrs())
587 {na.getName(), rewriteAttribute(*getTypeConverter(), op->getContext(),
590 loweredFuncOp->setAttrs(attrs);
592 rewriter.inlineRegionBefore(op.getBody(), loweredFuncOp.getBody(),
593 loweredFuncOp.end());
594 if (mlir::failed(rewriter.convertRegionTypes(
595 &loweredFuncOp.getBody(), *getTypeConverter(), &signatureConversion)))
596 return mlir::failure();
598 rewriter.eraseOp(op);
599 return mlir::success();
602mlir::LogicalResult CIRGlobalOpABILowering::matchAndRewrite(
603 cir::GlobalOp op, OpAdaptor adaptor,
604 mlir::ConversionPatternRewriter &rewriter)
const {
605 mlir::Type ty = op.getSymType();
606 mlir::Type loweredTy = getTypeConverter()->convertType(ty);
608 return mlir::failure();
610 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
613 lowerModule, layout, *getTypeConverter(), ty, op.getInitialValueAttr());
615 auto newOp = mlir::cast<cir::GlobalOp>(rewriter.clone(*op.getOperation()));
616 newOp.setInitialValueAttr(loweredInit);
617 newOp.setSymType(loweredTy);
618 rewriter.replaceOp(op, newOp);
619 return mlir::success();
622mlir::LogicalResult CIRBaseDataMemberOpABILowering::matchAndRewrite(
623 cir::BaseDataMemberOp op, OpAdaptor adaptor,
624 mlir::ConversionPatternRewriter &rewriter)
const {
625 mlir::Value loweredResult = lowerModule->getCXXABI().lowerBaseDataMember(
626 op, adaptor.getSrc(), rewriter);
627 rewriter.replaceOp(op, loweredResult);
628 return mlir::success();
631mlir::LogicalResult CIRBaseMethodOpABILowering::matchAndRewrite(
632 cir::BaseMethodOp op, OpAdaptor adaptor,
633 mlir::ConversionPatternRewriter &rewriter)
const {
634 mlir::Value loweredResult =
635 lowerModule->getCXXABI().lowerBaseMethod(op, adaptor.getSrc(), rewriter);
636 rewriter.replaceOp(op, loweredResult);
637 return mlir::success();
640mlir::LogicalResult CIRDeleteArrayOpABILowering::matchAndRewrite(
641 cir::DeleteArrayOp op, OpAdaptor adaptor,
642 mlir::ConversionPatternRewriter &rewriter)
const {
643 mlir::FlatSymbolRefAttr deleteFn = op.getDeleteFnAttr();
644 mlir::Location loc = op->getLoc();
645 mlir::Value loweredAddress = adaptor.getAddress();
647 cir::UsualDeleteParamsAttr deleteParams = op.getDeleteParams();
648 bool cookieRequired = deleteParams.getSize() || op.getElementDtorAttr();
650 assert(!deleteParams.getDestroyingDelete() &&
651 "destroying delete not legal on arrays");
652 assert(!deleteParams.getTypeAwareDelete() &&
653 "type-aware delete not legal on arrays");
655 const CIRCXXABI &cxxABI = lowerModule->getCXXABI();
664 mlir::Value deletePtr;
665 mlir::Value numElements;
666 cir::PointerType ptrTy;
668 mlir::DataLayout dl(op->getParentOfType<mlir::ModuleOp>());
671 cir::IntType sizeTy = cirBuilder.getUIntNTy(ptrWidth);
673 if (cookieRequired) {
674 ptrTy = mlir::cast<cir::PointerType>(loweredAddress.getType());
675 cxxABI.
readArrayCookie(loc, loweredAddress, dl, cirBuilder, numElements,
676 deletePtr, cookieSize);
678 deletePtr = cir::CastOp::create(rewriter, loc, cirBuilder.getVoidPtrTy(),
679 cir::CastKind::bitcast, loweredAddress);
689 mlir::FlatSymbolRefAttr dtorFn = op.getElementDtorAttr();
690 cir::CleanupKind cleanupKind =
691 op.getDtorMayThrow() ? cir::CleanupKind::All : cir::CleanupKind::Normal;
692 cir::CleanupScopeOp::create(
693 rewriter, loc, cleanupKind,
695 [&](mlir::OpBuilder &b, mlir::Location l) {
697 auto eltPtrTy = cir::PointerType::get(ptrTy.getPointee());
698 auto arrayDtor = cir::ArrayDtor::create(
699 b, l, loweredAddress, numElements,
700 [&](mlir::OpBuilder &bb, mlir::Location ll) {
702 bb.getInsertionBlock()->addArgument(eltPtrTy, ll);
703 auto dtorCall = cir::CallOp::create(
704 bb, ll, dtorFn, cir::VoidType(), mlir::ValueRange{
arg});
705 if (!op.getDtorMayThrow())
706 dtorCall.setNothrowAttr(bb.getUnitAttr());
707 cir::YieldOp::create(bb, ll);
709 if (op.getDtorMayThrow())
710 arrayDtor.setDtorMayThrow(
true);
712 cir::YieldOp::create(b, l);
715 [&](mlir::OpBuilder &b, mlir::Location l) {
718 if (deleteParams.getSize()) {
719 uint64_t eltSizeBytes = dl.getTypeSizeInBits(ptrTy.getPointee()) / 8;
720 auto eltSizeVal = cir::ConstantOp::create(
721 b, l, cir::IntAttr::get(sizeTy, eltSizeBytes));
722 mlir::Value allocSize =
723 cir::MulOp::create(b, l, sizeTy, eltSizeVal, numElements);
724 auto cookieSizeVal = cir::ConstantOp::create(
725 b, l, cir::IntAttr::get(sizeTy, cookieSize.
getQuantity()));
727 cir::AddOp::create(b, l, sizeTy, allocSize, cookieSizeVal);
730 if (deleteParams.getAlignment()) {
731 auto alignVal = cir::ConstantOp::create(
732 b, l, cir::IntAttr::get(sizeTy, *deleteParams.getAlignment()));
737 cir::CallOp::create(b, l, deleteFn, cir::VoidType(), callArgs);
740 deleteCall.setNothrowAttr(b.getUnitAttr());
741 cir::YieldOp::create(b, l);
744 rewriter.eraseOp(op);
745 return mlir::success();
748mlir::LogicalResult CIRDerivedDataMemberOpABILowering::matchAndRewrite(
749 cir::DerivedDataMemberOp op, OpAdaptor adaptor,
750 mlir::ConversionPatternRewriter &rewriter)
const {
751 mlir::Value loweredResult = lowerModule->getCXXABI().lowerDerivedDataMember(
752 op, adaptor.getSrc(), rewriter);
753 rewriter.replaceOp(op, loweredResult);
754 return mlir::success();
757mlir::LogicalResult CIRDerivedMethodOpABILowering::matchAndRewrite(
758 cir::DerivedMethodOp op, OpAdaptor adaptor,
759 mlir::ConversionPatternRewriter &rewriter)
const {
760 mlir::Value loweredResult = lowerModule->getCXXABI().lowerDerivedMethod(
761 op, adaptor.getSrc(), rewriter);
762 rewriter.replaceOp(op, loweredResult);
763 return mlir::success();
766mlir::LogicalResult CIRDynamicCastOpABILowering::matchAndRewrite(
767 cir::DynamicCastOp op, OpAdaptor adaptor,
768 mlir::ConversionPatternRewriter &rewriter)
const {
769 mlir::Value loweredResult =
770 lowerModule->getCXXABI().lowerDynamicCast(op, rewriter);
771 rewriter.replaceOp(op, loweredResult);
772 return mlir::success();
775mlir::LogicalResult CIRGetMethodOpABILowering::matchAndRewrite(
776 cir::GetMethodOp op, OpAdaptor adaptor,
777 mlir::ConversionPatternRewriter &rewriter)
const {
780 lowerModule->getCXXABI().lowerGetMethod(
781 op, callee, thisArg, adaptor.getMethod(), adaptor.getObject(), rewriter);
782 rewriter.replaceOp(op, {callee, thisArg});
783 return mlir::success();
786mlir::LogicalResult CIRGetRuntimeMemberOpABILowering::matchAndRewrite(
787 cir::GetRuntimeMemberOp op, OpAdaptor adaptor,
788 mlir::ConversionPatternRewriter &rewriter)
const {
789 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
790 mlir::Operation *newOp = lowerModule->getCXXABI().lowerGetRuntimeMember(
791 op, resTy, adaptor.getAddr(), adaptor.getMember(), rewriter);
792 rewriter.replaceOp(op, newOp);
793 return mlir::success();
796mlir::LogicalResult CIRVTableGetTypeInfoOpABILowering::matchAndRewrite(
797 cir::VTableGetTypeInfoOp op, OpAdaptor adaptor,
798 mlir::ConversionPatternRewriter &rewriter)
const {
799 mlir::Value loweredResult =
800 lowerModule->getCXXABI().lowerVTableGetTypeInfo(op, rewriter);
801 rewriter.replaceOp(op, loweredResult);
802 return mlir::success();
810class CIRABITypeConverter :
public mlir::TypeConverter {
812 mlir::MLIRContext &context;
817 DenseMap<uint64_t, std::unique_ptr<SmallVector<cir::RecordType>>>
819 llvm::sys::SmartRWMutex<true> callStackMutex;
824 llvm::SmallVector<cir::RecordType> convertedRecordTypes;
825 llvm::sys::SmartRWMutex<true> recordTypeMutex;
831 SmallVector<cir::RecordType> &getCurrentThreadRecursiveStack() {
834 std::shared_lock<
decltype(callStackMutex)> lock(callStackMutex,
836 if (context.isMultithreadingEnabled())
838 auto recursiveStack = conversionCallStack.find(llvm::get_threadid());
839 if (recursiveStack != conversionCallStack.end())
840 return *recursiveStack->second;
845 std::unique_lock<
decltype(callStackMutex)> lock(callStackMutex);
846 auto recursiveStackInserted = conversionCallStack.insert(
847 std::make_pair(llvm::get_threadid(),
848 std::make_unique<SmallVector<cir::RecordType>>()));
849 return *recursiveStackInserted.first->second;
852 void addConvertedRecordType(cir::RecordType rt) {
853 std::unique_lock<
decltype(recordTypeMutex)> lock(recordTypeMutex);
854 convertedRecordTypes.push_back(rt);
857 llvm::SmallVector<mlir::Type> convertRecordMemberTypes(cir::RecordType type) {
858 llvm::SmallVector<mlir::Type> loweredMemberTypes;
859 loweredMemberTypes.reserve(
type.getNumElements());
861 if (mlir::failed(convertTypes(
type.getMembers(), loweredMemberTypes)))
864 return loweredMemberTypes;
867 cir::RecordType convertRecordType(cir::RecordType type) {
871 if (!
type.getName()) {
872 llvm::SmallVector<mlir::Type> converted = convertRecordMemberTypes(type);
873 assert(converted.size() ==
type.getNumElements() &&
874 "member conversion must be one type in, one type out for the "
875 "kinds to carry over by index");
876 if (
auto u = mlir::dyn_cast<cir::UnionType>(type)) {
877 mlir::Type loweredPadding;
878 if (mlir::Type pad = u.getPadding())
879 loweredPadding = convertType(pad);
880 return cir::UnionType::get(
type.getContext(), converted,
881 type.getPacked(), loweredPadding,
884 auto s = mlir::cast<cir::StructType>(type);
885 return cir::StructType::get(
type.getContext(), converted,
886 type.getPacked(), s.getIsClass(),
890 assert(!
type.isIncomplete() ||
type.getMembers().empty());
895 if (
type.isIncomplete() ||
type.isABIConvertedRecord())
898 SmallVectorImpl<cir::RecordType> &recursiveStack =
899 getCurrentThreadRecursiveStack();
901 cir::RecordType convertedType;
902 if (mlir::isa<cir::UnionType>(type))
904 cir::UnionType::get(
type.getContext(),
type.getABIConvertedName());
907 cir::StructType::get(
type.getContext(),
type.getABIConvertedName(),
908 mlir::cast<cir::StructType>(type).getIsClass());
912 return convertedType;
918 if (llvm::is_contained(recursiveStack, type))
919 return convertedType;
921 recursiveStack.push_back(type);
922 llvm::scope_exit popConvertingType(
923 [&recursiveStack]() { recursiveStack.pop_back(); });
925 SmallVector<mlir::Type> convertedMembers = convertRecordMemberTypes(type);
926 assert(convertedMembers.size() ==
type.getNumElements() &&
927 "member conversion must be one type in, one type out for the kinds "
928 "to carry over by index");
930 mlir::Type loweredPadding;
931 if (
auto u = mlir::dyn_cast<cir::UnionType>(type))
932 if (mlir::Type pad = u.getPadding())
933 loweredPadding = convertType(pad);
934 convertedType.
complete(convertedMembers,
type.getPacked(), loweredPadding,
935 type.getMemberKinds());
936 addConvertedRecordType(convertedType);
937 return convertedType;
941 CIRABITypeConverter(mlir::MLIRContext &ctx, mlir::DataLayout &dataLayout,
942 cir::LowerModule &lowerModule)
944 addConversion([&](mlir::Type type) -> mlir::Type {
return type; });
947 addConversion([&](cir::PointerType type) -> mlir::Type {
948 mlir::Type loweredPointeeType = convertType(
type.getPointee());
949 if (!loweredPointeeType)
951 return cir::PointerType::get(
type.getContext(), loweredPointeeType,
952 type.getAddrSpace());
954 addConversion([&](cir::ArrayType type) -> mlir::Type {
955 mlir::Type loweredElementType = convertType(
type.getElementType());
956 if (!loweredElementType)
958 return cir::ArrayType::get(loweredElementType,
type.getSize());
961 addConversion([&](cir::DataMemberType type) -> mlir::Type {
964 return convertType(abiType);
966 addConversion([&](cir::MethodType type) -> mlir::Type {
968 return convertType(abiType);
973 addConversion([&](cir::FuncType type) -> mlir::Type {
974 llvm::SmallVector<mlir::Type> loweredInputTypes;
975 loweredInputTypes.reserve(
type.getNumInputs());
976 if (mlir::failed(convertTypes(
type.getInputs(), loweredInputTypes)))
979 mlir::Type loweredReturnType = convertType(
type.getReturnType());
980 if (!loweredReturnType)
983 return cir::FuncType::get(loweredInputTypes, loweredReturnType,
986 addConversion([&](cir::StructType type) -> mlir::Type {
987 return convertRecordType(type);
989 addConversion([&](cir::UnionType type) -> mlir::Type {
990 return convertRecordType(type);
994 void restoreRecordTypeNames() {
995 std::unique_lock<
decltype(recordTypeMutex)> lock(recordTypeMutex);
997 for (
auto rt : convertedRecordTypes)
1005 const mlir::TypeConverter &typeConverter) {
1006 target.addLegalOp<mlir::ModuleOp>();
1011 target.addDynamicallyLegalDialect<cir::CIRDialect>(
1012 [&typeConverter](mlir::Operation *op) {
1013 if (!typeConverter.isLegal(op))
1016 bool attrs = llvm::all_of(
1017 op->getAttrs(), [&typeConverter](
const mlir::NamedAttribute &a) {
1018 return isCXXABIAttributeLegal(typeConverter, a.getValue());
1022 std::all_of(op->getRegions().begin(), op->getRegions().end(),
1023 [&typeConverter](mlir::Region ®ion) {
1024 return typeConverter.isLegal(®ion);
1028 target.addDynamicallyLegalDialect<mlir::acc::OpenACCDialect>(
1029 [&typeConverter](mlir::Operation *op) {
1030 if (!typeConverter.isLegal(op))
1033 bool attrs = llvm::all_of(
1034 op->getAttrs(), [&typeConverter](
const mlir::NamedAttribute &a) {
1035 return isCXXABIAttributeLegal(typeConverter, a.getValue());
1039 std::all_of(op->getRegions().begin(), op->getRegions().end(),
1040 [&typeConverter](mlir::Region ®ion) {
1041 return typeConverter.isLegal(®ion);
1046 target.addDynamicallyLegalOp<cir::FuncOp>([&typeConverter](cir::FuncOp op) {
1047 bool attrs = llvm::all_of(
1048 op->getAttrs(), [&typeConverter](
const mlir::NamedAttribute &a) {
1049 return isCXXABIAttributeLegal(typeConverter, a.getValue());
1052 return attrs && typeConverter.isLegal(op.getFunctionType());
1054 target.addDynamicallyLegalOp<cir::GlobalOp>(
1055 [&typeConverter](cir::GlobalOp op) {
1056 return typeConverter.isLegal(op.getSymType());
1060 target.addIllegalOp<cir::DeleteArrayOp>();
1061 target.addIllegalOp<cir::DynamicCastOp>();
1062 target.addIllegalOp<cir::VTableGetTypeInfoOp>();
1069void CXXABILoweringPass::runOnOperation() {
1070 auto mod = mlir::cast<mlir::ModuleOp>(getOperation());
1071 mlir::MLIRContext *ctx = mod.getContext();
1076 mod.emitWarning(
"Cannot create a CIR lower module, skipping the ")
1081 mlir::DataLayout dataLayout(mod);
1082 CIRABITypeConverter typeConverter(*ctx, dataLayout, *lowerModule);
1084 mlir::RewritePatternSet patterns(ctx);
1085 patterns.add<CIRGenericCXXABILoweringPattern>(patterns.getContext(),
1088#define GET_ABI_LOWERING_PATTERNS_LIST
1089#include "clang/CIR/Dialect/IR/CIRLowering.inc"
1090#undef GET_ABI_LOWERING_PATTERNS_LIST
1091 >(patterns.getContext(), typeConverter, dataLayout, *lowerModule);
1093 mlir::ConversionTarget target(*ctx);
1096 llvm::SmallVector<mlir::Operation *> ops;
1100 if (failed(mlir::applyPartialConversion(ops, target, std::move(patterns))))
1101 signalPassFailure();
1103 typeConverter.restoreRecordTypeNames();
1107 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.
void readArrayCookie(mlir::Location loc, mlir::Value elementPtr, 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.
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.
CIRCXXABI & getCXXABI() const
void removeABIConversionNamePrefix()
void complete(llvm::ArrayRef< mlir::Type > members, bool packed, mlir::Type padding, llvm::ArrayRef< RecordMemberKind > memberKinds)
padding is union-only.
CharUnits - This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
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
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
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)