@@ -25,18 +25,32 @@ SealedInt Obj2 = 10;
2525// CHECK: @llvm.compiler.used = appending addrspace(200) global [2 x ptr addrspace(200)] [ptr addrspace(200) @Obj1, ptr addrspace(200) @Obj2], section "llvm.metadata"
2626
2727void doSomething (struct SealedStructObj * __sealed_capability obj );
28+ void doSomethingWithAddr (int addr );
2829void doSomething2 (SealedInt * __sealed_capability obj );
2930
3031// CHECK: ; Function Attrs: minsize nounwind optsize
3132// CHECK: define dso_local void @func() local_unnamed_addr addrspace(200) #1 {
3233void func () {
3334// CHECK: entry:
34- // CHECK: tail call void @doSomething(ptr addrspace(200) noundef nonnull @Obj1) #3
35+ // CHECK: tail call void @doSomething(ptr addrspace(200) noundef nonnull @Obj1) #5
3536 doSomething (& Obj1 );
3637
37- // CHECK: tail call void @doSomething2(ptr addrspace(200) noundef nonnull @Obj2) #3
38+ // Verify that observing the address of a sealed global value is done through a call to the launder built-in, so that
39+ // the KnownBits optimisation pass can't assume anything about the value of the pointer, specifically nothing about the alignment of the pointer.
40+ // This is because the CHERIoT RTOS uses the lower bits of the address to store the permissions of the sealed capability, and KnownBits can in turn
41+ // optimise away logical computations on lower parts of the address.
42+
43+ // CHECK: %0 = tail call ptr addrspace(200) @llvm.launder.alignment.p200(ptr addrspace(200) nonnull @Obj1)
44+ // CHECK: %1 = tail call i32 @llvm.cheri.cap.address.get.i32(ptr addrspace(200) nonnull %0)
45+ // CHECK: tail call void @doSomethingWithAddr(i32 noundef %1) #5
46+ doSomethingWithAddr (__builtin_cheri_address_get (& Obj1 ));
47+
48+ // CHECK: tail call void @doSomething2(ptr addrspace(200) noundef nonnull @Obj2) #5
3849 doSomething2 (& Obj2 );
3950}
4051
4152// CHECK: declare void @doSomething(ptr addrspace(200) noundef) local_unnamed_addr addrspace(200) #2
53+ // CHECK: declare void @doSomethingWithAddr(i32 noundef) local_unnamed_addr addrspace(200) #2
54+ // CHECK: declare ptr addrspace(200) @llvm.launder.alignment.p200(ptr addrspace(200)) addrspace(200) #3
55+ // CHECK: declare i32 @llvm.cheri.cap.address.get.i32(ptr addrspace(200)) addrspace(200) #4
4256// CHECK: declare void @doSomething2(ptr addrspace(200) noundef) local_unnamed_addr addrspace(200) #2
0 commit comments