[pypy-svn] r25031 - in pypy/dist/pypy/translator/llvm/pyllvm: . test

ericvrp at codespeak.net ericvrp at codespeak.net
Mon Mar 27 14:45:21 CEST 2006


Author: ericvrp
Date: Mon Mar 27 14:45:20 2006
New Revision: 25031

Modified:
   pypy/dist/pypy/translator/llvm/pyllvm/pyllvm.cpp
   pypy/dist/pypy/translator/llvm/pyllvm/test/test_ee.py
Log:
Added function replacement to pyllvm.
Added display of generated JIT code.
Added delete function.


Modified: pypy/dist/pypy/translator/llvm/pyllvm/pyllvm.cpp
==============================================================================
--- pypy/dist/pypy/translator/llvm/pyllvm/pyllvm.cpp	(original)
+++ pypy/dist/pypy/translator/llvm/pyllvm/pyllvm.cpp	Mon Mar 27 14:45:20 2006
@@ -14,6 +14,10 @@
 #include "llvm/Analysis/Verifier.h"
 #include "llvm/DerivedTypes.h"
 
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Target/TargetOptions.h"
+
+
 // c++ includes
 #include <string>
 #include <iostream>
@@ -61,26 +65,41 @@
 
   // parse and verify llcode
   try {
+    Module *M = &self->exec->getModule();
+
     if (fnname) {
-      // XXX ParseAssemblyString(llcode, &self->exec->getModule()); //redefinition
-      /*Module*   M  =*/ ParseAssemblyString(llcode, NULL);
-      Function *fn = self->exec->getModule().getNamedFunction(std::string(fnname));
-      if (fn == NULL) {
+      Function *F = M->getNamedFunction(fnname);
+      if (F == NULL) {
         PyErr_SetString(PyExc_Exception, "Failed to resolve function to be replaced");
         return NULL;
       }
-      self->exec->recompileAndRelinkFunction(fn);
-
-      // TODO replace fn with whatever ParseAssemblyString made of llcode
-
-      PyErr_SetString(PyExc_Exception, "function replacing not supported yet");
-      return NULL;
-
+      F->setName(""); // now it won't conflicht
+      ParseAssemblyString(llcode, M);
+      Function *Fnew = M->getNamedFunction(fnname);
+      F->replaceAllUsesWith(Fnew); // Everything using the old one uses the new one
+      self->exec->freeMachineCodeForFunction(F); // still no-op on march 27th 2006
+      F->eraseFromParent(); // also, take it out of the JIT (LLVM IR) if it was in it
+
+      /*
+      XXX this is a really dump implementation!!! Should really be somehthing like...
+      codegend_uses = list of function that have codegen'd calls to F
+      for func in codegend_uses:
+          self->exec->recompileAndRelinkFunction(func);
+      // what about (codegen-ed) pointers to F?
+      */
+      Module::FunctionListType &fns = M->getFunctionList();
+      for (Module::FunctionListType::iterator ii = fns.begin();
+           ii != fns.end();
+           ++ii) {
+        if (!(ii->isIntrinsic() || ii->isExternal())) {
+          self->exec->recompileAndRelinkFunction(ii);
+        }
+      }
     } else {
-      ParseAssemblyString(llcode, &self->exec->getModule());
+      ParseAssemblyString(llcode, M);
     }
 
-    verifyModule(self->exec->getModule(), ThrowExceptionAction);
+    verifyModule(*M, ThrowExceptionAction);  // XXX make this optional for performance?
     Py_INCREF(Py_None);
     return Py_None;
 
@@ -193,9 +212,9 @@
   char *fnname = PyString_AsString(pyfnname);
     
   try {
-    Function *fn = self->exec->getModule().getNamedFunction(std::string(fnname));
+    Function *fn = self->exec->getModule().getNamedFunction(fnname);
     if (fn == NULL) {
-      PyErr_SetString(PyExc_Exception, "Failed to resolve function");
+      PyErr_SetString(PyExc_Exception, "Failed to resolve function to call");
       return NULL;
     }
 
@@ -223,6 +242,39 @@
   }
 }
 
+static PyObject *ee_delete(PyExecutionEngine *self, PyObject *args) {
+
+  if (PyTuple_Size(args) != 1) {
+    PyErr_SetString(PyExc_TypeError, "missing functionname");
+    return NULL;
+  }
+
+  PyObject *pyfnname = PyTuple_GetItem(args, 0); 
+  if (!PyString_Check(pyfnname)) {
+    PyErr_SetString(PyExc_TypeError, "functionname expected as string");
+    return NULL;
+  }
+  char *fnname = PyString_AsString(pyfnname);
+    
+  try {
+    Function *fn = self->exec->getModule().getNamedFunction(fnname);
+    if (fn == NULL) {
+      PyErr_SetString(PyExc_Exception, "Failed to resolve function to delete");
+      return NULL;
+    }
+
+    // XXX fn should not be refered to from anywhere! Check for this?
+    self->exec->freeMachineCodeForFunction(fn); // still no-op on march 27th 2006
+    fn->eraseFromParent();
+  } catch (...) {
+    PyErr_SetString(PyExc_Exception, "Unexpected unknown exception occurred");
+    return NULL;
+  }
+  
+  Py_INCREF(Py_None);
+  return Py_None;
+}
+
 static PyObject *ee_functions(PyExecutionEngine *self) {
   int funccount = 0;
   Module::FunctionListType &fns = self->exec->getModule().getFunctionList();
@@ -267,9 +319,10 @@
 }
 
 static PyMethodDef ee_methodlist[] = {
-  {"parse", (PyCFunction) ee_parse, METH_VARARGS, NULL},
-  {"functions", (PyCFunction) ee_functions, METH_NOARGS, NULL},
-  {"call", (PyCFunction) ee_call, METH_VARARGS, NULL},
+  {"parse"    , (PyCFunction) ee_parse    , METH_VARARGS, NULL},
+  {"call"     , (PyCFunction) ee_call     , METH_VARARGS, NULL},
+  {"delete"   , (PyCFunction) ee_delete   , METH_VARARGS, NULL},
+  {"functions", (PyCFunction) ee_functions, METH_NOARGS , NULL},
 
   {NULL, NULL}
 };
@@ -380,9 +433,17 @@
   return Py_None;
 }
 
+static PyObject *pyllvm_toggle_print_machineinstrs(PyObject *self, PyObject *args) {
+  PrintMachineCode = !PrintMachineCode;
+  
+  Py_INCREF(Py_None);
+  return Py_None;
+}
+
 PyMethodDef pyllvm_functions[] = {
-  {"get_ee", pyllvm_get_ee, METH_NOARGS, NULL},
-  {"delete_ee", pyllvm_delete_ee, METH_NOARGS, NULL},
+  {"get_ee"                    , pyllvm_get_ee                    , METH_NOARGS, NULL},
+  {"delete_ee"                 , pyllvm_delete_ee                 , METH_NOARGS, NULL},
+  {"toggle_print_machineinstrs", pyllvm_toggle_print_machineinstrs, METH_NOARGS, NULL},
   {NULL, NULL}
 };
 
@@ -402,6 +463,11 @@
   PyModule_AddObject(module, "ExecutionEngine", 
 		     (PyObject*) &ExecutionEngine_Type);
 
+  if (0) { // pass in `lli` type parameters
+    static char * Args[] = { "", "-print-machineinstrs", 0 };
+    int n_args = 2;
+    cl::ParseCommandLineOptions(n_args, Args);
+  }
 }
 
 }

Modified: pypy/dist/pypy/translator/llvm/pyllvm/test/test_ee.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/pyllvm/test/test_ee.py	(original)
+++ pypy/dist/pypy/translator/llvm/pyllvm/test/test_ee.py	Mon Mar 27 14:45:20 2006
@@ -82,12 +82,11 @@
     """similar to test_call_between_parsed_code with additional complexity
     because we rebind the add1 function to another version after it the
     first version already has been used."""
-    py.test.skip("function replacement support in progress")
     ee = get_fresh_ee()
     ee.parse(ll_snippet.calc)
     ee.parse(ll_snippet.add1)
     assert ee.call("add1", 41) == 42
-    assert ee.call("calc", 122) == 123
+    assert ee.call("calc", 122) == 123 #XXX need recompileAndRelinkFunction somewhere
     ee.parse(ll_snippet.add1_version2, "add1")
     assert ee.call("add1", 42) == 142
     assert ee.call("calc", 142) == 242
@@ -102,11 +101,30 @@
     assert ee.call("add1_to_global_int_a") == 92
     assert ee.call("sub10_from_global_int_a") == 82
 
-def TODOtest_native_code(): #examine JIT generate native (assembly) code
-    pass
+def test_native_code(): #examine JIT generate native (assembly) code
+    pyllvm.toggle_print_machineinstrs()
+    ee = get_fresh_ee()
+    ee.parse(ll_snippet.calc)
+    ee.parse(ll_snippet.add1)
+    assert ee.call("calc", 41) == 42
+    pyllvm.toggle_print_machineinstrs()
 
-def TODOtest_delete_function():
-    pass
+def test_delete_function(): #this will only work if nothing uses Fn of course!
+    ee = get_fresh_ee()
+    ee.parse(ll_snippet.calc)
+    ee.parse(ll_snippet.add1)
+    assert len(ee.functions()) == 2
+
+    ee.delete("calc")
+    assert len(ee.functions()) == 1
+    assert ee.call("add1", 41) == 42
+
+    ee.delete("add1")
+    assert len(ee.functions()) == 0
+
+    ee.parse(ll_snippet.calc)
+    ee.parse(ll_snippet.add1)
+    assert ee.call("calc", 100) == 101
 
 def TODOtest_add_to_function():
     pass



More information about the Pypy-commit mailing list