@@ -14620,6 +14620,41 @@ static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_
14620
14620
zig_unreachable();
14621
14621
}
14622
14622
14623
+ static ErrorMsg *ir_eval_negation_scalar(IrAnalyze *ira, IrInstruction *source_instr, ZigType *scalar_type,
14624
+ ConstExprValue *operand_val, ConstExprValue *scalar_out_val, bool is_wrap_op)
14625
+ {
14626
+ bool is_float = (scalar_type->id == ZigTypeIdFloat || scalar_type->id == ZigTypeIdComptimeFloat);
14627
+
14628
+ bool ok_type = ((scalar_type->id == ZigTypeIdInt && scalar_type->data.integral.is_signed) ||
14629
+ scalar_type->id == ZigTypeIdComptimeInt || (is_float && !is_wrap_op));
14630
+
14631
+ if (!ok_type) {
14632
+ const char *fmt = is_wrap_op ? "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'";
14633
+ return ir_add_error(ira, source_instr, buf_sprintf(fmt, buf_ptr(&scalar_type->name)));
14634
+ }
14635
+
14636
+ if (is_float) {
14637
+ float_negate(scalar_out_val, operand_val);
14638
+ } else if (is_wrap_op) {
14639
+ bigint_negate_wrap(&scalar_out_val->data.x_bigint, &operand_val->data.x_bigint,
14640
+ scalar_type->data.integral.bit_count);
14641
+ } else {
14642
+ bigint_negate(&scalar_out_val->data.x_bigint, &operand_val->data.x_bigint);
14643
+ }
14644
+
14645
+ scalar_out_val->type = scalar_type;
14646
+ scalar_out_val->special = ConstValSpecialStatic;
14647
+
14648
+ if (is_wrap_op || is_float || scalar_type->id == ZigTypeIdComptimeInt) {
14649
+ return nullptr;
14650
+ }
14651
+
14652
+ if (!bigint_fits_in_bits(&scalar_out_val->data.x_bigint, scalar_type->data.integral.bit_count, true)) {
14653
+ return ir_add_error(ira, source_instr, buf_sprintf("negation caused overflow"));
14654
+ }
14655
+ return nullptr;
14656
+ }
14657
+
14623
14658
static IrInstruction *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *instruction) {
14624
14659
IrInstruction *value = instruction->value->child;
14625
14660
ZigType *expr_type = value->value.type;
@@ -14628,47 +14663,50 @@ static IrInstruction *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *ins
14628
14663
14629
14664
bool is_wrap_op = (instruction->op_id == IrUnOpNegationWrap);
14630
14665
14631
- bool is_float = (expr_type->id == ZigTypeIdFloat || expr_type->id == ZigTypeIdComptimeFloat) ;
14666
+ ZigType *scalar_type = (expr_type->id == ZigTypeIdVector) ? expr_type->data.vector.elem_type : expr_type ;
14632
14667
14633
- if ((expr_type->id == ZigTypeIdInt && expr_type->data.integral.is_signed) ||
14634
- expr_type->id == ZigTypeIdComptimeInt || (is_float && !is_wrap_op))
14635
- {
14636
- if (instr_is_comptime(value)) {
14637
- ConstExprValue *target_const_val = ir_resolve_const(ira, value, UndefBad);
14638
- if (!target_const_val)
14639
- return ira->codegen->invalid_instruction;
14668
+ if (instr_is_comptime(value)) {
14669
+ ConstExprValue *operand_val = ir_resolve_const(ira, value, UndefBad);
14670
+ if (!operand_val)
14671
+ return ira->codegen->invalid_instruction;
14640
14672
14641
- IrInstruction *result = ir_const(ira, &instruction->base, expr_type);
14642
- ConstExprValue *out_val = &result->value;
14643
- if (is_float) {
14644
- float_negate(out_val, target_const_val);
14645
- } else if (is_wrap_op) {
14646
- bigint_negate_wrap(&out_val->data.x_bigint, &target_const_val->data.x_bigint,
14647
- expr_type->data.integral.bit_count);
14648
- } else {
14649
- bigint_negate(&out_val->data.x_bigint, &target_const_val->data.x_bigint);
14650
- }
14651
- if (is_wrap_op || is_float || expr_type->id == ZigTypeIdComptimeInt) {
14652
- return result;
14673
+ IrInstruction *result_instruction = ir_const(ira, &instruction->base, expr_type);
14674
+ ConstExprValue *out_val = &result_instruction->value;
14675
+ if (expr_type->id == ZigTypeIdVector) {
14676
+ expand_undef_array(ira->codegen, operand_val);
14677
+ out_val->special = ConstValSpecialUndef;
14678
+ expand_undef_array(ira->codegen, out_val);
14679
+ size_t len = expr_type->data.vector.len;
14680
+ for (size_t i = 0; i < len; i += 1) {
14681
+ ConstExprValue *scalar_operand_val = &operand_val->data.x_array.data.s_none.elements[i];
14682
+ ConstExprValue *scalar_out_val = &out_val->data.x_array.data.s_none.elements[i];
14683
+ assert(scalar_operand_val->type == scalar_type);
14684
+ assert(scalar_out_val->type == scalar_type);
14685
+ ErrorMsg *msg = ir_eval_negation_scalar(ira, &instruction->base, scalar_type,
14686
+ scalar_operand_val, scalar_out_val, is_wrap_op);
14687
+ if (msg != nullptr) {
14688
+ add_error_note(ira->codegen, msg, instruction->base.source_node,
14689
+ buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, i));
14690
+ return ira->codegen->invalid_instruction;
14691
+ }
14653
14692
}
14654
-
14655
- if (!bigint_fits_in_bits(&out_val->data.x_bigint, expr_type->data.integral.bit_count, true)) {
14656
- ir_add_error(ira, &instruction->base, buf_sprintf("negation caused overflow"));
14693
+ out_val->type = expr_type;
14694
+ out_val->special = ConstValSpecialStatic;
14695
+ } else {
14696
+ if (ir_eval_negation_scalar(ira, &instruction->base, scalar_type, operand_val, out_val,
14697
+ is_wrap_op) != nullptr)
14698
+ {
14657
14699
return ira->codegen->invalid_instruction;
14658
14700
}
14659
- return result;
14660
14701
}
14661
-
14662
- IrInstruction *result = ir_build_un_op(&ira->new_irb,
14663
- instruction->base.scope, instruction->base.source_node,
14664
- instruction->op_id, value);
14665
- result->value.type = expr_type;
14666
- return result;
14702
+ return result_instruction;
14667
14703
}
14668
14704
14669
- const char *fmt = is_wrap_op ? "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'";
14670
- ir_add_error(ira, &instruction->base, buf_sprintf(fmt, buf_ptr(&expr_type->name)));
14671
- return ira->codegen->invalid_instruction;
14705
+ IrInstruction *result = ir_build_un_op(&ira->new_irb,
14706
+ instruction->base.scope, instruction->base.source_node,
14707
+ instruction->op_id, value);
14708
+ result->value.type = expr_type;
14709
+ return result;
14672
14710
}
14673
14711
14674
14712
static IrInstruction *ir_analyze_bin_not(IrAnalyze *ira, IrInstructionUnOp *instruction) {
0 commit comments