Я добавил внутреннее значение коду ввода с использованием прохода LLVM. Я могу видеть внутренний вызов, но я не могу понять, как скомпилировать код для моей целевой архитектуры (x86_64). Я запускаю следующую команду:Добавление intrinsics с использованием пропусков LLVM
clang++ $(llvm-config --ldflags --libs all) ff.s -o foo
Но компоновщик жалуется на неопределенные ссылки:
/tmp/ff-2ada42.o: In function `fact(unsigned int)':
/home/rubens/Desktop/ff.cpp:9: undefined reference to `llvm.x86.sse3.mwait.i32.i32'
/tmp/ff-2ada42.o: In function `fib(unsigned int)':
/home/rubens/Desktop/ff.cpp:16: undefined reference to `llvm.x86.sse3.mwait.i32.i32'
/home/rubens/Desktop/ff.cpp:16: undefined reference to `llvm.x86.sse3.mwait.i32.i32'
/home/rubens/Desktop/ff.cpp:16: undefined reference to `llvm.x86.sse3.mwait.i32.i32'
Несмотря на использование LDFLAGS из LLVM-конфигурации, компиляция не проходит. Любые идеи о том, что следует делать для правильного компиляции кода?
Чтобы сгенерировать код сборки, я сделал следующее:
# Generating optimized code
clang++ $(llvm-config --cxxflags) -emit-llvm -c ff.cpp -o ff.bc
opt ff.bc -load path/to/mypass.so -mypass > opt_ff.bc
# Generating assembly
llc opt_ff.bc -o ff.s
Я в настоящее время использую LLVM версии 3.4.2; clang version 3.4.2 (теги/RELEASE_34/dot2-final); gcc версия 4.9.2 (GCC); и Linux 3.17.2-1-ARCH x86_64.
Edit: добавление IR с собственными:
Файл ~/LLVM/включать/LLVM/IR/IntrinsicsX86.td:
...
589 // Thread synchronization ops.
590 let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
591 def int_x86_sse3_monitor : GCCBuiltin<"__builtin_ia32_monitor">,
592 Intrinsic<[], [llvm_ptr_ty,
593 llvm_i32_ty, llvm_i32_ty], []>;
594 def int_x86_sse3_mwait : GCCBuiltin<"__builtin_ia32_mwait">,
595 Intrinsic<[], [llvm_i32_ty,
596 llvm_i32_ty], []>;
597 }
...
И звонки (из ff.s файлов):
...
.Ltmp2:
callq llvm.x86.sse3.mwait.i32.i32
movl $_ZStL8__ioinit, %edi
callq _ZNSt8ios_base4InitC1Ev
movl $_ZNSt8ios_base4InitD1Ev, %edi
movl $_ZStL8__ioinit, %esi
movl $__dso_handle, %edx
callq __cxa_atexit
popq %rax
ret
...
Edit 2: Вот как я добавляю характеристическая во время отказа прохода:
Function *f(bb->getParent());
Module *m(f->getParent());
std::vector<Type *> types(2, Type::getInt32Ty(getGlobalContext()));
Function *mwait = Intrinsic::getDeclaration(m, Intrinsic::x86_sse3_mwait, types);
std::vector<Value *> args;
IRBuilder<> builder(&bb->front());
for (uint32_t i : {1, 2}) args.push_back(builder.getInt32(i));
ArrayRef<Value *> args_ref(args);
builder.CreateCall(mwait, args_ref);
вы можете поделиться LLVM IR с внутренней с обоими: призыв к внутренней и там декларации? –
@MichaelHaidl Я добавил информацию о запросе. Я ожидал, что инкрементные вызовы будут расширены в ассоциированные встроенные, но вызов остается в файле сборки после компиляции. – Rubens
Я говорил о LLVM IR. Вы можете использовать llvm-dis, чтобы сделать ваши .bc-файлы доступными для чтения или передать -S, чтобы выбрать. было бы также интересно, как вы добавляете внутренний и вызов в свой пропуск opt. в настоящее время выглядит так, что вызванная функция не является внутренней только функцией с тем же именем, что и внутренняя llvm. –