首页 > 解决方案 > 使用 OCaml 绑定在 LLVM IR 中定义新类型

问题描述

我正在尝试使用 LLVM 和 OCaml 实现具有用户定义类型的静态类型语言,但我不知道如何将新类型定义实际添加到 LLVM 模块中。

我查看了 OCaml 文档,但没有找到任何功能。我试过LLVM 的回答:Defining a new type via OCaml bindings,但它不起作用。

我尝试过的示例代码:

  let c = Llvm.create_context () in
  let m = Llvm.create_module c "MainModule" in

  let llar = [| Llvm.i16_type c; Llvm.float_type c; |] in

  let value_t = Llvm.struct_type c llar in
  ignore (Llvm.declare_global value_t "value_t" m);

  let llvalue_t = Llvm.named_struct_type c "value_t" in
  Llvm.struct_set_body llvalue_t llar true;

  ignore (Llvm.struct_type c llar);

编译输出:

; ModuleID = 'MainModule'
source_filename = "MainModule"

@value_t = external global { i16, float }

标签: ocamlllvmllvm-ir

解决方案


OCaml 代码:

let () =
  let c = Llvm.create_context () in
  let m = Llvm.create_module c "MainModule" in


  let struct1 = Llvm.named_struct_type c "B" in
  Llvm.struct_set_body struct1 [| Llvm.pointer_type struct1; Llvm.i32_type c|] false;

  let struct2 = Llvm.struct_type c [| Llvm.i32_type c; Llvm.pointer_type (Llvm.i8_type c) |] in


  let main_t = Llvm.function_type (Llvm.void_type c) [| struct1; struct2 |] in
  let _main = Llvm.declare_function "main" main_t m in


  Llvm.print_module "./main.ll" 

生成的 LLVM IR:

; ModuleID = 'MainModule'
source_filename = "MainModule"

%B = type { %B*, i32 }

declare void @main(%B, { i32, i8* })

这个 OCaml 代码:

let () =
  let c = Llvm.create_context () in
  let m = Llvm.create_module c "MainModule" in


  let struct1 = Llvm.named_struct_type c "B" in
  Llvm.struct_set_body struct1 [| Llvm.pointer_type struct1; Llvm.i32_type c|] false;

  let _struct2 = Llvm.struct_type c [| Llvm.i32_type c; Llvm.pointer_type (Llvm.i8_type c) |] in


  Llvm.print_module "./main.ll" m

生成的 LLVM IR:

; ModuleID = 'MainModule'
source_filename = "MainModule"

所以据我了解,新类型声明会自动插入到使用结构的模块中。而且它不仅在 OCaml 绑定中,而且在 C++ 中你也有StructType::create(LLVMContext &Context, StringRef Name),它具有相同的目的。


推荐阅读