hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 3cf277739c142cdc611415ca605639aa39c38d20
parent dbd2d7a542ae38337ff7e34758262bd0a1cebcb0
Author: Lorenz (xha) <me@xha.li>
Date:   Sat,  9 Dec 2023 18:20:24 +0100

cmd::hare add comments and cleanup

Signed-off-by: Lorenz (xha) <me@xha.li>

Diffstat:
Mcmd/hare/build.ha | 15++++++++++++---
Mcmd/hare/build/queue.ha | 14+++++++++-----
Mcmd/hare/build/util.ha | 9+++++++++
Mhare/module/deps.ha | 1+
4 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/cmd/hare/build.ha b/cmd/hare/build.ha @@ -123,25 +123,29 @@ fn build(name: str, cmd: *getopt::command) (void | error) = { case 'v' => if (ctx.mode == build::output::VERBOSE) { ctx.mode = build::output::VVERBOSE; - } else { + } else if (ctx.mode != build::output::VVERBOSE) { ctx.mode = build::output::VERBOSE; + } else { + fmt::fatal("Number of verbose levels must be <= 2"); }; case => abort(); }; }; - if (len(cmd.args) > 1 && name == "build") { + + if (name == "build" && len(cmd.args) > 1) { getopt::printusage(os::stderr, name, cmd.help...)!; os::exit(os::status::FAILURE); }; + set_arch_tags(&ctx.ctx.tags, arch); + ctx.cmds = ["", os::tryenv("HAREC", "harec"), os::tryenv("QBE", "qbe"), os::tryenv("AS", arch.as_cmd), os::tryenv("LD", arch.ld_cmd), ]; - set_arch_tags(&ctx.ctx.tags, arch); if (len(ctx.libs) > 0 || ctx.platform.need_libc) { ctx.libc = true; merge_tags(&ctx.ctx.tags, "+libc")?; @@ -169,6 +173,9 @@ fn build(name: str, cmd: *getopt::command) (void | error) = { if (ctx.goal == build::stage::BIN) { mode |= 0o111; }; + // in the case that we are outputting to a binary that is + // currently beeing executed, we need to remove it first or + // otherwise os::create() will fail os::remove(output): void; dest = match (os::create(output, mode)) { case let f: io::file => @@ -178,6 +185,7 @@ fn build(name: str, cmd: *getopt::command) (void | error) = { }; }; defer io::close(dest)!; + let src = os::open(built)?; defer io::close(src)!; io::copy(dest, src)?; @@ -204,6 +212,7 @@ fn get_output(goal: build::stage, input: str) (str | error) = { if (!fs::isdir(stat.mode)) { path::pop(&buf); }; + // don't add the .bin extension if the goal is to create a binary if (goal != build::stage::BIN) { path::push_ext(&buf, build::stage_ext[goal])?; }; diff --git a/cmd/hare/build/queue.ha b/cmd/hare/build/queue.ha @@ -34,6 +34,8 @@ export fn execute(ctx: *context) (str | error) = { defer for (let i = 0z; i < len(q); i += 1) { free_task(q[i]); }; + + // stage::TD (typedef files) are generated by the SSA stage (harec) const goal = if (ctx.goal == stage::TD) stage::SSA else ctx.goal; queue(ctx, &q, goal, ctx.top); // sort by stage, harec then qbe then as then ld, and keep reverse @@ -74,6 +76,7 @@ fn task_cmp(a: const *opaque, b: const *opaque) int = { }; fn queue(ctx: *context, q: *[]*task, kind: stage, idx: size) *task = { + // return already existing task to avoid creating duplicates for (let i = 0z; i < len(q); i += 1) { if (q[i].kind == kind && q[i].idx == idx) { return q[i]; @@ -95,9 +98,9 @@ fn queue(ctx: *context, q: *[]*task, kind: stage, idx: size) *task = { append(queue(ctx, q, kind - 1, idx).rdeps, t); case stage::SSA => t.ndeps = len(ctx.mods[idx].deps); - for (let i = 0z; i < len(ctx.mods[idx].deps); i += 1) { - let j = ctx.mods[idx].deps[i].0; - append(queue(ctx, q, stage::SSA, j).rdeps, t); + for (let i = 0z; i < t.ndeps; i += 1) { + let dep_idx = ctx.mods[idx].deps[i].0; + append(queue(ctx, q, stage::SSA, dep_idx).rdeps, t); }; case stage::TD => abort(); }; @@ -105,11 +108,13 @@ fn queue(ctx: *context, q: *[]*task, kind: stage, idx: size) *task = { return t; }; +// returns true if the task was executed. returns false if the task cannot be +// executed (because it is waiting for dependencies) or if the task is already +// running (possibly in another instance of this build driver) fn run_task(ctx: *context, jobs: *[]job, t: *task) (bool | error) = { if (len(jobs) == ctx.jobs) { await_task(ctx, jobs)?; }; - assert(len(jobs) < ctx.jobs); if (t.ndeps != 0) { return false; }; @@ -156,7 +161,6 @@ fn run_task(ctx: *context, jobs: *[]job, t: *task) (bool | error) = { return true; }; - switch (ctx.mode) { case output::DEFAULT, output::SILENT => void; case output::VERBOSE => diff --git a/cmd/hare/build/util.ha b/cmd/hare/build/util.ha @@ -74,6 +74,9 @@ fn get_deps(ctx: *context, t: *task) []str = { }; }; +// returns the arguments that don't depend on the result of the hash. these will +// be used to create the hash. see [[get_args]] for the arguments that depend +// on the result of the hash fn get_flags(ctx: *context, t: *task) ([]str | error) = { let flags: []str = strings::dupall(ctx.platform.default_flags[t.kind]); @@ -226,6 +229,8 @@ fn get_hash( return prefix; }; +// returns the value of flags plus the arguments that depend on the result of +// the hash. see [[get_flags]] for the arguments that don't depend on the hash fn get_args(ctx: *context, tmp: str, flags: []str, t: *task) []str = { let args = strings::dupall(flags); append(args, strings::dup("-o")); @@ -258,6 +263,10 @@ fn get_args(ctx: *context, tmp: str, flags: []str, t: *task) []str = { append(args, strings::dup(srcs.o[i])); }; }; + // XXX: when dynamically linking on Linux, we have to disable + // gc-sections again after enabling it in get_flags(); it looks + // like leaving this enabled gets us SIGILL in libc (musl). this + // is not broken on other platforms such as OpenBSD if (ctx.libc) { append(args, strings::dup("-Wl,--no-gc-sections")); }; diff --git a/hare/module/deps.ha b/hare/module/deps.ha @@ -22,6 +22,7 @@ export type module = struct { ns: ast::ident, path: str, srcs: srcset, + // [](Index to the module, Identifier of of the module) deps: [](size, ast::ident), };