sdg*_*sdh 15 c++ llvm llvm-ir lli
我一直在尝试构建和执行LLVM模块.我生成模块的代码很长,所以我不会在这里发布.相反,我的问题是Clang和LLVM如何协同工作来实现名称修改.我会解释我的具体问题来激发这个问题.
以下是我的一个LLVM模块的源代码:
#include <iostream>
int main() {
std::cout << "Hello, world. " << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是生成的LLVM IR ; 它对于StackOverflow来说太大了.
当我尝试使用我的模块时lli,我收到以下错误:
LLVM错误:程序使用了无法解析的外部函数'__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1Emc'!
通过demangler运行符号,缺少的符号是:
_std :: __ 1 :: basic_string,std :: __ 1 :: allocator> :: basic_string(unsigned long,char)
额外_是可疑的,没有前导下划线的功能似乎存在于IR中!
; Function Attrs: alwaysinline ssp uwtable
define available_externally hidden void @_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1Emc(%"class.std::__1::basic_string"*, i64, i8 signext) unnamed_addr #2 align 2 {
%4 = alloca %"class.std::__1::basic_string"*, align 8
%5 = alloca i64, align 8
%6 = alloca i8, align 1
store %"class.std::__1::basic_string"* %0, %"class.std::__1::basic_string"** %4, align 8
store i64 %1, i64* %5, align 8
store i8 %2, i8* %6, align 1
%7 = load %"class.std::__1::basic_string"*, %"class.std::__1::basic_string"** %4, align 8
%8 = load i64, i64* %5, align 8
%9 = load i8, i8* %6, align 1
call void @_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2Emc(%"class.std::__1::basic_string"* %7, i64 %8, i8 signext %9)
ret void
}
Run Code Online (Sandbox Code Playgroud)
我在macOS上,所以预计会有一个领先的下划线,但我认为Clang可能会添加两次.
我查看了LLVM/Clang源代码,看起来有两个错误的步骤:
但是,这只是我的理论.有人可以解释一下在Clang和LLVM中修剪过程是如何工作的吗?我应该如何创建我的llvm::DataLayout对象以获得我的平台的正确修改?
nm -gU /usr/lib/libc++.dylib并且nm -gU /usr/lib/libc++abi.dylib不包含__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorI??cEEEC1Emc
当我尝试编译IR时,我收到此错误:
llc generated.ll
clang++ generated.s
Run Code Online (Sandbox Code Playgroud)
体系结构x86_64的未定义符号:"std :: __ 1 :: basic_string,std :: __ 1 :: allocator> :: data()const",引用自:std :: __ 1 :: ostreambuf_iterator> std :: __ 1 :: __ pad_and_output> (std :: __ 1 :: ostreambuf_iterator>,char const*,char const*,char const*,std :: __ 1 :: ios_base&,char)in generated-b4252a.o"std :: __ 1 :: basic_ostream> :: sentry :: operator bool()const",引用自:std :: __ 1 :: basic_ostream>&std :: __ 1 :: __ put_character_sequence>(std :: __ 1 :: basic_ostream>&,char const*,unsigned long)in generated- b4252a.o"std :: __ 1 :: basic_ios> :: fill()const",引自:std :: __ 1 :: basic_ostream>&std :: __ 1 :: __ put_character_sequence>(std :: __ 1 :: basic_ostream>& ,char const*,unsigned long)in generated-b4252a.o"std :: __ 1 :: basic_ios> :: rdbuf()const",引用自:std :: __ 1 :: ostreambuf_iterator> :: ostreambuf_iterator(std :: __ 1 :: basic_ostream>&)in generated-b4252a.o"std :: __ 1 :: basic_ios> :: widen(char)const",引自:std :: __ 1 :: basic_ostream>&std :: __ 1 :: endl> (标准:: __ 1 :: BAS ic_ostream>&)in generated-b4252a.o"std :: __ 1 :: basic_string,std :: __ 1 :: allocator> :: basic_string(unsigned long,char)",引自:std :: __ 1 :: ostreambuf_iterator> std :: __ 1 :: __ pad_and_output>(std :: __ 1 :: ostreambuf_iterator>,char const*,char const*,char const*,std :: __ 1 :: ios_base&,char)in generated-b4252a.o"std :: __ 1 :: basic_ios> :: setstate(unsigned int)",引自:std :: __ 1 :: basic_ostream>&std :: __ 1 :: __ put_character_sequence>(std :: __ 1 :: basic_ostream>&,char const*,unsigned long )in generated-b4252a.o ld:找不到架构x86_64 clang-3.9的符号:错误:链接器命令失败,退出代码为1(使用-v查看调用)
我不会怀疑名称损坏问题。C++ 名称修改发生在前端(即clang),它是定义良好/记录良好的ABI 标准的一部分。
此外,我不认为存在虚假下划线,因为它不会生成有效的C++名称,并且您提供的 Pastebin 链接中的损坏名称显示为:
_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1Emc
我不在 Mac OS 上,但在 Linux 上使用 LLVM 3.8.1 进行模拟(使用--stdlib=libc++),使用相同的源并逐行匹配 IR,我得到以下符号:
_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEmc
分解回:
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__init(unsigned long, char)
我想这与某种结构几乎相同。
所以,我相信你的链接器选择了错误的libc++版本。
libc++您可以检查与您正在使用的 clang/LLVM 相关的可用符号,在给定的目录中找到llvm-config --libdir,甚至可以使用 . 检查工具链二进制文件的 rpath 条目readelf -d $(which lli)。
如果有多个 LLVM 安装(例如,一个系统和一个您自己从源代码编译的系统),您可能需要使用指示将该路径添加到其搜索列表中-L的选项。一个快速的替代方法(我不建议经常使用)是在命令行上执行此操作:clangld
LD_LIBRARY_PATH=$(llvm-config --libdir) clang generated.s