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(mlir::Type elementType,
121 const mlir::DataLayout &dataLayout)
const override;
123 mlir::Value readArrayCookieImpl(mlir::Location loc, mlir::Value allocPtr,
124 clang::CharUnits cookieSize,
125 clang::CharUnits cookieAlignment,
126 const mlir::DataLayout &dataLayout,
127 CIRBaseBuilderTy &builder)
const override;
137 case clang::TargetCXXABI::GenericAArch64:
138 return std::make_unique<LowerItaniumCXXABI>(
142 case clang::TargetCXXABI::AppleARM64:
146 return std::make_unique<LowerItaniumCXXABI>(
151 case clang::TargetCXXABI::GenericItanium:
152 return std::make_unique<LowerItaniumCXXABI>(lm);
154 case clang::TargetCXXABI::Microsoft:
155 llvm_unreachable(
"Microsoft ABI is not Itanium-based");
157 llvm_unreachable(
"Other Itanium ABI?");
169mlir::Type LowerItaniumCXXABI::lowerDataMemberType(
170 cir::DataMemberType type,
const mlir::TypeConverter &typeConverter)
const {
174 return getPtrDiffCIRTy(lm);
177mlir::Type LowerItaniumCXXABI::lowerMethodType(
178 cir::MethodType type,
const mlir::TypeConverter &typeConverter)
const {
193 mlir::Type members[] = {ptrdiffCIRTy, ptrdiffCIRTy};
194 return cir::StructType::get(
type.getContext(), members,
false,
199mlir::TypedAttr LowerItaniumCXXABI::lowerDataMemberConstant(
200 cir::DataMemberAttr attr,
const mlir::DataLayout &layout,
201 const mlir::TypeConverter &typeConverter)
const {
203 if (
attr.isNullPtr()) {
213 mlir::Type currentTy =
attr.getType().getClassTy();
215 auto recTy = mlir::cast<cir::RecordType>(currentTy);
216 memberOffset +=
static_cast<int64_t>(recTy.getElementOffset(layout, idx));
217 currentTy = recTy.getMembers()[idx];
221 mlir::Type abiTy = lowerDataMemberType(
attr.getType(), typeConverter);
222 return cir::IntAttr::get(abiTy, memberOffset);
225mlir::TypedAttr LowerItaniumCXXABI::lowerDataMemberOffsetConstant(
226 cir::DataMemberOffsetAttr attr,
const mlir::DataLayout &layout,
227 const mlir::TypeConverter &typeConverter)
const {
232 mlir::Type abiTy = lowerDataMemberType(
attr.getType(), typeConverter);
233 return cir::IntAttr::get(abiTy,
static_cast<int64_t>(
attr.getOffset()));
236mlir::TypedAttr LowerItaniumCXXABI::lowerMethodConstant(
237 cir::MethodAttr attr,
const mlir::DataLayout &layout,
238 const mlir::TypeConverter &typeConverter)
const {
241 auto loweredMethodTy = mlir::cast<cir::StructType>(
242 lowerMethodType(
attr.getType(), typeConverter));
244 auto zero = cir::IntAttr::get(ptrdiffCIRTy, 0);
265 return cir::ConstRecordAttr::get(
266 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {zero, zero}));
269 if (
attr.isVirtual()) {
270 if (useARMMethodPtrABI) {
279 cir::IntAttr::get(ptrdiffCIRTy,
attr.getVtableOffset().value());
280 auto one = cir::IntAttr::get(ptrdiffCIRTy, 1);
281 return cir::ConstRecordAttr::get(
282 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {ptr, one}));
293 cir::IntAttr::get(ptrdiffCIRTy, 1 +
attr.getVtableOffset().value());
294 return cir::ConstRecordAttr::get(
295 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {ptr, zero}));
303 auto ptr = cir::GlobalViewAttr::get(ptrdiffCIRTy,
attr.getSymbol().value());
304 return cir::ConstRecordAttr::get(
305 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {ptr, zero}));
308mlir::Operation *LowerItaniumCXXABI::lowerGetRuntimeMember(
309 cir::GetRuntimeMemberOp op, mlir::Type loweredResultTy,
310 mlir::Value loweredAddr, mlir::Value loweredMember,
311 mlir::OpBuilder &builder)
const {
312 auto byteTy = cir::IntType::get(op.getContext(), 8,
true);
313 auto bytePtrTy = cir::PointerType::get(
315 mlir::cast<cir::PointerType>(op.getAddr().getType()).getAddrSpace());
316 auto objectBytesPtr = cir::CastOp::create(
317 builder, op.getLoc(), bytePtrTy, cir::CastKind::bitcast, op.getAddr());
318 auto memberBytesPtr = cir::PtrStrideOp::create(
319 builder, op.getLoc(), bytePtrTy, objectBytesPtr, loweredMember);
320 return cir::CastOp::create(builder, op.getLoc(), op.getType(),
321 cir::CastKind::bitcast, memberBytesPtr);
324void LowerItaniumCXXABI::lowerGetMethod(
325 cir::GetMethodOp op, mlir::Value &callee, mlir::Value &thisArg,
326 mlir::Value loweredMethod, mlir::Value loweredObjectPtr,
327 mlir::ConversionPatternRewriter &rewriter)
const {
349 mlir::ImplicitLocOpBuilder locBuilder(op.getLoc(), rewriter);
350 mlir::Type calleePtrTy = op.getCallee().getType();
353 mlir::Value ptrdiffOne =
354 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 1));
357 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredMethod, 1);
358 mlir::Value adj = rawAdj;
359 if (useARMMethodPtrABI)
360 adj = cir::ShiftOp::create(locBuilder, ptrdiffCIRTy, adj, ptrdiffOne,
364 mlir::Type thisVoidPtrTy =
365 cir::PointerType::get(cir::VoidType::get(locBuilder.getContext()),
366 op.getObject().getType().getAddrSpace());
367 mlir::Value thisVoidPtr = cir::CastOp::create(
368 locBuilder, thisVoidPtrTy, cir::CastKind::bitcast, loweredObjectPtr);
370 cir::PtrStrideOp::create(locBuilder, thisVoidPtrTy, thisVoidPtr, adj);
374 mlir::Value methodPtrField =
375 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredMethod, 0);
376 mlir::Value virtualBit;
377 if (useARMMethodPtrABI)
378 virtualBit = cir::AndOp::create(locBuilder, rawAdj, ptrdiffOne);
380 virtualBit = cir::AndOp::create(locBuilder, methodPtrField, ptrdiffOne);
381 mlir::Value isVirtual = cir::CmpOp::create(locBuilder, cir::CmpOpKind::eq,
382 virtualBit, ptrdiffOne);
388 auto buildVirtualCallee = [&](mlir::OpBuilder &b, mlir::Location loc) {
392 cir::PointerType::get(cir::IntType::get(b.getContext(), 8,
true));
393 auto vtablePtrPtrTy = cir::PointerType::get(
394 vtablePtrTy, op.getObject().getType().getAddrSpace());
395 auto vtablePtrPtr = cir::CastOp::create(b, loc, vtablePtrPtrTy,
396 cir::CastKind::bitcast, thisArg);
398 mlir::Value vtablePtr =
399 cir::LoadOp::create(b, loc, vtablePtrPtr,
false,
403 cir::SyncScopeKindAttr{},
410 mlir::Value vtableOffset = methodPtrField;
411 if (!useARMMethodPtrABI)
412 vtableOffset = cir::SubOp::create(b, loc, vtableOffset.getType(),
413 vtableOffset, ptrdiffOne);
414 if (use32BitVTableOffsetABI)
415 llvm_unreachable(
"AppleARM64 method ptr abi NYI");
423 mlir::Value vfpAddr = cir::PtrStrideOp::create(locBuilder, vtablePtrTy,
424 vtablePtr, vtableOffset);
425 auto vfpPtrTy = cir::PointerType::get(calleePtrTy);
426 mlir::Value vfpPtr = cir::CastOp::create(locBuilder, vfpPtrTy,
427 cir::CastKind::bitcast, vfpAddr);
428 auto fnPtr = cir::LoadOp::create(b, loc, vfpPtr,
432 cir::SyncScopeKindAttr{},
436 cir::YieldOp::create(b, loc, fnPtr.getResult());
440 callee = cir::TernaryOp::create(
441 locBuilder, isVirtual, buildVirtualCallee,
443 [&](mlir::OpBuilder &b, mlir::Location loc) {
444 auto fnPtr = cir::CastOp::create(b, loc, calleePtrTy,
445 cir::CastKind::int_to_ptr,
447 cir::YieldOp::create(b, loc, fnPtr.getResult());
453 mlir::Value loweredSrc,
455 bool isDerivedToBase,
456 mlir::OpBuilder &builder) {
459 mlir::Location loc = op->getLoc();
460 mlir::Type ty = loweredSrc.getType();
462 auto getConstantInt = [&](int64_t value) -> cir::ConstantOp {
463 return cir::ConstantOp::create(builder, loc, cir::IntAttr::get(ty, value));
466 cir::ConstantOp nullValue = getConstantInt(-1);
467 auto isNull = cir::CmpOp::create(builder, loc, cir::CmpOpKind::eq, loweredSrc,
470 cir::ConstantOp offsetValue = getConstantInt(offset);
471 mlir::Value adjustedPtr;
472 if (isDerivedToBase) {
473 auto subOp = cir::SubOp::create(builder, loc, ty, loweredSrc, offsetValue);
474 subOp.setNoSignedWrap(
true);
477 auto addOp = cir::AddOp::create(builder, loc, ty, loweredSrc, offsetValue);
478 addOp.setNoSignedWrap(
true);
482 return cir::SelectOp::create(builder, loc, ty, isNull, loweredSrc,
487LowerItaniumCXXABI::lowerBaseDataMember(cir::BaseDataMemberOp op,
488 mlir::Value loweredSrc,
489 mlir::OpBuilder &builder)
const {
490 return lowerDataMemberCast(op, loweredSrc, op.getOffset().getSExtValue(),
495LowerItaniumCXXABI::lowerDerivedDataMember(cir::DerivedDataMemberOp op,
496 mlir::Value loweredSrc,
497 mlir::OpBuilder &builder)
const {
503 std::int64_t offset,
bool isDerivedToBase,
504 bool useARMMethodPtrABI,
506 mlir::OpBuilder &builder) {
512 if (useARMMethodPtrABI)
516 auto adjField = cir::ExtractMemberOp::create(builder, op->getLoc(),
517 ptrdiffCIRTy, loweredSrc, 1);
519 auto offsetValue = cir::ConstantOp::create(
520 builder, op->getLoc(), cir::IntAttr::get(ptrdiffCIRTy, offset));
521 mlir::Value adjustedAdjField;
522 if (isDerivedToBase) {
523 auto subOp = cir::SubOp::create(builder, op->getLoc(), ptrdiffCIRTy,
524 adjField, offsetValue);
525 subOp.setNoSignedWrap(
true);
526 adjustedAdjField = subOp;
528 auto addOp = cir::AddOp::create(builder, op->getLoc(), ptrdiffCIRTy,
529 adjField, offsetValue);
530 addOp.setNoSignedWrap(
true);
531 adjustedAdjField = addOp;
534 return cir::InsertMemberOp::create(builder, op->getLoc(), loweredSrc, 1,
539LowerItaniumCXXABI::lowerBaseMethod(cir::BaseMethodOp op,
540 mlir::Value loweredSrc,
541 mlir::OpBuilder &builder)
const {
542 return lowerMethodCast(op, loweredSrc, op.getOffset().getSExtValue(),
543 true, useARMMethodPtrABI, lm,
548LowerItaniumCXXABI::lowerDerivedMethod(cir::DerivedMethodOp op,
549 mlir::Value loweredSrc,
550 mlir::OpBuilder &builder)
const {
552 false, useARMMethodPtrABI, lm,
557LowerItaniumCXXABI::lowerDataMemberCmp(cir::CmpOp op, mlir::Value loweredLhs,
558 mlir::Value loweredRhs,
559 mlir::OpBuilder &builder)
const {
560 return cir::CmpOp::create(builder, op.getLoc(), op.getKind(), loweredLhs,
564mlir::Value LowerItaniumCXXABI::lowerMethodCmp(cir::CmpOp op,
565 mlir::Value loweredLhs,
566 mlir::Value loweredRhs,
567 mlir::OpBuilder &builder)
const {
568 assert(op.getKind() == cir::CmpOpKind::eq ||
569 op.getKind() == cir::CmpOpKind::ne);
571 mlir::ImplicitLocOpBuilder locBuilder(op.getLoc(), builder);
573 mlir::Value ptrdiffZero =
574 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 0));
576 mlir::Value lhsPtrField =
577 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredLhs, 0);
578 mlir::Value rhsPtrField =
579 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredRhs, 0);
581 cir::CmpOp::create(locBuilder, op.getKind(), lhsPtrField, rhsPtrField);
582 mlir::Value ptrCmpToNull =
583 cir::CmpOp::create(locBuilder, op.getKind(), lhsPtrField, ptrdiffZero);
585 mlir::Value lhsAdjField =
586 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredLhs, 1);
587 mlir::Value rhsAdjField =
588 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredRhs, 1);
590 cir::CmpOp::create(locBuilder, op.getKind(), lhsAdjField, rhsAdjField);
592 auto create_and = [&](mlir::Value lhs, mlir::Value rhs) {
593 return cir::AndOp::create(locBuilder, lhs.getType(), lhs, rhs);
595 auto create_or = [&](mlir::Value lhs, mlir::Value rhs) {
596 return cir::OrOp::create(locBuilder, lhs.getType(), lhs, rhs);
601 if (useARMMethodPtrABI) {
603 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 1));
619 mlir::Value orAdj = create_or(lhsAdjField, rhsAdjField);
620 mlir::Value orAdjAnd1 = create_and(orAdj, one);
621 mlir::Value orAdjAnd1CmpZero =
622 cir::CmpOp::create(locBuilder, op.getKind(), orAdjAnd1, ptrdiffZero);
624 if (op.getKind() == cir::CmpOpKind::eq)
625 ptrCmpToNull = create_and(ptrCmpToNull, orAdjAnd1CmpZero);
627 ptrCmpToNull = create_or(ptrCmpToNull, orAdjAnd1CmpZero);
631 if (op.getKind() == cir::CmpOpKind::eq) {
633 result = create_and(ptrCmp, create_or(ptrCmpToNull, adjCmp));
636 result = create_or(ptrCmp, create_and(ptrCmpToNull, adjCmp));
642mlir::Value LowerItaniumCXXABI::lowerDataMemberBitcast(
643 cir::CastOp op, mlir::Type loweredDstTy, mlir::Value loweredSrc,
644 mlir::OpBuilder &builder)
const {
645 if (loweredSrc.getType() == loweredDstTy)
648 return cir::CastOp::create(builder, op.getLoc(), loweredDstTy,
649 cir::CastKind::bitcast, loweredSrc);
652mlir::Value LowerItaniumCXXABI::lowerDataMemberToBoolCast(
653 cir::CastOp op, mlir::Value loweredSrc, mlir::OpBuilder &builder)
const {
657 auto nullValue = cir::ConstantOp::create(builder, op.getLoc(), nullAttr);
658 return cir::CmpOp::create(builder, op.getLoc(), cir::CmpOpKind::ne,
659 loweredSrc, nullValue);
663LowerItaniumCXXABI::lowerMethodBitcast(cir::CastOp op, mlir::Type loweredDstTy,
664 mlir::Value loweredSrc,
665 mlir::OpBuilder &builder)
const {
666 if (loweredSrc.getType() == loweredDstTy)
672mlir::Value LowerItaniumCXXABI::lowerMethodToBoolCast(
673 cir::CastOp op, mlir::Value loweredSrc, mlir::OpBuilder &builder)
const {
674 mlir::ImplicitLocOpBuilder locBuilder(op.getLoc(), builder);
682 mlir::Value ptrdiffZero =
683 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 0));
684 mlir::Value ptrField =
685 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredSrc, 0);
688 cir::CmpOp::create(locBuilder, cir::CmpOpKind::ne, ptrField, ptrdiffZero);
692 if (useARMMethodPtrABI) {
694 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 1));
696 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredSrc, 1);
697 mlir::Value virtualBit =
698 cir::AndOp::create(locBuilder, ptrdiffCIRTy, adj, one);
699 mlir::Value isVirtual = cir::CmpOp::create(locBuilder, cir::CmpOpKind::ne,
700 virtualBit, ptrdiffZero);
701 result = cir::OrOp::create(locBuilder, result, isVirtual);
708 mlir::FlatSymbolRefAttr badCastFuncRef) {
709 auto callOp = cir::CallOp::create(builder, loc, badCastFuncRef,
712 callOp->setAttr(cir::CIRDialect::getNoReturnAttrName(),
713 builder.getUnitAttr());
715 cir::UnreachableOp::create(builder, loc);
716 builder.clearInsertionPoint();
720 mlir::OpBuilder &builder) {
721 mlir::Location loc = op->getLoc();
722 mlir::Value srcValue = op.getSrc();
723 cir::DynamicCastInfoAttr castInfo = op.getInfo().value();
729 cir::PointerType::get(cir::VoidType::get(builder.getContext()));
731 mlir::Value srcPtr = cir::CastOp::create(builder, loc, voidPtrTy,
732 cir::CastKind::bitcast, srcValue);
733 mlir::Value srcRtti =
734 cir::ConstantOp::create(builder, loc, castInfo.getSrcRtti());
735 mlir::Value destRtti =
736 cir::ConstantOp::create(builder, loc, castInfo.getDestRtti());
737 mlir::Value offsetHint =
738 cir::ConstantOp::create(builder, loc, castInfo.getOffsetHint());
740 mlir::FlatSymbolRefAttr dynCastFuncRef = castInfo.getRuntimeFunc();
741 mlir::Value dynCastFuncArgs[4] = {srcPtr, srcRtti, destRtti, offsetHint};
743 mlir::Value castedPtr = cir::CallOp::create(builder, loc, dynCastFuncRef,
744 voidPtrTy, dynCastFuncArgs)
747 assert(mlir::isa<cir::PointerType>(castedPtr.getType()) &&
748 "the return value of __dynamic_cast should be a ptr");
752 if (op.isRefCast()) {
754 mlir::Value null = cir::ConstantOp::create(
756 cir::ConstPtrAttr::get(castedPtr.getType(),
757 builder.getI64IntegerAttr(0)));
758 mlir::Value castedPtrIsNull =
759 cir::CmpOp::create(builder, loc, cir::CmpOpKind::eq, castedPtr, null);
760 cir::IfOp::create(builder, loc, castedPtrIsNull,
false,
761 [&](mlir::OpBuilder &, mlir::Location) {
763 castInfo.getBadCastFunc());
769 return cir::CastOp::create(builder, loc, op.getType(), cir::CastKind::bitcast,
775 mlir::Location loc = op.getLoc();
776 bool vtableUsesRelativeLayout = op.getRelativeLayout();
781 mlir::Type vtableElemTy;
782 uint64_t vtableElemAlign;
783 if (vtableUsesRelativeLayout) {
785 cir::IntType::get(builder.getContext(), 32,
true);
789 vtableElemAlign = llvm::divideCeil(
793 mlir::Type vtableElemPtrTy = cir::PointerType::get(vtableElemTy);
794 mlir::Type i64Ty = cir::IntType::get(builder.getContext(), 64,
800 auto vptrPtr = cir::VTableGetVPtrOp::create(builder, loc, op.getSrc());
801 mlir::Value vptr = cir::LoadOp::create(
802 builder, loc, vptrPtr,
806 builder.getI64IntegerAttr(vtableElemAlign),
807 cir::SyncScopeKindAttr(),
810 mlir::Value elementPtr = cir::CastOp::create(builder, loc, vtableElemPtrTy,
811 cir::CastKind::bitcast, vptr);
812 mlir::Value minusTwo =
813 cir::ConstantOp::create(builder, loc, cir::IntAttr::get(i64Ty, -2));
814 mlir::Value offsetToTopSlotPtr = cir::PtrStrideOp::create(
815 builder, loc, vtableElemPtrTy, elementPtr, minusTwo);
816 mlir::Value offsetToTop = cir::LoadOp::create(
817 builder, loc, offsetToTopSlotPtr,
821 builder.getI64IntegerAttr(vtableElemAlign),
822 cir::SyncScopeKindAttr(),
827 cir::PointerType::get(cir::VoidType::get(builder.getContext()));
832 cir::PointerType::get(cir::IntType::get(builder.getContext(), 8,
834 mlir::Value srcBytePtr = cir::CastOp::create(
835 builder, loc, u8PtrTy, cir::CastKind::bitcast, op.getSrc());
837 cir::PtrStrideOp::create(builder, loc, u8PtrTy, srcBytePtr, offsetToTop);
839 return cir::CastOp::create(builder, loc, voidPtrTy, cir::CastKind::bitcast,
844LowerItaniumCXXABI::lowerDynamicCast(cir::DynamicCastOp op,
845 mlir::OpBuilder &builder)
const {
846 mlir::Location loc = op->getLoc();
847 mlir::Value srcValue = op.getSrc();
852 return buildDynamicCastAfterNullCheck(op, builder);
854 mlir::Value srcValueIsNotNull = cir::CastOp::create(
855 builder, loc, cir::BoolType::get(builder.getContext()),
856 cir::CastKind::ptr_to_bool, srcValue);
857 return cir::TernaryOp::create(
858 builder, loc, srcValueIsNotNull,
859 [&](mlir::OpBuilder &, mlir::Location) {
860 mlir::Value castedValue =
862 ? buildDynamicCastToVoidAfterNullCheck(op, lm, builder)
863 : buildDynamicCastAfterNullCheck(op, builder);
864 cir::YieldOp::create(builder, loc, castedValue);
866 [&](mlir::OpBuilder &, mlir::Location) {
867 mlir::Value null = cir::ConstantOp::create(
869 cir::ConstPtrAttr::get(op.getType(),
870 builder.getI64IntegerAttr(0)));
871 cir::YieldOp::create(builder, loc, null);
876LowerItaniumCXXABI::lowerVTableGetTypeInfo(cir::VTableGetTypeInfoOp op,
877 mlir::OpBuilder &builder)
const {
878 mlir::Location loc = op->getLoc();
879 auto offset = cir::ConstantOp::create(
883 auto vptrCast = cir::CastOp::create(builder, loc, op.getType(),
884 cir::CastKind::bitcast, op.getVptr());
886 return cir::PtrStrideOp::create(builder, loc, vptrCast.getType(), vptrCast,
891clang::CharUnits LowerItaniumCXXABI::getArrayCookieSizeImpl(
892 mlir::Type elementType,
const mlir::DataLayout &dataLayout)
const {
895 clang::CharUnits sizeOfSizeT =
898 dataLayout.getTypePreferredAlignment(elementType));
899 return std::max(sizeOfSizeT, eltAlign);
902mlir::Value LowerItaniumCXXABI::readArrayCookieImpl(
903 mlir::Location loc, mlir::Value allocPtr, clang::CharUnits cookieSize,
904 clang::CharUnits cookieAlignment,
const mlir::DataLayout &dataLayout,
905 CIRBaseBuilderTy &builder)
const {
906 unsigned ptrSizeInBits = getPtrSizeInBits();
908 auto ptrDiffTy = builder.
getSIntNTy(ptrSizeInBits);
909 auto sizeTy = builder.
getUIntNTy(ptrSizeInBits);
912 clang::CharUnits sizeOfSizeT =
914 clang::CharUnits countOffset = cookieSize - sizeOfSizeT;
916 mlir::Value countBytePtr = allocPtr;
917 clang::CharUnits countAlignment = cookieAlignment;
918 if (!countOffset.
isZero()) {
919 mlir::Value offsetVal = cir::ConstantOp::create(
920 builder, loc, cir::IntAttr::get(ptrDiffTy, countOffset.
getQuantity()));
922 cir::PtrStrideOp::create(builder, loc, u8PtrTy, allocPtr, offsetVal);
926 auto countPtrTy = cir::PointerType::get(sizeTy);
927 mlir::Value countPtr = cir::CastOp::create(
928 builder, loc, countPtrTy, cir::CastKind::bitcast, countBytePtr);
929 return cir::LoadOp::create(
930 builder, loc, countPtr,
false,
false,
932 builder.getI64IntegerAttr(countAlignment.
getQuantity()),
933 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
isZero - Test whether the quantity equals zero.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - 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.
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 int32_t
static bool addressSpace()
static bool appleArm64CXXABI()
static bool emitCFICheck()
static bool emitVFEInfo()
static bool emitWPDInfo()
static bool emitTypeCheck()
static bool pointerAuthentication()
IntType
===-— Target Data Type Query Methods ----------------------------—===//