https://github.com/xakep8 updated https://github.com/llvm/llvm-project/pull/220643
>From 4d14dd537ccbaa88021da802529244abe0328cc2 Mon Sep 17 00:00:00 2001 From: Kunal Dubey <[email protected]> Date: Wed, 2 Sep 2026 21:42:30 +0530 Subject: [PATCH] [CIR] Support pointer-to-int global initializers 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. --- clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp | 23 +++++++++++-------- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 13 ++++------- clang/test/CIR/CodeGen/compound_literal.c | 6 +++++ .../test/CIR/CodeGen/global-address-to-int.c | 22 ++++++++++++++++++ 4 files changed, 47 insertions(+), 17 deletions(-) create mode 100644 clang/test/CIR/CodeGen/global-address-to-int.c diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp index 4bebe053f5768..4a9e412d06816 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp @@ -818,7 +818,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. @@ -839,14 +841,15 @@ mlir::Attribute ConstantLValueEmitter::tryEmit() { // 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 {}; } @@ -881,9 +884,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 differ 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 6f7509c363fd3..3904e16c18578 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -2478,14 +2478,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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
