aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/spirv.zig97
1 files changed, 94 insertions, 3 deletions
diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig
index 82f156fc99..9ef44a18ba 100644
--- a/src/codegen/spirv.zig
+++ b/src/codegen/spirv.zig
@@ -717,8 +717,12 @@ pub const DeclGen = struct {
.bool_and => try self.airBinOpSimple(inst, .OpLogicalAnd),
.bool_or => try self.airBinOpSimple(inst, .OpLogicalOr),
- .bitcast => try self.airBitcast(inst),
- .not => try self.airNot(inst),
+ .bitcast => try self.airBitcast(inst),
+ .not => try self.airNot(inst),
+ .slice_ptr => try self.airSliceField(inst, 0),
+ .slice_len => try self.airSliceField(inst, 1),
+ .slice_elem_ptr => try self.airSliceElemPtr(inst),
+ .slice_elem_val => try self.airSliceElemVal(inst),
.cmp_eq => try self.airCmp(inst, .OpFOrdEqual, .OpLogicalEqual, .OpIEqual),
.cmp_neq => try self.airCmp(inst, .OpFOrdNotEqual, .OpLogicalNotEqual, .OpINotEqual),
@@ -924,7 +928,7 @@ pub const DeclGen = struct {
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
const operand_id = try self.resolve(ty_op.operand);
const result_id = self.spv.allocId();
- const result_type_id = try self.resolveTypeId(Type.initTag(.bool));
+ const result_type_id = try self.resolveTypeId(self.air.typeOfIndex(inst));
try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
.id_result_type = result_type_id,
.id_result = result_id,
@@ -947,6 +951,93 @@ pub const DeclGen = struct {
return result_id.toRef();
}
+ fn airSliceField(self: *DeclGen, inst: Air.Inst.Index, field: u32) !?IdRef {
+ if (self.liveness.isUnused(inst)) return null;
+ const ty_op = self.air.instructions.items(.data)[inst].ty_op;
+ const result_id = self.spv.allocId();
+ try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{
+ .id_result_type = try self.resolveTypeId(self.air.typeOfIndex(inst)),
+ .id_result = result_id,
+ .composite = try self.resolve(ty_op.operand),
+ .indexes = &.{field},
+ });
+ return result_id.toRef();
+ }
+
+ fn airSliceElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
+ const bin_op = self.air.instructions.items(.data)[inst].bin_op;
+ const slice_ty = self.air.typeOf(bin_op.lhs);
+ if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null;
+
+ const slice = try self.resolve(bin_op.lhs);
+ const index = try self.resolve(bin_op.rhs);
+
+ const spv_ptr_ty = try self.resolveTypeId(self.air.typeOfIndex(inst));
+
+ const slice_ptr = blk: {
+ const result_id = self.spv.allocId();
+ try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{
+ .id_result_type = spv_ptr_ty,
+ .id_result = result_id,
+ .composite = slice,
+ .indexes = &.{0},
+ });
+ break :blk result_id.toRef();
+ };
+
+ const result_id = self.spv.allocId();
+ try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{
+ .id_result_type = spv_ptr_ty,
+ .id_result = result_id,
+ .base = slice_ptr,
+ .indexes = &.{index},
+ });
+ return result_id.toRef();
+ }
+
+ fn airSliceElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
+ const bin_op = self.air.instructions.items(.data)[inst].bin_op;
+ const slice_ty = self.air.typeOf(bin_op.lhs);
+ if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null;
+
+ const slice = try self.resolve(bin_op.lhs);
+ const index = try self.resolve(bin_op.rhs);
+
+ const spv_elem_ty = try self.resolveTypeId(self.air.typeOfIndex(inst));
+ var slice_buf: Type.SlicePtrFieldTypeBuffer = undefined;
+ const spv_ptr_ty = try self.resolveTypeId(slice_ty.slicePtrFieldType(&slice_buf));
+
+ const slice_ptr = blk: {
+ const result_id = self.spv.allocId();
+ try self.func.body.emit(self.spv.gpa, .OpCompositeExtract, .{
+ .id_result_type = spv_ptr_ty,
+ .id_result = result_id,
+ .composite = slice,
+ .indexes = &.{0},
+ });
+ break :blk result_id.toRef();
+ };
+
+ const elem_ptr = blk: {
+ const result_id = self.spv.allocId();
+ try self.func.body.emit(self.spv.gpa, .OpInBoundsAccessChain, .{
+ .id_result_type = spv_ptr_ty,
+ .id_result = result_id,
+ .base = slice_ptr,
+ .indexes = &.{index},
+ });
+ break :blk result_id.toRef();
+ };
+
+ const result_id = self.spv.allocId();
+ try self.func.body.emit(self.spv.gpa, .OpLoad, .{
+ .id_result_type = spv_elem_ty,
+ .id_result = result_id,
+ .pointer = elem_ptr,
+ });
+ return result_id.toRef();
+ }
+
fn airAlloc(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
if (self.liveness.isUnused(inst)) return null;
const ty = self.air.typeOfIndex(inst);