Skip to content

Commit 27d8bd3

Browse files
mmhaerichkeane
andauthored
[CIR] Upstream CastOp and scalar conversions (#130690)
This patch upstreams ClangIR's CastOp with the following exceptions: - No Fixed/FP conversions - No casts between value categories - No complex casts - No array_to_ptrdecay - No address_space - No casts involving record types (member pointers, base/derived casts) - No casts specific to ObjC or OpenCL --------- Co-authored-by: Morris Hafner <[email protected]> Co-authored-by: Erich Keane <[email protected]>
1 parent dea5aa7 commit 27d8bd3

File tree

14 files changed

+1284
-21
lines changed

14 files changed

+1284
-21
lines changed

clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010
#define LLVM_CLANG_CIR_DIALECT_BUILDER_CIRBASEBUILDER_H
1111

1212
#include "clang/AST/CharUnits.h"
13+
#include "clang/AST/Type.h"
1314
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
1415
#include "clang/CIR/Dialect/IR/CIRDialect.h"
1516
#include "clang/CIR/Dialect/IR/CIRTypes.h"
17+
#include "llvm/Support/ErrorHandling.h"
1618

1719
#include "mlir/IR/Builders.h"
1820
#include "mlir/IR/BuiltinTypes.h"
@@ -78,6 +80,60 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
7880
return create<cir::StoreOp>(loc, val, dst);
7981
}
8082

83+
mlir::Value createDummyValue(mlir::Location loc, mlir::Type type,
84+
clang::CharUnits alignment) {
85+
auto addr = createAlloca(loc, getPointerTo(type), type, {},
86+
getSizeFromCharUnits(getContext(), alignment));
87+
return createLoad(loc, addr);
88+
}
89+
90+
//===--------------------------------------------------------------------===//
91+
// Cast/Conversion Operators
92+
//===--------------------------------------------------------------------===//
93+
94+
mlir::Value createCast(mlir::Location loc, cir::CastKind kind,
95+
mlir::Value src, mlir::Type newTy) {
96+
if (newTy == src.getType())
97+
return src;
98+
return create<cir::CastOp>(loc, newTy, kind, src);
99+
}
100+
101+
mlir::Value createCast(cir::CastKind kind, mlir::Value src,
102+
mlir::Type newTy) {
103+
if (newTy == src.getType())
104+
return src;
105+
return createCast(src.getLoc(), kind, src, newTy);
106+
}
107+
108+
mlir::Value createIntCast(mlir::Value src, mlir::Type newTy) {
109+
return createCast(cir::CastKind::integral, src, newTy);
110+
}
111+
112+
mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy) {
113+
return createCast(cir::CastKind::int_to_ptr, src, newTy);
114+
}
115+
116+
mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy) {
117+
return createCast(cir::CastKind::ptr_to_int, src, newTy);
118+
}
119+
120+
mlir::Value createPtrToBoolCast(mlir::Value v) {
121+
return createCast(cir::CastKind::ptr_to_bool, v, getBoolTy());
122+
}
123+
124+
mlir::Value createBoolToInt(mlir::Value src, mlir::Type newTy) {
125+
return createCast(cir::CastKind::bool_to_int, src, newTy);
126+
}
127+
128+
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy) {
129+
return createCast(cir::CastKind::bitcast, src, newTy);
130+
}
131+
132+
mlir::Value createBitcast(mlir::Location loc, mlir::Value src,
133+
mlir::Type newTy) {
134+
return createCast(loc, cir::CastKind::bitcast, src, newTy);
135+
}
136+
81137
//
82138
// Block handling helpers
83139
// ----------------------

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,156 @@ class LLVMLoweringInfo {
7878
class CIR_Op<string mnemonic, list<Trait> traits = []> :
7979
Op<CIR_Dialect, mnemonic, traits>, LLVMLoweringInfo;
8080

81+
//===----------------------------------------------------------------------===//
82+
// CastOp
83+
//===----------------------------------------------------------------------===//
84+
85+
// CK_Dependent
86+
def CK_BitCast : I32EnumAttrCase<"bitcast", 1>;
87+
// CK_LValueBitCast
88+
// CK_LValueToRValueBitCast
89+
// CK_LValueToRValue
90+
// CK_NoOp
91+
// CK_BaseToDerived
92+
// CK_DerivedToBase
93+
// CK_UncheckedDerivedToBase
94+
// CK_Dynamic
95+
// CK_ToUnion
96+
def CK_ArrayToPointerDecay : I32EnumAttrCase<"array_to_ptrdecay", 11>;
97+
// CK_FunctionToPointerDecay
98+
// CK_NullToPointer
99+
// CK_NullToMemberPointer
100+
// CK_BaseToDerivedMemberPointer
101+
// CK_DerivedToBaseMemberPointer
102+
def CK_MemberPointerToBoolean : I32EnumAttrCase<"member_ptr_to_bool", 17>;
103+
// CK_ReinterpretMemberPointer
104+
// CK_UserDefinedConversion
105+
// CK_ConstructorConversion
106+
def CK_IntegralToPointer : I32EnumAttrCase<"int_to_ptr", 21>;
107+
def CK_PointerToIntegral : I32EnumAttrCase<"ptr_to_int", 22>;
108+
def CK_PointerToBoolean : I32EnumAttrCase<"ptr_to_bool", 23>;
109+
// CK_ToVoid
110+
// CK_MatrixCast
111+
// CK_VectorSplat
112+
def CK_IntegralCast : I32EnumAttrCase<"integral", 27>;
113+
def CK_IntegralToBoolean : I32EnumAttrCase<"int_to_bool", 28>;
114+
def CK_IntegralToFloating : I32EnumAttrCase<"int_to_float", 29>;
115+
// CK_FloatingToFixedPoint
116+
// CK_FixedPointToFloating
117+
// CK_FixedPointCast
118+
// CK_FixedPointToIntegral
119+
// CK_IntegralToFixedPoint
120+
// CK_FixedPointToBoolean
121+
def CK_FloatingToIntegral : I32EnumAttrCase<"float_to_int", 36>;
122+
def CK_FloatingToBoolean : I32EnumAttrCase<"float_to_bool", 37>;
123+
def CK_BooleanToSignedIntegral : I32EnumAttrCase<"bool_to_int", 38>;
124+
def CK_FloatingCast : I32EnumAttrCase<"floating", 39>;
125+
// CK_CPointerToObjCPointerCast
126+
// CK_BlockPointerToObjCPointerCast
127+
// CK_AnyPointerToBlockPointerCast
128+
// CK_ObjCObjectLValueCast
129+
// CK_FloatingRealToComplex
130+
// CK_FloatingComplexToReal
131+
// CK_FloatingComplexToBoolean
132+
def CK_FloatingComplexCast : I32EnumAttrCase<"float_complex", 47>;
133+
// CK_FloatingComplexToIntegralComplex
134+
// CK_IntegralRealToComplex
135+
def CK_IntegralComplexToReal : I32EnumAttrCase<"int_complex_to_real", 50>;
136+
def CK_IntegralComplexToBoolean : I32EnumAttrCase<"int_complex_to_bool", 51>;
137+
def CK_IntegralComplexCast : I32EnumAttrCase<"int_complex", 52>;
138+
def CK_IntegralComplexToFloatingComplex
139+
: I32EnumAttrCase<"int_complex_to_float_complex", 53>;
140+
// CK_ARCProduceObject
141+
// CK_ARCConsumeObject
142+
// CK_ARCReclaimReturnedObject
143+
// CK_ARCExtendBlockObject
144+
// CK_AtomicToNonAtomic
145+
// CK_NonAtomicToAtomic
146+
// CK_CopyAndAutoreleaseBlockObject
147+
// CK_BuiltinFnToFnPtr
148+
// CK_ZeroToOCLOpaqueType
149+
def CK_AddressSpaceConversion : I32EnumAttrCase<"address_space", 63>;
150+
// CK_IntToOCLSampler
151+
// CK_HLSLVectorTruncation
152+
// CK_HLSLArrayRValue
153+
// CK_HLSLElementwiseCast
154+
// CK_HLSLAggregateSplatCast
155+
156+
// Enums below are specific to CIR and don't have a correspondence to classic
157+
// codegen:
158+
def CK_BooleanToFloat : I32EnumAttrCase<"bool_to_float", 1000>;
159+
160+
def CastKind : I32EnumAttr<
161+
"CastKind",
162+
"cast kind",
163+
[CK_BitCast, CK_ArrayToPointerDecay, CK_MemberPointerToBoolean,
164+
CK_IntegralToPointer, CK_PointerToIntegral, CK_PointerToBoolean,
165+
CK_IntegralCast, CK_IntegralToBoolean, CK_IntegralToFloating,
166+
CK_FloatingToIntegral, CK_FloatingToBoolean, CK_BooleanToSignedIntegral,
167+
CK_FloatingCast, CK_FloatingComplexCast, CK_IntegralComplexToReal,
168+
CK_IntegralComplexToBoolean, CK_IntegralComplexCast,
169+
CK_IntegralComplexToFloatingComplex, CK_AddressSpaceConversion,
170+
CK_BooleanToFloat]> {
171+
let cppNamespace = "::cir";
172+
}
173+
174+
def CastOp : CIR_Op<"cast",
175+
[Pure,
176+
DeclareOpInterfaceMethods<PromotableOpInterface>]> {
177+
// FIXME: not all conversions are free of side effects.
178+
let summary = "Conversion between values of different types";
179+
let description = [{
180+
Apply C/C++ usual conversions rules between values. Currently supported kinds:
181+
182+
- `array_to_ptrdecay`
183+
- `bitcast`
184+
- `integral`
185+
- `int_to_bool`
186+
- `int_to_float`
187+
- `floating`
188+
- `float_to_int`
189+
- `float_to_bool`
190+
- `ptr_to_int`
191+
- `ptr_to_bool`
192+
- `bool_to_int`
193+
- `bool_to_float`
194+
- `address_space`
195+
- `float_to_complex`
196+
- `int_to_complex`
197+
- `float_complex_to_real`
198+
- `int_complex_to_real`
199+
- `float_complex_to_bool`
200+
- `int_complex_to_bool`
201+
- `float_complex`
202+
- `float_complex_to_int_complex`
203+
- `int_complex`
204+
- `int_complex_to_float_complex`
205+
206+
This is effectively a subset of the rules from
207+
`llvm-project/clang/include/clang/AST/OperationKinds.def`; but note that some
208+
of the conversions aren't implemented in terms of `cir.cast`, `lvalue-to-rvalue`
209+
for instance is modeled as a regular `cir.load`.
210+
211+
```mlir
212+
%4 = cir.cast (int_to_bool, %3 : i32), !cir.bool
213+
...
214+
%x = cir.cast(array_to_ptrdecay, %0 : !cir.ptr<!cir.array<i32 x 10>>), !cir.ptr<i32>
215+
```
216+
}];
217+
218+
let arguments = (ins CastKind:$kind, CIR_AnyType:$src);
219+
let results = (outs CIR_AnyType:$result);
220+
221+
let assemblyFormat = [{
222+
`(` $kind `,` $src `:` type($src) `)`
223+
`,` type($result) attr-dict
224+
}];
225+
226+
// The input and output types should match the cast kind.
227+
let hasVerifier = 1;
228+
let hasFolder = 1;
229+
}
230+
81231
//===----------------------------------------------------------------------===//
82232
// ConstantOp
83233
//===----------------------------------------------------------------------===//

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,23 +77,31 @@ struct MissingFeatures {
7777
static bool opUnaryPromotionType() { return false; }
7878

7979
// Misc
80-
static bool scalarConversionOpts() { return false; }
80+
static bool cxxABI() { return false; }
8181
static bool tryEmitAsConstant() { return false; }
8282
static bool constructABIArgDirectExtend() { return false; }
8383
static bool opGlobalViewAttr() { return false; }
8484
static bool lowerModeOptLevel() { return false; }
8585
static bool opTBAA() { return false; }
86+
static bool opCmp() { return false; }
8687
static bool objCLifetime() { return false; }
8788
static bool emitNullabilityCheck() { return false; }
8889
static bool astVarDeclInterface() { return false; }
8990
static bool stackSaveOp() { return false; }
9091
static bool aggValueSlot() { return false; }
9192

92-
static bool unsizedTypes() { return false; }
93+
static bool fpConstraints() { return false; }
9394
static bool sanitizers() { return false; }
95+
static bool addHeapAllocSiteMetadata() { return false; }
96+
static bool targetCodeGenInfoGetNullPointer() { return false; }
9497
static bool CGFPOptionsRAII() { return false; }
9598

9699
// Missing types
100+
static bool dataMemberType() { return false; }
101+
static bool matrixType() { return false; }
102+
static bool methodType() { return false; }
103+
static bool scalableVectors() { return false; }
104+
static bool unsizedTypes() { return false; }
97105
static bool vectorType() { return false; }
98106
};
99107

clang/lib/CIR/CodeGen/CIRGenBuilder.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#define LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENBUILDER_H
1111

1212
#include "CIRGenTypeCache.h"
13+
#include "clang/CIR/MissingFeatures.h"
1314

1415
#include "clang/CIR/Dialect/Builder/CIRBaseBuilder.h"
1516
#include "clang/CIR/MissingFeatures.h"
@@ -43,6 +44,14 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
4344
assert(!cir::MissingFeatures::unsizedTypes());
4445
return false;
4546
}
47+
48+
bool isInt(mlir::Type i) { return mlir::isa<cir::IntType>(i); }
49+
50+
// Creates constant nullptr for pointer type ty.
51+
cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc) {
52+
assert(!cir::MissingFeatures::targetCodeGenInfoGetNullPointer());
53+
return create<cir::ConstantOp>(loc, ty, getConstPtrAttr(ty, 0));
54+
}
4655
};
4756

4857
} // namespace clang::CIRGen

clang/lib/CIR/CodeGen/CIRGenExpr.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,13 @@ mlir::Value CIRGenFunction::emitAlloca(StringRef name, mlir::Type ty,
264264
return addr;
265265
}
266266

267+
mlir::Value CIRGenFunction::createDummyValue(mlir::Location loc,
268+
clang::QualType qt) {
269+
mlir::Type t = convertType(qt);
270+
CharUnits alignment = getContext().getTypeAlignInChars(qt);
271+
return builder.createDummyValue(loc, t, alignment);
272+
}
273+
267274
/// This creates an alloca and inserts it at the current insertion point of the
268275
/// builder.
269276
Address CIRGenFunction::createTempAlloca(mlir::Type ty, CharUnits align,

0 commit comments

Comments
 (0)