6 Ke
= -2, /* Erroneous mode */
7 Km
= Kl
, /* Memory pointer (for x64) */
10 OpDesc opdesc
[NOp
] = {
11 #define A(a,b,c,d) {[Kw]=K##a, [Kl]=K##b, [Ks]=K##c, [Kd]=K##d}
13 /* NAME NM ARGCLS0 ARGCLS1 SF LF FLD*/
14 [Oadd
] = { "add", 2, {A(w
,l
,s
,d
), A(w
,l
,s
,d
)}, 1, 0, 1 },
15 [Osub
] = { "sub", 2, {A(w
,l
,s
,d
), A(w
,l
,s
,d
)}, 1, 0, 1 },
16 [Odiv
] = { "div", 2, {A(w
,l
,s
,d
), A(w
,l
,s
,d
)}, 0, 0, 1 },
17 [Orem
] = { "rem", 2, {A(w
,l
,e
,e
), A(w
,l
,e
,e
)}, 0, 0, 1 },
18 [Oudiv
] = { "udiv", 2, {A(w
,l
,e
,e
), A(w
,l
,e
,e
)}, 0, 0, 1 },
19 [Ourem
] = { "urem", 2, {A(w
,l
,e
,e
), A(w
,l
,e
,e
)}, 0, 0, 1 },
20 [Omul
] = { "mul", 2, {A(w
,l
,s
,d
), A(w
,l
,s
,d
)}, 0, 0, 1 },
21 [Oand
] = { "and", 2, {A(w
,l
,e
,e
), A(w
,l
,e
,e
)}, 1, 0, 1 },
22 [Oor
] = { "or", 2, {A(w
,l
,e
,e
), A(w
,l
,e
,e
)}, 1, 0, 1 },
23 [Oxor
] = { "xor", 2, {A(w
,l
,e
,e
), A(w
,l
,e
,e
)}, 1, 0, 1 },
24 [Osar
] = { "sar", 1, {A(w
,l
,e
,e
), A(w
,w
,e
,e
)}, 1, 0, 1 },
25 [Oshr
] = { "shr", 1, {A(w
,l
,e
,e
), A(w
,w
,e
,e
)}, 1, 0, 1 },
26 [Oshl
] = { "shl", 1, {A(w
,l
,e
,e
), A(w
,w
,e
,e
)}, 1, 0, 1 },
27 [Ostored
] = { "stored", 0, {A(d
,e
,e
,e
), A(m
,e
,e
,e
)}, 0, 1, 0 },
28 [Ostores
] = { "stores", 0, {A(s
,e
,e
,e
), A(m
,e
,e
,e
)}, 0, 1, 0 },
29 [Ostorel
] = { "storel", 0, {A(l
,e
,e
,e
), A(m
,e
,e
,e
)}, 0, 1, 0 },
30 [Ostorew
] = { "storew", 0, {A(w
,e
,e
,e
), A(m
,e
,e
,e
)}, 0, 1, 0 },
31 [Ostoreh
] = { "storeh", 0, {A(w
,e
,e
,e
), A(m
,e
,e
,e
)}, 0, 1, 0 },
32 [Ostoreb
] = { "storeb", 0, {A(w
,e
,e
,e
), A(m
,e
,e
,e
)}, 0, 1, 0 },
33 [Oload
] = { "load", 0, {A(m
,m
,m
,m
), A(x
,x
,x
,x
)}, 0, 1, 0 },
34 [Oloadsw
] = { "loadsw", 0, {A(m
,m
,e
,e
), A(x
,x
,e
,e
)}, 0, 1, 0 },
35 [Oloaduw
] = { "loaduw", 0, {A(m
,m
,e
,e
), A(x
,x
,e
,e
)}, 0, 1, 0 },
36 [Oloadsh
] = { "loadsh", 0, {A(m
,m
,e
,e
), A(x
,x
,e
,e
)}, 0, 1, 0 },
37 [Oloaduh
] = { "loaduh", 0, {A(m
,m
,e
,e
), A(x
,x
,e
,e
)}, 0, 1, 0 },
38 [Oloadsb
] = { "loadsb", 0, {A(m
,m
,e
,e
), A(x
,x
,e
,e
)}, 0, 1, 0 },
39 [Oloadub
] = { "loadub", 0, {A(m
,m
,e
,e
), A(x
,x
,e
,e
)}, 0, 1, 0 },
40 [Oextsw
] = { "extsw", 0, {A(e
,w
,e
,e
), A(e
,x
,e
,e
)}, 0, 1, 1 },
41 [Oextuw
] = { "extuw", 0, {A(e
,w
,e
,e
), A(e
,x
,e
,e
)}, 0, 1, 1 },
42 [Oextsh
] = { "extsh", 0, {A(w
,w
,e
,e
), A(x
,x
,e
,e
)}, 0, 1, 1 },
43 [Oextuh
] = { "extuh", 0, {A(w
,w
,e
,e
), A(x
,x
,e
,e
)}, 0, 1, 1 },
44 [Oextsb
] = { "extsb", 0, {A(w
,w
,e
,e
), A(x
,x
,e
,e
)}, 0, 1, 1 },
45 [Oextub
] = { "extub", 0, {A(w
,w
,e
,e
), A(x
,x
,e
,e
)}, 0, 1, 1 },
46 [Oexts
] = { "exts", 0, {A(e
,e
,e
,s
), A(e
,e
,e
,x
)}, 0, 1, 1 },
47 [Otruncd
] = { "truncd", 0, {A(e
,e
,d
,e
), A(e
,e
,x
,e
)}, 0, 1, 1 },
48 [Ostosi
] = { "stosi", 0, {A(s
,s
,e
,e
), A(x
,x
,e
,e
)}, 0, 1, 1 },
49 [Odtosi
] = { "dtosi", 0, {A(d
,d
,e
,e
), A(x
,x
,e
,e
)}, 0, 1, 1 },
50 [Oswtof
] = { "swtof", 0, {A(e
,e
,w
,w
), A(e
,e
,x
,x
)}, 0, 1, 1 },
51 [Osltof
] = { "sltof", 0, {A(e
,e
,l
,l
), A(e
,e
,x
,x
)}, 0, 1, 1 },
52 [Ocast
] = { "cast", 0, {A(s
,d
,w
,l
), A(x
,x
,x
,x
)}, 0, 1, 1 },
53 [Ocopy
] = { "copy", 1, {A(w
,l
,s
,d
), A(x
,x
,x
,x
)}, 0, 1, 0 },
54 [Onop
] = { "nop", 0, {A(x
,x
,x
,x
), A(x
,x
,x
,x
)}, 0, 1, 0 },
55 [Oswap
] = { "swap", 2, {A(w
,l
,s
,d
), A(w
,l
,s
,d
)}, 0, 0, 0 },
56 [Osign
] = { "sign", 0, {A(w
,l
,e
,e
), A(x
,x
,e
,e
)}, 0, 0, 0 },
57 [Osalloc
] = { "salloc", 0, {A(e
,l
,e
,e
), A(e
,x
,e
,e
)}, 0, 0, 0 },
58 [Oxidiv
] = { "xidiv", 1, {A(w
,l
,e
,e
), A(x
,x
,e
,e
)}, 0, 0, 0 },
59 [Oxdiv
] = { "xdiv", 1, {A(w
,l
,e
,e
), A(x
,x
,e
,e
)}, 0, 0, 0 },
60 [Oxcmp
] = { "xcmp", 1, {A(w
,l
,s
,d
), A(w
,l
,s
,d
)}, 1, 0, 0 },
61 [Oxtest
] = { "xtest", 1, {A(w
,l
,e
,e
), A(w
,l
,e
,e
)}, 1, 0, 0 },
62 [Oaddr
] = { "addr", 0, {A(m
,m
,e
,e
), A(x
,x
,e
,e
)}, 0, 1, 0 },
63 [Opar
] = { "par", 0, {A(x
,x
,x
,x
), A(x
,x
,x
,x
)}, 0, 0, 0 },
64 [Opare
] = { "pare", 0, {A(x
,x
,x
,x
), A(x
,x
,x
,x
)}, 0, 0, 0 },
65 [Oparc
] = { "parc", 0, {A(e
,x
,e
,e
), A(e
,x
,e
,e
)}, 0, 0, 0 },
66 [Oarg
] = { "arg", 0, {A(w
,l
,s
,d
), A(x
,x
,x
,x
)}, 0, 0, 0 },
67 [Oarge
] = { "arge", 0, {A(w
,l
,s
,d
), A(x
,x
,x
,x
)}, 0, 0, 0 },
68 [Oargc
] = { "argc", 0, {A(e
,x
,e
,e
), A(e
,l
,e
,e
)}, 0, 0, 0 },
69 [Ocall
] = { "call", 0, {A(m
,m
,m
,m
), A(x
,x
,x
,x
)}, 0, 0, 0 },
70 [Ovacall
] = { "vacall", 0, {A(m
,m
,m
,m
), A(x
,x
,x
,x
)}, 0, 0, 0 },
71 [Oxsetnp
] = { "xsetnp", 0, {A(x
,x
,e
,e
), A(x
,x
,e
,e
)}, 0, 0, 0 },
72 [Oxsetp
] = { "xsetp", 0, {A(x
,x
,e
,e
), A(x
,x
,e
,e
)}, 0, 0, 0 },
73 [Oalloc
] = { "alloc4", 1, {A(e
,l
,e
,e
), A(e
,x
,e
,e
)}, 0, 0, 0 },
74 [Oalloc
+1] = { "alloc8", 1, {A(e
,l
,e
,e
), A(e
,x
,e
,e
)}, 0, 0, 0 },
75 [Oalloc
+2] = { "alloc16", 1, {A(e
,l
,e
,e
), A(e
,x
,e
,e
)}, 0, 0, 0 },
76 [Ovaarg
] = { "vaarg", 0, {A(m
,m
,m
,m
), A(x
,x
,x
,x
)}, 0, 0, 0 },
77 [Ovastart
] = { "vastart", 0, {A(m
,e
,e
,e
), A(x
,e
,e
,e
)}, 0, 0, 0 },
79 [Ocmpw+IC##c] = { "c" #c "w", 0, {A(w,w,e,e), A(w,w,e,e)}, 1, 0, 1 }, \
80 [Ocmpl+IC##c] = { "c" #c "l", 0, {A(l,l,e,e), A(l,l,e,e)}, 1, 0, 1 }, \
81 [Oxset+IC##c] = { "xset" #c, 0, {A(x,x,e,e), A(x,x,e,e)}, 0, 1, 0 },
85 [Ocmps+FC##c] = { "c" #c "s", 0, {A(s,s,e,e), A(s,s,e,e)}, 1, 0, 1 }, \
86 [Ocmpd+FC##c] = { "c" #c "d", 0, {A(d,d,e,e), A(d,d,e,e)}, 1, 0, 1 },
154 static char *kwmap
[Ntok
] = {
159 [Talloc1
] = "alloc1",
160 [Talloc2
] = "alloc2",
167 [Texport
] = "export",
168 [Tfunc
] = "function",
183 BMask
= 8191, /* for blocks hash */
185 K
= 3233235, /* found using tools/lexh.c */
189 static char lexh
[1 << (32-M
)];
206 static Blk
*blkh
[BMask
+1];
217 fprintf(stderr
, "%s:%d: ", inpath
, lnum
);
218 vfprintf(stderr
, s
, ap
);
219 fprintf(stderr
, "\n");
224 static inline uint32_t
244 for (i
=0; i
<NPubOp
; ++i
)
246 kwmap
[i
] = opdesc
[i
].name
;
247 assert(Ntok
<= CHAR_MAX
);
248 for (i
=0; i
<Ntok
; ++i
)
250 h
= hash(kwmap
[i
])*K
>> M
;
251 assert(lexh
[h
] == Txxx
);
268 case '+': c
= fgetc(inf
);
271 n
= 10*n
+ (c
- '0');
273 } while ('0' <= c
&& c
<= '9');
277 return *(int64_t *)&n
;
283 static char tok
[NString
];
310 if (fscanf(inf
, "_%f", &tokval
.flts
) != 1)
314 if (fscanf(inf
, "_%lf", &tokval
.fltd
) != 1)
330 while ((c
=fgetc(inf
)) != '\n' && c
!= EOF
)
336 if (isdigit(c
) || c
== '-' || c
== '+') {
338 tokval
.num
= getint();
342 tokval
.str
= vnew(0, 1, Pfn
);
347 err("unterminated string");
348 vgrow(&tokval
.str
, i
+1);
349 if (c
== '"' && !esc
) {
353 esc
= (c
== '\\' && !esc
);
358 Alpha
: c
= fgetc(inf
);
359 if (!isalpha(c
) && c
!= '.' && c
!= '_')
360 err("invalid character %c (%d)", c
, c
);
364 err("identifier too long");
367 } while (isalpha(c
) || c
== '$' || c
== '.' || c
== '_' || isdigit(c
));
374 t
= lexh
[hash(tok
)*K
>> M
];
375 if (t
== Txxx
|| strcmp(kwmap
[t
], tok
) != 0) {
376 err("unknown keyword %s", tok
);
405 while ((t
= next()) == Tnl
)
413 static char *ttoa
[] = {
424 char buf
[128], *s1
, *s2
;
430 s1
= ttoa
[t
] ? ttoa
[t
] : "??";
431 s2
= ttoa
[t1
] ? ttoa
[t1
] : "??";
432 sprintf(buf
, "%s expected, got %s instead", s1
, s2
);
441 for (t
=Tmp0
; t
<curf
->ntmp
; t
++)
442 if (strcmp(v
, curf
->tmp
[t
].name
) == 0)
445 strcpy(curf
->tmp
[t
].name
, v
);
455 memset(&c
, 0, sizeof c
);
458 return tmpref(tokval
.str
);
461 c
.bits
.i
= tokval
.num
;
465 c
.bits
.s
= tokval
.flts
;
470 c
.bits
.d
= tokval
.fltd
;
475 strcpy(c
.label
, tokval
.str
);
477 for (i
=0; i
<curf
->ncon
; i
++)
478 if (curf
->con
[i
].type
== c
.type
479 && curf
->con
[i
].bits
.i
== c
.bits
.i
480 && strcmp(curf
->con
[i
].label
, c
.label
) == 0)
482 vgrow(&curf
->con
, ++curf
->ncon
);
494 if (strcmp(tokval
.str
, typ
[i
].name
) == 0)
496 err("undefined type :%s", tokval
.str
);
504 err("invalid class specifier");
506 *tyn
= findtyp(ntyp
);
522 int k
, ty
, env
, hasenv
;
527 while (peek() != Trparen
&& peek() != Tdots
) {
528 if (curi
- insb
>= NIns
)
529 err("too many instructions (1)");
530 env
= peek() == Tenv
;
536 err("invalid argument");
538 err("only one environment allowed");
540 err("environment must be of type l");
541 if (!arg
&& rtype(r
) != RTmp
)
542 err("invalid function parameter");
545 *curi
= (Ins
){Oargc
, R
, {TYPE(ty
), r
}, Kl
};
547 *curi
= (Ins
){Oparc
, r
, {TYPE(ty
)}, Kl
};
550 *curi
= (Ins
){Oarge
, R
, {r
}, k
};
552 *curi
= (Ins
){Opare
, r
, {R
}, k
};
555 *curi
= (Ins
){Oarg
, R
, {r
}, k
};
557 *curi
= (Ins
){Opar
, r
, {R
}, k
};
560 if (peek() == Trparen
)
564 if (next() == Tdots
) {
577 h
= hash(name
) & BMask
;
578 for (b
=blkh
[h
]; b
; b
=b
->dlink
)
579 if (strcmp(b
->name
, name
) == 0)
583 strcpy(b
->name
, name
);
592 curb
->nins
= curi
- insb
;
593 idup(&curb
->ins
, insb
, curb
->nins
);
601 Ref arg
[NPred
] = {R
};
609 if (ps
== PLbl
&& t
!= Tlbl
&& t
!= Trbrace
)
610 err("label or } expected");
616 /* operations without result */
622 err("label, instruction or jump expected");
628 b
= findblk(tokval
.str
);
629 if (curb
&& curb
->jmp
.type
== Jxxx
) {
631 curb
->jmp
.type
= Jjmp
;
634 if (b
->jmp
.type
!= Jxxx
)
635 err("multiple definitions of block @%s", b
->name
);
642 curb
->jmp
.type
= (int[]){
648 curb
->jmp
.type
= Jret0
;
652 err("invalid return value");
657 curb
->jmp
.type
= Jjmp
;
660 curb
->jmp
.type
= Jjnz
;
663 err("invalid argument for jnz jump");
668 curb
->s1
= findblk(tokval
.str
);
669 if (curb
->jmp
.type
!= Jjmp
) {
672 curb
->s2
= findblk(tokval
.str
);
674 if (curb
->s1
== curf
->start
|| curb
->s2
== curf
->start
)
675 err("invalid jump to the start node");
681 r
= tmpref(tokval
.str
);
687 if (ps
!= PPhi
|| curb
== curf
->start
)
688 err("unexpected phi instruction");
705 if (op
>= Tloadw
&& op
<= Tloadd
)
707 if (op
== Talloc1
|| op
== Talloc2
)
710 err("size class must be w, l, s, or d");
712 err("invalid instruction");
717 err("too many arguments");
720 blk
[i
] = findblk(tokval
.str
);
724 err("invalid instruction argument");
730 err(", or end of line expected");
736 if (curi
- insb
>= NIns
)
737 err("too many instructions (2)");
741 curi
->arg
[0] = arg
[0];
742 curi
->arg
[1] = arg
[1];
746 phi
= alloc(sizeof *phi
);
749 memcpy(phi
->arg
, arg
, i
* sizeof arg
[0]);
750 memcpy(phi
->blk
, blk
, i
* sizeof blk
[0]);
759 usecheck(Ref r
, int k
, Fn
*fn
)
761 return rtype(r
) != RTmp
|| fn
->tmp
[r
.val
].cls
== k
762 || (fn
->tmp
[r
.val
].cls
== Kl
&& k
== Kw
);
778 bsinit(pb
, fn
->nblk
);
779 bsinit(ppb
, fn
->nblk
);
780 for (b
=fn
->start
; b
; b
=b
->link
) {
781 for (p
=b
->phi
; p
; p
=p
->link
)
782 fn
->tmp
[p
->to
.val
].cls
= p
->cls
;
783 for (i
=b
->ins
; i
-b
->ins
< b
->nins
; i
++)
784 if (rtype(i
->to
) == RTmp
) {
785 t
= &fn
->tmp
[i
->to
.val
];
786 if (clsmerge(&t
->cls
, i
->cls
))
787 err("temporary %%%s is assigned with"
788 " multiple types", t
->name
);
791 for (b
=fn
->start
; b
; b
=b
->link
) {
793 for (n
=0; n
<b
->npred
; n
++)
794 bsset(pb
, b
->pred
[n
]->id
);
795 for (p
=b
->phi
; p
; p
=p
->link
) {
797 t
= &fn
->tmp
[p
->to
.val
];
798 for (n
=0; n
<p
->narg
; n
++) {
800 if (bshas(ppb
, p
->blk
[n
]->id
))
801 err("multiple entries for @%s in phi %%%s",
802 p
->blk
[n
]->name
, t
->name
);
803 if (!usecheck(p
->arg
[n
], k
, fn
))
804 err("invalid type for operand %%%s in phi %%%s",
805 fn
->tmp
[p
->arg
[n
].val
].name
, t
->name
);
806 bsset(ppb
, p
->blk
[n
]->id
);
808 if (!bsequal(pb
, ppb
))
809 err("predecessors not matched in phi %%%s", t
->name
);
811 for (i
=b
->ins
; i
-b
->ins
< b
->nins
; i
++)
812 for (n
=0; n
<2; n
++) {
813 k
= opdesc
[i
->op
].argcls
[n
][i
->cls
];
817 err("invalid instruction type in %s",
819 if (rtype(r
) == RType
)
821 if (rtype(r
) != -1 && k
== Kx
)
822 err("no %s operand expected in %s",
823 n
== 1 ? "second" : "first",
825 if (rtype(r
) == -1 && k
!= Kx
)
826 err("missing %s operand in %s",
827 n
== 1 ? "second" : "first",
829 if (!usecheck(r
, k
, fn
))
830 err("invalid type for %s operand %%%s in %s",
831 n
== 1 ? "second" : "first",
832 t
->name
, opdesc
[i
->op
].name
);
835 if (isret(b
->jmp
.type
)) {
836 if (b
->jmp
.type
== Jretc
) {
837 if (!usecheck(r
, Kl
, fn
))
839 } else if (!usecheck(r
, b
->jmp
.type
-Jretw
, fn
))
842 if (b
->jmp
.type
== Jjnz
&& !usecheck(r
, Kw
, fn
))
844 err("invalid type for jump argument %%%s in block @%s",
845 fn
->tmp
[r
.val
].name
, b
->name
);
846 if (b
->s1
&& b
->s1
->jmp
.type
== Jxxx
)
847 err("block @%s is used undefined", b
->s1
->name
);
848 if (b
->s2
&& b
->s2
->jmp
.type
== Jxxx
)
849 err("block @%s is used undefined", b
->s2
->name
);
863 curf
= alloc(sizeof *curf
);
865 curf
->ncon
= 1; /* first constant must be 0 */
866 curf
->tmp
= vnew(curf
->ntmp
, sizeof curf
->tmp
[0], Pfn
);
867 curf
->con
= vnew(curf
->ncon
, sizeof curf
->con
[0], Pfn
);
868 for (i
=0; i
<Tmp0
; ++i
)
869 newtmp(0, i
< XMM0
? Kl
: Kd
, curf
);
870 curf
->con
[0].type
= CBits
;
871 curf
->export
= export
;
872 blink
= &curf
->start
;
875 rcls
= parsecls(&curf
->retty
);
879 err("function name expected");
880 strcpy(curf
->name
, tokval
.str
);
881 curf
->vararg
= parserefl(0);
882 if (nextnl() != Tlbrace
)
883 err("function body must start with {");
889 err("empty function");
890 if (curb
->jmp
.type
== Jxxx
)
891 err("last block misses jump");
892 curf
->mem
= vnew(0, sizeof curf
->mem
[0], Pfn
);
896 for (b
=0; b
; b
=b
->link
)
897 b
->dlink
= 0; /* was trashed by findblk() */
898 for (i
=0; i
<BMask
+1; ++i
)
905 parseseg(Seg
*seg
, Typ
*ty
, int t
)
908 int n
, c
, a
, al
, type
;
914 while (t
!= Trbrace
) {
917 default: err("invalid type member specifier");
918 case Td
: type
= SFlt
;
919 case Tl
: s
= 8; a
= 3; break;
920 case Ts
: type
= SFlt
;
921 case Tw
: s
= 4; a
= 2; break;
922 case Th
: s
= 2; a
= 1; break;
923 case Tb
: s
= 1; a
= 0; break;
926 ty1
= &typ
[findtyp(ntyp
-1)];
933 if ((a
= sz
& (s
-1))) {
936 /* padding segment */
951 for (; c
>0 && n
<NSeg
; c
--, n
++) {
960 err(", or } expected");
963 sz
= (sz
+ a
- 1) & -a
;
976 err("too many type definitions");
981 if (nextnl() != Ttyp
|| nextnl() != Teq
)
982 err("type name and then = expected");
983 strcpy(ty
->name
, tokval
.str
);
986 if (nextnl() != Tint
)
987 err("alignment expected");
988 for (al
=0; tokval
.num
/= 2; al
++)
994 err("type body must start with {");
998 ty
->size
= tokval
.num
;
1000 err("dark types need alignment");
1001 if (nextnl() != Trbrace
)
1006 ty
->seg
= vnew(1, sizeof ty
->seg
[0], Pheap
);
1010 err("invalid union member");
1011 vgrow(&ty
->seg
, n
+1);
1012 parseseg(ty
->seg
[n
++], ty
, nextnl());
1014 } while (t
!= Trbrace
);
1016 parseseg(ty
->seg
[n
++], ty
, t
);
1026 d
->u
.ref
.nam
= tokval
.str
;
1032 err("invalid token after offset in ref");
1033 d
->u
.ref
.off
= tokval
.num
;
1041 d
->u
.str
= tokval
.str
;
1045 parsedat(void cb(Dat
*), int export
)
1056 if (nextnl() != Tglo
|| nextnl() != Teq
)
1057 err("data name, then = expected");
1058 strcpy(s
, tokval
.str
);
1061 if (nextnl() != Tint
)
1062 err("alignment expected");
1064 d
.u
.num
= tokval
.num
;
1073 err("expected data contents in { .. }");
1076 default: err("invalid size specifier %c in data", tokval
.chr
);
1077 case Trbrace
: goto Done
;
1078 case Tl
: d
.type
= DL
; break;
1079 case Tw
: d
.type
= DW
; break;
1080 case Th
: d
.type
= DH
; break;
1081 case Tb
: d
.type
= DB
; break;
1082 case Ts
: d
.type
= DW
; break;
1083 case Td
: d
.type
= DL
; break;
1084 case Tz
: d
.type
= DZ
; break;
1090 memset(&d
.u
, 0, sizeof d
.u
);
1092 d
.u
.flts
= tokval
.flts
;
1093 else if (t
== Tfltd
)
1094 d
.u
.fltd
= tokval
.fltd
;
1096 d
.u
.num
= tokval
.num
;
1102 err("constant literal expected");
1105 } while (t
== Tint
|| t
== Tflts
|| t
== Tfltd
);
1109 err(", or } expected");
1117 parse(FILE *f
, char *path
, void data(Dat
*), void func(Fn
*))
1131 err("top-level definition expected");
1137 func(parsefn(export
));
1140 else if (t
== Tdata
) {
1142 parsedat(data
, export
);
1146 err("export can only qualify data and function");
1157 printcon(Con
*c
, FILE *f
)
1163 fprintf(f
, "$%s", c
->label
);
1165 fprintf(f
, "%+"PRIi64
, c
->bits
.i
);
1169 fprintf(f
, "s_%f", c
->bits
.s
);
1170 else if (c
->flt
== 2)
1171 fprintf(f
, "d_%lf", c
->bits
.d
);
1173 fprintf(f
, "%"PRIi64
, c
->bits
.i
);
1179 printref(Ref r
, Fn
*fn
, FILE *f
)
1187 fprintf(f
, "R%d", r
.val
);
1189 fprintf(f
, "%%%s", fn
->tmp
[r
.val
].name
);
1192 printcon(&fn
->con
[r
.val
], f
);
1195 fprintf(f
, "S%d", (r
.val
&(1<<28)) ? r
.val
-(1<<29) : r
.val
);
1198 fprintf(f
, "%04x", r
.val
);
1201 fprintf(f
, ":%s", typ
[r
.val
].name
);
1205 m
= &fn
->mem
[r
.val
];
1207 if (m
->offset
.type
!= CUndef
) {
1208 printcon(&m
->offset
, f
);
1211 if (!req(m
->base
, R
)) {
1214 printref(m
->base
, fn
, f
);
1217 if (!req(m
->index
, R
)) {
1220 fprintf(f
, "%d * ", m
->scale
);
1221 printref(m
->index
, fn
, f
);
1229 printfn(Fn
*fn
, FILE *f
)
1231 static char *jtoa
[NJmp
] = {
1241 #define X(c) [Jxjc+IC##c] = "xj" #c,
1245 static char prcls
[NOp
] = {
1253 static char ktoc
[] = "wlsd";
1260 fprintf(f
, "export ");
1261 fprintf(f
, "function $%s() {\n", fn
->name
);
1262 for (b
=fn
->start
; b
; b
=b
->link
) {
1263 fprintf(f
, "@%s\n", b
->name
);
1264 for (p
=b
->phi
; p
; p
=p
->link
) {
1266 printref(p
->to
, fn
, f
);
1267 fprintf(f
, " =%c phi ", ktoc
[p
->cls
]);
1270 fprintf(f
, "@%s ", p
->blk
[n
]->name
);
1271 printref(p
->arg
[n
], fn
, f
);
1272 if (n
== p
->narg
-1) {
1279 for (i
=b
->ins
; i
-b
->ins
< b
->nins
; i
++) {
1281 if (!req(i
->to
, R
)) {
1282 printref(i
->to
, fn
, f
);
1283 fprintf(f
, " =%c ", ktoc
[i
->cls
]);
1285 assert(opdesc
[i
->op
].name
);
1286 fprintf(f
, "%s", opdesc
[i
->op
].name
);
1287 if (req(i
->to
, R
) && prcls
[i
->op
])
1288 fputc(ktoc
[i
->cls
], f
);
1289 if (!req(i
->arg
[0], R
)) {
1291 printref(i
->arg
[0], fn
, f
);
1293 if (!req(i
->arg
[1], R
)) {
1295 printref(i
->arg
[1], fn
, f
);
1299 switch (b
->jmp
.type
) {
1306 fprintf(f
, "\t%s", jtoa
[b
->jmp
.type
]);
1307 if (b
->jmp
.type
!= Jret0
|| !req(b
->jmp
.arg
, R
)) {
1309 printref(b
->jmp
.arg
, fn
, f
);
1311 if (b
->jmp
.type
== Jretc
)
1312 fprintf(f
, ", :%s", typ
[fn
->retty
].name
);
1316 if (b
->s1
!= b
->link
)
1317 fprintf(f
, "\tjmp @%s\n", b
->s1
->name
);
1320 fprintf(f
, "\t%s ", jtoa
[b
->jmp
.type
]);
1321 if (b
->jmp
.type
== Jjnz
) {
1322 printref(b
->jmp
.arg
, fn
, f
);
1325 fprintf(f
, "@%s, @%s\n", b
->s1
->name
, b
->s2
->name
);