//
//===----------------------------------------------------------------------===//
-#include "llvm/Transforms/CleanupGCCOutput.h"
+#include "llvm/Transforms/IPO.h"
#include "llvm/Module.h"
-#include "llvm/Function.h"
-#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/SymbolTable.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Pass.h"
#include "llvm/iOther.h"
-#include "Support/StatisticReporter.h"
-#include <iostream>
+#include "llvm/Constant.h"
+#include "Support/Statistic.h"
#include <algorithm>
using std::vector;
using std::cerr;
namespace {
- Statistic<>NumResolved("funcresolve\t- Number of varargs functions resolved");
+ Statistic<>NumResolved("funcresolve", "Number of varargs functions resolved");
struct FunctionResolvingPass : public Pass {
- const char *getPassName() const { return "Resolve Functions"; }
-
- bool run(Module *M);
+ bool run(Module &M);
};
+ RegisterOpt<FunctionResolvingPass> X("funcresolve", "Resolve Functions");
}
Pass *createFunctionResolvingPass() {
Dest->getFunctionType()->getParamTypes();
BasicBlock *BB = CI->getParent();
- // Get an iterator to where we want to insert cast instructions if the
+ // Keep an iterator to where we want to insert cast instructions if the
// argument types don't agree.
//
- BasicBlock::iterator BBI = find(BB->begin(), BB->end(), CI);
- assert(BBI != BB->end() && "CallInst not in parent block?");
-
- assert(CI->getNumOperands()-1 == ParamTys.size()&&
+ BasicBlock::iterator BBI = CI;
+ assert(CI->getNumOperands()-1 == ParamTys.size() &&
"Function calls resolved funny somehow, incompatible number of args");
vector<Value*> Params;
for (unsigned i = 1; i < CI->getNumOperands(); ++i) {
Value *V = CI->getOperand(i);
- if (V->getType() != ParamTys[i-1]) { // Must insert a cast...
- Instruction *Cast = new CastInst(V, ParamTys[i-1]);
- BBI = BB->getInstList().insert(BBI, Cast)+1;
- V = Cast;
- }
+ if (V->getType() != ParamTys[i-1]) // Must insert a cast...
+ V = new CastInst(V, ParamTys[i-1], "argcast", BBI);
Params.push_back(V);
}
// Replace the old call instruction with a new call instruction that calls
// the real function.
//
- ReplaceInstWithInst(BB->getInstList(), BBI, new CallInst(Dest, Params));
+ Instruction *NewCall = new CallInst(Dest, Params, "", BBI);
+
+ // Remove the old call instruction from the program...
+ BB->getInstList().remove(BBI);
+
+ // Transfer the name over...
+ if (NewCall->getType() != Type::VoidTy)
+ NewCall->setName(CI->getName());
+
+ // Replace uses of the old instruction with the appropriate values...
+ //
+ if (NewCall->getType() == CI->getType()) {
+ CI->replaceAllUsesWith(NewCall);
+ NewCall->setName(CI->getName());
+
+ } else if (NewCall->getType() == Type::VoidTy) {
+ // Resolved function does not return a value but the prototype does. This
+ // often occurs because undefined functions default to returning integers.
+ // Just replace uses of the call (which are broken anyway) with dummy
+ // values.
+ CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
+ } else if (CI->getType() == Type::VoidTy) {
+ // If we are gaining a new return value, we don't have to do anything
+ // special here, because it will automatically be ignored.
+ } else {
+ // Insert a cast instruction to convert the return value of the function
+ // into it's new type. Of course we only need to do this if the return
+ // value of the function is actually USED.
+ //
+ if (!CI->use_empty()) {
+ // Insert the new cast instruction...
+ CastInst *NewCast = new CastInst(NewCall, CI->getType(),
+ NewCall->getName(), BBI);
+ CI->replaceAllUsesWith(NewCast);
+ }
+ }
+
+ // The old instruction is no longer needed, destroy it!
+ delete CI;
}
-bool FunctionResolvingPass::run(Module *M) {
- SymbolTable *ST = M->getSymbolTable();
+bool FunctionResolvingPass::run(Module &M) {
+ SymbolTable *ST = M.getSymbolTable();
if (!ST) return false;
std::map<string, vector<Function*> > Functions;
SymbolTable::VarMap &Plane = I->second;
for (SymbolTable::type_iterator PI = Plane.begin(), PE = Plane.end();
PI != PE; ++PI) {
- const string &Name = PI->first;
- Functions[Name].push_back(cast<Function>(PI->second));
+ Function *F = cast<Function>(PI->second);
+ assert(PI->first == F->getName() &&
+ "Function name and symbol table do not agree!");
+ if (F->hasExternalLinkage()) // Only resolve decls to external fns
+ Functions[PI->first].push_back(F);
}
}
Function *Concrete = 0;
for (unsigned i = 0; i < Functions.size(); ) {
if (!Functions[i]->isExternal()) { // Found an implementation
+ if (Implementation != 0)
assert(Implementation == 0 && "Multiple definitions of the same"
" function. Case not handled yet!");
Implementation = Functions[i];
// warnings... here we will actually DCE the function so that it isn't
// used later.
//
- if (Functions[i]->use_size() == 0) {
- M->getFunctionList().remove(Functions[i]);
- delete Functions[i];
+ if (Functions[i]->use_empty()) {
+ M.getFunctionList().erase(Functions[i]);
Functions.erase(Functions.begin()+i);
Changed = true;
++NumResolved;
const FunctionType *ConcreteMT = Concrete->getFunctionType();
bool Broken = false;
- assert(Old->getReturnType() == Concrete->getReturnType() &&
- "Differing return types not handled yet!");
assert(OldMT->getParamTypes().size() <=
ConcreteMT->getParamTypes().size() &&
"Concrete type must have more specified parameters!");
// Attempt to convert all of the uses of the old function to the
- // concrete form of the function. If there is a use of the fn
- // that we don't understand here we punt to avoid making a bad
+ // concrete form of the function. If there is a use of the fn that
+ // we don't understand here we punt to avoid making a bad
// transformation.
//
// At this point, we know that the return values are the same for