authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-07 18:55:15-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-25 05:11:28-04:00
log7c9a9a0fd4560d8ce5d61ab96b9403d27dd872b3
tree9ee261f8ddc6802882827b4e429f681f9bcfcf1e
parent525dcaecba43f9931aff69fd7dd0cd5b443c2859

cbe: cleanup code and fix cases test breakage


4 files changed, 355 insertions(+), 291 deletions(-)

lib/include/zig.h+1-1
...@@ -165,7 +165,7 @@...@@ -165,7 +165,7 @@
165165
166#define int128_t __int128166#define int128_t __int128
167#define uint128_t unsigned __int128167#define uint128_t unsigned __int128
168#define UINT128_MAX ((uint128_t)(0xffffffffffffffffull) | 0xffffffffffffffffull)168#define UINT128_MAX (((uint128_t)UINT64_MAX<<64|UINT64_MAX))
169ZIG_EXTERN_C void *memcpy (void *ZIG_RESTRICT, const void *ZIG_RESTRICT, size_t);169ZIG_EXTERN_C void *memcpy (void *ZIG_RESTRICT, const void *ZIG_RESTRICT, size_t);
170ZIG_EXTERN_C void *memset (void *, int, size_t);170ZIG_EXTERN_C void *memset (void *, int, size_t);
171ZIG_EXTERN_C int64_t __addodi4(int64_t lhs, int64_t rhs, int *overflow);171ZIG_EXTERN_C int64_t __addodi4(int64_t lhs, int64_t rhs, int *overflow);
src/codegen/c.zig+321-277
...@@ -19,7 +19,7 @@ const Liveness = @import("../Liveness.zig");...@@ -19,7 +19,7 @@ const Liveness = @import("../Liveness.zig");
19const CType = @import("../type.zig").CType;19const CType = @import("../type.zig").CType;
2020
21const Mutability = enum { Const, Mut };21const Mutability = enum { Const, Mut };
22const BigIntConst = std.math.big.int.Const;22const BigInt = std.math.big.int;
2323
24pub const CValue = union(enum) {24pub const CValue = union(enum) {
25 none: void,25 none: void,
...@@ -35,7 +35,7 @@ pub const CValue = union(enum) {...@@ -35,7 +35,7 @@ pub const CValue = union(enum) {
35 decl: Decl.Index,35 decl: Decl.Index,
36 decl_ref: Decl.Index,36 decl_ref: Decl.Index,
37 /// An undefined (void *) pointer (cannot be dereferenced)37 /// An undefined (void *) pointer (cannot be dereferenced)
38 undefined_ptr: void,38 undefined_ptr: Type,
39 /// Render the slice as an identifier (using fmtIdent)39 /// Render the slice as an identifier (using fmtIdent)
40 identifier: []const u8,40 identifier: []const u8,
41 /// Render these bytes literally.41 /// Render these bytes literally.
...@@ -74,11 +74,11 @@ fn formatTypeAsCIdentifier(...@@ -74,11 +74,11 @@ fn formatTypeAsCIdentifier(
74 options: std.fmt.FormatOptions,74 options: std.fmt.FormatOptions,
75 writer: anytype,75 writer: anytype,
76) !void {76) !void {
77 _ = fmt;77 var stack = std.heap.stackFallback(128, data.mod.gpa);
78 _ = options;78 const allocator = stack.get();
79 var buffer = [1]u8{0} ** 128;79 const str = std.fmt.allocPrint(allocator, "{}", .{data.ty.fmt(data.mod)}) catch "";
80 var buf = std.fmt.bufPrint(&buffer, "{}", .{data.ty.fmt(data.mod)}) catch &buffer;80 defer allocator.free(str);
81 return formatIdent(buf, "", .{}, writer);81 return formatIdent(str, fmt, options, writer);
82}82}
8383
84pub fn typeToCIdentifier(ty: Type, mod: *Module) std.fmt.Formatter(formatTypeAsCIdentifier) {84pub fn typeToCIdentifier(ty: Type, mod: *Module) std.fmt.Formatter(formatTypeAsCIdentifier) {
...@@ -332,8 +332,8 @@ pub const Function = struct {...@@ -332,8 +332,8 @@ pub const Function = struct {
332 return f.object.dg.renderTypecast(w, t);332 return f.object.dg.renderTypecast(w, t);
333 }333 }
334334
335 fn fmtIntLiteral(f: *Function, ty: Type, int_val: anytype) !IntLiteralFormatter(@TypeOf(int_val)) {335 fn fmtIntLiteral(f: *Function, ty: Type, val: Value) !std.fmt.Formatter(formatIntLiteral) {
336 return f.object.dg.fmtIntLiteral(ty, int_val, .Other);336 return f.object.dg.fmtIntLiteral(ty, val, .Other);
337 }337 }
338};338};
339339
...@@ -423,51 +423,6 @@ pub const DeclGen = struct {...@@ -423,51 +423,6 @@ pub const DeclGen = struct {
423 try dg.renderDeclName(writer, decl_index);423 try dg.renderDeclName(writer, decl_index);
424 }424 }
425425
426 fn renderInt128(
427 writer: anytype,
428 int_val: anytype,
429 ) error{ OutOfMemory, AnalysisFail }!void {
430 const int_info = @typeInfo(@TypeOf(int_val)).Int;
431 const is_signed = int_info.signedness == .signed;
432 const is_neg = int_val < 0;
433 comptime assert(int_info.bits > 64 and int_info.bits <= 128);
434
435 // Clang and GCC don't support 128-bit integer constants but will hopefully unfold them
436 // if we construct one manually.
437 const magnitude = std.math.absCast(int_val);
438
439 const high = @truncate(u64, magnitude >> 64);
440 const low = @truncate(u64, magnitude);
441
442 // (int128_t)/<->( ( (uint128_t)( val_high << 64 )u ) + (uint128_t)val_low/u )
443 if (is_signed) try writer.writeAll("(int128_t)");
444 if (is_neg) try writer.writeByte('-');
445
446 try writer.print("(((uint128_t)0x{x}u<<64)", .{high});
447
448 if (low > 0)
449 try writer.print("+(uint128_t)0x{x}u", .{low});
450
451 return writer.writeByte(')');
452 }
453
454 fn renderBigIntConst(
455 dg: *DeclGen,
456 writer: anytype,
457 val: BigIntConst,
458 signed: bool,
459 ) error{ OutOfMemory, AnalysisFail }!void {
460 if (signed) {
461 try renderInt128(writer, val.to(i128) catch {
462 return dg.fail("TODO implement integer constants larger than 128 bits", .{});
463 });
464 } else {
465 try renderInt128(writer, val.to(u128) catch {
466 return dg.fail("TODO implement integer constants larger than 128 bits", .{});
467 });
468 }
469 }
470
471 // Renders a "parent" pointer by recursing to the root decl/variable426 // Renders a "parent" pointer by recursing to the root decl/variable
472 // that its contents are defined with respect to.427 // that its contents are defined with respect to.
473 //428 //
...@@ -578,14 +533,14 @@ pub const DeclGen = struct {...@@ -578,14 +533,14 @@ pub const DeclGen = struct {
578 .Enum,533 .Enum,
579 .ErrorSet,534 .ErrorSet,
580 => return writer.print("{x}", .{535 => return writer.print("{x}", .{
581 try dg.fmtIntLiteral(ty, UndefInt{}, location),536 try dg.fmtIntLiteral(ty, val, location),
582 }),537 }),
583 .Float => switch (ty.tag()) {538 .Float => switch (ty.tag()) {
584 .f32 => return writer.print("zig_bitcast_f32_u32({x})", .{539 .f32 => return writer.print("zig_bitcast_f32_u32({x})", .{
585 try dg.fmtIntLiteral(Type.u32, UndefInt{}, location),540 try dg.fmtIntLiteral(Type.u32, val, location),
586 }),541 }),
587 .f64 => return writer.print("zig_bitcast_f64_u64({x})", .{542 .f64 => return writer.print("zig_bitcast_f64_u64({x})", .{
588 try dg.fmtIntLiteral(Type.u64, UndefInt{}, location),543 try dg.fmtIntLiteral(Type.u64, val, location),
589 }),544 }),
590 else => return dg.fail("TODO float types > 64 bits are not support in renderValue() as of now", .{}),545 else => return dg.fail("TODO float types > 64 bits are not support in renderValue() as of now", .{}),
591 },546 },
...@@ -593,13 +548,19 @@ pub const DeclGen = struct {...@@ -593,13 +548,19 @@ pub const DeclGen = struct {
593 .Slice => {548 .Slice => {
594 try writer.writeByte('(');549 try writer.writeByte('(');
595 try dg.renderTypecast(writer, ty);550 try dg.renderTypecast(writer, ty);
596 return writer.print("){{(void *){x}, {0x}}}", .{551 try writer.writeAll("){(");
597 try dg.fmtIntLiteral(Type.usize, UndefInt{}, location),552 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
553 const ptr_ty = ty.slicePtrFieldType(&buf);
554 try dg.renderTypecast(writer, ptr_ty);
555 return writer.print("){x}, {0x}}}", .{
556 try dg.fmtIntLiteral(Type.usize, val, location),
598 });557 });
599 },558 },
600 .Many, .C, .One => return writer.print("((void *){x})", .{559 .Many, .C, .One => {
601 try dg.fmtIntLiteral(Type.usize, UndefInt{}, location),560 try writer.writeAll("((");
602 }),561 try dg.renderTypecast(writer, ty);
562 return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, location)});
563 },
603 },564 },
604 .Optional => {565 .Optional => {
605 var opt_buf: Type.Payload.ElemType = undefined;566 var opt_buf: Type.Payload.ElemType = undefined;
...@@ -636,7 +597,7 @@ pub const DeclGen = struct {...@@ -636,7 +597,7 @@ pub const DeclGen = struct {
636 empty = false;597 empty = false;
637 }598 }
638 if (empty) try writer.print("{x}", .{599 if (empty) try writer.print("{x}", .{
639 try dg.fmtIntLiteral(Type.u8, UndefInt{}, location),600 try dg.fmtIntLiteral(Type.u8, Value.undef, location),
640 });601 });
641602
642 return writer.writeByte('}');603 return writer.writeByte('}');
...@@ -651,7 +612,7 @@ pub const DeclGen = struct {...@@ -651,7 +612,7 @@ pub const DeclGen = struct {
651 try dg.renderValue(writer, field.ty, val, location);612 try dg.renderValue(writer, field.ty, val, location);
652 break;613 break;
653 } else try writer.print("{x}", .{614 } else try writer.print("{x}", .{
654 try dg.fmtIntLiteral(Type.u8, UndefInt{}, location),615 try dg.fmtIntLiteral(Type.u8, Value.undef, location),
655 });616 });
656617
657 return writer.writeByte('}');618 return writer.writeByte('}');
...@@ -662,7 +623,7 @@ pub const DeclGen = struct {...@@ -662,7 +623,7 @@ pub const DeclGen = struct {
662 try writer.writeAll("){ .payload = ");623 try writer.writeAll("){ .payload = ");
663 try dg.renderValue(writer, ty.errorUnionPayload(), val, location);624 try dg.renderValue(writer, ty.errorUnionPayload(), val, location);
664 return writer.print(", .error = {x} }}", .{625 return writer.print(", .error = {x} }}", .{
665 try dg.fmtIntLiteral(ty.errorUnionSet(), UndefInt{}, location),626 try dg.fmtIntLiteral(ty.errorUnionSet(), Value.undef, location),
666 });627 });
667 },628 },
668 .Array => {629 .Array => {
...@@ -696,15 +657,10 @@ pub const DeclGen = struct {...@@ -696,15 +657,10 @@ pub const DeclGen = struct {
696 @tagName(tag),657 @tagName(tag),
697 }),658 }),
698 }659 }
660 unreachable;
699 }661 }
700 switch (ty.zigTypeTag()) {662 switch (ty.zigTypeTag()) {
701 .Int => switch (val.tag()) {663 .Int => switch (val.tag()) {
702 .int_big_positive => return writer.print("{x}", .{
703 try dg.fmtIntLiteral(ty, val.castTag(.int_big_positive).?.asBigInt(), location),
704 }),
705 .int_big_negative => return writer.print("{x}", .{
706 try dg.fmtIntLiteral(ty, val.castTag(.int_big_negative).?.asBigInt(), location),
707 }),
708 .field_ptr,664 .field_ptr,
709 .elem_ptr,665 .elem_ptr,
710 .opt_payload_ptr,666 .opt_payload_ptr,
...@@ -712,32 +668,35 @@ pub const DeclGen = struct {...@@ -712,32 +668,35 @@ pub const DeclGen = struct {
712 .decl_ref_mut,668 .decl_ref_mut,
713 .decl_ref,669 .decl_ref,
714 => try dg.renderParentPtr(writer, val, ty),670 => try dg.renderParentPtr(writer, val, ty),
715 else => if (ty.isSignedInt())671 else => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val, location)}),
716 return writer.print("{d}", .{try dg.fmtIntLiteral(ty, val.toSignedInt(), location)})
717 else
718 return writer.print("{d}", .{
719 try dg.fmtIntLiteral(ty, val.toUnsignedInt(target), location),
720 }),
721 },672 },
722 .Float => {673 .Float => {
723 if (ty.floatBits(target) <= 64) {674 if (ty.floatBits(target) <= 64) {
724 if (std.math.isNan(val.toFloat(f64)) or std.math.isInf(val.toFloat(f64))) {675 if (std.math.isNan(val.toFloat(f64)) or std.math.isInf(val.toFloat(f64))) {
725 // just generate a bit cast (exactly like we do in airBitcast)676 // just generate a bit cast (exactly like we do in airBitcast)
726 switch (ty.tag()) {677 switch (ty.tag()) {
727 .f32 => return writer.print("zig_bitcast_f32_u32({x})", .{678 .f32 => {
728 try dg.fmtIntLiteral(679 var bitcast_val_pl = Value.Payload.U64{
680 .base = .{ .tag = .int_u64 },
681 .data = @bitCast(u32, val.toFloat(f32)),
682 };
683 return writer.print("zig_bitcast_f32_u32({x})", .{try dg.fmtIntLiteral(
729 Type.u32,684 Type.u32,
730 @bitCast(u32, val.toFloat(f32)),685 Value.initPayload(&bitcast_val_pl.base),
731 location,686 location,
732 ),687 )});
733 }),688 },
734 .f64 => return writer.print("zig_bitcast_f64_u64({x})", .{689 .f64 => {
735 try dg.fmtIntLiteral(690 var bitcast_val_pl = Value.Payload.U64{
691 .base = .{ .tag = .int_u64 },
692 .data = @bitCast(u64, val.toFloat(f64)),
693 };
694 return writer.print("zig_bitcast_f32_u32({x})", .{try dg.fmtIntLiteral(
736 Type.u64,695 Type.u64,
737 @bitCast(u64, val.toFloat(f64)),696 Value.initPayload(&bitcast_val_pl.base),
738 location,697 location,
739 ),698 )});
740 }),699 },
741 else => return dg.fail("TODO float types > 64 bits are not support in renderValue() as of now", .{}),700 else => return dg.fail("TODO float types > 64 bits are not support in renderValue() as of now", .{}),
742 }701 }
743 } else {702 } else {
...@@ -779,9 +738,7 @@ pub const DeclGen = struct {...@@ -779,9 +738,7 @@ pub const DeclGen = struct {
779 .int_u64, .one => {738 .int_u64, .one => {
780 try writer.writeAll("((");739 try writer.writeAll("((");
781 try dg.renderTypecast(writer, ty);740 try dg.renderTypecast(writer, ty);
782 return writer.print("){x})", .{741 return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, location)});
783 try dg.fmtIntLiteral(Type.usize, val.toUnsignedInt(target), location),
784 });
785 },742 },
786 .field_ptr,743 .field_ptr,
787 .elem_ptr,744 .elem_ptr,
...@@ -1069,7 +1026,7 @@ pub const DeclGen = struct {...@@ -1069,7 +1026,7 @@ pub const DeclGen = struct {
1069 try bw.writeAll(" (*");1026 try bw.writeAll(" (*");
10701027
1071 const name_start = buffer.items.len;1028 const name_start = buffer.items.len;
1072 try bw.print("zig_F_{s})(", .{typeToCIdentifier(t, dg.module)});1029 try bw.print("zig_F_{})(", .{typeToCIdentifier(t, dg.module)});
1073 const name_end = buffer.items.len - 2;1030 const name_end = buffer.items.len - 2;
10741031
1075 const param_len = fn_info.param_types.len;1032 const param_len = fn_info.param_types.len;
...@@ -1124,13 +1081,16 @@ pub const DeclGen = struct {...@@ -1124,13 +1081,16 @@ pub const DeclGen = struct {
1124 try bw.writeAll("; size_t len; } ");1081 try bw.writeAll("; size_t len; } ");
1125 const name_index = buffer.items.len;1082 const name_index = buffer.items.len;
1126 if (t.isConstPtr()) {1083 if (t.isConstPtr()) {
1127 try bw.print("zig_L_{s}", .{typeToCIdentifier(child_type, dg.module)});1084 try bw.print("zig_L_{}", .{typeToCIdentifier(child_type, dg.module)});
1128 } else {1085 } else {
1129 try bw.print("zig_M_{s}", .{typeToCIdentifier(child_type, dg.module)});1086 try bw.print("zig_M_{}", .{typeToCIdentifier(child_type, dg.module)});
1130 }1087 }
1131 if (ptr_sentinel) |s| {1088 if (ptr_sentinel) |s| {
1132 try bw.writeAll("_s_");1089 var sentinel_buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1133 try dg.renderValue(bw, child_type, s, .Identifier);1090 defer sentinel_buffer.deinit();
1091
1092 try dg.renderValue(sentinel_buffer.writer(), child_type, s, .Identifier);
1093 try bw.print("_s_{}", .{fmtIdent(sentinel_buffer.items)});
1134 }1094 }
1135 try bw.writeAll(";\n");1095 try bw.writeAll(";\n");
11361096
...@@ -1327,7 +1287,7 @@ pub const DeclGen = struct {...@@ -1327,7 +1287,7 @@ pub const DeclGen = struct {
1327 try dg.renderDeclName(bw, func.owner_decl);1287 try dg.renderDeclName(bw, func.owner_decl);
1328 try bw.writeAll(";\n");1288 try bw.writeAll(";\n");
1329 } else {1289 } else {
1330 try bw.print("zig_E_{s}_{s};\n", .{1290 try bw.print("zig_E_{}_{};\n", .{
1331 typeToCIdentifier(error_ty, dg.module), typeToCIdentifier(payload_ty, dg.module),1291 typeToCIdentifier(error_ty, dg.module), typeToCIdentifier(payload_ty, dg.module),
1332 });1292 });
1333 }1293 }
...@@ -1356,10 +1316,13 @@ pub const DeclGen = struct {...@@ -1356,10 +1316,13 @@ pub const DeclGen = struct {
1356 try dg.renderType(bw, elem_type);1316 try dg.renderType(bw, elem_type);
13571317
1358 const name_start = buffer.items.len + 1;1318 const name_start = buffer.items.len + 1;
1359 try bw.print(" zig_A_{s}_{d}", .{ typeToCIdentifier(elem_type, dg.module), t.arrayLen() });1319 try bw.print(" zig_A_{}_{d}", .{ typeToCIdentifier(elem_type, dg.module), t.arrayLen() });
1360 if (t.sentinel()) |s| {1320 if (t.sentinel()) |s| {
1361 try bw.writeAll("_s_");1321 var sentinel_buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1362 try dg.renderValue(bw, elem_type, s, .Identifier);1322 defer sentinel_buffer.deinit();
1323
1324 try dg.renderValue(sentinel_buffer.writer(), elem_type, s, .Identifier);
1325 try bw.print("_s_{}", .{fmtIdent(sentinel_buffer.items)});
1363 }1326 }
1364 const name_end = buffer.items.len;1327 const name_end = buffer.items.len;
13651328
...@@ -1389,7 +1352,7 @@ pub const DeclGen = struct {...@@ -1389,7 +1352,7 @@ pub const DeclGen = struct {
1389 try dg.renderTypeAndName(bw, child_type, payload_name, .Mut, 0);1352 try dg.renderTypeAndName(bw, child_type, payload_name, .Mut, 0);
1390 try bw.writeAll("; bool is_null; } ");1353 try bw.writeAll("; bool is_null; } ");
1391 const name_index = buffer.items.len;1354 const name_index = buffer.items.len;
1392 try bw.print("zig_Q_{s};\n", .{typeToCIdentifier(child_type, dg.module)});1355 try bw.print("zig_Q_{};\n", .{typeToCIdentifier(child_type, dg.module)});
13931356
1394 const rendered = buffer.toOwnedSlice();1357 const rendered = buffer.toOwnedSlice();
1395 errdefer dg.typedefs.allocator.free(rendered);1358 errdefer dg.typedefs.allocator.free(rendered);
...@@ -1413,7 +1376,7 @@ pub const DeclGen = struct {...@@ -1413,7 +1376,7 @@ pub const DeclGen = struct {
1413 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);1376 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1414 defer buffer.deinit();1377 defer buffer.deinit();
14151378
1416 try buffer.writer().print("typedef struct {} ", .{fmtIdent(std.mem.span(unqualified_name))});1379 try buffer.writer().print("typedef struct { } ", .{fmtIdent(std.mem.span(unqualified_name))});
14171380
1418 const name_start = buffer.items.len;1381 const name_start = buffer.items.len;
1419 try buffer.writer().print("zig_O_{};\n", .{fmtIdent(fqn)});1382 try buffer.writer().print("zig_O_{};\n", .{fmtIdent(fqn)});
...@@ -1710,9 +1673,11 @@ pub const DeclGen = struct {...@@ -1710,9 +1673,11 @@ pub const DeclGen = struct {
1710 try w.writeByte('&');1673 try w.writeByte('&');
1711 return dg.renderDeclName(w, decl);1674 return dg.renderDeclName(w, decl);
1712 },1675 },
1713 .undefined_ptr => return w.print("((void *){x})", .{1676 .undefined_ptr => |ty| {
1714 try dg.fmtIntLiteral(Type.usize, UndefInt{}, .Other),1677 try w.writeAll("((");
1715 }),1678 try dg.renderTypecast(w, ty);
1679 return w.print("){x})", .{try dg.fmtIntLiteral(Type.usize, Value.undef, .Other)});
1680 },
1716 .identifier => |ident| return w.print("{ }", .{fmtIdent(ident)}),1681 .identifier => |ident| return w.print("{ }", .{fmtIdent(ident)}),
1717 .bytes => |bytes| return w.writeAll(bytes),1682 .bytes => |bytes| return w.writeAll(bytes),
1718 }1683 }
...@@ -1760,19 +1725,19 @@ pub const DeclGen = struct {...@@ -1760,19 +1725,19 @@ pub const DeclGen = struct {
1760 fn fmtIntLiteral(1725 fn fmtIntLiteral(
1761 dg: *DeclGen,1726 dg: *DeclGen,
1762 ty: Type,1727 ty: Type,
1763 int_val: anytype,1728 val: Value,
1764 location: ValueRenderLocation,1729 location: ValueRenderLocation,
1765 ) !IntLiteralFormatter(@TypeOf(int_val)) {1730 ) !std.fmt.Formatter(formatIntLiteral) {
1766 const target = dg.module.getTarget();1731 const int_info = ty.intInfo(dg.module.getTarget());
1767 const int_info = ty.intInfo(target);1732 const c_bits = toCIntBits(int_info.bits);
1768 _ = toCIntBits(int_info.bits) orelse1733 if (c_bits == null or c_bits.? > 128)
1769 return dg.fail("TODO implement integer constants larger than 128 bits", .{});1734 return dg.fail("TODO implement integer constants larger than 128 bits", .{});
1770 return IntLiteralFormatter(@TypeOf(int_val)){1735 return std.fmt.Formatter(formatIntLiteral){ .data = .{
1771 .ty = ty,1736 .ty = ty,
1772 .target = target,1737 .val = val,
1773 .int_val = int_val,1738 .mod = dg.module,
1774 .location = location,1739 .location = location,
1775 };1740 } };
1776 }1741 }
1777};1742};
17781743
...@@ -1785,8 +1750,8 @@ pub fn genErrDecls(o: *Object) !void {...@@ -1785,8 +1750,8 @@ pub fn genErrDecls(o: *Object) !void {
1785 var max_name_len: usize = 0;1750 var max_name_len: usize = 0;
1786 for (o.dg.module.error_name_list.items) |name, value| {1751 for (o.dg.module.error_name_list.items) |name, value| {
1787 max_name_len = std.math.max(name.len, max_name_len);1752 max_name_len = std.math.max(name.len, max_name_len);
1788 var err_val_payload = Value.Payload.Error{ .data = .{ .name = name } };1753 var err_val_pl = Value.Payload.Error{ .data = .{ .name = name } };
1789 try o.dg.renderValue(writer, Type.anyerror, Value.initPayload(&err_val_payload.base), .Other);1754 try o.dg.renderValue(writer, Type.anyerror, Value.initPayload(&err_val_pl.base), .Other);
1790 try writer.print(" = {d}u,\n", .{value});1755 try writer.print(" = {d}u,\n", .{value});
1791 }1756 }
1792 o.indent_writer.popIndent();1757 o.indent_writer.popIndent();
...@@ -1804,14 +1769,14 @@ pub fn genErrDecls(o: *Object) !void {...@@ -1804,14 +1769,14 @@ pub fn genErrDecls(o: *Object) !void {
1804 const identifier = name_buf[0 .. name_prefix.len + name.len :0];1769 const identifier = name_buf[0 .. name_prefix.len + name.len :0];
1805 const nameZ = identifier[name_prefix.len..];1770 const nameZ = identifier[name_prefix.len..];
18061771
1807 var name_ty_payload = Type.Payload.Len{1772 var name_ty_pl = Type.Payload.Len{
1808 .base = .{ .tag = .array_u8_sentinel_0 },1773 .base = .{ .tag = .array_u8_sentinel_0 },
1809 .data = name.len,1774 .data = name.len,
1810 };1775 };
1811 const name_ty = Type.initPayload(&name_ty_payload.base);1776 const name_ty = Type.initPayload(&name_ty_pl.base);
18121777
1813 var name_val_payload = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = nameZ };1778 var name_val_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = nameZ };
1814 const name_val = Value.initPayload(&name_val_payload.base);1779 const name_val = Value.initPayload(&name_val_pl.base);
18151780
1816 try writer.writeAll("static ");1781 try writer.writeAll("static ");
1817 try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, .Const, 0);1782 try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, .Const, 0);
...@@ -1820,11 +1785,11 @@ pub fn genErrDecls(o: *Object) !void {...@@ -1820,11 +1785,11 @@ pub fn genErrDecls(o: *Object) !void {
1820 try writer.writeAll(";\n");1785 try writer.writeAll(";\n");
1821 }1786 }
18221787
1823 var name_array_ty_payload = Type.Payload.Array{ .base = .{ .tag = .array }, .data = .{1788 var name_array_ty_pl = Type.Payload.Array{ .base = .{ .tag = .array }, .data = .{
1824 .len = o.dg.module.error_name_list.items.len,1789 .len = o.dg.module.error_name_list.items.len,
1825 .elem_type = Type.initTag(.const_slice_u8_sentinel_0),1790 .elem_type = Type.initTag(.const_slice_u8_sentinel_0),
1826 } };1791 } };
1827 const name_array_ty = Type.initPayload(&name_array_ty_payload.base);1792 const name_array_ty = Type.initPayload(&name_array_ty_pl.base);
18281793
1829 try writer.writeAll("static ");1794 try writer.writeAll("static ");
1830 try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = "zig_errorName" }, .Const, 0);1795 try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = "zig_errorName" }, .Const, 0);
...@@ -2363,7 +2328,7 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -2363,7 +2328,7 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {
2363 const elem_type = inst_ty.elemType();2328 const elem_type = inst_ty.elemType();
2364 const mutability: Mutability = if (inst_ty.isConstPtr()) .Const else .Mut;2329 const mutability: Mutability = if (inst_ty.isConstPtr()) .Const else .Mut;
2365 if (!elem_type.isFnOrHasRuntimeBitsIgnoreComptime()) {2330 if (!elem_type.isFnOrHasRuntimeBitsIgnoreComptime()) {
2366 return CValue.undefined_ptr;2331 return CValue{ .undefined_ptr = inst_ty };
2367 }2332 }
23682333
2369 const target = f.object.dg.module.getTarget();2334 const target = f.object.dg.module.getTarget();
...@@ -2540,7 +2505,7 @@ fn airStoreUndefined(f: *Function, dest_ptr: CValue) !CValue {...@@ -2540,7 +2505,7 @@ fn airStoreUndefined(f: *Function, dest_ptr: CValue) !CValue {
2540 const writer = f.object.writer();2505 const writer = f.object.writer();
2541 try writer.writeAll("memset(");2506 try writer.writeAll("memset(");
2542 try f.writeCValue(writer, dest_ptr);2507 try f.writeCValue(writer, dest_ptr);
2543 try writer.print(", {x}, sizeof(", .{try f.fmtIntLiteral(Type.u8, UndefInt{})});2508 try writer.print(", {x}, sizeof(", .{try f.fmtIntLiteral(Type.u8, Value.undef)});
2544 try f.writeCValueDeref(writer, dest_ptr);2509 try f.writeCValueDeref(writer, dest_ptr);
2545 try writer.writeAll("));\n");2510 try writer.writeAll("));\n");
2546 },2511 },
...@@ -2659,9 +2624,22 @@ fn airWrapOp(...@@ -2659,9 +2624,22 @@ fn airWrapOp(
2659 try f.writeCValue(w, lhs);2624 try f.writeCValue(w, lhs);
2660 try w.writeAll(", ");2625 try w.writeAll(", ");
2661 try f.writeCValue(w, rhs);2626 try f.writeCValue(w, rhs);
2662 if (int_info.signedness == .signed)2627 {
2663 try w.print(", {}", .{try f.fmtIntLiteral(inst_ty, MinInt{})});2628 var arena = std.heap.ArenaAllocator.init(f.object.dg.module.gpa);
2664 try w.print(", {});", .{try f.fmtIntLiteral(inst_ty, MaxInt{})});2629 defer arena.deinit();
2630
2631 const expected_contents = union { u: Value.Payload.U64, i: Value.Payload.I64 };
2632 var stack align(@alignOf(expected_contents)) =
2633 std.heap.stackFallback(@sizeOf(expected_contents), arena.allocator());
2634
2635 if (int_info.signedness == .signed) {
2636 const min_val = try inst_ty.minInt(stack.get(), target);
2637 try w.print(", {}", .{try f.fmtIntLiteral(inst_ty, min_val)});
2638 }
2639
2640 const max_val = try inst_ty.maxInt(stack.get(), target);
2641 try w.print(", {});", .{try f.fmtIntLiteral(inst_ty, max_val)});
2642 }
2665 try f.object.indent_writer.insertNewline();2643 try f.object.indent_writer.insertNewline();
26662644
2667 return ret;2645 return ret;
...@@ -2673,7 +2651,8 @@ fn airSatOp(f: *Function, inst: Air.Inst.Index, fn_op: [*:0]const u8) !CValue {...@@ -2673,7 +2651,8 @@ fn airSatOp(f: *Function, inst: Air.Inst.Index, fn_op: [*:0]const u8) !CValue {
26732651
2674 const bin_op = f.air.instructions.items(.data)[inst].bin_op;2652 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2675 const inst_ty = f.air.typeOfIndex(inst);2653 const inst_ty = f.air.typeOfIndex(inst);
2676 const int_info = inst_ty.intInfo(f.object.dg.module.getTarget());2654 const target = f.object.dg.module.getTarget();
2655 const int_info = inst_ty.intInfo(target);
2677 const bits = int_info.bits;2656 const bits = int_info.bits;
26782657
2679 switch (bits) {2658 switch (bits) {
...@@ -2716,9 +2695,22 @@ fn airSatOp(f: *Function, inst: Air.Inst.Index, fn_op: [*:0]const u8) !CValue {...@@ -2716,9 +2695,22 @@ fn airSatOp(f: *Function, inst: Air.Inst.Index, fn_op: [*:0]const u8) !CValue {
2716 try f.writeCValue(w, lhs);2695 try f.writeCValue(w, lhs);
2717 try w.writeAll(", ");2696 try w.writeAll(", ");
2718 try f.writeCValue(w, rhs);2697 try f.writeCValue(w, rhs);
2719 if (int_info.signedness == .signed)2698 {
2720 try w.print(", {}", .{try f.fmtIntLiteral(inst_ty, MinInt{})});2699 var arena = std.heap.ArenaAllocator.init(f.object.dg.module.gpa);
2721 try w.print(", {});", .{try f.fmtIntLiteral(inst_ty, MaxInt{})});2700 defer arena.deinit();
2701
2702 const expected_contents = union { u: Value.Payload.U64, i: Value.Payload.I64 };
2703 var stack align(@alignOf(expected_contents)) =
2704 std.heap.stackFallback(@sizeOf(expected_contents), arena.allocator());
2705
2706 if (int_info.signedness == .signed) {
2707 const min_val = try inst_ty.minInt(stack.get(), target);
2708 try w.print(", {}", .{try f.fmtIntLiteral(inst_ty, min_val)});
2709 }
2710
2711 const max_val = try inst_ty.maxInt(stack.get(), target);
2712 try w.print(", {});", .{try f.fmtIntLiteral(inst_ty, max_val)});
2713 }
2722 try f.object.indent_writer.insertNewline();2714 try f.object.indent_writer.insertNewline();
27232715
2724 return ret;2716 return ret;
...@@ -2756,9 +2748,22 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, op_abbrev: [*:0]const u8) !CV...@@ -2756,9 +2748,22 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, op_abbrev: [*:0]const u8) !CV
2756 try w.writeAll(", &");2748 try w.writeAll(", &");
2757 try f.writeCValue(w, ret);2749 try f.writeCValue(w, ret);
2758 try w.writeAll(".field_0, ");2750 try w.writeAll(".field_0, ");
2759 if (int_info.signedness == .signed)2751 {
2760 try w.print("{}, ", .{try f.fmtIntLiteral(scalar_ty, MinInt{})});2752 var arena = std.heap.ArenaAllocator.init(f.object.dg.module.gpa);
2761 try w.print("{});", .{try f.fmtIntLiteral(scalar_ty, MaxInt{})});2753 defer arena.deinit();
2754
2755 const expected_contents = union { u: Value.Payload.U64, i: Value.Payload.I64 };
2756 var stack align(@alignOf(expected_contents)) =
2757 std.heap.stackFallback(@sizeOf(expected_contents), arena.allocator());
2758
2759 if (int_info.signedness == .signed) {
2760 const min_val = try scalar_ty.minInt(stack.get(), target);
2761 try w.print("{}, ", .{try f.fmtIntLiteral(scalar_ty, min_val)});
2762 }
2763
2764 const max_val = try scalar_ty.maxInt(stack.get(), target);
2765 try w.print("{});", .{try f.fmtIntLiteral(scalar_ty, max_val)});
2766 }
2762 try f.object.indent_writer.insertNewline();2767 try f.object.indent_writer.insertNewline();
2763 return ret;2768 return ret;
2764}2769}
...@@ -3360,9 +3365,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3360,9 +3365,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
33603365
3361 const inputs_extra_begin = extra_i;3366 const inputs_extra_begin = extra_i;
3362 for (inputs) |input, i| {3367 for (inputs) |input, i| {
3363 const input_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);3368 const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);
3364 const constraint = std.mem.sliceTo(input_bytes, 0);3369 const constraint = std.mem.sliceTo(extra_bytes, 0);
3365 const name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);3370 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
3366 // This equation accounts for the fact that even if we have exactly 4 bytes3371 // This equation accounts for the fact that even if we have exactly 4 bytes
3367 // for the string, we still use the next u32 for the null terminator.3372 // for the string, we still use the next u32 for the null terminator.
3368 extra_i += (constraint.len + name.len + (2 + 3)) / 4;3373 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
...@@ -3411,10 +3416,12 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3411,10 +3416,12 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
3411 try writer.writeAll(": ");3416 try writer.writeAll(": ");
3412 extra_i = inputs_extra_begin;3417 extra_i = inputs_extra_begin;
3413 for (inputs) |_, index| {3418 for (inputs) |_, index| {
3414 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(f.air.extra[extra_i..]), 0);3419 const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);
3420 const constraint = std.mem.sliceTo(extra_bytes, 0);
3421 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
3415 // This equation accounts for the fact that even if we have exactly 4 bytes3422 // This equation accounts for the fact that even if we have exactly 4 bytes
3416 // for the string, we still use the next u32 for the null terminator.3423 // for the string, we still use the next u32 for the null terminator.
3417 extra_i += constraint.len / 4 + 1;3424 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
34183425
3419 if (constraint[0] == '{' and constraint[constraint.len - 1] == '}') {3426 if (constraint[0] == '{' and constraint[constraint.len - 1] == '}') {
3420 const reg = constraint[1 .. constraint.len - 1];3427 const reg = constraint[1 .. constraint.len - 1];
...@@ -3511,11 +3518,10 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3511,11 +3518,10 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3511 const operand = try f.resolveInst(ty_op.operand);3518 const operand = try f.resolveInst(ty_op.operand);
3512 const ptr_ty = f.air.typeOf(ty_op.operand);3519 const ptr_ty = f.air.typeOf(ty_op.operand);
3513 const opt_ty = ptr_ty.childType();3520 const opt_ty = ptr_ty.childType();
3514 var buf: Type.Payload.ElemType = undefined;3521 const inst_ty = f.air.typeOfIndex(inst);
3515 const payload_ty = opt_ty.optionalChild(&buf);
35163522
3517 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {3523 if (!inst_ty.childType().hasRuntimeBitsIgnoreComptime()) {
3518 return CValue.undefined_ptr;3524 return CValue{ .undefined_ptr = inst_ty };
3519 }3525 }
35203526
3521 if (opt_ty.optionalReprIsPayload()) {3527 if (opt_ty.optionalReprIsPayload()) {
...@@ -3524,7 +3530,6 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3524,7 +3530,6 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3524 return operand;3530 return operand;
3525 }3531 }
35263532
3527 const inst_ty = f.air.typeOfIndex(inst);
3528 const local = try f.allocLocal(inst_ty, .Const);3533 const local = try f.allocLocal(inst_ty, .Const);
3529 try writer.writeAll(" = &(");3534 try writer.writeAll(" = &(");
3530 try f.writeCValue(writer, operand);3535 try f.writeCValue(writer, operand);
...@@ -3892,7 +3897,8 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3892,7 +3897,8 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
3892 if (operand == .undefined_ptr) {3897 if (operand == .undefined_ptr) {
3893 // Unfortunately, C does not support any equivalent to3898 // Unfortunately, C does not support any equivalent to
3894 // &(*(void *)p)[0], although LLVM does via GetElementPtr3899 // &(*(void *)p)[0], although LLVM does via GetElementPtr
3895 try f.writeCValue(writer, CValue.undefined_ptr);3900 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
3901 try f.writeCValue(writer, CValue{ .undefined_ptr = inst_ty.slicePtrFieldType(&buf) });
3896 } else {3902 } else {
3897 try writer.writeAll("&(");3903 try writer.writeAll("&(");
3898 try f.writeCValueDeref(writer, operand);3904 try f.writeCValueDeref(writer, operand);
...@@ -4478,148 +4484,186 @@ fn signAbbrev(signedness: std.builtin.Signedness) u8 {...@@ -4478,148 +4484,186 @@ fn signAbbrev(signedness: std.builtin.Signedness) u8 {
4478 };4484 };
4479}4485}
44804486
4481const UndefInt = struct {4487const FormatIntLiteralContext = struct {
4482 pub fn to(_: UndefInt, comptime T: type) error{}!T {4488 ty: Type,
4483 comptime {4489 val: Value,
4484 if (@bitSizeOf(T) < 2) return 0;4490 mod: *Module,
4485 var value: T = 2;4491 location: ValueRenderLocation,
4486 var shift = 2;
4487 while (shift < @bitSizeOf(T)) : (shift <<= 1)
4488 value |= value << shift;
4489 return value;
4490 }
4491 }
4492};
4493const MaxInt = struct {
4494 pub fn to(_: MaxInt, comptime T: type) error{}!T {
4495 return std.math.maxInt(T);
4496 }
4497};
4498const MinInt = struct {
4499 pub fn to(_: MinInt, comptime T: type) error{}!T {
4500 return std.math.minInt(T);
4501 }
4502};4492};
4493fn formatIntLiteral(
4494 data: FormatIntLiteralContext,
4495 comptime fmt: []const u8,
4496 options: std.fmt.FormatOptions,
4497 writer: anytype,
4498) @TypeOf(writer).Error!void {
4499 const target = data.mod.getTarget();
4500 const int_info = data.ty.intInfo(target);
4501
4502 const Limb = std.math.big.Limb;
4503 const expected_contents = struct {
4504 const base = 10;
4505 const limbs_count_128 = BigInt.calcTwosCompLimbCount(128);
4506 const expected_needed_limbs_count = BigInt.calcToStringLimbsBufferLen(limbs_count_128, base);
4507 const worst_case_int = BigInt.Const{
4508 .limbs = &([1]Limb{std.math.maxInt(Limb)} ** expected_needed_limbs_count),
4509 .positive = false,
4510 };
45034511
4504fn IntLiteralFormatter(comptime IntType: type) type {4512 undef_limbs: [limbs_count_128]Limb,
4505 return struct {4513 str: [worst_case_int.sizeInBaseUpperBound(base)]u8,
4506 ty: Type,4514 limbs_limbs: [expected_needed_limbs_count]Limb,
4507 target: std.Target,4515 };
4508 int_val: IntType,4516 var stack align(@alignOf(expected_contents)) =
4509 location: ValueRenderLocation,4517 std.heap.stackFallback(@sizeOf(expected_contents), data.mod.gpa);
4518 const allocator = stack.get();
45104519
4511 fn formatHelper(4520 var undef_limbs: []Limb = &.{};
4512 self: @This(),4521 defer allocator.free(undef_limbs);
4513 comptime CIntType: type,
4514 comptime fmt: []const u8,
4515 options: std.fmt.FormatOptions,
4516 writer: anytype,
4517 ) !void {
4518 const c_int_info = @typeInfo(CIntType).Int;
4519 const c_int_val = switch (@typeInfo(IntType)) {
4520 .Int => @intCast(CIntType, self.int_val),
4521 .Struct, .Pointer => self.int_val.to(CIntType) catch unreachable,
4522 else => unreachable,
4523 };
4524 const c_abs_val = std.math.absCast(c_int_val);
4525 if (self.location == .Identifier) {
4526 if (c_int_val < 0) try writer.writeAll("_N");
4527 try writer.print("{d}", .{c_abs_val});
4528 } else if (c_int_info.bits == 128) {
4529 // Clang and GCC don't support 128-bit integer constants but
4530 // will hopefully unfold them if we construct one manually.
4531 //std.debug.todo("128-bit is unimplemented");
4532 try writer.writeByte('(');
4533 if (c_int_info.signedness == .signed) {
4534 try writer.writeAll("(int128_t)");
4535 if (c_int_val < 0) try writer.writeByte('-');
4536 }
45374522
4538 const upper = @intCast(u64, c_abs_val >> 64);4523 var int_buf: Value.BigIntSpace = undefined;
4539 if (upper != 0) try writer.writeByte('(');4524 const int = if (data.val.isUndefDeep()) blk: {
4540 if (upper != 0 or c_int_val < 0) try writer.writeAll("(uint128_t)");4525 undef_limbs = try allocator.alloc(Limb, BigInt.calcTwosCompLimbCount(int_info.bits));
4541 if (upper != 0) {
4542 try (IntLiteralFormatter(u64){
4543 .ty = Type.u64,
4544 .target = self.target,
4545 .int_val = upper,
4546 .location = self.location,
4547 }).formatHelper(u64, fmt, options, writer);
4548 try writer.writeAll("<<64|");
4549 }
45504526
4551 const lower = @truncate(u64, c_abs_val);4527 const undef_pattern: Limb = (1 << (@bitSizeOf(Limb) | 1)) / 3;
4552 try (IntLiteralFormatter(u64){4528 std.mem.set(Limb, undef_limbs, undef_pattern);
4553 .ty = Type.u64,
4554 .target = self.target,
4555 .int_val = lower,
4556 .location = self.location,
4557 }).formatHelper(u64, fmt, options, writer);
45584529
4559 if (upper != 0) try writer.writeByte(')');4530 var undef_int = BigInt.Mutable{
4560 try writer.writeByte(')');4531 .limbs = undef_limbs,
4561 } else if (c_int_val == std.math.maxInt(CIntType) or4532 .len = undef_limbs.len,
4562 c_int_info.signedness == .signed and c_int_val == std.math.minInt(CIntType))4533 .positive = true,
4563 {4534 };
4564 if (c_int_info.signedness == .unsigned) try writer.writeByte('U');4535 undef_int.truncate(undef_int.toConst(), int_info.signedness, int_info.bits);
4565 try writer.writeAll(switch (self.ty.tag()) {4536 break :blk undef_int.toConst();
4566 .c_short, .c_ushort => "SHRT",4537 } else data.val.toBigInt(&int_buf, target);
4567 .c_int, .c_uint => "INT",4538 assert(int.fitsInTwosComp(int_info.signedness, int_info.bits));
4568 .c_long, .c_ulong => "LONG",4539
4569 .c_longlong, .c_ulonglong => "LLONG",4540 if (data.location == .Identifier) {
4570 .isize, .usize => "INTPTR",4541 const str = try int.toStringAlloc(allocator, 10, undefined);
4571 else => std.fmt.comptimePrint("INT{d}", .{c_int_info.bits}),4542 defer allocator.free(str);
4572 });4543
4573 try writer.writeAll(if (c_int_val < 0) "_MIN" else "_MAX");4544 return writer.writeAll(str);
4574 } else {4545 }
4575 if (c_int_val < 0) try writer.writeByte('-');4546
4576 if (c_int_info.signedness == .unsigned) try writer.writeByte('U');4547 const limbs_count_64 = @divExact(64, @bitSizeOf(Limb));
4577 try writer.print("INT{d}_C(" ++ switch (fmt.len) {4548 const c_bits = toCIntBits(int_info.bits) orelse unreachable;
4578 0 => "{d}",4549 if (c_bits == 128) {
4579 1 => switch (fmt[0]) {4550 // Clang and GCC don't support 128-bit integer constants but
4580 'o' => "0{o}",4551 // will hopefully unfold them if we construct one manually.
4581 'd' => "{d}",4552 //std.debug.todo("128-bit is unimplemented");
4582 'x' => "0x{x}",4553 try writer.writeByte('(');
4583 'X' => "0x{X}",4554 if (int_info.signedness == .signed) {
4584 else => @compileError("Invalid fmt: " ++ fmt),4555 try writer.writeAll("(int128_t)");
4585 },4556 if (!int.positive) try writer.writeByte('-');
4586 else => @compileError("Invalid fmt: " ++ fmt),
4587 } ++ ")", .{ c_int_info.bits, c_abs_val });
4588 }
4589 }4557 }
45904558
4591 pub fn format(4559 const split = std.math.min(int.limbs.len, limbs_count_64);
4592 self: @This(),4560 var upper_val_pl = Value.Payload.BigInt{
4593 comptime fmt: []const u8,4561 .base = .{ .tag = .int_big_positive },
4594 options: std.fmt.FormatOptions,4562 .data = int.limbs[split..],
4595 writer: anytype,4563 };
4596 ) !void {4564 const have_upper = !upper_val_pl.asBigInt().eqZero();
4597 const int_info = self.ty.intInfo(self.target);4565 if (have_upper) try writer.writeByte('(');
4598 switch (toCIntBits(int_info.bits).?) {4566 if (have_upper or !int.positive) try writer.writeAll("(uint128_t)");
4599 8 => switch (int_info.signedness) {4567 if (have_upper) {
4600 .signed => try self.formatHelper(i8, fmt, options, writer),4568 const upper_val = Value.initPayload(&upper_val_pl.base);
4601 .unsigned => try self.formatHelper(u8, fmt, options, writer),4569 try formatIntLiteral(.{
4602 },4570 .ty = Type.u64,
4603 16 => switch (int_info.signedness) {4571 .val = upper_val,
4604 .signed => try self.formatHelper(i16, fmt, options, writer),4572 .mod = data.mod,
4605 .unsigned => try self.formatHelper(u16, fmt, options, writer),4573 .location = data.location,
4606 },4574 }, fmt, options, writer);
4607 32 => switch (int_info.signedness) {4575 try writer.writeAll("<<64|");
4608 .signed => try self.formatHelper(i32, fmt, options, writer),
4609 .unsigned => try self.formatHelper(u32, fmt, options, writer),
4610 },
4611 64 => switch (int_info.signedness) {
4612 .signed => try self.formatHelper(i64, fmt, options, writer),
4613 .unsigned => try self.formatHelper(u64, fmt, options, writer),
4614 },
4615 128 => switch (int_info.signedness) {
4616 .signed => try self.formatHelper(i128, fmt, options, writer),
4617 .unsigned => try self.formatHelper(u128, fmt, options, writer),
4618 },
4619 else => unreachable,
4620 }
4621 }4576 }
4622 };4577
4578 var lower_val_pl = Value.Payload.BigInt{
4579 .base = .{ .tag = .int_big_positive },
4580 .data = int.limbs[0..split],
4581 };
4582 const lower_val = Value.initPayload(&lower_val_pl.base);
4583 try formatIntLiteral(.{
4584 .ty = Type.u64,
4585 .val = lower_val,
4586 .mod = data.mod,
4587 .location = data.location,
4588 }, fmt, options, writer);
4589
4590 if (have_upper) try writer.writeByte(')');
4591 return writer.writeByte(')');
4592 }
4593
4594 assert(c_bits <= 64);
4595 var one_limbs: [BigInt.calcLimbLen(1)]Limb = undefined;
4596 const one = BigInt.Mutable.init(&one_limbs, 1).toConst();
4597
4598 var wrap_limbs: [BigInt.calcTwosCompLimbCount(64)]Limb = undefined;
4599 var wrap = BigInt.Mutable{ .limbs = &wrap_limbs, .len = undefined, .positive = undefined };
4600 if (wrap.addWrap(int, one, int_info.signedness, c_bits) or
4601 int_info.signedness == .signed and wrap.subWrap(int, one, int_info.signedness, c_bits))
4602 {
4603 if (int_info.signedness == .unsigned) try writer.writeByte('U');
4604 switch (data.ty.tag()) {
4605 .c_short, .c_ushort => try writer.writeAll("SHRT"),
4606 .c_int, .c_uint => try writer.writeAll("INT"),
4607 .c_long, .c_ulong => try writer.writeAll("LONG"),
4608 .c_longlong, .c_ulonglong => try writer.writeAll("LLONG"),
4609 .isize, .usize => try writer.writeAll("INTPTR"),
4610 else => try writer.print("INT{d}", .{c_bits}),
4611 }
4612 try writer.writeAll(if (int.positive) "_MAX" else "_MIN");
4613 return;
4614 }
4615
4616 if (!int.positive) try writer.writeByte('-');
4617 switch (data.ty.tag()) {
4618 .c_short, .c_ushort, .c_int, .c_uint, .c_long, .c_ulong, .c_longlong, .c_ulonglong => {},
4619 else => {
4620 if (int_info.signedness == .unsigned) try writer.writeByte('U');
4621 try writer.print("INT{d}_C(", .{c_bits});
4622 },
4623 }
4624
4625 var base: u8 = undefined;
4626 var case: std.fmt.Case = undefined;
4627 switch (fmt.len) {
4628 0 => base = 10,
4629 1 => switch (fmt[0]) {
4630 'b' => {
4631 base = 2;
4632 try writer.writeAll("0b");
4633 },
4634 'o' => {
4635 base = 8;
4636 try writer.writeByte('0');
4637 },
4638 'd' => base = 10,
4639 'x' => {
4640 base = 16;
4641 case = .lower;
4642 try writer.writeAll("0x");
4643 },
4644 'X' => {
4645 base = 16;
4646 case = .upper;
4647 try writer.writeAll("0x");
4648 },
4649 else => @compileError("Invalid fmt: " ++ fmt),
4650 },
4651 else => @compileError("Invalid fmt: " ++ fmt),
4652 }
4653
4654 var str: [64]u8 = undefined;
4655 var limbs_buf: [BigInt.calcToStringLimbsBufferLen(limbs_count_64, 10)]Limb = undefined;
4656 try writer.writeAll(str[0..int.abs().toString(&str, base, case, &limbs_buf)]);
4657
4658 switch (data.ty.tag()) {
4659 .c_short, .c_ushort, .c_int => {},
4660 .c_uint => try writer.writeAll("u"),
4661 .c_long => try writer.writeAll("l"),
4662 .c_ulong => try writer.writeAll("ul"),
4663 .c_longlong => try writer.writeAll("ll"),
4664 .c_ulonglong => try writer.writeAll("ull"),
4665 else => try writer.writeByte(')'),
4666 }
4623}4667}
46244668
4625fn loweredFnRetTyHasBits(fn_ty: Type) bool {4669fn loweredFnRetTyHasBits(fn_ty: Type) bool {
src/link/C.zig+13-7
...@@ -363,32 +363,38 @@ fn flushTypedefs(self: *C, f: *Flush, typedefs: codegen.TypedefMap.Unmanaged) Fl...@@ -363,32 +363,38 @@ fn flushTypedefs(self: *C, f: *Flush, typedefs: codegen.TypedefMap.Unmanaged) Fl
363}363}
364364
365fn flushErrDecls(self: *C, f: *Flush) FlushDeclError!void {365fn flushErrDecls(self: *C, f: *Flush) FlushDeclError!void {
366 const gpa = self.base.allocator;
367 const module = self.base.options.module.?;366 const module = self.base.options.module.?;
368367
369 var object = codegen.Object{368 var object = codegen.Object{
370 .dg = .{369 .dg = .{
371 .gpa = gpa,370 .gpa = module.gpa,
372 .module = module,371 .module = module,
373 .error_msg = null,372 .error_msg = null,
374 .decl_index = undefined,373 .decl_index = undefined,
375 .decl = undefined,374 .decl = undefined,
376 .fwd_decl = undefined,375 .fwd_decl = undefined,
377 .typedefs = codegen.TypedefMap.initContext(gpa, .{ .mod = module }),376 .typedefs = codegen.TypedefMap.initContext(module.gpa, .{ .mod = module }),
378 .typedefs_arena = gpa,377 .typedefs_arena = self.arena.allocator(),
379 },378 },
380 .code = f.err_buf.toManaged(gpa),379 .code = f.err_buf.toManaged(module.gpa),
381 .indent_writer = undefined, // set later so we can get a pointer to object.code380 .indent_writer = undefined, // set later so we can get a pointer to object.code
382 };381 };
383 object.indent_writer = .{ .underlying_writer = object.code.writer() };382 object.indent_writer = .{ .underlying_writer = object.code.writer() };
384 defer object.dg.typedefs.deinit();383 defer {
385 defer f.err_buf = object.code.moveToUnmanaged();384 f.err_buf = object.code.moveToUnmanaged();
385 for (object.dg.typedefs.values()) |value| {
386 module.gpa.free(value.rendered);
387 }
388 object.dg.typedefs.deinit();
389 }
386390
387 codegen.genErrDecls(&object) catch |err| switch (err) {391 codegen.genErrDecls(&object) catch |err| switch (err) {
388 error.AnalysisFail => unreachable,392 error.AnalysisFail => unreachable,
389 else => |e| return e,393 else => |e| return e,
390 };394 };
391395
396 const gpa = self.base.allocator;
397
392 try self.flushTypedefs(f, object.dg.typedefs.unmanaged);398 try self.flushTypedefs(f, object.dg.typedefs.unmanaged);
393 try f.all_buffers.ensureUnusedCapacity(gpa, 1);399 try f.all_buffers.ensureUnusedCapacity(gpa, 1);
394 f.appendBufAssumeCapacity(object.code.items);400 f.appendBufAssumeCapacity(object.code.items);
src/type.zig+20-6
...@@ -5347,7 +5347,7 @@ pub const Type = extern union {...@@ -5347,7 +5347,7 @@ pub const Type = extern union {
5347 // Works for vectors and vectors of integers.5347 // Works for vectors and vectors of integers.
5348 pub fn minInt(ty: Type, arena: Allocator, target: Target) !Value {5348 pub fn minInt(ty: Type, arena: Allocator, target: Target) !Value {
5349 const scalar = try minIntScalar(ty.scalarType(), arena, target);5349 const scalar = try minIntScalar(ty.scalarType(), arena, target);
5350 if (ty.zigTypeTag() == .Vector) {5350 if (ty.zigTypeTag() == .Vector and scalar.tag() != .the_only_possible_value) {
5351 return Value.Tag.repeated.create(arena, scalar);5351 return Value.Tag.repeated.create(arena, scalar);
5352 } else {5352 } else {
5353 return scalar;5353 return scalar;
...@@ -5359,12 +5359,16 @@ pub const Type = extern union {...@@ -5359,12 +5359,16 @@ pub const Type = extern union {
5359 assert(ty.zigTypeTag() == .Int);5359 assert(ty.zigTypeTag() == .Int);
5360 const info = ty.intInfo(target);5360 const info = ty.intInfo(target);
53615361
5362 if (info.bits == 0) {
5363 return Value.initTag(.the_only_possible_value);
5364 }
5365
5362 if (info.signedness == .unsigned) {5366 if (info.signedness == .unsigned) {
5363 return Value.zero;5367 return Value.zero;
5364 }5368 }
53655369
5366 if (info.bits <= 6) {5370 if (std.math.cast(u6, info.bits - 1)) |shift| {
5367 const n: i64 = -(@as(i64, 1) << @truncate(u6, info.bits - 1));5371 const n = @as(i64, std.math.minInt(i64)) >> (63 - shift);
5368 return Value.Tag.int_i64.create(arena, n);5372 return Value.Tag.int_i64.create(arena, n);
5369 }5373 }
53705374
...@@ -5384,13 +5388,23 @@ pub const Type = extern union {...@@ -5384,13 +5388,23 @@ pub const Type = extern union {
5384 assert(self.zigTypeTag() == .Int);5388 assert(self.zigTypeTag() == .Int);
5385 const info = self.intInfo(target);5389 const info = self.intInfo(target);
53865390
5387 if (info.bits <= 6) switch (info.signedness) {5391 if (info.bits == 0) {
5392 return Value.initTag(.the_only_possible_value);
5393 }
5394
5395 switch (info.bits - @boolToInt(info.signedness == .signed)) {
5396 0 => return Value.zero,
5397 1 => return Value.one,
5398 else => {},
5399 }
5400
5401 if (std.math.cast(u6, info.bits - 1)) |shift| switch (info.signedness) {
5388 .signed => {5402 .signed => {
5389 const n: i64 = (@as(i64, 1) << @truncate(u6, info.bits - 1)) - 1;5403 const n = @as(i64, std.math.maxInt(i64)) >> (63 - shift);
5390 return Value.Tag.int_i64.create(arena, n);5404 return Value.Tag.int_i64.create(arena, n);
5391 },5405 },
5392 .unsigned => {5406 .unsigned => {
5393 const n: u64 = (@as(u64, 1) << @truncate(u6, info.bits)) - 1;5407 const n = @as(u64, std.math.maxInt(u64)) >> (63 - shift);
5394 return Value.Tag.int_u64.create(arena, n);5408 return Value.Tag.int_u64.create(arena, n);
5395 },5409 },
5396 };5410 };