Pass around IntrinsicLowering instances as appropriate.
authorChris Lattner <sabre@nondot.org>
Sun, 28 Dec 2003 09:44:37 +0000 (09:44 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 28 Dec 2003 09:44:37 +0000 (09:44 +0000)
Reimplement the Interpreters implementation of va_* to be more direct.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@10627 91177308-0d34-0410-b5e6-96231b3b80d8

lib/ExecutionEngine/ExecutionEngine.cpp
lib/ExecutionEngine/Interpreter/Execution.cpp
lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp
lib/ExecutionEngine/Interpreter/Interpreter.cpp
lib/ExecutionEngine/Interpreter/Interpreter.h
lib/ExecutionEngine/JIT/JIT.h
lib/ExecutionEngine/JIT/TargetSelect.cpp

index bb52c943111867ac72184dd43aba14543721b1cc..45643abca9d06fdc510de4efbc10c18c75d53adc 100644 (file)
@@ -17,6 +17,7 @@
 #include "JIT/JIT.h"
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
+#include "llvm/IntrinsicLowering.h"
 #include "llvm/Module.h"
 #include "llvm/ModuleProvider.h"
 #include "llvm/ExecutionEngine/ExecutionEngine.h"
@@ -105,20 +106,23 @@ int ExecutionEngine::runFunctionAsMain(Function *Fn,
 /// NULL is returned. 
 ///
 ExecutionEngine *ExecutionEngine::create(ModuleProvider *MP, 
-                                         bool ForceInterpreter) {
+                                         bool ForceInterpreter,
+                                         IntrinsicLowering *IL) {
   ExecutionEngine *EE = 0;
 
-  // Unless the interpreter was explicitly selected, make a JIT.
+  // Unless the interpreter was explicitly selected, try making a JIT.
   if (!ForceInterpreter)
-    EE = JIT::create(MP);
+    EE = JIT::create(MP, IL);
 
   // If we can't make a JIT, make an interpreter instead.
   try {
     if (EE == 0)
-      EE = Interpreter::create(MP->materializeModule());
+      EE = Interpreter::create(MP->materializeModule(), IL);
   } catch (...) {
     EE = 0;
   }
+
+  if (EE == 0) delete IL;
   return EE;
 }
 
index abade5f857a0cc3a2b5a2446477b1c6b047ea11e..bec4b7b9056b8bb3afaf8ee436b826ad92523bb5 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #define DEBUG_TYPE "interpreter"
-
 #include "Interpreter.h"
-#include "llvm/Instructions.h"
-#include "llvm/DerivedTypes.h"
 #include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Instructions.h"
+#include "llvm/IntrinsicLowering.h"
+#include "llvm/Intrinsics.h"
 #include "llvm/Support/GetElementPtrTypeIterator.h"
 #include "Support/Statistic.h"
 #include "Support/Debug.h"
@@ -25,15 +26,15 @@ using namespace llvm;
 
 namespace {
   Statistic<> NumDynamicInsts("lli", "Number of dynamic instructions executed");
-}
 
-namespace llvm {
   Interpreter *TheEE = 0;
 }
 
+
 //===----------------------------------------------------------------------===//
 //                     Value Manipulation code
 //===----------------------------------------------------------------------===//
+
 static GenericValue executeAddInst(GenericValue Src1, GenericValue Src2, 
                                   const Type *Ty);
 static GenericValue executeSubInst(GenericValue Src1, GenericValue Src2, 
@@ -764,6 +765,36 @@ void Interpreter::visitStoreInst(StoreInst &I) {
 
 void Interpreter::visitCallSite(CallSite CS) {
   ExecutionContext &SF = ECStack.back();
+
+  // Check to see if this is an intrinsic function call...
+  if (Function *F = CS.getCalledFunction())
+    switch (F->getIntrinsicID()) {
+    case Intrinsic::va_start:  // va_start: implemented by getFirstVarArg()
+      SetValue(CS.getInstruction(), getFirstVarArg(), SF);
+      return;
+    case Intrinsic::va_end:    // va_end is a noop for the interpreter
+      return;
+    case Intrinsic::va_copy:   // va_copy: dest = src
+      SetValue(CS.getInstruction(), getOperandValue(*CS.arg_begin(), SF), SF);
+      return;
+    default:
+      // If it is an unknown intrinsic function, using the intrinsic lowering
+      // class to transform it into hopefully tasty LLVM code.
+      //
+      Instruction *Prev = CS.getInstruction()->getPrev();
+      BasicBlock *Parent = CS.getInstruction()->getParent();
+      IL->LowerIntrinsicCall(cast<CallInst>(CS.getInstruction()));
+
+      // Restore the CurInst pointer to the first instruction newly inserted, if
+      // any.
+      if (!Prev) {
+        SF.CurInst = Parent->begin();
+      } else {
+        SF.CurInst = Prev;
+        ++SF.CurInst;
+      }
+    }
+
   SF.Caller = CS;
   std::vector<GenericValue> ArgVals;
   const unsigned NumArgs = SF.Caller.arg_size();
index 8cde5fe535ce5a3a91fe13cfa2a63d50b8a71236..1fe0c01275db103f66f26caaafcb7716d50635f0 100644 (file)
@@ -676,28 +676,6 @@ GenericValue lle_X_fprintf(FunctionType *M, const vector<GenericValue> &Args) {
   return GV;
 }
 
-//===----------------------------------------------------------------------===//
-// LLVM Intrinsic Functions...
-//===----------------------------------------------------------------------===//
-
-// <va_list> llvm.va_start() - Implement the va_start operation...
-GenericValue llvm_va_start(FunctionType *F, const vector<GenericValue> &Args) {
-  assert(Args.size() == 0);
-  return TheInterpreter->getFirstVarArg();
-}
-
-// void llvm.va_end(<va_list> *) - Implement the va_end operation...
-GenericValue llvm_va_end(FunctionType *F, const vector<GenericValue> &Args) {
-  assert(Args.size() == 1);
-  return GenericValue();    // Noop!
-}
-
-// <va_list> llvm.va_copy(<va_list>) - Implement the va_copy operation...
-GenericValue llvm_va_copy(FunctionType *F, const vector<GenericValue> &Args) {
-  assert(Args.size() == 1);
-  return Args[0];
-}
-
 } // End extern "C"
 
 
@@ -749,9 +727,5 @@ void Interpreter::initializeExternalFunctions() {
   FuncNames["lle_X_ungetc"]       = lle_X_ungetc;
   FuncNames["lle_X_fprintf"]      = lle_X_fprintf;
   FuncNames["lle_X_freopen"]      = lle_X_freopen;
-
-  FuncNames["lle_X_llvm.va_start"]= llvm_va_start;
-  FuncNames["lle_X_llvm.va_end"]  = llvm_va_end;
-  FuncNames["lle_X_llvm.va_copy"] = llvm_va_copy;
 }
 
index 77c008730ff1565166adbe0e9908daae44fbd8d0..46e5ef0b6ac30ef8591216df20358e2b339d28f2 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #include "Interpreter.h"
-#include "llvm/Module.h"
+#include "llvm/IntrinsicLowering.h"
 #include "llvm/DerivedTypes.h"
+#include "llvm/Module.h"
 using namespace llvm;
 
 /// create - Create a new interpreter object.  This can never fail.
 ///
-ExecutionEngine *Interpreter::create(Module *M){
+ExecutionEngine *Interpreter::create(Module *M, IntrinsicLowering *IL) {
   bool isLittleEndian = false;
   switch (M->getEndianness()) {
   case Module::LittleEndian: isLittleEndian = true; break;
@@ -41,22 +42,29 @@ ExecutionEngine *Interpreter::create(Module *M){
     break;
   }
 
-  return new Interpreter(M, isLittleEndian, isLongPointer);
+  return new Interpreter(M, isLittleEndian, isLongPointer, IL);
 }
 
 //===----------------------------------------------------------------------===//
 // Interpreter ctor - Initialize stuff
 //
-Interpreter::Interpreter(Module *M, bool isLittleEndian, bool isLongPointer)
-  : ExecutionEngine(M), ExitCode(0),
+Interpreter::Interpreter(Module *M, bool isLittleEndian, bool isLongPointer,
+                         IntrinsicLowering *il)
+  : ExecutionEngine(M), ExitCode(0), 
     TD("lli", isLittleEndian, isLongPointer ? 8 : 4, isLongPointer ? 8 : 4,
-       isLongPointer ? 8 : 4) {
+       isLongPointer ? 8 : 4), IL(il) {
 
   setTargetData(TD);
   // Initialize the "backend"
   initializeExecutionEngine();
   initializeExternalFunctions();
   emitGlobals();
+
+  if (IL == 0) IL = new DefaultIntrinsicLowering();
+}
+
+Interpreter::~Interpreter() {
+  delete IL;
 }
 
 void Interpreter::runAtExitHandlers () {
index 1f50777351f3c48fbd1263460f738e15044f0a52..5757327c208cde495d39f26baf29bb0f40accf2d 100644 (file)
@@ -79,6 +79,7 @@ struct ExecutionContext {
 class Interpreter : public ExecutionEngine, public InstVisitor<Interpreter> {
   int ExitCode;                // The exit code to be returned by the lli util
   TargetData TD;
+  IntrinsicLowering *IL;
 
   // The runtime stack of executing code.  The top of the stack is the current
   // function record.
@@ -89,17 +90,20 @@ class Interpreter : public ExecutionEngine, public InstVisitor<Interpreter> {
   std::vector<Function*> AtExitHandlers;
 
 public:
-  Interpreter(Module *M, bool isLittleEndian, bool isLongPointer);
-  inline ~Interpreter() { }
+  Interpreter(Module *M, bool isLittleEndian, bool isLongPointer,
+              IntrinsicLowering *IL);
+  ~Interpreter();
 
   /// runAtExitHandlers - Run any functions registered by the program's calls to
   /// atexit(3), which we intercept and store in AtExitHandlers.
   ///
   void runAtExitHandlers();
 
-  /// create - Create an interpreter ExecutionEngine. This can never fail.
+  /// create - Create an interpreter ExecutionEngine. This can never fail.  The
+  /// specified IntrinsicLowering implementation will be deleted when the
+  /// Interpreter execution engine is destroyed.
   ///
-  static ExecutionEngine *create(Module *M);
+  static ExecutionEngine *create(Module *M, IntrinsicLowering *IL);
 
   /// run - Start execution with the specified function and arguments.
   ///
index 53e8738bb84fb93cfd1d91252f007ffdac4b0814..414d1c6e6832ebffec18d716699be11482afc32f 100644 (file)
@@ -44,9 +44,11 @@ public:
   ~JIT();
 
   /// create - Create an return a new JIT compiler if there is one available
-  /// for the current target.  Otherwise, return null.
+  /// for the current target.  Otherwise, return null.  If the JIT is created
+  /// successfully, it takes responsibility for deleting the specified
+  /// IntrinsicLowering implementation.
   ///
-  static ExecutionEngine *create(ModuleProvider *MP);
+  static ExecutionEngine *create(ModuleProvider *MP, IntrinsicLowering *IL = 0);
 
   /// run - Start execution with the specified function and arguments.
   ///
index 4a381fb5a2dcc8fb8d9e9841698af3a63b81ddc1..0540862870377dd47d0d15445e89b5dd7a8f20d6 100644 (file)
@@ -53,8 +53,9 @@ namespace {
 /// create - Create an return a new JIT compiler if there is one available
 /// for the current target.  Otherwise, return null.
 ///
-ExecutionEngine *JIT::create(ModuleProvider *MP) {
-  TargetMachine* (*TargetMachineAllocator)(const Module &) = 0;
+ExecutionEngine *JIT::create(ModuleProvider *MP, IntrinsicLowering *IL) {
+  TargetMachine* (*TargetMachineAllocator)(const Module &,
+                                           IntrinsicLowering *IL) = 0;
 
   // Allow a command-line switch to override what *should* be the default target
   // machine for this platform. This allows for debugging a Sparc JIT on X86 --
@@ -80,7 +81,7 @@ ExecutionEngine *JIT::create(ModuleProvider *MP) {
 #endif
 
   // Allocate a target...
-  TargetMachine *Target = TargetMachineAllocator(*MP->getModule());
+  TargetMachine *Target = TargetMachineAllocator(*MP->getModule(), IL);
   assert(Target && "Could not allocate target machine!");
 
   // If the target supports JIT code generation, return a new JIT now.