1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
#include "lisc.h"
static void
eref(Ref r, Fn *fn, FILE *f)
{
switch (rtype(r)) {
case RSym:
assert(fn->sym[r.val].type == SReg);
fprintf(f, "%%%s", fn->sym[r.val].name);
break;
case RSlot:
fprintf(f, "-%d(%%rbp)", 8 * r.val);
break;
case RConst:
fprintf(f, "$%d", (int)r.val);
break;
default:
diag("emitref: invalid reference");
}
}
static void
eop(char *op, Ref a, Ref b, Fn *fn, FILE *f)
{
fprintf(f, "\t%s ", op);
eref(a, fn, f);
if (!req(b, R)) {
fprintf(f, ", ");
eref(b, fn, f);
}
fprintf(f, "\n");
}
static void
eins(Ins i, Fn *fn, FILE *f)
{
static char *opi[] = {
[OAdd] = "add",
[OSub] = "sub",
};
switch (i.op) {
case OAdd:
case OSub:
if (!req(i.to, i.arg[0]))
eop("mov", i.arg[0], i.to, fn, f);
eop(opi[i.op], i.arg[1], i.to, fn, f);
break;
case OStore:
i.to = i.arg[1];
/* fall through */
case OCopy:
case OLoad:
if (!req(i.arg[0], i.to))
eop("mov", i.arg[0], i.to, fn, f);
break;
case OSwap:
eop("xchg", i.arg[0], i.arg[1], fn, f);
break;
case ONop:
break;
default:
diag("emit: unhandled instruction");
}
}
void
emitfn(Fn *fn, FILE *f)
{
char *js;
Blk *b, *s;
Ins *i;
fprintf(f,
".text\n"
".globl liscf\n"
".type liscf, @function\n"
"liscf:\n"
"\tpush %%rbp\n"
"\tmov %%rsp, %%rbp\n"
"\tsub $%u, %%rsp\n",
fn->nspill * 8
);
for (b=fn->start; b; b=b->link) {
fprintf(f, ".L%s:\n", b->name);
for (i=b->ins; i-b->ins < b->nins; i++)
eins(*i, fn, f);
switch (b->jmp.type) {
case JRet:
fprintf(f,
"\tleave\n"
"\tret\n"
);
break;
case JJmp:
if (b->s1 != b->link)
fprintf(f, "\tjmp .L%s\n", b->s1->name);
break;
case JJez:
if (b->s1 == b->link) {
js = "jnz";
s = b->s2;
} else if (b->s2 == b->link) {
js = "jz";
s = b->s1;
} else
diag("emit: unhandled jump (1)");
eop("test", b->jmp.arg, b->jmp.arg, fn, f);
fprintf(f, "\t%s .L%s\n", js, s->name);
break;
default:
diag("emit: unhandled jump (2)");
}
}
}
|