summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp69
-rw-r--r--llvm/test/CodeGen/WebAssembly/add-prototypes.ll34
2 files changed, 72 insertions, 31 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp
index a4d276c7936..3f17160964b 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAddMissingPrototypes.cpp
@@ -90,16 +90,23 @@ bool WebAssemblyAddMissingPrototypes::runOnModule(Module &M) {
Function *NewF = nullptr;
for (Use &U : F.uses()) {
LLVM_DEBUG(dbgs() << "prototype-less use: " << F.getName() << "\n");
- if (BitCastOperator *BC = dyn_cast<BitCastOperator>(U.getUser())) {
- FunctionType *DestType =
- cast<FunctionType>(BC->getDestTy()->getPointerElementType());
-
- // Create a new function with the correct type
- NewType = DestType;
- NewF = Function::Create(NewType, F.getLinkage(), F.getName());
- NewF->setAttributes(F.getAttributes());
- NewF->removeFnAttr("no-prototype");
- break;
+ 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;
+ NewF = Function::Create(NewType, F.getLinkage(), F.getName());
+ NewF->setAttributes(F.getAttributes());
+ NewF->removeFnAttr("no-prototype");
+ } else {
+ if (NewType != DestType) {
+ report_fatal_error("Prototypeless function used with "
+ "conflicting signatures: " +
+ F.getName());
+ }
+ }
+ }
}
}
@@ -110,28 +117,38 @@ bool WebAssemblyAddMissingPrototypes::runOnModule(Module &M) {
continue;
}
- for (Use &U : F.uses()) {
- if (BitCastOperator *BC = dyn_cast<BitCastOperator>(U.getUser())) {
- FunctionType *DestType =
- cast<FunctionType>(BC->getDestTy()->getPointerElementType());
- if (NewType != DestType) {
- report_fatal_error(
- "Prototypeless function used with conflicting signatures: " +
- F.getName());
- }
- BC->replaceAllUsesWith(NewF);
- Replacements.emplace_back(&F, NewF);
- } else {
- dbgs() << *U.getUser()->getType() << "\n";
+ SmallVector<Instruction *, 4> DeadInsts;
+
+ for (Use &US : F.uses()) {
+ User *U = US.getUser();
+ if (auto *BC = dyn_cast<BitCastOperator>(U)) {
+ if (auto *Inst = dyn_cast<BitCastInst>(U)) {
+ // Replace with a new bitcast
+ IRBuilder<> Builder(Inst);
+ Value *NewCast = Builder.CreatePointerCast(NewF, BC->getDestTy());
+ Inst->replaceAllUsesWith(NewCast);
+ DeadInsts.push_back(Inst);
+ } else if (auto *Const = dyn_cast<ConstantExpr>(U)) {
+ Constant *NewConst =
+ ConstantExpr::getPointerCast(NewF, BC->getDestTy());
+ Const->replaceAllUsesWith(NewConst);
+ } else {
+ dbgs() << *U->getType() << "\n";
#ifndef NDEBUG
- U.getUser()->dump();
+ U->dump();
#endif
- report_fatal_error(
- "unexpected use of prototypeless function: " + F.getName() + "\n");
+ report_fatal_error("unexpected use of prototypeless function: " +
+ F.getName() + "\n");
+ }
}
}
+
+ for (auto I : DeadInsts)
+ I->eraseFromParent();
+ Replacements.emplace_back(&F, NewF);
}
+
// Finally replace the old function declarations with the new ones
for (auto &Pair : Replacements) {
Function *Old = Pair.first;
diff --git a/llvm/test/CodeGen/WebAssembly/add-prototypes.ll b/llvm/test/CodeGen/WebAssembly/add-prototypes.ll
index 2b227678b07..583cadea03b 100644
--- a/llvm/test/CodeGen/WebAssembly/add-prototypes.ll
+++ b/llvm/test/CodeGen/WebAssembly/add-prototypes.ll
@@ -3,18 +3,42 @@
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
target triple = "wasm32-unknown-unknown"
+; CHECK: @foo_addr = global i64 (i32)* @foo, align 8
@foo_addr = global i64 (i32)* bitcast (i64 (...)* @foo to i64 (i32)*), align 8
-define void @bar(i32 %a) {
-entry:
+; CHECK: @foo_addr_i8 = global i8* bitcast (i64 (i32)* @foo to i8*), 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
}
-declare i64 @foo(...) #1
+; CHECK-LABEL: @call_foo_ptr
+; CHECK: %call = call i64 @foo(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
+}
-attributes #1 = { "no-prototype" }
+; CHECK-LABEL: @to_intptr_inst
+; CHECK: ret i8* bitcast (i64 (i32)* @foo to i8*)
+define i8* @to_intptr_inst() {
+ %1 = bitcast i64 (...)* @foo to i8*
+ ret i8* %1
+}
+
+; CHECK-LABEL: @to_intptr_constexpr
+; CHECK: ret i8* bitcast (i64 (i32)* @foo to i8*)
+define i8* @to_intptr_constexpr() {
+ ret i8* bitcast (i64 (...)* @foo to i8*)
+}
-; CHECK: %call = call i64 @foo(i32 42)
; CHECK: declare i64 @foo(i32)
+declare i64 @foo(...) #1
+
; CHECK-NOT: attributes {{.*}} = { {{.*}}"no-prototype"{{.*}} }
+attributes #1 = { "no-prototype" }
OpenPOWER on IntegriCloud