Author: David Rivera
Date: 2026-10-08T01:57:37-04:00
New Revision: b22be3443558a3834e1d7d444c02e2f32bad2ef2

URL: 
https://github.com/llvm/llvm-project/commit/b22be3443558a3834e1d7d444c02e2f32bad2ef2
DIFF: 
https://github.com/llvm/llvm-project/commit/b22be3443558a3834e1d7d444c02e2f32bad2ef2.diff

LOG: [CIR] Print the initial value of globals with a ctor region (#229565)

Globals were not printing their initializer when a ctor region existed
for the op. So round tripping the serialized op before running
LoweringPrepareo on a .cir module was throwing this error from the
verifier:

```sh
error: 'cir.global' op symbol declaration cannot have public visibility
```

The global lost its initial value on the round trip. Once
LoweringPrepare moved the ctor region out, had no initial value and no
regions, so it looked like a public declaration.


The initial value is now printed before the ctor region, the same way
the dtor region already works:
```mlir
  cir.global external @s = #cir.zero : !rec_S ctor { ... }
```

The old `= ctor : type { ... }` form no longer parses, and the verifier
requires an initial value on any global with a ctor region.


Claude assisted with this patch.

Added: 
    

Modified: 
    clang/lib/CIR/Dialect/IR/CIRDialect.cpp
    clang/test/CIR/CodeGen/builtin-call.cpp
    clang/test/CIR/CodeGen/global-constant-storage.cpp
    clang/test/CIR/CodeGen/global-init-order.cpp
    clang/test/CIR/CodeGen/global-init.cpp
    clang/test/CIR/CodeGen/global-temp-dtor.cpp
    clang/test/CIR/CodeGen/global-tls-dyn-init.cpp
    clang/test/CIR/CodeGen/global-tls-dynamic-vs-static.cpp
    clang/test/CIR/CodeGen/global-tls-simple-init.cpp
    clang/test/CIR/CodeGen/global-tls-templates.cpp
    clang/test/CIR/CodeGen/pointer-to-data-member.cpp
    clang/test/CIR/CodeGen/pointer-to-member-func.cpp
    clang/test/CIR/CodeGen/unions-with-zero-init.cpp
    clang/test/CIR/CodeGenCXX/global-refs.cpp
    clang/test/CIR/CodeGenCXX/init-priority-attr.cpp
    clang/test/CIR/CodeGenCXX/typeid.cpp
    clang/test/CIR/CodeGenCXX/zero_init_bases.cpp
    clang/test/CIR/IR/global-init.cir
    clang/test/CIR/IR/invalid-global.cir
    clang/test/CIR/IR/invalid-static-local.cir
    clang/unittests/CIR/ControlFlowTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index a97606a5a9bd7..2c5b785d5fc34 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -2371,6 +2371,12 @@ mlir::LogicalResult cir::GlobalOp::verify() {
       return failure();
   }
 
+  // The initial value can't be recomputed from the type once the ctor is
+  // lowered (e.g. a null member pointer becomes -1 after CXXABILowering).
+  if (!getCtorRegion().empty() && !getInitialValue().has_value())
+    return emitOpError(
+        "cannot have a constructor region without an initial value");
+
   std::optional<DynamicInitInfoAttr> info = getDynamicInitInfo();
 
   if ((getDynamicInitGuard().has_value()) && (!info || info->getLocal()) &&
@@ -2519,17 +2525,14 @@ static void 
printGlobalOpTypeAndInitialValue(OpAsmPrinter &p, cir::GlobalOp op,
   }
 
   p << "= ";
+  if (initAttr)
+    printConstant(p, initAttr);
+
   if (!ctorRegion.empty()) {
-    p << "ctor ";
-    printType();
-    p << " ";
+    p << " ctor ";
     p.printRegion(ctorRegion,
                   /*printEntryBlockArgs=*/false,
                   /*printBlockTerminators=*/false);
-  } else {
-    // This also prints the type...
-    if (initAttr)
-      printConstant(p, initAttr);
   }
 
   if (!dtorRegion.empty()) {
@@ -2552,26 +2555,24 @@ static ParseResult 
parseGlobalOpTypeAndInitialValue(OpAsmParser &parser,
     if (parser.parseColonType(opTy))
       return failure();
   } else {
-    // Parse contructor, example:
-    //  cir.global @rgb = ctor : type { ... }
+    // Parse constant with initializer, examples:
+    //  cir.global @y = 3.400000e+00 : f32
+    //  cir.global @rgb = #cir.const_array<[...] : !cir.array<i8 x 3>>
+    if (parseConstantValue(parser, initialValueAttr).failed())
+      return failure();
+
+    assert(mlir::isa<mlir::TypedAttr>(initialValueAttr) &&
+           "Non-typed attrs shouldn't appear here.");
+    opTy = mlir::cast<mlir::TypedAttr>(initialValueAttr).getType();
+
+    // Parse constructor, example:
+    //  cir.global @rgb = #cir.zero : type ctor { ... }
     if (!parser.parseOptionalKeyword("ctor")) {
-      if (parser.parseColonType(opTy))
-        return failure();
       auto parseLoc = parser.getCurrentLocation();
       if (parser.parseRegion(ctorRegion, /*arguments=*/{}, /*argTypes=*/{}))
         return failure();
       if (ensureRegionTerm(parser, ctorRegion, parseLoc).failed())
         return failure();
-    } else {
-      // Parse constant with initializer, examples:
-      //  cir.global @y = 3.400000e+00 : f32
-      //  cir.global @rgb = #cir.const_array<[...] : !cir.array<i8 x 3>>
-      if (parseConstantValue(parser, initialValueAttr).failed())
-        return failure();
-
-      assert(mlir::isa<mlir::TypedAttr>(initialValueAttr) &&
-             "Non-typed attrs shouldn't appear here.");
-      opTy = mlir::cast<mlir::TypedAttr>(initialValueAttr).getType();
     }
 
     // Parse destructor, example:

diff  --git a/clang/test/CIR/CodeGen/builtin-call.cpp 
b/clang/test/CIR/CodeGen/builtin-call.cpp
index 5d84d0e762223..e647852521b41 100644
--- a/clang/test/CIR/CodeGen/builtin-call.cpp
+++ b/clang/test/CIR/CodeGen/builtin-call.cpp
@@ -14,7 +14,7 @@ const double parsed = strtod(str, nullptr);
 // LLVM:  @_ZL6parsed = internal global double 0.000000e+00, align 8 
 // LLVM:  @v = global ptr null, align 8
 
-// CIR-BEFORE-LPP:  cir.global "private" internal dso_local @_ZL6parsed = ctor 
: !cir.double {
+// CIR-BEFORE-LPP:  cir.global "private" internal dso_local @_ZL6parsed = 
#cir.fp<0.000000e+00> : !cir.double ctor {
 // CIR-BEFORE-LPP:    %[[GET_GLOB:.*]] = cir.get_global @_ZL6parsed : 
!cir.ptr<!cir.double>
 // CIR-BEFORE-LPP:    %[[GET_BUILTIN:.*]] = cir.get_global @strtod : 
!cir.ptr<!cir.func<(!cir.ptr<!s8i>, !cir.ptr<!cir.ptr<!s8i>>) -> !cir.double>>
 // CIR-BEFORE-LPP:    %[[GET_STR:.*]] = cir.get_global @str : 
!cir.ptr<!cir.ptr<!s8i>>
@@ -50,7 +50,7 @@ void *memcpy(void *a, const void *b, size_t c) {
 }
 
 const void* v = memcpy(nullptr, nullptr, 1);
-// CIR-BEFORE-LPP:  cir.global external @v = ctor : !cir.ptr<!void> {
+// CIR-BEFORE-LPP:  cir.global external @v = #cir.ptr<null> : !cir.ptr<!void> 
ctor {
 // CIR-BEFORE-LPP:    %[[GET_V:.*]] = cir.get_global @v : 
!cir.ptr<!cir.ptr<!void>>
 // CIR-BEFORE-LPP:    %[[NULL1:.*]] = cir.const #cir.ptr<null> : 
!cir.ptr<!void>
 // CIR-BEFORE-LPP:    %[[NULL2:.*]] = cir.const #cir.ptr<null> : 
!cir.ptr<!void>

diff  --git a/clang/test/CIR/CodeGen/global-constant-storage.cpp 
b/clang/test/CIR/CodeGen/global-constant-storage.cpp
index 64b75c69f2971..e9ae3151401dd 100644
--- a/clang/test/CIR/CodeGen/global-constant-storage.cpp
+++ b/clang/test/CIR/CodeGen/global-constant-storage.cpp
@@ -52,27 +52,27 @@ const C c;
 
 // CIR checks before LoweringPrepare transformation - globals have ctor regions
 // Test case 'a' - before LoweringPrepare
-// CIR-BEFORE-LPP: cir.global external @a = ctor : !rec_A {
+// CIR-BEFORE-LPP: cir.global external @a = #cir.zero : !rec_A ctor {
 // CIR-BEFORE-LPP:   %[[OBJ:.*]] = cir.get_global @a : !cir.ptr<!rec_A>
 // CIR-BEFORE-LPP:   cir.call @_ZN1AC1Ev(%[[OBJ]]) : (!cir.ptr<!rec_A> {{.*}}) 
-> ()
 // CIR-BEFORE-LPP:   %[[OBJ2:.*]] = cir.get_global @a : !cir.ptr<!rec_A>
 // CIR-BEFORE-LPP: }
 
 // Test case 'a2' - before LoweringPrepare
-// CIR-BEFORE-LPP: cir.global external @a2 = ctor : !rec_A2 {
+// CIR-BEFORE-LPP: cir.global external @a2 = #cir.zero : !rec_A2 ctor {
 // CIR-BEFORE-LPP:   %[[OBJ:.*]] = cir.get_global @a2 : !cir.ptr<!rec_A2>
 // CIR-BEFORE-LPP:   cir.call @_ZN2A2C1Ev(%[[OBJ]]) : (!cir.ptr<!rec_A2> 
{{.*}}) -> ()
 // CIR-BEFORE-LPP:   %[[OBJ2:.*]] = cir.get_global @a2 : !cir.ptr<!rec_A2>
 // CIR-BEFORE-LPP: }
 
 // Test case 'b' - before LoweringPrepare
-// CIR-BEFORE-LPP: cir.global external @b = ctor : !rec_B {
+// CIR-BEFORE-LPP: cir.global external @b = #cir.zero : !rec_B ctor {
 // CIR-BEFORE-LPP:   %[[OBJ:.*]] = cir.get_global @b : !cir.ptr<!rec_B>
 // CIR-BEFORE-LPP:   cir.call @_ZN1BC1Ev(%[[OBJ]]) : (!cir.ptr<!rec_B> {{.*}}) 
-> ()
 // CIR-BEFORE-LPP: }
 
 // Test case 'c' - before LoweringPrepare (internal linkage)
-// CIR-BEFORE-LPP: cir.global {{.*}} internal {{.*}} @_ZL1c = ctor : !rec_C {
+// CIR-BEFORE-LPP: cir.global {{.*}} internal {{.*}} @_ZL1c = #cir.zero : 
!rec_C ctor {
 // CIR-BEFORE-LPP:   %[[OBJ:.*]] = cir.get_global @_ZL1c : !cir.ptr<!rec_C>
 // CIR-BEFORE-LPP:   cir.call @_ZN1CC1Ev(%[[OBJ]]) : (!cir.ptr<!rec_C> {{.*}}) 
-> ()
 // CIR-BEFORE-LPP:   %[[OBJ2:.*]] = cir.get_global @_ZL1c : !cir.ptr<!rec_C>

diff  --git a/clang/test/CIR/CodeGen/global-init-order.cpp 
b/clang/test/CIR/CodeGen/global-init-order.cpp
index 41ab8f21abafc..7e2c1251e1360 100644
--- a/clang/test/CIR/CodeGen/global-init-order.cpp
+++ b/clang/test/CIR/CodeGen/global-init-order.cpp
@@ -21,11 +21,11 @@ NeedsCtor Holder::second;
 NeedsCtor Holder::first;
 
 // CIR-BEFORE-LPP: cir.global external @p = 
#cir.global_view<@_ZN6Holder5firstE> : !cir.ptr<!rec_NeedsCtor>
-// CIR-BEFORE-LPP: cir.global external @_ZN6Holder6secondE = ctor : 
!rec_NeedsCtor {
+// CIR-BEFORE-LPP: cir.global external @_ZN6Holder6secondE = #cir.zero : 
!rec_NeedsCtor ctor {
 // CIR-BEFORE-LPP:   %[[THIS:.*]] = cir.get_global @_ZN6Holder6secondE : 
!cir.ptr<!rec_NeedsCtor>
 // CIR-BEFORE-LPP:   cir.call @_ZN9NeedsCtorC1Ev(%[[THIS]])
 // CIR-BEFORE-LPP: }
-// CIR-BEFORE-LPP: cir.global external @_ZN6Holder5firstE = ctor : 
!rec_NeedsCtor {
+// CIR-BEFORE-LPP: cir.global external @_ZN6Holder5firstE = #cir.zero : 
!rec_NeedsCtor ctor {
 // CIR-BEFORE-LPP:   %[[THIS:.*]] = cir.get_global @_ZN6Holder5firstE : 
!cir.ptr<!rec_NeedsCtor>
 // CIR-BEFORE-LPP:   cir.call @_ZN9NeedsCtorC1Ev(%[[THIS]])
 // CIR-BEFORE-LPP: }

diff  --git a/clang/test/CIR/CodeGen/global-init.cpp 
b/clang/test/CIR/CodeGen/global-init.cpp
index 7d54e911829b2..6696e73f5b1f5 100644
--- a/clang/test/CIR/CodeGen/global-init.cpp
+++ b/clang/test/CIR/CodeGen/global-init.cpp
@@ -37,7 +37,7 @@ struct NeedsCtor {
 
 NeedsCtor needsCtor;
 
-// CIR-BEFORE-LPP: cir.global external @needsCtor = ctor : !rec_NeedsCtor {
+// CIR-BEFORE-LPP: cir.global external @needsCtor = #cir.zero : !rec_NeedsCtor 
ctor {
 // CIR-BEFORE-LPP:   %[[THIS:.*]] = cir.get_global @needsCtor : 
!cir.ptr<!rec_NeedsCtor>
 // CIR-BEFORE-LPP:   cir.call @_ZN9NeedsCtorC1Ev(%[[THIS]]) : 
(!cir.ptr<!rec_NeedsCtor> {{.*}}) -> ()
 
@@ -85,7 +85,7 @@ struct NeedsCtorDtor {
 
 NeedsCtorDtor needsCtorDtor;
 
-// CIR-BEFORE-LPP: cir.global external @needsCtorDtor = ctor : 
!rec_NeedsCtorDtor {
+// CIR-BEFORE-LPP: cir.global external @needsCtorDtor = #cir.zero : 
!rec_NeedsCtorDtor ctor {
 // CIR-BEFORE-LPP:   %[[THIS:.*]] = cir.get_global @needsCtorDtor : 
!cir.ptr<!rec_NeedsCtorDtor>
 // CIR-BEFORE-LPP:   cir.call @_ZN13NeedsCtorDtorC1Ev(%[[THIS]]) : 
(!cir.ptr<!rec_NeedsCtorDtor> {{.*}}) -> ()
 // CIR-BEFORE-LPP: } dtor {
@@ -115,7 +115,7 @@ float num;
 float _Complex a = {num, num};
 
 // CIR-BEFORE-LPP: cir.global external @num = #cir.fp<0.000000e+00> : 
!cir.float
-// CIR-BEFORE-LPP: cir.global external @a = ctor : !cir.complex<!cir.float> {
+// CIR-BEFORE-LPP: cir.global external @a = #cir.zero : 
!cir.complex<!cir.float> ctor {
 // CIR-BEFORE-LPP:  %[[THIS:.*]] = cir.get_global @a : 
!cir.ptr<!cir.complex<!cir.float>>
 // CIR-BEFORE-LPP:  %[[NUM:.*]] = cir.get_global @num : !cir.ptr<!cir.float>
 // CIR-BEFORE-LPP:  %[[REAL:.*]] = cir.load{{.*}} %[[NUM]] : 
!cir.ptr<!cir.float>, !cir.float
@@ -152,7 +152,7 @@ float _Complex a = {num, num};
 float fp;
 int i = (int)fp;
 
-// CIR-BEFORE-LPP: cir.global external @i = ctor : !s32i {
+// CIR-BEFORE-LPP: cir.global external @i = #cir.int<0> : !s32i ctor {
 // CIR-BEFORE-LPP:   %[[I:.*]] = cir.get_global @i : !cir.ptr<!s32i>
 // CIR-BEFORE-LPP:   %[[FP:.*]] = cir.get_global @fp : !cir.ptr<!cir.float>
 // CIR-BEFORE-LPP:   %[[FP_VAL:.*]] = cir.load{{.*}} %[[FP]] : 
!cir.ptr<!cir.float>, !cir.float
@@ -271,7 +271,7 @@ ArrayDtor arrDtor[16];
 int globalInt;
 double &&globalDoubleRef = static_cast<double &&>(globalInt);
 // CIR-BEFORE-LPP: cir.global external @globalInt = #cir.int<0> : !s32i
-// CIR-BEFORE-LPP: cir.global external @globalDoubleRef = ctor : 
!cir.ptr<!cir.double> {
+// CIR-BEFORE-LPP: cir.global external @globalDoubleRef = #cir.ptr<null> : 
!cir.ptr<!cir.double> ctor {
 // CIR-BEFORE-LPP:   %[[GET_SELF:.*]] = cir.get_global @globalDoubleRef : 
!cir.ptr<!cir.ptr<!cir.double>>
 // CIR-BEFORE-LPP:   %[[GET_BACKING_VAR:.*]] = cir.get_global 
@_ZGR15globalDoubleRef_ : !cir.ptr<!cir.double>
 // CIR-BEFORE-LPP:   %[[GET_INT_VAR:.*]] = cir.get_global @globalInt : 
!cir.ptr<!s32i>

diff  --git a/clang/test/CIR/CodeGen/global-temp-dtor.cpp 
b/clang/test/CIR/CodeGen/global-temp-dtor.cpp
index e34bb8b009aeb..7c267ffd0558e 100644
--- a/clang/test/CIR/CodeGen/global-temp-dtor.cpp
+++ b/clang/test/CIR/CodeGen/global-temp-dtor.cpp
@@ -24,7 +24,7 @@ typedef NonTrivial NonTrivialArr[2];
 const NonTrivialArr &static_arr_ref = NonTrivialArr{};
 thread_local const NonTrivialArr &thread_arr_ref = NonTrivialArr{};
 
-// CIR-BEFORE: cir.global external @static_ref = ctor : 
!cir.ptr<!rec_NonTrivial> {
+// CIR-BEFORE: cir.global external @static_ref = #cir.ptr<null> : 
!cir.ptr<!rec_NonTrivial> ctor {
 // CIR-BEFORE:   %[[STATIC_REF:.*]] = cir.get_global @static_ref
 // CIR-BEFORE:   %[[REF_TEMP:.*]] = cir.get_global @_ZGR10static_ref_
 // CIR-BEFORE:   cir.call @_ZN10NonTrivialC1Ev(%[[REF_TEMP]])
@@ -47,7 +47,7 @@ thread_local const NonTrivialArr &thread_arr_ref = 
NonTrivialArr{};
 // CIR:   cir.call @__cxa_atexit
 // CIR: cir.global "private" internal @_ZGR10static_ref_ = #cir.zero : 
!rec_NonTrivial
 
-// CIR-BEFORE: cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW10thread_ref", "_ZTH10thread_ref"> @thread_ref = ctor : 
!cir.ptr<!rec_NonTrivial> {
+// CIR-BEFORE: cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW10thread_ref", "_ZTH10thread_ref"> @thread_ref = #cir.ptr<null> : 
!cir.ptr<!rec_NonTrivial> ctor {
 // CIR-BEFORE:   %[[THREAD_REF:.*]] = cir.get_global thread_local @thread_ref
 // CIR-BEFORE:   %[[REF_TEMP:.*]] = cir.get_global @_ZGR10thread_ref_
 // CIR-BEFORE:   cir.call @_ZN10NonTrivialC1Ev(%[[REF_TEMP]])
@@ -70,7 +70,7 @@ thread_local const NonTrivialArr &thread_arr_ref = 
NonTrivialArr{};
 // CIR:   cir.call @__cxa_thread_atexit
 // CIR: cir.global "private" internal tls_model = tls_dyn @_ZGR10thread_ref_ = 
#cir.zero : !rec_NonTrivial
 
-// CIR-BEFORE: cir.global external @static_arr_ref = ctor : 
!cir.ptr<!cir.array<!rec_NonTrivial x 2>> {
+// CIR-BEFORE: cir.global external @static_arr_ref = #cir.ptr<null> : 
!cir.ptr<!cir.array<!rec_NonTrivial x 2>> ctor {
 // CIR-BEFORE:   %[[ARRAY_INIT_TEMP:.*]] = cir.alloca {{.*}}"arrayinit.temp"
 // CIR-BEFORE:   %[[STATIC_ARR_REF:.*]] = cir.get_global @static_arr_ref
 // CIR-BEFORE:   %[[STATIC_ARR_REF_TEMP:.*]] = cir.get_global 
@_ZGR14static_arr_ref_
@@ -108,7 +108,7 @@ thread_local const NonTrivialArr &thread_arr_ref = 
NonTrivialArr{};
 // CIR:   cir.call @__cxa_atexit
 // CIR: cir.global "private" internal @_ZGR14static_arr_ref_ = #cir.zero : 
!cir.array<!rec_NonTrivial x 2>
 
-// CIR-BEFORE: cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW14thread_arr_ref", "_ZTH14thread_arr_ref"> @thread_arr_ref = ctor : 
!cir.ptr<!cir.array<!rec_NonTrivial x 2>> {
+// CIR-BEFORE: cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW14thread_arr_ref", "_ZTH14thread_arr_ref"> @thread_arr_ref = 
#cir.ptr<null> : !cir.ptr<!cir.array<!rec_NonTrivial x 2>> ctor {
 // CIR-BEFORE:   %[[ARRAY_INIT_TEMP:.*]] = cir.alloca {{.*}}"arrayinit.temp"
 // CIR-BEFORE:   %[[THREAD_ARR_REF:.*]] = cir.get_global thread_local 
@thread_arr_ref
 // CIR-BEFORE:   %[[THREAD_ARR_REF_TEMP:.*]] = cir.get_global 
@_ZGR14thread_arr_ref_
@@ -273,7 +273,7 @@ struct OwnsTemp {
 };
 OwnsTemp owns_temp{ExtendedTemp()};
 
-// CIR-BEFORE: cir.global external @owns_temp = ctor : !rec_OwnsTemp {
+// CIR-BEFORE: cir.global external @owns_temp = #cir.zero : !rec_OwnsTemp ctor 
{
 // CIR-BEFORE: } dtor {
 // CIR-BEFORE-NEXT: %[[OWNER:.*]] = cir.get_global @owns_temp
 // CIR-BEFORE-NEXT: cir.call @_ZN8OwnsTempD1Ev(%[[OWNER]])

diff  --git a/clang/test/CIR/CodeGen/global-tls-dyn-init.cpp 
b/clang/test/CIR/CodeGen/global-tls-dyn-init.cpp
index 4c23dedee6d38..0a0cc48035b0e 100644
--- a/clang/test/CIR/CodeGen/global-tls-dyn-init.cpp
+++ b/clang/test/CIR/CodeGen/global-tls-dyn-init.cpp
@@ -122,7 +122,7 @@ thread_local CtorDtor tls_cd = 5;
 // LLVM-BOTH:   ret void
 
 thread_local CtorDtor tls_cd_dyn = get_i();
-// CIR-BEFORE-LPP:  cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW10tls_cd_dyn", "_ZTH10tls_cd_dyn"> @tls_cd_dyn = ctor : !rec_CtorDtor {
+// CIR-BEFORE-LPP:  cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW10tls_cd_dyn", "_ZTH10tls_cd_dyn"> @tls_cd_dyn = #cir.zero : 
!rec_CtorDtor ctor {
 // CIR-BEFORE-LPP:    %[[GET_GLOB:.*]] = cir.get_global thread_local 
@tls_cd_dyn : !cir.ptr<!rec_CtorDtor>
 // CIR-BEFORE-LPP:    %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i 
{llvm.noundef})
 // CIR-BEFORE-LPP:    cir.call @_ZN8CtorDtorC1Ei(%[[GET_GLOB]], %[[CALL]]) : 
(!cir.ptr<!rec_CtorDtor>
@@ -155,7 +155,7 @@ thread_local CtorDtor tls_cd_dyn = get_i();
 // LLVM-BOTH:   ret void
 
 thread_local CtorDtor &tls_cd_ref = tls_cd_dyn;
-// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW10tls_cd_ref", "_ZTH10tls_cd_ref"> @tls_cd_ref = ctor : 
!cir.ptr<!rec_CtorDtor> {
+// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW10tls_cd_ref", "_ZTH10tls_cd_ref"> @tls_cd_ref = #cir.ptr<null> : 
!cir.ptr<!rec_CtorDtor> ctor {
 // CIR-BEFORE-LPP:   %[[GET_GLOB:.*]] = cir.get_global thread_local 
@tls_cd_ref : !cir.ptr<!cir.ptr<!rec_CtorDtor>>
 // CIR-BEFORE-LPP:   %[[CALL:.*]] = cir.get_global thread_local @tls_cd_dyn : 
!cir.ptr<!rec_CtorDtor>
 // CIR-BEFORE-LPP:   cir.store {{.*}}%[[CALL]], %[[GET_GLOB]] : 
!cir.ptr<!rec_CtorDtor>, !cir.ptr<!cir.ptr<!rec_CtorDtor>>
@@ -182,7 +182,7 @@ thread_local CtorDtor &tls_cd_ref = tls_cd_dyn;
 // OGCG: }
 
 thread_local CtorDtor tls_cd_dyn_not_used = get_i();
-// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW19tls_cd_dyn_not_used", "_ZTH19tls_cd_dyn_not_used"> @tls_cd_dyn_not_used 
= ctor : !rec_CtorDtor {
+// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW19tls_cd_dyn_not_used", "_ZTH19tls_cd_dyn_not_used"> @tls_cd_dyn_not_used 
= #cir.zero : !rec_CtorDtor ctor {
 // CIR-BEFORE-LPP:   %[[GET_GLOB:.*]] = cir.get_global thread_local 
@tls_cd_dyn_not_used : !cir.ptr<!rec_CtorDtor>
 // CIR-BEFORE-LPP:   %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i 
{llvm.noundef})
 // CIR-BEFORE-LPP:   cir.call @_ZN8CtorDtorC1Ei(%[[GET_GLOB]], %[[CALL]])

diff  --git a/clang/test/CIR/CodeGen/global-tls-dynamic-vs-static.cpp 
b/clang/test/CIR/CodeGen/global-tls-dynamic-vs-static.cpp
index 08d3a2d9ed4f3..c6442a0e3cc59 100644
--- a/clang/test/CIR/CodeGen/global-tls-dynamic-vs-static.cpp
+++ b/clang/test/CIR/CodeGen/global-tls-dynamic-vs-static.cpp
@@ -12,7 +12,7 @@ thread_local  int d = f();
 // CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn @a = #cir.int<5> : 
!s32i
 // CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn @b = #cir.int<5> : 
!s32i
 // CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW1c", "_ZTH1c"> @c = #cir.int<5> : !s32i
-// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW1d", "_ZTH1d"> @d = ctor
+// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW1d", "_ZTH1d"> @d = #cir.int<0> : !s32i ctor
 
 // CIR-DAG: cir.global external tls_model = tls_dyn @a = #cir.int<5> : !s32i
 // CIR-DAG: cir.global external tls_model = tls_dyn @b = #cir.int<5> : !s32i

diff  --git a/clang/test/CIR/CodeGen/global-tls-simple-init.cpp 
b/clang/test/CIR/CodeGen/global-tls-simple-init.cpp
index 049e8fd9f16d7..af6c9fe8695dd 100644
--- a/clang/test/CIR/CodeGen/global-tls-simple-init.cpp
+++ b/clang/test/CIR/CodeGen/global-tls-simple-init.cpp
@@ -144,7 +144,7 @@ thread_local int tls_int = 5;
 // CIR: cir.global external tls_model = tls_dyn tls_refs = <"_ZTW7tls_int", 
"_ZTH7tls_int"> @tls_int = #cir.int<5> : !s32i
 
 thread_local int tls_int_dyn = get_i();
-// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW11tls_int_dyn", "_ZTH11tls_int_dyn"> @tls_int_dyn = ctor : !s32i {
+// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW11tls_int_dyn", "_ZTH11tls_int_dyn"> @tls_int_dyn = #cir.int<0> : !s32i 
ctor {
 // CIR-BEFORE-LPP:   %[[GET_GLOB:.*]] = cir.get_global thread_local 
@tls_int_dyn : !cir.ptr<!s32i>
 // CIR-BEFORE-LPP:   %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i 
{llvm.noundef})
 // CIR-BEFORE-LPP:   cir.store {{.*}}%[[CALL]], %[[GET_GLOB]] : !s32i, 
!cir.ptr<!s32i>
@@ -164,7 +164,7 @@ thread_local int tls_int_dyn = get_i();
 // LLVM-BOTH:   ret void
 
 thread_local int &tls_int_ref = tls_int_dyn;
-// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW11tls_int_ref", "_ZTH11tls_int_ref"> @tls_int_ref = ctor : 
!cir.ptr<!s32i> {
+// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW11tls_int_ref", "_ZTH11tls_int_ref"> @tls_int_ref = #cir.ptr<null> : 
!cir.ptr<!s32i> ctor {
 // CIR-BEFORE-LPP:   %[[GET_GLOB:.*]] = cir.get_global thread_local 
@tls_int_ref : !cir.ptr<!cir.ptr<!s32i>>
 // CIR-BEFORE-LPP:   %[[GET_OTHER:.*]] = cir.get_global thread_local 
@tls_int_dyn : !cir.ptr<!s32i>
 // CIR-BEFORE-LPP:   cir.store {{.*}}%[[GET_OTHER]], %[[GET_GLOB]] : 
!cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
@@ -189,7 +189,7 @@ thread_local int &tls_int_ref = tls_int_dyn;
 // OGCG:   ret ptr %[[GET_GLOB]]
 
 thread_local int tls_int_self_init = tls_int_self_init + get_i();
-// CIR-BEFORE-LPP:  cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW17tls_int_self_init", "_ZTH17tls_int_self_init"> @tls_int_self_init = 
ctor : !s32i {
+// CIR-BEFORE-LPP:  cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW17tls_int_self_init", "_ZTH17tls_int_self_init"> @tls_int_self_init = 
#cir.int<0> : !s32i ctor {
 // CIR-BEFORE-LPP:    %[[GET_GLOB:.*]] = cir.get_global thread_local 
@tls_int_self_init : !cir.ptr<!s32i>
 // CIR-BEFORE-LPP:    %[[GET_SELF:.*]] = cir.get_global thread_local 
@tls_int_self_init : !cir.ptr<!s32i>
 // CIR-BEFORE-LPP:    %[[LOAD_SELF:.*]] = cir.load {{.*}}%[[GET_SELF]] : 
!cir.ptr<!s32i>, !s32i
@@ -227,7 +227,7 @@ extern thread_local int definitely_inited = 5;
 // CIR: cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW17definitely_inited", "_ZTH17definitely_inited"> @definitely_inited = 
#cir.int<5> : !s32i
 
 extern thread_local int definitely_inited_dyn = get_i();
-// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW21definitely_inited_dyn", "_ZTH21definitely_inited_dyn"> 
@definitely_inited_dyn = ctor : !s32i {
+// CIR-BEFORE-LPP: cir.global external tls_model = tls_dyn tls_refs = 
<"_ZTW21definitely_inited_dyn", "_ZTH21definitely_inited_dyn"> 
@definitely_inited_dyn = #cir.int<0> : !s32i ctor {
 // CIR-BEFORE-LPP:   %[[GET_GLOB:.*]] = cir.get_global thread_local 
@definitely_inited_dyn : !cir.ptr<!s32i>
 // CIR-BEFORE-LPP:   %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i 
{llvm.noundef})
 // CIR-BEFORE-LPP:   cir.store {{.*}}%[[CALL]], %[[GET_GLOB]] : !s32i, 
!cir.ptr<!s32i>

diff  --git a/clang/test/CIR/CodeGen/global-tls-templates.cpp 
b/clang/test/CIR/CodeGen/global-tls-templates.cpp
index 8c896a4acf0af..1022d296b0b79 100644
--- a/clang/test/CIR/CodeGen/global-tls-templates.cpp
+++ b/clang/test/CIR/CodeGen/global-tls-templates.cpp
@@ -13,13 +13,13 @@ struct CtorDtor {
 template<typename T>
 thread_local T tls_templ = {get_i()};
 
-// CIR-BEFORE-LPP-LABEL:  cir.global linkonce_odr comdat tls_model = tls_dyn 
tls_refs = <"_ZTW9tls_templIiE", "_ZTH9tls_templIiE", "_ZGV9tls_templIiE"> 
dynamic_init_guard<"_ZGV9tls_templIiE"> @_Z9tls_templIiE = ctor : !s32i {
+// CIR-BEFORE-LPP-LABEL:  cir.global linkonce_odr comdat tls_model = tls_dyn 
tls_refs = <"_ZTW9tls_templIiE", "_ZTH9tls_templIiE", "_ZGV9tls_templIiE"> 
dynamic_init_guard<"_ZGV9tls_templIiE"> @_Z9tls_templIiE = #cir.int<0> : !s32i 
ctor {
 // CIR-BEFORE-LPP:    %[[GET_GLOB:.*]] = cir.get_global thread_local 
@_Z9tls_templIiE : !cir.ptr<!s32i>
 // CIR-BEFORE-LPP:    %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i 
{llvm.noundef})
 // CIR-BEFORE-LPP:    cir.store{{.*}} %[[CALL]], %[[GET_GLOB]] : !s32i, 
!cir.ptr<!s32i>
 // CIR-BEFORE-LPP:  }
 //
-// CIR-BEFORE-LPP-LABEL:  cir.global linkonce_odr comdat tls_model = tls_dyn 
tls_refs = <"_ZTW9tls_templI8CtorDtorE", "_ZTH9tls_templI8CtorDtorE", 
"_ZGV9tls_templI8CtorDtorE"> dynamic_init_guard<"_ZGV9tls_templI8CtorDtorE"> 
@_Z9tls_templI8CtorDtorE = ctor : !rec_CtorDtor {
+// CIR-BEFORE-LPP-LABEL:  cir.global linkonce_odr comdat tls_model = tls_dyn 
tls_refs = <"_ZTW9tls_templI8CtorDtorE", "_ZTH9tls_templI8CtorDtorE", 
"_ZGV9tls_templI8CtorDtorE"> dynamic_init_guard<"_ZGV9tls_templI8CtorDtorE"> 
@_Z9tls_templI8CtorDtorE = #cir.zero : !rec_CtorDtor ctor {
 // CIR-BEFORE-LPP:    %[[GET_GLOB:.*]] = cir.get_global thread_local 
@_Z9tls_templI8CtorDtorE : !cir.ptr<!rec_CtorDtor>
 // CIR-BEFORE-LPP:    %[[CALL:.*]] = cir.call @_Z5get_iv() : () -> (!s32i 
{llvm.noundef})
 // CIR-BEFORE-LPP:    cir.call @_ZN8CtorDtorC1Ei(%[[GET_GLOB]], %[[CALL]]) : 
(!cir.ptr<!rec_CtorDtor>

diff  --git a/clang/test/CIR/CodeGen/pointer-to-data-member.cpp 
b/clang/test/CIR/CodeGen/pointer-to-data-member.cpp
index 46b3cb88fd1a4..f8e06fdf69a2d 100644
--- a/clang/test/CIR/CodeGen/pointer-to-data-member.cpp
+++ b/clang/test/CIR/CodeGen/pointer-to-data-member.cpp
@@ -30,7 +30,7 @@ auto test1() -> int Point::* {
 
 int Point::*pt_member_nested_region = test1();
 
-// CIR-BEFORE: cir.global external @pt_member_nested_region = ctor : 
!cir.data_member<!s32i in !rec_Point> {
+// CIR-BEFORE: cir.global external @pt_member_nested_region = 
#cir.data_member<null> : !cir.data_member<!s32i in !rec_Point> ctor {
 // CIR-BEFORE:   %[[MEMBER_PTR_ADDR:.*]] = cir.get_global 
@pt_member_nested_region : !cir.ptr<!cir.data_member<!s32i in !rec_Point>>
 // CIR-BEFORE:   %[[MEMBER_PTR:.*]] = cir.call @_Z5test1v() : () -> 
!cir.data_member<!s32i in !rec_Point>
 // CIR-BEFORE:   cir.store{{.*}} %[[MEMBER_PTR]], %[[MEMBER_PTR_ADDR]] : 
!cir.data_member<!s32i in !rec_Point>, !cir.ptr<!cir.data_member<!s32i in 
!rec_Point>>

diff  --git a/clang/test/CIR/CodeGen/pointer-to-member-func.cpp 
b/clang/test/CIR/CodeGen/pointer-to-member-func.cpp
index afe853c3423a9..65494afa5fd23 100644
--- a/clang/test/CIR/CodeGen/pointer-to-member-func.cpp
+++ b/clang/test/CIR/CodeGen/pointer-to-member-func.cpp
@@ -52,7 +52,7 @@ void (Foo::*m2_ptr)(int) = &Foo::m2;
 
 // Self-referencing PMF causes a null method.
 long (Foo::*pmf1)(int) = pmf1;
-// CIR-BEFORE: @pmf1 = ctor : !cir.method<!cir.func<(!cir.ptr<!rec_Foo>, 
!s32i) -> !s64i> in !rec_Foo> {
+// CIR-BEFORE: @pmf1 = #cir.method<null> : 
!cir.method<!cir.func<(!cir.ptr<!rec_Foo>, !s32i) -> !s64i> in !rec_Foo> ctor {
 // CIR-AFTER: cir.global external @pmf1 = #cir.const_record<{#cir.int<0> : 
!s64i, #cir.int<0> : !s64i}> 
 // LLVM: @pmf1 = global { i64, i64 } zeroinitializer, align 8 
 // OGCG: @pmf1 = global { i64, i64 } zeroinitializer, align 8 

diff  --git a/clang/test/CIR/CodeGen/unions-with-zero-init.cpp 
b/clang/test/CIR/CodeGen/unions-with-zero-init.cpp
index ebddb95c545eb..2b84c18925dae 100644
--- a/clang/test/CIR/CodeGen/unions-with-zero-init.cpp
+++ b/clang/test/CIR/CodeGen/unions-with-zero-init.cpp
@@ -66,7 +66,7 @@ auto use() {
 }
 
 union outer_aggregate{int S::*m; int i; } outer_a1 = { p };
-// CIR-BEFORE-LABEL:   cir.global external @outer_a1 = ctor : 
!rec_outer_aggregate {
+// CIR-BEFORE-LABEL:   cir.global external @outer_a1 = 
#cir.const_record<{#cir.data_member<null> : !cir.data_member<!s32i in !rec_S>}> 
: !rec_outer_aggregate ctor {
 // CIR-BEFORE:     %[[GET_GLOB:.*]] = cir.get_global @outer_a1 : 
!cir.ptr<!rec_outer_aggregate>
 // CIR-BEFORE:     %[[GET_MEM:.*]] = cir.get_member %[[GET_GLOB]][0] {name = 
"m"} : !cir.ptr<!rec_outer_aggregate> -> !cir.ptr<!cir.data_member<!s32i in 
!rec_S>>
 // CIR-BEFORE:     %[[GET_P:.*]] = cir.get_global @p : 
!cir.ptr<!cir.data_member<!s32i in !rec_S>>

diff  --git a/clang/test/CIR/CodeGenCXX/global-refs.cpp 
b/clang/test/CIR/CodeGenCXX/global-refs.cpp
index 7843fad4de638..98a2e85e71ca0 100644
--- a/clang/test/CIR/CodeGenCXX/global-refs.cpp
+++ b/clang/test/CIR/CodeGenCXX/global-refs.cpp
@@ -51,7 +51,7 @@ const DefCtor &constDefCtorRef{};
 // LLVM: @constDefCtorRef = constant ptr @_ZGR15constDefCtorRef_, align 8
 
 WithCtor withCtor{};
-// CIR-BEFORE:  cir.global external @withCtor = ctor : !rec_WithCtor {
+// CIR-BEFORE:  cir.global external @withCtor = #cir.zero : !rec_WithCtor ctor 
{
 // CIR-BEFORE-NEXT:    %[[GET_GLOB:.*]] = cir.get_global @withCtor : 
!cir.ptr<!rec_WithCtor>
 // CIR-BEFORE-NEXT:    cir.call @_ZN8WithCtorC1Ev(%[[GET_GLOB]]) : 
(!cir.ptr<!rec_WithCtor>{{.*}}) -> ()
 // CIR-BEFORE-NEXT:  } align(1) ast(#cir.var.decl.ast)
@@ -68,7 +68,7 @@ WithCtor &withCtorRef = withCtor;
 // LLVM: @withCtorRef = constant ptr @withCtor, align 8
 
 const WithCtor &constWithCtorRef{};
-// CIR-BEFORE: cir.global external @constWithCtorRef = ctor : 
!cir.ptr<!rec_WithCtor> {
+// CIR-BEFORE: cir.global external @constWithCtorRef = #cir.ptr<null> : 
!cir.ptr<!rec_WithCtor> ctor {
 // CIR-BEFORE-NEXT:   %[[GET_GLOB:.*]] = cir.get_global @constWithCtorRef : 
!cir.ptr<!cir.ptr<!rec_WithCtor>>
 // CIR-BEFORE-NEXT:   %[[GET_GLOB_OBJ:.*]] = cir.get_global 
@_ZGR16constWithCtorRef_ : !cir.ptr<!rec_WithCtor>
 // CIR-BEFORE-NEXT:   cir.call @_ZN8WithCtorC1Ev(%[[GET_GLOB_OBJ]]) : 
(!cir.ptr<!rec_WithCtor>{{.*}}) -> ()
@@ -85,7 +85,7 @@ const WithCtor &constWithCtorRef{};
 // LLVM: @constWithCtorRef = global ptr null, align 8
 
 const WithCtor &constWithCtorRef2{5};
-// CIR-BEFORE: cir.global external @constWithCtorRef2 = ctor : 
!cir.ptr<!rec_WithCtor> {
+// CIR-BEFORE: cir.global external @constWithCtorRef2 = #cir.ptr<null> : 
!cir.ptr<!rec_WithCtor> ctor {
 // CIR-BEFORE-NEXT:   %[[GET_GLOB:.*]] = cir.get_global @constWithCtorRef2 : 
!cir.ptr<!cir.ptr<!rec_WithCtor>>
 // CIR-BEFORE-NEXT:   %[[GET_GLOB_OBJ:.*]] = cir.get_global 
@_ZGR17constWithCtorRef2_ : !cir.ptr<!rec_WithCtor>
 // CIR-BEFORE-NEXT:   %[[FIVE:.*]] = cir.const #cir.int<5> : !s32i
@@ -104,7 +104,7 @@ const WithCtor &constWithCtorRef2{5};
 // LLVM: @constWithCtorRef2 = global ptr null, align 8
 
 WithCtorDtor withCtorDtor{};
-// CIR-BEFORE: cir.global external @withCtorDtor = ctor : !rec_WithCtorDtor {
+// CIR-BEFORE: cir.global external @withCtorDtor = #cir.zero : 
!rec_WithCtorDtor ctor {
 // CIR-BEFORE-NEXT:   %[[GET_GLOB:.*]] = cir.get_global @withCtorDtor : 
!cir.ptr<!rec_WithCtorDtor>
 // CIR-BEFORE-NEXT:   cir.call @_ZN12WithCtorDtorC1Ev(%[[GET_GLOB]]) : 
(!cir.ptr<!rec_WithCtorDtor>{{.*}}) -> ()
 // CIR-BEFORE-NEXT: } dtor {

diff  --git a/clang/test/CIR/CodeGenCXX/init-priority-attr.cpp 
b/clang/test/CIR/CodeGenCXX/init-priority-attr.cpp
index 60aeff885b3af..75e303a3b15ba 100644
--- a/clang/test/CIR/CodeGenCXX/init-priority-attr.cpp
+++ b/clang/test/CIR/CodeGenCXX/init-priority-attr.cpp
@@ -38,16 +38,16 @@ A C::a = A();
 
 
 // Static inside of C.
-// CIR-BEFORE-LPP: cir.global external @_ZN1C1aE = ctor : !rec_A {
+// CIR-BEFORE-LPP: cir.global external @_ZN1C1aE = #cir.zero : !rec_A ctor {
 // CIR-BEFORE-LPP: } align(1) ast(#cir.var.decl.ast)
-// CIR-BEFORE-LPP: cir.global external @c = ctor : !rec_C {
+// CIR-BEFORE-LPP: cir.global external @c = #cir.zero : !rec_C ctor {
 // CIR-BEFORE-LPP: } align(1) ast(#cir.var.decl.ast)
 
-// CIR-BEFORE-LPP: cir.global external @a1 = ctor : !rec_A1 {
+// CIR-BEFORE-LPP: cir.global external @a1 = #cir.zero : !rec_A1 ctor {
 // CIR-BEFORE-LPP: } align(1) ast(#cir.var.decl.ast) init_priority(300)
-// CIR-BEFORE-LPP: cir.global external @a = ctor : !rec_A {
+// CIR-BEFORE-LPP: cir.global external @a = #cir.zero : !rec_A ctor {
 // CIR-BEFORE-LPP: } align(1) ast(#cir.var.decl.ast) init_priority(300)
-// CIR-BEFORE-LPP: cir.global external @b = ctor : !rec_B {
+// CIR-BEFORE-LPP: cir.global external @b = #cir.zero : !rec_B ctor {
 // CIR-BEFORE-LPP: } align(1) ast(#cir.var.decl.ast) init_priority(200)
 
 // CIR: cir.global_ctors = [#cir.global_ctor<"_GLOBAL__I_000200", 200>, 
#cir.global_ctor<"_GLOBAL__I_000300", 300>, 
#cir.global_ctor<"_GLOBAL__sub_I_[[FILENAME:.*]]", 65535>]

diff  --git a/clang/test/CIR/CodeGenCXX/typeid.cpp 
b/clang/test/CIR/CodeGenCXX/typeid.cpp
index a4608bf6a0205..ec1c0e4f81cd0 100644
--- a/clang/test/CIR/CodeGenCXX/typeid.cpp
+++ b/clang/test/CIR/CodeGenCXX/typeid.cpp
@@ -34,7 +34,7 @@ extern A &a;
 
 // CIR-AFTER: cir.global external @_ZN5Test14a_tiE = #cir.ptr<null> : 
!cir.ptr<!rec_std3A3Atype_info>
 
-// CIR-BEFORE: cir.global external @_ZN5Test14a_tiE = ctor : 
!cir.ptr<!rec_std3A3Atype_info> {
+// CIR-BEFORE: cir.global external @_ZN5Test14a_tiE = #cir.ptr<null> : 
!cir.ptr<!rec_std3A3Atype_info> ctor {
 // CIR-AFTER: cir.func{{.*}}@__cxx_global_var_init() {
 //
 // CIR-NEXT: %[[GET_GLOB_ATI:.*]] = cir.get_global @_ZN5Test14a_tiE : 
!cir.ptr<!cir.ptr<!rec_std3A3Atype_info>>

diff  --git a/clang/test/CIR/CodeGenCXX/zero_init_bases.cpp 
b/clang/test/CIR/CodeGenCXX/zero_init_bases.cpp
index 22508f0ed5c0c..03491faadfe1f 100644
--- a/clang/test/CIR/CodeGenCXX/zero_init_bases.cpp
+++ b/clang/test/CIR/CodeGenCXX/zero_init_bases.cpp
@@ -42,7 +42,7 @@ Inherits I2 {{1,2,3},{1.1, 2.2, 3.3}, 4, 5, 6};
 // OGCG: @I2 = global { i32, i32, i32, float, float, float, i32, i32, i32 } { 
i32 1, i32 2, i32 3, float {{.*}}, float {{.*}}, float {{.*}}, i32 4, i32 5, 
i32 6 }, align 4
 
 VirtualInherits VI;
-// CIR-BEFORE: cir.global external @VI = ctor : !rec_VirtualInherits {
+// CIR-BEFORE: cir.global external @VI = #cir.zero : !rec_VirtualInherits ctor 
{
 // CIR-BEFORE:   %[[GET_GLOB:.*]] = cir.get_global @VI : 
!cir.ptr<!rec_VirtualInherits>
 // CIR-BEFORE:   cir.call @_ZN15VirtualInheritsC1Ev(%[[GET_GLOB]]) nothrow : 
(!cir.ptr<!rec_VirtualInherits> {llvm.align = 8 : i64, llvm.dereferenceable = 
20 : i64, llvm.nonnull, llvm.noundef}) -> ()
 // CIR-BEFORE: } align(8) ast(#cir.var.decl.ast)

diff  --git a/clang/test/CIR/IR/global-init.cir 
b/clang/test/CIR/IR/global-init.cir
index 3e0387ed52594..f73362e3b9ee8 100644
--- a/clang/test/CIR/IR/global-init.cir
+++ b/clang/test/CIR/IR/global-init.cir
@@ -1,6 +1,7 @@
 // RUN: cir-opt %s --verify-roundtrip | FileCheck %s
 
 !u8i = !cir.int<u, 8>
+!s64i = !cir.int<s, 64>
 
 !rec_NeedsCtor = !cir.struct<"NeedsCtor" {pad !u8i}>
 !rec_NeedsDtor = !cir.struct<"NeedsDtor" {pad !u8i}>
@@ -8,11 +9,11 @@
 
 module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
   cir.func private @_ZN9NeedsCtorC1Ev(!cir.ptr<!rec_NeedsCtor>)
-  cir.global external @needsCtor = ctor : !rec_NeedsCtor {
+  cir.global external @needsCtor = #cir.zero : !rec_NeedsCtor ctor {
     %0 = cir.get_global @needsCtor : !cir.ptr<!rec_NeedsCtor>
     cir.call @_ZN9NeedsCtorC1Ev(%0) : (!cir.ptr<!rec_NeedsCtor>) -> ()
   }
-  // CHECK: cir.global external @needsCtor = ctor : !rec_NeedsCtor {
+  // CHECK: cir.global external @needsCtor = #cir.zero : !rec_NeedsCtor ctor {
   // CHECK:   %0 = cir.get_global @needsCtor : !cir.ptr<!rec_NeedsCtor>
   // CHECK:   cir.call @_ZN9NeedsCtorC1Ev(%0) : (!cir.ptr<!rec_NeedsCtor>) -> 
()
   // CHECK: }
@@ -29,7 +30,7 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
 
   cir.func private @_ZN13NeedsCtorDtorC1Ev(!cir.ptr<!rec_NeedsCtorDtor>)
   cir.func private @_ZN13NeedsCtorDtorD1Ev(!cir.ptr<!rec_NeedsCtorDtor>)
-  cir.global external dso_local @needsCtorDtor = ctor : !rec_NeedsCtorDtor {
+  cir.global external dso_local @needsCtorDtor = #cir.zero : 
!rec_NeedsCtorDtor ctor {
     %0 = cir.get_global @needsCtorDtor : !cir.ptr<!rec_NeedsCtorDtor>
     cir.call @_ZN13NeedsCtorDtorC1Ev(%0) : (!cir.ptr<!rec_NeedsCtorDtor>) -> ()
   } dtor {
@@ -38,11 +39,25 @@ module attributes {cir.triple = "x86_64-unknown-linux-gnu"} 
{
   }
   // CHECK: cir.func private 
@_ZN13NeedsCtorDtorC1Ev(!cir.ptr<!rec_NeedsCtorDtor>)
   // CHECK: cir.func private 
@_ZN13NeedsCtorDtorD1Ev(!cir.ptr<!rec_NeedsCtorDtor>)
-  // CHECK: cir.global external dso_local @needsCtorDtor = ctor : 
!rec_NeedsCtorDtor {
+  // CHECK: cir.global external dso_local @needsCtorDtor = #cir.zero : 
!rec_NeedsCtorDtor ctor {
   // CHECK:   %0 = cir.get_global @needsCtorDtor : !cir.ptr<!rec_NeedsCtorDtor>
   // CHECK:   cir.call @_ZN13NeedsCtorDtorC1Ev(%0) : 
(!cir.ptr<!rec_NeedsCtorDtor>) -> ()
   // CHECK: } dtor {
   // CHECK:   %0 = cir.get_global @needsCtorDtor : !cir.ptr<!rec_NeedsCtorDtor>
   // CHECK:   cir.call @_ZN13NeedsCtorDtorD1Ev(%0) : 
(!cir.ptr<!rec_NeedsCtorDtor>) -> ()
   // CHECK: }
+
+  // The initial value is kept alongside the ctor even when it is not zero,
+  // e.g. a null data member pointer after CXX ABI lowering.
+  cir.func private @_Z9getMemberv() -> !s64i
+  cir.global external @memberPtr = #cir.int<-1> : !s64i ctor {
+    %0 = cir.get_global @memberPtr : !cir.ptr<!s64i>
+    %1 = cir.call @_Z9getMemberv() : () -> !s64i
+    cir.store %1, %0 : !s64i, !cir.ptr<!s64i>
+  }
+  // CHECK: cir.global external @memberPtr = #cir.int<-1> : !s64i ctor {
+  // CHECK:   %0 = cir.get_global @memberPtr : !cir.ptr<!s64i>
+  // CHECK:   %1 = cir.call @_Z9getMemberv() : () -> !s64i
+  // CHECK:   cir.store %1, %0 : !s64i, !cir.ptr<!s64i>
+  // CHECK: }
 }

diff  --git a/clang/test/CIR/IR/invalid-global.cir 
b/clang/test/CIR/IR/invalid-global.cir
index dda5de7af9560..620cdbabb2c24 100644
--- a/clang/test/CIR/IR/invalid-global.cir
+++ b/clang/test/CIR/IR/invalid-global.cir
@@ -20,7 +20,7 @@ module {
 cir.global external @target = #cir.int<42> : !s32i
 
 // expected-error @below {{global alias shall not have an initializer or 
constructor/destructor regions}}
-cir.global external @bad_alias_with_ctor alias(@target) = ctor : !s32i {
+cir.global external @bad_alias_with_ctor alias(@target) = #cir.int<0> : !s32i 
ctor {
   cir.yield
 }
 
@@ -60,3 +60,18 @@ module {
 cir.global external comdat(1) @bad_comdat = #cir.int<42> : !s32i
 
 }
+
+// -----
+
+!s32i = !cir.int<s, 32>
+
+module {
+
+// The custom syntax always carries an initial value, so use the generic form.
+// expected-error @below {{cannot have a constructor region without an initial 
value}}
+"cir.global"() <{global_visibility = 0 : i32, linkage = 
#cir.linkage<external>, sym_name = "ctor_without_init", sym_type = !s32i}> ({
+  cir.yield
+}, {
+}) : () -> ()
+
+}

diff  --git a/clang/test/CIR/IR/invalid-static-local.cir 
b/clang/test/CIR/IR/invalid-static-local.cir
index 31a7b1178d92e..6c3a73cb7984e 100644
--- a/clang/test/CIR/IR/invalid-static-local.cir
+++ b/clang/test/CIR/IR/invalid-static-local.cir
@@ -67,7 +67,7 @@ module {
 cir.global "private" internal dynamic_init_guard<"_ZGVZ1fvE1y"> @_ZZ1fvE1y : 
!s32i
   dynamic_init_info<local = true, tls = none, is_inline = false, tsk = 
undeclared>
 
-cir.global "private" internal @_AnotherGlobal = ctor : !s32i {
+cir.global "private" internal @_AnotherGlobal = #cir.int<0> : !s32i ctor {
   // expected-error @below {{'cir.local_init' op expects ancestor op 
'cir.func'}}
   cir.local_init static_local @_ZZ1fvE1y ctor {
     cir.yield

diff  --git a/clang/unittests/CIR/ControlFlowTest.cpp 
b/clang/unittests/CIR/ControlFlowTest.cpp
index 47312d5e8843a..51b22c620c0a1 100644
--- a/clang/unittests/CIR/ControlFlowTest.cpp
+++ b/clang/unittests/CIR/ControlFlowTest.cpp
@@ -543,7 +543,7 @@ TEST_F(CIRControlFlowTest, CleanupScopeOp) {
 TEST_F(CIRControlFlowTest, GlobalOpWithCtorAndDtor) {
   OwningOpRef<ModuleOp> module = parse(R"CIR(
     !s32i = !cir.int<s, 32>
-    cir.global external @g = ctor : !s32i {
+    cir.global external @g = #cir.int<0> : !s32i ctor {
       cir.yield
     } dtor {
       cir.yield


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to