Skip to content

Commit

Permalink
add peer type resolution for mixed-const []T and *[N]T
Browse files Browse the repository at this point in the history
closes #4766

This commit also fixes the implementation of some utility functions for
adjusting properties of pointer types. Previously these functions would
incorrectly drop vector, sentinel, and inference metadata.
  • Loading branch information
andrewrk committed Mar 30, 2020
1 parent ef419dd commit b980568
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 17 deletions.
78 changes: 61 additions & 17 deletions src/ir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op);
static IrInstSrc *ir_lval_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *value, LVal lval, ResultLoc *result_loc);
static IrInstSrc *ir_expr_wrap(IrBuilderSrc *irb, Scope *scope, IrInstSrc *inst, ResultLoc *result_loc);
static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);
static ZigType *adjust_ptr_const(CodeGen *g, ZigType *ptr_type, bool is_const);
static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);
static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ZigValue *val);
static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val);
Expand Down Expand Up @@ -11844,6 +11845,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT

bool any_are_null = (prev_inst->value->type->id == ZigTypeIdNull);
bool convert_to_const_slice = false;
bool make_the_slice_const = false;
for (; i < instruction_count; i += 1) {
IrInstGen *cur_inst = instructions[i];
ZigType *cur_type = cur_inst->value->type;
Expand Down Expand Up @@ -12357,12 +12359,12 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
ZigType *slice_type = (prev_type->id == ZigTypeIdErrorUnion) ?
prev_type->data.error_union.payload_type : prev_type;
ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||
!cur_type->data.pointer.is_const) &&
types_match_const_cast_only(ira,
slice_ptr_type->data.pointer.child_type,
if (types_match_const_cast_only(ira, slice_ptr_type->data.pointer.child_type,
array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)
{
bool const_ok = (slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||
!cur_type->data.pointer.is_const);
if (!const_ok) make_the_slice_const = true;
convert_to_const_slice = false;
continue;
}
Expand Down Expand Up @@ -12391,12 +12393,12 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
break;
}
ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||
!prev_type->data.pointer.is_const) &&
types_match_const_cast_only(ira,
slice_ptr_type->data.pointer.child_type,
if (types_match_const_cast_only(ira, slice_ptr_type->data.pointer.child_type,
array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)
{
bool const_ok = (slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||
!prev_type->data.pointer.is_const);
if (!const_ok) make_the_slice_const = true;
prev_inst = cur_inst;
convert_to_const_slice = false;
continue;
Expand All @@ -12408,8 +12410,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
cur_type->data.pointer.child_type->id == ZigTypeIdArray &&
prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenSingle &&
prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
(cur_type->data.pointer.is_const || !prev_type->data.pointer.is_const ||
prev_type->data.pointer.child_type->data.array.len == 0) &&
(
prev_type->data.pointer.child_type->data.array.sentinel == nullptr ||
(cur_type->data.pointer.child_type->data.array.sentinel != nullptr &&
Expand All @@ -12421,6 +12421,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
prev_type->data.pointer.child_type->data.array.child_type,
source_node, !cur_type->data.pointer.is_const).id == ConstCastResultIdOk)
{
bool const_ok = (cur_type->data.pointer.is_const || !prev_type->data.pointer.is_const ||
prev_type->data.pointer.child_type->data.array.len == 0);
if (!const_ok) make_the_slice_const = true;
prev_inst = cur_inst;
convert_to_const_slice = true;
continue;
Expand All @@ -12429,8 +12432,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenSingle &&
cur_type->data.pointer.child_type->id == ZigTypeIdArray &&
(prev_type->data.pointer.is_const || !cur_type->data.pointer.is_const ||
cur_type->data.pointer.child_type->data.array.len == 0) &&
(
cur_type->data.pointer.child_type->data.array.sentinel == nullptr ||
(prev_type->data.pointer.child_type->data.array.sentinel != nullptr &&
Expand All @@ -12442,6 +12443,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
cur_type->data.pointer.child_type->data.array.child_type,
source_node, !prev_type->data.pointer.is_const).id == ConstCastResultIdOk)
{
bool const_ok = (prev_type->data.pointer.is_const || !cur_type->data.pointer.is_const ||
cur_type->data.pointer.child_type->data.array.len == 0);
if (!const_ok) make_the_slice_const = true;
convert_to_const_slice = true;
continue;
}
Expand Down Expand Up @@ -12486,7 +12490,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
src_assert(array_type->id == ZigTypeIdArray, source_node);
ZigType *ptr_type = get_pointer_to_type_extra2(
ira->codegen, array_type->data.array.child_type,
prev_inst->value->type->data.pointer.is_const, false,
prev_inst->value->type->data.pointer.is_const || make_the_slice_const, false,
PtrLenUnknown,
0, 0, 0, false,
VECTOR_INDEX_NONE, nullptr, array_type->data.array.sentinel);
Expand Down Expand Up @@ -12537,6 +12541,26 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
return ira->codegen->builtin_types.entry_invalid;
return get_optional_type(ira->codegen, prev_inst->value->type);
}
} else if (make_the_slice_const) {
ZigType *slice_type;
if (prev_inst->value->type->id == ZigTypeIdErrorUnion) {
slice_type = prev_inst->value->type->data.error_union.payload_type;
} else if (is_slice(prev_inst->value->type)) {
slice_type = prev_inst->value->type;
} else {
zig_unreachable();
}
ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
ZigType *adjusted_ptr_type = adjust_ptr_const(ira->codegen, slice_ptr_type, make_the_slice_const);
ZigType *adjusted_slice_type = get_slice_type(ira->codegen, adjusted_ptr_type);
if (prev_inst->value->type->id == ZigTypeIdErrorUnion) {
return get_error_union_type(ira->codegen, prev_inst->value->type->data.error_union.err_set_type,
adjusted_slice_type);
} else if (is_slice(prev_inst->value->type)) {
return adjusted_slice_type;
} else {
zig_unreachable();
}
} else {
return prev_inst->value->type;
}
Expand Down Expand Up @@ -20708,24 +20732,44 @@ static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new

static ZigType *adjust_ptr_len(CodeGen *g, ZigType *ptr_type, PtrLen ptr_len) {
assert(ptr_type->id == ZigTypeIdPointer);
return get_pointer_to_type_extra(g,
return get_pointer_to_type_extra2(g,
ptr_type->data.pointer.child_type,
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
ptr_len,
ptr_type->data.pointer.explicit_alignment,
ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,
ptr_type->data.pointer.allow_zero);
ptr_type->data.pointer.allow_zero,
ptr_type->data.pointer.vector_index,
ptr_type->data.pointer.inferred_struct_field,
ptr_type->data.pointer.sentinel);
}

static ZigType *adjust_ptr_allow_zero(CodeGen *g, ZigType *ptr_type, bool allow_zero) {
assert(ptr_type->id == ZigTypeIdPointer);
return get_pointer_to_type_extra(g,
return get_pointer_to_type_extra2(g,
ptr_type->data.pointer.child_type,
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
ptr_type->data.pointer.ptr_len,
ptr_type->data.pointer.explicit_alignment,
ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,
allow_zero);
allow_zero,
ptr_type->data.pointer.vector_index,
ptr_type->data.pointer.inferred_struct_field,
ptr_type->data.pointer.sentinel);
}

static ZigType *adjust_ptr_const(CodeGen *g, ZigType *ptr_type, bool is_const) {
assert(ptr_type->id == ZigTypeIdPointer);
return get_pointer_to_type_extra2(g,
ptr_type->data.pointer.child_type,
is_const, ptr_type->data.pointer.is_volatile,
ptr_type->data.pointer.ptr_len,
ptr_type->data.pointer.explicit_alignment,
ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,
ptr_type->data.pointer.allow_zero,
ptr_type->data.pointer.vector_index,
ptr_type->data.pointer.inferred_struct_field,
ptr_type->data.pointer.sentinel);
}

static Error compute_elem_align(IrAnalyze *ira, ZigType *elem_type, uint32_t base_ptr_align,
Expand Down
15 changes: 15 additions & 0 deletions test/stage1/behavior/cast.zig
Original file line number Diff line number Diff line change
Expand Up @@ -790,3 +790,18 @@ test "assignment to optional pointer result loc" {
var foo: struct { ptr: ?*c_void } = .{ .ptr = &global_struct };
expect(foo.ptr.? == @ptrCast(*c_void, &global_struct));
}

test "peer type resolve string lit with sentinel-terminated mutable slice" {
var array: [4:0]u8 = undefined;
array[4] = 0; // TODO remove this when #4372 is solved
var slice: [:0]u8 = array[0..4 :0];
comptime expect(@TypeOf(slice, "hi") == [:0]const u8);
comptime expect(@TypeOf("hi", slice) == [:0]const u8);
}

test "peer type resolve array pointers, one of them const" {
var array1: [4]u8 = undefined;
const array2: [5]u8 = undefined;
comptime expect(@TypeOf(&array1, &array2) == []const u8);
comptime expect(@TypeOf(&array2, &array1) == []const u8);
}

0 comments on commit b980568

Please sign in to comment.