2015-08-04 3 views
0

Я изучаю LLVM, реализуя свой собственный язык игрушек, теперь я столкнулся с проблемой, когда я не могу назвать свои сгенерированные функции, когда функция принимает несколько аргументов. Ниже приводится простой пример воспроизводства я сталкивался до сих пор (неоптимизированном IR для функции принимает два аргумента и возвращает значение второго аргумента):ExecutionEngine LLVM :: runFunction передает неправильные параметры для работы. Зачем?

define i32 @Test_twoArg(i32 %a, i32 %b) { 
entry: 
    %b2 = alloca i32 
    %a1 = alloca i32 
    %returnValue = alloca i32 
    store i32 %a, i32* %a1 
    store i32 %b, i32* %b2 
    %b3 = load i32* %b2, !dbg !8 
    store i32 %b3, i32* %returnValue, !dbg !8 
    br label %exit, !dbg !8 

exit:            ; preds = %entry 
    %returnValue4 = load i32* %returnValue, !dbg !9 
    ret i32 %returnValue4, !dbg !9 
} 

мой Google-тест код выглядит следующим образом, где свалка функция производит выход выше:

TEST_F(BinaryOperatorTest, TwoArg) { 
    compileFunction("int twoArg(int a, int b) { return b; }"); 
    ASSERT_NE((llvm::Module *)NULL, m_module); 

    llvm::Function *llvmFunction = m_module->getFunction("Test_twoArg"); 
    ASSERT_NE((llvm::Function *)NULL, llvmFunction); 

    llvmFunction->dump(); 

    std::vector<llvm::GenericValue> arguments(2); 
    arguments[0].IntVal = llvm::APInt(32, 11); 
    arguments[1].IntVal = llvm::APInt(32, 13); 
    llvm::GenericValue res 
    = m_executionEngine->runFunction(llvmFunction, arguments); 
    EXPECT_EQ(13, res.IntVal); 
} 

и это терпит неудачу с:

binaryoperator_test.cpp:129: Failure 
Value of: res.IntVal 
    Actual: 16-byte object <20-00 00-00 8B-7F 00-00 20-00 00-00 00-00 00-00> 
Expected: 13 

если я изменяю тест, чтобы принимать только один аргумент в качестве входных данных и возвращения аргумент, то он работает. Я использовал lldb проверить сгенерированный код и он выглядит действительным (но не-оптимальное):

(lldb) disassemble 
    0x7ffff7ff4000 <Test_twoArg>: movl %edi, -0x8(%rsp) 
    0x7ffff7ff4004 <Test_twoArg+4>: movl %esi, -0x4(%rsp) 
-> 0x7ffff7ff4008 <Test_twoArg+8>: movl %esi, -0xc(%rsp) 
    0x7ffff7ff400c <Test_twoArg+12>: movl -0xc(%rsp), %eax 
    0x7ffff7ff4010 <Test_twoArg+16>: retq 

но значения регистра неправы (%rsi и %rdi должен содержать 11 и 13):

(lldb) register read 
General Purpose Registers: 
     rax = 0x0000000000a48fef unittests`llvm::MCJIT::runFunction(llvm::Function*, std::vector<llvm::GenericValue, std::allocator<llvm::GenericValue> > const&) + 399 
     rbx = 0x00007fffffffdb70 
     rcx = 0x0000000000000000 
     rdx = 0xffffffffffc3469f 
     rdi = 0x0000000001229328 
     rsi = 0x0000000000000020 
     rbp = 0x0000000000000020 
     rsp = 0x00007fffffffda38 
     r8 = 0x0000000000000000 
     r9 = 0x0000000000000003 
     r10 = 0x0000000000000001 
     r11 = 0x0000000000000088 
     r12 = 0x00007ffff7ff4000 JIT(0x12526d0)`Test_twoArg at unittest.dw:1 
     r13 = 0x0000000001229328 
     r14 = 0x0000000001249690 
     r15 = 0x00007fffffffdb50 
     rip = 0x00007ffff7ff4008 JIT(0x12526d0)`Test_twoArg + 8 at unittest.dw:1 
    rflags = 0x0000000000000246 
     cs = 0x0000000000000033 
     fs = 0x0000000000000000 
     gs = 0x0000000000000000 
     ss = 0x000000000000002b 
     ds = 0x0000000000000000 
     es = 0x0000000000000000 

Итак, похоже, что я вызываю runFunction неправильно, но я не могу понять, как, или это ошибка LLVM? Запуск LLVM-3.6 на Ubuntu, x86-64.

UPDATE: Извлекая указатель на функцию Я могу правильно вызвать функцию, так что это больше похоже на ошибку в runFunction:

int (*function)(int, int) = (int (*)(int, int))m_executionEngine->getPointerToFunction(llvmFunction); 
    int resi = function(11, 13); 
    EXPECT_EQ(13, resi); // works 

ответ

0

Существует действительно проблема с вызовом runFunction при использовании MCJIT, переключившись на интерпретатор как механизм выполнения, все работает так, как ожидалось. Возникает проблема: here: где обрабатываются только некоторые комбинации возвращаемых и аргументов. Поскольку LLVM скомпилирован в NDEBUG, вызов llvm_unreachable в конце - removed and replaced by a hint that the code can't be reached (вероятно, это должно быть обработано лучше, так как, вероятно, я могу поставить точки останова внутри сгенерированной функции).

+0

Кажется, что он закреплен на llvm-багажнике. –

Смежные вопросы