| ... | ... | @@ -755,7 +755,7 @@ pub const DeclGen = struct { |
| 755 | 755 | switch (aggregate.storage) { |
| 756 | 756 | .bytes => |bytes| try self.addBytes(bytes), |
| 757 | 757 | .elems, .repeated_elem => { |
| 758 | | for (0..array_type.len) |i| { |
| 758 | for (0..@intCast(usize, array_type.len)) |i| { |
| 759 | 759 | try self.lower(elem_ty, switch (aggregate.storage) { |
| 760 | 760 | .bytes => unreachable, |
| 761 | 761 | .elems => |elem_vals| elem_vals[@intCast(usize, i)].toValue(), |
| ... | ... | @@ -771,16 +771,23 @@ pub const DeclGen = struct { |
| 771 | 771 | .vector_type => return dg.todo("indirect constant of type {}", .{ty.fmt(mod)}), |
| 772 | 772 | .struct_type => { |
| 773 | 773 | const struct_ty = mod.typeToStruct(ty).?; |
| 774 | | |
| 775 | 774 | if (struct_ty.layout == .Packed) { |
| 776 | 775 | return dg.todo("packed struct constants", .{}); |
| 777 | 776 | } |
| 778 | 777 | |
| 779 | 778 | const struct_begin = self.size; |
| 780 | | const field_vals = val.castTag(.aggregate).?.data; |
| 781 | 779 | for (struct_ty.fields.values(), 0..) |field, i| { |
| 782 | 780 | if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue; |
| 783 | | try self.lower(field.ty, field_vals[i]); |
| 781 | |
| 782 | const field_val = switch (aggregate.storage) { |
| 783 | .bytes => |bytes| try mod.intern_pool.get(mod.gpa, .{ .int = .{ |
| 784 | .ty = field.ty.toIntern(), |
| 785 | .storage = .{ .u64 = bytes[i] }, |
| 786 | } }), |
| 787 | .elems => |elems| elems[i], |
| 788 | .repeated_elem => |elem| elem, |
| 789 | }; |
| 790 | try self.lower(field.ty, field_val.toValue()); |
| 784 | 791 | |
| 785 | 792 | // Add padding if required. |
| 786 | 793 | // TODO: Add to type generation as well? |
| ... | ... | @@ -974,6 +981,7 @@ pub const DeclGen = struct { |
| 974 | 981 | /// This function should only be called during function code generation. |
| 975 | 982 | fn constant(self: *DeclGen, ty: Type, val: Value, repr: Repr) !IdRef { |
| 976 | 983 | const mod = self.module; |
| 984 | const target = self.getTarget(); |
| 977 | 985 | const result_ty_ref = try self.resolveType(ty, repr); |
| 978 | 986 | |
| 979 | 987 | log.debug("constant: ty = {}, val = {}", .{ ty.fmt(self.module), val.fmtValue(ty, self.module) }); |
| ... | ... | @@ -990,9 +998,19 @@ pub const DeclGen = struct { |
| 990 | 998 | return try self.spv.constInt(result_ty_ref, val.toUnsignedInt(mod)); |
| 991 | 999 | } |
| 992 | 1000 | }, |
| 993 | | .Bool => { |
| 994 | | @compileError("TODO merge conflict failure"); |
| 1001 | .Bool => switch (repr) { |
| 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) } } }), |
| 1007 | 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) } } }), |
| 1009 | 80, 128 => unreachable, // TODO |
| 1010 | else => unreachable, |
| 995 | 1011 | }, |
| 1012 | .ErrorSet => @panic("TODO"), |
| 1013 | .ErrorUnion => @panic("TODO"), |
| 996 | 1014 | // TODO: We can handle most pointers here (decl refs etc), because now they emit an extra |
| 997 | 1015 | // OpVariable that is not really required. |
| 998 | 1016 | else => { |
| ... | ... | @@ -1189,12 +1207,12 @@ pub const DeclGen = struct { |
| 1189 | 1207 | if (fn_info.is_var_args) |
| 1190 | 1208 | return self.fail("VarArgs functions are unsupported for SPIR-V", .{}); |
| 1191 | 1209 | |
| 1192 | | const param_ty_refs = try self.gpa.alloc(CacheRef, ty.fnParamLen()); |
| 1210 | const param_ty_refs = try self.gpa.alloc(CacheRef, fn_info.param_types.len); |
| 1193 | 1211 | defer self.gpa.free(param_ty_refs); |
| 1194 | 1212 | for (param_ty_refs, 0..) |*param_type, i| { |
| 1195 | | param_type.* = try self.resolveType(ty.fnParamType(i), .direct); |
| 1213 | param_type.* = try self.resolveType(fn_info.param_types[i].toType(), .direct); |
| 1196 | 1214 | } |
| 1197 | | const return_ty_ref = try self.resolveType(ty.fnReturnType(), .direct); |
| 1215 | const return_ty_ref = try self.resolveType(fn_info.return_type.toType(), .direct); |
| 1198 | 1216 | |
| 1199 | 1217 | return try self.spv.resolve(.{ .function_type = .{ |
| 1200 | 1218 | .return_type = return_ty_ref, |
| ... | ... | @@ -1245,17 +1263,18 @@ pub const DeclGen = struct { |
| 1245 | 1263 | } }); |
| 1246 | 1264 | }, |
| 1247 | 1265 | .Struct => { |
| 1248 | | if (ty.isSimpleTupleOrAnonStruct()) { |
| 1249 | | const tuple = ty.tupleFields(); |
| 1250 | | const member_types = try self.gpa.alloc(CacheRef, tuple.types.len); |
| 1266 | const struct_ty = mod.typeToStruct(ty).?; |
| 1267 | const fields = struct_ty.fields.values(); |
| 1268 | |
| 1269 | if (ty.isSimpleTupleOrAnonStruct(mod)) { |
| 1270 | const member_types = try self.gpa.alloc(CacheRef, fields.len); |
| 1251 | 1271 | defer self.gpa.free(member_types); |
| 1252 | 1272 | |
| 1253 | 1273 | var member_index: usize = 0; |
| 1254 | | for (tuple.types, 0..) |field_ty, i| { |
| 1255 | | const field_val = tuple.values[i]; |
| 1256 | | if (field_val.ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue; |
| 1274 | for (fields) |field| { |
| 1275 | if (field.ty.ip_index != .unreachable_value or !field.ty.hasRuntimeBits(mod)) continue; |
| 1257 | 1276 | |
| 1258 | | member_types[member_index] = try self.resolveType(field_ty, .indirect); |
| 1277 | member_types[member_index] = try self.resolveType(field.ty, .indirect); |
| 1259 | 1278 | member_index += 1; |
| 1260 | 1279 | } |
| 1261 | 1280 | |
| ... | ... | @@ -1264,29 +1283,26 @@ pub const DeclGen = struct { |
| 1264 | 1283 | } }); |
| 1265 | 1284 | } |
| 1266 | 1285 | |
| 1267 | | const struct_ty = mod.typeToStruct(ty).?; |
| 1268 | | |
| 1269 | 1286 | if (struct_ty.layout == .Packed) { |
| 1270 | 1287 | return try self.resolveType(struct_ty.backing_int_ty, .direct); |
| 1271 | 1288 | } |
| 1272 | 1289 | |
| 1273 | | const member_types = try self.gpa.alloc(CacheRef, struct_ty.fields.count()); |
| 1290 | const member_types = try self.gpa.alloc(CacheRef, fields.len); |
| 1274 | 1291 | defer self.gpa.free(member_types); |
| 1275 | 1292 | |
| 1276 | | const member_names = try self.gpa.alloc(CacheString, struct_ty.fields.count()); |
| 1293 | const member_names = try self.gpa.alloc(CacheString, fields.len); |
| 1277 | 1294 | defer self.gpa.free(member_names); |
| 1278 | 1295 | |
| 1279 | 1296 | var member_index: usize = 0; |
| 1280 | | const struct_obj = void; // TODO |
| 1281 | | for (struct_obj.fields.values(), 0..) |field, i| { |
| 1297 | for (fields, 0..) |field, i| { |
| 1282 | 1298 | if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue; |
| 1283 | 1299 | |
| 1284 | 1300 | member_types[member_index] = try self.resolveType(field.ty, .indirect); |
| 1285 | | member_names[member_index] = try self.spv.resolveString(struct_ty.fields.keys()[i]); |
| 1301 | member_names[member_index] = try self.spv.resolveString(mod.intern_pool.stringToSlice(struct_ty.fields.keys()[i])); |
| 1286 | 1302 | member_index += 1; |
| 1287 | 1303 | } |
| 1288 | 1304 | |
| 1289 | | const name = mod.intern_pool.stringToSlice(try struct_obj.getFullyQualifiedName(self.module)); |
| 1305 | const name = mod.intern_pool.stringToSlice(try struct_ty.getFullyQualifiedName(self.module)); |
| 1290 | 1306 | |
| 1291 | 1307 | return try self.spv.resolve(.{ .struct_type = .{ |
| 1292 | 1308 | .name = try self.spv.resolveString(name), |
| ... | ... | @@ -1491,7 +1507,6 @@ pub const DeclGen = struct { |
| 1491 | 1507 | } |
| 1492 | 1508 | |
| 1493 | 1509 | fn genDecl(self: *DeclGen) !void { |
| 1494 | | if (true) @panic("TODO: update SPIR-V backend for InternPool changes"); |
| 1495 | 1510 | const mod = self.module; |
| 1496 | 1511 | const decl = mod.declPtr(self.decl_index); |
| 1497 | 1512 | const spv_decl_index = try self.resolveDecl(self.decl_index); |
| ... | ... | @@ -1947,7 +1962,7 @@ pub const DeclGen = struct { |
| 1947 | 1962 | |
| 1948 | 1963 | const bool_ty_ref = try self.resolveType(Type.bool, .direct); |
| 1949 | 1964 | |
| 1950 | | const ov_ty = result_ty.tupleFields().types[1]; |
| 1965 | const ov_ty = result_ty.structFieldType(1, self.module); |
| 1951 | 1966 | // Note: result is stored in a struct, so indirect representation. |
| 1952 | 1967 | const ov_ty_ref = try self.resolveType(ov_ty, .indirect); |
| 1953 | 1968 | |
| ... | ... | @@ -2160,7 +2175,7 @@ pub const DeclGen = struct { |
| 2160 | 2175 | const opcode: Opcode = opcode: { |
| 2161 | 2176 | const op_ty = switch (ty.zigTypeTag(mod)) { |
| 2162 | 2177 | .Int, .Bool, .Float => ty, |
| 2163 | | .Enum => ty.intTagType(), |
| 2178 | .Enum => ty.intTagType(mod), |
| 2164 | 2179 | .ErrorSet => Type.u16, |
| 2165 | 2180 | .Pointer => blk: { |
| 2166 | 2181 | // Note that while SPIR-V offers OpPtrEqual and OpPtrNotEqual, they are |
| ... | ... | @@ -2443,8 +2458,7 @@ pub const DeclGen = struct { |
| 2443 | 2458 | const slice_id = try self.resolve(bin_op.lhs); |
| 2444 | 2459 | const index_id = try self.resolve(bin_op.rhs); |
| 2445 | 2460 | |
| 2446 | | var slice_buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 2447 | | const ptr_ty = slice_ty.slicePtrFieldType(&slice_buf, mod); |
| 2461 | const ptr_ty = slice_ty.slicePtrFieldType(mod); |
| 2448 | 2462 | const ptr_ty_ref = try self.resolveType(ptr_ty, .direct); |
| 2449 | 2463 | |
| 2450 | 2464 | const slice_ptr = try self.extractField(ptr_ty, slice_id, 0); |
| ... | ... | @@ -2497,8 +2511,8 @@ pub const DeclGen = struct { |
| 2497 | 2511 | // If we pass ptr_ty directly, it will attempt to load the entire array rather than |
| 2498 | 2512 | // just an element. |
| 2499 | 2513 | var elem_ptr_info = ptr_ty.ptrInfo(mod); |
| 2500 | | elem_ptr_info.size = .One; |
| 2501 | | const elem_ptr_ty = try Type.ptr(undefined, mod, elem_ptr_info); |
| 2514 | elem_ptr_info.flags.size = .One; |
| 2515 | const elem_ptr_ty = elem_ptr_info.child.toType(); |
| 2502 | 2516 | |
| 2503 | 2517 | return try self.load(elem_ptr_ty, elem_ptr_id); |
| 2504 | 2518 | } |
| ... | ... | @@ -2514,7 +2528,7 @@ pub const DeclGen = struct { |
| 2514 | 2528 | const union_handle = try self.resolve(ty_op.operand); |
| 2515 | 2529 | if (layout.payload_size == 0) return union_handle; |
| 2516 | 2530 | |
| 2517 | | const tag_ty = un_ty.unionTagTypeSafety().?; |
| 2531 | const tag_ty = un_ty.unionTagTypeSafety(mod).?; |
| 2518 | 2532 | const tag_index = @intFromBool(layout.tag_align < layout.payload_align); |
| 2519 | 2533 | return try self.extractField(tag_ty, union_handle, tag_index); |
| 2520 | 2534 | } |