From 178acc656f78c219f1b89c47bc412643ebe3a72a Mon Sep 17 00:00:00 2001 From: Luna Date: Fri, 27 Sep 2019 22:49:33 -0300 Subject: [PATCH] codegen: allow for mutable statements - ast: add llvm_alloca llvmvalueref pointer in VarDeclStmt --- src/ast.zig | 2 ++ src/codegen.zig | 33 ++++++++++++++++++++++----------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/ast.zig b/src/ast.zig index 02093ed..efb0015 100644 --- a/src/ast.zig +++ b/src/ast.zig @@ -1,5 +1,6 @@ const std = @import("std"); const tokens = @import("tokens.zig"); +const llvm = @import("llvm.zig"); const Token = tokens.Token; pub const NodeList = std.ArrayList(Node); @@ -184,6 +185,7 @@ pub const ForStmt = struct { pub const VarDeclStmt = struct { name: Token, value: *Expr, + llvm_alloca: ?llvm.LLVMValueRef = null, }; pub const Stmt = union(enum) { diff --git a/src/codegen.zig b/src/codegen.zig index b7212eb..f06ba92 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -238,6 +238,9 @@ pub const Codegen = struct { var param = metadata.from_function.?.parameters.get(vari.lexeme).?.value; var llvm_func = self.llvm_table.get(self.current_function_name.?).?.value; + // TODO we should create stack-stored variables + // instead of the arg registers + // may i thank all the demons in hell for giving me // good energies to make this work break :blk llvm.LLVMGetParam(llvm_func, @intCast(c_uint, param.idx)); @@ -254,7 +257,7 @@ pub const Codegen = struct { }; } - fn emitStmt(self: *Codegen, builder: var, stmt: *const ast.Stmt) anyerror!void { + fn emitStmt(self: *Codegen, builder: var, stmt: *ast.Stmt) anyerror!void { switch (stmt.*) { .Expr => |expr| _ = try self.emitExpr(builder, expr), @@ -286,11 +289,12 @@ pub const Codegen = struct { self.ctx.setScope(self.ctx.current_scope.?.nextChild()); - for (ifstmt.then_branch.toSlice()) |then_stmt| { + var then_branch = ifstmt.then_branch.toSlice(); + for (then_branch) |_, idx| { // keep emitting until branch has ret if (!then_rets) - try self.emitStmt(builder, &then_stmt); + try self.emitStmt(builder, &then_branch[idx]); switch (then_stmt) { .Return => then_rets = true, @@ -314,10 +318,12 @@ pub const Codegen = struct { // 'Else *ElseV = Else->codegen();' if (ifstmt.else_branch) |else_block| { self.ctx.setScope(self.ctx.current_scope.?.nextChild()); - for (else_block.toSlice()) |else_stmt| { + + var else_slice = else_block.toSlice(); + for (else_slice) |_, idx| { // keep emitting until branch has ret if (!else_rets) - try self.emitStmt(builder, &else_stmt); + try self.emitStmt(builder, &else_slice[idx]); switch (else_stmt) { .Return => else_rets = true, @@ -335,11 +341,12 @@ pub const Codegen = struct { llvm.LLVMPositionBuilderAtEnd(builder, merge_bb); + // if both of the branches return, we should put + // the merge branch as unreachable. if (then_rets and else_rets) _ = llvm.LLVMBuildUnreachable(builder); }, - // TODO .VarDecl => |vardecl| { // we alaready inferred the type of the variable in the // analyze pass and the current scope contains the variable's @@ -352,14 +359,17 @@ pub const Codegen = struct { var fn_symbol = self.getFnSymbol(self.current_function_name.?); - _ = llvm.LLVMBuildAlloca( + // TODO add llvm value ref to var metadata as well + var variable = llvm.LLVMBuildAlloca( builder, try self.typeToLLVM(var_metadata.typ), name_cstr.ptr, ); - // TODO generate the store for the initializer - //var llvm_expr = try self.emitExpr(vardecl.value); + vardecl.llvm_alloca = variable; + + var llvm_expr = try self.emitExpr(builder, vardecl.value); + _ = llvm.LLVMBuildStore(builder, llvm_expr, variable); }, else => { @@ -423,8 +433,9 @@ pub const Codegen = struct { self.ctx.setScope(fn_sym.scope); defer self.ctx.dumpScope(); - for (decl.body.toSlice()) |stmt| { - try self.emitStmt(builder, &stmt); + var body_slice = decl.body.toSlice(); + for (body_slice) |_, idx| { + try self.emitStmt(builder, &body_slice[idx]); } std.debug.warn("cgen: generated function '{}'\n", name);