Skip to content

Commit

Permalink
[CHERI] Prefer capability types when lowering unions to LLVM IR types
Browse files Browse the repository at this point in the history
This ensures that a union contain a __int128 and a capability will
be lowered as a struct with one capability field instead of as an
i128. This fixes tag stripping when passing such unions to functions
by value instead of by reference.
  • Loading branch information
arichardson committed Feb 9, 2024
1 parent 94742cf commit e80c5f5
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 15 deletions.
7 changes: 4 additions & 3 deletions clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -349,10 +349,11 @@ void CGRecordLowering::lowerUnion() {
if (!IsZeroInitializable)
continue;
// Conditionally update our storage type if we've got a new "better" one.
if (!StorageType ||
getAlignment(FieldType) > getAlignment(StorageType) ||
if (!StorageType || getAlignment(FieldType) > getAlignment(StorageType) ||
(getAlignment(FieldType) == getAlignment(StorageType) &&
getSize(FieldType) > getSize(StorageType)))
getSize(FieldType) > getSize(StorageType)) ||
(DataLayout.isFatPointer(FieldType) &&
!DataLayout.isFatPointer(StorageType)))
StorageType = FieldType;
}
// If we have no storage type just pad to the appropriate size and return.
Expand Down
23 changes: 11 additions & 12 deletions clang/test/CodeGen/cheri/cheri-union-i128.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
// RUN: %riscv64_cheri_purecap_cc1 %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,CHECK-64

// UTC_ARGS: --disable
// CHECK-32: %union.u64 = type { i64 }
// CHECK-64: %union.u64 = type { ptr addrspace(200) }
// CHECK: %union.u128 = type { i128 }
// CHECK: %union.u64 = type { ptr addrspace(200) }
// CHECK-32: %union.u128 = type { ptr addrspace(200), [8 x i8] }
// CHECK-64: %union.u128 = type { ptr addrspace(200) }
// CHECK: %union.nested = type { %struct.anon }
// CHECK: %struct.anon = type { i32, ptr addrspace(200) }
// CHECK: %struct.anon.0 = type { ptr addrspace(200), i32 }
Expand All @@ -18,11 +18,11 @@ union u64 {
extern union u64 global64;

// CHECK-32-LABEL: define {{[^@]+}}@arg64
// CHECK-32-SAME: (i64 [[U_COERCE:%.*]]) addrspace(200) #[[ATTR0:[0-9]+]] {
// CHECK-32-SAME: (ptr addrspace(200) [[U_COERCE:%.*]]) addrspace(200) #[[ATTR0:[0-9]+]] {
// CHECK-32-NEXT: entry:
// CHECK-32-NEXT: [[U:%.*]] = alloca [[UNION_U64:%.*]], align 8, addrspace(200)
// CHECK-32-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds [[UNION_U64]], ptr addrspace(200) [[U]], i32 0, i32 0
// CHECK-32-NEXT: store i64 [[U_COERCE]], ptr addrspace(200) [[COERCE_DIVE]], align 8
// CHECK-32-NEXT: store ptr addrspace(200) [[U_COERCE]], ptr addrspace(200) [[COERCE_DIVE]], align 8
// CHECK-32-NEXT: [[TMP0:%.*]] = load i64, ptr addrspace(200) [[U]], align 8
// CHECK-32-NEXT: ret i64 [[TMP0]]
//
Expand All @@ -41,8 +41,8 @@ __INT64_TYPE__ arg64(union u64 u) {
// CHECK-32-LABEL: define {{[^@]+}}@call64
// CHECK-32-SAME: () addrspace(200) #[[ATTR0]] {
// CHECK-32-NEXT: entry:
// CHECK-32-NEXT: [[TMP0:%.*]] = load i64, ptr addrspace(200) @global64, align 8
// CHECK-32-NEXT: [[CALL:%.*]] = call i64 @arg64(i64 [[TMP0]])
// CHECK-32-NEXT: [[TMP0:%.*]] = load ptr addrspace(200), ptr addrspace(200) @global64, align 8
// CHECK-32-NEXT: [[CALL:%.*]] = call i64 @arg64(ptr addrspace(200) [[TMP0]])
// CHECK-32-NEXT: ret void
//
// CHECK-64-LABEL: define {{[^@]+}}@call64
Expand Down Expand Up @@ -76,7 +76,6 @@ union u64 ret64(void) {
return global64;
}

// FIXME: Unions with int128+capability members should not be passed as i128!
union u128 {
__int128 x;
__intcap cap;
Expand All @@ -90,11 +89,11 @@ extern union u128 global128;
// CHECK-32-NEXT: ret i128 [[TMP0]]
//
// CHECK-64-LABEL: define {{[^@]+}}@arg128
// CHECK-64-SAME: (i128 [[U_COERCE:%.*]]) addrspace(200) #[[ATTR0]] {
// CHECK-64-SAME: (ptr addrspace(200) [[U_COERCE:%.*]]) addrspace(200) #[[ATTR0]] {
// CHECK-64-NEXT: entry:
// CHECK-64-NEXT: [[U:%.*]] = alloca [[UNION_U128:%.*]], align 16, addrspace(200)
// CHECK-64-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds [[UNION_U128]], ptr addrspace(200) [[U]], i32 0, i32 0
// CHECK-64-NEXT: store i128 [[U_COERCE]], ptr addrspace(200) [[COERCE_DIVE]], align 16
// CHECK-64-NEXT: store ptr addrspace(200) [[U_COERCE]], ptr addrspace(200) [[COERCE_DIVE]], align 16
// CHECK-64-NEXT: [[TMP0:%.*]] = load i128, ptr addrspace(200) [[U]], align 16
// CHECK-64-NEXT: ret i128 [[TMP0]]
//
Expand All @@ -112,8 +111,8 @@ __int128 arg128(union u128 u) {
// CHECK-64-LABEL: define {{[^@]+}}@call128
// CHECK-64-SAME: () addrspace(200) #[[ATTR0]] {
// CHECK-64-NEXT: entry:
// CHECK-64-NEXT: [[TMP0:%.*]] = load i128, ptr addrspace(200) @global128, align 16
// CHECK-64-NEXT: [[CALL:%.*]] = call i128 @arg128(i128 [[TMP0]])
// CHECK-64-NEXT: [[TMP0:%.*]] = load ptr addrspace(200), ptr addrspace(200) @global128, align 16
// CHECK-64-NEXT: [[CALL:%.*]] = call i128 @arg128(ptr addrspace(200) [[TMP0]])
// CHECK-64-NEXT: ret void
//
void call128(void) {
Expand Down

0 comments on commit e80c5f5

Please sign in to comment.