6 Ksb
= 4, /* matches Oarg/Opar/Jret */
13 Ke
= -2, /* erroneous mode */
14 Km
= Kl
, /* memory pointer */
19 #define P(cf, hi, id) .canfold = cf, .hasid = hi, .idval = id
20 #define O(op, t, p) [O##op]={.name = #op, .argcls = t, p},
96 static char *kwmap
[Ntok
] = {
101 [Talloc1
] = "alloc1",
102 [Talloc2
] = "alloc2",
111 [Texport
] = "export",
112 [Tthread
] = "thread",
113 [Tcommon
] = "common",
114 [Tfunc
] = "function",
117 [Tsection
] = "section",
119 [Tdbgfile
] = "dbgfile",
137 TMask
= 16383, /* for temps hash */
138 BMask
= 8191, /* for blocks hash */
140 K
= 11183273, /* found using tools/lexh.c */
144 static uchar lexh
[1 << (32-M
)];
163 static Blk
*blkh
[BMask
+1];
174 fprintf(stderr
, "qbe:%s:%d: ", inpath
, lnum
);
175 vfprintf(stderr
, s
, ap
);
176 fprintf(stderr
, "\n");
190 for (i
=0; i
<NPubOp
; ++i
)
192 kwmap
[i
] = optab
[i
].name
;
193 assert(Ntok
<= UCHAR_MAX
);
194 for (i
=0; i
<Ntok
; ++i
)
196 h
= hash(kwmap
[i
])*K
>> M
;
197 assert(lexh
[h
] == Txxx
);
215 n
= 10*n
+ (c
- '0');
217 } while ('0' <= c
&& c
<= '9');
221 return *(int64_t *)&n
;
227 static char tok
[NString
];
254 if (fscanf(inf
, "_%f", &tokval
.flts
) != 1)
258 if (fscanf(inf
, "_%lf", &tokval
.fltd
) != 1)
271 if ((c
= fgetc(inf
)) == '"')
279 while ((c
=fgetc(inf
)) != '\n' && c
!= EOF
)
286 if (isdigit(c
) || c
== '-') {
288 tokval
.num
= getint();
294 tokval
.str
= vnew(2, 1, PFn
);
300 err("unterminated string");
301 vgrow(&tokval
.str
, i
+2);
303 if (c
== '"' && !esc
) {
307 esc
= (c
== '\\' && !esc
);
311 if (!isalpha(c
) && c
!= '.' && c
!= '_')
312 err("invalid character %c (%d)", c
, c
);
316 err("identifier too long");
319 } while (isalpha(c
) || c
== '$' || c
== '.' || c
== '_' || isdigit(c
));
326 t
= lexh
[hash(tok
)*K
>> M
];
327 if (t
== Txxx
|| strcmp(kwmap
[t
], tok
) != 0) {
328 err("unknown keyword %s", tok
);
357 while ((t
= next()) == Tnl
)
365 static char *ttoa
[] = {
376 char buf
[128], *s1
, *s2
;
382 s1
= ttoa
[t
] ? ttoa
[t
] : "??";
383 s2
= ttoa
[t1
] ? ttoa
[t1
] : "??";
384 sprintf(buf
, "%s expected, got %s instead", s1
, s2
);
393 if (tmphcap
/2 <= curf
->ntmp
-Tmp0
) {
395 tmphcap
= tmphcap
? tmphcap
*2 : TMask
+1;
396 tmph
= emalloc(tmphcap
* sizeof tmph
[0]);
397 for (t
=Tmp0
; t
<curf
->ntmp
; t
++) {
398 i
= hash(curf
->tmp
[t
].name
) & (tmphcap
-1);
399 for (; tmph
[i
]; i
=(i
+1) & (tmphcap
-1))
404 i
= hash(v
) & (tmphcap
-1);
405 for (; tmph
[i
]; i
=(i
+1) & (tmphcap
-1)) {
407 if (strcmp(curf
->tmp
[t
].name
, v
) == 0)
413 strcpy(curf
->tmp
[t
].name
, v
);
422 memset(&c
, 0, sizeof c
);
427 return tmpref(tokval
.str
);
430 c
.bits
.i
= tokval
.num
;
434 c
.bits
.s
= tokval
.flts
;
439 c
.bits
.d
= tokval
.fltd
;
448 c
.sym
.id
= intern(tokval
.str
);
451 return newcon(&c
, curf
);
458 if (strcmp(tokval
.str
, typ
[i
].name
) == 0)
460 err("undefined type :%s", tokval
.str
);
468 err("invalid class specifier");
470 *tyn
= findtyp(ntyp
);
494 int k
, ty
, env
, hasenv
, vararg
;
500 while (peek() != Trparen
) {
501 if (curi
- insb
>= NIns
)
502 err("too many instructions");
504 err("no parameters allowed after '...'");
508 err("only one '...' allowed");
511 *curi
= (Ins
){.op
= Oargv
};
518 err("only one environment allowed");
531 err("invalid argument");
532 if (!arg
&& rtype(r
) != RTmp
)
533 err("invalid function parameter");
536 *curi
= (Ins
){Oarge
, k
, R
, {r
}};
538 *curi
= (Ins
){Opare
, k
, r
, {R
}};
541 *curi
= (Ins
){Oargc
, Kl
, R
, {TYPE(ty
), r
}};
543 *curi
= (Ins
){Oparc
, Kl
, r
, {TYPE(ty
)}};
546 *curi
= (Ins
){Oargsb
+(k
-Ksb
), Kw
, R
, {r
}};
548 *curi
= (Ins
){Oparsb
+(k
-Ksb
), Kw
, r
, {R
}};
551 *curi
= (Ins
){Oarg
, k
, R
, {r
}};
553 *curi
= (Ins
){Opar
, k
, r
, {R
}};
556 if (peek() == Trparen
)
570 h
= hash(name
) & BMask
;
571 for (b
=blkh
[h
]; b
; b
=b
->dlink
)
572 if (strcmp(b
->name
, name
) == 0)
576 strcpy(b
->name
, name
);
585 curb
->nins
= curi
- insb
;
586 idup(&curb
->ins
, insb
, curb
->nins
);
594 Ref arg
[NPred
] = {R
};
603 if (ps
== PLbl
&& t
!= Tlbl
&& t
!= Trbrace
)
604 err("label or } expected");
607 r
= tmpref(tokval
.str
);
617 /* operations without result */
623 err("label, instruction or jump expected");
627 b
= findblk(tokval
.str
);
628 if (curb
&& curb
->jmp
.type
== Jxxx
) {
630 curb
->jmp
.type
= Jjmp
;
633 if (b
->jmp
.type
!= Jxxx
)
634 err("multiple definitions of block @%s", b
->name
);
641 curb
->jmp
.type
= Jretw
+ rcls
;
643 curb
->jmp
.type
= Jret0
;
644 else if (rcls
!= K0
) {
647 err("invalid return value");
652 curb
->jmp
.type
= Jjmp
;
655 curb
->jmp
.type
= Jjnz
;
658 err("invalid argument for jnz jump");
663 curb
->s1
= findblk(tokval
.str
);
664 if (curb
->jmp
.type
!= Jjmp
) {
667 curb
->s2
= findblk(tokval
.str
);
669 if (curb
->s1
== curf
->start
|| curb
->s2
== curf
->start
)
670 err("invalid jump to the start block");
673 curb
->jmp
.type
= Jhlt
;
683 arg
[0] = INT(tokval
.num
);
684 if (arg
[0].val
!= tokval
.num
)
685 err("line number too big");
686 if (peek() == Tcomma
) {
689 arg
[1] = INT(tokval
.num
);
690 if (arg
[1].val
!= tokval
.num
)
691 err("column number too big");
711 if (op
>= Tloadl
&& op
<= Tloadd
)
713 if (op
== Talloc1
|| op
== Talloc2
)
715 if (op
== Ovastart
&& !curf
->vararg
)
716 err("cannot use vastart in non-variadic function");
718 err("size class must be w, l, s, or d");
723 err("too many arguments");
726 blk
[i
] = findblk(tokval
.str
);
730 err("invalid instruction argument");
736 err(", or end of line expected");
742 if (ps
!= PPhi
|| curb
== curf
->start
)
743 err("unexpected phi instruction");
744 phi
= alloc(sizeof *phi
);
747 phi
->arg
= vnew(i
, sizeof arg
[0], PFn
);
748 memcpy(phi
->arg
, arg
, i
* sizeof arg
[0]);
749 phi
->blk
= vnew(i
, sizeof blk
[0], PFn
);
750 memcpy(phi
->blk
, blk
, i
* sizeof blk
[0]);
756 if (curi
- insb
>= NIns
-1)
757 err("too many instructions");
758 memset(curi
, 0, 2 * sizeof(Ins
));
760 curi
->arg
[0] = arg
[0];
761 curi
->arg
[1] = arg
[1];
763 if (rtype(arg
[2]) != RCon
)
764 err("blit size must be constant");
765 c
= &curf
->con
[arg
[2].val
];
769 || rsval(r
) != c
->bits
.i
)
770 err("invalid blit size");
777 err("invalid instruction");
779 if (curi
- insb
>= NIns
)
780 err("too many instructions");
784 curi
->arg
[0] = arg
[0];
785 curi
->arg
[1] = arg
[1];
792 usecheck(Ref r
, int k
, Fn
*fn
)
794 return rtype(r
) != RTmp
|| fn
->tmp
[r
.val
].cls
== k
795 || (fn
->tmp
[r
.val
].cls
== Kl
&& k
== Kw
);
811 bsinit(pb
, fn
->nblk
);
812 bsinit(ppb
, fn
->nblk
);
813 for (b
=fn
->start
; b
; b
=b
->link
) {
814 for (p
=b
->phi
; p
; p
=p
->link
)
815 fn
->tmp
[p
->to
.val
].cls
= p
->cls
;
816 for (i
=b
->ins
; i
<&b
->ins
[b
->nins
]; i
++)
817 if (rtype(i
->to
) == RTmp
) {
818 t
= &fn
->tmp
[i
->to
.val
];
819 if (clsmerge(&t
->cls
, i
->cls
))
820 err("temporary %%%s is assigned with"
821 " multiple types", t
->name
);
824 for (b
=fn
->start
; b
; b
=b
->link
) {
826 for (n
=0; n
<b
->npred
; n
++)
827 bsset(pb
, b
->pred
[n
]->id
);
828 for (p
=b
->phi
; p
; p
=p
->link
) {
830 t
= &fn
->tmp
[p
->to
.val
];
831 for (n
=0; n
<p
->narg
; n
++) {
833 if (bshas(ppb
, p
->blk
[n
]->id
))
834 err("multiple entries for @%s in phi %%%s",
835 p
->blk
[n
]->name
, t
->name
);
836 if (!usecheck(p
->arg
[n
], k
, fn
))
837 err("invalid type for operand %%%s in phi %%%s",
838 fn
->tmp
[p
->arg
[n
].val
].name
, t
->name
);
839 bsset(ppb
, p
->blk
[n
]->id
);
841 if (!bsequal(pb
, ppb
))
842 err("predecessors not matched in phi %%%s", t
->name
);
844 for (i
=b
->ins
; i
<&b
->ins
[b
->nins
]; i
++)
845 for (n
=0; n
<2; n
++) {
846 k
= optab
[i
->op
].argcls
[n
][i
->cls
];
850 err("invalid instruction type in %s",
852 if (rtype(r
) == RType
)
854 if (rtype(r
) != -1 && k
== Kx
)
855 err("no %s operand expected in %s",
856 n
== 1 ? "second" : "first",
858 if (rtype(r
) == -1 && k
!= Kx
)
859 err("missing %s operand in %s",
860 n
== 1 ? "second" : "first",
862 if (!usecheck(r
, k
, fn
))
863 err("invalid type for %s operand %%%s in %s",
864 n
== 1 ? "second" : "first",
865 t
->name
, optab
[i
->op
].name
);
868 if (isret(b
->jmp
.type
)) {
869 if (b
->jmp
.type
== Jretc
)
871 else if (b
->jmp
.type
>= Jretsb
)
874 k
= b
->jmp
.type
- Jretw
;
875 if (!usecheck(r
, k
, fn
))
878 if (b
->jmp
.type
== Jjnz
&& !usecheck(r
, Kw
, fn
))
880 err("invalid type for jump argument %%%s in block @%s",
881 fn
->tmp
[r
.val
].name
, b
->name
);
882 if (b
->s1
&& b
->s1
->jmp
.type
== Jxxx
)
883 err("block @%s is used undefined", b
->s1
->name
);
884 if (b
->s2
&& b
->s2
->jmp
.type
== Jxxx
)
885 err("block @%s is used undefined", b
->s2
->name
);
899 curf
= alloc(sizeof *curf
);
902 curf
->tmp
= vnew(curf
->ntmp
, sizeof curf
->tmp
[0], PFn
);
903 curf
->con
= vnew(curf
->ncon
, sizeof curf
->con
[0], PFn
);
904 for (i
=0; i
<Tmp0
; ++i
)
905 if (T
.fpr0
<= i
&& i
< T
.fpr0
+ T
.nfpr
)
909 curf
->con
[0].type
= CBits
;
910 curf
->con
[0].bits
.i
= 0xdeaddead; /* UNDEF */
911 curf
->con
[1].type
= CBits
;
913 blink
= &curf
->start
;
916 rcls
= parsecls(&curf
->retty
);
920 err("function name expected");
921 strncpy(curf
->name
, tokval
.str
, NString
-1);
922 curf
->vararg
= parserefl(0);
923 if (nextnl() != Tlbrace
)
924 err("function body must start with {");
930 err("empty function");
931 if (curb
->jmp
.type
== Jxxx
)
932 err("last block misses jump");
933 curf
->mem
= vnew(0, sizeof curf
->mem
[0], PFn
);
937 for (b
=curf
->start
; b
; b
=b
->link
)
938 b
->dlink
= 0; /* was trashed by findblk() */
939 for (i
=0; i
<BMask
+1; ++i
)
941 memset(tmph
, 0, tmphcap
* sizeof tmph
[0]);
947 parsefields(Field
*fld
, Typ
*ty
, int t
)
950 int n
, c
, a
, al
, type
;
956 while (t
!= Trbrace
) {
959 default: err("invalid type member specifier");
960 case Td
: type
= Fd
; s
= 8; a
= 3; break;
961 case Tl
: type
= Fl
; s
= 8; a
= 3; break;
962 case Ts
: type
= Fs
; s
= 4; a
= 2; break;
963 case Tw
: type
= Fw
; s
= 4; a
= 2; break;
964 case Th
: type
= Fh
; s
= 2; a
= 1; break;
965 case Tb
: type
= Fb
; s
= 1; a
= 0; break;
968 ty1
= &typ
[findtyp(ntyp
-1)];
976 a
= ((sz
+ a
) & ~a
) - sz
;
994 for (; c
>0 && n
<NField
; c
--, n
++) {
1003 err(", or } expected");
1008 ty
->size
= (sz
+ a
- 1) & -a
;
1019 /* be careful if extending the syntax
1020 * to handle nested types, any pointer
1021 * held to typ[] might be invalidated!
1023 vgrow(&typ
, ntyp
+1);
1029 if (nextnl() != Ttyp
|| nextnl() != Teq
)
1030 err("type name and then = expected");
1031 strcpy(ty
->name
, tokval
.str
);
1034 if (nextnl() != Tint
)
1035 err("alignment expected");
1036 for (al
=0; tokval
.num
/= 2; al
++)
1042 err("type body must start with {");
1046 ty
->size
= tokval
.num
;
1047 if (ty
->align
== -1)
1048 err("dark types need alignment");
1049 if (nextnl() != Trbrace
)
1054 ty
->fields
= vnew(1, sizeof ty
->fields
[0], PHeap
);
1059 err("invalid union member");
1060 vgrow(&ty
->fields
, n
+1);
1061 parsefields(ty
->fields
[n
++], ty
, nextnl());
1063 } while (t
!= Trbrace
);
1065 parsefields(ty
->fields
[n
++], ty
, t
);
1075 d
->u
.ref
.name
= tokval
.str
;
1081 err("invalid token after offset in ref");
1082 d
->u
.ref
.off
= tokval
.num
;
1090 d
->u
.str
= tokval
.str
;
1094 parsedat(void cb(Dat
*), Lnk
*lnk
)
1096 char name
[NString
] = {0};
1100 if (nextnl() != Tglo
|| nextnl() != Teq
)
1101 err("data name, then = expected");
1102 strncpy(name
, tokval
.str
, NString
-1);
1106 if (nextnl() != Tint
)
1107 err("alignment expected");
1108 if (tokval
.num
<= 0 || tokval
.num
> CHAR_MAX
1109 || (tokval
.num
& (tokval
.num
-1)) != 0)
1110 err("invalid alignment");
1111 lnk
->align
= tokval
.num
;
1120 err("expected data contents in { .. }");
1123 default: err("invalid size specifier %c in data", tokval
.chr
);
1124 case Trbrace
: goto Done
;
1125 case Tl
: d
.type
= DL
; break;
1126 case Tw
: d
.type
= DW
; break;
1127 case Th
: d
.type
= DH
; break;
1128 case Tb
: d
.type
= DB
; break;
1129 case Ts
: d
.type
= DW
; break;
1130 case Td
: d
.type
= DL
; break;
1131 case Tz
: d
.type
= DZ
; break;
1137 memset(&d
.u
, 0, sizeof d
.u
);
1139 d
.u
.flts
= tokval
.flts
;
1140 else if (t
== Tfltd
)
1141 d
.u
.fltd
= tokval
.fltd
;
1143 d
.u
.num
= tokval
.num
;
1149 err("constant literal expected");
1152 } while (t
== Tint
|| t
== Tflts
|| t
== Tfltd
|| t
== Tstr
|| t
== Tglo
);
1156 err(", or } expected");
1168 for (haslnk
=0;; haslnk
=1)
1169 switch ((t
=nextnl())) {
1181 err("only one section allowed");
1183 err("section \"name\" expected");
1184 lnk
->sec
= tokval
.str
;
1185 if (peek() == Tstr
) {
1187 lnk
->secf
= tokval
.str
;
1191 if (t
== Tfunc
&& lnk
->thread
)
1192 err("only data may have thread linkage");
1193 if (haslnk
&& t
!= Tdata
&& t
!= Tfunc
)
1194 err("only data and function have linkage");
1200 parse(FILE *f
, char *path
, void dbgfile(char *), void data(Dat
*), void func(Fn
*))
1211 typ
= vnew(0, sizeof typ
[0], PHeap
);
1214 switch (parselnk(&lnk
)) {
1216 err("top-level definition expected");
1219 dbgfile(tokval
.str
);
1223 func(parsefn(&lnk
));
1226 parsedat(data
, &lnk
);
1232 for (n
=0; n
<ntyp
; n
++)
1234 vfree(typ
[n
].fields
);
1242 printcon(Con
*c
, FILE *f
)
1248 if (c
->sym
.type
== SThr
)
1249 fprintf(f
, "thread ");
1250 fprintf(f
, "$%s", str(c
->sym
.id
));
1252 fprintf(f
, "%+"PRIi64
, c
->bits
.i
);
1256 fprintf(f
, "s_%f", c
->bits
.s
);
1257 else if (c
->flt
== 2)
1258 fprintf(f
, "d_%lf", c
->bits
.d
);
1260 fprintf(f
, "%"PRIi64
, c
->bits
.i
);
1266 printref(Ref r
, Fn
*fn
, FILE *f
)
1274 fprintf(f
, "R%d", r
.val
);
1276 fprintf(f
, "%%%s", fn
->tmp
[r
.val
].name
);
1280 fprintf(f
, "UNDEF");
1282 printcon(&fn
->con
[r
.val
], f
);
1285 fprintf(f
, "S%d", rsval(r
));
1288 fprintf(f
, "%04x", r
.val
);
1291 fprintf(f
, ":%s", typ
[r
.val
].name
);
1295 m
= &fn
->mem
[r
.val
];
1297 if (m
->offset
.type
!= CUndef
) {
1298 printcon(&m
->offset
, f
);
1301 if (!req(m
->base
, R
)) {
1304 printref(m
->base
, fn
, f
);
1307 if (!req(m
->index
, R
)) {
1310 fprintf(f
, "%d * ", m
->scale
);
1311 printref(m
->index
, fn
, f
);
1316 fprintf(f
, "%d", rsval(r
));
1325 printfn(Fn
*fn
, FILE *f
)
1327 static char ktoc
[] = "wlsd";
1328 static char *jtoa
[NJmp
] = {
1329 #define X(j) [J##j] = #j,
1338 fprintf(f
, "function $%s() {\n", fn
->name
);
1339 for (b
=fn
->start
; b
; b
=b
->link
) {
1340 fprintf(f
, "@%s\n", b
->name
);
1341 for (p
=b
->phi
; p
; p
=p
->link
) {
1343 printref(p
->to
, fn
, f
);
1344 fprintf(f
, " =%c phi ", ktoc
[p
->cls
]);
1347 fprintf(f
, "@%s ", p
->blk
[n
]->name
);
1348 printref(p
->arg
[n
], fn
, f
);
1349 if (n
== p
->narg
-1) {
1356 for (i
=b
->ins
; i
<&b
->ins
[b
->nins
]; i
++) {
1358 if (!req(i
->to
, R
)) {
1359 printref(i
->to
, fn
, f
);
1360 fprintf(f
, " =%c ", ktoc
[i
->cls
]);
1362 assert(optab
[i
->op
].name
);
1363 fprintf(f
, "%s", optab
[i
->op
].name
);
1375 fputc(ktoc
[i
->cls
], f
);
1377 if (!req(i
->arg
[0], R
)) {
1379 printref(i
->arg
[0], fn
, f
);
1381 if (!req(i
->arg
[1], R
)) {
1383 printref(i
->arg
[1], fn
, f
);
1387 switch (b
->jmp
.type
) {
1398 fprintf(f
, "\t%s", jtoa
[b
->jmp
.type
]);
1399 if (b
->jmp
.type
!= Jret0
|| !req(b
->jmp
.arg
, R
)) {
1401 printref(b
->jmp
.arg
, fn
, f
);
1403 if (b
->jmp
.type
== Jretc
)
1404 fprintf(f
, ", :%s", typ
[fn
->retty
].name
);
1408 fprintf(f
, "\thlt\n");
1411 if (b
->s1
!= b
->link
)
1412 fprintf(f
, "\tjmp @%s\n", b
->s1
->name
);
1415 fprintf(f
, "\t%s ", jtoa
[b
->jmp
.type
]);
1416 if (b
->jmp
.type
== Jjnz
) {
1417 printref(b
->jmp
.arg
, fn
, f
);
1420 assert(b
->s1
&& b
->s2
);
1421 fprintf(f
, "@%s, @%s\n", b
->s1
->name
, b
->s2
->name
);