| ... | @@ -43,10 +43,12 @@ pub const CValue = union(enum) { | ... | @@ -43,10 +43,12 @@ pub const CValue = union(enum) { |
| 43 | decl_ref: InternPool.DeclIndex, | 43 | decl_ref: InternPool.DeclIndex, |
| 44 | /// An undefined value (cannot be dereferenced) | 44 | /// An undefined value (cannot be dereferenced) |
| 45 | undef: Type, | 45 | undef: Type, |
| 46 | /// Render the slice as an identifier (using fmtIdent) | 46 | /// Rendered as an identifier (using fmtIdent) |
| 47 | identifier: []const u8, | 47 | identifier: []const u8, |
| 48 | /// Render the slice as an payload.identifier (using fmtIdent) | 48 | /// Rendered as "payload." followed by as identifier (using fmtIdent) |
| 49 | payload_identifier: []const u8, | 49 | payload_identifier: []const u8, |
| | 50 | /// Rendered with fmtCTypePoolString |
| | 51 | ctype_pool_string: CType.Pool.String, |
| 50 | }; | 52 | }; |
| 51 | | 53 | |
| 52 | const BlockData = struct { | 54 | const BlockData = struct { |
| ... | @@ -62,10 +64,10 @@ pub const LazyFnKey = union(enum) { | ... | @@ -62,10 +64,10 @@ pub const LazyFnKey = union(enum) { |
| 62 | never_inline: InternPool.DeclIndex, | 64 | never_inline: InternPool.DeclIndex, |
| 63 | }; | 65 | }; |
| 64 | pub const LazyFnValue = struct { | 66 | pub const LazyFnValue = struct { |
| 65 | fn_name: CType.String, | 67 | fn_name: CType.Pool.String, |
| 66 | data: Data, | 68 | data: Data, |
| 67 | | 69 | |
| 68 | pub const Data = union { | 70 | const Data = union { |
| 69 | tag_name: Type, | 71 | tag_name: Type, |
| 70 | never_tail: void, | 72 | never_tail: void, |
| 71 | never_inline: void, | 73 | never_inline: void, |
| ... | @@ -80,7 +82,7 @@ const Local = struct { | ... | @@ -80,7 +82,7 @@ const Local = struct { |
| 80 | _: u20 = undefined, | 82 | _: u20 = undefined, |
| 81 | }, | 83 | }, |
| 82 | | 84 | |
| 83 | pub fn getType(local: Local) LocalType { | 85 | fn getType(local: Local) LocalType { |
| 84 | return .{ .ctype = local.ctype, .alignas = local.flags.alignas }; | 86 | return .{ .ctype = local.ctype, .alignas = local.flags.alignas }; |
| 85 | } | 87 | } |
| 86 | }; | 88 | }; |
| ... | @@ -96,12 +98,20 @@ const ValueRenderLocation = enum { | ... | @@ -96,12 +98,20 @@ const ValueRenderLocation = enum { |
| 96 | StaticInitializer, | 98 | StaticInitializer, |
| 97 | Other, | 99 | Other, |
| 98 | | 100 | |
| 99 | pub fn isInitializer(self: ValueRenderLocation) bool { | 101 | fn isInitializer(loc: ValueRenderLocation) bool { |
| 100 | return switch (self) { | 102 | return switch (loc) { |
| 101 | .Initializer, .StaticInitializer => true, | 103 | .Initializer, .StaticInitializer => true, |
| 102 | else => false, | 104 | else => false, |
| 103 | }; | 105 | }; |
| 104 | } | 106 | } |
| | 107 | |
| | 108 | fn toCTypeKind(loc: ValueRenderLocation) CType.Kind { |
| | 109 | return switch (loc) { |
| | 110 | .FunctionArgument => .parameter, |
| | 111 | .Initializer, .Other => .complete, |
| | 112 | .StaticInitializer => .global, |
| | 113 | }; |
| | 114 | } |
| 105 | }; | 115 | }; |
| 106 | | 116 | |
| 107 | const BuiltinInfo = enum { none, bits }; | 117 | const BuiltinInfo = enum { none, bits }; |
| ... | @@ -234,12 +244,11 @@ fn isReservedIdent(ident: []const u8) bool { | ... | @@ -234,12 +244,11 @@ fn isReservedIdent(ident: []const u8) bool { |
| 234 | | 244 | |
| 235 | fn formatIdent( | 245 | fn formatIdent( |
| 236 | ident: []const u8, | 246 | ident: []const u8, |
| 237 | comptime fmt: []const u8, | 247 | comptime fmt_str: []const u8, |
| 238 | options: std.fmt.FormatOptions, | 248 | _: std.fmt.FormatOptions, |
| 239 | writer: anytype, | 249 | writer: anytype, |
| 240 | ) !void { | 250 | ) @TypeOf(writer).Error!void { |
| 241 | _ = options; | 251 | const solo = fmt_str.len != 0 and fmt_str[0] == ' '; // space means solo; not part of a bigger ident. |
| 242 | const solo = fmt.len != 0 and fmt[0] == ' '; // space means solo; not part of a bigger ident. | | |
| 243 | if (solo and isReservedIdent(ident)) { | 252 | if (solo and isReservedIdent(ident)) { |
| 244 | try writer.writeAll("zig_e_"); | 253 | try writer.writeAll("zig_e_"); |
| 245 | } | 254 | } |
| ... | @@ -256,11 +265,32 @@ fn formatIdent( | ... | @@ -256,11 +265,32 @@ fn formatIdent( |
| 256 | } | 265 | } |
| 257 | } | 266 | } |
| 258 | } | 267 | } |
| 259 | | | |
| 260 | pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) { | 268 | pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) { |
| 261 | return .{ .data = ident }; | 269 | return .{ .data = ident }; |
| 262 | } | 270 | } |
| 263 | | 271 | |
| | 272 | const CTypePoolStringFormatData = struct { |
| | 273 | ctype_pool_string: CType.Pool.String, |
| | 274 | ctype_pool: *const CType.Pool, |
| | 275 | }; |
| | 276 | fn formatCTypePoolString( |
| | 277 | data: CTypePoolStringFormatData, |
| | 278 | comptime fmt_str: []const u8, |
| | 279 | fmt_opts: std.fmt.FormatOptions, |
| | 280 | writer: anytype, |
| | 281 | ) @TypeOf(writer).Error!void { |
| | 282 | if (data.ctype_pool_string.toSlice(data.ctype_pool)) |slice| |
| | 283 | try formatIdent(slice, fmt_str, fmt_opts, writer) |
| | 284 | else |
| | 285 | try writer.print("{}", .{data.ctype_pool_string.fmt(data.ctype_pool)}); |
| | 286 | } |
| | 287 | pub fn fmtCTypePoolString( |
| | 288 | ctype_pool_string: CType.Pool.String, |
| | 289 | ctype_pool: *const CType.Pool, |
| | 290 | ) std.fmt.Formatter(formatCTypePoolString) { |
| | 291 | return .{ .data = .{ .ctype_pool_string = ctype_pool_string, .ctype_pool = ctype_pool } }; |
| | 292 | } |
| | 293 | |
| 264 | // Returns true if `formatIdent` would make any edits to ident. | 294 | // Returns true if `formatIdent` would make any edits to ident. |
| 265 | // This must be kept in sync with `formatIdent`. | 295 | // This must be kept in sync with `formatIdent`. |
| 266 | pub fn isMangledIdent(ident: []const u8, solo: bool) bool { | 296 | pub fn isMangledIdent(ident: []const u8, solo: bool) bool { |
| ... | @@ -321,7 +351,7 @@ pub const Function = struct { | ... | @@ -321,7 +351,7 @@ pub const Function = struct { |
| 321 | try writer.writeAll(" = "); | 351 | try writer.writeAll(" = "); |
| 322 | try f.object.dg.renderValue(writer, val, .StaticInitializer); | 352 | try f.object.dg.renderValue(writer, val, .StaticInitializer); |
| 323 | try writer.writeAll(";\n "); | 353 | try writer.writeAll(";\n "); |
| 324 | break :result decl_c_value; | 354 | break :result .{ .local = decl_c_value.new_local }; |
| 325 | } else .{ .constant = val }; | 355 | } else .{ .constant = val }; |
| 326 | | 356 | |
| 327 | gop.value_ptr.* = result; | 357 | gop.value_ptr.* = result; |
| ... | @@ -377,27 +407,7 @@ pub const Function = struct { | ... | @@ -377,27 +407,7 @@ pub const Function = struct { |
| 377 | switch (c_value) { | 407 | switch (c_value) { |
| 378 | .none => unreachable, | 408 | .none => unreachable, |
| 379 | .new_local, .local => |i| try w.print("t{d}", .{i}), | 409 | .new_local, .local => |i| try w.print("t{d}", .{i}), |
| 380 | .local_ref => |i| { | 410 | .local_ref => |i| try w.print("&t{d}", .{i}), |
| 381 | const local = &f.locals.items[i]; | | |
| 382 | if (local.flags.alignas.abiOrder().compare(.lt)) { | | |
| 383 | const gpa = f.object.dg.gpa; | | |
| 384 | const mod = f.object.dg.mod; | | |
| 385 | const ctype_pool = &f.object.dg.ctype_pool; | | |
| 386 | | | |
| 387 | try w.writeByte('('); | | |
| 388 | try f.renderCType(w, try ctype_pool.getPointer(gpa, .{ | | |
| 389 | .elem_ctype = try ctype_pool.fromIntInfo(gpa, .{ | | |
| 390 | .signedness = .unsigned, | | |
| 391 | .bits = @min( | | |
| 392 | local.flags.alignas.toByteUnits(), | | |
| 393 | mod.resolved_target.result.maxIntAlignment(), | | |
| 394 | ) * 8, | | |
| 395 | }, mod, .forward), | | |
| 396 | })); | | |
| 397 | try w.writeByte(')'); | | |
| 398 | } | | |
| 399 | try w.print("&t{d}", .{i}); | | |
| 400 | }, | | |
| 401 | .constant => |val| try f.object.dg.renderValue(w, val, location), | 411 | .constant => |val| try f.object.dg.renderValue(w, val, location), |
| 402 | .arg => |i| try w.print("a{d}", .{i}), | 412 | .arg => |i| try w.print("a{d}", .{i}), |
| 403 | .arg_array => |i| try f.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" }), | 413 | .arg_array => |i| try f.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" }), |
| ... | @@ -516,7 +526,7 @@ pub const Function = struct { | ... | @@ -516,7 +526,7 @@ pub const Function = struct { |
| 516 | }, | 526 | }, |
| 517 | }; | 527 | }; |
| 518 | } | 528 | } |
| 519 | return gop.value_ptr.fn_name.slice(ctype_pool); | 529 | return gop.value_ptr.fn_name.toSlice(ctype_pool).?; |
| 520 | } | 530 | } |
| 521 | | 531 | |
| 522 | pub fn deinit(f: *Function) void { | 532 | pub fn deinit(f: *Function) void { |
| ... | @@ -538,6 +548,43 @@ pub const Function = struct { | ... | @@ -538,6 +548,43 @@ pub const Function = struct { |
| 538 | const zcu = f.object.dg.zcu; | 548 | const zcu = f.object.dg.zcu; |
| 539 | return f.air.typeOfIndex(inst, &zcu.intern_pool); | 549 | return f.air.typeOfIndex(inst, &zcu.intern_pool); |
| 540 | } | 550 | } |
| | 551 | |
| | 552 | fn copyCValue(f: *Function, ctype: CType, dst: CValue, src: CValue) !void { |
| | 553 | switch (dst) { |
| | 554 | .new_local, .local => |dst_local_index| switch (src) { |
| | 555 | .new_local, .local => |src_local_index| if (dst_local_index == src_local_index) return, |
| | 556 | else => {}, |
| | 557 | }, |
| | 558 | else => {}, |
| | 559 | } |
| | 560 | const writer = f.object.writer(); |
| | 561 | const a = try Assignment.start(f, writer, ctype); |
| | 562 | try f.writeCValue(writer, dst, .Other); |
| | 563 | try a.assign(f, writer); |
| | 564 | try f.writeCValue(writer, src, .Initializer); |
| | 565 | try a.end(f, writer); |
| | 566 | } |
| | 567 | |
| | 568 | fn moveCValue(f: *Function, inst: Air.Inst.Index, ty: Type, src: CValue) !CValue { |
| | 569 | switch (src) { |
| | 570 | // Move the freshly allocated local to be owned by this instruction, |
| | 571 | // by returning it here instead of freeing it. |
| | 572 | .new_local => return src, |
| | 573 | else => { |
| | 574 | try freeCValue(f, inst, src); |
| | 575 | const dst = try f.allocLocal(inst, ty); |
| | 576 | try f.copyCValue(try f.ctypeFromType(ty, .complete), dst, src); |
| | 577 | return dst; |
| | 578 | }, |
| | 579 | } |
| | 580 | } |
| | 581 | |
| | 582 | fn freeCValue(f: *Function, inst: ?Air.Inst.Index, val: CValue) !void { |
| | 583 | switch (val) { |
| | 584 | .new_local => |local_index| try freeLocal(f, inst, local_index, null), |
| | 585 | else => {}, |
| | 586 | } |
| | 587 | } |
| 541 | }; | 588 | }; |
| 542 | | 589 | |
| 543 | /// This data is available when outputting .c code for a `Zcu`. | 590 | /// This data is available when outputting .c code for a `Zcu`. |
| ... | @@ -627,13 +674,14 @@ pub const DeclGen = struct { | ... | @@ -627,13 +674,14 @@ pub const DeclGen = struct { |
| 627 | // them). The analysis until now should ensure that the C function | 674 | // them). The analysis until now should ensure that the C function |
| 628 | // pointers are compatible. If they are not, then there is a bug | 675 | // pointers are compatible. If they are not, then there is a bug |
| 629 | // somewhere and we should let the C compiler tell us about it. | 676 | // somewhere and we should let the C compiler tell us about it. |
| 630 | const elem_ctype = (try dg.ctypeFromType(ptr_ty, .complete)).info(ctype_pool).pointer.elem_ctype; | 677 | const ptr_ctype = try dg.ctypeFromType(ptr_ty, .complete); |
| | 678 | const elem_ctype = ptr_ctype.info(ctype_pool).pointer.elem_ctype; |
| 631 | const decl_ctype = try dg.ctypeFromType(decl_ty, .complete); | 679 | const decl_ctype = try dg.ctypeFromType(decl_ty, .complete); |
| 632 | const need_cast = !elem_ctype.eql(decl_ctype) and | 680 | const need_cast = !elem_ctype.eql(decl_ctype) and |
| 633 | (elem_ctype.info(ctype_pool) != .function or decl_ctype.info(ctype_pool) != .function); | 681 | (elem_ctype.info(ctype_pool) != .function or decl_ctype.info(ctype_pool) != .function); |
| 634 | if (need_cast) { | 682 | if (need_cast) { |
| 635 | try writer.writeAll("(("); | 683 | try writer.writeAll("(("); |
| 636 | try dg.renderType(writer, ptr_ty); | 684 | try dg.renderCType(writer, ptr_ctype); |
| 637 | try writer.writeByte(')'); | 685 | try writer.writeByte(')'); |
| 638 | } | 686 | } |
| 639 | try writer.writeByte('&'); | 687 | try writer.writeByte('&'); |
| ... | @@ -692,13 +740,14 @@ pub const DeclGen = struct { | ... | @@ -692,13 +740,14 @@ pub const DeclGen = struct { |
| 692 | // them). The analysis until now should ensure that the C function | 740 | // them). The analysis until now should ensure that the C function |
| 693 | // pointers are compatible. If they are not, then there is a bug | 741 | // pointers are compatible. If they are not, then there is a bug |
| 694 | // somewhere and we should let the C compiler tell us about it. | 742 | // somewhere and we should let the C compiler tell us about it. |
| 695 | const elem_ctype = (try dg.ctypeFromType(ty, .complete)).info(ctype_pool).pointer.elem_ctype; | 743 | const ctype = try dg.ctypeFromType(ty, .complete); |
| | 744 | const elem_ctype = ctype.info(ctype_pool).pointer.elem_ctype; |
| 696 | const decl_ctype = try dg.ctypeFromType(decl_ty, .complete); | 745 | const decl_ctype = try dg.ctypeFromType(decl_ty, .complete); |
| 697 | const need_cast = !elem_ctype.eql(decl_ctype) and | 746 | const need_cast = !elem_ctype.eql(decl_ctype) and |
| 698 | (elem_ctype.info(ctype_pool) != .function or decl_ctype.info(ctype_pool) != .function); | 747 | (elem_ctype.info(ctype_pool) != .function or decl_ctype.info(ctype_pool) != .function); |
| 699 | if (need_cast) { | 748 | if (need_cast) { |
| 700 | try writer.writeAll("(("); | 749 | try writer.writeAll("(("); |
| 701 | try dg.renderType(writer, ty); | 750 | try dg.renderCType(writer, ctype); |
| 702 | try writer.writeByte(')'); | 751 | try writer.writeByte(')'); |
| 703 | } | 752 | } |
| 704 | try writer.writeByte('&'); | 753 | try writer.writeByte('&'); |
| ... | @@ -828,6 +877,12 @@ pub const DeclGen = struct { | ... | @@ -828,6 +877,12 @@ pub const DeclGen = struct { |
| 828 | } | 877 | } |
| 829 | } | 878 | } |
| 830 | | 879 | |
| | 880 | fn renderErrorName(dg: *DeclGen, writer: anytype, err_name: InternPool.NullTerminatedString) !void { |
| | 881 | const zcu = dg.zcu; |
| | 882 | const ip = &zcu.intern_pool; |
| | 883 | try writer.print("zig_error_{}", .{fmtIdent(err_name.toSlice(ip))}); |
| | 884 | } |
| | 885 | |
| 831 | fn renderValue( | 886 | fn renderValue( |
| 832 | dg: *DeclGen, | 887 | dg: *DeclGen, |
| 833 | writer: anytype, | 888 | writer: anytype, |
| ... | @@ -837,6 +892,7 @@ pub const DeclGen = struct { | ... | @@ -837,6 +892,7 @@ pub const DeclGen = struct { |
| 837 | const zcu = dg.zcu; | 892 | const zcu = dg.zcu; |
| 838 | const ip = &zcu.intern_pool; | 893 | const ip = &zcu.intern_pool; |
| 839 | const target = &dg.mod.resolved_target.result; | 894 | const target = &dg.mod.resolved_target.result; |
| | 895 | const ctype_pool = &dg.ctype_pool; |
| 840 | | 896 | |
| 841 | const initializer_type: ValueRenderLocation = switch (location) { | 897 | const initializer_type: ValueRenderLocation = switch (location) { |
| 842 | .StaticInitializer => .StaticInitializer, | 898 | .StaticInitializer => .StaticInitializer, |
| ... | @@ -845,6 +901,7 @@ pub const DeclGen = struct { | ... | @@ -845,6 +901,7 @@ pub const DeclGen = struct { |
| 845 | | 901 | |
| 846 | const ty = val.typeOf(zcu); | 902 | const ty = val.typeOf(zcu); |
| 847 | if (val.isUndefDeep(zcu)) return dg.renderUndefValue(writer, ty, location); | 903 | if (val.isUndefDeep(zcu)) return dg.renderUndefValue(writer, ty, location); |
| | 904 | const ctype = try dg.ctypeFromType(ty, location.toCTypeKind()); |
| 848 | switch (ip.indexToKey(val.toIntern())) { | 905 | switch (ip.indexToKey(val.toIntern())) { |
| 849 | // types, not values | 906 | // types, not values |
| 850 | .int_type, | 907 | .int_type, |
| ... | @@ -890,76 +947,53 @@ pub const DeclGen = struct { | ... | @@ -890,76 +947,53 @@ pub const DeclGen = struct { |
| 890 | .u64, .i64, .big_int => try writer.print("{}", .{try dg.fmtIntLiteral(val, location)}), | 947 | .u64, .i64, .big_int => try writer.print("{}", .{try dg.fmtIntLiteral(val, location)}), |
| 891 | .lazy_align, .lazy_size => { | 948 | .lazy_align, .lazy_size => { |
| 892 | try writer.writeAll("(("); | 949 | try writer.writeAll("(("); |
| 893 | try dg.renderType(writer, ty); | 950 | try dg.renderCType(writer, ctype); |
| 894 | try writer.print("){x})", .{try dg.fmtIntLiteral( | 951 | try writer.print("){x})", .{try dg.fmtIntLiteral( |
| 895 | try zcu.intValue(Type.usize, val.toUnsignedInt(zcu)), | 952 | try zcu.intValue(Type.usize, val.toUnsignedInt(zcu)), |
| 896 | .Other, | 953 | .Other, |
| 897 | )}); | 954 | )}); |
| 898 | }, | 955 | }, |
| 899 | }, | 956 | }, |
| 900 | .err => |err| try writer.print("zig_error_{}", .{ | 957 | .err => |err| try dg.renderErrorName(writer, err.name), |
| 901 | fmtIdent(err.name.toSlice(ip)), | 958 | .error_union => |error_union| switch (ctype.info(ctype_pool)) { |
| 902 | }), | 959 | .basic => switch (error_union.val) { |
| 903 | .error_union => |error_union| { | 960 | .err_name => |err_name| try dg.renderErrorName(writer, err_name), |
| 904 | const payload_ty = ty.errorUnionPayload(zcu); | 961 | .payload => try writer.writeAll("0"), |
| 905 | const error_ty = ty.errorUnionSet(zcu); | 962 | }, |
| 906 | const err_int_ty = try zcu.errorIntType(); | 963 | .pointer, .aligned, .array, .vector, .fwd_decl, .function => unreachable, |
| 907 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 964 | .aggregate => |aggregate| { |
| 908 | switch (error_union.val) { | 965 | if (!location.isInitializer()) { |
| 909 | .err_name => |err_name| return dg.renderValue( | 966 | try writer.writeByte('('); |
| 910 | writer, | 967 | try dg.renderCType(writer, ctype); |
| 911 | Value.fromInterned((try zcu.intern(.{ .err = .{ | 968 | try writer.writeByte(')'); |
| 912 | .ty = error_ty.toIntern(), | | |
| 913 | .name = err_name, | | |
| 914 | } }))), | | |
| 915 | location, | | |
| 916 | ), | | |
| 917 | .payload => return dg.renderValue( | | |
| 918 | writer, | | |
| 919 | try zcu.intValue(err_int_ty, 0), | | |
| 920 | location, | | |
| 921 | ), | | |
| 922 | } | 969 | } |
| 923 | } | 970 | try writer.writeByte('{'); |
| 924 | | 971 | for (0..aggregate.fields.len) |field_index| { |
| 925 | if (!location.isInitializer()) { | 972 | if (field_index > 0) try writer.writeByte(','); |
| 926 | try writer.writeByte('('); | 973 | switch (aggregate.fields.at(field_index, ctype_pool).name.index) { |
| 927 | try dg.renderType(writer, ty); | 974 | .@"error" => switch (error_union.val) { |
| 928 | try writer.writeByte(')'); | 975 | .err_name => |err_name| try dg.renderErrorName(writer, err_name), |
| 929 | } | 976 | .payload => try writer.writeByte('0'), |
| 930 | | 977 | }, |
| 931 | try writer.writeAll("{ .payload = "); | 978 | .payload => switch (error_union.val) { |
| 932 | try dg.renderValue( | 979 | .err_name => try dg.renderUndefValue( |
| 933 | writer, | 980 | writer, |
| 934 | Value.fromInterned(switch (error_union.val) { | 981 | ty.errorUnionPayload(zcu), |
| 935 | .err_name => (try zcu.undefValue(payload_ty)).toIntern(), | 982 | initializer_type, |
| 936 | .payload => |payload| payload, | 983 | ), |
| 937 | }), | 984 | .payload => |payload| try dg.renderValue( |
| 938 | initializer_type, | 985 | writer, |
| 939 | ); | 986 | Value.fromInterned(payload), |
| 940 | try writer.writeAll(", .error = "); | 987 | initializer_type, |
| 941 | switch (error_union.val) { | 988 | ), |
| 942 | .err_name => |err_name| try dg.renderValue( | 989 | }, |
| 943 | writer, | 990 | else => unreachable, |
| 944 | Value.fromInterned((try zcu.intern(.{ .err = .{ | 991 | } |
| 945 | .ty = error_ty.toIntern(), | 992 | } |
| 946 | .name = err_name, | 993 | try writer.writeByte('}'); |
| 947 | } }))), | 994 | }, |
| 948 | location, | | |
| 949 | ), | | |
| 950 | .payload => try dg.renderValue( | | |
| 951 | writer, | | |
| 952 | try zcu.intValue(err_int_ty, 0), | | |
| 953 | location, | | |
| 954 | ), | | |
| 955 | } | | |
| 956 | try writer.writeAll(" }"); | | |
| 957 | }, | 995 | }, |
| 958 | .enum_tag => |enum_tag| try dg.renderValue( | 996 | .enum_tag => |enum_tag| try dg.renderValue(writer, Value.fromInterned(enum_tag.int), location), |
| 959 | writer, | | |
| 960 | Value.fromInterned(enum_tag.int), | | |
| 961 | location, | | |
| 962 | ), | | |
| 963 | .float => { | 997 | .float => { |
| 964 | const bits = ty.floatBits(target.*); | 998 | const bits = ty.floatBits(target.*); |
| 965 | const f128_val = val.toFloat(f128, zcu); | 999 | const f128_val = val.toFloat(f128, zcu); |
| ... | @@ -1050,15 +1084,23 @@ pub const DeclGen = struct { | ... | @@ -1050,15 +1084,23 @@ pub const DeclGen = struct { |
| 1050 | if (!empty) try writer.writeByte(')'); | 1084 | if (!empty) try writer.writeByte(')'); |
| 1051 | }, | 1085 | }, |
| 1052 | .slice => |slice| { | 1086 | .slice => |slice| { |
| | 1087 | const aggregate = ctype.info(ctype_pool).aggregate; |
| 1053 | if (!location.isInitializer()) { | 1088 | if (!location.isInitializer()) { |
| 1054 | try writer.writeByte('('); | 1089 | try writer.writeByte('('); |
| 1055 | try dg.renderType(writer, ty); | 1090 | try dg.renderCType(writer, ctype); |
| 1056 | try writer.writeByte(')'); | 1091 | try writer.writeByte(')'); |
| 1057 | } | 1092 | } |
| 1058 | try writer.writeByte('{'); | 1093 | try writer.writeByte('{'); |
| 1059 | try dg.renderValue(writer, Value.fromInterned(slice.ptr), initializer_type); | 1094 | for (0..aggregate.fields.len) |field_index| { |
| 1060 | try writer.writeAll(", "); | 1095 | if (field_index > 0) try writer.writeByte(','); |
| 1061 | try dg.renderValue(writer, Value.fromInterned(slice.len), initializer_type); | 1096 | try dg.renderValue(writer, Value.fromInterned( |
| | 1097 | switch (aggregate.fields.at(field_index, ctype_pool).name.index) { |
| | 1098 | .ptr => slice.ptr, |
| | 1099 | .len => slice.len, |
| | 1100 | else => unreachable, |
| | 1101 | }, |
| | 1102 | ), initializer_type); |
| | 1103 | } |
| 1062 | try writer.writeByte('}'); | 1104 | try writer.writeByte('}'); |
| 1063 | }, | 1105 | }, |
| 1064 | .ptr => |ptr| switch (ptr.addr) { | 1106 | .ptr => |ptr| switch (ptr.addr) { |
| ... | @@ -1066,7 +1108,7 @@ pub const DeclGen = struct { | ... | @@ -1066,7 +1108,7 @@ pub const DeclGen = struct { |
| 1066 | .anon_decl => |decl_val| try dg.renderAnonDeclValue(writer, val, decl_val, location), | 1108 | .anon_decl => |decl_val| try dg.renderAnonDeclValue(writer, val, decl_val, location), |
| 1067 | .int => |int| { | 1109 | .int => |int| { |
| 1068 | try writer.writeAll("(("); | 1110 | try writer.writeAll("(("); |
| 1069 | try dg.renderType(writer, ty); | 1111 | try dg.renderCType(writer, ctype); |
| 1070 | try writer.print("){x})", .{try dg.fmtIntLiteral(Value.fromInterned(int), location)}); | 1112 | try writer.print("){x})", .{try dg.fmtIntLiteral(Value.fromInterned(int), location)}); |
| 1071 | }, | 1113 | }, |
| 1072 | .eu_payload, | 1114 | .eu_payload, |
| ... | @@ -1076,54 +1118,80 @@ pub const DeclGen = struct { | ... | @@ -1076,54 +1118,80 @@ pub const DeclGen = struct { |
| 1076 | => try dg.renderParentPtr(writer, val.toIntern(), location), | 1118 | => try dg.renderParentPtr(writer, val.toIntern(), location), |
| 1077 | .comptime_field, .comptime_alloc => unreachable, | 1119 | .comptime_field, .comptime_alloc => unreachable, |
| 1078 | }, | 1120 | }, |
| 1079 | .opt => |opt| { | 1121 | .opt => |opt| switch (ctype.info(ctype_pool)) { |
| 1080 | const payload_ty = ty.optionalChild(zcu); | 1122 | .basic => if (ctype.isBool()) try writer.writeAll(switch (opt.val) { |
| 1081 | | 1123 | .none => "true", |
| 1082 | const is_null_val = Value.makeBool(opt.val == .none); | 1124 | else => "false", |
| 1083 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) | 1125 | }) else switch (opt.val) { |
| 1084 | return dg.renderValue(writer, is_null_val, location); | 1126 | .none => try writer.writeAll("0"), |
| 1085 | | 1127 | else => |payload| switch (ip.indexToKey(payload)) { |
| 1086 | if (ty.optionalReprIsPayload(zcu)) return dg.renderValue( | 1128 | .undef => |err_ty| try dg.renderUndefValue( |
| 1087 | writer, | 1129 | writer, |
| | 1130 | Type.fromInterned(err_ty), |
| | 1131 | location, |
| | 1132 | ), |
| | 1133 | .err => |err| try dg.renderErrorName(writer, err.name), |
| | 1134 | else => unreachable, |
| | 1135 | }, |
| | 1136 | }, |
| | 1137 | .pointer => switch (opt.val) { |
| | 1138 | .none => try writer.writeAll("NULL"), |
| | 1139 | else => |payload| try dg.renderValue(writer, Value.fromInterned(payload), location), |
| | 1140 | }, |
| | 1141 | .aligned, .array, .vector, .fwd_decl, .function => unreachable, |
| | 1142 | .aggregate => |aggregate| { |
| 1088 | switch (opt.val) { | 1143 | switch (opt.val) { |
| 1089 | .none => switch (payload_ty.zigTypeTag(zcu)) { | 1144 | .none => {}, |
| 1090 | .ErrorSet => try zcu.intValue(try zcu.errorIntType(), 0), | 1145 | else => |payload| switch (aggregate.fields.at(0, ctype_pool).name.index) { |
| 1091 | .Pointer => try zcu.getCoerced(val, payload_ty), | 1146 | .is_null, .payload => {}, |
| | 1147 | .ptr, .len => return dg.renderValue( |
| | 1148 | writer, |
| | 1149 | Value.fromInterned(payload), |
| | 1150 | location, |
| | 1151 | ), |
| 1092 | else => unreachable, | 1152 | else => unreachable, |
| 1093 | }, | 1153 | }, |
| 1094 | else => |payload| Value.fromInterned(payload), | 1154 | } |
| 1095 | }, | 1155 | if (!location.isInitializer()) { |
| 1096 | location, | 1156 | try writer.writeByte('('); |
| 1097 | ); | 1157 | try dg.renderCType(writer, ctype); |
| 1098 | | 1158 | try writer.writeByte(')'); |
| 1099 | if (!location.isInitializer()) { | 1159 | } |
| 1100 | try writer.writeByte('('); | 1160 | try writer.writeByte('{'); |
| 1101 | try dg.renderType(writer, ty); | 1161 | for (0..aggregate.fields.len) |field_index| { |
| 1102 | try writer.writeByte(')'); | 1162 | if (field_index > 0) try writer.writeByte(','); |
| 1103 | } | 1163 | switch (aggregate.fields.at(field_index, ctype_pool).name.index) { |
| 1104 | | 1164 | .is_null => try writer.writeAll(switch (opt.val) { |
| 1105 | try writer.writeAll("{ .payload = "); | 1165 | .none => "true", |
| 1106 | switch (opt.val) { | 1166 | else => "false", |
| 1107 | .none => try dg.renderUndefValue(writer, payload_ty, initializer_type), | 1167 | }), |
| 1108 | else => |payload| try dg.renderValue( | 1168 | .payload => switch (opt.val) { |
| 1109 | writer, | 1169 | .none => try dg.renderUndefValue( |
| 1110 | Value.fromInterned(payload), | 1170 | writer, |
| 1111 | initializer_type, | 1171 | ty.optionalChild(zcu), |
| 1112 | ), | 1172 | initializer_type, |
| 1113 | } | 1173 | ), |
| 1114 | try writer.writeAll(", .is_null = "); | 1174 | else => |payload| try dg.renderValue( |
| 1115 | try dg.renderValue(writer, is_null_val, initializer_type); | 1175 | writer, |
| 1116 | try writer.writeAll(" }"); | 1176 | Value.fromInterned(payload), |
| | 1177 | initializer_type, |
| | 1178 | ), |
| | 1179 | }, |
| | 1180 | .ptr => try writer.writeAll("NULL"), |
| | 1181 | .len => try dg.renderUndefValue(writer, Type.usize, initializer_type), |
| | 1182 | else => unreachable, |
| | 1183 | } |
| | 1184 | } |
| | 1185 | try writer.writeByte('}'); |
| | 1186 | }, |
| 1117 | }, | 1187 | }, |
| 1118 | .aggregate => switch (ip.indexToKey(ty.toIntern())) { | 1188 | .aggregate => switch (ip.indexToKey(ty.toIntern())) { |
| 1119 | .array_type, .vector_type => { | 1189 | .array_type, .vector_type => { |
| 1120 | if (location == .FunctionArgument) { | 1190 | if (location == .FunctionArgument) { |
| 1121 | try writer.writeByte('('); | 1191 | try writer.writeByte('('); |
| 1122 | try dg.renderType(writer, ty); | 1192 | try dg.renderCType(writer, ctype); |
| 1123 | try writer.writeByte(')'); | 1193 | try writer.writeByte(')'); |
| 1124 | } | 1194 | } |
| 1125 | // Fall back to generic implementation. | | |
| 1126 | | | |
| 1127 | const ai = ty.arrayInfo(zcu); | 1195 | const ai = ty.arrayInfo(zcu); |
| 1128 | if (ai.elem_type.eql(Type.u8, zcu)) { | 1196 | if (ai.elem_type.eql(Type.u8, zcu)) { |
| 1129 | var literal = stringLiteral(writer, ty.arrayLenIncludingSentinel(zcu)); | 1197 | var literal = stringLiteral(writer, ty.arrayLenIncludingSentinel(zcu)); |
| ... | @@ -1160,7 +1228,7 @@ pub const DeclGen = struct { | ... | @@ -1160,7 +1228,7 @@ pub const DeclGen = struct { |
| 1160 | .anon_struct_type => |tuple| { | 1228 | .anon_struct_type => |tuple| { |
| 1161 | if (!location.isInitializer()) { | 1229 | if (!location.isInitializer()) { |
| 1162 | try writer.writeByte('('); | 1230 | try writer.writeByte('('); |
| 1163 | try dg.renderType(writer, ty); | 1231 | try dg.renderCType(writer, ctype); |
| 1164 | try writer.writeByte(')'); | 1232 | try writer.writeByte(')'); |
| 1165 | } | 1233 | } |
| 1166 | | 1234 | |
| ... | @@ -1196,7 +1264,7 @@ pub const DeclGen = struct { | ... | @@ -1196,7 +1264,7 @@ pub const DeclGen = struct { |
| 1196 | .auto, .@"extern" => { | 1264 | .auto, .@"extern" => { |
| 1197 | if (!location.isInitializer()) { | 1265 | if (!location.isInitializer()) { |
| 1198 | try writer.writeByte('('); | 1266 | try writer.writeByte('('); |
| 1199 | try dg.renderType(writer, ty); | 1267 | try dg.renderCType(writer, ctype); |
| 1200 | try writer.writeByte(')'); | 1268 | try writer.writeByte(')'); |
| 1201 | } | 1269 | } |
| 1202 | | 1270 | |
| ... | @@ -1238,7 +1306,7 @@ pub const DeclGen = struct { | ... | @@ -1238,7 +1306,7 @@ pub const DeclGen = struct { |
| 1238 | | 1306 | |
| 1239 | if (eff_num_fields == 0) { | 1307 | if (eff_num_fields == 0) { |
| 1240 | try writer.writeByte('('); | 1308 | try writer.writeByte('('); |
| 1241 | try dg.renderUndefValue(writer, ty, initializer_type); | 1309 | try dg.renderUndefValue(writer, ty, location); |
| 1242 | try writer.writeByte(')'); | 1310 | try writer.writeByte(')'); |
| 1243 | } else if (ty.bitSize(zcu) > 64) { | 1311 | } else if (ty.bitSize(zcu) > 64) { |
| 1244 | // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off)) | 1312 | // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off)) |
| ... | @@ -1293,7 +1361,7 @@ pub const DeclGen = struct { | ... | @@ -1293,7 +1361,7 @@ pub const DeclGen = struct { |
| 1293 | | 1361 | |
| 1294 | if (!empty) try writer.writeAll(" | "); | 1362 | if (!empty) try writer.writeAll(" | "); |
| 1295 | try writer.writeByte('('); | 1363 | try writer.writeByte('('); |
| 1296 | try dg.renderType(writer, ty); | 1364 | try dg.renderCType(writer, ctype); |
| 1297 | try writer.writeByte(')'); | 1365 | try writer.writeByte(')'); |
| 1298 | | 1366 | |
| 1299 | const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { | 1367 | const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { |
| ... | @@ -1334,7 +1402,7 @@ pub const DeclGen = struct { | ... | @@ -1334,7 +1402,7 @@ pub const DeclGen = struct { |
| 1334 | try dg.renderType(writer, backing_ty); | 1402 | try dg.renderType(writer, backing_ty); |
| 1335 | try writer.writeByte(')'); | 1403 | try writer.writeByte(')'); |
| 1336 | } | 1404 | } |
| 1337 | try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type); | 1405 | try dg.renderValue(writer, Value.fromInterned(un.val), location); |
| 1338 | }, | 1406 | }, |
| 1339 | .@"extern" => { | 1407 | .@"extern" => { |
| 1340 | if (location == .StaticInitializer) { | 1408 | if (location == .StaticInitializer) { |
| ... | @@ -1347,7 +1415,7 @@ pub const DeclGen = struct { | ... | @@ -1347,7 +1415,7 @@ pub const DeclGen = struct { |
| 1347 | try writer.writeAll(")("); | 1415 | try writer.writeAll(")("); |
| 1348 | try dg.renderType(writer, backing_ty); | 1416 | try dg.renderType(writer, backing_ty); |
| 1349 | try writer.writeAll("){"); | 1417 | try writer.writeAll("){"); |
| 1350 | try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type); | 1418 | try dg.renderValue(writer, Value.fromInterned(un.val), location); |
| 1351 | try writer.writeAll("})"); | 1419 | try writer.writeAll("})"); |
| 1352 | }, | 1420 | }, |
| 1353 | else => unreachable, | 1421 | else => unreachable, |
| ... | @@ -1355,7 +1423,7 @@ pub const DeclGen = struct { | ... | @@ -1355,7 +1423,7 @@ pub const DeclGen = struct { |
| 1355 | } else { | 1423 | } else { |
| 1356 | if (!location.isInitializer()) { | 1424 | if (!location.isInitializer()) { |
| 1357 | try writer.writeByte('('); | 1425 | try writer.writeByte('('); |
| 1358 | try dg.renderType(writer, ty); | 1426 | try dg.renderCType(writer, ctype); |
| 1359 | try writer.writeByte(')'); | 1427 | try writer.writeByte(')'); |
| 1360 | } | 1428 | } |
| 1361 | | 1429 | |
| ... | @@ -1366,43 +1434,56 @@ pub const DeclGen = struct { | ... | @@ -1366,43 +1434,56 @@ pub const DeclGen = struct { |
| 1366 | if (field_ty.hasRuntimeBits(zcu)) { | 1434 | if (field_ty.hasRuntimeBits(zcu)) { |
| 1367 | if (field_ty.isPtrAtRuntime(zcu)) { | 1435 | if (field_ty.isPtrAtRuntime(zcu)) { |
| 1368 | try writer.writeByte('('); | 1436 | try writer.writeByte('('); |
| 1369 | try dg.renderType(writer, ty); | 1437 | try dg.renderCType(writer, ctype); |
| 1370 | try writer.writeByte(')'); | 1438 | try writer.writeByte(')'); |
| 1371 | } else if (field_ty.zigTypeTag(zcu) == .Float) { | 1439 | } else if (field_ty.zigTypeTag(zcu) == .Float) { |
| 1372 | try writer.writeByte('('); | 1440 | try writer.writeByte('('); |
| 1373 | try dg.renderType(writer, ty); | 1441 | try dg.renderCType(writer, ctype); |
| 1374 | try writer.writeByte(')'); | 1442 | try writer.writeByte(')'); |
| 1375 | } | 1443 | } |
| 1376 | try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type); | 1444 | try dg.renderValue(writer, Value.fromInterned(un.val), location); |
| 1377 | } else { | 1445 | } else try writer.writeAll("0"); |
| 1378 | try writer.writeAll("0"); | | |
| 1379 | } | | |
| 1380 | return; | 1446 | return; |
| 1381 | } | 1447 | } |
| 1382 | | 1448 | |
| 1383 | try writer.writeByte('{'); | 1449 | const has_tag = loaded_union.hasTag(ip); |
| 1384 | if (ty.unionTagTypeSafety(zcu)) |_| { | 1450 | if (has_tag) try writer.writeByte('{'); |
| 1385 | const layout = zcu.getUnionLayout(loaded_union); | 1451 | const aggregate = ctype.info(ctype_pool).aggregate; |
| 1386 | if (layout.tag_size != 0) { | 1452 | for (0..if (has_tag) aggregate.fields.len else 1) |outer_field_index| { |
| 1387 | try writer.writeAll(" .tag = "); | 1453 | if (outer_field_index > 0) try writer.writeByte(','); |
| 1388 | try dg.renderValue(writer, Value.fromInterned(un.tag), initializer_type); | 1454 | switch (if (has_tag) |
| | 1455 | aggregate.fields.at(outer_field_index, ctype_pool).name.index |
| | 1456 | else |
| | 1457 | .payload) { |
| | 1458 | .tag => try dg.renderValue( |
| | 1459 | writer, |
| | 1460 | Value.fromInterned(un.tag), |
| | 1461 | initializer_type, |
| | 1462 | ), |
| | 1463 | .payload => { |
| | 1464 | try writer.writeByte('{'); |
| | 1465 | if (field_ty.hasRuntimeBits(zcu)) { |
| | 1466 | try writer.print(" .{ } = ", .{fmtIdent(field_name.toSlice(ip))}); |
| | 1467 | try dg.renderValue( |
| | 1468 | writer, |
| | 1469 | Value.fromInterned(un.val), |
| | 1470 | initializer_type, |
| | 1471 | ); |
| | 1472 | try writer.writeByte(' '); |
| | 1473 | } else for (0..loaded_union.field_types.len) |inner_field_index| { |
| | 1474 | const inner_field_ty = Type.fromInterned( |
| | 1475 | loaded_union.field_types.get(ip)[inner_field_index], |
| | 1476 | ); |
| | 1477 | if (!inner_field_ty.hasRuntimeBits(zcu)) continue; |
| | 1478 | try dg.renderUndefValue(writer, inner_field_ty, initializer_type); |
| | 1479 | break; |
| | 1480 | } |
| | 1481 | try writer.writeByte('}'); |
| | 1482 | }, |
| | 1483 | else => unreachable, |
| 1389 | } | 1484 | } |
| 1390 | if (ty.unionHasAllZeroBitFieldTypes(zcu)) return try writer.writeByte('}'); | | |
| 1391 | if (layout.tag_size != 0) try writer.writeByte(','); | | |
| 1392 | try writer.writeAll(" .payload = {"); | | |
| 1393 | } | | |
| 1394 | if (field_ty.hasRuntimeBits(zcu)) { | | |
| 1395 | try writer.print(" .{ } = ", .{fmtIdent(field_name.toSlice(ip))}); | | |
| 1396 | try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type); | | |
| 1397 | try writer.writeByte(' '); | | |
| 1398 | } else for (0..loaded_union.field_types.len) |this_field_index| { | | |
| 1399 | const this_field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[this_field_index]); | | |
| 1400 | if (!this_field_ty.hasRuntimeBits(zcu)) continue; | | |
| 1401 | try dg.renderUndefValue(writer, this_field_ty, initializer_type); | | |
| 1402 | break; | | |
| 1403 | } | 1485 | } |
| 1404 | if (ty.unionTagTypeSafety(zcu)) |_| try writer.writeByte('}'); | 1486 | if (has_tag) try writer.writeByte('}'); |
| 1405 | try writer.writeByte('}'); | | |
| 1406 | } | 1487 | } |
| 1407 | }, | 1488 | }, |
| 1408 | } | 1489 | } |
| ... | @@ -1417,6 +1498,7 @@ pub const DeclGen = struct { | ... | @@ -1417,6 +1498,7 @@ pub const DeclGen = struct { |
| 1417 | const zcu = dg.zcu; | 1498 | const zcu = dg.zcu; |
| 1418 | const ip = &zcu.intern_pool; | 1499 | const ip = &zcu.intern_pool; |
| 1419 | const target = &dg.mod.resolved_target.result; | 1500 | const target = &dg.mod.resolved_target.result; |
| | 1501 | const ctype_pool = &dg.ctype_pool; |
| 1420 | | 1502 | |
| 1421 | const initializer_type: ValueRenderLocation = switch (location) { | 1503 | const initializer_type: ValueRenderLocation = switch (location) { |
| 1422 | .StaticInitializer => .StaticInitializer, | 1504 | .StaticInitializer => .StaticInitializer, |
| ... | @@ -1428,6 +1510,7 @@ pub const DeclGen = struct { | ... | @@ -1428,6 +1510,7 @@ pub const DeclGen = struct { |
| 1428 | .ReleaseFast, .ReleaseSmall => false, | 1510 | .ReleaseFast, .ReleaseSmall => false, |
| 1429 | }; | 1511 | }; |
| 1430 | | 1512 | |
| | 1513 | const ctype = try dg.ctypeFromType(ty, location.toCTypeKind()); |
| 1431 | switch (ty.toIntern()) { | 1514 | switch (ty.toIntern()) { |
| 1432 | .c_longdouble_type, | 1515 | .c_longdouble_type, |
| 1433 | .f16_type, | 1516 | .f16_type, |
| ... | @@ -1465,48 +1548,64 @@ pub const DeclGen = struct { | ... | @@ -1465,48 +1548,64 @@ pub const DeclGen = struct { |
| 1465 | => return writer.print("{x}", .{ | 1548 | => return writer.print("{x}", .{ |
| 1466 | try dg.fmtIntLiteral(try zcu.undefValue(ty), location), | 1549 | try dg.fmtIntLiteral(try zcu.undefValue(ty), location), |
| 1467 | }), | 1550 | }), |
| 1468 | .ptr_type => if (ty.isSlice(zcu)) { | 1551 | .ptr_type => |ptr_type| switch (ptr_type.flags.size) { |
| 1469 | if (!location.isInitializer()) { | 1552 | .One, .Many, .C => { |
| 1470 | try writer.writeByte('('); | 1553 | try writer.writeAll("(("); |
| 1471 | try dg.renderType(writer, ty); | 1554 | try dg.renderCType(writer, ctype); |
| 1472 | try writer.writeByte(')'); | 1555 | return writer.print("){x})", .{ |
| 1473 | } | 1556 | try dg.fmtIntLiteral(try zcu.undefValue(Type.usize), .Other), |
| | 1557 | }); |
| | 1558 | }, |
| | 1559 | .Slice => { |
| | 1560 | if (!location.isInitializer()) { |
| | 1561 | try writer.writeByte('('); |
| | 1562 | try dg.renderCType(writer, ctype); |
| | 1563 | try writer.writeByte(')'); |
| | 1564 | } |
| 1474 | | 1565 | |
| 1475 | try writer.writeAll("{("); | 1566 | try writer.writeAll("{("); |
| 1476 | const ptr_ty = ty.slicePtrFieldType(zcu); | 1567 | const ptr_ty = ty.slicePtrFieldType(zcu); |
| 1477 | try dg.renderType(writer, ptr_ty); | 1568 | try dg.renderType(writer, ptr_ty); |
| 1478 | return writer.print("){x}, {0x}}}", .{ | 1569 | return writer.print("){x}, {0x}}}", .{ |
| 1479 | try dg.fmtIntLiteral(try zcu.undefValue(Type.usize), .Other), | 1570 | try dg.fmtIntLiteral(try zcu.undefValue(Type.usize), .Other), |
| 1480 | }); | 1571 | }); |
| 1481 | } else { | 1572 | }, |
| 1482 | try writer.writeAll("(("); | | |
| 1483 | try dg.renderType(writer, ty); | | |
| 1484 | return writer.print("){x})", .{ | | |
| 1485 | try dg.fmtIntLiteral(try zcu.undefValue(Type.usize), .Other), | | |
| 1486 | }); | | |
| 1487 | }, | 1573 | }, |
| 1488 | .opt_type => { | 1574 | .opt_type => |child_type| switch (ctype.info(ctype_pool)) { |
| 1489 | const payload_ty = ty.optionalChild(zcu); | 1575 | .basic, .pointer => try dg.renderUndefValue( |
| 1490 | | 1576 | writer, |
| 1491 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 1577 | Type.fromInterned(if (ctype.isBool()) .bool_type else child_type), |
| 1492 | return dg.renderUndefValue(writer, Type.bool, location); | 1578 | location, |
| 1493 | } | 1579 | ), |
| 1494 | | 1580 | .aligned, .array, .vector, .fwd_decl, .function => unreachable, |
| 1495 | if (ty.optionalReprIsPayload(zcu)) { | 1581 | .aggregate => |aggregate| { |
| 1496 | return dg.renderUndefValue(writer, payload_ty, location); | 1582 | switch (aggregate.fields.at(0, ctype_pool).name.index) { |
| 1497 | } | 1583 | .is_null, .payload => {}, |
| 1498 | | 1584 | .ptr, .len => return dg.renderUndefValue( |
| 1499 | if (!location.isInitializer()) { | 1585 | writer, |
| 1500 | try writer.writeByte('('); | 1586 | Type.fromInterned(child_type), |
| 1501 | try dg.renderType(writer, ty); | 1587 | location, |
| 1502 | try writer.writeByte(')'); | 1588 | ), |
| 1503 | } | 1589 | else => unreachable, |
| 1504 | | 1590 | } |
| 1505 | try writer.writeAll("{ .payload = "); | 1591 | if (!location.isInitializer()) { |
| 1506 | try dg.renderUndefValue(writer, payload_ty, initializer_type); | 1592 | try writer.writeByte('('); |
| 1507 | try writer.writeAll(", .is_null = "); | 1593 | try dg.renderCType(writer, ctype); |
| 1508 | try dg.renderUndefValue(writer, Type.bool, initializer_type); | 1594 | try writer.writeByte(')'); |
| 1509 | return writer.writeAll(" }"); | 1595 | } |
| | 1596 | try writer.writeByte('{'); |
| | 1597 | for (0..aggregate.fields.len) |field_index| { |
| | 1598 | if (field_index > 0) try writer.writeByte(','); |
| | 1599 | try dg.renderUndefValue(writer, Type.fromInterned( |
| | 1600 | switch (aggregate.fields.at(field_index, ctype_pool).name.index) { |
| | 1601 | .is_null => .bool_type, |
| | 1602 | .payload => child_type, |
| | 1603 | else => unreachable, |
| | 1604 | }, |
| | 1605 | ), initializer_type); |
| | 1606 | } |
| | 1607 | try writer.writeByte('}'); |
| | 1608 | }, |
| 1510 | }, | 1609 | }, |
| 1511 | .struct_type => { | 1610 | .struct_type => { |
| 1512 | const loaded_struct = ip.loadStructType(ty.toIntern()); | 1611 | const loaded_struct = ip.loadStructType(ty.toIntern()); |
| ... | @@ -1514,7 +1613,7 @@ pub const DeclGen = struct { | ... | @@ -1514,7 +1613,7 @@ pub const DeclGen = struct { |
| 1514 | .auto, .@"extern" => { | 1613 | .auto, .@"extern" => { |
| 1515 | if (!location.isInitializer()) { | 1614 | if (!location.isInitializer()) { |
| 1516 | try writer.writeByte('('); | 1615 | try writer.writeByte('('); |
| 1517 | try dg.renderType(writer, ty); | 1616 | try dg.renderCType(writer, ctype); |
| 1518 | try writer.writeByte(')'); | 1617 | try writer.writeByte(')'); |
| 1519 | } | 1618 | } |
| 1520 | | 1619 | |
| ... | @@ -1539,7 +1638,7 @@ pub const DeclGen = struct { | ... | @@ -1539,7 +1638,7 @@ pub const DeclGen = struct { |
| 1539 | .anon_struct_type => |anon_struct_info| { | 1638 | .anon_struct_type => |anon_struct_info| { |
| 1540 | if (!location.isInitializer()) { | 1639 | if (!location.isInitializer()) { |
| 1541 | try writer.writeByte('('); | 1640 | try writer.writeByte('('); |
| 1542 | try dg.renderType(writer, ty); | 1641 | try dg.renderCType(writer, ctype); |
| 1543 | try writer.writeByte(')'); | 1642 | try writer.writeByte(')'); |
| 1544 | } | 1643 | } |
| 1545 | | 1644 | |
| ... | @@ -1562,54 +1661,80 @@ pub const DeclGen = struct { | ... | @@ -1562,54 +1661,80 @@ pub const DeclGen = struct { |
| 1562 | .auto, .@"extern" => { | 1661 | .auto, .@"extern" => { |
| 1563 | if (!location.isInitializer()) { | 1662 | if (!location.isInitializer()) { |
| 1564 | try writer.writeByte('('); | 1663 | try writer.writeByte('('); |
| 1565 | try dg.renderType(writer, ty); | 1664 | try dg.renderCType(writer, ctype); |
| 1566 | try writer.writeByte(')'); | 1665 | try writer.writeByte(')'); |
| 1567 | } | 1666 | } |
| 1568 | | 1667 | |
| 1569 | try writer.writeByte('{'); | 1668 | const has_tag = loaded_union.hasTag(ip); |
| 1570 | if (ty.unionTagTypeSafety(zcu)) |tag_ty| { | 1669 | if (has_tag) try writer.writeByte('{'); |
| 1571 | const layout = ty.unionGetLayout(zcu); | 1670 | const aggregate = ctype.info(ctype_pool).aggregate; |
| 1572 | if (layout.tag_size != 0) { | 1671 | for (0..if (has_tag) aggregate.fields.len else 1) |outer_field_index| { |
| 1573 | try writer.writeAll(" .tag = "); | 1672 | if (outer_field_index > 0) try writer.writeByte(','); |
| 1574 | try dg.renderUndefValue(writer, tag_ty, initializer_type); | 1673 | switch (if (has_tag) |
| | 1674 | aggregate.fields.at(outer_field_index, ctype_pool).name.index |
| | 1675 | else |
| | 1676 | .payload) { |
| | 1677 | .tag => try dg.renderUndefValue( |
| | 1678 | writer, |
| | 1679 | Type.fromInterned(loaded_union.enum_tag_ty), |
| | 1680 | initializer_type, |
| | 1681 | ), |
| | 1682 | .payload => { |
| | 1683 | try writer.writeByte('{'); |
| | 1684 | for (0..loaded_union.field_types.len) |inner_field_index| { |
| | 1685 | const inner_field_ty = Type.fromInterned( |
| | 1686 | loaded_union.field_types.get(ip)[inner_field_index], |
| | 1687 | ); |
| | 1688 | if (!inner_field_ty.hasRuntimeBits(zcu)) continue; |
| | 1689 | try dg.renderUndefValue( |
| | 1690 | writer, |
| | 1691 | inner_field_ty, |
| | 1692 | initializer_type, |
| | 1693 | ); |
| | 1694 | break; |
| | 1695 | } |
| | 1696 | try writer.writeByte('}'); |
| | 1697 | }, |
| | 1698 | else => unreachable, |
| 1575 | } | 1699 | } |
| 1576 | if (ty.unionHasAllZeroBitFieldTypes(zcu)) return try writer.writeByte('}'); | | |
| 1577 | if (layout.tag_size != 0) try writer.writeByte(','); | | |
| 1578 | try writer.writeAll(" .payload = {"); | | |
| 1579 | } | | |
| 1580 | for (0..loaded_union.field_types.len) |field_index| { | | |
| 1581 | const field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]); | | |
| 1582 | if (!field_ty.hasRuntimeBits(zcu)) continue; | | |
| 1583 | try dg.renderUndefValue(writer, field_ty, initializer_type); | | |
| 1584 | break; | | |
| 1585 | } | 1700 | } |
| 1586 | if (ty.unionTagTypeSafety(zcu)) |_| try writer.writeByte('}'); | 1701 | if (has_tag) try writer.writeByte('}'); |
| 1587 | return writer.writeByte('}'); | | |
| 1588 | }, | 1702 | }, |
| 1589 | .@"packed" => return writer.print("{x}", .{ | 1703 | .@"packed" => return writer.print("{x}", .{ |
| 1590 | try dg.fmtIntLiteral(try zcu.undefValue(ty), .Other), | 1704 | try dg.fmtIntLiteral(try zcu.undefValue(ty), .Other), |
| 1591 | }), | 1705 | }), |
| 1592 | } | 1706 | } |
| 1593 | }, | 1707 | }, |
| 1594 | .error_union_type => { | 1708 | .error_union_type => |error_union_type| switch (ctype.info(ctype_pool)) { |
| 1595 | const payload_ty = ty.errorUnionPayload(zcu); | 1709 | .basic => try dg.renderUndefValue( |
| 1596 | const error_ty = ty.errorUnionSet(zcu); | 1710 | writer, |
| 1597 | | 1711 | Type.fromInterned(error_union_type.error_set_type), |
| 1598 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 1712 | location, |
| 1599 | return dg.renderUndefValue(writer, error_ty, location); | 1713 | ), |
| 1600 | } | 1714 | .pointer, .aligned, .array, .vector, .fwd_decl, .function => unreachable, |
| 1601 | | 1715 | .aggregate => |aggregate| { |
| 1602 | if (!location.isInitializer()) { | 1716 | if (!location.isInitializer()) { |
| 1603 | try writer.writeByte('('); | 1717 | try writer.writeByte('('); |
| 1604 | try dg.renderType(writer, ty); | 1718 | try dg.renderCType(writer, ctype); |
| 1605 | try writer.writeByte(')'); | 1719 | try writer.writeByte(')'); |
| 1606 | } | 1720 | } |
| 1607 | | 1721 | try writer.writeByte('{'); |
| 1608 | try writer.writeAll("{ .payload = "); | 1722 | for (0..aggregate.fields.len) |field_index| { |
| 1609 | try dg.renderUndefValue(writer, payload_ty, initializer_type); | 1723 | if (field_index > 0) try writer.writeByte(','); |
| 1610 | try writer.writeAll(", .error = "); | 1724 | try dg.renderUndefValue( |
| 1611 | try dg.renderUndefValue(writer, error_ty, initializer_type); | 1725 | writer, |
| 1612 | return writer.writeAll(" }"); | 1726 | Type.fromInterned( |
| | 1727 | switch (aggregate.fields.at(field_index, ctype_pool).name.index) { |
| | 1728 | .@"error" => error_union_type.error_set_type, |
| | 1729 | .payload => error_union_type.payload_type, |
| | 1730 | else => unreachable, |
| | 1731 | }, |
| | 1732 | ), |
| | 1733 | initializer_type, |
| | 1734 | ); |
| | 1735 | } |
| | 1736 | try writer.writeByte('}'); |
| | 1737 | }, |
| 1613 | }, | 1738 | }, |
| 1614 | .array_type, .vector_type => { | 1739 | .array_type, .vector_type => { |
| 1615 | const ai = ty.arrayInfo(zcu); | 1740 | const ai = ty.arrayInfo(zcu); |
| ... | @@ -1624,7 +1749,7 @@ pub const DeclGen = struct { | ... | @@ -1624,7 +1749,7 @@ pub const DeclGen = struct { |
| 1624 | } else { | 1749 | } else { |
| 1625 | if (!location.isInitializer()) { | 1750 | if (!location.isInitializer()) { |
| 1626 | try writer.writeByte('('); | 1751 | try writer.writeByte('('); |
| 1627 | try dg.renderType(writer, ty); | 1752 | try dg.renderCType(writer, ctype); |
| 1628 | try writer.writeByte(')'); | 1753 | try writer.writeByte(')'); |
| 1629 | } | 1754 | } |
| 1630 | | 1755 | |
| ... | @@ -1674,6 +1799,7 @@ pub const DeclGen = struct { | ... | @@ -1674,6 +1799,7 @@ pub const DeclGen = struct { |
| 1674 | name: union(enum) { | 1799 | name: union(enum) { |
| 1675 | export_index: u32, | 1800 | export_index: u32, |
| 1676 | ident: []const u8, | 1801 | ident: []const u8, |
| | 1802 | fmt_ctype_pool_string: std.fmt.Formatter(formatCTypePoolString), |
| 1677 | }, | 1803 | }, |
| 1678 | ) !void { | 1804 | ) !void { |
| 1679 | const zcu = dg.zcu; | 1805 | const zcu = dg.zcu; |
| ... | @@ -1717,6 +1843,7 @@ pub const DeclGen = struct { | ... | @@ -1717,6 +1843,7 @@ pub const DeclGen = struct { |
| 1717 | try dg.renderDeclName(w, fn_decl_index, export_index); | 1843 | try dg.renderDeclName(w, fn_decl_index, export_index); |
| 1718 | }, | 1844 | }, |
| 1719 | .ident => |ident| try w.print("{}{ }", .{ trailing, fmtIdent(ident) }), | 1845 | .ident => |ident| try w.print("{}{ }", .{ trailing, fmtIdent(ident) }), |
| | 1846 | .fmt_ctype_pool_string => |fmt| try w.print("{}{ }", .{ trailing, fmt }), |
| 1720 | } | 1847 | } |
| 1721 | | 1848 | |
| 1722 | try renderTypeSuffix( | 1849 | try renderTypeSuffix( |
| ... | @@ -1772,7 +1899,7 @@ pub const DeclGen = struct { | ... | @@ -1772,7 +1899,7 @@ pub const DeclGen = struct { |
| 1772 | }); | 1899 | }); |
| 1773 | } | 1900 | } |
| 1774 | }, | 1901 | }, |
| 1775 | .ident => {}, | 1902 | .ident, .fmt_ctype_pool_string => {}, |
| 1776 | } | 1903 | } |
| 1777 | }, | 1904 | }, |
| 1778 | .complete => {}, | 1905 | .complete => {}, |
| ... | @@ -1800,11 +1927,11 @@ pub const DeclGen = struct { | ... | @@ -1800,11 +1927,11 @@ pub const DeclGen = struct { |
| 1800 | /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" | | 1927 | /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" | |
| 1801 | /// | `renderType` | "uint8_t *" | "uint8_t *[10]" | | 1928 | /// | `renderType` | "uint8_t *" | "uint8_t *[10]" | |
| 1802 | /// | 1929 | /// |
| 1803 | fn renderType(dg: *DeclGen, w: anytype, t: Type) error{ OutOfMemory, AnalysisFail }!void { | 1930 | fn renderType(dg: *DeclGen, w: anytype, t: Type) error{OutOfMemory}!void { |
| 1804 | try dg.renderCType(w, try dg.ctypeFromType(t, .complete)); | 1931 | try dg.renderCType(w, try dg.ctypeFromType(t, .complete)); |
| 1805 | } | 1932 | } |
| 1806 | | 1933 | |
| 1807 | fn renderCType(dg: *DeclGen, w: anytype, ctype: CType) error{ OutOfMemory, AnalysisFail }!void { | 1934 | fn renderCType(dg: *DeclGen, w: anytype, ctype: CType) error{OutOfMemory}!void { |
| 1808 | _ = try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{}); | 1935 | _ = try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{}); |
| 1809 | try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{}); | 1936 | try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{}); |
| 1810 | } | 1937 | } |
| ... | @@ -1829,7 +1956,26 @@ pub const DeclGen = struct { | ... | @@ -1829,7 +1956,26 @@ pub const DeclGen = struct { |
| 1829 | } | 1956 | } |
| 1830 | } | 1957 | } |
| 1831 | }; | 1958 | }; |
| | 1959 | fn intCastIsNoop(dg: *DeclGen, dest_ty: Type, src_ty: Type) bool { |
| | 1960 | const zcu = dg.zcu; |
| | 1961 | const dest_bits = dest_ty.bitSize(zcu); |
| | 1962 | const dest_int_info = dest_ty.intInfo(zcu); |
| | 1963 | |
| | 1964 | const src_is_ptr = src_ty.isPtrAtRuntime(zcu); |
| | 1965 | const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) { |
| | 1966 | .unsigned => Type.usize, |
| | 1967 | .signed => Type.isize, |
| | 1968 | } else src_ty; |
| 1832 | | 1969 | |
| | 1970 | const src_bits = src_eff_ty.bitSize(zcu); |
| | 1971 | const src_int_info = if (src_eff_ty.isAbiInt(zcu)) src_eff_ty.intInfo(zcu) else null; |
| | 1972 | if (dest_bits <= 64 and src_bits <= 64) { |
| | 1973 | const needs_cast = src_int_info == null or |
| | 1974 | (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or |
| | 1975 | dest_int_info.signedness != src_int_info.?.signedness); |
| | 1976 | return !needs_cast and !src_is_ptr; |
| | 1977 | } else return false; |
| | 1978 | } |
| 1833 | /// Renders a cast to an int type, from either an int or a pointer. | 1979 | /// Renders a cast to an int type, from either an int or a pointer. |
| 1834 | /// | 1980 | /// |
| 1835 | /// Some platforms don't have 128 bit integers, so we need to use | 1981 | /// Some platforms don't have 128 bit integers, so we need to use |
| ... | @@ -1843,7 +1989,14 @@ pub const DeclGen = struct { | ... | @@ -1843,7 +1989,14 @@ pub const DeclGen = struct { |
| 1843 | /// | > 64 bit integer | pointer | zig_make_<dest_ty>(0, (zig_<u|i>size)src) | 1989 | /// | > 64 bit integer | pointer | zig_make_<dest_ty>(0, (zig_<u|i>size)src) |
| 1844 | /// | > 64 bit integer | < 64 bit integer | zig_make_<dest_ty>(0, src) | 1990 | /// | > 64 bit integer | < 64 bit integer | zig_make_<dest_ty>(0, src) |
| 1845 | /// | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src)) | 1991 | /// | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src)) |
| 1846 | fn renderIntCast(dg: *DeclGen, w: anytype, dest_ty: Type, context: IntCastContext, src_ty: Type, location: ValueRenderLocation) !void { | 1992 | fn renderIntCast( |
| | 1993 | dg: *DeclGen, |
| | 1994 | w: anytype, |
| | 1995 | dest_ty: Type, |
| | 1996 | context: IntCastContext, |
| | 1997 | src_ty: Type, |
| | 1998 | location: ValueRenderLocation, |
| | 1999 | ) !void { |
| 1847 | const zcu = dg.zcu; | 2000 | const zcu = dg.zcu; |
| 1848 | const dest_bits = dest_ty.bitSize(zcu); | 2001 | const dest_bits = dest_ty.bitSize(zcu); |
| 1849 | const dest_int_info = dest_ty.intInfo(zcu); | 2002 | const dest_int_info = dest_ty.intInfo(zcu); |
| ... | @@ -1998,12 +2151,23 @@ pub const DeclGen = struct { | ... | @@ -1998,12 +2151,23 @@ pub const DeclGen = struct { |
| 1998 | fmtIdent("payload"), | 2151 | fmtIdent("payload"), |
| 1999 | fmtIdent(ident), | 2152 | fmtIdent(ident), |
| 2000 | }), | 2153 | }), |
| | 2154 | .ctype_pool_string => |string| try w.print("{ }", .{ |
| | 2155 | fmtCTypePoolString(string, &dg.ctype_pool), |
| | 2156 | }), |
| 2001 | } | 2157 | } |
| 2002 | } | 2158 | } |
| 2003 | | 2159 | |
| 2004 | fn writeCValueDeref(dg: *DeclGen, w: anytype, c_value: CValue) !void { | 2160 | fn writeCValueDeref(dg: *DeclGen, w: anytype, c_value: CValue) !void { |
| 2005 | switch (c_value) { | 2161 | switch (c_value) { |
| 2006 | .none, .new_local, .local, .local_ref, .constant, .arg, .arg_array => unreachable, | 2162 | .none, |
| | 2163 | .new_local, |
| | 2164 | .local, |
| | 2165 | .local_ref, |
| | 2166 | .constant, |
| | 2167 | .arg, |
| | 2168 | .arg_array, |
| | 2169 | .ctype_pool_string, |
| | 2170 | => unreachable, |
| 2007 | .field => |i| try w.print("f{d}", .{i}), | 2171 | .field => |i| try w.print("f{d}", .{i}), |
| 2008 | .decl => |decl| { | 2172 | .decl => |decl| { |
| 2009 | try w.writeAll("(*"); | 2173 | try w.writeAll("(*"); |
| ... | @@ -2033,7 +2197,17 @@ pub const DeclGen = struct { | ... | @@ -2033,7 +2197,17 @@ pub const DeclGen = struct { |
| 2033 | | 2197 | |
| 2034 | fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void { | 2198 | fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void { |
| 2035 | switch (c_value) { | 2199 | switch (c_value) { |
| 2036 | .none, .new_local, .local, .local_ref, .constant, .field, .undef, .arg, .arg_array => unreachable, | 2200 | .none, |
| | 2201 | .new_local, |
| | 2202 | .local, |
| | 2203 | .local_ref, |
| | 2204 | .constant, |
| | 2205 | .field, |
| | 2206 | .undef, |
| | 2207 | .arg, |
| | 2208 | .arg_array, |
| | 2209 | .ctype_pool_string, |
| | 2210 | => unreachable, |
| 2037 | .decl, .identifier, .payload_identifier => { | 2211 | .decl, .identifier, .payload_identifier => { |
| 2038 | try dg.writeCValue(writer, c_value); | 2212 | try dg.writeCValue(writer, c_value); |
| 2039 | try writer.writeAll("->"); | 2213 | try writer.writeAll("->"); |
| ... | @@ -2172,11 +2346,7 @@ pub const DeclGen = struct { | ... | @@ -2172,11 +2346,7 @@ pub const DeclGen = struct { |
| 2172 | loc: ValueRenderLocation, | 2346 | loc: ValueRenderLocation, |
| 2173 | ) !std.fmt.Formatter(formatIntLiteral) { | 2347 | ) !std.fmt.Formatter(formatIntLiteral) { |
| 2174 | const zcu = dg.zcu; | 2348 | const zcu = dg.zcu; |
| 2175 | const kind: CType.Kind = switch (loc) { | 2349 | const kind = loc.toCTypeKind(); |
| 2176 | .FunctionArgument => .parameter, | | |
| 2177 | .Initializer, .Other => .complete, | | |
| 2178 | .StaticInitializer => .global, | | |
| 2179 | }; | | |
| 2180 | const ty = val.typeOf(zcu); | 2350 | const ty = val.typeOf(zcu); |
| 2181 | return std.fmt.Formatter(formatIntLiteral){ .data = .{ | 2351 | return std.fmt.Formatter(formatIntLiteral){ .data = .{ |
| 2182 | .dg = dg, | 2352 | .dg = dg, |
| ... | @@ -2439,7 +2609,7 @@ fn renderFields( | ... | @@ -2439,7 +2609,7 @@ fn renderFields( |
| 2439 | .suffix, | 2609 | .suffix, |
| 2440 | .{}, | 2610 | .{}, |
| 2441 | ); | 2611 | ); |
| 2442 | try writer.print("{}{ }", .{ trailing, fmtIdent(field_info.name.slice(ctype_pool)) }); | 2612 | try writer.print("{}{ }", .{ trailing, fmtCTypePoolString(field_info.name, ctype_pool) }); |
| 2443 | try renderTypeSuffix(.flush, ctype_pool, zcu, writer, field_info.ctype, .suffix, .{}); | 2613 | try renderTypeSuffix(.flush, ctype_pool, zcu, writer, field_info.ctype, .suffix, .{}); |
| 2444 | try writer.writeAll(";\n"); | 2614 | try writer.writeAll(";\n"); |
| 2445 | } | 2615 | } |
| ... | @@ -2698,9 +2868,7 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn | ... | @@ -2698,9 +2868,7 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn |
| 2698 | | 2868 | |
| 2699 | try w.writeAll("static "); | 2869 | try w.writeAll("static "); |
| 2700 | try o.dg.renderType(w, name_slice_ty); | 2870 | try o.dg.renderType(w, name_slice_ty); |
| 2701 | try w.writeByte(' '); | 2871 | try w.print(" {}(", .{val.fn_name.fmt(lazy_ctype_pool)}); |
| 2702 | try w.writeAll(val.fn_name.slice(lazy_ctype_pool)); | | |
| 2703 | try w.writeByte('('); | | |
| 2704 | try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, .none, .complete); | 2872 | try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, .none, .complete); |
| 2705 | try w.writeAll(") {\n switch (tag) {\n"); | 2873 | try w.writeAll(") {\n switch (tag) {\n"); |
| 2706 | const tag_names = enum_ty.enumFields(zcu); | 2874 | const tag_names = enum_ty.enumFields(zcu); |
| ... | @@ -2744,21 +2912,18 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn | ... | @@ -2744,21 +2912,18 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn |
| 2744 | const fn_decl = zcu.declPtr(fn_decl_index); | 2912 | const fn_decl = zcu.declPtr(fn_decl_index); |
| 2745 | const fn_ctype = try o.dg.ctypeFromType(fn_decl.typeOf(zcu), .complete); | 2913 | const fn_ctype = try o.dg.ctypeFromType(fn_decl.typeOf(zcu), .complete); |
| 2746 | const fn_info = fn_ctype.info(ctype_pool).function; | 2914 | const fn_info = fn_ctype.info(ctype_pool).function; |
| 2747 | const fn_name = val.fn_name.slice(lazy_ctype_pool); | 2915 | const fn_name = fmtCTypePoolString(val.fn_name, lazy_ctype_pool); |
| 2748 | | 2916 | |
| 2749 | const fwd_decl_writer = o.dg.fwdDeclWriter(); | 2917 | const fwd_decl_writer = o.dg.fwdDeclWriter(); |
| 2750 | try fwd_decl_writer.print("static zig_{s} ", .{@tagName(key)}); | 2918 | try fwd_decl_writer.print("static zig_{s} ", .{@tagName(key)}); |
| 2751 | try o.dg.renderFunctionSignature( | 2919 | try o.dg.renderFunctionSignature(fwd_decl_writer, fn_decl_index, .forward, .{ |
| 2752 | fwd_decl_writer, | 2920 | .fmt_ctype_pool_string = fn_name, |
| 2753 | fn_decl_index, | 2921 | }); |
| 2754 | .forward, | | |
| 2755 | .{ .ident = fn_name }, | | |
| 2756 | ); | | |
| 2757 | try fwd_decl_writer.writeAll(";\n"); | 2922 | try fwd_decl_writer.writeAll(";\n"); |
| 2758 | | 2923 | |
| 2759 | try w.print("static zig_{s} ", .{@tagName(key)}); | 2924 | try w.print("static zig_{s} ", .{@tagName(key)}); |
| 2760 | try o.dg.renderFunctionSignature(w, fn_decl_index, .complete, .{ | 2925 | try o.dg.renderFunctionSignature(w, fn_decl_index, .complete, .{ |
| 2761 | .ident = fn_name, | 2926 | .fmt_ctype_pool_string = fn_name, |
| 2762 | }); | 2927 | }); |
| 2763 | try w.writeAll(" {\n return "); | 2928 | try w.writeAll(" {\n return "); |
| 2764 | try o.dg.renderDeclName(w, fn_decl_index, 0); | 2929 | try o.dg.renderDeclName(w, fn_decl_index, 0); |
| ... | @@ -3143,8 +3308,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, | ... | @@ -3143,8 +3308,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 3143 | .shl_exact => try airBinOp(f, inst, "<<", "shl", .none), | 3308 | .shl_exact => try airBinOp(f, inst, "<<", "shl", .none), |
| 3144 | .not => try airNot (f, inst), | 3309 | .not => try airNot (f, inst), |
| 3145 | | 3310 | |
| 3146 | .optional_payload => try airOptionalPayload(f, inst), | 3311 | .optional_payload => try airOptionalPayload(f, inst, false), |
| 3147 | .optional_payload_ptr => try airOptionalPayloadPtr(f, inst), | 3312 | .optional_payload_ptr => try airOptionalPayload(f, inst, true), |
| 3148 | .optional_payload_ptr_set => try airOptionalPayloadPtrSet(f, inst), | 3313 | .optional_payload_ptr_set => try airOptionalPayloadPtrSet(f, inst), |
| 3149 | .wrap_optional => try airWrapOptional(f, inst), | 3314 | .wrap_optional => try airWrapOptional(f, inst), |
| 3150 | | 3315 | |
| ... | @@ -3153,10 +3318,10 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, | ... | @@ -3153,10 +3318,10 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 3153 | .is_err_ptr => try airIsErr(f, inst, true, "!="), | 3318 | .is_err_ptr => try airIsErr(f, inst, true, "!="), |
| 3154 | .is_non_err_ptr => try airIsErr(f, inst, true, "=="), | 3319 | .is_non_err_ptr => try airIsErr(f, inst, true, "=="), |
| 3155 | | 3320 | |
| 3156 | .is_null => try airIsNull(f, inst, "==", false), | 3321 | .is_null => try airIsNull(f, inst, .eq, false), |
| 3157 | .is_non_null => try airIsNull(f, inst, "!=", false), | 3322 | .is_non_null => try airIsNull(f, inst, .neq, false), |
| 3158 | .is_null_ptr => try airIsNull(f, inst, "==", true), | 3323 | .is_null_ptr => try airIsNull(f, inst, .eq, true), |
| 3159 | .is_non_null_ptr => try airIsNull(f, inst, "!=", true), | 3324 | .is_non_null_ptr => try airIsNull(f, inst, .neq, true), |
| 3160 | | 3325 | |
| 3161 | .alloc => try airAlloc(f, inst), | 3326 | .alloc => try airAlloc(f, inst), |
| 3162 | .ret_ptr => try airRetPtr(f, inst), | 3327 | .ret_ptr => try airRetPtr(f, inst), |
| ... | @@ -3239,8 +3404,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, | ... | @@ -3239,8 +3404,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 3239 | .slice_ptr => try airSliceField(f, inst, false, "ptr"), | 3404 | .slice_ptr => try airSliceField(f, inst, false, "ptr"), |
| 3240 | .slice_len => try airSliceField(f, inst, false, "len"), | 3405 | .slice_len => try airSliceField(f, inst, false, "len"), |
| 3241 | | 3406 | |
| 3242 | .ptr_slice_len_ptr => try airSliceField(f, inst, true, "len"), | | |
| 3243 | .ptr_slice_ptr_ptr => try airSliceField(f, inst, true, "ptr"), | 3407 | .ptr_slice_ptr_ptr => try airSliceField(f, inst, true, "ptr"), |
| | 3408 | .ptr_slice_len_ptr => try airSliceField(f, inst, true, "len"), |
| 3244 | | 3409 | |
| 3245 | .ptr_elem_val => try airPtrElemVal(f, inst), | 3410 | .ptr_elem_val => try airPtrElemVal(f, inst), |
| 3246 | .ptr_elem_ptr => try airPtrElemPtr(f, inst), | 3411 | .ptr_elem_ptr => try airPtrElemPtr(f, inst), |
| ... | @@ -3308,7 +3473,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, | ... | @@ -3308,7 +3473,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, |
| 3308 | } | 3473 | } |
| 3309 | try f.value_map.putNoClobber(inst.toRef(), switch (result_value) { | 3474 | try f.value_map.putNoClobber(inst.toRef(), switch (result_value) { |
| 3310 | .none => continue, | 3475 | .none => continue, |
| 3311 | .new_local => |i| .{ .local = i }, | 3476 | .new_local => |local_index| .{ .local = local_index }, |
| 3312 | else => result_value, | 3477 | else => result_value, |
| 3313 | }); | 3478 | }); |
| 3314 | } | 3479 | } |
| ... | @@ -3323,7 +3488,7 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [ | ... | @@ -3323,7 +3488,7 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [ |
| 3323 | | 3488 | |
| 3324 | const writer = f.object.writer(); | 3489 | const writer = f.object.writer(); |
| 3325 | const local = try f.allocLocal(inst, inst_ty); | 3490 | const local = try f.allocLocal(inst, inst_ty); |
| 3326 | const a = try Assignment.start(f, writer, inst_ty); | 3491 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); |
| 3327 | try f.writeCValue(writer, local, .Other); | 3492 | try f.writeCValue(writer, local, .Other); |
| 3328 | try a.assign(f, writer); | 3493 | try a.assign(f, writer); |
| 3329 | if (is_ptr) { | 3494 | if (is_ptr) { |
| ... | @@ -3349,7 +3514,7 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3349,7 +3514,7 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3349 | | 3514 | |
| 3350 | const writer = f.object.writer(); | 3515 | const writer = f.object.writer(); |
| 3351 | const local = try f.allocLocal(inst, inst_ty); | 3516 | const local = try f.allocLocal(inst, inst_ty); |
| 3352 | const a = try Assignment.start(f, writer, inst_ty); | 3517 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); |
| 3353 | try f.writeCValue(writer, local, .Other); | 3518 | try f.writeCValue(writer, local, .Other); |
| 3354 | try a.assign(f, writer); | 3519 | try a.assign(f, writer); |
| 3355 | try f.writeCValue(writer, ptr, .Other); | 3520 | try f.writeCValue(writer, ptr, .Other); |
| ... | @@ -3375,7 +3540,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3375,7 +3540,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3375 | | 3540 | |
| 3376 | const writer = f.object.writer(); | 3541 | const writer = f.object.writer(); |
| 3377 | const local = try f.allocLocal(inst, inst_ty); | 3542 | const local = try f.allocLocal(inst, inst_ty); |
| 3378 | const a = try Assignment.start(f, writer, inst_ty); | 3543 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); |
| 3379 | try f.writeCValue(writer, local, .Other); | 3544 | try f.writeCValue(writer, local, .Other); |
| 3380 | try a.assign(f, writer); | 3545 | try a.assign(f, writer); |
| 3381 | try writer.writeByte('('); | 3546 | try writer.writeByte('('); |
| ... | @@ -3410,7 +3575,7 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3410,7 +3575,7 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3410 | | 3575 | |
| 3411 | const writer = f.object.writer(); | 3576 | const writer = f.object.writer(); |
| 3412 | const local = try f.allocLocal(inst, inst_ty); | 3577 | const local = try f.allocLocal(inst, inst_ty); |
| 3413 | const a = try Assignment.start(f, writer, inst_ty); | 3578 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); |
| 3414 | try f.writeCValue(writer, local, .Other); | 3579 | try f.writeCValue(writer, local, .Other); |
| 3415 | try a.assign(f, writer); | 3580 | try a.assign(f, writer); |
| 3416 | try f.writeCValueMember(writer, slice, .{ .identifier = "ptr" }); | 3581 | try f.writeCValueMember(writer, slice, .{ .identifier = "ptr" }); |
| ... | @@ -3437,7 +3602,7 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3437,7 +3602,7 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3437 | | 3602 | |
| 3438 | const writer = f.object.writer(); | 3603 | const writer = f.object.writer(); |
| 3439 | const local = try f.allocLocal(inst, inst_ty); | 3604 | const local = try f.allocLocal(inst, inst_ty); |
| 3440 | const a = try Assignment.start(f, writer, inst_ty); | 3605 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); |
| 3441 | try f.writeCValue(writer, local, .Other); | 3606 | try f.writeCValue(writer, local, .Other); |
| 3442 | try a.assign(f, writer); | 3607 | try a.assign(f, writer); |
| 3443 | if (elem_has_bits) try writer.writeByte('&'); | 3608 | if (elem_has_bits) try writer.writeByte('&'); |
| ... | @@ -3466,7 +3631,7 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3466,7 +3631,7 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3466 | | 3631 | |
| 3467 | const writer = f.object.writer(); | 3632 | const writer = f.object.writer(); |
| 3468 | const local = try f.allocLocal(inst, inst_ty); | 3633 | const local = try f.allocLocal(inst, inst_ty); |
| 3469 | const a = try Assignment.start(f, writer, inst_ty); | 3634 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); |
| 3470 | try f.writeCValue(writer, local, .Other); | 3635 | try f.writeCValue(writer, local, .Other); |
| 3471 | try a.assign(f, writer); | 3636 | try a.assign(f, writer); |
| 3472 | try f.writeCValue(writer, array, .Other); | 3637 | try f.writeCValue(writer, array, .Other); |
| ... | @@ -3691,17 +3856,18 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3691,17 +3856,18 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3691 | const operand_ty = f.typeOf(ty_op.operand); | 3856 | const operand_ty = f.typeOf(ty_op.operand); |
| 3692 | const scalar_ty = operand_ty.scalarType(zcu); | 3857 | const scalar_ty = operand_ty.scalarType(zcu); |
| 3693 | | 3858 | |
| | 3859 | if (f.object.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) return f.moveCValue(inst, inst_ty, operand); |
| | 3860 | |
| 3694 | const writer = f.object.writer(); | 3861 | const writer = f.object.writer(); |
| 3695 | const local = try f.allocLocal(inst, inst_ty); | 3862 | const local = try f.allocLocal(inst, inst_ty); |
| 3696 | const v = try Vectorize.start(f, inst, writer, operand_ty); | 3863 | const v = try Vectorize.start(f, inst, writer, operand_ty); |
| 3697 | const a = try Assignment.start(f, writer, scalar_ty); | 3864 | const a = try Assignment.start(f, writer, try f.ctypeFromType(scalar_ty, .complete)); |
| 3698 | try f.writeCValue(writer, local, .Other); | 3865 | try f.writeCValue(writer, local, .Other); |
| 3699 | try v.elem(f, writer); | 3866 | try v.elem(f, writer); |
| 3700 | try a.assign(f, writer); | 3867 | try a.assign(f, writer); |
| 3701 | try f.renderIntCast(writer, inst_scalar_ty, operand, v, scalar_ty, .Other); | 3868 | try f.renderIntCast(writer, inst_scalar_ty, operand, v, scalar_ty, .Other); |
| 3702 | try a.end(f, writer); | 3869 | try a.end(f, writer); |
| 3703 | try v.end(f, inst, writer); | 3870 | try v.end(f, inst, writer); |
| 3704 | | | |
| 3705 | return local; | 3871 | return local; |
| 3706 | } | 3872 | } |
| 3707 | | 3873 | |
| ... | @@ -3711,38 +3877,40 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3711,38 +3877,40 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3711 | | 3877 | |
| 3712 | const operand = try f.resolveInst(ty_op.operand); | 3878 | const operand = try f.resolveInst(ty_op.operand); |
| 3713 | try reap(f, inst, &.{ty_op.operand}); | 3879 | try reap(f, inst, &.{ty_op.operand}); |
| | 3880 | |
| 3714 | const inst_ty = f.typeOfIndex(inst); | 3881 | const inst_ty = f.typeOfIndex(inst); |
| 3715 | const inst_scalar_ty = inst_ty.scalarType(zcu); | 3882 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 3716 | const dest_int_info = inst_scalar_ty.intInfo(zcu); | 3883 | const dest_int_info = inst_scalar_ty.intInfo(zcu); |
| 3717 | const dest_bits = dest_int_info.bits; | 3884 | const dest_bits = dest_int_info.bits; |
| 3718 | const dest_c_bits = toCIntBits(dest_int_info.bits) orelse | 3885 | const dest_c_bits = toCIntBits(dest_bits) orelse |
| 3719 | return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); | 3886 | return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); |
| 3720 | const operand_ty = f.typeOf(ty_op.operand); | 3887 | const operand_ty = f.typeOf(ty_op.operand); |
| 3721 | const scalar_ty = operand_ty.scalarType(zcu); | 3888 | const scalar_ty = operand_ty.scalarType(zcu); |
| 3722 | const scalar_int_info = scalar_ty.intInfo(zcu); | 3889 | const scalar_int_info = scalar_ty.intInfo(zcu); |
| 3723 | | 3890 | |
| | 3891 | const need_cast = dest_c_bits < 64; |
| | 3892 | const need_lo = scalar_int_info.bits > 64 and dest_bits <= 64; |
| | 3893 | const need_mask = dest_bits < 8 or !std.math.isPowerOfTwo(dest_bits); |
| | 3894 | if (!need_cast and !need_lo and !need_mask) return f.moveCValue(inst, inst_ty, operand); |
| | 3895 | |
| 3724 | const writer = f.object.writer(); | 3896 | const writer = f.object.writer(); |
| 3725 | const local = try f.allocLocal(inst, inst_ty); | 3897 | const local = try f.allocLocal(inst, inst_ty); |
| 3726 | const v = try Vectorize.start(f, inst, writer, operand_ty); | 3898 | const v = try Vectorize.start(f, inst, writer, operand_ty); |
| 3727 | | 3899 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_scalar_ty, .complete)); |
| 3728 | try f.writeCValue(writer, local, .Other); | 3900 | try f.writeCValue(writer, local, .Other); |
| 3729 | try v.elem(f, writer); | 3901 | try v.elem(f, writer); |
| 3730 | try writer.writeAll(" = "); | 3902 | try a.assign(f, writer); |
| 3731 | | 3903 | if (need_cast) { |
| 3732 | if (dest_c_bits < 64) { | | |
| 3733 | try writer.writeByte('('); | 3904 | try writer.writeByte('('); |
| 3734 | try f.renderType(writer, inst_scalar_ty); | 3905 | try f.renderType(writer, inst_scalar_ty); |
| 3735 | try writer.writeByte(')'); | 3906 | try writer.writeByte(')'); |
| 3736 | } | 3907 | } |
| 3737 | | 3908 | if (need_lo) { |
| 3738 | const needs_lo = scalar_int_info.bits > 64 and dest_bits <= 64; | | |
| 3739 | if (needs_lo) { | | |
| 3740 | try writer.writeAll("zig_lo_"); | 3909 | try writer.writeAll("zig_lo_"); |
| 3741 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); | 3910 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); |
| 3742 | try writer.writeByte('('); | 3911 | try writer.writeByte('('); |
| 3743 | } | 3912 | } |
| 3744 | | 3913 | if (!need_mask) { |
| 3745 | if (dest_bits >= 8 and std.math.isPowerOfTwo(dest_bits)) { | | |
| 3746 | try f.writeCValue(writer, operand, .Other); | 3914 | try f.writeCValue(writer, operand, .Other); |
| 3747 | try v.elem(f, writer); | 3915 | try v.elem(f, writer); |
| 3748 | } else switch (dest_int_info.signedness) { | 3916 | } else switch (dest_int_info.signedness) { |
| ... | @@ -3782,11 +3950,9 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3782,11 +3950,9 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3782 | try writer.print(", {})", .{try f.fmtIntLiteral(shift_val)}); | 3950 | try writer.print(", {})", .{try f.fmtIntLiteral(shift_val)}); |
| 3783 | }, | 3951 | }, |
| 3784 | } | 3952 | } |
| 3785 | | 3953 | if (need_lo) try writer.writeByte(')'); |
| 3786 | if (needs_lo) try writer.writeByte(')'); | 3954 | try a.end(f, writer); |
| 3787 | try writer.writeAll(";\n"); | | |
| 3788 | try v.end(f, inst, writer); | 3955 | try v.end(f, inst, writer); |
| 3789 | | | |
| 3790 | return local; | 3956 | return local; |
| 3791 | } | 3957 | } |
| 3792 | | 3958 | |
| ... | @@ -3797,7 +3963,7 @@ fn airIntFromBool(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3797,7 +3963,7 @@ fn airIntFromBool(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3797 | const writer = f.object.writer(); | 3963 | const writer = f.object.writer(); |
| 3798 | const inst_ty = f.typeOfIndex(inst); | 3964 | const inst_ty = f.typeOfIndex(inst); |
| 3799 | const local = try f.allocLocal(inst, inst_ty); | 3965 | const local = try f.allocLocal(inst, inst_ty); |
| 3800 | const a = try Assignment.start(f, writer, inst_ty); | 3966 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); |
| 3801 | try f.writeCValue(writer, local, .Other); | 3967 | try f.writeCValue(writer, local, .Other); |
| 3802 | try a.assign(f, writer); | 3968 | try a.assign(f, writer); |
| 3803 | try f.writeCValue(writer, operand, .Other); | 3969 | try f.writeCValue(writer, operand, .Other); |
| ... | @@ -3842,9 +4008,8 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -3842,9 +4008,8 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3842 | const src_val = try f.resolveInst(bin_op.rhs); | 4008 | const src_val = try f.resolveInst(bin_op.rhs); |
| 3843 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 4009 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 3844 | | 4010 | |
| | 4011 | const src_scalar_ctype = try f.ctypeFromType(src_ty.scalarType(zcu), .complete); |
| 3845 | const writer = f.object.writer(); | 4012 | const writer = f.object.writer(); |
| 3846 | const v = try Vectorize.start(f, inst, writer, ptr_ty); | | |
| 3847 | | | |
| 3848 | if (need_memcpy) { | 4013 | if (need_memcpy) { |
| 3849 | // For this memcpy to safely work we need the rhs to have the same | 4014 | // For this memcpy to safely work we need the rhs to have the same |
| 3850 | // underlying type as the lhs (i.e. they must both be arrays of the same underlying type). | 4015 | // underlying type as the lhs (i.e. they must both be arrays of the same underlying type). |
| ... | @@ -3863,6 +4028,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -3863,6 +4028,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3863 | break :blk new_local; | 4028 | break :blk new_local; |
| 3864 | } else src_val; | 4029 | } else src_val; |
| 3865 | | 4030 | |
| | 4031 | const v = try Vectorize.start(f, inst, writer, ptr_ty); |
| 3866 | try writer.writeAll("memcpy((char *)"); | 4032 | try writer.writeAll("memcpy((char *)"); |
| 3867 | try f.writeCValue(writer, ptr_val, .FunctionArgument); | 4033 | try f.writeCValue(writer, ptr_val, .FunctionArgument); |
| 3868 | try v.elem(f, writer); | 4034 | try v.elem(f, writer); |
| ... | @@ -3873,9 +4039,9 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -3873,9 +4039,9 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3873 | try writer.writeAll(", sizeof("); | 4039 | try writer.writeAll(", sizeof("); |
| 3874 | try f.renderType(writer, src_ty); | 4040 | try f.renderType(writer, src_ty); |
| 3875 | try writer.writeAll("))"); | 4041 | try writer.writeAll("))"); |
| 3876 | if (src_val == .constant) { | 4042 | try f.freeCValue(inst, array_src); |
| 3877 | try freeLocal(f, inst, array_src.new_local, null); | 4043 | try writer.writeAll(";\n"); |
| 3878 | } | 4044 | try v.end(f, inst, writer); |
| 3879 | } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) { | 4045 | } else if (ptr_info.packed_offset.host_size > 0 and ptr_info.flags.vector_index == .none) { |
| 3880 | const host_bits = ptr_info.packed_offset.host_size * 8; | 4046 | const host_bits = ptr_info.packed_offset.host_size * 8; |
| 3881 | const host_ty = try zcu.intType(.unsigned, host_bits); | 4047 | const host_ty = try zcu.intType(.unsigned, host_bits); |
| ... | @@ -3898,9 +4064,12 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -3898,9 +4064,12 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3898 | | 4064 | |
| 3899 | const mask_val = try zcu.intValue_big(host_ty, mask.toConst()); | 4065 | const mask_val = try zcu.intValue_big(host_ty, mask.toConst()); |
| 3900 | | 4066 | |
| | 4067 | const v = try Vectorize.start(f, inst, writer, ptr_ty); |
| | 4068 | const a = try Assignment.start(f, writer, src_scalar_ctype); |
| 3901 | try f.writeCValueDeref(writer, ptr_val); | 4069 | try f.writeCValueDeref(writer, ptr_val); |
| 3902 | try v.elem(f, writer); | 4070 | try v.elem(f, writer); |
| 3903 | try writer.writeAll(" = zig_or_"); | 4071 | try a.assign(f, writer); |
| | 4072 | try writer.writeAll("zig_or_"); |
| 3904 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); | 4073 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); |
| 3905 | try writer.writeAll("(zig_and_"); | 4074 | try writer.writeAll("(zig_and_"); |
| 3906 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); | 4075 | try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty); |
| ... | @@ -3931,16 +4100,27 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -3931,16 +4100,27 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3931 | try v.elem(f, writer); | 4100 | try v.elem(f, writer); |
| 3932 | if (cant_cast) try writer.writeByte(')'); | 4101 | if (cant_cast) try writer.writeByte(')'); |
| 3933 | try writer.print(", {}))", .{try f.fmtIntLiteral(bit_offset_val)}); | 4102 | try writer.print(", {}))", .{try f.fmtIntLiteral(bit_offset_val)}); |
| | 4103 | try a.end(f, writer); |
| | 4104 | try v.end(f, inst, writer); |
| 3934 | } else { | 4105 | } else { |
| | 4106 | switch (ptr_val) { |
| | 4107 | .local_ref => |ptr_local_index| switch (src_val) { |
| | 4108 | .new_local, .local => |src_local_index| if (ptr_local_index == src_local_index) |
| | 4109 | return .none, |
| | 4110 | else => {}, |
| | 4111 | }, |
| | 4112 | else => {}, |
| | 4113 | } |
| | 4114 | const v = try Vectorize.start(f, inst, writer, ptr_ty); |
| | 4115 | const a = try Assignment.start(f, writer, src_scalar_ctype); |
| 3935 | try f.writeCValueDeref(writer, ptr_val); | 4116 | try f.writeCValueDeref(writer, ptr_val); |
| 3936 | try v.elem(f, writer); | 4117 | try v.elem(f, writer); |
| 3937 | try writer.writeAll(" = "); | 4118 | try a.assign(f, writer); |
| 3938 | try f.writeCValue(writer, src_val, .Other); | 4119 | try f.writeCValue(writer, src_val, .Other); |
| 3939 | try v.elem(f, writer); | 4120 | try v.elem(f, writer); |
| | 4121 | try a.end(f, writer); |
| | 4122 | try v.end(f, inst, writer); |
| 3940 | } | 4123 | } |
| 3941 | try writer.writeAll(";\n"); | | |
| 3942 | try v.end(f, inst, writer); | | |
| 3943 | | | |
| 3944 | return .none; | 4124 | return .none; |
| 3945 | } | 4125 | } |
| 3946 | | 4126 | |
| ... | @@ -4103,6 +4283,7 @@ fn airEquality( | ... | @@ -4103,6 +4283,7 @@ fn airEquality( |
| 4103 | operator: std.math.CompareOperator, | 4283 | operator: std.math.CompareOperator, |
| 4104 | ) !CValue { | 4284 | ) !CValue { |
| 4105 | const zcu = f.object.dg.zcu; | 4285 | const zcu = f.object.dg.zcu; |
| | 4286 | const ctype_pool = &f.object.dg.ctype_pool; |
| 4106 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 4287 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 4107 | | 4288 | |
| 4108 | const operand_ty = f.typeOf(bin_op.lhs); | 4289 | const operand_ty = f.typeOf(bin_op.lhs); |
| ... | @@ -4124,28 +4305,47 @@ fn airEquality( | ... | @@ -4124,28 +4305,47 @@ fn airEquality( |
| 4124 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 4305 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 4125 | | 4306 | |
| 4126 | const writer = f.object.writer(); | 4307 | const writer = f.object.writer(); |
| 4127 | const inst_ty = f.typeOfIndex(inst); | 4308 | const local = try f.allocLocal(inst, Type.bool); |
| 4128 | const local = try f.allocLocal(inst, inst_ty); | 4309 | const a = try Assignment.start(f, writer, CType.bool); |
| 4129 | const a = try Assignment.start(f, writer, inst_ty); | | |
| 4130 | try f.writeCValue(writer, local, .Other); | 4310 | try f.writeCValue(writer, local, .Other); |
| 4131 | try a.assign(f, writer); | 4311 | try a.assign(f, writer); |
| 4132 | | 4312 | |
| 4133 | if (operand_ty.zigTypeTag(zcu) == .Optional and !operand_ty.optionalReprIsPayload(zcu)) { | 4313 | const operand_ctype = try f.ctypeFromType(operand_ty, .complete); |
| 4134 | try f.writeCValueMember(writer, lhs, .{ .identifier = "is_null" }); | 4314 | switch (operand_ctype.info(ctype_pool)) { |
| 4135 | try writer.writeAll(" || "); | 4315 | .basic, .pointer => { |
| 4136 | try f.writeCValueMember(writer, rhs, .{ .identifier = "is_null" }); | 4316 | try f.writeCValue(writer, lhs, .Other); |
| 4137 | try writer.writeAll(" ? "); | 4317 | try writer.writeAll(compareOperatorC(operator)); |
| 4138 | try f.writeCValueMember(writer, lhs, .{ .identifier = "is_null" }); | 4318 | try f.writeCValue(writer, rhs, .Other); |
| 4139 | try writer.writeAll(compareOperatorC(operator)); | 4319 | }, |
| 4140 | try f.writeCValueMember(writer, rhs, .{ .identifier = "is_null" }); | 4320 | .aligned, .array, .vector, .fwd_decl, .function => unreachable, |
| 4141 | try writer.writeAll(" : "); | 4321 | .aggregate => |aggregate| if (aggregate.fields.len == 2 and |
| 4142 | try f.writeCValueMember(writer, lhs, .{ .identifier = "payload" }); | 4322 | (aggregate.fields.at(0, ctype_pool).name.index == .is_null or |
| 4143 | try writer.writeAll(compareOperatorC(operator)); | 4323 | aggregate.fields.at(1, ctype_pool).name.index == .is_null)) |
| 4144 | try f.writeCValueMember(writer, rhs, .{ .identifier = "payload" }); | 4324 | { |
| 4145 | } else { | 4325 | try f.writeCValueMember(writer, lhs, .{ .identifier = "is_null" }); |
| 4146 | try f.writeCValue(writer, lhs, .Other); | 4326 | try writer.writeAll(" || "); |
| 4147 | try writer.writeAll(compareOperatorC(operator)); | 4327 | try f.writeCValueMember(writer, rhs, .{ .identifier = "is_null" }); |
| 4148 | try f.writeCValue(writer, rhs, .Other); | 4328 | try writer.writeAll(" ? "); |
| | 4329 | try f.writeCValueMember(writer, lhs, .{ .identifier = "is_null" }); |
| | 4330 | try writer.writeAll(compareOperatorC(operator)); |
| | 4331 | try f.writeCValueMember(writer, rhs, .{ .identifier = "is_null" }); |
| | 4332 | try writer.writeAll(" : "); |
| | 4333 | try f.writeCValueMember(writer, lhs, .{ .identifier = "payload" }); |
| | 4334 | try writer.writeAll(compareOperatorC(operator)); |
| | 4335 | try f.writeCValueMember(writer, rhs, .{ .identifier = "payload" }); |
| | 4336 | } else for (0..aggregate.fields.len) |field_index| { |
| | 4337 | if (field_index > 0) try writer.writeAll(switch (operator) { |
| | 4338 | .lt, .lte, .gte, .gt => unreachable, |
| | 4339 | .eq => " && ", |
| | 4340 | .neq => " || ", |
| | 4341 | }); |
| | 4342 | const field_name: CValue = .{ |
| | 4343 | .ctype_pool_string = aggregate.fields.at(field_index, ctype_pool).name, |
| | 4344 | }; |
| | 4345 | try f.writeCValueMember(writer, lhs, field_name); |
| | 4346 | try writer.writeAll(compareOperatorC(operator)); |
| | 4347 | try f.writeCValueMember(writer, rhs, field_name); |
| | 4348 | }, |
| 4149 | } | 4349 | } |
| 4150 | try a.end(f, writer); | 4350 | try a.end(f, writer); |
| 4151 | | 4351 | |
| ... | @@ -4155,12 +4355,11 @@ fn airEquality( | ... | @@ -4155,12 +4355,11 @@ fn airEquality( |
| 4155 | fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue { | 4355 | fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4156 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; | 4356 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 4157 | | 4357 | |
| 4158 | const inst_ty = f.typeOfIndex(inst); | | |
| 4159 | const operand = try f.resolveInst(un_op); | 4358 | const operand = try f.resolveInst(un_op); |
| 4160 | try reap(f, inst, &.{un_op}); | 4359 | try reap(f, inst, &.{un_op}); |
| 4161 | | 4360 | |
| 4162 | const writer = f.object.writer(); | 4361 | const writer = f.object.writer(); |
| 4163 | const local = try f.allocLocal(inst, inst_ty); | 4362 | const local = try f.allocLocal(inst, Type.bool); |
| 4164 | try f.writeCValue(writer, local, .Other); | 4363 | try f.writeCValue(writer, local, .Other); |
| 4165 | try writer.writeAll(" = "); | 4364 | try writer.writeAll(" = "); |
| 4166 | try f.writeCValue(writer, operand, .Other); | 4365 | try f.writeCValue(writer, operand, .Other); |
| ... | @@ -4180,39 +4379,34 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { | ... | @@ -4180,39 +4379,34 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { |
| 4180 | const inst_ty = f.typeOfIndex(inst); | 4379 | const inst_ty = f.typeOfIndex(inst); |
| 4181 | const inst_scalar_ty = inst_ty.scalarType(zcu); | 4380 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 4182 | const elem_ty = inst_scalar_ty.elemType2(zcu); | 4381 | const elem_ty = inst_scalar_ty.elemType2(zcu); |
| | 4382 | if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) return f.moveCValue(inst, inst_ty, lhs); |
| | 4383 | const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); |
| 4183 | | 4384 | |
| 4184 | const local = try f.allocLocal(inst, inst_ty); | 4385 | const local = try f.allocLocal(inst, inst_ty); |
| 4185 | const writer = f.object.writer(); | 4386 | const writer = f.object.writer(); |
| 4186 | const v = try Vectorize.start(f, inst, writer, inst_ty); | 4387 | const v = try Vectorize.start(f, inst, writer, inst_ty); |
| | 4388 | const a = try Assignment.start(f, writer, inst_scalar_ctype); |
| 4187 | try f.writeCValue(writer, local, .Other); | 4389 | try f.writeCValue(writer, local, .Other); |
| 4188 | try v.elem(f, writer); | 4390 | try v.elem(f, writer); |
| 4189 | try writer.writeAll(" = "); | 4391 | try a.assign(f, writer); |
| 4190 | | 4392 | // We must convert to and from integer types to prevent UB if the operation |
| 4191 | if (elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 4393 | // results in a NULL pointer, or if LHS is NULL. The operation is only UB |
| 4192 | // We must convert to and from integer types to prevent UB if the operation | 4394 | // if the result is NULL and then dereferenced. |
| 4193 | // results in a NULL pointer, or if LHS is NULL. The operation is only UB | 4395 | try writer.writeByte('('); |
| 4194 | // if the result is NULL and then dereferenced. | 4396 | try f.renderCType(writer, inst_scalar_ctype); |
| 4195 | try writer.writeByte('('); | 4397 | try writer.writeAll(")(((uintptr_t)"); |
| 4196 | try f.renderType(writer, inst_scalar_ty); | 4398 | try f.writeCValue(writer, lhs, .Other); |
| 4197 | try writer.writeAll(")(((uintptr_t)"); | 4399 | try v.elem(f, writer); |
| 4198 | try f.writeCValue(writer, lhs, .Other); | 4400 | try writer.writeAll(") "); |
| 4199 | try v.elem(f, writer); | 4401 | try writer.writeByte(operator); |
| 4200 | try writer.writeAll(") "); | 4402 | try writer.writeAll(" ("); |
| 4201 | try writer.writeByte(operator); | 4403 | try f.writeCValue(writer, rhs, .Other); |
| 4202 | try writer.writeAll(" ("); | 4404 | try v.elem(f, writer); |
| 4203 | try f.writeCValue(writer, rhs, .Other); | 4405 | try writer.writeAll("*sizeof("); |
| 4204 | try v.elem(f, writer); | 4406 | try f.renderType(writer, elem_ty); |
| 4205 | try writer.writeAll("*sizeof("); | 4407 | try writer.writeAll(")))"); |
| 4206 | try f.renderType(writer, elem_ty); | 4408 | try a.end(f, writer); |
| 4207 | try writer.writeAll(")))"); | | |
| 4208 | } else { | | |
| 4209 | try f.writeCValue(writer, lhs, .Other); | | |
| 4210 | try v.elem(f, writer); | | |
| 4211 | } | | |
| 4212 | | | |
| 4213 | try writer.writeAll(";\n"); | | |
| 4214 | try v.end(f, inst, writer); | 4409 | try v.end(f, inst, writer); |
| 4215 | | | |
| 4216 | return local; | 4410 | return local; |
| 4217 | } | 4411 | } |
| 4218 | | 4412 | |
| ... | @@ -4273,14 +4467,14 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4273,14 +4467,14 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4273 | const writer = f.object.writer(); | 4467 | const writer = f.object.writer(); |
| 4274 | const local = try f.allocLocal(inst, inst_ty); | 4468 | const local = try f.allocLocal(inst, inst_ty); |
| 4275 | { | 4469 | { |
| 4276 | const a = try Assignment.start(f, writer, ptr_ty); | 4470 | const a = try Assignment.start(f, writer, try f.ctypeFromType(ptr_ty, .complete)); |
| 4277 | try f.writeCValueMember(writer, local, .{ .identifier = "ptr" }); | 4471 | try f.writeCValueMember(writer, local, .{ .identifier = "ptr" }); |
| 4278 | try a.assign(f, writer); | 4472 | try a.assign(f, writer); |
| 4279 | try f.writeCValue(writer, ptr, .Other); | 4473 | try f.writeCValue(writer, ptr, .Other); |
| 4280 | try a.end(f, writer); | 4474 | try a.end(f, writer); |
| 4281 | } | 4475 | } |
| 4282 | { | 4476 | { |
| 4283 | const a = try Assignment.start(f, writer, Type.usize); | 4477 | const a = try Assignment.start(f, writer, CType.usize); |
| 4284 | try f.writeCValueMember(writer, local, .{ .identifier = "len" }); | 4478 | try f.writeCValueMember(writer, local, .{ .identifier = "len" }); |
| 4285 | try a.assign(f, writer); | 4479 | try a.assign(f, writer); |
| 4286 | try f.writeCValue(writer, len, .Initializer); | 4480 | try f.writeCValue(writer, len, .Initializer); |
| ... | @@ -4347,7 +4541,7 @@ fn airCall( | ... | @@ -4347,7 +4541,7 @@ fn airCall( |
| 4347 | }).?; | 4541 | }).?; |
| 4348 | const ret_ty = Type.fromInterned(fn_info.return_type); | 4542 | const ret_ty = Type.fromInterned(fn_info.return_type); |
| 4349 | const ret_ctype: CType = if (ret_ty.isNoReturn(zcu)) | 4543 | const ret_ctype: CType = if (ret_ty.isNoReturn(zcu)) |
| 4350 | .{ .index = .void } | 4544 | CType.void |
| 4351 | else | 4545 | else |
| 4352 | try f.ctypeFromType(ret_ty, .parameter); | 4546 | try f.ctypeFromType(ret_ty, .parameter); |
| 4353 | | 4547 | |
| ... | @@ -4359,7 +4553,7 @@ fn airCall( | ... | @@ -4359,7 +4553,7 @@ fn airCall( |
| 4359 | break :result .none; | 4553 | break :result .none; |
| 4360 | } else if (f.liveness.isUnused(inst)) { | 4554 | } else if (f.liveness.isUnused(inst)) { |
| 4361 | try writer.writeByte('('); | 4555 | try writer.writeByte('('); |
| 4362 | try f.renderCType(writer, .{ .index = .void }); | 4556 | try f.renderCType(writer, CType.void); |
| 4363 | try writer.writeByte(')'); | 4557 | try writer.writeByte(')'); |
| 4364 | break :result .none; | 4558 | break :result .none; |
| 4365 | } else { | 4559 | } else { |
| ... | @@ -4414,10 +4608,7 @@ fn airCall( | ... | @@ -4414,10 +4608,7 @@ fn airCall( |
| 4414 | if (need_comma) try writer.writeAll(", "); | 4608 | if (need_comma) try writer.writeAll(", "); |
| 4415 | need_comma = true; | 4609 | need_comma = true; |
| 4416 | try f.writeCValue(writer, resolved_arg, .FunctionArgument); | 4610 | try f.writeCValue(writer, resolved_arg, .FunctionArgument); |
| 4417 | switch (resolved_arg) { | 4611 | try f.freeCValue(inst, resolved_arg); |
| 4418 | .new_local => |local| try freeLocal(f, inst, local, null), | | |
| 4419 | else => {}, | | |
| 4420 | } | | |
| 4421 | } | 4612 | } |
| 4422 | try writer.writeAll(");\n"); | 4613 | try writer.writeAll(");\n"); |
| 4423 | | 4614 | |
| ... | @@ -4601,7 +4792,7 @@ fn lowerTry( | ... | @@ -4601,7 +4792,7 @@ fn lowerTry( |
| 4601 | } | 4792 | } |
| 4602 | | 4793 | |
| 4603 | const local = try f.allocLocal(inst, inst_ty); | 4794 | const local = try f.allocLocal(inst, inst_ty); |
| 4604 | const a = try Assignment.start(f, writer, inst_ty); | 4795 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); |
| 4605 | try f.writeCValue(writer, local, .Other); | 4796 | try f.writeCValue(writer, local, .Other); |
| 4606 | try a.assign(f, writer); | 4797 | try a.assign(f, writer); |
| 4607 | if (is_ptr) { | 4798 | if (is_ptr) { |
| ... | @@ -4624,7 +4815,7 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4624,7 +4815,7 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4624 | const operand = try f.resolveInst(branch.operand); | 4815 | const operand = try f.resolveInst(branch.operand); |
| 4625 | try reap(f, inst, &.{branch.operand}); | 4816 | try reap(f, inst, &.{branch.operand}); |
| 4626 | | 4817 | |
| 4627 | const a = try Assignment.start(f, writer, operand_ty); | 4818 | const a = try Assignment.start(f, writer, try f.ctypeFromType(operand_ty, .complete)); |
| 4628 | try f.writeCValue(writer, result, .Other); | 4819 | try f.writeCValue(writer, result, .Other); |
| 4629 | try a.assign(f, writer); | 4820 | try a.assign(f, writer); |
| 4630 | try f.writeCValue(writer, operand, .Other); | 4821 | try f.writeCValue(writer, operand, .Other); |
| ... | @@ -4637,53 +4828,17 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4637,53 +4828,17 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4637 | | 4828 | |
| 4638 | fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { | 4829 | fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4639 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 4830 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 4640 | const dest_ty = f.typeOfIndex(inst); | 4831 | const inst_ty = f.typeOfIndex(inst); |
| 4641 | | 4832 | |
| 4642 | const operand = try f.resolveInst(ty_op.operand); | 4833 | const operand = try f.resolveInst(ty_op.operand); |
| 4643 | const operand_ty = f.typeOf(ty_op.operand); | 4834 | const operand_ty = f.typeOf(ty_op.operand); |
| 4644 | | 4835 | |
| 4645 | const bitcasted = try bitcast(f, dest_ty, operand, operand_ty); | 4836 | const bitcasted = try bitcast(f, inst_ty, operand, operand_ty); |
| 4646 | try reap(f, inst, &.{ty_op.operand}); | 4837 | try reap(f, inst, &.{ty_op.operand}); |
| 4647 | return bitcasted.move(f, inst, dest_ty); | 4838 | return f.moveCValue(inst, inst_ty, bitcasted); |
| 4648 | } | 4839 | } |
| 4649 | | 4840 | |
| 4650 | const LocalResult = struct { | 4841 | fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !CValue { |
| 4651 | c_value: CValue, | | |
| 4652 | need_free: bool, | | |
| 4653 | | | |
| 4654 | fn move(lr: LocalResult, f: *Function, inst: Air.Inst.Index, dest_ty: Type) !CValue { | | |
| 4655 | const zcu = f.object.dg.zcu; | | |
| 4656 | | | |
| 4657 | if (lr.need_free) { | | |
| 4658 | // Move the freshly allocated local to be owned by this instruction, | | |
| 4659 | // by returning it here instead of freeing it. | | |
| 4660 | return lr.c_value; | | |
| 4661 | } | | |
| 4662 | | | |
| 4663 | const local = try f.allocLocal(inst, dest_ty); | | |
| 4664 | try lr.free(f); | | |
| 4665 | const writer = f.object.writer(); | | |
| 4666 | try f.writeCValue(writer, local, .Other); | | |
| 4667 | if (dest_ty.isAbiInt(zcu)) { | | |
| 4668 | try writer.writeAll(" = "); | | |
| 4669 | } else { | | |
| 4670 | try writer.writeAll(" = ("); | | |
| 4671 | try f.renderType(writer, dest_ty); | | |
| 4672 | try writer.writeByte(')'); | | |
| 4673 | } | | |
| 4674 | try f.writeCValue(writer, lr.c_value, .Initializer); | | |
| 4675 | try writer.writeAll(";\n"); | | |
| 4676 | return local; | | |
| 4677 | } | | |
| 4678 | | | |
| 4679 | fn free(lr: LocalResult, f: *Function) !void { | | |
| 4680 | if (lr.need_free) { | | |
| 4681 | try freeLocal(f, null, lr.c_value.new_local, null); | | |
| 4682 | } | | |
| 4683 | } | | |
| 4684 | }; | | |
| 4685 | | | |
| 4686 | fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !LocalResult { | | |
| 4687 | const zcu = f.object.dg.zcu; | 4842 | const zcu = f.object.dg.zcu; |
| 4688 | const target = &f.object.dg.mod.resolved_target.result; | 4843 | const target = &f.object.dg.mod.resolved_target.result; |
| 4689 | const ctype_pool = &f.object.dg.ctype_pool; | 4844 | const ctype_pool = &f.object.dg.ctype_pool; |
| ... | @@ -4693,13 +4848,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca | ... | @@ -4693,13 +4848,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca |
| 4693 | const src_info = dest_ty.intInfo(zcu); | 4848 | const src_info = dest_ty.intInfo(zcu); |
| 4694 | const dest_info = operand_ty.intInfo(zcu); | 4849 | const dest_info = operand_ty.intInfo(zcu); |
| 4695 | if (src_info.signedness == dest_info.signedness and | 4850 | if (src_info.signedness == dest_info.signedness and |
| 4696 | src_info.bits == dest_info.bits) | 4851 | src_info.bits == dest_info.bits) return operand; |
| 4697 | { | | |
| 4698 | return .{ | | |
| 4699 | .c_value = operand, | | |
| 4700 | .need_free = false, | | |
| 4701 | }; | | |
| 4702 | } | | |
| 4703 | } | 4852 | } |
| 4704 | | 4853 | |
| 4705 | if (dest_ty.isPtrAtRuntime(zcu) and operand_ty.isPtrAtRuntime(zcu)) { | 4854 | if (dest_ty.isPtrAtRuntime(zcu) and operand_ty.isPtrAtRuntime(zcu)) { |
| ... | @@ -4710,10 +4859,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca | ... | @@ -4710,10 +4859,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca |
| 4710 | try writer.writeByte(')'); | 4859 | try writer.writeByte(')'); |
| 4711 | try f.writeCValue(writer, operand, .Other); | 4860 | try f.writeCValue(writer, operand, .Other); |
| 4712 | try writer.writeAll(";\n"); | 4861 | try writer.writeAll(";\n"); |
| 4713 | return .{ | 4862 | return local; |
| 4714 | .c_value = local, | | |
| 4715 | .need_free = true, | | |
| 4716 | }; | | |
| 4717 | } | 4863 | } |
| 4718 | | 4864 | |
| 4719 | const operand_lval = if (operand == .constant) blk: { | 4865 | const operand_lval = if (operand == .constant) blk: { |
| ... | @@ -4800,14 +4946,8 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca | ... | @@ -4800,14 +4946,8 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca |
| 4800 | try writer.writeAll(");\n"); | 4946 | try writer.writeAll(");\n"); |
| 4801 | } | 4947 | } |
| 4802 | | 4948 | |
| 4803 | if (operand == .constant) { | 4949 | try f.freeCValue(null, operand_lval); |
| 4804 | try freeLocal(f, null, operand_lval.new_local, null); | 4950 | return local; |
| 4805 | } | | |
| 4806 | | | |
| 4807 | return .{ | | |
| 4808 | .c_value = local, | | |
| 4809 | .need_free = true, | | |
| 4810 | }; | | |
| 4811 | } | 4951 | } |
| 4812 | | 4952 | |
| 4813 | fn airTrap(f: *Function, writer: anytype) !CValue { | 4953 | fn airTrap(f: *Function, writer: anytype) !CValue { |
| ... | @@ -4918,13 +5058,16 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4918,13 +5058,16 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4918 | const writer = f.object.writer(); | 5058 | const writer = f.object.writer(); |
| 4919 | | 5059 | |
| 4920 | try writer.writeAll("switch ("); | 5060 | try writer.writeAll("switch ("); |
| 4921 | if (condition_ty.zigTypeTag(zcu) == .Bool) { | 5061 | |
| 4922 | try writer.writeByte('('); | 5062 | const lowered_condition_ty = if (condition_ty.toIntern() == .bool_type) |
| 4923 | try f.renderType(writer, Type.u1); | 5063 | Type.u1 |
| 4924 | try writer.writeByte(')'); | 5064 | else if (condition_ty.isPtrAtRuntime(zcu)) |
| 4925 | } else if (condition_ty.isPtrAtRuntime(zcu)) { | 5065 | Type.usize |
| | 5066 | else |
| | 5067 | condition_ty; |
| | 5068 | if (condition_ty.toIntern() != lowered_condition_ty.toIntern()) { |
| 4926 | try writer.writeByte('('); | 5069 | try writer.writeByte('('); |
| 4927 | try f.renderType(writer, Type.usize); | 5070 | try f.renderType(writer, lowered_condition_ty); |
| 4928 | try writer.writeByte(')'); | 5071 | try writer.writeByte(')'); |
| 4929 | } | 5072 | } |
| 4930 | try f.writeCValue(writer, condition, .Other); | 5073 | try f.writeCValue(writer, condition, .Other); |
| ... | @@ -4943,18 +5086,24 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4943,18 +5086,24 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4943 | for (0..switch_br.data.cases_len) |case_i| { | 5086 | for (0..switch_br.data.cases_len) |case_i| { |
| 4944 | const case = f.air.extraData(Air.SwitchBr.Case, extra_index); | 5087 | const case = f.air.extraData(Air.SwitchBr.Case, extra_index); |
| 4945 | const items = @as([]const Air.Inst.Ref, @ptrCast(f.air.extra[case.end..][0..case.data.items_len])); | 5088 | const items = @as([]const Air.Inst.Ref, @ptrCast(f.air.extra[case.end..][0..case.data.items_len])); |
| 4946 | const case_body: []const Air.Inst.Index = @ptrCast(f.air.extra[case.end + items.len ..][0..case.data.body_len]); | 5089 | const case_body: []const Air.Inst.Index = |
| | 5090 | @ptrCast(f.air.extra[case.end + items.len ..][0..case.data.body_len]); |
| 4947 | extra_index = case.end + case.data.items_len + case_body.len; | 5091 | extra_index = case.end + case.data.items_len + case_body.len; |
| 4948 | | 5092 | |
| 4949 | for (items) |item| { | 5093 | for (items) |item| { |
| 4950 | try f.object.indent_writer.insertNewline(); | 5094 | try f.object.indent_writer.insertNewline(); |
| 4951 | try writer.writeAll("case "); | 5095 | try writer.writeAll("case "); |
| 4952 | if (condition_ty.isPtrAtRuntime(zcu)) { | 5096 | const item_value = try f.air.value(item, zcu); |
| 4953 | try writer.writeByte('('); | 5097 | if (item_value.?.getUnsignedInt(zcu)) |item_int| try writer.print("{}\n", .{ |
| 4954 | try f.renderType(writer, Type.usize); | 5098 | try f.fmtIntLiteral(try zcu.intValue(lowered_condition_ty, item_int)), |
| 4955 | try writer.writeByte(')'); | 5099 | }) else { |
| | 5100 | if (condition_ty.isPtrAtRuntime(zcu)) { |
| | 5101 | try writer.writeByte('('); |
| | 5102 | try f.renderType(writer, Type.usize); |
| | 5103 | try writer.writeByte(')'); |
| | 5104 | } |
| | 5105 | try f.object.dg.renderValue(writer, (try f.air.value(item, zcu)).?, .Other); |
| 4956 | } | 5106 | } |
| 4957 | try f.object.dg.renderValue(writer, (try f.air.value(item, zcu)).?, .Other); | | |
| 4958 | try writer.writeByte(':'); | 5107 | try writer.writeByte(':'); |
| 4959 | } | 5108 | } |
| 4960 | try writer.writeByte(' '); | 5109 | try writer.writeByte(' '); |
| ... | @@ -5276,10 +5425,11 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5276,10 +5425,11 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5276 | fn airIsNull( | 5425 | fn airIsNull( |
| 5277 | f: *Function, | 5426 | f: *Function, |
| 5278 | inst: Air.Inst.Index, | 5427 | inst: Air.Inst.Index, |
| 5279 | operator: []const u8, | 5428 | operator: std.math.CompareOperator, |
| 5280 | is_ptr: bool, | 5429 | is_ptr: bool, |
| 5281 | ) !CValue { | 5430 | ) !CValue { |
| 5282 | const zcu = f.object.dg.zcu; | 5431 | const zcu = f.object.dg.zcu; |
| | 5432 | const ctype_pool = &f.object.dg.ctype_pool; |
| 5283 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; | 5433 | const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 5284 | | 5434 | |
| 5285 | const writer = f.object.writer(); | 5435 | const writer = f.object.writer(); |
| ... | @@ -5287,106 +5437,84 @@ fn airIsNull( | ... | @@ -5287,106 +5437,84 @@ fn airIsNull( |
| 5287 | try reap(f, inst, &.{un_op}); | 5437 | try reap(f, inst, &.{un_op}); |
| 5288 | | 5438 | |
| 5289 | const local = try f.allocLocal(inst, Type.bool); | 5439 | const local = try f.allocLocal(inst, Type.bool); |
| | 5440 | const a = try Assignment.start(f, writer, CType.bool); |
| 5290 | try f.writeCValue(writer, local, .Other); | 5441 | try f.writeCValue(writer, local, .Other); |
| 5291 | try writer.writeAll(" = "); | 5442 | try a.assign(f, writer); |
| 5292 | if (is_ptr) { | | |
| 5293 | try f.writeCValueDeref(writer, operand); | | |
| 5294 | } else { | | |
| 5295 | try f.writeCValue(writer, operand, .Other); | | |
| 5296 | } | | |
| 5297 | | 5443 | |
| 5298 | const operand_ty = f.typeOf(un_op); | 5444 | const operand_ty = f.typeOf(un_op); |
| 5299 | const optional_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty; | 5445 | const optional_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty; |
| 5300 | const payload_ty = optional_ty.optionalChild(zcu); | 5446 | const opt_ctype = try f.ctypeFromType(optional_ty, .complete); |
| 5301 | const err_int_ty = try zcu.errorIntType(); | 5447 | const rhs = switch (opt_ctype.info(ctype_pool)) { |
| 5302 | | 5448 | .basic, .pointer => rhs: { |
| 5303 | const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) | 5449 | if (is_ptr) |
| 5304 | Value.true | 5450 | try f.writeCValueDeref(writer, operand) |
| 5305 | else if (optional_ty.isPtrLikeOptional(zcu)) | 5451 | else |
| 5306 | // operand is a regular pointer, test `operand !=/== NULL` | 5452 | try f.writeCValue(writer, operand, .Other); |
| 5307 | try zcu.getCoerced(Value.null, optional_ty) | 5453 | break :rhs if (opt_ctype.isBool()) |
| 5308 | else if (payload_ty.zigTypeTag(zcu) == .ErrorSet) | 5454 | "true" |
| 5309 | try zcu.intValue(err_int_ty, 0) | 5455 | else if (opt_ctype.isInteger()) |
| 5310 | else if (payload_ty.isSlice(zcu) and optional_ty.optionalReprIsPayload(zcu)) rhs: { | 5456 | "0" |
| 5311 | try writer.writeAll(".ptr"); | 5457 | else |
| 5312 | const slice_ptr_ty = payload_ty.slicePtrFieldType(zcu); | 5458 | "NULL"; |
| 5313 | const opt_slice_ptr_ty = try zcu.optionalType(slice_ptr_ty.toIntern()); | 5459 | }, |
| 5314 | break :rhs try zcu.nullValue(opt_slice_ptr_ty); | 5460 | .aligned, .array, .vector, .fwd_decl, .function => unreachable, |
| 5315 | } else rhs: { | 5461 | .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) { |
| 5316 | try writer.writeAll(".is_null"); | 5462 | .is_null, .payload => rhs: { |
| 5317 | break :rhs Value.true; | 5463 | if (is_ptr) |
| | 5464 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "is_null" }) |
| | 5465 | else |
| | 5466 | try f.writeCValueMember(writer, operand, .{ .identifier = "is_null" }); |
| | 5467 | break :rhs "true"; |
| | 5468 | }, |
| | 5469 | .ptr, .len => rhs: { |
| | 5470 | if (is_ptr) |
| | 5471 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "ptr" }) |
| | 5472 | else |
| | 5473 | try f.writeCValueMember(writer, operand, .{ .identifier = "ptr" }); |
| | 5474 | break :rhs "NULL"; |
| | 5475 | }, |
| | 5476 | else => unreachable, |
| | 5477 | }, |
| 5318 | }; | 5478 | }; |
| 5319 | try writer.writeByte(' '); | 5479 | try writer.writeAll(compareOperatorC(operator)); |
| 5320 | try writer.writeAll(operator); | 5480 | try writer.writeAll(rhs); |
| 5321 | try writer.writeByte(' '); | | |
| 5322 | try f.object.dg.renderValue(writer, rhs, .Other); | | |
| 5323 | try writer.writeAll(";\n"); | | |
| 5324 | return local; | | |
| 5325 | } | | |
| 5326 | | | |
| 5327 | fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { | | |
| 5328 | const zcu = f.object.dg.zcu; | | |
| 5329 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | | |
| 5330 | | | |
| 5331 | const operand = try f.resolveInst(ty_op.operand); | | |
| 5332 | try reap(f, inst, &.{ty_op.operand}); | | |
| 5333 | const opt_ty = f.typeOf(ty_op.operand); | | |
| 5334 | | | |
| 5335 | const payload_ty = opt_ty.optionalChild(zcu); | | |
| 5336 | | | |
| 5337 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | | |
| 5338 | return .none; | | |
| 5339 | } | | |
| 5340 | | | |
| 5341 | const inst_ty = f.typeOfIndex(inst); | | |
| 5342 | const writer = f.object.writer(); | | |
| 5343 | const local = try f.allocLocal(inst, inst_ty); | | |
| 5344 | | | |
| 5345 | if (opt_ty.optionalReprIsPayload(zcu)) { | | |
| 5346 | try f.writeCValue(writer, local, .Other); | | |
| 5347 | try writer.writeAll(" = "); | | |
| 5348 | try f.writeCValue(writer, operand, .Other); | | |
| 5349 | try writer.writeAll(";\n"); | | |
| 5350 | return local; | | |
| 5351 | } | | |
| 5352 | | | |
| 5353 | const a = try Assignment.start(f, writer, inst_ty); | | |
| 5354 | try f.writeCValue(writer, local, .Other); | | |
| 5355 | try a.assign(f, writer); | | |
| 5356 | try f.writeCValueMember(writer, operand, .{ .identifier = "payload" }); | | |
| 5357 | try a.end(f, writer); | 5481 | try a.end(f, writer); |
| 5358 | return local; | 5482 | return local; |
| 5359 | } | 5483 | } |
| 5360 | | 5484 | |
| 5361 | fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue { | 5485 | fn airOptionalPayload(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { |
| 5362 | const zcu = f.object.dg.zcu; | 5486 | const zcu = f.object.dg.zcu; |
| | 5487 | const ctype_pool = &f.object.dg.ctype_pool; |
| 5363 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 5488 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5364 | | 5489 | |
| 5365 | const writer = f.object.writer(); | | |
| 5366 | const operand = try f.resolveInst(ty_op.operand); | | |
| 5367 | try reap(f, inst, &.{ty_op.operand}); | | |
| 5368 | const ptr_ty = f.typeOf(ty_op.operand); | | |
| 5369 | const opt_ty = ptr_ty.childType(zcu); | | |
| 5370 | const inst_ty = f.typeOfIndex(inst); | 5490 | const inst_ty = f.typeOfIndex(inst); |
| | 5491 | const operand_ty = f.typeOf(ty_op.operand); |
| | 5492 | const opt_ty = if (is_ptr) operand_ty.childType(zcu) else operand_ty; |
| | 5493 | const opt_ctype = try f.ctypeFromType(opt_ty, .complete); |
| | 5494 | if (opt_ctype.isBool()) return if (is_ptr) .{ .undef = inst_ty } else .none; |
| 5371 | | 5495 | |
| 5372 | if (!inst_ty.childType(zcu).hasRuntimeBitsIgnoreComptime(zcu)) { | 5496 | const operand = try f.resolveInst(ty_op.operand); |
| 5373 | return .{ .undef = inst_ty }; | 5497 | switch (opt_ctype.info(ctype_pool)) { |
| 5374 | } | 5498 | .basic, .pointer => return f.moveCValue(inst, inst_ty, operand), |
| 5375 | | 5499 | .aligned, .array, .vector, .fwd_decl, .function => unreachable, |
| 5376 | const local = try f.allocLocal(inst, inst_ty); | 5500 | .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) { |
| 5377 | try f.writeCValue(writer, local, .Other); | 5501 | .is_null, .payload => { |
| 5378 | | 5502 | const writer = f.object.writer(); |
| 5379 | if (opt_ty.optionalReprIsPayload(zcu)) { | 5503 | const local = try f.allocLocal(inst, inst_ty); |
| 5380 | // the operand is just a regular pointer, no need to do anything special. | 5504 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); |
| 5381 | // *?*T -> **T and ?*T -> *T are **T -> **T and *T -> *T in C | 5505 | try f.writeCValue(writer, local, .Other); |
| 5382 | try writer.writeAll(" = "); | 5506 | try a.assign(f, writer); |
| 5383 | try f.writeCValue(writer, operand, .Other); | 5507 | if (is_ptr) { |
| 5384 | } else { | 5508 | try writer.writeByte('&'); |
| 5385 | try writer.writeAll(" = &"); | 5509 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" }); |
| 5386 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" }); | 5510 | } else try f.writeCValueMember(writer, operand, .{ .identifier = "payload" }); |
| | 5511 | try a.end(f, writer); |
| | 5512 | return local; |
| | 5513 | }, |
| | 5514 | .ptr, .len => return f.moveCValue(inst, inst_ty, operand), |
| | 5515 | else => unreachable, |
| | 5516 | }, |
| 5387 | } | 5517 | } |
| 5388 | try writer.writeAll(";\n"); | | |
| 5389 | return local; | | |
| 5390 | } | 5518 | } |
| 5391 | | 5519 | |
| 5392 | fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { | 5520 | fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| ... | @@ -5397,38 +5525,46 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5397,38 +5525,46 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5397 | try reap(f, inst, &.{ty_op.operand}); | 5525 | try reap(f, inst, &.{ty_op.operand}); |
| 5398 | const operand_ty = f.typeOf(ty_op.operand); | 5526 | const operand_ty = f.typeOf(ty_op.operand); |
| 5399 | | 5527 | |
| 5400 | const opt_ty = operand_ty.childType(zcu); | | |
| 5401 | | | |
| 5402 | const inst_ty = f.typeOfIndex(inst); | 5528 | const inst_ty = f.typeOfIndex(inst); |
| 5403 | | 5529 | const opt_ctype = try f.ctypeFromType(operand_ty.childType(zcu), .complete); |
| 5404 | if (opt_ty.optionalReprIsPayload(zcu)) { | 5530 | switch (opt_ctype.info(&f.object.dg.ctype_pool)) { |
| 5405 | if (f.liveness.isUnused(inst)) { | 5531 | .basic => { |
| 5406 | return .none; | 5532 | const a = try Assignment.start(f, writer, opt_ctype); |
| 5407 | } | 5533 | try f.writeCValueDeref(writer, operand); |
| 5408 | const local = try f.allocLocal(inst, inst_ty); | 5534 | try a.assign(f, writer); |
| 5409 | // The payload and the optional are the same value. | 5535 | try f.object.dg.renderValue(writer, Value.false, .Initializer); |
| 5410 | // Setting to non-null will be done when the payload is set. | 5536 | try a.end(f, writer); |
| 5411 | try f.writeCValue(writer, local, .Other); | | |
| 5412 | try writer.writeAll(" = "); | | |
| 5413 | try f.writeCValue(writer, operand, .Other); | | |
| 5414 | try writer.writeAll(";\n"); | | |
| 5415 | return local; | | |
| 5416 | } else { | | |
| 5417 | try f.writeCValueDeref(writer, operand); | | |
| 5418 | try writer.writeAll(".is_null = "); | | |
| 5419 | try f.object.dg.renderValue(writer, Value.false, .Initializer); | | |
| 5420 | try writer.writeAll(";\n"); | | |
| 5421 | | | |
| 5422 | if (f.liveness.isUnused(inst)) { | | |
| 5423 | return .none; | 5537 | return .none; |
| 5424 | } | 5538 | }, |
| 5425 | | 5539 | .pointer => { |
| 5426 | const local = try f.allocLocal(inst, inst_ty); | 5540 | if (f.liveness.isUnused(inst)) return .none; |
| 5427 | try f.writeCValue(writer, local, .Other); | 5541 | const local = try f.allocLocal(inst, inst_ty); |
| 5428 | try writer.writeAll(" = &"); | 5542 | const a = try Assignment.start(f, writer, opt_ctype); |
| 5429 | try f.writeCValueDeref(writer, operand); | 5543 | try f.writeCValue(writer, local, .Other); |
| 5430 | try writer.writeAll(".payload;\n"); | 5544 | try a.assign(f, writer); |
| 5431 | return local; | 5545 | try f.writeCValue(writer, operand, .Other); |
| | 5546 | try a.end(f, writer); |
| | 5547 | return local; |
| | 5548 | }, |
| | 5549 | .aligned, .array, .vector, .fwd_decl, .function => unreachable, |
| | 5550 | .aggregate => { |
| | 5551 | { |
| | 5552 | const a = try Assignment.start(f, writer, opt_ctype); |
| | 5553 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "is_null" }); |
| | 5554 | try a.assign(f, writer); |
| | 5555 | try f.object.dg.renderValue(writer, Value.false, .Initializer); |
| | 5556 | try a.end(f, writer); |
| | 5557 | } |
| | 5558 | if (f.liveness.isUnused(inst)) return .none; |
| | 5559 | const local = try f.allocLocal(inst, inst_ty); |
| | 5560 | const a = try Assignment.start(f, writer, opt_ctype); |
| | 5561 | try f.writeCValue(writer, local, .Other); |
| | 5562 | try a.assign(f, writer); |
| | 5563 | try writer.writeByte('&'); |
| | 5564 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" }); |
| | 5565 | try a.end(f, writer); |
| | 5566 | return local; |
| | 5567 | }, |
| 5432 | } | 5568 | } |
| 5433 | } | 5569 | } |
| 5434 | | 5570 | |
| ... | @@ -5688,13 +5824,15 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5688,13 +5824,15 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5688 | if (inst_ty.eql(field_int_ty, f.object.dg.zcu)) return temp_local; | 5824 | if (inst_ty.eql(field_int_ty, f.object.dg.zcu)) return temp_local; |
| 5689 | | 5825 | |
| 5690 | const local = try f.allocLocal(inst, inst_ty); | 5826 | const local = try f.allocLocal(inst, inst_ty); |
| 5691 | try writer.writeAll("memcpy("); | 5827 | if (local.new_local != temp_local.new_local) { |
| 5692 | try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument); | 5828 | try writer.writeAll("memcpy("); |
| 5693 | try writer.writeAll(", "); | 5829 | try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument); |
| 5694 | try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument); | 5830 | try writer.writeAll(", "); |
| 5695 | try writer.writeAll(", sizeof("); | 5831 | try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument); |
| 5696 | try f.renderType(writer, inst_ty); | 5832 | try writer.writeAll(", sizeof("); |
| 5697 | try writer.writeAll("));\n"); | 5833 | try f.renderType(writer, inst_ty); |
| | 5834 | try writer.writeAll("));\n"); |
| | 5835 | } |
| 5698 | try freeLocal(f, inst, temp_local.new_local, null); | 5836 | try freeLocal(f, inst, temp_local.new_local, null); |
| 5699 | return local; | 5837 | return local; |
| 5700 | }, | 5838 | }, |
| ... | @@ -5723,20 +5861,23 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5723,20 +5861,23 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5723 | try writer.writeAll(";\n"); | 5861 | try writer.writeAll(";\n"); |
| 5724 | break :blk operand_local; | 5862 | break :blk operand_local; |
| 5725 | } else struct_byval; | 5863 | } else struct_byval; |
| 5726 | | | |
| 5727 | const local = try f.allocLocal(inst, inst_ty); | 5864 | const local = try f.allocLocal(inst, inst_ty); |
| 5728 | try writer.writeAll("memcpy(&"); | 5865 | if (switch (local) { |
| 5729 | try f.writeCValue(writer, local, .Other); | 5866 | .new_local, .local => |local_index| switch (operand_lval) { |
| 5730 | try writer.writeAll(", &"); | 5867 | .new_local, .local => |operand_local_index| local_index != operand_local_index, |
| 5731 | try f.writeCValue(writer, operand_lval, .Other); | 5868 | else => true, |
| 5732 | try writer.writeAll(", sizeof("); | 5869 | }, |
| 5733 | try f.renderType(writer, inst_ty); | 5870 | else => true, |
| 5734 | try writer.writeAll("));\n"); | 5871 | }) { |
| 5735 | | 5872 | try writer.writeAll("memcpy(&"); |
| 5736 | if (struct_byval == .constant) { | 5873 | try f.writeCValue(writer, local, .Other); |
| 5737 | try freeLocal(f, inst, operand_lval.new_local, null); | 5874 | try writer.writeAll(", &"); |
| | 5875 | try f.writeCValue(writer, operand_lval, .Other); |
| | 5876 | try writer.writeAll(", sizeof("); |
| | 5877 | try f.renderType(writer, inst_ty); |
| | 5878 | try writer.writeAll("));\n"); |
| 5738 | } | 5879 | } |
| 5739 | | 5880 | try f.freeCValue(inst, operand_lval); |
| 5740 | return local; | 5881 | return local; |
| 5741 | }, | 5882 | }, |
| 5742 | } | 5883 | } |
| ... | @@ -5745,7 +5886,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5745,7 +5886,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5745 | }; | 5886 | }; |
| 5746 | | 5887 | |
| 5747 | const local = try f.allocLocal(inst, inst_ty); | 5888 | const local = try f.allocLocal(inst, inst_ty); |
| 5748 | const a = try Assignment.start(f, writer, inst_ty); | 5889 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); |
| 5749 | try f.writeCValue(writer, local, .Other); | 5890 | try f.writeCValue(writer, local, .Other); |
| 5750 | try a.assign(f, writer); | 5891 | try a.assign(f, writer); |
| 5751 | try f.writeCValueMember(writer, struct_byval, field_name); | 5892 | try f.writeCValueMember(writer, struct_byval, field_name); |
| ... | @@ -5818,7 +5959,7 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu | ... | @@ -5818,7 +5959,7 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu |
| 5818 | } | 5959 | } |
| 5819 | | 5960 | |
| 5820 | const local = try f.allocLocal(inst, inst_ty); | 5961 | const local = try f.allocLocal(inst, inst_ty); |
| 5821 | const a = try Assignment.start(f, writer, inst_ty); | 5962 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); |
| 5822 | try f.writeCValue(writer, local, .Other); | 5963 | try f.writeCValue(writer, local, .Other); |
| 5823 | try a.assign(f, writer); | 5964 | try a.assign(f, writer); |
| 5824 | if (is_ptr) { | 5965 | if (is_ptr) { |
| ... | @@ -5830,35 +5971,42 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu | ... | @@ -5830,35 +5971,42 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu |
| 5830 | } | 5971 | } |
| 5831 | | 5972 | |
| 5832 | fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { | 5973 | fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5833 | const zcu = f.object.dg.zcu; | 5974 | const ctype_pool = &f.object.dg.ctype_pool; |
| 5834 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 5975 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5835 | | 5976 | |
| 5836 | const inst_ty = f.typeOfIndex(inst); | 5977 | const inst_ty = f.typeOfIndex(inst); |
| 5837 | const repr_is_payload = inst_ty.optionalReprIsPayload(zcu); | 5978 | const inst_ctype = try f.ctypeFromType(inst_ty, .complete); |
| 5838 | const payload_ty = f.typeOf(ty_op.operand); | 5979 | if (inst_ctype.isBool()) return .{ .constant = Value.true }; |
| 5839 | const payload = try f.resolveInst(ty_op.operand); | | |
| 5840 | try reap(f, inst, &.{ty_op.operand}); | | |
| 5841 | | 5980 | |
| 5842 | const writer = f.object.writer(); | 5981 | const operand = try f.resolveInst(ty_op.operand); |
| 5843 | const local = try f.allocLocal(inst, inst_ty); | 5982 | switch (inst_ctype.info(ctype_pool)) { |
| 5844 | { | 5983 | .basic, .pointer => return f.moveCValue(inst, inst_ty, operand), |
| 5845 | const a = try Assignment.start(f, writer, payload_ty); | 5984 | .aligned, .array, .vector, .fwd_decl, .function => unreachable, |
| 5846 | if (repr_is_payload) | 5985 | .aggregate => |aggregate| switch (aggregate.fields.at(0, ctype_pool).name.index) { |
| 5847 | try f.writeCValue(writer, local, .Other) | 5986 | .is_null, .payload => { |
| 5848 | else | 5987 | const operand_ctype = try f.ctypeFromType(f.typeOf(ty_op.operand), .complete); |
| 5849 | try f.writeCValueMember(writer, local, .{ .identifier = "payload" }); | 5988 | const writer = f.object.writer(); |
| 5850 | try a.assign(f, writer); | 5989 | const local = try f.allocLocal(inst, inst_ty); |
| 5851 | try f.writeCValue(writer, payload, .Other); | 5990 | { |
| 5852 | try a.end(f, writer); | 5991 | const a = try Assignment.start(f, writer, CType.bool); |
| 5853 | } | 5992 | try f.writeCValueMember(writer, local, .{ .identifier = "is_null" }); |
| 5854 | if (!repr_is_payload) { | 5993 | try a.assign(f, writer); |
| 5855 | const a = try Assignment.start(f, writer, Type.bool); | 5994 | try writer.writeAll("false"); |
| 5856 | try f.writeCValueMember(writer, local, .{ .identifier = "is_null" }); | 5995 | try a.end(f, writer); |
| 5857 | try a.assign(f, writer); | 5996 | } |
| 5858 | try f.object.dg.renderValue(writer, Value.false, .Other); | 5997 | { |
| 5859 | try a.end(f, writer); | 5998 | const a = try Assignment.start(f, writer, operand_ctype); |
| | 5999 | try f.writeCValueMember(writer, local, .{ .identifier = "payload" }); |
| | 6000 | try a.assign(f, writer); |
| | 6001 | try f.writeCValue(writer, operand, .Initializer); |
| | 6002 | try a.end(f, writer); |
| | 6003 | } |
| | 6004 | return local; |
| | 6005 | }, |
| | 6006 | .ptr, .len => return f.moveCValue(inst, inst_ty, operand), |
| | 6007 | else => unreachable, |
| | 6008 | }, |
| 5860 | } | 6009 | } |
| 5861 | return local; | | |
| 5862 | } | 6010 | } |
| 5863 | | 6011 | |
| 5864 | fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { | 6012 | fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| ... | @@ -5881,14 +6029,14 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5881,14 +6029,14 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5881 | } | 6029 | } |
| 5882 | | 6030 | |
| 5883 | if (!repr_is_err) { | 6031 | if (!repr_is_err) { |
| 5884 | const a = try Assignment.start(f, writer, payload_ty); | 6032 | const a = try Assignment.start(f, writer, try f.ctypeFromType(payload_ty, .complete)); |
| 5885 | try f.writeCValueMember(writer, local, .{ .identifier = "payload" }); | 6033 | try f.writeCValueMember(writer, local, .{ .identifier = "payload" }); |
| 5886 | try a.assign(f, writer); | 6034 | try a.assign(f, writer); |
| 5887 | try f.object.dg.renderUndefValue(writer, payload_ty, .Other); | 6035 | try f.object.dg.renderUndefValue(writer, payload_ty, .Other); |
| 5888 | try a.end(f, writer); | 6036 | try a.end(f, writer); |
| 5889 | } | 6037 | } |
| 5890 | { | 6038 | { |
| 5891 | const a = try Assignment.start(f, writer, err_ty); | 6039 | const a = try Assignment.start(f, writer, try f.ctypeFromType(err_ty, .complete)); |
| 5892 | if (repr_is_err) | 6040 | if (repr_is_err) |
| 5893 | try f.writeCValue(writer, local, .Other) | 6041 | try f.writeCValue(writer, local, .Other) |
| 5894 | else | 6042 | else |
| ... | @@ -5904,31 +6052,43 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5904,31 +6052,43 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5904 | const zcu = f.object.dg.zcu; | 6052 | const zcu = f.object.dg.zcu; |
| 5905 | const writer = f.object.writer(); | 6053 | const writer = f.object.writer(); |
| 5906 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 6054 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| | 6055 | const inst_ty = f.typeOfIndex(inst); |
| 5907 | const operand = try f.resolveInst(ty_op.operand); | 6056 | const operand = try f.resolveInst(ty_op.operand); |
| 5908 | const error_union_ty = f.typeOf(ty_op.operand).childType(zcu); | 6057 | const operand_ty = f.typeOf(ty_op.operand); |
| | 6058 | const error_union_ty = operand_ty.childType(zcu); |
| 5909 | | 6059 | |
| 5910 | const payload_ty = error_union_ty.errorUnionPayload(zcu); | 6060 | const payload_ty = error_union_ty.errorUnionPayload(zcu); |
| 5911 | const err_int_ty = try zcu.errorIntType(); | 6061 | const err_int_ty = try zcu.errorIntType(); |
| 5912 | const no_err = try zcu.intValue(err_int_ty, 0); | 6062 | const no_err = try zcu.intValue(err_int_ty, 0); |
| | 6063 | try reap(f, inst, &.{ty_op.operand}); |
| 5913 | | 6064 | |
| 5914 | // First, set the non-error value. | 6065 | // First, set the non-error value. |
| 5915 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 6066 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| | 6067 | const a = try Assignment.start(f, writer, try f.ctypeFromType(operand_ty, .complete)); |
| 5916 | try f.writeCValueDeref(writer, operand); | 6068 | try f.writeCValueDeref(writer, operand); |
| 5917 | try writer.print(" = {};\n", .{try f.fmtIntLiteral(no_err)}); | 6069 | try a.assign(f, writer); |
| 5918 | return operand; | 6070 | try writer.print("{}", .{try f.fmtIntLiteral(no_err)}); |
| | 6071 | try a.end(f, writer); |
| | 6072 | return .none; |
| | 6073 | } |
| | 6074 | { |
| | 6075 | const a = try Assignment.start(f, writer, try f.ctypeFromType(err_int_ty, .complete)); |
| | 6076 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" }); |
| | 6077 | try a.assign(f, writer); |
| | 6078 | try writer.print("{}", .{try f.fmtIntLiteral(no_err)}); |
| | 6079 | try a.end(f, writer); |
| 5919 | } | 6080 | } |
| 5920 | try reap(f, inst, &.{ty_op.operand}); | | |
| 5921 | try f.writeCValueDeref(writer, operand); | | |
| 5922 | try writer.print(".error = {};\n", .{try f.fmtIntLiteral(no_err)}); | | |
| 5923 | | 6081 | |
| 5924 | // Then return the payload pointer (only if it is used) | 6082 | // Then return the payload pointer (only if it is used) |
| 5925 | if (f.liveness.isUnused(inst)) return .none; | 6083 | if (f.liveness.isUnused(inst)) return .none; |
| 5926 | | 6084 | |
| 5927 | const local = try f.allocLocal(inst, f.typeOfIndex(inst)); | 6085 | const local = try f.allocLocal(inst, inst_ty); |
| | 6086 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); |
| 5928 | try f.writeCValue(writer, local, .Other); | 6087 | try f.writeCValue(writer, local, .Other); |
| 5929 | try writer.writeAll(" = &("); | 6088 | try a.assign(f, writer); |
| 5930 | try f.writeCValueDeref(writer, operand); | 6089 | try writer.writeByte('&'); |
| 5931 | try writer.writeAll(").payload;\n"); | 6090 | try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" }); |
| | 6091 | try a.end(f, writer); |
| 5932 | return local; | 6092 | return local; |
| 5933 | } | 6093 | } |
| 5934 | | 6094 | |
| ... | @@ -5961,14 +6121,14 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5961,14 +6121,14 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5961 | const writer = f.object.writer(); | 6121 | const writer = f.object.writer(); |
| 5962 | const local = try f.allocLocal(inst, inst_ty); | 6122 | const local = try f.allocLocal(inst, inst_ty); |
| 5963 | if (!repr_is_err) { | 6123 | if (!repr_is_err) { |
| 5964 | const a = try Assignment.start(f, writer, payload_ty); | 6124 | const a = try Assignment.start(f, writer, try f.ctypeFromType(payload_ty, .complete)); |
| 5965 | try f.writeCValueMember(writer, local, .{ .identifier = "payload" }); | 6125 | try f.writeCValueMember(writer, local, .{ .identifier = "payload" }); |
| 5966 | try a.assign(f, writer); | 6126 | try a.assign(f, writer); |
| 5967 | try f.writeCValue(writer, payload, .Other); | 6127 | try f.writeCValue(writer, payload, .Other); |
| 5968 | try a.end(f, writer); | 6128 | try a.end(f, writer); |
| 5969 | } | 6129 | } |
| 5970 | { | 6130 | { |
| 5971 | const a = try Assignment.start(f, writer, err_ty); | 6131 | const a = try Assignment.start(f, writer, try f.ctypeFromType(err_ty, .complete)); |
| 5972 | if (repr_is_err) | 6132 | if (repr_is_err) |
| 5973 | try f.writeCValue(writer, local, .Other) | 6133 | try f.writeCValue(writer, local, .Other) |
| 5974 | else | 6134 | else |
| ... | @@ -5993,7 +6153,7 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const | ... | @@ -5993,7 +6153,7 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const |
| 5993 | const payload_ty = err_union_ty.errorUnionPayload(zcu); | 6153 | const payload_ty = err_union_ty.errorUnionPayload(zcu); |
| 5994 | const error_ty = err_union_ty.errorUnionSet(zcu); | 6154 | const error_ty = err_union_ty.errorUnionSet(zcu); |
| 5995 | | 6155 | |
| 5996 | const a = try Assignment.start(f, writer, Type.bool); | 6156 | const a = try Assignment.start(f, writer, CType.bool); |
| 5997 | try f.writeCValue(writer, local, .Other); | 6157 | try f.writeCValue(writer, local, .Other); |
| 5998 | try a.assign(f, writer); | 6158 | try a.assign(f, writer); |
| 5999 | const err_int_ty = try zcu.errorIntType(); | 6159 | const err_int_ty = try zcu.errorIntType(); |
| ... | @@ -6030,7 +6190,7 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6030,7 +6190,7 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6030 | const array_ty = operand_ty.childType(zcu); | 6190 | const array_ty = operand_ty.childType(zcu); |
| 6031 | | 6191 | |
| 6032 | { | 6192 | { |
| 6033 | const a = try Assignment.start(f, writer, ptr_ty); | 6193 | const a = try Assignment.start(f, writer, try f.ctypeFromType(ptr_ty, .complete)); |
| 6034 | try f.writeCValueMember(writer, local, .{ .identifier = "ptr" }); | 6194 | try f.writeCValueMember(writer, local, .{ .identifier = "ptr" }); |
| 6035 | try a.assign(f, writer); | 6195 | try a.assign(f, writer); |
| 6036 | if (operand == .undef) { | 6196 | if (operand == .undef) { |
| ... | @@ -6056,7 +6216,7 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6056,7 +6216,7 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6056 | try a.end(f, writer); | 6216 | try a.end(f, writer); |
| 6057 | } | 6217 | } |
| 6058 | { | 6218 | { |
| 6059 | const a = try Assignment.start(f, writer, Type.usize); | 6219 | const a = try Assignment.start(f, writer, CType.usize); |
| 6060 | try f.writeCValueMember(writer, local, .{ .identifier = "len" }); | 6220 | try f.writeCValueMember(writer, local, .{ .identifier = "len" }); |
| 6061 | try a.assign(f, writer); | 6221 | try a.assign(f, writer); |
| 6062 | try writer.print("{}", .{ | 6222 | try writer.print("{}", .{ |
| ... | @@ -6091,7 +6251,7 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6091,7 +6251,7 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6091 | const writer = f.object.writer(); | 6251 | const writer = f.object.writer(); |
| 6092 | const local = try f.allocLocal(inst, inst_ty); | 6252 | const local = try f.allocLocal(inst, inst_ty); |
| 6093 | const v = try Vectorize.start(f, inst, writer, operand_ty); | 6253 | const v = try Vectorize.start(f, inst, writer, operand_ty); |
| 6094 | const a = try Assignment.start(f, writer, scalar_ty); | 6254 | const a = try Assignment.start(f, writer, try f.ctypeFromType(scalar_ty, .complete)); |
| 6095 | try f.writeCValue(writer, local, .Other); | 6255 | try f.writeCValue(writer, local, .Other); |
| 6096 | try v.elem(f, writer); | 6256 | try v.elem(f, writer); |
| 6097 | try a.assign(f, writer); | 6257 | try a.assign(f, writer); |
| ... | @@ -6133,11 +6293,10 @@ fn airIntFromPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6133,11 +6293,10 @@ fn airIntFromPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6133 | try writer.writeAll(" = ("); | 6293 | try writer.writeAll(" = ("); |
| 6134 | try f.renderType(writer, inst_ty); | 6294 | try f.renderType(writer, inst_ty); |
| 6135 | try writer.writeByte(')'); | 6295 | try writer.writeByte(')'); |
| 6136 | if (operand_ty.isSlice(zcu)) { | 6296 | if (operand_ty.isSlice(zcu)) |
| 6137 | try f.writeCValueMember(writer, operand, .{ .identifier = "ptr" }); | 6297 | try f.writeCValueMember(writer, operand, .{ .identifier = "ptr" }) |
| 6138 | } else { | 6298 | else |
| 6139 | try f.writeCValue(writer, operand, .Other); | 6299 | try f.writeCValue(writer, operand, .Other); |
| 6140 | } | | |
| 6141 | try writer.writeAll(";\n"); | 6300 | try writer.writeAll(";\n"); |
| 6142 | return local; | 6301 | return local; |
| 6143 | } | 6302 | } |
| ... | @@ -6306,9 +6465,10 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue | ... | @@ -6306,9 +6465,10 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 6306 | const new_value = try f.resolveInst(extra.new_value); | 6465 | const new_value = try f.resolveInst(extra.new_value); |
| 6307 | const ptr_ty = f.typeOf(extra.ptr); | 6466 | const ptr_ty = f.typeOf(extra.ptr); |
| 6308 | const ty = ptr_ty.childType(zcu); | 6467 | const ty = ptr_ty.childType(zcu); |
| | 6468 | const ctype = try f.ctypeFromType(ty, .complete); |
| 6309 | | 6469 | |
| 6310 | const writer = f.object.writer(); | 6470 | const writer = f.object.writer(); |
| 6311 | const new_value_mat = try Materialize.start(f, inst, writer, ty, new_value); | 6471 | const new_value_mat = try Materialize.start(f, inst, ty, new_value); |
| 6312 | try reap(f, inst, &.{ extra.ptr, extra.expected_value, extra.new_value }); | 6472 | try reap(f, inst, &.{ extra.ptr, extra.expected_value, extra.new_value }); |
| 6313 | | 6473 | |
| 6314 | const repr_ty = if (ty.isRuntimeFloat()) | 6474 | const repr_ty = if (ty.isRuntimeFloat()) |
| ... | @@ -6319,7 +6479,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue | ... | @@ -6319,7 +6479,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 6319 | const local = try f.allocLocal(inst, inst_ty); | 6479 | const local = try f.allocLocal(inst, inst_ty); |
| 6320 | if (inst_ty.isPtrLikeOptional(zcu)) { | 6480 | if (inst_ty.isPtrLikeOptional(zcu)) { |
| 6321 | { | 6481 | { |
| 6322 | const a = try Assignment.start(f, writer, ty); | 6482 | const a = try Assignment.start(f, writer, ctype); |
| 6323 | try f.writeCValue(writer, local, .Other); | 6483 | try f.writeCValue(writer, local, .Other); |
| 6324 | try a.assign(f, writer); | 6484 | try a.assign(f, writer); |
| 6325 | try f.writeCValue(writer, expected_value, .Other); | 6485 | try f.writeCValue(writer, expected_value, .Other); |
| ... | @@ -6349,7 +6509,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue | ... | @@ -6349,7 +6509,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 6349 | try writer.writeAll(") {\n"); | 6509 | try writer.writeAll(") {\n"); |
| 6350 | f.object.indent_writer.pushIndent(); | 6510 | f.object.indent_writer.pushIndent(); |
| 6351 | { | 6511 | { |
| 6352 | const a = try Assignment.start(f, writer, ty); | 6512 | const a = try Assignment.start(f, writer, ctype); |
| 6353 | try f.writeCValue(writer, local, .Other); | 6513 | try f.writeCValue(writer, local, .Other); |
| 6354 | try a.assign(f, writer); | 6514 | try a.assign(f, writer); |
| 6355 | try writer.writeAll("NULL"); | 6515 | try writer.writeAll("NULL"); |
| ... | @@ -6359,14 +6519,14 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue | ... | @@ -6359,14 +6519,14 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 6359 | try writer.writeAll("}\n"); | 6519 | try writer.writeAll("}\n"); |
| 6360 | } else { | 6520 | } else { |
| 6361 | { | 6521 | { |
| 6362 | const a = try Assignment.start(f, writer, ty); | 6522 | const a = try Assignment.start(f, writer, ctype); |
| 6363 | try f.writeCValueMember(writer, local, .{ .identifier = "payload" }); | 6523 | try f.writeCValueMember(writer, local, .{ .identifier = "payload" }); |
| 6364 | try a.assign(f, writer); | 6524 | try a.assign(f, writer); |
| 6365 | try f.writeCValue(writer, expected_value, .Other); | 6525 | try f.writeCValue(writer, expected_value, .Other); |
| 6366 | try a.end(f, writer); | 6526 | try a.end(f, writer); |
| 6367 | } | 6527 | } |
| 6368 | { | 6528 | { |
| 6369 | const a = try Assignment.start(f, writer, Type.bool); | 6529 | const a = try Assignment.start(f, writer, CType.bool); |
| 6370 | try f.writeCValueMember(writer, local, .{ .identifier = "is_null" }); | 6530 | try f.writeCValueMember(writer, local, .{ .identifier = "is_null" }); |
| 6371 | try a.assign(f, writer); | 6531 | try a.assign(f, writer); |
| 6372 | try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor}); | 6532 | try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor}); |
| ... | @@ -6412,7 +6572,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6412,7 +6572,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6412 | const operand = try f.resolveInst(extra.operand); | 6572 | const operand = try f.resolveInst(extra.operand); |
| 6413 | | 6573 | |
| 6414 | const writer = f.object.writer(); | 6574 | const writer = f.object.writer(); |
| 6415 | const operand_mat = try Materialize.start(f, inst, writer, ty, operand); | 6575 | const operand_mat = try Materialize.start(f, inst, ty, operand); |
| 6416 | try reap(f, inst, &.{ pl_op.operand, extra.operand }); | 6576 | try reap(f, inst, &.{ pl_op.operand, extra.operand }); |
| 6417 | | 6577 | |
| 6418 | const repr_bits = @as(u16, @intCast(ty.abiSize(zcu) * 8)); | 6578 | const repr_bits = @as(u16, @intCast(ty.abiSize(zcu) * 8)); |
| ... | @@ -6501,7 +6661,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa | ... | @@ -6501,7 +6661,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa |
| 6501 | const element = try f.resolveInst(bin_op.rhs); | 6661 | const element = try f.resolveInst(bin_op.rhs); |
| 6502 | | 6662 | |
| 6503 | const writer = f.object.writer(); | 6663 | const writer = f.object.writer(); |
| 6504 | const element_mat = try Materialize.start(f, inst, writer, ty, element); | 6664 | const element_mat = try Materialize.start(f, inst, ty, element); |
| 6505 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 6665 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 6506 | | 6666 | |
| 6507 | const repr_ty = if (ty.isRuntimeFloat()) | 6667 | const repr_ty = if (ty.isRuntimeFloat()) |
| ... | @@ -6612,7 +6772,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -6612,7 +6772,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 6612 | try f.writeCValue(writer, index, .Other); | 6772 | try f.writeCValue(writer, index, .Other); |
| 6613 | try writer.writeAll(") "); | 6773 | try writer.writeAll(") "); |
| 6614 | | 6774 | |
| 6615 | const a = try Assignment.start(f, writer, elem_ty); | 6775 | const a = try Assignment.start(f, writer, try f.ctypeFromType(elem_ty, .complete)); |
| 6616 | try writer.writeAll("(("); | 6776 | try writer.writeAll("(("); |
| 6617 | try f.renderType(writer, elem_ptr_ty); | 6777 | try f.renderType(writer, elem_ptr_ty); |
| 6618 | try writer.writeByte(')'); | 6778 | try writer.writeByte(')'); |
| ... | @@ -6637,7 +6797,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -6637,7 +6797,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 6637 | .Slice => { | 6797 | .Slice => { |
| 6638 | try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" }); | 6798 | try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" }); |
| 6639 | try writer.writeAll(", "); | 6799 | try writer.writeAll(", "); |
| 6640 | try f.writeCValue(writer, bitcasted.c_value, .FunctionArgument); | 6800 | try f.writeCValue(writer, bitcasted, .FunctionArgument); |
| 6641 | try writer.writeAll(", "); | 6801 | try writer.writeAll(", "); |
| 6642 | try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" }); | 6802 | try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" }); |
| 6643 | try writer.writeAll(");\n"); | 6803 | try writer.writeAll(");\n"); |
| ... | @@ -6648,12 +6808,12 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -6648,12 +6808,12 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 6648 | | 6808 | |
| 6649 | try f.writeCValue(writer, dest_slice, .FunctionArgument); | 6809 | try f.writeCValue(writer, dest_slice, .FunctionArgument); |
| 6650 | try writer.writeAll(", "); | 6810 | try writer.writeAll(", "); |
| 6651 | try f.writeCValue(writer, bitcasted.c_value, .FunctionArgument); | 6811 | try f.writeCValue(writer, bitcasted, .FunctionArgument); |
| 6652 | try writer.print(", {d});\n", .{len}); | 6812 | try writer.print(", {d});\n", .{len}); |
| 6653 | }, | 6813 | }, |
| 6654 | .Many, .C => unreachable, | 6814 | .Many, .C => unreachable, |
| 6655 | } | 6815 | } |
| 6656 | try bitcasted.free(f); | 6816 | try f.freeCValue(inst, bitcasted); |
| 6657 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 6817 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 6658 | return .none; | 6818 | return .none; |
| 6659 | } | 6819 | } |
| ... | @@ -6700,7 +6860,7 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6700,7 +6860,7 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6700 | const tag_ty = union_ty.unionTagTypeSafety(zcu).?; | 6860 | const tag_ty = union_ty.unionTagTypeSafety(zcu).?; |
| 6701 | | 6861 | |
| 6702 | const writer = f.object.writer(); | 6862 | const writer = f.object.writer(); |
| 6703 | const a = try Assignment.start(f, writer, tag_ty); | 6863 | const a = try Assignment.start(f, writer, try f.ctypeFromType(tag_ty, .complete)); |
| 6704 | try f.writeCValueDerefMember(writer, union_ptr, .{ .identifier = "tag" }); | 6864 | try f.writeCValueDerefMember(writer, union_ptr, .{ .identifier = "tag" }); |
| 6705 | try a.assign(f, writer); | 6865 | try a.assign(f, writer); |
| 6706 | try f.writeCValue(writer, new_tag, .Other); | 6866 | try f.writeCValue(writer, new_tag, .Other); |
| ... | @@ -6722,7 +6882,7 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6722,7 +6882,7 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6722 | const inst_ty = f.typeOfIndex(inst); | 6882 | const inst_ty = f.typeOfIndex(inst); |
| 6723 | const writer = f.object.writer(); | 6883 | const writer = f.object.writer(); |
| 6724 | const local = try f.allocLocal(inst, inst_ty); | 6884 | const local = try f.allocLocal(inst, inst_ty); |
| 6725 | const a = try Assignment.start(f, writer, inst_ty); | 6885 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_ty, .complete)); |
| 6726 | try f.writeCValue(writer, local, .Other); | 6886 | try f.writeCValue(writer, local, .Other); |
| 6727 | try a.assign(f, writer); | 6887 | try a.assign(f, writer); |
| 6728 | try f.writeCValueMember(writer, operand, .{ .identifier = "tag" }); | 6888 | try f.writeCValueMember(writer, operand, .{ .identifier = "tag" }); |
| ... | @@ -6780,7 +6940,7 @@ fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6780,7 +6940,7 @@ fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6780 | const writer = f.object.writer(); | 6940 | const writer = f.object.writer(); |
| 6781 | const local = try f.allocLocal(inst, inst_ty); | 6941 | const local = try f.allocLocal(inst, inst_ty); |
| 6782 | const v = try Vectorize.start(f, inst, writer, inst_ty); | 6942 | const v = try Vectorize.start(f, inst, writer, inst_ty); |
| 6783 | const a = try Assignment.init(f, inst_scalar_ty); | 6943 | const a = try Assignment.start(f, writer, try f.ctypeFromType(inst_scalar_ty, .complete)); |
| 6784 | try f.writeCValue(writer, local, .Other); | 6944 | try f.writeCValue(writer, local, .Other); |
| 6785 | try v.elem(f, writer); | 6945 | try v.elem(f, writer); |
| 6786 | try a.assign(f, writer); | 6946 | try a.assign(f, writer); |
| ... | @@ -7033,7 +7193,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7033,7 +7193,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7033 | const local = try f.allocLocal(inst, inst_ty); | 7193 | const local = try f.allocLocal(inst, inst_ty); |
| 7034 | switch (ip.indexToKey(inst_ty.toIntern())) { | 7194 | switch (ip.indexToKey(inst_ty.toIntern())) { |
| 7035 | inline .array_type, .vector_type => |info, tag| { | 7195 | inline .array_type, .vector_type => |info, tag| { |
| 7036 | const a = try Assignment.init(f, Type.fromInterned(info.child)); | 7196 | const a: Assignment = .{ |
| | 7197 | .ctype = try f.ctypeFromType(Type.fromInterned(info.child), .complete), |
| | 7198 | }; |
| 7037 | for (resolved_elements, 0..) |element, i| { | 7199 | for (resolved_elements, 0..) |element, i| { |
| 7038 | try a.restart(f, writer); | 7200 | try a.restart(f, writer); |
| 7039 | try f.writeCValue(writer, local, .Other); | 7201 | try f.writeCValue(writer, local, .Other); |
| ... | @@ -7060,7 +7222,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7060,7 +7222,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7060 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); | 7222 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 7061 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | 7223 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 7062 | | 7224 | |
| 7063 | const a = try Assignment.start(f, writer, field_ty); | 7225 | const a = try Assignment.start(f, writer, try f.ctypeFromType(field_ty, .complete)); |
| 7064 | try f.writeCValueMember(writer, local, if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name| | 7226 | try f.writeCValueMember(writer, local, if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name| |
| 7065 | .{ .identifier = field_name.toSlice(ip) } | 7227 | .{ .identifier = field_name.toSlice(ip) } |
| 7066 | else | 7228 | else |
| ... | @@ -7140,7 +7302,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7140,7 +7302,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7140 | const field_ty = Type.fromInterned(anon_struct_info.types.get(ip)[field_index]); | 7302 | const field_ty = Type.fromInterned(anon_struct_info.types.get(ip)[field_index]); |
| 7141 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | 7303 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 7142 | | 7304 | |
| 7143 | const a = try Assignment.start(f, writer, field_ty); | 7305 | const a = try Assignment.start(f, writer, try f.ctypeFromType(field_ty, .complete)); |
| 7144 | try f.writeCValueMember(writer, local, if (anon_struct_info.fieldName(ip, field_index).unwrap()) |field_name| | 7306 | try f.writeCValueMember(writer, local, if (anon_struct_info.fieldName(ip, field_index).unwrap()) |field_name| |
| 7145 | .{ .identifier = field_name.toSlice(ip) } | 7307 | .{ .identifier = field_name.toSlice(ip) } |
| 7146 | else | 7308 | else |
| ... | @@ -7170,13 +7332,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7170,13 +7332,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7170 | | 7332 | |
| 7171 | const writer = f.object.writer(); | 7333 | const writer = f.object.writer(); |
| 7172 | const local = try f.allocLocal(inst, union_ty); | 7334 | const local = try f.allocLocal(inst, union_ty); |
| 7173 | if (loaded_union.getLayout(ip) == .@"packed") { | 7335 | if (loaded_union.getLayout(ip) == .@"packed") return f.moveCValue(inst, union_ty, payload); |
| 7174 | try f.writeCValue(writer, local, .Other); | | |
| 7175 | try writer.writeAll(" = "); | | |
| 7176 | try f.writeCValue(writer, payload, .Initializer); | | |
| 7177 | try writer.writeAll(";\n"); | | |
| 7178 | return local; | | |
| 7179 | } | | |
| 7180 | | 7336 | |
| 7181 | const field: CValue = if (union_ty.unionTagTypeSafety(zcu)) |tag_ty| field: { | 7337 | const field: CValue = if (union_ty.unionTagTypeSafety(zcu)) |tag_ty| field: { |
| 7182 | const layout = union_ty.unionGetLayout(zcu); | 7338 | const layout = union_ty.unionGetLayout(zcu); |
| ... | @@ -7184,7 +7340,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7184,7 +7340,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7184 | const field_index = tag_ty.enumFieldIndex(field_name, zcu).?; | 7340 | const field_index = tag_ty.enumFieldIndex(field_name, zcu).?; |
| 7185 | const tag_val = try zcu.enumValueFieldIndex(tag_ty, field_index); | 7341 | const tag_val = try zcu.enumValueFieldIndex(tag_ty, field_index); |
| 7186 | | 7342 | |
| 7187 | const a = try Assignment.start(f, writer, tag_ty); | 7343 | const a = try Assignment.start(f, writer, try f.ctypeFromType(tag_ty, .complete)); |
| 7188 | try f.writeCValueMember(writer, local, .{ .identifier = "tag" }); | 7344 | try f.writeCValueMember(writer, local, .{ .identifier = "tag" }); |
| 7189 | try a.assign(f, writer); | 7345 | try a.assign(f, writer); |
| 7190 | try writer.print("{}", .{try f.fmtIntLiteral(try tag_val.intFromEnum(tag_ty, zcu))}); | 7346 | try writer.print("{}", .{try f.fmtIntLiteral(try tag_val.intFromEnum(tag_ty, zcu))}); |
| ... | @@ -7193,7 +7349,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7193,7 +7349,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7193 | break :field .{ .payload_identifier = field_name.toSlice(ip) }; | 7349 | break :field .{ .payload_identifier = field_name.toSlice(ip) }; |
| 7194 | } else .{ .identifier = field_name.toSlice(ip) }; | 7350 | } else .{ .identifier = field_name.toSlice(ip) }; |
| 7195 | | 7351 | |
| 7196 | const a = try Assignment.start(f, writer, payload_ty); | 7352 | const a = try Assignment.start(f, writer, try f.ctypeFromType(payload_ty, .complete)); |
| 7197 | try f.writeCValueMember(writer, local, field); | 7353 | try f.writeCValueMember(writer, local, field); |
| 7198 | try a.assign(f, writer); | 7354 | try a.assign(f, writer); |
| 7199 | try f.writeCValue(writer, payload, .Other); | 7355 | try f.writeCValue(writer, payload, .Other); |
| ... | @@ -7648,11 +7804,13 @@ fn StringLiteral(comptime WriterType: type) type { | ... | @@ -7648,11 +7804,13 @@ fn StringLiteral(comptime WriterType: type) type { |
| 7648 | // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal, | 7804 | // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal, |
| 7649 | // regardless of the length of the string literal initializing it. Array initializer syntax is | 7805 | // regardless of the length of the string literal initializing it. Array initializer syntax is |
| 7650 | // used instead. | 7806 | // used instead. |
| 7651 | const max_string_initializer_len = 65535; | 7807 | // C99 only requires 4095. |
| | 7808 | const max_string_initializer_len = @min(65535, 4095); |
| 7652 | | 7809 | |
| 7653 | // MSVC has a length limit of 16380 per string literal (before concatenation) | 7810 | // MSVC has a length limit of 16380 per string literal (before concatenation) |
| | 7811 | // C99 only requires 4095. |
| 7654 | const max_char_len = 4; | 7812 | const max_char_len = 4; |
| 7655 | const max_literal_len = 16380 - max_char_len; | 7813 | const max_literal_len = @min(16380 - max_char_len, 4095); |
| 7656 | | 7814 | |
| 7657 | return struct { | 7815 | return struct { |
| 7658 | len: u64, | 7816 | len: u64, |
| ... | @@ -7824,13 +7982,13 @@ fn formatIntLiteral( | ... | @@ -7824,13 +7982,13 @@ fn formatIntLiteral( |
| 7824 | } = switch (data.ctype.info(ctype_pool)) { | 7982 | } = switch (data.ctype.info(ctype_pool)) { |
| 7825 | .basic => |basic_info| switch (basic_info) { | 7983 | .basic => |basic_info| switch (basic_info) { |
| 7826 | else => .{ | 7984 | else => .{ |
| 7827 | .ctype = .{ .index = .void }, | 7985 | .ctype = CType.void, |
| 7828 | .count = 1, | 7986 | .count = 1, |
| 7829 | .endian = .little, | 7987 | .endian = .little, |
| 7830 | .homogeneous = true, | 7988 | .homogeneous = true, |
| 7831 | }, | 7989 | }, |
| 7832 | .zig_u128, .zig_i128 => .{ | 7990 | .zig_u128, .zig_i128 => .{ |
| 7833 | .ctype = .{ .index = .uint64_t }, | 7991 | .ctype = CType.u64, |
| 7834 | .count = 2, | 7992 | .count = 2, |
| 7835 | .endian = .big, | 7993 | .endian = .big, |
| 7836 | .homogeneous = false, | 7994 | .homogeneous = false, |
| ... | @@ -7946,28 +8104,12 @@ fn formatIntLiteral( | ... | @@ -7946,28 +8104,12 @@ fn formatIntLiteral( |
| 7946 | const Materialize = struct { | 8104 | const Materialize = struct { |
| 7947 | local: CValue, | 8105 | local: CValue, |
| 7948 | | 8106 | |
| 7949 | pub fn start( | 8107 | pub fn start(f: *Function, inst: Air.Inst.Index, ty: Type, value: CValue) !Materialize { |
| 7950 | f: *Function, | 8108 | return .{ .local = switch (value) { |
| 7951 | inst: Air.Inst.Index, | 8109 | .local_ref, .constant, .decl_ref, .undef => try f.moveCValue(inst, ty, value), |
| 7952 | writer: anytype, | 8110 | .new_local => |local| .{ .local = local }, |
| 7953 | ty: Type, | 8111 | else => value, |
| 7954 | value: CValue, | 8112 | } }; |
| 7955 | ) !Materialize { | | |
| 7956 | switch (value) { | | |
| 7957 | .local_ref, .constant, .decl_ref, .undef => { | | |
| 7958 | const local = try f.allocLocal(inst, ty); | | |
| 7959 | | | |
| 7960 | const a = try Assignment.start(f, writer, ty); | | |
| 7961 | try f.writeCValue(writer, local, .Other); | | |
| 7962 | try a.assign(f, writer); | | |
| 7963 | try f.writeCValue(writer, value, .Other); | | |
| 7964 | try a.end(f, writer); | | |
| 7965 | | | |
| 7966 | return .{ .local = local }; | | |
| 7967 | }, | | |
| 7968 | .new_local => |local| return .{ .local = .{ .local = local } }, | | |
| 7969 | else => return .{ .local = value }, | | |
| 7970 | } | | |
| 7971 | } | 8113 | } |
| 7972 | | 8114 | |
| 7973 | pub fn mat(self: Materialize, f: *Function, writer: anytype) !void { | 8115 | pub fn mat(self: Materialize, f: *Function, writer: anytype) !void { |
| ... | @@ -7975,22 +8117,15 @@ const Materialize = struct { | ... | @@ -7975,22 +8117,15 @@ const Materialize = struct { |
| 7975 | } | 8117 | } |
| 7976 | | 8118 | |
| 7977 | pub fn end(self: Materialize, f: *Function, inst: Air.Inst.Index) !void { | 8119 | pub fn end(self: Materialize, f: *Function, inst: Air.Inst.Index) !void { |
| 7978 | switch (self.local) { | 8120 | try f.freeCValue(inst, self.local); |
| 7979 | .new_local => |local| try freeLocal(f, inst, local, null), | | |
| 7980 | else => {}, | | |
| 7981 | } | | |
| 7982 | } | 8121 | } |
| 7983 | }; | 8122 | }; |
| 7984 | | 8123 | |
| 7985 | const Assignment = struct { | 8124 | const Assignment = struct { |
| 7986 | ctype: CType, | 8125 | ctype: CType, |
| 7987 | | 8126 | |
| 7988 | pub fn init(f: *Function, ty: Type) !Assignment { | 8127 | pub fn start(f: *Function, writer: anytype, ctype: CType) !Assignment { |
| 7989 | return .{ .ctype = try f.ctypeFromType(ty, .complete) }; | 8128 | const self: Assignment = .{ .ctype = ctype }; |
| 7990 | } | | |
| 7991 | | | |
| 7992 | pub fn start(f: *Function, writer: anytype, ty: Type) !Assignment { | | |
| 7993 | const self = try init(f, ty); | | |
| 7994 | try self.restart(f, writer); | 8129 | try self.restart(f, writer); |
| 7995 | return self; | 8130 | return self; |
| 7996 | } | 8131 | } |