2017-02-03 12 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!

デマングラを通じてシンボルを実行して、不足している記号は次のとおりです。

_std::__1::basic_string, std::__1::allocator >::basic_string(unsigned long, char)

余分_です不審なことがあり、先頭にアンダースコアのない機能がIRに存在するようです!私はMacOSで午前

; 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 
} 

、その先頭にアンダースコアが予想されるが、私はクランがそれを2回追加するかもしれないと思います。

私はLLVM /クランソースから見て、2つのマングリングステップがあるようです:

  1. はおそらくオーバーロードされたC++の機能を撮影し、マングルさを取るLLVM IRのためのユニークな名前
  2. にそれらをマングリングLLVM IRから名前を取得し、先頭にアンダースコアなどのプラットフォーム固有のクォークを追加する

ただしこれは私の理論にすぎません。 ClangとLLVMでmanglingプロセスがどのように機能するのか誰かが説明できますか?自分のプラットフォームで適切なマングリングを得るために、llvm::DataLayoutオブジェクトを作成するにはどうすればよいですか?


nm -gU /usr/lib/libc++.dylibnm -gU /usr/lib/libc++abi.dylib私はIRをコンパイルしようとすると、私はこのエラーを取得する__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorI‌​cEEEC1Emc


が含まれていない:

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 -emit-llvmでIRを生成しましたか?どのようにファイルを編集しましたか?あなたはそれを実行したいのですか、あなたはあなた自身の名前を生成するb/c名前がどのようにmangled b/cを知りたいですか? – Tobias

+0

@Tobias私は 'clang :: CreateLLVMCodeGen'ファクトリと' HandleTopLevelDecl'を使ってLLVMを生成しました – sdgfsdh

答えて

2

私は疑いないだろう名前のマングリング問題。フロントエンド(つまり、clang)でC++の名前マングリングが発生し、それはかなり明確な/文書化されたABI standardの一部です。

_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1Emc

また、私はあなたのように表示されてペーストビンリンクにおけるスプリアスアンダースコア、バック有効なC++名前を生成しない原因とマングルされた名前があるとは思いません私はMac OSではなく、LLVM 3.8でシミュレートしています。Linux上の1、同じソースを使用して、ラインによるIR線に一致する、私は、次の記号を取得 (--stdlib=libc++を使用):

_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++バージョンを選択したと思います。

あなたはllvm-config --libdirによって与えられた、あるいはreadelf -d $(which lli)であなたのツールチェーンのバイナリのRPATHエントリをチェックしたディレクトリで見つかった、使用している打ち鳴らす/ LLVMに接続されていlibc++で利用可能なシンボルをチェックすることができます。

複数LLVMのインストール(例えば、システム1、あなたがソースから自分をコンパイルしたもの)がある場合は、その検索リストにそのパスを追加するldに指示clang-Lオプションで遊んでする必要がある場合があります。 迅速な代替(私は定期的に使用するためお勧めしませんという)コマンドラインでこれを行うことです。

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

関連する問題