-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[CIR] Support for static variables #143980
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clangir Author: Andy Kaylor (andykaylor) ChangesThis adds support for emitting static variables and their initializers. Patch is 21.07 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/143980.diff 8 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index a3754f4de66b0..dfff2740c75b5 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -185,11 +185,23 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
global.getSymName());
}
+ mlir::Value createGetGlobal(cir::GlobalOp global) {
+ return createGetGlobal(global.getLoc(), global);
+ }
+
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, mlir::Value dst,
mlir::IntegerAttr align = {}) {
return create<cir::StoreOp>(loc, val, dst, align);
}
+ [[nodiscard]] cir::GlobalOp
+ createGlobal(mlir::ModuleOp module, mlir::Location loc, mlir::StringRef name,
+ mlir::Type type, cir::GlobalLinkageKind linkage) {
+ mlir::OpBuilder::InsertionGuard guard(*this);
+ setInsertionPointToStart(module.getBody());
+ return create<cir::GlobalOp>(loc, name, type, linkage);
+ }
+
cir::GetMemberOp createGetMember(mlir::Location loc, mlir::Type resultTy,
mlir::Value base, llvm::StringRef name,
unsigned index) {
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index fbd15d5c886d2..570b1544a6964 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -230,6 +230,7 @@ struct MissingFeatures {
static bool emitCtorPrologue() { return false; }
static bool thunks() { return false; }
static bool runCleanupsScope() { return false; }
+ static bool dataLayoutAllocaSize() { return false; }
// Missing types
static bool dataMemberType() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index fb1a290c18fa2..c81301e9a6fe1 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -24,6 +24,7 @@ namespace clang::CIRGen {
class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
const CIRGenTypeCache &typeCache;
llvm::StringMap<unsigned> recordNames;
+ llvm::StringMap<unsigned> globalsVersioning;
public:
CIRGenBuilderTy(mlir::MLIRContext &mlirContext, const CIRGenTypeCache &tc)
@@ -358,6 +359,23 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
/// pointed to by \p arrayPtr.
mlir::Value maybeBuildArrayDecay(mlir::Location loc, mlir::Value arrayPtr,
mlir::Type eltTy);
+
+ /// Creates a versioned global variable. If the symbol is already taken, an ID
+ /// will be appended to the symbol. The returned global must always be queried
+ /// for its name so it can be referenced correctly.
+ [[nodiscard]] cir::GlobalOp
+ createVersionedGlobal(mlir::ModuleOp module, mlir::Location loc,
+ mlir::StringRef name, mlir::Type type,
+ cir::GlobalLinkageKind linkage) {
+ // Create a unique name if the given name is already taken.
+ std::string uniqueName;
+ if (unsigned version = globalsVersioning[name.str()]++)
+ uniqueName = name.str() + "." + std::to_string(version);
+ else
+ uniqueName = name.str();
+
+ return createGlobal(module, loc, uniqueName, type, linkage);
+ }
};
} // namespace clang::CIRGen
diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
index 80b0172090aa3..1d703d78c8bf3 100644
--- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
@@ -208,8 +208,25 @@ void CIRGenFunction::emitVarDecl(const VarDecl &d) {
if (d.hasExternalStorage())
return;
- if (d.getStorageDuration() != SD_Automatic)
- cgm.errorNYI(d.getSourceRange(), "emitVarDecl automatic storage duration");
+ if (d.getStorageDuration() != SD_Automatic) {
+ // Static sampler variables translated to function calls.
+ if (d.getType()->isSamplerT()) {
+ // Nothing needs to be done here, but let's flag it as an error until we
+ // have a test. It requires OpenCL support.
+ cgm.errorNYI(d.getSourceRange(), "emitVarDecl static sampler type");
+ return;
+ }
+
+ cir::GlobalLinkageKind linkage =
+ cgm.getCIRLinkageVarDefinition(&d, /*IsConstant=*/false);
+
+ // FIXME: We need to force the emission/use of a guard variable for
+ // some variables even if we can constant-evaluate them because
+ // we can't guarantee every translation unit will constant-evaluate them.
+
+ return emitStaticVarDecl(d, linkage);
+ }
+
if (d.getType().getAddressSpace() == LangAS::opencl_local)
cgm.errorNYI(d.getSourceRange(), "emitVarDecl openCL address space");
@@ -219,6 +236,252 @@ void CIRGenFunction::emitVarDecl(const VarDecl &d) {
return emitAutoVarDecl(d);
}
+static std::string getStaticDeclName(CIRGenModule &cgm, const VarDecl &d) {
+ if (cgm.getLangOpts().CPlusPlus)
+ return cgm.getMangledName(&d).str();
+
+ // If this isn't C++, we don't need a mangled name, just a pretty one.
+ assert(!d.isExternallyVisible() && "name shouldn't matter");
+ std::string contextName;
+ const DeclContext *dc = d.getDeclContext();
+ if (auto *cd = dyn_cast<CapturedDecl>(dc))
+ dc = cast<DeclContext>(cd->getNonClosureContext());
+ if (const auto *fd = dyn_cast<FunctionDecl>(dc))
+ contextName = std::string(cgm.getMangledName(fd));
+ else if (isa<BlockDecl>(dc))
+ cgm.errorNYI(d.getSourceRange(), "block decl context for static var");
+ else if (isa<ObjCMethodDecl>(dc))
+ cgm.errorNYI(d.getSourceRange(), "ObjC decl context for static var");
+ else
+ cgm.errorNYI(d.getSourceRange(), "Unknown context for static var decl");
+
+ contextName += "." + d.getNameAsString();
+ return contextName;
+}
+
+// TODO(cir): LLVM uses a Constant base class. Maybe CIR could leverage an
+// interface for all constants?
+cir::GlobalOp
+CIRGenModule::getOrCreateStaticVarDecl(const VarDecl &d,
+ cir::GlobalLinkageKind linkage) {
+ // In general, we don't always emit static var decls once before we reference
+ // them. It is possible to reference them before emitting the function that
+ // contains them, and it is possible to emit the containing function multiple
+ // times.
+ if (cir::GlobalOp existingGV = getStaticLocalDeclAddress(&d))
+ return existingGV;
+
+ QualType ty = d.getType();
+ assert(ty->isConstantSizeType() && "VLAs can't be static");
+
+ // Use the label if the variable is renamed with the asm-label extension.
+ std::string name;
+ if (d.hasAttr<AsmLabelAttr>())
+ errorNYI(d.getSourceRange(), "getOrCreateStaticVarDecl: asm label");
+ else
+ name = getStaticDeclName(*this, d);
+
+ mlir::Type lty = getTypes().convertTypeForMem(ty);
+ assert(!cir::MissingFeatures::addressSpace());
+
+ // OpenCL variables in local address space and CUDA shared
+ // variables cannot have an initializer.
+ mlir::Attribute init = nullptr;
+ if (d.hasAttr<LoaderUninitializedAttr>())
+ errorNYI(d.getSourceRange(),
+ "getOrCreateStaticVarDecl: LoaderUninitializedAttr");
+
+ init = builder.getZeroInitAttr(convertType(ty));
+
+ cir::GlobalOp gv = builder.createVersionedGlobal(
+ getModule(), getLoc(d.getLocation()), name, lty, linkage);
+ // TODO(cir): infer visibility from linkage in global op builder.
+ gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));
+ gv.setInitialValueAttr(init);
+ gv.setAlignment(getASTContext().getDeclAlign(&d).getAsAlign().value());
+
+ if (supportsCOMDAT() && gv.isWeakForLinker())
+ gv.setComdat(true);
+
+ assert(!cir::MissingFeatures::opGlobalThreadLocal());
+
+ setGVProperties(gv, &d);
+
+ // OG checks if the expected address space, denoted by the type, is the
+ // same as the actual address space indicated by attributes. If they aren't
+ // the same, an addrspacecast is emitted when this variable is accessed.
+ // In CIR however, cir.get_global already carries that information in
+ // !cir.ptr type - if this global is in OpenCL local address space, then its
+ // type would be !cir.ptr<..., addrspace(offload_local)>. Therefore we don't
+ // need an explicit address space cast in CIR: they will get emitted when
+ // lowering to LLVM IR.
+
+ // Ensure that the static local gets initialized by making sure the parent
+ // function gets emitted eventually.
+ const Decl *dc = cast<Decl>(d.getDeclContext());
+
+ // We can't name blocks or captured statements directly, so try to emit their
+ // parents.
+ if (isa<BlockDecl>(dc) || isa<CapturedDecl>(dc)) {
+ dc = dc->getNonClosureContext();
+ // FIXME: Ensure that global blocks get emitted.
+ if (!dc)
+ errorNYI(d.getSourceRange(), "non-closure context");
+ }
+
+ GlobalDecl gd;
+ if (isa<CXXConstructorDecl>(dc))
+ errorNYI(d.getSourceRange(), "C++ constructors static var context");
+ else if (isa<CXXDestructorDecl>(dc))
+ errorNYI(d.getSourceRange(), "C++ destructors static var context");
+ else if (const auto *fd = dyn_cast<FunctionDecl>(dc))
+ gd = GlobalDecl(fd);
+ else {
+ // Don't do anything for Obj-C method decls or global closures. We should
+ // never defer them.
+ assert(isa<ObjCMethodDecl>(dc) && "unexpected parent code decl");
+ }
+ if (gd.getDecl() && cir::MissingFeatures::openMP()) {
+ // Disable emission of the parent function for the OpenMP device codegen.
+ errorNYI(d.getSourceRange(), "OpenMP");
+ }
+
+ return gv;
+}
+
+/// Add the initializer for 'd' to the global variable that has already been
+/// created for it. If the initializer has a different type than gv does, this
+/// may free gv and return a different one. Otherwise it just returns gv.
+cir::GlobalOp CIRGenFunction::addInitializerToStaticVarDecl(
+ const VarDecl &d, cir::GlobalOp gv, cir::GetGlobalOp gvAddr) {
+ ConstantEmitter emitter(*this);
+ mlir::TypedAttr init =
+ mlir::cast<mlir::TypedAttr>(emitter.tryEmitForInitializer(d));
+
+ // If constant emission failed, then this should be a C++ static
+ // initializer.
+ if (!init) {
+ cgm.errorNYI(d.getSourceRange(), "static var without initializer");
+ return gv;
+ }
+
+ // TODO(cir): There should be debug code here to assert that the decl size
+ // matches the CIR data layout alloca size, but the code for calculating the
+ // alloca size is not implemented yet.
+ assert(!cir::MissingFeatures::dataLayoutAllocaSize());
+
+ // The initializer may differ in type from the global. Rewrite
+ // the global to match the initializer. (We have to do this
+ // because some types, like unions, can't be completely represented
+ // in the LLVM type system.)
+ if (gv.getSymType() != init.getType()) {
+ gv.setSymType(init.getType());
+
+ // Normally this should be done with a call to cgm.replaceGlobal(oldGV, gv),
+ // but since at this point the current block hasn't been really attached,
+ // there's no visibility into the GetGlobalOp corresponding to this Global.
+ // Given those constraints, thread in the GetGlobalOp and update it
+ // directly.
+ assert(!cir::MissingFeatures::addressSpace());
+ gvAddr.getAddr().setType(builder.getPointerTo(init.getType()));
+ }
+
+ bool needsDtor =
+ d.needsDestruction(getContext()) == QualType::DK_cxx_destructor;
+
+ assert(!cir::MissingFeatures::opGlobalConstant());
+ gv.setInitialValueAttr(init);
+
+ emitter.finalize(gv);
+
+ if (needsDtor) {
+ // We have a constant initializer, but a nontrivial destructor. We still
+ // need to perform a guarded "initialization" in order to register the
+ // destructor.
+ cgm.errorNYI(d.getSourceRange(), "C++ guarded init");
+ }
+
+ return gv;
+}
+
+void CIRGenFunction::emitStaticVarDecl(const VarDecl &d,
+ cir::GlobalLinkageKind linkage) {
+ // Check to see if we already have a global variable for this
+ // declaration. This can happen when double-emitting function
+ // bodies, e.g. with complete and base constructors.
+ cir::GlobalOp globalOp = cgm.getOrCreateStaticVarDecl(d, linkage);
+ // TODO(cir): we should have a way to represent global ops as values without
+ // having to emit a get global op. Sometimes these emissions are not used.
+ mlir::Value addr = builder.createGetGlobal(globalOp);
+ auto getAddrOp = mlir::cast<cir::GetGlobalOp>(addr.getDefiningOp());
+
+ CharUnits alignment = getContext().getDeclAlign(&d);
+
+ // Store into LocalDeclMap before generating initializer to handle
+ // circular references.
+ mlir::Type elemTy = convertTypeForMem(d.getType());
+ setAddrOfLocalVar(&d, Address(addr, elemTy, alignment));
+
+ // We can't have a VLA here, but we can have a pointer to a VLA,
+ // even though that doesn't really make any sense.
+ // Make sure to evaluate VLA bounds now so that we have them for later.
+ if (d.getType()->isVariablyModifiedType()) {
+ cgm.errorNYI(d.getSourceRange(),
+ "emitStaticVarDecl: variably modified type");
+ }
+
+ // Save the type in case adding the initializer forces a type change.
+ mlir::Type expectedType = addr.getType();
+
+ cir::GlobalOp var = globalOp;
+
+ assert(!cir::MissingFeatures::cudaSupport());
+
+ // If this value has an initializer, emit it.
+ if (d.getInit())
+ var = addInitializerToStaticVarDecl(d, var, getAddrOp);
+
+ var.setAlignment(alignment.getAsAlign().value());
+
+ if (d.hasAttr<AnnotateAttr>())
+ cgm.errorNYI(d.getSourceRange(), "static var annotation");
+
+ if (d.getAttr<PragmaClangBSSSectionAttr>())
+ cgm.errorNYI(d.getSourceRange(), "static var BSS section attribute");
+ if (d.getAttr<PragmaClangDataSectionAttr>())
+ cgm.errorNYI(d.getSourceRange(), "static var Data section attribute");
+ if (d.getAttr<PragmaClangRodataSectionAttr>())
+ cgm.errorNYI(d.getSourceRange(), "static var Rodata section attribute");
+ if (d.getAttr<PragmaClangRelroSectionAttr>())
+ cgm.errorNYI(d.getSourceRange(), "static var Relro section attribute");
+
+ if (d.getAttr<SectionAttr>())
+ cgm.errorNYI(d.getSourceRange(),
+ "static var object file section attribute");
+
+ if (d.hasAttr<RetainAttr>())
+ cgm.errorNYI(d.getSourceRange(), "static var retain attribute");
+ else if (d.hasAttr<UsedAttr>())
+ cgm.errorNYI(d.getSourceRange(), "static var used attribute");
+
+ if (cgm.getCodeGenOpts().KeepPersistentStorageVariables)
+ cgm.errorNYI(d.getSourceRange(), "static var keep persistent storage");
+
+ // From traditional codegen:
+ // We may have to cast the constant because of the initializer
+ // mismatch above.
+ //
+ // FIXME: It is really dangerous to store this in the map; if anyone
+ // RAUW's the GV uses of this constant will be invalid.
+ mlir::Value castedAddr =
+ builder.createBitcast(getAddrOp.getAddr(), expectedType);
+ localDeclMap.find(&d)->second = Address(castedAddr, elemTy, alignment);
+ cgm.setStaticLocalDeclAddress(&d, var);
+
+ assert(!cir::MissingFeatures::sanitizers());
+ assert(!cir::MissingFeatures::generateDebugInfo());
+}
+
void CIRGenFunction::emitScalarInit(const Expr *init, mlir::Location loc,
LValue lvalue, bool capturedByInit) {
assert(!cir::MissingFeatures::objCLifetime());
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 361dcd5ef1c31..56ecee3f45367 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -465,6 +465,10 @@ class CIRGenFunction : public CIRGenTypeCache {
/// compare the result against zero, returning an Int1Ty value.
mlir::Value evaluateExprAsBool(const clang::Expr *e);
+ cir::GlobalOp addInitializerToStaticVarDecl(const VarDecl &d,
+ cir::GlobalOp gv,
+ cir::GetGlobalOp gvAddr);
+
/// Set the address of a local variable.
void setAddrOfLocalVar(const clang::VarDecl *vd, Address addr) {
assert(!localDeclMap.count(vd) && "Decl already exists in LocalDeclMap!");
@@ -935,6 +939,8 @@ class CIRGenFunction : public CIRGenTypeCache {
void emitScalarInit(const clang::Expr *init, mlir::Location loc,
LValue lvalue, bool capturedByInit = false);
+ void emitStaticVarDecl(const VarDecl &d, cir::GlobalLinkageKind linkage);
+
void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile,
clang::QualType ty, bool isInit = false,
bool isNontemporal = false);
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h
index f76fd8e733642..03606dba200fd 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -113,8 +113,21 @@ class CIRGenModule : public CIRGenTypeCache {
mlir::Operation *lastGlobalOp = nullptr;
+ llvm::DenseMap<const Decl *, cir::GlobalOp> staticLocalDeclMap;
+
mlir::Operation *getGlobalValue(llvm::StringRef ref);
+ cir::GlobalOp getStaticLocalDeclAddress(const VarDecl *d) {
+ return staticLocalDeclMap[d];
+ }
+
+ void setStaticLocalDeclAddress(const VarDecl *d, cir::GlobalOp c) {
+ staticLocalDeclMap[d] = c;
+ }
+
+ cir::GlobalOp getOrCreateStaticVarDecl(const VarDecl &d,
+ cir::GlobalLinkageKind linkage);
+
/// If the specified mangled name is not in the module, create and return an
/// mlir::GlobalOp value
cir::GlobalOp getOrCreateCIRGlobal(llvm::StringRef mangledName, mlir::Type ty,
diff --git a/clang/test/CIR/CodeGen/static-vars.c b/clang/test/CIR/CodeGen/static-vars.c
new file mode 100644
index 0000000000000..f45a41d9a00fc
--- /dev/null
+++ b/clang/test/CIR/CodeGen/static-vars.c
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s
+
+void func1(void) {
+ // Should lower default-initialized static vars.
+ static int i;
+ // CHECK-DAG: cir.global "private" internal dsolocal @func1.i = #cir.int<0> : !s32i
+
+ // Should lower constant-initialized static vars.
+ static int j = 1;
+ // CHECK-DAG: cir.global "private" internal dsolocal @func1.j = #cir.int<1> : !s32i
+
+ // Should properly shadow static vars in nested scopes.
+ {
+ static int j = 2;
+ // CHECK-DAG: cir.global "private" internal dsolocal @func1.j.1 = #cir.int<2> : !s32i
+ }
+ {
+ static int j = 3;
+ // CHECK-DAG: cir.global "private" internal dsolocal @func1.j.2 = #cir.int<3> : !s32i
+ }
+
+ // Should lower basic static vars arithmetics.
+ j++;
+ // CHECK-DAG: %[[#V2:]] = cir.get_global @func1.j : !cir.ptr<!s32i>
+ // CHECK-DAG: %[[#V3:]] = cir.load{{.*}} %[[#V2]] : !cir.ptr<!s32i>, !s32i
+ // CHECK-DAG: %[[#V4:]] = cir.unary(inc, %[[#V3]]) nsw : !s32i, !s32i
+ // CHECK-DAG: cir.store{{.*}} %[[#V4]], %[[#V2]] : !s32i, !cir.ptr<!s32i>
+}
+
+// Should shadow static vars on different functions.
+void func2(void) {
+ static char i;
+ // CHECK-DAG: cir.global "private" internal dsolocal @func2.i = #cir.int<0> : !s8i
+ static float j;
+ // CHECK-DAG: cir.global "private" internal dsolocal @func2.j = #cir.fp<0.000000e+00> : !cir.float
+}
diff --git a/clang/test/CIR/CodeGen/static-vars.cpp b/clang/test/CIR/CodeGen/static-vars.cpp
new file mode 100644
index 0000000000000..9b892c69a6fed
--- /dev/null
+++ b/clang/test/CIR/CodeGen/static-vars.cpp
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t1.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t1.ll %s
+
+void func1(void) {
+ // Should lower default-initialized static vars.
+ static int i;
+ // CHECK-DAG: cir.global "private" internal dsolocal @_ZZ5func1vE1i = #cir.int<0> : !s32i
+
+ // Should lower constant-initialized static vars.
+ static int j = 1;
+ // CHECK-DAG: cir.global "private" internal dsolocal @_ZZ5func1vE1j = #cir.int<1> : !s32i
+
+ // Should properly shadow static vars in nested scopes.
+ {
+ static int j = 2;
+ // CHECK-DAG: cir.global "private" internal dsolocal @_ZZ5func1vE1j_0 = #cir.int<2> : !s32i
+ }
+ {
+ static int j = 3;
+ // CHECK-DAG: cir.global "private" internal ds...
[truncated]
|
erichkeane
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor suggestions, else LGTM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't use module! I realize it is a contextual keyword, but some parsers are going to get grumpy at this (like githubs!).
clang/lib/CIR/CodeGen/CIRGenDecl.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm on the fence about a suggestion here... just always init 'name' above and let AsmLabelAttr errorNYI for now, and whoever comes to fix this can figure out if the branch is reasonable. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I thought about that too. It's going to do something bad if it hits the NYI case, but I guess we may as well make that something as predictable as possible.
clang/lib/CIR/CodeGen/CIRGenDecl.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The set isn't in its own branch, can we just do this one inline?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was one of those "making it look like the code that is to come" things. The incubator code looks like this:
mlir::Attribute Init = nullptr;
if (D.hasAttr<LoaderUninitializedAttr>())
llvm_unreachable("CUDA is NYI");
else if (Ty.getAddressSpace() != LangAS::opencl_local &&
!D.hasAttr<CUDASharedAttr>())
Init = builder.getZeroInitAttr(convertType(Ty));
And so there is a path where it's left as nullptr. That's shouldn't be too hard to figure out later though.
clang/lib/CIR/CodeGen/CIRGenDecl.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First, the else is weird here? Thought IDK the rules of Retain vs Used. Second, this pile of attributes changing stuff here is illuminating :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose I should just have one check for any of a list of attributes. This is also not implemented in the incubator, FWIW. It seemed wrong to just put a pile of MissingFeatures here, so I did this. Classic codegen does this with retain and used:
if (D.hasAttr<RetainAttr>())
CGM.addUsedGlobal(var);
else if (D.hasAttr<UsedAttr>())
CGM.addUsedOrCompilerUsedGlobal(var);
I guess if it had retain, also handling used is redundant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dont mind the list, it was more of a lamenting how many we have that changes this behavior here :) I guess you're right on used/retain, just an odd looking one after everything else.
This adds support for emitting static variables and their initializers.
fcc90ef to
f72d8d9
Compare
This adds support for emitting static variables and their initializers.
This adds support for emitting static variables and their initializers.
This adds support for emitting static variables and their initializers.