diff options
author | Mark Seaborn <mseaborn@chromium.org> | 2013-06-04 08:28:07 -0700 |
---|---|---|
committer | Mark Seaborn <mseaborn@chromium.org> | 2013-06-04 08:28:07 -0700 |
commit | 012feeb588d28e5604f0ab9f9d9555e63fd68648 (patch) | |
tree | 0a2b241fcb79d9bdc6e05035010c52434b04ceb1 /test | |
parent | b32a69792213eef2ff93440ba09c659b28733169 (diff) |
PNaCl ABI checker: Check for normal form introduced by ReplacePtrsWithInts
Move most of the per-instruction checking in
PNaClABIVerifyFunctions::runOnFunction() to a top-level function so
that it can do an early exit to reject the instruction. Reporting
just a single error per instruction makes the test expectations easier
to understand and update.
Remove the check for metadata types. Metadata won't be part of
PNaCl's stable ABI, so if the metadata-rejecting check is disabled for
debugging purpose, we don't really need to recursively check the
metadata's types.
This lets us remove the recursive checks of Constants and types. We
now only accept a very restricted, non-recursive set of Constants
inside functions and global variable initialisers. This means
PNaClABITypeChecker doesn't need to be stateful any more, and its
methods can become static.
This change also fixes a hole where the operands of "switch"
instructions weren't fully checked.
Add a test to replace-ptrs-with-ints.ll to ensure that "undef" doesn't
appear directly in loads and stores.
BUG=https://code.google.com/p/nativeclient/issues/detail?id=3343
TEST=PNaCl toolchain trybots + GCC torture tests + LLVM test suite
Review URL: https://codereview.chromium.org/15780014
Diffstat (limited to 'test')
-rw-r--r-- | test/NaCl/PNaClABI/abi-debug-info.ll | 37 | ||||
-rw-r--r-- | test/NaCl/PNaClABI/abi-metadata.ll | 11 | ||||
-rw-r--r-- | test/NaCl/PNaClABI/abi-small-arguments.ll | 17 | ||||
-rw-r--r-- | test/NaCl/PNaClABI/abi-stripped-pointers.ll | 131 | ||||
-rw-r--r-- | test/NaCl/PNaClABI/abi-switch.ll | 31 | ||||
-rw-r--r-- | test/NaCl/PNaClABI/abi-varargs.ll | 2 | ||||
-rw-r--r-- | test/NaCl/PNaClABI/instructions.ll | 61 | ||||
-rw-r--r-- | test/NaCl/PNaClABI/types-function.ll | 13 | ||||
-rw-r--r-- | test/NaCl/PNaClABI/types.ll | 56 | ||||
-rw-r--r-- | test/Transforms/NaCl/replace-ptrs-with-ints.ll | 8 |
10 files changed, 292 insertions, 75 deletions
diff --git a/test/NaCl/PNaClABI/abi-debug-info.ll b/test/NaCl/PNaClABI/abi-debug-info.ll new file mode 100644 index 0000000000..95efa0ced7 --- /dev/null +++ b/test/NaCl/PNaClABI/abi-debug-info.ll @@ -0,0 +1,37 @@ +; RUN: pnacl-abicheck -pnaclabi-allow-dev-intrinsics=0 < %s | FileCheck %s +; RUN: pnacl-abicheck -pnaclabi-allow-dev-intrinsics=0 \ +; RUN: -pnaclabi-allow-debug-metadata < %s | FileCheck %s --check-prefix=DBG +; RUN: pnacl-abicheck -pnaclabi-allow-dev-intrinsics=1 < %s | \ +; RUN: FileCheck %s --check-prefix=DBG + + +; DBG-NOT: disallowed + + +declare void @llvm.dbg.declare(metadata, metadata) +declare void @llvm.dbg.value(metadata, i64, metadata) + +; CHECK: Function llvm.dbg.declare is a disallowed LLVM intrinsic +; CHECK: Function llvm.dbg.value is a disallowed LLVM intrinsic + + +define void @debug_declare(i32 %val) { + ; We normally expect llvm.dbg.declare to be used on an alloca. + %var = alloca [4 x i8] + tail call void @llvm.dbg.declare(metadata !{[4 x i8]* %var}, metadata !{}) + tail call void @llvm.dbg.declare(metadata !{i32 %val}, metadata !{}) + ret void +} + +define void @debug_value(i32 %ptr_as_int, i32 %val) { + %ptr = inttoptr i32 %ptr_as_int to i8* + tail call void @llvm.dbg.value(metadata !{i8* %ptr}, i64 2, metadata !{}) + tail call void @llvm.dbg.value(metadata !{i32 %val}, i64 1, metadata !{}) + ret void +} + +; FileCheck gives an error if its input file is empty, so ensure that +; the output of pnacl-abicheck is non-empty by generating at least one +; error. +declare void @bad_func(ppc_fp128 %bad_arg) +; DBG: Function bad_func has disallowed type: void (ppc_fp128) diff --git a/test/NaCl/PNaClABI/abi-metadata.ll b/test/NaCl/PNaClABI/abi-metadata.ll index 4734c25973..751a3d3673 100644 --- a/test/NaCl/PNaClABI/abi-metadata.ll +++ b/test/NaCl/PNaClABI/abi-metadata.ll @@ -2,12 +2,13 @@ ; RUN: pnacl-abicheck -pnaclabi-allow-debug-metadata < %s | FileCheck %s --check-prefix=DEBUG -; If the metadata is allowed we want to check for types. -; We have a hacky way to test this. The -allow-debug-metadata whitelists debug -; metadata. That allows us to check types within debug metadata, even though -; debug metadata normally does not have illegal types. +; Metadata is not part of the PNaCl's stable ABI, so normally the ABI +; checker rejects metadata entirely. However, for debugging support, +; pre-finalized pexes may contain metadata. When checking a +; pre-finalized pexe, the ABI checker does not check the types in the +; metadata. + ; DEBUG-NOT: Named metadata node llvm.dbg.cu is disallowed -; DEBUG: Named metadata node llvm.dbg.cu refers to disallowed type: half ; CHECK: Named metadata node llvm.dbg.cu is disallowed !llvm.dbg.cu = !{!0} !0 = metadata !{ half 0.0} diff --git a/test/NaCl/PNaClABI/abi-small-arguments.ll b/test/NaCl/PNaClABI/abi-small-arguments.ll index 890b84c42a..ce698e7d47 100644 --- a/test/NaCl/PNaClABI/abi-small-arguments.ll +++ b/test/NaCl/PNaClABI/abi-small-arguments.ll @@ -21,25 +21,32 @@ define i8 @return_i8() { ; CHECK: Function return_i8 has disallowed type: -; Direct calls currently do not produce errors because the functions -; are deemed to have already been flagged. -; CHECK-NOT: disallowed define void @bad_direct_calls() { call void @arg_i1(i1 0) +; CHECK: bad function callee operand: call void @arg_i1 + call void @arg_i16(i32 0, i16 0) +; CHECK-NEXT: bad function callee operand: call void @arg_i16 + %result1 = call i1 @return_i1() +; CHECK-NEXT: bad function callee operand: {{.*}} call i1 @return_i1 + %result2 = call i8 @return_i8() +; CHECK-NEXT: bad function callee operand: {{.*}} call i8 @return_i8 + ret void } define void @bad_indirect_calls(i32 %ptr) { %func1 = inttoptr i32 %ptr to void (i8)* +; CHECK: bad result type: %func1 call void %func1(i8 0) -; CHECK: Function bad_indirect_calls has instruction with disallowed type: void (i8)* +; CHECK: bad function callee operand: {{.*}} %func1 %func2 = inttoptr i32 %ptr to i16 ()* +; CHECK: bad result type: %func2 %result3 = call i16 %func2() -; CHECK: Function bad_indirect_calls has instruction with disallowed type: i16 ()* +; CHECK: bad function callee operand: {{.*}} %func2 ret void } diff --git a/test/NaCl/PNaClABI/abi-stripped-pointers.ll b/test/NaCl/PNaClABI/abi-stripped-pointers.ll new file mode 100644 index 0000000000..c994b7d009 --- /dev/null +++ b/test/NaCl/PNaClABI/abi-stripped-pointers.ll @@ -0,0 +1,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 diff --git a/test/NaCl/PNaClABI/abi-switch.ll b/test/NaCl/PNaClABI/abi-switch.ll new file mode 100644 index 0000000000..a3b5e631fc --- /dev/null +++ b/test/NaCl/PNaClABI/abi-switch.ll @@ -0,0 +1,31 @@ +; RUN: pnacl-abicheck < %s | FileCheck %s + +@var = global [4 x i8] c"xxxx" + + +; CHECK-NOT: disallowed + +define void @bad_cases() { + ; ConstantExprs should be rejected here. + switch i32 ptrtoint ([4 x i8]* @var to i32), label %next [i32 0, label %next] +; CHECK: disallowed: bad switch condition +next: + + ; Bad integer type. + switch i32 0, label %next [i99 0, label %next] +; CHECK: bad switch case + + ; Bad integer type. + switch i32 0, label %next [i32 0, label %next + i99 1, label %next] +; CHECK: bad switch case + + ; Note that the reader only allows ConstantInts in the label list. + ; We don't need to check the following, because the reader rejects + ; it: + ; switch i32 0, label %next [i32 ptrtoint (i32* @ptr to i32), label %next] + + ret void +} + +; CHECK-NOT: disallowed diff --git a/test/NaCl/PNaClABI/abi-varargs.ll b/test/NaCl/PNaClABI/abi-varargs.ll index 6eda0b9b53..dac94e00e0 100644 --- a/test/NaCl/PNaClABI/abi-varargs.ll +++ b/test/NaCl/PNaClABI/abi-varargs.ll @@ -10,4 +10,4 @@ define void @call_varargs_func(i32 %ptr) { call void (i32, ...)* %ptr2(i32 123) ret void } -; CHECK: Function call_varargs_func has instruction with disallowed type: void (i32, ...)* +; CHECK: Function call_varargs_func disallowed: bad function callee operand: call void (i32, ...)* diff --git a/test/NaCl/PNaClABI/instructions.ll b/test/NaCl/PNaClABI/instructions.ll index 0076c3d07c..57d1ec856b 100644 --- a/test/NaCl/PNaClABI/instructions.ll +++ b/test/NaCl/PNaClABI/instructions.ll @@ -1,6 +1,5 @@ ; RUN: pnacl-abicheck < %s | FileCheck %s ; Test instruction opcodes allowed by PNaCl ABI -; No testing yet of operands, types, attributes, etc target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32" target triple = "le32-unknown-nacl" @@ -15,7 +14,7 @@ next: next2: unreachable ; CHECK-NOT: disallowed -; CHECK: Function terminators has disallowed instruction: indirectbr +; CHECK: Function terminators disallowed: bad instruction opcode: indirectbr indirectbr i8* undef, [label %next, label %next2] } @@ -44,37 +43,43 @@ define void @binops() { define void @vectors() { ; CHECK-NOT: disallowed -; CHECK: Function vectors has disallowed instruction: extractelement + +; CHECK: disallowed: bad instruction opcode: {{.*}} extractelement %a1 = extractelement <2 x i32> <i32 0, i32 0>, i32 0 -; CHECK: Function vectors has disallowed instruction: shufflevector + +; CHECK: disallowed: bad instruction opcode: {{.*}} shufflevector %a2 = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> undef -; CHECK: Function vectors has disallowed instruction: insertelement -; CHECK: Function vectors has instruction with disallowed type -; CHECK: Function vectors has instruction operand with disallowed type + +; CHECK: disallowed: bad instruction opcode: {{.*}} insertelement %a3 = insertelement <2 x i32> undef, i32 1, i32 0 + ret void } define void @aggregates() { +; CHECK-NOT: disallowed + ; Aggregate operations %a1 = extractvalue { i32, i32 } { i32 0, i32 0 }, 0 -; CHECK-NOT: disallowed -; CHECK: Function aggregates has disallowed instruction: extractvalue +; CHECK: disallowed: bad instruction opcode: {{.*}} extractvalue + %a2 = insertvalue {i32, float} undef, i32 1, 0 -; CHECK-NEXT: Function aggregates has disallowed instruction: insertvalue +; CHECK-NEXT: disallowed: bad instruction opcode: {{.*}} insertvalue + ret void } define void @memory() { ; Memory operations - %a1 = alloca i32 - %a2 = load i32* undef - store i32 undef, i32* undef + %a1 = alloca [4 x i8] + %ptr = inttoptr i32 0 to i32* + %a2 = load i32* %ptr + store i32 undef, i32* %ptr fence acq_rel - %a3 = cmpxchg i32* undef, i32 undef, i32 undef acq_rel - %a4 = atomicrmw add i32* undef, i32 1 acquire + %a3 = cmpxchg i32* %ptr, i32 undef, i32 undef acq_rel + %a4 = atomicrmw add i32* %ptr, i32 1 acquire ; CHECK-NOT: disallowed -; CHECK: Function memory has disallowed instruction: getelementptr +; CHECK: disallowed: bad instruction opcode: {{.*}} getelementptr %a5 = getelementptr { i32, i32}* undef ret void } @@ -90,9 +95,6 @@ define void @conversion() { %a7 = fptosi double undef to i64 %a8 = uitofp i64 undef to double %a9 = sitofp i64 undef to double - %a10 = ptrtoint i8* undef to i32 - %a11 = inttoptr i32 undef to i8* - %a12 = bitcast i8* undef to i32* ret void } @@ -117,40 +119,41 @@ declare void @personality_func() define void @invoke_func() { invoke void @external_func() to label %ok unwind label %onerror ; CHECK-NOT: disallowed -; CHECK: Function invoke_func has disallowed instruction: invoke +; CHECK: disallowed: bad instruction opcode: invoke ok: ret void onerror: %lp = landingpad i32 personality i8* bitcast (void ()* @personality_func to i8*) catch i32* null -; CHECK-NEXT: Function invoke_func has disallowed instruction: landingpad -; CHECK-NEXT: Function invoke_func contains disallowed ConstantExpr +; CHECK: disallowed: bad instruction opcode: {{.*}} landingpad resume i32 %lp -; CHECK-NEXT: Function invoke_func has disallowed instruction: resume +; CHECK: disallowed: bad instruction opcode: resume } -define i32 @va_arg(i8* %va_list) { +define i32 @va_arg(i32 %va_list_as_int) { + %va_list = inttoptr i32 %va_list_as_int to i8* %val = va_arg i8* %va_list, i32 ret i32 %val } ; CHECK-NOT: disallowed -; CHECK: Function va_arg has disallowed instruction: va_arg +; CHECK: disallowed: bad instruction opcode: {{.*}} va_arg @global_var = global [4 x i8] zeroinitializer -define i8* @constantexpr() { - ret i8* getelementptr ([4 x i8]* @global_var, i32 1, i32 0) +define void @constantexpr() { + ptrtoint i8* getelementptr ([4 x i8]* @global_var, i32 1, i32 0) to i32 + ret void } ; CHECK-NOT: disallowed -; CHECK: Function constantexpr contains disallowed ConstantExpr +; CHECK: disallowed: operand not InherentPtr: %1 = ptrtoint i8* getelementptr define void @inline_asm() { call void asm "foo", ""() ret void } ; CHECK-NOT: disallowed -; CHECK: Function inline_asm contains disallowed inline assembly +; CHECK: disallowed: inline assembly: call void asm "foo", ""() ; CHECK-NOT: disallowed ; If another check is added, there should be a check-not in between each check diff --git a/test/NaCl/PNaClABI/types-function.ll b/test/NaCl/PNaClABI/types-function.ll index 32004d39ad..1482c727f0 100644 --- a/test/NaCl/PNaClABI/types-function.ll +++ b/test/NaCl/PNaClABI/types-function.ll @@ -4,22 +4,27 @@ ; stashed in various places in function bodies are caught. @a2 = private global i17 zeroinitializer + +; CHECK: Function func has disallowed type: void (i15) declare void @func(i15 %arg) !llvm.foo = !{!0} !0 = metadata !{ half 0.0} define void @types() { -; CHECK: Function types has instruction with disallowed type: half +; CHECK: bad result type: {{.*}} fptrunc %h1 = fptrunc double undef to half -; CHECK: Function types has instruction operand with disallowed type: half + +; CHECK: bad operand: {{.*}} bitcast half %h2 = bitcast half 0.0 to i16 + ; see below... %h3 = fadd double 0.0, fpext (half 0.0 to double) -; CHECK: Function types has instruction operand with disallowed type: i17* +; CHECK: bad pointer: store store i32 0, i32* bitcast (i17* @a2 to i32*), align 4 -; CHECK: Function types has instruction operand with disallowed type: i15 + +; CHECK: bad function callee operand: call void @func(i15 1) call void @func(i15 1) ; CHECK: Function types has disallowed instruction metadata: !foo diff --git a/test/NaCl/PNaClABI/types.ll b/test/NaCl/PNaClABI/types.ll index 7587609d11..b1527ec111 100644 --- a/test/NaCl/PNaClABI/types.ll +++ b/test/NaCl/PNaClABI/types.ll @@ -34,66 +34,59 @@ block: ; Disallowed integer types phi i4 [ undef, %entry ] -; CHECK: Function func has instruction with disallowed type: i4 +; CHECK: Function func disallowed: bad operand: {{.*}} i4 phi i33 [ undef, %entry ] -; CHECK: instruction with disallowed type: i33 +; CHECK-NEXT: disallowed: bad operand: {{.*}} i33 phi i128 [ undef, %entry ] -; CHECK: instruction with disallowed type: i128 +; CHECK-NEXT: disallowed: bad operand: {{.*}} i128 ; Disallowed floating point types phi half [ undef, %entry ] -; CHECK: instruction with disallowed type: half +; CHECK-NEXT: disallowed: bad operand: {{.*}} half phi x86_fp80 [ undef, %entry ] -; CHECK: instruction with disallowed type: x86_fp80 +; CHECK-NEXT: disallowed: bad operand: {{.*}} x86_fp80 phi fp128 [ undef, %entry ] -; CHECK: instruction with disallowed type: fp128 +; CHECK-NEXT: disallowed: bad operand: {{.*}} fp128 phi ppc_fp128 [ undef, %entry ] -; CHECK: instruction with disallowed type: ppc_fp128 +; CHECK-NEXT: disallowed: bad operand: {{.*}} ppc_fp128 phi x86_mmx [ undef, %entry ] -; CHECK: instruction with disallowed type: x86_mmx -; CHECK: instruction operand with disallowed type: x86_mmx +; CHECK-NEXT: disallowed: bad operand: {{.*}} x86_mmx - ; Derived types + ; Derived types are disallowed too - ; TODO(mseaborn): These are currently allowed but should be disallowed. phi i32* [ undef, %entry ] +; CHECK-NEXT: disallowed: bad operand: {{.*}} i32* + phi [1 x i32] [ undef, %entry ] +; CHECK-NEXT: disallowed: bad operand: {{.*}} [1 x i32] + phi { i32, float } [ undef, %entry ] +; CHECK-NEXT: disallowed: bad operand: {{.*}} { i32, float } + phi void (i32)* [ undef, %entry ] - phi <{ i8, i32 }> [ undef, %entry ] - phi { i32, { i32, double }, float } [ undef, %entry ] -; CHECK-NOT: disallowed +; CHECK-NEXT: disallowed: bad operand: {{.*}} void (i32)* - ; Derived types containing disallowed types - phi half* [ undef, %entry ] -; CHECK: instruction with disallowed type: half* - phi [2 x i33] [ undef, %entry ] -; CHECK: instruction with disallowed type: [2 x i33] - phi { half, i32 } [ undef, %entry ] -; CHECK: instruction with disallowed type: { half, i32 } - phi { float, i33 } [ undef, %entry ] -; CHECK: instruction with disallowed type: { float, i33 } - phi { i32, { i32, half }, float } [ undef, %entry ] -; CHECK: instruction with disallowed type: { i32, { i32, half }, float } + phi <{ i8, i32 }> [ undef, %entry ] +; CHECK-NEXT: disallowed: bad operand: {{.*}} <{ i8, i32 }> ; Vector types are disallowed phi <2 x i32> [ undef, %entry ] -; CHECK: instruction with disallowed type: <2 x i32> +; CHECK-NEXT: disallowed: bad operand: {{.*}} <2 x i32> ret void } -; named types. with the current implementation, bogus named types are legal +; Named types. With the current implementation, named types are legal ; until they are actually attempted to be used. Might want to fix that. %struct.s1 = type { half, float} %struct.s2 = type { i32, i32} @@ -104,11 +97,10 @@ entry: block: phi %struct.s1 [ undef, %entry ] -; CHECK: instruction with disallowed type: %struct.s1 = type { half, float } -; CHECK: instruction operand with disallowed type: %struct.s1 = type { half, float } +; CHECK: disallowed: bad operand: {{.*}} %struct.s1 phi %struct.s2 [ undef, %entry ] -; CHECK-NOT: disallowed +; CHECK-NEXT: disallowed: bad operand: {{.*}} %struct.s2 ret void } @@ -129,8 +121,10 @@ entry: block: phi %struct.snake [ undef, %entry ] +; CHECK: disallowed: bad operand: {{.*}} %struct.snake + phi %struct.linked [ undef, %entry ] -; CHECK-NOT: disallowed +; CHECK-NEXT: disallowed: bad operand: {{.*}} %struct.linked ret void } diff --git a/test/Transforms/NaCl/replace-ptrs-with-ints.ll b/test/Transforms/NaCl/replace-ptrs-with-ints.ll index 5a8f58dbaf..823697d738 100644 --- a/test/Transforms/NaCl/replace-ptrs-with-ints.ll +++ b/test/Transforms/NaCl/replace-ptrs-with-ints.ll @@ -202,6 +202,14 @@ define i16* @constant_pointer_null_load() { ; CHECK-NEXT: %.asptr = inttoptr i32 0 to i32* ; CHECK-NEXT: %val = load i32* %.asptr +define i16* @constant_pointer_undef_load() { + %val = load i16** undef + ret i16* %val +} +; CHECK: define i32 @constant_pointer_undef_load() { +; CHECK-NEXT: %.asptr = inttoptr i32 undef to i32* +; CHECK-NEXT: %val = load i32* %.asptr + define i8 @load(i8* %ptr) { %x = load i8* %ptr |