25#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
26#include "mlir/IR/ImplicitLocOpBuilder.h"
27#include "llvm/Support/ErrorHandling.h"
33class LowerItaniumCXXABI :
public CIRCXXABI {
35 bool useARMMethodPtrABI;
36 bool use32BitVTableOffsetABI;
39 LowerItaniumCXXABI(LowerModule &lm,
bool useARMMethodPtrABI =
false,
40 bool use32BitVTableOffsetABI =
false)
41 : CIRCXXABI(lm), useARMMethodPtrABI(useARMMethodPtrABI),
42 use32BitVTableOffsetABI(use32BitVTableOffsetABI) {}
47 lowerDataMemberType(cir::DataMemberType type,
48 const mlir::TypeConverter &typeConverter)
const override;
51 lowerMethodType(cir::MethodType type,
52 const mlir::TypeConverter &typeConverter)
const override;
54 mlir::TypedAttr lowerDataMemberConstant(
55 cir::DataMemberAttr attr,
const mlir::DataLayout &layout,
56 const mlir::TypeConverter &typeConverter)
const override;
58 mlir::TypedAttr lowerDataMemberOffsetConstant(
59 cir::DataMemberOffsetAttr attr,
const mlir::DataLayout &layout,
60 const mlir::TypeConverter &typeConverter)
const override;
63 lowerMethodConstant(cir::MethodAttr attr,
const mlir::DataLayout &layout,
64 const mlir::TypeConverter &typeConverter)
const override;
67 lowerGetRuntimeMember(cir::GetRuntimeMemberOp op, mlir::Type loweredResultTy,
68 mlir::Value loweredAddr, mlir::Value loweredMember,
69 mlir::OpBuilder &builder)
const override;
71 void lowerGetMethod(cir::GetMethodOp op, mlir::Value &callee,
72 mlir::Value &thisArg, mlir::Value loweredMethod,
73 mlir::Value loweredObjectPtr,
74 mlir::ConversionPatternRewriter &rewriter)
const override;
76 mlir::Value lowerBaseDataMember(cir::BaseDataMemberOp op,
77 mlir::Value loweredSrc,
78 mlir::OpBuilder &builder)
const override;
80 mlir::Value lowerDerivedDataMember(cir::DerivedDataMemberOp op,
81 mlir::Value loweredSrc,
82 mlir::OpBuilder &builder)
const override;
84 mlir::Value lowerBaseMethod(cir::BaseMethodOp op, mlir::Value loweredSrc,
85 mlir::OpBuilder &builder)
const override;
87 mlir::Value lowerDerivedMethod(cir::DerivedMethodOp op,
88 mlir::Value loweredSrc,
89 mlir::OpBuilder &builder)
const override;
91 mlir::Value lowerDataMemberCmp(cir::CmpOp op, mlir::Value loweredLhs,
92 mlir::Value loweredRhs,
93 mlir::OpBuilder &builder)
const override;
95 mlir::Value lowerMethodCmp(cir::CmpOp op, mlir::Value loweredLhs,
96 mlir::Value loweredRhs,
97 mlir::OpBuilder &builder)
const override;
99 mlir::Value lowerDataMemberBitcast(cir::CastOp op, mlir::Type loweredDstTy,
100 mlir::Value loweredSrc,
101 mlir::OpBuilder &builder)
const override;
104 lowerDataMemberToBoolCast(cir::CastOp op, mlir::Value loweredSrc,
105 mlir::OpBuilder &builder)
const override;
107 mlir::Value lowerMethodBitcast(cir::CastOp op, mlir::Type loweredDstTy,
108 mlir::Value loweredSrc,
109 mlir::OpBuilder &builder)
const override;
111 mlir::Value lowerMethodToBoolCast(cir::CastOp op, mlir::Value loweredSrc,
112 mlir::OpBuilder &builder)
const override;
114 mlir::Value lowerDynamicCast(cir::DynamicCastOp op,
115 mlir::OpBuilder &builder)
const override;
116 mlir::Value lowerVTableGetTypeInfo(cir::VTableGetTypeInfoOp op,
117 mlir::OpBuilder &builder)
const override;
120 getArrayCookieSizeImpl(clang::CharUnits elementAlign)
const override;
122 mlir::Value readArrayCookieImpl(mlir::Location loc, mlir::Value allocPtr,
123 clang::CharUnits cookieSize,
124 clang::CharUnits cookieAlignment,
125 const mlir::DataLayout &dataLayout,
126 CIRBaseBuilderTy &builder)
const override;
136 case clang::TargetCXXABI::GenericAArch64:
137 return std::make_unique<LowerItaniumCXXABI>(
141 case clang::TargetCXXABI::AppleARM64:
145 return std::make_unique<LowerItaniumCXXABI>(
150 case clang::TargetCXXABI::GenericItanium:
151 return std::make_unique<LowerItaniumCXXABI>(lm);
153 case clang::TargetCXXABI::GenericARM:
154 case clang::TargetCXXABI::iOS:
155 case clang::TargetCXXABI::WatchOS:
156 case clang::TargetCXXABI::Fuchsia:
157 case clang::TargetCXXABI::GenericMIPS:
158 case clang::TargetCXXABI::WebAssembly:
159 case clang::TargetCXXABI::XL:
164 case clang::TargetCXXABI::Microsoft:
165 llvm_unreachable(
"Microsoft ABI is not Itanium-based");
167 llvm_unreachable(
"bad ABI kind");
178mlir::Type LowerItaniumCXXABI::lowerDataMemberType(
179 cir::DataMemberType type,
const mlir::TypeConverter &typeConverter)
const {
183 return getPtrDiffCIRTy(lm);
186mlir::Type LowerItaniumCXXABI::lowerMethodType(
187 cir::MethodType type,
const mlir::TypeConverter &typeConverter)
const {
202 mlir::Type members[] = {ptrdiffCIRTy, ptrdiffCIRTy};
203 return cir::StructType::get(
type.getContext(), members,
false,
208mlir::TypedAttr LowerItaniumCXXABI::lowerDataMemberConstant(
209 cir::DataMemberAttr attr,
const mlir::DataLayout &layout,
210 const mlir::TypeConverter &typeConverter)
const {
212 if (
attr.isNullPtr()) {
222 mlir::Type currentTy =
attr.getType().getClassTy();
224 auto recTy = mlir::cast<cir::RecordType>(currentTy);
225 memberOffset +=
static_cast<int64_t>(recTy.getElementOffset(layout, idx));
226 currentTy = recTy.getMembers()[idx];
230 mlir::Type abiTy = lowerDataMemberType(
attr.getType(), typeConverter);
231 return cir::IntAttr::get(abiTy, memberOffset);
234mlir::TypedAttr LowerItaniumCXXABI::lowerDataMemberOffsetConstant(
235 cir::DataMemberOffsetAttr attr,
const mlir::DataLayout &layout,
236 const mlir::TypeConverter &typeConverter)
const {
241 mlir::Type abiTy = lowerDataMemberType(
attr.getType(), typeConverter);
242 return cir::IntAttr::get(abiTy,
static_cast<int64_t>(
attr.getOffset()));
245mlir::TypedAttr LowerItaniumCXXABI::lowerMethodConstant(
246 cir::MethodAttr attr,
const mlir::DataLayout &layout,
247 const mlir::TypeConverter &typeConverter)
const {
250 auto loweredMethodTy = mlir::cast<cir::StructType>(
251 lowerMethodType(
attr.getType(), typeConverter));
253 auto zero = cir::IntAttr::get(ptrdiffCIRTy, 0);
274 return cir::ConstRecordAttr::get(
275 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {zero, zero}));
278 if (
attr.isVirtual()) {
279 if (useARMMethodPtrABI) {
288 cir::IntAttr::get(ptrdiffCIRTy,
attr.getVtableOffset().value());
289 auto one = cir::IntAttr::get(ptrdiffCIRTy, 1);
290 return cir::ConstRecordAttr::get(
291 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {ptr, one}));
302 cir::IntAttr::get(ptrdiffCIRTy, 1 +
attr.getVtableOffset().value());
303 return cir::ConstRecordAttr::get(
304 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {ptr, zero}));
312 auto ptr = cir::GlobalViewAttr::get(ptrdiffCIRTy,
attr.getSymbol().value());
313 return cir::ConstRecordAttr::get(
314 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {ptr, zero}));
317mlir::Operation *LowerItaniumCXXABI::lowerGetRuntimeMember(
318 cir::GetRuntimeMemberOp op, mlir::Type loweredResultTy,
319 mlir::Value loweredAddr, mlir::Value loweredMember,
320 mlir::OpBuilder &builder)
const {
321 auto byteTy = cir::IntType::get(op.getContext(), 8,
true);
322 auto bytePtrTy = cir::PointerType::get(
324 mlir::cast<cir::PointerType>(op.getAddr().getType()).getAddrSpace());
325 auto objectBytesPtr = cir::CastOp::create(
326 builder, op.getLoc(), bytePtrTy, cir::CastKind::bitcast, op.getAddr());
327 auto memberBytesPtr = cir::PtrStrideOp::create(
328 builder, op.getLoc(), bytePtrTy, objectBytesPtr, loweredMember);
329 return cir::CastOp::create(builder, op.getLoc(), op.getType(),
330 cir::CastKind::bitcast, memberBytesPtr);
333void LowerItaniumCXXABI::lowerGetMethod(
334 cir::GetMethodOp op, mlir::Value &callee, mlir::Value &thisArg,
335 mlir::Value loweredMethod, mlir::Value loweredObjectPtr,
336 mlir::ConversionPatternRewriter &rewriter)
const {
358 mlir::ImplicitLocOpBuilder locBuilder(op.getLoc(), rewriter);
359 mlir::Type calleePtrTy = op.getCallee().getType();
362 mlir::Value ptrdiffOne =
363 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 1));
366 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredMethod, 1);
367 mlir::Value adj = rawAdj;
368 if (useARMMethodPtrABI)
369 adj = cir::ShiftOp::create(locBuilder, ptrdiffCIRTy, adj, ptrdiffOne,
373 mlir::Type thisVoidPtrTy =
374 cir::PointerType::get(cir::VoidType::get(locBuilder.getContext()),
375 op.getObject().getType().getAddrSpace());
376 mlir::Value thisVoidPtr = cir::CastOp::create(
377 locBuilder, thisVoidPtrTy, cir::CastKind::bitcast, loweredObjectPtr);
379 cir::PtrStrideOp::create(locBuilder, thisVoidPtrTy, thisVoidPtr, adj);
383 mlir::Value methodPtrField =
384 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredMethod, 0);
385 mlir::Value virtualBit;
386 if (useARMMethodPtrABI)
387 virtualBit = cir::AndOp::create(locBuilder, rawAdj, ptrdiffOne);
389 virtualBit = cir::AndOp::create(locBuilder, methodPtrField, ptrdiffOne);
390 mlir::Value isVirtual = cir::CmpOp::create(locBuilder, cir::CmpOpKind::eq,
391 virtualBit, ptrdiffOne);
397 auto buildVirtualCallee = [&](mlir::OpBuilder &b, mlir::Location loc) {
401 cir::PointerType::get(cir::IntType::get(b.getContext(), 8,
true));
402 auto vtablePtrPtrTy = cir::PointerType::get(
403 vtablePtrTy, op.getObject().getType().getAddrSpace());
404 auto vtablePtrPtr = cir::CastOp::create(b, loc, vtablePtrPtrTy,
405 cir::CastKind::bitcast, thisArg);
407 mlir::Value vtablePtr =
408 cir::LoadOp::create(b, loc, vtablePtrPtr,
false,
412 cir::SyncScopeKindAttr{},
419 mlir::Value vtableOffset = methodPtrField;
420 if (!useARMMethodPtrABI)
421 vtableOffset = cir::SubOp::create(b, loc, vtableOffset.getType(),
422 vtableOffset, ptrdiffOne);
423 if (use32BitVTableOffsetABI)
424 llvm_unreachable(
"AppleARM64 method ptr abi NYI");
432 mlir::Value vfpAddr = cir::PtrStrideOp::create(locBuilder, vtablePtrTy,
433 vtablePtr, vtableOffset);
434 auto vfpPtrTy = cir::PointerType::get(calleePtrTy);
435 mlir::Value vfpPtr = cir::CastOp::create(locBuilder, vfpPtrTy,
436 cir::CastKind::bitcast, vfpAddr);
437 auto fnPtr = cir::LoadOp::create(b, loc, vfpPtr,
441 cir::SyncScopeKindAttr{},
445 cir::YieldOp::create(b, loc, fnPtr.getResult());
449 callee = cir::TernaryOp::create(
450 locBuilder, isVirtual, buildVirtualCallee,
452 [&](mlir::OpBuilder &b, mlir::Location loc) {
453 auto fnPtr = cir::CastOp::create(b, loc, calleePtrTy,
454 cir::CastKind::int_to_ptr,
456 cir::YieldOp::create(b, loc, fnPtr.getResult());
462 mlir::Value loweredSrc,
464 bool isDerivedToBase,
465 mlir::OpBuilder &builder) {
468 mlir::Location loc = op->getLoc();
469 mlir::Type ty = loweredSrc.getType();
471 auto getConstantInt = [&](
int64_t value) -> cir::ConstantOp {
472 return cir::ConstantOp::create(builder, loc, cir::IntAttr::get(ty, value));
475 cir::ConstantOp nullValue = getConstantInt(-1);
476 auto isNull = cir::CmpOp::create(builder, loc, cir::CmpOpKind::eq, loweredSrc,
479 cir::ConstantOp offsetValue = getConstantInt(offset);
480 mlir::Value adjustedPtr;
481 if (isDerivedToBase) {
482 auto subOp = cir::SubOp::create(builder, loc, ty, loweredSrc, offsetValue);
483 subOp.setNoSignedWrap(
true);
486 auto addOp = cir::AddOp::create(builder, loc, ty, loweredSrc, offsetValue);
487 addOp.setNoSignedWrap(
true);
491 return cir::SelectOp::create(builder, loc, ty, isNull, loweredSrc,
496LowerItaniumCXXABI::lowerBaseDataMember(cir::BaseDataMemberOp op,
497 mlir::Value loweredSrc,
498 mlir::OpBuilder &builder)
const {
499 return lowerDataMemberCast(op, loweredSrc, op.getOffset().getSExtValue(),
504LowerItaniumCXXABI::lowerDerivedDataMember(cir::DerivedDataMemberOp op,
505 mlir::Value loweredSrc,
506 mlir::OpBuilder &builder)
const {
512 std::int64_t offset,
bool isDerivedToBase,
513 bool useARMMethodPtrABI,
515 mlir::OpBuilder &builder) {
521 if (useARMMethodPtrABI)
525 auto adjField = cir::ExtractMemberOp::create(builder, op->getLoc(),
526 ptrdiffCIRTy, loweredSrc, 1);
528 auto offsetValue = cir::ConstantOp::create(
529 builder, op->getLoc(), cir::IntAttr::get(ptrdiffCIRTy, offset));
530 mlir::Value adjustedAdjField;
531 if (isDerivedToBase) {
532 auto subOp = cir::SubOp::create(builder, op->getLoc(), ptrdiffCIRTy,
533 adjField, offsetValue);
534 subOp.setNoSignedWrap(
true);
535 adjustedAdjField = subOp;
537 auto addOp = cir::AddOp::create(builder, op->getLoc(), ptrdiffCIRTy,
538 adjField, offsetValue);
539 addOp.setNoSignedWrap(
true);
540 adjustedAdjField = addOp;
543 return cir::InsertMemberOp::create(builder, op->getLoc(), loweredSrc, 1,
548LowerItaniumCXXABI::lowerBaseMethod(cir::BaseMethodOp op,
549 mlir::Value loweredSrc,
550 mlir::OpBuilder &builder)
const {
551 return lowerMethodCast(op, loweredSrc, op.getOffset().getSExtValue(),
552 true, useARMMethodPtrABI, lm,
557LowerItaniumCXXABI::lowerDerivedMethod(cir::DerivedMethodOp op,
558 mlir::Value loweredSrc,
559 mlir::OpBuilder &builder)
const {
561 false, useARMMethodPtrABI, lm,
566LowerItaniumCXXABI::lowerDataMemberCmp(cir::CmpOp op, mlir::Value loweredLhs,
567 mlir::Value loweredRhs,
568 mlir::OpBuilder &builder)
const {
569 return cir::CmpOp::create(builder, op.getLoc(), op.getKind(), loweredLhs,
573mlir::Value LowerItaniumCXXABI::lowerMethodCmp(cir::CmpOp op,
574 mlir::Value loweredLhs,
575 mlir::Value loweredRhs,
576 mlir::OpBuilder &builder)
const {
577 assert(op.getKind() == cir::CmpOpKind::eq ||
578 op.getKind() == cir::CmpOpKind::ne);
580 mlir::ImplicitLocOpBuilder locBuilder(op.getLoc(), builder);
582 mlir::Value ptrdiffZero =
583 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 0));
585 mlir::Value lhsPtrField =
586 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredLhs, 0);
587 mlir::Value rhsPtrField =
588 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredRhs, 0);
590 cir::CmpOp::create(locBuilder, op.getKind(), lhsPtrField, rhsPtrField);
591 mlir::Value ptrCmpToNull =
592 cir::CmpOp::create(locBuilder, op.getKind(), lhsPtrField, ptrdiffZero);
594 mlir::Value lhsAdjField =
595 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredLhs, 1);
596 mlir::Value rhsAdjField =
597 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredRhs, 1);
599 cir::CmpOp::create(locBuilder, op.getKind(), lhsAdjField, rhsAdjField);
601 auto create_and = [&](mlir::Value lhs, mlir::Value rhs) {
602 return cir::AndOp::create(locBuilder, lhs.getType(), lhs, rhs);
604 auto create_or = [&](mlir::Value lhs, mlir::Value rhs) {
605 return cir::OrOp::create(locBuilder, lhs.getType(), lhs, rhs);
610 if (useARMMethodPtrABI) {
612 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 1));
628 mlir::Value orAdj = create_or(lhsAdjField, rhsAdjField);
629 mlir::Value orAdjAnd1 = create_and(orAdj, one);
630 mlir::Value orAdjAnd1CmpZero =
631 cir::CmpOp::create(locBuilder, op.getKind(), orAdjAnd1, ptrdiffZero);
633 if (op.getKind() == cir::CmpOpKind::eq)
634 ptrCmpToNull = create_and(ptrCmpToNull, orAdjAnd1CmpZero);
636 ptrCmpToNull = create_or(ptrCmpToNull, orAdjAnd1CmpZero);
640 if (op.getKind() == cir::CmpOpKind::eq) {
642 result = create_and(ptrCmp, create_or(ptrCmpToNull, adjCmp));
645 result = create_or(ptrCmp, create_and(ptrCmpToNull, adjCmp));
651mlir::Value LowerItaniumCXXABI::lowerDataMemberBitcast(
652 cir::CastOp op, mlir::Type loweredDstTy, mlir::Value loweredSrc,
653 mlir::OpBuilder &builder)
const {
654 if (loweredSrc.getType() == loweredDstTy)
657 return cir::CastOp::create(builder, op.getLoc(), loweredDstTy,
658 cir::CastKind::bitcast, loweredSrc);
661mlir::Value LowerItaniumCXXABI::lowerDataMemberToBoolCast(
662 cir::CastOp op, mlir::Value loweredSrc, mlir::OpBuilder &builder)
const {
666 auto nullValue = cir::ConstantOp::create(builder, op.getLoc(), nullAttr);
667 return cir::CmpOp::create(builder, op.getLoc(), cir::CmpOpKind::ne,
668 loweredSrc, nullValue);
672LowerItaniumCXXABI::lowerMethodBitcast(cir::CastOp op, mlir::Type loweredDstTy,
673 mlir::Value loweredSrc,
674 mlir::OpBuilder &builder)
const {
675 if (loweredSrc.getType() == loweredDstTy)
681mlir::Value LowerItaniumCXXABI::lowerMethodToBoolCast(
682 cir::CastOp op, mlir::Value loweredSrc, mlir::OpBuilder &builder)
const {
683 mlir::ImplicitLocOpBuilder locBuilder(op.getLoc(), builder);
691 mlir::Value ptrdiffZero =
692 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 0));
693 mlir::Value ptrField =
694 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredSrc, 0);
697 cir::CmpOp::create(locBuilder, cir::CmpOpKind::ne, ptrField, ptrdiffZero);
701 if (useARMMethodPtrABI) {
703 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 1));
705 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredSrc, 1);
706 mlir::Value virtualBit =
707 cir::AndOp::create(locBuilder, ptrdiffCIRTy, adj, one);
708 mlir::Value isVirtual = cir::CmpOp::create(locBuilder, cir::CmpOpKind::ne,
709 virtualBit, ptrdiffZero);
710 result = cir::OrOp::create(locBuilder, result, isVirtual);
717 mlir::FlatSymbolRefAttr badCastFuncRef) {
720 auto callOp = cir::CallOp::create(builder, loc, badCastFuncRef,
723 callOp->setAttr(cir::CIRDialect::getNoReturnAttrName(),
724 builder.getUnitAttr());
726 cir::UnreachableOp::create(builder, loc);
727 builder.clearInsertionPoint();
731 mlir::OpBuilder &builder) {
732 mlir::Location loc = op->getLoc();
733 mlir::Value srcValue = op.getSrc();
734 cir::DynamicCastInfoAttr castInfo = op.getInfo().value();
740 cir::PointerType::get(cir::VoidType::get(builder.getContext()));
742 mlir::Value srcPtr = cir::CastOp::create(builder, loc, voidPtrTy,
743 cir::CastKind::bitcast, srcValue);
744 mlir::Value srcRtti =
745 cir::ConstantOp::create(builder, loc, castInfo.getSrcRtti());
746 mlir::Value destRtti =
747 cir::ConstantOp::create(builder, loc, castInfo.getDestRtti());
748 mlir::Value offsetHint =
749 cir::ConstantOp::create(builder, loc, castInfo.getOffsetHint());
751 mlir::FlatSymbolRefAttr dynCastFuncRef = castInfo.getRuntimeFunc();
752 mlir::Value dynCastFuncArgs[4] = {srcPtr, srcRtti, destRtti, offsetHint};
757 mlir::Value castedPtr = cir::CallOp::create(builder, loc, dynCastFuncRef,
758 voidPtrTy, dynCastFuncArgs)
761 assert(mlir::isa<cir::PointerType>(castedPtr.getType()) &&
762 "the return value of __dynamic_cast should be a ptr");
766 if (op.isRefCast()) {
768 mlir::Value null = cir::ConstantOp::create(
770 cir::ConstPtrAttr::get(castedPtr.getType(),
771 builder.getI64IntegerAttr(0)));
772 mlir::Value castedPtrIsNull =
773 cir::CmpOp::create(builder, loc, cir::CmpOpKind::eq, castedPtr, null);
774 cir::IfOp::create(builder, loc, castedPtrIsNull,
false,
775 [&](mlir::OpBuilder &, mlir::Location) {
777 castInfo.getBadCastFunc());
783 return cir::CastOp::create(builder, loc, op.getType(), cir::CastKind::bitcast,
789 mlir::Location loc = op.getLoc();
790 bool vtableUsesRelativeLayout = op.getRelativeLayout();
795 mlir::Type vtableElemTy;
796 uint64_t vtableElemAlign;
797 if (vtableUsesRelativeLayout) {
799 cir::IntType::get(builder.getContext(), 32,
true);
803 vtableElemAlign = llvm::divideCeil(
807 mlir::Type vtableElemPtrTy = cir::PointerType::get(vtableElemTy);
808 mlir::Type i64Ty = cir::IntType::get(builder.getContext(), 64,
814 auto vptrPtr = cir::VTableGetVPtrOp::create(builder, loc, op.getSrc());
815 mlir::Value vptr = cir::LoadOp::create(
816 builder, loc, vptrPtr,
820 builder.getI64IntegerAttr(vtableElemAlign),
821 cir::SyncScopeKindAttr(),
824 mlir::Value elementPtr = cir::CastOp::create(builder, loc, vtableElemPtrTy,
825 cir::CastKind::bitcast, vptr);
826 mlir::Value minusTwo =
827 cir::ConstantOp::create(builder, loc, cir::IntAttr::get(i64Ty, -2));
828 mlir::Value offsetToTopSlotPtr = cir::PtrStrideOp::create(
829 builder, loc, vtableElemPtrTy, elementPtr, minusTwo);
830 mlir::Value offsetToTop = cir::LoadOp::create(
831 builder, loc, offsetToTopSlotPtr,
835 builder.getI64IntegerAttr(vtableElemAlign),
836 cir::SyncScopeKindAttr(),
843 cir::PointerType::get(cir::IntType::get(builder.getContext(), 8,
845 op.getSrc().getType().getAddrSpace());
846 mlir::Value srcBytePtr = cir::CastOp::create(
847 builder, loc, u8PtrTy, cir::CastKind::bitcast, op.getSrc());
849 cir::PtrStrideOp::create(builder, loc, u8PtrTy, srcBytePtr, offsetToTop);
851 return cir::CastOp::create(builder, loc, op.getType(), cir::CastKind::bitcast,
856LowerItaniumCXXABI::lowerDynamicCast(cir::DynamicCastOp op,
857 mlir::OpBuilder &builder)
const {
858 mlir::Location loc = op->getLoc();
859 mlir::Value srcValue = op.getSrc();
864 return buildDynamicCastAfterNullCheck(op, builder);
866 mlir::Value srcValueIsNotNull = cir::CastOp::create(
867 builder, loc, cir::BoolType::get(builder.getContext()),
868 cir::CastKind::ptr_to_bool, srcValue);
869 return cir::TernaryOp::create(
870 builder, loc, srcValueIsNotNull,
871 [&](mlir::OpBuilder &, mlir::Location) {
872 mlir::Value castedValue =
874 ? buildDynamicCastToVoidAfterNullCheck(op, lm, builder)
875 : buildDynamicCastAfterNullCheck(op, builder);
876 cir::YieldOp::create(builder, loc, castedValue);
878 [&](mlir::OpBuilder &, mlir::Location) {
879 mlir::Value null = cir::ConstantOp::create(
881 cir::ConstPtrAttr::get(op.getType(),
882 builder.getI64IntegerAttr(0)));
883 cir::YieldOp::create(builder, loc, null);
888LowerItaniumCXXABI::lowerVTableGetTypeInfo(cir::VTableGetTypeInfoOp op,
889 mlir::OpBuilder &builder)
const {
890 mlir::Location loc = op->getLoc();
891 auto offset = cir::ConstantOp::create(
895 auto vptrCast = cir::CastOp::create(builder, loc, op.getType(),
896 cir::CastKind::bitcast, op.getVptr());
898 return cir::PtrStrideOp::create(builder, loc, vptrCast.getType(), vptrCast,
903clang::CharUnits LowerItaniumCXXABI::getArrayCookieSizeImpl(
904 clang::CharUnits elementAlign)
const {
907 clang::CharUnits sizeOfSizeT =
909 return std::max(sizeOfSizeT, elementAlign);
912mlir::Value LowerItaniumCXXABI::readArrayCookieImpl(
913 mlir::Location loc, mlir::Value allocPtr, clang::CharUnits cookieSize,
914 clang::CharUnits cookieAlignment,
const mlir::DataLayout &dataLayout,
915 CIRBaseBuilderTy &builder)
const {
916 unsigned ptrSizeInBits = getPtrSizeInBits();
917 mlir::ptr::MemorySpaceAttrInterface addrSpace =
918 mlir::cast<cir::PointerType>(allocPtr.getType()).getAddrSpace();
920 auto ptrDiffTy = builder.
getSIntNTy(ptrSizeInBits);
921 auto sizeTy = builder.
getUIntNTy(ptrSizeInBits);
924 clang::CharUnits sizeOfSizeT =
926 clang::CharUnits countOffset = cookieSize - sizeOfSizeT;
928 mlir::Value countBytePtr = allocPtr;
929 clang::CharUnits countAlignment = cookieAlignment;
930 if (!countOffset.
isZero()) {
931 mlir::Value offsetVal = cir::ConstantOp::create(
932 builder, loc, cir::IntAttr::get(ptrDiffTy, countOffset.
getQuantity()));
934 cir::PtrStrideOp::create(builder, loc, u8PtrTy, allocPtr, offsetVal);
938 auto countPtrTy = cir::PointerType::get(sizeTy, addrSpace);
939 mlir::Value countPtr = cir::CastOp::create(
940 builder, loc, countPtrTy, cir::CastKind::bitcast, countBytePtr);
941 return cir::LoadOp::create(
942 builder, loc, countPtr,
false,
false,
944 builder.getI64IntegerAttr(countAlignment.
getQuantity()),
945 cir::SyncScopeKindAttr(), cir::MemOrderAttr(),
cir::PointerType getPointerTo(mlir::Type ty)
cir::IntType getUIntNTy(int n)
cir::IntType getSIntNTy(int n)
mlir::MLIRContext * getMLIRContext()
clang::TargetCXXABI::Kind getCXXABIKind() const
const clang::TargetInfo & getTarget() const
static llvm::SmallVector< RecordMemberKind > getAllDataKinds(llvm::ArrayRef< mlir::Type > members)
One Data kind per member.
CharUnits alignmentAtOffset(CharUnits offset) const
Given that this is a non-zero alignment value, what is the alignment at the given offset?
bool isZero() const
Test whether the quantity equals zero.
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.
Exposes information about the current target.
unsigned getTypeWidth(IntType T) const
Return the width (in bits) of the specified integer type enum.
static bool isTypeSigned(IntType T)
Returns true if the type is signed; false otherwise.
IntType getPtrDiffType(LangAS AddrSpace) const
uint64_t getPointerAlign(LangAS AddrSpace) const
static mlir::Value lowerDataMemberCast(mlir::Operation *op, mlir::Value loweredSrc, std::int64_t offset, bool isDerivedToBase, mlir::OpBuilder &builder)
std::unique_ptr< CIRCXXABI > createItaniumCXXABI(LowerModule &lm)
Creates an Itanium-family ABI.
static mlir::Value buildDynamicCastAfterNullCheck(cir::DynamicCastOp op, mlir::OpBuilder &builder)
static cir::IntType getPtrDiffCIRTy(LowerModule &lm)
static mlir::Value buildDynamicCastToVoidAfterNullCheck(cir::DynamicCastOp op, cir::LowerModule &lm, mlir::OpBuilder &builder)
static mlir::Value lowerMethodCast(mlir::Operation *op, mlir::Value loweredSrc, std::int64_t offset, bool isDerivedToBase, bool useARMMethodPtrABI, LowerModule &lowerMod, mlir::OpBuilder &builder)
static void buildBadCastCall(mlir::OpBuilder &builder, mlir::Location loc, mlir::FlatSymbolRefAttr badCastFuncRef)
const internal::VariadicAllOfMatcher< Attr > attr
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t uint32_t uint32_t __builtin_riscv_mhacc_i32 __builtin_riscv_mhaccu_u32 __builtin_riscv_mhaccsu_i32 __builtin_riscv_mulq_i32 int64_t
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t
static bool addressSpace()
static bool appleArm64CXXABI()
static bool emitCFICheck()
static bool emitVFEInfo()
static bool emitWPDInfo()
static bool emitTypeCheck()
static bool pointerAuthentication()
static bool opFuncCallingConv()
IntType
===-— Target Data Type Query Methods ----------------------------—===//