| ... | @@ -343,27 +343,24 @@ static bool cc_want_sret_attr(CallingConvention cc) { | ... | @@ -343,27 +343,24 @@ static bool cc_want_sret_attr(CallingConvention cc) { |
| 343 | zig_unreachable(); | 343 | zig_unreachable(); |
| 344 | } | 344 | } |
| 345 | | 345 | |
| 346 | static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { | 346 | static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { |
| 347 | if (fn_table_entry->llvm_value) | 347 | Buf *unmangled_name = &fn->symbol_name; |
| 348 | return fn_table_entry->llvm_value; | | |
| 349 | | | |
| 350 | Buf *unmangled_name = &fn_table_entry->symbol_name; | | |
| 351 | Buf *symbol_name; | 348 | Buf *symbol_name; |
| 352 | GlobalLinkageId linkage; | 349 | GlobalLinkageId linkage; |
| 353 | if (fn_table_entry->body_node == nullptr) { | 350 | if (fn->body_node == nullptr) { |
| 354 | symbol_name = unmangled_name; | 351 | symbol_name = unmangled_name; |
| 355 | linkage = GlobalLinkageIdStrong; | 352 | linkage = GlobalLinkageIdStrong; |
| 356 | } else if (fn_table_entry->export_list.length == 0) { | 353 | } else if (fn->export_list.length == 0) { |
| 357 | symbol_name = get_mangled_name(g, unmangled_name, false); | 354 | symbol_name = get_mangled_name(g, unmangled_name, false); |
| 358 | linkage = GlobalLinkageIdInternal; | 355 | linkage = GlobalLinkageIdInternal; |
| 359 | } else { | 356 | } else { |
| 360 | GlobalExport *fn_export = &fn_table_entry->export_list.items[0]; | 357 | GlobalExport *fn_export = &fn->export_list.items[0]; |
| 361 | symbol_name = &fn_export->name; | 358 | symbol_name = &fn_export->name; |
| 362 | linkage = fn_export->linkage; | 359 | linkage = fn_export->linkage; |
| 363 | } | 360 | } |
| 364 | | 361 | |
| 365 | bool external_linkage = linkage != GlobalLinkageIdInternal; | 362 | bool external_linkage = linkage != GlobalLinkageIdInternal; |
| 366 | CallingConvention cc = fn_table_entry->type_entry->data.fn.fn_type_id.cc; | 363 | CallingConvention cc = fn->type_entry->data.fn.fn_type_id.cc; |
| 367 | if (cc == CallingConventionStdcall && external_linkage && | 364 | if (cc == CallingConventionStdcall && external_linkage && |
| 368 | g->zig_target->arch == ZigLLVM_x86) | 365 | g->zig_target->arch == ZigLLVM_x86) |
| 369 | { | 366 | { |
| ... | @@ -371,28 +368,28 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { | ... | @@ -371,28 +368,28 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { |
| 371 | symbol_name = buf_sprintf("\x01_%s", buf_ptr(symbol_name)); | 368 | symbol_name = buf_sprintf("\x01_%s", buf_ptr(symbol_name)); |
| 372 | } | 369 | } |
| 373 | | 370 | |
| 374 | bool is_async = fn_is_async(fn_table_entry); | 371 | bool is_async = fn_is_async(fn); |
| 375 | | 372 | |
| 376 | | 373 | |
| 377 | ZigType *fn_type = fn_table_entry->type_entry; | 374 | ZigType *fn_type = fn->type_entry; |
| 378 | // Make the raw_type_ref populated | 375 | // Make the raw_type_ref populated |
| 379 | resolve_llvm_types_fn(g, fn_table_entry); | 376 | resolve_llvm_types_fn(g, fn); |
| 380 | LLVMTypeRef fn_llvm_type = fn_table_entry->raw_type_ref; | 377 | LLVMTypeRef fn_llvm_type = fn->raw_type_ref; |
| 381 | if (fn_table_entry->body_node == nullptr) { | 378 | LLVMValueRef llvm_fn = nullptr; |
| | 379 | if (fn->body_node == nullptr) { |
| 382 | LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name)); | 380 | LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name)); |
| 383 | if (existing_llvm_fn) { | 381 | if (existing_llvm_fn) { |
| 384 | fn_table_entry->llvm_value = LLVMConstBitCast(existing_llvm_fn, LLVMPointerType(fn_llvm_type, 0)); | 382 | return LLVMConstBitCast(existing_llvm_fn, LLVMPointerType(fn_llvm_type, 0)); |
| 385 | return fn_table_entry->llvm_value; | | |
| 386 | } else { | 383 | } else { |
| 387 | auto entry = g->exported_symbol_names.maybe_get(symbol_name); | 384 | auto entry = g->exported_symbol_names.maybe_get(symbol_name); |
| 388 | if (entry == nullptr) { | 385 | if (entry == nullptr) { |
| 389 | fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type); | 386 | llvm_fn = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type); |
| 390 | | 387 | |
| 391 | if (target_is_wasm(g->zig_target)) { | 388 | if (target_is_wasm(g->zig_target)) { |
| 392 | assert(fn_table_entry->proto_node->type == NodeTypeFnProto); | 389 | assert(fn->proto_node->type == NodeTypeFnProto); |
| 393 | AstNodeFnProto *fn_proto = &fn_table_entry->proto_node->data.fn_proto; | 390 | AstNodeFnProto *fn_proto = &fn->proto_node->data.fn_proto; |
| 394 | if (fn_proto-> is_extern && fn_proto->lib_name != nullptr ) { | 391 | if (fn_proto-> is_extern && fn_proto->lib_name != nullptr ) { |
| 395 | addLLVMFnAttrStr(fn_table_entry->llvm_value, "wasm-import-module", buf_ptr(fn_proto->lib_name)); | 392 | addLLVMFnAttrStr(llvm_fn, "wasm-import-module", buf_ptr(fn_proto->lib_name)); |
| 396 | } | 393 | } |
| 397 | } | 394 | } |
| 398 | } else { | 395 | } else { |
| ... | @@ -402,101 +399,98 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { | ... | @@ -402,101 +399,98 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { |
| 402 | resolve_llvm_types_fn(g, tld_fn->fn_entry); | 399 | resolve_llvm_types_fn(g, tld_fn->fn_entry); |
| 403 | tld_fn->fn_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), | 400 | tld_fn->fn_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), |
| 404 | tld_fn->fn_entry->raw_type_ref); | 401 | tld_fn->fn_entry->raw_type_ref); |
| 405 | fn_table_entry->llvm_value = LLVMConstBitCast(tld_fn->fn_entry->llvm_value, | 402 | llvm_fn = LLVMConstBitCast(tld_fn->fn_entry->llvm_value, LLVMPointerType(fn_llvm_type, 0)); |
| 406 | LLVMPointerType(fn_llvm_type, 0)); | 403 | return llvm_fn; |
| 407 | return fn_table_entry->llvm_value; | | |
| 408 | } | 404 | } |
| 409 | } | 405 | } |
| 410 | } else { | 406 | } else { |
| 411 | if (fn_table_entry->llvm_value == nullptr) { | 407 | if (llvm_fn == nullptr) { |
| 412 | fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type); | 408 | llvm_fn = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type); |
| 413 | } | 409 | } |
| 414 | | 410 | |
| 415 | for (size_t i = 1; i < fn_table_entry->export_list.length; i += 1) { | 411 | for (size_t i = 1; i < fn->export_list.length; i += 1) { |
| 416 | GlobalExport *fn_export = &fn_table_entry->export_list.items[i]; | 412 | GlobalExport *fn_export = &fn->export_list.items[i]; |
| 417 | LLVMAddAlias(g->module, LLVMTypeOf(fn_table_entry->llvm_value), | 413 | LLVMAddAlias(g->module, LLVMTypeOf(llvm_fn), llvm_fn, buf_ptr(&fn_export->name)); |
| 418 | fn_table_entry->llvm_value, buf_ptr(&fn_export->name)); | | |
| 419 | } | 414 | } |
| 420 | } | 415 | } |
| 421 | fn_table_entry->llvm_name = strdup(LLVMGetValueName(fn_table_entry->llvm_value)); | | |
| 422 | | 416 | |
| 423 | switch (fn_table_entry->fn_inline) { | 417 | switch (fn->fn_inline) { |
| 424 | case FnInlineAlways: | 418 | case FnInlineAlways: |
| 425 | addLLVMFnAttr(fn_table_entry->llvm_value, "alwaysinline"); | 419 | addLLVMFnAttr(llvm_fn, "alwaysinline"); |
| 426 | g->inline_fns.append(fn_table_entry); | 420 | g->inline_fns.append(fn); |
| 427 | break; | 421 | break; |
| 428 | case FnInlineNever: | 422 | case FnInlineNever: |
| 429 | addLLVMFnAttr(fn_table_entry->llvm_value, "noinline"); | 423 | addLLVMFnAttr(llvm_fn, "noinline"); |
| 430 | break; | 424 | break; |
| 431 | case FnInlineAuto: | 425 | case FnInlineAuto: |
| 432 | if (fn_table_entry->alignstack_value != 0) { | 426 | if (fn->alignstack_value != 0) { |
| 433 | addLLVMFnAttr(fn_table_entry->llvm_value, "noinline"); | 427 | addLLVMFnAttr(llvm_fn, "noinline"); |
| 434 | } | 428 | } |
| 435 | break; | 429 | break; |
| 436 | } | 430 | } |
| 437 | | 431 | |
| 438 | if (cc == CallingConventionNaked) { | 432 | if (cc == CallingConventionNaked) { |
| 439 | addLLVMFnAttr(fn_table_entry->llvm_value, "naked"); | 433 | addLLVMFnAttr(llvm_fn, "naked"); |
| 440 | } else { | 434 | } else { |
| 441 | LLVMSetFunctionCallConv(fn_table_entry->llvm_value, get_llvm_cc(g, fn_type->data.fn.fn_type_id.cc)); | 435 | LLVMSetFunctionCallConv(llvm_fn, get_llvm_cc(g, fn_type->data.fn.fn_type_id.cc)); |
| 442 | } | 436 | } |
| 443 | if (cc == CallingConventionAsync) { | 437 | if (cc == CallingConventionAsync) { |
| 444 | addLLVMFnAttr(fn_table_entry->llvm_value, "optnone"); | 438 | addLLVMFnAttr(llvm_fn, "optnone"); |
| 445 | addLLVMFnAttr(fn_table_entry->llvm_value, "noinline"); | 439 | addLLVMFnAttr(llvm_fn, "noinline"); |
| 446 | } | 440 | } |
| 447 | | 441 | |
| 448 | bool want_cold = fn_table_entry->is_cold || cc == CallingConventionCold; | 442 | bool want_cold = fn->is_cold || cc == CallingConventionCold; |
| 449 | if (want_cold) { | 443 | if (want_cold) { |
| 450 | ZigLLVMAddFunctionAttrCold(fn_table_entry->llvm_value); | 444 | ZigLLVMAddFunctionAttrCold(llvm_fn); |
| 451 | } | 445 | } |
| 452 | | 446 | |
| 453 | | 447 | |
| 454 | LLVMSetLinkage(fn_table_entry->llvm_value, to_llvm_linkage(linkage)); | 448 | LLVMSetLinkage(llvm_fn, to_llvm_linkage(linkage)); |
| 455 | | 449 | |
| 456 | if (linkage == GlobalLinkageIdInternal) { | 450 | if (linkage == GlobalLinkageIdInternal) { |
| 457 | LLVMSetUnnamedAddr(fn_table_entry->llvm_value, true); | 451 | LLVMSetUnnamedAddr(llvm_fn, true); |
| 458 | } | 452 | } |
| 459 | | 453 | |
| 460 | ZigType *return_type = fn_type->data.fn.fn_type_id.return_type; | 454 | ZigType *return_type = fn_type->data.fn.fn_type_id.return_type; |
| 461 | if (return_type->id == ZigTypeIdUnreachable) { | 455 | if (return_type->id == ZigTypeIdUnreachable) { |
| 462 | addLLVMFnAttr(fn_table_entry->llvm_value, "noreturn"); | 456 | addLLVMFnAttr(llvm_fn, "noreturn"); |
| 463 | } | 457 | } |
| 464 | | 458 | |
| 465 | if (fn_table_entry->body_node != nullptr) { | 459 | if (fn->body_node != nullptr) { |
| 466 | maybe_export_dll(g, fn_table_entry->llvm_value, linkage); | 460 | maybe_export_dll(g, llvm_fn, linkage); |
| 467 | | 461 | |
| 468 | bool want_fn_safety = g->build_mode != BuildModeFastRelease && | 462 | bool want_fn_safety = g->build_mode != BuildModeFastRelease && |
| 469 | g->build_mode != BuildModeSmallRelease && | 463 | g->build_mode != BuildModeSmallRelease && |
| 470 | !fn_table_entry->def_scope->safety_off; | 464 | !fn->def_scope->safety_off; |
| 471 | if (want_fn_safety) { | 465 | if (want_fn_safety) { |
| 472 | if (g->libc_link_lib != nullptr) { | 466 | if (g->libc_link_lib != nullptr) { |
| 473 | addLLVMFnAttr(fn_table_entry->llvm_value, "sspstrong"); | 467 | addLLVMFnAttr(llvm_fn, "sspstrong"); |
| 474 | addLLVMFnAttrStr(fn_table_entry->llvm_value, "stack-protector-buffer-size", "4"); | 468 | addLLVMFnAttrStr(llvm_fn, "stack-protector-buffer-size", "4"); |
| 475 | } | 469 | } |
| 476 | } | 470 | } |
| 477 | if (g->have_stack_probing && !fn_table_entry->def_scope->safety_off) { | 471 | if (g->have_stack_probing && !fn->def_scope->safety_off) { |
| 478 | addLLVMFnAttrStr(fn_table_entry->llvm_value, "probe-stack", "__zig_probe_stack"); | 472 | addLLVMFnAttrStr(llvm_fn, "probe-stack", "__zig_probe_stack"); |
| 479 | } | 473 | } |
| 480 | } else { | 474 | } else { |
| 481 | maybe_import_dll(g, fn_table_entry->llvm_value, linkage); | 475 | maybe_import_dll(g, llvm_fn, linkage); |
| 482 | } | 476 | } |
| 483 | | 477 | |
| 484 | if (fn_table_entry->alignstack_value != 0) { | 478 | if (fn->alignstack_value != 0) { |
| 485 | addLLVMFnAttrInt(fn_table_entry->llvm_value, "alignstack", fn_table_entry->alignstack_value); | 479 | addLLVMFnAttrInt(llvm_fn, "alignstack", fn->alignstack_value); |
| 486 | } | 480 | } |
| 487 | | 481 | |
| 488 | addLLVMFnAttr(fn_table_entry->llvm_value, "nounwind"); | 482 | addLLVMFnAttr(llvm_fn, "nounwind"); |
| 489 | add_uwtable_attr(g, fn_table_entry->llvm_value); | 483 | add_uwtable_attr(g, llvm_fn); |
| 490 | addLLVMFnAttr(fn_table_entry->llvm_value, "nobuiltin"); | 484 | addLLVMFnAttr(llvm_fn, "nobuiltin"); |
| 491 | if (g->build_mode == BuildModeDebug && fn_table_entry->fn_inline != FnInlineAlways) { | 485 | if (g->build_mode == BuildModeDebug && fn->fn_inline != FnInlineAlways) { |
| 492 | ZigLLVMAddFunctionAttr(fn_table_entry->llvm_value, "no-frame-pointer-elim", "true"); | 486 | ZigLLVMAddFunctionAttr(llvm_fn, "no-frame-pointer-elim", "true"); |
| 493 | ZigLLVMAddFunctionAttr(fn_table_entry->llvm_value, "no-frame-pointer-elim-non-leaf", nullptr); | 487 | ZigLLVMAddFunctionAttr(llvm_fn, "no-frame-pointer-elim-non-leaf", nullptr); |
| 494 | } | 488 | } |
| 495 | if (fn_table_entry->section_name) { | 489 | if (fn->section_name) { |
| 496 | LLVMSetSection(fn_table_entry->llvm_value, buf_ptr(fn_table_entry->section_name)); | 490 | LLVMSetSection(llvm_fn, buf_ptr(fn->section_name)); |
| 497 | } | 491 | } |
| 498 | if (fn_table_entry->align_bytes > 0) { | 492 | if (fn->align_bytes > 0) { |
| 499 | LLVMSetAlignment(fn_table_entry->llvm_value, (unsigned)fn_table_entry->align_bytes); | 493 | LLVMSetAlignment(llvm_fn, (unsigned)fn->align_bytes); |
| 500 | } else { | 494 | } else { |
| 501 | // We'd like to set the best alignment for the function here, but on Darwin LLVM gives | 495 | // We'd like to set the best alignment for the function here, but on Darwin LLVM gives |
| 502 | // "Cannot getTypeInfo() on a type that is unsized!" assertion failure when calling | 496 | // "Cannot getTypeInfo() on a type that is unsized!" assertion failure when calling |
| ... | @@ -508,36 +502,46 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { | ... | @@ -508,36 +502,46 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { |
| 508 | if (!type_has_bits(return_type)) { | 502 | if (!type_has_bits(return_type)) { |
| 509 | // nothing to do | 503 | // nothing to do |
| 510 | } else if (type_is_nonnull_ptr(return_type)) { | 504 | } else if (type_is_nonnull_ptr(return_type)) { |
| 511 | addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull"); | 505 | addLLVMAttr(llvm_fn, 0, "nonnull"); |
| 512 | } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) { | 506 | } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) { |
| 513 | // Sret pointers must not be address 0 | 507 | // Sret pointers must not be address 0 |
| 514 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull"); | 508 | addLLVMArgAttr(llvm_fn, 0, "nonnull"); |
| 515 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret"); | 509 | addLLVMArgAttr(llvm_fn, 0, "sret"); |
| 516 | if (cc_want_sret_attr(cc)) { | 510 | if (cc_want_sret_attr(cc)) { |
| 517 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "noalias"); | 511 | addLLVMArgAttr(llvm_fn, 0, "noalias"); |
| 518 | } | 512 | } |
| 519 | init_gen_i = 1; | 513 | init_gen_i = 1; |
| 520 | } | 514 | } |
| 521 | | 515 | |
| 522 | if (is_async) { | 516 | if (is_async) { |
| 523 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull"); | 517 | addLLVMArgAttr(llvm_fn, 0, "nonnull"); |
| 524 | } else { | 518 | } else { |
| 525 | // set parameter attributes | 519 | // set parameter attributes |
| 526 | FnWalk fn_walk = {}; | 520 | FnWalk fn_walk = {}; |
| 527 | fn_walk.id = FnWalkIdAttrs; | 521 | fn_walk.id = FnWalkIdAttrs; |
| 528 | fn_walk.data.attrs.fn = fn_table_entry; | 522 | fn_walk.data.attrs.fn = fn; |
| | 523 | fn_walk.data.attrs.llvm_fn = llvm_fn; |
| 529 | fn_walk.data.attrs.gen_i = init_gen_i; | 524 | fn_walk.data.attrs.gen_i = init_gen_i; |
| 530 | walk_function_params(g, fn_type, &fn_walk); | 525 | walk_function_params(g, fn_type, &fn_walk); |
| 531 | | 526 | |
| 532 | uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry); | 527 | uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn); |
| 533 | if (err_ret_trace_arg_index != UINT32_MAX) { | 528 | if (err_ret_trace_arg_index != UINT32_MAX) { |
| 534 | // Error return trace memory is in the stack, which is impossible to be at address 0 | 529 | // Error return trace memory is in the stack, which is impossible to be at address 0 |
| 535 | // on any architecture. | 530 | // on any architecture. |
| 536 | addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull"); | 531 | addLLVMArgAttr(llvm_fn, (unsigned)err_ret_trace_arg_index, "nonnull"); |
| 537 | } | 532 | } |
| 538 | } | 533 | } |
| 539 | | 534 | |
| 540 | return fn_table_entry->llvm_value; | 535 | return llvm_fn; |
| | 536 | } |
| | 537 | |
| | 538 | static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn) { |
| | 539 | if (fn->llvm_value) |
| | 540 | return fn->llvm_value; |
| | 541 | |
| | 542 | fn->llvm_value = make_fn_llvm_value(g, fn); |
| | 543 | fn->llvm_name = strdup(LLVMGetValueName(fn->llvm_value)); |
| | 544 | return fn->llvm_value; |
| 541 | } | 545 | } |
| 542 | | 546 | |
| 543 | static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { | 547 | static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { |
| ... | @@ -1665,7 +1669,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ | ... | @@ -1665,7 +1669,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ |
| 1665 | param_info = &fn_type->data.fn.fn_type_id.param_info[src_i]; | 1669 | param_info = &fn_type->data.fn.fn_type_id.param_info[src_i]; |
| 1666 | ty = param_info->type; | 1670 | ty = param_info->type; |
| 1667 | source_node = fn_walk->data.attrs.fn->proto_node; | 1671 | source_node = fn_walk->data.attrs.fn->proto_node; |
| 1668 | llvm_fn = fn_walk->data.attrs.fn->llvm_value; | 1672 | llvm_fn = fn_walk->data.attrs.llvm_fn; |
| 1669 | break; | 1673 | break; |
| 1670 | case FnWalkIdCall: { | 1674 | case FnWalkIdCall: { |
| 1671 | if (src_i >= fn_walk->data.call.inst->arg_count) | 1675 | if (src_i >= fn_walk->data.call.inst->arg_count) |
| ... | @@ -1916,7 +1920,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) { | ... | @@ -1916,7 +1920,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) { |
| 1916 | | 1920 | |
| 1917 | switch (fn_walk->id) { | 1921 | switch (fn_walk->id) { |
| 1918 | case FnWalkIdAttrs: { | 1922 | case FnWalkIdAttrs: { |
| 1919 | LLVMValueRef llvm_fn = fn_walk->data.attrs.fn->llvm_value; | 1923 | LLVMValueRef llvm_fn = fn_walk->data.attrs.llvm_fn; |
| 1920 | bool is_byval = gen_info->is_byval; | 1924 | bool is_byval = gen_info->is_byval; |
| 1921 | FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[param_i]; | 1925 | FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[param_i]; |
| 1922 | | 1926 | |
| ... | @@ -1989,10 +1993,9 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns | ... | @@ -1989,10 +1993,9 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns |
| 1989 | if (fn_is_async(g->cur_fn)) { | 1993 | if (fn_is_async(g->cur_fn)) { |
| 1990 | if (ir_want_runtime_safety(g, &return_instruction->base)) { | 1994 | if (ir_want_runtime_safety(g, &return_instruction->base)) { |
| 1991 | LLVMValueRef locals_ptr = g->cur_ret_ptr; | 1995 | LLVMValueRef locals_ptr = g->cur_ret_ptr; |
| 1992 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, locals_ptr, coro_resume_index_index, ""); | 1996 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, locals_ptr, coro_fn_ptr_index, ""); |
| 1993 | LLVMValueRef new_resume_index = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, | 1997 | LLVMValueRef new_resume_fn = g->cur_fn->resume_blocks.last()->split_llvm_fn; |
| 1994 | g->cur_fn->resume_blocks.length + 2, false); | 1998 | LLVMBuildStore(g->builder, new_resume_fn, resume_index_ptr); |
| 1995 | LLVMBuildStore(g->builder, new_resume_index, resume_index_ptr); | | |
| 1996 | } | 1999 | } |
| 1997 | | 2000 | |
| 1998 | LLVMBuildRetVoid(g->builder); | 2001 | LLVMBuildRetVoid(g->builder); |
| ... | @@ -2954,14 +2957,17 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -2954,14 +2957,17 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI |
| 2954 | return LLVMBuildICmp(g->builder, LLVMIntEQ, value, zero, ""); | 2957 | return LLVMBuildICmp(g->builder, LLVMIntEQ, value, zero, ""); |
| 2955 | } | 2958 | } |
| 2956 | | 2959 | |
| 2957 | static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, IrInstructionDeclVarGen *instruction) { | 2960 | static void render_decl_var(CodeGen *g, ZigVar *var) { |
| 2958 | ZigVar *var = instruction->var; | | |
| 2959 | | | |
| 2960 | if (!type_has_bits(var->var_type)) | 2961 | if (!type_has_bits(var->var_type)) |
| 2961 | return nullptr; | 2962 | return; |
| 2962 | | 2963 | |
| 2963 | var->value_ref = ir_llvm_value(g, instruction->var_ptr); | 2964 | var->value_ref = ir_llvm_value(g, var->ptr_instruction); |
| 2964 | gen_var_debug_decl(g, var); | 2965 | gen_var_debug_decl(g, var); |
| | 2966 | } |
| | 2967 | |
| | 2968 | static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, IrInstructionDeclVarGen *instruction) { |
| | 2969 | instruction->var->ptr_instruction = instruction->var_ptr; |
| | 2970 | render_decl_var(g, instruction->var); |
| 2965 | return nullptr; | 2971 | return nullptr; |
| 2966 | } | 2972 | } |
| 2967 | | 2973 | |
| ... | @@ -3369,12 +3375,6 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -3369,12 +3375,6 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3369 | if (instruction->is_async || callee_is_async) { | 3375 | if (instruction->is_async || callee_is_async) { |
| 3370 | assert(frame_result_loc != nullptr); | 3376 | assert(frame_result_loc != nullptr); |
| 3371 | assert(instruction->fn_entry != nullptr); | 3377 | assert(instruction->fn_entry != nullptr); |
| 3372 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_resume_index_index, ""); | | |
| 3373 | LLVMBuildStore(g->builder, zero, resume_index_ptr); | | |
| 3374 | LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_fn_ptr_index, ""); | | |
| 3375 | LLVMValueRef bitcasted_fn_val = LLVMBuildBitCast(g->builder, fn_val, | | |
| 3376 | LLVMGetElementType(LLVMTypeOf(fn_ptr_ptr)), ""); | | |
| 3377 | LLVMBuildStore(g->builder, bitcasted_fn_val, fn_ptr_ptr); | | |
| 3378 | | 3378 | |
| 3379 | if (prefix_arg_err_ret_stack) { | 3379 | if (prefix_arg_err_ret_stack) { |
| 3380 | zig_panic("TODO"); | 3380 | zig_panic("TODO"); |
| ... | @@ -3431,10 +3431,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -3431,10 +3431,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3431 | ZigLLVMBuildCall(g->builder, fn_val, &frame_result_loc, 1, llvm_cc, fn_inline, ""); | 3431 | ZigLLVMBuildCall(g->builder, fn_val, &frame_result_loc, 1, llvm_cc, fn_inline, ""); |
| 3432 | return nullptr; | 3432 | return nullptr; |
| 3433 | } else if (callee_is_async) { | 3433 | } else if (callee_is_async) { |
| 3434 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_resume_index_index, ""); | 3434 | LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_fn_ptr_index, ""); |
| 3435 | LLVMValueRef new_resume_index = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, | 3435 | LLVMValueRef new_fn_ptr = instruction->resume_block->split_llvm_fn; |
| 3436 | instruction->resume_block->resume_index, false); | 3436 | LLVMBuildStore(g->builder, new_fn_ptr, fn_ptr_ptr); |
| 3437 | LLVMBuildStore(g->builder, new_resume_index, resume_index_ptr); | | |
| 3438 | | 3437 | |
| 3439 | LLVMValueRef call_inst = ZigLLVMBuildCall(g->builder, fn_val, &frame_result_loc, 1, llvm_cc, fn_inline, ""); | 3438 | LLVMValueRef call_inst = ZigLLVMBuildCall(g->builder, fn_val, &frame_result_loc, 1, llvm_cc, fn_inline, ""); |
| 3440 | ZigLLVMSetTailCall(call_inst); | 3439 | ZigLLVMSetTailCall(call_inst); |
| ... | @@ -4888,10 +4887,9 @@ static LLVMValueRef ir_render_suspend_begin(CodeGen *g, IrExecutable *executable | ... | @@ -4888,10 +4887,9 @@ static LLVMValueRef ir_render_suspend_begin(CodeGen *g, IrExecutable *executable |
| 4888 | IrInstructionSuspendBegin *instruction) | 4887 | IrInstructionSuspendBegin *instruction) |
| 4889 | { | 4888 | { |
| 4890 | LLVMValueRef locals_ptr = g->cur_ret_ptr; | 4889 | LLVMValueRef locals_ptr = g->cur_ret_ptr; |
| 4891 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, locals_ptr, coro_resume_index_index, ""); | 4890 | LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, locals_ptr, coro_fn_ptr_index, ""); |
| 4892 | LLVMValueRef new_resume_index = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, | 4891 | LLVMValueRef new_fn_ptr = instruction->resume_block->split_llvm_fn; |
| 4893 | instruction->resume_block->resume_index, false); | 4892 | LLVMBuildStore(g->builder, new_fn_ptr, fn_ptr_ptr); |
| 4894 | LLVMBuildStore(g->builder, new_resume_index, resume_index_ptr); | | |
| 4895 | return nullptr; | 4893 | return nullptr; |
| 4896 | } | 4894 | } |
| 4897 | | 4895 | |
| ... | @@ -4902,17 +4900,17 @@ static LLVMValueRef ir_render_suspend_br(CodeGen *g, IrExecutable *executable, | ... | @@ -4902,17 +4900,17 @@ static LLVMValueRef ir_render_suspend_br(CodeGen *g, IrExecutable *executable, |
| 4902 | return nullptr; | 4900 | return nullptr; |
| 4903 | } | 4901 | } |
| 4904 | | 4902 | |
| 4905 | static LLVMTypeRef async_fn_llvm_type(CodeGen *g) { | 4903 | static LLVMTypeRef anyframe_fn_type(CodeGen *g) { |
| 4906 | if (g->async_fn_llvm_type != nullptr) | 4904 | if (g->anyframe_fn_type != nullptr) |
| 4907 | return g->async_fn_llvm_type; | 4905 | return g->anyframe_fn_type; |
| 4908 | | 4906 | |
| 4909 | ZigType *anyframe_type = get_any_frame_type(g, nullptr); | 4907 | ZigType *anyframe_type = get_any_frame_type(g, nullptr); |
| 4910 | LLVMTypeRef param_type = get_llvm_type(g, anyframe_type); | 4908 | LLVMTypeRef param_type = get_llvm_type(g, anyframe_type); |
| 4911 | LLVMTypeRef return_type = LLVMVoidType(); | 4909 | LLVMTypeRef return_type = LLVMVoidType(); |
| 4912 | LLVMTypeRef fn_type = LLVMFunctionType(return_type, &param_type, 1, false); | 4910 | LLVMTypeRef fn_type = LLVMFunctionType(return_type, &param_type, 1, false); |
| 4913 | g->async_fn_llvm_type = LLVMPointerType(fn_type, 0); | 4911 | g->anyframe_fn_type = LLVMPointerType(fn_type, 0); |
| 4914 | | 4912 | |
| 4915 | return g->async_fn_llvm_type; | 4913 | return g->anyframe_fn_type; |
| 4916 | } | 4914 | } |
| 4917 | | 4915 | |
| 4918 | static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable, | 4916 | static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable, |
| ... | @@ -4923,7 +4921,7 @@ static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable, | ... | @@ -4923,7 +4921,7 @@ static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable, |
| 4923 | assert(frame_type->id == ZigTypeIdAnyFrame); | 4921 | assert(frame_type->id == ZigTypeIdAnyFrame); |
| 4924 | LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, frame, coro_fn_ptr_index, ""); | 4922 | LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, frame, coro_fn_ptr_index, ""); |
| 4925 | LLVMValueRef uncasted_fn_val = LLVMBuildLoad(g->builder, fn_ptr_ptr, ""); | 4923 | LLVMValueRef uncasted_fn_val = LLVMBuildLoad(g->builder, fn_ptr_ptr, ""); |
| 4926 | LLVMValueRef fn_val = LLVMBuildIntToPtr(g->builder, uncasted_fn_val, async_fn_llvm_type(g), ""); | 4924 | LLVMValueRef fn_val = LLVMBuildIntToPtr(g->builder, uncasted_fn_val, anyframe_fn_type(g), ""); |
| 4927 | ZigLLVMBuildCall(g->builder, fn_val, &frame, 1, LLVMFastCallConv, ZigLLVM_FnInlineAuto, ""); | 4925 | ZigLLVMBuildCall(g->builder, fn_val, &frame, 1, LLVMFastCallConv, ZigLLVM_FnInlineAuto, ""); |
| 4928 | return nullptr; | 4926 | return nullptr; |
| 4929 | } | 4927 | } |
| ... | @@ -5022,7 +5020,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -5022,7 +5020,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5022 | case IrInstructionIdCallSrc: | 5020 | case IrInstructionIdCallSrc: |
| 5023 | case IrInstructionIdAllocaSrc: | 5021 | case IrInstructionIdAllocaSrc: |
| 5024 | case IrInstructionIdEndExpr: | 5022 | case IrInstructionIdEndExpr: |
| 5025 | case IrInstructionIdAllocaGen: | | |
| 5026 | case IrInstructionIdImplicitCast: | 5023 | case IrInstructionIdImplicitCast: |
| 5027 | case IrInstructionIdResolveResult: | 5024 | case IrInstructionIdResolveResult: |
| 5028 | case IrInstructionIdResetResult: | 5025 | case IrInstructionIdResetResult: |
| ... | @@ -5035,6 +5032,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -5035,6 +5032,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5035 | case IrInstructionIdUnionInitNamedField: | 5032 | case IrInstructionIdUnionInitNamedField: |
| 5036 | case IrInstructionIdFrameType: | 5033 | case IrInstructionIdFrameType: |
| 5037 | case IrInstructionIdFrameSizeSrc: | 5034 | case IrInstructionIdFrameSizeSrc: |
| | 5035 | case IrInstructionIdAllocaGen: |
| 5038 | zig_unreachable(); | 5036 | zig_unreachable(); |
| 5039 | | 5037 | |
| 5040 | case IrInstructionIdDeclVarGen: | 5038 | case IrInstructionIdDeclVarGen: |
| ... | @@ -5195,6 +5193,92 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -5195,6 +5193,92 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 5195 | zig_unreachable(); | 5193 | zig_unreachable(); |
| 5196 | } | 5194 | } |
| 5197 | | 5195 | |
| | 5196 | static void render_async_spills(CodeGen *g) { |
| | 5197 | ZigType *fn_type = g->cur_fn->type_entry; |
| | 5198 | ZigType *import = get_scope_import(&g->cur_fn->fndef_scope->base); |
| | 5199 | size_t async_var_index = coro_arg_start + (type_has_bits(fn_type->data.fn.fn_type_id.return_type) ? 2 : 0); |
| | 5200 | for (size_t var_i = 0; var_i < g->cur_fn->variable_list.length; var_i += 1) { |
| | 5201 | ZigVar *var = g->cur_fn->variable_list.at(var_i); |
| | 5202 | |
| | 5203 | if (!type_has_bits(var->var_type)) { |
| | 5204 | continue; |
| | 5205 | } |
| | 5206 | if (ir_get_var_is_comptime(var)) |
| | 5207 | continue; |
| | 5208 | switch (type_requires_comptime(g, var->var_type)) { |
| | 5209 | case ReqCompTimeInvalid: |
| | 5210 | zig_unreachable(); |
| | 5211 | case ReqCompTimeYes: |
| | 5212 | continue; |
| | 5213 | case ReqCompTimeNo: |
| | 5214 | break; |
| | 5215 | } |
| | 5216 | if (var->src_arg_index == SIZE_MAX) { |
| | 5217 | continue; |
| | 5218 | } |
| | 5219 | |
| | 5220 | var->value_ref = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, async_var_index, |
| | 5221 | buf_ptr(&var->name)); |
| | 5222 | async_var_index += 1; |
| | 5223 | if (var->decl_node) { |
| | 5224 | var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), |
| | 5225 | buf_ptr(&var->name), import->data.structure.root_struct->di_file, |
| | 5226 | (unsigned)(var->decl_node->line + 1), |
| | 5227 | get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0); |
| | 5228 | gen_var_debug_decl(g, var); |
| | 5229 | } |
| | 5230 | } |
| | 5231 | for (size_t alloca_i = 0; alloca_i < g->cur_fn->alloca_gen_list.length; alloca_i += 1) { |
| | 5232 | IrInstructionAllocaGen *instruction = g->cur_fn->alloca_gen_list.at(alloca_i); |
| | 5233 | ZigType *ptr_type = instruction->base.value.type; |
| | 5234 | assert(ptr_type->id == ZigTypeIdPointer); |
| | 5235 | ZigType *child_type = ptr_type->data.pointer.child_type; |
| | 5236 | if (!type_has_bits(child_type)) |
| | 5237 | continue; |
| | 5238 | if (instruction->base.ref_count == 0) |
| | 5239 | continue; |
| | 5240 | if (instruction->base.value.special != ConstValSpecialRuntime) { |
| | 5241 | if (const_ptr_pointee(nullptr, g, &instruction->base.value, nullptr)->special != |
| | 5242 | ConstValSpecialRuntime) |
| | 5243 | { |
| | 5244 | continue; |
| | 5245 | } |
| | 5246 | } |
| | 5247 | instruction->base.llvm_value = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, async_var_index, |
| | 5248 | instruction->name_hint); |
| | 5249 | async_var_index += 1; |
| | 5250 | } |
| | 5251 | } |
| | 5252 | |
| | 5253 | static void render_async_var_decls(CodeGen *g, Scope *scope) { |
| | 5254 | render_async_spills(g); |
| | 5255 | for (;;) { |
| | 5256 | switch (scope->id) { |
| | 5257 | case ScopeIdCImport: |
| | 5258 | zig_unreachable(); |
| | 5259 | case ScopeIdFnDef: |
| | 5260 | return; |
| | 5261 | case ScopeIdVarDecl: { |
| | 5262 | ZigVar *var = reinterpret_cast<ScopeVarDecl *>(scope)->var; |
| | 5263 | if (var->ptr_instruction != nullptr) { |
| | 5264 | render_decl_var(g, var); |
| | 5265 | } |
| | 5266 | // fallthrough |
| | 5267 | } |
| | 5268 | case ScopeIdDecls: |
| | 5269 | case ScopeIdBlock: |
| | 5270 | case ScopeIdDefer: |
| | 5271 | case ScopeIdDeferExpr: |
| | 5272 | case ScopeIdLoop: |
| | 5273 | case ScopeIdSuspend: |
| | 5274 | case ScopeIdCompTime: |
| | 5275 | case ScopeIdRuntime: |
| | 5276 | scope = scope->parent; |
| | 5277 | continue; |
| | 5278 | } |
| | 5279 | } |
| | 5280 | } |
| | 5281 | |
| 5198 | static void ir_render(CodeGen *g, ZigFn *fn_entry) { | 5282 | static void ir_render(CodeGen *g, ZigFn *fn_entry) { |
| 5199 | assert(fn_entry); | 5283 | assert(fn_entry); |
| 5200 | | 5284 | |
| ... | @@ -5204,6 +5288,11 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) { | ... | @@ -5204,6 +5288,11 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) { |
| 5204 | IrBasicBlock *current_block = executable->basic_block_list.at(block_i); | 5288 | IrBasicBlock *current_block = executable->basic_block_list.at(block_i); |
| 5205 | assert(current_block->llvm_block); | 5289 | assert(current_block->llvm_block); |
| 5206 | LLVMPositionBuilderAtEnd(g->builder, current_block->llvm_block); | 5290 | LLVMPositionBuilderAtEnd(g->builder, current_block->llvm_block); |
| | 5291 | if (current_block->split_llvm_fn != nullptr) { |
| | 5292 | g->cur_fn_val = current_block->split_llvm_fn; |
| | 5293 | g->cur_ret_ptr = LLVMGetParam(g->cur_fn_val, 0); |
| | 5294 | render_async_var_decls(g, current_block->instruction_list.at(0)->scope); |
| | 5295 | } |
| 5207 | for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) { | 5296 | for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) { |
| 5208 | IrInstruction *instruction = current_block->instruction_list.at(instr_i); | 5297 | IrInstruction *instruction = current_block->instruction_list.at(instr_i); |
| 5209 | if (instruction->ref_count == 0 && !ir_has_side_effects(instruction)) | 5298 | if (instruction->ref_count == 0 && !ir_has_side_effects(instruction)) |
| ... | @@ -6064,19 +6153,17 @@ static void build_all_basic_blocks(CodeGen *g, ZigFn *fn) { | ... | @@ -6064,19 +6153,17 @@ static void build_all_basic_blocks(CodeGen *g, ZigFn *fn) { |
| 6064 | IrExecutable *executable = &fn->analyzed_executable; | 6153 | IrExecutable *executable = &fn->analyzed_executable; |
| 6065 | assert(executable->basic_block_list.length > 0); | 6154 | assert(executable->basic_block_list.length > 0); |
| 6066 | LLVMValueRef fn_val = fn_llvm_value(g, fn); | 6155 | LLVMValueRef fn_val = fn_llvm_value(g, fn); |
| 6067 | LLVMBasicBlockRef first_bb = nullptr; | | |
| 6068 | if (fn_is_async(fn)) { | | |
| 6069 | first_bb = LLVMAppendBasicBlock(fn_val, "AsyncSwitch"); | | |
| 6070 | fn->preamble_llvm_block = first_bb; | | |
| 6071 | } | | |
| 6072 | for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) { | 6156 | for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) { |
| 6073 | IrBasicBlock *bb = executable->basic_block_list.at(block_i); | 6157 | IrBasicBlock *bb = executable->basic_block_list.at(block_i); |
| | 6158 | if (bb->split_llvm_fn != nullptr) { |
| | 6159 | assert(bb->split_llvm_fn == reinterpret_cast<LLVMValueRef>(0x1)); |
| | 6160 | fn_val = make_fn_llvm_value(g, fn); |
| | 6161 | bb->split_llvm_fn = fn_val; |
| | 6162 | } |
| 6074 | bb->llvm_block = LLVMAppendBasicBlock(fn_val, bb->name_hint); | 6163 | bb->llvm_block = LLVMAppendBasicBlock(fn_val, bb->name_hint); |
| 6075 | } | 6164 | } |
| 6076 | if (first_bb == nullptr) { | 6165 | IrBasicBlock *entry_bb = executable->basic_block_list.at(0); |
| 6077 | first_bb = executable->basic_block_list.at(0)->llvm_block; | 6166 | LLVMPositionBuilderAtEnd(g->builder, entry_bb->llvm_block); |
| 6078 | } | | |
| 6079 | LLVMPositionBuilderAtEnd(g->builder, first_bb); | | |
| 6080 | } | 6167 | } |
| 6081 | | 6168 | |
| 6082 | static void gen_global_var(CodeGen *g, ZigVar *var, LLVMValueRef init_val, | 6169 | static void gen_global_var(CodeGen *g, ZigVar *var, LLVMValueRef init_val, |
| ... | @@ -6254,7 +6341,6 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6254,7 +6341,6 @@ static void do_code_gen(CodeGen *g) { |
| 6254 | clear_debug_source_node(g); | 6341 | clear_debug_source_node(g); |
| 6255 | | 6342 | |
| 6256 | bool is_async = fn_is_async(fn_table_entry); | 6343 | bool is_async = fn_is_async(fn_table_entry); |
| 6257 | size_t async_var_index = coro_arg_start + (type_has_bits(fn_type_id->return_type) ? 2 : 0); | | |
| 6258 | | 6344 | |
| 6259 | if (want_sret || is_async) { | 6345 | if (want_sret || is_async) { |
| 6260 | g->cur_ret_ptr = LLVMGetParam(fn, 0); | 6346 | g->cur_ret_ptr = LLVMGetParam(fn, 0); |
| ... | @@ -6287,7 +6373,9 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6287,7 +6373,9 @@ static void do_code_gen(CodeGen *g) { |
| 6287 | g->cur_err_ret_trace_val_stack = nullptr; | 6373 | g->cur_err_ret_trace_val_stack = nullptr; |
| 6288 | } | 6374 | } |
| 6289 | | 6375 | |
| 6290 | if (!is_async) { | 6376 | if (is_async) { |
| | 6377 | render_async_spills(g); |
| | 6378 | } else { |
| 6291 | // allocate temporary stack data | 6379 | // allocate temporary stack data |
| 6292 | for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_gen_list.length; alloca_i += 1) { | 6380 | for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_gen_list.length; alloca_i += 1) { |
| 6293 | IrInstructionAllocaGen *instruction = fn_table_entry->alloca_gen_list.at(alloca_i); | 6381 | IrInstructionAllocaGen *instruction = fn_table_entry->alloca_gen_list.at(alloca_i); |
| ... | @@ -6345,18 +6433,7 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6345,18 +6433,7 @@ static void do_code_gen(CodeGen *g) { |
| 6345 | } else if (is_c_abi) { | 6433 | } else if (is_c_abi) { |
| 6346 | fn_walk_var.data.vars.var = var; | 6434 | fn_walk_var.data.vars.var = var; |
| 6347 | iter_function_params_c_abi(g, fn_table_entry->type_entry, &fn_walk_var, var->src_arg_index); | 6435 | iter_function_params_c_abi(g, fn_table_entry->type_entry, &fn_walk_var, var->src_arg_index); |
| 6348 | } else if (is_async) { | 6436 | } else if (!is_async) { |
| 6349 | var->value_ref = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, async_var_index, | | |
| 6350 | buf_ptr(&var->name)); | | |
| 6351 | async_var_index += 1; | | |
| 6352 | if (var->decl_node) { | | |
| 6353 | var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), | | |
| 6354 | buf_ptr(&var->name), import->data.structure.root_struct->di_file, | | |
| 6355 | (unsigned)(var->decl_node->line + 1), | | |
| 6356 | get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0); | | |
| 6357 | gen_var_debug_decl(g, var); | | |
| 6358 | } | | |
| 6359 | } else { | | |
| 6360 | ZigType *gen_type; | 6437 | ZigType *gen_type; |
| 6361 | FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index]; | 6438 | FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index]; |
| 6362 | assert(gen_info->gen_index != SIZE_MAX); | 6439 | assert(gen_info->gen_index != SIZE_MAX); |
| ... | @@ -6382,29 +6459,6 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6382,29 +6459,6 @@ static void do_code_gen(CodeGen *g) { |
| 6382 | } | 6459 | } |
| 6383 | } | 6460 | } |
| 6384 | | 6461 | |
| 6385 | if (is_async) { | | |
| 6386 | for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_gen_list.length; alloca_i += 1) { | | |
| 6387 | IrInstructionAllocaGen *instruction = fn_table_entry->alloca_gen_list.at(alloca_i); | | |
| 6388 | ZigType *ptr_type = instruction->base.value.type; | | |
| 6389 | assert(ptr_type->id == ZigTypeIdPointer); | | |
| 6390 | ZigType *child_type = ptr_type->data.pointer.child_type; | | |
| 6391 | if (!type_has_bits(child_type)) | | |
| 6392 | continue; | | |
| 6393 | if (instruction->base.ref_count == 0) | | |
| 6394 | continue; | | |
| 6395 | if (instruction->base.value.special != ConstValSpecialRuntime) { | | |
| 6396 | if (const_ptr_pointee(nullptr, g, &instruction->base.value, nullptr)->special != | | |
| 6397 | ConstValSpecialRuntime) | | |
| 6398 | { | | |
| 6399 | continue; | | |
| 6400 | } | | |
| 6401 | } | | |
| 6402 | instruction->base.llvm_value = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, async_var_index, | | |
| 6403 | instruction->name_hint); | | |
| 6404 | async_var_index += 1; | | |
| 6405 | } | | |
| 6406 | } | | |
| 6407 | | | |
| 6408 | // finishing error return trace setup. we have to do this after all the allocas. | 6462 | // finishing error return trace setup. we have to do this after all the allocas. |
| 6409 | if (have_err_ret_trace_stack) { | 6463 | if (have_err_ret_trace_stack) { |
| 6410 | ZigType *usize = g->builtin_types.entry_usize; | 6464 | ZigType *usize = g->builtin_types.entry_usize; |
| ... | @@ -6435,31 +6489,16 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6435,31 +6489,16 @@ static void do_code_gen(CodeGen *g) { |
| 6435 | LLVMValueRef size_val = LLVMConstInt(usize_type_ref, fn_table_entry->frame_type->abi_size, false); | 6489 | LLVMValueRef size_val = LLVMConstInt(usize_type_ref, fn_table_entry->frame_type->abi_size, false); |
| 6436 | ZigLLVMFunctionSetPrefixData(fn_table_entry->llvm_value, size_val); | 6490 | ZigLLVMFunctionSetPrefixData(fn_table_entry->llvm_value, size_val); |
| 6437 | | 6491 | |
| 6438 | if (!g->strip_debug_symbols) { | 6492 | if (ir_want_runtime_safety_scope(g, fn_table_entry->child_scope)) { |
| 6439 | AstNode *source_node = fn_table_entry->proto_node; | 6493 | IrBasicBlock *bad_resume_block = allocate<IrBasicBlock>(1); |
| 6440 | ZigLLVMSetCurrentDebugLocation(g->builder, (int)source_node->line + 1, | 6494 | bad_resume_block->name_hint = "BadResume"; |
| 6441 | (int)source_node->column + 1, get_di_scope(g, fn_table_entry->child_scope)); | 6495 | bad_resume_block->split_llvm_fn = make_fn_llvm_value(g, fn_table_entry); |
| 6442 | } | 6496 | |
| 6443 | IrExecutable *executable = &fn_table_entry->analyzed_executable; | 6497 | LLVMBasicBlockRef llvm_block = LLVMAppendBasicBlock(bad_resume_block->split_llvm_fn, "BadResume"); |
| 6444 | LLVMBasicBlockRef bad_resume_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadResume"); | 6498 | LLVMPositionBuilderAtEnd(g->builder, llvm_block); |
| 6445 | LLVMPositionBuilderAtEnd(g->builder, bad_resume_block); | 6499 | gen_safety_crash(g, PanicMsgIdBadResume); |
| 6446 | gen_assertion_scope(g, PanicMsgIdBadResume, fn_table_entry->child_scope); | 6500 | |
| 6447 | | 6501 | fn_table_entry->resume_blocks.append(bad_resume_block); |
| 6448 | LLVMPositionBuilderAtEnd(g->builder, fn_table_entry->preamble_llvm_block); | | |
| 6449 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, | | |
| 6450 | coro_resume_index_index, ""); | | |
| 6451 | LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, ""); | | |
| 6452 | // +1 - index 0 is reserved for the entry block | | |
| 6453 | LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, resume_index, bad_resume_block, | | |
| 6454 | fn_table_entry->resume_blocks.length + 1); | | |
| 6455 | | | |
| 6456 | LLVMValueRef zero = LLVMConstNull(usize_type_ref); | | |
| 6457 | LLVMAddCase(switch_instr, zero, executable->basic_block_list.at(0)->llvm_block); | | |
| 6458 | | | |
| 6459 | for (size_t resume_i = 0; resume_i < fn_table_entry->resume_blocks.length; resume_i += 1) { | | |
| 6460 | IrBasicBlock *resume_block = fn_table_entry->resume_blocks.at(resume_i); | | |
| 6461 | LLVMValueRef case_value = LLVMConstInt(usize_type_ref, resume_block->resume_index, false); | | |
| 6462 | LLVMAddCase(switch_instr, case_value, resume_block->llvm_block); | | |
| 6463 | } | 6502 | } |
| 6464 | } else { | 6503 | } else { |
| 6465 | // create debug variable declarations for parameters | 6504 | // create debug variable declarations for parameters |
| ... | @@ -6472,7 +6511,6 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6472,7 +6511,6 @@ static void do_code_gen(CodeGen *g) { |
| 6472 | walk_function_params(g, fn_table_entry->type_entry, &fn_walk_init); | 6511 | walk_function_params(g, fn_table_entry->type_entry, &fn_walk_init); |
| 6473 | } | 6512 | } |
| 6474 | | 6513 | |
| 6475 | | | |
| 6476 | ir_render(g, fn_table_entry); | 6514 | ir_render(g, fn_table_entry); |
| 6477 | | 6515 | |
| 6478 | } | 6516 | } |