| ... | @@ -306,7 +306,7 @@ pub const Function = struct { | ... | @@ -306,7 +306,7 @@ pub const Function = struct { |
| 306 | const ty = f.typeOf(ref); | 306 | const ty = f.typeOf(ref); |
| 307 | | 307 | |
| 308 | const result: CValue = if (lowersToArray(ty, mod)) result: { | 308 | const result: CValue = if (lowersToArray(ty, mod)) result: { |
| 309 | const writer = f.object.code_header.writer(); | 309 | const writer = f.object.codeHeaderWriter(); |
| 310 | const alignment: Alignment = .none; | 310 | const alignment: Alignment = .none; |
| 311 | const decl_c_value = try f.allocLocalValue(ty, alignment); | 311 | const decl_c_value = try f.allocLocalValue(ty, alignment); |
| 312 | const gpa = f.object.dg.gpa; | 312 | const gpa = f.object.dg.gpa; |
| ... | @@ -534,6 +534,10 @@ pub const Object = struct { | ... | @@ -534,6 +534,10 @@ pub const Object = struct { |
| 534 | fn writer(o: *Object) IndentWriter(std.ArrayList(u8).Writer).Writer { | 534 | fn writer(o: *Object) IndentWriter(std.ArrayList(u8).Writer).Writer { |
| 535 | return o.indent_writer.writer(); | 535 | return o.indent_writer.writer(); |
| 536 | } | 536 | } |
| | 537 | |
| | 538 | fn codeHeaderWriter(o: *Object) ArrayListWriter { |
| | 539 | return arrayListWriter(&o.code_header); |
| | 540 | } |
| 537 | }; | 541 | }; |
| 538 | | 542 | |
| 539 | /// This data is available both when outputting .c code and when outputting an .h file. | 543 | /// This data is available both when outputting .c code and when outputting an .h file. |
| ... | @@ -557,6 +561,10 @@ pub const DeclGen = struct { | ... | @@ -557,6 +561,10 @@ pub const DeclGen = struct { |
| 557 | flush, | 561 | flush, |
| 558 | }; | 562 | }; |
| 559 | | 563 | |
| | 564 | fn fwdDeclWriter(dg: *DeclGen) ArrayListWriter { |
| | 565 | return arrayListWriter(&dg.fwd_decl); |
| | 566 | } |
| | 567 | |
| 560 | fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { | 568 | fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { |
| 561 | @setCold(true); | 569 | @setCold(true); |
| 562 | const mod = dg.module; | 570 | const mod = dg.module; |
| ... | @@ -1997,7 +2005,7 @@ pub const DeclGen = struct { | ... | @@ -1997,7 +2005,7 @@ pub const DeclGen = struct { |
| 1997 | fwd_kind: enum { tentative, final }, | 2005 | fwd_kind: enum { tentative, final }, |
| 1998 | ) !void { | 2006 | ) !void { |
| 1999 | const decl = dg.module.declPtr(decl_index); | 2007 | const decl = dg.module.declPtr(decl_index); |
| 2000 | const fwd = dg.fwd_decl.writer(); | 2008 | const fwd = dg.fwdDeclWriter(); |
| 2001 | const is_global = variable.is_extern or dg.declIsGlobal(.{ .ty = decl.ty, .val = decl.val }); | 2009 | const is_global = variable.is_extern or dg.declIsGlobal(.{ .ty = decl.ty, .val = decl.val }); |
| 2002 | try fwd.writeAll(if (is_global) "zig_extern " else "static "); | 2010 | try fwd.writeAll(if (is_global) "zig_extern " else "static "); |
| 2003 | const maybe_exports = dg.module.decl_exports.get(decl_index); | 2011 | const maybe_exports = dg.module.decl_exports.get(decl_index); |
| ... | @@ -2683,7 +2691,7 @@ fn genExports(o: *Object) !void { | ... | @@ -2683,7 +2691,7 @@ fn genExports(o: *Object) !void { |
| 2683 | }; | 2691 | }; |
| 2684 | const decl = mod.declPtr(decl_index); | 2692 | const decl = mod.declPtr(decl_index); |
| 2685 | const tv: TypedValue = .{ .ty = decl.ty, .val = Value.fromInterned((try decl.internValue(mod))) }; | 2693 | const tv: TypedValue = .{ .ty = decl.ty, .val = Value.fromInterned((try decl.internValue(mod))) }; |
| 2686 | const fwd = o.dg.fwd_decl.writer(); | 2694 | const fwd = o.dg.fwdDeclWriter(); |
| 2687 | | 2695 | |
| 2688 | const exports = mod.decl_exports.get(decl_index) orelse return; | 2696 | const exports = mod.decl_exports.get(decl_index) orelse return; |
| 2689 | if (exports.items.len < 2) return; | 2697 | if (exports.items.len < 2) return; |
| ... | @@ -2797,7 +2805,7 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { | ... | @@ -2797,7 +2805,7 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { |
| 2797 | const fn_cty = try o.dg.typeToCType(fn_decl.ty, .complete); | 2805 | const fn_cty = try o.dg.typeToCType(fn_decl.ty, .complete); |
| 2798 | const fn_info = fn_cty.cast(CType.Payload.Function).?.data; | 2806 | const fn_info = fn_cty.cast(CType.Payload.Function).?.data; |
| 2799 | | 2807 | |
| 2800 | const fwd_decl_writer = o.dg.fwd_decl.writer(); | 2808 | const fwd_decl_writer = o.dg.fwdDeclWriter(); |
| 2801 | try fwd_decl_writer.print("static zig_{s} ", .{@tagName(key)}); | 2809 | try fwd_decl_writer.print("static zig_{s} ", .{@tagName(key)}); |
| 2802 | try o.dg.renderFunctionSignature( | 2810 | try o.dg.renderFunctionSignature( |
| 2803 | fwd_decl_writer, | 2811 | fwd_decl_writer, |
| ... | @@ -2839,7 +2847,7 @@ pub fn genFunc(f: *Function) !void { | ... | @@ -2839,7 +2847,7 @@ pub fn genFunc(f: *Function) !void { |
| 2839 | defer o.code_header.deinit(); | 2847 | defer o.code_header.deinit(); |
| 2840 | | 2848 | |
| 2841 | const is_global = o.dg.declIsGlobal(tv); | 2849 | const is_global = o.dg.declIsGlobal(tv); |
| 2842 | const fwd_decl_writer = o.dg.fwd_decl.writer(); | 2850 | const fwd_decl_writer = o.dg.fwdDeclWriter(); |
| 2843 | try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); | 2851 | try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); |
| 2844 | | 2852 | |
| 2845 | if (mod.decl_exports.get(decl_index)) |exports| | 2853 | if (mod.decl_exports.get(decl_index)) |exports| |
| ... | @@ -2894,7 +2902,7 @@ pub fn genFunc(f: *Function) !void { | ... | @@ -2894,7 +2902,7 @@ pub fn genFunc(f: *Function) !void { |
| 2894 | }; | 2902 | }; |
| 2895 | free_locals.sort(SortContext{ .keys = free_locals.keys() }); | 2903 | free_locals.sort(SortContext{ .keys = free_locals.keys() }); |
| 2896 | | 2904 | |
| 2897 | const w = o.code_header.writer(); | 2905 | const w = o.codeHeaderWriter(); |
| 2898 | for (free_locals.values()) |list| { | 2906 | for (free_locals.values()) |list| { |
| 2899 | for (list.keys()) |local_index| { | 2907 | for (list.keys()) |local_index| { |
| 2900 | const local = f.locals.items[local_index]; | 2908 | const local = f.locals.items[local_index]; |
| ... | @@ -2922,7 +2930,7 @@ pub fn genDecl(o: *Object) !void { | ... | @@ -2922,7 +2930,7 @@ pub fn genDecl(o: *Object) !void { |
| 2922 | | 2930 | |
| 2923 | if (!tv.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return; | 2931 | if (!tv.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return; |
| 2924 | if (tv.val.getExternFunc(mod)) |_| { | 2932 | if (tv.val.getExternFunc(mod)) |_| { |
| 2925 | const fwd_decl_writer = o.dg.fwd_decl.writer(); | 2933 | const fwd_decl_writer = o.dg.fwdDeclWriter(); |
| 2926 | try fwd_decl_writer.writeAll("zig_extern "); | 2934 | try fwd_decl_writer.writeAll("zig_extern "); |
| 2927 | try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 }); | 2935 | try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 }); |
| 2928 | try fwd_decl_writer.writeAll(";\n"); | 2936 | try fwd_decl_writer.writeAll(";\n"); |
| ... | @@ -2963,7 +2971,7 @@ pub fn genDeclValue( | ... | @@ -2963,7 +2971,7 @@ pub fn genDeclValue( |
| 2963 | link_section: InternPool.OptionalNullTerminatedString, | 2971 | link_section: InternPool.OptionalNullTerminatedString, |
| 2964 | ) !void { | 2972 | ) !void { |
| 2965 | const mod = o.dg.module; | 2973 | const mod = o.dg.module; |
| 2966 | const fwd_decl_writer = o.dg.fwd_decl.writer(); | 2974 | const fwd_decl_writer = o.dg.fwdDeclWriter(); |
| 2967 | | 2975 | |
| 2968 | try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); | 2976 | try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); |
| 2969 | try o.dg.renderTypeAndName(fwd_decl_writer, tv.ty, decl_c_value, Const, alignment, .complete); | 2977 | try o.dg.renderTypeAndName(fwd_decl_writer, tv.ty, decl_c_value, Const, alignment, .complete); |
| ... | @@ -3007,7 +3015,7 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { | ... | @@ -3007,7 +3015,7 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { |
| 3007 | .ty = decl.ty, | 3015 | .ty = decl.ty, |
| 3008 | .val = decl.val, | 3016 | .val = decl.val, |
| 3009 | }; | 3017 | }; |
| 3010 | const writer = dg.fwd_decl.writer(); | 3018 | const writer = dg.fwdDeclWriter(); |
| 3011 | | 3019 | |
| 3012 | switch (tv.ty.zigTypeTag(mod)) { | 3020 | switch (tv.ty.zigTypeTag(mod)) { |
| 3013 | .Fn => if (dg.declIsGlobal(tv)) { | 3021 | .Fn => if (dg.declIsGlobal(tv)) { |
| ... | @@ -7531,11 +7539,25 @@ fn toAtomicRmwSuffix(order: std.builtin.AtomicRmwOp) []const u8 { | ... | @@ -7531,11 +7539,25 @@ fn toAtomicRmwSuffix(order: std.builtin.AtomicRmwOp) []const u8 { |
| 7531 | }; | 7539 | }; |
| 7532 | } | 7540 | } |
| 7533 | | 7541 | |
| | 7542 | const ArrayListWriter = ErrorOnlyGenericWriter(std.ArrayList(u8).Writer.Error); |
| | 7543 | |
| | 7544 | fn arrayListWriter(list: *std.ArrayList(u8)) ArrayListWriter { |
| | 7545 | return .{ .context = .{ |
| | 7546 | .context = list, |
| | 7547 | .writeFn = struct { |
| | 7548 | fn write(context: *const anyopaque, bytes: []const u8) anyerror!usize { |
| | 7549 | const l: *std.ArrayList(u8) = @alignCast(@constCast(@ptrCast(context))); |
| | 7550 | return l.writer().write(bytes); |
| | 7551 | } |
| | 7552 | }.write, |
| | 7553 | } }; |
| | 7554 | } |
| | 7555 | |
| 7534 | fn IndentWriter(comptime UnderlyingWriter: type) type { | 7556 | fn IndentWriter(comptime UnderlyingWriter: type) type { |
| 7535 | return struct { | 7557 | return struct { |
| 7536 | const Self = @This(); | 7558 | const Self = @This(); |
| 7537 | pub const Error = UnderlyingWriter.Error; | 7559 | pub const Error = UnderlyingWriter.Error; |
| 7538 | pub const Writer = std.io.Writer(*Self, Error, write); | 7560 | pub const Writer = ErrorOnlyGenericWriter(Error); |
| 7539 | | 7561 | |
| 7540 | pub const indent_delta = 1; | 7562 | pub const indent_delta = 1; |
| 7541 | | 7563 | |
| ... | @@ -7544,7 +7566,10 @@ fn IndentWriter(comptime UnderlyingWriter: type) type { | ... | @@ -7544,7 +7566,10 @@ fn IndentWriter(comptime UnderlyingWriter: type) type { |
| 7544 | current_line_empty: bool = true, | 7566 | current_line_empty: bool = true, |
| 7545 | | 7567 | |
| 7546 | pub fn writer(self: *Self) Writer { | 7568 | pub fn writer(self: *Self) Writer { |
| 7547 | return .{ .context = self }; | 7569 | return .{ .context = .{ |
| | 7570 | .context = self, |
| | 7571 | .writeFn = writeAny, |
| | 7572 | } }; |
| 7548 | } | 7573 | } |
| 7549 | | 7574 | |
| 7550 | pub fn write(self: *Self, bytes: []const u8) Error!usize { | 7575 | pub fn write(self: *Self, bytes: []const u8) Error!usize { |
| ... | @@ -7559,6 +7584,11 @@ fn IndentWriter(comptime UnderlyingWriter: type) type { | ... | @@ -7559,6 +7584,11 @@ fn IndentWriter(comptime UnderlyingWriter: type) type { |
| 7559 | return self.writeNoIndent(bytes); | 7584 | return self.writeNoIndent(bytes); |
| 7560 | } | 7585 | } |
| 7561 | | 7586 | |
| | 7587 | fn writeAny(context: *const anyopaque, bytes: []const u8) anyerror!usize { |
| | 7588 | const self: *Self = @alignCast(@constCast(@ptrCast(context))); |
| | 7589 | return self.write(bytes); |
| | 7590 | } |
| | 7591 | |
| 7562 | pub fn insertNewline(self: *Self) Error!void { | 7592 | pub fn insertNewline(self: *Self) Error!void { |
| 7563 | _ = try self.writeNoIndent("\n"); | 7593 | _ = try self.writeNoIndent("\n"); |
| 7564 | } | 7594 | } |
| ... | @@ -7584,6 +7614,18 @@ fn IndentWriter(comptime UnderlyingWriter: type) type { | ... | @@ -7584,6 +7614,18 @@ fn IndentWriter(comptime UnderlyingWriter: type) type { |
| 7584 | }; | 7614 | }; |
| 7585 | } | 7615 | } |
| 7586 | | 7616 | |
| | 7617 | /// A wrapper around `std.io.AnyWriter` that maintains a generic error set while |
| | 7618 | /// erasing the rest of the implementation. This is intended to avoid duplicate |
| | 7619 | /// generic instantiations for writer types which share the same error set, while |
| | 7620 | /// maintaining ease of error handling. |
| | 7621 | fn ErrorOnlyGenericWriter(comptime Error: type) type { |
| | 7622 | return std.io.GenericWriter(std.io.AnyWriter, Error, struct { |
| | 7623 | fn write(context: std.io.AnyWriter, bytes: []const u8) Error!usize { |
| | 7624 | return @errorCast(context.write(bytes)); |
| | 7625 | } |
| | 7626 | }.write); |
| | 7627 | } |
| | 7628 | |
| 7587 | fn toCIntBits(zig_bits: u32) ?u32 { | 7629 | fn toCIntBits(zig_bits: u32) ?u32 { |
| 7588 | for (&[_]u8{ 8, 16, 32, 64, 128 }) |c_bits| { | 7630 | for (&[_]u8{ 8, 16, 32, 64, 128 }) |c_bits| { |
| 7589 | if (zig_bits <= c_bits) { | 7631 | if (zig_bits <= c_bits) { |