@@ -907,6 +907,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionErrorUnionFieldE
907
907
return IrInstructionIdErrorUnionFieldErrorSet;
908
908
}
909
909
910
+ static constexpr IrInstructionId ir_instruction_id(IrInstructionFirstArgResultLoc *) {
911
+ return IrInstructionIdFirstArgResultLoc;
912
+ }
913
+
910
914
template<typename T>
911
915
static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
912
916
T *special_instruction = allocate<T>(1);
@@ -2936,6 +2940,19 @@ static IrInstruction *ir_build_error_union_field_error_set(IrBuilder *irb, Scope
2936
2940
return &instruction->base;
2937
2941
}
2938
2942
2943
+ static IrInstruction *ir_build_first_arg_result_loc(IrBuilder *irb, Scope *scope, AstNode *source_node,
2944
+ IrInstruction *prev_result_loc, IrInstruction *fn_ref)
2945
+ {
2946
+ IrInstructionFirstArgResultLoc *instruction = ir_build_instruction<IrInstructionFirstArgResultLoc>(irb, scope, source_node);
2947
+ instruction->prev_result_loc = prev_result_loc;
2948
+ instruction->fn_ref = fn_ref;
2949
+
2950
+ ir_ref_instruction(prev_result_loc, irb->current_basic_block);
2951
+ ir_ref_instruction(fn_ref, irb->current_basic_block);
2952
+
2953
+ return &instruction->base;
2954
+ }
2955
+
2939
2956
static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
2940
2957
results[ReturnKindUnconditional] = 0;
2941
2958
results[ReturnKindError] = 0;
@@ -4969,16 +4986,31 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
4969
4986
if (fn_ref == irb->codegen->invalid_instruction)
4970
4987
return fn_ref;
4971
4988
4989
+ // In pass 1, we can't tell the difference between a function call with a single argument
4990
+ // and an implicit cast. So if there is only one argument, we emit a special instruction.
4972
4991
size_t arg_count = node->data.fn_call_expr.params.length;
4973
4992
IrInstruction **args = allocate<IrInstruction*>(arg_count);
4993
+ bool is_async = node->data.fn_call_expr.is_async;
4994
+ if (arg_count == 1 && !is_async) {
4995
+ AstNode *arg_node = node->data.fn_call_expr.params.at(0);
4996
+ IrInstruction *arg_result_loc = ir_build_first_arg_result_loc(irb, scope, arg_node, result_loc, fn_ref);
4997
+ args[0] = ir_gen_node(irb, arg_node, scope, LValNone, arg_result_loc);
4998
+ if (args[0] == irb->codegen->invalid_instruction)
4999
+ return irb->codegen->invalid_instruction;
5000
+ // In the analysis, this call instruction will be a simple LoadPtr instruction if
5001
+ // it turns out to be an implicit cast.
5002
+ IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false,
5003
+ FnInlineAuto, false, nullptr, nullptr, result_loc);
5004
+ return ir_lval_wrap(irb, scope, fn_call, lval);
5005
+ }
5006
+
4974
5007
for (size_t i = 0; i < arg_count; i += 1) {
4975
5008
AstNode *arg_node = node->data.fn_call_expr.params.at(i);
4976
5009
args[i] = ir_gen_node(irb, arg_node, scope, LValNone, nullptr);
4977
5010
if (args[i] == irb->codegen->invalid_instruction)
4978
5011
return args[i];
4979
5012
}
4980
5013
4981
- bool is_async = node->data.fn_call_expr.is_async;
4982
5014
IrInstruction *async_allocator = nullptr;
4983
5015
if (is_async) {
4984
5016
if (node->data.fn_call_expr.async_allocator) {
@@ -13989,6 +14021,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
13989
14021
}
13990
14022
13991
14023
static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCall *call_instruction) {
14024
+ Error err;
13992
14025
IrInstruction *fn_ref = call_instruction->fn_ref->child;
13993
14026
if (type_is_invalid(fn_ref->value.type))
13994
14027
return ira->codegen->invalid_instruction;
@@ -14010,12 +14043,18 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC
14010
14043
return ira->codegen->invalid_instruction;
14011
14044
}
14012
14045
14013
- IrInstruction *arg = call_instruction->args[0]->child;
14046
+ // This is handled with the result location mechanism. So all we need to do here is
14047
+ // a LoadPtr on the result location.
14048
+ IrInstruction *result_loc = call_instruction->result_loc->child;
14049
+ if (type_is_invalid(result_loc->value.type))
14050
+ return ira->codegen->invalid_instruction;
14051
+ if ((err = resolve_possible_alloca_inference(ira, result_loc, dest_type)))
14052
+ return ira->codegen->invalid_instruction;
14014
14053
14015
- IrInstruction *cast_instruction = ir_analyze_cast (ira, &call_instruction->base, dest_type, arg );
14016
- if (type_is_invalid(cast_instruction ->value.type))
14054
+ IrInstruction *deref = ir_get_deref (ira, &call_instruction->base, result_loc );
14055
+ if (type_is_invalid(deref ->value.type))
14017
14056
return ira->codegen->invalid_instruction;
14018
- return ir_finish_anal(ira, cast_instruction );
14057
+ return ir_finish_anal(ira, deref );
14019
14058
} else if (fn_ref->value.type->id == ZigTypeIdFn) {
14020
14059
ZigFn *fn_table_entry = ir_resolve_fn(ira, fn_ref);
14021
14060
if (fn_table_entry == nullptr)
@@ -21357,6 +21396,47 @@ static IrInstruction *ir_analyze_instruction_alloca(IrAnalyze *ira, IrInstructio
21357
21396
return &result->base;
21358
21397
}
21359
21398
21399
+ static IrInstruction *ir_analyze_instruction_first_arg_result_loc(IrAnalyze *ira,
21400
+ IrInstructionFirstArgResultLoc *instruction)
21401
+ {
21402
+ Error err;
21403
+
21404
+ IrInstruction *fn_ref = instruction->fn_ref->child;
21405
+ if (type_is_invalid(fn_ref->value.type))
21406
+ return ira->codegen->invalid_instruction;
21407
+
21408
+ if (fn_ref->value.type->id == ZigTypeIdMetaType) {
21409
+ // Result of this instruction should be the implicitly casted result location.
21410
+
21411
+ ZigType *dest_type = ir_resolve_type(ira, fn_ref);
21412
+ if (type_is_invalid(dest_type))
21413
+ return ira->codegen->invalid_instruction;
21414
+
21415
+ IrInstruction *new_result_loc = ir_implicit_cast_result(ira, instruction->prev_result_loc->child,
21416
+ dest_type);
21417
+ if (type_is_invalid(new_result_loc->value.type))
21418
+ return ira->codegen->invalid_instruction;
21419
+ return new_result_loc;
21420
+ }
21421
+
21422
+ // Result of this instruction should be the result location for the first argument of the function call.
21423
+ // This means it should be a stack allocation.
21424
+ IrInstructionAllocaGen *result = ir_create_alloca_gen(&ira->new_irb, instruction->base.scope,
21425
+ instruction->base.source_node, 0, "");
21426
+
21427
+ assert(fn_ref->value.type->id == ZigTypeIdFn);
21428
+ ZigType *param_type = fn_ref->value.type->data.fn.fn_type_id.param_info[0].type;
21429
+ if (type_is_invalid(param_type))
21430
+ return ira->codegen->invalid_instruction;
21431
+ if ((err = resolve_alloca_inference(ira, result, param_type)))
21432
+ return ira->codegen->invalid_instruction;
21433
+ ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
21434
+ if (fn_entry != nullptr) {
21435
+ fn_entry->alloca_list.append(result);
21436
+ }
21437
+ return &result->base;
21438
+ }
21439
+
21360
21440
static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
21361
21441
switch (instruction->id) {
21362
21442
case IrInstructionIdInvalid:
@@ -21650,6 +21730,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
21650
21730
return ir_analyze_instruction_alloca(ira, (IrInstructionAllocaSrc *)instruction);
21651
21731
case IrInstructionIdErrorUnionFieldErrorSet:
21652
21732
return ir_analyze_instruction_error_union_field_error_set(ira, (IrInstructionErrorUnionFieldErrorSet *)instruction);
21733
+ case IrInstructionIdFirstArgResultLoc:
21734
+ return ir_analyze_instruction_first_arg_result_loc(ira, (IrInstructionFirstArgResultLoc *)instruction);
21653
21735
case IrInstructionIdResultBytesToSlice:
21654
21736
zig_panic("TODO");
21655
21737
case IrInstructionIdResultSliceToBytes:
@@ -21887,6 +21969,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21887
21969
case IrInstructionIdAllocaSrc:
21888
21970
case IrInstructionIdAllocaGen:
21889
21971
case IrInstructionIdErrorUnionFieldErrorSet:
21972
+ case IrInstructionIdFirstArgResultLoc:
21890
21973
return false;
21891
21974
21892
21975
case IrInstructionIdLoadPtr:
0 commit comments