Code Generate

Tiny+代码生成

目录

Tiny+代码生成... 1

一.        说明... 2

二.        CGEN.C说明... 2

1.         对于string的处理... 2

2.         对于bool表达式的处理... 2

3.         对于op表达式的处理... 3

4.         对于while语句的处理... 4

5.         对于read语句的处理... 4

6.         对于write语句的处理... 5

三.        运行结果... 6

四.        实验中遇到的问题... 7

五.        实验感想... 7

六.        附录(详细运行结果)... 7


一.          说明

代码生成部分主要在CODE.C,CODE.H,CGEN.C,CGEN.H中实现。其中对CODE.C未作修改。

二.          CGEN.C说明

1. 对于string的处理

由于要确定内存分配空间,所以规定string的最大长度是MAXSTRING,即32。

把string里面的char一个一个的存放到内存的gp空间里,然后把首字母的内存地址放到ac寄存器上,即返回string首字母的内存地址。

关键代码:

case StringK :

      if (TraceCode) emitComment("-> String") ;

      /* gen code to store a string */

      for(i=0; i<MAXSTRING; i++){

          char ch = tree->attr.name[i];

          if(ch == '\0')

              break;

          emitRM("LDC",ac,(int)ch,0,"load a char");

          emitRM("ST",ac,location+i,gp,"String: store a char");

      }

      emitRM("LDC",ac,location,0,"load the string address");

      location += MAXSTRING-1;

      if (TraceCode)  emitComment("<- String") ;

      break; /* StringK */

2. 对于bool表达式的处理

主要模仿opK表达式:

  • Ø AND操作符:

先判断左边表达式是否为0,若是则直接跳到false case,否则跳到true case;

再判断右边表达式是否为1,若是则跳到true case,否则跳到false case。

关键代码:

case AND:

                emitComment(“->op: And”);

                emitRM(“JEQ”,ac1,1,pc,”br if false”) ;

                emitRM(“JGT”,ac,2,pc,”br if true”) ;

                emitRM(“LDC”,ac,0,ac,”false case”) ;

                emitRM(“LDA”,pc,1,pc,”unconditional jmp”) ;

                emitRM(“LDC”,ac,1,ac,”true case”) ;

                emitComment(“<-op:And”);

            break;

  • Ø OR操作符:

先判断左边表达式是否为1,若是则跳到true case,否则跳到false case;

再判断右边表达式是否为1,若是则跳到true case,否则跳到false case。

关键代码:

case OR:

                            emitComment(“->op: OR”);

                            emitRM(“JGT”,ac1,3,pc,”br if true”) ;

                            emitRM(“JGT”,ac,2,pc,”br if true”) ;

                            emitRM(“LDC”,ac,0,ac,”false case”) ;

                            emitRM(“LDA”,pc,1,pc,”unconditional jmp”) ;

                            emitRM(“LDC”,ac,1,ac,”true case”) ;

                            emitComment(“<-op:OR”);

                     break;

3. 对于op表达式的处理

添加了>,>=,<=三个比较符

关键代码:

case MT :

               emitRO(“SUB”,ac,ac1,ac,”op >”) ;

               emitRM(“JGT”,ac,2,pc,”br if true”) ;

               emitRM(“LDC”,ac,0,ac,”false case”) ;

               emitRM(“LDA”,pc,1,pc,”unconditional jmp”) ;

               emitRM(“LDC”,ac,1,ac,”true case”) ;

               break;

                     case LOE :

               emitRO(“SUB”,ac,ac1,ac,”op >”) ;

               emitRM(“JLE”,ac,2,pc,”br if true”) ;

               emitRM(“LDC”,ac,0,ac,”false case”) ;

               emitRM(“LDA”,pc,1,pc,”unconditional jmp”) ;

               emitRM(“LDC”,ac,1,ac,”true case”) ;

               break;

                     case MOE :

               emitRO(“SUB”,ac,ac1,ac,”op >”) ;

               emitRM(“JGE”,ac,2,pc,”br if true”) ;

               emitRM(“LDC”,ac,0,ac,”false case”) ;

               emitRM(“LDA”,pc,1,pc,”unconditional jmp”) ;

               emitRM(“LDC”,ac,1,ac,”true case”) ;

               break;

4. 对于while语句的处理

while语句的代码生成:

 

p1是child[0],即while的判断条件;p2是child[1],即while的执行语句。

关键代码:

case WhileK:

               if (TraceCode) emitComment(“-> while”) ;

         p1 = tree->child[0] ;

         p2 = tree->child[1] ;

               savedLoc1 = emitSkip(0);

         emitComment(“while: jump after body comes back here”);

               /* generate code for test */

         cGen(p1);

               savedLoc2 = emitSkip(1) ;

         emitComment(“while: jump to end belongs here”);

               /* recurse on body part */

         cGen(p2);

               /*go back to the test without any condition*/

               emitRM_Abs(“LDA”,pc,savedLoc1,”jmp to the while test”) ;

               /*if while test is false jump to the end*/

               currentLoc = emitSkip(0) ;

         emitBackup(savedLoc2) ;

         emitRM_Abs(“JEQ”,ac,currentLoc,”while: jmp to the end”);

               emitRestore() ;

         if (TraceCode)  emitComment(“<- while”) ;

     break; /* while */

5. 对于read语句的处理

输入赋值前添加了变量类型的判断,如果类型不是String的话就按照原来的代码执行;如果类型是String的话,则把该string的char字符一个个放到内存gp空间里,并把首字母的内存地址赋值给该变量。

关键代码:

case ReadK:

         if (TraceCode) emitComment("-> read") ;

         loc = st_lookup(tree->attr.name);

         /*if the id is a string, then read and store the chars in the string one by one*/

         if(type_lookup(tree->attr.name) == String){

             for(i=0; i<MAXSTRING; i++){

                 emitRO("IN",ac,0,0,"read a char");

                 emitRM("ST",ac,location+i,gp,"read: store value");

            }

            emitRM("LDC",ac,location,0,"load the string address");

            location += MAXSTRING-1;

         }

         emitRM("ST",ac,loc,gp,"read: store value");

         if (TraceCode) emitComment("<- read") ;

     break;

6. 对于write语句的处理

输出前添加了变量类型的判断,如果类型不是String的话就按照原来的代码执行;如果类型是String的话,则变量储存的内存地址,把该string的char字符一个个从内存gp空间里取出来并打印。

关键代码:

case WriteK:

if (TraceCode) emitComment("-> write") ;

         /* generate code for expression to write */

         p1 = tree->child[0] ;

         cGen(p1);

         if(p1->type == String){

             for(i=0; i<MAXSTRING; i++){

/*

*Here has a problem, ac stores the address of a string,

*but i don't know how to find the value in gp memory according to this address.

*It seems that tm doesn't provide this service.

*The offset here i written is ac+i, but actually is the value of ac plus i. :(

*/

                emitRM("LD",ac1,(ac)+i,gp,"write: load value”);

                emitRO(“OUT”,ac1,0,0,”write ac”);

             }

         }

         else

            emitRO(“OUT”,ac,0,0,”write ac”);

         if (TraceCode) emitComment(“<- write”) ;

         break;

三.          运行结果

测试代码:

string str;

int x, fact;

str:= 'sample program' ;

read x;

if x>0 and x<100 then {don't compute if x<=0}

       fact:=1;

       while x>0 do

              fact:=fact*x;

              x:=x-1

       end;

       write fact

end

输出结果:(文字版放在附录)

 

四.         实验中遇到的问题

修改write语句关于string输出的时候,遇到了问题。相关代码如下:

if(p1->type == String){

             for(i=0; i<MAXSTRING; i++){

/*

*Here has a problem, ac stores the address of a string,

*but i don't know how to find the value in gp memory according to this address.

*It seems that tm doesn't provide this service.

*The offset here i written is ac+i, but actually is the value of ac plus i. :(

*/

                emitRM("LD",ac1,(ac)+i,gp,"write: load value”);

                emitRO(“OUT”,ac1,0,0,”write ac”);

             }

         }

TM代码貌似没有提供把寄存器ac的值作为内存地址,去取这个地址对应的东西。所以此处的实现是有问题的。由于是TM代码的缺陷,暂时想不到解决的方案。还有一个问题是,TM能否输出字符的问题。我看原来tiny生成代码,好像只能输出数字,未知如何控制输出是字符。

五.          实验感想

老实说,这个代码生成我写了一个通宵。其实我觉得代码生成比语义分析要难,难是难在关于string的处理。我请教了部分生成TM代码的同学,因为他们说很简单,仔细问了一下,发现他们都直接把string当成integer去处理。我觉得这个是很有问题的!

个人觉得寄存器只能存string的地址,而不是整个string。string和数字是不能等同的!这是一个值还是一个指针(也就是地址)的差别!我绝不允许自己这样子蒙混过关的!(聊过以后,那些同学也承认了自己的偷工减料,但懒得去改。)

于是我把string的字符一个个存放到内存里,赋值给变量的话是直接赋值其地址,也就是说String变量里存的不是string本身,而是存放这个string的内存地址。虽然这次写的时间比预想中要多,但至少我认真对待了,而且对内存管理、指针等概念有了更深刻的认识。

——黄聪

 

六.         附录(详细运行结果)

测试代码:

string str;

int x, fact;

str:= 'sample program' ;

read x;

if x>0 and x<100 then {don't compute if x<=0}

       fact:=1;

       while x>0 do

              fact:=fact*x;

              x:=x-1

       end;

       write fact

end

运行结果:

* TINY Compilation to TM Code

* File: test.tm

* Standard prelude:

  0:     LD  6,0(0) load maxaddress from location 0

  1:     ST  0,0(0)   clear location 0

* End of standard prelude.

* -> assign

* -> String

  2:    LDC  0,115(0)      load a char

  3:     ST  0,3(5)   String: store a char

  4:    LDC  0,97(0)       load a char

  5:     ST  0,4(5)   String: store a char

  6:    LDC  0,109(0)     load a char

  7:     ST  0,5(5)   String: store a char

  8:    LDC  0,112(0)      load a char

  9:     ST  0,6(5)   String: store a char

 10:    LDC  0,108(0)     load a char

 11:     ST  0,7(5)   String: store a char

 12:    LDC  0,101(0)     load a char

 13:     ST  0,8(5)   String: store a char

 14:    LDC  0,32(0)       load a char

 15:     ST  0,9(5)   String: store a char

 16:    LDC  0,112(0)      load a char

 17:     ST  0,10(5)        String: store a char

 18:    LDC  0,114(0)      load a char

 19:     ST  0,11(5)        String: store a char

 20:    LDC  0,111(0)      load a char

 21:     ST  0,12(5)        String: store a char

 22:    LDC  0,103(0)     load a char

 23:     ST  0,13(5)        String: store a char

 24:    LDC  0,114(0)      load a char

 25:     ST  0,14(5)        String: store a char

 26:    LDC  0,97(0)       load a char

 27:     ST  0,15(5)        String: store a char

 28:    LDC  0,109(0)     load a char

 29:     ST  0,16(5)        String: store a char

 30:    LDC  0,3(0) load the string address

* <- String

 31:     ST  0,0(5)   assign: store value

* <- assign

* -> read

 32:     ST  0,1(5)   read: store value

* <- read

* -> if

* -> Bool

* -> Op

* -> Id

 33:     LD  0,1(5) load id value

* <- Id

 34:     ST  0,0(6)   op: push left

* -> Const

 35:    LDC  0,0(0) load const

* <- Const

 36:     LD  1,0(6) op: load left

 37:    SUB  0,1,0   op >

 38:    JGT  0,2(7)   br if true

 39:    LDC  0,0(0) false case

 40:    LDA  7,1(7) unconditional jmp

 41:    LDC  0,1(0) true case

* <- Op

 42:     ST  0,0(6)   op: push left

* -> Op

* -> Id

 43:     LD  0,1(5) load id value

* <- Id

 44:     ST  0,-1(6) op: push left

* -> Const

 45:    LDC  0,100(0)     load const

* <- Const

 46:     LD  1,-1(6)        op: load left

 47:    SUB  0,1,0   op <

 48:    JLT  0,2(7)   br if true

 49:    LDC  0,0(0) false case

 50:    LDA  7,1(7) unconditional jmp

 51:    LDC  0,1(0) true case

* <- Op

 52:     LD  1,0(6) op: load left

* ->op: And

 53:    JEQ  1,1(7) br if false

 54:    JGT  0,2(7)   br if true

 55:    LDC  0,0(0) false case

 56:    LDA  7,1(7) unconditional jmp

 57:    LDC  0,1(0) true case

* <-op:And

* <- Bool

* if: jump to else belongs here

* -> assign

* -> Const

 59:    LDC  0,1(0) load const

* <- Const

 60:     ST  0,2(5)   assign: store value

* <- assign

* -> while

* while: jump after body comes back here

* -> Op

* -> Id

 61:     LD  0,1(5) load id value

* <- Id

 62:     ST  0,0(6)   op: push left

* -> Const

 63:    LDC  0,0(0) load const

* <- Const

 64:     LD  1,0(6) op: load left

 65:    SUB  0,1,0   op >

 66:    JGT  0,2(7)   br if true

 67:    LDC  0,0(0) false case

 68:    LDA  7,1(7) unconditional jmp

 69:    LDC  0,1(0) true case

* <- Op

* while: jump to end belongs here

* -> assign

* -> Op

* -> Id

 71:     LD  0,2(5) load id value

* <- Id

 72:     ST  0,0(6)   op: push left

* -> Id

 73:     LD  0,1(5) load id value

* <- Id

 74:     LD  1,0(6) op: load left

 75:    MUL  0,1,0   op *

* <- Op

 76:     ST  0,2(5)   assign: store value

* <- assign

* -> assign

* -> Op

* -> Id

 77:     LD  0,1(5) load id value

* <- Id

 78:     ST  0,0(6)   op: push left

* -> Const

 79:    LDC  0,1(0) load const

* <- Const

 80:     LD  1,0(6) op: load left

 81:    SUB  0,1,0   op -

* <- Op

 82:     ST  0,1(5)   assign: store value

* <- assign

 83:    LDA  7,-23(7)      jmp to the while test

 70:    JEQ  0,13(7)        while: jmp to the end

* <- while

* -> write

* -> Id

 84:     LD  0,2(5) load id value

* <- Id

 85:    OUT  0,0,0   write ac

* <- write

* if: jump to end belongs here

 58:    JEQ  0,28(7)        if: jmp to else

 86:    LDA  7,0(7) jmp to end

* <- if

* End of execution.

 87:   HALT  0,0,0   

代码和文档下载请按 https://files.cnblogs.com/sandywong/TINY%e5%8a%a0.rar

posted @ 2011-02-08 19:40  free_swallow  阅读(398)  评论(0编辑  收藏  举报