cgen.c
来自「这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易」· C语言 代码 · 共 1,165 行 · 第 1/2 页
C
1,165 行
regind(t, n); return; } } else if(n->op == OINDREG) { if((v = n->xoffset) > -4096 && v < 4096) { n->op = OREGISTER; cgen(n, t); t->xoffset += v; n->op = OINDREG; regind(t, n); return; } } lcgen(n, t); regind(t, n);}voidreglpcgen(Node *n, Node *nn, int f){ Type *t; t = nn->type; nn->type = types[TLONG]; if(f) reglcgen(n, nn, Z); else { regialloc(n, nn, Z); lcgen(nn, n); regind(n, nn); } nn->type = t;}voidlcgen(Node *n, Node *nn){ Prog *p1; Node nod; if(debug['g']) { prtree(nn, "lcgen lhs"); prtree(n, "lcgen"); } if(n == Z || n->type == T) return; if(nn == Z) { nn = &nod; regalloc(&nod, n, Z); } switch(n->op) { default: if(n->addable < INDEXED) { diag(n, "unknown op in lcgen: %O", n->op); break; } nod = *n; nod.op = OADDR; nod.left = n; nod.right = Z; nod.type = types[TIND]; gopcode(OAS, &nod, Z, nn); break; case OCOMMA: cgen(n->left, n->left); lcgen(n->right, nn); break; case OIND: cgen(n->left, nn); break; case OCOND: bcgen(n->left, 1); p1 = p; lcgen(n->right->left, nn); gbranch(OGOTO); patch(p1, pc); p1 = p; lcgen(n->right->right, nn); patch(p1, pc); break; }}voidbcgen(Node *n, int true){ if(n->type == T) gbranch(OGOTO); else boolgen(n, true, Z);}voidboolgen(Node *n, int true, Node *nn){ int o; Prog *p1, *p2; Node *l, *r, nod, nod1; long curs; if(debug['g']) { prtree(nn, "boolgen lhs"); prtree(n, "boolgen"); } curs = cursafe; l = n->left; r = n->right; switch(n->op) { default: regalloc(&nod, n, nn); cgen(n, &nod); o = ONE; if(true) o = comrel[relindex(o)]; if(typefd[n->type->etype]) { gopcode(o, nodfconst(0), &nod, Z); } else gopcode(o, nodconst(0), &nod, Z); regfree(&nod); goto com; case OCONST: o = vconst(n); if(!true) o = !o; gbranch(OGOTO); if(o) { p1 = p; gbranch(OGOTO); patch(p1, pc); } goto com; case OCOMMA: cgen(l, Z); boolgen(r, true, nn); break; case ONOT: boolgen(l, !true, nn); break; case OCOND: bcgen(l, 1); p1 = p; bcgen(r->left, true); p2 = p; gbranch(OGOTO); patch(p1, pc); p1 = p; bcgen(r->right, !true); patch(p2, pc); p2 = p; gbranch(OGOTO); patch(p1, pc); patch(p2, pc); goto com; case OANDAND: if(!true) goto caseor; caseand: bcgen(l, true); p1 = p; bcgen(r, !true); p2 = p; patch(p1, pc); gbranch(OGOTO); patch(p2, pc); goto com; case OOROR: if(!true) goto caseand; caseor: bcgen(l, !true); p1 = p; bcgen(r, !true); p2 = p; gbranch(OGOTO); patch(p1, pc); patch(p2, pc); goto com; case OEQ: case ONE: case OLE: case OLT: case OGE: case OGT: case OHI: case OHS: case OLO: case OLS: o = n->op; if(true) o = comrel[relindex(o)]; if(l->complex >= FNX && r->complex >= FNX) { regret(&nod, r); cgenrel(r, &nod, 1); regsalloc(&nod1, r); gopcode(OAS, &nod, Z, &nod1); regfree(&nod); nod = *n; nod.right = &nod1; boolgen(&nod, true, nn); break; } if(sconst(l)) { regalloc(&nod, r, nn); cgenrel(r, &nod, 1); o = invrel[relindex(o)]; gopcode(o, l, &nod, Z); regfree(&nod); goto com; } if(sconst(r)) { regalloc(&nod, l, nn); cgenrel(l, &nod, 1); gopcode(o, r, &nod, Z); regfree(&nod); goto com; } if(l->complex >= r->complex) { regalloc(&nod1, l, nn); cgenrel(l, &nod1, 1); regalloc(&nod, r, Z); cgenrel(r, &nod, 1); } else { regalloc(&nod, r, nn); cgenrel(r, &nod, 1); regalloc(&nod1, l, Z); cgenrel(l, &nod1, 1); } gopcode(o, &nod, &nod1, Z); regfree(&nod); regfree(&nod1); com: if(nn != Z) { p1 = p; gopcode(OAS, nodconst(1), Z, nn); gbranch(OGOTO); p2 = p; patch(p1, pc); gopcode(OAS, nodconst(0), Z, nn); patch(p2, pc); } break; } cursafe = curs;}voidsugen(Node *n, Node *nn, long w){ Prog *p1; Node nod0, nod1, nod2, nod3, nod4, *l, *r; Type *t; long pc1; int i, m, c; if(n == Z || n->type == T) return; if(debug['g']) { prtree(nn, "sugen lhs"); prtree(n, "sugen"); } if(nn == nodrat) if(w > nrathole) nrathole = w; switch(n->op) { case OIND: if(nn == Z) { nullwarn(n->left, Z); break; } default: goto copy; case OCONST: if(n->type && typev[n->type->etype]) { if(nn == Z) { nullwarn(n->left, Z); break; } t = nn->type; nn->type = types[TLONG]; reglcgen(&nod1, nn, Z); nn->type = t; if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); else gopcode(OAS, nod32const(n->vconst), Z, &nod1); nod1.xoffset += SZ_LONG; if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ gopcode(OAS, nod32const(n->vconst), Z, &nod1); else gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1); regfree(&nod1); break; } goto copy; case ODOT: l = n->left; sugen(l, nodrat, l->type->width); if(nn != Z) { warn(n, "non-interruptable temporary"); nod1 = *nodrat; r = n->right; if(!r || r->op != OCONST) { diag(n, "DOT and no offset"); break; } nod1.xoffset += (long)r->vconst; nod1.type = n->type; sugen(&nod1, nn, w); } break; case OSTRUCT: /* * rewrite so lhs has no fn call */ if(nn != Z && nn->complex >= FNX) { nod1 = *n; nod1.type = typ(TIND, n->type); regret(&nod2, &nod1); lcgen(nn, &nod2); regsalloc(&nod0, &nod1); gopcode(OAS, &nod2, Z, &nod0); regfree(&nod2); nod1 = *n; nod1.op = OIND; nod1.left = &nod0; nod1.right = Z; nod1.complex = 1; sugen(n, &nod1, w); return; } r = n->left; for(t = n->type->link; t != T; t = t->down) { l = r; if(r->op == OLIST) { l = r->left; r = r->right; } if(nn == Z) { cgen(l, nn); continue; } /* * hand craft *(&nn + o) = l */ nod0 = znode; nod0.op = OAS; nod0.type = t; nod0.left = &nod1; nod0.right = l; nod1 = znode; nod1.op = OIND; nod1.type = t; nod1.left = &nod2; nod2 = znode; nod2.op = OADD; nod2.type = typ(TIND, t); nod2.left = &nod3; nod2.right = &nod4; nod3 = znode; nod3.op = OADDR; nod3.type = nod2.type; nod3.left = nn; nod4 = znode; nod4.op = OCONST; nod4.type = nod2.type; nod4.vconst = t->offset; ccom(&nod0); acom(&nod0); xcom(&nod0); nod0.addable = 0; cgen(&nod0, Z); } break; case OAS: if(nn == Z) { if(n->addable < INDEXED) sugen(n->right, n->left, w); break; } sugen(n->right, nodrat, w); warn(n, "non-interruptable temporary"); sugen(nodrat, n->left, w); sugen(nodrat, nn, w); break; case OFUNC: if(nn == Z) { sugen(n, nodrat, w); break; } if(nn->op != OIND) { nn = new1(OADDR, nn, Z); nn->type = types[TIND]; nn->addable = 0; } else nn = nn->left; n = new(OFUNC, n->left, new(OLIST, nn, n->right)); n->type = types[TVOID]; n->left->type = types[TVOID]; cgen(n, Z); break; case OCOND: bcgen(n->left, 1); p1 = p; sugen(n->right->left, nn, w); gbranch(OGOTO); patch(p1, pc); p1 = p; sugen(n->right->right, nn, w); patch(p1, pc); break; case OCOMMA: cgen(n->left, Z); sugen(n->right, nn, w); break; } return;copy: if(nn == Z) return; if(n->complex >= FNX && nn->complex >= FNX) { t = nn->type; nn->type = types[TLONG]; regialloc(&nod1, nn, Z); lcgen(nn, &nod1); regsalloc(&nod2, nn); nn->type = t; gopcode(OAS, &nod1, Z, &nod2); regfree(&nod1); nod2.type = typ(TIND, t); nod1 = nod2; nod1.op = OIND; nod1.left = &nod2; nod1.right = Z; nod1.complex = 1; nod1.type = t; sugen(n, &nod1, w); return; } w /= SZ_LONG; if(w <= 2) { if(n->complex > nn->complex) { reglpcgen(&nod1, n, 1); reglpcgen(&nod2, nn, 1); } else { reglpcgen(&nod2, nn, 1); reglpcgen(&nod1, n, 1); } regalloc(&nod3, ®node, Z); regalloc(&nod4, ®node, Z); nod0 = *nodconst((1<<nod3.reg)|(1<<nod4.reg)); if(w == 2 && nod1.xoffset == 0) gmovm(&nod1, &nod0, 0); else { gmove(&nod1, &nod3); if(w == 2) { nod1.xoffset += SZ_LONG; gmove(&nod1, &nod4); } } if(w == 2 && nod2.xoffset == 0) gmovm(&nod0, &nod2, 0); else { gmove(&nod3, &nod2); if(w == 2) { nod2.xoffset += SZ_LONG; gmove(&nod4, &nod2); } } regfree(&nod1); regfree(&nod2); regfree(&nod3); regfree(&nod4); return; } if(n->complex > nn->complex) { reglpcgen(&nod1, n, 0); reglpcgen(&nod2, nn, 0); } else { reglpcgen(&nod2, nn, 0); reglpcgen(&nod1, n, 0); } m = 0; for(c = 0; c < w && c < 4; c++) { i = tmpreg(); if (i == 0) break; reg[i]++; m |= 1<<i; } nod4 = *(nodconst(m)); if(w < 3*c) { for (; w>c; w-=c) { gmovm(&nod1, &nod4, 1); gmovm(&nod4, &nod2, 1); } goto out; } regalloc(&nod3, ®node, Z); gopcode(OAS, nodconst(w/c), Z, &nod3); w %= c; pc1 = pc; gmovm(&nod1, &nod4, 1); gmovm(&nod4, &nod2, 1); gopcode(OSUB, nodconst(1), Z, &nod3); gopcode(OEQ, nodconst(0), &nod3, Z); p->as = ABGT; patch(p, pc1); regfree(&nod3);out: if (w) { i = 0; while (c>w) { while ((m&(1<<i)) == 0) i++; m &= ~(1<<i); reg[i] = 0; c--; i++; } nod4.vconst = m; gmovm(&nod1, &nod4, 0); gmovm(&nod4, &nod2, 0); } i = 0; do { while ((m&(1<<i)) == 0) i++; reg[i] = 0; c--; i++; } while (c>0); regfree(&nod1); regfree(&nod2);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?