LCC编译器的源程序分析(40)赋值表达式树

前面分析了表达式的语法,也分析了语句的语法,但它们最终的目的就是生成合适的中间表示,在LCC里是采用树作为中间表示的。
现在就来分析语句生成什么样的树表示,下面的语句是来自例子里,如下:
int nTest1 = 1;
这个语句是声明了一个局部变量nTest1,并且给nTest1赋值为1。LCC编译器要把它变换到分析树的表示,这样才利于后面的分析和使用。它的分析树如下:
左子树=右子树

赋值树:
左子树-ID树
右子树-常量表达式树
由语法分析可知,赋值语句分析过程是先生成常量表达式树,然后生成ID树,最后生成赋值树,把它变换到DAG树,然后添加到代码表。
在函数dcllocal里调用下面的语句生成赋值树:
walk(root(asgn(p, e)), 0, 0);
其中e就是已经分析生成的表达式树,在这里应是常量表达式树。p是指向ID树的符号,在asgn函数里生成ID树。这样就可以生成赋值树返回。
接着下来,我们先分析一下ID树怎么样表示的,它的代码如下:
#001 Tree idtree(Symbol p)
#002 {
#003 int op;
#004 Tree e;
#005 Type ty = p->type ? unqual(p->type) : voidptype;
#006
第5行是判断类型是否存在,如果没有类型指定为void类型,否则就获取符号指向的类型,并且用unqual宏判断类型是否基本类型,如果不是,就需要获取它的基本类型。

#007 if (p->scope == GLOBAL || p->sclass == STATIC)
#008 op = ADDRG;
#009 else if (p->scope == PARAM)
#010 {
#011 op = ADDRF;
#012 if (isstruct(p->type) && !IR->wants_argb)
#013 {
#014 e = tree(mkop(op,voidptype), ptr(ptr(p->type)), NULL, NULL);
#015 e->u.sym = p;
#016 return rvalue(rvalue(e));
#017 }
#018 }
#019 else if (p->sclass == EXTERN)
#020 {
#021 assert(p->u.alias);
#022 p = p->u.alias;
#023 op = ADDRG;
#024 }
#025 else
#026 op = ADDRL;
#027
第7行是根据变量的作用域和存储类型来区分变量是否全局变量。如果是全局变量,就在第8行里标识操作符的类型为全局变量ADDRG。
第9行是判断是否参数变量,如果是就在第11行里标识操作符的类型为ADDRF。
第19行是判断是否外面文件的变量,如果是也需要把它定义为全局变量的类型ADDRG。
第26行标识操作符的类型ADDRL,这就是局部变量的类型。也就是上面例子里nTest1变量的类型。

#028 p->ref += refinc;
#029
#030 if (isarray(ty))
#031 e = tree(mkop(op,voidptype), p->type, NULL, NULL);
#032 else if (isfunc(ty))
#033 e = tree(mkop(op,funcptype), p->type, NULL, NULL);
#034 else
#035 e = tree(mkop(op,voidptype), ptr(p->type), NULL, NULL);
#036
#037 e->u.sym = p;
#038 if (isptr(e->type))
#039 e = rvalue(e);
#040
#041 return e;
#042 }
第28行是添加这个变量的引用计数。
第30行是判断是否数组类型处理。
第32行是判断函数类型处理。
第35行是生成其它类型的ID树。
第38行是判断是否指针类型,如果是指针类型,就需要生成取地址的操作INDIR。

在LCC里把所有变量都会生成指针的操作,主要有三种:ADDRGP,ADDRFP,ADDRLP。如果是指针类型,就需要生成右值操作树。最后变量nTest1就生成下面的ID树:
INDIR树-ADDRL树
在asgn函数里会生成赋值树,它是调用下面语句实现的:
e = asgntree(ASGN, idtree(p), e);
在函数asgntree里根据ID树的类型和表达式e树的类型进行自动转换,并生成赋值树的操作类型。也就是生成下面的赋值树:
ASGN树:
左子树- INDIR树-ADDRL树
右子树-常量表达式树
通过上面的处理,就可以把赋值表达式语句生成一棵赋值树返回给walk函数更进一步处理。下一次再分析怎么样把树变换到无环有向图(DAG)表示。

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License