codegen: allow for mutable statements

- ast: add llvm_alloca llvmvalueref pointer in VarDeclStmt
This commit is contained in:
Luna 2019-09-27 22:49:33 -03:00
parent d235ce0d13
commit 178acc656f
2 changed files with 24 additions and 11 deletions

View File

@ -1,5 +1,6 @@
const std = @import("std"); const std = @import("std");
const tokens = @import("tokens.zig"); const tokens = @import("tokens.zig");
const llvm = @import("llvm.zig");
const Token = tokens.Token; const Token = tokens.Token;
pub const NodeList = std.ArrayList(Node); pub const NodeList = std.ArrayList(Node);
@ -184,6 +185,7 @@ pub const ForStmt = struct {
pub const VarDeclStmt = struct { pub const VarDeclStmt = struct {
name: Token, name: Token,
value: *Expr, value: *Expr,
llvm_alloca: ?llvm.LLVMValueRef = null,
}; };
pub const Stmt = union(enum) { pub const Stmt = union(enum) {

View File

@ -238,6 +238,9 @@ pub const Codegen = struct {
var param = metadata.from_function.?.parameters.get(vari.lexeme).?.value; var param = metadata.from_function.?.parameters.get(vari.lexeme).?.value;
var llvm_func = self.llvm_table.get(self.current_function_name.?).?.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 // may i thank all the demons in hell for giving me
// good energies to make this work // good energies to make this work
break :blk llvm.LLVMGetParam(llvm_func, @intCast(c_uint, param.idx)); 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.*) { switch (stmt.*) {
.Expr => |expr| _ = try self.emitExpr(builder, expr), .Expr => |expr| _ = try self.emitExpr(builder, expr),
@ -286,11 +289,12 @@ pub const Codegen = struct {
self.ctx.setScope(self.ctx.current_scope.?.nextChild()); 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 // keep emitting until branch has ret
if (!then_rets) if (!then_rets)
try self.emitStmt(builder, &then_stmt); try self.emitStmt(builder, &then_branch[idx]);
switch (then_stmt) { switch (then_stmt) {
.Return => then_rets = true, .Return => then_rets = true,
@ -314,10 +318,12 @@ pub const Codegen = struct {
// 'Else *ElseV = Else->codegen();' // 'Else *ElseV = Else->codegen();'
if (ifstmt.else_branch) |else_block| { if (ifstmt.else_branch) |else_block| {
self.ctx.setScope(self.ctx.current_scope.?.nextChild()); 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 // keep emitting until branch has ret
if (!else_rets) if (!else_rets)
try self.emitStmt(builder, &else_stmt); try self.emitStmt(builder, &else_slice[idx]);
switch (else_stmt) { switch (else_stmt) {
.Return => else_rets = true, .Return => else_rets = true,
@ -335,11 +341,12 @@ pub const Codegen = struct {
llvm.LLVMPositionBuilderAtEnd(builder, merge_bb); 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) if (then_rets and else_rets)
_ = llvm.LLVMBuildUnreachable(builder); _ = llvm.LLVMBuildUnreachable(builder);
}, },
// TODO
.VarDecl => |vardecl| { .VarDecl => |vardecl| {
// we alaready inferred the type of the variable in the // we alaready inferred the type of the variable in the
// analyze pass and the current scope contains the variable's // 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.?); 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, builder,
try self.typeToLLVM(var_metadata.typ), try self.typeToLLVM(var_metadata.typ),
name_cstr.ptr, name_cstr.ptr,
); );
// TODO generate the store for the initializer vardecl.llvm_alloca = variable;
//var llvm_expr = try self.emitExpr(vardecl.value);
var llvm_expr = try self.emitExpr(builder, vardecl.value);
_ = llvm.LLVMBuildStore(builder, llvm_expr, variable);
}, },
else => { else => {
@ -423,8 +433,9 @@ pub const Codegen = struct {
self.ctx.setScope(fn_sym.scope); self.ctx.setScope(fn_sym.scope);
defer self.ctx.dumpScope(); defer self.ctx.dumpScope();
for (decl.body.toSlice()) |stmt| { var body_slice = decl.body.toSlice();
try self.emitStmt(builder, &stmt); for (body_slice) |_, idx| {
try self.emitStmt(builder, &body_slice[idx]);
} }
std.debug.warn("cgen: generated function '{}'\n", name); std.debug.warn("cgen: generated function '{}'\n", name);