1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00

[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.

llvm-svn: 291326
This commit is contained in:
Dan Gohman 2017-01-07 01:50:01 +00:00
parent 278666eda3
commit f98e4f70d1
3 changed files with 44 additions and 7 deletions

View File

@ -77,6 +77,9 @@ static void FindUses(Value *V, Function &F,
// - Call with fewer arguments than needed: arguments are filled in with undef
// - Return value is not needed: drop it
// - Return value needed but not present: supply an undef
//
// For now, return nullptr without creating a wrapper if the wrapper cannot
// be generated due to incompatible types.
static Function *CreateWrapper(Function *F, FunctionType *Ty) {
Module *M = F->getParent();
@ -90,8 +93,10 @@ static Function *CreateWrapper(Function *F, FunctionType *Ty) {
FunctionType::param_iterator PI = F->getFunctionType()->param_begin();
FunctionType::param_iterator PE = F->getFunctionType()->param_end();
for (; AI != Wrapper->arg_end() && PI != PE; ++AI, ++PI) {
assert(AI->getType() == *PI &&
"mismatched argument types not supported yet");
if (AI->getType() != *PI) {
Wrapper->eraseFromParent();
return nullptr;
}
Args.push_back(&*AI);
}
for (; PI != PE; ++PI)
@ -107,8 +112,10 @@ static Function *CreateWrapper(Function *F, FunctionType *Ty) {
BB);
else if (F->getFunctionType()->getReturnType() == Ty->getReturnType())
ReturnInst::Create(M->getContext(), Call, BB);
else
llvm_unreachable("mismatched return types not supported yet");
else {
Wrapper->eraseFromParent();
return nullptr;
}
return Wrapper;
}
@ -138,10 +145,14 @@ bool FixFunctionBitcasts::runOnModule(Module &M) {
if (Pair.second)
Pair.first->second = CreateWrapper(F, Ty);
Function *Wrapper = Pair.first->second;
if (!Wrapper)
continue;
if (isa<Constant>(U->get()))
U->get()->replaceAllUsesWith(Pair.first->second);
U->get()->replaceAllUsesWith(Wrapper);
else
U->set(Pair.first->second);
U->set(Wrapper);
}
return true;

View File

@ -8,7 +8,7 @@ target triple = "wasm32-unknown-unknown"
; CHECK-LABEL: test:
; CHECK-NEXT: call .Lbitcast@FUNCTION{{$}}
; CHECK-NEXT: call .Lbitcast.1@FUNCTION{{$}}
; CHECK-NEXT: i32.const $push[[L0:[0-9]*]]=, 0
; CHECK-NEXT: i32.const $push[[L0:[0-9]+]]=, 0
; CHECK-NEXT: call .Lbitcast.2@FUNCTION, $pop[[L0]]{{$}}
; CHECK-NEXT: i32.call $drop=, .Lbitcast.3@FUNCTION{{$}}
; CHECK-NEXT: call foo2@FUNCTION{{$}}

View File

@ -0,0 +1,26 @@
; RUN: llc < %s -asm-verbose=false | FileCheck %s
; Test that function pointer casts that require conversions are not converted
; to wrappers. In theory some conversions could be supported, but currently no
; conversions are implemented.
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
target triple = "wasm32-unknown-unknown"
; CHECK-LABEL: test:
; CHECK-NEXT: i32.const $push[[L0:[0-9]+]]=, 0{{$}}
; CHECK-NEXT: call has_i64_arg@FUNCTION, $pop[[L0]]{{$}}
; CHECK-NEXT: i32.call $drop=, has_i64_ret@FUNCTION{{$}}
; CHECK-NEXT: .endfunc
; CHECK-NOT: .Lbitcast
declare void @has_i64_arg(i64)
declare i64 @has_i64_ret()
define void @test() {
entry:
call void bitcast (void (i64)* @has_i64_arg to void (i32)*)(i32 0)
%t = call i32 bitcast (i64 ()* @has_i64_ret to i32 ()*)()
ret void
}