From 05c5c99a95c894d7e3241e1729e09aa7eacb6035 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Mon, 18 Oct 2021 01:00:07 +0200 Subject: [PATCH] stage2: air ptr_slice_len_ptr and ptr_slice_ptr_ptr --- src/Air.zig | 8 ++++++++ src/Liveness.zig | 2 ++ src/arch/aarch64/CodeGen.zig | 15 +++++++++++++++ src/codegen.zig | 19 +++++++++++++++++++ src/codegen/c.zig | 18 ++++++++++++++++++ src/codegen/llvm.zig | 13 +++++++++++++ src/print_air.zig | 2 ++ 7 files changed, 77 insertions(+) diff --git a/src/Air.zig b/src/Air.zig index 86e16487bb..f3e0865ba8 100644 --- a/src/Air.zig +++ b/src/Air.zig @@ -367,6 +367,12 @@ pub const Inst = struct { /// Given a slice value, return the pointer. /// Uses the `ty_op` field. slice_ptr, + /// Given a pointer to a slice, return a pointer to the length of the slice. + /// Uses the `ty_op` field. + ptr_slice_len_ptr, + /// Given a pointer to a slice, return a pointer to the pointer of the slice. + /// Uses the `ty_op` field. + ptr_slice_ptr_ptr, /// Given an array value and element index, return the element value at that index. /// Result type is the element type of the array operand. /// Uses the `bin_op` field. @@ -707,6 +713,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { .wrap_errunion_payload, .wrap_errunion_err, .slice_ptr, + .ptr_slice_len_ptr, + .ptr_slice_ptr_ptr, .struct_field_ptr_index_0, .struct_field_ptr_index_1, .struct_field_ptr_index_2, diff --git a/src/Liveness.zig b/src/Liveness.zig index 6f7c938f4c..c56bcc8c09 100644 --- a/src/Liveness.zig +++ b/src/Liveness.zig @@ -300,6 +300,8 @@ fn analyzeInst( .wrap_errunion_err, .slice_ptr, .slice_len, + .ptr_slice_len_ptr, + .ptr_slice_ptr_ptr, .struct_field_ptr_index_0, .struct_field_ptr_index_1, .struct_field_ptr_index_2, diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 73ada3a9ca..34d9090224 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -494,6 +494,9 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .slice_ptr => try self.airSlicePtr(inst), .slice_len => try self.airSliceLen(inst), + .ptr_slice_len_ptr => try self.airPtrSliceLenPtr(inst), + .ptr_slice_ptr_ptr => try self.airPtrSlicePtrPtr(inst), + .array_elem_val => try self.airArrayElemVal(inst), .slice_elem_val => try self.airSliceElemVal(inst), .ptr_slice_elem_val => try self.airPtrSliceElemVal(inst), @@ -1057,6 +1060,18 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); } +fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void { + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement ptr_slice_len_ptr for {}", .{self.target.cpu.arch}); + return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); +} + +fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void { + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement ptr_slice_ptr_ptr for {}", .{self.target.cpu.arch}); + return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); +} + fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { const is_volatile = false; // TODO const bin_op = self.air.instructions.items(.data)[inst].bin_op; diff --git a/src/codegen.zig b/src/codegen.zig index 0371f32a8a..bedbdf44f1 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -842,6 +842,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { .slice_ptr => try self.airSlicePtr(inst), .slice_len => try self.airSliceLen(inst), + .ptr_slice_len_ptr => try self.airPtrSliceLenPtr(inst), + .ptr_slice_ptr_ptr => try self.airPtrSlicePtrPtr(inst), + .array_elem_val => try self.airArrayElemVal(inst), .slice_elem_val => try self.airSliceElemVal(inst), .ptr_slice_elem_val => try self.airPtrSliceElemVal(inst), @@ -1498,6 +1501,22 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); } + fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void { + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) { + else => return self.fail("TODO implement ptr_slice_len_ptr for {}", .{self.target.cpu.arch}), + }; + return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); + } + + fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void { + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) { + else => return self.fail("TODO implement ptr_slice_ptr_ptr for {}", .{self.target.cpu.arch}), + }; + return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); + } + fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { const is_volatile = false; // TODO const bin_op = self.air.instructions.items(.data)[inst].bin_op; diff --git a/src/codegen/c.zig b/src/codegen/c.zig index ad98dc87c1..1bb337743d 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1075,6 +1075,9 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO .slice_ptr => try airSliceField(f, inst, ".ptr;\n"), .slice_len => try airSliceField(f, inst, ".len;\n"), + .ptr_slice_len_ptr => try airPtrSliceFieldPtr(f, inst, ".len;\n"), + .ptr_slice_ptr_ptr => try airPtrSliceFieldPtr(f, inst, ".ptr;\n"), + .ptr_elem_val => try airPtrElemVal(f, inst, "["), .ptr_ptr_elem_val => try airPtrElemVal(f, inst, "[0]["), .ptr_elem_ptr => try airPtrElemPtr(f, inst), @@ -1114,6 +1117,21 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, suffix: []const u8) !CValue return local; } +fn airPtrSliceFieldPtr(f: *Function, inst: Air.Inst.Index, suffix: []const u8) !CValue { + if (f.liveness.isUnused(inst)) + return CValue.none; + + const ty_op = f.air.instructions.items(.data)[inst].ty_op; + const operand = try f.resolveInst(ty_op.operand); + const writer = f.object.writer(); + + _ = writer; + _ = operand; + _ = suffix; + + return f.fail("TODO: C backend: airPtrSliceFieldPtr", .{}); +} + fn airPtrElemVal(f: *Function, inst: Air.Inst.Index, prefix: []const u8) !CValue { const is_volatile = false; // TODO if (!is_volatile and f.liveness.isUnused(inst)) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 1a8a70c39b..8ec5075f84 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1709,6 +1709,10 @@ pub const FuncGen = struct { .assembly => try self.airAssembly(inst), .slice_ptr => try self.airSliceField(inst, 0), .slice_len => try self.airSliceField(inst, 1), + + .ptr_slice_ptr_ptr => try self.airPtrSliceFieldPtr(inst, 0), + .ptr_slice_len_ptr => try self.airPtrSliceFieldPtr(inst, 1), + .array_to_slice => try self.airArrayToSlice(inst), .float_to_int => try self.airFloatToInt(inst), .int_to_float => try self.airIntToFloat(inst), @@ -2091,6 +2095,15 @@ pub const FuncGen = struct { return self.builder.buildExtractValue(operand, index, ""); } + fn airPtrSliceFieldPtr(self: *FuncGen, inst: Air.Inst.Index, index: c_uint) !?*const llvm.Value { + if (self.liveness.isUnused(inst)) return null; + + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const slice_ptr = try self.resolveInst(ty_op.operand); + + return self.builder.buildStructGEP(slice_ptr, index, ""); + } + fn airSliceElemVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { const bin_op = self.air.instructions.items(.data)[inst].bin_op; const slice_ty = self.air.typeOf(bin_op.lhs); diff --git a/src/print_air.zig b/src/print_air.zig index 861483abac..48014d02b0 100644 --- a/src/print_air.zig +++ b/src/print_air.zig @@ -183,6 +183,8 @@ const Writer = struct { .wrap_errunion_err, .slice_ptr, .slice_len, + .ptr_slice_len_ptr, + .ptr_slice_ptr_ptr, .struct_field_ptr_index_0, .struct_field_ptr_index_1, .struct_field_ptr_index_2,