使用LLVM API将全局字符串存储在可变变量中

时间:2015-08-04 16:47:17

标签: php string ocaml llvm

我正在使用LLVM和OCaml为PHP子集编译。 LLVM中字符串处理的教程有点缺乏 - 至少我找不到。

这是我要编译的代码:

<?php

$a = "foo";

这是我输入的以上代码的AST:

[(Typedast.Stmt
    Typedast.Expr (Typedast.TUnit,
      (<opaque>,
       Typedast.Binop ((Typedast.Eq None),
         (<opaque>, Typedast.Lvar ((<opaque>, "$a"), Typedast.TString)),
         (<opaque>, (Typedast.String (<opaque>, "asd"))), Typedast.TUnit))))]

<opaque>此处仅表示pos(位置)未显示。)

这是我生成的LLVM IR:

; ModuleID = 'mymodule'

@foo = private unnamed_addr constant [4 x i8] c"foo\00"

define i32 @main() {
entry:
  %"$a" = alloca i8
  store i8 0, i8* %"$a"
  store i8* getelementptr inbounds ([4 x i8]* @foo, i32 0, i32 0), i8* %"$a"
  ret i32 0
}

我的错误信息:

Stored value type does not match pointer operand type!
  store i8* getelementptr inbounds ([4 x i8]* @asd, i32 0, i32 0), i8* %"$a"
 i8LLVM ERROR: Broken module found, compilation aborted!

问题是i8* %"$a"应该是i8** %"$a",如简单C程序的LLVM IR所示:

int main() {
  char* str = "Hello, world!";
  puts(str);
  return 0;
}

将生成此LLVM IR:

@.str = private unnamed_addr constant [14 x i8] c"Hello, world!\00", align 1

; Function Attrs: nounwind uwtable
define i32 @main() #0 {
  %1 = alloca i32, align 4
  %str = alloca i8*, align 8
  store i32 0, i32* %1
  store i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0), i8** %str, align 8
  %2 = load i8** %str, align 8
  %3 = call i32 @puts(i8* %2)
  ret i32 0
}

任何帮助表示感谢。

1 个答案:

答案 0 :(得分:1)

通过更改分配代码解决(我真的希望)。而不是

build_alloca i8_t ...

应该是

build_alloca (pointer_type i8_t) ...

我通过直接编辑生成的代码然后用llc编译它来调试它,看看需要改变什么。