[clang] b623a0c - [CIR] Support pointer-to-int global initializers (#220643)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 15 09:57:07 PDT 2026
Author: Kunal Dubey
Date: 2026-09-15T09:57:02-07:00
New Revision: b623a0c6d49f2c8e1031216ead5641c3bf57f1d1
URL: https://github.com/llvm/llvm-project/commit/b623a0c6d49f2c8e1031216ead5641c3bf57f1d1
DIFF: https://github.com/llvm/llvm-project/commit/b623a0c6d49f2c8e1031216ead5641c3bf57f1d1.diff
LOG: [CIR] Support pointer-to-int global initializers (#220643)
This allows CIR to emit global initializers where a constant address is
cast to an integer.
This fixes compound literals like `unsigned long addr = (unsigned
long)(int[]){1, 2, 3}` and also handles global variable, array element
and function addresses cast to integers.
Fixes #216618
Added:
clang/test/CIR/CodeGen/global-address-to-int.c
Modified:
clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
clang/test/CIR/CodeGen/compound_literal.c
Removed:
################################################################################
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index d8a3aa9c1c558..46aabba5b567a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -839,7 +839,9 @@ mlir::Attribute ConstantLValueEmitter::tryEmit() {
// non-zero null pointer and addrspace casts that aren't trivially
// represented in LLVM IR.
mlir::Type destTy = cgm.getTypes().convertTypeForMem(destType);
- assert(mlir::isa<cir::PointerType>(destTy));
+ assert((mlir::isa<cir::PointerType>(destTy) ||
+ mlir::isa<cir::IntType>(destTy)) &&
+ "constant lvalue destination must be pointer or integer");
// If there's no base at all, this is a null or absolute pointer,
// possibly cast back to an integer type.
@@ -858,16 +860,25 @@ mlir::Attribute ConstantLValueEmitter::tryEmit() {
if (!result.hasOffsetApplied)
value = applyOffset(result).value;
+ // CIR does not yet support signing constant lvalue initializers with pointer
+ // authentication. Classic CodeGen signs the offset-adjusted pointer here
+ // before the final pointer cast or ptrtoint conversion.
+ if (PointerAuthQualifier pointerAuth = destType.getPointerAuth()) {
+ cgm.errorNYI("ConstantLValueEmitter: pointer authentication");
+ return {};
+ }
+
// Convert to the appropriate type; this could be an lvalue for
// an integer. FIXME: performAddrSpaceCast
- if (mlir::isa<cir::PointerType>(destTy)) {
- if (auto attr = mlir::dyn_cast<mlir::Attribute>(value))
+ if (auto attr = mlir::dyn_cast<mlir::Attribute>(value)) {
+ if (auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(attr))
+ return cir::GlobalViewAttr::get(destTy, gv.getSymbol(), gv.getIndices());
+
+ if (mlir::isa<cir::PointerType>(destTy))
return attr;
- cgm.errorNYI("ConstantLValueEmitter: non-attribute pointer");
- return {};
}
- cgm.errorNYI("ConstantLValueEmitter: other?");
+ cgm.errorNYI("ConstantLValueEmitter: non-attribute pointer or integer");
return {};
}
@@ -902,9 +913,11 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
// fop.getFunctionType(), so initializers stay valid when a no-prototype
// FuncOp is later replaced by a prototyped definition with the same
// symbol. CIR allows the view type to
diff er from the symbol's type.
- mlir::Type ptrTy = cgm.getTypes().convertTypeForMem(destType);
- assert(mlir::isa<cir::PointerType>(ptrTy) &&
- "function address in constant must be a pointer");
+ mlir::Type destTy = cgm.getTypes().convertTypeForMem(destType);
+ cir::PointerType ptrTy =
+ mlir::isa<cir::PointerType>(destTy)
+ ? mlir::cast<cir::PointerType>(destTy)
+ : cir::PointerType::get(fop.getFunctionType());
return cir::GlobalViewAttr::get(
ptrTy,
mlir::FlatSymbolRefAttr::get(mlirContext, fop.getSymNameAttr()));
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index f4ada8eb04c1c..24ee700e87ece 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -2484,14 +2484,11 @@ mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
value);
} else if (mlir::isa<cir::IntType>(op.getType())) {
// Lower GlobalViewAttr to llvm.mlir.addressof + llvm.mlir.ptrtoint
- if (auto ga = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
- // We can have a global view with an integer type in the case of method
- // pointers, but the lowering of those doesn't go through this path.
- // They are handled in the visitCirAttr. This is left as an error until
- // we have a test case that reaches it.
- assert(!cir::MissingFeatures::globalViewIntLowering());
- op.emitError() << "global view with integer type";
- return mlir::failure();
+ if (auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
+ auto newOp = lowerCirAttrAsValue(op, gv, rewriter, symbolTables,
+ getTypeConverter());
+ rewriter.replaceOp(op, newOp);
+ return mlir::success();
}
attr = rewriter.getIntegerAttr(
diff --git a/clang/test/CIR/CodeGen/compound_literal.c b/clang/test/CIR/CodeGen/compound_literal.c
index d3d45f5af8e27..7d38e5b2cd6d0 100644
--- a/clang/test/CIR/CodeGen/compound_literal.c
+++ b/clang/test/CIR/CodeGen/compound_literal.c
@@ -65,3 +65,9 @@ int **p9 = (int*[]){&x, &x};
// LLVM: @x = global i32 0, align 4
// LLVM: @.compoundliteral.9 = internal global [2 x ptr] [ptr @x, ptr @x], align 8
// LLVM: @p9 = global ptr @.compoundliteral.9, align 8
+
+unsigned long addr = (unsigned long)(int[]){1, 2, 3};
+// CIR: cir.global "private" internal @".compoundliteral.10" = #cir.const_array<[#cir.int<1> : !s32i, #cir.int<2> : !s32i, #cir.int<3> : !s32i]> : !cir.array<!s32i x 3> {alignment = 4 : i64}
+// CIR: cir.global external @addr = #cir.global_view<@".compoundliteral.10"> : !u64i {alignment = 8 : i64}
+// LLVM: @.compoundliteral.10 = internal global [3 x i32] [i32 1, i32 2, i32 3], align 4
+// LLVM: @addr = global i64 ptrtoint (ptr @.compoundliteral.10 to i64), align 8
diff --git a/clang/test/CIR/CodeGen/global-address-to-int.c b/clang/test/CIR/CodeGen/global-address-to-int.c
new file mode 100644
index 0000000000000..3b24941d4c9c4
--- /dev/null
+++ b/clang/test/CIR/CodeGen/global-address-to-int.c
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM
+
+int x;
+int arr[4];
+int f(void);
+
+unsigned long gx = (unsigned long)&x;
+// CIR: cir.global external @gx = #cir.global_view<@x> : !u64i
+// LLVM: @gx = global i64 ptrtoint (ptr @x to i64), align 8
+
+unsigned long garr2 = (unsigned long)&arr[2];
+// CIR: cir.global external @garr2 = #cir.global_view<@arr, [2 : i32]> : !u64i
+// LLVM: @garr2 = global i64 ptrtoint (ptr getelementptr {{.*}}(i8, ptr @arr, i64 8) to i64), align 8
+
+unsigned long gf = (unsigned long)&f;
+// CIR: cir.global external @gf = #cir.global_view<@f> : !u64i
+// LLVM: @gf = global i64 ptrtoint (ptr @f to i64), align 8
More information about the cfe-commits
mailing list