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, };