Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CIR] Remove InavalidUnionFieldAttr and remove a check in array attr #1166

Merged
merged 1 commit into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
Original file line number Diff line number Diff line change
Expand Up @@ -92,21 +92,6 @@ def CIR_BoolAttr : CIR_Attr<"Bool", "bool", [TypedAttrInterface]> {
}];
}

//===----------------------------------------------------------------------===//
// InactiveUnionFieldAttr
//===----------------------------------------------------------------------===//

def InactiveUnionFieldAttr : CIR_Attr<"InactiveUnionField", "inactive_field", [TypedAttrInterface]> {
let summary = "Attribute to represent an uninitialized field for a union.";
let description = [{
The InactiveUnionFieldAttr is used to represent an uninitialized field
for a union.
}];

let parameters = (ins AttributeSelfTypeParameter<"">:$type);
let assemblyFormat = [{}];
}

//===----------------------------------------------------------------------===//
// ZeroAttr
//===----------------------------------------------------------------------===//
Expand Down
3 changes: 0 additions & 3 deletions clang/lib/CIR/CodeGen/CIRGenBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,9 +297,6 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
return true;
}

if (mlir::isa<cir::InactiveUnionFieldAttr>(attr))
return true;

llvm_unreachable("NYI");
}

Expand Down
28 changes: 1 addition & 27 deletions clang/lib/CIR/CodeGen/CIRGenExprConst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,31 +377,7 @@ mlir::Attribute ConstantAggregateBuilder::buildFrom(
CharUnits AlignedSize = Size.alignTo(Align);

bool Packed = false;
ArrayRef<mlir::Attribute> UnpackedElems;

// Fill the init elements for union. This comes from a fundamental
// difference between CIR and LLVM IR. In LLVM IR, the union is simply a
// struct with the largest member. So it is fine to have only one init
// element. But in CIR, the union has the information for all members. So if
// we only pass a single init element, we may be in trouble. We solve the
// problem by appending placeholder attribute for the uninitialized fields.
llvm::SmallVector<mlir::Attribute, 32> UnionElemsStorage;
if (auto desired = dyn_cast<cir::StructType>(DesiredTy);
desired && desired.isUnion() &&
Elems.size() != desired.getNumElements()) {
for (auto elemTy : desired.getMembers()) {
if (auto Ty = mlir::dyn_cast<mlir::TypedAttr>(Elems.back());
Ty && Ty.getType() == elemTy)
UnionElemsStorage.push_back(Elems.back());
else
UnionElemsStorage.push_back(cir::InactiveUnionFieldAttr::get(
CGM.getBuilder().getContext(), elemTy));
}

UnpackedElems = UnionElemsStorage;
} else {
UnpackedElems = Elems;
}
ArrayRef<mlir::Attribute> UnpackedElems = Elems;

llvm::SmallVector<mlir::Attribute, 32> UnpackedElemStorage;
if (DesiredSize < AlignedSize || DesiredSize.alignTo(Align) != DesiredSize) {
Expand Down Expand Up @@ -1048,8 +1024,6 @@ class ConstExprEmitter
return {};
if (i == 0)
CommonElementType = C.getType();
else if (C.getType() != CommonElementType)
CommonElementType = nullptr;
Elts.push_back(std::move(C));
}

Expand Down
16 changes: 1 addition & 15 deletions clang/lib/CIR/Dialect/IR/CIRDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3197,21 +3197,7 @@ LogicalResult cir::ConstArrayAttr::verify(
// Make sure both number of elements and subelement types match type.
if (at.getSize() != arrayAttr.size() + trailingZerosNum)
return emitError() << "constant array size should match type size";
LogicalResult eltTypeCheck = success();
arrayAttr.walkImmediateSubElements(
[&](Attribute attr) {
// Once we find a mismatch, stop there.
if (eltTypeCheck.failed())
return;
auto typedAttr = mlir::dyn_cast<TypedAttr>(attr);
if (!typedAttr || typedAttr.getType() != at.getEltType()) {
eltTypeCheck = failure();
emitError()
<< "constant array element should match array element type";
}
},
[&](Type type) {});
return eltTypeCheck;
return success();
}

::mlir::Attribute cir::ConstArrayAttr::parse(::mlir::AsmParser &parser,
Expand Down
8 changes: 0 additions & 8 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -436,14 +436,6 @@ lowerCirAttrAsValue(mlir::Operation *parentOp, cir::ConstStructAttr constStruct,

// Iteratively lower each constant element of the struct.
for (auto [idx, elt] : llvm::enumerate(constStruct.getMembers())) {
if (auto constStructType = dyn_cast<cir::StructType>(constStruct.getType());
constStructType && constStructType.isUnion()) {
if (isa<cir::InactiveUnionFieldAttr>(elt))
continue;

idx = 0;
}

mlir::Value init = lowerCirAttrAsValue(parentOp, elt, rewriter, converter);
result = rewriter.create<mlir::LLVM::InsertValueOp>(loc, result, init, idx);
}
Expand Down
33 changes: 0 additions & 33 deletions clang/test/CIR/CodeGen/nested-union-array.c

This file was deleted.

13 changes: 6 additions & 7 deletions clang/test/CIR/CodeGen/union-init.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@ void foo(int x) {
A a = {.x = x};
}

// CHECK-DAG: ![[TY_U:.*]] = !cir.struct<union "U" {!s32i}>
// CHECK-DAG: ![[anon0:.*]] = !cir.struct<struct {{.*}}{!u32i}
// CHECK-DAG: ![[TY_u:.*]] = !cir.struct<union {{.*}}{!s32i, !cir.float}
// CHECK-DAG: ![[anon0:.*]] = !cir.struct<struct {!u32i}>
// CHECK-DAG: ![[anon:.*]] = !cir.struct<struct {!s32i}>
// CHECK-DAG: #[[bfi_x:.*]] = #cir.bitfield_info<name = "x", storage_type = !u32i, size = 16, offset = 0, is_signed = true>
// CHECK-DAG: #[[bfi_y:.*]] = #cir.bitfield_info<name = "y", storage_type = !u32i, size = 16, offset = 16, is_signed = true>
// CHECK-DAG: ![[TY_A:.*]] = !cir.struct<union "A" {!s32i, ![[anon0]]}>
// CHECK-DAG: ![[anon1:.*]] = !cir.struct<union "{{.*}}" {!u32i, !cir.array<!u8i x 4>}

// CHECK-LABEL: cir.func @foo(
Expand All @@ -34,7 +32,7 @@ void foo(int x) {
// CHECK: cir.return

union { int i; float f; } u = { };
// CHECK: cir.global external @u = #cir.zero : ![[TY_u]]
// CHECK: cir.global external @u = #cir.zero : ![[anon]]

unsigned is_little(void) {
const union {
Expand All @@ -45,8 +43,9 @@ unsigned is_little(void) {
}

// CHECK: cir.func @is_little
// CHECK: %[[VAL_1:.*]] = cir.get_global @is_little.one : !cir.ptr<![[anon1]]>
// CHECK: %[[VAL_2:.*]] = cir.get_member %[[VAL_1]][1] {name = "c"} : !cir.ptr<![[anon1]]> -> !cir.ptr<!cir.array<!u8i x 4>>
// CHECK: %[[VAL_1:.*]] = cir.get_global @is_little.one : !cir.ptr<![[anon0]]>
// CHECK: %[[VAL_2:.*]] = cir.cast(bitcast, %[[VAL_1]] : !cir.ptr<![[anon0]]>), !cir.ptr<![[anon1]]>
// CHECK: %[[VAL_3:.*]] = cir.get_member %[[VAL_2]][1] {name = "c"} : !cir.ptr<![[anon1]]> -> !cir.ptr<!cir.array<!u8i x 4>>

typedef union {
int x;
Expand Down
3 changes: 2 additions & 1 deletion clang/test/CIR/IR/invalid.cir
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,8 @@ cir.func @cast27(%p : !u64i) {
!u32i = !cir.int<u, 32>
!u8i = !cir.int<u, 8>
module {
// expected-error@+1 {{constant array element should match array element type}}
// FIXME: The check for equality of the array element type is currently disabled due to https://github.com/llvm/clangir/pull/1007
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's file an issue for this

// expected error {{constant array element should match array element type}}
cir.global external @a = #cir.const_array<[#cir.int<0> : !u8i, #cir.int<23> : !u8i, #cir.int<33> : !u8i] : !cir.array<!u32i x 3>>
}

Expand Down
28 changes: 28 additions & 0 deletions clang/test/CIR/Lowering/nested-union-array.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// 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

struct nested
{
union {
const char *single;
const char *const *multi;
} output;
};
static const char * const test[] = {
"test",
};
const struct nested data[] =
{
{
{
.multi = test,
},
},
{
{
.single = "hello",
},
},
};

// LLVM: @data = constant [2 x {{.*}}]
51 changes: 51 additions & 0 deletions clang/test/CIR/Lowering/union-in-struct-init.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// 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 {
union {
int a;
long b;
};
} S;

S s = { .a = 1 };

// LLVM: @s = global { { i32, [4 x i8] } } { { i32, [4 x i8] } { i32 1, [4 x i8] zeroinitializer } }

typedef struct {
union {
int a;
long b;
};
} S2;

S2 s2 = { .b = 1 };

// LLVM: @s2 = global { { i64 } } { { i64 } { i64 1 } }

typedef struct {
union {
int a;
long b;
long double c;
};
} S3;

S3 s3 = { .a = 1 };

// LLVM: @s3 = global { { i32, [12 x i8] } } { { i32, [12 x i8] } { i32 1, [12 x i8] zeroinitializer } }

typedef struct {
int a, b, c, d;
} T;

typedef union {
struct {
int a;
long b;
};
T c;
} S4;

S4 s4 = {.c = {1, 2, 3, 4}};

// LLVM: @s4 = global { %struct.T } { %struct.T { i32 1, i32 2, i32 3, i32 4 } }