[clang] [CIR] Lower constant NTTP objects (PR #194496)
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 27 16:56:36 PDT 2026
https://github.com/erichkeane created https://github.com/llvm/llvm-project/pull/194496
Like my previous patch, this just stores an NTTP object as a global (using the same code, with 1 level of indrection slipped off), and initializes it as a const. This patch also fleshes out the CIRGenExprConstant.cpp area, leaving just 2 'NYI's in the area, 1 of which is the MSGuidAttr again.
>From 57be7430d9e405db5dd80b8976e86603a8815bb3 Mon Sep 17 00:00:00 2001
From: erichkeane <ekeane at nvidia.com>
Date: Mon, 27 Apr 2026 16:47:50 -0700
Subject: [PATCH] [CIR] Lower constant NTTP objects
Like my previous patch, this just stores an NTTP object as a global
(using the same code, with 1 level of indrection slipped off), and
initializes it as a const. This patch also fleshes out the
CIRGenExprConstant.cpp area, leaving just 2 'NYI's in the area, 1 of
which is the MSGuidAttr again.
---
clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 3 +-
clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp | 16 ++++---
clang/lib/CIR/CodeGen/CIRGenModule.cpp | 6 +--
clang/lib/CIR/CodeGen/CIRGenModule.h | 2 +-
.../test/CIR/CodeGen/temp-param-obj-decl.cpp | 43 +++++++++++++++++--
5 files changed, 55 insertions(+), 15 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index dc1d5185189bf..26ced070de8ba 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -1062,7 +1062,8 @@ LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr *e) {
if (const auto *tpo = dyn_cast<TemplateParamObjectDecl>(nd)) {
CharUnits alignment = cgm.getNaturalTypeAlignment(tpo->getType());
- cir::GetGlobalOp atpo = cgm.getAddrOfTemplateParamObject(tpo);
+ cir::GetGlobalOp atpo =
+ builder.createGetGlobal(cgm.getAddrOfTemplateParamObject(tpo));
assert(!MissingFeatures::addressSpace() &&
"Do an address space conversion if necessary");
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index a8b24fb686088..49920a2741aa2 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -1411,12 +1411,16 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
}
}
- // Classic codegen handles MSGuidDecl,UnnamedGlobalConstantDecl, and
- // TemplateParamObjectDecl, but it can also fall through from VarDecl,
- // in which case it silently returns nullptr. For now, let's emit an
- // error to see what cases we need to handle.
- cgm.errorNYI(d->getSourceRange(),
- "ConstantLValueEmitter: unhandled value decl");
+ if (isa<MSGuidDecl>(d))
+ cgm.errorNYI(d->getSourceRange(), "ConstantLValueEmitter: MSGuidDecl");
+
+ if (const auto *gcd = dyn_cast<UnnamedGlobalConstantDecl>(d))
+ cgm.errorNYI(d->getSourceRange(),
+ "ConstantLValueEmitter: Unnamed global constant");
+
+ if (const auto *tpo = dyn_cast<TemplateParamObjectDecl>(d))
+ cgm.getBuilder().getGlobalViewAttr(cgm.getAddrOfTemplateParamObject(tpo));
+
return {};
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 1f35f55669ff7..7d719600a6025 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -3570,14 +3570,14 @@ CIRGenModule::getAddrOfGlobalTemporary(const MaterializeTemporaryExpr *mte,
return cv;
}
-cir::GetGlobalOp
+cir::GlobalOp
CIRGenModule::getAddrOfTemplateParamObject(const TemplateParamObjectDecl *tpo) {
StringRef name = getMangledName(tpo);
CharUnits alignment = getNaturalTypeAlignment(tpo->getType());
if (auto globalOp =
mlir::dyn_cast_or_null<cir::GlobalOp>(getGlobalValue(name)))
- return builder.createGetGlobal(globalOp);
+ return globalOp;
ConstantEmitter emitter(*this);
assert(!cir::MissingFeatures::addressSpace() &&
@@ -3610,7 +3610,7 @@ CIRGenModule::getAddrOfTemplateParamObject(const TemplateParamObjectDecl *tpo) {
insertGlobalSymbol(globalOp);
- return builder.createGetGlobal(globalOp);
+ return globalOp;
}
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h
index 299346dc2de3f..b2c630ca7defd 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -358,7 +358,7 @@ class CIRGenModule : public CIRGenTypeCache {
cir::GlobalViewAttr getAddrOfGlobalVarAttr(const VarDecl *d);
/// Get the GlobalOp of a template parameter object.
- cir::GetGlobalOp
+ cir::GlobalOp
getAddrOfTemplateParamObject(const TemplateParamObjectDecl *tpo);
CharUnits computeNonVirtualBaseClassOffset(
diff --git a/clang/test/CIR/CodeGen/temp-param-obj-decl.cpp b/clang/test/CIR/CodeGen/temp-param-obj-decl.cpp
index 8437af739268a..f815cf6ee99da 100644
--- a/clang/test/CIR/CodeGen/temp-param-obj-decl.cpp
+++ b/clang/test/CIR/CodeGen/temp-param-obj-decl.cpp
@@ -7,11 +7,46 @@
struct HasMem { int x;};
-// CIR: cir.global "private" constant linkonce_odr comdat @_ZTAXtl6HasMemLi1EEE = #cir.const_record<{#cir.int<1> : !s32i}> : !rec_HasMem
-// CIR: cir.global "private" constant linkonce_odr comdat @_ZTAXtl6HasMemLi2EEE = #cir.const_record<{#cir.int<2> : !s32i}> : !rec_HasMem
+// CIR-DAG: cir.global "private" constant linkonce_odr comdat @_ZTAXtl6HasMemLi3EEE = #cir.const_record<{#cir.int<3> : !s32i}> : !rec_HasMem
+
+// LLVM-BOTH-DAG: @_ZTAXtl6HasMemLi1EEE = linkonce_odr constant %struct.HasMem { i32 1 }, comdat
+// LLVM-BOTH-DAG: @_ZTAXtl6HasMemLi2EEE = linkonce_odr constant %struct.HasMem { i32 2 }, comdat
+// LLVM-BOTH-DAG: @_ZTAXtl6HasMemLi3EEE = linkonce_odr constant %struct.HasMem { i32 3 }, comdat
+
+// LLVM-DAG: @ptr = global ptr null
+// OGCG-DAG: @ptr = global ptr @_ZTAXtl6HasMemLi3EEE
+
+template <HasMem m>
+constexpr const HasMem *get_ptr() { return &m; }
+
+const auto *ptr = get_ptr<HasMem{3}>();
+
+// CIR-LABEL: cir.func {{.*}}@_Z7get_ptrIXtl6HasMemLi3EEEEPKS0_v()
+// CIR: %[[RET_ALLOCA:.*]] = cir.alloca !cir.ptr<!rec_HasMem>, !cir.ptr<!cir.ptr<!rec_HasMem>>
+// CIR: %[[GET_GLOB:.*]] = cir.get_global @_ZTAXtl6HasMemLi3EEE : !cir.ptr<!rec_HasMem>
+// CIR: cir.store %[[GET_GLOB]], %[[RET_ALLOCA]]
+// CIR: %[[RET_LOAD:.*]] = cir.load %[[RET_ALLOCA]] : !cir.ptr<!cir.ptr<!rec_HasMem>>, !cir.ptr<!rec_HasMem>
+// CIR: cir.return %[[RET_LOAD]] : !cir.ptr<!rec_HasMem>
+//
+// LLVM-LABEL: define {{.*}}@_Z7get_ptrIXtl6HasMemLi3EEEEPKS0_v()
+// LLVM: %[[RET_ALLOCA:.*]] = alloca ptr
+// LLVM: store ptr @_ZTAXtl6HasMemLi3EEE, ptr %[[RET_ALLOCA]]
+// LLVM: %[[RET_LOAD:.*]] = load ptr, ptr %[[RET_ALLOCA]]
+// LLVM: ret ptr %[[RET_LOAD]]
+//
+// CIR-DAG: cir.global external @ptr = #cir.ptr<null> : !cir.ptr<!rec_HasMem>
+// CIR-LABEL: cir.func {{.*}}@__cxx_global_var_init
+// CIR: %[[GET_GLOB:.*]] = cir.get_global @ptr : !cir.ptr<!cir.ptr<!rec_HasMem>>
+// CIR: %[[CALL:.*]] = cir.call @_Z7get_ptrIXtl6HasMemLi3EEEEPKS0_v() : ()
+// CIR: cir.store {{.*}}%[[CALL]], %[[GET_GLOB]] : !cir.ptr<!rec_HasMem>, !cir.ptr<!cir.ptr<!rec_HasMem>>
+//
+// LLVM-LABEL: define {{.*}}@__cxx_global_var_init
+// LLVM: %[[CALL:.*]] = call{{.*}} @_Z7get_ptrIXtl6HasMemLi3EEEEPKS0_v()
+// LLVM: store ptr %[[CALL]], ptr @ptr
+
+// CIR-DAG: cir.global "private" constant linkonce_odr comdat @_ZTAXtl6HasMemLi1EEE = #cir.const_record<{#cir.int<1> : !s32i}> : !rec_HasMem
+// CIR-DAG: cir.global "private" constant linkonce_odr comdat @_ZTAXtl6HasMemLi2EEE = #cir.const_record<{#cir.int<2> : !s32i}> : !rec_HasMem
-// LLVM-BOTH: @_ZTAXtl6HasMemLi1EEE = linkonce_odr constant %struct.HasMem { i32 1 }, comdat
-// LLVM-BOTH: @_ZTAXtl6HasMemLi2EEE = linkonce_odr constant %struct.HasMem { i32 2 }, comdat
template<HasMem m>
int get_x() { return m.x; }
// CIR-LABEL: cir.func {{.*}}@_Z5get_xIXtl6HasMemLi1EEEEiv()
More information about the cfe-commits
mailing list