diff options
author | Misha Brukman <brukman+llvm@gmail.com> | 2004-04-19 03:36:47 +0000 |
---|---|---|
committer | Misha Brukman <brukman+llvm@gmail.com> | 2004-04-19 03:36:47 +0000 |
commit | de4803d0af6824a2d5da41fa09b512084c73ce34 (patch) | |
tree | 7dce857c19be027b6f037588af4c0973001f116f /tools/bugpoint | |
parent | f6f7ec1ee270cfe79cd12ecd7ba3184da71fb482 (diff) | |
download | llvm-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.cpp | 97 |
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); } } } |