From e18b172d3e4e31b4d50ca978a66187730f744a31 Mon Sep 17 00:00:00 2001 From: Mathias Magnusson Date: Mon, 2 Jun 2025 21:13:42 +0200 Subject: add read_int built in procedure --- src/codegen.zig | 111 +++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 77 insertions(+), 34 deletions(-) (limited to 'src/codegen.zig') diff --git a/src/codegen.zig b/src/codegen.zig index 07f3a4d..d2b5d2a 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -610,40 +610,83 @@ const Context = struct { } } - fn genPrint(self: *Context, print: compile.Instr.Print) !void { - const num = self.register_allocator.get(print.arg); - - const quot = try self.register_allocator.allocateAux(); - defer self.register_allocator.freeAux(quot); - const digit = try self.register_allocator.allocateAux(); - defer self.register_allocator.freeAux(digit); - const count = try self.register_allocator.allocate(print.dest); - - try self.maybeFreeSources(); - - try self.emit(.addi(digit, .zero, '\n')); - try self.emit(.addi(.sp, .sp, -1)); - try self.emit(.sb(.sp, 0, digit)); - try self.emit(.addi(count, .zero, 1)); - try self.emit(.addi(quot, .zero, 10)); - - try self.emit(.addi(digit, num, 0)); - try self.emit(.divu(num, digit, quot)); - try self.emit(.remu(digit, digit, quot)); - try self.emit(.addi(digit, digit, '0')); - try self.emit(.addi(.sp, .sp, -1)); - try self.emit(.sb(.sp, 0, digit)); - try self.emit(.addi(count, count, 1)); - try self.emit(.bne(num, .zero, -4 * 7)); - - 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)); - - try self.emit(.addi(count, count, -1)); + fn genProcCall(self: *Context, call: compile.Instr.ProcCall) !void { + switch (call.proc) { + .print => { + const num = self.register_allocator.get(call.arg); + + const quot = try self.register_allocator.allocateAux(); + defer self.register_allocator.freeAux(quot); + const digit = try self.register_allocator.allocateAux(); + defer self.register_allocator.freeAux(digit); + const count = try self.register_allocator.allocate(call.dest); + + try self.maybeFreeSources(); + + try self.emit(.addi(digit, .zero, '\n')); + try self.emit(.addi(.sp, .sp, -1)); + try self.emit(.sb(.sp, 0, digit)); + try self.emit(.addi(count, .zero, 1)); + try self.emit(.addi(quot, .zero, 10)); + + try self.emit(.addi(digit, num, 0)); + try self.emit(.divu(num, digit, quot)); + try self.emit(.remu(digit, digit, quot)); + try self.emit(.addi(digit, digit, '0')); + try self.emit(.addi(.sp, .sp, -1)); + try self.emit(.sb(.sp, 0, digit)); + try self.emit(.addi(count, count, 1)); + try self.emit(.bne(num, .zero, -4 * 7)); + + try self.emit(.addi(.a7, .zero, @intFromEnum(std.os.linux.syscalls.RiscV64.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)); + + try self.emit(.addi(count, count, -1)); + }, + .read_int => { + try self.maybeFreeSources(); + + const result = try self.register_allocator.allocate(call.dest); + const ptr = try self.register_allocator.allocateAux(); + defer self.register_allocator.freeAux(ptr); + const char = try self.register_allocator.allocateAux(); + defer self.register_allocator.freeAux(char); + const newline = try self.register_allocator.allocateAux(); + defer self.register_allocator.freeAux(newline); + + try self.emit(.addi(.sp, .sp, -21)); + try self.emit(.addi(newline, .zero, '\n')); + try self.emit(.addi(result, .zero, 0)); + + try self.emit(.addi(.a7, .zero, @intFromEnum(std.os.linux.syscalls.RiscV64.read))); + try self.emit(.addi(.a0, .zero, 0)); // fd = stdin + try self.emit(.addi(.a1, .sp, 0)); // buf = sp + try self.emit(.addi(.a2, .zero, 21)); // count = count + try self.emit(.ecall()); // syscall(no, fd, buf, count) + + try self.emit(.addi(ptr, .sp, 0)); + try self.emit(.add(.a0, .a0, .sp)); // a0 = end + + // loop start + try self.emit(.bgeu(ptr, .a0, 4 * 8)); // done + try self.emit(.lb(char, ptr, 0)); + try self.emit(.beq(char, newline, 4 * 6)); // done + try self.emit(.mul(result, result, newline)); // '\n' happens to also be 10 + try self.emit(.addi(char, char, -'0')); + // assert 0 <= char <= 9 + try self.emit(.add(result, result, char)); + + try self.emit(.addi(ptr, ptr, 1)); + try self.emit(.jal(.zero, -4 * 7)); // -> loop start + // done + + try self.emit(.addi(.sp, .sp, 21)); + }, + } } fn genDiscard(self: *Context, _: compile.Instr.Discard) !void { -- cgit v1.2.3