Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 15816a5

Browse files
committedMar 16, 2020
slicing with comptime start and end results in array
implements #863
1 parent a2432b6 commit 15816a5

File tree

3 files changed

+119
-37
lines changed

3 files changed

+119
-37
lines changed
 

‎src/analyze.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -791,7 +791,10 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, Zi
791791
return existing_entry->value;
792792
}
793793

794-
assert(type_is_resolved(child_type, ResolveStatusSizeKnown));
794+
Error err;
795+
if ((err = type_resolve(g, child_type, ResolveStatusSizeKnown))) {
796+
codegen_report_errors_and_exit(g);
797+
}
795798

796799
ZigType *entry = new_type_table_entry(ZigTypeIdArray);
797800

‎src/codegen.cpp

+54-18
Original file line numberDiff line numberDiff line change
@@ -5422,8 +5422,22 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
54225422

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

5425-
ZigType *res_slice_ptr_type = instruction->base.value->type->data.structure.fields[slice_ptr_index]->type_entry;
5426-
ZigValue *sentinel = res_slice_ptr_type->data.pointer.sentinel;
5425+
ZigType *result_type = instruction->base.value->type;
5426+
if (!type_has_bits(g, result_type)) {
5427+
return nullptr;
5428+
}
5429+
5430+
ZigValue *sentinel = nullptr;
5431+
if (result_type->id == ZigTypeIdPointer) {
5432+
ZigType *result_array_type = result_type->data.pointer.child_type;
5433+
ir_assert(result_array_type->id == ZigTypeIdArray, &instruction->base);
5434+
sentinel = result_array_type->data.array.sentinel;
5435+
} else if (result_type->id == ZigTypeIdStruct) {
5436+
ZigType *res_slice_ptr_type = result_type->data.structure.fields[slice_ptr_index]->type_entry;
5437+
sentinel = res_slice_ptr_type->data.pointer.sentinel;
5438+
} else {
5439+
zig_unreachable();
5440+
}
54275441

54285442
if (array_type->id == ZigTypeIdArray ||
54295443
(array_type->id == ZigTypeIdPointer && array_type->data.pointer.ptr_len == PtrLenSingle))
@@ -5466,18 +5480,24 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
54665480
return tmp_struct_ptr;
54675481
}
54685482

5469-
5470-
LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_ptr_index, "");
54715483
LLVMValueRef indices[] = {
54725484
LLVMConstNull(g->builtin_types.entry_usize->llvm_type),
54735485
start_val,
54745486
};
54755487
LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, "");
5476-
gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
5488+
if (result_type->id == ZigTypeIdPointer) {
5489+
LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type);
5490+
LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, "");
5491+
gen_store_untyped(g, bitcasted, tmp_struct_ptr, 0, false);
5492+
return slice_start_ptr;
5493+
} else {
5494+
LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_ptr_index, "");
5495+
gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
54775496

5478-
LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, "");
5479-
LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
5480-
gen_store_untyped(g, len_value, len_field_ptr, 0, false);
5497+
LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_len_index, "");
5498+
LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
5499+
gen_store_untyped(g, len_value, len_field_ptr, 0, false);
5500+
}
54815501

54825502
return tmp_struct_ptr;
54835503
} else if (array_type->id == ZigTypeIdPointer) {
@@ -5493,14 +5513,21 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
54935513
}
54945514
}
54955515

5516+
LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, "");
5517+
if (result_type->id == ZigTypeIdPointer) {
5518+
LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type);
5519+
LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, "");
5520+
gen_store_untyped(g, bitcasted, tmp_struct_ptr, 0, false);
5521+
return bitcasted;
5522+
}
5523+
54965524
if (type_has_bits(g, array_type)) {
5497-
size_t gen_ptr_index = instruction->base.value->type->data.structure.fields[slice_ptr_index]->gen_index;
5525+
size_t gen_ptr_index = result_type->data.structure.fields[slice_ptr_index]->gen_index;
54985526
LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_ptr_index, "");
5499-
LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, "");
55005527
gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
55015528
}
55025529

5503-
size_t gen_len_index = instruction->base.value->type->data.structure.fields[slice_len_index]->gen_index;
5530+
size_t gen_len_index = result_type->data.structure.fields[slice_len_index]->gen_index;
55045531
LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_len_index, "");
55055532
LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
55065533
gen_store_untyped(g, len_value, len_field_ptr, 0, false);
@@ -5510,7 +5537,9 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
55105537
assert(array_type->data.structure.special == StructSpecialSlice);
55115538
assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
55125539
assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
5513-
assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(tmp_struct_ptr))) == LLVMStructTypeKind);
5540+
if (result_type->id != ZigTypeIdPointer) {
5541+
assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(tmp_struct_ptr))) == LLVMStructTypeKind);
5542+
}
55145543

55155544
size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index;
55165545
assert(ptr_index != SIZE_MAX);
@@ -5547,15 +5576,22 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutableGen *executable, IrI
55475576
}
55485577
}
55495578

5550-
LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, (unsigned)ptr_index, "");
55515579
LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr, &start_val, 1, "");
5552-
gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
5580+
if (result_type->id == ZigTypeIdPointer) {
5581+
LLVMTypeRef result_ptr_type = get_llvm_type(g, result_type);
5582+
LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, slice_start_ptr, result_ptr_type, "");
5583+
gen_store_untyped(g, bitcasted, tmp_struct_ptr, 0, false);
5584+
return bitcasted;
5585+
} else {
5586+
LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, (unsigned)ptr_index, "");
5587+
gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false);
55535588

5554-
LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, (unsigned)len_index, "");
5555-
LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
5556-
gen_store_untyped(g, len_value, len_field_ptr, 0, false);
5589+
LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, (unsigned)len_index, "");
5590+
LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, "");
5591+
gen_store_untyped(g, len_value, len_field_ptr, 0, false);
55575592

5558-
return tmp_struct_ptr;
5593+
return tmp_struct_ptr;
5594+
}
55595595
} else {
55605596
zig_unreachable();
55615597
}

‎src/ir.cpp

+61-18
Original file line numberDiff line numberDiff line change
@@ -849,11 +849,6 @@ static bool is_slice(ZigType *type) {
849849
return type->id == ZigTypeIdStruct && type->data.structure.special == StructSpecialSlice;
850850
}
851851

852-
static bool slice_is_const(ZigType *type) {
853-
assert(is_slice(type));
854-
return type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const;
855-
}
856-
857852
// This function returns true when you can change the type of a ZigValue and the
858853
// value remains meaningful.
859854
static bool types_have_same_zig_comptime_repr(CodeGen *codegen, ZigType *expected, ZigType *actual) {
@@ -26211,7 +26206,6 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
2621126206
return ira->codegen->invalid_inst_gen;
2621226207
}
2621326208

26214-
ZigType *return_type;
2621526209
ZigValue *sentinel_val = nullptr;
2621626210
if (instruction->sentinel) {
2621726211
IrInstGen *uncasted_sentinel = instruction->sentinel->child;
@@ -26223,6 +26217,46 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
2622326217
sentinel_val = ir_resolve_const(ira, sentinel, UndefBad);
2622426218
if (sentinel_val == nullptr)
2622526219
return ira->codegen->invalid_inst_gen;
26220+
}
26221+
26222+
// If start index and end index are both comptime known, then the result type is a pointer to array
26223+
// not a slice.
26224+
ZigType *return_type;
26225+
26226+
if (value_is_comptime(casted_start->value) &&
26227+
((end != nullptr && value_is_comptime(end->value)) || array_type->id == ZigTypeIdArray ))
26228+
{
26229+
ZigValue *start_val = ir_resolve_const(ira, casted_start, UndefBad);
26230+
if (!start_val)
26231+
return ira->codegen->invalid_inst_gen;
26232+
26233+
uint64_t start_scalar = bigint_as_u64(&start_val->data.x_bigint);
26234+
26235+
uint64_t end_scalar;
26236+
if (end != nullptr) {
26237+
ZigValue *end_val = ir_resolve_const(ira, end, UndefBad);
26238+
if (!end_val)
26239+
return ira->codegen->invalid_inst_gen;
26240+
end_scalar = bigint_as_u64(&end_val->data.x_bigint);
26241+
} else {
26242+
end_scalar = array_type->data.array.len;
26243+
}
26244+
ZigValue *array_sentinel = (array_type->id == ZigTypeIdArray && end_scalar == array_type->data.array.len)
26245+
? sentinel_val : nullptr;
26246+
26247+
if (start_scalar > end_scalar) {
26248+
ir_add_error(ira, &instruction->base.base, buf_sprintf("out of bounds slice"));
26249+
return ira->codegen->invalid_inst_gen;
26250+
}
26251+
26252+
ZigType *return_array_type = get_array_type(ira->codegen, elem_type, end_scalar - start_scalar,
26253+
array_sentinel);
26254+
return_type = get_pointer_to_type_extra(ira->codegen, return_array_type,
26255+
non_sentinel_slice_ptr_type->data.pointer.is_const,
26256+
non_sentinel_slice_ptr_type->data.pointer.is_volatile,
26257+
PtrLenSingle,
26258+
0, 0, 0, false);
26259+
} else if (sentinel_val != nullptr) {
2622626260
ZigType *slice_ptr_type = adjust_ptr_sentinel(ira->codegen, non_sentinel_slice_ptr_type, sentinel_val);
2622726261
return_type = get_slice_type(ira->codegen, slice_ptr_type);
2622826262
} else {
@@ -26406,15 +26440,25 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
2640626440
}
2640726441

2640826442
IrInstGen *result = ir_const(ira, &instruction->base.base, return_type);
26409-
ZigValue *out_val = result->value;
26410-
out_val->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, 2);
2641126443

26412-
ZigValue *ptr_val = out_val->data.x_struct.fields[slice_ptr_index];
26444+
ZigValue *ptr_val;
26445+
if (return_type->id == ZigTypeIdPointer) {
26446+
// pointer to array
26447+
ptr_val = result->value;
26448+
} else {
26449+
// slice
26450+
result->value->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, 2);
26451+
26452+
ptr_val = result->value->data.x_struct.fields[slice_ptr_index];
26453+
26454+
ZigValue *len_val = result->value->data.x_struct.fields[slice_len_index];
26455+
init_const_usize(ira->codegen, len_val, end_scalar - start_scalar);
26456+
}
2641326457

26458+
bool return_type_is_const = non_sentinel_slice_ptr_type->data.pointer.is_const;
2641426459
if (array_val) {
2641526460
size_t index = abs_offset + start_scalar;
26416-
bool is_const = slice_is_const(return_type);
26417-
init_const_ptr_array(ira->codegen, ptr_val, array_val, index, is_const, PtrLenUnknown);
26461+
init_const_ptr_array(ira->codegen, ptr_val, array_val, index, return_type_is_const, PtrLenUnknown);
2641826462
if (array_type->id == ZigTypeIdArray) {
2641926463
ptr_val->data.x_ptr.mut = ptr_ptr->value->data.x_ptr.mut;
2642026464
} else if (is_slice(array_type)) {
@@ -26424,15 +26468,15 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
2642426468
}
2642526469
} else if (ptr_is_undef) {
2642626470
ptr_val->type = get_pointer_to_type(ira->codegen, parent_ptr->type->data.pointer.child_type,
26427-
slice_is_const(return_type));
26471+
return_type_is_const);
2642826472
ptr_val->special = ConstValSpecialUndef;
2642926473
} else switch (parent_ptr->data.x_ptr.special) {
2643026474
case ConstPtrSpecialInvalid:
2643126475
case ConstPtrSpecialDiscard:
2643226476
zig_unreachable();
2643326477
case ConstPtrSpecialRef:
26434-
init_const_ptr_ref(ira->codegen, ptr_val,
26435-
parent_ptr->data.x_ptr.data.ref.pointee, slice_is_const(return_type));
26478+
init_const_ptr_ref(ira->codegen, ptr_val, parent_ptr->data.x_ptr.data.ref.pointee,
26479+
return_type_is_const);
2643626480
break;
2643726481
case ConstPtrSpecialBaseArray:
2643826482
zig_unreachable();
@@ -26448,17 +26492,16 @@ static IrInstGen *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstSrcSlice *i
2644826492
init_const_ptr_hard_coded_addr(ira->codegen, ptr_val,
2644926493
parent_ptr->type->data.pointer.child_type,
2645026494
parent_ptr->data.x_ptr.data.hard_coded_addr.addr + start_scalar,
26451-
slice_is_const(return_type));
26495+
return_type_is_const);
2645226496
break;
2645326497
case ConstPtrSpecialFunction:
2645426498
zig_panic("TODO");
2645526499
case ConstPtrSpecialNull:
2645626500
zig_panic("TODO");
2645726501
}
2645826502

26459-
ZigValue *len_val = out_val->data.x_struct.fields[slice_len_index];
26460-
init_const_usize(ira->codegen, len_val, end_scalar - start_scalar);
26461-
26503+
// In the case of pointer-to-array, we must restore this because above it overwrites ptr_val->type
26504+
result->value->type = return_type;
2646226505
return result;
2646326506
}
2646426507

0 commit comments

Comments
 (0)
Please sign in to comment.