diff options
Diffstat (limited to 'src/codegen.zig')
-rw-r--r-- | src/codegen.zig | 49 |
1 files changed, 48 insertions, 1 deletions
diff --git a/src/codegen.zig b/src/codegen.zig index e52fb47..011d28a 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -529,6 +529,18 @@ const RegisterAllocator = struct { std.debug.assert(std.mem.indexOfScalar(Register, self.available.items, reg) == null); return self.available.appendAssumeCapacity(reg); } + + fn allocateAux(self: *RegisterAllocator) !Register { + const reg = self.available.pop() orelse return error.OutOfRegisters; + return reg; + } + + fn freeAux(self: *RegisterAllocator, reg: Register) void { + var it = self.allocated.valueIterator(); + while (it.next()) |r| std.debug.assert(reg != r.*); + std.debug.assert(std.mem.indexOfScalar(Register, self.available.items, reg) == null); + return self.available.appendAssumeCapacity(reg); + } }; const Context = struct { @@ -597,6 +609,41 @@ const Context = struct { } } + fn genPrint(self: *Context, print: compile.Instr.Print) !void { + const arg = self.register_allocator.get(print.arg); + + const quot = try self.register_allocator.allocateAux(); + defer self.register_allocator.freeAux(quot); + const aux1 = try self.register_allocator.allocateAux(); + defer self.register_allocator.freeAux(aux1); + const count = try self.register_allocator.allocateAux(); + defer self.register_allocator.freeAux(count); + + try self.maybeFreeSources(print.sources()); + + try self.emit(.addi(aux1, .zero, '\n')); + try self.emit(.addi(.sp, .sp, -1)); + try self.emit(.sb(.sp, 0, aux1)); + try self.emit(.addi(count, .zero, 1)); + + try self.emit(.addi(aux1, arg, 0)); + try self.emit(.addi(quot, .zero, 10)); + try self.emit(.divu(arg, aux1, quot)); + try self.emit(.remu(aux1, aux1, quot)); + try self.emit(.addi(aux1, aux1, '0')); + try self.emit(.addi(.sp, .sp, -1)); + try self.emit(.sb(.sp, 0, aux1)); + try self.emit(.addi(count, count, 1)); + try self.emit(.bne(arg, .zero, -4 * 8)); + + try self.emit(.addi(.a7, .zero, 64)); // no = write + try self.emit(.addi(.a0, .zero, 1)); // fd = stdout + try self.emit(.addi(.a1, .sp, 0)); // buf = sp + try self.emit(.addi(.a2, count, 0)); // count = count + try self.emit(.ecall()); // syscall(no, fd, buf, count) + try self.emit(.add(.sp, .sp, count)); + } + fn codegenInstr(self: *Context, instr: compile.Instr) !void { switch (instr.type) { inline else => |ty| { @@ -635,7 +682,7 @@ pub fn create_elf(allocator: Allocator, block: compile.Block) ![]u8 { try ctx.codegenBlock(block); try ctx.instructions.appendSlice(&[_]Instruction{ - .addi(.a0, ctx.register_allocator.get(block.instrs[block.instrs.len - 1].dest()), 0), + .addi(.a0, .zero, 0), .addi(.a7, .zero, 93), .ecall(), }); |