| ... | @@ -11049,6 +11049,19 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) { | ... | @@ -11049,6 +11049,19 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) { |
| 11049 | return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, type_value->source_node, val); | 11049 | return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, type_value->source_node, val); |
| 11050 | } | 11050 | } |
| 11051 | | 11051 | |
| | 11052 | static ZigType *ir_resolve_vector_elem_type(IrAnalyze *ira, IrInstruction *elem_type_value) { |
| | 11053 | ZigType *elem_type = ir_resolve_type(ira, elem_type_value); |
| | 11054 | if (type_is_invalid(elem_type)) |
| | 11055 | return ira->codegen->builtin_types.entry_invalid; |
| | 11056 | if (!is_valid_vector_elem_type(elem_type)) { |
| | 11057 | ir_add_error(ira, elem_type_value, |
| | 11058 | buf_sprintf("vector element type must be integer, float, bool, or pointer; '%s' is invalid", |
| | 11059 | buf_ptr(&elem_type->name))); |
| | 11060 | return ira->codegen->builtin_types.entry_invalid; |
| | 11061 | } |
| | 11062 | return elem_type; |
| | 11063 | } |
| | 11064 | |
| 11052 | static ZigType *ir_resolve_int_type(IrAnalyze *ira, IrInstruction *type_value) { | 11065 | static ZigType *ir_resolve_int_type(IrAnalyze *ira, IrInstruction *type_value) { |
| 11053 | ZigType *ty = ir_resolve_type(ira, type_value); | 11066 | ZigType *ty = ir_resolve_type(ira, type_value); |
| 11054 | if (type_is_invalid(ty)) | 11067 | if (type_is_invalid(ty)) |
| ... | @@ -22096,242 +22109,212 @@ static IrInstruction *ir_analyze_instruction_vector_type(IrAnalyze *ira, IrInstr | ... | @@ -22096,242 +22109,212 @@ static IrInstruction *ir_analyze_instruction_vector_type(IrAnalyze *ira, IrInstr |
| 22096 | if (!ir_resolve_unsigned(ira, instruction->len->child, ira->codegen->builtin_types.entry_u32, &len)) | 22109 | if (!ir_resolve_unsigned(ira, instruction->len->child, ira->codegen->builtin_types.entry_u32, &len)) |
| 22097 | return ira->codegen->invalid_instruction; | 22110 | return ira->codegen->invalid_instruction; |
| 22098 | | 22111 | |
| 22099 | ZigType *elem_type = ir_resolve_type(ira, instruction->elem_type->child); | 22112 | ZigType *elem_type = ir_resolve_vector_elem_type(ira, instruction->elem_type->child); |
| 22100 | if (type_is_invalid(elem_type)) | 22113 | if (type_is_invalid(elem_type)) |
| 22101 | return ira->codegen->invalid_instruction; | 22114 | return ira->codegen->invalid_instruction; |
| 22102 | | 22115 | |
| 22103 | if (!is_valid_vector_elem_type(elem_type)) { | | |
| 22104 | ir_add_error(ira, instruction->elem_type, | | |
| 22105 | buf_sprintf("vector element type must be integer, float, bool, or pointer; '%s' is invalid", | | |
| 22106 | buf_ptr(&elem_type->name))); | | |
| 22107 | return ira->codegen->invalid_instruction; | | |
| 22108 | } | | |
| 22109 | | | |
| 22110 | ZigType *vector_type = get_vector_type(ira->codegen, len, elem_type); | 22116 | ZigType *vector_type = get_vector_type(ira->codegen, len, elem_type); |
| 22111 | | 22117 | |
| 22112 | return ir_const_type(ira, &instruction->base, vector_type); | 22118 | return ir_const_type(ira, &instruction->base, vector_type); |
| 22113 | } | 22119 | } |
| 22114 | | 22120 | |
| 22115 | static IrInstruction *ir_analyze_shuffle_vector(IrAnalyze *ira, IrInstruction *source_instr, | 22121 | static IrInstruction *ir_analyze_shuffle_vector(IrAnalyze *ira, IrInstruction *source_instr, |
| 22116 | ZigType *scalar_type, IrInstruction *a, IrInstruction *b, IrInstruction *mask) { | 22122 | ZigType *scalar_type, IrInstruction *a, IrInstruction *b, IrInstruction *mask) |
| 22117 | assert(source_instr && scalar_type && a && b && mask); | 22123 | { |
| 22118 | assert(scalar_type->id == ZigTypeIdBool || | 22124 | ir_assert(source_instr && scalar_type && a && b && mask, source_instr); |
| 22119 | scalar_type->id == ZigTypeIdInt || | 22125 | ir_assert(is_valid_vector_elem_type(scalar_type), source_instr); |
| 22120 | scalar_type->id == ZigTypeIdFloat || | 22126 | |
| 22121 | scalar_type->id == ZigTypeIdPointer); | 22127 | uint32_t len_mask; |
| 22122 | | 22128 | if (mask->value.type->id == ZigTypeIdVector) { |
| 22123 | ZigType *mask_type = mask->value.type; | 22129 | len_mask = mask->value.type->data.vector.len; |
| 22124 | if (type_is_invalid(mask_type)) | 22130 | } else if (mask->value.type->id == ZigTypeIdArray) { |
| | 22131 | len_mask = mask->value.type->data.array.len; |
| | 22132 | } else { |
| | 22133 | ir_add_error(ira, mask, |
| | 22134 | buf_sprintf("expected vector or array, found '%s'", |
| | 22135 | buf_ptr(&mask->value.type->name))); |
| 22125 | return ira->codegen->invalid_instruction; | 22136 | return ira->codegen->invalid_instruction; |
| 22126 | | | |
| 22127 | const char *shuffle_mask_fail_fmt = "@shuffle mask operand must be a vector of signed 32-bit integers, got '%s'"; | | |
| 22128 | | | |
| 22129 | if (mask_type->id == ZigTypeIdArray) { | | |
| 22130 | ZigType *vector_type = get_vector_type(ira->codegen, mask_type->data.array.len, mask_type->data.array.child_type); | | |
| 22131 | mask = ir_analyze_array_to_vector(ira, mask, mask, vector_type); | | |
| 22132 | if (!mask) | | |
| 22133 | return ira->codegen->invalid_instruction; | | |
| 22134 | mask_type = vector_type; | | |
| 22135 | } | 22137 | } |
| | 22138 | mask = ir_implicit_cast(ira, mask, get_vector_type(ira->codegen, len_mask, |
| | 22139 | ira->codegen->builtin_types.entry_i32)); |
| | 22140 | if (type_is_invalid(mask->value.type)) |
| | 22141 | return ira->codegen->invalid_instruction; |
| 22136 | | 22142 | |
| 22137 | if (mask_type->id != ZigTypeIdVector) { | 22143 | uint32_t len_a; |
| 22138 | ir_add_error(ira, mask, | 22144 | if (a->value.type->id == ZigTypeIdVector) { |
| 22139 | buf_sprintf(shuffle_mask_fail_fmt, buf_ptr(&mask->value.type->name))); | 22145 | len_a = a->value.type->data.vector.len; |
| | 22146 | } else if (a->value.type->id == ZigTypeIdArray) { |
| | 22147 | len_a = a->value.type->data.array.len; |
| | 22148 | } else if (a->value.type->id == ZigTypeIdUndefined) { |
| | 22149 | len_a = UINT32_MAX; |
| | 22150 | } else { |
| | 22151 | ir_add_error(ira, a, |
| | 22152 | buf_sprintf("expected vector or array with element type '%s', found '%s'", |
| | 22153 | buf_ptr(&scalar_type->name), |
| | 22154 | buf_ptr(&a->value.type->name))); |
| 22140 | return ira->codegen->invalid_instruction; | 22155 | return ira->codegen->invalid_instruction; |
| 22141 | } | 22156 | } |
| 22142 | | 22157 | |
| 22143 | ZigType *mask_scalar_type = mask_type->data.array.child_type; | 22158 | uint32_t len_b; |
| 22144 | if (mask_scalar_type->id != ZigTypeIdInt) { | 22159 | if (b->value.type->id == ZigTypeIdVector) { |
| 22145 | ir_add_error(ira, mask, | 22160 | len_b = b->value.type->data.vector.len; |
| 22146 | buf_sprintf(shuffle_mask_fail_fmt, buf_ptr(&mask->value.type->name))); | 22161 | } else if (b->value.type->id == ZigTypeIdArray) { |
| | 22162 | len_b = b->value.type->data.array.len; |
| | 22163 | } else if (b->value.type->id == ZigTypeIdUndefined) { |
| | 22164 | len_b = UINT32_MAX; |
| | 22165 | } else { |
| | 22166 | ir_add_error(ira, b, |
| | 22167 | buf_sprintf("expected vector or array with element type '%s', found '%s'", |
| | 22168 | buf_ptr(&scalar_type->name), |
| | 22169 | buf_ptr(&b->value.type->name))); |
| 22147 | return ira->codegen->invalid_instruction; | 22170 | return ira->codegen->invalid_instruction; |
| 22148 | } | 22171 | } |
| 22149 | | 22172 | |
| 22150 | if (mask_scalar_type->data.integral.bit_count != 32 || | 22173 | if (len_a == UINT32_MAX && len_b == UINT32_MAX) { |
| 22151 | mask_scalar_type->data.integral.is_signed == false) { | 22174 | return ir_const_undef(ira, a, get_vector_type(ira->codegen, len_mask, scalar_type)); |
| 22152 | ir_add_error(ira, mask, | | |
| 22153 | buf_sprintf(shuffle_mask_fail_fmt, buf_ptr(&mask->value.type->name))); | | |
| 22154 | return ira->codegen->invalid_instruction; | | |
| 22155 | } | 22175 | } |
| 22156 | | 22176 | |
| 22157 | uint64_t len_a, len_b, len_c = mask->value.type->data.vector.len; | 22177 | if (len_a == UINT32_MAX) { |
| 22158 | if (a->value.type->id != ZigTypeIdVector) { | 22178 | len_a = len_b; |
| 22159 | if (a->value.type->id != ZigTypeIdUndefined) { | 22179 | a = ir_const_undef(ira, a, get_vector_type(ira->codegen, len_a, scalar_type)); |
| 22160 | ir_add_error(ira, a, | 22180 | } else { |
| 22161 | buf_sprintf("expected vector of element type '%s' got '%s'", | 22181 | a = ir_implicit_cast(ira, a, get_vector_type(ira->codegen, len_a, scalar_type)); |
| 22162 | buf_ptr(&scalar_type->name), | 22182 | if (type_is_invalid(a->value.type)) |
| 22163 | buf_ptr(&a->value.type->name))); | | |
| 22164 | return ira->codegen->invalid_instruction; | 22183 | return ira->codegen->invalid_instruction; |
| 22165 | } | 22184 | } |
| | 22185 | |
| | 22186 | if (len_b == UINT32_MAX) { |
| | 22187 | len_b = len_a; |
| | 22188 | b = ir_const_undef(ira, b, get_vector_type(ira->codegen, len_b, scalar_type)); |
| 22166 | } else { | 22189 | } else { |
| 22167 | len_a = a->value.type->data.vector.len; | 22190 | b = ir_implicit_cast(ira, b, get_vector_type(ira->codegen, len_b, scalar_type)); |
| | 22191 | if (type_is_invalid(b->value.type)) |
| | 22192 | return ira->codegen->invalid_instruction; |
| 22168 | } | 22193 | } |
| 22169 | | 22194 | |
| 22170 | if (b->value.type->id != ZigTypeIdVector) { | 22195 | ConstExprValue *mask_val = ir_resolve_const(ira, mask, UndefOk); |
| 22171 | if (b->value.type->id != ZigTypeIdUndefined) { | 22196 | if (mask_val == nullptr) |
| 22172 | ir_add_error(ira, b, | 22197 | return ira->codegen->invalid_instruction; |
| 22173 | buf_sprintf("expected vector of element type '%s' got '%s'", | 22198 | |
| 22174 | buf_ptr(&scalar_type->name), | 22199 | expand_undef_array(ira->codegen, mask_val); |
| 22175 | buf_ptr(&b->value.type->name))); | 22200 | |
| | 22201 | for (uint32_t i = 0; i < len_mask; i += 1) { |
| | 22202 | ConstExprValue *mask_elem_val = &mask_val->data.x_array.data.s_none.elements[i]; |
| | 22203 | if (mask_elem_val->special == ConstValSpecialUndef) |
| | 22204 | continue; |
| | 22205 | int32_t v_i32 = bigint_as_signed(&mask_elem_val->data.x_bigint); |
| | 22206 | uint32_t v; |
| | 22207 | IrInstruction *chosen_operand; |
| | 22208 | if (v_i32 >= 0) { |
| | 22209 | v = (uint32_t)v_i32; |
| | 22210 | chosen_operand = a; |
| | 22211 | } else { |
| | 22212 | v = (uint32_t)~v_i32; |
| | 22213 | chosen_operand = b; |
| | 22214 | } |
| | 22215 | if (v >= chosen_operand->value.type->data.vector.len) { |
| | 22216 | ErrorMsg *msg = ir_add_error(ira, mask, |
| | 22217 | buf_sprintf("mask index '%u' has out-of-bounds selection", i)); |
| | 22218 | add_error_note(ira->codegen, msg, chosen_operand->source_node, |
| | 22219 | buf_sprintf("selected index '%u' out of bounds of %s", v, |
| | 22220 | buf_ptr(&chosen_operand->value.type->name))); |
| | 22221 | if (chosen_operand == a && v < len_a + len_b) { |
| | 22222 | add_error_note(ira->codegen, msg, b->source_node, |
| | 22223 | buf_create_from_str("selections from the second vector are specified with negative numbers")); |
| | 22224 | } |
| 22176 | return ira->codegen->invalid_instruction; | 22225 | return ira->codegen->invalid_instruction; |
| 22177 | } | 22226 | } |
| 22178 | } else { | | |
| 22179 | len_b = b->value.type->data.vector.len; | | |
| 22180 | } | 22227 | } |
| 22181 | | 22228 | |
| 22182 | if (a->value.type->id == ZigTypeIdUndefined && b->value.type->id == ZigTypeIdUndefined) { | 22229 | ZigType *result_type = get_vector_type(ira->codegen, len_mask, scalar_type); |
| 22183 | return ir_const_undef(ira, a, get_vector_type(ira->codegen, len_c, scalar_type)); | 22230 | if (instr_is_comptime(a) && instr_is_comptime(b)) { |
| 22184 | } | 22231 | ConstExprValue *a_val = ir_resolve_const(ira, a, UndefOk); |
| | 22232 | if (a_val == nullptr) |
| | 22233 | return ira->codegen->invalid_instruction; |
| 22185 | | 22234 | |
| 22186 | // undefined is a vector up to length of the other vector. | 22235 | ConstExprValue *b_val = ir_resolve_const(ira, b, UndefOk); |
| 22187 | if (a->value.type->id == ZigTypeIdUndefined) { | 22236 | if (b_val == nullptr) |
| 22188 | a = ir_const_undef(ira, a, b->value.type); | 22237 | return ira->codegen->invalid_instruction; |
| 22189 | len_a = b->value.type->data.vector.len; | | |
| 22190 | } else if (b->value.type->id == ZigTypeIdUndefined) { | | |
| 22191 | b = ir_const_undef(ira, b, a->value.type); | | |
| 22192 | len_b = a->value.type->data.vector.len; | | |
| 22193 | } | | |
| 22194 | | 22238 | |
| 22195 | // FIXME I think this needs to be more sophisticated | 22239 | expand_undef_array(ira->codegen, a_val); |
| 22196 | if (a->value.type->data.vector.elem_type != scalar_type) { | 22240 | expand_undef_array(ira->codegen, b_val); |
| 22197 | ir_add_error(ira, a, | 22241 | |
| 22198 | buf_sprintf("element type '%s' does not match '%s'", | 22242 | IrInstruction *result = ir_const(ira, source_instr, result_type); |
| 22199 | buf_ptr(&a->value.type->data.vector.elem_type->name), | 22243 | result->value.data.x_array.data.s_none.elements = create_const_vals(len_mask); |
| 22200 | buf_ptr(&scalar_type->name))); | 22244 | for (uint32_t i = 0; i < mask_val->type->data.vector.len; i += 1) { |
| 22201 | return ira->codegen->invalid_instruction; | 22245 | ConstExprValue *mask_elem_val = &mask_val->data.x_array.data.s_none.elements[i]; |
| 22202 | } | 22246 | ConstExprValue *result_elem_val = &result->value.data.x_array.data.s_none.elements[i]; |
| 22203 | if (b->value.type->data.vector.elem_type != scalar_type) { | 22247 | if (mask_elem_val->special == ConstValSpecialUndef) { |
| 22204 | ir_add_error(ira, b, | 22248 | result_elem_val->special = ConstValSpecialUndef; |
| 22205 | buf_sprintf("element type '%s' does not match '%s'", | 22249 | continue; |
| 22206 | buf_ptr(&b->value.type->data.vector.elem_type->name), | 22250 | } |
| 22207 | buf_ptr(&scalar_type->name))); | 22251 | int32_t v = bigint_as_signed(&mask_elem_val->data.x_bigint); |
| 22208 | return ira->codegen->invalid_instruction; | 22252 | // We've already checked for and emitted compile errors for index out of bounds here. |
| | 22253 | ConstExprValue *src_elem_val = (v >= 0) ? |
| | 22254 | &a->value.data.x_array.data.s_none.elements[v] : |
| | 22255 | &b->value.data.x_array.data.s_none.elements[~v]; |
| | 22256 | copy_const_val(result_elem_val, src_elem_val, false); |
| | 22257 | |
| | 22258 | ir_assert(result_elem_val->special == ConstValSpecialStatic, source_instr); |
| | 22259 | } |
| | 22260 | result->value.special = ConstValSpecialStatic; |
| | 22261 | return result; |
| 22209 | } | 22262 | } |
| 22210 | | 22263 | |
| 22211 | if (a->value.type != b->value.type) { | 22264 | // All static analysis passed, and not comptime. |
| 22212 | assert(len_a != len_b); | 22265 | // For runtime codegen, vectors a and b must be the same length. Here we |
| 22213 | uint32_t len_max = max(len_a, len_b), len_min = min(len_a, len_b); | 22266 | // recursively @shuffle the smaller vector to append undefined elements |
| 22214 | bool expand_b = len_b < len_a; | 22267 | // to it up to the length of the longer vector. This recursion terminates |
| | 22268 | // in 1 call because these calls to ir_analyze_shuffle_vector guarantee |
| | 22269 | // len_a == len_b. |
| | 22270 | if (len_a != len_b) { |
| | 22271 | uint32_t len_min = min(len_a, len_b); |
| | 22272 | uint32_t len_max = max(len_a, len_b); |
| | 22273 | |
| 22215 | IrInstruction *expand_mask = ir_const(ira, mask, | 22274 | IrInstruction *expand_mask = ir_const(ira, mask, |
| 22216 | get_vector_type(ira->codegen, len_max, ira->codegen->builtin_types.entry_i32)); | 22275 | get_vector_type(ira->codegen, len_max, ira->codegen->builtin_types.entry_i32)); |
| 22217 | expand_mask->value.data.x_array.data.s_none.elements = create_const_vals(len_max); | 22276 | expand_mask->value.data.x_array.data.s_none.elements = create_const_vals(len_max); |
| 22218 | uint32_t i = 0; | 22277 | uint32_t i = 0; |
| 22219 | for (; i < len_min; i++) | 22278 | for (; i < len_min; i += 1) |
| 22220 | bigint_init_unsigned(&expand_mask->value.data.x_array.data.s_none.elements[i].data.x_bigint, i); | 22279 | bigint_init_unsigned(&expand_mask->value.data.x_array.data.s_none.elements[i].data.x_bigint, i); |
| 22221 | for (; i < len_max; i++) | 22280 | for (; i < len_max; i += 1) |
| 22222 | bigint_init_signed(&expand_mask->value.data.x_array.data.s_none.elements[i].data.x_bigint, -1); | 22281 | bigint_init_signed(&expand_mask->value.data.x_array.data.s_none.elements[i].data.x_bigint, -1); |
| | 22282 | |
| 22223 | IrInstruction *undef = ir_const_undef(ira, source_instr, | 22283 | IrInstruction *undef = ir_const_undef(ira, source_instr, |
| 22224 | get_vector_type(ira->codegen, len_min, scalar_type)); | 22284 | get_vector_type(ira->codegen, len_min, scalar_type)); |
| 22225 | if (expand_b) { | | |
| 22226 | if (instr_is_comptime(b)) { | | |
| 22227 | ConstExprValue *old = b->value.data.x_array.data.s_none.elements; | | |
| 22228 | b->value.data.x_array.data.s_none.elements = | | |
| 22229 | allocate<ConstExprValue>(len_a); | | |
| 22230 | memcpy(b->value.data.x_array.data.s_none.elements, old, | | |
| 22231 | b->value.type->data.vector.len * sizeof(ConstExprValue)); | | |
| 22232 | } else { | | |
| 22233 | b = ir_build_shuffle_vector(&ira->new_irb, | | |
| 22234 | source_instr->scope, source_instr->source_node, | | |
| 22235 | nullptr, b, undef, expand_mask); | | |
| 22236 | b->value.special = ConstValSpecialRuntime; | | |
| 22237 | } | | |
| 22238 | b->value.type = get_vector_type(ira->codegen, len_max, scalar_type); | | |
| 22239 | } else { | | |
| 22240 | if (instr_is_comptime(a)) { | | |
| 22241 | ConstExprValue *old = a->value.data.x_array.data.s_none.elements; | | |
| 22242 | a->value.data.x_array.data.s_none.elements = | | |
| 22243 | allocate<ConstExprValue>(len_b); | | |
| 22244 | memcpy(a->value.data.x_array.data.s_none.elements, old, | | |
| 22245 | a->value.type->data.vector.len * sizeof(ConstExprValue)); | | |
| 22246 | } else { | | |
| 22247 | a = ir_build_shuffle_vector(&ira->new_irb, | | |
| 22248 | source_instr->scope, source_instr->source_node, | | |
| 22249 | nullptr, a, undef, expand_mask); | | |
| 22250 | a->value.special = ConstValSpecialRuntime; | | |
| 22251 | } | | |
| 22252 | a->value.type = get_vector_type(ira->codegen, len_max, scalar_type); | | |
| 22253 | } | | |
| 22254 | } | | |
| 22255 | ConstExprValue *mask_val = ir_resolve_const(ira, mask, UndefOk); | | |
| 22256 | if (!mask_val) { | | |
| 22257 | ir_add_error(ira, mask, | | |
| 22258 | buf_sprintf("mask must be comptime")); | | |
| 22259 | return ira->codegen->invalid_instruction; | | |
| 22260 | } | | |
| 22261 | for (uint32_t i = 0;i < mask->value.type->data.vector.len;i++) { | | |
| 22262 | if (mask->value.data.x_array.data.s_none.elements[i].special == ConstValSpecialUndef) | | |
| 22263 | continue; | | |
| 22264 | int64_t v = bigint_as_signed(&mask->value.data.x_array.data.s_none.elements[i].data.x_bigint); | | |
| 22265 | if (v >= 0 && (uint64_t)v + 1 > len_a) { | | |
| 22266 | ErrorMsg *msg = ir_add_error(ira, mask, | | |
| 22267 | buf_sprintf("mask index out of bounds")); | | |
| 22268 | add_error_note(ira->codegen, msg, mask->source_node, | | |
| 22269 | buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, (uintptr_t)i)); | | |
| 22270 | if ((uint64_t)v <= len_a + len_b) | | |
| 22271 | add_error_note(ira->codegen, msg, mask->source_node, | | |
| 22272 | buf_sprintf("selections from the second vector are specified with negative numbers")); | | |
| 22273 | } else if (v < 0 && (uint64_t)~v + 1 > len_b) { | | |
| 22274 | ErrorMsg *msg = ir_add_error(ira, mask, | | |
| 22275 | buf_sprintf("mask index out of bounds")); | | |
| 22276 | add_error_note(ira->codegen, msg, mask->source_node, | | |
| 22277 | buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, (uintptr_t)i)); | | |
| 22278 | } | | |
| 22279 | else | | |
| 22280 | continue; | | |
| 22281 | return ira->codegen->invalid_instruction; | | |
| 22282 | } | | |
| 22283 | | 22285 | |
| 22284 | ZigType *result_type = get_vector_type(ira->codegen, len_c, scalar_type); | 22286 | if (len_b < len_a) { |
| 22285 | if (instr_is_comptime(a) && | 22287 | b = ir_analyze_shuffle_vector(ira, source_instr, scalar_type, b, undef, expand_mask); |
| 22286 | instr_is_comptime(b)) { | 22288 | } else { |
| 22287 | IrInstruction *result = ir_const(ira, source_instr, result_type); | 22289 | a = ir_analyze_shuffle_vector(ira, source_instr, scalar_type, a, undef, expand_mask); |
| 22288 | result->value.data.x_array.data.s_none.elements = create_const_vals(len_c); | | |
| 22289 | for (uint32_t i = 0;i < mask->value.type->data.vector.len;i++) { | | |
| 22290 | if (mask->value.data.x_array.data.s_none.elements[i].special == ConstValSpecialUndef) | | |
| 22291 | result->value.data.x_array.data.s_none.elements[i].special = | | |
| 22292 | ConstValSpecialUndef; | | |
| 22293 | int64_t v = bigint_as_signed(&mask->value.data.x_array.data.s_none.elements[i].data.x_bigint); | | |
| 22294 | if (v >= 0) | | |
| 22295 | result->value.data.x_array.data.s_none.elements[i] = | | |
| 22296 | a->value.data.x_array.data.s_none.elements[v]; | | |
| 22297 | else if (v < 0) | | |
| 22298 | result->value.data.x_array.data.s_none.elements[i] = | | |
| 22299 | b->value.data.x_array.data.s_none.elements[~v]; | | |
| 22300 | else | | |
| 22301 | zig_unreachable(); | | |
| 22302 | result->value.data.x_array.data.s_none.elements[i].special = | | |
| 22303 | ConstValSpecialStatic; | | |
| 22304 | } | 22290 | } |
| 22305 | result->value.special = ConstValSpecialStatic; | | |
| 22306 | return result; | | |
| 22307 | } | 22291 | } |
| 22308 | | 22292 | |
| 22309 | // All static analysis passed, and not comptime | | |
| 22310 | IrInstruction *result = ir_build_shuffle_vector(&ira->new_irb, | 22293 | IrInstruction *result = ir_build_shuffle_vector(&ira->new_irb, |
| 22311 | source_instr->scope, source_instr->source_node, | 22294 | source_instr->scope, source_instr->source_node, |
| 22312 | nullptr, a, b, mask); | 22295 | nullptr, a, b, mask); |
| 22313 | result->value.type = result_type; | 22296 | result->value.type = result_type; |
| 22314 | result->value.special = ConstValSpecialRuntime; | | |
| 22315 | return result; | 22297 | return result; |
| 22316 | } | 22298 | } |
| 22317 | | 22299 | |
| 22318 | static IrInstruction *ir_analyze_instruction_shuffle_vector(IrAnalyze *ira, IrInstructionShuffleVector *instruction) { | 22300 | static IrInstruction *ir_analyze_instruction_shuffle_vector(IrAnalyze *ira, IrInstructionShuffleVector *instruction) { |
| 22319 | ZigType *scalar_type = ir_resolve_type(ira, instruction->scalar_type); | 22301 | ZigType *scalar_type = ir_resolve_vector_elem_type(ira, instruction->scalar_type); |
| 22320 | assert(scalar_type); | | |
| 22321 | if (type_is_invalid(scalar_type)) | 22302 | if (type_is_invalid(scalar_type)) |
| 22322 | return ira->codegen->invalid_instruction; | 22303 | return ira->codegen->invalid_instruction; |
| 22323 | | 22304 | |
| 22324 | if (scalar_type->id != ZigTypeIdBool && | 22305 | IrInstruction *a = instruction->a->child; |
| 22325 | scalar_type->id != ZigTypeIdInt && | 22306 | if (type_is_invalid(a->value.type)) |
| 22326 | scalar_type->id != ZigTypeIdFloat && | 22307 | return ira->codegen->invalid_instruction; |
| 22327 | scalar_type->id != ZigTypeIdPointer) { | 22308 | |
| 22328 | ir_add_error(ira, instruction->scalar_type, | 22309 | IrInstruction *b = instruction->b->child; |
| 22329 | buf_sprintf("vector element type must be integer, float, bool, or pointer; '%s' is invalid", | 22310 | if (type_is_invalid(b->value.type)) |
| 22330 | buf_ptr(&scalar_type->name))); | 22311 | return ira->codegen->invalid_instruction; |
| | 22312 | |
| | 22313 | IrInstruction *mask = instruction->mask->child; |
| | 22314 | if (type_is_invalid(mask->value.type)) |
| 22331 | return ira->codegen->invalid_instruction; | 22315 | return ira->codegen->invalid_instruction; |
| 22332 | } | | |
| 22333 | | 22316 | |
| 22334 | return ir_analyze_shuffle_vector(ira, &instruction->base, scalar_type, instruction->a->child, instruction->b->child, instruction->mask->child); | 22317 | return ir_analyze_shuffle_vector(ira, &instruction->base, scalar_type, a, b, mask); |
| 22335 | } | 22318 | } |
| 22336 | | 22319 | |
| 22337 | static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) { | 22320 | static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) { |