home *** CD-ROM | disk | FTP | other *** search
- #include "c.h"
- #pragma warning(disable:4100)
- char *fname;
- #define add(x,n) (x > INT_MAX-(n) ? (overflow=1,x) : x+(n))
- #define chkoverflow(x,n) ((void)add(x,n))
- #define bits2bytes(n) (((n) + 7)/8)
-
- int DefaultAlignment = 16;
-
- static int regcount;
-
- static List autos, registers;
- Symbol cfunc; /* current function */
- FunctionDescriptor FunctionInfo;
- typedef struct tagDefinedFunctions {
- struct tagDefinedFunctions *Next;
- Symbol func;
- } DefinedFunctionsList;
-
- static DefinedFunctionsList *DefinedFunctions=NULL;
-
- Symbol retv; /* return value location for structs */
-
- static void checkref ARGS((Symbol, void *));
- static Symbol dclglobal ARGS((int, char *, Type, Coordinate *, int callAttributes));
- static Symbol dcllocal (int, char *, Type, Coordinate *,int);
- static Symbol dclparam (int, char *, Type, Coordinate *,int);
- static Type dclr ARGS((Type, char **, Symbol **, int, int *));
- static Type dclr1 ARGS((char **, Symbol **, int, int *));
- static void decl ARGS((Symbol(*) (int, char *, Type, Coordinate *,int)));
- extern void doconst ARGS((Symbol, void *));
- static void doglobal ARGS((Symbol, void *));
- static void doextern ARGS((Symbol, void *));
- static void exitparams ARGS((Symbol[]));
- static void fields ARGS((Type));
- static void funcdefn ARGS((int, char *, Type, Symbol[], Coordinate, int));
- static void initglobal ARGS((Symbol, int));
- static void oldparam ARGS((Symbol, void *));
- static Symbol *parameters ARGS((Type));
- static Type specifier ARGS((int *, int *, int *));
- static Type structdcl ARGS((int));
- static Type tnode ARGS((int, Type));
-
- static void AddToFunctionsList(Symbol s)
- {
- DefinedFunctionsList *rvp;
- if (DefinedFunctions == NULL) {
- DefinedFunctions = allocate(sizeof(DefinedFunctionsList),PERM);
- rvp = DefinedFunctions;
- }
- else {
- rvp = DefinedFunctions;
- while (rvp->Next) {
- rvp = rvp->Next;
- }
- rvp->Next = allocate(sizeof(DefinedFunctionsList),PERM);
- rvp = rvp->Next;
- }
- rvp->func = s;
- rvp->Next = NULL;
- }
-
- void program()
- {
- int n;
-
- level = GLOBAL;
- for (n = 0; t != EOI; n++)
- if (kind[t] == CHAR || kind[t] == STATIC
- || t == ID || t == '*' || t == '(') {
- decl(dclglobal);
- deallocate(STMT);
- if (!(glevel >= 3 || xref))
- deallocate(FUNC);
- }
- else if (t == ';') {
- warning("empty declaration\n");
- t = gettok();
- }
- else {
- error("unrecognized declaration\n");
- t = gettok();
- }
- if (n == 0)
- warning("empty input file\n");
- }
- static Type specifier(int *sclass, int *isRedeclaration, int *attributes)
- {
- int cls, cons, sign, size, type, vol;
- int qualifierseen=0;
- Type ty = NULL;
- int isPascal = 0;
-
- if (isRedeclaration)
- *isRedeclaration = 0;
- *attributes = 0;
- cls = vol = cons = sign = size = type = 0;
- if (sclass == NULL)
- cls = AUTO;
- for (;;) {
- int *p, tt = t;
- restart:
- switch (t) {
- case AUTO:
- case REGISTER:
- if (level <= GLOBAL && cls == 0)
- error("invalid use of `%k'\n", t);
- p = &cls;
- t = gettok();
- qualifierseen = 1;
- break;
- case STATIC:
- case EXTERN:
- case TYPEDEF:
- p = &cls;
- t = gettok();
- break;
- case CONST:
- p = &cons;
- t = gettok();
- break;
- case VOLATILE:
- p = &vol;
- t = gettok();
- break;
- case SIGNED:
- case UNSIGNED:
- p = &sign;
- t = gettok();
- qualifierseen = 1;
- break;
- case LONG:
- case SHORT:
- p = &size;
- t = gettok();
- qualifierseen = 1;
- break;
- case VOID:
- case CHAR:
- case INT:
- case FLOAT:
- case DOUBLE:
- case LONGLONG:
- p = &type;
- ty = tsym->type;
- t = gettok();
- qualifierseen = 1;
- break;
- case ENUM:
- p = &type;
- ty = enumdcl();
- break;
- case STRUCT:
- case UNION:
- p = &type;
- ty = structdcl(t);
- break;
- case PASCALKEYW:
- p = &isPascal;
- t = gettok();
- break;
- case STDCALL:
- *attributes = 1;
- t = gettok();
- goto restart;
- case ID:
- if (istypename(t, tsym) && type == 0) {
- use(tsym, src);
- ty = tsym->type;
- p = &type;
- t = gettok();
- }
- else
- p = NULL;
- break;
- default:
- p = NULL;
- }
- if (p == NULL)
- break;
- if (*p)
- error("invalid use of `%k'\n", tt);
- *p = tt;
- }
- if (sclass)
- *sclass = cls;
- if (type == 0) {
- if (!qualifierseen && Aflag > 1)
- warning("no type specified. Defaulting to int\n");
- type = INT;
- ty = inttype;
- }
- if (size == SHORT && type != INT
- || size == LONG && type != INT && type != DOUBLE
- || sign && type != INT && type != CHAR && type != LONGLONG) {
- if (isRedeclaration && type == ID) {
- Symbol sy;
-
- sy = lookup(tsym->name, identifiers);
- if (sy == NULL)
- goto err;
- if (sy->sclass != TYPEDEF)
- goto err;
- if (sy->type == NULL)
- goto err;
- if (sy->type->op != size) {
- if (sy->type->op != ty->op && sy->type->op != sign)
- goto err;
- }
- warning("redefinition of %s\n", sy->name);
- *isRedeclaration = 1;
- return (sy->type);
- }
- err:
- error("invalid type specification\n");
- }
- if (type == CHAR && sign)
- ty = sign == UNSIGNED ? unsignedchar : signedchar;
- else if (type == LONGLONG && sign)
- ty = sign == UNSIGNED ? ulonglongtype : longlongtype;
- else if (size == SHORT)
- ty = sign == UNSIGNED ? unsignedshort : shorttype;
- else if (size == LONG && type == DOUBLE)
- ty = longdouble;
- else if (size == LONG)
- ty = sign == UNSIGNED ? unsignedlong : longtype;
- else if (sign == UNSIGNED && type == INT)
- ty = unsignedtype;
- if (cons == CONST)
- ty = qual(CONST, ty);
- if (vol == VOLATILE)
- ty = qual(VOLATILE, ty);
- if (isPascal == PASCALKEYW)
- ty = qual(PASCALKEYW, ty);
- return ty;
- }
- static void decl(Symbol(*dcl)(int, char *, Type, Coordinate *, int callAttribute))
- {
- int sclass, redeclaration, callAttributes;
- Type ty, ty1;
- static char stop[] = {CHAR, STATIC, ID, 0};
-
- ty = specifier(&sclass, &redeclaration, &callAttributes);
- if (redeclaration) {
- test(';', stop);
- return;
- }
- if (t == ID || t == '*' || t == '(' || t == '[') {
- char *id;
- int dummy;
- Coordinate pos;
- id = NULL;
- pos = src;
- if (level == GLOBAL) {
- Symbol *params = NULL;
- ty1 = dclr(ty, &id, ¶ms, 0, &dummy);
- if (dummy) callAttributes = dummy;
- if (params && id && isfunc(ty1)
- && (t == '{' || istypename(t, tsym)
- || (kind[t] == STATIC && t != TYPEDEF))) {
- if (sclass == TYPEDEF) {
- error("invalid use of `typedef'\n");
- sclass = EXTERN;
- }
- if (ty1->u.f.oldstyle)
- exitscope();
- if (callAttributes) {
- if (ty1->op != FUNCTION)
- error("Incorrect usage of _stdcall");
- else
- ty1->u.f.isStdCall = 1;
- }
- funcdefn(sclass,fname = id, ty1, params, pos, callAttributes);
- fname = NULL;
- return;
- }
- else if (params)
- exitparams(params);
- }
- else {
- int oldAttrib = callAttributes;
- ty1 = dclr(ty, &id, NULL, 0, &callAttributes);
- if (oldAttrib) callAttributes = oldAttrib;
- }
- for (;;) {
- if (Aflag >= 1 && !hasproto(ty1))
- warning("missing prototype\n");
- if (id == NULL)
- error("missing identifier\n");
- else if (sclass == TYPEDEF) {
- Symbol p = lookup(id, identifiers);
- if (p && p->scope == level) {
- if (p->type->op == POINTER &&
- ty1->op == POINTER) {
- warning("redeclaration of '%s'\n", id);
- }
- else if (p->type->op != ty1->op)
- error("redeclaration of `%s'\n", id);
- }
- p = install(id, &identifiers, level,
- level < LOCAL ? PERM : FUNC);
- p->type = ty1;
- p->sclass = TYPEDEF;
- p->src = pos;
- if (callAttributes)
- p->Flags = 1;
- }
- else
- (void) (*dcl) (sclass, id, ty1, &pos, callAttributes);
- if (t != ',')
- break;
- t = gettok();
- id = NULL;
- pos = src;
- ty1 = dclr(ty, &id, NULL, 0, &callAttributes);
- }
- }
- else if (ty == NULL
- || !(isenum(ty) ||
- isstruct(ty) && (*unqual(ty)->u.sym->name < '1' || *unqual(ty)->u.sym->name > '9')))
- error("empty declaration\n");
- test(';', stop);
- }
- static Symbol dclglobal(int sclass, char *id, Type ty, Coordinate * pos, int callAttributes)
- {
- Symbol p;
-
- if (sclass == 0)
- sclass = AUTO;
- else if (sclass != EXTERN && sclass != STATIC) {
- error("invalid storage class `%k' for `%t %s'\n",
- sclass, ty, id);
- sclass = AUTO;
- }
- p = lookup(id, identifiers);
- if (p && p->scope == GLOBAL) {
- if (p->sclass != TYPEDEF && eqtype(ty, p->type, 1))
- ty = compose(ty, p->type);
- else
- error("redeclaration of `%s' previously declared at %w\n", p->name, &p->src);
-
- if (!isfunc(ty) && p->defined && t == '=')
- error("redefinition of `%s' previously defined at %w\n", p->name, &p->src);
-
- if (p->sclass == EXTERN && sclass == STATIC
- || p->sclass == STATIC && sclass == AUTO
- || p->sclass == AUTO && sclass == STATIC)
- warning("inconsistent linkage for `%s' previously declared at %w\n", p->name, &p->src);
-
- }
- if (p == NULL || p->scope != GLOBAL) {
- p = install(id, &globals, GLOBAL, PERM);
- p->sclass = sclass;
- if (p->sclass != STATIC) {
- static int nglobals;
- nglobals++;
- if (Aflag >= 2 && nglobals == 512)
- warning("more than 511 external identifiers\n");
- }
- if (callAttributes)
- p->Flags = 1;
- p->type = ty;
- (*IR->defsymbol) (p);
- }
- else if (p->sclass == EXTERN)
- p->sclass = sclass;
- p->type = ty;
- p->src = *pos;
- if (callAttributes)
- p->Flags = 1;
- {
- Symbol q = lookup(p->name, externals);
- if (q && (p->sclass == STATIC
- || !eqtype(p->type, q->type, 1)))
- warning("declaration of `%s' does not match previous declaration at %w\n", p->name, &q->src);
-
- }
- if (t == '=' && isfunc(p->type)) {
- error("illegal initialization for `%s'\n", p->name);
- t = gettok();
- initializer(p->type, 0);
- }
- else if (t == '=')
- initglobal(p, 0);
- else if (p->sclass == STATIC && !isfunc(p->type)
- && p->type->size == 0)
- error("undefined size for `%t %s'\n", p->type, p->name);
- return p;
- }
- static void initglobal(Symbol p, int flag)
- {
- Type ty;
-
- if (t == '=' || flag) {
- p->assigned = 1;
- p->references++;
- p->firstuse = StatementCount;
- if (p->sclass == STATIC) {
- for (ty = p->type; isarray(ty); ty = ty->type);
- defglobal(p, isconst(ty) ? LIT : DATA);
- }
- else
- defglobal(p, DATA);
- if (t == '=')
- t = gettok();
- ty = initializer(p->type, 0);
- if (isarray(p->type) && p->type->size == 0)
- p->type = ty;
- if (p->sclass == EXTERN)
- p->sclass = AUTO;
- p->defined = 1;
- }
- }
- void defglobal(Symbol p, int seg)
- {
- p->u.seg = seg;
- swtoseg(p->u.seg);
- if (p->sclass != STATIC)
- (*IR->export) (p);
- if (level == GLOBAL && glevel > 0 && IR->stabsym) {
- (*IR->stabsym) (p);
- swtoseg(p->u.seg);
- }
- (*IR->global) (p);
- }
-
- static Type dclr(Type basety, char **id, Symbol ** params, int abstract, int *attributes)
- {
-
- Type ty;
-
- *attributes = 0;
- ty = dclr1(id, params, abstract, attributes);
- for (; ty; ty = ty->type)
- switch (ty->op) {
- case POINTER:
- basety = ptr(basety);
- break;
- case FUNCTION:
- basety = func(basety, ty->u.f.proto, ty->u.f.oldstyle);
- break;
- case ARRAY:
- basety = array(basety, ty->size, 0);
- break;
- case CONST:
- case VOLATILE:
- basety = qual(ty->op, basety);
- break;
- default:
- assert(0);
- }
- if (Aflag >= 2 && basety->size > 32767)
- warning("more than 32767 bytes in `%t'\n", basety);
- return basety;
- }
- static Type tnode(int op, Type type)
- {
- Type ty;
-
- NEW0(ty, STMT);
- ty->op = op;
- ty->type = type;
- return ty;
- }
- static Type dclr1(char **id, Symbol ** params, int abstract, int *attributes)
- {
- Type ty = NULL;
- Type ty1;
-
- restart:
- switch (t) {
- case ID:
- if (id)
- *id = token;
- else
- error("extraneous identifier `%s'\n", token);
- t = gettok();
- break;
- case '*':
- t = gettok();
- if (t == CONST || t == VOLATILE) {
- ty1 = ty = tnode(t, NULL);
- while ((t = gettok()) == CONST || t == VOLATILE)
- ty1 = tnode(t, ty1);
- ty->type = dclr1(id, params, abstract, attributes);
- ty = ty1;
- }
- else
- ty = dclr1(id, params, abstract, attributes);
- ty = tnode(POINTER, ty);
- break;
- case STDCALL:
- t = gettok();
- *attributes = 1;
- goto restart;
- case '(':
- t = gettok();
- if (t == STDCALL) {
- t = gettok();
- *attributes = 1;
- }
- if (abstract
- && (t == REGISTER || istypename(t, tsym) || t == ')')) {
- Symbol *args;
- ty = tnode(FUNCTION, ty);
- enterscope();
- if (level > PARAM)
- enterscope();
- args = parameters(ty);
- exitparams(args);
- }
- else {
- ty = dclr1(id, params, abstract, attributes);
- expect(')');
- if (abstract && ty == NULL
- && (id == NULL || *id == NULL))
- return tnode(FUNCTION, NULL);
- } break;
- case '[':
- break;
- default:
- return ty;
- }
- while (t == '(' || t == '[')
- switch (t) {
- case '(':
- t = gettok(); {
- Symbol *args;
- ty = tnode(FUNCTION, ty);
- enterscope();
- if (level > PARAM)
- enterscope();
- args = parameters(ty);
- if (params && *params == NULL)
- *params = args;
- else
- exitparams(args);
- }
- break;
- case '[':
- t = gettok(); {
- int n = 0;
- if (kind[t] == ID) {
- n = intexpr(']', 1);
- if (n <= 0) {
- error("`%d' is an illegal array size\n", n);
- n = 1;
- }
- }
- else
- expect(']');
- ty = tnode(ARRAY, ty);
- ty->size = n;
- } break;
- default:
- assert(0);
- }
- return ty;
- }
- static Symbol *parameters(Type fty)
- {
- List list = NULL;
- Symbol *params;
- int callAttributes, dummy;
- Type tmpType;
-
- if (kind[t] == STATIC || istypename(t, tsym)) {
- int n = 0;
- Type ty1 = NULL;
- for (;;) {
- Type ty;
- int sclass = 0;
- char *id = NULL;
- if (ty1 && t == ELLIPSIS) {
- static struct symbol sentinel;
- if (sentinel.type == NULL) {
- sentinel.type = voidtype;
- sentinel.defined = 1;
- }
- if (ty1 == voidtype)
- error("illegal formal parameter types\n");
- list = append(&sentinel, list);
- t = gettok();
- break;
- }
- if (!istypename(t, tsym) && t != REGISTER)
- error("missing parameter type\n");
- n++;
- tmpType = specifier(&sclass, NULL, &dummy);
- ty = dclr(tmpType, &id, NULL, 1, &callAttributes);
- if (ty == voidtype && (ty1 || id)
- || ty1 == voidtype)
- error("illegal formal parameter types\n");
- if (id == NULL)
- id = stringd(n);
- if (ty != voidtype)
- list = append(dclparam(sclass, id, ty, &src,callAttributes), list);
- if (Aflag >= 1 && !hasproto(ty))
- warning("missing prototype\n");
- if (ty1 == NULL)
- ty1 = ty;
- if (t != ',')
- break;
- t = gettok();
- }
- fty->u.f.proto = newarray(length(list) + 1,
- sizeof(Type *), PERM);
- params = ltov(&list, FUNC);
- for (n = 0; params[n]; n++)
- fty->u.f.proto[n] = params[n]->type;
- fty->u.f.proto[n] = NULL;
- fty->u.f.oldstyle = 0;
- }
- else {
- if (t == ID)
- for (;;) {
- Symbol p;
-
- if (t != ID) {
- error("expecting an identifier\n");
- break;
- }
- p = dclparam(0, token, inttype, &src,callAttributes);
- p->defined = 0;
- list = append(p, list);
- t = gettok();
- if (t != ',')
- break;
- t = gettok();
- }
- params = ltov(&list, FUNC);
- fty->u.f.proto = NULL;
- fty->u.f.oldstyle = 1;
- }
- if (t != ')') {
- static char stop[] = {CHAR, STATIC, IF, ')', 0};
- expect(')');
- skipto('{', stop);
- }
- if (t == ')')
- t = gettok();
- return params;
- }
- static void exitparams(Symbol params[])
- {
- assert(params);
- if (params[0] && !params[0]->defined)
- error("extraneous old-style parameter list\n");
- if (level > PARAM)
- exitscope();
- exitscope();
- }
-
- static Symbol dclparam(int sclass, char *id, Type ty, Coordinate * pos,int callAttributes)
- {
- Symbol p;
-
- if (isfunc(ty))
- ty = ptr(ty);
- else if (isarray(ty))
- ty = atop(ty);
- if (sclass == 0)
- sclass = AUTO;
- else if (sclass != REGISTER) {
- error("invalid storage class `%k' for `%t%s\n",
- sclass, ty, stringf(id ? " %s'" : "' parameter", id));
- sclass = AUTO;
- }
- else if (isvolatile(ty) || isstruct(ty)) {
- warning("register declaration ignored for `%t%s\n",
- ty, stringf(id ? " %s'" : "' parameter", id));
- sclass = AUTO;
- }
-
- p = lookup(id, identifiers);
- if (p && p->scope == level)
- error("duplicate declaration for `%s' previously declared at %w\n", id, &p->src);
-
- else
- p = install(id, &identifiers, level, FUNC);
- p->sclass = sclass;
- p->src = *pos;
- p->type = ty;
- p->defined = 1;
- if (t == '=') {
- error("illegal initialization for parameter `%s'\n", id);
- t = gettok();
- (void) expr1(0);
- }
- return p;
- }
- static Type structdcl(int op)
- {
- char *tag;
- Type ty;
- Symbol p;
- Coordinate pos;
-
- t = gettok();
- pos = src;
- if (t == ID) {
- tag = token;
- t = gettok();
- }
- else
- tag = "";
- if (t == '{') {
- static char stop[] = {IF, ',', 0};
- ty = newstruct(op, tag);
- ty->u.sym->src = pos;
- ty->u.sym->defined = 1;
- t = gettok();
- if (istypename(t, tsym))
- fields(ty);
- else
- error("invalid %k field declarations\n", op);
- test('}', stop);
- }
- else if (*tag && (p = lookup(tag, types)) != NULL
- && p->type->op == op) {
- ty = p->type;
- if (t == ';' && p->scope < level)
- ty = newstruct(op, tag);
- }
- else {
- if (*tag == 0)
- error("missing %k tag\n", op);
- ty = newstruct(op, tag);
- }
- if (*tag && xref)
- use(ty->u.sym, pos);
- return ty;
- }
- static void fields(Type ty)
- {
- {
- int n = 0;
- int callAttributes;
- int dummy;
-
- while (istypename(t, tsym)) {
- static char stop[] = {IF, CHAR, '}', 0};
- Type ty1 = specifier(NULL, NULL, &callAttributes);
- for (;;) {
- Field p;
- char *id = NULL;
-
- Type fty = dclr(ty1, &id, NULL, 0, &dummy);
- p = newfield(id, ty, fty);
- if (Aflag >= 1 && !hasproto(p->type)) {
- if (id)
- warning("missing prototype for %s\n", id);
- else
- warning("missing prototype\n");
- }
- if (t == ':') {
- if (unqual(p->type) != inttype
- && unqual(p->type) != unsignedtype) {
- if (unqual(p->type) != unsignedshort
- && unqual(p->type) != unsignedlong)
- error("`%t' is an illegal bit-field type\n",
- p->type);
- else if (Aflag > 1)
- warning("promoting %t to int\n", p->type);
- p->type = inttype;
- }
- t = gettok();
- p->bitsize = (short)intexpr(0, 0);
- if (p->bitsize > 8 * inttype->size || p->bitsize < 0) {
- error("`%d' is an illegal bit-field size\n",
- p->bitsize);
- p->bitsize = (short)(8 * inttype->size);
- }
- else if (p->bitsize == 0 && id) {
- warning("extraneous 0-width bit field `%t %s' ignored\n", p->type, id);
-
- p->name = stringd(genlabel(1));
- }
- p->lsb = 1;
- }
- else if (id == NULL && Xflag && isstruct(p->type)) {
- if (Aflag >= 2)
- warning("non-ANSI unnamed substructure in `%t'\n", ty);
- if (p->type->size == 0)
- error("undefined size for field `%t'\n", p->type);
- p->name = NULL;
- break;
- }
- else {
- if (id == 0 && isstruct(p->type)) {
- if (Aflag >= 2)
- warning("non-ANSI unnamed substructure\n");
- if (p->type->size == 0)
- error("undefined size for field '%t'\n",p->type);
- p->name = 0;
- break;
- }
- else if (isfunc(p->type))
- error("`%t' is an illegal field type\n", p->type);
- else if (p->type->size == 0) {
-
- warning("undefined size for field `%t %s'\n", p->type, id);
- p->type->size = p->type->align;
- }
- }
- if (isconst(p->type))
- ty->u.sym->u.s.cfields = 1;
- if (isvolatile(p->type))
- ty->u.sym->u.s.vfields = 1;
- if (dummy) {
- if (fty->op == POINTER) {
- if (fty->type->op != FUNCTION)
- error("incorrect _stdcall usage");
- else
- fty->type->u.f.isStdCall = 1;
- }
- else
- fty->u.f.isStdCall = 1;
- }
- n++;
- if (Aflag >= 2 && n == 128)
- warning("more than 127 fields in `%t'\n", ty);
- if (t != ',')
- break;
- t = gettok();
- }
- test(';', stop);
- }
- }
- {
- int bits = 0, off = 0, overflow = 0;
- Field p, *q = &ty->u.sym->u.s.flist;
- ty->align = IR->structmetric.align;
- for (p = *q; p; p = p->link) {
- int a = p->type->align ? p->type->align : 1;
- if (a > DefaultAlignment) a = DefaultAlignment;
- if (p->lsb)
- a = unsignedtype->align;
- if (ty->op == UNION)
- off = bits = 0;
- else if (p->bitsize == 0 || bits == 0
- || bits - 1 + p->bitsize > 8 * unsignedtype->size) {
- off = add(off, bits2bytes(bits - 1));
- bits = 0;
- chkoverflow(off, a - 1);
- off = roundup(off, a);
- }
- if (a > ty->align)
- ty->align = a;
- p->offset = off;
-
- if (p->lsb) {
- if (bits == 0)
- bits = 1;
- if (IR->little_endian)
- p->lsb = (short)bits;
- else
- p->lsb = (short)(8 * unsignedtype->size - bits + 1 - p->bitsize + 1);
- bits += p->bitsize;
- }
- else
- off = add(off, p->type->size);
- if (off + bits2bytes(bits - 1) > ty->size)
- ty->size = off + bits2bytes(bits - 1);
- if (p->name == NULL
- || !('1' <= *p->name && *p->name <= '9')) {
- *q = p;
- q = &p->link;
- }
- }
- *q = NULL;
- chkoverflow(ty->size, ty->align - 1);
- ty->size = roundup(ty->size, ty->align);
- if (overflow) {
- error("size of `%t' exceeds %d bytes\n", ty, INT_MAX);
- ty->size = INT_MAX & (~(ty->align - 1));
- }
- if (Xflag)
- checkfields(ty);
- }
- }
- static void funcdefn(int sclass, char *id, Type ty, Symbol params[], Coordinate pt, int callAttributes)
- {
- int i, n;
- Symbol *callee, *caller, p;
- Type rty = freturn(ty);
- Code cp;
-
- if (isstruct(rty) && rty->size == 0)
- error("illegal use of incomplete type `%t'\n", rty);
- memset(&FunctionInfo,0,sizeof(FunctionInfo));
- StatementCount = 1;
- for (n = 0; params[n]; n++);
- if (n > 0 && params[n - 1]->name == NULL)
- params[--n] = NULL;
- if (Aflag >= 2 && n > 31)
- warning("more than 31 parameters in function `%s'\n", id);
- for (i=0; i<n;i++) {
- params[i]->firstuse = StatementCount;
- params[i]->x.isArgument = 1;
- }
- StatementCount++;
- if (ty->u.f.oldstyle) {
- caller = params;
- callee = newarray(n + 1, sizeof *callee, FUNC);
- memcpy(callee, caller, (n + 1) * sizeof *callee);
- enterscope();
- assert(level == PARAM);
- while (kind[t] == STATIC || istypename(t, tsym))
- decl(dclparam);
- foreach(identifiers, PARAM, oldparam, callee);
-
- for (i = 0; (p = callee[i]) != NULL; i++) {
- if (!p->defined)
- callee[i] = dclparam(0, p->name, inttype, &p->src,0);
- *caller[i] = *p;
- caller[i]->sclass = AUTO;
- if (unqual(p->type) == floattype)
- caller[i]->type = doubletype;
- else
- caller[i]->type = promote(p->type);
- }
- p = lookup(id, identifiers);
- if (p && p->scope == GLOBAL && isfunc(p->type)
- && p->type->u.f.proto) {
- Type *proto = p->type->u.f.proto;
- for (i = 0; caller[i] && proto[i]; i++)
- if (eqtype(unqual(proto[i]),
- unqual(caller[i]->type), 1) == 0)
- break;
- if (proto[i] || caller[i])
- error("conflicting argument declarations for function `%s'\n", id);
-
- }
- else {
- Type *proto = newarray(n + 1, sizeof *proto, PERM);
- if (Aflag >= 1)
- warning("missing prototype for `%s'\n", id);
- for (i = 0; i < n; i++)
- proto[i] = caller[i]->type;
- proto[i] = NULL;
- ty = func(rty, proto, 1);
- }
- for (i=0; i < n; i++) {
- callee[i]->x.isArgument = 1;
- }
- }
- else {
- callee = params;
- caller = newarray(n + 1, sizeof *caller, FUNC);
- for (i = 0; (p = callee[i]) != NULL && p->name; i++) {
- NEW(caller[i], FUNC);
- *caller[i] = *p;
- caller[i]->type = promote(p->type);
- caller[i]->sclass = AUTO;
- if ('1' <= *p->name && *p->name <= '9')
- error("missing name for parameter %d to function `%s'\n", i + 1, id);
-
- }
- caller[i] = NULL;
- }
- for (i = 0; (p = callee[i]) != NULL; i++)
- if (p->type->size == 0) {
- error("undefined size for parameter `%t %s'\n",
- p->type, p->name);
- caller[i]->type = p->type = inttype;
- }
- p = lookup(id, identifiers);
- if (p && isfunc(p->type) && p->defined)
- error("redefinition of `%s' previously defined at %w\n",
- p->name, &p->src);
- cfunc = dclglobal(sclass, id, ty, &pt, callAttributes);
- cfunc->u.f.label = genlabel(1);
- cfunc->u.f.callee = callee;
- cfunc->u.f.pt = src;
- cfunc->defined = 1;
- cfunc->Flags = (unsigned char)callAttributes;
- if (xref)
- use(cfunc, cfunc->src);
- if (Pflag)
- printproto(cfunc, cfunc->u.f.callee);
- if (ncalled >= 0)
- ncalled = findfunc(cfunc->name, pt.file);
- labels = table(NULL, LABELS);
- stmtlabs = table(NULL, LABELS);
- refinc = (float) 1.0;
- regcount = 0;
- codelist = &codehead;
- codelist->next = NULL;
- definept(NULL);
- if (!IR->wants_callb && isstruct(rty))
- retv = genident(AUTO, ptr(rty), PARAM);
- cp = compound(0, NULL, 0);
- FunctionInfo.cp = cp;
- for (cp = codelist; cp->kind < Label; cp = cp->prev);
- if (cp->kind != Jump) {
- if (rty != voidtype
- && (rty != inttype || Aflag >= 1))
- warning("missing return value\n");
- retcode(NULL);
- }
- definelab(cfunc->u.f.label);
- definept(NULL);
- if (events.exit)
- apply(events.exit, cfunc, NULL);
- walk(NULL, 0, 0);
- exitscope();
- assert(level == PARAM);
- foreach(identifiers, level, checkref, NULL);
- if (!IR->wants_callb && isstruct(rty)) {
- Symbol *a;
- a = newarray(n + 2, sizeof *a, FUNC);
- a[0] = retv;
- memcpy(&a[1], callee, (n + 1) * sizeof *callee);
- callee = a;
- a = newarray(n + 2, sizeof *a, FUNC);
- NEW(a[0], FUNC);
- *a[0] = *retv;
- memcpy(&a[1], caller, (n + 1) * sizeof *callee);
- caller = a;
- }
- if (!IR->wants_argb)
- for (i = 0; caller[i]; i++)
- if (isstruct(caller[i]->type)) {
- caller[i]->type = ptr(caller[i]->type);
- callee[i]->type = ptr(callee[i]->type);
- caller[i]->structarg = callee[i]->structarg = 1;
- }
- if (glevel > 1)
- for (i = 0; callee[i]; i++)
- callee[i]->sclass = AUTO;
- #if 0
- if (cfunc->sclass != STATIC)
- (*IR->export) (cfunc);
- #endif
- if (glevel) {
- swtoseg(CODE);
- (*IR->stabsym) (cfunc);
- }
- swtoseg(CODE);
- if (cfunc->u.f.ncalls)
- FunctionHasCalls = 1;
- else
- FunctionHasCalls = 0;
-
- (*IR->function) (cfunc, caller, callee, cfunc->u.f.ncalls);
- #if 1
- if (cfunc->sclass != STATIC)
- (*IR->export) (cfunc);
- #endif
- if (glevel && IR->stabfend)
- (*IR->stabfend) (cfunc, lineno);
- outflush();
- foreach(stmtlabs, LABELS, checklab, NULL);
- exitscope();
- expect('}');
- AddToFunctionsList(cfunc);
- labels = stmtlabs = NULL;
- retv = NULL;
- cfunc = NULL;
- ResetExceptions();
- }
- static void oldparam(Symbol p, void *cl)
- {
- int i;
- Symbol *callee = cl;
-
- for (i = 0; callee[i]; i++)
- if (p->name == callee[i]->name) {
- callee[i] = p;
- return;
- }
- error("declared parameter `%s' is missing\n", p->name);
- }
- Code compound(int loop, struct swtch * swp, int lev)
- {
- Code cp;
- int nregs;
-
- walk(NULL, 0, 0);
- cp = code(Blockbeg);
- enterscope();
- assert(level >= LOCAL);
- autos = registers = NULL;
- if (level == LOCAL && IR->wants_callb
- && isstruct(freturn(cfunc->type))) {
- retv = genident(AUTO, ptr(freturn(cfunc->type)), level);
- retv->defined = 1;
- retv->ref = (float) 1.0;
- registers = append(retv, registers);
- }
- if (level == LOCAL && events.entry)
- apply(events.entry, cfunc, NULL);
- expect('{');
- while (kind[t] == CHAR || kind[t] == STATIC
- || istypename(t, tsym) && getchr() != ':')
- decl(dcllocal);
- {
- int i;
- Symbol *a = ltov(&autos, STMT);
- nregs = length(registers);
- for (i = 0; a[i]; i++)
- registers = append(a[i], registers);
- cp->u.block.locals = ltov(®isters, FUNC);
- }
- while (kind[t] == IF || kind[t] == ID)
- statement(loop, swp, lev);
- walk(NULL, 0, 0);
- foreach(identifiers, level, checkref, NULL);
- {
- int i = nregs, j;
- Symbol p;
- for (; (p = cp->u.block.locals[i]) != NULL; i++) {
- for (j = i; j > nregs
- && cp->u.block.locals[j - 1]->ref < p->ref; j--)
- cp->u.block.locals[j] = cp->u.block.locals[j - 1];
- cp->u.block.locals[j] = p;
- }
- }
- cp->u.block.level = level;
- cp->u.block.identifiers = identifiers;
- cp->u.block.types = types;
- code(Blockend)->u.begin = cp;
- if (level > LOCAL) {
- exitscope();
- expect('}');
- }
- return cp;
- }
- static void checkref(Symbol p, void *cl)
- {
- if (p->scope >= PARAM
- && (isvolatile(p->type) || isfunc(p->type)))
- p->addressed = 1;
- if (/*Aflag >= 2 &&*/ p->defined && p->ref == 0) {
- if (p->sclass == STATIC)
- warning("static `%t %s' is not referenced\n",
- p->type, p->name);
- else if (p->scope == PARAM && Aflag > 1)
- warning("parameter `%t %s' is not referenced\n",
- p->type, p->name);
- else if (p->scope >= LOCAL && p->sclass != EXTERN)
- warning("local `%t %s' is not referenced\n",
- p->type, p->name);
- }
- #if 0
- if (p->sclass == AUTO
- && (p->scope == PARAM && regcount == 0
- || p->scope >= LOCAL)
- && !p->addressed && isscalar(p->type) && p->ref >= 3.0)
- p->sclass = REGISTER;
- #endif
- if (p->scope >= LOCAL && p->sclass == EXTERN) {
- Symbol q = lookup(p->name, externals);
- assert(q);
- q->ref += p->ref;
- }
- if (p->scope >= LOCAL && p->sclass != EXTERN ) {
-
- if (Aflag &&
- p->assigned == 1 && p->references == 1 && p->addressed == 0) {
- warning(" %s is assigned a value that is never used\n",p->name);
- }
- else if (p->assigned == 0 && p->references > 0) {
- if (p->type && p->type->op != ARRAY && p->type->op != STRUCT)
- warning(" possible usage of %s before definition\n",p->name);
- }
- }
- if (level == GLOBAL && p->sclass == STATIC && !p->defined
- && isfunc(p->type) && p->ref)
- error("undefined static `%t %s'\n", p->type, p->name);
- assert(!(level == GLOBAL && p->sclass == STATIC && !p->defined && !isfunc(p->type)));
- }
- static Symbol dcllocal(int sclass, char *id, Type ty, Coordinate * pos,int callAttributes)
- {
- Symbol p, q;
-
- if (sclass == 0)
- sclass = isfunc(ty) ? EXTERN : AUTO;
- else if (isfunc(ty) && sclass != EXTERN) {
- error("invalid storage class `%k' for `%t %s'\n",
- sclass, ty, id);
- sclass = EXTERN;
- }
- else if (sclass == REGISTER
- && (isvolatile(ty) || isstruct(ty) || isarray(ty))) {
- warning("register declaration ignored for `%t %s'\n",
- ty, id);
- sclass = AUTO;
- }
- q = lookup(id, identifiers);
- if (q && q->scope >= level
- || q && q->scope == PARAM && level == LOCAL)
- if (sclass == EXTERN && q->sclass == EXTERN
- && eqtype(q->type, ty, 1))
- ty = compose(ty, q->type);
- else
- error("redeclaration of `%s' previously declared at %w\n", q->name, &q->src);
-
- assert(level >= LOCAL);
- p = install(id, &identifiers, level, FUNC);
- p->type = ty;
- p->sclass = sclass;
- p->src = *pos;
- p->Flags = callAttributes;
- switch (sclass) {
- case EXTERN:
- if (q && q->scope == GLOBAL && q->sclass == STATIC) {
- p->sclass = STATIC;
- p->scope = GLOBAL;
- (*IR->defsymbol) (p);
- p->sclass = EXTERN;
- p->scope = level;
- }
- else
- (*IR->defsymbol) (p);
- {
- Symbol r = lookup(id, externals);
- if (r == NULL) {
- r = install(p->name, &externals, GLOBAL, PERM);
- r->src = p->src;
- r->type = p->type;
- r->sclass = p->sclass;
- q = lookup(id, globals);
- if (q && q->sclass != TYPEDEF && q->sclass != ENUM)
- r = q;
- }
- if (r && !eqtype(r->type, p->type, 1))
- warning("declaration of `%s' does not match previous declaration at %w\n", r->name, &r->src);
-
- } break;
- case STATIC:
- (*IR->defsymbol) (p);
- initglobal(p, 0);
- if (!p->defined)
- if (p->type->size > 0) {
- defglobal(p, BSS);
- (*IR->space) (p->type->size);
- }
- else
- error("undefined size for `%t %s'\n",
- p->type, p->name);
- p->defined = 1;
- break;
- case REGISTER:
- registers = append(p, registers);
- regcount++;
- p->defined = 1;
- break;
- case AUTO:
- autos = append(p, autos);
- p->defined = 1;
- break;
- default:
- assert(0);
- }
- if (t == '=') {
- Tree e;
- if (sclass == EXTERN)
- error("illegal initialization of `extern %s'\n", id);
- t = gettok();
- definept(NULL);
- if (isscalar(p->type)
- || isstruct(p->type) && t != '{') {
- if (t == '{') {
- t = gettok();
- e = expr1(0);
- expect('}');
- }
- else
- e = expr1(0);
- }
- else {
- Symbol t1;
- Type ty = p->type, ty1 = ty;
- while (isarray(ty1))
- ty1 = ty1->type;
- if (!isconst(ty) && (!isarray(ty) || !isconst(ty1)))
- ty = qual(CONST, ty);
- t1 = genident(STATIC, ty, GLOBAL);
- initglobal(t1, 1);
- if (isarray(p->type) && p->type->size == 0
- && t1->type->size > 0)
- p->type = array(p->type->type,
- t1->type->size / t1->type->type->size, 0);
- e = idtree(t1);
- }
- walk(root(asgn(p, e)), 0, 0);
- p->ref = (float) 1.0;
- p->firstuse = p->lastuse = StatementCount;
- }
- if (!isfunc(p->type) && p->defined && p->type->size <= 0)
- error("undefined size for `%t %s'\n", p->type, id);
- return p;
- }
- void finalize(void)
- {
- foreach(externals, GLOBAL, doextern, NULL);
- foreach(identifiers, GLOBAL, doglobal, NULL);
- foreach(identifiers, GLOBAL, checkref, NULL);
- foreach(constants, CONSTANTS, doconst, NULL);
- }
- static void doextern(Symbol p, void *cl)
- {
- Symbol q = lookup(p->name, identifiers);
-
- if (q)
- q->ref += p->ref;
- else {
- (*IR->defsymbol) (p);
- (*IR->import) (p);
- }
- }
- static void doglobal(Symbol p,void *cl)
- {
- if (!p->defined && (p->sclass == EXTERN
- || isfunc(p->type) && p->sclass == AUTO))
- (*IR->import) (p);
- else if (!p->defined && !isfunc(p->type)
- && (p->sclass == AUTO || p->sclass == STATIC)) {
- if (isarray(p->type)
- && p->type->size == 0 && p->type->type->size > 0)
- p->type = array(p->type->type, 1, 0);
- if (p->type->size > 0) {
- defglobal(p, BSS);
- (*IR->space) (p->type->size);
- }
- else
- error("undefined size for `%t %s'\n",
- p->type, p->name);
- p->defined = 1;
- }
- if (Pflag
- && !isfunc(p->type)
- && !p->generated && p->sclass != EXTERN)
- printdecl(p, p->type);
- }
- void doconst(Symbol p,void * cl)
- {
- if (p->u.c.loc) {
- assert(p->u.c.loc->u.seg == 0);
- defglobal(p->u.c.loc, LIT);
- if (isarray(p->type))
- (*IR->defstring) (p->type->size, p->u.c.v.p);
- else
- (*IR->defconst) (ttob(p->type), p->u.c.v);
- p->u.c.loc->defined = 1;
- p->u.c.loc = NULL;
- }
- }
- void checklab(Symbol p, void *cl)
- {
- if (!p->defined)
- error("undefined label `%s'\n", p->name);
- p->defined = 1;
- }
-
- Type enumdcl(void)
- {
- char *tag;
- Type ty;
- Symbol p;
- Coordinate pos;
-
- t = gettok();
- pos = src;
- p = NULL; /* Better be sure that p is initialized before use */
- if (t == ID) {
- tag = token;
- t = gettok();
- }
- else
- tag = "";
- if (t == '{') {
- static char follow[] = {IF, 0};
- int n = 0, k = -1;
- List idlist = 0;
- ty = newstruct(ENUM, tag);
- t = gettok();
- if (t != ID)
- error("expecting an enumerator identifier\n");
- while (t == ID) {
- char *id = token;
- Coordinate s;
- if (tsym && tsym->scope == level)
- error("redeclaration of `%s' previously declared at %w\n",
- token, &tsym->src);
- s = src;
- t = gettok();
- if (t == '=') {
- t = gettok();
- k = intexpr(0, 0);
- }
- else {
- if (k == INT_MAX)
- error("overflow in value for enumeration constant `%s'\n", id);
- k++;
- }
- p = install(id, &identifiers, level, level < LOCAL ? PERM : FUNC);
- p->src = s;
- p->type = ty;
- p->sclass = ENUM;
- p->u.value = k;
- idlist = append(p, idlist);
- n++;
- if (Aflag >= 2 && n == 128)
- warning("more than 127 enumeration constants in `%t'\n", ty);
- if (t != ',')
- break;
- t = gettok();
- if (Aflag >= 2 && t == '}')
- warning("non-ANSI trailing comma in enumerator list\n");
- }
- test('}', follow);
- ty->type = inttype;
- ty->size = ty->type->size;
- ty->align = ty->type->align;
- ty->u.sym->u.idlist = ltov(&idlist, PERM);
- ty->u.sym->defined = 1;
- }
- else if ((p = lookup(tag, types)) != NULL && p->type->op == ENUM) {
- ty = p->type;
- if (t == ';')
- error("empty declaration\n");
- }
- else {
- error("unknown enumeration `%s'\n", tag);
- ty = newstruct(ENUM, tag);
- ty->type = inttype;
- }
- if (*tag && xref)
- use(p, pos);
- return ty;
- }
-
- Type typename(void)
- {
- int callAttributes = 0;
- Type ty = specifier(NULL, NULL, &callAttributes);
-
- if (t == '*' || t == '(' || t == '[') {
- ty = dclr(ty, NULL, NULL, 1, &callAttributes);
- if (Aflag >= 1 && !hasproto(ty))
- warning("missing prototype\n");
- }
- return ty;
- }
-
- void DumpDefinedFunctions(void)
- {
- DefinedFunctionsList *rvp;
-
- rvp = DefinedFunctions;
- while (rvp) {
- if (rvp->func->scope == GLOBAL && rvp->func->sclass != STATIC)
- fprintf(xrefFile,"e %s %d\n",rvp->func->name,rvp->func->src.y);
- rvp = rvp->Next;
- }
- rvp = DefinedFunctions;
- while (rvp) {
- if (rvp->func->sclass == STATIC)
- fprintf(xrefFile,"s %s %d\n",rvp->func->name,rvp->func->src.y);
- rvp = rvp->Next;
- }
- }
-
- void CheckStaticUses(void)
- {
-
- DefinedFunctionsList *rvp;
-
- rvp = DefinedFunctions;
- return;
- while (rvp) {
- if (rvp->func->sclass == STATIC) {
- if (rvp->func->x.callused == 0 && rvp->func->ref == 0.0) {
- warning("static function %s is never used\n",rvp->func->name);
- }
- }
- rvp = rvp->Next;
- }
- }
-
- int GetLastFunctionLabel(void)
- {
- return cfunc->u.f.label;
- }
-
-