swtch.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
       ---
       swtch.c (2125B)
       ---
            1 #include <limits.h>
            2 #include <stdlib.h>
            3 
            4 #include <scc/scc.h>
            5 
            6 #include "cc2.h"
            7 
            8 static Swtch *list = NULL;
            9 
           10 static Node *
           11 swtch_if(Node *np)
           12 {
           13         Type *tp;
           14         Swtch *swt;
           15         Node **cases, **bp, *tmpvar, *p;
           16 
           17         swt = np->u.swtch;
           18         tp = &np->left->type;
           19 
           20         tmpvar = tmpnode(tp, NULL);
           21         np->type = *tp;
           22         np->right = np->left;
           23         np->left = tmpvar;
           24         np->op = OASSIG;
           25         np->u.subop = 0;
           26 
           27         cases = swt->cases;
           28         for (bp = cases; bp < &cases[swt->nr]; ++bp) {
           29                 Node *eq, *tmp = tmpnode(tp, tmpvar->u.sym);
           30 
           31                 p = *bp;
           32                 eq = node(OEQ);
           33                 eq->type = *tp;
           34                 eq->left = p->left;
           35                 eq->right = tmp;
           36                 *bp = NULL;
           37 
           38                 p->left = eq;
           39                 p->op = OBRANCH;
           40                 addstmt(p);
           41         }
           42         p = swtchdefault(swt);
           43         p->op = OJMP;
           44         addstmt(p);
           45 
           46         free(cases);
           47         swt->cases = NULL;
           48 
           49         return sethi(np);
           50 }
           51 
           52 static Node *
           53 swtch_dir(Node *np, TINT min, TINT max)
           54 {
           55         int i;
           56         TINT cur, nval;
           57         Swtch *swt;
           58         Symbol *tbl;
           59         Node *p, *def, **cases;
           60 
           61         tbl = getsym(TMPSYM);
           62         tbl->kind = SLOCAL;
           63         tbl->type = ptrtype;
           64         tbl->type.flags |= INITF;
           65         defglobal(tbl);
           66 
           67         swt = np->u.swtch;
           68         cases = swt->cases;
           69 
           70         def = swtchdefault(swt);
           71         def->type = ptrtype;
           72         def->op = OLABEL;
           73 
           74         i = 0;
           75         p = NULL;
           76         for (cur = min; cur <= max; ++cur) {
           77                 if (!p && i < swt->nr) {
           78                         p = cases[i++];
           79                         p->type = ptrtype;
           80                         p->op = OLABEL;
           81                         nval = p->left->u.i;
           82                 }
           83                 if (p && nval == cur) {
           84                         data(p);
           85                         p = NULL;
           86                 } else {
           87                         data(def);
           88                 }
           89         }
           90         endinit();
           91 
           92         return np;
           93 }
           94 
           95 Node *
           96 swtch(Node *np)
           97 {
           98         Swtch *swt;
           99         int n;
          100         TINT min, max, range;
          101 
          102         swt = np->u.swtch;
          103         min = swt->min;
          104         max = swt->max;
          105         range = max - min + 1;
          106         n = swt->nr;
          107 
          108         if (n < mach.swtchif)
          109                 return swtch_if(np);
          110         return swtch_dir(np, min, max);
          111 }
          112 
          113 Node *
          114 swtchdefault(Swtch *swt)
          115 {
          116         Node *np;
          117 
          118         np = swt->defnode;
          119         if (!np)
          120                 np = swt->eswtch;
          121         return np;
          122 }
          123 
          124 Swtch *
          125 newswtch(Swtch *swt)
          126 {
          127         Swtch *p = xmalloc(sizeof(*p));
          128 
          129         *p = *swt;
          130         p->next = list;
          131         return list = p;
          132 }
          133 
          134 void
          135 cleanswtch(void)
          136 {
          137         Swtch *p, *next;
          138         Node **bp, **cases;
          139 
          140         for (p = list; p; p = next) {
          141                 next = p->next;
          142                 cases = p->cases;
          143                 if (cases) {
          144                         for (bp = cases; bp < &cases[p->nr]; ++p)
          145                                 deltree(*bp);
          146                         free(cases);
          147                 }
          148                 free(p);
          149         }
          150         list = NULL;
          151 }