stage2: Add container_ty/elem_ty to elem_ptr, field_ptr, *_payload_ptr Values

This commit is contained in:
Cody Tapscott 2022-03-10 18:10:41 -07:00 committed by Andrew Kelley
parent a2a5d3c288
commit bbd750ff05
3 changed files with 92 additions and 55 deletions

View File

@ -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,

View File

@ -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

View File

@ -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,
},
};