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
|
import "cffc.hff";
import "common.hff";
struct ASM {
outf *FILE,
lastsection enum { none, data, text },
fn gen(A *ASM, fmt *const u8, ...) void {
let ap va_list #?;
ap->start(fmt);
fn fmtproc(c u8, fp *void) void {
fputc(c, fp);
}
for let c = *fmt; c != 0; c = *++fmt {
if c != '%' {
fputc(c, A.outf);
continue;
}
switch (c = *++fmt) {
case 's';
fprintf(A.outf, "%s", ap->arg(*const u8));
case 'd';
fprintf(A.outf, "%d", ap->arg(int));
case 'I';
fprintf(A.outf, "%lld", as(c_llong) ap->arg(i64));
case 'f';
fprintf(A.outf, "%.17f", ap->arg(f64));
case 'z';
fprintf(A.outf, "%llu", as(c_ullong) ap->arg(usize));
case 'S';
pfmt(&fmtproc, A.outf, "%S", ap->arg([#]const u8));
case else
assert(#f, "bad fmt '%c'", c);
}
}
ap->end();
}
}
fn init(B *Backend, outf *FILE) void {
B.impl = calloc(1, sizeof ASM);
let impl *ASM = B.impl;
impl.outf = outf;
}
static directive4size []*const u8 = {
[1] = "byte",
[2] = "short",
[4] = "int",
[8] = "quad"
};
fn gendata(A *ASM, ty *const Type, ex *Expr) void {
switch ex.u {
case ZeroIni;
A->gen(".fill %z", ty.size);
case IntLit i;
A->gen(".%s %I", directive4size[ty.size], i.i);
case FloLit f;
A->gen(".%s %f", ty.size == 4 ? "single" : "double", f);
case StrLit s;
if ty->is(:Arr) {
A->gen(".ascii %S", s);
} else {
static id int = 0;
A->gen(".%s strlit%d.", directive4size[g_targ.ptrsize], id);
A->gen("\nstrlit%d.:\n\t.ascii %S", id++, s);
}
case else
assert(#f, "NYI data");
}
}
fn genstatic(A *ASM, decl *Decl) void {
if decl.u.Static.fwd {
return;
}
if A.lastsection != :data {
A->gen(".section data\n");
A.lastsection = :data;
}
if decl.externp {
A->gen(".globl %s\n%s:\n", decl.name, decl.name);
} else {
A->gen("%s.s%d:\n", decl.name, decl.u.Static.id);
}
A->gen("\t.align %z\n", decl.u.Static.ty.align);
switch decl.u.Static.ini {
case None;
A->gen("\t.fill %z\n", decl.u.Static.ty.size);
case Some *ex;
A->gen("\t");
gendata(A, decl.u.Static.ty, ex);
A->gen("\n");
}
}
fn bgenstatic(B *Backend, decl *Decl) void {
genstatic(B.impl, decl);
}
fn bgenfn(B *Backend, Fn *Fn) void {
}
extern static g_asmbackend Backend = {
.initf: &init,
.genstaticf: &bgenstatic,
.genfnf: &bgenfn,
};
|