0
点赞
收藏
分享

微信扫一扫

Transpiler 如何实现源代码的对应关系


最近在写一个 IEC 61131-3 中的结构化文本 (ST) 到 C 语言的 transpiler,遇到一个小小的麻烦,调试时,用户看到的是 ST 代码,而调试器看到的 C 语言的 debug symbols,怎么把两者对应起来呢。最开始我想的是自己来实现映射关系,理论上是可行的,但是有些额外的工作要做。

是否有更简单的办法呢?我想其它 transpiler 应该有同样的需求。为此研究了一下 ​​Vala​​ 的做法,Vala 语言也是把自己翻译成 C 语言,再用 gcc 来编译的。

先写一个小程序(t.vala)

void main () {
print ("hello, world\n");
}

  • 编译:

valac -v -g t.vala

编译时加一个-v 参数,我们可以看到,valac 先把 t.vala 转换成 t.vala.c,再调用 cc 去编译生成 t 。

Loaded package `/usr/local/share/vala-0.56/vapi/glib-2.0.vapi'
Loaded package `/usr/local/share/vala-0.56/vapi/gobject-2.0.vapi'
cc -g -o '/Users/jim/work/lab/lang/vala-0.56.1/compiler/demo/t' '/Users/jim/work/lab/lang/vala-0.56.1/compiler/demo/t.vala.c' -I/usr/local/Cellar/libffi/3.3_3/include -I/usr/local/Cellar/glib/2.68.4/include -I/usr/local/Cellar/glib/2.68.4/include/glib-2.0 -I/usr/local/Cellar/glib/2.68.4/lib/glib-2.0/include -I/usr/local/opt/gettext/include -I/usr/local/Cellar/pcre/8.45/include -L/usr/local/Cellar/glib/2.68.4/lib -L/usr/local/opt/gettext/lib -lgobject-2.0 -lglib-2.0 -lintl

  • 调试:

Transpiler 如何实现源代码的对应关系_服务器

我们可以看到,虽然可执行文件 t 是由 t.vala.c 生成的,但是调试器里看到源码仍然是原始的 t.vala。这个是怎么做到的呢?

那个得先看看 t.vala.c 长什么样的了。但是 t.vala.c 是个临时文件,编译完后就被删除了。开始想了一个土的办法,在 vala_ccode_compiler_compile 里的 585 行,把删除临时文件的代码注释掉,就拿到了 t.vala.c 。后来发现可以直接生成 C 代码:

valac -g -c t.vala

t.vala.c 的内容:

/* t.vala.c generated by valac 0.56.1, the Vala compiler
* generated from t.vala, do not modify */

#include <glib.h>

static void _vala_main (void);

static void
_vala_main (void)
{
#line 2 "t.vala"
g_print ("hello, world\n");
#line 14 "t.vala.c"
}

int
main (int argc,
char ** argv)
{
#line 1 "t.vala"
_vala_main ();
#line 1 "t.vala"
return 0;
#line 25 "t.vala.c"
}

原来是通过 #line 宏指令实现的,#line 指令并不陌生,在 bison/yacc/flex 生成的代码里经常见到。这里有 ​​line 指令​​详细的解释。


举报

相关推荐

0 条评论