authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-26 19:42:39-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-26 19:43:12-05:00
log557983e5020d0a28dba1f63ee9e515c6b779bfd4
tree2fd2b3b2715d99eba024e0c6d27fe5cf29c9be38
parent763357c9c3e8feba34a932c60b55f2224989f2d4
signaturelock-open Commit is signed but in an unrecognized format.

fix handling when there are multiple externs and

an export in the same object closes #529

8 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);
34413441
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 }
485498
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 }
1328113281
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 }
1328913298
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 @@
1const A = extern struct {
2 field: c_int,
3};
4
5extern fn issue529(?*A) void;
6
7comptime {
8 _ = @import("529_other_file_2.zig");
9}
10
11test "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 @@
1pub const A = extern struct {
2 field: c_int,
3};
4
5pub extern fn issue529(?*A) void;
test/stage1/behavior/bugs/529_other_file_2.zig created+4
...@@ -0,0 +1,4 @@
1pub const A = extern struct {
2 field: c_int,
3};
4export fn issue529(a: ?*A) void {}