mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
analyze: BlockContext has concept of module scope
This commit is contained in:
parent
3049410260
commit
52e19b4a9b
5 changed files with 47 additions and 36 deletions
|
|
@ -32,7 +32,9 @@ zig | C equivalent | Description
|
||||||
```
|
```
|
||||||
Root : many(TopLevelDecl) token(EOF)
|
Root : many(TopLevelDecl) token(EOF)
|
||||||
|
|
||||||
TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl
|
TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl | VariableDeclaration
|
||||||
|
|
||||||
|
VariableDeclaration : (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression))
|
||||||
|
|
||||||
StructDecl : many(Directive) token(Struct) token(Symbol) token(LBrace) many(StructField) token(RBrace)
|
StructDecl : many(Directive) token(Struct) token(Symbol) token(LBrace) many(StructField) token(RBrace)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -445,6 +445,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NodeTypeUse:
|
case NodeTypeUse:
|
||||||
|
case NodeTypeVariableDeclaration:
|
||||||
// nothing to do here
|
// nothing to do here
|
||||||
break;
|
break;
|
||||||
case NodeTypeDirective:
|
case NodeTypeDirective:
|
||||||
|
|
@ -453,7 +454,6 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
|
||||||
case NodeTypeType:
|
case NodeTypeType:
|
||||||
case NodeTypeFnDecl:
|
case NodeTypeFnDecl:
|
||||||
case NodeTypeReturnExpr:
|
case NodeTypeReturnExpr:
|
||||||
case NodeTypeVariableDeclaration:
|
|
||||||
case NodeTypeRoot:
|
case NodeTypeRoot:
|
||||||
case NodeTypeBlock:
|
case NodeTypeBlock:
|
||||||
case NodeTypeBinOpExpr:
|
case NodeTypeBinOpExpr:
|
||||||
|
|
@ -505,6 +505,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {
|
||||||
case NodeTypeFnDef:
|
case NodeTypeFnDef:
|
||||||
case NodeTypeRootExportDecl:
|
case NodeTypeRootExportDecl:
|
||||||
case NodeTypeUse:
|
case NodeTypeUse:
|
||||||
|
case NodeTypeVariableDeclaration:
|
||||||
// nothing to do
|
// nothing to do
|
||||||
break;
|
break;
|
||||||
case NodeTypeDirective:
|
case NodeTypeDirective:
|
||||||
|
|
@ -513,7 +514,6 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {
|
||||||
case NodeTypeType:
|
case NodeTypeType:
|
||||||
case NodeTypeFnDecl:
|
case NodeTypeFnDecl:
|
||||||
case NodeTypeReturnExpr:
|
case NodeTypeReturnExpr:
|
||||||
case NodeTypeVariableDeclaration:
|
|
||||||
case NodeTypeRoot:
|
case NodeTypeRoot:
|
||||||
case NodeTypeBlock:
|
case NodeTypeBlock:
|
||||||
case NodeTypeBinOpExpr:
|
case NodeTypeBinOpExpr:
|
||||||
|
|
@ -537,26 +537,20 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static TypeTableEntry * get_return_type(BlockContext *context) {
|
static FnTableEntry *get_context_fn_entry(BlockContext *context) {
|
||||||
AstNode *fn_def_node = context->root->node;
|
assert(context->fn_entry);
|
||||||
assert(fn_def_node->type == NodeTypeFnDef);
|
return context->fn_entry;
|
||||||
AstNode *fn_proto_node = fn_def_node->data.fn_def.fn_proto;
|
}
|
||||||
|
|
||||||
|
static TypeTableEntry *get_return_type(BlockContext *context) {
|
||||||
|
FnTableEntry *fn_entry = get_context_fn_entry(context);
|
||||||
|
AstNode *fn_proto_node = fn_entry->proto_node;
|
||||||
assert(fn_proto_node->type == NodeTypeFnProto);
|
assert(fn_proto_node->type == NodeTypeFnProto);
|
||||||
AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
|
AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
|
||||||
assert(return_type_node->codegen_node);
|
assert(return_type_node->codegen_node);
|
||||||
return return_type_node->codegen_node->data.type_node.entry;
|
return return_type_node->codegen_node->data.type_node.entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FnTableEntry *get_context_fn_entry(BlockContext *context) {
|
|
||||||
AstNode *fn_def_node = context->root->node;
|
|
||||||
assert(fn_def_node->type == NodeTypeFnDef);
|
|
||||||
AstNode *fn_proto_node = fn_def_node->data.fn_def.fn_proto;
|
|
||||||
assert(fn_proto_node->type == NodeTypeFnProto);
|
|
||||||
assert(fn_proto_node->codegen_node);
|
|
||||||
assert(fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry);
|
|
||||||
return fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void check_type_compatibility(CodeGen *g, AstNode *node,
|
static void check_type_compatibility(CodeGen *g, AstNode *node,
|
||||||
TypeTableEntry *expected_type, TypeTableEntry *actual_type)
|
TypeTableEntry *expected_type, TypeTableEntry *actual_type)
|
||||||
{
|
{
|
||||||
|
|
@ -575,21 +569,22 @@ static void check_type_compatibility(CodeGen *g, AstNode *node,
|
||||||
buf_ptr(&actual_type->name)));
|
buf_ptr(&actual_type->name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
|
BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
|
||||||
BlockContext *context = allocate<BlockContext>(1);
|
BlockContext *context = allocate<BlockContext>(1);
|
||||||
context->node = node;
|
context->node = node;
|
||||||
context->parent = parent;
|
context->parent = parent;
|
||||||
if (parent != nullptr)
|
|
||||||
context->root = parent->root;
|
|
||||||
else
|
|
||||||
context->root = context;
|
|
||||||
context->variable_table.init(8);
|
context->variable_table.init(8);
|
||||||
|
|
||||||
AstNode *fn_def_node = context->root->node;
|
if (parent) {
|
||||||
assert(fn_def_node->type == NodeTypeFnDef);
|
context->fn_entry = parent->fn_entry;
|
||||||
assert(fn_def_node->codegen_node);
|
} else if (node && node->type == NodeTypeFnDef) {
|
||||||
FnDefNode *fn_def_info = &fn_def_node->codegen_node->data.fn_def_node;
|
AstNode *fn_proto_node = node->data.fn_def.fn_proto;
|
||||||
fn_def_info->all_block_contexts.append(context);
|
context->fn_entry = fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context->fn_entry) {
|
||||||
|
context->fn_entry->all_block_contexts.append(context);
|
||||||
|
}
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
@ -1509,13 +1504,15 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,
|
||||||
case NodeTypeStructDecl:
|
case NodeTypeStructDecl:
|
||||||
// nothing to do
|
// nothing to do
|
||||||
break;
|
break;
|
||||||
|
case NodeTypeVariableDeclaration:
|
||||||
|
analyze_variable_declaration(g, import, import->block_context, nullptr, node);
|
||||||
|
break;
|
||||||
case NodeTypeDirective:
|
case NodeTypeDirective:
|
||||||
case NodeTypeParamDecl:
|
case NodeTypeParamDecl:
|
||||||
case NodeTypeFnProto:
|
case NodeTypeFnProto:
|
||||||
case NodeTypeType:
|
case NodeTypeType:
|
||||||
case NodeTypeFnDecl:
|
case NodeTypeFnDecl:
|
||||||
case NodeTypeReturnExpr:
|
case NodeTypeReturnExpr:
|
||||||
case NodeTypeVariableDeclaration:
|
|
||||||
case NodeTypeRoot:
|
case NodeTypeRoot:
|
||||||
case NodeTypeBlock:
|
case NodeTypeBlock:
|
||||||
case NodeTypeBinOpExpr:
|
case NodeTypeBinOpExpr:
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,7 @@ struct ImportTableEntry {
|
||||||
LLVMZigDIFile *di_file;
|
LLVMZigDIFile *di_file;
|
||||||
Buf *source_code;
|
Buf *source_code;
|
||||||
ZigList<int> *line_offsets;
|
ZigList<int> *line_offsets;
|
||||||
|
BlockContext *block_context;
|
||||||
|
|
||||||
// reminder: hash tables must be initialized before use
|
// reminder: hash tables must be initialized before use
|
||||||
HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
|
HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
|
||||||
|
|
@ -116,6 +117,8 @@ struct FnTableEntry {
|
||||||
unsigned calling_convention;
|
unsigned calling_convention;
|
||||||
ImportTableEntry *import_entry;
|
ImportTableEntry *import_entry;
|
||||||
ZigList<FnAttrId> fn_attr_list;
|
ZigList<FnAttrId> fn_attr_list;
|
||||||
|
// Required to be a pre-order traversal of the AST. (parents must come before children)
|
||||||
|
ZigList<BlockContext *> all_block_contexts;
|
||||||
|
|
||||||
// reminder: hash tables must be initialized before use
|
// reminder: hash tables must be initialized before use
|
||||||
HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table;
|
HashMap<Buf *, LabelTableEntry *, buf_hash, buf_eql_buf> label_table;
|
||||||
|
|
@ -201,9 +204,9 @@ struct LocalVariableTableEntry {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BlockContext {
|
struct BlockContext {
|
||||||
AstNode *node; // either NodeTypeFnDef or NodeTypeBlock
|
AstNode *node; // either NodeTypeFnDef or NodeTypeBlock or null for module scope
|
||||||
BlockContext *root; // always points to the BlockContext with the NodeTypeFnDef
|
FnTableEntry *fn_entry; // null at the module scope
|
||||||
BlockContext *parent; // nullptr when this is the root
|
BlockContext *parent; // null when this is the root
|
||||||
HashMap<Buf *, LocalVariableTableEntry *, buf_hash, buf_eql_buf> variable_table;
|
HashMap<Buf *, LocalVariableTableEntry *, buf_hash, buf_eql_buf> variable_table;
|
||||||
ZigList<AstNode *> cast_expr_alloca_list;
|
ZigList<AstNode *> cast_expr_alloca_list;
|
||||||
LLVMZigDIScope *di_scope;
|
LLVMZigDIScope *di_scope;
|
||||||
|
|
@ -221,8 +224,6 @@ struct FnDefNode {
|
||||||
TypeTableEntry *implicit_return_type;
|
TypeTableEntry *implicit_return_type;
|
||||||
BlockContext *block_context;
|
BlockContext *block_context;
|
||||||
bool skip;
|
bool skip;
|
||||||
// Required to be a pre-order traversal of the AST. (parents must come before children)
|
|
||||||
ZigList<BlockContext *> all_block_contexts;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExprNode {
|
struct ExprNode {
|
||||||
|
|
@ -295,5 +296,6 @@ void add_node_error(CodeGen *g, AstNode *node, Buf *msg);
|
||||||
TypeTableEntry *new_type_table_entry(TypeTableEntryId id);
|
TypeTableEntry *new_type_table_entry(TypeTableEntryId id);
|
||||||
TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
|
TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
|
||||||
LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name);
|
LocalVariableTableEntry *find_local_variable(BlockContext *context, Buf *name);
|
||||||
|
BlockContext *new_block_context(AstNode *node, BlockContext *parent);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1132,8 +1132,8 @@ static void do_code_gen(CodeGen *g) {
|
||||||
|
|
||||||
// Set up debug info for blocks and variables and
|
// Set up debug info for blocks and variables and
|
||||||
// allocate all local variables
|
// allocate all local variables
|
||||||
for (int bc_i = 0; bc_i < codegen_fn_def->all_block_contexts.length; bc_i += 1) {
|
for (int bc_i = 0; bc_i < fn_table_entry->all_block_contexts.length; bc_i += 1) {
|
||||||
BlockContext *block_context = codegen_fn_def->all_block_contexts.at(bc_i);
|
BlockContext *block_context = fn_table_entry->all_block_contexts.at(bc_i);
|
||||||
|
|
||||||
if (block_context->parent) {
|
if (block_context->parent) {
|
||||||
LLVMZigDILexicalBlock *di_block = LLVMZigCreateLexicalBlock(g->dbuilder,
|
LLVMZigDILexicalBlock *di_block = LLVMZigCreateLexicalBlock(g->dbuilder,
|
||||||
|
|
@ -1530,6 +1530,9 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *src_dirname, Buf *src
|
||||||
import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
|
import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
|
||||||
g->import_table.put(full_path, import_entry);
|
g->import_table.put(full_path, import_entry);
|
||||||
|
|
||||||
|
import_entry->block_context = new_block_context(nullptr, nullptr);
|
||||||
|
import_entry->block_context->di_scope = LLVMZigFileToScope(import_entry->di_file);
|
||||||
|
|
||||||
|
|
||||||
assert(import_entry->root->type == NodeTypeRoot);
|
assert(import_entry->root->type == NodeTypeRoot);
|
||||||
for (int decl_i = 0; decl_i < import_entry->root->data.root.top_level_decls.length; decl_i += 1) {
|
for (int decl_i = 0; decl_i < import_entry->root->data.root.top_level_decls.length; decl_i += 1) {
|
||||||
|
|
|
||||||
|
|
@ -2266,7 +2266,7 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl
|
TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | StructDecl | VariableDeclaration
|
||||||
*/
|
*/
|
||||||
static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) {
|
static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
@ -2310,6 +2310,13 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis
|
||||||
}
|
}
|
||||||
pc->directive_list = nullptr;
|
pc->directive_list = nullptr;
|
||||||
|
|
||||||
|
AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false);
|
||||||
|
if (var_decl_node) {
|
||||||
|
ast_eat_token(pc, token_index, TokenIdSemicolon);
|
||||||
|
top_level_decls->append(var_decl_node);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue