Skip to content

Commit 38c62a3

Browse files
committed
Pointer Reform: proper slicing and indexing
* enable slicing for single-item ptr to arrays * disable slicing for other single-item pointers * enable indexing for single-item ptr to arrays * disable indexing for other single-item pointers see #770 closes #386
1 parent 32e0dfd commit 38c62a3

21 files changed

+268
-79
lines changed

doc/langref.html.in

+8-5
Original file line numberDiff line numberDiff line change
@@ -1565,7 +1565,7 @@ var foo: u8 align(4) = 100;
15651565
test "global variable alignment" {
15661566
assert(@typeOf(&foo).alignment == 4);
15671567
assert(@typeOf(&foo) == *align(4) u8);
1568-
const slice = (&foo)[0..1];
1568+
const slice = (*[1]u8)(&foo)[0..];
15691569
assert(@typeOf(slice) == []align(4) u8);
15701570
}
15711571

@@ -1671,7 +1671,7 @@ test "using slices for strings" {
16711671

16721672
test "slice pointer" {
16731673
var array: [10]u8 = undefined;
1674-
const ptr = &array[0];
1674+
const ptr = &array;
16751675

16761676
// You can use slicing syntax to convert a pointer into a slice:
16771677
const slice = ptr[0..5];
@@ -6004,9 +6004,12 @@ const c = @cImport({
60046004
{#code_begin|syntax#}
60056005
const base64 = @import("std").base64;
60066006

6007-
export fn decode_base_64(dest_ptr: *u8, dest_len: usize,
6008-
source_ptr: *const u8, source_len: usize) usize
6009-
{
6007+
export fn decode_base_64(
6008+
dest_ptr: [*]u8,
6009+
dest_len: usize,
6010+
source_ptr: [*]const u8,
6011+
source_len: usize,
6012+
) usize {
60106013
const src = source_ptr[0..source_len];
60116014
const dest = dest_ptr[0..dest_len];
60126015
const base64_decoder = base64.standard_decoder_unsafe;

example/mix_o_files/base64.zig

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const base64 = @import("std").base64;
22

3-
export fn decode_base_64(dest_ptr: *u8, dest_len: usize, source_ptr: *const u8, source_len: usize) usize {
3+
export fn decode_base_64(dest_ptr: [*]u8, dest_len: usize, source_ptr: [*]const u8, source_len: usize) usize {
44
const src = source_ptr[0..source_len];
55
const dest = dest_ptr[0..dest_len];
66
const base64_decoder = base64.standard_decoder_unsafe;

src/all_types.hpp

+5
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ enum ConstParentId {
8383
ConstParentIdStruct,
8484
ConstParentIdArray,
8585
ConstParentIdUnion,
86+
ConstParentIdScalar,
8687
};
8788

8889
struct ConstParent {
@@ -100,6 +101,9 @@ struct ConstParent {
100101
struct {
101102
ConstExprValue *union_val;
102103
} p_union;
104+
struct {
105+
ConstExprValue *scalar_val;
106+
} p_scalar;
103107
} data;
104108
};
105109

@@ -578,6 +582,7 @@ enum CastOp {
578582
CastOpBytesToSlice,
579583
CastOpNumLitToConcrete,
580584
CastOpErrSet,
585+
CastOpBitCast,
581586
};
582587

583588
struct AstNodeFnCallExpr {

src/analyze.cpp

+9-5
Original file line numberDiff line numberDiff line change
@@ -5158,7 +5158,8 @@ void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *arr
51585158
const_val->type = get_slice_type(g, ptr_type);
51595159
const_val->data.x_struct.fields = create_const_vals(2);
51605160

5161-
init_const_ptr_array(g, &const_val->data.x_struct.fields[slice_ptr_index], array_val, start, is_const);
5161+
init_const_ptr_array(g, &const_val->data.x_struct.fields[slice_ptr_index], array_val, start, is_const,
5162+
PtrLenUnknown);
51625163
init_const_usize(g, &const_val->data.x_struct.fields[slice_len_index], len);
51635164
}
51645165

@@ -5169,21 +5170,24 @@ ConstExprValue *create_const_slice(CodeGen *g, ConstExprValue *array_val, size_t
51695170
}
51705171

51715172
void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val,
5172-
size_t elem_index, bool is_const)
5173+
size_t elem_index, bool is_const, PtrLen ptr_len)
51735174
{
51745175
assert(array_val->type->id == TypeTableEntryIdArray);
51755176
TypeTableEntry *child_type = array_val->type->data.array.child_type;
51765177

51775178
const_val->special = ConstValSpecialStatic;
5178-
const_val->type = get_pointer_to_type(g, child_type, is_const);
5179+
const_val->type = get_pointer_to_type_extra(g, child_type, is_const, false,
5180+
ptr_len, get_abi_alignment(g, child_type), 0, 0);
51795181
const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
51805182
const_val->data.x_ptr.data.base_array.array_val = array_val;
51815183
const_val->data.x_ptr.data.base_array.elem_index = elem_index;
51825184
}
51835185

5184-
ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index, bool is_const) {
5186+
ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index, bool is_const,
5187+
PtrLen ptr_len)
5188+
{
51855189
ConstExprValue *const_val = create_const_vals(1);
5186-
init_const_ptr_array(g, const_val, array_val, elem_index, is_const);
5190+
init_const_ptr_array(g, const_val, array_val, elem_index, is_const, ptr_len);
51875191
return const_val;
51885192
}
51895193

src/analyze.hpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,9 @@ ConstExprValue *create_const_ptr_hard_coded_addr(CodeGen *g, TypeTableEntry *poi
152152
size_t addr, bool is_const);
153153

154154
void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val,
155-
size_t elem_index, bool is_const);
156-
ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index, bool is_const);
155+
size_t elem_index, bool is_const, PtrLen ptr_len);
156+
ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index,
157+
bool is_const, PtrLen ptr_len);
157158

158159
void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val,
159160
size_t start, size_t len, bool is_const);

src/codegen.cpp

+23-4
Original file line numberDiff line numberDiff line change
@@ -2574,6 +2574,8 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
25742574
add_error_range_check(g, wanted_type, g->err_tag_type, expr_val);
25752575
}
25762576
return expr_val;
2577+
case CastOpBitCast:
2578+
return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, "");
25772579
}
25782580
zig_unreachable();
25792581
}
@@ -2884,7 +2886,13 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
28842886

28852887
bool safety_check_on = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on;
28862888

2887-
if (array_type->id == TypeTableEntryIdArray) {
2889+
if (array_type->id == TypeTableEntryIdArray ||
2890+
(array_type->id == TypeTableEntryIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))
2891+
{
2892+
if (array_type->id == TypeTableEntryIdPointer) {
2893+
assert(array_type->data.pointer.child_type->id == TypeTableEntryIdArray);
2894+
array_type = array_type->data.pointer.child_type;
2895+
}
28882896
if (safety_check_on) {
28892897
LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
28902898
array_type->data.array.len, false);
@@ -3794,7 +3802,12 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
37943802

37953803
bool want_runtime_safety = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base);
37963804

3797-
if (array_type->id == TypeTableEntryIdArray) {
3805+
if (array_type->id == TypeTableEntryIdArray ||
3806+
(array_type->id == TypeTableEntryIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))
3807+
{
3808+
if (array_type->id == TypeTableEntryIdPointer) {
3809+
array_type = array_type->data.pointer.child_type;
3810+
}
37983811
LLVMValueRef start_val = ir_llvm_value(g, instruction->start);
37993812
LLVMValueRef end_val;
38003813
if (instruction->end) {
@@ -3835,6 +3848,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
38353848

38363849
return tmp_struct_ptr;
38373850
} else if (array_type->id == TypeTableEntryIdPointer) {
3851+
assert(array_type->data.pointer.ptr_len == PtrLenUnknown);
38383852
LLVMValueRef start_val = ir_llvm_value(g, instruction->start);
38393853
LLVMValueRef end_val = ir_llvm_value(g, instruction->end);
38403854

@@ -4812,7 +4826,7 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {
48124826

48134827
static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index);
48144828
static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index);
4815-
static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *array_const_val);
4829+
static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val);
48164830

48174831
static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) {
48184832
switch (parent->id) {
@@ -4828,6 +4842,10 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
48284842
parent->data.p_array.elem_index);
48294843
case ConstParentIdUnion:
48304844
return gen_const_ptr_union_recursive(g, parent->data.p_union.union_val);
4845+
case ConstParentIdScalar:
4846+
render_const_val(g, parent->data.p_scalar.scalar_val, "");
4847+
render_const_val_global(g, parent->data.p_scalar.scalar_val, "");
4848+
return parent->data.p_scalar.scalar_val->global_refs->llvm_global;
48314849
}
48324850
zig_unreachable();
48334851
}
@@ -4853,7 +4871,8 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar
48534871
};
48544872
return LLVMConstInBoundsGEP(base_ptr, indices, 2);
48554873
} else {
4856-
zig_unreachable();
4874+
assert(parent->id == ConstParentIdScalar);
4875+
return base_ptr;
48574876
}
48584877
}
48594878

0 commit comments

Comments
 (0)