Reputation:
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
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