Skip to content

Commit

Permalink
Pointer Reform: proper slicing and indexing
Browse files Browse the repository at this point in the history
 * 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
  • Loading branch information
andrewrk committed Jun 5, 2018
1 parent 32e0dfd commit 38c62a3
Show file tree
Hide file tree
Showing 21 changed files with 268 additions and 79 deletions.
13 changes: 8 additions & 5 deletions doc/langref.html.in
Expand Up @@ -1565,7 +1565,7 @@ var foo: u8 align(4) = 100;
test "global variable alignment" {
assert(@typeOf(&foo).alignment == 4);
assert(@typeOf(&foo) == *align(4) u8);
const slice = (&foo)[0..1];
const slice = (*[1]u8)(&foo)[0..];
assert(@typeOf(slice) == []align(4) u8);
}

Expand Down Expand Up @@ -1671,7 +1671,7 @@ test "using slices for strings" {

test "slice pointer" {
var array: [10]u8 = undefined;
const ptr = &array[0];
const ptr = &array;

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

export fn decode_base_64(dest_ptr: *u8, dest_len: usize,
source_ptr: *const u8, source_len: usize) usize
{
export fn decode_base_64(
dest_ptr: [*]u8,
dest_len: usize,
source_ptr: [*]const u8,
source_len: usize,
) usize {
const src = source_ptr[0..source_len];
const dest = dest_ptr[0..dest_len];
const base64_decoder = base64.standard_decoder_unsafe;
Expand Down
2 changes: 1 addition & 1 deletion example/mix_o_files/base64.zig
@@ -1,6 +1,6 @@
const base64 = @import("std").base64;

export fn decode_base_64(dest_ptr: *u8, dest_len: usize, source_ptr: *const u8, source_len: usize) usize {
export fn decode_base_64(dest_ptr: [*]u8, dest_len: usize, source_ptr: [*]const u8, source_len: usize) usize {
const src = source_ptr[0..source_len];
const dest = dest_ptr[0..dest_len];
const base64_decoder = base64.standard_decoder_unsafe;
Expand Down
5 changes: 5 additions & 0 deletions src/all_types.hpp
Expand Up @@ -83,6 +83,7 @@ enum ConstParentId {
ConstParentIdStruct,
ConstParentIdArray,
ConstParentIdUnion,
ConstParentIdScalar,
};

struct ConstParent {
Expand All @@ -100,6 +101,9 @@ struct ConstParent {
struct {
ConstExprValue *union_val;
} p_union;
struct {
ConstExprValue *scalar_val;
} p_scalar;
} data;
};

Expand Down Expand Up @@ -578,6 +582,7 @@ enum CastOp {
CastOpBytesToSlice,
CastOpNumLitToConcrete,
CastOpErrSet,
CastOpBitCast,
};

struct AstNodeFnCallExpr {
Expand Down
14 changes: 9 additions & 5 deletions src/analyze.cpp
Expand Up @@ -5158,7 +5158,8 @@ void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *arr
const_val->type = get_slice_type(g, ptr_type);
const_val->data.x_struct.fields = create_const_vals(2);

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

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

void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val,
size_t elem_index, bool is_const)
size_t elem_index, bool is_const, PtrLen ptr_len)
{
assert(array_val->type->id == TypeTableEntryIdArray);
TypeTableEntry *child_type = array_val->type->data.array.child_type;

const_val->special = ConstValSpecialStatic;
const_val->type = get_pointer_to_type(g, child_type, is_const);
const_val->type = get_pointer_to_type_extra(g, child_type, is_const, false,
ptr_len, get_abi_alignment(g, child_type), 0, 0);
const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
const_val->data.x_ptr.data.base_array.array_val = array_val;
const_val->data.x_ptr.data.base_array.elem_index = elem_index;
}

ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index, bool is_const) {
ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index, bool is_const,
PtrLen ptr_len)
{
ConstExprValue *const_val = create_const_vals(1);
init_const_ptr_array(g, const_val, array_val, elem_index, is_const);
init_const_ptr_array(g, const_val, array_val, elem_index, is_const, ptr_len);
return const_val;
}

Expand Down
5 changes: 3 additions & 2 deletions src/analyze.hpp
Expand Up @@ -152,8 +152,9 @@ ConstExprValue *create_const_ptr_hard_coded_addr(CodeGen *g, TypeTableEntry *poi
size_t addr, bool is_const);

void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val,
size_t elem_index, bool is_const);
ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index, bool is_const);
size_t elem_index, bool is_const, PtrLen ptr_len);
ConstExprValue *create_const_ptr_array(CodeGen *g, ConstExprValue *array_val, size_t elem_index,
bool is_const, PtrLen ptr_len);

void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val,
size_t start, size_t len, bool is_const);
Expand Down
27 changes: 23 additions & 4 deletions src/codegen.cpp
Expand Up @@ -2574,6 +2574,8 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
add_error_range_check(g, wanted_type, g->err_tag_type, expr_val);
}
return expr_val;
case CastOpBitCast:
return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, "");
}
zig_unreachable();
}
Expand Down Expand Up @@ -2884,7 +2886,13 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI

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

if (array_type->id == TypeTableEntryIdArray) {
if (array_type->id == TypeTableEntryIdArray ||
(array_type->id == TypeTableEntryIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))
{
if (array_type->id == TypeTableEntryIdPointer) {
assert(array_type->data.pointer.child_type->id == TypeTableEntryIdArray);
array_type = array_type->data.pointer.child_type;
}
if (safety_check_on) {
LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
array_type->data.array.len, false);
Expand Down Expand Up @@ -3794,7 +3802,12 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst

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

if (array_type->id == TypeTableEntryIdArray) {
if (array_type->id == TypeTableEntryIdArray ||
(array_type->id == TypeTableEntryIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))
{
if (array_type->id == TypeTableEntryIdPointer) {
array_type = array_type->data.pointer.child_type;
}
LLVMValueRef start_val = ir_llvm_value(g, instruction->start);
LLVMValueRef end_val;
if (instruction->end) {
Expand Down Expand Up @@ -3835,6 +3848,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst

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

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

static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index);
static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index);
static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *array_const_val);
static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val);

static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) {
switch (parent->id) {
Expand All @@ -4828,6 +4842,10 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
parent->data.p_array.elem_index);
case ConstParentIdUnion:
return gen_const_ptr_union_recursive(g, parent->data.p_union.union_val);
case ConstParentIdScalar:
render_const_val(g, parent->data.p_scalar.scalar_val, "");
render_const_val_global(g, parent->data.p_scalar.scalar_val, "");
return parent->data.p_scalar.scalar_val->global_refs->llvm_global;
}
zig_unreachable();
}
Expand All @@ -4853,7 +4871,8 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar
};
return LLVMConstInBoundsGEP(base_ptr, indices, 2);
} else {
zig_unreachable();
assert(parent->id == ConstParentIdScalar);
return base_ptr;
}
}

Expand Down

0 comments on commit 38c62a3

Please sign in to comment.