[llvm-commits] CVS: llvm/tools/bugpoint/Miscompilation.cpp

Misha Brukman brukman at cs.uiuc.edu
Sun Apr 18 22:37:01 PDT 2004


Changes in directory llvm/tools/bugpoint:

Miscompilation.cpp updated: 1.40 -> 1.41

---
Log message:

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.


---
Diffs of the changes:  (+22 -75)

Index: llvm/tools/bugpoint/Miscompilation.cpp
diff -u llvm/tools/bugpoint/Miscompilation.cpp:1.40 llvm/tools/bugpoint/Miscompilation.cpp:1.41
--- llvm/tools/bugpoint/Miscompilation.cpp:1.40	Sun Apr 18 20:12:01 2004
+++ llvm/tools/bugpoint/Miscompilation.cpp	Sun Apr 18 22:36:47 2004
@@ -491,31 +491,29 @@
         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 @@
 
           // 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);
         }
       }
     }





More information about the llvm-commits mailing list