You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过clang -emit-llvm保留未使用的C/C++结构体定义

解决未使用结构体不生成LLVM IR的问题

核心逻辑:clang的延迟类型生成机制

clang对未被引用的结构体,仅在语义分析阶段完成类型解析,但不会生成对应的LLVM IR——因为IR生成阶段默认只处理实际被使用的类型,以此减少冗余代码。

源码修改关键点

要强制生成所有结构体的LLVM IR,需修改clang中类型生成的触发逻辑,核心涉及以下几个位置:

1. 主动遍历AST生成类型

在clang/lib/CodeGen/CodeGenModule.cpp中,CodeGenModule是IR生成的核心管理类。默认仅当类型被GetOrCreateLLVMType主动请求时才会生成IR,你可以修改EmitGlobalDecls或类似入口函数,遍历所有已完成定义的结构体,主动触发IR生成:

// 适配clang源码结构的示例代码
for (const auto *Record : getASTContext().getRecords()) {
  if (Record->isCompleteDefinition() && !Record->isAnonymousStructOrUnion()) {
    GetOrCreateLLVMType(QualType(Record, 0));
  }
}

2. 语义分析阶段标记类型需生成IR

在clang/lib/Sema/SemaDecl.cpp的Sema::ActOnTagDecl函数中,处理结构体/联合体声明的逻辑默认会跳过未被使用的类型。你需要修改此处,强制标记所有完成定义的结构体为"需要生成IR",确保后续流程不会忽略它们。

3. 避免LLVM后端消除未使用类型

LLVM后端可能会移除未被引用的类型定义,生成类型后需强制将其加入模块的全局类型列表:

llvm::Type *LLVMType = GetOrCreateLLVMType(TargetType);
if (auto *StructTy = dyn_cast<llvm::StructType>(LLVMType)) {
  if (!StructTy->isLiteral()) {
    getModule().addTypeName(StructTy->getName(), StructTy);
  }
}

无需修改源码的替代方案

如果不想改动clang源码,可以给结构体添加__attribute__((used))属性,强制clang保留其IR定义:

struct __attribute__((used)) A {
    void *ptr;
    int m_buf;
};

struct __attribute__((used)) B {
    struct A a;
    int m_val;
};

编译时使用clang -g -S -emit-llvm,即使结构体未被main函数使用,也会生成对应的LLVM IR。针对大型代码库,可通过clang插件或预处理脚本批量添加该属性,开销远低于手动修改代码。

内容的提问来源于stack exchange,提问作者Yinwhe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 04:17:15