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(clang::CharUnits elementAlign)
const override;
122 mlir::Value readArrayCookieImpl(mlir::Location loc, mlir::Value allocPtr,
123 clang::CharUnits cookieSize,
124 clang::CharUnits cookieAlignment,
125 const mlir::DataLayout &dataLayout,
126 CIRBaseBuilderTy &builder)
const override;
136 case clang::TargetCXXABI::GenericAArch64:
137 return std::make_unique<LowerItaniumCXXABI>(
141 case clang::TargetCXXABI::AppleARM64:
145 return std::make_unique<LowerItaniumCXXABI>(
150 case clang::TargetCXXABI::GenericItanium:
151 return std::make_unique<LowerItaniumCXXABI>(lm);
153 case clang::TargetCXXABI::Microsoft:
154 llvm_unreachable(
"Microsoft ABI is not Itanium-based");
156 llvm_unreachable(
"Other Itanium ABI?");
168mlir::Type LowerItaniumCXXABI::lowerDataMemberType(
169 cir::DataMemberType type,
const mlir::TypeConverter &typeConverter)
const {
173 return getPtrDiffCIRTy(lm);
176mlir::Type LowerItaniumCXXABI::lowerMethodType(
177 cir::MethodType type,
const mlir::TypeConverter &typeConverter)
const {
192 mlir::Type members[] = {ptrdiffCIRTy, ptrdiffCIRTy};
193 return cir::StructType::get(
type.getContext(), members,
false,
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) {
710 auto callOp = cir::CallOp::create(builder, loc, badCastFuncRef,
713 callOp->setAttr(cir::CIRDialect::getNoReturnAttrName(),
714 builder.getUnitAttr());
716 cir::UnreachableOp::create(builder, loc);
717 builder.clearInsertionPoint();
721 mlir::OpBuilder &builder) {
722 mlir::Location loc = op->getLoc();
723 mlir::Value srcValue = op.getSrc();
724 cir::DynamicCastInfoAttr castInfo = op.getInfo().value();
730 cir::PointerType::get(cir::VoidType::get(builder.getContext()));
732 mlir::Value srcPtr = cir::CastOp::create(builder, loc, voidPtrTy,
733 cir::CastKind::bitcast, srcValue);
734 mlir::Value srcRtti =
735 cir::ConstantOp::create(builder, loc, castInfo.getSrcRtti());
736 mlir::Value destRtti =
737 cir::ConstantOp::create(builder, loc, castInfo.getDestRtti());
738 mlir::Value offsetHint =
739 cir::ConstantOp::create(builder, loc, castInfo.getOffsetHint());
741 mlir::FlatSymbolRefAttr dynCastFuncRef = castInfo.getRuntimeFunc();
742 mlir::Value dynCastFuncArgs[4] = {srcPtr, srcRtti, destRtti, offsetHint};
747 mlir::Value castedPtr = cir::CallOp::create(builder, loc, dynCastFuncRef,
748 voidPtrTy, dynCastFuncArgs)
751 assert(mlir::isa<cir::PointerType>(castedPtr.getType()) &&
752 "the return value of __dynamic_cast should be a ptr");
756 if (op.isRefCast()) {
758 mlir::Value null = cir::ConstantOp::create(
760 cir::ConstPtrAttr::get(castedPtr.getType(),
761 builder.getI64IntegerAttr(0)));
762 mlir::Value castedPtrIsNull =
763 cir::CmpOp::create(builder, loc, cir::CmpOpKind::eq, castedPtr, null);
764 cir::IfOp::create(builder, loc, castedPtrIsNull,
false,
765 [&](mlir::OpBuilder &, mlir::Location) {
767 castInfo.getBadCastFunc());
773 return cir::CastOp::create(builder, loc, op.getType(), cir::CastKind::bitcast,
779 mlir::Location loc = op.getLoc();
780 bool vtableUsesRelativeLayout = op.getRelativeLayout();
785 mlir::Type vtableElemTy;
786 uint64_t vtableElemAlign;
787 if (vtableUsesRelativeLayout) {
789 cir::IntType::get(builder.getContext(), 32,
true);
793 vtableElemAlign = llvm::divideCeil(
797 mlir::Type vtableElemPtrTy = cir::PointerType::get(vtableElemTy);
798 mlir::Type i64Ty = cir::IntType::get(builder.getContext(), 64,
804 auto vptrPtr = cir::VTableGetVPtrOp::create(builder, loc, op.getSrc());
805 mlir::Value vptr = cir::LoadOp::create(
806 builder, loc, vptrPtr,
810 builder.getI64IntegerAttr(vtableElemAlign),
811 cir::SyncScopeKindAttr(),
814 mlir::Value elementPtr = cir::CastOp::create(builder, loc, vtableElemPtrTy,
815 cir::CastKind::bitcast, vptr);
816 mlir::Value minusTwo =
817 cir::ConstantOp::create(builder, loc, cir::IntAttr::get(i64Ty, -2));
818 mlir::Value offsetToTopSlotPtr = cir::PtrStrideOp::create(
819 builder, loc, vtableElemPtrTy, elementPtr, minusTwo);
820 mlir::Value offsetToTop = cir::LoadOp::create(
821 builder, loc, offsetToTopSlotPtr,
825 builder.getI64IntegerAttr(vtableElemAlign),
826 cir::SyncScopeKindAttr(),
831 cir::PointerType::get(cir::VoidType::get(builder.getContext()));
836 cir::PointerType::get(cir::IntType::get(builder.getContext(), 8,
838 mlir::Value srcBytePtr = cir::CastOp::create(
839 builder, loc, u8PtrTy, cir::CastKind::bitcast, op.getSrc());
841 cir::PtrStrideOp::create(builder, loc, u8PtrTy, srcBytePtr, offsetToTop);
843 return cir::CastOp::create(builder, loc, voidPtrTy, cir::CastKind::bitcast,
848LowerItaniumCXXABI::lowerDynamicCast(cir::DynamicCastOp op,
849 mlir::OpBuilder &builder)
const {
850 mlir::Location loc = op->getLoc();
851 mlir::Value srcValue = op.getSrc();
856 return buildDynamicCastAfterNullCheck(op, builder);
858 mlir::Value srcValueIsNotNull = cir::CastOp::create(
859 builder, loc, cir::BoolType::get(builder.getContext()),
860 cir::CastKind::ptr_to_bool, srcValue);
861 return cir::TernaryOp::create(
862 builder, loc, srcValueIsNotNull,
863 [&](mlir::OpBuilder &, mlir::Location) {
864 mlir::Value castedValue =
866 ? buildDynamicCastToVoidAfterNullCheck(op, lm, builder)
867 : buildDynamicCastAfterNullCheck(op, builder);
868 cir::YieldOp::create(builder, loc, castedValue);
870 [&](mlir::OpBuilder &, mlir::Location) {
871 mlir::Value null = cir::ConstantOp::create(
873 cir::ConstPtrAttr::get(op.getType(),
874 builder.getI64IntegerAttr(0)));
875 cir::YieldOp::create(builder, loc, null);
880LowerItaniumCXXABI::lowerVTableGetTypeInfo(cir::VTableGetTypeInfoOp op,
881 mlir::OpBuilder &builder)
const {
882 mlir::Location loc = op->getLoc();
883 auto offset = cir::ConstantOp::create(
887 auto vptrCast = cir::CastOp::create(builder, loc, op.getType(),
888 cir::CastKind::bitcast, op.getVptr());
890 return cir::PtrStrideOp::create(builder, loc, vptrCast.getType(), vptrCast,
895clang::CharUnits LowerItaniumCXXABI::getArrayCookieSizeImpl(
896 clang::CharUnits elementAlign)
const {
899 clang::CharUnits sizeOfSizeT =
901 return std::max(sizeOfSizeT, elementAlign);
904mlir::Value LowerItaniumCXXABI::readArrayCookieImpl(
905 mlir::Location loc, mlir::Value allocPtr, clang::CharUnits cookieSize,
906 clang::CharUnits cookieAlignment,
const mlir::DataLayout &dataLayout,
907 CIRBaseBuilderTy &builder)
const {
908 unsigned ptrSizeInBits = getPtrSizeInBits();
910 auto ptrDiffTy = builder.
getSIntNTy(ptrSizeInBits);
911 auto sizeTy = builder.
getUIntNTy(ptrSizeInBits);
914 clang::CharUnits sizeOfSizeT =
916 clang::CharUnits countOffset = cookieSize - sizeOfSizeT;
918 mlir::Value countBytePtr = allocPtr;
919 clang::CharUnits countAlignment = cookieAlignment;
920 if (!countOffset.
isZero()) {
921 mlir::Value offsetVal = cir::ConstantOp::create(
922 builder, loc, cir::IntAttr::get(ptrDiffTy, countOffset.
getQuantity()));
924 cir::PtrStrideOp::create(builder, loc, u8PtrTy, allocPtr, offsetVal);
928 auto countPtrTy = cir::PointerType::get(sizeTy);
929 mlir::Value countPtr = cir::CastOp::create(
930 builder, loc, countPtrTy, cir::CastKind::bitcast, countBytePtr);
931 return cir::LoadOp::create(
932 builder, loc, countPtr,
false,
false,
934 builder.getI64IntegerAttr(countAlignment.
getQuantity()),
935 cir::SyncScopeKindAttr(), cir::MemOrderAttr(),
cir::PointerType getPointerTo(mlir::Type ty)
cir::IntType getUIntNTy(int n)
cir::IntType getSIntNTy(int n)
mlir::MLIRContext * getMLIRContext()
clang::TargetCXXABI::Kind getCXXABIKind() const
const clang::TargetInfo & getTarget() const
static llvm::SmallVector< RecordMemberKind > getAllDataKinds(llvm::ArrayRef< mlir::Type > members)
One Data kind per member.
CharUnits alignmentAtOffset(CharUnits offset) const
Given that this is a non-zero alignment value, what is the alignment at the given offset?
bool isZero() const
Test whether the quantity equals zero.
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
static CharUnits fromQuantity(QuantityType Quantity)
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.
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t
static bool addressSpace()
static bool appleArm64CXXABI()
static bool emitCFICheck()
static bool emitVFEInfo()
static bool emitWPDInfo()
static bool emitTypeCheck()
static bool pointerAuthentication()
static bool opFuncCallingConv()
IntType
===-— Target Data Type Query Methods ----------------------------—===//