2014-01-16 2 views
2

Моей программы, которая JIT компилирует модуль LLVM IR и вызывает функцию foo определенных в ней терпит неудачу во время выполнения, если foo использует внешне определенную функцию:LLVM JIT-компилируются программа не может найти внешние функции

LLVM ERROR: Program used external function 'glutInit' which could not be resolved! 

Моей программу:

// foo1.cpp 
#include <GL/glut.h> 

extern "C" void foo() 
{ 
    glutInit(0,0); 
} 

// foo2.cpp 
#include <iostream> 
#include <fstream> 
#include <string> 

#include <llvm/Support/raw_ostream.h> 
#include <llvm/LLVMContext.h> 
#include <llvm/Support/TargetSelect.h> 
#include <llvm/Support/IRReader.h> 
#include <llvm/ExecutionEngine/ExecutionEngine.h> 
#include <llvm/Support/MemoryBuffer.h> 
#include <llvm/ExecutionEngine/JIT.h> 
#include <llvm/ExecutionEngine/RuntimeDyld.h> 

int main(int argc, char **argv) 
{ 
    using namespace llvm; 
    InitializeNativeTarget(); 

    LLVMContext context; 
    SMDiagnostic error; 

    std::ifstream ir_file("foo1.s"); 
    std::string ir((std::istreambuf_iterator<char>(ir_file)), 
       (std::istreambuf_iterator<char>())); 

    Module *m = ParseIR(MemoryBuffer::getMemBuffer(StringRef(ir)), error, context); 
    if(!m) 
    { 
    error.print(argv[0], errs()); 
    } 

    ExecutionEngine *ee = ExecutionEngine::create(m); 

    Function *func = ee->FindFunctionNamed("foo"); 
    if(func == 0) 
    { 
    std::cerr << "Couldn't find Function foo" << std::endl; 
    std::exit(-1); 
    } 

    typedef void (*fcn_ptr)(); 
    fcn_ptr foo = reinterpret_cast<fcn_ptr>(ee->getPointerToFunction(func)); 
    foo(); 
    delete ee; 

    return 0; 
} 

Вот как я строить свою программу:

$ clang -S -emit-llvm foo1.cpp 
$ g++ -rdynamic foo2.cpp `llvm-config --cxxflags` `llvm-config --libs` `llvm-config --ldflags` -lglut 

Выход:

$ ./a.out 
LLVM ERROR: Program used external function 'glutInit' which could not be resolved! 

Это терпит неудачу с подобной ошибкой в ​​любое время, когда я пытаюсь использовать наружно определенную функцию, которая не находится в стандартной библиотеке C++ (например, printf, malloc, & free не проблема) , Что я делаю не так?

ответ

3

Убедившись, что glutInit было связано с a.out. Если ваш хост-код (вещь, выполняющая JIT) не назвал его, он мог бы быть смешано с компоновщиком. Если это так, вам нужно добавить к нему фиктивную ссылку или использовать скрипты/флаги компоновщика.

+0

Спасибо, распечатав адрес 'glutInit' достаточно сделайте JIT успешным, так что это похоже на то, что компоновщик бросает символ. Я думал, что флага '-rdynamic' достаточно для сохранения символов без ссылок? –

2

Добавление опции командной строки -Wl,-no-as-needed непосредственно перед -lglut предотвратит линкер закапывание glut библиотеку, которую он иначе думает не требуется:

$ g++ -rdynamic foo2.cpp `llvm-config --cxxflags` `llvm-config --libs` `llvm-config --ldflags` -Wl,-no-as-needed -lglut