| author | |
| committer | |
| log | 5af4ef88acb68b66d38846b398e1e34845cccfbf |
| tree | 36c7ac3ee73510adaf8ba08d9a1105f7f5a5b87c |
| parent | 708cae3786a5ce103d92bffe7ea8107df039426f |
5 files changed, 33 insertions(+), 34 deletions(-)
example/expressions/expressions.zig+2-2| ... | @@ -7,8 +7,8 @@ extern { | ... | @@ -7,8 +7,8 @@ extern { |
| 7 | export fn _start() -> unreachable { | 7 | export 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 error | 11 | // 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); |
| 118 | 118 | 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 | } |
| 125 | 120 | ||
| 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); |
| 176 | 170 | ||
| 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); |
| 227 | 220 | ||
| 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 | } |
| 365 | 358 | ||
| 366 | static LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name) { | 359 | LocalVariableTableEntry *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; |
| 434 | 427 | ||
| 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 parser | 433 | assert(type != nullptr); // should have been caught by the parser |
| 437 | 434 | ||
| ... | @@ -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, |
| 736 | 733 | ||
| 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; |
| 741 | 739 |
src/analyze.hpp+3| ... | @@ -13,9 +13,12 @@ struct AstNode; | ... | @@ -13,9 +13,12 @@ struct AstNode; |
| 13 | struct Buf; | 13 | struct Buf; |
| 14 | 14 | ||
| 15 | struct TypeTableEntry; | 15 | struct TypeTableEntry; |
| 16 | struct LocalVariableTableEntry; | ||
| 17 | struct BlockContext; | ||
| 16 | 18 | ||
| 17 | void semantic_analyze(CodeGen *g); | 19 | void semantic_analyze(CodeGen *g); |
| 18 | void add_node_error(CodeGen *g, AstNode *node, Buf *msg); | 20 | void add_node_error(CodeGen *g, AstNode *node, Buf *msg); |
| 19 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const); | 21 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const); |
| 22 | LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name); | ||
| 20 | 23 | ||
| 21 | #endif | 24 | #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 | } |
| 105 | 105 | ||
| 106 | static 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 | |||
| 117 | static TypeTableEntry *get_expr_type(AstNode *node) { | 106 | static 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) { |
| 648 | 642 | ||
| 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 | } | ||
| 653 | 656 | ||
| 654 | build_label_blocks(g, fn_def_node->data.fn_def.body); | 657 | build_label_blocks(g, fn_def_node->data.fn_def.body); |
| 655 | 658 |
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 | }; |
| 40 | 40 | ||
| 41 | struct SymbolTableEntry { | ||
| 42 | TypeTableEntry *type_entry; | ||
| 43 | int param_index; // only valid in the case of parameters | ||
| 44 | }; | ||
| 45 | |||
| 46 | struct LabelTableEntry { | 41 | struct 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; |
| 59 | 54 | ||
| 60 | // reminder: hash tables must be initialized before use | 55 | // 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 | }; |
| 64 | 58 | ||
| ... | @@ -120,6 +114,7 @@ struct CodeGen { | ... | @@ -120,6 +114,7 @@ struct CodeGen { |
| 120 | struct LocalVariableTableEntry { | 114 | struct LocalVariableTableEntry { |
| 121 | Buf name; | 115 | Buf name; |
| 122 | TypeTableEntry *type; | 116 | TypeTableEntry *type; |
| 117 | LLVMValueRef value_ref; | ||
| 123 | }; | 118 | }; |
| 124 | 119 | ||
| 125 | struct BlockContext { | 120 | struct BlockContext { |
| ... | @@ -139,8 +134,8 @@ struct FnProtoNode { | ... | @@ -139,8 +134,8 @@ struct FnProtoNode { |
| 139 | 134 | ||
| 140 | struct FnDefNode { | 135 | struct 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 | }; |
| 145 | 140 | ||
| 146 | struct ExprNode { | 141 | struct ExprNode { |