Skip to content

Commit b3ae2d6

Browse files
committed
[CIR] Refactor global variable emission and initialization
When global variable support was initially upstreamed, we took some shortcuts and only implemented the minimum support for simple variables and constant initializers. This change refactors the code that creates global variables to introduce more of the complexities that are present in the incubator and the classic codegen. I can't really say this is NFC, because the code executed is very different and it will report different NYI diagnostics, but for the currently implemented cases, it results in the same output.
1 parent 74f55c7 commit b3ae2d6

File tree

5 files changed

+320
-39
lines changed

5 files changed

+320
-39
lines changed

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ struct MissingFeatures {
3636
static bool opGlobalConstant() { return false; }
3737
static bool opGlobalAlignment() { return false; }
3838
static bool opGlobalWeakRef() { return false; }
39+
static bool opGlobalLinkage() { return false; }
40+
static bool opGlobalSetVisitibility() { return false; }
3941

4042
static bool supportIFuncAttr() { return false; }
4143
static bool supportVisibility() { return false; }
@@ -163,6 +165,10 @@ struct MissingFeatures {
163165
static bool setDSOLocal() { return false; }
164166
static bool foldCaseStmt() { return false; }
165167
static bool constantFoldSwitchStatement() { return false; }
168+
static bool cudaSupport() { return false; }
169+
static bool maybeHandleStaticInExternC() { return false; }
170+
static bool constEmitterArrayILE() { return false; }
171+
static bool constEmitterVectorILE() { return false; }
166172

167173
// Missing types
168174
static bool dataMemberType() { return false; }

clang/lib/CIR/CodeGen/CIRGenConstantEmitter.h

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ class ConstantEmitter {
3131
private:
3232
bool abstract = false;
3333

34+
/// Whether non-abstract components of the emitter have been initialized.
35+
bool initializedNonAbstract = false;
36+
37+
/// Whether the emitter has been finalized.
38+
bool finalized = false;
39+
40+
/// Whether the constant-emission failed.
41+
bool failed = false;
42+
3443
/// Whether we're in a constant context.
3544
bool inConstantContext = false;
3645

@@ -46,6 +55,14 @@ class ConstantEmitter {
4655
ConstantEmitter(const ConstantEmitter &other) = delete;
4756
ConstantEmitter &operator=(const ConstantEmitter &other) = delete;
4857

58+
~ConstantEmitter();
59+
60+
/// Try to emit the initiaizer of the given declaration as an abstract
61+
/// constant. If this succeeds, the emission must be finalized.
62+
mlir::Attribute tryEmitForInitializer(const VarDecl &d);
63+
64+
void finalize(cir::GlobalOp gv);
65+
4966
// All of the "abstract" emission methods below permit the emission to
5067
// be immediately discarded without finalizing anything. Therefore, they
5168
// must also promise not to do anything that will, in the future, require
@@ -61,6 +78,10 @@ class ConstantEmitter {
6178
// reference to its current location.
6279
mlir::Attribute emitForMemory(mlir::Attribute c, QualType t);
6380

81+
/// Try to emit the initializer of the given declaration as an abstract
82+
/// constant.
83+
mlir::Attribute tryEmitAbstractForInitializer(const VarDecl &d);
84+
6485
/// Emit the result of the given expression as an abstract constant,
6586
/// asserting that it succeeded. This is only safe to do when the
6687
/// expression is known to be a constant expression with either a fairly
@@ -79,11 +100,18 @@ class ConstantEmitter {
79100
mlir::Attribute tryEmitPrivate(const APValue &value, QualType destType);
80101
mlir::Attribute tryEmitPrivateForMemory(const APValue &value, QualType t);
81102

82-
/// Try to emit the initializer of the given declaration as an abstract
83-
/// constant.
84-
mlir::Attribute tryEmitAbstractForInitializer(const VarDecl &d);
85-
86103
private:
104+
void initializeNonAbstract() {
105+
assert(!initializedNonAbstract);
106+
initializedNonAbstract = true;
107+
assert(!cir::MissingFeatures::addressSpace());
108+
}
109+
mlir::Attribute markIfFailed(mlir::Attribute init) {
110+
if (!init)
111+
failed = true;
112+
return init;
113+
}
114+
87115
class AbstractStateRAII {
88116
ConstantEmitter &emitter;
89117
bool oldValue;

clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp

Lines changed: 134 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,100 @@ class ConstExprEmitter
9090
}
9191

9292
mlir::Attribute VisitCastExpr(CastExpr *e, QualType destType) {
93-
cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitCastExpr");
94-
return {};
93+
if (const auto *ece = dyn_cast<ExplicitCastExpr>(e))
94+
cgm.errorNYI(e->getBeginLoc(),
95+
"ConstExprEmitter::VisitCastExpr explicit cast");
96+
Expr *subExpr = e->getSubExpr();
97+
98+
switch (e->getCastKind()) {
99+
case CK_HLSLArrayRValue:
100+
case CK_HLSLVectorTruncation:
101+
case CK_HLSLElementwiseCast:
102+
case CK_HLSLAggregateSplatCast:
103+
case CK_ToUnion:
104+
case CK_AddressSpaceConversion:
105+
case CK_ReinterpretMemberPointer:
106+
case CK_DerivedToBaseMemberPointer:
107+
case CK_BaseToDerivedMemberPointer:
108+
cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitCastExpr");
109+
return {};
110+
111+
case CK_LValueToRValue:
112+
case CK_AtomicToNonAtomic:
113+
case CK_NonAtomicToAtomic:
114+
case CK_NoOp:
115+
case CK_ConstructorConversion:
116+
return Visit(subExpr, destType);
117+
118+
case CK_IntToOCLSampler:
119+
llvm_unreachable("global sampler variables are not generated");
120+
121+
case CK_Dependent:
122+
llvm_unreachable("saw dependent cast!");
123+
124+
case CK_BuiltinFnToFnPtr:
125+
llvm_unreachable("builtin functions are handled elsewhere");
126+
127+
// These will never be supported.
128+
case CK_ObjCObjectLValueCast:
129+
case CK_ARCProduceObject:
130+
case CK_ARCConsumeObject:
131+
case CK_ARCReclaimReturnedObject:
132+
case CK_ARCExtendBlockObject:
133+
case CK_CopyAndAutoreleaseBlockObject:
134+
return {};
135+
136+
// These don't need to be handled here because Evaluate knows how to
137+
// evaluate them in the cases where they can be folded.
138+
case CK_BitCast:
139+
case CK_ToVoid:
140+
case CK_Dynamic:
141+
case CK_LValueBitCast:
142+
case CK_LValueToRValueBitCast:
143+
case CK_NullToMemberPointer:
144+
case CK_UserDefinedConversion:
145+
case CK_CPointerToObjCPointerCast:
146+
case CK_BlockPointerToObjCPointerCast:
147+
case CK_AnyPointerToBlockPointerCast:
148+
case CK_ArrayToPointerDecay:
149+
case CK_FunctionToPointerDecay:
150+
case CK_BaseToDerived:
151+
case CK_DerivedToBase:
152+
case CK_UncheckedDerivedToBase:
153+
case CK_MemberPointerToBoolean:
154+
case CK_VectorSplat:
155+
case CK_FloatingRealToComplex:
156+
case CK_FloatingComplexToReal:
157+
case CK_FloatingComplexToBoolean:
158+
case CK_FloatingComplexCast:
159+
case CK_FloatingComplexToIntegralComplex:
160+
case CK_IntegralRealToComplex:
161+
case CK_IntegralComplexToReal:
162+
case CK_IntegralComplexToBoolean:
163+
case CK_IntegralComplexCast:
164+
case CK_IntegralComplexToFloatingComplex:
165+
case CK_PointerToIntegral:
166+
case CK_PointerToBoolean:
167+
case CK_NullToPointer:
168+
case CK_IntegralCast:
169+
case CK_BooleanToSignedIntegral:
170+
case CK_IntegralToPointer:
171+
case CK_IntegralToBoolean:
172+
case CK_IntegralToFloating:
173+
case CK_FloatingToIntegral:
174+
case CK_FloatingToBoolean:
175+
case CK_FloatingCast:
176+
case CK_FloatingToFixedPoint:
177+
case CK_FixedPointToFloating:
178+
case CK_FixedPointCast:
179+
case CK_FixedPointToBoolean:
180+
case CK_FixedPointToIntegral:
181+
case CK_IntegralToFixedPoint:
182+
case CK_ZeroToOCLOpaqueType:
183+
case CK_MatrixCast:
184+
return {};
185+
}
186+
llvm_unreachable("Invalid CastKind");
95187
}
96188

97189
mlir::Attribute VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die, QualType t) {
@@ -118,7 +210,26 @@ class ConstExprEmitter
118210
}
119211

120212
mlir::Attribute VisitInitListExpr(InitListExpr *ile, QualType t) {
121-
cgm.errorNYI(ile->getBeginLoc(), "ConstExprEmitter::VisitInitListExpr");
213+
if (ile->isTransparent())
214+
return Visit(ile->getInit(0), t);
215+
216+
if (ile->getType()->isArrayType()) {
217+
// If we return null here, the non-constant initializer will take care of
218+
// it, but we would prefer to handle it here.
219+
assert(!cir::MissingFeatures::constEmitterArrayILE());
220+
return {};
221+
}
222+
223+
if (ile->getType()->isRecordType())
224+
cgm.errorNYI(ile->getBeginLoc(), "ConstExprEmitter: record ILE");
225+
226+
if (ile->getType()->isVectorType()) {
227+
// If we return null here, the non-constant initializer will take care of
228+
// it, but we would prefer to handle it here.
229+
assert(!cir::MissingFeatures::constEmitterVectorILE());
230+
return {};
231+
}
232+
122233
return {};
123234
}
124235

@@ -218,12 +329,32 @@ emitArrayConstant(CIRGenModule &cgm, mlir::Type desiredType,
218329
// ConstantEmitter
219330
//===----------------------------------------------------------------------===//
220331

332+
mlir::Attribute ConstantEmitter::tryEmitForInitializer(const VarDecl &d) {
333+
initializeNonAbstract();
334+
return markIfFailed(tryEmitPrivateForVarInit(d));
335+
}
336+
337+
void ConstantEmitter::finalize(cir::GlobalOp gv) {
338+
assert(initializedNonAbstract &&
339+
"finalizing emitter that was used for abstract emission?");
340+
assert(!finalized && "finalizing emitter multiple times");
341+
assert(!gv.isDeclaration());
342+
343+
// Note that we might also be Failed.
344+
finalized = true;
345+
}
346+
221347
mlir::Attribute
222348
ConstantEmitter::tryEmitAbstractForInitializer(const VarDecl &d) {
223349
AbstractStateRAII state(*this, true);
224350
return tryEmitPrivateForVarInit(d);
225351
}
226352

353+
ConstantEmitter::~ConstantEmitter() {
354+
assert((!initializedNonAbstract || finalized || failed) &&
355+
"not finalized after being initialized for non-abstract emission");
356+
}
357+
227358
mlir::Attribute ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &d) {
228359
// Make a quick check if variable can be default NULL initialized
229360
// and avoid going through rest of code which may do, for c++11,

0 commit comments

Comments
 (0)