authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-12-03 03:39:28-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-12-03 08:21:03-05:00
log81c271cc6298bf164b202a194ef18b56665ce2d9
treeb5f6c7e64853d3cd7c1e1297e8b74fe61b5549d4
parent2cfc08ba0d5ad2f0f4cef71ad4365dfd0e71b9bd

cbe: don't emit extern decls that are already exported


4 files changed, 27 insertions(+), 14 deletions(-)

src/codegen/c.zig+7-6
...@@ -2427,11 +2427,15 @@ pub fn genFunc(f: *Function) !void {...@@ -2427,11 +2427,15 @@ pub fn genFunc(f: *Function) !void {
2427 defer tracy.end();2427 defer tracy.end();
24282428
2429 const o = &f.object;2429 const o = &f.object;
2430 const tv: TypedValue = .{
2431 .ty = o.dg.decl.ty,
2432 .val = o.dg.decl.val,
2433 };
24302434
2431 o.code_header = std.ArrayList(u8).init(f.object.dg.gpa);2435 o.code_header = std.ArrayList(u8).init(f.object.dg.gpa);
2432 defer o.code_header.deinit();2436 defer o.code_header.deinit();
24332437
2434 const is_global = o.dg.module.decl_exports.contains(f.func.owner_decl);2438 const is_global = o.dg.declIsGlobal(tv);
2435 const fwd_decl_writer = o.dg.fwd_decl.writer();2439 const fwd_decl_writer = o.dg.fwd_decl.writer();
2436 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");2440 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
2437 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward);2441 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward);
...@@ -2478,14 +2482,11 @@ pub fn genDecl(o: *Object) !void {...@@ -2478,14 +2482,11 @@ pub fn genDecl(o: *Object) !void {
2478 try fwd_decl_writer.writeAll(";\n");2482 try fwd_decl_writer.writeAll(";\n");
2479 } else if (tv.val.castTag(.variable)) |var_payload| {2483 } else if (tv.val.castTag(.variable)) |var_payload| {
2480 const variable: *Module.Var = var_payload.data;2484 const variable: *Module.Var = var_payload.data;
2485
2481 const is_global = o.dg.declIsGlobal(tv) or variable.is_extern;2486 const is_global = o.dg.declIsGlobal(tv) or variable.is_extern;
2482 const fwd_decl_writer = o.dg.fwd_decl.writer();2487 const fwd_decl_writer = o.dg.fwd_decl.writer();
24832488
2484 const decl_c_value: CValue = if (is_global) .{2489 const decl_c_value = CValue{ .decl = o.dg.decl_index };
2485 .bytes = mem.span(o.dg.decl.name),
2486 } else .{
2487 .decl = o.dg.decl_index,
2488 };
24892490
2490 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");2491 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
2491 if (variable.is_threadlocal) try fwd_decl_writer.writeAll("zig_threadlocal ");2492 if (variable.is_threadlocal) try fwd_decl_writer.writeAll("zig_threadlocal ");
src/link/C.zig+20-6
...@@ -290,9 +290,17 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)...@@ -290,9 +290,17 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
290 f.remaining_decls.putAssumeCapacityNoClobber(decl_index, {});290 f.remaining_decls.putAssumeCapacityNoClobber(decl_index, {});
291 }291 }
292292
293 while (f.remaining_decls.popOrNull()) |kv| {293 {
294 const decl_index = kv.key;294 var export_names = std.StringHashMapUnmanaged(void){};
295 try self.flushDecl(&f, decl_index);295 defer export_names.deinit(gpa);
296 try export_names.ensureTotalCapacity(gpa, @intCast(u32, module.decl_exports.entries.len));
297 for (module.decl_exports.values()) |exports| for (exports.items) |@"export"|
298 try export_names.put(gpa, @"export".options.name, {});
299
300 while (f.remaining_decls.popOrNull()) |kv| {
301 const decl_index = kv.key;
302 try self.flushDecl(&f, decl_index, export_names);
303 }
296 }304 }
297305
298 f.all_buffers.items[typedef_index] = .{306 f.all_buffers.items[typedef_index] = .{
...@@ -415,7 +423,12 @@ fn flushErrDecls(self: *C, f: *Flush) FlushDeclError!void {...@@ -415,7 +423,12 @@ fn flushErrDecls(self: *C, f: *Flush) FlushDeclError!void {
415}423}
416424
417/// Assumes `decl` was in the `remaining_decls` set, and has already been removed.425/// Assumes `decl` was in the `remaining_decls` set, and has already been removed.
418fn flushDecl(self: *C, f: *Flush, decl_index: Module.Decl.Index) FlushDeclError!void {426fn flushDecl(
427 self: *C,
428 f: *Flush,
429 decl_index: Module.Decl.Index,
430 export_names: std.StringHashMapUnmanaged(void),
431) FlushDeclError!void {
419 const module = self.base.options.module.?;432 const module = self.base.options.module.?;
420 const decl = module.declPtr(decl_index);433 const decl = module.declPtr(decl_index);
421 // Before flushing any particular Decl we must ensure its434 // Before flushing any particular Decl we must ensure its
...@@ -423,7 +436,7 @@ fn flushDecl(self: *C, f: *Flush, decl_index: Module.Decl.Index) FlushDeclError!...@@ -423,7 +436,7 @@ fn flushDecl(self: *C, f: *Flush, decl_index: Module.Decl.Index) FlushDeclError!
423 // file comes out correctly.436 // file comes out correctly.
424 for (decl.dependencies.keys()) |dep| {437 for (decl.dependencies.keys()) |dep| {
425 if (f.remaining_decls.swapRemove(dep)) {438 if (f.remaining_decls.swapRemove(dep)) {
426 try flushDecl(self, f, dep);439 try flushDecl(self, f, dep, export_names);
427 }440 }
428 }441 }
429442
...@@ -432,7 +445,8 @@ fn flushDecl(self: *C, f: *Flush, decl_index: Module.Decl.Index) FlushDeclError!...@@ -432,7 +445,8 @@ fn flushDecl(self: *C, f: *Flush, decl_index: Module.Decl.Index) FlushDeclError!
432445
433 try self.flushTypedefs(f, decl_block.typedefs);446 try self.flushTypedefs(f, decl_block.typedefs);
434 try f.all_buffers.ensureUnusedCapacity(gpa, 2);447 try f.all_buffers.ensureUnusedCapacity(gpa, 2);
435 f.appendBufAssumeCapacity(decl_block.fwd_decl.items);448 if (!(decl.isExtern() and export_names.contains(mem.span(decl.name))))
449 f.appendBufAssumeCapacity(decl_block.fwd_decl.items);
436}450}
437451
438pub fn flushEmitH(module: *Module) !void {452pub fn flushEmitH(module: *Module) !void {
test/behavior/basic.zig-1
...@@ -788,7 +788,6 @@ test "extern variable with non-pointer opaque type" {...@@ -788,7 +788,6 @@ test "extern variable with non-pointer opaque type" {
788 return error.SkipZigTest;788 return error.SkipZigTest;
789 }789 }
790 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO790 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
791 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
792 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO791 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
793 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO792 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
794 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO793 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/behavior/bugs/529.zig-1
...@@ -11,7 +11,6 @@ comptime {...@@ -11,7 +11,6 @@ comptime {
11const builtin = @import("builtin");11const builtin = @import("builtin");
1212
13test "issue 529 fixed" {13test "issue 529 fixed" {
14 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
15 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO14 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
16 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO15 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
17 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO16 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO