diff options
author | Quentin Carbonneaux <quentin.carbonneaux@yale.edu> | 2015-09-07 21:59:45 -0400 |
---|---|---|
committer | Quentin Carbonneaux <quentin.carbonneaux@yale.edu> | 2015-09-15 23:01:32 -0400 |
commit | 87ab8941edb69a84979068fe74718f8a12b43262 (patch) | |
tree | 4377daade67022c2f591a4210f8f17245bfe2c43 /lisc/parse.c | |
parent | 8f2922eb1a9155b0097fb09854f267ddb17ed2dd (diff) | |
download | roux-87ab8941edb69a84979068fe74718f8a12b43262.tar.gz |
start work on aggregate types
The parser now has some code to parse the description of structured types. I tried to be even less specific than LLVM "type" by creating just enough abstraction so that I can deal with both AARCH64 and x64. The base types used in the definition of an aggregate are really just syntactic sugar to give a structure a size and an alignment. Only the location of float components matters for the compilation. In particular this means that the front-ends have to know how the ABI works to pass/return small integer types. This also means that the font-end has to be aware of the layout of structures. Chris Lattner has a proposition [1] for LLVM that is still pending and goes in the direction of giving more control of the ABI the front-end. [1]: http://www.nondot.org/sabre/LLVMNotes/ExtendedIntegerResults.txt
Diffstat (limited to 'lisc/parse.c')
-rw-r--r-- | lisc/parse.c | 193 |
1 files changed, 170 insertions, 23 deletions
diff --git a/lisc/parse.c b/lisc/parse.c index 1508063..43d40bb 100644 --- a/lisc/parse.c +++ b/lisc/parse.c @@ -25,8 +25,8 @@ OpDesc opdesc[NOp] = { [OStores] = { "stores", 2, 0 }, [OStoreb] = { "storeb", 2, 0 }, [OLoad] = { "load", 1, 0 }, - [OLoadss] = { "loadss", 1, 0 }, - [OLoadus] = { "loadus", 1, 0 }, + [OLoadsh] = { "loadsh", 1, 0 }, + [OLoaduh] = { "loaduh", 1, 0 }, [OLoadsb] = { "loadsb", 1, 0 }, [OLoadub] = { "loadub", 1, 0 }, [OCopy] = { "copy", 1, 1 }, @@ -34,8 +34,8 @@ OpDesc opdesc[NOp] = { [OSwap] = { "swap", 2, 2 }, [OSign] = { "sign", 1, 0 }, [OXDiv] = { "xdiv", 1, 1 }, - [OXCmp] = { "xcmp", 2, 1 }, - [OXTest] = { "xtest", 2, 1 }, + [OXCmp] = { "xcmp", 2, 1 }, + [OXTest] = { "xtest", 2, 1 }, [OAddr] = { "addr", 1, 0 }, [OAlloc] = { "alloc4", 1, 1 }, [OAlloc+1] = { "alloc8", 1, 1 }, @@ -62,17 +62,27 @@ enum { TJmp, TJnz, TRet, - TW, + TFunc, + TType, + TAlign, TL, + TW, + TH, + TB, + TD, + TS, TNum, TTmp, TLbl, - TAddr, + TGlo, + TTyp, TEq, TComma, TLParen, TRParen, + TLBrace, + TRBrace, TNL, TEOF, }; @@ -140,8 +150,15 @@ lex() { "jmp", TJmp }, { "jnz", TJnz }, { "ret", TRet }, - { "w", TW }, + { "function", TFunc }, + { "type", TType }, + { "align", TAlign }, { "l", TL }, + { "w", TW }, + { "h", TS }, + { "b", TB }, + { "d", TD }, + { "s", TS }, { 0, TXXX } }; static char tok[NString]; @@ -160,19 +177,23 @@ lex() return TLParen; case ')': return TRParen; + case '{': + return TLBrace; + case '}': + return TRBrace; case '=': return TEq; case '%': t = TTmp; - c = fgetc(inf); goto Alpha; case '@': t = TLbl; - c = fgetc(inf); goto Alpha; case '$': - t = TAddr; - c = fgetc(inf); + t = TGlo; + goto Alpha; + case ':': + t = TTyp; goto Alpha; case '#': while (fgetc(inf) != '\n') @@ -201,7 +222,8 @@ lex() return TNum; } t = TXXX; -Alpha: + if (0) +Alpha: c = fgetc(inf); if (!isalpha(c)) err("lexing failure"); i = 0; @@ -246,6 +268,17 @@ next() return t; } +static int +nextnl() +{ + int t; + + do + t = next(); + while (t == TNL); + return t; +} + Blk * blocka() { @@ -288,7 +321,7 @@ parseref() c = (Con){.type = CNum, .val = tokval.num}; strcpy(c.label, ""); if (0) { - case TAddr: + case TGlo: c = (Con){.type = CAddr, .val = 0}; strcpy(c.label, tokval.str); } @@ -367,11 +400,9 @@ parseline(PState ps) Blk *b; int t, op, i, w; - do - t = next(); - while (t == TNL); - if (ps == PLbl && t != TLbl && t != TEOF) - err("label or end of file expected"); + t = nextnl(); + if (ps == PLbl && t != TLbl && t != TRBrace) + err("label or } expected"); switch (t) { default: if (OStorel <= t && t <= OStoreb) { @@ -381,7 +412,7 @@ parseline(PState ps) goto DoOp; } err("label, instruction or jump expected"); - case TEOF: + case TRBrace: return PEnd; case TTmp: break; @@ -492,15 +523,17 @@ DoOp: } } -Fn * -parsefn(FILE *f) +static Fn * +parsefn() { int i; PState ps; Fn *fn; - inf = f; - thead = TXXX; + if (next() != TGlo) + err("function name expected"); + if (nextnl() != TLBrace) + err("function must start with {"); for (i=0; i<NBlk; i++) bmap[i] = 0; for (i=Tmp0; i<NTmp; i++) @@ -512,6 +545,7 @@ parsefn(FILE *f) lnum = 1; nblk = 0; fn = alloc(sizeof *fn); + strcpy(fn->name, tokval.str); blink = &fn->start; ps = PLbl; do @@ -533,6 +567,119 @@ parsefn(FILE *f) } static void +parsety() +{ + Type *ty; + int t, n, sz, al, s, a, c, flt; + + ty = alloc(sizeof *ty); + ty->align = -1; + if (nextnl() != TTyp || nextnl() != TEq) + err("type name, then = expected"); + t = nextnl(); + if (t == TAlign) { + if (nextnl() != TNum) + err("alignment value expected"); + for (al=0; tokval.num /= 2; al++) + ; + ty->align = al; + t = nextnl(); + } + if (t != TLBrace) + err("type body must start with {"); + t = nextnl(); + if (t == TNum) { + ty->dark = 1; + ty->size = tokval.num; + if (ty->align == -1) + err("dark types need alignment"); + t = nextnl(); + } else { + ty->dark = 0; + n = -1; + sz = 0; + al = 0; + do { + flt = 0; + switch (nextnl()) { + default: err("invalid size specifier"); + case TD: flt = 1; + case TL: s = 8; a = 3; break; + case TS: flt = 1; + case TW: s = 4; a = 2; break; + case TH: s = 2; a = 1; break; + case TB: s = 1; a = 0; break; + } + if (a > al) + al = a; + if ((a = sz & s-1)) { + a = s - a; + if (++n < NSeg) { + /* padding segment */ + ty->seg[n].flt = 0; + ty->seg[n].len = a; + } + } + t = nextnl(); + if (t == TNum) { + c = tokval.num; + t = nextnl(); + } else + c = 1; + while (c-- > 0) { + if (flt && ++n < NSeg) { + /* floating point segment */ + ty->seg[n].flt = 1; + ty->seg[n].len = s; + } + sz += a + s; + } + } while (t == TComma); + if (++n >= NSeg) + ty->dark = 1; + else + ty->seg[n].len = 0; + if (ty->align == -1) + ty->align = al; + else + al = ty->align; + a = (1 << al) - 1; + ty->size = (sz + a) & ~a; + } + if (t != TLBrace) + err("expected closing }"); +} + +Fn * +parse(FILE *f) +{ + Fn *fn; + + fn = 0; + inf = f; + thead = TXXX; + for (;;) + switch (nextnl()) { + case TFunc: + if (fn) + /* todo, support multiple + * functions per file + */ + diag("too many functions"); + fn = parsefn(); + break; + case TType: + parsety(); + break; + case TEOF: + return fn; + default: + err("top-level definition expected"); + break; + } +} + +static void printref(Ref r, Fn *fn, FILE *f) { switch (r.type) { |