OLD | NEW |
(Empty) | |
| 1 ; Test how we handle eliding pointers in call instructions. |
| 2 |
| 3 ; RUN: llvm-as < %s | pnacl-freeze \ |
| 4 ; RUN: | pnacl-bcanalyzer -dump-records \ |
| 5 ; RUN: | FileCheck %s -check-prefix=PF2 |
| 6 |
| 7 ; RUN: llvm-as < %s | pnacl-freeze -allow-local-symbol-tables \ |
| 8 ; RUN: | pnacl-thaw -allow-local-symbol-tables \ |
| 9 ; RUN: | llvm-dis - | FileCheck %s -check-prefix=TD2 |
| 10 |
| 11 ; ------------------------------------------------------ |
| 12 ; Define some global functions/variables to be used in testing. |
| 13 |
| 14 |
| 15 @bytes = internal global [4 x i8] c"abcd" |
| 16 declare void @foo(i32 %i) |
| 17 declare i32 @llvm.nacl.setjmp(i8* %i) |
| 18 |
| 19 ; ------------------------------------------------------ |
| 20 ; Test how we handle a direct call. |
| 21 |
| 22 define void @DirectCall() { |
| 23 call void @foo(i32 0) |
| 24 ret void |
| 25 } |
| 26 |
| 27 ; TD2: define void @DirectCall() { |
| 28 ; TD2-NEXT: call void @foo(i32 0) |
| 29 ; TD2-NEXT: ret void |
| 30 ; TD2-NEXT: } |
| 31 |
| 32 ; PF2: <FUNCTION_BLOCK> |
| 33 ; PF2: </CONSTANTS_BLOCK> |
| 34 ; PF2-NEXT: <INST_CALL op0=0 op1=14 op2=1/> |
| 35 ; PF2-NEXT: <INST_RET/> |
| 36 ; PF2-NEXT: </FUNCTION_BLOCK> |
| 37 |
| 38 ; ------------------------------------------------------ |
| 39 ; Test how we handle a direct call with a normalized inttoptr argument. |
| 40 ; Pointer arguments are only allowed for intrinsic calls. |
| 41 |
| 42 define void @DirectCallIntToPtrArg(i32 %i) { |
| 43 %1 = inttoptr i32 %i to i8* |
| 44 %2 = call i32 @llvm.nacl.setjmp(i8* %1) |
| 45 ret void |
| 46 } |
| 47 |
| 48 ; TD2: define void @DirectCallIntToPtrArg(i32 %i) { |
| 49 ; TD2-NEXT: %1 = inttoptr i32 %i to i8* |
| 50 ; TD2-NEXT: %2 = call i32 @llvm.nacl.setjmp(i8* %1) |
| 51 ; TD2-NEXT: ret void |
| 52 ; TD2-NEXT: } |
| 53 |
| 54 ; PF2: <FUNCTION_BLOCK> |
| 55 ; PF2-NEXT: <DECLAREBLOCKS op0=1/> |
| 56 ; PF2-NEXT: <INST_CALL op0=0 op1=13 op2=1/> |
| 57 ; PF2-NEXT: <INST_RET/> |
| 58 ; PF2-NEXT: </FUNCTION_BLOCK> |
| 59 |
| 60 ; ------------------------------------------------------ |
| 61 ; Test how we handle a direct call with a normalized ptroint argument. |
| 62 ; Pointer arguments are only allowed for intrinsic calls. |
| 63 |
| 64 define void @DirectCallPtrToIntArg() { |
| 65 %1 = alloca i8, i32 4, align 8 |
| 66 %2 = ptrtoint i8* %1 to i32 |
| 67 call void @foo(i32 %2) |
| 68 ret void |
| 69 } |
| 70 |
| 71 ; TD2: define void @DirectCallPtrToIntArg() { |
| 72 ; TD2-NEXT: %1 = alloca i8, i32 4, align 8 |
| 73 ; TD2-NEXT: %2 = ptrtoint i8* %1 to i32 |
| 74 ; TD2-NEXT: call void @foo(i32 %2) |
| 75 ; TD2-NEXT: ret void |
| 76 ; TD2-NEXT: } |
| 77 |
| 78 ; PF2: <FUNCTION_BLOCK> |
| 79 ; PF2: </CONSTANTS_BLOCK> |
| 80 ; PF2-NEXT: <INST_ALLOCA op0=1 op1=4/> |
| 81 ; PF2-NEXT: <INST_CALL op0=0 op1=15 op2=1/> |
| 82 ; PF2-NEXT: <INST_RET/> |
| 83 ; PF2-NEXT: </FUNCTION_BLOCK> |
| 84 |
| 85 ; ------------------------------------------------------ |
| 86 ; Test how we handle a direct call with a normalized bitcast argument. |
| 87 |
| 88 define void @DirectCallBitcastArg(i32 %i) { |
| 89 %1 = bitcast [4 x i8]* @bytes to i8* |
| 90 %2 = call i32 @llvm.nacl.setjmp(i8* %1) |
| 91 ret void |
| 92 } |
| 93 |
| 94 ; TD2: define void @DirectCallBitcastArg(i32 %i) { |
| 95 ; TD2-NEXT: %1 = bitcast [4 x i8]* @bytes to i8* |
| 96 ; TD2-NEXT: %2 = call i32 @llvm.nacl.setjmp(i8* %1) |
| 97 ; TD2-NEXT: ret void |
| 98 ; TD2-NEXT: } |
| 99 |
| 100 ; PF2: <FUNCTION_BLOCK> |
| 101 ; PF2-NEXT: <DECLAREBLOCKS op0=1/> |
| 102 ; PF2-NEXT: <INST_CALL op0=0 op1=13 op2=2/> |
| 103 ; PF2-NEXT: <INST_RET/> |
| 104 ; PF2-NEXT: </FUNCTION_BLOCK> |
| 105 |
| 106 ; ------------------------------------------------------ |
| 107 ; Test how we handle a direct call with a pointer to scalar conversion. |
| 108 |
| 109 define void @DirectCallScalarArg() { |
| 110 %1 = ptrtoint [4 x i8]* @bytes to i32 |
| 111 call void @foo(i32 %1) |
| 112 ret void |
| 113 } |
| 114 |
| 115 ; TD2: define void @DirectCallScalarArg() { |
| 116 ; TD2-NEXT: %1 = ptrtoint [4 x i8]* @bytes to i32 |
| 117 ; TD2-NEXT: call void @foo(i32 %1) |
| 118 ; TD2-NEXT: ret void |
| 119 ; TD2-NEXT: } |
| 120 |
| 121 ; PF2: <FUNCTION_BLOCK> |
| 122 ; PF2-NEXT: <DECLAREBLOCKS op0=1/> |
| 123 ; PF2-NEXT: <INST_CALL op0=0 op1=13 op2=1/> |
| 124 ; PF2-NEXT: <INST_RET/> |
| 125 ; PF2-NEXT: </FUNCTION_BLOCK> |
| 126 |
| 127 ; ------------------------------------------------------ |
| 128 ; Test how we handle an indirect call. |
| 129 |
| 130 define void @IndirectCall(i32 %i) { |
| 131 %1 = inttoptr i32 %i to void (i32)* |
| 132 call void %1(i32 %i) |
| 133 ret void |
| 134 } |
| 135 |
| 136 ; TD2: define void @IndirectCall(i32 %i) { |
| 137 ; TD2-NEXT: %1 = inttoptr i32 %i to void (i32)* |
| 138 ; TD2-NEXT: call void %1(i32 %i) |
| 139 ; TD2-NEXT: ret void |
| 140 ; TD2-NEXT: } |
| 141 |
| 142 ; PF2: <FUNCTION_BLOCK> |
| 143 ; PF2-NEXT: <DECLAREBLOCKS op0=1/> |
| 144 ; PF2-NEXT: <INST_CALL_INDIRECT op0=0 op1=1 op2=1 op3=1/> |
| 145 ; PF2-NEXT: <INST_RET/> |
| 146 ; PF2-NEXT: </FUNCTION_BLOCK> |
| 147 |
| 148 ; ------------------------------------------------------ |
| 149 ; Test how we handle an indirect call with a normalized ptrtoint argument. |
| 150 |
| 151 define void @IndirectCallPtrToIntArg(i32 %i) { |
| 152 %1 = alloca i8, i32 4, align 8 |
| 153 %2 = inttoptr i32 %i to void (i32)* |
| 154 %3 = ptrtoint i8* %1 to i32 |
| 155 call void %2(i32 %3) |
| 156 ret void |
| 157 } |
| 158 |
| 159 ; TD2: define void @IndirectCallPtrToIntArg(i32 %i) { |
| 160 ; TD2-NEXT: %1 = alloca i8, i32 4, align 8 |
| 161 ; TD2-NEXT: %2 = ptrtoint i8* %1 to i32 |
| 162 ; TD2-NEXT: %3 = inttoptr i32 %i to void (i32)* |
| 163 ; TD2-NEXT: call void %3(i32 %2) |
| 164 ; TD2-NEXT: ret void |
| 165 ; TD2-NEXT: } |
| 166 |
| 167 ; PF2: <FUNCTION_BLOCK> |
| 168 ; PF2: </CONSTANTS_BLOCK> |
| 169 ; PF2-NEXT: <INST_ALLOCA op0=1 op1=4/> |
| 170 ; PF2-NEXT: <INST_CALL_INDIRECT op0=0 op1=3 op2=1 op3=1/> |
| 171 ; PF2-NEXT: <INST_RET/> |
| 172 ; PF2-NEXT: </FUNCTION_BLOCK> |
| 173 |
| 174 ; ------------------------------------------------------ |
| 175 ; Test how we handle an indirect call with a pointer to scalar conversion. |
| 176 |
| 177 define void @IndirectCallScalarArg(i32 %i) { |
| 178 %1 = inttoptr i32 %i to void (i32)* |
| 179 %2 = ptrtoint [4 x i8]* @bytes to i32 |
| 180 call void %1(i32 %2) |
| 181 ret void |
| 182 } |
| 183 |
| 184 ; TD2: define void @IndirectCallScalarArg(i32 %i) { |
| 185 ; TD2-NEXT: %1 = ptrtoint [4 x i8]* @bytes to i32 |
| 186 ; TD2-NEXT: %2 = inttoptr i32 %i to void (i32)* |
| 187 ; TD2-NEXT: call void %2(i32 %1) |
| 188 ; TD2-NEXT: ret void |
| 189 ; TD2-NEXT: } |
| 190 |
| 191 ; PF2: <FUNCTION_BLOCK> |
| 192 ; PF2-NEXT: <DECLAREBLOCKS op0=1/> |
| 193 ; PF2-NEXT: <INST_CALL_INDIRECT op0=0 op1=1 op2=1 op3=2/> |
| 194 ; PF2-NEXT: <INST_RET/> |
| 195 ; PF2-NEXT: </FUNCTION_BLOCK> |
| 196 |
| 197 ; ------------------------------------------------------ |
| 198 ; Test how we handle intrinsics that can return (inherent) pointers, and |
| 199 ; return statements that expect scalar values. |
| 200 |
| 201 declare i8* @llvm.nacl.read.tp() |
| 202 |
| 203 define i32 @ReturnPtrIntrinsic() { |
| 204 %1 = call i8* @llvm.nacl.read.tp() |
| 205 %2 = ptrtoint i8* %1 to i32 |
| 206 ret i32 %2 |
| 207 } |
| 208 |
| 209 ; TD2: define i32 @ReturnPtrIntrinsic() { |
| 210 ; TD2-NEXT: %1 = call i8* @llvm.nacl.read.tp() |
| 211 ; TD2-NEXT: %2 = ptrtoint i8* %1 to i32 |
| 212 ; TD2-NEXT: ret i32 %2 |
| 213 ; TD2-NEXT: } |
| 214 |
| 215 ; PF2: <FUNCTION_BLOCK> |
| 216 ; PF2-NEXT: <DECLAREBLOCKS op0=1/> |
| 217 ; PF2-NEXT: <INST_CALL op0=0 op1=3/> |
| 218 ; PF2-NEXT: <INST_RET op0=1/> |
| 219 ; PF2-NEXT: </FUNCTION_BLOCK> |
OLD | NEW |