【问题标题】:What ways exists to generate MSIL from unmanaged code有哪些方法可以从非托管代码生成 MSIL
【发布时间】:2010-07-11 08:09:31
【问题描述】:

我正在尝试为 .NET 平台创建我的语言的后端。 用 Delphi 编写的前端和解释器。 非托管 API 只允许类型定义,但不允许发出 MSIL。

有哪些方法可以从非托管代码生成 MSIL? 不使用 Reflection.Emit 并使用 ILasm 来实现这一点? 谢谢。

【问题讨论】:

    标签: .net delphi compiler-construction backend


    【解决方案1】:

    Delphi 的 .NET 代码生成器将 IL 作为字节码直接发送到内存中,这与 x86 代码生成非常相似,但带有适当的标头等。也就是说,代码生成器直接发出与编码的 IL 格式相对应的字节、异常表等。它不是通过 API 来做到这一点的,而是使用老式的方式:一次编写一个字节的代码。

    稍后,Delphi 的内置链接器与IMetaDataEmit 等一起生成元数据,IMetaDataEmit::SetRVA 告诉元数据代码在可执行文件中的位置。元数据使用IMetaDataEmit::SaveToMemory 复制出来,然后复制到链接器正在构建的 PE 中,并相应地修补 CLR 标头以指向元数据开始。

    它有很多代码,其中一些很繁琐,因为其中大部分是通过 Delphi 现有的 x86 链接器进行线程化的,它执行诸如分支优化和消除未使用代码(智能链接)之类的事情,严格来说这通常不是必需的对于 .NET。

    如果我们重做一遍,我们很可能会避免使用 .NET API 来创建元数据,而直接根据规范生成整个内容。 API 最终成为优化的黑匣子,并增加了大量的编译时间。

    【讨论】:

      【解决方案2】:

      来自非托管代码? TBH,我最好的建议是“使用 P/Invoke”,或者“弄清楚它的用途,然后重新实现它”。

      即使您可以找到一些东西来移植非托管​​代码,并且即使它有效 - 它也不会完全利用框架。而且非托管和托管之间的比例也不完全是 1:1。

      【讨论】:

      • 我需要一个 API,它允许我直接发出 MSIL(从本机 Delphi 读取),而不使用非托管管理的编组(Pinvoke、反向 pinvoke、IJW、COM)。你建议我自己生成 PE 文件吗?
      【解决方案3】:

      你让事情变得困难了。 Codeplex.com 上提供的 Irony 和 Common Compiler Infrastructure 库已经发布,它们针对的是在托管代码中实现的编译器。下一个选项是使用非托管元数据接口,例如 IMetaDataAssemblyEmit、IMetaDataAssemblyImport、IMetaDataEmit2。然而,这些 COM 接口在 cor.h SDK 头文件中声明,仅适用于 C/C++ 程序使用。他们没有可用的类型库。除了煞费苦心地复制接口声明之外,您还需要某种工具将它们转换为 Delphi 声明。不确定是否存在。

      【讨论】:

      • 我在 2 天前手动将 (cor.h corhdr.h) 翻译为 pas 文件。所以非托管 API 可用于我的编译器的本机前端。但 API 不支持为方法实现发出 MSIL。
      • ICeeGen 已过时。我不知道有替代品。
      【解决方案4】:

      MSIL 或 CIL 本质上是 机器码 的 .Net 等价物。当您解析一种语言并将其翻译成机器代码时,您拥有的是一个编译器。任何语言的早期编译器通常都会手动生成它们的机器代码。也就是说,对于源语言中的每种命令或表达式,编写汇编指令的“模板”以将其翻译成。在处理程序的中间表示时,选择相应的模板,填写程序特定的详细信息,然后发出 CIL。对于像 CIL 这样的基于堆栈的语言,将来自多个语句的模板链接在一起应该是相当容易的;一条语句的输出栈是下一条语句的输入栈。

      您需要熟悉CIL instruction set

      您的编译器是非托管代码这一事实并不重要。您可以从任何您想要的程序中生成 CIL 文本。准备好后,通过ilasm 发送它以从中创建程序集。

      【讨论】:

      • Rob,我在 3 年前读过 ECMA335 以及 Serge Lidin 的“Expert .NET 2.0”。 (所以 ilAsm 只是我的另一个朋友)。 Rob,你能问 Barry Kelly 还是 Remobjects 的人,他们是如何解决这个问题的。或者他们都使用混合模式 C++。
      • Prism 编译器是用 Prism 构建的,是 100% 的 .NET 应用程序。
      猜你喜欢
      • 1970-01-01
      • 2013-08-24
      • 1970-01-01
      • 2010-09-20
      • 2010-12-25
      • 1970-01-01
      • 2012-01-14
      • 1970-01-01
      • 2012-03-04
      相关资源
      最近更新 更多