Commit 05c5c99a95

Robin Voetter <robin@voetter.nl>
2021-10-18 01:00:07
stage2: air ptr_slice_len_ptr and ptr_slice_ptr_ptr
1 parent e5d6fe1
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;
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))
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);
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,
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;
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,
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,