16#include "mlir/IR/BuiltinAttributes.h"
17#include "mlir/IR/Value.h"
18#include "mlir/IR/ValueRange.h"
30 cir::DynamicCastOp op)
override;
38 mlir::FlatSymbolRefAttr badCastFuncRef) {
39 builder.
createCallOp(loc, badCastFuncRef, cir::VoidType(),
43 cir::UnreachableOp::create(builder, loc);
44 builder.clearInsertionPoint();
49 cir::DynamicCastOp op) {
50 mlir::Location loc = op->getLoc();
51 mlir::Value srcValue = op.getSrc();
52 cir::DynamicCastInfoAttr castInfo = op.getInfo().value();
58 cir::ConstantOp srcRtti = builder.
getConstant(loc, castInfo.getSrcRtti());
59 cir::ConstantOp destRtti = builder.
getConstant(loc, castInfo.getDestRtti());
60 cir::ConstantOp offsetHint =
63 mlir::FlatSymbolRefAttr dynCastFuncRef = castInfo.getRuntimeFunc();
64 mlir::Value dynCastFuncArgs[4] = {srcPtr, srcRtti, destRtti, offsetHint};
66 mlir::Value castedPtr =
72 assert(mlir::isa<cir::PointerType>(castedPtr.getType()) &&
73 "the return value of __dynamic_cast should be a ptr");
80 cir::IfOp::create(builder, loc, castedValueIsNull,
false,
81 [&](mlir::OpBuilder &, mlir::Location) {
83 castInfo.getBadCastFunc());
95 cir::DynamicCastOp op) {
96 mlir::Location loc = op.getLoc();
97 bool vtableUsesRelativeLayout = op.getRelativeLayout();
102 mlir::Type vtableElemTy;
103 uint64_t vtableElemAlign;
104 if (vtableUsesRelativeLayout) {
111 uint64_t ptrdiffTyWidth = targetInfo.getTypeWidth(ptrdiffTy);
113 vtableElemTy = cir::IntType::get(builder.getContext(), ptrdiffTyWidth,
122 auto vptrTy = cir::VPtrType::get(builder.getContext());
123 cir::PointerType vptrPtrTy = builder.
getPointerTo(vptrTy);
125 cir::VTableGetVPtrOp::create(builder, loc, vptrPtrTy, op.getSrc());
126 mlir::Value vptr = builder.
createLoad(loc, vptrPtr);
127 mlir::Value elementPtr =
129 mlir::Value minusTwo = builder.
getSignedInt(loc, -2, 64);
130 auto offsetToTopSlotPtr = cir::PtrStrideOp::create(
131 builder, loc, builder.
getPointerTo(vtableElemTy), elementPtr, minusTwo);
132 mlir::Value offsetToTop =
138 mlir::Value srcBytePtr = builder.
createBitcast(op.getSrc(), u8PtrTy);
140 cir::PtrStrideOp::create(builder, loc, u8PtrTy, srcBytePtr, offsetToTop);
148 cir::DynamicCastOp op) {
149 mlir::Location loc = op->getLoc();
150 mlir::Value srcValue = op.getSrc();
158 return cir::TernaryOp::create(
159 builder, loc, srcValueIsNotNull,
160 [&](mlir::OpBuilder &, mlir::Location) {
161 mlir::Value castedValue =
168 [&](mlir::OpBuilder &, mlir::Location) {
170 loc, builder.
getNullPtr(op.getType(), loc).getResult());
static void buildBadCastCall(cir::CIRBaseBuilderTy &builder, mlir::Location loc, mlir::FlatSymbolRefAttr badCastFuncRef)
static mlir::Value buildDynamicCastToVoidAfterNullCheck(cir::CIRBaseBuilderTy &builder, clang::ASTContext &astCtx, cir::DynamicCastOp op)
static mlir::Value buildDynamicCastAfterNullCheck(cir::CIRBaseBuilderTy &builder, cir::DynamicCastOp op)
mlir::Value lowerDynamicCast(cir::CIRBaseBuilderTy &builder, clang::ASTContext &astCtx, cir::DynamicCastOp op) override
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
mlir::Value createPtrIsNull(mlir::Value ptr)
cir::PointerType getPointerTo(mlir::Type ty)
cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc)
cir::IntType getUIntNTy(int n)
cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee, mlir::Type returnType, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={})
mlir::Value getSignedInt(mlir::Location loc, int64_t val, unsigned numBits)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
cir::LoadOp createLoad(mlir::Location loc, mlir::Value ptr, bool isVolatile=false, uint64_t alignment=0)
mlir::Value createPtrToBoolCast(mlir::Value v)
cir::PointerType getVoidPtrTy(clang::LangAS langAS=clang::LangAS::Default)
cir::IntType getSIntNTy(int n)
mlir::Value createAlignedLoad(mlir::Location loc, mlir::Value ptr, uint64_t alignment)
cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value={})
Create a yield operation.
static LoweringPrepareCXXABI * createItaniumABI()
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const TargetInfo & getTargetInfo() const
static bool isTypeSigned(IntType T)
Returns true if the type is signed; false otherwise.
IntType getPtrDiffType(LangAS AddrSpace) const
Defines the clang::TargetInfo interface.
static bool addressSpace()
static bool opFuncNoReturn()
static bool emitTypeCheck()