11 #define O(op, t, cf) [O##op]={#op, t, cf}, 76 static char *kwmap[
Ntok] = {
111 static char lexh[1 << (32-
M)];
139 fprintf(stderr,
"%s:%d: ", inpath, lnum);
140 vfprintf(stderr, s, ap);
141 fprintf(stderr,
"\n");
158 assert(
Ntok <= CHAR_MAX);
159 for (i=0; i<
Ntok; ++i)
161 h =
hash(kwmap[i])*
K >>
M;
162 assert(lexh[h] ==
Txxx);
179 case '+': c = fgetc(inf);
182 n = 10*n + (c -
'0');
184 }
while (
'0' <= c && c <=
'9');
188 return *(int64_t *)&n;
221 if (fscanf(inf,
"_%f", &tokval.flts) != 1)
225 if (fscanf(inf,
"_%lf", &tokval.fltd) != 1)
241 while ((c=fgetc(inf)) !=
'\n' && c != EOF)
247 if (isdigit(c) || c ==
'-' || c ==
'+') {
249 tokval.num = getint();
258 err(
"unterminated string");
259 vgrow(&tokval.str, i+1);
260 if (c ==
'"' && !esc) {
264 esc = (c ==
'\\' && !esc);
269 Alpha: c = fgetc(inf);
270 if (!isalpha(c) && c !=
'.' && c !=
'_')
271 err(
"invalid character %c (%d)", c, c);
275 err(
"identifier too long");
278 }
while (isalpha(c) || c ==
'$' || c ==
'.' || c ==
'_' || isdigit(c));
285 t = lexh[
hash(tok)*
K >>
M];
286 if (t ==
Txxx || strcmp(kwmap[t], tok) != 0) {
287 err(
"unknown keyword %s", tok);
316 while ((t = next()) ==
Tnl)
324 static char *ttoa[] = {
335 char buf[128], *s1, *s2;
341 s1 = ttoa[t] ? ttoa[t] :
"??";
342 s2 = ttoa[t1] ? ttoa[t1] :
"??";
343 sprintf(buf,
"%s expected, got %s instead", s1, s2);
353 if (strcmp(v, curf->
tmp[t].
name) == 0)
366 memset(&c, 0,
sizeof c);
369 return tmpref(tokval.str);
372 c.
bits.
i = tokval.num;
376 c.
bits.
s = tokval.flts;
381 c.
bits.
d = tokval.fltd;
388 for (i=0; i<curf->
ncon; i++)
405 if (strcmp(tokval.str,
typ[i].
name) == 0)
407 err(
"undefined type :%s", tokval.str);
415 err(
"invalid class specifier");
417 *tyn = findtyp(ntyp);
433 int k, ty, env, hasenv;
440 err(
"too many instructions (1)");
441 env = peek() ==
Tenv;
449 err(
"invalid argument");
451 err(
"only one environment allowed");
452 if (!arg && rtype(r) !=
RTmp)
453 err(
"invalid function parameter");
475 if (next() ==
Tdots) {
489 for (b=blkh[h]; b; b=b->
dlink)
490 if (strcmp(b->
name, name) == 0)
494 strcpy(b->
name, name);
521 err(
"label or } expected");
533 err(
"label, instruction or jump expected");
539 b = findblk(tokval.str);
546 err(
"multiple definitions of block @%s", b->
name);
563 err(
"invalid return value");
574 err(
"invalid argument for jnz jump");
579 curb->
s1 = findblk(tokval.str);
583 curb->
s2 = findblk(tokval.str);
586 err(
"invalid jump to the start node");
592 r = tmpref(tokval.str);
599 err(
"unexpected phi instruction");
621 err(
"size class must be w, l, s, or d");
623 err(
"invalid instruction");
628 err(
"too many arguments");
631 blk[i] = findblk(tokval.str);
635 err(
"invalid instruction argument");
641 err(
", or end of line expected");
648 err(
"too many instructions (2)");
657 phi =
alloc(
sizeof *phi);
660 memcpy(phi->
arg, arg, i *
sizeof arg[0]);
661 memcpy(phi->
blk, blk, i *
sizeof blk[0]);
670 usecheck(
Ref r,
int k,
Fn *fn)
695 if (rtype(i->
to) ==
RTmp) {
698 err(
"temporary %%%s is assigned with" 699 " multiple types", t->
name);
704 for (n=0; n<b->
npred; n++)
709 for (n=0; n<p->
narg; n++) {
711 if (bshas(ppb, p->
blk[n]->
id))
712 err(
"multiple entries for @%s in phi %%%s",
714 if (!usecheck(p->
arg[n], k, fn))
715 err(
"invalid type for operand %%%s in phi %%%s",
720 err(
"predecessors not matched in phi %%%s", t->
name);
723 for (n=0; n<2; n++) {
728 err(
"invalid instruction type in %s",
730 if (rtype(r) ==
RType)
732 if (rtype(r) != -1 && k ==
Kx)
733 err(
"no %s operand expected in %s",
734 n == 1 ?
"second" :
"first",
736 if (rtype(r) == -1 && k !=
Kx)
737 err(
"missing %s operand in %s",
738 n == 1 ?
"second" :
"first",
740 if (!usecheck(r, k, fn))
741 err(
"invalid type for %s operand %%%s in %s",
742 n == 1 ?
"second" :
"first",
748 if (!usecheck(r,
Kl, fn))
755 err(
"invalid type for jump argument %%%s in block @%s",
758 err(
"block @%s is used undefined", b->
s1->
name);
760 err(
"block @%s is used undefined", b->
s2->
name);
774 curf =
alloc(
sizeof *curf);
779 for (i=0; i<
Tmp0; ++i)
780 if (
T.fpr0 <= i && i <
T.fpr0 +
T.nfpr)
786 blink = &curf->
start;
789 rcls = parsecls(&curf->
retty);
793 err(
"function name expected");
794 strcpy(curf->
name, tokval.str);
795 curf->
vararg = parserefl(0);
797 err(
"function body must start with {");
803 err(
"empty function");
805 err(
"last block misses jump");
810 for (b=0; b; b=b->
link)
812 for (i=0; i<
BMask+1; ++i)
819 parsefields(
Field *fld,
Typ *ty,
int t)
822 int n, c, a, al,
type;
831 default:
err(
"invalid type member specifier");
832 case Td:
type =
Fd; s = 8; a = 3;
break;
833 case Tl:
type =
Fl; s = 8; a = 3;
break;
834 case Ts:
type =
Fs; s = 4; a = 2;
break;
835 case Tw:
type =
Fw; s = 4; a = 2;
break;
836 case Th:
type =
Fh; s = 2; a = 1;
break;
837 case Tb:
type =
Fb; s = 1; a = 0;
break;
840 ty1 = &
typ[findtyp(ntyp-1)];
866 for (; c>0 && n<
NField; c--, n++) {
875 err(
", or } expected");
880 ty->
size = (sz + a - 1) & -a;
900 if (nextnl() !=
Ttyp || nextnl() !=
Teq)
901 err(
"type name and then = expected");
902 strcpy(ty->
name, tokval.str);
905 if (nextnl() !=
Tint)
906 err(
"alignment expected");
907 for (al=0; tokval.num /= 2; al++)
913 err(
"type body must start with {");
917 ty->
size = tokval.num;
919 err(
"dark types need alignment");
929 err(
"invalid union member");
931 parsefields(ty->
fields[n++], ty, nextnl());
935 parsefields(ty->
fields[n++], ty, t);
945 d->
u.
ref.nam = tokval.str;
951 err(
"invalid token after offset in ref");
952 d->
u.
ref.off = tokval.num;
960 d->
u.
str = tokval.str;
964 parsedat(
void cb(
Dat *),
int export)
975 if (nextnl() !=
Tglo || nextnl() !=
Teq)
976 err(
"data name, then = expected");
977 strcpy(s, tokval.str);
980 if (nextnl() !=
Tint)
981 err(
"alignment expected");
983 d.
u.
num = tokval.num;
992 err(
"expected data contents in { .. }");
995 default:
err(
"invalid size specifier %c in data", tokval.chr);
997 case Tl: d.
type = DL;
break;
998 case Tw: d.
type = DW;
break;
999 case Th: d.
type = DH;
break;
1000 case Tb: d.
type = DB;
break;
1001 case Ts: d.
type = DW;
break;
1002 case Td: d.
type = DL;
break;
1003 case Tz: d.
type = DZ;
break;
1009 memset(&d.
u, 0,
sizeof d.
u);
1011 d.
u.
flts = tokval.flts;
1012 else if (t ==
Tfltd)
1013 d.
u.
fltd = tokval.fltd;
1015 d.
u.
num = tokval.num;
1021 err(
"constant literal expected");
1028 err(
", or } expected");
1046 parse(FILE *f,
char *path,
void (*data)(
Dat *),
void (*func)(
Fn *))
1061 err(
"top-level definition expected");
1067 func(parsefn(export));
1070 else if (t ==
Tdata) {
1072 parsedat(data, export);
1076 err(
"export can only qualify data and function");
1088 printcon(
Con *c, FILE *f)
1096 fprintf(f,
"%+"PRIi64, c->
bits.
i);
1100 fprintf(f,
"s_%f", c->
bits.
s);
1101 else if (c->
flt == 2)
1102 fprintf(f,
"d_%lf", c->
bits.
d);
1104 fprintf(f,
"%"PRIi64, c->
bits.
i);
1118 fprintf(f,
"R%d", r.
val);
1123 printcon(&fn->
con[r.
val], f);
1126 fprintf(f,
"S%d", (r.
val&(1<<28)) ? r.
val-(1<<29) : r.
val);
1129 fprintf(f,
"%04x", r.
val);
1142 if (!req(m->
base,
R)) {
1151 fprintf(f,
"%d * ", m->
scale);
1162 static char ktoc[] =
"wlsd";
1163 static char *jtoa[
NJmp] = {
1164 #define X(j) [J##j] = #j, 1174 fprintf(f,
"export ");
1175 fprintf(f,
"function $%s() {\n", fn->
name);
1177 fprintf(f,
"@%s\n", b->
name);
1178 for (p=b->
phi; p; p=p->
link) {
1181 fprintf(f,
" =%c phi ", ktoc[p->
cls]);
1184 fprintf(f,
"@%s ", p->
blk[n]->
name);
1186 if (n == p->
narg-1) {
1195 if (!req(i->
to,
R)) {
1197 fprintf(f,
" =%c ", ktoc[i->
cls]);
1212 fputc(ktoc[i->
cls], f);
1214 if (!req(i->
arg[0],
R)) {
1218 if (!req(i->
arg[1],
R)) {
1231 fprintf(f,
"\t%s", jtoa[b->
jmp.
type]);
1242 fprintf(f,
"\tjmp @%s\n", b->
s1->
name);
1245 fprintf(f,
"\t%s ", jtoa[b->
jmp.
type]);
#define X(NMemArgs, SetsZeroFlag, LeavesFlags)
Blk * start
Указатель на блок функции, являющийся её входной точкой
int ncon
Размер массива con.
void parse(FILE *f, char *path, void(*data)(Dat *), void(*func)(Fn *))
Парсит файл с программой на QBE IL.
Структура, хранящая информацию об инструкциях.
int clsmerge(short *, short)
int retty
index in typ[], -1 if no aggregate return
void * vnew(ulong, size_t, Pool)
struct Typ::Field(* fields)[NField+1]
void printfn(Fn *fn, FILE *f)
Con * con
Массив используемых функцией констант
void bsinit(BSet *, uint)
Структура, хранящая описание переменных (более подробное описание переменной ищите в Tmp)...
Содержит информацию о переменной
Tmp * tmp
Массив используемых функцией переменных
int ntmp
Размер массива tmp.
Непосредственно информация о базовом блоке.
void idup(Ins **, Ins *, ulong)
int bsequal(BSet *, BSet *)
char name[NString]
Имя переменной
Op optab[NOp]
Массив всех операций.
void vgrow(void *, ulong)
uint nblk
Количество блоков в функции
void printref(Ref r, Fn *fn, FILE *f)
Blk ** rpo
Ссылка на массив блоков, пронумерованных в порядке Reverse-Post Order, заполняется функцией fillrpo...
int nmem
Размер массива mem.
Номер (в массиве Fn->tmp) первой не регистровой переменной
char name[NString]
Имя функции
Ref newtmp(char *, int, Fn *)
#define T(a, b, c, d, e, f, g, h)
Структура, хранящая в себе информацию о функции
Структура, хранящая информацию об операции.