diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-08-07 15:41:52 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-08-07 15:46:53 -0700 |
| commit | f81b2531cb4904064446f84a06f6e09e4120e28a (patch) | |
| tree | e4bac7a1a13c56b728309086d983091e9e009a65 /src/codegen/llvm.zig | |
| parent | ade85471e2cdab466ba685a38c2c7949c9dd1632 (diff) | |
| download | zig-f81b2531cb4904064446f84a06f6e09e4120e28a.tar.gz zig-f81b2531cb4904064446f84a06f6e09e4120e28a.zip | |
stage2: pass some pointer tests
* New AIR instructions: ptr_add, ptr_sub, ptr_elem_val, ptr_ptr_elem_val
- See the doc comments for details.
* Sema: implement runtime pointer arithmetic.
* Sema: implement elem_val for many-pointers.
* Sema: support coercion from `*[N:s]T` to `[*]T`.
* Type: isIndexable handles many-pointers.
Diffstat (limited to 'src/codegen/llvm.zig')
| -rw-r--r-- | src/codegen/llvm.zig | 60 |
1 files changed, 58 insertions, 2 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 4b7454d878..eccd5fa04f 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -966,6 +966,8 @@ pub const FuncGen = struct { .mul => try self.airMul(inst, false), .mulwrap => try self.airMul(inst, true), .div => try self.airDiv(inst), + .ptr_add => try self.airPtrAdd(inst), + .ptr_sub => try self.airPtrSub(inst), .bit_and, .bool_and => try self.airAnd(inst), .bit_or, .bool_or => try self.airOr(inst), @@ -1015,6 +1017,8 @@ pub const FuncGen = struct { .slice_elem_val => try self.airSliceElemVal(inst), .ptr_slice_elem_val => try self.airPtrSliceElemVal(inst), + .ptr_elem_val => try self.airPtrElemVal(inst), + .ptr_ptr_elem_val => try self.airPtrPtrElemVal(inst), .optional_payload => try self.airOptionalPayload(inst, false), .optional_payload_ptr => try self.airOptionalPayload(inst, true), @@ -1229,7 +1233,8 @@ pub const FuncGen = struct { } fn airSliceElemVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { - if (self.liveness.isUnused(inst)) + const is_volatile = false; // TODO + if (!is_volatile and self.liveness.isUnused(inst)) return null; const bin_op = self.air.instructions.items(.data)[inst].bin_op; @@ -1242,7 +1247,8 @@ pub const FuncGen = struct { } fn airPtrSliceElemVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { - if (self.liveness.isUnused(inst)) + const is_volatile = false; // TODO + if (!is_volatile and self.liveness.isUnused(inst)) return null; const bin_op = self.air.instructions.items(.data)[inst].bin_op; @@ -1264,6 +1270,33 @@ pub const FuncGen = struct { return self.builder.buildLoad(ptr, ""); } + fn airPtrElemVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { + const is_volatile = false; // TODO + if (!is_volatile and self.liveness.isUnused(inst)) + return null; + + const bin_op = self.air.instructions.items(.data)[inst].bin_op; + const base_ptr = try self.resolveInst(bin_op.lhs); + const rhs = try self.resolveInst(bin_op.rhs); + const indices: [1]*const llvm.Value = .{rhs}; + const ptr = self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + return self.builder.buildLoad(ptr, ""); + } + + fn airPtrPtrElemVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { + const is_volatile = false; // TODO + if (!is_volatile and self.liveness.isUnused(inst)) + return null; + + const bin_op = self.air.instructions.items(.data)[inst].bin_op; + const lhs = try self.resolveInst(bin_op.lhs); + const rhs = try self.resolveInst(bin_op.rhs); + const base_ptr = self.builder.buildLoad(lhs, ""); + const indices: [1]*const llvm.Value = .{rhs}; + const ptr = self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + return self.builder.buildLoad(ptr, ""); + } + fn airStructFieldPtr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { if (self.liveness.isUnused(inst)) return null; @@ -1624,6 +1657,29 @@ pub const FuncGen = struct { return self.builder.buildUDiv(lhs, rhs, ""); } + fn airPtrAdd(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { + if (self.liveness.isUnused(inst)) + return null; + + const bin_op = self.air.instructions.items(.data)[inst].bin_op; + const base_ptr = try self.resolveInst(bin_op.lhs); + const offset = try self.resolveInst(bin_op.rhs); + const indices: [1]*const llvm.Value = .{offset}; + return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + } + + fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { + if (self.liveness.isUnused(inst)) + return null; + + const bin_op = self.air.instructions.items(.data)[inst].bin_op; + const base_ptr = try self.resolveInst(bin_op.lhs); + const offset = try self.resolveInst(bin_op.rhs); + const negative_offset = self.builder.buildNeg(offset, ""); + const indices: [1]*const llvm.Value = .{negative_offset}; + return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + } + fn airAnd(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { if (self.liveness.isUnused(inst)) return null; |
