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 4, 2024
1 parent 40f9310 commit 451cfe0
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 11 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: 15 additions & 8 deletions clang/test/CodeGen/cheri/cheri-union-i128.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,25 @@
// RUN: %riscv32_cheri_purecap_cc1 %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-32
// RUN: %riscv64_cheri_purecap_cc1 %s -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-64

// UTC_ARGS: --disable
// CHECK-32: %union.u64 = type { ptr addrspace(200) }
// CHECK-32: %union.u128 = type { ptr addrspace(200), [8 x i8] }
// CHECK-64: %union.u64 = type { ptr addrspace(200) }
// CHECK-64: %union.u128 = type { ptr addrspace(200) }
// UTC_ARGS: --enable

union u64 {
__INT64_TYPE__ x;
__intcap cap;
};
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 @@ -32,8 +39,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 @@ -81,11 +88,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 @@ -103,8 +110,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 451cfe0

Please sign in to comment.