Skip to content

Commit 2fc47f2

Browse files
veselypetaresistor
authored andcommitted
[CHERI] Fix a crash during codegen of __builtin_offsetof.
Occurs only when getting an offset of an item of an array member when the index cannot be constant evaluated and the type is __intcap. We need to extract the addr part of the cap before it is used as an index.
1 parent 333c94c commit 2fc47f2

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3974,6 +3974,8 @@ Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) {
39743974
// Compute the index
39753975
Expr *IdxExpr = E->getIndexExpr(ON.getArrayExprIndex());
39763976
llvm::Value* Idx = CGF.EmitScalarExpr(IdxExpr);
3977+
if (Idx->getType()->isPointerTy())
3978+
Idx = CGF.getCapabilityIntegerValue(Idx);
39773979
bool IdxSigned = IdxExpr->getType()->isSignedIntegerOrEnumerationType();
39783980
Idx = Builder.CreateIntCast(Idx, ResultType, IdxSigned, "conv");
39793981

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 2
2+
// RUN: %riscv32_cheri_purecap_cc1 -o - -emit-llvm -O0 -disable-O0-optnone %s | \
3+
// RUN: opt -passes=mem2reg,instcombine -S -o - | FileCheck %s --check-prefixes=RV32
4+
// RUN: %riscv64_cheri_purecap_cc1 -o - -emit-llvm -O0 -disable-O0-optnone %s | \
5+
// RUN: opt -passes=mem2reg,instcombine -S -o - | FileCheck %s --check-prefixes=RV64
6+
7+
struct foo {
8+
unsigned int dummy;
9+
void *children[2];
10+
};
11+
12+
// RV32-LABEL: define dso_local i32 @off_with_intcap
13+
// RV32-SAME: (ptr addrspace(200) noundef [[BIT:%.*]]) addrspace(200) #[[ATTR0:[0-9]+]] {
14+
// RV32-NEXT: entry:
15+
// RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.cheri.cap.address.get.i32(ptr addrspace(200) [[BIT]])
16+
// RV32-NEXT: [[AND:%.*]] = shl i32 [[TMP0]], 3
17+
// RV32-NEXT: [[TMP1:%.*]] = and i32 [[AND]], 8
18+
// RV32-NEXT: [[TMP2:%.*]] = add nuw nsw i32 [[TMP1]], 8
19+
// RV32-NEXT: ret i32 [[TMP2]]
20+
//
21+
// RV64-LABEL: define dso_local i64 @off_with_intcap
22+
// RV64-SAME: (ptr addrspace(200) noundef [[BIT:%.*]]) addrspace(200) #[[ATTR0:[0-9]+]] {
23+
// RV64-NEXT: entry:
24+
// RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.cheri.cap.address.get.i64(ptr addrspace(200) [[BIT]])
25+
// RV64-NEXT: [[AND:%.*]] = shl i64 [[TMP0]], 4
26+
// RV64-NEXT: [[TMP1:%.*]] = and i64 [[AND]], 16
27+
// RV64-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 16
28+
// RV64-NEXT: ret i64 [[TMP2]]
29+
//
30+
unsigned long off_with_intcap(unsigned __intcap bit) {
31+
return __builtin_offsetof(struct foo, children[bit & 1]);
32+
}
33+
34+
// RV32-LABEL: define dso_local i32 @off_with_int
35+
// RV32-SAME: (i32 noundef [[BIT:%.*]]) addrspace(200) #[[ATTR0]] {
36+
// RV32-NEXT: entry:
37+
// RV32-NEXT: [[AND:%.*]] = shl i32 [[BIT]], 3
38+
// RV32-NEXT: [[TMP0:%.*]] = and i32 [[AND]], 8
39+
// RV32-NEXT: [[TMP1:%.*]] = add nuw nsw i32 [[TMP0]], 8
40+
// RV32-NEXT: ret i32 [[TMP1]]
41+
//
42+
// RV64-LABEL: define dso_local i64 @off_with_int
43+
// RV64-SAME: (i32 noundef signext [[BIT:%.*]]) addrspace(200) #[[ATTR0]] {
44+
// RV64-NEXT: entry:
45+
// RV64-NEXT: [[AND:%.*]] = shl i32 [[BIT]], 4
46+
// RV64-NEXT: [[TMP0:%.*]] = and i32 [[AND]], 16
47+
// RV64-NEXT: [[NARROW:%.*]] = add nuw nsw i32 [[TMP0]], 16
48+
// RV64-NEXT: [[TMP1:%.*]] = zext nneg i32 [[NARROW]] to i64
49+
// RV64-NEXT: ret i64 [[TMP1]]
50+
//
51+
unsigned long off_with_int(unsigned int bit) {
52+
return __builtin_offsetof(struct foo, children[bit & 1]);
53+
}

0 commit comments

Comments
 (0)