15 enum { /* minic types */
23 #define IDIR(x) (((x) << 3) + PTR)
24 #define FUNC(x) (((x) << 3) + FUN)
25 #define DREF(x) ((x) >> 3)
26 #define KIND(x) ((x) & 7)
28 (x
== NIL ?
(die
("void has no size"), 0) : \
31 typedef
struct Node Node
;
32 typedef
struct Symb Symb
;
33 typedef
struct Stmt Stmt
;
71 int yylex(void), yyerror(char *);
72 Symb expr
(Node
*), lval
(Node
*);
73 void bool(Node
*, int, int);
88 fprintf
(stderr
, "error:%d: %s\n", line
, s
);
119 for
(h
=0; h
<NVar
; h
++)
125 varadd
(char *v
, int glo
, unsigned ctyp
)
132 if
(varh
[h
].v
[0] == 0) {
133 strcpy
(varh
[h
].v
, v
);
138 if
(strcmp
(varh
[h
].v
, v
) == 0)
139 die
("double definition");
142 die
("too many variables");
154 if
(strcmp
(varh
[h
].v
, v
) == 0) {
162 s.ctyp
= varh
[h
].ctyp
;
166 } while
(h
!= h0
&& varh
[h
].v
[0] != 0);
173 return SIZE
(ctyp
) == 8 ?
'l' : 'w';
181 fprintf
(of
, "%%t%d", s.u.n
);
184 fprintf
(of
, "%%%s", s.u.v
);
187 fprintf
(of
, "$glo%d", s.u.n
);
190 fprintf
(of
, "%d", s.u.n
);
198 fprintf
(of
, "\t%%t%d =l extsw ", tmp
);
207 prom
(int op
, Symb
*l
, Symb
*r
)
212 if
(l
->ctyp
== r
->ctyp
&& KIND
(l
->ctyp
) != PTR
)
215 if
(l
->ctyp
== LNG
&& r
->ctyp
== INT
) {
219 if
(l
->ctyp
== INT
&& r
->ctyp
== LNG
) {
225 if
(KIND
(r
->ctyp
) == PTR
) {
230 if
(KIND
(r
->ctyp
) == PTR
)
231 die
("pointers added");
236 if
(KIND
(l
->ctyp
) != PTR
)
237 die
("pointer substracted from integer");
238 if
(KIND
(r
->ctyp
) != PTR
)
240 if
(l
->ctyp
!= r
->ctyp
)
241 die
("non-homogeneous pointers in substraction");
246 sz
= SIZE
(DREF
(l
->ctyp
));
250 if
(irtyp
(r
->ctyp
) != 'l')
252 fprintf
(of
, "\t%%t%d =l mul %d, ", tmp
, sz
);
268 fprintf
(of
, " =%c load%c ", t
, t
);
274 call
(Node
*n
, Symb
*sr
)
282 ft
= varget
(f
)->ctyp
;
288 for
(a
=n
->r
; a
; a
=a
->r
)
292 fprintf
(of
, " =%c call $%s(", irtyp
(sr
->ctyp
), f
);
293 for
(a
=n
->r
; a
; a
=a
->r
) {
294 fprintf
(of
, "%c ", irtyp
(a
->u.s.ctyp
));
298 fprintf
(of
, "...)\n");
304 static char *otoa
[] = {
311 ['<'] = "cslt", /* meeeeh, wrong for pointers! */
333 fprintf
(of
, "@l%d\n", l
);
334 fprintf
(of
, "\tjmp @l%d\n", l
+2);
335 fprintf
(of
, "@l%d\n", l
+1);
336 fprintf
(of
, "\tjmp @l%d\n", l
+2);
337 fprintf
(of
, "@l%d\n", l
+2);
341 fprintf
(of
, " =w phi @l%d 1, @l%d 0\n", l
, l
+1);
368 if
(KIND
(s0.ctyp
) != PTR
)
369 die
("dereference of a non-pointer");
370 sr.ctyp
= DREF
(s0.ctyp
);
376 sr.ctyp
= IDIR
(sr.ctyp
);
383 if
(s1.ctyp
== LNG
&& s0.ctyp
== INT
)
385 if
(s0.ctyp
!= IDIR
(NIL
) || KIND
(s1.ctyp
) != PTR
)
386 if
(s1.ctyp
!= IDIR
(NIL
) || KIND
(s0.ctyp
) != PTR
)
387 if
(s1.ctyp
!= s0.ctyp
)
388 die
("invalid assignment");
389 fprintf
(of
, "\tstore%c ", irtyp
(s1.ctyp
));
394 o
= n
->op
== 'P' ?
'+' : '-';
410 sr.ctyp
= prom
(o
, &s0
, &s1
);
411 if
(strchr
("ne<l", n
->op
)) {
412 sprintf
(ty
, "%c", irtyp
(sr.ctyp
));
418 fprintf
(of
, " =%c", irtyp
(sr.ctyp
));
419 fprintf
(of
, " %s%s ", otoa
[o
], ty
);
429 && KIND
(s0.ctyp
) == PTR
430 && KIND
(s1.ctyp
) == PTR
) {
431 fprintf
(of
, "\t%%t%d =l div ", tmp
);
433 fprintf
(of
, ", %d\n", SIZE
(DREF
(s0.ctyp
)));
436 if
(n
->op
== 'P' || n
->op
== 'M') {
437 fprintf
(of
, "\tstore%c ", irtyp
(sl.ctyp
));
454 die
("invalid lvalue");
457 die
("undefined variable");
458 sr
= *varget
(n
->u.v
);
462 if
(KIND
(sr.ctyp
) != PTR
)
463 die
("dereference of a non-pointer");
464 sr.ctyp
= DREF
(sr.ctyp
);
471 bool(Node
*n
, int lt
, int lf
)
478 s
= expr
(n
); /* TODO: insert comparison to 0 with proper type */
479 fprintf
(of
, "\tjnz ");
481 fprintf
(of
, ", @l%d, @l%d\n", lt
, lf
);
487 fprintf
(of
, "@l%d\n", l
);
494 fprintf
(of
, "@l%d\n", l
);
512 fprintf
(of
, "\tret ");
518 die
("break not in loop");
519 fprintf
(of
, "\tjmp @l%d\n", b
);
525 return stmt
(s
->p1
, b
) || stmt
(s
->p2
, b
);
530 fprintf
(of
, "@l%d\n", l
);
531 if
(!(r
=stmt
(s
->p2
, b
)))
533 fprintf
(of
, "\tjmp @l%d\n", l
+2);
534 fprintf
(of
, "@l%d\n", l
+1);
536 if
(!(r
&= stmt
(s
->p3
, b
)))
537 fprintf
(of
, "@l%d\n", l
+2);
542 fprintf
(of
, "@l%d\n", l
);
543 bool(s
->p1
, l
+1, l
+2);
544 fprintf
(of
, "@l%d\n", l
+1);
545 if
(!stmt
(s
->p2
, l
+2))
546 fprintf
(of
, "\tjmp @l%d\n", l
);
547 fprintf
(of
, "@l%d\n", l
+2);
553 mknode
(char op
, Node
*l
, Node
*r
)
557 n
= alloc
(sizeof
*n
);
565 mkidx
(Node
*a
, Node
*i
)
569 n
= mknode
('+', a
, i
);
570 n
= mknode
('@', n
, 0);
580 z
= mknode
('N', 0, 0);
583 return mknode
('-', z
, n
);
587 mkstmt
(int t
, void *p1
, void *p2
, void *p3
)
591 s
= alloc
(sizeof
*s
);
600 param
(char *v
, unsigned ctyp
, Node
*pl
)
605 die
("invalid void declaration");
606 n
= mknode
(0, 0, pl
);
613 mkfor
(Node
*ini
, Node
*tst
, Node
*inc
, Stmt
*s
)
618 s1
= mkstmt
(Expr
, ini
, 0, 0);
622 s2
= mkstmt
(Expr
, inc
, 0, 0);
623 s2
= mkstmt
(Seq
, s
, s2
, 0);
627 tst
= mknode
('N', 0, 0);
630 s2
= mkstmt
(While
, tst
, s2
, 0);
632 return mkstmt
(Seq
, s1
, s2
, 0);
648 %token PP MM LE GE SIZEOF
650 %token TVOID TINT TLNG
651 %token IF ELSE WHILE FOR BREAK RETURN
664 %type
<n
> expr exp0 pref post arg0 arg1 par0 par1
668 prog: func prog | fdcl prog | idcl prog |
;
670 fdcl: type IDENT
'(' ')' ';'
672 varadd
($2->u.v
, 1, FUNC
($1));
678 die
("invalid void declaration");
680 die
("too many string literals");
681 ini
[nglo
] = alloc
(sizeof
"{ x 0 }");
682 sprintf
(ini
[nglo
], "{ %c 0 }", irtyp
($1));
683 varadd
($2->u.v
, nglo
++, $1);
692 func: init prot
'{' dcls stmts
'}'
695 fprintf
(of
, "\tret 0\n");
696 fprintf
(of
, "}\n\n");
699 prot: IDENT
'(' par0
')'
705 varadd
($1->u.v
, 1, FUNC
(INT
));
706 fprintf
(of
, "export function w $%s(", $1->u.v
);
711 fprintf
(of
, "%c ", irtyp
(s
->ctyp
));
712 fprintf
(of
, "%%t%d", tmp
++);
719 fprintf
(of
, ") {\n");
720 fprintf
(of
, "@l%d\n", lbl
++);
721 for
(t
=0, n
=$3; n
; t
++, n
=n
->r
) {
724 fprintf
(of
, "\t%%%s =l alloc%d %d\n", n
->u.v
, m
, m
);
725 fprintf
(of
, "\tstore%c %%t%d", irtyp
(s
->ctyp
), t
);
726 fprintf
(of
, ", %%%s\n", n
->u.v
);
733 par1: type IDENT
',' par1
{ $$
= param
($2->u.v
, $1, $4); }
734 | type IDENT
{ $$
= param
($2->u.v
, $1, 0); }
738 dcls: | dcls type IDENT
';'
744 die
("invalid void declaration");
748 fprintf
(of
, "\t%%%s =l alloc%d %d\n", v
, s
, s
);
751 type: type
'*' { $$
= IDIR
($1); }
754 | TVOID
{ $$
= NIL
; }
757 stmt: ';' { $$
= 0; }
758 |
'{' stmts
'}' { $$
= $2; }
759 | BREAK
';' { $$
= mkstmt
(Break
, 0, 0, 0); }
760 | RETURN expr
';' { $$
= mkstmt
(Ret
, $2, 0, 0); }
761 | expr
';' { $$
= mkstmt
(Expr
, $1, 0, 0); }
762 | WHILE
'(' expr
')' stmt
{ $$
= mkstmt
(While
, $3, $5, 0); }
763 | IF
'(' expr
')' stmt ELSE stmt
{ $$
= mkstmt
(If
, $3, $5, $7); }
764 | IF
'(' expr
')' stmt
{ $$
= mkstmt
(If
, $3, $5, 0); }
765 | FOR
'(' exp0
';' exp0
';' exp0
')' stmt
766 { $$
= mkfor
($3, $5, $7, $9); }
769 stmts: stmts stmt
{ $$
= mkstmt
(Seq
, $1, $2, 0); }
774 | expr
'=' expr
{ $$
= mknode
('=', $1, $3); }
775 | expr
'+' expr
{ $$
= mknode
('+', $1, $3); }
776 | expr
'-' expr
{ $$
= mknode
('-', $1, $3); }
777 | expr
'*' expr
{ $$
= mknode
('*', $1, $3); }
778 | expr
'/' expr
{ $$
= mknode
('/', $1, $3); }
779 | expr
'%' expr
{ $$
= mknode
('%', $1, $3); }
780 | expr
'<' expr
{ $$
= mknode
('<', $1, $3); }
781 | expr
'>' expr
{ $$
= mknode
('<', $3, $1); }
782 | expr LE expr
{ $$
= mknode
('l', $1, $3); }
783 | expr GE expr
{ $$
= mknode
('l', $3, $1); }
784 | expr EQ expr
{ $$
= mknode
('e', $1, $3); }
785 | expr NE expr
{ $$
= mknode
('n', $1, $3); }
786 | expr
'&' expr
{ $$
= mknode
('&', $1, $3); }
787 | expr AND expr
{ $$
= mknode
('a', $1, $3); }
788 | expr OR expr
{ $$
= mknode
('o', $1, $3); }
796 |
'-' pref
{ $$
= mkneg
($2); }
797 |
'*' pref
{ $$
= mknode
('@', $2, 0); }
798 |
'&' pref
{ $$
= mknode
('A', $2, 0); }
804 | SIZEOF
'(' type
')' { $$
= mknode
('N', 0, 0); $$
->u.n
= SIZE
($3); }
805 |
'(' expr
')' { $$
= $2; }
806 | IDENT
'(' arg0
')' { $$
= mknode
('C', $1, $3); }
807 | post
'[' expr
']' { $$
= mkidx
($1, $3); }
808 | post PP
{ $$
= mknode
('P', $1, 0); }
809 | post MM
{ $$
= mknode
('M', $1, 0); }
815 arg1: expr
{ $$
= mknode
(0, $1, 0); }
816 | expr
',' arg1
{ $$
= mknode
(0, $1, $3); }
835 { "return", RETURN
},
837 { "sizeof", SIZEOF
},
846 while
((c
= getchar
()) != '\n')
850 } while
(isspace
(c
));
863 } while
(isdigit
(c
));
865 yylval.n
= mknode
('N', 0, 0);
873 if
(p
== &v
[NString
-1])
874 die
("ident too long");
877 } while
(isalpha
(c
) || c
== '_');
880 for
(i
=0; kwds
[i
].s
; i
++)
881 if
(strcmp
(v
, kwds
[i
].s
) == 0)
883 yylval.n
= mknode
('V', 0, 0);
884 strcpy
(yylval.n
->u.v
, v
);
896 die
("unclosed string literal");
898 p
= memcpy
(alloc
(n
*2), p
, n
);
902 if
(c
== '"' && p
[i
-1]!='\\')
905 strcpy
(&p
[i
], "\", b 0 }");
907 die
("too many globals");
909 yylval.n
= mknode
('S', 0, 0);
910 yylval.n
->u.n
= nglo
++;
915 #define DI(a, b) a + b*256
917 case DI
('!','='): return NE
;
918 case DI
('=','='): return EQ
;
919 case DI
('<','='): return LE
;
920 case DI
('>','='): return GE
;
921 case DI
('+','+'): return PP
;
922 case DI
('-','-'): return MM
;
923 case DI
('&','&'): return AND
;
924 case DI
('|','|'): return OR
;
948 for
(i
=1; i
<nglo
; i
++)
949 fprintf
(of
, "data $glo%d = %s\n", i
, ini
[i
]);