diff options
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/spirv.zig | 51 |
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 |
