| ... | ... | @@ -74,7 +74,7 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool |
| 74 | 74 | } |
| 75 | 75 | } |
| 76 | 76 | |
| 77 | | static void resolve_type(CodeGen *g, AstNode *node) { |
| 77 | static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) { |
| 78 | 78 | assert(!node->codegen_node); |
| 79 | 79 | node->codegen_node = allocate<CodeGenNode>(1); |
| 80 | 80 | TypeNode *type_node = &node->codegen_node->data.type_node; |
| ... | ... | @@ -90,7 +90,7 @@ static void resolve_type(CodeGen *g, AstNode *node) { |
| 90 | 90 | buf_sprintf("invalid type name: '%s'", buf_ptr(name))); |
| 91 | 91 | type_node->entry = g->builtin_types.entry_invalid; |
| 92 | 92 | } |
| 93 | | break; |
| 93 | return type_node->entry; |
| 94 | 94 | } |
| 95 | 95 | case AstNodeTypeTypePointer: |
| 96 | 96 | { |
| ... | ... | @@ -101,12 +101,12 @@ static void resolve_type(CodeGen *g, AstNode *node) { |
| 101 | 101 | buf_create_from_str("pointer to unreachable not allowed")); |
| 102 | 102 | } |
| 103 | 103 | type_node->entry = get_pointer_to_type(g, child_type, node->data.type.is_const); |
| 104 | | break; |
| 104 | return type_node->entry; |
| 105 | 105 | } |
| 106 | 106 | } |
| 107 | 107 | } |
| 108 | 108 | |
| 109 | | static void resolve_function_proto(CodeGen *g, AstNode *node) { |
| 109 | static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry) { |
| 110 | 110 | assert(node->type == NodeTypeFnProto); |
| 111 | 111 | |
| 112 | 112 | for (int i = 0; i < node->data.fn_proto.directives->length; i += 1) { |
| ... | ... | @@ -120,9 +120,11 @@ static void resolve_function_proto(CodeGen *g, AstNode *node) { |
| 120 | 120 | AstNode *child = node->data.fn_proto.params.at(i); |
| 121 | 121 | assert(child->type == NodeTypeParamDecl); |
| 122 | 122 | |
| 123 | | // parameter names are not important here. |
| 124 | | |
| 125 | | resolve_type(g, child->data.param_decl.type); |
| 123 | Buf *param_name = &child->data.param_decl.name; |
| 124 | SymbolTableEntry *symbol_entry = allocate<SymbolTableEntry>(1); |
| 125 | symbol_entry->type_entry = resolve_type(g, child->data.param_decl.type); |
| 126 | symbol_entry->param_index = i; |
| 127 | fn_table_entry->symbol_table.put(param_name, symbol_entry); |
| 126 | 128 | } |
| 127 | 129 | |
| 128 | 130 | resolve_type(g, node->data.fn_proto.return_type); |
| ... | ... | @@ -148,20 +150,26 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 148 | 150 | assert(fn_decl->type == NodeTypeFnDecl); |
| 149 | 151 | AstNode *fn_proto = fn_decl->data.fn_decl.fn_proto; |
| 150 | 152 | bool is_pub = (fn_proto->data.fn_proto.visib_mod == FnProtoVisibModPub); |
| 151 | | resolve_function_proto(g, fn_proto); |
| 152 | | Buf *name = &fn_proto->data.fn_proto.name; |
| 153 | 153 | |
| 154 | 154 | FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1); |
| 155 | 155 | fn_table_entry->proto_node = fn_proto; |
| 156 | 156 | fn_table_entry->is_extern = true; |
| 157 | 157 | fn_table_entry->calling_convention = LLVMCCallConv; |
| 158 | 158 | fn_table_entry->import_entry = import; |
| 159 | fn_table_entry->symbol_table.init(8); |
| 160 | |
| 161 | resolve_function_proto(g, fn_proto, fn_table_entry); |
| 159 | 162 | |
| 163 | Buf *name = &fn_proto->data.fn_proto.name; |
| 160 | 164 | g->fn_protos.append(fn_table_entry); |
| 161 | 165 | import->fn_table.put(name, fn_table_entry); |
| 162 | 166 | if (is_pub) { |
| 163 | 167 | g->fn_table.put(name, fn_table_entry); |
| 164 | 168 | } |
| 169 | |
| 170 | assert(!fn_proto->codegen_node); |
| 171 | fn_proto->codegen_node = allocate<CodeGenNode>(1); |
| 172 | fn_proto->codegen_node->data.fn_proto_node.fn_table_entry = fn_table_entry; |
| 165 | 173 | } |
| 166 | 174 | break; |
| 167 | 175 | case NodeTypeFnDef: |
| ... | ... | @@ -198,6 +206,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 198 | 206 | fn_table_entry->fn_def_node = node; |
| 199 | 207 | fn_table_entry->internal_linkage = is_internal; |
| 200 | 208 | fn_table_entry->calling_convention = is_internal ? LLVMFastCallConv : LLVMCCallConv; |
| 209 | fn_table_entry->symbol_table.init(8); |
| 201 | 210 | |
| 202 | 211 | g->fn_protos.append(fn_table_entry); |
| 203 | 212 | g->fn_defs.append(fn_table_entry); |
| ... | ... | @@ -207,7 +216,11 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 207 | 216 | g->fn_table.put(proto_name, fn_table_entry); |
| 208 | 217 | } |
| 209 | 218 | |
| 210 | | resolve_function_proto(g, proto_node); |
| 219 | resolve_function_proto(g, proto_node, fn_table_entry); |
| 220 | |
| 221 | assert(!proto_node->codegen_node); |
| 222 | proto_node->codegen_node = allocate<CodeGenNode>(1); |
| 223 | proto_node->codegen_node->data.fn_proto_node.fn_table_entry = fn_table_entry; |
| 211 | 224 | } |
| 212 | 225 | } |
| 213 | 226 | break; |
| ... | ... | @@ -289,6 +302,16 @@ static TypeTableEntry * get_return_type(BlockContext *context) { |
| 289 | 302 | return return_type_node->codegen_node->data.type_node.entry; |
| 290 | 303 | } |
| 291 | 304 | |
| 305 | static FnTableEntry *get_context_fn_entry(BlockContext *context) { |
| 306 | AstNode *fn_def_node = context->root->node; |
| 307 | assert(fn_def_node->type == NodeTypeFnDef); |
| 308 | AstNode *fn_proto_node = fn_def_node->data.fn_def.fn_proto; |
| 309 | assert(fn_proto_node->type == NodeTypeFnProto); |
| 310 | assert(fn_proto_node->codegen_node); |
| 311 | assert(fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry); |
| 312 | return fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry; |
| 313 | } |
| 314 | |
| 292 | 315 | static void check_type_compatibility(CodeGen *g, AstNode *node, TypeTableEntry *expected_type, TypeTableEntry *actual_type) { |
| 293 | 316 | if (expected_type == nullptr) |
| 294 | 317 | return; // anything will do |
| ... | ... | @@ -482,9 +505,20 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 482 | 505 | break; |
| 483 | 506 | |
| 484 | 507 | case NodeTypeSymbol: |
| 485 | | // look up symbol in symbol table |
| 486 | | zig_panic("TODO analyze_expression symbol"); |
| 487 | | |
| 508 | { |
| 509 | Buf *symbol_name = &node->data.symbol; |
| 510 | FnTableEntry *fn_table_entry = get_context_fn_entry(context); |
| 511 | auto table_entry = fn_table_entry->symbol_table.maybe_get(symbol_name); |
| 512 | if (table_entry) { |
| 513 | SymbolTableEntry *symbol_entry = table_entry->value; |
| 514 | return_type = symbol_entry->type_entry; |
| 515 | } else { |
| 516 | add_node_error(g, node, |
| 517 | buf_sprintf("use of undeclared identifier '%s'", buf_ptr(symbol_name))); |
| 518 | return_type = g->builtin_types.entry_invalid; |
| 519 | } |
| 520 | break; |
| 521 | } |
| 488 | 522 | case NodeTypeCastExpr: |
| 489 | 523 | zig_panic("TODO analyze_expression cast expr"); |
| 490 | 524 | break; |