aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cc.h23
-rw-r--r--decl.c13
-rw-r--r--qbe.c81
-rw-r--r--type.c110
4 files changed, 110 insertions, 117 deletions
diff --git a/cc.h b/cc.h
index c2ee78f..9de12b3 100644
--- a/cc.h
+++ b/cc.h
@@ -133,7 +133,16 @@ enum typekind {
TYPENONE,
TYPEVOID,
- TYPEBASIC,
+ TYPEBOOL,
+ TYPECHAR,
+ TYPESHORT,
+ TYPEINT,
+ TYPEENUM,
+ TYPELONG,
+ TYPELLONG,
+ TYPEFLOAT,
+ TYPEDOUBLE,
+ TYPELDOUBLE,
TYPEPOINTER,
TYPEARRAY,
TYPEFUNC,
@@ -191,18 +200,6 @@ struct type {
_Bool incomplete;
union {
struct {
- enum {
- BASICBOOL,
- BASICCHAR,
- BASICSHORT,
- BASICINT,
- BASICENUM,
- BASICLONG,
- BASICLLONG,
- BASICFLOAT,
- BASICDOUBLE,
- BASICLDOUBLE,
- } kind;
_Bool issigned, iscomplex;
} basic;
struct {
diff --git a/decl.c b/decl.c
index 95373da..38a4256 100644
--- a/decl.c
+++ b/decl.c
@@ -160,7 +160,7 @@ tagspec(struct scope *s)
switch (tok.kind) {
case TSTRUCT: kind = TYPESTRUCT; break;
case TUNION: kind = TYPEUNION; break;
- case TENUM: kind = TYPEBASIC; break;
+ case TENUM: kind = TYPEENUM; break;
default: fatal("internal error: unknown tag kind");
}
next();
@@ -168,7 +168,7 @@ tagspec(struct scope *s)
tag = tok.lit;
next();
t = scopegettag(s, tag, false);
- if (s->parent && !t && tok.kind != TLBRACE && (kind == TYPEBASIC || tok.kind != TSEMICOLON))
+ if (s->parent && !t && tok.kind != TLBRACE && (kind == TYPEENUM || tok.kind != TSEMICOLON))
t = scopegettag(s->parent, tag, true);
} else if (tok.kind != TLBRACE) {
error(&tok.loc, "expected identifier or '{' after struct/union");
@@ -180,11 +180,12 @@ tagspec(struct scope *s)
if (t->kind != kind)
error(&tok.loc, "redeclaration of tag '%s' with different kind", tag);
} else {
- t = mktype(kind);
- if (kind == TYPEBASIC) {
+ if (kind == TYPEENUM) {
+ t = xmalloc(sizeof(*t));
*t = typeuint;
- t->basic.kind = BASICENUM;
+ t->kind = kind;
} else {
+ t = mktype(kind);
t->repr = &i64; // XXX
t->size = 0;
t->align = 0;
@@ -212,7 +213,7 @@ tagspec(struct scope *s)
t->size = ALIGNUP(t->size, t->align);
t->incomplete = false;
break;
- case TYPEBASIC: /* enum */
+ case TYPEENUM:
for (i = 0; tok.kind == TIDENT; ++i) {
d = mkdecl(DECLCONST, &typeint, QUALNONE, LINKNONE);
scopeputdecl(s, tok.lit, d);
diff --git a/qbe.c b/qbe.c
index deb5520..d974bed 100644
--- a/qbe.c
+++ b/qbe.c
@@ -250,33 +250,6 @@ funcstore(struct func *f, struct type *t, enum typequal tq, struct lvalue lval,
tp = typeprop(t);
assert(!lval.bits.before && !lval.bits.after || tp & PROPINT);
switch (t->kind) {
- case TYPEPOINTER:
- t = &typeulong;
- /* fallthrough */
- case TYPEBASIC:
- switch (t->size) {
- case 1: loadop = ILOADUB; storeop = ISTOREB; break;
- case 2: loadop = ILOADUH; storeop = ISTOREH; break;
- case 4: loadop = ILOADUW; storeop = tp & PROPFLOAT ? ISTORES : ISTOREW; break;
- case 8: loadop = ILOADL; storeop = tp & PROPFLOAT ? ISTORED : ISTOREL; break;
- default:
- fatal("internal error; unimplemented store");
- }
- if (lval.bits.before || lval.bits.after) {
- mask = 0xffffffffffffffffu >> lval.bits.after + 64 - t->size * 8 ^ (1 << lval.bits.before) - 1;
- v = funcinst(f, IOR, t->repr,
- funcinst(f, IAND, t->repr,
- funcinst(f, loadop, t->repr, lval.addr),
- mkintconst(t->repr, ~mask),
- ),
- funcinst(f, IAND, t->repr,
- funcinst(f, ISHL, t->repr, v, mkintconst(&i32, lval.bits.before)),
- mkintconst(t->repr, mask),
- ),
- );
- }
- funcinst(f, storeop, NULL, v, lval.addr);
- break;
case TYPESTRUCT:
case TYPEUNION:
case TYPEARRAY: {
@@ -302,8 +275,34 @@ funcstore(struct func *f, struct type *t, enum typequal tq, struct lvalue lval,
}
break;
}
+ case TYPEPOINTER:
+ t = &typeulong;
+ /* fallthrough */
default:
- fatal("unimplemented store");
+ assert(tp & PROPSCALAR);
+ switch (t->size) {
+ case 1: loadop = ILOADUB; storeop = ISTOREB; break;
+ case 2: loadop = ILOADUH; storeop = ISTOREH; break;
+ case 4: loadop = ILOADUW; storeop = tp & PROPFLOAT ? ISTORES : ISTOREW; break;
+ case 8: loadop = ILOADL; storeop = tp & PROPFLOAT ? ISTORED : ISTOREL; break;
+ default:
+ fatal("internal error; unimplemented store");
+ }
+ if (lval.bits.before || lval.bits.after) {
+ mask = 0xffffffffffffffffu >> lval.bits.after + 64 - t->size * 8 ^ (1 << lval.bits.before) - 1;
+ v = funcinst(f, IOR, t->repr,
+ funcinst(f, IAND, t->repr,
+ funcinst(f, loadop, t->repr, lval.addr),
+ mkintconst(t->repr, ~mask),
+ ),
+ funcinst(f, IAND, t->repr,
+ funcinst(f, ISHL, t->repr, v, mkintconst(&i32, lval.bits.before)),
+ mkintconst(t->repr, mask),
+ ),
+ );
+ }
+ funcinst(f, storeop, NULL, v, lval.addr);
+ break;
}
}
@@ -314,16 +313,6 @@ funcload(struct func *f, struct type *t, struct lvalue lval)
enum instkind op;
switch (t->kind) {
- case TYPEBASIC:
- switch (t->size) {
- case 1: op = t->basic.issigned ? ILOADSB : ILOADUB; break;
- case 2: op = t->basic.issigned ? ILOADSH : ILOADUH; break;
- case 4: op = typeprop(t) & PROPFLOAT ? ILOADS : t->basic.issigned ? ILOADSW : ILOADUW; break;
- case 8: op = typeprop(t) & PROPFLOAT ? ILOADD : ILOADL; break;
- default:
- fatal("internal error; unimplemented load");
- }
- break;
case TYPEPOINTER:
op = ILOADL;
break;
@@ -335,7 +324,15 @@ funcload(struct func *f, struct type *t, struct lvalue lval)
v->repr = t->repr;
return v;
default:
- fatal("unimplemented load %d", t->kind);
+ assert(typeprop(t) & PROPREAL);
+ switch (t->size) {
+ case 1: op = t->basic.issigned ? ILOADSB : ILOADUB; break;
+ case 2: op = t->basic.issigned ? ILOADSH : ILOADUH; break;
+ case 4: op = typeprop(t) & PROPFLOAT ? ILOADS : t->basic.issigned ? ILOADSW : ILOADUW; break;
+ case 8: op = typeprop(t) & PROPFLOAT ? ILOADD : ILOADL; break;
+ default:
+ fatal("internal error; unimplemented load");
+ }
}
v = funcinst(f, op, t->repr, lval.addr);
if (lval.bits.after)
@@ -681,11 +678,11 @@ funcexpr(struct func *f, struct expr *e)
dst = &typeulong;
if (dst->kind == TYPEVOID)
return NULL;
- if (src->kind != TYPEBASIC || dst->kind != TYPEBASIC)
- fatal("internal error; unsupported conversion");
srcprop = typeprop(src);
dstprop = typeprop(dst);
- if (dst->basic.kind == BASICBOOL) {
+ if (!(srcprop & PROPREAL) || !(dstprop & PROPREAL))
+ fatal("internal error; unsupported conversion");
+ if (dst->kind == TYPEBOOL) {
l = extend(f, src, l);
r = mkintconst(src->repr, 0);
if (srcprop & PROPINT)
diff --git a/type.c b/type.c
index 0a4aa45..cac5061 100644
--- a/type.c
+++ b/type.c
@@ -6,28 +6,28 @@
#include "util.h"
#include "cc.h"
-struct type typevoid = {.kind = TYPEVOID, .incomplete = true};
+struct type typevoid = {.kind = TYPEVOID, .incomplete = true};
-struct type typechar = {.kind = TYPEBASIC, .size = 1, .align = 1, .repr = &i8, .basic = {.kind = BASICCHAR, .issigned = 1}};
-struct type typeschar = {.kind = TYPEBASIC, .size = 1, .align = 1, .repr = &i8, .basic = {.kind = BASICCHAR, .issigned = 1}};
-struct type typeuchar = {.kind = TYPEBASIC, .size = 1, .align = 1, .repr = &i8, .basic = {.kind = BASICCHAR}};
+struct type typechar = {.kind = TYPECHAR, .size = 1, .align = 1, .repr = &i8, .basic.issigned = 1};
+struct type typeschar = {.kind = TYPECHAR, .size = 1, .align = 1, .repr = &i8, .basic.issigned = 1};
+struct type typeuchar = {.kind = TYPECHAR, .size = 1, .align = 1, .repr = &i8};
-struct type typeshort = {.kind = TYPEBASIC, .size = 2, .align = 2, .repr = &i16, .basic = {.kind = BASICSHORT, .issigned = 1}};
-struct type typeushort = {.kind = TYPEBASIC, .size = 2, .align = 2, .repr = &i16, .basic = {.kind = BASICSHORT}};
+struct type typeshort = {.kind = TYPESHORT, .size = 2, .align = 2, .repr = &i16, .basic.issigned = 1};
+struct type typeushort = {.kind = TYPESHORT, .size = 2, .align = 2, .repr = &i16};
-struct type typeint = {.kind = TYPEBASIC, .size = 4, .align = 4, .repr = &i32, .basic = {.kind = BASICINT, .issigned = 1}};
-struct type typeuint = {.kind = TYPEBASIC, .size = 4, .align = 4, .repr = &i32, .basic = {.kind = BASICINT}};
+struct type typeint = {.kind = TYPEINT, .size = 4, .align = 4, .repr = &i32, .basic.issigned = 1};
+struct type typeuint = {.kind = TYPEINT, .size = 4, .align = 4, .repr = &i32};
-struct type typelong = {.kind = TYPEBASIC, .size = 8, .align = 8, .repr = &i64, .basic = {.kind = BASICLONG, .issigned = 1}};
-struct type typeulong = {.kind = TYPEBASIC, .size = 8, .align = 8, .repr = &i64, .basic = {.kind = BASICLONG}};
+struct type typelong = {.kind = TYPELONG, .size = 8, .align = 8, .repr = &i64, .basic.issigned = 1};
+struct type typeulong = {.kind = TYPELONG, .size = 8, .align = 8, .repr = &i64};
-struct type typellong = {.kind = TYPEBASIC, .size = 8, .align = 8, .repr = &i64, .basic = {.kind = BASICLLONG, .issigned = 1}};
-struct type typeullong = {.kind = TYPEBASIC, .size = 8, .align = 8, .repr = &i64, .basic = {.kind = BASICLLONG}};
+struct type typellong = {.kind = TYPELLONG, .size = 8, .align = 8, .repr = &i64, .basic.issigned = 1};
+struct type typeullong = {.kind = TYPELLONG, .size = 8, .align = 8, .repr = &i64};
-struct type typebool = {.kind = TYPEBASIC, .size = 1, .align = 1, .repr = &i8, .basic = {.kind = BASICBOOL}};
-struct type typefloat = {.kind = TYPEBASIC, .size = 4, .align = 4, .repr = &f32, .basic = {.kind = BASICFLOAT}};
-struct type typedouble = {.kind = TYPEBASIC, .size = 8, .align = 8, .repr = &f64, .basic = {.kind = BASICDOUBLE}};
-struct type typeldouble = {.kind = TYPEBASIC, .size = 16, .align = 16, .basic = {.kind = BASICLDOUBLE}}; // XXX: not supported by qbe
+struct type typebool = {.kind = TYPEBOOL, .size = 1, .align = 1, .repr = &i8};
+struct type typefloat = {.kind = TYPEFLOAT, .size = 4, .align = 4, .repr = &f32};
+struct type typedouble = {.kind = TYPEDOUBLE, .size = 8, .align = 8, .repr = &f64};
+struct type typeldouble = {.kind = TYPELDOUBLE, .size = 16, .align = 16}; // XXX: not supported by qbe
static struct type typevaliststruct = {.kind = TYPESTRUCT, .size = 24, .align = 8};
struct type typevalist = {.kind = TYPEARRAY, .size = 24, .align = 8, .array = {1}, .base = &typevaliststruct};
@@ -81,47 +81,47 @@ mkarraytype(struct type *base, enum typequal qual, uint64_t len)
enum typeprop
typeprop(struct type *t)
{
- enum typeprop p = PROPNONE;
+ enum typeprop p;
switch (t->kind) {
case TYPEVOID:
- p |= PROPOBJECT;
+ p = PROPOBJECT;
break;
- case TYPEBASIC:
- p |= PROPOBJECT|PROPARITH|PROPSCALAR;
+ case TYPECHAR:
+ p = PROPOBJECT|PROPARITH|PROPSCALAR|PROPREAL|PROPINT|PROPCHAR;
+ break;
+ case TYPEBOOL:
+ case TYPESHORT:
+ case TYPEINT:
+ case TYPEENUM:
+ case TYPELONG:
+ case TYPELLONG:
+ p = PROPOBJECT|PROPARITH|PROPSCALAR|PROPREAL|PROPINT;
+ break;
+ case TYPEFLOAT:
+ case TYPEDOUBLE:
+ case TYPELDOUBLE:
+ p = PROPOBJECT|PROPARITH|PROPSCALAR|PROPFLOAT;
if (!t->basic.iscomplex)
p |= PROPREAL;
- switch (t->basic.kind) {
- case BASICFLOAT:
- case BASICDOUBLE:
- case BASICLDOUBLE:
- p |= PROPFLOAT;
- break;
- case BASICCHAR:
- p |= PROPCHAR;
- /* fallthrough */
- default:
- p |= PROPINT;
- break;
- }
break;
case TYPEPOINTER:
- p |= PROPOBJECT|PROPSCALAR|PROPDERIVED;
+ p = PROPOBJECT|PROPSCALAR|PROPDERIVED;
break;
case TYPEARRAY:
- p |= PROPOBJECT|PROPAGGR|PROPDERIVED;
+ p = PROPOBJECT|PROPAGGR|PROPDERIVED;
break;
case TYPEFUNC:
- p |= PROPDERIVED;
+ p = PROPDERIVED;
break;
case TYPESTRUCT:
- p |= PROPOBJECT|PROPAGGR;
+ p = PROPOBJECT|PROPAGGR;
break;
case TYPEUNION:
- p |= PROPOBJECT;
+ p = PROPOBJECT;
break;
default:
- break;
+ fatal("unknown type");
}
return p;
@@ -131,14 +131,14 @@ static int
typerank(struct type *t)
{
assert(typeprop(t) & PROPINT);
- switch (t->basic.kind) {
- case BASICBOOL: return 1;
- case BASICCHAR: return 2;
- case BASICSHORT: return 3;
- case BASICENUM:
- case BASICINT: return 4;
- case BASICLONG: return 5;
- case BASICLLONG: return 6;
+ switch (t->kind) {
+ case TYPEBOOL: return 1;
+ case TYPECHAR: return 2;
+ case TYPESHORT: return 3;
+ case TYPEENUM:
+ case TYPEINT: return 4;
+ case TYPELONG: return 5;
+ case TYPELLONG: return 6;
default:
fatal("internal error; unhandled integer type");
}
@@ -152,16 +152,14 @@ typecompatible(struct type *t1, struct type *t2)
if (t1 == t2)
return true;
- if (t1->kind != t2->kind)
- return false;
- switch (t1->kind) {
- case TYPEBASIC:
- if (t1->basic.issigned != t2->basic.issigned)
- return false;
+ if (t1->kind != t2->kind) {
/* enum types are compatible with 'int', but not with
each other (unless they are the same type) */
- return t1->basic.kind == BASICENUM && t2->basic.kind == BASICINT ||
- t1->basic.kind == BASICINT && t2->basic.kind == BASICENUM;
+ return (t1->kind == TYPEENUM && t2->kind == TYPEINT ||
+ t1->kind == TYPEINT && t2->kind == TYPEENUM) &&
+ t1->basic.issigned == t2->basic.issigned;
+ }
+ switch (t1->kind) {
case TYPEVOID:
return true;
case TYPEPOINTER:
@@ -237,7 +235,7 @@ typecommonreal(struct type *t1, struct type *t2)
{
struct type *tmp;
- assert(t1->kind == TYPEBASIC && t2->kind == TYPEBASIC);
+ assert(typeprop(t1) & PROPREAL && typeprop(t2) & PROPREAL);
if (t1 == t2)
return t1;
if (t1 == &typeldouble || t2 == &typeldouble)