14#include "mlir/Dialect/OpenACC/OpenACCOpsDialect.h.inc"
15#include "mlir/Dialect/OpenMP/OpenMPOpsDialect.h.inc"
16#include "mlir/IR/PatternMatch.h"
17#include "mlir/Interfaces/DataLayoutInterfaces.h"
18#include "mlir/Pass/Pass.h"
19#include "mlir/Transforms/DialectConversion.h"
28#include "llvm/ADT/ScopeExit.h"
29#include "llvm/ADT/TypeSwitch.h"
35#define GEN_PASS_DEF_CXXABILOWERING
36#include "clang/CIR/Dialect/Passes.h.inc"
43bool isCXXABIAttributeLegal(
const mlir::TypeConverter &tc,
44 mlir::Attribute
attr) {
51 if (isa<mlir::acc::OpenACCDialect, mlir::omp::OpenMPDialect>(
57 if (
isa<mlir::DenseArrayAttr, mlir::FloatAttr, mlir::UnitAttr,
58 mlir::StringAttr, mlir::IntegerAttr, mlir::SymbolRefAttr>(
attr))
64#include
"clang/CIR/Dialect/IR/CIRLowering.inc"
70 if (isa<cir::DataMemberAttr, cir::MethodAttr>(
attr))
73 return llvm::TypeSwitch<mlir::Attribute, bool>(
attr)
76 [&tc](cir::ZeroAttr za) {
return tc.isLegal(za.getType()); })
77 .Case<cir::PoisonAttr>(
78 [&tc](cir::PoisonAttr pa) {
return tc.isLegal(pa.getType()); })
79 .Case<cir::UndefAttr>(
80 [&tc](cir::UndefAttr uda) {
return tc.isLegal(uda.getType()); })
81 .Case<mlir::TypeAttr>(
82 [&tc](mlir::TypeAttr ta) {
return tc.isLegal(ta.getValue()); })
83 .Case<cir::ConstPtrAttr>(
84 [&tc](cir::ConstPtrAttr cpa) {
return tc.isLegal(cpa.getType()); })
85 .Case<cir::CXXCtorAttr>(
86 [&tc](cir::CXXCtorAttr ca) {
return tc.isLegal(ca.getType()); })
87 .Case<cir::CXXDtorAttr>(
88 [&tc](cir::CXXDtorAttr da) {
return tc.isLegal(da.getType()); })
89 .Case<cir::CXXAssignAttr>(
90 [&tc](cir::CXXAssignAttr aa) {
return tc.isLegal(aa.getType()); })
94 .Case<mlir::ArrayAttr>([&tc](mlir::ArrayAttr array) {
95 return llvm::all_of(array.getValue(), [&tc](mlir::Attribute
attr) {
96 return isCXXABIAttributeLegal(tc, attr);
99 .Case<mlir::DictionaryAttr>([&tc](mlir::DictionaryAttr dict) {
100 return llvm::all_of(dict.getValue(), [&tc](mlir::NamedAttribute na) {
101 return isCXXABIAttributeLegal(tc, na.getValue());
105 .Case<cir::ConstArrayAttr>([&tc](cir::ConstArrayAttr array) {
106 return tc.isLegal(array.getType()) &&
107 isCXXABIAttributeLegal(tc, array.getElts());
109 .Case<cir::GlobalViewAttr>([&tc](cir::GlobalViewAttr gva) {
110 return tc.isLegal(gva.getType()) &&
111 isCXXABIAttributeLegal(tc, gva.getIndices());
113 .Case<cir::VTableAttr>([&tc](cir::VTableAttr vta) {
114 return tc.isLegal(vta.getType()) &&
115 isCXXABIAttributeLegal(tc, vta.getData());
117 .Case<cir::TypeInfoAttr>([&tc](cir::TypeInfoAttr tia) {
118 return tc.isLegal(tia.getType()) &&
119 isCXXABIAttributeLegal(tc, tia.getData());
121 .Case<cir::DynamicCastInfoAttr>([&tc](cir::DynamicCastInfoAttr dcia) {
122 return isCXXABIAttributeLegal(tc, dcia.getSrcRtti()) &&
123 isCXXABIAttributeLegal(tc, dcia.getDestRtti()) &&
124 isCXXABIAttributeLegal(tc, dcia.getRuntimeFunc()) &&
125 isCXXABIAttributeLegal(tc, dcia.getBadCastFunc());
127 .Case<cir::ConstRecordAttr>([&tc](cir::ConstRecordAttr cra) {
128 return tc.isLegal(cra.getType()) &&
129 isCXXABIAttributeLegal(tc, cra.getMembers());
140mlir::Attribute rewriteAttribute(
const mlir::TypeConverter &tc,
141 mlir::MLIRContext *ctx, mlir::Attribute attr) {
144 if (isCXXABIAttributeLegal(tc, attr))
152 return llvm::TypeSwitch<mlir::Attribute, mlir::Attribute>(attr)
154 .Case<cir::ZeroAttr>([&tc](cir::ZeroAttr za) {
155 return cir::ZeroAttr::get(tc.convertType(za.getType()));
157 .Case<cir::PoisonAttr>([&tc](cir::PoisonAttr pa) {
158 return cir::PoisonAttr::get(tc.convertType(pa.getType()));
160 .Case<cir::UndefAttr>([&tc](cir::UndefAttr uda) {
161 return cir::UndefAttr::get(tc.convertType(uda.getType()));
163 .Case<mlir::TypeAttr>([&tc](mlir::TypeAttr ta) {
164 return mlir::TypeAttr::get(tc.convertType(ta.getValue()));
166 .Case<cir::ConstPtrAttr>([&tc](cir::ConstPtrAttr cpa) {
167 return cir::ConstPtrAttr::get(tc.convertType(cpa.getType()),
170 .Case<cir::CXXCtorAttr>([&tc](cir::CXXCtorAttr ca) {
171 return cir::CXXCtorAttr::get(tc.convertType(ca.getType()),
172 ca.getCtorKind(), ca.getIsTrivial());
174 .Case<cir::CXXDtorAttr>([&tc](cir::CXXDtorAttr da) {
175 return cir::CXXDtorAttr::get(tc.convertType(da.getType()),
178 .Case<cir::CXXAssignAttr>([&tc](cir::CXXAssignAttr aa) {
179 return cir::CXXAssignAttr::get(tc.convertType(aa.getType()),
180 aa.getAssignKind(), aa.getIsTrivial());
184 .Case<mlir::ArrayAttr>([&tc, ctx](mlir::ArrayAttr array) {
186 for (mlir::Attribute a : array.getValue())
187 elts.push_back(rewriteAttribute(tc, ctx, a));
188 return mlir::ArrayAttr::get(ctx, elts);
190 .Case<mlir::DictionaryAttr>([&tc, ctx](mlir::DictionaryAttr dict) {
192 for (mlir::NamedAttribute na : dict.getValue())
193 elts.emplace_back(na.getName(),
194 rewriteAttribute(tc, ctx, na.getValue()));
196 return mlir::DictionaryAttr::get(ctx, elts);
199 .Case<cir::ConstArrayAttr>([&tc, ctx](cir::ConstArrayAttr array) {
200 return cir::ConstArrayAttr::get(
201 ctx, tc.convertType(array.getType()),
202 rewriteAttribute(tc, ctx, array.getElts()),
203 array.getTrailingZerosNum());
205 .Case<cir::GlobalViewAttr>([&tc, ctx](cir::GlobalViewAttr gva) {
206 return cir::GlobalViewAttr::get(
207 tc.convertType(gva.getType()), gva.getSymbol(),
208 mlir::cast<mlir::ArrayAttr>(
209 rewriteAttribute(tc, ctx, gva.getIndices())));
211 .Case<cir::VTableAttr>([&tc, ctx](cir::VTableAttr vta) {
212 return cir::VTableAttr::get(
213 tc.convertType(vta.getType()),
214 mlir::cast<mlir::ArrayAttr>(
215 rewriteAttribute(tc, ctx, vta.getData())));
217 .Case<cir::TypeInfoAttr>([&tc, ctx](cir::TypeInfoAttr tia) {
218 return cir::TypeInfoAttr::get(
219 tc.convertType(tia.getType()),
220 mlir::cast<mlir::ArrayAttr>(
221 rewriteAttribute(tc, ctx, tia.getData())));
223 .Case<cir::DynamicCastInfoAttr>([&tc,
224 ctx](cir::DynamicCastInfoAttr dcia) {
225 return cir::DynamicCastInfoAttr::get(
226 mlir::cast<cir::GlobalViewAttr>(
227 rewriteAttribute(tc, ctx, dcia.getSrcRtti())),
228 mlir::cast<cir::GlobalViewAttr>(
229 rewriteAttribute(tc, ctx, dcia.getDestRtti())),
230 dcia.getRuntimeFunc(), dcia.getBadCastFunc(), dcia.getOffsetHint());
232 .Case<cir::ConstRecordAttr>([&tc, ctx](cir::ConstRecordAttr cra) {
233 return cir::ConstRecordAttr::get(
234 ctx, tc.convertType(cra.getType()),
235 mlir::cast<mlir::ArrayAttr>(
236 rewriteAttribute(tc, ctx, cra.getMembers())));
238 .DefaultUnreachable(
"unrewritten illegal attribute kind");
241#define GET_ABI_LOWERING_PATTERNS
242#include "clang/CIR/Dialect/IR/CIRLowering.inc"
243#undef GET_ABI_LOWERING_PATTERNS
245struct CXXABILoweringPass
246 :
public impl::CXXABILoweringBase<CXXABILoweringPass> {
247 CXXABILoweringPass() =
default;
248 void runOnOperation()
override;
256class CIRGenericCXXABILoweringPattern :
public mlir::ConversionPattern {
258 CIRGenericCXXABILoweringPattern(mlir::MLIRContext *context,
259 const mlir::TypeConverter &typeConverter)
260 : mlir::ConversionPattern(typeConverter, MatchAnyOpTypeTag(),
264 matchAndRewrite(mlir::Operation *op, llvm::ArrayRef<mlir::Value> operands,
265 mlir::ConversionPatternRewriter &rewriter)
const override {
267 if (llvm::isa<cir::AllocaOp, cir::BaseDataMemberOp, cir::BaseMethodOp,
268 cir::CastOp, cir::CmpOp, cir::ConstantOp, cir::DeleteArrayOp,
269 cir::DerivedDataMemberOp, cir::DerivedMethodOp, cir::FuncOp,
270 cir::GetMethodOp, cir::GetRuntimeMemberOp, cir::GlobalOp>(op))
271 return mlir::failure();
273 const mlir::TypeConverter *typeConverter = getTypeConverter();
274 assert(typeConverter &&
275 "CIRGenericCXXABILoweringPattern requires a type converter");
276 bool operandsAndResultsLegal = typeConverter->isLegal(op);
278 std::all_of(op->getRegions().begin(), op->getRegions().end(),
279 [typeConverter](mlir::Region ®ion) {
280 return typeConverter->isLegal(®ion);
283 llvm::all_of(op->getAttrs(), [typeConverter](mlir::NamedAttribute na) {
284 return isCXXABIAttributeLegal(*typeConverter, na.getValue());
287 if (operandsAndResultsLegal && regionsLegal && attrsLegal) {
290 return mlir::failure();
293 mlir::OperationState loweredOpState(op->getLoc(), op->getName());
294 loweredOpState.addOperands(operands);
295 loweredOpState.addSuccessors(op->getSuccessors());
298 llvm::SmallVector<mlir::NamedAttribute> attrs;
299 for (
const mlir::NamedAttribute &na : op->getAttrs())
302 rewriteAttribute(*typeConverter, op->getContext(), na.getValue())});
303 loweredOpState.addAttributes(attrs);
306 llvm::SmallVector<mlir::Type> loweredResultTypes;
307 loweredResultTypes.reserve(op->getNumResults());
308 for (mlir::Type result : op->getResultTypes())
309 loweredResultTypes.push_back(typeConverter->convertType(result));
310 loweredOpState.addTypes(loweredResultTypes);
313 for (mlir::Region ®ion : op->getRegions()) {
314 mlir::Region *loweredRegion = loweredOpState.addRegion();
315 rewriter.inlineRegionBefore(region, *loweredRegion, loweredRegion->end());
317 rewriter.convertRegionTypes(loweredRegion, *getTypeConverter())))
318 return mlir::failure();
322 mlir::Operation *loweredOp = rewriter.create(loweredOpState);
324 rewriter.replaceOp(op, loweredOp);
325 return mlir::success();
331mlir::LogicalResult CIRAllocaOpABILowering::matchAndRewrite(
332 cir::AllocaOp op, OpAdaptor adaptor,
333 mlir::ConversionPatternRewriter &rewriter)
const {
334 mlir::Type allocaPtrTy = op.getType();
335 mlir::Type allocaTy = op.getAllocaType();
336 mlir::Type loweredAllocaPtrTy = getTypeConverter()->convertType(allocaPtrTy);
337 mlir::Type loweredAllocaTy = getTypeConverter()->convertType(allocaTy);
339 cir::AllocaOp loweredOp = cir::AllocaOp::create(
340 rewriter, op.getLoc(), loweredAllocaPtrTy, loweredAllocaTy, op.getName(),
341 op.getAlignmentAttr(), adaptor.getDynAllocSize());
342 loweredOp.setInit(op.getInit());
343 loweredOp.setConstant(op.getConstant());
344 loweredOp.setAnnotationsAttr(op.getAnnotationsAttr());
346 rewriter.replaceOp(op, loweredOp);
347 return mlir::success();
350mlir::LogicalResult CIRCastOpABILowering::matchAndRewrite(
351 cir::CastOp op, OpAdaptor adaptor,
352 mlir::ConversionPatternRewriter &rewriter)
const {
353 mlir::Type srcTy = op.getSrc().getType();
355 if (mlir::isa<cir::DataMemberType, cir::MethodType>(srcTy)) {
356 switch (op.getKind()) {
357 case cir::CastKind::bitcast: {
358 mlir::Type destTy = getTypeConverter()->convertType(op.getType());
359 mlir::Value loweredResult;
360 if (mlir::isa<cir::DataMemberType>(srcTy))
361 loweredResult = lowerModule->getCXXABI().lowerDataMemberBitcast(
362 op, destTy, adaptor.getSrc(), rewriter);
364 loweredResult = lowerModule->getCXXABI().lowerMethodBitcast(
365 op, destTy, adaptor.getSrc(), rewriter);
366 rewriter.replaceOp(op, loweredResult);
367 return mlir::success();
369 case cir::CastKind::member_ptr_to_bool: {
370 mlir::Value loweredResult;
371 if (mlir::isa<cir::DataMemberType>(srcTy))
372 loweredResult = lowerModule->getCXXABI().lowerDataMemberToBoolCast(
373 op, adaptor.getSrc(), rewriter);
375 loweredResult = lowerModule->getCXXABI().lowerMethodToBoolCast(
376 op, adaptor.getSrc(), rewriter);
377 rewriter.replaceOp(op, loweredResult);
378 return mlir::success();
385 mlir::Value loweredResult = cir::CastOp::create(
386 rewriter, op.getLoc(), getTypeConverter()->convertType(op.getType()),
387 adaptor.getKind(), adaptor.getSrc());
388 rewriter.replaceOp(op, loweredResult);
389 return mlir::success();
394 const mlir::DataLayout &layout,
395 const mlir::TypeConverter &tc,
397 mlir::Attribute initVal) {
398 if (mlir::isa<cir::DataMemberType>(ty)) {
399 auto dataMemberVal = mlir::cast_if_present<cir::DataMemberAttr>(initVal);
403 if (mlir::isa<cir::MethodType>(ty)) {
404 auto methodVal = mlir::cast_if_present<cir::MethodAttr>(initVal);
408 if (
auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty)) {
409 auto loweredArrTy = mlir::cast<cir::ArrayType>(tc.convertType(arrTy));
414 if (
auto zeroVal = mlir::dyn_cast_if_present<cir::ZeroAttr>(initVal))
415 return cir::ZeroAttr::get(loweredArrTy);
417 auto arrayVal = mlir::cast<cir::ConstArrayAttr>(initVal);
418 auto arrayElts = mlir::cast<ArrayAttr>(arrayVal.getElts());
420 loweredElements.reserve(arrTy.getSize());
421 for (
const mlir::Attribute &attr : arrayElts) {
422 auto typedAttr = cast<mlir::TypedAttr>(attr);
424 lowerModule, layout, tc, typedAttr.getType(), typedAttr));
427 return cir::ConstArrayAttr::get(
428 loweredArrTy, mlir::ArrayAttr::get(ty.getContext(), loweredElements),
429 arrayVal.getTrailingZerosNum());
432 if (
auto recordTy = mlir::dyn_cast<cir::RecordType>(ty)) {
433 auto convertedTy = mlir::cast<cir::RecordType>(tc.convertType(recordTy));
435 if (
auto recVal = mlir::dyn_cast_if_present<cir::ZeroAttr>(initVal))
436 return cir::ZeroAttr::get(convertedTy);
438 if (
auto undefVal = mlir::dyn_cast_if_present<cir::UndefAttr>(initVal))
439 return cir::UndefAttr::get(convertedTy);
443 if (
auto poisonVal = mlir::dyn_cast_if_present<cir::PoisonAttr>(initVal))
444 return cir::PoisonAttr::get(convertedTy);
447 mlir::dyn_cast_if_present<cir::ConstRecordAttr>(initVal)) {
448 auto recordMembers = mlir::cast<ArrayAttr>(recVal.getMembers());
451 loweredMembers.reserve(recordMembers.size());
453 for (
const mlir::Attribute &attr : recordMembers) {
454 auto typedAttr = cast<mlir::TypedAttr>(attr);
456 lowerModule, layout, tc, typedAttr.getType(), typedAttr));
459 return cir::ConstRecordAttr::get(
460 convertedTy, mlir::ArrayAttr::get(ty.getContext(), loweredMembers));
463 assert(!initVal &&
"Record init val type not handled");
468 if (
auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty)) {
469 auto convertedTy = mlir::cast<cir::PointerType>(tc.convertType(ptrTy));
472 if (
auto gva = mlir::dyn_cast_if_present<cir::GlobalViewAttr>(initVal))
473 return cir::GlobalViewAttr::get(convertedTy, gva.getSymbol(),
476 auto constPtr = mlir::cast_if_present<cir::ConstPtrAttr>(initVal);
479 return cir::ConstPtrAttr::get(convertedTy, constPtr.getValue());
482 assert(ty == tc.convertType(ty) &&
483 "cir.global or constant operand is not an CXXABI-dependent type");
486 return cast<mlir::TypedAttr>(initVal);
489mlir::LogicalResult CIRConstantOpABILowering::matchAndRewrite(
490 cir::ConstantOp op, OpAdaptor adaptor,
491 mlir::ConversionPatternRewriter &rewriter)
const {
493 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
495 lowerModule, layout, *getTypeConverter(), op.getType(), op.getValue());
496 rewriter.replaceOpWithNewOp<ConstantOp>(op, newValue);
497 return mlir::success();
500mlir::LogicalResult CIRCmpOpABILowering::matchAndRewrite(
501 cir::CmpOp op, OpAdaptor adaptor,
502 mlir::ConversionPatternRewriter &rewriter)
const {
503 mlir::Type type = op.getLhs().getType();
505 mlir::Value loweredResult;
506 if (mlir::isa<cir::DataMemberType>(type))
507 loweredResult = lowerModule->getCXXABI().lowerDataMemberCmp(
508 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
509 else if (mlir::isa<cir::MethodType>(type))
510 loweredResult = lowerModule->getCXXABI().lowerMethodCmp(
511 op, adaptor.getLhs(), adaptor.getRhs(), rewriter);
513 loweredResult = cir::CmpOp::create(
514 rewriter, op.getLoc(), getTypeConverter()->convertType(op.getType()),
515 adaptor.getKind(), adaptor.getLhs(), adaptor.getRhs());
517 rewriter.replaceOp(op, loweredResult);
518 return mlir::success();
521mlir::LogicalResult CIRFuncOpABILowering::matchAndRewrite(
522 cir::FuncOp op, OpAdaptor adaptor,
523 mlir::ConversionPatternRewriter &rewriter)
const {
524 cir::FuncType opFuncType = op.getFunctionType();
525 mlir::TypeConverter::SignatureConversion signatureConversion(
526 opFuncType.getNumInputs());
528 for (
const auto &[i, argType] : llvm::enumerate(opFuncType.getInputs())) {
529 mlir::Type loweredArgType = getTypeConverter()->convertType(argType);
531 return mlir::failure();
532 signatureConversion.addInputs(i, loweredArgType);
535 mlir::Type loweredResultType =
536 getTypeConverter()->convertType(opFuncType.getReturnType());
537 if (!loweredResultType)
538 return mlir::failure();
540 auto loweredFuncType =
541 cir::FuncType::get(signatureConversion.getConvertedTypes(),
542 loweredResultType, opFuncType.isVarArg());
545 cir::FuncOp loweredFuncOp = rewriter.cloneWithoutRegions(op);
546 loweredFuncOp.setFunctionType(loweredFuncType);
549 for (
const mlir::NamedAttribute &na : op->getAttrs())
551 {na.getName(), rewriteAttribute(*getTypeConverter(), op->getContext(),
554 loweredFuncOp->setAttrs(attrs);
556 rewriter.inlineRegionBefore(op.getBody(), loweredFuncOp.getBody(),
557 loweredFuncOp.end());
558 if (mlir::failed(rewriter.convertRegionTypes(
559 &loweredFuncOp.getBody(), *getTypeConverter(), &signatureConversion)))
560 return mlir::failure();
562 rewriter.eraseOp(op);
563 return mlir::success();
566mlir::LogicalResult CIRGlobalOpABILowering::matchAndRewrite(
567 cir::GlobalOp op, OpAdaptor adaptor,
568 mlir::ConversionPatternRewriter &rewriter)
const {
569 mlir::Type ty = op.getSymType();
570 mlir::Type loweredTy = getTypeConverter()->convertType(ty);
572 return mlir::failure();
574 mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
577 lowerModule, layout, *getTypeConverter(), ty, op.getInitialValueAttr());
579 auto newOp = mlir::cast<cir::GlobalOp>(rewriter.clone(*op.getOperation()));
580 newOp.setInitialValueAttr(loweredInit);
581 newOp.setSymType(loweredTy);
582 rewriter.replaceOp(op, newOp);
583 return mlir::success();
586mlir::LogicalResult CIRBaseDataMemberOpABILowering::matchAndRewrite(
587 cir::BaseDataMemberOp op, OpAdaptor adaptor,
588 mlir::ConversionPatternRewriter &rewriter)
const {
589 mlir::Value loweredResult = lowerModule->getCXXABI().lowerBaseDataMember(
590 op, adaptor.getSrc(), rewriter);
591 rewriter.replaceOp(op, loweredResult);
592 return mlir::success();
595mlir::LogicalResult CIRBaseMethodOpABILowering::matchAndRewrite(
596 cir::BaseMethodOp op, OpAdaptor adaptor,
597 mlir::ConversionPatternRewriter &rewriter)
const {
598 mlir::Value loweredResult =
599 lowerModule->getCXXABI().lowerBaseMethod(op, adaptor.getSrc(), rewriter);
600 rewriter.replaceOp(op, loweredResult);
601 return mlir::success();
604mlir::LogicalResult CIRDeleteArrayOpABILowering::matchAndRewrite(
605 cir::DeleteArrayOp op, OpAdaptor adaptor,
606 mlir::ConversionPatternRewriter &rewriter)
const {
607 mlir::FlatSymbolRefAttr deleteFn = op.getDeleteFnAttr();
608 mlir::Location loc = op->getLoc();
609 mlir::Value loweredAddress = adaptor.getAddress();
611 cir::UsualDeleteParamsAttr deleteParams = op.getDeleteParams();
612 bool cookieRequired = deleteParams.getSize();
613 assert((deleteParams.getSize() || !op.getElementDtorAttr()) &&
614 "Expected size parameter when dtor fn is provided!");
616 if (deleteParams.getTypeAwareDelete() || deleteParams.getDestroyingDelete() ||
617 deleteParams.getAlignment())
618 return rewriter.notifyMatchFailure(
619 op,
"type-aware, destroying, or aligned delete not yet supported");
621 const CIRCXXABI &cxxABI = lowerModule->getCXXABI();
623 mlir::Value deletePtr;
626 if (cookieRequired) {
627 mlir::Value numElements;
629 auto ptrTy = mlir::cast<cir::PointerType>(loweredAddress.getType());
630 mlir::DataLayout dl(op->getParentOfType<mlir::ModuleOp>());
632 cxxABI.
readArrayCookie(loc, loweredAddress, dl, cirBuilder, numElements,
633 deletePtr, cookieSize);
637 mlir::FlatSymbolRefAttr dtorFn = op.getElementDtorAttr();
639 auto eltPtrTy = cir::PointerType::get(ptrTy.getPointee());
640 cir::ArrayDtor::create(
641 rewriter, loc, loweredAddress, numElements,
642 [&](mlir::OpBuilder &
b, mlir::Location l) {
643 auto arg =
b.getInsertionBlock()->addArgument(eltPtrTy, l);
644 cir::CallOp::create(
b, l, dtorFn, cir::VoidType(),
645 mlir::ValueRange{
arg});
646 cir::YieldOp::create(
b, l);
652 uint64_t eltSizeBytes = dl.getTypeSizeInBits(ptrTy.getPointee()) / 8;
655 cir::IntType sizeTy = cirBuilder.getUIntNTy(ptrWidth);
657 mlir::Value eltSizeVal = cir::ConstantOp::create(
658 rewriter, loc, cir::IntAttr::get(sizeTy, eltSizeBytes));
659 mlir::Value allocSize =
660 cir::MulOp::create(rewriter, loc, sizeTy, eltSizeVal, numElements);
661 mlir::Value cookieSizeVal = cir::ConstantOp::create(
662 rewriter, loc, cir::IntAttr::get(sizeTy, cookieSize.
getQuantity()));
664 cir::AddOp::create(rewriter, loc, sizeTy, allocSize, cookieSizeVal);
667 deletePtr = cir::CastOp::create(rewriter, loc, cirBuilder.getVoidPtrTy(),
668 cir::CastKind::bitcast, loweredAddress);
672 cir::CallOp::create(rewriter, loc, deleteFn, cir::VoidType(), callArgs);
673 rewriter.eraseOp(op);
674 return mlir::success();
677mlir::LogicalResult CIRDerivedDataMemberOpABILowering::matchAndRewrite(
678 cir::DerivedDataMemberOp op, OpAdaptor adaptor,
679 mlir::ConversionPatternRewriter &rewriter)
const {
680 mlir::Value loweredResult = lowerModule->getCXXABI().lowerDerivedDataMember(
681 op, adaptor.getSrc(), rewriter);
682 rewriter.replaceOp(op, loweredResult);
683 return mlir::success();
686mlir::LogicalResult CIRDerivedMethodOpABILowering::matchAndRewrite(
687 cir::DerivedMethodOp op, OpAdaptor adaptor,
688 mlir::ConversionPatternRewriter &rewriter)
const {
689 mlir::Value loweredResult = lowerModule->getCXXABI().lowerDerivedMethod(
690 op, adaptor.getSrc(), rewriter);
691 rewriter.replaceOp(op, loweredResult);
692 return mlir::success();
695mlir::LogicalResult CIRDynamicCastOpABILowering::matchAndRewrite(
696 cir::DynamicCastOp op, OpAdaptor adaptor,
697 mlir::ConversionPatternRewriter &rewriter)
const {
698 mlir::Value loweredResult =
699 lowerModule->getCXXABI().lowerDynamicCast(op, rewriter);
700 rewriter.replaceOp(op, loweredResult);
701 return mlir::success();
704mlir::LogicalResult CIRGetMethodOpABILowering::matchAndRewrite(
705 cir::GetMethodOp op, OpAdaptor adaptor,
706 mlir::ConversionPatternRewriter &rewriter)
const {
709 lowerModule->getCXXABI().lowerGetMethod(
710 op, callee, thisArg, adaptor.getMethod(), adaptor.getObject(), rewriter);
711 rewriter.replaceOp(op, {callee, thisArg});
712 return mlir::success();
715mlir::LogicalResult CIRGetRuntimeMemberOpABILowering::matchAndRewrite(
716 cir::GetRuntimeMemberOp op, OpAdaptor adaptor,
717 mlir::ConversionPatternRewriter &rewriter)
const {
718 mlir::Type resTy = getTypeConverter()->convertType(op.getType());
719 mlir::Operation *newOp = lowerModule->getCXXABI().lowerGetRuntimeMember(
720 op, resTy, adaptor.getAddr(), adaptor.getMember(), rewriter);
721 rewriter.replaceOp(op, newOp);
722 return mlir::success();
725mlir::LogicalResult CIRVTableGetTypeInfoOpABILowering::matchAndRewrite(
726 cir::VTableGetTypeInfoOp op, OpAdaptor adaptor,
727 mlir::ConversionPatternRewriter &rewriter)
const {
728 mlir::Value loweredResult =
729 lowerModule->getCXXABI().lowerVTableGetTypeInfo(op, rewriter);
730 rewriter.replaceOp(op, loweredResult);
731 return mlir::success();
739class CIRABITypeConverter :
public mlir::TypeConverter {
741 mlir::MLIRContext &context;
746 DenseMap<uint64_t, std::unique_ptr<SmallVector<cir::RecordType>>>
748 llvm::sys::SmartRWMutex<true> callStackMutex;
753 llvm::SmallVector<cir::RecordType> convertedRecordTypes;
754 llvm::sys::SmartRWMutex<true> recordTypeMutex;
760 SmallVector<cir::RecordType> &getCurrentThreadRecursiveStack() {
763 std::shared_lock<
decltype(callStackMutex)> lock(callStackMutex,
765 if (context.isMultithreadingEnabled())
767 auto recursiveStack = conversionCallStack.find(llvm::get_threadid());
768 if (recursiveStack != conversionCallStack.end())
769 return *recursiveStack->second;
774 std::unique_lock<
decltype(callStackMutex)> lock(callStackMutex);
775 auto recursiveStackInserted = conversionCallStack.insert(
776 std::make_pair(llvm::get_threadid(),
777 std::make_unique<SmallVector<cir::RecordType>>()));
778 return *recursiveStackInserted.first->second;
781 void addConvertedRecordType(cir::RecordType rt) {
782 std::unique_lock<
decltype(recordTypeMutex)> lock(recordTypeMutex);
783 convertedRecordTypes.push_back(rt);
786 llvm::SmallVector<mlir::Type> convertRecordMemberTypes(cir::RecordType type) {
787 llvm::SmallVector<mlir::Type> loweredMemberTypes;
788 loweredMemberTypes.reserve(
type.getNumElements());
790 if (mlir::failed(convertTypes(
type.getMembers(), loweredMemberTypes)))
793 return loweredMemberTypes;
796 cir::RecordType convertRecordType(cir::RecordType type) {
801 return cir::RecordType::get(
802 type.getContext(), convertRecordMemberTypes(type),
type.getPacked(),
805 assert(!
type.isIncomplete() ||
type.getMembers().empty());
810 if (
type.isIncomplete() ||
type.isABIConvertedRecord())
813 SmallVectorImpl<cir::RecordType> &recursiveStack =
814 getCurrentThreadRecursiveStack();
816 auto convertedType = cir::RecordType::get(
817 type.getContext(),
type.getABIConvertedName(),
type.getKind());
820 if (convertedType.isComplete())
821 return convertedType;
827 if (llvm::is_contained(recursiveStack, type))
828 return convertedType;
830 recursiveStack.push_back(type);
831 llvm::scope_exit popConvertingType(
832 [&recursiveStack]() { recursiveStack.pop_back(); });
834 SmallVector<mlir::Type> convertedMembers = convertRecordMemberTypes(type);
836 convertedType.complete(convertedMembers,
type.getPacked(),
838 addConvertedRecordType(convertedType);
839 return convertedType;
843 CIRABITypeConverter(mlir::MLIRContext &ctx, mlir::DataLayout &dataLayout,
844 cir::LowerModule &lowerModule)
846 addConversion([&](mlir::Type type) -> mlir::Type {
return type; });
849 addConversion([&](cir::PointerType type) -> mlir::Type {
850 mlir::Type loweredPointeeType = convertType(
type.getPointee());
851 if (!loweredPointeeType)
853 return cir::PointerType::get(
type.getContext(), loweredPointeeType,
854 type.getAddrSpace());
856 addConversion([&](cir::ArrayType type) -> mlir::Type {
857 mlir::Type loweredElementType = convertType(
type.getElementType());
858 if (!loweredElementType)
860 return cir::ArrayType::get(loweredElementType,
type.getSize());
863 addConversion([&](cir::DataMemberType type) -> mlir::Type {
866 return convertType(abiType);
868 addConversion([&](cir::MethodType type) -> mlir::Type {
870 return convertType(abiType);
875 addConversion([&](cir::FuncType type) -> mlir::Type {
876 llvm::SmallVector<mlir::Type> loweredInputTypes;
877 loweredInputTypes.reserve(
type.getNumInputs());
878 if (mlir::failed(convertTypes(
type.getInputs(), loweredInputTypes)))
881 mlir::Type loweredReturnType = convertType(
type.getReturnType());
882 if (!loweredReturnType)
885 return cir::FuncType::get(loweredInputTypes, loweredReturnType,
888 addConversion([&](cir::RecordType type) -> mlir::Type {
889 return convertRecordType(type);
893 void restoreRecordTypeNames() {
894 std::unique_lock<
decltype(recordTypeMutex)> lock(recordTypeMutex);
896 for (
auto rt : convertedRecordTypes)
897 rt.removeABIConversionNamePrefix();
904 const mlir::TypeConverter &typeConverter) {
905 target.addLegalOp<mlir::ModuleOp>();
910 target.addDynamicallyLegalDialect<cir::CIRDialect>(
911 [&typeConverter](mlir::Operation *op) {
912 if (!typeConverter.isLegal(op))
915 bool attrs = llvm::all_of(
916 op->getAttrs(), [&typeConverter](
const mlir::NamedAttribute &a) {
917 return isCXXABIAttributeLegal(typeConverter, a.getValue());
921 std::all_of(op->getRegions().begin(), op->getRegions().end(),
922 [&typeConverter](mlir::Region ®ion) {
923 return typeConverter.isLegal(®ion);
927 target.addDynamicallyLegalDialect<mlir::acc::OpenACCDialect>(
928 [&typeConverter](mlir::Operation *op) {
929 if (!typeConverter.isLegal(op))
932 bool attrs = llvm::all_of(
933 op->getAttrs(), [&typeConverter](
const mlir::NamedAttribute &a) {
934 return isCXXABIAttributeLegal(typeConverter, a.getValue());
938 std::all_of(op->getRegions().begin(), op->getRegions().end(),
939 [&typeConverter](mlir::Region ®ion) {
940 return typeConverter.isLegal(®ion);
945 target.addDynamicallyLegalOp<cir::FuncOp>([&typeConverter](cir::FuncOp op) {
946 bool attrs = llvm::all_of(
947 op->getAttrs(), [&typeConverter](
const mlir::NamedAttribute &a) {
948 return isCXXABIAttributeLegal(typeConverter, a.getValue());
951 return attrs && typeConverter.isLegal(op.getFunctionType());
953 target.addDynamicallyLegalOp<cir::GlobalOp>(
954 [&typeConverter](cir::GlobalOp op) {
955 return typeConverter.isLegal(op.getSymType());
959 target.addIllegalOp<cir::DeleteArrayOp>();
960 target.addIllegalOp<cir::DynamicCastOp>();
961 target.addIllegalOp<cir::VTableGetTypeInfoOp>();
1003 parent->walk([&](mlir::Block *blk) {
1004 if (blk->hasNoPredecessors() && !blk->isEntryBlock())
1005 unreachableBlocks.push_back(blk);
1008 std::set<mlir::Block *> visited;
1009 for (mlir::Block *root : unreachableBlocks) {
1012 std::deque<mlir::Block *> workList;
1013 workList.push_back(root);
1015 while (!workList.empty()) {
1016 mlir::Block *blk = workList.back();
1017 workList.pop_back();
1018 if (visited.count(blk))
1020 visited.emplace(blk);
1022 for (mlir::Operation &op : *blk)
1025 for (mlir::Block *succ : blk->getSuccessors())
1026 workList.push_back(succ);
1031void CXXABILoweringPass::runOnOperation() {
1032 auto mod = mlir::cast<mlir::ModuleOp>(getOperation());
1033 mlir::MLIRContext *ctx = mod.getContext();
1038 mod.emitWarning(
"Cannot create a CIR lower module, skipping the ")
1043 mlir::DataLayout dataLayout(mod);
1044 CIRABITypeConverter typeConverter(*ctx, dataLayout, *lowerModule);
1046 mlir::RewritePatternSet patterns(ctx);
1047 patterns.add<CIRGenericCXXABILoweringPattern>(patterns.getContext(),
1050#define GET_ABI_LOWERING_PATTERNS_LIST
1051#include "clang/CIR/Dialect/IR/CIRLowering.inc"
1052#undef GET_ABI_LOWERING_PATTERNS_LIST
1053 >(patterns.getContext(), typeConverter, dataLayout, *lowerModule);
1055 mlir::ConversionTarget target(*ctx);
1058 llvm::SmallVector<mlir::Operation *> ops;
1062 if (failed(mlir::applyPartialConversion(ops, target, std::move(patterns))))
1063 signalPassFailure();
1065 typeConverter.restoreRecordTypeNames();
1069 return std::make_unique<CXXABILoweringPass>();
#define CXX_ABI_ALWAYS_LEGAL_ATTRS
static void collectUnreachable(mlir::Operation *parent, llvm::SmallVector< mlir::Operation * > &ops)
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 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
CharUnits - This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
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)
std::unique_ptr< Pass > createCXXABILoweringPass()
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)