LLVM系列第二章:模块Module

系列文章目录

LLVM系列第一章:编译LLVM源码
LLVM系列第二章:模块Module
LLVM系列第三章:函数Function
LLVM系列第四章:逻辑代码块Block
LLVM系列第五章:全局变量Global Variable
LLVM系列第六章:函数返回值Return
LLVM系列第七章:函数参数Function Arguments
LLVM系列第八章:算术运算语句Arithmetic Statement
LLVM系列第九章:控制流语句if-else
LLVM系列第十章:控制流语句if-else-phi
LLVM系列第十一章:写一个Hello World
LLVM系列第十二章:写一个简单的词法分析器Lexer
LLVM系列第十三章:写一个简单的语法分析器Parser
LLVM系列第十四章:写一个简单的语义分析器Semantic Analyzer
LLVM系列第十五章:写一个简单的中间代码生成器IR Generator
LLVM系列第十六章:写一个简单的编译器
LLVM系列第十七章:for循环
LLVM系列第十八章:写一个简单的IR处理流程Pass
LLVM系列第十九章:写一个简单的Module Pass
LLVM系列第二十章:写一个简单的Function Pass
LLVM系列第二十一章:写一个简单的Loop Pass
LLVM系列第二十二章:写一个简单的编译时函数调用统计器(Pass)
LLVM系列第二十三章:写一个简单的运行时函数调用统计器(Pass)
LLVM系列第二十四章:用Xcode编译调试LLVM源码
LLVM系列第二十五章:简单统计一下LLVM源码行数
LLVM系列第二十六章:理解LLVMContext
LLVM系列第二十七章:理解IRBuilder
LLVM系列第二十八章:写一个JIT Hello World
LLVM系列第二十九章:写一个简单的常量加法“消除”工具(Pass)

flex&bison系列



前言

在此记录下用LLVM生成模块(Module)的过程,以备查阅。

开发环境的配置请参考第一章 《LLVM系列第一章:编译LLVM源码》。

简单来说,LLVM中的模块(Module),代表了一块代码。它是一个比较完整独立的代码块,是一个最小的编译单元。需要注意的是,它跟我们平常说的“程序模块”不一样。程序模块是一个更大的集合,包含了很多个编译单元;而LLVM中的模块(Module),我们可以把它初步理解为一个编译单元。

在LLVM IR的基本概念(构件)中,模块是一个组合,它包含了其它更小的基本构件。比如,它可以包含的基本构件有全局变量、函数、数据结构等。

在这一章,我们就用LLVM的API来创建一个最简单的模块。

一、Hello Module

用LLVM创建模块之前,需要首先初始化LLVMContext,然后才能调用LLVM API,代码如下(示例):

// HelloModule.cpp

#include "llvm/IR/Module.h"
#include "llvm/IR/LLVMContext.h"

using namespace llvm;

int main(int argc, char* argv[])
{
    LLVMContext context;
    Module* module = new Module("HelloModule", context);

    module->print(outs(), nullptr);

    return 0;
}

二、编译

用clang++进行编译(示例):

# Set up C++ standard library and header path
export SDKROOT=$(xcrun --sdk macosx --show-sdk-path)

# Compile
clang++ -w -o HelloModule `llvm-config --cxxflags --ldflags --system-libs --libs core` HelloModule.cpp

以上命令会生成一个名为HelloModule的可执行程序。

三、运行

运行HelloModule(示例):

./HelloModule

输出结果如下(示例):

; ModuleID = 'HelloModule'
source_filename = "HelloModule"

四、总结

我们用LLVM提供的C++ API,创建了一个最简单的模块(Module),并打印出了它的IR代码。完整源码示例请参看:
https://github.com/wuzhanglin/llvm-IR-examples

使用clang++编译,报错: /usr/bin/ld: /usr/local/lib/libclangSerialization.a(ASTWriter.cpp.o): in function `llvm::SHA1::SHA1()': ASTWriter.cpp:(.text._ZN4llvm4SHA1C2Ev[_ZN4llvm4SHA1C5Ev]+0x14): undefined reference to `llvm::SHA1::init()' /usr/bin/ld: /usr/local/lib/libclangSerialization.a(ASTWriter.cpp.o): in function `clang::ASTWriter::createSignature() const [clone .localalias]': ASTWriter.cpp:(.text._ZNK5clang9ASTWriter15createSignatureEv+0xa0): undefined reference to `llvm::SHA1::update(llvm::StringRef)' /usr/bin/ld: ASTWriter.cpp:(.text._ZNK5clang9ASTWriter15createSignatureEv+0xb6): undefined reference to `llvm::SHA1::result()' /usr/bin/ld: ASTWriter.cpp:(.text._ZNK5clang9ASTWriter15createSignatureEv+0x11d): undefined reference to `llvm::SHA1::update(llvm::StringRef)' /usr/bin/ld: ASTWriter.cpp:(.text._ZNK5clang9ASTWriter15createSignatureEv+0x15a): undefined reference to `llvm::SHA1::update(llvm::StringRef)' /usr/bin/ld: ASTWriter.cpp:(.text._ZNK5clang9ASTWriter15createSignatureEv+0x193): undefined reference to `llvm::SHA1::update(llvm::StringRef)' /usr/bin/ld: ASTWriter.cpp:(.text._ZNK5clang9ASTWriter15createSignatureEv+0x1a9): undefined reference to `llvm::SHA1::result()' /usr/bin/ld: /usr/local/lib/libclangSerialization.a(ASTWriter.cpp.o): in function `clang::ASTWriter::createSignatureForNamedModule() const [clone .localalias]': ASTWriter.cpp:(.text._ZNK5clang9ASTWriter29createSignatureForNamedModuleEv+0x86): undefined reference to `llvm::SHA1::update(llvm::StringRef)' /usr/bin/ld: ASTWriter.cpp:(.text._ZNK5clang9ASTWriter29createSignatureForNamedModuleEv+0x1ba): undefined reference to `llvm::SHA1::update(llvm::ArrayRef<unsigned char>)' /usr/bin/ld: ASTWriter.cpp:(.text._ZNK5clang9ASTWriter29createSignatureForNamedModuleEv+0x23b): undefined reference to `llvm::SHA1::update(llvm::ArrayRef<unsigned char>)' /usr/bin/ld: ASTWriter.cpp:(.text._ZNK5clang9ASTWriter29createSignatureForNamedModuleEv+0x258): undefined reference to `llvm::SHA1::result()' /usr/bin/ld: /usr/local/lib/libclangSerialization.a(ASTWriter.cpp.o): in function `emitBlob(llvm::BitstreamWriter&, llvm::StringRef, unsigned int, unsigned int)': ASTWriter.cpp:(.text._ZL8emitBlobRN4llvm15BitstreamWriterENS_9StringRefEjj+0x44): undefined reference to `llvm::compression::zstd::isAvailable()' /usr/bin/ld: ASTWriter.cpp:(.text._ZL8emitBlobRN4llvm15BitstreamWriterENS_9StringRefEjj+0x9a): undefined reference to `llvm::compression::zstd::compress(llvm::ArrayRef<unsigned char>, llvm::SmallVectorImpl<unsigned char>&, int, bool)' /usr/bin/ld: ASTWriter.cpp:(.text._ZL8emitBlobRN4llvm15BitstreamWriterENS_9StringRefEjj+0x123): undefined reference to `llvm::compression::zlib::isAvailable()' /usr/bin/ld: ASTWriter.cpp:(.text._ZL8emitBlobRN4llvm15BitstreamWriterENS_9StringRefEjj+0x173): undefined reference to `llvm::compression::zlib::compress(llvm::ArrayRef<unsigned char>, llvm::SmallVectorImpl<unsigned char>&, int)' /usr/bin/ld: /usr/local/lib/libclangSerialization.a(ASTWriter.cpp.o): in function `clang::ASTRecordWriter::AddCXXDefinitionData(clang::CXXRecordDecl const*) [clone .localalias]': ASTWriter.cpp:(.text._ZN5clang15ASTRecordWriter20AddCXXDefinitionDataEPKNS_13CXXRecordDeclE+0x1a98): undefined reference to `clang::CXXRecordDecl::getFirstFriend() const' /usr/bin/ld: /usr/local/lib/libclangSerialization.a(ASTWriterDecl.cpp.o): in function `clang::ASTDeclWriter::VisitOMPDeclareReductionDecl(clang::OMPDeclareReductionDecl*) [clone .localalias]': ASTWriterDecl.cpp:(.text._ZN5clang13ASTDeclWriter28VisitOMPDeclareReductionDeclEPNS_23OMPDeclareReductionDeclE+0x139): undefined reference to `clang::OMPDeclareReductionDecl::getPrevDeclInScope()' /usr/bin/ld: /usr/local/lib/libclangSerialization.a(ASTWriterDecl.cpp.o): in function `clang::ASTDeclWriter::VisitOMPDeclareMapperDecl(clang::OMPDeclareMapperDecl*) [clone .localalias]': ASTWriterDecl.cpp:(.text._ZN5clang13ASTDeclWriter25VisitOMPDeclareMapperDeclEPNS_20OMPDeclareMapperDeclE+0x6e): undefined reference to `clang::OMPDeclareMapperDecl::getPrevDeclInScope()' /usr/bin/ld: /usr/local/lib/libclangSerialization.a(GlobalModuleIndex.cpp.o): in function `clang::GlobalModuleIndex::GlobalModuleIndex(std::unique_ptr<llvm::MemoryBuffer, std::default_delete<llvm::MemoryBuffer> >, llvm::BitstreamCursor) [clone .localalias]': GlobalModuleIndex.cpp:(.text._ZN5clang17GlobalModuleIndexC2ESt10unique_ptrIN4llvm12MemoryBufferESt14default_deleteIS3_EENS2_15BitstreamCursorE+0x236): undefined reference to `llvm::BitstreamCursor::EnterSubBlock(unsigned int, unsigned int*)' /usr/bin/ld: GlobalModuleIndex.cpp:(.text._ZN5clang17GlobalModuleIndexC2ESt10unique_ptrIN4llvm12MemoryBufferESt14default_deleteIS3_EENS2_15BitstreamCursorE+0x33c): undefined reference to `llvm::BitstreamCursor::readRecord(unsigned int, llvm::SmallVectorImpl<unsigned long>&, llvm::StringRef*)' /usr/bin/ld: /usr/local/lib/libclangSerialization.a(GlobalModuleIndex.cpp.o): in function `clang::GlobalModuleIndex::readIndex(llvm::StringRef)': GlobalModuleIndex.cpp:(.text._ZN5clang17GlobalModuleIndex9readIndexEN4llvm9StringRefE+0x246): undefined reference to `llvm::MemoryBufferRef::MemoryBufferRef(llvm::MemoryBuffer const&)' /usr/bin/ld: /usr/local/lib/libclangSerialization.a(GlobalModuleIndex.cpp.o): in function `(anonymous namespace)::GlobalModuleIndexBuilder::loadModuleFile(clang::FileEntryRef)': GlobalModuleIndex.cpp:(.text._ZN12_GLOBAL__N_124GlobalModuleIndexBuilder14loadModuleFileEN5clang12FileEntryRefE+0x111): undefined reference to `llvm::MemoryBufferRef::MemoryBufferRef(llvm::MemoryBuffer const&)' /usr/bin/ld: GlobalModuleIndex.cpp:(.text._ZN12_GLOBAL__N_124GlobalModuleIndexBuilder14loadModuleFileEN5clang12FileEntryRefE+0x389): undefined reference to `llvm::BitstreamCursor::skipRecord(unsigned int)' /usr/bin/ld: GlobalModuleIndex.cpp:(.text._ZN12_GLOBAL__N_124GlobalModuleIndexBuilder14loadModuleFileEN5clang12FileEntryRefE+0x417): undefined reference to `llvm::BitstreamCursor::EnterSubBlock(unsigned int, unsigned int*)' /usr/bin/ld: GlobalModuleIndex.cpp:(.text._ZN12_GLOBAL__N_124GlobalModuleIndexBuilder14loadModuleFileEN5clang12FileEntryRefE+0x4ad): undefined reference to `llvm::BitstreamCursor::EnterSubBlock(unsigned int, unsigned int*)' /usr/bin/ld: GlobalModuleIndex.cpp:(.text._ZN12_GLOBAL__N_124GlobalModuleIndexBuilder14loadModuleFileEN5clang12FileEntryRefE+0x543): undefined reference to `llvm::BitstreamCursor::EnterSubBlock(unsigned int, unsigned int*)' /usr/bin/ld: GlobalModuleIndex.cpp:(.text._ZN12_GLOBAL__N_124GlobalModuleIndexBuilder14loadModuleFileEN5clang12FileEntryRefE+0x687): undefined reference to `llvm::BitstreamCursor::readRecord(unsigned int, llvm::SmallVectorImpl<unsigned long>&, llvm::StringRef*)' /usr/bin/ld: /usr/local/lib/libclangSerialization.a(GlobalModuleIndex.cpp.o): in function `clang::GlobalModuleIndex::writeIndex(clang::FileManager&, clang::PCHContainerReader const&, llvm::StringRef)': GlobalModuleIndex.cpp:(.text._ZN5clang17GlobalModuleIndex10writeIndexERNS_11FileManagerERKNS_18PCHContainerReaderEN4llvm9StringRefE+0x110): undefined reference to `llvm::LockFileManager::LockFileManager(llvm::StringRef)' /usr/bin/ld: GlobalModuleIndex.cpp:(.text._ZN5clang17GlobalModuleIndex10writeIndexERNS_11FileManagerERKNS_18PCHContainerReaderEN4llvm9StringRefE+0x129): undefined reference to `llvm::LockFileManager::tryLock()' /usr/bin/ld: GlobalModuleIndex.cpp:(.text._ZN5clang17GlobalModuleIndex10writeIndexERNS_11FileManagerERKNS_18PCHContainerReaderEN4llvm9StringRefE+0x65d): undefined reference to `llvm::LockFileManager::~LockFileManager()' /usr/bin/ld: /usr/local/lib/libclangSerialization.a(ModuleCache.cpp.o): in function `std::_MakeUniq<llvm::LockFileManager>::__single_object std::make_unique<llvm::LockFileManager, llvm::StringRef&>(llvm::StringRef&)': ModuleCache.cpp:(.text._ZSt11make_uniqueIN4llvm15LockFileManagerEJRNS0_9StringRefEEENSt9_MakeUniqIT_E15__single_objectEDpOT0_[_ZSt11make_uniqueIN4llvm15LockFileManagerEJRNS0_9StringRefEEENSt9_MakeUniqIT_E15__single_objectEDpOT0_]+0x4b): undefined reference to `llvm::LockFileManager::LockFileManager(llvm::StringRef)' /usr/bin/ld: /usr/local/lib/libclangSerialization.a(ModuleManager.cpp.o): in function `clang::serialization::ModuleManager::addModule(llvm::StringRef, clang::serialization::ModuleKind, clang::SourceLocation, clang::serialization::ModuleFile*, unsigned int, long, long, clang::ASTFileSignature, clang::ASTFileSignature (*)(llvm::StringRef), clang::serialization::ModuleFile*&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)': ModuleManager.cpp:(.text._ZN5clang13serialization13ModuleManager9addModuleEN4llvm9StringRefENS0_10ModuleKindENS_14SourceLocationEPNS0_10ModuleFileEjllNS_16ASTFileSignatureEPFS8_S3_ERS7_RNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+0x7d8): undefined reference to `llvm::MemoryBufferRef::MemoryBufferRef(llvm::MemoryBuffer const&)' /usr/bin/ld: /usr/local/lib/libclangSerialization.a(TemplateArgumentHasher.cpp.o): in function `(anonymous namespace)::TemplateArgumentHasher::AddTemplateArgument(clang::TemplateArgument)': TemplateArgumentHasher.cpp:(.text._ZN12_GLOBAL__N_122TemplateArgumentHasher19AddTemplateArgumentEN5clang16TemplateArgumentE+0xec): undefined reference to `llvm::APSInt::Profile(llvm::FoldingSetNodeID&) const' /usr/bin/ld: /usr/local/lib/libclangSerialization.a(TemplateArgumentHasher.cpp.o): in function `(anonymous namespace)::TemplateArgumentHasher::AddIdentifierInfo(clang::IdentifierInfo const*)': TemplateArgumentHasher.cpp:(.text._ZN12_GLOBAL__N_122TemplateArgumentHasher17AddIdentifierInfoEPKN5clang14IdentifierInfoE+0x61): undefined reference to `llvm::FoldingSetNodeID::AddString(llvm::StringRef)' clang++: error: linker command failed with exit code 1 (use -v to see invocation)
最新发布
08-07
你遇到的错误是典型的 **链接失败(linker error)**,具体表现为: ``` undefined reference to `llvm::SHA1::init()` undefined reference to `llvm::compression::zstd::isAvailable()` undefined reference to `clang::CXXRecordDecl::getFirstFriend()` ... ``` --- ## 🔍 错误分析 这些错误表明: > **你链接的 LLVM 和 Clang 库中缺少某些符号定义**,也就是说,链接器找不到这些函数或类的实现。 这通常发生在以下几种情况: --- ## ✅ 常见原因与解决方法 ### 1. **Clang 和 LLVM 版本不一致** 你可能正在使用一个版本的 Clang(比如 17),但链接的是另一个版本的 LLVM(比如 20 或 14),或者反之。 #### 🔍 检查方法: ```bash clang++ --version llvm-config --version ``` #### ✅ 解决方法: 确保你安装的 Clang 和 LLVM 是**完全匹配的版本**,比如: - `clang-20` + `llvm-20-dev` + `libclang-20-dev` - `clang-17` + `llvm-17-dev` + `libclang-17-dev` --- ### 2. **未链接完整的 Clang 和 LLVM 库** 你只链接了部分 Clang 库,但缺少了某些关键库(如 `libclangAST`, `libclangSerialization`, `libclangBasic` 等)。 #### ✅ 解决方法: 确保你链接了所有需要的 Clang 和 LLVM 库。例如: ```bash clang++ -std=c++17 your_file.cpp -o your_tool \ $(llvm-config --cxxflags --ldflags --system-libs --libs core support) \ -lclangAST -lclangTooling -lclangFrontend -lclangBasic \ -lclangLex -lclangParse -lclangSema -lclangAnalysis \ -lclangSerialization -lclangEdit -lclangDriver ``` --- ### 3. **手动编译安装的 Clang/LLVM 未正确安装** 你可能从源码构建了 LLVM 和 Clang,并且没有正确安装到系统路径中,导致链接器找不到某些符号。 #### ✅ 解决方法: 确保你在构建 LLVM 和 Clang 时启用了所有必要的组件,并正确执行了 `make install`: ```bash cd llvm-project mkdir build && cd build cmake -DLLVM_ENABLE_PROJECTS="clang" -DCMAKE_INSTALL_PREFIX=/usr/local ../llvm make -j$(nproc) sudo make install ``` 然后确认 `/usr/local/lib` 中包含了所有 `.a` 或 `.so` 文件。 --- ### 4. **缺少 Zstd 或 Zlib 支持** 你看到的: ``` undefined reference to `llvm::compression::zstd::isAvailable()` ``` 表示你的 LLVM 编译时没有启用 Zstd 支持。 #### ✅ 解决方法: 重新配置 LLVM,启用 Zstd: ```bash cmake -DLLVM_ENABLE_ZSTD=ON ... ``` 并确保系统安装了 `libzstd-dev` 和 `zlib1g-dev`: ```bash sudo apt install libzstd-dev zlib1g-dev ``` --- ### 5. **Clang 的一些特性未启用** 如果你使用了某些高级特性(如模块、OpenMP、AST序列化等),但构建 Clang 时没有启用它们,也会导致链接失败。 #### ✅ 解决方法: 确保构建 LLVM 和 Clang 时启用了以下选项: ```bash -DBUILD_SHARED_LIBS=OFF \ -DLLVM_BUILD_TOOLS=ON \ -DLLVM_BUILD_EXAMPLES=ON \ -DLLVM_ENABLE_ASSERTIONS=ON \ -DLLVM_ENABLE_PROJECTS="clang" \ -DLLVM_TARGETS_TO_BUILD="X86" ``` --- ## ✅ 推荐完整命令示例(Clang 20) ```bash clang++ -std=c++17 ClassInheritanceDumper.cpp -o class_analyzer \ $(llvm-config --cxxflags --ldflags --system-libs --libs core support) \ -lclangAST -lclangTooling -lclangFrontend -lclangBasic \ -lclangLex -lclangParse -lclangSema -lclangAnalysis \ -lclangSerialization -lclangEdit -lclangDriver ``` --- ## ✅ 推荐调试方式 加上 `-v` 查看详细链接器日志: ```bash clang++ -v ... ``` 你也可以使用 `nm` 或 `objdump` 查看某个 `.a` 文件是否包含缺失的符号: ```bash nm /usr/local/lib/libclangSerialization.a | grep SHA1 ``` --- ## ✅ 总结检查清单 | 检查项 | 是否完成 | |--------|----------| | Clang 和 LLVM 版本是否一致? | ✅ | | 是否链接了所有需要的 Clang 库? | ✅ | | 是否启用了 Zstd 和 Zlib 支持? | ✅ | | 是否从源码构建并正确安装? | ✅ | | 使用 `nm` 或 `objdump` 验证库中是否有缺失符号? | ✅ | --- ###
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值