Skip to content

Commit

Permalink
implement Zig IR for async functions
Browse files Browse the repository at this point in the history
See #727
  • Loading branch information
andrewrk committed Feb 23, 2018
1 parent ca1b77b commit 99985ad
Show file tree
Hide file tree
Showing 6 changed files with 467 additions and 54 deletions.
36 changes: 36 additions & 0 deletions src/all_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,13 @@ struct IrExecutable {
IrAnalyze *analysis;
Scope *begin_scope;
ZigList<Tld *> tld_list;

IrInstruction *coro_handle;
IrInstruction *coro_awaiter_field_ptr;
IrInstruction *coro_result_ptr_field_ptr;
IrInstruction *implicit_allocator_ptr;
IrBasicBlock *coro_early_final;
IrBasicBlock *coro_normal_final;
};

enum OutType {
Expand Down Expand Up @@ -1968,6 +1974,10 @@ enum IrInstructionId {
IrInstructionIdCoroSize,
IrInstructionIdCoroBegin,
IrInstructionIdCoroAllocFail,
IrInstructionIdCoroSuspend,
IrInstructionIdCoroEnd,
IrInstructionIdCoroFree,
IrInstructionIdCoroResume,
};

struct IrInstruction {
Expand Down Expand Up @@ -2819,6 +2829,8 @@ struct IrInstructionGetImplicitAllocator {

struct IrInstructionCoroId {
IrInstruction base;

IrInstruction *promise_ptr;
};

struct IrInstructionCoroAlloc {
Expand All @@ -2844,6 +2856,30 @@ struct IrInstructionCoroAllocFail {
IrInstruction *err_val;
};

struct IrInstructionCoroSuspend {
IrInstruction base;

IrInstruction *save_point;
IrInstruction *is_final;
};

struct IrInstructionCoroEnd {
IrInstruction base;
};

struct IrInstructionCoroFree {
IrInstruction base;

IrInstruction *coro_id;
IrInstruction *coro_handle;
};

struct IrInstructionCoroResume {
IrInstruction base;

IrInstruction *awaiter_handle;
};

static const size_t slice_ptr_index = 0;
static const size_t slice_len_index = 1;

Expand Down
10 changes: 6 additions & 4 deletions src/analyze.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -475,9 +475,7 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
if (child_type->zero_bits) {
entry->type_ref = LLVMInt1Type();
entry->di_type = g->builtin_types.entry_bool->di_type;
} else if (child_type->id == TypeTableEntryIdPointer ||
child_type->id == TypeTableEntryIdFn)
{
} else if (type_is_codegen_pointer(child_type)) {
// this is an optimization but also is necessary for calling C
// functions where all pointers are maybe pointers
// function types are technically pointers
Expand Down Expand Up @@ -1262,7 +1260,7 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
case TypeTableEntryIdMaybe:
{
TypeTableEntry *child_type = type_entry->data.maybe.child_type;
return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn;
return type_is_codegen_pointer(child_type);
}
case TypeTableEntryIdEnum:
return type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr;
Expand Down Expand Up @@ -1673,6 +1671,8 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f
field->src_index = i;
field->gen_index = i;

assert(type_has_bits(field->type_entry));

auto prev_entry = struct_type->data.structure.fields_by_name.put_unique(field->name, field);
assert(prev_entry == nullptr);
}
Expand Down Expand Up @@ -3669,9 +3669,11 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
TypeTableEntry *get_codegen_ptr_type(TypeTableEntry *type) {
if (type->id == TypeTableEntryIdPointer) return type;
if (type->id == TypeTableEntryIdFn) return type;
if (type->id == TypeTableEntryIdPromise) return type;
if (type->id == TypeTableEntryIdMaybe) {
if (type->data.maybe.child_type->id == TypeTableEntryIdPointer) return type->data.maybe.child_type;
if (type->data.maybe.child_type->id == TypeTableEntryIdFn) return type->data.maybe.child_type;
if (type->data.maybe.child_type->id == TypeTableEntryIdPromise) return type->data.maybe.child_type;
}
return nullptr;
}
Expand Down
1 change: 1 addition & 0 deletions src/analyze.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ VariableTableEntry *find_variable(CodeGen *g, Scope *orig_context, Buf *name);
Tld *find_decl(CodeGen *g, Scope *scope, Buf *name);
void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *source_node);
bool type_is_codegen_pointer(TypeTableEntry *type);

TypeTableEntry *get_codegen_ptr_type(TypeTableEntry *type);
uint32_t get_ptr_align(TypeTableEntry *type);
TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry);
Expand Down
46 changes: 34 additions & 12 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {

if (!type_has_bits(return_type)) {
// nothing to do
} else if (return_type->id == TypeTableEntryIdPointer || return_type->id == TypeTableEntryIdFn) {
} else if (type_is_codegen_pointer(return_type)) {
addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
} else if (handle_is_ptr(return_type) &&
calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc))
Expand Down Expand Up @@ -2789,7 +2789,7 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, TypeTableEntry *maybe_type, LLV
if (child_type->zero_bits) {
return maybe_handle;
} else {
bool maybe_is_ptr = (child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn);
bool maybe_is_ptr = type_is_codegen_pointer(child_type);
if (maybe_is_ptr) {
return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), "");
} else {
Expand Down Expand Up @@ -2829,7 +2829,7 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
if (child_type->zero_bits) {
return nullptr;
} else {
bool maybe_is_ptr = (child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn);
bool maybe_is_ptr = type_is_codegen_pointer(child_type);
if (maybe_is_ptr) {
return maybe_ptr;
} else {
Expand Down Expand Up @@ -3052,6 +3052,10 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
{
align_bytes = target_type->data.maybe.child_type->data.fn.fn_type_id.alignment;
ptr_val = target_val;
} else if (target_type->id == TypeTableEntryIdMaybe &&
target_type->data.maybe.child_type->id == TypeTableEntryIdPromise)
{
zig_panic("TODO audit this function");
} else if (target_type->id == TypeTableEntryIdStruct && target_type->data.structure.is_slice) {
TypeTableEntry *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index].type_entry;
align_bytes = slice_ptr_type->data.pointer.alignment;
Expand Down Expand Up @@ -3522,9 +3526,7 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I
}

LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);
if (child_type->id == TypeTableEntryIdPointer ||
child_type->id == TypeTableEntryIdFn)
{
if (type_is_codegen_pointer(child_type)) {
return payload_val;
}

Expand Down Expand Up @@ -3716,6 +3718,22 @@ static LLVMValueRef ir_render_coro_alloc_fail(CodeGen *g, IrExecutable *executab
zig_panic("TODO ir_render_coro_alloc_fail");
}

static LLVMValueRef ir_render_coro_suspend(CodeGen *g, IrExecutable *executable, IrInstructionCoroSuspend *instruction) {
zig_panic("TODO ir_render_coro_suspend");
}

static LLVMValueRef ir_render_coro_end(CodeGen *g, IrExecutable *executable, IrInstructionCoroEnd *instruction) {
zig_panic("TODO ir_render_coro_end");
}

static LLVMValueRef ir_render_coro_free(CodeGen *g, IrExecutable *executable, IrInstructionCoroFree *instruction) {
zig_panic("TODO ir_render_coro_free");
}

static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable, IrInstructionCoroResume *instruction) {
zig_panic("TODO ir_render_coro_resume");
}

static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
AstNode *source_node = instruction->source_node;
Scope *scope = instruction->scope;
Expand Down Expand Up @@ -3911,6 +3929,14 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_coro_begin(g, executable, (IrInstructionCoroBegin *)instruction);
case IrInstructionIdCoroAllocFail:
return ir_render_coro_alloc_fail(g, executable, (IrInstructionCoroAllocFail *)instruction);
case IrInstructionIdCoroSuspend:
return ir_render_coro_suspend(g, executable, (IrInstructionCoroSuspend *)instruction);
case IrInstructionIdCoroEnd:
return ir_render_coro_end(g, executable, (IrInstructionCoroEnd *)instruction);
case IrInstructionIdCoroFree:
return ir_render_coro_free(g, executable, (IrInstructionCoroFree *)instruction);
case IrInstructionIdCoroResume:
return ir_render_coro_resume(g, executable, (IrInstructionCoroResume *)instruction);
}
zig_unreachable();
}
Expand Down Expand Up @@ -4155,9 +4181,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
TypeTableEntry *child_type = type_entry->data.maybe.child_type;
if (child_type->zero_bits) {
return LLVMConstInt(LLVMInt1Type(), const_val->data.x_maybe ? 1 : 0, false);
} else if (child_type->id == TypeTableEntryIdPointer ||
child_type->id == TypeTableEntryIdFn)
{
} else if (type_is_codegen_pointer(child_type)) {
if (const_val->data.x_maybe) {
return gen_const_val(g, const_val->data.x_maybe, "");
} else {
Expand Down Expand Up @@ -6085,9 +6109,7 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf
if (child_type->zero_bits) {
buf_init_from_str(out_buf, "bool");
return;
} else if (child_type->id == TypeTableEntryIdPointer ||
child_type->id == TypeTableEntryIdFn)
{
} else if (type_is_codegen_pointer(child_type)) {
return get_c_type(g, gen_h, child_type, out_buf);
} else {
zig_unreachable();
Expand Down
Loading

0 comments on commit 99985ad

Please sign in to comment.