authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-14 22:01:39-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-12-14 22:06:25-07:00
log52e19b4a9b6e6140bae3c20c6f1fef36dca20aa7
tree7f08300bbaedd657fc46ae816e0302470becfb1a
parent304941026013e6310c9362849610c32d98d1332a

analyze: BlockContext has concept of module scope


5 files changed, 47 insertions(+), 36 deletions(-)

doc/langref.md+3-1
...@@ -32,7 +32,9 @@ zig | C equivalent | Description...@@ -32,7 +32,9 @@ zig | C equivalent | Description
32```32```
33Root : many(TopLevelDecl) token(EOF)33Root : many(TopLevelDecl) token(EOF)
3434
35TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl35TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl | VariableDeclaration
36
37VariableDeclaration : (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression))
3638
37StructDecl : many(Directive) token(Struct) token(Symbol) token(LBrace) many(StructField) token(RBrace)39StructDecl : many(Directive) token(Struct) token(Symbol) token(LBrace) many(StructField) token(RBrace)
3840
src/analyze.cpp+24-27
...@@ -445,6 +445,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,...@@ -445,6 +445,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
445 break;445 break;
446 }446 }
447 case NodeTypeUse:447 case NodeTypeUse:
448 case NodeTypeVariableDeclaration:
448 // nothing to do here449 // nothing to do here
449 break;450 break;
450 case NodeTypeDirective:451 case NodeTypeDirective:
...@@ -453,7 +454,6 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,...@@ -453,7 +454,6 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
453 case NodeTypeType:454 case NodeTypeType:
454 case NodeTypeFnDecl:455 case NodeTypeFnDecl:
455 case NodeTypeReturnExpr:456 case NodeTypeReturnExpr:
456 case NodeTypeVariableDeclaration:
457 case NodeTypeRoot:457 case NodeTypeRoot:
458 case NodeTypeBlock:458 case NodeTypeBlock:
459 case NodeTypeBinOpExpr:459 case NodeTypeBinOpExpr:
...@@ -505,6 +505,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {...@@ -505,6 +505,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {
505 case NodeTypeFnDef:505 case NodeTypeFnDef:
506 case NodeTypeRootExportDecl:506 case NodeTypeRootExportDecl:
507 case NodeTypeUse:507 case NodeTypeUse:
508 case NodeTypeVariableDeclaration:
508 // nothing to do509 // nothing to do
509 break;510 break;
510 case NodeTypeDirective:511 case NodeTypeDirective:
...@@ -513,7 +514,6 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {...@@ -513,7 +514,6 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {
513 case NodeTypeType:514 case NodeTypeType:
514 case NodeTypeFnDecl:515 case NodeTypeFnDecl:
515 case NodeTypeReturnExpr:516 case NodeTypeReturnExpr:
516 case NodeTypeVariableDeclaration:
517 case NodeTypeRoot:517 case NodeTypeRoot:
518 case NodeTypeBlock:518 case NodeTypeBlock:
519 case NodeTypeBinOpExpr:519 case NodeTypeBinOpExpr:
...@@ -537,26 +537,20 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {...@@ -537,26 +537,20 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {
537 }537 }
538}538}
539539
540static TypeTableEntry * get_return_type(BlockContext *context) {540static FnTableEntry *get_context_fn_entry(BlockContext *context) {
541 AstNode *fn_def_node = context->root->node;541 assert(context->fn_entry);
542 assert(fn_def_node->type == NodeTypeFnDef);542 return context->fn_entry;
543 AstNode *fn_proto_node = fn_def_node->data.fn_def.fn_proto;543}
544
545static TypeTableEntry *get_return_type(BlockContext *context) {
546 FnTableEntry *fn_entry = get_context_fn_entry(context);
547 AstNode *fn_proto_node = fn_entry->proto_node;
544 assert(fn_proto_node->type == NodeTypeFnProto);548 assert(fn_proto_node->type == NodeTypeFnProto);
545 AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;549 AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
546 assert(return_type_node->codegen_node);550 assert(return_type_node->codegen_node);
547 return return_type_node->codegen_node->data.type_node.entry;551 return return_type_node->codegen_node->data.type_node.entry;
548}552}
549553
550static FnTableEntry *get_context_fn_entry(BlockContext *context) {
551 AstNode *fn_def_node = context->root->node;
552 assert(fn_def_node->type == NodeTypeFnDef);
553 AstNode *fn_proto_node = fn_def_node->data.fn_def.fn_proto;
554 assert(fn_proto_node->type == NodeTypeFnProto);
555 assert(fn_proto_node->codegen_node);
556 assert(fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry);
557 return fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry;
558}
559
560static void check_type_compatibility(CodeGen *g, AstNode *node,554static void check_type_compatibility(CodeGen *g, AstNode *node,
561 TypeTableEntry *expected_type, TypeTableEntry *actual_type)555 TypeTableEntry *expected_type, TypeTableEntry *actual_type)
562{556{
...@@ -575,21 +569,22 @@ static void check_type_compatibility(CodeGen *g, AstNode *node,...@@ -575,21 +569,22 @@ static void check_type_compatibility(CodeGen *g, AstNode *node,
575 buf_ptr(&actual_type->name)));569 buf_ptr(&actual_type->name)));
576}570}
577571
578static BlockContext *new_block_context(AstNode *node, BlockContext *parent) {572BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
579 BlockContext *context = allocate<BlockContext>(1);573 BlockContext *context = allocate<BlockContext>(1);
580 context->node = node;574 context->node = node;
581 context->parent = parent;575 context->parent = parent;
582 if (parent != nullptr)
583 context->root = parent->root;
584 else
585 context->root = context;
586 context->variable_table.init(8);576 context->variable_table.init(8);
587577
588 AstNode *fn_def_node = context->root->node;578 if (parent) {
589 assert(fn_def_node->type == NodeTypeFnDef);579 context->fn_entry = parent->fn_entry;
590 assert(fn_def_node->codegen_node);580 } else if (node && node->type == NodeTypeFnDef) {
591 FnDefNode *fn_def_info = &fn_def_node->codegen_node->data.fn_def_node;581 AstNode *fn_proto_node = node->data.fn_def.fn_proto;
592 fn_def_info->all_block_contexts.append(context);582 context->fn_entry = fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry;
583 }
584
585 if (context->fn_entry) {
586 context->fn_entry->all_block_contexts.append(context);
587 }
593588
594 return context;589 return context;
595}590}
...@@ -1509,13 +1504,15 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,...@@ -1509,13 +1504,15 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,
1509 case NodeTypeStructDecl:1504 case NodeTypeStructDecl:
1510 // nothing to do1505 // nothing to do
1511 break;1506 break;
1507 case NodeTypeVariableDeclaration:
1508 analyze_variable_declaration(g, import, import->block_context, nullptr, node);
1509 break;
1512 case NodeTypeDirective:1510 case NodeTypeDirective:
1513 case NodeTypeParamDecl:1511 case NodeTypeParamDecl:
1514 case NodeTypeFnProto:1512 case NodeTypeFnProto:
1515 case NodeTypeType:1513 case NodeTypeType:
1516 case NodeTypeFnDecl:1514 case NodeTypeFnDecl:
1517 case NodeTypeReturnExpr:1515 case NodeTypeReturnExpr:
1518 case NodeTypeVariableDeclaration:
1519 case NodeTypeRoot:1516 case NodeTypeRoot:
1520 case NodeTypeBlock:1517 case NodeTypeBlock:
1521 case NodeTypeBinOpExpr:1518 case NodeTypeBinOpExpr:
src/analyze.hpp+7-5
...@@ -90,6 +90,7 @@ struct ImportTableEntry {...@@ -90,6 +90,7 @@ struct ImportTableEntry {
90 LLVMZigDIFile *di_file;90 LLVMZigDIFile *di_file;
91 Buf *source_code;91 Buf *source_code;
92 ZigList<int> *line_offsets;92 ZigList<int> *line_offsets;
93 BlockContext *block_context;
9394
94 // reminder: hash tables must be initialized before use95 // reminder: hash tables must be initialized before use
95 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;96 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
...@@ -116,6 +117,8 @@ struct FnTableEntry {...@@ -116,6 +117,8 @@ struct FnTableEntry {
116 unsigned calling_convention;117 unsigned calling_convention;
117 ImportTableEntry *import_entry;118 ImportTableEntry *import_entry;
118 ZigList<FnAttrId> fn_attr_list;119 ZigList<FnAttrId> fn_attr_list;
120 // Required to be a pre-order traversal of the AST. (parents must come before children)
121 ZigList<BlockContext *> all_block_contexts;
119122
120 // reminder: hash tables must be initialized before use123 // reminder: hash tables must be initialized before use
121 HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table;124 HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table;
...@@ -201,9 +204,9 @@ struct LocalVariableTableEntry {...@@ -201,9 +204,9 @@ struct LocalVariableTableEntry {
201};204};
202205
203struct BlockContext {206struct BlockContext {
204 AstNode *node; // either NodeTypeFnDef or NodeTypeBlock207 AstNode *node; // either NodeTypeFnDef or NodeTypeBlock or null for module scope
205 BlockContext *root; // always points to the BlockContext with the NodeTypeFnDef208 FnTableEntry *fn_entry; // null at the module scope
206 BlockContext *parent; // nullptr when this is the root209 BlockContext *parent; // null when this is the root
207 HashMap<Buf *, LocalVariableTableEntry *, buf_hash, buf_eql_buf> variable_table;210 HashMap<Buf *, LocalVariableTableEntry *, buf_hash, buf_eql_buf> variable_table;
208 ZigList<AstNode *> cast_expr_alloca_list;211 ZigList<AstNode *> cast_expr_alloca_list;
209 LLVMZigDIScope *di_scope;212 LLVMZigDIScope *di_scope;
...@@ -221,8 +224,6 @@ struct FnDefNode {...@@ -221,8 +224,6 @@ struct FnDefNode {
221 TypeTableEntry *implicit_return_type;224 TypeTableEntry *implicit_return_type;
222 BlockContext *block_context;225 BlockContext *block_context;
223 bool skip;226 bool skip;
224 // Required to be a pre-order traversal of the AST. (parents must come before children)
225 ZigList<BlockContext *> all_block_contexts;
226};227};
227228
228struct ExprNode {229struct ExprNode {
...@@ -295,5 +296,6 @@ void add_node_error(CodeGen *g, AstNode *node, Buf *msg);...@@ -295,5 +296,6 @@ void add_node_error(CodeGen *g, AstNode *node, Buf *msg);
295TypeTableEntry *new_type_table_entry(TypeTableEntryId id);296TypeTableEntry *new_type_table_entry(TypeTableEntryId id);
296TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);297TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
297LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name);298LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name);
299BlockContext *new_block_context(AstNode *node, BlockContext *parent);
298300
299#endif301#endif
src/codegen.cpp+5-2
...@@ -1132,8 +1132,8 @@ static void do_code_gen(CodeGen *g) {...@@ -1132,8 +1132,8 @@ static void do_code_gen(CodeGen *g) {
11321132
1133 // Set up debug info for blocks and variables and1133 // Set up debug info for blocks and variables and
1134 // allocate all local variables1134 // allocate all local variables
1135 for (int bc_i = 0; bc_i < codegen_fn_def->all_block_contexts.length; bc_i += 1) {1135 for (int bc_i = 0; bc_i < fn_table_entry->all_block_contexts.length; bc_i += 1) {
1136 BlockContext *block_context = codegen_fn_def->all_block_contexts.at(bc_i);1136 BlockContext *block_context = fn_table_entry->all_block_contexts.at(bc_i);
11371137
1138 if (block_context->parent) {1138 if (block_context->parent) {
1139 LLVMZigDILexicalBlock *di_block = LLVMZigCreateLexicalBlock(g->dbuilder,1139 LLVMZigDILexicalBlock *di_block = LLVMZigCreateLexicalBlock(g->dbuilder,
...@@ -1530,6 +1530,9 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *src_dirname, Buf *src...@@ -1530,6 +1530,9 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *src_dirname, Buf *src
1530 import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));1530 import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
1531 g->import_table.put(full_path, import_entry);1531 g->import_table.put(full_path, import_entry);
15321532
1533 import_entry->block_context = new_block_context(nullptr, nullptr);
1534 import_entry->block_context->di_scope = LLVMZigFileToScope(import_entry->di_file);
1535
15331536
1534 assert(import_entry->root->type == NodeTypeRoot);1537 assert(import_entry->root->type == NodeTypeRoot);
1535 for (int decl_i = 0; decl_i < import_entry->root->data.root.top_level_decls.length; decl_i += 1) {1538 for (int decl_i = 0; decl_i < import_entry->root->data.root.top_level_decls.length; decl_i += 1) {
src/parser.cpp+8-1
...@@ -2266,7 +2266,7 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {...@@ -2266,7 +2266,7 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {
2266}2266}
22672267
2268/*2268/*
2269TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl2269TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl | VariableDeclaration
2270*/2270*/
2271static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) {2271static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) {
2272 for (;;) {2272 for (;;) {
...@@ -2310,6 +2310,13 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis...@@ -2310,6 +2310,13 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis
2310 }2310 }
2311 pc->directive_list = nullptr;2311 pc->directive_list = nullptr;
23122312
2313 AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false);
2314 if (var_decl_node) {
2315 ast_eat_token(pc, token_index, TokenIdSemicolon);
2316 top_level_decls->append(var_decl_node);
2317 continue;
2318 }
2319
2313 return;2320 return;
2314 }2321 }
2315 zig_unreachable();2322 zig_unreachable();