Skip to content

Commit e882590

Browse files
authored
[CIR] Refactor global variable emission and initialization (#138222)
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 880de1c commit e882590

File tree

5 files changed

+349
-39
lines changed

5 files changed

+349
-39
lines changed

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 7 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; }
@@ -176,6 +178,11 @@ struct MissingFeatures {
176178
static bool setDSOLocal() { return false; }
177179
static bool foldCaseStmt() { return false; }
178180
static bool constantFoldSwitchStatement() { return false; }
181+
static bool cudaSupport() { return false; }
182+
static bool maybeHandleStaticInExternC() { return false; }
183+
static bool constEmitterArrayILE() { return false; }
184+
static bool constEmitterVectorILE() { return false; }
185+
static bool needsGlobalCtorDtor() { return false; }
179186

180187
// Missing types
181188
static bool dataMemberType() { return false; }

clang/lib/CIR/CodeGen/CIRGenConstantEmitter.h

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

34+
#ifndef NDEBUG
35+
// Variables used for asserting state consistency.
36+
37+
/// Whether non-abstract components of the emitter have been initialized.
38+
bool initializedNonAbstract = false;
39+
40+
/// Whether the emitter has been finalized.
41+
bool finalized = false;
42+
43+
/// Whether the constant-emission failed.
44+
bool failed = false;
45+
#endif // NDEBUG
46+
3447
/// Whether we're in a constant context.
3548
bool inConstantContext = false;
3649

@@ -46,6 +59,14 @@ class ConstantEmitter {
4659
ConstantEmitter(const ConstantEmitter &other) = delete;
4760
ConstantEmitter &operator=(const ConstantEmitter &other) = delete;
4861

62+
~ConstantEmitter();
63+
64+
/// Try to emit the initializer of the given declaration as an abstract
65+
/// constant. If this succeeds, the emission must be finalized.
66+
mlir::Attribute tryEmitForInitializer(const VarDecl &d);
67+
68+
void finalize(cir::GlobalOp gv);
69+
4970
// All of the "abstract" emission methods below permit the emission to
5071
// be immediately discarded without finalizing anything. Therefore, they
5172
// must also promise not to do anything that will, in the future, require
@@ -61,6 +82,10 @@ class ConstantEmitter {
6182
// reference to its current location.
6283
mlir::Attribute emitForMemory(mlir::Attribute c, QualType t);
6384

85+
/// Try to emit the initializer of the given declaration as an abstract
86+
/// constant.
87+
mlir::Attribute tryEmitAbstractForInitializer(const VarDecl &d);
88+
6489
/// Emit the result of the given expression as an abstract constant,
6590
/// asserting that it succeeded. This is only safe to do when the
6691
/// expression is known to be a constant expression with either a fairly
@@ -79,11 +104,23 @@ class ConstantEmitter {
79104
mlir::Attribute tryEmitPrivate(const APValue &value, QualType destType);
80105
mlir::Attribute tryEmitPrivateForMemory(const APValue &value, QualType t);
81106

82-
/// Try to emit the initializer of the given declaration as an abstract
83-
/// constant.
84-
mlir::Attribute tryEmitAbstractForInitializer(const VarDecl &d);
85-
86107
private:
108+
#ifndef NDEBUG
109+
void initializeNonAbstract() {
110+
assert(!initializedNonAbstract);
111+
initializedNonAbstract = true;
112+
assert(!cir::MissingFeatures::addressSpace());
113+
}
114+
mlir::Attribute markIfFailed(mlir::Attribute init) {
115+
if (!init)
116+
failed = true;
117+
return init;
118+
}
119+
#else
120+
void initializeNonAbstract() {}
121+
mlir::Attribute markIfFailed(mlir::Attribute init) { return init; }
122+
#endif // NDEBUG
123+
87124
class AbstractStateRAII {
88125
ConstantEmitter &emitter;
89126
bool oldValue;

clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp

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

97189
mlir::Attribute VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die, QualType t) {
@@ -118,7 +210,28 @@ 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+
return {};
226+
}
227+
228+
if (ile->getType()->isVectorType()) {
229+
// If we return null here, the non-constant initializer will take care of
230+
// it, but we would prefer to handle it here.
231+
assert(!cir::MissingFeatures::constEmitterVectorILE());
232+
return {};
233+
}
234+
122235
return {};
123236
}
124237

@@ -218,12 +331,33 @@ emitArrayConstant(CIRGenModule &cgm, mlir::Type desiredType,
218331
// ConstantEmitter
219332
//===----------------------------------------------------------------------===//
220333

334+
mlir::Attribute ConstantEmitter::tryEmitForInitializer(const VarDecl &d) {
335+
initializeNonAbstract();
336+
return markIfFailed(tryEmitPrivateForVarInit(d));
337+
}
338+
339+
void ConstantEmitter::finalize(cir::GlobalOp gv) {
340+
assert(initializedNonAbstract &&
341+
"finalizing emitter that was used for abstract emission?");
342+
assert(!finalized && "finalizing emitter multiple times");
343+
assert(!gv.isDeclaration());
344+
#ifndef NDEBUG
345+
// Note that we might also be Failed.
346+
finalized = true;
347+
#endif // NDEBUG
348+
}
349+
221350
mlir::Attribute
222351
ConstantEmitter::tryEmitAbstractForInitializer(const VarDecl &d) {
223352
AbstractStateRAII state(*this, true);
224353
return tryEmitPrivateForVarInit(d);
225354
}
226355

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

0 commit comments

Comments
 (0)