| author | |
| committer | |
| log | 557983e5020d0a28dba1f63ee9e515c6b779bfd4 |
| tree | 2fd2b3b2715d99eba024e0c6d27fe5cf29c9be38 |
| parent | 763357c9c3e8feba34a932c60b55f2224989f2d4 |
| signature |
an export in the same object
closes #5298 files changed, 55 insertions(+), 7 deletions(-)
src/all_types.hpp+1-1| ... | @@ -1679,7 +1679,7 @@ struct CodeGen { | ... | @@ -1679,7 +1679,7 @@ struct CodeGen { |
| 1679 | HashMap<GenericFnTypeId *, ZigFn *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table; | 1679 | HashMap<GenericFnTypeId *, ZigFn *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table; |
| 1680 | HashMap<Scope *, ConstExprValue *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table; | 1680 | HashMap<Scope *, ConstExprValue *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table; |
| 1681 | HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table; | 1681 | HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table; |
| 1682 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names; | 1682 | HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> exported_symbol_names; |
| 1683 | HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes; | 1683 | HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes; |
| 1684 | HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> string_literals_table; | 1684 | HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> string_literals_table; |
| 1685 | HashMap<const ZigType *, ConstExprValue *, type_ptr_hash, type_ptr_eql> type_info_cache; | 1685 | HashMap<const ZigType *, ConstExprValue *, type_ptr_hash, type_ptr_eql> type_info_cache; |
src/analyze.cpp+2-2| ... | @@ -3439,9 +3439,9 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) { | ... | @@ -3439,9 +3439,9 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) { |
| 3439 | if (is_export) { | 3439 | if (is_export) { |
| 3440 | g->resolve_queue.append(tld); | 3440 | g->resolve_queue.append(tld); |
| 3441 | 3441 | ||
| 3442 | auto entry = g->exported_symbol_names.put_unique(tld->name, tld->source_node); | 3442 | auto entry = g->exported_symbol_names.put_unique(tld->name, tld); |
| 3443 | if (entry) { | 3443 | if (entry) { |
| 3444 | AstNode *other_source_node = entry->value; | 3444 | AstNode *other_source_node = entry->value->source_node; |
| 3445 | ErrorMsg *msg = add_node_error(g, tld->source_node, | 3445 | ErrorMsg *msg = add_node_error(g, tld->source_node, |
| 3446 | buf_sprintf("exported symbol collision: '%s'", buf_ptr(tld->name))); | 3446 | buf_sprintf("exported symbol collision: '%s'", buf_ptr(tld->name))); |
| 3447 | add_error_note(g, msg, other_source_node, buf_sprintf("other symbol here")); | 3447 | add_error_note(g, msg, other_source_node, buf_sprintf("other symbol here")); |
src/codegen.cpp+15-2| ... | @@ -478,10 +478,23 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { | ... | @@ -478,10 +478,23 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { |
| 478 | fn_table_entry->llvm_value = LLVMConstBitCast(existing_llvm_fn, LLVMPointerType(fn_llvm_type, 0)); | 478 | fn_table_entry->llvm_value = LLVMConstBitCast(existing_llvm_fn, LLVMPointerType(fn_llvm_type, 0)); |
| 479 | return fn_table_entry->llvm_value; | 479 | return fn_table_entry->llvm_value; |
| 480 | } else { | 480 | } else { |
| 481 | fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type); | 481 | auto entry = g->exported_symbol_names.maybe_get(symbol_name); |
| 482 | if (entry == nullptr) { | ||
| 483 | fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type); | ||
| 484 | } else { | ||
| 485 | assert(entry->value->id == TldIdFn); | ||
| 486 | TldFn *tld_fn = reinterpret_cast<TldFn *>(entry->value); | ||
| 487 | tld_fn->fn_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), | ||
| 488 | tld_fn->fn_entry->type_entry->data.fn.raw_type_ref); | ||
| 489 | fn_table_entry->llvm_value = LLVMConstBitCast(tld_fn->fn_entry->llvm_value, | ||
| 490 | LLVMPointerType(fn_llvm_type, 0)); | ||
| 491 | return fn_table_entry->llvm_value; | ||
| 492 | } | ||
| 482 | } | 493 | } |
| 483 | } else { | 494 | } else { |
| 484 | fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type); | 495 | if (fn_table_entry->llvm_value == nullptr) { |
| 496 | fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type); | ||
| 497 | } | ||
| 485 | 498 | ||
| 486 | for (size_t i = 1; i < fn_table_entry->export_list.length; i += 1) { | 499 | for (size_t i = 1; i < fn_table_entry->export_list.length; i += 1) { |
| 487 | FnExport *fn_export = &fn_table_entry->export_list.items[i]; | 500 | FnExport *fn_export = &fn_table_entry->export_list.items[i]; |
src/ir.cpp+12-2| ... | @@ -13279,12 +13279,21 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio | ... | @@ -13279,12 +13279,21 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio |
| 13279 | } | 13279 | } |
| 13280 | } | 13280 | } |
| 13281 | 13281 | ||
| 13282 | auto entry = ira->codegen->exported_symbol_names.put_unique(symbol_name, instruction->base.source_node); | 13282 | // TODO: This function needs to be audited. |
| 13283 | // It's not clear how all the different types are supposed to be handled. | ||
| 13284 | // Need comprehensive tests for exporting one thing in one file and declaring an extern var | ||
| 13285 | // in another file. | ||
| 13286 | TldFn *tld_fn = allocate<TldFn>(1); | ||
| 13287 | tld_fn->base.id = TldIdFn; | ||
| 13288 | tld_fn->base.source_node = instruction->base.source_node; | ||
| 13289 | |||
| 13290 | auto entry = ira->codegen->exported_symbol_names.put_unique(symbol_name, &tld_fn->base); | ||
| 13283 | if (entry) { | 13291 | if (entry) { |
| 13284 | AstNode *other_export_node = entry->value; | 13292 | AstNode *other_export_node = entry->value->source_node; |
| 13285 | ErrorMsg *msg = ir_add_error(ira, &instruction->base, | 13293 | ErrorMsg *msg = ir_add_error(ira, &instruction->base, |
| 13286 | buf_sprintf("exported symbol collision: '%s'", buf_ptr(symbol_name))); | 13294 | buf_sprintf("exported symbol collision: '%s'", buf_ptr(symbol_name))); |
| 13287 | add_error_note(ira->codegen, msg, other_export_node, buf_sprintf("other symbol is here")); | 13295 | add_error_note(ira->codegen, msg, other_export_node, buf_sprintf("other symbol is here")); |
| 13296 | return ira->codegen->invalid_instruction; | ||
| 13288 | } | 13297 | } |
| 13289 | 13298 | ||
| 13290 | bool want_var_export = false; | 13299 | bool want_var_export = false; |
| ... | @@ -13295,6 +13304,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio | ... | @@ -13295,6 +13304,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio |
| 13295 | case ZigTypeIdFn: { | 13304 | case ZigTypeIdFn: { |
| 13296 | assert(target->value.data.x_ptr.special == ConstPtrSpecialFunction); | 13305 | assert(target->value.data.x_ptr.special == ConstPtrSpecialFunction); |
| 13297 | ZigFn *fn_entry = target->value.data.x_ptr.data.fn.fn_entry; | 13306 | ZigFn *fn_entry = target->value.data.x_ptr.data.fn.fn_entry; |
| 13307 | tld_fn->fn_entry = fn_entry; | ||
| 13298 | CallingConvention cc = fn_entry->type_entry->data.fn.fn_type_id.cc; | 13308 | CallingConvention cc = fn_entry->type_entry->data.fn.fn_type_id.cc; |
| 13299 | switch (cc) { | 13309 | switch (cc) { |
| 13300 | case CallingConventionUnspecified: { | 13310 | case CallingConventionUnspecified: { |
test/stage1/behavior.zig+1| ... | @@ -22,6 +22,7 @@ comptime { | ... | @@ -22,6 +22,7 @@ comptime { |
| 22 | _ = @import("behavior/bugs/2006.zig"); | 22 | _ = @import("behavior/bugs/2006.zig"); |
| 23 | _ = @import("behavior/bugs/394.zig"); | 23 | _ = @import("behavior/bugs/394.zig"); |
| 24 | _ = @import("behavior/bugs/421.zig"); | 24 | _ = @import("behavior/bugs/421.zig"); |
| 25 | _ = @import("behavior/bugs/529.zig"); | ||
| 25 | _ = @import("behavior/bugs/655.zig"); | 26 | _ = @import("behavior/bugs/655.zig"); |
| 26 | _ = @import("behavior/bugs/656.zig"); | 27 | _ = @import("behavior/bugs/656.zig"); |
| 27 | _ = @import("behavior/bugs/704.zig"); | 28 | _ = @import("behavior/bugs/704.zig"); |
test/stage1/behavior/bugs/529.zig created+15| ... | @@ -0,0 +1,15 @@ | ||
| 1 | const A = extern struct { | ||
| 2 | field: c_int, | ||
| 3 | }; | ||
| 4 | |||
| 5 | extern fn issue529(?*A) void; | ||
| 6 | |||
| 7 | comptime { | ||
| 8 | _ = @import("529_other_file_2.zig"); | ||
| 9 | } | ||
| 10 | |||
| 11 | test "issue 529 fixed" { | ||
| 12 | @import("529_other_file.zig").issue529(null); | ||
| 13 | issue529(null); | ||
| 14 | } | ||
| 15 | |||
test/stage1/behavior/bugs/529_other_file.zig created+5| ... | @@ -0,0 +1,5 @@ | ||
| 1 | pub const A = extern struct { | ||
| 2 | field: c_int, | ||
| 3 | }; | ||
| 4 | |||
| 5 | pub extern fn issue529(?*A) void; | ||
test/stage1/behavior/bugs/529_other_file_2.zig created+4| ... | @@ -0,0 +1,4 @@ | ||
| 1 | pub const A = extern struct { | ||
| 2 | field: c_int, | ||
| 3 | }; | ||
| 4 | export fn issue529(a: ?*A) void {} | ||