authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-21 00:52:20-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-21 00:52:20-05:00
log236bbe1183575d7644f943b59096f2eb275ffa3a
treeef6d24009aefc23f7a4c305aba806cad83066ff0
parent65a51b401cfe17daee0c64404c8f564b0f282224

implement IR analysis for async function calls

See #727

8 files changed, 272 insertions(+), 54 deletions(-)

doc/langref.html.in+1-1
...@@ -5645,7 +5645,7 @@ UseDecl = "use" Expression ";"...@@ -5645,7 +5645,7 @@ UseDecl = "use" Expression ";"
56455645
5646ExternDecl = "extern" option(String) (FnProto | VariableDeclaration) ";"5646ExternDecl = "extern" option(String) (FnProto | VariableDeclaration) ";"
56475647
5648FnProto = option("nakedcc" | "stdcallcc" | "extern" | "async") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") TypeExpr5648FnProto = option("nakedcc" | "stdcallcc" | "extern" | ("async" option("(" Expression ")"))) "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") TypeExpr
56495649
5650FnDef = option("inline" | "export") FnProto Block5650FnDef = option("inline" | "export") FnProto Block
56515651
src/all_types.hpp+7
...@@ -428,6 +428,7 @@ struct AstNodeFnProto {...@@ -428,6 +428,7 @@ struct AstNodeFnProto {
428 AstNode *section_expr;428 AstNode *section_expr;
429429
430 bool auto_err_set;430 bool auto_err_set;
431 AstNode *async_allocator_type;
431};432};
432433
433struct AstNodeFnDef {434struct AstNodeFnDef {
...@@ -935,6 +936,7 @@ struct FnTypeId {...@@ -935,6 +936,7 @@ struct FnTypeId {
935 bool is_var_args;936 bool is_var_args;
936 CallingConvention cc;937 CallingConvention cc;
937 uint32_t alignment;938 uint32_t alignment;
939 TypeTableEntry *async_allocator_type;
938};940};
939941
940uint32_t fn_type_id_hash(FnTypeId*);942uint32_t fn_type_id_hash(FnTypeId*);
...@@ -1958,6 +1960,7 @@ enum IrInstructionId {...@@ -1958,6 +1960,7 @@ enum IrInstructionId {
1958 IrInstructionIdErrorReturnTrace,1960 IrInstructionIdErrorReturnTrace,
1959 IrInstructionIdErrorUnion,1961 IrInstructionIdErrorUnion,
1960 IrInstructionIdCancel,1962 IrInstructionIdCancel,
1963 IrInstructionIdGetImplicitAllocator,
1961};1964};
19621965
1963struct IrInstruction {1966struct IrInstruction {
...@@ -2803,6 +2806,10 @@ struct IrInstructionCancel {...@@ -2803,6 +2806,10 @@ struct IrInstructionCancel {
2803 IrInstruction *target;2806 IrInstruction *target;
2804};2807};
28052808
2809struct IrInstructionGetImplicitAllocator {
2810 IrInstruction base;
2811};
2812
2806static const size_t slice_ptr_index = 0;2813static const size_t slice_ptr_index = 0;
2807static const size_t slice_len_index = 1;2814static const size_t slice_len_index = 1;
28082815
src/analyze.cpp+31-5
...@@ -954,8 +954,13 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {...@@ -954,8 +954,13 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
954954
955 // populate the name of the type955 // populate the name of the type
956 buf_resize(&fn_type->name, 0);956 buf_resize(&fn_type->name, 0);
957 const char *cc_str = calling_convention_fn_type_str(fn_type->data.fn.fn_type_id.cc);957 if (fn_type->data.fn.fn_type_id.cc == CallingConventionAsync) {
958 buf_appendf(&fn_type->name, "%sfn(", cc_str);958 buf_appendf(&fn_type->name, "async(%s) ", buf_ptr(&fn_type_id->async_allocator_type->name));
959 } else {
960 const char *cc_str = calling_convention_fn_type_str(fn_type->data.fn.fn_type_id.cc);
961 buf_appendf(&fn_type->name, "%s", cc_str);
962 }
963 buf_appendf(&fn_type->name, "fn(");
959 for (size_t i = 0; i < fn_type_id->param_count; i += 1) {964 for (size_t i = 0; i < fn_type_id->param_count; i += 1) {
960 FnTypeParamInfo *param_info = &fn_type_id->param_info[i];965 FnTypeParamInfo *param_info = &fn_type_id->param_info[i];
961966
...@@ -1126,7 +1131,16 @@ TypeTableEntry *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {...@@ -1126,7 +1131,16 @@ TypeTableEntry *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
1126TypeTableEntry *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {1131TypeTableEntry *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
1127 TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn);1132 TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn);
1128 fn_type->is_copyable = false;1133 fn_type->is_copyable = false;
1129 buf_init_from_str(&fn_type->name, "fn(");1134 buf_resize(&fn_type->name, 0);
1135 if (fn_type->data.fn.fn_type_id.cc == CallingConventionAsync) {
1136 const char *async_allocator_type_str = (fn_type->data.fn.fn_type_id.async_allocator_type == nullptr) ?
1137 "var" : buf_ptr(&fn_type_id->async_allocator_type->name);
1138 buf_appendf(&fn_type->name, "async(%s) ", async_allocator_type_str);
1139 } else {
1140 const char *cc_str = calling_convention_fn_type_str(fn_type->data.fn.fn_type_id.cc);
1141 buf_appendf(&fn_type->name, "%s", cc_str);
1142 }
1143 buf_appendf(&fn_type->name, "fn(");
1130 size_t i = 0;1144 size_t i = 0;
1131 for (; i < fn_type_id->next_param_index; i += 1) {1145 for (; i < fn_type_id->next_param_index; i += 1) {
1132 const char *comma_str = (i == 0) ? "" : ",";1146 const char *comma_str = (i == 0) ? "" : ",";
...@@ -1515,6 +1529,16 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c...@@ -1515,6 +1529,16 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
1515 break;1529 break;
1516 }1530 }
15171531
1532 if (fn_type_id.cc == CallingConventionAsync) {
1533 if (fn_proto->async_allocator_type == nullptr) {
1534 return get_generic_fn_type(g, &fn_type_id);
1535 }
1536 fn_type_id.async_allocator_type = analyze_type_expr(g, child_scope, fn_proto->async_allocator_type);
1537 if (type_is_invalid(fn_type_id.async_allocator_type)) {
1538 return g->builtin_types.entry_invalid;
1539 }
1540 }
1541
1518 return get_fn_type(g, &fn_type_id);1542 return get_fn_type(g, &fn_type_id);
1519}1543}
15201544
...@@ -3676,7 +3700,7 @@ AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index) {...@@ -3676,7 +3700,7 @@ AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index) {
3676 return nullptr;3700 return nullptr;
3677}3701}
36783702
3679void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, VariableTableEntry **arg_vars) {3703static void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, VariableTableEntry **arg_vars) {
3680 TypeTableEntry *fn_type = fn_table_entry->type_entry;3704 TypeTableEntry *fn_type = fn_table_entry->type_entry;
3681 assert(!fn_type->data.fn.is_generic);3705 assert(!fn_type->data.fn.is_generic);
3682 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;3706 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
...@@ -4242,6 +4266,7 @@ uint32_t fn_type_id_hash(FnTypeId *id) {...@@ -4242,6 +4266,7 @@ uint32_t fn_type_id_hash(FnTypeId *id) {
4242 result += ((uint32_t)(id->cc)) * (uint32_t)3349388391;4266 result += ((uint32_t)(id->cc)) * (uint32_t)3349388391;
4243 result += id->is_var_args ? (uint32_t)1931444534 : 0;4267 result += id->is_var_args ? (uint32_t)1931444534 : 0;
4244 result += hash_ptr(id->return_type);4268 result += hash_ptr(id->return_type);
4269 result += hash_ptr(id->async_allocator_type);
4245 result += id->alignment * 0xd3b3f3e2;4270 result += id->alignment * 0xd3b3f3e2;
4246 for (size_t i = 0; i < id->param_count; i += 1) {4271 for (size_t i = 0; i < id->param_count; i += 1) {
4247 FnTypeParamInfo *info = &id->param_info[i];4272 FnTypeParamInfo *info = &id->param_info[i];
...@@ -4256,7 +4281,8 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {...@@ -4256,7 +4281,8 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {
4256 a->return_type != b->return_type ||4281 a->return_type != b->return_type ||
4257 a->is_var_args != b->is_var_args ||4282 a->is_var_args != b->is_var_args ||
4258 a->param_count != b->param_count ||4283 a->param_count != b->param_count ||
4259 a->alignment != b->alignment)4284 a->alignment != b->alignment ||
4285 a->async_allocator_type != b->async_allocator_type)
4260 {4286 {
4261 return false;4287 return false;
4262 }4288 }
src/analyze.hpp-1
...@@ -93,7 +93,6 @@ void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *...@@ -93,7 +93,6 @@ void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *
93void eval_min_max_value_int(CodeGen *g, TypeTableEntry *int_type, BigInt *bigint, bool is_max);93void eval_min_max_value_int(CodeGen *g, TypeTableEntry *int_type, BigInt *bigint, bool is_max);
9494
95void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val);95void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val);
96void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, VariableTableEntry **arg_vars);
97void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_type_node);96void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_type_node);
9897
99ScopeBlock *create_block_scope(AstNode *node, Scope *parent);98ScopeBlock *create_block_scope(AstNode *node, Scope *parent);
src/codegen.cpp+11
...@@ -2521,6 +2521,10 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -2521,6 +2521,10 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
2521 }2521 }
25222522
2523 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;2523 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
2524 if (fn_type_id->cc == CallingConventionAsync) {
2525 zig_panic("TODO codegen async function call");
2526 }
2527
2524 TypeTableEntry *src_return_type = fn_type_id->return_type;2528 TypeTableEntry *src_return_type = fn_type_id->return_type;
2525 bool ret_has_bits = type_has_bits(src_return_type);2529 bool ret_has_bits = type_has_bits(src_return_type);
2526 bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type);2530 bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type);
...@@ -3094,6 +3098,10 @@ static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrIns...@@ -3094,6 +3098,10 @@ static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrIns
3094 zig_panic("TODO ir_render_cancel");3098 zig_panic("TODO ir_render_cancel");
3095}3099}
30963100
3101static LLVMValueRef ir_render_get_implicit_allocator(CodeGen *g, IrExecutable *executable, IrInstructionGetImplicitAllocator *instruction) {
3102 zig_panic("TODO ir_render_get_implicit_allocator");
3103}
3104
3097static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) {3105static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) {
3098 switch (atomic_order) {3106 switch (atomic_order) {
3099 case AtomicOrderUnordered: return LLVMAtomicOrderingUnordered;3107 case AtomicOrderUnordered: return LLVMAtomicOrderingUnordered;
...@@ -3752,6 +3760,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -3752,6 +3760,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
3752 case IrInstructionIdExport:3760 case IrInstructionIdExport:
3753 case IrInstructionIdErrorUnion:3761 case IrInstructionIdErrorUnion:
3754 zig_unreachable();3762 zig_unreachable();
3763
3755 case IrInstructionIdReturn:3764 case IrInstructionIdReturn:
3756 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);3765 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
3757 case IrInstructionIdDeclVar:3766 case IrInstructionIdDeclVar:
...@@ -3870,6 +3879,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -3870,6 +3879,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
3870 return ir_render_error_return_trace(g, executable, (IrInstructionErrorReturnTrace *)instruction);3879 return ir_render_error_return_trace(g, executable, (IrInstructionErrorReturnTrace *)instruction);
3871 case IrInstructionIdCancel:3880 case IrInstructionIdCancel:
3872 return ir_render_cancel(g, executable, (IrInstructionCancel *)instruction);3881 return ir_render_cancel(g, executable, (IrInstructionCancel *)instruction);
3882 case IrInstructionIdGetImplicitAllocator:
3883 return ir_render_get_implicit_allocator(g, executable, (IrInstructionGetImplicitAllocator *)instruction);
3873 }3884 }
3874 zig_unreachable();3885 zig_unreachable();
3875}3886}
src/ir.cpp+197-46
...@@ -65,6 +65,7 @@ enum ConstCastResultId {...@@ -65,6 +65,7 @@ enum ConstCastResultId {
65 ConstCastResultIdFnArgNoAlias,65 ConstCastResultIdFnArgNoAlias,
66 ConstCastResultIdType,66 ConstCastResultIdType,
67 ConstCastResultIdUnresolvedInferredErrSet,67 ConstCastResultIdUnresolvedInferredErrSet,
68 ConstCastResultIdAsyncAllocatorType,
68};69};
6970
70struct ConstCastErrSetMismatch {71struct ConstCastErrSetMismatch {
...@@ -92,6 +93,7 @@ struct ConstCastOnly {...@@ -92,6 +93,7 @@ struct ConstCastOnly {
92 ConstCastOnly *error_union_payload;93 ConstCastOnly *error_union_payload;
93 ConstCastOnly *error_union_error_set;94 ConstCastOnly *error_union_error_set;
94 ConstCastOnly *return_type;95 ConstCastOnly *return_type;
96 ConstCastOnly *async_allocator_type;
95 ConstCastArg fn_arg;97 ConstCastArg fn_arg;
96 ConstCastArgNoAlias arg_no_alias;98 ConstCastArgNoAlias arg_no_alias;
97 } data;99 } data;
...@@ -104,6 +106,8 @@ static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *ins...@@ -104,6 +106,8 @@ static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *ins
104static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type);106static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type);
105static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr);107static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr);
106static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg);108static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg);
109static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
110 IrInstruction *source_instr, IrInstruction *container_ptr, TypeTableEntry *container_type);
107111
108ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {112ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {
109 assert(const_val->type->id == TypeTableEntryIdPointer);113 assert(const_val->type->id == TypeTableEntryIdPointer);
...@@ -641,6 +645,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCancel *) {...@@ -641,6 +645,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCancel *) {
641 return IrInstructionIdCancel;645 return IrInstructionIdCancel;
642}646}
643647
648static constexpr IrInstructionId ir_instruction_id(IrInstructionGetImplicitAllocator *) {
649 return IrInstructionIdGetImplicitAllocator;
650}
651
644template<typename T>652template<typename T>
645static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {653static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
646 T *special_instruction = allocate<T>(1);654 T *special_instruction = allocate<T>(1);
...@@ -954,15 +962,6 @@ static IrInstruction *ir_build_struct_field_ptr(IrBuilder *irb, Scope *scope, As...@@ -954,15 +962,6 @@ static IrInstruction *ir_build_struct_field_ptr(IrBuilder *irb, Scope *scope, As
954 return &instruction->base;962 return &instruction->base;
955}963}
956964
957static IrInstruction *ir_build_struct_field_ptr_from(IrBuilder *irb, IrInstruction *old_instruction,
958 IrInstruction *struct_ptr, TypeStructField *type_struct_field)
959{
960 IrInstruction *new_instruction = ir_build_struct_field_ptr(irb, old_instruction->scope,
961 old_instruction->source_node, struct_ptr, type_struct_field);
962 ir_link_new_instruction(new_instruction, old_instruction);
963 return new_instruction;
964}
965
966static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,965static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
967 IrInstruction *union_ptr, TypeUnionField *field)966 IrInstruction *union_ptr, TypeUnionField *field)
968{967{
...@@ -2415,6 +2414,12 @@ static IrInstruction *ir_build_cancel(IrBuilder *irb, Scope *scope, AstNode *sou...@@ -2415,6 +2414,12 @@ static IrInstruction *ir_build_cancel(IrBuilder *irb, Scope *scope, AstNode *sou
2415 return &instruction->base;2414 return &instruction->base;
2416}2415}
24172416
2417static IrInstruction *ir_build_get_implicit_allocator(IrBuilder *irb, Scope *scope, AstNode *source_node) {
2418 IrInstructionGetImplicitAllocator *instruction = ir_build_instruction<IrInstructionGetImplicitAllocator>(irb, scope, source_node);
2419
2420 return &instruction->base;
2421}
2422
2418static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {2423static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
2419 results[ReturnKindUnconditional] = 0;2424 results[ReturnKindUnconditional] = 0;
2420 results[ReturnKindError] = 0;2425 results[ReturnKindError] = 0;
...@@ -6740,6 +6745,12 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry...@@ -6740,6 +6745,12 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
6740 return result;6745 return result;
6741 }6746 }
67426747
6748 if (expected_type == ira->codegen->builtin_types.entry_promise &&
6749 actual_type->id == TypeTableEntryIdPromise)
6750 {
6751 return result;
6752 }
6753
6743 // fn6754 // fn
6744 if (expected_type->id == TypeTableEntryIdFn &&6755 if (expected_type->id == TypeTableEntryIdFn &&
6745 actual_type->id == TypeTableEntryIdFn)6756 actual_type->id == TypeTableEntryIdFn)
...@@ -6771,6 +6782,16 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry...@@ -6771,6 +6782,16 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
6771 return result;6782 return result;
6772 }6783 }
6773 }6784 }
6785 if (!expected_type->data.fn.is_generic && expected_type->data.fn.fn_type_id.cc == CallingConventionAsync) {
6786 ConstCastOnly child = types_match_const_cast_only(ira, actual_type->data.fn.fn_type_id.async_allocator_type,
6787 expected_type->data.fn.fn_type_id.async_allocator_type, source_node);
6788 if (child.id != ConstCastResultIdOk) {
6789 result.id = ConstCastResultIdAsyncAllocatorType;
6790 result.data.async_allocator_type = allocate_nonzero<ConstCastOnly>(1);
6791 *result.data.async_allocator_type = child;
6792 return result;
6793 }
6794 }
6774 if (expected_type->data.fn.fn_type_id.param_count != actual_type->data.fn.fn_type_id.param_count) {6795 if (expected_type->data.fn.fn_type_id.param_count != actual_type->data.fn.fn_type_id.param_count) {
6775 result.id = ConstCastResultIdFnArgCount;6796 result.id = ConstCastResultIdFnArgCount;
6776 return result;6797 return result;
...@@ -10768,6 +10789,58 @@ static TypeTableEntry *ir_analyze_instruction_error_union(IrAnalyze *ira,...@@ -10768,6 +10789,58 @@ static TypeTableEntry *ir_analyze_instruction_error_union(IrAnalyze *ira,
10768 return ira->codegen->builtin_types.entry_type;10789 return ira->codegen->builtin_types.entry_type;
10769}10790}
1077010791
10792IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_instr, FnTableEntry *parent_fn_entry) {
10793 FnTypeId *parent_fn_type = &parent_fn_entry->type_entry->data.fn.fn_type_id;
10794 if (parent_fn_type->cc != CallingConventionAsync) {
10795 ir_add_error(ira, source_instr, buf_sprintf("async function call from non-async caller requires allocator parameter"));
10796 return ira->codegen->invalid_instruction;
10797 }
10798
10799 assert(parent_fn_type->async_allocator_type != nullptr);
10800 IrInstruction *result = ir_build_get_implicit_allocator(&ira->new_irb, source_instr->scope, source_instr->source_node);
10801 result->value.type = parent_fn_type->async_allocator_type;
10802 return result;
10803}
10804
10805static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *call_instruction, FnTableEntry *fn_entry, TypeTableEntry *fn_type,
10806 IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count, IrInstruction *async_allocator_inst)
10807{
10808 Buf *alloc_field_name = buf_create_from_str("allocFn");
10809 //Buf *free_field_name = buf_create_from_str("freeFn");
10810 assert(async_allocator_inst->value.type->id == TypeTableEntryIdPointer);
10811 TypeTableEntry *container_type = async_allocator_inst->value.type->data.pointer.child_type;
10812 IrInstruction *field_ptr_inst = ir_analyze_container_field_ptr(ira, alloc_field_name, &call_instruction->base,
10813 async_allocator_inst, container_type);
10814 if (type_is_invalid(field_ptr_inst->value.type)) {
10815 return ira->codegen->invalid_instruction;
10816 }
10817 TypeTableEntry *ptr_to_alloc_fn_type = field_ptr_inst->value.type;
10818 assert(ptr_to_alloc_fn_type->id == TypeTableEntryIdPointer);
10819
10820 TypeTableEntry *alloc_fn_type = ptr_to_alloc_fn_type->data.pointer.child_type;
10821 if (alloc_fn_type->id != TypeTableEntryIdFn) {
10822 ir_add_error(ira, &call_instruction->base,
10823 buf_sprintf("expected allocation function, found '%s'", buf_ptr(&alloc_fn_type->name)));
10824 return ira->codegen->invalid_instruction;
10825 }
10826
10827 TypeTableEntry *alloc_fn_return_type = alloc_fn_type->data.fn.fn_type_id.return_type;
10828 if (alloc_fn_return_type->id != TypeTableEntryIdErrorUnion) {
10829 ir_add_error(ira, fn_ref,
10830 buf_sprintf("expected allocation function to return error union, but it returns '%s'", buf_ptr(&alloc_fn_return_type->name)));
10831 return ira->codegen->invalid_instruction;
10832 }
10833 TypeTableEntry *alloc_fn_error_set_type = alloc_fn_return_type->data.error_union.err_set_type;
10834 TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;
10835 TypeTableEntry *promise_type = get_promise_type(ira->codegen, return_type);
10836 TypeTableEntry *async_return_type = get_error_union_type(ira->codegen, alloc_fn_error_set_type, promise_type);
10837
10838 IrInstruction *result = ir_build_call(&ira->new_irb, call_instruction->base.scope, call_instruction->base.source_node,
10839 fn_entry, fn_ref, arg_count, casted_args, false, FnInlineAuto, true, async_allocator_inst);
10840 result->value.type = async_return_type;
10841 return result;
10842}
10843
10771static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node,10844static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node,
10772 IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i)10845 IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i)
10773{10846{
...@@ -10989,6 +11062,13 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal...@@ -10989,6 +11062,13 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
10989 }11062 }
10990 return ira->codegen->builtin_types.entry_invalid;11063 return ira->codegen->builtin_types.entry_invalid;
10991 }11064 }
11065 if (fn_type_id->cc != CallingConventionAsync && call_instruction->is_async) {
11066 ErrorMsg *msg = ir_add_error(ira, fn_ref, buf_sprintf("cannot use async keyword to call non-async function"));
11067 if (fn_proto_node) {
11068 add_error_note(ira->codegen, msg, fn_proto_node, buf_sprintf("declared here"));
11069 }
11070 return ira->codegen->builtin_types.entry_invalid;
11071 }
1099211072
1099311073
10994 if (fn_type_id->is_var_args) {11074 if (fn_type_id->is_var_args) {
...@@ -11115,6 +11195,11 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal...@@ -11115,6 +11195,11 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
11115 buf_sprintf("calling a generic function requires compile-time known function value"));11195 buf_sprintf("calling a generic function requires compile-time known function value"));
11116 return ira->codegen->builtin_types.entry_invalid;11196 return ira->codegen->builtin_types.entry_invalid;
11117 }11197 }
11198 if (call_instruction->is_async && fn_type_id->is_var_args) {
11199 ir_add_error(ira, call_instruction->fn_ref,
11200 buf_sprintf("compiler bug: TODO: implement var args async functions. https://github.com/zig-lang/zig/issues/557"));
11201 return ira->codegen->builtin_types.entry_invalid;
11202 }
1111811203
11119 // Count the arguments of the function type id we are creating11204 // Count the arguments of the function type id we are creating
11120 size_t new_fn_arg_count = first_arg_1_or_0;11205 size_t new_fn_arg_count = first_arg_1_or_0;
...@@ -11263,6 +11348,35 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal...@@ -11263,6 +11348,35 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
11263 return ir_analyze_fn_call(ira, call_instruction, fn_entry, fn_type, fn_ref, first_arg_ptr, true, FnInlineAuto);11348 return ir_analyze_fn_call(ira, call_instruction, fn_entry, fn_type, fn_ref, first_arg_ptr, true, FnInlineAuto);
11264 }11349 }
11265 }11350 }
11351 IrInstruction *async_allocator_inst = nullptr;
11352 if (call_instruction->is_async) {
11353 AstNode *async_allocator_type_node = fn_proto_node->data.fn_proto.async_allocator_type;
11354 if (async_allocator_type_node != nullptr) {
11355 TypeTableEntry *async_allocator_type = analyze_type_expr(ira->codegen, impl_fn->child_scope, async_allocator_type_node);
11356 if (type_is_invalid(async_allocator_type))
11357 return ira->codegen->builtin_types.entry_invalid;
11358 inst_fn_type_id.async_allocator_type = async_allocator_type;
11359 }
11360 IrInstruction *uncasted_async_allocator_inst;
11361 if (call_instruction->async_allocator == nullptr) {
11362 uncasted_async_allocator_inst = ir_get_implicit_allocator(ira, &call_instruction->base, parent_fn_entry);
11363 if (type_is_invalid(uncasted_async_allocator_inst->value.type))
11364 return ira->codegen->builtin_types.entry_invalid;
11365 } else {
11366 uncasted_async_allocator_inst = call_instruction->async_allocator->other;
11367 if (type_is_invalid(uncasted_async_allocator_inst->value.type))
11368 return ira->codegen->builtin_types.entry_invalid;
11369 }
11370 if (inst_fn_type_id.async_allocator_type == nullptr) {
11371 IrInstruction *casted_inst = ir_implicit_byval_const_ref_cast(ira, uncasted_async_allocator_inst);
11372 if (type_is_invalid(casted_inst->value.type))
11373 return ira->codegen->builtin_types.entry_invalid;
11374 inst_fn_type_id.async_allocator_type = casted_inst->value.type;
11375 }
11376 async_allocator_inst = ir_implicit_cast(ira, uncasted_async_allocator_inst, inst_fn_type_id.async_allocator_type);
11377 if (type_is_invalid(async_allocator_inst->value.type))
11378 return ira->codegen->builtin_types.entry_invalid;
11379 }
1126611380
11267 auto existing_entry = ira->codegen->generic_table.put_unique(generic_id, impl_fn);11381 auto existing_entry = ira->codegen->generic_table.put_unique(generic_id, impl_fn);
11268 if (existing_entry) {11382 if (existing_entry) {
...@@ -11282,17 +11396,24 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal...@@ -11282,17 +11396,24 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
11282 ira->codegen->fn_defs.append(impl_fn);11396 ira->codegen->fn_defs.append(impl_fn);
11283 }11397 }
1128411398
11285 size_t impl_param_count = impl_fn->type_entry->data.fn.fn_type_id.param_count;
11286 IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base,
11287 impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline, false, nullptr);
11288
11289 TypeTableEntry *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type;11399 TypeTableEntry *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type;
11290 ir_add_alloca(ira, new_call_instruction, return_type);
11291
11292 if (return_type->id == TypeTableEntryIdErrorSet || return_type->id == TypeTableEntryIdErrorUnion) {11400 if (return_type->id == TypeTableEntryIdErrorSet || return_type->id == TypeTableEntryIdErrorUnion) {
11293 parent_fn_entry->calls_errorable_function = true;11401 parent_fn_entry->calls_errorable_function = true;
11294 }11402 }
1129511403
11404 size_t impl_param_count = impl_fn->type_entry->data.fn.fn_type_id.param_count;
11405 if (call_instruction->is_async) {
11406 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry, fn_ref, casted_args, impl_param_count, async_allocator_inst);
11407 ir_link_new_instruction(result, &call_instruction->base);
11408 return ir_finish_anal(ira, result->value.type);
11409 }
11410
11411 IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base,
11412 impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline,
11413 call_instruction->is_async, async_allocator_inst);
11414
11415 ir_add_alloca(ira, new_call_instruction, return_type);
11416
11296 return ir_finish_anal(ira, return_type);11417 return ir_finish_anal(ira, return_type);
11297 }11418 }
1129811419
...@@ -11350,14 +11471,31 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal...@@ -11350,14 +11471,31 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1135011471
11351 assert(next_arg_index == call_param_count);11472 assert(next_arg_index == call_param_count);
1135211473
11353 if (call_instruction->is_async) {
11354 zig_panic("TODO handle async fn call");
11355 }
11356
11357 TypeTableEntry *return_type = fn_type_id->return_type;11474 TypeTableEntry *return_type = fn_type_id->return_type;
11358 if (type_is_invalid(return_type))11475 if (type_is_invalid(return_type))
11359 return ira->codegen->builtin_types.entry_invalid;11476 return ira->codegen->builtin_types.entry_invalid;
1136011477
11478 if (call_instruction->is_async) {
11479 IrInstruction *uncasted_async_allocator_inst;
11480 if (call_instruction->async_allocator == nullptr) {
11481 uncasted_async_allocator_inst = ir_get_implicit_allocator(ira, &call_instruction->base, parent_fn_entry);
11482 if (type_is_invalid(uncasted_async_allocator_inst->value.type))
11483 return ira->codegen->builtin_types.entry_invalid;
11484 } else {
11485 uncasted_async_allocator_inst = call_instruction->async_allocator->other;
11486 if (type_is_invalid(uncasted_async_allocator_inst->value.type))
11487 return ira->codegen->builtin_types.entry_invalid;
11488 }
11489 IrInstruction *async_allocator_inst = ir_implicit_cast(ira, uncasted_async_allocator_inst, fn_type_id->async_allocator_type);
11490 if (type_is_invalid(async_allocator_inst->value.type))
11491 return ira->codegen->builtin_types.entry_invalid;
11492
11493 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref, casted_args, call_param_count, async_allocator_inst);
11494 ir_link_new_instruction(result, &call_instruction->base);
11495 return ir_finish_anal(ira, result->value.type);
11496 }
11497
11498
11361 IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base,11499 IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base,
11362 fn_entry, fn_ref, call_param_count, casted_args, false, fn_inline, false, nullptr);11500 fn_entry, fn_ref, call_param_count, casted_args, false, fn_inline, false, nullptr);
1136311501
...@@ -12054,8 +12192,8 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc...@@ -12054,8 +12192,8 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
12054 return return_type;12192 return return_type;
12055}12193}
1205612194
12057static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira,12195static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
12058 TypeTableEntry *bare_struct_type, Buf *field_name, IrInstructionFieldPtr *field_ptr_instruction,12196 TypeTableEntry *bare_struct_type, Buf *field_name, IrInstruction *source_instr,
12059 IrInstruction *container_ptr, TypeTableEntry *container_type)12197 IrInstruction *container_ptr, TypeTableEntry *container_type)
12060{12198{
12061 if (!is_slice(bare_struct_type)) {12199 if (!is_slice(bare_struct_type)) {
...@@ -12063,17 +12201,17 @@ static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira,...@@ -12063,17 +12201,17 @@ static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira,
12063 auto entry = container_scope->decl_table.maybe_get(field_name);12201 auto entry = container_scope->decl_table.maybe_get(field_name);
12064 Tld *tld = entry ? entry->value : nullptr;12202 Tld *tld = entry ? entry->value : nullptr;
12065 if (tld && tld->id == TldIdFn) {12203 if (tld && tld->id == TldIdFn) {
12066 resolve_top_level_decl(ira->codegen, tld, false, field_ptr_instruction->base.source_node);12204 resolve_top_level_decl(ira->codegen, tld, false, source_instr->source_node);
12067 if (tld->resolution == TldResolutionInvalid)12205 if (tld->resolution == TldResolutionInvalid)
12068 return ira->codegen->builtin_types.entry_invalid;12206 return ira->codegen->invalid_instruction;
12069 TldFn *tld_fn = (TldFn *)tld;12207 TldFn *tld_fn = (TldFn *)tld;
12070 FnTableEntry *fn_entry = tld_fn->fn_entry;12208 FnTableEntry *fn_entry = tld_fn->fn_entry;
12071 if (type_is_invalid(fn_entry->type_entry))12209 if (type_is_invalid(fn_entry->type_entry))
12072 return ira->codegen->builtin_types.entry_invalid;12210 return ira->codegen->invalid_instruction;
1207312211
12074 IrInstruction *bound_fn_value = ir_build_const_bound_fn(&ira->new_irb, field_ptr_instruction->base.scope,12212 IrInstruction *bound_fn_value = ir_build_const_bound_fn(&ira->new_irb, source_instr->scope,
12075 field_ptr_instruction->base.source_node, fn_entry, container_ptr);12213 source_instr->source_node, fn_entry, container_ptr);
12076 return ir_analyze_ref(ira, &field_ptr_instruction->base, bound_fn_value, true, false);12214 return ir_get_ref(ira, source_instr, bound_fn_value, true, false);
12077 }12215 }
12078 }12216 }
12079 const char *prefix_name;12217 const char *prefix_name;
...@@ -12088,19 +12226,19 @@ static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira,...@@ -12088,19 +12226,19 @@ static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira,
12088 } else {12226 } else {
12089 prefix_name = "";12227 prefix_name = "";
12090 }12228 }
12091 ir_add_error_node(ira, field_ptr_instruction->base.source_node,12229 ir_add_error_node(ira, source_instr->source_node,
12092 buf_sprintf("no member named '%s' in %s'%s'", buf_ptr(field_name), prefix_name, buf_ptr(&bare_struct_type->name)));12230 buf_sprintf("no member named '%s' in %s'%s'", buf_ptr(field_name), prefix_name, buf_ptr(&bare_struct_type->name)));
12093 return ira->codegen->builtin_types.entry_invalid;12231 return ira->codegen->invalid_instruction;
12094}12232}
1209512233
1209612234
12097static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,12235static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
12098 IrInstructionFieldPtr *field_ptr_instruction, IrInstruction *container_ptr, TypeTableEntry *container_type)12236 IrInstruction *source_instr, IrInstruction *container_ptr, TypeTableEntry *container_type)
12099{12237{
12100 TypeTableEntry *bare_type = container_ref_type(container_type);12238 TypeTableEntry *bare_type = container_ref_type(container_type);
12101 ensure_complete_type(ira->codegen, bare_type);12239 ensure_complete_type(ira->codegen, bare_type);
12102 if (type_is_invalid(bare_type))12240 if (type_is_invalid(bare_type))
12103 return ira->codegen->builtin_types.entry_invalid;12241 return ira->codegen->invalid_instruction;
1210412242
12105 assert(container_ptr->value.type->id == TypeTableEntryIdPointer);12243 assert(container_ptr->value.type->id == TypeTableEntryIdPointer);
12106 bool is_const = container_ptr->value.type->data.pointer.is_const;12244 bool is_const = container_ptr->value.type->data.pointer.is_const;
...@@ -12117,46 +12255,51 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field...@@ -12117,46 +12255,51 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field
12117 if (instr_is_comptime(container_ptr)) {12255 if (instr_is_comptime(container_ptr)) {
12118 ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);12256 ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
12119 if (!ptr_val)12257 if (!ptr_val)
12120 return ira->codegen->builtin_types.entry_invalid;12258 return ira->codegen->invalid_instruction;
1212112259
12122 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {12260 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
12123 ConstExprValue *struct_val = const_ptr_pointee(ira->codegen, ptr_val);12261 ConstExprValue *struct_val = const_ptr_pointee(ira->codegen, ptr_val);
12124 if (type_is_invalid(struct_val->type))12262 if (type_is_invalid(struct_val->type))
12125 return ira->codegen->builtin_types.entry_invalid;12263 return ira->codegen->invalid_instruction;
12126 ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index];12264 ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index];
12127 TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, field_val->type,12265 TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, field_val->type,
12128 is_const, is_volatile, align_bytes,12266 is_const, is_volatile, align_bytes,
12129 (uint32_t)(ptr_bit_offset + field->packed_bits_offset),12267 (uint32_t)(ptr_bit_offset + field->packed_bits_offset),
12130 (uint32_t)unaligned_bit_count_for_result_type);12268 (uint32_t)unaligned_bit_count_for_result_type);
12131 ConstExprValue *const_val = ir_build_const_from(ira, &field_ptr_instruction->base);12269 IrInstruction *result = ir_get_const(ira, source_instr);
12270 ConstExprValue *const_val = &result->value;
12132 const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct;12271 const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct;
12133 const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut;12272 const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut;
12134 const_val->data.x_ptr.data.base_struct.struct_val = struct_val;12273 const_val->data.x_ptr.data.base_struct.struct_val = struct_val;
12135 const_val->data.x_ptr.data.base_struct.field_index = field->src_index;12274 const_val->data.x_ptr.data.base_struct.field_index = field->src_index;
12136 return ptr_type;12275 const_val->type = ptr_type;
12276 return result;
12137 }12277 }
12138 }12278 }
12139 ir_build_struct_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field);12279 IrInstruction *result = ir_build_struct_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node,
12140 return get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,12280 container_ptr, field);
12281 result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
12141 align_bytes,12282 align_bytes,
12142 (uint32_t)(ptr_bit_offset + field->packed_bits_offset),12283 (uint32_t)(ptr_bit_offset + field->packed_bits_offset),
12143 (uint32_t)unaligned_bit_count_for_result_type);12284 (uint32_t)unaligned_bit_count_for_result_type);
12285 return result;
12144 } else {12286 } else {
12145 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,12287 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
12146 field_ptr_instruction, container_ptr, container_type);12288 source_instr, container_ptr, container_type);
12147 }12289 }
12148 } else if (bare_type->id == TypeTableEntryIdEnum) {12290 } else if (bare_type->id == TypeTableEntryIdEnum) {
12149 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,12291 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
12150 field_ptr_instruction, container_ptr, container_type);12292 source_instr, container_ptr, container_type);
12151 } else if (bare_type->id == TypeTableEntryIdUnion) {12293 } else if (bare_type->id == TypeTableEntryIdUnion) {
12152 TypeUnionField *field = find_union_type_field(bare_type, field_name);12294 TypeUnionField *field = find_union_type_field(bare_type, field_name);
12153 if (field) {12295 if (field) {
12154 ir_build_union_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field);12296 IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, container_ptr, field);
12155 return get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,12297 result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
12156 get_abi_alignment(ira->codegen, field->type_entry), 0, 0);12298 get_abi_alignment(ira->codegen, field->type_entry), 0, 0);
12299 return result;
12157 } else {12300 } else {
12158 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,12301 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
12159 field_ptr_instruction, container_ptr, container_type);12302 source_instr, container_ptr, container_type);
12160 }12303 }
12161 } else {12304 } else {
12162 zig_unreachable();12305 zig_unreachable();
...@@ -12266,9 +12409,13 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru...@@ -12266,9 +12409,13 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
12266 if (container_type->id == TypeTableEntryIdPointer) {12409 if (container_type->id == TypeTableEntryIdPointer) {
12267 TypeTableEntry *bare_type = container_ref_type(container_type);12410 TypeTableEntry *bare_type = container_ref_type(container_type);
12268 IrInstruction *container_child = ir_get_deref(ira, &field_ptr_instruction->base, container_ptr);12411 IrInstruction *container_child = ir_get_deref(ira, &field_ptr_instruction->base, container_ptr);
12269 return ir_analyze_container_field_ptr(ira, field_name, field_ptr_instruction, container_child, bare_type);12412 IrInstruction *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base, container_child, bare_type);
12413 ir_link_new_instruction(result, &field_ptr_instruction->base);
12414 return result->value.type;
12270 } else {12415 } else {
12271 return ir_analyze_container_field_ptr(ira, field_name, field_ptr_instruction, container_ptr, container_type);12416 IrInstruction *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base, container_ptr, container_type);
12417 ir_link_new_instruction(result, &field_ptr_instruction->base);
12418 return result->value.type;
12272 }12419 }
12273 } else if (container_type->id == TypeTableEntryIdArray) {12420 } else if (container_type->id == TypeTableEntryIdArray) {
12274 if (buf_eql_str(field_name, "len")) {12421 if (buf_eql_str(field_name, "len")) {
...@@ -16539,7 +16686,8 @@ static TypeTableEntry *ir_analyze_instruction_cancel(IrAnalyze *ira, IrInstructi...@@ -16539,7 +16686,8 @@ static TypeTableEntry *ir_analyze_instruction_cancel(IrAnalyze *ira, IrInstructi
16539 return ira->codegen->builtin_types.entry_invalid;16686 return ira->codegen->builtin_types.entry_invalid;
1654016687
16541 IrInstruction *result = ir_build_cancel(&ira->new_irb, instruction->base.scope, instruction->base.source_node, casted_target);16688 IrInstruction *result = ir_build_cancel(&ira->new_irb, instruction->base.scope, instruction->base.source_node, casted_target);
16542 result->value.type = casted_target->value.type;16689 result->value.type = ira->codegen->builtin_types.entry_void;
16690 result->value.special = ConstValSpecialStatic;
16543 ir_link_new_instruction(result, &instruction->base);16691 ir_link_new_instruction(result, &instruction->base);
16544 return result->value.type;16692 return result->value.type;
16545}16693}
...@@ -16559,6 +16707,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -16559,6 +16707,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
16559 case IrInstructionIdErrWrapCode:16707 case IrInstructionIdErrWrapCode:
16560 case IrInstructionIdErrWrapPayload:16708 case IrInstructionIdErrWrapPayload:
16561 case IrInstructionIdCast:16709 case IrInstructionIdCast:
16710 case IrInstructionIdGetImplicitAllocator:
16562 zig_unreachable();16711 zig_unreachable();
16563 case IrInstructionIdReturn:16712 case IrInstructionIdReturn:
16564 return ir_analyze_instruction_return(ira, (IrInstructionReturn *)instruction);16713 return ir_analyze_instruction_return(ira, (IrInstructionReturn *)instruction);
...@@ -16936,7 +17085,9 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -16936,7 +17085,9 @@ bool ir_has_side_effects(IrInstruction *instruction) {
16936 case IrInstructionIdTagType:17085 case IrInstructionIdTagType:
16937 case IrInstructionIdErrorReturnTrace:17086 case IrInstructionIdErrorReturnTrace:
16938 case IrInstructionIdErrorUnion:17087 case IrInstructionIdErrorUnion:
17088 case IrInstructionIdGetImplicitAllocator:
16939 return false;17089 return false;
17090
16940 case IrInstructionIdAsm:17091 case IrInstructionIdAsm:
16941 {17092 {
16942 IrInstructionAsm *asm_instruction = (IrInstructionAsm *)instruction;17093 IrInstructionAsm *asm_instruction = (IrInstructionAsm *)instruction;
src/ir_print.cpp+16
...@@ -198,6 +198,15 @@ static void ir_print_cast(IrPrint *irp, IrInstructionCast *cast_instruction) {...@@ -198,6 +198,15 @@ static void ir_print_cast(IrPrint *irp, IrInstructionCast *cast_instruction) {
198}198}
199199
200static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {200static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {
201 if (call_instruction->is_async) {
202 fprintf(irp->f, "async");
203 if (call_instruction->async_allocator != nullptr) {
204 fprintf(irp->f, "(");
205 ir_print_other_instruction(irp, call_instruction->async_allocator);
206 fprintf(irp->f, ")");
207 }
208 fprintf(irp->f, " ");
209 }
201 if (call_instruction->fn_entry) {210 if (call_instruction->fn_entry) {
202 fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name));211 fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name));
203 } else {212 } else {
...@@ -1015,6 +1024,10 @@ static void ir_print_cancel(IrPrint *irp, IrInstructionCancel *instruction) {...@@ -1015,6 +1024,10 @@ static void ir_print_cancel(IrPrint *irp, IrInstructionCancel *instruction) {
1015 ir_print_other_instruction(irp, instruction->target);1024 ir_print_other_instruction(irp, instruction->target);
1016}1025}
10171026
1027static void ir_print_get_implicit_allocator(IrPrint *irp, IrInstructionGetImplicitAllocator *instruction) {
1028 fprintf(irp->f, "@getImplicitAllocator()");
1029}
1030
1018static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {1031static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1019 ir_print_prefix(irp, instruction);1032 ir_print_prefix(irp, instruction);
1020 switch (instruction->id) {1033 switch (instruction->id) {
...@@ -1338,6 +1351,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1338,6 +1351,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1338 case IrInstructionIdCancel:1351 case IrInstructionIdCancel:
1339 ir_print_cancel(irp, (IrInstructionCancel *)instruction);1352 ir_print_cancel(irp, (IrInstructionCancel *)instruction);
1340 break;1353 break;
1354 case IrInstructionIdGetImplicitAllocator:
1355 ir_print_get_implicit_allocator(irp, (IrInstructionGetImplicitAllocator *)instruction);
1356 break;
1341 }1357 }
1342 fprintf(irp->f, "\n");1358 fprintf(irp->f, "\n");
1343}1359}
src/parser.cpp+9-1
...@@ -2333,7 +2333,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand...@@ -2333,7 +2333,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand
2333}2333}
23342334
2335/*2335/*
2336FnProto = option("nakedcc" | "stdcallcc" | "extern" | "async") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") TypeExpr2336FnProto = option("nakedcc" | "stdcallcc" | "extern" | ("async" option("(" Expression ")"))) "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") TypeExpr
2337*/2337*/
2338static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {2338static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {
2339 Token *first_token = &pc->tokens->at(*token_index);2339 Token *first_token = &pc->tokens->at(*token_index);
...@@ -2341,12 +2341,18 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m...@@ -2341,12 +2341,18 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m
23412341
2342 CallingConvention cc;2342 CallingConvention cc;
2343 bool is_extern = false;2343 bool is_extern = false;
2344 AstNode *async_allocator_type_node = nullptr;
2344 if (first_token->id == TokenIdKeywordNakedCC) {2345 if (first_token->id == TokenIdKeywordNakedCC) {
2345 *token_index += 1;2346 *token_index += 1;
2346 fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn);2347 fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn);
2347 cc = CallingConventionNaked;2348 cc = CallingConventionNaked;
2348 } else if (first_token->id == TokenIdKeywordAsync) {2349 } else if (first_token->id == TokenIdKeywordAsync) {
2349 *token_index += 1;2350 *token_index += 1;
2351 Token *next_token = &pc->tokens->at(*token_index);
2352 if (next_token->id == TokenIdLParen) {
2353 async_allocator_type_node = ast_parse_type_expr(pc, token_index, true);
2354 ast_eat_token(pc, token_index, TokenIdRParen);
2355 }
2350 fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn);2356 fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn);
2351 cc = CallingConventionAsync;2357 cc = CallingConventionAsync;
2352 } else if (first_token->id == TokenIdKeywordStdcallCC) {2358 } else if (first_token->id == TokenIdKeywordStdcallCC) {
...@@ -2383,6 +2389,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m...@@ -2383,6 +2389,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m
2383 node->data.fn_proto.visib_mod = visib_mod;2389 node->data.fn_proto.visib_mod = visib_mod;
2384 node->data.fn_proto.cc = cc;2390 node->data.fn_proto.cc = cc;
2385 node->data.fn_proto.is_extern = is_extern;2391 node->data.fn_proto.is_extern = is_extern;
2392 node->data.fn_proto.async_allocator_type = async_allocator_type_node;
23862393
2387 Token *fn_name = &pc->tokens->at(*token_index);2394 Token *fn_name = &pc->tokens->at(*token_index);
23882395
...@@ -2798,6 +2805,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -2798,6 +2805,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
2798 visit_node_list(&node->data.fn_proto.params, visit, context);2805 visit_node_list(&node->data.fn_proto.params, visit, context);
2799 visit_field(&node->data.fn_proto.align_expr, visit, context);2806 visit_field(&node->data.fn_proto.align_expr, visit, context);
2800 visit_field(&node->data.fn_proto.section_expr, visit, context);2807 visit_field(&node->data.fn_proto.section_expr, visit, context);
2808 visit_field(&node->data.fn_proto.async_allocator_type, visit, context);
2801 break;2809 break;
2802 case NodeTypeFnDef:2810 case NodeTypeFnDef:
2803 visit_field(&node->data.fn_def.fn_proto, visit, context);2811 visit_field(&node->data.fn_def.fn_proto, visit, context);