commit 580e6be72c814c4943f6ba65e2329d14be660ee7
parent 68a9198dd18bd181e61b8d1ca273f97620e83233
Author: Eyal Sawady <ecs@d2evs.net>
Date: Fri, 15 Oct 2021 10:01:24 +0000
cmd/harec: implement -o
Signed-off-by: Eyal Sawady <ecs@d2evs.net>
Diffstat:
3 files changed, 32 insertions(+), 21 deletions(-)
diff --git a/cmd/harec/context.ha b/cmd/harec/context.ha
@@ -4,6 +4,7 @@ use hare::unit;
type context = struct {
out: *io::stream,
+ buf: *io::stream,
store: *types::typestore,
unit: *unit::unit,
arch: struct {
diff --git a/cmd/harec/gen.ha b/cmd/harec/gen.ha
@@ -11,10 +11,11 @@ use io;
use os;
use strings;
-fn gen(store: *types::typestore, unit: *unit::unit) void = {
+fn gen(out: *io::stream, store: *types::typestore, unit: *unit::unit) void = {
// TODO: context_init
let ctx = context {
- out = bufio::dynamic(io::mode::WRITE),
+ out = out,
+ buf = bufio::dynamic(io::mode::WRITE),
store = store,
unit = unit,
arch = struct {
@@ -24,7 +25,7 @@ fn gen(store: *types::typestore, unit: *unit::unit) void = {
},
...
};
- defer io::close(ctx.out);
+ defer io::close(ctx.buf);
for (let i = 0z; i < len(unit.decls); i += 1) {
match (unit.decls[i].decl) {
case func: unit::decl_func =>
@@ -49,7 +50,7 @@ fn gen_func(ctx: *context, decl: *unit::decl) void = {
const ident = module::identuscore(fndecl.ident);
defer free(ident);
- fmt::printf("{}function section \".text.{}\" \"ax\"",
+ fmt::fprintf(ctx.out, "{}function section \".text.{}\" \"ax\"",
if (decl.exported) "export " else "", ident)!;
const rtype = fntype.result;
const has_rval =
@@ -61,32 +62,32 @@ fn gen_func(ctx: *context, decl: *unit::decl) void = {
};
if (has_rval) {
const qrtype = qtype_lookup(ctx, rtype, false);
- fmt::printf(" {}", qtype_repr(qrtype))!;
+ fmt::fprintf(ctx.out, " {}", qtype_repr(qrtype))!;
};
- fmt::printf(" ${}(", ident)!;
+ fmt::fprintf(ctx.out, " ${}(", ident)!;
assert(len(fntype.params) == 0); // TODO
- fmt::println(") {")!;
- fmt::println(mklabel(ctx, "start"))!;
+ fmt::fprintln(ctx.out, ") {")!;
+ fmt::fprintln(ctx.out, mklabel(ctx, "start"))!;
// We use a dynamic buffer here so that we can emit alloc instructions
// on-demand at the start of the function, rather than spread out
// through the body. This is more reliable on qbe's ARM backend, and
// generates better IL besides.
- bufio::reset(ctx.out);
+ bufio::reset(ctx.buf);
- fmt::fprintln(ctx.out, mklabel(ctx, "body"))!;
+ fmt::fprintln(ctx.buf, mklabel(ctx, "body"))!;
const rval = gen_expr(ctx, body);
if (!body.terminates) {
if (has_rval) {
- emit(ctx.out, void, qinstr::RET, rval);
+ emit(ctx.buf, void, qinstr::RET, rval);
} else {
- emit(ctx.out, void, qinstr::RET);
+ emit(ctx.buf, void, qinstr::RET);
};
};
- io::write(os::stdout, bufio::buffer(ctx.out))!;
- fmt::println("}\n")!;
+ io::write(ctx.out, bufio::buffer(ctx.buf))!;
+ fmt::fprintln(ctx.out, "}\n")!;
};
fn gen_store(ctx: *context, object: value, value: value) void = {
@@ -102,7 +103,7 @@ fn gen_store(ctx: *context, object: value, value: value) void = {
case => void; // Handled below
};
const instr = qinstr_store(ctx, object._type);
- emit(ctx.out, void, instr, value, object);
+ emit(ctx.buf, void, instr, value, object);
};
fn gen_load(ctx: *context, object: value) value = {
@@ -120,7 +121,7 @@ fn gen_load(ctx: *context, object: value) value = {
const instr = qinstr_load(ctx, object._type);
const temp = mktemp(ctx);
const ty = qtype_lookup(ctx, object._type, false);
- emit(ctx.out, (ty, temp), instr, object);
+ emit(ctx.buf, (ty, temp), instr, object);
return value {
value = temp,
_type = object._type,
@@ -195,7 +196,7 @@ fn gen_binding(ctx: *context, expr: *unit::expr) value = {
// const lval, instr = allocval(value);
const instr = qinstr_alloc(value._type);
const lval = mklval(ctx, value);
- emit(ctx.out, lval, instr, value._type.sz);
+ emit(ctx.buf, lval, instr, value._type.sz);
gen_expr_at(ctx, item.init, value);
};
return vvoid;
@@ -237,9 +238,9 @@ fn gen_return(ctx: *context, expr: *unit::expr) value = {
const rexpr = expr.expr as unit::_return;
match (rexpr) {
case null =>
- emit(ctx.out, void, qinstr::RET);
+ emit(ctx.buf, void, qinstr::RET);
case expr: *unit::expr =>
- emit(ctx.out, void, qinstr::RET, gen_expr(ctx, expr));
+ emit(ctx.buf, void, qinstr::RET, gen_expr(ctx, expr));
};
return vvoid;
};
diff --git a/cmd/harec/main.ha b/cmd/harec/main.ha
@@ -10,6 +10,7 @@ use hare::unit;
use hare::unparse;
use io;
use os;
+use unix;
export fn main() void = {
let usage: []getopt::help = [
@@ -24,13 +25,21 @@ export fn main() void = {
let cmd = getopt::parse(os::args, usage...);
defer getopt::finish(&cmd);
+ let out = os::stdout;
+
for (let i = 0z; i < len(cmd.opts); i += 1) {
let opt = cmd.opts[i];
switch (opt.0) {
case 'D' => abort(); // TODO
case 'N' => abort(); // TODO
case 'T' => abort(); // TODO
- case 'o' => abort(); // TODO
+ case 'o' =>
+ out = match (os::create(opt.1, 0o644)) {
+ case f: io::file =>
+ yield &f;
+ case e: fs::error =>
+ fmt::fatal(fs::strerror(e));
+ };
case 't' => abort(); // TODO
case => abort();
};
@@ -80,5 +89,5 @@ export fn main() void = {
yield u;
};
defer unit::unit_free(unit);
- gen(store, &unit);
+ gen(out, store, &unit);
};