diff options
author | Mathias Magnusson <mathias@magnusson.space> | 2025-07-24 22:15:03 +0200 |
---|---|---|
committer | Mathias Magnusson <mathias@magnusson.space> | 2025-07-24 22:17:19 +0200 |
commit | 0fa2f445eb7140214471074fc544adfd0f8a524f (patch) | |
tree | cb3bca4a9604df71cfe0cfcdb0c0f1e3590923ea /src/codegen.zig | |
parent | b3909efb3a6bf76870b686b5062f9a4282fbdd66 (diff) | |
download | huginn-0fa2f445eb7140214471074fc544adfd0f8a524f.tar.gz |
continue implementing procedure calls
multiple procedures can now exist, but you cannot call them, the first
one is the "main" procedure since it happens to be placed first in the
binary, and all procedures end with an exit system call
Diffstat (limited to 'src/codegen.zig')
-rw-r--r-- | src/codegen.zig | 26 |
1 files changed, 16 insertions, 10 deletions
diff --git a/src/codegen.zig b/src/codegen.zig index a1c2171..00b3857 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -563,7 +563,7 @@ const Relocation = struct { const Context = struct { instructions: std.ArrayList(Instruction), relocations: std.ArrayList(Relocation), - block_starts: std.ArrayList(usize), + block_addrs: std.AutoHashMap(compile.BlockRef, usize), print_block: compile.BlockRef, read_int_block: compile.BlockRef, @@ -767,7 +767,7 @@ const ProcedureContext = struct { fn codegenProc(self: *Self, proc: compile.Procedure) !void { for (proc.blocks) |block| { - try self.ctx.block_starts.append(self.ctx.instructions.items.len); + try self.ctx.block_addrs.putNoClobber(block.ref, self.ctx.instructions.items.len); try self.codegenBlock(block); } } @@ -845,17 +845,23 @@ fn codegenReadInt(self: *Context) !void { try self.emit(.jalr(.zero, .ra, 0)); } -pub fn create_elf(allocator: Allocator, proc: compile.Procedure) ![]u8 { +pub fn create_elf(allocator: Allocator, mod: compile.Module) ![]u8 { + var maxBlockRef: usize = 0; + for (mod.procedures) |proc| { + for (proc.blocks) |block| { + maxBlockRef = @max(maxBlockRef, @intFromEnum(block.ref)); + } + } var ctx: Context = .{ .instructions = .init(allocator), .relocations = .init(allocator), - .block_starts = .init(allocator), - .print_block = @enumFromInt(proc.blocks.len), - .read_int_block = @enumFromInt(proc.blocks.len + 1), + .block_addrs = .init(allocator), + .print_block = @enumFromInt(maxBlockRef + 1), + .read_int_block = @enumFromInt(maxBlockRef + 2), }; defer ctx.deinit(); - { + for (mod.procedures) |proc| { var proc_ctx: ProcedureContext = .{ .register_allocator = try .init(allocator, &.{ .t6, .t5, .t4, .t3, .t2, .t1, .t0 }), .lvar_allocator = try .init(allocator, &.{ .s11, .s10, .s9, .s8, .s7, .s6, .s5, .s4, .s3, .s2, .s1, .s0 }), @@ -867,15 +873,15 @@ pub fn create_elf(allocator: Allocator, proc: compile.Procedure) ![]u8 { std.debug.assert(proc_ctx.register_allocator.allocated.count() == 0); } - try ctx.block_starts.append(ctx.instructions.items.len); + try ctx.block_addrs.putNoClobber(ctx.print_block, ctx.instructions.items.len); try codegenPrint(&ctx); - try ctx.block_starts.append(ctx.instructions.items.len); + try ctx.block_addrs.putNoClobber(ctx.read_int_block, ctx.instructions.items.len); try codegenReadInt(&ctx); // TODO: make this less sheiße for (ctx.relocations.items) |relocation| { const instr = &ctx.instructions.items[relocation.instr]; - const target: isize = @intCast(ctx.block_starts.items[@intFromEnum(relocation.target)]); + const target: isize = @intCast(ctx.block_addrs.get(relocation.target).?); const from: isize = @intCast(relocation.instr); switch (instr.*) { .j => |j| { |