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 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) {

View File

@ -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);