aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CIR/CodeGen/CIRGenModule.cpp
diff options
context:
space:
mode:
authorAndy Kaylor <akaylor@nvidia.com>2025-04-10 14:15:10 -0700
committerGitHub <noreply@github.com>2025-04-10 14:15:10 -0700
commitdb22909089dbc28d072e8cba6183f5a51f418bf0 (patch)
tree27fdefbeec928cdcb3cb645dfb872efdfa1edeaa /clang/lib/CIR/CodeGen/CIRGenModule.cpp
parent36acaa0be5cf6273200d4cc4c35042c4bfc3861b (diff)
downloadllvm-db22909089dbc28d072e8cba6183f5a51f418bf0.zip
llvm-db22909089dbc28d072e8cba6183f5a51f418bf0.tar.gz
llvm-db22909089dbc28d072e8cba6183f5a51f418bf0.tar.bz2
[CIR] Upstream support for cir.get_global (#135095)
This adds basic support for referencing global variables from within functions via the cir.get_global operation.
Diffstat (limited to 'clang/lib/CIR/CodeGen/CIRGenModule.cpp')
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenModule.cpp97
1 files changed, 97 insertions, 0 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 2f90141..4b5acb3 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -202,6 +202,102 @@ void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd,
curCGF = nullptr;
}
+mlir::Operation *CIRGenModule::getGlobalValue(StringRef name) {
+ return mlir::SymbolTable::lookupSymbolIn(theModule, name);
+}
+
+/// If the specified mangled name is not in the module,
+/// create and return an mlir GlobalOp with the specified type (TODO(cir):
+/// address space).
+///
+/// TODO(cir):
+/// 1. If there is something in the module with the specified name, return
+/// it potentially bitcasted to the right type.
+///
+/// 2. If \p d is non-null, it specifies a decl that correspond to this. This
+/// is used to set the attributes on the global when it is first created.
+///
+/// 3. If \p isForDefinition is true, it is guaranteed that an actual global
+/// with type \p ty will be returned, not conversion of a variable with the same
+/// mangled name but some other type.
+cir::GlobalOp
+CIRGenModule::getOrCreateCIRGlobal(StringRef mangledName, mlir::Type ty,
+ LangAS langAS, const VarDecl *d,
+ ForDefinition_t isForDefinition) {
+ // Lookup the entry, lazily creating it if necessary.
+ cir::GlobalOp entry;
+ if (mlir::Operation *v = getGlobalValue(mangledName)) {
+ if (!isa<cir::GlobalOp>(v))
+ errorNYI(d->getSourceRange(), "global with non-GlobalOp type");
+ entry = cast<cir::GlobalOp>(v);
+ }
+
+ if (entry) {
+ assert(!cir::MissingFeatures::addressSpace());
+ assert(!cir::MissingFeatures::opGlobalWeakRef());
+
+ assert(!cir::MissingFeatures::setDLLStorageClass());
+ assert(!cir::MissingFeatures::openMP());
+
+ if (entry.getSymType() == ty)
+ return entry;
+
+ // If there are two attempts to define the same mangled name, issue an
+ // error.
+ //
+ // TODO(cir): look at mlir::GlobalValue::isDeclaration for all aspects of
+ // recognizing the global as a declaration, for now only check if
+ // initializer is present.
+ if (isForDefinition && !entry.isDeclaration()) {
+ errorNYI(d->getSourceRange(), "global with conflicting type");
+ }
+
+ // Address space check removed because it is unnecessary because CIR records
+ // address space info in types.
+
+ // (If global is requested for a definition, we always need to create a new
+ // global, not just return a bitcast.)
+ if (!isForDefinition)
+ return entry;
+ }
+
+ errorNYI(d->getSourceRange(), "reference of undeclared global");
+}
+
+cir::GlobalOp
+CIRGenModule::getOrCreateCIRGlobal(const VarDecl *d, mlir::Type ty,
+ ForDefinition_t isForDefinition) {
+ assert(d->hasGlobalStorage() && "Not a global variable");
+ QualType astTy = d->getType();
+ if (!ty)
+ ty = getTypes().convertTypeForMem(astTy);
+
+ assert(!cir::MissingFeatures::mangledNames());
+ return getOrCreateCIRGlobal(d->getIdentifier()->getName(), ty,
+ astTy.getAddressSpace(), d, isForDefinition);
+}
+
+/// Return the mlir::Value for the address of the given global variable. If
+/// \p ty is non-null and if the global doesn't exist, then it will be created
+/// with the specified type instead of whatever the normal requested type would
+/// be. If \p isForDefinition is true, it is guaranteed that an actual global
+/// with type \p ty will be returned, not conversion of a variable with the same
+/// mangled name but some other type.
+mlir::Value CIRGenModule::getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty,
+ ForDefinition_t isForDefinition) {
+ assert(d->hasGlobalStorage() && "Not a global variable");
+ QualType astTy = d->getType();
+ if (!ty)
+ ty = getTypes().convertTypeForMem(astTy);
+
+ assert(!cir::MissingFeatures::opGlobalThreadLocal());
+
+ cir::GlobalOp g = getOrCreateCIRGlobal(d, ty, isForDefinition);
+ mlir::Type ptrTy = builder.getPointerTo(g.getSymType());
+ return builder.create<cir::GetGlobalOp>(getLoc(d->getSourceRange()), ptrTy,
+ g.getSymName());
+}
+
void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
bool isTentative) {
const QualType astTy = vd->getType();
@@ -507,6 +603,7 @@ cir::FuncOp CIRGenModule::getAddrOfFunction(clang::GlobalDecl gd,
funcType = convertType(fd->getType());
}
+ assert(!cir::MissingFeatures::mangledNames());
cir::FuncOp func = getOrCreateCIRFunction(
cast<NamedDecl>(gd.getDecl())->getIdentifier()->getName(), funcType, gd,
forVTable, dontDefer, /*isThunk=*/false, isForDefinition);