6 Ke
= -2, /* Erroneous mode */
7 Km
= Kl
, /* Memory pointer */
11 #define O(op, t, cf) [O##op]={#op, t, cf},
76 static char *kwmap
[Ntok
] = {
105 BMask
= 8191, /* for blocks hash */
107 K
= 3233235, /* found using tools/lexh.c */
111 static char lexh
[1 << (32-M
)];
128 static Blk
*blkh
[BMask
+1];
139 fprintf(stderr
, "%s:%d: ", inpath
, lnum
);
140 vfprintf(stderr
, s
, ap
);
141 fprintf(stderr
, "\n");
155 for (i
=0; i
<NPubOp
; ++i
)
157 kwmap
[i
] = optab
[i
].name
;
158 assert(Ntok
<= CHAR_MAX
);
159 for (i
=0; i
<Ntok
; ++i
)
161 h
= hash(kwmap
[i
])*K
>> M
;
162 assert(lexh
[h
] == Txxx
);
180 n
= 10*n
+ (c
- '0');
182 } while ('0' <= c
&& c
<= '9');
186 return *(int64_t *)&n
;
192 static char tok
[NString
];
219 if (fscanf(inf
, "_%f", &tokval
.flts
) != 1)
223 if (fscanf(inf
, "_%lf", &tokval
.fltd
) != 1)
239 while ((c
=fgetc(inf
)) != '\n' && c
!= EOF
)
246 if (isdigit(c
) || c
== '-' || c
== '+') {
248 tokval
.num
= getint();
252 tokval
.str
= vnew(0, 1, Pfn
);
257 err("unterminated string");
258 vgrow(&tokval
.str
, i
+1);
259 if (c
== '"' && !esc
) {
263 esc
= (c
== '\\' && !esc
);
268 Alpha
: c
= fgetc(inf
);
269 if (!isalpha(c
) && c
!= '.' && c
!= '_')
270 err("invalid character %c (%d)", c
, c
);
274 err("identifier too long");
277 } while (isalpha(c
) || c
== '$' || c
== '.' || c
== '_' || isdigit(c
));
284 t
= lexh
[hash(tok
)*K
>> M
];
285 if (t
== Txxx
|| strcmp(kwmap
[t
], tok
) != 0) {
286 err("unknown keyword %s", tok
);
315 while ((t
= next()) == Tnl
)
323 static char *ttoa
[] = {
334 char buf
[128], *s1
, *s2
;
340 s1
= ttoa
[t
] ? ttoa
[t
] : "??";
341 s2
= ttoa
[t1
] ? ttoa
[t1
] : "??";
342 sprintf(buf
, "%s expected, got %s instead", s1
, s2
);
351 for (t
=Tmp0
; t
<curf
->ntmp
; t
++)
352 if (strcmp(v
, curf
->tmp
[t
].name
) == 0)
355 strcpy(curf
->tmp
[t
].name
, v
);
365 memset(&c
, 0, sizeof c
);
368 return tmpref(tokval
.str
);
371 c
.bits
.i
= tokval
.num
;
375 c
.bits
.s
= tokval
.flts
;
380 c
.bits
.d
= tokval
.fltd
;
385 c
.label
= intern(tokval
.str
);
387 for (i
=0; i
<curf
->ncon
; i
++)
388 if (curf
->con
[i
].type
== c
.type
389 && curf
->con
[i
].bits
.i
== c
.bits
.i
390 && curf
->con
[i
].label
== c
.label
)
392 vgrow(&curf
->con
, ++curf
->ncon
);
404 if (strcmp(tokval
.str
, typ
[i
].name
) == 0)
406 err("undefined type :%s", tokval
.str
);
414 err("invalid class specifier");
416 *tyn
= findtyp(ntyp
);
432 int k
, ty
, env
, hasenv
;
437 while (peek() != Trparen
&& peek() != Tdots
) {
438 if (curi
- insb
>= NIns
)
439 err("too many instructions (1)");
440 env
= peek() == Tenv
;
448 err("invalid argument");
450 err("only one environment allowed");
451 if (!arg
&& rtype(r
) != RTmp
)
452 err("invalid function parameter");
455 *curi
= (Ins
){Oargc
, R
, {TYPE(ty
), r
}, Kl
};
457 *curi
= (Ins
){Oparc
, r
, {TYPE(ty
)}, Kl
};
460 *curi
= (Ins
){Oarge
, R
, {r
}, k
};
462 *curi
= (Ins
){Opare
, r
, {R
}, k
};
465 *curi
= (Ins
){Oarg
, R
, {r
}, k
};
467 *curi
= (Ins
){Opar
, r
, {R
}, k
};
470 if (peek() == Trparen
)
474 if (next() == Tdots
) {
487 h
= hash(name
) & BMask
;
488 for (b
=blkh
[h
]; b
; b
=b
->dlink
)
489 if (strcmp(b
->name
, name
) == 0)
493 strcpy(b
->name
, name
);
502 curb
->nins
= curi
- insb
;
503 idup(&curb
->ins
, insb
, curb
->nins
);
511 Ref arg
[NPred
] = {R
};
519 if (ps
== PLbl
&& t
!= Tlbl
&& t
!= Trbrace
)
520 err("label or } expected");
526 /* operations without result */
532 err("label, instruction or jump expected");
538 b
= findblk(tokval
.str
);
539 if (curb
&& curb
->jmp
.type
== Jxxx
) {
541 curb
->jmp
.type
= Jjmp
;
544 if (b
->jmp
.type
!= Jxxx
)
545 err("multiple definitions of block @%s", b
->name
);
552 curb
->jmp
.type
= (int[]){
558 curb
->jmp
.type
= Jret0
;
562 err("invalid return value");
567 curb
->jmp
.type
= Jjmp
;
570 curb
->jmp
.type
= Jjnz
;
573 err("invalid argument for jnz jump");
578 curb
->s1
= findblk(tokval
.str
);
579 if (curb
->jmp
.type
!= Jjmp
) {
582 curb
->s2
= findblk(tokval
.str
);
584 if (curb
->s1
== curf
->start
|| curb
->s2
== curf
->start
)
585 err("invalid jump to the start node");
591 r
= tmpref(tokval
.str
);
597 if (ps
!= PPhi
|| curb
== curf
->start
)
598 err("unexpected phi instruction");
615 if (op
>= Tloadw
&& op
<= Tloadd
)
617 if (op
== Talloc1
|| op
== Talloc2
)
620 err("size class must be w, l, s, or d");
622 err("invalid instruction");
627 err("too many arguments");
630 blk
[i
] = findblk(tokval
.str
);
634 err("invalid instruction argument");
640 err(", or end of line expected");
646 if (curi
- insb
>= NIns
)
647 err("too many instructions (2)");
651 curi
->arg
[0] = arg
[0];
652 curi
->arg
[1] = arg
[1];
656 phi
= alloc(sizeof *phi
);
659 memcpy(phi
->arg
, arg
, i
* sizeof arg
[0]);
660 memcpy(phi
->blk
, blk
, i
* sizeof blk
[0]);
669 usecheck(Ref r
, int k
, Fn
*fn
)
671 return rtype(r
) != RTmp
|| fn
->tmp
[r
.val
].cls
== k
672 || (fn
->tmp
[r
.val
].cls
== Kl
&& k
== Kw
);
688 bsinit(pb
, fn
->nblk
);
689 bsinit(ppb
, fn
->nblk
);
690 for (b
=fn
->start
; b
; b
=b
->link
) {
691 for (p
=b
->phi
; p
; p
=p
->link
)
692 fn
->tmp
[p
->to
.val
].cls
= p
->cls
;
693 for (i
=b
->ins
; i
<&b
->ins
[b
->nins
]; i
++)
694 if (rtype(i
->to
) == RTmp
) {
695 t
= &fn
->tmp
[i
->to
.val
];
696 if (clsmerge(&t
->cls
, i
->cls
))
697 err("temporary %%%s is assigned with"
698 " multiple types", t
->name
);
701 for (b
=fn
->start
; b
; b
=b
->link
) {
703 for (n
=0; n
<b
->npred
; n
++)
704 bsset(pb
, b
->pred
[n
]->id
);
705 for (p
=b
->phi
; p
; p
=p
->link
) {
707 t
= &fn
->tmp
[p
->to
.val
];
708 for (n
=0; n
<p
->narg
; n
++) {
710 if (bshas(ppb
, p
->blk
[n
]->id
))
711 err("multiple entries for @%s in phi %%%s",
712 p
->blk
[n
]->name
, t
->name
);
713 if (!usecheck(p
->arg
[n
], k
, fn
))
714 err("invalid type for operand %%%s in phi %%%s",
715 fn
->tmp
[p
->arg
[n
].val
].name
, t
->name
);
716 bsset(ppb
, p
->blk
[n
]->id
);
718 if (!bsequal(pb
, ppb
))
719 err("predecessors not matched in phi %%%s", t
->name
);
721 for (i
=b
->ins
; i
<&b
->ins
[b
->nins
]; i
++)
722 for (n
=0; n
<2; n
++) {
723 k
= optab
[i
->op
].argcls
[n
][i
->cls
];
727 err("invalid instruction type in %s",
729 if (rtype(r
) == RType
)
731 if (rtype(r
) != -1 && k
== Kx
)
732 err("no %s operand expected in %s",
733 n
== 1 ? "second" : "first",
735 if (rtype(r
) == -1 && k
!= Kx
)
736 err("missing %s operand in %s",
737 n
== 1 ? "second" : "first",
739 if (!usecheck(r
, k
, fn
))
740 err("invalid type for %s operand %%%s in %s",
741 n
== 1 ? "second" : "first",
742 t
->name
, optab
[i
->op
].name
);
745 if (isret(b
->jmp
.type
)) {
746 if (b
->jmp
.type
== Jretc
) {
747 if (!usecheck(r
, Kl
, fn
))
749 } else if (!usecheck(r
, b
->jmp
.type
-Jretw
, fn
))
752 if (b
->jmp
.type
== Jjnz
&& !usecheck(r
, Kw
, fn
))
754 err("invalid type for jump argument %%%s in block @%s",
755 fn
->tmp
[r
.val
].name
, b
->name
);
756 if (b
->s1
&& b
->s1
->jmp
.type
== Jxxx
)
757 err("block @%s is used undefined", b
->s1
->name
);
758 if (b
->s2
&& b
->s2
->jmp
.type
== Jxxx
)
759 err("block @%s is used undefined", b
->s2
->name
);
773 curf
= alloc(sizeof *curf
);
775 curf
->ncon
= 1; /* first constant must be 0 */
776 curf
->tmp
= vnew(curf
->ntmp
, sizeof curf
->tmp
[0], Pfn
);
777 curf
->con
= vnew(curf
->ncon
, sizeof curf
->con
[0], Pfn
);
778 for (i
=0; i
<Tmp0
; ++i
)
779 if (T
.fpr0
<= i
&& i
< T
.fpr0
+ T
.nfpr
)
783 curf
->con
[0].type
= CBits
;
784 curf
->export
= export
;
785 blink
= &curf
->start
;
788 rcls
= parsecls(&curf
->retty
);
792 err("function name expected");
793 strcpy(curf
->name
, tokval
.str
);
794 curf
->vararg
= parserefl(0);
795 if (nextnl() != Tlbrace
)
796 err("function body must start with {");
802 err("empty function");
803 if (curb
->jmp
.type
== Jxxx
)
804 err("last block misses jump");
805 curf
->mem
= vnew(0, sizeof curf
->mem
[0], Pfn
);
809 for (b
=0; b
; b
=b
->link
)
810 b
->dlink
= 0; /* was trashed by findblk() */
811 for (i
=0; i
<BMask
+1; ++i
)
818 parsefields(Field
*fld
, Typ
*ty
, int t
)
821 int n
, c
, a
, al
, type
;
827 while (t
!= Trbrace
) {
830 default: err("invalid type member specifier");
831 case Td
: type
= Fd
; s
= 8; a
= 3; break;
832 case Tl
: type
= Fl
; s
= 8; a
= 3; break;
833 case Ts
: type
= Fs
; s
= 4; a
= 2; break;
834 case Tw
: type
= Fw
; s
= 4; a
= 2; break;
835 case Th
: type
= Fh
; s
= 2; a
= 1; break;
836 case Tb
: type
= Fb
; s
= 1; a
= 0; break;
839 ty1
= &typ
[findtyp(ntyp
-1)];
865 for (; c
>0 && n
<NField
; c
--, n
++) {
874 err(", or } expected");
879 ty
->size
= (sz
+ a
- 1) & -a
;
890 /* be careful if extending the syntax
891 * to handle nested types, any pointer
892 * held to typ[] might be invalidated!
899 if (nextnl() != Ttyp
|| nextnl() != Teq
)
900 err("type name and then = expected");
901 strcpy(ty
->name
, tokval
.str
);
904 if (nextnl() != Tint
)
905 err("alignment expected");
906 for (al
=0; tokval
.num
/= 2; al
++)
912 err("type body must start with {");
916 ty
->size
= tokval
.num
;
918 err("dark types need alignment");
919 if (nextnl() != Trbrace
)
924 ty
->fields
= vnew(1, sizeof ty
->fields
[0], Pheap
);
928 err("invalid union member");
929 vgrow(&ty
->fields
, n
+1);
930 parsefields(ty
->fields
[n
++], ty
, nextnl());
932 } while (t
!= Trbrace
);
934 parsefields(ty
->fields
[n
++], ty
, t
);
944 d
->u
.ref
.nam
= tokval
.str
;
950 err("invalid token after offset in ref");
951 d
->u
.ref
.off
= tokval
.num
;
959 d
->u
.str
= tokval
.str
;
963 parsedat(void cb(Dat
*), int export
)
974 if (nextnl() != Tglo
|| nextnl() != Teq
)
975 err("data name, then = expected");
976 strcpy(s
, tokval
.str
);
979 if (nextnl() != Tint
)
980 err("alignment expected");
982 d
.u
.num
= tokval
.num
;
991 err("expected data contents in { .. }");
994 default: err("invalid size specifier %c in data", tokval
.chr
);
995 case Trbrace
: goto Done
;
996 case Tl
: d
.type
= DL
; break;
997 case Tw
: d
.type
= DW
; break;
998 case Th
: d
.type
= DH
; break;
999 case Tb
: d
.type
= DB
; break;
1000 case Ts
: d
.type
= DW
; break;
1001 case Td
: d
.type
= DL
; break;
1002 case Tz
: d
.type
= DZ
; break;
1008 memset(&d
.u
, 0, sizeof d
.u
);
1010 d
.u
.flts
= tokval
.flts
;
1011 else if (t
== Tfltd
)
1012 d
.u
.fltd
= tokval
.fltd
;
1014 d
.u
.num
= tokval
.num
;
1020 err("constant literal expected");
1023 } while (t
== Tint
|| t
== Tflts
|| t
== Tfltd
);
1027 err(", or } expected");
1035 parse(FILE *f
, char *path
, void data(Dat
*), void func(Fn
*))
1045 typ
= vnew(0, sizeof typ
[0], Pheap
);
1050 err("top-level definition expected");
1056 func(parsefn(export
));
1059 else if (t
== Tdata
) {
1061 parsedat(data
, export
);
1065 err("export can only qualify data and function");
1077 printcon(Con
*c
, FILE *f
)
1083 fprintf(f
, "$%s", str(c
->label
));
1085 fprintf(f
, "%+"PRIi64
, c
->bits
.i
);
1089 fprintf(f
, "s_%f", c
->bits
.s
);
1090 else if (c
->flt
== 2)
1091 fprintf(f
, "d_%lf", c
->bits
.d
);
1093 fprintf(f
, "%"PRIi64
, c
->bits
.i
);
1099 printref(Ref r
, Fn
*fn
, FILE *f
)
1107 fprintf(f
, "R%d", r
.val
);
1109 fprintf(f
, "%%%s", fn
->tmp
[r
.val
].name
);
1112 printcon(&fn
->con
[r
.val
], f
);
1115 fprintf(f
, "S%d", (r
.val
&(1<<28)) ? r
.val
-(1<<29) : r
.val
);
1118 fprintf(f
, "%04x", r
.val
);
1121 fprintf(f
, ":%s", typ
[r
.val
].name
);
1125 m
= &fn
->mem
[r
.val
];
1127 if (m
->offset
.type
!= CUndef
) {
1128 printcon(&m
->offset
, f
);
1131 if (!req(m
->base
, R
)) {
1134 printref(m
->base
, fn
, f
);
1137 if (!req(m
->index
, R
)) {
1140 fprintf(f
, "%d * ", m
->scale
);
1141 printref(m
->index
, fn
, f
);
1149 printfn(Fn
*fn
, FILE *f
)
1151 static char ktoc
[] = "wlsd";
1152 static char *jtoa
[NJmp
] = {
1153 #define X(j) [J##j] = #j,
1163 fprintf(f
, "export ");
1164 fprintf(f
, "function $%s() {\n", fn
->name
);
1165 for (b
=fn
->start
; b
; b
=b
->link
) {
1166 fprintf(f
, "@%s\n", b
->name
);
1167 for (p
=b
->phi
; p
; p
=p
->link
) {
1169 printref(p
->to
, fn
, f
);
1170 fprintf(f
, " =%c phi ", ktoc
[p
->cls
]);
1173 fprintf(f
, "@%s ", p
->blk
[n
]->name
);
1174 printref(p
->arg
[n
], fn
, f
);
1175 if (n
== p
->narg
-1) {
1182 for (i
=b
->ins
; i
<&b
->ins
[b
->nins
]; i
++) {
1184 if (!req(i
->to
, R
)) {
1185 printref(i
->to
, fn
, f
);
1186 fprintf(f
, " =%c ", ktoc
[i
->cls
]);
1188 assert(optab
[i
->op
].name
);
1189 fprintf(f
, "%s", optab
[i
->op
].name
);
1201 fputc(ktoc
[i
->cls
], f
);
1203 if (!req(i
->arg
[0], R
)) {
1205 printref(i
->arg
[0], fn
, f
);
1207 if (!req(i
->arg
[1], R
)) {
1209 printref(i
->arg
[1], fn
, f
);
1213 switch (b
->jmp
.type
) {
1220 fprintf(f
, "\t%s", jtoa
[b
->jmp
.type
]);
1221 if (b
->jmp
.type
!= Jret0
|| !req(b
->jmp
.arg
, R
)) {
1223 printref(b
->jmp
.arg
, fn
, f
);
1225 if (b
->jmp
.type
== Jretc
)
1226 fprintf(f
, ", :%s", typ
[fn
->retty
].name
);
1230 if (b
->s1
!= b
->link
)
1231 fprintf(f
, "\tjmp @%s\n", b
->s1
->name
);
1234 fprintf(f
, "\t%s ", jtoa
[b
->jmp
.type
]);
1235 if (b
->jmp
.type
== Jjnz
) {
1236 printref(b
->jmp
.arg
, fn
, f
);
1239 fprintf(f
, "@%s, @%s\n", b
->s1
->name
, b
->s2
->name
);