codegen: allow for mutable statements
- ast: add llvm_alloca llvmvalueref pointer in VarDeclStmt
This commit is contained in:
parent
d235ce0d13
commit
178acc656f
2 changed files with 24 additions and 11 deletions
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue