2009-12-03 19 views
22

He generado un archivo bc con el compilador en línea en llvm.org, y me gustaría saber si es posible cargar este archivo bc desde el programa ac o C++, ejecutar el IR en el bc archive con llvm jit (programáticamente en el programa c) y obtenga los resultados.Llamar LLVM Jit desde el programa c

¿Cómo puedo lograr esto?

Respuesta

-3

Desde la línea de comandos, puede usar el programa LLVM lli para ejecutar un archivo bc. Si el archivo está en el lenguaje ensamblador LLVM, deberá ejecutar llvm-as en él primero para crear un archivo binario de código de bits.

Es fácil de hacer esto a partir de C. Me gustaría recomendar nos fijamos en la extensa documentación LLVM: http://llvm.org/docs

el canal de IRC LLVM, que tiene un enlace en esa página, está lleno de personas muy bien que están dispuestos a responder preguntas.

Disculpe por la respuesta indirecta. Yo uso LLVM extensamente, pero hago generación directa de código no solo en tiempo de compilación.

15

Esto debería (más o menos) trabajar usando LLVM 2.6. Parece que hay algunas funciones más auxiliares en SVN para crear un ModuleProvider perezoso sobre un archivo de código de bits. No he intentado compilarlo, solo pegué algunas partes de una de mis aplicaciones JIT.

#include <string> 
#include <memory> 

#include <llvm/Bitcode/ReaderWriter.h> 
#include <llvm/ExecutionEngine/ExecutionEngine.h> 
#include <llvm/ModuleProvider.h> 
#include <llvm/Support/MemoryBuffer.h> 
#include <llvm/ExecutionEngine/JIT.h> 

using namespace std; 
using namespace llvm; 

int main() 
{ 
    InitializeNativeTarget(); 
    llvm_start_multithreaded(); 
    LLVMContext context; 

    string error; 
    auto_ptr<MemoryBuffer> buffer(MemoryBuffer::getFile("bitcode.bc")); 
    auto_ptr<Module> module(ParseBitcodeFile(buffer.get(), context, &error)); 
    auto_ptr<ModuleProvider> mp(new ExistingModuleProvider(module)); 
    module.release(); 

    auto_ptr<ExecutionEngine> ee(ExecutionEngine::createJIT(mp.get(), &error)); 
    mp.release(); 

    Function* func = ee->getFunction("foo"); 

    typedef void (*PFN)(); 
    PFN pfn = reinterpret_cast<PFN>(ee->getPointerToFunction(func)); 
    pfn(); 
} 
23

Aquí hay un código de trabajo basado en Nathan Howell:

#include <string> 
#include <memory> 
#include <iostream> 

#include <llvm/LLVMContext.h> 
#include <llvm/Target/TargetSelect.h> 
#include <llvm/Bitcode/ReaderWriter.h> 
#include <llvm/ExecutionEngine/ExecutionEngine.h> 
#include <llvm/ModuleProvider.h> 
#include <llvm/Support/MemoryBuffer.h> 
#include <llvm/ExecutionEngine/JIT.h> 

using namespace std; 
using namespace llvm; 

int main() 
{ 
    InitializeNativeTarget(); 
    llvm_start_multithreaded(); 
    LLVMContext context; 
    string error; 
    Module *m = ParseBitcodeFile(MemoryBuffer::getFile("tst.bc"), context, &error); 
    ExecutionEngine *ee = ExecutionEngine::create(m); 

    Function* func = ee->FindFunctionNamed("main"); 

    typedef void (*PFN)(); 
    PFN pfn = reinterpret_cast<PFN>(ee->getPointerToFunction(func)); 
    pfn(); 
    delete ee; 
} 

Una rareza era que sin la final incluyen, ee es NULL. Extraño.

Para generar mi tst.bc, utilicé http://llvm.org/demo/index.cgi y la herramienta de línea de comandos llvm-as.

+1

Doh, #including es necesario para obligar al vinculador a extraer el JIT, de lo contrario, se descartaría. Actualizaré mi muestra. –

+0

¿Hay c api para hacer esto? – Ariel

+1

Ariel: sí, la mayoría de LLVM se puede usar desde la C simple, utilizando enlaces suministrados con LLVM. Ver http://llvm.org/docs/FAQ.html#langirgen y http://npcontemplation.blogspot.com/2008/06/secret-of-llvm-c-bindings.html –