SIMD: array to vector, vector to array, wrapping int add
also vectors and arrays now use the same ConstExprVal representation See #903master
parent
2828a9695f
commit
8c6fa982cd
|
@ -252,10 +252,6 @@ struct ConstArgTuple {
|
|||
size_t end_index;
|
||||
};
|
||||
|
||||
struct ConstVector {
|
||||
ConstExprValue *elements;
|
||||
};
|
||||
|
||||
enum ConstValSpecial {
|
||||
ConstValSpecialRuntime,
|
||||
ConstValSpecialStatic,
|
||||
|
@ -322,7 +318,6 @@ struct ConstExprValue {
|
|||
ConstPtrValue x_ptr;
|
||||
ImportTableEntry *x_import;
|
||||
ConstArgTuple x_arg_tuple;
|
||||
ConstVector x_vector;
|
||||
|
||||
// populated if special == ConstValSpecialRuntime
|
||||
RuntimeHintErrorUnion rh_error_union;
|
||||
|
@ -2239,6 +2234,8 @@ enum IrInstructionId {
|
|||
IrInstructionIdToBytes,
|
||||
IrInstructionIdFromBytes,
|
||||
IrInstructionIdCheckRuntimeScope,
|
||||
IrInstructionIdVectorToArray,
|
||||
IrInstructionIdArrayToVector,
|
||||
};
|
||||
|
||||
struct IrInstruction {
|
||||
|
@ -3368,6 +3365,19 @@ struct IrInstructionBitReverse {
|
|||
IrInstruction *op;
|
||||
};
|
||||
|
||||
struct IrInstructionArrayToVector {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *array;
|
||||
};
|
||||
|
||||
struct IrInstructionVectorToArray {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *vector;
|
||||
LLVMValueRef tmp_ptr;
|
||||
};
|
||||
|
||||
static const size_t slice_ptr_index = 0;
|
||||
static const size_t slice_len_index = 1;
|
||||
|
||||
|
|
178
src/analyze.cpp
178
src/analyze.cpp
|
@ -4457,7 +4457,15 @@ ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
|
|||
return new_entry;
|
||||
}
|
||||
|
||||
bool is_valid_vector_elem_type(ZigType *elem_type) {
|
||||
return elem_type->id == ZigTypeIdInt ||
|
||||
elem_type->id == ZigTypeIdFloat ||
|
||||
get_codegen_ptr_type(elem_type) != nullptr;
|
||||
}
|
||||
|
||||
ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) {
|
||||
assert(is_valid_vector_elem_type(elem_type));
|
||||
|
||||
TypeId type_id = {};
|
||||
type_id.id = ZigTypeIdVector;
|
||||
type_id.data.vector.len = len;
|
||||
|
@ -5749,6 +5757,28 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
|
|||
zig_unreachable();
|
||||
}
|
||||
|
||||
static bool const_values_equal_array(CodeGen *g, ConstExprValue *a, ConstExprValue *b, size_t len) {
|
||||
assert(a->data.x_array.special != ConstArraySpecialUndef);
|
||||
assert(b->data.x_array.special != ConstArraySpecialUndef);
|
||||
if (a->data.x_array.special == ConstArraySpecialBuf &&
|
||||
b->data.x_array.special == ConstArraySpecialBuf)
|
||||
{
|
||||
return buf_eql_buf(a->data.x_array.data.s_buf, b->data.x_array.data.s_buf);
|
||||
}
|
||||
expand_undef_array(g, a);
|
||||
expand_undef_array(g, b);
|
||||
|
||||
ConstExprValue *a_elems = a->data.x_array.data.s_none.elements;
|
||||
ConstExprValue *b_elems = b->data.x_array.data.s_none.elements;
|
||||
|
||||
for (size_t i = 0; i < len; i += 1) {
|
||||
if (!const_values_equal(g, &a_elems[i], &b_elems[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
|
||||
assert(a->type->id == b->type->id);
|
||||
assert(a->special == ConstValSpecialStatic);
|
||||
|
@ -5803,28 +5833,12 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
|
|||
case ZigTypeIdPointer:
|
||||
case ZigTypeIdFn:
|
||||
return const_values_equal_ptr(a, b);
|
||||
case ZigTypeIdVector:
|
||||
assert(a->type->data.vector.len == b->type->data.vector.len);
|
||||
return const_values_equal_array(g, a, b, a->type->data.vector.len);
|
||||
case ZigTypeIdArray: {
|
||||
assert(a->type->data.array.len == b->type->data.array.len);
|
||||
assert(a->data.x_array.special != ConstArraySpecialUndef);
|
||||
assert(b->data.x_array.special != ConstArraySpecialUndef);
|
||||
if (a->data.x_array.special == ConstArraySpecialBuf &&
|
||||
b->data.x_array.special == ConstArraySpecialBuf)
|
||||
{
|
||||
return buf_eql_buf(a->data.x_array.data.s_buf, b->data.x_array.data.s_buf);
|
||||
}
|
||||
expand_undef_array(g, a);
|
||||
expand_undef_array(g, b);
|
||||
|
||||
size_t len = a->type->data.array.len;
|
||||
ConstExprValue *a_elems = a->data.x_array.data.s_none.elements;
|
||||
ConstExprValue *b_elems = b->data.x_array.data.s_none.elements;
|
||||
|
||||
for (size_t i = 0; i < len; i += 1) {
|
||||
if (!const_values_equal(g, &a_elems[i], &b_elems[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return const_values_equal_array(g, a, b, a->type->data.array.len);
|
||||
}
|
||||
case ZigTypeIdStruct:
|
||||
for (size_t i = 0; i < a->type->data.structure.src_field_count; i += 1) {
|
||||
|
@ -5853,20 +5867,6 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
|
|||
case ZigTypeIdArgTuple:
|
||||
return a->data.x_arg_tuple.start_index == b->data.x_arg_tuple.start_index &&
|
||||
a->data.x_arg_tuple.end_index == b->data.x_arg_tuple.end_index;
|
||||
case ZigTypeIdVector: {
|
||||
assert(a->type->data.vector.len == b->type->data.vector.len);
|
||||
|
||||
size_t len = a->type->data.vector.len;
|
||||
ConstExprValue *a_elems = a->data.x_vector.elements;
|
||||
ConstExprValue *b_elems = b->data.x_vector.elements;
|
||||
|
||||
for (size_t i = 0; i < len; i += 1) {
|
||||
if (!const_values_equal(g, &a_elems[i], &b_elems[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
case ZigTypeIdBoundFn:
|
||||
case ZigTypeIdInvalid:
|
||||
case ZigTypeIdUnreachable:
|
||||
|
@ -5985,6 +5985,40 @@ static void render_const_val_err_set(CodeGen *g, Buf *buf, ConstExprValue *const
|
|||
}
|
||||
}
|
||||
|
||||
static void render_const_val_array(CodeGen *g, Buf *buf, ConstExprValue *const_val, size_t len) {
|
||||
switch (const_val->data.x_array.special) {
|
||||
case ConstArraySpecialUndef:
|
||||
buf_append_str(buf, "undefined");
|
||||
return;
|
||||
case ConstArraySpecialBuf: {
|
||||
Buf *array_buf = const_val->data.x_array.data.s_buf;
|
||||
buf_append_char(buf, '"');
|
||||
for (size_t i = 0; i < buf_len(array_buf); i += 1) {
|
||||
uint8_t c = buf_ptr(array_buf)[i];
|
||||
if (c == '"') {
|
||||
buf_append_str(buf, "\\\"");
|
||||
} else {
|
||||
buf_append_char(buf, c);
|
||||
}
|
||||
}
|
||||
buf_append_char(buf, '"');
|
||||
return;
|
||||
}
|
||||
case ConstArraySpecialNone: {
|
||||
buf_appendf(buf, "%s{", buf_ptr(&const_val->type->name));
|
||||
for (uint64_t i = 0; i < len; i += 1) {
|
||||
if (i != 0)
|
||||
buf_appendf(buf, ",");
|
||||
ConstExprValue *child_value = &const_val->data.x_array.data.s_none.elements[i];
|
||||
render_const_value(g, buf, child_value);
|
||||
}
|
||||
buf_appendf(buf, "}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
|
||||
switch (const_val->special) {
|
||||
case ConstValSpecialRuntime:
|
||||
|
@ -6065,51 +6099,10 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
|
|||
}
|
||||
case ZigTypeIdPointer:
|
||||
return render_const_val_ptr(g, buf, const_val, type_entry);
|
||||
case ZigTypeIdVector:
|
||||
return render_const_val_array(g, buf, const_val, type_entry->data.vector.len);
|
||||
case ZigTypeIdArray:
|
||||
switch (const_val->data.x_array.special) {
|
||||
case ConstArraySpecialUndef:
|
||||
buf_append_str(buf, "undefined");
|
||||
return;
|
||||
case ConstArraySpecialBuf: {
|
||||
Buf *array_buf = const_val->data.x_array.data.s_buf;
|
||||
buf_append_char(buf, '"');
|
||||
for (size_t i = 0; i < buf_len(array_buf); i += 1) {
|
||||
uint8_t c = buf_ptr(array_buf)[i];
|
||||
if (c == '"') {
|
||||
buf_append_str(buf, "\\\"");
|
||||
} else {
|
||||
buf_append_char(buf, c);
|
||||
}
|
||||
}
|
||||
buf_append_char(buf, '"');
|
||||
return;
|
||||
}
|
||||
case ConstArraySpecialNone: {
|
||||
buf_appendf(buf, "%s{", buf_ptr(&type_entry->name));
|
||||
uint64_t len = type_entry->data.array.len;
|
||||
for (uint64_t i = 0; i < len; i += 1) {
|
||||
if (i != 0)
|
||||
buf_appendf(buf, ",");
|
||||
ConstExprValue *child_value = &const_val->data.x_array.data.s_none.elements[i];
|
||||
render_const_value(g, buf, child_value);
|
||||
}
|
||||
buf_appendf(buf, "}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
zig_unreachable();
|
||||
case ZigTypeIdVector: {
|
||||
buf_appendf(buf, "%s{", buf_ptr(&type_entry->name));
|
||||
uint64_t len = type_entry->data.vector.len;
|
||||
for (uint32_t i = 0; i < len; i += 1) {
|
||||
if (i != 0)
|
||||
buf_appendf(buf, ",");
|
||||
ConstExprValue *child_value = &const_val->data.x_vector.elements[i];
|
||||
render_const_value(g, buf, child_value);
|
||||
}
|
||||
buf_appendf(buf, "}");
|
||||
return;
|
||||
}
|
||||
return render_const_val_array(g, buf, const_val, type_entry->data.array.len);
|
||||
case ZigTypeIdNull:
|
||||
{
|
||||
buf_appendf(buf, "null");
|
||||
|
@ -6379,7 +6372,17 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
|
|||
|
||||
// Canonicalize the array value as ConstArraySpecialNone
|
||||
void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
|
||||
assert(const_val->type->id == ZigTypeIdArray);
|
||||
size_t elem_count;
|
||||
ZigType *elem_type;
|
||||
if (const_val->type->id == ZigTypeIdArray) {
|
||||
elem_count = const_val->type->data.array.len;
|
||||
elem_type = const_val->type->data.array.child_type;
|
||||
} else if (const_val->type->id == ZigTypeIdVector) {
|
||||
elem_count = const_val->type->data.vector.len;
|
||||
elem_type = const_val->type->data.vector.elem_type;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
if (const_val->special == ConstValSpecialUndef) {
|
||||
const_val->special = ConstValSpecialStatic;
|
||||
const_val->data.x_array.special = ConstArraySpecialUndef;
|
||||
|
@ -6389,18 +6392,14 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
|
|||
return;
|
||||
case ConstArraySpecialUndef: {
|
||||
const_val->data.x_array.special = ConstArraySpecialNone;
|
||||
size_t elem_count = const_val->type->data.array.len;
|
||||
const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count);
|
||||
for (size_t i = 0; i < elem_count; i += 1) {
|
||||
ConstExprValue *element_val = &const_val->data.x_array.data.s_none.elements[i];
|
||||
element_val->type = const_val->type->data.array.child_type;
|
||||
element_val->type = elem_type;
|
||||
init_const_undefined(g, element_val);
|
||||
ConstParent *parent = get_const_val_parent(g, element_val);
|
||||
if (parent != nullptr) {
|
||||
parent->id = ConstParentIdArray;
|
||||
parent->data.p_array.array_val = const_val;
|
||||
parent->data.p_array.elem_index = i;
|
||||
}
|
||||
element_val->parent.id = ConstParentIdArray;
|
||||
element_val->parent.data.p_array.array_val = const_val;
|
||||
element_val->parent.data.p_array.elem_index = i;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -6411,7 +6410,6 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
|
|||
g->string_literals_table.maybe_remove(buf);
|
||||
|
||||
const_val->data.x_array.special = ConstArraySpecialNone;
|
||||
size_t elem_count = const_val->type->data.array.len;
|
||||
assert(elem_count == buf_len(buf));
|
||||
const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count);
|
||||
for (size_t i = 0; i < elem_count; i += 1) {
|
||||
|
@ -6419,6 +6417,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
|
|||
this_char->special = ConstValSpecialStatic;
|
||||
this_char->type = g->builtin_types.entry_u8;
|
||||
bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(buf)[i]);
|
||||
this_char->parent.id = ConstParentIdArray;
|
||||
this_char->parent.data.p_array.array_val = const_val;
|
||||
this_char->parent.data.p_array.elem_index = i;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -6426,6 +6427,7 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
|
|||
zig_unreachable();
|
||||
}
|
||||
|
||||
// Deprecated. Reference the parent field directly.
|
||||
ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) {
|
||||
return &value->parent;
|
||||
}
|
||||
|
|
|
@ -74,6 +74,7 @@ TypeUnionField *find_union_field_by_tag(ZigType *type_entry, const BigInt *tag);
|
|||
bool is_ref(ZigType *type_entry);
|
||||
bool is_array_ref(ZigType *type_entry);
|
||||
bool is_container_ref(ZigType *type_entry);
|
||||
bool is_valid_vector_elem_type(ZigType *elem_type);
|
||||
void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
|
||||
void scan_import(CodeGen *g, ImportTableEntry *import);
|
||||
void preview_use_decl(CodeGen *g, AstNode *node);
|
||||
|
|
|
@ -1921,9 +1921,8 @@ static void give_up_with_c_abi_error(CodeGen *g, AstNode *source_node) {
|
|||
}
|
||||
|
||||
static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment) {
|
||||
assert(alignment > 0);
|
||||
LLVMValueRef result = LLVMBuildAlloca(g->builder, type_entry->type_ref, name);
|
||||
LLVMSetAlignment(result, alignment);
|
||||
LLVMSetAlignment(result, (alignment == 0) ? get_abi_alignment(g, type_entry) : alignment);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -3246,6 +3245,22 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
|
|||
return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, "");
|
||||
}
|
||||
|
||||
static bool value_is_all_undef_array(ConstExprValue *const_val, size_t len) {
|
||||
switch (const_val->data.x_array.special) {
|
||||
case ConstArraySpecialUndef:
|
||||
return true;
|
||||
case ConstArraySpecialBuf:
|
||||
return false;
|
||||
case ConstArraySpecialNone:
|
||||
for (size_t i = 0; i < len; i += 1) {
|
||||
if (!value_is_all_undef(&const_val->data.x_array.data.s_none.elements[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static bool value_is_all_undef(ConstExprValue *const_val) {
|
||||
switch (const_val->special) {
|
||||
case ConstValSpecialRuntime:
|
||||
|
@ -3260,19 +3275,9 @@ static bool value_is_all_undef(ConstExprValue *const_val) {
|
|||
}
|
||||
return true;
|
||||
} else if (const_val->type->id == ZigTypeIdArray) {
|
||||
switch (const_val->data.x_array.special) {
|
||||
case ConstArraySpecialUndef:
|
||||
return true;
|
||||
case ConstArraySpecialBuf:
|
||||
return false;
|
||||
case ConstArraySpecialNone:
|
||||
for (size_t i = 0; i < const_val->type->data.array.len; i += 1) {
|
||||
if (!value_is_all_undef(&const_val->data.x_array.data.s_none.elements[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
zig_unreachable();
|
||||
return value_is_all_undef_array(const_val, const_val->type->data.array.len);
|
||||
} else if (const_val->type->id == ZigTypeIdVector) {
|
||||
return value_is_all_undef_array(const_val, const_val->type->data.vector.len);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -5194,6 +5199,32 @@ static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutable *executable,
|
|||
return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionVectorToArray *instruction)
|
||||
{
|
||||
ZigType *array_type = instruction->base.value.type;
|
||||
assert(array_type->id == ZigTypeIdArray);
|
||||
assert(handle_is_ptr(array_type));
|
||||
assert(instruction->tmp_ptr);
|
||||
LLVMValueRef vector = ir_llvm_value(g, instruction->vector);
|
||||
LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr,
|
||||
LLVMPointerType(instruction->vector->value.type->type_ref, 0), "");
|
||||
gen_store_untyped(g, vector, casted_ptr, 0, false);
|
||||
return instruction->tmp_ptr;
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionArrayToVector *instruction)
|
||||
{
|
||||
ZigType *vector_type = instruction->base.value.type;
|
||||
assert(vector_type->id == ZigTypeIdVector);
|
||||
assert(!handle_is_ptr(vector_type));
|
||||
LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array);
|
||||
LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr,
|
||||
LLVMPointerType(vector_type->type_ref, 0), "");
|
||||
return gen_load_untyped(g, casted_ptr, 0, false, "");
|
||||
}
|
||||
|
||||
static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
|
||||
AstNode *source_node = instruction->source_node;
|
||||
Scope *scope = instruction->scope;
|
||||
|
@ -5439,6 +5470,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
|||
return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction);
|
||||
case IrInstructionIdBitReverse:
|
||||
return ir_render_bit_reverse(g, executable, (IrInstructionBitReverse *)instruction);
|
||||
case IrInstructionIdArrayToVector:
|
||||
return ir_render_array_to_vector(g, executable, (IrInstructionArrayToVector *)instruction);
|
||||
case IrInstructionIdVectorToArray:
|
||||
return ir_render_vector_to_array(g, executable, (IrInstructionVectorToArray *)instruction);
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
@ -6016,14 +6051,32 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
|||
return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf), true);
|
||||
}
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
case ZigTypeIdVector: {
|
||||
uint32_t len = type_entry->data.vector.len;
|
||||
LLVMValueRef *values = allocate<LLVMValueRef>(len);
|
||||
for (uint32_t i = 0; i < len; i += 1) {
|
||||
values[i] = gen_const_val(g, &const_val->data.x_vector.elements[i], "");
|
||||
switch (const_val->data.x_array.special) {
|
||||
case ConstArraySpecialUndef:
|
||||
return LLVMGetUndef(type_entry->type_ref);
|
||||
case ConstArraySpecialNone: {
|
||||
LLVMValueRef *values = allocate<LLVMValueRef>(len);
|
||||
for (uint64_t i = 0; i < len; i += 1) {
|
||||
ConstExprValue *elem_value = &const_val->data.x_array.data.s_none.elements[i];
|
||||
values[i] = gen_const_val(g, elem_value, "");
|
||||
}
|
||||
return LLVMConstVector(values, len);
|
||||
}
|
||||
case ConstArraySpecialBuf: {
|
||||
Buf *buf = const_val->data.x_array.data.s_buf;
|
||||
assert(buf_len(buf) == len);
|
||||
LLVMValueRef *values = allocate<LLVMValueRef>(len);
|
||||
for (uint64_t i = 0; i < len; i += 1) {
|
||||
values[i] = LLVMConstInt(g->builtin_types.entry_u8->type_ref, buf_ptr(buf)[i], false);
|
||||
}
|
||||
return LLVMConstVector(values, len);
|
||||
}
|
||||
}
|
||||
return LLVMConstVector(values, len);
|
||||
zig_unreachable();
|
||||
}
|
||||
case ZigTypeIdUnion:
|
||||
{
|
||||
|
@ -6467,6 +6520,7 @@ static void do_code_gen(CodeGen *g) {
|
|||
IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i);
|
||||
LLVMValueRef *slot;
|
||||
ZigType *slot_type = instruction->value.type;
|
||||
uint32_t alignment_bytes = 0;
|
||||
if (instruction->id == IrInstructionIdCast) {
|
||||
IrInstructionCast *cast_instruction = (IrInstructionCast *)instruction;
|
||||
slot = &cast_instruction->tmp_ptr;
|
||||
|
@ -6502,10 +6556,14 @@ static void do_code_gen(CodeGen *g) {
|
|||
} else if (instruction->id == IrInstructionIdCmpxchgGen) {
|
||||
IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction;
|
||||
slot = &cmpxchg_instruction->tmp_ptr;
|
||||
} else if (instruction->id == IrInstructionIdVectorToArray) {
|
||||
IrInstructionVectorToArray *vector_to_array_instruction = (IrInstructionVectorToArray *)instruction;
|
||||
alignment_bytes = get_abi_alignment(g, vector_to_array_instruction->vector->value.type);
|
||||
slot = &vector_to_array_instruction->tmp_ptr;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
*slot = build_alloca(g, slot_type, "", get_abi_alignment(g, slot_type));
|
||||
*slot = build_alloca(g, slot_type, "", alignment_bytes);
|
||||
}
|
||||
|
||||
ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base);
|
||||
|
|
291
src/ir.cpp
291
src/ir.cpp
|
@ -168,6 +168,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
|
|||
static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
|
||||
static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);
|
||||
static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
|
||||
static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry);
|
||||
|
||||
static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
|
||||
assert(get_src_ptr_type(const_val->type) != nullptr);
|
||||
|
@ -899,6 +900,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScop
|
|||
return IrInstructionIdCheckRuntimeScope;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorToArray *) {
|
||||
return IrInstructionIdVectorToArray;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayToVector *) {
|
||||
return IrInstructionIdArrayToVector;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
|
||||
T *special_instruction = allocate<T>(1);
|
||||
|
@ -2821,6 +2830,34 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope,
|
|||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_vector_to_array(IrAnalyze *ira, IrInstruction *source_instruction,
|
||||
IrInstruction *vector, ZigType *result_type)
|
||||
{
|
||||
IrInstructionVectorToArray *instruction = ir_build_instruction<IrInstructionVectorToArray>(&ira->new_irb,
|
||||
source_instruction->scope, source_instruction->source_node);
|
||||
instruction->base.value.type = result_type;
|
||||
instruction->vector = vector;
|
||||
|
||||
ir_ref_instruction(vector, ira->new_irb.current_basic_block);
|
||||
|
||||
ir_add_alloca(ira, &instruction->base, result_type);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_array_to_vector(IrAnalyze *ira, IrInstruction *source_instruction,
|
||||
IrInstruction *array, ZigType *result_type)
|
||||
{
|
||||
IrInstructionArrayToVector *instruction = ir_build_instruction<IrInstructionArrayToVector>(&ira->new_irb,
|
||||
source_instruction->scope, source_instruction->source_node);
|
||||
instruction->base.value.type = result_type;
|
||||
instruction->array = array;
|
||||
|
||||
ir_ref_instruction(array, ira->new_irb.current_basic_block);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
|
||||
results[ReturnKindUnconditional] = 0;
|
||||
results[ReturnKindError] = 0;
|
||||
|
@ -8270,6 +8307,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
|
|||
|
||||
bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || const_val->type->id == ZigTypeIdComptimeInt);
|
||||
bool const_val_is_float = (const_val->type->id == ZigTypeIdFloat || const_val->type->id == ZigTypeIdComptimeFloat);
|
||||
assert(const_val_is_int || const_val_is_float);
|
||||
|
||||
if (other_type->id == ZigTypeIdFloat) {
|
||||
if (const_val->type->id == ZigTypeIdComptimeInt || const_val->type->id == ZigTypeIdComptimeFloat) {
|
||||
|
@ -10714,6 +10752,32 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
|
|||
}
|
||||
}
|
||||
|
||||
static IrInstruction *ir_analyze_array_to_vector(IrAnalyze *ira, IrInstruction *source_instr,
|
||||
IrInstruction *array, ZigType *vector_type)
|
||||
{
|
||||
if (instr_is_comptime(array)) {
|
||||
// arrays and vectors have the same ConstExprValue representation
|
||||
IrInstruction *result = ir_const(ira, source_instr, vector_type);
|
||||
copy_const_val(&result->value, &array->value, false);
|
||||
result->value.type = vector_type;
|
||||
return result;
|
||||
}
|
||||
return ir_build_array_to_vector(ira, source_instr, array, vector_type);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *source_instr,
|
||||
IrInstruction *vector, ZigType *array_type)
|
||||
{
|
||||
if (instr_is_comptime(vector)) {
|
||||
// arrays and vectors have the same ConstExprValue representation
|
||||
IrInstruction *result = ir_const(ira, source_instr, array_type);
|
||||
copy_const_val(&result->value, &vector->value, false);
|
||||
result->value.type = array_type;
|
||||
return result;
|
||||
}
|
||||
return ir_build_vector_to_array(ira, source_instr, vector, array_type);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
|
||||
ZigType *wanted_type, IrInstruction *value)
|
||||
{
|
||||
|
@ -11102,6 +11166,23 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
|
|||
}
|
||||
}
|
||||
|
||||
// cast from @Vector(N, T) to [N]T
|
||||
if (wanted_type->id == ZigTypeIdArray && actual_type->id == ZigTypeIdVector &&
|
||||
wanted_type->data.array.len == actual_type->data.vector.len &&
|
||||
types_match_const_cast_only(ira, wanted_type->data.array.child_type,
|
||||
actual_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk)
|
||||
{
|
||||
return ir_analyze_vector_to_array(ira, source_instr, value, wanted_type);
|
||||
}
|
||||
|
||||
// cast from [N]T to @Vector(N, T)
|
||||
if (actual_type->id == ZigTypeIdArray && wanted_type->id == ZigTypeIdVector &&
|
||||
actual_type->data.array.len == wanted_type->data.vector.len &&
|
||||
types_match_const_cast_only(ira, actual_type->data.array.child_type,
|
||||
wanted_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk)
|
||||
{
|
||||
return ir_analyze_array_to_vector(ira, source_instr, value, wanted_type);
|
||||
}
|
||||
|
||||
// cast from undefined to anything
|
||||
if (actual_type->id == ZigTypeIdUndefined) {
|
||||
|
@ -11780,8 +11861,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
|
|||
return result;
|
||||
}
|
||||
|
||||
static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
|
||||
IrBinOp op_id, ConstExprValue *op2_val, ConstExprValue *out_val)
|
||||
static ErrorMsg *ir_eval_math_op_scalar(IrAnalyze *ira, IrInstruction *source_instr, ZigType *type_entry,
|
||||
ConstExprValue *op1_val, IrBinOp op_id, ConstExprValue *op2_val, ConstExprValue *out_val)
|
||||
{
|
||||
bool is_int;
|
||||
bool is_float;
|
||||
|
@ -11803,10 +11884,10 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
|
|||
if ((op_id == IrBinOpDivUnspecified || op_id == IrBinOpRemRem || op_id == IrBinOpRemMod ||
|
||||
op_id == IrBinOpDivTrunc || op_id == IrBinOpDivFloor) && op2_zcmp == CmpEQ)
|
||||
{
|
||||
return ErrorDivByZero;
|
||||
return ir_add_error(ira, source_instr, buf_sprintf("division by zero"));
|
||||
}
|
||||
if ((op_id == IrBinOpRemRem || op_id == IrBinOpRemMod) && op2_zcmp == CmpLT) {
|
||||
return ErrorNegativeDenominator;
|
||||
return ir_add_error(ira, source_instr, buf_sprintf("negative denominator"));
|
||||
}
|
||||
|
||||
switch (op_id) {
|
||||
|
@ -11852,7 +11933,7 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
|
|||
BigInt orig_bigint;
|
||||
bigint_shl(&orig_bigint, &out_val->data.x_bigint, &op2_val->data.x_bigint);
|
||||
if (bigint_cmp(&op1_val->data.x_bigint, &orig_bigint) != CmpEQ) {
|
||||
return ErrorShiftedOutOneBits;
|
||||
return ir_add_error(ira, source_instr, buf_sprintf("exact shift shifted out 1 bits"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -11920,14 +12001,14 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
|
|||
BigInt remainder;
|
||||
bigint_rem(&remainder, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
|
||||
if (bigint_cmp_zero(&remainder) != CmpEQ) {
|
||||
return ErrorExactDivRemainder;
|
||||
return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder"));
|
||||
}
|
||||
} else {
|
||||
float_div_trunc(out_val, op1_val, op2_val);
|
||||
ConstExprValue remainder;
|
||||
float_rem(&remainder, op1_val, op2_val);
|
||||
if (float_cmp_zero(&remainder) != CmpEQ) {
|
||||
return ErrorExactDivRemainder;
|
||||
return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -11951,13 +12032,51 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
|
|||
if (!bigint_fits_in_bits(&out_val->data.x_bigint, type_entry->data.integral.bit_count,
|
||||
type_entry->data.integral.is_signed))
|
||||
{
|
||||
return ErrorOverflow;
|
||||
return ir_add_error(ira, source_instr, buf_sprintf("operation caused overflow"));
|
||||
}
|
||||
}
|
||||
|
||||
out_val->type = type_entry;
|
||||
out_val->special = ConstValSpecialStatic;
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// This works on operands that have already been checked to be comptime known.
|
||||
static IrInstruction *ir_analyze_math_op(IrAnalyze *ira, IrInstruction *source_instr,
|
||||
ZigType *type_entry, ConstExprValue *op1_val, IrBinOp op_id, ConstExprValue *op2_val)
|
||||
{
|
||||
IrInstruction *result_instruction = ir_const(ira, source_instr, type_entry);
|
||||
ConstExprValue *out_val = &result_instruction->value;
|
||||
if (type_entry->id == ZigTypeIdVector) {
|
||||
expand_undef_array(ira->codegen, op1_val);
|
||||
expand_undef_array(ira->codegen, op2_val);
|
||||
out_val->special = ConstValSpecialUndef;
|
||||
expand_undef_array(ira->codegen, out_val);
|
||||
size_t len = type_entry->data.vector.len;
|
||||
ZigType *scalar_type = type_entry->data.vector.elem_type;
|
||||
for (size_t i = 0; i < len; i += 1) {
|
||||
ConstExprValue *scalar_op1_val = &op1_val->data.x_array.data.s_none.elements[i];
|
||||
ConstExprValue *scalar_op2_val = &op2_val->data.x_array.data.s_none.elements[i];
|
||||
ConstExprValue *scalar_out_val = &out_val->data.x_array.data.s_none.elements[i];
|
||||
assert(scalar_op1_val->type == scalar_type);
|
||||
assert(scalar_op2_val->type == scalar_type);
|
||||
assert(scalar_out_val->type == scalar_type);
|
||||
ErrorMsg *msg = ir_eval_math_op_scalar(ira, source_instr, scalar_type,
|
||||
scalar_op1_val, op_id, scalar_op2_val, scalar_out_val);
|
||||
if (msg != nullptr) {
|
||||
add_error_note(ira->codegen, msg, source_instr->source_node,
|
||||
buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, i));
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
}
|
||||
out_val->type = type_entry;
|
||||
out_val->special = ConstValSpecialStatic;
|
||||
} else {
|
||||
if (ir_eval_math_op_scalar(ira, source_instr, type_entry, op1_val, op_id, op2_val, out_val) != nullptr) {
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
}
|
||||
return ir_implicit_cast(ira, result_instruction, type_entry);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
|
||||
|
@ -12029,24 +12148,7 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b
|
|||
if (op2_val == nullptr)
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
IrInstruction *result_instruction = ir_const(ira, &bin_op_instruction->base, op1->value.type);
|
||||
|
||||
int err;
|
||||
if ((err = ir_eval_math_op(op1->value.type, op1_val, op_id, op2_val, &result_instruction->value))) {
|
||||
if (err == ErrorOverflow) {
|
||||
ir_add_error(ira, &bin_op_instruction->base, buf_sprintf("operation caused overflow"));
|
||||
return ira->codegen->invalid_instruction;
|
||||
} else if (err == ErrorShiftedOutOneBits) {
|
||||
ir_add_error(ira, &bin_op_instruction->base, buf_sprintf("exact shift shifted out 1 bits"));
|
||||
return ira->codegen->invalid_instruction;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
|
||||
ir_num_lit_fits_in_other_type(ira, result_instruction, op1->value.type, false);
|
||||
return result_instruction;
|
||||
return ir_analyze_math_op(ira, &bin_op_instruction->base, op1->value.type, op1_val, op_id, op2_val);
|
||||
} else if (op1->value.type->id == ZigTypeIdComptimeInt) {
|
||||
ir_add_error(ira, &bin_op_instruction->base,
|
||||
buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known"));
|
||||
|
@ -12292,30 +12394,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
|
|||
if (op2_val == nullptr)
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
IrInstruction *result_instruction = ir_const(ira, &instruction->base, resolved_type);
|
||||
|
||||
int err;
|
||||
if ((err = ir_eval_math_op(resolved_type, op1_val, op_id, op2_val, &result_instruction->value))) {
|
||||
if (err == ErrorDivByZero) {
|
||||
ir_add_error(ira, &instruction->base, buf_sprintf("division by zero"));
|
||||
return ira->codegen->invalid_instruction;
|
||||
} else if (err == ErrorOverflow) {
|
||||
ir_add_error(ira, &instruction->base, buf_sprintf("operation caused overflow"));
|
||||
return ira->codegen->invalid_instruction;
|
||||
} else if (err == ErrorExactDivRemainder) {
|
||||
ir_add_error(ira, &instruction->base, buf_sprintf("exact division had a remainder"));
|
||||
return ira->codegen->invalid_instruction;
|
||||
} else if (err == ErrorNegativeDenominator) {
|
||||
ir_add_error(ira, &instruction->base, buf_sprintf("negative denominator"));
|
||||
return ira->codegen->invalid_instruction;
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
|
||||
ir_num_lit_fits_in_other_type(ira, result_instruction, resolved_type, false);
|
||||
return result_instruction;
|
||||
return ir_analyze_math_op(ira, &instruction->base, resolved_type, op1_val, op_id, op2_val);
|
||||
}
|
||||
|
||||
IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,
|
||||
|
@ -18745,10 +18824,7 @@ static IrInstruction *ir_analyze_instruction_vector_type(IrAnalyze *ira, IrInstr
|
|||
if (type_is_invalid(elem_type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
if (elem_type->id != ZigTypeIdInt &&
|
||||
elem_type->id != ZigTypeIdFloat &&
|
||||
get_codegen_ptr_type(elem_type) == nullptr)
|
||||
{
|
||||
if (!is_valid_vector_elem_type(elem_type)) {
|
||||
ir_add_error(ira, instruction->elem_type,
|
||||
buf_sprintf("vector element type must be integer, float, or pointer; '%s' is invalid",
|
||||
buf_ptr(&elem_type->name)));
|
||||
|
@ -20345,6 +20421,17 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct
|
|||
return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value);
|
||||
}
|
||||
|
||||
static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ConstExprValue *val, size_t len) {
|
||||
size_t buf_i = 0;
|
||||
// TODO optimize the buf case
|
||||
expand_undef_array(codegen, val);
|
||||
for (size_t elem_i = 0; elem_i < val->type->data.array.len; elem_i += 1) {
|
||||
ConstExprValue *elem = &val->data.x_array.data.s_none.elements[elem_i];
|
||||
buf_write_value_bytes(codegen, &buf[buf_i], elem);
|
||||
buf_i += type_size(codegen, elem->type);
|
||||
}
|
||||
}
|
||||
|
||||
static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) {
|
||||
if (val->special == ConstValSpecialUndef)
|
||||
val->special = ConstValSpecialStatic;
|
||||
|
@ -20390,26 +20477,9 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
|
|||
zig_unreachable();
|
||||
}
|
||||
case ZigTypeIdArray:
|
||||
{
|
||||
size_t buf_i = 0;
|
||||
// TODO optimize the buf case
|
||||
expand_undef_array(codegen, val);
|
||||
for (size_t elem_i = 0; elem_i < val->type->data.array.len; elem_i += 1) {
|
||||
ConstExprValue *elem = &val->data.x_array.data.s_none.elements[elem_i];
|
||||
buf_write_value_bytes(codegen, &buf[buf_i], elem);
|
||||
buf_i += type_size(codegen, elem->type);
|
||||
}
|
||||
}
|
||||
return;
|
||||
case ZigTypeIdVector: {
|
||||
size_t buf_i = 0;
|
||||
for (uint32_t elem_i = 0; elem_i < val->type->data.vector.len; elem_i += 1) {
|
||||
ConstExprValue *elem = &val->data.x_vector.elements[elem_i];
|
||||
buf_write_value_bytes(codegen, &buf[buf_i], elem);
|
||||
buf_i += type_size(codegen, elem->type);
|
||||
}
|
||||
return;
|
||||
}
|
||||
return buf_write_value_bytes_array(codegen, buf, val, val->type->data.array.len);
|
||||
case ZigTypeIdVector:
|
||||
return buf_write_value_bytes_array(codegen, buf, val, val->type->data.vector.len);
|
||||
case ZigTypeIdStruct:
|
||||
zig_panic("TODO buf_write_value_bytes struct type");
|
||||
case ZigTypeIdOptional:
|
||||
|
@ -20426,6 +20496,31 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
|
|||
zig_unreachable();
|
||||
}
|
||||
|
||||
static Error buf_read_value_bytes_array(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf,
|
||||
ConstExprValue *val, ZigType *elem_type, size_t len)
|
||||
{
|
||||
Error err;
|
||||
uint64_t elem_size = type_size(codegen, elem_type);
|
||||
|
||||
switch (val->data.x_array.special) {
|
||||
case ConstArraySpecialNone:
|
||||
val->data.x_array.data.s_none.elements = create_const_vals(len);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
ConstExprValue *elem = &val->data.x_array.data.s_none.elements[i];
|
||||
elem->special = ConstValSpecialStatic;
|
||||
elem->type = elem_type;
|
||||
if ((err = buf_read_value_bytes(ira, codegen, source_node, buf + (elem_size * i), elem)))
|
||||
return err;
|
||||
}
|
||||
return ErrorNone;
|
||||
case ConstArraySpecialUndef:
|
||||
zig_panic("TODO buf_read_value_bytes ConstArraySpecialUndef array type");
|
||||
case ConstArraySpecialBuf:
|
||||
zig_panic("TODO buf_read_value_bytes ConstArraySpecialBuf array type");
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ConstExprValue *val) {
|
||||
Error err;
|
||||
assert(val->special == ConstValSpecialStatic);
|
||||
|
@ -20464,42 +20559,12 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
|
|||
val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn);
|
||||
return ErrorNone;
|
||||
}
|
||||
case ZigTypeIdArray: {
|
||||
uint64_t elem_size = type_size(codegen, val->type->data.array.child_type);
|
||||
size_t len = val->type->data.array.len;
|
||||
|
||||
switch (val->data.x_array.special) {
|
||||
case ConstArraySpecialNone:
|
||||
val->data.x_array.data.s_none.elements = create_const_vals(len);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
ConstExprValue *elem = &val->data.x_array.data.s_none.elements[i];
|
||||
elem->special = ConstValSpecialStatic;
|
||||
elem->type = val->type->data.array.child_type;
|
||||
if ((err = buf_read_value_bytes(ira, codegen, source_node, buf + (elem_size * i), elem)))
|
||||
return err;
|
||||
}
|
||||
return ErrorNone;
|
||||
case ConstArraySpecialUndef:
|
||||
zig_panic("TODO buf_read_value_bytes ConstArraySpecialUndef array type");
|
||||
case ConstArraySpecialBuf:
|
||||
zig_panic("TODO buf_read_value_bytes ConstArraySpecialBuf array type");
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
case ZigTypeIdVector: {
|
||||
uint64_t elem_size = type_size(codegen, val->type->data.vector.elem_type);
|
||||
uint32_t len = val->type->data.vector.len;
|
||||
|
||||
val->data.x_vector.elements = create_const_vals(len);
|
||||
for (uint32_t i = 0; i < len; i += 1) {
|
||||
ConstExprValue *elem = &val->data.x_vector.elements[i];
|
||||
elem->special = ConstValSpecialStatic;
|
||||
elem->type = val->type->data.vector.elem_type;
|
||||
if ((err = buf_read_value_bytes(ira, codegen, source_node, buf + (elem_size * i), elem)))
|
||||
return err;
|
||||
}
|
||||
return ErrorNone;
|
||||
}
|
||||
case ZigTypeIdArray:
|
||||
return buf_read_value_bytes_array(ira, codegen, source_node, buf, val, val->type->data.array.child_type,
|
||||
val->type->data.array.len);
|
||||
case ZigTypeIdVector:
|
||||
return buf_read_value_bytes_array(ira, codegen, source_node, buf, val, val->type->data.vector.elem_type,
|
||||
val->type->data.vector.len);
|
||||
case ZigTypeIdEnum:
|
||||
switch (val->type->data.enumeration.layout) {
|
||||
case ContainerLayoutAuto:
|
||||
|
@ -21634,6 +21699,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
|
|||
case IrInstructionIdDeclVarGen:
|
||||
case IrInstructionIdPtrCastGen:
|
||||
case IrInstructionIdCmpxchgGen:
|
||||
case IrInstructionIdArrayToVector:
|
||||
case IrInstructionIdVectorToArray:
|
||||
zig_unreachable();
|
||||
|
||||
case IrInstructionIdReturn:
|
||||
|
@ -22129,6 +22196,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
|||
case IrInstructionIdFromBytes:
|
||||
case IrInstructionIdToBytes:
|
||||
case IrInstructionIdEnumToInt:
|
||||
case IrInstructionIdVectorToArray:
|
||||
case IrInstructionIdArrayToVector:
|
||||
return false;
|
||||
|
||||
case IrInstructionIdAsm:
|
||||
|
|
|
@ -972,6 +972,18 @@ static void ir_print_check_runtime_scope(IrPrint *irp, IrInstructionCheckRuntime
|
|||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_array_to_vector(IrPrint *irp, IrInstructionArrayToVector *instruction) {
|
||||
fprintf(irp->f, "ArrayToVector(");
|
||||
ir_print_other_instruction(irp, instruction->array);
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_vector_to_array(IrPrint *irp, IrInstructionVectorToArray *instruction) {
|
||||
fprintf(irp->f, "VectorToArray(");
|
||||
ir_print_other_instruction(irp, instruction->vector);
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) {
|
||||
fprintf(irp->f, "inttoerr ");
|
||||
ir_print_other_instruction(irp, instruction->target);
|
||||
|
@ -1825,6 +1837,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
|||
case IrInstructionIdDeclVarGen:
|
||||
ir_print_decl_var_gen(irp, (IrInstructionDeclVarGen *)instruction);
|
||||
break;
|
||||
case IrInstructionIdArrayToVector:
|
||||
ir_print_array_to_vector(irp, (IrInstructionArrayToVector *)instruction);
|
||||
break;
|
||||
case IrInstructionIdVectorToArray:
|
||||
ir_print_vector_to_array(irp, (IrInstructionVectorToArray *)instruction);
|
||||
break;
|
||||
}
|
||||
fprintf(irp->f, "\n");
|
||||
}
|
||||
|
|
|
@ -74,6 +74,7 @@ comptime {
|
|||
_ = @import("behavior/underscore.zig");
|
||||
_ = @import("behavior/union.zig");
|
||||
_ = @import("behavior/var_args.zig");
|
||||
_ = @import("behavior/vector.zig");
|
||||
_ = @import("behavior/void.zig");
|
||||
_ = @import("behavior/while.zig");
|
||||
_ = @import("behavior/widening.zig");
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
const std = @import("std");
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
|
||||
test "implicit array to vector and vector to array" {
|
||||
const S = struct {
|
||||
fn doTheTest() void {
|
||||
var v: @Vector(4, i32) = [4]i32{10, 20, 30, 40};
|
||||
const x: @Vector(4, i32) = [4]i32{1, 2, 3, 4};
|
||||
v +%= x;
|
||||
const result: [4]i32 = v;
|
||||
assertOrPanic(result[0] == 11);
|
||||
assertOrPanic(result[1] == 22);
|
||||
assertOrPanic(result[2] == 33);
|
||||
assertOrPanic(result[3] == 44);
|
||||
}
|
||||
};
|
||||
S.doTheTest();
|
||||
comptime S.doTheTest();
|
||||
}
|
||||
|
Loading…
Reference in New Issue