| author | |
| committer | |
| log | f6cbb73c7402fc100bbfb26c1a35c9f23b3f36ff |
| tree | 6d62eb0f6b04292b98ef2bd92b40699a6c32da0a |
| parent | c6ace9720c8666f893f236c00ea9b370b1b2bb70 |
* now there are not extra unused hash tables
* each variable declaration opens a new scope inside a function7 files changed, 420 insertions(+), 266 deletions(-)
src/all_types.hpp+74-23| ... | @@ -31,6 +31,7 @@ struct ConstExprValue; | ... | @@ -31,6 +31,7 @@ struct ConstExprValue; |
| 31 | struct IrInstruction; | 31 | struct IrInstruction; |
| 32 | struct IrInstructionCast; | 32 | struct IrInstructionCast; |
| 33 | struct IrBasicBlock; | 33 | struct IrBasicBlock; |
| 34 | struct ScopeDecls; | ||
| 34 | 35 | ||
| 35 | struct IrExecutable { | 36 | struct IrExecutable { |
| 36 | ZigList<IrBasicBlock *> basic_block_list; | 37 | ZigList<IrBasicBlock *> basic_block_list; |
| ... | @@ -251,8 +252,8 @@ struct AstNodeFnDef { | ... | @@ -251,8 +252,8 @@ struct AstNodeFnDef { |
| 251 | 252 | ||
| 252 | // populated by semantic analyzer | 253 | // populated by semantic analyzer |
| 253 | TypeTableEntry *implicit_return_type; | 254 | TypeTableEntry *implicit_return_type; |
| 254 | // the first child block context | 255 | Scope *containing_scope; |
| 255 | Scope *scope; | 256 | Scope *child_scope; |
| 256 | }; | 257 | }; |
| 257 | 258 | ||
| 258 | struct AstNodeFnDecl { | 259 | struct AstNodeFnDecl { |
| ... | @@ -638,7 +639,7 @@ struct AstNodeStructDecl { | ... | @@ -638,7 +639,7 @@ struct AstNodeStructDecl { |
| 638 | ZigList<AstNode *> decls; | 639 | ZigList<AstNode *> decls; |
| 639 | 640 | ||
| 640 | // populated by semantic analyzer | 641 | // populated by semantic analyzer |
| 641 | Scope *scope; | 642 | ScopeDecls *decls_scope; |
| 642 | TypeTableEntry *type_entry; | 643 | TypeTableEntry *type_entry; |
| 643 | TypeTableEntry *generic_fn_type; | 644 | TypeTableEntry *generic_fn_type; |
| 644 | bool skip; | 645 | bool skip; |
| ... | @@ -884,7 +885,7 @@ struct TypeTableEntryStruct { | ... | @@ -884,7 +885,7 @@ struct TypeTableEntryStruct { |
| 884 | uint64_t size_bytes; | 885 | uint64_t size_bytes; |
| 885 | bool is_invalid; // true if any fields are invalid | 886 | bool is_invalid; // true if any fields are invalid |
| 886 | bool is_slice; | 887 | bool is_slice; |
| 887 | Scope *scope; | 888 | ScopeDecls *decls_scope; |
| 888 | 889 | ||
| 889 | // set this flag temporarily to detect infinite loops | 890 | // set this flag temporarily to detect infinite loops |
| 890 | bool embedded_in_current; | 891 | bool embedded_in_current; |
| ... | @@ -910,7 +911,7 @@ struct TypeTableEntryEnum { | ... | @@ -910,7 +911,7 @@ struct TypeTableEntryEnum { |
| 910 | TypeTableEntry *tag_type; | 911 | TypeTableEntry *tag_type; |
| 911 | TypeTableEntry *union_type; | 912 | TypeTableEntry *union_type; |
| 912 | 913 | ||
| 913 | Scope *scope; | 914 | ScopeDecls *decls_scope; |
| 914 | 915 | ||
| 915 | // set this flag temporarily to detect infinite loops | 916 | // set this flag temporarily to detect infinite loops |
| 916 | bool embedded_in_current; | 917 | bool embedded_in_current; |
| ... | @@ -926,7 +927,7 @@ struct TypeTableEntryUnion { | ... | @@ -926,7 +927,7 @@ struct TypeTableEntryUnion { |
| 926 | TypeStructField *fields; | 927 | TypeStructField *fields; |
| 927 | uint64_t size_bytes; | 928 | uint64_t size_bytes; |
| 928 | bool is_invalid; // true if any fields are invalid | 929 | bool is_invalid; // true if any fields are invalid |
| 929 | Scope *scope; | 930 | ScopeDecls *decls_scope; |
| 930 | 931 | ||
| 931 | // set this flag temporarily to detect infinite loops | 932 | // set this flag temporarily to detect infinite loops |
| 932 | bool embedded_in_current; | 933 | bool embedded_in_current; |
| ... | @@ -1044,7 +1045,7 @@ struct ImportTableEntry { | ... | @@ -1044,7 +1045,7 @@ struct ImportTableEntry { |
| 1044 | ZigLLVMDIFile *di_file; | 1045 | ZigLLVMDIFile *di_file; |
| 1045 | Buf *source_code; | 1046 | Buf *source_code; |
| 1046 | ZigList<size_t> *line_offsets; | 1047 | ZigList<size_t> *line_offsets; |
| 1047 | Scope *scope; | 1048 | ScopeDecls *decls_scope; |
| 1048 | AstNode *c_import_node; | 1049 | AstNode *c_import_node; |
| 1049 | bool any_imports_failed; | 1050 | bool any_imports_failed; |
| 1050 | 1051 | ||
| ... | @@ -1070,8 +1071,6 @@ struct FnTableEntry { | ... | @@ -1070,8 +1071,6 @@ struct FnTableEntry { |
| 1070 | AstNode *proto_node; | 1071 | AstNode *proto_node; |
| 1071 | AstNode *fn_def_node; | 1072 | AstNode *fn_def_node; |
| 1072 | ImportTableEntry *import_entry; | 1073 | ImportTableEntry *import_entry; |
| 1073 | // Required to be a pre-order traversal of the AST. (parents must come before children) | ||
| 1074 | ZigList<Scope *> all_block_contexts; | ||
| 1075 | Buf symbol_name; | 1074 | Buf symbol_name; |
| 1076 | TypeTableEntry *type_entry; // function type | 1075 | TypeTableEntry *type_entry; // function type |
| 1077 | bool internal_linkage; | 1076 | bool internal_linkage; |
| ... | @@ -1310,7 +1309,8 @@ struct VariableTableEntry { | ... | @@ -1310,7 +1309,8 @@ struct VariableTableEntry { |
| 1310 | ZigLLVMDILocalVariable *di_loc_var; | 1309 | ZigLLVMDILocalVariable *di_loc_var; |
| 1311 | size_t src_arg_index; | 1310 | size_t src_arg_index; |
| 1312 | size_t gen_arg_index; | 1311 | size_t gen_arg_index; |
| 1313 | Scope *scope; | 1312 | Scope *parent_scope; |
| 1313 | Scope *child_scope; | ||
| 1314 | LLVMValueRef param_value_ref; | 1314 | LLVMValueRef param_value_ref; |
| 1315 | bool force_depends_on_compile_var; | 1315 | bool force_depends_on_compile_var; |
| 1316 | ImportTableEntry *import; | 1316 | ImportTableEntry *import; |
| ... | @@ -1334,26 +1334,77 @@ struct LabelTableEntry { | ... | @@ -1334,26 +1334,77 @@ struct LabelTableEntry { |
| 1334 | struct Scope { | 1334 | struct Scope { |
| 1335 | AstNode *node; | 1335 | AstNode *node; |
| 1336 | 1336 | ||
| 1337 | // any variables that are introduced by this scope | 1337 | // if the scope has a parent, this is it. Every scope has a parent except |
| 1338 | // ScopeIdGlobal | ||
| 1339 | Scope *parent; | ||
| 1340 | |||
| 1341 | ZigLLVMDIScope *di_scope; | ||
| 1342 | |||
| 1343 | bool safety_off; | ||
| 1344 | AstNode *safety_set_node; | ||
| 1345 | }; | ||
| 1346 | |||
| 1347 | // This scope comes from global declarations or from | ||
| 1348 | // declarations in a container declaration | ||
| 1349 | // NodeTypeRoot, NodeTypeContainerDecl | ||
| 1350 | struct ScopeDecls { | ||
| 1351 | Scope base; | ||
| 1352 | |||
| 1353 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> decl_table; | ||
| 1354 | }; | ||
| 1355 | |||
| 1356 | // This scope comes from a container declaration such as a struct, | ||
| 1357 | // enum, or union. | ||
| 1358 | struct ScopeContainer { | ||
| 1359 | Scope base; | ||
| 1360 | |||
| 1338 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> decl_table; | 1361 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> decl_table; |
| 1339 | HashMap<Buf *, VariableTableEntry *, buf_hash, buf_eql_buf> var_table; | 1362 | }; |
| 1363 | |||
| 1364 | // This scope comes from a block expression in user code. | ||
| 1365 | // NodeTypeBlock | ||
| 1366 | struct ScopeBlock { | ||
| 1367 | Scope base; | ||
| 1368 | |||
| 1340 | HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table; | 1369 | HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table; |
| 1370 | }; | ||
| 1341 | 1371 | ||
| 1342 | // if the block is inside a function, this is the function it is in: | 1372 | // This scope is created from every defer expression. |
| 1343 | FnTableEntry *fn_entry; | 1373 | // NodeTypeDefer |
| 1374 | struct ScopeDefer { | ||
| 1375 | Scope base; | ||
| 1376 | }; | ||
| 1344 | 1377 | ||
| 1345 | // if the block has a parent, this is it | 1378 | // This scope is created for every variable declaration inside an IrExecutable |
| 1346 | Scope *parent; | 1379 | // NodeTypeVariableDeclaration, NodeTypeParamDecl |
| 1380 | struct ScopeVarDecl { | ||
| 1381 | Scope base; | ||
| 1347 | 1382 | ||
| 1348 | // if break or continue is valid in this context, this is the loop node that | 1383 | // The variable that creates this scope |
| 1349 | // it would pertain to | 1384 | VariableTableEntry *var; |
| 1350 | AstNode *parent_loop_node; | 1385 | }; |
| 1351 | 1386 | ||
| 1352 | ZigLLVMDIScope *di_scope; | 1387 | // This scope is created for a @cImport |
| 1353 | Buf *c_import_buf; | 1388 | // NodeTypeFnCallExpr |
| 1389 | struct ScopeCImport { | ||
| 1390 | Scope base; | ||
| 1354 | 1391 | ||
| 1355 | bool safety_off; | 1392 | Buf c_import_buf; |
| 1356 | AstNode *safety_set_node; | 1393 | }; |
| 1394 | |||
| 1395 | // This scope is created for a loop such as for or while in order to | ||
| 1396 | // make break and continue statements work. | ||
| 1397 | // NodeTypeForExpr or NodeTypeWhileExpr | ||
| 1398 | struct ScopeLoop { | ||
| 1399 | Scope base; | ||
| 1400 | }; | ||
| 1401 | |||
| 1402 | // This scope is created for a function definition. | ||
| 1403 | // NodeTypeFnDef | ||
| 1404 | struct ScopeFnBody { | ||
| 1405 | Scope base; | ||
| 1406 | |||
| 1407 | FnTableEntry *fn_entry; | ||
| 1357 | }; | 1408 | }; |
| 1358 | 1409 | ||
| 1359 | enum AtomicOrder { | 1410 | enum AtomicOrder { |
src/analyze.cpp+172-146| ... | @@ -115,26 +115,24 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) { | ... | @@ -115,26 +115,24 @@ TypeTableEntry *new_type_table_entry(TypeTableEntryId id) { |
| 115 | return entry; | 115 | return entry; |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | static Scope **get_container_block_context_ptr(TypeTableEntry *type_entry) { | 118 | static ScopeDecls **get_container_scope_ptr(TypeTableEntry *type_entry) { |
| 119 | if (type_entry->id == TypeTableEntryIdStruct) { | 119 | if (type_entry->id == TypeTableEntryIdStruct) { |
| 120 | return &type_entry->data.structure.scope; | 120 | return &type_entry->data.structure.decls_scope; |
| 121 | } else if (type_entry->id == TypeTableEntryIdEnum) { | 121 | } else if (type_entry->id == TypeTableEntryIdEnum) { |
| 122 | return &type_entry->data.enumeration.scope; | 122 | return &type_entry->data.enumeration.decls_scope; |
| 123 | } else if (type_entry->id == TypeTableEntryIdUnion) { | 123 | } else if (type_entry->id == TypeTableEntryIdUnion) { |
| 124 | return &type_entry->data.unionation.scope; | 124 | return &type_entry->data.unionation.decls_scope; |
| 125 | } | 125 | } |
| 126 | zig_unreachable(); | 126 | zig_unreachable(); |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | Scope *get_container_block_context(TypeTableEntry *type_entry) { | 129 | ScopeDecls *get_container_scope(TypeTableEntry *type_entry) { |
| 130 | return *get_container_block_context_ptr(type_entry); | 130 | return *get_container_scope_ptr(type_entry); |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | static TypeTableEntry *new_container_type_entry(TypeTableEntryId id, AstNode *source_node, | 133 | static TypeTableEntry *new_container_type_entry(TypeTableEntryId id, AstNode *source_node, Scope *parent_scope) { |
| 134 | Scope *parent_context) | ||
| 135 | { | ||
| 136 | TypeTableEntry *entry = new_type_table_entry(id); | 134 | TypeTableEntry *entry = new_type_table_entry(id); |
| 137 | *get_container_block_context_ptr(entry) = new_scope(source_node, parent_context); | 135 | *get_container_scope_ptr(entry) = create_decls_scope(source_node, parent_scope); |
| 138 | return entry; | 136 | return entry; |
| 139 | } | 137 | } |
| 140 | 138 | ||
| ... | @@ -766,11 +764,11 @@ static TypeTableEntryId container_to_type(ContainerKind kind) { | ... | @@ -766,11 +764,11 @@ static TypeTableEntryId container_to_type(ContainerKind kind) { |
| 766 | zig_unreachable(); | 764 | zig_unreachable(); |
| 767 | } | 765 | } |
| 768 | 766 | ||
| 769 | TypeTableEntry *get_partial_container_type(CodeGen *g, ImportTableEntry *import, Scope *context, | 767 | TypeTableEntry *get_partial_container_type(CodeGen *g, ImportTableEntry *import, Scope *scope, |
| 770 | ContainerKind kind, AstNode *decl_node, const char *name) | 768 | ContainerKind kind, AstNode *decl_node, const char *name) |
| 771 | { | 769 | { |
| 772 | TypeTableEntryId type_id = container_to_type(kind); | 770 | TypeTableEntryId type_id = container_to_type(kind); |
| 773 | TypeTableEntry *entry = new_container_type_entry(type_id, decl_node, context); | 771 | TypeTableEntry *entry = new_container_type_entry(type_id, decl_node, scope); |
| 774 | 772 | ||
| 775 | switch (kind) { | 773 | switch (kind) { |
| 776 | case ContainerKindStruct: | 774 | case ContainerKindStruct: |
| ... | @@ -844,10 +842,10 @@ static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *nod | ... | @@ -844,10 +842,10 @@ static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *nod |
| 844 | return result; | 842 | return result; |
| 845 | } | 843 | } |
| 846 | 844 | ||
| 847 | static TypeTableEntry *analyze_type_expr(CodeGen *g, ImportTableEntry *import, Scope *context, | 845 | static TypeTableEntry *analyze_type_expr(CodeGen *g, ImportTableEntry *import, Scope *scope, |
| 848 | AstNode *node) | 846 | AstNode *node) |
| 849 | { | 847 | { |
| 850 | IrInstruction *result = analyze_const_value(g, context, node, g->builtin_types.entry_type); | 848 | IrInstruction *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type); |
| 851 | if (result->type_entry->id == TypeTableEntryIdInvalid) | 849 | if (result->type_entry->id == TypeTableEntryIdInvalid) |
| 852 | return g->builtin_types.entry_invalid; | 850 | return g->builtin_types.entry_invalid; |
| 853 | 851 | ||
| ... | @@ -861,7 +859,7 @@ static bool fn_wants_full_static_eval(FnTableEntry *fn_table_entry) { | ... | @@ -861,7 +859,7 @@ static bool fn_wants_full_static_eval(FnTableEntry *fn_table_entry) { |
| 861 | } | 859 | } |
| 862 | 860 | ||
| 863 | // fn_table_entry is populated if and only if there is a function definition for this prototype | 861 | // fn_table_entry is populated if and only if there is a function definition for this prototype |
| 864 | static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *import, Scope *context, | 862 | static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *import, Scope *scope, |
| 865 | TypeTableEntry *expected_type, AstNode *node, bool is_naked, bool is_cold, FnTableEntry *fn_table_entry) | 863 | TypeTableEntry *expected_type, AstNode *node, bool is_naked, bool is_cold, FnTableEntry *fn_table_entry) |
| 866 | { | 864 | { |
| 867 | assert(node->type == NodeTypeFnProto); | 865 | assert(node->type == NodeTypeFnProto); |
| ... | @@ -888,7 +886,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor | ... | @@ -888,7 +886,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor |
| 888 | if (fn_proto->skip) { | 886 | if (fn_proto->skip) { |
| 889 | type_entry = g->builtin_types.entry_invalid; | 887 | type_entry = g->builtin_types.entry_invalid; |
| 890 | } else { | 888 | } else { |
| 891 | type_entry = analyze_type_expr(g, import, context, child->data.param_decl.type); | 889 | type_entry = analyze_type_expr(g, import, scope, child->data.param_decl.type); |
| 892 | } | 890 | } |
| 893 | 891 | ||
| 894 | switch (type_entry->id) { | 892 | switch (type_entry->id) { |
| ... | @@ -951,7 +949,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor | ... | @@ -951,7 +949,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor |
| 951 | if (fn_proto->skip) { | 949 | if (fn_proto->skip) { |
| 952 | fn_type_id.return_type = g->builtin_types.entry_invalid; | 950 | fn_type_id.return_type = g->builtin_types.entry_invalid; |
| 953 | } else { | 951 | } else { |
| 954 | fn_type_id.return_type = analyze_type_expr(g, import, context, fn_proto->return_type); | 952 | fn_type_id.return_type = analyze_type_expr(g, import, scope, fn_proto->return_type); |
| 955 | } | 953 | } |
| 956 | switch (fn_type_id.return_type->id) { | 954 | switch (fn_type_id.return_type->id) { |
| 957 | case TypeTableEntryIdInvalid: | 955 | case TypeTableEntryIdInvalid: |
| ... | @@ -1022,7 +1020,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor | ... | @@ -1022,7 +1020,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor |
| 1022 | } | 1020 | } |
| 1023 | 1021 | ||
| 1024 | static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry, | 1022 | static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry, |
| 1025 | ImportTableEntry *import, Scope *containing_context) | 1023 | ImportTableEntry *import, Scope *containing_scope) |
| 1026 | { | 1024 | { |
| 1027 | assert(node->type == NodeTypeFnProto); | 1025 | assert(node->type == NodeTypeFnProto); |
| 1028 | AstNodeFnProto *fn_proto = &node->data.fn_proto; | 1026 | AstNodeFnProto *fn_proto = &node->data.fn_proto; |
| ... | @@ -1037,7 +1035,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t | ... | @@ -1037,7 +1035,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t |
| 1037 | 1035 | ||
| 1038 | 1036 | ||
| 1039 | 1037 | ||
| 1040 | TypeTableEntry *fn_type = analyze_fn_proto_type(g, import, containing_context, nullptr, node, | 1038 | TypeTableEntry *fn_type = analyze_fn_proto_type(g, import, containing_scope, nullptr, node, |
| 1041 | fn_proto->is_nakedcc, fn_proto->is_coldcc, fn_table_entry); | 1039 | fn_proto->is_nakedcc, fn_proto->is_coldcc, fn_table_entry); |
| 1042 | 1040 | ||
| 1043 | fn_table_entry->type_entry = fn_type; | 1041 | fn_table_entry->type_entry = fn_type; |
| ... | @@ -1060,8 +1058,8 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t | ... | @@ -1060,8 +1058,8 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t |
| 1060 | } | 1058 | } |
| 1061 | 1059 | ||
| 1062 | if (fn_table_entry->fn_def_node) { | 1060 | if (fn_table_entry->fn_def_node) { |
| 1063 | Scope *context = new_scope(fn_table_entry->fn_def_node, containing_context); | 1061 | fn_table_entry->fn_def_node->data.fn_def.containing_scope = create_fndef_scope( |
| 1064 | fn_table_entry->fn_def_node->data.fn_def.scope = context; | 1062 | fn_table_entry->fn_def_node, containing_scope, fn_table_entry); |
| 1065 | } | 1063 | } |
| 1066 | 1064 | ||
| 1067 | if (!fn_wants_full_static_eval(fn_table_entry)) { | 1065 | if (!fn_wants_full_static_eval(fn_table_entry)) { |
| ... | @@ -1095,23 +1093,6 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t | ... | @@ -1095,23 +1093,6 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t |
| 1095 | ZigLLVMAddFunctionAttr(fn_table_entry->fn_value, "no-frame-pointer-elim", "true"); | 1093 | ZigLLVMAddFunctionAttr(fn_table_entry->fn_value, "no-frame-pointer-elim", "true"); |
| 1096 | ZigLLVMAddFunctionAttr(fn_table_entry->fn_value, "no-frame-pointer-elim-non-leaf", nullptr); | 1094 | ZigLLVMAddFunctionAttr(fn_table_entry->fn_value, "no-frame-pointer-elim-non-leaf", nullptr); |
| 1097 | } | 1095 | } |
| 1098 | |||
| 1099 | if (fn_table_entry->fn_def_node) { | ||
| 1100 | // Add debug info. | ||
| 1101 | unsigned line_number = node->line + 1; | ||
| 1102 | unsigned scope_line = line_number; | ||
| 1103 | bool is_definition = fn_table_entry->fn_def_node != nullptr; | ||
| 1104 | unsigned flags = 0; | ||
| 1105 | bool is_optimized = g->is_release_build; | ||
| 1106 | ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder, | ||
| 1107 | containing_context->di_scope, buf_ptr(&fn_table_entry->symbol_name), "", | ||
| 1108 | import->di_file, line_number, | ||
| 1109 | fn_type->di_type, fn_table_entry->internal_linkage, | ||
| 1110 | is_definition, scope_line, flags, is_optimized, nullptr); | ||
| 1111 | |||
| 1112 | fn_table_entry->fn_def_node->data.fn_def.scope->di_scope = ZigLLVMSubprogramToScope(subprogram); | ||
| 1113 | ZigLLVMFnSetSubprogram(fn_table_entry->fn_value, subprogram); | ||
| 1114 | } | ||
| 1115 | } | 1096 | } |
| 1116 | } | 1097 | } |
| 1117 | 1098 | ||
| ... | @@ -1151,7 +1132,7 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt | ... | @@ -1151,7 +1132,7 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt |
| 1151 | uint64_t biggest_align_in_bits = 0; | 1132 | uint64_t biggest_align_in_bits = 0; |
| 1152 | uint64_t biggest_union_member_size_in_bits = 0; | 1133 | uint64_t biggest_union_member_size_in_bits = 0; |
| 1153 | 1134 | ||
| 1154 | Scope *context = enum_type->data.enumeration.scope; | 1135 | Scope *scope = &enum_type->data.enumeration.decls_scope->base; |
| 1155 | 1136 | ||
| 1156 | // set temporary flag | 1137 | // set temporary flag |
| 1157 | enum_type->data.enumeration.embedded_in_current = true; | 1138 | enum_type->data.enumeration.embedded_in_current = true; |
| ... | @@ -1161,7 +1142,7 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt | ... | @@ -1161,7 +1142,7 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt |
| 1161 | AstNode *field_node = decl_node->data.struct_decl.fields.at(i); | 1142 | AstNode *field_node = decl_node->data.struct_decl.fields.at(i); |
| 1162 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i]; | 1143 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i]; |
| 1163 | type_enum_field->name = field_node->data.struct_field.name; | 1144 | type_enum_field->name = field_node->data.struct_field.name; |
| 1164 | TypeTableEntry *field_type = analyze_type_expr(g, import, context, | 1145 | TypeTableEntry *field_type = analyze_type_expr(g, import, scope, |
| 1165 | field_node->data.struct_field.type); | 1146 | field_node->data.struct_field.type); |
| 1166 | type_enum_field->type_entry = field_type; | 1147 | type_enum_field->type_entry = field_type; |
| 1167 | type_enum_field->value = i; | 1148 | type_enum_field->value = i; |
| ... | @@ -1337,14 +1318,14 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE | ... | @@ -1337,14 +1318,14 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE |
| 1337 | // this field should be set to true only during the recursive calls to resolve_struct_type | 1318 | // this field should be set to true only during the recursive calls to resolve_struct_type |
| 1338 | struct_type->data.structure.embedded_in_current = true; | 1319 | struct_type->data.structure.embedded_in_current = true; |
| 1339 | 1320 | ||
| 1340 | Scope *context = struct_type->data.structure.scope; | 1321 | Scope *scope = &struct_type->data.structure.decls_scope->base; |
| 1341 | 1322 | ||
| 1342 | size_t gen_field_index = 0; | 1323 | size_t gen_field_index = 0; |
| 1343 | for (size_t i = 0; i < field_count; i += 1) { | 1324 | for (size_t i = 0; i < field_count; i += 1) { |
| 1344 | AstNode *field_node = decl_node->data.struct_decl.fields.at(i); | 1325 | AstNode *field_node = decl_node->data.struct_decl.fields.at(i); |
| 1345 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; | 1326 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; |
| 1346 | type_struct_field->name = field_node->data.struct_field.name; | 1327 | type_struct_field->name = field_node->data.struct_field.name; |
| 1347 | TypeTableEntry *field_type = analyze_type_expr(g, import, context, | 1328 | TypeTableEntry *field_type = analyze_type_expr(g, import, scope, |
| 1348 | field_node->data.struct_field.type); | 1329 | field_node->data.struct_field.type); |
| 1349 | type_struct_field->type_entry = field_type; | 1330 | type_struct_field->type_entry = field_type; |
| 1350 | type_struct_field->src_index = i; | 1331 | type_struct_field->src_index = i; |
| ... | @@ -1463,7 +1444,7 @@ static bool get_is_generic_fn(AstNode *proto_node) { | ... | @@ -1463,7 +1444,7 @@ static bool get_is_generic_fn(AstNode *proto_node) { |
| 1463 | } | 1444 | } |
| 1464 | 1445 | ||
| 1465 | static void preview_fn_proto_instance(CodeGen *g, ImportTableEntry *import, AstNode *proto_node, | 1446 | static void preview_fn_proto_instance(CodeGen *g, ImportTableEntry *import, AstNode *proto_node, |
| 1466 | Scope *containing_context) | 1447 | Scope *containing_scope) |
| 1467 | { | 1448 | { |
| 1468 | assert(proto_node->type == NodeTypeFnProto); | 1449 | assert(proto_node->type == NodeTypeFnProto); |
| 1469 | 1450 | ||
| ... | @@ -1515,7 +1496,7 @@ static void preview_fn_proto_instance(CodeGen *g, ImportTableEntry *import, AstN | ... | @@ -1515,7 +1496,7 @@ static void preview_fn_proto_instance(CodeGen *g, ImportTableEntry *import, AstN |
| 1515 | 1496 | ||
| 1516 | 1497 | ||
| 1517 | } else { | 1498 | } else { |
| 1518 | resolve_function_proto(g, proto_node, fn_table_entry, import, containing_context); | 1499 | resolve_function_proto(g, proto_node, fn_table_entry, import, containing_scope); |
| 1519 | 1500 | ||
| 1520 | if (!fn_wants_full_static_eval(fn_table_entry)) { | 1501 | if (!fn_wants_full_static_eval(fn_table_entry)) { |
| 1521 | g->fn_protos.append(fn_table_entry); | 1502 | g->fn_protos.append(fn_table_entry); |
| ... | @@ -1546,7 +1527,7 @@ static void preview_fn_proto_instance(CodeGen *g, ImportTableEntry *import, AstN | ... | @@ -1546,7 +1527,7 @@ static void preview_fn_proto_instance(CodeGen *g, ImportTableEntry *import, AstN |
| 1546 | } | 1527 | } |
| 1547 | } | 1528 | } |
| 1548 | 1529 | ||
| 1549 | static void add_top_level_decl(CodeGen *g, ImportTableEntry *import, Scope *scope, | 1530 | static void add_top_level_decl(CodeGen *g, ImportTableEntry *import, ScopeDecls *decls_scope, |
| 1550 | AstNode *node, Buf *name) | 1531 | AstNode *node, Buf *name) |
| 1551 | { | 1532 | { |
| 1552 | assert(import); | 1533 | assert(import); |
| ... | @@ -1562,19 +1543,17 @@ static void add_top_level_decl(CodeGen *g, ImportTableEntry *import, Scope *scop | ... | @@ -1562,19 +1543,17 @@ static void add_top_level_decl(CodeGen *g, ImportTableEntry *import, Scope *scop |
| 1562 | g->resolve_queue.append(node); | 1543 | g->resolve_queue.append(node); |
| 1563 | } | 1544 | } |
| 1564 | 1545 | ||
| 1565 | node->scope = scope; | 1546 | node->scope = &decls_scope->base; |
| 1566 | 1547 | ||
| 1567 | auto entry = scope->decl_table.maybe_get(name); | 1548 | auto entry = decls_scope->decl_table.put_unique(name, node); |
| 1568 | if (entry) { | 1549 | if (entry) { |
| 1569 | AstNode *other_decl_node = entry->value; | 1550 | AstNode *other_decl_node = entry->value; |
| 1570 | ErrorMsg *msg = add_node_error(g, node, buf_sprintf("redefinition of '%s'", buf_ptr(name))); | 1551 | ErrorMsg *msg = add_node_error(g, node, buf_sprintf("redefinition of '%s'", buf_ptr(name))); |
| 1571 | add_error_note(g, msg, other_decl_node, buf_sprintf("previous definition is here")); | 1552 | add_error_note(g, msg, other_decl_node, buf_sprintf("previous definition is here")); |
| 1572 | } else { | ||
| 1573 | scope->decl_table.put(name, node); | ||
| 1574 | } | 1553 | } |
| 1575 | } | 1554 | } |
| 1576 | 1555 | ||
| 1577 | static void scan_struct_decl(CodeGen *g, ImportTableEntry *import, Scope *context, AstNode *node) { | 1556 | static void scan_struct_decl(CodeGen *g, ImportTableEntry *import, ScopeDecls *decls_scope, AstNode *node) { |
| 1578 | assert(node->type == NodeTypeContainerDecl); | 1557 | assert(node->type == NodeTypeContainerDecl); |
| 1579 | 1558 | ||
| 1580 | if (node->data.struct_decl.type_entry) { | 1559 | if (node->data.struct_decl.type_entry) { |
| ... | @@ -1583,7 +1562,7 @@ static void scan_struct_decl(CodeGen *g, ImportTableEntry *import, Scope *contex | ... | @@ -1583,7 +1562,7 @@ static void scan_struct_decl(CodeGen *g, ImportTableEntry *import, Scope *contex |
| 1583 | } | 1562 | } |
| 1584 | 1563 | ||
| 1585 | Buf *name = node->data.struct_decl.name; | 1564 | Buf *name = node->data.struct_decl.name; |
| 1586 | TypeTableEntry *container_type = get_partial_container_type(g, import, context, | 1565 | TypeTableEntry *container_type = get_partial_container_type(g, import, &decls_scope->base, |
| 1587 | node->data.struct_decl.kind, node, buf_ptr(name)); | 1566 | node->data.struct_decl.kind, node, buf_ptr(name)); |
| 1588 | node->data.struct_decl.type_entry = container_type; | 1567 | node->data.struct_decl.type_entry = container_type; |
| 1589 | 1568 | ||
| ... | @@ -1591,8 +1570,8 @@ static void scan_struct_decl(CodeGen *g, ImportTableEntry *import, Scope *contex | ... | @@ -1591,8 +1570,8 @@ static void scan_struct_decl(CodeGen *g, ImportTableEntry *import, Scope *contex |
| 1591 | for (size_t i = 0; i < node->data.struct_decl.decls.length; i += 1) { | 1570 | for (size_t i = 0; i < node->data.struct_decl.decls.length; i += 1) { |
| 1592 | AstNode *child_node = node->data.struct_decl.decls.at(i); | 1571 | AstNode *child_node = node->data.struct_decl.decls.at(i); |
| 1593 | get_as_top_level_decl(child_node)->parent_decl = node; | 1572 | get_as_top_level_decl(child_node)->parent_decl = node; |
| 1594 | Scope *child_context = get_container_block_context(container_type); | 1573 | ScopeDecls *child_scope = get_container_scope(container_type); |
| 1595 | scan_decls(g, import, child_context, child_node); | 1574 | scan_decls(g, import, child_scope, child_node); |
| 1596 | } | 1575 | } |
| 1597 | } | 1576 | } |
| 1598 | 1577 | ||
| ... | @@ -1644,37 +1623,37 @@ static void preview_error_value_decl(CodeGen *g, AstNode *node) { | ... | @@ -1644,37 +1623,37 @@ static void preview_error_value_decl(CodeGen *g, AstNode *node) { |
| 1644 | node->data.error_value_decl.top_level_decl.resolution = TldResolutionOk; | 1623 | node->data.error_value_decl.top_level_decl.resolution = TldResolutionOk; |
| 1645 | } | 1624 | } |
| 1646 | 1625 | ||
| 1647 | void scan_decls(CodeGen *g, ImportTableEntry *import, Scope *context, AstNode *node) { | 1626 | void scan_decls(CodeGen *g, ImportTableEntry *import, ScopeDecls *decls_scope, AstNode *node) { |
| 1648 | switch (node->type) { | 1627 | switch (node->type) { |
| 1649 | case NodeTypeRoot: | 1628 | case NodeTypeRoot: |
| 1650 | for (size_t i = 0; i < import->root->data.root.top_level_decls.length; i += 1) { | 1629 | for (size_t i = 0; i < import->root->data.root.top_level_decls.length; i += 1) { |
| 1651 | AstNode *child = import->root->data.root.top_level_decls.at(i); | 1630 | AstNode *child = import->root->data.root.top_level_decls.at(i); |
| 1652 | scan_decls(g, import, context, child); | 1631 | scan_decls(g, import, decls_scope, child); |
| 1653 | } | 1632 | } |
| 1654 | break; | 1633 | break; |
| 1655 | case NodeTypeContainerDecl: | 1634 | case NodeTypeContainerDecl: |
| 1656 | { | 1635 | { |
| 1657 | Buf *name = node->data.struct_decl.name; | 1636 | Buf *name = node->data.struct_decl.name; |
| 1658 | add_top_level_decl(g, import, context, node, name); | 1637 | add_top_level_decl(g, import, decls_scope, node, name); |
| 1659 | if (node->data.struct_decl.generic_params.length == 0) { | 1638 | if (node->data.struct_decl.generic_params.length == 0) { |
| 1660 | scan_struct_decl(g, import, context, node); | 1639 | scan_struct_decl(g, import, decls_scope, node); |
| 1661 | } | 1640 | } |
| 1662 | } | 1641 | } |
| 1663 | break; | 1642 | break; |
| 1664 | case NodeTypeFnDef: | 1643 | case NodeTypeFnDef: |
| 1665 | node->data.fn_def.fn_proto->data.fn_proto.fn_def_node = node; | 1644 | node->data.fn_def.fn_proto->data.fn_proto.fn_def_node = node; |
| 1666 | scan_decls(g, import, context, node->data.fn_def.fn_proto); | 1645 | scan_decls(g, import, decls_scope, node->data.fn_def.fn_proto); |
| 1667 | break; | 1646 | break; |
| 1668 | case NodeTypeVariableDeclaration: | 1647 | case NodeTypeVariableDeclaration: |
| 1669 | { | 1648 | { |
| 1670 | Buf *name = node->data.variable_declaration.symbol; | 1649 | Buf *name = node->data.variable_declaration.symbol; |
| 1671 | add_top_level_decl(g, import, context, node, name); | 1650 | add_top_level_decl(g, import, decls_scope, node, name); |
| 1672 | break; | 1651 | break; |
| 1673 | } | 1652 | } |
| 1674 | case NodeTypeTypeDecl: | 1653 | case NodeTypeTypeDecl: |
| 1675 | { | 1654 | { |
| 1676 | Buf *name = node->data.type_decl.symbol; | 1655 | Buf *name = node->data.type_decl.symbol; |
| 1677 | add_top_level_decl(g, import, context, node, name); | 1656 | add_top_level_decl(g, import, decls_scope, node, name); |
| 1678 | break; | 1657 | break; |
| 1679 | } | 1658 | } |
| 1680 | case NodeTypeFnProto: | 1659 | case NodeTypeFnProto: |
| ... | @@ -1688,14 +1667,14 @@ void scan_decls(CodeGen *g, ImportTableEntry *import, Scope *context, AstNode *n | ... | @@ -1688,14 +1667,14 @@ void scan_decls(CodeGen *g, ImportTableEntry *import, Scope *context, AstNode *n |
| 1688 | } | 1667 | } |
| 1689 | count_inline_and_var_args(node); | 1668 | count_inline_and_var_args(node); |
| 1690 | 1669 | ||
| 1691 | add_top_level_decl(g, import, context, node, fn_name); | 1670 | add_top_level_decl(g, import, decls_scope, node, fn_name); |
| 1692 | break; | 1671 | break; |
| 1693 | } | 1672 | } |
| 1694 | case NodeTypeUse: | 1673 | case NodeTypeUse: |
| 1695 | { | 1674 | { |
| 1696 | TopLevelDecl *tld = get_as_top_level_decl(node); | 1675 | TopLevelDecl *tld = get_as_top_level_decl(node); |
| 1697 | tld->import = import; | 1676 | tld->import = import; |
| 1698 | node->scope = context; | 1677 | node->scope = &decls_scope->base; |
| 1699 | g->use_queue.append(node); | 1678 | g->use_queue.append(node); |
| 1700 | tld->import->use_decls.append(node); | 1679 | tld->import->use_decls.append(node); |
| 1701 | break; | 1680 | break; |
| ... | @@ -1816,70 +1795,65 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt | ... | @@ -1816,70 +1795,65 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt |
| 1816 | 1795 | ||
| 1817 | // Set name to nullptr to make the variable anonymous (not visible to programmer). | 1796 | // Set name to nullptr to make the variable anonymous (not visible to programmer). |
| 1818 | // TODO merge with definition of add_local_var in ir.cpp | 1797 | // TODO merge with definition of add_local_var in ir.cpp |
| 1819 | static VariableTableEntry *add_local_var_shadowable(CodeGen *g, AstNode *source_node, ImportTableEntry *import, | 1798 | static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, ImportTableEntry *import, |
| 1820 | Scope *context, Buf *name, TypeTableEntry *type_entry, bool is_const, AstNode *val_node, | 1799 | Scope *parent_scope, Buf *name, TypeTableEntry *type_entry, bool is_const, AstNode *val_node) |
| 1821 | bool shadowable) | ||
| 1822 | { | 1800 | { |
| 1823 | VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1); | 1801 | VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1); |
| 1824 | variable_entry->type = type_entry; | 1802 | variable_entry->type = type_entry; |
| 1825 | variable_entry->scope = context; | 1803 | variable_entry->parent_scope = parent_scope; |
| 1826 | variable_entry->import = import; | 1804 | variable_entry->import = import; |
| 1827 | variable_entry->shadowable = shadowable; | 1805 | variable_entry->shadowable = false; |
| 1828 | variable_entry->mem_slot_index = SIZE_MAX; | 1806 | variable_entry->mem_slot_index = SIZE_MAX; |
| 1829 | 1807 | ||
| 1830 | if (name) { | 1808 | assert(name); |
| 1831 | buf_init_from_buf(&variable_entry->name, name); | ||
| 1832 | 1809 | ||
| 1833 | if (type_entry->id != TypeTableEntryIdInvalid) { | 1810 | buf_init_from_buf(&variable_entry->name, name); |
| 1834 | VariableTableEntry *existing_var = find_variable(g, context, name); | 1811 | |
| 1835 | if (existing_var && !existing_var->shadowable) { | 1812 | if (type_entry->id != TypeTableEntryIdInvalid) { |
| 1836 | ErrorMsg *msg = add_node_error(g, source_node, | 1813 | VariableTableEntry *existing_var = find_variable(g, parent_scope, name); |
| 1837 | buf_sprintf("redeclaration of variable '%s'", buf_ptr(name))); | 1814 | if (existing_var && !existing_var->shadowable) { |
| 1838 | add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here")); | 1815 | ErrorMsg *msg = add_node_error(g, source_node, |
| 1816 | buf_sprintf("redeclaration of variable '%s'", buf_ptr(name))); | ||
| 1817 | add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here")); | ||
| 1818 | variable_entry->type = g->builtin_types.entry_invalid; | ||
| 1819 | } else { | ||
| 1820 | auto primitive_table_entry = g->primitive_type_table.maybe_get(name); | ||
| 1821 | if (primitive_table_entry) { | ||
| 1822 | TypeTableEntry *type = primitive_table_entry->value; | ||
| 1823 | add_node_error(g, source_node, | ||
| 1824 | buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name))); | ||
| 1839 | variable_entry->type = g->builtin_types.entry_invalid; | 1825 | variable_entry->type = g->builtin_types.entry_invalid; |
| 1840 | } else { | 1826 | } else { |
| 1841 | auto primitive_table_entry = g->primitive_type_table.maybe_get(name); | 1827 | AstNode *decl_node = find_decl(parent_scope, name); |
| 1842 | if (primitive_table_entry) { | 1828 | if (decl_node && decl_node->type != NodeTypeVariableDeclaration) { |
| 1843 | TypeTableEntry *type = primitive_table_entry->value; | 1829 | ErrorMsg *msg = add_node_error(g, source_node, |
| 1844 | add_node_error(g, source_node, | 1830 | buf_sprintf("redefinition of '%s'", buf_ptr(name))); |
| 1845 | buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name))); | 1831 | add_error_note(g, msg, decl_node, buf_sprintf("previous definition is here")); |
| 1846 | variable_entry->type = g->builtin_types.entry_invalid; | 1832 | variable_entry->type = g->builtin_types.entry_invalid; |
| 1847 | } else { | ||
| 1848 | AstNode *decl_node = find_decl(context, name); | ||
| 1849 | if (decl_node && decl_node->type != NodeTypeVariableDeclaration) { | ||
| 1850 | ErrorMsg *msg = add_node_error(g, source_node, | ||
| 1851 | buf_sprintf("redefinition of '%s'", buf_ptr(name))); | ||
| 1852 | add_error_note(g, msg, decl_node, buf_sprintf("previous definition is here")); | ||
| 1853 | variable_entry->type = g->builtin_types.entry_invalid; | ||
| 1854 | } | ||
| 1855 | } | 1833 | } |
| 1856 | } | 1834 | } |
| 1857 | } | 1835 | } |
| 1836 | } | ||
| 1858 | 1837 | ||
| 1859 | context->var_table.put(&variable_entry->name, variable_entry); | 1838 | Scope *child_scope; |
| 1839 | if (source_node->type == NodeTypeParamDecl) { | ||
| 1840 | child_scope = create_var_scope(source_node, parent_scope, variable_entry); | ||
| 1860 | } else { | 1841 | } else { |
| 1861 | // TODO replace _anon with @anon and make sure all tests still pass | 1842 | // it's already in the decls table |
| 1862 | buf_init_from_str(&variable_entry->name, "_anon"); | 1843 | child_scope = parent_scope; |
| 1863 | } | ||
| 1864 | if (context->fn_entry) { | ||
| 1865 | context->fn_entry->variable_list.append(variable_entry); | ||
| 1866 | } | 1844 | } |
| 1867 | 1845 | ||
| 1846 | |||
| 1868 | variable_entry->src_is_const = is_const; | 1847 | variable_entry->src_is_const = is_const; |
| 1869 | variable_entry->gen_is_const = is_const; | 1848 | variable_entry->gen_is_const = is_const; |
| 1870 | variable_entry->decl_node = source_node; | 1849 | variable_entry->decl_node = source_node; |
| 1871 | variable_entry->val_node = val_node; | 1850 | variable_entry->val_node = val_node; |
| 1851 | variable_entry->child_scope = child_scope; | ||
| 1872 | 1852 | ||
| 1873 | 1853 | ||
| 1874 | return variable_entry; | 1854 | return variable_entry; |
| 1875 | } | 1855 | } |
| 1876 | 1856 | ||
| 1877 | static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, ImportTableEntry *import, | ||
| 1878 | Scope *context, Buf *name, TypeTableEntry *type_entry, bool is_const, AstNode *val_node) | ||
| 1879 | { | ||
| 1880 | return add_local_var_shadowable(g, source_node, import, context, name, type_entry, is_const, val_node, false); | ||
| 1881 | } | ||
| 1882 | |||
| 1883 | static void resolve_var_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) { | 1857 | static void resolve_var_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 1884 | assert(node->type == NodeTypeVariableDeclaration); | 1858 | assert(node->type == NodeTypeVariableDeclaration); |
| 1885 | 1859 | ||
| ... | @@ -1889,8 +1863,6 @@ static void resolve_var_decl(CodeGen *g, ImportTableEntry *import, AstNode *node | ... | @@ -1889,8 +1863,6 @@ static void resolve_var_decl(CodeGen *g, ImportTableEntry *import, AstNode *node |
| 1889 | bool is_export = (var_decl->top_level_decl.visib_mod == VisibModExport); | 1863 | bool is_export = (var_decl->top_level_decl.visib_mod == VisibModExport); |
| 1890 | bool is_extern = var_decl->is_extern; | 1864 | bool is_extern = var_decl->is_extern; |
| 1891 | 1865 | ||
| 1892 | assert(!scope->fn_entry); | ||
| 1893 | |||
| 1894 | TypeTableEntry *explicit_type = nullptr; | 1866 | TypeTableEntry *explicit_type = nullptr; |
| 1895 | if (var_decl->type) { | 1867 | if (var_decl->type) { |
| 1896 | TypeTableEntry *proposed_type = analyze_type_expr(g, import, scope, var_decl->type); | 1868 | TypeTableEntry *proposed_type = analyze_type_expr(g, import, scope, var_decl->type); |
| ... | @@ -1980,7 +1952,7 @@ void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only) { | ... | @@ -1980,7 +1952,7 @@ void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only) { |
| 1980 | if (node->data.type_decl.override_type) { | 1952 | if (node->data.type_decl.override_type) { |
| 1981 | entry = node->data.type_decl.override_type; | 1953 | entry = node->data.type_decl.override_type; |
| 1982 | } else { | 1954 | } else { |
| 1983 | TypeTableEntry *child_type = analyze_type_expr(g, import, import->scope, type_node); | 1955 | TypeTableEntry *child_type = analyze_type_expr(g, import, &import->decls_scope->base, type_node); |
| 1984 | if (child_type->id == TypeTableEntryIdInvalid) { | 1956 | if (child_type->id == TypeTableEntryIdInvalid) { |
| 1985 | entry = child_type; | 1957 | entry = child_type; |
| 1986 | } else { | 1958 | } else { |
| ... | @@ -2170,52 +2142,105 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry * | ... | @@ -2170,52 +2142,105 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry * |
| 2170 | return false; | 2142 | return false; |
| 2171 | } | 2143 | } |
| 2172 | 2144 | ||
| 2173 | Scope *new_scope(AstNode *node, Scope *parent) { | 2145 | ScopeDecls *create_decls_scope(AstNode *node, Scope *parent) { |
| 2174 | Scope *context = allocate<Scope>(1); | 2146 | assert(node->type == NodeTypeRoot || node->type == NodeTypeContainerDecl); |
| 2175 | context->node = node; | 2147 | ScopeDecls *scope = allocate<ScopeDecls>(1); |
| 2176 | context->parent = parent; | 2148 | scope->base.node = node; |
| 2177 | context->decl_table.init(1); | 2149 | scope->base.parent = parent; |
| 2178 | context->var_table.init(1); | 2150 | scope->decl_table.init(4); |
| 2179 | context->label_table.init(1); | 2151 | return scope; |
| 2152 | } | ||
| 2153 | |||
| 2154 | Scope *create_block_scope(AstNode *node, Scope *parent) { | ||
| 2155 | assert(node->type == NodeTypeBlock); | ||
| 2156 | ScopeBlock *scope = allocate<ScopeBlock>(1); | ||
| 2157 | scope->base.node = node; | ||
| 2158 | scope->base.parent = parent; | ||
| 2159 | scope->label_table.init(1); | ||
| 2160 | return &scope->base; | ||
| 2161 | } | ||
| 2180 | 2162 | ||
| 2181 | if (parent) { | 2163 | Scope *create_defer_scope(AstNode *node, Scope *parent) { |
| 2182 | context->parent_loop_node = parent->parent_loop_node; | 2164 | assert(node->type == NodeTypeDefer); |
| 2183 | context->c_import_buf = parent->c_import_buf; | 2165 | ScopeDefer *scope = allocate<ScopeDefer>(1); |
| 2184 | } | 2166 | scope->base.node = node; |
| 2167 | scope->base.parent = parent; | ||
| 2168 | return &scope->base; | ||
| 2169 | } | ||
| 2185 | 2170 | ||
| 2186 | if (node && node->type == NodeTypeFnDef) { | 2171 | Scope *create_var_scope(AstNode *node, Scope *parent, VariableTableEntry *var) { |
| 2187 | AstNode *fn_proto_node = node->data.fn_def.fn_proto; | 2172 | assert(node->type == NodeTypeVariableDeclaration || node->type == NodeTypeParamDecl); |
| 2188 | context->fn_entry = fn_proto_node->data.fn_proto.fn_table_entry; | 2173 | ScopeVarDecl *scope = allocate<ScopeVarDecl>(1); |
| 2189 | } else if (parent) { | 2174 | scope->base.node = node; |
| 2190 | context->fn_entry = parent->fn_entry; | 2175 | scope->base.parent = parent; |
| 2191 | } | 2176 | scope->var = var; |
| 2177 | return &scope->base; | ||
| 2178 | } | ||
| 2192 | 2179 | ||
| 2193 | if (context->fn_entry) { | 2180 | Scope *create_cimport_scope(AstNode *node, Scope *parent) { |
| 2194 | context->fn_entry->all_block_contexts.append(context); | 2181 | assert(node->type == NodeTypeFnCallExpr); |
| 2195 | } | 2182 | ScopeCImport *scope = allocate<ScopeCImport>(1); |
| 2183 | scope->base.node = node; | ||
| 2184 | scope->base.parent = parent; | ||
| 2185 | buf_resize(&scope->c_import_buf, 0); | ||
| 2186 | return &scope->base; | ||
| 2187 | } | ||
| 2188 | |||
| 2189 | Scope *create_loop_scope(AstNode *node, Scope *parent) { | ||
| 2190 | assert(node->type == NodeTypeWhileExpr || node->type == NodeTypeForExpr); | ||
| 2191 | ScopeLoop *scope = allocate<ScopeLoop>(1); | ||
| 2192 | scope->base.node = node; | ||
| 2193 | scope->base.parent = parent; | ||
| 2194 | return &scope->base; | ||
| 2195 | } | ||
| 2196 | 2196 | ||
| 2197 | return context; | 2197 | Scope *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_entry) { |
| 2198 | assert(node->type == NodeTypeFnDef); | ||
| 2199 | ScopeFnBody *scope = allocate<ScopeFnBody>(1); | ||
| 2200 | scope->base.node = node; | ||
| 2201 | scope->base.parent = parent; | ||
| 2202 | scope->fn_entry = fn_entry; | ||
| 2203 | return &scope->base; | ||
| 2198 | } | 2204 | } |
| 2199 | 2205 | ||
| 2200 | AstNode *find_decl(Scope *context, Buf *name) { | 2206 | AstNode *find_decl(Scope *scope, Buf *name) { |
| 2201 | while (context) { | 2207 | while (scope) { |
| 2202 | auto entry = context->decl_table.maybe_get(name); | 2208 | if (scope->node->type == NodeTypeRoot || |
| 2203 | if (entry) { | 2209 | scope->node->type == NodeTypeContainerDecl) |
| 2204 | return entry->value; | 2210 | { |
| 2211 | ScopeDecls *decls_scope = (ScopeDecls *)scope; | ||
| 2212 | auto entry = decls_scope->decl_table.maybe_get(name); | ||
| 2213 | if (entry) | ||
| 2214 | return entry->value; | ||
| 2205 | } | 2215 | } |
| 2206 | context = context->parent; | 2216 | scope = scope->parent; |
| 2207 | } | 2217 | } |
| 2208 | return nullptr; | 2218 | return nullptr; |
| 2209 | } | 2219 | } |
| 2210 | 2220 | ||
| 2211 | VariableTableEntry *find_variable(CodeGen *g, Scope *orig_context, Buf *name) { | 2221 | VariableTableEntry *find_variable(CodeGen *g, Scope *scope, Buf *name) { |
| 2212 | Scope *context = orig_context; | 2222 | while (scope) { |
| 2213 | while (context) { | 2223 | if (scope->node->type == NodeTypeVariableDeclaration || |
| 2214 | auto entry = context->var_table.maybe_get(name); | 2224 | scope->node->type == NodeTypeParamDecl) |
| 2215 | if (entry) { | 2225 | { |
| 2216 | return entry->value; | 2226 | ScopeVarDecl *var_scope = (ScopeVarDecl *)scope; |
| 2227 | if (buf_eql_buf(name, &var_scope->var->name)) | ||
| 2228 | return var_scope->var; | ||
| 2229 | } else if (scope->node->type == NodeTypeRoot || | ||
| 2230 | scope->node->type == NodeTypeContainerDecl) | ||
| 2231 | { | ||
| 2232 | ScopeDecls *decls_scope = (ScopeDecls *)scope; | ||
| 2233 | auto entry = decls_scope->decl_table.maybe_get(name); | ||
| 2234 | if (entry) { | ||
| 2235 | AstNode *decl_node = entry->value; | ||
| 2236 | if (decl_node->type == NodeTypeVariableDeclaration) { | ||
| 2237 | VariableTableEntry *var = decl_node->data.variable_declaration.variable; | ||
| 2238 | if (var) | ||
| 2239 | return var; | ||
| 2240 | } | ||
| 2241 | } | ||
| 2217 | } | 2242 | } |
| 2218 | context = context->parent; | 2243 | scope = scope->parent; |
| 2219 | } | 2244 | } |
| 2220 | 2245 | ||
| 2221 | return nullptr; | 2246 | return nullptr; |
| ... | @@ -2355,7 +2380,7 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) { | ... | @@ -2355,7 +2380,7 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 2355 | } | 2380 | } |
| 2356 | fn_table_entry->anal_state = FnAnalStateProbing; | 2381 | fn_table_entry->anal_state = FnAnalStateProbing; |
| 2357 | 2382 | ||
| 2358 | Scope *context = node->data.fn_def.scope; | 2383 | Scope *child_scope = node->data.fn_def.containing_scope; |
| 2359 | 2384 | ||
| 2360 | TypeTableEntry *fn_type = fn_table_entry->type_entry; | 2385 | TypeTableEntry *fn_type = fn_table_entry->type_entry; |
| 2361 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; | 2386 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; |
| ... | @@ -2381,16 +2406,20 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) { | ... | @@ -2381,16 +2406,20 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 2381 | add_node_error(g, param_decl_node, buf_sprintf("missing parameter name")); | 2406 | add_node_error(g, param_decl_node, buf_sprintf("missing parameter name")); |
| 2382 | } | 2407 | } |
| 2383 | 2408 | ||
| 2384 | VariableTableEntry *var = add_local_var(g, param_decl_node, import, context, param_decl->name, | 2409 | VariableTableEntry *var = add_local_var(g, param_decl_node, import, child_scope, param_decl->name, |
| 2385 | type, true, nullptr); | 2410 | type, true, nullptr); |
| 2386 | var->src_arg_index = i; | 2411 | var->src_arg_index = i; |
| 2387 | param_decl_node->data.param_decl.variable = var; | 2412 | param_decl_node->data.param_decl.variable = var; |
| 2413 | child_scope = var->child_scope; | ||
| 2414 | fn_table_entry->variable_list.append(var); | ||
| 2388 | 2415 | ||
| 2389 | if (fn_type->data.fn.gen_param_info) { | 2416 | if (fn_type->data.fn.gen_param_info) { |
| 2390 | var->gen_arg_index = fn_type->data.fn.gen_param_info[i].gen_index; | 2417 | var->gen_arg_index = fn_type->data.fn.gen_param_info[i].gen_index; |
| 2391 | } | 2418 | } |
| 2392 | } | 2419 | } |
| 2393 | 2420 | ||
| 2421 | node->data.fn_def.child_scope = child_scope; | ||
| 2422 | |||
| 2394 | TypeTableEntry *expected_type = fn_type->data.fn.fn_type_id.return_type; | 2423 | TypeTableEntry *expected_type = fn_type->data.fn.fn_type_id.return_type; |
| 2395 | 2424 | ||
| 2396 | if (fn_type->data.fn.fn_type_id.is_extern && handle_is_ptr(expected_type)) { | 2425 | if (fn_type->data.fn.fn_type_id.is_extern && handle_is_ptr(expected_type)) { |
| ... | @@ -2456,7 +2485,7 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode * | ... | @@ -2456,7 +2485,7 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode * |
| 2456 | continue; | 2485 | continue; |
| 2457 | } | 2486 | } |
| 2458 | if (target_tld->visib_mod != VisibModPrivate) { | 2487 | if (target_tld->visib_mod != VisibModPrivate) { |
| 2459 | auto existing_entry = tld->import->scope->decl_table.maybe_get(target_tld->name); | 2488 | auto existing_entry = tld->import->decls_scope->decl_table.put_unique(target_tld->name, decl_node); |
| 2460 | if (existing_entry) { | 2489 | if (existing_entry) { |
| 2461 | AstNode *existing_decl = existing_entry->value; | 2490 | AstNode *existing_decl = existing_entry->value; |
| 2462 | if (existing_decl != decl_node) { | 2491 | if (existing_decl != decl_node) { |
| ... | @@ -2466,8 +2495,6 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode * | ... | @@ -2466,8 +2495,6 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode * |
| 2466 | add_error_note(g, msg, existing_decl, buf_sprintf("previous definition here")); | 2495 | add_error_note(g, msg, existing_decl, buf_sprintf("previous definition here")); |
| 2467 | add_error_note(g, msg, decl_node, buf_sprintf("imported definition here")); | 2496 | add_error_note(g, msg, decl_node, buf_sprintf("imported definition here")); |
| 2468 | } | 2497 | } |
| 2469 | } else { | ||
| 2470 | tld->import->scope->decl_table.put(target_tld->name, decl_node); | ||
| 2471 | } | 2498 | } |
| 2472 | } | 2499 | } |
| 2473 | } | 2500 | } |
| ... | @@ -2494,7 +2521,7 @@ void preview_use_decl(CodeGen *g, AstNode *node) { | ... | @@ -2494,7 +2521,7 @@ void preview_use_decl(CodeGen *g, AstNode *node) { |
| 2494 | assert(node->type == NodeTypeUse); | 2521 | assert(node->type == NodeTypeUse); |
| 2495 | TopLevelDecl *tld = get_as_top_level_decl(node); | 2522 | TopLevelDecl *tld = get_as_top_level_decl(node); |
| 2496 | 2523 | ||
| 2497 | IrInstruction *result = analyze_const_value(g, tld->import->scope, node->data.use.expr, | 2524 | IrInstruction *result = analyze_const_value(g, &tld->import->decls_scope->base, node->data.use.expr, |
| 2498 | g->builtin_types.entry_namespace); | 2525 | g->builtin_types.entry_namespace); |
| 2499 | if (result->type_entry->id == TypeTableEntryIdInvalid) | 2526 | if (result->type_entry->id == TypeTableEntryIdInvalid) |
| 2500 | tld->import->any_imports_failed = true; | 2527 | tld->import->any_imports_failed = true; |
| ... | @@ -2553,8 +2580,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, | ... | @@ -2553,8 +2580,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, |
| 2553 | g->import_table.put(abs_full_path, import_entry); | 2580 | g->import_table.put(abs_full_path, import_entry); |
| 2554 | g->import_queue.append(import_entry); | 2581 | g->import_queue.append(import_entry); |
| 2555 | 2582 | ||
| 2556 | import_entry->scope = new_scope(import_entry->root, nullptr); | 2583 | import_entry->decls_scope = create_decls_scope(import_entry->root, nullptr); |
| 2557 | import_entry->scope->di_scope = ZigLLVMFileToScope(import_entry->di_file); | ||
| 2558 | 2584 | ||
| 2559 | 2585 | ||
| 2560 | assert(import_entry->root->type == NodeTypeRoot); | 2586 | assert(import_entry->root->type == NodeTypeRoot); |
| ... | @@ -2581,7 +2607,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, | ... | @@ -2581,7 +2607,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, |
| 2581 | void semantic_analyze(CodeGen *g) { | 2607 | void semantic_analyze(CodeGen *g) { |
| 2582 | for (; g->import_queue_index < g->import_queue.length; g->import_queue_index += 1) { | 2608 | for (; g->import_queue_index < g->import_queue.length; g->import_queue_index += 1) { |
| 2583 | ImportTableEntry *import = g->import_queue.at(g->import_queue_index); | 2609 | ImportTableEntry *import = g->import_queue.at(g->import_queue_index); |
| 2584 | scan_decls(g, import, import->scope, import->root); | 2610 | scan_decls(g, import, import->decls_scope, import->root); |
| 2585 | } | 2611 | } |
| 2586 | 2612 | ||
| 2587 | for (; g->use_queue_index < g->use_queue.length; g->use_queue_index += 1) { | 2613 | for (; g->use_queue_index < g->use_queue.length; g->use_queue_index += 1) { |
src/analyze.hpp+10-3| ... | @@ -15,7 +15,6 @@ ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg); | ... | @@ -15,7 +15,6 @@ ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg); |
| 15 | ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg); | 15 | ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg); |
| 16 | TypeTableEntry *new_type_table_entry(TypeTableEntryId id); | 16 | TypeTableEntry *new_type_table_entry(TypeTableEntryId id); |
| 17 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const); | 17 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const); |
| 18 | Scope *new_scope(AstNode *node, Scope *parent); | ||
| 19 | bool is_node_void_expr(AstNode *node); | 18 | bool is_node_void_expr(AstNode *node); |
| 20 | uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry); | 19 | uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry); |
| 21 | TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, size_t size_in_bits); | 20 | TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, size_t size_in_bits); |
| ... | @@ -59,11 +58,19 @@ TypeTableEntry *container_ref_type(TypeTableEntry *type_entry); | ... | @@ -59,11 +58,19 @@ TypeTableEntry *container_ref_type(TypeTableEntry *type_entry); |
| 59 | bool type_is_complete(TypeTableEntry *type_entry); | 58 | bool type_is_complete(TypeTableEntry *type_entry); |
| 60 | void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry); | 59 | void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry); |
| 61 | TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name); | 60 | TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name); |
| 62 | Scope *get_container_block_context(TypeTableEntry *type_entry); | 61 | ScopeDecls *get_container_scope(TypeTableEntry *type_entry); |
| 63 | TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name); | 62 | TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name); |
| 64 | bool is_container_ref(TypeTableEntry *type_entry); | 63 | bool is_container_ref(TypeTableEntry *type_entry); |
| 65 | void scan_decls(CodeGen *g, ImportTableEntry *import, Scope *context, AstNode *node); | 64 | void scan_decls(CodeGen *g, ImportTableEntry *import, ScopeDecls *decls_scope, AstNode *node); |
| 66 | void preview_use_decl(CodeGen *g, AstNode *node); | 65 | void preview_use_decl(CodeGen *g, AstNode *node); |
| 67 | void resolve_use_decl(CodeGen *g, AstNode *node); | 66 | void resolve_use_decl(CodeGen *g, AstNode *node); |
| 68 | 67 | ||
| 68 | ScopeDecls *create_decls_scope(AstNode *node, Scope *parent); | ||
| 69 | Scope *create_block_scope(AstNode *node, Scope *parent); | ||
| 70 | Scope *create_defer_scope(AstNode *node, Scope *parent); | ||
| 71 | Scope *create_var_scope(AstNode *node, Scope *parent, VariableTableEntry *var); | ||
| 72 | Scope *create_cimport_scope(AstNode *node, Scope *parent); | ||
| 73 | Scope *create_loop_scope(AstNode *node, Scope *parent); | ||
| 74 | Scope *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_entry); | ||
| 75 | |||
| 69 | #endif | 76 | #endif |
src/codegen.cpp+44-26| ... | @@ -227,9 +227,47 @@ void codegen_set_rdynamic(CodeGen *g, bool rdynamic) { | ... | @@ -227,9 +227,47 @@ void codegen_set_rdynamic(CodeGen *g, bool rdynamic) { |
| 227 | static void render_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val); | 227 | static void render_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val); |
| 228 | static void render_const_val_global(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val); | 228 | static void render_const_val_global(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val); |
| 229 | 229 | ||
| 230 | static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { | ||
| 231 | if (scope->di_scope) | ||
| 232 | return scope->di_scope; | ||
| 233 | |||
| 234 | if (scope->node->type == NodeTypeFnDef) { | ||
| 235 | assert(scope->parent); | ||
| 236 | ScopeFnBody *fn_scope = (ScopeFnBody *)scope; | ||
| 237 | FnTableEntry *fn_table_entry = fn_scope->fn_entry; | ||
| 238 | unsigned line_number = fn_table_entry->proto_node->line + 1; | ||
| 239 | unsigned scope_line = line_number; | ||
| 240 | bool is_definition = fn_table_entry->fn_def_node != nullptr; | ||
| 241 | unsigned flags = 0; | ||
| 242 | bool is_optimized = g->is_release_build; | ||
| 243 | ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder, | ||
| 244 | get_di_scope(g, scope->parent), buf_ptr(&fn_table_entry->symbol_name), "", | ||
| 245 | scope->node->owner->di_file, line_number, | ||
| 246 | fn_table_entry->type_entry->di_type, fn_table_entry->internal_linkage, | ||
| 247 | is_definition, scope_line, flags, is_optimized, nullptr); | ||
| 248 | |||
| 249 | scope->di_scope = ZigLLVMSubprogramToScope(subprogram); | ||
| 250 | ZigLLVMFnSetSubprogram(fn_table_entry->fn_value, subprogram); | ||
| 251 | } else if (scope->node->type == NodeTypeRoot || | ||
| 252 | scope->node->type == NodeTypeContainerDecl) | ||
| 253 | { | ||
| 254 | scope->di_scope = ZigLLVMFileToScope(scope->node->owner->di_file); | ||
| 255 | } else { | ||
| 256 | assert(scope->parent); | ||
| 257 | ZigLLVMDILexicalBlock *di_block = ZigLLVMCreateLexicalBlock(g->dbuilder, | ||
| 258 | get_di_scope(g, scope->parent), | ||
| 259 | scope->node->owner->di_file, | ||
| 260 | scope->node->line + 1, | ||
| 261 | scope->node->column + 1); | ||
| 262 | scope->di_scope = ZigLLVMLexicalBlockToScope(di_block); | ||
| 263 | } | ||
| 264 | |||
| 265 | return scope->di_scope; | ||
| 266 | } | ||
| 267 | |||
| 230 | static void set_debug_source_node(CodeGen *g, AstNode *node) { | 268 | static void set_debug_source_node(CodeGen *g, AstNode *node) { |
| 231 | assert(node->scope); | 269 | assert(node->scope); |
| 232 | ZigLLVMSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1, node->scope->di_scope); | 270 | ZigLLVMSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1, get_di_scope(g, node->scope)); |
| 233 | } | 271 | } |
| 234 | 272 | ||
| 235 | static void clear_debug_source_node(CodeGen *g) { | 273 | static void clear_debug_source_node(CodeGen *g) { |
| ... | @@ -558,10 +596,9 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, | ... | @@ -558,10 +596,9 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, |
| 558 | } | 596 | } |
| 559 | 597 | ||
| 560 | static void gen_var_debug_decl(CodeGen *g, VariableTableEntry *var) { | 598 | static void gen_var_debug_decl(CodeGen *g, VariableTableEntry *var) { |
| 561 | Scope *scope = var->scope; | ||
| 562 | AstNode *source_node = var->decl_node; | 599 | AstNode *source_node = var->decl_node; |
| 563 | ZigLLVMDILocation *debug_loc = ZigLLVMGetDebugLoc(source_node->line + 1, source_node->column + 1, | 600 | ZigLLVMDILocation *debug_loc = ZigLLVMGetDebugLoc(source_node->line + 1, source_node->column + 1, |
| 564 | scope->di_scope); | 601 | get_di_scope(g, var->parent_scope)); |
| 565 | ZigLLVMInsertDeclareAtEnd(g->dbuilder, var->value_ref, var->di_loc_var, debug_loc, | 602 | ZigLLVMInsertDeclareAtEnd(g->dbuilder, var->value_ref, var->di_loc_var, debug_loc, |
| 566 | LLVMGetInsertBlock(g->builder)); | 603 | LLVMGetInsertBlock(g->builder)); |
| 567 | } | 604 | } |
| ... | @@ -2133,8 +2170,7 @@ static void gen_global_var(CodeGen *g, VariableTableEntry *var, LLVMValueRef ini | ... | @@ -2133,8 +2170,7 @@ static void gen_global_var(CodeGen *g, VariableTableEntry *var, LLVMValueRef ini |
| 2133 | assert(var->import); | 2170 | assert(var->import); |
| 2134 | assert(type_entry); | 2171 | assert(type_entry); |
| 2135 | bool is_local_to_unit = true; | 2172 | bool is_local_to_unit = true; |
| 2136 | ZigLLVMCreateGlobalVariable(g->dbuilder, | 2173 | ZigLLVMCreateGlobalVariable(g->dbuilder, get_di_scope(g, var->parent_scope), buf_ptr(&var->name), |
| 2137 | var->scope->di_scope, buf_ptr(&var->name), | ||
| 2138 | buf_ptr(&var->name), var->import->di_file, var->decl_node->line + 1, | 2174 | buf_ptr(&var->name), var->import->di_file, var->decl_node->line + 1, |
| 2139 | type_entry->di_type, is_local_to_unit, init_val); | 2175 | type_entry->di_type, is_local_to_unit, init_val); |
| 2140 | } | 2176 | } |
| ... | @@ -2328,24 +2364,6 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -2328,24 +2364,6 @@ static void do_code_gen(CodeGen *g) { |
| 2328 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; | 2364 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; |
| 2329 | 2365 | ||
| 2330 | build_all_basic_blocks(g, fn_table_entry); | 2366 | build_all_basic_blocks(g, fn_table_entry); |
| 2331 | |||
| 2332 | |||
| 2333 | // Set up debug info for blocks | ||
| 2334 | for (size_t bc_i = 0; bc_i < fn_table_entry->all_block_contexts.length; bc_i += 1) { | ||
| 2335 | Scope *scope = fn_table_entry->all_block_contexts.at(bc_i); | ||
| 2336 | |||
| 2337 | if (!scope->di_scope) { | ||
| 2338 | ZigLLVMDILexicalBlock *di_block = ZigLLVMCreateLexicalBlock(g->dbuilder, | ||
| 2339 | scope->parent->di_scope, | ||
| 2340 | import->di_file, | ||
| 2341 | scope->node->line + 1, | ||
| 2342 | scope->node->column + 1); | ||
| 2343 | scope->di_scope = ZigLLVMLexicalBlockToScope(di_block); | ||
| 2344 | } | ||
| 2345 | |||
| 2346 | |||
| 2347 | } | ||
| 2348 | |||
| 2349 | clear_debug_source_node(g); | 2367 | clear_debug_source_node(g); |
| 2350 | 2368 | ||
| 2351 | // allocate temporary stack data | 2369 | // allocate temporary stack data |
| ... | @@ -2383,7 +2401,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -2383,7 +2401,7 @@ static void do_code_gen(CodeGen *g) { |
| 2383 | if (var->is_inline) | 2401 | if (var->is_inline) |
| 2384 | continue; | 2402 | continue; |
| 2385 | 2403 | ||
| 2386 | if (var->scope->node->type == NodeTypeFnDef) { | 2404 | if (var->parent_scope->node->type == NodeTypeFnDef) { |
| 2387 | assert(var->gen_arg_index != SIZE_MAX); | 2405 | assert(var->gen_arg_index != SIZE_MAX); |
| 2388 | TypeTableEntry *gen_type; | 2406 | TypeTableEntry *gen_type; |
| 2389 | if (handle_is_ptr(var->type)) { | 2407 | if (handle_is_ptr(var->type)) { |
| ... | @@ -2395,7 +2413,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -2395,7 +2413,7 @@ static void do_code_gen(CodeGen *g) { |
| 2395 | unsigned align_bytes = ZigLLVMGetPrefTypeAlignment(g->target_data_ref, var->type->type_ref); | 2413 | unsigned align_bytes = ZigLLVMGetPrefTypeAlignment(g->target_data_ref, var->type->type_ref); |
| 2396 | LLVMSetAlignment(var->value_ref, align_bytes); | 2414 | LLVMSetAlignment(var->value_ref, align_bytes); |
| 2397 | } | 2415 | } |
| 2398 | var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, var->scope->di_scope, | 2416 | var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), |
| 2399 | buf_ptr(&var->name), import->di_file, var->decl_node->line + 1, | 2417 | buf_ptr(&var->name), import->di_file, var->decl_node->line + 1, |
| 2400 | gen_type->di_type, !g->strip_debug_symbols, 0, var->gen_arg_index + 1); | 2418 | gen_type->di_type, !g->strip_debug_symbols, 0, var->gen_arg_index + 1); |
| 2401 | 2419 | ||
| ... | @@ -2406,7 +2424,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -2406,7 +2424,7 @@ static void do_code_gen(CodeGen *g) { |
| 2406 | unsigned align_bytes = ZigLLVMGetPrefTypeAlignment(g->target_data_ref, var->type->type_ref); | 2424 | unsigned align_bytes = ZigLLVMGetPrefTypeAlignment(g->target_data_ref, var->type->type_ref); |
| 2407 | LLVMSetAlignment(var->value_ref, align_bytes); | 2425 | LLVMSetAlignment(var->value_ref, align_bytes); |
| 2408 | 2426 | ||
| 2409 | var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, var->scope->di_scope, | 2427 | var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), |
| 2410 | buf_ptr(&var->name), import->di_file, var->decl_node->line + 1, | 2428 | buf_ptr(&var->name), import->di_file, var->decl_node->line + 1, |
| 2411 | var->type->di_type, !g->strip_debug_symbols, 0); | 2429 | var->type->di_type, !g->strip_debug_symbols, 0); |
| 2412 | } | 2430 | } |
src/hash_map.hpp+9| ... | @@ -61,6 +61,15 @@ public: | ... | @@ -61,6 +61,15 @@ public: |
| 61 | } | 61 | } |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | Entry *put_unique(const K &key, const V &value) { | ||
| 65 | // TODO make this more efficient | ||
| 66 | Entry *entry = internal_get(key); | ||
| 67 | if (entry) | ||
| 68 | return entry; | ||
| 69 | put(key, value); | ||
| 70 | return nullptr; | ||
| 71 | } | ||
| 72 | |||
| 64 | const V &get(const K &key) const { | 73 | const V &get(const K &key) const { |
| 65 | Entry *entry = internal_get(key); | 74 | Entry *entry = internal_get(key); |
| 66 | if (!entry) | 75 | if (!entry) |
src/ir.cpp+108-65| ... | @@ -1211,28 +1211,39 @@ static IrInstruction *ir_build_ref_from(IrBuilder *irb, IrInstruction *old_instr | ... | @@ -1211,28 +1211,39 @@ static IrInstruction *ir_build_ref_from(IrBuilder *irb, IrInstruction *old_instr |
| 1211 | return new_instruction; | 1211 | return new_instruction; |
| 1212 | } | 1212 | } |
| 1213 | 1213 | ||
| 1214 | static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_block, Scope *outer_block, | 1214 | static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, |
| 1215 | bool gen_error_defers, bool gen_maybe_defers) | 1215 | bool gen_error_defers, bool gen_maybe_defers) |
| 1216 | { | 1216 | { |
| 1217 | while (inner_block != outer_block) { | 1217 | while (inner_scope != outer_scope) { |
| 1218 | if (inner_block->node->type == NodeTypeDefer && | 1218 | if (inner_scope->node->type == NodeTypeDefer && |
| 1219 | ((inner_block->node->data.defer.kind == ReturnKindUnconditional) || | 1219 | ((inner_scope->node->data.defer.kind == ReturnKindUnconditional) || |
| 1220 | (gen_error_defers && inner_block->node->data.defer.kind == ReturnKindError) || | 1220 | (gen_error_defers && inner_scope->node->data.defer.kind == ReturnKindError) || |
| 1221 | (gen_maybe_defers && inner_block->node->data.defer.kind == ReturnKindMaybe))) | 1221 | (gen_maybe_defers && inner_scope->node->data.defer.kind == ReturnKindMaybe))) |
| 1222 | { | 1222 | { |
| 1223 | AstNode *defer_expr_node = inner_block->node->data.defer.expr; | 1223 | AstNode *defer_expr_node = inner_scope->node->data.defer.expr; |
| 1224 | ir_gen_node(irb, defer_expr_node, defer_expr_node->scope); | 1224 | ir_gen_node(irb, defer_expr_node, defer_expr_node->scope); |
| 1225 | } | 1225 | } |
| 1226 | inner_block = inner_block->parent; | 1226 | inner_scope = inner_scope->parent; |
| 1227 | } | 1227 | } |
| 1228 | } | 1228 | } |
| 1229 | 1229 | ||
| 1230 | static FnTableEntry *scope_fn_entry(Scope *scope) { | ||
| 1231 | while (scope) { | ||
| 1232 | if (scope->node->type == NodeTypeFnDef) { | ||
| 1233 | ScopeFnBody *fn_scope = (ScopeFnBody *)scope; | ||
| 1234 | return fn_scope->fn_entry; | ||
| 1235 | } | ||
| 1236 | scope = scope->parent; | ||
| 1237 | } | ||
| 1238 | return nullptr; | ||
| 1239 | } | ||
| 1240 | |||
| 1230 | static IrInstruction *ir_gen_return(IrBuilder *irb, AstNode *node) { | 1241 | static IrInstruction *ir_gen_return(IrBuilder *irb, AstNode *node) { |
| 1231 | assert(node->type == NodeTypeReturnExpr); | 1242 | assert(node->type == NodeTypeReturnExpr); |
| 1232 | 1243 | ||
| 1233 | Scope *scope = node->scope; | 1244 | Scope *scope = node->scope; |
| 1234 | 1245 | ||
| 1235 | if (!scope->fn_entry) { | 1246 | if (!scope_fn_entry(scope)) { |
| 1236 | add_node_error(irb->codegen, node, buf_sprintf("return expression outside function definition")); | 1247 | add_node_error(irb->codegen, node, buf_sprintf("return expression outside function definition")); |
| 1237 | return irb->codegen->invalid_instruction; | 1248 | return irb->codegen->invalid_instruction; |
| 1238 | } | 1249 | } |
| ... | @@ -1243,7 +1254,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, AstNode *node) { | ... | @@ -1243,7 +1254,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, AstNode *node) { |
| 1243 | { | 1254 | { |
| 1244 | IrInstruction *return_value; | 1255 | IrInstruction *return_value; |
| 1245 | if (expr_node) { | 1256 | if (expr_node) { |
| 1246 | return_value = ir_gen_node(irb, expr_node, scope); | 1257 | return_value = ir_gen_node(irb, expr_node, node->scope); |
| 1247 | } else { | 1258 | } else { |
| 1248 | return_value = ir_build_const_void(irb, node); | 1259 | return_value = ir_build_const_void(irb, node); |
| 1249 | } | 1260 | } |
| ... | @@ -1264,11 +1275,11 @@ static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) { | ... | @@ -1264,11 +1275,11 @@ static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) { |
| 1264 | irb->current_basic_block = basic_block; | 1275 | irb->current_basic_block = basic_block; |
| 1265 | } | 1276 | } |
| 1266 | 1277 | ||
| 1267 | static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, Scope *scope, | 1278 | static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, Scope *parent_scope, |
| 1268 | Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, bool is_inline) | 1279 | Buf *name, bool src_is_const, bool gen_is_const, bool is_shadowable, bool is_inline) |
| 1269 | { | 1280 | { |
| 1270 | VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1); | 1281 | VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1); |
| 1271 | variable_entry->scope = scope; | 1282 | variable_entry->parent_scope = parent_scope; |
| 1272 | variable_entry->import = node->owner; | 1283 | variable_entry->import = node->owner; |
| 1273 | variable_entry->shadowable = is_shadowable; | 1284 | variable_entry->shadowable = is_shadowable; |
| 1274 | variable_entry->mem_slot_index = SIZE_MAX; | 1285 | variable_entry->mem_slot_index = SIZE_MAX; |
| ... | @@ -1277,7 +1288,7 @@ static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, Scope | ... | @@ -1277,7 +1288,7 @@ static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, Scope |
| 1277 | if (name) { | 1288 | if (name) { |
| 1278 | buf_init_from_buf(&variable_entry->name, name); | 1289 | buf_init_from_buf(&variable_entry->name, name); |
| 1279 | 1290 | ||
| 1280 | VariableTableEntry *existing_var = find_variable(codegen, scope, name); | 1291 | VariableTableEntry *existing_var = find_variable(codegen, parent_scope, name); |
| 1281 | if (existing_var && !existing_var->shadowable) { | 1292 | if (existing_var && !existing_var->shadowable) { |
| 1282 | ErrorMsg *msg = add_node_error(codegen, node, | 1293 | ErrorMsg *msg = add_node_error(codegen, node, |
| 1283 | buf_sprintf("redeclaration of variable '%s'", buf_ptr(name))); | 1294 | buf_sprintf("redeclaration of variable '%s'", buf_ptr(name))); |
| ... | @@ -1291,7 +1302,7 @@ static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, Scope | ... | @@ -1291,7 +1302,7 @@ static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, Scope |
| 1291 | buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name))); | 1302 | buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name))); |
| 1292 | variable_entry->type = codegen->builtin_types.entry_invalid; | 1303 | variable_entry->type = codegen->builtin_types.entry_invalid; |
| 1293 | } else { | 1304 | } else { |
| 1294 | AstNode *decl_node = find_decl(scope, name); | 1305 | AstNode *decl_node = find_decl(parent_scope, name); |
| 1295 | if (decl_node && decl_node->type != NodeTypeVariableDeclaration) { | 1306 | if (decl_node && decl_node->type != NodeTypeVariableDeclaration) { |
| 1296 | ErrorMsg *msg = add_node_error(codegen, node, | 1307 | ErrorMsg *msg = add_node_error(codegen, node, |
| 1297 | buf_sprintf("redefinition of '%s'", buf_ptr(name))); | 1308 | buf_sprintf("redefinition of '%s'", buf_ptr(name))); |
| ... | @@ -1301,28 +1312,32 @@ static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, Scope | ... | @@ -1301,28 +1312,32 @@ static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, Scope |
| 1301 | } | 1312 | } |
| 1302 | } | 1313 | } |
| 1303 | 1314 | ||
| 1304 | scope->var_table.put(&variable_entry->name, variable_entry); | ||
| 1305 | } else { | 1315 | } else { |
| 1306 | assert(is_shadowable); | 1316 | assert(is_shadowable); |
| 1307 | // TODO replace _anon with @anon and make sure all tests still pass | 1317 | // TODO make this name not actually be in scope. user should be able to make a variable called "_anon" |
| 1318 | // might already be solved, let's just make sure it has test coverage | ||
| 1319 | // maybe we put a prefix on this so the debug info doesn't clobber user debug info for same named variables | ||
| 1308 | buf_init_from_str(&variable_entry->name, "_anon"); | 1320 | buf_init_from_str(&variable_entry->name, "_anon"); |
| 1309 | } | 1321 | } |
| 1310 | 1322 | ||
| 1311 | variable_entry->src_is_const = src_is_const; | 1323 | variable_entry->src_is_const = src_is_const; |
| 1312 | variable_entry->gen_is_const = gen_is_const; | 1324 | variable_entry->gen_is_const = gen_is_const; |
| 1313 | variable_entry->decl_node = node; | 1325 | variable_entry->decl_node = node; |
| 1326 | variable_entry->child_scope = create_var_scope(node, parent_scope, variable_entry); | ||
| 1314 | 1327 | ||
| 1315 | return variable_entry; | 1328 | return variable_entry; |
| 1316 | } | 1329 | } |
| 1317 | 1330 | ||
| 1318 | // Set name to nullptr to make the variable anonymous (not visible to programmer). | 1331 | // Set name to nullptr to make the variable anonymous (not visible to programmer). |
| 1319 | static VariableTableEntry *ir_add_local_var(IrBuilder *irb, AstNode *node, Scope *scope, Buf *name, | 1332 | // After you call this function var->child_scope has the variable in scope |
| 1333 | static VariableTableEntry *ir_create_var(IrBuilder *irb, AstNode *node, Scope *scope, Buf *name, | ||
| 1320 | bool src_is_const, bool gen_is_const, bool is_shadowable, bool is_inline) | 1334 | bool src_is_const, bool gen_is_const, bool is_shadowable, bool is_inline) |
| 1321 | { | 1335 | { |
| 1322 | VariableTableEntry *var = add_local_var(irb->codegen, node, scope, name, | 1336 | VariableTableEntry *var = add_local_var(irb->codegen, node, scope, name, |
| 1323 | src_is_const, gen_is_const, is_shadowable, is_inline); | 1337 | src_is_const, gen_is_const, is_shadowable, is_inline); |
| 1324 | if (is_inline || gen_is_const) | 1338 | if (is_inline || gen_is_const) |
| 1325 | var->mem_slot_index = exec_next_mem_slot(irb->exec); | 1339 | var->mem_slot_index = exec_next_mem_slot(irb->exec); |
| 1340 | assert(var->child_scope); | ||
| 1326 | return var; | 1341 | return var; |
| 1327 | } | 1342 | } |
| 1328 | 1343 | ||
| ... | @@ -1330,7 +1345,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, AstNode *block_node) { | ... | @@ -1330,7 +1345,7 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, AstNode *block_node) { |
| 1330 | assert(block_node->type == NodeTypeBlock); | 1345 | assert(block_node->type == NodeTypeBlock); |
| 1331 | 1346 | ||
| 1332 | Scope *parent_scope = block_node->scope; | 1347 | Scope *parent_scope = block_node->scope; |
| 1333 | Scope *outer_block_scope = new_scope(block_node, parent_scope); | 1348 | Scope *outer_block_scope = create_block_scope(block_node, parent_scope); |
| 1334 | Scope *child_scope = outer_block_scope; | 1349 | Scope *child_scope = outer_block_scope; |
| 1335 | 1350 | ||
| 1336 | IrInstruction *return_value = nullptr; | 1351 | IrInstruction *return_value = nullptr; |
| ... | @@ -1341,6 +1356,9 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, AstNode *block_node) { | ... | @@ -1341,6 +1356,9 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, AstNode *block_node) { |
| 1341 | // defer starts a new block context | 1356 | // defer starts a new block context |
| 1342 | child_scope = statement_node->data.defer.child_block; | 1357 | child_scope = statement_node->data.defer.child_block; |
| 1343 | assert(child_scope); | 1358 | assert(child_scope); |
| 1359 | } else if (return_value->id == IrInstructionIdDeclVar) { | ||
| 1360 | IrInstructionDeclVar *decl_var_instruction = (IrInstructionDeclVar *)return_value; | ||
| 1361 | child_scope = decl_var_instruction->var->child_scope; | ||
| 1344 | } | 1362 | } |
| 1345 | } | 1363 | } |
| 1346 | 1364 | ||
| ... | @@ -1760,7 +1778,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { | ... | @@ -1760,7 +1778,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { |
| 1760 | if (arg0_value == irb->codegen->invalid_instruction) | 1778 | if (arg0_value == irb->codegen->invalid_instruction) |
| 1761 | return arg0_value; | 1779 | return arg0_value; |
| 1762 | 1780 | ||
| 1763 | if (node->scope->fn_entry) { | 1781 | if (scope_fn_entry(node->scope)) { |
| 1764 | add_node_error(irb->codegen, node, buf_sprintf("import valid only at top level scope")); | 1782 | add_node_error(irb->codegen, node, buf_sprintf("import valid only at top level scope")); |
| 1765 | return irb->codegen->invalid_instruction; | 1783 | return irb->codegen->invalid_instruction; |
| 1766 | } | 1784 | } |
| ... | @@ -1999,8 +2017,10 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, AstNode *node) { | ... | @@ -1999,8 +2017,10 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, AstNode *node) { |
| 1999 | bool is_const = variable_declaration->is_const; | 2017 | bool is_const = variable_declaration->is_const; |
| 2000 | bool is_extern = variable_declaration->is_extern; | 2018 | bool is_extern = variable_declaration->is_extern; |
| 2001 | bool is_inline = ir_should_inline(irb) || variable_declaration->is_inline; | 2019 | bool is_inline = ir_should_inline(irb) || variable_declaration->is_inline; |
| 2002 | VariableTableEntry *var = ir_add_local_var(irb, node, node->scope, | 2020 | VariableTableEntry *var = ir_create_var(irb, node, node->scope, |
| 2003 | variable_declaration->symbol, is_const, is_const, is_shadowable, is_inline); | 2021 | variable_declaration->symbol, is_const, is_const, is_shadowable, is_inline); |
| 2022 | // we detect IrInstructionIdDeclVar in gen_block to make sure the next node | ||
| 2023 | // is inside var->child_scope | ||
| 2004 | 2024 | ||
| 2005 | if (!is_extern && !variable_declaration->expr) { | 2025 | if (!is_extern && !variable_declaration->expr) { |
| 2006 | var->type = irb->codegen->builtin_types.entry_invalid; | 2026 | var->type = irb->codegen->builtin_types.entry_invalid; |
| ... | @@ -2079,14 +2099,15 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, AstNode *node) { | ... | @@ -2079,14 +2099,15 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, AstNode *node) { |
| 2079 | } | 2099 | } |
| 2080 | bool is_inline = ir_should_inline(irb) || node->data.for_expr.is_inline; | 2100 | bool is_inline = ir_should_inline(irb) || node->data.for_expr.is_inline; |
| 2081 | 2101 | ||
| 2082 | Scope *child_scope = new_scope(node, parent_scope); | 2102 | Scope *child_scope = create_loop_scope(node, parent_scope); |
| 2083 | child_scope->parent_loop_node = node; | ||
| 2084 | elem_node->scope = child_scope; | 2103 | elem_node->scope = child_scope; |
| 2085 | 2104 | ||
| 2086 | // TODO make it an error to write to element variable or i variable. | 2105 | // TODO make it an error to write to element variable or i variable. |
| 2087 | Buf *elem_var_name = elem_node->data.symbol_expr.symbol; | 2106 | Buf *elem_var_name = elem_node->data.symbol_expr.symbol; |
| 2088 | node->data.for_expr.elem_var = ir_add_local_var(irb, elem_node, child_scope, elem_var_name, | 2107 | node->data.for_expr.elem_var = ir_create_var(irb, elem_node, child_scope, elem_var_name, |
| 2089 | true, false, false, is_inline); | 2108 | true, false, false, is_inline); |
| 2109 | child_scope = node->data.for_expr.elem_var->child_scope; | ||
| 2110 | |||
| 2090 | IrInstruction *undefined_value = ir_build_const_undefined(irb, elem_node); | 2111 | IrInstruction *undefined_value = ir_build_const_undefined(irb, elem_node); |
| 2091 | ir_build_var_decl(irb, elem_node, node->data.for_expr.elem_var, elem_var_type, undefined_value); | 2112 | ir_build_var_decl(irb, elem_node, node->data.for_expr.elem_var, elem_var_type, undefined_value); |
| 2092 | IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, node, node->data.for_expr.elem_var); | 2113 | IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, node, node->data.for_expr.elem_var); |
| ... | @@ -2096,13 +2117,15 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, AstNode *node) { | ... | @@ -2096,13 +2117,15 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, AstNode *node) { |
| 2096 | index_var_source_node = index_node; | 2117 | index_var_source_node = index_node; |
| 2097 | Buf *index_var_name = index_node->data.symbol_expr.symbol; | 2118 | Buf *index_var_name = index_node->data.symbol_expr.symbol; |
| 2098 | index_node->scope = child_scope; | 2119 | index_node->scope = child_scope; |
| 2099 | node->data.for_expr.index_var = ir_add_local_var(irb, index_node, child_scope, index_var_name, | 2120 | node->data.for_expr.index_var = ir_create_var(irb, index_node, child_scope, index_var_name, |
| 2100 | true, false, false, is_inline); | 2121 | true, false, false, is_inline); |
| 2101 | } else { | 2122 | } else { |
| 2102 | index_var_source_node = node; | 2123 | index_var_source_node = node; |
| 2103 | node->data.for_expr.index_var = ir_add_local_var(irb, node, child_scope, nullptr, | 2124 | node->data.for_expr.index_var = ir_create_var(irb, node, child_scope, nullptr, |
| 2104 | true, false, true, is_inline); | 2125 | true, false, true, is_inline); |
| 2105 | } | 2126 | } |
| 2127 | child_scope = node->data.for_expr.index_var->child_scope; | ||
| 2128 | |||
| 2106 | IrInstruction *usize = ir_build_const_type(irb, node, irb->codegen->builtin_types.entry_usize); | 2129 | IrInstruction *usize = ir_build_const_type(irb, node, irb->codegen->builtin_types.entry_usize); |
| 2107 | IrInstruction *zero = ir_build_const_usize(irb, node, 0); | 2130 | IrInstruction *zero = ir_build_const_usize(irb, node, 0); |
| 2108 | IrInstruction *one = ir_build_const_usize(irb, node, 1); | 2131 | IrInstruction *one = ir_build_const_usize(irb, node, 1); |
| ... | @@ -2159,10 +2182,11 @@ static IrInstruction *ir_gen_this_literal(IrBuilder *irb, AstNode *node) { | ... | @@ -2159,10 +2182,11 @@ static IrInstruction *ir_gen_this_literal(IrBuilder *irb, AstNode *node) { |
| 2159 | if (!scope->parent) | 2182 | if (!scope->parent) |
| 2160 | return ir_build_const_import(irb, node, node->owner); | 2183 | return ir_build_const_import(irb, node, node->owner); |
| 2161 | 2184 | ||
| 2162 | if (scope->fn_entry && (!scope->parent->fn_entry || | 2185 | FnTableEntry *fn_entry = scope_fn_entry(scope); |
| 2163 | (scope->parent->parent && !scope->parent->parent->fn_entry))) | 2186 | if (fn_entry && scope->parent && scope->parent->parent && |
| 2187 | !scope_fn_entry(scope->parent->parent)) | ||
| 2164 | { | 2188 | { |
| 2165 | return ir_build_const_fn(irb, node, scope->fn_entry); | 2189 | return ir_build_const_fn(irb, node, fn_entry); |
| 2166 | } | 2190 | } |
| 2167 | 2191 | ||
| 2168 | if (scope->node->type == NodeTypeContainerDecl) { | 2192 | if (scope->node->type == NodeTypeContainerDecl) { |
| ... | @@ -2308,15 +2332,15 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, AstNode *node) { | ... | @@ -2308,15 +2332,15 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, AstNode *node) { |
| 2308 | if (var_type == irb->codegen->invalid_instruction) | 2332 | if (var_type == irb->codegen->invalid_instruction) |
| 2309 | return irb->codegen->invalid_instruction; | 2333 | return irb->codegen->invalid_instruction; |
| 2310 | } | 2334 | } |
| 2311 | Scope *child_scope = new_scope(node, node->scope); | ||
| 2312 | bool is_shadowable = false; | 2335 | bool is_shadowable = false; |
| 2313 | bool is_const = var_decl->is_const; | 2336 | bool is_const = var_decl->is_const; |
| 2314 | VariableTableEntry *var = ir_add_local_var(irb, node, child_scope, | 2337 | VariableTableEntry *var = ir_create_var(irb, node, node->scope, |
| 2315 | var_decl->symbol, is_const, is_const, is_shadowable, is_inline); | 2338 | var_decl->symbol, is_const, is_const, is_shadowable, is_inline); |
| 2339 | |||
| 2316 | IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, node, expr_value, false); | 2340 | IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, node, expr_value, false); |
| 2317 | IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, node, var_ptr_value); | 2341 | IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, node, var_ptr_value); |
| 2318 | ir_build_var_decl(irb, node, var, var_type, var_value); | 2342 | ir_build_var_decl(irb, node, var, var_type, var_value); |
| 2319 | IrInstruction *then_expr_result = ir_gen_node(irb, then_node, child_scope); | 2343 | IrInstruction *then_expr_result = ir_gen_node(irb, then_node, var->child_scope); |
| 2320 | if (then_expr_result == irb->codegen->invalid_instruction) | 2344 | if (then_expr_result == irb->codegen->invalid_instruction) |
| 2321 | return then_expr_result; | 2345 | return then_expr_result; |
| 2322 | IrBasicBlock *after_then_block = irb->current_basic_block; | 2346 | IrBasicBlock *after_then_block = irb->current_basic_block; |
| ... | @@ -2360,11 +2384,11 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, AstNode *switch_node, AstNo | ... | @@ -2360,11 +2384,11 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, AstNode *switch_node, AstNo |
| 2360 | Buf *var_name = var_symbol_node->data.symbol_expr.symbol; | 2384 | Buf *var_name = var_symbol_node->data.symbol_expr.symbol; |
| 2361 | bool var_is_ptr = prong_node->data.switch_prong.var_is_ptr; | 2385 | bool var_is_ptr = prong_node->data.switch_prong.var_is_ptr; |
| 2362 | 2386 | ||
| 2363 | child_scope = new_scope(switch_node, switch_node->scope); | ||
| 2364 | bool is_shadowable = false; | 2387 | bool is_shadowable = false; |
| 2365 | bool is_const = true; | 2388 | bool is_const = true; |
| 2366 | VariableTableEntry *var = ir_add_local_var(irb, var_symbol_node, child_scope, | 2389 | VariableTableEntry *var = ir_create_var(irb, var_symbol_node, switch_node->scope, |
| 2367 | var_name, is_const, is_const, is_shadowable, is_inline); | 2390 | var_name, is_const, is_const, is_shadowable, is_inline); |
| 2391 | child_scope = var->child_scope; | ||
| 2368 | IrInstruction *var_value; | 2392 | IrInstruction *var_value; |
| 2369 | if (prong_value) { | 2393 | if (prong_value) { |
| 2370 | IrInstruction *var_ptr_value = ir_build_switch_var(irb, var_symbol_node, target_value_ptr, prong_value); | 2394 | IrInstruction *var_ptr_value = ir_build_switch_var(irb, var_symbol_node, target_value_ptr, prong_value); |
| ... | @@ -2542,14 +2566,25 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) { | ... | @@ -2542,14 +2566,25 @@ static IrInstruction *ir_gen_switch_expr(IrBuilder *irb, AstNode *node) { |
| 2542 | return ir_build_phi(irb, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items); | 2566 | return ir_build_phi(irb, node, incoming_blocks.length, incoming_blocks.items, incoming_values.items); |
| 2543 | } | 2567 | } |
| 2544 | 2568 | ||
| 2545 | static LabelTableEntry *find_label(IrExecutable *exec, Scope *orig_context, Buf *name) { | 2569 | static LabelTableEntry *find_label(IrExecutable *exec, Scope *scope, Buf *name) { |
| 2546 | Scope *context = orig_context; | 2570 | while (scope) { |
| 2547 | while (context) { | 2571 | if (scope->node->type == NodeTypeBlock) { |
| 2548 | auto entry = context->label_table.maybe_get(name); | 2572 | ScopeBlock *block_scope = (ScopeBlock *)scope; |
| 2549 | if (entry) { | 2573 | auto entry = block_scope->label_table.maybe_get(name); |
| 2550 | return entry->value; | 2574 | if (entry) |
| 2575 | return entry->value; | ||
| 2551 | } | 2576 | } |
| 2552 | context = context->parent; | 2577 | scope = scope->parent; |
| 2578 | } | ||
| 2579 | |||
| 2580 | return nullptr; | ||
| 2581 | } | ||
| 2582 | |||
| 2583 | static ScopeBlock *find_block_scope(IrExecutable *exec, Scope *scope) { | ||
| 2584 | while (scope) { | ||
| 2585 | if (scope->node->type == NodeTypeBlock) | ||
| 2586 | return (ScopeBlock *)scope; | ||
| 2587 | scope = scope->parent; | ||
| 2553 | } | 2588 | } |
| 2554 | return nullptr; | 2589 | return nullptr; |
| 2555 | } | 2590 | } |
| ... | @@ -2571,7 +2606,8 @@ static IrInstruction *ir_gen_label(IrBuilder *irb, AstNode *node) { | ... | @@ -2571,7 +2606,8 @@ static IrInstruction *ir_gen_label(IrBuilder *irb, AstNode *node) { |
| 2571 | add_error_note(irb->codegen, msg, existing_label->decl_node, buf_sprintf("other label here")); | 2606 | add_error_note(irb->codegen, msg, existing_label->decl_node, buf_sprintf("other label here")); |
| 2572 | return irb->codegen->invalid_instruction; | 2607 | return irb->codegen->invalid_instruction; |
| 2573 | } else { | 2608 | } else { |
| 2574 | node->scope->label_table.put(label_name, label); | 2609 | ScopeBlock *scope_block = find_block_scope(irb->exec, node->scope); |
| 2610 | scope_block->label_table.put(label_name, label); | ||
| 2575 | } | 2611 | } |
| 2576 | 2612 | ||
| 2577 | bool is_inline = ir_should_inline(irb); | 2613 | bool is_inline = ir_should_inline(irb); |
| ... | @@ -2778,9 +2814,9 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) { | ... | @@ -2778,9 +2814,9 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) { |
| 2778 | assert(fn_def_node->type == NodeTypeFnDef); | 2814 | assert(fn_def_node->type == NodeTypeFnDef); |
| 2779 | 2815 | ||
| 2780 | AstNode *body_node = fn_def_node->data.fn_def.body; | 2816 | AstNode *body_node = fn_def_node->data.fn_def.body; |
| 2781 | Scope *scope = fn_def_node->data.fn_def.scope; | 2817 | Scope *child_scope = fn_def_node->data.fn_def.child_scope; |
| 2782 | 2818 | ||
| 2783 | return ir_gen(codegn, body_node, scope, ir_executable); | 2819 | return ir_gen(codegn, body_node, child_scope, ir_executable); |
| 2784 | } | 2820 | } |
| 2785 | 2821 | ||
| 2786 | static IrInstruction *ir_eval_fn(IrAnalyze *ira, IrInstruction *source_instruction, | 2822 | static IrInstruction *ir_eval_fn(IrAnalyze *ira, IrInstruction *source_instruction, |
| ... | @@ -3023,8 +3059,10 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -3023,8 +3059,10 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 3023 | } else { | 3059 | } else { |
| 3024 | IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->source_node, wanted_type, value, cast_op); | 3060 | IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->source_node, wanted_type, value, cast_op); |
| 3025 | result->type_entry = wanted_type; | 3061 | result->type_entry = wanted_type; |
| 3026 | if (need_alloca && source_instr->source_node->scope->fn_entry) { | 3062 | if (need_alloca) { |
| 3027 | source_instr->source_node->scope->fn_entry->alloca_list.append(result); | 3063 | FnTableEntry *fn_entry = scope_fn_entry(source_instr->source_node->scope); |
| 3064 | if (fn_entry) | ||
| 3065 | fn_entry->alloca_list.append(result); | ||
| 3028 | } | 3066 | } |
| 3029 | return result; | 3067 | return result; |
| 3030 | } | 3068 | } |
| ... | @@ -3550,7 +3588,8 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -3550,7 +3588,8 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst |
| 3550 | ir_link_new_instruction(value, source_instruction); | 3588 | ir_link_new_instruction(value, source_instruction); |
| 3551 | return ptr_type; | 3589 | return ptr_type; |
| 3552 | } else { | 3590 | } else { |
| 3553 | FnTableEntry *fn_entry = source_instruction->source_node->scope->fn_entry; | 3591 | FnTableEntry *fn_entry = scope_fn_entry(source_instruction->source_node->scope); |
| 3592 | assert(fn_entry); | ||
| 3554 | IrInstruction *new_instruction = ir_build_ref_from(&ira->new_irb, source_instruction, value); | 3593 | IrInstruction *new_instruction = ir_build_ref_from(&ira->new_irb, source_instruction, value); |
| 3555 | fn_entry->alloca_list.append(new_instruction); | 3594 | fn_entry->alloca_list.append(new_instruction); |
| 3556 | return ptr_type; | 3595 | return ptr_type; |
| ... | @@ -4098,8 +4137,9 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc | ... | @@ -4098,8 +4137,9 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 4098 | ir_build_var_decl_from(&ira->new_irb, &decl_var_instruction->base, var, var_type, casted_init_value); | 4137 | ir_build_var_decl_from(&ira->new_irb, &decl_var_instruction->base, var, var_type, casted_init_value); |
| 4099 | 4138 | ||
| 4100 | Scope *scope = decl_var_instruction->base.source_node->scope; | 4139 | Scope *scope = decl_var_instruction->base.source_node->scope; |
| 4101 | if (scope->fn_entry) | 4140 | FnTableEntry *fn_entry = scope_fn_entry(scope); |
| 4102 | scope->fn_entry->variable_list.append(var); | 4141 | if (fn_entry) |
| 4142 | fn_entry->variable_list.append(var); | ||
| 4103 | 4143 | ||
| 4104 | return ira->codegen->builtin_types.entry_void; | 4144 | return ira->codegen->builtin_types.entry_void; |
| 4105 | } | 4145 | } |
| ... | @@ -4200,8 +4240,11 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -4200,8 +4240,11 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 4200 | IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base, | 4240 | IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base, |
| 4201 | fn_entry, fn_ref, call_param_count, casted_args); | 4241 | fn_entry, fn_ref, call_param_count, casted_args); |
| 4202 | 4242 | ||
| 4203 | if (type_has_bits(return_type) && handle_is_ptr(return_type)) | 4243 | if (type_has_bits(return_type) && handle_is_ptr(return_type)) { |
| 4204 | call_instruction->base.source_node->scope->fn_entry->alloca_list.append(new_call_instruction); | 4244 | FnTableEntry *fn_entry = scope_fn_entry(call_instruction->base.source_node->scope); |
| 4245 | assert(fn_entry); | ||
| 4246 | fn_entry->alloca_list.append(new_call_instruction); | ||
| 4247 | } | ||
| 4205 | 4248 | ||
| 4206 | return ir_finish_anal(ira, return_type); | 4249 | return ir_finish_anal(ira, return_type); |
| 4207 | } | 4250 | } |
| ... | @@ -4732,7 +4775,8 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc | ... | @@ -4732,7 +4775,8 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc |
| 4732 | return var->type; | 4775 | return var->type; |
| 4733 | 4776 | ||
| 4734 | ConstExprValue *mem_slot = nullptr; | 4777 | ConstExprValue *mem_slot = nullptr; |
| 4735 | if (var->scope->fn_entry) { | 4778 | FnTableEntry *fn_entry = scope_fn_entry(var->parent_scope); |
| 4779 | if (fn_entry) { | ||
| 4736 | // TODO once the analyze code is fully ported over to IR we won't need this SIZE_MAX thing. | 4780 | // TODO once the analyze code is fully ported over to IR we won't need this SIZE_MAX thing. |
| 4737 | if (var->mem_slot_index != SIZE_MAX) | 4781 | if (var->mem_slot_index != SIZE_MAX) |
| 4738 | mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; | 4782 | mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; |
| ... | @@ -4879,9 +4923,8 @@ static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira, | ... | @@ -4879,9 +4923,8 @@ static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira, |
| 4879 | IrInstruction *container_ptr, TypeTableEntry *container_type) | 4923 | IrInstruction *container_ptr, TypeTableEntry *container_type) |
| 4880 | { | 4924 | { |
| 4881 | if (!is_slice(bare_struct_type)) { | 4925 | if (!is_slice(bare_struct_type)) { |
| 4882 | Scope *container_block_context = get_container_block_context(bare_struct_type); | 4926 | ScopeDecls *container_scope = get_container_scope(bare_struct_type); |
| 4883 | assert(container_block_context); | 4927 | auto entry = container_scope->decl_table.maybe_get(field_name); |
| 4884 | auto entry = container_block_context->decl_table.maybe_get(field_name); | ||
| 4885 | AstNode *fn_decl_node = entry ? entry->value : nullptr; | 4928 | AstNode *fn_decl_node = entry ? entry->value : nullptr; |
| 4886 | if (fn_decl_node && fn_decl_node->type == NodeTypeFnProto) { | 4929 | if (fn_decl_node && fn_decl_node->type == NodeTypeFnProto) { |
| 4887 | resolve_top_level_decl(ira->codegen, fn_decl_node, false); | 4930 | resolve_top_level_decl(ira->codegen, fn_decl_node, false); |
| ... | @@ -5023,8 +5066,8 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -5023,8 +5066,8 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 5023 | } else if (child_type->id == TypeTableEntryIdEnum) { | 5066 | } else if (child_type->id == TypeTableEntryIdEnum) { |
| 5024 | zig_panic("TODO enum type field"); | 5067 | zig_panic("TODO enum type field"); |
| 5025 | } else if (child_type->id == TypeTableEntryIdStruct) { | 5068 | } else if (child_type->id == TypeTableEntryIdStruct) { |
| 5026 | Scope *container_block_context = get_container_block_context(child_type); | 5069 | ScopeDecls *container_scope = get_container_scope(child_type); |
| 5027 | auto entry = container_block_context->decl_table.maybe_get(field_name); | 5070 | auto entry = container_scope->decl_table.maybe_get(field_name); |
| 5028 | AstNode *decl_node = entry ? entry->value : nullptr; | 5071 | AstNode *decl_node = entry ? entry->value : nullptr; |
| 5029 | if (decl_node) { | 5072 | if (decl_node) { |
| 5030 | bool depends_on_compile_var = container_ptr->static_value.depends_on_compile_var; | 5073 | bool depends_on_compile_var = container_ptr->static_value.depends_on_compile_var; |
| ... | @@ -5055,7 +5098,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -5055,7 +5098,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 5055 | ImportTableEntry *namespace_import = namespace_val->data.x_import; | 5098 | ImportTableEntry *namespace_import = namespace_val->data.x_import; |
| 5056 | 5099 | ||
| 5057 | bool depends_on_compile_var = container_ptr->static_value.depends_on_compile_var; | 5100 | bool depends_on_compile_var = container_ptr->static_value.depends_on_compile_var; |
| 5058 | AstNode *decl_node = find_decl(namespace_import->scope, field_name); | 5101 | AstNode *decl_node = find_decl(&namespace_import->decls_scope->base, field_name); |
| 5059 | if (!decl_node) { | 5102 | if (!decl_node) { |
| 5060 | // we must now resolve all the use decls | 5103 | // we must now resolve all the use decls |
| 5061 | for (size_t i = 0; i < namespace_import->use_decls.length; i += 1) { | 5104 | for (size_t i = 0; i < namespace_import->use_decls.length; i += 1) { |
| ... | @@ -5066,7 +5109,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -5066,7 +5109,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 5066 | } | 5109 | } |
| 5067 | resolve_use_decl(ira->codegen, use_decl_node); | 5110 | resolve_use_decl(ira->codegen, use_decl_node); |
| 5068 | } | 5111 | } |
| 5069 | decl_node = find_decl(namespace_import->scope, field_name); | 5112 | decl_node = find_decl(&namespace_import->decls_scope->base, field_name); |
| 5070 | } | 5113 | } |
| 5071 | if (decl_node) { | 5114 | if (decl_node) { |
| 5072 | TopLevelDecl *tld = get_as_top_level_decl(decl_node); | 5115 | TopLevelDecl *tld = get_as_top_level_decl(decl_node); |
| ... | @@ -5327,15 +5370,15 @@ static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira, | ... | @@ -5327,15 +5370,15 @@ static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira, |
| 5327 | if (target_type->id == TypeTableEntryIdBlock) { | 5370 | if (target_type->id == TypeTableEntryIdBlock) { |
| 5328 | target_context = target_val->data.x_block; | 5371 | target_context = target_val->data.x_block; |
| 5329 | } else if (target_type->id == TypeTableEntryIdFn) { | 5372 | } else if (target_type->id == TypeTableEntryIdFn) { |
| 5330 | target_context = target_val->data.x_fn->fn_def_node->data.fn_def.scope; | 5373 | target_context = target_val->data.x_fn->fn_def_node->data.fn_def.child_scope; |
| 5331 | } else if (target_type->id == TypeTableEntryIdMetaType) { | 5374 | } else if (target_type->id == TypeTableEntryIdMetaType) { |
| 5332 | TypeTableEntry *type_arg = target_val->data.x_type; | 5375 | TypeTableEntry *type_arg = target_val->data.x_type; |
| 5333 | if (type_arg->id == TypeTableEntryIdStruct) { | 5376 | if (type_arg->id == TypeTableEntryIdStruct) { |
| 5334 | target_context = type_arg->data.structure.scope; | 5377 | target_context = &type_arg->data.structure.decls_scope->base; |
| 5335 | } else if (type_arg->id == TypeTableEntryIdEnum) { | 5378 | } else if (type_arg->id == TypeTableEntryIdEnum) { |
| 5336 | target_context = type_arg->data.enumeration.scope; | 5379 | target_context = &type_arg->data.enumeration.decls_scope->base; |
| 5337 | } else if (type_arg->id == TypeTableEntryIdUnion) { | 5380 | } else if (type_arg->id == TypeTableEntryIdUnion) { |
| 5338 | target_context = type_arg->data.unionation.scope; | 5381 | target_context = &type_arg->data.unionation.decls_scope->base; |
| 5339 | } else { | 5382 | } else { |
| 5340 | add_node_error(ira->codegen, target_instruction->source_node, | 5383 | add_node_error(ira->codegen, target_instruction->source_node, |
| 5341 | buf_sprintf("expected scope reference, found type '%s'", buf_ptr(&type_arg->name))); | 5384 | buf_sprintf("expected scope reference, found type '%s'", buf_ptr(&type_arg->name))); |
| ... | @@ -5966,7 +6009,7 @@ static TypeTableEntry *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructi | ... | @@ -5966,7 +6009,7 @@ static TypeTableEntry *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructi |
| 5966 | ImportTableEntry *target_import = add_source_file(ira->codegen, target_package, | 6009 | ImportTableEntry *target_import = add_source_file(ira->codegen, target_package, |
| 5967 | abs_full_path, search_dir, import_target_path, import_code); | 6010 | abs_full_path, search_dir, import_target_path, import_code); |
| 5968 | 6011 | ||
| 5969 | scan_decls(ira->codegen, target_import, target_import->scope, target_import->root); | 6012 | scan_decls(ira->codegen, target_import, target_import->decls_scope, target_import->root); |
| 5970 | 6013 | ||
| 5971 | ConstExprValue *out_val = ir_build_const_from(ira, &import_instruction->base, depends_on_compile_var); | 6014 | ConstExprValue *out_val = ir_build_const_from(ira, &import_instruction->base, depends_on_compile_var); |
| 5972 | out_val->data.x_import = target_import; | 6015 | out_val->data.x_import = target_import; |
| ... | @@ -6021,7 +6064,7 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru | ... | @@ -6021,7 +6064,7 @@ static TypeTableEntry *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstru |
| 6021 | 6064 | ||
| 6022 | IrInstructionStructInitField *new_fields = allocate<IrInstructionStructInitField>(actual_field_count); | 6065 | IrInstructionStructInitField *new_fields = allocate<IrInstructionStructInitField>(actual_field_count); |
| 6023 | 6066 | ||
| 6024 | FnTableEntry *fn_entry = instruction->source_node->scope->fn_entry; | 6067 | FnTableEntry *fn_entry = scope_fn_entry(instruction->source_node->scope); |
| 6025 | bool outside_fn = (fn_entry == nullptr); | 6068 | bool outside_fn = (fn_entry == nullptr); |
| 6026 | 6069 | ||
| 6027 | ConstExprValue const_val = {}; | 6070 | ConstExprValue const_val = {}; |
| ... | @@ -6124,7 +6167,7 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira | ... | @@ -6124,7 +6167,7 @@ static TypeTableEntry *ir_analyze_instruction_container_init_list(IrAnalyze *ira |
| 6124 | const_val.data.x_array.elements = allocate<ConstExprValue>(elem_count); | 6167 | const_val.data.x_array.elements = allocate<ConstExprValue>(elem_count); |
| 6125 | const_val.data.x_array.size = elem_count; | 6168 | const_val.data.x_array.size = elem_count; |
| 6126 | 6169 | ||
| 6127 | FnTableEntry *fn_entry = instruction->base.source_node->scope->fn_entry; | 6170 | FnTableEntry *fn_entry = scope_fn_entry(instruction->base.source_node->scope); |
| 6128 | bool outside_fn = (fn_entry == nullptr); | 6171 | bool outside_fn = (fn_entry == nullptr); |
| 6129 | 6172 | ||
| 6130 | IrInstruction **new_items = allocate<IrInstruction *>(elem_count); | 6173 | IrInstruction **new_items = allocate<IrInstruction *>(elem_count); |
src/parseh.cpp+3-3| ... | @@ -817,7 +817,7 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) | ... | @@ -817,7 +817,7 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) |
| 817 | const EnumDecl *enum_def = enum_decl->getDefinition(); | 817 | const EnumDecl *enum_def = enum_decl->getDefinition(); |
| 818 | if (!enum_def) { | 818 | if (!enum_def) { |
| 819 | TypeTableEntry *enum_type = get_partial_container_type(c->codegen, c->import, | 819 | TypeTableEntry *enum_type = get_partial_container_type(c->codegen, c->import, |
| 820 | c->import->scope, | 820 | &c->import->decls_scope->base, |
| 821 | ContainerKindEnum, c->source_node, buf_ptr(full_type_name)); | 821 | ContainerKindEnum, c->source_node, buf_ptr(full_type_name)); |
| 822 | c->enum_type_table.put(bare_name, enum_type); | 822 | c->enum_type_table.put(bare_name, enum_type); |
| 823 | c->decl_table.put(enum_decl, enum_type); | 823 | c->decl_table.put(enum_decl, enum_type); |
| ... | @@ -842,7 +842,7 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) | ... | @@ -842,7 +842,7 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) |
| 842 | 842 | ||
| 843 | if (pure_enum) { | 843 | if (pure_enum) { |
| 844 | TypeTableEntry *enum_type = get_partial_container_type(c->codegen, c->import, | 844 | TypeTableEntry *enum_type = get_partial_container_type(c->codegen, c->import, |
| 845 | c->import->scope, | 845 | &c->import->decls_scope->base, |
| 846 | ContainerKindEnum, c->source_node, buf_ptr(full_type_name)); | 846 | ContainerKindEnum, c->source_node, buf_ptr(full_type_name)); |
| 847 | c->enum_type_table.put(bare_name, enum_type); | 847 | c->enum_type_table.put(bare_name, enum_type); |
| 848 | c->decl_table.put(enum_decl, enum_type); | 848 | c->decl_table.put(enum_decl, enum_type); |
| ... | @@ -1002,7 +1002,7 @@ static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_ | ... | @@ -1002,7 +1002,7 @@ static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_ |
| 1002 | 1002 | ||
| 1003 | 1003 | ||
| 1004 | TypeTableEntry *struct_type = get_partial_container_type(c->codegen, c->import, | 1004 | TypeTableEntry *struct_type = get_partial_container_type(c->codegen, c->import, |
| 1005 | c->import->scope, ContainerKindStruct, c->source_node, buf_ptr(full_type_name)); | 1005 | &c->import->decls_scope->base, ContainerKindStruct, c->source_node, buf_ptr(full_type_name)); |
| 1006 | 1006 | ||
| 1007 | c->struct_type_table.put(bare_name, struct_type); | 1007 | c->struct_type_table.put(bare_name, struct_type); |
| 1008 | c->decl_table.put(record_decl, struct_type); | 1008 | c->decl_table.put(record_decl, struct_type); |