sethi.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
       ---
       sethi.c (3599B)
       ---
            1 #include <scc/scc.h>
            2 
            3 #include "cc2.h"
            4 
            5 static Node *
            6 assignnode(Type *tp, Node *lhs, Node *rhs)
            7 {
            8         Node *np;
            9 
           10         np = node(OASSIG);
           11         np->type = *tp;
           12         np->left = lhs;
           13         np->right = rhs;
           14         return sethi(np);
           15 }
           16 
           17 static Node *
           18 branchnode(Node *cond, Symbol *sym)
           19 {
           20         Node *np;
           21         int op = cond ? OBRANCH : OJMP;
           22 
           23         np = node(op);
           24         np->op = op;
           25         np->left = sethi(cond);
           26         np->u.sym = sym;
           27         sym->refcnt++;
           28 
           29         return np;
           30 }
           31 
           32 static Node *
           33 bool(Node *cond, Symbol *true, Symbol *false)
           34 {
           35         Symbol *label;
           36         Node *p, *l = cond->left, *r = cond->right;
           37 
           38         switch (cond->op) {
           39         case ONEG:
           40                 l = bool(l, false, true);
           41                 break;
           42         case OAND:
           43                 label = newlabel();
           44                 l = bool(l, label, false);
           45                 prestmt(labelstmt(NULL, label));
           46                 r = bool(r, true, false);
           47                 break;
           48         case OOR:
           49                 label = newlabel();
           50                 l = bool(l, true, label);
           51                 prestmt(labelstmt(NULL, label));
           52                 r = bool(r, true, false);
           53                 break;
           54         default:
           55                 prestmt(branchnode(cond, true));
           56                 prestmt(branchnode(NULL, false));
           57                 return NULL;
           58         }
           59 
           60         cond->left = l;
           61         cond->right = r;
           62         return cond;
           63 }
           64 
           65 Node *
           66 logicexpr(Node *np)
           67 {
           68         Node *tmpvar, *p, *zero, *one;
           69         Type *tp = &np->type;
           70         Symbol *true, *false, *phi, *tmpsym;
           71 
           72         true = newlabel();
           73         false = newlabel();
           74         phi = newlabel();
           75 
           76         bool(np, true, false);
           77 
           78         tmpvar = tmpnode(tp, NULL);
           79         tmpsym = tmpvar->u.sym;
           80         zero = constnode(NULL, 0, tp);
           81         one = constnode(NULL, 1, tp);
           82 
           83         p = assignnode(tp, tmpnode(tp, tmpsym), one);
           84         prestmt(labelstmt(p, true));
           85 
           86         prestmt(branchnode(NULL, phi));
           87 
           88         p = assignnode(tp, tmpnode(tp, tmpsym), zero);
           89         prestmt(labelstmt(p, false));
           90 
           91         prestmt(labelstmt(NULL, phi));
           92 
           93         return sethi(tmpvar);
           94 }
           95 
           96 static void
           97 comma(Node *np)
           98 {
           99         if (np->op != OCOMMA) {
          100                 prestmt(sethi(np));
          101         } else {
          102                 comma(np->left);
          103                 prestmt(sethi(np->right));
          104                 delnode(np);
          105         }
          106 }
          107 
          108 static Node *
          109 ternary(Node *np)
          110 {
          111         Type *tp;
          112         Node *tmpvar, *colon, *p;
          113         Symbol *tmpsym, *true, *false, *phi;
          114 
          115         true = newlabel();
          116         false = newlabel();
          117         phi = newlabel();
          118         bool(np->left, true, false);
          119 
          120         tp = &np->type;
          121         colon = np->right;
          122         tmpvar = tmpnode(tp, NULL);
          123         tmpsym = tmpvar->u.sym;
          124 
          125         prestmt(labelstmt(NULL, true));
          126         p = assignnode(tp, tmpnode(tp, tmpsym), sethi(colon->left));
          127         prestmt(p);
          128         prestmt(branchnode(NULL, phi));
          129 
          130         prestmt(labelstmt(NULL, false));
          131         p = assignnode(tp, tmpnode(tp, tmpsym), sethi(colon->right));
          132         prestmt(p);
          133 
          134         prestmt(labelstmt(NULL, phi));
          135 
          136         return sethi(tmpvar);
          137 }
          138 
          139 static Node *
          140 replace(Node *what, Node *with)
          141 {
          142         Node *prev, *next;
          143 
          144         next = what->next, prev = what->prev;
          145         *what = *with;
          146         delnode(with);
          147         what->next = next, what->prev = prev;
          148 
          149         return sethi(what);
          150 }
          151 
          152 Node *
          153 sethi(Node *np)
          154 {
          155         int op;
          156         Node *next, *l, *r;
          157 
          158         if (!np)
          159                 return np;
          160 
          161         np->complex = 0;
          162         np->address = 0;
          163 
          164         switch (np->op) {
          165         case OBSWITCH:
          166                 np = swtch(np);
          167                 break;
          168         case OBRANCH:
          169                 next = np->next;
          170                 if (!next->label)
          171                         labelstmt(next, NULL);
          172 
          173                 op = np->left->op;
          174                 if (op != ONEG && op != OOR && op != OAND) {
          175                         sethi(np->left);
          176                         return np;
          177                 }
          178 
          179                 bool(np->left, np->u.sym, next->label);
          180                 np->u.sym->refcnt--;
          181                 return NULL;
          182         case OCOMMA:
          183                 r = np->right;
          184                 comma(np->left);
          185                 return replace(np, r);
          186         case OASK:
          187                 return replace(np, ternary(np));
          188         case ONEG:
          189         case OAND:
          190         case OOR:
          191                 return replace(np, logicexpr(np));
          192         default:
          193                 np = tsethi(np);
          194                 break;
          195         }
          196 
          197         l = np->left;
          198         r = np->right;
          199 
          200         if (np->address > 10)
          201                 return np;
          202         if (l)
          203                 np->complex = l->complex;
          204         if (r) {
          205                 int d = np->complex - r->complex;
          206 
          207                 if (d == 0)
          208                         ++np->complex;
          209                 else if (d < 0)
          210                         np->complex = r->complex;
          211         }
          212         if (np->complex == 0)
          213                 ++np->complex;
          214 
          215         return np;
          216 }
          217 
          218 void
          219 genaddr(void)
          220 {
          221         apply(sethi);
          222         PRTREE("after sethi");
          223 }