parent
236bbe1183
commit
b261da0672
|
@ -56,6 +56,7 @@ struct IrExecutable {
|
|||
IrAnalyze *analysis;
|
||||
Scope *begin_scope;
|
||||
ZigList<Tld *> tld_list;
|
||||
IrInstruction *coro_handle;
|
||||
};
|
||||
|
||||
enum OutType {
|
||||
|
@ -1961,6 +1962,10 @@ enum IrInstructionId {
|
|||
IrInstructionIdErrorUnion,
|
||||
IrInstructionIdCancel,
|
||||
IrInstructionIdGetImplicitAllocator,
|
||||
IrInstructionIdCoroId,
|
||||
IrInstructionIdCoroAlloc,
|
||||
IrInstructionIdCoroSize,
|
||||
IrInstructionIdCoroBegin,
|
||||
};
|
||||
|
||||
struct IrInstruction {
|
||||
|
@ -2810,6 +2815,27 @@ struct IrInstructionGetImplicitAllocator {
|
|||
IrInstruction base;
|
||||
};
|
||||
|
||||
struct IrInstructionCoroId {
|
||||
IrInstruction base;
|
||||
};
|
||||
|
||||
struct IrInstructionCoroAlloc {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *coro_id;
|
||||
};
|
||||
|
||||
struct IrInstructionCoroSize {
|
||||
IrInstruction base;
|
||||
};
|
||||
|
||||
struct IrInstructionCoroBegin {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *coro_id;
|
||||
IrInstruction *coro_mem_ptr;
|
||||
};
|
||||
|
||||
static const size_t slice_ptr_index = 0;
|
||||
static const size_t slice_len_index = 1;
|
||||
|
||||
|
|
|
@ -3696,6 +3696,23 @@ static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutable *executable, IrInst
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_coro_id(CodeGen *g, IrExecutable *executable, IrInstructionCoroId *instruction) {
|
||||
zig_panic("TODO ir_render_coro_id");
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_coro_alloc(CodeGen *g, IrExecutable *executable, IrInstructionCoroAlloc *instruction) {
|
||||
zig_panic("TODO ir_render_coro_alloc");
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_coro_size(CodeGen *g, IrExecutable *executable, IrInstructionCoroSize *instruction) {
|
||||
zig_panic("TODO ir_render_coro_size");
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_coro_begin(CodeGen *g, IrExecutable *executable, IrInstructionCoroBegin *instruction) {
|
||||
zig_panic("TODO ir_render_coro_begin");
|
||||
}
|
||||
|
||||
|
||||
static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
|
||||
AstNode *source_node = instruction->source_node;
|
||||
Scope *scope = instruction->scope;
|
||||
|
@ -3881,12 +3898,21 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
|||
return ir_render_cancel(g, executable, (IrInstructionCancel *)instruction);
|
||||
case IrInstructionIdGetImplicitAllocator:
|
||||
return ir_render_get_implicit_allocator(g, executable, (IrInstructionGetImplicitAllocator *)instruction);
|
||||
case IrInstructionIdCoroId:
|
||||
return ir_render_coro_id(g, executable, (IrInstructionCoroId *)instruction);
|
||||
case IrInstructionIdCoroAlloc:
|
||||
return ir_render_coro_alloc(g, executable, (IrInstructionCoroAlloc *)instruction);
|
||||
case IrInstructionIdCoroSize:
|
||||
return ir_render_coro_size(g, executable, (IrInstructionCoroSize *)instruction);
|
||||
case IrInstructionIdCoroBegin:
|
||||
return ir_render_coro_begin(g, executable, (IrInstructionCoroBegin *)instruction);
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {
|
||||
assert(fn_entry);
|
||||
|
||||
IrExecutable *executable = &fn_entry->analyzed_executable;
|
||||
assert(executable->basic_block_list.length > 0);
|
||||
for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {
|
||||
|
|
138
src/ir.cpp
138
src/ir.cpp
|
@ -45,6 +45,9 @@ static LVal make_lval_addr(bool is_const, bool is_volatile) {
|
|||
return { true, is_const, is_volatile };
|
||||
}
|
||||
|
||||
static const char * ASYNC_ALLOC_FIELD_NAME = "allocFn";
|
||||
//static const char * ASYNC_FREE_FIELD_NAME = "freeFn";
|
||||
|
||||
enum ConstCastResultId {
|
||||
ConstCastResultIdOk,
|
||||
ConstCastResultIdErrSet,
|
||||
|
@ -649,6 +652,22 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionGetImplicitAlloc
|
|||
return IrInstructionIdGetImplicitAllocator;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroId *) {
|
||||
return IrInstructionIdCoroId;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroAlloc *) {
|
||||
return IrInstructionIdCoroAlloc;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroSize *) {
|
||||
return IrInstructionIdCoroSize;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroBegin *) {
|
||||
return IrInstructionIdCoroBegin;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
|
||||
T *special_instruction = allocate<T>(1);
|
||||
|
@ -2420,6 +2439,38 @@ static IrInstruction *ir_build_get_implicit_allocator(IrBuilder *irb, Scope *sco
|
|||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_coro_id(IrBuilder *irb, Scope *scope, AstNode *source_node) {
|
||||
IrInstructionCoroId *instruction = ir_build_instruction<IrInstructionCoroId>(irb, scope, source_node);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_coro_alloc(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *coro_id) {
|
||||
IrInstructionCoroAlloc *instruction = ir_build_instruction<IrInstructionCoroAlloc>(irb, scope, source_node);
|
||||
instruction->coro_id = coro_id;
|
||||
|
||||
ir_ref_instruction(coro_id, irb->current_basic_block);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_coro_size(IrBuilder *irb, Scope *scope, AstNode *source_node) {
|
||||
IrInstructionCoroSize *instruction = ir_build_instruction<IrInstructionCoroSize>(irb, scope, source_node);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_coro_begin(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *coro_id, IrInstruction *coro_mem_ptr) {
|
||||
IrInstructionCoroBegin *instruction = ir_build_instruction<IrInstructionCoroBegin>(irb, scope, source_node);
|
||||
instruction->coro_id = coro_id;
|
||||
instruction->coro_mem_ptr = coro_mem_ptr;
|
||||
|
||||
ir_ref_instruction(coro_id, irb->current_basic_block);
|
||||
ir_ref_instruction(coro_mem_ptr, irb->current_basic_block);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
|
||||
results[ReturnKindUnconditional] = 0;
|
||||
results[ReturnKindError] = 0;
|
||||
|
@ -5782,6 +5833,63 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
|
|||
// Entry block gets a reference because we enter it to begin.
|
||||
ir_ref_bb(irb->current_basic_block);
|
||||
|
||||
FnTableEntry *fn_entry = exec_fn_entry(irb->exec);
|
||||
bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
|
||||
if (is_async) {
|
||||
IrInstruction *is_comptime_false = ir_build_const_bool(irb, scope, node, false);
|
||||
IrInstruction *coro_id = ir_build_coro_id(irb, scope, node);
|
||||
IrInstruction *need_dyn_alloc = ir_build_coro_alloc(irb, scope, node, coro_id);
|
||||
IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);
|
||||
IrInstruction *u8_ptr_type = ir_build_const_type(irb, scope, node,
|
||||
get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));
|
||||
IrInstruction *null_ptr = ir_build_int_to_ptr(irb, scope, node, u8_ptr_type, zero);
|
||||
|
||||
IrBasicBlock *dyn_alloc_block = ir_create_basic_block(irb, scope, "DynAlloc");
|
||||
IrBasicBlock *coro_begin_block = ir_create_basic_block(irb, scope, "CoroBegin");
|
||||
ir_build_cond_br(irb, scope, node, need_dyn_alloc, dyn_alloc_block, coro_begin_block, is_comptime_false);
|
||||
|
||||
ir_set_cursor_at_end_and_append_block(irb, dyn_alloc_block);
|
||||
IrInstruction *coro_size = ir_build_coro_size(irb, scope, node);
|
||||
IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node);
|
||||
Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);
|
||||
IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, alloc_field_name);
|
||||
IrInstruction *alloc_fn = ir_build_load_ptr(irb, scope, node, alloc_fn_ptr);
|
||||
IrInstruction *implicit_allocator = ir_build_load_ptr(irb, scope, node, implicit_allocator_ptr);
|
||||
IrInstruction *alignment = ir_build_const_usize(irb, scope, node, irb->codegen->pointer_size_bytes * 2);
|
||||
size_t arg_count = 3;
|
||||
IrInstruction **args = allocate<IrInstruction *>(arg_count);
|
||||
args[0] = implicit_allocator; // self
|
||||
args[1] = coro_size; // byte_count
|
||||
args[2] = alignment; // alignment
|
||||
IrInstruction *alloc_result = ir_build_call(irb, scope, node, nullptr, alloc_fn, arg_count, args, false, FnInlineAuto, false, nullptr);
|
||||
IrInstruction *alloc_result_ptr = ir_build_ref(irb, scope, node, alloc_result, true, false);
|
||||
IrInstruction *alloc_result_is_err = ir_build_test_err(irb, scope, node, alloc_result_ptr);
|
||||
IrBasicBlock *alloc_err_block = ir_create_basic_block(irb, scope, "AllocError");
|
||||
IrBasicBlock *alloc_ok_block = ir_create_basic_block(irb, scope, "AllocOk");
|
||||
ir_build_cond_br(irb, scope, node, alloc_result_is_err, alloc_err_block, alloc_ok_block, is_comptime_false);
|
||||
|
||||
ir_set_cursor_at_end_and_append_block(irb, alloc_err_block);
|
||||
IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, alloc_result_ptr);
|
||||
ir_build_return(irb, scope, node, err_val);
|
||||
|
||||
ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);
|
||||
IrInstruction *unwrapped_mem_ptr = ir_build_unwrap_err_payload(irb, scope, node, alloc_result_ptr, false);
|
||||
Buf *ptr_field_name = buf_create_from_str("ptr");
|
||||
IrInstruction *coro_mem_ptr_field = ir_build_field_ptr(irb, scope, node, unwrapped_mem_ptr, ptr_field_name);
|
||||
IrInstruction *coro_mem_ptr = ir_build_load_ptr(irb, scope, node, coro_mem_ptr_field);
|
||||
ir_build_br(irb, scope, node, coro_begin_block, is_comptime_false);
|
||||
|
||||
ir_set_cursor_at_end_and_append_block(irb, coro_begin_block);
|
||||
IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2);
|
||||
IrInstruction **incoming_values = allocate<IrInstruction *>(2);
|
||||
incoming_blocks[0] = entry_block;
|
||||
incoming_values[0] = null_ptr;
|
||||
incoming_blocks[1] = dyn_alloc_block;
|
||||
incoming_values[1] = coro_mem_ptr;
|
||||
IrInstruction *coro_mem = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
|
||||
irb->exec->coro_handle = ir_build_coro_begin(irb, scope, node, coro_id, coro_mem);
|
||||
}
|
||||
|
||||
IrInstruction *result = ir_gen_node_extra(irb, node, scope, LVAL_NONE);
|
||||
assert(result);
|
||||
if (irb->exec->invalid)
|
||||
|
@ -10805,7 +10913,7 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i
|
|||
static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *call_instruction, FnTableEntry *fn_entry, TypeTableEntry *fn_type,
|
||||
IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count, IrInstruction *async_allocator_inst)
|
||||
{
|
||||
Buf *alloc_field_name = buf_create_from_str("allocFn");
|
||||
Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);
|
||||
//Buf *free_field_name = buf_create_from_str("freeFn");
|
||||
assert(async_allocator_inst->value.type->id == TypeTableEntryIdPointer);
|
||||
TypeTableEntry *container_type = async_allocator_inst->value.type->data.pointer.child_type;
|
||||
|
@ -16692,6 +16800,22 @@ static TypeTableEntry *ir_analyze_instruction_cancel(IrAnalyze *ira, IrInstructi
|
|||
return result->value.type;
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_coro_id(IrAnalyze *ira, IrInstructionCoroId *instruction) {
|
||||
zig_panic("TODO ir_analyze_instruction_coro_id");
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_coro_alloc(IrAnalyze *ira, IrInstructionCoroAlloc *instruction) {
|
||||
zig_panic("TODO ir_analyze_instruction_coro_alloc");
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_coro_size(IrAnalyze *ira, IrInstructionCoroSize *instruction) {
|
||||
zig_panic("TODO ir_analyze_instruction_coro_size");
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_coro_begin(IrAnalyze *ira, IrInstructionCoroBegin *instruction) {
|
||||
zig_panic("TODO ir_analyze_instruction_coro_begin");
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
|
||||
switch (instruction->id) {
|
||||
case IrInstructionIdInvalid:
|
||||
|
@ -16897,6 +17021,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
|
|||
return ir_analyze_instruction_error_union(ira, (IrInstructionErrorUnion *)instruction);
|
||||
case IrInstructionIdCancel:
|
||||
return ir_analyze_instruction_cancel(ira, (IrInstructionCancel *)instruction);
|
||||
case IrInstructionIdCoroId:
|
||||
return ir_analyze_instruction_coro_id(ira, (IrInstructionCoroId *)instruction);
|
||||
case IrInstructionIdCoroAlloc:
|
||||
return ir_analyze_instruction_coro_alloc(ira, (IrInstructionCoroAlloc *)instruction);
|
||||
case IrInstructionIdCoroSize:
|
||||
return ir_analyze_instruction_coro_size(ira, (IrInstructionCoroSize *)instruction);
|
||||
case IrInstructionIdCoroBegin:
|
||||
return ir_analyze_instruction_coro_begin(ira, (IrInstructionCoroBegin *)instruction);
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
@ -17011,6 +17143,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
|||
case IrInstructionIdSetAlignStack:
|
||||
case IrInstructionIdExport:
|
||||
case IrInstructionIdCancel:
|
||||
case IrInstructionIdCoroId:
|
||||
case IrInstructionIdCoroBegin:
|
||||
return true;
|
||||
|
||||
case IrInstructionIdPhi:
|
||||
|
@ -17086,6 +17220,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
|||
case IrInstructionIdErrorReturnTrace:
|
||||
case IrInstructionIdErrorUnion:
|
||||
case IrInstructionIdGetImplicitAllocator:
|
||||
case IrInstructionIdCoroAlloc:
|
||||
case IrInstructionIdCoroSize:
|
||||
return false;
|
||||
|
||||
case IrInstructionIdAsm:
|
||||
|
|
|
@ -1028,6 +1028,28 @@ static void ir_print_get_implicit_allocator(IrPrint *irp, IrInstructionGetImplic
|
|||
fprintf(irp->f, "@getImplicitAllocator()");
|
||||
}
|
||||
|
||||
static void ir_print_coro_id(IrPrint *irp, IrInstructionCoroId *instruction) {
|
||||
fprintf(irp->f, "@coroId()");
|
||||
}
|
||||
|
||||
static void ir_print_coro_alloc(IrPrint *irp, IrInstructionCoroAlloc *instruction) {
|
||||
fprintf(irp->f, "@coroAlloc(");
|
||||
ir_print_other_instruction(irp, instruction->coro_id);
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_coro_size(IrPrint *irp, IrInstructionCoroSize *instruction) {
|
||||
fprintf(irp->f, "@coroSize()");
|
||||
}
|
||||
|
||||
static void ir_print_coro_begin(IrPrint *irp, IrInstructionCoroBegin *instruction) {
|
||||
fprintf(irp->f, "@coroBegin(");
|
||||
ir_print_other_instruction(irp, instruction->coro_id);
|
||||
fprintf(irp->f, ",");
|
||||
ir_print_other_instruction(irp, instruction->coro_mem_ptr);
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
ir_print_prefix(irp, instruction);
|
||||
switch (instruction->id) {
|
||||
|
@ -1354,6 +1376,18 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
|||
case IrInstructionIdGetImplicitAllocator:
|
||||
ir_print_get_implicit_allocator(irp, (IrInstructionGetImplicitAllocator *)instruction);
|
||||
break;
|
||||
case IrInstructionIdCoroId:
|
||||
ir_print_coro_id(irp, (IrInstructionCoroId *)instruction);
|
||||
break;
|
||||
case IrInstructionIdCoroAlloc:
|
||||
ir_print_coro_alloc(irp, (IrInstructionCoroAlloc *)instruction);
|
||||
break;
|
||||
case IrInstructionIdCoroSize:
|
||||
ir_print_coro_size(irp, (IrInstructionCoroSize *)instruction);
|
||||
break;
|
||||
case IrInstructionIdCoroBegin:
|
||||
ir_print_coro_begin(irp, (IrInstructionCoroBegin *)instruction);
|
||||
break;
|
||||
}
|
||||
fprintf(irp->f, "\n");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue