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(destTy)); + assert((mlir::isa(destTy) || + mlir::isa(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(destTy)) { - if (auto attr = mlir::dyn_cast(value)) + if (auto attr = mlir::dyn_cast(value)) { + if (auto gv = mlir::dyn_cast(attr)) + return cir::GlobalViewAttr::get(destTy, gv.getSymbol(), gv.getIndices()); + + if (mlir::isa(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(ptrTy) && - "function address in constant must be a pointer"); + mlir::Type destTy = cgm.getTypes().convertTypeForMem(destType); + cir::PointerType ptrTy = + mlir::isa(destTy) + ? mlir::cast(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(op.getType())) { // Lower GlobalViewAttr to llvm.mlir.addressof + llvm.mlir.ptrtoint - if (auto ga = mlir::dyn_cast(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(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 {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