diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index 3e12a9307807..298d06805c54 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -622,6 +622,30 @@ def GlobalViewAttr : CIR_Attr<"GlobalView", "global_view", [TypedAttrInterface]> cir.global external @elt_ptr = #cir.global_view<@rgb, [1]> : !cir.ptr cir.global external @table_of_ptrs = #cir.const_array<[#cir.global_view<@rgb, [1]> : !cir.ptr] : !cir.array x 1>> ``` + + Note, that unlike LLVM IR's gep instruction, CIR doesn't add the leading zero index + when it's known to be constant zero, e.g. for pointers, i.e. we use indexes exactly + to access sub elements or for the offset. The leading zero index is added later in + the lowering. + + Example: + ``` + struct A { + int a; + }; + + struct B: virtual A { + int b; + }; + ``` + VTT for B: + ``` + cir.global linkonce_odr @_ZTT1B = #cir.const_array<[#cir.global_view<@_ZTV1B, [0 : i32, 3 : i32]> : !cir.ptr]> : !cir.array x 1> + ``` + The same for LLVM IR after CIR: + ``` + @_ZTT1B = linkonce_odr global [1 x ptr] [ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV1B, i32 0, i32 0, i32 3)], align 8 + ``` }]; let parameters = (ins AttributeSelfTypeParameter<"">:$type, diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp b/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp index a50cefe34c79..905ca67aafd5 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp @@ -63,3 +63,74 @@ cir::ConstantOp CIRGenBuilderTy::getConstInt(mlir::Location loc, mlir::Type t, assert(intTy && "expected cir::IntType"); return create(loc, intTy, cir::IntAttr::get(t, C)); } + +void CIRGenBuilderTy::computeGlobalViewIndicesFromFlatOffset( + int64_t Offset, mlir::Type Ty, cir::CIRDataLayout Layout, + llvm::SmallVectorImpl &Indices) { + if (!Offset) + return; + + mlir::Type SubType; + + auto getIndexAndNewOffset = + [](int64_t Offset, int64_t EltSize) -> std::pair { + int64_t DivRet = Offset / EltSize; + if (DivRet < 0) + DivRet -= 1; // make sure offset is positive + int64_t ModRet = Offset - (DivRet * EltSize); + return {DivRet, ModRet}; + }; + + if (auto ArrayTy = mlir::dyn_cast(Ty)) { + int64_t EltSize = Layout.getTypeAllocSize(ArrayTy.getEltType()); + SubType = ArrayTy.getEltType(); + const auto [Index, NewOffset] = getIndexAndNewOffset(Offset, EltSize); + Indices.push_back(Index); + Offset = NewOffset; + } else if (auto StructTy = mlir::dyn_cast(Ty)) { + auto Elts = StructTy.getMembers(); + int64_t Pos = 0; + for (size_t I = 0; I < Elts.size(); ++I) { + int64_t EltSize = + (int64_t)Layout.getTypeAllocSize(Elts[I]).getFixedValue(); + unsigned AlignMask = Layout.getABITypeAlign(Elts[I]).value() - 1; + if (StructTy.getPacked()) + AlignMask = 0; + Pos = (Pos + AlignMask) & ~AlignMask; + assert(Offset >= 0); + if (Offset < Pos + EltSize) { + Indices.push_back(I); + SubType = Elts[I]; + Offset -= Pos; + break; + } + Pos += EltSize; + } + } else { + llvm_unreachable("unexpected type"); + } + + assert(SubType); + computeGlobalViewIndicesFromFlatOffset(Offset, SubType, Layout, Indices); +} + +uint64_t CIRGenBuilderTy::computeOffsetFromGlobalViewIndices( + const cir::CIRDataLayout &layout, mlir::Type typ, + llvm::ArrayRef indexes) { + + uint64_t offset = 0; + for (auto idx : indexes) { + if (auto sTy = dyn_cast(typ)) { + offset += sTy.getElementOffset(layout.layout, idx); + assert(idx < sTy.getMembers().size()); + typ = sTy.getMembers()[idx]; + } else if (auto arTy = dyn_cast(typ)) { + typ = arTy.getEltType(); + offset += layout.getTypeAllocSize(typ) * idx; + } else { + llvm_unreachable("NYI"); + } + } + + return offset; +} \ No newline at end of file diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h index f41dcf871c6b..3a8a3955d7f2 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h @@ -146,6 +146,20 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { return cir::GlobalViewAttr::get(type, symbol, indices); } + cir::GlobalViewAttr getGlobalViewAttr(cir::PointerType type, + cir::GlobalOp globalOp, + llvm::ArrayRef indices) { + llvm::SmallVector attrs; + for (auto ind : indices) { + auto a = + mlir::IntegerAttr::get(mlir::IntegerType::get(getContext(), 64), ind); + attrs.push_back(a); + } + + mlir::ArrayAttr arAttr = mlir::ArrayAttr::get(getContext(), attrs); + return getGlobalViewAttr(type, globalOp, arAttr); + } + mlir::Attribute getString(llvm::StringRef str, mlir::Type eltTy, unsigned size = 0) { unsigned finalSize = size ? size : str.size(); @@ -941,51 +955,12 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { // yet, return them. void computeGlobalViewIndicesFromFlatOffset( int64_t Offset, mlir::Type Ty, cir::CIRDataLayout Layout, - llvm::SmallVectorImpl &Indices) { - if (!Offset) - return; - - mlir::Type SubType; - - auto getIndexAndNewOffset = - [](int64_t Offset, int64_t EltSize) -> std::pair { - int64_t DivRet = Offset / EltSize; - if (DivRet < 0) - DivRet -= 1; // make sure offset is positive - int64_t ModRet = Offset - (DivRet * EltSize); - return {DivRet, ModRet}; - }; - - if (auto ArrayTy = mlir::dyn_cast(Ty)) { - int64_t EltSize = Layout.getTypeAllocSize(ArrayTy.getEltType()); - SubType = ArrayTy.getEltType(); - auto const [Index, NewOffset] = getIndexAndNewOffset(Offset, EltSize); - Indices.push_back(Index); - Offset = NewOffset; - } else if (auto StructTy = mlir::dyn_cast(Ty)) { - auto Elts = StructTy.getMembers(); - int64_t Pos = 0; - for (size_t I = 0; I < Elts.size(); ++I) { - int64_t EltSize = - (int64_t)Layout.getTypeAllocSize(Elts[I]).getFixedValue(); - unsigned AlignMask = Layout.getABITypeAlign(Elts[I]).value() - 1; - Pos = (Pos + AlignMask) & ~AlignMask; - assert(Offset >= 0); - if (Offset < Pos + EltSize) { - Indices.push_back(I); - SubType = Elts[I]; - Offset -= Pos; - break; - } - Pos += EltSize; - } - } else { - llvm_unreachable("unexpected type"); - } + llvm::SmallVectorImpl &Indices); - assert(SubType); - computeGlobalViewIndicesFromFlatOffset(Offset, SubType, Layout, Indices); - } + // Convert high-level indices (e.g. from GlobalViewAttr) to byte offset + uint64_t computeOffsetFromGlobalViewIndices(const cir::CIRDataLayout &layout, + mlir::Type t, + llvm::ArrayRef indexes); cir::StackSaveOp createStackSave(mlir::Location loc, mlir::Type ty) { return create(loc, ty); diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp index c2955d7ad3fa..f0ee6333c53a 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp @@ -756,7 +756,6 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD, .getAddressPoint(BaseSubobject(CD, Offset)); assert(!cir::MissingFeatures::ptrAuth()); mlir::ArrayAttr indices = builder.getArrayAttr({ - builder.getI32IntegerAttr(0), builder.getI32IntegerAttr(addressPoint.VTableIndex), builder.getI32IntegerAttr(addressPoint.AddressPointIndex), }); diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index c93a145f35ce..521c41aa4504 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -9,9 +9,7 @@ // This is the internal per-translation-unit state used for CIR translation. // //===----------------------------------------------------------------------===// - #include "CIRGenModule.h" - #include "CIRGenCXXABI.h" #include "CIRGenCstEmitter.h" #include "CIRGenFunction.h" @@ -797,9 +795,75 @@ void CIRGenModule::setNonAliasAttributes(GlobalDecl GD, mlir::Operation *GO) { assert(!cir::MissingFeatures::setTargetAttributes()); } +static llvm::SmallVector indexesOfArrayAttr(mlir::ArrayAttr indexes) { + llvm::SmallVector inds; + + for (mlir::Attribute i : indexes) { + auto ind = dyn_cast(i); + assert(ind && "expect MLIR integer attribute"); + inds.push_back(ind.getValue().getSExtValue()); + } + + return inds; +} + +static bool isViewOnGlobal(GlobalOp glob, GlobalViewAttr view) { + return view.getSymbol().getValue() == glob.getSymName(); +} + +static GlobalViewAttr createNewGlobalView(CIRGenModule &CGM, GlobalOp newGlob, + GlobalViewAttr attr, + mlir::Type oldTy) { + if (!attr.getIndices() || !isViewOnGlobal(newGlob, attr)) + return attr; + + llvm::SmallVector oldInds = indexesOfArrayAttr(attr.getIndices()); + llvm::SmallVector newInds; + CIRGenBuilderTy &bld = CGM.getBuilder(); + const CIRDataLayout &layout = CGM.getDataLayout(); + mlir::MLIRContext *ctxt = bld.getContext(); + auto newTy = newGlob.getSymType(); + + auto offset = bld.computeOffsetFromGlobalViewIndices(layout, oldTy, oldInds); + bld.computeGlobalViewIndicesFromFlatOffset(offset, newTy, layout, newInds); + cir::PointerType newPtrTy; + + if (isa(oldTy)) + newPtrTy = cir::PointerType::get(ctxt, newTy); + else if (cir::ArrayType oldArTy = dyn_cast(oldTy)) + newPtrTy = dyn_cast(attr.getType()); + + if (newPtrTy) + return bld.getGlobalViewAttr(newPtrTy, newGlob, newInds); + + llvm_unreachable("NYI"); +} + +static mlir::Attribute getNewInitValue(CIRGenModule &CGM, GlobalOp newGlob, + mlir::Type oldTy, GlobalOp user, + mlir::Attribute oldInit) { + if (auto oldView = mlir::dyn_cast(oldInit)) { + return createNewGlobalView(CGM, newGlob, oldView, oldTy); + } else if (auto oldArray = mlir::dyn_cast(oldInit)) { + llvm::SmallVector newArray; + auto eltsAttr = dyn_cast(oldArray.getElts()); + for (auto elt : eltsAttr) { + if (auto view = dyn_cast(elt)) + newArray.push_back(createNewGlobalView(CGM, newGlob, view, oldTy)); + else if (auto view = dyn_cast(elt)) + newArray.push_back(getNewInitValue(CGM, newGlob, oldTy, user, elt)); + } + + auto &builder = CGM.getBuilder(); + mlir::Attribute ar = mlir::ArrayAttr::get(builder.getContext(), newArray); + return builder.getConstArray(ar, cast(oldArray.getType())); + } else { + llvm_unreachable("NYI"); + } +} + void CIRGenModule::replaceGlobal(cir::GlobalOp Old, cir::GlobalOp New) { assert(Old.getSymName() == New.getSymName() && "symbol names must match"); - // If the types does not match, update all references to Old to the new type. auto OldTy = Old.getSymType(); auto NewTy = New.getSymType(); @@ -809,6 +873,7 @@ void CIRGenModule::replaceGlobal(cir::GlobalOp Old, cir::GlobalOp New) { if (oldAS != newAS) { llvm_unreachable("NYI"); } + if (OldTy != NewTy) { auto OldSymUses = Old.getSymbolUses(theModule.getOperation()); if (OldSymUses.has_value()) { @@ -823,11 +888,16 @@ void CIRGenModule::replaceGlobal(cir::GlobalOp Old, cir::GlobalOp New) { cir::PointerType::get(&getMLIRContext(), NewTy)); mlir::OpBuilder::InsertionGuard guard(builder); - builder.setInsertionPointAfter(UserOp); + builder.setInsertionPointAfter(GGO); mlir::Type ptrTy = builder.getPointerTo(OldTy); mlir::Value cast = builder.createBitcast(GGO->getLoc(), UseOpResultValue, ptrTy); UseOpResultValue.replaceAllUsesExcept(cast, cast.getDefiningOp()); + } else if (auto glob = dyn_cast(UserOp)) { + if (auto init = glob.getInitialValue()) { + auto nw = getNewInitValue(*this, New, OldTy, glob, init.value()); + glob.setInitialValueAttr(nw); + } } } } @@ -1083,7 +1153,8 @@ CIRGenModule::getAddrOfGlobalVarAttr(const VarDecl *D, mlir::Type Ty, Ty = getTypes().convertTypeForMem(ASTTy); auto globalOp = getOrCreateCIRGlobal(D, Ty, IsForDefinition); - return builder.getGlobalViewAttr(builder.getPointerTo(Ty), globalOp); + auto ptrTy = builder.getPointerTo(globalOp.getSymType()); + return builder.getGlobalViewAttr(ptrTy, globalOp); } mlir::Operation *CIRGenModule::getWeakRefReference(const ValueDecl *VD) { diff --git a/clang/lib/CIR/CodeGen/CIRGenVTables.cpp b/clang/lib/CIR/CodeGen/CIRGenVTables.cpp index 2fa51b534da4..81f7971ac787 100644 --- a/clang/lib/CIR/CodeGen/CIRGenVTables.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenVTables.cpp @@ -622,8 +622,7 @@ void CIRGenVTables::emitVTTDefinition(cir::GlobalOp VTT, "Did not find ctor vtable address point!"); } - mlir::Attribute Idxs[3] = { - CGM.getBuilder().getI32IntegerAttr(0), + mlir::Attribute Idxs[2] = { CGM.getBuilder().getI32IntegerAttr(AddressPoint.VTableIndex), CGM.getBuilder().getI32IntegerAttr(AddressPoint.AddressPointIndex), }; diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 05679d9d86dd..0331122f35d2 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -680,12 +680,8 @@ lowerCirAttrAsValue(mlir::Operation *parentOp, cir::GlobalViewAttr globalAttr, if (globalAttr.getIndices()) { llvm::SmallVector indices; - if (auto stTy = dyn_cast(sourceType)) { - if (stTy.isIdentified()) - indices.push_back(0); - } else if (isa(sourceType)) { + if (isa(sourceType)) indices.push_back(0); - } for (auto idx : globalAttr.getIndices()) { auto intAttr = dyn_cast(idx); diff --git a/clang/test/CIR/CodeGen/globals-ref-globals.c b/clang/test/CIR/CodeGen/globals-ref-globals.c new file mode 100644 index 000000000000..8343153e3e8e --- /dev/null +++ b/clang/test/CIR/CodeGen/globals-ref-globals.c @@ -0,0 +1,126 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM + +typedef struct { + int f0 : 24; + int f1; + int f2; +} S; + +static S g1 = {2799, 9, 123}; +static int *g2[4] = {&g1.f1, &g1.f1, &g1.f1, &g1.f1}; +static int **g3 = &g2[1]; +static int ***g4 = &g3; +static int ****g5 = &g4; + +static S g6[2] = {{2799, 9, 123}, {2799, 9, 123}}; +static int *g7[2] = {&g6[0].f2, &g6[1].f2}; +static int **g8 = &g7[1]; + +// CHECK-DAG: !ty_anon_struct = !cir.struct +// CHECK-DAG: !ty_anon_struct1 = !cir.struct, !s32i}> +// CHECK-DAG: !ty_anon_struct2 = !cir.struct +// CHECK-DAG: !ty_anon_struct3 = !cir.struct, !s32i, !s8i, !cir.array}> + +// CHECK-DAG: g1 = #cir.const_struct<{#cir.int<239> : !u8i, #cir.int<10> : !u8i, #cir.int<0> : !u8i, #cir.zero : !u8i, #cir.int<9> : !s32i, #cir.int<123> : !s32i}> : !ty_anon_struct +// CHECK-DAG: g2 = #cir.const_array<[#cir.global_view<@g1, [4]> : !cir.ptr, #cir.global_view<@g1, [4]> : !cir.ptr, #cir.global_view<@g1, [4]> : !cir.ptr, #cir.global_view<@g1, [4]> : !cir.ptr]> : !cir.array x 4> +// CHECK-DAG: g3 = #cir.global_view<@g2, [1 : i32]> : !cir.ptr> +// CHECK-DAG: g4 = #cir.global_view<@g3> : !cir.ptr>> +// CHECK-DAG: g5 = #cir.global_view<@g4> : !cir.ptr>>> +// CHECK-DAG: g6 = #cir.const_array<[#cir.const_struct<{#cir.int<239> : !u8i, #cir.int<10> : !u8i, #cir.int<0> : !u8i, #cir.zero : !u8i, #cir.int<9> : !s32i, #cir.int<123> : !s32i}> : !ty_anon_struct, #cir.const_struct<{#cir.int<239> : !u8i, #cir.int<10> : !u8i, #cir.int<0> : !u8i, #cir.zero : !u8i, #cir.int<9> : !s32i, #cir.int<123> : !s32i}> : !ty_anon_struct]> : !cir.array +// CHECK-DAG: g7 = #cir.const_array<[#cir.global_view<@g6, [0, 5]> : !cir.ptr, #cir.global_view<@g6, [1, 5]> : !cir.ptr]> : !cir.array x 2> +// CHECK-DAG: g8 = #cir.global_view<@g7, [1 : i32]> : !cir.ptr> + +// LLVM-DAG: @g1 = internal global { i8, i8, i8, i8, i32, i32 } { i8 -17, i8 10, i8 0, i8 0, i32 9, i32 123 }, align 4 +// LLVM-DAG: @g2 = internal global [4 x ptr] [ptr getelementptr inbounds ({ i8, i8, i8, i8, i32, i32 }, ptr @g1, i32 0, i32 4), ptr getelementptr inbounds ({ i8, i8, i8, i8, i32, i32 }, ptr @g1, i32 0, i32 4), ptr getelementptr inbounds ({ i8, i8, i8, i8, i32, i32 }, ptr @g1, i32 0, i32 4), ptr getelementptr inbounds ({ i8, i8, i8, i8, i32, i32 }, ptr @g1, i32 0, i32 4)], align 16 +// LLVM-DAG: @g3 = internal global ptr getelementptr inbounds ([4 x ptr], ptr @g2, i32 0, i32 1), align 8 +// LLVM-DAG: @g4 = internal global ptr @g3, align 8 +// LLVM-DAG: @g5 = internal global ptr @g4, align 8 +// LLVM-DAG: @g6 = internal global [2 x { i8, i8, i8, i8, i32, i32 }] [{ i8, i8, i8, i8, i32, i32 } { i8 -17, i8 10, i8 0, i8 0, i32 9, i32 123 }, { i8, i8, i8, i8, i32, i32 } { i8 -17, i8 10, i8 0, i8 0, i32 9, i32 123 }], align 16 +// LLVM-DAG: @g7 = internal global [2 x ptr] [ptr getelementptr inbounds ([2 x { i8, i8, i8, i8, i32, i32 }], ptr @g6, i32 0, i32 0, i32 5), ptr getelementptr inbounds ([2 x { i8, i8, i8, i8, i32, i32 }], ptr @g6, i32 0, i32 1, i32 5)], align 16 +// LLVM-DAG: @g8 = internal global ptr getelementptr inbounds ([2 x ptr], ptr @g7, i32 0, i32 1), align 8 + +// FIXME: LLVM output should be: @g2 = internal global [4 x ptr] [ptr getelementptr (i8, ptr @g1, i64 4), ptr getelementptr (i8, ptr @g1, i64 4), ptr getelementptr (i8, ptr @g1, i64 4), ptr getelementptr (i8, ptr @g1, i64 4)], align 16 +// FIXME: LLVM output should be: @g3 = internal global ptr getelementptr (i8, ptr @g2, i64 8), align 8 +// FIXME: LLVM output should be: @g7 = internal global [2 x ptr] [ptr getelementptr (i8, ptr @g6, i64 8), ptr getelementptr (i8, ptr @g6, i64 20)], align 16 +// FIXME: LLVM output should be: @g8 = internal global ptr getelementptr (i8, ptr @g7, i64 8), align 8 + +typedef struct { + char f1; + int f6; +} S1; + +S1 g9 = {1, 42}; +int* g10 = &g9.f6; + +#pragma pack(push) +#pragma pack(1) +typedef struct { + char f1; + int f6; +} S2; +#pragma pack(pop) + +S2 g11 = {1, 42}; +int* g12 = &g11.f6; + +// CHECK-DAG: g9 = #cir.const_struct<{#cir.int<1> : !s8i, #cir.const_array<[#cir.zero : !u8i, #cir.zero : !u8i, #cir.zero : !u8i]> : !cir.array, #cir.int<42> : !s32i}> : !ty_anon_struct1 {alignment = 4 : i64} +// CHECK-DAG: g10 = #cir.global_view<@g9, [2 : i32]> : !cir.ptr {alignment = 8 : i64} +// CHECK-DAG: g11 = #cir.const_struct<{#cir.int<1> : !s8i, #cir.int<42> : !s32i}> : !ty_S2_ {alignment = 1 : i64} +// CHECK-DAG: g12 = #cir.global_view<@g11, [1 : i32]> : !cir.ptr {alignment = 8 : i64} + +// LLVM-DAG: @g9 = global { i8, [3 x i8], i32 } { i8 1, [3 x i8] zeroinitializer, i32 42 }, align 4 +// LLVM-DAG: @g10 = global ptr getelementptr inbounds ({ i8, [3 x i8], i32 }, ptr @g9, i32 0, i32 2), align 8 +// LLVM-DAG: @g11 = global %struct.S2 <{ i8 1, i32 42 }>, align 1 +// LLVM-DAG: @g12 = global ptr getelementptr inbounds (%struct.S2, ptr @g11, i32 0, i32 1), align 8 + +// FIXME: LLVM output should be: @g10 = dso_local global ptr getelementptr (i8, ptr @g9, i64 4), align 8 +// FIXME: LLVM output should be: @g12 = dso_local global ptr getelementptr (i8, ptr @g11, i64 1), align 8 + + +typedef struct { + short f0; + int f1; + char f2; +} S3; + +static S3 g13 = {-1L,0L,1L}; +static S3* g14[2][2] = {{&g13, &g13}, {&g13, &g13}}; + +// CHECK-DAG: g13 = #cir.const_struct<{#cir.int<-1> : !s16i, #cir.const_array<[#cir.zero : !u8i, #cir.zero : !u8i]> : !cir.array, #cir.int<0> : !s32i, #cir.int<1> : !s8i, #cir.const_array<[#cir.zero : !u8i, #cir.zero : !u8i, #cir.zero : !u8i]> : !cir.array}> : !ty_anon_struct3 +// CHECK-DAG: g14 = #cir.const_array<[#cir.const_array<[#cir.global_view<@g13> : !cir.ptr, #cir.global_view<@g13> : !cir.ptr]> : !cir.array x 2>, #cir.const_array<[#cir.global_view<@g13> : !cir.ptr, #cir.global_view<@g13> : !cir.ptr]> : !cir.array x 2>]> : !cir.array x 2> x 2> + +typedef struct { + int f0; + int f1; +} S4; + +typedef struct { + int f0 : 17; + int f1 : 5; + int f2 : 19; + S4 f3; +} S5; + +static S5 g15 = {187,1,442,{123,321}}; + +int* g16 = &g15.f3.f1; + +// CHECK-DAG: g15 = #cir.const_struct<{#cir.int<187> : !u8i, #cir.int<0> : !u8i, #cir.int<2> : !u8i, #cir.zero : !u8i, #cir.int<186> : !u8i, #cir.int<1> : !u8i, #cir.int<0> : !u8i, #cir.zero : !u8i, #cir.const_struct<{#cir.int<123> : !s32i, #cir.int<321> : !s32i}> : !ty_S4_}> : !ty_anon_struct2 {alignment = 4 : i64} +// CHECK-DAG: g16 = #cir.global_view<@g15, [8, 1]> : !cir.ptr {alignment = 8 : i64} + +// LLVM-DAG: @g15 = internal global { i8, i8, i8, i8, i8, i8, i8, i8, %struct.S4 } { i8 -69, i8 0, i8 2, i8 0, i8 -70, i8 1, i8 0, i8 0, %struct.S4 { i32 123, i32 321 } }, align 4 +// LLVM-DAG: @g16 = global ptr getelementptr inbounds ({ i8, i8, i8, i8, i8, i8, i8, i8, %struct.S4 }, ptr @g15, i32 0, i32 8, i32 1), align 8 + +// FIXME: LLVM output should be: @g16 = dso_local global ptr getelementptr (i8, ptr @g15, i64 12), align 8 + +void use() { + int a = **g3; + int b = ***g4; + int c = ****g5; + int d = **g8; + S3 s = *g14[1][1]; + int f = *g16; +} diff --git a/clang/test/CIR/CodeGen/union-padding.c b/clang/test/CIR/CodeGen/union-padding.c index 8deb2890083c..85ed30d52ce5 100644 --- a/clang/test/CIR/CodeGen/union-padding.c +++ b/clang/test/CIR/CodeGen/union-padding.c @@ -19,7 +19,7 @@ short use() { // CHECK: !ty_anon_struct = !cir.struct}> // CHECK: @g3 = #cir.global_view<@g2> : !cir.ptr> -// CHECK: @g2 = #cir.const_array<[#cir.global_view<@g1, [1 : i32]> : !cir.ptr]> : !cir.array x 1> +// CHECK: @g2 = #cir.const_array<[#cir.global_view<@g1, [1]> : !cir.ptr]> : !cir.array x 1> // CHECK: @g1 = // CHECK-SAME: #cir.const_array<[ diff --git a/clang/test/CIR/CodeGen/vbase.cpp b/clang/test/CIR/CodeGen/vbase.cpp index 1ba565b7cb79..574d2d943258 100644 --- a/clang/test/CIR/CodeGen/vbase.cpp +++ b/clang/test/CIR/CodeGen/vbase.cpp @@ -18,7 +18,7 @@ void ppp() { B b; } // CIR: cir.global linkonce_odr @_ZTV1B = #cir.vtable<{#cir.const_array<[#cir.ptr<12 : i64> : !cir.ptr, #cir.ptr : !cir.ptr, #cir.global_view<@_ZTI1B> : !cir.ptr]> : !cir.array x 3>}> // VTT for B. -// CIR: cir.global linkonce_odr @_ZTT1B = #cir.const_array<[#cir.global_view<@_ZTV1B, [0 : i32, 0 : i32, 3 : i32]> : !cir.ptr]> : !cir.array x 1> +// CIR: cir.global linkonce_odr @_ZTT1B = #cir.const_array<[#cir.global_view<@_ZTV1B, [0 : i32, 3 : i32]> : !cir.ptr]> : !cir.array x 1> // CIR: cir.global "private" external @_ZTVN10__cxxabiv121__vmi_class_type_infoE diff --git a/clang/test/CIR/CodeGen/vtable-emission.cpp b/clang/test/CIR/CodeGen/vtable-emission.cpp index 6691167488c5..7f09f74de0d5 100644 --- a/clang/test/CIR/CodeGen/vtable-emission.cpp +++ b/clang/test/CIR/CodeGen/vtable-emission.cpp @@ -20,7 +20,7 @@ void S::key() {} // LLVM-SAME: [ptr null, ptr @_ZTI1S, ptr @_ZN1S3keyEv, ptr @_ZN1S6nonKeyEv] }, align 8 // CHECK: cir.global external @sobj = #cir.const_struct -// CHECK-SAME: <{#cir.global_view<@_ZTV1S, [0 : i32, 0 : i32, 2 : i32]> : +// CHECK-SAME: <{#cir.global_view<@_ZTV1S, [0 : i32, 2 : i32]> : // CHECK-SAME: !cir.ptr}> : !ty_anon_struct2 {alignment = 8 : i64} // LLVM: @sobj = global { ptr } { ptr getelementptr inbounds // LLVM-SAME: ({ [4 x ptr] }, ptr @_ZTV1S, i32 0, i32 0, i32 2) }, align 8 diff --git a/clang/test/CIR/CodeGen/vtt.cpp b/clang/test/CIR/CodeGen/vtt.cpp index ab8cc999f856..c32e242737cf 100644 --- a/clang/test/CIR/CodeGen/vtt.cpp +++ b/clang/test/CIR/CodeGen/vtt.cpp @@ -46,7 +46,7 @@ int f() { // Vtable of Class D // CIR: cir.global linkonce_odr @_ZTV1D = #cir.vtable<{#cir.const_array<[#cir.ptr<40 : i64> : !cir.ptr, #cir.ptr : !cir.ptr, #cir.global_view<@_ZTI1D> : !cir.ptr, #cir.global_view<@_ZN1B1wEv> : !cir.ptr, #cir.global_view<@_ZN1D1yEv> : !cir.ptr]> : !cir.array x 5>, #cir.const_array<[#cir.ptr<24 : i64> : !cir.ptr, #cir.ptr<-16 : i64> : !cir.ptr, #cir.global_view<@_ZTI1D> : !cir.ptr, #cir.global_view<@_ZN1C1xEv> : !cir.ptr]> : !cir.array x 4>, #cir.const_array<[#cir.ptr : !cir.ptr, #cir.ptr<-40 : i64> : !cir.ptr, #cir.global_view<@_ZTI1D> : !cir.ptr, #cir.global_view<@_ZN1A1vEv> : !cir.ptr]> : !cir.array x 4>}> : !ty_anon_struct4 {alignment = 8 : i64} // VTT of class D -// CIR: cir.global linkonce_odr @_ZTT1D = #cir.const_array<[#cir.global_view<@_ZTV1D, [0 : i32, 0 : i32, 3 : i32]> : !cir.ptr, #cir.global_view<@_ZTC1D0_1B, [0 : i32, 0 : i32, 3 : i32]> : !cir.ptr, #cir.global_view<@_ZTC1D0_1B, [0 : i32, 1 : i32, 3 : i32]> : !cir.ptr, #cir.global_view<@_ZTC1D16_1C, [0 : i32, 0 : i32, 3 : i32]> : !cir.ptr, #cir.global_view<@_ZTC1D16_1C, [0 : i32, 1 : i32, 3 : i32]> : !cir.ptr, #cir.global_view<@_ZTV1D, [0 : i32, 2 : i32, 3 : i32]> : !cir.ptr, #cir.global_view<@_ZTV1D, [0 : i32, 1 : i32, 3 : i32]> : !cir.ptr]> : !cir.array x 7> {alignment = 8 : i64} +// CIR: cir.global linkonce_odr @_ZTT1D = #cir.const_array<[#cir.global_view<@_ZTV1D, [0 : i32, 3 : i32]> : !cir.ptr, #cir.global_view<@_ZTC1D0_1B, [0 : i32, 3 : i32]> : !cir.ptr, #cir.global_view<@_ZTC1D0_1B, [1 : i32, 3 : i32]> : !cir.ptr, #cir.global_view<@_ZTC1D16_1C, [0 : i32, 3 : i32]> : !cir.ptr, #cir.global_view<@_ZTC1D16_1C, [1 : i32, 3 : i32]> : !cir.ptr, #cir.global_view<@_ZTV1D, [2 : i32, 3 : i32]> : !cir.ptr, #cir.global_view<@_ZTV1D, [1 : i32, 3 : i32]> : !cir.ptr]> : !cir.array x 7> {alignment = 8 : i64} // Class B constructor // CIR: cir.func linkonce_odr @_ZN1BC2Ev(%arg0: !cir.ptr