commit b030669fdd8ad27aa84cbaf769e12109d7deff02
parent ac3222b2e1fd0e94b4b1483df5b3db06b9c8edca
Author: Drew DeVault <sir@cmpwn.com>
Date: Wed, 10 Mar 2021 10:16:17 -0500
Update stdlib and schedule more tasks
Diffstat:
4 files changed, 103 insertions(+), 26 deletions(-)
diff --git a/gen-stdlib b/gen-stdlib
@@ -353,7 +353,7 @@ os_exec() {
'process$(PLATFORM).ha' \
'cmd$(PLATFORM).ha' \
cmd.ha
- gen_ssa os::exec os strings fmt
+ gen_ssa os::exec os strings fmt bytes path
}
path() {
@@ -362,7 +362,6 @@ path() {
'$(PLATFORM).ha' \
util.ha \
join.ha \
- norm.ha \
names.ha \
iter.ha
gen_ssa path strings bufio bytes
diff --git a/main.ha b/main.ha
@@ -19,7 +19,6 @@ export fn main() void = {
...
};
defer os::rmdirall(plan.workdir);
- defer path::path_free(plan.workdir);
let ctx = module::context_init([module::tag {
name = os::machine(),
mode = module::tag_mode::INCLUSIVE,
@@ -29,6 +28,13 @@ export fn main() void = {
mode = module::tag_mode::INCLUSIVE,
}]);
+ const rtdir = match (module::lookup(&ctx, ["rt"])) {
+ err: module::error => fmt::fatal("Error resolving rt: {}",
+ module::errstr(err)),
+ ver: module::version => ver.basedir,
+ };
+ plan.script = path::join(rtdir, "hare.sc");
+
let ver = match (module::scan(&ctx, os::args[1])) {
ver: module::version => ver,
err: module::error => fmt::fatal("Error scanning module: {}",
@@ -48,14 +54,14 @@ export fn main() void = {
fmt::errorfln("{}: selecting version {}",
ident, hash);
for (let i = 0z; i < len(ver.inputs); i += 1) {
- fmt::errorfln("\t{}",
- ver.inputs[i].path as str);
+ fmt::errorfln("\t{}", ver.inputs[i].path);
};
},
};
};
- sched_hare_exe(&plan, ver.inputs, "hare.ssa", []);
+ // TODO: Choose less stupid output name
+ sched_hare_exe(&plan, ver.inputs, "a.out");
for (len(plan.scheduled) != 0) {
let next: nullable *task = null;
@@ -81,6 +87,7 @@ export fn main() void = {
};
task.status = status::COMPLETE;
+
delete(plan.scheduled[i]);
append(plan.complete, task);
};
diff --git a/mk/stdlib.mk b/mk/stdlib.mk
@@ -419,7 +419,7 @@ stdlib_os_exec_srcs= \
$(STDLIB)/os/exec/cmd$(PLATFORM).ha \
$(STDLIB)/os/exec/cmd.ha
-$(HARECACHE)/os/exec/os.exec.ssa: $(stdlib_os_exec_srcs) $(stdlib_rt) $(stdlib_os) $(stdlib_strings) $(stdlib_fmt)
+$(HARECACHE)/os/exec/os.exec.ssa: $(stdlib_os_exec_srcs) $(stdlib_rt) $(stdlib_os) $(stdlib_strings) $(stdlib_fmt) $(stdlib_bytes) $(stdlib_path)
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/os/exec
@HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Nos::exec \
@@ -430,7 +430,6 @@ stdlib_path_srcs= \
$(STDLIB)/path/$(PLATFORM).ha \
$(STDLIB)/path/util.ha \
$(STDLIB)/path/join.ha \
- $(STDLIB)/path/norm.ha \
$(STDLIB)/path/names.ha \
$(STDLIB)/path/iter.ha
@@ -955,7 +954,7 @@ testlib_os_exec_srcs= \
$(STDLIB)/os/exec/cmd$(PLATFORM).ha \
$(STDLIB)/os/exec/cmd.ha
-$(TESTCACHE)/os/exec/os.exec.ssa: $(testlib_os_exec_srcs) $(testlib_rt) $(testlib_os) $(testlib_strings) $(testlib_fmt)
+$(TESTCACHE)/os/exec/os.exec.ssa: $(testlib_os_exec_srcs) $(testlib_rt) $(testlib_os) $(testlib_strings) $(testlib_fmt) $(testlib_bytes) $(testlib_path)
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/os/exec
@HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nos::exec \
@@ -966,7 +965,6 @@ testlib_path_srcs= \
$(STDLIB)/path/$(PLATFORM).ha \
$(STDLIB)/path/util.ha \
$(STDLIB)/path/join.ha \
- $(STDLIB)/path/norm.ha \
$(STDLIB)/path/names.ha \
$(STDLIB)/path/iter.ha
diff --git a/plan.ha b/plan.ha
@@ -11,38 +11,96 @@ type status = enum {
type task = struct {
status: status,
- inputs: []module::input,
depend: []*task,
- output: path::path,
+ output: str,
cmd: []str,
};
type plan = struct {
- workdir: path::path,
+ workdir: str,
+ counter: uint,
scheduled: []*task,
complete: []*task,
+ script: str,
+};
+
+// Schedules a task which compiles objects into an executable.
+fn sched_ld(plan: *plan, output: str, depend: *task...) *task = {
+ let task = alloc(task {
+ status = status::SCHEDULED,
+ output = output,
+ depend = mkdepends(depend...),
+ cmd = alloc([
+ os::tryenv("LD", "ld"),
+ "-T", plan.script,
+ "-o", output,
+ ]),
+ });
+ for (let i = 0z; i < len(depend); i += 1) {
+ append(task.cmd, depend[i].output);
+ };
+ append(plan.scheduled, task);
+ return task;
+};
+
+// Schedules a task which compiles assembly into an object.
+fn sched_as(plan: *plan, output: str, depend: *task) *task = {
+ let task = alloc(task {
+ status = status::SCHEDULED,
+ output = output,
+ depend = mkdepends(depend),
+ cmd = alloc([
+ os::tryenv("AS", "as"), "-o", output, depend.output,
+ ]),
+ });
+ append(plan.scheduled, task);
+ return task;
+};
+
+// Schedules a task which compiles an SSA file into assembly.
+fn sched_qbe(plan: *plan, output: str, depend: *task) *task = {
+ let task = alloc(task {
+ status = status::SCHEDULED,
+ output = output,
+ depend = mkdepends(depend),
+ cmd = alloc([
+ os::tryenv("QBE", "qbe"), "-o", output, depend.output,
+ ]),
+ });
+ append(plan.scheduled, task);
+ return task;
};
+// Schedules tasks which compiles hare sources into an executable.
fn sched_hare_exe(
plan: *plan,
inputs: []module::input,
- output: path::path,
- depend: []*task,
+ output: str,
+ depend: *task...
) *task = {
- // TODO: Schedule the qbe, as, and ld tasks
- let task = alloc(task {
+ // TODO: Handle mixed sources
+ let ssa = mkfile(plan, "ssa");
+ let s = mkfile(plan, "s");
+ let o = mkfile(plan, "o");
+
+ let harec = alloc(task {
status = status::SCHEDULED,
- inputs = inputs,
- output = output,
- depend = depend,
- cmd = alloc([os::tryenv("HAREC", "harec"), "-o", output as str]),
+ output = ssa,
+ depend = mkdepends(depend...),
+ cmd = alloc([
+ os::tryenv("HAREC", "harec"), "-o", ssa,
+ ]),
});
+
for (let i = 0z; i < len(inputs); i += 1) {
- let path = inputs[i].path as str;
- append(task.cmd, path);
+ let path = inputs[i].path;
+ append(harec.cmd, path);
};
- append(plan.scheduled, task);
- return task;
+ append(plan.scheduled, harec);
+
+ let qbe = sched_qbe(plan, s, harec);
+ let asm = sched_as(plan, o, qbe);
+ return sched_ld(plan, output, asm);
};
fn execute(
@@ -55,9 +113,24 @@ fn execute(
fmt::errorln();
let cmd = exec::cmd(task.cmd[0], task.cmd[1..]...)?;
- exec::setenv(&cmd, "HARECACHE", ctx.cache as str);
+ exec::setenv(&cmd, "HARECACHE", ctx.cache);
let proc = exec::start(&cmd)?;
let st = exec::wait(&proc)?;
return exec::check(&st)?;
};
+
+fn mkfile(plan: *plan, ext: str) str = {
+ static let namebuf: [32]u8 = [0...];
+ const name = fmt::bsprintf(namebuf, "temp.{}.{}",
+ plan.counter, ext);
+ plan.counter += 1;
+ return path::join(plan.workdir, name);
+};
+
+fn mkdepends(t: *task...) []*task = {
+ // XXX: This should just be one alloc call
+ let deps: []*task = alloc([], len(t));
+ append(deps, ...t);
+ return deps;
+};