| ... | @@ -62,7 +62,6 @@ const FormatTypeAsCIdentContext = struct { | ... | @@ -62,7 +62,6 @@ const FormatTypeAsCIdentContext = struct { |
| 62 | }; | 62 | }; |
| 63 | | 63 | |
| 64 | const ValueRenderLocation = enum { | 64 | const ValueRenderLocation = enum { |
| 65 | Identifier, | | |
| 66 | FunctionArgument, | 65 | FunctionArgument, |
| 67 | Other, | 66 | Other, |
| 68 | }; | 67 | }; |
| ... | @@ -340,7 +339,7 @@ pub const Function = struct { | ... | @@ -340,7 +339,7 @@ pub const Function = struct { |
| 340 | } | 339 | } |
| 341 | | 340 | |
| 342 | fn fmtIntLiteral(f: *Function, ty: Type, val: Value) !std.fmt.Formatter(formatIntLiteral) { | 341 | fn fmtIntLiteral(f: *Function, ty: Type, val: Value) !std.fmt.Formatter(formatIntLiteral) { |
| 343 | return f.object.dg.fmtIntLiteral(ty, val, .Other); | 342 | return f.object.dg.fmtIntLiteral(ty, val); |
| 344 | } | 343 | } |
| 345 | }; | 344 | }; |
| 346 | | 345 | |
| ... | @@ -533,16 +532,13 @@ pub const DeclGen = struct { | ... | @@ -533,16 +532,13 @@ pub const DeclGen = struct { |
| 533 | // Using '{}' for integer and floats seemed to error C compilers (both GCC and Clang) | 532 | // Using '{}' for integer and floats seemed to error C compilers (both GCC and Clang) |
| 534 | // with 'error: expected expression' (including when built with 'zig cc') | 533 | // with 'error: expected expression' (including when built with 'zig cc') |
| 535 | .Bool => return writer.writeAll("false"), | 534 | .Bool => return writer.writeAll("false"), |
| 536 | .Int, | 535 | .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val)}), |
| 537 | .Enum, | | |
| 538 | .ErrorSet, | | |
| 539 | => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val, location)}), | | |
| 540 | .Float => switch (ty.tag()) { | 536 | .Float => switch (ty.tag()) { |
| 541 | .f32 => return writer.print("zig_bitcast_f32_u32({x})", .{ | 537 | .f32 => return writer.print("zig_bitcast_f32_u32({x})", .{ |
| 542 | try dg.fmtIntLiteral(Type.u32, val, location), | 538 | try dg.fmtIntLiteral(Type.u32, val), |
| 543 | }), | 539 | }), |
| 544 | .f64 => return writer.print("zig_bitcast_f64_u64({x})", .{ | 540 | .f64 => return writer.print("zig_bitcast_f64_u64({x})", .{ |
| 545 | try dg.fmtIntLiteral(Type.u64, val, location), | 541 | try dg.fmtIntLiteral(Type.u64, val), |
| 546 | }), | 542 | }), |
| 547 | else => return dg.fail("TODO float types > 64 bits are not support in renderValue() as of now", .{}), | 543 | else => return dg.fail("TODO float types > 64 bits are not support in renderValue() as of now", .{}), |
| 548 | }, | 544 | }, |
| ... | @@ -554,14 +550,12 @@ pub const DeclGen = struct { | ... | @@ -554,14 +550,12 @@ pub const DeclGen = struct { |
| 554 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | 550 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 555 | const ptr_ty = ty.slicePtrFieldType(&buf); | 551 | const ptr_ty = ty.slicePtrFieldType(&buf); |
| 556 | try dg.renderTypecast(writer, ptr_ty); | 552 | try dg.renderTypecast(writer, ptr_ty); |
| 557 | return writer.print("){x}, {0x}}}", .{ | 553 | return writer.print("){x}, {0x}}}", .{try dg.fmtIntLiteral(Type.usize, val)}); |
| 558 | try dg.fmtIntLiteral(Type.usize, val, location), | | |
| 559 | }); | | |
| 560 | }, | 554 | }, |
| 561 | .Many, .C, .One => { | 555 | .Many, .C, .One => { |
| 562 | try writer.writeAll("(("); | 556 | try writer.writeAll("(("); |
| 563 | try dg.renderTypecast(writer, ty); | 557 | try dg.renderTypecast(writer, ty); |
| 564 | return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, location)}); | 558 | return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val)}); |
| 565 | }, | 559 | }, |
| 566 | }, | 560 | }, |
| 567 | .Optional => { | 561 | .Optional => { |
| ... | @@ -598,9 +592,7 @@ pub const DeclGen = struct { | ... | @@ -598,9 +592,7 @@ pub const DeclGen = struct { |
| 598 | | 592 | |
| 599 | empty = false; | 593 | empty = false; |
| 600 | } | 594 | } |
| 601 | if (empty) try writer.print("{x}", .{ | 595 | if (empty) try writer.print("{x}", .{try dg.fmtIntLiteral(Type.u8, Value.undef)}); |
| 602 | try dg.fmtIntLiteral(Type.u8, Value.undef, location), | | |
| 603 | }); | | |
| 604 | | 596 | |
| 605 | return writer.writeByte('}'); | 597 | return writer.writeByte('}'); |
| 606 | }, | 598 | }, |
| ... | @@ -613,9 +605,7 @@ pub const DeclGen = struct { | ... | @@ -613,9 +605,7 @@ pub const DeclGen = struct { |
| 613 | if (!field.ty.hasRuntimeBits()) continue; | 605 | if (!field.ty.hasRuntimeBits()) continue; |
| 614 | try dg.renderValue(writer, field.ty, val, location); | 606 | try dg.renderValue(writer, field.ty, val, location); |
| 615 | break; | 607 | break; |
| 616 | } else try writer.print("{x}", .{ | 608 | } else try writer.print("{x}", .{try dg.fmtIntLiteral(Type.u8, Value.undef)}); |
| 617 | try dg.fmtIntLiteral(Type.u8, Value.undef, location), | | |
| 618 | }); | | |
| 619 | | 609 | |
| 620 | return writer.writeByte('}'); | 610 | return writer.writeByte('}'); |
| 621 | }, | 611 | }, |
| ... | @@ -625,7 +615,7 @@ pub const DeclGen = struct { | ... | @@ -625,7 +615,7 @@ pub const DeclGen = struct { |
| 625 | try writer.writeAll("){ .payload = "); | 615 | try writer.writeAll("){ .payload = "); |
| 626 | try dg.renderValue(writer, ty.errorUnionPayload(), val, location); | 616 | try dg.renderValue(writer, ty.errorUnionPayload(), val, location); |
| 627 | return writer.print(", .error = {x} }}", .{ | 617 | return writer.print(", .error = {x} }}", .{ |
| 628 | try dg.fmtIntLiteral(ty.errorUnionSet(), Value.undef, location), | 618 | try dg.fmtIntLiteral(ty.errorUnionSet(), Value.undef), |
| 629 | }); | 619 | }); |
| 630 | }, | 620 | }, |
| 631 | .Array => { | 621 | .Array => { |
| ... | @@ -670,7 +660,7 @@ pub const DeclGen = struct { | ... | @@ -670,7 +660,7 @@ pub const DeclGen = struct { |
| 670 | .decl_ref_mut, | 660 | .decl_ref_mut, |
| 671 | .decl_ref, | 661 | .decl_ref, |
| 672 | => try dg.renderParentPtr(writer, val, ty), | 662 | => try dg.renderParentPtr(writer, val, ty), |
| 673 | else => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val, location)}), | 663 | else => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val)}), |
| 674 | }, | 664 | }, |
| 675 | .Float => { | 665 | .Float => { |
| 676 | if (ty.floatBits(target) <= 64) { | 666 | if (ty.floatBits(target) <= 64) { |
| ... | @@ -682,22 +672,20 @@ pub const DeclGen = struct { | ... | @@ -682,22 +672,20 @@ pub const DeclGen = struct { |
| 682 | .base = .{ .tag = .int_u64 }, | 672 | .base = .{ .tag = .int_u64 }, |
| 683 | .data = @bitCast(u32, val.toFloat(f32)), | 673 | .data = @bitCast(u32, val.toFloat(f32)), |
| 684 | }; | 674 | }; |
| 685 | return writer.print("zig_bitcast_f32_u32({x})", .{try dg.fmtIntLiteral( | 675 | const bitcast_val = Value.initPayload(&bitcast_val_pl.base); |
| 686 | Type.u32, | 676 | return writer.print("zig_bitcast_f32_u32({x})", .{ |
| 687 | Value.initPayload(&bitcast_val_pl.base), | 677 | try dg.fmtIntLiteral(Type.u32, bitcast_val), |
| 688 | location, | 678 | }); |
| 689 | )}); | | |
| 690 | }, | 679 | }, |
| 691 | .f64 => { | 680 | .f64 => { |
| 692 | var bitcast_val_pl = Value.Payload.U64{ | 681 | var bitcast_val_pl = Value.Payload.U64{ |
| 693 | .base = .{ .tag = .int_u64 }, | 682 | .base = .{ .tag = .int_u64 }, |
| 694 | .data = @bitCast(u64, val.toFloat(f64)), | 683 | .data = @bitCast(u64, val.toFloat(f64)), |
| 695 | }; | 684 | }; |
| 696 | return writer.print("zig_bitcast_f32_u32({x})", .{try dg.fmtIntLiteral( | 685 | const bitcast_val = Value.initPayload(&bitcast_val_pl.base); |
| 697 | Type.u64, | 686 | return writer.print("zig_bitcast_f64_u64({x})", .{ |
| 698 | Value.initPayload(&bitcast_val_pl.base), | 687 | try dg.fmtIntLiteral(Type.u64, bitcast_val), |
| 699 | location, | 688 | }); |
| 700 | )}); | | |
| 701 | }, | 689 | }, |
| 702 | else => return dg.fail("TODO float types > 64 bits are not support in renderValue() as of now", .{}), | 690 | else => return dg.fail("TODO float types > 64 bits are not support in renderValue() as of now", .{}), |
| 703 | } | 691 | } |
| ... | @@ -740,7 +728,7 @@ pub const DeclGen = struct { | ... | @@ -740,7 +728,7 @@ pub const DeclGen = struct { |
| 740 | .int_u64, .one => { | 728 | .int_u64, .one => { |
| 741 | try writer.writeAll("(("); | 729 | try writer.writeAll("(("); |
| 742 | try dg.renderTypecast(writer, ty); | 730 | try dg.renderTypecast(writer, ty); |
| 743 | return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, location)}); | 731 | return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val)}); |
| 744 | }, | 732 | }, |
| 745 | .field_ptr, | 733 | .field_ptr, |
| 746 | .elem_ptr, | 734 | .elem_ptr, |
| ... | @@ -918,7 +906,7 @@ pub const DeclGen = struct { | ... | @@ -918,7 +906,7 @@ pub const DeclGen = struct { |
| 918 | | 906 | |
| 919 | empty = false; | 907 | empty = false; |
| 920 | } | 908 | } |
| 921 | if (empty) try writer.writeByte('0'); | 909 | if (empty) try writer.print("{}", .{try dg.fmtIntLiteral(Type.u8, Value.zero)}); |
| 922 | | 910 | |
| 923 | try writer.writeByte('}'); | 911 | try writer.writeByte('}'); |
| 924 | }, | 912 | }, |
| ... | @@ -1730,7 +1718,7 @@ pub const DeclGen = struct { | ... | @@ -1730,7 +1718,7 @@ pub const DeclGen = struct { |
| 1730 | var len_val_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len }; | 1718 | var len_val_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len }; |
| 1731 | const len_val = Value.initPayload(&len_val_pl.base); | 1719 | const len_val = Value.initPayload(&len_val_pl.base); |
| 1732 | | 1720 | |
| 1733 | try bw.print(" case {}: {{\n static ", .{try dg.fmtIntLiteral(enum_ty, int_val, .Other)}); | 1721 | try bw.print(" case {}: {{\n static ", .{try dg.fmtIntLiteral(enum_ty, int_val)}); |
| 1734 | try dg.renderTypeAndName(bw, name_ty, .{ .identifier = "name" }, .Const, 0); | 1722 | try dg.renderTypeAndName(bw, name_ty, .{ .identifier = "name" }, .Const, 0); |
| 1735 | try buffer.appendSlice(" = "); | 1723 | try buffer.appendSlice(" = "); |
| 1736 | try dg.renderValue(bw, name_ty, name_val, .Other); | 1724 | try dg.renderValue(bw, name_ty, name_val, .Other); |
| ... | @@ -1738,7 +1726,7 @@ pub const DeclGen = struct { | ... | @@ -1738,7 +1726,7 @@ pub const DeclGen = struct { |
| 1738 | try dg.renderTypecast(bw, name_slice_ty); | 1726 | try dg.renderTypecast(bw, name_slice_ty); |
| 1739 | try bw.print("){{{}, {}}};\n", .{ | 1727 | try bw.print("){{{}, {}}};\n", .{ |
| 1740 | fmtIdent("name"), | 1728 | fmtIdent("name"), |
| 1741 | try dg.fmtIntLiteral(Type.usize, len_val, .Other), | 1729 | try dg.fmtIntLiteral(Type.usize, len_val), |
| 1742 | }); | 1730 | }); |
| 1743 | | 1731 | |
| 1744 | try buffer.appendSlice(" }\n"); | 1732 | try buffer.appendSlice(" }\n"); |
| ... | @@ -1793,7 +1781,7 @@ pub const DeclGen = struct { | ... | @@ -1793,7 +1781,7 @@ pub const DeclGen = struct { |
| 1793 | .undefined_ptr => |ty| { | 1781 | .undefined_ptr => |ty| { |
| 1794 | try w.writeAll("(("); | 1782 | try w.writeAll("(("); |
| 1795 | try dg.renderTypecast(w, ty); | 1783 | try dg.renderTypecast(w, ty); |
| 1796 | return w.print("){x})", .{try dg.fmtIntLiteral(Type.usize, Value.undef, .Other)}); | 1784 | return w.print("){x})", .{try dg.fmtIntLiteral(Type.usize, Value.undef)}); |
| 1797 | }, | 1785 | }, |
| 1798 | .identifier => |ident| return w.print("{ }", .{fmtIdent(ident)}), | 1786 | .identifier => |ident| return w.print("{ }", .{fmtIdent(ident)}), |
| 1799 | .bytes => |bytes| return w.writeAll(bytes), | 1787 | .bytes => |bytes| return w.writeAll(bytes), |
| ... | @@ -1843,7 +1831,6 @@ pub const DeclGen = struct { | ... | @@ -1843,7 +1831,6 @@ pub const DeclGen = struct { |
| 1843 | dg: *DeclGen, | 1831 | dg: *DeclGen, |
| 1844 | ty: Type, | 1832 | ty: Type, |
| 1845 | val: Value, | 1833 | val: Value, |
| 1846 | location: ValueRenderLocation, | | |
| 1847 | ) !std.fmt.Formatter(formatIntLiteral) { | 1834 | ) !std.fmt.Formatter(formatIntLiteral) { |
| 1848 | const int_info = ty.intInfo(dg.module.getTarget()); | 1835 | const int_info = ty.intInfo(dg.module.getTarget()); |
| 1849 | const c_bits = toCIntBits(int_info.bits); | 1836 | const c_bits = toCIntBits(int_info.bits); |
| ... | @@ -1853,7 +1840,6 @@ pub const DeclGen = struct { | ... | @@ -1853,7 +1840,6 @@ pub const DeclGen = struct { |
| 1853 | .ty = ty, | 1840 | .ty = ty, |
| 1854 | .val = val, | 1841 | .val = val, |
| 1855 | .mod = dg.module, | 1842 | .mod = dg.module, |
| 1856 | .location = location, | | |
| 1857 | } }; | 1843 | } }; |
| 1858 | } | 1844 | } |
| 1859 | }; | 1845 | }; |
| ... | @@ -1916,7 +1902,7 @@ pub fn genErrDecls(o: *Object) !void { | ... | @@ -1916,7 +1902,7 @@ pub fn genErrDecls(o: *Object) !void { |
| 1916 | | 1902 | |
| 1917 | try writer.print("{{" ++ name_prefix ++ "_{}, {}}}", .{ | 1903 | try writer.print("{{" ++ name_prefix ++ "_{}, {}}}", .{ |
| 1918 | fmtIdent(name), | 1904 | fmtIdent(name), |
| 1919 | try o.dg.fmtIntLiteral(Type.usize, len_val, .Other), | 1905 | try o.dg.fmtIntLiteral(Type.usize, len_val), |
| 1920 | }); | 1906 | }); |
| 1921 | } | 1907 | } |
| 1922 | try writer.writeAll("};\n"); | 1908 | try writer.writeAll("};\n"); |
| ... | @@ -4415,27 +4401,44 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4415,27 +4401,44 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4415 | | 4401 | |
| 4416 | const inst_ty = f.air.typeOfIndex(inst); | 4402 | const inst_ty = f.air.typeOfIndex(inst); |
| 4417 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 4403 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 4418 | const vector_ty = f.air.getRefType(ty_pl.ty); | 4404 | const len = @intCast(usize, inst_ty.arrayLen()); |
| 4419 | const len = vector_ty.vectorLen(); | | |
| 4420 | const elements = @ptrCast([]const Air.Inst.Ref, f.air.extra[ty_pl.payload..][0..len]); | 4405 | const elements = @ptrCast([]const Air.Inst.Ref, f.air.extra[ty_pl.payload..][0..len]); |
| 4421 | | 4406 | |
| 4422 | const writer = f.object.writer(); | 4407 | const writer = f.object.writer(); |
| 4423 | const local = try f.allocLocal(inst_ty, .Const); | 4408 | const local = try f.allocLocal(inst_ty, .Const); |
| 4424 | try writer.writeAll(" = {"); | 4409 | try writer.writeAll(" = {"); |
| 4425 | switch (vector_ty.zigTypeTag()) { | 4410 | switch (inst_ty.zigTypeTag()) { |
| | 4411 | .Array => { |
| | 4412 | const elem_ty = inst_ty.childType(); |
| | 4413 | var empty = true; |
| | 4414 | for (elements) |element| { |
| | 4415 | if (empty) try writer.writeAll(", "); |
| | 4416 | try f.writeCValue(writer, try f.resolveInst(element)); |
| | 4417 | empty = false; |
| | 4418 | } |
| | 4419 | if (inst_ty.sentinel()) |sentinel| { |
| | 4420 | if (empty) try writer.writeAll(", "); |
| | 4421 | try f.object.dg.renderValue(writer, elem_ty, sentinel, .Other); |
| | 4422 | empty = false; |
| | 4423 | } |
| | 4424 | if (empty) try writer.print("{}", .{try f.fmtIntLiteral(Type.u8, Value.zero)}); |
| | 4425 | }, |
| 4426 | .Struct => { | 4426 | .Struct => { |
| 4427 | const tuple = vector_ty.tupleFields(); | 4427 | var empty = true; |
| 4428 | var i: usize = 0; | 4428 | for (elements) |element, index| { |
| 4429 | for (elements) |elem, elem_index| { | 4429 | if (inst_ty.structFieldValueComptime(index)) |_| continue; |
| 4430 | if (tuple.values[elem_index].tag() != .unreachable_value) continue; | 4430 | |
| 4431 | | 4431 | if (!empty) try writer.writeAll(", "); |
| 4432 | const value = try f.resolveInst(elem); | 4432 | if (!inst_ty.isTupleOrAnonStruct()) { |
| 4433 | if (i != 0) try writer.writeAll(", "); | 4433 | try writer.print(".{ } = ", .{fmtIdent(inst_ty.structFieldName(index))}); |
| 4434 | try f.writeCValue(writer, value); | 4434 | } |
| 4435 | i += 1; | 4435 | try f.writeCValue(writer, try f.resolveInst(element)); |
| | 4436 | empty = false; |
| 4436 | } | 4437 | } |
| | 4438 | if (empty) try writer.print("{}", .{try f.fmtIntLiteral(Type.u8, Value.zero)}); |
| 4437 | }, | 4439 | }, |
| 4438 | else => |tag| return f.fail("TODO: C backend: implement airAggregateInit for type {s}", .{@tagName(tag)}), | 4440 | .Vector => return f.fail("TODO: C backend: implement airAggregateInit for vectors", .{}), |
| | 4441 | else => unreachable, |
| 4439 | } | 4442 | } |
| 4440 | try writer.writeAll("};\n"); | 4443 | try writer.writeAll("};\n"); |
| 4441 | | 4444 | |
| ... | @@ -4706,7 +4709,6 @@ const FormatIntLiteralContext = struct { | ... | @@ -4706,7 +4709,6 @@ const FormatIntLiteralContext = struct { |
| 4706 | ty: Type, | 4709 | ty: Type, |
| 4707 | val: Value, | 4710 | val: Value, |
| 4708 | mod: *Module, | 4711 | mod: *Module, |
| 4709 | location: ValueRenderLocation, | | |
| 4710 | }; | 4712 | }; |
| 4711 | fn formatIntLiteral( | 4713 | fn formatIntLiteral( |
| 4712 | data: FormatIntLiteralContext, | 4714 | data: FormatIntLiteralContext, |
| ... | @@ -4755,13 +4757,6 @@ fn formatIntLiteral( | ... | @@ -4755,13 +4757,6 @@ fn formatIntLiteral( |
| 4755 | } else data.val.toBigInt(&int_buf, target); | 4757 | } else data.val.toBigInt(&int_buf, target); |
| 4756 | assert(int.fitsInTwosComp(int_info.signedness, int_info.bits)); | 4758 | assert(int.fitsInTwosComp(int_info.signedness, int_info.bits)); |
| 4757 | | 4759 | |
| 4758 | if (data.location == .Identifier) { | | |
| 4759 | const str = try int.toStringAlloc(allocator, 10, undefined); | | |
| 4760 | defer allocator.free(str); | | |
| 4761 | | | |
| 4762 | return writer.writeAll(str); | | |
| 4763 | } | | |
| 4764 | | | |
| 4765 | const limbs_count_64 = @divExact(64, @bitSizeOf(Limb)); | 4760 | const limbs_count_64 = @divExact(64, @bitSizeOf(Limb)); |
| 4766 | const c_bits = toCIntBits(int_info.bits) orelse unreachable; | 4761 | const c_bits = toCIntBits(int_info.bits) orelse unreachable; |
| 4767 | if (c_bits == 128) { | 4762 | if (c_bits == 128) { |
| ... | @@ -4788,7 +4783,6 @@ fn formatIntLiteral( | ... | @@ -4788,7 +4783,6 @@ fn formatIntLiteral( |
| 4788 | .ty = Type.u64, | 4783 | .ty = Type.u64, |
| 4789 | .val = upper_val, | 4784 | .val = upper_val, |
| 4790 | .mod = data.mod, | 4785 | .mod = data.mod, |
| 4791 | .location = data.location, | | |
| 4792 | }, fmt, options, writer); | 4786 | }, fmt, options, writer); |
| 4793 | try writer.writeAll("<<64|"); | 4787 | try writer.writeAll("<<64|"); |
| 4794 | } | 4788 | } |
| ... | @@ -4802,7 +4796,6 @@ fn formatIntLiteral( | ... | @@ -4802,7 +4796,6 @@ fn formatIntLiteral( |
| 4802 | .ty = Type.u64, | 4796 | .ty = Type.u64, |
| 4803 | .val = lower_val, | 4797 | .val = lower_val, |
| 4804 | .mod = data.mod, | 4798 | .mod = data.mod, |
| 4805 | .location = data.location, | | |
| 4806 | }, fmt, options, writer); | 4799 | }, fmt, options, writer); |
| 4807 | | 4800 | |
| 4808 | if (have_upper) try writer.writeByte(')'); | 4801 | if (have_upper) try writer.writeByte(')'); |