[WebAssembly] Support opaque pointers in AddMissingPrototypes
The change here is basically the same as in D108880: Rather than looking at bitcasts, look at calls and their function type. We still need to look through bitcasts to find those calls. The change in llvm/test/CodeGen/WebAssembly/add-prototypes-conflict.ll is due to different visitation order. add-prototypes-opaque-ptrs.ll is a copy of add-prototypes.ll with -force-opaque-pointers. Differential Revision: https://reviews.llvm.org/D109256
This commit is contained in:
parent
9e06c767a4
commit
66a54af967
|
@ -86,27 +86,37 @@ bool WebAssemblyAddMissingPrototypes::runOnModule(Module &M) {
|
|||
F.getName());
|
||||
}
|
||||
|
||||
// Create a function prototype based on the first call site (first bitcast)
|
||||
// that we find.
|
||||
// Find calls of this function, looking through bitcasts.
|
||||
SmallVector<CallBase *> Calls;
|
||||
SmallVector<Value *> Worklist;
|
||||
Worklist.push_back(&F);
|
||||
while (!Worklist.empty()) {
|
||||
Value *V = Worklist.pop_back_val();
|
||||
for (User *U : V->users()) {
|
||||
if (auto *BC = dyn_cast<BitCastOperator>(U))
|
||||
Worklist.push_back(BC);
|
||||
else if (auto *CB = dyn_cast<CallBase>(U))
|
||||
if (CB->getCalledOperand() == V)
|
||||
Calls.push_back(CB);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a function prototype based on the first call site that we find.
|
||||
FunctionType *NewType = nullptr;
|
||||
for (Use &U : F.uses()) {
|
||||
LLVM_DEBUG(dbgs() << "prototype-less use: " << F.getName() << "\n");
|
||||
LLVM_DEBUG(dbgs() << *U.getUser() << "\n");
|
||||
if (auto *BC = dyn_cast<BitCastOperator>(U.getUser())) {
|
||||
if (auto *DestType = dyn_cast<FunctionType>(
|
||||
BC->getDestTy()->getPointerElementType())) {
|
||||
if (!NewType) {
|
||||
// Create a new function with the correct type
|
||||
NewType = DestType;
|
||||
LLVM_DEBUG(dbgs() << "found function type: " << *NewType << "\n");
|
||||
} else if (NewType != DestType) {
|
||||
errs() << "warning: prototype-less function used with "
|
||||
"conflicting signatures: "
|
||||
<< F.getName() << "\n";
|
||||
LLVM_DEBUG(dbgs() << " " << *DestType << "\n");
|
||||
LLVM_DEBUG(dbgs() << " "<< *NewType << "\n");
|
||||
}
|
||||
}
|
||||
for (CallBase *CB : Calls) {
|
||||
LLVM_DEBUG(dbgs() << "prototype-less call of " << F.getName() << ":\n");
|
||||
LLVM_DEBUG(dbgs() << *CB << "\n");
|
||||
FunctionType *DestType = CB->getFunctionType();
|
||||
if (!NewType) {
|
||||
// Create a new function with the correct type
|
||||
NewType = DestType;
|
||||
LLVM_DEBUG(dbgs() << "found function type: " << *NewType << "\n");
|
||||
} else if (NewType != DestType) {
|
||||
errs() << "warning: prototype-less function used with "
|
||||
"conflicting signatures: "
|
||||
<< F.getName() << "\n";
|
||||
LLVM_DEBUG(dbgs() << " " << *DestType << "\n");
|
||||
LLVM_DEBUG(dbgs() << " " << *NewType << "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,15 +7,15 @@ target triple = "wasm32-unknown-unknown"
|
|||
; WARNING: warning: prototype-less function used with conflicting signatures: foo
|
||||
|
||||
; CHECK-LABEL: @call_with_conflicting_prototypes
|
||||
; CHECK: %call1 = call i64 @foo(i32 42)
|
||||
; CHECK: %call2 = call i64 bitcast (i64 (i32)* @foo to i64 (i32, i32)*)(i32 42, i32 43)
|
||||
; CHECK: %call1 = call i64 bitcast (i64 (i32, i32)* @foo to i64 (i32)*)(i32 42)
|
||||
; CHECK: %call2 = call i64 @foo(i32 42, i32 43)
|
||||
define void @call_with_conflicting_prototypes() {
|
||||
%call1 = call i64 bitcast (i64 (...)* @foo to i64 (i32)*)(i32 42)
|
||||
%call2 = call i64 bitcast (i64 (...)* @foo to i64 (i32, i32)*)(i32 42, i32 43)
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: declare extern_weak i64 @foo(i32)
|
||||
; CHECK: declare extern_weak i64 @foo(i32, i32)
|
||||
declare extern_weak i64 @foo(...) #1
|
||||
|
||||
; CHECK-NOT: attributes {{.*}} = { {{.*}}"no-prototype"{{.*}} }
|
||||
|
|
79
llvm/test/CodeGen/WebAssembly/add-prototypes-opaque-ptrs.ll
Normal file
79
llvm/test/CodeGen/WebAssembly/add-prototypes-opaque-ptrs.ll
Normal file
|
@ -0,0 +1,79 @@
|
|||
; RUN: opt -S -wasm-add-missing-prototypes -force-opaque-pointers %s | FileCheck %s
|
||||
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
|
||||
target triple = "wasm32-unknown-unknown"
|
||||
|
||||
; CHECK: @foo_addr = global ptr @foo, align 8
|
||||
@foo_addr = global i64 (i32)* bitcast (i64 (...)* @foo to i64 (i32)*), align 8
|
||||
|
||||
; CHECK: @foo_addr_i8 = global ptr @foo, align 8
|
||||
@foo_addr_i8 = global i8* bitcast (i64 (...)* @foo to i8*), align 8
|
||||
|
||||
; CHECK-LABEL: @call_foo
|
||||
; CHECK: %call = call i64 @foo(i32 42)
|
||||
define void @call_foo(i32 %a) {
|
||||
%call = call i64 bitcast (i64 (...)* @foo to i64 (i32)*)(i32 42)
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @call_foo_ptr
|
||||
; CHECK: %1 = bitcast ptr @foo to ptr
|
||||
; CHECK-NEXT: %call = call i64 %1(i32 43)
|
||||
define i64 @call_foo_ptr(i32 %a) {
|
||||
%1 = bitcast i64 (...)* @foo to i64 (i32)*
|
||||
%call = call i64 (i32) %1(i32 43)
|
||||
ret i64 %call
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @to_intptr_inst
|
||||
; CHECK: %1 = bitcast ptr @foo to ptr
|
||||
; CHECK-NEXT: ret ptr %1
|
||||
define i8* @to_intptr_inst() {
|
||||
%1 = bitcast i64 (...)* @foo to i8*
|
||||
ret i8* %1
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @to_intptr_constexpr
|
||||
; CHECK: ret ptr @foo
|
||||
define i8* @to_intptr_constexpr() {
|
||||
ret i8* bitcast (i64 (...)* @foo to i8*)
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @null_compare
|
||||
; CHECK: br i1 icmp eq (ptr @foo, ptr null), label %if.then, label %if.end
|
||||
define i8 @null_compare() {
|
||||
br i1 icmp eq (i64 (...)* @foo, i64 (...)* null), label %if.then, label %if.end
|
||||
if.then:
|
||||
ret i8 0
|
||||
if.end:
|
||||
ret i8 1
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @as_paramater
|
||||
; CHECK: call void @func_param(ptr @foo)
|
||||
define void @as_paramater() {
|
||||
call void @func_param(i64 (...)* @foo)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Check if a sret parameter works in a no-prototype function.
|
||||
; CHECK-LABEL: @sret_param
|
||||
; CHECK: call void @make_struct_foo(ptr sret(%struct.foo) %foo)
|
||||
%struct.foo = type { i32, i32 }
|
||||
declare void @make_struct_foo(%struct.foo* sret(%struct.foo), ...) #1
|
||||
define void @sret_param() {
|
||||
%foo = alloca %struct.foo, align 4
|
||||
call void bitcast (void (%struct.foo*, ...)* @make_struct_foo to void (%struct.foo*)*)(%struct.foo* sret(%struct.foo) %foo)
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @func_param(i64 (...)*)
|
||||
|
||||
; CHECK: declare void @func_not_called()
|
||||
declare void @func_not_called(...) #1
|
||||
|
||||
; CHECK: declare extern_weak i64 @foo(i32)
|
||||
declare extern_weak i64 @foo(...) #1
|
||||
|
||||
; CHECK-NOT: attributes {{.*}} = { {{.*}}"no-prototype"{{.*}} }
|
||||
attributes #1 = { "no-prototype" }
|
Loading…
Reference in a new issue