⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dag.c

📁 lcc source code enjoy your self
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "c.h"

static char rcsid[] = "$Id: dag.c,v 1.1 2002/08/28 23:12:42 drh Exp $";

#define iscall(op) (generic(op) == CALL \
	|| IR->mulops_calls \
	&& (generic(op)==DIV||generic(op)==MOD||generic(op)==MUL) \
	&& ( optype(op)==U  || optype(op)==I))
static Node forest;
static struct dag {
	struct node node;
	struct dag *hlink;
} *buckets[16];
int nodecount;
static Tree firstarg;
int assignargs = 1;
int prunetemps = -1;
static Node *tail;

static int depth = 0;
static Node replace(Node);
static Node prune(Node);
static Node asgnnode(Symbol, Node);
static struct dag *dagnode(int, Node, Node, Symbol);
static Symbol equated(Symbol);
static void fixup(Node);
static void labelnode(int);
static void list(Node);
static void killnodes(Symbol);
static Node node(int, Node, Node, Symbol);
static void printdag1(Node, int, int);
static void printnode(Node, int, int);
static void reset(void);
static Node tmpnode(Node);
static void typestab(Symbol, void *);
static Node undag(Node);
static Node visit(Node, int);
static void unlist(void);
void walk(Tree tp, int tlab, int flab) {
	listnodes(tp, tlab, flab);
	if (forest) {
		Node list = forest->link;
		forest->link = NULL;
		if (!IR->wants_dag && errcnt == 0)
			list = undag(list);
		code(Gen)->u.forest = list;
		forest = NULL;
	}
	reset();
	deallocate(STMT);
}

static Node node(int op, Node l, Node r, Symbol sym) {
	int i;
	struct dag *p;

	i = (opindex(op)^((unsigned long)sym>>2))&(NELEMS(buckets)-1);
	for (p = buckets[i]; p; p = p->hlink)
		if (p->node.op      == op && p->node.syms[0] == sym
		&&  p->node.kids[0] == l  && p->node.kids[1] == r)
			return &p->node;
	p = dagnode(op, l, r, sym);
	p->hlink = buckets[i];
	buckets[i] = p;
	++nodecount;
	return &p->node;
}
static struct dag *dagnode(int op, Node l, Node r, Symbol sym) {
	struct dag *p;

	NEW0(p, FUNC);
	p->node.op = op;
	if ((p->node.kids[0] = l) != NULL)
		++l->count;
	if ((p->node.kids[1] = r) != NULL)
		++r->count;
	p->node.syms[0] = sym;
	return p;
}
Node newnode(int op, Node l, Node r, Symbol sym) {
	return &dagnode(op, l, r, sym)->node;
}
static void killnodes(Symbol p) {
	int i;
	struct dag **q;

	for (i = 0; i < NELEMS(buckets); i++)
		for (q = &buckets[i]; *q; )
			if (generic((*q)->node.op) == INDIR &&
			    (!isaddrop((*q)->node.kids[0]->op)
			     || (*q)->node.kids[0]->syms[0] == p)) {
				*q = (*q)->hlink;
				--nodecount;
			} else
				q = &(*q)->hlink;
}
static void reset(void) {
	if (nodecount > 0)
		memset(buckets, 0, sizeof buckets);
	nodecount = 0;
}
Node listnodes(Tree tp, int tlab, int flab) {
	Node p = NULL, l, r;
	int op;

	assert(tlab || flab || tlab == 0 && flab == 0);
	if (tp == NULL)
		return NULL;
	if (tp->node)
		return tp->node;
	if (isarray(tp->type))
		op = tp->op + sizeop(voidptype->size);
	else
		op = tp->op + sizeop(tp->type->size);
	switch (generic(tp->op)) {
	case AND:   { if (depth++ == 0) reset();
		      if (flab) {
		      	listnodes(tp->kids[0], 0, flab);
		      	listnodes(tp->kids[1], 0, flab);
		      } else {
		      	listnodes(tp->kids[0], 0, flab = genlabel(1));
		      	listnodes(tp->kids[1], tlab, 0);
		      	labelnode(flab);
		      }
		      depth--; } break;
	case OR:    { if (depth++ == 0)
		      	reset();
		      if (tlab) {
		      	listnodes(tp->kids[0], tlab, 0);
		      	listnodes(tp->kids[1], tlab, 0);
		      } else {
		      	tlab = genlabel(1);
		      	listnodes(tp->kids[0], tlab, 0);
		      	listnodes(tp->kids[1], 0, flab);
		      	labelnode(tlab);
		      }
		      depth--;
 } break;
	case NOT:   { return listnodes(tp->kids[0], flab, tlab); }
	case COND:  { Tree q = tp->kids[1];
		      assert(tlab == 0 && flab == 0);
		      if (tp->u.sym)
		      	addlocal(tp->u.sym);
		      flab = genlabel(2);
		      listnodes(tp->kids[0], 0, flab);
		      assert(q && q->op == RIGHT);
		      reset();
		      listnodes(q->kids[0], 0, 0);
		      if (forest->op == LABEL+V) {
		      	equatelab(forest->syms[0], findlabel(flab + 1));
		      	unlist();
		      }
		      list(jump(flab + 1));
		      labelnode(flab);
		      listnodes(q->kids[1], 0, 0);
		      if (forest->op == LABEL+V) {
		      	equatelab(forest->syms[0], findlabel(flab + 1));
		      	unlist();
		      }
		      labelnode(flab + 1);

		      if (tp->u.sym)
		      	p = listnodes(idtree(tp->u.sym), 0, 0); } break;
	case CNST:  { Type ty = unqual(tp->type);
		      assert(ty->u.sym);
		      if (tlab || flab) {
		      	assert(ty == inttype);
		      	if (tlab && tp->u.v.i != 0)
		      		list(jump(tlab));
		      	else if (flab && tp->u.v.i == 0)
		      		list(jump(flab));
		      }
		      else if (ty->u.sym->addressed)
		      	p = listnodes(cvtconst(tp), 0, 0);
		      else
		      	p = node(op, NULL, NULL, constant(ty, tp->u.v)); } break;
	case RIGHT: { if (   tp->kids[0] && tp->kids[1]
			  &&  generic(tp->kids[1]->op) == ASGN
			  && (generic(tp->kids[0]->op) == INDIR
			  && tp->kids[0]->kids[0] == tp->kids[1]->kids[0]
			  || (tp->kids[0]->op == FIELD
			  &&  tp->kids[0] == tp->kids[1]->kids[0]))) {
		      	assert(tlab == 0 && flab == 0);
			if (generic(tp->kids[0]->op) == INDIR) {
				p = listnodes(tp->kids[0], 0, 0);
				list(p);
				listnodes(tp->kids[1], 0, 0);
			}
			else {
				assert(generic(tp->kids[0]->kids[0]->op) == INDIR);
				list(listnodes(tp->kids[0]->kids[0], 0, 0));
				p = listnodes(tp->kids[0], 0, 0);
				listnodes(tp->kids[1], 0, 0);
			}
		      } else if (tp->kids[1]) {
		      	listnodes(tp->kids[0], 0, 0);
		      	p = listnodes(tp->kids[1], tlab, flab);
		      } else
		      	p = listnodes(tp->kids[0], tlab, flab); } break;
	case JUMP:  { assert(tlab == 0 && flab == 0);
		      assert(tp->u.sym == 0);
		      assert(tp->kids[0]);
		      l = listnodes(tp->kids[0], 0, 0);
		      list(newnode(JUMP+V, l, NULL, NULL));
		      reset(); } break;
	case CALL:  { Tree save = firstarg;
		      firstarg = NULL;
		      assert(tlab == 0 && flab == 0);
		      if (tp->op == CALL+B && !IR->wants_callb) {
		      	Tree arg0 = tree(ARG+P, tp->kids[1]->type,
				tp->kids[1], NULL);
			if (IR->left_to_right)
				firstarg = arg0;
			l = listnodes(tp->kids[0], 0, 0);
			if (!IR->left_to_right || firstarg) {
				firstarg = NULL;
				listnodes(arg0, 0, 0);
			}
		      	p = newnode(CALL+V, l, NULL, NULL);
		      } else {
		      	l = listnodes(tp->kids[0], 0, 0);
		      	r = listnodes(tp->kids[1], 0, 0);
		      	p = newnode(tp->op == CALL+B ? tp->op : op, l, r, NULL);
		      }
		      NEW0(p->syms[0], FUNC);
		      assert(isptr(tp->kids[0]->type));
		      assert(isfunc(tp->kids[0]->type->type));
		      p->syms[0]->type = tp->kids[0]->type->type;
		      list(p);
		      reset();
		      cfunc->u.f.ncalls++;
		      firstarg = save;
 } break;
	case ARG:   { assert(tlab == 0 && flab == 0);
		      if (IR->left_to_right)
		      	listnodes(tp->kids[1], 0, 0);
		      if (firstarg) {
		      	Tree arg = firstarg;
		      	firstarg = NULL;
		      	listnodes(arg, 0, 0);
		      }
		      l = listnodes(tp->kids[0], 0, 0);
		      list(newnode(tp->op == ARG+B ? tp->op : op, l, NULL, NULL));
		      forest->syms[0] = intconst(tp->type->size);
		      forest->syms[1] = intconst(tp->type->align);
		      if (!IR->left_to_right)
		      	listnodes(tp->kids[1], 0, 0); } break;
	case EQ:  case NE: case GT: case GE: case LE:
	case LT:    { assert(tp->u.sym == 0);
		      assert(errcnt || tlab || flab);
		      l = listnodes(tp->kids[0], 0, 0);
		      r = listnodes(tp->kids[1], 0, 0);
		      assert(errcnt || opkind(l->op) == opkind(r->op));
		      assert(errcnt || optype(op) == optype(l->op));
		      if (tlab)
		      	assert(flab == 0),
		      	list(newnode(generic(tp->op) + opkind(l->op), l, r, findlabel(tlab)));
		      else if (flab) {
		      	switch (generic(tp->op)) {
		      	case EQ: op = NE; break;
		      	case NE: op = EQ; break;
		      	case GT: op = LE; break;
		      	case LT: op = GE; break;
		      	case GE: op = LT; break;
		      	case LE: op = GT; break;
		      	default: assert(0);
		      	}
		      	list(newnode(op + opkind(l->op), l, r, findlabel(flab)));
		      }
		      if (forest && forest->syms[0])
		      	forest->syms[0]->ref++; } break;
	case ASGN:  { assert(tlab == 0 && flab == 0);
		      if (tp->kids[0]->op == FIELD) {
		      	Tree  x = tp->kids[0]->kids[0];
			Field f = tp->kids[0]->u.field;
			assert(generic(x->op) == INDIR);
			reset();
			l = listnodes(lvalue(x), 0, 0);
			if (fieldsize(f) < 8*f->type->size) {
				unsigned int fmask = fieldmask(f);
				unsigned int  mask = fmask<<fieldright(f);
				Tree q = tp->kids[1];
				if (q->op == CNST+I && q->u.v.i == 0
				||  q->op == CNST+U && q->u.v.u == 0)
					q = bittree(BAND, x, cnsttree(unsignedtype, (unsigned long)~mask));
				else if (q->op == CNST+I && (q->u.v.i&fmask) == fmask
				||       q->op == CNST+U && (q->u.v.u&fmask) == fmask)
					q = bittree(BOR, x, cnsttree(unsignedtype, (unsigned long)mask));
				else {
					listnodes(q, 0, 0);
					q = bittree(BOR,
						bittree(BAND, rvalue(lvalue(x)),
							cnsttree(unsignedtype, (unsigned long)~mask)),
						bittree(BAND, shtree(LSH, cast(q, unsignedtype),
							cnsttree(unsignedtype, (unsigned long)fieldright(f))),
							cnsttree(unsignedtype, (unsigned long)mask)));
				}
				r = listnodes(q, 0, 0);
				op = ASGN + ttob(q->type);
			} else {
				r = listnodes(tp->kids[1], 0, 0);
				op = ASGN + ttob(tp->kids[1]->type);
			}
		      } else {
		      	l = listnodes(tp->kids[0], 0, 0);
		      	r = listnodes(tp->kids[1], 0, 0);
		      }
		      list(newnode(tp->op == ASGN+B ? tp->op : op, l, r, NULL));
		      forest->syms[0] = intconst(tp->kids[1]->type->size);
		      forest->syms[1] = intconst(tp->kids[1]->type->align);
		      if (isaddrop(tp->kids[0]->op)
		      && !tp->kids[0]->u.sym->computed)
		      	killnodes(tp->kids[0]->u.sym);
		      else
		      	reset();
		      p = listnodes(tp->kids[1], 0, 0); } break;
	case BOR: case BAND: case BXOR:
	case ADD: case SUB:  case RSH:
	case LSH:   { assert(tlab == 0 && flab == 0);
		      l = listnodes(tp->kids[0], 0, 0);
		      r = listnodes(tp->kids[1], 0, 0);
		      p = node(op, l, r, NULL); } break;
	case DIV: case MUL:
	case MOD:   { assert(tlab == 0 && flab == 0);
		      l = listnodes(tp->kids[0], 0, 0);
		      r = listnodes(tp->kids[1], 0, 0);
		      p = node(op, l, r, NULL);
		      if (IR->mulops_calls && isint(tp->type)) {
		      	list(p);
		      	cfunc->u.f.ncalls++;
		      } } break;
	case RET:   { assert(tlab == 0 && flab == 0);
		      l = listnodes(tp->kids[0], 0, 0);
		      list(newnode(op, l, NULL, NULL)); } break;
	case CVF: case CVI: case CVP:
	case CVU:   { assert(tlab == 0 && flab == 0);
		      assert(optype(tp->kids[0]->op) != optype(tp->op) || tp->kids[0]->type->size != tp->type->size);
		      l = listnodes(tp->kids[0], 0, 0);
		      p = node(op, l, NULL, intconst(tp->kids[0]->type->size));
 } break;
	case BCOM:
	case NEG:   { assert(tlab == 0 && flab == 0);
		      l = listnodes(tp->kids[0], 0, 0);
		      p = node(op, l, NULL, NULL); } break;
	case INDIR: { Type ty = tp->kids[0]->type;
		      assert(tlab == 0 && flab == 0);
		      l = listnodes(tp->kids[0], 0, 0);
		      if (isptr(ty))
		      	ty = unqual(ty)->type;
		      if (isvolatile(ty)
		      || (isstruct(ty) && unqual(ty)->u.sym->u.s.vfields))
		      	p = newnode(tp->op == INDIR+B ? tp->op : op, l, NULL, NULL);
		      else
		      	p = node(tp->op == INDIR+B ? tp->op : op, l, NULL, NULL); } break;
	case FIELD: { Tree q = tp->kids[0];
		      if (tp->type == inttype) {
		      	long n = fieldleft(tp->u.field);
		      	q = shtree(RSH,
		      		shtree(LSH, q, cnsttree(inttype, n)),
		      		cnsttree(inttype, n + fieldright(tp->u.field)));
		      } else if (fieldsize(tp->u.field) < 8*tp->u.field->type->size)
		      	q = bittree(BAND,
		      		shtree(RSH, q, cnsttree(inttype, (long)fieldright(tp->u.field))),
		      		cnsttree(unsignedtype, (unsigned long)fieldmask(tp->u.field)));
		      assert(tlab == 0 && flab == 0);
		      p = listnodes(q, 0, 0); } break;
	case ADDRG:
	case ADDRF: { assert(tlab == 0 && flab == 0);
		      p = node(tp->op + sizeop(voidptype->size), NULL, NULL, tp->u.sym);
 } break;
	case ADDRL: { assert(tlab == 0 && flab == 0);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -