if (!NewType) {
// Create a new function with the correct type
NewType = DestType;
- NewF = Function::Create(NewType, F.getLinkage(), F.getName());
+ NewF = Function::Create(NewType, F.getLinkage(), F.getName() + ".fixed_sig");
NewF->setAttributes(F.getAttributes());
NewF->removeFnAttr("no-prototype");
+ Replacements.emplace_back(&F, NewF);
} else {
if (NewType != DestType) {
report_fatal_error("Prototypeless function used with "
F.getName() + "\n");
continue;
}
-
- 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->dump();
-#endif
- 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;
- Function *New = Pair.second;
- Old->eraseFromParent();
- M.getFunctionList().push_back(New);
+ Function *OldF = Pair.first;
+ Function *NewF = Pair.second;
+ std::string Name = OldF->getName();
+ M.getFunctionList().push_back(NewF);
+ OldF->replaceAllUsesWith(
+ ConstantExpr::getPointerBitCastOrAddrSpaceCast(NewF, OldF->getType()));
+ OldF->eraseFromParent();
+ NewF->setName(Name);
}
return !Replacements.empty();
}
; CHECK-LABEL: @call_foo_ptr
-; CHECK: %call = call i64 @foo(i32 43)
+; CHECK: %1 = bitcast i64 (...)* bitcast (i64 (i32)* @foo to i64 (...)*) to i64 (i32)*
+; 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)
}
; CHECK-LABEL: @to_intptr_inst
-; CHECK: ret i8* bitcast (i64 (i32)* @foo to i8*)
+; CHECK: %1 = bitcast i64 (...)* bitcast (i64 (i32)* @foo to i64 (...)*) to i8*
+; CHECK-NEXT: ret i8* %1
define i8* @to_intptr_inst() {
%1 = bitcast i64 (...)* @foo to i8*
ret i8* %1
ret i8* bitcast (i64 (...)* @foo to i8*)
}
-; CHECK: declare i64 @foo(i32)
-declare i64 @foo(...) #1
+; CHECK-LABEL: @null_compare
+; CHECK: br i1 icmp eq (i64 (...)* bitcast (i64 (i32)* @foo to i64 (...)*), i64 (...)* 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(i64 (...)* bitcast (i64 (i32)* @foo to i64 (...)*))
+define void @as_paramater() {
+ call void @func_param(i64 (...)* @foo)
+ ret void
+}
+
+declare void @func_param(i64 (...)*)
+
+; CHECK: declare extern_weak i64 @foo(i32)
+declare extern_weak i64 @foo(...) #1
; CHECK-NOT: attributes {{.*}} = { {{.*}}"no-prototype"{{.*}} }
attributes #1 = { "no-prototype" }