authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-28 16:47:13-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-28 16:47:13-05:00
logad2a29ccf25af189fc180cba6843c20b9dd029d1
tree63b15e027ec02baa4d119e9aca20756c339e193c
parent026aebf2ea567c15eebf9ddb9180f7d0e2ec7a9d

break the data dependencies that llvm coro transforms cant handle

my simple coro test program builds now see #727

4 files changed, 71 insertions(+), 23 deletions(-)

src/all_types.hpp+8-1
...@@ -60,11 +60,11 @@ struct IrExecutable {...@@ -60,11 +60,11 @@ struct IrExecutable {
60 IrInstruction *coro_handle;60 IrInstruction *coro_handle;
61 IrInstruction *coro_awaiter_field_ptr;61 IrInstruction *coro_awaiter_field_ptr;
62 IrInstruction *coro_result_ptr_field_ptr;62 IrInstruction *coro_result_ptr_field_ptr;
63 IrInstruction *implicit_allocator_ptr;
64 IrBasicBlock *coro_early_final;63 IrBasicBlock *coro_early_final;
65 IrBasicBlock *coro_normal_final;64 IrBasicBlock *coro_normal_final;
66 IrBasicBlock *coro_suspend_block;65 IrBasicBlock *coro_suspend_block;
67 IrBasicBlock *coro_final_cleanup_block;66 IrBasicBlock *coro_final_cleanup_block;
67 VariableTableEntry *coro_allocator_var;
68};68};
6969
70enum OutType {70enum OutType {
...@@ -2852,8 +2852,15 @@ struct IrInstructionCancel {...@@ -2852,8 +2852,15 @@ struct IrInstructionCancel {
2852 IrInstruction *target;2852 IrInstruction *target;
2853};2853};
28542854
2855enum ImplicitAllocatorId {
2856 ImplicitAllocatorIdArg,
2857 ImplicitAllocatorIdLocalVar,
2858};
2859
2855struct IrInstructionGetImplicitAllocator {2860struct IrInstructionGetImplicitAllocator {
2856 IrInstruction base;2861 IrInstruction base;
2862
2863 ImplicitAllocatorId id;
2857};2864};
28582865
2859struct IrInstructionCoroId {2866struct IrInstructionCoroId {
src/codegen.cpp+1
...@@ -3294,6 +3294,7 @@ static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrIns...@@ -3294,6 +3294,7 @@ static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrIns
3294static LLVMValueRef ir_render_get_implicit_allocator(CodeGen *g, IrExecutable *executable,3294static LLVMValueRef ir_render_get_implicit_allocator(CodeGen *g, IrExecutable *executable,
3295 IrInstructionGetImplicitAllocator *instruction)3295 IrInstructionGetImplicitAllocator *instruction)
3296{3296{
3297 assert(instruction->id == ImplicitAllocatorIdArg);
3297 size_t allocator_arg_index = get_async_allocator_arg_index(g, &g->cur_fn->type_entry->data.fn.fn_type_id);3298 size_t allocator_arg_index = get_async_allocator_arg_index(g, &g->cur_fn->type_entry->data.fn.fn_type_id);
3298 return LLVMGetParam(g->cur_fn_val, allocator_arg_index);3299 return LLVMGetParam(g->cur_fn_val, allocator_arg_index);
3299}3300}
src/ir.cpp+52-21
...@@ -114,6 +114,8 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc...@@ -114,6 +114,8 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
114static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg);114static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg);
115static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,115static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name,
116 IrInstruction *source_instr, IrInstruction *container_ptr, TypeTableEntry *container_type);116 IrInstruction *source_instr, IrInstruction *container_ptr, TypeTableEntry *container_type);
117static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
118 VariableTableEntry *var, bool is_const_ptr, bool is_volatile_ptr);
117119
118ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {120ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {
119 assert(const_val->type->id == TypeTableEntryIdPointer);121 assert(const_val->type->id == TypeTableEntryIdPointer);
...@@ -2491,8 +2493,11 @@ static IrInstruction *ir_build_cancel(IrBuilder *irb, Scope *scope, AstNode *sou...@@ -2491,8 +2493,11 @@ static IrInstruction *ir_build_cancel(IrBuilder *irb, Scope *scope, AstNode *sou
2491 return &instruction->base;2493 return &instruction->base;
2492}2494}
24932495
2494static IrInstruction *ir_build_get_implicit_allocator(IrBuilder *irb, Scope *scope, AstNode *source_node) {2496static IrInstruction *ir_build_get_implicit_allocator(IrBuilder *irb, Scope *scope, AstNode *source_node,
2497 ImplicitAllocatorId id)
2498{
2495 IrInstructionGetImplicitAllocator *instruction = ir_build_instruction<IrInstructionGetImplicitAllocator>(irb, scope, source_node);2499 IrInstructionGetImplicitAllocator *instruction = ir_build_instruction<IrInstructionGetImplicitAllocator>(irb, scope, source_node);
2500 instruction->id = id;
24962501
2497 return &instruction->base;2502 return &instruction->base;
2498}2503}
...@@ -6081,15 +6086,13 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -6081,15 +6086,13 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
60816086
6082 FnTableEntry *fn_entry = exec_fn_entry(irb->exec);6087 FnTableEntry *fn_entry = exec_fn_entry(irb->exec);
6083 bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;6088 bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
6089 IrInstruction *coro_id;
6084 IrInstruction *u8_ptr_type;6090 IrInstruction *u8_ptr_type;
6085 IrInstruction *const_bool_false;6091 IrInstruction *const_bool_false;
6086 IrInstruction *coro_size;
6087 IrInstruction *coro_id;
6088 IrInstruction *coro_promise_ptr;
6089 IrInstruction *coro_result_field_ptr;6092 IrInstruction *coro_result_field_ptr;
6090 IrInstruction *coro_mem_ptr;
6091 TypeTableEntry *return_type;6093 TypeTableEntry *return_type;
6092 Buf *result_ptr_field_name;6094 Buf *result_ptr_field_name;
6095 VariableTableEntry *coro_size_var;
6093 if (is_async) {6096 if (is_async) {
6094 // create the coro promise6097 // create the coro promise
6095 const_bool_false = ir_build_const_bool(irb, scope, node, false);6098 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...@@ -6099,17 +6102,21 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
6099 return_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;6102 return_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
6100 IrInstruction *promise_init = ir_build_const_promise_init(irb, scope, node, return_type);6103 IrInstruction *promise_init = ir_build_const_promise_init(irb, scope, node, return_type);
6101 ir_build_var_decl(irb, scope, node, promise_var, nullptr, nullptr, promise_init);6104 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
6104 u8_ptr_type = ir_build_const_type(irb, scope, node,6107 u8_ptr_type = ir_build_const_type(irb, scope, node,
6105 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));6108 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));
6106 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, coro_promise_ptr);6109 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, coro_promise_ptr);
6107 coro_id = ir_build_coro_id(irb, scope, node, promise_as_u8_ptr);6110 coro_id = ir_build_coro_id(irb, scope, node, promise_as_u8_ptr);
6108 coro_size = ir_build_coro_size(irb, scope, node);6111 coro_size_var = ir_create_var(irb, node, scope, nullptr, false, false, true, const_bool_false);
6109 irb->exec->implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node);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);
6110 Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);6118 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,6119 IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, alloc_field_name);
6112 alloc_field_name);
6113 IrInstruction *alloc_fn = ir_build_load_ptr(irb, scope, node, alloc_fn_ptr);6120 IrInstruction *alloc_fn = ir_build_load_ptr(irb, scope, node, alloc_fn_ptr);
6114 IrInstruction *maybe_coro_mem_ptr = ir_build_coro_alloc_helper(irb, scope, node, alloc_fn, coro_size);6121 IrInstruction *maybe_coro_mem_ptr = ir_build_coro_alloc_helper(irb, scope, node, alloc_fn, coro_size);
6115 IrInstruction *alloc_result_is_ok = ir_build_test_nonnull(irb, scope, node, maybe_coro_mem_ptr);6122 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...@@ -6122,7 +6129,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
6122 ir_build_return(irb, scope, node, undef);6129 ir_build_return(irb, scope, node, undef);
61236130
6124 ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);6131 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);
6126 irb->exec->coro_handle = ir_build_coro_begin(irb, scope, node, coro_id, coro_mem_ptr);6133 irb->exec->coro_handle = ir_build_coro_begin(irb, scope, node, coro_id, coro_mem_ptr);
61276134
6128 Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME);6135 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...@@ -6200,15 +6207,20 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
6200 IrInstruction *resume_awaiter = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);6207 IrInstruction *resume_awaiter = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
62016208
6202 Buf *free_field_name = buf_create_from_str(ASYNC_FREE_FIELD_NAME);6209 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,6210 IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node,
6204 free_field_name);6211 ImplicitAllocatorIdLocalVar);
6212 IrInstruction *free_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, free_field_name);
6205 IrInstruction *free_fn = ir_build_load_ptr(irb, scope, node, free_fn_ptr);6213 IrInstruction *free_fn = ir_build_load_ptr(irb, scope, node, free_fn_ptr);
6206 IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);6214 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);
6207 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);6217 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);
6208 IrInstruction *mem_slice = ir_build_slice(irb, scope, node, coro_mem_ptr_ref, zero, coro_size, false);6220 IrInstruction *mem_slice = ir_build_slice(irb, scope, node, coro_mem_ptr_ref, zero, coro_size, false);
6209 size_t arg_count = 2;6221 size_t arg_count = 2;
6210 IrInstruction **args = allocate<IrInstruction *>(arg_count);6222 IrInstruction **args = allocate<IrInstruction *>(arg_count);
6211 args[0] = irb->exec->implicit_allocator_ptr; // self6223 args[0] = implicit_allocator_ptr; // self
6212 args[1] = mem_slice; // old_mem6224 args[1] = mem_slice; // old_mem
6213 ir_build_call(irb, scope, node, nullptr, free_fn, arg_count, args, false, FnInlineAuto, false, nullptr);6225 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,...@@ -11229,7 +11241,7 @@ static TypeTableEntry *ir_analyze_instruction_error_union(IrAnalyze *ira,
11229 return ira->codegen->builtin_types.entry_type;11241 return ira->codegen->builtin_types.entry_type;
11230}11242}
1123111243
11232IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_instr) {11244IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_instr, ImplicitAllocatorId id) {
11233 FnTableEntry *parent_fn_entry = exec_fn_entry(ira->new_irb.exec);11245 FnTableEntry *parent_fn_entry = exec_fn_entry(ira->new_irb.exec);
11234 if (parent_fn_entry == nullptr) {11246 if (parent_fn_entry == nullptr) {
11235 ir_add_error(ira, source_instr, buf_sprintf("no implicit allocator available"));11247 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...@@ -11243,9 +11255,26 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i
11243 }11255 }
1124411256
11245 assert(parent_fn_type->async_allocator_type != nullptr);11257 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);11258
11247 result->value.type = parent_fn_type->async_allocator_type;11259 switch (id) {
11248 return result;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();
11249}11278}
1125011279
11251static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *call_instruction, FnTableEntry *fn_entry, TypeTableEntry *fn_type,11280static 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...@@ -11805,7 +11834,8 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
11805 }11834 }
11806 IrInstruction *uncasted_async_allocator_inst;11835 IrInstruction *uncasted_async_allocator_inst;
11807 if (call_instruction->async_allocator == nullptr) {11836 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);
11809 if (type_is_invalid(uncasted_async_allocator_inst->value.type))11839 if (type_is_invalid(uncasted_async_allocator_inst->value.type))
11810 return ira->codegen->builtin_types.entry_invalid;11840 return ira->codegen->builtin_types.entry_invalid;
11811 } else {11841 } else {
...@@ -11927,7 +11957,8 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal...@@ -11927,7 +11957,8 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
11927 if (call_instruction->is_async) {11957 if (call_instruction->is_async) {
11928 IrInstruction *uncasted_async_allocator_inst;11958 IrInstruction *uncasted_async_allocator_inst;
11929 if (call_instruction->async_allocator == nullptr) {11959 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);
11931 if (type_is_invalid(uncasted_async_allocator_inst->value.type))11962 if (type_is_invalid(uncasted_async_allocator_inst->value.type))
11932 return ira->codegen->builtin_types.entry_invalid;11963 return ira->codegen->builtin_types.entry_invalid;
11933 } else {11964 } else {
...@@ -17189,7 +17220,7 @@ static TypeTableEntry *ir_analyze_instruction_coro_begin(IrAnalyze *ira, IrInstr...@@ -17189,7 +17220,7 @@ static TypeTableEntry *ir_analyze_instruction_coro_begin(IrAnalyze *ira, IrInstr
17189}17220}
1719017221
17191static TypeTableEntry *ir_analyze_instruction_get_implicit_allocator(IrAnalyze *ira, IrInstructionGetImplicitAllocator *instruction) {17222static 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);
17193 ir_link_new_instruction(result, &instruction->base);17224 ir_link_new_instruction(result, &instruction->base);
17194 return result->value.type;17225 return result->value.type;
17195}17226}
src/ir_print.cpp+10-1
...@@ -1027,7 +1027,16 @@ static void ir_print_cancel(IrPrint *irp, IrInstructionCancel *instruction) {...@@ -1027,7 +1027,16 @@ static void ir_print_cancel(IrPrint *irp, IrInstructionCancel *instruction) {
1027}1027}
10281028
1029static void ir_print_get_implicit_allocator(IrPrint *irp, IrInstructionGetImplicitAllocator *instruction) {1029static 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, ")");
1031}1040}
10321041
1033static void ir_print_coro_id(IrPrint *irp, IrInstructionCoroId *instruction) {1042static void ir_print_coro_id(IrPrint *irp, IrInstructionCoroId *instruction) {