| ... | ... | @@ -1301,6 +1301,72 @@ pub const DeclGen = struct { |
| 1301 | 1301 | .vector_type, .anon_struct_type => unreachable, // TODO |
| 1302 | 1302 | else => unreachable, |
| 1303 | 1303 | }, |
| 1304 | .un => |un| { |
| 1305 | // To initialize a union, generate a temporary variable with the |
| 1306 | // type that has the right field active, then pointer-cast and store |
| 1307 | // the active field, and finally load and return the entire union. |
| 1308 | |
| 1309 | const layout = ty.unionGetLayout(mod); |
| 1310 | const union_ty = mod.typeToUnion(ty).?; |
| 1311 | |
| 1312 | if (union_ty.getLayout(ip) == .Packed) { |
| 1313 | return self.todo("packed union types", .{}); |
| 1314 | } else if (layout.payload_size == 0) { |
| 1315 | // No payload, so represent this as just the tag type. |
| 1316 | return try self.constant(ty.unionTagTypeSafety(mod).?, un.tag.toValue(), .indirect); |
| 1317 | } |
| 1318 | |
| 1319 | const has_tag = layout.tag_size != 0; |
| 1320 | const tag_first = layout.tag_align >= layout.payload_align; |
| 1321 | |
| 1322 | const un_ptr_ty_ref = try self.spv.ptrType(result_ty_ref, .Function); |
| 1323 | |
| 1324 | const var_id = self.spv.allocId(); |
| 1325 | try self.func.prologue.emit(self.spv.gpa, .OpVariable, .{ |
| 1326 | .id_result_type = self.typeId(un_ptr_ty_ref), |
| 1327 | .id_result = var_id, |
| 1328 | .storage_class = .Function, |
| 1329 | }); |
| 1330 | |
| 1331 | const index_ty_ref = try self.intType(.unsigned, 32); |
| 1332 | |
| 1333 | if (has_tag) { |
| 1334 | const tag_index: u32 = if (tag_first) 0 else 1; |
| 1335 | const index_id = try self.spv.constInt(index_ty_ref, tag_index); |
| 1336 | const tag_ty = ty.unionTagTypeSafety(mod).?; |
| 1337 | const tag_ty_ref = try self.resolveType(tag_ty, .indirect); |
| 1338 | const tag_ptr_ty_ref = try self.spv.ptrType(tag_ty_ref, .Function); |
| 1339 | const ptr_id = try self.accessChain(tag_ptr_ty_ref, var_id, &.{index_id}); |
| 1340 | const tag_id = try self.constant(tag_ty, un.tag.toValue(), .indirect); |
| 1341 | try self.func.body.emit(self.spv.gpa, .OpStore, .{ |
| 1342 | .pointer = ptr_id, |
| 1343 | .object = tag_id, |
| 1344 | }); |
| 1345 | } |
| 1346 | |
| 1347 | const pl_index: u32 = if (tag_first) 1 else 0; |
| 1348 | const index_id = try self.spv.constInt(index_ty_ref, pl_index); |
| 1349 | const active_field = ty.unionTagFieldIndex(un.tag.toValue(), mod).?; |
| 1350 | const active_field_ty = union_ty.field_types.get(ip)[active_field].toType(); |
| 1351 | const active_field_ty_ref = try self.resolveType(active_field_ty, .indirect); |
| 1352 | const active_field_ptr_ty_ref = try self.spv.ptrType(active_field_ty_ref, .Function); |
| 1353 | const ptr_id = try self.accessChain(active_field_ptr_ty_ref, var_id, &.{index_id}); |
| 1354 | const value_id = try self.constant(active_field_ty, un.val.toValue(), .indirect); |
| 1355 | try self.func.body.emit(self.spv.gpa, .OpStore, .{ |
| 1356 | .pointer = ptr_id, |
| 1357 | .object = value_id, |
| 1358 | }); |
| 1359 | |
| 1360 | // Just leave the padding fields uninitialized... |
| 1361 | |
| 1362 | const result_id = self.spv.allocId(); |
| 1363 | try self.func.body.emit(self.spv.gpa, .OpLoad, .{ |
| 1364 | .id_result_type = self.typeId(result_ty_ref), |
| 1365 | .id_result = result_id, |
| 1366 | .pointer = var_id, |
| 1367 | }); |
| 1368 | return result_id; |
| 1369 | }, |
| 1304 | 1370 | else => { |
| 1305 | 1371 | // The value cannot be generated directly, so generate it as an indirect constant, |
| 1306 | 1372 | // and then perform an OpLoad. |
| ... | ... | @@ -1417,7 +1483,7 @@ pub const DeclGen = struct { |
| 1417 | 1483 | if (has_tag and tag_first) { |
| 1418 | 1484 | const tag_ty_ref = try self.resolveType(union_obj.enum_tag_ty.toType(), .indirect); |
| 1419 | 1485 | member_types.appendAssumeCapacity(tag_ty_ref); |
| 1420 | | member_names.appendAssumeCapacity(try self.spv.resolveString("tag")); |
| 1486 | member_names.appendAssumeCapacity(try self.spv.resolveString("(tag)")); |
| 1421 | 1487 | } |
| 1422 | 1488 | |
| 1423 | 1489 | const active_field = maybe_active_field orelse layout.most_aligned_field; |
| ... | ... | @@ -1426,7 +1492,7 @@ pub const DeclGen = struct { |
| 1426 | 1492 | const active_field_size = if (active_field_ty.hasRuntimeBitsIgnoreComptime(mod)) blk: { |
| 1427 | 1493 | const active_payload_ty_ref = try self.resolveType(active_field_ty, .indirect); |
| 1428 | 1494 | member_types.appendAssumeCapacity(active_payload_ty_ref); |
| 1429 | | member_names.appendAssumeCapacity(try self.spv.resolveString("payload")); |
| 1495 | member_names.appendAssumeCapacity(try self.spv.resolveString("(payload)")); |
| 1430 | 1496 | break :blk active_field_ty.abiSize(mod); |
| 1431 | 1497 | } else 0; |
| 1432 | 1498 | |
| ... | ... | @@ -1434,19 +1500,19 @@ pub const DeclGen = struct { |
| 1434 | 1500 | if (payload_padding_len != 0) { |
| 1435 | 1501 | const payload_padding_ty_ref = try self.spv.arrayType(@as(u32, @intCast(payload_padding_len)), u8_ty_ref); |
| 1436 | 1502 | member_types.appendAssumeCapacity(payload_padding_ty_ref); |
| 1437 | | member_names.appendAssumeCapacity(try self.spv.resolveString("payload_padding")); |
| 1503 | member_names.appendAssumeCapacity(try self.spv.resolveString("(payload padding)")); |
| 1438 | 1504 | } |
| 1439 | 1505 | |
| 1440 | 1506 | if (has_tag and !tag_first) { |
| 1441 | 1507 | const tag_ty_ref = try self.resolveType(union_obj.enum_tag_ty.toType(), .indirect); |
| 1442 | 1508 | member_types.appendAssumeCapacity(tag_ty_ref); |
| 1443 | | member_names.appendAssumeCapacity(try self.spv.resolveString("tag")); |
| 1509 | member_names.appendAssumeCapacity(try self.spv.resolveString("(tag)")); |
| 1444 | 1510 | } |
| 1445 | 1511 | |
| 1446 | 1512 | if (layout.padding != 0) { |
| 1447 | 1513 | const padding_ty_ref = try self.spv.arrayType(layout.padding, u8_ty_ref); |
| 1448 | 1514 | member_types.appendAssumeCapacity(padding_ty_ref); |
| 1449 | | member_names.appendAssumeCapacity(try self.spv.resolveString("padding")); |
| 1515 | member_names.appendAssumeCapacity(try self.spv.resolveString("(padding)")); |
| 1450 | 1516 | } |
| 1451 | 1517 | |
| 1452 | 1518 | const ty_ref = try self.spv.resolve(.{ .struct_type = .{ |