user2781190
user2781190

Reputation:

LLVM malloc and memory referencing

I am writing compiler from Java similar language to LLVM. However I've met some difficulties in allocating memory and referencing to it. This is code which I try to compile:

class Node {
  Node a;
}

int main () {
  Node n = new Node;
  n.a = new Node;
  return 0;
}

And I generate LLVM code (sorry, it can't be shorter):

i32, i32* in %struct.Node are intended to hold some internal info in future

declare i8* @malloc(i32)

%struct.Node = type { i32, i32* , %struct.Node*}
define i32 @main()
{

    %temp_0 = call i8* @malloc(i32 12)
    %temp_1 = bitcast i8* %temp_0 to %struct.Node*
    call void @Node_init(%struct.Node* %temp_1)
    %var_0 = alloca %struct.Node*
    store %struct.Node* %temp_1, %struct.Node** %var_0

    %temp_3= load %struct.Node** %var_0
    %temp_4 = getelementptr inbounds %struct.Node* %temp_3, i32 0, i32 2

    %temp_6 = call i8* @malloc(i32 12)
    %temp_7 = bitcast i8* %temp_6 to %struct.Node*
    call void @Node_init(%struct.Node* %temp_7)
     store %struct.Node* %temp_7, %struct.Node** %temp_4
     ret i32 0
}
define void @Node_init(%struct.Node* %temp_0)
{
     %var_0 = alloca %struct.Node*
     %temp_10 = getelementptr inbounds %struct.Node* %temp_0, i32 0 
    store %struct.Node*  %temp_10, %struct.Node**  %var_0

    %temp_11= load %struct.Node** %var_0
    %temp_12 = getelementptr inbounds %struct.Node* %temp_11, i32 0, i32 2
     store %struct.Node* null, %struct.Node** %temp_12

     ret void
}

During execution valgrind shows error:

==3217== Invalid write of size 4
==3217==    at 0x5A8901F: ???
==3217==  Address 0x570dff8 is 4 bytes after a block of size 12 alloc'd
==3217==    at 0x402BB7A: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3217==    by 0x5A8901E: ???

It is strange, because when I remove one of lines:

 call void @Node_init(%struct.Node* %temp_7)
 store %struct.Node* %temp_7, %struct.Node** %temp_4

the problem dissapears. Also program with replaced

class Node {
  Node a;
}

with

class Node {
  int a;
}

and performing similar operations on object field doesn't cause any errors.

Upvotes: 2

Views: 4748

Answers (1)

Oak
Oak

Reputation: 26868

It looks as if the size of pointers is 8 bytes on your target, while you assumed it's only 4. So getelementptr %temp, 0, 2 returned the pointer's location + 12, not its location + 8.

In other words, change the mallocs to allocate 20 bytes, not 12, and it should work.

In general, when generating the IR, be sure to properly set up the target data and then use the DataLayout class to retrieve the pointer size.

Upvotes: 3

Related Questions