ref: b03fed420a5b24f4368698ed681651c59dad683a
dir: /expr.c/
#include <stdint.h> #include <stdio.h> #include "cc.h" #define SWAP(x1, x2, t) (t = x1, x1 = x2, x2 = t) #define GETBTYPE(n, tp, t) ((t) = (tp = UNQUAL(n->type))->op) static Symbol *zero, *one; Node *expr(void); void init_expr(void) { static Symbol zdummy, odummy; zdummy.type = odummy.type = inttype; zdummy.u.i = 0; odummy.u.i = 1; zero = &zdummy; one = &odummy; } static Node * promote(Node *np) { Type *tp; if (options.npromote) return np; tp = UNQUAL(np->type); if (tp == chartype || tp == shortype || tp == booltype) return castcode(np, inttype); else if (tp == uchartype || tp == ushortype) return castcode(np, uinttype); return np; } static void typeconv(Node **p1, Node **p2) { Type *tp1, *tp2, *new1, *new2; Node *np1 = *p1, *np2 = *p2; signed char n; tp1 = UNQUAL(np1->type); tp2 = UNQUAL(np2->type); new1 = new2 = NULL; n = tp1->u.size - tp2->u.size; if (n > 0) new2 = tp1; else if (n < 0) new1 = tp2; else if (tp1->sign) new2 = tp1; else new1 = tp2; if (new1) *p1 = castcode(np1, new1); else *p2 = castcode(np2, new2); } static Node * bitlogic(char op, Node *np1, Node *np2) { Type *tp1, *tp2; uint8_t t1, t2; np1 = promote(np1); np2 = promote(np2); GETBTYPE(np1, tp1, t1); GETBTYPE(np2, tp2, t2); if (t1 != INT || t2 != INT) error("No integer operand in bit logical operation"); if (tp1 != tp2) typeconv(&np1, &np2); return bincode(op, np1->type, np1, np2); } static Node * addr2ptr(Node *np) { Type *tp; tp = UNQUAL(np->type); tp = mktype(tp->type, PTR, NULL, 0); return unarycode(OADDR, tp, np); } /* * Convert a Node to a type */ Node * convert(Node *np, Type *tp1, char iscast) { Type *tp2; register uint8_t t1, t2; tp1 = UNQUAL(tp1), tp2 = UNQUAL(np->type); if (tp1 == tp2) return np; t1 = tp1->op, t2 = tp2->op; switch (t1) { case ENUM: case INT: case FLOAT: switch (t2) { case INT: case FLOAT: case ENUM: return castcode(np, tp1); } break; case PTR: switch (t2) { case ARY: case FTN: np = addr2ptr(np); case PTR: if (iscast || tp1 == pvoidtype || tp2 == pvoidtype) { /* TODO: * we assume conversion between pointers * do not need any operation, but due to * alignment problems that may be false */ np->type = tp1; return np; } return NULL; } } return NULL; } static Node * arithmetic(char op, Node *np1, Node *np2) { char *err; Node *naux; Type *tp1, *tp2, *tp3; uint8_t t1, t2, taux; np1 = promote(np1); np2 = promote(np2); GETBTYPE(np1, tp1, t1); GETBTYPE(np2, tp2, t2); switch (t1) { case INT: case FLOAT: switch (t2) { case INT: case FLOAT: if (tp1 != tp2) typeconv(&np1, &np2); tp1 = np1->type; break; case PTR: case ARY: SWAP(np1, np2, naux); SWAP(t1, t2, taux); goto pointer; default: goto incorrect; } break; case ARY: np1 = addr2ptr(np1); tp1 = np1->type; case PTR: pointer: /* TODO: substraction between pointers */ switch (op) { case OADD: case OSUB: tp3 = tp1->type; if (!tp3->defined) goto nocomplete; if (t2 != INT) goto incorrect; np2 = bincode(OMUL, tp1, castcode(np2, tp1), sizeofcode(tp3)); break; default: goto incorrect; } break; default: goto incorrect; } return bincode(op, tp1, np1, np2); nocomplete: err = "invalid use of indefined type"; goto error; incorrect: err = "incorrect arithmetic operands"; error: error(err); } static Node * compare(char op, Node *np1, Node *np2) { Type *tp1, *tp2; uint8_t t1, t2; np1 = promote(np1); np2 = promote(np2); GETBTYPE(np1, tp1, t1); GETBTYPE(np2, tp2, t2); switch (t1) { case INT: case FLOAT: switch (t2) { case INT: case FLOAT: if (tp1 != tp2) typeconv(&np1, &np2); break; default: goto incompatibles; } break; case ARY: case FTN: np1 = addr2ptr(np1); tp1 = UNQUAL(np1->type); case PTR: if (tp1 != tp2) goto incompatibles; break; default: goto incompatibles; } return bincode(op, inttype, np1, np2); incompatibles: error("incompatibles type in comparision"); } static Node * exp2cond(Node *np, char neg) { if (ISNODELOG(np)) { np->u.op ^= neg; return np; } return compare(ONE ^ neg, np, constcode(zero)); } static Node * logic(char op, Node *np1, Node *np2) { np1 = exp2cond(np1, 0); np2 = exp2cond(np2, 0); return bincode(op, inttype, np1, np2); } static Node * array(Node *np1, Node *np2) { Type *tp; uint8_t t1, t2; char *err; t1 = BTYPE(np1->type); t2 = BTYPE(np2->type); if (t1 != INT && t2 != INT) goto bad_subs; np1 = arithmetic(OADD, np1, np2); tp = np1->type; if (tp->op != PTR) goto bad_vector; np1 = unarycode(OARY, tp->type , np1); np1->b.lvalue = 1; return np1; bad_vector: err = "subscripted value is neither array nor pointer nor vector"; goto error; bad_subs: err = "array subscript is not an integer"; error: error(err); } static Node * eval(Node *np) { Node *ifyes, *ifno; if (!ISNODELOG(np)) return np; return ternarycode(np, constcode(one), constcode(zero)); } static Node * incdec(Node *np, char op) { Type *tp; uint8_t t; char *err; GETBTYPE(np, tp, t); if (!np->b.lvalue) goto nolvalue; if (isconst(np->type->op)) goto const_mod; switch (t) { case PTR: if (!tp->type->defined) goto nocomplete; case INT: case FLOAT: np = unarycode(op, np->type, np); return np; default: goto bad_type; } nolvalue: err = "lvalue required in operation"; goto error; nocomplete: err = "invalid use of indefined type"; goto error; bad_type: err = "incorrect type in arithmetic operation"; goto error; const_mod: err = "const value modified"; error: error(err); } static Node * primary(void) { Node *np; Symbol *sym; switch (yytoken) { case IDEN: if ((sym = yylval.sym) == NULL) error("'%s' undeclared", yytext); np = node(emitsym, sym->type, SYM(sym), 0); np->b.lvalue = 1; next(); break; case CONSTANT: np = constcode(yylval.sym); next(); break; /* TODO: case STRING: */ case '(': next(); np = expr(); expect(')'); case ';': break; default: error("unexpected '%s'", yytext); } return np; } static Node * postfix(void) { register Node *np1, *np2; np1 = primary(); for (;;) { switch (yytoken) { case '[': next(); np2 = expr(); np1 = array(np1, np2); expect(']'); break; case DEC: case INC: np1 = incdec(np1, (yytoken == INC) ? OPINC : OPDEC); next(); break; /* TODO: case '.': */ /* TODO: case INDIR: */ /* TODO: case '(' */ default: return np1; } } } static Node *cast(void); static Node * unary(void) { register Node *np; Type *tp; char op, *err; uint8_t t; switch (yytoken) { case SIZEOF: next(); if (yytoken == '(' && ahead() == TYPE) { next(); tp = typename(); expect(')'); } else { tp = unary()->type; /* TODO: Free memory */ } return sizeofcode(tp); case INC: case DEC: op = (yytoken == INC) ? OINC : ODEC; next(); return incdec(unary(), op); case '!': case '&': case '*': case '+': case '~': case '-': op = yytoken; next(); np = cast(); tp = UNQUAL(np->type); t = tp->op; switch (op) { case '*': op = OPTR; switch (t) { case ARY: case FTN: np = addr2ptr(np); case PTR: tp = tp->type; break; default: goto bad_operand; } break; case '&': op = OADDR; if (!np->b.lvalue) goto no_lvalue; if (ISNODESYM(np) && np->u.sym->s.isregister) goto reg_address; tp = mktype(tp, PTR, NULL, 0); break; case '!': switch (t) { case FTN: case ARY: np = addr2ptr(np); case INT: case FLOAT: case PTR: return exp2cond(np, 1); break; default: goto bad_operand; } case '+': if (t != INT) goto bad_operand; return np; case '~': op = OCPL; if (t != INT) goto bad_operand; break; case '-': op = ONEG; if (t != INT && t != FLOAT) goto bad_operand; } return unarycode(op, tp, np); default: return postfix(); } no_lvalue: err = "lvalue required in unary expression"; goto error; reg_address: err = "address of register variable '%s' requested"; goto error; bad_operand: err = "bad operand in unary expression"; error: error(err, yytext); } static Node * cast(void) { Type *tp; register Node *np1, *np2; if (yytoken == '(') { switch(ahead()) { case TQUALIFIER: case TYPE: next(); tp = typename(); expect(')'); np1 = cast(); if ((np2 = convert(np1, tp, 1)) == NULL) error("bad type convertion requested"); np2->b.lvalue = np1->b.lvalue; return np1; default: break; } } return unary(); } static Node * mul(void) { register Node *np; register char op; np = cast(); for (;;) { switch (yytoken) { case '*': op = OMUL; break; case '/': op = ODIV; break; case '%': op = OMOD; break; default: return np; } next(); np = arithmetic(op, np, cast()); } } static Node * add(void) { register char op; register Node *np; np = mul(); for (;;) { switch (yytoken) { case '+': op = OADD; break; case '-': op = OSUB; break; default: return np; } next(); np = arithmetic(op, np, mul()); } } static Node * shift(void) { register char op; register Node *np; np = add(); for (;;) { switch (yytoken) { case SHL: op = OSHL; break; case SHR: op = OSHR; break; default: return np; } next(); np = bitlogic(op, np, add()); } } static Node * relational(void) { register char op; register Node *np; np = shift(); for (;;) { switch (yytoken) { case '<': op = OLT; break; case '>': op = OGT; break; case GE: op = OGE; break; case LE: op = OLE; break; default: return np; } next(); np = compare(op, np, shift()); } } static Node * eq(void) { register char op; register Node *np; np = relational(); for (;;) { switch (yytoken) { case EQ: op = OEQ; break; case NE: op = ONE; break; default: return np; } next(); np = compare(op, np, relational()); } } static Node * bit_and(void) { register Node *np; np = eq(); while (accept('&')) np = bitlogic(OBAND, np, eq()); return np; } static Node * bit_xor(void) { register Node *np; np = bit_and(); while (accept('^')) np = bitlogic(OBXOR, np, bit_and()); return np; } static Node * bit_or(void) { register Node *np; np = bit_xor(); while (accept('|')) np = bitlogic(OBOR, np, bit_xor()); return np; } static Node * and(void) { register Node *np; np = bit_or(); while (accept(AND)) np = logic(OAND, np, bit_or()); return np; } static Node * or(void) { register Node *np; np = and(); while (accept(OR)) np = logic(OOR, np, and()); return np; } static Node * ternary(void) { register Node *cond, *ifyes, *ifno; cond = or(); while (accept('?')) { ifyes = promote(expr()); expect(':'); ifno = promote(ternary()); /* TODO: check the types of ifno and ifyes */ cond = ternarycode(compare(ONE, cond, constcode(zero)), ifyes, ifno); } return cond; } static Node * assign(void) { register Node *np1, *np2; char *err; np1 = ternary(); for (;;) { register char op; switch (yytoken) { case '=': op = OASSIGN; break; case MUL_EQ: op = OA_MUL; break; case DIV_EQ: op = OA_DIV; break; case MOD_EQ: op = OA_MOD; break; case ADD_EQ: op = OA_ADD; break; case SUB_EQ: op = OA_SUB; break; case SHL_EQ: op = OA_SHL; break; case SHR_EQ: op = OA_SHR; break; case AND_EQ: op = OA_AND; break; case XOR_EQ: op = OA_XOR; break; case OR_EQ: op = OA_OR; break; default: return np1; } next(); np2 = assign(); if (!np1->b.lvalue) goto nolvalue; if (isconst(np1->type->op)) goto const_mod; np2 = eval(np2); if ((np2 = convert(np2, np1->type, 0)) == NULL) goto incompatibles; np1 = bincode(op, np1->type, np1, np2); } return np1; const_mod: err = "const value modified"; goto error; nolvalue: err = "lvalue required as left operand of assignment"; goto error; incompatibles: err = "incompatible types when assigning"; error: error(err); } Node * expr(void) { register Node *np1, *np2; np1 = assign(); while (accept(',')) { np2 = assign(); np1 = bincode(OCOMMA, np2->type, np1, np2); } return np1; }