假设我有时想编写一个为以下语言生成C代码的编译器:
(return-from)
形式),你将如何实现这一目标?你可以用C setjmp()
和longjmp()
(以及在展开堆栈时返回清理点的全局点列表)来做(好)吗?
另一种可能性就是生成C ++代码。
答案 0 :(得分:1)
首先我会考虑几种方法。
一个类似于异常帧。创建每线程链接的结构列表。在调用函数之前,在堆栈上创建一个结构并将其添加到列表的末尾。该结构包含jmp_buf
。调用setjmp
如果它返回0继续使用此函数,否则(以某种方式)检查您是否是return-from
的目标 - 如果是,则继续该函数,否则清理您的本地和longjmp
前一帧。我认为这可能有点过分,这取决于return-from
需要多么灵活。是否只需要从周围词法范围内的函数返回,或者我们是否实际上在调用堆栈中搜索可能存在或可能不存在的命名函数?如果是前者,我怀疑我们是否需要这个。
另一种可能性是使所有引用计数类型实现一个公共接口(在语言实现的内部,这是 - 它不需要对用户可见)。然后你可以创建一个(指向)需要清理的对象的堆栈,以及在该堆栈中创建与调用堆栈级别相对应的索引点的能力。在函数退出时,您将清理所返回的堆栈级别以下的所有变量,只需循环遍历每个变量的列表,而不是需要跳转到调用堆栈上我们上面的例程中的清理代码段。然后你可以longjmp
直接到目标,或者你可以想出一个“调用约定”,其中就你的语言而言,返回值实际上存储在由指针参数确定的位置(一个-param),而关于C的返回值表示你要返回的堆栈中的哪个位置。因此,呼叫者检查返回值是否与他们自己的级别匹配,如果不立即返回,则不需要longjmp
。 longjmp
可能有效,也可能没有效率,这取决于您跳过的堆栈级别,以及检查和返回的重复次数。
这个方案有点像Symbian / C ++中的清理栈。事实上,这更进一步 - 它不是必须实现公共接口的清理资源,堆栈上的内容是一个TCleanupItem,它包含一个知道如何释放资源的函数,以及一些要提供给的资源。那个功能。