| ... | @@ -2368,8 +2368,8 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, | ... | @@ -2368,8 +2368,8 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, |
| 2368 | auto primitive_table_entry = irb->codegen->primitive_type_table.maybe_get(variable_name); | 2368 | auto primitive_table_entry = irb->codegen->primitive_type_table.maybe_get(variable_name); |
| 2369 | if (primitive_table_entry) { | 2369 | if (primitive_table_entry) { |
| 2370 | IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_table_entry->value); | 2370 | IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_table_entry->value); |
| 2371 | if (lval == LValPurposeAddressOf) { | 2371 | if (lval != LValPurposeNone) { |
| 2372 | return ir_build_un_op(irb, scope, node, IrUnOpAddressOf, value); | 2372 | return ir_build_ref(irb, scope, node, value); |
| 2373 | } else { | 2373 | } else { |
| 2374 | return value; | 2374 | return value; |
| 2375 | } | 2375 | } |
| ... | @@ -2947,10 +2947,6 @@ static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, Ast | ... | @@ -2947,10 +2947,6 @@ static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, Ast |
| 2947 | if (value == irb->codegen->invalid_instruction) | 2947 | if (value == irb->codegen->invalid_instruction) |
| 2948 | return value; | 2948 | return value; |
| 2949 | | 2949 | |
| 2950 | if (lval == LValPurposeAddressOf && (op_id == IrUnOpAddressOf || op_id == IrUnOpConstAddressOf)) { | | |
| 2951 | return value; | | |
| 2952 | } | | |
| 2953 | | | |
| 2954 | return ir_build_un_op(irb, scope, node, op_id, value); | 2950 | return ir_build_un_op(irb, scope, node, op_id, value); |
| 2955 | } | 2951 | } |
| 2956 | | 2952 | |
| ... | @@ -2958,6 +2954,29 @@ static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode | ... | @@ -2958,6 +2954,29 @@ static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode |
| 2958 | return ir_gen_prefix_op_id_lval(irb, scope, node, op_id, LValPurposeNone); | 2954 | return ir_gen_prefix_op_id_lval(irb, scope, node, op_id, LValPurposeNone); |
| 2959 | } | 2955 | } |
| 2960 | | 2956 | |
| | 2957 | static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LValPurpose lval) { |
| | 2958 | if (lval == LValPurposeNone) |
| | 2959 | return value; |
| | 2960 | if (value == irb->codegen->invalid_instruction) |
| | 2961 | return value; |
| | 2962 | |
| | 2963 | // We needed a pointer to a value, but we got a value. So we create |
| | 2964 | // an instruction which just makes a const pointer of it. |
| | 2965 | return ir_build_ref(irb, scope, value->source_node, value); |
| | 2966 | } |
| | 2967 | |
| | 2968 | static IrInstruction *ir_gen_address_of(IrBuilder *irb, Scope *scope, AstNode *node, bool is_const, LValPurpose lval) { |
| | 2969 | assert(node->type == NodeTypePrefixOpExpr); |
| | 2970 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; |
| | 2971 | |
| | 2972 | IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, LValPurposeAddressOf); |
| | 2973 | if (value == irb->codegen->invalid_instruction) |
| | 2974 | return value; |
| | 2975 | |
| | 2976 | |
| | 2977 | return ir_lval_wrap(irb, scope, value, lval); |
| | 2978 | } |
| | 2979 | |
| 2961 | static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) { | 2980 | static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) { |
| 2962 | assert(node->type == NodeTypePrefixOpExpr); | 2981 | assert(node->type == NodeTypePrefixOpExpr); |
| 2963 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; | 2982 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; |
| ... | @@ -3002,17 +3021,6 @@ static IrInstruction *ir_gen_bool_not(IrBuilder *irb, Scope *scope, AstNode *nod | ... | @@ -3002,17 +3021,6 @@ static IrInstruction *ir_gen_bool_not(IrBuilder *irb, Scope *scope, AstNode *nod |
| 3002 | return ir_build_bool_not(irb, scope, node, value); | 3021 | return ir_build_bool_not(irb, scope, node, value); |
| 3003 | } | 3022 | } |
| 3004 | | 3023 | |
| 3005 | static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LValPurpose lval) { | | |
| 3006 | if (lval == LValPurposeNone) | | |
| 3007 | return value; | | |
| 3008 | if (value == irb->codegen->invalid_instruction) | | |
| 3009 | return value; | | |
| 3010 | | | |
| 3011 | // We needed a pointer to a value, but we got a value. So we create | | |
| 3012 | // an instruction which just makes a const pointer of it. | | |
| 3013 | return ir_build_ref(irb, scope, value->source_node, value); | | |
| 3014 | } | | |
| 3015 | | | |
| 3016 | static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) { | 3024 | static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) { |
| 3017 | assert(node->type == NodeTypePrefixOpExpr); | 3025 | assert(node->type == NodeTypePrefixOpExpr); |
| 3018 | | 3026 | |
| ... | @@ -3024,21 +3032,21 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod | ... | @@ -3024,21 +3032,21 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod |
| 3024 | case PrefixOpBoolNot: | 3032 | case PrefixOpBoolNot: |
| 3025 | return ir_lval_wrap(irb, scope, ir_gen_bool_not(irb, scope, node), lval); | 3033 | return ir_lval_wrap(irb, scope, ir_gen_bool_not(irb, scope, node), lval); |
| 3026 | case PrefixOpBinNot: | 3034 | case PrefixOpBinNot: |
| 3027 | return ir_gen_prefix_op_id(irb, scope, node, IrUnOpBinNot); | 3035 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpBinNot), lval); |
| 3028 | case PrefixOpNegation: | 3036 | case PrefixOpNegation: |
| 3029 | return ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation); | 3037 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation), lval); |
| 3030 | case PrefixOpNegationWrap: | 3038 | case PrefixOpNegationWrap: |
| 3031 | return ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap); | 3039 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval); |
| 3032 | case PrefixOpAddressOf: | 3040 | case PrefixOpAddressOf: |
| 3033 | return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpAddressOf, LValPurposeAddressOf); | 3041 | return ir_gen_address_of(irb, scope, node, false, lval); |
| 3034 | case PrefixOpConstAddressOf: | 3042 | case PrefixOpConstAddressOf: |
| 3035 | return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpConstAddressOf, LValPurposeAddressOf); | 3043 | return ir_gen_address_of(irb, scope, node, true, lval); |
| 3036 | case PrefixOpDereference: | 3044 | case PrefixOpDereference: |
| 3037 | return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval); | 3045 | return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval); |
| 3038 | case PrefixOpMaybe: | 3046 | case PrefixOpMaybe: |
| 3039 | return ir_gen_prefix_op_id(irb, scope, node, IrUnOpMaybe); | 3047 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpMaybe), lval); |
| 3040 | case PrefixOpError: | 3048 | case PrefixOpError: |
| 3041 | return ir_gen_prefix_op_id(irb, scope, node, IrUnOpError); | 3049 | return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpError), lval); |
| 3042 | case PrefixOpUnwrapError: | 3050 | case PrefixOpUnwrapError: |
| 3043 | return ir_gen_err_assert_ok(irb, scope, node, lval); | 3051 | return ir_gen_err_assert_ok(irb, scope, node, lval); |
| 3044 | case PrefixOpUnwrapMaybe: | 3052 | case PrefixOpUnwrapMaybe: |
| ... | @@ -4501,13 +4509,20 @@ static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instr | ... | @@ -4501,13 +4509,20 @@ static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instr |
| 4501 | ConstExprValue *pointee, TypeTableEntry *pointee_type, bool depends_on_compile_var, | 4509 | ConstExprValue *pointee, TypeTableEntry *pointee_type, bool depends_on_compile_var, |
| 4502 | ConstPtrSpecial special, bool ptr_is_const) | 4510 | ConstPtrSpecial special, bool ptr_is_const) |
| 4503 | { | 4511 | { |
| 4504 | TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, pointee_type, ptr_is_const); | 4512 | if (pointee_type->id == TypeTableEntryIdMetaType) { |
| 4505 | ConstExprValue *const_val = ir_build_const_from(ira, instruction, | 4513 | TypeTableEntry *type_entry = pointee->data.x_type; |
| 4506 | depends_on_compile_var || pointee->depends_on_compile_var); | 4514 | ConstExprValue *const_val = ir_build_const_from(ira, instruction, depends_on_compile_var || pointee->depends_on_compile_var); |
| 4507 | const_val->data.x_ptr.base_ptr = pointee; | 4515 | const_val->data.x_type = get_pointer_to_type(ira->codegen, type_entry, ptr_is_const); |
| 4508 | const_val->data.x_ptr.index = SIZE_MAX; | 4516 | return pointee_type; |
| 4509 | const_val->data.x_ptr.special = special; | 4517 | } else { |
| 4510 | return ptr_type; | 4518 | TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, pointee_type, ptr_is_const); |
| | 4519 | ConstExprValue *const_val = ir_build_const_from(ira, instruction, |
| | 4520 | depends_on_compile_var || pointee->depends_on_compile_var); |
| | 4521 | const_val->data.x_ptr.base_ptr = pointee; |
| | 4522 | const_val->data.x_ptr.index = SIZE_MAX; |
| | 4523 | const_val->data.x_ptr.special = special; |
| | 4524 | return ptr_type; |
| | 4525 | } |
| 4511 | } | 4526 | } |
| 4512 | | 4527 | |
| 4513 | static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *instruction, uint64_t value, | 4528 | static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *instruction, uint64_t value, |
| ... | @@ -5004,6 +5019,20 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc | ... | @@ -5004,6 +5019,20 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 5004 | IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope, source_instruction->source_node, ptr); | 5019 | IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope, source_instruction->source_node, ptr); |
| 5005 | load_ptr_instruction->type_entry = child_type; | 5020 | load_ptr_instruction->type_entry = child_type; |
| 5006 | return load_ptr_instruction; | 5021 | return load_ptr_instruction; |
| | 5022 | } else if (type_entry->id == TypeTableEntryIdMetaType) { |
| | 5023 | ConstExprValue *ptr_val = ir_resolve_const(ira, ptr); |
| | 5024 | if (!ptr_val) |
| | 5025 | return ira->codegen->invalid_instruction; |
| | 5026 | |
| | 5027 | TypeTableEntry *ptr_type = ptr_val->data.x_type; |
| | 5028 | if (ptr_type->id == TypeTableEntryIdPointer) { |
| | 5029 | TypeTableEntry *child_type = ptr_type->data.pointer.child_type; |
| | 5030 | return ir_create_const_type(&ira->new_irb, source_instruction->scope, source_instruction->source_node, child_type); |
| | 5031 | } else { |
| | 5032 | ir_add_error(ira, source_instruction, |
| | 5033 | buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr_type->name))); |
| | 5034 | return ira->codegen->invalid_instruction; |
| | 5035 | } |
| 5007 | } else { | 5036 | } else { |
| 5008 | add_node_error(ira->codegen, source_instruction->source_node, | 5037 | add_node_error(ira->codegen, source_instruction->source_node, |
| 5009 | buf_sprintf("attempt to dereference non pointer type '%s'", | 5038 | buf_sprintf("attempt to dereference non pointer type '%s'", |
| ... | @@ -5034,7 +5063,6 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -5034,7 +5063,6 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst |
| 5034 | return ptr_type; | 5063 | return ptr_type; |
| 5035 | } | 5064 | } |
| 5036 | | 5065 | |
| 5037 | | | |
| 5038 | static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out) { | 5066 | static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out) { |
| 5039 | if (value->type_entry->id == TypeTableEntryIdInvalid) | 5067 | if (value->type_entry->id == TypeTableEntryIdInvalid) |
| 5040 | return false; | 5068 | return false; |
| ... | @@ -6182,66 +6210,6 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct | ... | @@ -6182,66 +6210,6 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct |
| 6182 | zig_unreachable(); | 6210 | zig_unreachable(); |
| 6183 | } | 6211 | } |
| 6184 | | 6212 | |
| 6185 | static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction, | | |
| 6186 | bool is_const) | | |
| 6187 | { | | |
| 6188 | IrInstruction *value = un_op_instruction->value->other; | | |
| 6189 | if (value->type_entry->id == TypeTableEntryIdInvalid) | | |
| 6190 | return ira->codegen->builtin_types.entry_invalid; | | |
| 6191 | | | |
| 6192 | TypeTableEntry *target_type = value->type_entry; | | |
| 6193 | TypeTableEntry *canon_target_type = get_underlying_type(target_type); | | |
| 6194 | switch (canon_target_type->id) { | | |
| 6195 | case TypeTableEntryIdTypeDecl: | | |
| 6196 | // impossible because we look at the canonicalized type | | |
| 6197 | zig_unreachable(); | | |
| 6198 | case TypeTableEntryIdInvalid: | | |
| 6199 | return ira->codegen->builtin_types.entry_invalid; | | |
| 6200 | case TypeTableEntryIdNumLitFloat: | | |
| 6201 | case TypeTableEntryIdNumLitInt: | | |
| 6202 | case TypeTableEntryIdUndefLit: | | |
| 6203 | case TypeTableEntryIdNullLit: | | |
| 6204 | case TypeTableEntryIdNamespace: | | |
| 6205 | case TypeTableEntryIdBlock: | | |
| 6206 | case TypeTableEntryIdUnreachable: | | |
| 6207 | case TypeTableEntryIdVar: | | |
| 6208 | case TypeTableEntryIdBoundFn: | | |
| 6209 | add_node_error(ira->codegen, un_op_instruction->base.source_node, | | |
| 6210 | buf_sprintf("unable to get address of type '%s'", buf_ptr(&target_type->name))); | | |
| 6211 | // TODO if type decl, add note pointing to type decl declaration | | |
| 6212 | return ira->codegen->builtin_types.entry_invalid; | | |
| 6213 | case TypeTableEntryIdMetaType: | | |
| 6214 | { | | |
| 6215 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, | | |
| 6216 | value->static_value.depends_on_compile_var); | | |
| 6217 | assert(value->static_value.special != ConstValSpecialRuntime); | | |
| 6218 | TypeTableEntry *child_type = value->static_value.data.x_type; | | |
| 6219 | out_val->data.x_type = get_pointer_to_type(ira->codegen, child_type, is_const); | | |
| 6220 | return ira->codegen->builtin_types.entry_type; | | |
| 6221 | } | | |
| 6222 | case TypeTableEntryIdPointer: | | |
| 6223 | { | | |
| 6224 | // this instruction is a noop - we solved this in IR gen by passing | | |
| 6225 | // LValPurposeAddressOf which caused the loadptr to not do the load. | | |
| 6226 | ir_link_new_instruction(value, &un_op_instruction->base); | | |
| 6227 | return ir_finish_anal(ira, target_type); | | |
| 6228 | } | | |
| 6229 | case TypeTableEntryIdVoid: | | |
| 6230 | case TypeTableEntryIdBool: | | |
| 6231 | case TypeTableEntryIdInt: | | |
| 6232 | case TypeTableEntryIdFloat: | | |
| 6233 | case TypeTableEntryIdArray: | | |
| 6234 | case TypeTableEntryIdStruct: | | |
| 6235 | case TypeTableEntryIdMaybe: | | |
| 6236 | case TypeTableEntryIdErrorUnion: | | |
| 6237 | case TypeTableEntryIdPureError: | | |
| 6238 | case TypeTableEntryIdEnum: | | |
| 6239 | case TypeTableEntryIdUnion: | | |
| 6240 | case TypeTableEntryIdFn: | | |
| 6241 | zig_unreachable(); | | |
| 6242 | } | | |
| 6243 | zig_unreachable(); | | |
| 6244 | } | | |
| 6245 | | 6213 | |
| 6246 | static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { | 6214 | static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { |
| 6247 | IrInstruction *value = un_op_instruction->value->other; | 6215 | IrInstruction *value = un_op_instruction->value->other; |
| ... | @@ -6385,9 +6353,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio | ... | @@ -6385,9 +6353,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio |
| 6385 | case IrUnOpNegation: | 6353 | case IrUnOpNegation: |
| 6386 | case IrUnOpNegationWrap: | 6354 | case IrUnOpNegationWrap: |
| 6387 | return ir_analyze_negation(ira, un_op_instruction); | 6355 | return ir_analyze_negation(ira, un_op_instruction); |
| 6388 | case IrUnOpAddressOf: | | |
| 6389 | case IrUnOpConstAddressOf: | | |
| 6390 | return ir_analyze_unary_address_of(ira, un_op_instruction, op_id == IrUnOpConstAddressOf); | | |
| 6391 | case IrUnOpDereference: | 6356 | case IrUnOpDereference: |
| 6392 | return ir_analyze_dereference(ira, un_op_instruction); | 6357 | return ir_analyze_dereference(ira, un_op_instruction); |
| 6393 | case IrUnOpMaybe: | 6358 | case IrUnOpMaybe: |