Skip to content

Commit

Permalink
generate stubs for function returning at FA0 and A0 separately
Browse files Browse the repository at this point in the history
  • Loading branch information
glyh committed Oct 22, 2024
1 parent 6bcafec commit dee0dd4
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 10 deletions.
18 changes: 14 additions & 4 deletions src/riscv/collect_labels.mbt
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
fn collect_externals(cfg : @ssacfg.SsaCfg) -> @hashset.T[Var] {
let out : @hashset.T[Var] = @hashset.new()
struct ExternalLabels {
returns_i : @hashset.T[Var]
returns_f : @hashset.T[Var]
}

fn collect_externals(cfg : @ssacfg.SsaCfg) -> ExternalLabels {
let out = { returns_i: @hashset.new(), returns_f: @hashset.new() }
fn collect_label_var(v : Var) {
if v.id < 0 {
out.insert(v)
//println("adding \{v}, now: \{out}")
guard let Fun(_, ret) = v.ty.val else {
_ => @util.die("unexpected non function external: \{v}")
}
match ret {
Double => out.returns_f.insert(v)
_ => out.returns_i.insert(v)
}
}
}

Expand Down
58 changes: 52 additions & 6 deletions src/riscv/emit.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ pub fn emit(cfg : @ssacfg.SsaCfg) -> Array[AssemblyFunction] {
cfg.counter += 1
stub_label.val = "c_stub_\{cfg.counter}"
cfg.counter += 1
let stub_resolved = "c_stub_resolved_\{cfg.counter}"
let stub_resolved_i = "c_stub_resolved_i_\{cfg.counter}"
cfg.counter += 1
let body : Array[RvAsm] = []
//println(collect_externals(cfg))
for external in collect_externals(cfg) {
let externals = collect_externals(cfg)
// generate stubs for function returning ints
for external in externals.returns_i {
guard let @typing.Type::Fun(args, _) = external.ty.val else {
_ => @util.die("external non function \{external}")
}
Expand All @@ -35,7 +36,7 @@ pub fn emit(cfg : @ssacfg.SsaCfg) -> Array[AssemblyFunction] {
[
Comment("store the register holding continuation"),
Mv(S1, kont_reg),
J(stub_resolved),
J(stub_resolved_i),
],
)
}
Expand All @@ -45,17 +46,62 @@ pub fn emit(cfg : @ssacfg.SsaCfg) -> Array[AssemblyFunction] {
// to a2(where we store continuaion) and then call the continuation
body.append(
[
Label(stub_resolved),
Label(stub_resolved_i),
Comment("call the external function"),
Jalr(T6),
Comment("put continuation as 2nd arg"),
Comment("A0 holds result, put continuation as 2nd arg"),
Mv(A1, S1),
Comment("fetch continuation address"),
Ld(T1, { base: S1, offset: 0 }),
Comment("call continuation"),
Jr(T1),
],
)
// generates stub for function returning floats
let stub_resolved_f = "c_stub_resolved_f_\{cfg.counter}"
cfg.counter += 1
for external in externals.returns_f {
guard let @typing.Type::Fun(args, _) = external.ty.val else {
_ => @util.die("external non function \{external}")
}
let fn_name = external.to_string()
body.append([Label(fn_name), La(T6, Label("minimbt_" + fn_name))])
let int_arg_cnt = args.iter().filter(fn(arg) { arg != Double }).count()
let kont_reg = match int_arg_cnt {
0 => A0
1 => A1
2 => A2
3 => A3
4 => A4
5 => A5
_ => @util.die("too many args for external call")
}
// we never return so it's safe to modify the stored regs without backing up
body.append(
[
Comment("store the register holding continuation"),
Mv(S1, kont_reg),
J(stub_resolved_f),
],
)
}
// now in swap reg stores our target function's address
// S1 stores the continuation
// we just need to first call the target function, then move closure pointer
// to a2(where we store continuaion) and then call the continuation
body.append(
[
Label(stub_resolved_f),
Comment("call the external function"),
Jalr(T6),
Comment("Fa0 holds result, put continuation as 2nd arg"),
Mv(A0, S1),
Comment("fetch continuation address"),
Ld(T1, { base: S1, offset: 0 }),
Comment("call continuation"),
Jr(T1),
],
)
let stub_fn : AssemblyFunction = { name: stub_label.val, export: false, body }
output.push(stub_fn)
// genereating asm code for all functions
Expand Down

0 comments on commit dee0dd4

Please sign in to comment.