| ... | @@ -1018,7 +1018,7 @@ const NavGen = struct { | ... | @@ -1018,7 +1018,7 @@ const NavGen = struct { |
| 1018 | const comp_ty_id = try self.resolveType(ty, .direct); | 1018 | const comp_ty_id = try self.resolveType(ty, .direct); |
| 1019 | return try self.constructComposite(comp_ty_id, constituents.items); | 1019 | return try self.constructComposite(comp_ty_id, constituents.items); |
| 1020 | }, | 1020 | }, |
| 1021 | .tuple_type => unreachable, // TODO | 1021 | .tuple_type => return self.todo("implement tuple types", .{}), |
| 1022 | else => unreachable, | 1022 | else => unreachable, |
| 1023 | }, | 1023 | }, |
| 1024 | .un => |un| { | 1024 | .un => |un| { |
| ... | @@ -1255,6 +1255,7 @@ const NavGen = struct { | ... | @@ -1255,6 +1255,7 @@ const NavGen = struct { |
| 1255 | | 1255 | |
| 1256 | fn ptrType(self: *NavGen, child_ty: Type, storage_class: StorageClass, child_repr: Repr) !IdRef { | 1256 | fn ptrType(self: *NavGen, child_ty: Type, storage_class: StorageClass, child_repr: Repr) !IdRef { |
| 1257 | const zcu = self.pt.zcu; | 1257 | const zcu = self.pt.zcu; |
| | 1258 | const ip = &zcu.intern_pool; |
| 1258 | const key = .{ child_ty.toIntern(), storage_class, child_repr }; | 1259 | const key = .{ child_ty.toIntern(), storage_class, child_repr }; |
| 1259 | const entry = try self.ptr_types.getOrPut(self.gpa, key); | 1260 | const entry = try self.ptr_types.getOrPut(self.gpa, key); |
| 1260 | if (entry.found_existing) { | 1261 | if (entry.found_existing) { |
| ... | @@ -1285,7 +1286,12 @@ const NavGen = struct { | ... | @@ -1285,7 +1286,12 @@ const NavGen = struct { |
| 1285 | } | 1286 | } |
| 1286 | } | 1287 | } |
| 1287 | | 1288 | |
| 1288 | try self.spv.decorate(result_id, .{ .ArrayStride = .{ .array_stride = @intCast(child_ty.abiSize(zcu)) } }); | 1289 | switch (ip.indexToKey(child_ty.toIntern())) { |
| | 1290 | .func_type, .opaque_type => {}, |
| | 1291 | else => { |
| | 1292 | try self.spv.decorate(result_id, .{ .ArrayStride = .{ .array_stride = @intCast(child_ty.abiSize(zcu)) } }); |
| | 1293 | }, |
| | 1294 | } |
| 1289 | } | 1295 | } |
| 1290 | | 1296 | |
| 1291 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{ | 1297 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{ |
| ... | @@ -1704,7 +1710,10 @@ const NavGen = struct { | ... | @@ -1704,7 +1710,10 @@ const NavGen = struct { |
| 1704 | return result_id; | 1710 | return result_id; |
| 1705 | }, | 1711 | }, |
| 1706 | .@"union" => return try self.resolveUnionType(ty), | 1712 | .@"union" => return try self.resolveUnionType(ty), |
| 1707 | .error_set => return try self.resolveType(Type.u16, repr), | 1713 | .error_set => { |
| | 1714 | const err_int_ty = try pt.errorIntType(); |
| | 1715 | return try self.resolveType(err_int_ty, repr); |
| | 1716 | }, |
| 1708 | .error_union => { | 1717 | .error_union => { |
| 1709 | const payload_ty = ty.errorUnionPayload(zcu); | 1718 | const payload_ty = ty.errorUnionPayload(zcu); |
| 1710 | const error_ty_id = try self.resolveType(Type.anyerror, .indirect); | 1719 | const error_ty_id = try self.resolveType(Type.anyerror, .indirect); |
| ... | @@ -2329,7 +2338,7 @@ const NavGen = struct { | ... | @@ -2329,7 +2338,7 @@ const NavGen = struct { |
| 2329 | // NOTE: Vulkan's FMA instruction does *NOT* produce the right values! | 2338 | // NOTE: Vulkan's FMA instruction does *NOT* produce the right values! |
| 2330 | // its precision guarantees do NOT match zigs and it does NOT match OpenCLs! | 2339 | // its precision guarantees do NOT match zigs and it does NOT match OpenCLs! |
| 2331 | // it needs to be emulated! | 2340 | // it needs to be emulated! |
| 2332 | .vulkan, .opengl => unreachable, // TODO: See above | 2341 | .vulkan, .opengl => return self.todo("implement fma operation for {s} os", .{@tagName(target.os.tag)}), |
| 2333 | else => unreachable, | 2342 | else => unreachable, |
| 2334 | }; | 2343 | }; |
| 2335 | | 2344 | |
| ... | @@ -2529,12 +2538,12 @@ const NavGen = struct { | ... | @@ -2529,12 +2538,12 @@ const NavGen = struct { |
| 2529 | .vulkan, .opengl => switch (op) { | 2538 | .vulkan, .opengl => switch (op) { |
| 2530 | .i_abs => 5, // SAbs | 2539 | .i_abs => 5, // SAbs |
| 2531 | .f_abs => 4, // FAbs | 2540 | .f_abs => 4, // FAbs |
| 2532 | .clz => unreachable, // TODO | | |
| 2533 | .ctz => unreachable, // TODO | | |
| 2534 | .floor => 8, // Floor | 2541 | .floor => 8, // Floor |
| 2535 | .ceil => 9, // Ceil | 2542 | .ceil => 9, // Ceil |
| 2536 | .trunc => 3, // Trunc | 2543 | .trunc => 3, // Trunc |
| 2537 | .round => 1, // Round | 2544 | .round => 1, // Round |
| | 2545 | .clz, |
| | 2546 | .ctz, |
| 2538 | .sqrt, | 2547 | .sqrt, |
| 2539 | .sin, | 2548 | .sin, |
| 2540 | .cos, | 2549 | .cos, |
| ... | @@ -2544,7 +2553,7 @@ const NavGen = struct { | ... | @@ -2544,7 +2553,7 @@ const NavGen = struct { |
| 2544 | .log, | 2553 | .log, |
| 2545 | .log2, | 2554 | .log2, |
| 2546 | .log10, | 2555 | .log10, |
| 2547 | => unreachable, // TODO | 2556 | => return self.todo("implement unary operation '{s}' for {s} os", .{ @tagName(op), @tagName(target.os.tag) }), |
| 2548 | else => unreachable, | 2557 | else => unreachable, |
| 2549 | }, | 2558 | }, |
| 2550 | else => unreachable, | 2559 | else => unreachable, |
| ... | @@ -2810,6 +2819,8 @@ const NavGen = struct { | ... | @@ -2810,6 +2819,8 @@ const NavGen = struct { |
| 2810 | /// TODO is to also write out the error as a function call parameter, and to somehow fetch | 2819 | /// TODO is to also write out the error as a function call parameter, and to somehow fetch |
| 2811 | /// the name of an error in the text executor. | 2820 | /// the name of an error in the text executor. |
| 2812 | fn generateTestEntryPoint(self: *NavGen, name: []const u8, spv_test_decl_index: SpvModule.Decl.Index) !void { | 2821 | fn generateTestEntryPoint(self: *NavGen, name: []const u8, spv_test_decl_index: SpvModule.Decl.Index) !void { |
| | 2822 | const target = self.spv.target; |
| | 2823 | |
| 2813 | const anyerror_ty_id = try self.resolveType(Type.anyerror, .direct); | 2824 | const anyerror_ty_id = try self.resolveType(Type.anyerror, .direct); |
| 2814 | const ptr_anyerror_ty = try self.pt.ptrType(.{ | 2825 | const ptr_anyerror_ty = try self.pt.ptrType(.{ |
| 2815 | .child = Type.anyerror.toIntern(), | 2826 | .child = Type.anyerror.toIntern(), |
| ... | @@ -2819,12 +2830,12 @@ const NavGen = struct { | ... | @@ -2819,12 +2830,12 @@ const NavGen = struct { |
| 2819 | | 2830 | |
| 2820 | const spv_decl_index = try self.spv.allocDecl(.func); | 2831 | const spv_decl_index = try self.spv.allocDecl(.func); |
| 2821 | const kernel_id = self.spv.declPtr(spv_decl_index).result_id; | 2832 | const kernel_id = self.spv.declPtr(spv_decl_index).result_id; |
| 2822 | // for some reason we don't need to decorate the push constant here... | | |
| 2823 | try self.spv.declareDeclDeps(spv_decl_index, &.{spv_test_decl_index}); | | |
| 2824 | | 2833 | |
| 2825 | const section = &self.spv.sections.functions; | 2834 | var decl_deps = std.ArrayList(SpvModule.Decl.Index).init(self.gpa); |
| | 2835 | defer decl_deps.deinit(); |
| | 2836 | try decl_deps.append(spv_test_decl_index); |
| 2826 | | 2837 | |
| 2827 | const target = self.spv.target; | 2838 | const section = &self.spv.sections.functions; |
| 2828 | | 2839 | |
| 2829 | const p_error_id = self.spv.allocId(); | 2840 | const p_error_id = self.spv.allocId(); |
| 2830 | switch (target.os.tag) { | 2841 | switch (target.os.tag) { |
| ... | @@ -2904,6 +2915,7 @@ const NavGen = struct { | ... | @@ -2904,6 +2915,7 @@ const NavGen = struct { |
| 2904 | | 2915 | |
| 2905 | const spv_err_decl_index = self.object.error_push_constant.?.push_constant_ptr; | 2916 | const spv_err_decl_index = self.object.error_push_constant.?.push_constant_ptr; |
| 2906 | const push_constant_id = self.spv.declPtr(spv_err_decl_index).result_id; | 2917 | const push_constant_id = self.spv.declPtr(spv_err_decl_index).result_id; |
| | 2918 | try decl_deps.append(spv_err_decl_index); |
| 2907 | | 2919 | |
| 2908 | const zero_id = try self.constInt(Type.u32, 0); | 2920 | const zero_id = try self.constInt(Type.u32, 0); |
| 2909 | // We cannot use OpInBoundsAccessChain to dereference cross-storage class, so we have to use | 2921 | // We cannot use OpInBoundsAccessChain to dereference cross-storage class, so we have to use |
| ... | @@ -2953,6 +2965,7 @@ const NavGen = struct { | ... | @@ -2953,6 +2965,7 @@ const NavGen = struct { |
| 2953 | else => unreachable, | 2965 | else => unreachable, |
| 2954 | }; | 2966 | }; |
| 2955 | | 2967 | |
| | 2968 | try self.spv.declareDeclDeps(spv_decl_index, decl_deps.items); |
| 2956 | try self.spv.declareEntryPoint(spv_decl_index, test_name, execution_mode); | 2969 | try self.spv.declareEntryPoint(spv_decl_index, test_name, execution_mode); |
| 2957 | } | 2970 | } |
| 2958 | | 2971 | |
| ... | @@ -3372,6 +3385,7 @@ const NavGen = struct { | ... | @@ -3372,6 +3385,7 @@ const NavGen = struct { |
| 3372 | .switch_br => return self.airSwitchBr(inst), | 3385 | .switch_br => return self.airSwitchBr(inst), |
| 3373 | .unreach, .trap => return self.airUnreach(), | 3386 | .unreach, .trap => return self.airUnreach(), |
| 3374 | | 3387 | |
| | 3388 | .dbg_empty_stmt => return, |
| 3375 | .dbg_stmt => return self.airDbgStmt(inst), | 3389 | .dbg_stmt => return self.airDbgStmt(inst), |
| 3376 | .dbg_inline_block => try self.airDbgInlineBlock(inst), | 3390 | .dbg_inline_block => try self.airDbgInlineBlock(inst), |
| 3377 | .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => return self.airDbgVar(inst), | 3391 | .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => return self.airDbgVar(inst), |
| ... | @@ -3651,6 +3665,7 @@ const NavGen = struct { | ... | @@ -3651,6 +3665,7 @@ const NavGen = struct { |
| 3651 | } | 3665 | } |
| 3652 | | 3666 | |
| 3653 | fn abs(self: *NavGen, result_ty: Type, value: Temporary) !Temporary { | 3667 | fn abs(self: *NavGen, result_ty: Type, value: Temporary) !Temporary { |
| | 3668 | const zcu = self.pt.zcu; |
| 3654 | const operand_info = self.arithmeticTypeInfo(value.ty); | 3669 | const operand_info = self.arithmeticTypeInfo(value.ty); |
| 3655 | | 3670 | |
| 3656 | switch (operand_info.class) { | 3671 | switch (operand_info.class) { |
| ... | @@ -3658,11 +3673,9 @@ const NavGen = struct { | ... | @@ -3658,11 +3673,9 @@ const NavGen = struct { |
| 3658 | .integer, .strange_integer => { | 3673 | .integer, .strange_integer => { |
| 3659 | const abs_value = try self.buildUnary(.i_abs, value); | 3674 | const abs_value = try self.buildUnary(.i_abs, value); |
| 3660 | | 3675 | |
| 3661 | // TODO: We may need to bitcast the result to a uint | 3676 | if (value.ty.intInfo(zcu).signedness == .signed and self.spv.hasFeature(.shader)) { |
| 3662 | // depending on the result type. Do that when | 3677 | return self.todo("perform bitcast after @abs", .{}); |
| 3663 | // bitCast is implemented for vectors. | 3678 | } |
| 3664 | // This is only relevant for Vulkan | | |
| 3665 | assert(self.spv.hasFeature(.kernel)); // TODO | | |
| 3666 | | 3679 | |
| 3667 | return try self.normalize(abs_value, self.arithmeticTypeInfo(result_ty)); | 3680 | return try self.normalize(abs_value, self.arithmeticTypeInfo(result_ty)); |
| 3668 | }, | 3681 | }, |
| ... | @@ -3980,8 +3993,6 @@ const NavGen = struct { | ... | @@ -3980,8 +3993,6 @@ const NavGen = struct { |
| 3980 | .float, .bool => unreachable, | 3993 | .float, .bool => unreachable, |
| 3981 | } | 3994 | } |
| 3982 | | 3995 | |
| 3983 | assert(self.spv.hasFeature(.kernel)); // TODO | | |
| 3984 | | | |
| 3985 | const count = try self.buildUnary(op, operand); | 3996 | const count = try self.buildUnary(op, operand); |
| 3986 | | 3997 | |
| 3987 | // Result of OpenCL ctz/clz returns operand.ty, and we want result_ty. | 3998 | // Result of OpenCL ctz/clz returns operand.ty, and we want result_ty. |
| ... | @@ -4307,7 +4318,8 @@ const NavGen = struct { | ... | @@ -4307,7 +4318,8 @@ const NavGen = struct { |
| 4307 | }, | 4318 | }, |
| 4308 | .error_set => { | 4319 | .error_set => { |
| 4309 | assert(!is_vector); | 4320 | assert(!is_vector); |
| 4310 | return try self.cmp(op, lhs.pun(Type.u16), rhs.pun(Type.u16)); | 4321 | const err_int_ty = try pt.errorIntType(); |
| | 4322 | return try self.cmp(op, lhs.pun(err_int_ty), rhs.pun(err_int_ty)); |
| 4311 | }, | 4323 | }, |
| 4312 | .pointer => { | 4324 | .pointer => { |
| 4313 | assert(!is_vector); | 4325 | assert(!is_vector); |
| ... | @@ -4411,7 +4423,7 @@ const NavGen = struct { | ... | @@ -4411,7 +4423,7 @@ const NavGen = struct { |
| 4411 | else => unreachable, | 4423 | else => unreachable, |
| 4412 | }; | 4424 | }; |
| 4413 | }, | 4425 | }, |
| 4414 | else => unreachable, | 4426 | else => |ty| return self.todo("implement cmp operation for '{s}' type", .{@tagName(ty)}), |
| 4415 | } | 4427 | } |
| 4416 | | 4428 | |
| 4417 | const info = self.arithmeticTypeInfo(scalar_ty); | 4429 | const info = self.arithmeticTypeInfo(scalar_ty); |
| ... | @@ -5233,13 +5245,13 @@ const NavGen = struct { | ... | @@ -5233,13 +5245,13 @@ const NavGen = struct { |
| 5233 | return self.accessChain(result_ty_id, object_ptr, &.{field_index}); | 5245 | return self.accessChain(result_ty_id, object_ptr, &.{field_index}); |
| 5234 | }, | 5246 | }, |
| 5235 | .@"struct" => switch (object_ty.containerLayout(zcu)) { | 5247 | .@"struct" => switch (object_ty.containerLayout(zcu)) { |
| 5236 | .@"packed" => unreachable, // TODO | 5248 | .@"packed" => return self.todo("implement field access for packed structs", .{}), |
| 5237 | else => { | 5249 | else => { |
| 5238 | return try self.accessChain(result_ty_id, object_ptr, &.{field_index}); | 5250 | return try self.accessChain(result_ty_id, object_ptr, &.{field_index}); |
| 5239 | }, | 5251 | }, |
| 5240 | }, | 5252 | }, |
| 5241 | .@"union" => switch (object_ty.containerLayout(zcu)) { | 5253 | .@"union" => switch (object_ty.containerLayout(zcu)) { |
| 5242 | .@"packed" => unreachable, // TODO | 5254 | .@"packed" => return self.todo("implement field access for packed unions", .{}), |
| 5243 | else => { | 5255 | else => { |
| 5244 | const layout = self.unionLayout(object_ty); | 5256 | const layout = self.unionLayout(object_ty); |
| 5245 | if (!layout.has_payload) { | 5257 | if (!layout.has_payload) { |