diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2015-12-01 02:08:58 -0700 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2015-12-01 02:08:58 -0700 |
| commit | 58e375d0a1423c04f4d3faabe4d84bfc11028d56 (patch) | |
| tree | 733056bbfef07b984aabaea612d1dae67f698f68 /src | |
| parent | 29f24e3c5066e7cb28876d40a811a4a64f9d4b33 (diff) | |
| download | zig-58e375d0a1423c04f4d3faabe4d84bfc11028d56.tar.gz zig-58e375d0a1423c04f4d3faabe4d84bfc11028d56.zip | |
support multiple files
Diffstat (limited to 'src')
| -rw-r--r-- | src/analyze.cpp | 103 | ||||
| -rw-r--r-- | src/codegen.cpp | 24 | ||||
| -rw-r--r-- | src/semantic_info.hpp | 7 |
3 files changed, 93 insertions, 41 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp index fccbad8bb7..d7d5aeb5b0 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -137,6 +137,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, AstNode *fn_decl = node->data.extern_block.fn_decls.at(fn_decl_i); assert(fn_decl->type == NodeTypeFnDecl); AstNode *fn_proto = fn_decl->data.fn_decl.fn_proto; + bool is_pub = (fn_proto->data.fn_proto.visib_mod == FnProtoVisibModPub); resolve_function_proto(g, fn_proto); Buf *name = &fn_proto->data.fn_proto.name; @@ -145,7 +146,12 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, fn_table_entry->is_extern = true; fn_table_entry->calling_convention = LLVMCCallConv; fn_table_entry->import_entry = import; - g->fn_table.put(name, fn_table_entry); + + g->fn_protos.append(fn_table_entry); + import->fn_table.put(name, fn_table_entry); + if (is_pub) { + g->fn_table.put(name, fn_table_entry); + } } break; case NodeTypeFnDef: @@ -153,27 +159,44 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, AstNode *proto_node = node->data.fn_def.fn_proto; assert(proto_node->type == NodeTypeFnProto); Buf *proto_name = &proto_node->data.fn_proto.name; - auto entry = g->fn_table.maybe_get(proto_name); + auto entry = import->fn_table.maybe_get(proto_name); + bool skip = false; + bool is_internal = (proto_node->data.fn_proto.visib_mod != FnProtoVisibModExport); + bool is_pub = (proto_node->data.fn_proto.visib_mod == FnProtoVisibModPub); if (entry) { add_node_error(g, node, buf_sprintf("redefinition of '%s'", buf_ptr(proto_name))); assert(!node->codegen_node); node->codegen_node = allocate<CodeGenNode>(1); node->codegen_node->data.fn_def_node.skip = true; - } else { + skip = true; + } else if (is_pub) { + auto entry = g->fn_table.maybe_get(proto_name); + if (entry) { + add_node_error(g, node, + buf_sprintf("redefinition of '%s'", buf_ptr(proto_name))); + assert(!node->codegen_node); + node->codegen_node = allocate<CodeGenNode>(1); + node->codegen_node->data.fn_def_node.skip = true; + skip = true; + } + } + if (!skip) { FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1); fn_table_entry->import_entry = import; fn_table_entry->proto_node = proto_node; fn_table_entry->fn_def_node = node; - fn_table_entry->internal_linkage = proto_node->data.fn_proto.visib_mod != FnProtoVisibModExport; - if (fn_table_entry->internal_linkage) { - fn_table_entry->calling_convention = LLVMFastCallConv; - } else { - fn_table_entry->calling_convention = LLVMCCallConv; - } - g->fn_table.put(proto_name, fn_table_entry); + fn_table_entry->internal_linkage = is_internal; + fn_table_entry->calling_convention = is_internal ? LLVMFastCallConv : LLVMCCallConv; + + g->fn_protos.append(fn_table_entry); g->fn_defs.append(fn_table_entry); + import->fn_table.put(proto_name, fn_table_entry); + if (is_pub) { + g->fn_table.put(proto_name, fn_table_entry); + } + resolve_function_proto(g, proto_node); } } @@ -297,28 +320,31 @@ static void check_fn_def_control_flow(CodeGen *g, AstNode *node) { } } -static void analyze_expression(CodeGen *g, AstNode *node) { +static void analyze_expression(CodeGen *g, ImportTableEntry *import, AstNode *node) { switch (node->type) { case NodeTypeBlock: for (int i = 0; i < node->data.block.statements.length; i += 1) { AstNode *child = node->data.block.statements.at(i); - analyze_expression(g, child); + analyze_expression(g, import, child); } break; case NodeTypeReturnExpr: if (node->data.return_expr.expr) { - analyze_expression(g, node->data.return_expr.expr); + analyze_expression(g, import, node->data.return_expr.expr); } break; case NodeTypeBinOpExpr: - analyze_expression(g, node->data.bin_op_expr.op1); - analyze_expression(g, node->data.bin_op_expr.op2); + analyze_expression(g, import, node->data.bin_op_expr.op1); + analyze_expression(g, import, node->data.bin_op_expr.op2); break; case NodeTypeFnCallExpr: { Buf *name = hack_get_fn_call_name(g, node->data.fn_call_expr.fn_ref_expr); - auto entry = g->fn_table.maybe_get(name); + auto entry = import->fn_table.maybe_get(name); + if (!entry) + entry = g->fn_table.maybe_get(name); + if (!entry) { add_node_error(g, node, buf_sprintf("undefined function: '%s'", buf_ptr(name))); @@ -336,7 +362,7 @@ static void analyze_expression(CodeGen *g, AstNode *node) { for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) { AstNode *child = node->data.fn_call_expr.params.at(i); - analyze_expression(g, child); + analyze_expression(g, import, child); } break; } @@ -366,7 +392,7 @@ static void analyze_expression(CodeGen *g, AstNode *node) { } } -static void analyze_top_level_declaration(CodeGen *g, AstNode *node) { +static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import, AstNode *node) { switch (node->type) { case NodeTypeFnDef: { @@ -387,7 +413,7 @@ static void analyze_top_level_declaration(CodeGen *g, AstNode *node) { } check_fn_def_control_flow(g, node); - analyze_expression(g, node->data.fn_def.body); + analyze_expression(g, import, node->data.fn_def.body); } break; @@ -423,33 +449,50 @@ static void analyze_top_level_declaration(CodeGen *g, AstNode *node) { } } -static void analyze_root(CodeGen *g, ImportTableEntry *import, AstNode *node) { +static void find_function_declarations_root(CodeGen *g, ImportTableEntry *import, AstNode *node) { assert(node->type == NodeTypeRoot); - // find function declarations for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) { AstNode *child = node->data.root.top_level_decls.at(i); preview_function_declarations(g, import, child); } +} + +static void analyze_top_level_decls_root(CodeGen *g, ImportTableEntry *import, AstNode *node) { + assert(node->type == NodeTypeRoot); + for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) { AstNode *child = node->data.root.top_level_decls.at(i); - analyze_top_level_declaration(g, child); + analyze_top_level_declaration(g, import, child); } - } void semantic_analyze(CodeGen *g) { - auto it = g->import_table.entry_iterator(); - for (;;) { - auto *entry = it.next(); - if (!entry) - break; + { + auto it = g->import_table.entry_iterator(); + for (;;) { + auto *entry = it.next(); + if (!entry) + break; - ImportTableEntry *import = entry->value; - analyze_root(g, import, import->root); + ImportTableEntry *import = entry->value; + find_function_declarations_root(g, import, import->root); + } + } + { + auto it = g->import_table.entry_iterator(); + for (;;) { + auto *entry = it.next(); + if (!entry) + break; + + ImportTableEntry *import = entry->value; + analyze_top_level_decls_root(g, import, import->root); + } } + if (!g->root_out_name) { add_node_error(g, g->root_import->root, buf_sprintf("missing export declaration and output name not provided")); diff --git a/src/codegen.cpp b/src/codegen.cpp index 2f9bf47383..5ce95023e1 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -125,7 +125,13 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) { Buf *name = hack_get_fn_call_name(g, node->data.fn_call_expr.fn_ref_expr); - FnTableEntry *fn_table_entry = g->fn_table.get(name); + FnTableEntry *fn_table_entry; + auto entry = g->cur_fn->import_entry->fn_table.maybe_get(name); + if (entry) + fn_table_entry = entry->value; + else + fn_table_entry = g->fn_table.get(name); + assert(fn_table_entry->proto_node->type == NodeTypeFnProto); int expected_param_count = fn_table_entry->proto_node->data.fn_proto.params.length; int actual_param_count = node->data.fn_call_expr.params.length; @@ -478,13 +484,8 @@ static void do_code_gen(CodeGen *g) { // Generate function prototypes - auto it = g->fn_table.entry_iterator(); - for (;;) { - auto *entry = it.next(); - if (!entry) - break; - - FnTableEntry *fn_table_entry = entry->value; + for (int i = 0; i < g->fn_protos.length; i += 1) { + FnTableEntry *fn_table_entry = g->fn_protos.at(i); AstNode *proto_node = fn_table_entry->proto_node; assert(proto_node->type == NodeTypeFnProto); @@ -547,6 +548,7 @@ static void do_code_gen(CodeGen *g) { assert(codegen_node); FnDefNode *codegen_fn_def = &codegen_node->data.fn_def_node; + assert(codegen_fn_def); codegen_fn_def->params = allocate<LLVMValueRef>(LLVMCountParams(fn)); LLVMGetParams(fn, codegen_fn_def->params); @@ -733,9 +735,9 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *source_path, Buf *sou if (!entry) { Buf full_path = BUF_INIT; os_path_join(g->root_source_dir, &top_level_decl->data.use.path, &full_path); - Buf import_code = BUF_INIT; - os_fetch_file_path(&full_path, &import_code); - codegen_add_code(g, &top_level_decl->data.use.path, &import_code); + Buf *import_code = buf_alloc(); + os_fetch_file_path(&full_path, import_code); + codegen_add_code(g, &top_level_decl->data.use.path, import_code); } } diff --git a/src/semantic_info.hpp b/src/semantic_info.hpp index 075b1c8bdc..f0a79d685d 100644 --- a/src/semantic_info.hpp +++ b/src/semantic_info.hpp @@ -80,7 +80,14 @@ struct CodeGen { Buf *root_source_dir; Buf *root_out_name; ZigList<LLVMZigDIScope *> block_scopes; + + // The function definitions this module includes. There must be a corresponding + // fn_protos entry. ZigList<FnTableEntry *> fn_defs; + // The function prototypes this module includes. In the case of external declarations, + // there will not be a corresponding fn_defs entry. + ZigList<FnTableEntry *> fn_protos; + OutType out_type; FnTableEntry *cur_fn; bool c_stdint_used; |
