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;
38 LowerItaniumCXXABI(LowerModule &lm,
bool useARMMethodPtrABI =
false)
39 : CIRCXXABI(lm), useARMMethodPtrABI(useARMMethodPtrABI) {}
44 lowerDataMemberType(cir::DataMemberType type,
45 const mlir::TypeConverter &typeConverter)
const override;
48 lowerMethodType(cir::MethodType type,
49 const mlir::TypeConverter &typeConverter)
const override;
51 mlir::TypedAttr lowerDataMemberConstant(
52 cir::DataMemberAttr attr,
const mlir::DataLayout &layout,
53 const mlir::TypeConverter &typeConverter)
const override;
56 lowerMethodConstant(cir::MethodAttr attr,
const mlir::DataLayout &layout,
57 const mlir::TypeConverter &typeConverter)
const override;
60 lowerGetRuntimeMember(cir::GetRuntimeMemberOp op, mlir::Type loweredResultTy,
61 mlir::Value loweredAddr, mlir::Value loweredMember,
62 mlir::OpBuilder &builder)
const override;
64 void lowerGetMethod(cir::GetMethodOp op, mlir::Value &callee,
65 mlir::Value &thisArg, mlir::Value loweredMethod,
66 mlir::Value loweredObjectPtr,
67 mlir::ConversionPatternRewriter &rewriter)
const override;
69 mlir::Value lowerBaseDataMember(cir::BaseDataMemberOp op,
70 mlir::Value loweredSrc,
71 mlir::OpBuilder &builder)
const override;
73 mlir::Value lowerDerivedDataMember(cir::DerivedDataMemberOp op,
74 mlir::Value loweredSrc,
75 mlir::OpBuilder &builder)
const override;
77 mlir::Value lowerBaseMethod(cir::BaseMethodOp op, mlir::Value loweredSrc,
78 mlir::OpBuilder &builder)
const override;
80 mlir::Value lowerDerivedMethod(cir::DerivedMethodOp op,
81 mlir::Value loweredSrc,
82 mlir::OpBuilder &builder)
const override;
84 mlir::Value lowerDataMemberCmp(cir::CmpOp op, mlir::Value loweredLhs,
85 mlir::Value loweredRhs,
86 mlir::OpBuilder &builder)
const override;
88 mlir::Value lowerMethodCmp(cir::CmpOp op, mlir::Value loweredLhs,
89 mlir::Value loweredRhs,
90 mlir::OpBuilder &builder)
const override;
92 mlir::Value lowerDataMemberBitcast(cir::CastOp op, mlir::Type loweredDstTy,
93 mlir::Value loweredSrc,
94 mlir::OpBuilder &builder)
const override;
97 lowerDataMemberToBoolCast(cir::CastOp op, mlir::Value loweredSrc,
98 mlir::OpBuilder &builder)
const override;
100 mlir::Value lowerMethodBitcast(cir::CastOp op, mlir::Type loweredDstTy,
101 mlir::Value loweredSrc,
102 mlir::OpBuilder &builder)
const override;
104 mlir::Value lowerMethodToBoolCast(cir::CastOp op, mlir::Value loweredSrc,
105 mlir::OpBuilder &builder)
const override;
107 mlir::Value lowerDynamicCast(cir::DynamicCastOp op,
108 mlir::OpBuilder &builder)
const override;
109 mlir::Value lowerVTableGetTypeInfo(cir::VTableGetTypeInfoOp op,
110 mlir::OpBuilder &builder)
const override;
113 getArrayCookieSizeImpl(mlir::Type elementType,
114 const mlir::DataLayout &dataLayout)
const override;
116 mlir::Value readArrayCookieImpl(mlir::Location loc, mlir::Value allocPtr,
117 clang::CharUnits cookieSize,
118 clang::CharUnits cookieAlignment,
119 const mlir::DataLayout &dataLayout,
120 CIRBaseBuilderTy &builder)
const override;
130 case clang::TargetCXXABI::GenericAArch64:
131 case clang::TargetCXXABI::AppleARM64:
135 return std::make_unique<LowerItaniumCXXABI>(lm,
138 case clang::TargetCXXABI::GenericItanium:
139 return std::make_unique<LowerItaniumCXXABI>(lm);
141 case clang::TargetCXXABI::Microsoft:
142 llvm_unreachable(
"Microsoft ABI is not Itanium-based");
144 llvm_unreachable(
"Other Itanium ABI?");
156mlir::Type LowerItaniumCXXABI::lowerDataMemberType(
157 cir::DataMemberType type,
const mlir::TypeConverter &typeConverter)
const {
161 return getPtrDiffCIRTy(lm);
164mlir::Type LowerItaniumCXXABI::lowerMethodType(
165 cir::MethodType type,
const mlir::TypeConverter &typeConverter)
const {
180 return cir::RecordType::get(
type.getContext(), {ptrdiffCIRTy, ptrdiffCIRTy},
182 cir::RecordType::Struct);
185mlir::TypedAttr LowerItaniumCXXABI::lowerDataMemberConstant(
186 cir::DataMemberAttr attr,
const mlir::DataLayout &layout,
187 const mlir::TypeConverter &typeConverter)
const {
189 if (
attr.isNullPtr()) {
197 unsigned memberIndex =
attr.getMemberIndex().value();
199 attr.getType().getClassTy().getElementOffset(layout, memberIndex);
202 mlir::Type abiTy = lowerDataMemberType(
attr.getType(), typeConverter);
203 return cir::IntAttr::get(abiTy, memberOffset);
206mlir::TypedAttr LowerItaniumCXXABI::lowerMethodConstant(
207 cir::MethodAttr attr,
const mlir::DataLayout &layout,
208 const mlir::TypeConverter &typeConverter)
const {
214 auto loweredMethodTy = mlir::cast<cir::RecordType>(
215 lowerMethodType(
attr.getType(), typeConverter));
217 auto zero = cir::IntAttr::get(ptrdiffCIRTy, 0);
238 return cir::ConstRecordAttr::get(
239 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {zero, zero}));
242 if (
attr.isVirtual()) {
243 if (useARMMethodPtrABI) {
250 llvm_unreachable(
"ARM method ptr abi NYI");
261 cir::IntAttr::get(ptrdiffCIRTy, 1 +
attr.getVtableOffset().value());
262 return cir::ConstRecordAttr::get(
263 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {ptr, zero}));
271 auto ptr = cir::GlobalViewAttr::get(ptrdiffCIRTy,
attr.getSymbol().value());
272 return cir::ConstRecordAttr::get(
273 loweredMethodTy, mlir::ArrayAttr::get(
attr.getContext(), {ptr, zero}));
276mlir::Operation *LowerItaniumCXXABI::lowerGetRuntimeMember(
277 cir::GetRuntimeMemberOp op, mlir::Type loweredResultTy,
278 mlir::Value loweredAddr, mlir::Value loweredMember,
279 mlir::OpBuilder &builder)
const {
280 auto byteTy = cir::IntType::get(op.getContext(), 8,
true);
281 auto bytePtrTy = cir::PointerType::get(
283 mlir::cast<cir::PointerType>(op.getAddr().getType()).getAddrSpace());
284 auto objectBytesPtr = cir::CastOp::create(
285 builder, op.getLoc(), bytePtrTy, cir::CastKind::bitcast, op.getAddr());
286 auto memberBytesPtr = cir::PtrStrideOp::create(
287 builder, op.getLoc(), bytePtrTy, objectBytesPtr, loweredMember);
288 return cir::CastOp::create(builder, op.getLoc(), op.getType(),
289 cir::CastKind::bitcast, memberBytesPtr);
292void LowerItaniumCXXABI::lowerGetMethod(
293 cir::GetMethodOp op, mlir::Value &callee, mlir::Value &thisArg,
294 mlir::Value loweredMethod, mlir::Value loweredObjectPtr,
295 mlir::ConversionPatternRewriter &rewriter)
const {
317 mlir::ImplicitLocOpBuilder locBuilder(op.getLoc(), rewriter);
318 mlir::Type calleePtrTy = op.getCallee().getType();
321 mlir::Value ptrdiffOne =
322 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 1));
325 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredMethod, 1);
326 if (useARMMethodPtrABI) {
327 op.emitError(
"ARM method ptr abi NYI");
332 mlir::Type thisVoidPtrTy =
333 cir::PointerType::get(cir::VoidType::get(locBuilder.getContext()),
334 op.getObject().getType().getAddrSpace());
335 mlir::Value thisVoidPtr = cir::CastOp::create(
336 locBuilder, thisVoidPtrTy, cir::CastKind::bitcast, loweredObjectPtr);
338 cir::PtrStrideOp::create(locBuilder, thisVoidPtrTy, thisVoidPtr, adj);
342 mlir::Value methodPtrField =
343 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredMethod, 0);
344 mlir::Value virtualBit =
345 cir::AndOp::create(rewriter, op.getLoc(), methodPtrField, ptrdiffOne);
346 mlir::Value isVirtual;
347 if (useARMMethodPtrABI)
348 llvm_unreachable(
"ARM method ptr abi NYI");
350 isVirtual = cir::CmpOp::create(locBuilder, cir::CmpOpKind::eq, virtualBit,
357 auto buildVirtualCallee = [&](mlir::OpBuilder &
b, mlir::Location loc) {
361 cir::PointerType::get(cir::IntType::get(
b.getContext(), 8,
true));
362 auto vtablePtrPtrTy = cir::PointerType::get(
363 vtablePtrTy, op.getObject().getType().getAddrSpace());
364 auto vtablePtrPtr = cir::CastOp::create(
b, loc, vtablePtrPtrTy,
365 cir::CastKind::bitcast, thisArg);
367 mlir::Value vtablePtr =
368 cir::LoadOp::create(
b, loc, vtablePtrPtr,
false,
371 cir::SyncScopeKindAttr{},
372 cir::MemOrderAttr());
375 mlir::Value vtableOffset = methodPtrField;
376 assert(!useARMMethodPtrABI &&
"ARM method ptr abi NYI");
377 vtableOffset = cir::SubOp::create(
b, loc, vtableOffset.getType(),
378 vtableOffset, ptrdiffOne);
386 mlir::Value vfpAddr = cir::PtrStrideOp::create(locBuilder, vtablePtrTy,
387 vtablePtr, vtableOffset);
388 auto vfpPtrTy = cir::PointerType::get(calleePtrTy);
389 mlir::Value vfpPtr = cir::CastOp::create(locBuilder, vfpPtrTy,
390 cir::CastKind::bitcast, vfpAddr);
391 auto fnPtr = cir::LoadOp::create(
b, loc, vfpPtr,
394 cir::SyncScopeKindAttr{},
395 cir::MemOrderAttr());
397 cir::YieldOp::create(
b, loc, fnPtr.getResult());
401 callee = cir::TernaryOp::create(
402 locBuilder, isVirtual, buildVirtualCallee,
404 [&](mlir::OpBuilder &
b, mlir::Location loc) {
405 auto fnPtr = cir::CastOp::create(
b, loc, calleePtrTy,
406 cir::CastKind::int_to_ptr,
408 cir::YieldOp::create(
b, loc, fnPtr.getResult());
414 mlir::Value loweredSrc,
416 bool isDerivedToBase,
417 mlir::OpBuilder &builder) {
420 mlir::Location loc = op->getLoc();
421 mlir::Type ty = loweredSrc.getType();
423 auto getConstantInt = [&](int64_t value) -> cir::ConstantOp {
424 return cir::ConstantOp::create(builder, loc, cir::IntAttr::get(ty, value));
427 cir::ConstantOp nullValue = getConstantInt(-1);
428 auto isNull = cir::CmpOp::create(builder, loc, cir::CmpOpKind::eq, loweredSrc,
431 cir::ConstantOp offsetValue = getConstantInt(offset);
432 mlir::Value adjustedPtr;
433 if (isDerivedToBase) {
434 auto subOp = cir::SubOp::create(builder, loc, ty, loweredSrc, offsetValue);
435 subOp.setNoSignedWrap(
true);
438 auto addOp = cir::AddOp::create(builder, loc, ty, loweredSrc, offsetValue);
439 addOp.setNoSignedWrap(
true);
443 return cir::SelectOp::create(builder, loc, ty, isNull, loweredSrc,
448LowerItaniumCXXABI::lowerBaseDataMember(cir::BaseDataMemberOp op,
449 mlir::Value loweredSrc,
450 mlir::OpBuilder &builder)
const {
451 return lowerDataMemberCast(op, loweredSrc, op.getOffset().getSExtValue(),
456LowerItaniumCXXABI::lowerDerivedDataMember(cir::DerivedDataMemberOp op,
457 mlir::Value loweredSrc,
458 mlir::OpBuilder &builder)
const {
464 std::int64_t offset,
bool isDerivedToBase,
466 mlir::OpBuilder &builder) {
471 auto adjField = cir::ExtractMemberOp::create(builder, op->getLoc(),
472 ptrdiffCIRTy, loweredSrc, 1);
474 auto offsetValue = cir::ConstantOp::create(
475 builder, op->getLoc(), cir::IntAttr::get(ptrdiffCIRTy, offset));
476 mlir::Value adjustedAdjField;
477 if (isDerivedToBase) {
478 auto subOp = cir::SubOp::create(builder, op->getLoc(), ptrdiffCIRTy,
479 adjField, offsetValue);
480 subOp.setNoSignedWrap(
true);
481 adjustedAdjField = subOp;
483 auto addOp = cir::AddOp::create(builder, op->getLoc(), ptrdiffCIRTy,
484 adjField, offsetValue);
485 addOp.setNoSignedWrap(
true);
486 adjustedAdjField = addOp;
489 return cir::InsertMemberOp::create(builder, op->getLoc(), loweredSrc, 1,
494LowerItaniumCXXABI::lowerBaseMethod(cir::BaseMethodOp op,
495 mlir::Value loweredSrc,
496 mlir::OpBuilder &builder)
const {
497 return lowerMethodCast(op, loweredSrc, op.getOffset().getSExtValue(),
502LowerItaniumCXXABI::lowerDerivedMethod(cir::DerivedMethodOp op,
503 mlir::Value loweredSrc,
504 mlir::OpBuilder &builder)
const {
510LowerItaniumCXXABI::lowerDataMemberCmp(cir::CmpOp op, mlir::Value loweredLhs,
511 mlir::Value loweredRhs,
512 mlir::OpBuilder &builder)
const {
513 return cir::CmpOp::create(builder, op.getLoc(), op.getKind(), loweredLhs,
517mlir::Value LowerItaniumCXXABI::lowerMethodCmp(cir::CmpOp op,
518 mlir::Value loweredLhs,
519 mlir::Value loweredRhs,
520 mlir::OpBuilder &builder)
const {
521 assert(op.getKind() == cir::CmpOpKind::eq ||
522 op.getKind() == cir::CmpOpKind::ne);
524 mlir::ImplicitLocOpBuilder locBuilder(op.getLoc(), builder);
526 mlir::Value ptrdiffZero =
527 cir::ConstantOp::create(locBuilder, cir::IntAttr::get(ptrdiffCIRTy, 0));
529 mlir::Value lhsPtrField =
530 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredLhs, 0);
531 mlir::Value rhsPtrField =
532 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredRhs, 0);
534 cir::CmpOp::create(locBuilder, op.getKind(), lhsPtrField, rhsPtrField);
535 mlir::Value ptrCmpToNull =
536 cir::CmpOp::create(locBuilder, op.getKind(), lhsPtrField, ptrdiffZero);
538 mlir::Value lhsAdjField =
539 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredLhs, 1);
540 mlir::Value rhsAdjField =
541 cir::ExtractMemberOp::create(locBuilder, ptrdiffCIRTy, loweredRhs, 1);
543 cir::CmpOp::create(locBuilder, op.getKind(), lhsAdjField, rhsAdjField);
545 auto create_and = [&](mlir::Value lhs, mlir::Value rhs) {
546 return cir::AndOp::create(locBuilder, lhs.getType(), lhs, rhs);
548 auto create_or = [&](mlir::Value lhs, mlir::Value rhs) {
549 return cir::OrOp::create(locBuilder, lhs.getType(), lhs, rhs);
553 if (op.getKind() == cir::CmpOpKind::eq) {
555 result = create_and(ptrCmp, create_or(ptrCmpToNull, adjCmp));
558 result = create_or(ptrCmp, create_and(ptrCmpToNull, adjCmp));
564mlir::Value LowerItaniumCXXABI::lowerDataMemberBitcast(
565 cir::CastOp op, mlir::Type loweredDstTy, mlir::Value loweredSrc,
566 mlir::OpBuilder &builder)
const {
567 if (loweredSrc.getType() == loweredDstTy)
570 return cir::CastOp::create(builder, op.getLoc(), loweredDstTy,
571 cir::CastKind::bitcast, loweredSrc);
574mlir::Value LowerItaniumCXXABI::lowerDataMemberToBoolCast(
575 cir::CastOp op, mlir::Value loweredSrc, mlir::OpBuilder &builder)
const {
579 auto nullValue = cir::ConstantOp::create(builder, op.getLoc(), nullAttr);
580 return cir::CmpOp::create(builder, op.getLoc(), cir::CmpOpKind::ne,
581 loweredSrc, nullValue);
585LowerItaniumCXXABI::lowerMethodBitcast(cir::CastOp op, mlir::Type loweredDstTy,
586 mlir::Value loweredSrc,
587 mlir::OpBuilder &builder)
const {
588 if (loweredSrc.getType() == loweredDstTy)
594mlir::Value LowerItaniumCXXABI::lowerMethodToBoolCast(
595 cir::CastOp op, mlir::Value loweredSrc, mlir::OpBuilder &builder)
const {
602 mlir::Value ptrdiffZero = cir::ConstantOp::create(
603 builder, op.getLoc(), cir::IntAttr::get(ptrdiffCIRTy, 0));
604 mlir::Value ptrField = cir::ExtractMemberOp::create(
605 builder, op.getLoc(), ptrdiffCIRTy, loweredSrc, 0);
606 return cir::CmpOp::create(builder, op.getLoc(), cir::CmpOpKind::ne, ptrField,
611 mlir::FlatSymbolRefAttr badCastFuncRef) {
612 cir::CallOp::create(builder, loc, badCastFuncRef, cir::VoidType(),
617 cir::UnreachableOp::create(builder, loc);
618 builder.clearInsertionPoint();
622 mlir::OpBuilder &builder) {
623 mlir::Location loc = op->getLoc();
624 mlir::Value srcValue = op.getSrc();
625 cir::DynamicCastInfoAttr castInfo = op.getInfo().value();
631 cir::PointerType::get(cir::VoidType::get(builder.getContext()));
633 mlir::Value srcPtr = cir::CastOp::create(builder, loc, voidPtrTy,
634 cir::CastKind::bitcast, srcValue);
635 mlir::Value srcRtti =
636 cir::ConstantOp::create(builder, loc, castInfo.getSrcRtti());
637 mlir::Value destRtti =
638 cir::ConstantOp::create(builder, loc, castInfo.getDestRtti());
639 mlir::Value offsetHint =
640 cir::ConstantOp::create(builder, loc, castInfo.getOffsetHint());
642 mlir::FlatSymbolRefAttr dynCastFuncRef = castInfo.getRuntimeFunc();
643 mlir::Value dynCastFuncArgs[4] = {srcPtr, srcRtti, destRtti, offsetHint};
645 mlir::Value castedPtr = cir::CallOp::create(builder, loc, dynCastFuncRef,
646 voidPtrTy, dynCastFuncArgs)
649 assert(mlir::isa<cir::PointerType>(castedPtr.getType()) &&
650 "the return value of __dynamic_cast should be a ptr");
654 if (op.isRefCast()) {
656 mlir::Value null = cir::ConstantOp::create(
658 cir::ConstPtrAttr::get(castedPtr.getType(),
659 builder.getI64IntegerAttr(0)));
660 mlir::Value castedPtrIsNull =
661 cir::CmpOp::create(builder, loc, cir::CmpOpKind::eq, castedPtr, null);
662 cir::IfOp::create(builder, loc, castedPtrIsNull,
false,
663 [&](mlir::OpBuilder &, mlir::Location) {
665 castInfo.getBadCastFunc());
671 return cir::CastOp::create(builder, loc, op.getType(), cir::CastKind::bitcast,
677 mlir::Location loc = op.getLoc();
678 bool vtableUsesRelativeLayout = op.getRelativeLayout();
683 mlir::Type vtableElemTy;
684 uint64_t vtableElemAlign;
685 if (vtableUsesRelativeLayout) {
687 cir::IntType::get(builder.getContext(), 32,
true);
691 vtableElemAlign = llvm::divideCeil(
695 mlir::Type vtableElemPtrTy = cir::PointerType::get(vtableElemTy);
696 mlir::Type i64Ty = cir::IntType::get(builder.getContext(), 64,
702 auto vptrPtr = cir::VTableGetVPtrOp::create(builder, loc, op.getSrc());
703 mlir::Value vptr = cir::LoadOp::create(
704 builder, loc, vptrPtr,
707 builder.getI64IntegerAttr(vtableElemAlign),
708 cir::SyncScopeKindAttr(),
709 cir::MemOrderAttr());
710 mlir::Value elementPtr = cir::CastOp::create(builder, loc, vtableElemPtrTy,
711 cir::CastKind::bitcast, vptr);
712 mlir::Value minusTwo =
713 cir::ConstantOp::create(builder, loc, cir::IntAttr::get(i64Ty, -2));
714 mlir::Value offsetToTopSlotPtr = cir::PtrStrideOp::create(
715 builder, loc, vtableElemPtrTy, elementPtr, minusTwo);
716 mlir::Value offsetToTop = cir::LoadOp::create(
717 builder, loc, offsetToTopSlotPtr,
720 builder.getI64IntegerAttr(vtableElemAlign),
721 cir::SyncScopeKindAttr(),
722 cir::MemOrderAttr());
725 cir::PointerType::get(cir::VoidType::get(builder.getContext()));
730 cir::PointerType::get(cir::IntType::get(builder.getContext(), 8,
732 mlir::Value srcBytePtr = cir::CastOp::create(
733 builder, loc, u8PtrTy, cir::CastKind::bitcast, op.getSrc());
735 cir::PtrStrideOp::create(builder, loc, u8PtrTy, srcBytePtr, offsetToTop);
737 return cir::CastOp::create(builder, loc, voidPtrTy, cir::CastKind::bitcast,
742LowerItaniumCXXABI::lowerDynamicCast(cir::DynamicCastOp op,
743 mlir::OpBuilder &builder)
const {
744 mlir::Location loc = op->getLoc();
745 mlir::Value srcValue = op.getSrc();
750 return buildDynamicCastAfterNullCheck(op, builder);
752 mlir::Value srcValueIsNotNull = cir::CastOp::create(
753 builder, loc, cir::BoolType::get(builder.getContext()),
754 cir::CastKind::ptr_to_bool, srcValue);
755 return cir::TernaryOp::create(
756 builder, loc, srcValueIsNotNull,
757 [&](mlir::OpBuilder &, mlir::Location) {
758 mlir::Value castedValue =
760 ? buildDynamicCastToVoidAfterNullCheck(op, lm, builder)
761 : buildDynamicCastAfterNullCheck(op, builder);
762 cir::YieldOp::create(builder, loc, castedValue);
764 [&](mlir::OpBuilder &, mlir::Location) {
765 mlir::Value null = cir::ConstantOp::create(
767 cir::ConstPtrAttr::get(op.getType(),
768 builder.getI64IntegerAttr(0)));
769 cir::YieldOp::create(builder, loc, null);
774LowerItaniumCXXABI::lowerVTableGetTypeInfo(cir::VTableGetTypeInfoOp op,
775 mlir::OpBuilder &builder)
const {
776 mlir::Location loc = op->getLoc();
777 auto offset = cir::ConstantOp::create(
781 auto vptrCast = cir::CastOp::create(builder, loc, op.getType(),
782 cir::CastKind::bitcast, op.getVptr());
784 return cir::PtrStrideOp::create(builder, loc, vptrCast.getType(), vptrCast,
789clang::CharUnits LowerItaniumCXXABI::getArrayCookieSizeImpl(
790 mlir::Type elementType,
const mlir::DataLayout &dataLayout)
const {
793 clang::CharUnits sizeOfSizeT =
796 dataLayout.getTypePreferredAlignment(elementType));
797 return std::max(sizeOfSizeT, eltAlign);
800mlir::Value LowerItaniumCXXABI::readArrayCookieImpl(
801 mlir::Location loc, mlir::Value allocPtr, clang::CharUnits cookieSize,
802 clang::CharUnits cookieAlignment,
const mlir::DataLayout &dataLayout,
803 CIRBaseBuilderTy &builder)
const {
804 unsigned ptrSizeInBits = getPtrSizeInBits();
805 auto u8PtrTy = builder.getPointerTo(builder.getUIntNTy(8));
806 auto ptrDiffTy = builder.getSIntNTy(ptrSizeInBits);
807 auto sizeTy = builder.getUIntNTy(ptrSizeInBits);
810 clang::CharUnits sizeOfSizeT =
812 clang::CharUnits countOffset = cookieSize - sizeOfSizeT;
814 mlir::Value countBytePtr = allocPtr;
815 clang::CharUnits countAlignment = cookieAlignment;
816 if (!countOffset.
isZero()) {
817 mlir::Value offsetVal = cir::ConstantOp::create(
818 builder, loc, cir::IntAttr::get(ptrDiffTy, countOffset.
getQuantity()));
820 cir::PtrStrideOp::create(builder, loc, u8PtrTy, allocPtr, offsetVal);
824 auto countPtrTy = cir::PointerType::get(sizeTy);
825 mlir::Value countPtr = cir::CastOp::create(
826 builder, loc, countPtrTy, cir::CastKind::bitcast, countBytePtr);
827 return cir::LoadOp::create(
828 builder, loc, countPtr,
false,
false,
829 builder.getI64IntegerAttr(countAlignment.
getQuantity()),
830 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 void buildBadCastCall(mlir::OpBuilder &builder, mlir::Location loc, mlir::FlatSymbolRefAttr badCastFuncRef)
static mlir::Value lowerMethodCast(mlir::Operation *op, mlir::Value loweredSrc, std::int64_t offset, bool isDerivedToBase, LowerModule &lowerMod, mlir::OpBuilder &builder)
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 opFuncNoReturn()
static bool emitWPDInfo()
static bool emitTypeCheck()
IntType
===-— Target Data Type Query Methods ----------------------------—===//