1515
1616#include  " clang/AST/GlobalDecl.h" 
1717#include  " clang/CIR/MissingFeatures.h" 
18+ #include  " llvm/Support/SaveAndRestore.h" 
1819
1920using  namespace  clang ; 
2021using  namespace  clang ::CIRGen; 
2122
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+ 
22101cir::FuncOp CIRGenModule::codegenCXXStructor (GlobalDecl gd) {
23102  const  CIRGenFunctionInfo &fnInfo =
24103      getTypes ().arrangeCXXStructorDeclaration (gd);
@@ -38,3 +117,63 @@ cir::FuncOp CIRGenModule::codegenCXXStructor(GlobalDecl gd) {
38117  assert (!cir::MissingFeatures::opFuncAttributesForDefinition ());
39118  return  fn;
40119}
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