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 return cir::StructType::get(
type.getContext(), {ptrdiffCIRTy, ptrdiffCIRTy},
198mlir::TypedAttr LowerItaniumCXXABI::lowerDataMemberConstant(
199 cir::DataMemberAttr attr,
const mlir::DataLayout &layout,
200 const mlir::TypeConverter &typeConverter)
const {
202 if (
attr.isNullPtr()) {
212 mlir::Type currentTy =
attr.getType().getClassTy();
214 auto recTy = mlir::cast<cir::RecordType>(currentTy);
215 memberOffset +=
static_cast<int64_t>(recTy.getElementOffset(layout, idx));
216 currentTy = recTy.getMembers()[idx];
220 mlir::Type abiTy = lowerDataMemberType(
attr.getType(), typeConverter);
221 return cir::IntAttr::get(abiTy, memberOffset);
224mlir::TypedAttr LowerItaniumCXXABI::lowerDataMemberOffsetConstant(
225 cir::DataMemberOffsetAttr attr,
const mlir::DataLayout &layout,
226 const mlir::TypeConverter &typeConverter)
const {
231 mlir::Type abiTy = lowerDataMemberType(
attr.getType(), typeConverter);
232 return cir::IntAttr::get(abiTy,
static_cast<int64_t>(
attr.getOffset()));
235mlir::TypedAttr LowerItaniumCXXABI::lowerMethodConstant(
236 cir::MethodAttr attr,
const mlir::DataLayout &layout,
237 const mlir::TypeConverter &typeConverter)
const {
240 auto loweredMethodTy = mlir::cast<cir::StructType>(
241 lowerMethodType(
attr.getType(), typeConverter));
243 auto zero = cir::IntAttr::get(ptrdiffCIRTy, 0);
264 return cir::ConstRecordAttr::get(
265 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {zero, zero}));
268 if (
attr.isVirtual()) {
269 if (useARMMethodPtrABI) {
278 cir::IntAttr::get(ptrdiffCIRTy,
attr.getVtableOffset().value());
279 auto one = cir::IntAttr::get(ptrdiffCIRTy, 1);
280 return cir::ConstRecordAttr::get(
281 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {ptr, one}));
292 cir::IntAttr::get(ptrdiffCIRTy, 1 +
attr.getVtableOffset().value());
293 return cir::ConstRecordAttr::get(
294 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {ptr, zero}));
302 auto ptr = cir::GlobalViewAttr::get(ptrdiffCIRTy,
attr.getSymbol().value());
303 return cir::ConstRecordAttr::get(
304 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {ptr, zero}));
307mlir::Operation *LowerItaniumCXXABI::lowerGetRuntimeMember(
308 cir::GetRuntimeMemberOp op, mlir::Type loweredResultTy,
309 mlir::Value loweredAddr, mlir::Value loweredMember,
310 mlir::OpBuilder &builder)
const {
311 auto byteTy = cir::IntType::get(op.getContext(), 8,
true);
312 auto bytePtrTy = cir::PointerType::get(
314 mlir::cast<cir::PointerType>(op.getAddr().getType()).getAddrSpace());
315 auto objectBytesPtr = cir::CastOp::create(
316 builder, op.getLoc(), bytePtrTy, cir::CastKind::bitcast, op.getAddr());
317 auto memberBytesPtr = cir::PtrStrideOp::create(
318 builder, op.getLoc(), bytePtrTy, objectBytesPtr, loweredMember);
319 return cir::CastOp::create(builder, op.getLoc(), op.getType(),
320 cir::CastKind::bitcast, memberBytesPtr);
323void LowerItaniumCXXABI::lowerGetMethod(
324 cir::GetMethodOp op, mlir::Value &callee, mlir::Value &thisArg,
325 mlir::Value loweredMethod, mlir::Value loweredObjectPtr,
326 mlir::ConversionPatternRewriter &rewriter)
const {
348 mlir::ImplicitLocOpBuilder locBuilder(op.getLoc(), rewriter);
349 mlir::Type calleePtrTy = op.getCallee().getType();
352 mlir::Value ptrdiffOne =
353 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 1));
356 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredMethod, 1);
357 mlir::Value adj = rawAdj;
358 if (useARMMethodPtrABI)
359 adj = cir::ShiftOp::create(locBuilder, ptrdiffCIRTy, adj, ptrdiffOne,
363 mlir::Type thisVoidPtrTy =
364 cir::PointerType::get(cir::VoidType::get(locBuilder.getContext()),
365 op.getObject().getType().getAddrSpace());
366 mlir::Value thisVoidPtr = cir::CastOp::create(
367 locBuilder, thisVoidPtrTy, cir::CastKind::bitcast, loweredObjectPtr);
369 cir::PtrStrideOp::create(locBuilder, thisVoidPtrTy, thisVoidPtr, adj);
373 mlir::Value methodPtrField =
374 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredMethod, 0);
375 mlir::Value virtualBit;
376 if (useARMMethodPtrABI)
377 virtualBit = cir::AndOp::create(locBuilder, rawAdj, ptrdiffOne);
379 virtualBit = cir::AndOp::create(locBuilder, methodPtrField, ptrdiffOne);
380 mlir::Value isVirtual = cir::CmpOp::create(locBuilder, cir::CmpOpKind::eq,
381 virtualBit, ptrdiffOne);
387 auto buildVirtualCallee = [&](mlir::OpBuilder &b, mlir::Location loc) {
391 cir::PointerType::get(cir::IntType::get(b.getContext(), 8,
true));
392 auto vtablePtrPtrTy = cir::PointerType::get(
393 vtablePtrTy, op.getObject().getType().getAddrSpace());
394 auto vtablePtrPtr = cir::CastOp::create(b, loc, vtablePtrPtrTy,
395 cir::CastKind::bitcast, thisArg);
397 mlir::Value vtablePtr =
398 cir::LoadOp::create(b, loc, vtablePtrPtr,
false,
402 cir::SyncScopeKindAttr{},
409 mlir::Value vtableOffset = methodPtrField;
410 if (!useARMMethodPtrABI)
411 vtableOffset = cir::SubOp::create(b, loc, vtableOffset.getType(),
412 vtableOffset, ptrdiffOne);
413 if (use32BitVTableOffsetABI)
414 llvm_unreachable(
"AppleARM64 method ptr abi NYI");
422 mlir::Value vfpAddr = cir::PtrStrideOp::create(locBuilder, vtablePtrTy,
423 vtablePtr, vtableOffset);
424 auto vfpPtrTy = cir::PointerType::get(calleePtrTy);
425 mlir::Value vfpPtr = cir::CastOp::create(locBuilder, vfpPtrTy,
426 cir::CastKind::bitcast, vfpAddr);
427 auto fnPtr = cir::LoadOp::create(b, loc, vfpPtr,
431 cir::SyncScopeKindAttr{},
435 cir::YieldOp::create(b, loc, fnPtr.getResult());
439 callee = cir::TernaryOp::create(
440 locBuilder, isVirtual, buildVirtualCallee,
442 [&](mlir::OpBuilder &b, mlir::Location loc) {
443 auto fnPtr = cir::CastOp::create(b, loc, calleePtrTy,
444 cir::CastKind::int_to_ptr,
446 cir::YieldOp::create(b, loc, fnPtr.getResult());
452 mlir::Value loweredSrc,
454 bool isDerivedToBase,
455 mlir::OpBuilder &builder) {
458 mlir::Location loc = op->getLoc();
459 mlir::Type ty = loweredSrc.getType();
461 auto getConstantInt = [&](int64_t value) -> cir::ConstantOp {
462 return cir::ConstantOp::create(builder, loc, cir::IntAttr::get(ty, value));
465 cir::ConstantOp nullValue = getConstantInt(-1);
466 auto isNull = cir::CmpOp::create(builder, loc, cir::CmpOpKind::eq, loweredSrc,
469 cir::ConstantOp offsetValue = getConstantInt(offset);
470 mlir::Value adjustedPtr;
471 if (isDerivedToBase) {
472 auto subOp = cir::SubOp::create(builder, loc, ty, loweredSrc, offsetValue);
473 subOp.setNoSignedWrap(
true);
476 auto addOp = cir::AddOp::create(builder, loc, ty, loweredSrc, offsetValue);
477 addOp.setNoSignedWrap(
true);
481 return cir::SelectOp::create(builder, loc, ty, isNull, loweredSrc,
486LowerItaniumCXXABI::lowerBaseDataMember(cir::BaseDataMemberOp op,
487 mlir::Value loweredSrc,
488 mlir::OpBuilder &builder)
const {
489 return lowerDataMemberCast(op, loweredSrc, op.getOffset().getSExtValue(),
494LowerItaniumCXXABI::lowerDerivedDataMember(cir::DerivedDataMemberOp op,
495 mlir::Value loweredSrc,
496 mlir::OpBuilder &builder)
const {
502 std::int64_t offset,
bool isDerivedToBase,
503 bool useARMMethodPtrABI,
505 mlir::OpBuilder &builder) {
511 if (useARMMethodPtrABI)
515 auto adjField = cir::ExtractMemberOp::create(builder, op->getLoc(),
516 ptrdiffCIRTy, loweredSrc, 1);
518 auto offsetValue = cir::ConstantOp::create(
519 builder, op->getLoc(), cir::IntAttr::get(ptrdiffCIRTy, offset));
520 mlir::Value adjustedAdjField;
521 if (isDerivedToBase) {
522 auto subOp = cir::SubOp::create(builder, op->getLoc(), ptrdiffCIRTy,
523 adjField, offsetValue);
524 subOp.setNoSignedWrap(
true);
525 adjustedAdjField = subOp;
527 auto addOp = cir::AddOp::create(builder, op->getLoc(), ptrdiffCIRTy,
528 adjField, offsetValue);
529 addOp.setNoSignedWrap(
true);
530 adjustedAdjField = addOp;
533 return cir::InsertMemberOp::create(builder, op->getLoc(), loweredSrc, 1,
538LowerItaniumCXXABI::lowerBaseMethod(cir::BaseMethodOp op,
539 mlir::Value loweredSrc,
540 mlir::OpBuilder &builder)
const {
541 return lowerMethodCast(op, loweredSrc, op.getOffset().getSExtValue(),
542 true, useARMMethodPtrABI, lm,
547LowerItaniumCXXABI::lowerDerivedMethod(cir::DerivedMethodOp op,
548 mlir::Value loweredSrc,
549 mlir::OpBuilder &builder)
const {
551 false, useARMMethodPtrABI, lm,
556LowerItaniumCXXABI::lowerDataMemberCmp(cir::CmpOp op, mlir::Value loweredLhs,
557 mlir::Value loweredRhs,
558 mlir::OpBuilder &builder)
const {
559 return cir::CmpOp::create(builder, op.getLoc(), op.getKind(), loweredLhs,
563mlir::Value LowerItaniumCXXABI::lowerMethodCmp(cir::CmpOp op,
564 mlir::Value loweredLhs,
565 mlir::Value loweredRhs,
566 mlir::OpBuilder &builder)
const {
567 assert(op.getKind() == cir::CmpOpKind::eq ||
568 op.getKind() == cir::CmpOpKind::ne);
570 mlir::ImplicitLocOpBuilder locBuilder(op.getLoc(), builder);
572 mlir::Value ptrdiffZero =
573 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 0));
575 mlir::Value lhsPtrField =
576 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredLhs, 0);
577 mlir::Value rhsPtrField =
578 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredRhs, 0);
580 cir::CmpOp::create(locBuilder, op.getKind(), lhsPtrField, rhsPtrField);
581 mlir::Value ptrCmpToNull =
582 cir::CmpOp::create(locBuilder, op.getKind(), lhsPtrField, ptrdiffZero);
584 mlir::Value lhsAdjField =
585 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredLhs, 1);
586 mlir::Value rhsAdjField =
587 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredRhs, 1);
589 cir::CmpOp::create(locBuilder, op.getKind(), lhsAdjField, rhsAdjField);
591 auto create_and = [&](mlir::Value lhs, mlir::Value rhs) {
592 return cir::AndOp::create(locBuilder, lhs.getType(), lhs, rhs);
594 auto create_or = [&](mlir::Value lhs, mlir::Value rhs) {
595 return cir::OrOp::create(locBuilder, lhs.getType(), lhs, rhs);
600 if (useARMMethodPtrABI) {
602 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 1));
618 mlir::Value orAdj = create_or(lhsAdjField, rhsAdjField);
619 mlir::Value orAdjAnd1 = create_and(orAdj, one);
620 mlir::Value orAdjAnd1CmpZero =
621 cir::CmpOp::create(locBuilder, op.getKind(), orAdjAnd1, ptrdiffZero);
623 if (op.getKind() == cir::CmpOpKind::eq)
624 ptrCmpToNull = create_and(ptrCmpToNull, orAdjAnd1CmpZero);
626 ptrCmpToNull = create_or(ptrCmpToNull, orAdjAnd1CmpZero);
630 if (op.getKind() == cir::CmpOpKind::eq) {
632 result = create_and(ptrCmp, create_or(ptrCmpToNull, adjCmp));
635 result = create_or(ptrCmp, create_and(ptrCmpToNull, adjCmp));
641mlir::Value LowerItaniumCXXABI::lowerDataMemberBitcast(
642 cir::CastOp op, mlir::Type loweredDstTy, mlir::Value loweredSrc,
643 mlir::OpBuilder &builder)
const {
644 if (loweredSrc.getType() == loweredDstTy)
647 return cir::CastOp::create(builder, op.getLoc(), loweredDstTy,
648 cir::CastKind::bitcast, loweredSrc);
651mlir::Value LowerItaniumCXXABI::lowerDataMemberToBoolCast(
652 cir::CastOp op, mlir::Value loweredSrc, mlir::OpBuilder &builder)
const {
656 auto nullValue = cir::ConstantOp::create(builder, op.getLoc(), nullAttr);
657 return cir::CmpOp::create(builder, op.getLoc(), cir::CmpOpKind::ne,
658 loweredSrc, nullValue);
662LowerItaniumCXXABI::lowerMethodBitcast(cir::CastOp op, mlir::Type loweredDstTy,
663 mlir::Value loweredSrc,
664 mlir::OpBuilder &builder)
const {
665 if (loweredSrc.getType() == loweredDstTy)
671mlir::Value LowerItaniumCXXABI::lowerMethodToBoolCast(
672 cir::CastOp op, mlir::Value loweredSrc, mlir::OpBuilder &builder)
const {
673 mlir::ImplicitLocOpBuilder locBuilder(op.getLoc(), builder);
681 mlir::Value ptrdiffZero =
682 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 0));
683 mlir::Value ptrField =
684 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredSrc, 0);
687 cir::CmpOp::create(locBuilder, cir::CmpOpKind::ne, ptrField, ptrdiffZero);
691 if (useARMMethodPtrABI) {
693 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 1));
695 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredSrc, 1);
696 mlir::Value virtualBit =
697 cir::AndOp::create(locBuilder, ptrdiffCIRTy, adj, one);
698 mlir::Value isVirtual = cir::CmpOp::create(locBuilder, cir::CmpOpKind::ne,
699 virtualBit, ptrdiffZero);
700 result = cir::OrOp::create(locBuilder, result, isVirtual);
707 mlir::FlatSymbolRefAttr badCastFuncRef) {
708 auto callOp = cir::CallOp::create(builder, loc, badCastFuncRef,
711 callOp->setAttr(cir::CIRDialect::getNoReturnAttrName(),
712 builder.getUnitAttr());
714 cir::UnreachableOp::create(builder, loc);
715 builder.clearInsertionPoint();
719 mlir::OpBuilder &builder) {
720 mlir::Location loc = op->getLoc();
721 mlir::Value srcValue = op.getSrc();
722 cir::DynamicCastInfoAttr castInfo = op.getInfo().value();
728 cir::PointerType::get(cir::VoidType::get(builder.getContext()));
730 mlir::Value srcPtr = cir::CastOp::create(builder, loc, voidPtrTy,
731 cir::CastKind::bitcast, srcValue);
732 mlir::Value srcRtti =
733 cir::ConstantOp::create(builder, loc, castInfo.getSrcRtti());
734 mlir::Value destRtti =
735 cir::ConstantOp::create(builder, loc, castInfo.getDestRtti());
736 mlir::Value offsetHint =
737 cir::ConstantOp::create(builder, loc, castInfo.getOffsetHint());
739 mlir::FlatSymbolRefAttr dynCastFuncRef = castInfo.getRuntimeFunc();
740 mlir::Value dynCastFuncArgs[4] = {srcPtr, srcRtti, destRtti, offsetHint};
742 mlir::Value castedPtr = cir::CallOp::create(builder, loc, dynCastFuncRef,
743 voidPtrTy, dynCastFuncArgs)
746 assert(mlir::isa<cir::PointerType>(castedPtr.getType()) &&
747 "the return value of __dynamic_cast should be a ptr");
751 if (op.isRefCast()) {
753 mlir::Value null = cir::ConstantOp::create(
755 cir::ConstPtrAttr::get(castedPtr.getType(),
756 builder.getI64IntegerAttr(0)));
757 mlir::Value castedPtrIsNull =
758 cir::CmpOp::create(builder, loc, cir::CmpOpKind::eq, castedPtr, null);
759 cir::IfOp::create(builder, loc, castedPtrIsNull,
false,
760 [&](mlir::OpBuilder &, mlir::Location) {
762 castInfo.getBadCastFunc());
768 return cir::CastOp::create(builder, loc, op.getType(), cir::CastKind::bitcast,
774 mlir::Location loc = op.getLoc();
775 bool vtableUsesRelativeLayout = op.getRelativeLayout();
780 mlir::Type vtableElemTy;
781 uint64_t vtableElemAlign;
782 if (vtableUsesRelativeLayout) {
784 cir::IntType::get(builder.getContext(), 32,
true);
788 vtableElemAlign = llvm::divideCeil(
792 mlir::Type vtableElemPtrTy = cir::PointerType::get(vtableElemTy);
793 mlir::Type i64Ty = cir::IntType::get(builder.getContext(), 64,
799 auto vptrPtr = cir::VTableGetVPtrOp::create(builder, loc, op.getSrc());
800 mlir::Value vptr = cir::LoadOp::create(
801 builder, loc, vptrPtr,
805 builder.getI64IntegerAttr(vtableElemAlign),
806 cir::SyncScopeKindAttr(),
809 mlir::Value elementPtr = cir::CastOp::create(builder, loc, vtableElemPtrTy,
810 cir::CastKind::bitcast, vptr);
811 mlir::Value minusTwo =
812 cir::ConstantOp::create(builder, loc, cir::IntAttr::get(i64Ty, -2));
813 mlir::Value offsetToTopSlotPtr = cir::PtrStrideOp::create(
814 builder, loc, vtableElemPtrTy, elementPtr, minusTwo);
815 mlir::Value offsetToTop = cir::LoadOp::create(
816 builder, loc, offsetToTopSlotPtr,
820 builder.getI64IntegerAttr(vtableElemAlign),
821 cir::SyncScopeKindAttr(),
826 cir::PointerType::get(cir::VoidType::get(builder.getContext()));
831 cir::PointerType::get(cir::IntType::get(builder.getContext(), 8,
833 mlir::Value srcBytePtr = cir::CastOp::create(
834 builder, loc, u8PtrTy, cir::CastKind::bitcast, op.getSrc());
836 cir::PtrStrideOp::create(builder, loc, u8PtrTy, srcBytePtr, offsetToTop);
838 return cir::CastOp::create(builder, loc, voidPtrTy, cir::CastKind::bitcast,
843LowerItaniumCXXABI::lowerDynamicCast(cir::DynamicCastOp op,
844 mlir::OpBuilder &builder)
const {
845 mlir::Location loc = op->getLoc();
846 mlir::Value srcValue = op.getSrc();
851 return buildDynamicCastAfterNullCheck(op, builder);
853 mlir::Value srcValueIsNotNull = cir::CastOp::create(
854 builder, loc, cir::BoolType::get(builder.getContext()),
855 cir::CastKind::ptr_to_bool, srcValue);
856 return cir::TernaryOp::create(
857 builder, loc, srcValueIsNotNull,
858 [&](mlir::OpBuilder &, mlir::Location) {
859 mlir::Value castedValue =
861 ? buildDynamicCastToVoidAfterNullCheck(op, lm, builder)
862 : buildDynamicCastAfterNullCheck(op, builder);
863 cir::YieldOp::create(builder, loc, castedValue);
865 [&](mlir::OpBuilder &, mlir::Location) {
866 mlir::Value null = cir::ConstantOp::create(
868 cir::ConstPtrAttr::get(op.getType(),
869 builder.getI64IntegerAttr(0)));
870 cir::YieldOp::create(builder, loc, null);
875LowerItaniumCXXABI::lowerVTableGetTypeInfo(cir::VTableGetTypeInfoOp op,
876 mlir::OpBuilder &builder)
const {
877 mlir::Location loc = op->getLoc();
878 auto offset = cir::ConstantOp::create(
882 auto vptrCast = cir::CastOp::create(builder, loc, op.getType(),
883 cir::CastKind::bitcast, op.getVptr());
885 return cir::PtrStrideOp::create(builder, loc, vptrCast.getType(), vptrCast,
890clang::CharUnits LowerItaniumCXXABI::getArrayCookieSizeImpl(
891 mlir::Type elementType,
const mlir::DataLayout &dataLayout)
const {
894 clang::CharUnits sizeOfSizeT =
897 dataLayout.getTypePreferredAlignment(elementType));
898 return std::max(sizeOfSizeT, eltAlign);
901mlir::Value LowerItaniumCXXABI::readArrayCookieImpl(
902 mlir::Location loc, mlir::Value allocPtr, clang::CharUnits cookieSize,
903 clang::CharUnits cookieAlignment,
const mlir::DataLayout &dataLayout,
904 CIRBaseBuilderTy &builder)
const {
905 unsigned ptrSizeInBits = getPtrSizeInBits();
907 auto ptrDiffTy = builder.
getSIntNTy(ptrSizeInBits);
908 auto sizeTy = builder.
getUIntNTy(ptrSizeInBits);
911 clang::CharUnits sizeOfSizeT =
913 clang::CharUnits countOffset = cookieSize - sizeOfSizeT;
915 mlir::Value countBytePtr = allocPtr;
916 clang::CharUnits countAlignment = cookieAlignment;
917 if (!countOffset.
isZero()) {
918 mlir::Value offsetVal = cir::ConstantOp::create(
919 builder, loc, cir::IntAttr::get(ptrDiffTy, countOffset.
getQuantity()));
921 cir::PtrStrideOp::create(builder, loc, u8PtrTy, allocPtr, offsetVal);
925 auto countPtrTy = cir::PointerType::get(sizeTy);
926 mlir::Value countPtr = cir::CastOp::create(
927 builder, loc, countPtrTy, cir::CastKind::bitcast, countBytePtr);
928 return cir::LoadOp::create(
929 builder, loc, countPtr,
false,
false,
931 builder.getI64IntegerAttr(countAlignment.
getQuantity()),
932 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 ----------------------------—===//