aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/codegen.zig111
-rw-r--r--src/compile.zig21
-rw-r--r--src/main.zig2
3 files changed, 91 insertions, 43 deletions
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 {
diff --git a/src/compile.zig b/src/compile.zig
index acae7ff..c837495 100644
--- a/src/compile.zig
+++ b/src/compile.zig
@@ -14,7 +14,7 @@ pub const Instr = struct {
pub const Type = union(enum) {
constant: Constant,
bin_op: BinOp,
- print: Print,
+ proc_call: ProcCall,
discard: Discard,
};
@@ -43,11 +43,17 @@ pub const Instr = struct {
}
};
- pub const Print = struct {
+ pub const ProcCall = struct {
dest: VReg,
arg: VReg,
+ proc: Proc,
- pub fn sources(self: Print) Sources {
+ const Proc = enum {
+ print,
+ read_int,
+ };
+
+ pub fn sources(self: ProcCall) Sources {
return Sources.fromSlice(&.{self.arg}) catch unreachable;
}
};
@@ -68,7 +74,7 @@ pub const Instr = struct {
pub fn dest(self: *const Instr) ?VReg {
return switch (self.type) {
- inline .constant, .bin_op, .print => |s| s.dest,
+ inline .constant, .bin_op, .proc_call => |s| s.dest,
// inline .x => null,
};
}
@@ -167,14 +173,13 @@ const CompileContext = struct {
});
},
.call => |call| {
- if (call.proc.type != .identifier or
- !std.mem.eql(u8, call.proc.loc.getIdent(self.source), "print"))
- return error.CantCallAnythingButPrint;
+ if (call.proc.type != .identifier) return error.CanOnlyCallIdentifiers;
+ const proc = std.meta.stringToEnum(Instr.ProcCall.Proc, call.proc.loc.getIdent(self.source)) orelse return error.UnknownProcedure;
const arg = try self.compileExpr(call.arg);
try self.addInstr(.{
.loc = expr.loc,
- .type = .{ .print = .{ .dest = dest, .arg = arg } },
+ .type = .{ .proc_call = .{ .dest = dest, .arg = arg, .proc = proc } },
});
},
.identifier => {
diff --git a/src/main.zig b/src/main.zig
index 7e0794a..15118d8 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -37,7 +37,7 @@ pub fn main() !void {
// }
const source =
- \\let x = 1;
+ \\let x = read_int(0);
\\print(18446744073709551615);
\\print(x + x);
;