Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 面向对象的三地址代码生成_Java_Code Generation_Compiler Optimization_Compiler Construction - Fatal编程技术网

Java 面向对象的三地址代码生成

Java 面向对象的三地址代码生成,java,code-generation,compiler-optimization,compiler-construction,Java,Code Generation,Compiler Optimization,Compiler Construction,我在做一个与编译器设计相关的项目。我需要为基于Java的语言生成三个地址代码,这意味着使用对象和作用域。我希望您能帮助我生成以下示例的TAC(或让我参考教程): 首先,您需要了解“对象布局”,或者换句话说,对象在运行时在内存(RAM)中的外观。这方面没有标准,但大多数编译器都以类似的方式创建对象。我们假设执行将发生在x86(32位)机器上,因此指针是4B或32位,而对于64位(x64)机器,指针是8B。所以对象“A”看起来是这样的:“A”对象的前4个字节将是指向虚拟指针表的指针。接下来的4字节

我在做一个与编译器设计相关的项目。我需要为基于Java的语言生成三个地址代码,这意味着使用对象和作用域。我希望您能帮助我生成以下示例的TAC(或让我参考教程):



首先,您需要了解“对象布局”,或者换句话说,对象在运行时在内存(RAM)中的外观。这方面没有标准,但大多数编译器都以类似的方式创建对象。我们假设执行将发生在x86(32位)机器上,因此指针是4B或32位,而对于64位(x64)机器,指针是8B。所以对象“A”看起来是这样的:“A”对象的前4个字节将是指向虚拟指针表的指针。接下来的4字节或偏移量4到8将存储“intx”。偏移量8到12将存储指向“字符串y”的指针。类A的虚拟指针表可以为空,或者对象中偏移量0上的指针可以为空-这取决于编译器。至于“B”类,情况类似。偏移量0将存储VPT(虚拟指针表)的地址、偏移量4“int f”和偏移量8指向“A foo”的指针。在B的VPT中,“createFoo”地址将存储在偏移量0处,因为它是B类中唯一的方法。现在让我们来实现:

_B.createFoo:
    BeginFunc 12    // stack frame size = 3 registers * sizeof( each_register )
    _t0 = 8         // size of A object
    PushParam _t0   // this is the memory ammount that we are asking
    _t1 = LCall _Alloc  // allocate memory
    PopParams 4     //  clear stack
    _t2 = A
    *(_t1) = _t2    // load VPT
    *(_t1 + 4) = 0  // initialize _A.x
    *(_t1 + 8) = "TAC Example"  // initialize _A.foo
    *(this + 8) = _t1
    Return 1
    EndFunc
现在让我们实现main:

_B.main:
    BeginFunc 68    // 15 * 4 + 2 * 4 
    _t0 = 8         // size of B object
    PushParam _t0   // memory amount that we need
    _t1 = LCall _Alloc  // allocate memory
    PopParams 4     //  clear stack
    _t2 = B
    *(_t1) = _t2    // load VPT
    *(_t1 + 4) = 0  // initialize _B.foo
    *(_t1 + 8) = -1 // initialize _B.f
    bar = _t1
    _t3 = 8         // size of A object
    PushParam _t3   // this is the memory ammount that we are asking
    _t4 = LCall _Alloc  // allocate memory
    PopParams 4     //  clear stack
    _t5 = A
    *(_t4) = _t5    // load VPT
    *(_t4 + 4) = 666    // initialize _A.x
    *(_t4 + 8) = "TAC generation"   // initialize _A.foo
    baz = _t4
    _t6 = *(bar)    // address of _B.VPT
    _t7 = *(_t6)    // address of _B.createFoo
    PushParam bar   // this for createFoo
    ACall _t7       // call _B.createFoo
    PopParams 4     // clear stack
    _t8 = *(bar + 8)    // get _B.foo
    _t9 = *(_t8 + 8)    // get _B.foo.y
    *(_t9) = "Hello world"  // set _B.foo.y value
    _t10 = *(bar + 8)   // get _B.foo
    _t11 = *(_t10 + 4)  // get _B.foo.x
    _t12 = _t11 == 666  // test _B.foo.x equal to 666
    IfZ _t12 GoTo _L0   // if not equal continue to _L0
    Return
    _L0:
    _t13 = *(bar + 8)   // get _B.foo
    _t14 = _t13 + 4     // get address of _B.foo.x
    _t15 = *(baz + 4)   // get _A.x
    *(_t14) = _t15      // set _B.foo.x
    EndFunc

正如你所看到的,这并不太难,但还有一些工作要做。希望这会有所帮助。

首先,您需要了解“对象布局”,或者换句话说,对象在运行时在内存(RAM)中的外观。这方面没有标准,但大多数编译器都以类似的方式创建对象。我们假设执行将发生在x86(32位)机器上,因此指针是4B或32位,而对于64位(x64)机器,指针是8B。所以对象“A”看起来是这样的:“A”对象的前4个字节将是指向虚拟指针表的指针。接下来的4字节或偏移量4到8将存储“intx”。偏移量8到12将存储指向“字符串y”的指针。类A的虚拟指针表可以为空,或者对象中偏移量0上的指针可以为空-这取决于编译器。至于“B”类,情况类似。偏移量0将存储VPT(虚拟指针表)的地址、偏移量4“int f”和偏移量8指向“A foo”的指针。在B的VPT中,“createFoo”地址将存储在偏移量0处,因为它是B类中唯一的方法。现在让我们来实现:

_B.createFoo:
    BeginFunc 12    // stack frame size = 3 registers * sizeof( each_register )
    _t0 = 8         // size of A object
    PushParam _t0   // this is the memory ammount that we are asking
    _t1 = LCall _Alloc  // allocate memory
    PopParams 4     //  clear stack
    _t2 = A
    *(_t1) = _t2    // load VPT
    *(_t1 + 4) = 0  // initialize _A.x
    *(_t1 + 8) = "TAC Example"  // initialize _A.foo
    *(this + 8) = _t1
    Return 1
    EndFunc
现在让我们实现main:

_B.main:
    BeginFunc 68    // 15 * 4 + 2 * 4 
    _t0 = 8         // size of B object
    PushParam _t0   // memory amount that we need
    _t1 = LCall _Alloc  // allocate memory
    PopParams 4     //  clear stack
    _t2 = B
    *(_t1) = _t2    // load VPT
    *(_t1 + 4) = 0  // initialize _B.foo
    *(_t1 + 8) = -1 // initialize _B.f
    bar = _t1
    _t3 = 8         // size of A object
    PushParam _t3   // this is the memory ammount that we are asking
    _t4 = LCall _Alloc  // allocate memory
    PopParams 4     //  clear stack
    _t5 = A
    *(_t4) = _t5    // load VPT
    *(_t4 + 4) = 666    // initialize _A.x
    *(_t4 + 8) = "TAC generation"   // initialize _A.foo
    baz = _t4
    _t6 = *(bar)    // address of _B.VPT
    _t7 = *(_t6)    // address of _B.createFoo
    PushParam bar   // this for createFoo
    ACall _t7       // call _B.createFoo
    PopParams 4     // clear stack
    _t8 = *(bar + 8)    // get _B.foo
    _t9 = *(_t8 + 8)    // get _B.foo.y
    *(_t9) = "Hello world"  // set _B.foo.y value
    _t10 = *(bar + 8)   // get _B.foo
    _t11 = *(_t10 + 4)  // get _B.foo.x
    _t12 = _t11 == 666  // test _B.foo.x equal to 666
    IfZ _t12 GoTo _L0   // if not equal continue to _L0
    Return
    _L0:
    _t13 = *(bar + 8)   // get _B.foo
    _t14 = _t13 + 4     // get address of _B.foo.x
    _t15 = *(baz + 4)   // get _A.x
    *(_t14) = _t15      // set _B.foo.x
    EndFunc

正如你所看到的,这并不太难,但还有一些工作要做。希望这能有所帮助。

我能够完成我的项目。无论如何,谢谢你。只是一个评论。。。像
“TAC generation”
这样的字符串我在堆内存中一个字节一个字节地分配。干得好。我很高兴我帮了忙。仅供参考,“接受”你问题的最佳答案是一种很好的礼仪,这样答案的作者就可以因为他的努力而获得声誉分数。你有没有可能找到更多关于如何将OO语言翻译成TAC的理论资源?我能够完成我的项目。无论如何,谢谢你。只是一个评论。。。像
“TAC generation”
这样的字符串我在堆内存中一个字节一个字节地分配。干得好。我很高兴我帮了忙。敬请参考,最好是“接受”你问题的最佳答案,这样答案的作者就可以因为他的努力而获得荣誉分数。你有没有可能找到更多关于如何将OO语言翻译成TAC的理论资源?