implement runtime @byteSwap and other fixups
* update docs for `@byteSwap`. * fix hash & eql functions for ZigLLVMFnIdBswap not updated to include vector len. this was causing incorrect bswap function being called in unrelated code * fix `@byteSwap` behavior tests only testing comptime and not runtime operations * implement runtime `@byteSwap` * fix incorrect logic in ir_render_vector_to_array and ir_render_array_to_vector with regards to whether or not to bitcast * `@byteSwap` accepts an array operand which it will cast to vector * simplify `@byteSwap` semantic analysis code and various fixes
This commit is contained in:
91
src/ir.cpp
91
src/ir.cpp
@@ -11068,8 +11068,15 @@ static ZigType *ir_resolve_int_type(IrAnalyze *ira, IrInstruction *type_value) {
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
if (ty->id != ZigTypeIdInt) {
|
||||
ir_add_error(ira, type_value,
|
||||
ErrorMsg *msg = ir_add_error(ira, type_value,
|
||||
buf_sprintf("expected integer type, found '%s'", buf_ptr(&ty->name)));
|
||||
if (ty->id == ZigTypeIdVector &&
|
||||
ty->data.vector.elem_type->id == ZigTypeIdInt)
|
||||
{
|
||||
add_error_note(ira->codegen, msg, type_value->source_node,
|
||||
buf_sprintf("represent vectors with their element types, i.e. '%s'",
|
||||
buf_ptr(&ty->data.vector.elem_type->name)));
|
||||
}
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
@@ -25253,47 +25260,35 @@ static IrInstruction *ir_analyze_instruction_float_op(IrAnalyze *ira, IrInstruct
|
||||
}
|
||||
|
||||
static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) {
|
||||
IrInstruction *op = instruction->op->child;
|
||||
ZigType *type_expr = ir_resolve_type(ira, instruction->type->child);
|
||||
if (type_is_invalid(type_expr))
|
||||
Error err;
|
||||
|
||||
ZigType *int_type = ir_resolve_int_type(ira, instruction->type->child);
|
||||
if (type_is_invalid(int_type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
if (type_expr->id != ZigTypeIdInt) {
|
||||
ir_add_error(ira, instruction->type,
|
||||
buf_sprintf("expected integer type, found '%s'", buf_ptr(&type_expr->name)));
|
||||
if (type_expr->id == ZigTypeIdVector &&
|
||||
type_expr->data.vector.elem_type->id == ZigTypeIdInt)
|
||||
ir_add_error(ira, instruction->type,
|
||||
buf_sprintf("represent vectors with their scalar types, i.e. '%s'",
|
||||
buf_ptr(&type_expr->data.vector.elem_type->name)));
|
||||
IrInstruction *uncasted_op = instruction->op->child;
|
||||
if (type_is_invalid(uncasted_op->value.type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
uint32_t vector_len; // UINT32_MAX means not a vector
|
||||
if (uncasted_op->value.type->id == ZigTypeIdArray &&
|
||||
is_valid_vector_elem_type(uncasted_op->value.type->data.array.child_type))
|
||||
{
|
||||
vector_len = uncasted_op->value.type->data.array.len;
|
||||
} else if (uncasted_op->value.type->id == ZigTypeIdVector) {
|
||||
vector_len = uncasted_op->value.type->data.vector.len;
|
||||
} else {
|
||||
vector_len = UINT32_MAX;
|
||||
}
|
||||
ZigType *int_type = type_expr;
|
||||
|
||||
ZigType *expr_type = op->value.type;
|
||||
bool is_vector = expr_type->id == ZigTypeIdVector;
|
||||
ZigType *ret_type = int_type;
|
||||
if (is_vector)
|
||||
ret_type = get_vector_type(ira->codegen, expr_type->data.vector.len, int_type);
|
||||
bool is_vector = (vector_len != UINT32_MAX);
|
||||
ZigType *op_type = is_vector ? get_vector_type(ira->codegen, vector_len, int_type) : int_type;
|
||||
|
||||
op = ir_implicit_cast(ira, instruction->op->child, ret_type);
|
||||
IrInstruction *op = ir_implicit_cast(ira, uncasted_op, op_type);
|
||||
if (type_is_invalid(op->value.type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
if (int_type->data.integral.bit_count == 0) {
|
||||
IrInstruction *result = ir_const(ira, &instruction->base, ret_type);
|
||||
if (is_vector) {
|
||||
expand_undef_array(ira->codegen, &result->value);
|
||||
result->value.data.x_array.data.s_none.elements =
|
||||
allocate<ConstExprValue>(expr_type->data.vector.len);
|
||||
for (unsigned i = 0; i < expr_type->data.vector.len; i++)
|
||||
bigint_init_unsigned(&result->value.data.x_array.data.s_none.elements[i].data.x_bigint, 0);
|
||||
}
|
||||
bigint_init_unsigned(&result->value.data.x_bigint, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (int_type->data.integral.bit_count == 8)
|
||||
if (int_type->data.integral.bit_count == 8 || int_type->data.integral.bit_count == 0)
|
||||
return op;
|
||||
|
||||
if (int_type->data.integral.bit_count % 8 != 0) {
|
||||
@@ -25308,21 +25303,28 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction
|
||||
if (val == nullptr)
|
||||
return ira->codegen->invalid_instruction;
|
||||
if (val->special == ConstValSpecialUndef)
|
||||
return ir_const_undef(ira, &instruction->base, ret_type);
|
||||
return ir_const_undef(ira, &instruction->base, op_type);
|
||||
|
||||
IrInstruction *result = ir_const(ira, &instruction->base, ret_type);
|
||||
IrInstruction *result = ir_const(ira, &instruction->base, op_type);
|
||||
size_t buf_size = int_type->data.integral.bit_count / 8;
|
||||
uint8_t *buf = allocate_nonzero<uint8_t>(buf_size);
|
||||
if (is_vector) {
|
||||
expand_undef_array(ira->codegen, &result->value);
|
||||
result->value.data.x_array.data.s_none.elements =
|
||||
allocate<ConstExprValue>(expr_type->data.vector.len);
|
||||
for (unsigned i = 0; i < expr_type->data.vector.len; i++) {
|
||||
ConstExprValue *cur = &val->data.x_array.data.s_none.elements[i];
|
||||
result->value.data.x_array.data.s_none.elements[i].special = cur->special;
|
||||
if (cur->special == ConstValSpecialUndef)
|
||||
expand_undef_array(ira->codegen, val);
|
||||
result->value.data.x_array.data.s_none.elements = create_const_vals(op_type->data.vector.len);
|
||||
for (unsigned i = 0; i < op_type->data.vector.len; i += 1) {
|
||||
ConstExprValue *op_elem_val = &val->data.x_array.data.s_none.elements[i];
|
||||
if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, instruction->base.source_node,
|
||||
op_elem_val, UndefOk)))
|
||||
{
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
ConstExprValue *result_elem_val = &result->value.data.x_array.data.s_none.elements[i];
|
||||
result_elem_val->type = int_type;
|
||||
result_elem_val->special = op_elem_val->special;
|
||||
if (op_elem_val->special == ConstValSpecialUndef)
|
||||
continue;
|
||||
bigint_write_twos_complement(&cur->data.x_bigint, buf, int_type->data.integral.bit_count, true);
|
||||
|
||||
bigint_write_twos_complement(&op_elem_val->data.x_bigint, buf, int_type->data.integral.bit_count, true);
|
||||
bigint_read_twos_complement(&result->value.data.x_array.data.s_none.elements[i].data.x_bigint,
|
||||
buf, int_type->data.integral.bit_count, false,
|
||||
int_type->data.integral.is_signed);
|
||||
@@ -25332,12 +25334,13 @@ static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstruction
|
||||
bigint_read_twos_complement(&result->value.data.x_bigint, buf, int_type->data.integral.bit_count, false,
|
||||
int_type->data.integral.is_signed);
|
||||
}
|
||||
free(buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
IrInstruction *result = ir_build_bswap(&ira->new_irb, instruction->base.scope,
|
||||
instruction->base.source_node, nullptr, op);
|
||||
result->value.type = ret_type;
|
||||
result->value.type = op_type;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user