//
//===----------------------------------------------------------------------===//
-#include "llvm/Transforms/CleanupGCCOutput.h"
+#include "llvm/Transforms/IPO.h"
#include "llvm/Module.h"
-#include "llvm/Function.h"
-#include "llvm/BasicBlock.h"
#include "llvm/SymbolTable.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Pass.h"
#include "llvm/iOther.h"
#include "llvm/Constant.h"
-#include "Support/StatisticReporter.h"
-#include <iostream>
+#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?");
-
+ BasicBlock::iterator BBI = CI;
assert(CI->getNumOperands()-1 == ParamTys.size() &&
"Function calls resolved funny somehow, incompatible number of args");
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);
}
- Instruction *NewCall = new CallInst(Dest, Params);
-
// Replace the old call instruction with a new call instruction that calls
// the real function.
//
- BBI = BB->getInstList().insert(BBI, NewCall)+1;
+ 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(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.
+ // special here, because it will automatically be ignored.
} else {
- assert(0 && "This should have been checked before!");
- abort();
+ // 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!
}
-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() ||
- Concrete->getReturnType() == Type::VoidTy ||
- Old->getReturnType() == Type::VoidTy) &&
- "Differing return types not handled yet!");
assert(OldMT->getParamTypes().size() <=
ConcreteMT->getParamTypes().size() &&
"Concrete type must have more specified parameters!");