| ... | ... | @@ -153,6 +153,8 @@ static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_ali |
| 153 | 153 | static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align); |
| 154 | 154 | static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val); |
| 155 | 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 | 159 | static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { |
| 158 | 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 | 11207 | } |
| 11206 | 11208 | |
| 11207 | 11209 | static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr) { |
| 11210 | Error err; |
| 11208 | 11211 | ZigType *type_entry = ptr->value.type; |
| 11209 | 11212 | if (type_is_invalid(type_entry)) { |
| 11210 | 11213 | return ira->codegen->invalid_instruction; |
| 11211 | 11214 | } else if (type_entry->id == ZigTypeIdPointer) { |
| 11212 | 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 | 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 | 11228 | if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst || |
| 11215 | 11229 | ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) |
| 11216 | 11230 | { |
| 11217 | | ConstExprValue *pointee = ir_const_ptr_pointee(ira, &ptr->value, source_instruction->source_node); |
| 11218 | | if (pointee == nullptr) |
| 11219 | | return ira->codegen->invalid_instruction; |
| 11231 | ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value); |
| 11220 | 11232 | if (pointee->special != ConstValSpecialRuntime) { |
| 11221 | 11233 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope, |
| 11222 | 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 | 11241 | result->value.type = child_type; |
| 11225 | 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 | 11246 | // TODO if the instruction is a const ref instruction we can skip it |
| 11237 | 11247 | IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope, |
| 11238 | 11248 | source_instruction->source_node, ptr); |
| ... | ... | @@ -13931,10 +13941,16 @@ static ZigType *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCall *c |
| 13931 | 13941 | static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, |
| 13932 | 13942 | ConstExprValue *out_val, ConstExprValue *ptr_val) |
| 13933 | 13943 | { |
| 13944 | Error err; |
| 13934 | 13945 | assert(out_val->type != nullptr); |
| 13935 | 13946 | |
| 13936 | 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 | 13954 | size_t src_size = type_size(ira->codegen, pointee->type); |
| 13939 | 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 | 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 | 13976 | static ZigType *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { |
| 14003 | 13977 | Error err; |
| 14004 | 13978 | IrInstruction *value = un_op_instruction->value->other; |
| ... | ... | @@ -14131,8 +14105,25 @@ static ZigType *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructionUnOp * |
| 14131 | 14105 | case IrUnOpNegation: |
| 14132 | 14106 | case IrUnOpNegationWrap: |
| 14133 | 14107 | return ir_analyze_negation(ira, un_op_instruction); |
| 14134 | | case IrUnOpDereference: |
| 14135 | | return ir_analyze_dereference(ira, un_op_instruction); |
| 14108 | case IrUnOpDereference: { |
| 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 | 14127 | case IrUnOpOptional: |
| 14137 | 14128 | return ir_analyze_maybe(ira, un_op_instruction); |
| 14138 | 14129 | } |