aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Sema.zig45
-rw-r--r--src/codegen/llvm.zig4
-rw-r--r--src/value.zig98
3 files changed, 92 insertions, 55 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index b339e4374d..5fa7866586 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -5568,7 +5568,10 @@ fn analyzeOptionalPayloadPtr(
}
return sema.addConstant(
child_pointer,
- try Value.Tag.opt_payload_ptr.create(sema.arena, ptr_val),
+ try Value.Tag.opt_payload_ptr.create(sema.arena, .{
+ .container_ptr = ptr_val,
+ .container_ty = optional_ptr_ty.childType(),
+ }),
);
}
if (try sema.pointerDeref(block, src, ptr_val, optional_ptr_ty)) |val| {
@@ -5578,7 +5581,10 @@ fn analyzeOptionalPayloadPtr(
// The same Value represents the pointer to the optional and the payload.
return sema.addConstant(
child_pointer,
- try Value.Tag.opt_payload_ptr.create(sema.arena, ptr_val),
+ try Value.Tag.opt_payload_ptr.create(sema.arena, .{
+ .container_ptr = ptr_val,
+ .container_ty = optional_ptr_ty.childType(),
+ }),
);
}
}
@@ -5733,7 +5739,10 @@ fn analyzeErrUnionPayloadPtr(
}
return sema.addConstant(
operand_pointer_ty,
- try Value.Tag.eu_payload_ptr.create(sema.arena, ptr_val),
+ try Value.Tag.eu_payload_ptr.create(sema.arena, .{
+ .container_ptr = ptr_val,
+ .container_ty = operand_ty.elemType(),
+ }),
);
}
if (try sema.pointerDeref(block, src, ptr_val, operand_ty)) |val| {
@@ -5743,7 +5752,10 @@ fn analyzeErrUnionPayloadPtr(
return sema.addConstant(
operand_pointer_ty,
- try Value.Tag.eu_payload_ptr.create(sema.arena, ptr_val),
+ try Value.Tag.eu_payload_ptr.create(sema.arena, .{
+ .container_ptr = ptr_val,
+ .container_ty = operand_ty.elemType(),
+ }),
);
}
}
@@ -6652,6 +6664,7 @@ fn zirSwitchCapture(
field_ty_ptr,
try Value.Tag.field_ptr.create(sema.arena, .{
.container_ptr = op_ptr_val,
+ .container_ty = operand_ty,
.field_index = field_index,
}),
);
@@ -9638,7 +9651,7 @@ fn analyzePtrArithmetic(
if (air_tag == .ptr_sub) {
return sema.fail(block, op_src, "TODO implement Sema comptime pointer subtraction", .{});
}
- const new_ptr_val = try ptr_val.elemPtr(sema.arena, offset_int);
+ const new_ptr_val = try ptr_val.elemPtr(ptr_ty, sema.arena, offset_int);
return sema.addConstant(new_ptr_ty, new_ptr_val);
} else break :rs offset_src;
} else break :rs ptr_src;
@@ -15903,6 +15916,7 @@ fn finishFieldCallBind(
ptr_field_ty,
try Value.Tag.field_ptr.create(arena, .{
.container_ptr = struct_ptr_val,
+ .container_ty = ptr_ty.childType(),
.field_index = field_index,
}),
);
@@ -16065,6 +16079,7 @@ fn structFieldPtrByIndex(
ptr_field_ty,
try Value.Tag.field_ptr.create(sema.arena, .{
.container_ptr = struct_ptr_val,
+ .container_ty = struct_ptr_ty.childType(),
.field_index = field_index,
}),
);
@@ -16241,6 +16256,7 @@ fn unionFieldPtr(
ptr_field_ty,
try Value.Tag.field_ptr.create(arena, .{
.container_ptr = union_ptr_val,
+ .container_ty = union_ty,
.field_index = field_index,
}),
);
@@ -16333,7 +16349,7 @@ fn elemPtr(
const runtime_src = if (maybe_slice_val) |slice_val| rs: {
const index_val = maybe_index_val orelse break :rs elem_index_src;
const index = @intCast(usize, index_val.toUnsignedInt());
- const elem_ptr = try slice_val.elemPtr(sema.arena, index);
+ const elem_ptr = try slice_val.elemPtr(array_ty, sema.arena, index);
return sema.addConstant(result_ty, elem_ptr);
} else array_ptr_src;
@@ -16348,7 +16364,7 @@ fn elemPtr(
const ptr_val = maybe_ptr_val orelse break :rs array_ptr_src;
const index_val = maybe_index_val orelse break :rs elem_index_src;
const index = @intCast(usize, index_val.toUnsignedInt());
- const elem_ptr = try ptr_val.elemPtr(sema.arena, index);
+ const elem_ptr = try ptr_val.elemPtr(array_ty, sema.arena, index);
return sema.addConstant(result_ty, elem_ptr);
};
@@ -16473,6 +16489,7 @@ fn tupleFieldPtr(
ptr_field_ty,
try Value.Tag.field_ptr.create(sema.arena, .{
.container_ptr = tuple_ptr_val,
+ .container_ty = tuple_ty,
.field_index = field_index,
}),
);
@@ -16563,7 +16580,7 @@ fn elemPtrArray(
const index_u64 = index_val.toUnsignedInt();
// @intCast here because it would have been impossible to construct a value that
// required a larger index.
- const elem_ptr = try array_ptr_val.elemPtr(sema.arena, @intCast(usize, index_u64));
+ const elem_ptr = try array_ptr_val.elemPtr(array_ptr_ty, sema.arena, @intCast(usize, index_u64));
return sema.addConstant(result_ty, elem_ptr);
}
}
@@ -17757,8 +17774,8 @@ fn beginComptimePtrMutation(
}
},
.eu_payload_ptr => {
- const eu_ptr_val = ptr_val.castTag(.eu_payload_ptr).?.data;
- var parent = try beginComptimePtrMutation(sema, block, src, eu_ptr_val);
+ const eu_ptr = ptr_val.castTag(.eu_payload_ptr).?.data;
+ var parent = try beginComptimePtrMutation(sema, block, src, eu_ptr.container_ptr);
const payload_ty = parent.ty.errorUnionPayload();
switch (parent.val.tag()) {
else => {
@@ -17790,8 +17807,8 @@ fn beginComptimePtrMutation(
}
},
.opt_payload_ptr => {
- const opt_ptr_val = ptr_val.castTag(.opt_payload_ptr).?.data;
- var parent = try beginComptimePtrMutation(sema, block, src, opt_ptr_val);
+ const opt_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;
+ var parent = try beginComptimePtrMutation(sema, block, src, opt_ptr.container_ptr);
const payload_ty = try parent.ty.optionalChildAlloc(sema.arena);
switch (parent.val.tag()) {
.undef, .null_value => {
@@ -17965,7 +17982,7 @@ fn beginComptimePtrLoad(
},
.eu_payload_ptr => {
const err_union_ptr = ptr_val.castTag(.eu_payload_ptr).?.data;
- const parent = try beginComptimePtrLoad(sema, block, src, err_union_ptr);
+ const parent = try beginComptimePtrLoad(sema, block, src, err_union_ptr.container_ptr);
return ComptimePtrLoadKit{
.root_val = parent.root_val,
.root_ty = parent.root_ty,
@@ -17977,7 +17994,7 @@ fn beginComptimePtrLoad(
},
.opt_payload_ptr => {
const opt_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;
- const parent = try beginComptimePtrLoad(sema, block, src, opt_ptr);
+ const parent = try beginComptimePtrLoad(sema, block, src, opt_ptr.container_ptr);
return ComptimePtrLoadKit{
.root_val = parent.root_val,
.root_ty = parent.root_ty,
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 7c4455f296..01f7d60a53 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -2901,7 +2901,7 @@ pub const DeclGen = struct {
},
.opt_payload_ptr => {
const opt_payload_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;
- const parent = try dg.lowerParentPtr(opt_payload_ptr, base_ty);
+ const parent = try dg.lowerParentPtr(opt_payload_ptr.container_ptr, base_ty);
var buf: Type.Payload.ElemType = undefined;
const payload_ty = parent.ty.optionalChild(&buf);
if (!payload_ty.hasRuntimeBitsIgnoreComptime() or parent.ty.isPtrLikeOptional()) {
@@ -2925,7 +2925,7 @@ pub const DeclGen = struct {
},
.eu_payload_ptr => {
const eu_payload_ptr = ptr_val.castTag(.eu_payload_ptr).?.data;
- const parent = try dg.lowerParentPtr(eu_payload_ptr, base_ty);
+ const parent = try dg.lowerParentPtr(eu_payload_ptr.container_ptr, base_ty);
const payload_ty = parent.ty.errorUnionPayload();
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
// In this case, we represent pointer to error union the same as pointer
diff --git a/src/value.zig b/src/value.zig
index c6e201d3f8..f997b554a3 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -268,12 +268,14 @@ pub const Value = extern union {
.repeated,
.eu_payload,
- .eu_payload_ptr,
.opt_payload,
- .opt_payload_ptr,
.empty_array_sentinel,
=> Payload.SubValue,
+ .eu_payload_ptr,
+ .opt_payload_ptr,
+ => Payload.PayloadPtr,
+
.bytes,
.enum_literal,
=> Payload.Bytes,
@@ -479,6 +481,20 @@ pub const Value = extern union {
.variable => return self.copyPayloadShallow(arena, Payload.Variable),
.decl_ref => return self.copyPayloadShallow(arena, Payload.Decl),
.decl_ref_mut => return self.copyPayloadShallow(arena, Payload.DeclRefMut),
+ .eu_payload_ptr,
+ .opt_payload_ptr,
+ => {
+ const payload = self.cast(Payload.PayloadPtr).?;
+ const new_payload = try arena.create(Payload.PayloadPtr);
+ new_payload.* = .{
+ .base = payload.base,
+ .data = .{
+ .container_ptr = try payload.data.container_ptr.copy(arena),
+ .container_ty = try payload.data.container_ty.copy(arena),
+ },
+ };
+ return Value{ .ptr_otherwise = &new_payload.base };
+ },
.elem_ptr => {
const payload = self.castTag(.elem_ptr).?;
const new_payload = try arena.create(Payload.ElemPtr);
@@ -486,6 +502,7 @@ pub const Value = extern union {
.base = payload.base,
.data = .{
.array_ptr = try payload.data.array_ptr.copy(arena),
+ .elem_ty = try payload.data.elem_ty.copy(arena),
.index = payload.data.index,
},
};
@@ -498,6 +515,7 @@ pub const Value = extern union {
.base = payload.base,
.data = .{
.container_ptr = try payload.data.container_ptr.copy(arena),
+ .container_ty = try payload.data.container_ty.copy(arena),
.field_index = payload.data.field_index,
},
};
@@ -506,9 +524,7 @@ pub const Value = extern union {
.bytes => return self.copyPayloadShallow(arena, Payload.Bytes),
.repeated,
.eu_payload,
- .eu_payload_ptr,
.opt_payload,
- .opt_payload_ptr,
.empty_array_sentinel,
=> {
const payload = self.cast(Payload.SubValue).?;
@@ -740,11 +756,11 @@ pub const Value = extern union {
.inferred_alloc_comptime => return out_stream.writeAll("(inferred comptime allocation value)"),
.eu_payload_ptr => {
try out_stream.writeAll("(eu_payload_ptr)");
- val = val.castTag(.eu_payload_ptr).?.data;
+ val = val.castTag(.eu_payload_ptr).?.data.container_ptr;
},
.opt_payload_ptr => {
try out_stream.writeAll("(opt_payload_ptr)");
- val = val.castTag(.opt_payload_ptr).?.data;
+ val = val.castTag(.opt_payload_ptr).?.data.container_ptr;
},
.bound_fn => {
const bound_func = val.castTag(.bound_fn).?.data;
@@ -2162,8 +2178,8 @@ pub const Value = extern union {
.decl_ref_mut => true,
.elem_ptr => isComptimeMutablePtr(val.castTag(.elem_ptr).?.data.array_ptr),
.field_ptr => isComptimeMutablePtr(val.castTag(.field_ptr).?.data.container_ptr),
- .eu_payload_ptr => isComptimeMutablePtr(val.castTag(.eu_payload_ptr).?.data),
- .opt_payload_ptr => isComptimeMutablePtr(val.castTag(.opt_payload_ptr).?.data),
+ .eu_payload_ptr => isComptimeMutablePtr(val.castTag(.eu_payload_ptr).?.data.container_ptr),
+ .opt_payload_ptr => isComptimeMutablePtr(val.castTag(.opt_payload_ptr).?.data.container_ptr),
else => false,
};
@@ -2174,9 +2190,9 @@ pub const Value = extern union {
switch (val.tag()) {
.repeated => return val.castTag(.repeated).?.data.canMutateComptimeVarState(),
.eu_payload => return val.castTag(.eu_payload).?.data.canMutateComptimeVarState(),
- .eu_payload_ptr => return val.castTag(.eu_payload_ptr).?.data.canMutateComptimeVarState(),
+ .eu_payload_ptr => return val.castTag(.eu_payload_ptr).?.data.container_ptr.canMutateComptimeVarState(),
.opt_payload => return val.castTag(.opt_payload).?.data.canMutateComptimeVarState(),
- .opt_payload_ptr => return val.castTag(.opt_payload_ptr).?.data.canMutateComptimeVarState(),
+ .opt_payload_ptr => return val.castTag(.opt_payload_ptr).?.data.container_ptr.canMutateComptimeVarState(),
.aggregate => {
const fields = val.castTag(.aggregate).?.data;
for (fields) |field| {
@@ -2239,12 +2255,12 @@ pub const Value = extern union {
.eu_payload_ptr => {
const err_union_ptr = ptr_val.castTag(.eu_payload_ptr).?.data;
std.hash.autoHash(hasher, Value.Tag.eu_payload_ptr);
- hashPtr(err_union_ptr, hasher);
+ hashPtr(err_union_ptr.container_ptr, hasher);
},
.opt_payload_ptr => {
const opt_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;
std.hash.autoHash(hasher, Value.Tag.opt_payload_ptr);
- hashPtr(opt_ptr, hasher);
+ hashPtr(opt_ptr.container_ptr, hasher);
},
.zero,
@@ -2272,12 +2288,14 @@ pub const Value = extern union {
.repeated,
.eu_payload,
- .eu_payload_ptr,
.opt_payload,
- .opt_payload_ptr,
.empty_array_sentinel,
=> return markReferencedDeclsAlive(val.cast(Payload.SubValue).?.data),
+ .eu_payload_ptr,
+ .opt_payload_ptr,
+ => return markReferencedDeclsAlive(val.cast(Payload.PayloadPtr).?.data.container_ptr),
+
.slice => {
const slice = val.cast(Payload.Slice).?.data;
markReferencedDeclsAlive(slice.ptr);
@@ -2422,36 +2440,28 @@ pub const Value = extern union {
}
/// Returns a pointer to the element value at the index.
- pub fn elemPtr(val: Value, arena: Allocator, index: usize) Allocator.Error!Value {
- switch (val.tag()) {
- .elem_ptr => {
- const elem_ptr = val.castTag(.elem_ptr).?.data;
+ pub fn elemPtr(val: Value, ty: Type, arena: Allocator, index: usize) Allocator.Error!Value {
+ const elem_ty = ty.elemType2();
+ const ptr_val = switch (val.tag()) {
+ .slice => val.slicePtr(),
+ else => val,
+ };
+
+ if (ptr_val.tag() == .elem_ptr) {
+ const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
+ if (elem_ptr.elem_ty.eql(elem_ty)) {
return Tag.elem_ptr.create(arena, .{
.array_ptr = elem_ptr.array_ptr,
+ .elem_ty = elem_ptr.elem_ty,
.index = elem_ptr.index + index,
});
- },
- .slice => {
- const ptr_val = val.castTag(.slice).?.data.ptr;
- switch (ptr_val.tag()) {
- .elem_ptr => {
- const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
- return Tag.elem_ptr.create(arena, .{
- .array_ptr = elem_ptr.array_ptr,
- .index = elem_ptr.index + index,
- });
- },
- else => return Tag.elem_ptr.create(arena, .{
- .array_ptr = ptr_val,
- .index = index,
- }),
- }
- },
- else => return Tag.elem_ptr.create(arena, .{
- .array_ptr = val,
- .index = index,
- }),
+ }
}
+ return Tag.elem_ptr.create(arena, .{
+ .array_ptr = ptr_val,
+ .elem_ty = elem_ty,
+ .index = index,
+ });
}
pub fn isUndef(self: Value) bool {
@@ -4144,12 +4154,21 @@ pub const Value = extern union {
};
};
+ pub const PayloadPtr = struct {
+ base: Payload,
+ data: struct {
+ container_ptr: Value,
+ container_ty: Type,
+ },
+ };
+
pub const ElemPtr = struct {
pub const base_tag = Tag.elem_ptr;
base: Payload = Payload{ .tag = base_tag },
data: struct {
array_ptr: Value,
+ elem_ty: Type,
index: usize,
},
};
@@ -4160,6 +4179,7 @@ pub const Value = extern union {
base: Payload = Payload{ .tag = base_tag },
data: struct {
container_ptr: Value,
+ container_ty: Type,
field_index: usize,
},
};