| 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 | 7 | export fn _start() -> unreachable { |
| 8 | 8 | let a : i32 = 1; |
| 9 | 9 | let b = 2; |
| 10 | let c : i32; | |
| 11 | // let d; // compile error | |
| 10 | // let c : i32; // not yet support for const variables | |
| 11 | // let d; // parse error | |
| 12 | 12 | puts("Hello, world!"); |
| 13 | 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 | 115 | for (int i = 0; i < node->data.fn_proto.params.length; i += 1) { |
| 116 | 116 | AstNode *child = node->data.fn_proto.params.at(i); |
| 117 | 117 | assert(child->type == NodeTypeParamDecl); |
| 118 | ||
| 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); | |
| 118 | resolve_type(g, child->data.param_decl.type); | |
| 124 | 119 | } |
| 125 | 120 | |
| 126 | 121 | resolve_type(g, node->data.fn_proto.return_type); |
| ... | ... | @@ -171,7 +166,6 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 171 | 166 | fn_table_entry->is_extern = true; |
| 172 | 167 | fn_table_entry->calling_convention = LLVMCCallConv; |
| 173 | 168 | fn_table_entry->import_entry = import; |
| 174 | fn_table_entry->symbol_table.init(8); | |
| 175 | 169 | fn_table_entry->label_table.init(8); |
| 176 | 170 | |
| 177 | 171 | resolve_function_proto(g, fn_proto, fn_table_entry); |
| ... | ... | @@ -222,7 +216,6 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 222 | 216 | fn_table_entry->fn_def_node = node; |
| 223 | 217 | fn_table_entry->internal_linkage = is_internal; |
| 224 | 218 | fn_table_entry->calling_convention = is_internal ? LLVMFastCallConv : LLVMCCallConv; |
| 225 | fn_table_entry->symbol_table.init(8); | |
| 226 | 219 | fn_table_entry->label_table.init(8); |
| 227 | 220 | |
| 228 | 221 | g->fn_protos.append(fn_table_entry); |
| ... | ... | @@ -363,7 +356,7 @@ static BlockContext *new_block_context(AstNode *node, BlockContext *parent) { |
| 363 | 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 | 360 | while (true) { |
| 368 | 361 | auto entry = context->variable_table.maybe_get(name); |
| 369 | 362 | if (entry != nullptr) |
| ... | ... | @@ -432,6 +425,10 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 432 | 425 | TypeTableEntry *implicit_type = variable_declaration->expr != nullptr ? |
| 433 | 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 | 432 | TypeTableEntry *type = explicit_type != nullptr ? explicit_type : implicit_type; |
| 436 | 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 | 733 | |
| 737 | 734 | node->codegen_node = allocate<CodeGenNode>(1); |
| 738 | 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 | 738 | break; |
| 741 | 739 |
src/analyze.hpp+3| ... | ... | @@ -13,9 +13,12 @@ struct AstNode; |
| 13 | 13 | struct Buf; |
| 14 | 14 | |
| 15 | 15 | struct TypeTableEntry; |
| 16 | struct LocalVariableTableEntry; | |
| 17 | struct BlockContext; | |
| 16 | 18 | |
| 17 | 19 | void semantic_analyze(CodeGen *g); |
| 18 | 20 | void add_node_error(CodeGen *g, AstNode *node, Buf *msg); |
| 19 | 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 | 24 | #endif |
src/codegen.cpp+19-16| ... | ... | @@ -103,17 +103,6 @@ static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str) { |
| 103 | 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 | 106 | static TypeTableEntry *get_expr_type(AstNode *node) { |
| 118 | 107 | return node->codegen_node->expr_node.type_entry; |
| 119 | 108 | } |
| ... | ... | @@ -481,7 +470,12 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { |
| 481 | 470 | case NodeTypeReturnExpr: |
| 482 | 471 | return gen_return_expr(g, node); |
| 483 | 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 | 479 | case NodeTypeCastExpr: |
| 486 | 480 | return gen_cast_expr(g, node); |
| 487 | 481 | case NodeTypePrefixOpExpr: |
| ... | ... | @@ -516,8 +510,8 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { |
| 516 | 510 | } |
| 517 | 511 | case NodeTypeSymbol: |
| 518 | 512 | { |
| 519 | Buf *name = &node->data.symbol; | |
| 520 | return get_variable_value(g, name); | |
| 513 | LocalVariableTableEntry *variable = find_local_variable(node->codegen_node->expr_node.block_context, &node->data.symbol); | |
| 514 | return variable->value_ref; | |
| 521 | 515 | } |
| 522 | 516 | case NodeTypeBlock: |
| 523 | 517 | return gen_block(g, node, nullptr); |
| ... | ... | @@ -648,8 +642,17 @@ static void do_code_gen(CodeGen *g) { |
| 648 | 642 | |
| 649 | 643 | FnDefNode *codegen_fn_def = &codegen_node->data.fn_def_node; |
| 650 | 644 | assert(codegen_fn_def); |
| 651 | codegen_fn_def->params = allocate<LLVMValueRef>(LLVMCountParams(fn)); | |
| 652 | LLVMGetParams(fn, codegen_fn_def->params); | |
| 645 | int param_count = fn_proto->params.length; | |
| 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 | 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 | 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 | 41 | struct LabelTableEntry { |
| 47 | 42 | AstNode *label_node; |
| 48 | 43 | LLVMBasicBlockRef basic_block; |
| ... | ... | @@ -58,7 +53,6 @@ struct FnTableEntry { |
| 58 | 53 | ImportTableEntry *import_entry; |
| 59 | 54 | |
| 60 | 55 | // reminder: hash tables must be initialized before use |
| 61 | HashMap<Buf *, SymbolTableEntry *, buf_hash, buf_eql_buf> symbol_table; | |
| 62 | 56 | HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table; |
| 63 | 57 | }; |
| 64 | 58 | |
| ... | ... | @@ -120,6 +114,7 @@ struct CodeGen { |
| 120 | 114 | struct LocalVariableTableEntry { |
| 121 | 115 | Buf name; |
| 122 | 116 | TypeTableEntry *type; |
| 117 | LLVMValueRef value_ref; | |
| 123 | 118 | }; |
| 124 | 119 | |
| 125 | 120 | struct BlockContext { |
| ... | ... | @@ -139,8 +134,8 @@ struct FnProtoNode { |
| 139 | 134 | |
| 140 | 135 | struct FnDefNode { |
| 141 | 136 | TypeTableEntry *implicit_return_type; |
| 137 | BlockContext *block_context; | |
| 142 | 138 | bool skip; |
| 143 | LLVMValueRef *params; | |
| 144 | 139 | }; |
| 145 | 140 | |
| 146 | 141 | struct ExprNode { |