clang 22.0.0git
LoweringPrepareItaniumCXXABI.cpp
Go to the documentation of this file.
1//===--------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with
4// LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===--------------------------------------------------------------------===//
9//
10// This file provides Itanium C++ ABI specific code
11// that is used during LLVMIR lowering prepare.
12//
13//===--------------------------------------------------------------------===//
14
16#include "mlir/IR/BuiltinAttributes.h"
17#include "mlir/IR/Value.h"
18#include "mlir/IR/ValueRange.h"
25
27public:
28 mlir::Value lowerDynamicCast(cir::CIRBaseBuilderTy &builder,
29 clang::ASTContext &astCtx,
30 cir::DynamicCastOp op) override;
31};
32
36
37static void buildBadCastCall(cir::CIRBaseBuilderTy &builder, mlir::Location loc,
38 mlir::FlatSymbolRefAttr badCastFuncRef) {
39 builder.createCallOp(loc, badCastFuncRef, cir::VoidType(),
40 mlir::ValueRange{});
41 // TODO(cir): Set the 'noreturn' attribute on the function.
43 cir::UnreachableOp::create(builder, loc);
44 builder.clearInsertionPoint();
45}
46
47static mlir::Value
49 cir::DynamicCastOp op) {
50 mlir::Location loc = op->getLoc();
51 mlir::Value srcValue = op.getSrc();
52 cir::DynamicCastInfoAttr castInfo = op.getInfo().value();
53
54 // TODO(cir): consider address space
56
57 mlir::Value srcPtr = builder.createBitcast(srcValue, builder.getVoidPtrTy());
58 cir::ConstantOp srcRtti = builder.getConstant(loc, castInfo.getSrcRtti());
59 cir::ConstantOp destRtti = builder.getConstant(loc, castInfo.getDestRtti());
60 cir::ConstantOp offsetHint =
61 builder.getConstant(loc, castInfo.getOffsetHint());
62
63 mlir::FlatSymbolRefAttr dynCastFuncRef = castInfo.getRuntimeFunc();
64 mlir::Value dynCastFuncArgs[4] = {srcPtr, srcRtti, destRtti, offsetHint};
65
66 mlir::Value castedPtr =
67 builder
68 .createCallOp(loc, dynCastFuncRef, builder.getVoidPtrTy(),
69 dynCastFuncArgs)
70 .getResult();
71
72 assert(mlir::isa<cir::PointerType>(castedPtr.getType()) &&
73 "the return value of __dynamic_cast should be a ptr");
74
75 /// C++ [expr.dynamic.cast]p9:
76 /// A failed cast to reference type throws std::bad_cast
77 if (op.isRefCast()) {
78 // Emit a cir.if that checks the casted value.
79 mlir::Value castedValueIsNull = builder.createPtrIsNull(castedPtr);
80 builder.create<cir::IfOp>(
81 loc, castedValueIsNull, false, [&](mlir::OpBuilder &, mlir::Location) {
82 buildBadCastCall(builder, loc, castInfo.getBadCastFunc());
83 });
84 }
85
86 // Note that castedPtr is a void*. Cast it to a pointer to the destination
87 // type before return.
88 return builder.createBitcast(castedPtr, op.getType());
89}
90
91static mlir::Value
93 clang::ASTContext &astCtx,
94 cir::DynamicCastOp op) {
95 llvm_unreachable("dynamic cast to void is NYI");
96}
97
98mlir::Value
100 clang::ASTContext &astCtx,
101 cir::DynamicCastOp op) {
102 mlir::Location loc = op->getLoc();
103 mlir::Value srcValue = op.getSrc();
104
106
107 if (op.isRefCast())
108 return buildDynamicCastAfterNullCheck(builder, op);
109
110 mlir::Value srcValueIsNotNull = builder.createPtrToBoolCast(srcValue);
111 return builder
112 .create<cir::TernaryOp>(
113 loc, srcValueIsNotNull,
114 [&](mlir::OpBuilder &, mlir::Location) {
115 mlir::Value castedValue =
116 op.isCastToVoid()
117 ? buildDynamicCastToVoidAfterNullCheck(builder, astCtx, op)
118 : buildDynamicCastAfterNullCheck(builder, op);
119 builder.createYield(loc, castedValue);
120 },
121 [&](mlir::OpBuilder &, mlir::Location) {
122 builder.createYield(
123 loc, builder.getNullPtr(op.getType(), loc).getResult());
124 })
125 .getResult();
126}
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::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc)
cir::CallOp createCallOp(mlir::Location loc, mlir::SymbolRefAttr callee, mlir::Type returnType, mlir::ValueRange operands, llvm::ArrayRef< mlir::NamedAttribute > attrs={})
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
mlir::Value createPtrToBoolCast(mlir::Value v)
cir::PointerType getVoidPtrTy(clang::LangAS langAS=clang::LangAS::Default)
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 ...
Definition ASTContext.h:220
Defines the clang::TargetInfo interface.
static bool addressSpace()
static bool opFuncNoReturn()
static bool emitTypeCheck()