add codegen for allocating vardecls onto stack (not init yet)
codegen pass needs type information about the variable. thankfully, analyze pass already did the hard work for it, and scope info has types of all its declared names. we use that info to generate the alloca to have information about which current scope we are, we add a "child index" to scopes so we can repoint current context at them instead of bumpScope(), which always creates new, empty ones. initializer exprs are next
This commit is contained in:
parent
77c88fad34
commit
d235ce0d13
4 changed files with 52 additions and 18 deletions
|
@ -32,13 +32,12 @@ fn test_function() B {
|
|||
}
|
||||
|
||||
fn multwo(num: i32, double_flag: bool) i32 {
|
||||
// TODO resolve expr variables
|
||||
if (true) {
|
||||
if (double_flag) {
|
||||
var truthy = true;
|
||||
return 1 * 2;
|
||||
return num * 2;
|
||||
} else {
|
||||
var falsey = false;
|
||||
return 1;
|
||||
return num;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -458,7 +458,7 @@ pub const TypeSolver = struct {
|
|||
|
||||
// for a function, we always create a new root scope for it
|
||||
// and force-set it into the current context
|
||||
var scope = try comp.Scope.create(self.allocator, null, "function");
|
||||
var scope = try comp.Scope.create(self.allocator, null, name);
|
||||
errdefer scope.deinit();
|
||||
|
||||
// we intentionally insert the function so that:
|
||||
|
|
|
@ -284,6 +284,8 @@ pub const Codegen = struct {
|
|||
var then_rets = false;
|
||||
var else_rets = false;
|
||||
|
||||
self.ctx.setScope(self.ctx.current_scope.?.nextChild());
|
||||
|
||||
for (ifstmt.then_branch.toSlice()) |then_stmt| {
|
||||
|
||||
// keep emitting until branch has ret
|
||||
|
@ -296,6 +298,8 @@ pub const Codegen = struct {
|
|||
}
|
||||
}
|
||||
|
||||
self.ctx.dumpScope();
|
||||
|
||||
// only build the br instruction if we didn't ret, because
|
||||
// there can't be any instruction after a terminator
|
||||
// same applies for the else branch
|
||||
|
@ -309,6 +313,7 @@ pub const Codegen = struct {
|
|||
// roughly translating to kaleidoscope's
|
||||
// 'Else *ElseV = Else->codegen();'
|
||||
if (ifstmt.else_branch) |else_block| {
|
||||
self.ctx.setScope(self.ctx.current_scope.?.nextChild());
|
||||
for (else_block.toSlice()) |else_stmt| {
|
||||
// keep emitting until branch has ret
|
||||
if (!else_rets)
|
||||
|
@ -319,6 +324,8 @@ pub const Codegen = struct {
|
|||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
self.ctx.dumpScope();
|
||||
}
|
||||
|
||||
if (!else_rets)
|
||||
|
@ -330,18 +337,30 @@ pub const Codegen = struct {
|
|||
|
||||
if (then_rets and else_rets)
|
||||
_ = llvm.LLVMBuildUnreachable(builder);
|
||||
|
||||
// phis aren't needed since our ifs arent expressions
|
||||
|
||||
//var phi = llvm.LLVMBuildPhi(builder, llvm.LLVMVoidType(), c"iftmp");
|
||||
//var then_bb_val = llvm.LLVMBasicBlockAsValue(then_bb);
|
||||
//var else_bb_val = llvm.LLVMBasicBlockAsValue(else_bb);
|
||||
//llvm.LLVMAddIncoming(phi, &then_bb_val, &then_bb, 1);
|
||||
//llvm.LLVMAddIncoming(phi, &else_bb_val, &else_bb, 1);
|
||||
},
|
||||
|
||||
// TODO
|
||||
.VarDecl => {},
|
||||
.VarDecl => |vardecl| {
|
||||
// we alaready inferred the type of the variable in the
|
||||
// analyze pass and the current scope contains the variable's
|
||||
// type(hopefully), so we resolve it
|
||||
const name = vardecl.name.lexeme;
|
||||
var var_metadata = try self.ctx.resolveVarType(name);
|
||||
|
||||
var name_cstr = try std.cstr.addNullByte(self.allocator, name);
|
||||
errdefer self.allocator.free(name_cstr);
|
||||
|
||||
var fn_symbol = self.getFnSymbol(self.current_function_name.?);
|
||||
|
||||
_ = 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);
|
||||
},
|
||||
|
||||
else => {
|
||||
std.debug.warn("Got unexpected stmt {}\n", stmt.*);
|
||||
|
@ -350,6 +369,12 @@ pub const Codegen = struct {
|
|||
}
|
||||
}
|
||||
|
||||
fn getFnSymbol(self: *@This(), name: []const u8) comp.FunctionSymbol {
|
||||
var fn_sym_search = self.ctx.symbol_table.get(name).?.value;
|
||||
std.debug.assert(comp.SymbolType(fn_sym_search) == .Function);
|
||||
return fn_sym_search.Function;
|
||||
}
|
||||
|
||||
/// Emit LLVM ir for the given node.
|
||||
fn genNode(
|
||||
self: *Codegen,
|
||||
|
@ -361,10 +386,9 @@ pub const Codegen = struct {
|
|||
.FnDecl => |decl| {
|
||||
const name = decl.func_name.lexeme;
|
||||
self.current_function_name = name;
|
||||
std.debug.warn("cgen: genning function '{}'\n", name);
|
||||
|
||||
var fn_sym_search = self.ctx.symbol_table.get(name).?.value;
|
||||
std.debug.assert(comp.SymbolType(fn_sym_search) == .Function);
|
||||
var fn_sym = fn_sym_search.Function;
|
||||
var fn_sym = self.getFnSymbol(name);
|
||||
|
||||
const name_cstr = try std.cstr.addNullByte(self.allocator, name);
|
||||
errdefer self.allocator.free(name_cstr);
|
||||
|
@ -396,6 +420,9 @@ pub const Codegen = struct {
|
|||
var builder = llvm.LLVMCreateBuilder();
|
||||
llvm.LLVMPositionBuilderAtEnd(builder, entry);
|
||||
|
||||
self.ctx.setScope(fn_sym.scope);
|
||||
defer self.ctx.dumpScope();
|
||||
|
||||
for (decl.body.toSlice()) |stmt| {
|
||||
try self.emitStmt(builder, &stmt);
|
||||
}
|
||||
|
|
|
@ -39,8 +39,9 @@ pub const Scope = struct {
|
|||
parent: ?*Scope,
|
||||
env: UnderlyingTypeMap,
|
||||
|
||||
/// Used for debug information.
|
||||
/// List of children in the scope.
|
||||
children: ScopeList,
|
||||
cur_child_idx: usize = 0,
|
||||
|
||||
allocator: *std.mem.Allocator,
|
||||
id: ?[]const u8 = null,
|
||||
|
@ -64,6 +65,12 @@ pub const Scope = struct {
|
|||
return child;
|
||||
}
|
||||
|
||||
pub fn nextChild(self: *@This()) *Scope {
|
||||
var child = self.children.at(self.cur_child_idx);
|
||||
self.cur_child_idx += 1;
|
||||
return child;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *const @This()) void {
|
||||
self.env.deinit();
|
||||
}
|
||||
|
@ -184,6 +191,7 @@ pub const CompilationContext = struct {
|
|||
|
||||
/// Set a given scope as the current scope.
|
||||
pub fn setScope(self: *@This(), scope: *Scope) void {
|
||||
std.debug.warn("==set== set scope to {}\n", scope.id);
|
||||
self.current_scope = scope;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue