authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-05 16:55:32-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-05 17:07:15-05:00
log1f602fe8c5b3dea9f00f96e70dad73ebce405b49
tree30df1e8c6fd6f4dd99d91679aa02c79e0ff75c5f
parent38791ac616069963fd808ec724161b93cbc564c1
signature Commit is signed but in an unrecognized format.

implement `@call`

closes #3732

14 files changed, 529 insertions(+), 188 deletions(-)

lib/std/builtin.zig+18
...@@ -372,6 +372,24 @@ pub const Version = struct {...@@ -372,6 +372,24 @@ pub const Version = struct {
372 patch: u32,372 patch: u32,
373};373};
374374
375/// This data structure is used by the Zig language code generation and
376/// therefore must be kept in sync with the compiler implementation.
377pub const CallOptions = struct {
378 modifier: Modifier = .auto,
379 stack: ?[]align(std.Target.stack_align) u8 = null,
380
381 pub const Modifier = enum {
382 auto,
383 no_async,
384 async_call,
385 never_tail,
386 never_inline,
387 always_tail,
388 always_inline,
389 compile_time,
390 };
391};
392
375/// This function type is used by the Zig language code generation and393/// This function type is used by the Zig language code generation and
376/// therefore must be kept in sync with the compiler implementation.394/// therefore must be kept in sync with the compiler implementation.
377pub const PanicFn = fn ([]const u8, ?*StackTrace) noreturn;395pub const PanicFn = fn ([]const u8, ?*StackTrace) noreturn;
src-self-hosted/llvm.zig+6-4
...@@ -260,10 +260,12 @@ pub const X86StdcallCallConv = c.LLVMX86StdcallCallConv;...@@ -260,10 +260,12 @@ pub const X86StdcallCallConv = c.LLVMX86StdcallCallConv;
260pub const X86FastcallCallConv = c.LLVMX86FastcallCallConv;260pub const X86FastcallCallConv = c.LLVMX86FastcallCallConv;
261pub const CallConv = c.LLVMCallConv;261pub const CallConv = c.LLVMCallConv;
262262
263pub const FnInline = extern enum {263pub const CallAttr = extern enum {
264 Auto,264 Auto,
265 Always,265 NeverTail,
266 Never,266 NeverInline,
267 AlwaysTail,
268 AlwaysInline,
267};269};
268270
269fn removeNullability(comptime T: type) type {271fn removeNullability(comptime T: type) type {
...@@ -286,6 +288,6 @@ extern fn ZigLLVMTargetMachineEmitToFile(...@@ -286,6 +288,6 @@ extern fn ZigLLVMTargetMachineEmitToFile(
286) bool;288) bool;
287289
288pub const BuildCall = ZigLLVMBuildCall;290pub const BuildCall = ZigLLVMBuildCall;
289extern fn ZigLLVMBuildCall(B: *Builder, Fn: *Value, Args: [*]*Value, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*:0]const u8) ?*Value;291extern fn ZigLLVMBuildCall(B: *Builder, Fn: *Value, Args: [*]*Value, NumArgs: c_uint, CC: c_uint, fn_inline: CallAttr, Name: [*:0]const u8) ?*Value;
290292
291pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage;293pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage;
src/all_types.hpp+23-5
...@@ -767,10 +767,18 @@ struct AstNodeUnwrapOptional {...@@ -767,10 +767,18 @@ struct AstNodeUnwrapOptional {
767 AstNode *expr;767 AstNode *expr;
768};768};
769769
770// Must be synchronized with std.builtin.CallOptions.Modifier
770enum CallModifier {771enum CallModifier {
771 CallModifierNone,772 CallModifierNone,
772 CallModifierAsync,
773 CallModifierNoAsync,773 CallModifierNoAsync,
774 CallModifierAsync,
775 CallModifierNeverTail,
776 CallModifierNeverInline,
777 CallModifierAlwaysTail,
778 CallModifierAlwaysInline,
779 CallModifierCompileTime,
780
781 // This is an additional tag in the compiler, but not exposed in the std lib.
774 CallModifierBuiltin,782 CallModifierBuiltin,
775};783};
776784
...@@ -1717,6 +1725,7 @@ enum BuiltinFnId {...@@ -1717,6 +1725,7 @@ enum BuiltinFnId {
1717 BuiltinFnIdFrameHandle,1725 BuiltinFnIdFrameHandle,
1718 BuiltinFnIdFrameSize,1726 BuiltinFnIdFrameSize,
1719 BuiltinFnIdAs,1727 BuiltinFnIdAs,
1728 BuiltinFnIdCall,
1720};1729};
17211730
1722struct BuiltinFnEntry {1731struct BuiltinFnEntry {
...@@ -2479,6 +2488,7 @@ enum IrInstructionId {...@@ -2479,6 +2488,7 @@ enum IrInstructionId {
2479 IrInstructionIdVarPtr,2488 IrInstructionIdVarPtr,
2480 IrInstructionIdReturnPtr,2489 IrInstructionIdReturnPtr,
2481 IrInstructionIdCallSrc,2490 IrInstructionIdCallSrc,
2491 IrInstructionIdCallExtra,
2482 IrInstructionIdCallGen,2492 IrInstructionIdCallGen,
2483 IrInstructionIdConst,2493 IrInstructionIdConst,
2484 IrInstructionIdReturn,2494 IrInstructionIdReturn,
...@@ -2886,15 +2896,24 @@ struct IrInstructionCallSrc {...@@ -2886,15 +2896,24 @@ struct IrInstructionCallSrc {
2886 ZigFn *fn_entry;2896 ZigFn *fn_entry;
2887 size_t arg_count;2897 size_t arg_count;
2888 IrInstruction **args;2898 IrInstruction **args;
2899 IrInstruction *ret_ptr;
2889 ResultLoc *result_loc;2900 ResultLoc *result_loc;
28902901
2891 IrInstruction *new_stack;2902 IrInstruction *new_stack;
28922903
2893 FnInline fn_inline;
2894 CallModifier modifier;2904 CallModifier modifier;
2895
2896 bool is_async_call_builtin;2905 bool is_async_call_builtin;
2897 bool is_comptime;2906};
2907
2908/// This is a pass1 instruction, used by @call.
2909/// `args` is expected to be either a struct or a tuple.
2910struct IrInstructionCallExtra {
2911 IrInstruction base;
2912
2913 IrInstruction *options;
2914 IrInstruction *fn_ref;
2915 IrInstruction *args;
2916 ResultLoc *result_loc;
2898};2917};
28992918
2900struct IrInstructionCallGen {2919struct IrInstructionCallGen {
...@@ -2908,7 +2927,6 @@ struct IrInstructionCallGen {...@@ -2908,7 +2927,6 @@ struct IrInstructionCallGen {
2908 IrInstruction *frame_result_loc;2927 IrInstruction *frame_result_loc;
2909 IrInstruction *new_stack;2928 IrInstruction *new_stack;
29102929
2911 FnInline fn_inline;
2912 CallModifier modifier;2930 CallModifier modifier;
29132931
2914 bool is_async_call_builtin;2932 bool is_async_call_builtin;
src/analyze.cpp+10-7
...@@ -956,10 +956,7 @@ bool calling_convention_allows_zig_types(CallingConvention cc) {...@@ -956,10 +956,7 @@ bool calling_convention_allows_zig_types(CallingConvention cc) {
956956
957ZigType *get_stack_trace_type(CodeGen *g) {957ZigType *get_stack_trace_type(CodeGen *g) {
958 if (g->stack_trace_type == nullptr) {958 if (g->stack_trace_type == nullptr) {
959 ZigValue *stack_trace_type_val = get_builtin_value(g, "StackTrace");959 g->stack_trace_type = get_builtin_type(g, "StackTrace");
960 assert(stack_trace_type_val->type->id == ZigTypeIdMetaType);
961
962 g->stack_trace_type = stack_trace_type_val->data.x_type;
963 assertNoError(type_resolve(g, g->stack_trace_type, ResolveStatusZeroBitsKnown));960 assertNoError(type_resolve(g, g->stack_trace_type, ResolveStatusZeroBitsKnown));
964 }961 }
965 return g->stack_trace_type;962 return g->stack_trace_type;
...@@ -2717,10 +2714,10 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {...@@ -2717,10 +2714,10 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
2717 src_assert(struct_type->data.structure.fields == nullptr, decl_node);2714 src_assert(struct_type->data.structure.fields == nullptr, decl_node);
2718 struct_type->data.structure.fields = alloc_type_struct_fields(field_count);2715 struct_type->data.structure.fields = alloc_type_struct_fields(field_count);
2719 } else if (decl_node->type == NodeTypeContainerInitExpr) {2716 } else if (decl_node->type == NodeTypeContainerInitExpr) {
2720 src_assert(struct_type->data.structure.is_inferred, decl_node);
2721 src_assert(struct_type->data.structure.fields != nullptr, decl_node);
2722
2723 field_count = struct_type->data.structure.src_field_count;2717 field_count = struct_type->data.structure.src_field_count;
2718
2719 src_assert(struct_type->data.structure.is_inferred, decl_node);
2720 src_assert(field_count == 0 || struct_type->data.structure.fields != nullptr, decl_node);
2724 } else zig_unreachable();2721 } else zig_unreachable();
27252722
2726 struct_type->data.structure.fields_by_name.init(field_count);2723 struct_type->data.structure.fields_by_name.init(field_count);
...@@ -7531,6 +7528,12 @@ ZigValue *get_builtin_value(CodeGen *codegen, const char *name) {...@@ -7531,6 +7528,12 @@ ZigValue *get_builtin_value(CodeGen *codegen, const char *name) {
7531 return var_value;7528 return var_value;
7532}7529}
75337530
7531ZigType *get_builtin_type(CodeGen *codegen, const char *name) {
7532 ZigValue *type_val = get_builtin_value(codegen, name);
7533 assert(type_val->type->id == ZigTypeIdMetaType);
7534 return type_val->data.x_type;
7535}
7536
7534bool type_is_global_error_set(ZigType *err_set_type) {7537bool type_is_global_error_set(ZigType *err_set_type) {
7535 assert(err_set_type->id == ZigTypeIdErrorSet);7538 assert(err_set_type->id == ZigTypeIdErrorSet);
7536 assert(!err_set_type->data.error_set.incomplete);7539 assert(!err_set_type->data.error_set.incomplete);
src/analyze.hpp+1
...@@ -207,6 +207,7 @@ void add_var_export(CodeGen *g, ZigVar *fn_table_entry, const char *symbol_name,...@@ -207,6 +207,7 @@ void add_var_export(CodeGen *g, ZigVar *fn_table_entry, const char *symbol_name,
207207
208208
209ZigValue *get_builtin_value(CodeGen *codegen, const char *name);209ZigValue *get_builtin_value(CodeGen *codegen, const char *name);
210ZigType *get_builtin_type(CodeGen *codegen, const char *name);
210ZigType *get_stack_trace_type(CodeGen *g);211ZigType *get_stack_trace_type(CodeGen *g);
211bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *source_node);212bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *source_node);
212213
src/ast_render.cpp+19-4
...@@ -702,14 +702,29 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -702,14 +702,29 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
702 switch (node->data.fn_call_expr.modifier) {702 switch (node->data.fn_call_expr.modifier) {
703 case CallModifierNone:703 case CallModifierNone:
704 break;704 break;
705 case CallModifierBuiltin:705 case CallModifierNoAsync:
706 fprintf(ar->f, "@");706 fprintf(ar->f, "noasync ");
707 break;707 break;
708 case CallModifierAsync:708 case CallModifierAsync:
709 fprintf(ar->f, "async ");709 fprintf(ar->f, "async ");
710 break;710 break;
711 case CallModifierNoAsync:711 case CallModifierNeverTail:
712 fprintf(ar->f, "noasync ");712 fprintf(ar->f, "notail ");
713 break;
714 case CallModifierNeverInline:
715 fprintf(ar->f, "noinline ");
716 break;
717 case CallModifierAlwaysTail:
718 fprintf(ar->f, "tail ");
719 break;
720 case CallModifierAlwaysInline:
721 fprintf(ar->f, "inline ");
722 break;
723 case CallModifierCompileTime:
724 fprintf(ar->f, "comptime ");
725 break;
726 case CallModifierBuiltin:
727 fprintf(ar->f, "@");
713 break;728 break;
714 }729 }
715 AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;730 AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr;
src/codegen.cpp+35-20
...@@ -981,7 +981,7 @@ static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace...@@ -981,7 +981,7 @@ static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace
981 msg_arg,981 msg_arg,
982 stack_trace_arg,982 stack_trace_arg,
983 };983 };
984 ZigLLVMBuildCall(g->builder, fn_val, args, 2, llvm_cc, ZigLLVM_FnInlineAuto, "");984 ZigLLVMBuildCall(g->builder, fn_val, args, 2, llvm_cc, ZigLLVM_CallAttrAuto, "");
985 if (!stack_trace_is_llvm_alloca) {985 if (!stack_trace_is_llvm_alloca) {
986 // The stack trace argument is not in the stack of the caller, so986 // The stack trace argument is not in the stack of the caller, so
987 // we'd like to set tail call here, but because slices (the type of msg_arg) are987 // we'd like to set tail call here, but because slices (the type of msg_arg) are
...@@ -1201,7 +1201,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {...@@ -1201,7 +1201,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {
12011201
1202 LLVMPositionBuilderAtEnd(g->builder, dest_non_null_block);1202 LLVMPositionBuilderAtEnd(g->builder, dest_non_null_block);
1203 LLVMValueRef args[] = { err_ret_trace_ptr, return_address };1203 LLVMValueRef args[] = { err_ret_trace_ptr, return_address };
1204 ZigLLVMBuildCall(g->builder, add_error_return_trace_addr_fn_val, args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAlways, "");1204 ZigLLVMBuildCall(g->builder, add_error_return_trace_addr_fn_val, args, 2,
1205 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAlwaysInline, "");
1205 LLVMBuildRetVoid(g->builder);1206 LLVMBuildRetVoid(g->builder);
12061207
1207 LLVMPositionBuilderAtEnd(g->builder, prev_block);1208 LLVMPositionBuilderAtEnd(g->builder, prev_block);
...@@ -1370,13 +1371,13 @@ static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *sc...@@ -1370,13 +1371,13 @@ static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *sc
1370 err_val,1371 err_val,
1371 };1372 };
1372 call_instruction = ZigLLVMBuildCall(g->builder, safety_crash_err_fn, args, 2,1373 call_instruction = ZigLLVMBuildCall(g->builder, safety_crash_err_fn, args, 2,
1373 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");1374 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, "");
1374 } else {1375 } else {
1375 LLVMValueRef args[] = {1376 LLVMValueRef args[] = {
1376 err_val,1377 err_val,
1377 };1378 };
1378 call_instruction = ZigLLVMBuildCall(g->builder, safety_crash_err_fn, args, 1,1379 call_instruction = ZigLLVMBuildCall(g->builder, safety_crash_err_fn, args, 1,
1379 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");1380 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, "");
1380 }1381 }
1381 if (!is_llvm_alloca) {1382 if (!is_llvm_alloca) {
1382 LLVMSetTailCall(call_instruction, true);1383 LLVMSetTailCall(call_instruction, true);
...@@ -2216,7 +2217,7 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {...@@ -2216,7 +2217,7 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
2216 LLVMValueRef addr_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr_val, &ptr_index, 1, "");2217 LLVMValueRef addr_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr_val, &ptr_index, 1, "");
2217 LLVMValueRef this_addr_val = LLVMBuildLoad(g->builder, addr_ptr, "");2218 LLVMValueRef this_addr_val = LLVMBuildLoad(g->builder, addr_ptr, "");
2218 LLVMValueRef args[] = {dest_stack_trace_ptr, this_addr_val};2219 LLVMValueRef args[] = {dest_stack_trace_ptr, this_addr_val};
2219 ZigLLVMBuildCall(g->builder, add_error_return_trace_addr_fn_val, args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAlways, "");2220 ZigLLVMBuildCall(g->builder, add_error_return_trace_addr_fn_val, args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAlwaysInline, "");
2220 LLVMValueRef prev_frames_left = LLVMBuildLoad(g->builder, frames_left_ptr, "");2221 LLVMValueRef prev_frames_left = LLVMBuildLoad(g->builder, frames_left_ptr, "");
2221 LLVMValueRef new_frames_left = LLVMBuildNUWSub(g->builder, prev_frames_left, usize_one, "");2222 LLVMValueRef new_frames_left = LLVMBuildNUWSub(g->builder, prev_frames_left, usize_one, "");
2222 LLVMValueRef done_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, new_frames_left, usize_zero, "");2223 LLVMValueRef done_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, new_frames_left, usize_zero, "");
...@@ -2253,7 +2254,7 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut...@@ -2253,7 +2254,7 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut
2253 LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, save_err_ret_addr_instruction->base.scope,2254 LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, save_err_ret_addr_instruction->base.scope,
2254 &is_llvm_alloca);2255 &is_llvm_alloca);
2255 ZigLLVMBuildCall(g->builder, return_err_fn, &my_err_trace_val, 1,2256 ZigLLVMBuildCall(g->builder, return_err_fn, &my_err_trace_val, 1,
2256 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");2257 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, "");
22572258
2258 ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;2259 ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type;
2259 if (fn_is_async(g->cur_fn) && codegen_fn_has_err_ret_tracing_arg(g, ret_type)) {2260 if (fn_is_async(g->cur_fn) && codegen_fn_has_err_ret_tracing_arg(g, ret_type)) {
...@@ -2297,7 +2298,7 @@ static LLVMValueRef gen_resume(CodeGen *g, LLVMValueRef fn_val, LLVMValueRef tar...@@ -2297,7 +2298,7 @@ static LLVMValueRef gen_resume(CodeGen *g, LLVMValueRef fn_val, LLVMValueRef tar
2297 LLVMValueRef arg_val = LLVMConstSub(LLVMConstAllOnes(usize_type_ref),2298 LLVMValueRef arg_val = LLVMConstSub(LLVMConstAllOnes(usize_type_ref),
2298 LLVMConstInt(usize_type_ref, resume_id, false));2299 LLVMConstInt(usize_type_ref, resume_id, false));
2299 LLVMValueRef args[] = {target_frame_ptr, arg_val};2300 LLVMValueRef args[] = {target_frame_ptr, arg_val};
2300 return ZigLLVMBuildCall(g->builder, fn_val, args, 2, LLVMFastCallConv, ZigLLVM_FnInlineAuto, "");2301 return ZigLLVMBuildCall(g->builder, fn_val, args, 2, LLVMFastCallConv, ZigLLVM_CallAttrAuto, "");
2301}2302}
23022303
2303static LLVMBasicBlockRef gen_suspend_begin(CodeGen *g, const char *name_hint) {2304static LLVMBasicBlockRef gen_suspend_begin(CodeGen *g, const char *name_hint) {
...@@ -2424,7 +2425,7 @@ static void gen_async_return(CodeGen *g, IrInstructionReturn *instruction) {...@@ -2424,7 +2425,7 @@ static void gen_async_return(CodeGen *g, IrInstructionReturn *instruction) {
2424 LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca);2425 LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca);
2425 LLVMValueRef args[] = { dest_trace_ptr, my_err_trace_val };2426 LLVMValueRef args[] = { dest_trace_ptr, my_err_trace_val };
2426 ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2,2427 ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2,
2427 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");2428 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, "");
2428 }2429 }
2429 }2430 }
24302431
...@@ -4142,16 +4143,28 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -4142,16 +4143,28 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
4142 fn_walk.data.call.gen_param_types = &gen_param_types;4143 fn_walk.data.call.gen_param_types = &gen_param_types;
4143 walk_function_params(g, fn_type, &fn_walk);4144 walk_function_params(g, fn_type, &fn_walk);
41444145
4145 ZigLLVM_FnInline fn_inline;4146 ZigLLVM_CallAttr call_attr;
4146 switch (instruction->fn_inline) {4147 switch (instruction->modifier) {
4147 case FnInlineAuto:4148 case CallModifierBuiltin:
4148 fn_inline = ZigLLVM_FnInlineAuto;4149 case CallModifierCompileTime:
4150 zig_unreachable();
4151 case CallModifierNone:
4152 case CallModifierNoAsync:
4153 case CallModifierAsync:
4154 call_attr = ZigLLVM_CallAttrAuto;
4149 break;4155 break;
4150 case FnInlineAlways:4156 case CallModifierNeverTail:
4151 fn_inline = (instruction->fn_entry == nullptr) ? ZigLLVM_FnInlineAuto : ZigLLVM_FnInlineAlways;4157 call_attr = ZigLLVM_CallAttrNeverTail;
4152 break;4158 break;
4153 case FnInlineNever:4159 case CallModifierNeverInline:
4154 fn_inline = ZigLLVM_FnInlineNever;4160 call_attr = ZigLLVM_CallAttrNeverInline;
4161 break;
4162 case CallModifierAlwaysTail:
4163 call_attr = ZigLLVM_CallAttrAlwaysTail;
4164 break;
4165 case CallModifierAlwaysInline:
4166 ir_assert(instruction->fn_entry != nullptr, &instruction->base);
4167 call_attr = ZigLLVM_CallAttrAlwaysInline;
4155 break;4168 break;
4156 }4169 }
41574170
...@@ -4257,7 +4270,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -4257,7 +4270,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
42574270
4258 if (instruction->new_stack == nullptr || instruction->is_async_call_builtin) {4271 if (instruction->new_stack == nullptr || instruction->is_async_call_builtin) {
4259 result = ZigLLVMBuildCall(g->builder, fn_val,4272 result = ZigLLVMBuildCall(g->builder, fn_val,
4260 gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, fn_inline, "");4273 gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, call_attr, "");
4261 } else if (instruction->modifier == CallModifierAsync) {4274 } else if (instruction->modifier == CallModifierAsync) {
4262 zig_panic("TODO @asyncCall of non-async function");4275 zig_panic("TODO @asyncCall of non-async function");
4263 } else {4276 } else {
...@@ -4269,7 +4282,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -4269,7 +4282,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
4269 }4282 }
4270 gen_set_stack_pointer(g, new_stack_addr);4283 gen_set_stack_pointer(g, new_stack_addr);
4271 result = ZigLLVMBuildCall(g->builder, fn_val,4284 result = ZigLLVMBuildCall(g->builder, fn_val,
4272 gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, fn_inline, "");4285 gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, call_attr, "");
4273 if (src_return_type->id != ZigTypeIdUnreachable) {4286 if (src_return_type->id != ZigTypeIdUnreachable) {
4274 LLVMValueRef stackrestore_fn_val = get_stackrestore_fn_val(g);4287 LLVMValueRef stackrestore_fn_val = get_stackrestore_fn_val(g);
4275 LLVMBuildCall(g->builder, stackrestore_fn_val, &old_stack_ref, 1, "");4288 LLVMBuildCall(g->builder, stackrestore_fn_val, &old_stack_ref, 1, "");
...@@ -4947,7 +4960,7 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable...@@ -4947,7 +4960,7 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, IrExecutable *executable
49474960
4948 LLVMValueRef enum_tag_value = ir_llvm_value(g, instruction->target);4961 LLVMValueRef enum_tag_value = ir_llvm_value(g, instruction->target);
4949 return ZigLLVMBuildCall(g->builder, enum_name_function, &enum_tag_value, 1,4962 return ZigLLVMBuildCall(g->builder, enum_name_function, &enum_tag_value, 1,
4950 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");4963 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, "");
4951}4964}
49524965
4953static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutable *executable,4966static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutable *executable,
...@@ -5903,7 +5916,7 @@ static LLVMValueRef gen_await_early_return(CodeGen *g, IrInstruction *source_ins...@@ -5903,7 +5916,7 @@ static LLVMValueRef gen_await_early_return(CodeGen *g, IrInstruction *source_ins
5903 LLVMValueRef dest_trace_ptr = get_cur_err_ret_trace_val(g, source_instr->scope, &is_llvm_alloca);5916 LLVMValueRef dest_trace_ptr = get_cur_err_ret_trace_val(g, source_instr->scope, &is_llvm_alloca);
5904 LLVMValueRef args[] = { dest_trace_ptr, src_trace_ptr };5917 LLVMValueRef args[] = { dest_trace_ptr, src_trace_ptr };
5905 ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2,5918 ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2,
5906 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");5919 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, "");
5907 }5920 }
5908 if (non_async && type_has_bits(result_type)) {5921 if (non_async && type_has_bits(result_type)) {
5909 LLVMValueRef result_ptr = (result_loc == nullptr) ? their_result_ptr : result_loc;5922 LLVMValueRef result_ptr = (result_loc == nullptr) ? their_result_ptr : result_loc;
...@@ -6137,6 +6150,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -6137,6 +6150,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
6137 case IrInstructionIdLoadPtr:6150 case IrInstructionIdLoadPtr:
6138 case IrInstructionIdHasDecl:6151 case IrInstructionIdHasDecl:
6139 case IrInstructionIdUndeclaredIdent:6152 case IrInstructionIdUndeclaredIdent:
6153 case IrInstructionIdCallExtra:
6140 case IrInstructionIdCallSrc:6154 case IrInstructionIdCallSrc:
6141 case IrInstructionIdAllocaSrc:6155 case IrInstructionIdAllocaSrc:
6142 case IrInstructionIdEndExpr:6156 case IrInstructionIdEndExpr:
...@@ -8146,6 +8160,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -8146,6 +8160,7 @@ static void define_builtin_fns(CodeGen *g) {
8146 create_builtin_fn(g, BuiltinFnIdFrameAddress, "frameAddress", 0);8160 create_builtin_fn(g, BuiltinFnIdFrameAddress, "frameAddress", 0);
8147 create_builtin_fn(g, BuiltinFnIdFrameSize, "frameSize", 1);8161 create_builtin_fn(g, BuiltinFnIdFrameSize, "frameSize", 1);
8148 create_builtin_fn(g, BuiltinFnIdAs, "as", 2);8162 create_builtin_fn(g, BuiltinFnIdAs, "as", 2);
8163 create_builtin_fn(g, BuiltinFnIdCall, "call", 3);
8149}8164}
81508165
8151static const char *bool_to_str(bool b) {8166static const char *bool_to_str(bool b) {
src/ir.cpp+292-133
...@@ -265,6 +265,7 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction...@@ -265,6 +265,7 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction
265static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name,265static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name,
266 IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type);266 IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type);
267static ResultLoc *no_result_loc(void);267static ResultLoc *no_result_loc(void);
268static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value);
268269
269static void destroy_instruction(IrInstruction *inst) {270static void destroy_instruction(IrInstruction *inst) {
270#ifdef ZIG_ENABLE_MEM_PROFILE271#ifdef ZIG_ENABLE_MEM_PROFILE
...@@ -289,6 +290,8 @@ static void destroy_instruction(IrInstruction *inst) {...@@ -289,6 +290,8 @@ static void destroy_instruction(IrInstruction *inst) {
289 return destroy(reinterpret_cast<IrInstructionCast *>(inst), name);290 return destroy(reinterpret_cast<IrInstructionCast *>(inst), name);
290 case IrInstructionIdCallSrc:291 case IrInstructionIdCallSrc:
291 return destroy(reinterpret_cast<IrInstructionCallSrc *>(inst), name);292 return destroy(reinterpret_cast<IrInstructionCallSrc *>(inst), name);
293 case IrInstructionIdCallExtra:
294 return destroy(reinterpret_cast<IrInstructionCallExtra *>(inst), name);
292 case IrInstructionIdCallGen:295 case IrInstructionIdCallGen:
293 return destroy(reinterpret_cast<IrInstructionCallGen *>(inst), name);296 return destroy(reinterpret_cast<IrInstructionCallGen *>(inst), name);
294 case IrInstructionIdUnOp:297 case IrInstructionIdUnOp:
...@@ -705,6 +708,13 @@ static bool is_opt_err_set(ZigType *ty) {...@@ -705,6 +708,13 @@ static bool is_opt_err_set(ZigType *ty) {
705 (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet);708 (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet);
706}709}
707710
711static bool is_tuple(ZigType *type) {
712 return type->id == ZigTypeIdStruct && type->data.structure.decl_node != nullptr &&
713 type->data.structure.decl_node->type == NodeTypeContainerInitExpr &&
714 (type->data.structure.decl_node->data.container_init_expr.kind == ContainerInitKindArray ||
715 type->data.structure.decl_node->data.container_init_expr.entries.length == 0);
716}
717
708static bool is_slice(ZigType *type) {718static bool is_slice(ZigType *type) {
709 return type->id == ZigTypeIdStruct && type->data.structure.is_slice;719 return type->id == ZigTypeIdStruct && type->data.structure.is_slice;
710}720}
...@@ -968,6 +978,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCallSrc *) {...@@ -968,6 +978,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCallSrc *) {
968 return IrInstructionIdCallSrc;978 return IrInstructionIdCallSrc;
969}979}
970980
981static constexpr IrInstructionId ir_instruction_id(IrInstructionCallExtra *) {
982 return IrInstructionIdCallExtra;
983}
984
971static constexpr IrInstructionId ir_instruction_id(IrInstructionCallGen *) {985static constexpr IrInstructionId ir_instruction_id(IrInstructionCallGen *) {
972 return IrInstructionIdCallGen;986 return IrInstructionIdCallGen;
973}987}
...@@ -1891,30 +1905,42 @@ static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, Ast...@@ -1891,30 +1905,42 @@ static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, Ast
1891 return &instruction->base;1905 return &instruction->base;
1892}1906}
18931907
1908static IrInstruction *ir_build_call_extra(IrBuilder *irb, Scope *scope, AstNode *source_node,
1909 IrInstruction *options, IrInstruction *fn_ref, IrInstruction *args, ResultLoc *result_loc)
1910{
1911 IrInstructionCallExtra *call_instruction = ir_build_instruction<IrInstructionCallExtra>(irb, scope, source_node);
1912 call_instruction->options = options;
1913 call_instruction->fn_ref = fn_ref;
1914 call_instruction->args = args;
1915 call_instruction->result_loc = result_loc;
1916
1917 ir_ref_instruction(options, irb->current_basic_block);
1918 ir_ref_instruction(fn_ref, irb->current_basic_block);
1919 ir_ref_instruction(args, irb->current_basic_block);
1920
1921 return &call_instruction->base;
1922}
1923
1894static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *source_node,1924static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
1895 ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,1925 ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
1896 bool is_comptime, FnInline fn_inline, CallModifier modifier, bool is_async_call_builtin,1926 IrInstruction *ret_ptr, CallModifier modifier, bool is_async_call_builtin,
1897 IrInstruction *new_stack, ResultLoc *result_loc)1927 IrInstruction *new_stack, ResultLoc *result_loc)
1898{1928{
1899 IrInstructionCallSrc *call_instruction = ir_build_instruction<IrInstructionCallSrc>(irb, scope, source_node);1929 IrInstructionCallSrc *call_instruction = ir_build_instruction<IrInstructionCallSrc>(irb, scope, source_node);
1900 call_instruction->fn_entry = fn_entry;1930 call_instruction->fn_entry = fn_entry;
1901 call_instruction->fn_ref = fn_ref;1931 call_instruction->fn_ref = fn_ref;
1902 call_instruction->is_comptime = is_comptime;
1903 call_instruction->fn_inline = fn_inline;
1904 call_instruction->args = args;1932 call_instruction->args = args;
1905 call_instruction->arg_count = arg_count;1933 call_instruction->arg_count = arg_count;
1906 call_instruction->modifier = modifier;1934 call_instruction->modifier = modifier;
1907 call_instruction->is_async_call_builtin = is_async_call_builtin;1935 call_instruction->is_async_call_builtin = is_async_call_builtin;
1908 call_instruction->new_stack = new_stack;1936 call_instruction->new_stack = new_stack;
1909 call_instruction->result_loc = result_loc;1937 call_instruction->result_loc = result_loc;
1938 call_instruction->ret_ptr = ret_ptr;
19101939
1911 if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block);1940 if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block);
1912 for (size_t i = 0; i < arg_count; i += 1)1941 for (size_t i = 0; i < arg_count; i += 1)
1913 ir_ref_instruction(args[i], irb->current_basic_block);1942 ir_ref_instruction(args[i], irb->current_basic_block);
1914 if (modifier == CallModifierAsync && new_stack != nullptr) {1943 if (ret_ptr != nullptr) ir_ref_instruction(ret_ptr, irb->current_basic_block);
1915 // in this case the arg at the end is the return pointer
1916 ir_ref_instruction(args[arg_count], irb->current_basic_block);
1917 }
1918 if (new_stack != nullptr) ir_ref_instruction(new_stack, irb->current_basic_block);1944 if (new_stack != nullptr) ir_ref_instruction(new_stack, irb->current_basic_block);
19191945
1920 return &call_instruction->base;1946 return &call_instruction->base;
...@@ -1922,7 +1948,7 @@ static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *s...@@ -1922,7 +1948,7 @@ static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *s
19221948
1923static IrInstructionCallGen *ir_build_call_gen(IrAnalyze *ira, IrInstruction *source_instruction,1949static IrInstructionCallGen *ir_build_call_gen(IrAnalyze *ira, IrInstruction *source_instruction,
1924 ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,1950 ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
1925 FnInline fn_inline, CallModifier modifier, IrInstruction *new_stack, bool is_async_call_builtin,1951 CallModifier modifier, IrInstruction *new_stack, bool is_async_call_builtin,
1926 IrInstruction *result_loc, ZigType *return_type)1952 IrInstruction *result_loc, ZigType *return_type)
1927{1953{
1928 IrInstructionCallGen *call_instruction = ir_build_instruction<IrInstructionCallGen>(&ira->new_irb,1954 IrInstructionCallGen *call_instruction = ir_build_instruction<IrInstructionCallGen>(&ira->new_irb,
...@@ -1930,7 +1956,6 @@ static IrInstructionCallGen *ir_build_call_gen(IrAnalyze *ira, IrInstruction *so...@@ -1930,7 +1956,6 @@ static IrInstructionCallGen *ir_build_call_gen(IrAnalyze *ira, IrInstruction *so
1930 call_instruction->base.value->type = return_type;1956 call_instruction->base.value->type = return_type;
1931 call_instruction->fn_entry = fn_entry;1957 call_instruction->fn_entry = fn_entry;
1932 call_instruction->fn_ref = fn_ref;1958 call_instruction->fn_ref = fn_ref;
1933 call_instruction->fn_inline = fn_inline;
1934 call_instruction->args = args;1959 call_instruction->args = args;
1935 call_instruction->arg_count = arg_count;1960 call_instruction->arg_count = arg_count;
1936 call_instruction->modifier = modifier;1961 call_instruction->modifier = modifier;
...@@ -5054,10 +5079,7 @@ static IrInstruction *ir_gen_async_call(IrBuilder *irb, Scope *scope, AstNode *a...@@ -5054,10 +5079,7 @@ static IrInstruction *ir_gen_async_call(IrBuilder *irb, Scope *scope, AstNode *a
5054 return fn_ref;5079 return fn_ref;
50555080
5056 size_t arg_count = call_node->data.fn_call_expr.params.length - arg_offset;5081 size_t arg_count = call_node->data.fn_call_expr.params.length - arg_offset;
50575082 IrInstruction **args = allocate<IrInstruction*>(arg_count);
5058 // last "arg" is return pointer
5059 IrInstruction **args = allocate<IrInstruction*>(arg_count + 1);
5060
5061 for (size_t i = 0; i < arg_count; i += 1) {5083 for (size_t i = 0; i < arg_count; i += 1) {
5062 AstNode *arg_node = call_node->data.fn_call_expr.params.at(i + arg_offset);5084 AstNode *arg_node = call_node->data.fn_call_expr.params.at(i + arg_offset);
5063 IrInstruction *arg = ir_gen_node(irb, arg_node, scope);5085 IrInstruction *arg = ir_gen_node(irb, arg_node, scope);
...@@ -5066,12 +5088,10 @@ static IrInstruction *ir_gen_async_call(IrBuilder *irb, Scope *scope, AstNode *a...@@ -5066,12 +5088,10 @@ static IrInstruction *ir_gen_async_call(IrBuilder *irb, Scope *scope, AstNode *a
5066 args[i] = arg;5088 args[i] = arg;
5067 }5089 }
50685090
5069 args[arg_count] = ret_ptr;
5070
5071 CallModifier modifier = (await_node == nullptr) ? CallModifierAsync : CallModifierNone;5091 CallModifier modifier = (await_node == nullptr) ? CallModifierAsync : CallModifierNone;
5072 bool is_async_call_builtin = true;5092 bool is_async_call_builtin = true;
5073 IrInstruction *call = ir_build_call_src(irb, scope, call_node, nullptr, fn_ref, arg_count, args, false,5093 IrInstruction *call = ir_build_call_src(irb, scope, call_node, nullptr, fn_ref, arg_count, args,
5074 FnInlineAuto, modifier, is_async_call_builtin, bytes, result_loc);5094 ret_ptr, modifier, is_async_call_builtin, bytes, result_loc);
5075 return ir_lval_wrap(irb, scope, call, lval, result_loc);5095 return ir_lval_wrap(irb, scope, call, lval, result_loc);
5076}5096}
50775097
...@@ -6015,10 +6035,11 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -6015,10 +6035,11 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
6015 if (args[i] == irb->codegen->invalid_instruction)6035 if (args[i] == irb->codegen->invalid_instruction)
6016 return args[i];6036 return args[i];
6017 }6037 }
6018 FnInline fn_inline = (builtin_fn->id == BuiltinFnIdInlineCall) ? FnInlineAlways : FnInlineNever;6038 CallModifier modifier = (builtin_fn->id == BuiltinFnIdInlineCall) ?
6039 CallModifierAlwaysInline : CallModifierNeverInline;
60196040
6020 IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,6041 IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args,
6021 fn_inline, CallModifierNone, false, nullptr, result_loc);6042 nullptr, modifier, false, nullptr, result_loc);
6022 return ir_lval_wrap(irb, scope, call, lval, result_loc);6043 return ir_lval_wrap(irb, scope, call, lval, result_loc);
6023 }6044 }
6024 case BuiltinFnIdNewStackCall:6045 case BuiltinFnIdNewStackCall:
...@@ -6050,10 +6071,36 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -6050,10 +6071,36 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
6050 return args[i];6071 return args[i];
6051 }6072 }
60526073
6053 IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,6074 IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args,
6054 FnInlineAuto, CallModifierNone, false, new_stack, result_loc);6075 nullptr, CallModifierNone, false, new_stack, result_loc);
6055 return ir_lval_wrap(irb, scope, call, lval, result_loc);6076 return ir_lval_wrap(irb, scope, call, lval, result_loc);
6056 }6077 }
6078 case BuiltinFnIdCall: {
6079 // Cast the options parameter to the options type
6080 ZigType *options_type = get_builtin_type(irb->codegen, "CallOptions");
6081 IrInstruction *options_type_inst = ir_build_const_type(irb, scope, node, options_type);
6082 ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, options_type_inst, no_result_loc());
6083
6084 AstNode *options_node = node->data.fn_call_expr.params.at(0);
6085 IrInstruction *options_inner = ir_gen_node_extra(irb, options_node, scope,
6086 LValNone, &result_loc_cast->base);
6087 if (options_inner == irb->codegen->invalid_instruction)
6088 return options_inner;
6089 IrInstruction *options = ir_build_implicit_cast(irb, scope, options_node, options_inner, result_loc_cast);
6090
6091 AstNode *fn_ref_node = node->data.fn_call_expr.params.at(1);
6092 IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, scope);
6093 if (fn_ref == irb->codegen->invalid_instruction)
6094 return fn_ref;
6095
6096 AstNode *args_node = node->data.fn_call_expr.params.at(2);
6097 IrInstruction *args = ir_gen_node(irb, args_node, scope);
6098 if (args == irb->codegen->invalid_instruction)
6099 return args;
6100
6101 IrInstruction *call = ir_build_call_extra(irb, scope, node, options, fn_ref, args, result_loc);
6102 return ir_lval_wrap(irb, scope, call, lval, result_loc);
6103 }
6057 case BuiltinFnIdAsyncCall:6104 case BuiltinFnIdAsyncCall:
6058 return ir_gen_async_call(irb, scope, nullptr, node, lval, result_loc);6105 return ir_gen_async_call(irb, scope, nullptr, node, lval, result_loc);
6059 case BuiltinFnIdTypeId:6106 case BuiltinFnIdTypeId:
...@@ -6395,8 +6442,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node...@@ -6395,8 +6442,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
6395 args[i] = ir_build_implicit_cast(irb, scope, arg_node, arg, result_loc_cast);6442 args[i] = ir_build_implicit_cast(irb, scope, arg_node, arg, result_loc_cast);
6396 }6443 }
63976444
6398 IrInstruction *fn_call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,6445 IrInstruction *fn_call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, nullptr,
6399 FnInlineAuto, node->data.fn_call_expr.modifier, false, nullptr, result_loc);6446 node->data.fn_call_expr.modifier, false, nullptr, result_loc);
6400 return ir_lval_wrap(irb, scope, fn_call, lval, result_loc);6447 return ir_lval_wrap(irb, scope, fn_call, lval, result_loc);
6401}6448}
64026449
...@@ -14102,9 +14149,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic...@@ -14102,9 +14149,7 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic
14102 if (type_is_invalid(value->value->type))14149 if (type_is_invalid(value->value->type))
14103 return false;14150 return false;
1410414151
14105 ZigValue *atomic_order_val = get_builtin_value(ira->codegen, "AtomicOrder");14152 ZigType *atomic_order_type = get_builtin_type(ira->codegen, "AtomicOrder");
14106 assert(atomic_order_val->type->id == ZigTypeIdMetaType);
14107 ZigType *atomic_order_type = atomic_order_val->data.x_type;
1410814153
14109 IrInstruction *casted_value = ir_implicit_cast(ira, value, atomic_order_type);14154 IrInstruction *casted_value = ir_implicit_cast(ira, value, atomic_order_type);
14110 if (type_is_invalid(casted_value->value->type))14155 if (type_is_invalid(casted_value->value->type))
...@@ -14122,9 +14167,7 @@ static bool ir_resolve_atomic_rmw_op(IrAnalyze *ira, IrInstruction *value, Atomi...@@ -14122,9 +14167,7 @@ static bool ir_resolve_atomic_rmw_op(IrAnalyze *ira, IrInstruction *value, Atomi
14122 if (type_is_invalid(value->value->type))14167 if (type_is_invalid(value->value->type))
14123 return false;14168 return false;
1412414169
14125 ZigValue *atomic_rmw_op_val = get_builtin_value(ira->codegen, "AtomicRmwOp");14170 ZigType *atomic_rmw_op_type = get_builtin_type(ira->codegen, "AtomicRmwOp");
14126 assert(atomic_rmw_op_val->type->id == ZigTypeIdMetaType);
14127 ZigType *atomic_rmw_op_type = atomic_rmw_op_val->data.x_type;
1412814171
14129 IrInstruction *casted_value = ir_implicit_cast(ira, value, atomic_rmw_op_type);14172 IrInstruction *casted_value = ir_implicit_cast(ira, value, atomic_rmw_op_type);
14130 if (type_is_invalid(casted_value->value->type))14173 if (type_is_invalid(casted_value->value->type))
...@@ -14142,9 +14185,7 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob...@@ -14142,9 +14185,7 @@ static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, Glob
14142 if (type_is_invalid(value->value->type))14185 if (type_is_invalid(value->value->type))
14143 return false;14186 return false;
1414414187
14145 ZigValue *global_linkage_val = get_builtin_value(ira->codegen, "GlobalLinkage");14188 ZigType *global_linkage_type = get_builtin_type(ira->codegen, "GlobalLinkage");
14146 assert(global_linkage_val->type->id == ZigTypeIdMetaType);
14147 ZigType *global_linkage_type = global_linkage_val->data.x_type;
1414814189
14149 IrInstruction *casted_value = ir_implicit_cast(ira, value, global_linkage_type);14190 IrInstruction *casted_value = ir_implicit_cast(ira, value, global_linkage_type);
14150 if (type_is_invalid(casted_value->value->type))14191 if (type_is_invalid(casted_value->value->type))
...@@ -14162,9 +14203,7 @@ static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstruction *value, FloatMod...@@ -14162,9 +14203,7 @@ static bool ir_resolve_float_mode(IrAnalyze *ira, IrInstruction *value, FloatMod
14162 if (type_is_invalid(value->value->type))14203 if (type_is_invalid(value->value->type))
14163 return false;14204 return false;
1416414205
14165 ZigValue *float_mode_val = get_builtin_value(ira->codegen, "FloatMode");14206 ZigType *float_mode_type = get_builtin_type(ira->codegen, "FloatMode");
14166 assert(float_mode_val->type->id == ZigTypeIdMetaType);
14167 ZigType *float_mode_type = float_mode_val->data.x_type;
1416814207
14169 IrInstruction *casted_value = ir_implicit_cast(ira, value, float_mode_type);14208 IrInstruction *casted_value = ir_implicit_cast(ira, value, float_mode_type);
14170 if (type_is_invalid(casted_value->value->type))14209 if (type_is_invalid(casted_value->value->type))
...@@ -16972,11 +17011,11 @@ static IrInstruction *ir_analyze_instruction_reset_result(IrAnalyze *ira, IrInst...@@ -16972,11 +17011,11 @@ static IrInstruction *ir_analyze_instruction_reset_result(IrAnalyze *ira, IrInst
16972 return ir_const_void(ira, &instruction->base);17011 return ir_const_void(ira, &instruction->base);
16973}17012}
1697417013
16975static IrInstruction *get_async_call_result_loc(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,17014static IrInstruction *get_async_call_result_loc(IrAnalyze *ira, IrInstruction *source_instr,
16976 ZigType *fn_ret_type)17015 ZigType *fn_ret_type, bool is_async_call_builtin, IrInstruction **args_ptr, size_t args_len,
17016 IrInstruction *ret_ptr_uncasted)
16977{17017{
16978 ir_assert(call_instruction->is_async_call_builtin, &call_instruction->base);17018 ir_assert(is_async_call_builtin, source_instr);
16979 IrInstruction *ret_ptr_uncasted = call_instruction->args[call_instruction->arg_count]->child;
16980 if (type_is_invalid(ret_ptr_uncasted->value->type))17019 if (type_is_invalid(ret_ptr_uncasted->value->type))
16981 return ira->codegen->invalid_instruction;17020 return ira->codegen->invalid_instruction;
16982 if (ret_ptr_uncasted->value->type->id == ZigTypeIdVoid) {17021 if (ret_ptr_uncasted->value->type->id == ZigTypeIdVoid) {
...@@ -16986,9 +17025,10 @@ static IrInstruction *get_async_call_result_loc(IrAnalyze *ira, IrInstructionCal...@@ -16986,9 +17025,10 @@ static IrInstruction *get_async_call_result_loc(IrAnalyze *ira, IrInstructionCal
16986 return ir_implicit_cast(ira, ret_ptr_uncasted, get_pointer_to_type(ira->codegen, fn_ret_type, false));17025 return ir_implicit_cast(ira, ret_ptr_uncasted, get_pointer_to_type(ira->codegen, fn_ret_type, false));
16987}17026}
1698817027
16989static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction, ZigFn *fn_entry,17028static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstruction *source_instr, ZigFn *fn_entry,
16990 ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count,17029 ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count,
16991 IrInstruction *casted_new_stack)17030 IrInstruction *casted_new_stack, bool is_async_call_builtin, IrInstruction *ret_ptr_uncasted,
17031 ResultLoc *call_result_loc)
16992{17032{
16993 if (fn_entry == nullptr) {17033 if (fn_entry == nullptr) {
16994 if (fn_type->data.fn.fn_type_id.cc != CallingConventionAsync) {17034 if (fn_type->data.fn.fn_type_id.cc != CallingConventionAsync) {
...@@ -17003,19 +17043,20 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc...@@ -17003,19 +17043,20 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc
17003 }17043 }
17004 if (casted_new_stack != nullptr) {17044 if (casted_new_stack != nullptr) {
17005 ZigType *fn_ret_type = fn_type->data.fn.fn_type_id.return_type;17045 ZigType *fn_ret_type = fn_type->data.fn.fn_type_id.return_type;
17006 IrInstruction *ret_ptr = get_async_call_result_loc(ira, call_instruction, fn_ret_type);17046 IrInstruction *ret_ptr = get_async_call_result_loc(ira, source_instr, fn_ret_type, is_async_call_builtin,
17047 casted_args, arg_count, ret_ptr_uncasted);
17007 if (ret_ptr != nullptr && type_is_invalid(ret_ptr->value->type))17048 if (ret_ptr != nullptr && type_is_invalid(ret_ptr->value->type))
17008 return ira->codegen->invalid_instruction;17049 return ira->codegen->invalid_instruction;
1700917050
17010 ZigType *anyframe_type = get_any_frame_type(ira->codegen, fn_ret_type);17051 ZigType *anyframe_type = get_any_frame_type(ira->codegen, fn_ret_type);
1701117052
17012 IrInstructionCallGen *call_gen = ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref,17053 IrInstructionCallGen *call_gen = ir_build_call_gen(ira, source_instr, fn_entry, fn_ref,
17013 arg_count, casted_args, FnInlineAuto, CallModifierAsync, casted_new_stack,17054 arg_count, casted_args, CallModifierAsync, casted_new_stack,
17014 call_instruction->is_async_call_builtin, ret_ptr, anyframe_type);17055 is_async_call_builtin, ret_ptr, anyframe_type);
17015 return &call_gen->base;17056 return &call_gen->base;
17016 } else {17057 } else {
17017 ZigType *frame_type = get_fn_frame_type(ira->codegen, fn_entry);17058 ZigType *frame_type = get_fn_frame_type(ira->codegen, fn_entry);
17018 IrInstruction *result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,17059 IrInstruction *result_loc = ir_resolve_result(ira, source_instr, call_result_loc,
17019 frame_type, nullptr, true, true, false);17060 frame_type, nullptr, true, true, false);
17020 if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) {17061 if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) {
17021 return result_loc;17062 return result_loc;
...@@ -17023,9 +17064,9 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc...@@ -17023,9 +17064,9 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc
17023 result_loc = ir_implicit_cast(ira, result_loc, get_pointer_to_type(ira->codegen, frame_type, false));17064 result_loc = ir_implicit_cast(ira, result_loc, get_pointer_to_type(ira->codegen, frame_type, false));
17024 if (type_is_invalid(result_loc->value->type))17065 if (type_is_invalid(result_loc->value->type))
17025 return ira->codegen->invalid_instruction;17066 return ira->codegen->invalid_instruction;
17026 return &ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref, arg_count,17067 return &ir_build_call_gen(ira, source_instr, fn_entry, fn_ref, arg_count,
17027 casted_args, FnInlineAuto, CallModifierAsync, casted_new_stack,17068 casted_args, CallModifierAsync, casted_new_stack,
17028 call_instruction->is_async_call_builtin, result_loc, frame_type)->base;17069 is_async_call_builtin, result_loc, frame_type)->base;
17029 }17070 }
17030}17071}
17031static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node,17072static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node,
...@@ -17417,25 +17458,21 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -17417,25 +17458,21 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
17417 return &store_ptr->base;17458 return &store_ptr->base;
17418}17459}
1741917460
17420static IrInstruction *analyze_casted_new_stack(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,17461static IrInstruction *analyze_casted_new_stack(IrAnalyze *ira, IrInstruction *source_instr,
17421 ZigFn *fn_entry)17462 IrInstruction *new_stack, bool is_async_call_builtin, ZigFn *fn_entry)
17422{17463{
17423 if (call_instruction->new_stack == nullptr)17464 if (new_stack == nullptr)
17424 return nullptr;17465 return nullptr;
1742517466
17426 if (!call_instruction->is_async_call_builtin &&17467 if (!is_async_call_builtin &&
17427 arch_stack_pointer_register_name(ira->codegen->zig_target->arch) == nullptr)17468 arch_stack_pointer_register_name(ira->codegen->zig_target->arch) == nullptr)
17428 {17469 {
17429 ir_add_error(ira, &call_instruction->base,17470 ir_add_error(ira, source_instr,
17430 buf_sprintf("target arch '%s' does not support @newStackCall",17471 buf_sprintf("target arch '%s' does not support @newStackCall",
17431 target_arch_name(ira->codegen->zig_target->arch)));17472 target_arch_name(ira->codegen->zig_target->arch)));
17432 }17473 }
1743317474
17434 IrInstruction *new_stack = call_instruction->new_stack->child;17475 if (is_async_call_builtin &&
17435 if (type_is_invalid(new_stack->value->type))
17436 return ira->codegen->invalid_instruction;
17437
17438 if (call_instruction->is_async_call_builtin &&
17439 fn_entry != nullptr && new_stack->value->type->id == ZigTypeIdPointer &&17476 fn_entry != nullptr && new_stack->value->type->id == ZigTypeIdPointer &&
17440 new_stack->value->type->data.pointer.child_type->id == ZigTypeIdFnFrame)17477 new_stack->value->type->data.pointer.child_type->id == ZigTypeIdFnFrame)
17441 {17478 {
...@@ -17451,9 +17488,11 @@ static IrInstruction *analyze_casted_new_stack(IrAnalyze *ira, IrInstructionCall...@@ -17451,9 +17488,11 @@ static IrInstruction *analyze_casted_new_stack(IrAnalyze *ira, IrInstructionCall
17451 }17488 }
17452}17489}
1745317490
17454static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,17491static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstruction *source_instr,
17455 ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,17492 ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,
17456 IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline)17493 IrInstruction *first_arg_ptr, CallModifier modifier,
17494 IrInstruction *new_stack, bool is_async_call_builtin,
17495 IrInstruction **args_ptr, size_t args_len, IrInstruction *ret_ptr, ResultLoc *call_result_loc)
17457{17496{
17458 Error err;17497 Error err;
17459 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;17498 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
...@@ -17469,16 +17508,16 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17469,16 +17508,16 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
17469 }17508 }
17470 size_t src_param_count = fn_type_id->param_count - var_args_1_or_0;17509 size_t src_param_count = fn_type_id->param_count - var_args_1_or_0;
1747117510
17472 size_t call_param_count = call_instruction->arg_count + first_arg_1_or_0;17511 size_t call_param_count = args_len + first_arg_1_or_0;
17473 for (size_t i = 0; i < call_instruction->arg_count; i += 1) {17512 for (size_t i = 0; i < args_len; i += 1) {
17474 ZigValue *arg_tuple_value = call_instruction->args[i]->child->value;17513 ZigValue *arg_tuple_value = args_ptr[i]->value;
17475 if (arg_tuple_value->type->id == ZigTypeIdArgTuple) {17514 if (arg_tuple_value->type->id == ZigTypeIdArgTuple) {
17476 call_param_count -= 1;17515 call_param_count -= 1;
17477 call_param_count += arg_tuple_value->data.x_arg_tuple.end_index -17516 call_param_count += arg_tuple_value->data.x_arg_tuple.end_index -
17478 arg_tuple_value->data.x_arg_tuple.start_index;17517 arg_tuple_value->data.x_arg_tuple.start_index;
17479 }17518 }
17480 }17519 }
17481 AstNode *source_node = call_instruction->base.source_node;17520 AstNode *source_node = source_instr->source_node;
1748217521
17483 AstNode *fn_proto_node = fn_entry ? fn_entry->proto_node : nullptr;;17522 AstNode *fn_proto_node = fn_entry ? fn_entry->proto_node : nullptr;;
1748417523
...@@ -17511,14 +17550,14 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17511,14 +17550,14 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
17511 return ira->codegen->invalid_instruction;17550 return ira->codegen->invalid_instruction;
17512 }17551 }
1751317552
17514 if (comptime_fn_call) {17553 if (modifier == CallModifierCompileTime) {
17515 // No special handling is needed for compile time evaluation of generic functions.17554 // No special handling is needed for compile time evaluation of generic functions.
17516 if (!fn_entry || fn_entry->body_node == nullptr) {17555 if (!fn_entry || fn_entry->body_node == nullptr) {
17517 ir_add_error(ira, fn_ref, buf_sprintf("unable to evaluate constant expression"));17556 ir_add_error(ira, fn_ref, buf_sprintf("unable to evaluate constant expression"));
17518 return ira->codegen->invalid_instruction;17557 return ira->codegen->invalid_instruction;
17519 }17558 }
1752017559
17521 if (!ir_emit_backward_branch(ira, &call_instruction->base))17560 if (!ir_emit_backward_branch(ira, source_instr))
17522 return ira->codegen->invalid_instruction;17561 return ira->codegen->invalid_instruction;
1752317562
17524 // Fork a scope of the function with known values for the parameters.17563 // Fork a scope of the function with known values for the parameters.
...@@ -17550,16 +17589,14 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17550,16 +17589,14 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
17550 }17589 }
1755117590
17552 if (fn_proto_node->data.fn_proto.is_var_args) {17591 if (fn_proto_node->data.fn_proto.is_var_args) {
17553 ir_add_error(ira, &call_instruction->base,17592 ir_add_error(ira, source_instr,
17554 buf_sprintf("compiler bug: unable to call var args function at compile time. https://github.com/ziglang/zig/issues/313"));17593 buf_sprintf("compiler bug: unable to call var args function at compile time. https://github.com/ziglang/zig/issues/313"));
17555 return ira->codegen->invalid_instruction;17594 return ira->codegen->invalid_instruction;
17556 }17595 }
1755717596
1755817597
17559 for (size_t call_i = 0; call_i < call_instruction->arg_count; call_i += 1) {17598 for (size_t call_i = 0; call_i < args_len; call_i += 1) {
17560 IrInstruction *old_arg = call_instruction->args[call_i]->child;17599 IrInstruction *old_arg = args_ptr[call_i];
17561 if (type_is_invalid(old_arg->value->type))
17562 return ira->codegen->invalid_instruction;
1756317600
17564 if (!ir_analyze_fn_call_inline_arg(ira, fn_proto_node, old_arg, &exec_scope, &next_proto_i))17601 if (!ir_analyze_fn_call_inline_arg(ira, fn_proto_node, old_arg, &exec_scope, &next_proto_i))
17565 return ira->codegen->invalid_instruction;17602 return ira->codegen->invalid_instruction;
...@@ -17593,7 +17630,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17593,7 +17630,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
17593 AstNode *body_node = fn_entry->body_node;17630 AstNode *body_node = fn_entry->body_node;
17594 result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,17631 result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,
17595 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry,17632 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry,
17596 nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec, return_type_node,17633 nullptr, source_instr->source_node, nullptr, ira->new_irb.exec, return_type_node,
17597 UndefOk);17634 UndefOk);
1759817635
17599 if (inferred_err_set_type != nullptr) {17636 if (inferred_err_set_type != nullptr) {
...@@ -17623,24 +17660,21 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17623,24 +17660,21 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
17623 }17660 }
17624 }17661 }
1762517662
17626 IrInstruction *new_instruction = ir_const_move(ira, &call_instruction->base, result);17663 IrInstruction *new_instruction = ir_const_move(ira, source_instr, result);
17627 return ir_finish_anal(ira, new_instruction);17664 return ir_finish_anal(ira, new_instruction);
17628 }17665 }
1762917666
17630 if (fn_type->data.fn.is_generic) {17667 if (fn_type->data.fn.is_generic) {
17631 if (!fn_entry) {17668 if (!fn_entry) {
17632 ir_add_error(ira, call_instruction->fn_ref,17669 ir_add_error(ira, fn_ref,
17633 buf_sprintf("calling a generic function requires compile-time known function value"));17670 buf_sprintf("calling a generic function requires compile-time known function value"));
17634 return ira->codegen->invalid_instruction;17671 return ira->codegen->invalid_instruction;
17635 }17672 }
1763617673
17637 // Count the arguments of the function type id we are creating17674 // Count the arguments of the function type id we are creating
17638 size_t new_fn_arg_count = first_arg_1_or_0;17675 size_t new_fn_arg_count = first_arg_1_or_0;
17639 for (size_t call_i = 0; call_i < call_instruction->arg_count; call_i += 1) {17676 for (size_t call_i = 0; call_i < args_len; call_i += 1) {
17640 IrInstruction *arg = call_instruction->args[call_i]->child;17677 IrInstruction *arg = args_ptr[call_i];
17641 if (type_is_invalid(arg->value->type))
17642 return ira->codegen->invalid_instruction;
17643
17644 if (arg->value->type->id == ZigTypeIdArgTuple) {17678 if (arg->value->type->id == ZigTypeIdArgTuple) {
17645 new_fn_arg_count += arg->value->data.x_arg_tuple.end_index - arg->value->data.x_arg_tuple.start_index;17679 new_fn_arg_count += arg->value->data.x_arg_tuple.end_index - arg->value->data.x_arg_tuple.start_index;
17646 } else {17680 } else {
...@@ -17702,10 +17736,8 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17702,10 +17736,8 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
1770217736
17703 ZigFn *parent_fn_entry = exec_fn_entry(ira->new_irb.exec);17737 ZigFn *parent_fn_entry = exec_fn_entry(ira->new_irb.exec);
17704 assert(parent_fn_entry);17738 assert(parent_fn_entry);
17705 for (size_t call_i = 0; call_i < call_instruction->arg_count; call_i += 1) {17739 for (size_t call_i = 0; call_i < args_len; call_i += 1) {
17706 IrInstruction *arg = call_instruction->args[call_i]->child;17740 IrInstruction *arg = args_ptr[call_i];
17707 if (type_is_invalid(arg->value->type))
17708 return ira->codegen->invalid_instruction;
1770917741
17710 if (arg->value->type->id == ZigTypeIdArgTuple) {17742 if (arg->value->type->id == ZigTypeIdArgTuple) {
17711 for (size_t arg_tuple_i = arg->value->data.x_arg_tuple.start_index;17743 for (size_t arg_tuple_i = arg->value->data.x_arg_tuple.start_index;
...@@ -17804,8 +17836,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17804,8 +17836,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
17804 switch (type_requires_comptime(ira->codegen, specified_return_type)) {17836 switch (type_requires_comptime(ira->codegen, specified_return_type)) {
17805 case ReqCompTimeYes:17837 case ReqCompTimeYes:
17806 // Throw out our work and call the function as if it were comptime.17838 // Throw out our work and call the function as if it were comptime.
17807 return ir_analyze_fn_call(ira, call_instruction, fn_entry, fn_type, fn_ref, first_arg_ptr,17839 return ir_analyze_fn_call(ira, source_instr, fn_entry, fn_type, fn_ref, first_arg_ptr,
17808 true, FnInlineAuto);17840 CallModifierCompileTime, new_stack, is_async_call_builtin, args_ptr, args_len,
17841 ret_ptr, call_result_loc);
17809 case ReqCompTimeInvalid:17842 case ReqCompTimeInvalid:
17810 return ira->codegen->invalid_instruction;17843 return ira->codegen->invalid_instruction;
17811 case ReqCompTimeNo:17844 case ReqCompTimeNo:
...@@ -17823,9 +17856,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17823,9 +17856,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
17823 if (type_is_invalid(impl_fn->type_entry))17856 if (type_is_invalid(impl_fn->type_entry))
17824 return ira->codegen->invalid_instruction;17857 return ira->codegen->invalid_instruction;
1782517858
17826 impl_fn->ir_executable->source_node = call_instruction->base.source_node;17859 impl_fn->ir_executable->source_node = source_instr->source_node;
17827 impl_fn->ir_executable->parent_exec = ira->new_irb.exec;17860 impl_fn->ir_executable->parent_exec = ira->new_irb.exec;
17828 impl_fn->analyzed_executable.source_node = call_instruction->base.source_node;17861 impl_fn->analyzed_executable.source_node = source_instr->source_node;
17829 impl_fn->analyzed_executable.parent_exec = ira->new_irb.exec;17862 impl_fn->analyzed_executable.parent_exec = ira->new_irb.exec;
17830 impl_fn->analyzed_executable.backward_branch_quota = ira->new_irb.exec->backward_branch_quota;17863 impl_fn->analyzed_executable.backward_branch_quota = ira->new_irb.exec->backward_branch_quota;
17831 impl_fn->analyzed_executable.is_generic_instantiation = true;17864 impl_fn->analyzed_executable.is_generic_instantiation = true;
...@@ -17839,32 +17872,35 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17839,32 +17872,35 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
17839 parent_fn_entry->calls_or_awaits_errorable_fn = true;17872 parent_fn_entry->calls_or_awaits_errorable_fn = true;
17840 }17873 }
1784117874
17842 IrInstruction *casted_new_stack = analyze_casted_new_stack(ira, call_instruction, impl_fn);17875 IrInstruction *casted_new_stack = analyze_casted_new_stack(ira, source_instr, new_stack,
17876 is_async_call_builtin, impl_fn);
17843 if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value->type))17877 if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value->type))
17844 return ira->codegen->invalid_instruction;17878 return ira->codegen->invalid_instruction;
1784517879
17846 size_t impl_param_count = impl_fn_type_id->param_count;17880 size_t impl_param_count = impl_fn_type_id->param_count;
17847 if (call_instruction->modifier == CallModifierAsync) {17881 if (modifier == CallModifierAsync) {
17848 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,17882 IrInstruction *result = ir_analyze_async_call(ira, source_instr, impl_fn, impl_fn->type_entry,
17849 nullptr, casted_args, impl_param_count, casted_new_stack);17883 nullptr, casted_args, impl_param_count, casted_new_stack, is_async_call_builtin, ret_ptr,
17884 call_result_loc);
17850 return ir_finish_anal(ira, result);17885 return ir_finish_anal(ira, result);
17851 }17886 }
1785217887
17853 IrInstruction *result_loc;17888 IrInstruction *result_loc;
17854 if (handle_is_ptr(impl_fn_type_id->return_type)) {17889 if (handle_is_ptr(impl_fn_type_id->return_type)) {
17855 result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,17890 result_loc = ir_resolve_result(ira, source_instr, call_result_loc,
17856 impl_fn_type_id->return_type, nullptr, true, true, false);17891 impl_fn_type_id->return_type, nullptr, true, true, false);
17857 if (result_loc != nullptr) {17892 if (result_loc != nullptr) {
17858 if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) {17893 if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) {
17859 return result_loc;17894 return result_loc;
17860 }17895 }
17861 if (!handle_is_ptr(result_loc->value->type->data.pointer.child_type)) {17896 if (!handle_is_ptr(result_loc->value->type->data.pointer.child_type)) {
17862 ir_reset_result(call_instruction->result_loc);17897 ir_reset_result(call_result_loc);
17863 result_loc = nullptr;17898 result_loc = nullptr;
17864 }17899 }
17865 }17900 }
17866 } else if (call_instruction->is_async_call_builtin) {17901 } else if (is_async_call_builtin) {
17867 result_loc = get_async_call_result_loc(ira, call_instruction, impl_fn_type_id->return_type);17902 result_loc = get_async_call_result_loc(ira, source_instr, impl_fn_type_id->return_type,
17903 is_async_call_builtin, args_ptr, args_len, ret_ptr);
17868 if (result_loc != nullptr && type_is_invalid(result_loc->value->type))17904 if (result_loc != nullptr && type_is_invalid(result_loc->value->type))
17869 return ira->codegen->invalid_instruction;17905 return ira->codegen->invalid_instruction;
17870 } else {17906 } else {
...@@ -17873,18 +17909,17 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17873,18 +17909,17 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
1787317909
17874 if (impl_fn_type_id->cc == CallingConventionAsync &&17910 if (impl_fn_type_id->cc == CallingConventionAsync &&
17875 parent_fn_entry->inferred_async_node == nullptr &&17911 parent_fn_entry->inferred_async_node == nullptr &&
17876 call_instruction->modifier != CallModifierNoAsync)17912 modifier != CallModifierNoAsync)
17877 {17913 {
17878 parent_fn_entry->inferred_async_node = fn_ref->source_node;17914 parent_fn_entry->inferred_async_node = fn_ref->source_node;
17879 parent_fn_entry->inferred_async_fn = impl_fn;17915 parent_fn_entry->inferred_async_fn = impl_fn;
17880 }17916 }
1788117917
17882 IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base,17918 IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, source_instr,
17883 impl_fn, nullptr, impl_param_count, casted_args, fn_inline,17919 impl_fn, nullptr, impl_param_count, casted_args, modifier, casted_new_stack,
17884 call_instruction->modifier, casted_new_stack, call_instruction->is_async_call_builtin, result_loc,17920 is_async_call_builtin, result_loc, impl_fn_type_id->return_type);
17885 impl_fn_type_id->return_type);
1788617921
17887 if (get_scope_typeof(call_instruction->base.scope) == nullptr) {17922 if (get_scope_typeof(source_instr->scope) == nullptr) {
17888 parent_fn_entry->call_list.append(new_call_instruction);17923 parent_fn_entry->call_list.append(new_call_instruction);
17889 }17924 }
1789017925
...@@ -17926,8 +17961,8 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17926,8 +17961,8 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
17926 casted_args[next_arg_index] = casted_arg;17961 casted_args[next_arg_index] = casted_arg;
17927 next_arg_index += 1;17962 next_arg_index += 1;
17928 }17963 }
17929 for (size_t call_i = 0; call_i < call_instruction->arg_count; call_i += 1) {17964 for (size_t call_i = 0; call_i < args_len; call_i += 1) {
17930 IrInstruction *old_arg = call_instruction->args[call_i]->child;17965 IrInstruction *old_arg = args_ptr[call_i];
17931 if (type_is_invalid(old_arg->value->type))17966 if (type_is_invalid(old_arg->value->type))
17932 return ira->codegen->invalid_instruction;17967 return ira->codegen->invalid_instruction;
1793317968
...@@ -17988,25 +18023,26 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -17988,25 +18023,26 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
17988 if (type_is_invalid(return_type))18023 if (type_is_invalid(return_type))
17989 return ira->codegen->invalid_instruction;18024 return ira->codegen->invalid_instruction;
1799018025
17991 if (fn_entry != nullptr && fn_entry->fn_inline == FnInlineAlways && fn_inline == FnInlineNever) {18026 if (fn_entry != nullptr && fn_entry->fn_inline == FnInlineAlways && modifier == CallModifierNeverInline) {
17992 ir_add_error(ira, &call_instruction->base,18027 ir_add_error(ira, source_instr,
17993 buf_sprintf("no-inline call of inline function"));18028 buf_sprintf("no-inline call of inline function"));
17994 return ira->codegen->invalid_instruction;18029 return ira->codegen->invalid_instruction;
17995 }18030 }
1799618031
17997 IrInstruction *casted_new_stack = analyze_casted_new_stack(ira, call_instruction, fn_entry);18032 IrInstruction *casted_new_stack = analyze_casted_new_stack(ira, source_instr, new_stack,
18033 is_async_call_builtin, fn_entry);
17998 if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value->type))18034 if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value->type))
17999 return ira->codegen->invalid_instruction;18035 return ira->codegen->invalid_instruction;
1800018036
18001 if (call_instruction->modifier == CallModifierAsync) {18037 if (modifier == CallModifierAsync) {
18002 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref,18038 IrInstruction *result = ir_analyze_async_call(ira, source_instr, fn_entry, fn_type, fn_ref,
18003 casted_args, call_param_count, casted_new_stack);18039 casted_args, call_param_count, casted_new_stack, is_async_call_builtin, ret_ptr, call_result_loc);
18004 return ir_finish_anal(ira, result);18040 return ir_finish_anal(ira, result);
18005 }18041 }
1800618042
18007 if (fn_type_id->cc == CallingConventionAsync &&18043 if (fn_type_id->cc == CallingConventionAsync &&
18008 parent_fn_entry->inferred_async_node == nullptr &&18044 parent_fn_entry->inferred_async_node == nullptr &&
18009 call_instruction->modifier != CallModifierNoAsync)18045 modifier != CallModifierNoAsync)
18010 {18046 {
18011 parent_fn_entry->inferred_async_node = fn_ref->source_node;18047 parent_fn_entry->inferred_async_node = fn_ref->source_node;
18012 parent_fn_entry->inferred_async_fn = fn_entry;18048 parent_fn_entry->inferred_async_fn = fn_entry;
...@@ -18014,41 +18050,163 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -18014,41 +18050,163 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
1801418050
18015 IrInstruction *result_loc;18051 IrInstruction *result_loc;
18016 if (handle_is_ptr(return_type)) {18052 if (handle_is_ptr(return_type)) {
18017 result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,18053 result_loc = ir_resolve_result(ira, source_instr, call_result_loc,
18018 return_type, nullptr, true, true, false);18054 return_type, nullptr, true, true, false);
18019 if (result_loc != nullptr) {18055 if (result_loc != nullptr) {
18020 if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) {18056 if (type_is_invalid(result_loc->value->type) || instr_is_unreachable(result_loc)) {
18021 return result_loc;18057 return result_loc;
18022 }18058 }
18023 if (!handle_is_ptr(result_loc->value->type->data.pointer.child_type)) {18059 if (!handle_is_ptr(result_loc->value->type->data.pointer.child_type)) {
18024 ir_reset_result(call_instruction->result_loc);18060 ir_reset_result(call_result_loc);
18025 result_loc = nullptr;18061 result_loc = nullptr;
18026 }18062 }
18027 }18063 }
18028 } else if (call_instruction->is_async_call_builtin) {18064 } else if (is_async_call_builtin) {
18029 result_loc = get_async_call_result_loc(ira, call_instruction, return_type);18065 result_loc = get_async_call_result_loc(ira, source_instr, return_type, is_async_call_builtin,
18066 args_ptr, args_len, ret_ptr);
18030 if (result_loc != nullptr && type_is_invalid(result_loc->value->type))18067 if (result_loc != nullptr && type_is_invalid(result_loc->value->type))
18031 return ira->codegen->invalid_instruction;18068 return ira->codegen->invalid_instruction;
18032 } else {18069 } else {
18033 result_loc = nullptr;18070 result_loc = nullptr;
18034 }18071 }
1803518072
18036 IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref,18073 IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, source_instr, fn_entry, fn_ref,
18037 call_param_count, casted_args, fn_inline, call_instruction->modifier, casted_new_stack,18074 call_param_count, casted_args, modifier, casted_new_stack,
18038 call_instruction->is_async_call_builtin, result_loc, return_type);18075 is_async_call_builtin, result_loc, return_type);
18039 if (get_scope_typeof(call_instruction->base.scope) == nullptr) {18076 if (get_scope_typeof(source_instr->scope) == nullptr) {
18040 parent_fn_entry->call_list.append(new_call_instruction);18077 parent_fn_entry->call_list.append(new_call_instruction);
18041 }18078 }
18042 return ir_finish_anal(ira, &new_call_instruction->base);18079 return ir_finish_anal(ira, &new_call_instruction->base);
18043}18080}
1804418081
18082static IrInstruction *ir_analyze_fn_call_src(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,
18083 ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,
18084 IrInstruction *first_arg_ptr, CallModifier modifier)
18085{
18086 IrInstruction *new_stack = nullptr;
18087 if (call_instruction->new_stack) {
18088 new_stack = call_instruction->new_stack->child;
18089 if (type_is_invalid(new_stack->value->type))
18090 return ira->codegen->invalid_instruction;
18091 }
18092 IrInstruction **args_ptr = allocate<IrInstruction *>(call_instruction->arg_count, "IrInstruction *");
18093 for (size_t i = 0; i < call_instruction->arg_count; i += 1) {
18094 args_ptr[i] = call_instruction->args[i]->child;
18095 if (type_is_invalid(args_ptr[i]->value->type))
18096 return ira->codegen->invalid_instruction;
18097 }
18098 IrInstruction *ret_ptr = nullptr;
18099 if (call_instruction->ret_ptr != nullptr) {
18100 ret_ptr = call_instruction->ret_ptr->child;
18101 if (type_is_invalid(ret_ptr->value->type))
18102 return ira->codegen->invalid_instruction;
18103 }
18104 IrInstruction *result = ir_analyze_fn_call(ira, &call_instruction->base, fn_entry, fn_type, fn_ref,
18105 first_arg_ptr, modifier, new_stack, call_instruction->is_async_call_builtin,
18106 args_ptr, call_instruction->arg_count, ret_ptr, call_instruction->result_loc);
18107 deallocate(args_ptr, call_instruction->arg_count, "IrInstruction *");
18108 return result;
18109}
18110
18111static IrInstruction *ir_analyze_instruction_call_extra(IrAnalyze *ira, IrInstructionCallExtra *instruction) {
18112 IrInstruction *options = instruction->options->child;
18113 if (type_is_invalid(options->value->type))
18114 return ira->codegen->invalid_instruction;
18115
18116 IrInstruction *fn_ref = instruction->fn_ref->child;
18117 if (type_is_invalid(fn_ref->value->type))
18118 return ira->codegen->invalid_instruction;
18119 ZigFn *fn = ir_resolve_fn(ira, fn_ref);
18120 ZigType *fn_type = (fn != nullptr) ? fn->type_entry : fn_ref->value->type;
18121
18122 IrInstruction *args = instruction->args->child;
18123 ZigType *args_type = args->value->type;
18124 if (type_is_invalid(args_type))
18125 return ira->codegen->invalid_instruction;
18126
18127 if (args_type->id != ZigTypeIdStruct) {
18128 ir_add_error(ira, args,
18129 buf_sprintf("expected tuple or struct, found '%s'", buf_ptr(&args_type->name)));
18130 return ira->codegen->invalid_instruction;
18131 }
18132
18133 IrInstruction **args_ptr = nullptr;
18134 size_t args_len = 0;
18135
18136 if (is_tuple(args_type)) {
18137 args_len = args_type->data.structure.src_field_count;
18138 args_ptr = allocate<IrInstruction *>(args_len, "IrInstruction *");
18139 for (size_t i = 0; i < args_len; i += 1) {
18140 TypeStructField *arg_field = args_type->data.structure.fields[i];
18141 args_ptr[i] = ir_analyze_struct_value_field_value(ira, &instruction->base, args, arg_field);
18142 if (type_is_invalid(args_ptr[i]->value->type))
18143 return ira->codegen->invalid_instruction;
18144 }
18145 } else {
18146 ir_add_error(ira, args, buf_sprintf("TODO: struct args"));
18147 return ira->codegen->invalid_instruction;
18148 }
18149
18150 TypeStructField *modifier_field = find_struct_type_field(options->value->type, buf_create_from_str("modifier"));
18151 ir_assert(modifier_field != nullptr, &instruction->base);
18152 IrInstruction *modifier_inst = ir_analyze_struct_value_field_value(ira, &instruction->base, options, modifier_field);
18153 ZigValue *modifier_val = ir_resolve_const(ira, modifier_inst, UndefBad);
18154 if (modifier_val == nullptr)
18155 return ira->codegen->invalid_instruction;
18156 CallModifier modifier = (CallModifier)bigint_as_u32(&modifier_val->data.x_enum_tag);
18157 if (modifier == CallModifierAsync) {
18158 ir_add_error(ira, args, buf_sprintf("TODO: @call with async modifier"));
18159 return ira->codegen->invalid_instruction;
18160 }
18161 if (ir_should_inline(ira->new_irb.exec, instruction->base.scope)) {
18162 switch (modifier) {
18163 case CallModifierBuiltin:
18164 zig_unreachable();
18165 case CallModifierAsync:
18166 ir_add_error(ira, args, buf_sprintf("TODO: comptime @call with async modifier"));
18167 return ira->codegen->invalid_instruction;
18168 case CallModifierCompileTime:
18169 case CallModifierNone:
18170 case CallModifierAlwaysInline:
18171 case CallModifierAlwaysTail:
18172 case CallModifierNoAsync:
18173 modifier = CallModifierCompileTime;
18174 break;
18175 case CallModifierNeverInline:
18176 ir_add_error(ira, args,
18177 buf_sprintf("unable to perform 'never_inline' call at compile-time"));
18178 return ira->codegen->invalid_instruction;
18179 case CallModifierNeverTail:
18180 ir_add_error(ira, args,
18181 buf_sprintf("unable to perform 'never_tail' call at compile-time"));
18182 return ira->codegen->invalid_instruction;
18183 }
18184 }
18185
18186 TypeStructField *stack_field = find_struct_type_field(options->value->type, buf_create_from_str("stack"));
18187 ir_assert(stack_field != nullptr, &instruction->base);
18188 IrInstruction *stack = ir_analyze_struct_value_field_value(ira, &instruction->base, options, stack_field);
18189 IrInstruction *stack_is_non_null_inst = ir_analyze_test_non_null(ira, &instruction->base, stack);
18190 bool stack_is_non_null;
18191 if (!ir_resolve_bool(ira, stack_is_non_null_inst, &stack_is_non_null))
18192 return ira->codegen->invalid_instruction;
18193 if (!stack_is_non_null)
18194 stack = nullptr;
18195
18196 IrInstruction *result = ir_analyze_fn_call(ira, &instruction->base, fn, fn_type, fn_ref, nullptr,
18197 modifier, stack, false, args_ptr, args_len, nullptr, instruction->result_loc);
18198 deallocate(args_ptr, args_len, "IrInstruction *");
18199 return result;
18200}
18201
18045static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction) {18202static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction) {
18046 IrInstruction *fn_ref = call_instruction->fn_ref->child;18203 IrInstruction *fn_ref = call_instruction->fn_ref->child;
18047 if (type_is_invalid(fn_ref->value->type))18204 if (type_is_invalid(fn_ref->value->type))
18048 return ira->codegen->invalid_instruction;18205 return ira->codegen->invalid_instruction;
1804918206
18050 bool is_comptime = call_instruction->is_comptime ||18207 bool is_comptime = (call_instruction->modifier == CallModifierCompileTime) ||
18051 ir_should_inline(ira->new_irb.exec, call_instruction->base.scope);18208 ir_should_inline(ira->new_irb.exec, call_instruction->base.scope);
18209 CallModifier modifier = is_comptime ? CallModifierCompileTime : call_instruction->modifier;
1805218210
18053 if (is_comptime || instr_is_comptime(fn_ref)) {18211 if (is_comptime || instr_is_comptime(fn_ref)) {
18054 if (fn_ref->value->type->id == ZigTypeIdMetaType) {18212 if (fn_ref->value->type->id == ZigTypeIdMetaType) {
...@@ -18063,14 +18221,16 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC...@@ -18063,14 +18221,16 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC
18063 } else if (fn_ref->value->type->id == ZigTypeIdFn) {18221 } else if (fn_ref->value->type->id == ZigTypeIdFn) {
18064 ZigFn *fn_table_entry = ir_resolve_fn(ira, fn_ref);18222 ZigFn *fn_table_entry = ir_resolve_fn(ira, fn_ref);
18065 ZigType *fn_type = fn_table_entry ? fn_table_entry->type_entry : fn_ref->value->type;18223 ZigType *fn_type = fn_table_entry ? fn_table_entry->type_entry : fn_ref->value->type;
18066 return ir_analyze_fn_call(ira, call_instruction, fn_table_entry, fn_type,18224 CallModifier modifier = is_comptime ? CallModifierCompileTime : call_instruction->modifier;
18067 fn_ref, nullptr, is_comptime, call_instruction->fn_inline);18225 return ir_analyze_fn_call_src(ira, call_instruction, fn_table_entry, fn_type,
18226 fn_ref, nullptr, modifier);
18068 } else if (fn_ref->value->type->id == ZigTypeIdBoundFn) {18227 } else if (fn_ref->value->type->id == ZigTypeIdBoundFn) {
18069 assert(fn_ref->value->special == ConstValSpecialStatic);18228 assert(fn_ref->value->special == ConstValSpecialStatic);
18070 ZigFn *fn_table_entry = fn_ref->value->data.x_bound_fn.fn;18229 ZigFn *fn_table_entry = fn_ref->value->data.x_bound_fn.fn;
18071 IrInstruction *first_arg_ptr = fn_ref->value->data.x_bound_fn.first_arg;18230 IrInstruction *first_arg_ptr = fn_ref->value->data.x_bound_fn.first_arg;
18072 return ir_analyze_fn_call(ira, call_instruction, fn_table_entry, fn_table_entry->type_entry,18231 CallModifier modifier = is_comptime ? CallModifierCompileTime : call_instruction->modifier;
18073 fn_ref, first_arg_ptr, is_comptime, call_instruction->fn_inline);18232 return ir_analyze_fn_call_src(ira, call_instruction, fn_table_entry, fn_table_entry->type_entry,
18233 fn_ref, first_arg_ptr, modifier);
18074 } else {18234 } else {
18075 ir_add_error_node(ira, fn_ref->source_node,18235 ir_add_error_node(ira, fn_ref->source_node,
18076 buf_sprintf("type '%s' not a function", buf_ptr(&fn_ref->value->type->name)));18236 buf_sprintf("type '%s' not a function", buf_ptr(&fn_ref->value->type->name)));
...@@ -18079,8 +18239,8 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC...@@ -18079,8 +18239,8 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC
18079 }18239 }
1808018240
18081 if (fn_ref->value->type->id == ZigTypeIdFn) {18241 if (fn_ref->value->type->id == ZigTypeIdFn) {
18082 return ir_analyze_fn_call(ira, call_instruction, nullptr, fn_ref->value->type,18242 return ir_analyze_fn_call_src(ira, call_instruction, nullptr, fn_ref->value->type,
18083 fn_ref, nullptr, false, call_instruction->fn_inline);18243 fn_ref, nullptr, modifier);
18084 } else {18244 } else {
18085 ir_add_error_node(ira, fn_ref->source_node,18245 ir_add_error_node(ira, fn_ref->source_node,
18086 buf_sprintf("type '%s' not a function", buf_ptr(&fn_ref->value->type->name)));18246 buf_sprintf("type '%s' not a function", buf_ptr(&fn_ref->value->type->name)));
...@@ -21794,9 +21954,7 @@ static void ensure_field_index(ZigType *type, const char *field_name, size_t ind...@@ -21794,9 +21954,7 @@ static void ensure_field_index(ZigType *type, const char *field_name, size_t ind
2179421954
21795static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, ZigType *root) {21955static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, ZigType *root) {
21796 Error err;21956 Error err;
21797 ZigValue *type_info_var = get_builtin_value(ira->codegen, "TypeInfo");21957 ZigType *type_info_type = get_builtin_type(ira->codegen, "TypeInfo");
21798 assert(type_info_var->type->id == ZigTypeIdMetaType);
21799 ZigType *type_info_type = type_info_var->data.x_type;
21800 assert(type_info_type->id == ZigTypeIdUnion);21958 assert(type_info_type->id == ZigTypeIdUnion);
21801 if ((err = type_resolve(ira->codegen, type_info_type, ResolveStatusSizeKnown))) {21959 if ((err = type_resolve(ira->codegen, type_info_type, ResolveStatusSizeKnown))) {
21802 zig_unreachable();21960 zig_unreachable();
...@@ -23026,9 +23184,7 @@ static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira,...@@ -23026,9 +23184,7 @@ static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira,
23026 if (type_is_invalid(type_entry))23184 if (type_is_invalid(type_entry))
23027 return ira->codegen->invalid_instruction;23185 return ira->codegen->invalid_instruction;
2302823186
23029 ZigValue *var_value = get_builtin_value(ira->codegen, "TypeId");23187 ZigType *result_type = get_builtin_type(ira->codegen, "TypeId");
23030 assert(var_value->type->id == ZigTypeIdMetaType);
23031 ZigType *result_type = var_value->data.x_type;
2303223188
23033 IrInstruction *result = ir_const(ira, &instruction->base, result_type);23189 IrInstruction *result = ir_const(ira, &instruction->base, result_type);
23034 bigint_init_unsigned(&result->value->data.x_enum_tag, type_id_index(type_entry));23190 bigint_init_unsigned(&result->value->data.x_enum_tag, type_id_index(type_entry));
...@@ -27779,6 +27935,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction...@@ -27779,6 +27935,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
27779 return ir_analyze_instruction_field_ptr(ira, (IrInstructionFieldPtr *)instruction);27935 return ir_analyze_instruction_field_ptr(ira, (IrInstructionFieldPtr *)instruction);
27780 case IrInstructionIdCallSrc:27936 case IrInstructionIdCallSrc:
27781 return ir_analyze_instruction_call(ira, (IrInstructionCallSrc *)instruction);27937 return ir_analyze_instruction_call(ira, (IrInstructionCallSrc *)instruction);
27938 case IrInstructionIdCallExtra:
27939 return ir_analyze_instruction_call_extra(ira, (IrInstructionCallExtra *)instruction);
27782 case IrInstructionIdBr:27940 case IrInstructionIdBr:
27783 return ir_analyze_instruction_br(ira, (IrInstructionBr *)instruction);27941 return ir_analyze_instruction_br(ira, (IrInstructionBr *)instruction);
27784 case IrInstructionIdCondBr:27942 case IrInstructionIdCondBr:
...@@ -28176,6 +28334,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -28176,6 +28334,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
28176 case IrInstructionIdDeclVarGen:28334 case IrInstructionIdDeclVarGen:
28177 case IrInstructionIdStorePtr:28335 case IrInstructionIdStorePtr:
28178 case IrInstructionIdVectorStoreElem:28336 case IrInstructionIdVectorStoreElem:
28337 case IrInstructionIdCallExtra:
28179 case IrInstructionIdCallSrc:28338 case IrInstructionIdCallSrc:
28180 case IrInstructionIdCallGen:28339 case IrInstructionIdCallGen:
28181 case IrInstructionIdReturn:28340 case IrInstructionIdReturn:
src/ir_print.cpp+50-4
...@@ -92,6 +92,8 @@ const char* ir_instruction_type_str(IrInstructionId id) {...@@ -92,6 +92,8 @@ const char* ir_instruction_type_str(IrInstructionId id) {
92 return "VarPtr";92 return "VarPtr";
93 case IrInstructionIdReturnPtr:93 case IrInstructionIdReturnPtr:
94 return "ReturnPtr";94 return "ReturnPtr";
95 case IrInstructionIdCallExtra:
96 return "CallExtra";
95 case IrInstructionIdCallSrc:97 case IrInstructionIdCallSrc:
96 return "CallSrc";98 return "CallSrc";
97 case IrInstructionIdCallGen:99 case IrInstructionIdCallGen:
...@@ -636,15 +638,41 @@ static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) {...@@ -636,15 +638,41 @@ static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) {
636 zig_unreachable();638 zig_unreachable();
637}639}
638640
641static void ir_print_call_extra(IrPrint *irp, IrInstructionCallExtra *instruction) {
642 fprintf(irp->f, "opts=");
643 ir_print_other_instruction(irp, instruction->options);
644 fprintf(irp->f, ", fn=");
645 ir_print_other_instruction(irp, instruction->fn_ref);
646 fprintf(irp->f, ", args=");
647 ir_print_other_instruction(irp, instruction->args);
648 fprintf(irp->f, ", result=");
649 ir_print_result_loc(irp, instruction->result_loc);
650}
651
639static void ir_print_call_src(IrPrint *irp, IrInstructionCallSrc *call_instruction) {652static void ir_print_call_src(IrPrint *irp, IrInstructionCallSrc *call_instruction) {
640 switch (call_instruction->modifier) {653 switch (call_instruction->modifier) {
641 case CallModifierNone:654 case CallModifierNone:
642 break;655 break;
656 case CallModifierNoAsync:
657 fprintf(irp->f, "noasync ");
658 break;
643 case CallModifierAsync:659 case CallModifierAsync:
644 fprintf(irp->f, "async ");660 fprintf(irp->f, "async ");
645 break;661 break;
646 case CallModifierNoAsync:662 case CallModifierNeverTail:
647 fprintf(irp->f, "noasync ");663 fprintf(irp->f, "notail ");
664 break;
665 case CallModifierNeverInline:
666 fprintf(irp->f, "noinline ");
667 break;
668 case CallModifierAlwaysTail:
669 fprintf(irp->f, "tail ");
670 break;
671 case CallModifierAlwaysInline:
672 fprintf(irp->f, "inline ");
673 break;
674 case CallModifierCompileTime:
675 fprintf(irp->f, "comptime ");
648 break;676 break;
649 case CallModifierBuiltin:677 case CallModifierBuiltin:
650 zig_unreachable();678 zig_unreachable();
...@@ -670,11 +698,26 @@ static void ir_print_call_gen(IrPrint *irp, IrInstructionCallGen *call_instructi...@@ -670,11 +698,26 @@ static void ir_print_call_gen(IrPrint *irp, IrInstructionCallGen *call_instructi
670 switch (call_instruction->modifier) {698 switch (call_instruction->modifier) {
671 case CallModifierNone:699 case CallModifierNone:
672 break;700 break;
701 case CallModifierNoAsync:
702 fprintf(irp->f, "noasync ");
703 break;
673 case CallModifierAsync:704 case CallModifierAsync:
674 fprintf(irp->f, "async ");705 fprintf(irp->f, "async ");
675 break;706 break;
676 case CallModifierNoAsync:707 case CallModifierNeverTail:
677 fprintf(irp->f, "noasync ");708 fprintf(irp->f, "notail ");
709 break;
710 case CallModifierNeverInline:
711 fprintf(irp->f, "noinline ");
712 break;
713 case CallModifierAlwaysTail:
714 fprintf(irp->f, "tail ");
715 break;
716 case CallModifierAlwaysInline:
717 fprintf(irp->f, "inline ");
718 break;
719 case CallModifierCompileTime:
720 fprintf(irp->f, "comptime ");
678 break;721 break;
679 case CallModifierBuiltin:722 case CallModifierBuiltin:
680 zig_unreachable();723 zig_unreachable();
...@@ -2082,6 +2125,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool...@@ -2082,6 +2125,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool
2082 case IrInstructionIdCast:2125 case IrInstructionIdCast:
2083 ir_print_cast(irp, (IrInstructionCast *)instruction);2126 ir_print_cast(irp, (IrInstructionCast *)instruction);
2084 break;2127 break;
2128 case IrInstructionIdCallExtra:
2129 ir_print_call_extra(irp, (IrInstructionCallExtra *)instruction);
2130 break;
2085 case IrInstructionIdCallSrc:2131 case IrInstructionIdCallSrc:
2086 ir_print_call_src(irp, (IrInstructionCallSrc *)instruction);2132 ir_print_call_src(irp, (IrInstructionCallSrc *)instruction);
2087 break;2133 break;
src/zig_llvm.cpp+12-6
...@@ -269,19 +269,25 @@ ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref) {...@@ -269,19 +269,25 @@ ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref) {
269}269}
270270
271LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,271LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
272 unsigned NumArgs, unsigned CC, ZigLLVM_FnInline fn_inline, const char *Name)272 unsigned NumArgs, unsigned CC, ZigLLVM_CallAttr attr, const char *Name)
273{273{
274 CallInst *call_inst = CallInst::Create(unwrap(Fn), makeArrayRef(unwrap(Args), NumArgs), Name);274 CallInst *call_inst = CallInst::Create(unwrap(Fn), makeArrayRef(unwrap(Args), NumArgs), Name);
275 call_inst->setCallingConv(CC);275 call_inst->setCallingConv(CC);
276 switch (fn_inline) {276 switch (attr) {
277 case ZigLLVM_FnInlineAuto:277 case ZigLLVM_CallAttrAuto:
278 break;278 break;
279 case ZigLLVM_FnInlineAlways:279 case ZigLLVM_CallAttrNeverTail:
280 call_inst->addAttribute(AttributeList::FunctionIndex, Attribute::AlwaysInline);280 call_inst->setTailCallKind(CallInst::TCK_NoTail);
281 break;281 break;
282 case ZigLLVM_FnInlineNever:282 case ZigLLVM_CallAttrNeverInline:
283 call_inst->addAttribute(AttributeList::FunctionIndex, Attribute::NoInline);283 call_inst->addAttribute(AttributeList::FunctionIndex, Attribute::NoInline);
284 break;284 break;
285 case ZigLLVM_CallAttrAlwaysTail:
286 call_inst->setTailCallKind(CallInst::TCK_MustTail);
287 break;
288 case ZigLLVM_CallAttrAlwaysInline:
289 call_inst->addAttribute(AttributeList::FunctionIndex, Attribute::AlwaysInline);
290 break;
285 }291 }
286 return wrap(unwrap(B)->Insert(call_inst));292 return wrap(unwrap(B)->Insert(call_inst));
287}293}
src/zig_llvm.h+7-5
...@@ -64,13 +64,15 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co...@@ -64,13 +64,15 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co
6464
65ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref);65ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref);
6666
67enum ZigLLVM_FnInline {67enum ZigLLVM_CallAttr {
68 ZigLLVM_FnInlineAuto,68 ZigLLVM_CallAttrAuto,
69 ZigLLVM_FnInlineAlways,69 ZigLLVM_CallAttrNeverTail,
70 ZigLLVM_FnInlineNever,70 ZigLLVM_CallAttrNeverInline,
71 ZigLLVM_CallAttrAlwaysTail,
72 ZigLLVM_CallAttrAlwaysInline,
71};73};
72ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,74ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
73 unsigned NumArgs, unsigned CC, enum ZigLLVM_FnInline fn_inline, const char *Name);75 unsigned NumArgs, unsigned CC, enum ZigLLVM_CallAttr attr, const char *Name);
7476
75ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,77ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,
76 LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile);78 LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile);
test/compile_errors.zig+18
...@@ -2,6 +2,24 @@ const tests = @import("tests.zig");...@@ -2,6 +2,24 @@ const tests = @import("tests.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4pub fn addCases(cases: *tests.CompileErrorContext) void {4pub fn addCases(cases: *tests.CompileErrorContext) void {
5 cases.add(
6 "bad usage of @call",
7 \\export fn entry1() void {
8 \\ @call(.{}, foo, {});
9 \\}
10 \\export fn entry2() void {
11 \\ comptime @call(.{ .modifier = .never_inline }, foo, .{});
12 \\}
13 \\export fn entry3() void {
14 \\ comptime @call(.{ .modifier = .never_tail }, foo, .{});
15 \\}
16 \\fn foo() void {}
17 ,
18 "tmp.zig:2:21: error: expected tuple or struct, found 'void'",
19 "tmp.zig:5:58: error: unable to perform 'never_inline' call at compile-time",
20 "tmp.zig:8:56: error: unable to perform 'never_tail' call at compile-time",
21 );
22
5 cases.add(23 cases.add(
6 \\export async fn foo() void {}24 \\export async fn foo() void {}
7 , "tmp.zig:1:1: error: exported function cannot be async");25 , "tmp.zig:1:1: error: exported function cannot be async");
test/stage1/behavior.zig+1
...@@ -52,6 +52,7 @@ comptime {...@@ -52,6 +52,7 @@ comptime {
52 _ = @import("behavior/bugs/920.zig");52 _ = @import("behavior/bugs/920.zig");
53 _ = @import("behavior/byteswap.zig");53 _ = @import("behavior/byteswap.zig");
54 _ = @import("behavior/byval_arg_var.zig");54 _ = @import("behavior/byval_arg_var.zig");
55 _ = @import("behavior/call.zig");
55 _ = @import("behavior/cast.zig");56 _ = @import("behavior/cast.zig");
56 _ = @import("behavior/const_slice_child.zig");57 _ = @import("behavior/const_slice_child.zig");
57 _ = @import("behavior/defer.zig");58 _ = @import("behavior/defer.zig");
test/stage1/behavior/call.zig created+37
...@@ -0,0 +1,37 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "basic invocations" {
5 const foo = struct {
6 fn foo() i32 {
7 return 1234;
8 }
9 }.foo;
10 expect(@call(.{}, foo, .{}) == 1234);
11 comptime {
12 // modifiers that allow comptime calls
13 expect(@call(.{}, foo, .{}) == 1234);
14 expect(@call(.{ .modifier = .no_async }, foo, .{}) == 1234);
15 expect(@call(.{ .modifier = .always_tail }, foo, .{}) == 1234);
16 expect(@call(.{ .modifier = .always_inline }, foo, .{}) == 1234);
17 }
18 {
19 // comptime call without comptime keyword
20 const result = @call(.{ .modifier = .compile_time }, foo, .{}) == 1234;
21 comptime expect(result);
22 }
23}
24
25test "tuple parameters" {
26 const add = struct {
27 fn add(a: i32, b: i32) i32 {
28 return a + b;
29 }
30 }.add;
31 expect(@call(.{}, add, .{ 12, 34 }) == 46);
32 comptime expect(@call(.{}, add, .{ 12, 34 }) == 46);
33 {
34 const separate_args = .{ 12, 34 };
35 expect(@call(.{ .modifier = .always_inline }, add, separate_args) == 46);
36 }
37}