| ... | @@ -3801,6 +3801,24 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3801,6 +3801,24 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3801 | }); | 3801 | }); |
| 3802 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); | 3802 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); |
| 3803 | try f.allocs.put(zcu.gpa, local.new_local, true); | 3803 | try f.allocs.put(zcu.gpa, local.new_local, true); |
| | 3804 | |
| | 3805 | switch (elem_ty.zigTypeTag(zcu)) { |
| | 3806 | .@"struct", .@"union" => switch (elem_ty.containerLayout(zcu)) { |
| | 3807 | .@"packed" => { |
| | 3808 | // For packed aggregates, we zero-initialize to try and work around a design flaw |
| | 3809 | // related to how `packed`, `undefined`, and RLS interact. See comment in `airStore` |
| | 3810 | // for details. |
| | 3811 | const w = &f.object.code.writer; |
| | 3812 | try w.print("memset(&t{d}, 0x00, sizeof(", .{local.new_local}); |
| | 3813 | try f.renderType(w, elem_ty); |
| | 3814 | try w.writeAll("));"); |
| | 3815 | try f.object.newline(); |
| | 3816 | }, |
| | 3817 | .auto, .@"extern" => {}, |
| | 3818 | }, |
| | 3819 | else => {}, |
| | 3820 | } |
| | 3821 | |
| 3804 | return .{ .local_ref = local.new_local }; | 3822 | return .{ .local_ref = local.new_local }; |
| 3805 | } | 3823 | } |
| 3806 | | 3824 | |
| ... | @@ -3820,6 +3838,24 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3820,6 +3838,24 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3820 | }); | 3838 | }); |
| 3821 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); | 3839 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); |
| 3822 | try f.allocs.put(zcu.gpa, local.new_local, true); | 3840 | try f.allocs.put(zcu.gpa, local.new_local, true); |
| | 3841 | |
| | 3842 | switch (elem_ty.zigTypeTag(zcu)) { |
| | 3843 | .@"struct", .@"union" => switch (elem_ty.containerLayout(zcu)) { |
| | 3844 | .@"packed" => { |
| | 3845 | // For packed aggregates, we zero-initialize to try and work around a design flaw |
| | 3846 | // related to how `packed`, `undefined`, and RLS interact. See comment in `airStore` |
| | 3847 | // for details. |
| | 3848 | const w = &f.object.code.writer; |
| | 3849 | try w.print("memset(&t{d}, 0x00, sizeof(", .{local.new_local}); |
| | 3850 | try f.renderType(w, elem_ty); |
| | 3851 | try w.writeAll("));"); |
| | 3852 | try f.object.newline(); |
| | 3853 | }, |
| | 3854 | .auto, .@"extern" => {}, |
| | 3855 | }, |
| | 3856 | else => {}, |
| | 3857 | } |
| | 3858 | |
| 3823 | return .{ .local_ref = local.new_local }; | 3859 | return .{ .local_ref = local.new_local }; |
| 3824 | } | 3860 | } |
| 3825 | | 3861 | |
| ... | @@ -4098,9 +4134,24 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -4098,9 +4134,24 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 4098 | if (val_is_undef) { | 4134 | if (val_is_undef) { |
| 4099 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | 4135 | try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); |
| 4100 | if (safety and ptr_info.packed_offset.host_size == 0) { | 4136 | if (safety and ptr_info.packed_offset.host_size == 0) { |
| | 4137 | // If the thing we're initializing is a packed struct/union, we set to 0 instead of |
| | 4138 | // 0xAA. This is a hack to work around a problem with partially-undefined packed |
| | 4139 | // aggregates. If we used 0xAA here, then a later initialization through RLS would |
| | 4140 | // not zero the high padding bits (for a packed type which is not 8/16/32/64/etc bits), |
| | 4141 | // so we would get a miscompilation. Using 0x00 here avoids this bug in some cases. It |
| | 4142 | // is *not* a correct fix; for instance it misses any case where packed structs are |
| | 4143 | // nested in other aggregates. A proper fix for this will involve changing the language, |
| | 4144 | // such as to remove RLS. This just prevents miscompilations in *some* common cases. |
| | 4145 | const byte_str: []const u8 = switch (src_ty.zigTypeTag(zcu)) { |
| | 4146 | else => "0xaa", |
| | 4147 | .@"struct", .@"union" => switch (src_ty.containerLayout(zcu)) { |
| | 4148 | .auto, .@"extern" => "0xaa", |
| | 4149 | .@"packed" => "0x00", |
| | 4150 | }, |
| | 4151 | }; |
| 4101 | try w.writeAll("memset("); | 4152 | try w.writeAll("memset("); |
| 4102 | try f.writeCValue(w, ptr_val, .FunctionArgument); | 4153 | try f.writeCValue(w, ptr_val, .FunctionArgument); |
| 4103 | try w.writeAll(", 0xaa, sizeof("); | 4154 | try w.print(", {s}, sizeof(", .{byte_str}); |
| 4104 | try f.renderType(w, .fromInterned(ptr_info.child)); | 4155 | try f.renderType(w, .fromInterned(ptr_info.child)); |
| 4105 | try w.writeAll("));"); | 4156 | try w.writeAll("));"); |
| 4106 | try f.object.newline(); | 4157 | try f.object.newline(); |