> So as it stands, one should think of out JIT as something akin to the > early Java JITs: one function at a time and only one compile per > function. This is extremely primative by modern JIT standards, where a > JIT will do profiling, find hot functions and reoptimize them, > reoptimize functions when more information about the call tree is > available, have several levels of optimizations, etc.While this is extremely primative by modern JIT standards, it is extremely good by modern Open Source standards, so I'm quite thankfull for it. If no one else does, this is something I'll invenstigate in the future.> > Does there happen to be a C interface to the jit ? Our scheme impl > > has a good FFI, but it doesn't do C++. If not, this is no big deal, > > and i'll just write something myself. > > No, but such bindings would be *very useful*. And since there might be > other people who need them this summer, such work might also get a lot > of help.I'll probably wind up writing one, and if I do, I will certainly submit it - it seems like it should just be gluing a bunch of functions together and proving an 'extern "C" ' decleration. What sort of interface should such an interface provide? The simplest is "pass-in-a-string-to-compile", but that's rather crude. -- -Alex
On Thu, 5 May 2005, Alexander Friedman wrote:>>> Does there happen to be a C interface to the jit ? Our scheme impl >>> has a good FFI, but it doesn't do C++. If not, this is no big deal, >>> and i'll just write something myself. >> >> No, but such bindings would be *very useful*. And since there might be >> other people who need them this summer, such work might also get a lot >> of help. > > I'll probably wind up writing one, and if I do, I will certainly > submit it - it seems like it should just be gluing a bunch of > functions together and proving an 'extern "C" ' decleration. > > What sort of interface should such an interface provide? The simplest > is "pass-in-a-string-to-compile", but that's rather crude.To me, the best interface is the most simple: I would suggest just wrapping the llvm classes and methods you need with simple functions, e.g. llvm_function_new/llvm_value_set_name/llvm_executionengine_run_function, etc. If kept simple, standardized, and generic, I think it would be very useful to people (even if incomplete). This would allow others to build on it, and we could 'ship' it as a standard llvm library. -Chris -- http://nondot.org/sabre/ http://llvm.cs.uiuc.edu/
On May 9, Chris Lattner wrote:> To me, the best interface is the most simple: I would suggest just > wrapping the llvm classes and methods you need with simple functions, e.g. > > llvm_function_new/llvm_value_set_name/llvm_executionengine_run_function, > etc. > > If kept simple, standardized, and generic, I think it would be very useful > to people (even if incomplete). This would allow others to build on it, > and we could 'ship' it as a standard llvm library.Well, it seems that this is actually the next thing on my to-do list. I'll have something simple in a few days - where/how should I post stuff to get some criticism? Also, how are calling conventions/tail calls progressing? -- -Alex
> llvm_function_new/llvm_value_set_name/llvm_executionengine_run_function, > etc. > > If kept simple, standardized, and generic, I think it would be very useful > to people (even if incomplete). This would allow others to build on it, > and we could 'ship' it as a standard llvm library.It looks like my interface will look vaguely like this. Functions like "llvm_make_module" will take in text representations of the module. This seems to be the fastest way of getting our scheme implementation to talk to the jit. This requires being able to parse strings. The LLVM 'Parser.h' interface (and implementation) has the built in assumptions that it will always be parsing from the file system. Would you guys accept a patch that makes it more general (ie, parse from file or string)? If so, what's an easy way to do it? Is it possible to have a "FILE" struct backed by a string? FYI, here is a sketch of what the fib example would look like: #include "llvm_c.h" /* Everything takes and recieves void * pointers. This to avoid redefining C++ types. This is the C 'version' of the Fib example, at least in spirit. */ char* fib_function "int %fib (int %AnArg) {" " EntryBlock: " " %cond = setle int AnArg, 2" " branch bool %cond, label return, label recur" " return:" " ret int 1" " recur:" " %sub1 = sub int %AnArg, 1" " %fibx1 = call tail int %fib (int %sub1) " " %sub2 = sub int %AnArg, 2" " %fibx2 = call tail int %fib (int %sub2) " " %result = add int %fibx1, %fibx2" " ret int %result" "}"; void * M = llvm_make_module_from_text (program, "test") ; // now we want to run some optimizations on this thing. // make a pass manager void * PM = llvm_make_pass_manager(); // add 'target data' to module llvm_addPass(PM, make_target_data("jit-lib",M)); llvm_addPass (PM, llvm_createVerifierPass()); // add optimization passes here // addPass (PM, ... ) llvm_run_passes(PM,M); // merge modules - not relevant here // make an execution engine from the module void * JE = llvm_make_jit_engine (M); // get a function pointer by name. If you have several functions with the same // name, you are out of luck int (*fib) (int) = (int (*)(int)) llvm_get_function_pointer(JE,M,"fib"); // the above cast is probably wrong. int result =fib (24); -- -Alex