Commit 0707be8de8
Changed files (13)
lib
std
src-self-hosted
test
lib/std/mem.zig
@@ -560,7 +560,7 @@ pub fn span(ptr: var) Span(@TypeOf(ptr)) {
test "span" {
var array: [5]u16 = [_]u16{ 1, 2, 3, 4, 5 };
- const ptr = array[0..2 :3].ptr;
+ const ptr = @as([*:3]u16, array[0..2 :3]);
testing.expect(eql(u16, span(ptr), &[_]u16{ 1, 2 }));
testing.expect(eql(u16, span(&array), &[_]u16{ 1, 2, 3, 4, 5 }));
}
@@ -602,7 +602,7 @@ test "len" {
testing.expect(len(&array) == 5);
testing.expect(len(array[0..3]) == 3);
array[2] = 0;
- const ptr = array[0..2 :0].ptr;
+ const ptr = @as([*:0]u16, array[0..2 :0]);
testing.expect(len(ptr) == 2);
}
{
src/all_types.hpp
@@ -231,6 +231,7 @@ enum ConstPtrSpecial {
// The pointer is a reference to a single object.
ConstPtrSpecialRef,
// The pointer points to an element in an underlying array.
+ // Not to be confused with ConstPtrSpecialSubArray.
ConstPtrSpecialBaseArray,
// The pointer points to a field in an underlying struct.
ConstPtrSpecialBaseStruct,
@@ -257,6 +258,10 @@ enum ConstPtrSpecial {
// types to be the same, so all optionals of pointer types use x_ptr
// instead of x_optional.
ConstPtrSpecialNull,
+ // The pointer points to a sub-array (not an individual element).
+ // Not to be confused with ConstPtrSpecialBaseArray. However, it uses the same
+ // union payload struct (base_array).
+ ConstPtrSpecialSubArray,
};
enum ConstPtrMut {
src/analyze.cpp
@@ -5280,6 +5280,11 @@ static uint32_t hash_const_val_ptr(ZigValue *const_val) {
hash_val += hash_ptr(const_val->data.x_ptr.data.base_array.array_val);
hash_val += hash_size(const_val->data.x_ptr.data.base_array.elem_index);
return hash_val;
+ case ConstPtrSpecialSubArray:
+ hash_val += (uint32_t)2643358777;
+ hash_val += hash_ptr(const_val->data.x_ptr.data.base_array.array_val);
+ hash_val += hash_size(const_val->data.x_ptr.data.base_array.elem_index);
+ return hash_val;
case ConstPtrSpecialBaseStruct:
hash_val += (uint32_t)3518317043;
hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val);
@@ -6746,6 +6751,7 @@ bool const_values_equal_ptr(ZigValue *a, ZigValue *b) {
return false;
return true;
case ConstPtrSpecialBaseArray:
+ case ConstPtrSpecialSubArray:
if (a->data.x_ptr.data.base_array.array_val != b->data.x_ptr.data.base_array.array_val) {
return false;
}
@@ -7003,6 +7009,7 @@ static void render_const_val_ptr(CodeGen *g, Buf *buf, ZigValue *const_val, ZigT
render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
return;
case ConstPtrSpecialBaseArray:
+ case ConstPtrSpecialSubArray:
buf_appendf(buf, "*");
// TODO we need a source node for const_ptr_pointee because it can generate compile errors
render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
src/codegen.cpp
@@ -5418,8 +5418,6 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
ZigType *array_type = array_ptr_type->data.pointer.child_type;
LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);
- LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc);
-
bool want_runtime_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base);
ZigType *result_type = instruction->base.value->type;
@@ -5472,6 +5470,8 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
}
}
if (!type_has_bits(g, array_type)) {
+ LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc);
+
LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, "");
// TODO if runtime safety is on, store 0xaaaaaaa in ptr field
@@ -5486,20 +5486,20 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
};
LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, "");
if (result_type->id == ZigTypeIdPointer) {
+ ir_assert(instruction->result_loc == nullptr, &instruction->base);
LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type);
- LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, "");
- gen_store_untyped(g, bitcasted, tmp_struct_ptr, 0, false);
- return slice_start_ptr;
+ return LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, "");
} else {
+ LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc);
LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_ptr_index, "");
gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, "");
LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
gen_store_untyped(g, len_value, len_field_ptr, 0, false);
- }
- return tmp_struct_ptr;
+ return tmp_struct_ptr;
+ }
} else if (array_type->id == ZigTypeIdPointer) {
assert(array_type->data.pointer.ptr_len != PtrLenSingle);
LLVMValueRef start_val = ir_llvm_value(g, instruction->start);
@@ -5515,12 +5515,12 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, "");
if (result_type->id == ZigTypeIdPointer) {
+ ir_assert(instruction->result_loc == nullptr, &instruction->base);
LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type);
- LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, "");
- gen_store_untyped(g, bitcasted, tmp_struct_ptr, 0, false);
- return bitcasted;
+ return LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, "");
}
+ LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc);
if (type_has_bits(g, array_type)) {
size_t gen_ptr_index = result_type->data.structure.fields[slice_ptr_index]->gen_index;
LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_ptr_index, "");
@@ -5537,9 +5537,6 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
assert(array_type->data.structure.special == StructSpecialSlice);
assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
- if (result_type->id != ZigTypeIdPointer) {
- assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(tmp_struct_ptr))) == LLVMStructTypeKind);
- }
size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index;
assert(ptr_index != SIZE_MAX);
@@ -5578,11 +5575,11 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr, &start_val, 1, "");
if (result_type->id == ZigTypeIdPointer) {
+ ir_assert(instruction->result_loc == nullptr, &instruction->base);
LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type);
- LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, "");
- gen_store_untyped(g, bitcasted, tmp_struct_ptr, 0, false);
- return bitcasted;
+ return LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, "");
} else {
+ LLVMValueRef tmp_struct_ptr = ir_llvm_value(g, instruction->result_loc);
LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, (unsigned)ptr_index, "");
gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
@@ -6676,7 +6673,6 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ZigValue *array_co
};
return LLVMConstInBoundsGEP(base_ptr, indices, 2);
} else {
- assert(parent->id == ConstParentIdScalar);
return base_ptr;
}
}
@@ -6904,6 +6900,7 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ZigValue *const_val, const cha
return const_val->llvm_value;
}
case ConstPtrSpecialBaseArray:
+ case ConstPtrSpecialSubArray:
{
ZigValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;
assert(array_const_val->type->id == ZigTypeIdArray);
src/ir.cpp
@@ -784,14 +784,32 @@ static ZigValue *const_ptr_pointee_unchecked_no_isf(CodeGen *g, ZigValue *const_
break;
case ConstPtrSpecialBaseArray: {
ZigValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
- if (const_val->data.x_ptr.data.base_array.elem_index == array_val->type->data.array.len) {
+ size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
+ if (elem_index == array_val->type->data.array.len) {
result = array_val->type->data.array.sentinel;
} else {
expand_undef_array(g, array_val);
- result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];
+ result = &array_val->data.x_array.data.s_none.elements[elem_index];
}
break;
}
+ case ConstPtrSpecialSubArray: {
+ ZigValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
+ size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
+
+ // TODO handle sentinel terminated arrays
+ expand_undef_array(g, array_val);
+ result = g->pass1_arena->create<ZigValue>();
+ result->special = array_val->special;
+ result->type = get_array_type(g, array_val->type->data.array.child_type,
+ array_val->type->data.array.len - elem_index, nullptr);
+ result->data.x_array.special = ConstArraySpecialNone;
+ result->data.x_array.data.s_none.elements = &array_val->data.x_array.data.s_none.elements[elem_index];
+ result->parent.id = ConstParentIdArray;
+ result->parent.data.p_array.array_val = array_val;
+ result->parent.data.p_array.elem_index = elem_index;
+ break;
+ }
case ConstPtrSpecialBaseStruct: {
ZigValue *struct_val = const_val->data.x_ptr.data.base_struct.struct_val;
expand_undef_struct(g, struct_val);
@@ -3727,8 +3745,8 @@ static IrInstGen *ir_build_slice_gen(IrAnalyze *ira, IrInst *source_instruction,
ir_ref_inst_gen(ptr, ira->new_irb.current_basic_block);
ir_ref_inst_gen(start, ira->new_irb.current_basic_block);
- if (end) ir_ref_inst_gen(end, ira->new_irb.current_basic_block);
- ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block);
+ if (end != nullptr) ir_ref_inst_gen(end, ira->new_irb.current_basic_block);
+ if (result_loc != nullptr) ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block);
return &instruction->base;
}
@@ -12672,40 +12690,63 @@ static IrInstGen *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInst* sourc
Error err;
assert(array_ptr->value->type->id == ZigTypeIdPointer);
+ assert(array_ptr->value->type->data.pointer.child_type->id == ZigTypeIdArray);
- if ((err = type_resolve(ira->codegen, array_ptr->value->type, ResolveStatusAlignmentKnown))) {
- return ira->codegen->invalid_inst_gen;
- }
+ ZigType *array_type = array_ptr->value->type->data.pointer.child_type;
+ const size_t array_len = array_type->data.array.len;
- assert(array_ptr->value->type->data.pointer.child_type->id == ZigTypeIdArray);
+ // A zero-sized array can be casted regardless of the destination alignment, or
+ // whether the pointer is undefined, and the result is always comptime known.
+ if (array_len == 0) {
+ ZigValue *undef_array = ira->codegen->pass1_arena->create<ZigValue>();
+ undef_array->special = ConstValSpecialUndef;
+ undef_array->type = array_type;
- const size_t array_len = array_ptr->value->type->data.pointer.child_type->data.array.len;
+ IrInstGen *result = ir_const(ira, source_instr, wanted_type);
+ init_const_slice(ira->codegen, result->value, undef_array, 0, 0, false);
+ result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = ConstPtrMutComptimeConst;
+ result->value->type = wanted_type;
+ return result;
+ }
- // A zero-sized array can always be casted irregardless of the destination
- // alignment
- if (array_len != 0) {
- wanted_type = adjust_slice_align(ira->codegen, wanted_type,
- get_ptr_align(ira->codegen, array_ptr->value->type));
+ if ((err = type_resolve(ira->codegen, array_ptr->value->type, ResolveStatusAlignmentKnown))) {
+ return ira->codegen->invalid_inst_gen;
}
+ wanted_type = adjust_slice_align(ira->codegen, wanted_type,
+ get_ptr_align(ira->codegen, array_ptr->value->type));
+
if (instr_is_comptime(array_ptr)) {
ZigValue *array_ptr_val = ir_resolve_const(ira, array_ptr, UndefBad);
if (array_ptr_val == nullptr)
return ira->codegen->invalid_inst_gen;
- ZigValue *pointee = const_ptr_pointee(ira, ira->codegen, array_ptr_val, source_instr->source_node);
- if (pointee == nullptr)
- return ira->codegen->invalid_inst_gen;
- if (pointee->special != ConstValSpecialRuntime) {
- assert(array_ptr_val->type->id == ZigTypeIdPointer);
- ZigType *array_type = array_ptr_val->type->data.pointer.child_type;
- assert(is_slice(wanted_type));
- bool is_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const;
+ ir_assert(is_slice(wanted_type), source_instr);
+ bool wanted_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const;
+ // Optimization to avoid creating unnecessary ZigValue in const_ptr_pointee
+ if (array_ptr_val->data.x_ptr.special == ConstPtrSpecialSubArray) {
+ ZigValue *array_val = array_ptr_val->data.x_ptr.data.base_array.array_val;
+ if (array_val->special != ConstValSpecialRuntime) {
+ IrInstGen *result = ir_const(ira, source_instr, wanted_type);
+ init_const_slice(ira->codegen, result->value, array_val,
+ array_ptr_val->data.x_ptr.data.base_array.elem_index,
+ array_type->data.array.len, wanted_const);
+ result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut;
+ result->value->type = wanted_type;
+ return result;
+ }
+ } else {
+ ZigValue *pointee = const_ptr_pointee(ira, ira->codegen, array_ptr_val, source_instr->source_node);
+ if (pointee == nullptr)
+ return ira->codegen->invalid_inst_gen;
+ if (pointee->special != ConstValSpecialRuntime) {
+ assert(array_ptr_val->type->id == ZigTypeIdPointer);
- IrInstGen *result = ir_const(ira, source_instr, wanted_type);
- init_const_slice(ira->codegen, result->value, pointee, 0, array_type->data.array.len, is_const);
- result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut;
- result->value->type = wanted_type;
- return result;
+ IrInstGen *result = ir_const(ira, source_instr, wanted_type);
+ init_const_slice(ira->codegen, result->value, pointee, 0, array_type->data.array.len, wanted_const);
+ result->value->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut;
+ result->value->type = wanted_type;
+ return result;
+ }
}
}
@@ -19931,6 +19972,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
dst_size, buf_ptr(&pointee->type->name), src_size));
return ErrorSemanticAnalyzeFail;
}
+ case ConstPtrSpecialSubArray:
case ConstPtrSpecialBaseArray: {
ZigValue *array_val = ptr_val->data.x_ptr.data.base_array.array_val;
assert(array_val->type->id == ZigTypeIdArray);
@@ -20814,6 +20856,7 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP
}
break;
case ConstPtrSpecialBaseArray:
+ case ConstPtrSpecialSubArray:
{
size_t offset = array_ptr_val->data.x_ptr.data.base_array.elem_index;
new_index = offset + index;
@@ -20884,6 +20927,7 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP
out_val->data.x_ptr.special = ConstPtrSpecialRef;
out_val->data.x_ptr.data.ref.pointee = ptr_field->data.x_ptr.data.ref.pointee;
break;
+ case ConstPtrSpecialSubArray:
case ConstPtrSpecialBaseArray:
{
size_t offset = ptr_field->data.x_ptr.data.base_array.elem_index;
@@ -25894,6 +25938,7 @@ static IrInstGen *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstSrcMemset
start = 0;
bound_end = 1;
break;
+ case ConstPtrSpecialSubArray:
case ConstPtrSpecialBaseArray:
{
ZigValue *array_val = dest_ptr_val->data.x_ptr.data.base_array.array_val;
@@ -26027,6 +26072,7 @@ static IrInstGen *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstSrcMemcpy
dest_start = 0;
dest_end = 1;
break;
+ case ConstPtrSpecialSubArray:
case ConstPtrSpecialBaseArray:
{
ZigValue *array_val = dest_ptr_val->data.x_ptr.data.base_array.array_val;
@@ -26070,6 +26116,7 @@ static IrInstGen *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstSrcMemcpy
src_start = 0;
src_end = 1;
break;
+ case ConstPtrSpecialSubArray:
case ConstPtrSpecialBaseArray:
{
ZigValue *array_val = src_ptr_val->data.x_ptr.data.base_array.array_val;
@@ -26219,7 +26266,8 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
ZigType *return_type;
if (value_is_comptime(casted_start->value) &&
- ((end != nullptr && value_is_comptime(end->value)) || array_type->id == ZigTypeIdArray ))
+ ((end != nullptr && value_is_comptime(end->value)) ||
+ (end == nullptr && array_type->id == ZigTypeIdArray)))
{
ZigValue *start_val = ir_resolve_const(ira, casted_start, UndefBad);
if (!start_val)
@@ -26244,13 +26292,16 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
return ira->codegen->invalid_inst_gen;
}
+ // TODO in the case of non-zero start index, the byte alignment should be smarter here.
+ // we should be able to use the same logic as indexing.
+ uint32_t ptr_byte_alignment = ((end_scalar - start_scalar != 0) && start_scalar == 0) ?
+ non_sentinel_slice_ptr_type->data.pointer.explicit_alignment : 0;
ZigType *return_array_type = get_array_type(ira->codegen, elem_type, end_scalar - start_scalar,
array_sentinel);
return_type = get_pointer_to_type_extra(ira->codegen, return_array_type,
non_sentinel_slice_ptr_type->data.pointer.is_const,
non_sentinel_slice_ptr_type->data.pointer.is_volatile,
- PtrLenSingle,
- 0, 0, 0, false);
+ PtrLenSingle, ptr_byte_alignment, 0, 0, false);
} else if (sentinel_val != nullptr) {
ZigType *slice_ptr_type = adjust_ptr_sentinel(ira->codegen, non_sentinel_slice_ptr_type, sentinel_val);
return_type = get_slice_type(ira->codegen, slice_ptr_type);
@@ -26283,6 +26334,10 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
abs_offset = 0;
rel_end = SIZE_MAX;
ptr_is_undef = true;
+ } else if (parent_ptr->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
+ array_val = nullptr;
+ abs_offset = 0;
+ rel_end = SIZE_MAX;
} else {
array_val = const_ptr_pointee(ira, ira->codegen, parent_ptr, instruction->base.base.source_node);
if (array_val == nullptr)
@@ -26325,6 +26380,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
rel_end = 1;
}
break;
+ case ConstPtrSpecialSubArray:
case ConstPtrSpecialBaseArray:
array_val = parent_ptr->data.x_ptr.data.base_array.array_val;
abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index;
@@ -26375,6 +26431,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
abs_offset = SIZE_MAX;
rel_end = 1;
break;
+ case ConstPtrSpecialSubArray:
case ConstPtrSpecialBaseArray:
array_val = parent_ptr->data.x_ptr.data.base_array.array_val;
abs_offset = parent_ptr->data.x_ptr.data.base_array.elem_index;
@@ -26454,6 +26511,9 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
if (array_val) {
size_t index = abs_offset + start_scalar;
init_const_ptr_array(ira->codegen, ptr_val, array_val, index, return_type_is_const, PtrLenUnknown);
+ if (return_type->id == ZigTypeIdPointer) {
+ ptr_val->data.x_ptr.special = ConstPtrSpecialSubArray;
+ }
if (array_type->id == ZigTypeIdArray) {
ptr_val->data.x_ptr.mut = ptr_ptr->value->data.x_ptr.mut;
} else if (is_slice(array_type)) {
@@ -26463,7 +26523,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
}
} else if (ptr_is_undef) {
ptr_val->type = get_pointer_to_type(ira->codegen, parent_ptr->type->data.pointer.child_type,
- return_type_is_const);
+ return_type_is_const);
ptr_val->special = ConstValSpecialUndef;
} else switch (parent_ptr->data.x_ptr.special) {
case ConstPtrSpecialInvalid:
@@ -26473,6 +26533,7 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
init_const_ptr_ref(ira->codegen, ptr_val, parent_ptr->data.x_ptr.data.ref.pointee,
return_type_is_const);
break;
+ case ConstPtrSpecialSubArray:
case ConstPtrSpecialBaseArray:
zig_unreachable();
case ConstPtrSpecialBaseStruct:
@@ -26500,20 +26561,6 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
return result;
}
- IrInstGen *result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc,
- return_type, nullptr, true, true);
- if (result_loc != nullptr) {
- if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) {
- return result_loc;
- }
- IrInstGen *dummy_value = ir_const(ira, &instruction->base.base, return_type);
- dummy_value->value->special = ConstValSpecialRuntime;
- IrInstGen *dummy_result = ir_implicit_cast2(ira, &instruction->base.base,
- dummy_value, result_loc->value->type->data.pointer.child_type);
- if (type_is_invalid(dummy_result->value->type))
- return ira->codegen->invalid_inst_gen;
- }
-
if (generate_non_null_assert) {
IrInstGen *ptr_val = ir_get_deref(ira, &instruction->base.base, ptr_ptr, nullptr);
@@ -26523,6 +26570,24 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
ir_build_assert_non_null(ira, &instruction->base.base, ptr_val);
}
+ IrInstGen *result_loc = nullptr;
+
+ if (return_type->id != ZigTypeIdPointer) {
+ result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc,
+ return_type, nullptr, true, true);
+ if (result_loc != nullptr) {
+ if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) {
+ return result_loc;
+ }
+ IrInstGen *dummy_value = ir_const(ira, &instruction->base.base, return_type);
+ dummy_value->value->special = ConstValSpecialRuntime;
+ IrInstGen *dummy_result = ir_implicit_cast2(ira, &instruction->base.base,
+ dummy_value, result_loc->value->type->data.pointer.child_type);
+ if (type_is_invalid(dummy_result->value->type))
+ return ira->codegen->invalid_inst_gen;
+ }
+ }
+
return ir_build_slice_gen(ira, &instruction->base.base, return_type, ptr_ptr,
casted_start, end, instruction->safety_check_on, result_loc);
}
src-self-hosted/stage2.zig
@@ -128,7 +128,7 @@ export fn stage2_translate_c(
args_end: [*]?[*]const u8,
resources_path: [*:0]const u8,
) Error {
- var errors = @as([*]translate_c.ClangErrMsg, undefined)[0..0];
+ var errors: []translate_c.ClangErrMsg = &[0]translate_c.ClangErrMsg{};
out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, &errors, resources_path) catch |err| switch (err) {
error.SemanticAnalyzeFail => {
out_errors_ptr.* = errors.ptr;
test/stage1/behavior/align.zig
@@ -171,18 +171,19 @@ test "runtime known array index has best alignment possible" {
// because pointer is align 2 and u32 align % 2 == 0 we can assume align 2
var smaller align(2) = [_]u32{ 1, 2, 3, 4 };
- comptime expect(@TypeOf(smaller[0..]) == []align(2) u32);
- comptime expect(@TypeOf(smaller[0..].ptr) == [*]align(2) u32);
- testIndex(smaller[0..].ptr, 0, *align(2) u32);
- testIndex(smaller[0..].ptr, 1, *align(2) u32);
- testIndex(smaller[0..].ptr, 2, *align(2) u32);
- testIndex(smaller[0..].ptr, 3, *align(2) u32);
+ var runtime_zero: usize = 0;
+ comptime expect(@TypeOf(smaller[runtime_zero..]) == []align(2) u32);
+ comptime expect(@TypeOf(smaller[runtime_zero..].ptr) == [*]align(2) u32);
+ testIndex(smaller[runtime_zero..].ptr, 0, *align(2) u32);
+ testIndex(smaller[runtime_zero..].ptr, 1, *align(2) u32);
+ testIndex(smaller[runtime_zero..].ptr, 2, *align(2) u32);
+ testIndex(smaller[runtime_zero..].ptr, 3, *align(2) u32);
// has to use ABI alignment because index known at runtime only
- testIndex2(array[0..].ptr, 0, *u8);
- testIndex2(array[0..].ptr, 1, *u8);
- testIndex2(array[0..].ptr, 2, *u8);
- testIndex2(array[0..].ptr, 3, *u8);
+ testIndex2(array[runtime_zero..].ptr, 0, *u8);
+ testIndex2(array[runtime_zero..].ptr, 1, *u8);
+ testIndex2(array[runtime_zero..].ptr, 2, *u8);
+ testIndex2(array[runtime_zero..].ptr, 3, *u8);
}
fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void {
comptime expect(@TypeOf(&smaller[index]) == T);
test/stage1/behavior/cast.zig
@@ -435,7 +435,8 @@ fn incrementVoidPtrValue(value: ?*c_void) void {
test "implicit cast from [*]T to ?*c_void" {
var a = [_]u8{ 3, 2, 1 };
- incrementVoidPtrArray(a[0..].ptr, 3);
+ var runtime_zero: usize = 0;
+ incrementVoidPtrArray(a[runtime_zero..].ptr, 3);
expect(std.mem.eql(u8, &a, &[_]u8{ 4, 3, 2 }));
}
test/stage1/behavior/eval.zig
@@ -524,7 +524,7 @@ test "comptime slice of slice preserves comptime var" {
test "comptime slice of pointer preserves comptime var" {
comptime {
var buff: [10]u8 = undefined;
- var a = buff[0..].ptr;
+ var a = @ptrCast([*]u8, &buff);
a[0..1][0] = 1;
expect(buff[0..][0..][0] == 1);
}
test/stage1/behavior/misc.zig
@@ -102,8 +102,8 @@ test "memcpy and memset intrinsics" {
var foo: [20]u8 = undefined;
var bar: [20]u8 = undefined;
- @memset(foo[0..].ptr, 'A', foo.len);
- @memcpy(bar[0..].ptr, foo[0..].ptr, bar.len);
+ @memset(&foo, 'A', foo.len);
+ @memcpy(&bar, &foo, bar.len);
if (bar[11] != 'A') unreachable;
}
@@ -565,12 +565,16 @@ test "volatile load and store" {
expect(ptr.* == 1235);
}
-test "slice string literal has type []const u8" {
+test "slice string literal has correct type" {
comptime {
- expect(@TypeOf("aoeu"[0..]) == []const u8);
+ expect(@TypeOf("aoeu"[0..]) == *const [4:0]u8);
const array = [_]i32{ 1, 2, 3, 4 };
- expect(@TypeOf(array[0..]) == []const i32);
+ expect(@TypeOf(array[0..]) == *const [4]i32);
}
+ var runtime_zero: usize = 0;
+ expect(@TypeOf("aoeu"[runtime_zero..]) == [:0]const u8);
+ const array = [_]i32{ 1, 2, 3, 4 };
+ expect(@TypeOf(array[runtime_zero..]) == []const u8);
}
test "pointer child field" {
test/stage1/behavior/ptrcast.zig
@@ -13,7 +13,7 @@ fn testReinterpretBytesAsInteger() void {
builtin.Endian.Little => 0xab785634,
builtin.Endian.Big => 0x345678ab,
};
- expect(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected);
+ expect(@ptrCast(*align(1) const u32, bytes[1..5]).* == expected);
}
test "reinterpret bytes of an array into an extern struct" {
test/stage1/behavior/slice.zig
@@ -7,7 +7,7 @@ const mem = std.mem;
const x = @intToPtr([*]i32, 0x1000)[0..0x500];
const y = x[0x100..];
test "compile time slice of pointer to hard coded address" {
- expect(@ptrToInt(x.ptr) == 0x1000);
+ expect(@ptrToInt(x) == 0x1000);
expect(x.len == 0x500);
expect(@ptrToInt(y.ptr) == 0x1100);
@@ -47,7 +47,9 @@ test "C pointer slice access" {
var buf: [10]u32 = [1]u32{42} ** 10;
const c_ptr = @ptrCast([*c]const u32, &buf);
- comptime expectEqual([]const u32, @TypeOf(c_ptr[0..1]));
+ var runtime_zero: usize = 0;
+ comptime expectEqual([]const u32, @TypeOf(c_ptr[runtime_zero..1]));
+ comptime expectEqual(*const [1]u32, @TypeOf(c_ptr[0..1]));
for (c_ptr[0..5]) |*cl| {
expectEqual(@as(u32, 42), cl.*);
@@ -107,7 +109,9 @@ test "obtaining a null terminated slice" {
const ptr2 = buf[0..runtime_len :0];
// ptr2 is a null-terminated slice
comptime expect(@TypeOf(ptr2) == [:0]u8);
- comptime expect(@TypeOf(ptr2[0..2]) == []u8);
+ comptime expect(@TypeOf(ptr2[0..2]) == *[2]u8);
+ var runtime_zero: usize = 0;
+ comptime expect(@TypeOf(ptr2[runtime_zero..2]) == []u8);
}
test "empty array to slice" {
test/stage1/behavior/struct.zig
@@ -409,8 +409,8 @@ const Bitfields = packed struct {
test "native bit field understands endianness" {
var all: u64 = 0x7765443322221111;
var bytes: [8]u8 = undefined;
- @memcpy(bytes[0..].ptr, @ptrCast([*]u8, &all), 8);
- var bitfields = @ptrCast(*Bitfields, bytes[0..].ptr).*;
+ @memcpy(&bytes, @ptrCast([*]u8, &all), 8);
+ var bitfields = @ptrCast(*Bitfields, &bytes).*;
expect(bitfields.f1 == 0x1111);
expect(bitfields.f2 == 0x2222);