| ... | @@ -11,6 +11,7 @@ | ... | @@ -11,6 +11,7 @@ |
| 11 | //! vectors) must have a _unique_ representation in the final binary. | 11 | //! vectors) must have a _unique_ representation in the final binary. |
| 12 | | 12 | |
| 13 | const std = @import("std"); | 13 | const std = @import("std"); |
| | 14 | const assert = std.debug.assert; |
| 14 | const Allocator = std.mem.Allocator; | 15 | const Allocator = std.mem.Allocator; |
| 15 | | 16 | |
| 16 | const Section = @import("Section.zig"); | 17 | const Section = @import("Section.zig"); |
| ... | @@ -68,8 +69,11 @@ const Tag = enum { | ... | @@ -68,8 +69,11 @@ const Tag = enum { |
| 68 | /// data is child type | 69 | /// data is child type |
| 69 | type_ptr_function, | 70 | type_ptr_function, |
| 70 | /// Simple pointer type that does not have any decorations. | 71 | /// Simple pointer type that does not have any decorations. |
| 71 | /// data is SimplePointerType | 72 | /// data is payload to SimplePointerType |
| 72 | type_ptr_simple, | 73 | type_ptr_simple, |
| | 74 | /// Simple structure type that does not have any decorations. |
| | 75 | /// data is payload to SimpleStructType |
| | 76 | type_struct_simple, |
| 73 | | 77 | |
| 74 | // -- Values | 78 | // -- Values |
| 75 | /// Value of type u8 | 79 | /// Value of type u8 |
| ... | @@ -107,7 +111,7 @@ const Tag = enum { | ... | @@ -107,7 +111,7 @@ const Tag = enum { |
| 107 | const ArrayType = Key.ArrayType; | 111 | const ArrayType = Key.ArrayType; |
| 108 | | 112 | |
| 109 | // Trailing: | 113 | // Trailing: |
| 110 | // - [param_len]Ref: parameter types | 114 | // - [param_len]Ref: parameter types. |
| 111 | const FunctionType = struct { | 115 | const FunctionType = struct { |
| 112 | param_len: u32, | 116 | param_len: u32, |
| 113 | return_type: Ref, | 117 | return_type: Ref, |
| ... | @@ -118,6 +122,13 @@ const Tag = enum { | ... | @@ -118,6 +122,13 @@ const Tag = enum { |
| 118 | child_type: Ref, | 122 | child_type: Ref, |
| 119 | }; | 123 | }; |
| 120 | | 124 | |
| | 125 | /// Trailing: |
| | 126 | /// - [members_len]Ref: Member types. |
| | 127 | const SimpleStructType = struct { |
| | 128 | /// Number of members that this struct has. |
| | 129 | members_len: u32, |
| | 130 | }; |
| | 131 | |
| 121 | const Float64 = struct { | 132 | const Float64 = struct { |
| 122 | // Low-order 32 bits of the value. | 133 | // Low-order 32 bits of the value. |
| 123 | low: u32, | 134 | low: u32, |
| ... | @@ -201,6 +212,7 @@ pub const Key = union(enum) { | ... | @@ -201,6 +212,7 @@ pub const Key = union(enum) { |
| 201 | array_type: ArrayType, | 212 | array_type: ArrayType, |
| 202 | function_type: FunctionType, | 213 | function_type: FunctionType, |
| 203 | ptr_type: PointerType, | 214 | ptr_type: PointerType, |
| | 215 | struct_type: StructType, |
| 204 | | 216 | |
| 205 | // -- values | 217 | // -- values |
| 206 | int: Int, | 218 | int: Int, |
| ... | @@ -238,6 +250,12 @@ pub const Key = union(enum) { | ... | @@ -238,6 +250,12 @@ pub const Key = union(enum) { |
| 238 | // - MaxByteOffset, | 250 | // - MaxByteOffset, |
| 239 | }; | 251 | }; |
| 240 | | 252 | |
| | 253 | pub const StructType = struct { |
| | 254 | // TODO: Decorations. |
| | 255 | /// The type of each member. |
| | 256 | member_types: []const Ref, |
| | 257 | }; |
| | 258 | |
| 241 | pub const Int = struct { | 259 | pub const Int = struct { |
| 242 | /// The type: any bitness integer. | 260 | /// The type: any bitness integer. |
| 243 | ty: Ref, | 261 | ty: Ref, |
| ... | @@ -304,6 +322,11 @@ pub const Key = union(enum) { | ... | @@ -304,6 +322,11 @@ pub const Key = union(enum) { |
| 304 | std.hash.autoHash(&hasher, param_type); | 322 | std.hash.autoHash(&hasher, param_type); |
| 305 | } | 323 | } |
| 306 | }, | 324 | }, |
| | 325 | .struct_type => |struct_type| { |
| | 326 | for (struct_type.member_types) |member_type| { |
| | 327 | std.hash.autoHash(&hasher, member_type); |
| | 328 | } |
| | 329 | }, |
| 307 | inline else => |key| std.hash.autoHash(&hasher, key), | 330 | inline else => |key| std.hash.autoHash(&hasher, key), |
| 308 | } | 331 | } |
| 309 | return @truncate(u32, hasher.final()); | 332 | return @truncate(u32, hasher.final()); |
| ... | @@ -318,10 +341,14 @@ pub const Key = union(enum) { | ... | @@ -318,10 +341,14 @@ pub const Key = union(enum) { |
| 318 | } | 341 | } |
| 319 | return switch (a) { | 342 | return switch (a) { |
| 320 | .function_type => |a_func| { | 343 | .function_type => |a_func| { |
| 321 | const b_func = a.function_type; | 344 | const b_func = b.function_type; |
| 322 | return a_func.return_type == b_func.return_type and | 345 | return a_func.return_type == b_func.return_type and |
| 323 | std.mem.eql(Ref, a_func.parameters, b_func.parameters); | 346 | std.mem.eql(Ref, a_func.parameters, b_func.parameters); |
| 324 | }, | 347 | }, |
| | 348 | .struct_type => |a_struct| { |
| | 349 | const b_struct = b.struct_type; |
| | 350 | return std.mem.eql(Ref, a_struct.member_types, b_struct.member_types); |
| | 351 | }, |
| 325 | // TODO: Unroll? | 352 | // TODO: Unroll? |
| 326 | else => std.meta.eql(a, b), | 353 | else => std.meta.eql(a, b), |
| 327 | }; | 354 | }; |
| ... | @@ -442,6 +469,14 @@ fn emit( | ... | @@ -442,6 +469,14 @@ fn emit( |
| 442 | }); | 469 | }); |
| 443 | // TODO: Decorations? | 470 | // TODO: Decorations? |
| 444 | }, | 471 | }, |
| | 472 | .struct_type => |struct_type| { |
| | 473 | try section.emitRaw(spv.gpa, .OpTypeStruct, 1 + struct_type.member_types.len); |
| | 474 | section.writeOperand(IdResult, result_id); |
| | 475 | for (struct_type.member_types) |member_type| { |
| | 476 | section.writeOperand(IdResult, self.resultId(member_type)); |
| | 477 | } |
| | 478 | // TODO: Decorations? |
| | 479 | }, |
| 445 | .int => |int| { | 480 | .int => |int| { |
| 446 | const int_type = self.lookup(int.ty).int_type; | 481 | const int_type = self.lookup(int.ty).int_type; |
| 447 | const ty_id = self.resultId(int.ty); | 482 | const ty_id = self.resultId(int.ty); |
| ... | @@ -552,6 +587,18 @@ pub fn resolve(self: *Self, spv: *Module, key: Key) !Ref { | ... | @@ -552,6 +587,18 @@ pub fn resolve(self: *Self, spv: *Module, key: Key) !Ref { |
| 552 | }), | 587 | }), |
| 553 | }, | 588 | }, |
| 554 | }, | 589 | }, |
| | 590 | .struct_type => |struct_type| blk: { |
| | 591 | const extra = try self.addExtra(spv, Tag.SimpleStructType{ |
| | 592 | .members_len = @intCast(u32, struct_type.member_types.len), |
| | 593 | }); |
| | 594 | try self.extra.appendSlice(spv.gpa, @ptrCast([]const u32, struct_type.member_types)); |
| | 595 | |
| | 596 | break :blk Item{ |
| | 597 | .tag = .type_struct_simple, |
| | 598 | .result_id = result_id, |
| | 599 | .data = extra, |
| | 600 | }; |
| | 601 | }, |
| 555 | .int => |int| blk: { | 602 | .int => |int| blk: { |
| 556 | const int_type = self.lookup(int.ty).int_type; | 603 | const int_type = self.lookup(int.ty).int_type; |
| 557 | if (int_type.signedness == .unsigned and int_type.bits == 8) { | 604 | if (int_type.signedness == .unsigned and int_type.bits == 8) { |
| ... | @@ -687,6 +734,15 @@ pub fn lookup(self: *const Self, ref: Ref) Key { | ... | @@ -687,6 +734,15 @@ pub fn lookup(self: *const Self, ref: Ref) Key { |
| 687 | }, | 734 | }, |
| 688 | }; | 735 | }; |
| 689 | }, | 736 | }, |
| | 737 | .type_struct_simple => { |
| | 738 | const payload = self.extraDataTrail(Tag.SimpleStructType, data); |
| | 739 | const member_types = @ptrCast([]const Ref, self.extra.items[payload.trail..][0..payload.data.members_len]); |
| | 740 | return .{ |
| | 741 | .struct_type = .{ |
| | 742 | .member_types = member_types, |
| | 743 | }, |
| | 744 | }; |
| | 745 | }, |
| 690 | .float16 => .{ .float = .{ | 746 | .float16 => .{ .float = .{ |
| 691 | .ty = self.get(.{ .float_type = .{ .bits = 16 } }), | 747 | .ty = self.get(.{ .float_type = .{ .bits = 16 } }), |
| 692 | .value = .{ .float16 = @bitCast(f16, @intCast(u16, data)) }, | 748 | .value = .{ .float16 = @bitCast(f16, @intCast(u16, data)) }, |