@@ -547,7 +547,10 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
547
547
} else if (handle_is_ptr (return_type) &&
548
548
calling_convention_does_first_arg_return (fn_type->data .fn .fn_type_id .cc ))
549
549
{
550
- addLLVMArgAttr (fn_table_entry->llvm_value , 0 , " sret" );
550
+ // We do not add the sret attribute, because it would require the return type to be void,
551
+ // and we want the return value to return the sret pointer, to work around LLVM Coroutine
552
+ // transformation passes not understanding the data dependency.
553
+ // addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
551
554
addLLVMArgAttr (fn_table_entry->llvm_value , 0 , " nonnull" );
552
555
}
553
556
@@ -1616,7 +1619,9 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns
1616
1619
if (calling_convention_does_first_arg_return (g->cur_fn ->type_entry ->data .fn .fn_type_id .cc )) {
1617
1620
assert (g->cur_ret_ptr );
1618
1621
gen_assign_raw (g, g->cur_ret_ptr , get_pointer_to_type (g, return_type, false ), value);
1619
- LLVMBuildRetVoid (g->builder );
1622
+ // as a workaround for LLVM coroutines not understanding instruction dependencies,
1623
+ // we return the sret pointer argument instead of returning void
1624
+ LLVMBuildRet (g->builder , g->cur_ret_ptr );
1620
1625
} else {
1621
1626
LLVMValueRef by_val_value = gen_load_untyped (g, value, 0 , false , " " );
1622
1627
LLVMBuildRet (g->builder , by_val_value);
@@ -2775,7 +2780,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
2775
2780
} else if (!ret_has_bits) {
2776
2781
return nullptr ;
2777
2782
} else if (first_arg_ret) {
2778
- return instruction->tmp_ptr ;
2783
+ // instead of returning instruction->tmp_ptr here, we trust that the function returned the first arg.
2784
+ // this is a workaround for llvm coroutines not understanding the data dependency
2785
+ return result;
2779
2786
} else {
2780
2787
return result;
2781
2788
}
0 commit comments