llvm.org GIT mirror llvm / e877be1
[WebAssembly] Don't abort on code with UB. Gracefully leave code that performs function-pointer bitcasts implying non-trivial pointer conversions alone, rather than aborting, since it's just undefined behavior. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@291326 91177308-0d34-0410-b5e6-96231b3b80d8 Dan Gohman 3 years ago
3 changed file(s) with 44 addition(s) and 7 deletion(s). Raw diff Collapse all Expand all
7676 // - Call with fewer arguments than needed: arguments are filled in with undef
7777 // - Return value is not needed: drop it
7878 // - Return value needed but not present: supply an undef
79 //
80 // For now, return nullptr without creating a wrapper if the wrapper cannot
81 // be generated due to incompatible types.
7982 static Function *CreateWrapper(Function *F, FunctionType *Ty) {
8083 Module *M = F->getParent();
8184
8992 FunctionType::param_iterator PI = F->getFunctionType()->param_begin();
9093 FunctionType::param_iterator PE = F->getFunctionType()->param_end();
9194 for (; AI != Wrapper->arg_end() && PI != PE; ++AI, ++PI) {
92 assert(AI->getType() == *PI &&
93 "mismatched argument types not supported yet");
95 if (AI->getType() != *PI) {
96 Wrapper->eraseFromParent();
97 return nullptr;
98 }
9499 Args.push_back(&*AI);
95100 }
96101 for (; PI != PE; ++PI)
106111 BB);
107112 else if (F->getFunctionType()->getReturnType() == Ty->getReturnType())
108113 ReturnInst::Create(M->getContext(), Call, BB);
109 else
110 llvm_unreachable("mismatched return types not supported yet");
114 else {
115 Wrapper->eraseFromParent();
116 return nullptr;
117 }
111118
112119 return Wrapper;
113120 }
137144 if (Pair.second)
138145 Pair.first->second = CreateWrapper(F, Ty);
139146
147 Function *Wrapper = Pair.first->second;
148 if (!Wrapper)
149 continue;
150
140151 if (isa(U->get()))
141 U->get()->replaceAllUsesWith(Pair.first->second);
152 U->get()->replaceAllUsesWith(Wrapper);
142153 else
143 U->set(Pair.first->second);
154 U->set(Wrapper);
144155 }
145156
146157 return true;
77 ; CHECK-LABEL: test:
88 ; CHECK-NEXT: call .Lbitcast@FUNCTION{{$}}
99 ; CHECK-NEXT: call .Lbitcast.1@FUNCTION{{$}}
10 ; CHECK-NEXT: i32.const $push[[L0:[0-9]*]]=, 0
10 ; CHECK-NEXT: i32.const $push[[L0:[0-9]+]]=, 0
1111 ; CHECK-NEXT: call .Lbitcast.2@FUNCTION, $pop[[L0]]{{$}}
1212 ; CHECK-NEXT: i32.call $drop=, .Lbitcast.3@FUNCTION{{$}}
1313 ; CHECK-NEXT: call foo2@FUNCTION{{$}}
0 ; RUN: llc < %s -asm-verbose=false | FileCheck %s
1
2 ; Test that function pointer casts that require conversions are not converted
3 ; to wrappers. In theory some conversions could be supported, but currently no
4 ; conversions are implemented.
5
6 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
7 target triple = "wasm32-unknown-unknown"
8
9 ; CHECK-LABEL: test:
10 ; CHECK-NEXT: i32.const $push[[L0:[0-9]+]]=, 0{{$}}
11 ; CHECK-NEXT: call has_i64_arg@FUNCTION, $pop[[L0]]{{$}}
12 ; CHECK-NEXT: i32.call $drop=, has_i64_ret@FUNCTION{{$}}
13 ; CHECK-NEXT: .endfunc
14
15 ; CHECK-NOT: .Lbitcast
16
17 declare void @has_i64_arg(i64)
18 declare i64 @has_i64_ret()
19
20 define void @test() {
21 entry:
22 call void bitcast (void (i64)* @has_i64_arg to void (i32)*)(i32 0)
23 %t = call i32 bitcast (i64 ()* @has_i64_ret to i32 ()*)()
24 ret void
25 }