[llvm] 66a54af - [WebAssembly] Support opaque pointers in AddMissingPrototypes
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Sat Sep 4 02:32:26 PDT 2021
Author: Nikita Popov
Date: 2021-09-04T11:25:42+02:00
New Revision: 66a54af96766ab635bc1a9fdaf2d568e3c46eb11
URL: https://github.com/llvm/llvm-project/commit/66a54af96766ab635bc1a9fdaf2d568e3c46eb11
DIFF: https://github.com/llvm/llvm-project/commit/66a54af96766ab635bc1a9fdaf2d568e3c46eb11.diff
LOG: [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
Added:
llvm/test/CodeGen/WebAssembly/add-prototypes-opaque-ptrs.ll
Modified:
llvm/lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp
llvm/test/CodeGen/WebAssembly/add-prototypes-conflict.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp
index 530a55cda0e5a..90e8199128471 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp
@@ -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");
}
}
diff --git a/llvm/test/CodeGen/WebAssembly/add-prototypes-conflict.ll b/llvm/test/CodeGen/WebAssembly/add-prototypes-conflict.ll
index 914ac0c89cebe..3b84797d8fdbb 100644
--- a/llvm/test/CodeGen/WebAssembly/add-prototypes-conflict.ll
+++ b/llvm/test/CodeGen/WebAssembly/add-prototypes-conflict.ll
@@ -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"{{.*}} }
diff --git a/llvm/test/CodeGen/WebAssembly/add-prototypes-opaque-ptrs.ll b/llvm/test/CodeGen/WebAssembly/add-prototypes-opaque-ptrs.ll
new file mode 100644
index 0000000000000..67233a17c91a0
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/add-prototypes-opaque-ptrs.ll
@@ -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
+ at foo_addr = global i64 (i32)* bitcast (i64 (...)* @foo to i64 (i32)*), align 8
+
+; CHECK: @foo_addr_i8 = global ptr @foo, align 8
+ at 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" }
More information about the llvm-commits
mailing list