[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:10:20 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:
I think it's only used in conjunction with constructors and destructors, so it isn't needed yet. I should probably drop an errorNYI or two for that.
https://github.com/llvm/llvm-project/pull/138222
More information about the cfe-commits
mailing list