C编译器剖析_5.2.6 中间代码生成及优化_一元表达式及其他表达式的翻译

来源:互联网 发布:淘宝抢购前1000名半价 编辑:程序博客网 时间:2024/04/30 10:15

5.2.6  一元表达式及其他表达式的翻译

    在这一小节中,我们先来讨论一下一元表达式的翻译,我们先举个例子来说明一下。在以下C程序中,符号arr被声明为int[3][5]的数组类型,UCC编译器在语义检查后,为表达式“**arr=30;”构造的语法树为“(= ([]([] arr  0) 0) 30)”,在中间代码生成阶段,对应的中间代码为“arr[0] = 30;”。由这个例子可见,并不是所有出现在C程序中的“*”运算符都会对应“提领操作Dereference”,即间接寻址。

         int  arr[3][5];

         int * ptr = &arr[0][0];

         void f(void){

                   ** arr = 30;               

                   *ptr = 50;

         }

    对于C表达式“*ptr=50;”,UCC编译器在语义检查后构造的语法树为“(=  (* ptr) 50)”,在中间代码生成阶段,UCC编译器需要为该语法树中的“*”运算符产生“提领Dereference指令”。一元表达式的翻译如图5.2.17所示,第4行调用TranslateBranchExpression函数来计算形如“!a”的布尔表达式的算术值(0或者1),第7行调用我们在第5.2.4节中介绍过的TranslateIncrement函数来翻译表达式“++a”或者“--a”,第14行调用的AddressOf用于产生“取地址指令”,第16行的Deref函数用于产生“提领Dereference指令”,我们也在前面的章节中已分析过这几个函数,这里不再重复。


图5.2.17 TranslateUnaryExpression()

    图5.2.17第12行调用TranslateCast来为形如“(int) a”的表达式产生转型指令,该函数并不复杂,我们也从略。第17至19行用于翻译形如“-a”和“~a”的表达式,我们在第19行调用Simplify函数做一些编译时的代数简化,该函数也已在前面的章节中做过分析。

    接下来我们再分析条件表达式的翻译,以下给出了一段C程序及其对应的中间代码,我们生成临时一个临时变量t0用来存放b+2或b+3的值,然后再把t0赋值给变量c。

         int  a ,b,c;

         c = a > 0? b+2: b+3;

         //////////////////对应的中间代码////////////////////////////

         if(a <= 0) goto BB7;

BB6:    //trueBB

        t1 : b + 2;

         t0= t1;

         gotoBB8;

BB7:    //falseBB

        t2 : b + 3;

         t0= t2;

BB8:    //nextBB

        c = t0;

    UCC编译器中的函数TranslateConditionalExpression用于产生上述中间代码,如图5.2.18

所示,第6行调用的CreateTemp函数用于产生上述临时变量t0,第8行的trueBB对应“BB6”,而第9行的falseBB对应上述“BB7”,第10行的nextBB对应“BB8”。第11行调用TranslateBranch函数来产生上述跳转指令“if (a <= 0) goto BB7;”,第13行递归地调用TranslateExpression函数用来翻译“b+2”,而第15行的GenerateMove用来产生MOV指令“t0 = t1;”,第17行产生无条件跳转指令“goto BB8;”。第18至22行的代码用于翻译“b+3”并产生相应的标号“BB7”和“BB8”。


图5.2.18 TranslateConditionalExpression

    我们已在第5.2.1节时介绍过用于二元表达式的翻译函数TranslateBinaryExpression,而逗号表达式的翻译,可由以下TranslateCommaExpression函数来实现。例如,对逗号表达式“a,b,c”而言,按照C语言的语义,最后一个表达式“c”的值即为整个逗号表达式的值,UCC编译器在语义检查后为“a,b,c”产生的语法树为“(, (, a  b)  c)”。我们只要递归地调用TranslateExpression函数来翻译其左子树和右子树即可。

         // 翻译逗号表达式,我们面对的是形如“(, (, a  b)  c)”的语法树

         static SymbolTranslateCommaExpression(AstExpression expr){

            //翻译左子树(, a  b)

            TranslateExpression(expr->kids[0]);       

            //翻译右子树c

            returnTranslateExpression(expr->kids[1]);    

        }

    至此,我们完成了对表达式的翻译,在下一节中,我们要讨论语句的翻译。


0 0
原创粉丝点击