From 5af4ef88acb68b66d38846b398e1e34845cccfbf Mon Sep 17 00:00:00 2001 From: Josh Wolfe Date: Thu, 3 Dec 2015 10:56:17 -0700 Subject: [PATCH] local variables work --- example/expressions/expressions.zig | 4 ++-- src/analyze.cpp | 16 ++++++------- src/analyze.hpp | 3 +++ src/codegen.cpp | 35 ++++++++++++++++------------- src/semantic_info.hpp | 9 ++------ 5 files changed, 33 insertions(+), 34 deletions(-) diff --git a/example/expressions/expressions.zig b/example/expressions/expressions.zig index 289bee9c40..fabc9fe160 100644 --- a/example/expressions/expressions.zig +++ b/example/expressions/expressions.zig @@ -7,8 +7,8 @@ extern { export fn _start() -> unreachable { let a : i32 = 1; let b = 2; - let c : i32; - // let d; // compile error + // let c : i32; // not yet support for const variables + // let d; // parse error puts("Hello, world!"); exit(a + b); } diff --git a/src/analyze.cpp b/src/analyze.cpp index dc7af6b809..c0ce2f7e8e 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -115,12 +115,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t for (int i = 0; i < node->data.fn_proto.params.length; i += 1) { AstNode *child = node->data.fn_proto.params.at(i); assert(child->type == NodeTypeParamDecl); - - Buf *param_name = &child->data.param_decl.name; - SymbolTableEntry *symbol_entry = allocate(1); - symbol_entry->type_entry = resolve_type(g, child->data.param_decl.type); - symbol_entry->param_index = i; - fn_table_entry->symbol_table.put(param_name, symbol_entry); + resolve_type(g, child->data.param_decl.type); } resolve_type(g, node->data.fn_proto.return_type); @@ -171,7 +166,6 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, fn_table_entry->is_extern = true; fn_table_entry->calling_convention = LLVMCCallConv; fn_table_entry->import_entry = import; - fn_table_entry->symbol_table.init(8); fn_table_entry->label_table.init(8); resolve_function_proto(g, fn_proto, fn_table_entry); @@ -222,7 +216,6 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, fn_table_entry->fn_def_node = node; fn_table_entry->internal_linkage = is_internal; fn_table_entry->calling_convention = is_internal ? LLVMFastCallConv : LLVMCCallConv; - fn_table_entry->symbol_table.init(8); fn_table_entry->label_table.init(8); g->fn_protos.append(fn_table_entry); @@ -363,7 +356,7 @@ static BlockContext *new_block_context(AstNode *node, BlockContext *parent) { return context; } -static LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name) { +LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name) { while (true) { auto entry = context->variable_table.maybe_get(name); if (entry != nullptr) @@ -432,6 +425,10 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, TypeTableEntry *implicit_type = variable_declaration->expr != nullptr ? analyze_expression(g, import, context, explicit_type, variable_declaration->expr) : nullptr; + if (implicit_type == nullptr) { + add_node_error(g, node, buf_sprintf("initial values are required for variable declaration.")); + } + TypeTableEntry *type = explicit_type != nullptr ? explicit_type : implicit_type; assert(type != nullptr); // should have been caught by the parser @@ -736,6 +733,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import, node->codegen_node = allocate(1); node->codegen_node->data.fn_def_node.implicit_return_type = block_return_type; + node->codegen_node->data.fn_def_node.block_context = context; } break; diff --git a/src/analyze.hpp b/src/analyze.hpp index 72908c682b..839b88f53c 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -13,9 +13,12 @@ struct AstNode; struct Buf; struct TypeTableEntry; +struct LocalVariableTableEntry; +struct BlockContext; void semantic_analyze(CodeGen *g); void add_node_error(CodeGen *g, AstNode *node, Buf *msg); TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const); +LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name); #endif diff --git a/src/codegen.cpp b/src/codegen.cpp index e91464771a..eac6267888 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -103,17 +103,6 @@ static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str) { return global_value; } -static LLVMValueRef get_variable_value(CodeGen *g, Buf *name) { - assert(g->cur_fn->proto_node->type == NodeTypeFnProto); - - SymbolTableEntry *symbol_entry = g->cur_fn->symbol_table.get(name); - - CodeGenNode *codegen_node = g->cur_fn->fn_def_node->codegen_node; - assert(codegen_node); - FnDefNode *codegen_fn_def = &codegen_node->data.fn_def_node; - return codegen_fn_def->params[symbol_entry->param_index]; -} - static TypeTableEntry *get_expr_type(AstNode *node) { return node->codegen_node->expr_node.type_entry; } @@ -481,7 +470,12 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { case NodeTypeReturnExpr: return gen_return_expr(g, node); case NodeTypeVariableDeclaration: - zig_panic("TODO: variable declaration code gen"); + { + LocalVariableTableEntry *variable = find_local_variable(node->codegen_node->expr_node.block_context, &node->data.variable_declaration.symbol); + assert(node->data.variable_declaration.expr); + variable->value_ref = gen_expr(g, node->data.variable_declaration.expr); + return nullptr; + } case NodeTypeCastExpr: return gen_cast_expr(g, node); case NodeTypePrefixOpExpr: @@ -516,8 +510,8 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { } case NodeTypeSymbol: { - Buf *name = &node->data.symbol; - return get_variable_value(g, name); + LocalVariableTableEntry *variable = find_local_variable(node->codegen_node->expr_node.block_context, &node->data.symbol); + return variable->value_ref; } case NodeTypeBlock: return gen_block(g, node, nullptr); @@ -648,8 +642,17 @@ static void do_code_gen(CodeGen *g) { FnDefNode *codegen_fn_def = &codegen_node->data.fn_def_node; assert(codegen_fn_def); - codegen_fn_def->params = allocate(LLVMCountParams(fn)); - LLVMGetParams(fn, codegen_fn_def->params); + int param_count = fn_proto->params.length; + assert(param_count == (int)LLVMCountParams(fn)); + LLVMValueRef *params = allocate(param_count); + LLVMGetParams(fn, params); + + for (int i = 0; i < param_count; i += 1) { + AstNode *param_decl = fn_proto->params.at(i); + assert(param_decl->type == NodeTypeParamDecl); + LocalVariableTableEntry *parameter_variable = fn_def_node->codegen_node->data.fn_def_node.block_context->variable_table.get(¶m_decl->data.param_decl.name); + parameter_variable->value_ref = params[i]; + } build_label_blocks(g, fn_def_node->data.fn_def.body); diff --git a/src/semantic_info.hpp b/src/semantic_info.hpp index e612bf32bd..6f4b7da8b3 100644 --- a/src/semantic_info.hpp +++ b/src/semantic_info.hpp @@ -38,11 +38,6 @@ struct ImportTableEntry { HashMap fn_table; }; -struct SymbolTableEntry { - TypeTableEntry *type_entry; - int param_index; // only valid in the case of parameters -}; - struct LabelTableEntry { AstNode *label_node; LLVMBasicBlockRef basic_block; @@ -58,7 +53,6 @@ struct FnTableEntry { ImportTableEntry *import_entry; // reminder: hash tables must be initialized before use - HashMap symbol_table; HashMap label_table; }; @@ -120,6 +114,7 @@ struct CodeGen { struct LocalVariableTableEntry { Buf name; TypeTableEntry *type; + LLVMValueRef value_ref; }; struct BlockContext { @@ -139,8 +134,8 @@ struct FnProtoNode { struct FnDefNode { TypeTableEntry *implicit_return_type; + BlockContext *block_context; bool skip; - LLVMValueRef *params; }; struct ExprNode {