authorgravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-12-03 10:56:17-07:00
committergravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-12-03 10:56:17-07:00
log5af4ef88acb68b66d38846b398e1e34845cccfbf
tree36c7ac3ee73510adaf8ba08d9a1105f7f5a5b87c
parent708cae3786a5ce103d92bffe7ea8107df039426f

local variables work


5 files changed, 33 insertions(+), 34 deletions(-)

example/expressions/expressions.zig+2-2
...@@ -7,8 +7,8 @@ extern {...@@ -7,8 +7,8 @@ extern {
7export fn _start() -> unreachable {7export fn _start() -> unreachable {
8 let a : i32 = 1;8 let a : i32 = 1;
9 let b = 2;9 let b = 2;
10 let c : i32;10 // let c : i32; // not yet support for const variables
11 // let d; // compile error11 // let d; // parse error
12 puts("Hello, world!");12 puts("Hello, world!");
13 exit(a + b);13 exit(a + b);
14}14}
src/analyze.cpp+7-9
...@@ -115,12 +115,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -115,12 +115,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
115 for (int i = 0; i < node->data.fn_proto.params.length; i += 1) {115 for (int i = 0; i < node->data.fn_proto.params.length; i += 1) {
116 AstNode *child = node->data.fn_proto.params.at(i);116 AstNode *child = node->data.fn_proto.params.at(i);
117 assert(child->type == NodeTypeParamDecl);117 assert(child->type == NodeTypeParamDecl);
118118 resolve_type(g, child->data.param_decl.type);
119 Buf *param_name = &child->data.param_decl.name;
120 SymbolTableEntry *symbol_entry = allocate<SymbolTableEntry>(1);
121 symbol_entry->type_entry = resolve_type(g, child->data.param_decl.type);
122 symbol_entry->param_index = i;
123 fn_table_entry->symbol_table.put(param_name, symbol_entry);
124 }119 }
125120
126 resolve_type(g, node->data.fn_proto.return_type);121 resolve_type(g, node->data.fn_proto.return_type);
...@@ -171,7 +166,6 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,...@@ -171,7 +166,6 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
171 fn_table_entry->is_extern = true;166 fn_table_entry->is_extern = true;
172 fn_table_entry->calling_convention = LLVMCCallConv;167 fn_table_entry->calling_convention = LLVMCCallConv;
173 fn_table_entry->import_entry = import;168 fn_table_entry->import_entry = import;
174 fn_table_entry->symbol_table.init(8);
175 fn_table_entry->label_table.init(8);169 fn_table_entry->label_table.init(8);
176170
177 resolve_function_proto(g, fn_proto, fn_table_entry);171 resolve_function_proto(g, fn_proto, fn_table_entry);
...@@ -222,7 +216,6 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,...@@ -222,7 +216,6 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
222 fn_table_entry->fn_def_node = node;216 fn_table_entry->fn_def_node = node;
223 fn_table_entry->internal_linkage = is_internal;217 fn_table_entry->internal_linkage = is_internal;
224 fn_table_entry->calling_convention = is_internal ? LLVMFastCallConv : LLVMCCallConv;218 fn_table_entry->calling_convention = is_internal ? LLVMFastCallConv : LLVMCCallConv;
225 fn_table_entry->symbol_table.init(8);
226 fn_table_entry->label_table.init(8);219 fn_table_entry->label_table.init(8);
227220
228 g->fn_protos.append(fn_table_entry);221 g->fn_protos.append(fn_table_entry);
...@@ -363,7 +356,7 @@ static BlockContext *new_block_context(AstNode *node, BlockContext *parent) {...@@ -363,7 +356,7 @@ static BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
363 return context;356 return context;
364}357}
365358
366static LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name) {359LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name) {
367 while (true) {360 while (true) {
368 auto entry = context->variable_table.maybe_get(name);361 auto entry = context->variable_table.maybe_get(name);
369 if (entry != nullptr)362 if (entry != nullptr)
...@@ -432,6 +425,10 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -432,6 +425,10 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
432 TypeTableEntry *implicit_type = variable_declaration->expr != nullptr ?425 TypeTableEntry *implicit_type = variable_declaration->expr != nullptr ?
433 analyze_expression(g, import, context, explicit_type, variable_declaration->expr) : nullptr;426 analyze_expression(g, import, context, explicit_type, variable_declaration->expr) : nullptr;
434427
428 if (implicit_type == nullptr) {
429 add_node_error(g, node, buf_sprintf("initial values are required for variable declaration."));
430 }
431
435 TypeTableEntry *type = explicit_type != nullptr ? explicit_type : implicit_type;432 TypeTableEntry *type = explicit_type != nullptr ? explicit_type : implicit_type;
436 assert(type != nullptr); // should have been caught by the parser433 assert(type != nullptr); // should have been caught by the parser
437434
...@@ -736,6 +733,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,...@@ -736,6 +733,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,
736733
737 node->codegen_node = allocate<CodeGenNode>(1);734 node->codegen_node = allocate<CodeGenNode>(1);
738 node->codegen_node->data.fn_def_node.implicit_return_type = block_return_type;735 node->codegen_node->data.fn_def_node.implicit_return_type = block_return_type;
736 node->codegen_node->data.fn_def_node.block_context = context;
739 }737 }
740 break;738 break;
741739
src/analyze.hpp+3
...@@ -13,9 +13,12 @@ struct AstNode;...@@ -13,9 +13,12 @@ struct AstNode;
13struct Buf;13struct Buf;
1414
15struct TypeTableEntry;15struct TypeTableEntry;
16struct LocalVariableTableEntry;
17struct BlockContext;
1618
17void semantic_analyze(CodeGen *g);19void semantic_analyze(CodeGen *g);
18void add_node_error(CodeGen *g, AstNode *node, Buf *msg);20void add_node_error(CodeGen *g, AstNode *node, Buf *msg);
19TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);21TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
22LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name);
2023
21#endif24#endif
src/codegen.cpp+19-16
...@@ -103,17 +103,6 @@ static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str) {...@@ -103,17 +103,6 @@ static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str) {
103 return global_value;103 return global_value;
104}104}
105105
106static LLVMValueRef get_variable_value(CodeGen *g, Buf *name) {
107 assert(g->cur_fn->proto_node->type == NodeTypeFnProto);
108
109 SymbolTableEntry *symbol_entry = g->cur_fn->symbol_table.get(name);
110
111 CodeGenNode *codegen_node = g->cur_fn->fn_def_node->codegen_node;
112 assert(codegen_node);
113 FnDefNode *codegen_fn_def = &codegen_node->data.fn_def_node;
114 return codegen_fn_def->params[symbol_entry->param_index];
115}
116
117static TypeTableEntry *get_expr_type(AstNode *node) {106static TypeTableEntry *get_expr_type(AstNode *node) {
118 return node->codegen_node->expr_node.type_entry;107 return node->codegen_node->expr_node.type_entry;
119}108}
...@@ -481,7 +470,12 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {...@@ -481,7 +470,12 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
481 case NodeTypeReturnExpr:470 case NodeTypeReturnExpr:
482 return gen_return_expr(g, node);471 return gen_return_expr(g, node);
483 case NodeTypeVariableDeclaration:472 case NodeTypeVariableDeclaration:
484 zig_panic("TODO: variable declaration code gen");473 {
474 LocalVariableTableEntry *variable = find_local_variable(node->codegen_node->expr_node.block_context, &node->data.variable_declaration.symbol);
475 assert(node->data.variable_declaration.expr);
476 variable->value_ref = gen_expr(g, node->data.variable_declaration.expr);
477 return nullptr;
478 }
485 case NodeTypeCastExpr:479 case NodeTypeCastExpr:
486 return gen_cast_expr(g, node);480 return gen_cast_expr(g, node);
487 case NodeTypePrefixOpExpr:481 case NodeTypePrefixOpExpr:
...@@ -516,8 +510,8 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {...@@ -516,8 +510,8 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
516 }510 }
517 case NodeTypeSymbol:511 case NodeTypeSymbol:
518 {512 {
519 Buf *name = &node->data.symbol;513 LocalVariableTableEntry *variable = find_local_variable(node->codegen_node->expr_node.block_context, &node->data.symbol);
520 return get_variable_value(g, name);514 return variable->value_ref;
521 }515 }
522 case NodeTypeBlock:516 case NodeTypeBlock:
523 return gen_block(g, node, nullptr);517 return gen_block(g, node, nullptr);
...@@ -648,8 +642,17 @@ static void do_code_gen(CodeGen *g) {...@@ -648,8 +642,17 @@ static void do_code_gen(CodeGen *g) {
648642
649 FnDefNode *codegen_fn_def = &codegen_node->data.fn_def_node;643 FnDefNode *codegen_fn_def = &codegen_node->data.fn_def_node;
650 assert(codegen_fn_def);644 assert(codegen_fn_def);
651 codegen_fn_def->params = allocate<LLVMValueRef>(LLVMCountParams(fn));645 int param_count = fn_proto->params.length;
652 LLVMGetParams(fn, codegen_fn_def->params);646 assert(param_count == (int)LLVMCountParams(fn));
647 LLVMValueRef *params = allocate<LLVMValueRef>(param_count);
648 LLVMGetParams(fn, params);
649
650 for (int i = 0; i < param_count; i += 1) {
651 AstNode *param_decl = fn_proto->params.at(i);
652 assert(param_decl->type == NodeTypeParamDecl);
653 LocalVariableTableEntry *parameter_variable = fn_def_node->codegen_node->data.fn_def_node.block_context->variable_table.get(&param_decl->data.param_decl.name);
654 parameter_variable->value_ref = params[i];
655 }
653656
654 build_label_blocks(g, fn_def_node->data.fn_def.body);657 build_label_blocks(g, fn_def_node->data.fn_def.body);
655658
src/semantic_info.hpp+2-7
...@@ -38,11 +38,6 @@ struct ImportTableEntry {...@@ -38,11 +38,6 @@ struct ImportTableEntry {
38 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;38 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
39};39};
4040
41struct SymbolTableEntry {
42 TypeTableEntry *type_entry;
43 int param_index; // only valid in the case of parameters
44};
45
46struct LabelTableEntry {41struct LabelTableEntry {
47 AstNode *label_node;42 AstNode *label_node;
48 LLVMBasicBlockRef basic_block;43 LLVMBasicBlockRef basic_block;
...@@ -58,7 +53,6 @@ struct FnTableEntry {...@@ -58,7 +53,6 @@ struct FnTableEntry {
58 ImportTableEntry *import_entry;53 ImportTableEntry *import_entry;
5954
60 // reminder: hash tables must be initialized before use55 // reminder: hash tables must be initialized before use
61 HashMap<Buf *, SymbolTableEntry *, buf_hash, buf_eql_buf> symbol_table;
62 HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table;56 HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table;
63};57};
6458
...@@ -120,6 +114,7 @@ struct CodeGen {...@@ -120,6 +114,7 @@ struct CodeGen {
120struct LocalVariableTableEntry {114struct LocalVariableTableEntry {
121 Buf name;115 Buf name;
122 TypeTableEntry *type;116 TypeTableEntry *type;
117 LLVMValueRef value_ref;
123};118};
124119
125struct BlockContext {120struct BlockContext {
...@@ -139,8 +134,8 @@ struct FnProtoNode {...@@ -139,8 +134,8 @@ struct FnProtoNode {
139134
140struct FnDefNode {135struct FnDefNode {
141 TypeTableEntry *implicit_return_type;136 TypeTableEntry *implicit_return_type;
137 BlockContext *block_context;
142 bool skip;138 bool skip;
143 LLVMValueRef *params;
144};139};
145140
146struct ExprNode {141struct ExprNode {