1

Java 類似言語から LLVM へのコンパイラーを作成しています。ただし、メモリの割り当てと参照でいくつかの問題に遭遇しました。これは私がコンパイルしようとするコードです:

class Node {
  Node a;
}

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

そして、LLVM コードを生成します (申し訳ありませんが、これより短くすることはできません)。

%struct.Node の i32、i32* は、将来的に内部情報を保持することを目的としています。

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
}

実行中に valgrind にエラーが表示されます:

==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: ???

行の1つを削除すると、奇妙で​​す:

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

問題は消えます。また、置換されたプログラム

class Node {
  Node a;
}

class Node {
  int a;
}

オブジェクトフィールドで同様の操作を実行しても、エラーは発生しません。

4

1 に答える 1