aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CIR/CodeGen/CIRGenModule.cpp
diff options
context:
space:
mode:
authorAndy Kaylor <akaylor@nvidia.com>2025-05-28 13:53:30 -0700
committerGitHub <noreply@github.com>2025-05-28 13:53:30 -0700
commitb574c811e83a2f638714153cb2f915c625ac945c (patch)
treeea17b489184ce8e5938835f257cda5d059583d55 /clang/lib/CIR/CodeGen/CIRGenModule.cpp
parent711a1779dcb4ed5616d5727d990b642a3593855f (diff)
downloadllvm-b574c811e83a2f638714153cb2f915c625ac945c.zip
llvm-b574c811e83a2f638714153cb2f915c625ac945c.tar.gz
llvm-b574c811e83a2f638714153cb2f915c625ac945c.tar.bz2
[CIR] Defer declarations and tentative definitions (#141700)
This change adds code to defer emitting declarations and tentative definitions until they are referenced or trigger by a call to CompleteTentativeDefinition. This is needed to avoid premature handling of declarations and definitions that might not be referenced in the current translation unit. It also avoids incorrectly adding an initializer to external declarations. This change also updates the way the insertion location for globals is chosen so that all globals will be emitted together at the top of the module. This makes no functional difference, but it is very useful for writing sensible tests. Some tests are modified in this change to reorder global variables so that they can be checked in the order in which they will be emitted.
Diffstat (limited to 'clang/lib/CIR/CodeGen/CIRGenModule.cpp')
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenModule.cpp61
1 files changed, 46 insertions, 15 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 60a3048..b31b2b3 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -231,8 +231,20 @@ void CIRGenModule::emitGlobal(clang::GlobalDecl gd) {
return;
}
} else {
- assert(cast<VarDecl>(global)->isFileVarDecl() &&
- "Cannot emit local var decl as global");
+ const auto *vd = cast<VarDecl>(global);
+ assert(vd->isFileVarDecl() && "Cannot emit local var decl as global.");
+ if (vd->isThisDeclarationADefinition() != VarDecl::Definition &&
+ !astContext.isMSStaticDataMemberInlineDefinition(vd)) {
+ assert(!cir::MissingFeatures::openMP());
+ // If this declaration may have caused an inline variable definition to
+ // change linkage, make sure that it's emitted.
+ if (astContext.getInlineVariableDefinitionKind(vd) ==
+ ASTContext::InlineVariableDefinitionKind::Strong)
+ getAddrOfGlobalVar(vd);
+ // Otherwise, we can ignore this declaration. The variable will be emitted
+ // on its first use.
+ return;
+ }
}
// TODO(CIR): Defer emitting some global definitions until later
@@ -279,22 +291,23 @@ cir::GlobalOp CIRGenModule::createGlobalOp(CIRGenModule &cgm,
{
mlir::OpBuilder::InsertionGuard guard(builder);
- // Some global emissions are triggered while emitting a function, e.g.
- // void s() { const char *s = "yolo"; ... }
- //
- // Be sure to insert global before the current function
- CIRGenFunction *curCGF = cgm.curCGF;
- if (curCGF)
- builder.setInsertionPoint(curCGF->curFn);
-
- g = builder.create<cir::GlobalOp>(loc, name, t);
- if (!curCGF) {
- if (insertPoint)
- cgm.getModule().insert(insertPoint, g);
+ // If an insertion point is provided, we're replacing an existing global,
+ // otherwise, create the new global immediately after the last gloabl we
+ // emitted.
+ if (insertPoint) {
+ builder.setInsertionPoint(insertPoint);
+ } else {
+ // Group global operations together at the top of the module.
+ if (cgm.lastGlobalOp)
+ builder.setInsertionPointAfter(cgm.lastGlobalOp);
else
- cgm.getModule().push_back(g);
+ builder.setInsertionPointToStart(cgm.getModule().getBody());
}
+ g = builder.create<cir::GlobalOp>(loc, name, t);
+ if (!insertPoint)
+ cgm.lastGlobalOp = g;
+
// Default to private until we can judge based on the initializer,
// since MLIR doesn't allow public declarations.
mlir::SymbolTable::setSymbolVisibility(
@@ -1044,6 +1057,24 @@ StringRef CIRGenModule::getMangledName(GlobalDecl gd) {
return mangledDeclNames[canonicalGd] = result.first->first();
}
+void CIRGenModule::emitTentativeDefinition(const VarDecl *d) {
+ assert(!d->getInit() && "Cannot emit definite definitions here!");
+
+ StringRef mangledName = getMangledName(d);
+ mlir::Operation *gv = getGlobalValue(mangledName);
+
+ // If we already have a definition, not declaration, with the same mangled
+ // name, emitting of declaration is not required (and would actually overwrite
+ // the emitted definition).
+ if (gv && !mlir::cast<cir::GlobalOp>(gv).isDeclaration())
+ return;
+
+ assert(!cir::MissingFeatures::deferredDecls());
+
+ // The tentative definition is the only definition.
+ emitGlobalVarDefinition(d);
+}
+
cir::FuncOp CIRGenModule::getOrCreateCIRFunction(
StringRef mangledName, mlir::Type funcType, GlobalDecl gd, bool forVTable,
bool dontDefer, bool isThunk, ForDefinition_t isForDefinition,