MSIL 和 LLVM bitcode 有什么区别?

11

我是.Net的新手,正在努力先了解基础知识。MSIL和LLVM bitcode有什么区别?


你是指微软的“.Net Framework”吗?如果是,那么这与Swift或LLVM有什么关系(据我所知没有)? - Qbyte
1个回答

22

LLVM比特码和MSIL都是中间语言。本质上,它们是一种通用的汇编代码语言:不像大多数源语言(例如Swift、C#)那样高级,但也不像真正的汇编语言(例如ARM、x86)那样低级。两种语言之间存在许多技术实现差异,但大多数开发人员不需要知道这些细节*.他们只需要知道在各自平台的分布模型中如何使用它们。


LLVM bitcode格式是LLVM编译器中使用的中间表示代码的序列化版本。编译器的“前端”将源语言(如Swift)转换为LLVM位码,然后编译器的“后端”将位码转换为目标指令集(如ARM机器码)。请注意:之前的回答暗示LLVM位码是处理器无关的。这不是事实,因为源语言取决于目标处理器。
Apple允许iOS开发者将其应用程序提交为完全编译的ARM代码或LLVM位码,后者:
[...]将允许Apple在未来重新优化您的应用程序二进制文件,而无需向商店提交新版本的应用程序。
基本上,您在开发环境上运行LLVM前端,将位码传递给Apple,他们在服务器上运行LLVM后端。这个过程被称为预编译(AOT)编译(维基百科文章对非位码情况是否也是AOT或只是“标准”编译有两种看法)。
但无论您是否使用位码,iOS最终用户始终以ARM机器码形式获取应用程序。
在.NET中,情况有些不同。大多数.NET代码被编译为MSIL,并打包到名为程序集的文件中。最终用户设备上的.NET运行时加载并执行程序集,在运行时将MSIL编译成设备处理器的机器码。这被称为即时(JIT)编译
通常,MSIL是处理器无关的,因此大多数开发人员可以认为.NET应用程序也是处理器无关的。但是,在最终用户通过JIT运行应用程序之前,可以采用许多特定于处理器的代码打包方式。
  1. 一些工具,例如 本地图像生成器.NET Native,可以进行AOT编译。实际上,上传到Microsoft Store的通用Windows平台(UWP)应用程序都是经过AOT编译的-您将应用程序的MSIL版本提交给Microsoft,然后他们的服务器使用.NET Native将其编译为Windows 10支持的各种体系结构。

  2. 还可以将本机代码与程序集本身一起包含; 这些被称为混合程序集

  3. 如果源语言使用“不安全”操作(例如,C#中的指针运算),则MSIL本身可以是处理器特定的。

但这些通常是例外,而不是规则。通常,.NET应用程序以MSIL形式分发,并且最终用户的设备是生成本地代码的地方。


总之:

  • LLVM位码是特定于处理器的,但不像实际机器码那样低级。苹果允许iOS开发者将应用程序提交为位码,以便在未来引入优化时进行重新编译。最终用户运行本地可执行文件。

  • MSIL通常不特定于处理器。最终用户通常运行这种处理器不可知的代码,.NET会在运行时将MSIL编译为本地代码。但是,在某些情况下,一些或所有应用程序可能是本地代码。


* 当然,如果您对技术细节感兴趣,有LLVM比特码的标准在ECMA名称CIL下的MSIL的标准。我在后者方面有一定的知识;经过对前者的粗略浏览,最显着的技术差异是内存模型:LLVM比特码是基于寄存器的,而MSIL/CIL使用评估堆栈。


1
LLVM IR 目标于低级虚拟机,它不必是特定的处理器架构。看看它针对 wasm,这是一个特定于浏览器/ JavaScript 模拟的虚拟机。了解 LLVM 是 AOT,而 MSIL 是 JIT(带有 AOT 提示和本地混合模式扩展)是很好的。 - TamusJRoyce

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接