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::RecordType::get(
type.getContext(), {ptrdiffCIRTy, ptrdiffCIRTy},
191 cir::RecordType::Struct);
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 {
223 auto loweredMethodTy = mlir::cast<cir::RecordType>(
224 lowerMethodType(
attr.getType(), typeConverter));
226 auto zero = cir::IntAttr::get(ptrdiffCIRTy, 0);
247 return cir::ConstRecordAttr::get(
248 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {zero, zero}));
251 if (
attr.isVirtual()) {
252 if (useARMMethodPtrABI) {
261 cir::IntAttr::get(ptrdiffCIRTy,
attr.getVtableOffset().value());
262 auto one = cir::IntAttr::get(ptrdiffCIRTy, 1);
263 return cir::ConstRecordAttr::get(
264 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {ptr, one}));
275 cir::IntAttr::get(ptrdiffCIRTy, 1 +
attr.getVtableOffset().value());
276 return cir::ConstRecordAttr::get(
277 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {ptr, zero}));
285 auto ptr = cir::GlobalViewAttr::get(ptrdiffCIRTy,
attr.getSymbol().value());
286 return cir::ConstRecordAttr::get(
287 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {ptr, zero}));
290mlir::Operation *LowerItaniumCXXABI::lowerGetRuntimeMember(
291 cir::GetRuntimeMemberOp op, mlir::Type loweredResultTy,
292 mlir::Value loweredAddr, mlir::Value loweredMember,
293 mlir::OpBuilder &builder)
const {
294 auto byteTy = cir::IntType::get(op.getContext(), 8,
true);
295 auto bytePtrTy = cir::PointerType::get(
297 mlir::cast<cir::PointerType>(op.getAddr().getType()).getAddrSpace());
298 auto objectBytesPtr = cir::CastOp::create(
299 builder, op.getLoc(), bytePtrTy, cir::CastKind::bitcast, op.getAddr());
300 auto memberBytesPtr = cir::PtrStrideOp::create(
301 builder, op.getLoc(), bytePtrTy, objectBytesPtr, loweredMember);
302 return cir::CastOp::create(builder, op.getLoc(), op.getType(),
303 cir::CastKind::bitcast, memberBytesPtr);
306void LowerItaniumCXXABI::lowerGetMethod(
307 cir::GetMethodOp op, mlir::Value &callee, mlir::Value &thisArg,
308 mlir::Value loweredMethod, mlir::Value loweredObjectPtr,
309 mlir::ConversionPatternRewriter &rewriter)
const {
331 mlir::ImplicitLocOpBuilder locBuilder(op.getLoc(), rewriter);
332 mlir::Type calleePtrTy = op.getCallee().getType();
335 mlir::Value ptrdiffOne =
336 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 1));
339 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredMethod, 1);
340 mlir::Value adj = rawAdj;
341 if (useARMMethodPtrABI)
342 adj = cir::ShiftOp::create(locBuilder, ptrdiffCIRTy, adj, ptrdiffOne,
346 mlir::Type thisVoidPtrTy =
347 cir::PointerType::get(cir::VoidType::get(locBuilder.getContext()),
348 op.getObject().getType().getAddrSpace());
349 mlir::Value thisVoidPtr = cir::CastOp::create(
350 locBuilder, thisVoidPtrTy, cir::CastKind::bitcast, loweredObjectPtr);
352 cir::PtrStrideOp::create(locBuilder, thisVoidPtrTy, thisVoidPtr, adj);
356 mlir::Value methodPtrField =
357 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredMethod, 0);
358 mlir::Value virtualBit;
359 if (useARMMethodPtrABI)
360 virtualBit = cir::AndOp::create(locBuilder, rawAdj, ptrdiffOne);
362 virtualBit = cir::AndOp::create(locBuilder, methodPtrField, ptrdiffOne);
363 mlir::Value isVirtual = cir::CmpOp::create(locBuilder, cir::CmpOpKind::eq,
364 virtualBit, ptrdiffOne);
370 auto buildVirtualCallee = [&](mlir::OpBuilder &
b, mlir::Location loc) {
374 cir::PointerType::get(cir::IntType::get(
b.getContext(), 8,
true));
375 auto vtablePtrPtrTy = cir::PointerType::get(
376 vtablePtrTy, op.getObject().getType().getAddrSpace());
377 auto vtablePtrPtr = cir::CastOp::create(
b, loc, vtablePtrPtrTy,
378 cir::CastKind::bitcast, thisArg);
380 mlir::Value vtablePtr =
381 cir::LoadOp::create(
b, loc, vtablePtrPtr,
false,
384 cir::SyncScopeKindAttr{},
385 cir::MemOrderAttr());
390 mlir::Value vtableOffset = methodPtrField;
391 if (!useARMMethodPtrABI)
392 vtableOffset = cir::SubOp::create(
b, loc, vtableOffset.getType(),
393 vtableOffset, ptrdiffOne);
394 if (use32BitVTableOffsetABI)
395 llvm_unreachable(
"AppleARM64 method ptr abi NYI");
403 mlir::Value vfpAddr = cir::PtrStrideOp::create(locBuilder, vtablePtrTy,
404 vtablePtr, vtableOffset);
405 auto vfpPtrTy = cir::PointerType::get(calleePtrTy);
406 mlir::Value vfpPtr = cir::CastOp::create(locBuilder, vfpPtrTy,
407 cir::CastKind::bitcast, vfpAddr);
408 auto fnPtr = cir::LoadOp::create(
b, loc, vfpPtr,
411 cir::SyncScopeKindAttr{},
412 cir::MemOrderAttr());
414 cir::YieldOp::create(
b, loc, fnPtr.getResult());
418 callee = cir::TernaryOp::create(
419 locBuilder, isVirtual, buildVirtualCallee,
421 [&](mlir::OpBuilder &
b, mlir::Location loc) {
422 auto fnPtr = cir::CastOp::create(
b, loc, calleePtrTy,
423 cir::CastKind::int_to_ptr,
425 cir::YieldOp::create(
b, loc, fnPtr.getResult());
431 mlir::Value loweredSrc,
433 bool isDerivedToBase,
434 mlir::OpBuilder &builder) {
437 mlir::Location loc = op->getLoc();
438 mlir::Type ty = loweredSrc.getType();
440 auto getConstantInt = [&](int64_t value) -> cir::ConstantOp {
441 return cir::ConstantOp::create(builder, loc, cir::IntAttr::get(ty, value));
444 cir::ConstantOp nullValue = getConstantInt(-1);
445 auto isNull = cir::CmpOp::create(builder, loc, cir::CmpOpKind::eq, loweredSrc,
448 cir::ConstantOp offsetValue = getConstantInt(offset);
449 mlir::Value adjustedPtr;
450 if (isDerivedToBase) {
451 auto subOp = cir::SubOp::create(builder, loc, ty, loweredSrc, offsetValue);
452 subOp.setNoSignedWrap(
true);
455 auto addOp = cir::AddOp::create(builder, loc, ty, loweredSrc, offsetValue);
456 addOp.setNoSignedWrap(
true);
460 return cir::SelectOp::create(builder, loc, ty, isNull, loweredSrc,
465LowerItaniumCXXABI::lowerBaseDataMember(cir::BaseDataMemberOp op,
466 mlir::Value loweredSrc,
467 mlir::OpBuilder &builder)
const {
468 return lowerDataMemberCast(op, loweredSrc, op.getOffset().getSExtValue(),
473LowerItaniumCXXABI::lowerDerivedDataMember(cir::DerivedDataMemberOp op,
474 mlir::Value loweredSrc,
475 mlir::OpBuilder &builder)
const {
481 std::int64_t offset,
bool isDerivedToBase,
482 bool useARMMethodPtrABI,
484 mlir::OpBuilder &builder) {
490 if (useARMMethodPtrABI)
494 auto adjField = cir::ExtractMemberOp::create(builder, op->getLoc(),
495 ptrdiffCIRTy, loweredSrc, 1);
497 auto offsetValue = cir::ConstantOp::create(
498 builder, op->getLoc(), cir::IntAttr::get(ptrdiffCIRTy, offset));
499 mlir::Value adjustedAdjField;
500 if (isDerivedToBase) {
501 auto subOp = cir::SubOp::create(builder, op->getLoc(), ptrdiffCIRTy,
502 adjField, offsetValue);
503 subOp.setNoSignedWrap(
true);
504 adjustedAdjField = subOp;
506 auto addOp = cir::AddOp::create(builder, op->getLoc(), ptrdiffCIRTy,
507 adjField, offsetValue);
508 addOp.setNoSignedWrap(
true);
509 adjustedAdjField = addOp;
512 return cir::InsertMemberOp::create(builder, op->getLoc(), loweredSrc, 1,
517LowerItaniumCXXABI::lowerBaseMethod(cir::BaseMethodOp op,
518 mlir::Value loweredSrc,
519 mlir::OpBuilder &builder)
const {
520 return lowerMethodCast(op, loweredSrc, op.getOffset().getSExtValue(),
521 true, useARMMethodPtrABI, lm,
526LowerItaniumCXXABI::lowerDerivedMethod(cir::DerivedMethodOp op,
527 mlir::Value loweredSrc,
528 mlir::OpBuilder &builder)
const {
530 false, useARMMethodPtrABI, lm,
535LowerItaniumCXXABI::lowerDataMemberCmp(cir::CmpOp op, mlir::Value loweredLhs,
536 mlir::Value loweredRhs,
537 mlir::OpBuilder &builder)
const {
538 return cir::CmpOp::create(builder, op.getLoc(), op.getKind(), loweredLhs,
542mlir::Value LowerItaniumCXXABI::lowerMethodCmp(cir::CmpOp op,
543 mlir::Value loweredLhs,
544 mlir::Value loweredRhs,
545 mlir::OpBuilder &builder)
const {
546 assert(op.getKind() == cir::CmpOpKind::eq ||
547 op.getKind() == cir::CmpOpKind::ne);
549 mlir::ImplicitLocOpBuilder locBuilder(op.getLoc(), builder);
551 mlir::Value ptrdiffZero =
552 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 0));
554 mlir::Value lhsPtrField =
555 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredLhs, 0);
556 mlir::Value rhsPtrField =
557 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredRhs, 0);
559 cir::CmpOp::create(locBuilder, op.getKind(), lhsPtrField, rhsPtrField);
560 mlir::Value ptrCmpToNull =
561 cir::CmpOp::create(locBuilder, op.getKind(), lhsPtrField, ptrdiffZero);
563 mlir::Value lhsAdjField =
564 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredLhs, 1);
565 mlir::Value rhsAdjField =
566 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredRhs, 1);
568 cir::CmpOp::create(locBuilder, op.getKind(), lhsAdjField, rhsAdjField);
570 auto create_and = [&](mlir::Value lhs, mlir::Value rhs) {
571 return cir::AndOp::create(locBuilder, lhs.getType(), lhs, rhs);
573 auto create_or = [&](mlir::Value lhs, mlir::Value rhs) {
574 return cir::OrOp::create(locBuilder, lhs.getType(), lhs, rhs);
579 if (useARMMethodPtrABI) {
581 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 1));
597 mlir::Value orAdj = create_or(lhsAdjField, rhsAdjField);
598 mlir::Value orAdjAnd1 = create_and(orAdj, one);
599 mlir::Value orAdjAnd1CmpZero =
600 cir::CmpOp::create(locBuilder, op.getKind(), orAdjAnd1, ptrdiffZero);
602 if (op.getKind() == cir::CmpOpKind::eq)
603 ptrCmpToNull = create_and(ptrCmpToNull, orAdjAnd1CmpZero);
605 ptrCmpToNull = create_or(ptrCmpToNull, orAdjAnd1CmpZero);
609 if (op.getKind() == cir::CmpOpKind::eq) {
611 result = create_and(ptrCmp, create_or(ptrCmpToNull, adjCmp));
614 result = create_or(ptrCmp, create_and(ptrCmpToNull, adjCmp));
620mlir::Value LowerItaniumCXXABI::lowerDataMemberBitcast(
621 cir::CastOp op, mlir::Type loweredDstTy, mlir::Value loweredSrc,
622 mlir::OpBuilder &builder)
const {
623 if (loweredSrc.getType() == loweredDstTy)
626 return cir::CastOp::create(builder, op.getLoc(), loweredDstTy,
627 cir::CastKind::bitcast, loweredSrc);
630mlir::Value LowerItaniumCXXABI::lowerDataMemberToBoolCast(
631 cir::CastOp op, mlir::Value loweredSrc, mlir::OpBuilder &builder)
const {
635 auto nullValue = cir::ConstantOp::create(builder, op.getLoc(), nullAttr);
636 return cir::CmpOp::create(builder, op.getLoc(), cir::CmpOpKind::ne,
637 loweredSrc, nullValue);
641LowerItaniumCXXABI::lowerMethodBitcast(cir::CastOp op, mlir::Type loweredDstTy,
642 mlir::Value loweredSrc,
643 mlir::OpBuilder &builder)
const {
644 if (loweredSrc.getType() == loweredDstTy)
650mlir::Value LowerItaniumCXXABI::lowerMethodToBoolCast(
651 cir::CastOp op, mlir::Value loweredSrc, mlir::OpBuilder &builder)
const {
652 mlir::ImplicitLocOpBuilder locBuilder(op.getLoc(), builder);
660 mlir::Value ptrdiffZero =
661 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 0));
662 mlir::Value ptrField =
663 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredSrc, 0);
666 cir::CmpOp::create(locBuilder, cir::CmpOpKind::ne, ptrField, ptrdiffZero);
670 if (useARMMethodPtrABI) {
672 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 1));
674 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredSrc, 1);
675 mlir::Value virtualBit =
676 cir::AndOp::create(locBuilder, ptrdiffCIRTy, adj, one);
677 mlir::Value isVirtual = cir::CmpOp::create(locBuilder, cir::CmpOpKind::ne,
678 virtualBit, ptrdiffZero);
679 result = cir::OrOp::create(locBuilder, result, isVirtual);
686 mlir::FlatSymbolRefAttr badCastFuncRef) {
687 auto callOp = cir::CallOp::create(builder, loc, badCastFuncRef,
690 callOp->setAttr(cir::CIRDialect::getNoReturnAttrName(),
691 builder.getUnitAttr());
693 cir::UnreachableOp::create(builder, loc);
694 builder.clearInsertionPoint();
698 mlir::OpBuilder &builder) {
699 mlir::Location loc = op->getLoc();
700 mlir::Value srcValue = op.getSrc();
701 cir::DynamicCastInfoAttr castInfo = op.getInfo().value();
707 cir::PointerType::get(cir::VoidType::get(builder.getContext()));
709 mlir::Value srcPtr = cir::CastOp::create(builder, loc, voidPtrTy,
710 cir::CastKind::bitcast, srcValue);
711 mlir::Value srcRtti =
712 cir::ConstantOp::create(builder, loc, castInfo.getSrcRtti());
713 mlir::Value destRtti =
714 cir::ConstantOp::create(builder, loc, castInfo.getDestRtti());
715 mlir::Value offsetHint =
716 cir::ConstantOp::create(builder, loc, castInfo.getOffsetHint());
718 mlir::FlatSymbolRefAttr dynCastFuncRef = castInfo.getRuntimeFunc();
719 mlir::Value dynCastFuncArgs[4] = {srcPtr, srcRtti, destRtti, offsetHint};
721 mlir::Value castedPtr = cir::CallOp::create(builder, loc, dynCastFuncRef,
722 voidPtrTy, dynCastFuncArgs)
725 assert(mlir::isa<cir::PointerType>(castedPtr.getType()) &&
726 "the return value of __dynamic_cast should be a ptr");
730 if (op.isRefCast()) {
732 mlir::Value null = cir::ConstantOp::create(
734 cir::ConstPtrAttr::get(castedPtr.getType(),
735 builder.getI64IntegerAttr(0)));
736 mlir::Value castedPtrIsNull =
737 cir::CmpOp::create(builder, loc, cir::CmpOpKind::eq, castedPtr, null);
738 cir::IfOp::create(builder, loc, castedPtrIsNull,
false,
739 [&](mlir::OpBuilder &, mlir::Location) {
741 castInfo.getBadCastFunc());
747 return cir::CastOp::create(builder, loc, op.getType(), cir::CastKind::bitcast,
753 mlir::Location loc = op.getLoc();
754 bool vtableUsesRelativeLayout = op.getRelativeLayout();
759 mlir::Type vtableElemTy;
760 uint64_t vtableElemAlign;
761 if (vtableUsesRelativeLayout) {
763 cir::IntType::get(builder.getContext(), 32,
true);
767 vtableElemAlign = llvm::divideCeil(
771 mlir::Type vtableElemPtrTy = cir::PointerType::get(vtableElemTy);
772 mlir::Type i64Ty = cir::IntType::get(builder.getContext(), 64,
778 auto vptrPtr = cir::VTableGetVPtrOp::create(builder, loc, op.getSrc());
779 mlir::Value vptr = cir::LoadOp::create(
780 builder, loc, vptrPtr,
783 builder.getI64IntegerAttr(vtableElemAlign),
784 cir::SyncScopeKindAttr(),
785 cir::MemOrderAttr());
786 mlir::Value elementPtr = cir::CastOp::create(builder, loc, vtableElemPtrTy,
787 cir::CastKind::bitcast, vptr);
788 mlir::Value minusTwo =
789 cir::ConstantOp::create(builder, loc, cir::IntAttr::get(i64Ty, -2));
790 mlir::Value offsetToTopSlotPtr = cir::PtrStrideOp::create(
791 builder, loc, vtableElemPtrTy, elementPtr, minusTwo);
792 mlir::Value offsetToTop = cir::LoadOp::create(
793 builder, loc, offsetToTopSlotPtr,
796 builder.getI64IntegerAttr(vtableElemAlign),
797 cir::SyncScopeKindAttr(),
798 cir::MemOrderAttr());
801 cir::PointerType::get(cir::VoidType::get(builder.getContext()));
806 cir::PointerType::get(cir::IntType::get(builder.getContext(), 8,
808 mlir::Value srcBytePtr = cir::CastOp::create(
809 builder, loc, u8PtrTy, cir::CastKind::bitcast, op.getSrc());
811 cir::PtrStrideOp::create(builder, loc, u8PtrTy, srcBytePtr, offsetToTop);
813 return cir::CastOp::create(builder, loc, voidPtrTy, cir::CastKind::bitcast,
818LowerItaniumCXXABI::lowerDynamicCast(cir::DynamicCastOp op,
819 mlir::OpBuilder &builder)
const {
820 mlir::Location loc = op->getLoc();
821 mlir::Value srcValue = op.getSrc();
826 return buildDynamicCastAfterNullCheck(op, builder);
828 mlir::Value srcValueIsNotNull = cir::CastOp::create(
829 builder, loc, cir::BoolType::get(builder.getContext()),
830 cir::CastKind::ptr_to_bool, srcValue);
831 return cir::TernaryOp::create(
832 builder, loc, srcValueIsNotNull,
833 [&](mlir::OpBuilder &, mlir::Location) {
834 mlir::Value castedValue =
836 ? buildDynamicCastToVoidAfterNullCheck(op, lm, builder)
837 : buildDynamicCastAfterNullCheck(op, builder);
838 cir::YieldOp::create(builder, loc, castedValue);
840 [&](mlir::OpBuilder &, mlir::Location) {
841 mlir::Value null = cir::ConstantOp::create(
843 cir::ConstPtrAttr::get(op.getType(),
844 builder.getI64IntegerAttr(0)));
845 cir::YieldOp::create(builder, loc, null);
850LowerItaniumCXXABI::lowerVTableGetTypeInfo(cir::VTableGetTypeInfoOp op,
851 mlir::OpBuilder &builder)
const {
852 mlir::Location loc = op->getLoc();
853 auto offset = cir::ConstantOp::create(
857 auto vptrCast = cir::CastOp::create(builder, loc, op.getType(),
858 cir::CastKind::bitcast, op.getVptr());
860 return cir::PtrStrideOp::create(builder, loc, vptrCast.getType(), vptrCast,
865clang::CharUnits LowerItaniumCXXABI::getArrayCookieSizeImpl(
866 mlir::Type elementType,
const mlir::DataLayout &dataLayout)
const {
869 clang::CharUnits sizeOfSizeT =
872 dataLayout.getTypePreferredAlignment(elementType));
873 return std::max(sizeOfSizeT, eltAlign);
876mlir::Value LowerItaniumCXXABI::readArrayCookieImpl(
877 mlir::Location loc, mlir::Value allocPtr, clang::CharUnits cookieSize,
878 clang::CharUnits cookieAlignment,
const mlir::DataLayout &dataLayout,
879 CIRBaseBuilderTy &builder)
const {
880 unsigned ptrSizeInBits = getPtrSizeInBits();
881 auto u8PtrTy = builder.getPointerTo(builder.getUIntNTy(8));
882 auto ptrDiffTy = builder.getSIntNTy(ptrSizeInBits);
883 auto sizeTy = builder.getUIntNTy(ptrSizeInBits);
886 clang::CharUnits sizeOfSizeT =
888 clang::CharUnits countOffset = cookieSize - sizeOfSizeT;
890 mlir::Value countBytePtr = allocPtr;
891 clang::CharUnits countAlignment = cookieAlignment;
892 if (!countOffset.
isZero()) {
893 mlir::Value offsetVal = cir::ConstantOp::create(
894 builder, loc, cir::IntAttr::get(ptrDiffTy, countOffset.
getQuantity()));
896 cir::PtrStrideOp::create(builder, loc, u8PtrTy, allocPtr, offsetVal);
900 auto countPtrTy = cir::PointerType::get(sizeTy);
901 mlir::Value countPtr = cir::CastOp::create(
902 builder, loc, countPtrTy, cir::CastKind::bitcast, countBytePtr);
903 return cir::LoadOp::create(
904 builder, loc, countPtr,
false,
false,
905 builder.getI64IntegerAttr(countAlignment.
getQuantity()),
906 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 ----------------------------—===//