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;
59 lowerMethodConstant(cir::MethodAttr attr,
const mlir::DataLayout &layout,
60 const mlir::TypeConverter &typeConverter)
const override;
63 lowerGetRuntimeMember(cir::GetRuntimeMemberOp op, mlir::Type loweredResultTy,
64 mlir::Value loweredAddr, mlir::Value loweredMember,
65 mlir::OpBuilder &builder)
const override;
67 void lowerGetMethod(cir::GetMethodOp op, mlir::Value &callee,
68 mlir::Value &thisArg, mlir::Value loweredMethod,
69 mlir::Value loweredObjectPtr,
70 mlir::ConversionPatternRewriter &rewriter)
const override;
72 mlir::Value lowerBaseDataMember(cir::BaseDataMemberOp op,
73 mlir::Value loweredSrc,
74 mlir::OpBuilder &builder)
const override;
76 mlir::Value lowerDerivedDataMember(cir::DerivedDataMemberOp op,
77 mlir::Value loweredSrc,
78 mlir::OpBuilder &builder)
const override;
80 mlir::Value lowerBaseMethod(cir::BaseMethodOp op, mlir::Value loweredSrc,
81 mlir::OpBuilder &builder)
const override;
83 mlir::Value lowerDerivedMethod(cir::DerivedMethodOp op,
84 mlir::Value loweredSrc,
85 mlir::OpBuilder &builder)
const override;
87 mlir::Value lowerDataMemberCmp(cir::CmpOp op, mlir::Value loweredLhs,
88 mlir::Value loweredRhs,
89 mlir::OpBuilder &builder)
const override;
91 mlir::Value lowerMethodCmp(cir::CmpOp op, mlir::Value loweredLhs,
92 mlir::Value loweredRhs,
93 mlir::OpBuilder &builder)
const override;
95 mlir::Value lowerDataMemberBitcast(cir::CastOp op, mlir::Type loweredDstTy,
96 mlir::Value loweredSrc,
97 mlir::OpBuilder &builder)
const override;
100 lowerDataMemberToBoolCast(cir::CastOp op, mlir::Value loweredSrc,
101 mlir::OpBuilder &builder)
const override;
103 mlir::Value lowerMethodBitcast(cir::CastOp op, mlir::Type loweredDstTy,
104 mlir::Value loweredSrc,
105 mlir::OpBuilder &builder)
const override;
107 mlir::Value lowerMethodToBoolCast(cir::CastOp op, mlir::Value loweredSrc,
108 mlir::OpBuilder &builder)
const override;
110 mlir::Value lowerDynamicCast(cir::DynamicCastOp op,
111 mlir::OpBuilder &builder)
const override;
112 mlir::Value lowerVTableGetTypeInfo(cir::VTableGetTypeInfoOp op,
113 mlir::OpBuilder &builder)
const override;
116 getArrayCookieSizeImpl(mlir::Type elementType,
117 const mlir::DataLayout &dataLayout)
const override;
119 mlir::Value readArrayCookieImpl(mlir::Location loc, mlir::Value allocPtr,
120 clang::CharUnits cookieSize,
121 clang::CharUnits cookieAlignment,
122 const mlir::DataLayout &dataLayout,
123 CIRBaseBuilderTy &builder)
const override;
133 case clang::TargetCXXABI::GenericAArch64:
134 return std::make_unique<LowerItaniumCXXABI>(
138 case clang::TargetCXXABI::AppleARM64:
142 return std::make_unique<LowerItaniumCXXABI>(
147 case clang::TargetCXXABI::GenericItanium:
148 return std::make_unique<LowerItaniumCXXABI>(lm);
150 case clang::TargetCXXABI::Microsoft:
151 llvm_unreachable(
"Microsoft ABI is not Itanium-based");
153 llvm_unreachable(
"Other Itanium ABI?");
165mlir::Type LowerItaniumCXXABI::lowerDataMemberType(
166 cir::DataMemberType type,
const mlir::TypeConverter &typeConverter)
const {
170 return getPtrDiffCIRTy(lm);
173mlir::Type LowerItaniumCXXABI::lowerMethodType(
174 cir::MethodType type,
const mlir::TypeConverter &typeConverter)
const {
189 return cir::StructType::get(
type.getContext(), {ptrdiffCIRTy, ptrdiffCIRTy},
194mlir::TypedAttr LowerItaniumCXXABI::lowerDataMemberConstant(
195 cir::DataMemberAttr attr,
const mlir::DataLayout &layout,
196 const mlir::TypeConverter &typeConverter)
const {
198 if (
attr.isNullPtr()) {
206 unsigned memberIndex =
attr.getMemberIndex().value();
208 attr.getType().getClassTy().getElementOffset(layout, memberIndex);
211 mlir::Type abiTy = lowerDataMemberType(
attr.getType(), typeConverter);
212 return cir::IntAttr::get(abiTy, memberOffset);
215mlir::TypedAttr LowerItaniumCXXABI::lowerMethodConstant(
216 cir::MethodAttr attr,
const mlir::DataLayout &layout,
217 const mlir::TypeConverter &typeConverter)
const {
220 auto loweredMethodTy = mlir::cast<cir::StructType>(
221 lowerMethodType(
attr.getType(), typeConverter));
223 auto zero = cir::IntAttr::get(ptrdiffCIRTy, 0);
244 return cir::ConstRecordAttr::get(
245 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {zero, zero}));
248 if (
attr.isVirtual()) {
249 if (useARMMethodPtrABI) {
258 cir::IntAttr::get(ptrdiffCIRTy,
attr.getVtableOffset().value());
259 auto one = cir::IntAttr::get(ptrdiffCIRTy, 1);
260 return cir::ConstRecordAttr::get(
261 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {ptr, one}));
272 cir::IntAttr::get(ptrdiffCIRTy, 1 +
attr.getVtableOffset().value());
273 return cir::ConstRecordAttr::get(
274 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {ptr, zero}));
282 auto ptr = cir::GlobalViewAttr::get(ptrdiffCIRTy,
attr.getSymbol().value());
283 return cir::ConstRecordAttr::get(
284 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {ptr, zero}));
287mlir::Operation *LowerItaniumCXXABI::lowerGetRuntimeMember(
288 cir::GetRuntimeMemberOp op, mlir::Type loweredResultTy,
289 mlir::Value loweredAddr, mlir::Value loweredMember,
290 mlir::OpBuilder &builder)
const {
291 auto byteTy = cir::IntType::get(op.getContext(), 8,
true);
292 auto bytePtrTy = cir::PointerType::get(
294 mlir::cast<cir::PointerType>(op.getAddr().getType()).getAddrSpace());
295 auto objectBytesPtr = cir::CastOp::create(
296 builder, op.getLoc(), bytePtrTy, cir::CastKind::bitcast, op.getAddr());
297 auto memberBytesPtr = cir::PtrStrideOp::create(
298 builder, op.getLoc(), bytePtrTy, objectBytesPtr, loweredMember);
299 return cir::CastOp::create(builder, op.getLoc(), op.getType(),
300 cir::CastKind::bitcast, memberBytesPtr);
303void LowerItaniumCXXABI::lowerGetMethod(
304 cir::GetMethodOp op, mlir::Value &callee, mlir::Value &thisArg,
305 mlir::Value loweredMethod, mlir::Value loweredObjectPtr,
306 mlir::ConversionPatternRewriter &rewriter)
const {
328 mlir::ImplicitLocOpBuilder locBuilder(op.getLoc(), rewriter);
329 mlir::Type calleePtrTy = op.getCallee().getType();
332 mlir::Value ptrdiffOne =
333 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 1));
336 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredMethod, 1);
337 mlir::Value adj = rawAdj;
338 if (useARMMethodPtrABI)
339 adj = cir::ShiftOp::create(locBuilder, ptrdiffCIRTy, adj, ptrdiffOne,
343 mlir::Type thisVoidPtrTy =
344 cir::PointerType::get(cir::VoidType::get(locBuilder.getContext()),
345 op.getObject().getType().getAddrSpace());
346 mlir::Value thisVoidPtr = cir::CastOp::create(
347 locBuilder, thisVoidPtrTy, cir::CastKind::bitcast, loweredObjectPtr);
349 cir::PtrStrideOp::create(locBuilder, thisVoidPtrTy, thisVoidPtr, adj);
353 mlir::Value methodPtrField =
354 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredMethod, 0);
355 mlir::Value virtualBit;
356 if (useARMMethodPtrABI)
357 virtualBit = cir::AndOp::create(locBuilder, rawAdj, ptrdiffOne);
359 virtualBit = cir::AndOp::create(locBuilder, methodPtrField, ptrdiffOne);
360 mlir::Value isVirtual = cir::CmpOp::create(locBuilder, cir::CmpOpKind::eq,
361 virtualBit, ptrdiffOne);
367 auto buildVirtualCallee = [&](mlir::OpBuilder &b, mlir::Location loc) {
371 cir::PointerType::get(cir::IntType::get(b.getContext(), 8,
true));
372 auto vtablePtrPtrTy = cir::PointerType::get(
373 vtablePtrTy, op.getObject().getType().getAddrSpace());
374 auto vtablePtrPtr = cir::CastOp::create(b, loc, vtablePtrPtrTy,
375 cir::CastKind::bitcast, thisArg);
377 mlir::Value vtablePtr =
378 cir::LoadOp::create(b, loc, vtablePtrPtr,
false,
381 cir::SyncScopeKindAttr{},
382 cir::MemOrderAttr());
387 mlir::Value vtableOffset = methodPtrField;
388 if (!useARMMethodPtrABI)
389 vtableOffset = cir::SubOp::create(b, loc, vtableOffset.getType(),
390 vtableOffset, ptrdiffOne);
391 if (use32BitVTableOffsetABI)
392 llvm_unreachable(
"AppleARM64 method ptr abi NYI");
400 mlir::Value vfpAddr = cir::PtrStrideOp::create(locBuilder, vtablePtrTy,
401 vtablePtr, vtableOffset);
402 auto vfpPtrTy = cir::PointerType::get(calleePtrTy);
403 mlir::Value vfpPtr = cir::CastOp::create(locBuilder, vfpPtrTy,
404 cir::CastKind::bitcast, vfpAddr);
405 auto fnPtr = cir::LoadOp::create(b, loc, vfpPtr,
408 cir::SyncScopeKindAttr{},
409 cir::MemOrderAttr());
411 cir::YieldOp::create(b, loc, fnPtr.getResult());
415 callee = cir::TernaryOp::create(
416 locBuilder, isVirtual, buildVirtualCallee,
418 [&](mlir::OpBuilder &b, mlir::Location loc) {
419 auto fnPtr = cir::CastOp::create(b, loc, calleePtrTy,
420 cir::CastKind::int_to_ptr,
422 cir::YieldOp::create(b, loc, fnPtr.getResult());
428 mlir::Value loweredSrc,
430 bool isDerivedToBase,
431 mlir::OpBuilder &builder) {
434 mlir::Location loc = op->getLoc();
435 mlir::Type ty = loweredSrc.getType();
437 auto getConstantInt = [&](int64_t value) -> cir::ConstantOp {
438 return cir::ConstantOp::create(builder, loc, cir::IntAttr::get(ty, value));
441 cir::ConstantOp nullValue = getConstantInt(-1);
442 auto isNull = cir::CmpOp::create(builder, loc, cir::CmpOpKind::eq, loweredSrc,
445 cir::ConstantOp offsetValue = getConstantInt(offset);
446 mlir::Value adjustedPtr;
447 if (isDerivedToBase) {
448 auto subOp = cir::SubOp::create(builder, loc, ty, loweredSrc, offsetValue);
449 subOp.setNoSignedWrap(
true);
452 auto addOp = cir::AddOp::create(builder, loc, ty, loweredSrc, offsetValue);
453 addOp.setNoSignedWrap(
true);
457 return cir::SelectOp::create(builder, loc, ty, isNull, loweredSrc,
462LowerItaniumCXXABI::lowerBaseDataMember(cir::BaseDataMemberOp op,
463 mlir::Value loweredSrc,
464 mlir::OpBuilder &builder)
const {
465 return lowerDataMemberCast(op, loweredSrc, op.getOffset().getSExtValue(),
470LowerItaniumCXXABI::lowerDerivedDataMember(cir::DerivedDataMemberOp op,
471 mlir::Value loweredSrc,
472 mlir::OpBuilder &builder)
const {
478 std::int64_t offset,
bool isDerivedToBase,
479 bool useARMMethodPtrABI,
481 mlir::OpBuilder &builder) {
487 if (useARMMethodPtrABI)
491 auto adjField = cir::ExtractMemberOp::create(builder, op->getLoc(),
492 ptrdiffCIRTy, loweredSrc, 1);
494 auto offsetValue = cir::ConstantOp::create(
495 builder, op->getLoc(), cir::IntAttr::get(ptrdiffCIRTy, offset));
496 mlir::Value adjustedAdjField;
497 if (isDerivedToBase) {
498 auto subOp = cir::SubOp::create(builder, op->getLoc(), ptrdiffCIRTy,
499 adjField, offsetValue);
500 subOp.setNoSignedWrap(
true);
501 adjustedAdjField = subOp;
503 auto addOp = cir::AddOp::create(builder, op->getLoc(), ptrdiffCIRTy,
504 adjField, offsetValue);
505 addOp.setNoSignedWrap(
true);
506 adjustedAdjField = addOp;
509 return cir::InsertMemberOp::create(builder, op->getLoc(), loweredSrc, 1,
514LowerItaniumCXXABI::lowerBaseMethod(cir::BaseMethodOp op,
515 mlir::Value loweredSrc,
516 mlir::OpBuilder &builder)
const {
517 return lowerMethodCast(op, loweredSrc, op.getOffset().getSExtValue(),
518 true, useARMMethodPtrABI, lm,
523LowerItaniumCXXABI::lowerDerivedMethod(cir::DerivedMethodOp op,
524 mlir::Value loweredSrc,
525 mlir::OpBuilder &builder)
const {
527 false, useARMMethodPtrABI, lm,
532LowerItaniumCXXABI::lowerDataMemberCmp(cir::CmpOp op, mlir::Value loweredLhs,
533 mlir::Value loweredRhs,
534 mlir::OpBuilder &builder)
const {
535 return cir::CmpOp::create(builder, op.getLoc(), op.getKind(), loweredLhs,
539mlir::Value LowerItaniumCXXABI::lowerMethodCmp(cir::CmpOp op,
540 mlir::Value loweredLhs,
541 mlir::Value loweredRhs,
542 mlir::OpBuilder &builder)
const {
543 assert(op.getKind() == cir::CmpOpKind::eq ||
544 op.getKind() == cir::CmpOpKind::ne);
546 mlir::ImplicitLocOpBuilder locBuilder(op.getLoc(), builder);
548 mlir::Value ptrdiffZero =
549 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 0));
551 mlir::Value lhsPtrField =
552 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredLhs, 0);
553 mlir::Value rhsPtrField =
554 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredRhs, 0);
556 cir::CmpOp::create(locBuilder, op.getKind(), lhsPtrField, rhsPtrField);
557 mlir::Value ptrCmpToNull =
558 cir::CmpOp::create(locBuilder, op.getKind(), lhsPtrField, ptrdiffZero);
560 mlir::Value lhsAdjField =
561 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredLhs, 1);
562 mlir::Value rhsAdjField =
563 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredRhs, 1);
565 cir::CmpOp::create(locBuilder, op.getKind(), lhsAdjField, rhsAdjField);
567 auto create_and = [&](mlir::Value lhs, mlir::Value rhs) {
568 return cir::AndOp::create(locBuilder, lhs.getType(), lhs, rhs);
570 auto create_or = [&](mlir::Value lhs, mlir::Value rhs) {
571 return cir::OrOp::create(locBuilder, lhs.getType(), lhs, rhs);
576 if (useARMMethodPtrABI) {
578 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 1));
594 mlir::Value orAdj = create_or(lhsAdjField, rhsAdjField);
595 mlir::Value orAdjAnd1 = create_and(orAdj, one);
596 mlir::Value orAdjAnd1CmpZero =
597 cir::CmpOp::create(locBuilder, op.getKind(), orAdjAnd1, ptrdiffZero);
599 if (op.getKind() == cir::CmpOpKind::eq)
600 ptrCmpToNull = create_and(ptrCmpToNull, orAdjAnd1CmpZero);
602 ptrCmpToNull = create_or(ptrCmpToNull, orAdjAnd1CmpZero);
606 if (op.getKind() == cir::CmpOpKind::eq) {
608 result = create_and(ptrCmp, create_or(ptrCmpToNull, adjCmp));
611 result = create_or(ptrCmp, create_and(ptrCmpToNull, adjCmp));
617mlir::Value LowerItaniumCXXABI::lowerDataMemberBitcast(
618 cir::CastOp op, mlir::Type loweredDstTy, mlir::Value loweredSrc,
619 mlir::OpBuilder &builder)
const {
620 if (loweredSrc.getType() == loweredDstTy)
623 return cir::CastOp::create(builder, op.getLoc(), loweredDstTy,
624 cir::CastKind::bitcast, loweredSrc);
627mlir::Value LowerItaniumCXXABI::lowerDataMemberToBoolCast(
628 cir::CastOp op, mlir::Value loweredSrc, mlir::OpBuilder &builder)
const {
632 auto nullValue = cir::ConstantOp::create(builder, op.getLoc(), nullAttr);
633 return cir::CmpOp::create(builder, op.getLoc(), cir::CmpOpKind::ne,
634 loweredSrc, nullValue);
638LowerItaniumCXXABI::lowerMethodBitcast(cir::CastOp op, mlir::Type loweredDstTy,
639 mlir::Value loweredSrc,
640 mlir::OpBuilder &builder)
const {
641 if (loweredSrc.getType() == loweredDstTy)
647mlir::Value LowerItaniumCXXABI::lowerMethodToBoolCast(
648 cir::CastOp op, mlir::Value loweredSrc, mlir::OpBuilder &builder)
const {
649 mlir::ImplicitLocOpBuilder locBuilder(op.getLoc(), builder);
657 mlir::Value ptrdiffZero =
658 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 0));
659 mlir::Value ptrField =
660 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredSrc, 0);
663 cir::CmpOp::create(locBuilder, cir::CmpOpKind::ne, ptrField, ptrdiffZero);
667 if (useARMMethodPtrABI) {
669 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 1));
671 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredSrc, 1);
672 mlir::Value virtualBit =
673 cir::AndOp::create(locBuilder, ptrdiffCIRTy, adj, one);
674 mlir::Value isVirtual = cir::CmpOp::create(locBuilder, cir::CmpOpKind::ne,
675 virtualBit, ptrdiffZero);
676 result = cir::OrOp::create(locBuilder, result, isVirtual);
683 mlir::FlatSymbolRefAttr badCastFuncRef) {
684 auto callOp = cir::CallOp::create(builder, loc, badCastFuncRef,
687 callOp->setAttr(cir::CIRDialect::getNoReturnAttrName(),
688 builder.getUnitAttr());
690 cir::UnreachableOp::create(builder, loc);
691 builder.clearInsertionPoint();
695 mlir::OpBuilder &builder) {
696 mlir::Location loc = op->getLoc();
697 mlir::Value srcValue = op.getSrc();
698 cir::DynamicCastInfoAttr castInfo = op.getInfo().value();
704 cir::PointerType::get(cir::VoidType::get(builder.getContext()));
706 mlir::Value srcPtr = cir::CastOp::create(builder, loc, voidPtrTy,
707 cir::CastKind::bitcast, srcValue);
708 mlir::Value srcRtti =
709 cir::ConstantOp::create(builder, loc, castInfo.getSrcRtti());
710 mlir::Value destRtti =
711 cir::ConstantOp::create(builder, loc, castInfo.getDestRtti());
712 mlir::Value offsetHint =
713 cir::ConstantOp::create(builder, loc, castInfo.getOffsetHint());
715 mlir::FlatSymbolRefAttr dynCastFuncRef = castInfo.getRuntimeFunc();
716 mlir::Value dynCastFuncArgs[4] = {srcPtr, srcRtti, destRtti, offsetHint};
718 mlir::Value castedPtr = cir::CallOp::create(builder, loc, dynCastFuncRef,
719 voidPtrTy, dynCastFuncArgs)
722 assert(mlir::isa<cir::PointerType>(castedPtr.getType()) &&
723 "the return value of __dynamic_cast should be a ptr");
727 if (op.isRefCast()) {
729 mlir::Value null = cir::ConstantOp::create(
731 cir::ConstPtrAttr::get(castedPtr.getType(),
732 builder.getI64IntegerAttr(0)));
733 mlir::Value castedPtrIsNull =
734 cir::CmpOp::create(builder, loc, cir::CmpOpKind::eq, castedPtr, null);
735 cir::IfOp::create(builder, loc, castedPtrIsNull,
false,
736 [&](mlir::OpBuilder &, mlir::Location) {
738 castInfo.getBadCastFunc());
744 return cir::CastOp::create(builder, loc, op.getType(), cir::CastKind::bitcast,
750 mlir::Location loc = op.getLoc();
751 bool vtableUsesRelativeLayout = op.getRelativeLayout();
756 mlir::Type vtableElemTy;
757 uint64_t vtableElemAlign;
758 if (vtableUsesRelativeLayout) {
760 cir::IntType::get(builder.getContext(), 32,
true);
764 vtableElemAlign = llvm::divideCeil(
768 mlir::Type vtableElemPtrTy = cir::PointerType::get(vtableElemTy);
769 mlir::Type i64Ty = cir::IntType::get(builder.getContext(), 64,
775 auto vptrPtr = cir::VTableGetVPtrOp::create(builder, loc, op.getSrc());
776 mlir::Value vptr = cir::LoadOp::create(
777 builder, loc, vptrPtr,
780 builder.getI64IntegerAttr(vtableElemAlign),
781 cir::SyncScopeKindAttr(),
782 cir::MemOrderAttr());
783 mlir::Value elementPtr = cir::CastOp::create(builder, loc, vtableElemPtrTy,
784 cir::CastKind::bitcast, vptr);
785 mlir::Value minusTwo =
786 cir::ConstantOp::create(builder, loc, cir::IntAttr::get(i64Ty, -2));
787 mlir::Value offsetToTopSlotPtr = cir::PtrStrideOp::create(
788 builder, loc, vtableElemPtrTy, elementPtr, minusTwo);
789 mlir::Value offsetToTop = cir::LoadOp::create(
790 builder, loc, offsetToTopSlotPtr,
793 builder.getI64IntegerAttr(vtableElemAlign),
794 cir::SyncScopeKindAttr(),
795 cir::MemOrderAttr());
798 cir::PointerType::get(cir::VoidType::get(builder.getContext()));
803 cir::PointerType::get(cir::IntType::get(builder.getContext(), 8,
805 mlir::Value srcBytePtr = cir::CastOp::create(
806 builder, loc, u8PtrTy, cir::CastKind::bitcast, op.getSrc());
808 cir::PtrStrideOp::create(builder, loc, u8PtrTy, srcBytePtr, offsetToTop);
810 return cir::CastOp::create(builder, loc, voidPtrTy, cir::CastKind::bitcast,
815LowerItaniumCXXABI::lowerDynamicCast(cir::DynamicCastOp op,
816 mlir::OpBuilder &builder)
const {
817 mlir::Location loc = op->getLoc();
818 mlir::Value srcValue = op.getSrc();
823 return buildDynamicCastAfterNullCheck(op, builder);
825 mlir::Value srcValueIsNotNull = cir::CastOp::create(
826 builder, loc, cir::BoolType::get(builder.getContext()),
827 cir::CastKind::ptr_to_bool, srcValue);
828 return cir::TernaryOp::create(
829 builder, loc, srcValueIsNotNull,
830 [&](mlir::OpBuilder &, mlir::Location) {
831 mlir::Value castedValue =
833 ? buildDynamicCastToVoidAfterNullCheck(op, lm, builder)
834 : buildDynamicCastAfterNullCheck(op, builder);
835 cir::YieldOp::create(builder, loc, castedValue);
837 [&](mlir::OpBuilder &, mlir::Location) {
838 mlir::Value null = cir::ConstantOp::create(
840 cir::ConstPtrAttr::get(op.getType(),
841 builder.getI64IntegerAttr(0)));
842 cir::YieldOp::create(builder, loc, null);
847LowerItaniumCXXABI::lowerVTableGetTypeInfo(cir::VTableGetTypeInfoOp op,
848 mlir::OpBuilder &builder)
const {
849 mlir::Location loc = op->getLoc();
850 auto offset = cir::ConstantOp::create(
854 auto vptrCast = cir::CastOp::create(builder, loc, op.getType(),
855 cir::CastKind::bitcast, op.getVptr());
857 return cir::PtrStrideOp::create(builder, loc, vptrCast.getType(), vptrCast,
862clang::CharUnits LowerItaniumCXXABI::getArrayCookieSizeImpl(
863 mlir::Type elementType,
const mlir::DataLayout &dataLayout)
const {
866 clang::CharUnits sizeOfSizeT =
869 dataLayout.getTypePreferredAlignment(elementType));
870 return std::max(sizeOfSizeT, eltAlign);
873mlir::Value LowerItaniumCXXABI::readArrayCookieImpl(
874 mlir::Location loc, mlir::Value allocPtr, clang::CharUnits cookieSize,
875 clang::CharUnits cookieAlignment,
const mlir::DataLayout &dataLayout,
876 CIRBaseBuilderTy &builder)
const {
877 unsigned ptrSizeInBits = getPtrSizeInBits();
878 auto u8PtrTy = builder.getPointerTo(builder.getUIntNTy(8));
879 auto ptrDiffTy = builder.getSIntNTy(ptrSizeInBits);
880 auto sizeTy = builder.getUIntNTy(ptrSizeInBits);
883 clang::CharUnits sizeOfSizeT =
885 clang::CharUnits countOffset = cookieSize - sizeOfSizeT;
887 mlir::Value countBytePtr = allocPtr;
888 clang::CharUnits countAlignment = cookieAlignment;
889 if (!countOffset.
isZero()) {
890 mlir::Value offsetVal = cir::ConstantOp::create(
891 builder, loc, cir::IntAttr::get(ptrDiffTy, countOffset.
getQuantity()));
893 cir::PtrStrideOp::create(builder, loc, u8PtrTy, allocPtr, offsetVal);
897 auto countPtrTy = cir::PointerType::get(sizeTy);
898 mlir::Value countPtr = cir::CastOp::create(
899 builder, loc, countPtrTy, cir::CastKind::bitcast, countBytePtr);
900 return cir::LoadOp::create(
901 builder, loc, countPtr,
false,
false,
902 builder.getI64IntegerAttr(countAlignment.
getQuantity()),
903 cir::SyncScopeKindAttr(), cir::MemOrderAttr());
mlir::MLIRContext * getMLIRContext()
clang::TargetCXXABI::Kind getCXXABIKind() const
const clang::TargetInfo & getTarget() const
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.
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 ----------------------------—===//