15
15
16
16
#include " clang/AST/GlobalDecl.h"
17
17
#include " clang/CIR/MissingFeatures.h"
18
+ #include " llvm/Support/SaveAndRestore.h"
18
19
19
20
using namespace clang ;
20
21
using namespace clang ::CIRGen;
21
22
23
+ static void emitDeclInit (CIRGenFunction &cgf, const VarDecl *varDecl,
24
+ cir::GlobalOp globalOp) {
25
+ assert ((varDecl->hasGlobalStorage () ||
26
+ (varDecl->hasLocalStorage () &&
27
+ cgf.getContext ().getLangOpts ().OpenCLCPlusPlus )) &&
28
+ " VarDecl must have global or local (in the case of OpenCL) storage!" );
29
+ assert (!varDecl->getType ()->isReferenceType () &&
30
+ " Should not call emitDeclInit on a reference!" );
31
+
32
+ CIRGenBuilderTy &builder = cgf.getBuilder ();
33
+
34
+ // Set up the ctor region.
35
+ mlir::OpBuilder::InsertionGuard guard (builder);
36
+ mlir::Block *block = builder.createBlock (&globalOp.getCtorRegion ());
37
+ CIRGenFunction::LexicalScope lexScope{cgf, globalOp.getLoc (),
38
+ builder.getInsertionBlock ()};
39
+ lexScope.setAsGlobalInit ();
40
+ builder.setInsertionPointToStart (block);
41
+
42
+ Address declAddr (cgf.cgm .getAddrOfGlobalVar (varDecl),
43
+ cgf.cgm .getASTContext ().getDeclAlign (varDecl));
44
+
45
+ QualType type = varDecl->getType ();
46
+ LValue lv = cgf.makeAddrLValue (declAddr, type);
47
+
48
+ const Expr *init = varDecl->getInit ();
49
+ switch (CIRGenFunction::getEvaluationKind (type)) {
50
+ case cir::TEK_Scalar:
51
+ assert (!cir::MissingFeatures::objCGC ());
52
+ cgf.emitScalarInit (init, cgf.getLoc (varDecl->getLocation ()), lv, false );
53
+ break ;
54
+ case cir::TEK_Complex:
55
+ cgf.cgm .errorNYI (varDecl->getSourceRange (), " complex global initializer" );
56
+ break ;
57
+ case cir::TEK_Aggregate:
58
+ assert (!cir::MissingFeatures::aggValueSlotGC ());
59
+ cgf.emitAggExpr (init,
60
+ AggValueSlot::forLValue (lv, AggValueSlot::IsDestructed,
61
+ AggValueSlot::IsNotAliased,
62
+ AggValueSlot::DoesNotOverlap));
63
+ break ;
64
+ }
65
+
66
+ // Finish the ctor region.
67
+ builder.setInsertionPointToEnd (block);
68
+ cir::YieldOp::create (builder, globalOp.getLoc ());
69
+ }
70
+
71
+ static void emitDeclDestroy (CIRGenFunction &cgf, const VarDecl *vd,
72
+ cir::GlobalOp addr) {
73
+ // Honor __attribute__((no_destroy)) and bail instead of attempting
74
+ // to emit a reference to a possibly nonexistent destructor, which
75
+ // in turn can cause a crash. This will result in a global constructor
76
+ // that isn't balanced out by a destructor call as intended by the
77
+ // attribute. This also checks for -fno-c++-static-destructors and
78
+ // bails even if the attribute is not present.
79
+ QualType::DestructionKind dtorKind = vd->needsDestruction (cgf.getContext ());
80
+
81
+ // FIXME: __attribute__((cleanup)) ?
82
+
83
+ switch (dtorKind) {
84
+ case QualType::DK_none:
85
+ return ;
86
+
87
+ case QualType::DK_cxx_destructor:
88
+ break ;
89
+
90
+ case QualType::DK_objc_strong_lifetime:
91
+ case QualType::DK_objc_weak_lifetime:
92
+ case QualType::DK_nontrivial_c_struct:
93
+ // We don't care about releasing objects during process teardown.
94
+ assert (!vd->getTLSKind () && " should have rejected this" );
95
+ return ;
96
+ }
97
+
98
+ cgf.cgm .errorNYI (vd->getSourceRange (), " global with destructor" );
99
+ }
100
+
22
101
cir::FuncOp CIRGenModule::codegenCXXStructor (GlobalDecl gd) {
23
102
const CIRGenFunctionInfo &fnInfo =
24
103
getTypes ().arrangeCXXStructorDeclaration (gd);
@@ -38,3 +117,63 @@ cir::FuncOp CIRGenModule::codegenCXXStructor(GlobalDecl gd) {
38
117
assert (!cir::MissingFeatures::opFuncAttributesForDefinition ());
39
118
return fn;
40
119
}
120
+
121
+ // Global variables requiring non-trivial initialization are handled
122
+ // differently in CIR than in classic codegen. Classic codegen emits
123
+ // a global init function (__cxx_global_var_init) and inserts
124
+ // initialization for each global there. In CIR, we attach a ctor
125
+ // region to the global variable and insert the initialization code
126
+ // into the ctor region. This will be moved into the
127
+ // __cxx_global_var_init function during the LoweringPrepare pass.
128
+ void CIRGenModule::emitCXXGlobalVarDeclInit (const VarDecl *varDecl,
129
+ cir::GlobalOp addr,
130
+ bool performInit) {
131
+ QualType ty = varDecl->getType ();
132
+
133
+ // TODO: handle address space
134
+ // The address space of a static local variable (addr) may be different
135
+ // from the address space of the "this" argument of the constructor. In that
136
+ // case, we need an addrspacecast before calling the constructor.
137
+ //
138
+ // struct StructWithCtor {
139
+ // __device__ StructWithCtor() {...}
140
+ // };
141
+ // __device__ void foo() {
142
+ // __shared__ StructWithCtor s;
143
+ // ...
144
+ // }
145
+ //
146
+ // For example, in the above CUDA code, the static local variable s has a
147
+ // "shared" address space qualifier, but the constructor of StructWithCtor
148
+ // expects "this" in the "generic" address space.
149
+ assert (!cir::MissingFeatures::addressSpace ());
150
+
151
+ // Create a CIRGenFunction to emit the initializer. While this isn't a true
152
+ // function, the handling works the same way.
153
+ CIRGenFunction cgf{*this , builder, true };
154
+ llvm::SaveAndRestore<CIRGenFunction *> savedCGF (curCGF, &cgf);
155
+ curCGF->curFn = addr;
156
+
157
+ CIRGenFunction::SourceLocRAIIObject fnLoc{cgf,
158
+ getLoc (varDecl->getLocation ())};
159
+
160
+ assert (!cir::MissingFeatures::astVarDeclInterface ());
161
+
162
+ if (!ty->isReferenceType ()) {
163
+ assert (!cir::MissingFeatures::openMP ());
164
+
165
+ bool needsDtor = varDecl->needsDestruction (getASTContext ()) ==
166
+ QualType::DK_cxx_destructor;
167
+ // PerformInit, constant store invariant / destroy handled below.
168
+ if (performInit)
169
+ emitDeclInit (cgf, varDecl, addr);
170
+
171
+ if (varDecl->getType ().isConstantStorage (getASTContext (), true , !needsDtor))
172
+ errorNYI (varDecl->getSourceRange (), " global with constant storage" );
173
+ else
174
+ emitDeclDestroy (cgf, varDecl, addr);
175
+ return ;
176
+ }
177
+
178
+ errorNYI (varDecl->getSourceRange (), " global with reference type" );
179
+ }
0 commit comments