aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/CIR/CIRGenerator.h2
-rw-r--r--clang/include/clang/CIR/MissingFeatures.h1
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenModule.cpp61
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenModule.h4
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenerator.cpp7
-rw-r--r--clang/lib/CIR/FrontendAction/CIRGenAction.cpp4
-rw-r--r--clang/test/CIR/CodeGen/array.cpp26
-rw-r--r--clang/test/CIR/CodeGen/basic.c47
-rw-r--r--clang/test/CIR/CodeGen/basic.cpp53
-rw-r--r--clang/test/CIR/CodeGen/string-literals.c7
-rw-r--r--clang/test/CIR/CodeGen/struct.c12
-rw-r--r--clang/test/CIR/Lowering/array.cpp18
-rw-r--r--clang/test/CIR/Lowering/hello.c8
13 files changed, 155 insertions, 95 deletions
diff --git a/clang/include/clang/CIR/CIRGenerator.h b/clang/include/clang/CIR/CIRGenerator.h
index 883dce9..bb20fdf 100644
--- a/clang/include/clang/CIR/CIRGenerator.h
+++ b/clang/include/clang/CIR/CIRGenerator.h
@@ -54,6 +54,8 @@ public:
~CIRGenerator() override;
void Initialize(clang::ASTContext &astContext) override;
bool HandleTopLevelDecl(clang::DeclGroupRef group) override;
+ void CompleteTentativeDefinition(clang::VarDecl *d) override;
+
mlir::ModuleOp getModule() const;
mlir::MLIRContext &getMLIRContext() { return *mlirContext; };
const mlir::MLIRContext &getMLIRContext() const { return *mlirContext; };
diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h
index fb205e9..56bf9b1 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -201,6 +201,7 @@ struct MissingFeatures {
static bool writebacks() { return false; }
static bool cleanupsToDeactivate() { return false; }
static bool stackBase() { return false; }
+ static bool deferredDecls() { return false; }
// Missing types
static bool dataMemberType() { return false; }
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,
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h
index add1b40..aac8fe7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -111,6 +111,8 @@ public:
/// Handling globals
/// -------
+ mlir::Operation *lastGlobalOp = nullptr;
+
mlir::Operation *getGlobalValue(llvm::StringRef ref);
/// If the specified mangled name is not in the module, create and return an
@@ -194,6 +196,8 @@ public:
llvm::StringRef getMangledName(clang::GlobalDecl gd);
+ void emitTentativeDefinition(const VarDecl *d);
+
static void setInitializer(cir::GlobalOp &op, mlir::Attribute value);
cir::FuncOp
diff --git a/clang/lib/CIR/CodeGen/CIRGenerator.cpp b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
index 40252ff..726da5b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenerator.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
@@ -62,3 +62,10 @@ bool CIRGenerator::HandleTopLevelDecl(DeclGroupRef group) {
return true;
}
+
+void CIRGenerator::CompleteTentativeDefinition(VarDecl *d) {
+ if (diags.hasErrorOccurred())
+ return;
+
+ cgm->emitTentativeDefinition(d);
+}
diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
index cc65c93..48ae2a0 100644
--- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
+++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
@@ -135,6 +135,10 @@ public:
}
}
}
+
+ void CompleteTentativeDefinition(VarDecl *D) override {
+ Gen->CompleteTentativeDefinition(D);
+ }
};
} // namespace cir
diff --git a/clang/test/CIR/CodeGen/array.cpp b/clang/test/CIR/CodeGen/array.cpp
index a4b9398..18f30b2 100644
--- a/clang/test/CIR/CodeGen/array.cpp
+++ b/clang/test/CIR/CodeGen/array.cpp
@@ -19,16 +19,6 @@ int aa[10][5];
// OGCG: @aa = global [10 x [5 x i32]] zeroinitializer
-extern int b[10];
-// CIR: cir.global external @b = #cir.zero : !cir.array<!s32i x 10>
-
-// LLVM: @b = dso_local global [10 x i32] zeroinitializer
-
-extern int bb[10][5];
-// CIR: cir.global external @bb = #cir.zero : !cir.array<!cir.array<!s32i x 5> x 10>
-
-// LLVM: @bb = dso_local global [10 x [5 x i32]] zeroinitializer
-
int c[10] = {};
// CIR: cir.global external @c = #cir.zero : !cir.array<!s32i x 10>
@@ -66,6 +56,22 @@ int f[5] = {1, 2};
// OGCG: @f = global [5 x i32] [i32 1, i32 2, i32 0, i32 0, i32 0]
+extern int b[10];
+// CIR: cir.global external @b : !cir.array<!s32i x 10>
+// LLVM: @b = external dso_local global [10 x i32]
+// OGCG: @b = external global [10 x i32]
+
+extern int bb[10][5];
+// CIR: cir.global external @bb : !cir.array<!cir.array<!s32i x 5> x 10>
+// LLVM: @bb = external dso_local global [10 x [5 x i32]]
+// OGCG: @bb = external global [10 x [5 x i32]]
+
+// This function is only here to make sure the external globals are emitted.
+void reference_externs() {
+ b;
+ bb;
+}
+
// OGCG: @[[FUN2_ARR:.*]] = private unnamed_addr constant [2 x i32] [i32 5, i32 0], align 4
// OGCG: @[[FUN3_ARR:.*]] = private unnamed_addr constant [2 x i32] [i32 5, i32 6], align 4
// OGCG: @[[FUN4_ARR:.*]] = private unnamed_addr constant [2 x [1 x i32]] [
diff --git a/clang/test/CIR/CodeGen/basic.c b/clang/test/CIR/CodeGen/basic.c
index 835885c..abc1a45f 100644
--- a/clang/test/CIR/CodeGen/basic.c
+++ b/clang/test/CIR/CodeGen/basic.c
@@ -5,6 +5,28 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll
// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+enum A {
+ A_one,
+ A_two
+};
+enum A a;
+
+// CHECK: cir.global external @a = #cir.int<0> : !u32i
+
+enum B : int;
+enum B b;
+
+// CHECK: cir.global external @b = #cir.int<0> : !u32i
+
+
+enum C : int {
+ C_one,
+ C_two
+};
+enum C c;
+
+// CHECK: cir.global external @c = #cir.int<0> : !u32i
+
int f1(int i);
int f1(int i) {
@@ -12,8 +34,7 @@ int f1(int i) {
return i;
}
-// CIR: module
-// CIR-NEXT: cir.func @f1(%arg0: !s32i loc({{.*}})) -> !s32i
+// CIR: cir.func @f1(%arg0: !s32i loc({{.*}})) -> !s32i
// CIR-NEXT: %[[I_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init] {alignment = 4 : i64}
// CIR-NEXT: %[[RV:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}
// CIR-NEXT: cir.store{{.*}} %arg0, %[[I_PTR]] : !s32i, !cir.ptr<!s32i>
@@ -288,25 +309,3 @@ size_type max_size(void) {
// CHECK: %6 = cir.load{{.*}} %0 : !cir.ptr<!u64i>, !u64i
// CHECK: cir.return %6 : !u64i
// CHECK: }
-
-enum A {
- A_one,
- A_two
-};
-enum A a;
-
-// CHECK: cir.global external @a = #cir.int<0> : !u32i
-
-enum B : int;
-enum B b;
-
-// CHECK: cir.global external @b = #cir.int<0> : !u32i
-
-
-enum C : int {
- C_one,
- C_two
-};
-enum C c;
-
-// CHECK: cir.global external @c = #cir.int<0> : !u32i
diff --git a/clang/test/CIR/CodeGen/basic.cpp b/clang/test/CIR/CodeGen/basic.cpp
index 53f13f1..ed1c6d3 100644
--- a/clang/test/CIR/CodeGen/basic.cpp
+++ b/clang/test/CIR/CodeGen/basic.cpp
@@ -1,11 +1,36 @@
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - 2>&1 | FileCheck %s
+enum A {
+ A_one,
+ A_two
+};
+enum A a;
+
+// CHECK: cir.global external @a = #cir.int<0> : !u32i
+
+enum B : int;
+enum B b;
+
+// CHECK: cir.global external @b = #cir.int<0> : !s32i
+
+enum C : int {
+ C_one,
+ C_two
+};
+enum C c;
+
+// CHECK: cir.global external @c = #cir.int<0> : !s32i
+
+enum class D : int;
+enum D d;
+
+// CHECK: cir.global external @d = #cir.int<0> : !s32i
+
int f1() {
int i;
return i;
}
-// CHECK: module
// CHECK: cir.func @_Z2f1v() -> !s32i
// CHECK: %[[RV:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}
// CHECK: %[[I_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["i"] {alignment = 4 : i64}
@@ -145,29 +170,3 @@ void ref_local(short x) {
// CHECK: %[[Y_REF_ADDR:.*]] = cir.alloca !cir.ptr<!s16i>, !cir.ptr<!cir.ptr<!s16i>>, ["y", init, const] {alignment = 8 : i64}
// CHECK: cir.store{{.*}} %[[ARG]], %[[X_ADDR]] : !s16i, !cir.ptr<!s16i>
// CHECK: cir.store{{.*}} %[[X_ADDR]], %[[Y_REF_ADDR]] : !cir.ptr<!s16i>, !cir.ptr<!cir.ptr<!s16i>>
-
-enum A {
- A_one,
- A_two
-};
-enum A a;
-
-// CHECK: cir.global external @a = #cir.int<0> : !u32i
-
-enum B : int;
-enum B b;
-
-// CHECK: cir.global external @b = #cir.int<0> : !s32i
-
-enum C : int {
- C_one,
- C_two
-};
-enum C c;
-
-// CHECK: cir.global external @c = #cir.int<0> : !s32i
-
-enum class D : int;
-enum D d;
-
-// CHECK: cir.global external @d = #cir.int<0> : !s32i
diff --git a/clang/test/CIR/CodeGen/string-literals.c b/clang/test/CIR/CodeGen/string-literals.c
index 873b00d..81d2a27 100644
--- a/clang/test/CIR/CodeGen/string-literals.c
+++ b/clang/test/CIR/CodeGen/string-literals.c
@@ -5,6 +5,10 @@
// RUN: %clang_cc1 -triple aarch64-none-linux-android21 -emit-llvm %s -o %t.ll
// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
+// CIR: cir.global external @[[STR1_GLOBAL:.*]] = #cir.const_array<"1\00" : !cir.array<!s8i x 2>> : !cir.array<!s8i x 2>
+// CIR: cir.global external @[[STR2_GLOBAL:.*]] = #cir.zero : !cir.array<!s8i x 1>
+// CIR: cir.global external @[[STR3_GLOBAL:.*]] = #cir.zero : !cir.array<!s8i x 2>
+
// LLVM: @[[STR1_GLOBAL:.*]] = dso_local global [2 x i8] c"1\00"
// LLVM: @[[STR2_GLOBAL:.*]] = dso_local global [1 x i8] zeroinitializer
// LLVM: @[[STR3_GLOBAL:.*]] = dso_local global [2 x i8] zeroinitializer
@@ -17,7 +21,6 @@ char *f1() {
return "1";
}
-// CIR: cir.global external @[[STR1_GLOBAL:.*]] = #cir.const_array<"1\00" : !cir.array<!s8i x 2>> : !cir.array<!s8i x 2>
// CIR: cir.func @f1()
// CIR: %[[STR:.*]] = cir.get_global @[[STR1_GLOBAL]] : !cir.ptr<!cir.array<!s8i x 2>>
@@ -31,7 +34,6 @@ char *f2() {
return "";
}
-// CIR: cir.global external @[[STR2_GLOBAL:.*]] = #cir.zero : !cir.array<!s8i x 1>
// CIR: cir.func @f2()
// CIR: %[[STR2:.*]] = cir.get_global @[[STR2_GLOBAL]] : !cir.ptr<!cir.array<!s8i x 1>>
@@ -45,7 +47,6 @@ char *f3() {
return "\00";
}
-// CIR: cir.global external @[[STR3_GLOBAL:.*]] = #cir.zero : !cir.array<!s8i x 2>
// CIR: cir.func @f3()
// CIR: %[[STR3:.*]] = cir.get_global @[[STR3_GLOBAL]] : !cir.ptr<!cir.array<!s8i x 2>>
diff --git a/clang/test/CIR/CodeGen/struct.c b/clang/test/CIR/CodeGen/struct.c
index 9c4a730..4c18de2 100644
--- a/clang/test/CIR/CodeGen/struct.c
+++ b/clang/test/CIR/CodeGen/struct.c
@@ -42,12 +42,6 @@
// OGCG-DAG: %struct.CycleMiddle = type { ptr }
// OGCG-DAG: %struct.CycleEnd = type { ptr }
-struct IncompleteS *p;
-
-// CIR: cir.global external @p = #cir.ptr<null> : !cir.ptr<!rec_IncompleteS>
-// LLVM-DAG: @p = dso_local global ptr null
-// OGCG-DAG: @p = global ptr null, align 8
-
struct CompleteS {
int a;
char b;
@@ -57,6 +51,12 @@ struct CompleteS {
// LLVM-DAG: @cs = dso_local global %struct.CompleteS zeroinitializer
// OGCG-DAG: @cs = global %struct.CompleteS zeroinitializer, align 4
+struct IncompleteS *p;
+
+// CIR: cir.global external @p = #cir.ptr<null> : !cir.ptr<!rec_IncompleteS>
+// LLVM-DAG: @p = dso_local global ptr null
+// OGCG-DAG: @p = global ptr null, align 8
+
struct InnerS {
int a;
char b;
diff --git a/clang/test/CIR/Lowering/array.cpp b/clang/test/CIR/Lowering/array.cpp
index 4d9161d..335042c 100644
--- a/clang/test/CIR/Lowering/array.cpp
+++ b/clang/test/CIR/Lowering/array.cpp
@@ -7,12 +7,6 @@ int a[10];
int aa[10][5];
// CHECK: @aa = dso_local global [10 x [5 x i32]] zeroinitializer
-extern int b[10];
-// CHECK: @b = dso_local global [10 x i32] zeroinitializer
-
-extern int bb[10][5];
-// CHECK: @bb = dso_local global [10 x [5 x i32]] zeroinitializer
-
int c[10] = {};
// CHECK: @c = dso_local global [10 x i32] zeroinitializer
@@ -30,6 +24,18 @@ int e[10] = {1, 2};
int f[5] = {1, 2};
// CHECK: @f = dso_local global [5 x i32] [i32 1, i32 2, i32 0, i32 0, i32 0]
+extern int b[10];
+// CHECK: @b = external dso_local global [10 x i32]
+
+extern int bb[10][5];
+// CHECK: @bb = external dso_local global [10 x [5 x i32]]
+
+// This function is only here to make sure the external globals are emitted.
+void reference_externs() {
+ b;
+ bb;
+}
+
void func() {
int arr[10];
int e = arr[0];
diff --git a/clang/test/CIR/Lowering/hello.c b/clang/test/CIR/Lowering/hello.c
index f45beaf..21adf17 100644
--- a/clang/test/CIR/Lowering/hello.c
+++ b/clang/test/CIR/Lowering/hello.c
@@ -1,10 +1,10 @@
// Smoke test for ClangIR-to-LLVM IR code generation
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s
-int a;
-
-// CHECK: @a = dso_local global i32 0
-
int b = 2;
// CHECK: @b = dso_local global i32 2
+
+int a;
+
+// CHECK: @a = dso_local global i32 0