| ... | ... | @@ -11,6 +11,7 @@ |
| 11 | 11 | //! vectors) must have a _unique_ representation in the final binary. |
| 12 | 12 | |
| 13 | 13 | const std = @import("std"); |
| 14 | const assert = std.debug.assert; |
| 14 | 15 | const Allocator = std.mem.Allocator; |
| 15 | 16 | |
| 16 | 17 | const Section = @import("Section.zig"); |
| ... | ... | @@ -68,8 +69,11 @@ const Tag = enum { |
| 68 | 69 | /// data is child type |
| 69 | 70 | type_ptr_function, |
| 70 | 71 | /// Simple pointer type that does not have any decorations. |
| 71 | | /// data is SimplePointerType |
| 72 | /// data is payload to SimplePointerType |
| 72 | 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 | 78 | // -- Values |
| 75 | 79 | /// Value of type u8 |
| ... | ... | @@ -107,7 +111,7 @@ const Tag = enum { |
| 107 | 111 | const ArrayType = Key.ArrayType; |
| 108 | 112 | |
| 109 | 113 | // Trailing: |
| 110 | | // - [param_len]Ref: parameter types |
| 114 | // - [param_len]Ref: parameter types. |
| 111 | 115 | const FunctionType = struct { |
| 112 | 116 | param_len: u32, |
| 113 | 117 | return_type: Ref, |
| ... | ... | @@ -118,6 +122,13 @@ const Tag = enum { |
| 118 | 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 | 132 | const Float64 = struct { |
| 122 | 133 | // Low-order 32 bits of the value. |
| 123 | 134 | low: u32, |
| ... | ... | @@ -201,6 +212,7 @@ pub const Key = union(enum) { |
| 201 | 212 | array_type: ArrayType, |
| 202 | 213 | function_type: FunctionType, |
| 203 | 214 | ptr_type: PointerType, |
| 215 | struct_type: StructType, |
| 204 | 216 | |
| 205 | 217 | // -- values |
| 206 | 218 | int: Int, |
| ... | ... | @@ -238,6 +250,12 @@ pub const Key = union(enum) { |
| 238 | 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 | 259 | pub const Int = struct { |
| 242 | 260 | /// The type: any bitness integer. |
| 243 | 261 | ty: Ref, |
| ... | ... | @@ -304,6 +322,11 @@ pub const Key = union(enum) { |
| 304 | 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 | 330 | inline else => |key| std.hash.autoHash(&hasher, key), |
| 308 | 331 | } |
| 309 | 332 | return @truncate(u32, hasher.final()); |
| ... | ... | @@ -318,10 +341,14 @@ pub const Key = union(enum) { |
| 318 | 341 | } |
| 319 | 342 | return switch (a) { |
| 320 | 343 | .function_type => |a_func| { |
| 321 | | const b_func = a.function_type; |
| 344 | const b_func = b.function_type; |
| 322 | 345 | return a_func.return_type == b_func.return_type and |
| 323 | 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 | 352 | // TODO: Unroll? |
| 326 | 353 | else => std.meta.eql(a, b), |
| 327 | 354 | }; |
| ... | ... | @@ -442,6 +469,14 @@ fn emit( |
| 442 | 469 | }); |
| 443 | 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 | 480 | .int => |int| { |
| 446 | 481 | const int_type = self.lookup(int.ty).int_type; |
| 447 | 482 | const ty_id = self.resultId(int.ty); |
| ... | ... | @@ -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 | 602 | .int => |int| blk: { |
| 556 | 603 | const int_type = self.lookup(int.ty).int_type; |
| 557 | 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 | 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 | 746 | .float16 => .{ .float = .{ |
| 691 | 747 | .ty = self.get(.{ .float_type = .{ .bits = 16 } }), |
| 692 | 748 | .value = .{ .float16 = @bitCast(f16, @intCast(u16, data)) }, |