예제 #1
0
Tree asgntree(int op, Tree l, Tree r) {
    Type aty, ty;

    r = pointer(r);
    ty = assign(l->type, r);
    if (ty)
        r = cast(r, ty);
    else {
        typeerror(ASGN, l, r);
        if (r->type == voidtype)
            r = retype(r, inttype);
        ty = r->type;
    }
    if (l->op != FIELD)
        l = lvalue(l);
    aty = l->type;
    if (isptr(aty))
        aty = unqual(aty)->type;
    if (isconst(aty)
            || (isstruct(aty) && unqual(aty)->u.sym->u.s.cfields)) {
        if (isaddrop(l->op)
                && !l->u.sym->computed && !l->u.sym->generated)
            error("assignment to const identifier `%s'\n",
                  l->u.sym->name);
        else
            error("assignment to const location\n");
    }
    if (l->op == FIELD) {
        long n = 8 * l->u.field->type->size - fieldsize(l->u.field);
        if (n > 0 && isunsigned(l->u.field->type))
            r = bittree(BAND, r,
                        cnsttree(r->type, (unsigned long)fieldmask(l->u.field)));
        else if (n > 0) {
            if (r->op == CNST + I) {
                n = r->u.v.i;
                if (n & (1 << (fieldsize(l->u.field) - 1)))
                    n |= ~0UL << fieldsize(l->u.field);
                r = cnsttree(r->type, n);
            } else
                r = shtree(RSH,
                           shtree(LSH, r, cnsttree(inttype, n)),
                           cnsttree(inttype, n));
        }
    }
    if (isstruct(ty) && isaddrop(l->op) && iscallb(r))
        return tree(RIGHT, ty,
                    tree(CALL + B, ty, r->kids[0]->kids[0], l),
                    idtree(l->u.sym));
    return tree(mkop(op, ty), ty, l, r);
}
예제 #2
0
파일: emit.c 프로젝트: a8m/c
static void
assign(Node *n)
{
	Node *l, *r;
	int op;

	op = n->Assign.op;
	l = n->Assign.l;
	r = n->Assign.r;
	if(op == '=') {
		expr(r);
		pushq("rax");
		addr(l);
		popq("rcx");
		if(!isptr(l->type) && !isitype(l->type) && !isstruct(l->type))
			errorf("unimplemented assign\n");
		store(l->type);
		outi("movq %%rcx, %%rax\n");
		return;
	}
	addr(l);
	pushq("rax");
	load(l->type);
	pushq("rax");
	expr(r);
	outi("movq %%rax, %%rcx\n");
	popq("rax");
	/* XXX this type is not correct for comparison ops works anyway, but should be changed*/
	obinop(op, n->type);
	outi("movq %%rax, %%rcx\n");
	popq("rax");
	store(l->type);
	outi("movq %%rcx, %%rax\n");
}
예제 #3
0
파일: stmt.c 프로젝트: HanumathRao/lcc
void retcode(Tree p) {
	Type ty;

	if (p == NULL) {
		if (events.returns)
			apply(events.returns, cfunc, NULL);
		return;
	}
	p = pointer(p);
	ty = assign(freturn(cfunc->type), p);
	if (ty == NULL) {
		error("illegal return type; found `%t' expected `%t'\n",
			p->type, freturn(cfunc->type));
		return;
	}
	p = cast(p, ty);
	if (retv)
		{
			if (iscallb(p))
				p = tree(RIGHT, p->type,
					tree(CALL+B, p->type,
						p->kids[0]->kids[0], idtree(retv)),
					rvalue(idtree(retv)));
			else {
				Type ty = retv->type->type;
				assert(isstruct(ty));
				if (ty->u.sym->u.s.cfields) {
					ty->u.sym->u.s.cfields = 0;
					p = asgntree(ASGN, rvalue(idtree(retv)), p);
					ty->u.sym->u.s.cfields = 1;
				} else
					p = asgntree(ASGN, rvalue(idtree(retv)), p);
			}
			walk(p, 0, 0);
			if (events.returns)
				apply(events.returns, cfunc, rvalue(idtree(retv)));
			return;
		}
	if (events.returns)
		{
			Symbol t1 = genident(AUTO, p->type, level);
			addlocal(t1);
			walk(asgn(t1, p), 0, 0);
			apply(events.returns, cfunc, idtree(t1));
			p = idtree(t1);
		}
	if (!isfloat(p->type))
		p = cast(p, promote(p->type));
	if (isptr(p->type))
		{
			Symbol q = localaddr(p);
			if (q && (q->computed || q->generated))
				warning("pointer to a %s is an illegal return value\n",
					q->scope == PARAM ? "parameter" : "local");
			else if (q)
				warning("pointer to %s `%s' is an illegal return value\n",
					q->scope == PARAM ? "parameter" : "local", q->name);
		}
	walk(tree(mkop(RET,p->type), p->type, p, NULL), 0, 0);
}
예제 #4
0
파일: emit.c 프로젝트: a8m/c
static void
load(CTy *t)
{
	if(isitype(t) || isptr(t)) {
		switch(t->size) {
		case 8:
			outi("movq (%%rax), %%rax\n");
			break;
		case 4:
			outi("movslq (%%rax), %%rax\n");
			break;
		case 2:
			outi("movswq (%%rax), %%rax\n");
			break;
		case 1:
			outi("movsbq (%%rax), %%rax\n");
			break;
		default:
			panic("internal error\n");
		}
		return;
	}
	if(isstruct(t)) {
		return;
	}
	if(isarray(t)) {
		return;
	}
	if(isfunc(t)) {
		return;
	}
	errorf("unimplemented load %d\n", t->t);
}
예제 #5
0
파일: emit.c 프로젝트: a8m/c
void
emitsym(Sym *sym)
{
	out("# emit sym %s\n", sym->name);
	switch(sym->k){
	case SYMGLOBAL:
		if(sym->Global.sclass == SCEXTERN)
			break;
		if(isfunc(sym->type)) {
			func(sym->init, sym->Global.label, sym->Global.sclass == SCGLOBAL);
			break;
		}
		penddata(sym->Global.label, sym->type, sym->init, sym->Global.sclass == SCGLOBAL);
		break;
	case SYMLOCAL:
		if(sym->init) {
			expr(sym->init);
			pushq("rax");
			outi("leaq %d(%%rbp), %%rax\n", sym->Local.slot->offset);
			popq("rcx");
			if(!isptr(sym->type) && !isitype(sym->type) && !isstruct(sym->type))
				errorf("unimplemented init\n");
			store(sym->type);
		}
		break;
	case SYMENUM:
	case SYMTYPE:
		panic("internal error");
	}
	out("\n");
}
예제 #6
0
파일: gen.c 프로젝트: Godzil/osXdk
void function(sSymbol_t f, sSymbol_t caller[], sSymbol_t callee[], int ncalls) 
{
	int i;

	localsize=offset=tmpsize=nbregs=0; funame=f->x.name;
	for (i=8;i<32;i++) temp[i]->x.name="******";
	for (i = 0; caller[i] && callee[i]; i++) 
	{
		caller[i]->x.name=stringf("(ap),%d",offset);
		caller[i]->x.adrmode='A';
		offset+=caller[i]->type->size;
		if (optimizelevel>1 && callee[i]->sclass==REGISTER && allocreg(callee[i]))
			; /* allocreg ok */
		else 
		{
			callee[i]->x.adrmode=caller[i]->x.adrmode;
			callee[i]->x.name=caller[i]->x.name;
			callee[i]->sclass=AUTO;
		}
	}
	busy=localsize=0; offset=6;
	gencode(caller,callee);
	omit_frame=(i==0 && localsize==6);
	print("%s\n",funame);
	if (optimizelevel>1 && omit_frame && nbregs==0)
		;
	else print("\tENTER(%d,%d)\n",nbregs,localsize);
	if (isstruct(freturn(f->type)))
		print("\tMOVW_DI(op1,(fp),6)\n");
	emitcode();
}
예제 #7
0
파일: decl.c 프로젝트: JamesLinus/mcc
static void fields(node_t * sym)
{
    int follow[] = {INT, CONST, '}', IF, 0};
    node_t *sty = SYM_TYPE(sym);

    if (!first_decl(token)) {
        error("expect type name or qualifiers");
        return;
    }

    struct vector *v = vec_new();
    do {
        node_t *basety = specifiers(NULL, NULL);

        for (;;) {
            node_t *field = new_field();
            if (token->id == ':') {
                bitfield(field);
                FIELD_TYPE(field) = basety;
            } else {
                node_t *ty = NULL;
                struct token *id = NULL;
                declarator(&ty, &id, NULL);
                attach_type(&ty, basety);
                if (token->id == ':')
                    bitfield(field);
                FIELD_TYPE(field) = ty;
                if (id) {
                    for (int i = 0; i < vec_len(v); i++) {
                        node_t *f = vec_at(v, i);
                        if (FIELD_NAME(f) &&
                                !strcmp(FIELD_NAME(f), id->name)) {
                            errorf(id->src,
                                   "redefinition of '%s'",
                                   id->name);
                            break;
                        }
                    }
                    FIELD_NAME(field) = id->name;
                    AST_SRC(field) = id->src;
                }
            }

            vec_push(v, field);
            if (token->id != ',')
                break;
            expect(',');
            ensure_field(field, vec_len(v), false);
        }

        match(';', follow);
        ensure_field(vec_tail(v), vec_len(v),
                     isstruct(sty) && !first_decl(token));
    } while (first_decl(token));

    TYPE_FIELDS(sty) = (node_t **) vtoa(v);
    set_typesize(sty);
}
예제 #8
0
/* dbxout - output .stabs entry for type ty */
static void dbxout(Type ty) {
	ty = unqual(ty);
	if (!ty->x.printed) {
		int col = 0;
		print(".stabs \""), col += 8;
		if (ty->u.sym && !(isfunc(ty) || isarray(ty) || isptr(ty)))
			print("%s", ty->u.sym->name), col += strlen(ty->u.sym->name);
		print(":%c", isstruct(ty) || isenum(ty) ? 'T' : 't'), col += 2;
		emittype(ty, 0, col);
		print("\",%d,0,0,0\n", N_LSYM);
	}
}
예제 #9
0
파일: emit.c 프로젝트: a8m/c
static void
addr(Node *n)
{
	int sz;
	int offset;
	Sym *sym;
	
	switch(n->t) {
	case NUNOP:
		expr(n->Unop.operand);
		break;
	case NSEL:
		expr(n->Sel.operand);
		if(isptr(n->Sel.operand->type))
			offset = structoffsetfromname(n->Sel.operand->type->Ptr.subty, n->Sel.name);
		else if(isstruct(n->Sel.operand->type))
			offset = structoffsetfromname(n->Sel.operand->type, n->Sel.name);
		else
			panic("internal error");
		if(offset < 0)
			panic("internal error");
		outi("addq $%d, %%rax\n", offset);
		break;
	case NIDENT:
		sym = n->Ident.sym;
		switch(sym->k) {
		case SYMGLOBAL:
			outi("leaq %s(%%rip), %%rax\n", sym->Global.label);
			break;
		case SYMLOCAL:
			outi("leaq %d(%%rbp), %%rax\n", sym->Local.slot->offset);
			break;
		default:
			panic("internal error");
		}
		break;
	case NIDX:
		expr(n->Idx.idx);
		sz = n->type->size;
		if(sz != 1) {
			outi("imul $%d, %%rax\n", sz);
		}
		pushq("rax");
		expr(n->Idx.operand);
		popq("rcx");
		outi("addq %%rcx, %%rax\n");
		break;
	default:
		errorf("unimplemented addr\n");
	}
}
예제 #10
0
파일: emit.c 프로젝트: a8m/c
static void
data(Data *d)
{
	InitMember *initmemb;
	int   i, offset;
	char *l;
	
	if(!d->init) {
		out(".comm %s, %d, %d\n", d->label, d->type->size, d->type->align);
		return;
	}
	if(d->isglobal)
		out(".globl %s\n", d->label);
	out("%s:\n", d->label);
	
	if(ischararray(d->type))
	if(d->init->t == NSTR) {
		out(".string %s\n", d->init->Str.v);
		return;
	}
	
	if(ischarptr(d->type))
	if(d->init->t == NSTR) {
		l = newlabel();
		out(".quad %s\n", l);
		out("%s:\n", l);
		out(".string %s\n", d->init->Str.v);
		return;
	}
	if(isitype(d->type) || isptr(d->type)) {
		itypedata(d->init);
		return;
	}
	if(isarray(d->type) || isstruct(d->type)) {
		if(d->init->t != NINIT)
			errorposf(&d->init->pos, "array/struct expects a '{' style initializer");
		offset = 0;
		for(i = 0; i < d->init->Init.inits->len ; i++) {
			initmemb = vecget(d->init->Init.inits, i);
			if(initmemb->offset != offset)
				out(".fill %d, 1, 0\n", initmemb->offset - offset);
			itypedata(initmemb->n);
			offset = initmemb->offset + initmemb->n->type->size;
		}
		if(offset < d->type->size)
			out(".fill %d, 1, 0\n", d->type->size - offset);
		return;
	}
	panic("internal error");
}
예제 #11
0
파일: types.c 프로젝트: xtao/c
void
addstructmember(SrcPos *pos, CTy *t, char *name, CTy *membt)
{
	StructMember *sm, *subsm;
	int i, align, sz;

	sm = gcmalloc(sizeof(StructMember));
	sm->name = name;
	sm->type = membt;
	if(!isstruct(t))
		panic("internal error");
	if(sm->name == 0 && isstruct(sm->type)) {
		for(i = 0; i < sm->type->Struct.members->len; i++) {
			subsm = vecget(sm->type->Struct.members, i);
			addstructmember(pos, t, subsm->name, subsm->type);
		}
		return;
	}
	if(sm->name) {
		for(i = 0; i < t->Struct.members->len; i++) {
			subsm = vecget(t->Struct.members, i);
			if(subsm->name)
			if(strcmp(sm->name, subsm->name) == 0)
				errorposf(pos ,"struct already has a member named %s", sm->name);
		}
	}
	if(membt->align < t->align)
		t->align = membt->align;
	sz = t->size;
	align = membt->align;
	if(sz % align)
		sz = sz + align - (sz % align);
	sm->offset = sz;
	sz += sm->type->size;
	t->size = sz;
	vecappend(t->Struct.members, sm);
}
예제 #12
0
/* asgn - generate tree for assignment of expr e to symbol p sans qualifiers */
Tree asgn(Symbol p, Tree e) {
	if (isarray(p->type))
		e = tree(ASGN+B, p->type, idtree(p),
			tree(INDIR+B, e->type, e, NULL));
	else {
		Type ty = p->type;
		p->type = unqual(p->type);
		if (isstruct(p->type) && p->type->u.sym->u.s.cfields) {
			p->type->u.sym->u.s.cfields = 0;
			e = asgntree(ASGN, idtree(p), e);
			p->type->u.sym->u.s.cfields = 1;
		} else
			e = asgntree(ASGN, idtree(p), e);
		p->type = ty;
	}
	return e;
}
예제 #13
0
파일: types.c 프로젝트: xtao/c
StructMember *
getstructmember(CTy *t, char *n)
{
	int i;
	StructMember *sm;
	
	if(isptr(t))
		t = t->Ptr.subty;
	if(!isstruct(t))
		panic("internal error");
	for(i = 0; i < t->Struct.members->len; i++) {
		sm = vecget(t->Struct.members, i);
		if(strcmp(n, sm->name) == 0)
			return sm;
	}
	return 0;
}
예제 #14
0
/* stabsym - output a stab entry for symbol p */
void stabsym(Symbol p) {
	int code, tc, sz = p->type->size;

	if (p->generated || p->computed)
		return;
	if (isfunc(p->type)) {
		print(".stabs \"%s:%c%d\",%d,0,0,%s\n", p->name,
			p->sclass == STATIC ? 'f' : 'F', dbxtype(freturn(p->type)),
			N_FUN, p->x.name);
		return;
	}
	if (!IR->wants_argb && p->scope == PARAM && p->structarg) {
		assert(isptr(p->type) && isstruct(p->type->type));
		tc = dbxtype(p->type->type);
		sz = p->type->type->size;
	} else
		tc = dbxtype(p->type);
	if (p->sclass == AUTO && p->scope == GLOBAL || p->sclass == EXTERN) {
		print(".stabs \"%s:G", p->name);
		code = N_GSYM;
	} else if (p->sclass == STATIC) {
		print(".stabs \"%s:%c%d\",%d,0,0,%s\n", p->name, p->scope == GLOBAL ? 'S' : 'V',
			tc, p->u.seg == BSS ? N_LCSYM : N_STSYM, p->x.name);
		return;
	} else if (p->sclass == REGISTER) {
		if (p->x.regnode) {
			int r = p->x.regnode->number;
			if (p->x.regnode->set == FREG)
				r += 32;	/* floating point */
				print(".stabs \"%s:%c%d\",%d,0,", p->name,
					p->scope == PARAM ? 'P' : 'r', tc, N_RSYM);
			print("%d,%d\n", sz, r);
		}
		return;
	} else if (p->scope == PARAM) {
		print(".stabs \"%s:p", p->name);
		code = N_PSYM;
	} else if (p->scope >= LOCAL) {
		print(".stabs \"%s:", p->name);
		code = N_LSYM;
	} else
		assert(0);
	print("%d\",%d,0,0,%s\n", tc, code,
		p->scope >= PARAM && p->sclass != EXTERN ? p->x.name : "0");
}
예제 #15
0
파일: emit.c 프로젝트: a8m/c
static void
sel(Node *n)
{
	CTy *t;
	int offset;

	expr(n->Sel.operand);
	t = n->Sel.operand->type;
	if(isptr(t))
		offset = structoffsetfromname(t->Ptr.subty, n->Sel.name);
	else if(isstruct(t))
		offset = structoffsetfromname(t, n->Sel.name);
	else
		panic("internal error");
	if(offset < 0)
		panic("internal error");
	if(offset != 0)
		outi("add $%d, %%rax\n", offset);
	load(n->type);
}
예제 #16
0
Tree calltree(Tree f, Type ty, Tree args, Symbol t3) {
	Tree p;

	if (args)
		f = tree(RIGHT, f->type, args, f);
	if (isstruct(ty))
		assert(t3),
		p = tree(RIGHT, ty,
			tree(CALL+B, ty, f, addrof(idtree(t3))),
			idtree(t3));
	else {
		Type rty = ty;
		if (isenum(ty))
			rty = unqual(ty)->type;
		if (!isfloat(rty))
			rty = promote(rty);
		p = tree(mkop(CALL, rty), rty, f, NULL);
		if (isptr(ty) || p->type->size > ty->size)
			p = cast(p, ty);
	}
	return p;
}
예제 #17
0
Type assign(Type xty, Tree e) {
	Type yty = unqual(e->type);

	xty = unqual(xty);
	if (isenum(xty))
		xty = xty->type;
	if (xty->size == 0 || yty->size == 0)
		return NULL;
	if ( isarith(xty) && isarith(yty)
	||  isstruct(xty) && xty == yty)
		return xty;
	if (isptr(xty) && isnullptr(e))
		return xty;
	if ((isvoidptr(xty) && isptr(yty)
	  || isptr(xty)     && isvoidptr(yty))
	&& (  (isconst(xty->type)    || !isconst(yty->type))
	   && (isvolatile(xty->type) || !isvolatile(yty->type))))
		return xty;

	if ((isptr(xty) && isptr(yty)
	    && eqtype(unqual(xty->type), unqual(yty->type), 1))
	&&  (  (isconst(xty->type)    || !isconst(yty->type))
	    && (isvolatile(xty->type) || !isvolatile(yty->type))))
		return xty;
	if (isptr(xty) && isptr(yty)
	&& (  (isconst(xty->type)    || !isconst(yty->type))
	   && (isvolatile(xty->type) || !isvolatile(yty->type)))) {
		Type lty = unqual(xty->type), rty = unqual(yty->type);
		if (isenum(lty) && rty == inttype
		||  isenum(rty) && lty == inttype) {
			if (Aflag >= 1)
				warning("assignment between `%t' and `%t' is compiler-dependent\n",
					xty, yty);
			return xty;
		}
	}
	return NULL;
}
예제 #18
0
파일: emit.c 프로젝트: a8m/c
static void
store(CTy *t)
{
	if(isitype(t) || isptr(t)) {
		switch(t->size) {
		case 8:
			outi("movq %%rcx, (%%rax)\n");
			break;
		case 4:
			outi("movl %%ecx, (%%rax)\n");
			break;
		case 2:
			outi("movw %%cx, (%%rax)\n");
			break;
		case 1:
			outi("movb %%cl, (%%rax)\n");
			break;
		default:
			panic("internal error\n");
		}
		return;
	}
	if(isstruct(t)) {
		pushq("rdi");
		pushq("rsi");
		pushq("rcx");
		outi("movq %%rcx, %%rsi\n");
		outi("movq %%rax, %%rdi\n");
		outi("movq $%d, %%rcx\n", t->size);
		outi("rep movsb\n");
		popq("rcx");
		popq("rsi");
		popq("rdi");
		return;
	}
	errorf("unimplemented store\n");
}
예제 #19
0
Tree call(Tree f, Type fty, Coordinate src) {
	int n = 0;
	Tree args = NULL, r = NULL, e;
	Type *proto, rty = unqual(freturn(fty));
	Symbol t3 = NULL;

	if (fty->u.f.oldstyle)
		proto = NULL;
	else
		proto = fty->u.f.proto;
	if (hascall(f))
		r = f;
	if (isstruct(rty))
		{
			t3 = temporary(AUTO, unqual(rty));
			if (rty->size == 0)
				error("illegal use of incomplete type `%t'\n", rty);
		}
	if (t != ')')
		for (;;) {
			Tree q = pointer(expr1(0));
			if (proto && *proto && *proto != voidtype)
				{
					Type aty;
					q = value(q);
					aty = assign(*proto, q);
					if (aty)
						q = cast(q, aty);
					else
						error("type error in argument %d to %s; found `%t' expected `%t'\n", n + 1, funcname(f),

							q->type, *proto);
					if ((isint(q->type) || isenum(q->type))
					&& q->type->size != inttype->size)
						q = cast(q, promote(q->type));
					++proto;
				}
			else
				{
					if (!fty->u.f.oldstyle && *proto == NULL)
						error("too many arguments to %s\n", funcname(f));
					q = value(q);
					if (isarray(q->type) || q->type->size == 0)
						error("type error in argument %d to %s; `%t' is illegal\n", n + 1, funcname(f), q->type);

					else
						q = cast(q, promote(q->type));
				}
			if (!IR->wants_argb && isstruct(q->type))
				if (iscallb(q))
					q = addrof(q);
				else {
					Symbol t1 = temporary(AUTO, unqual(q->type));
					q = asgn(t1, q);
					q = tree(RIGHT, ptr(t1->type),
						root(q), lvalue(idtree(t1)));
				}
			if (q->type->size == 0)
				q->type = inttype;
			if (hascall(q))
				r = r ? tree(RIGHT, voidtype, r, q) : q;
			args = tree(mkop(ARG, q->type), q->type, q, args);
			n++;
			if (Aflag >= 2 && n == 32)
				warning("more than 31 arguments in a call to %s\n",
					funcname(f));
			if (t != ',')
				break;
			t = gettok();
		}
	expect(')');
	if (proto && *proto && *proto != voidtype)
		error("insufficient number of arguments to %s\n",
			funcname(f));
	if (r)
		args = tree(RIGHT, voidtype, r, args);
	e = calltree(f, rty, args, t3);
	if (events.calls)
		apply(events.calls, &src, &e);
	return e;
}
예제 #20
0
파일: function.c 프로젝트: bill2009/lcc1802
//function(..) module saved jan 1 2013 as part of prep for scrt integration
static void function(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {
    int i, saved, sizefsave, sizeisave, varargs;
    Symbol r, argregs[NUM_ARG_REGS];

    usedmask[0] = usedmask[1] = 0;
    freemask[0] = freemask[1] = ~(unsigned)0;
    offset = maxoffset = maxargoffset = 0;
    for (i = 0; callee[i]; i++) //find last argument
        ;
    varargs = variadic(f->type) //see if variable arguments by type or by name of final argument
              || i > 0 && strcmp(callee[i-1]->name, "va_alist") == 0;
    for (i = 0; callee[i]; i++) {  //for each argument
        Symbol p = callee[i];
        Symbol q = caller[i];
        assert(q);
        offset = roundup(offset, q->type->align); //calculate the offset from the caller's sp
        p->x.offset = q->x.offset = offset;
        p->x.name = q->x.name = stringd(offset);
        r = argreg(i, offset, optype(ttob(q->type)), q->type->size, optype(ttob(caller[0]->type)));
        if (i < NUM_ARG_REGS)
            argregs[i] = r;
        offset = roundup(offset + q->type->size, 2); //i dunno
        if (varargs)
            p->sclass = AUTO;  //variable args are always auto?
        else if (r && ncalls == 0 &&  //I dunno
                 !isstruct(q->type) && !p->addressed &&
                 !(isfloat(q->type) && r->x.regnode->set == IREG)) {
            p->sclass = q->sclass = REGISTER;
            askregvar(p, r);
            assert(p->x.regnode && p->x.regnode->vbl == p);
            q->x = p->x;
            q->type = p->type;
        }
        else if (askregvar(p, rmap(ttob(p->type)))
                 && r != NULL
                 && (isint(p->type) || p->type == q->type)) {
            assert(q->sclass != REGISTER);
            p->sclass = q->sclass = REGISTER;
            q->type = p->type;
        }
    }
    assert(!caller[i]);  //done with arguments, their individual offsets and maxargoffset have been set
    offset = 0;
    gencode(caller, callee);
    if (ncalls) //prepare to save return address if necessary(i.e. we do calls of our own)
        usedmask[IREG] |= ((unsigned)1)<<REG_RETADDR;
    usedmask[IREG] &= INT_CALLEE_SAVE;  //limit saving to those we're responsible for
    usedmask[FREG] &= 0xfff00000;
    maxargoffset = roundup(maxargoffset, usedmask[FREG] ? 8 : 2);
    if (ncalls && maxargoffset < NUM_ARG_REGS*2)
        maxargoffset = NUM_ARG_REGS*2;
    sizefsave = 4*bitcount(usedmask[FREG]); //space needed to save the float regs
    sizeisave = 2*bitcount(usedmask[IREG]);  //space needed to save the int regs
    framesize = roundup(maxargoffset + sizefsave //space for outgoing arguments, space for saving floats,
                        + sizeisave + maxoffset, 2);  //space for saving ints, space for locals
    //segment(CODE);
    //printf("\talign 16\n");
    printf("%s:\n", f->x.name);
    i = maxargoffset + sizefsave - framesize;  //I dunno but it's -v and it's never used!
    if (framesize > 0)
        print("\talu2I sp,sp,%d,smi,smbi\n", framesize);
    saved = maxargoffset;
    /space needed for outgoing arguments
예제 #21
0
int
main(int argc, char **argv)
{
	Dwarf_Off off, lastoff;
	Dwarf *dw;

	size_t hdr_size;
	int cufd, error;

	argv0 = argv[0];
	if (argc < 3)
		usage();

	structname = argv[1];
	binary = argv[2];

	elf_version(EV_CURRENT);

	cufd = open(binary, O_RDONLY);
	if (cufd == -1)
		err(EX_USAGE, "open");

	dw = dwarf_begin(cufd, DWARF_C_READ);
	if (dw == NULL) {
		error = dwarf_errno();
		if (error == DWARF_E_NO_REGFILE)
			errx(EX_USAGE, "%s: Not a regular file", binary);
		dwarf_err_errno(EX_DATAERR, error, "dwarf_begin");
	}

	get_elf_pointer_size(dw);

	/* XXX worry about .debug_types sections later. */

	lastoff = off = 0;
	while (dwarf_nextcu(dw, off, &off, &hdr_size, NULL, NULL, NULL) == 0) {
		Dwarf_Die cu_die, die;
		int x;

		if (dwarf_offdie(dw, lastoff + hdr_size, &cu_die) == NULL)
			continue;
		lastoff = off;

		/*
		 * A CU may be empty because e.g. an empty (or fully #if0'd)
		 * file is compiled.
		 */
		if (dwarf_child(&cu_die, &die))
			continue;

		/* Loop through all DIEs in the CU. */
		do {
			if (isstruct(dwarf_tag(&die)) &&
			    dwarf_haschildren(&die) &&
			    dwarf_diename(&die) &&
			    strcmp(dwarf_diename(&die), structname) == 0) {
				structprobe(dw, &die);
				goto out;
			}

		} while ((x = dwarf_siblingof(&die, &die)) == 0);
		if (x == -1)
			dwarf_err(EX_DATAERR, "dwarf_siblingof");
	}

out:
	if (dwarf_end(dw))
		dwarf_err(EX_SOFTWARE, "dwarf_end");

	return (EX_OK);
}
예제 #22
0
static void
structprobe(Dwarf *dw, Dwarf_Die *structdie)
{
	Dwarf_Die memdie;
	Dwarf_Word lastoff = 0, structsize;
	unsigned cline, members, nholes;
	size_t memsz, holesz;
	int x;

	(void)dw;

	cline = members = nholes = 0;
	memsz = holesz = 0;

	printf("struct %s {\n", dwarf_diename(structdie));

	if (dwarf_aggregate_size(structdie, &structsize) == -1)
		dwarf_err(EX_DATAERR, "dwarf_aggregate_size");

	if (dwarf_child(structdie, &memdie)) {
		printf("XXX ???\n");
		exit(EX_DATAERR);
	}

	do {
		Dwarf_Attribute type_attr, base_type_attr;
		Dwarf_Die type_die, base_type_die;
		char type_name[128], mem_name[128], ptr_suffix[32] = { '\0' };
		const char *type_tag = "";
		const char *type = NULL;
		unsigned type_ptrlevel = 0;

		Dwarf_Word msize, off;

		if (dwarf_tag(&memdie) != DW_TAG_member)
			continue;

		members++;
		/*
		 * TODO: Handle bitfield members. DW_AT_bit_offset,
		 * DW_AT_bit_size;
		 */

	 	/* Chase down the type die of this member */
		get_dwarf_attr(&memdie, DW_AT_type, &type_attr, &type_die);

		/* Member offset ... */
		if (get_member_offset(&memdie, &off) == -1)
			dwarf_err(EX_DATAERR, "%s", dwarf_diename(&memdie));

		/* Member size. */
		if (get_member_size(&type_die, &msize) == -1)
			dwarf_err(EX_DATAERR, "get_member_size");

		/* Format name; 'struct foo', 'enum bar', 'char **', etc. */
		if (isstruct(dwarf_tag(&type_die))) {
			type_tag = "struct ";
			type = dwarf_diename(&type_die);
		} else if (dwarf_tag(&type_die) == DW_TAG_enumeration_type) {
			type_tag = "enum ";
			type = dwarf_diename(&type_die);
		} else if (dwarf_tag(&type_die) == DW_TAG_pointer_type) {
			unsigned i;

			do {
				if (dwarf_tag(&type_die) == DW_TAG_pointer_type)
					type_ptrlevel++;
				else if (isstruct(dwarf_tag(&type_die)))
					type_tag = "struct ";
				else if (dwarf_tag(&type_die) == DW_TAG_enumeration_type)
					type_tag = "enum ";
				else
					printf("!!! XXX ignored pointer qualifier TAG %#x\n",
					    dwarf_tag(&type_die));

				/*
				 * Pointers to basic types still need some
				 * work. Clang doesn't emit an AT_TYPE for
				 * 'void*,' for example.
				 */
				if (!dwarf_hasattr(&type_die, DW_AT_type))
					break;

				get_dwarf_attr(&type_die, DW_AT_type,
				    &base_type_attr, &base_type_die);
				type_die = base_type_die;
				type_attr = base_type_attr;
			} while (dwarf_tag(&type_die) != DW_TAG_base_type);

			type = dwarf_diename(&type_die);
			if (type_ptrlevel > sizeof(ptr_suffix) - 2)
				type_ptrlevel = sizeof(ptr_suffix) - 2;
			ptr_suffix[0] = ' ';
			for (i = 1; i <= type_ptrlevel; i++)
				ptr_suffix[i] = '*';
			ptr_suffix[i] = '\0';
		} else
			type = dwarf_diename(&type_die);

		if (type == NULL)
			type = "<anonymous>";

		snprintf(type_name, sizeof(type_name), "%s%s%s", type_tag,
		    type, ptr_suffix);

		if (off != lastoff) {
			printf("\n\t/* XXX %ld bytes hole, try to pack */\n\n", off - lastoff);
			nholes++;
			holesz += (off - lastoff);
		}

		snprintf(mem_name, sizeof(mem_name), "%s;",
		    dwarf_diename(&memdie));

		printf("\t%-27s%-21s /* %5ld %5ld */\n", type_name, mem_name,
		    (long)off, (long)msize);
		memsz += msize;

		lastoff = off + msize;
		if (lastoff / cachelinesize > cline) {
			int ago = lastoff % cachelinesize;
			cline = lastoff / cachelinesize;

			if (ago)
				printf("\t/* --- cacheline %u boundary (%ld "
				    "bytes) was %d bytes ago --- */\n", cline,
				    (long)cline * cachelinesize, ago);
			else
				printf("\t/* --- cacheline %u boundary (%ld "
				    "bytes) --- */\n", cline, (long)cline *
				    cachelinesize);
		}
	} while ((x = dwarf_siblingof(&memdie, &memdie)) == 0);
	if (x == -1)
		dwarf_err(EX_DATAERR, "dwarf_siblingof");

	printf("\n\t/* size: %lu, cachelines: %u, members: %u */\n",
	    structsize, cline + 1, members);
	printf("\t/* sum members: %zu, holes: %u, sum holes: %zu */\n", memsz,
	    nholes, holesz);
	printf("\t/* last cacheline: %lu bytes */\n", lastoff % cachelinesize);

	printf("};\n");
}
예제 #23
0
파일: decl.c 프로젝트: JamesLinus/mcc
static struct vector *decls(declfun_p * dcl)
{
    struct vector *v = vec_new();
    node_t *basety;
    int sclass, fspec;
    int level = SCOPE;
    int follow[] = {STATIC, INT, CONST, IF, '}', 0};

    basety = specifiers(&sclass, &fspec);
    if (token->id == ID || token->id == '*' || token->id == '(') {
        struct token *id = NULL;
        node_t *ty = NULL;
        int params = 0;        // for functioness

        // declarator
        if (level == GLOBAL)
            declarator(&ty, &id, &params);
        else
            declarator(&ty, &id, NULL);
        attach_type(&ty, basety);

        if (level == GLOBAL && params) {
            if (first_funcdef(ty)) {
                vec_push(v, funcdef(id, ty, sclass, fspec));
                return v;
            } else {
                exit_params();
            }
        }

        for (;;) {
            if (id) {
                int kind;
                if (dcl == globaldecl)
                    kind = GLOBAL;
                else if (dcl == paramdecl)
                    kind = PARAM;
                else
                    kind = LOCAL;
                node_t *decl = make_decl(id, ty, sclass, fspec, dcl);
                if (token->id == '=')
                    decl_initializer(decl, sclass, kind);
                ensure_decl(decl, sclass, kind);
                vec_push(v, decl);
            }

            if (token->id != ',')
                break;

            expect(',');
            id = NULL;
            ty = NULL;
            // declarator
            declarator(&ty, &id, NULL);
            attach_type(&ty, basety);
        }
    } else if (isenum(basety) || isstruct(basety) || isunion(basety)) {
        // struct/union/enum
        int node_id;
        node_t *decl;
        if (isstruct(basety))
            node_id = STRUCT_DECL;
        else if (isunion(basety))
            node_id = UNION_DECL;
        else
            node_id = ENUM_DECL;

        decl = ast_decl(node_id);
        DECL_SYM(decl) = TYPE_TSYM(basety);
        vec_push(v, decl);
    } else {
        error("invalid token '%s' in declaration", token->name);
    }
    match(';', follow);

    return v;
}