Jul*_*ale 1 java compiler-construction code-generation compiler-optimization
我正在做一个与编译器设计相关的项目。我需要为基于 Java 的语言生成三个地址代码,这意味着使用对象和范围。我想您是否可以帮助我为以下示例生成 TAC(或向我推荐教程):
class A {
int x;
String y;
public A(int x, String y) {
this.x = x;
this.y = y;
}
}
Run Code Online (Sandbox Code Playgroud)
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;
}
}
Run Code Online (Sandbox Code Playgroud)
首先,您需要了解“对象布局”,或者换句话说,对象在运行时在内存 (RAM) 中的外观。对此没有标准,但大多数编译器都以类似的方式创建对象。我们假设执行将发生在 x86(32 位)机器上,因此指针是 4B 或 32 位,而对于 64 位(x64)机器,指针是 8B。因此对象“A”将如下所示:“A”对象的前 4 个字节将是指向虚拟指针表的指针。接下来的 4 个字节或偏移量 4 到 8 将存储“int x”。偏移量 8 到 12 将存储指向“字符串 y”的指针。类 A 的虚拟指针表可以为空或对象中偏移量 0 上的指针可以为 NULL - 这取决于编译器。至于“B”类情况类似。偏移量 0 将存储 VPT(虚拟指针表)的地址,偏移量 4"
_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
Run Code Online (Sandbox Code Playgroud)
现在让我们实现主要:
_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
Run Code Online (Sandbox Code Playgroud)
如您所见,这并不太难,但还有一些工作要做。希望这会有所帮助。
| 归档时间: |
|
| 查看次数: |
1843 次 |
| 最近记录: |