mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
IR: implement compile time array access
This commit is contained in:
parent
2edc6c1a3f
commit
af4d4c882a
64
src/ir.cpp
64
src/ir.cpp
@ -2180,7 +2180,9 @@ static ConstExprValue *ir_build_const_from(IrAnalyze *ira, IrInstruction *old_in
|
||||
} else if (old_instruction->id == IrInstructionIdFieldPtr) {
|
||||
zig_panic("TODO");
|
||||
} else if (old_instruction->id == IrInstructionIdElemPtr) {
|
||||
zig_panic("TODO");
|
||||
IrInstructionElemPtr *elem_ptr_instruction = ir_create_instruction<IrInstructionElemPtr>(ira->new_irb.exec,
|
||||
old_instruction->source_node);
|
||||
new_instruction = &elem_ptr_instruction->base;
|
||||
} else {
|
||||
IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(ira->new_irb.exec,
|
||||
old_instruction->source_node);
|
||||
@ -2577,7 +2579,7 @@ static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira,
|
||||
IrInstructionReturn *return_instruction)
|
||||
{
|
||||
IrInstruction *value = return_instruction->value->other;
|
||||
if (value == ira->codegen->invalid_instruction)
|
||||
if (value->type_entry->id == TypeTableEntryIdInvalid)
|
||||
return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
|
||||
ira->implicit_return_type_list.append(value);
|
||||
|
||||
@ -3512,7 +3514,12 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstructionElemPtr *elem_ptr_instruction) {
|
||||
IrInstruction *array_ptr = elem_ptr_instruction->array_ptr->other;
|
||||
if (array_ptr->type_entry->id == TypeTableEntryIdInvalid)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
IrInstruction *elem_index = elem_ptr_instruction->elem_index->other;
|
||||
if (elem_index->type_entry->id == TypeTableEntryIdInvalid)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
TypeTableEntry *array_type = array_ptr->type_entry;
|
||||
TypeTableEntry *return_type;
|
||||
@ -3522,7 +3529,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
|
||||
} else if (array_type->id == TypeTableEntryIdArray) {
|
||||
if (array_type->data.array.len == 0) {
|
||||
add_node_error(ira->codegen, elem_ptr_instruction->base.source_node,
|
||||
buf_sprintf("out of bounds array access"));
|
||||
buf_sprintf("index 0 outside array of size 0"));
|
||||
}
|
||||
TypeTableEntry *child_type = array_type->data.array.child_type;
|
||||
return_type = get_pointer_to_type(ira->codegen, child_type, false);
|
||||
@ -3541,12 +3548,57 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
|
||||
if (casted_elem_index == ira->codegen->invalid_instruction)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
if (array_ptr->static_value.ok && casted_elem_index->static_value.ok) {
|
||||
zig_panic("TODO compile time array access");
|
||||
if (casted_elem_index->static_value.ok) {
|
||||
uint64_t index = casted_elem_index->static_value.data.x_bignum.data.x_uint;
|
||||
if (array_type->id == TypeTableEntryIdArray) {
|
||||
uint64_t array_len = array_type->data.array.len;
|
||||
if (index >= array_len) {
|
||||
add_node_error(ira->codegen, elem_ptr_instruction->base.source_node,
|
||||
buf_sprintf("index %" PRIu64 " outside array of size %" PRIu64,
|
||||
index, array_len));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
if (array_ptr->static_value.ok) {
|
||||
bool depends_on_compile_var = array_ptr->static_value.depends_on_compile_var ||
|
||||
casted_elem_index->static_value.depends_on_compile_var;
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base, depends_on_compile_var);
|
||||
out_val->data.x_ptr.len = 1;
|
||||
out_val->data.x_ptr.is_c_str = false;
|
||||
out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1);
|
||||
if (array_type->id == TypeTableEntryIdPointer) {
|
||||
uint64_t pointer_len = array_ptr->static_value.data.x_ptr.len;
|
||||
if (index >= pointer_len) {
|
||||
add_node_error(ira->codegen, elem_ptr_instruction->base.source_node,
|
||||
buf_sprintf("index %" PRIu64 " outside pointer of size %" PRIu64,
|
||||
index, pointer_len));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
out_val->data.x_ptr.ptr[0] = array_ptr->static_value.data.x_ptr.ptr[index];
|
||||
} else if (is_slice(array_type)) {
|
||||
ConstExprValue *ptr_field = array_ptr->static_value.data.x_struct.fields[0];
|
||||
ConstExprValue *len_field = array_ptr->static_value.data.x_struct.fields[1];
|
||||
uint64_t slice_len = len_field->data.x_bignum.data.x_uint;
|
||||
if (index >= slice_len) {
|
||||
add_node_error(ira->codegen, elem_ptr_instruction->base.source_node,
|
||||
buf_sprintf("index %" PRIu64 " outside slice of size %" PRIu64,
|
||||
index, slice_len));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
assert(index < ptr_field->data.x_ptr.len);
|
||||
out_val->data.x_ptr.ptr[0] = ptr_field->data.x_ptr.ptr[index];
|
||||
} else if (array_type->id == TypeTableEntryIdArray) {
|
||||
out_val->data.x_ptr.ptr[0] = array_ptr->static_value.data.x_array.fields[index];
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
return return_type;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ir_build_elem_ptr_from(&ira->new_irb, &elem_ptr_instruction->base, array_ptr, casted_elem_index);
|
||||
|
||||
return return_type;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user