上下文
我使用LLVM作为我的后端,因此codegen需要所有这些运行时类型(函数,结构等)的类型,而不是使用LLVM API手动定义所有这些类型或手写LLVM IR我想编写C中的头文件并编译为编译器可以使用 LLVMParseBitcodeInContext2
引入的bitcode .
问题
问题我似乎保留了任何任何函数定义都没有使用的类型声明 . Clang有 -femit-all-decls
,听起来像是's supposed to solve it, but it unfortunately isn' t和谷歌搜索表明它的名字错误,因为它只影响未使用的定义,而不是声明 .
然后我想也许如果我只将头文件编译成 .gch
文件,我可以用 LLVMParseBitcodeInContext2
以同样的方式将它们拉进去(因为文档说他们使用"the same" bitcode格式“,但是这样做错误 error: Invalid bitcode signature
因此必须有所不同 . 也许差别小到可以解决?
任何可以为复杂运行时自动化的建议或相对简单的解决方法?如果有人对接近这个一般用例有一个完全替代的建议,我也会感兴趣,记住我不想在运行时函数体中静态链接我生成的每个单个目标文件,只是类型 . 我想这也是其他编译器所需要的,所以如果我接近这个错误,我不会感到惊讶 .
例如鉴于此输入:
runtime.h
struct Foo {
int a;
int b;
};
struct Foo * something_with_foo(struct Foo *foo);
我需要一个具有此等效IR的bitcode文件
runtime.ll
; ...etc...
%struct.Foo = type { i32, i32 }
declare %struct.Foo* @something_with_foo(%struct.Foo*)
; ...etc...
我可以手动编写它,但这将是重复的,因为我还需要为其他互操作创建C头,并且理想的是不必手动保持它们同步 . 运行时相当大 . 我想我也可以做相反的事情:在LLVM IR中编写声明并生成C头 .
今年有人问过这个问题,但是对于这种大小和类型复杂的运行时来说,所提出的解决方案相当苛刻且相当不切实际:Clang - Compiling a C header to LLVM IR/bitcode
2 回答
所以,
clang
实际上并没有过滤掉未使用的声明 . 它推迟发出前向声明,直到第一次使用 . 每当使用一个函数时,它会检查它是否已经被发出,如果没有,它会发出函数声明 .您可以在clang repo中查看these lines .
这里的简单修复是注释最后两行或只是将
&& false
添加到第二个条件 .这将导致
clang
在看到它时立即发出声明,这也可能会更改定义在.ll
(或.bc
)文件中出现的顺序 . 假设这不是问题 .为了使它更干净,您还可以添加命令行标志
--emit-all-declarations
并在继续之前检查此处 .Clang的precompiled headers实现似乎不输出LLVM IR,而只输出AST(抽象语法树),因此不需要再次解析标头:
底层二进制格式可能相同,但听起来内容不同,LLVM的bitcode格式在这种情况下仅仅是一个容器 . 这在网站的帮助页面上并不是很清楚,所以我只是在猜测 . LLVM / Clang专家可以帮助澄清这一点 .
不幸的是,似乎并没有一种优雅的方式 . 我建议最小化实现所需的工作量是构建一个最小的C / C源文件,它以某种方式使用您要编译为LLVM IR的所有声明 . 例如,您只需要声明一个指向结构的指针,以确保它不会被优化掉,并且您可能只为函数提供一个空的定义以保持其签名 .
获得最小的源文件后,使用
clang -O0 -c -emit-llvm -o precompiled.ll
进行编译,以获得具有LLVM IR格式的所有定义的模块 .您发布的代码段中的示例:
显示定义的输出:https://godbolt.org/g/2F89BH