#define EXTERN #include "cc.h" /* * locals, parameters, globals etc of the same name should work ok without having * to duplicate Syms because the details are on the containing Nodes */ #define SZ_CHAR 1#define SZ_SHORT 2#define SZ_INT 4#define SZ_LONG 4#define SZ_FLOAT 4#define SZ_IND 4#define SZ_VLONG 8#define SZ_DOUBLE 8 char buf[128], mbuf[128];static Sym *sysop, *bioop, *libcop;static int again; #define STAR 0x80#define RET 0x80 #define LARR (-1729) static void swalk(void);static int isdec(Node*);static int isconst(Node*, vlong);static int cktype(Node*, Node*, int, int);static void addnode(int, Node*);static int argpos(Node*, Node*);static void setdec(Sym*, Type*);static Type* tcp(Type*);static int isadt(Type*);static void aargs(Node*);static int iteq(Type*, Type*);static Node* arg(Node*, int);static void etgen2(Sym*);static Node* ckneg(Node*);static Sym* suename(Type*);static int isnil(Node*);static void sliceasgn(Node*);static Node* lastn(Node*);static char* hasm(void);static void prn(Node*, int);static int isfn(Type*); schar ewidth[NTYPE] ={ -1, /* [TXXX] */ SZ_CHAR, /* [TCHAR] */ SZ_CHAR, /* [TUCHAR] */ SZ_SHORT, /* [TSHORT] */ SZ_SHORT, /* [TUSHORT] */ SZ_INT, /* [TINT] */ SZ_INT, /* [TUINT] */ SZ_LONG, /* [TLONG] */ SZ_LONG, /* [TULONG] */ SZ_VLONG, /* [TVLONG] */ SZ_VLONG, /* [TUVLONG] */ SZ_FLOAT, /* [TFLOAT] */ SZ_DOUBLE, /* [TDOUBLE] */ SZ_IND, /* [TIND] */ 0, /* [TFUNC] */ -1, /* [TARRAY] */ 0, /* [TVOID] */ -1, /* [TSTRUCT] */ -1, /* [TUNION] */ SZ_INT, /* [TENUM] */}; long ncast[NTYPE] ={ 0, /* [TXXX] */ BCHAR|BUCHAR, /* [TCHAR] */ BCHAR|BUCHAR, /* [TUCHAR] */ BSHORT|BUSHORT, /* [TSHORT] */ BSHORT|BUSHORT, /* [TUSHORT] */ BINT|BUINT|BLONG|BULONG|BIND, /* [TINT] */ BINT|BUINT|BLONG|BULONG|BIND, /* [TUINT] */ BINT|BUINT|BLONG|BULONG|BIND, /* [TLONG] */ BINT|BUINT|BLONG|BULONG|BIND, /* [TULONG] */ BVLONG|BUVLONG, /* [TVLONG] */ BVLONG|BUVLONG, /* [TUVLONG] */ BFLOAT, /* [TFLOAT] */ BDOUBLE, /* [TDOUBLE] */ BLONG|BULONG|BIND, /* [TIND] */ 0, /* [TFUNC] */ 0, /* [TARRAY] */ 0, /* [TVOID] */ BSTRUCT, /* [TSTRUCT] */ BUNION, /* [TUNION] */ 0, /* [TENUM] */}; enum{ TCFD = 1, TCFC = 2, TCPC = 4, TCAR = 8, TCIN = 16, TCGEN = TCFD|TCFC|TCPC|TCAR, TCALL = TCFD|TCFC|TCPC|TCAR|TCIN,}; enum{ SGLOB, SPARM, SAUTO,}; typedef struct Scope Scope; struct Scope{ Node *n; int k; Scope *nxt;}; static voidprtyp(Type *t, char *s, int nl){ print("%s: ", s); if(t == T){ print("nil"); if(nl) print("\n"); return; } while(t != T){ print("%d(%d)[%x] ", t->etype, t->mark, (int)t); if(isadt(t)) break; t = t->link; } if(nl) print("\n");} static Node*func(Node *n){ while(n != Z && n->op != OFUNC) n = n->left; return n;} static voidsetmain(Node *n){ inmain |= n->left->op == ONAME && strcmp(n->left->sym->name, "main") == 0;} static Node*protoname(Node *n){ do n = n->left; while(n != Z && n->op != ONAME && n->op != ODOTDOT); return n;} static Type*prototype(Node *n, Type *t){ for( ; n != Z ; n = n->left){ switch(n->op){ case OARRAY: t = typ(TARRAY, t); t->width = 0; break; case OIND: t = typ(TIND, t); break; case OFUNC: t = typ(TFUNC, t); t->down = fnproto(n); break; } } return t;} static Scope *scopes, *freescopes; static voidpushdcl(Node *n, int c){ Sym *s; if(passes){ s = n->sym; push1(s); if(c != CAUTO || s->class != CSTATIC) s->class = c; s->type = n->type; }} static voidpushparams(Node *n){ if(n == Z) return; if(passes){ if(n->op == OLIST){ pushparams(n->left); pushparams(n->right); } else if(n->op == OPROTO){ n = protoname(n); if(n != Z && n->op == ONAME) pushdcl(n, CPARAM); } else if(n->op == ONAME){ addnode(OPROTO, n); pushdcl(n, CPARAM); } else if(n->op != ODOTDOT) diag(Z, "bad op in pushparams"); }} static voidpushscope(Node *n, int k){ Scope *s; if(freescopes != nil){ s = freescopes; freescopes = freescopes->nxt; } else s = (Scope*)malloc(sizeof(Scope)); s->n = n; s->k = k; s->nxt = scopes; scopes = s; if(passes && (k == SPARM || k == SAUTO)) markdcl(); if(k == SPARM) pushparams(n->right);} static voidpopscope(void){ int k; Scope *s; s = scopes; k = s->k; scopes = scopes->nxt; s->nxt = freescopes; freescopes = s; if(passes && (k == SPARM || k == SAUTO)) revertdcl();} static Node*curfn(void){ Scope *s; for(s = scopes; s != nil; s = s->nxt) if(s->k == SPARM) return s->n; return Z;} static voidmarktype(Type *t, int tc){ t->mark = tc;} static intmarked(Type *t){ return t == T ? 0 : t->mark;} static Sym*decsym(Node *n){ if(n == Z) return S; if(n->op == OFUNC){ if(n->left->op == ONAME) return n->left->sym; return S; } if(n->op == ODAS) return n->left->sym; return n->sym;} static voidtrep(Type *t1, Type *t){ int l; Sym *s; Type *t2; if(t1 != T){ l = t1->lineno; s = t1->sym; t2 = t1->down; *t1 = *t; t1->down = t2; t1->sym = s; t1->lineno = l; }} static voidtind(Node *n){ if(n == Z) return; n = protoname(n); if(n != Z && n->type != T){ n->type = tcp(n->type->link); marktype(n->type, TCIN); }} static voidtcon(Node *n, Type *t){ Type *tt; if(n->garb) return; n->garb = 1; again = 1; switch(n->op){ case OCONST: if(t->mark == TCFD && !isnil(n)) addnode(OFILDES, n); n->type = t; break; case OCAST: tcon(n->left, t); *n = *n->left; n->type = t; break; case ONAME: n->sym->type = t; n->type = t; setdec(n->sym, t); break; case ODOT: case ODOTIND: trep(n->type, t); n->type = t; break; case OARRIND: tt = n->left->type; if(tt != T) tt->link = t; n->type = t; break; case OFUNC: n->left->type->link = t; if(n->left->op == ONAME) n->left->sym->type->link = t; n->type = t; break; }} static Node*retval(Node *n){ int i; Type *t; Node *a, *l, *cf; cf = curfn(); t = cf->left->type->link; if(t->mark&(TCPC|TCFC) && (n == Z || !(n->type->mark&(TCPC|TCFC)))){ if(n == Z) n = new1(ORETURN, Z, Z); l = n->left; for(i = 0; ; i++){ a = arg(cf->right, i); if(a == Z) break; a = protoname(a); if(a == Z || a->op != ONAME) break; if(a->type->mark == TCIN){ if(l == Z) l = ncopy(a); else l = new1(OTUPLE, l, ncopy(a)); } } n->left = l; n->type = l->type = t; } return n;} static voidsube(Node *n){ Node *l, *r, *nn; Type *tt; static Node *gn; int p; if(n == Z) return; l = n->left; r = n->right; switch(n->op){ default: sube(l); sube(r); break; case OIND: if(l == Z) return; tt = l->type; sube(l); if(cktype(l, n, TCIN, 0) && iteq(tt, l->type)) *n = *n->left; break; case OARRIND: tt = l->type; sube(l); sube(r); if(!isconst(r, 0)) break; if(cktype(l, n, TCIN, 0) && iteq(tt, l->type)) *n = *n->left; break; case ONAME: if(cktype(n, n, TCALL, 0)) setdec(n->sym, n->type); break; case OCAST: sube(l); if(cktype(l, n, TCALL, 0)) n->type = l->type; break; case OPROTO: sube(l); sube(r); nn = protoname(n); if(nn != Z && cktype(nn, n, TCALL, 0)){ n->type = nn->type; p = argpos(n, gn->right); for(tt = gn->left->type->down; tt != T && p >= 0; tt = tt->down){ if(p == 0){ trep(tt, nn->type); break; } --p; } } break; case OFUNC: if(n->kind == KEXP) aargs(n); if(n->left->op == ONAME) gn = n; sube(l); sube(r); if(l != Z && cktype(n, n, TCGEN, 0)) l->type->link = n->type; break; case OAS: sube(l); sube(r); if(r->op == ORETV){ n->left = new1(OTUPLE, l, r->right); n->right = r->left; n->left->type = n->type; break; } if(cktype(r, n, TCGEN, 0)){ tcon(l, r->type); n->type = r->type; } if(cktype(l, n, TCGEN, 1)){ tcon(r, l->type); n->type = l->type; } break; case OLT: case OGE: sube(l); sube(r); if(cktype(l, n, TCFD, 0) && isconst(r, 0)){ n->op = n->op == OLT ? OEQ : ONE;Lines 1–500 of 5115. Load more
#define EXTERN #include "cc.h" /* * locals, parameters, globals etc of the same name should work ok without having * to duplicate Syms because the details are on the containing Nodes */ #define SZ_CHAR 1 #define SZ_SHORT 2 #define SZ_INT 4 #define SZ_LONG 4 #define SZ_FLOAT 4 #define SZ_IND 4 #define SZ_VLONG 8 #define SZ_DOUBLE 8 char buf[128], mbuf[128]; static Sym *sysop, *bioop, *libcop; static int again; #define STAR 0x80 #define RET 0x80 #define LARR (-1729) static void swalk(void); static int isdec(Node*); static int isconst(Node*, vlong); static int cktype(Node*, Node*, int, int); static void addnode(int, Node*); static int argpos(Node*, Node*); static void setdec(Sym*, Type*); static Type* tcp(Type*); static int isadt(Type*); static void aargs(Node*); static int iteq(Type*, Type*); static Node* arg(Node*, int); static void etgen2(Sym*); static Node* ckneg(Node*); static Sym* suename(Type*); static int isnil(Node*); static void sliceasgn(Node*); static Node* lastn(Node*); static char* hasm(void); static void prn(Node*, int); static int isfn(Type*); schar ewidth[NTYPE] = { -1, /* [TXXX] */ SZ_CHAR, /* [TCHAR] */ SZ_CHAR, /* [TUCHAR] */ SZ_SHORT, /* [TSHORT] */ SZ_SHORT, /* [TUSHORT] */ SZ_INT, /* [TINT] */ SZ_INT, /* [TUINT] */ SZ_LONG, /* [TLONG] */ SZ_LONG, /* [TULONG] */ SZ_VLONG, /* [TVLONG] */ SZ_VLONG, /* [TUVLONG] */ SZ_FLOAT, /* [TFLOAT] */ SZ_DOUBLE, /* [TDOUBLE] */ SZ_IND, /* [TIND] */ 0, /* [TFUNC] */ -1, /* [TARRAY] */ 0, /* [TVOID] */ -1, /* [TSTRUCT] */ -1, /* [TUNION] */ SZ_INT, /* [TENUM] */ }; long ncast[NTYPE] = { 0, /* [TXXX] */ BCHAR|BUCHAR, /* [TCHAR] */ BCHAR|BUCHAR, /* [TUCHAR] */ BSHORT|BUSHORT, /* [TSHORT] */ BSHORT|BUSHORT, /* [TUSHORT] */ BINT|BUINT|BLONG|BULONG|BIND, /* [TINT] */ BINT|BUINT|BLONG|BULONG|BIND, /* [TUINT] */ BINT|BUINT|BLONG|BULONG|BIND, /* [TLONG] */ BINT|BUINT|BLONG|BULONG|BIND, /* [TULONG] */ BVLONG|BUVLONG, /* [TVLONG] */ BVLONG|BUVLONG, /* [TUVLONG] */ BFLOAT, /* [TFLOAT] */ BDOUBLE, /* [TDOUBLE] */ BLONG|BULONG|BIND, /* [TIND] */ 0, /* [TFUNC] */ 0, /* [TARRAY] */ 0, /* [TVOID] */ BSTRUCT, /* [TSTRUCT] */ BUNION, /* [TUNION] */ 0, /* [TENUM] */ }; enum{ TCFD = 1, TCFC = 2, TCPC = 4, TCAR = 8, TCIN = 16, TCGEN = TCFD|TCFC|TCPC|TCAR, TCALL = TCFD|TCFC|TCPC|TCAR|TCIN, }; enum{ SGLOB, SPARM, SAUTO, }; typedef struct Scope Scope; struct Scope{ Node *n; int k; Scope *nxt; }; static void prtyp(Type *t, char *s, int nl) { print("%s: ", s); if(t == T){ print("nil"); if(nl) print("\n"); return; } while(t != T){ print("%d(%d)[%x] ", t->etype, t->mark, (int)t); if(isadt(t)) break; t = t->link; } if(nl) print("\n"); } static Node* func(Node *n) { while(n != Z && n->op != OFUNC) n = n->left; return n; } static void setmain(Node *n) { inmain |= n->left->op == ONAME && strcmp(n->left->sym->name, "main") == 0; } static Node* protoname(Node *n) { do n = n->left; while(n != Z && n->op != ONAME && n->op != ODOTDOT); return n; } static Type* prototype(Node *n, Type *t) { for( ; n != Z ; n = n->left){ switch(n->op){ case OARRAY: t = typ(TARRAY, t); t->width = 0; break; case OIND: t = typ(TIND, t); break; case OFUNC: t = typ(TFUNC, t); t->down = fnproto(n); break; } } return t; } static Scope *scopes, *freescopes; static void pushdcl(Node *n, int c) { Sym *s; if(passes){ s = n->sym; push1(s); if(c != CAUTO || s->class != CSTATIC) s->class = c; s->type = n->type; } } static void pushparams(Node *n) { if(n == Z) return; if(passes){ if(n->op == OLIST){ pushparams(n->left); pushparams(n->right); } else if(n->op == OPROTO){ n = protoname(n); if(n != Z && n->op == ONAME) pushdcl(n, CPARAM); } else if(n->op == ONAME){ addnode(OPROTO, n); pushdcl(n, CPARAM); } else if(n->op != ODOTDOT) diag(Z, "bad op in pushparams"); } } static void pushscope(Node *n, int k) { Scope *s; if(freescopes != nil){ s = freescopes; freescopes = freescopes->nxt; } else s = (Scope*)malloc(sizeof(Scope)); s->n = n; s->k = k; s->nxt = scopes; scopes = s; if(passes && (k == SPARM || k == SAUTO)) markdcl(); if(k == SPARM) pushparams(n->right); } static void popscope(void) { int k; Scope *s; s = scopes; k = s->k; scopes = scopes->nxt; s->nxt = freescopes; freescopes = s; if(passes && (k == SPARM || k == SAUTO)) revertdcl(); } static Node* curfn(void) { Scope *s; for(s = scopes; s != nil; s = s->nxt) if(s->k == SPARM) return s->n; return Z; } static void marktype(Type *t, int tc) { t->mark = tc; } static int marked(Type *t) { return t == T ? 0 : t->mark; } static Sym* decsym(Node *n) { if(n == Z) return S; if(n->op == OFUNC){ if(n->left->op == ONAME) return n->left->sym; return S; } if(n->op == ODAS) return n->left->sym; return n->sym; } static void trep(Type *t1, Type *t) { int l; Sym *s; Type *t2; if(t1 != T){ l = t1->lineno; s = t1->sym; t2 = t1->down; *t1 = *t; t1->down = t2; t1->sym = s; t1->lineno = l; } } static void tind(Node *n) { if(n == Z) return; n = protoname(n); if(n != Z && n->type != T){ n->type = tcp(n->type->link); marktype(n->type, TCIN); } } static void tcon(Node *n, Type *t) { Type *tt; if(n->garb) return; n->garb = 1; again = 1; switch(n->op){ case OCONST: if(t->mark == TCFD && !isnil(n)) addnode(OFILDES, n); n->type = t; break; case OCAST: tcon(n->left, t); *n = *n->left; n->type = t; break; case ONAME: n->sym->type = t; n->type = t; setdec(n->sym, t); break; case ODOT: case ODOTIND: trep(n->type, t); n->type = t; break; case OARRIND: tt = n->left->type; if(tt != T) tt->link = t; n->type = t; break; case OFUNC: n->left->type->link = t; if(n->left->op == ONAME) n->left->sym->type->link = t; n->type = t; break; } } static Node* retval(Node *n) { int i; Type *t; Node *a, *l, *cf; cf = curfn(); t = cf->left->type->link; if(t->mark&(TCPC|TCFC) && (n == Z || !(n->type->mark&(TCPC|TCFC)))){ if(n == Z) n = new1(ORETURN, Z, Z); l = n->left; for(i = 0; ; i++){ a = arg(cf->right, i); if(a == Z) break; a = protoname(a); if(a == Z || a->op != ONAME) break; if(a->type->mark == TCIN){ if(l == Z) l = ncopy(a); else l = new1(OTUPLE, l, ncopy(a)); } } n->left = l; n->type = l->type = t; } return n; } static void sube(Node *n) { Node *l, *r, *nn; Type *tt; static Node *gn; int p; if(n == Z) return; l = n->left; r = n->right; switch(n->op){ default: sube(l); sube(r); break; case OIND: if(l == Z) return; tt = l->type; sube(l); if(cktype(l, n, TCIN, 0) && iteq(tt, l->type)) *n = *n->left; break; case OARRIND: tt = l->type; sube(l); sube(r); if(!isconst(r, 0)) break; if(cktype(l, n, TCIN, 0) && iteq(tt, l->type)) *n = *n->left; break; case ONAME: if(cktype(n, n, TCALL, 0)) setdec(n->sym, n->type); break; case OCAST: sube(l); if(cktype(l, n, TCALL, 0)) n->type = l->type; break; case OPROTO: sube(l); sube(r); nn = protoname(n); if(nn != Z && cktype(nn, n, TCALL, 0)){ n->type = nn->type; p = argpos(n, gn->right); for(tt = gn->left->type->down; tt != T && p >= 0; tt = tt->down){ if(p == 0){ trep(tt, nn->type); break; } --p; } } break; case OFUNC: if(n->kind == KEXP) aargs(n); if(n->left->op == ONAME) gn = n; sube(l); sube(r); if(l != Z && cktype(n, n, TCGEN, 0)) l->type->link = n->type; break; case OAS: sube(l); sube(r); if(r->op == ORETV){ n->left = new1(OTUPLE, l, r->right); n->right = r->left; n->left->type = n->type; break; } if(cktype(r, n, TCGEN, 0)){ tcon(l, r->type); n->type = r->type; } if(cktype(l, n, TCGEN, 1)){ tcon(r, l->type); n->type = l->type; } break; case OLT: case OGE: sube(l); sube(r); if(cktype(l, n, TCFD, 0) && isconst(r, 0)){ n->op = n->op == OLT ? OEQ : ONE;