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

来源:互联网 发布:linux rar安装 编辑:程序博客网 时间:2024/05/19 22:03
前面分析了表达式的语法,也分析了语句的语法,但它们最终的目的就是生成合适的中间表示,在LCC里是采用树作为中间表示的。
现在就来分析语句生成什么样的树表示,下面的语句是来自例子里,如下:
int nTest1 = 1;
这个语句是声明了一个局部变量nTest1,并且给nTest1赋值为1LCC编译器要把它变换到分析树的表示,这样才利于后面的分析和使用。它的分析树如下:
  左子树右子树
 
  赋值树:
左子树-----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里把所有变量都会生成指针的操作,主要有三种:ADDRGPADDRFPADDRLP。如果是指针类型,就需要生成右值操作树。最后变量nTest1就生成下面的ID树:
 INDIR-----ADDRL
asgn函数里会生成赋值树,它是调用下面语句实现的:
e = asgntree(ASGN, idtree(p), e);
在函数asgntree里根据ID树的类型和表达式e树的类型进行自动转换,并生成赋值树的操作类型。也就是生成下面的赋值树:
ASGN树:
左子树----- INDIR-----ADDRL
右子树-----常量表达式树
通过上面的处理,就可以把赋值表达式语句生成一棵赋值树返回给walk函数更进一步处理。下一次再分析怎么样把树变换到无环有向图(DAG)表示。