Store global string in mutable variable using LLVM API

I am making a compiler for a subset of PHP using LLVM and OCaml. LLVM string processing tutorials are a bit missing - at least I can't find them.

This is the code I want to compile:

<?php $a = "foo"; 

This is my typed AST for the code above:

 [(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> here simply means that pos (position) is not displayed.)

This is my generated 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 } 

And my error message:

 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! 

The problem is that i8* %"$a" should be i8** %"$a" , as shown in LLVM IR for a simple C program:

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

which this LLVM IR will generate:

 @.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 } 

Any help was appreciated.

+4
source share
1 answer

Solved (I really hope) by changing the allocation code. Instead

 build_alloca i8_t ... 

he should be

 build_alloca (pointer_type i8_t) ... 

I debugged this by editing the generated code directly and then compiling it with llc to see what needs to be changed.

+1
source

All Articles