Sema: different solution to elemVal

I think that reusing the ComptimePtrLoad infrastructure is ultimately
less logic and more robust than adding a `direct` flag to elem_ptr.

 * Some code in zirTypeInfo needed to be fixed to create proper
   Type/Value encodings.
 * comptime elemVal works by constructing an elem_ptr Value and then
   using the already existing pointerDeref function.

There are some remaining calls to Value.elemValue which should be
considered code smells at this point.
This commit is contained in:
Andrew Kelley 2022-03-16 16:29:08 -07:00
parent 418197b6c5
commit cdeb1fb881
2 changed files with 64 additions and 42 deletions

View File

@ -10388,25 +10388,32 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
)).?;
try sema.mod.declareDeclDependency(sema.owner_decl, fn_info_decl);
try sema.ensureDeclAnalyzed(fn_info_decl);
var fn_ty_buffer: Value.ToTypeBuffer = undefined;
const fn_ty = fn_info_decl.val.toType(&fn_ty_buffer);
const param_info_decl = (try sema.namespaceLookup(
block,
src,
fn_info_decl.val.castTag(.ty).?.data.getNamespace().?,
fn_ty.getNamespace().?,
"Param",
)).?;
try sema.mod.declareDeclDependency(sema.owner_decl, param_info_decl);
try sema.ensureDeclAnalyzed(param_info_decl);
var param_buffer: Value.ToTypeBuffer = undefined;
const param_ty = param_info_decl.val.toType(&param_buffer);
const new_decl = try params_anon_decl.finish(
try Type.Tag.array.create(params_anon_decl.arena(), .{
.len = param_vals.len,
.elem_type = param_info_decl.ty,
.elem_type = try param_ty.copy(params_anon_decl.arena()),
}),
try Value.Tag.aggregate.create(
params_anon_decl.arena(),
param_vals,
),
);
break :v try Value.Tag.decl_ref.create(sema.arena, new_decl);
break :v try Value.Tag.slice.create(sema.arena, .{
.ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
.len = try Value.Tag.int_u64.create(sema.arena, param_vals.len),
});
};
const ret_ty_opt = if (info.return_type.tag() != .generic_poison)
@ -10823,7 +10830,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
try fields_anon_decl.arena().dupe(Value, union_field_vals),
),
);
break :v try Value.Tag.decl_ref.create(sema.arena, new_decl);
break :v try Value.Tag.slice.create(sema.arena, .{
.ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
.len = try Value.Tag.int_u64.create(sema.arena, union_field_vals.len),
});
};
const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, union_ty.getNamespace());
@ -10897,7 +10907,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
);
break :v try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl);
break :v try Value.Tag.slice.create(sema.arena, .{
.ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),
.len = try Value.Tag.int_u64.create(sema.arena, bytes.len),
});
};
const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
@ -10937,7 +10950,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
);
break :v try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl);
break :v try Value.Tag.slice.create(sema.arena, .{
.ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),
.len = try Value.Tag.int_u64.create(sema.arena, bytes.len),
});
};
const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
@ -10979,7 +10995,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
try fields_anon_decl.arena().dupe(Value, struct_field_vals),
),
);
break :v try Value.Tag.decl_ref.create(sema.arena, new_decl);
break :v try Value.Tag.slice.create(sema.arena, .{
.ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
.len = try Value.Tag.int_u64.create(sema.arena, struct_field_vals.len),
});
};
const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, struct_ty.getNamespace());
@ -11048,7 +11067,7 @@ fn typeInfoDecls(
block,
src,
type_info_ty.getNamespace().?,
"EnumField",
"Declaration",
)).?;
try sema.mod.declareDeclDependency(sema.owner_decl, declaration_ty_decl);
try sema.ensureDeclAnalyzed(declaration_ty_decl);
@ -11069,7 +11088,10 @@ fn typeInfoDecls(
try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
);
break :v try Value.Tag.decl_ref.create(decls_anon_decl.arena(), new_decl);
break :v try Value.Tag.slice.create(decls_anon_decl.arena(), .{
.ptr = try Value.Tag.decl_ref.create(decls_anon_decl.arena(), new_decl),
.len = try Value.Tag.int_u64.create(decls_anon_decl.arena(), bytes.len),
});
};
const fields = try decls_anon_decl.arena().create([2]Value);
@ -11092,7 +11114,10 @@ fn typeInfoDecls(
try decls_anon_decl.arena().dupe(Value, decls_vals),
),
);
return try Value.Tag.decl_ref.create(sema.arena, new_decl);
return try Value.Tag.slice.create(sema.arena, .{
.ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
.len = try Value.Tag.int_u64.create(sema.arena, decls_vals.len),
});
}
fn zirTypeof(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@ -16574,8 +16599,20 @@ fn elemVal(
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_val = try slice_val.elemValue(sema.arena, index);
return sema.addConstant(array_ty.elemType2(), elem_val);
const elem_ty = array_ty.elemType2();
var payload: Value.Payload.ElemPtr = .{ .data = .{
.array_ptr = slice_val.slicePtr(),
.elem_ty = elem_ty,
.index = index,
} };
const elem_ptr_val = Value.initPayload(&payload.base);
if (try sema.pointerDeref(block, array_src, elem_ptr_val, array_ty)) |elem_val| {
return sema.addConstant(elem_ty, elem_val);
}
break :rs array_src;
} else array_src;
try sema.requireRuntimeBlock(block, runtime_src);
@ -16589,8 +16626,19 @@ fn elemVal(
const array_val = maybe_array_val orelse break :rs array_src;
const index_val = maybe_index_val orelse break :rs elem_index_src;
const index = @intCast(usize, index_val.toUnsignedInt());
const elem_val = try array_val.elemValue(sema.arena, index);
return sema.addConstant(array_ty.elemType2(), elem_val);
const elem_ty = array_ty.elemType2();
var payload: Value.Payload.ElemPtr = .{ .data = .{
.array_ptr = array_val,
.elem_ty = elem_ty,
.index = index,
} };
const elem_ptr_val = Value.initPayload(&payload.base);
if (try sema.pointerDeref(block, array_src, elem_ptr_val, array_ty)) |elem_val| {
return sema.addConstant(elem_ty, elem_val);
}
break :rs array_src;
};
try sema.requireRuntimeBlock(block, runtime_src);
@ -16739,7 +16787,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.elemPtrDirect(array_ptr_ty, 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);
}
}

View File

@ -505,7 +505,6 @@ pub const Value = extern union {
.array_ptr = try payload.data.array_ptr.copy(arena),
.elem_ty = try payload.data.elem_ty.copy(arena),
.index = payload.data.index,
.direct = payload.data.direct,
},
};
return Value{ .ptr_otherwise = &new_payload.base };
@ -2403,11 +2402,7 @@ pub const Value = extern union {
.decl_ref_mut => return val.castTag(.decl_ref_mut).?.data.decl.val.elemValueAdvanced(index, arena, buffer),
.elem_ptr => {
const data = val.castTag(.elem_ptr).?.data;
if (!data.direct)
return data.array_ptr.elemValueAdvanced(index + data.index, arena, buffer);
const underlying = try data.array_ptr.elemValueAdvanced(data.index, arena, buffer);
return underlying.elemValueAdvanced(index, arena, buffer);
return data.array_ptr.elemValueAdvanced(index + data.index, arena, buffer);
},
// The child type of arrays which have only one possible value need
@ -2470,25 +2465,12 @@ pub const Value = extern union {
/// Returns a pointer to the element value at the index.
pub fn elemPtr(val: Value, ty: Type, arena: Allocator, index: usize) Allocator.Error!Value {
return val.elemPtrAdvanced(ty, arena, index, false);
}
/// Returns a pointer to the element value at the index. The behavior
/// of this is slightly different for comptime; the "direct" means that
/// indexing indexes the referenced child value, not the parent array.
pub fn elemPtrDirect(val: Value, ty: Type, arena: Allocator, index: usize) Allocator.Error!Value {
return val.elemPtrAdvanced(ty, arena, index, true);
}
pub fn elemPtrAdvanced(val: Value, ty: Type, arena: Allocator, index: usize, direct: bool) Allocator.Error!Value {
const elem_ty = ty.elemType2();
const ptr_val = switch (val.tag()) {
.slice => val.castTag(.slice).?.data.ptr,
else => val,
};
// If the val is already an elem ptr, then we do ptr arithmetic logic
// and just move the index.
if (ptr_val.tag() == .elem_ptr) {
const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
if (elem_ptr.elem_ty.eql(elem_ty)) {
@ -2496,12 +2478,6 @@ pub const Value = extern union {
.array_ptr = elem_ptr.array_ptr,
.elem_ty = elem_ptr.elem_ty,
.index = elem_ptr.index + index,
// Retain the direct preference. This enables a direct
// elem ptr (i.e. &arr[0]) to be bitcasted to a many-pointer
// with pointer arithmetic then casted back to a single
// pointer.
.direct = elem_ptr.direct,
});
}
}
@ -2509,7 +2485,6 @@ pub const Value = extern union {
.array_ptr = ptr_val,
.elem_ty = elem_ty,
.index = index,
.direct = direct,
});
}
@ -4219,7 +4194,6 @@ pub const Value = extern union {
array_ptr: Value,
elem_ty: Type,
index: usize,
direct: bool,
},
};