aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/spirv.zig51
1 files changed, 47 insertions, 4 deletions
diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig
index 2c9018463d..ded73d6afd 100644
--- a/src/codegen/spirv.zig
+++ b/src/codegen/spirv.zig
@@ -2012,6 +2012,7 @@ const DeclGen = struct {
.array_to_slice => try self.airArrayToSlice(inst),
.slice => try self.airSlice(inst),
.aggregate_init => try self.airAggregateInit(inst),
+ .memcpy => return self.airMemcpy(inst),
.slice_ptr => try self.airSliceField(inst, 0),
.slice_len => try self.airSliceField(inst, 1),
@@ -2021,7 +2022,7 @@ const DeclGen = struct {
.ptr_elem_val => try self.airPtrElemVal(inst),
.array_elem_val => try self.airArrayElemVal(inst),
- .set_union_tag => return try self.airSetUnionTag(inst),
+ .set_union_tag => return self.airSetUnionTag(inst),
.get_union_tag => try self.airGetUnionTag(inst),
.union_init => try self.airUnionInit(inst),
@@ -3159,6 +3160,46 @@ const DeclGen = struct {
}
}
+ fn sliceOrArrayLen(self: *DeclGen, operand_id: IdRef, ty: Type) !IdRef {
+ const mod = self.module;
+ switch (ty.ptrSize(mod)) {
+ .Slice => return self.extractField(Type.usize, operand_id, 1),
+ .One => {
+ const array_ty = ty.childType(mod);
+ const elem_ty = array_ty.childType(mod);
+ const abi_size = elem_ty.abiSize(mod);
+ const usize_ty_ref = try self.resolveType(Type.usize, .direct);
+ return self.spv.constInt(usize_ty_ref, array_ty.arrayLenIncludingSentinel(mod) * abi_size);
+ },
+ .Many, .C => unreachable,
+ }
+ }
+
+ fn sliceOrArrayPtr(self: *DeclGen, operand_id: IdRef, ty: Type) !IdRef {
+ const mod = self.module;
+ if (ty.isSlice(mod)) {
+ const ptr_ty = ty.slicePtrFieldType(mod);
+ return self.extractField(ptr_ty, operand_id, 0);
+ }
+ return operand_id;
+ }
+
+ fn airMemcpy(self: *DeclGen, inst: Air.Inst.Index) !void {
+ const bin_op = self.air.instructions.items(.data)[inst].bin_op;
+ const dest_slice = try self.resolve(bin_op.lhs);
+ const src_slice = try self.resolve(bin_op.rhs);
+ const dest_ty = self.typeOf(bin_op.lhs);
+ const src_ty = self.typeOf(bin_op.rhs);
+ const dest_ptr = try self.sliceOrArrayPtr(dest_slice, dest_ty);
+ const src_ptr = try self.sliceOrArrayPtr(src_slice, src_ty);
+ const len = try self.sliceOrArrayLen(dest_slice, dest_ty);
+ try self.func.body.emit(self.spv.gpa, .OpCopyMemorySized, .{
+ .target = dest_ptr,
+ .source = src_ptr,
+ .size = len,
+ });
+ }
+
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;
@@ -4098,11 +4139,13 @@ const DeclGen = struct {
fn airSwitchBr(self: *DeclGen, inst: Air.Inst.Index) !void {
const mod = self.module;
const pl_op = self.air.instructions.items(.data)[inst].pl_op;
- const cond = try self.resolve(pl_op.operand);
const cond_ty = self.typeOf(pl_op.operand);
+ const cond = try self.resolve(pl_op.operand);
+ const cond_indirect = try self.convertToIndirect(cond_ty, cond);
const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);
const cond_words: u32 = switch (cond_ty.zigTypeTag(mod)) {
+ .Bool => 1,
.Int => blk: {
const bits = cond_ty.intInfo(mod).bits;
const backing_bits = self.backingIntBits(bits) orelse {
@@ -4146,7 +4189,7 @@ const DeclGen = struct {
// Emit the instruction before generating the blocks.
try self.func.body.emitRaw(self.spv.gpa, .OpSwitch, 2 + (cond_words + 1) * num_conditions);
- self.func.body.writeOperand(IdRef, cond);
+ self.func.body.writeOperand(IdRef, cond_indirect);
self.func.body.writeOperand(IdRef, default);
// Emit each of the cases
@@ -4167,7 +4210,7 @@ const DeclGen = struct {
return self.todo("switch on runtime value???", .{});
};
const int_val = switch (cond_ty.zigTypeTag(mod)) {
- .Int => if (cond_ty.isSignedInt(mod)) @as(u64, @bitCast(value.toSignedInt(mod))) else value.toUnsignedInt(mod),
+ .Bool, .Int => if (cond_ty.isSignedInt(mod)) @as(u64, @bitCast(value.toSignedInt(mod))) else value.toUnsignedInt(mod),
.Enum => blk: {
// TODO: figure out of cond_ty is correct (something with enum literals)
break :blk (try value.intFromEnum(cond_ty, mod)).toUnsignedInt(mod); // TODO: composite integer constants