[LLVMdev] Newbie JITter
Evan Cheng
evan.cheng at apple.com
Fri Nov 9 00:20:36 PST 2007
On Nov 7, 2007, at 6:10 PM, Antony Blakey wrote:
> Hi,
> I'm experimenting with using LLVM to generate dynamic FFI bridges
> in VisualWorks Smalltalk. LLVM is an amazing thing! I'm going from
> dynamically generated assembler source to machine code, and I have
> that all working, copied from the llc tool and the JIT example. I
> have two questions:
>
> 1. What optimization passes, if any, should I run on the module
> before I pass it to the ExecutionEngine.
The default JIt driver, lli, runs everything. Code generation are
almost the same whether you do dynamic compilation or static
compilation (except for relocation-model / code-model used). You can
pick and choose what passes to run if compile time is a concern. You
can use
> 2. Do I need to retain the Module/ExistingModuleProvider, once I've
> built the ExecutionEngine and have a Function object. Or is there
> some simpler way to store/call the native code block?
I don't think it's safe to free Module early if you are using lazy
compilation. If that's disabled, I suppose it's safe to delete Module
once all references are resolved and relocated. Chris, can you confirm?
Don't understand your last question.
>
> An unrelated question: I want to dump the native assembler form of
> the code generated by the JIT. Currently I dump it using some code I
> adapted from llc, but that's not actually showing what the JIT is
> generating. How can I dump the JIT generated code, as native
> assembler? It's a debugging requirement only.
I think there is disassembly capability built-in. See JITEmitter.cpp
Evan
>
> My test code is as follows, much of which is to do with generating
> the native assembler output.
>
> #include "llvm/Module.h"
> #include "llvm/Assembly/Parser.h"
> #include "llvm/Analysis/Verifier.h"
> #include "llvm/ModuleProvider.h"
> #include "llvm/ExecutionEngine/JIT.h"
> #include "llvm/System/Signals.h"
> #include "llvm/ExecutionEngine/GenericValue.h"
> #include "llvm/PassManager.h"
> #include "llvm/CodeGen/Passes.h"
> #include "llvm/Target/TargetData.h"
> #include "llvm/Target/TargetMachine.h"
> #include "llvm/Target/TargetMachineRegistry.h"
> #include <iostream>
> using namespace llvm;
>
> int main() {
> sys::PrintStackTraceOnErrorSignal();
>
> const char* assembler =
> "@.LC0 = internal constant [19 x i8] c\"cooking with gas!\\0A\\00
> \" ; [11 x i8]*\n"
> "\n"
> "declare i32 @puts(i8 *) ;
> i32(i8 *)* \n"
> "\n"
> "define i32 @main() { ;
> i32()* \n"
> " ; Convert [19 x i8 ]* to i8 *...\n"
> " %cast210 = getelementptr [19 x i8]* @.LC0, i64 0, i64 0 ; i8
> *\n"
> " call i32 @puts(i8 * %cast210) ;
> i32\n"
> " ret i32 0\n"
> "};\n";
>
> int exitCode = 0;
> try {
> ParseError ParseErr;
> Module* M = ParseAssemblyString(assembler, new Module("test"),
> &ParseErr);
> if (!M) {
> cerr << "parse error: " << ParseErr.getMessage() << "\n";
> return 1;
> }
>
> std::cout << "\nWe just constructed this LLVM module:\n\n" << *M;
>
> std::string MArchErr;
> const TargetMachineRegistry::entry* MArch =
> TargetMachineRegistry::getClosestStaticTargetForModule(*M, MArchErr);
> if (MArch == 0) {
> std::cerr << "error auto-selecting target for module '" <<
> MArchErr << "'.\n";
> return 1;
> }
>
> TargetMachine* target = MArch->CtorFn(*M, "");
> assert(target && "Could not allocate target machine!");
>
> FunctionPassManager Passes(new ExistingModuleProvider(M));
> Passes.add(new TargetData(*target->getTargetData()));
>
> Passes.add(createVerifierPass());
>
> switch (target->addPassesToEmitFile(Passes, std::cout,
> TargetMachine::AssemblyFile, false)) {
> default:
> assert(0 && "Invalid file model!");
> return 1;
> case FileModel::MachOFile:
> case FileModel::ElfFile:
> case FileModel::Error:
> std::cerr << "target does not support generation of this file
> type!\n";
> return 1;
> case FileModel::AsmFile:
> break;
> }
>
> MachineCodeEmitter *MCE = 0;
> if (target->addPassesToEmitFileFinish(Passes, MCE, false)) {
> std::cerr << "target does not support generation of this file type!
> \n";
> return 1;
> }
>
> std::cout << "\nWhich has this machine code form:";
>
> Passes.doInitialization();
>
> for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
> if (!I->isDeclaration())
> Passes.run(*I);
>
> Passes.doFinalization();
>
> ExistingModuleProvider* MP = new ExistingModuleProvider(M);
> ExecutionEngine* EE = ExecutionEngine::create(MP, false);
>
> Function *MainFunction = M->getFunction("main");
> if (!MainFunction) {
> std::cerr << "'main' function not found in module.\n";
> return -1;
> }
>
> std::cout << "\n\nRunning main: " << std::flush;
>
> // Call the function with no arguments:
> std::vector<GenericValue> noargs;
> GenericValue gv = EE->runFunction(MainFunction, noargs);
>
> // Import result of execution:
> std::cout << "Result: " << gv.IntVal.toStringUnsigned(10) << "\n";
>
> } catch (const std::string& msg) {
> cerr << "exception: " << msg << "\n";
> exitCode = 1;
> } catch (...) {
> cerr << "exception: Unexpected unknown exception occurred.\n";
> exitCode = 1;
> }
>
> return exitCode;
> }
>
> Thanks,
>
> Antony Blakey
> --------------------------
> CTO, Linkuistics Pty Ltd
> Ph: 0438 840 787
>
> Plurality is not to be assumed without necessity
> -- William of Ockham (ca. 1285-1349)
>
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
More information about the llvm-dev
mailing list