authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2019-09-01 23:45:51+02:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2019-09-01 23:45:51+02:00
logd62f7c6b605a672f032aff8870496d2ae2366017
tree659ae46ac0061fcafd3ec29de8682ec1f18e97cc
parente7912dee9bd63b03415f441b4de9b3babc79c859
parent8b1900e5df76a126404c6905b9e91136c738da55

Merge remote-tracking branch 'upstream/master' into arm-support-improvement


21 files changed, 1020 insertions(+), 205 deletions(-)

doc/langref.html.in+16
...@@ -8114,7 +8114,23 @@ pub const TypeInfo = union(TypeId) {...@@ -8114,7 +8114,23 @@ pub const TypeInfo = union(TypeId) {
8114 This function returns a compile-time constant, which is the type of the8114 This function returns a compile-time constant, which is the type of the
8115 expression passed as an argument. The expression is evaluated.8115 expression passed as an argument. The expression is evaluated.
8116 </p>8116 </p>
8117 <p>{#syntax#}@typeOf{#endsyntax#} guarantees no run-time side-effects within the expression:</p>
8118 {#code_begin|test#}
8119const std = @import("std");
8120const assert = std.debug.assert;
8121
8122test "no runtime side effects" {
8123 var data: i32 = 0;
8124 const T = @typeOf(foo(i32, &data));
8125 comptime assert(T == i32);
8126 assert(data == 0);
8127}
81178128
8129fn foo(comptime T: type, ptr: *T) T {
8130 ptr.* += 1;
8131 return ptr.*;
8132}
8133 {#code_end#}
8118 {#header_close#}8134 {#header_close#}
81198135
8120 {#header_open|@unionInit#}8136 {#header_open|@unionInit#}
src/all_types.hpp+11-1
...@@ -627,7 +627,7 @@ struct AstNodeParamDecl {...@@ -627,7 +627,7 @@ struct AstNodeParamDecl {
627 AstNode *type;627 AstNode *type;
628 Token *var_token;628 Token *var_token;
629 bool is_noalias;629 bool is_noalias;
630 bool is_inline;630 bool is_comptime;
631 bool is_var_args;631 bool is_var_args;
632};632};
633633
...@@ -2104,6 +2104,7 @@ enum ScopeId {...@@ -2104,6 +2104,7 @@ enum ScopeId {
2104 ScopeIdFnDef,2104 ScopeIdFnDef,
2105 ScopeIdCompTime,2105 ScopeIdCompTime,
2106 ScopeIdRuntime,2106 ScopeIdRuntime,
2107 ScopeIdTypeOf,
2107};2108};
21082109
2109struct Scope {2110struct Scope {
...@@ -2244,6 +2245,13 @@ struct ScopeFnDef {...@@ -2244,6 +2245,13 @@ struct ScopeFnDef {
2244 ZigFn *fn_entry;2245 ZigFn *fn_entry;
2245};2246};
22462247
2248// This scope is created for a @typeOf.
2249// All runtime side-effects are elided within it.
2250// NodeTypeFnCallExpr
2251struct ScopeTypeOf {
2252 Scope base;
2253};
2254
2247// synchronized with code in define_builtin_compile_vars2255// synchronized with code in define_builtin_compile_vars
2248enum AtomicOrder {2256enum AtomicOrder {
2249 AtomicOrderUnordered,2257 AtomicOrderUnordered,
...@@ -2711,6 +2719,7 @@ struct IrInstructionCallSrc {...@@ -2711,6 +2719,7 @@ struct IrInstructionCallSrc {
2711 IrInstruction *new_stack;2719 IrInstruction *new_stack;
2712 FnInline fn_inline;2720 FnInline fn_inline;
2713 bool is_async;2721 bool is_async;
2722 bool is_async_call_builtin;
2714 bool is_comptime;2723 bool is_comptime;
2715};2724};
27162725
...@@ -2727,6 +2736,7 @@ struct IrInstructionCallGen {...@@ -2727,6 +2736,7 @@ struct IrInstructionCallGen {
2727 IrInstruction *new_stack;2736 IrInstruction *new_stack;
2728 FnInline fn_inline;2737 FnInline fn_inline;
2729 bool is_async;2738 bool is_async;
2739 bool is_async_call_builtin;
2730};2740};
27312741
2732struct IrInstructionConst {2742struct IrInstructionConst {
src/analyze.cpp+33-4
...@@ -197,6 +197,12 @@ Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent) {...@@ -197,6 +197,12 @@ Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent) {
197 return &scope->base;197 return &scope->base;
198}198}
199199
200Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent) {
201 ScopeTypeOf *scope = allocate<ScopeTypeOf>(1);
202 init_scope(g, &scope->base, ScopeIdTypeOf, node, parent);
203 return &scope->base;
204}
205
200ZigType *get_scope_import(Scope *scope) {206ZigType *get_scope_import(Scope *scope) {
201 while (scope) {207 while (scope) {
202 if (scope->id == ScopeIdDecls) {208 if (scope->id == ScopeIdDecls) {
...@@ -209,6 +215,22 @@ ZigType *get_scope_import(Scope *scope) {...@@ -209,6 +215,22 @@ ZigType *get_scope_import(Scope *scope) {
209 zig_unreachable();215 zig_unreachable();
210}216}
211217
218ScopeTypeOf *get_scope_typeof(Scope *scope) {
219 while (scope) {
220 switch (scope->id) {
221 case ScopeIdTypeOf:
222 return reinterpret_cast<ScopeTypeOf *>(scope);
223 case ScopeIdFnDef:
224 case ScopeIdDecls:
225 return nullptr;
226 default:
227 scope = scope->parent;
228 continue;
229 }
230 }
231 zig_unreachable();
232}
233
212static ZigType *new_container_type_entry(CodeGen *g, ZigTypeId id, AstNode *source_node, Scope *parent_scope,234static ZigType *new_container_type_entry(CodeGen *g, ZigTypeId id, AstNode *source_node, Scope *parent_scope,
213 Buf *bare_name)235 Buf *bare_name)
214{236{
...@@ -1556,7 +1578,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc...@@ -1556,7 +1578,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
1556 AstNode *param_node = fn_proto->params.at(fn_type_id.next_param_index);1578 AstNode *param_node = fn_proto->params.at(fn_type_id.next_param_index);
1557 assert(param_node->type == NodeTypeParamDecl);1579 assert(param_node->type == NodeTypeParamDecl);
15581580
1559 bool param_is_comptime = param_node->data.param_decl.is_inline;1581 bool param_is_comptime = param_node->data.param_decl.is_comptime;
1560 bool param_is_var_args = param_node->data.param_decl.is_var_args;1582 bool param_is_var_args = param_node->data.param_decl.is_var_args;
15611583
1562 if (param_is_comptime) {1584 if (param_is_comptime) {
...@@ -4393,7 +4415,7 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {...@@ -4393,7 +4415,7 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) {
43934415
4394 if (g->verbose_ir) {4416 if (g->verbose_ir) {
4395 fprintf(stderr, "fn %s() { // (analyzed)\n", buf_ptr(&fn->symbol_name));4417 fprintf(stderr, "fn %s() { // (analyzed)\n", buf_ptr(&fn->symbol_name));
4396 ir_print(g, stderr, &fn->analyzed_executable, 4);4418 ir_print(g, stderr, &fn->analyzed_executable, 4, 2);
4397 fprintf(stderr, "}\n");4419 fprintf(stderr, "}\n");
4398 }4420 }
4399 fn->anal_state = FnAnalStateComplete;4421 fn->anal_state = FnAnalStateComplete;
...@@ -4427,7 +4449,7 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) {...@@ -4427,7 +4449,7 @@ static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) {
4427 fprintf(stderr, "\n");4449 fprintf(stderr, "\n");
4428 ast_render(stderr, fn_table_entry->body_node, 4);4450 ast_render(stderr, fn_table_entry->body_node, 4);
4429 fprintf(stderr, "\n{ // (IR)\n");4451 fprintf(stderr, "\n{ // (IR)\n");
4430 ir_print(g, stderr, &fn_table_entry->ir_executable, 4);4452 ir_print(g, stderr, &fn_table_entry->ir_executable, 4, 1);
4431 fprintf(stderr, "}\n");4453 fprintf(stderr, "}\n");
4432 }4454 }
44334455
...@@ -5705,6 +5727,10 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {...@@ -5705,6 +5727,10 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
57055727
5706 for (size_t i = 0; i < fn->call_list.length; i += 1) {5728 for (size_t i = 0; i < fn->call_list.length; i += 1) {
5707 IrInstructionCallGen *call = fn->call_list.at(i);5729 IrInstructionCallGen *call = fn->call_list.at(i);
5730 if (call->new_stack != nullptr) {
5731 // don't need to allocate a frame for this
5732 continue;
5733 }
5708 ZigFn *callee = call->fn_entry;5734 ZigFn *callee = call->fn_entry;
5709 if (callee == nullptr) {5735 if (callee == nullptr) {
5710 add_node_error(g, call->base.source_node,5736 add_node_error(g, call->base.source_node,
...@@ -8234,6 +8260,10 @@ static void resolve_llvm_types_anyerror(CodeGen *g) {...@@ -8234,6 +8260,10 @@ static void resolve_llvm_types_anyerror(CodeGen *g) {
8234}8260}
82358261
8236static void resolve_llvm_types_async_frame(CodeGen *g, ZigType *frame_type, ResolveStatus wanted_resolve_status) {8262static void resolve_llvm_types_async_frame(CodeGen *g, ZigType *frame_type, ResolveStatus wanted_resolve_status) {
8263 Error err;
8264 if ((err = type_resolve(g, frame_type, ResolveStatusSizeKnown)))
8265 zig_unreachable();
8266
8237 ZigType *passed_frame_type = fn_is_async(frame_type->data.frame.fn) ? frame_type : nullptr;8267 ZigType *passed_frame_type = fn_is_async(frame_type->data.frame.fn) ? frame_type : nullptr;
8238 resolve_llvm_types_struct(g, frame_type->data.frame.locals_struct, wanted_resolve_status, passed_frame_type);8268 resolve_llvm_types_struct(g, frame_type->data.frame.locals_struct, wanted_resolve_status, passed_frame_type);
8239 frame_type->llvm_type = frame_type->data.frame.locals_struct->llvm_type;8269 frame_type->llvm_type = frame_type->data.frame.locals_struct->llvm_type;
...@@ -8375,7 +8405,6 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re...@@ -8375,7 +8405,6 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re
8375}8405}
83768406
8377static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {8407static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {
8378 assert(type->id == ZigTypeIdOpaque || type_is_resolved(type, ResolveStatusSizeKnown));
8379 assert(wanted_resolve_status > ResolveStatusSizeKnown);8408 assert(wanted_resolve_status > ResolveStatusSizeKnown);
8380 switch (type->id) {8409 switch (type->id) {
8381 case ZigTypeIdInvalid:8410 case ZigTypeIdInvalid:
src/analyze.hpp+2
...@@ -85,6 +85,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);...@@ -85,6 +85,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
85ZigFn *scope_fn_entry(Scope *scope);85ZigFn *scope_fn_entry(Scope *scope);
86ZigPackage *scope_package(Scope *scope);86ZigPackage *scope_package(Scope *scope);
87ZigType *get_scope_import(Scope *scope);87ZigType *get_scope_import(Scope *scope);
88ScopeTypeOf *get_scope_typeof(Scope *scope);
88void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope);89void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope);
89ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,90ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
90 bool is_const, ConstExprValue *init_value, Tld *src_tld, ZigType *var_type);91 bool is_const, ConstExprValue *init_value, Tld *src_tld, ZigType *var_type);
...@@ -112,6 +113,7 @@ ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent);...@@ -112,6 +113,7 @@ ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent);
112ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *fn_entry);113ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *fn_entry);
113Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent);114Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent);
114Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime);115Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstruction *is_comptime);
116Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent);
115117
116void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);118void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);
117ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);119ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);
src/ast_render.cpp+1-1
...@@ -448,7 +448,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -448,7 +448,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
448 assert(param_decl->type == NodeTypeParamDecl);448 assert(param_decl->type == NodeTypeParamDecl);
449 if (param_decl->data.param_decl.name != nullptr) {449 if (param_decl->data.param_decl.name != nullptr) {
450 const char *noalias_str = param_decl->data.param_decl.is_noalias ? "noalias " : "";450 const char *noalias_str = param_decl->data.param_decl.is_noalias ? "noalias " : "";
451 const char *inline_str = param_decl->data.param_decl.is_inline ? "inline " : "";451 const char *inline_str = param_decl->data.param_decl.is_comptime ? "comptime " : "";
452 fprintf(ar->f, "%s%s", noalias_str, inline_str);452 fprintf(ar->f, "%s%s", noalias_str, inline_str);
453 print_symbol(ar, param_decl->data.param_decl.name);453 print_symbol(ar, param_decl->data.param_decl.name);
454 fprintf(ar->f, ": ");454 fprintf(ar->f, ": ");
src/codegen.cpp+54-21
...@@ -645,6 +645,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {...@@ -645,6 +645,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
645 case ScopeIdSuspend:645 case ScopeIdSuspend:
646 case ScopeIdCompTime:646 case ScopeIdCompTime:
647 case ScopeIdRuntime:647 case ScopeIdRuntime:
648 case ScopeIdTypeOf:
648 return get_di_scope(g, scope->parent);649 return get_di_scope(g, scope->parent);
649 }650 }
650 zig_unreachable();651 zig_unreachable();
...@@ -3757,6 +3758,7 @@ static void render_async_var_decls(CodeGen *g, Scope *scope) {...@@ -3757,6 +3758,7 @@ static void render_async_var_decls(CodeGen *g, Scope *scope) {
3757 case ScopeIdSuspend:3758 case ScopeIdSuspend:
3758 case ScopeIdCompTime:3759 case ScopeIdCompTime:
3759 case ScopeIdRuntime:3760 case ScopeIdRuntime:
3761 case ScopeIdTypeOf:
3760 scope = scope->parent;3762 scope = scope->parent;
3761 continue;3763 continue;
3762 }3764 }
...@@ -3824,17 +3826,18 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3824,17 +3826,18 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3824 LLVMValueRef awaiter_init_val;3826 LLVMValueRef awaiter_init_val;
3825 LLVMValueRef ret_ptr;3827 LLVMValueRef ret_ptr;
3826 if (callee_is_async) {3828 if (callee_is_async) {
3827 if (instruction->is_async) {3829 if (instruction->new_stack == nullptr) {
3828 if (instruction->new_stack == nullptr) {3830 if (instruction->is_async) {
3829 awaiter_init_val = zero;
3830 frame_result_loc = result_loc;3831 frame_result_loc = result_loc;
38313832 } else {
3832 if (ret_has_bits) {3833 frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc);
3833 // Use the result location which is inside the frame if this is an async call.3834 }
3834 ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, "");3835 } else {
3835 }3836 if (instruction->new_stack->value.type->id == ZigTypeIdPointer &&
3836 } else if (cc == CallingConventionAsync) {3837 instruction->new_stack->value.type->data.pointer.child_type->id == ZigTypeIdFnFrame)
3837 awaiter_init_val = zero;3838 {
3839 frame_result_loc = ir_llvm_value(g, instruction->new_stack);
3840 } else {
3838 LLVMValueRef frame_slice_ptr = ir_llvm_value(g, instruction->new_stack);3841 LLVMValueRef frame_slice_ptr = ir_llvm_value(g, instruction->new_stack);
3839 if (ir_want_runtime_safety(g, &instruction->base)) {3842 if (ir_want_runtime_safety(g, &instruction->base)) {
3840 LLVMValueRef given_len_ptr = LLVMBuildStructGEP(g->builder, frame_slice_ptr, slice_len_index, "");3843 LLVMValueRef given_len_ptr = LLVMBuildStructGEP(g->builder, frame_slice_ptr, slice_len_index, "");
...@@ -3854,15 +3857,37 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3854,15 +3857,37 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3854 }3857 }
3855 LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_slice_ptr, slice_ptr_index, "");3858 LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_slice_ptr, slice_ptr_index, "");
3856 LLVMValueRef frame_ptr = LLVMBuildLoad(g->builder, frame_ptr_ptr, "");3859 LLVMValueRef frame_ptr = LLVMBuildLoad(g->builder, frame_ptr_ptr, "");
3857 frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr,3860 if (instruction->fn_entry == nullptr) {
3858 get_llvm_type(g, instruction->base.value.type), "");3861 ZigType *anyframe_type = get_any_frame_type(g, src_return_type);
3862 frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr, get_llvm_type(g, anyframe_type), "");
3863 } else {
3864 ZigType *ptr_frame_type = get_pointer_to_type(g,
3865 get_fn_frame_type(g, instruction->fn_entry), false);
3866 frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr,
3867 get_llvm_type(g, ptr_frame_type), "");
3868 }
3869 }
3870 }
3871 if (instruction->is_async) {
3872 if (instruction->new_stack == nullptr) {
3873 awaiter_init_val = zero;
38593874
3860 if (ret_has_bits) {3875 if (ret_has_bits) {
3861 // Use the result location provided to the @asyncCall builtin3876 // Use the result location which is inside the frame if this is an async call.
3862 ret_ptr = result_loc;3877 ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, "");
3863 }3878 }
3864 } else {3879 } else {
3865 zig_unreachable();3880 awaiter_init_val = zero;
3881
3882 if (ret_has_bits) {
3883 if (result_loc != nullptr) {
3884 // Use the result location provided to the @asyncCall builtin
3885 ret_ptr = result_loc;
3886 } else {
3887 // no result location provided to @asyncCall - use the one inside the frame.
3888 ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, "");
3889 }
3890 }
3866 }3891 }
38673892
3868 // even if prefix_arg_err_ret_stack is true, let the async function do its own3893 // even if prefix_arg_err_ret_stack is true, let the async function do its own
...@@ -3870,7 +3895,6 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3870,7 +3895,6 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3870 } else {3895 } else {
3871 // async function called as a normal function3896 // async function called as a normal function
38723897
3873 frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc);
3874 awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, ""); // caller's own frame pointer3898 awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, ""); // caller's own frame pointer
3875 if (ret_has_bits) {3899 if (ret_has_bits) {
3876 if (result_loc == nullptr) {3900 if (result_loc == nullptr) {
...@@ -3986,7 +4010,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3986,7 +4010,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3986 uint32_t arg_start_i = frame_index_arg(g, fn_type->data.fn.fn_type_id.return_type);4010 uint32_t arg_start_i = frame_index_arg(g, fn_type->data.fn.fn_type_id.return_type);
39874011
3988 LLVMValueRef casted_frame;4012 LLVMValueRef casted_frame;
3989 if (instruction->new_stack != nullptr) {4013 if (instruction->new_stack != nullptr && instruction->fn_entry == nullptr) {
3990 // We need the frame type to be a pointer to a struct that includes the args4014 // We need the frame type to be a pointer to a struct that includes the args
3991 size_t field_count = arg_start_i + gen_param_values.length;4015 size_t field_count = arg_start_i + gen_param_values.length;
3992 LLVMTypeRef *field_types = allocate_nonzero<LLVMTypeRef>(field_count);4016 LLVMTypeRef *field_types = allocate_nonzero<LLVMTypeRef>(field_count);
...@@ -4012,7 +4036,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -4012,7 +4036,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
4012 if (instruction->is_async) {4036 if (instruction->is_async) {
4013 gen_resume(g, fn_val, frame_result_loc, ResumeIdCall);4037 gen_resume(g, fn_val, frame_result_loc, ResumeIdCall);
4014 if (instruction->new_stack != nullptr) {4038 if (instruction->new_stack != nullptr) {
4015 return frame_result_loc;4039 return LLVMBuildBitCast(g->builder, frame_result_loc,
4040 get_llvm_type(g, instruction->base.value.type), "");
4016 }4041 }
4017 return nullptr;4042 return nullptr;
4018 } else {4043 } else {
...@@ -4039,7 +4064,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -4039,7 +4064,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
4039 }4064 }
4040 }4065 }
40414066
4042 if (instruction->new_stack == nullptr) {4067 if (instruction->new_stack == nullptr || instruction->is_async_call_builtin) {
4043 result = ZigLLVMBuildCall(g->builder, fn_val,4068 result = ZigLLVMBuildCall(g->builder, fn_val,
4044 gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, fn_inline, "");4069 gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, fn_inline, "");
4045 } else if (instruction->is_async) {4070 } else if (instruction->is_async) {
...@@ -5942,12 +5967,17 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {...@@ -5942,12 +5967,17 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
59425967
5943 for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {5968 for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {
5944 IrBasicBlock *current_block = executable->basic_block_list.at(block_i);5969 IrBasicBlock *current_block = executable->basic_block_list.at(block_i);
5970 if (get_scope_typeof(current_block->scope) != nullptr) {
5971 LLVMBuildBr(g->builder, current_block->llvm_block);
5972 }
5945 assert(current_block->llvm_block);5973 assert(current_block->llvm_block);
5946 LLVMPositionBuilderAtEnd(g->builder, current_block->llvm_block);5974 LLVMPositionBuilderAtEnd(g->builder, current_block->llvm_block);
5947 for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {5975 for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {
5948 IrInstruction *instruction = current_block->instruction_list.at(instr_i);5976 IrInstruction *instruction = current_block->instruction_list.at(instr_i);
5949 if (instruction->ref_count == 0 && !ir_has_side_effects(instruction))5977 if (instruction->ref_count == 0 && !ir_has_side_effects(instruction))
5950 continue;5978 continue;
5979 if (get_scope_typeof(instruction->scope) != nullptr)
5980 continue;
59515981
5952 if (!g->strip_debug_symbols) {5982 if (!g->strip_debug_symbols) {
5953 set_debug_location(g, instruction);5983 set_debug_location(g, instruction);
...@@ -6340,9 +6370,12 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -6340,9 +6370,12 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
6340 ZigType *type_entry = const_val->type;6370 ZigType *type_entry = const_val->type;
6341 assert(type_has_bits(type_entry));6371 assert(type_has_bits(type_entry));
63426372
6343 switch (const_val->special) {6373check: switch (const_val->special) {
6344 case ConstValSpecialLazy:6374 case ConstValSpecialLazy:
6345 zig_unreachable();6375 if ((err = ir_resolve_lazy(g, nullptr, const_val))) {
6376 report_errors_and_exit(g);
6377 }
6378 goto check;
6346 case ConstValSpecialRuntime:6379 case ConstValSpecialRuntime:
6347 zig_unreachable();6380 zig_unreachable();
6348 case ConstValSpecialUndef:6381 case ConstValSpecialUndef:
src/ir.cpp+239-116
...@@ -1382,7 +1382,7 @@ static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, Ast...@@ -1382,7 +1382,7 @@ static IrInstruction *ir_build_union_field_ptr(IrBuilder *irb, Scope *scope, Ast
13821382
1383static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *source_node,1383static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
1384 ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,1384 ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
1385 bool is_comptime, FnInline fn_inline, bool is_async,1385 bool is_comptime, FnInline fn_inline, bool is_async, bool is_async_call_builtin,
1386 IrInstruction *new_stack, ResultLoc *result_loc)1386 IrInstruction *new_stack, ResultLoc *result_loc)
1387{1387{
1388 IrInstructionCallSrc *call_instruction = ir_build_instruction<IrInstructionCallSrc>(irb, scope, source_node);1388 IrInstructionCallSrc *call_instruction = ir_build_instruction<IrInstructionCallSrc>(irb, scope, source_node);
...@@ -1393,6 +1393,7 @@ static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *s...@@ -1393,6 +1393,7 @@ static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *s
1393 call_instruction->args = args;1393 call_instruction->args = args;
1394 call_instruction->arg_count = arg_count;1394 call_instruction->arg_count = arg_count;
1395 call_instruction->is_async = is_async;1395 call_instruction->is_async = is_async;
1396 call_instruction->is_async_call_builtin = is_async_call_builtin;
1396 call_instruction->new_stack = new_stack;1397 call_instruction->new_stack = new_stack;
1397 call_instruction->result_loc = result_loc;1398 call_instruction->result_loc = result_loc;
13981399
...@@ -1410,7 +1411,7 @@ static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *s...@@ -1410,7 +1411,7 @@ static IrInstruction *ir_build_call_src(IrBuilder *irb, Scope *scope, AstNode *s
14101411
1411static IrInstructionCallGen *ir_build_call_gen(IrAnalyze *ira, IrInstruction *source_instruction,1412static IrInstructionCallGen *ir_build_call_gen(IrAnalyze *ira, IrInstruction *source_instruction,
1412 ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,1413 ZigFn *fn_entry, IrInstruction *fn_ref, size_t arg_count, IrInstruction **args,
1413 FnInline fn_inline, bool is_async, IrInstruction *new_stack,1414 FnInline fn_inline, bool is_async, IrInstruction *new_stack, bool is_async_call_builtin,
1414 IrInstruction *result_loc, ZigType *return_type)1415 IrInstruction *result_loc, ZigType *return_type)
1415{1416{
1416 IrInstructionCallGen *call_instruction = ir_build_instruction<IrInstructionCallGen>(&ira->new_irb,1417 IrInstructionCallGen *call_instruction = ir_build_instruction<IrInstructionCallGen>(&ira->new_irb,
...@@ -1422,6 +1423,7 @@ static IrInstructionCallGen *ir_build_call_gen(IrAnalyze *ira, IrInstruction *so...@@ -1422,6 +1423,7 @@ static IrInstructionCallGen *ir_build_call_gen(IrAnalyze *ira, IrInstruction *so
1422 call_instruction->args = args;1423 call_instruction->args = args;
1423 call_instruction->arg_count = arg_count;1424 call_instruction->arg_count = arg_count;
1424 call_instruction->is_async = is_async;1425 call_instruction->is_async = is_async;
1426 call_instruction->is_async_call_builtin = is_async_call_builtin;
1425 call_instruction->new_stack = new_stack;1427 call_instruction->new_stack = new_stack;
1426 call_instruction->result_loc = result_loc;1428 call_instruction->result_loc = result_loc;
14271429
...@@ -3344,6 +3346,7 @@ static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_sco...@@ -3344,6 +3346,7 @@ static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_sco
3344 case ScopeIdSuspend:3346 case ScopeIdSuspend:
3345 case ScopeIdCompTime:3347 case ScopeIdCompTime:
3346 case ScopeIdRuntime:3348 case ScopeIdRuntime:
3349 case ScopeIdTypeOf:
3347 scope = scope->parent;3350 scope = scope->parent;
3348 continue;3351 continue;
3349 case ScopeIdDeferExpr:3352 case ScopeIdDeferExpr:
...@@ -3399,6 +3402,7 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o...@@ -3399,6 +3402,7 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o
3399 case ScopeIdSuspend:3402 case ScopeIdSuspend:
3400 case ScopeIdCompTime:3403 case ScopeIdCompTime:
3401 case ScopeIdRuntime:3404 case ScopeIdRuntime:
3405 case ScopeIdTypeOf:
3402 scope = scope->parent;3406 scope = scope->parent;
3403 continue;3407 continue;
3404 case ScopeIdDeferExpr:3408 case ScopeIdDeferExpr:
...@@ -4349,6 +4353,54 @@ static IrInstruction *ir_gen_this(IrBuilder *irb, Scope *orig_scope, AstNode *no...@@ -4349,6 +4353,54 @@ static IrInstruction *ir_gen_this(IrBuilder *irb, Scope *orig_scope, AstNode *no
4349 zig_unreachable();4353 zig_unreachable();
4350}4354}
43514355
4356static IrInstruction *ir_gen_async_call(IrBuilder *irb, Scope *scope, AstNode *await_node, AstNode *call_node,
4357 LVal lval, ResultLoc *result_loc)
4358{
4359 size_t arg_offset = 3;
4360 if (call_node->data.fn_call_expr.params.length < arg_offset) {
4361 add_node_error(irb->codegen, call_node,
4362 buf_sprintf("expected at least %" ZIG_PRI_usize " arguments, found %" ZIG_PRI_usize,
4363 arg_offset, call_node->data.fn_call_expr.params.length));
4364 return irb->codegen->invalid_instruction;
4365 }
4366
4367 AstNode *bytes_node = call_node->data.fn_call_expr.params.at(0);
4368 IrInstruction *bytes = ir_gen_node(irb, bytes_node, scope);
4369 if (bytes == irb->codegen->invalid_instruction)
4370 return bytes;
4371
4372 AstNode *ret_ptr_node = call_node->data.fn_call_expr.params.at(1);
4373 IrInstruction *ret_ptr = ir_gen_node(irb, ret_ptr_node, scope);
4374 if (ret_ptr == irb->codegen->invalid_instruction)
4375 return ret_ptr;
4376
4377 AstNode *fn_ref_node = call_node->data.fn_call_expr.params.at(2);
4378 IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, scope);
4379 if (fn_ref == irb->codegen->invalid_instruction)
4380 return fn_ref;
4381
4382 size_t arg_count = call_node->data.fn_call_expr.params.length - arg_offset;
4383
4384 // last "arg" is return pointer
4385 IrInstruction **args = allocate<IrInstruction*>(arg_count + 1);
4386
4387 for (size_t i = 0; i < arg_count; i += 1) {
4388 AstNode *arg_node = call_node->data.fn_call_expr.params.at(i + arg_offset);
4389 IrInstruction *arg = ir_gen_node(irb, arg_node, scope);
4390 if (arg == irb->codegen->invalid_instruction)
4391 return arg;
4392 args[i] = arg;
4393 }
4394
4395 args[arg_count] = ret_ptr;
4396
4397 bool is_async = await_node == nullptr;
4398 bool is_async_call_builtin = true;
4399 IrInstruction *call = ir_build_call_src(irb, scope, call_node, nullptr, fn_ref, arg_count, args, false,
4400 FnInlineAuto, is_async, is_async_call_builtin, bytes, result_loc);
4401 return ir_lval_wrap(irb, scope, call, lval, result_loc);
4402}
4403
4352static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,4404static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
4353 ResultLoc *result_loc)4405 ResultLoc *result_loc)
4354{4406{
...@@ -4358,7 +4410,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4358,7 +4410,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4358 Buf *name = fn_ref_expr->data.symbol_expr.symbol;4410 Buf *name = fn_ref_expr->data.symbol_expr.symbol;
4359 auto entry = irb->codegen->builtin_fn_table.maybe_get(name);4411 auto entry = irb->codegen->builtin_fn_table.maybe_get(name);
43604412
4361 if (!entry) { // new built in not found4413 if (!entry) {
4362 add_node_error(irb->codegen, node,4414 add_node_error(irb->codegen, node,
4363 buf_sprintf("invalid builtin function: '%s'", buf_ptr(name)));4415 buf_sprintf("invalid builtin function: '%s'", buf_ptr(name)));
4364 return irb->codegen->invalid_instruction;4416 return irb->codegen->invalid_instruction;
...@@ -4379,8 +4431,10 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4379,8 +4431,10 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4379 zig_unreachable();4431 zig_unreachable();
4380 case BuiltinFnIdTypeof:4432 case BuiltinFnIdTypeof:
4381 {4433 {
4434 Scope *sub_scope = create_typeof_scope(irb->codegen, node, scope);
4435
4382 AstNode *arg_node = node->data.fn_call_expr.params.at(0);4436 AstNode *arg_node = node->data.fn_call_expr.params.at(0);
4383 IrInstruction *arg = ir_gen_node(irb, arg_node, scope);4437 IrInstruction *arg = ir_gen_node(irb, arg_node, sub_scope);
4384 if (arg == irb->codegen->invalid_instruction)4438 if (arg == irb->codegen->invalid_instruction)
4385 return arg;4439 return arg;
43864440
...@@ -5220,7 +5274,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -5220,7 +5274,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
5220 FnInline fn_inline = (builtin_fn->id == BuiltinFnIdInlineCall) ? FnInlineAlways : FnInlineNever;5274 FnInline fn_inline = (builtin_fn->id == BuiltinFnIdInlineCall) ? FnInlineAlways : FnInlineNever;
52215275
5222 IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,5276 IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,
5223 fn_inline, false, nullptr, result_loc);5277 fn_inline, false, false, nullptr, result_loc);
5224 return ir_lval_wrap(irb, scope, call, lval, result_loc);5278 return ir_lval_wrap(irb, scope, call, lval, result_loc);
5225 }5279 }
5226 case BuiltinFnIdNewStackCall:5280 case BuiltinFnIdNewStackCall:
...@@ -5253,53 +5307,11 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -5253,53 +5307,11 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
5253 }5307 }
52545308
5255 IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,5309 IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,
5256 FnInlineAuto, false, new_stack, result_loc);5310 FnInlineAuto, false, false, new_stack, result_loc);
5257 return ir_lval_wrap(irb, scope, call, lval, result_loc);5311 return ir_lval_wrap(irb, scope, call, lval, result_loc);
5258 }5312 }
5259 case BuiltinFnIdAsyncCall:5313 case BuiltinFnIdAsyncCall:
5260 {5314 return ir_gen_async_call(irb, scope, nullptr, node, lval, result_loc);
5261 size_t arg_offset = 3;
5262 if (node->data.fn_call_expr.params.length < arg_offset) {
5263 add_node_error(irb->codegen, node,
5264 buf_sprintf("expected at least %" ZIG_PRI_usize " arguments, found %" ZIG_PRI_usize,
5265 arg_offset, node->data.fn_call_expr.params.length));
5266 return irb->codegen->invalid_instruction;
5267 }
5268
5269 AstNode *bytes_node = node->data.fn_call_expr.params.at(0);
5270 IrInstruction *bytes = ir_gen_node(irb, bytes_node, scope);
5271 if (bytes == irb->codegen->invalid_instruction)
5272 return bytes;
5273
5274 AstNode *ret_ptr_node = node->data.fn_call_expr.params.at(1);
5275 IrInstruction *ret_ptr = ir_gen_node(irb, ret_ptr_node, scope);
5276 if (ret_ptr == irb->codegen->invalid_instruction)
5277 return ret_ptr;
5278
5279 AstNode *fn_ref_node = node->data.fn_call_expr.params.at(2);
5280 IrInstruction *fn_ref = ir_gen_node(irb, fn_ref_node, scope);
5281 if (fn_ref == irb->codegen->invalid_instruction)
5282 return fn_ref;
5283
5284 size_t arg_count = node->data.fn_call_expr.params.length - arg_offset;
5285
5286 // last "arg" is return pointer
5287 IrInstruction **args = allocate<IrInstruction*>(arg_count + 1);
5288
5289 for (size_t i = 0; i < arg_count; i += 1) {
5290 AstNode *arg_node = node->data.fn_call_expr.params.at(i + arg_offset);
5291 IrInstruction *arg = ir_gen_node(irb, arg_node, scope);
5292 if (arg == irb->codegen->invalid_instruction)
5293 return arg;
5294 args[i] = arg;
5295 }
5296
5297 args[arg_count] = ret_ptr;
5298
5299 IrInstruction *call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,
5300 FnInlineAuto, true, bytes, result_loc);
5301 return ir_lval_wrap(irb, scope, call, lval, result_loc);
5302 }
5303 case BuiltinFnIdTypeId:5315 case BuiltinFnIdTypeId:
5304 {5316 {
5305 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);5317 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
...@@ -5603,7 +5615,7 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node...@@ -5603,7 +5615,7 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
56035615
5604 bool is_async = node->data.fn_call_expr.is_async;5616 bool is_async = node->data.fn_call_expr.is_async;
5605 IrInstruction *fn_call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,5617 IrInstruction *fn_call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false,
5606 FnInlineAuto, is_async, nullptr, result_loc);5618 FnInlineAuto, is_async, false, nullptr, result_loc);
5607 return ir_lval_wrap(irb, scope, fn_call, lval, result_loc);5619 return ir_lval_wrap(irb, scope, fn_call, lval, result_loc);
5608}5620}
56095621
...@@ -7896,6 +7908,19 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -7896,6 +7908,19 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
7896{7908{
7897 assert(node->type == NodeTypeAwaitExpr);7909 assert(node->type == NodeTypeAwaitExpr);
78987910
7911 AstNode *expr_node = node->data.await_expr.expr;
7912 if (expr_node->type == NodeTypeFnCallExpr && expr_node->data.fn_call_expr.is_builtin) {
7913 AstNode *fn_ref_expr = expr_node->data.fn_call_expr.fn_ref_expr;
7914 Buf *name = fn_ref_expr->data.symbol_expr.symbol;
7915 auto entry = irb->codegen->builtin_fn_table.maybe_get(name);
7916 if (entry != nullptr) {
7917 BuiltinFnEntry *builtin_fn = entry->value;
7918 if (builtin_fn->id == BuiltinFnIdAsyncCall) {
7919 return ir_gen_async_call(irb, scope, node, expr_node, lval, result_loc);
7920 }
7921 }
7922 }
7923
7899 ZigFn *fn_entry = exec_fn_entry(irb->exec);7924 ZigFn *fn_entry = exec_fn_entry(irb->exec);
7900 if (!fn_entry) {7925 if (!fn_entry) {
7901 add_node_error(irb->codegen, node, buf_sprintf("await outside function definition"));7926 add_node_error(irb->codegen, node, buf_sprintf("await outside function definition"));
...@@ -7911,7 +7936,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -7911,7 +7936,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
7911 return irb->codegen->invalid_instruction;7936 return irb->codegen->invalid_instruction;
7912 }7937 }
79137938
7914 IrInstruction *target_inst = ir_gen_node_extra(irb, node->data.await_expr.expr, scope, LValPtr, nullptr);7939 IrInstruction *target_inst = ir_gen_node_extra(irb, expr_node, scope, LValPtr, nullptr);
7915 if (target_inst == irb->codegen->invalid_instruction)7940 if (target_inst == irb->codegen->invalid_instruction)
7916 return irb->codegen->invalid_instruction;7941 return irb->codegen->invalid_instruction;
79177942
...@@ -8269,6 +8294,10 @@ static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec...@@ -8269,6 +8294,10 @@ static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec
8269 break;8294 break;
8270 }8295 }
8271 }8296 }
8297 if (get_scope_typeof(instruction->scope) != nullptr) {
8298 // doesn't count, it's inside a @typeOf()
8299 continue;
8300 }
8272 exec_add_error_node(codegen, exec, instruction->source_node,8301 exec_add_error_node(codegen, exec, instruction->source_node,
8273 buf_sprintf("unable to evaluate constant expression"));8302 buf_sprintf("unable to evaluate constant expression"));
8274 return &codegen->invalid_instruction->value;8303 return &codegen->invalid_instruction->value;
...@@ -9012,7 +9041,42 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc...@@ -9012,7 +9041,42 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
9012 return false;9041 return false;
9013 }9042 }
90149043
9015 ConstExprValue *const_val = ir_resolve_const(ira, instruction, UndefBad);9044 ConstExprValue *const_val = ir_resolve_const(ira, instruction, LazyOkNoUndef);
9045 if (const_val == nullptr)
9046 return false;
9047
9048 if (const_val->special == ConstValSpecialLazy) {
9049 switch (const_val->data.x_lazy->id) {
9050 case LazyValueIdAlignOf: {
9051 // This is guaranteed to fit into a u29
9052 if (other_type->id == ZigTypeIdComptimeInt)
9053 return true;
9054 size_t align_bits = get_align_amt_type(ira->codegen)->data.integral.bit_count;
9055 if (other_type->id == ZigTypeIdInt && !other_type->data.integral.is_signed &&
9056 other_type->data.integral.bit_count >= align_bits)
9057 {
9058 return true;
9059 }
9060 break;
9061 }
9062 case LazyValueIdSizeOf: {
9063 // This is guaranteed to fit into a usize
9064 if (other_type->id == ZigTypeIdComptimeInt)
9065 return true;
9066 size_t usize_bits = ira->codegen->builtin_types.entry_usize->data.integral.bit_count;
9067 if (other_type->id == ZigTypeIdInt && !other_type->data.integral.is_signed &&
9068 other_type->data.integral.bit_count >= usize_bits)
9069 {
9070 return true;
9071 }
9072 break;
9073 }
9074 default:
9075 break;
9076 }
9077 }
9078
9079 const_val = ir_resolve_const(ira, instruction, UndefBad);
9016 if (const_val == nullptr)9080 if (const_val == nullptr)
9017 return false;9081 return false;
90189082
...@@ -10262,7 +10326,7 @@ static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_...@@ -10262,7 +10326,7 @@ static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_
10262 memcpy(dest, src, sizeof(ConstExprValue));10326 memcpy(dest, src, sizeof(ConstExprValue));
10263 if (!same_global_refs) {10327 if (!same_global_refs) {
10264 dest->global_refs = global_refs;10328 dest->global_refs = global_refs;
10265 if (src->special == ConstValSpecialUndef)10329 if (src->special != ConstValSpecialStatic)
10266 return;10330 return;
10267 if (dest->type->id == ZigTypeIdStruct) {10331 if (dest->type->id == ZigTypeIdStruct) {
10268 dest->data.x_struct.fields = create_const_vals(dest->type->data.structure.src_field_count);10332 dest->data.x_struct.fields = create_const_vals(dest->type->data.structure.src_field_count);
...@@ -10803,7 +10867,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod...@@ -10803,7 +10867,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod
10803 fprintf(stderr, "\nSource: ");10867 fprintf(stderr, "\nSource: ");
10804 ast_render(stderr, node, 4);10868 ast_render(stderr, node, 4);
10805 fprintf(stderr, "\n{ // (IR)\n");10869 fprintf(stderr, "\n{ // (IR)\n");
10806 ir_print(codegen, stderr, ir_executable, 2);10870 ir_print(codegen, stderr, ir_executable, 2, 1);
10807 fprintf(stderr, "}\n");10871 fprintf(stderr, "}\n");
10808 }10872 }
10809 IrExecutable *analyzed_executable = allocate<IrExecutable>(1);10873 IrExecutable *analyzed_executable = allocate<IrExecutable>(1);
...@@ -10824,7 +10888,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod...@@ -10824,7 +10888,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod
1082410888
10825 if (codegen->verbose_ir) {10889 if (codegen->verbose_ir) {
10826 fprintf(stderr, "{ // (analyzed)\n");10890 fprintf(stderr, "{ // (analyzed)\n");
10827 ir_print(codegen, stderr, analyzed_executable, 2);10891 ir_print(codegen, stderr, analyzed_executable, 2, 2);
10828 fprintf(stderr, "}\n");10892 fprintf(stderr, "}\n");
10829 }10893 }
1083010894
...@@ -11213,7 +11277,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi...@@ -11213,7 +11277,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
11213 return ira->codegen->invalid_instruction;11277 return ira->codegen->invalid_instruction;
1121411278
11215 if (instr_is_comptime(value)) {11279 if (instr_is_comptime(value)) {
11216 ConstExprValue *val = ir_resolve_const(ira, value, UndefOk);11280 ConstExprValue *val = ir_resolve_const(ira, value, LazyOk);
11217 if (!val)11281 if (!val)
11218 return ira->codegen->invalid_instruction;11282 return ira->codegen->invalid_instruction;
11219 return ir_get_const_ptr(ira, source_instruction, val, value->value.type,11283 return ir_get_const_ptr(ira, source_instruction, val, value->value.type,
...@@ -12125,7 +12189,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -12125,7 +12189,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
12125 if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) {12189 if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) {
12126 IrInstruction *result = ir_const(ira, source_instr, wanted_type);12190 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
12127 if (actual_type->id == ZigTypeIdComptimeInt || actual_type->id == ZigTypeIdInt) {12191 if (actual_type->id == ZigTypeIdComptimeInt || actual_type->id == ZigTypeIdInt) {
12128 bigint_init_bigint(&result->value.data.x_bigint, &value->value.data.x_bigint);12192 copy_const_val(&result->value, &value->value, false);
12193 result->value.type = wanted_type;
12129 } else {12194 } else {
12130 float_init_bigint(&result->value.data.x_bigint, &value->value);12195 float_init_bigint(&result->value.data.x_bigint, &value->value);
12131 }12196 }
...@@ -14869,7 +14934,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe...@@ -14869,7 +14934,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
14869 PtrLenSingle, 0, 0, 0, false);14934 PtrLenSingle, 0, 0, 0, false);
14870 set_up_result_loc_for_inferred_comptime(&alloca_gen->base);14935 set_up_result_loc_for_inferred_comptime(&alloca_gen->base);
14871 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);14936 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
14872 if (fn_entry != nullptr) {14937 if (fn_entry != nullptr && get_scope_typeof(suspend_source_instr->scope) == nullptr) {
14873 fn_entry->alloca_gen_list.append(alloca_gen);14938 fn_entry->alloca_gen_list.append(alloca_gen);
14874 }14939 }
14875 result_loc->written = true;14940 result_loc->written = true;
...@@ -15200,44 +15265,61 @@ static IrInstruction *ir_analyze_instruction_reset_result(IrAnalyze *ira, IrInst...@@ -15200,44 +15265,61 @@ static IrInstruction *ir_analyze_instruction_reset_result(IrAnalyze *ira, IrInst
15200 return ir_const_void(ira, &instruction->base);15265 return ir_const_void(ira, &instruction->base);
15201}15266}
1520215267
15268static IrInstruction *get_async_call_result_loc(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,
15269 ZigType *fn_ret_type)
15270{
15271 ir_assert(call_instruction->is_async_call_builtin, &call_instruction->base);
15272 IrInstruction *ret_ptr_uncasted = call_instruction->args[call_instruction->arg_count]->child;
15273 if (type_is_invalid(ret_ptr_uncasted->value.type))
15274 return ira->codegen->invalid_instruction;
15275 if (ret_ptr_uncasted->value.type->id == ZigTypeIdVoid) {
15276 // Result location will be inside the async frame.
15277 return nullptr;
15278 }
15279 return ir_implicit_cast(ira, ret_ptr_uncasted, get_pointer_to_type(ira->codegen, fn_ret_type, false));
15280}
15281
15203static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction, ZigFn *fn_entry,15282static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction, ZigFn *fn_entry,
15204 ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count,15283 ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count,
15205 IrInstruction *casted_new_stack)15284 IrInstruction *casted_new_stack)
15206{15285{
15207 if (casted_new_stack != nullptr) {15286 if (fn_entry == nullptr) {
15208 // this is an @asyncCall
15209
15210 if (fn_type->data.fn.fn_type_id.cc != CallingConventionAsync) {15287 if (fn_type->data.fn.fn_type_id.cc != CallingConventionAsync) {
15211 ir_add_error(ira, fn_ref,15288 ir_add_error(ira, fn_ref,
15212 buf_sprintf("expected async function, found '%s'", buf_ptr(&fn_type->name)));15289 buf_sprintf("expected async function, found '%s'", buf_ptr(&fn_type->name)));
15213 return ira->codegen->invalid_instruction;15290 return ira->codegen->invalid_instruction;
15214 }15291 }
1521515292 if (casted_new_stack == nullptr) {
15216 IrInstruction *ret_ptr = call_instruction->args[call_instruction->arg_count]->child;15293 ir_add_error(ira, fn_ref, buf_sprintf("function is not comptime-known; @asyncCall required"));
15217 if (type_is_invalid(ret_ptr->value.type))15294 return ira->codegen->invalid_instruction;
15295 }
15296 }
15297 if (casted_new_stack != nullptr) {
15298 ZigType *fn_ret_type = fn_type->data.fn.fn_type_id.return_type;
15299 IrInstruction *ret_ptr = get_async_call_result_loc(ira, call_instruction, fn_ret_type);
15300 if (ret_ptr != nullptr && type_is_invalid(ret_ptr->value.type))
15218 return ira->codegen->invalid_instruction;15301 return ira->codegen->invalid_instruction;
1521915302
15220 ZigType *anyframe_type = get_any_frame_type(ira->codegen, fn_type->data.fn.fn_type_id.return_type);15303 ZigType *anyframe_type = get_any_frame_type(ira->codegen, fn_ret_type);
1522115304
15222 IrInstructionCallGen *call_gen = ir_build_call_gen(ira, &call_instruction->base, nullptr, fn_ref,15305 IrInstructionCallGen *call_gen = ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref,
15223 arg_count, casted_args, FnInlineAuto, true, casted_new_stack, ret_ptr, anyframe_type);15306 arg_count, casted_args, FnInlineAuto, true, casted_new_stack,
15307 call_instruction->is_async_call_builtin, ret_ptr, anyframe_type);
15224 return &call_gen->base;15308 return &call_gen->base;
15225 } else if (fn_entry == nullptr) {15309 } else {
15226 ir_add_error(ira, fn_ref, buf_sprintf("function is not comptime-known; @asyncCall required"));15310 ZigType *frame_type = get_fn_frame_type(ira->codegen, fn_entry);
15227 return ira->codegen->invalid_instruction;15311 IrInstruction *result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
15228 }15312 frame_type, nullptr, true, true, false);
1522915313 if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {
15230 ZigType *frame_type = get_fn_frame_type(ira->codegen, fn_entry);15314 return result_loc;
15231 IrInstruction *result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,15315 }
15232 frame_type, nullptr, true, true, false);15316 result_loc = ir_implicit_cast(ira, result_loc, get_pointer_to_type(ira->codegen, frame_type, false));
15233 if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc)) {15317 if (type_is_invalid(result_loc->value.type))
15234 return result_loc;15318 return ira->codegen->invalid_instruction;
15319 return &ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref, arg_count,
15320 casted_args, FnInlineAuto, true, casted_new_stack, call_instruction->is_async_call_builtin,
15321 result_loc, frame_type)->base;
15235 }15322 }
15236 result_loc = ir_implicit_cast(ira, result_loc, get_pointer_to_type(ira->codegen, frame_type, false));
15237 if (type_is_invalid(result_loc->value.type))
15238 return ira->codegen->invalid_instruction;
15239 return &ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref, arg_count,
15240 casted_args, FnInlineAuto, true, nullptr, result_loc, frame_type)->base;
15241}15323}
15242static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node,15324static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node,
15243 IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i)15325 IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i)
...@@ -15301,7 +15383,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod...@@ -15301,7 +15383,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
15301 }15383 }
15302 }15384 }
1530315385
15304 bool comptime_arg = param_decl_node->data.param_decl.is_inline ||15386 bool comptime_arg = param_decl_node->data.param_decl.is_comptime ||
15305 casted_arg->value.type->id == ZigTypeIdComptimeInt || casted_arg->value.type->id == ZigTypeIdComptimeFloat;15387 casted_arg->value.type->id == ZigTypeIdComptimeInt || casted_arg->value.type->id == ZigTypeIdComptimeFloat;
1530615388
15307 ConstExprValue *arg_val;15389 ConstExprValue *arg_val;
...@@ -15746,16 +15828,27 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -15746,16 +15828,27 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
1574615828
15747 IrInstruction *casted_new_stack = nullptr;15829 IrInstruction *casted_new_stack = nullptr;
15748 if (call_instruction->new_stack != nullptr) {15830 if (call_instruction->new_stack != nullptr) {
15749 ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
15750 false, false, PtrLenUnknown, target_fn_align(ira->codegen->zig_target), 0, 0, false);
15751 ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
15752 IrInstruction *new_stack = call_instruction->new_stack->child;15831 IrInstruction *new_stack = call_instruction->new_stack->child;
15753 if (type_is_invalid(new_stack->value.type))15832 if (type_is_invalid(new_stack->value.type))
15754 return ira->codegen->invalid_instruction;15833 return ira->codegen->invalid_instruction;
1575515834
15756 casted_new_stack = ir_implicit_cast(ira, new_stack, u8_slice);15835 if (call_instruction->is_async_call_builtin &&
15757 if (type_is_invalid(casted_new_stack->value.type))15836 fn_entry != nullptr && new_stack->value.type->id == ZigTypeIdPointer &&
15758 return ira->codegen->invalid_instruction;15837 new_stack->value.type->data.pointer.child_type->id == ZigTypeIdFnFrame)
15838 {
15839 ZigType *needed_frame_type = get_pointer_to_type(ira->codegen,
15840 get_fn_frame_type(ira->codegen, fn_entry), false);
15841 casted_new_stack = ir_implicit_cast(ira, new_stack, needed_frame_type);
15842 if (type_is_invalid(casted_new_stack->value.type))
15843 return ira->codegen->invalid_instruction;
15844 } else {
15845 ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
15846 false, false, PtrLenUnknown, target_fn_align(ira->codegen->zig_target), 0, 0, false);
15847 ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
15848 casted_new_stack = ir_implicit_cast(ira, new_stack, u8_slice);
15849 if (type_is_invalid(casted_new_stack->value.type))
15850 return ira->codegen->invalid_instruction;
15851 }
15759 }15852 }
1576015853
15761 if (fn_type->data.fn.is_generic) {15854 if (fn_type->data.fn.is_generic) {
...@@ -15965,8 +16058,24 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -15965,8 +16058,24 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
15965 }16058 }
1596616059
15967 FnTypeId *impl_fn_type_id = &impl_fn->type_entry->data.fn.fn_type_id;16060 FnTypeId *impl_fn_type_id = &impl_fn->type_entry->data.fn.fn_type_id;
16061
16062 if (fn_type_can_fail(impl_fn_type_id)) {
16063 parent_fn_entry->calls_or_awaits_errorable_fn = true;
16064 }
16065
16066 size_t impl_param_count = impl_fn_type_id->param_count;
16067 if (call_instruction->is_async) {
16068 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,
16069 nullptr, casted_args, impl_param_count, casted_new_stack);
16070 return ir_finish_anal(ira, result);
16071 }
16072
15968 IrInstruction *result_loc;16073 IrInstruction *result_loc;
15969 if (handle_is_ptr(impl_fn_type_id->return_type)) {16074 if (call_instruction->is_async_call_builtin) {
16075 result_loc = get_async_call_result_loc(ira, call_instruction, impl_fn_type_id->return_type);
16076 if (result_loc != nullptr && type_is_invalid(result_loc->value.type))
16077 return ira->codegen->invalid_instruction;
16078 } else if (handle_is_ptr(impl_fn_type_id->return_type)) {
15970 result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,16079 result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
15971 impl_fn_type_id->return_type, nullptr, true, true, false);16080 impl_fn_type_id->return_type, nullptr, true, true, false);
15972 if (result_loc != nullptr) {16081 if (result_loc != nullptr) {
...@@ -15982,17 +16091,6 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -15982,17 +16091,6 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
15982 result_loc = nullptr;16091 result_loc = nullptr;
15983 }16092 }
1598416093
15985 if (fn_type_can_fail(impl_fn_type_id)) {
15986 parent_fn_entry->calls_or_awaits_errorable_fn = true;
15987 }
15988
15989 size_t impl_param_count = impl_fn_type_id->param_count;
15990 if (call_instruction->is_async) {
15991 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,
15992 nullptr, casted_args, impl_param_count, casted_new_stack);
15993 return ir_finish_anal(ira, result);
15994 }
15995
15996 if (impl_fn_type_id->cc == CallingConventionAsync && parent_fn_entry->inferred_async_node == nullptr) {16094 if (impl_fn_type_id->cc == CallingConventionAsync && parent_fn_entry->inferred_async_node == nullptr) {
15997 parent_fn_entry->inferred_async_node = fn_ref->source_node;16095 parent_fn_entry->inferred_async_node = fn_ref->source_node;
15998 parent_fn_entry->inferred_async_fn = impl_fn;16096 parent_fn_entry->inferred_async_fn = impl_fn;
...@@ -16000,10 +16098,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -16000,10 +16098,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
1600016098
16001 IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base,16099 IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base,
16002 impl_fn, nullptr, impl_param_count, casted_args, fn_inline,16100 impl_fn, nullptr, impl_param_count, casted_args, fn_inline,
16003 false, casted_new_stack, result_loc,16101 false, casted_new_stack, call_instruction->is_async_call_builtin, result_loc,
16004 impl_fn_type_id->return_type);16102 impl_fn_type_id->return_type);
1600516103
16006 parent_fn_entry->call_list.append(new_call_instruction);16104 if (get_scope_typeof(call_instruction->base.scope) == nullptr) {
16105 parent_fn_entry->call_list.append(new_call_instruction);
16106 }
1600716107
16008 return ir_finish_anal(ira, &new_call_instruction->base);16108 return ir_finish_anal(ira, &new_call_instruction->base);
16009 }16109 }
...@@ -16123,7 +16223,11 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -16123,7 +16223,11 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
16123 }16223 }
1612416224
16125 IrInstruction *result_loc;16225 IrInstruction *result_loc;
16126 if (handle_is_ptr(return_type)) {16226 if (call_instruction->is_async_call_builtin) {
16227 result_loc = get_async_call_result_loc(ira, call_instruction, return_type);
16228 if (result_loc != nullptr && type_is_invalid(result_loc->value.type))
16229 return ira->codegen->invalid_instruction;
16230 } else if (handle_is_ptr(return_type)) {
16127 result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,16231 result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
16128 return_type, nullptr, true, true, false);16232 return_type, nullptr, true, true, false);
16129 if (result_loc != nullptr) {16233 if (result_loc != nullptr) {
...@@ -16141,8 +16245,10 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -16141,8 +16245,10 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
1614116245
16142 IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref,16246 IrInstructionCallGen *new_call_instruction = ir_build_call_gen(ira, &call_instruction->base, fn_entry, fn_ref,
16143 call_param_count, casted_args, fn_inline, false, casted_new_stack,16247 call_param_count, casted_args, fn_inline, false, casted_new_stack,
16144 result_loc, return_type);16248 call_instruction->is_async_call_builtin, result_loc, return_type);
16145 parent_fn_entry->call_list.append(new_call_instruction);16249 if (get_scope_typeof(call_instruction->base.scope) == nullptr) {
16250 parent_fn_entry->call_list.append(new_call_instruction);
16251 }
16146 return ir_finish_anal(ira, &new_call_instruction->base);16252 return ir_finish_anal(ira, &new_call_instruction->base);
16147}16253}
1614816254
...@@ -17594,6 +17700,11 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc...@@ -17594,6 +17700,11 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
17594 ConstExprValue *child_val = const_ptr_pointee(ira, ira->codegen, container_ptr_val, source_node);17700 ConstExprValue *child_val = const_ptr_pointee(ira, ira->codegen, container_ptr_val, source_node);
17595 if (child_val == nullptr)17701 if (child_val == nullptr)
17596 return ira->codegen->invalid_instruction;17702 return ira->codegen->invalid_instruction;
17703 if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec,
17704 field_ptr_instruction->base.source_node, child_val, UndefBad)))
17705 {
17706 return ira->codegen->invalid_instruction;
17707 }
17597 ZigType *child_type = child_val->data.x_type;17708 ZigType *child_type = child_val->data.x_type;
1759817709
17599 if (type_is_invalid(child_type)) {17710 if (type_is_invalid(child_type)) {
...@@ -21293,8 +21404,10 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru...@@ -21293,8 +21404,10 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru
21293 src_ptr_align = get_abi_alignment(ira->codegen, target->value.type);21404 src_ptr_align = get_abi_alignment(ira->codegen, target->value.type);
21294 }21405 }
2129521406
21296 if ((err = type_resolve(ira->codegen, dest_child_type, ResolveStatusSizeKnown)))21407 if (src_ptr_align != 0) {
21297 return ira->codegen->invalid_instruction;21408 if ((err = type_resolve(ira->codegen, dest_child_type, ResolveStatusAlignmentKnown)))
21409 return ira->codegen->invalid_instruction;
21410 }
2129821411
21299 ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_child_type,21412 ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_child_type,
21300 src_ptr_const, src_ptr_volatile, PtrLenUnknown,21413 src_ptr_const, src_ptr_volatile, PtrLenUnknown,
...@@ -21337,6 +21450,8 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru...@@ -21337,6 +21450,8 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru
21337 }21450 }
2133821451
21339 if (have_known_len) {21452 if (have_known_len) {
21453 if ((err = type_resolve(ira->codegen, dest_child_type, ResolveStatusSizeKnown)))
21454 return ira->codegen->invalid_instruction;
21340 uint64_t child_type_size = type_size(ira->codegen, dest_child_type);21455 uint64_t child_type_size = type_size(ira->codegen, dest_child_type);
21341 uint64_t remainder = known_len % child_type_size;21456 uint64_t remainder = known_len % child_type_size;
21342 if (remainder != 0) {21457 if (remainder != 0) {
...@@ -23963,15 +24078,23 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct...@@ -23963,15 +24078,23 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
23963}24078}
2396424079
23965static IrInstruction *ir_analyze_instruction_align_cast(IrAnalyze *ira, IrInstructionAlignCast *instruction) {24080static IrInstruction *ir_analyze_instruction_align_cast(IrAnalyze *ira, IrInstructionAlignCast *instruction) {
23966 uint32_t align_bytes;
23967 IrInstruction *align_bytes_inst = instruction->align_bytes->child;
23968 if (!ir_resolve_align(ira, align_bytes_inst, nullptr, &align_bytes))
23969 return ira->codegen->invalid_instruction;
23970
23971 IrInstruction *target = instruction->target->child;24081 IrInstruction *target = instruction->target->child;
23972 if (type_is_invalid(target->value.type))24082 if (type_is_invalid(target->value.type))
23973 return ira->codegen->invalid_instruction;24083 return ira->codegen->invalid_instruction;
2397424084
24085 ZigType *elem_type = nullptr;
24086 if (is_slice(target->value.type)) {
24087 ZigType *slice_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry;
24088 elem_type = slice_ptr_type->data.pointer.child_type;
24089 } else if (target->value.type->id == ZigTypeIdPointer) {
24090 elem_type = target->value.type->data.pointer.child_type;
24091 }
24092
24093 uint32_t align_bytes;
24094 IrInstruction *align_bytes_inst = instruction->align_bytes->child;
24095 if (!ir_resolve_align(ira, align_bytes_inst, elem_type, &align_bytes))
24096 return ira->codegen->invalid_instruction;
24097
23975 IrInstruction *result = ir_align_cast(ira, target, align_bytes, true);24098 IrInstruction *result = ir_align_cast(ira, target, align_bytes, true);
23976 if (type_is_invalid(result->value.type))24099 if (type_is_invalid(result->value.type))
23977 return ira->codegen->invalid_instruction;24100 return ira->codegen->invalid_instruction;
...@@ -25644,7 +25767,7 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {...@@ -25644,7 +25767,7 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
25644 }25767 }
2564525768
25646 val->special = ConstValSpecialStatic;25769 val->special = ConstValSpecialStatic;
25647 assert(val->type->id == ZigTypeIdComptimeInt);25770 assert(val->type->id == ZigTypeIdComptimeInt || val->type->id == ZigTypeIdInt);
25648 bigint_init_unsigned(&val->data.x_bigint, align_in_bytes);25771 bigint_init_unsigned(&val->data.x_bigint, align_in_bytes);
25649 return ErrorNone;25772 return ErrorNone;
25650 }25773 }
...@@ -25699,7 +25822,7 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {...@@ -25699,7 +25822,7 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
25699 }25822 }
2570025823
25701 val->special = ConstValSpecialStatic;25824 val->special = ConstValSpecialStatic;
25702 assert(val->type->id == ZigTypeIdComptimeInt);25825 assert(val->type->id == ZigTypeIdComptimeInt || val->type->id == ZigTypeIdInt);
25703 bigint_init_unsigned(&val->data.x_bigint, abi_size);25826 bigint_init_unsigned(&val->data.x_bigint, abi_size);
25704 return ErrorNone;25827 return ErrorNone;
25705 }25828 }
...@@ -25885,7 +26008,7 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {...@@ -25885,7 +26008,7 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
25885Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ConstExprValue *val) {26008Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ConstExprValue *val) {
25886 Error err;26009 Error err;
25887 if ((err = ir_resolve_lazy_raw(source_node, val))) {26010 if ((err = ir_resolve_lazy_raw(source_node, val))) {
25888 if (codegen->trace_err != nullptr && !source_node->already_traced_this_node) {26011 if (codegen->trace_err != nullptr && source_node != nullptr && !source_node->already_traced_this_node) {
25889 source_node->already_traced_this_node = true;26012 source_node->already_traced_this_node = true;
25890 codegen->trace_err = add_error_note(codegen, codegen->trace_err, source_node,26013 codegen->trace_err = add_error_note(codegen, codegen->trace_err, source_node,
25891 buf_create_from_str("referenced here"));26014 buf_create_from_str("referenced here"));
src/ir_print.cpp+377-8
...@@ -10,27 +10,374 @@...@@ -10,27 +10,374 @@
10#include "ir_print.hpp"10#include "ir_print.hpp"
11#include "os.hpp"11#include "os.hpp"
1212
13static uint32_t hash_instruction_ptr(IrInstruction* instruction) {
14 return (uint32_t)(uintptr_t)instruction;
15}
16
17static bool instruction_ptr_equal(IrInstruction* a, IrInstruction* b) {
18 return a == b;
19}
20
21using InstructionSet = HashMap<IrInstruction*, uint8_t, hash_instruction_ptr, instruction_ptr_equal>;
22using InstructionList = ZigList<IrInstruction*>;
23
13struct IrPrint {24struct IrPrint {
25 size_t pass_num;
14 CodeGen *codegen;26 CodeGen *codegen;
15 FILE *f;27 FILE *f;
16 int indent;28 int indent;
17 int indent_size;29 int indent_size;
30
31 // When printing pass 2 instructions referenced var instructions are not
32 // present in the instruction list. Thus we track which instructions
33 // are printed (per executable) and after each pass 2 instruction those
34 // var instructions are rendered in a trailing fashion.
35 InstructionSet printed;
36 InstructionList pending;
18};37};
1938
20static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction);39static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction);
2140
41static const char* ir_instruction_type_str(IrInstruction* instruction) {
42 switch (instruction->id) {
43 case IrInstructionIdInvalid:
44 return "Invalid";
45 case IrInstructionIdDeclVarSrc:
46 return "DeclVarSrc";
47 case IrInstructionIdDeclVarGen:
48 return "DeclVarGen";
49 case IrInstructionIdBr:
50 return "Br";
51 case IrInstructionIdCondBr:
52 return "CondBr";
53 case IrInstructionIdSwitchBr:
54 return "SwitchBr";
55 case IrInstructionIdSwitchVar:
56 return "SwitchVar";
57 case IrInstructionIdSwitchElseVar:
58 return "SwitchElseVar";
59 case IrInstructionIdSwitchTarget:
60 return "SwitchTarget";
61 case IrInstructionIdPhi:
62 return "Phi";
63 case IrInstructionIdUnOp:
64 return "UnOp";
65 case IrInstructionIdBinOp:
66 return "BinOp";
67 case IrInstructionIdLoadPtr:
68 return "LoadPtr";
69 case IrInstructionIdLoadPtrGen:
70 return "LoadPtrGen";
71 case IrInstructionIdStorePtr:
72 return "StorePtr";
73 case IrInstructionIdFieldPtr:
74 return "FieldPtr";
75 case IrInstructionIdStructFieldPtr:
76 return "StructFieldPtr";
77 case IrInstructionIdUnionFieldPtr:
78 return "UnionFieldPtr";
79 case IrInstructionIdElemPtr:
80 return "ElemPtr";
81 case IrInstructionIdVarPtr:
82 return "VarPtr";
83 case IrInstructionIdReturnPtr:
84 return "ReturnPtr";
85 case IrInstructionIdCallSrc:
86 return "CallSrc";
87 case IrInstructionIdCallGen:
88 return "CallGen";
89 case IrInstructionIdConst:
90 return "Const";
91 case IrInstructionIdReturn:
92 return "Return";
93 case IrInstructionIdCast:
94 return "Cast";
95 case IrInstructionIdResizeSlice:
96 return "ResizeSlice";
97 case IrInstructionIdContainerInitList:
98 return "ContainerInitList";
99 case IrInstructionIdContainerInitFields:
100 return "ContainerInitFields";
101 case IrInstructionIdUnreachable:
102 return "Unreachable";
103 case IrInstructionIdTypeOf:
104 return "TypeOf";
105 case IrInstructionIdSetCold:
106 return "SetCold";
107 case IrInstructionIdSetRuntimeSafety:
108 return "SetRuntimeSafety";
109 case IrInstructionIdSetFloatMode:
110 return "SetFloatMode";
111 case IrInstructionIdArrayType:
112 return "ArrayType";
113 case IrInstructionIdAnyFrameType:
114 return "AnyFrameType";
115 case IrInstructionIdSliceType:
116 return "SliceType";
117 case IrInstructionIdGlobalAsm:
118 return "GlobalAsm";
119 case IrInstructionIdAsm:
120 return "Asm";
121 case IrInstructionIdSizeOf:
122 return "SizeOf";
123 case IrInstructionIdTestNonNull:
124 return "TestNonNull";
125 case IrInstructionIdOptionalUnwrapPtr:
126 return "OptionalUnwrapPtr";
127 case IrInstructionIdOptionalWrap:
128 return "OptionalWrap";
129 case IrInstructionIdUnionTag:
130 return "UnionTag";
131 case IrInstructionIdClz:
132 return "Clz";
133 case IrInstructionIdCtz:
134 return "Ctz";
135 case IrInstructionIdPopCount:
136 return "PopCount";
137 case IrInstructionIdBswap:
138 return "Bswap";
139 case IrInstructionIdBitReverse:
140 return "BitReverse";
141 case IrInstructionIdImport:
142 return "Import";
143 case IrInstructionIdCImport:
144 return "CImport";
145 case IrInstructionIdCInclude:
146 return "CInclude";
147 case IrInstructionIdCDefine:
148 return "CDefine";
149 case IrInstructionIdCUndef:
150 return "CUndef";
151 case IrInstructionIdRef:
152 return "Ref";
153 case IrInstructionIdRefGen:
154 return "RefGen";
155 case IrInstructionIdCompileErr:
156 return "CompileErr";
157 case IrInstructionIdCompileLog:
158 return "CompileLog";
159 case IrInstructionIdErrName:
160 return "ErrName";
161 case IrInstructionIdEmbedFile:
162 return "EmbedFile";
163 case IrInstructionIdCmpxchgSrc:
164 return "CmpxchgSrc";
165 case IrInstructionIdCmpxchgGen:
166 return "CmpxchgGen";
167 case IrInstructionIdFence:
168 return "Fence";
169 case IrInstructionIdTruncate:
170 return "Truncate";
171 case IrInstructionIdIntCast:
172 return "IntCast";
173 case IrInstructionIdFloatCast:
174 return "FloatCast";
175 case IrInstructionIdIntToFloat:
176 return "IntToFloat";
177 case IrInstructionIdFloatToInt:
178 return "FloatToInt";
179 case IrInstructionIdBoolToInt:
180 return "BoolToInt";
181 case IrInstructionIdIntType:
182 return "IntType";
183 case IrInstructionIdVectorType:
184 return "VectorType";
185 case IrInstructionIdBoolNot:
186 return "BoolNot";
187 case IrInstructionIdMemset:
188 return "Memset";
189 case IrInstructionIdMemcpy:
190 return "Memcpy";
191 case IrInstructionIdSliceSrc:
192 return "SliceSrc";
193 case IrInstructionIdSliceGen:
194 return "SliceGen";
195 case IrInstructionIdMemberCount:
196 return "MemberCount";
197 case IrInstructionIdMemberType:
198 return "MemberType";
199 case IrInstructionIdMemberName:
200 return "MemberName";
201 case IrInstructionIdBreakpoint:
202 return "Breakpoint";
203 case IrInstructionIdReturnAddress:
204 return "ReturnAddress";
205 case IrInstructionIdFrameAddress:
206 return "FrameAddress";
207 case IrInstructionIdFrameHandle:
208 return "FrameHandle";
209 case IrInstructionIdFrameType:
210 return "FrameType";
211 case IrInstructionIdFrameSizeSrc:
212 return "FrameSizeSrc";
213 case IrInstructionIdFrameSizeGen:
214 return "FrameSizeGen";
215 case IrInstructionIdAlignOf:
216 return "AlignOf";
217 case IrInstructionIdOverflowOp:
218 return "OverflowOp";
219 case IrInstructionIdTestErrSrc:
220 return "TestErrSrc";
221 case IrInstructionIdTestErrGen:
222 return "TestErrGen";
223 case IrInstructionIdMulAdd:
224 return "MulAdd";
225 case IrInstructionIdFloatOp:
226 return "FloatOp";
227 case IrInstructionIdUnwrapErrCode:
228 return "UnwrapErrCode";
229 case IrInstructionIdUnwrapErrPayload:
230 return "UnwrapErrPayload";
231 case IrInstructionIdErrWrapCode:
232 return "ErrWrapCode";
233 case IrInstructionIdErrWrapPayload:
234 return "ErrWrapPayload";
235 case IrInstructionIdFnProto:
236 return "FnProto";
237 case IrInstructionIdTestComptime:
238 return "TestComptime";
239 case IrInstructionIdPtrCastSrc:
240 return "PtrCastSrc";
241 case IrInstructionIdPtrCastGen:
242 return "PtrCastGen";
243 case IrInstructionIdBitCastSrc:
244 return "BitCastSrc";
245 case IrInstructionIdBitCastGen:
246 return "BitCastGen";
247 case IrInstructionIdWidenOrShorten:
248 return "WidenOrShorten";
249 case IrInstructionIdIntToPtr:
250 return "IntToPtr";
251 case IrInstructionIdPtrToInt:
252 return "PtrToInt";
253 case IrInstructionIdIntToEnum:
254 return "IntToEnum";
255 case IrInstructionIdEnumToInt:
256 return "EnumToInt";
257 case IrInstructionIdIntToErr:
258 return "IntToErr";
259 case IrInstructionIdErrToInt:
260 return "ErrToInt";
261 case IrInstructionIdCheckSwitchProngs:
262 return "CheckSwitchProngs";
263 case IrInstructionIdCheckStatementIsVoid:
264 return "CheckStatementIsVoid";
265 case IrInstructionIdTypeName:
266 return "TypeName";
267 case IrInstructionIdDeclRef:
268 return "DeclRef";
269 case IrInstructionIdPanic:
270 return "Panic";
271 case IrInstructionIdTagName:
272 return "TagName";
273 case IrInstructionIdTagType:
274 return "TagType";
275 case IrInstructionIdFieldParentPtr:
276 return "FieldParentPtr";
277 case IrInstructionIdByteOffsetOf:
278 return "ByteOffsetOf";
279 case IrInstructionIdBitOffsetOf:
280 return "BitOffsetOf";
281 case IrInstructionIdTypeInfo:
282 return "TypeInfo";
283 case IrInstructionIdHasField:
284 return "HasField";
285 case IrInstructionIdTypeId:
286 return "TypeId";
287 case IrInstructionIdSetEvalBranchQuota:
288 return "SetEvalBranchQuota";
289 case IrInstructionIdPtrType:
290 return "PtrType";
291 case IrInstructionIdAlignCast:
292 return "AlignCast";
293 case IrInstructionIdImplicitCast:
294 return "ImplicitCast";
295 case IrInstructionIdResolveResult:
296 return "ResolveResult";
297 case IrInstructionIdResetResult:
298 return "ResetResult";
299 case IrInstructionIdOpaqueType:
300 return "OpaqueType";
301 case IrInstructionIdSetAlignStack:
302 return "SetAlignStack";
303 case IrInstructionIdArgType:
304 return "ArgType";
305 case IrInstructionIdExport:
306 return "Export";
307 case IrInstructionIdErrorReturnTrace:
308 return "ErrorReturnTrace";
309 case IrInstructionIdErrorUnion:
310 return "ErrorUnion";
311 case IrInstructionIdAtomicRmw:
312 return "AtomicRmw";
313 case IrInstructionIdAtomicLoad:
314 return "AtomicLoad";
315 case IrInstructionIdSaveErrRetAddr:
316 return "SaveErrRetAddr";
317 case IrInstructionIdAddImplicitReturnType:
318 return "AddImplicitReturnType";
319 case IrInstructionIdErrSetCast:
320 return "ErrSetCast";
321 case IrInstructionIdToBytes:
322 return "ToBytes";
323 case IrInstructionIdFromBytes:
324 return "FromBytes";
325 case IrInstructionIdCheckRuntimeScope:
326 return "CheckRuntimeScope";
327 case IrInstructionIdVectorToArray:
328 return "VectorToArray";
329 case IrInstructionIdArrayToVector:
330 return "ArrayToVector";
331 case IrInstructionIdAssertZero:
332 return "AssertZero";
333 case IrInstructionIdAssertNonNull:
334 return "AssertNonNull";
335 case IrInstructionIdHasDecl:
336 return "HasDecl";
337 case IrInstructionIdUndeclaredIdent:
338 return "UndeclaredIdent";
339 case IrInstructionIdAllocaSrc:
340 return "AllocaSrc";
341 case IrInstructionIdAllocaGen:
342 return "AllocaGen";
343 case IrInstructionIdEndExpr:
344 return "EndExpr";
345 case IrInstructionIdPtrOfArrayToSlice:
346 return "PtrOfArrayToSlice";
347 case IrInstructionIdUnionInitNamedField:
348 return "UnionInitNamedField";
349 case IrInstructionIdSuspendBegin:
350 return "SuspendBegin";
351 case IrInstructionIdSuspendFinish:
352 return "SuspendFinish";
353 case IrInstructionIdAwaitSrc:
354 return "AwaitSrc";
355 case IrInstructionIdAwaitGen:
356 return "AwaitGen";
357 case IrInstructionIdResume:
358 return "Resume";
359 case IrInstructionIdSpillBegin:
360 return "SpillBegin";
361 case IrInstructionIdSpillEnd:
362 return "SpillEnd";
363 }
364 zig_unreachable();
365}
366
22static void ir_print_indent(IrPrint *irp) {367static void ir_print_indent(IrPrint *irp) {
23 for (int i = 0; i < irp->indent; i += 1) {368 for (int i = 0; i < irp->indent; i += 1) {
24 fprintf(irp->f, " ");369 fprintf(irp->f, " ");
25 }370 }
26}371}
27372
28static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction) {373static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction, bool trailing) {
29 ir_print_indent(irp);374 ir_print_indent(irp);
375 const char mark = trailing ? ':' : '#';
30 const char *type_name = instruction->value.type ? buf_ptr(&instruction->value.type->name) : "(unknown)";376 const char *type_name = instruction->value.type ? buf_ptr(&instruction->value.type->name) : "(unknown)";
31 const char *ref_count = ir_has_side_effects(instruction) ?377 const char *ref_count = ir_has_side_effects(instruction) ?
32 "-" : buf_ptr(buf_sprintf("%" ZIG_PRI_usize "", instruction->ref_count));378 "-" : buf_ptr(buf_sprintf("%" ZIG_PRI_usize "", instruction->ref_count));
33 fprintf(irp->f, "#%-3zu| %-12s| %-2s| ", instruction->debug_id, type_name, ref_count);379 fprintf(irp->f, "%c%-3zu| %-22s| %-12s| %-2s| ", mark, instruction->debug_id,
380 ir_instruction_type_str(instruction), type_name, ref_count);
34}381}
35382
36static void ir_print_const_value(IrPrint *irp, ConstExprValue *const_val) {383static void ir_print_const_value(IrPrint *irp, ConstExprValue *const_val) {
...@@ -42,6 +389,10 @@ static void ir_print_const_value(IrPrint *irp, ConstExprValue *const_val) {...@@ -42,6 +389,10 @@ static void ir_print_const_value(IrPrint *irp, ConstExprValue *const_val) {
42389
43static void ir_print_var_instruction(IrPrint *irp, IrInstruction *instruction) {390static void ir_print_var_instruction(IrPrint *irp, IrInstruction *instruction) {
44 fprintf(irp->f, "#%" ZIG_PRI_usize "", instruction->debug_id);391 fprintf(irp->f, "#%" ZIG_PRI_usize "", instruction->debug_id);
392 if (irp->pass_num == 2 && irp->printed.maybe_get(instruction) == nullptr) {
393 irp->printed.put(instruction, 0);
394 irp->pending.append(instruction);
395 }
45}396}
46397
47static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction) {398static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction) {
...@@ -49,6 +400,7 @@ static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction)...@@ -49,6 +400,7 @@ static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction)
49 fprintf(irp->f, "(null)");400 fprintf(irp->f, "(null)");
50 return;401 return;
51 }402 }
403
52 if (instruction->value.special != ConstValSpecialRuntime) {404 if (instruction->value.special != ConstValSpecialRuntime) {
53 ir_print_const_value(irp, &instruction->value);405 ir_print_const_value(irp, &instruction->value);
54 } else {406 } else {
...@@ -1550,8 +1902,8 @@ static void ir_print_spill_end(IrPrint *irp, IrInstructionSpillEnd *instruction)...@@ -1550,8 +1902,8 @@ static void ir_print_spill_end(IrPrint *irp, IrInstructionSpillEnd *instruction)
1550 fprintf(irp->f, ")");1902 fprintf(irp->f, ")");
1551}1903}
15521904
1553static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {1905static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool trailing) {
1554 ir_print_prefix(irp, instruction);1906 ir_print_prefix(irp, instruction, trailing);
1555 switch (instruction->id) {1907 switch (instruction->id) {
1556 case IrInstructionIdInvalid:1908 case IrInstructionIdInvalid:
1557 zig_unreachable();1909 zig_unreachable();
...@@ -2036,31 +2388,48 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -2036,31 +2388,48 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
2036 fprintf(irp->f, "\n");2388 fprintf(irp->f, "\n");
2037}2389}
20382390
2039void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size) {2391void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size, size_t pass_num) {
2040 IrPrint ir_print = {};2392 IrPrint ir_print = {};
2041 IrPrint *irp = &ir_print;2393 IrPrint *irp = &ir_print;
2394 irp->pass_num = pass_num;
2042 irp->codegen = codegen;2395 irp->codegen = codegen;
2043 irp->f = f;2396 irp->f = f;
2044 irp->indent = indent_size;2397 irp->indent = indent_size;
2045 irp->indent_size = indent_size;2398 irp->indent_size = indent_size;
2399 irp->printed = {};
2400 irp->printed.init(64);
2401 irp->pending = {};
20462402
2047 for (size_t bb_i = 0; bb_i < executable->basic_block_list.length; bb_i += 1) {2403 for (size_t bb_i = 0; bb_i < executable->basic_block_list.length; bb_i += 1) {
2048 IrBasicBlock *current_block = executable->basic_block_list.at(bb_i);2404 IrBasicBlock *current_block = executable->basic_block_list.at(bb_i);
2049 fprintf(irp->f, "%s_%" ZIG_PRI_usize ":\n", current_block->name_hint, current_block->debug_id);2405 fprintf(irp->f, "%s_%" ZIG_PRI_usize ":\n", current_block->name_hint, current_block->debug_id);
2050 for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {2406 for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {
2051 IrInstruction *instruction = current_block->instruction_list.at(instr_i);2407 IrInstruction *instruction = current_block->instruction_list.at(instr_i);
2052 ir_print_instruction(irp, instruction);2408 if (irp->pass_num == 2) {
2409 irp->printed.put(instruction, 0);
2410 irp->pending.clear();
2411 }
2412 ir_print_instruction(irp, instruction, false);
2413 for (size_t j = 0; j < irp->pending.length; ++j)
2414 ir_print_instruction(irp, irp->pending.at(j), true);
2053 }2415 }
2054 }2416 }
2417
2418 irp->pending.deinit();
2419 irp->printed.deinit();
2055}2420}
20562421
2057void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, int indent_size) {2422void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, int indent_size, size_t pass_num) {
2058 IrPrint ir_print = {};2423 IrPrint ir_print = {};
2059 IrPrint *irp = &ir_print;2424 IrPrint *irp = &ir_print;
2425 irp->pass_num = pass_num;
2060 irp->codegen = codegen;2426 irp->codegen = codegen;
2061 irp->f = f;2427 irp->f = f;
2062 irp->indent = indent_size;2428 irp->indent = indent_size;
2063 irp->indent_size = indent_size;2429 irp->indent_size = indent_size;
2430 irp->printed = {};
2431 irp->printed.init(4);
2432 irp->pending = {};
20642433
2065 ir_print_instruction(irp, instruction);2434 ir_print_instruction(irp, instruction, false);
2066}2435}
src/ir_print.hpp+2-2
...@@ -12,7 +12,7 @@...@@ -12,7 +12,7 @@
1212
13#include <stdio.h>13#include <stdio.h>
1414
15void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size);15void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size, size_t pass_num);
16void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, int indent_size);16void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, int indent_size, size_t pass_num);
1717
18#endif18#endif
src/os.cpp+15-15
...@@ -1125,27 +1125,29 @@ Error os_get_cwd(Buf *out_cwd) {...@@ -1125,27 +1125,29 @@ Error os_get_cwd(Buf *out_cwd) {
1125#endif1125#endif
1126}1126}
11271127
1128#if defined(ZIG_OS_WINDOWS)
1128#define is_wprefix(s, prefix) \1129#define is_wprefix(s, prefix) \
1129 (wcsncmp((s), (prefix), sizeof(prefix) / sizeof(WCHAR) - 1) == 0)1130 (wcsncmp((s), (prefix), sizeof(prefix) / sizeof(WCHAR) - 1) == 0)
1130bool ATTRIBUTE_MUST_USE os_is_cygwin_pty(int fd) {1131static bool is_stderr_cyg_pty(void) {
1131#if defined(ZIG_OS_WINDOWS)1132 HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
1132 HANDLE handle = (HANDLE)_get_osfhandle(fd);1133 if (stderr_handle == INVALID_HANDLE_VALUE)
1133
1134 // Cygwin/msys's pty is a pipe.
1135 if (handle == INVALID_HANDLE_VALUE || GetFileType(handle) != FILE_TYPE_PIPE) {
1136 return false;1134 return false;
1137 }
11381135
1139 int size = sizeof(FILE_NAME_INFO) + sizeof(WCHAR) * MAX_PATH;1136 int size = sizeof(FILE_NAME_INFO) + sizeof(WCHAR) * MAX_PATH;
1137 FILE_NAME_INFO *nameinfo;
1140 WCHAR *p = NULL;1138 WCHAR *p = NULL;
11411139
1142 FILE_NAME_INFO *nameinfo = (FILE_NAME_INFO *)allocate<char>(size);1140 // Cygwin/msys's pty is a pipe.
1141 if (GetFileType(stderr_handle) != FILE_TYPE_PIPE) {
1142 return 0;
1143 }
1144 nameinfo = (FILE_NAME_INFO *)allocate<char>(size);
1143 if (nameinfo == NULL) {1145 if (nameinfo == NULL) {
1144 return false;1146 return 0;
1145 }1147 }
1146 // Check the name of the pipe:1148 // Check the name of the pipe:
1147 // '\{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master'1149 // '\{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master'
1148 if (GetFileInformationByHandleEx(handle, FileNameInfo, nameinfo, size)) {1150 if (GetFileInformationByHandleEx(stderr_handle, FileNameInfo, nameinfo, size)) {
1149 nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = L'\0';1151 nameinfo->FileName[nameinfo->FileNameLength / sizeof(WCHAR)] = L'\0';
1150 p = nameinfo->FileName;1152 p = nameinfo->FileName;
1151 if (is_wprefix(p, L"\\cygwin-")) { /* Cygwin */1153 if (is_wprefix(p, L"\\cygwin-")) { /* Cygwin */
...@@ -1178,14 +1180,12 @@ bool ATTRIBUTE_MUST_USE os_is_cygwin_pty(int fd) {...@@ -1178,14 +1180,12 @@ bool ATTRIBUTE_MUST_USE os_is_cygwin_pty(int fd) {
1178 }1180 }
1179 free(nameinfo);1181 free(nameinfo);
1180 return (p != NULL);1182 return (p != NULL);
1181#else
1182 return false;
1183#endif
1184}1183}
1184#endif
11851185
1186bool os_stderr_tty(void) {1186bool os_stderr_tty(void) {
1187#if defined(ZIG_OS_WINDOWS)1187#if defined(ZIG_OS_WINDOWS)
1188 return _isatty(fileno(stderr)) != 0 || os_is_cygwin_pty(fileno(stderr));1188 return _isatty(_fileno(stderr)) != 0 || is_stderr_cyg_pty();
1189#elif defined(ZIG_OS_POSIX)1189#elif defined(ZIG_OS_POSIX)
1190 return isatty(STDERR_FILENO) != 0;1190 return isatty(STDERR_FILENO) != 0;
1191#else1191#else
...@@ -1486,7 +1486,7 @@ WORD original_console_attributes = FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BL...@@ -1486,7 +1486,7 @@ WORD original_console_attributes = FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BL
14861486
1487void os_stderr_set_color(TermColor color) {1487void os_stderr_set_color(TermColor color) {
1488#if defined(ZIG_OS_WINDOWS)1488#if defined(ZIG_OS_WINDOWS)
1489 if (os_stderr_tty()) {1489 if (is_stderr_cyg_pty()) {
1490 set_color_posix(color);1490 set_color_posix(color);
1491 return;1491 return;
1492 }1492 }
src/os.hpp-8
...@@ -11,7 +11,6 @@...@@ -11,7 +11,6 @@
11#include "list.hpp"11#include "list.hpp"
12#include "buffer.hpp"12#include "buffer.hpp"
13#include "error.hpp"13#include "error.hpp"
14#include "target.hpp"
15#include "zig_llvm.h"14#include "zig_llvm.h"
16#include "windows_sdk.h"15#include "windows_sdk.h"
1716
...@@ -89,11 +88,6 @@ struct Termination {...@@ -89,11 +88,6 @@ struct Termination {
89#define OsFile int88#define OsFile int
90#endif89#endif
9190
92#if defined(ZIG_OS_WINDOWS)
93#undef fileno
94#define fileno _fileno
95#endif
96
97struct OsTimeStamp {91struct OsTimeStamp {
98 uint64_t sec;92 uint64_t sec;
99 uint64_t nsec;93 uint64_t nsec;
...@@ -158,8 +152,6 @@ Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf...@@ -158,8 +152,6 @@ Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf
158Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);152Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
159Error ATTRIBUTE_MUST_USE os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);153Error ATTRIBUTE_MUST_USE os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
160154
161bool ATTRIBUTE_MUST_USE os_is_cygwin_pty(int fd);
162
163Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths);155Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths);
164156
165#endif157#endif
src/parser.cpp+1-1
...@@ -2075,7 +2075,7 @@ static AstNode *ast_parse_param_decl(ParseContext *pc) {...@@ -2075,7 +2075,7 @@ static AstNode *ast_parse_param_decl(ParseContext *pc) {
2075 res->column = first->start_column;2075 res->column = first->start_column;
2076 res->data.param_decl.name = token_buf(name);2076 res->data.param_decl.name = token_buf(name);
2077 res->data.param_decl.is_noalias = first->id == TokenIdKeywordNoAlias;2077 res->data.param_decl.is_noalias = first->id == TokenIdKeywordNoAlias;
2078 res->data.param_decl.is_inline = first->id == TokenIdKeywordCompTime;2078 res->data.param_decl.is_comptime = first->id == TokenIdKeywordCompTime;
2079 return res;2079 return res;
2080}2080}
20812081
src/target.cpp+1-14
...@@ -491,16 +491,6 @@ Error target_parse_glibc_version(ZigGLibCVersion *glibc_ver, const char *text) {...@@ -491,16 +491,6 @@ Error target_parse_glibc_version(ZigGLibCVersion *glibc_ver, const char *text) {
491 return ErrorNone;491 return ErrorNone;
492}492}
493493
494static ZigLLVM_EnvironmentType target_get_win32_abi() {
495 FILE* files[] = { stdin, stdout, stderr, nullptr };
496 for (int i = 0; files[i] != nullptr; i++) {
497 if (os_is_cygwin_pty(fileno(files[i]))) {
498 return ZigLLVM_GNU;
499 }
500 }
501 return ZigLLVM_MSVC;
502}
503
504void get_native_target(ZigTarget *target) {494void get_native_target(ZigTarget *target) {
505 // first zero initialize495 // first zero initialize
506 *target = {};496 *target = {};
...@@ -515,9 +505,6 @@ void get_native_target(ZigTarget *target) {...@@ -515,9 +505,6 @@ void get_native_target(ZigTarget *target) {
515 &target->abi,505 &target->abi,
516 &oformat);506 &oformat);
517 target->os = get_zig_os_type(os_type);507 target->os = get_zig_os_type(os_type);
518 if (target->os == OsWindows) {
519 target->abi = target_get_win32_abi();
520 }
521 target->is_native = true;508 target->is_native = true;
522 if (target->abi == ZigLLVM_UnknownEnvironment) {509 if (target->abi == ZigLLVM_UnknownEnvironment) {
523 target->abi = target_default_abi(target->arch, target->os);510 target->abi = target_default_abi(target->arch, target->os);
...@@ -1614,7 +1601,7 @@ ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) {...@@ -1614,7 +1601,7 @@ ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) {
1614 return ZigLLVM_GNU;1601 return ZigLLVM_GNU;
1615 case OsUefi:1602 case OsUefi:
1616 case OsWindows:1603 case OsWindows:
1617 return ZigLLVM_MSVC; 1604 return ZigLLVM_MSVC;
1618 case OsLinux:1605 case OsLinux:
1619 case OsWASI:1606 case OsWASI:
1620 return ZigLLVM_Musl;1607 return ZigLLVM_Musl;
std/mem.zig+9-1
...@@ -117,7 +117,15 @@ pub const Allocator = struct {...@@ -117,7 +117,15 @@ pub const Allocator = struct {
117 const byte_slice = try self.reallocFn(self, ([*]u8)(undefined)[0..0], undefined, byte_count, a);117 const byte_slice = try self.reallocFn(self, ([*]u8)(undefined)[0..0], undefined, byte_count, a);
118 assert(byte_slice.len == byte_count);118 assert(byte_slice.len == byte_count);
119 @memset(byte_slice.ptr, undefined, byte_slice.len);119 @memset(byte_slice.ptr, undefined, byte_slice.len);
120 return @bytesToSlice(T, @alignCast(a, byte_slice));120 if (alignment == null) {
121 // TODO This is a workaround for zig not being able to successfully do
122 // @bytesToSlice(T, @alignCast(a, byte_slice)) without resolving alignment of T,
123 // which causes a circular dependency in async functions which try to heap-allocate
124 // their own frame with @Frame(func).
125 return @intToPtr([*]T, @ptrToInt(byte_slice.ptr))[0..n];
126 } else {
127 return @bytesToSlice(T, @alignCast(a, byte_slice));
128 }
121 }129 }
122130
123 /// This function requests a new byte size for an existing allocation,131 /// This function requests a new byte size for an existing allocation,
std/os/windows.zig+4-3
...@@ -65,7 +65,7 @@ pub const CreateFileError = error{...@@ -65,7 +65,7 @@ pub const CreateFileError = error{
65 InvalidUtf8,65 InvalidUtf8,
6666
67 /// On Windows, file paths cannot contain these characters:67 /// On Windows, file paths cannot contain these characters:
68 /// '*', '?', '"', '<', '>', '|', and '/' (when the ABI is not GNU)68 /// '/', '*', '?', '"', '<', '>', '|'
69 BadPathName,69 BadPathName,
7070
71 Unexpected,71 Unexpected,
...@@ -836,10 +836,11 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16)...@@ -836,10 +836,11 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16)
836 // > converting the name to an NT-style name, except when using the "\\?\"836 // > converting the name to an NT-style name, except when using the "\\?\"
837 // > prefix as detailed in the following sections.837 // > prefix as detailed in the following sections.
838 // from https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation838 // from https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation
839 // Because we want the larger maximum path length for absolute paths, we
840 // disallow forward slashes in zig std lib file functions on Windows.
839 for (s) |byte| {841 for (s) |byte| {
840 switch (byte) {842 switch (byte) {
841 '*', '?', '"', '<', '>', '|' => return error.BadPathName,843 '/', '*', '?', '"', '<', '>', '|' => return error.BadPathName,
842 '/' => if (builtin.abi == .msvc) return error.BadPathName,
843 else => {},844 else => {},
844 }845 }
845 }846 }
std/special/compiler_rt/comparetf2.zig+7-6
...@@ -38,12 +38,14 @@ pub extern fn __letf2(a: f128, b: f128) c_int {...@@ -38,12 +38,14 @@ pub extern fn __letf2(a: f128, b: f128) c_int {
3838
39 // If at least one of a and b is positive, we get the same result comparing39 // If at least one of a and b is positive, we get the same result comparing
40 // a and b as signed integers as we would with a floating-point compare.40 // a and b as signed integers as we would with a floating-point compare.
41 return if ((aInt & bInt) >= 0) if (aInt < bInt)41 return if ((aInt & bInt) >= 0)
42 LE_LESS42 if (aInt < bInt)
43 else if (aInt == bInt)43 LE_LESS
44 LE_EQUAL44 else if (aInt == bInt)
45 LE_EQUAL
46 else
47 LE_GREATER
45 else48 else
46 LE_GREATER else
47 // Otherwise, both are negative, so we need to flip the sense of the49 // Otherwise, both are negative, so we need to flip the sense of the
48 // comparison to get the correct result. (This assumes a twos- or ones-50 // comparison to get the correct result. (This assumes a twos- or ones-
49 // complement integer representation; if integers are represented in a51 // complement integer representation; if integers are represented in a
...@@ -73,7 +75,6 @@ pub extern fn __getf2(a: f128, b: f128) c_int {...@@ -73,7 +75,6 @@ pub extern fn __getf2(a: f128, b: f128) c_int {
7375
74 if (aAbs > infRep or bAbs > infRep) return GE_UNORDERED;76 if (aAbs > infRep or bAbs > infRep) return GE_UNORDERED;
75 if ((aAbs | bAbs) == 0) return GE_EQUAL;77 if ((aAbs | bAbs) == 0) return GE_EQUAL;
76 // zig fmt issue here, see https://github.com/ziglang/zig/issues/2661
77 return if ((aInt & bInt) >= 0)78 return if ((aInt & bInt) >= 0)
78 if (aInt < bInt)79 if (aInt < bInt)
79 GE_LESS80 GE_LESS
std/zig/parser_test.zig+21
...@@ -482,6 +482,27 @@ test "zig fmt: if-else with comment before else" {...@@ -482,6 +482,27 @@ test "zig fmt: if-else with comment before else" {
482 );482 );
483}483}
484484
485test "zig fmt: if nested" {
486 try testCanonical(
487 \\pub fn foo() void {
488 \\ return if ((aInt & bInt) >= 0)
489 \\ if (aInt < bInt)
490 \\ GE_LESS
491 \\ else if (aInt == bInt)
492 \\ GE_EQUAL
493 \\ else
494 \\ GE_GREATER
495 \\ else if (aInt > bInt)
496 \\ GE_LESS
497 \\ else if (aInt == bInt)
498 \\ GE_EQUAL
499 \\ else
500 \\ GE_GREATER;
501 \\}
502 \\
503 );
504}
505
485test "zig fmt: respect line breaks in if-else" {506test "zig fmt: respect line breaks in if-else" {
486 try testCanonical(507 try testCanonical(
487 \\comptime {508 \\comptime {
std/zig/render.zig+4-2
...@@ -276,7 +276,6 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i...@@ -276,7 +276,6 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i
276 } else {276 } else {
277 try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, Space.Comma); // type,277 try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr.?, Space.Comma); // type,
278 }278 }
279
280 } else if (field.type_expr == null and field.value_expr != null) {279 } else if (field.type_expr == null and field.value_expr != null) {
281 try renderToken(tree, stream, field.name_token, indent, start_col, Space.Space); // name280 try renderToken(tree, stream, field.name_token, indent, start_col, Space.Space); // name
282 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // =281 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // =
...@@ -1521,9 +1520,12 @@ fn renderExpression(...@@ -1521,9 +1520,12 @@ fn renderExpression(
15211520
1522 try renderExpression(allocator, stream, tree, indent, start_col, if_node.condition, Space.None); // condition1521 try renderExpression(allocator, stream, tree, indent, start_col, if_node.condition, Space.None); // condition
15231522
1523 const body_is_if_block = if_node.body.id == ast.Node.Id.If;
1524 const body_is_block = nodeIsBlock(if_node.body);1524 const body_is_block = nodeIsBlock(if_node.body);
15251525
1526 if (body_is_block) {1526 if (body_is_if_block) {
1527 try renderExtraNewline(tree, stream, start_col, if_node.body);
1528 } else if (body_is_block) {
1527 const after_rparen_space = if (if_node.payload == null) Space.BlockStart else Space.Space;1529 const after_rparen_space = if (if_node.payload == null) Space.BlockStart else Space.Space;
1528 try renderToken(tree, stream, rparen, indent, start_col, after_rparen_space); // )1530 try renderToken(tree, stream, rparen, indent, start_col, after_rparen_space); // )
15291531
test/compile_errors.zig+18
...@@ -2,6 +2,22 @@ const tests = @import("tests.zig");...@@ -2,6 +2,22 @@ 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 "wrong type for result ptr to @asyncCall",
7 \\export fn entry() void {
8 \\ _ = async amain();
9 \\}
10 \\fn amain() i32 {
11 \\ var frame: @Frame(foo) = undefined;
12 \\ return await @asyncCall(&frame, false, foo);
13 \\}
14 \\fn foo() i32 {
15 \\ return 1234;
16 \\}
17 ,
18 "tmp.zig:6:37: error: expected type '*i32', found 'bool'",
19 );
20
5 cases.add(21 cases.add(
6 "struct depends on itself via optional field",22 "struct depends on itself via optional field",
7 \\const LhsExpr = struct {23 \\const LhsExpr = struct {
...@@ -1051,6 +1067,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1051,6 +1067,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1051 \\const Foo = struct {};1067 \\const Foo = struct {};
1052 \\export fn a() void {1068 \\export fn a() void {
1053 \\ const T = [*c]Foo;1069 \\ const T = [*c]Foo;
1070 \\ var t: T = undefined;
1054 \\}1071 \\}
1055 ,1072 ,
1056 "tmp.zig:3:19: error: C pointers cannot point to non-C-ABI-compatible type 'Foo'",1073 "tmp.zig:3:19: error: C pointers cannot point to non-C-ABI-compatible type 'Foo'",
...@@ -2290,6 +2307,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2290,6 +2307,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2290 "error union operator with non error set LHS",2307 "error union operator with non error set LHS",
2291 \\comptime {2308 \\comptime {
2292 \\ const z = i32!i32;2309 \\ const z = i32!i32;
2310 \\ var x: z = undefined;
2293 \\}2311 \\}
2294 ,2312 ,
2295 "tmp.zig:2:15: error: expected error set type, found type 'i32'",2313 "tmp.zig:2:15: error: expected error set type, found type 'i32'",
test/stage1/behavior/async_fn.zig+179-2
...@@ -331,8 +331,9 @@ test "async fn with inferred error set" {...@@ -331,8 +331,9 @@ test "async fn with inferred error set" {
331331
332 fn doTheTest() void {332 fn doTheTest() void {
333 var frame: [1]@Frame(middle) = undefined;333 var frame: [1]@Frame(middle) = undefined;
334 var result: anyerror!void = undefined;334 var fn_ptr = middle;
335 _ = @asyncCall(@sliceToBytes(frame[0..]), &result, middle);335 var result: @typeOf(fn_ptr).ReturnType.ErrorSet!void = undefined;
336 _ = @asyncCall(@sliceToBytes(frame[0..]), &result, fn_ptr);
336 resume global_frame;337 resume global_frame;
337 std.testing.expectError(error.Fail, result);338 std.testing.expectError(error.Fail, result);
338 }339 }
...@@ -819,6 +820,34 @@ test "struct parameter to async function is copied to the frame" {...@@ -819,6 +820,34 @@ test "struct parameter to async function is copied to the frame" {
819}820}
820821
821test "cast fn to async fn when it is inferred to be async" {822test "cast fn to async fn when it is inferred to be async" {
823 const S = struct {
824 var frame: anyframe = undefined;
825 var ok = false;
826
827 fn doTheTest() void {
828 var ptr: async fn () i32 = undefined;
829 ptr = func;
830 var buf: [100]u8 align(16) = undefined;
831 var result: i32 = undefined;
832 const f = @asyncCall(&buf, &result, ptr);
833 _ = await f;
834 expect(result == 1234);
835 ok = true;
836 }
837
838 fn func() i32 {
839 suspend {
840 frame = @frame();
841 }
842 return 1234;
843 }
844 };
845 _ = async S.doTheTest();
846 resume S.frame;
847 expect(S.ok);
848}
849
850test "cast fn to async fn when it is inferred to be async, awaited directly" {
822 const S = struct {851 const S = struct {
823 var frame: anyframe = undefined;852 var frame: anyframe = undefined;
824 var ok = false;853 var ok = false;
...@@ -854,3 +883,151 @@ test "await does not force async if callee is blocking" {...@@ -854,3 +883,151 @@ test "await does not force async if callee is blocking" {
854 var x = async S.simple();883 var x = async S.simple();
855 expect(await x == 1234);884 expect(await x == 1234);
856}885}
886
887test "recursive async function" {
888 expect(recursiveAsyncFunctionTest(false).doTheTest() == 55);
889 expect(recursiveAsyncFunctionTest(true).doTheTest() == 55);
890}
891
892fn recursiveAsyncFunctionTest(comptime suspending_implementation: bool) type {
893 return struct {
894 fn fib(allocator: *std.mem.Allocator, x: u32) error{OutOfMemory}!u32 {
895 if (x <= 1) return x;
896
897 if (suspending_implementation) {
898 suspend {
899 resume @frame();
900 }
901 }
902
903 const f1 = try allocator.create(@Frame(fib));
904 defer allocator.destroy(f1);
905
906 const f2 = try allocator.create(@Frame(fib));
907 defer allocator.destroy(f2);
908
909 f1.* = async fib(allocator, x - 1);
910 var f1_awaited = false;
911 errdefer if (!f1_awaited) {
912 _ = await f1;
913 };
914
915 f2.* = async fib(allocator, x - 2);
916 var f2_awaited = false;
917 errdefer if (!f2_awaited) {
918 _ = await f2;
919 };
920
921 var sum: u32 = 0;
922
923 f1_awaited = true;
924 const result_f1 = await f1; // TODO https://github.com/ziglang/zig/issues/3077
925 sum += try result_f1;
926
927 f2_awaited = true;
928 const result_f2 = await f2; // TODO https://github.com/ziglang/zig/issues/3077
929 sum += try result_f2;
930
931 return sum;
932 }
933
934 fn doTheTest() u32 {
935 if (suspending_implementation) {
936 var result: u32 = undefined;
937 _ = async amain(&result);
938 return result;
939 } else {
940 return fib(std.heap.direct_allocator, 10) catch unreachable;
941 }
942 }
943
944 fn amain(result: *u32) void {
945 var x = async fib(std.heap.direct_allocator, 10);
946 const res = await x; // TODO https://github.com/ziglang/zig/issues/3077
947 result.* = res catch unreachable;
948 }
949 };
950}
951
952test "@asyncCall with comptime-known function, but not awaited directly" {
953 const S = struct {
954 var global_frame: anyframe = undefined;
955
956 fn doTheTest() void {
957 var frame: [1]@Frame(middle) = undefined;
958 var result: @typeOf(middle).ReturnType.ErrorSet!void = undefined;
959 _ = @asyncCall(@sliceToBytes(frame[0..]), &result, middle);
960 resume global_frame;
961 std.testing.expectError(error.Fail, result);
962 }
963
964 async fn middle() !void {
965 var f = async middle2();
966 return await f;
967 }
968
969 fn middle2() !void {
970 return failing();
971 }
972
973 fn failing() !void {
974 global_frame = @frame();
975 suspend;
976 return error.Fail;
977 }
978 };
979 S.doTheTest();
980}
981
982test "@asyncCall with actual frame instead of byte buffer" {
983 const S = struct {
984 fn func() i32 {
985 suspend;
986 return 1234;
987 }
988 };
989 var frame: @Frame(S.func) = undefined;
990 var result: i32 = undefined;
991 const ptr = @asyncCall(&frame, &result, S.func);
992 resume ptr;
993 expect(result == 1234);
994}
995
996test "@asyncCall using the result location inside the frame" {
997 const S = struct {
998 async fn simple2(y: *i32) i32 {
999 defer y.* += 2;
1000 y.* += 1;
1001 suspend;
1002 return 1234;
1003 }
1004 fn getAnswer(f: anyframe->i32, out: *i32) void {
1005 var res = await f; // TODO https://github.com/ziglang/zig/issues/3077
1006 out.* = res;
1007 }
1008 };
1009 var data: i32 = 1;
1010 const Foo = struct {
1011 bar: async fn (*i32) i32,
1012 };
1013 var foo = Foo{ .bar = S.simple2 };
1014 var bytes: [64]u8 align(16) = undefined;
1015 const f = @asyncCall(&bytes, {}, foo.bar, &data);
1016 comptime expect(@typeOf(f) == anyframe->i32);
1017 expect(data == 2);
1018 resume f;
1019 expect(data == 4);
1020 _ = async S.getAnswer(f, &data);
1021 expect(data == 1234);
1022}
1023
1024test "@typeOf an async function call of generic fn with error union type" {
1025 const S = struct {
1026 fn func(comptime x: var) anyerror!i32 {
1027 const T = @typeOf(async func(x));
1028 comptime expect(T == @typeOf(@frame()).Child);
1029 return undefined;
1030 }
1031 };
1032 _ = async S.func(i32);
1033}
test/stage1/behavior/sizeof_and_typeof.zig+26
...@@ -89,3 +89,29 @@ test "@sizeOf(T) == 0 doesn't force resolving struct size" {...@@ -89,3 +89,29 @@ test "@sizeOf(T) == 0 doesn't force resolving struct size" {
89 expect(@sizeOf(S.Foo) == 4);89 expect(@sizeOf(S.Foo) == 4);
90 expect(@sizeOf(S.Bar) == 8);90 expect(@sizeOf(S.Bar) == 8);
91}91}
92
93test "@typeOf() has no runtime side effects" {
94 const S = struct {
95 fn foo(comptime T: type, ptr: *T) T {
96 ptr.* += 1;
97 return ptr.*;
98 }
99 };
100 var data: i32 = 0;
101 const T = @typeOf(S.foo(i32, &data));
102 comptime expect(T == i32);
103 expect(data == 0);
104}
105
106test "branching logic inside @typeOf" {
107 const S = struct {
108 var data: i32 = 0;
109 fn foo() anyerror!i32 {
110 data += 1;
111 return undefined;
112 }
113 };
114 const T = @typeOf(S.foo() catch undefined);
115 comptime expect(T == i32);
116 expect(S.data == 0);
117}