| ... | @@ -153,6 +153,8 @@ static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_ali | ... | @@ -153,6 +153,8 @@ static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_ali |
| 153 | static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align); | 153 | static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align); |
| 154 | static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val); | 154 | static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val); |
| 155 | static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val); | 155 | static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val); |
| | 156 | static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, |
| | 157 | ConstExprValue *out_val, ConstExprValue *ptr_val); |
| 156 | | 158 | |
| 157 | static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { | 159 | static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { |
| 158 | assert(get_src_ptr_type(const_val->type) != nullptr); | 160 | assert(get_src_ptr_type(const_val->type) != nullptr); |
| ... | @@ -11205,34 +11207,42 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Zig | ... | @@ -11205,34 +11207,42 @@ static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, Zig |
| 11205 | } | 11207 | } |
| 11206 | | 11208 | |
| 11207 | static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr) { | 11209 | static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr) { |
| | 11210 | Error err; |
| 11208 | ZigType *type_entry = ptr->value.type; | 11211 | ZigType *type_entry = ptr->value.type; |
| 11209 | if (type_is_invalid(type_entry)) { | 11212 | if (type_is_invalid(type_entry)) { |
| 11210 | return ira->codegen->invalid_instruction; | 11213 | return ira->codegen->invalid_instruction; |
| 11211 | } else if (type_entry->id == ZigTypeIdPointer) { | 11214 | } else if (type_entry->id == ZigTypeIdPointer) { |
| 11212 | ZigType *child_type = type_entry->data.pointer.child_type; | 11215 | ZigType *child_type = type_entry->data.pointer.child_type; |
| | 11216 | // dereferencing a *u0 is comptime known to be 0 |
| | 11217 | if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) { |
| | 11218 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope, |
| | 11219 | source_instruction->source_node, child_type); |
| | 11220 | init_const_unsigned_negative(&result->value, child_type, 0, false); |
| | 11221 | return result; |
| | 11222 | } |
| 11213 | if (instr_is_comptime(ptr)) { | 11223 | if (instr_is_comptime(ptr)) { |
| | 11224 | if (ptr->value.special == ConstValSpecialUndef) { |
| | 11225 | ir_add_error(ira, ptr, buf_sprintf("attempt to dereference undefined value")); |
| | 11226 | return ira->codegen->invalid_instruction; |
| | 11227 | } |
| 11214 | if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst || | 11228 | if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst || |
| 11215 | ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) | 11229 | ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) |
| 11216 | { | 11230 | { |
| 11217 | ConstExprValue *pointee = ir_const_ptr_pointee(ira, &ptr->value, source_instruction->source_node); | 11231 | ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value); |
| 11218 | if (pointee == nullptr) | | |
| 11219 | return ira->codegen->invalid_instruction; | | |
| 11220 | if (pointee->special != ConstValSpecialRuntime) { | 11232 | if (pointee->special != ConstValSpecialRuntime) { |
| 11221 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope, | 11233 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope, |
| 11222 | source_instruction->source_node, child_type); | 11234 | source_instruction->source_node, child_type); |
| 11223 | copy_const_val(&result->value, pointee, ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst); | 11235 | |
| | 11236 | if ((err = ir_read_const_ptr(ira, source_instruction->source_node, &result->value, |
| | 11237 | &ptr->value))) |
| | 11238 | { |
| | 11239 | return ira->codegen->invalid_instruction; |
| | 11240 | } |
| 11224 | result->value.type = child_type; | 11241 | result->value.type = child_type; |
| 11225 | return result; | 11242 | return result; |
| 11226 | } | 11243 | } |
| 11227 | } | 11244 | } |
| 11228 | } | 11245 | } |
| 11229 | // dereferencing a *u0 is comptime known to be 0 | | |
| 11230 | if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) { | | |
| 11231 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope, | | |
| 11232 | source_instruction->source_node, child_type); | | |
| 11233 | init_const_unsigned_negative(&result->value, child_type, 0, false); | | |
| 11234 | return result; | | |
| 11235 | } | | |
| 11236 | // TODO if the instruction is a const ref instruction we can skip it | 11246 | // TODO if the instruction is a const ref instruction we can skip it |
| 11237 | IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope, | 11247 | IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope, |
| 11238 | source_instruction->source_node, ptr); | 11248 | source_instruction->source_node, ptr); |
| ... | @@ -13931,10 +13941,16 @@ static ZigType *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCall *c | ... | @@ -13931,10 +13941,16 @@ static ZigType *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCall *c |
| 13931 | static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, | 13941 | static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, |
| 13932 | ConstExprValue *out_val, ConstExprValue *ptr_val) | 13942 | ConstExprValue *out_val, ConstExprValue *ptr_val) |
| 13933 | { | 13943 | { |
| | 13944 | Error err; |
| 13934 | assert(out_val->type != nullptr); | 13945 | assert(out_val->type != nullptr); |
| 13935 | | 13946 | |
| 13936 | ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, ptr_val); | 13947 | ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, ptr_val); |
| 13937 | | 13948 | |
| | 13949 | if ((err = type_resolve(ira->codegen, pointee->type, ResolveStatusSizeKnown))) |
| | 13950 | return ErrorSemanticAnalyzeFail; |
| | 13951 | if ((err = type_resolve(ira->codegen, out_val->type, ResolveStatusSizeKnown))) |
| | 13952 | return ErrorSemanticAnalyzeFail; |
| | 13953 | |
| 13938 | size_t src_size = type_size(ira->codegen, pointee->type); | 13954 | size_t src_size = type_size(ira->codegen, pointee->type); |
| 13939 | size_t dst_size = type_size(ira->codegen, out_val->type); | 13955 | size_t dst_size = type_size(ira->codegen, out_val->type); |
| 13940 | | 13956 | |
| ... | @@ -13957,48 +13973,6 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, | ... | @@ -13957,48 +13973,6 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, |
| 13957 | return ErrorNone; | 13973 | return ErrorNone; |
| 13958 | } | 13974 | } |
| 13959 | | 13975 | |
| 13960 | static ZigType *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { | | |
| 13961 | Error err; | | |
| 13962 | IrInstruction *value = un_op_instruction->value->other; | | |
| 13963 | | | |
| 13964 | ZigType *ptr_type = value->value.type; | | |
| 13965 | ZigType *child_type; | | |
| 13966 | if (type_is_invalid(ptr_type)) { | | |
| 13967 | return ira->codegen->builtin_types.entry_invalid; | | |
| 13968 | } else if (ptr_type->id == ZigTypeIdPointer) { | | |
| 13969 | if (ptr_type->data.pointer.ptr_len == PtrLenUnknown) { | | |
| 13970 | ir_add_error_node(ira, un_op_instruction->base.source_node, | | |
| 13971 | buf_sprintf("index syntax required for unknown-length pointer type '%s'", | | |
| 13972 | buf_ptr(&ptr_type->name))); | | |
| 13973 | return ira->codegen->builtin_types.entry_invalid; | | |
| 13974 | } | | |
| 13975 | child_type = ptr_type->data.pointer.child_type; | | |
| 13976 | } else { | | |
| 13977 | ir_add_error_node(ira, un_op_instruction->base.source_node, | | |
| 13978 | buf_sprintf("attempt to dereference non-pointer type '%s'", | | |
| 13979 | buf_ptr(&ptr_type->name))); | | |
| 13980 | return ira->codegen->builtin_types.entry_invalid; | | |
| 13981 | } | | |
| 13982 | | | |
| 13983 | // this dereference is always an rvalue because in the IR gen we identify lvalue and emit | | |
| 13984 | // one of the ptr instructions | | |
| 13985 | | | |
| 13986 | if (instr_is_comptime(value)) { | | |
| 13987 | ConstExprValue *comptime_value = ir_resolve_const(ira, value, UndefBad); | | |
| 13988 | if (comptime_value == nullptr) | | |
| 13989 | return ira->codegen->builtin_types.entry_invalid; | | |
| 13990 | | | |
| 13991 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base); | | |
| 13992 | out_val->type = child_type; | | |
| 13993 | if ((err = ir_read_const_ptr(ira, un_op_instruction->base.source_node, out_val, comptime_value))) | | |
| 13994 | return ira->codegen->builtin_types.entry_invalid; | | |
| 13995 | return child_type; | | |
| 13996 | } | | |
| 13997 | | | |
| 13998 | ir_build_load_ptr_from(&ira->new_irb, &un_op_instruction->base, value); | | |
| 13999 | return child_type; | | |
| 14000 | } | | |
| 14001 | | | |
| 14002 | static ZigType *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { | 13976 | static ZigType *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { |
| 14003 | Error err; | 13977 | Error err; |
| 14004 | IrInstruction *value = un_op_instruction->value->other; | 13978 | IrInstruction *value = un_op_instruction->value->other; |
| ... | @@ -14131,8 +14105,25 @@ static ZigType *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructionUnOp * | ... | @@ -14131,8 +14105,25 @@ static ZigType *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructionUnOp * |
| 14131 | case IrUnOpNegation: | 14105 | case IrUnOpNegation: |
| 14132 | case IrUnOpNegationWrap: | 14106 | case IrUnOpNegationWrap: |
| 14133 | return ir_analyze_negation(ira, un_op_instruction); | 14107 | return ir_analyze_negation(ira, un_op_instruction); |
| 14134 | case IrUnOpDereference: | 14108 | case IrUnOpDereference: { |
| 14135 | return ir_analyze_dereference(ira, un_op_instruction); | 14109 | IrInstruction *ptr = un_op_instruction->value->other; |
| | 14110 | if (type_is_invalid(ptr->value.type)) |
| | 14111 | return ira->codegen->builtin_types.entry_invalid; |
| | 14112 | ZigType *ptr_type = ptr->value.type; |
| | 14113 | if (ptr_type->id == ZigTypeIdPointer && ptr_type->data.pointer.ptr_len == PtrLenUnknown) { |
| | 14114 | ir_add_error_node(ira, un_op_instruction->base.source_node, |
| | 14115 | buf_sprintf("index syntax required for unknown-length pointer type '%s'", |
| | 14116 | buf_ptr(&ptr_type->name))); |
| | 14117 | return ira->codegen->builtin_types.entry_invalid; |
| | 14118 | } |
| | 14119 | // this dereference is always an rvalue because in the IR gen we identify lvalue and emit |
| | 14120 | // one of the ptr instructions |
| | 14121 | IrInstruction *result = ir_get_deref(ira, &un_op_instruction->base, ptr); |
| | 14122 | if (result == ira->codegen->invalid_instruction) |
| | 14123 | return ira->codegen->builtin_types.entry_invalid; |
| | 14124 | ir_link_new_instruction(result, &un_op_instruction->base); |
| | 14125 | return result->value.type; |
| | 14126 | } |
| 14136 | case IrUnOpOptional: | 14127 | case IrUnOpOptional: |
| 14137 | return ir_analyze_maybe(ira, un_op_instruction); | 14128 | return ir_analyze_maybe(ira, un_op_instruction); |
| 14138 | } | 14129 | } |