codegen: allow for mutable statements
- ast: add llvm_alloca llvmvalueref pointer in VarDeclStmt
This commit is contained in:
parent
d235ce0d13
commit
178acc656f
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue