Rub*_*ens 6 c++ linker llvm undefined-reference llvm-ir
我使用LLVM传递为输入代码添加了内在函数.我能够看到内部调用,但我无法弄清楚如何将代码编译到我的目标体系结构(x86_64).我正在运行以下命令:
clang++ $(llvm-config --ldflags --libs all) ff.s -o foo
Run Code Online (Sandbox Code Playgroud)
但链接器抱怨未定义的引用:
/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'
Run Code Online (Sandbox Code Playgroud)
尽管使用llvm-config中的ldflags,但编译仍未进行.关于应该如何正确编译代码的任何想法?
要生成汇编代码,我已完成以下操作:
# 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
Run Code Online (Sandbox Code Playgroud)
我目前正在使用llvm版本3.4.2; clang版本3.4.2(标签/ RELEASE_34/dot2-final); gcc版本4.9.2(GCC); 和Linux 3.17.2-1-ARCH x86_64.
编辑:添加内在的IR:
文件〜/ llvm/include/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 }
...
Run Code Online (Sandbox Code Playgroud)
和调用(来自文件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
...
Run Code Online (Sandbox Code Playgroud)
编辑2:这是我在opt pass中添加内在函数的方式:
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);
Run Code Online (Sandbox Code Playgroud)
编辑: 我目前正在写一个LLVM通行证,基本上做你在这个问题中尝试做的事情.您的代码存在以下问题:
std::vector<Type *> types(2, Type::getInt32Ty(getGlobalContext()));
Function *mwait = Intrinsic::getDeclaration(m, Intrinsic::x86_sse3_mwait, types);
Run Code Online (Sandbox Code Playgroud)
您正试图获取名为llvm.x86.sse3.mwait.i32.i32的Intrinsic函数的减速,并且此Intrinsic不存在.但是,llvm.x86.sse3.mwait存在,因此你必须写这个:
Function *mwait = Intrinsic::getDeclaration(m, Intrinsic::x86_sse3_mwait);
Run Code Online (Sandbox Code Playgroud)
注意调用的缺失类型参数.这是因为llvm.x86.sse3.mwait没有过载.
我希望你能在此期间弄明白.
好吧,因为我想能够回答你一段时间这里是一个疯狂的猜测答案.
问题是通过优化器传递添加内在函数的方式.看起来你只是创建一个与内在同名而不是内在本身的函数.
这里有一个小C++代码,只使用内置的clang来获取IR内部的内在函数(我使用clang 3.5,但这不应该有任何影响).
int main ()
{
__builtin_ia32_mwait(4,2);
}
Run Code Online (Sandbox Code Playgroud)
用它来编译它clang -emit-llvm -S得到:
; ModuleID = 'intrin.cpp'
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; Function Attrs: nounwind uwtable
define i32 @main() #0 {
call void @llvm.x86.sse3.mwait(i32 4, i32 2)
ret i32 0
}
; Function Attrs: nounwind
declare void @llvm.x86.sse3.mwait(i32, i32) #1
attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { nounwind }
!llvm.ident = !{!0}
!0 = metadata !{metadata !"clang version 3.5.0 "}
Run Code Online (Sandbox Code Playgroud)
请注意,SSE3内在函数没有像您的版本那样的类型重载.
在生成的文件上使用llc为我提供:
.Ltmp2:
.cfi_def_cfa_register %rbp
movl $4, %ecx
movl $2, %eax
mwait
xorl %eax, %eax
popq %rbp
retq
Run Code Online (Sandbox Code Playgroud)
正确的装配已创建.
所以我假设你在函数传递中引入函数的内在方式是错误的.
获取内在函数并调用它:
vector<Type*> types;
types.push_back(IntegerType::get(/*LLVM context*/, 32));
types.push_back(IntegerType::get(/*LLVM context*/, 32));
Function* func = Intrinsic::getDeclaration(/* module */, Intrinsic::x86_sse3_mwait, types);
CallInst* call = CallInst::Create(func, /* arguments */);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1724 次 |
| 最近记录: |