| author | |
| committer | |
| log | fcadeb50c04199fce2d9675ba2976680c71c67ff |
| tree | 6d4bba1ab17adc6f6b42539c2dbeadf166327e37 |
| parent | 650e07ebd96d6c476cadc1f7c19856e950ceef9c |
| signature |
5 files changed, 123 insertions(+), 45 deletions(-)
src/analyze.cpp+50-18| ... | @@ -1865,7 +1865,8 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) { | ... | @@ -1865,7 +1865,8 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) { |
| 1865 | } | 1865 | } |
| 1866 | 1866 | ||
| 1867 | static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { | 1867 | static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { |
| 1868 | assert(frame_type->data.frame.locals_struct == nullptr); | 1868 | if (frame_type->data.frame.locals_struct != nullptr) |
| 1869 | return ErrorNone; | ||
| 1869 | 1870 | ||
| 1870 | ZigFn *fn = frame_type->data.frame.fn; | 1871 | ZigFn *fn = frame_type->data.frame.fn; |
| 1871 | switch (fn->anal_state) { | 1872 | switch (fn->anal_state) { |
| ... | @@ -3824,6 +3825,15 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn_table_entry, AstNode *return_typ | ... | @@ -3824,6 +3825,15 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn_table_entry, AstNode *return_typ |
| 3824 | } | 3825 | } |
| 3825 | 3826 | ||
| 3826 | fn_table_entry->anal_state = FnAnalStateComplete; | 3827 | fn_table_entry->anal_state = FnAnalStateComplete; |
| 3828 | |||
| 3829 | if (fn_table_entry->resume_blocks.length != 0) { | ||
| 3830 | ZigType *frame_type = get_coro_frame_type(g, fn_table_entry); | ||
| 3831 | Error err; | ||
| 3832 | if ((err = type_resolve(g, frame_type, ResolveStatusSizeKnown))) { | ||
| 3833 | fn_table_entry->anal_state = FnAnalStateInvalid; | ||
| 3834 | return; | ||
| 3835 | } | ||
| 3836 | } | ||
| 3827 | } | 3837 | } |
| 3828 | 3838 | ||
| 3829 | static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) { | 3839 | static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry) { |
| ... | @@ -7050,18 +7060,12 @@ static void resolve_llvm_types_array(CodeGen *g, ZigType *type) { | ... | @@ -7050,18 +7060,12 @@ static void resolve_llvm_types_array(CodeGen *g, ZigType *type) { |
| 7050 | debug_align_in_bits, get_llvm_di_type(g, elem_type), (int)type->data.array.len); | 7060 | debug_align_in_bits, get_llvm_di_type(g, elem_type), (int)type->data.array.len); |
| 7051 | } | 7061 | } |
| 7052 | 7062 | ||
| 7053 | void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type, ZigFn *fn) { | 7063 | static void resolve_llvm_types_fn_type(CodeGen *g, ZigType *fn_type) { |
| 7054 | if (fn_type->llvm_di_type != nullptr) { | 7064 | if (fn_type->llvm_di_type != nullptr) return; |
| 7055 | if (fn != nullptr) { | ||
| 7056 | fn->raw_type_ref = fn_type->data.fn.raw_type_ref; | ||
| 7057 | fn->raw_di_type = fn_type->data.fn.raw_di_type; | ||
| 7058 | } | ||
| 7059 | return; | ||
| 7060 | } | ||
| 7061 | 7065 | ||
| 7062 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; | 7066 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; |
| 7063 | bool first_arg_return = want_first_arg_sret(g, fn_type_id); | 7067 | bool first_arg_return = want_first_arg_sret(g, fn_type_id); |
| 7064 | bool is_async = fn_type_id->cc == CallingConventionAsync || (fn != nullptr && fn->resume_blocks.length != 0); | 7068 | bool is_async = fn_type_id->cc == CallingConventionAsync; |
| 7065 | bool is_c_abi = fn_type_id->cc == CallingConventionC; | 7069 | bool is_c_abi = fn_type_id->cc == CallingConventionC; |
| 7066 | bool prefix_arg_error_return_trace = g->have_err_ret_tracing && fn_type_can_fail(fn_type_id); | 7070 | bool prefix_arg_error_return_trace = g->have_err_ret_tracing && fn_type_can_fail(fn_type_id); |
| 7067 | // +1 for maybe making the first argument the return value | 7071 | // +1 for maybe making the first argument the return value |
| ... | @@ -7100,7 +7104,11 @@ void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type, ZigFn *fn) { | ... | @@ -7100,7 +7104,11 @@ void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type, ZigFn *fn) { |
| 7100 | if (is_async) { | 7104 | if (is_async) { |
| 7101 | fn_type->data.fn.gen_param_info = allocate<FnGenParamInfo>(1); | 7105 | fn_type->data.fn.gen_param_info = allocate<FnGenParamInfo>(1); |
| 7102 | 7106 | ||
| 7103 | ZigType *frame_type = (fn == nullptr) ? g->builtin_types.entry_frame_header : get_coro_frame_type(g, fn); | 7107 | ZigType *frame_type = g->builtin_types.entry_frame_header; |
| 7108 | Error err; | ||
| 7109 | if ((err = type_resolve(g, frame_type, ResolveStatusSizeKnown))) { | ||
| 7110 | zig_unreachable(); | ||
| 7111 | } | ||
| 7104 | ZigType *ptr_type = get_pointer_to_type(g, frame_type, false); | 7112 | ZigType *ptr_type = get_pointer_to_type(g, frame_type, false); |
| 7105 | gen_param_types.append(get_llvm_type(g, ptr_type)); | 7113 | gen_param_types.append(get_llvm_type(g, ptr_type)); |
| 7106 | param_di_types.append(get_llvm_di_type(g, ptr_type)); | 7114 | param_di_types.append(get_llvm_di_type(g, ptr_type)); |
| ... | @@ -7150,12 +7158,7 @@ void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type, ZigFn *fn) { | ... | @@ -7150,12 +7158,7 @@ void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type, ZigFn *fn) { |
| 7150 | for (size_t i = 0; i < gen_param_types.length; i += 1) { | 7158 | for (size_t i = 0; i < gen_param_types.length; i += 1) { |
| 7151 | assert(gen_param_types.items[i] != nullptr); | 7159 | assert(gen_param_types.items[i] != nullptr); |
| 7152 | } | 7160 | } |
| 7153 | if (fn != nullptr) { | 7161 | |
| 7154 | fn->raw_type_ref = LLVMFunctionType(get_llvm_type(g, gen_return_type), | ||
| 7155 | gen_param_types.items, (unsigned int)gen_param_types.length, fn_type_id->is_var_args); | ||
| 7156 | fn->raw_di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types.items, (int)param_di_types.length, 0); | ||
| 7157 | return; | ||
| 7158 | } | ||
| 7159 | fn_type->data.fn.raw_type_ref = LLVMFunctionType(get_llvm_type(g, gen_return_type), | 7162 | fn_type->data.fn.raw_type_ref = LLVMFunctionType(get_llvm_type(g, gen_return_type), |
| 7160 | gen_param_types.items, (unsigned int)gen_param_types.length, fn_type_id->is_var_args); | 7163 | gen_param_types.items, (unsigned int)gen_param_types.length, fn_type_id->is_var_args); |
| 7161 | fn_type->llvm_type = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0); | 7164 | fn_type->llvm_type = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0); |
| ... | @@ -7165,6 +7168,35 @@ void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type, ZigFn *fn) { | ... | @@ -7165,6 +7168,35 @@ void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type, ZigFn *fn) { |
| 7165 | LLVMABIAlignmentOfType(g->target_data_ref, fn_type->llvm_type), ""); | 7168 | LLVMABIAlignmentOfType(g->target_data_ref, fn_type->llvm_type), ""); |
| 7166 | } | 7169 | } |
| 7167 | 7170 | ||
| 7171 | void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn) { | ||
| 7172 | if (fn->raw_di_type != nullptr) return; | ||
| 7173 | |||
| 7174 | ZigType *fn_type = fn->type_entry; | ||
| 7175 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; | ||
| 7176 | bool cc_async = fn_type_id->cc == CallingConventionAsync; | ||
| 7177 | bool inferred_async = fn->resume_blocks.length != 0; | ||
| 7178 | bool is_async = cc_async || inferred_async; | ||
| 7179 | if (!is_async) { | ||
| 7180 | resolve_llvm_types_fn_type(g, fn_type); | ||
| 7181 | fn->raw_type_ref = fn_type->data.fn.raw_type_ref; | ||
| 7182 | fn->raw_di_type = fn_type->data.fn.raw_di_type; | ||
| 7183 | return; | ||
| 7184 | } | ||
| 7185 | |||
| 7186 | ZigType *gen_return_type = g->builtin_types.entry_usize; | ||
| 7187 | ZigList<ZigLLVMDIType *> param_di_types = {}; | ||
| 7188 | // first "parameter" is return value | ||
| 7189 | param_di_types.append(get_llvm_di_type(g, gen_return_type)); | ||
| 7190 | |||
| 7191 | ZigType *frame_type = get_coro_frame_type(g, fn); | ||
| 7192 | ZigType *ptr_type = get_pointer_to_type(g, frame_type, false); | ||
| 7193 | LLVMTypeRef gen_param_type = get_llvm_type(g, ptr_type); | ||
| 7194 | param_di_types.append(get_llvm_di_type(g, ptr_type)); | ||
| 7195 | |||
| 7196 | fn->raw_type_ref = LLVMFunctionType(get_llvm_type(g, gen_return_type), &gen_param_type, 1, false); | ||
| 7197 | fn->raw_di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types.items, (int)param_di_types.length, 0); | ||
| 7198 | } | ||
| 7199 | |||
| 7168 | static void resolve_llvm_types_anyerror(CodeGen *g) { | 7200 | static void resolve_llvm_types_anyerror(CodeGen *g) { |
| 7169 | ZigType *entry = g->builtin_types.entry_global_error_set; | 7201 | ZigType *entry = g->builtin_types.entry_global_error_set; |
| 7170 | entry->llvm_type = get_llvm_type(g, g->err_tag_type); | 7202 | entry->llvm_type = get_llvm_type(g, g->err_tag_type); |
| ... | @@ -7241,7 +7273,7 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_r | ... | @@ -7241,7 +7273,7 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_r |
| 7241 | case ZigTypeIdArray: | 7273 | case ZigTypeIdArray: |
| 7242 | return resolve_llvm_types_array(g, type); | 7274 | return resolve_llvm_types_array(g, type); |
| 7243 | case ZigTypeIdFn: | 7275 | case ZigTypeIdFn: |
| 7244 | return resolve_llvm_types_fn(g, type, nullptr); | 7276 | return resolve_llvm_types_fn_type(g, type); |
| 7245 | case ZigTypeIdErrorSet: { | 7277 | case ZigTypeIdErrorSet: { |
| 7246 | if (type->llvm_di_type != nullptr) return; | 7278 | if (type->llvm_di_type != nullptr) return; |
| 7247 | 7279 |
src/analyze.hpp+1-1| ... | @@ -247,6 +247,6 @@ void src_assert(bool ok, AstNode *source_node); | ... | @@ -247,6 +247,6 @@ void src_assert(bool ok, AstNode *source_node); |
| 247 | bool is_container(ZigType *type_entry); | 247 | bool is_container(ZigType *type_entry); |
| 248 | ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name); | 248 | ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name); |
| 249 | 249 | ||
| 250 | void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type, ZigFn *fn); | 250 | void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn); |
| 251 | 251 | ||
| 252 | #endif | 252 | #endif |
src/codegen.cpp+40-26| ... | @@ -371,10 +371,12 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { | ... | @@ -371,10 +371,12 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { |
| 371 | symbol_name = buf_sprintf("\x01_%s", buf_ptr(symbol_name)); | 371 | symbol_name = buf_sprintf("\x01_%s", buf_ptr(symbol_name)); |
| 372 | } | 372 | } |
| 373 | 373 | ||
| 374 | bool is_async = fn_table_entry->resume_blocks.length != 0 || cc == CallingConventionAsync; | ||
| 375 | |||
| 374 | 376 | ||
| 375 | ZigType *fn_type = fn_table_entry->type_entry; | 377 | ZigType *fn_type = fn_table_entry->type_entry; |
| 376 | // Make the raw_type_ref populated | 378 | // Make the raw_type_ref populated |
| 377 | resolve_llvm_types_fn(g, fn_type, fn_table_entry); | 379 | resolve_llvm_types_fn(g, fn_table_entry); |
| 378 | LLVMTypeRef fn_llvm_type = fn_table_entry->raw_type_ref; | 380 | LLVMTypeRef fn_llvm_type = fn_table_entry->raw_type_ref; |
| 379 | if (fn_table_entry->body_node == nullptr) { | 381 | if (fn_table_entry->body_node == nullptr) { |
| 380 | LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name)); | 382 | LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name)); |
| ... | @@ -397,7 +399,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { | ... | @@ -397,7 +399,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { |
| 397 | assert(entry->value->id == TldIdFn); | 399 | assert(entry->value->id == TldIdFn); |
| 398 | TldFn *tld_fn = reinterpret_cast<TldFn *>(entry->value); | 400 | TldFn *tld_fn = reinterpret_cast<TldFn *>(entry->value); |
| 399 | // Make the raw_type_ref populated | 401 | // Make the raw_type_ref populated |
| 400 | resolve_llvm_types_fn(g, tld_fn->fn_entry->type_entry, tld_fn->fn_entry); | 402 | resolve_llvm_types_fn(g, tld_fn->fn_entry); |
| 401 | tld_fn->fn_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), | 403 | tld_fn->fn_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), |
| 402 | tld_fn->fn_entry->raw_type_ref); | 404 | tld_fn->fn_entry->raw_type_ref); |
| 403 | fn_table_entry->llvm_value = LLVMConstBitCast(tld_fn->fn_entry->llvm_value, | 405 | fn_table_entry->llvm_value = LLVMConstBitCast(tld_fn->fn_entry->llvm_value, |
| ... | @@ -517,18 +519,22 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { | ... | @@ -517,18 +519,22 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { |
| 517 | init_gen_i = 1; | 519 | init_gen_i = 1; |
| 518 | } | 520 | } |
| 519 | 521 | ||
| 520 | // set parameter attributes | 522 | if (is_async) { |
| 521 | FnWalk fn_walk = {}; | 523 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull"); |
| 522 | fn_walk.id = FnWalkIdAttrs; | 524 | } else { |
| 523 | fn_walk.data.attrs.fn = fn_table_entry; | 525 | // set parameter attributes |
| 524 | fn_walk.data.attrs.gen_i = init_gen_i; | 526 | FnWalk fn_walk = {}; |
| 525 | walk_function_params(g, fn_type, &fn_walk); | 527 | fn_walk.id = FnWalkIdAttrs; |
| 528 | fn_walk.data.attrs.fn = fn_table_entry; | ||
| 529 | fn_walk.data.attrs.gen_i = init_gen_i; | ||
| 530 | walk_function_params(g, fn_type, &fn_walk); | ||
| 526 | 531 | ||
| 527 | uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry); | 532 | uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry); |
| 528 | if (err_ret_trace_arg_index != UINT32_MAX) { | 533 | if (err_ret_trace_arg_index != UINT32_MAX) { |
| 529 | // Error return trace memory is in the stack, which is impossible to be at address 0 | 534 | // Error return trace memory is in the stack, which is impossible to be at address 0 |
| 530 | // on any architecture. | 535 | // on any architecture. |
| 531 | addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull"); | 536 | addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull"); |
| 537 | } | ||
| 532 | } | 538 | } |
| 533 | 539 | ||
| 534 | return fn_table_entry->llvm_value; | 540 | return fn_table_entry->llvm_value; |
| ... | @@ -6254,14 +6260,21 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6254,14 +6260,21 @@ static void do_code_gen(CodeGen *g) { |
| 6254 | } else if (is_c_abi) { | 6260 | } else if (is_c_abi) { |
| 6255 | fn_walk_var.data.vars.var = var; | 6261 | fn_walk_var.data.vars.var = var; |
| 6256 | iter_function_params_c_abi(g, fn_table_entry->type_entry, &fn_walk_var, var->src_arg_index); | 6262 | iter_function_params_c_abi(g, fn_table_entry->type_entry, &fn_walk_var, var->src_arg_index); |
| 6263 | } else if (is_async) { | ||
| 6264 | var->value_ref = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_arg_start + var_i, ""); | ||
| 6265 | if (var->decl_node) { | ||
| 6266 | var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), | ||
| 6267 | buf_ptr(&var->name), import->data.structure.root_struct->di_file, | ||
| 6268 | (unsigned)(var->decl_node->line + 1), | ||
| 6269 | get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0); | ||
| 6270 | gen_var_debug_decl(g, var); | ||
| 6271 | } | ||
| 6257 | } else { | 6272 | } else { |
| 6258 | ZigType *gen_type; | 6273 | ZigType *gen_type; |
| 6259 | FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index]; | 6274 | FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index]; |
| 6260 | assert(gen_info->gen_index != SIZE_MAX); | 6275 | assert(gen_info->gen_index != SIZE_MAX); |
| 6261 | 6276 | ||
| 6262 | if (is_async) { | 6277 | if (handle_is_ptr(var->var_type)) { |
| 6263 | var->value_ref = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_arg_start + var_i, ""); | ||
| 6264 | } else if (handle_is_ptr(var->var_type)) { | ||
| 6265 | if (gen_info->is_byval) { | 6278 | if (gen_info->is_byval) { |
| 6266 | gen_type = var->var_type; | 6279 | gen_type = var->var_type; |
| 6267 | } else { | 6280 | } else { |
| ... | @@ -6307,16 +6320,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6307,16 +6320,7 @@ static void do_code_gen(CodeGen *g) { |
| 6307 | gen_store(g, LLVMConstInt(usize->llvm_type, stack_trace_ptr_count, false), len_field_ptr, get_pointer_to_type(g, usize, false)); | 6320 | gen_store(g, LLVMConstInt(usize->llvm_type, stack_trace_ptr_count, false), len_field_ptr, get_pointer_to_type(g, usize, false)); |
| 6308 | } | 6321 | } |
| 6309 | 6322 | ||
| 6310 | // create debug variable declarations for parameters | 6323 | if (is_async) { |
| 6311 | // rely on the first variables in the variable_list being parameters. | ||
| 6312 | FnWalk fn_walk_init = {}; | ||
| 6313 | fn_walk_init.id = FnWalkIdInits; | ||
| 6314 | fn_walk_init.data.inits.fn = fn_table_entry; | ||
| 6315 | fn_walk_init.data.inits.llvm_fn = fn; | ||
| 6316 | fn_walk_init.data.inits.gen_i = gen_i_init; | ||
| 6317 | walk_function_params(g, fn_table_entry->type_entry, &fn_walk_init); | ||
| 6318 | |||
| 6319 | if (fn_table_entry->resume_blocks.length != 0) { | ||
| 6320 | if (!g->strip_debug_symbols) { | 6324 | if (!g->strip_debug_symbols) { |
| 6321 | AstNode *source_node = fn_table_entry->proto_node; | 6325 | AstNode *source_node = fn_table_entry->proto_node; |
| 6322 | ZigLLVMSetCurrentDebugLocation(g->builder, (int)source_node->line + 1, | 6326 | ZigLLVMSetCurrentDebugLocation(g->builder, (int)source_node->line + 1, |
| ... | @@ -6354,8 +6358,18 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6354,8 +6358,18 @@ static void do_code_gen(CodeGen *g) { |
| 6354 | LLVMValueRef case_value = LLVMConstInt(usize_type_ref, resume_i + 2, false); | 6358 | LLVMValueRef case_value = LLVMConstInt(usize_type_ref, resume_i + 2, false); |
| 6355 | LLVMAddCase(switch_instr, case_value, fn_table_entry->resume_blocks.at(resume_i)->llvm_block); | 6359 | LLVMAddCase(switch_instr, case_value, fn_table_entry->resume_blocks.at(resume_i)->llvm_block); |
| 6356 | } | 6360 | } |
| 6361 | } else { | ||
| 6362 | // create debug variable declarations for parameters | ||
| 6363 | // rely on the first variables in the variable_list being parameters. | ||
| 6364 | FnWalk fn_walk_init = {}; | ||
| 6365 | fn_walk_init.id = FnWalkIdInits; | ||
| 6366 | fn_walk_init.data.inits.fn = fn_table_entry; | ||
| 6367 | fn_walk_init.data.inits.llvm_fn = fn; | ||
| 6368 | fn_walk_init.data.inits.gen_i = gen_i_init; | ||
| 6369 | walk_function_params(g, fn_table_entry->type_entry, &fn_walk_init); | ||
| 6357 | } | 6370 | } |
| 6358 | 6371 | ||
| 6372 | |||
| 6359 | ir_render(g, fn_table_entry); | 6373 | ir_render(g, fn_table_entry); |
| 6360 | 6374 | ||
| 6361 | } | 6375 | } |
test/runtime_safety.zig+14| ... | @@ -1,6 +1,20 @@ | ... | @@ -1,6 +1,20 @@ |
| 1 | const tests = @import("tests.zig"); | 1 | const tests = @import("tests.zig"); |
| 2 | 2 | ||
| 3 | pub fn addCases(cases: *tests.CompareOutputContext) void { | 3 | pub fn addCases(cases: *tests.CompareOutputContext) void { |
| 4 | cases.addRuntimeSafety("invalid resume of async function", | ||
| 5 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { | ||
| 6 | \\ @import("std").os.exit(126); | ||
| 7 | \\} | ||
| 8 | \\pub fn main() void { | ||
| 9 | \\ var p = async suspendOnce(); | ||
| 10 | \\ resume p; //ok | ||
| 11 | \\ resume p; //bad | ||
| 12 | \\} | ||
| 13 | \\fn suspendOnce() void { | ||
| 14 | \\ suspend; | ||
| 15 | \\} | ||
| 16 | ); | ||
| 17 | |||
| 4 | cases.addRuntimeSafety(".? operator on null pointer", | 18 | cases.addRuntimeSafety(".? operator on null pointer", |
| 5 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { | 19 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { |
| 6 | \\ @import("std").os.exit(126); | 20 | \\ @import("std").os.exit(126); |
test/stage1/behavior/coroutines.zig+18| ... | @@ -29,6 +29,24 @@ fn simpleAsyncFnWithArg(delta: i32) void { | ... | @@ -29,6 +29,24 @@ fn simpleAsyncFnWithArg(delta: i32) void { |
| 29 | suspend; | 29 | suspend; |
| 30 | global_y += delta; | 30 | global_y += delta; |
| 31 | } | 31 | } |
| 32 | |||
| 33 | test "suspend at end of function" { | ||
| 34 | const S = struct { | ||
| 35 | var x: i32 = 1; | ||
| 36 | |||
| 37 | fn doTheTest() void { | ||
| 38 | expect(x == 1); | ||
| 39 | const p = async suspendAtEnd(); | ||
| 40 | expect(x == 2); | ||
| 41 | } | ||
| 42 | |||
| 43 | fn suspendAtEnd() void { | ||
| 44 | x += 1; | ||
| 45 | suspend; | ||
| 46 | } | ||
| 47 | }; | ||
| 48 | S.doTheTest(); | ||
| 49 | } | ||
| 32 | //test "coroutine suspend, resume" { | 50 | //test "coroutine suspend, resume" { |
| 33 | // seq('a'); | 51 | // seq('a'); |
| 34 | // const p = try async<allocator> testAsyncSeq(); | 52 | // const p = try async<allocator> testAsyncSeq(); |