【问题标题】:Compiling stack based language to CIL将基于堆栈的语言编译为 CIL
【发布时间】:2012-07-20 05:20:12
【问题描述】:

我有一个基于堆栈的自定义语言,我正在尝试将其编译为 CIL,因此可以对其进行 JIT 处理。该语言本身相当简单,因为它只有整数和布尔值。但是,每种数据类型都有一个专用堆栈。语言本身是一个命令流,其中每个命令都可以从任一堆栈中查看、推送和/或弹出值。命令推送/弹出的整数或布尔值的数量永远不会改变(因此命令具有固定的数量)。还有一个平面整数数组,该语言可以读取和写入值,表示外部存储器。堆栈本身可以任意深。

对于像“add”、“subtract”等简单的命令,将整数堆栈命令转换为 CIL 几乎是微不足道的:CIL 堆栈可以完全替换整数堆栈(尽管我有一个附带问题:是否存在限制 CIL 堆栈的深度,无论是在规范中还是在实践中?)但是还有像 StoreIfTrue 这样的命令,它只会将一个值(来自整数堆栈)存储到某个索引处的平面整数数组(索引也来自整数堆栈)如果布尔堆栈的顶部值为真。所以我需要同时访问一些命令的布尔堆栈和整数堆栈。

现在我必须维护一个 System.Collections.Generic.Stack 来表示布尔堆栈。但我想知道是否有已知的算法或方法可以将我的自定义语言的两个堆栈模型“扁平化”为一个更直接与 CIL 兼容的堆栈模型。

【问题讨论】:

  • CIL 堆栈是无类型的,它可以处理和混合整数和布尔值。应该有一种方法可以将多堆栈执行模型转换为无类型的单堆栈,但从您的问题中不清楚应该如何完成。

标签: .net compiler-construction stack cil


【解决方案1】:

我认为将两个独立的堆栈存储在一个堆栈中是不可能的(至少在没有外部临时存储的情况下,但那样你会得到糟糕的性能)。那是因为无论您使用什么表示,都无法让两个堆栈的顶部以某种方式始终接近实际堆栈的顶部。

但是 CIL 不仅有栈和堆,它还有局部变量。但是您只能通过常量索引访问局部变量。所以,如果你在编译时就一直知道栈顶的索引,并且你也知道栈的最大大小,你可以用局部变量来表示它。但我认为这两个条件不适用于您的情况。

因此,我认为将Stack<T> 用于您的一个或两个堆栈是您的最佳选择。

【讨论】:

  • 处理堆栈的深度可能很棘手,但因为每个命令都有固定的数量,我认为找出一个正在查找的常量索引是可能的。我必须对其进行测试,看看它是否比使用 Stack 快得多。
【解决方案2】:

我无法从您的问题中推断出您是否知道如何从例如 C# 生成 CIL 代码。为此,您可以使用ReflectionCecil

对于虚拟执行系统(VES,将执行 CIL 指令的虚拟系统模型)堆栈(和寄存器)上的值没有关联的复杂类型。 VES 仅跟踪简单类型(int32、int64、托管对象引用、托管指针和浮点数)。因此,VES 无法看到堆栈上的布尔值和整数之间的区别(在内部,VES 将布尔值视为 32 位整数),因此无法使用执行堆栈来模拟布尔堆栈和整数堆栈。您也可以这样做:将布尔值视为整数,将非零整数视为布尔值 true。因此,对两个整数进行比较会产生另一个整数。但是,你只有一个堆栈而不是两个。


编辑

啊,我明白了。您的语言旨在成为通用编程语言,因此必须高度健壮,并且对所有可能的输入(包括无效输入)具有一些预定义(或没有)行为。通过为每种可能的类型设置单独的堆栈,更有可能使用兼容的操作数而不是任何随机操作数。

由于不可能使用单个堆栈来模拟多个堆栈,因此我会为每种类型使用真正的 Stack<T> 对象,而不是尝试使用 CIL 堆栈。这有几个优点:

  • 以后更容易添加新类型
  • 允许堆栈边界检查(例如,使操作成为无操作)
  • 比在一个堆栈上混合类型的任何自定义方案更易于管理
  • 随机访问,如果需要的话
  • 无需了解 CIL 内部原理,因此可以在 Mono 和 .Net 上运行
  • CIL 堆栈仅用于临时操作数、堆栈帧和返回地址

【讨论】:

  • 我可以生成 CIL,是的。我不介意将布尔值视为整数。但是我看不到将两个逻辑堆栈组合到一个物理执行堆栈中的方法。这确实是我问题的核心。
  • 或者换种说法:我的语言使用两台堆栈机器。我如何处理它(作为我的编译步骤的一部分)以有效地使用单个堆栈机器?
  • 一般来说不可能用一个栈来模拟两个栈。为什么首先有两个逻辑堆栈?对我来说更有意义(除非我完全误解了你)只有一个堆栈并将所有布尔值和整数值混合在一起。然后,add 指令可能会弹出两个值(无论它们的类型如何),将它们相加并将结果推回。然后后续的if 指令将获取一个布尔值,它只是获取堆栈的顶部整数(由add 推送的那个)并假装它是一个布尔值。反之亦然。
  • 该语言与另一种称为 Push 的语言非常相似,具有相似的动机(即:基因编程):faculty.hampshire.edu/lspector/push3-description.html。不同数据类型的单独堆栈有助于使其更具容错性(或者这就是希望)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-20
  • 1970-01-01
  • 2012-04-05
  • 2012-11-08
  • 2011-12-16
  • 2020-07-09
  • 2017-02-23
相关资源
最近更新 更多