aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen.zig')
-rw-r--r--src/codegen.zig49
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(),
});