如何从OCaml .cmm文件生成机器码?及.cmm转Cmm.phrase方法
能否直接从Cmm文件生成机器码?
示例OCaml代码
let rec fib(n: int) = match n with | 0 -> 0 | 1 -> 1 | _ -> fib(n-1) + fib(n-2)
生成的Cmm代码
cmm: (data) (data int 3063 "camlTest__1": addr "camlTest__fib_267" int 72057594037927941) (data int 1792 global "camlTest" "camlTest": int 1) (data global "camlTest__gc_roots" "camlTest__gc_roots": addr "camlTest" int 0) (function{test.ml:1,11-88} camlTest__fib_267 (n/268: val) (if (!= n/268 1) (if (!= n/268 3) (+ (+ (app{test.ml:5,9-17} "camlTest__fib_267" (+ n/268 -2) val) (app{test.ml:5,20-28} "camlTest__fib_267" (+ n/268 -4) val)) -1) 3) 1)) (function camlTest__entry () (let clos/271 "camlTest__1" (store val(root-init) "camlTest" clos/271)) 1) (data)
问题背景
通过ocamlopt -dcmm生成上述Cmm文件后,发现ocamlopt没有直接编译Cmm文件到机器码的命令行选项。尝试使用ocaml-base-compiler中的Asmgen模块生成机器码,但找不到将Cmm文本转换为Cmm.phrase类型的方法。
解决方案
1. OCamlopt无官方直接编译Cmm的选项
ocamlopt的标准工作流是从.ml/.mli文件逐步编译到Cmm,再生成汇编和机器码,确实没有公开的命令行选项支持直接输入Cmm文件完成编译。
2. 借助编译器内部模块解析Cmm文本
OCaml编译器内部包含未公开的Cmm_lexer(词法分析器)和Cmm_parser(语法分析器),可以用它们将Cmm文本解析为Cmm.phrase类型,再传给Asmgen生成机器码。以下是一个简单的工具框架:
open Cmm open Format let parse_cmm_file filename = let ic = open_in filename in let lexbuf = Lexing.from_channel ic in try let phrases = Cmm_parser.file Cmm_lexer.token lexbuf in close_in ic; phrases with e -> close_in ic; raise e let () = if Array.length Sys.argv <> 2 then failwith "Usage: cmm_to_asm <cmm-file>"; let phrases = parse_cmm_file Sys.argv.(1) in let target = Target.default () in let asm_config = Asmgen.create_config target in Asmgen.compile_phrase asm_config std_formatter phrases
3. 编译自定义工具的注意事项
- 需要链接OCaml编译器库,编译命令示例:
ocamlopt -I +compiler-libs ocamlcommon.cmxa ocamlbytecomp.cmxa ocamloptcomp.cmxa cmm_to_asm.ml -o cmm_to_asm - 不同OCaml版本的内部模块结构可能有差异,需对应调整代码。
- 生成的汇编代码需通过系统汇编器(如
as)和链接器(如ld)处理,最终得到可执行机器码。
总结
虽然没有官方支持的直接编译路径,但利用OCaml编译器内部的解析模块,完全可以实现从Cmm文本生成机器码的需求,仅需自行编写工具衔接解析与代码生成流程。
内容的提问来源于stack exchange,提问作者Liu
相关产品推荐
相关产品推荐

