| ... | ... | @@ -1377,18 +1377,22 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, AstNode *node) { |
| 1377 | 1377 | return ir_build_phi(irb, node, 2, incoming_blocks, incoming_values); |
| 1378 | 1378 | } |
| 1379 | 1379 | |
| 1380 | | static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, AstNode *node, IrUnOp op_id) { |
| 1380 | static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, AstNode *node, IrUnOp op_id, LValPurpose lval) { |
| 1381 | 1381 | assert(node->type == NodeTypePrefixOpExpr); |
| 1382 | 1382 | AstNode *expr_node = node->data.prefix_op_expr.primary_expr; |
| 1383 | 1383 | |
| 1384 | | IrInstruction *value = ir_gen_node(irb, expr_node, node->block_context); |
| 1384 | IrInstruction *value = ir_gen_node_extra(irb, expr_node, node->block_context, lval); |
| 1385 | 1385 | if (value == irb->codegen->invalid_instruction) |
| 1386 | 1386 | return value; |
| 1387 | 1387 | |
| 1388 | 1388 | return ir_build_un_op(irb, node, op_id, value); |
| 1389 | 1389 | } |
| 1390 | 1390 | |
| 1391 | | static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, AstNode *node) { |
| 1391 | static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, AstNode *node, IrUnOp op_id) { |
| 1392 | return ir_gen_prefix_op_id_lval(irb, node, op_id, LValPurposeNone); |
| 1393 | } |
| 1394 | |
| 1395 | static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, AstNode *node, LValPurpose lval) { |
| 1392 | 1396 | assert(node->type == NodeTypePrefixOpExpr); |
| 1393 | 1397 | |
| 1394 | 1398 | PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op; |
| ... | ... | @@ -1405,11 +1409,11 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, AstNode *node) { |
| 1405 | 1409 | case PrefixOpNegationWrap: |
| 1406 | 1410 | return ir_gen_prefix_op_id(irb, node, IrUnOpNegationWrap); |
| 1407 | 1411 | case PrefixOpAddressOf: |
| 1408 | | return ir_gen_prefix_op_id(irb, node, IrUnOpAddressOf); |
| 1412 | return ir_gen_prefix_op_id_lval(irb, node, IrUnOpAddressOf, LValPurposeAddressOf); |
| 1409 | 1413 | case PrefixOpConstAddressOf: |
| 1410 | | return ir_gen_prefix_op_id(irb, node, IrUnOpConstAddressOf); |
| 1414 | return ir_gen_prefix_op_id_lval(irb, node, IrUnOpConstAddressOf, LValPurposeConstAddressOf); |
| 1411 | 1415 | case PrefixOpDereference: |
| 1412 | | return ir_gen_prefix_op_id(irb, node, IrUnOpDereference); |
| 1416 | return ir_gen_prefix_op_id_lval(irb, node, IrUnOpDereference, lval); |
| 1413 | 1417 | case PrefixOpMaybe: |
| 1414 | 1418 | return ir_gen_prefix_op_id(irb, node, IrUnOpMaybe); |
| 1415 | 1419 | case PrefixOpError: |
| ... | ... | @@ -1789,7 +1793,7 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont |
| 1789 | 1793 | case NodeTypeIfBoolExpr: |
| 1790 | 1794 | return ir_gen_if_bool_expr(irb, node); |
| 1791 | 1795 | case NodeTypePrefixOpExpr: |
| 1792 | | return ir_gen_prefix_op_expr(irb, node); |
| 1796 | return ir_gen_prefix_op_expr(irb, node, lval); |
| 1793 | 1797 | case NodeTypeContainerInitExpr: |
| 1794 | 1798 | return ir_gen_container_init_expr(irb, node); |
| 1795 | 1799 | case NodeTypeVariableDeclaration: |
| ... | ... | @@ -3168,24 +3172,18 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct |
| 3168 | 3172 | zig_unreachable(); |
| 3169 | 3173 | } |
| 3170 | 3174 | |
| 3171 | | static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { |
| 3175 | static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction, |
| 3176 | bool is_const) |
| 3177 | { |
| 3172 | 3178 | IrInstruction *value = un_op_instruction->value->other; |
| 3173 | 3179 | if (value->type_entry->id == TypeTableEntryIdInvalid) |
| 3174 | 3180 | return ira->codegen->builtin_types.entry_invalid; |
| 3175 | 3181 | |
| 3176 | | bool is_const; |
| 3177 | | if (un_op_instruction->op_id == IrUnOpAddressOf) { |
| 3178 | | is_const = false; |
| 3179 | | } else if (un_op_instruction->op_id == IrUnOpConstAddressOf) { |
| 3180 | | is_const = true; |
| 3181 | | } else { |
| 3182 | | zig_unreachable(); |
| 3183 | | } |
| 3184 | | |
| 3185 | 3182 | TypeTableEntry *target_type = value->type_entry; |
| 3186 | 3183 | TypeTableEntry *canon_target_type = get_underlying_type(target_type); |
| 3187 | 3184 | switch (canon_target_type->id) { |
| 3188 | 3185 | case TypeTableEntryIdTypeDecl: |
| 3186 | // impossible because we look at the canonicalized type |
| 3189 | 3187 | zig_unreachable(); |
| 3190 | 3188 | case TypeTableEntryIdInvalid: |
| 3191 | 3189 | return ira->codegen->builtin_types.entry_invalid; |
| ... | ... | @@ -3197,6 +3195,7 @@ static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstruction |
| 3197 | 3195 | case TypeTableEntryIdBlock: |
| 3198 | 3196 | case TypeTableEntryIdUnreachable: |
| 3199 | 3197 | case TypeTableEntryIdVar: |
| 3198 | case TypeTableEntryIdGenericFn: |
| 3200 | 3199 | add_node_error(ira->codegen, un_op_instruction->base.source_node, |
| 3201 | 3200 | buf_sprintf("unable to get address of type '%s'", buf_ptr(&target_type->name))); |
| 3202 | 3201 | // TODO if type decl, add note pointing to type decl declaration |
| ... | ... | @@ -3210,11 +3209,17 @@ static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstruction |
| 3210 | 3209 | out_val->data.x_type = get_pointer_to_type(ira->codegen, child_type, is_const); |
| 3211 | 3210 | return ira->codegen->builtin_types.entry_type; |
| 3212 | 3211 | } |
| 3212 | case TypeTableEntryIdPointer: |
| 3213 | { |
| 3214 | // this instruction is a noop - we solved this in IR gen by passing |
| 3215 | // LValPurposeAddressOf which caused the loadptr to not do the load. |
| 3216 | ir_link_new_instruction(value, &un_op_instruction->base); |
| 3217 | return ir_finish_anal(ira, target_type); |
| 3218 | } |
| 3213 | 3219 | case TypeTableEntryIdVoid: |
| 3214 | 3220 | case TypeTableEntryIdBool: |
| 3215 | 3221 | case TypeTableEntryIdInt: |
| 3216 | 3222 | case TypeTableEntryIdFloat: |
| 3217 | | case TypeTableEntryIdPointer: |
| 3218 | 3223 | case TypeTableEntryIdArray: |
| 3219 | 3224 | case TypeTableEntryIdStruct: |
| 3220 | 3225 | case TypeTableEntryIdMaybe: |
| ... | ... | @@ -3223,15 +3228,40 @@ static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstruction |
| 3223 | 3228 | case TypeTableEntryIdEnum: |
| 3224 | 3229 | case TypeTableEntryIdUnion: |
| 3225 | 3230 | case TypeTableEntryIdFn: |
| 3226 | | case TypeTableEntryIdGenericFn: |
| 3227 | | { |
| 3228 | | zig_panic("TODO address of operation"); |
| 3229 | | break; |
| 3230 | | } |
| 3231 | zig_unreachable(); |
| 3231 | 3232 | } |
| 3232 | 3233 | zig_unreachable(); |
| 3233 | 3234 | } |
| 3234 | 3235 | |
| 3236 | static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { |
| 3237 | IrInstruction *value = un_op_instruction->value->other; |
| 3238 | |
| 3239 | TypeTableEntry *ptr_type = value->type_entry; |
| 3240 | TypeTableEntry *child_type; |
| 3241 | if (ptr_type->id == TypeTableEntryIdInvalid) { |
| 3242 | return ira->codegen->builtin_types.entry_invalid; |
| 3243 | } else if (ptr_type->id == TypeTableEntryIdPointer) { |
| 3244 | child_type = ptr_type->data.pointer.child_type; |
| 3245 | } else { |
| 3246 | add_node_error(ira->codegen, un_op_instruction->base.source_node, |
| 3247 | buf_sprintf("attempt to dereference non-pointer type '%s'", |
| 3248 | buf_ptr(&ptr_type->name))); |
| 3249 | return ira->codegen->builtin_types.entry_invalid; |
| 3250 | } |
| 3251 | |
| 3252 | // this dereference is always an rvalue because in the IR gen we identify lvalue and emit |
| 3253 | // one of the ptr instructions |
| 3254 | |
| 3255 | if (value->static_value.ok) { |
| 3256 | ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, false); |
| 3257 | *out_val = *value->static_value.data.x_ptr.ptr[0]; |
| 3258 | return child_type; |
| 3259 | } |
| 3260 | |
| 3261 | ir_build_un_op_from(&ira->new_irb, &un_op_instruction->base, IrUnOpDereference, value); |
| 3262 | return child_type; |
| 3263 | } |
| 3264 | |
| 3235 | 3265 | static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) { |
| 3236 | 3266 | IrUnOp op_id = un_op_instruction->op_id; |
| 3237 | 3267 | switch (op_id) { |
| ... | ... | @@ -3304,9 +3334,9 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio |
| 3304 | 3334 | //} |
| 3305 | 3335 | case IrUnOpAddressOf: |
| 3306 | 3336 | case IrUnOpConstAddressOf: |
| 3307 | | return ir_analyze_unary_address_of(ira, un_op_instruction); |
| 3337 | return ir_analyze_unary_address_of(ira, un_op_instruction, op_id == IrUnOpConstAddressOf); |
| 3308 | 3338 | case IrUnOpDereference: |
| 3309 | | zig_panic("TODO remove this IrUnOp item"); |
| 3339 | return ir_analyze_dereference(ira, un_op_instruction); |
| 3310 | 3340 | case IrUnOpMaybe: |
| 3311 | 3341 | zig_panic("TODO analyze PrefixOpMaybe"); |
| 3312 | 3342 | //{ |
| ... | ... | @@ -3502,7 +3532,6 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct |
| 3502 | 3532 | mem_slot->depends_on_compile_var); |
| 3503 | 3533 | |
| 3504 | 3534 | out_val->data.x_ptr.len = 1; |
| 3505 | | out_val->data.x_ptr.is_c_str = false; |
| 3506 | 3535 | out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1); |
| 3507 | 3536 | out_val->data.x_ptr.ptr[0] = mem_slot; |
| 3508 | 3537 | return ptr_type; |
| ... | ... | @@ -3565,7 +3594,6 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 3565 | 3594 | casted_elem_index->static_value.depends_on_compile_var; |
| 3566 | 3595 | ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base, depends_on_compile_var); |
| 3567 | 3596 | out_val->data.x_ptr.len = 1; |
| 3568 | | out_val->data.x_ptr.is_c_str = false; |
| 3569 | 3597 | out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1); |
| 3570 | 3598 | if (array_type->id == TypeTableEntryIdPointer) { |
| 3571 | 3599 | uint64_t pointer_len = array_ptr->static_value.data.x_ptr.len; |