aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/spirv/Assembler.zig
diff options
context:
space:
mode:
authorLoris Cro <kappaloris@gmail.com>2023-06-18 09:06:40 +0200
committerGitHub <noreply@github.com>2023-06-18 09:06:40 +0200
commit216ef10dc471e4db60a30208be178d6c59efeaaf (patch)
tree8c239dab283ae9cb3b7fe099bae240bcc53f894e /src/codegen/spirv/Assembler.zig
parent0fc1d396495c1ab482197021dedac8bea3f9401c (diff)
parent729a051e9e38674233190aea23c0ac8c134f2d67 (diff)
downloadzig-216ef10dc471e4db60a30208be178d6c59efeaaf.tar.gz
zig-216ef10dc471e4db60a30208be178d6c59efeaaf.zip
Merge branch 'master' into autodoc-searchkey
Diffstat (limited to 'src/codegen/spirv/Assembler.zig')
-rw-r--r--src/codegen/spirv/Assembler.zig170
1 files changed, 36 insertions, 134 deletions
diff --git a/src/codegen/spirv/Assembler.zig b/src/codegen/spirv/Assembler.zig
index eebf43866d..c7848bbc92 100644
--- a/src/codegen/spirv/Assembler.zig
+++ b/src/codegen/spirv/Assembler.zig
@@ -11,7 +11,8 @@ const IdRef = spec.IdRef;
const IdResult = spec.IdResult;
const SpvModule = @import("Module.zig");
-const SpvType = @import("type.zig").Type;
+const CacheRef = SpvModule.CacheRef;
+const CacheKey = SpvModule.CacheKey;
/// Represents a token in the assembly template.
const Token = struct {
@@ -126,7 +127,7 @@ const AsmValue = union(enum) {
value: IdRef,
/// This result-value represents a type registered into the module's type system.
- ty: SpvType.Ref,
+ ty: CacheRef,
/// Retrieve the result-id of this AsmValue. Asserts that this AsmValue
/// is of a variant that allows the result to be obtained (not an unresolved
@@ -135,7 +136,7 @@ const AsmValue = union(enum) {
return switch (self) {
.just_declared, .unresolved_forward_reference => unreachable,
.value => |result| result,
- .ty => |ref| spv.typeId(ref),
+ .ty => |ref| spv.resultId(ref),
};
}
};
@@ -267,9 +268,9 @@ fn processInstruction(self: *Assembler) !void {
/// refers to the result.
fn processTypeInstruction(self: *Assembler) !AsmValue {
const operands = self.inst.operands.items;
- const ty = switch (self.inst.opcode) {
- .OpTypeVoid => SpvType.initTag(.void),
- .OpTypeBool => SpvType.initTag(.bool),
+ const ref = switch (self.inst.opcode) {
+ .OpTypeVoid => try self.spv.resolve(.void_type),
+ .OpTypeBool => try self.spv.resolve(.bool_type),
.OpTypeInt => blk: {
const signedness: std.builtin.Signedness = switch (operands[2].literal32) {
0 => .unsigned,
@@ -282,7 +283,7 @@ fn processTypeInstruction(self: *Assembler) !AsmValue {
const width = std.math.cast(u16, operands[1].literal32) orelse {
return self.fail(0, "int type of {} bits is too large", .{operands[1].literal32});
};
- break :blk try SpvType.int(self.spv.arena, signedness, width);
+ break :blk try self.spv.intType(signedness, width);
},
.OpTypeFloat => blk: {
const bits = operands[1].literal32;
@@ -292,136 +293,36 @@ fn processTypeInstruction(self: *Assembler) !AsmValue {
return self.fail(0, "{} is not a valid bit count for floats (expected 16, 32 or 64)", .{bits});
},
}
- break :blk SpvType.float(@intCast(u16, bits));
- },
- .OpTypeVector => blk: {
- const payload = try self.spv.arena.create(SpvType.Payload.Vector);
- payload.* = .{
- .component_type = try self.resolveTypeRef(operands[1].ref_id),
- .component_count = operands[2].literal32,
- };
- break :blk SpvType.initPayload(&payload.base);
- },
- .OpTypeMatrix => blk: {
- const payload = try self.spv.arena.create(SpvType.Payload.Matrix);
- payload.* = .{
- .column_type = try self.resolveTypeRef(operands[1].ref_id),
- .column_count = operands[2].literal32,
- };
- break :blk SpvType.initPayload(&payload.base);
- },
- .OpTypeImage => blk: {
- const payload = try self.spv.arena.create(SpvType.Payload.Image);
- payload.* = .{
- .sampled_type = try self.resolveTypeRef(operands[1].ref_id),
- .dim = @intToEnum(spec.Dim, operands[2].value),
- .depth = switch (operands[3].literal32) {
- 0 => .no,
- 1 => .yes,
- 2 => .maybe,
- else => {
- return self.fail(0, "'{}' is not a valid image depth (expected 0, 1 or 2)", .{operands[3].literal32});
- },
- },
- .arrayed = switch (operands[4].literal32) {
- 0 => false,
- 1 => true,
- else => {
- return self.fail(0, "'{}' is not a valid image arrayed-ness (expected 0 or 1)", .{operands[4].literal32});
- },
- },
- .multisampled = switch (operands[5].literal32) {
- 0 => false,
- 1 => true,
- else => {
- return self.fail(0, "'{}' is not a valid image multisampled-ness (expected 0 or 1)", .{operands[5].literal32});
- },
- },
- .sampled = switch (operands[6].literal32) {
- 0 => .known_at_runtime,
- 1 => .with_sampler,
- 2 => .without_sampler,
- else => {
- return self.fail(0, "'{}' is not a valid image sampled-ness (expected 0, 1 or 2)", .{operands[6].literal32});
- },
- },
- .format = @intToEnum(spec.ImageFormat, operands[7].value),
- .access_qualifier = if (operands.len > 8)
- @intToEnum(spec.AccessQualifier, operands[8].value)
- else
- null,
- };
- break :blk SpvType.initPayload(&payload.base);
- },
- .OpTypeSampler => SpvType.initTag(.sampler),
- .OpTypeSampledImage => blk: {
- const payload = try self.spv.arena.create(SpvType.Payload.SampledImage);
- payload.* = .{
- .image_type = try self.resolveTypeRef(operands[1].ref_id),
- };
- break :blk SpvType.initPayload(&payload.base);
+ break :blk try self.spv.resolve(.{ .float_type = .{ .bits = @intCast(u16, bits) } });
},
+ .OpTypeVector => try self.spv.resolve(.{ .vector_type = .{
+ .component_type = try self.resolveTypeRef(operands[1].ref_id),
+ .component_count = operands[2].literal32,
+ } }),
.OpTypeArray => {
// TODO: The length of an OpTypeArray is determined by a constant (which may be a spec constant),
// and so some consideration must be taken when entering this in the type system.
return self.todo("process OpTypeArray", .{});
},
- .OpTypeRuntimeArray => blk: {
- const payload = try self.spv.arena.create(SpvType.Payload.RuntimeArray);
- payload.* = .{
- .element_type = try self.resolveTypeRef(operands[1].ref_id),
- // TODO: Fetch array stride from decorations.
- .array_stride = 0,
- };
- break :blk SpvType.initPayload(&payload.base);
- },
- .OpTypeOpaque => blk: {
- const payload = try self.spv.arena.create(SpvType.Payload.Opaque);
- const name_offset = operands[1].string;
- payload.* = .{
- .name = std.mem.sliceTo(self.inst.string_bytes.items[name_offset..], 0),
- };
- break :blk SpvType.initPayload(&payload.base);
- },
- .OpTypePointer => blk: {
- const payload = try self.spv.arena.create(SpvType.Payload.Pointer);
- payload.* = .{
- .storage_class = @intToEnum(spec.StorageClass, operands[1].value),
- .child_type = try self.resolveTypeRef(operands[2].ref_id),
- // TODO: Fetch decorations
- };
- break :blk SpvType.initPayload(&payload.base);
- },
+ .OpTypePointer => try self.spv.ptrType(
+ try self.resolveTypeRef(operands[2].ref_id),
+ @intToEnum(spec.StorageClass, operands[1].value),
+ ),
.OpTypeFunction => blk: {
const param_operands = operands[2..];
- const param_types = try self.spv.arena.alloc(SpvType.Ref, param_operands.len);
+ const param_types = try self.spv.gpa.alloc(CacheRef, param_operands.len);
+ defer self.spv.gpa.free(param_types);
for (param_types, 0..) |*param, i| {
param.* = try self.resolveTypeRef(param_operands[i].ref_id);
}
- const payload = try self.spv.arena.create(SpvType.Payload.Function);
- payload.* = .{
+ break :blk try self.spv.resolve(.{ .function_type = .{
.return_type = try self.resolveTypeRef(operands[1].ref_id),
.parameters = param_types,
- };
- break :blk SpvType.initPayload(&payload.base);
+ } });
},
- .OpTypeEvent => SpvType.initTag(.event),
- .OpTypeDeviceEvent => SpvType.initTag(.device_event),
- .OpTypeReserveId => SpvType.initTag(.reserve_id),
- .OpTypeQueue => SpvType.initTag(.queue),
- .OpTypePipe => blk: {
- const payload = try self.spv.arena.create(SpvType.Payload.Pipe);
- payload.* = .{
- .qualifier = @intToEnum(spec.AccessQualifier, operands[1].value),
- };
- break :blk SpvType.initPayload(&payload.base);
- },
- .OpTypePipeStorage => SpvType.initTag(.pipe_storage),
- .OpTypeNamedBarrier => SpvType.initTag(.named_barrier),
else => return self.todo("process type instruction {s}", .{@tagName(self.inst.opcode)}),
};
- const ref = try self.spv.resolveType(ty);
return AsmValue{ .ty = ref };
}
@@ -528,7 +429,7 @@ fn resolveRef(self: *Assembler, ref: AsmValue.Ref) !AsmValue {
}
/// Resolve a value reference as type.
-fn resolveTypeRef(self: *Assembler, ref: AsmValue.Ref) !SpvType.Ref {
+fn resolveTypeRef(self: *Assembler, ref: AsmValue.Ref) !CacheRef {
const value = try self.resolveRef(ref);
switch (value) {
.just_declared, .unresolved_forward_reference => unreachable,
@@ -761,19 +662,20 @@ fn parseContextDependentNumber(self: *Assembler) !void {
const tok = self.currentToken();
const result_type_ref = try self.resolveTypeRef(self.inst.operands.items[0].ref_id);
- const result_type = self.spv.type_cache.keys()[@enumToInt(result_type_ref)];
- if (result_type.isInt()) {
- try self.parseContextDependentInt(result_type.intSignedness(), result_type.intFloatBits());
- } else if (result_type.isFloat()) {
- const width = result_type.intFloatBits();
- switch (width) {
- 16 => try self.parseContextDependentFloat(16),
- 32 => try self.parseContextDependentFloat(32),
- 64 => try self.parseContextDependentFloat(64),
- else => return self.fail(tok.start, "cannot parse {}-bit float literal", .{width}),
- }
- } else {
- return self.fail(tok.start, "cannot parse literal constant {s}", .{@tagName(result_type.tag())});
+ const result_type = self.spv.cache.lookup(result_type_ref);
+ switch (result_type) {
+ .int_type => |int| {
+ try self.parseContextDependentInt(int.signedness, int.bits);
+ },
+ .float_type => |float| {
+ switch (float.bits) {
+ 16 => try self.parseContextDependentFloat(16),
+ 32 => try self.parseContextDependentFloat(32),
+ 64 => try self.parseContextDependentFloat(64),
+ else => return self.fail(tok.start, "cannot parse {}-bit float literal", .{float.bits}),
+ }
+ },
+ else => return self.fail(tok.start, "cannot parse literal constant", .{}),
}
}