| ... | ... | @@ -10283,6 +10283,12 @@ static IrInstruction *ir_const_bool(IrAnalyze *ira, IrInstruction *source_instru |
| 10283 | 10283 | return result; |
| 10284 | 10284 | } |
| 10285 | 10285 | |
| 10286 | static IrInstruction *ir_const_undef(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) { |
| 10287 | IrInstruction *result = ir_const(ira, source_instruction, ty); |
| 10288 | result->value.special = ConstValSpecialUndef; |
| 10289 | return result; |
| 10290 | } |
| 10291 | |
| 10286 | 10292 | static IrInstruction *ir_const_void(IrAnalyze *ira, IrInstruction *source_instruction) { |
| 10287 | 10293 | return ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_void); |
| 10288 | 10294 | } |
| ... | ... | @@ -10596,19 +10602,34 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so |
| 10596 | 10602 | assert(instr_is_comptime(value)); |
| 10597 | 10603 | |
| 10598 | 10604 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); |
| 10599 | | assert(val); |
| 10605 | assert(val != nullptr); |
| 10600 | 10606 | |
| 10601 | | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, source_instr->scope, source_instr->source_node); |
| 10602 | | const_instruction->base.value.special = ConstValSpecialStatic; |
| 10607 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| 10608 | result->value.special = ConstValSpecialStatic; |
| 10603 | 10609 | if (get_codegen_ptr_type(wanted_type) != nullptr) { |
| 10604 | | const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialNull; |
| 10610 | result->value.data.x_ptr.special = ConstPtrSpecialNull; |
| 10605 | 10611 | } else if (is_opt_err_set(wanted_type)) { |
| 10606 | | const_instruction->base.value.data.x_err_set = nullptr; |
| 10612 | result->value.data.x_err_set = nullptr; |
| 10607 | 10613 | } else { |
| 10608 | | const_instruction->base.value.data.x_optional = nullptr; |
| 10614 | result->value.data.x_optional = nullptr; |
| 10609 | 10615 | } |
| 10610 | | const_instruction->base.value.type = wanted_type; |
| 10611 | | return &const_instruction->base; |
| 10616 | return result; |
| 10617 | } |
| 10618 | |
| 10619 | static IrInstruction *ir_analyze_null_to_c_pointer(IrAnalyze *ira, IrInstruction *source_instr, |
| 10620 | IrInstruction *value, ZigType *wanted_type) |
| 10621 | { |
| 10622 | assert(wanted_type->id == ZigTypeIdPointer); |
| 10623 | assert(wanted_type->data.pointer.ptr_len == PtrLenC); |
| 10624 | assert(instr_is_comptime(value)); |
| 10625 | |
| 10626 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); |
| 10627 | assert(val != nullptr); |
| 10628 | |
| 10629 | IrInstruction *result = ir_const(ira, source_instr, wanted_type); |
| 10630 | result->value.data.x_ptr.special = ConstPtrSpecialNull; |
| 10631 | result->value.data.x_ptr.mut = ConstPtrMutComptimeConst; |
| 10632 | return result; |
| 10612 | 10633 | } |
| 10613 | 10634 | |
| 10614 | 10635 | static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *value, |
| ... | ... | @@ -11610,6 +11631,13 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 11610 | 11631 | return ir_analyze_null_to_maybe(ira, source_instr, value, wanted_type); |
| 11611 | 11632 | } |
| 11612 | 11633 | |
| 11634 | // cast from null literal to C pointer |
| 11635 | if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC && |
| 11636 | actual_type->id == ZigTypeIdNull) |
| 11637 | { |
| 11638 | return ir_analyze_null_to_c_pointer(ira, source_instr, value, wanted_type); |
| 11639 | } |
| 11640 | |
| 11613 | 11641 | // cast from [N]T to E![]const T |
| 11614 | 11642 | if (wanted_type->id == ZigTypeIdErrorUnion && |
| 11615 | 11643 | is_slice(wanted_type->data.error_union.payload_type) && |
| ... | ... | @@ -12227,14 +12255,12 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 12227 | 12255 | |
| 12228 | 12256 | IrBinOp op_id = bin_op_instruction->op_id; |
| 12229 | 12257 | bool is_equality_cmp = (op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq); |
| 12230 | | if (is_equality_cmp && |
| 12258 | if (is_equality_cmp && op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdNull) { |
| 12259 | return ir_const_bool(ira, &bin_op_instruction->base, (op_id == IrBinOpCmpEq)); |
| 12260 | } else if (is_equality_cmp && |
| 12231 | 12261 | ((op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdOptional) || |
| 12232 | | (op2->value.type->id == ZigTypeIdNull && op1->value.type->id == ZigTypeIdOptional) || |
| 12233 | | (op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdNull))) |
| 12262 | (op2->value.type->id == ZigTypeIdNull && op1->value.type->id == ZigTypeIdOptional))) |
| 12234 | 12263 | { |
| 12235 | | if (op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdNull) { |
| 12236 | | return ir_const_bool(ira, &bin_op_instruction->base, (op_id == IrBinOpCmpEq)); |
| 12237 | | } |
| 12238 | 12264 | IrInstruction *maybe_op; |
| 12239 | 12265 | if (op1->value.type->id == ZigTypeIdNull) { |
| 12240 | 12266 | maybe_op = op2; |
| ... | ... | @@ -12256,6 +12282,44 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 12256 | 12282 | source_node, maybe_op); |
| 12257 | 12283 | is_non_null->value.type = ira->codegen->builtin_types.entry_bool; |
| 12258 | 12284 | |
| 12285 | if (op_id == IrBinOpCmpEq) { |
| 12286 | IrInstruction *result = ir_build_bool_not(&ira->new_irb, bin_op_instruction->base.scope, |
| 12287 | bin_op_instruction->base.source_node, is_non_null); |
| 12288 | result->value.type = ira->codegen->builtin_types.entry_bool; |
| 12289 | return result; |
| 12290 | } else { |
| 12291 | return is_non_null; |
| 12292 | } |
| 12293 | } else if (is_equality_cmp && |
| 12294 | ((op1->value.type->id == ZigTypeIdNull && op2->value.type->id == ZigTypeIdPointer && |
| 12295 | op2->value.type->data.pointer.ptr_len == PtrLenC) || |
| 12296 | (op2->value.type->id == ZigTypeIdNull && op1->value.type->id == ZigTypeIdPointer && |
| 12297 | op1->value.type->data.pointer.ptr_len == PtrLenC))) |
| 12298 | { |
| 12299 | IrInstruction *c_ptr_op; |
| 12300 | if (op1->value.type->id == ZigTypeIdNull) { |
| 12301 | c_ptr_op = op2; |
| 12302 | } else if (op2->value.type->id == ZigTypeIdNull) { |
| 12303 | c_ptr_op = op1; |
| 12304 | } else { |
| 12305 | zig_unreachable(); |
| 12306 | } |
| 12307 | if (instr_is_comptime(c_ptr_op)) { |
| 12308 | ConstExprValue *c_ptr_val = ir_resolve_const(ira, c_ptr_op, UndefOk); |
| 12309 | if (!c_ptr_val) |
| 12310 | return ira->codegen->invalid_instruction; |
| 12311 | if (c_ptr_val->special == ConstValSpecialUndef) |
| 12312 | return ir_const_undef(ira, &bin_op_instruction->base, ira->codegen->builtin_types.entry_bool); |
| 12313 | bool is_null = c_ptr_val->data.x_ptr.special == ConstPtrSpecialNull || |
| 12314 | (c_ptr_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr && |
| 12315 | c_ptr_val->data.x_ptr.data.hard_coded_addr.addr == 0); |
| 12316 | bool bool_result = (op_id == IrBinOpCmpEq) ? is_null : !is_null; |
| 12317 | return ir_const_bool(ira, &bin_op_instruction->base, bool_result); |
| 12318 | } |
| 12319 | IrInstruction *is_non_null = ir_build_test_nonnull(&ira->new_irb, bin_op_instruction->base.scope, |
| 12320 | source_node, c_ptr_op); |
| 12321 | is_non_null->value.type = ira->codegen->builtin_types.entry_bool; |
| 12322 | |
| 12259 | 12323 | if (op_id == IrBinOpCmpEq) { |
| 12260 | 12324 | IrInstruction *result = ir_build_bool_not(&ira->new_irb, bin_op_instruction->base.scope, |
| 12261 | 12325 | bin_op_instruction->base.source_node, is_non_null); |
| ... | ... | @@ -12265,8 +12329,9 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp * |
| 12265 | 12329 | return is_non_null; |
| 12266 | 12330 | } |
| 12267 | 12331 | } else if (op1->value.type->id == ZigTypeIdNull || op2->value.type->id == ZigTypeIdNull) { |
| 12268 | | ir_add_error_node(ira, source_node, buf_sprintf("only optionals (not '%s') can compare to null", |
| 12269 | | buf_ptr(&(op1->value.type->id == ZigTypeIdNull ? op2->value.type->name : op1->value.type->name)))); |
| 12332 | ZigType *non_null_type = (op1->value.type->id == ZigTypeIdNull) ? op2->value.type : op1->value.type; |
| 12333 | ir_add_error_node(ira, source_node, buf_sprintf("comparison of '%s' with null", |
| 12334 | buf_ptr(&non_null_type->name))); |
| 12270 | 12335 | return ira->codegen->invalid_instruction; |
| 12271 | 12336 | } |
| 12272 | 12337 | |