aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/llvm.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-08-07 15:41:52 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-08-07 15:46:53 -0700
commitf81b2531cb4904064446f84a06f6e09e4120e28a (patch)
treee4bac7a1a13c56b728309086d983091e9e009a65 /src/codegen/llvm.zig
parentade85471e2cdab466ba685a38c2c7949c9dd1632 (diff)
downloadzig-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.zig60
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;