| ... | ... | @@ -39,7 +39,7 @@ pub const CValue = union(enum) { |
| 39 | 39 | constant: Air.Inst.Ref, |
| 40 | 40 | /// Index into the parameters |
| 41 | 41 | arg: usize, |
| 42 | | /// The payload field of a parameter |
| 42 | /// The array field of a parameter |
| 43 | 43 | arg_array: usize, |
| 44 | 44 | /// Index into a tuple's fields |
| 45 | 45 | field: usize, |
| ... | ... | @@ -50,6 +50,8 @@ pub const CValue = union(enum) { |
| 50 | 50 | undef: Type, |
| 51 | 51 | /// Render the slice as an identifier (using fmtIdent) |
| 52 | 52 | identifier: []const u8, |
| 53 | /// Render the slice as an payload.identifier (using fmtIdent) |
| 54 | payload_identifier: []const u8, |
| 53 | 55 | /// Render these bytes literally. |
| 54 | 56 | /// TODO make this a [*:0]const u8 to save memory |
| 55 | 57 | bytes: []const u8, |
| ... | ... | @@ -416,12 +418,20 @@ pub const Function = struct { |
| 416 | 418 | return f.object.dg.fail(format, args); |
| 417 | 419 | } |
| 418 | 420 | |
| 419 | | fn renderType(f: *Function, w: anytype, t: Type) !void { |
| 420 | | return f.object.dg.renderType(w, t, .Complete); |
| 421 | fn indexToCType(f: *Function, idx: CType.Index) CType { |
| 422 | return f.object.dg.indexToCType(idx); |
| 423 | } |
| 424 | |
| 425 | fn typeToIndex(f: *Function, ty: Type, kind: CType.Kind) !CType.Index { |
| 426 | return f.object.dg.typeToIndex(ty, kind); |
| 427 | } |
| 428 | |
| 429 | fn typeToCType(f: *Function, ty: Type, kind: CType.Kind) !CType { |
| 430 | return f.object.dg.typeToCType(ty, kind); |
| 421 | 431 | } |
| 422 | 432 | |
| 423 | | fn renderTypecast(f: *Function, w: anytype, t: Type) !void { |
| 424 | | return f.object.dg.renderTypecast(w, t); |
| 433 | fn renderType(f: *Function, w: anytype, t: Type) !void { |
| 434 | return f.object.dg.renderType(w, t); |
| 425 | 435 | } |
| 426 | 436 | |
| 427 | 437 | fn renderIntCast(f: *Function, w: anytype, dest_ty: Type, src: CValue, src_ty: Type, location: ValueRenderLocation) !void { |
| ... | ... | @@ -532,7 +542,7 @@ pub const DeclGen = struct { |
| 532 | 542 | try writer.writeByte('{'); |
| 533 | 543 | } else { |
| 534 | 544 | try writer.writeByte('('); |
| 535 | | try dg.renderTypecast(writer, ty); |
| 545 | try dg.renderType(writer, ty); |
| 536 | 546 | try writer.writeAll("){ .ptr = "); |
| 537 | 547 | } |
| 538 | 548 | |
| ... | ... | @@ -559,7 +569,7 @@ pub const DeclGen = struct { |
| 559 | 569 | const need_typecast = if (ty.castPtrToFn()) |_| false else !ty.eql(decl.ty, dg.module); |
| 560 | 570 | if (need_typecast) { |
| 561 | 571 | try writer.writeAll("(("); |
| 562 | | try dg.renderTypecast(writer, ty); |
| 572 | try dg.renderType(writer, ty); |
| 563 | 573 | try writer.writeByte(')'); |
| 564 | 574 | } |
| 565 | 575 | try writer.writeByte('&'); |
| ... | ... | @@ -574,7 +584,7 @@ pub const DeclGen = struct { |
| 574 | 584 | fn renderParentPtr(dg: *DeclGen, writer: anytype, ptr_val: Value, ptr_ty: Type, location: ValueRenderLocation) error{ OutOfMemory, AnalysisFail }!void { |
| 575 | 585 | if (!ptr_ty.isSlice()) { |
| 576 | 586 | try writer.writeByte('('); |
| 577 | | try dg.renderTypecast(writer, ptr_ty); |
| 587 | try dg.renderType(writer, ptr_ty); |
| 578 | 588 | try writer.writeByte(')'); |
| 579 | 589 | } |
| 580 | 590 | switch (ptr_val.tag()) { |
| ... | ... | @@ -589,90 +599,71 @@ pub const DeclGen = struct { |
| 589 | 599 | try dg.renderDeclValue(writer, ptr_ty, ptr_val, decl_index, location); |
| 590 | 600 | }, |
| 591 | 601 | .field_ptr => { |
| 592 | | const ptr_info = ptr_ty.ptrInfo(); |
| 602 | const target = dg.module.getTarget(); |
| 593 | 603 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; |
| 594 | | const container_ty = field_ptr.container_ty; |
| 595 | | const index = field_ptr.field_index; |
| 596 | | |
| 597 | | var container_ptr_ty_pl: Type.Payload.ElemType = .{ |
| 598 | | .base = .{ .tag = .c_mut_pointer }, |
| 599 | | .data = field_ptr.container_ty, |
| 600 | | }; |
| 601 | | const container_ptr_ty = Type.initPayload(&container_ptr_ty_pl.base); |
| 602 | | |
| 603 | | const FieldInfo = struct { name: []const u8, ty: Type }; |
| 604 | | const field_info: FieldInfo = switch (container_ty.zigTypeTag()) { |
| 605 | | .Struct => switch (container_ty.containerLayout()) { |
| 606 | | .Auto, .Extern => FieldInfo{ |
| 607 | | .name = container_ty.structFields().keys()[index], |
| 608 | | .ty = container_ty.structFields().values()[index].ty, |
| 609 | | }, |
| 610 | | .Packed => if (ptr_info.data.host_size == 0) { |
| 611 | | const target = dg.module.getTarget(); |
| 612 | | |
| 613 | | const byte_offset = container_ty.packedStructFieldByteOffset(index, target); |
| 614 | | var byte_offset_pl = Value.Payload.U64{ |
| 615 | | .base = .{ .tag = .int_u64 }, |
| 616 | | .data = byte_offset, |
| 617 | | }; |
| 618 | | const byte_offset_val = Value.initPayload(&byte_offset_pl.base); |
| 619 | | |
| 620 | | var u8_ptr_pl = ptr_info; |
| 621 | | u8_ptr_pl.data.pointee_type = Type.u8; |
| 622 | | const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base); |
| 623 | | |
| 624 | | try writer.writeAll("&(("); |
| 625 | | try dg.renderTypecast(writer, u8_ptr_ty); |
| 626 | | try writer.writeByte(')'); |
| 627 | | try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty, location); |
| 628 | | return writer.print(")[{}]", .{try dg.fmtIntLiteral(Type.usize, byte_offset_val)}); |
| 629 | | } else { |
| 630 | | var host_pl = Type.Payload.Bits{ |
| 631 | | .base = .{ .tag = .int_unsigned }, |
| 632 | | .data = ptr_info.data.host_size * 8, |
| 633 | | }; |
| 634 | | const host_ty = Type.initPayload(&host_pl.base); |
| 635 | 604 | |
| 636 | | try writer.writeByte('('); |
| 637 | | try dg.renderTypecast(writer, ptr_ty); |
| 638 | | try writer.writeByte(')'); |
| 639 | | return dg.renderParentPtr(writer, field_ptr.container_ptr, host_ty, location); |
| 640 | | }, |
| 641 | | }, |
| 642 | | .Union => switch (container_ty.containerLayout()) { |
| 643 | | .Auto, .Extern => FieldInfo{ |
| 644 | | .name = container_ty.unionFields().keys()[index], |
| 645 | | .ty = container_ty.unionFields().values()[index].ty, |
| 646 | | }, |
| 647 | | .Packed => { |
| 648 | | return dg.renderParentPtr(writer, field_ptr.container_ptr, ptr_ty, location); |
| 649 | | }, |
| 605 | // Ensure complete type definition is visible before accessing fields. |
| 606 | _ = try dg.typeToIndex(field_ptr.container_ty, .complete); |
| 607 | |
| 608 | var container_ptr_pl = ptr_ty.ptrInfo(); |
| 609 | container_ptr_pl.data.pointee_type = field_ptr.container_ty; |
| 610 | const container_ptr_ty = Type.initPayload(&container_ptr_pl.base); |
| 611 | |
| 612 | switch (fieldLocation( |
| 613 | field_ptr.container_ty, |
| 614 | ptr_ty, |
| 615 | @intCast(u32, field_ptr.field_index), |
| 616 | target, |
| 617 | )) { |
| 618 | .begin => try dg.renderParentPtr( |
| 619 | writer, |
| 620 | field_ptr.container_ptr, |
| 621 | container_ptr_ty, |
| 622 | location, |
| 623 | ), |
| 624 | .field => |field| { |
| 625 | try writer.writeAll("&("); |
| 626 | try dg.renderParentPtr( |
| 627 | writer, |
| 628 | field_ptr.container_ptr, |
| 629 | container_ptr_ty, |
| 630 | location, |
| 631 | ); |
| 632 | try writer.writeAll(")->"); |
| 633 | try dg.writeCValue(writer, field); |
| 650 | 634 | }, |
| 651 | | .Pointer => field_info: { |
| 652 | | assert(container_ty.isSlice()); |
| 653 | | break :field_info switch (index) { |
| 654 | | 0 => FieldInfo{ .name = "ptr", .ty = container_ty.childType() }, |
| 655 | | 1 => FieldInfo{ .name = "len", .ty = Type.usize }, |
| 656 | | else => unreachable, |
| 635 | .byte_offset => |byte_offset| { |
| 636 | var u8_ptr_pl = ptr_ty.ptrInfo(); |
| 637 | u8_ptr_pl.data.pointee_type = Type.u8; |
| 638 | const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base); |
| 639 | |
| 640 | var byte_offset_pl = Value.Payload.U64{ |
| 641 | .base = .{ .tag = .int_u64 }, |
| 642 | .data = byte_offset, |
| 657 | 643 | }; |
| 658 | | }, |
| 659 | | else => unreachable, |
| 660 | | }; |
| 661 | | |
| 662 | | if (field_info.ty.hasRuntimeBitsIgnoreComptime()) { |
| 663 | | // Ensure complete type definition is visible before accessing fields. |
| 664 | | try dg.renderType(std.io.null_writer, field_ptr.container_ty, .Complete); |
| 644 | const byte_offset_val = Value.initPayload(&byte_offset_pl.base); |
| 665 | 645 | |
| 666 | | try writer.writeAll("&("); |
| 667 | | try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty, location); |
| 668 | | try writer.writeAll(")->"); |
| 669 | | switch (field_ptr.container_ty.tag()) { |
| 670 | | .union_tagged, .union_safety_tagged => try writer.writeAll("payload."), |
| 671 | | else => {}, |
| 672 | | } |
| 673 | | try writer.print("{ }", .{fmtIdent(field_info.name)}); |
| 674 | | } else { |
| 675 | | try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty, location); |
| 646 | try writer.writeAll("(("); |
| 647 | try dg.renderType(writer, u8_ptr_ty); |
| 648 | try writer.writeByte(')'); |
| 649 | try dg.renderParentPtr( |
| 650 | writer, |
| 651 | field_ptr.container_ptr, |
| 652 | container_ptr_ty, |
| 653 | location, |
| 654 | ); |
| 655 | try writer.print(" + {})", .{try dg.fmtIntLiteral(Type.usize, byte_offset_val)}); |
| 656 | }, |
| 657 | .end => { |
| 658 | try writer.writeAll("(("); |
| 659 | try dg.renderParentPtr( |
| 660 | writer, |
| 661 | field_ptr.container_ptr, |
| 662 | container_ptr_ty, |
| 663 | location, |
| 664 | ); |
| 665 | try writer.print(") + {})", .{try dg.fmtIntLiteral(Type.usize, Value.one)}); |
| 666 | }, |
| 676 | 667 | } |
| 677 | 668 | }, |
| 678 | 669 | .elem_ptr => { |
| ... | ... | @@ -696,7 +687,7 @@ pub const DeclGen = struct { |
| 696 | 687 | const container_ptr_ty = Type.initPayload(&container_ptr_ty_pl.base); |
| 697 | 688 | |
| 698 | 689 | // Ensure complete type definition is visible before accessing fields. |
| 699 | | try dg.renderType(std.io.null_writer, payload_ptr.container_ty, .Complete); |
| 690 | _ = try dg.typeToIndex(payload_ptr.container_ty, .complete); |
| 700 | 691 | |
| 701 | 692 | try writer.writeAll("&("); |
| 702 | 693 | try dg.renderParentPtr(writer, payload_ptr.container_ptr, container_ptr_ty, location); |
| ... | ... | @@ -763,18 +754,18 @@ pub const DeclGen = struct { |
| 763 | 754 | .Pointer => if (ty.isSlice()) { |
| 764 | 755 | if (!location.isInitializer()) { |
| 765 | 756 | try writer.writeByte('('); |
| 766 | | try dg.renderTypecast(writer, ty); |
| 757 | try dg.renderType(writer, ty); |
| 767 | 758 | try writer.writeByte(')'); |
| 768 | 759 | } |
| 769 | 760 | |
| 770 | 761 | try writer.writeAll("{("); |
| 771 | 762 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 772 | 763 | const ptr_ty = ty.slicePtrFieldType(&buf); |
| 773 | | try dg.renderTypecast(writer, ptr_ty); |
| 764 | try dg.renderType(writer, ptr_ty); |
| 774 | 765 | return writer.print("){x}, {0x}}}", .{try dg.fmtIntLiteral(Type.usize, val)}); |
| 775 | 766 | } else { |
| 776 | 767 | try writer.writeAll("(("); |
| 777 | | try dg.renderTypecast(writer, ty); |
| 768 | try dg.renderType(writer, ty); |
| 778 | 769 | return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val)}); |
| 779 | 770 | }, |
| 780 | 771 | .Optional => { |
| ... | ... | @@ -791,7 +782,7 @@ pub const DeclGen = struct { |
| 791 | 782 | |
| 792 | 783 | if (!location.isInitializer()) { |
| 793 | 784 | try writer.writeByte('('); |
| 794 | | try dg.renderTypecast(writer, ty); |
| 785 | try dg.renderType(writer, ty); |
| 795 | 786 | try writer.writeByte(')'); |
| 796 | 787 | } |
| 797 | 788 | |
| ... | ... | @@ -805,7 +796,7 @@ pub const DeclGen = struct { |
| 805 | 796 | .Auto, .Extern => { |
| 806 | 797 | if (!location.isInitializer()) { |
| 807 | 798 | try writer.writeByte('('); |
| 808 | | try dg.renderTypecast(writer, ty); |
| 799 | try dg.renderType(writer, ty); |
| 809 | 800 | try writer.writeByte(')'); |
| 810 | 801 | } |
| 811 | 802 | |
| ... | ... | @@ -827,7 +818,7 @@ pub const DeclGen = struct { |
| 827 | 818 | .Union => { |
| 828 | 819 | if (!location.isInitializer()) { |
| 829 | 820 | try writer.writeByte('('); |
| 830 | | try dg.renderTypecast(writer, ty); |
| 821 | try dg.renderType(writer, ty); |
| 831 | 822 | try writer.writeByte(')'); |
| 832 | 823 | } |
| 833 | 824 | |
| ... | ... | @@ -852,7 +843,7 @@ pub const DeclGen = struct { |
| 852 | 843 | .ErrorUnion => { |
| 853 | 844 | if (!location.isInitializer()) { |
| 854 | 845 | try writer.writeByte('('); |
| 855 | | try dg.renderTypecast(writer, ty); |
| 846 | try dg.renderType(writer, ty); |
| 856 | 847 | try writer.writeByte(')'); |
| 857 | 848 | } |
| 858 | 849 | |
| ... | ... | @@ -865,7 +856,7 @@ pub const DeclGen = struct { |
| 865 | 856 | .Array, .Vector => { |
| 866 | 857 | if (!location.isInitializer()) { |
| 867 | 858 | try writer.writeByte('('); |
| 868 | | try dg.renderTypecast(writer, ty); |
| 859 | try dg.renderType(writer, ty); |
| 869 | 860 | try writer.writeByte(')'); |
| 870 | 861 | } |
| 871 | 862 | |
| ... | ... | @@ -1026,7 +1017,7 @@ pub const DeclGen = struct { |
| 1026 | 1017 | return dg.renderValue(writer, ty, slice_val, location); |
| 1027 | 1018 | } else { |
| 1028 | 1019 | try writer.writeAll("(("); |
| 1029 | | try dg.renderTypecast(writer, ty); |
| 1020 | try dg.renderType(writer, ty); |
| 1030 | 1021 | try writer.writeAll(")NULL)"); |
| 1031 | 1022 | }, |
| 1032 | 1023 | .variable => { |
| ... | ... | @@ -1036,7 +1027,7 @@ pub const DeclGen = struct { |
| 1036 | 1027 | .slice => { |
| 1037 | 1028 | if (!location.isInitializer()) { |
| 1038 | 1029 | try writer.writeByte('('); |
| 1039 | | try dg.renderTypecast(writer, ty); |
| 1030 | try dg.renderType(writer, ty); |
| 1040 | 1031 | try writer.writeByte(')'); |
| 1041 | 1032 | } |
| 1042 | 1033 | |
| ... | ... | @@ -1059,7 +1050,7 @@ pub const DeclGen = struct { |
| 1059 | 1050 | }, |
| 1060 | 1051 | .int_u64, .one => { |
| 1061 | 1052 | try writer.writeAll("(("); |
| 1062 | | try dg.renderTypecast(writer, ty); |
| 1053 | try dg.renderType(writer, ty); |
| 1063 | 1054 | return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val)}); |
| 1064 | 1055 | }, |
| 1065 | 1056 | .field_ptr, |
| ... | ... | @@ -1074,7 +1065,7 @@ pub const DeclGen = struct { |
| 1074 | 1065 | .Array, .Vector => { |
| 1075 | 1066 | if (location == .FunctionArgument) { |
| 1076 | 1067 | try writer.writeByte('('); |
| 1077 | | try dg.renderTypecast(writer, ty); |
| 1068 | try dg.renderType(writer, ty); |
| 1078 | 1069 | try writer.writeByte(')'); |
| 1079 | 1070 | } |
| 1080 | 1071 | |
| ... | ... | @@ -1177,7 +1168,7 @@ pub const DeclGen = struct { |
| 1177 | 1168 | |
| 1178 | 1169 | if (!location.isInitializer()) { |
| 1179 | 1170 | try writer.writeByte('('); |
| 1180 | | try dg.renderTypecast(writer, ty); |
| 1171 | try dg.renderType(writer, ty); |
| 1181 | 1172 | try writer.writeByte(')'); |
| 1182 | 1173 | } |
| 1183 | 1174 | |
| ... | ... | @@ -1211,7 +1202,7 @@ pub const DeclGen = struct { |
| 1211 | 1202 | |
| 1212 | 1203 | if (!location.isInitializer()) { |
| 1213 | 1204 | try writer.writeByte('('); |
| 1214 | | try dg.renderTypecast(writer, ty); |
| 1205 | try dg.renderType(writer, ty); |
| 1215 | 1206 | try writer.writeByte(')'); |
| 1216 | 1207 | } |
| 1217 | 1208 | |
| ... | ... | @@ -1275,7 +1266,7 @@ pub const DeclGen = struct { |
| 1275 | 1266 | |
| 1276 | 1267 | if (!location.isInitializer()) { |
| 1277 | 1268 | try writer.writeByte('('); |
| 1278 | | try dg.renderTypecast(writer, ty); |
| 1269 | try dg.renderType(writer, ty); |
| 1279 | 1270 | try writer.writeByte(')'); |
| 1280 | 1271 | } |
| 1281 | 1272 | |
| ... | ... | @@ -1362,7 +1353,7 @@ pub const DeclGen = struct { |
| 1362 | 1353 | |
| 1363 | 1354 | if (!empty) try writer.writeAll(" | "); |
| 1364 | 1355 | try writer.writeByte('('); |
| 1365 | | try dg.renderTypecast(writer, ty); |
| 1356 | try dg.renderType(writer, ty); |
| 1366 | 1357 | try writer.writeByte(')'); |
| 1367 | 1358 | |
| 1368 | 1359 | if (bit_offset_val_pl.data != 0) { |
| ... | ... | @@ -1385,7 +1376,7 @@ pub const DeclGen = struct { |
| 1385 | 1376 | |
| 1386 | 1377 | if (!location.isInitializer()) { |
| 1387 | 1378 | try writer.writeByte('('); |
| 1388 | | try dg.renderTypecast(writer, ty); |
| 1379 | try dg.renderType(writer, ty); |
| 1389 | 1380 | try writer.writeByte(')'); |
| 1390 | 1381 | } |
| 1391 | 1382 | |
| ... | ... | @@ -1396,11 +1387,11 @@ pub const DeclGen = struct { |
| 1396 | 1387 | if (field_ty.hasRuntimeBits()) { |
| 1397 | 1388 | if (field_ty.isPtrAtRuntime()) { |
| 1398 | 1389 | try writer.writeByte('('); |
| 1399 | | try dg.renderTypecast(writer, ty); |
| 1390 | try dg.renderType(writer, ty); |
| 1400 | 1391 | try writer.writeByte(')'); |
| 1401 | 1392 | } else if (field_ty.zigTypeTag() == .Float) { |
| 1402 | 1393 | try writer.writeByte('('); |
| 1403 | | try dg.renderTypecast(writer, ty); |
| 1394 | try dg.renderType(writer, ty); |
| 1404 | 1395 | try writer.writeByte(')'); |
| 1405 | 1396 | } |
| 1406 | 1397 | try dg.renderValue(writer, field_ty, union_obj.val, initializer_type); |
| ... | ... | @@ -1509,9 +1500,11 @@ pub const DeclGen = struct { |
| 1509 | 1500 | fn indexToCType(dg: *DeclGen, idx: CType.Index) CType { |
| 1510 | 1501 | return dg.ctypes.indexToCType(idx); |
| 1511 | 1502 | } |
| 1503 | |
| 1512 | 1504 | fn typeToIndex(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType.Index { |
| 1513 | 1505 | return dg.ctypes.typeToIndex(dg.gpa, ty, dg.module, kind); |
| 1514 | 1506 | } |
| 1507 | |
| 1515 | 1508 | fn typeToCType(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType { |
| 1516 | 1509 | return dg.ctypes.typeToCType(dg.gpa, ty, dg.module, kind); |
| 1517 | 1510 | } |
| ... | ... | @@ -1524,16 +1517,10 @@ pub const DeclGen = struct { |
| 1524 | 1517 | /// There are three type formats in total that we support rendering: |
| 1525 | 1518 | /// | Function | Example 1 (*u8) | Example 2 ([10]*u8) | |
| 1526 | 1519 | /// |---------------------|-----------------|---------------------| |
| 1527 | | /// | `renderTypecast` | "uint8_t *" | "uint8_t *[10]" | |
| 1528 | 1520 | /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" | |
| 1529 | 1521 | /// | `renderType` | "uint8_t *" | "uint8_t *[10]" | |
| 1530 | 1522 | /// |
| 1531 | | fn renderType( |
| 1532 | | dg: *DeclGen, |
| 1533 | | w: anytype, |
| 1534 | | t: Type, |
| 1535 | | _: TypedefKind, |
| 1536 | | ) error{ OutOfMemory, AnalysisFail }!void { |
| 1523 | fn renderType(dg: *DeclGen, w: anytype, t: Type) error{ OutOfMemory, AnalysisFail }!void { |
| 1537 | 1524 | const store = &dg.ctypes.set; |
| 1538 | 1525 | const module = dg.module; |
| 1539 | 1526 | const idx = try dg.typeToIndex(t, .complete); |
| ... | ... | @@ -1603,12 +1590,12 @@ pub const DeclGen = struct { |
| 1603 | 1590 | |
| 1604 | 1591 | if (needs_cast) { |
| 1605 | 1592 | try w.writeByte('('); |
| 1606 | | try dg.renderTypecast(w, dest_ty); |
| 1593 | try dg.renderType(w, dest_ty); |
| 1607 | 1594 | try w.writeByte(')'); |
| 1608 | 1595 | } |
| 1609 | 1596 | if (src_is_ptr) { |
| 1610 | 1597 | try w.writeByte('('); |
| 1611 | | try dg.renderTypecast(w, src_eff_ty); |
| 1598 | try dg.renderType(w, src_eff_ty); |
| 1612 | 1599 | try w.writeByte(')'); |
| 1613 | 1600 | } |
| 1614 | 1601 | try context.writeValue(dg, w, src_ty, location); |
| ... | ... | @@ -1625,7 +1612,7 @@ pub const DeclGen = struct { |
| 1625 | 1612 | try w.writeAll("(0, "); // TODO: Should the 0 go through fmtIntLiteral? |
| 1626 | 1613 | if (src_is_ptr) { |
| 1627 | 1614 | try w.writeByte('('); |
| 1628 | | try dg.renderTypecast(w, src_eff_ty); |
| 1615 | try dg.renderType(w, src_eff_ty); |
| 1629 | 1616 | try w.writeByte(')'); |
| 1630 | 1617 | } |
| 1631 | 1618 | try context.writeValue(dg, w, src_ty, .FunctionArgument); |
| ... | ... | @@ -1646,28 +1633,11 @@ pub const DeclGen = struct { |
| 1646 | 1633 | } |
| 1647 | 1634 | } |
| 1648 | 1635 | |
| 1649 | | /// Renders a type in C typecast format. |
| 1650 | | /// |
| 1651 | | /// This is guaranteed to be valid in a typecast expression, but not |
| 1652 | | /// necessarily in a variable/field declaration. |
| 1653 | | /// |
| 1654 | | /// There are three type formats in total that we support rendering: |
| 1655 | | /// | Function | Example 1 (*u8) | Example 2 ([10]*u8) | |
| 1656 | | /// |---------------------|-----------------|---------------------| |
| 1657 | | /// | `renderTypecast` | "uint8_t *" | "uint8_t *[10]" | |
| 1658 | | /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" | |
| 1659 | | /// | `renderType` | "uint8_t *" | "uint8_t *[10]" | |
| 1660 | | /// |
| 1661 | | fn renderTypecast(dg: *DeclGen, w: anytype, ty: Type) error{ OutOfMemory, AnalysisFail }!void { |
| 1662 | | try dg.renderType(w, ty, undefined); |
| 1663 | | } |
| 1664 | | |
| 1665 | 1636 | /// Renders a type and name in field declaration/definition format. |
| 1666 | 1637 | /// |
| 1667 | 1638 | /// There are three type formats in total that we support rendering: |
| 1668 | 1639 | /// | Function | Example 1 (*u8) | Example 2 ([10]*u8) | |
| 1669 | 1640 | /// |---------------------|-----------------|---------------------| |
| 1670 | | /// | `renderTypecast` | "uint8_t *" | "uint8_t *[10]" | |
| 1671 | 1641 | /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" | |
| 1672 | 1642 | /// | `renderType` | "uint8_t *" | "uint8_t *[10]" | |
| 1673 | 1643 | /// |
| ... | ... | @@ -1708,7 +1678,7 @@ pub const DeclGen = struct { |
| 1708 | 1678 | const name_slice_ty = Type.initTag(.const_slice_u8_sentinel_0); |
| 1709 | 1679 | |
| 1710 | 1680 | try w.writeAll("static "); |
| 1711 | | try dg.renderType(w, name_slice_ty, .Complete); |
| 1681 | try dg.renderType(w, name_slice_ty); |
| 1712 | 1682 | try w.writeByte(' '); |
| 1713 | 1683 | try w.writeAll(fn_name); |
| 1714 | 1684 | try w.writeByte('('); |
| ... | ... | @@ -1742,7 +1712,7 @@ pub const DeclGen = struct { |
| 1742 | 1712 | try w.writeAll(" = "); |
| 1743 | 1713 | try dg.renderValue(w, name_ty, name_val, .Initializer); |
| 1744 | 1714 | try w.writeAll(";\n return ("); |
| 1745 | | try dg.renderTypecast(w, name_slice_ty); |
| 1715 | try dg.renderType(w, name_slice_ty); |
| 1746 | 1716 | try w.print("){{{}, {}}};\n", .{ |
| 1747 | 1717 | fmtIdent("name"), try dg.fmtIntLiteral(Type.usize, len_val), |
| 1748 | 1718 | }); |
| ... | ... | @@ -1787,6 +1757,10 @@ pub const DeclGen = struct { |
| 1787 | 1757 | }, |
| 1788 | 1758 | .undef => |ty| return dg.renderValue(w, ty, Value.undef, .Other), |
| 1789 | 1759 | .identifier => |ident| return w.print("{ }", .{fmtIdent(ident)}), |
| 1760 | .payload_identifier => |ident| return w.print("{ }.{ }", .{ |
| 1761 | fmtIdent("payload"), |
| 1762 | fmtIdent(ident), |
| 1763 | }), |
| 1790 | 1764 | .bytes => |bytes| return w.writeAll(bytes), |
| 1791 | 1765 | } |
| 1792 | 1766 | } |
| ... | ... | @@ -1812,6 +1786,10 @@ pub const DeclGen = struct { |
| 1812 | 1786 | .decl_ref => |decl| return dg.renderDeclName(w, decl, 0), |
| 1813 | 1787 | .undef => unreachable, |
| 1814 | 1788 | .identifier => |ident| return w.print("(*{ })", .{fmtIdent(ident)}), |
| 1789 | .payload_identifier => |ident| return w.print("(*{ }.{ })", .{ |
| 1790 | fmtIdent("payload"), |
| 1791 | fmtIdent(ident), |
| 1792 | }), |
| 1815 | 1793 | .bytes => |bytes| { |
| 1816 | 1794 | try w.writeAll("(*"); |
| 1817 | 1795 | try w.writeAll(bytes); |
| ... | ... | @@ -1829,7 +1807,7 @@ pub const DeclGen = struct { |
| 1829 | 1807 | fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void { |
| 1830 | 1808 | switch (c_value) { |
| 1831 | 1809 | .none, .constant, .field, .undef => unreachable, |
| 1832 | | .new_local, .local, .arg, .arg_array, .decl, .identifier, .bytes => { |
| 1810 | .new_local, .local, .arg, .arg_array, .decl, .identifier, .payload_identifier, .bytes => { |
| 1833 | 1811 | try dg.writeCValue(writer, c_value); |
| 1834 | 1812 | try writer.writeAll("->"); |
| 1835 | 1813 | }, |
| ... | ... | @@ -3048,7 +3026,7 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3048 | 3026 | try writer.writeByte(']'); |
| 3049 | 3027 | if (is_array) { |
| 3050 | 3028 | try writer.writeAll(", sizeof("); |
| 3051 | | try f.renderTypecast(writer, inst_ty); |
| 3029 | try f.renderType(writer, inst_ty); |
| 3052 | 3030 | try writer.writeAll("))"); |
| 3053 | 3031 | } |
| 3054 | 3032 | try writer.writeAll(";\n"); |
| ... | ... | @@ -3080,7 +3058,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3080 | 3058 | const local = try f.allocLocal(inst, f.air.typeOfIndex(inst)); |
| 3081 | 3059 | try f.writeCValue(writer, local, .Other); |
| 3082 | 3060 | try writer.writeAll(" = ("); |
| 3083 | | try f.renderTypecast(writer, inst_ty); |
| 3061 | try f.renderType(writer, inst_ty); |
| 3084 | 3062 | try writer.writeAll(")&("); |
| 3085 | 3063 | if (ptr_ty.ptrSize() == .One) { |
| 3086 | 3064 | // It's a pointer to an array, so we need to de-reference. |
| ... | ... | @@ -3128,7 +3106,7 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3128 | 3106 | try writer.writeByte(']'); |
| 3129 | 3107 | if (is_array) { |
| 3130 | 3108 | try writer.writeAll(", sizeof("); |
| 3131 | | try f.renderTypecast(writer, inst_ty); |
| 3109 | try f.renderType(writer, inst_ty); |
| 3132 | 3110 | try writer.writeAll("))"); |
| 3133 | 3111 | } |
| 3134 | 3112 | try writer.writeAll(";\n"); |
| ... | ... | @@ -3197,7 +3175,7 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3197 | 3175 | try writer.writeByte(']'); |
| 3198 | 3176 | if (is_array) { |
| 3199 | 3177 | try writer.writeAll(", sizeof("); |
| 3200 | | try f.renderTypecast(writer, inst_ty); |
| 3178 | try f.renderType(writer, inst_ty); |
| 3201 | 3179 | try writer.writeAll("))"); |
| 3202 | 3180 | } |
| 3203 | 3181 | try writer.writeAll(";\n"); |
| ... | ... | @@ -3240,11 +3218,11 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3240 | 3218 | |
| 3241 | 3219 | fn airArg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3242 | 3220 | const inst_ty = f.air.typeOfIndex(inst); |
| 3243 | | const inst_cty = try f.object.dg.typeToIndex(inst_ty, .parameter); |
| 3221 | const inst_cty = try f.typeToIndex(inst_ty, .parameter); |
| 3244 | 3222 | |
| 3245 | 3223 | const i = f.next_arg_index; |
| 3246 | 3224 | f.next_arg_index += 1; |
| 3247 | | return if (inst_cty != try f.object.dg.typeToIndex(inst_ty, .complete)) |
| 3225 | return if (inst_cty != try f.typeToIndex(inst_ty, .complete)) |
| 3248 | 3226 | .{ .arg_array = i } |
| 3249 | 3227 | else |
| 3250 | 3228 | .{ .arg = i }; |
| ... | ... | @@ -3281,7 +3259,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3281 | 3259 | try writer.writeAll(", (const char *)"); |
| 3282 | 3260 | try f.writeCValue(writer, operand, .Other); |
| 3283 | 3261 | try writer.writeAll(", sizeof("); |
| 3284 | | try f.renderTypecast(writer, src_ty); |
| 3262 | try f.renderType(writer, src_ty); |
| 3285 | 3263 | try writer.writeAll("))"); |
| 3286 | 3264 | } else if (ptr_info.host_size != 0) { |
| 3287 | 3265 | var host_pl = Type.Payload.Bits{ |
| ... | ... | @@ -3310,11 +3288,11 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3310 | 3288 | |
| 3311 | 3289 | try f.writeCValue(writer, local, .Other); |
| 3312 | 3290 | try writer.writeAll(" = ("); |
| 3313 | | try f.renderTypecast(writer, src_ty); |
| 3291 | try f.renderType(writer, src_ty); |
| 3314 | 3292 | try writer.writeAll(")zig_wrap_"); |
| 3315 | 3293 | try f.object.dg.renderTypeForBuiltinFnName(writer, field_ty); |
| 3316 | 3294 | try writer.writeAll("(("); |
| 3317 | | try f.renderTypecast(writer, field_ty); |
| 3295 | try f.renderType(writer, field_ty); |
| 3318 | 3296 | try writer.writeByte(')'); |
| 3319 | 3297 | const cant_cast = host_ty.isInt() and host_ty.bitSize(target) > 64; |
| 3320 | 3298 | if (cant_cast) { |
| ... | ... | @@ -3365,7 +3343,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { |
| 3365 | 3343 | try f.writeCValue(writer, operand, .FunctionArgument); |
| 3366 | 3344 | deref = false; |
| 3367 | 3345 | try writer.writeAll(", sizeof("); |
| 3368 | | try f.renderTypecast(writer, ret_ty); |
| 3346 | try f.renderType(writer, ret_ty); |
| 3369 | 3347 | try writer.writeAll("));\n"); |
| 3370 | 3348 | break :ret_val array_local; |
| 3371 | 3349 | } else operand; |
| ... | ... | @@ -3440,7 +3418,7 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3440 | 3418 | try writer.writeByte('('); |
| 3441 | 3419 | } else if (dest_c_bits <= 64) { |
| 3442 | 3420 | try writer.writeByte('('); |
| 3443 | | try f.renderTypecast(writer, inst_ty); |
| 3421 | try f.renderType(writer, inst_ty); |
| 3444 | 3422 | try writer.writeByte(')'); |
| 3445 | 3423 | } |
| 3446 | 3424 | |
| ... | ... | @@ -3521,7 +3499,7 @@ fn storeUndefined(f: *Function, lhs_child_ty: Type, dest_ptr: CValue) !CValue { |
| 3521 | 3499 | try writer.writeAll("memset("); |
| 3522 | 3500 | try f.writeCValue(writer, dest_ptr, .FunctionArgument); |
| 3523 | 3501 | try writer.print(", {x}, sizeof(", .{try f.fmtIntLiteral(Type.u8, Value.undef)}); |
| 3524 | | try f.renderTypecast(writer, lhs_child_ty); |
| 3502 | try f.renderType(writer, lhs_child_ty); |
| 3525 | 3503 | try writer.writeAll("));\n"); |
| 3526 | 3504 | } |
| 3527 | 3505 | return CValue.none; |
| ... | ... | @@ -3582,7 +3560,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3582 | 3560 | if (!is_array) try writer.writeByte('&'); |
| 3583 | 3561 | try f.writeCValue(writer, array_src, .FunctionArgument); |
| 3584 | 3562 | try writer.writeAll(", sizeof("); |
| 3585 | | try f.renderTypecast(writer, src_ty); |
| 3563 | try f.renderType(writer, src_ty); |
| 3586 | 3564 | try writer.writeAll("))"); |
| 3587 | 3565 | if (src_val == .constant) { |
| 3588 | 3566 | try freeLocal(f, inst, array_src.new_local, 0); |
| ... | ... | @@ -3641,13 +3619,13 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3641 | 3619 | try writer.writeAll("(0, "); |
| 3642 | 3620 | } else { |
| 3643 | 3621 | try writer.writeByte('('); |
| 3644 | | try f.renderTypecast(writer, host_ty); |
| 3622 | try f.renderType(writer, host_ty); |
| 3645 | 3623 | try writer.writeByte(')'); |
| 3646 | 3624 | } |
| 3647 | 3625 | |
| 3648 | 3626 | if (src_ty.isPtrAtRuntime()) { |
| 3649 | 3627 | try writer.writeByte('('); |
| 3650 | | try f.renderTypecast(writer, Type.usize); |
| 3628 | try f.renderType(writer, Type.usize); |
| 3651 | 3629 | try writer.writeByte(')'); |
| 3652 | 3630 | } |
| 3653 | 3631 | try f.writeCValue(writer, src_val, .Other); |
| ... | ... | @@ -3919,7 +3897,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { |
| 3919 | 3897 | // results in a NULL pointer, or if LHS is NULL. The operation is only UB |
| 3920 | 3898 | // if the result is NULL and then dereferenced. |
| 3921 | 3899 | try writer.writeByte('('); |
| 3922 | | try f.renderTypecast(writer, inst_ty); |
| 3900 | try f.renderType(writer, inst_ty); |
| 3923 | 3901 | try writer.writeAll(")(((uintptr_t)"); |
| 3924 | 3902 | try f.writeCValue(writer, lhs, .Other); |
| 3925 | 3903 | try writer.writeAll(") "); |
| ... | ... | @@ -3927,7 +3905,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { |
| 3927 | 3905 | try writer.writeAll(" ("); |
| 3928 | 3906 | try f.writeCValue(writer, rhs, .Other); |
| 3929 | 3907 | try writer.writeAll("*sizeof("); |
| 3930 | | try f.renderTypecast(writer, elem_ty); |
| 3908 | try f.renderType(writer, elem_ty); |
| 3931 | 3909 | try writer.writeAll(")))"); |
| 3932 | 3910 | } else try f.writeCValue(writer, lhs, .Initializer); |
| 3933 | 3911 | |
| ... | ... | @@ -3992,7 +3970,7 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3992 | 3970 | try f.writeCValue(writer, local, .Other); |
| 3993 | 3971 | try writer.writeAll(".ptr = ("); |
| 3994 | 3972 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 3995 | | try f.renderTypecast(writer, inst_ty.slicePtrFieldType(&buf)); |
| 3973 | try f.renderType(writer, inst_ty.slicePtrFieldType(&buf)); |
| 3996 | 3974 | try writer.writeByte(')'); |
| 3997 | 3975 | try f.writeCValue(writer, ptr, .Other); |
| 3998 | 3976 | try writer.writeAll("; "); |
| ... | ... | @@ -4032,13 +4010,13 @@ fn airCall( |
| 4032 | 4010 | defer gpa.free(resolved_args); |
| 4033 | 4011 | for (resolved_args, args) |*resolved_arg, arg| { |
| 4034 | 4012 | const arg_ty = f.air.typeOf(arg); |
| 4035 | | const arg_cty = try f.object.dg.typeToIndex(arg_ty, .parameter); |
| 4036 | | if (f.object.dg.indexToCType(arg_cty).tag() == .void) { |
| 4013 | const arg_cty = try f.typeToIndex(arg_ty, .parameter); |
| 4014 | if (f.indexToCType(arg_cty).tag() == .void) { |
| 4037 | 4015 | resolved_arg.* = .none; |
| 4038 | 4016 | continue; |
| 4039 | 4017 | } |
| 4040 | 4018 | resolved_arg.* = try f.resolveInst(arg); |
| 4041 | | if (arg_cty != try f.object.dg.typeToIndex(arg_ty, .complete)) { |
| 4019 | if (arg_cty != try f.typeToIndex(arg_ty, .complete)) { |
| 4042 | 4020 | var lowered_arg_buf: LowerFnRetTyBuffer = undefined; |
| 4043 | 4021 | const lowered_arg_ty = lowerFnRetTy(arg_ty, &lowered_arg_buf, target); |
| 4044 | 4022 | |
| ... | ... | @@ -4048,7 +4026,7 @@ fn airCall( |
| 4048 | 4026 | try writer.writeAll(", "); |
| 4049 | 4027 | try f.writeCValue(writer, resolved_arg.*, .FunctionArgument); |
| 4050 | 4028 | try writer.writeAll(", sizeof("); |
| 4051 | | try f.renderTypecast(writer, lowered_arg_ty); |
| 4029 | try f.renderType(writer, lowered_arg_ty); |
| 4052 | 4030 | try writer.writeAll("));\n"); |
| 4053 | 4031 | resolved_arg.* = array_local; |
| 4054 | 4032 | } |
| ... | ... | @@ -4077,7 +4055,7 @@ fn airCall( |
| 4077 | 4055 | .none |
| 4078 | 4056 | else if (f.liveness.isUnused(inst)) r: { |
| 4079 | 4057 | try writer.writeByte('('); |
| 4080 | | try f.renderTypecast(writer, Type.void); |
| 4058 | try f.renderType(writer, Type.void); |
| 4081 | 4059 | try writer.writeByte(')'); |
| 4082 | 4060 | break :r .none; |
| 4083 | 4061 | } else r: { |
| ... | ... | @@ -4132,7 +4110,7 @@ fn airCall( |
| 4132 | 4110 | try writer.writeAll(", "); |
| 4133 | 4111 | try f.writeCValueMember(writer, result_local, .{ .identifier = "array" }); |
| 4134 | 4112 | try writer.writeAll(", sizeof("); |
| 4135 | | try f.renderTypecast(writer, ret_ty); |
| 4113 | try f.renderType(writer, ret_ty); |
| 4136 | 4114 | try writer.writeAll("));\n"); |
| 4137 | 4115 | try freeLocal(f, inst, result_local.new_local, 0); |
| 4138 | 4116 | break :r array_local; |
| ... | ... | @@ -4280,7 +4258,7 @@ fn lowerTry( |
| 4280 | 4258 | try writer.writeAll(", "); |
| 4281 | 4259 | try f.writeCValueMember(writer, err_union, .{ .identifier = "payload" }); |
| 4282 | 4260 | try writer.writeAll(", sizeof("); |
| 4283 | | try f.renderTypecast(writer, payload_ty); |
| 4261 | try f.renderType(writer, payload_ty); |
| 4284 | 4262 | try writer.writeAll("));\n"); |
| 4285 | 4263 | } else { |
| 4286 | 4264 | try f.writeCValue(writer, local, .Other); |
| ... | ... | @@ -4313,7 +4291,7 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4313 | 4291 | try writer.writeAll(", "); |
| 4314 | 4292 | try f.writeCValue(writer, operand, .FunctionArgument); |
| 4315 | 4293 | try writer.writeAll(", sizeof("); |
| 4316 | | try f.renderTypecast(writer, operand_ty); |
| 4294 | try f.renderType(writer, operand_ty); |
| 4317 | 4295 | try writer.writeAll("))"); |
| 4318 | 4296 | } else { |
| 4319 | 4297 | try f.writeCValue(writer, result, .Other); |
| ... | ... | @@ -4362,7 +4340,7 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4362 | 4340 | if (dest_ty.isPtrAtRuntime() and operand_ty.isPtrAtRuntime()) { |
| 4363 | 4341 | try f.writeCValue(writer, local, .Other); |
| 4364 | 4342 | try writer.writeAll(" = ("); |
| 4365 | | try f.renderTypecast(writer, dest_ty); |
| 4343 | try f.renderType(writer, dest_ty); |
| 4366 | 4344 | try writer.writeByte(')'); |
| 4367 | 4345 | try f.writeCValue(writer, operand, .Other); |
| 4368 | 4346 | try writer.writeAll(";\n"); |
| ... | ... | @@ -4383,7 +4361,7 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4383 | 4361 | try writer.writeAll(", &"); |
| 4384 | 4362 | try f.writeCValue(writer, operand_lval, .Other); |
| 4385 | 4363 | try writer.writeAll(", sizeof("); |
| 4386 | | try f.renderTypecast(writer, dest_ty); |
| 4364 | try f.renderType(writer, dest_ty); |
| 4387 | 4365 | try writer.writeAll("));\n"); |
| 4388 | 4366 | |
| 4389 | 4367 | // Ensure padding bits have the expected value. |
| ... | ... | @@ -4415,7 +4393,7 @@ fn airRetAddr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4415 | 4393 | const local = try f.allocLocal(inst, Type.usize); |
| 4416 | 4394 | try f.writeCValue(writer, local, .Other); |
| 4417 | 4395 | try writer.writeAll(" = ("); |
| 4418 | | try f.renderTypecast(writer, Type.usize); |
| 4396 | try f.renderType(writer, Type.usize); |
| 4419 | 4397 | try writer.writeAll(")zig_return_address();\n"); |
| 4420 | 4398 | return local; |
| 4421 | 4399 | } |
| ... | ... | @@ -4426,7 +4404,7 @@ fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4426 | 4404 | const local = try f.allocLocal(inst, Type.usize); |
| 4427 | 4405 | try f.writeCValue(writer, local, .Other); |
| 4428 | 4406 | try writer.writeAll(" = ("); |
| 4429 | | try f.renderTypecast(writer, Type.usize); |
| 4407 | try f.renderType(writer, Type.usize); |
| 4430 | 4408 | try writer.writeAll(")zig_frame_address();\n"); |
| 4431 | 4409 | return local; |
| 4432 | 4410 | } |
| ... | ... | @@ -4558,11 +4536,11 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4558 | 4536 | try writer.writeAll("switch ("); |
| 4559 | 4537 | if (condition_ty.zigTypeTag() == .Bool) { |
| 4560 | 4538 | try writer.writeByte('('); |
| 4561 | | try f.renderTypecast(writer, Type.u1); |
| 4539 | try f.renderType(writer, Type.u1); |
| 4562 | 4540 | try writer.writeByte(')'); |
| 4563 | 4541 | } else if (condition_ty.isPtrAtRuntime()) { |
| 4564 | 4542 | try writer.writeByte('('); |
| 4565 | | try f.renderTypecast(writer, Type.usize); |
| 4543 | try f.renderType(writer, Type.usize); |
| 4566 | 4544 | try writer.writeByte(')'); |
| 4567 | 4545 | } |
| 4568 | 4546 | try f.writeCValue(writer, condition, .Other); |
| ... | ... | @@ -4591,7 +4569,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4591 | 4569 | try writer.writeAll("case "); |
| 4592 | 4570 | if (condition_ty.isPtrAtRuntime()) { |
| 4593 | 4571 | try writer.writeByte('('); |
| 4594 | | try f.renderTypecast(writer, Type.usize); |
| 4572 | try f.renderType(writer, Type.usize); |
| 4595 | 4573 | try writer.writeByte(')'); |
| 4596 | 4574 | } |
| 4597 | 4575 | try f.object.dg.renderValue(writer, condition_ty, f.air.value(item).?, .Other); |
| ... | ... | @@ -5043,7 +5021,7 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5043 | 5021 | try f.writeCValueMember(writer, operand, .{ .identifier = "payload" }); |
| 5044 | 5022 | if (is_array) { |
| 5045 | 5023 | try writer.writeAll(", sizeof("); |
| 5046 | | try f.renderTypecast(writer, inst_ty); |
| 5024 | try f.renderType(writer, inst_ty); |
| 5047 | 5025 | try writer.writeAll("))"); |
| 5048 | 5026 | } |
| 5049 | 5027 | try writer.writeAll(";\n"); |
| ... | ... | @@ -5127,6 +5105,62 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5127 | 5105 | } |
| 5128 | 5106 | } |
| 5129 | 5107 | |
| 5108 | fn fieldLocation( |
| 5109 | container_ty: Type, |
| 5110 | field_ptr_ty: Type, |
| 5111 | field_index: u32, |
| 5112 | target: std.Target, |
| 5113 | ) union(enum) { |
| 5114 | begin: void, |
| 5115 | field: CValue, |
| 5116 | byte_offset: u32, |
| 5117 | end: void, |
| 5118 | } { |
| 5119 | return switch (container_ty.zigTypeTag()) { |
| 5120 | .Struct => switch (container_ty.containerLayout()) { |
| 5121 | .Auto, .Extern => for (field_index..container_ty.structFieldCount()) |next_field_index| { |
| 5122 | if (container_ty.structFieldIsComptime(next_field_index)) continue; |
| 5123 | const field_ty = container_ty.structFieldType(next_field_index); |
| 5124 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue; |
| 5125 | break .{ .field = if (container_ty.isSimpleTuple()) |
| 5126 | .{ .field = next_field_index } |
| 5127 | else |
| 5128 | .{ .identifier = container_ty.structFieldName(next_field_index) } }; |
| 5129 | } else if (container_ty.hasRuntimeBitsIgnoreComptime()) .end else .begin, |
| 5130 | .Packed => if (field_ptr_ty.ptrInfo().data.host_size == 0) |
| 5131 | .{ .byte_offset = container_ty.packedStructFieldByteOffset(field_index, target) } |
| 5132 | else |
| 5133 | .begin, |
| 5134 | }, |
| 5135 | .Union => switch (container_ty.containerLayout()) { |
| 5136 | .Auto, .Extern => { |
| 5137 | const field_ty = container_ty.structFieldType(field_index); |
| 5138 | if (!field_ty.hasRuntimeBitsIgnoreComptime()) |
| 5139 | return if (container_ty.unionTagTypeSafety() != null and |
| 5140 | !container_ty.unionHasAllZeroBitFieldTypes()) |
| 5141 | .{ .field = .{ .identifier = "payload" } } |
| 5142 | else |
| 5143 | .begin; |
| 5144 | const field_name = container_ty.unionFields().keys()[field_index]; |
| 5145 | return .{ .field = if (container_ty.unionTagTypeSafety()) |_| |
| 5146 | .{ .payload_identifier = field_name } |
| 5147 | else |
| 5148 | .{ .identifier = field_name } }; |
| 5149 | }, |
| 5150 | .Packed => .begin, |
| 5151 | }, |
| 5152 | .Pointer => switch (container_ty.ptrSize()) { |
| 5153 | .Slice => switch (field_index) { |
| 5154 | 0 => .{ .field = .{ .identifier = "ptr" } }, |
| 5155 | 1 => .{ .field = .{ .identifier = "len" } }, |
| 5156 | else => unreachable, |
| 5157 | }, |
| 5158 | .One, .Many, .C => unreachable, |
| 5159 | }, |
| 5160 | else => unreachable, |
| 5161 | }; |
| 5162 | } |
| 5163 | |
| 5130 | 5164 | fn airStructFieldPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5131 | 5165 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 5132 | 5166 | const extra = f.air.extraData(Air.StructField, ty_pl.payload).data; |
| ... | ... | @@ -5136,10 +5170,10 @@ fn airStructFieldPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5136 | 5170 | return .none; |
| 5137 | 5171 | } |
| 5138 | 5172 | |
| 5139 | | const struct_ptr = try f.resolveInst(extra.struct_operand); |
| 5173 | const container_ptr_val = try f.resolveInst(extra.struct_operand); |
| 5140 | 5174 | try reap(f, inst, &.{extra.struct_operand}); |
| 5141 | | const struct_ptr_ty = f.air.typeOf(extra.struct_operand); |
| 5142 | | return structFieldPtr(f, inst, struct_ptr_ty, struct_ptr, extra.field_index); |
| 5175 | const container_ptr_ty = f.air.typeOf(extra.struct_operand); |
| 5176 | return fieldPtr(f, inst, container_ptr_ty, container_ptr_val, extra.field_index); |
| 5143 | 5177 | } |
| 5144 | 5178 | |
| 5145 | 5179 | fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue { |
| ... | ... | @@ -5150,10 +5184,10 @@ fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue |
| 5150 | 5184 | return .none; |
| 5151 | 5185 | } |
| 5152 | 5186 | |
| 5153 | | const struct_ptr = try f.resolveInst(ty_op.operand); |
| 5187 | const container_ptr_val = try f.resolveInst(ty_op.operand); |
| 5154 | 5188 | try reap(f, inst, &.{ty_op.operand}); |
| 5155 | | const struct_ptr_ty = f.air.typeOf(ty_op.operand); |
| 5156 | | return structFieldPtr(f, inst, struct_ptr_ty, struct_ptr, index); |
| 5189 | const container_ptr_ty = f.air.typeOf(ty_op.operand); |
| 5190 | return fieldPtr(f, inst, container_ptr_ty, container_ptr_val, index); |
| 5157 | 5191 | } |
| 5158 | 5192 | |
| 5159 | 5193 | fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| ... | ... | @@ -5165,130 +5199,115 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5165 | 5199 | return CValue.none; |
| 5166 | 5200 | } |
| 5167 | 5201 | |
| 5168 | | const struct_ptr_ty = f.air.typeOfIndex(inst); |
| 5202 | const target = f.object.dg.module.getTarget(); |
| 5203 | const container_ptr_ty = f.air.typeOfIndex(inst); |
| 5204 | const container_ty = container_ptr_ty.childType(); |
| 5169 | 5205 | |
| 5170 | 5206 | const field_ptr_ty = f.air.typeOf(extra.field_ptr); |
| 5171 | 5207 | const field_ptr_val = try f.resolveInst(extra.field_ptr); |
| 5172 | 5208 | try reap(f, inst, &.{extra.field_ptr}); |
| 5173 | 5209 | |
| 5174 | | const target = f.object.dg.module.getTarget(); |
| 5175 | | const struct_ty = struct_ptr_ty.childType(); |
| 5210 | const writer = f.object.writer(); |
| 5211 | const local = try f.allocLocal(inst, container_ptr_ty); |
| 5212 | try f.writeCValue(writer, local, .Other); |
| 5213 | try writer.writeAll(" = ("); |
| 5214 | try f.renderType(writer, container_ptr_ty); |
| 5215 | try writer.writeByte(')'); |
| 5176 | 5216 | |
| 5177 | | if (struct_ty.zigTypeTag() == .Union) { |
| 5178 | | return f.fail("TODO: CBE: @fieldParentPtr for unions", .{}); |
| 5179 | | } |
| 5217 | switch (fieldLocation(container_ty, field_ptr_ty, extra.field_index, target)) { |
| 5218 | .begin => try f.writeCValue(writer, field_ptr_val, .Initializer), |
| 5219 | .field => |field| { |
| 5220 | var u8_ptr_pl = field_ptr_ty.ptrInfo(); |
| 5221 | u8_ptr_pl.data.pointee_type = Type.u8; |
| 5222 | const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base); |
| 5180 | 5223 | |
| 5181 | | const field_offset = struct_ty.structFieldOffset(extra.field_index, target); |
| 5224 | try writer.writeAll("(("); |
| 5225 | try f.renderType(writer, u8_ptr_ty); |
| 5226 | try writer.writeByte(')'); |
| 5227 | try f.writeCValue(writer, field_ptr_val, .Other); |
| 5228 | try writer.writeAll(" - offsetof("); |
| 5229 | try f.renderType(writer, container_ty); |
| 5230 | try writer.writeAll(", "); |
| 5231 | try f.writeCValue(writer, field, .Other); |
| 5232 | try writer.writeAll("))"); |
| 5233 | }, |
| 5234 | .byte_offset => |byte_offset| { |
| 5235 | var u8_ptr_pl = field_ptr_ty.ptrInfo(); |
| 5236 | u8_ptr_pl.data.pointee_type = Type.u8; |
| 5237 | const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base); |
| 5182 | 5238 | |
| 5183 | | var field_offset_pl = Value.Payload.I64{ |
| 5184 | | .base = .{ .tag = .int_i64 }, |
| 5185 | | .data = -@intCast(i64, field_offset), |
| 5186 | | }; |
| 5187 | | const field_offset_val = Value.initPayload(&field_offset_pl.base); |
| 5239 | var byte_offset_pl = Value.Payload.U64{ |
| 5240 | .base = .{ .tag = .int_u64 }, |
| 5241 | .data = byte_offset, |
| 5242 | }; |
| 5243 | const byte_offset_val = Value.initPayload(&byte_offset_pl.base); |
| 5188 | 5244 | |
| 5189 | | var u8_ptr_pl = field_ptr_ty.ptrInfo(); |
| 5190 | | u8_ptr_pl.data.pointee_type = Type.u8; |
| 5191 | | const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base); |
| 5245 | try writer.writeAll("(("); |
| 5246 | try f.renderType(writer, u8_ptr_ty); |
| 5247 | try writer.writeByte(')'); |
| 5248 | try f.writeCValue(writer, field_ptr_val, .Other); |
| 5249 | try writer.print(" - {})", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)}); |
| 5250 | }, |
| 5251 | .end => { |
| 5252 | try f.writeCValue(writer, field_ptr_val, .Other); |
| 5253 | try writer.print(" - {}", .{try f.fmtIntLiteral(Type.usize, Value.one)}); |
| 5254 | }, |
| 5255 | } |
| 5192 | 5256 | |
| 5193 | | const writer = f.object.writer(); |
| 5194 | | const local = try f.allocLocal(inst, struct_ptr_ty); |
| 5195 | | try f.writeCValue(writer, local, .Other); |
| 5196 | | try writer.writeAll(" = ("); |
| 5197 | | try f.renderTypecast(writer, struct_ptr_ty); |
| 5198 | | try writer.writeAll(")&(("); |
| 5199 | | try f.renderTypecast(writer, u8_ptr_ty); |
| 5200 | | try writer.writeByte(')'); |
| 5201 | | try f.writeCValue(writer, field_ptr_val, .Other); |
| 5202 | | try writer.print(")[{}];\n", .{try f.fmtIntLiteral(Type.isize, field_offset_val)}); |
| 5257 | try writer.writeAll(";\n"); |
| 5203 | 5258 | return local; |
| 5204 | 5259 | } |
| 5205 | 5260 | |
| 5206 | | fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struct_ptr: CValue, index: u32) !CValue { |
| 5207 | | const writer = f.object.writer(); |
| 5261 | fn fieldPtr( |
| 5262 | f: *Function, |
| 5263 | inst: Air.Inst.Index, |
| 5264 | container_ptr_ty: Type, |
| 5265 | container_ptr_val: CValue, |
| 5266 | field_index: u32, |
| 5267 | ) !CValue { |
| 5268 | const target = f.object.dg.module.getTarget(); |
| 5269 | const container_ty = container_ptr_ty.elemType(); |
| 5208 | 5270 | const field_ptr_ty = f.air.typeOfIndex(inst); |
| 5209 | | const field_ptr_info = field_ptr_ty.ptrInfo(); |
| 5210 | | const struct_ty = struct_ptr_ty.elemType(); |
| 5211 | | const field_ty = struct_ty.structFieldType(index); |
| 5212 | 5271 | |
| 5213 | 5272 | // Ensure complete type definition is visible before accessing fields. |
| 5214 | | try f.renderType(std.io.null_writer, struct_ty); |
| 5273 | _ = try f.typeToIndex(container_ty, .complete); |
| 5215 | 5274 | |
| 5275 | const writer = f.object.writer(); |
| 5216 | 5276 | const local = try f.allocLocal(inst, field_ptr_ty); |
| 5217 | 5277 | try f.writeCValue(writer, local, .Other); |
| 5218 | 5278 | try writer.writeAll(" = ("); |
| 5219 | | try f.renderTypecast(writer, field_ptr_ty); |
| 5279 | try f.renderType(writer, field_ptr_ty); |
| 5220 | 5280 | try writer.writeByte(')'); |
| 5221 | 5281 | |
| 5222 | | const extra_name: CValue = switch (struct_ty.tag()) { |
| 5223 | | .union_tagged, .union_safety_tagged => .{ .identifier = "payload" }, |
| 5224 | | else => .none, |
| 5225 | | }; |
| 5226 | | |
| 5227 | | const field_loc: union(enum) { |
| 5228 | | begin: void, |
| 5229 | | field: CValue, |
| 5230 | | end: void, |
| 5231 | | } = switch (struct_ty.tag()) { |
| 5232 | | .tuple, .anon_struct, .@"struct" => switch (struct_ty.containerLayout()) { |
| 5233 | | .Auto, .Extern => for (index..struct_ty.structFieldCount()) |field_i| { |
| 5234 | | if (!struct_ty.structFieldIsComptime(field_i) and |
| 5235 | | struct_ty.structFieldType(field_i).hasRuntimeBitsIgnoreComptime()) |
| 5236 | | break .{ .field = if (struct_ty.isSimpleTuple()) |
| 5237 | | .{ .field = field_i } |
| 5238 | | else |
| 5239 | | .{ .identifier = struct_ty.structFieldName(field_i) } }; |
| 5240 | | } else .end, |
| 5241 | | .Packed => if (field_ptr_info.data.host_size == 0) { |
| 5242 | | const target = f.object.dg.module.getTarget(); |
| 5243 | | |
| 5244 | | const byte_offset = struct_ty.packedStructFieldByteOffset(index, target); |
| 5245 | | var byte_offset_pl = Value.Payload.U64{ |
| 5246 | | .base = .{ .tag = .int_u64 }, |
| 5247 | | .data = byte_offset, |
| 5248 | | }; |
| 5249 | | const byte_offset_val = Value.initPayload(&byte_offset_pl.base); |
| 5250 | | |
| 5251 | | var u8_ptr_pl = field_ptr_info; |
| 5252 | | u8_ptr_pl.data.pointee_type = Type.u8; |
| 5253 | | const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base); |
| 5282 | switch (fieldLocation(container_ty, field_ptr_ty, field_index, target)) { |
| 5283 | .begin => try f.writeCValue(writer, container_ptr_val, .Initializer), |
| 5284 | .field => |field| { |
| 5285 | try writer.writeByte('&'); |
| 5286 | try f.writeCValueDerefMember(writer, container_ptr_val, field); |
| 5287 | }, |
| 5288 | .byte_offset => |byte_offset| { |
| 5289 | var u8_ptr_pl = field_ptr_ty.ptrInfo(); |
| 5290 | u8_ptr_pl.data.pointee_type = Type.u8; |
| 5291 | const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base); |
| 5254 | 5292 | |
| 5255 | | if (!std.mem.isAligned(byte_offset, field_ptr_ty.ptrAlignment(target))) { |
| 5256 | | return f.fail("TODO: CBE: unaligned packed struct field pointer", .{}); |
| 5257 | | } |
| 5293 | var byte_offset_pl = Value.Payload.U64{ |
| 5294 | .base = .{ .tag = .int_u64 }, |
| 5295 | .data = byte_offset, |
| 5296 | }; |
| 5297 | const byte_offset_val = Value.initPayload(&byte_offset_pl.base); |
| 5258 | 5298 | |
| 5259 | | try writer.writeAll("&(("); |
| 5260 | | try f.renderTypecast(writer, u8_ptr_ty); |
| 5261 | | try writer.writeByte(')'); |
| 5262 | | try f.writeCValue(writer, struct_ptr, .Other); |
| 5263 | | try writer.print(")[{}];\n", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)}); |
| 5264 | | return local; |
| 5265 | | } else .begin, |
| 5299 | try writer.writeAll("(("); |
| 5300 | try f.renderType(writer, u8_ptr_ty); |
| 5301 | try writer.writeByte(')'); |
| 5302 | try f.writeCValue(writer, container_ptr_val, .Other); |
| 5303 | try writer.print(" + {})", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)}); |
| 5266 | 5304 | }, |
| 5267 | | .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) { |
| 5268 | | try f.writeCValue(writer, struct_ptr, .Other); |
| 5269 | | try writer.writeAll(";\n"); |
| 5270 | | return local; |
| 5271 | | } else if (field_ty.hasRuntimeBitsIgnoreComptime()) .{ .field = .{ |
| 5272 | | .identifier = struct_ty.unionFields().keys()[index], |
| 5273 | | } } else .end, |
| 5274 | | else => unreachable, |
| 5275 | | }; |
| 5305 | .end => { |
| 5306 | try f.writeCValue(writer, container_ptr_val, .Other); |
| 5307 | try writer.print(" + {}", .{try f.fmtIntLiteral(Type.usize, Value.one)}); |
| 5308 | }, |
| 5309 | } |
| 5276 | 5310 | |
| 5277 | | if (struct_ty.hasRuntimeBitsIgnoreComptime()) { |
| 5278 | | try writer.writeByte('&'); |
| 5279 | | switch (field_loc) { |
| 5280 | | .begin, .end => { |
| 5281 | | try writer.writeByte('('); |
| 5282 | | try f.writeCValue(writer, struct_ptr, .Other); |
| 5283 | | try writer.print(")[{}]", .{@boolToInt(field_loc == .end)}); |
| 5284 | | }, |
| 5285 | | .field => |field| if (extra_name != .none) { |
| 5286 | | try f.writeCValueDerefMember(writer, struct_ptr, extra_name); |
| 5287 | | try writer.writeByte('.'); |
| 5288 | | try f.writeCValue(writer, field, .Other); |
| 5289 | | } else try f.writeCValueDerefMember(writer, struct_ptr, field), |
| 5290 | | } |
| 5291 | | } else try f.writeCValue(writer, struct_ptr, .Other); |
| 5292 | 5311 | try writer.writeAll(";\n"); |
| 5293 | 5312 | return local; |
| 5294 | 5313 | } |
| ... | ... | @@ -5315,7 +5334,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5315 | 5334 | const writer = f.object.writer(); |
| 5316 | 5335 | |
| 5317 | 5336 | // Ensure complete type definition is visible before accessing fields. |
| 5318 | | try f.renderType(std.io.null_writer, struct_ty); |
| 5337 | _ = try f.typeToIndex(struct_ty, .complete); |
| 5319 | 5338 | |
| 5320 | 5339 | const extra_name: CValue = switch (struct_ty.tag()) { |
| 5321 | 5340 | .union_tagged, .union_safety_tagged => .{ .identifier = "payload" }, |
| ... | ... | @@ -5362,7 +5381,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5362 | 5381 | try writer.writeAll(" = zig_wrap_"); |
| 5363 | 5382 | try f.object.dg.renderTypeForBuiltinFnName(writer, field_int_ty); |
| 5364 | 5383 | try writer.writeAll("(("); |
| 5365 | | try f.renderTypecast(writer, field_int_ty); |
| 5384 | try f.renderType(writer, field_int_ty); |
| 5366 | 5385 | try writer.writeByte(')'); |
| 5367 | 5386 | const cant_cast = int_info.bits > 64; |
| 5368 | 5387 | if (cant_cast) { |
| ... | ... | @@ -5389,7 +5408,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5389 | 5408 | try writer.writeAll(", "); |
| 5390 | 5409 | try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument); |
| 5391 | 5410 | try writer.writeAll(", sizeof("); |
| 5392 | | try f.renderTypecast(writer, inst_ty); |
| 5411 | try f.renderType(writer, inst_ty); |
| 5393 | 5412 | try writer.writeAll("));\n"); |
| 5394 | 5413 | try freeLocal(f, inst, temp_local.new_local, 0); |
| 5395 | 5414 | return local; |
| ... | ... | @@ -5411,7 +5430,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5411 | 5430 | try writer.writeAll(", &"); |
| 5412 | 5431 | try f.writeCValue(writer, operand_lval, .FunctionArgument); |
| 5413 | 5432 | try writer.writeAll(", sizeof("); |
| 5414 | | try f.renderTypecast(writer, inst_ty); |
| 5433 | try f.renderType(writer, inst_ty); |
| 5415 | 5434 | try writer.writeAll("));\n"); |
| 5416 | 5435 | |
| 5417 | 5436 | if (struct_byval == .constant) { |
| ... | ... | @@ -5442,7 +5461,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5442 | 5461 | } else try f.writeCValueMember(writer, struct_byval, field_name); |
| 5443 | 5462 | if (is_array) { |
| 5444 | 5463 | try writer.writeAll(", sizeof("); |
| 5445 | | try f.renderTypecast(writer, inst_ty); |
| 5464 | try f.renderType(writer, inst_ty); |
| 5446 | 5465 | try writer.writeAll("))"); |
| 5447 | 5466 | } |
| 5448 | 5467 | try writer.writeAll(";\n"); |
| ... | ... | @@ -5510,7 +5529,7 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu |
| 5510 | 5529 | const local = try f.allocLocal(inst, inst_ty); |
| 5511 | 5530 | try f.writeCValue(w, local, .Other); |
| 5512 | 5531 | try w.writeAll(" = ("); |
| 5513 | | try f.renderTypecast(w, inst_ty); |
| 5532 | try f.renderType(w, inst_ty); |
| 5514 | 5533 | try w.writeByte(')'); |
| 5515 | 5534 | try f.writeCValue(w, operand, .Initializer); |
| 5516 | 5535 | try w.writeAll(";\n"); |
| ... | ... | @@ -5571,7 +5590,7 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5571 | 5590 | try writer.writeAll(", "); |
| 5572 | 5591 | try f.writeCValue(writer, payload, .FunctionArgument); |
| 5573 | 5592 | try writer.writeAll(", sizeof("); |
| 5574 | | try f.renderTypecast(writer, payload_ty); |
| 5593 | try f.renderType(writer, payload_ty); |
| 5575 | 5594 | try writer.writeAll("));\n"); |
| 5576 | 5595 | } |
| 5577 | 5596 | return local; |
| ... | ... | @@ -5691,7 +5710,7 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5691 | 5710 | try writer.writeAll(", "); |
| 5692 | 5711 | try f.writeCValue(writer, payload, .FunctionArgument); |
| 5693 | 5712 | try writer.writeAll(", sizeof("); |
| 5694 | | try f.renderTypecast(writer, payload_ty); |
| 5713 | try f.renderType(writer, payload_ty); |
| 5695 | 5714 | try writer.writeAll("));\n"); |
| 5696 | 5715 | } |
| 5697 | 5716 | return local; |
| ... | ... | @@ -5837,7 +5856,7 @@ fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5837 | 5856 | try f.writeCValue(writer, local, .Other); |
| 5838 | 5857 | |
| 5839 | 5858 | try writer.writeAll(" = ("); |
| 5840 | | try f.renderTypecast(writer, inst_ty); |
| 5859 | try f.renderType(writer, inst_ty); |
| 5841 | 5860 | try writer.writeByte(')'); |
| 5842 | 5861 | try f.writeCValue(writer, operand, .Other); |
| 5843 | 5862 | try writer.writeAll(";\n"); |
| ... | ... | @@ -5959,7 +5978,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 5959 | 5978 | try writer.writeAll(";\n"); |
| 5960 | 5979 | try writer.writeAll("if ("); |
| 5961 | 5980 | try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor}); |
| 5962 | | try f.renderTypecast(writer, ptr_ty.childType()); |
| 5981 | try f.renderType(writer, ptr_ty.childType()); |
| 5963 | 5982 | try writer.writeByte(')'); |
| 5964 | 5983 | if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); |
| 5965 | 5984 | try writer.writeAll(" *)"); |
| ... | ... | @@ -5988,7 +6007,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue |
| 5988 | 6007 | try writer.writeAll(";\n"); |
| 5989 | 6008 | try f.writeCValue(writer, local, .Other); |
| 5990 | 6009 | try writer.print(".is_null = zig_cmpxchg_{s}((zig_atomic(", .{flavor}); |
| 5991 | | try f.renderTypecast(writer, ptr_ty.childType()); |
| 6010 | try f.renderType(writer, ptr_ty.childType()); |
| 5992 | 6011 | try writer.writeByte(')'); |
| 5993 | 6012 | if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); |
| 5994 | 6013 | try writer.writeAll(" *)"); |
| ... | ... | @@ -6031,12 +6050,12 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6031 | 6050 | switch (extra.op()) { |
| 6032 | 6051 | else => { |
| 6033 | 6052 | try writer.writeAll("zig_atomic("); |
| 6034 | | try f.renderTypecast(writer, ptr_ty.elemType()); |
| 6053 | try f.renderType(writer, ptr_ty.elemType()); |
| 6035 | 6054 | try writer.writeByte(')'); |
| 6036 | 6055 | }, |
| 6037 | 6056 | .Nand, .Min, .Max => { |
| 6038 | 6057 | // These are missing from stdatomic.h, so no atomic types for now. |
| 6039 | | try f.renderTypecast(writer, ptr_ty.elemType()); |
| 6058 | try f.renderType(writer, ptr_ty.elemType()); |
| 6040 | 6059 | }, |
| 6041 | 6060 | } |
| 6042 | 6061 | if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); |
| ... | ... | @@ -6073,7 +6092,7 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6073 | 6092 | try f.writeCValue(writer, local, .Other); |
| 6074 | 6093 | |
| 6075 | 6094 | try writer.writeAll(" = zig_atomic_load((zig_atomic("); |
| 6076 | | try f.renderTypecast(writer, ptr_ty.elemType()); |
| 6095 | try f.renderType(writer, ptr_ty.elemType()); |
| 6077 | 6096 | try writer.writeByte(')'); |
| 6078 | 6097 | if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); |
| 6079 | 6098 | try writer.writeAll(" *)"); |
| ... | ... | @@ -6096,7 +6115,7 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa |
| 6096 | 6115 | const writer = f.object.writer(); |
| 6097 | 6116 | |
| 6098 | 6117 | try writer.writeAll("zig_atomic_store((zig_atomic("); |
| 6099 | | try f.renderTypecast(writer, ptr_ty.elemType()); |
| 6118 | try f.renderType(writer, ptr_ty.elemType()); |
| 6100 | 6119 | try writer.writeByte(')'); |
| 6101 | 6120 | if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile"); |
| 6102 | 6121 | try writer.writeAll(" *)"); |
| ... | ... | @@ -6138,7 +6157,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6138 | 6157 | try writer.writeAll(" += "); |
| 6139 | 6158 | try f.object.dg.renderValue(writer, Type.usize, Value.one, .Other); |
| 6140 | 6159 | try writer.writeAll(") (("); |
| 6141 | | try f.renderTypecast(writer, u8_ptr_ty); |
| 6160 | try f.renderType(writer, u8_ptr_ty); |
| 6142 | 6161 | try writer.writeByte(')'); |
| 6143 | 6162 | try f.writeCValue(writer, dest_ptr, .FunctionArgument); |
| 6144 | 6163 | try writer.writeAll(")["); |
| ... | ... | @@ -6514,7 +6533,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6514 | 6533 | .Auto, .Extern => { |
| 6515 | 6534 | try f.writeCValue(writer, local, .Other); |
| 6516 | 6535 | try writer.writeAll(" = ("); |
| 6517 | | try f.renderTypecast(writer, inst_ty); |
| 6536 | try f.renderType(writer, inst_ty); |
| 6518 | 6537 | try writer.writeAll(")"); |
| 6519 | 6538 | try writer.writeByte('{'); |
| 6520 | 6539 | var empty = true; |
| ... | ... | @@ -6557,7 +6576,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6557 | 6576 | try writer.writeAll(", "); |
| 6558 | 6577 | try f.writeCValue(writer, resolved_element, .FunctionArgument); |
| 6559 | 6578 | try writer.writeAll(", sizeof("); |
| 6560 | | try f.renderTypecast(writer, element_ty); |
| 6579 | try f.renderType(writer, element_ty); |
| 6561 | 6580 | try writer.writeAll("));\n"); |
| 6562 | 6581 | } |
| 6563 | 6582 | }, |
| ... | ... | @@ -6602,11 +6621,11 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6602 | 6621 | try f.renderIntCast(writer, inst_ty, element, field_ty, .FunctionArgument); |
| 6603 | 6622 | } else { |
| 6604 | 6623 | try writer.writeByte('('); |
| 6605 | | try f.renderTypecast(writer, inst_ty); |
| 6624 | try f.renderType(writer, inst_ty); |
| 6606 | 6625 | try writer.writeByte(')'); |
| 6607 | 6626 | if (field_ty.isPtrAtRuntime()) { |
| 6608 | 6627 | try writer.writeByte('('); |
| 6609 | | try f.renderTypecast(writer, switch (int_info.signedness) { |
| 6628 | try f.renderType(writer, switch (int_info.signedness) { |
| 6610 | 6629 | .unsigned => Type.usize, |
| 6611 | 6630 | .signed => Type.isize, |
| 6612 | 6631 | }); |