Tôi đã cố gắng xây dựng và thực thi các mô-đun LLVM. Mã của tôi để tạo ra các mô-đun là khá dài, vì vậy tôi sẽ không đăng nó ở đây. Thay vào đó, câu hỏi của tôi là về cách Clang và LLVM làm việc cùng nhau để đạt được tên mangling. Tôi sẽ giải thích vấn đề cụ thể của tôi để thúc đẩy câu hỏi.Tên nhầm lẫn mangling trong LLVM
Đây là mã nguồn của một trong những module LLVM tôi:
#include <iostream>
int main() {
std::cout << "Hello, world. " << std::endl;
return 0;
}
Here is the generated LLVM IR; nó quá lớn đối với StackOverflow.
Khi tôi cố gắng thực hiện mô-đun của tôi sử dụng lli
, tôi nhận được lỗi sau:
LLVM ERROR: Program used external function '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1Emc' which could not be resolved!
Chạy biểu tượng thông qua một demangler, biểu tượng mất tích là:
_std::__1::basic_string, std::__1::allocator >::basic_string(unsigned long, char)
Các phụ _
là đáng ngờ, và chức năng không có dấu gạch dưới hàng đầu dường như tồn tại trong 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
}
Tôi đang trên hệ điều hành MacOS, do đó, một dấu gạch dưới hàng đầu là để được mong đợi, nhưng tôi nghĩ rằng Clang có thể thêm nó hai lần.
Tôi nhìn qua nguồn LLVM/Clang, và có vẻ như rằng có hai bước mangling:
- Lấy có thể bị quá tải chức năng C++ và mangling họ tên duy nhất cho LLVM IR
- Lấy một đọc sai tên từ IR LLVM và thêm bất kỳ quirks nền tảng cụ thể nào, chẳng hạn như dấu gạch dưới hàng đầu
Tuy nhiên, đây chỉ là lý thuyết của tôi. Ai đó có thể giải thích quá trình xâu chuỗi hoạt động như thế nào ở Clang và LLVM? Làm cách nào để tạo các đối tượng llvm::DataLayout
của tôi để có được xâu xén chính xác cho nền tảng của tôi?
nm -gU /usr/lib/libc++.dylib
và nm -gU /usr/lib/libc++abi.dylib
không chứa __ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1Emc
Khi tôi cố gắng biên dịch IR, tôi nhận được lỗi này:
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)
Tôi không nghĩ rằng đây là một vấn đề tên mangling. Miễn là bạn không chạm vào tên, bạn sẽ ổn thôi. Thay vào đó, đây là một vấn đề liên kết. lli không liên kết trong bất kỳ thư viện nào, vì vậy các ký hiệu STL không thể được giải quyết. Nếu bạn biên dịch và liên kết các mô-đun bạn sẽ được tốt ... llc test.ll, clang ++ test.s (hoặc bất kỳ trình biên dịch khác). Hãy cho tôi biết nếu điều này giúp & tôi sẽ thêm nó làm câu trả lời. – Tobias
... bạn đã tạo IR với clang ++ -S -emit-llvm chưa? đã chỉnh sửa tệp theo bất kỳ cách nào? Bạn có muốn nó chạy hay bạn muốn biết làm thế nào tên được băm nhỏ b/c bạn muốn tạo ra một tên bị xâu xé cho mình? – Tobias
@Tobias Tôi đã tạo LLVM bằng cách sử dụng nhà máy 'clang :: CreateLLVMCodeGen' và' HandleTopLevelDecl' – sdgfsdh