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()) {
208 mlir::Type currentTy =
attr.getType().getClassTy();
210 auto recTy = mlir::cast<cir::RecordType>(currentTy);
211 memberOffset +=
static_cast<int64_t>(recTy.getElementOffset(layout, idx));
212 currentTy = recTy.getMembers()[idx];
216 mlir::Type abiTy = lowerDataMemberType(
attr.getType(), typeConverter);
217 return cir::IntAttr::get(abiTy, memberOffset);
220mlir::TypedAttr LowerItaniumCXXABI::lowerMethodConstant(
221 cir::MethodAttr attr,
const mlir::DataLayout &layout,
222 const mlir::TypeConverter &typeConverter)
const {
225 auto loweredMethodTy = mlir::cast<cir::StructType>(
226 lowerMethodType(
attr.getType(), typeConverter));
228 auto zero = cir::IntAttr::get(ptrdiffCIRTy, 0);
249 return cir::ConstRecordAttr::get(
250 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {zero, zero}));
253 if (
attr.isVirtual()) {
254 if (useARMMethodPtrABI) {
263 cir::IntAttr::get(ptrdiffCIRTy,
attr.getVtableOffset().value());
264 auto one = cir::IntAttr::get(ptrdiffCIRTy, 1);
265 return cir::ConstRecordAttr::get(
266 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {ptr, one}));
277 cir::IntAttr::get(ptrdiffCIRTy, 1 +
attr.getVtableOffset().value());
278 return cir::ConstRecordAttr::get(
279 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {ptr, zero}));
287 auto ptr = cir::GlobalViewAttr::get(ptrdiffCIRTy,
attr.getSymbol().value());
288 return cir::ConstRecordAttr::get(
289 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {ptr, zero}));
292mlir::Operation *LowerItaniumCXXABI::lowerGetRuntimeMember(
293 cir::GetRuntimeMemberOp op, mlir::Type loweredResultTy,
294 mlir::Value loweredAddr, mlir::Value loweredMember,
295 mlir::OpBuilder &builder)
const {
296 auto byteTy = cir::IntType::get(op.getContext(), 8,
true);
297 auto bytePtrTy = cir::PointerType::get(
299 mlir::cast<cir::PointerType>(op.getAddr().getType()).getAddrSpace());
300 auto objectBytesPtr = cir::CastOp::create(
301 builder, op.getLoc(), bytePtrTy, cir::CastKind::bitcast, op.getAddr());
302 auto memberBytesPtr = cir::PtrStrideOp::create(
303 builder, op.getLoc(), bytePtrTy, objectBytesPtr, loweredMember);
304 return cir::CastOp::create(builder, op.getLoc(), op.getType(),
305 cir::CastKind::bitcast, memberBytesPtr);
308void LowerItaniumCXXABI::lowerGetMethod(
309 cir::GetMethodOp op, mlir::Value &callee, mlir::Value &thisArg,
310 mlir::Value loweredMethod, mlir::Value loweredObjectPtr,
311 mlir::ConversionPatternRewriter &rewriter)
const {
333 mlir::ImplicitLocOpBuilder locBuilder(op.getLoc(), rewriter);
334 mlir::Type calleePtrTy = op.getCallee().getType();
337 mlir::Value ptrdiffOne =
338 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 1));
341 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredMethod, 1);
342 mlir::Value adj = rawAdj;
343 if (useARMMethodPtrABI)
344 adj = cir::ShiftOp::create(locBuilder, ptrdiffCIRTy, adj, ptrdiffOne,
348 mlir::Type thisVoidPtrTy =
349 cir::PointerType::get(cir::VoidType::get(locBuilder.getContext()),
350 op.getObject().getType().getAddrSpace());
351 mlir::Value thisVoidPtr = cir::CastOp::create(
352 locBuilder, thisVoidPtrTy, cir::CastKind::bitcast, loweredObjectPtr);
354 cir::PtrStrideOp::create(locBuilder, thisVoidPtrTy, thisVoidPtr, adj);
358 mlir::Value methodPtrField =
359 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredMethod, 0);
360 mlir::Value virtualBit;
361 if (useARMMethodPtrABI)
362 virtualBit = cir::AndOp::create(locBuilder, rawAdj, ptrdiffOne);
364 virtualBit = cir::AndOp::create(locBuilder, methodPtrField, ptrdiffOne);
365 mlir::Value isVirtual = cir::CmpOp::create(locBuilder, cir::CmpOpKind::eq,
366 virtualBit, ptrdiffOne);
372 auto buildVirtualCallee = [&](mlir::OpBuilder &b, mlir::Location loc) {
376 cir::PointerType::get(cir::IntType::get(b.getContext(), 8,
true));
377 auto vtablePtrPtrTy = cir::PointerType::get(
378 vtablePtrTy, op.getObject().getType().getAddrSpace());
379 auto vtablePtrPtr = cir::CastOp::create(b, loc, vtablePtrPtrTy,
380 cir::CastKind::bitcast, thisArg);
382 mlir::Value vtablePtr =
383 cir::LoadOp::create(b, loc, vtablePtrPtr,
false,
387 cir::SyncScopeKindAttr{},
394 mlir::Value vtableOffset = methodPtrField;
395 if (!useARMMethodPtrABI)
396 vtableOffset = cir::SubOp::create(b, loc, vtableOffset.getType(),
397 vtableOffset, ptrdiffOne);
398 if (use32BitVTableOffsetABI)
399 llvm_unreachable(
"AppleARM64 method ptr abi NYI");
407 mlir::Value vfpAddr = cir::PtrStrideOp::create(locBuilder, vtablePtrTy,
408 vtablePtr, vtableOffset);
409 auto vfpPtrTy = cir::PointerType::get(calleePtrTy);
410 mlir::Value vfpPtr = cir::CastOp::create(locBuilder, vfpPtrTy,
411 cir::CastKind::bitcast, vfpAddr);
412 auto fnPtr = cir::LoadOp::create(b, loc, vfpPtr,
416 cir::SyncScopeKindAttr{},
420 cir::YieldOp::create(b, loc, fnPtr.getResult());
424 callee = cir::TernaryOp::create(
425 locBuilder, isVirtual, buildVirtualCallee,
427 [&](mlir::OpBuilder &b, mlir::Location loc) {
428 auto fnPtr = cir::CastOp::create(b, loc, calleePtrTy,
429 cir::CastKind::int_to_ptr,
431 cir::YieldOp::create(b, loc, fnPtr.getResult());
437 mlir::Value loweredSrc,
439 bool isDerivedToBase,
440 mlir::OpBuilder &builder) {
443 mlir::Location loc = op->getLoc();
444 mlir::Type ty = loweredSrc.getType();
446 auto getConstantInt = [&](int64_t value) -> cir::ConstantOp {
447 return cir::ConstantOp::create(builder, loc, cir::IntAttr::get(ty, value));
450 cir::ConstantOp nullValue = getConstantInt(-1);
451 auto isNull = cir::CmpOp::create(builder, loc, cir::CmpOpKind::eq, loweredSrc,
454 cir::ConstantOp offsetValue = getConstantInt(offset);
455 mlir::Value adjustedPtr;
456 if (isDerivedToBase) {
457 auto subOp = cir::SubOp::create(builder, loc, ty, loweredSrc, offsetValue);
458 subOp.setNoSignedWrap(
true);
461 auto addOp = cir::AddOp::create(builder, loc, ty, loweredSrc, offsetValue);
462 addOp.setNoSignedWrap(
true);
466 return cir::SelectOp::create(builder, loc, ty, isNull, loweredSrc,
471LowerItaniumCXXABI::lowerBaseDataMember(cir::BaseDataMemberOp op,
472 mlir::Value loweredSrc,
473 mlir::OpBuilder &builder)
const {
474 return lowerDataMemberCast(op, loweredSrc, op.getOffset().getSExtValue(),
479LowerItaniumCXXABI::lowerDerivedDataMember(cir::DerivedDataMemberOp op,
480 mlir::Value loweredSrc,
481 mlir::OpBuilder &builder)
const {
487 std::int64_t offset,
bool isDerivedToBase,
488 bool useARMMethodPtrABI,
490 mlir::OpBuilder &builder) {
496 if (useARMMethodPtrABI)
500 auto adjField = cir::ExtractMemberOp::create(builder, op->getLoc(),
501 ptrdiffCIRTy, loweredSrc, 1);
503 auto offsetValue = cir::ConstantOp::create(
504 builder, op->getLoc(), cir::IntAttr::get(ptrdiffCIRTy, offset));
505 mlir::Value adjustedAdjField;
506 if (isDerivedToBase) {
507 auto subOp = cir::SubOp::create(builder, op->getLoc(), ptrdiffCIRTy,
508 adjField, offsetValue);
509 subOp.setNoSignedWrap(
true);
510 adjustedAdjField = subOp;
512 auto addOp = cir::AddOp::create(builder, op->getLoc(), ptrdiffCIRTy,
513 adjField, offsetValue);
514 addOp.setNoSignedWrap(
true);
515 adjustedAdjField = addOp;
518 return cir::InsertMemberOp::create(builder, op->getLoc(), loweredSrc, 1,
523LowerItaniumCXXABI::lowerBaseMethod(cir::BaseMethodOp op,
524 mlir::Value loweredSrc,
525 mlir::OpBuilder &builder)
const {
526 return lowerMethodCast(op, loweredSrc, op.getOffset().getSExtValue(),
527 true, useARMMethodPtrABI, lm,
532LowerItaniumCXXABI::lowerDerivedMethod(cir::DerivedMethodOp op,
533 mlir::Value loweredSrc,
534 mlir::OpBuilder &builder)
const {
536 false, useARMMethodPtrABI, lm,
541LowerItaniumCXXABI::lowerDataMemberCmp(cir::CmpOp op, mlir::Value loweredLhs,
542 mlir::Value loweredRhs,
543 mlir::OpBuilder &builder)
const {
544 return cir::CmpOp::create(builder, op.getLoc(), op.getKind(), loweredLhs,
548mlir::Value LowerItaniumCXXABI::lowerMethodCmp(cir::CmpOp op,
549 mlir::Value loweredLhs,
550 mlir::Value loweredRhs,
551 mlir::OpBuilder &builder)
const {
552 assert(op.getKind() == cir::CmpOpKind::eq ||
553 op.getKind() == cir::CmpOpKind::ne);
555 mlir::ImplicitLocOpBuilder locBuilder(op.getLoc(), builder);
557 mlir::Value ptrdiffZero =
558 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 0));
560 mlir::Value lhsPtrField =
561 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredLhs, 0);
562 mlir::Value rhsPtrField =
563 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredRhs, 0);
565 cir::CmpOp::create(locBuilder, op.getKind(), lhsPtrField, rhsPtrField);
566 mlir::Value ptrCmpToNull =
567 cir::CmpOp::create(locBuilder, op.getKind(), lhsPtrField, ptrdiffZero);
569 mlir::Value lhsAdjField =
570 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredLhs, 1);
571 mlir::Value rhsAdjField =
572 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredRhs, 1);
574 cir::CmpOp::create(locBuilder, op.getKind(), lhsAdjField, rhsAdjField);
576 auto create_and = [&](mlir::Value lhs, mlir::Value rhs) {
577 return cir::AndOp::create(locBuilder, lhs.getType(), lhs, rhs);
579 auto create_or = [&](mlir::Value lhs, mlir::Value rhs) {
580 return cir::OrOp::create(locBuilder, lhs.getType(), lhs, rhs);
585 if (useARMMethodPtrABI) {
587 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 1));
603 mlir::Value orAdj = create_or(lhsAdjField, rhsAdjField);
604 mlir::Value orAdjAnd1 = create_and(orAdj, one);
605 mlir::Value orAdjAnd1CmpZero =
606 cir::CmpOp::create(locBuilder, op.getKind(), orAdjAnd1, ptrdiffZero);
608 if (op.getKind() == cir::CmpOpKind::eq)
609 ptrCmpToNull = create_and(ptrCmpToNull, orAdjAnd1CmpZero);
611 ptrCmpToNull = create_or(ptrCmpToNull, orAdjAnd1CmpZero);
615 if (op.getKind() == cir::CmpOpKind::eq) {
617 result = create_and(ptrCmp, create_or(ptrCmpToNull, adjCmp));
620 result = create_or(ptrCmp, create_and(ptrCmpToNull, adjCmp));
626mlir::Value LowerItaniumCXXABI::lowerDataMemberBitcast(
627 cir::CastOp op, mlir::Type loweredDstTy, mlir::Value loweredSrc,
628 mlir::OpBuilder &builder)
const {
629 if (loweredSrc.getType() == loweredDstTy)
632 return cir::CastOp::create(builder, op.getLoc(), loweredDstTy,
633 cir::CastKind::bitcast, loweredSrc);
636mlir::Value LowerItaniumCXXABI::lowerDataMemberToBoolCast(
637 cir::CastOp op, mlir::Value loweredSrc, mlir::OpBuilder &builder)
const {
641 auto nullValue = cir::ConstantOp::create(builder, op.getLoc(), nullAttr);
642 return cir::CmpOp::create(builder, op.getLoc(), cir::CmpOpKind::ne,
643 loweredSrc, nullValue);
647LowerItaniumCXXABI::lowerMethodBitcast(cir::CastOp op, mlir::Type loweredDstTy,
648 mlir::Value loweredSrc,
649 mlir::OpBuilder &builder)
const {
650 if (loweredSrc.getType() == loweredDstTy)
656mlir::Value LowerItaniumCXXABI::lowerMethodToBoolCast(
657 cir::CastOp op, mlir::Value loweredSrc, mlir::OpBuilder &builder)
const {
658 mlir::ImplicitLocOpBuilder locBuilder(op.getLoc(), builder);
666 mlir::Value ptrdiffZero =
667 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 0));
668 mlir::Value ptrField =
669 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredSrc, 0);
672 cir::CmpOp::create(locBuilder, cir::CmpOpKind::ne, ptrField, ptrdiffZero);
676 if (useARMMethodPtrABI) {
678 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 1));
680 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredSrc, 1);
681 mlir::Value virtualBit =
682 cir::AndOp::create(locBuilder, ptrdiffCIRTy, adj, one);
683 mlir::Value isVirtual = cir::CmpOp::create(locBuilder, cir::CmpOpKind::ne,
684 virtualBit, ptrdiffZero);
685 result = cir::OrOp::create(locBuilder, result, isVirtual);
692 mlir::FlatSymbolRefAttr badCastFuncRef) {
693 auto callOp = cir::CallOp::create(builder, loc, badCastFuncRef,
696 callOp->setAttr(cir::CIRDialect::getNoReturnAttrName(),
697 builder.getUnitAttr());
699 cir::UnreachableOp::create(builder, loc);
700 builder.clearInsertionPoint();
704 mlir::OpBuilder &builder) {
705 mlir::Location loc = op->getLoc();
706 mlir::Value srcValue = op.getSrc();
707 cir::DynamicCastInfoAttr castInfo = op.getInfo().value();
713 cir::PointerType::get(cir::VoidType::get(builder.getContext()));
715 mlir::Value srcPtr = cir::CastOp::create(builder, loc, voidPtrTy,
716 cir::CastKind::bitcast, srcValue);
717 mlir::Value srcRtti =
718 cir::ConstantOp::create(builder, loc, castInfo.getSrcRtti());
719 mlir::Value destRtti =
720 cir::ConstantOp::create(builder, loc, castInfo.getDestRtti());
721 mlir::Value offsetHint =
722 cir::ConstantOp::create(builder, loc, castInfo.getOffsetHint());
724 mlir::FlatSymbolRefAttr dynCastFuncRef = castInfo.getRuntimeFunc();
725 mlir::Value dynCastFuncArgs[4] = {srcPtr, srcRtti, destRtti, offsetHint};
727 mlir::Value castedPtr = cir::CallOp::create(builder, loc, dynCastFuncRef,
728 voidPtrTy, dynCastFuncArgs)
731 assert(mlir::isa<cir::PointerType>(castedPtr.getType()) &&
732 "the return value of __dynamic_cast should be a ptr");
736 if (op.isRefCast()) {
738 mlir::Value null = cir::ConstantOp::create(
740 cir::ConstPtrAttr::get(castedPtr.getType(),
741 builder.getI64IntegerAttr(0)));
742 mlir::Value castedPtrIsNull =
743 cir::CmpOp::create(builder, loc, cir::CmpOpKind::eq, castedPtr, null);
744 cir::IfOp::create(builder, loc, castedPtrIsNull,
false,
745 [&](mlir::OpBuilder &, mlir::Location) {
747 castInfo.getBadCastFunc());
753 return cir::CastOp::create(builder, loc, op.getType(), cir::CastKind::bitcast,
759 mlir::Location loc = op.getLoc();
760 bool vtableUsesRelativeLayout = op.getRelativeLayout();
765 mlir::Type vtableElemTy;
766 uint64_t vtableElemAlign;
767 if (vtableUsesRelativeLayout) {
769 cir::IntType::get(builder.getContext(), 32,
true);
773 vtableElemAlign = llvm::divideCeil(
777 mlir::Type vtableElemPtrTy = cir::PointerType::get(vtableElemTy);
778 mlir::Type i64Ty = cir::IntType::get(builder.getContext(), 64,
784 auto vptrPtr = cir::VTableGetVPtrOp::create(builder, loc, op.getSrc());
785 mlir::Value vptr = cir::LoadOp::create(
786 builder, loc, vptrPtr,
790 builder.getI64IntegerAttr(vtableElemAlign),
791 cir::SyncScopeKindAttr(),
794 mlir::Value elementPtr = cir::CastOp::create(builder, loc, vtableElemPtrTy,
795 cir::CastKind::bitcast, vptr);
796 mlir::Value minusTwo =
797 cir::ConstantOp::create(builder, loc, cir::IntAttr::get(i64Ty, -2));
798 mlir::Value offsetToTopSlotPtr = cir::PtrStrideOp::create(
799 builder, loc, vtableElemPtrTy, elementPtr, minusTwo);
800 mlir::Value offsetToTop = cir::LoadOp::create(
801 builder, loc, offsetToTopSlotPtr,
805 builder.getI64IntegerAttr(vtableElemAlign),
806 cir::SyncScopeKindAttr(),
811 cir::PointerType::get(cir::VoidType::get(builder.getContext()));
816 cir::PointerType::get(cir::IntType::get(builder.getContext(), 8,
818 mlir::Value srcBytePtr = cir::CastOp::create(
819 builder, loc, u8PtrTy, cir::CastKind::bitcast, op.getSrc());
821 cir::PtrStrideOp::create(builder, loc, u8PtrTy, srcBytePtr, offsetToTop);
823 return cir::CastOp::create(builder, loc, voidPtrTy, cir::CastKind::bitcast,
828LowerItaniumCXXABI::lowerDynamicCast(cir::DynamicCastOp op,
829 mlir::OpBuilder &builder)
const {
830 mlir::Location loc = op->getLoc();
831 mlir::Value srcValue = op.getSrc();
836 return buildDynamicCastAfterNullCheck(op, builder);
838 mlir::Value srcValueIsNotNull = cir::CastOp::create(
839 builder, loc, cir::BoolType::get(builder.getContext()),
840 cir::CastKind::ptr_to_bool, srcValue);
841 return cir::TernaryOp::create(
842 builder, loc, srcValueIsNotNull,
843 [&](mlir::OpBuilder &, mlir::Location) {
844 mlir::Value castedValue =
846 ? buildDynamicCastToVoidAfterNullCheck(op, lm, builder)
847 : buildDynamicCastAfterNullCheck(op, builder);
848 cir::YieldOp::create(builder, loc, castedValue);
850 [&](mlir::OpBuilder &, mlir::Location) {
851 mlir::Value null = cir::ConstantOp::create(
853 cir::ConstPtrAttr::get(op.getType(),
854 builder.getI64IntegerAttr(0)));
855 cir::YieldOp::create(builder, loc, null);
860LowerItaniumCXXABI::lowerVTableGetTypeInfo(cir::VTableGetTypeInfoOp op,
861 mlir::OpBuilder &builder)
const {
862 mlir::Location loc = op->getLoc();
863 auto offset = cir::ConstantOp::create(
867 auto vptrCast = cir::CastOp::create(builder, loc, op.getType(),
868 cir::CastKind::bitcast, op.getVptr());
870 return cir::PtrStrideOp::create(builder, loc, vptrCast.getType(), vptrCast,
875clang::CharUnits LowerItaniumCXXABI::getArrayCookieSizeImpl(
876 mlir::Type elementType,
const mlir::DataLayout &dataLayout)
const {
879 clang::CharUnits sizeOfSizeT =
882 dataLayout.getTypePreferredAlignment(elementType));
883 return std::max(sizeOfSizeT, eltAlign);
886mlir::Value LowerItaniumCXXABI::readArrayCookieImpl(
887 mlir::Location loc, mlir::Value allocPtr, clang::CharUnits cookieSize,
888 clang::CharUnits cookieAlignment,
const mlir::DataLayout &dataLayout,
889 CIRBaseBuilderTy &builder)
const {
890 unsigned ptrSizeInBits = getPtrSizeInBits();
892 auto ptrDiffTy = builder.
getSIntNTy(ptrSizeInBits);
893 auto sizeTy = builder.
getUIntNTy(ptrSizeInBits);
896 clang::CharUnits sizeOfSizeT =
898 clang::CharUnits countOffset = cookieSize - sizeOfSizeT;
900 mlir::Value countBytePtr = allocPtr;
901 clang::CharUnits countAlignment = cookieAlignment;
902 if (!countOffset.
isZero()) {
903 mlir::Value offsetVal = cir::ConstantOp::create(
904 builder, loc, cir::IntAttr::get(ptrDiffTy, countOffset.
getQuantity()));
906 cir::PtrStrideOp::create(builder, loc, u8PtrTy, allocPtr, offsetVal);
910 auto countPtrTy = cir::PointerType::get(sizeTy);
911 mlir::Value countPtr = cir::CastOp::create(
912 builder, loc, countPtrTy, cir::CastKind::bitcast, countBytePtr);
913 return cir::LoadOp::create(
914 builder, loc, countPtr,
false,
false,
916 builder.getI64IntegerAttr(countAlignment.
getQuantity()),
917 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
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 ----------------------------—===//