
Emscripten 中 LLVM compiler-rt 的集成与维护基于 llvm-project 22.1.8 的运行时库移植指南【免费下载链接】emscriptenEmscripten: An LLVM-to-WebAssembly Compiler项目地址: https://gitcode.com/gh_mirrors/em/emscriptencompiler-rt 是 LLVM 项目自带的运行时库集合涵盖编译器内置辅助函数builtins、AddressSanitizer/LeakSanitizer/UBSan 等内存与未定义行为检测工具以及代码覆盖率profile支撑模块。在 Emscripten 工具链中这一整套运行时库被直接移植进仓库为 WebAssembly 目标提供底层支撑。本文以 system/lib/compiler-rt/README.md 为核心线索结合仓库中的更新脚本与构建配置完整讲解 compiler-rt 的来源版本、fork 维护策略、本地目录结构、一键更新流程、Emscripten 特有改动以及最终如何被链接进产物读完即可掌握这套运行时库在 Emscripten 中从上游同步到本地构建的完整链路。compiler-rt 在 Emscripten 中的作用WebAssembly 没有传统意义上的操作系统编译器生成的代码中需要大量辅助函数来补全指令集能力的空缺。compiler-rt 的lib/builtins就是这些辅助函数的集合例如 64 位整数乘法除法muldi3.c、udivdi3.c、浮点转换floatdidf.c、fixdfsi.c、128 位整数运算ashlti3.c、udivti3.c、原子操作atomic.c等。当 clang 为 wasm32/wasm64 目标生成代码时凡是目标指令集无法直接表达的操作都会退化为对这类运行时函数的调用。此外Emscripten 的多种内存安全与调试功能也依赖 compiler-rt 的 sanitizer 家族AddressSanitizerASan检测越界访问、use-after-free、内存泄漏对应lib/asan与lib/sanitizer_commonLeakSanitizerLSan检测内存泄漏对应lib/lsanUndefinedBehaviorSanitizerUBSan检测整数溢出、空指针解引用等未定义行为对应lib/ubsan与lib/ubsan_minimal代码覆盖率profile支撑 gcov / instrprof 类功能对应lib/profile与include/profile。这些目录中的*_emscripten.*文件如asan_emscripten.cpp、lsan_common_emscripten.cpp、sanitizer_emscripten.cpp、sanitizer_symbolizer_emscripten.cpp、sanitizer_stacktrace_emscripten.cpp即是在移植过程中为 wasm 目标新增的平台适配层可见 sanitizer 在 Emscripten 中是完整可用的。版本来源与 fork 维护策略原文档明确指出仓库中的 compiler-rt 文件来自llvm-project release 22.1.8并且 Emscripten 维护了一个本地 fork 的 llvm-project用于承载所有 Emscripten 特有的补丁当前补丁基于emscripten-libs-22分支。这套上游基线版本 专属分支补丁的策略有两点直接好处版本可追踪所有文件都对应上游某个确定的 release tag22.1.8审计与升级时能精确对照补丁集中管理Emscripten 相关的改动全部落在 fork 的emscripten-libs-22分支上不会散落在本地目录中无法追溯。分支名中的22与 LLVM 主版本号绑定后续大版本升级时会自然演进为emscripten-libs-23等。这一绑定关系并非手动维护而是由更新脚本自动完成见下文。本地目录结构一览system/lib/compiler-rt/下除了 README、CREDITS.TXT、LICENSE.TXT两个上游版权文件还包括两类内容从上游整目录复制而来的源码lib/与include/目录内容lib/builtins编译器辅助函数整数/浮点/原子/复杂数运算等约 200 个 C 源文件lib/asan、lib/lsan、lib/ubsan、lib/ubsan_minimal各类 sanitizer 运行时lib/sanitizer_commonsanitizer 公共基础设施分配器、栈回溯、符号化、互斥锁等lib/interception函数拦截基础设施供 sanitizer 钩住 libc 调用lib/profile覆盖率与插桩相关的运行时include/sanitizer各 sanitizer 的公共头文件asan_interface.h、lsan_interface.h、ubsan_interface.h等include/profile覆盖率数据结构定义InstrProfData.inc等Emscripten 特有的文件位于system/lib/compiler-rt/顶层emscripten_setjmp.cwasm 目标的 setjmp/longjmp 运行时实现emscripten_exception_builtins.c异常处理辅助函数setThrew等emscripten_tempret.s、__c_longjmp.S与栈回溯、longjmp 抛出相关的汇编实现stack_ops.S、stack_limits.S栈操作与栈边界查询函数emscripten_stack_get_base等__trap.c__trap辅助实现。其中 stack_limits.S 通过 WebAssembly 全局变量__stack_base/__stack_end暴露emscripten_stack_get_base、emscripten_stack_get_end、emscripten_stack_get_free等 API并同时适配 wasm32i32与 wasm64i64两种指针宽度是 Emscripten 栈管理的基础设施之一。一键更新update_compiler_rt.py 的工作机制原文档给出的更新指令为python3 system/lib/update_compiler_rt.py path/to/llvm-project其中path/to/llvm-project指向本地 checkout 的 llvm-project 仓库根目录。查看 system/lib/update_compiler_rt.py 的源码可以还原整个同步流程定位上游目录脚本读取llvm_dir/compiler-rt并断言lib/builtins与include/sanitizer存在update_compiler_rt.py 第 38-43 行按清单复制子目录通过copy_dirs列表逐一对include/sanitizer、include/profile、lib/sanitizer_common、lib/asan、lib/interception、lib/builtins、lib/lsan、lib/ubsan、lib/ubsan_minimal、lib/profile执行清空旧内容再复制第 20-31 行过滤上游构建文件复制时跳过.clang-format、CMakeLists.txt、README.txt、weak_symbols.txt以及.syms.extra、.S汇编文件第 51-54 行——这些属于上游 CMake 构建系统产物Emscripten 使用自己基于 tools/system_libs.py 的构建体系不需要它们同步版权文件复制上游CREDITS.TXT与LICENSE.TXT到本地自动更新 README调用update_common.update_readme重写本 README。关键的一点在第 5 步。查看 system/lib/update_common.py 的update_readme实现第 73-88 行它会解析上游cmake/Modules/LLVMVersion.cmake中的LLVM_VERSION_MAJOR/MINOR/PATCH然后用正则把 README 里所有x.y.z形式的版本号替换为最新完整版本并把emscripten-libs-NN中的数字替换为新的主版本号。也就是说每次执行更新脚本后本 README 中基于 release 22.1.8emscripten-libs-22 分支等字样都会被自动刷新保证文档与代码永远同步这也是本 README 中版本信息准确性的来源。如果省略路径参数直接运行python3 system/lib/update_compiler_rt.py脚本会默认使用update_common.py中定义的默认目录Emscripten 仓库同级目录下的llvm-project见 update_common.py 第 13 行路径不存在时脚本会给出提示并打印帮助信息后退出第 21-25 行。Emscripten 特有改动setjmp/longjmp 与异常辅助函数compiler-rt 移植中最重要的本地改动集中在 wasm 的 setjmp/longjmp 与异常处理支持上。LLVM 后端会为 wasm 目标的setjmp/longjmp生成对特殊运行时函数的引用这些函数由 Emscripten 在 emscripten_setjmp.c 中实现__wasm_setjmp(env, label, func_invocation_id)将跳转目标label与当前函数调用 ID 记录到jmp_buf__wasm_setjmp_test(env, func_invocation_id)判断当前调用是否匹配之前保存的调用匹配则返回对应 label__wasm_longjmp(env, val)遵循 C 标准longjmp不能使setjmp返回 0若val为 0 则改为返回 1最终通过__builtin_wasm_throw(C_LONGJMP, arg)抛出 wasm 异常实现非局部跳转。在未启用 wasm 异常处理的模式下则回退到 emscripten_exception_builtins.c 提供的setThrew/__THREW__机制用线程局部变量记录抛出位置与值再调用_emscripten_throw_longjmp()完成跳转。这些符号的引用关系由 LLVM 后端的WebAssemblyLowerEmscriptenEHSjLjpass 生成属于 Emscripten 工具链与 compiler-rt 之间约定的 ABI。构建集成compiler-rt 如何进入最终产物compiler-rt 的源码并不直接参与编译而是由 Emscripten 的库构建系统在 tools/system_libs.py 中注册为若干系统库按需链接进最终 wasm 产物libclang_rt.builtins核心运行时库编译lib/builtins全部 C 文件、lib/profile的源码并额外加入上文提到的 Emscripten 特有文件stack_ops.S、stack_limits.S、emscripten_setjmp.c、emscripten_exception_builtins.c、emscripten_tempret.s、__c_longjmp.S、__trap.c。构建配置第 955-996 行还揭示了几个重要细节使用-fno-builtin -DNDEBUG -DCOMPILER_RT_HAS_ATOMICS1等编译选项通过excludes排除不适用的文件gcc_personality_v0.c依赖未默认包含的 libunwind、bfloat16 转换函数、Emscripten 自带的 crtcrtbegin.c/crtend.c以及 wasm 不支持的 80 位 x87long double系列函数force_object_files Truecompiler-rt 文件目前不能参与 LTO 链接注释中附带相关上游讨论链接因此强制按目标文件方式处理libclang_rt.sanitizer_common与libclang_rt.ubsan、libclang_rt.lsan、libclang_rt.lsan_common、libclang_rt.ubsan_minimal在启用对应 sanitizer 或按需时编译均以-fno-builtin为基础并统一把system/lib/compiler-rt/lib与system/lib/compiler-rt/include加入头文件搜索路径。值得注意的是 system_libs.py 第 2564 行 把system/lib/compiler-rt/include作为全局包含路径之一意味着编译器内置的 sanitizer 头文件对用户代码也是可用的例如直接#include sanitizer/asan_interface.h。如何查看修改列表与升级注意事项原文档指出本地文件与上游的具体差异可以通过对比 llvm-project 的llvmorg-22.1.8tag 与 Emscripten fork 的emscripten-libs-22分支得到。在本地操作时等价的做法是# 在 Emscripten 的 llvm-project fork 中 git diff llvmorg-22.1.8..emscripten-libs-22 -- compiler-rt参与 compiler-rt 升级或修补时有几个约定值得留意不要手工改动目录结构本地目录与上游的对应关系由copy_dirs清单决定新增/删除目录需同步修改 update_compiler_rt.py 的copy_dirs否则下次同步会被清掉Emscripten 专属文件会被保留update_common.clean_dir清理旧文件时会跳过文件名含emscripten的文件update_common.py 第 34 行因此顶层这些 Emscripten 特有源码不会在更新中被误删README 由脚本自动维护版本号与分支名不要手工修改脚本会在下次更新时按上游LLVMVersion.cmake自动刷新上游构建文件不落地CMake 配置、.S汇编等由 Emscripten 自有构建体系替代避免与tools/system_libs.py的编译流程冲突。小结system/lib/compiler-rt是 Emscripten 工具链中上游代码 本地补丁合作模式的典型样本以 llvm-project 22.1.8 为基线通过 fork 分支emscripten-libs-22承载全部 wasm 专属改动再由 update_compiler_rt.py 一键同步源码、自动刷新 README 版本信息最终经 tools/system_libs.py 编译为 builtins、sanitizer 等若干系统库随链接进入最终产物。理解这条链路无论是排查 sanitizer 相关构建问题、评估升级 LLVM 版本的影响还是为 wasm 目标新增运行时辅助函数都能快速定位到正确的文件和流程。【免费下载链接】emscriptenEmscripten: An LLVM-to-WebAssembly Compiler项目地址: https://gitcode.com/gh_mirrors/em/emscripten创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考