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 )表示。
 

转载于:https://www.cnblogs.com/ajuanabc/archive/2007/06/18/2464343.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值