| ... | @@ -585,9 +585,10 @@ pub const DeclGen = struct { | ... | @@ -585,9 +585,10 @@ pub const DeclGen = struct { |
| 585 | switch (ty.zigTypeTag()) { | 585 | switch (ty.zigTypeTag()) { |
| 586 | .Void, .NoReturn => return try self.spv.resolveType(SpvType.initTag(.void)), | 586 | .Void, .NoReturn => return try self.spv.resolveType(SpvType.initTag(.void)), |
| 587 | .Bool => { | 587 | .Bool => { |
| 588 | // TODO: SPIR-V booleans are opaque. For local variables this is fine, but for structs | 588 | // SPIR-V booleans are opaque, which is fine for operations, but they cant be stored. |
| 589 | // members we want to use integer types instead. | 589 | // This function returns the *stored* type, for values directly we convert this into a bool when |
| 590 | return try self.spv.resolveType(SpvType.initTag(.bool)); | 590 | // it is loaded, and convert it back to this type when stored. |
| | 591 | return try self.intType(.unsigned, 1); |
| 591 | }, | 592 | }, |
| 592 | .Int => { | 593 | .Int => { |
| 593 | const int_info = ty.intInfo(target); | 594 | const int_info = ty.intInfo(target); |
| ... | @@ -627,7 +628,6 @@ pub const DeclGen = struct { | ... | @@ -627,7 +628,6 @@ pub const DeclGen = struct { |
| 627 | payload.* = .{ | 628 | payload.* = .{ |
| 628 | .element_type = try self.resolveType(elem_ty), | 629 | .element_type = try self.resolveType(elem_ty), |
| 629 | .length = total_len, | 630 | .length = total_len, |
| 630 | .array_stride = @intCast(u32, ty.abiSize(target)), | | |
| 631 | }; | 631 | }; |
| 632 | return try self.spv.resolveType(SpvType.initPayload(&payload.base)); | 632 | return try self.spv.resolveType(SpvType.initPayload(&payload.base)); |
| 633 | }, | 633 | }, |
| ... | @@ -654,29 +654,18 @@ pub const DeclGen = struct { | ... | @@ -654,29 +654,18 @@ pub const DeclGen = struct { |
| 654 | ptr_payload.* = .{ | 654 | ptr_payload.* = .{ |
| 655 | .storage_class = spirvStorageClass(ptr_info.@"addrspace"), | 655 | .storage_class = spirvStorageClass(ptr_info.@"addrspace"), |
| 656 | .child_type = try self.resolveType(ptr_info.pointee_type), | 656 | .child_type = try self.resolveType(ptr_info.pointee_type), |
| 657 | // TODO: ??? | | |
| 658 | .array_stride = 0, | | |
| 659 | // Note: only available in Kernels! | 657 | // Note: only available in Kernels! |
| 660 | .alignment = ty.ptrAlignment(target) * 8, | 658 | .alignment = ty.ptrAlignment(target) * 8, |
| 661 | .max_byte_offset = null, | | |
| 662 | }; | 659 | }; |
| 663 | const spv_ptr_ty = try self.spv.resolveType(SpvType.initPayload(&ptr_payload.base)); | 660 | const ptr_ty_id = try self.spv.resolveType(SpvType.initPayload(&ptr_payload.base)); |
| 664 | | 661 | |
| 665 | if (ptr_info.size != .Slice) { | 662 | if (ptr_info.size != .Slice) { |
| 666 | return spv_ptr_ty; | 663 | return ptr_ty_id; |
| 667 | } | 664 | } |
| 668 | | 665 | |
| 669 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | | |
| 670 | const ptr_ty = ty.slicePtrFieldType(&buf); | | |
| 671 | const len_ty = Type.usize; | | |
| 672 | | | |
| 673 | const ptr_size = ptr_ty.abiSize(target); | | |
| 674 | const len_align = len_ty.abiAlignment(target); | | |
| 675 | const len_offset = std.mem.alignForwardGeneric(u64, ptr_size, len_align); | | |
| 676 | | | |
| 677 | return try self.simpleStructType(&.{ | 666 | return try self.simpleStructType(&.{ |
| 678 | .{ .ty = spv_ptr_ty, .offset = 0 }, | 667 | .{ .ty = ptr_ty_id, .name = "ptr" }, |
| 679 | .{ .ty = try self.sizeType(), .offset = @intCast(u32, len_offset) }, | 668 | .{ .ty = try self.sizeType(), .name = "len" }, |
| 680 | }); | 669 | }); |
| 681 | }, | 670 | }, |
| 682 | .Vector => { | 671 | .Vector => { |
| ... | @@ -700,18 +689,15 @@ pub const DeclGen = struct { | ... | @@ -700,18 +689,15 @@ pub const DeclGen = struct { |
| 700 | if (ty.isSimpleTupleOrAnonStruct()) { | 689 | if (ty.isSimpleTupleOrAnonStruct()) { |
| 701 | const tuple = ty.tupleFields(); | 690 | const tuple = ty.tupleFields(); |
| 702 | const members = try self.spv.arena.alloc(SpvType.Payload.Struct.Member, tuple.types.len); | 691 | const members = try self.spv.arena.alloc(SpvType.Payload.Struct.Member, tuple.types.len); |
| 703 | var member_index: usize = 0; | 692 | var member_index: u32 = 0; |
| 704 | for (tuple.types) |field_ty, i| { | 693 | for (tuple.types) |field_ty, i| { |
| 705 | const field_val = tuple.values[i]; | 694 | const field_val = tuple.values[i]; |
| 706 | if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue; | 695 | if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBitsIgnoreComptime()) continue; |
| 707 | | | |
| 708 | members[member_index] = .{ | 696 | members[member_index] = .{ |
| 709 | .ty = try self.resolveType(field_ty), | 697 | .ty = try self.resolveType(field_ty), |
| 710 | .offset = 0, | | |
| 711 | }; | 698 | }; |
| 712 | member_index += 1; | 699 | member_index += 1; |
| 713 | } | 700 | } |
| 714 | | | |
| 715 | const payload = try self.spv.arena.create(SpvType.Payload.Struct); | 701 | const payload = try self.spv.arena.create(SpvType.Payload.Struct); |
| 716 | payload.* = .{ | 702 | payload.* = .{ |
| 717 | .members = members[0..member_index], | 703 | .members = members[0..member_index], |
| ... | @@ -727,18 +713,23 @@ pub const DeclGen = struct { | ... | @@ -727,18 +713,23 @@ pub const DeclGen = struct { |
| 727 | | 713 | |
| 728 | const members = try self.spv.arena.alloc(SpvType.Payload.Struct.Member, struct_ty.fields.count()); | 714 | const members = try self.spv.arena.alloc(SpvType.Payload.Struct.Member, struct_ty.fields.count()); |
| 729 | var member_index: usize = 0; | 715 | var member_index: usize = 0; |
| 730 | for (struct_ty.fields.values()) |field| { | 716 | for (struct_ty.fields.values()) |field, i| { |
| 731 | if (field.is_comptime or !field.ty.hasRuntimeBits()) continue; | 717 | if (field.is_comptime or !field.ty.hasRuntimeBits()) continue; |
| 732 | | 718 | |
| 733 | members[member_index] = .{ | 719 | members[member_index] = .{ |
| 734 | .ty = try self.resolveType(field.ty), | 720 | .ty = try self.resolveType(field.ty), |
| 735 | .offset = field.offset, | 721 | .name = struct_ty.fields.keys()[i], |
| 736 | }; | 722 | }; |
| | 723 | member_index += 1; |
| 737 | } | 724 | } |
| 738 | | 725 | |
| | 726 | const name = try struct_ty.getFullyQualifiedName(self.module); |
| | 727 | defer self.module.gpa.free(name); |
| | 728 | |
| 739 | const payload = try self.spv.arena.create(SpvType.Payload.Struct); | 729 | const payload = try self.spv.arena.create(SpvType.Payload.Struct); |
| 740 | payload.* = .{ | 730 | payload.* = .{ |
| 741 | .members = members[0..member_index], | 731 | .members = members[0..member_index], |
| | 732 | .name = try self.spv.arena.dupe(u8, name), |
| 742 | }; | 733 | }; |
| 743 | return try self.spv.resolveType(SpvType.initPayload(&payload.base)); | 734 | return try self.spv.resolveType(SpvType.initPayload(&payload.base)); |
| 744 | }, | 735 | }, |
| ... | @@ -808,6 +799,14 @@ pub const DeclGen = struct { | ... | @@ -808,6 +799,14 @@ pub const DeclGen = struct { |
| 808 | // Append the actual code into the functions section. | 799 | // Append the actual code into the functions section. |
| 809 | try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {}); | 800 | try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {}); |
| 810 | try self.spv.addFunction(self.func); | 801 | try self.spv.addFunction(self.func); |
| | 802 | |
| | 803 | const fqn = try decl.getFullyQualifiedName(self.module); |
| | 804 | defer self.module.gpa.free(fqn); |
| | 805 | |
| | 806 | try self.spv.sections.debug_names.emit(self.gpa, .OpName, .{ |
| | 807 | .target = result_id.toRef(), |
| | 808 | .name = fqn, |
| | 809 | }); |
| 811 | } else { | 810 | } else { |
| 812 | // TODO | 811 | // TODO |
| 813 | // return self.todo("generate decl type {}", .{decl.ty.zigTypeTag()}); | 812 | // return self.todo("generate decl type {}", .{decl.ty.zigTypeTag()}); |
| ... | @@ -1053,8 +1052,6 @@ pub const DeclGen = struct { | ... | @@ -1053,8 +1052,6 @@ pub const DeclGen = struct { |
| 1053 | fn airOverflowArithOp(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { | 1052 | fn airOverflowArithOp(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 1054 | if (self.liveness.isUnused(inst)) return null; | 1053 | if (self.liveness.isUnused(inst)) return null; |
| 1055 | | 1054 | |
| 1056 | const target = self.getTarget(); | | |
| 1057 | | | |
| 1058 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 1055 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1059 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | 1056 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 1060 | const lhs = try self.resolve(extra.lhs); | 1057 | const lhs = try self.resolve(extra.lhs); |
| ... | @@ -1082,8 +1079,8 @@ pub const DeclGen = struct { | ... | @@ -1082,8 +1079,8 @@ pub const DeclGen = struct { |
| 1082 | // It is almost the same as the zig one, except that the fields must be the same type | 1079 | // It is almost the same as the zig one, except that the fields must be the same type |
| 1083 | // and they must be unsigned. | 1080 | // and they must be unsigned. |
| 1084 | const overflow_result_ty = try self.simpleStructTypeId(&.{ | 1081 | const overflow_result_ty = try self.simpleStructTypeId(&.{ |
| 1085 | .{ .ty = overflow_member_ty, .offset = 0 }, | 1082 | .{ .ty = overflow_member_ty, .name = "res" }, |
| 1086 | .{ .ty = overflow_member_ty, .offset = @intCast(u32, operand_ty.abiSize(target)) }, | 1083 | .{ .ty = overflow_member_ty, .name = "ov" }, |
| 1087 | }); | 1084 | }); |
| 1088 | const result_id = self.spv.allocId(); | 1085 | const result_id = self.spv.allocId(); |
| 1089 | try self.func.body.emit(self.spv.gpa, .OpIAddCarry, .{ | 1086 | try self.func.body.emit(self.spv.gpa, .OpIAddCarry, .{ |
| ... | @@ -1098,7 +1095,7 @@ pub const DeclGen = struct { | ... | @@ -1098,7 +1095,7 @@ pub const DeclGen = struct { |
| 1098 | // Now convert the SPIR-V flavor result into a Zig-flavor result. | 1095 | // Now convert the SPIR-V flavor result into a Zig-flavor result. |
| 1099 | // First, extract the two fields. | 1096 | // First, extract the two fields. |
| 1100 | const unsigned_result = try self.extractField(overflow_member_ty_id, op_result_id, 0); | 1097 | const unsigned_result = try self.extractField(overflow_member_ty_id, op_result_id, 0); |
| 1101 | const overflow = try self.extractField(overflow_member_ty_id, op_result_id, 0); | 1098 | const overflow = try self.extractField(overflow_member_ty_id, op_result_id, 1); |
| 1102 | | 1099 | |
| 1103 | // We need to convert the results to the types that Zig expects here. | 1100 | // We need to convert the results to the types that Zig expects here. |
| 1104 | // The `result` is the same type except unsigned, so we can just bitcast that. | 1101 | // The `result` is the same type except unsigned, so we can just bitcast that. |
| ... | @@ -1190,8 +1187,9 @@ pub const DeclGen = struct { | ... | @@ -1190,8 +1187,9 @@ pub const DeclGen = struct { |
| 1190 | .float => 0, | 1187 | .float => 0, |
| 1191 | .bool => 1, | 1188 | .bool => 1, |
| 1192 | .strange_integer => blk: { | 1189 | .strange_integer => blk: { |
| 1193 | lhs_id = try self.maskStrangeInt(result_type_id, lhs_id, info.bits); | 1190 | const op_ty_id = try self.resolveTypeId(op_ty); |
| 1194 | rhs_id = try self.maskStrangeInt(result_type_id, rhs_id, info.bits); | 1191 | lhs_id = try self.maskStrangeInt(op_ty_id, lhs_id, info.bits); |
| | 1192 | rhs_id = try self.maskStrangeInt(op_ty_id, rhs_id, info.bits); |
| 1195 | break :blk switch (info.signedness) { | 1193 | break :blk switch (info.signedness) { |
| 1196 | .signed => @as(usize, 1), | 1194 | .signed => @as(usize, 1), |
| 1197 | .unsigned => @as(usize, 2), | 1195 | .unsigned => @as(usize, 2), |
| ... | @@ -1437,7 +1435,7 @@ pub const DeclGen = struct { | ... | @@ -1437,7 +1435,7 @@ pub const DeclGen = struct { |
| 1437 | else => { | 1435 | else => { |
| 1438 | const field_index_id = self.spv.allocId(); | 1436 | const field_index_id = self.spv.allocId(); |
| 1439 | const u32_ty_id = self.spv.typeResultId(try self.intType(.unsigned, 32)); | 1437 | const u32_ty_id = self.spv.typeResultId(try self.intType(.unsigned, 32)); |
| 1440 | try self.func.body.emit(self.spv.gpa, .OpConstant, .{ | 1438 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpConstant, .{ |
| 1441 | .id_result_type = u32_ty_id, | 1439 | .id_result_type = u32_ty_id, |
| 1442 | .id_result = field_index_id, | 1440 | .id_result = field_index_id, |
| 1443 | .value = .{ .uint32 = field_index }, | 1441 | .value = .{ .uint32 = field_index }, |
| ... | @@ -1632,7 +1630,6 @@ pub const DeclGen = struct { | ... | @@ -1632,7 +1630,6 @@ pub const DeclGen = struct { |
| 1632 | } | 1630 | } |
| 1633 | | 1631 | |
| 1634 | fn airRet(self: *DeclGen, inst: Air.Inst.Index) !void { | 1632 | fn airRet(self: *DeclGen, inst: Air.Inst.Index) !void { |
| 1635 | if (self.liveness.isUnused(inst)) return; | | |
| 1636 | const operand = self.air.instructions.items(.data)[inst].un_op; | 1633 | const operand = self.air.instructions.items(.data)[inst].un_op; |
| 1637 | const operand_ty = self.air.typeOf(operand); | 1634 | const operand_ty = self.air.typeOf(operand); |
| 1638 | if (operand_ty.hasRuntimeBits()) { | 1635 | if (operand_ty.hasRuntimeBits()) { |