aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.zig
diff options
context:
space:
mode:
authorMathias Magnusson <mathias@magnusson.space>2025-07-24 22:15:03 +0200
committerMathias Magnusson <mathias@magnusson.space>2025-07-24 22:17:19 +0200
commit0fa2f445eb7140214471074fc544adfd0f8a524f (patch)
treecb3bca4a9604df71cfe0cfcdb0c0f1e3590923ea /src/codegen.zig
parentb3909efb3a6bf76870b686b5062f9a4282fbdd66 (diff)
downloadhuginn-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.zig26
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| {