From 068ff09a96ad3cdea31d788c053ea3d544713e39 Mon Sep 17 00:00:00 2001 From: Nic Gaffney Date: Wed, 7 Aug 2024 02:28:47 -0500 Subject: Updated codegen to allow defining / assigning variables --- src/codegen.zig | 114 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 67 insertions(+), 47 deletions(-) (limited to 'src/codegen.zig') diff --git a/src/codegen.zig b/src/codegen.zig index e2889a6..6dde45d 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -8,6 +8,7 @@ const target = llvm.target; const types = llvm.types; const CodegenError = error{ + Immutable, OutOfMemory, }; @@ -30,6 +31,7 @@ pub const Generator = struct { module: types.LLVMModuleRef, currentFunc: ?types.LLVMValueRef, currentFuncIsVoid: bool, + references: std.AutoHashMap(u32, types.LLVMValueRef), pub fn init(allocator: std.mem.Allocator, root: parse.NodeStmt) Generator { _ = target.LLVMInitializeNativeTarget(); @@ -48,6 +50,7 @@ pub const Generator = struct { .module = module, .currentFunc = null, .currentFuncIsVoid = false, + .references = std.AutoHashMap(u32, types.LLVMValueRef).init(allocator), }; } @@ -62,61 +65,63 @@ pub const Generator = struct { fn genExit(self: *Generator, exit: parse.NodeExit) !void { const expr = exit; - const val = core.LLVMConstInt(core.LLVMInt32Type(), switch (expr.kind) { - .intLit => |i| @intCast(i.intLit), - .ident => unreachable, - }, 0); + const val = self.genExpr(expr); _ = core.LLVMBuildRet(self.builder, val); } - fn genVar(self: *Generator, value: parse.NodeVar) !void { - const str = try std.fmt.allocPrint(self.allocator, - \\section .data - \\ {s}: dw {d} - \\ - , .{ value.ident.ident, switch (value.expr.kind) { - .intLit => |intlit| intlit.intLit, - else => return error.NotImplemented, - } }); - defer self.allocator.free(str); - try self.code.insertSlice(0, str); + fn genVar(self: *Generator, stmt: parse.NodeStmt) !void { + const nodeVar = stmt.kind.defVar; + + const table = stmt.symtable; + const symbol = table.getValue(nodeVar.ident.ident).?; + const value = self.genExpr(nodeVar.expr); + const ptr = try self.genAlloc(toLLVMtype(nodeVar.expr.typ.?, table).?, nodeVar.ident.ident); + _ = core.LLVMBuildStore(self.builder, value, ptr); + try self.references.put(symbol.id, ptr); + } + + fn genValue(self: *Generator, stmt: parse.NodeStmt) !void { + const nodeVar = stmt.kind.defValue; + + const table = stmt.symtable; + const symbol = table.getValue(nodeVar.ident.ident).?; + const ptr = try self.genAlloc(toLLVMtype(nodeVar.expr.typ.?, table), nodeVar.ident.ident); + const value = self.genExpr(nodeVar.expr); + _ = core.LLVMBuildStore(self.builder, value, ptr); + try self.references.put(symbol.id, ptr); } - fn genValue(self: *Generator, value: parse.NodeValue) !void { - const str = try std.fmt.allocPrint(self.allocator, - \\section .data - \\ {s}: dw {d} - \\ - , .{ value.ident.ident, switch (value.expr.kind) { - .intLit => |intlit| intlit.intLit, - else => return error.NotImplemented, - } }); - defer self.allocator.free(str); - try self.code.insertSlice(0, str); + fn genAlloc(self: *Generator, typ: types.LLVMTypeRef, ident: []const u8) !types.LLVMValueRef { + const builder = core.LLVMCreateBuilderInContext(self.context); + + const entryFunc = self.currentFunc.?; + const entry = core.LLVMGetFirstBasicBlock(entryFunc).?; + + if (core.LLVMGetFirstInstruction(entry)) |first| { + core.LLVMPositionBuilderBefore(builder, first); + } else { + core.LLVMPositionBuilderAtEnd(builder, entry); + } + + const str: [*:0]const u8 = try self.allocator.dupeZ(u8, ident); + return core.LLVMBuildAlloca(builder, typ, str); } - fn genAssign(self: *Generator, assign: parse.NodeAssign) !void { - const newCode = - switch (assign.expr.kind) { - .intLit => |intlit| try std.fmt.allocPrint(self.allocator, - \\ mov rax, {d} - \\ mov [{s}], rax - \\ - , .{ - intlit.intLit, - assign.ident.ident, - }), - .ident => |ident| try std.fmt.allocPrint(self.allocator, - \\ mov rax, [{s}] - \\ mov [{s}], rax - \\ - , .{ - ident.ident, - assign.ident.ident, - }), + fn asBasicType(typ: symb.SymbType) ?types.LLVMTypeKind { + return switch (typ) { + .Integer => types.LLVMTypeKind.LLVMIntegerTypeKind, + else => null, }; - try self.code.appendSlice(newCode); - self.allocator.free(newCode); + } + + fn genAssign(self: *Generator, stmt: parse.NodeStmt) !void { + std.debug.print("assign\n", .{}); + const table = stmt.symtable; + const symbol = table.get(stmt.kind.assignVar.ident.ident).?; + if (!symbol.Value.mut) return CodegenError.Immutable; + const ptr = self.references.get(symbol.Value.id).?; + const value = self.genExpr(stmt.kind.assignVar.expr); + _ = core.LLVMBuildStore(self.builder, value, ptr); } fn genBlock(self: *Generator, block: []const parse.NodeStmt) CodegenError!void { @@ -155,10 +160,25 @@ pub const Generator = struct { try switch (stmt.kind) { .exit => |expr| self.genExit(expr), .function => self.genFunc(stmt), + .defValue => self.genValue(stmt), + .defVar => self.genVar(stmt), + .assignVar => self.genAssign(stmt), else => {}, }; } + fn genExpr(self: *Generator, expr: parse.NodeExpr) types.LLVMValueRef { + return switch (expr.kind) { + .ident => blk: { + const table = expr.symtable; + const symbol = table.getValue(expr.kind.ident.ident).?; + const ptr = self.references.get(symbol.id).?; + break :blk core.LLVMBuildLoad2(self.builder, toLLVMtype(expr.typ.?, table), ptr, ""); + }, + .intLit => |int| core.LLVMConstInt(core.LLVMInt32TypeInContext(self.context), @intCast(int.intLit), 1), + }; + } + pub fn generate(self: *Generator) ![]const u8 { try switch (self.root.kind) { .block => |b| { -- cgit v1.2.3