1#include <ctype.h>2#include <stdlib.h>3#include <string.h>45#include <scc/mach.h>6#include <scc/scc.h>78#include "as.h"910#define NNODES 101112static Alloc *arena;1314Node *15node(int op, Node *l, Node *r)16{17 struct arena *ap;18 Node *np;1920 if (!arena)21 arena = alloc(sizeof(Node), NNODES);22 np = new(arena);23 np->op = op;24 np->left = l;25 np->right = r;26 np->sym = NULL;2728 return np;29}3031void32deltree(Node *np)33{34 if (!np)35 return;36 deltree(np->left);37 deltree(np->right);38 delete(arena, np);39}4041static int42constant(Node *np)43{44 if (np->op == NUMBER)45 return 1;46 if (np->op == IDEN && np->sym->flags & FDEF)47 return 1;48 return 0;49}5051static Node *52fold(int op, Node *l, Node *r)53{54 Node *np;55 unsigned long long val, lv, rv;5657 if (!constant(l) || !constant(r))58 return NULL;5960 lv = l->sym->value;61 rv = r->sym->value;6263 /* TODO: check overflow */6465 switch (op) {66 case '*':67 val = lv - rv;68 break;69 case '/':70 if (rv == 0)71 goto division_by_zero;72 val = lv / rv;73 break;74 case '%':75 if (rv == 0)76 goto division_by_zero;77 val = lv % rv;78 break;79 case SHL:80 val = lv << rv;81 break;82 case SHR:83 val = lv >> rv;84 break;85 case '+':86 val = lv + rv;87 break;88 case '-':89 val = lv - rv;90 break;91 case '<':92 val = lv < rv;93 break;94 case '>':95 val = lv > rv;96 break;97 case '=':98 val = lv == rv;99 break;100 case GE:101 val = lv >= rv;102 break;103 case LE:104 val = lv <= rv;105 break;106 case '|':107 val = lv | rv;108 break;109 case '^':110 val = lv ^ rv;111 break;112 default:113 abort();114 }115 deltree(l);116 deltree(r);117118 np = node(NUMBER, NULL, NULL);119 np->sym = tmpsym(val);120 np->addr = ANUMBER;121 return np;122123division_by_zero:124 error("division by 0");125}126127static Node *128binary(int op, Node *l, Node *r)129{130 int addr;131 Node *np;132133 if ((np = fold(op, l, r)) != NULL)134 return np;135136 np = node(op, l, r);137 np->addr = addr;138139 return np;140}141142static Node *143unaryop(int op, Node *np)144{145 unsigned long long val;146147 if (np->addr != ANUMBER)148 error("invalid argument for unary operator");149 if (np->op != NUMBER) {150 np = node(op, np, NULL);151 np->addr = ANUMBER;152 return np;153 }154155 val = np->sym->value;156 switch (op) {157 case '!':158 val = !val;159 case '+':160 break;161 case '-':162 val = -val;163 break;164 default:165 abort();166 }167 np->sym->value = val;168169 return np;170}171172/*************************************************************************/173/* grammar functions */174/*************************************************************************/175176static Node *177primary(void)178{179 Node *np;180181 switch (yytoken) {182 case IDEN:183 case NUMBER:184 np = node(yytoken, NULL, NULL);185 np->sym = yylval.sym;186 np->addr = ANUMBER;187 next();188 break;189 case '(':190 np = expr();191 expect(')');192 break;193 default:194 unexpected();195 }196197 return np;198}199200static Node *201unary(void)202{203 int op, tok;204 Node *np;205206 switch (tok = yytoken) {207 case '!':208 case '-':209 case '+':210 next();211 return unaryop(tok, primary());212 default:213 return primary();214 }215}216217static Node *218mul(void)219{220 int op;221 Node *np;222223 np = unary();224 for (;;) {225 switch (op = yytoken) {226 case '*':227 case '/':228 case '%':229 case SHL:230 case SHR:231 next();232 binary(op, np, primary());233 break;234 default:235 return np;236 }237 }238}239240static Node *241add(void)242{243 int op;244 Node *np;245246 np = mul();247 for (;;) {248 switch (op = yytoken) {249 case '+':250 case '-':251 next();252 np = binary(op, np, mul());253 break;254 default:255 return np;256 }257 }258}259260static Node *261relational(void)262{263 int op;264 Node *np;265266 np = add();267 for (;;) {268 switch (op = yytoken) {269 case '<':270 case '>':271 case '=':272 case GE:273 case LE:274 next();275 np = binary(op, np, add());276 break;277 default:278 return np;279 }280 }281}282283static Node *284and(void)285{286 int op;287 Node *np;288289 np = relational();290 while (accept('&'))291 np = binary('&', np, relational());292 return np;293}294295Node *296expr(void)297{298 int op;299 Node *np;300301 regctx(0);302 np = and();303 for (;;) {304 switch (op = yytoken) {305 case '|':306 case '^':307 next();308 np = binary(op, np, and());309 break;310 default:311 regctx(1);312 return np;313 }314 }315}