[clang] [CIR] Refactor global variable emission and initialization (PR #138222)

Andy Kaylor via cfe-commits cfe-commits at lists.llvm.org
Fri May 2 13:23:53 PDT 2025


================
@@ -365,46 +406,108 @@ mlir::Value CIRGenModule::getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty,
 void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
                                            bool isTentative) {
   const QualType astTy = vd->getType();
-  const mlir::Type type = convertType(vd->getType());
-  if (vd->getIdentifier()) {
-    StringRef name = getMangledName(GlobalDecl(vd));
-    auto varOp =
-        builder.create<cir::GlobalOp>(getLoc(vd->getSourceRange()), name, type);
-    // TODO(CIR): This code for processing initial values is a placeholder
-    // until class ConstantEmitter is upstreamed and the code for processing
-    // constant expressions is filled out.  Only the most basic handling of
-    // certain constant expressions is implemented for now.
-    const VarDecl *initDecl;
-    const Expr *initExpr = vd->getAnyInitializer(initDecl);
-    mlir::Attribute initializer;
-    if (initExpr) {
-      if (APValue *value = initDecl->evaluateValue()) {
-        ConstantEmitter emitter(*this);
-        initializer = emitter.tryEmitPrivateForMemory(*value, astTy);
+
+  if (getLangOpts().OpenCL || getLangOpts().OpenMPIsTargetDevice) {
+    errorNYI(vd->getSourceRange(), "emit OpenCL/OpenMP global variable");
+    return;
+  }
+
+  mlir::Attribute init;
+  const VarDecl *initDecl;
+  const Expr *initExpr = vd->getAnyInitializer(initDecl);
+
+  std::optional<ConstantEmitter> emitter;
+
+  assert(!cir::MissingFeatures::cudaSupport());
+
+  if (vd->hasAttr<LoaderUninitializedAttr>()) {
+    errorNYI(vd->getSourceRange(), "loader uninitialized attribute");
+    return;
+  } else if (!initExpr) {
+    // This is a tentative definition; tentative definitions are
+    // implicitly initialized with { 0 }.
+    //
+    // Note that tentative definitions are only emitted at the end of
+    // a translation unit, so they should never have incomplete
+    // type. In addition, EmitTentativeDefinition makes sure that we
+    // never attempt to emit a tentative definition if a real one
+    // exists. A use may still exists, however, so we still may need
+    // to do a RAUW.
+    assert(!astTy->isIncompleteType() && "Unexpected incomplete type");
+    init = builder.getZeroInitAttr(convertType(vd->getType()));
+  } else {
+    emitter.emplace(*this);
+    auto initializer = emitter->tryEmitForInitializer(*initDecl);
+    if (!initializer) {
+      QualType qt = initExpr->getType();
+      if (vd->getType()->isReferenceType())
+        qt = vd->getType();
+
+      if (getLangOpts().CPlusPlus) {
+        if (initDecl->hasFlexibleArrayInit(astContext))
+          errorNYI(vd->getSourceRange(), "flexible array initializer");
+        init = builder.getZeroInitAttr(convertType(qt));
+        if (astContext.GetGVALinkageForVariable(vd) != GVA_AvailableExternally)
+          errorNYI(vd->getSourceRange(), "global constructor");
       } else {
-        errorNYI(initExpr->getSourceRange(), "non-constant initializer");
+        errorNYI(vd->getSourceRange(), "static initializer");
       }
     } else {
-      initializer = builder.getZeroInitAttr(convertType(astTy));
+      init = initializer;
+      // We don't need an initializer, so remove the entry for the delayed
+      // initializer position (just in case this entry was delayed) if we
+      // also don't need to register a destructor.
+      if (vd->needsDestruction(astContext) == QualType::DK_cxx_destructor)
----------------
andykaylor wrote:

It looks like I missed a non-C++ case where it was used. I'll add it now.

https://github.com/llvm/llvm-project/pull/138222


More information about the cfe-commits mailing list