cproc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/cproc
Log | Files | Refs | Submodules | README | LICENSE

commit b345b989c87aa0515bfd1d9206c3c80831923b1c
parent cbff9bf03861b8d63f598d3370c82a96511a754c
Author: Michael Forney <mforney@mforney.org>
Date:   Sat, 20 Apr 2019 19:19:05 -0700

Make basic types have their own kind

Diffstat:
Mcc.h | 23++++++++++-------------
Mdecl.c | 13+++++++------
Mqbe.c | 81++++++++++++++++++++++++++++++++++++++-----------------------------------------
Mtype.c | 110+++++++++++++++++++++++++++++++++++++++----------------------------------------
4 files changed, 110 insertions(+), 117 deletions(-)

diff --git 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 @@ -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 @@ -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 @@ -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)