我想改进为“断言”OCaml 3.12.1构造生成的lambda代码。这是一个例子:
let f x =
assert (x = 4);
assert (2 + x = 6);
assert (x - x = 0);
exit x
上面的文件longfilename.ml代表了我希望改进lambda代码生成的大型OCaml模块。它汇编为:
$ ocamlopt -S longfilename.ml
$ cat longfilename.s
...
.data
.quad 3072
_camlLongfilename__2:
.quad L100007
.quad 9
.quad 9
.quad 2300
L100007: .L100007:
.ascii "longfilename.ml"
.byte 0
.data
.quad 3072
_camlLongfilename__3:
.quad L100006
.quad 7
.quad 9
.quad 2300
L100006: .L100006:
.ascii "longfilename.ml"
.byte 0
.data
.quad 3072
_camlLongfilename__4:
.quad L100005
.quad 5
.quad 9
.quad 2300
L100005: .L100005:
.ascii "longfilename.ml"
.byte 0
...
以上是非常多余的。每个断言可能来自的源文件的名称是重复的。罪魁祸首似乎是bytecomp / translcore.ml:
let assert_failed loc =
(* [Location.get_pos_info] is too expensive *)
let fname = match loc.Location.loc_start.Lexing.pos_fname with
| "" -> !Location.input_name
| x -> x
in
let pos = loc.Location.loc_start in
let line = pos.Lexing.pos_lnum in
let char = pos.Lexing.pos_cnum - pos.Lexing.pos_bol in
Lprim(Praise, [Lprim(Pmakeblock(0, Immutable),
[transl_path Predef.path_assert_failure;
Lconst(Const_block(0,
[Const_base(Const_string fname);
Const_base(Const_int line);
Const_base(Const_int char)]))])])
;;
从表面上看,它似乎足以给出一个名字
Const_base(Const_string fname)
,并存储和重复使用它
编译时哈希表。对于模块内优化,
这些变化可能是可以控制的
(只要在每个编译单元重置哈希表)。
我有点超出我的深度,尤其是“每次编辑时重置” 单位“部分。任何提示?
答案 0 :(得分:8)
OCaml编译器中已经有一种机制可以共享一些常量:请参阅asmcomp/compilenv.ml
中的structured_constants
及其使用,特别是asmcomp/cmmgen.ml
值。Const_base (Const_string foo)
。我不熟悉这段代码,所以我不确定为什么你的特定用例没有被共享,但似乎在lambda代码Const_immstring foo
和immstring
之间存在差异;后者是共享的,也许前者不是。
我不知道bytecomp/translclass.ml
的预期语义是什么。它似乎在内部编译器用于编译方法标签(asmcomp/cmmgen.ml:emit_constant
),但不会暴露给输入语言。
(我怀疑区别是因为字符串是可变的,因此共享用户可见的字符串将是可观察的并且改变程序行为。但字符串常量已经被提升,因此用户已经可以观察到语义上不一致的共享。增加用户的共享 - 可见字符串可能仍会因兼容性中断而被拒绝。)
看看这些直接字符串由常量发射代码(immstring
)处理的方式,它们就像通常的字符串一样表示,所以也许你可以修改编译器以使用assert_failed
in Const_base (Const_string fname)
并且事情会奏效。
[编辑OP]
将Const_immstring fname
更改为$ cat longfilename.s
...
.data
.quad 3072
_camlLongfilename__2:
.quad L100005
.quad 9
.quad 9
.data
.quad 3072
_camlLongfilename__3:
.quad L100005
.quad 7
.quad 9
.data
.quad 3072
_camlLongfilename__4:
.quad L100005
.quad 5
.quad 9
.quad 2300
L100005: .L100005:
.ascii "longfilename.ml"
.byte 0
虽然稍微不兼容,但允许OCaml自行编译,编译Frama-C并且新的Frama-C通过其回归测试。在原始示例中,效果如下,这正是所需的结果:
{{1}}