summaryrefslogtreecommitdiff
path: root/tools/bugpoint
diff options
context:
space:
mode:
authorMisha Brukman <brukman+llvm@gmail.com>2004-04-19 03:36:47 +0000
committerMisha Brukman <brukman+llvm@gmail.com>2004-04-19 03:36:47 +0000
commitde4803d0af6824a2d5da41fa09b512084c73ce34 (patch)
tree7dce857c19be027b6f037588af4c0973001f116f /tools/bugpoint
parentf6f7ec1ee270cfe79cd12ecd7ba3184da71fb482 (diff)
downloadllvm-de4803d0af6824a2d5da41fa09b512084c73ce34.tar.gz
llvm-de4803d0af6824a2d5da41fa09b512084c73ce34.tar.bz2
llvm-de4803d0af6824a2d5da41fa09b512084c73ce34.tar.xz
As per Chris, greatly simplify handling of external functions by using the
wrapper idea uniformly: we can use Value::replaceAllUsesWith() instead of special-casing by class of user. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@13063 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/bugpoint')
-rw-r--r--tools/bugpoint/Miscompilation.cpp97
1 files changed, 22 insertions, 75 deletions
diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp
index fa60aa57f4..fac65ac91a 100644
--- a/tools/bugpoint/Miscompilation.cpp
+++ b/tools/bugpoint/Miscompilation.cpp
@@ -491,31 +491,29 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
std::vector<Value*> ResolverArgs;
ResolverArgs.push_back(GEP);
- // Convert uses of F in global initializers, etc. to uses in
- // instructions, which are then fixed-up below
- std::vector<User*> Users(F->use_begin(), F->use_end());
- for (std::vector<User*>::iterator U = Users.begin(), UE = Users.end();
- U != UE; ++U)
- {
- User *Use = *U;
- if (Instruction *Inst = dyn_cast<Instruction>(Use))
- continue; // Will be taken care of below
-
- // Take care of cases where a function is used by something other
- // than an instruction; e.g., global variable initializers and
- // constant expressions.
- //
- // Create a new wrapper function with the same signature as the old
- // function which will just pass the call to the other function. The
- // use of the other function will then be re-written (below) to look
- // up the function by name.
-
+ // Rewrite uses of F in global initializers, etc. to uses of a wrapper
+ // function that dynamically resolves the calls to F via our JIT API
+ if (F->use_begin() != F->use_end()) {
+ // Construct a new stub function that will re-route calls to F
const FunctionType *FuncTy = F->getFunctionType();
- Function *FuncWrapper = new Function(FuncTy, F->getLinkage(),
+ Function *FuncWrapper = new Function(FuncTy,
+ GlobalValue::InternalLinkage,
F->getName() + "_wrapper",
F->getParent());
BasicBlock *Header = new BasicBlock("header", FuncWrapper);
+ // Resolve the call to function F via the JIT API:
+ //
+ // call resolver(GetElementPtr...)
+ CallInst *resolve = new CallInst(resolverFunc, ResolverArgs,
+ "resolver");
+ Header->getInstList().push_back(resolve);
+ // cast the result from the resolver to correctly-typed function
+ CastInst *castResolver =
+ new CastInst(resolve, PointerType::get(F->getFunctionType()),
+ "resolverCast");
+ Header->getInstList().push_back(castResolver);
+
// Save the argument list
std::vector<Value*> Args;
for (Function::aiterator i = FuncWrapper->abegin(),
@@ -524,70 +522,19 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
// Pass on the arguments to the real function, return its result
if (F->getReturnType() == Type::VoidTy) {
- CallInst *Call = new CallInst(F, Args);
+ CallInst *Call = new CallInst(castResolver, Args);
Header->getInstList().push_back(Call);
ReturnInst *Ret = new ReturnInst();
Header->getInstList().push_back(Ret);
} else {
- CallInst *Call = new CallInst(F, Args, "redir");
+ CallInst *Call = new CallInst(castResolver, Args, "redir");
Header->getInstList().push_back(Call);
ReturnInst *Ret = new ReturnInst(Call);
Header->getInstList().push_back(Ret);
}
- // Replace uses of old function with our wrapper
- if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Use)) {
- Constant *Init = GV->getInitializer();
- // Functions should only be used as pointers in arrays and structs;
- // if any other uses come up, they must be handled here
- if (ConstantArray *CA = dyn_cast<ConstantArray>(Init))
- CA->replaceUsesOfWithOnConstant(F, FuncWrapper);
- else if (ConstantStruct *CS = dyn_cast<ConstantStruct>(Init))
- CS->replaceUsesOfWithOnConstant(F, FuncWrapper);
- else {
- std::cerr << "UNHANDLED global initializer: " << *Init << "\n";
- exit(1);
- }
- } else if (Constant *C = dyn_cast<Constant>(Use)) {
- // no need to do anything for constants
- } else if (Function *FuncUser = dyn_cast<Function>(Use)) {
- // no need to do anything for function declarations
- } else {
- std::cerr << "UNHANDLED non-instruction use, not a global: "
- << *Use << "\ntype: " << *Use->getType() << "\n";
- exit(1);
- }
- }
-
- // 3. Replace all uses of `func' with calls to resolver by:
- // (a) Iterating through the list of uses of this function
- // (b) Insert a cast instruction in front of each use
- // (c) Replace use of old call with new call
-
- // Insert code at the beginning of the function
- std::vector<User*> Uses(F->use_begin(), F->use_end());
- for (std::vector<User*>::iterator U = Uses.begin(), UE = Uses.end();
- U != UE; ++U) {
- User *Use = *U;
- if (Instruction *Inst = dyn_cast<Instruction>(Use)) {
- // call resolver(GetElementPtr...)
- CallInst *resolve = new CallInst(resolverFunc, ResolverArgs,
- "resolver", Inst);
- // cast the result from the resolver to correctly-typed function
- CastInst *castResolver =
- new CastInst(resolve, PointerType::get(F->getFunctionType()),
- "resolverCast", Inst);
- // actually use the resolved function
- Inst->replaceUsesOfWith(F, castResolver);
- } else if (Constant *C = dyn_cast<Constant>(Use)) {
- // no need to do anything for constants
- } else if (Function *FuncUser = dyn_cast<Function>(Use)) {
- // no need to do anything for function declarations
- } else {
- std::cerr << "UNHANDLED: use of function not rewritten to become "
- << "an instruction: " << *Use << "\n";
- exit(1);
- }
+ // Use the wrapper function instead of the old function
+ F->replaceAllUsesWith(FuncWrapper);
}
}
}