Я изучаю 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
Кажется, что он закреплен на llvm-багажнике. –