1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
; RUN: pnacl-abicheck < %s | FileCheck %s
; This test checks that the PNaCl ABI verifier enforces the normal
; form introduced by the ReplacePtrsWithInts pass.
@var = global [4 x i8] c"xxxx"
@ptr = global i32 ptrtoint ([4 x i8]* @var to i32)
declare i8* @llvm.nacl.read.tp()
define void @pointer_arg(i8* %arg) {
ret void
}
; CHECK: Function pointer_arg has disallowed type
define i8* @pointer_return() {
unreachable
}
; CHECK-NEXT: Function pointer_return has disallowed type
define void @func() {
ret void
}
define void @func_with_arg(i32 %arg) {
ret void
}
define void @allowed_cases(i32 %arg) {
inttoptr i32 123 to i8*
ptrtoint [4 x i8]* @var to i32
%alloc = alloca [1 x i8]
ptrtoint [1 x i8]* %alloc to i32
; These instructions may use a NormalizedPtr, which may be a global.
load i32* @ptr
store i32 123, i32* @ptr
cmpxchg i32* @ptr, i32 1, i32 2 seq_cst
atomicrmw add i32* @ptr, i32 3 seq_cst
; A NormalizedPtr may be a bitcast.
%ptr_bitcast = bitcast [4 x i8]* @var to i32*
load i32* %ptr_bitcast
; A NormalizedPtr may be an inttoptr.
%ptr_from_int = inttoptr i32 123 to i32*
load i32* %ptr_from_int
; Check direct and indirect function calls.
%func_as_int = ptrtoint void ()* @func to i32
%func_ptr = inttoptr i32 %func_as_int to void ()*
call void %func_ptr()
call void @func()
call void @func_with_arg(i32 123)
; Intrinsic calls may return pointers.
%thread_ptr = call i8* @llvm.nacl.read.tp()
ptrtoint i8* %thread_ptr to i32
; Bitcasts between non-pointers are not restricted
bitcast i64 0 to double
bitcast i32 0 to float
; ConstantInts and Arguments are allowed as operands.
add i32 %arg, 123
ret void
}
; CHECK-NOT: disallowed
define void @bad_cases() {
entry:
ptrtoint [4 x i8]* @var to i16
; CHECK: Function bad_cases disallowed: non-i32 ptrtoint
inttoptr i16 123 to i8*
; CHECK-NEXT: non-i32 inttoptr
%a = alloca i32
; CHECK-NEXT: non-i8-array alloca
store i32 0, i32* null
; CHECK-NEXT: bad pointer
store i32 0, i32* undef
; CHECK-NEXT: bad pointer
%bc = bitcast i32* @ptr to i31*
; CHECK-NEXT: bad result type
store i31 0, i31* %bc
; CHECK-NEXT: bad pointer
; Only one level of bitcasts is allowed.
%b = bitcast i32* %a to i8*
%c = bitcast i8* %b to i16*
; CHECK-NEXT: operand not InherentPtr
br label %block
block:
%phi1 = phi i8* [ undef, %entry ]
; CHECK-NEXT: bad operand: %phi1
%phi2 = phi i32* [ undef, %entry ]
; CHECK-NEXT: bad operand: %phi2
icmp eq i32* @ptr, @ptr
; CHECK-NEXT: bad operand: {{.*}} icmp
icmp eq void ()* @func, @func
; CHECK-NEXT: bad operand: {{.*}} icmp
icmp eq i31 0, 0
; CHECK-NEXT: bad operand: {{.*}} icmp
call void null()
; CHECK-NEXT: bad function callee operand
call void @func_with_arg(i32 ptrtoint (i32* @ptr to i32))
; CHECK-NEXT: bad operand
; Taking the address of an intrinsic is not allowed.
ptrtoint i8* ()* @llvm.nacl.read.tp to i32
; CHECK-NEXT: operand not InherentPtr
ret void
}
; CHECK-NOT: disallowed
|