From de4803d0af6824a2d5da41fa09b512084c73ce34 Mon Sep 17 00:00:00 2001 From: Misha Brukman Date: Mon, 19 Apr 2004 03:36:47 +0000 Subject: [PATCH] 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 --- tools/bugpoint/Miscompilation.cpp | 97 +++++++------------------------ 1 file changed, 22 insertions(+), 75 deletions(-) diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp index fa60aa57f4a..fac65ac91ab 100644 --- a/tools/bugpoint/Miscompilation.cpp +++ b/tools/bugpoint/Miscompilation.cpp @@ -491,31 +491,29 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test, std::vector 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 Users(F->use_begin(), F->use_end()); - for (std::vector::iterator U = Users.begin(), UE = Users.end(); - U != UE; ++U) - { - User *Use = *U; - if (Instruction *Inst = dyn_cast(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 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(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(Init)) - CA->replaceUsesOfWithOnConstant(F, FuncWrapper); - else if (ConstantStruct *CS = dyn_cast(Init)) - CS->replaceUsesOfWithOnConstant(F, FuncWrapper); - else { - std::cerr << "UNHANDLED global initializer: " << *Init << "\n"; - exit(1); - } - } else if (Constant *C = dyn_cast(Use)) { - // no need to do anything for constants - } else if (Function *FuncUser = dyn_cast(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 Uses(F->use_begin(), F->use_end()); - for (std::vector::iterator U = Uses.begin(), UE = Uses.end(); - U != UE; ++U) { - User *Use = *U; - if (Instruction *Inst = dyn_cast(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(Use)) { - // no need to do anything for constants - } else if (Function *FuncUser = dyn_cast(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); } } }