| ... | ... | @@ -698,17 +698,27 @@ pub const Object = struct { |
| 698 | 698 | indent_counter: usize, |
| 699 | 699 | |
| 700 | 700 | const indent_width = 1; |
| 701 | const indent_char = ' '; |
| 701 | 702 | |
| 702 | 703 | fn newline(o: *Object) !void { |
| 703 | 704 | const bw = &o.code.buffered_writer; |
| 704 | 705 | try bw.writeByte('\n'); |
| 705 | | try bw.splatByteAll(' ', o.indent_counter); |
| 706 | try bw.splatByteAll(indent_char, o.indent_counter); |
| 706 | 707 | } |
| 707 | 708 | fn indent(o: *Object) void { |
| 708 | 709 | o.indent_counter += indent_width; |
| 709 | 710 | } |
| 710 | | fn outdent(o: *Object) void { |
| 711 | fn outdent(o: *Object) !void { |
| 711 | 712 | o.indent_counter -= indent_width; |
| 713 | const written = o.code.getWritten(); |
| 714 | switch (written[written.len - 1]) { |
| 715 | indent_char => o.code.shrinkRetainingCapacity(written.len - indent_width), |
| 716 | '\n' => try o.code.buffered_writer.splatByteAll(indent_char, o.indent_counter), |
| 717 | else => { |
| 718 | std.debug.print("\"{f}\"\n", .{std.zig.fmtEscapes(written[written.len -| 100..])}); |
| 719 | unreachable; |
| 720 | }, |
| 721 | } |
| 712 | 722 | } |
| 713 | 723 | }; |
| 714 | 724 | |
| ... | ... | @@ -1041,7 +1051,7 @@ pub const DeclGen = struct { |
| 1041 | 1051 | .error_union => |error_union| switch (ctype.info(ctype_pool)) { |
| 1042 | 1052 | .basic => switch (error_union.val) { |
| 1043 | 1053 | .err_name => |err_name| try dg.renderErrorName(writer, err_name), |
| 1044 | | .payload => try writer.writeAll("0"), |
| 1054 | .payload => try writer.writeByte('0'), |
| 1045 | 1055 | }, |
| 1046 | 1056 | .pointer, .aligned, .array, .vector, .fwd_decl, .function => unreachable, |
| 1047 | 1057 | .aggregate => |aggregate| { |
| ... | ... | @@ -1197,7 +1207,7 @@ pub const DeclGen = struct { |
| 1197 | 1207 | .none => "true", |
| 1198 | 1208 | else => "false", |
| 1199 | 1209 | }) else switch (opt.val) { |
| 1200 | | .none => try writer.writeAll("0"), |
| 1210 | .none => try writer.writeByte('0'), |
| 1201 | 1211 | else => |payload| switch (ip.indexToKey(payload)) { |
| 1202 | 1212 | .undef => |err_ty| try dg.renderUndefValue( |
| 1203 | 1213 | writer, |
| ... | ... | @@ -1528,7 +1538,7 @@ pub const DeclGen = struct { |
| 1528 | 1538 | try writer.writeByte(')'); |
| 1529 | 1539 | } |
| 1530 | 1540 | try dg.renderValue(writer, Value.fromInterned(un.val), location); |
| 1531 | | } else try writer.writeAll("0"); |
| 1541 | } else try writer.writeByte('0'); |
| 1532 | 1542 | return; |
| 1533 | 1543 | } |
| 1534 | 1544 | |
| ... | ... | @@ -2786,7 +2796,7 @@ pub fn genErrDecls(o: *Object) Error!void { |
| 2786 | 2796 | try bw.print(" = {d}u,", .{value}); |
| 2787 | 2797 | try o.newline(); |
| 2788 | 2798 | } |
| 2789 | | o.outdent(); |
| 2799 | try o.outdent(); |
| 2790 | 2800 | try bw.writeAll("};"); |
| 2791 | 2801 | try o.newline(); |
| 2792 | 2802 | } |
| ... | ... | @@ -2895,6 +2905,7 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn |
| 2895 | 2905 | try bw.print("case {f}: {{", .{ |
| 2896 | 2906 | try o.dg.fmtIntLiteral(try tag_val.intFromEnum(enum_ty, pt), .Other), |
| 2897 | 2907 | }); |
| 2908 | o.indent(); |
| 2898 | 2909 | try o.newline(); |
| 2899 | 2910 | try bw.writeAll("static "); |
| 2900 | 2911 | try o.dg.renderTypeAndName(bw, name_ty, .{ .identifier = "name" }, Const, .none, .complete); |
| ... | ... | @@ -2909,16 +2920,15 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn |
| 2909 | 2920 | try o.dg.fmtIntLiteral(try pt.intValue(.usize, tag_name_len), .Other), |
| 2910 | 2921 | }); |
| 2911 | 2922 | try o.newline(); |
| 2912 | | |
| 2923 | try o.outdent(); |
| 2913 | 2924 | try bw.writeByte('}'); |
| 2914 | 2925 | try o.newline(); |
| 2915 | 2926 | } |
| 2927 | try o.outdent(); |
| 2916 | 2928 | try bw.writeByte('}'); |
| 2917 | 2929 | try o.newline(); |
| 2918 | | try bw.writeAll("while ("); |
| 2919 | | try o.dg.renderValue(bw, Value.true, .Other); |
| 2920 | | try bw.writeAll(") "); |
| 2921 | | _ = try airBreakpoint(o, bw); |
| 2930 | try airUnreach(o); |
| 2931 | try o.outdent(); |
| 2922 | 2932 | try bw.writeByte('}'); |
| 2923 | 2933 | try o.newline(); |
| 2924 | 2934 | }, |
| ... | ... | @@ -2940,6 +2950,7 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn |
| 2940 | 2950 | .fmt_ctype_pool_string = fn_name, |
| 2941 | 2951 | }); |
| 2942 | 2952 | try bw.writeAll(" {"); |
| 2953 | o.indent(); |
| 2943 | 2954 | try o.newline(); |
| 2944 | 2955 | try bw.writeAll("return "); |
| 2945 | 2956 | try o.dg.renderNavName(bw, fn_nav_index); |
| ... | ... | @@ -2950,6 +2961,7 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn |
| 2950 | 2961 | } |
| 2951 | 2962 | try bw.writeAll(");"); |
| 2952 | 2963 | try o.newline(); |
| 2964 | try o.outdent(); |
| 2953 | 2965 | try bw.writeByte('}'); |
| 2954 | 2966 | try o.newline(); |
| 2955 | 2967 | }, |
| ... | ... | @@ -3066,7 +3078,10 @@ fn genFunc(f: *Function) !void { |
| 3066 | 3078 | f.free_locals_map.clearRetainingCapacity(); |
| 3067 | 3079 | |
| 3068 | 3080 | const main_body = f.air.getMainBody(); |
| 3069 | | try genBodyResolveState(f, undefined, &.{}, main_body, false); |
| 3081 | o.indent(); |
| 3082 | try genBodyResolveState(f, undefined, &.{}, main_body, true); |
| 3083 | try o.outdent(); |
| 3084 | try o.code.buffered_writer.writeByte('}'); |
| 3070 | 3085 | try o.newline(); |
| 3071 | 3086 | if (o.dg.expected_block) |_| |
| 3072 | 3087 | return f.fail("runtime code not allowed in naked function", .{}); |
| ... | ... | @@ -3285,11 +3300,11 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) Error!void { |
| 3285 | 3300 | if (body.len == 0) { |
| 3286 | 3301 | try bw.writeAll("{}"); |
| 3287 | 3302 | } else { |
| 3288 | | try bw.writeAll("{"); |
| 3303 | try bw.writeByte('{'); |
| 3289 | 3304 | f.object.indent(); |
| 3290 | 3305 | try f.object.newline(); |
| 3291 | 3306 | try genBodyInner(f, body); |
| 3292 | | f.object.outdent(); |
| 3307 | try f.object.outdent(); |
| 3293 | 3308 | try bw.writeByte('}'); |
| 3294 | 3309 | } |
| 3295 | 3310 | } |
| ... | ... | @@ -3367,7 +3382,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void { |
| 3367 | 3382 | |
| 3368 | 3383 | .arg => try airArg(f, inst), |
| 3369 | 3384 | |
| 3370 | | .breakpoint => try airBreakpoint(&f.object, &f.object.code.buffered_writer), |
| 3385 | .breakpoint => try airBreakpoint(f), |
| 3371 | 3386 | .ret_addr => try airRetAddr(f, inst), |
| 3372 | 3387 | .frame_addr => try airFrameAddress(f, inst), |
| 3373 | 3388 | |
| ... | ... | @@ -3621,7 +3636,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void { |
| 3621 | 3636 | .ret_safe => return airRet(f, inst, false), // TODO |
| 3622 | 3637 | .ret_load => return airRet(f, inst, true), |
| 3623 | 3638 | .trap => return airTrap(f, &f.object.code.buffered_writer), |
| 3624 | | .unreach => return airUnreach(f), |
| 3639 | .unreach => return airUnreach(&f.object), |
| 3625 | 3640 | |
| 3626 | 3641 | // Instructions which may be `noreturn`. |
| 3627 | 3642 | .block => res: { |
| ... | ... | @@ -4017,18 +4032,14 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void { |
| 4017 | 4032 | try f.writeCValueDeref(bw, ret_val) |
| 4018 | 4033 | else |
| 4019 | 4034 | try f.writeCValue(bw, ret_val, .Other); |
| 4020 | | try bw.writeByte(';'); |
| 4021 | | try f.object.newline(); |
| 4035 | try bw.writeAll(";\n"); |
| 4022 | 4036 | if (is_array) { |
| 4023 | 4037 | try freeLocal(f, inst, ret_val.new_local, null); |
| 4024 | 4038 | } |
| 4025 | 4039 | } else { |
| 4026 | 4040 | try reap(f, inst, &.{un_op}); |
| 4027 | 4041 | // Not even allowed to return void in a naked function. |
| 4028 | | if (!f.object.dg.is_naked_fn) { |
| 4029 | | try bw.writeAll("return;"); |
| 4030 | | try f.object.newline(); |
| 4031 | | } |
| 4042 | if (!f.object.dg.is_naked_fn) try bw.writeAll("return;\n"); |
| 4032 | 4043 | } |
| 4033 | 4044 | } |
| 4034 | 4045 | |
| ... | ... | @@ -4817,7 +4828,10 @@ fn airCall( |
| 4817 | 4828 | try f.freeCValue(inst, resolved_arg); |
| 4818 | 4829 | } |
| 4819 | 4830 | try bw.writeAll(");"); |
| 4820 | | try f.object.newline(); |
| 4831 | switch (modifier) { |
| 4832 | .always_tail => try bw.writeByte('\n'), |
| 4833 | else => try f.object.newline(), |
| 4834 | } |
| 4821 | 4835 | |
| 4822 | 4836 | const result = result: { |
| 4823 | 4837 | if (result_local == .none or !lowersToArray(ret_ty, pt)) |
| ... | ... | @@ -4925,8 +4939,6 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) |
| 4925 | 4939 | try die(f, inst, death.toRef()); |
| 4926 | 4940 | } |
| 4927 | 4941 | |
| 4928 | | try f.object.newline(); |
| 4929 | | |
| 4930 | 4942 | // noreturn blocks have no `br` instructions reaching them, so we don't want a label |
| 4931 | 4943 | if (f.object.dg.is_naked_fn) { |
| 4932 | 4944 | if (f.object.dg.expected_block) |expected_block| { |
| ... | ... | @@ -4936,7 +4948,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) |
| 4936 | 4948 | } |
| 4937 | 4949 | } else if (!f.typeOfIndex(inst).isNoReturn(zcu)) { |
| 4938 | 4950 | // label must be followed by an expression, include an empty one. |
| 4939 | | try bw.print("zig_block_{d}:;", .{block_id}); |
| 4951 | try bw.print("\nzig_block_{d}:;", .{block_id}); |
| 4940 | 4952 | try f.object.newline(); |
| 4941 | 4953 | } |
| 4942 | 4954 | |
| ... | ... | @@ -5057,14 +5069,12 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !void { |
| 5057 | 5069 | try a.end(f, bw); |
| 5058 | 5070 | } |
| 5059 | 5071 | |
| 5060 | | try bw.print("goto zig_block_{d};", .{block.block_id}); |
| 5061 | | try f.object.newline(); |
| 5072 | try bw.print("goto zig_block_{d};\n", .{block.block_id}); |
| 5062 | 5073 | } |
| 5063 | 5074 | |
| 5064 | 5075 | fn airRepeat(f: *Function, inst: Air.Inst.Index) !void { |
| 5065 | 5076 | const repeat = f.air.instructions.items(.data)[@intFromEnum(inst)].repeat; |
| 5066 | | try f.object.code.buffered_writer.print("goto zig_loop_{d};", .{@intFromEnum(repeat.loop_inst)}); |
| 5067 | | try f.object.newline(); |
| 5077 | try f.object.code.buffered_writer.print("goto zig_loop_{d};\n", .{@intFromEnum(repeat.loop_inst)}); |
| 5068 | 5078 | } |
| 5069 | 5079 | |
| 5070 | 5080 | fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void { |
| ... | ... | @@ -5093,8 +5103,7 @@ fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void { |
| 5093 | 5103 | } |
| 5094 | 5104 | } |
| 5095 | 5105 | } else switch_br.cases_len; |
| 5096 | | try bw.print("goto zig_switch_{d}_dispatch_{d};", .{ @intFromEnum(br.block_inst), target_case_idx }); |
| 5097 | | try f.object.newline(); |
| 5106 | try bw.print("goto zig_switch_{d}_dispatch_{d};\n", .{ @intFromEnum(br.block_inst), target_case_idx }); |
| 5098 | 5107 | return; |
| 5099 | 5108 | } |
| 5100 | 5109 | |
| ... | ... | @@ -5106,7 +5115,7 @@ fn airSwitchDispatch(f: *Function, inst: Air.Inst.Index) !void { |
| 5106 | 5115 | try f.writeCValue(bw, cond, .Other); |
| 5107 | 5116 | try bw.writeByte(';'); |
| 5108 | 5117 | try f.object.newline(); |
| 5109 | | try bw.print("goto zig_switch_{d}_loop;", .{@intFromEnum(br.block_inst)}); |
| 5118 | try bw.print("goto zig_switch_{d}_loop;\n", .{@intFromEnum(br.block_inst)}); |
| 5110 | 5119 | } |
| 5111 | 5120 | |
| 5112 | 5121 | fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { |
| ... | ... | @@ -5241,13 +5250,13 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CVal |
| 5241 | 5250 | fn airTrap(f: *Function, bw: *std.io.BufferedWriter) !void { |
| 5242 | 5251 | // Not even allowed to call trap in a naked function. |
| 5243 | 5252 | if (f.object.dg.is_naked_fn) return; |
| 5244 | | try bw.writeAll("zig_trap();"); |
| 5245 | | try f.object.newline(); |
| 5253 | try bw.writeAll("zig_trap();\n"); |
| 5246 | 5254 | } |
| 5247 | 5255 | |
| 5248 | | fn airBreakpoint(o: *Object, bw: *std.io.BufferedWriter) !CValue { |
| 5256 | fn airBreakpoint(f: *Function) !CValue { |
| 5257 | const bw = &f.object.code.buffered_writer; |
| 5249 | 5258 | try bw.writeAll("zig_breakpoint();"); |
| 5250 | | try o.newline(); |
| 5259 | try f.object.newline(); |
| 5251 | 5260 | return .none; |
| 5252 | 5261 | } |
| 5253 | 5262 | |
| ... | ... | @@ -5273,11 +5282,10 @@ fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5273 | 5282 | return local; |
| 5274 | 5283 | } |
| 5275 | 5284 | |
| 5276 | | fn airUnreach(f: *Function) !void { |
| 5285 | fn airUnreach(o: *Object) !void { |
| 5277 | 5286 | // Not even allowed to call unreachable in a naked function. |
| 5278 | | if (f.object.dg.is_naked_fn) return; |
| 5279 | | try f.object.code.buffered_writer.writeAll("zig_unreachable();"); |
| 5280 | | try f.object.newline(); |
| 5287 | if (o.dg.is_naked_fn) return; |
| 5288 | try o.code.buffered_writer.writeAll("zig_unreachable();\n"); |
| 5281 | 5289 | } |
| 5282 | 5290 | |
| 5283 | 5291 | fn airLoop(f: *Function, inst: Air.Inst.Index) !void { |
| ... | ... | @@ -5407,10 +5415,11 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void |
| 5407 | 5415 | f.object.indent(); |
| 5408 | 5416 | try f.object.newline(); |
| 5409 | 5417 | if (is_dispatch_loop) { |
| 5410 | | try bw.print("zig_switch_{d}_dispatch_{d}: ", .{ @intFromEnum(inst), case.idx }); |
| 5418 | try bw.print("zig_switch_{d}_dispatch_{d}:;", .{ @intFromEnum(inst), case.idx }); |
| 5419 | try f.object.newline(); |
| 5411 | 5420 | } |
| 5412 | 5421 | try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true); |
| 5413 | | f.object.outdent(); |
| 5422 | try f.object.outdent(); |
| 5414 | 5423 | try bw.writeByte('}'); |
| 5415 | 5424 | if (f.object.dg.expected_block) |_| |
| 5416 | 5425 | return f.fail("runtime code not allowed in naked function", .{}); |
| ... | ... | @@ -5456,7 +5465,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void |
| 5456 | 5465 | try bw.print("zig_switch_{d}_dispatch_{d}: ", .{ @intFromEnum(inst), case.idx }); |
| 5457 | 5466 | } |
| 5458 | 5467 | try genBodyResolveState(f, inst, liveness.deaths[case.idx], case.body, true); |
| 5459 | | f.object.outdent(); |
| 5468 | try f.object.outdent(); |
| 5460 | 5469 | try bw.writeByte('}'); |
| 5461 | 5470 | if (f.object.dg.expected_block) |_| |
| 5462 | 5471 | return f.fail("runtime code not allowed in naked function", .{}); |
| ... | ... | @@ -5474,14 +5483,10 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index, is_dispatch_loop: bool) !void |
| 5474 | 5483 | try genBody(f, else_body); |
| 5475 | 5484 | if (f.object.dg.expected_block) |_| |
| 5476 | 5485 | return f.fail("runtime code not allowed in naked function", .{}); |
| 5477 | | } else { |
| 5478 | | try bw.writeAll("zig_unreachable();"); |
| 5479 | | } |
| 5480 | | try f.object.newline(); |
| 5481 | | |
| 5482 | | f.object.outdent(); |
| 5483 | | try bw.writeByte('}'); |
| 5486 | } else try airUnreach(&f.object); |
| 5484 | 5487 | try f.object.newline(); |
| 5488 | try f.object.outdent(); |
| 5489 | try bw.writeAll("}\n"); |
| 5485 | 5490 | } |
| 5486 | 5491 | |
| 5487 | 5492 | fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool { |
| ... | ... | @@ -6868,7 +6873,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 6868 | 6873 | try bw.writeAll("NULL"); |
| 6869 | 6874 | try a.end(f, bw); |
| 6870 | 6875 | } |
| 6871 | | f.object.outdent(); |
| 6876 | try f.object.outdent(); |
| 6872 | 6877 | try bw.writeByte('}'); |
| 6873 | 6878 | try f.object.newline(); |
| 6874 | 6879 | } else { |
| ... | ... | @@ -8119,6 +8124,7 @@ fn compareOperatorC(operator: std.math.CompareOperator) []const u8 { |
| 8119 | 8124 | const StringLiteral = struct { |
| 8120 | 8125 | len: usize, |
| 8121 | 8126 | cur_len: usize, |
| 8127 | start_count: usize, |
| 8122 | 8128 | bw: *std.io.BufferedWriter, |
| 8123 | 8129 | |
| 8124 | 8130 | // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal, |
| ... | ... | @@ -8136,6 +8142,7 @@ const StringLiteral = struct { |
| 8136 | 8142 | return .{ |
| 8137 | 8143 | .cur_len = 0, |
| 8138 | 8144 | .len = len, |
| 8145 | .start_count = bw.count, |
| 8139 | 8146 | .bw = bw, |
| 8140 | 8147 | }; |
| 8141 | 8148 | } |
| ... | ... | @@ -8175,7 +8182,7 @@ const StringLiteral = struct { |
| 8175 | 8182 | |
| 8176 | 8183 | pub fn writeChar(sl: *StringLiteral, c: u8) std.io.Writer.Error!void { |
| 8177 | 8184 | if (sl.len <= max_string_initializer_len) { |
| 8178 | | if (sl.cur_len == 0 and sl.bw.count > 1) |
| 8185 | if (sl.cur_len == 0 and sl.bw.count - sl.start_count > 1) |
| 8179 | 8186 | try sl.bw.writeAll("\"\""); |
| 8180 | 8187 | |
| 8181 | 8188 | const count = sl.bw.count; |
| ... | ... | @@ -8186,7 +8193,7 @@ const StringLiteral = struct { |
| 8186 | 8193 | |
| 8187 | 8194 | if (sl.cur_len >= max_literal_len) sl.cur_len = 0; |
| 8188 | 8195 | } else { |
| 8189 | | if (sl.bw.count > 1) try sl.bw.writeByte(','); |
| 8196 | if (sl.bw.count - sl.start_count > 1) try sl.bw.writeByte(','); |
| 8190 | 8197 | try sl.bw.print("'\\x{x}'", .{c}); |
| 8191 | 8198 | } |
| 8192 | 8199 | } |
| ... | ... | @@ -8502,7 +8509,7 @@ const Vectorize = struct { |
| 8502 | 8509 | |
| 8503 | 8510 | pub fn end(self: Vectorize, f: *Function, inst: Air.Inst.Index, bw: *std.io.BufferedWriter) !void { |
| 8504 | 8511 | if (self.index != .none) { |
| 8505 | | f.object.outdent(); |
| 8512 | try f.object.outdent(); |
| 8506 | 8513 | try bw.writeByte('}'); |
| 8507 | 8514 | try f.object.newline(); |
| 8508 | 8515 | try freeLocal(f, inst, self.index.new_local, null); |