| author | |
| committer | |
| log | 09c7d5aebc4f7fe96a89f93c0cf99cc03977ea5f |
| tree | 7877d79040b38f43aea7fc192546b19d07821bc0 |
| parent | 84876fec582e13707a809c8136bb1eaf92b5da09 |
* Restructure elemPtr a bit
* New AIR instruction: slice_elem_ptr, which returns a pointer to an element of a slice
* Value: adapt elemPtr to work on slices10 files changed, 157 insertions(+), 32 deletions(-)
src/Air.zig+5| ... | @@ -384,6 +384,10 @@ pub const Inst = struct { | ... | @@ -384,6 +384,10 @@ pub const Inst = struct { |
| 384 | /// Result type is the element type of the slice operand. | 384 | /// Result type is the element type of the slice operand. |
| 385 | /// Uses the `bin_op` field. | 385 | /// Uses the `bin_op` field. |
| 386 | slice_elem_val, | 386 | slice_elem_val, |
| 387 | /// Given a slice value and element index, return a pointer to the element value at that index. | ||
| 388 | /// Result type is a pointer to the element type of the slice operand. | ||
| 389 | /// Uses the `ty_pl` field with payload `Bin`. | ||
| 390 | slice_elem_ptr, | ||
| 387 | /// Given a pointer value, and element index, return the element value at that index. | 391 | /// Given a pointer value, and element index, return the element value at that index. |
| 388 | /// Result type is the element type of the pointer operand. | 392 | /// Result type is the element type of the pointer operand. |
| 389 | /// Uses the `bin_op` field. | 393 | /// Uses the `bin_op` field. |
| ... | @@ -685,6 +689,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { | ... | @@ -685,6 +689,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { |
| 685 | .constant, | 689 | .constant, |
| 686 | .struct_field_ptr, | 690 | .struct_field_ptr, |
| 687 | .struct_field_val, | 691 | .struct_field_val, |
| 692 | .slice_elem_ptr, | ||
| 688 | .ptr_elem_ptr, | 693 | .ptr_elem_ptr, |
| 689 | .cmpxchg_weak, | 694 | .cmpxchg_weak, |
| 690 | .cmpxchg_strong, | 695 | .cmpxchg_strong, |
src/Liveness.zig+1-1| ... | @@ -360,7 +360,7 @@ fn analyzeInst( | ... | @@ -360,7 +360,7 @@ fn analyzeInst( |
| 360 | const extra = a.air.extraData(Air.StructField, inst_datas[inst].ty_pl.payload).data; | 360 | const extra = a.air.extraData(Air.StructField, inst_datas[inst].ty_pl.payload).data; |
| 361 | return trackOperands(a, new_set, inst, main_tomb, .{ extra.struct_operand, .none, .none }); | 361 | return trackOperands(a, new_set, inst, main_tomb, .{ extra.struct_operand, .none, .none }); |
| 362 | }, | 362 | }, |
| 363 | .ptr_elem_ptr => { | 363 | .ptr_elem_ptr, .slice_elem_ptr => { |
| 364 | const extra = a.air.extraData(Air.Bin, inst_datas[inst].ty_pl.payload).data; | 364 | const extra = a.air.extraData(Air.Bin, inst_datas[inst].ty_pl.payload).data; |
| 365 | return trackOperands(a, new_set, inst, main_tomb, .{ extra.lhs, extra.rhs, .none }); | 365 | return trackOperands(a, new_set, inst, main_tomb, .{ extra.lhs, extra.rhs, .none }); |
| 366 | }, | 366 | }, |
src/Sema.zig+51-17| ... | @@ -333,6 +333,24 @@ pub const Block = struct { | ... | @@ -333,6 +333,24 @@ pub const Block = struct { |
| 333 | }); | 333 | }); |
| 334 | } | 334 | } |
| 335 | 335 | ||
| 336 | pub fn addSliceElemPtr( | ||
| 337 | block: *Block, | ||
| 338 | slice: Air.Inst.Ref, | ||
| 339 | elem_index: Air.Inst.Ref, | ||
| 340 | elem_ptr_ty: Type, | ||
| 341 | ) !Air.Inst.Ref { | ||
| 342 | return block.addInst(.{ | ||
| 343 | .tag = .slice_elem_ptr, | ||
| 344 | .data = .{ .ty_pl = .{ | ||
| 345 | .ty = try block.sema.addType(elem_ptr_ty), | ||
| 346 | .payload = try block.sema.addExtra(Air.Bin{ | ||
| 347 | .lhs = slice, | ||
| 348 | .rhs = elem_index, | ||
| 349 | }), | ||
| 350 | } }, | ||
| 351 | }); | ||
| 352 | } | ||
| 353 | |||
| 336 | pub fn addInst(block: *Block, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Ref { | 354 | pub fn addInst(block: *Block, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Ref { |
| 337 | return Air.indexToRef(try block.addInstAsIndex(inst)); | 355 | return Air.indexToRef(try block.addInstAsIndex(inst)); |
| 338 | } | 356 | } |
| ... | @@ -11476,18 +11494,39 @@ fn elemPtr( | ... | @@ -11476,18 +11494,39 @@ fn elemPtr( |
| 11476 | else => return sema.fail(block, array_ptr_src, "expected pointer, found '{}'", .{array_ptr_ty}), | 11494 | else => return sema.fail(block, array_ptr_src, "expected pointer, found '{}'", .{array_ptr_ty}), |
| 11477 | }; | 11495 | }; |
| 11478 | if (!array_ty.isIndexable()) { | 11496 | if (!array_ty.isIndexable()) { |
| 11479 | return sema.fail(block, src, "array access of non-array type '{}'", .{array_ty}); | 11497 | return sema.fail(block, src, "array access of non-indexable type '{}'", .{array_ty}); |
| 11480 | } | ||
| 11481 | if (array_ty.isSinglePointer() and array_ty.elemType().zigTypeTag() == .Array) { | ||
| 11482 | // we have to deref the ptr operand to get the actual array pointer | ||
| 11483 | const array_ptr_deref = try sema.analyzeLoad(block, src, array_ptr, array_ptr_src); | ||
| 11484 | return sema.elemPtrArray(block, src, array_ptr_deref, elem_index, elem_index_src); | ||
| 11485 | } | ||
| 11486 | if (array_ty.zigTypeTag() == .Array) { | ||
| 11487 | return sema.elemPtrArray(block, src, array_ptr, elem_index, elem_index_src); | ||
| 11488 | } | 11498 | } |
| 11489 | 11499 | ||
| 11490 | return sema.fail(block, src, "TODO implement more analyze elemptr", .{}); | 11500 | switch (array_ty.zigTypeTag()) { |
| 11501 | .Pointer => { | ||
| 11502 | // In all below cases, we have to deref the ptr operand to get the actual array pointer. | ||
| 11503 | const array = try sema.analyzeLoad(block, src, array_ptr, array_ptr_src); | ||
| 11504 | switch (array_ty.ptrSize()) { | ||
| 11505 | .Slice => { | ||
| 11506 | const result_ty = try array_ty.elemPtrType(sema.arena); | ||
| 11507 | const maybe_slice_val = try sema.resolveDefinedValue(block, array_ptr_src, array); | ||
| 11508 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); | ||
| 11509 | const runtime_src = if (maybe_slice_val) |slice_val| rs: { | ||
| 11510 | const index_val = maybe_index_val orelse break :rs elem_index_src; | ||
| 11511 | const index = @intCast(usize, index_val.toUnsignedInt()); | ||
| 11512 | const elem_ptr = try slice_val.elemPtr(sema.arena, index); | ||
| 11513 | return sema.addConstant(result_ty, elem_ptr); | ||
| 11514 | } else array_ptr_src; | ||
| 11515 | |||
| 11516 | try sema.requireRuntimeBlock(block, runtime_src); | ||
| 11517 | return block.addSliceElemPtr(array, elem_index, result_ty); | ||
| 11518 | }, | ||
| 11519 | .Many, .C => return sema.fail(block, src, "TODO implement Sema for elemPtr for many/c pointer", .{}), | ||
| 11520 | .One => { | ||
| 11521 | assert(array_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable | ||
| 11522 | return sema.elemPtrArray(block, src, array, elem_index, elem_index_src); | ||
| 11523 | }, | ||
| 11524 | } | ||
| 11525 | }, | ||
| 11526 | .Array => return sema.elemPtrArray(block, src, array_ptr, elem_index, elem_index_src), | ||
| 11527 | .Vector => return sema.fail(block, src, "TODO implement Sema for elemPtr for vector", .{}), | ||
| 11528 | else => unreachable, | ||
| 11529 | } | ||
| 11491 | } | 11530 | } |
| 11492 | 11531 | ||
| 11493 | fn elemVal( | 11532 | fn elemVal( |
| ... | @@ -11529,7 +11568,7 @@ fn elemVal( | ... | @@ -11529,7 +11568,7 @@ fn elemVal( |
| 11529 | return block.addBinOp(.ptr_elem_val, array, elem_index); | 11568 | return block.addBinOp(.ptr_elem_val, array, elem_index); |
| 11530 | }, | 11569 | }, |
| 11531 | .One => { | 11570 | .One => { |
| 11532 | assert(array_ty.childType().zigTypeTag() == .Array); | 11571 | assert(array_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable |
| 11533 | const elem_ptr = try sema.elemPtr(block, src, array, elem_index, elem_index_src); | 11572 | const elem_ptr = try sema.elemPtr(block, src, array, elem_index, elem_index_src); |
| 11534 | return sema.analyzeLoad(block, src, elem_ptr, elem_index_src); | 11573 | return sema.analyzeLoad(block, src, elem_ptr, elem_index_src); |
| 11535 | }, | 11574 | }, |
| ... | @@ -11562,12 +11601,7 @@ fn elemPtrArray( | ... | @@ -11562,12 +11601,7 @@ fn elemPtrArray( |
| 11562 | elem_index_src: LazySrcLoc, | 11601 | elem_index_src: LazySrcLoc, |
| 11563 | ) CompileError!Air.Inst.Ref { | 11602 | ) CompileError!Air.Inst.Ref { |
| 11564 | const array_ptr_ty = sema.typeOf(array_ptr); | 11603 | const array_ptr_ty = sema.typeOf(array_ptr); |
| 11565 | const pointee_type = array_ptr_ty.elemType().elemType(); | 11604 | const result_ty = try array_ptr_ty.elemPtrType(sema.arena); |
| 11566 | const result_ty = try Type.ptr(sema.arena, .{ | ||
| 11567 | .pointee_type = pointee_type, | ||
| 11568 | .mutable = array_ptr_ty.ptrIsMutable(), | ||
| 11569 | .@"addrspace" = array_ptr_ty.ptrAddressSpace(), | ||
| 11570 | }); | ||
| 11571 | 11605 | ||
| 11572 | if (try sema.resolveDefinedValue(block, src, array_ptr)) |array_ptr_val| { | 11606 | if (try sema.resolveDefinedValue(block, src, array_ptr)) |array_ptr_val| { |
| 11573 | if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| { | 11607 | if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| { |
src/arch/aarch64/CodeGen.zig+8| ... | @@ -500,6 +500,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -500,6 +500,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 500 | 500 | ||
| 501 | .array_elem_val => try self.airArrayElemVal(inst), | 501 | .array_elem_val => try self.airArrayElemVal(inst), |
| 502 | .slice_elem_val => try self.airSliceElemVal(inst), | 502 | .slice_elem_val => try self.airSliceElemVal(inst), |
| 503 | .slice_elem_ptr => try self.airSliceElemPtr(inst), | ||
| 503 | .ptr_elem_val => try self.airPtrElemVal(inst), | 504 | .ptr_elem_val => try self.airPtrElemVal(inst), |
| 504 | .ptr_elem_ptr => try self.airPtrElemPtr(inst), | 505 | .ptr_elem_ptr => try self.airPtrElemPtr(inst), |
| 505 | 506 | ||
| ... | @@ -1084,6 +1085,13 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1084,6 +1085,13 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1084 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1085 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1085 | } | 1086 | } |
| 1086 | 1087 | ||
| 1088 | fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void { | ||
| 1089 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | ||
| 1090 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | ||
| 1091 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement slice_elem_ptr for {}", .{self.target.cpu.arch}); | ||
| 1092 | return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none }); | ||
| 1093 | } | ||
| 1094 | |||
| 1087 | fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { | 1095 | fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1088 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 1096 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1089 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement array_elem_val for {}", .{self.target.cpu.arch}); | 1097 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement array_elem_val for {}", .{self.target.cpu.arch}); |
src/codegen.zig+10| ... | @@ -848,6 +848,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -848,6 +848,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 848 | 848 | ||
| 849 | .array_elem_val => try self.airArrayElemVal(inst), | 849 | .array_elem_val => try self.airArrayElemVal(inst), |
| 850 | .slice_elem_val => try self.airSliceElemVal(inst), | 850 | .slice_elem_val => try self.airSliceElemVal(inst), |
| 851 | .slice_elem_ptr => try self.airSliceElemPtr(inst), | ||
| 851 | .ptr_elem_val => try self.airPtrElemVal(inst), | 852 | .ptr_elem_val => try self.airPtrElemVal(inst), |
| 852 | .ptr_elem_ptr => try self.airPtrElemPtr(inst), | 853 | .ptr_elem_ptr => try self.airPtrElemPtr(inst), |
| 853 | 854 | ||
| ... | @@ -1533,6 +1534,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -1533,6 +1534,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1533 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1534 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1534 | } | 1535 | } |
| 1535 | 1536 | ||
| 1537 | fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void { | ||
| 1538 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | ||
| 1539 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | ||
| 1540 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) { | ||
| 1541 | else => return self.fail("TODO implement slice_elem_ptr for {}", .{self.target.cpu.arch}), | ||
| 1542 | }; | ||
| 1543 | return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none }); | ||
| 1544 | } | ||
| 1545 | |||
| 1536 | fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { | 1546 | fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1537 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 1547 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1538 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) { | 1548 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) { |
src/codegen/c.zig+19| ... | @@ -1083,6 +1083,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO | ... | @@ -1083,6 +1083,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 1083 | .ptr_elem_val => try airPtrElemVal(f, inst, "["), | 1083 | .ptr_elem_val => try airPtrElemVal(f, inst, "["), |
| 1084 | .ptr_elem_ptr => try airPtrElemPtr(f, inst), | 1084 | .ptr_elem_ptr => try airPtrElemPtr(f, inst), |
| 1085 | .slice_elem_val => try airSliceElemVal(f, inst, "["), | 1085 | .slice_elem_val => try airSliceElemVal(f, inst, "["), |
| 1086 | .slice_elem_ptr => try airSliceElemPtr(f, inst), | ||
| 1086 | .array_elem_val => try airArrayElemVal(f, inst), | 1087 | .array_elem_val => try airArrayElemVal(f, inst), |
| 1087 | 1088 | ||
| 1088 | .unwrap_errunion_payload => try airUnwrapErrUnionPay(f, inst), | 1089 | .unwrap_errunion_payload => try airUnwrapErrUnionPay(f, inst), |
| ... | @@ -1165,6 +1166,24 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index, prefix: []const u8) !CVal | ... | @@ -1165,6 +1166,24 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index, prefix: []const u8) !CVal |
| 1165 | return local; | 1166 | return local; |
| 1166 | } | 1167 | } |
| 1167 | 1168 | ||
| 1169 | fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ||
| 1170 | if (f.liveness.isUnused(inst)) | ||
| 1171 | return CValue.none; | ||
| 1172 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | ||
| 1173 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; | ||
| 1174 | |||
| 1175 | const slice = try f.resolveInst(bin_op.lhs); | ||
| 1176 | const index = try f.resolveInst(bin_op.rhs); | ||
| 1177 | const writer = f.object.writer(); | ||
| 1178 | const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const); | ||
| 1179 | try writer.writeAll(" = &"); | ||
| 1180 | try f.writeCValue(writer, slice); | ||
| 1181 | try writer.writeByte('['); | ||
| 1182 | try f.writeCValue(writer, index); | ||
| 1183 | try writer.writeAll("];\n"); | ||
| 1184 | return local; | ||
| 1185 | } | ||
| 1186 | |||
| 1168 | fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | 1187 | fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 1169 | if (f.liveness.isUnused(inst)) return CValue.none; | 1188 | if (f.liveness.isUnused(inst)) return CValue.none; |
| 1170 | 1189 |
src/codegen/llvm.zig+22-3| ... | @@ -1760,6 +1760,7 @@ pub const FuncGen = struct { | ... | @@ -1760,6 +1760,7 @@ pub const FuncGen = struct { |
| 1760 | 1760 | ||
| 1761 | .array_elem_val => try self.airArrayElemVal(inst), | 1761 | .array_elem_val => try self.airArrayElemVal(inst), |
| 1762 | .slice_elem_val => try self.airSliceElemVal(inst), | 1762 | .slice_elem_val => try self.airSliceElemVal(inst), |
| 1763 | .slice_elem_ptr => try self.airSliceElemPtr(inst), | ||
| 1763 | .ptr_elem_val => try self.airPtrElemVal(inst), | 1764 | .ptr_elem_val => try self.airPtrElemVal(inst), |
| 1764 | .ptr_elem_ptr => try self.airPtrElemPtr(inst), | 1765 | .ptr_elem_ptr => try self.airPtrElemPtr(inst), |
| 1765 | 1766 | ||
| ... | @@ -2157,12 +2158,20 @@ pub const FuncGen = struct { | ... | @@ -2157,12 +2158,20 @@ pub const FuncGen = struct { |
| 2157 | 2158 | ||
| 2158 | const slice = try self.resolveInst(bin_op.lhs); | 2159 | const slice = try self.resolveInst(bin_op.lhs); |
| 2159 | const index = try self.resolveInst(bin_op.rhs); | 2160 | const index = try self.resolveInst(bin_op.rhs); |
| 2160 | const base_ptr = self.builder.buildExtractValue(slice, 0, ""); | 2161 | const ptr = self.sliceElemPtr(slice, index); |
| 2161 | const indices: [1]*const llvm.Value = .{index}; | ||
| 2162 | const ptr = self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); | ||
| 2163 | return self.load(ptr, slice_ty); | 2162 | return self.load(ptr, slice_ty); |
| 2164 | } | 2163 | } |
| 2165 | 2164 | ||
| 2165 | fn airSliceElemPtr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | ||
| 2166 | if (self.liveness.isUnused(inst)) return null; | ||
| 2167 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | ||
| 2168 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; | ||
| 2169 | |||
| 2170 | const slice = try self.resolveInst(bin_op.lhs); | ||
| 2171 | const index = try self.resolveInst(bin_op.rhs); | ||
| 2172 | return self.sliceElemPtr(slice, index); | ||
| 2173 | } | ||
| 2174 | |||
| 2166 | fn airArrayElemVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { | 2175 | fn airArrayElemVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { |
| 2167 | if (self.liveness.isUnused(inst)) return null; | 2176 | if (self.liveness.isUnused(inst)) return null; |
| 2168 | 2177 | ||
| ... | @@ -3575,6 +3584,16 @@ pub const FuncGen = struct { | ... | @@ -3575,6 +3584,16 @@ pub const FuncGen = struct { |
| 3575 | return self.builder.buildBitCast(union_field_ptr, result_llvm_ty, ""); | 3584 | return self.builder.buildBitCast(union_field_ptr, result_llvm_ty, ""); |
| 3576 | } | 3585 | } |
| 3577 | 3586 | ||
| 3587 | fn sliceElemPtr( | ||
| 3588 | self: *FuncGen, | ||
| 3589 | slice: *const llvm.Value, | ||
| 3590 | index: *const llvm.Value, | ||
| 3591 | ) *const llvm.Value { | ||
| 3592 | const base_ptr = self.builder.buildExtractValue(slice, 0, ""); | ||
| 3593 | const indices: [1]*const llvm.Value = .{index}; | ||
| 3594 | return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); | ||
| 3595 | } | ||
| 3596 | |||
| 3578 | fn getIntrinsic(self: *FuncGen, name: []const u8) *const llvm.Value { | 3597 | fn getIntrinsic(self: *FuncGen, name: []const u8) *const llvm.Value { |
| 3579 | const id = llvm.lookupIntrinsicID(name.ptr, name.len); | 3598 | const id = llvm.lookupIntrinsicID(name.ptr, name.len); |
| 3580 | assert(id != 0); | 3599 | assert(id != 0); |
src/print_air.zig+10| ... | @@ -200,6 +200,7 @@ const Writer = struct { | ... | @@ -200,6 +200,7 @@ const Writer = struct { |
| 200 | .loop, | 200 | .loop, |
| 201 | => try w.writeBlock(s, inst), | 201 | => try w.writeBlock(s, inst), |
| 202 | 202 | ||
| 203 | .slice_elem_ptr => try w.writeSliceElemPtr(s, inst), | ||
| 203 | .ptr_elem_ptr => try w.writePtrElemPtr(s, inst), | 204 | .ptr_elem_ptr => try w.writePtrElemPtr(s, inst), |
| 204 | .struct_field_ptr => try w.writeStructField(s, inst), | 205 | .struct_field_ptr => try w.writeStructField(s, inst), |
| 205 | .struct_field_val => try w.writeStructField(s, inst), | 206 | .struct_field_val => try w.writeStructField(s, inst), |
| ... | @@ -281,6 +282,15 @@ const Writer = struct { | ... | @@ -281,6 +282,15 @@ const Writer = struct { |
| 281 | try s.print(", {d}", .{extra.field_index}); | 282 | try s.print(", {d}", .{extra.field_index}); |
| 282 | } | 283 | } |
| 283 | 284 | ||
| 285 | fn writeSliceElemPtr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | ||
| 286 | const ty_pl = w.air.instructions.items(.data)[inst].ty_pl; | ||
| 287 | const extra = w.air.extraData(Air.Bin, ty_pl.payload).data; | ||
| 288 | |||
| 289 | try w.writeOperand(s, inst, 0, extra.lhs); | ||
| 290 | try s.writeAll(", "); | ||
| 291 | try w.writeOperand(s, inst, 1, extra.rhs); | ||
| 292 | } | ||
| 293 | |||
| 284 | fn writePtrElemPtr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { | 294 | fn writePtrElemPtr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { |
| 285 | const ty_pl = w.air.instructions.items(.data)[inst].ty_pl; | 295 | const ty_pl = w.air.instructions.items(.data)[inst].ty_pl; |
| 286 | const extra = w.air.extraData(Air.Bin, ty_pl.payload).data; | 296 | const extra = w.air.extraData(Air.Bin, ty_pl.payload).data; |
src/type.zig+14| ... | @@ -2520,6 +2520,20 @@ pub const Type = extern union { | ... | @@ -2520,6 +2520,20 @@ pub const Type = extern union { |
| 2520 | }; | 2520 | }; |
| 2521 | } | 2521 | } |
| 2522 | 2522 | ||
| 2523 | /// Returns the type of a pointer to an element. | ||
| 2524 | /// Asserts that the type is a pointer, and that the element type is indexable. | ||
| 2525 | /// For *[N]T, return *T | ||
| 2526 | /// For [*]T, returns *T | ||
| 2527 | /// For []T, returns *T | ||
| 2528 | /// Handles const-ness and address spaces in particular. | ||
| 2529 | pub fn elemPtrType(ptr_ty: Type, arena: *Allocator) !Type { | ||
| 2530 | return try Type.ptr(arena, .{ | ||
| 2531 | .pointee_type = ptr_ty.elemType2(), | ||
| 2532 | .mutable = ptr_ty.ptrIsMutable(), | ||
| 2533 | .@"addrspace" = ptr_ty.ptrAddressSpace(), | ||
| 2534 | }); | ||
| 2535 | } | ||
| 2536 | |||
| 2523 | fn shallowElemType(child_ty: Type) Type { | 2537 | fn shallowElemType(child_ty: Type) Type { |
| 2524 | return switch (child_ty.zigTypeTag()) { | 2538 | return switch (child_ty.zigTypeTag()) { |
| 2525 | .Array, .Vector => child_ty.childType(), | 2539 | .Array, .Vector => child_ty.childType(), |
src/value.zig+17-11| ... | @@ -114,7 +114,7 @@ pub const Value = extern union { | ... | @@ -114,7 +114,7 @@ pub const Value = extern union { |
| 114 | /// This Tag will never be seen by machine codegen backends. It is changed into a | 114 | /// This Tag will never be seen by machine codegen backends. It is changed into a |
| 115 | /// `decl_ref` when a comptime variable goes out of scope. | 115 | /// `decl_ref` when a comptime variable goes out of scope. |
| 116 | decl_ref_mut, | 116 | decl_ref_mut, |
| 117 | /// Pointer to a specific element of an array. | 117 | /// Pointer to a specific element of an array, vector or slice. |
| 118 | elem_ptr, | 118 | elem_ptr, |
| 119 | /// Pointer to a specific field of a struct or union. | 119 | /// Pointer to a specific field of a struct or union. |
| 120 | field_ptr, | 120 | field_ptr, |
| ... | @@ -1792,17 +1792,23 @@ pub const Value = extern union { | ... | @@ -1792,17 +1792,23 @@ pub const Value = extern union { |
| 1792 | 1792 | ||
| 1793 | /// Returns a pointer to the element value at the index. | 1793 | /// Returns a pointer to the element value at the index. |
| 1794 | pub fn elemPtr(self: Value, allocator: *Allocator, index: usize) !Value { | 1794 | pub fn elemPtr(self: Value, allocator: *Allocator, index: usize) !Value { |
| 1795 | if (self.castTag(.elem_ptr)) |elem_ptr| { | 1795 | switch (self.tag()) { |
| 1796 | return Tag.elem_ptr.create(allocator, .{ | 1796 | .elem_ptr => { |
| 1797 | .array_ptr = elem_ptr.data.array_ptr, | 1797 | const elem_ptr = self.castTag(.elem_ptr).?.data; |
| 1798 | .index = elem_ptr.data.index + index, | 1798 | return Tag.elem_ptr.create(allocator, .{ |
| 1799 | }); | 1799 | .array_ptr = elem_ptr.array_ptr, |
| 1800 | .index = elem_ptr.index + index, | ||
| 1801 | }); | ||
| 1802 | }, | ||
| 1803 | .slice => return Tag.elem_ptr.create(allocator, .{ | ||
| 1804 | .array_ptr = self.castTag(.slice).?.data.ptr, | ||
| 1805 | .index = index, | ||
| 1806 | }), | ||
| 1807 | else => return Tag.elem_ptr.create(allocator, .{ | ||
| 1808 | .array_ptr = self, | ||
| 1809 | .index = index, | ||
| 1810 | }), | ||
| 1800 | } | 1811 | } |
| 1801 | |||
| 1802 | return Tag.elem_ptr.create(allocator, .{ | ||
| 1803 | .array_ptr = self, | ||
| 1804 | .index = index, | ||
| 1805 | }); | ||
| 1806 | } | 1812 | } |
| 1807 | 1813 | ||
| 1808 | pub fn isUndef(self: Value) bool { | 1814 | pub fn isUndef(self: Value) bool { |