在 LLVM 中创建模块化语言?
Creating a modular language in LLVM?
我正在使用 C++ API 在 LLVM 中开发一种新语言,它编译下来以 C ABI 为目标。
我想通过允许最终用户构建有效的静态库来支持模块化编译。我注意到 LLVM C++ API 有一个 llvm::Linker class that I can use during compilation to combine source files (llvm::Module),但是我想通过元数据版本号或至少在单独的编译运行之间公开暴露的接口来保证库兼容性。
LLVM 中 metadata 上的许多可用信息表明,它应该仅用于扩展信息,在静默删除时不会破坏正确性。
我不认为这会破坏交易,因为它可能是全局元数据,但在这一点上征求第二意见会很好。
我也知道 IRReader to parseIRFile 中有一个方法,所以我可以加载一些以前构建的 bc 文件。我很好奇在加载这些文件时包含大小和 CRC 信息以进行比较是否合理。
我的语言有类似于 C# 的概念,包括接口。我认为我可以允许通过 importing/exporting 接口类型和外部函数进行模块化编译(很像 C++,我不会将语言限制为仅 类 的方法)。
这种方法允许我在界面中包含特定于语言的信息,而无需在 IR 中对其进行编码,因为使用界面构建时需要库和调用代码。这再次要求接口兼容。
一种需要扩展信息的语言功能是函数中的命名参数。
我的语言是非常类型安全的,并且还要求命名参数,因此没有预先确定的函数参数顺序。这允许调用站点更加明确,编译器可以捕获错误的参数使用,并且作者可以更自由地确定默认参数,因为它们不限于函数的最后一个参数。
编译器需要知道这些参数的名称、修饰符、默认值等,以便在编译时正确映射调用,所以我认为接口方法在这里会很有效。
TL;DR
- LLVM 是否有任何用于构建静态库的预定义工具?
- 版本号、大小和 CRC 信息是否是 LLVM 元数据的合理用例?
这可能不是一个完整的答案...或者至少不是一个完整的答案。
我喜欢这个问题,因为我将来(在接下来几个月或几年的某个时候)也需要为我的 Pascal 编译器提供解决方案。它支持 "units" 这意味着是一个单独编译的对象,但目前我所做的只是简单地拖入源文件并将其编译到主要 llvm::Module
- 这既不高效也不灵活(不能例如,使用 linker 在某些代码的 "Linux" 和 "Windows" 版本之间进行选择 - 并不是说我认为我的编译器有 5% 的机会可以在 Windows 反正没有修改...)
但是,我不确定将 "object" 文件存储为 LLVM IR 是否正确。我在想更好的方法是以某种序列化形式存储你的 AST - 然后
- 您不依赖于更改 IR 格式的 LLVM 版本。
- 您可以添加任何您喜欢的元数据。不会有太多
在 link 阶段或从中生成 LLVM-IR 的区别
在编译时构建 IR,然后读取 IR 以确定是否
元数据是正确的。 [你可能已经发现,最慢的部分是优化和 MC 生成,无论哪种方式你仍然必须这样做]
就像我开始时一样,我不确定这是一个答案,但这是我到目前为止对这个主题的想法。现在我要回去为我的 Pascal 编译器添加调试符号了……圣诞节前,我在 GDB 中看不到源代码。现在我可以一步了,但还没有查看变量...
我正在使用 C++ API 在 LLVM 中开发一种新语言,它编译下来以 C ABI 为目标。
我想通过允许最终用户构建有效的静态库来支持模块化编译。我注意到 LLVM C++ API 有一个 llvm::Linker class that I can use during compilation to combine source files (llvm::Module),但是我想通过元数据版本号或至少在单独的编译运行之间公开暴露的接口来保证库兼容性。
LLVM 中 metadata 上的许多可用信息表明,它应该仅用于扩展信息,在静默删除时不会破坏正确性。
我不认为这会破坏交易,因为它可能是全局元数据,但在这一点上征求第二意见会很好。
我也知道 IRReader to parseIRFile 中有一个方法,所以我可以加载一些以前构建的 bc 文件。我很好奇在加载这些文件时包含大小和 CRC 信息以进行比较是否合理。
我的语言有类似于 C# 的概念,包括接口。我认为我可以允许通过 importing/exporting 接口类型和外部函数进行模块化编译(很像 C++,我不会将语言限制为仅 类 的方法)。
这种方法允许我在界面中包含特定于语言的信息,而无需在 IR 中对其进行编码,因为使用界面构建时需要库和调用代码。这再次要求接口兼容。
一种需要扩展信息的语言功能是函数中的命名参数。
我的语言是非常类型安全的,并且还要求命名参数,因此没有预先确定的函数参数顺序。这允许调用站点更加明确,编译器可以捕获错误的参数使用,并且作者可以更自由地确定默认参数,因为它们不限于函数的最后一个参数。
编译器需要知道这些参数的名称、修饰符、默认值等,以便在编译时正确映射调用,所以我认为接口方法在这里会很有效。
TL;DR
- LLVM 是否有任何用于构建静态库的预定义工具?
- 版本号、大小和 CRC 信息是否是 LLVM 元数据的合理用例?
这可能不是一个完整的答案...或者至少不是一个完整的答案。
我喜欢这个问题,因为我将来(在接下来几个月或几年的某个时候)也需要为我的 Pascal 编译器提供解决方案。它支持 "units" 这意味着是一个单独编译的对象,但目前我所做的只是简单地拖入源文件并将其编译到主要 llvm::Module
- 这既不高效也不灵活(不能例如,使用 linker 在某些代码的 "Linux" 和 "Windows" 版本之间进行选择 - 并不是说我认为我的编译器有 5% 的机会可以在 Windows 反正没有修改...)
但是,我不确定将 "object" 文件存储为 LLVM IR 是否正确。我在想更好的方法是以某种序列化形式存储你的 AST - 然后
- 您不依赖于更改 IR 格式的 LLVM 版本。
- 您可以添加任何您喜欢的元数据。不会有太多 在 link 阶段或从中生成 LLVM-IR 的区别 在编译时构建 IR,然后读取 IR 以确定是否 元数据是正确的。 [你可能已经发现,最慢的部分是优化和 MC 生成,无论哪种方式你仍然必须这样做]
就像我开始时一样,我不确定这是一个答案,但这是我到目前为止对这个主题的想法。现在我要回去为我的 Pascal 编译器添加调试符号了……圣诞节前,我在 GDB 中看不到源代码。现在我可以一步了,但还没有查看变量...