2017-02-03 77 views
15

我一直在试图建立和执行LLVM模块重整混乱。我的代码生成模块很长,所以我不会在这里发布。相反,我的问题是关于Clang和LLVM如何共同实现名称修改。我将解释我的具体问题来激发这个问题。名称在LLVM

这里是我的LLVM模块之一的源代码:

#include <iostream> 

int main() { 
    std::cout << "Hello, world. " << std::endl; 
    return 0; 
} 

Here is the generated LLVM IR;它对于StackOverflow来说太大了。

当我尝试使用lli我的模块来执行,我得到以下错误:

LLVM ERROR: Program used external function '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1Emc' which could not be resolved!

通过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 
} 

我在MacOS,所以前面的下划线是可以预料的,但我认为锵可能会增加它两次

我通过LLVM/Clang的来源看,似乎有两个重整步骤:

  1. 考虑可能重载C++函数和重整他们唯一的名称为LLVM IR
  2. 隔空错位从LLVM IR的名称和添加任何特定于平台的怪癖,如领先的下划线

但是,这只是我的理论。有人可以解释Clang和LLVM中的加工过程是如何工作的吗?我应该如何创建我的llvm::DataLayout对象才能为我的平台获得正确的绑定?


nm -gU /usr/lib/libc++.dylibnm -gU /usr/lib/libc++abi.dylib不包含__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorI‌​cEEEC1Emc


当我试图编译IR,我得到这个错误:

llc generated.ll 
clang++ generated.s 

Undefined symbols for architecture x86_64: "std::__1::basic_string, std::__1::allocator >::data() const", referenced from: 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", referenced from: 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", referenced from: 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", referenced from: std::__1::ostreambuf_iterator >::ostreambuf_iterator(std::__1::basic_ostream >&) in generated-b4252a.o "std::__1::basic_ios >::widen(char) const", referenced from: std::__1::basic_ostream >& std::__1::endl >(std::__1::basic_ostream >&) in generated-b4252a.o "std::__1::basic_string, std::__1::allocator >::basic_string(unsigned long, char)", referenced from: 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)", referenced from: std::__1::basic_ostream >& std::__1::__put_character_sequence >(std::__1::basic_ostream >&, char const*, unsigned long) in generated-b4252a.o ld: symbol(s) not found for architecture x86_64 clang-3.9: error: linker command failed with exit code 1 (use -v to see invocation)

+1

我不认为这是一个名称重整问题。只要你没有碰到名字,你应该没问题。相反,这是一个链接问题。 lli没有链接到任何库中,所以STL符号无法解析。如果你编译和链接模块,你应该没问题...... llc test.ll,clang ++ test.s(或其他编译器)。让我知道这是否有帮助,我会将其添加为答案。 – Tobias

+0

...你是否用clang ++ -S -mit-llvm生成IR?以任何方式编辑文件?你想让它运行吗?或者你想知道你想自己生成一个损坏的名字是如何改名的? – Tobias

+0

@Tobias我使用'clang :: CreateLLVMCodeGen'工厂和'HandleTopLevelDecl'生成了LLVM – sdgfsdh

回答

2

我不会怀疑名称损坏问题。 C++名字粉碎发生在前端(即clang),它是一个相当良好定义/ -documented ABI standard一部分。

而且,我不认为这是一个虚假的下划线,因为那不会产生有效的C++名字后面,并在引擎收录链接,您提供的出现为重整名称:

_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1Emc

我不是在Mac OS上,而是使用我的LLVM 3.8进行模拟。1上的Linux(使用--stdlib=libc++),使用相同的源和匹配由线红外线, 我得到以下符号:

_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEmc

其中demangles回:

std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__init(unsigned long, char)

我猜这种结构几乎与某种结构相同。

所以,我相信你的链接器会提取错误的libc++版本。

你可以检查由llvm-config --libdir甚至检查你的工具链的二进制文件与readelf -d $(which lli)将rpath条目中给出的目录中发现被捆绑到铛/ LLVM您正在使用的libc++可用的符号。

如果有多个LLVM装置(例如一个系统,一个又一个,你从自己的来源编译),你可能要玩的-L选项clang其指导ld添加在其搜索列表中的路径。 快速替代(即我不推荐经常使用)是这样做的命令行:

LD_LIBRARY_PATH=$(llvm-config --libdir) clang generated.s