| ... | @@ -1024,6 +1024,11 @@ const NavGen = struct { | ... | @@ -1024,6 +1024,11 @@ const NavGen = struct { |
| 1024 | else => unreachable, | 1024 | else => unreachable, |
| 1025 | }, | 1025 | }, |
| 1026 | .un => |un| { | 1026 | .un => |un| { |
| | 1027 | if (un.tag == .none) { |
| | 1028 | assert(ty.containerLayout(zcu) == .@"packed"); // TODO |
| | 1029 | const int_ty = try pt.intType(.unsigned, @intCast(ty.bitSize(zcu))); |
| | 1030 | return try self.constant(int_ty, Value.fromInterned(un.val), .direct); |
| | 1031 | } |
| 1027 | const active_field = ty.unionTagFieldIndex(Value.fromInterned(un.tag), zcu).?; | 1032 | const active_field = ty.unionTagFieldIndex(Value.fromInterned(un.tag), zcu).?; |
| 1028 | const union_obj = zcu.typeToUnion(ty).?; | 1033 | const union_obj = zcu.typeToUnion(ty).?; |
| 1029 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[active_field]); | 1034 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[active_field]); |
| ... | @@ -1356,7 +1361,7 @@ const NavGen = struct { | ... | @@ -1356,7 +1361,7 @@ const NavGen = struct { |
| 1356 | const union_obj = zcu.typeToUnion(ty).?; | 1361 | const union_obj = zcu.typeToUnion(ty).?; |
| 1357 | | 1362 | |
| 1358 | if (union_obj.flagsUnordered(ip).layout == .@"packed") { | 1363 | if (union_obj.flagsUnordered(ip).layout == .@"packed") { |
| 1359 | return self.todo("packed union types", .{}); | 1364 | return try self.intType(.unsigned, @intCast(ty.bitSize(zcu))); |
| 1360 | } | 1365 | } |
| 1361 | | 1366 | |
| 1362 | const layout = self.unionLayout(ty); | 1367 | const layout = self.unionLayout(ty); |
| ... | @@ -3226,10 +3231,13 @@ const NavGen = struct { | ... | @@ -3226,10 +3231,13 @@ const NavGen = struct { |
| 3226 | }; | 3231 | }; |
| 3227 | | 3232 | |
| 3228 | fn load(self: *NavGen, value_ty: Type, ptr_id: IdRef, options: MemoryOptions) !IdRef { | 3233 | fn load(self: *NavGen, value_ty: Type, ptr_id: IdRef, options: MemoryOptions) !IdRef { |
| | 3234 | const zcu = self.pt.zcu; |
| | 3235 | const alignment: u32 = @intCast(value_ty.abiAlignment(zcu).toByteUnits().?); |
| 3229 | const indirect_value_ty_id = try self.resolveType(value_ty, .indirect); | 3236 | const indirect_value_ty_id = try self.resolveType(value_ty, .indirect); |
| 3230 | const result_id = self.spv.allocId(); | 3237 | const result_id = self.spv.allocId(); |
| 3231 | const access = spec.MemoryAccess.Extended{ | 3238 | const access = spec.MemoryAccess.Extended{ |
| 3232 | .Volatile = options.is_volatile, | 3239 | .Volatile = options.is_volatile, |
| | 3240 | .Aligned = .{ .literal_integer = alignment }, |
| 3233 | }; | 3241 | }; |
| 3234 | try self.func.body.emit(self.spv.gpa, .OpLoad, .{ | 3242 | try self.func.body.emit(self.spv.gpa, .OpLoad, .{ |
| 3235 | .id_result_type = indirect_value_ty_id, | 3243 | .id_result_type = indirect_value_ty_id, |
| ... | @@ -5130,11 +5138,33 @@ const NavGen = struct { | ... | @@ -5130,11 +5138,33 @@ const NavGen = struct { |
| 5130 | const union_ty = zcu.typeToUnion(ty).?; | 5138 | const union_ty = zcu.typeToUnion(ty).?; |
| 5131 | const tag_ty = Type.fromInterned(union_ty.enum_tag_ty); | 5139 | const tag_ty = Type.fromInterned(union_ty.enum_tag_ty); |
| 5132 | | 5140 | |
| | 5141 | const layout = self.unionLayout(ty); |
| | 5142 | const payload_ty = Type.fromInterned(union_ty.field_types.get(ip)[active_field]); |
| | 5143 | |
| 5133 | if (union_ty.flagsUnordered(ip).layout == .@"packed") { | 5144 | if (union_ty.flagsUnordered(ip).layout == .@"packed") { |
| 5134 | unreachable; // TODO | 5145 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 5135 | } | 5146 | const int_ty = try pt.intType(.unsigned, @intCast(ty.bitSize(zcu))); |
| | 5147 | return self.constInt(int_ty, 0); |
| | 5148 | } |
| 5136 | | 5149 | |
| 5137 | const layout = self.unionLayout(ty); | 5150 | assert(payload != null); |
| | 5151 | if (payload_ty.isInt(zcu)) { |
| | 5152 | if (ty.bitSize(zcu) == payload_ty.bitSize(zcu)) { |
| | 5153 | return self.bitCast(ty, payload_ty, payload.?); |
| | 5154 | } |
| | 5155 | |
| | 5156 | const trunc = try self.buildIntConvert(ty, .{ .ty = payload_ty, .value = .{ .singleton = payload.? } }); |
| | 5157 | return try trunc.materialize(self); |
| | 5158 | } |
| | 5159 | |
| | 5160 | const payload_int_ty = try pt.intType(.unsigned, @intCast(payload_ty.bitSize(zcu))); |
| | 5161 | const payload_int = if (payload_ty.ip_index == .bool_type) |
| | 5162 | try self.convertToIndirect(payload_ty, payload.?) |
| | 5163 | else |
| | 5164 | try self.bitCast(payload_int_ty, payload_ty, payload.?); |
| | 5165 | const trunc = try self.buildIntConvert(ty, .{ .ty = payload_int_ty, .value = .{ .singleton = payload_int } }); |
| | 5166 | return try trunc.materialize(self); |
| | 5167 | } |
| 5138 | | 5168 | |
| 5139 | const tag_int = if (layout.tag_size != 0) blk: { | 5169 | const tag_int = if (layout.tag_size != 0) blk: { |
| 5140 | const tag_val = try pt.enumValueFieldIndex(tag_ty, active_field); | 5170 | const tag_val = try pt.enumValueFieldIndex(tag_ty, active_field); |
| ... | @@ -5155,7 +5185,6 @@ const NavGen = struct { | ... | @@ -5155,7 +5185,6 @@ const NavGen = struct { |
| 5155 | try self.store(tag_ty, ptr_id, tag_id, .{}); | 5185 | try self.store(tag_ty, ptr_id, tag_id, .{}); |
| 5156 | } | 5186 | } |
| 5157 | | 5187 | |
| 5158 | const payload_ty = Type.fromInterned(union_ty.field_types.get(ip)[active_field]); | | |
| 5159 | if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 5188 | if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 5160 | const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, .Function, .indirect); | 5189 | const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, .Function, .indirect); |
| 5161 | const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index}); | 5190 | const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index}); |
| ... | @@ -5198,7 +5227,6 @@ const NavGen = struct { | ... | @@ -5198,7 +5227,6 @@ const NavGen = struct { |
| 5198 | fn airStructFieldVal(self: *NavGen, inst: Air.Inst.Index) !?IdRef { | 5227 | fn airStructFieldVal(self: *NavGen, inst: Air.Inst.Index) !?IdRef { |
| 5199 | const pt = self.pt; | 5228 | const pt = self.pt; |
| 5200 | const zcu = pt.zcu; | 5229 | const zcu = pt.zcu; |
| 5201 | const ip = &zcu.intern_pool; | | |
| 5202 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; | 5230 | const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; |
| 5203 | const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data; | 5231 | const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data; |
| 5204 | | 5232 | |
| ... | @@ -5213,16 +5241,39 @@ const NavGen = struct { | ... | @@ -5213,16 +5241,39 @@ const NavGen = struct { |
| 5213 | .@"struct" => switch (object_ty.containerLayout(zcu)) { | 5241 | .@"struct" => switch (object_ty.containerLayout(zcu)) { |
| 5214 | .@"packed" => { | 5242 | .@"packed" => { |
| 5215 | const struct_ty = zcu.typeToPackedStruct(object_ty).?; | 5243 | const struct_ty = zcu.typeToPackedStruct(object_ty).?; |
| 5216 | const backing_int_ty = Type.fromInterned(struct_ty.backingIntTypeUnordered(ip)); | | |
| 5217 | const bit_offset = pt.structPackedFieldBitOffset(struct_ty, field_index); | 5244 | const bit_offset = pt.structPackedFieldBitOffset(struct_ty, field_index); |
| 5218 | const bit_offset_id = try self.constInt(.u16, bit_offset); | 5245 | const bit_offset_id = try self.constInt(.u16, bit_offset); |
| 5219 | const signedness = if (field_ty.isInt(zcu)) field_ty.intInfo(zcu).signedness else .unsigned; | 5246 | const signedness = if (field_ty.isInt(zcu)) field_ty.intInfo(zcu).signedness else .unsigned; |
| 5220 | const field_bit_size: u16 = @intCast(field_ty.bitSize(zcu)); | 5247 | const field_bit_size: u16 = @intCast(field_ty.bitSize(zcu)); |
| 5221 | const int_ty = try pt.intType(signedness, field_bit_size); | 5248 | const field_int_ty = try pt.intType(signedness, field_bit_size); |
| 5222 | const shift_lhs: Temporary = .{ .ty = backing_int_ty, .value = .{ .singleton = object_id } }; | 5249 | const shift_lhs: Temporary = .{ .ty = object_ty, .value = .{ .singleton = object_id } }; |
| 5223 | const shift = try self.buildBinary(.srl, shift_lhs, .{ .ty = .u16, .value = .{ .singleton = bit_offset_id } }); | 5250 | const shift = try self.buildBinary(.srl, shift_lhs, .{ .ty = .u16, .value = .{ .singleton = bit_offset_id } }); |
| | 5251 | const mask_id = try self.constInt(object_ty, (@as(u64, 1) << @as(u6, @intCast(field_bit_size))) - 1); |
| | 5252 | const masked = try self.buildBinary(.bit_and, shift, .{ .ty = object_ty, .value = .{ .singleton = mask_id } }); |
| | 5253 | const result_id = blk: { |
| | 5254 | if (self.backingIntBits(field_bit_size).? == self.backingIntBits(@intCast(object_ty.bitSize(zcu))).?) |
| | 5255 | break :blk try self.bitCast(field_int_ty, object_ty, try masked.materialize(self)); |
| | 5256 | const trunc = try self.buildIntConvert(field_int_ty, masked); |
| | 5257 | break :blk try trunc.materialize(self); |
| | 5258 | }; |
| | 5259 | if (field_ty.ip_index == .bool_type) return try self.convertToDirect(.bool, result_id); |
| | 5260 | if (field_ty.isInt(zcu)) return result_id; |
| | 5261 | return try self.bitCast(field_ty, field_int_ty, result_id); |
| | 5262 | }, |
| | 5263 | else => return try self.extractField(field_ty, object_id, field_index), |
| | 5264 | }, |
| | 5265 | .@"union" => switch (object_ty.containerLayout(zcu)) { |
| | 5266 | .@"packed" => { |
| | 5267 | const backing_int_ty = try pt.intType(.unsigned, @intCast(object_ty.bitSize(zcu))); |
| | 5268 | const signedness = if (field_ty.isInt(zcu)) field_ty.intInfo(zcu).signedness else .unsigned; |
| | 5269 | const field_bit_size: u16 = @intCast(field_ty.bitSize(zcu)); |
| | 5270 | const int_ty = try pt.intType(signedness, field_bit_size); |
| 5224 | const mask_id = try self.constInt(backing_int_ty, (@as(u64, 1) << @as(u6, @intCast(field_bit_size))) - 1); | 5271 | const mask_id = try self.constInt(backing_int_ty, (@as(u64, 1) << @as(u6, @intCast(field_bit_size))) - 1); |
| 5225 | const masked = try self.buildBinary(.bit_and, shift, .{ .ty = backing_int_ty, .value = .{ .singleton = mask_id } }); | 5272 | const masked = try self.buildBinary( |
| | 5273 | .bit_and, |
| | 5274 | .{ .ty = backing_int_ty, .value = .{ .singleton = object_id } }, |
| | 5275 | .{ .ty = backing_int_ty, .value = .{ .singleton = mask_id } }, |
| | 5276 | ); |
| 5226 | const result_id = blk: { | 5277 | const result_id = blk: { |
| 5227 | if (self.backingIntBits(field_bit_size).? == self.backingIntBits(@intCast(backing_int_ty.bitSize(zcu))).?) | 5278 | if (self.backingIntBits(field_bit_size).? == self.backingIntBits(@intCast(backing_int_ty.bitSize(zcu))).?) |
| 5228 | break :blk try self.bitCast(int_ty, backing_int_ty, try masked.materialize(self)); | 5279 | break :blk try self.bitCast(int_ty, backing_int_ty, try masked.materialize(self)); |
| ... | @@ -5233,10 +5284,6 @@ const NavGen = struct { | ... | @@ -5233,10 +5284,6 @@ const NavGen = struct { |
| 5233 | if (field_ty.isInt(zcu)) return result_id; | 5284 | if (field_ty.isInt(zcu)) return result_id; |
| 5234 | return try self.bitCast(field_ty, int_ty, result_id); | 5285 | return try self.bitCast(field_ty, int_ty, result_id); |
| 5235 | }, | 5286 | }, |
| 5236 | else => return try self.extractField(field_ty, object_id, field_index), | | |
| 5237 | }, | | |
| 5238 | .@"union" => switch (object_ty.containerLayout(zcu)) { | | |
| 5239 | .@"packed" => unreachable, // TODO | | |
| 5240 | else => { | 5287 | else => { |
| 5241 | // Store, ptr-elem-ptr, pointer-cast, load | 5288 | // Store, ptr-elem-ptr, pointer-cast, load |
| 5242 | const layout = self.unionLayout(object_ty); | 5289 | const layout = self.unionLayout(object_ty); |
| ... | @@ -5317,28 +5364,28 @@ const NavGen = struct { | ... | @@ -5317,28 +5364,28 @@ const NavGen = struct { |
| 5317 | return try self.accessChain(result_ty_id, object_ptr, &.{field_index}); | 5364 | return try self.accessChain(result_ty_id, object_ptr, &.{field_index}); |
| 5318 | }, | 5365 | }, |
| 5319 | }, | 5366 | }, |
| 5320 | .@"union" => switch (object_ty.containerLayout(zcu)) { | 5367 | .@"union" => { |
| 5321 | .@"packed" => return self.todo("implement field access for packed unions", .{}), | 5368 | const layout = self.unionLayout(object_ty); |
| 5322 | else => { | 5369 | if (!layout.has_payload) { |
| 5323 | const layout = self.unionLayout(object_ty); | 5370 | // Asked to get a pointer to a zero-sized field. Just lower this |
| 5324 | if (!layout.has_payload) { | 5371 | // to undefined, there is no reason to make it be a valid pointer. |
| 5325 | // Asked to get a pointer to a zero-sized field. Just lower this | 5372 | return try self.spv.constUndef(result_ty_id); |
| 5326 | // to undefined, there is no reason to make it be a valid pointer. | 5373 | } |
| 5327 | return try self.spv.constUndef(result_ty_id); | | |
| 5328 | } | | |
| 5329 | | 5374 | |
| 5330 | const storage_class = self.spvStorageClass(object_ptr_ty.ptrAddressSpace(zcu)); | 5375 | const storage_class = self.spvStorageClass(object_ptr_ty.ptrAddressSpace(zcu)); |
| 5331 | const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, storage_class, .indirect); | 5376 | const pl_ptr_ty_id = try self.ptrType(layout.payload_ty, storage_class, .indirect); |
| 5332 | const pl_ptr_id = try self.accessChain(pl_ptr_ty_id, object_ptr, &.{layout.payload_index}); | 5377 | const pl_ptr_id = blk: { |
| | 5378 | if (object_ty.containerLayout(zcu) == .@"packed") break :blk object_ptr; |
| | 5379 | break :blk try self.accessChain(pl_ptr_ty_id, object_ptr, &.{layout.payload_index}); |
| | 5380 | }; |
| 5333 | | 5381 | |
| 5334 | const active_pl_ptr_id = self.spv.allocId(); | 5382 | const active_pl_ptr_id = self.spv.allocId(); |
| 5335 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ | 5383 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ |
| 5336 | .id_result_type = result_ty_id, | 5384 | .id_result_type = result_ty_id, |
| 5337 | .id_result = active_pl_ptr_id, | 5385 | .id_result = active_pl_ptr_id, |
| 5338 | .operand = pl_ptr_id, | 5386 | .operand = pl_ptr_id, |
| 5339 | }); | 5387 | }); |
| 5340 | return active_pl_ptr_id; | 5388 | return active_pl_ptr_id; |
| 5341 | }, | | |
| 5342 | }, | 5389 | }, |
| 5343 | else => unreachable, | 5390 | else => unreachable, |
| 5344 | } | 5391 | } |