Skip to content

Commit a923c97

Browse files
committed
Rewrite calls to bitcast unprototyped functions when emitting a definition.
My variadics patch, r169588, changed these calls to typically be bitcasts rather than calls to a supposedly variadic function. This totally subverted a hack where we intentionally dropped excess arguments from such calls in order to appease the inliner and a "warning" from the optimizer. This patch extends the hack to also work with bitcasts, as well as teaching it to rewrite invokes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@170034 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent b2c0887 commit a923c97

File tree

3 files changed

+123
-78
lines changed

3 files changed

+123
-78
lines changed

lib/CodeGen/CodeGenModule.cpp

+113-77
Original file line numberDiff line numberDiff line change
@@ -1785,99 +1785,131 @@ CodeGenModule::GetLLVMLinkageVarDefinition(const VarDecl *D,
17851785
return llvm::GlobalVariable::ExternalLinkage;
17861786
}
17871787

1788-
/// ReplaceUsesOfNonProtoTypeWithRealFunction - This function is called when we
1789-
/// implement a function with no prototype, e.g. "int foo() {}". If there are
1790-
/// existing call uses of the old function in the module, this adjusts them to
1791-
/// call the new function directly.
1792-
///
1793-
/// This is not just a cleanup: the always_inline pass requires direct calls to
1794-
/// functions to be able to inline them. If there is a bitcast in the way, it
1795-
/// won't inline them. Instcombine normally deletes these calls, but it isn't
1796-
/// run at -O0.
1797-
static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old,
1798-
llvm::Function *NewFn) {
1799-
// If we're redefining a global as a function, don't transform it.
1800-
llvm::Function *OldFn = dyn_cast<llvm::Function>(Old);
1801-
if (OldFn == 0) return;
1802-
1803-
llvm::Type *NewRetTy = NewFn->getReturnType();
1804-
SmallVector<llvm::Value*, 4> ArgList;
1805-
1806-
for (llvm::Value::use_iterator UI = OldFn->use_begin(), E = OldFn->use_end();
1807-
UI != E; ) {
1808-
// TODO: Do invokes ever occur in C code? If so, we should handle them too.
1809-
llvm::Value::use_iterator I = UI++; // Increment before the CI is erased.
1810-
llvm::CallInst *CI = dyn_cast<llvm::CallInst>(*I);
1811-
if (!CI) continue; // FIXME: when we allow Invoke, just do CallSite CS(*I)
1812-
llvm::CallSite CS(CI);
1813-
if (!CI || !CS.isCallee(I)) continue;
1814-
1815-
// If the return types don't match exactly, and if the call isn't dead, then
1816-
// we can't transform this call.
1817-
if (CI->getType() != NewRetTy && !CI->use_empty())
1788+
/// Replace the uses of a function that was declared with a non-proto type.
1789+
/// We want to silently drop extra arguments from call sites
1790+
static void replaceUsesOfNonProtoConstant(llvm::Constant *old,
1791+
llvm::Function *newFn) {
1792+
// Fast path.
1793+
if (old->use_empty()) return;
1794+
1795+
llvm::Type *newRetTy = newFn->getReturnType();
1796+
SmallVector<llvm::Value*, 4> newArgs;
1797+
1798+
for (llvm::Value::use_iterator ui = old->use_begin(), ue = old->use_end();
1799+
ui != ue; ) {
1800+
llvm::Value::use_iterator use = ui++; // Increment before the use is erased.
1801+
llvm::User *user = *use;
1802+
1803+
// Recognize and replace uses of bitcasts. Most calls to
1804+
// unprototyped functions will use bitcasts.
1805+
if (llvm::ConstantExpr *bitcast = dyn_cast<llvm::ConstantExpr>(user)) {
1806+
if (bitcast->getOpcode() == llvm::Instruction::BitCast)
1807+
replaceUsesOfNonProtoConstant(bitcast, newFn);
18181808
continue;
1809+
}
1810+
1811+
// Recognize calls to the function.
1812+
llvm::CallSite callSite(user);
1813+
if (!callSite) continue;
1814+
if (!callSite.isCallee(use)) continue;
18191815

1820-
// Get the attribute list.
1821-
llvm::SmallVector<llvm::AttributeWithIndex, 8> AttrVec;
1822-
llvm::AttributeSet AttrList = CI->getAttributes();
1823-
1824-
// Get any return attributes.
1825-
llvm::Attributes RAttrs = AttrList.getRetAttributes();
1826-
1827-
// Add the return attributes.
1828-
if (RAttrs.hasAttributes())
1829-
AttrVec.push_back(llvm::
1830-
AttributeWithIndex::get(llvm::AttributeSet::ReturnIndex,
1831-
RAttrs));
1832-
1833-
// If the function was passed too few arguments, don't transform. If extra
1834-
// arguments were passed, we silently drop them. If any of the types
1835-
// mismatch, we don't transform.
1836-
unsigned ArgNo = 0;
1837-
bool DontTransform = false;
1838-
for (llvm::Function::arg_iterator AI = NewFn->arg_begin(),
1839-
E = NewFn->arg_end(); AI != E; ++AI, ++ArgNo) {
1840-
if (CS.arg_size() == ArgNo ||
1841-
CS.getArgument(ArgNo)->getType() != AI->getType()) {
1842-
DontTransform = true;
1816+
// If the return types don't match exactly, then we can't
1817+
// transform this call unless it's dead.
1818+
if (callSite->getType() != newRetTy && !callSite->use_empty())
1819+
continue;
1820+
1821+
// Get the call site's attribute list.
1822+
llvm::SmallVector<llvm::AttributeWithIndex, 8> newAttrs;
1823+
llvm::AttributeSet oldAttrs = callSite.getAttributes();
1824+
1825+
// Collect any return attributes from the call.
1826+
llvm::Attributes returnAttrs = oldAttrs.getRetAttributes();
1827+
if (returnAttrs.hasAttributes())
1828+
newAttrs.push_back(llvm::AttributeWithIndex::get(
1829+
llvm::AttributeSet::ReturnIndex, returnAttrs));
1830+
1831+
// If the function was passed too few arguments, don't transform.
1832+
unsigned newNumArgs = newFn->arg_size();
1833+
if (callSite.arg_size() < newNumArgs) continue;
1834+
1835+
// If extra arguments were passed, we silently drop them.
1836+
// If any of the types mismatch, we don't transform.
1837+
unsigned argNo = 0;
1838+
bool dontTransform = false;
1839+
for (llvm::Function::arg_iterator ai = newFn->arg_begin(),
1840+
ae = newFn->arg_end(); ai != ae; ++ai, ++argNo) {
1841+
if (callSite.getArgument(argNo)->getType() != ai->getType()) {
1842+
dontTransform = true;
18431843
break;
18441844
}
18451845

18461846
// Add any parameter attributes.
1847-
llvm::Attributes PAttrs = AttrList.getParamAttributes(ArgNo + 1);
1848-
if (PAttrs.hasAttributes())
1849-
AttrVec.push_back(llvm::AttributeWithIndex::get(ArgNo + 1, PAttrs));
1847+
llvm::Attributes pAttrs = oldAttrs.getParamAttributes(argNo + 1);
1848+
if (pAttrs.hasAttributes())
1849+
newAttrs.push_back(llvm::AttributeWithIndex::get(argNo + 1, pAttrs));
18501850
}
1851-
if (DontTransform)
1851+
if (dontTransform)
18521852
continue;
18531853

1854-
llvm::Attributes FnAttrs = AttrList.getFnAttributes();
1855-
if (FnAttrs.hasAttributes())
1856-
AttrVec.push_back(llvm::
1854+
llvm::Attributes fnAttrs = oldAttrs.getFnAttributes();
1855+
if (fnAttrs.hasAttributes())
1856+
newAttrs.push_back(llvm::
18571857
AttributeWithIndex::get(llvm::AttributeSet::FunctionIndex,
1858-
FnAttrs));
1858+
fnAttrs));
18591859

18601860
// Okay, we can transform this. Create the new call instruction and copy
18611861
// over the required information.
1862-
ArgList.append(CS.arg_begin(), CS.arg_begin() + ArgNo);
1863-
llvm::CallInst *NewCall = llvm::CallInst::Create(NewFn, ArgList, "", CI);
1864-
ArgList.clear();
1865-
if (!NewCall->getType()->isVoidTy())
1866-
NewCall->takeName(CI);
1867-
NewCall->setAttributes(llvm::AttributeSet::get(OldFn->getContext(), AttrVec));
1868-
NewCall->setCallingConv(CI->getCallingConv());
1862+
newArgs.append(callSite.arg_begin(), callSite.arg_begin() + argNo);
1863+
1864+
llvm::CallSite newCall;
1865+
if (callSite.isCall()) {
1866+
newCall = llvm::CallInst::Create(newFn, newArgs, "",
1867+
callSite.getInstruction());
1868+
} else {
1869+
llvm::InvokeInst *oldInvoke =
1870+
cast<llvm::InvokeInst>(callSite.getInstruction());
1871+
newCall = llvm::InvokeInst::Create(newFn,
1872+
oldInvoke->getNormalDest(),
1873+
oldInvoke->getUnwindDest(),
1874+
newArgs, "",
1875+
callSite.getInstruction());
1876+
}
1877+
newArgs.clear(); // for the next iteration
1878+
1879+
if (!newCall->getType()->isVoidTy())
1880+
newCall->takeName(callSite.getInstruction());
1881+
newCall.setAttributes(
1882+
llvm::AttributeSet::get(newFn->getContext(), newAttrs));
1883+
newCall.setCallingConv(callSite.getCallingConv());
18691884

18701885
// Finally, remove the old call, replacing any uses with the new one.
1871-
if (!CI->use_empty())
1872-
CI->replaceAllUsesWith(NewCall);
1886+
if (!callSite->use_empty())
1887+
callSite->replaceAllUsesWith(newCall.getInstruction());
18731888

18741889
// Copy debug location attached to CI.
1875-
if (!CI->getDebugLoc().isUnknown())
1876-
NewCall->setDebugLoc(CI->getDebugLoc());
1877-
CI->eraseFromParent();
1890+
if (!callSite->getDebugLoc().isUnknown())
1891+
newCall->setDebugLoc(callSite->getDebugLoc());
1892+
callSite->eraseFromParent();
18781893
}
18791894
}
18801895

1896+
/// ReplaceUsesOfNonProtoTypeWithRealFunction - This function is called when we
1897+
/// implement a function with no prototype, e.g. "int foo() {}". If there are
1898+
/// existing call uses of the old function in the module, this adjusts them to
1899+
/// call the new function directly.
1900+
///
1901+
/// This is not just a cleanup: the always_inline pass requires direct calls to
1902+
/// functions to be able to inline them. If there is a bitcast in the way, it
1903+
/// won't inline them. Instcombine normally deletes these calls, but it isn't
1904+
/// run at -O0.
1905+
static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old,
1906+
llvm::Function *NewFn) {
1907+
// If we're redefining a global as a function, don't transform it.
1908+
if (!isa<llvm::Function>(Old)) return;
1909+
1910+
replaceUsesOfNonProtoConstant(Old, NewFn);
1911+
}
1912+
18811913
void CodeGenModule::HandleCXXStaticMemberVarInstantiation(VarDecl *VD) {
18821914
TemplateSpecializationKind TSK = VD->getTemplateSpecializationKind();
18831915
// If we have a definition, this might be a deferred decl. If the
@@ -1921,10 +1953,14 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) {
19211953
OldFn->setName(StringRef());
19221954
llvm::Function *NewFn = cast<llvm::Function>(GetAddrOfFunction(GD, Ty));
19231955

1924-
// If this is an implementation of a function without a prototype, try to
1925-
// replace any existing uses of the function (which may be calls) with uses
1926-
// of the new function
1927-
if (D->getType()->isFunctionNoProtoType()) {
1956+
// This might be an implementation of a function without a
1957+
// prototype, in which case, try to do special replacement of
1958+
// calls which match the new prototype. The really key thing here
1959+
// is that we also potentially drop arguments from the call site
1960+
// so as to make a direct call, which makes the inliner happier
1961+
// and suppresses a number of optimizer warnings (!) about
1962+
// dropping arguments.
1963+
if (!OldFn->use_empty()) {
19281964
ReplaceUsesOfNonProtoTypeWithRealFunction(OldFn, NewFn);
19291965
OldFn->removeDeadConstantUsers();
19301966
}

test/CodeGen/exceptions.c

+9
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,12 @@ void test1() {
1919
// CHECK-ARM: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gcc_personality_sj0 to i8*)
2020
// CHECK-ARM-NEXT: cleanup
2121
}
22+
23+
void test2_helper();
24+
void test2() {
25+
__block int x = 10;
26+
test2_helper(5, 6, 7);
27+
}
28+
void test2_helper(int x, int y) {
29+
}
30+
// CHECK: invoke void @test2_helper(i32 5, i32 6)

test/CodeGen/functions.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ void f0() {}
2424

2525
void f1();
2626
void f2(void) {
27-
// CHECK: call void bitcast (void ()* @f1 to void (i32, i32, i32)*)(i32 1, i32 2, i32 3)
27+
// CHECK: call void @f1()
2828
f1(1, 2, 3);
2929
}
3030
// CHECK: define void @f1()

0 commit comments

Comments
 (0)