Skip to content

Commit ad2a29c

Browse files
committed
break the data dependencies that llvm coro transforms cant handle
my simple coro test program builds now see #727
1 parent 026aebf commit ad2a29c

File tree

4 files changed

+71
-23
lines changed

4 files changed

+71
-23
lines changed

src/all_types.hpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,11 @@ struct IrExecutable {
6060
IrInstruction *coro_handle;
6161
IrInstruction *coro_awaiter_field_ptr;
6262
IrInstruction *coro_result_ptr_field_ptr;
63-
IrInstruction *implicit_allocator_ptr;
6463
IrBasicBlock *coro_early_final;
6564
IrBasicBlock *coro_normal_final;
6665
IrBasicBlock *coro_suspend_block;
6766
IrBasicBlock *coro_final_cleanup_block;
67+
VariableTableEntry *coro_allocator_var;
6868
};
6969

7070
enum OutType {
@@ -2852,8 +2852,15 @@ struct IrInstructionCancel {
28522852
IrInstruction *target;
28532853
};
28542854

2855+
enum ImplicitAllocatorId {
2856+
ImplicitAllocatorIdArg,
2857+
ImplicitAllocatorIdLocalVar,
2858+
};
2859+
28552860
struct IrInstructionGetImplicitAllocator {
28562861
IrInstruction base;
2862+
2863+
ImplicitAllocatorId id;
28572864
};
28582865

28592866
struct IrInstructionCoroId {

src/codegen.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -3294,6 +3294,7 @@ static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrIns
32943294
static LLVMValueRef ir_render_get_implicit_allocator(CodeGen *g, IrExecutable *executable,
32953295
IrInstructionGetImplicitAllocator *instruction)
32963296
{
3297+
assert(instruction->id == ImplicitAllocatorIdArg);
32973298
size_t allocator_arg_index = get_async_allocator_arg_index(g, &g->cur_fn->type_entry->data.fn.fn_type_id);
32983299
return LLVMGetParam(g->cur_fn_val, allocator_arg_index);
32993300
}

src/ir.cpp

+52-21
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
114114
static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg);
115115
static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
116116
IrInstruction *source_instr, IrInstruction *container_ptr, TypeTableEntry *container_type);
117+
static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
118+
VariableTableEntry *var, bool is_const_ptr, bool is_volatile_ptr);
117119

118120
ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {
119121
assert(const_val->type->id == TypeTableEntryIdPointer);
@@ -2491,8 +2493,11 @@ static IrInstruction *ir_build_cancel(IrBuilder *irb, Scope *scope, AstNode *sou
24912493
return &instruction->base;
24922494
}
24932495

2494-
static IrInstruction *ir_build_get_implicit_allocator(IrBuilder *irb, Scope *scope, AstNode *source_node) {
2496+
static IrInstruction *ir_build_get_implicit_allocator(IrBuilder *irb, Scope *scope, AstNode *source_node,
2497+
ImplicitAllocatorId id)
2498+
{
24952499
IrInstructionGetImplicitAllocator *instruction = ir_build_instruction<IrInstructionGetImplicitAllocator>(irb, scope, source_node);
2500+
instruction->id = id;
24962501

24972502
return &instruction->base;
24982503
}
@@ -6081,15 +6086,13 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
60816086

60826087
FnTableEntry *fn_entry = exec_fn_entry(irb->exec);
60836088
bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
6089+
IrInstruction *coro_id;
60846090
IrInstruction *u8_ptr_type;
60856091
IrInstruction *const_bool_false;
6086-
IrInstruction *coro_size;
6087-
IrInstruction *coro_id;
6088-
IrInstruction *coro_promise_ptr;
60896092
IrInstruction *coro_result_field_ptr;
6090-
IrInstruction *coro_mem_ptr;
60916093
TypeTableEntry *return_type;
60926094
Buf *result_ptr_field_name;
6095+
VariableTableEntry *coro_size_var;
60936096
if (is_async) {
60946097
// create the coro promise
60956098
const_bool_false = ir_build_const_bool(irb, scope, node, false);
@@ -6099,17 +6102,21 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
60996102
return_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
61006103
IrInstruction *promise_init = ir_build_const_promise_init(irb, scope, node, return_type);
61016104
ir_build_var_decl(irb, scope, node, promise_var, nullptr, nullptr, promise_init);
6102-
coro_promise_ptr = ir_build_var_ptr(irb, scope, node, promise_var, false, false);
6105+
IrInstruction *coro_promise_ptr = ir_build_var_ptr(irb, scope, node, promise_var, false, false);
61036106

61046107
u8_ptr_type = ir_build_const_type(irb, scope, node,
61056108
get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));
61066109
IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, coro_promise_ptr);
61076110
coro_id = ir_build_coro_id(irb, scope, node, promise_as_u8_ptr);
6108-
coro_size = ir_build_coro_size(irb, scope, node);
6109-
irb->exec->implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node);
6111+
coro_size_var = ir_create_var(irb, node, scope, nullptr, false, false, true, const_bool_false);
6112+
IrInstruction *coro_size = ir_build_coro_size(irb, scope, node);
6113+
ir_build_var_decl(irb, scope, node, coro_size_var, nullptr, nullptr, coro_size);
6114+
IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node,
6115+
ImplicitAllocatorIdArg);
6116+
irb->exec->coro_allocator_var = ir_create_var(irb, node, scope, nullptr, true, true, true, const_bool_false);
6117+
ir_build_var_decl(irb, scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr);
61106118
Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);
6111-
IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, scope, node, irb->exec->implicit_allocator_ptr,
6112-
alloc_field_name);
6119+
IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, alloc_field_name);
61136120
IrInstruction *alloc_fn = ir_build_load_ptr(irb, scope, node, alloc_fn_ptr);
61146121
IrInstruction *maybe_coro_mem_ptr = ir_build_coro_alloc_helper(irb, scope, node, alloc_fn, coro_size);
61156122
IrInstruction *alloc_result_is_ok = ir_build_test_nonnull(irb, scope, node, maybe_coro_mem_ptr);
@@ -6122,7 +6129,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
61226129
ir_build_return(irb, scope, node, undef);
61236130

61246131
ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);
6125-
coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, maybe_coro_mem_ptr);
6132+
IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, maybe_coro_mem_ptr);
61266133
irb->exec->coro_handle = ir_build_coro_begin(irb, scope, node, coro_id, coro_mem_ptr);
61276134

61286135
Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME);
@@ -6200,15 +6207,20 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
62006207
IrInstruction *resume_awaiter = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
62016208

62026209
Buf *free_field_name = buf_create_from_str(ASYNC_FREE_FIELD_NAME);
6203-
IrInstruction *free_fn_ptr = ir_build_field_ptr(irb, scope, node, irb->exec->implicit_allocator_ptr,
6204-
free_field_name);
6210+
IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node,
6211+
ImplicitAllocatorIdLocalVar);
6212+
IrInstruction *free_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, free_field_name);
62056213
IrInstruction *free_fn = ir_build_load_ptr(irb, scope, node, free_fn_ptr);
62066214
IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);
6215+
IrInstruction *coro_mem_ptr_maybe = ir_build_coro_free(irb, scope, node, coro_id, irb->exec->coro_handle);
6216+
IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, coro_mem_ptr_maybe);
62076217
IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
6218+
IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var, true, false);
6219+
IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);
62086220
IrInstruction *mem_slice = ir_build_slice(irb, scope, node, coro_mem_ptr_ref, zero, coro_size, false);
62096221
size_t arg_count = 2;
62106222
IrInstruction **args = allocate<IrInstruction *>(arg_count);
6211-
args[0] = irb->exec->implicit_allocator_ptr; // self
6223+
args[0] = implicit_allocator_ptr; // self
62126224
args[1] = mem_slice; // old_mem
62136225
ir_build_call(irb, scope, node, nullptr, free_fn, arg_count, args, false, FnInlineAuto, false, nullptr);
62146226

@@ -11229,7 +11241,7 @@ static TypeTableEntry *ir_analyze_instruction_error_union(IrAnalyze *ira,
1122911241
return ira->codegen->builtin_types.entry_type;
1123011242
}
1123111243

11232-
IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_instr) {
11244+
IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_instr, ImplicitAllocatorId id) {
1123311245
FnTableEntry *parent_fn_entry = exec_fn_entry(ira->new_irb.exec);
1123411246
if (parent_fn_entry == nullptr) {
1123511247
ir_add_error(ira, source_instr, buf_sprintf("no implicit allocator available"));
@@ -11243,9 +11255,26 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i
1124311255
}
1124411256

1124511257
assert(parent_fn_type->async_allocator_type != nullptr);
11246-
IrInstruction *result = ir_build_get_implicit_allocator(&ira->new_irb, source_instr->scope, source_instr->source_node);
11247-
result->value.type = parent_fn_type->async_allocator_type;
11248-
return result;
11258+
11259+
switch (id) {
11260+
case ImplicitAllocatorIdArg:
11261+
{
11262+
IrInstruction *result = ir_build_get_implicit_allocator(&ira->new_irb, source_instr->scope,
11263+
source_instr->source_node, ImplicitAllocatorIdArg);
11264+
result->value.type = parent_fn_type->async_allocator_type;
11265+
return result;
11266+
}
11267+
case ImplicitAllocatorIdLocalVar:
11268+
{
11269+
VariableTableEntry *coro_allocator_var = ira->old_irb.exec->coro_allocator_var;
11270+
assert(coro_allocator_var != nullptr);
11271+
IrInstruction *var_ptr_inst = ir_get_var_ptr(ira, source_instr, coro_allocator_var, true, false);
11272+
IrInstruction *result = ir_get_deref(ira, source_instr, var_ptr_inst);
11273+
assert(result->value.type != nullptr);
11274+
return result;
11275+
}
11276+
}
11277+
zig_unreachable();
1124911278
}
1125011279

1125111280
static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *call_instruction, FnTableEntry *fn_entry, TypeTableEntry *fn_type,
@@ -11805,7 +11834,8 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1180511834
}
1180611835
IrInstruction *uncasted_async_allocator_inst;
1180711836
if (call_instruction->async_allocator == nullptr) {
11808-
uncasted_async_allocator_inst = ir_get_implicit_allocator(ira, &call_instruction->base);
11837+
uncasted_async_allocator_inst = ir_get_implicit_allocator(ira, &call_instruction->base,
11838+
ImplicitAllocatorIdLocalVar);
1180911839
if (type_is_invalid(uncasted_async_allocator_inst->value.type))
1181011840
return ira->codegen->builtin_types.entry_invalid;
1181111841
} else {
@@ -11927,7 +11957,8 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1192711957
if (call_instruction->is_async) {
1192811958
IrInstruction *uncasted_async_allocator_inst;
1192911959
if (call_instruction->async_allocator == nullptr) {
11930-
uncasted_async_allocator_inst = ir_get_implicit_allocator(ira, &call_instruction->base);
11960+
uncasted_async_allocator_inst = ir_get_implicit_allocator(ira, &call_instruction->base,
11961+
ImplicitAllocatorIdLocalVar);
1193111962
if (type_is_invalid(uncasted_async_allocator_inst->value.type))
1193211963
return ira->codegen->builtin_types.entry_invalid;
1193311964
} else {
@@ -17189,7 +17220,7 @@ static TypeTableEntry *ir_analyze_instruction_coro_begin(IrAnalyze *ira, IrInstr
1718917220
}
1719017221

1719117222
static TypeTableEntry *ir_analyze_instruction_get_implicit_allocator(IrAnalyze *ira, IrInstructionGetImplicitAllocator *instruction) {
17192-
IrInstruction *result = ir_get_implicit_allocator(ira, &instruction->base);
17223+
IrInstruction *result = ir_get_implicit_allocator(ira, &instruction->base, instruction->id);
1719317224
ir_link_new_instruction(result, &instruction->base);
1719417225
return result->value.type;
1719517226
}

src/ir_print.cpp

+10-1
Original file line numberDiff line numberDiff line change
@@ -1027,7 +1027,16 @@ static void ir_print_cancel(IrPrint *irp, IrInstructionCancel *instruction) {
10271027
}
10281028

10291029
static void ir_print_get_implicit_allocator(IrPrint *irp, IrInstructionGetImplicitAllocator *instruction) {
1030-
fprintf(irp->f, "@getImplicitAllocator()");
1030+
fprintf(irp->f, "@getImplicitAllocator(");
1031+
switch (instruction->id) {
1032+
case ImplicitAllocatorIdArg:
1033+
fprintf(irp->f, "Arg");
1034+
break;
1035+
case ImplicitAllocatorIdLocalVar:
1036+
fprintf(irp->f, "LocalVar");
1037+
break;
1038+
}
1039+
fprintf(irp->f, ")");
10311040
}
10321041

10331042
static void ir_print_coro_id(IrPrint *irp, IrInstructionCoroId *instruction) {

0 commit comments

Comments
 (0)