commit 2d30362df693b46f67f1515e9d23e56e237410a5
parent 08c42cdfaea4d0cc3bf0bc00ee3e7cf2e5a9664a
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Thu, 10 Apr 2014 07:29:53 +0200
Add shift operators
Diffstat:
3 files changed, 36 insertions(+), 5 deletions(-)
diff --git a/cc.h b/cc.h
@@ -219,7 +219,8 @@ typedef void (*Inst)(Node *);
enum {
OCAST, OPTR, OADD, OARY, OSIZE, OMUL, OSUB,
- OINC, ODEC, OPINC, OPDEC, ODIV, OMOD
+ OINC, ODEC, OPINC, OPDEC, ODIV, OMOD, OSHL,
+ OSHR
};
extern void
diff --git a/code.c b/code.c
@@ -15,7 +15,9 @@ char *opcodes[] = {
[OSIZE] = "#",
[OPTR] = "@",
[OMOD] = "*",
- [ODIV] = "/'"
+ [ODIV] = "/'",
+ [OSHL] = "l",
+ [OSHR] = "r"
};
Node *
diff --git a/expr.c b/expr.c
@@ -49,6 +49,7 @@ floatconv(Node **np1, Node **np2)
static Node *
arithmetic(char op, Node *np1, Node *np2)
{
+ char *err;
Node *naux;
Type *tp1, *tp2, *tp3;
uint8_t t1, t2, taux, lvalue = 0;
@@ -56,6 +57,9 @@ arithmetic(char op, Node *np1, Node *np2)
tp1 = UNQUAL(np1->type), tp2 = UNQUAL(np2->type);
t1 = tp1->op, t2 = tp2->op;
+ if ((op == OSHL || op == OSHR) && (t1 != INT || t2 != INT))
+ goto bad_shift;
+
switch (t1) {
case INT:
switch (t2) {
@@ -112,10 +116,16 @@ pointer:
np1->b.lvalue = lvalue;
return np1;
+bad_shift:
+ err = "invalid operands to shift operator";
+ goto error;
nocomplete:
- error("invalid use of indefined type");
+ err = "invalid use of indefined type";
+ goto error;
incorrect:
- error("incorrect arithmetic operands");
+ err = "incorrect arithmetic operands";
+error:
+ error(err);
}
static Node *
@@ -283,13 +293,31 @@ add(void)
}
}
+static struct 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 = arithmetic(op, np, add());
+ }
+}
+
Node *
expr(void)
{
register Node *np;
do
- np = add();
+ np = shift();
while (yytoken == ',');
return np;
}