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

Misha Brukman brukman at cs.uiuc.edu
Sun Apr 18 20:12:01 PDT 2004


Changes in directory llvm/tools/bugpoint:

Miscompilation.cpp updated: 1.39 -> 1.40

---
Log message:

Finally implement rewriting global initializers which use external functions
by creating an internal wrapper function with same signature as the external
function, and use it instead of the "real" function.

The wrapper then calls the external function using the same JIT function
resolution API that has been used before for rewriting instructions, since the
wrapper has an explicit call instruction which we can rewrite.


---
Diffs of the changes:  (+83 -10)

Index: llvm/tools/bugpoint/Miscompilation.cpp
diff -u llvm/tools/bugpoint/Miscompilation.cpp:1.39 llvm/tools/bugpoint/Miscompilation.cpp:1.40
--- llvm/tools/bugpoint/Miscompilation.cpp:1.39	Sun Apr 11 18:52:35 2004
+++ llvm/tools/bugpoint/Miscompilation.cpp	Sun Apr 18 20:12:01 2004
@@ -466,10 +466,10 @@
                               PointerType::get(Type::SByteTy), 0);
     
   // Use the function we just added to get addresses of functions we need.
-  for (Module::iterator F = Safe->begin(), E = Safe->end(); F != E; ++F){
+  for (Module::iterator F = Safe->begin(), E = Safe->end(); F != E; ++F) {
     if (F->isExternal() && !F->use_empty() && &*F != resolverFunc &&
         F->getIntrinsicID() == 0 /* ignore intrinsics */) {
-      Function *TestFn =Test->getFunction(F->getName(), F->getFunctionType());
+      Function *TestFn = Test->getFunction(F->getName(), F->getFunctionType());
 
       // Don't forward functions which are external in the test module too.
       if (TestFn && !TestFn->isExternal()) {
@@ -491,14 +491,85 @@
         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.
+
+          const FunctionType *FuncTy = F->getFunctionType();
+          Function *FuncWrapper = new Function(FuncTy, F->getLinkage(),
+                                               F->getName() + "_wrapper",
+                                               F->getParent());
+          BasicBlock *Header = new BasicBlock("header", FuncWrapper);
+
+          // Save the argument list
+          std::vector<Value*> Args;
+          for (Function::aiterator i = FuncWrapper->abegin(),
+                 e = FuncWrapper->aend(); i != e; ++i)
+            Args.push_back(i);
+
+          // Pass on the arguments to the real function, return its result
+          if (F->getReturnType() == Type::VoidTy) {
+            CallInst *Call = new CallInst(F, Args);
+            Header->getInstList().push_back(Call);
+            ReturnInst *Ret = new ReturnInst();
+            Header->getInstList().push_back(Ret);
+          } else {
+            CallInst *Call = new CallInst(F, 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
-        while (!F->use_empty())
-          if (Instruction *Inst = dyn_cast<Instruction>(F->use_back())) {
+        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);
@@ -508,14 +579,16 @@
                            "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 {
-            // FIXME: need to take care of cases where a function is used by
-            // something other than an instruction; e.g., global variable
-            // initializers and constant expressions.
-            std::cerr << "UNSUPPORTED: Non-instruction is using an external "
-                      << "function, " << F->getName() << "().\n";
-            abort();
+            std::cerr << "UNHANDLED: use of function not rewritten to become "
+                      << "an instruction: " << *Use << "\n";
+            exit(1);
           }
+        }
       }
     }
   }





More information about the llvm-commits mailing list