【问题标题】:Object oriented three address code generation面向对象的三地址代码生成
【发布时间】:2013-04-27 10:00:59
【问题描述】:

我正在从事与编译器设计相关的项目。我需要为基于 Java 的语言生成三个地址代码,这意味着使用对象和范围。我想您能否帮我为以下示例生成 TAC(或参考我的教程):

class A {
    int x;
    String y;

    public A(int x, String y) {
       this.x = x;
       this.y = y;
    }
}

import A;

class B {
    int f;
    A foo;

    public B() {
       this.foo = null;
       this.f = -1;
    }

    public boolean createFoo() {
       this.foo = new A(0, "TAC Example");
       return true;
    } 

    public static void main() {
       B bar = new B();
       A baz = new A(666, "TAC generation");
       bar.createFoo();
       bar.foo.y = "Hello World";
       if(bar.foo.x == 666)
           return;
       bar.foo.x = baz.x;           
    }        
}

【问题讨论】:

    标签: java code-generation compiler-optimization compiler-construction


    【解决方案1】:

    首先,您需要了解“对象布局”,或者换句话说,对象在运行时在内存 (RAM) 中的外观。这没有标准,但大多数编译器以类似的方式创建对象。我们假设执行将发生在 x86(32 位)机器上,因此指针是 4B 或 32 位,而对于 64 位(x64)机器,指针是 8B。所以对象“A”看起来像这样:“A”对象的前 4 个字节将是指向虚拟指针表的指针。接下来的 4Bytes 或偏移量 4 到 8 将存储“int x”。偏移量 8 到 12 将存储指向“字符串 y”的指针。 A 类的虚拟指针表可以为空,或者 A 对象中偏移量 0 上的指针可以为 NULL - 这取决于编译器。至于“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" 这样的字符串我在堆内存中逐字节分配。
    • 干得好。我很高兴我能帮上忙。问候。
    • 仅供参考,最好的 StackOverflow 礼节“接受”您问题的最佳答案,以便答案的作者因其努力而获得声誉积分。
    • 您能否指出更多关于如何将 OO 语言翻译成 TAC 的理论资源?
    猜你喜欢
    • 2012-01-15
    • 2015-05-30
    • 1970-01-01
    • 2013-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多