authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-02-22 23:31:41-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-02-23 00:29:23-05:00
logbdb1e014a085fdd872886dddc66cfe1081887e5c
tree78a17c0c3280910a26fc8758c9be75d837930c89
parentc9e02d3e69f909a6eb215286c6109f2b3f1e68a2

CBE: cleanup field access

* Implement @fieldParentPtr on a union * Refactor field access to ensure that it is handled consistently * Remove `renderTypecast` as it is now behaves the same as `renderType`

3 files changed, 314 insertions(+), 299 deletions(-)

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