cgen.c - scc - simple c99 compiler
 (HTM) git clone git://git.simple-cc.org/scc
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
 (DIR) README
 (DIR) LICENSE
       ---
       cgen.c (7571B)
       ---
            1 #include <stdlib.h>
            2 #include <string.h>
            3 
            4 #include <scc/scc.h>
            5 
            6 #include "../cc2.h"
            7 #include "arch.h"
            8 
            9 #define NLOCALS 16
           10 
           11 struct local {
           12         Symbol *sym;
           13         struct local *next;
           14 };
           15 
           16 static Symbol *retlabel;
           17 static int offpar, offvar;
           18 
           19 static Node *reguse[NPAIRS];
           20 static int upper[] = {[DE] = D, [HL] = H, [BC] = B,  [IY] = IYH};
           21 static int lower[] = {[DE] = E, [HL] = L, [BC] = C, [IY] = IYL};
           22 static int pair[] = {
           23         [A] = A,
           24         [H] = HL, [L] = HL, [HL] = HL,
           25         [B] = BC, [C] = BC, [BC] = BC,
           26         [D] = DE, [E] = DE, [DE] = DE,
           27         [IYL] = IY, [IYH] = IY, [IY] = IY
           28 };
           29 
           30 static Node regs[] = {
           31         [E] =  {
           32                 .op = OMREG,
           33                 .type.size = 1,
           34                 .u.reg = E
           35         },
           36         [D] = {
           37                 .op = OMREG,
           38                 .type.size = 1,
           39                 .u.reg = D
           40         },
           41         [H] = {
           42                 .op = OMREG,
           43                 .type.size = 1,
           44                 .u.reg = H
           45         },
           46         [L] = {
           47                 .op = OMREG,
           48                 .type.size = 1,
           49                 .u.reg = L
           50         },
           51         [C] = {
           52                 .op= OMREG,
           53                 .type.size = 1,
           54                 .u.reg = C
           55         },
           56         [B] = {
           57                 .op= OMREG,
           58                 .type.size = 1,
           59                 .u.reg = B
           60         },
           61         [A] = {
           62                 .op= OMREG,
           63                 .type.size = 1,
           64                 .u.reg = A
           65         },
           66         [IYL] = {
           67                 .op = OMREG,
           68                 .type.size = 1,
           69                 .u.reg = IYL
           70         },
           71         [IYH] = {
           72                 .op = OMREG,
           73                 .type.size = 1,
           74                 .u.reg = IYH
           75         },
           76         [DE] = {
           77                 .op = OMREG,
           78                 .type.size = 2,
           79                 .u.reg = DE
           80         },
           81         [HL] = {
           82                 .op = OMREG,
           83                 .type.size = 2,
           84                 .u.reg = HL
           85         },
           86         [BC] = {
           87                 .op = OMREG,
           88                 .type.size = 2,
           89                 .u.reg = BC
           90         },
           91         [IX] = {
           92                 .op = OMREG,
           93                 .type.size = 2,
           94                 .u.reg = IX
           95         },
           96         [IY] = {
           97                 .op = OMREG,
           98                 .type.size = 2,
           99                 .u.reg = IY
          100         },
          101         [SP] = {
          102                 .op = OMREG,
          103                 .type.size = 2,
          104                 .u.reg = SP
          105         }
          106 };
          107 
          108 void
          109 defpar(Symbol *sym)
          110 {
          111         unsigned align, size;
          112 
          113         if (sym->kind != SREG && sym->kind != SAUTO)
          114                 return;
          115         align = sym->type.align;
          116         size = sym->type.size;
          117 
          118         if (offpar == 0)
          119                 offpar = +2;
          120 
          121         sym->u.off = offpar;
          122         offpar += size;
          123         offpar += offpar & 1;
          124 }
          125 
          126 void
          127 defvar(Symbol *sym)
          128 {
          129         unsigned long align, size;
          130 
          131         if (sym->kind != SREG && sym->kind != SAUTO)
          132                 return;
          133         align = sym->type.align;
          134         size = sym->type.size;
          135 
          136         if (offvar == 0)
          137                 offvar = -2;
          138 
          139         sym->u.off = offvar;
          140         offvar -= size;
          141         offvar -= offpar & 1;
          142 }
          143 
          144 static Node *
          145 function(void)
          146 {
          147         Node aux;
          148 
          149         memset(reguse, 0, sizeof(reguse));
          150 
          151         retlabel = newlabel();
          152 
          153         code(ASPUSH, NULL, &regs[IX], NULL);
          154         code(ASMOV, &regs[IX], &regs[SP], NULL);
          155 
          156         constnode(&aux, offvar + 2, &ptrtype);
          157         code(ASMOV, &regs[HL], &aux, NULL);
          158         code(ASADD, &regs[HL], &regs[SP], &regs[HL]);
          159         code(ASMOV, &regs[SP], &regs[HL], NULL);
          160 }
          161 
          162 static void
          163 efunction(void)
          164 {
          165         setlabel(retlabel);
          166         code(ASMOV, &regs[SP], &regs[IX], NULL);
          167         code(ASPOP, &regs[IX], NULL, NULL);
          168         code(ASRET, NULL, NULL, NULL);
          169         offpar = offvar = 0;
          170 }
          171 
          172 static void
          173 allocreg(Node *np)
          174 {
          175 }
          176 
          177 static void
          178 store(Node *np)
          179 {
          180 }
          181 
          182 static void
          183 load(Node *np)
          184 {
          185 }
          186 
          187 static void
          188 spill(int reg)
          189 {
          190         Node *np, *r;
          191         Symbol *sym;
          192         int p, h, l;
          193 
          194         if ((np = reguse[reg]) == NULL)
          195                 return;
          196         r = &regs[reg];
          197 
          198         store(r);
          199         p = pair[reg];
          200         l = lower[p];
          201         h = upper[p];
          202 
          203         if (reg >= NREGS)
          204                 reguse[l] = reguse[h] = NULL;
          205         else
          206                 reguse[reg] = NULL;
          207 
          208         if (!reguse[l] && !reguse[h])
          209                 reguse[p] = NULL;
          210 }
          211 
          212 static void
          213 use(int reg, Node *np)
          214 {
          215         reguse[reg] = np;
          216 
          217         if (reg < NREGS) {
          218                 reguse[pair[reg]] = np;
          219         } else if (reg >= NREGS && reg < NPAIRS) {
          220                 reguse[lower[reg]] = np;
          221                 reguse[upper[reg]] = np;
          222         } else {
          223                 abort();
          224         }
          225 }
          226 
          227 static void
          228 load2(Node *np, int dst)
          229 {
          230         long offl, offh;
          231         Node low, high;
          232 
          233         switch (np->op) {
          234         case OAUTO:
          235                 offl = np->u.sym->u.off - 1;
          236                 offh = offl + 1;
          237                 break;
          238         default:
          239                 abort();
          240         }
          241 
          242         code(ASLD, &regs[lower[dst]], idxnode(&low, offl), NULL);
          243         code(ASLD, &regs[upper[dst]], idxnode(&high, offh), NULL);
          244         use(dst, np);
          245 }
          246 
          247 static void
          248 moveto1(Node *np, int dst)
          249 {
          250         int src;
          251         Node *pdst = &regs[dst];
          252 
          253         switch (np->op) {
          254         case OAUTO:
          255                 code(ASLD, pdst, np, NULL);
          256                 break;
          257         case OMREG:
          258                 src = np->u.reg;
          259                 if (src == dst)
          260                         return;
          261 
          262                 code(ASMOV, pdst, &regs[np->u.reg], NULL);
          263                 break;
          264         default:
          265                 abort();
          266         }
          267 
          268         use(dst, np);
          269 }
          270 
          271 static void
          272 moveto2(Node *np, int dst)
          273 {
          274         int src;
          275         Node aux;
          276 
          277         switch (np->op) {
          278         case OAUTO:
          279                 load2(np, dst);
          280                 break;
          281         case OMREG:
          282                 src = np->u.reg;
          283                 if (src == dst)
          284                         return;
          285 
          286                 if (src == HL && dst == DE || src == DE && dst == HL) {
          287                         code(ASEXHL, &regs[HL], &regs[HL], &regs[DE]);
          288                         use(src, reguse[dst]);
          289                 } else {
          290                         code(ASMOV, &regs[lower[dst]], &regs[lower[src]], NULL);
          291                         code(ASMOV, &regs[upper[dst]], &regs[upper[src]], NULL);
          292                 }
          293                 break;
          294         default:
          295                 abort();
          296         }
          297 
          298         use(dst, np);
          299 }
          300 
          301 static void
          302 moveto4(Node *np, int dst)
          303 {
          304         abort();
          305 }
          306 
          307 static void
          308 moveto8(Node *np, int dst)
          309 {
          310         abort();
          311 }
          312 
          313 static void
          314 moveto(Node *np, int reg)
          315 {
          316         switch (np->type.size) {
          317         case 1:
          318                 moveto1(np, reg);
          319                 break;
          320         case 2:
          321                 moveto2(np, reg);
          322                 break;
          323         case 4:
          324                 moveto4(np, reg);
          325                 break;
          326         case 8:
          327                 moveto4(np, reg);
          328                 break;
          329         default:
          330                 abort();
          331         }
          332 }
          333 
          334 static int
          335 cmpnode(Node *n1, Node *n2)
          336 {
          337         if (n1 == n2)
          338                 return 1;
          339         if (!n1 || !n2)
          340                 return 0;
          341         if (n1->op != n2->op)
          342                 return 0;
          343 
          344         switch (n1->op) {
          345         case OAUTO:
          346                 return n1->u.sym == n2->u.sym;
          347         default:
          348                 return 0;
          349         }
          350 }
          351 
          352 static void
          353 move(Node *np, int reg)
          354 {
          355         int i;
          356 
          357         switch (np->type.size) {
          358         case 1:
          359                 for (i = A; i < NREGS; ++i) {
          360                         if (cmpnode(reguse[i], np))
          361                                 goto found;
          362                 }
          363                 break;
          364         case 2:
          365                 for (i = AF; i < NPAIRS; ++i) {
          366                         if (cmpnode(reguse[i], np))
          367                                 goto found;
          368                 }
          369                 break;
          370         case 4:
          371                 abort();
          372         case 8:
          373                 abort();
          374         }
          375 
          376         moveto(np, reg);
          377         return;
          378 
          379 found:
          380         moveto(&regs[i], reg);
          381 }
          382 
          383 static int
          384 whatacc(Node *np)
          385 {
          386         switch (np->type.size) {
          387         case 1:
          388                 return A;
          389         case 2:
          390                 return HL;
          391         case 4:
          392                 return HLDE;
          393         case 8:
          394                 return EXHLDE;
          395         default:
          396                 abort();
          397         }
          398 }
          399 
          400 static Node *
          401 acc(Node *np)
          402 {
          403         int reg = whatacc(np);
          404         move(np, reg);
          405         return &regs[reg];
          406 }
          407 
          408 static Node *
          409 rhs(Node *np)
          410 {
          411         switch (np->op) {
          412         case OAUTO:
          413                 return acc(np);
          414         case OMEM:
          415         case OSNEG:
          416         case OTMP:
          417         case OCONST:
          418         case OREG:
          419         case OMOD:
          420         case OSHL:
          421         case OBAND:
          422         case OBOR:
          423         case OBXOR:
          424         case OSHR:
          425         case ODIV:
          426         case OLT:
          427         case OGT:
          428         case OLE:
          429         case OGE:
          430         case OADD:
          431         case OSUB:
          432         case OMUL:
          433         case OEQ:
          434         case ONE:
          435         case OCALL:
          436         case OCALLE:
          437         case OCAST:
          438         case OASSIG:
          439         case OASK:
          440         case OCOMMA:
          441         case OPTR:
          442         case OADDR:
          443         case OFIELD:
          444         case OBUILTIN:
          445         default:
          446                 abort();
          447         }
          448 }
          449 
          450 static Node *
          451 field(Node *np, int islhs)
          452 {
          453 }
          454 
          455 static Node *
          456 lhs(Node *np)
          457 {
          458         switch (np->op) {
          459         case OMEM:
          460         case OAUTO:
          461                 return np;
          462         case OPTR:
          463                 return rhs(np->left);
          464         case OFIELD:
          465                 return field(np, 1);
          466         default:
          467                 abort();
          468         }
          469 }
          470 
          471 static void
          472 ret(Node *np)
          473 {
          474         Node aux;
          475 
          476         if (np->left)
          477                 acc(np->left);
          478         label2node(&aux, retlabel);
          479         code(ASJP, NULL, &aux, NULL);
          480 }
          481 
          482 static Node *
          483 cgen(Node *np)
          484 {
          485         Node aux, *next;
          486 
          487         setlabel(np->label);
          488         switch (np->op) {
          489         case OBFUN:
          490                 function();
          491                 break;
          492         case OEFUN:
          493                 efunction();
          494                 break;
          495         case ONOP:
          496         case OBLOOP:
          497         case OELOOP:
          498                 break;
          499         case OJMP:
          500                 label2node(&aux, np->u.sym);
          501                 code(ASJP, NULL, &aux, NULL);
          502                 break;
          503         case OBRANCH:
          504                 /* TODO */
          505                 break;
          506         case ORET:
          507                 ret(np);
          508                 break;
          509         case OBSWITCH:
          510                 /* TODO */
          511                 break;
          512         default:
          513                 rhs(np);
          514                 break;
          515         }
          516         return np;
          517 }
          518 
          519 /*
          520  * This is strongly influenced by
          521  * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps)
          522  * calculate addresability as follows
          523  *     AUTO => 11          value+fp
          524  *     REG => 13           reg
          525  *     STATIC => 12        (value)
          526  *     CONST => 20         $value
          527  */
          528 Node *
          529 tsethi(Node *np)
          530 {
          531         Node *l, *r;
          532 
          533         l = np->left;
          534         r = np->right;
          535         switch (np->op) {
          536         case OAUTO:
          537                 np->address = 11;
          538                 break;
          539         case OREG:
          540                 np->address = 13;
          541                 break;
          542         case OMEM:
          543                 np->address = 12;
          544                 break;
          545         case OCONST:
          546                 np->address = 20;
          547                 break;
          548         default:
          549                 l = sethi(l);
          550                 r = sethi(r);
          551                 break;
          552         }
          553 
          554         np->left = l;
          555         np->right = r;
          556 
          557         return np;
          558 }
          559 
          560 void
          561 genasm(void)
          562 {
          563         apply(cgen);
          564 }