上一次说到赋值表达式转换为有向无环图的函数
listnodes
,下面继续来分析这个函数代码。
当赋值树处理时,就运行下面的分支来处理:
#256 case ASGN:
#257 {
#258 assert(tlab == 0 && flab == 0);
#259 if (tp->kids[0]->op == FIELD)
#260 {
#261 Tree x = tp->kids[0]->kids[0];
#262 Field f = tp->kids[0]->u.field;
#263 assert(generic(x->op) == INDIR);
#264 reset();
#265 l = listnodes(lvalue(x), 0, 0);
#266
#267 if (fieldsize(f) < 8*f->type->size)
#268 {
#269 unsigned int fmask = fieldmask(f);
#270 unsigned int mask = fmask<<fieldright(f);
#271 Tree q = tp->kids[1];
#272 if (q->op == CNST+I && q->u.v.i == 0
#273 || q->op == CNST+U && q->u.v.u == 0)
#274 q = bittree(BAND, x, cnsttree(unsignedtype, (unsigned long)~mask));
#275 else if (q->op == CNST+I && (q->u.v.i&fmask) == fmask
#276 || q->op == CNST+U && (q->u.v.u&fmask) == fmask)
#277 q = bittree(BOR, x, cnsttree(unsignedtype, (unsigned long)mask));
#278 else
#279 {
#280 listnodes(q, 0, 0);
#281 q = bittree(BOR,
#282 bittree(BAND, rvalue(lvalue(x)),
#283 cnsttree(unsignedtype, (unsigned long)~mask)),
#284 bittree(BAND, shtree(LSH, cast(q, unsignedtype),
#285 cnsttree(unsignedtype, (unsigned long)fieldright(f))),
#286 cnsttree(unsignedtype, (unsigned long)mask)));
#287 }
#288 r = listnodes(q, 0, 0);
#289 op = ASGN + ttob(q->type);
#290 }
#291 else
#292 {
#293 r = listnodes(tp->kids[1], 0, 0);
#294 op = ASGN + ttob(tp->kids[1]->type);
#295 }
#296
#297 }
#298 else
#299 {
#300 l = listnodes(tp->kids[0], 0, 0);
#301 r = listnodes(tp->kids[1], 0, 0);
#302 }
#303
第
259
行是处理结构里字段操作,在这个赋值表达式里没有字段操作,先把它放下。
第
300
行处理非字段操作的左子树,然后生成有向无环图的左子树,这里递归调用
listnodes
函数来实现下一层树,其实这里是采用后序遍历二叉树的算法来构造
DAG
图。
第
301
行递归处理右子树的节点。
#304 list(newnode(tp->op == ASGN+B ? tp->op : op, l, r, NULL));
#305 forest->syms[0] = intconst(tp->kids[1]->type->size);
#306 forest->syms[1] = intconst(tp->kids[1]->type->align);
#307
#308 if (isaddrop(tp->kids[0]->op)
#309 && !tp->kids[0]->u.sym->computed)
#310 killnodes(tp->kids[0]->u.sym);
#311 else
#312 reset();
#313
#314 p = listnodes(tp->kids[1], 0, 0);
#315 }
#316 break;
第
304
行是创建一个
DAG
森林的根节点,保存在全局变量
forest
那里。
第
305
行和第
306
行设置符号属性。
第
308
行和第
309
行判断是否需要调用函数
killnodes
来删除公共表达式。如果不需要就直接调用函数
reset
复位。
第
314
行调用函数
listnodes
递归处理兄弟树节点。
…
上面是采用后序遍历的算法把所有树节点转换到
DAG
节点,并构造成有向无环图。下一次分析处理赋值树的几个类型操作树节点。