authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-07-01 14:27:12+02:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2023-07-01 14:27:12+02:00
log8eee3928626f9469dbd5ca15127b836e48553bd3
treec6e4952a20fde8657ccfa7d00bce8ea35e6f1fdf
parent0a6cd257b9c8a9093b966e3851dc8261e19b531a
signaturebadge-check Signed by SSH key SHA256:CQ99aPxq+RueiL9u7z0FEki5Fm7V6T8q4PrEGmINrA4

spirv: fix up todos & errors from intern pool changes

This replaces the implementation of constant() which one that is directly based on the intern pool rather than the Zig type tag too.

1 files changed, 124 insertions(+), 56 deletions(-)

src/codegen/spirv.zig+124-56
...@@ -537,6 +537,12 @@ pub const DeclGen = struct {...@@ -537,6 +537,12 @@ pub const DeclGen = struct {
537537
538 fn addInt(self: *@This(), ty: Type, val: Value) !void {538 fn addInt(self: *@This(), ty: Type, val: Value) !void {
539 const mod = self.dg.module;539 const mod = self.dg.module;
540 const len = ty.abiSize(mod);
541 if (val.isUndef(mod)) {
542 try self.addUndef(len);
543 return;
544 }
545
540 const int_info = ty.intInfo(mod);546 const int_info = ty.intInfo(mod);
541 const int_bits = switch (int_info.signedness) {547 const int_bits = switch (int_info.signedness) {
542 .signed => @as(u64, @bitCast(val.toSignedInt(mod))),548 .signed => @as(u64, @bitCast(val.toSignedInt(mod))),
...@@ -544,7 +550,6 @@ pub const DeclGen = struct {...@@ -544,7 +550,6 @@ pub const DeclGen = struct {
544 };550 };
545551
546 // TODO: Swap endianess if the compiler is big endian.552 // TODO: Swap endianess if the compiler is big endian.
547 const len = ty.abiSize(mod);
548 try self.addBytes(std.mem.asBytes(&int_bits)[0..@as(usize, @intCast(len))]);553 try self.addBytes(std.mem.asBytes(&int_bits)[0..@as(usize, @intCast(len))]);
549 }554 }
550555
...@@ -667,31 +672,41 @@ pub const DeclGen = struct {...@@ -667,31 +672,41 @@ pub const DeclGen = struct {
667 try self.addConstInt(u16, @as(u16, @intCast(int)));672 try self.addConstInt(u16, @as(u16, @intCast(int)));
668 },673 },
669 .error_union => |error_union| {674 .error_union => |error_union| {
675 const err_ty = switch (error_union.val) {
676 .err_name => ty.errorUnionSet(mod),
677 .payload => Type.err_int,
678 };
679 const err_val = switch (error_union.val) {
680 .err_name => |err_name| (try mod.intern(.{ .err = .{
681 .ty = ty.errorUnionSet(mod).toIntern(),
682 .name = err_name,
683 } })).toValue(),
684 .payload => try mod.intValue(Type.err_int, 0),
685 };
670 const payload_ty = ty.errorUnionPayload(mod);686 const payload_ty = ty.errorUnionPayload(mod);
671 const is_pl = val.errorUnionIsPayload(mod);
672 const error_val = if (!is_pl) val else try mod.intValue(Type.anyerror, 0);
673
674 const eu_layout = dg.errorUnionLayout(payload_ty);687 const eu_layout = dg.errorUnionLayout(payload_ty);
675 if (!eu_layout.payload_has_bits) {688 if (!eu_layout.payload_has_bits) {
676 return try self.lower(Type.anyerror, error_val);689 // We use the error type directly as the type.
690 try self.lower(err_ty, err_val);
691 return;
677 }692 }
678693
679 const payload_size = payload_ty.abiSize(mod);694 const payload_size = payload_ty.abiSize(mod);
680 const error_size = Type.anyerror.abiAlignment(mod);695 const error_size = err_ty.abiSize(mod);
681 const ty_size = ty.abiSize(mod);696 const ty_size = ty.abiSize(mod);
682 const padding = ty_size - payload_size - error_size;697 const padding = ty_size - payload_size - error_size;
683698
684 const payload_val = switch (error_union.val) {699 const payload_val = switch (error_union.val) {
685 .err_name => try mod.intern(.{ .undef = payload_ty.ip_index }),700 .err_name => try mod.intern(.{ .undef = payload_ty.toIntern() }),
686 .payload => |payload| payload,701 .payload => |payload| payload,
687 }.toValue();702 }.toValue();
688703
689 if (eu_layout.error_first) {704 if (eu_layout.error_first) {
690 try self.lower(Type.anyerror, error_val);705 try self.lower(err_ty, err_val);
691 try self.lower(payload_ty, payload_val);706 try self.lower(payload_ty, payload_val);
692 } else {707 } else {
693 try self.lower(payload_ty, payload_val);708 try self.lower(payload_ty, payload_val);
694 try self.lower(Type.anyerror, error_val);709 try self.lower(err_ty, err_val);
695 }710 }
696711
697 try self.addUndef(padding);712 try self.addUndef(padding);
...@@ -705,9 +720,14 @@ pub const DeclGen = struct {...@@ -705,9 +720,14 @@ pub const DeclGen = struct {
705 },720 },
706 .float => try self.addFloat(ty, val),721 .float => try self.addFloat(ty, val),
707 .ptr => |ptr| {722 .ptr => |ptr| {
723 const ptr_ty = switch (ptr.len) {
724 .none => ty,
725 else => ty.slicePtrFieldType(mod),
726 };
708 switch (ptr.addr) {727 switch (ptr.addr) {
709 .decl => |decl| try self.addDeclRef(ty, decl),728 .decl => |decl| try self.addDeclRef(ptr_ty, decl),
710 .mut_decl => |mut_decl| try self.addDeclRef(ty, mut_decl.decl),729 .mut_decl => |mut_decl| try self.addDeclRef(ptr_ty, mut_decl.decl),
730 .int => |int| try self.addInt(Type.usize, int.toValue()),
711 else => |tag| return dg.todo("pointer value of type {s}", .{@tagName(tag)}),731 else => |tag| return dg.todo("pointer value of type {s}", .{@tagName(tag)}),
712 }732 }
713 if (ptr.len != .none) {733 if (ptr.len != .none) {
...@@ -979,38 +999,84 @@ pub const DeclGen = struct {...@@ -979,38 +999,84 @@ pub const DeclGen = struct {
979 /// the constant is more complicated however, it needs to be lowered to an indirect constant, which999 /// the constant is more complicated however, it needs to be lowered to an indirect constant, which
980 /// is then loaded using OpLoad. Such values are loaded into the UniformConstant storage class by default.1000 /// is then loaded using OpLoad. Such values are loaded into the UniformConstant storage class by default.
981 /// This function should only be called during function code generation.1001 /// This function should only be called during function code generation.
982 fn constant(self: *DeclGen, ty: Type, val: Value, repr: Repr) !IdRef {1002 fn constant(self: *DeclGen, ty: Type, arg_val: Value, repr: Repr) !IdRef {
983 const mod = self.module;1003 const mod = self.module;
984 const target = self.getTarget();1004 const target = self.getTarget();
985 const result_ty_ref = try self.resolveType(ty, repr);1005 const result_ty_ref = try self.resolveType(ty, repr);
9861006
987 log.debug("constant: ty = {}, val = {}", .{ ty.fmt(self.module), val.fmtValue(ty, self.module) });1007 var val = arg_val;
1008 switch (mod.intern_pool.indexToKey(val.toIntern())) {
1009 .runtime_value => |rt| val = rt.val.toValue(),
1010 else => {},
1011 }
9881012
1013 log.debug("constant: ty = {}, val = {}", .{ ty.fmt(self.module), val.fmtValue(ty, self.module) });
989 if (val.isUndef(mod)) {1014 if (val.isUndef(mod)) {
990 return self.spv.constUndef(result_ty_ref);1015 return self.spv.constUndef(result_ty_ref);
991 }1016 }
9921017
993 switch (ty.zigTypeTag(mod)) {1018 switch (mod.intern_pool.indexToKey(val.toIntern())) {
994 .Int => {1019 .int_type,
1020 .ptr_type,
1021 .array_type,
1022 .vector_type,
1023 .opt_type,
1024 .anyframe_type,
1025 .error_union_type,
1026 .simple_type,
1027 .struct_type,
1028 .anon_struct_type,
1029 .union_type,
1030 .opaque_type,
1031 .enum_type,
1032 .func_type,
1033 .error_set_type,
1034 .inferred_error_set_type,
1035 => unreachable, // types, not values
1036
1037 .undef => unreachable, // handled above
1038 .runtime_value => unreachable, // ???
1039
1040 .variable,
1041 .extern_func,
1042 .func,
1043 .enum_literal,
1044 .empty_enum_value,
1045 => unreachable, // non-runtime values
1046
1047 .simple_value => |simple_value| switch (simple_value) {
1048 .undefined,
1049 .void,
1050 .null,
1051 .empty_struct,
1052 .@"unreachable",
1053 .generic_poison,
1054 => unreachable, // non-runtime values
1055
1056 .false, .true => switch (repr) {
1057 .direct => return try self.spv.constBool(result_ty_ref, val.toBool()),
1058 .indirect => return try self.spv.constInt(result_ty_ref, @intFromBool(val.toBool())),
1059 },
1060 },
1061
1062 .int => {
995 if (ty.isSignedInt(mod)) {1063 if (ty.isSignedInt(mod)) {
996 return try self.spv.constInt(result_ty_ref, val.toSignedInt(mod));1064 return try self.spv.constInt(result_ty_ref, val.toSignedInt(mod));
997 } else {1065 } else {
998 return try self.spv.constInt(result_ty_ref, val.toUnsignedInt(mod));1066 return try self.spv.constInt(result_ty_ref, val.toUnsignedInt(mod));
999 }1067 }
1000 },1068 },
1001 .Bool => switch (repr) {1069 .float => return switch (ty.floatBits(target)) {
1002 .direct => return try self.spv.constBool(result_ty_ref, val.toBool()),
1003 .indirect => return try self.spv.constInt(result_ty_ref, @intFromBool(val.toBool())),
1004 },
1005 .Float => return switch (ty.floatBits(target)) {
1006 16 => try self.spv.resolveId(.{ .float = .{ .ty = result_ty_ref, .value = .{ .float16 = val.toFloat(f16, mod) } } }),1070 16 => try self.spv.resolveId(.{ .float = .{ .ty = result_ty_ref, .value = .{ .float16 = val.toFloat(f16, mod) } } }),
1007 32 => try self.spv.resolveId(.{ .float = .{ .ty = result_ty_ref, .value = .{ .float32 = val.toFloat(f32, mod) } } }),1071 32 => try self.spv.resolveId(.{ .float = .{ .ty = result_ty_ref, .value = .{ .float32 = val.toFloat(f32, mod) } } }),
1008 64 => try self.spv.resolveId(.{ .float = .{ .ty = result_ty_ref, .value = .{ .float64 = val.toFloat(f64, mod) } } }),1072 64 => try self.spv.resolveId(.{ .float = .{ .ty = result_ty_ref, .value = .{ .float64 = val.toFloat(f64, mod) } } }),
1009 80, 128 => unreachable, // TODO1073 80, 128 => unreachable, // TODO
1010 else => unreachable,1074 else => unreachable,
1011 },1075 },
1012 .ErrorSet => @panic("TODO"),1076 .err => |err| {
1013 .ErrorUnion => @panic("TODO"),1077 const value = try mod.getErrorValue(err.name);
1078 return try self.spv.constInt(result_ty_ref, value);
1079 },
1014 // TODO: We can handle most pointers here (decl refs etc), because now they emit an extra1080 // TODO: We can handle most pointers here (decl refs etc), because now they emit an extra
1015 // OpVariable that is not really required.1081 // OpVariable that is not really required.
1016 else => {1082 else => {
...@@ -1263,51 +1329,53 @@ pub const DeclGen = struct {...@@ -1263,51 +1329,53 @@ pub const DeclGen = struct {
1263 } });1329 } });
1264 },1330 },
1265 .Struct => {1331 .Struct => {
1266 const struct_ty = mod.typeToStruct(ty).?;1332 const struct_ty = switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1267 const fields = struct_ty.fields.values();1333 .anon_struct_type => |tuple| {
12681334 const member_types = try self.gpa.alloc(CacheRef, tuple.values.len);
1269 if (ty.isSimpleTupleOrAnonStruct(mod)) {1335 defer self.gpa.free(member_types);
1270 const member_types = try self.gpa.alloc(CacheRef, fields.len);
1271 defer self.gpa.free(member_types);
12721336
1273 var member_index: usize = 0;1337 var member_index: usize = 0;
1274 for (fields) |field| {1338 for (tuple.types, tuple.values) |field_ty, field_val| {
1275 if (field.ty.ip_index != .unreachable_value or !field.ty.hasRuntimeBits(mod)) continue;1339 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
12761340
1277 member_types[member_index] = try self.resolveType(field.ty, .indirect);1341 member_types[member_index] = try self.resolveType(field_ty.toType(), .indirect);
1278 member_index += 1;1342 member_index += 1;
1279 }1343 }
12801344
1281 return try self.spv.resolve(.{ .struct_type = .{1345 return try self.spv.resolve(.{ .struct_type = .{
1282 .member_types = member_types[0..member_index],1346 .member_types = member_types[0..member_index],
1283 } });1347 } });
1284 }1348 },
1349 .struct_type => |struct_ty| struct_ty,
1350 else => unreachable,
1351 };
12851352
1286 if (struct_ty.layout == .Packed) {1353 const struct_obj = mod.structPtrUnwrap(struct_ty.index).?;
1287 return try self.resolveType(struct_ty.backing_int_ty, .direct);1354 if (struct_obj.layout == .Packed) {
1355 return try self.resolveType(struct_obj.backing_int_ty, .direct);
1288 }1356 }
12891357
1290 const member_types = try self.gpa.alloc(CacheRef, fields.len);1358 var member_types = std.ArrayList(CacheRef).init(self.gpa);
1291 defer self.gpa.free(member_types);1359 defer member_types.deinit();
1292
1293 const member_names = try self.gpa.alloc(CacheString, fields.len);
1294 defer self.gpa.free(member_names);
12951360
1296 var member_index: usize = 0;1361 var member_names = std.ArrayList(CacheString).init(self.gpa);
1297 for (fields, 0..) |field, i| {1362 defer member_names.deinit();
1298 if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue;
12991363
1300 member_types[member_index] = try self.resolveType(field.ty, .indirect);1364 var it = struct_obj.runtimeFieldIterator(mod);
1301 member_names[member_index] = try self.spv.resolveString(mod.intern_pool.stringToSlice(struct_ty.fields.keys()[i]));1365 while (it.next()) |field_and_index| {
1302 member_index += 1;1366 const field = field_and_index.field;
1367 const index = field_and_index.index;
1368 const field_name = mod.intern_pool.stringToSlice(struct_obj.fields.keys()[index]);
1369 try member_types.append(try self.resolveType(field.ty, .indirect));
1370 try member_names.append(try self.spv.resolveString(field_name));
1303 }1371 }
13041372
1305 const name = mod.intern_pool.stringToSlice(try struct_ty.getFullyQualifiedName(self.module));1373 const name = mod.intern_pool.stringToSlice(try struct_obj.getFullyQualifiedName(self.module));
13061374
1307 return try self.spv.resolve(.{ .struct_type = .{1375 return try self.spv.resolve(.{ .struct_type = .{
1308 .name = try self.spv.resolveString(name),1376 .name = try self.spv.resolveString(name),
1309 .member_types = member_types[0..member_index],1377 .member_types = member_types.items,
1310 .member_names = member_names[0..member_index],1378 .member_names = member_names.items,
1311 } });1379 } });
1312 },1380 },
1313 .Optional => {1381 .Optional => {
...@@ -2512,9 +2580,9 @@ pub const DeclGen = struct {...@@ -2512,9 +2580,9 @@ pub const DeclGen = struct {
2512 // just an element.2580 // just an element.
2513 var elem_ptr_info = ptr_ty.ptrInfo(mod);2581 var elem_ptr_info = ptr_ty.ptrInfo(mod);
2514 elem_ptr_info.flags.size = .One;2582 elem_ptr_info.flags.size = .One;
2515 const elem_ptr_ty = elem_ptr_info.child.toType();2583 const elem_ptr_ty = try mod.intern_pool.get(mod.gpa, .{ .ptr_type = elem_ptr_info });
25162584
2517 return try self.load(elem_ptr_ty, elem_ptr_id);2585 return try self.load(elem_ptr_ty.toType(), elem_ptr_id);
2518 }2586 }
25192587
2520 fn airGetUnionTag(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {2588 fn airGetUnionTag(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {