From e5d311f91ecda870c8e50d3f9c860b99e244a908 Mon Sep 17 00:00:00 2001 From: Nic Gaffney Date: Sun, 28 Jul 2024 01:33:19 -0500 Subject: Added const, var, and assigning variables. --- src/codegen.zig | 103 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 87 insertions(+), 16 deletions(-) (limited to 'src/codegen.zig') diff --git a/src/codegen.zig b/src/codegen.zig index a200e23..98501c2 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -18,35 +18,106 @@ pub const Generator = struct { self.code.deinit(); } - fn genExit(self: *Generator, expr: parse.NodeExpr) ![]const u8 { - return try std.fmt.allocPrint(self.allocator, - \\ mov rax, 60 - \\ mov rdi, {d} - \\ syscall + fn genExit(self: *Generator, expr: parse.NodeExpr) !void { + const newCode = + switch (expr) { + .intLit => try std.fmt.allocPrint(self.allocator, + \\ mov rax, 60 + \\ mov rdi, {d} + \\ syscall + \\ + , .{ + expr.intLit.intlit.intLit, + }), + .ident => try std.fmt.allocPrint(self.allocator, + \\ mov rax, 60 + \\ mov rdi, [{s}] + \\ syscall + \\ + , .{ + expr.ident.ident.ident, + }), + }; + try self.code.appendSlice(newCode); + self.allocator.free(newCode); + } + + fn genValue(self: *Generator, value: parse.NodeValue) !void { + const str = try std.fmt.allocPrint(self.allocator, + \\section .data + \\ {s}: dw {d} \\ - , .{switch (expr) { - .intLit => expr.intLit.intlit.intLit, + , .{ value.ident.ident, switch (value.value) { + .intLit => value.value.intLit.intlit.intLit, else => return error.NotImplemented, - }}); + } }); + defer self.allocator.free(str); + try self.code.insertSlice(0, str); } - fn genValue(self: *Generator) ![]const u8 { - _ = self; - return error.NotImplemented; + fn genAssign(self: *Generator, assign: parse.NodeAssign) !void { + const newCode = + switch (assign.value) { + .intLit => try std.fmt.allocPrint(self.allocator, + \\ mov rax, {d} + \\ mov [{s}], rax + \\ + , .{ + assign.value.intLit.intlit.intLit, + assign.ident.ident, + }), + .ident => try std.fmt.allocPrint(self.allocator, + \\ mov rax, [{s}] + \\ mov [{s}], rax + \\ + , .{ + assign.value.ident.ident.ident, + assign.ident.ident, + }), + }; + try self.code.appendSlice(newCode); + self.allocator.free(newCode); } pub fn generate(self: *Generator) ![]const u8 { try self.code.appendSlice( - \\global _start: + \\section .text + \\ global _start + \\_start: \\ ); for (self.root) |stmt| { - const code = switch (stmt) { + switch (stmt) { .exit => try self.genExit(stmt.exit.expr), - .value => try self.genValue(), - }; - try self.code.appendSlice(code); + .value => try self.genValue(stmt.value), + .assign => try self.genAssign(stmt.assign), + } } return self.code.items; } }; + +test "Codegen exit" { + const tok = @import("tokenize.zig"); + const expect = std.testing.expect; + const src = "exit 120;"; + var tokenizer = tok.Tokenizer.init(std.testing.allocator, src); + defer tokenizer.deinit(); + const toks = try tokenizer.tokenize(); + var parser = parse.Parser.init(std.testing.allocator, toks); + defer parser.deinit(); + const parseTree = try parser.parse(); + var gen = Generator.init(std.testing.allocator, parseTree); + defer gen.deinit(); + const actual = try gen.generate(); + const expected = + \\section .text + \\ global _start + \\_start: + \\ mov rax, 60 + \\ mov rdi, 120 + \\ syscall + \\ + ; + try expect(std.mem.eql(u8, actual, expected)); +} -- cgit v1.2.3