authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-03-01 21:55:15-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-03-01 21:55:15-05:00
log7d494b3e7b09403358232dc61f45374d6c26905f
tree601e35d18140e4a83ca2550b9aeaa7e1415d48e7
parent6568be575cb87c2f54aad2dfa20d1f35471d2224
parentde5c0c9f4092a9d5914013e3428af2252da0be81

Merge branch 'async'

closes #727

18 files changed, 2913 insertions(+), 160 deletions(-)

doc/langref.html.in+34-7
......@@ -3844,6 +3844,25 @@ pub fn main() void {
38443844 {#header_open|@ArgType#}
38453845 <p>TODO</p>
38463846 {#header_close#}
3847 {#header_open|@atomicRmw#}
3848 <pre><code class="zig">@atomicRmw(comptime T: type, ptr: &amp;T, comptime op: builtin.AtomicRmwOp, operand: T, comptime ordering: builtin.AtomicOrder) -&gt; T</code></pre>
3849 <p>
3850 This builtin function atomically modifies memory and then returns the previous value.
3851 </p>
3852 <p>
3853 <code>T</code> must be a pointer type, a <code>bool</code>,
3854 or an integer whose bit count meets these requirements:
3855 </p>
3856 <ul>
3857 <li>At least 8</li>
3858 <li>At most the same as usize</li>
3859 <li>Power of 2</li>
3860 </ul>
3861 <p>
3862 TODO right now bool is not accepted. Also I think we could make non powers of 2 work fine, maybe
3863 we can remove this restriction
3864 </p>
3865 {#header_close#}
38473866 {#header_open|@bitCast#}
38483867 <pre><code class="zig">@bitCast(comptime DestType: type, value: var) -&gt; DestType</code></pre>
38493868 <p>
......@@ -5714,7 +5733,7 @@ UseDecl = "use" Expression ";"
57145733
57155734ExternDecl = "extern" option(String) (FnProto | VariableDeclaration) ";"
57165735
5717FnProto = option("nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") TypeExpr
5736FnProto = option("nakedcc" | "stdcallcc" | "extern" | ("async" option("(" Expression ")"))) "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") TypeExpr
57185737
57195738FnDef = option("inline" | "export") FnProto Block
57205739
......@@ -5732,7 +5751,7 @@ ErrorSetExpr = (PrefixOpExpression "!" PrefixOpExpression) | PrefixOpExpression
57325751
57335752BlockOrExpression = Block | Expression
57345753
5735Expression = TryExpression | ReturnExpression | BreakExpression | AssignmentExpression
5754Expression = TryExpression | ReturnExpression | BreakExpression | AssignmentExpression | CancelExpression | ResumeExpression
57365755
57375756AsmExpression = "asm" option("volatile") "(" String option(AsmOutput) ")"
57385757
......@@ -5756,7 +5775,7 @@ AssignmentExpression = UnwrapExpression AssignmentOperator UnwrapExpression | Un
57565775
57575776AssignmentOperator = "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "&lt;&lt;=" | "&gt;&gt;=" | "&amp;=" | "^=" | "|=" | "*%=" | "+%=" | "-%="
57585777
5759BlockExpression(body) = Block | IfExpression(body) | IfErrorExpression(body) | TestExpression(body) | WhileExpression(body) | ForExpression(body) | SwitchExpression | CompTimeExpression(body)
5778BlockExpression(body) = Block | IfExpression(body) | IfErrorExpression(body) | TestExpression(body) | WhileExpression(body) | ForExpression(body) | SwitchExpression | CompTimeExpression(body) | SuspendExpression(body)
57605779
57615780CompTimeExpression(body) = "comptime" body
57625781
......@@ -5774,12 +5793,20 @@ ReturnExpression = "return" option(Expression)
57745793
57755794TryExpression = "try" Expression
57765795
5796AwaitExpression = "await" Expression
5797
57775798BreakExpression = "break" option(":" Symbol) option(Expression)
57785799
5800CancelExpression = "cancel" Expression;
5801
5802ResumeExpression = "resume" Expression;
5803
57795804Defer(body) = ("defer" | "deferror") body
57805805
57815806IfExpression(body) = "if" "(" Expression ")" body option("else" BlockExpression(body))
57825807
5808SuspendExpression(body) = "suspend" option(("|" Symbol "|" body))
5809
57835810IfErrorExpression(body) = "if" "(" Expression ")" option("|" option("*") Symbol "|") body "else" "|" Symbol "|" BlockExpression(body)
57845811
57855812TestExpression(body) = "if" "(" Expression ")" option("|" option("*") Symbol "|") body option("else" BlockExpression(body))
......@@ -5814,7 +5841,7 @@ MultiplyOperator = "||" | "*" | "/" | "%" | "**" | "*%"
58145841
58155842PrefixOpExpression = PrefixOp ErrorSetExpr | SuffixOpExpression
58165843
5817SuffixOpExpression = PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
5844SuffixOpExpression = ("async" option("(" Expression ")") PrimaryExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
58185845
58195846FieldAccessExpression = "." Symbol
58205847
......@@ -5830,7 +5857,7 @@ ContainerInitBody = list(StructLiteralField, ",") | list(Expression, ",")
58305857
58315858StructLiteralField = "." Symbol "=" Expression
58325859
5833PrefixOp = "!" | "-" | "~" | "*" | ("&amp;" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try"
5860PrefixOp = "!" | "-" | "~" | "*" | ("&amp;" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await"
58345861
58355862PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl
58365863
......@@ -5838,7 +5865,7 @@ ArrayType : "[" option(Expression) "]" option("align" "(" Expression option(":"
58385865
58395866GroupedExpression = "(" Expression ")"
58405867
5841KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "unreachable"
5868KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "unreachable" | "suspend"
58425869
58435870ErrorSetDecl = "error" "{" list(Symbol, ",") "}"
58445871
......@@ -5922,7 +5949,7 @@ hljs.registerLanguage("zig", function(t) {
59225949 a = t.IR + "\\s*\\(",
59235950 c = {
59245951 keyword: "const align var extern stdcallcc nakedcc volatile export pub noalias inline struct packed enum union break return try catch test continue unreachable comptime and or asm defer errdefer if else switch while for fn use bool f32 f64 void type noreturn error i8 u8 i16 u16 i32 u32 i64 u64 isize usize i8w u8w i16w i32w u32w i64w u64w isizew usizew c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong",
5925 built_in: "breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic canImplicitCast ptrCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchg fence divExact truncate",
5952 built_in: "breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic canImplicitCast ptrCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchg fence divExact truncate atomicRmw",
59265953 literal: "true false null undefined"
59275954 },
59285955 n = [e, t.CLCM, t.CBCM, s, r];
src/all_types.hpp+210
......@@ -56,6 +56,16 @@ struct IrExecutable {
5656 IrAnalyze *analysis;
5757 Scope *begin_scope;
5858 ZigList<Tld *> tld_list;
59
60 IrInstruction *coro_handle;
61 IrInstruction *coro_awaiter_field_ptr; // this one is shared and in the promise
62 IrInstruction *coro_result_ptr_field_ptr;
63 IrInstruction *await_handle_var_ptr; // this one is where we put the one we extracted from the promise
64 IrBasicBlock *coro_early_final;
65 IrBasicBlock *coro_normal_final;
66 IrBasicBlock *coro_suspend_block;
67 IrBasicBlock *coro_final_cleanup_block;
68 VariableTableEntry *coro_allocator_var;
5969};
6070
6171enum OutType {
......@@ -393,6 +403,10 @@ enum NodeType {
393403 NodeTypeIfErrorExpr,
394404 NodeTypeTestExpr,
395405 NodeTypeErrorSetDecl,
406 NodeTypeCancel,
407 NodeTypeResume,
408 NodeTypeAwaitExpr,
409 NodeTypeSuspend,
396410};
397411
398412struct AstNodeRoot {
......@@ -405,6 +419,7 @@ enum CallingConvention {
405419 CallingConventionCold,
406420 CallingConventionNaked,
407421 CallingConventionStdcall,
422 CallingConventionAsync,
408423};
409424
410425struct AstNodeFnProto {
......@@ -426,6 +441,7 @@ struct AstNodeFnProto {
426441 AstNode *section_expr;
427442
428443 bool auto_err_set;
444 AstNode *async_allocator_type;
429445};
430446
431447struct AstNodeFnDef {
......@@ -567,6 +583,8 @@ struct AstNodeFnCallExpr {
567583 AstNode *fn_ref_expr;
568584 ZigList<AstNode *> params;
569585 bool is_builtin;
586 bool is_async;
587 AstNode *async_allocator;
570588};
571589
572590struct AstNodeArrayAccessExpr {
......@@ -829,6 +847,14 @@ struct AstNodeBreakExpr {
829847 AstNode *expr; // may be null
830848};
831849
850struct AstNodeCancelExpr {
851 AstNode *expr;
852};
853
854struct AstNodeResumeExpr {
855 AstNode *expr;
856};
857
832858struct AstNodeContinueExpr {
833859 Buf *name;
834860};
......@@ -843,6 +869,15 @@ struct AstNodeErrorType {
843869struct AstNodeVarLiteral {
844870};
845871
872struct AstNodeAwaitExpr {
873 AstNode *expr;
874};
875
876struct AstNodeSuspend {
877 AstNode *block;
878 AstNode *promise_symbol;
879};
880
846881struct AstNode {
847882 enum NodeType type;
848883 size_t line;
......@@ -900,6 +935,10 @@ struct AstNode {
900935 AstNodeErrorType error_type;
901936 AstNodeVarLiteral var_literal;
902937 AstNodeErrorSetDecl err_set_decl;
938 AstNodeCancelExpr cancel_expr;
939 AstNodeResumeExpr resume_expr;
940 AstNodeAwaitExpr await_expr;
941 AstNodeSuspend suspend;
903942 } data;
904943};
905944
......@@ -926,6 +965,7 @@ struct FnTypeId {
926965 bool is_var_args;
927966 CallingConvention cc;
928967 uint32_t alignment;
968 TypeTableEntry *async_allocator_type;
929969};
930970
931971uint32_t fn_type_id_hash(FnTypeId*);
......@@ -1087,6 +1127,11 @@ struct TypeTableEntryBoundFn {
10871127 TypeTableEntry *fn_type;
10881128};
10891129
1130struct TypeTableEntryPromise {
1131 // null if `promise` instead of `promise->T`
1132 TypeTableEntry *result_type;
1133};
1134
10901135enum TypeTableEntryId {
10911136 TypeTableEntryIdInvalid,
10921137 TypeTableEntryIdVar,
......@@ -1114,6 +1159,7 @@ enum TypeTableEntryId {
11141159 TypeTableEntryIdBoundFn,
11151160 TypeTableEntryIdArgTuple,
11161161 TypeTableEntryIdOpaque,
1162 TypeTableEntryIdPromise,
11171163};
11181164
11191165struct TypeTableEntry {
......@@ -1140,11 +1186,14 @@ struct TypeTableEntry {
11401186 TypeTableEntryUnion unionation;
11411187 TypeTableEntryFn fn;
11421188 TypeTableEntryBoundFn bound_fn;
1189 TypeTableEntryPromise promise;
11431190 } data;
11441191
11451192 // use these fields to make sure we don't duplicate type table entries for the same type
11461193 TypeTableEntry *pointer_parent[2]; // [0 - mut, 1 - const]
11471194 TypeTableEntry *maybe_parent;
1195 TypeTableEntry *promise_parent;
1196 TypeTableEntry *promise_frame_parent;
11481197 // If we generate a constant name value for this type, we memoize it here.
11491198 // The type of this is array
11501199 ConstExprValue *cached_const_name_val;
......@@ -1297,6 +1346,7 @@ enum BuiltinFnId {
12971346 BuiltinFnIdArgType,
12981347 BuiltinFnIdExport,
12991348 BuiltinFnIdErrorReturnTrace,
1349 BuiltinFnIdAtomicRmw,
13001350};
13011351
13021352struct BuiltinFnEntry {
......@@ -1470,6 +1520,7 @@ struct CodeGen {
14701520 TypeTableEntry *entry_u8;
14711521 TypeTableEntry *entry_u16;
14721522 TypeTableEntry *entry_u32;
1523 TypeTableEntry *entry_u29;
14731524 TypeTableEntry *entry_u64;
14741525 TypeTableEntry *entry_u128;
14751526 TypeTableEntry *entry_i8;
......@@ -1495,6 +1546,7 @@ struct CodeGen {
14951546 TypeTableEntry *entry_var;
14961547 TypeTableEntry *entry_global_error_set;
14971548 TypeTableEntry *entry_arg_tuple;
1549 TypeTableEntry *entry_promise;
14981550 } builtin_types;
14991551
15001552 EmitFileType emit_file_type;
......@@ -1581,6 +1633,18 @@ struct CodeGen {
15811633 LLVMValueRef trap_fn_val;
15821634 LLVMValueRef return_address_fn_val;
15831635 LLVMValueRef frame_address_fn_val;
1636 LLVMValueRef coro_destroy_fn_val;
1637 LLVMValueRef coro_id_fn_val;
1638 LLVMValueRef coro_alloc_fn_val;
1639 LLVMValueRef coro_size_fn_val;
1640 LLVMValueRef coro_begin_fn_val;
1641 LLVMValueRef coro_suspend_fn_val;
1642 LLVMValueRef coro_end_fn_val;
1643 LLVMValueRef coro_free_fn_val;
1644 LLVMValueRef coro_resume_fn_val;
1645 LLVMValueRef coro_save_fn_val;
1646 LLVMValueRef coro_promise_fn_val;
1647 LLVMValueRef coro_alloc_helper_fn_val;
15841648 bool error_during_imports;
15851649
15861650 const char **clang_argv;
......@@ -1803,6 +1867,19 @@ enum AtomicOrder {
18031867 AtomicOrderSeqCst,
18041868};
18051869
1870// synchronized with the code in define_builtin_compile_vars
1871enum AtomicRmwOp {
1872 AtomicRmwOp_xchg,
1873 AtomicRmwOp_add,
1874 AtomicRmwOp_sub,
1875 AtomicRmwOp_and,
1876 AtomicRmwOp_nand,
1877 AtomicRmwOp_or,
1878 AtomicRmwOp_xor,
1879 AtomicRmwOp_max,
1880 AtomicRmwOp_min,
1881};
1882
18061883// A basic block contains no branching. Branches send control flow
18071884// to another basic block.
18081885// Phi instructions must be first in a basic block.
......@@ -1939,6 +2016,22 @@ enum IrInstructionId {
19392016 IrInstructionIdExport,
19402017 IrInstructionIdErrorReturnTrace,
19412018 IrInstructionIdErrorUnion,
2019 IrInstructionIdCancel,
2020 IrInstructionIdGetImplicitAllocator,
2021 IrInstructionIdCoroId,
2022 IrInstructionIdCoroAlloc,
2023 IrInstructionIdCoroSize,
2024 IrInstructionIdCoroBegin,
2025 IrInstructionIdCoroAllocFail,
2026 IrInstructionIdCoroSuspend,
2027 IrInstructionIdCoroEnd,
2028 IrInstructionIdCoroFree,
2029 IrInstructionIdCoroResume,
2030 IrInstructionIdCoroSave,
2031 IrInstructionIdCoroPromise,
2032 IrInstructionIdCoroAllocHelper,
2033 IrInstructionIdAtomicRmw,
2034 IrInstructionIdPromiseResultType,
19422035};
19432036
19442037struct IrInstruction {
......@@ -2142,6 +2235,9 @@ struct IrInstructionCall {
21422235 bool is_comptime;
21432236 LLVMValueRef tmp_ptr;
21442237 FnInline fn_inline;
2238 bool is_async;
2239
2240 IrInstruction *async_allocator;
21452241};
21462242
21472243struct IrInstructionConst {
......@@ -2776,6 +2872,113 @@ struct IrInstructionErrorUnion {
27762872 IrInstruction *payload;
27772873};
27782874
2875struct IrInstructionCancel {
2876 IrInstruction base;
2877
2878 IrInstruction *target;
2879};
2880
2881enum ImplicitAllocatorId {
2882 ImplicitAllocatorIdArg,
2883 ImplicitAllocatorIdLocalVar,
2884};
2885
2886struct IrInstructionGetImplicitAllocator {
2887 IrInstruction base;
2888
2889 ImplicitAllocatorId id;
2890};
2891
2892struct IrInstructionCoroId {
2893 IrInstruction base;
2894
2895 IrInstruction *promise_ptr;
2896};
2897
2898struct IrInstructionCoroAlloc {
2899 IrInstruction base;
2900
2901 IrInstruction *coro_id;
2902};
2903
2904struct IrInstructionCoroSize {
2905 IrInstruction base;
2906};
2907
2908struct IrInstructionCoroBegin {
2909 IrInstruction base;
2910
2911 IrInstruction *coro_id;
2912 IrInstruction *coro_mem_ptr;
2913};
2914
2915struct IrInstructionCoroAllocFail {
2916 IrInstruction base;
2917
2918 IrInstruction *err_val;
2919};
2920
2921struct IrInstructionCoroSuspend {
2922 IrInstruction base;
2923
2924 IrInstruction *save_point;
2925 IrInstruction *is_final;
2926};
2927
2928struct IrInstructionCoroEnd {
2929 IrInstruction base;
2930};
2931
2932struct IrInstructionCoroFree {
2933 IrInstruction base;
2934
2935 IrInstruction *coro_id;
2936 IrInstruction *coro_handle;
2937};
2938
2939struct IrInstructionCoroResume {
2940 IrInstruction base;
2941
2942 IrInstruction *awaiter_handle;
2943};
2944
2945struct IrInstructionCoroSave {
2946 IrInstruction base;
2947
2948 IrInstruction *coro_handle;
2949};
2950
2951struct IrInstructionCoroPromise {
2952 IrInstruction base;
2953
2954 IrInstruction *coro_handle;
2955};
2956
2957struct IrInstructionCoroAllocHelper {
2958 IrInstruction base;
2959
2960 IrInstruction *alloc_fn;
2961 IrInstruction *coro_size;
2962};
2963
2964struct IrInstructionAtomicRmw {
2965 IrInstruction base;
2966
2967 IrInstruction *operand_type;
2968 IrInstruction *ptr;
2969 IrInstruction *op;
2970 AtomicRmwOp resolved_op;
2971 IrInstruction *operand;
2972 IrInstruction *ordering;
2973 AtomicOrder resolved_ordering;
2974};
2975
2976struct IrInstructionPromiseResultType {
2977 IrInstruction base;
2978
2979 IrInstruction *promise_type;
2980};
2981
27792982static const size_t slice_ptr_index = 0;
27802983static const size_t slice_len_index = 1;
27812984
......@@ -2785,6 +2988,13 @@ static const size_t maybe_null_index = 1;
27852988static const size_t err_union_err_index = 0;
27862989static const size_t err_union_payload_index = 1;
27872990
2991#define ASYNC_ALLOC_FIELD_NAME "allocFn"
2992#define ASYNC_FREE_FIELD_NAME "freeFn"
2993#define AWAITER_HANDLE_FIELD_NAME "awaiter_handle"
2994#define RESULT_FIELD_NAME "result"
2995#define RESULT_PTR_FIELD_NAME "result_ptr"
2996
2997
27882998enum FloatMode {
27892999 FloatModeOptimized,
27903000 FloatModeStrict,
src/analyze.cpp+179-30
......@@ -230,6 +230,7 @@ bool type_is_complete(TypeTableEntry *type_entry) {
230230 case TypeTableEntryIdBlock:
231231 case TypeTableEntryIdBoundFn:
232232 case TypeTableEntryIdArgTuple:
233 case TypeTableEntryIdPromise:
233234 return true;
234235 }
235236 zig_unreachable();
......@@ -267,6 +268,7 @@ bool type_has_zero_bits_known(TypeTableEntry *type_entry) {
267268 case TypeTableEntryIdBoundFn:
268269 case TypeTableEntryIdArgTuple:
269270 case TypeTableEntryIdOpaque:
271 case TypeTableEntryIdPromise:
270272 return true;
271273 }
272274 zig_unreachable();
......@@ -339,6 +341,32 @@ TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) {
339341 return get_int_type(g, false, bits_needed_for_unsigned(x));
340342}
341343
344TypeTableEntry *get_promise_type(CodeGen *g, TypeTableEntry *result_type) {
345 if (result_type != nullptr && result_type->promise_parent != nullptr) {
346 return result_type->promise_parent;
347 } else if (result_type == nullptr && g->builtin_types.entry_promise != nullptr) {
348 return g->builtin_types.entry_promise;
349 }
350
351 TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, false);
352 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPromise);
353 entry->type_ref = u8_ptr_type->type_ref;
354 entry->zero_bits = false;
355 entry->data.promise.result_type = result_type;
356 buf_init_from_str(&entry->name, "promise");
357 if (result_type != nullptr) {
358 buf_appendf(&entry->name, "->%s", buf_ptr(&result_type->name));
359 }
360 entry->di_type = u8_ptr_type->di_type;
361
362 if (result_type != nullptr) {
363 result_type->promise_parent = entry;
364 } else if (result_type == nullptr) {
365 g->builtin_types.entry_promise = entry;
366 }
367 return entry;
368}
369
342370TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type, bool is_const,
343371 bool is_volatile, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count)
344372{
......@@ -429,6 +457,23 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
429457 return get_pointer_to_type_extra(g, child_type, is_const, false, get_abi_alignment(g, child_type), 0, 0);
430458}
431459
460TypeTableEntry *get_promise_frame_type(CodeGen *g, TypeTableEntry *return_type) {
461 if (return_type->promise_frame_parent != nullptr) {
462 return return_type->promise_frame_parent;
463 }
464
465 TypeTableEntry *awaiter_handle_type = get_maybe_type(g, g->builtin_types.entry_promise);
466 TypeTableEntry *result_ptr_type = get_pointer_to_type(g, return_type, false);
467 const char *field_names[] = {AWAITER_HANDLE_FIELD_NAME, RESULT_FIELD_NAME, RESULT_PTR_FIELD_NAME};
468 TypeTableEntry *field_types[] = {awaiter_handle_type, return_type, result_ptr_type};
469 size_t field_count = type_has_bits(result_ptr_type) ? 3 : 1;
470 Buf *name = buf_sprintf("AsyncFramePromise(%s)", buf_ptr(&return_type->name));
471 TypeTableEntry *entry = get_struct_type(g, buf_ptr(name), field_names, field_types, field_count);
472
473 return_type->promise_frame_parent = entry;
474 return entry;
475}
476
432477TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
433478 if (child_type->maybe_parent) {
434479 TypeTableEntry *entry = child_type->maybe_parent;
......@@ -447,9 +492,7 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
447492 if (child_type->zero_bits) {
448493 entry->type_ref = LLVMInt1Type();
449494 entry->di_type = g->builtin_types.entry_bool->di_type;
450 } else if (child_type->id == TypeTableEntryIdPointer ||
451 child_type->id == TypeTableEntryIdFn)
452 {
495 } else if (type_is_codegen_pointer(child_type)) {
453496 // this is an optimization but also is necessary for calling C
454497 // functions where all pointers are maybe pointers
455498 // function types are technically pointers
......@@ -884,6 +927,7 @@ static const char *calling_convention_name(CallingConvention cc) {
884927 case CallingConventionCold: return "coldcc";
885928 case CallingConventionNaked: return "nakedcc";
886929 case CallingConventionStdcall: return "stdcallcc";
930 case CallingConventionAsync: return "async";
887931 }
888932 zig_unreachable();
889933}
......@@ -895,6 +939,21 @@ static const char *calling_convention_fn_type_str(CallingConvention cc) {
895939 case CallingConventionCold: return "coldcc ";
896940 case CallingConventionNaked: return "nakedcc ";
897941 case CallingConventionStdcall: return "stdcallcc ";
942 case CallingConventionAsync: return "async ";
943 }
944 zig_unreachable();
945}
946
947static bool calling_convention_allows_zig_types(CallingConvention cc) {
948 switch (cc) {
949 case CallingConventionUnspecified:
950 case CallingConventionAsync:
951 return true;
952 case CallingConventionC:
953 case CallingConventionCold:
954 case CallingConventionNaked:
955 case CallingConventionStdcall:
956 return false;
898957 }
899958 zig_unreachable();
900959}
......@@ -924,8 +983,13 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
924983
925984 // populate the name of the type
926985 buf_resize(&fn_type->name, 0);
927 const char *cc_str = calling_convention_fn_type_str(fn_type->data.fn.fn_type_id.cc);
928 buf_appendf(&fn_type->name, "%sfn(", cc_str);
986 if (fn_type->data.fn.fn_type_id.cc == CallingConventionAsync) {
987 buf_appendf(&fn_type->name, "async(%s) ", buf_ptr(&fn_type_id->async_allocator_type->name));
988 } else {
989 const char *cc_str = calling_convention_fn_type_str(fn_type->data.fn.fn_type_id.cc);
990 buf_appendf(&fn_type->name, "%s", cc_str);
991 }
992 buf_appendf(&fn_type->name, "fn(");
929993 for (size_t i = 0; i < fn_type_id->param_count; i += 1) {
930994 FnTypeParamInfo *param_info = &fn_type_id->param_info[i];
931995
......@@ -953,20 +1017,23 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
9531017 if (!skip_debug_info) {
9541018 bool first_arg_return = calling_convention_does_first_arg_return(fn_type_id->cc) &&
9551019 handle_is_ptr(fn_type_id->return_type);
956 bool prefix_arg_error_return_trace = g->have_err_ret_tracing &&
957 (fn_type_id->return_type->id == TypeTableEntryIdErrorUnion ||
958 fn_type_id->return_type->id == TypeTableEntryIdErrorSet);
1020 bool is_async = fn_type_id->cc == CallingConventionAsync;
1021 bool prefix_arg_error_return_trace = g->have_err_ret_tracing && fn_type_can_fail(fn_type_id);
9591022 // +1 for maybe making the first argument the return value
960 // +1 for maybe last argument the error return trace
961 LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(2 + fn_type_id->param_count);
1023 // +1 for maybe first argument the error return trace
1024 // +2 for maybe arguments async allocator and error code pointer
1025 LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(4 + fn_type_id->param_count);
9621026 // +1 because 0 is the return type and
9631027 // +1 for maybe making first arg ret val and
964 // +1 for maybe last argument the error return trace
965 ZigLLVMDIType **param_di_types = allocate<ZigLLVMDIType*>(3 + fn_type_id->param_count);
1028 // +1 for maybe first argument the error return trace
1029 // +2 for maybe arguments async allocator and error code pointer
1030 ZigLLVMDIType **param_di_types = allocate<ZigLLVMDIType*>(5 + fn_type_id->param_count);
9661031 param_di_types[0] = fn_type_id->return_type->di_type;
9671032 size_t gen_param_index = 0;
9681033 TypeTableEntry *gen_return_type;
969 if (!type_has_bits(fn_type_id->return_type)) {
1034 if (is_async) {
1035 gen_return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, false);
1036 } else if (!type_has_bits(fn_type_id->return_type)) {
9701037 gen_return_type = g->builtin_types.entry_void;
9711038 } else if (first_arg_return) {
9721039 TypeTableEntry *gen_type = get_pointer_to_type(g, fn_type_id->return_type, false);
......@@ -987,6 +1054,25 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
9871054 // after the gen_param_index += 1 because 0 is the return type
9881055 param_di_types[gen_param_index] = gen_type->di_type;
9891056 }
1057 if (is_async) {
1058 {
1059 // async allocator param
1060 TypeTableEntry *gen_type = fn_type_id->async_allocator_type;
1061 gen_param_types[gen_param_index] = gen_type->type_ref;
1062 gen_param_index += 1;
1063 // after the gen_param_index += 1 because 0 is the return type
1064 param_di_types[gen_param_index] = gen_type->di_type;
1065 }
1066
1067 {
1068 // error code pointer
1069 TypeTableEntry *gen_type = get_pointer_to_type(g, g->builtin_types.entry_global_error_set, false);
1070 gen_param_types[gen_param_index] = gen_type->type_ref;
1071 gen_param_index += 1;
1072 // after the gen_param_index += 1 because 0 is the return type
1073 param_di_types[gen_param_index] = gen_type->di_type;
1074 }
1075 }
9901076
9911077 fn_type->data.fn.gen_param_info = allocate<FnGenParamInfo>(fn_type_id->param_count);
9921078 for (size_t i = 0; i < fn_type_id->param_count; i += 1) {
......@@ -1096,7 +1182,16 @@ TypeTableEntry *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
10961182TypeTableEntry *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
10971183 TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn);
10981184 fn_type->is_copyable = false;
1099 buf_init_from_str(&fn_type->name, "fn(");
1185 buf_resize(&fn_type->name, 0);
1186 if (fn_type->data.fn.fn_type_id.cc == CallingConventionAsync) {
1187 const char *async_allocator_type_str = (fn_type->data.fn.fn_type_id.async_allocator_type == nullptr) ?
1188 "var" : buf_ptr(&fn_type_id->async_allocator_type->name);
1189 buf_appendf(&fn_type->name, "async(%s) ", async_allocator_type_str);
1190 } else {
1191 const char *cc_str = calling_convention_fn_type_str(fn_type->data.fn.fn_type_id.cc);
1192 buf_appendf(&fn_type->name, "%s", cc_str);
1193 }
1194 buf_appendf(&fn_type->name, "fn(");
11001195 size_t i = 0;
11011196 for (; i < fn_type_id->next_param_index; i += 1) {
11021197 const char *comma_str = (i == 0) ? "" : ",";
......@@ -1201,6 +1296,7 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
12011296 case TypeTableEntryIdBoundFn:
12021297 case TypeTableEntryIdArgTuple:
12031298 case TypeTableEntryIdOpaque:
1299 case TypeTableEntryIdPromise:
12041300 return false;
12051301 case TypeTableEntryIdVoid:
12061302 case TypeTableEntryIdBool:
......@@ -1217,7 +1313,7 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
12171313 case TypeTableEntryIdMaybe:
12181314 {
12191315 TypeTableEntry *child_type = type_entry->data.maybe.child_type;
1220 return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn;
1316 return type_is_codegen_pointer(child_type);
12211317 }
12221318 case TypeTableEntryIdEnum:
12231319 return type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr;
......@@ -1241,6 +1337,7 @@ static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) {
12411337 case TypeTableEntryIdBlock:
12421338 case TypeTableEntryIdBoundFn:
12431339 case TypeTableEntryIdArgTuple:
1340 case TypeTableEntryIdPromise:
12441341 return false;
12451342 case TypeTableEntryIdOpaque:
12461343 case TypeTableEntryIdUnreachable:
......@@ -1312,7 +1409,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
13121409 bool param_is_var_args = param_node->data.param_decl.is_var_args;
13131410
13141411 if (param_is_comptime) {
1315 if (fn_type_id.cc != CallingConventionUnspecified) {
1412 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
13161413 add_node_error(g, param_node,
13171414 buf_sprintf("comptime parameter not allowed in function with calling convention '%s'",
13181415 calling_convention_name(fn_type_id.cc)));
......@@ -1323,7 +1420,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
13231420 if (fn_type_id.cc == CallingConventionC) {
13241421 fn_type_id.param_count = fn_type_id.next_param_index;
13251422 continue;
1326 } else if (fn_type_id.cc == CallingConventionUnspecified) {
1423 } else if (calling_convention_allows_zig_types(fn_type_id.cc)) {
13271424 return get_generic_fn_type(g, &fn_type_id);
13281425 } else {
13291426 add_node_error(g, param_node,
......@@ -1337,7 +1434,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
13371434 if (type_is_invalid(type_entry)) {
13381435 return g->builtin_types.entry_invalid;
13391436 }
1340 if (fn_type_id.cc != CallingConventionUnspecified) {
1437 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
13411438 type_ensure_zero_bits_known(g, type_entry);
13421439 if (!type_has_bits(type_entry)) {
13431440 add_node_error(g, param_node->data.param_decl.type,
......@@ -1347,7 +1444,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
13471444 }
13481445 }
13491446
1350 if (fn_type_id.cc != CallingConventionUnspecified && !type_allowed_in_extern(g, type_entry)) {
1447 if (!calling_convention_allows_zig_types(fn_type_id.cc) && !type_allowed_in_extern(g, type_entry)) {
13511448 add_node_error(g, param_node->data.param_decl.type,
13521449 buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'",
13531450 buf_ptr(&type_entry->name),
......@@ -1367,7 +1464,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
13671464 buf_sprintf("parameter of type '%s' not allowed", buf_ptr(&type_entry->name)));
13681465 return g->builtin_types.entry_invalid;
13691466 case TypeTableEntryIdVar:
1370 if (fn_type_id.cc != CallingConventionUnspecified) {
1467 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
13711468 add_node_error(g, param_node->data.param_decl.type,
13721469 buf_sprintf("parameter of type 'var' not allowed in function with calling convention '%s'",
13731470 calling_convention_name(fn_type_id.cc)));
......@@ -1381,7 +1478,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
13811478 case TypeTableEntryIdBoundFn:
13821479 case TypeTableEntryIdMetaType:
13831480 add_node_error(g, param_node->data.param_decl.type,
1384 buf_sprintf("parameter of type '%s' must be declared inline",
1481 buf_sprintf("parameter of type '%s' must be declared comptime",
13851482 buf_ptr(&type_entry->name)));
13861483 return g->builtin_types.entry_invalid;
13871484 case TypeTableEntryIdVoid:
......@@ -1397,8 +1494,9 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
13971494 case TypeTableEntryIdEnum:
13981495 case TypeTableEntryIdUnion:
13991496 case TypeTableEntryIdFn:
1497 case TypeTableEntryIdPromise:
14001498 ensure_complete_type(g, type_entry);
1401 if (fn_type_id.cc == CallingConventionUnspecified && !type_is_copyable(g, type_entry)) {
1499 if (calling_convention_allows_zig_types(fn_type_id.cc) && !type_is_copyable(g, type_entry)) {
14021500 add_node_error(g, param_node->data.param_decl.type,
14031501 buf_sprintf("type '%s' is not copyable; cannot pass by value", buf_ptr(&type_entry->name)));
14041502 return g->builtin_types.entry_invalid;
......@@ -1429,7 +1527,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
14291527 fn_type_id.return_type = specified_return_type;
14301528 }
14311529
1432 if (fn_type_id.cc != CallingConventionUnspecified && !type_allowed_in_extern(g, fn_type_id.return_type)) {
1530 if (!calling_convention_allows_zig_types(fn_type_id.cc) && !type_allowed_in_extern(g, fn_type_id.return_type)) {
14331531 add_node_error(g, fn_proto->return_type,
14341532 buf_sprintf("return type '%s' not allowed in function with calling convention '%s'",
14351533 buf_ptr(&fn_type_id.return_type->name),
......@@ -1456,7 +1554,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
14561554 case TypeTableEntryIdBoundFn:
14571555 case TypeTableEntryIdVar:
14581556 case TypeTableEntryIdMetaType:
1459 if (fn_type_id.cc != CallingConventionUnspecified) {
1557 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
14601558 add_node_error(g, fn_proto->return_type,
14611559 buf_sprintf("return type '%s' not allowed in function with calling convention '%s'",
14621560 buf_ptr(&fn_type_id.return_type->name),
......@@ -1478,9 +1576,20 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
14781576 case TypeTableEntryIdEnum:
14791577 case TypeTableEntryIdUnion:
14801578 case TypeTableEntryIdFn:
1579 case TypeTableEntryIdPromise:
14811580 break;
14821581 }
14831582
1583 if (fn_type_id.cc == CallingConventionAsync) {
1584 if (fn_proto->async_allocator_type == nullptr) {
1585 return get_generic_fn_type(g, &fn_type_id);
1586 }
1587 fn_type_id.async_allocator_type = analyze_type_expr(g, child_scope, fn_proto->async_allocator_type);
1588 if (type_is_invalid(fn_type_id.async_allocator_type)) {
1589 return g->builtin_types.entry_invalid;
1590 }
1591 }
1592
14841593 return get_fn_type(g, &fn_type_id);
14851594}
14861595
......@@ -1615,6 +1724,8 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f
16151724 field->src_index = i;
16161725 field->gen_index = i;
16171726
1727 assert(type_has_bits(field->type_entry));
1728
16181729 auto prev_entry = struct_type->data.structure.fields_by_name.put_unique(field->name, field);
16191730 assert(prev_entry == nullptr);
16201731 }
......@@ -3119,6 +3230,10 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
31193230 case NodeTypeIfErrorExpr:
31203231 case NodeTypeTestExpr:
31213232 case NodeTypeErrorSetDecl:
3233 case NodeTypeCancel:
3234 case NodeTypeResume:
3235 case NodeTypeAwaitExpr:
3236 case NodeTypeSuspend:
31223237 zig_unreachable();
31233238 }
31243239}
......@@ -3174,6 +3289,7 @@ TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEnt
31743289 case TypeTableEntryIdUnion:
31753290 case TypeTableEntryIdFn:
31763291 case TypeTableEntryIdBoundFn:
3292 case TypeTableEntryIdPromise:
31773293 return type_entry;
31783294 }
31793295 zig_unreachable();
......@@ -3552,6 +3668,7 @@ static bool is_container(TypeTableEntry *type_entry) {
35523668 case TypeTableEntryIdBoundFn:
35533669 case TypeTableEntryIdArgTuple:
35543670 case TypeTableEntryIdOpaque:
3671 case TypeTableEntryIdPromise:
35553672 return false;
35563673 }
35573674 zig_unreachable();
......@@ -3602,6 +3719,7 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
36023719 case TypeTableEntryIdVar:
36033720 case TypeTableEntryIdArgTuple:
36043721 case TypeTableEntryIdOpaque:
3722 case TypeTableEntryIdPromise:
36053723 zig_unreachable();
36063724 }
36073725}
......@@ -3609,15 +3727,17 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
36093727TypeTableEntry *get_codegen_ptr_type(TypeTableEntry *type) {
36103728 if (type->id == TypeTableEntryIdPointer) return type;
36113729 if (type->id == TypeTableEntryIdFn) return type;
3730 if (type->id == TypeTableEntryIdPromise) return type;
36123731 if (type->id == TypeTableEntryIdMaybe) {
36133732 if (type->data.maybe.child_type->id == TypeTableEntryIdPointer) return type->data.maybe.child_type;
36143733 if (type->data.maybe.child_type->id == TypeTableEntryIdFn) return type->data.maybe.child_type;
3734 if (type->data.maybe.child_type->id == TypeTableEntryIdPromise) return type->data.maybe.child_type;
36153735 }
36163736 return nullptr;
36173737}
36183738
36193739bool type_is_codegen_pointer(TypeTableEntry *type) {
3620 return get_codegen_ptr_type(type) != nullptr;
3740 return get_codegen_ptr_type(type) == type;
36213741}
36223742
36233743uint32_t get_ptr_align(TypeTableEntry *type) {
......@@ -3626,6 +3746,8 @@ uint32_t get_ptr_align(TypeTableEntry *type) {
36263746 return ptr_type->data.pointer.alignment;
36273747 } else if (ptr_type->id == TypeTableEntryIdFn) {
36283748 return (ptr_type->data.fn.fn_type_id.alignment == 0) ? 1 : ptr_type->data.fn.fn_type_id.alignment;
3749 } else if (ptr_type->id == TypeTableEntryIdPromise) {
3750 return 1;
36293751 } else {
36303752 zig_unreachable();
36313753 }
......@@ -3640,7 +3762,7 @@ AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index) {
36403762 return nullptr;
36413763}
36423764
3643void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, VariableTableEntry **arg_vars) {
3765static void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, VariableTableEntry **arg_vars) {
36443766 TypeTableEntry *fn_type = fn_table_entry->type_entry;
36453767 assert(!fn_type->data.fn.is_generic);
36463768 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
......@@ -3661,7 +3783,7 @@ void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, Vari
36613783 TypeTableEntry *param_type = param_info->type;
36623784 bool is_noalias = param_info->is_noalias;
36633785
3664 if (is_noalias && !type_is_codegen_pointer(param_type)) {
3786 if (is_noalias && get_codegen_ptr_type(param_type) == nullptr) {
36653787 add_node_error(g, param_decl_node, buf_sprintf("noalias on non-pointer parameter"));
36663788 }
36673789
......@@ -4094,6 +4216,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
40944216 case TypeTableEntryIdErrorSet:
40954217 case TypeTableEntryIdFn:
40964218 case TypeTableEntryIdEnum:
4219 case TypeTableEntryIdPromise:
40974220 return false;
40984221 case TypeTableEntryIdArray:
40994222 case TypeTableEntryIdStruct:
......@@ -4102,8 +4225,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
41024225 return type_has_bits(type_entry->data.error_union.payload_type);
41034226 case TypeTableEntryIdMaybe:
41044227 return type_has_bits(type_entry->data.maybe.child_type) &&
4105 type_entry->data.maybe.child_type->id != TypeTableEntryIdPointer &&
4106 type_entry->data.maybe.child_type->id != TypeTableEntryIdFn;
4228 !type_is_codegen_pointer(type_entry->data.maybe.child_type);
41074229 case TypeTableEntryIdUnion:
41084230 assert(type_entry->data.unionation.complete);
41094231 if (type_entry->data.unionation.gen_field_count == 0)
......@@ -4205,6 +4327,7 @@ uint32_t fn_type_id_hash(FnTypeId *id) {
42054327 result += ((uint32_t)(id->cc)) * (uint32_t)3349388391;
42064328 result += id->is_var_args ? (uint32_t)1931444534 : 0;
42074329 result += hash_ptr(id->return_type);
4330 result += hash_ptr(id->async_allocator_type);
42084331 result += id->alignment * 0xd3b3f3e2;
42094332 for (size_t i = 0; i < id->param_count; i += 1) {
42104333 FnTypeParamInfo *info = &id->param_info[i];
......@@ -4219,7 +4342,8 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {
42194342 a->return_type != b->return_type ||
42204343 a->is_var_args != b->is_var_args ||
42214344 a->param_count != b->param_count ||
4222 a->alignment != b->alignment)
4345 a->alignment != b->alignment ||
4346 a->async_allocator_type != b->async_allocator_type)
42234347 {
42244348 return false;
42254349 }
......@@ -4341,6 +4465,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
43414465 }
43424466 zig_unreachable();
43434467 }
4468 case TypeTableEntryIdPromise:
4469 // TODO better hashing algorithm
4470 return 223048345;
43444471 case TypeTableEntryIdUndefLit:
43454472 return 162837799;
43464473 case TypeTableEntryIdNullLit:
......@@ -4500,6 +4627,7 @@ bool type_requires_comptime(TypeTableEntry *type_entry) {
45004627 case TypeTableEntryIdPointer:
45014628 case TypeTableEntryIdVoid:
45024629 case TypeTableEntryIdUnreachable:
4630 case TypeTableEntryIdPromise:
45034631 return false;
45044632 }
45054633 zig_unreachable();
......@@ -4969,6 +5097,7 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
49695097 case TypeTableEntryIdInvalid:
49705098 case TypeTableEntryIdUnreachable:
49715099 case TypeTableEntryIdVar:
5100 case TypeTableEntryIdPromise:
49725101 zig_unreachable();
49735102 }
49745103 zig_unreachable();
......@@ -5243,6 +5372,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
52435372 buf_appendf(buf, "(args value)");
52445373 return;
52455374 }
5375 case TypeTableEntryIdPromise:
5376 zig_unreachable();
52465377 }
52475378 zig_unreachable();
52485379}
......@@ -5304,6 +5435,7 @@ uint32_t type_id_hash(TypeId x) {
53045435 case TypeTableEntryIdBlock:
53055436 case TypeTableEntryIdBoundFn:
53065437 case TypeTableEntryIdArgTuple:
5438 case TypeTableEntryIdPromise:
53075439 zig_unreachable();
53085440 case TypeTableEntryIdErrorUnion:
53095441 return hash_ptr(x.data.error_union.err_set_type) ^ hash_ptr(x.data.error_union.payload_type);
......@@ -5341,6 +5473,7 @@ bool type_id_eql(TypeId a, TypeId b) {
53415473 case TypeTableEntryIdUndefLit:
53425474 case TypeTableEntryIdNullLit:
53435475 case TypeTableEntryIdMaybe:
5476 case TypeTableEntryIdPromise:
53445477 case TypeTableEntryIdErrorSet:
53455478 case TypeTableEntryIdEnum:
53465479 case TypeTableEntryIdUnion:
......@@ -5468,6 +5601,7 @@ static const TypeTableEntryId all_type_ids[] = {
54685601 TypeTableEntryIdBoundFn,
54695602 TypeTableEntryIdArgTuple,
54705603 TypeTableEntryIdOpaque,
5604 TypeTableEntryIdPromise,
54715605};
54725606
54735607TypeTableEntryId type_id_at_index(size_t index) {
......@@ -5532,6 +5666,8 @@ size_t type_id_index(TypeTableEntryId id) {
55325666 return 22;
55335667 case TypeTableEntryIdOpaque:
55345668 return 23;
5669 case TypeTableEntryIdPromise:
5670 return 24;
55355671 }
55365672 zig_unreachable();
55375673}
......@@ -5589,6 +5725,8 @@ const char *type_id_name(TypeTableEntryId id) {
55895725 return "ArgTuple";
55905726 case TypeTableEntryIdOpaque:
55915727 return "Opaque";
5728 case TypeTableEntryIdPromise:
5729 return "Promise";
55925730 }
55935731 zig_unreachable();
55945732}
......@@ -5671,3 +5809,14 @@ bool type_is_global_error_set(TypeTableEntry *err_set_type) {
56715809 assert(err_set_type->data.error_set.infer_fn == nullptr);
56725810 return err_set_type->data.error_set.err_count == UINT32_MAX;
56735811}
5812
5813uint32_t get_coro_frame_align_bytes(CodeGen *g) {
5814 return g->pointer_size_bytes * 2;
5815}
5816
5817bool fn_type_can_fail(FnTypeId *fn_type_id) {
5818 TypeTableEntry *return_type = fn_type_id->return_type;
5819 return return_type->id == TypeTableEntryIdErrorUnion || return_type->id == TypeTableEntryIdErrorSet ||
5820 fn_type_id->cc == CallingConventionAsync;
5821}
5822
src/analyze.hpp+6-1
......@@ -35,6 +35,8 @@ TypeTableEntry *get_bound_fn_type(CodeGen *g, FnTableEntry *fn_entry);
3535TypeTableEntry *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *name);
3636TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[],
3737 TypeTableEntry *field_types[], size_t field_count);
38TypeTableEntry *get_promise_type(CodeGen *g, TypeTableEntry *result_type);
39TypeTableEntry *get_promise_frame_type(CodeGen *g, TypeTableEntry *return_type);
3840TypeTableEntry *get_test_fn_type(CodeGen *g);
3941bool handle_is_ptr(TypeTableEntry *type_entry);
4042void find_libc_include_path(CodeGen *g);
......@@ -50,6 +52,7 @@ VariableTableEntry *find_variable(CodeGen *g, Scope *orig_context, Buf *name);
5052Tld *find_decl(CodeGen *g, Scope *scope, Buf *name);
5153void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *source_node);
5254bool type_is_codegen_pointer(TypeTableEntry *type);
55
5356TypeTableEntry *get_codegen_ptr_type(TypeTableEntry *type);
5457uint32_t get_ptr_align(TypeTableEntry *type);
5558TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry);
......@@ -92,7 +95,6 @@ void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *
9295void eval_min_max_value_int(CodeGen *g, TypeTableEntry *int_type, BigInt *bigint, bool is_max);
9396
9497void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val);
95void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, VariableTableEntry **arg_vars);
9698void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_type_node);
9799
98100ScopeBlock *create_block_scope(AstNode *node, Scope *parent);
......@@ -190,4 +192,7 @@ void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry);
190192
191193TypeTableEntry *get_auto_err_set_type(CodeGen *g, FnTableEntry *fn_entry);
192194
195uint32_t get_coro_frame_align_bytes(CodeGen *g);
196bool fn_type_can_fail(FnTypeId *fn_type_id);
197
193198#endif
src/ast_render.cpp+37
......@@ -244,6 +244,14 @@ static const char *node_type_str(NodeType node_type) {
244244 return "TestExpr";
245245 case NodeTypeErrorSetDecl:
246246 return "ErrorSetDecl";
247 case NodeTypeCancel:
248 return "Cancel";
249 case NodeTypeResume:
250 return "Resume";
251 case NodeTypeAwaitExpr:
252 return "AwaitExpr";
253 case NodeTypeSuspend:
254 return "Suspend";
247255 }
248256 zig_unreachable();
249257}
......@@ -1037,6 +1045,35 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
10371045 fprintf(ar->f, "}");
10381046 break;
10391047 }
1048 case NodeTypeCancel:
1049 {
1050 fprintf(ar->f, "cancel ");
1051 render_node_grouped(ar, node->data.cancel_expr.expr);
1052 break;
1053 }
1054 case NodeTypeResume:
1055 {
1056 fprintf(ar->f, "resume ");
1057 render_node_grouped(ar, node->data.resume_expr.expr);
1058 break;
1059 }
1060 case NodeTypeAwaitExpr:
1061 {
1062 fprintf(ar->f, "await ");
1063 render_node_grouped(ar, node->data.await_expr.expr);
1064 break;
1065 }
1066 case NodeTypeSuspend:
1067 {
1068 fprintf(ar->f, "suspend");
1069 if (node->data.suspend.block != nullptr) {
1070 fprintf(ar->f, " |");
1071 render_node_grouped(ar, node->data.suspend.promise_symbol);
1072 fprintf(ar->f, "| ");
1073 render_node_grouped(ar, node->data.suspend.block);
1074 }
1075 break;
1076 }
10401077 case NodeTypeFnDecl:
10411078 case NodeTypeParamDecl:
10421079 case NodeTypeTestDecl:
src/codegen.cpp+572-17
......@@ -381,6 +381,8 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
381381 } else {
382382 return LLVMCCallConv;
383383 }
384 case CallingConventionAsync:
385 return LLVMFastCallConv;
384386 }
385387 zig_unreachable();
386388}
......@@ -410,10 +412,10 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, FnTableEntry *fn_table_e
410412 return UINT32_MAX;
411413 }
412414 TypeTableEntry *fn_type = fn_table_entry->type_entry;
413 TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;
414 if (return_type->id != TypeTableEntryIdErrorUnion && return_type->id != TypeTableEntryIdErrorSet) {
415 if (!fn_type_can_fail(&fn_type->data.fn.fn_type_id)) {
415416 return UINT32_MAX;
416417 }
418 TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;
417419 bool first_arg_ret = type_has_bits(return_type) && handle_is_ptr(return_type);
418420 return first_arg_ret ? 1 : 0;
419421}
......@@ -540,7 +542,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
540542
541543 if (!type_has_bits(return_type)) {
542544 // nothing to do
543 } else if (return_type->id == TypeTableEntryIdPointer || return_type->id == TypeTableEntryIdFn) {
545 } else if (type_is_codegen_pointer(return_type)) {
544546 addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
545547 } else if (handle_is_ptr(return_type) &&
546548 calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc))
......@@ -925,6 +927,177 @@ static LLVMValueRef get_memcpy_fn_val(CodeGen *g) {
925927 return g->memcpy_fn_val;
926928}
927929
930static LLVMValueRef get_coro_destroy_fn_val(CodeGen *g) {
931 if (g->coro_destroy_fn_val)
932 return g->coro_destroy_fn_val;
933
934 LLVMTypeRef param_types[] = {
935 LLVMPointerType(LLVMInt8Type(), 0),
936 };
937 LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), param_types, 1, false);
938 Buf *name = buf_sprintf("llvm.coro.destroy");
939 g->coro_destroy_fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);
940 assert(LLVMGetIntrinsicID(g->coro_destroy_fn_val));
941
942 return g->coro_destroy_fn_val;
943}
944
945static LLVMValueRef get_coro_id_fn_val(CodeGen *g) {
946 if (g->coro_id_fn_val)
947 return g->coro_id_fn_val;
948
949 LLVMTypeRef param_types[] = {
950 LLVMInt32Type(),
951 LLVMPointerType(LLVMInt8Type(), 0),
952 LLVMPointerType(LLVMInt8Type(), 0),
953 LLVMPointerType(LLVMInt8Type(), 0),
954 };
955 LLVMTypeRef fn_type = LLVMFunctionType(ZigLLVMTokenTypeInContext(LLVMGetGlobalContext()), param_types, 4, false);
956 Buf *name = buf_sprintf("llvm.coro.id");
957 g->coro_id_fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);
958 assert(LLVMGetIntrinsicID(g->coro_id_fn_val));
959
960 return g->coro_id_fn_val;
961}
962
963static LLVMValueRef get_coro_alloc_fn_val(CodeGen *g) {
964 if (g->coro_alloc_fn_val)
965 return g->coro_alloc_fn_val;
966
967 LLVMTypeRef param_types[] = {
968 ZigLLVMTokenTypeInContext(LLVMGetGlobalContext()),
969 };
970 LLVMTypeRef fn_type = LLVMFunctionType(LLVMInt1Type(), param_types, 1, false);
971 Buf *name = buf_sprintf("llvm.coro.alloc");
972 g->coro_alloc_fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);
973 assert(LLVMGetIntrinsicID(g->coro_alloc_fn_val));
974
975 return g->coro_alloc_fn_val;
976}
977
978static LLVMValueRef get_coro_size_fn_val(CodeGen *g) {
979 if (g->coro_size_fn_val)
980 return g->coro_size_fn_val;
981
982 LLVMTypeRef fn_type = LLVMFunctionType(g->builtin_types.entry_usize->type_ref, nullptr, 0, false);
983 Buf *name = buf_sprintf("llvm.coro.size.i%d", g->pointer_size_bytes * 8);
984 g->coro_size_fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);
985 assert(LLVMGetIntrinsicID(g->coro_size_fn_val));
986
987 return g->coro_size_fn_val;
988}
989
990static LLVMValueRef get_coro_begin_fn_val(CodeGen *g) {
991 if (g->coro_begin_fn_val)
992 return g->coro_begin_fn_val;
993
994 LLVMTypeRef param_types[] = {
995 ZigLLVMTokenTypeInContext(LLVMGetGlobalContext()),
996 LLVMPointerType(LLVMInt8Type(), 0),
997 };
998 LLVMTypeRef fn_type = LLVMFunctionType(LLVMPointerType(LLVMInt8Type(), 0), param_types, 2, false);
999 Buf *name = buf_sprintf("llvm.coro.begin");
1000 g->coro_begin_fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);
1001 assert(LLVMGetIntrinsicID(g->coro_begin_fn_val));
1002
1003 return g->coro_begin_fn_val;
1004}
1005
1006static LLVMValueRef get_coro_suspend_fn_val(CodeGen *g) {
1007 if (g->coro_suspend_fn_val)
1008 return g->coro_suspend_fn_val;
1009
1010 LLVMTypeRef param_types[] = {
1011 ZigLLVMTokenTypeInContext(LLVMGetGlobalContext()),
1012 LLVMInt1Type(),
1013 };
1014 LLVMTypeRef fn_type = LLVMFunctionType(LLVMInt8Type(), param_types, 2, false);
1015 Buf *name = buf_sprintf("llvm.coro.suspend");
1016 g->coro_suspend_fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);
1017 assert(LLVMGetIntrinsicID(g->coro_suspend_fn_val));
1018
1019 return g->coro_suspend_fn_val;
1020}
1021
1022static LLVMValueRef get_coro_end_fn_val(CodeGen *g) {
1023 if (g->coro_end_fn_val)
1024 return g->coro_end_fn_val;
1025
1026 LLVMTypeRef param_types[] = {
1027 LLVMPointerType(LLVMInt8Type(), 0),
1028 LLVMInt1Type(),
1029 };
1030 LLVMTypeRef fn_type = LLVMFunctionType(LLVMInt1Type(), param_types, 2, false);
1031 Buf *name = buf_sprintf("llvm.coro.end");
1032 g->coro_end_fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);
1033 assert(LLVMGetIntrinsicID(g->coro_end_fn_val));
1034
1035 return g->coro_end_fn_val;
1036}
1037
1038static LLVMValueRef get_coro_free_fn_val(CodeGen *g) {
1039 if (g->coro_free_fn_val)
1040 return g->coro_free_fn_val;
1041
1042 LLVMTypeRef param_types[] = {
1043 ZigLLVMTokenTypeInContext(LLVMGetGlobalContext()),
1044 LLVMPointerType(LLVMInt8Type(), 0),
1045 };
1046 LLVMTypeRef fn_type = LLVMFunctionType(LLVMPointerType(LLVMInt8Type(), 0), param_types, 2, false);
1047 Buf *name = buf_sprintf("llvm.coro.free");
1048 g->coro_free_fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);
1049 assert(LLVMGetIntrinsicID(g->coro_free_fn_val));
1050
1051 return g->coro_free_fn_val;
1052}
1053
1054static LLVMValueRef get_coro_resume_fn_val(CodeGen *g) {
1055 if (g->coro_resume_fn_val)
1056 return g->coro_resume_fn_val;
1057
1058 LLVMTypeRef param_types[] = {
1059 LLVMPointerType(LLVMInt8Type(), 0),
1060 };
1061 LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), param_types, 1, false);
1062 Buf *name = buf_sprintf("llvm.coro.resume");
1063 g->coro_resume_fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);
1064 assert(LLVMGetIntrinsicID(g->coro_resume_fn_val));
1065
1066 return g->coro_resume_fn_val;
1067}
1068
1069static LLVMValueRef get_coro_save_fn_val(CodeGen *g) {
1070 if (g->coro_save_fn_val)
1071 return g->coro_save_fn_val;
1072
1073 LLVMTypeRef param_types[] = {
1074 LLVMPointerType(LLVMInt8Type(), 0),
1075 };
1076 LLVMTypeRef fn_type = LLVMFunctionType(ZigLLVMTokenTypeInContext(LLVMGetGlobalContext()), param_types, 1, false);
1077 Buf *name = buf_sprintf("llvm.coro.save");
1078 g->coro_save_fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);
1079 assert(LLVMGetIntrinsicID(g->coro_save_fn_val));
1080
1081 return g->coro_save_fn_val;
1082}
1083
1084static LLVMValueRef get_coro_promise_fn_val(CodeGen *g) {
1085 if (g->coro_promise_fn_val)
1086 return g->coro_promise_fn_val;
1087
1088 LLVMTypeRef param_types[] = {
1089 LLVMPointerType(LLVMInt8Type(), 0),
1090 LLVMInt32Type(),
1091 LLVMInt1Type(),
1092 };
1093 LLVMTypeRef fn_type = LLVMFunctionType(LLVMPointerType(LLVMInt8Type(), 0), param_types, 3, false);
1094 Buf *name = buf_sprintf("llvm.coro.promise");
1095 g->coro_promise_fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);
1096 assert(LLVMGetIntrinsicID(g->coro_promise_fn_val));
1097
1098 return g->coro_promise_fn_val;
1099}
1100
9281101static LLVMValueRef get_return_address_fn_val(CodeGen *g) {
9291102 if (g->return_address_fn_val)
9301103 return g->return_address_fn_val;
......@@ -2506,6 +2679,25 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
25062679 }
25072680}
25082681
2682static bool get_prefix_arg_err_ret_stack(CodeGen *g, FnTypeId *fn_type_id) {
2683 return g->have_err_ret_tracing &&
2684 (fn_type_id->return_type->id == TypeTableEntryIdErrorUnion ||
2685 fn_type_id->return_type->id == TypeTableEntryIdErrorSet ||
2686 fn_type_id->cc == CallingConventionAsync);
2687}
2688
2689static size_t get_async_allocator_arg_index(CodeGen *g, FnTypeId *fn_type_id) {
2690 // 0 1 2 3
2691 // err_ret_stack allocator_ptr err_code other_args...
2692 return get_prefix_arg_err_ret_stack(g, fn_type_id) ? 1 : 0;
2693}
2694
2695static size_t get_async_err_code_arg_index(CodeGen *g, FnTypeId *fn_type_id) {
2696 // 0 1 2 3
2697 // err_ret_stack allocator_ptr err_code other_args...
2698 return 1 + get_async_allocator_arg_index(g, fn_type_id);
2699}
2700
25092701static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) {
25102702 LLVMValueRef fn_val;
25112703 TypeTableEntry *fn_type;
......@@ -2519,11 +2711,15 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
25192711 }
25202712
25212713 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
2714
25222715 TypeTableEntry *src_return_type = fn_type_id->return_type;
25232716 bool ret_has_bits = type_has_bits(src_return_type);
2524 bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type);
2525 bool prefix_arg_err_ret_stack = g->have_err_ret_tracing && (src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdErrorSet);
2526 size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0);
2717
2718 bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type) &&
2719 calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc);
2720 bool prefix_arg_err_ret_stack = get_prefix_arg_err_ret_stack(g, fn_type_id);
2721 // +2 for the async args
2722 size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0) + 2;
25272723 bool is_var_args = fn_type_id->is_var_args;
25282724 LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count);
25292725 size_t gen_param_index = 0;
......@@ -2535,6 +2731,14 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
25352731 gen_param_values[gen_param_index] = g->cur_err_ret_trace_val;
25362732 gen_param_index += 1;
25372733 }
2734 if (instruction->is_async) {
2735 gen_param_values[gen_param_index] = ir_llvm_value(g, instruction->async_allocator);
2736 gen_param_index += 1;
2737
2738 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, "");
2739 gen_param_values[gen_param_index] = err_val_ptr;
2740 gen_param_index += 1;
2741 }
25382742 for (size_t call_i = 0; call_i < instruction->arg_count; call_i += 1) {
25392743 IrInstruction *param_instruction = instruction->args[call_i];
25402744 TypeTableEntry *param_type = param_instruction->value.type;
......@@ -2572,6 +2776,12 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
25722776 }
25732777 }
25742778
2779 if (instruction->is_async) {
2780 LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_payload_index, "");
2781 LLVMBuildStore(g->builder, result, payload_ptr);
2782 return instruction->tmp_ptr;
2783 }
2784
25752785 if (src_return_type->id == TypeTableEntryIdUnreachable) {
25762786 return LLVMBuildUnreachable(g->builder);
25772787 } else if (!ret_has_bits) {
......@@ -2783,7 +2993,7 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, TypeTableEntry *maybe_type, LLV
27832993 if (child_type->zero_bits) {
27842994 return maybe_handle;
27852995 } else {
2786 bool maybe_is_ptr = (child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn);
2996 bool maybe_is_ptr = type_is_codegen_pointer(child_type);
27872997 if (maybe_is_ptr) {
27882998 return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), "");
27892999 } else {
......@@ -2823,7 +3033,7 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
28233033 if (child_type->zero_bits) {
28243034 return nullptr;
28253035 } else {
2826 bool maybe_is_ptr = (child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn);
3036 bool maybe_is_ptr = type_is_codegen_pointer(child_type);
28273037 if (maybe_is_ptr) {
28283038 return maybe_ptr;
28293039 } else {
......@@ -3046,6 +3256,10 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
30463256 {
30473257 align_bytes = target_type->data.maybe.child_type->data.fn.fn_type_id.alignment;
30483258 ptr_val = target_val;
3259 } else if (target_type->id == TypeTableEntryIdMaybe &&
3260 target_type->data.maybe.child_type->id == TypeTableEntryIdPromise)
3261 {
3262 zig_panic("TODO audit this function");
30493263 } else if (target_type->id == TypeTableEntryIdStruct && target_type->data.structure.is_slice) {
30503264 TypeTableEntry *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index].type_entry;
30513265 align_bytes = slice_ptr_type->data.pointer.alignment;
......@@ -3088,6 +3302,20 @@ static LLVMValueRef ir_render_error_return_trace(CodeGen *g, IrExecutable *execu
30883302 return g->cur_err_ret_trace_val;
30893303}
30903304
3305static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrInstructionCancel *instruction) {
3306 LLVMValueRef target_handle = ir_llvm_value(g, instruction->target);
3307 LLVMBuildCall(g->builder, get_coro_destroy_fn_val(g), &target_handle, 1, "");
3308 return nullptr;
3309}
3310
3311static LLVMValueRef ir_render_get_implicit_allocator(CodeGen *g, IrExecutable *executable,
3312 IrInstructionGetImplicitAllocator *instruction)
3313{
3314 assert(instruction->id == ImplicitAllocatorIdArg);
3315 size_t allocator_arg_index = get_async_allocator_arg_index(g, &g->cur_fn->type_entry->data.fn.fn_type_id);
3316 return LLVMGetParam(g->cur_fn_val, allocator_arg_index);
3317}
3318
30913319static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) {
30923320 switch (atomic_order) {
30933321 case AtomicOrderUnordered: return LLVMAtomicOrderingUnordered;
......@@ -3100,6 +3328,23 @@ static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) {
31003328 zig_unreachable();
31013329}
31023330
3331static LLVMAtomicRMWBinOp to_LLVMAtomicRMWBinOp(AtomicRmwOp op, bool is_signed) {
3332 switch (op) {
3333 case AtomicRmwOp_xchg: return LLVMAtomicRMWBinOpXchg;
3334 case AtomicRmwOp_add: return LLVMAtomicRMWBinOpAdd;
3335 case AtomicRmwOp_sub: return LLVMAtomicRMWBinOpSub;
3336 case AtomicRmwOp_and: return LLVMAtomicRMWBinOpAnd;
3337 case AtomicRmwOp_nand: return LLVMAtomicRMWBinOpNand;
3338 case AtomicRmwOp_or: return LLVMAtomicRMWBinOpOr;
3339 case AtomicRmwOp_xor: return LLVMAtomicRMWBinOpXor;
3340 case AtomicRmwOp_max:
3341 return is_signed ? LLVMAtomicRMWBinOpMax : LLVMAtomicRMWBinOpUMax;
3342 case AtomicRmwOp_min:
3343 return is_signed ? LLVMAtomicRMWBinOpMin : LLVMAtomicRMWBinOpUMin;
3344 }
3345 zig_unreachable();
3346}
3347
31033348static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchg *instruction) {
31043349 LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr);
31053350 LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value);
......@@ -3508,9 +3753,7 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I
35083753 }
35093754
35103755 LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);
3511 if (child_type->id == TypeTableEntryIdPointer ||
3512 child_type->id == TypeTableEntryIdFn)
3513 {
3756 if (type_is_codegen_pointer(child_type)) {
35143757 return payload_val;
35153758 }
35163759
......@@ -3682,6 +3925,264 @@ static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutable *executable, IrInst
36823925 return nullptr;
36833926}
36843927
3928static LLVMValueRef ir_render_coro_id(CodeGen *g, IrExecutable *executable, IrInstructionCoroId *instruction) {
3929 LLVMValueRef promise_ptr = ir_llvm_value(g, instruction->promise_ptr);
3930 LLVMValueRef align_val = LLVMConstInt(LLVMInt32Type(), get_coro_frame_align_bytes(g), false);
3931 LLVMValueRef null = LLVMConstIntToPtr(LLVMConstNull(g->builtin_types.entry_usize->type_ref),
3932 LLVMPointerType(LLVMInt8Type(), 0));
3933 LLVMValueRef params[] = {
3934 align_val,
3935 promise_ptr,
3936 null,
3937 null,
3938 };
3939 return LLVMBuildCall(g->builder, get_coro_id_fn_val(g), params, 4, "");
3940}
3941
3942static LLVMValueRef ir_render_coro_alloc(CodeGen *g, IrExecutable *executable, IrInstructionCoroAlloc *instruction) {
3943 LLVMValueRef token = ir_llvm_value(g, instruction->coro_id);
3944 return LLVMBuildCall(g->builder, get_coro_alloc_fn_val(g), &token, 1, "");
3945}
3946
3947static LLVMValueRef ir_render_coro_size(CodeGen *g, IrExecutable *executable, IrInstructionCoroSize *instruction) {
3948 return LLVMBuildCall(g->builder, get_coro_size_fn_val(g), nullptr, 0, "");
3949}
3950
3951static LLVMValueRef ir_render_coro_begin(CodeGen *g, IrExecutable *executable, IrInstructionCoroBegin *instruction) {
3952 LLVMValueRef coro_id = ir_llvm_value(g, instruction->coro_id);
3953 LLVMValueRef coro_mem_ptr = ir_llvm_value(g, instruction->coro_mem_ptr);
3954 LLVMValueRef params[] = {
3955 coro_id,
3956 coro_mem_ptr,
3957 };
3958 return LLVMBuildCall(g->builder, get_coro_begin_fn_val(g), params, 2, "");
3959}
3960
3961static LLVMValueRef ir_render_coro_alloc_fail(CodeGen *g, IrExecutable *executable,
3962 IrInstructionCoroAllocFail *instruction)
3963{
3964 size_t err_code_ptr_arg_index = get_async_err_code_arg_index(g, &g->cur_fn->type_entry->data.fn.fn_type_id);
3965 LLVMValueRef err_code_ptr_val = LLVMGetParam(g->cur_fn_val, err_code_ptr_arg_index);
3966 LLVMValueRef err_code = ir_llvm_value(g, instruction->err_val);
3967 LLVMBuildStore(g->builder, err_code, err_code_ptr_val);
3968
3969 LLVMValueRef return_value;
3970 if (ir_want_runtime_safety(g, &instruction->base)) {
3971 return_value = LLVMConstNull(LLVMPointerType(LLVMInt8Type(), 0));
3972 } else {
3973 return_value = LLVMGetUndef(LLVMPointerType(LLVMInt8Type(), 0));
3974 }
3975 LLVMBuildRet(g->builder, return_value);
3976 return nullptr;
3977}
3978
3979static LLVMValueRef ir_render_coro_suspend(CodeGen *g, IrExecutable *executable, IrInstructionCoroSuspend *instruction) {
3980 LLVMValueRef save_point;
3981 if (instruction->save_point == nullptr) {
3982 save_point = LLVMConstNull(ZigLLVMTokenTypeInContext(LLVMGetGlobalContext()));
3983 } else {
3984 save_point = ir_llvm_value(g, instruction->save_point);
3985 }
3986 LLVMValueRef is_final = ir_llvm_value(g, instruction->is_final);
3987 LLVMValueRef params[] = {
3988 save_point,
3989 is_final,
3990 };
3991 return LLVMBuildCall(g->builder, get_coro_suspend_fn_val(g), params, 2, "");
3992}
3993
3994static LLVMValueRef ir_render_coro_end(CodeGen *g, IrExecutable *executable, IrInstructionCoroEnd *instruction) {
3995 LLVMValueRef params[] = {
3996 LLVMConstNull(LLVMPointerType(LLVMInt8Type(), 0)),
3997 LLVMConstNull(LLVMInt1Type()),
3998 };
3999 return LLVMBuildCall(g->builder, get_coro_end_fn_val(g), params, 2, "");
4000}
4001
4002static LLVMValueRef ir_render_coro_free(CodeGen *g, IrExecutable *executable, IrInstructionCoroFree *instruction) {
4003 LLVMValueRef coro_id = ir_llvm_value(g, instruction->coro_id);
4004 LLVMValueRef coro_handle = ir_llvm_value(g, instruction->coro_handle);
4005 LLVMValueRef params[] = {
4006 coro_id,
4007 coro_handle,
4008 };
4009 return LLVMBuildCall(g->builder, get_coro_free_fn_val(g), params, 2, "");
4010}
4011
4012static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable, IrInstructionCoroResume *instruction) {
4013 LLVMValueRef awaiter_handle = ir_llvm_value(g, instruction->awaiter_handle);
4014 return LLVMBuildCall(g->builder, get_coro_resume_fn_val(g), &awaiter_handle, 1, "");
4015}
4016
4017static LLVMValueRef ir_render_coro_save(CodeGen *g, IrExecutable *executable, IrInstructionCoroSave *instruction) {
4018 LLVMValueRef coro_handle = ir_llvm_value(g, instruction->coro_handle);
4019 return LLVMBuildCall(g->builder, get_coro_save_fn_val(g), &coro_handle, 1, "");
4020}
4021
4022static LLVMValueRef ir_render_coro_promise(CodeGen *g, IrExecutable *executable, IrInstructionCoroPromise *instruction) {
4023 LLVMValueRef coro_handle = ir_llvm_value(g, instruction->coro_handle);
4024 LLVMValueRef params[] = {
4025 coro_handle,
4026 LLVMConstInt(LLVMInt32Type(), get_coro_frame_align_bytes(g), false),
4027 LLVMConstNull(LLVMInt1Type()),
4028 };
4029 LLVMValueRef uncasted_result = LLVMBuildCall(g->builder, get_coro_promise_fn_val(g), params, 3, "");
4030 return LLVMBuildBitCast(g->builder, uncasted_result, instruction->base.value.type->type_ref, "");
4031}
4032
4033static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_fn_type_ref, TypeTableEntry *fn_type) {
4034 if (g->coro_alloc_helper_fn_val != nullptr)
4035 return g->coro_alloc_helper_fn_val;
4036
4037 assert(fn_type->id == TypeTableEntryIdFn);
4038
4039 TypeTableEntry *ptr_to_err_code_type = get_pointer_to_type(g, g->builtin_types.entry_global_error_set, false);
4040
4041 LLVMTypeRef alloc_raw_fn_type_ref = LLVMGetElementType(alloc_fn_type_ref);
4042 LLVMTypeRef *alloc_fn_arg_types = allocate<LLVMTypeRef>(LLVMCountParamTypes(alloc_raw_fn_type_ref));
4043 LLVMGetParamTypes(alloc_raw_fn_type_ref, alloc_fn_arg_types);
4044
4045 ZigList<LLVMTypeRef> arg_types = {};
4046 arg_types.append(alloc_fn_type_ref);
4047 if (g->have_err_ret_tracing) {
4048 arg_types.append(alloc_fn_arg_types[1]);
4049 }
4050 arg_types.append(alloc_fn_arg_types[g->have_err_ret_tracing ? 2 : 1]);
4051 arg_types.append(ptr_to_err_code_type->type_ref);
4052 arg_types.append(g->builtin_types.entry_usize->type_ref);
4053
4054 LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMPointerType(LLVMInt8Type(), 0),
4055 arg_types.items, arg_types.length, false);
4056
4057 Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_coro_alloc_helper"), false);
4058 LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref);
4059 LLVMSetLinkage(fn_val, LLVMInternalLinkage);
4060 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
4061 addLLVMFnAttr(fn_val, "nounwind");
4062 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
4063 addLLVMArgAttr(fn_val, (unsigned)1, "nonnull");
4064
4065 LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder);
4066 LLVMValueRef prev_debug_location = LLVMGetCurrentDebugLocation(g->builder);
4067 FnTableEntry *prev_cur_fn = g->cur_fn;
4068 LLVMValueRef prev_cur_fn_val = g->cur_fn_val;
4069
4070 LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry");
4071 LLVMPositionBuilderAtEnd(g->builder, entry_block);
4072 ZigLLVMClearCurrentDebugLocation(g->builder);
4073 g->cur_fn = nullptr;
4074 g->cur_fn_val = fn_val;
4075
4076 LLVMValueRef sret_ptr = LLVMBuildAlloca(g->builder, LLVMGetElementType(alloc_fn_arg_types[0]), "");
4077
4078 size_t next_arg = 0;
4079 LLVMValueRef alloc_fn_val = LLVMGetParam(fn_val, next_arg);
4080 next_arg += 1;
4081
4082 LLVMValueRef stack_trace_val;
4083 if (g->have_err_ret_tracing) {
4084 stack_trace_val = LLVMGetParam(fn_val, next_arg);
4085 next_arg += 1;
4086 }
4087
4088 LLVMValueRef allocator_val = LLVMGetParam(fn_val, next_arg);
4089 next_arg += 1;
4090 LLVMValueRef err_code_ptr = LLVMGetParam(fn_val, next_arg);
4091 next_arg += 1;
4092 LLVMValueRef coro_size = LLVMGetParam(fn_val, next_arg);
4093 next_arg += 1;
4094 LLVMValueRef alignment_val = LLVMConstInt(g->builtin_types.entry_u29->type_ref,
4095 get_coro_frame_align_bytes(g), false);
4096
4097 ZigList<LLVMValueRef> args = {};
4098 args.append(sret_ptr);
4099 if (g->have_err_ret_tracing) {
4100 args.append(stack_trace_val);
4101 }
4102 args.append(allocator_val);
4103 args.append(coro_size);
4104 args.append(alignment_val);
4105 ZigLLVMBuildCall(g->builder, alloc_fn_val, args.items, args.length,
4106 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
4107 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, sret_ptr, err_union_err_index, "");
4108 LLVMValueRef err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
4109 LLVMBuildStore(g->builder, err_val, err_code_ptr);
4110 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, LLVMConstNull(LLVMTypeOf(err_val)), "");
4111 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(fn_val, "AllocOk");
4112 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(fn_val, "AllocFail");
4113 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
4114
4115 LLVMPositionBuilderAtEnd(g->builder, ok_block);
4116 LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, sret_ptr, err_union_payload_index, "");
4117 TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, false);
4118 TypeTableEntry *slice_type = get_slice_type(g, u8_ptr_type);
4119 size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index;
4120 LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, payload_ptr, ptr_field_index, "");
4121 LLVMValueRef ptr_val = LLVMBuildLoad(g->builder, ptr_field_ptr, "");
4122 LLVMBuildRet(g->builder, ptr_val);
4123
4124 LLVMPositionBuilderAtEnd(g->builder, fail_block);
4125 LLVMBuildRet(g->builder, LLVMConstNull(LLVMPointerType(LLVMInt8Type(), 0)));
4126
4127 g->cur_fn = prev_cur_fn;
4128 g->cur_fn_val = prev_cur_fn_val;
4129 LLVMPositionBuilderAtEnd(g->builder, prev_block);
4130 LLVMSetCurrentDebugLocation(g->builder, prev_debug_location);
4131
4132 g->coro_alloc_helper_fn_val = fn_val;
4133 return fn_val;
4134}
4135
4136static LLVMValueRef ir_render_coro_alloc_helper(CodeGen *g, IrExecutable *executable,
4137 IrInstructionCoroAllocHelper *instruction)
4138{
4139 LLVMValueRef alloc_fn = ir_llvm_value(g, instruction->alloc_fn);
4140 LLVMValueRef coro_size = ir_llvm_value(g, instruction->coro_size);
4141 LLVMValueRef fn_val = get_coro_alloc_helper_fn_val(g, LLVMTypeOf(alloc_fn), instruction->alloc_fn->value.type);
4142 size_t err_code_ptr_arg_index = get_async_err_code_arg_index(g, &g->cur_fn->type_entry->data.fn.fn_type_id);
4143 size_t allocator_arg_index = get_async_allocator_arg_index(g, &g->cur_fn->type_entry->data.fn.fn_type_id);
4144
4145 ZigList<LLVMValueRef> params = {};
4146 params.append(alloc_fn);
4147 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, g->cur_fn);
4148 if (err_ret_trace_arg_index != UINT32_MAX) {
4149 params.append(LLVMGetParam(g->cur_fn_val, err_ret_trace_arg_index));
4150 }
4151 params.append(LLVMGetParam(g->cur_fn_val, allocator_arg_index));
4152 params.append(LLVMGetParam(g->cur_fn_val, err_code_ptr_arg_index));
4153 params.append(coro_size);
4154
4155 return ZigLLVMBuildCall(g->builder, fn_val, params.items, params.length,
4156 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
4157}
4158
4159static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutable *executable,
4160 IrInstructionAtomicRmw *instruction)
4161{
4162 bool is_signed;
4163 TypeTableEntry *operand_type = instruction->operand->value.type;
4164 if (operand_type->id == TypeTableEntryIdInt) {
4165 is_signed = operand_type->data.integral.is_signed;
4166 } else {
4167 is_signed = false;
4168 }
4169 LLVMAtomicRMWBinOp op = to_LLVMAtomicRMWBinOp(instruction->resolved_op, is_signed);
4170 LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->resolved_ordering);
4171 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
4172 LLVMValueRef operand = ir_llvm_value(g, instruction->operand);
4173
4174 if (get_codegen_ptr_type(operand_type) == nullptr) {
4175 return LLVMBuildAtomicRMW(g->builder, op, ptr, operand, ordering, false);
4176 }
4177
4178 // it's a pointer but we need to treat it as an int
4179 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, ptr,
4180 LLVMPointerType(g->builtin_types.entry_usize->type_ref, 0), "");
4181 LLVMValueRef casted_operand = LLVMBuildPtrToInt(g->builder, operand, g->builtin_types.entry_usize->type_ref, "");
4182 LLVMValueRef uncasted_result = LLVMBuildAtomicRMW(g->builder, op, casted_ptr, casted_operand, ordering, false);
4183 return LLVMBuildIntToPtr(g->builder, uncasted_result, operand_type->type_ref, "");
4184}
4185
36854186static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
36864187 AstNode *source_node = instruction->source_node;
36874188 Scope *scope = instruction->scope;
......@@ -3745,7 +4246,9 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
37454246 case IrInstructionIdTagType:
37464247 case IrInstructionIdExport:
37474248 case IrInstructionIdErrorUnion:
4249 case IrInstructionIdPromiseResultType:
37484250 zig_unreachable();
4251
37494252 case IrInstructionIdReturn:
37504253 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
37514254 case IrInstructionIdDeclVar:
......@@ -3862,12 +4365,43 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
38624365 return ir_render_align_cast(g, executable, (IrInstructionAlignCast *)instruction);
38634366 case IrInstructionIdErrorReturnTrace:
38644367 return ir_render_error_return_trace(g, executable, (IrInstructionErrorReturnTrace *)instruction);
4368 case IrInstructionIdCancel:
4369 return ir_render_cancel(g, executable, (IrInstructionCancel *)instruction);
4370 case IrInstructionIdGetImplicitAllocator:
4371 return ir_render_get_implicit_allocator(g, executable, (IrInstructionGetImplicitAllocator *)instruction);
4372 case IrInstructionIdCoroId:
4373 return ir_render_coro_id(g, executable, (IrInstructionCoroId *)instruction);
4374 case IrInstructionIdCoroAlloc:
4375 return ir_render_coro_alloc(g, executable, (IrInstructionCoroAlloc *)instruction);
4376 case IrInstructionIdCoroSize:
4377 return ir_render_coro_size(g, executable, (IrInstructionCoroSize *)instruction);
4378 case IrInstructionIdCoroBegin:
4379 return ir_render_coro_begin(g, executable, (IrInstructionCoroBegin *)instruction);
4380 case IrInstructionIdCoroAllocFail:
4381 return ir_render_coro_alloc_fail(g, executable, (IrInstructionCoroAllocFail *)instruction);
4382 case IrInstructionIdCoroSuspend:
4383 return ir_render_coro_suspend(g, executable, (IrInstructionCoroSuspend *)instruction);
4384 case IrInstructionIdCoroEnd:
4385 return ir_render_coro_end(g, executable, (IrInstructionCoroEnd *)instruction);
4386 case IrInstructionIdCoroFree:
4387 return ir_render_coro_free(g, executable, (IrInstructionCoroFree *)instruction);
4388 case IrInstructionIdCoroResume:
4389 return ir_render_coro_resume(g, executable, (IrInstructionCoroResume *)instruction);
4390 case IrInstructionIdCoroSave:
4391 return ir_render_coro_save(g, executable, (IrInstructionCoroSave *)instruction);
4392 case IrInstructionIdCoroPromise:
4393 return ir_render_coro_promise(g, executable, (IrInstructionCoroPromise *)instruction);
4394 case IrInstructionIdCoroAllocHelper:
4395 return ir_render_coro_alloc_helper(g, executable, (IrInstructionCoroAllocHelper *)instruction);
4396 case IrInstructionIdAtomicRmw:
4397 return ir_render_atomic_rmw(g, executable, (IrInstructionAtomicRmw *)instruction);
38654398 }
38664399 zig_unreachable();
38674400}
38684401
38694402static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {
38704403 assert(fn_entry);
4404
38714405 IrExecutable *executable = &fn_entry->analyzed_executable;
38724406 assert(executable->basic_block_list.length > 0);
38734407 for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {
......@@ -4009,6 +4543,7 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
40094543 case TypeTableEntryIdPointer:
40104544 case TypeTableEntryIdFn:
40114545 case TypeTableEntryIdMaybe:
4546 case TypeTableEntryIdPromise:
40124547 {
40134548 LLVMValueRef ptr_val = gen_const_val(g, const_val, "");
40144549 LLVMValueRef ptr_size_int_val = LLVMConstPtrToInt(ptr_val, g->builtin_types.entry_usize->type_ref);
......@@ -4104,9 +4639,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
41044639 TypeTableEntry *child_type = type_entry->data.maybe.child_type;
41054640 if (child_type->zero_bits) {
41064641 return LLVMConstInt(LLVMInt1Type(), const_val->data.x_maybe ? 1 : 0, false);
4107 } else if (child_type->id == TypeTableEntryIdPointer ||
4108 child_type->id == TypeTableEntryIdFn)
4109 {
4642 } else if (type_is_codegen_pointer(child_type)) {
41104643 if (const_val->data.x_maybe) {
41114644 return gen_const_val(g, const_val->data.x_maybe, "");
41124645 } else {
......@@ -4426,6 +4959,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
44264959 case TypeTableEntryIdVar:
44274960 case TypeTableEntryIdArgTuple:
44284961 case TypeTableEntryIdOpaque:
4962 case TypeTableEntryIdPromise:
44294963 zig_unreachable();
44304964
44314965 }
......@@ -5235,6 +5769,7 @@ static void define_builtin_types(CodeGen *g) {
52355769
52365770 g->builtin_types.entry_u8 = get_int_type(g, false, 8);
52375771 g->builtin_types.entry_u16 = get_int_type(g, false, 16);
5772 g->builtin_types.entry_u29 = get_int_type(g, false, 29);
52385773 g->builtin_types.entry_u32 = get_int_type(g, false, 32);
52395774 g->builtin_types.entry_u64 = get_int_type(g, false, 64);
52405775 g->builtin_types.entry_u128 = get_int_type(g, false, 128);
......@@ -5271,6 +5806,10 @@ static void define_builtin_types(CodeGen *g) {
52715806
52725807 g->primitive_type_table.put(&entry->name, entry);
52735808 }
5809 {
5810 TypeTableEntry *entry = get_promise_type(g, nullptr);
5811 g->primitive_type_table.put(&entry->name, entry);
5812 }
52745813
52755814}
52765815
......@@ -5348,6 +5887,7 @@ static void define_builtin_fns(CodeGen *g) {
53485887 create_builtin_fn(g, BuiltinFnIdArgType, "ArgType", 2);
53495888 create_builtin_fn(g, BuiltinFnIdExport, "export", 3);
53505889 create_builtin_fn(g, BuiltinFnIdErrorReturnTrace, "errorReturnTrace", 0);
5890 create_builtin_fn(g, BuiltinFnIdAtomicRmw, "atomicRmw", 5);
53515891}
53525892
53535893static const char *bool_to_str(bool b) {
......@@ -5477,6 +6017,20 @@ static void define_builtin_compile_vars(CodeGen *g) {
54776017 " SeqCst,\n"
54786018 "};\n\n");
54796019 }
6020 {
6021 buf_appendf(contents,
6022 "pub const AtomicRmwOp = enum {\n"
6023 " Xchg,\n"
6024 " Add,\n"
6025 " Sub,\n"
6026 " And,\n"
6027 " Nand,\n"
6028 " Or,\n"
6029 " Xor,\n"
6030 " Max,\n"
6031 " Min,\n"
6032 "};\n\n");
6033 }
54806034 {
54816035 buf_appendf(contents,
54826036 "pub const Mode = enum {\n"
......@@ -5898,6 +6452,7 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, TypeTableEntry
58986452 case TypeTableEntryIdArgTuple:
58996453 case TypeTableEntryIdErrorUnion:
59006454 case TypeTableEntryIdErrorSet:
6455 case TypeTableEntryIdPromise:
59016456 zig_unreachable();
59026457 case TypeTableEntryIdVoid:
59036458 case TypeTableEntryIdUnreachable:
......@@ -6027,9 +6582,7 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf
60276582 if (child_type->zero_bits) {
60286583 buf_init_from_str(out_buf, "bool");
60296584 return;
6030 } else if (child_type->id == TypeTableEntryIdPointer ||
6031 child_type->id == TypeTableEntryIdFn)
6032 {
6585 } else if (type_is_codegen_pointer(child_type)) {
60336586 return get_c_type(g, gen_h, child_type, out_buf);
60346587 } else {
60356588 zig_unreachable();
......@@ -6084,6 +6637,7 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf
60846637 case TypeTableEntryIdNullLit:
60856638 case TypeTableEntryIdVar:
60866639 case TypeTableEntryIdArgTuple:
6640 case TypeTableEntryIdPromise:
60876641 zig_unreachable();
60886642 }
60896643}
......@@ -6244,6 +6798,7 @@ static void gen_h_file(CodeGen *g) {
62446798 case TypeTableEntryIdArgTuple:
62456799 case TypeTableEntryIdMaybe:
62466800 case TypeTableEntryIdFn:
6801 case TypeTableEntryIdPromise:
62476802 zig_unreachable();
62486803 case TypeTableEntryIdEnum:
62496804 assert(type_entry->data.enumeration.layout == ContainerLayoutExtern);
src/ir.cpp+1320-83
......@@ -65,6 +65,7 @@ enum ConstCastResultId {
6565 ConstCastResultIdFnArgNoAlias,
6666 ConstCastResultIdType,
6767 ConstCastResultIdUnresolvedInferredErrSet,
68 ConstCastResultIdAsyncAllocatorType,
6869};
6970
7071struct ConstCastErrSetMismatch {
......@@ -92,6 +93,7 @@ struct ConstCastOnly {
9293 ConstCastOnly *error_union_payload;
9394 ConstCastOnly *error_union_error_set;
9495 ConstCastOnly *return_type;
96 ConstCastOnly *async_allocator_type;
9597 ConstCastArg fn_arg;
9698 ConstCastArgNoAlias arg_no_alias;
9799 } data;
......@@ -104,6 +106,10 @@ static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *ins
104106static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type);
105107static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr);
106108static 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);
111static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
112 VariableTableEntry *var, bool is_const_ptr, bool is_volatile_ptr);
107113
108114ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {
109115 assert(const_val->type->id == TypeTableEntryIdPointer);
......@@ -637,6 +643,70 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionErrorUnion *) {
637643 return IrInstructionIdErrorUnion;
638644}
639645
646static constexpr IrInstructionId ir_instruction_id(IrInstructionCancel *) {
647 return IrInstructionIdCancel;
648}
649
650static constexpr IrInstructionId ir_instruction_id(IrInstructionGetImplicitAllocator *) {
651 return IrInstructionIdGetImplicitAllocator;
652}
653
654static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroId *) {
655 return IrInstructionIdCoroId;
656}
657
658static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroAlloc *) {
659 return IrInstructionIdCoroAlloc;
660}
661
662static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroSize *) {
663 return IrInstructionIdCoroSize;
664}
665
666static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroBegin *) {
667 return IrInstructionIdCoroBegin;
668}
669
670static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroAllocFail *) {
671 return IrInstructionIdCoroAllocFail;
672}
673
674static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroSuspend *) {
675 return IrInstructionIdCoroSuspend;
676}
677
678static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroEnd *) {
679 return IrInstructionIdCoroEnd;
680}
681
682static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroFree *) {
683 return IrInstructionIdCoroFree;
684}
685
686static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroResume *) {
687 return IrInstructionIdCoroResume;
688}
689
690static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroSave *) {
691 return IrInstructionIdCoroSave;
692}
693
694static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroPromise *) {
695 return IrInstructionIdCoroPromise;
696}
697
698static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroAllocHelper *) {
699 return IrInstructionIdCoroAllocHelper;
700}
701
702static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicRmw *) {
703 return IrInstructionIdAtomicRmw;
704}
705
706static constexpr IrInstructionId ir_instruction_id(IrInstructionPromiseResultType *) {
707 return IrInstructionIdPromiseResultType;
708}
709
640710template<typename T>
641711static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
642712 T *special_instruction = allocate<T>(1);
......@@ -708,14 +778,6 @@ static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *sou
708778 return &return_instruction->base;
709779}
710780
711static IrInstruction *ir_build_return_from(IrBuilder *irb, IrInstruction *old_instruction,
712 IrInstruction *return_value)
713{
714 IrInstruction *new_instruction = ir_build_return(irb, old_instruction->scope, old_instruction->source_node, return_value);
715 ir_link_new_instruction(new_instruction, old_instruction);
716 return new_instruction;
717}
718
719781static IrInstruction *ir_create_const(IrBuilder *irb, Scope *scope, AstNode *source_node,
720782 TypeTableEntry *type_entry)
721783{
......@@ -779,6 +841,14 @@ static IrInstruction *ir_build_const_usize(IrBuilder *irb, Scope *scope, AstNode
779841 return &const_instruction->base;
780842}
781843
844static IrInstruction *ir_build_const_u8(IrBuilder *irb, Scope *scope, AstNode *source_node, uint8_t value) {
845 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
846 const_instruction->base.value.type = irb->codegen->builtin_types.entry_u8;
847 const_instruction->base.value.special = ConstValSpecialStatic;
848 bigint_init_unsigned(&const_instruction->base.value.data.x_bigint, value);
849 return &const_instruction->base;
850}
851
782852static IrInstruction *ir_create_const_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
783853 TypeTableEntry *type_entry)
784854{
......@@ -866,6 +936,27 @@ static IrInstruction *ir_build_const_c_str_lit(IrBuilder *irb, Scope *scope, Ast
866936 return &const_instruction->base;
867937}
868938
939static IrInstruction *ir_build_const_promise_init(IrBuilder *irb, Scope *scope, AstNode *source_node,
940 TypeTableEntry *return_type)
941{
942 TypeTableEntry *struct_type = get_promise_frame_type(irb->codegen, return_type);
943
944 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
945 const_instruction->base.value.type = struct_type;
946 const_instruction->base.value.special = ConstValSpecialStatic;
947 const_instruction->base.value.data.x_struct.fields = allocate<ConstExprValue>(struct_type->data.structure.src_field_count);
948 const_instruction->base.value.data.x_struct.fields[0].type = struct_type->data.structure.fields[0].type_entry;
949 const_instruction->base.value.data.x_struct.fields[0].special = ConstValSpecialStatic;
950 const_instruction->base.value.data.x_struct.fields[0].data.x_maybe = nullptr;
951 if (struct_type->data.structure.src_field_count > 1) {
952 const_instruction->base.value.data.x_struct.fields[1].type = return_type;
953 const_instruction->base.value.data.x_struct.fields[1].special = ConstValSpecialUndef;
954 const_instruction->base.value.data.x_struct.fields[2].type = struct_type->data.structure.fields[2].type_entry;
955 const_instruction->base.value.data.x_struct.fields[2].special = ConstValSpecialUndef;
956 }
957 return &const_instruction->base;
958}
959
869960static IrInstruction *ir_build_bin_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrBinOp op_id,
870961 IrInstruction *op1, IrInstruction *op2, bool safety_check_on)
871962{
......@@ -950,15 +1041,6 @@ static IrInstruction *ir_build_struct_field_ptr(IrBuilder *irb, Scope *scope, As
9501041 return &instruction->base;
9511042}
9521043
953static IrInstruction *ir_build_struct_field_ptr_from(IrBuilder *irb, IrInstruction *old_instruction,
954 IrInstruction *struct_ptr, TypeStructField *type_struct_field)
955{
956 IrInstruction *new_instruction = ir_build_struct_field_ptr(irb, old_instruction->scope,
957 old_instruction->source_node, struct_ptr, type_struct_field);
958 ir_link_new_instruction(new_instruction, old_instruction);
959 return new_instruction;
960}
961
9621044static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
9631045 IrInstruction *union_ptr, TypeUnionField *field)
9641046{
......@@ -982,7 +1064,7 @@ static IrInstruction *ir_build_union_field_ptr_from(IrBuilder *irb, IrInstructio
9821064
9831065static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *source_node,
9841066 FnTableEntry *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
985 bool is_comptime, FnInline fn_inline)
1067 bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator)
9861068{
9871069 IrInstructionCall *call_instruction = ir_build_instruction<IrInstructionCall>(irb, scope, source_node);
9881070 call_instruction->fn_entry = fn_entry;
......@@ -991,21 +1073,25 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc
9911073 call_instruction->fn_inline = fn_inline;
9921074 call_instruction->args = args;
9931075 call_instruction->arg_count = arg_count;
1076 call_instruction->is_async = is_async;
1077 call_instruction->async_allocator = async_allocator;
9941078
9951079 if (fn_ref)
9961080 ir_ref_instruction(fn_ref, irb->current_basic_block);
9971081 for (size_t i = 0; i < arg_count; i += 1)
9981082 ir_ref_instruction(args[i], irb->current_basic_block);
1083 if (async_allocator)
1084 ir_ref_instruction(async_allocator, irb->current_basic_block);
9991085
10001086 return &call_instruction->base;
10011087}
10021088
10031089static IrInstruction *ir_build_call_from(IrBuilder *irb, IrInstruction *old_instruction,
10041090 FnTableEntry *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
1005 bool is_comptime, FnInline fn_inline)
1091 bool is_comptime, FnInline fn_inline, bool is_async, IrInstruction *async_allocator)
10061092{
10071093 IrInstruction *new_instruction = ir_build_call(irb, old_instruction->scope,
1008 old_instruction->source_node, fn_entry, fn_ref, arg_count, args, is_comptime, fn_inline);
1094 old_instruction->source_node, fn_entry, fn_ref, arg_count, args, is_comptime, fn_inline, is_async, async_allocator);
10091095 ir_link_new_instruction(new_instruction, old_instruction);
10101096 return new_instruction;
10111097}
......@@ -2396,6 +2482,182 @@ static IrInstruction *ir_build_error_union(IrBuilder *irb, Scope *scope, AstNode
23962482 return &instruction->base;
23972483}
23982484
2485static IrInstruction *ir_build_cancel(IrBuilder *irb, Scope *scope, AstNode *source_node,
2486 IrInstruction *target)
2487{
2488 IrInstructionCancel *instruction = ir_build_instruction<IrInstructionCancel>(irb, scope, source_node);
2489 instruction->target = target;
2490
2491 ir_ref_instruction(target, irb->current_basic_block);
2492
2493 return &instruction->base;
2494}
2495
2496static IrInstruction *ir_build_get_implicit_allocator(IrBuilder *irb, Scope *scope, AstNode *source_node,
2497 ImplicitAllocatorId id)
2498{
2499 IrInstructionGetImplicitAllocator *instruction = ir_build_instruction<IrInstructionGetImplicitAllocator>(irb, scope, source_node);
2500 instruction->id = id;
2501
2502 return &instruction->base;
2503}
2504
2505static IrInstruction *ir_build_coro_id(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *promise_ptr) {
2506 IrInstructionCoroId *instruction = ir_build_instruction<IrInstructionCoroId>(irb, scope, source_node);
2507 instruction->promise_ptr = promise_ptr;
2508
2509 ir_ref_instruction(promise_ptr, irb->current_basic_block);
2510
2511 return &instruction->base;
2512}
2513
2514static IrInstruction *ir_build_coro_alloc(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *coro_id) {
2515 IrInstructionCoroAlloc *instruction = ir_build_instruction<IrInstructionCoroAlloc>(irb, scope, source_node);
2516 instruction->coro_id = coro_id;
2517
2518 ir_ref_instruction(coro_id, irb->current_basic_block);
2519
2520 return &instruction->base;
2521}
2522
2523static IrInstruction *ir_build_coro_size(IrBuilder *irb, Scope *scope, AstNode *source_node) {
2524 IrInstructionCoroSize *instruction = ir_build_instruction<IrInstructionCoroSize>(irb, scope, source_node);
2525
2526 return &instruction->base;
2527}
2528
2529static IrInstruction *ir_build_coro_begin(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *coro_id, IrInstruction *coro_mem_ptr) {
2530 IrInstructionCoroBegin *instruction = ir_build_instruction<IrInstructionCoroBegin>(irb, scope, source_node);
2531 instruction->coro_id = coro_id;
2532 instruction->coro_mem_ptr = coro_mem_ptr;
2533
2534 ir_ref_instruction(coro_id, irb->current_basic_block);
2535 ir_ref_instruction(coro_mem_ptr, irb->current_basic_block);
2536
2537 return &instruction->base;
2538}
2539
2540static IrInstruction *ir_build_coro_alloc_fail(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *err_val) {
2541 IrInstructionCoroAllocFail *instruction = ir_build_instruction<IrInstructionCoroAllocFail>(irb, scope, source_node);
2542 instruction->base.value.type = irb->codegen->builtin_types.entry_unreachable;
2543 instruction->base.value.special = ConstValSpecialStatic;
2544 instruction->err_val = err_val;
2545
2546 ir_ref_instruction(err_val, irb->current_basic_block);
2547
2548 return &instruction->base;
2549}
2550
2551static IrInstruction *ir_build_coro_suspend(IrBuilder *irb, Scope *scope, AstNode *source_node,
2552 IrInstruction *save_point, IrInstruction *is_final)
2553{
2554 IrInstructionCoroSuspend *instruction = ir_build_instruction<IrInstructionCoroSuspend>(irb, scope, source_node);
2555 instruction->save_point = save_point;
2556 instruction->is_final = is_final;
2557
2558 if (save_point != nullptr) ir_ref_instruction(save_point, irb->current_basic_block);
2559 ir_ref_instruction(is_final, irb->current_basic_block);
2560
2561 return &instruction->base;
2562}
2563
2564static IrInstruction *ir_build_coro_end(IrBuilder *irb, Scope *scope, AstNode *source_node) {
2565 IrInstructionCoroEnd *instruction = ir_build_instruction<IrInstructionCoroEnd>(irb, scope, source_node);
2566 return &instruction->base;
2567}
2568
2569static IrInstruction *ir_build_coro_free(IrBuilder *irb, Scope *scope, AstNode *source_node,
2570 IrInstruction *coro_id, IrInstruction *coro_handle)
2571{
2572 IrInstructionCoroFree *instruction = ir_build_instruction<IrInstructionCoroFree>(irb, scope, source_node);
2573 instruction->coro_id = coro_id;
2574 instruction->coro_handle = coro_handle;
2575
2576 ir_ref_instruction(coro_id, irb->current_basic_block);
2577 ir_ref_instruction(coro_handle, irb->current_basic_block);
2578
2579 return &instruction->base;
2580}
2581
2582static IrInstruction *ir_build_coro_resume(IrBuilder *irb, Scope *scope, AstNode *source_node,
2583 IrInstruction *awaiter_handle)
2584{
2585 IrInstructionCoroResume *instruction = ir_build_instruction<IrInstructionCoroResume>(irb, scope, source_node);
2586 instruction->awaiter_handle = awaiter_handle;
2587
2588 ir_ref_instruction(awaiter_handle, irb->current_basic_block);
2589
2590 return &instruction->base;
2591}
2592
2593static IrInstruction *ir_build_coro_save(IrBuilder *irb, Scope *scope, AstNode *source_node,
2594 IrInstruction *coro_handle)
2595{
2596 IrInstructionCoroSave *instruction = ir_build_instruction<IrInstructionCoroSave>(irb, scope, source_node);
2597 instruction->coro_handle = coro_handle;
2598
2599 ir_ref_instruction(coro_handle, irb->current_basic_block);
2600
2601 return &instruction->base;
2602}
2603
2604static IrInstruction *ir_build_coro_promise(IrBuilder *irb, Scope *scope, AstNode *source_node,
2605 IrInstruction *coro_handle)
2606{
2607 IrInstructionCoroPromise *instruction = ir_build_instruction<IrInstructionCoroPromise>(irb, scope, source_node);
2608 instruction->coro_handle = coro_handle;
2609
2610 ir_ref_instruction(coro_handle, irb->current_basic_block);
2611
2612 return &instruction->base;
2613}
2614
2615static IrInstruction *ir_build_coro_alloc_helper(IrBuilder *irb, Scope *scope, AstNode *source_node,
2616 IrInstruction *alloc_fn, IrInstruction *coro_size)
2617{
2618 IrInstructionCoroAllocHelper *instruction = ir_build_instruction<IrInstructionCoroAllocHelper>(irb, scope, source_node);
2619 instruction->alloc_fn = alloc_fn;
2620 instruction->coro_size = coro_size;
2621
2622 ir_ref_instruction(alloc_fn, irb->current_basic_block);
2623 ir_ref_instruction(coro_size, irb->current_basic_block);
2624
2625 return &instruction->base;
2626}
2627
2628static IrInstruction *ir_build_atomic_rmw(IrBuilder *irb, Scope *scope, AstNode *source_node,
2629 IrInstruction *operand_type, IrInstruction *ptr, IrInstruction *op, IrInstruction *operand,
2630 IrInstruction *ordering, AtomicRmwOp resolved_op, AtomicOrder resolved_ordering)
2631{
2632 IrInstructionAtomicRmw *instruction = ir_build_instruction<IrInstructionAtomicRmw>(irb, scope, source_node);
2633 instruction->operand_type = operand_type;
2634 instruction->ptr = ptr;
2635 instruction->op = op;
2636 instruction->operand = operand;
2637 instruction->ordering = ordering;
2638 instruction->resolved_op = resolved_op;
2639 instruction->resolved_ordering = resolved_ordering;
2640
2641 if (operand_type != nullptr) ir_ref_instruction(operand_type, irb->current_basic_block);
2642 ir_ref_instruction(ptr, irb->current_basic_block);
2643 if (op != nullptr) ir_ref_instruction(op, irb->current_basic_block);
2644 ir_ref_instruction(operand, irb->current_basic_block);
2645 if (ordering != nullptr) ir_ref_instruction(ordering, irb->current_basic_block);
2646
2647 return &instruction->base;
2648}
2649
2650static IrInstruction *ir_build_promise_result_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
2651 IrInstruction *promise_type)
2652{
2653 IrInstructionPromiseResultType *instruction = ir_build_instruction<IrInstructionPromiseResultType>(irb, scope, source_node);
2654 instruction->promise_type = promise_type;
2655
2656 ir_ref_instruction(promise_type, irb->current_basic_block);
2657
2658 return &instruction->base;
2659}
2660
23992661static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
24002662 results[ReturnKindUnconditional] = 0;
24012663 results[ReturnKindError] = 0;
......@@ -2468,6 +2730,36 @@ static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) {
24682730 return nullptr;
24692731}
24702732
2733static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode *node, IrInstruction *return_value,
2734 bool is_generated_code)
2735{
2736 FnTableEntry *fn_entry = exec_fn_entry(irb->exec);
2737 bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
2738 if (!is_async) {
2739 IrInstruction *return_inst = ir_build_return(irb, scope, node, return_value);
2740 return_inst->is_gen = is_generated_code;
2741 return return_inst;
2742 }
2743
2744 if (irb->exec->coro_result_ptr_field_ptr) {
2745 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);
2746 ir_build_store_ptr(irb, scope, node, result_ptr, return_value);
2747 }
2748 IrInstruction *promise_type_val = ir_build_const_type(irb, scope, node,
2749 get_maybe_type(irb->codegen, irb->codegen->builtin_types.entry_promise));
2750 // TODO replace replacement_value with @intToPtr(?promise, 0x1) when it doesn't crash zig
2751 IrInstruction *replacement_value = irb->exec->coro_handle;
2752 IrInstruction *maybe_await_handle = ir_build_atomic_rmw(irb, scope, node,
2753 promise_type_val, irb->exec->coro_awaiter_field_ptr, nullptr, replacement_value, nullptr,
2754 AtomicRmwOp_xchg, AtomicOrderSeqCst);
2755 ir_build_store_ptr(irb, scope, node, irb->exec->await_handle_var_ptr, maybe_await_handle);
2756 IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, maybe_await_handle);
2757 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, false);
2758 return ir_build_cond_br(irb, scope, node, is_non_null, irb->exec->coro_normal_final, irb->exec->coro_early_final,
2759 is_comptime);
2760 // the above blocks are rendered by ir_gen after the rest of codegen
2761}
2762
24712763static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
24722764 assert(node->type == NodeTypeReturnExpr);
24732765
......@@ -2517,18 +2809,22 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
25172809 }
25182810
25192811 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err, err_block, ok_block, is_comptime));
2812 IrBasicBlock *ret_stmt_block = ir_create_basic_block(irb, scope, "RetStmt");
25202813
25212814 ir_set_cursor_at_end_and_append_block(irb, err_block);
25222815 ir_gen_defers_for_block(irb, scope, outer_scope, true);
2523 ir_build_return(irb, scope, node, return_value);
2816 ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);
25242817
25252818 ir_set_cursor_at_end_and_append_block(irb, ok_block);
25262819 ir_gen_defers_for_block(irb, scope, outer_scope, false);
2527 return ir_build_return(irb, scope, node, return_value);
2820 ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);
2821
2822 ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block);
2823 return ir_gen_async_return(irb, scope, node, return_value, false);
25282824 } else {
25292825 // generate unconditional defers
25302826 ir_gen_defers_for_block(irb, scope, outer_scope, false);
2531 return ir_build_return(irb, scope, node, return_value);
2827 return ir_gen_async_return(irb, scope, node, return_value, false);
25322828 }
25332829 }
25342830 case ReturnKindError:
......@@ -2548,7 +2844,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
25482844 ir_set_cursor_at_end_and_append_block(irb, return_block);
25492845 ir_gen_defers_for_block(irb, scope, outer_scope, true);
25502846 IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr);
2551 ir_build_return(irb, scope, node, err_val);
2847 ir_gen_async_return(irb, scope, node, err_val, false);
25522848
25532849 ir_set_cursor_at_end_and_append_block(irb, continue_block);
25542850 IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, false);
......@@ -3739,7 +4035,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
37394035 }
37404036 FnInline fn_inline = (builtin_fn->id == BuiltinFnIdInlineCall) ? FnInlineAlways : FnInlineNever;
37414037
3742 return ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, fn_inline);
4038 return ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, fn_inline, false, nullptr);
37434039 }
37444040 case BuiltinFnIdTypeId:
37454041 {
......@@ -3849,6 +4145,38 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
38494145 {
38504146 return ir_build_error_return_trace(irb, scope, node);
38514147 }
4148 case BuiltinFnIdAtomicRmw:
4149 {
4150 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4151 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4152 if (arg0_value == irb->codegen->invalid_instruction)
4153 return arg0_value;
4154
4155 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4156 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
4157 if (arg1_value == irb->codegen->invalid_instruction)
4158 return arg1_value;
4159
4160 AstNode *arg2_node = node->data.fn_call_expr.params.at(2);
4161 IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope);
4162 if (arg2_value == irb->codegen->invalid_instruction)
4163 return arg2_value;
4164
4165 AstNode *arg3_node = node->data.fn_call_expr.params.at(3);
4166 IrInstruction *arg3_value = ir_gen_node(irb, arg3_node, scope);
4167 if (arg3_value == irb->codegen->invalid_instruction)
4168 return arg3_value;
4169
4170 AstNode *arg4_node = node->data.fn_call_expr.params.at(4);
4171 IrInstruction *arg4_value = ir_gen_node(irb, arg4_node, scope);
4172 if (arg4_value == irb->codegen->invalid_instruction)
4173 return arg4_value;
4174
4175 return ir_build_atomic_rmw(irb, scope, node, arg0_value, arg1_value, arg2_value, arg3_value,
4176 arg4_value,
4177 // these 2 values don't mean anything since we passed non-null values for other args
4178 AtomicRmwOp_xchg, AtomicOrderMonotonic);
4179 }
38524180 }
38534181 zig_unreachable();
38544182}
......@@ -3873,7 +4201,17 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
38734201 return args[i];
38744202 }
38754203
3876 return ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto);
4204 bool is_async = node->data.fn_call_expr.is_async;
4205 IrInstruction *async_allocator = nullptr;
4206 if (is_async) {
4207 if (node->data.fn_call_expr.async_allocator) {
4208 async_allocator = ir_gen_node(irb, node->data.fn_call_expr.async_allocator, scope);
4209 if (async_allocator == irb->codegen->invalid_instruction)
4210 return async_allocator;
4211 }
4212 }
4213
4214 return ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, is_async, async_allocator);
38774215}
38784216
38794217static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
......@@ -5604,6 +5942,187 @@ static IrInstruction *ir_gen_fn_proto(IrBuilder *irb, Scope *parent_scope, AstNo
56045942 return ir_build_fn_proto(irb, parent_scope, node, param_types, align_value, return_type, is_var_args);
56055943}
56065944
5945static IrInstruction *ir_gen_cancel(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
5946 assert(node->type == NodeTypeCancel);
5947
5948 IrInstruction *target_inst = ir_gen_node(irb, node->data.cancel_expr.expr, parent_scope);
5949 if (target_inst == irb->codegen->invalid_instruction)
5950 return irb->codegen->invalid_instruction;
5951
5952 return ir_build_cancel(irb, parent_scope, node, target_inst);
5953}
5954
5955static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
5956 assert(node->type == NodeTypeResume);
5957
5958 IrInstruction *target_inst = ir_gen_node(irb, node->data.resume_expr.expr, parent_scope);
5959 if (target_inst == irb->codegen->invalid_instruction)
5960 return irb->codegen->invalid_instruction;
5961
5962 return ir_build_coro_resume(irb, parent_scope, node, target_inst);
5963}
5964
5965static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
5966 assert(node->type == NodeTypeAwaitExpr);
5967
5968 IrInstruction *target_inst = ir_gen_node(irb, node->data.await_expr.expr, parent_scope);
5969 if (target_inst == irb->codegen->invalid_instruction)
5970 return irb->codegen->invalid_instruction;
5971
5972 FnTableEntry *fn_entry = exec_fn_entry(irb->exec);
5973 if (!fn_entry) {
5974 add_node_error(irb->codegen, node, buf_sprintf("await outside function definition"));
5975 return irb->codegen->invalid_instruction;
5976 }
5977 if (fn_entry->type_entry->data.fn.fn_type_id.cc != CallingConventionAsync) {
5978 add_node_error(irb->codegen, node, buf_sprintf("await in non-async function"));
5979 return irb->codegen->invalid_instruction;
5980 }
5981
5982 ScopeDeferExpr *scope_defer_expr = get_scope_defer_expr(parent_scope);
5983 if (scope_defer_expr) {
5984 if (!scope_defer_expr->reported_err) {
5985 add_node_error(irb->codegen, node, buf_sprintf("cannot await inside defer expression"));
5986 scope_defer_expr->reported_err = true;
5987 }
5988 return irb->codegen->invalid_instruction;
5989 }
5990
5991 Scope *outer_scope = irb->exec->begin_scope;
5992
5993 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, parent_scope, node, target_inst);
5994 Buf *result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME);
5995 IrInstruction *result_ptr_field_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr, result_ptr_field_name);
5996
5997 Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME);
5998 IrInstruction *awaiter_field_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr,
5999 awaiter_handle_field_name);
6000
6001 IrInstruction *const_bool_false = ir_build_const_bool(irb, parent_scope, node, false);
6002 VariableTableEntry *result_var = ir_create_var(irb, node, parent_scope, nullptr,
6003 false, false, true, const_bool_false);
6004 IrInstruction *undefined_value = ir_build_const_undefined(irb, parent_scope, node);
6005 IrInstruction *target_promise_type = ir_build_typeof(irb, parent_scope, node, target_inst);
6006 IrInstruction *promise_result_type = ir_build_promise_result_type(irb, parent_scope, node, target_promise_type);
6007 ir_build_var_decl(irb, parent_scope, node, result_var, promise_result_type, nullptr, undefined_value);
6008 IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, parent_scope, node, result_var, false, false);
6009 ir_build_store_ptr(irb, parent_scope, node, result_ptr_field_ptr, my_result_var_ptr);
6010 IrInstruction *save_token = ir_build_coro_save(irb, parent_scope, node, irb->exec->coro_handle);
6011 IrInstruction *promise_type_val = ir_build_const_type(irb, parent_scope, node,
6012 get_maybe_type(irb->codegen, irb->codegen->builtin_types.entry_promise));
6013 IrInstruction *maybe_await_handle = ir_build_atomic_rmw(irb, parent_scope, node,
6014 promise_type_val, awaiter_field_ptr, nullptr, irb->exec->coro_handle, nullptr,
6015 AtomicRmwOp_xchg, AtomicOrderSeqCst);
6016 IrInstruction *is_non_null = ir_build_test_nonnull(irb, parent_scope, node, maybe_await_handle);
6017 IrBasicBlock *yes_suspend_block = ir_create_basic_block(irb, parent_scope, "YesSuspend");
6018 IrBasicBlock *no_suspend_block = ir_create_basic_block(irb, parent_scope, "NoSuspend");
6019 IrBasicBlock *merge_block = ir_create_basic_block(irb, parent_scope, "Merge");
6020 ir_build_cond_br(irb, parent_scope, node, is_non_null, no_suspend_block, yes_suspend_block, const_bool_false);
6021
6022 ir_set_cursor_at_end_and_append_block(irb, no_suspend_block);
6023 Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);
6024 IrInstruction *promise_result_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr, result_field_name);
6025 IrInstruction *no_suspend_result = ir_build_load_ptr(irb, parent_scope, node, promise_result_ptr);
6026 ir_build_cancel(irb, parent_scope, node, target_inst);
6027 ir_build_br(irb, parent_scope, node, merge_block, const_bool_false);
6028
6029 ir_set_cursor_at_end_and_append_block(irb, yes_suspend_block);
6030 IrInstruction *suspend_code = ir_build_coro_suspend(irb, parent_scope, node, save_token, const_bool_false);
6031 IrBasicBlock *cleanup_block = ir_create_basic_block(irb, parent_scope, "SuspendCleanup");
6032 IrBasicBlock *resume_block = ir_create_basic_block(irb, parent_scope, "SuspendResume");
6033
6034 IrInstructionSwitchBrCase *cases = allocate<IrInstructionSwitchBrCase>(2);
6035 cases[0].value = ir_build_const_u8(irb, parent_scope, node, 0);
6036 cases[0].block = resume_block;
6037 cases[1].value = ir_build_const_u8(irb, parent_scope, node, 1);
6038 cases[1].block = cleanup_block;
6039 ir_build_switch_br(irb, parent_scope, node, suspend_code, irb->exec->coro_suspend_block,
6040 2, cases, const_bool_false);
6041
6042 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);
6043 ir_gen_defers_for_block(irb, parent_scope, outer_scope, true);
6044 ir_build_br(irb, parent_scope, node, irb->exec->coro_final_cleanup_block, const_bool_false);
6045
6046 ir_set_cursor_at_end_and_append_block(irb, resume_block);
6047 IrInstruction *yes_suspend_result = ir_build_load_ptr(irb, parent_scope, node, my_result_var_ptr);
6048 ir_build_br(irb, parent_scope, node, merge_block, const_bool_false);
6049
6050 ir_set_cursor_at_end_and_append_block(irb, merge_block);
6051 IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2);
6052 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
6053 incoming_blocks[0] = resume_block;
6054 incoming_values[0] = yes_suspend_result;
6055 incoming_blocks[1] = no_suspend_block;
6056 incoming_values[1] = no_suspend_result;
6057 return ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values);
6058}
6059
6060static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
6061 assert(node->type == NodeTypeSuspend);
6062
6063 FnTableEntry *fn_entry = exec_fn_entry(irb->exec);
6064 if (!fn_entry) {
6065 add_node_error(irb->codegen, node, buf_sprintf("suspend outside function definition"));
6066 return irb->codegen->invalid_instruction;
6067 }
6068 if (fn_entry->type_entry->data.fn.fn_type_id.cc != CallingConventionAsync) {
6069 add_node_error(irb->codegen, node, buf_sprintf("suspend in non-async function"));
6070 return irb->codegen->invalid_instruction;
6071 }
6072
6073 ScopeDeferExpr *scope_defer_expr = get_scope_defer_expr(parent_scope);
6074 if (scope_defer_expr) {
6075 if (!scope_defer_expr->reported_err) {
6076 add_node_error(irb->codegen, node, buf_sprintf("cannot suspend inside defer expression"));
6077 scope_defer_expr->reported_err = true;
6078 }
6079 return irb->codegen->invalid_instruction;
6080 }
6081
6082 Scope *outer_scope = irb->exec->begin_scope;
6083
6084
6085 IrInstruction *suspend_code;
6086 IrInstruction *const_bool_false = ir_build_const_bool(irb, parent_scope, node, false);
6087 if (node->data.suspend.block == nullptr) {
6088 suspend_code = ir_build_coro_suspend(irb, parent_scope, node, nullptr, const_bool_false);
6089 } else {
6090 assert(node->data.suspend.promise_symbol != nullptr);
6091 assert(node->data.suspend.promise_symbol->type == NodeTypeSymbol);
6092 Buf *promise_symbol_name = node->data.suspend.promise_symbol->data.symbol_expr.symbol;
6093 Scope *child_scope;
6094 if (!buf_eql_str(promise_symbol_name, "_")) {
6095 VariableTableEntry *promise_var = ir_create_var(irb, node, parent_scope, promise_symbol_name,
6096 true, true, false, const_bool_false);
6097 ir_build_var_decl(irb, parent_scope, node, promise_var, nullptr, nullptr, irb->exec->coro_handle);
6098 child_scope = promise_var->child_scope;
6099 } else {
6100 child_scope = parent_scope;
6101 }
6102 IrInstruction *save_token = ir_build_coro_save(irb, child_scope, node, irb->exec->coro_handle);
6103 ir_gen_node(irb, node->data.suspend.block, child_scope);
6104 suspend_code = ir_build_coro_suspend(irb, parent_scope, node, save_token, const_bool_false);
6105 }
6106
6107 IrBasicBlock *cleanup_block = ir_create_basic_block(irb, parent_scope, "SuspendCleanup");
6108 IrBasicBlock *resume_block = ir_create_basic_block(irb, parent_scope, "SuspendResume");
6109
6110 IrInstructionSwitchBrCase *cases = allocate<IrInstructionSwitchBrCase>(2);
6111 cases[0].value = ir_build_const_u8(irb, parent_scope, node, 0);
6112 cases[0].block = resume_block;
6113 cases[1].value = ir_build_const_u8(irb, parent_scope, node, 1);
6114 cases[1].block = cleanup_block;
6115 ir_build_switch_br(irb, parent_scope, node, suspend_code, irb->exec->coro_suspend_block,
6116 2, cases, const_bool_false);
6117
6118 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);
6119 ir_gen_defers_for_block(irb, parent_scope, outer_scope, true);
6120 ir_build_br(irb, parent_scope, node, irb->exec->coro_final_cleanup_block, const_bool_false);
6121
6122 ir_set_cursor_at_end_and_append_block(irb, resume_block);
6123 return ir_build_const_void(irb, parent_scope, node);
6124}
6125
56076126static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope,
56086127 LVal lval)
56096128{
......@@ -5700,6 +6219,14 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
57006219 return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval);
57016220 case NodeTypeErrorSetDecl:
57026221 return ir_lval_wrap(irb, scope, ir_gen_err_set_decl(irb, scope, node), lval);
6222 case NodeTypeCancel:
6223 return ir_lval_wrap(irb, scope, ir_gen_cancel(irb, scope, node), lval);
6224 case NodeTypeResume:
6225 return ir_lval_wrap(irb, scope, ir_gen_resume(irb, scope, node), lval);
6226 case NodeTypeAwaitExpr:
6227 return ir_lval_wrap(irb, scope, ir_gen_await_expr(irb, scope, node), lval);
6228 case NodeTypeSuspend:
6229 return ir_lval_wrap(irb, scope, ir_gen_suspend(irb, scope, node), lval);
57036230 }
57046231 zig_unreachable();
57056232}
......@@ -5728,6 +6255,7 @@ static void invalidate_exec(IrExecutable *exec) {
57286255 invalidate_exec(exec->source_exec);
57296256}
57306257
6258
57316259bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_executable) {
57326260 assert(node->owner);
57336261
......@@ -5742,13 +6270,162 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
57426270 // Entry block gets a reference because we enter it to begin.
57436271 ir_ref_bb(irb->current_basic_block);
57446272
6273 FnTableEntry *fn_entry = exec_fn_entry(irb->exec);
6274 bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
6275 IrInstruction *coro_id;
6276 IrInstruction *u8_ptr_type;
6277 IrInstruction *const_bool_false;
6278 IrInstruction *coro_result_field_ptr;
6279 TypeTableEntry *return_type;
6280 Buf *result_ptr_field_name;
6281 VariableTableEntry *coro_size_var;
6282 if (is_async) {
6283 // create the coro promise
6284 const_bool_false = ir_build_const_bool(irb, scope, node, false);
6285 VariableTableEntry *promise_var = ir_create_var(irb, node, scope, nullptr, false, false, true, const_bool_false);
6286
6287 return_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
6288 IrInstruction *promise_init = ir_build_const_promise_init(irb, scope, node, return_type);
6289 ir_build_var_decl(irb, scope, node, promise_var, nullptr, nullptr, promise_init);
6290 IrInstruction *coro_promise_ptr = ir_build_var_ptr(irb, scope, node, promise_var, false, false);
6291
6292 VariableTableEntry *await_handle_var = ir_create_var(irb, node, scope, nullptr, false, false, true, const_bool_false);
6293 IrInstruction *null_value = ir_build_const_null(irb, scope, node);
6294 IrInstruction *await_handle_type_val = ir_build_const_type(irb, scope, node,
6295 get_maybe_type(irb->codegen, irb->codegen->builtin_types.entry_promise));
6296 ir_build_var_decl(irb, scope, node, await_handle_var, await_handle_type_val, nullptr, null_value);
6297 irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, scope, node,
6298 await_handle_var, false, false);
6299
6300 u8_ptr_type = ir_build_const_type(irb, scope, node,
6301 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));
6302 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, coro_promise_ptr);
6303 coro_id = ir_build_coro_id(irb, scope, node, promise_as_u8_ptr);
6304 coro_size_var = ir_create_var(irb, node, scope, nullptr, false, false, true, const_bool_false);
6305 IrInstruction *coro_size = ir_build_coro_size(irb, scope, node);
6306 ir_build_var_decl(irb, scope, node, coro_size_var, nullptr, nullptr, coro_size);
6307 IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node,
6308 ImplicitAllocatorIdArg);
6309 irb->exec->coro_allocator_var = ir_create_var(irb, node, scope, nullptr, true, true, true, const_bool_false);
6310 ir_build_var_decl(irb, scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr);
6311 Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);
6312 IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, alloc_field_name);
6313 IrInstruction *alloc_fn = ir_build_load_ptr(irb, scope, node, alloc_fn_ptr);
6314 IrInstruction *maybe_coro_mem_ptr = ir_build_coro_alloc_helper(irb, scope, node, alloc_fn, coro_size);
6315 IrInstruction *alloc_result_is_ok = ir_build_test_nonnull(irb, scope, node, maybe_coro_mem_ptr);
6316 IrBasicBlock *alloc_err_block = ir_create_basic_block(irb, scope, "AllocError");
6317 IrBasicBlock *alloc_ok_block = ir_create_basic_block(irb, scope, "AllocOk");
6318 ir_build_cond_br(irb, scope, node, alloc_result_is_ok, alloc_ok_block, alloc_err_block, const_bool_false);
6319
6320 ir_set_cursor_at_end_and_append_block(irb, alloc_err_block);
6321 IrInstruction *undef = ir_build_const_undefined(irb, scope, node);
6322 ir_build_return(irb, scope, node, undef);
6323
6324 ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);
6325 IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, maybe_coro_mem_ptr);
6326 irb->exec->coro_handle = ir_build_coro_begin(irb, scope, node, coro_id, coro_mem_ptr);
6327
6328 Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME);
6329 irb->exec->coro_awaiter_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
6330 awaiter_handle_field_name);
6331 if (type_has_bits(return_type)) {
6332 Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);
6333 coro_result_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name);
6334 result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME);
6335 irb->exec->coro_result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
6336 result_ptr_field_name);
6337 ir_build_store_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr, coro_result_field_ptr);
6338 }
6339
6340
6341 irb->exec->coro_early_final = ir_create_basic_block(irb, scope, "CoroEarlyFinal");
6342 irb->exec->coro_normal_final = ir_create_basic_block(irb, scope, "CoroNormalFinal");
6343 irb->exec->coro_suspend_block = ir_create_basic_block(irb, scope, "Suspend");
6344 irb->exec->coro_final_cleanup_block = ir_create_basic_block(irb, scope, "FinalCleanup");
6345 }
6346
57456347 IrInstruction *result = ir_gen_node_extra(irb, node, scope, LVAL_NONE);
57466348 assert(result);
57476349 if (irb->exec->invalid)
57486350 return false;
57496351
57506352 if (!instr_is_unreachable(result)) {
5751 ir_mark_gen(ir_build_return(irb, scope, result->source_node, result));
6353 ir_gen_async_return(irb, scope, result->source_node, result, true);
6354 }
6355
6356 if (is_async) {
6357 IrBasicBlock *invalid_resume_block = ir_create_basic_block(irb, scope, "InvalidResume");
6358 IrBasicBlock *check_free_block = ir_create_basic_block(irb, scope, "CheckFree");
6359
6360 ir_set_cursor_at_end_and_append_block(irb, irb->exec->coro_early_final);
6361 IrInstruction *const_bool_true = ir_build_const_bool(irb, scope, node, true);
6362 IrInstruction *suspend_code = ir_build_coro_suspend(irb, scope, node, nullptr, const_bool_true);
6363 IrInstructionSwitchBrCase *cases = allocate<IrInstructionSwitchBrCase>(2);
6364 cases[0].value = ir_build_const_u8(irb, scope, node, 0);
6365 cases[0].block = invalid_resume_block;
6366 cases[1].value = ir_build_const_u8(irb, scope, node, 1);
6367 cases[1].block = irb->exec->coro_final_cleanup_block;
6368 ir_build_switch_br(irb, scope, node, suspend_code, irb->exec->coro_suspend_block, 2, cases, const_bool_false);
6369
6370 ir_set_cursor_at_end_and_append_block(irb, irb->exec->coro_suspend_block);
6371 ir_build_coro_end(irb, scope, node);
6372 ir_build_return(irb, scope, node, irb->exec->coro_handle);
6373
6374 ir_set_cursor_at_end_and_append_block(irb, invalid_resume_block);
6375 ir_build_unreachable(irb, scope, node);
6376
6377 ir_set_cursor_at_end_and_append_block(irb, irb->exec->coro_normal_final);
6378 ir_build_br(irb, scope, node, check_free_block, const_bool_false);
6379
6380 ir_set_cursor_at_end_and_append_block(irb, irb->exec->coro_final_cleanup_block);
6381 if (type_has_bits(return_type)) {
6382 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);
6383 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, result_ptr);
6384 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type,
6385 coro_result_field_ptr);
6386 IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,
6387 fn_entry->type_entry->data.fn.fn_type_id.return_type);
6388 IrInstruction *size_of_ret_val = ir_build_size_of(irb, scope, node, return_type_inst);
6389 ir_build_memcpy(irb, scope, node, result_ptr_as_u8_ptr, return_value_ptr_as_u8_ptr, size_of_ret_val);
6390 }
6391 ir_build_br(irb, scope, node, check_free_block, const_bool_false);
6392
6393 ir_set_cursor_at_end_and_append_block(irb, check_free_block);
6394 IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2);
6395 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
6396 incoming_blocks[0] = irb->exec->coro_final_cleanup_block;
6397 incoming_values[0] = const_bool_false;
6398 incoming_blocks[1] = irb->exec->coro_normal_final;
6399 incoming_values[1] = const_bool_true;
6400 IrInstruction *resume_awaiter = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
6401
6402 Buf *free_field_name = buf_create_from_str(ASYNC_FREE_FIELD_NAME);
6403 IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node,
6404 ImplicitAllocatorIdLocalVar);
6405 IrInstruction *free_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, free_field_name);
6406 IrInstruction *free_fn = ir_build_load_ptr(irb, scope, node, free_fn_ptr);
6407 IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);
6408 IrInstruction *coro_mem_ptr_maybe = ir_build_coro_free(irb, scope, node, coro_id, irb->exec->coro_handle);
6409 IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, coro_mem_ptr_maybe);
6410 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
6411 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var, true, false);
6412 IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);
6413 IrInstruction *mem_slice = ir_build_slice(irb, scope, node, coro_mem_ptr_ref, zero, coro_size, false);
6414 size_t arg_count = 2;
6415 IrInstruction **args = allocate<IrInstruction *>(arg_count);
6416 args[0] = implicit_allocator_ptr; // self
6417 args[1] = mem_slice; // old_mem
6418 ir_build_call(irb, scope, node, nullptr, free_fn, arg_count, args, false, FnInlineAuto, false, nullptr);
6419
6420 IrBasicBlock *resume_block = ir_create_basic_block(irb, scope, "Resume");
6421 ir_build_cond_br(irb, scope, node, resume_awaiter, resume_block, irb->exec->coro_suspend_block, const_bool_false);
6422
6423 ir_set_cursor_at_end_and_append_block(irb, resume_block);
6424 IrInstruction *unwrapped_await_handle_ptr = ir_build_unwrap_maybe(irb, scope, node,
6425 irb->exec->await_handle_var_ptr, false);
6426 IrInstruction *awaiter_handle = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr);
6427 ir_build_coro_resume(irb, scope, node, awaiter_handle);
6428 ir_build_br(irb, scope, node, irb->exec->coro_suspend_block, const_bool_false);
57526429 }
57536430
57546431 return true;
......@@ -6705,6 +7382,12 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
67057382 return result;
67067383 }
67077384
7385 if (expected_type == ira->codegen->builtin_types.entry_promise &&
7386 actual_type->id == TypeTableEntryIdPromise)
7387 {
7388 return result;
7389 }
7390
67087391 // fn
67097392 if (expected_type->id == TypeTableEntryIdFn &&
67107393 actual_type->id == TypeTableEntryIdFn)
......@@ -6736,6 +7419,16 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, TypeTableEntry
67367419 return result;
67377420 }
67387421 }
7422 if (!expected_type->data.fn.is_generic && expected_type->data.fn.fn_type_id.cc == CallingConventionAsync) {
7423 ConstCastOnly child = types_match_const_cast_only(ira, actual_type->data.fn.fn_type_id.async_allocator_type,
7424 expected_type->data.fn.fn_type_id.async_allocator_type, source_node);
7425 if (child.id != ConstCastResultIdOk) {
7426 result.id = ConstCastResultIdAsyncAllocatorType;
7427 result.data.async_allocator_type = allocate_nonzero<ConstCastOnly>(1);
7428 *result.data.async_allocator_type = child;
7429 return result;
7430 }
7431 }
67397432 if (expected_type->data.fn.fn_type_id.param_count != actual_type->data.fn.fn_type_id.param_count) {
67407433 result.id = ConstCastResultIdFnArgCount;
67417434 return result;
......@@ -9224,15 +9917,35 @@ static bool ir_resolve_comptime(IrAnalyze *ira, IrInstruction *value, bool *out)
92249917 return ir_resolve_bool(ira, value, out);
92259918}
92269919
9227static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, AtomicOrder *out) {
9920static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, AtomicOrder *out) {
9921 if (type_is_invalid(value->value.type))
9922 return false;
9923
9924 ConstExprValue *atomic_order_val = get_builtin_value(ira->codegen, "AtomicOrder");
9925 assert(atomic_order_val->type->id == TypeTableEntryIdMetaType);
9926 TypeTableEntry *atomic_order_type = atomic_order_val->data.x_type;
9927
9928 IrInstruction *casted_value = ir_implicit_cast(ira, value, atomic_order_type);
9929 if (type_is_invalid(casted_value->value.type))
9930 return false;
9931
9932 ConstExprValue *const_val = ir_resolve_const(ira, casted_value, UndefBad);
9933 if (!const_val)
9934 return false;
9935
9936 *out = (AtomicOrder)bigint_as_unsigned(&const_val->data.x_enum_tag);
9937 return true;
9938}
9939
9940static bool ir_resolve_atomic_rmw_op(IrAnalyze *ira, IrInstruction *value, AtomicRmwOp *out) {
92289941 if (type_is_invalid(value->value.type))
92299942 return false;
92309943
9231 ConstExprValue *atomic_order_val = get_builtin_value(ira->codegen, "AtomicOrder");
9232 assert(atomic_order_val->type->id == TypeTableEntryIdMetaType);
9233 TypeTableEntry *atomic_order_type = atomic_order_val->data.x_type;
9944 ConstExprValue *atomic_rmw_op_val = get_builtin_value(ira->codegen, "AtomicRmwOp");
9945 assert(atomic_rmw_op_val->type->id == TypeTableEntryIdMetaType);
9946 TypeTableEntry *atomic_rmw_op_type = atomic_rmw_op_val->data.x_type;
92349947
9235 IrInstruction *casted_value = ir_implicit_cast(ira, value, atomic_order_type);
9948 IrInstruction *casted_value = ir_implicit_cast(ira, value, atomic_rmw_op_type);
92369949 if (type_is_invalid(casted_value->value.type))
92379950 return false;
92389951
......@@ -9240,7 +9953,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic
92409953 if (!const_val)
92419954 return false;
92429955
9243 *out = (AtomicOrder)bigint_as_unsigned(&const_val->data.x_enum_tag);
9956 *out = (AtomicRmwOp)bigint_as_unsigned(&const_val->data.x_enum_tag);
92449957 return true;
92459958}
92469959
......@@ -9342,8 +10055,11 @@ static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira,
934210055 ir_add_error(ira, casted_value, buf_sprintf("function returns address of local variable"));
934310056 return ir_unreach_error(ira);
934410057 }
9345 ir_build_return_from(&ira->new_irb, &return_instruction->base, casted_value);
9346 return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
10058 IrInstruction *result = ir_build_return(&ira->new_irb, return_instruction->base.scope,
10059 return_instruction->base.source_node, casted_value);
10060 result->value.type = ira->codegen->builtin_types.entry_unreachable;
10061 ir_link_new_instruction(result, &return_instruction->base);
10062 return ir_finish_anal(ira, result->value.type);
934710063}
934810064
934910065static TypeTableEntry *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *const_instruction) {
......@@ -9568,6 +10284,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
956810284 case TypeTableEntryIdBlock:
956910285 case TypeTableEntryIdBoundFn:
957010286 case TypeTableEntryIdArgTuple:
10287 case TypeTableEntryIdPromise:
957110288 if (!is_equality_cmp) {
957210289 ir_add_error_node(ira, source_node,
957310290 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
......@@ -10397,6 +11114,7 @@ static VarClassRequired get_var_class_required(TypeTableEntry *type_entry) {
1039711114 case TypeTableEntryIdVoid:
1039811115 case TypeTableEntryIdErrorSet:
1039911116 case TypeTableEntryIdFn:
11117 case TypeTableEntryIdPromise:
1040011118 return VarClassRequiredAny;
1040111119 case TypeTableEntryIdNumLitFloat:
1040211120 case TypeTableEntryIdNumLitInt:
......@@ -10573,6 +11291,11 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi
1057311291 buf_sprintf("exported function must specify calling convention"));
1057411292 add_error_note(ira->codegen, msg, fn_entry->proto_node, buf_sprintf("declared here"));
1057511293 } break;
11294 case CallingConventionAsync: {
11295 ErrorMsg *msg = ir_add_error(ira, target,
11296 buf_sprintf("exported function cannot be async"));
11297 add_error_note(ira->codegen, msg, fn_entry->proto_node, buf_sprintf("declared here"));
11298 } break;
1057611299 case CallingConventionC:
1057711300 case CallingConventionNaked:
1057811301 case CallingConventionCold:
......@@ -10662,6 +11385,7 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi
1066211385 case TypeTableEntryIdBoundFn:
1066311386 case TypeTableEntryIdArgTuple:
1066411387 case TypeTableEntryIdOpaque:
11388 case TypeTableEntryIdPromise:
1066511389 ir_add_error(ira, target,
1066611390 buf_sprintf("invalid export target '%s'", buf_ptr(&type_value->name)));
1066711391 break;
......@@ -10686,6 +11410,7 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi
1068611410 case TypeTableEntryIdBoundFn:
1068711411 case TypeTableEntryIdArgTuple:
1068811412 case TypeTableEntryIdOpaque:
11413 case TypeTableEntryIdPromise:
1068911414 ir_add_error(ira, target,
1069011415 buf_sprintf("invalid export target type '%s'", buf_ptr(&target->value.type->name)));
1069111416 break;
......@@ -10738,6 +11463,81 @@ static TypeTableEntry *ir_analyze_instruction_error_union(IrAnalyze *ira,
1073811463 return ira->codegen->builtin_types.entry_type;
1073911464}
1074011465
11466IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_instr, ImplicitAllocatorId id) {
11467 FnTableEntry *parent_fn_entry = exec_fn_entry(ira->new_irb.exec);
11468 if (parent_fn_entry == nullptr) {
11469 ir_add_error(ira, source_instr, buf_sprintf("no implicit allocator available"));
11470 return ira->codegen->invalid_instruction;
11471 }
11472
11473 FnTypeId *parent_fn_type = &parent_fn_entry->type_entry->data.fn.fn_type_id;
11474 if (parent_fn_type->cc != CallingConventionAsync) {
11475 ir_add_error(ira, source_instr, buf_sprintf("async function call from non-async caller requires allocator parameter"));
11476 return ira->codegen->invalid_instruction;
11477 }
11478
11479 assert(parent_fn_type->async_allocator_type != nullptr);
11480
11481 switch (id) {
11482 case ImplicitAllocatorIdArg:
11483 {
11484 IrInstruction *result = ir_build_get_implicit_allocator(&ira->new_irb, source_instr->scope,
11485 source_instr->source_node, ImplicitAllocatorIdArg);
11486 result->value.type = parent_fn_type->async_allocator_type;
11487 return result;
11488 }
11489 case ImplicitAllocatorIdLocalVar:
11490 {
11491 VariableTableEntry *coro_allocator_var = ira->old_irb.exec->coro_allocator_var;
11492 assert(coro_allocator_var != nullptr);
11493 IrInstruction *var_ptr_inst = ir_get_var_ptr(ira, source_instr, coro_allocator_var, true, false);
11494 IrInstruction *result = ir_get_deref(ira, source_instr, var_ptr_inst);
11495 assert(result->value.type != nullptr);
11496 return result;
11497 }
11498 }
11499 zig_unreachable();
11500}
11501
11502static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *call_instruction, FnTableEntry *fn_entry, TypeTableEntry *fn_type,
11503 IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count, IrInstruction *async_allocator_inst)
11504{
11505 Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);
11506 //Buf *free_field_name = buf_create_from_str("freeFn");
11507 assert(async_allocator_inst->value.type->id == TypeTableEntryIdPointer);
11508 TypeTableEntry *container_type = async_allocator_inst->value.type->data.pointer.child_type;
11509 IrInstruction *field_ptr_inst = ir_analyze_container_field_ptr(ira, alloc_field_name, &call_instruction->base,
11510 async_allocator_inst, container_type);
11511 if (type_is_invalid(field_ptr_inst->value.type)) {
11512 return ira->codegen->invalid_instruction;
11513 }
11514 TypeTableEntry *ptr_to_alloc_fn_type = field_ptr_inst->value.type;
11515 assert(ptr_to_alloc_fn_type->id == TypeTableEntryIdPointer);
11516
11517 TypeTableEntry *alloc_fn_type = ptr_to_alloc_fn_type->data.pointer.child_type;
11518 if (alloc_fn_type->id != TypeTableEntryIdFn) {
11519 ir_add_error(ira, &call_instruction->base,
11520 buf_sprintf("expected allocation function, found '%s'", buf_ptr(&alloc_fn_type->name)));
11521 return ira->codegen->invalid_instruction;
11522 }
11523
11524 TypeTableEntry *alloc_fn_return_type = alloc_fn_type->data.fn.fn_type_id.return_type;
11525 if (alloc_fn_return_type->id != TypeTableEntryIdErrorUnion) {
11526 ir_add_error(ira, fn_ref,
11527 buf_sprintf("expected allocation function to return error union, but it returns '%s'", buf_ptr(&alloc_fn_return_type->name)));
11528 return ira->codegen->invalid_instruction;
11529 }
11530 TypeTableEntry *alloc_fn_error_set_type = alloc_fn_return_type->data.error_union.err_set_type;
11531 TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;
11532 TypeTableEntry *promise_type = get_promise_type(ira->codegen, return_type);
11533 TypeTableEntry *async_return_type = get_error_union_type(ira->codegen, alloc_fn_error_set_type, promise_type);
11534
11535 IrInstruction *result = ir_build_call(&ira->new_irb, call_instruction->base.scope, call_instruction->base.source_node,
11536 fn_entry, fn_ref, arg_count, casted_args, false, FnInlineAuto, true, async_allocator_inst);
11537 result->value.type = async_return_type;
11538 return result;
11539}
11540
1074111541static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node,
1074211542 IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i)
1074311543{
......@@ -10952,6 +11752,20 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1095211752 }
1095311753 return ira->codegen->builtin_types.entry_invalid;
1095411754 }
11755 if (fn_type_id->cc == CallingConventionAsync && !call_instruction->is_async) {
11756 ErrorMsg *msg = ir_add_error(ira, fn_ref, buf_sprintf("must use async keyword to call async function"));
11757 if (fn_proto_node) {
11758 add_error_note(ira->codegen, msg, fn_proto_node, buf_sprintf("declared here"));
11759 }
11760 return ira->codegen->builtin_types.entry_invalid;
11761 }
11762 if (fn_type_id->cc != CallingConventionAsync && call_instruction->is_async) {
11763 ErrorMsg *msg = ir_add_error(ira, fn_ref, buf_sprintf("cannot use async keyword to call non-async function"));
11764 if (fn_proto_node) {
11765 add_error_note(ira->codegen, msg, fn_proto_node, buf_sprintf("declared here"));
11766 }
11767 return ira->codegen->builtin_types.entry_invalid;
11768 }
1095511769
1095611770
1095711771 if (fn_type_id->is_var_args) {
......@@ -11078,6 +11892,11 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1107811892 buf_sprintf("calling a generic function requires compile-time known function value"));
1107911893 return ira->codegen->builtin_types.entry_invalid;
1108011894 }
11895 if (call_instruction->is_async && fn_type_id->is_var_args) {
11896 ir_add_error(ira, call_instruction->fn_ref,
11897 buf_sprintf("compiler bug: TODO: implement var args async functions. https://github.com/zig-lang/zig/issues/557"));
11898 return ira->codegen->builtin_types.entry_invalid;
11899 }
1108111900
1108211901 // Count the arguments of the function type id we are creating
1108311902 size_t new_fn_arg_count = first_arg_1_or_0;
......@@ -11226,6 +12045,36 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1122612045 return ir_analyze_fn_call(ira, call_instruction, fn_entry, fn_type, fn_ref, first_arg_ptr, true, FnInlineAuto);
1122712046 }
1122812047 }
12048 IrInstruction *async_allocator_inst = nullptr;
12049 if (call_instruction->is_async) {
12050 AstNode *async_allocator_type_node = fn_proto_node->data.fn_proto.async_allocator_type;
12051 if (async_allocator_type_node != nullptr) {
12052 TypeTableEntry *async_allocator_type = analyze_type_expr(ira->codegen, impl_fn->child_scope, async_allocator_type_node);
12053 if (type_is_invalid(async_allocator_type))
12054 return ira->codegen->builtin_types.entry_invalid;
12055 inst_fn_type_id.async_allocator_type = async_allocator_type;
12056 }
12057 IrInstruction *uncasted_async_allocator_inst;
12058 if (call_instruction->async_allocator == nullptr) {
12059 uncasted_async_allocator_inst = ir_get_implicit_allocator(ira, &call_instruction->base,
12060 ImplicitAllocatorIdLocalVar);
12061 if (type_is_invalid(uncasted_async_allocator_inst->value.type))
12062 return ira->codegen->builtin_types.entry_invalid;
12063 } else {
12064 uncasted_async_allocator_inst = call_instruction->async_allocator->other;
12065 if (type_is_invalid(uncasted_async_allocator_inst->value.type))
12066 return ira->codegen->builtin_types.entry_invalid;
12067 }
12068 if (inst_fn_type_id.async_allocator_type == nullptr) {
12069 IrInstruction *casted_inst = ir_implicit_byval_const_ref_cast(ira, uncasted_async_allocator_inst);
12070 if (type_is_invalid(casted_inst->value.type))
12071 return ira->codegen->builtin_types.entry_invalid;
12072 inst_fn_type_id.async_allocator_type = casted_inst->value.type;
12073 }
12074 async_allocator_inst = ir_implicit_cast(ira, uncasted_async_allocator_inst, inst_fn_type_id.async_allocator_type);
12075 if (type_is_invalid(async_allocator_inst->value.type))
12076 return ira->codegen->builtin_types.entry_invalid;
12077 }
1122912078
1123012079 auto existing_entry = ira->codegen->generic_table.put_unique(generic_id, impl_fn);
1123112080 if (existing_entry) {
......@@ -11245,24 +12094,34 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1124512094 ira->codegen->fn_defs.append(impl_fn);
1124612095 }
1124712096
12097 TypeTableEntry *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type;
12098 if (fn_type_can_fail(&impl_fn->type_entry->data.fn.fn_type_id)) {
12099 parent_fn_entry->calls_errorable_function = true;
12100 }
12101
1124812102 size_t impl_param_count = impl_fn->type_entry->data.fn.fn_type_id.param_count;
12103 if (call_instruction->is_async) {
12104 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry, fn_ref, casted_args, impl_param_count,
12105 async_allocator_inst);
12106 ir_link_new_instruction(result, &call_instruction->base);
12107 ir_add_alloca(ira, result, result->value.type);
12108 return ir_finish_anal(ira, result->value.type);
12109 }
12110
12111 assert(async_allocator_inst == nullptr);
1124912112 IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base,
11250 impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline);
12113 impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline,
12114 call_instruction->is_async, nullptr);
1125112115
11252 TypeTableEntry *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type;
1125312116 ir_add_alloca(ira, new_call_instruction, return_type);
1125412117
11255 if (return_type->id == TypeTableEntryIdErrorSet || return_type->id == TypeTableEntryIdErrorUnion) {
11256 parent_fn_entry->calls_errorable_function = true;
11257 }
11258
1125912118 return ir_finish_anal(ira, return_type);
1126012119 }
1126112120
1126212121 FnTableEntry *parent_fn_entry = exec_fn_entry(ira->new_irb.exec);
1126312122 assert(fn_type_id->return_type != nullptr);
1126412123 assert(parent_fn_entry != nullptr);
11265 if (fn_type_id->return_type->id == TypeTableEntryIdErrorSet || fn_type_id->return_type->id == TypeTableEntryIdErrorUnion) {
12124 if (fn_type_can_fail(fn_type_id)) {
1126612125 parent_fn_entry->calls_errorable_function = true;
1126712126 }
1126812127
......@@ -11317,8 +12176,33 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1131712176 if (type_is_invalid(return_type))
1131812177 return ira->codegen->builtin_types.entry_invalid;
1131912178
12179 if (call_instruction->is_async) {
12180 IrInstruction *uncasted_async_allocator_inst;
12181 if (call_instruction->async_allocator == nullptr) {
12182 uncasted_async_allocator_inst = ir_get_implicit_allocator(ira, &call_instruction->base,
12183 ImplicitAllocatorIdLocalVar);
12184 if (type_is_invalid(uncasted_async_allocator_inst->value.type))
12185 return ira->codegen->builtin_types.entry_invalid;
12186 } else {
12187 uncasted_async_allocator_inst = call_instruction->async_allocator->other;
12188 if (type_is_invalid(uncasted_async_allocator_inst->value.type))
12189 return ira->codegen->builtin_types.entry_invalid;
12190
12191 }
12192 IrInstruction *async_allocator_inst = ir_implicit_cast(ira, uncasted_async_allocator_inst, fn_type_id->async_allocator_type);
12193 if (type_is_invalid(async_allocator_inst->value.type))
12194 return ira->codegen->builtin_types.entry_invalid;
12195
12196 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref, casted_args, call_param_count,
12197 async_allocator_inst);
12198 ir_link_new_instruction(result, &call_instruction->base);
12199 ir_add_alloca(ira, result, result->value.type);
12200 return ir_finish_anal(ira, result->value.type);
12201 }
12202
12203
1132012204 IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base,
11321 fn_entry, fn_ref, call_param_count, casted_args, false, fn_inline);
12205 fn_entry, fn_ref, call_param_count, casted_args, false, fn_inline, false, nullptr);
1132212206
1132312207 ir_add_alloca(ira, new_call_instruction, return_type);
1132412208 return ir_finish_anal(ira, return_type);
......@@ -11444,6 +12328,7 @@ static TypeTableEntry *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op
1144412328 case TypeTableEntryIdBlock:
1144512329 case TypeTableEntryIdBoundFn:
1144612330 case TypeTableEntryIdArgTuple:
12331 case TypeTableEntryIdPromise:
1144712332 {
1144812333 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base);
1144912334 out_val->data.x_type = get_maybe_type(ira->codegen, type_entry);
......@@ -12012,8 +12897,8 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
1201212897 return return_type;
1201312898}
1201412899
12015static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira,
12016 TypeTableEntry *bare_struct_type, Buf *field_name, IrInstructionFieldPtr *field_ptr_instruction,
12900static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
12901 TypeTableEntry *bare_struct_type, Buf *field_name, IrInstruction *source_instr,
1201712902 IrInstruction *container_ptr, TypeTableEntry *container_type)
1201812903{
1201912904 if (!is_slice(bare_struct_type)) {
......@@ -12021,17 +12906,17 @@ static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira,
1202112906 auto entry = container_scope->decl_table.maybe_get(field_name);
1202212907 Tld *tld = entry ? entry->value : nullptr;
1202312908 if (tld && tld->id == TldIdFn) {
12024 resolve_top_level_decl(ira->codegen, tld, false, field_ptr_instruction->base.source_node);
12909 resolve_top_level_decl(ira->codegen, tld, false, source_instr->source_node);
1202512910 if (tld->resolution == TldResolutionInvalid)
12026 return ira->codegen->builtin_types.entry_invalid;
12911 return ira->codegen->invalid_instruction;
1202712912 TldFn *tld_fn = (TldFn *)tld;
1202812913 FnTableEntry *fn_entry = tld_fn->fn_entry;
1202912914 if (type_is_invalid(fn_entry->type_entry))
12030 return ira->codegen->builtin_types.entry_invalid;
12915 return ira->codegen->invalid_instruction;
1203112916
12032 IrInstruction *bound_fn_value = ir_build_const_bound_fn(&ira->new_irb, field_ptr_instruction->base.scope,
12033 field_ptr_instruction->base.source_node, fn_entry, container_ptr);
12034 return ir_analyze_ref(ira, &field_ptr_instruction->base, bound_fn_value, true, false);
12917 IrInstruction *bound_fn_value = ir_build_const_bound_fn(&ira->new_irb, source_instr->scope,
12918 source_instr->source_node, fn_entry, container_ptr);
12919 return ir_get_ref(ira, source_instr, bound_fn_value, true, false);
1203512920 }
1203612921 }
1203712922 const char *prefix_name;
......@@ -12046,19 +12931,19 @@ static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira,
1204612931 } else {
1204712932 prefix_name = "";
1204812933 }
12049 ir_add_error_node(ira, field_ptr_instruction->base.source_node,
12934 ir_add_error_node(ira, source_instr->source_node,
1205012935 buf_sprintf("no member named '%s' in %s'%s'", buf_ptr(field_name), prefix_name, buf_ptr(&bare_struct_type->name)));
12051 return ira->codegen->builtin_types.entry_invalid;
12936 return ira->codegen->invalid_instruction;
1205212937}
1205312938
1205412939
12055static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
12056 IrInstructionFieldPtr *field_ptr_instruction, IrInstruction *container_ptr, TypeTableEntry *container_type)
12940static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
12941 IrInstruction *source_instr, IrInstruction *container_ptr, TypeTableEntry *container_type)
1205712942{
1205812943 TypeTableEntry *bare_type = container_ref_type(container_type);
1205912944 ensure_complete_type(ira->codegen, bare_type);
1206012945 if (type_is_invalid(bare_type))
12061 return ira->codegen->builtin_types.entry_invalid;
12946 return ira->codegen->invalid_instruction;
1206212947
1206312948 assert(container_ptr->value.type->id == TypeTableEntryIdPointer);
1206412949 bool is_const = container_ptr->value.type->data.pointer.is_const;
......@@ -12075,46 +12960,51 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field
1207512960 if (instr_is_comptime(container_ptr)) {
1207612961 ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
1207712962 if (!ptr_val)
12078 return ira->codegen->builtin_types.entry_invalid;
12963 return ira->codegen->invalid_instruction;
1207912964
1208012965 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
1208112966 ConstExprValue *struct_val = const_ptr_pointee(ira->codegen, ptr_val);
1208212967 if (type_is_invalid(struct_val->type))
12083 return ira->codegen->builtin_types.entry_invalid;
12968 return ira->codegen->invalid_instruction;
1208412969 ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index];
1208512970 TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, field_val->type,
1208612971 is_const, is_volatile, align_bytes,
1208712972 (uint32_t)(ptr_bit_offset + field->packed_bits_offset),
1208812973 (uint32_t)unaligned_bit_count_for_result_type);
12089 ConstExprValue *const_val = ir_build_const_from(ira, &field_ptr_instruction->base);
12974 IrInstruction *result = ir_get_const(ira, source_instr);
12975 ConstExprValue *const_val = &result->value;
1209012976 const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct;
1209112977 const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut;
1209212978 const_val->data.x_ptr.data.base_struct.struct_val = struct_val;
1209312979 const_val->data.x_ptr.data.base_struct.field_index = field->src_index;
12094 return ptr_type;
12980 const_val->type = ptr_type;
12981 return result;
1209512982 }
1209612983 }
12097 ir_build_struct_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field);
12098 return get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
12984 IrInstruction *result = ir_build_struct_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node,
12985 container_ptr, field);
12986 result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
1209912987 align_bytes,
1210012988 (uint32_t)(ptr_bit_offset + field->packed_bits_offset),
1210112989 (uint32_t)unaligned_bit_count_for_result_type);
12990 return result;
1210212991 } else {
1210312992 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
12104 field_ptr_instruction, container_ptr, container_type);
12993 source_instr, container_ptr, container_type);
1210512994 }
1210612995 } else if (bare_type->id == TypeTableEntryIdEnum) {
1210712996 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
12108 field_ptr_instruction, container_ptr, container_type);
12997 source_instr, container_ptr, container_type);
1210912998 } else if (bare_type->id == TypeTableEntryIdUnion) {
1211012999 TypeUnionField *field = find_union_type_field(bare_type, field_name);
1211113000 if (field) {
12112 ir_build_union_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field);
12113 return get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
13001 IrInstruction *result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node, container_ptr, field);
13002 result->value.type = get_pointer_to_type_extra(ira->codegen, field->type_entry, is_const, is_volatile,
1211413003 get_abi_alignment(ira->codegen, field->type_entry), 0, 0);
13004 return result;
1211513005 } else {
1211613006 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
12117 field_ptr_instruction, container_ptr, container_type);
13007 source_instr, container_ptr, container_type);
1211813008 }
1211913009 } else {
1212013010 zig_unreachable();
......@@ -12224,9 +13114,13 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru
1222413114 if (container_type->id == TypeTableEntryIdPointer) {
1222513115 TypeTableEntry *bare_type = container_ref_type(container_type);
1222613116 IrInstruction *container_child = ir_get_deref(ira, &field_ptr_instruction->base, container_ptr);
12227 return ir_analyze_container_field_ptr(ira, field_name, field_ptr_instruction, container_child, bare_type);
13117 IrInstruction *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base, container_child, bare_type);
13118 ir_link_new_instruction(result, &field_ptr_instruction->base);
13119 return result->value.type;
1222813120 } else {
12229 return ir_analyze_container_field_ptr(ira, field_name, field_ptr_instruction, container_ptr, container_type);
13121 IrInstruction *result = ir_analyze_container_field_ptr(ira, field_name, &field_ptr_instruction->base, container_ptr, container_type);
13122 ir_link_new_instruction(result, &field_ptr_instruction->base);
13123 return result->value.type;
1223013124 }
1223113125 } else if (container_type->id == TypeTableEntryIdArray) {
1223213126 if (buf_eql_str(field_name, "len")) {
......@@ -12673,6 +13567,7 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi
1267313567 case TypeTableEntryIdFn:
1267413568 case TypeTableEntryIdArgTuple:
1267513569 case TypeTableEntryIdOpaque:
13570 case TypeTableEntryIdPromise:
1267613571 {
1267713572 ConstExprValue *out_val = ir_build_const_from(ira, &typeof_instruction->base);
1267813573 out_val->data.x_type = type_entry;
......@@ -12940,6 +13835,7 @@ static TypeTableEntry *ir_analyze_instruction_slice_type(IrAnalyze *ira,
1294013835 case TypeTableEntryIdFn:
1294113836 case TypeTableEntryIdNamespace:
1294213837 case TypeTableEntryIdBoundFn:
13838 case TypeTableEntryIdPromise:
1294313839 {
1294413840 type_ensure_zero_bits_known(ira->codegen, child_type);
1294513841 TypeTableEntry *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,
......@@ -13048,6 +13944,7 @@ static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira,
1304813944 case TypeTableEntryIdFn:
1304913945 case TypeTableEntryIdNamespace:
1305013946 case TypeTableEntryIdBoundFn:
13947 case TypeTableEntryIdPromise:
1305113948 {
1305213949 TypeTableEntry *result_type = get_array_type(ira->codegen, child_type, size);
1305313950 ConstExprValue *out_val = ir_build_const_from(ira, &array_type_instruction->base);
......@@ -13099,6 +13996,7 @@ static TypeTableEntry *ir_analyze_instruction_size_of(IrAnalyze *ira,
1309913996 case TypeTableEntryIdEnum:
1310013997 case TypeTableEntryIdUnion:
1310113998 case TypeTableEntryIdFn:
13999 case TypeTableEntryIdPromise:
1310214000 {
1310314001 uint64_t size_in_bytes = type_size(ira->codegen, type_entry);
1310414002 ConstExprValue *out_val = ir_build_const_from(ira, &size_of_instruction->base);
......@@ -13428,6 +14326,7 @@ static TypeTableEntry *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1342814326 case TypeTableEntryIdNumLitFloat:
1342914327 case TypeTableEntryIdNumLitInt:
1343014328 case TypeTableEntryIdPointer:
14329 case TypeTableEntryIdPromise:
1343114330 case TypeTableEntryIdFn:
1343214331 case TypeTableEntryIdNamespace:
1343314332 case TypeTableEntryIdErrorSet:
......@@ -14016,6 +14915,7 @@ static TypeTableEntry *ir_analyze_min_max(IrAnalyze *ira, IrInstruction *source_
1401614915 case TypeTableEntryIdMetaType:
1401714916 case TypeTableEntryIdUnreachable:
1401814917 case TypeTableEntryIdPointer:
14918 case TypeTableEntryIdPromise:
1401914919 case TypeTableEntryIdArray:
1402014920 case TypeTableEntryIdStruct:
1402114921 case TypeTableEntryIdNumLitFloat:
......@@ -15276,6 +16176,7 @@ static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruc
1527616176 case TypeTableEntryIdInt:
1527716177 case TypeTableEntryIdFloat:
1527816178 case TypeTableEntryIdPointer:
16179 case TypeTableEntryIdPromise:
1527916180 case TypeTableEntryIdArray:
1528016181 case TypeTableEntryIdStruct:
1528116182 case TypeTableEntryIdMaybe:
......@@ -15904,12 +16805,12 @@ static TypeTableEntry *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruc
1590416805 if (type_is_invalid(src_type))
1590516806 return ira->codegen->builtin_types.entry_invalid;
1590616807
15907 if (!type_is_codegen_pointer(src_type)) {
16808 if (get_codegen_ptr_type(src_type) == nullptr) {
1590816809 ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name)));
1590916810 return ira->codegen->builtin_types.entry_invalid;
1591016811 }
1591116812
15912 if (!type_is_codegen_pointer(dest_type)) {
16813 if (get_codegen_ptr_type(dest_type) == nullptr) {
1591316814 ir_add_error(ira, dest_type_value,
1591416815 buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
1591516816 return ira->codegen->builtin_types.entry_invalid;
......@@ -15971,6 +16872,7 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
1597116872 case TypeTableEntryIdNumLitInt:
1597216873 case TypeTableEntryIdUndefLit:
1597316874 case TypeTableEntryIdNullLit:
16875 case TypeTableEntryIdPromise:
1597416876 zig_unreachable();
1597516877 case TypeTableEntryIdVoid:
1597616878 return;
......@@ -16038,6 +16940,7 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
1603816940 case TypeTableEntryIdNumLitInt:
1603916941 case TypeTableEntryIdUndefLit:
1604016942 case TypeTableEntryIdNullLit:
16943 case TypeTableEntryIdPromise:
1604116944 zig_unreachable();
1604216945 case TypeTableEntryIdVoid:
1604316946 return;
......@@ -16094,9 +16997,9 @@ static TypeTableEntry *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruc
1609416997 ensure_complete_type(ira->codegen, dest_type);
1609516998 ensure_complete_type(ira->codegen, src_type);
1609616999
16097 if (type_is_codegen_pointer(src_type)) {
17000 if (get_codegen_ptr_type(src_type) != nullptr) {
1609817001 ir_add_error(ira, value,
16099 buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));
17002 buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&src_type->name)));
1610017003 return ira->codegen->builtin_types.entry_invalid;
1610117004 }
1610217005
......@@ -16121,9 +17024,9 @@ static TypeTableEntry *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruc
1612117024 break;
1612217025 }
1612317026
16124 if (type_is_codegen_pointer(dest_type)) {
17027 if (get_codegen_ptr_type(dest_type) != nullptr) {
1612517028 ir_add_error(ira, dest_type_value,
16126 buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
17029 buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));
1612717030 return ira->codegen->builtin_types.entry_invalid;
1612817031 }
1612917032
......@@ -16184,7 +17087,7 @@ static TypeTableEntry *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstr
1618417087 if (type_is_invalid(dest_type))
1618517088 return ira->codegen->builtin_types.entry_invalid;
1618617089
16187 if (!type_is_codegen_pointer(dest_type)) {
17090 if (get_codegen_ptr_type(dest_type) == nullptr) {
1618817091 ir_add_error(ira, dest_type_value, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
1618917092 return ira->codegen->builtin_types.entry_invalid;
1619017093 }
......@@ -16290,12 +17193,7 @@ static TypeTableEntry *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstr
1629017193
1629117194 TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize;
1629217195
16293 if (!(target->value.type->id == TypeTableEntryIdPointer ||
16294 target->value.type->id == TypeTableEntryIdFn ||
16295 (target->value.type->id == TypeTableEntryIdMaybe &&
16296 (target->value.type->data.maybe.child_type->id == TypeTableEntryIdPointer ||
16297 target->value.type->data.maybe.child_type->id == TypeTableEntryIdFn))))
16298 {
17196 if (get_codegen_ptr_type(target->value.type) == nullptr) {
1629917197 ir_add_error(ira, target,
1630017198 buf_sprintf("expected pointer, found '%s'", buf_ptr(&target->value.type->name)));
1630117199 return ira->codegen->builtin_types.entry_invalid;
......@@ -16479,6 +17377,292 @@ static TypeTableEntry *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstruc
1647917377 }
1648017378}
1648117379
17380static TypeTableEntry *ir_analyze_instruction_cancel(IrAnalyze *ira, IrInstructionCancel *instruction) {
17381 IrInstruction *target_inst = instruction->target->other;
17382 if (type_is_invalid(target_inst->value.type))
17383 return ira->codegen->builtin_types.entry_invalid;
17384 IrInstruction *casted_target = ir_implicit_cast(ira, target_inst, ira->codegen->builtin_types.entry_promise);
17385 if (type_is_invalid(casted_target->value.type))
17386 return ira->codegen->builtin_types.entry_invalid;
17387
17388 IrInstruction *result = ir_build_cancel(&ira->new_irb, instruction->base.scope, instruction->base.source_node, casted_target);
17389 result->value.type = ira->codegen->builtin_types.entry_void;
17390 result->value.special = ConstValSpecialStatic;
17391 ir_link_new_instruction(result, &instruction->base);
17392 return result->value.type;
17393}
17394
17395static TypeTableEntry *ir_analyze_instruction_coro_id(IrAnalyze *ira, IrInstructionCoroId *instruction) {
17396 IrInstruction *promise_ptr = instruction->promise_ptr->other;
17397 if (type_is_invalid(promise_ptr->value.type))
17398 return ira->codegen->builtin_types.entry_invalid;
17399
17400 IrInstruction *result = ir_build_coro_id(&ira->new_irb, instruction->base.scope, instruction->base.source_node,
17401 promise_ptr);
17402 ir_link_new_instruction(result, &instruction->base);
17403 result->value.type = ira->codegen->builtin_types.entry_usize;
17404 return result->value.type;
17405}
17406
17407static TypeTableEntry *ir_analyze_instruction_coro_alloc(IrAnalyze *ira, IrInstructionCoroAlloc *instruction) {
17408 IrInstruction *coro_id = instruction->coro_id->other;
17409 if (type_is_invalid(coro_id->value.type))
17410 return ira->codegen->builtin_types.entry_invalid;
17411
17412 IrInstruction *result = ir_build_coro_alloc(&ira->new_irb, instruction->base.scope, instruction->base.source_node,
17413 coro_id);
17414 ir_link_new_instruction(result, &instruction->base);
17415 result->value.type = ira->codegen->builtin_types.entry_bool;
17416 return result->value.type;
17417}
17418
17419static TypeTableEntry *ir_analyze_instruction_coro_size(IrAnalyze *ira, IrInstructionCoroSize *instruction) {
17420 IrInstruction *result = ir_build_coro_size(&ira->new_irb, instruction->base.scope, instruction->base.source_node);
17421 ir_link_new_instruction(result, &instruction->base);
17422 result->value.type = ira->codegen->builtin_types.entry_usize;
17423 return result->value.type;
17424}
17425
17426static TypeTableEntry *ir_analyze_instruction_coro_begin(IrAnalyze *ira, IrInstructionCoroBegin *instruction) {
17427 IrInstruction *coro_id = instruction->coro_id->other;
17428 if (type_is_invalid(coro_id->value.type))
17429 return ira->codegen->builtin_types.entry_invalid;
17430
17431 IrInstruction *coro_mem_ptr = instruction->coro_mem_ptr->other;
17432 if (type_is_invalid(coro_mem_ptr->value.type))
17433 return ira->codegen->builtin_types.entry_invalid;
17434
17435 FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec);
17436 assert(fn_entry != nullptr);
17437 IrInstruction *result = ir_build_coro_begin(&ira->new_irb, instruction->base.scope, instruction->base.source_node,
17438 coro_id, coro_mem_ptr);
17439 ir_link_new_instruction(result, &instruction->base);
17440 result->value.type = get_promise_type(ira->codegen, fn_entry->type_entry->data.fn.fn_type_id.return_type);
17441 return result->value.type;
17442}
17443
17444static TypeTableEntry *ir_analyze_instruction_get_implicit_allocator(IrAnalyze *ira, IrInstructionGetImplicitAllocator *instruction) {
17445 IrInstruction *result = ir_get_implicit_allocator(ira, &instruction->base, instruction->id);
17446 ir_link_new_instruction(result, &instruction->base);
17447 return result->value.type;
17448}
17449
17450static TypeTableEntry *ir_analyze_instruction_coro_alloc_fail(IrAnalyze *ira, IrInstructionCoroAllocFail *instruction) {
17451 IrInstruction *err_val = instruction->err_val->other;
17452 if (type_is_invalid(err_val->value.type))
17453 return ir_unreach_error(ira);
17454
17455 IrInstruction *result = ir_build_coro_alloc_fail(&ira->new_irb, instruction->base.scope, instruction->base.source_node, err_val);
17456 ir_link_new_instruction(result, &instruction->base);
17457 result->value.type = ira->codegen->builtin_types.entry_unreachable;
17458 return ir_finish_anal(ira, result->value.type);
17459}
17460
17461static TypeTableEntry *ir_analyze_instruction_coro_suspend(IrAnalyze *ira, IrInstructionCoroSuspend *instruction) {
17462 IrInstruction *save_point = nullptr;
17463 if (instruction->save_point != nullptr) {
17464 save_point = instruction->save_point->other;
17465 if (type_is_invalid(save_point->value.type))
17466 return ira->codegen->builtin_types.entry_invalid;
17467 }
17468
17469 IrInstruction *is_final = instruction->is_final->other;
17470 if (type_is_invalid(is_final->value.type))
17471 return ira->codegen->builtin_types.entry_invalid;
17472
17473 IrInstruction *result = ir_build_coro_suspend(&ira->new_irb, instruction->base.scope,
17474 instruction->base.source_node, save_point, is_final);
17475 ir_link_new_instruction(result, &instruction->base);
17476 result->value.type = ira->codegen->builtin_types.entry_u8;
17477 return result->value.type;
17478}
17479
17480static TypeTableEntry *ir_analyze_instruction_coro_end(IrAnalyze *ira, IrInstructionCoroEnd *instruction) {
17481 IrInstruction *result = ir_build_coro_end(&ira->new_irb, instruction->base.scope,
17482 instruction->base.source_node);
17483 ir_link_new_instruction(result, &instruction->base);
17484 result->value.type = ira->codegen->builtin_types.entry_void;
17485 return result->value.type;
17486}
17487
17488static TypeTableEntry *ir_analyze_instruction_coro_free(IrAnalyze *ira, IrInstructionCoroFree *instruction) {
17489 IrInstruction *coro_id = instruction->coro_id->other;
17490 if (type_is_invalid(coro_id->value.type))
17491 return ira->codegen->builtin_types.entry_invalid;
17492
17493 IrInstruction *coro_handle = instruction->coro_handle->other;
17494 if (type_is_invalid(coro_handle->value.type))
17495 return ira->codegen->builtin_types.entry_invalid;
17496
17497 IrInstruction *result = ir_build_coro_free(&ira->new_irb, instruction->base.scope,
17498 instruction->base.source_node, coro_id, coro_handle);
17499 ir_link_new_instruction(result, &instruction->base);
17500 TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, false);
17501 result->value.type = get_maybe_type(ira->codegen, ptr_type);
17502 return result->value.type;
17503}
17504
17505static TypeTableEntry *ir_analyze_instruction_coro_resume(IrAnalyze *ira, IrInstructionCoroResume *instruction) {
17506 IrInstruction *awaiter_handle = instruction->awaiter_handle->other;
17507 if (type_is_invalid(awaiter_handle->value.type))
17508 return ira->codegen->builtin_types.entry_invalid;
17509
17510 IrInstruction *casted_target = ir_implicit_cast(ira, awaiter_handle, ira->codegen->builtin_types.entry_promise);
17511 if (type_is_invalid(casted_target->value.type))
17512 return ira->codegen->builtin_types.entry_invalid;
17513
17514 IrInstruction *result = ir_build_coro_resume(&ira->new_irb, instruction->base.scope,
17515 instruction->base.source_node, casted_target);
17516 ir_link_new_instruction(result, &instruction->base);
17517 result->value.type = ira->codegen->builtin_types.entry_void;
17518 return result->value.type;
17519}
17520
17521static TypeTableEntry *ir_analyze_instruction_coro_save(IrAnalyze *ira, IrInstructionCoroSave *instruction) {
17522 IrInstruction *coro_handle = instruction->coro_handle->other;
17523 if (type_is_invalid(coro_handle->value.type))
17524 return ira->codegen->builtin_types.entry_invalid;
17525
17526 IrInstruction *result = ir_build_coro_save(&ira->new_irb, instruction->base.scope,
17527 instruction->base.source_node, coro_handle);
17528 ir_link_new_instruction(result, &instruction->base);
17529 result->value.type = ira->codegen->builtin_types.entry_usize;
17530 return result->value.type;
17531}
17532
17533static TypeTableEntry *ir_analyze_instruction_coro_promise(IrAnalyze *ira, IrInstructionCoroPromise *instruction) {
17534 IrInstruction *coro_handle = instruction->coro_handle->other;
17535 if (type_is_invalid(coro_handle->value.type))
17536 return ira->codegen->builtin_types.entry_invalid;
17537
17538 if (coro_handle->value.type->id != TypeTableEntryIdPromise ||
17539 coro_handle->value.type->data.promise.result_type == nullptr)
17540 {
17541 ir_add_error(ira, &instruction->base, buf_sprintf("expected promise->T, found '%s'",
17542 buf_ptr(&coro_handle->value.type->name)));
17543 return ira->codegen->builtin_types.entry_invalid;
17544 }
17545
17546 TypeTableEntry *coro_frame_type = get_promise_frame_type(ira->codegen,
17547 coro_handle->value.type->data.promise.result_type);
17548
17549 IrInstruction *result = ir_build_coro_promise(&ira->new_irb, instruction->base.scope,
17550 instruction->base.source_node, coro_handle);
17551 ir_link_new_instruction(result, &instruction->base);
17552 result->value.type = get_pointer_to_type(ira->codegen, coro_frame_type, false);
17553 return result->value.type;
17554}
17555
17556static TypeTableEntry *ir_analyze_instruction_coro_alloc_helper(IrAnalyze *ira, IrInstructionCoroAllocHelper *instruction) {
17557 IrInstruction *alloc_fn = instruction->alloc_fn->other;
17558 if (type_is_invalid(alloc_fn->value.type))
17559 return ira->codegen->builtin_types.entry_invalid;
17560
17561 IrInstruction *coro_size = instruction->coro_size->other;
17562 if (type_is_invalid(coro_size->value.type))
17563 return ira->codegen->builtin_types.entry_invalid;
17564
17565 IrInstruction *result = ir_build_coro_alloc_helper(&ira->new_irb, instruction->base.scope,
17566 instruction->base.source_node, alloc_fn, coro_size);
17567 ir_link_new_instruction(result, &instruction->base);
17568 TypeTableEntry *u8_ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, false);
17569 result->value.type = get_maybe_type(ira->codegen, u8_ptr_type);
17570 return result->value.type;
17571}
17572
17573static TypeTableEntry *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstructionAtomicRmw *instruction) {
17574 TypeTableEntry *operand_type = ir_resolve_type(ira, instruction->operand_type->other);
17575 if (type_is_invalid(operand_type)) {
17576 return ira->codegen->builtin_types.entry_invalid;
17577 }
17578 if (operand_type->id == TypeTableEntryIdInt) {
17579 if (operand_type->data.integral.bit_count < 8) {
17580 ir_add_error(ira, &instruction->base,
17581 buf_sprintf("expected integer type 8 bits or larger, found %" PRIu32 "-bit integer type",
17582 operand_type->data.integral.bit_count));
17583 return ira->codegen->builtin_types.entry_invalid;
17584 }
17585 if (operand_type->data.integral.bit_count > ira->codegen->pointer_size_bytes * 8) {
17586 ir_add_error(ira, &instruction->base,
17587 buf_sprintf("expected integer type pointer size or smaller, found %" PRIu32 "-bit integer type",
17588 operand_type->data.integral.bit_count));
17589 return ira->codegen->builtin_types.entry_invalid;
17590 }
17591 if (!is_power_of_2(operand_type->data.integral.bit_count)) {
17592 ir_add_error(ira, &instruction->base,
17593 buf_sprintf("%" PRIu32 "-bit integer type is not a power of 2", operand_type->data.integral.bit_count));
17594 return ira->codegen->builtin_types.entry_invalid;
17595 }
17596 } else if (get_codegen_ptr_type(operand_type) == nullptr) {
17597 ir_add_error(ira, &instruction->base,
17598 buf_sprintf("expected integer or pointer type, found '%s'", buf_ptr(&operand_type->name)));
17599 return ira->codegen->builtin_types.entry_invalid;
17600 }
17601
17602 IrInstruction *ptr_inst = instruction->ptr->other;
17603 if (type_is_invalid(ptr_inst->value.type))
17604 return ira->codegen->builtin_types.entry_invalid;
17605
17606 TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, operand_type, false);
17607 IrInstruction *casted_ptr = ir_implicit_cast(ira, ptr_inst, ptr_type);
17608 if (type_is_invalid(casted_ptr->value.type))
17609 return ira->codegen->builtin_types.entry_invalid;
17610
17611 AtomicRmwOp op;
17612 if (instruction->op == nullptr) {
17613 op = instruction->resolved_op;
17614 } else {
17615 if (!ir_resolve_atomic_rmw_op(ira, instruction->op->other, &op)) {
17616 return ira->codegen->builtin_types.entry_invalid;
17617 }
17618 }
17619
17620 IrInstruction *operand = instruction->operand->other;
17621 if (type_is_invalid(operand->value.type))
17622 return ira->codegen->builtin_types.entry_invalid;
17623
17624 IrInstruction *casted_operand = ir_implicit_cast(ira, operand, operand_type);
17625 if (type_is_invalid(casted_ptr->value.type))
17626 return ira->codegen->builtin_types.entry_invalid;
17627
17628 AtomicOrder ordering;
17629 if (instruction->ordering == nullptr) {
17630 ordering = instruction->resolved_ordering;
17631 } else {
17632 if (!ir_resolve_atomic_order(ira, instruction->ordering->other, &ordering))
17633 return ira->codegen->builtin_types.entry_invalid;
17634 }
17635
17636 if (instr_is_comptime(casted_operand) && instr_is_comptime(casted_ptr) && casted_ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar)
17637 {
17638 zig_panic("TODO compile-time execution of atomicRmw");
17639 }
17640
17641 IrInstruction *result = ir_build_atomic_rmw(&ira->new_irb, instruction->base.scope,
17642 instruction->base.source_node, nullptr, casted_ptr, nullptr, casted_operand, nullptr,
17643 op, ordering);
17644 ir_link_new_instruction(result, &instruction->base);
17645 result->value.type = operand_type;
17646 return result->value.type;
17647}
17648
17649static TypeTableEntry *ir_analyze_instruction_promise_result_type(IrAnalyze *ira, IrInstructionPromiseResultType *instruction) {
17650 TypeTableEntry *promise_type = ir_resolve_type(ira, instruction->promise_type->other);
17651 if (type_is_invalid(promise_type))
17652 return ira->codegen->builtin_types.entry_invalid;
17653
17654 if (promise_type->id != TypeTableEntryIdPromise || promise_type->data.promise.result_type == nullptr) {
17655 ir_add_error(ira, &instruction->base, buf_sprintf("expected promise->T, found '%s'",
17656 buf_ptr(&promise_type->name)));
17657 return ira->codegen->builtin_types.entry_invalid;
17658 }
17659
17660 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
17661 out_val->data.x_type = promise_type->data.promise.result_type;
17662 return ira->codegen->builtin_types.entry_type;
17663}
17664
17665
1648217666static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
1648317667 switch (instruction->id) {
1648417668 case IrInstructionIdInvalid:
......@@ -16681,6 +17865,38 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
1668117865 return ir_analyze_instruction_error_return_trace(ira, (IrInstructionErrorReturnTrace *)instruction);
1668217866 case IrInstructionIdErrorUnion:
1668317867 return ir_analyze_instruction_error_union(ira, (IrInstructionErrorUnion *)instruction);
17868 case IrInstructionIdCancel:
17869 return ir_analyze_instruction_cancel(ira, (IrInstructionCancel *)instruction);
17870 case IrInstructionIdCoroId:
17871 return ir_analyze_instruction_coro_id(ira, (IrInstructionCoroId *)instruction);
17872 case IrInstructionIdCoroAlloc:
17873 return ir_analyze_instruction_coro_alloc(ira, (IrInstructionCoroAlloc *)instruction);
17874 case IrInstructionIdCoroSize:
17875 return ir_analyze_instruction_coro_size(ira, (IrInstructionCoroSize *)instruction);
17876 case IrInstructionIdCoroBegin:
17877 return ir_analyze_instruction_coro_begin(ira, (IrInstructionCoroBegin *)instruction);
17878 case IrInstructionIdGetImplicitAllocator:
17879 return ir_analyze_instruction_get_implicit_allocator(ira, (IrInstructionGetImplicitAllocator *)instruction);
17880 case IrInstructionIdCoroAllocFail:
17881 return ir_analyze_instruction_coro_alloc_fail(ira, (IrInstructionCoroAllocFail *)instruction);
17882 case IrInstructionIdCoroSuspend:
17883 return ir_analyze_instruction_coro_suspend(ira, (IrInstructionCoroSuspend *)instruction);
17884 case IrInstructionIdCoroEnd:
17885 return ir_analyze_instruction_coro_end(ira, (IrInstructionCoroEnd *)instruction);
17886 case IrInstructionIdCoroFree:
17887 return ir_analyze_instruction_coro_free(ira, (IrInstructionCoroFree *)instruction);
17888 case IrInstructionIdCoroResume:
17889 return ir_analyze_instruction_coro_resume(ira, (IrInstructionCoroResume *)instruction);
17890 case IrInstructionIdCoroSave:
17891 return ir_analyze_instruction_coro_save(ira, (IrInstructionCoroSave *)instruction);
17892 case IrInstructionIdCoroPromise:
17893 return ir_analyze_instruction_coro_promise(ira, (IrInstructionCoroPromise *)instruction);
17894 case IrInstructionIdCoroAllocHelper:
17895 return ir_analyze_instruction_coro_alloc_helper(ira, (IrInstructionCoroAllocHelper *)instruction);
17896 case IrInstructionIdAtomicRmw:
17897 return ir_analyze_instruction_atomic_rmw(ira, (IrInstructionAtomicRmw *)instruction);
17898 case IrInstructionIdPromiseResultType:
17899 return ir_analyze_instruction_promise_result_type(ira, (IrInstructionPromiseResultType *)instruction);
1668417900 }
1668517901 zig_unreachable();
1668617902}
......@@ -16710,7 +17926,10 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl
1671017926 IrAnalyze *ira = allocate<IrAnalyze>(1);
1671117927 old_exec->analysis = ira;
1671217928 ira->codegen = codegen;
16713 ira->explicit_return_type = expected_type;
17929
17930 FnTableEntry *fn_entry = exec_fn_entry(old_exec);
17931 bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
17932 ira->explicit_return_type = is_async ? get_promise_type(codegen, expected_type) : expected_type;
1671417933
1671517934 ira->old_irb.codegen = codegen;
1671617935 ira->old_irb.exec = old_exec;
......@@ -16794,7 +18013,16 @@ bool ir_has_side_effects(IrInstruction *instruction) {
1679418013 case IrInstructionIdPtrTypeOf:
1679518014 case IrInstructionIdSetAlignStack:
1679618015 case IrInstructionIdExport:
18016 case IrInstructionIdCancel:
18017 case IrInstructionIdCoroId:
18018 case IrInstructionIdCoroBegin:
18019 case IrInstructionIdCoroAllocFail:
18020 case IrInstructionIdCoroEnd:
18021 case IrInstructionIdCoroResume:
18022 case IrInstructionIdCoroSave:
18023 case IrInstructionIdCoroAllocHelper:
1679718024 return true;
18025
1679818026 case IrInstructionIdPhi:
1679918027 case IrInstructionIdUnOp:
1680018028 case IrInstructionIdBinOp:
......@@ -16867,7 +18095,16 @@ bool ir_has_side_effects(IrInstruction *instruction) {
1686718095 case IrInstructionIdTagType:
1686818096 case IrInstructionIdErrorReturnTrace:
1686918097 case IrInstructionIdErrorUnion:
18098 case IrInstructionIdGetImplicitAllocator:
18099 case IrInstructionIdCoroAlloc:
18100 case IrInstructionIdCoroSize:
18101 case IrInstructionIdCoroSuspend:
18102 case IrInstructionIdCoroFree:
18103 case IrInstructionIdAtomicRmw:
18104 case IrInstructionIdCoroPromise:
18105 case IrInstructionIdPromiseResultType:
1687018106 return false;
18107
1687118108 case IrInstructionIdAsm:
1687218109 {
1687318110 IrInstructionAsm *asm_instruction = (IrInstructionAsm *)instruction;
src/ir_print.cpp+193
......@@ -198,6 +198,15 @@ static void ir_print_cast(IrPrint *irp, IrInstructionCast *cast_instruction) {
198198}
199199
200200static 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 }
201210 if (call_instruction->fn_entry) {
202211 fprintf(irp->f, "%s", buf_ptr(&call_instruction->fn_entry->symbol_name));
203212 } else {
......@@ -830,6 +839,12 @@ static void ir_print_ptr_to_int(IrPrint *irp, IrInstructionPtrToInt *instruction
830839
831840static void ir_print_int_to_ptr(IrPrint *irp, IrInstructionIntToPtr *instruction) {
832841 fprintf(irp->f, "@intToPtr(");
842 if (instruction->dest_type == nullptr) {
843 fprintf(irp->f, "(null)");
844 } else {
845 ir_print_other_instruction(irp, instruction->dest_type);
846 }
847 fprintf(irp->f, ",");
833848 ir_print_other_instruction(irp, instruction->target);
834849 fprintf(irp->f, ")");
835850}
......@@ -1010,6 +1025,136 @@ static void ir_print_error_union(IrPrint *irp, IrInstructionErrorUnion *instruct
10101025 ir_print_other_instruction(irp, instruction->payload);
10111026}
10121027
1028static void ir_print_cancel(IrPrint *irp, IrInstructionCancel *instruction) {
1029 fprintf(irp->f, "cancel ");
1030 ir_print_other_instruction(irp, instruction->target);
1031}
1032
1033static void ir_print_get_implicit_allocator(IrPrint *irp, IrInstructionGetImplicitAllocator *instruction) {
1034 fprintf(irp->f, "@getImplicitAllocator(");
1035 switch (instruction->id) {
1036 case ImplicitAllocatorIdArg:
1037 fprintf(irp->f, "Arg");
1038 break;
1039 case ImplicitAllocatorIdLocalVar:
1040 fprintf(irp->f, "LocalVar");
1041 break;
1042 }
1043 fprintf(irp->f, ")");
1044}
1045
1046static void ir_print_coro_id(IrPrint *irp, IrInstructionCoroId *instruction) {
1047 fprintf(irp->f, "@coroId(");
1048 ir_print_other_instruction(irp, instruction->promise_ptr);
1049 fprintf(irp->f, ")");
1050}
1051
1052static void ir_print_coro_alloc(IrPrint *irp, IrInstructionCoroAlloc *instruction) {
1053 fprintf(irp->f, "@coroAlloc(");
1054 ir_print_other_instruction(irp, instruction->coro_id);
1055 fprintf(irp->f, ")");
1056}
1057
1058static void ir_print_coro_size(IrPrint *irp, IrInstructionCoroSize *instruction) {
1059 fprintf(irp->f, "@coroSize()");
1060}
1061
1062static void ir_print_coro_begin(IrPrint *irp, IrInstructionCoroBegin *instruction) {
1063 fprintf(irp->f, "@coroBegin(");
1064 ir_print_other_instruction(irp, instruction->coro_id);
1065 fprintf(irp->f, ",");
1066 ir_print_other_instruction(irp, instruction->coro_mem_ptr);
1067 fprintf(irp->f, ")");
1068}
1069
1070static void ir_print_coro_alloc_fail(IrPrint *irp, IrInstructionCoroAllocFail *instruction) {
1071 fprintf(irp->f, "@coroAllocFail(");
1072 ir_print_other_instruction(irp, instruction->err_val);
1073 fprintf(irp->f, ")");
1074}
1075
1076static void ir_print_coro_suspend(IrPrint *irp, IrInstructionCoroSuspend *instruction) {
1077 fprintf(irp->f, "@coroSuspend(");
1078 if (instruction->save_point != nullptr) {
1079 ir_print_other_instruction(irp, instruction->save_point);
1080 } else {
1081 fprintf(irp->f, "null");
1082 }
1083 fprintf(irp->f, ",");
1084 ir_print_other_instruction(irp, instruction->is_final);
1085 fprintf(irp->f, ")");
1086}
1087
1088static void ir_print_coro_end(IrPrint *irp, IrInstructionCoroEnd *instruction) {
1089 fprintf(irp->f, "@coroEnd()");
1090}
1091
1092static void ir_print_coro_free(IrPrint *irp, IrInstructionCoroFree *instruction) {
1093 fprintf(irp->f, "@coroFree(");
1094 ir_print_other_instruction(irp, instruction->coro_id);
1095 fprintf(irp->f, ",");
1096 ir_print_other_instruction(irp, instruction->coro_handle);
1097 fprintf(irp->f, ")");
1098}
1099
1100static void ir_print_coro_resume(IrPrint *irp, IrInstructionCoroResume *instruction) {
1101 fprintf(irp->f, "@coroResume(");
1102 ir_print_other_instruction(irp, instruction->awaiter_handle);
1103 fprintf(irp->f, ")");
1104}
1105
1106static void ir_print_coro_save(IrPrint *irp, IrInstructionCoroSave *instruction) {
1107 fprintf(irp->f, "@coroSave(");
1108 ir_print_other_instruction(irp, instruction->coro_handle);
1109 fprintf(irp->f, ")");
1110}
1111
1112static void ir_print_coro_promise(IrPrint *irp, IrInstructionCoroPromise *instruction) {
1113 fprintf(irp->f, "@coroPromise(");
1114 ir_print_other_instruction(irp, instruction->coro_handle);
1115 fprintf(irp->f, ")");
1116}
1117
1118static void ir_print_promise_result_type(IrPrint *irp, IrInstructionPromiseResultType *instruction) {
1119 fprintf(irp->f, "@PromiseResultType(");
1120 ir_print_other_instruction(irp, instruction->promise_type);
1121 fprintf(irp->f, ")");
1122}
1123
1124static void ir_print_coro_alloc_helper(IrPrint *irp, IrInstructionCoroAllocHelper *instruction) {
1125 fprintf(irp->f, "@coroAllocHelper(");
1126 ir_print_other_instruction(irp, instruction->alloc_fn);
1127 fprintf(irp->f, ",");
1128 ir_print_other_instruction(irp, instruction->coro_size);
1129 fprintf(irp->f, ")");
1130}
1131
1132static void ir_print_atomic_rmw(IrPrint *irp, IrInstructionAtomicRmw *instruction) {
1133 fprintf(irp->f, "@atomicRmw(");
1134 if (instruction->operand_type != nullptr) {
1135 ir_print_other_instruction(irp, instruction->operand_type);
1136 } else {
1137 fprintf(irp->f, "[TODO print]");
1138 }
1139 fprintf(irp->f, ",");
1140 ir_print_other_instruction(irp, instruction->ptr);
1141 fprintf(irp->f, ",");
1142 if (instruction->op != nullptr) {
1143 ir_print_other_instruction(irp, instruction->op);
1144 } else {
1145 fprintf(irp->f, "[TODO print]");
1146 }
1147 fprintf(irp->f, ",");
1148 ir_print_other_instruction(irp, instruction->operand);
1149 fprintf(irp->f, ",");
1150 if (instruction->ordering != nullptr) {
1151 ir_print_other_instruction(irp, instruction->ordering);
1152 } else {
1153 fprintf(irp->f, "[TODO print]");
1154 }
1155 fprintf(irp->f, ")");
1156}
1157
10131158static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
10141159 ir_print_prefix(irp, instruction);
10151160 switch (instruction->id) {
......@@ -1330,6 +1475,54 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
13301475 case IrInstructionIdErrorUnion:
13311476 ir_print_error_union(irp, (IrInstructionErrorUnion *)instruction);
13321477 break;
1478 case IrInstructionIdCancel:
1479 ir_print_cancel(irp, (IrInstructionCancel *)instruction);
1480 break;
1481 case IrInstructionIdGetImplicitAllocator:
1482 ir_print_get_implicit_allocator(irp, (IrInstructionGetImplicitAllocator *)instruction);
1483 break;
1484 case IrInstructionIdCoroId:
1485 ir_print_coro_id(irp, (IrInstructionCoroId *)instruction);
1486 break;
1487 case IrInstructionIdCoroAlloc:
1488 ir_print_coro_alloc(irp, (IrInstructionCoroAlloc *)instruction);
1489 break;
1490 case IrInstructionIdCoroSize:
1491 ir_print_coro_size(irp, (IrInstructionCoroSize *)instruction);
1492 break;
1493 case IrInstructionIdCoroBegin:
1494 ir_print_coro_begin(irp, (IrInstructionCoroBegin *)instruction);
1495 break;
1496 case IrInstructionIdCoroAllocFail:
1497 ir_print_coro_alloc_fail(irp, (IrInstructionCoroAllocFail *)instruction);
1498 break;
1499 case IrInstructionIdCoroSuspend:
1500 ir_print_coro_suspend(irp, (IrInstructionCoroSuspend *)instruction);
1501 break;
1502 case IrInstructionIdCoroEnd:
1503 ir_print_coro_end(irp, (IrInstructionCoroEnd *)instruction);
1504 break;
1505 case IrInstructionIdCoroFree:
1506 ir_print_coro_free(irp, (IrInstructionCoroFree *)instruction);
1507 break;
1508 case IrInstructionIdCoroResume:
1509 ir_print_coro_resume(irp, (IrInstructionCoroResume *)instruction);
1510 break;
1511 case IrInstructionIdCoroSave:
1512 ir_print_coro_save(irp, (IrInstructionCoroSave *)instruction);
1513 break;
1514 case IrInstructionIdCoroAllocHelper:
1515 ir_print_coro_alloc_helper(irp, (IrInstructionCoroAllocHelper *)instruction);
1516 break;
1517 case IrInstructionIdAtomicRmw:
1518 ir_print_atomic_rmw(irp, (IrInstructionAtomicRmw *)instruction);
1519 break;
1520 case IrInstructionIdCoroPromise:
1521 ir_print_coro_promise(irp, (IrInstructionCoroPromise *)instruction);
1522 break;
1523 case IrInstructionIdPromiseResultType:
1524 ir_print_promise_result_type(irp, (IrInstructionPromiseResultType *)instruction);
1525 break;
13331526 }
13341527 fprintf(irp->f, "\n");
13351528}
src/parser.cpp+170-9
......@@ -221,6 +221,7 @@ static AstNode *ast_parse_grouped_expr(ParseContext *pc, size_t *token_index, bo
221221static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory);
222222static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory);
223223static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index);
224static AstNode *ast_parse_await_expr(ParseContext *pc, size_t *token_index);
224225static AstNode *ast_parse_symbol(ParseContext *pc, size_t *token_index);
225226
226227static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) {
......@@ -650,6 +651,41 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc, size_t *token_index, bool m
650651 return node;
651652}
652653
654/*
655SuspendExpression(body) = "suspend" "|" Symbol "|" body
656*/
657static AstNode *ast_parse_suspend_block(ParseContext *pc, size_t *token_index, bool mandatory) {
658 size_t orig_token_index = *token_index;
659
660 Token *suspend_token = &pc->tokens->at(*token_index);
661 if (suspend_token->id == TokenIdKeywordSuspend) {
662 *token_index += 1;
663 } else if (mandatory) {
664 ast_expect_token(pc, suspend_token, TokenIdKeywordSuspend);
665 zig_unreachable();
666 } else {
667 return nullptr;
668 }
669
670 Token *bar_token = &pc->tokens->at(*token_index);
671 if (bar_token->id == TokenIdBinOr) {
672 *token_index += 1;
673 } else if (mandatory) {
674 ast_expect_token(pc, suspend_token, TokenIdBinOr);
675 zig_unreachable();
676 } else {
677 *token_index = orig_token_index;
678 return nullptr;
679 }
680
681 AstNode *node = ast_create_node(pc, NodeTypeSuspend, suspend_token);
682 node->data.suspend.promise_symbol = ast_parse_symbol(pc, token_index);
683 ast_eat_token(pc, token_index, TokenIdBinOr);
684 node->data.suspend.block = ast_parse_block(pc, token_index, true);
685
686 return node;
687}
688
653689/*
654690CompTimeExpression(body) = "comptime" body
655691*/
......@@ -674,7 +710,7 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b
674710
675711/*
676712PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ContainerDecl | ("continue" option(":" Symbol)) | ErrorSetDecl
677KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "unreachable"
713KeywordLiteral = "true" | "false" | "null" | "undefined" | "error" | "this" | "unreachable" | "suspend"
678714ErrorSetDecl = "error" "{" list(Symbol, ",") "}"
679715*/
680716static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
......@@ -738,6 +774,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
738774 AstNode *node = ast_create_node(pc, NodeTypeUnreachable, token);
739775 *token_index += 1;
740776 return node;
777 } else if (token->id == TokenIdKeywordSuspend) {
778 AstNode *node = ast_create_node(pc, NodeTypeSuspend, token);
779 *token_index += 1;
780 return node;
741781 } else if (token->id == TokenIdKeywordError) {
742782 Token *next_token = &pc->tokens->at(*token_index + 1);
743783 if (next_token->id == TokenIdLBrace) {
......@@ -920,7 +960,7 @@ static AstNode *ast_parse_curly_suffix_expr(ParseContext *pc, size_t *token_inde
920960}
921961
922962/*
923SuffixOpExpression = PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
963SuffixOpExpression = ("async" option("(" Expression ")") PrimaryExpression FnCallExpression) | PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
924964FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)
925965ArrayAccessExpression : token(LBracket) Expression token(RBracket)
926966SliceExpression = "[" Expression ".." option(Expression) "]"
......@@ -928,9 +968,34 @@ FieldAccessExpression : token(Dot) token(Symbol)
928968StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression
929969*/
930970static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
931 AstNode *primary_expr = ast_parse_primary_expr(pc, token_index, mandatory);
932 if (!primary_expr)
933 return nullptr;
971 AstNode *primary_expr;
972
973 Token *async_token = &pc->tokens->at(*token_index);
974 if (async_token->id == TokenIdKeywordAsync) {
975 *token_index += 1;
976
977 AstNode *allocator_expr_node = nullptr;
978 Token *async_lparen_tok = &pc->tokens->at(*token_index);
979 if (async_lparen_tok->id == TokenIdLParen) {
980 *token_index += 1;
981 allocator_expr_node = ast_parse_expression(pc, token_index, true);
982 ast_eat_token(pc, token_index, TokenIdRParen);
983 }
984
985 AstNode *fn_ref_expr_node = ast_parse_primary_expr(pc, token_index, true);
986 Token *lparen_tok = ast_eat_token(pc, token_index, TokenIdLParen);
987 AstNode *node = ast_create_node(pc, NodeTypeFnCallExpr, lparen_tok);
988 node->data.fn_call_expr.is_async = true;
989 node->data.fn_call_expr.async_allocator = allocator_expr_node;
990 node->data.fn_call_expr.fn_ref_expr = fn_ref_expr_node;
991 ast_parse_fn_call_param_list(pc, token_index, &node->data.fn_call_expr.params);
992
993 primary_expr = node;
994 } else {
995 primary_expr = ast_parse_primary_expr(pc, token_index, mandatory);
996 if (!primary_expr)
997 return nullptr;
998 }
934999
9351000 while (true) {
9361001 Token *first_token = &pc->tokens->at(*token_index);
......@@ -1042,7 +1107,7 @@ static AstNode *ast_parse_addr_of(ParseContext *pc, size_t *token_index) {
10421107
10431108/*
10441109PrefixOpExpression = PrefixOp ErrorSetExpr | SuffixOpExpression
1045PrefixOp = "!" | "-" | "~" | "*" | ("&" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try"
1110PrefixOp = "!" | "-" | "~" | "*" | ("&" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "??" | "-%" | "try" | "await"
10461111*/
10471112static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
10481113 Token *token = &pc->tokens->at(*token_index);
......@@ -1052,6 +1117,9 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index,
10521117 if (token->id == TokenIdKeywordTry) {
10531118 return ast_parse_try_expr(pc, token_index);
10541119 }
1120 if (token->id == TokenIdKeywordAwait) {
1121 return ast_parse_await_expr(pc, token_index);
1122 }
10551123 PrefixOp prefix_op = tok_to_prefix_op(token);
10561124 if (prefix_op == PrefixOpInvalid) {
10571125 return ast_parse_suffix_op_expr(pc, token_index, mandatory);
......@@ -1510,6 +1578,23 @@ static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index) {
15101578 return node;
15111579}
15121580
1581/*
1582AwaitExpression : "await" Expression
1583*/
1584static AstNode *ast_parse_await_expr(ParseContext *pc, size_t *token_index) {
1585 Token *token = &pc->tokens->at(*token_index);
1586
1587 if (token->id != TokenIdKeywordAwait) {
1588 return nullptr;
1589 }
1590 *token_index += 1;
1591
1592 AstNode *node = ast_create_node(pc, NodeTypeAwaitExpr, token);
1593 node->data.await_expr.expr = ast_parse_expression(pc, token_index, true);
1594
1595 return node;
1596}
1597
15131598/*
15141599BreakExpression = "break" option(":" Symbol) option(Expression)
15151600*/
......@@ -1535,6 +1620,42 @@ static AstNode *ast_parse_break_expr(ParseContext *pc, size_t *token_index) {
15351620 return node;
15361621}
15371622
1623/*
1624CancelExpression = "cancel" Expression;
1625*/
1626static AstNode *ast_parse_cancel_expr(ParseContext *pc, size_t *token_index) {
1627 Token *token = &pc->tokens->at(*token_index);
1628
1629 if (token->id != TokenIdKeywordCancel) {
1630 return nullptr;
1631 }
1632 *token_index += 1;
1633
1634 AstNode *node = ast_create_node(pc, NodeTypeCancel, token);
1635
1636 node->data.cancel_expr.expr = ast_parse_expression(pc, token_index, false);
1637
1638 return node;
1639}
1640
1641/*
1642ResumeExpression = "resume" Expression;
1643*/
1644static AstNode *ast_parse_resume_expr(ParseContext *pc, size_t *token_index) {
1645 Token *token = &pc->tokens->at(*token_index);
1646
1647 if (token->id != TokenIdKeywordResume) {
1648 return nullptr;
1649 }
1650 *token_index += 1;
1651
1652 AstNode *node = ast_create_node(pc, NodeTypeResume, token);
1653
1654 node->data.resume_expr.expr = ast_parse_expression(pc, token_index, false);
1655
1656 return node;
1657}
1658
15381659/*
15391660Defer(body) = ("defer" | "errdefer") body
15401661*/
......@@ -2001,7 +2122,7 @@ static AstNode *ast_parse_switch_expr(ParseContext *pc, size_t *token_index, boo
20012122}
20022123
20032124/*
2004BlockExpression(body) = Block | IfExpression(body) | TryExpression(body) | TestExpression(body) | WhileExpression(body) | ForExpression(body) | SwitchExpression | CompTimeExpression(body)
2125BlockExpression(body) = Block | IfExpression(body) | IfErrorExpression(body) | TestExpression(body) | WhileExpression(body) | ForExpression(body) | SwitchExpression | CompTimeExpression(body) | SuspendExpression(body)
20052126*/
20062127static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
20072128 Token *token = &pc->tokens->at(*token_index);
......@@ -2030,6 +2151,10 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, size_t *token_index, bool
20302151 if (comptime_node)
20312152 return comptime_node;
20322153
2154 AstNode *suspend_node = ast_parse_suspend_block(pc, token_index, false);
2155 if (suspend_node)
2156 return suspend_node;
2157
20332158 if (mandatory)
20342159 ast_invalid_token_error(pc, token);
20352160
......@@ -2159,7 +2284,7 @@ static AstNode *ast_parse_block_or_expression(ParseContext *pc, size_t *token_in
21592284}
21602285
21612286/*
2162Expression = TryExpression | ReturnExpression | BreakExpression | AssignmentExpression
2287Expression = TryExpression | ReturnExpression | BreakExpression | AssignmentExpression | CancelExpression | ResumeExpression
21632288*/
21642289static AstNode *ast_parse_expression(ParseContext *pc, size_t *token_index, bool mandatory) {
21652290 Token *token = &pc->tokens->at(*token_index);
......@@ -2176,6 +2301,14 @@ static AstNode *ast_parse_expression(ParseContext *pc, size_t *token_index, bool
21762301 if (break_expr)
21772302 return break_expr;
21782303
2304 AstNode *cancel_expr = ast_parse_cancel_expr(pc, token_index);
2305 if (cancel_expr)
2306 return cancel_expr;
2307
2308 AstNode *resume_expr = ast_parse_resume_expr(pc, token_index);
2309 if (resume_expr)
2310 return resume_expr;
2311
21792312 AstNode *ass_expr = ast_parse_ass_expr(pc, token_index, false);
21802313 if (ass_expr)
21812314 return ass_expr;
......@@ -2208,6 +2341,8 @@ static bool statement_terminates_without_semicolon(AstNode *node) {
22082341 return node->data.comptime_expr.expr->type == NodeTypeBlock;
22092342 case NodeTypeDefer:
22102343 return node->data.defer.expr->type == NodeTypeBlock;
2344 case NodeTypeSuspend:
2345 return node->data.suspend.block != nullptr && node->data.suspend.block->type == NodeTypeBlock;
22112346 case NodeTypeSwitchExpr:
22122347 case NodeTypeBlock:
22132348 return true;
......@@ -2286,7 +2421,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand
22862421}
22872422
22882423/*
2289FnProto = option("nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") TypeExpr
2424FnProto = option("nakedcc" | "stdcallcc" | "extern" | ("async" option("(" Expression ")"))) "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") TypeExpr
22902425*/
22912426static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {
22922427 Token *first_token = &pc->tokens->at(*token_index);
......@@ -2294,10 +2429,20 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m
22942429
22952430 CallingConvention cc;
22962431 bool is_extern = false;
2432 AstNode *async_allocator_type_node = nullptr;
22972433 if (first_token->id == TokenIdKeywordNakedCC) {
22982434 *token_index += 1;
22992435 fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn);
23002436 cc = CallingConventionNaked;
2437 } else if (first_token->id == TokenIdKeywordAsync) {
2438 *token_index += 1;
2439 Token *next_token = &pc->tokens->at(*token_index);
2440 if (next_token->id == TokenIdLParen) {
2441 async_allocator_type_node = ast_parse_type_expr(pc, token_index, true);
2442 ast_eat_token(pc, token_index, TokenIdRParen);
2443 }
2444 fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn);
2445 cc = CallingConventionAsync;
23012446 } else if (first_token->id == TokenIdKeywordStdcallCC) {
23022447 *token_index += 1;
23032448 fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn);
......@@ -2332,6 +2477,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m
23322477 node->data.fn_proto.visib_mod = visib_mod;
23332478 node->data.fn_proto.cc = cc;
23342479 node->data.fn_proto.is_extern = is_extern;
2480 node->data.fn_proto.async_allocator_type = async_allocator_type_node;
23352481
23362482 Token *fn_name = &pc->tokens->at(*token_index);
23372483
......@@ -2747,6 +2893,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
27472893 visit_node_list(&node->data.fn_proto.params, visit, context);
27482894 visit_field(&node->data.fn_proto.align_expr, visit, context);
27492895 visit_field(&node->data.fn_proto.section_expr, visit, context);
2896 visit_field(&node->data.fn_proto.async_allocator_type, visit, context);
27502897 break;
27512898 case NodeTypeFnDef:
27522899 visit_field(&node->data.fn_def.fn_proto, visit, context);
......@@ -2809,6 +2956,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
28092956 case NodeTypeFnCallExpr:
28102957 visit_field(&node->data.fn_call_expr.fn_ref_expr, visit, context);
28112958 visit_node_list(&node->data.fn_call_expr.params, visit, context);
2959 visit_field(&node->data.fn_call_expr.async_allocator, visit, context);
28122960 break;
28132961 case NodeTypeArrayAccessExpr:
28142962 visit_field(&node->data.array_access_expr.array_ref_expr, visit, context);
......@@ -2931,5 +3079,18 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
29313079 case NodeTypeErrorSetDecl:
29323080 visit_node_list(&node->data.err_set_decl.decls, visit, context);
29333081 break;
3082 case NodeTypeCancel:
3083 visit_field(&node->data.cancel_expr.expr, visit, context);
3084 break;
3085 case NodeTypeResume:
3086 visit_field(&node->data.resume_expr.expr, visit, context);
3087 break;
3088 case NodeTypeAwaitExpr:
3089 visit_field(&node->data.await_expr.expr, visit, context);
3090 break;
3091 case NodeTypeSuspend:
3092 visit_field(&node->data.suspend.promise_symbol, visit, context);
3093 visit_field(&node->data.suspend.block, visit, context);
3094 break;
29343095 }
29353096}
src/tokenizer.cpp+10
......@@ -110,7 +110,10 @@ static const struct ZigKeyword zig_keywords[] = {
110110 {"align", TokenIdKeywordAlign},
111111 {"and", TokenIdKeywordAnd},
112112 {"asm", TokenIdKeywordAsm},
113 {"async", TokenIdKeywordAsync},
114 {"await", TokenIdKeywordAwait},
113115 {"break", TokenIdKeywordBreak},
116 {"cancel", TokenIdKeywordCancel},
114117 {"catch", TokenIdKeywordCatch},
115118 {"comptime", TokenIdKeywordCompTime},
116119 {"const", TokenIdKeywordConst},
......@@ -133,10 +136,12 @@ static const struct ZigKeyword zig_keywords[] = {
133136 {"or", TokenIdKeywordOr},
134137 {"packed", TokenIdKeywordPacked},
135138 {"pub", TokenIdKeywordPub},
139 {"resume", TokenIdKeywordResume},
136140 {"return", TokenIdKeywordReturn},
137141 {"section", TokenIdKeywordSection},
138142 {"stdcallcc", TokenIdKeywordStdcallCC},
139143 {"struct", TokenIdKeywordStruct},
144 {"suspend", TokenIdKeywordSuspend},
140145 {"switch", TokenIdKeywordSwitch},
141146 {"test", TokenIdKeywordTest},
142147 {"this", TokenIdKeywordThis},
......@@ -1523,6 +1528,11 @@ const char * token_name(TokenId id) {
15231528 case TokenIdFatArrow: return "=>";
15241529 case TokenIdFloatLiteral: return "FloatLiteral";
15251530 case TokenIdIntLiteral: return "IntLiteral";
1531 case TokenIdKeywordAsync: return "async";
1532 case TokenIdKeywordAwait: return "await";
1533 case TokenIdKeywordResume: return "resume";
1534 case TokenIdKeywordSuspend: return "suspend";
1535 case TokenIdKeywordCancel: return "cancel";
15261536 case TokenIdKeywordAlign: return "align";
15271537 case TokenIdKeywordAnd: return "and";
15281538 case TokenIdKeywordAsm: return "asm";
src/tokenizer.hpp+5
......@@ -51,7 +51,10 @@ enum TokenId {
5151 TokenIdKeywordAlign,
5252 TokenIdKeywordAnd,
5353 TokenIdKeywordAsm,
54 TokenIdKeywordAsync,
55 TokenIdKeywordAwait,
5456 TokenIdKeywordBreak,
57 TokenIdKeywordCancel,
5558 TokenIdKeywordCatch,
5659 TokenIdKeywordCompTime,
5760 TokenIdKeywordConst,
......@@ -74,10 +77,12 @@ enum TokenId {
7477 TokenIdKeywordOr,
7578 TokenIdKeywordPacked,
7679 TokenIdKeywordPub,
80 TokenIdKeywordResume,
7781 TokenIdKeywordReturn,
7882 TokenIdKeywordSection,
7983 TokenIdKeywordStdcallCC,
8084 TokenIdKeywordStruct,
85 TokenIdKeywordSuspend,
8186 TokenIdKeywordSwitch,
8287 TokenIdKeywordTest,
8388 TokenIdKeywordThis,
src/zig_llvm.cpp+6
......@@ -32,6 +32,7 @@
3232#include <llvm/Support/TargetParser.h>
3333#include <llvm/Support/raw_ostream.h>
3434#include <llvm/Target/TargetMachine.h>
35#include <llvm/Transforms/Coroutines.h>
3536#include <llvm/Transforms/IPO.h>
3637#include <llvm/Transforms/IPO/PassManagerBuilder.h>
3738#include <llvm/Transforms/IPO/AlwaysInliner.h>
......@@ -129,6 +130,8 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
129130 PMBuilder->Inliner = createFunctionInliningPass(PMBuilder->OptLevel, PMBuilder->SizeLevel, false);
130131 }
131132
133 addCoroutinePassesToExtensionPoints(*PMBuilder);
134
132135 // Set up the per-function pass manager.
133136 legacy::FunctionPassManager FPM = legacy::FunctionPassManager(module);
134137 auto tliwp = new(std::nothrow) TargetLibraryInfoWrapperPass(tlii);
......@@ -182,6 +185,9 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
182185 return false;
183186}
184187
188ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref) {
189 return wrap(Type::getTokenTy(*unwrap(context_ref)));
190}
185191
186192LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
187193 unsigned NumArgs, unsigned CC, ZigLLVM_FnInline fn_inline, const char *Name)
src/zig_llvm.h+2
......@@ -54,6 +54,8 @@ enum ZigLLVM_EmitOutputType {
5454ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
5555 const char *filename, enum ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug);
5656
57ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref);
58
5759enum ZigLLVM_FnInline {
5860 ZigLLVM_FnInlineAuto,
5961 ZigLLVM_FnInlineAlways,
std/debug/index.zig+8-10
......@@ -98,21 +98,18 @@ pub fn assertOrPanic(ok: bool) void {
9898 }
9999}
100100
101var panicking = false;
101var panicking: u8 = 0; // TODO make this a bool
102102/// This is the default panic implementation.
103103pub fn panic(comptime format: []const u8, args: ...) noreturn {
104 // TODO an intrinsic that labels this as unlikely to be reached
104 @setCold(true);
105105
106 // TODO
107 // if (@atomicRmw(AtomicOp.XChg, &panicking, true, AtomicOrder.SeqCst)) { }
108 if (panicking) {
106 if (@atomicRmw(u8, &panicking, builtin.AtomicRmwOp.Xchg, 1, builtin.AtomicOrder.SeqCst) == 1) {
109107 // Panicked during a panic.
108
110109 // TODO detect if a different thread caused the panic, because in that case
111110 // we would want to return here instead of calling abort, so that the thread
112111 // which first called panic can finish printing a stack trace.
113112 os.abort();
114 } else {
115 panicking = true;
116113 }
117114
118115 const stderr = getStderrStream() catch os.abort();
......@@ -123,10 +120,11 @@ pub fn panic(comptime format: []const u8, args: ...) noreturn {
123120}
124121
125122pub fn panicWithTrace(trace: &const builtin.StackTrace, comptime format: []const u8, args: ...) noreturn {
126 if (panicking) {
123 @setCold(true);
124
125 if (@atomicRmw(u8, &panicking, builtin.AtomicRmwOp.Xchg, 1, builtin.AtomicOrder.SeqCst) == 1) {
126 // See TODO in above function
127127 os.abort();
128 } else {
129 panicking = true;
130128 }
131129 const stderr = getStderrStream() catch os.abort();
132130 stderr.print(format ++ "\n", args) catch os.abort();
std/hash_map.zig+1-1
......@@ -235,7 +235,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
235235 };
236236}
237237
238test "basicHashMapTest" {
238test "basic hash map usage" {
239239 var map = HashMap(i32, i32, hash_i32, eql_i32).init(debug.global_allocator);
240240 defer map.deinit();
241241
test/behavior.zig+14-1
......@@ -1,3 +1,5 @@
1const builtin = @import("builtin");
2
13comptime {
24 _ = @import("cases/align.zig");
35 _ = @import("cases/alignof.zig");
......@@ -34,8 +36,8 @@ comptime {
3436 _ = @import("cases/sizeof_and_typeof.zig");
3537 _ = @import("cases/slice.zig");
3638 _ = @import("cases/struct.zig");
37 _ = @import("cases/struct_contains_slice_of_itself.zig");
3839 _ = @import("cases/struct_contains_null_ptr_itself.zig");
40 _ = @import("cases/struct_contains_slice_of_itself.zig");
3941 _ = @import("cases/switch.zig");
4042 _ = @import("cases/switch_prong_err_enum.zig");
4143 _ = @import("cases/switch_prong_implicit_cast.zig");
......@@ -47,4 +49,15 @@ comptime {
4749 _ = @import("cases/var_args.zig");
4850 _ = @import("cases/void.zig");
4951 _ = @import("cases/while.zig");
52
53
54 // LLVM 5.0.1, 6.0.0, and trunk crash when attempting to optimize coroutine code.
55 // So, Zig does not support ReleaseFast or ReleaseSafe for coroutines yet.
56 // Luckily, Clang users are running into the same crashes, so folks from the LLVM
57 // community are working on fixes. If we're really lucky they'll be fixed in 6.0.1.
58 // Otherwise we can hope for 7.0.0.
59 if (builtin.mode == builtin.Mode.Debug) {
60 _ = @import("cases/coroutines.zig");
61 }
62
5063}
test/cases/atomics.zig+14-1
......@@ -1,5 +1,7 @@
11const assert = @import("std").debug.assert;
2const AtomicOrder = @import("builtin").AtomicOrder;
2const builtin = @import("builtin");
3const AtomicRmwOp = builtin.AtomicRmwOp;
4const AtomicOrder = builtin.AtomicOrder;
35
46test "cmpxchg" {
57 var x: i32 = 1234;
......@@ -12,3 +14,14 @@ test "fence" {
1214 @fence(AtomicOrder.SeqCst);
1315 x = 5678;
1416}
17
18test "atomicrmw" {
19 var data: u8 = 200;
20 testAtomicRmw(&data);
21 assert(data == 42);
22}
23
24fn testAtomicRmw(ptr: &u8) void {
25 const prev_value = @atomicRmw(u8, ptr, AtomicRmwOp.Xchg, 42, AtomicOrder.SeqCst);
26 assert(prev_value == 200);
27}
test/cases/coroutines.zig created+132
......@@ -0,0 +1,132 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4var x: i32 = 1;
5
6test "create a coroutine and cancel it" {
7 const p = try async(std.debug.global_allocator) simpleAsyncFn();
8 cancel p;
9 assert(x == 2);
10}
11
12async fn simpleAsyncFn() void {
13 x += 1;
14 suspend;
15 x += 1;
16}
17
18test "coroutine suspend, resume, cancel" {
19 seq('a');
20 const p = try async(std.debug.global_allocator) testAsyncSeq();
21 seq('c');
22 resume p;
23 seq('f');
24 cancel p;
25 seq('g');
26
27 assert(std.mem.eql(u8, points, "abcdefg"));
28}
29
30async fn testAsyncSeq() void {
31 defer seq('e');
32
33 seq('b');
34 suspend;
35 seq('d');
36}
37var points = []u8{0} ** "abcdefg".len;
38var index: usize = 0;
39
40fn seq(c: u8) void {
41 points[index] = c;
42 index += 1;
43}
44
45test "coroutine suspend with block" {
46 const p = try async(std.debug.global_allocator) testSuspendBlock();
47 std.debug.assert(!result);
48 resume a_promise;
49 std.debug.assert(result);
50 cancel p;
51}
52
53var a_promise: promise = undefined;
54var result = false;
55
56async fn testSuspendBlock() void {
57 suspend |p| {
58 a_promise = p;
59 }
60 result = true;
61}
62
63var await_a_promise: promise = undefined;
64var await_final_result: i32 = 0;
65
66test "coroutine await" {
67 await_seq('a');
68 const p = async(std.debug.global_allocator) await_amain() catch unreachable;
69 await_seq('f');
70 resume await_a_promise;
71 await_seq('i');
72 assert(await_final_result == 1234);
73 assert(std.mem.eql(u8, await_points, "abcdefghi"));
74}
75
76async fn await_amain() void {
77 await_seq('b');
78 const p = async await_another() catch unreachable;
79 await_seq('e');
80 await_final_result = await p;
81 await_seq('h');
82}
83
84async fn await_another() i32 {
85 await_seq('c');
86 suspend |p| {
87 await_seq('d');
88 await_a_promise = p;
89 }
90 await_seq('g');
91 return 1234;
92}
93
94var await_points = []u8{0} ** "abcdefghi".len;
95var await_seq_index: usize = 0;
96
97fn await_seq(c: u8) void {
98 await_points[await_seq_index] = c;
99 await_seq_index += 1;
100}
101
102
103var early_final_result: i32 = 0;
104
105test "coroutine await early return" {
106 early_seq('a');
107 const p = async(std.debug.global_allocator) early_amain() catch unreachable;
108 early_seq('f');
109 assert(early_final_result == 1234);
110 assert(std.mem.eql(u8, early_points, "abcdef"));
111}
112
113async fn early_amain() void {
114 early_seq('b');
115 const p = async early_another() catch unreachable;
116 early_seq('d');
117 early_final_result = await p;
118 early_seq('e');
119}
120
121async fn early_another() i32 {
122 early_seq('c');
123 return 1234;
124}
125
126var early_points = []u8{0} ** "abcdef".len;
127var early_seq_index: usize = 0;
128
129fn early_seq(c: u8) void {
130 early_points[early_seq_index] = c;
131 early_seq_index += 1;
132}