Skip to content

Commit 99985ad

Browse files
committed
implement Zig IR for async functions
See #727
1 parent ca1b77b commit 99985ad

File tree

6 files changed

+467
-54
lines changed

6 files changed

+467
-54
lines changed

src/all_types.hpp

+36
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,13 @@ struct IrExecutable {
5656
IrAnalyze *analysis;
5757
Scope *begin_scope;
5858
ZigList<Tld *> tld_list;
59+
5960
IrInstruction *coro_handle;
61+
IrInstruction *coro_awaiter_field_ptr;
62+
IrInstruction *coro_result_ptr_field_ptr;
63+
IrInstruction *implicit_allocator_ptr;
64+
IrBasicBlock *coro_early_final;
65+
IrBasicBlock *coro_normal_final;
6066
};
6167

6268
enum OutType {
@@ -1968,6 +1974,10 @@ enum IrInstructionId {
19681974
IrInstructionIdCoroSize,
19691975
IrInstructionIdCoroBegin,
19701976
IrInstructionIdCoroAllocFail,
1977+
IrInstructionIdCoroSuspend,
1978+
IrInstructionIdCoroEnd,
1979+
IrInstructionIdCoroFree,
1980+
IrInstructionIdCoroResume,
19711981
};
19721982

19731983
struct IrInstruction {
@@ -2819,6 +2829,8 @@ struct IrInstructionGetImplicitAllocator {
28192829

28202830
struct IrInstructionCoroId {
28212831
IrInstruction base;
2832+
2833+
IrInstruction *promise_ptr;
28222834
};
28232835

28242836
struct IrInstructionCoroAlloc {
@@ -2844,6 +2856,30 @@ struct IrInstructionCoroAllocFail {
28442856
IrInstruction *err_val;
28452857
};
28462858

2859+
struct IrInstructionCoroSuspend {
2860+
IrInstruction base;
2861+
2862+
IrInstruction *save_point;
2863+
IrInstruction *is_final;
2864+
};
2865+
2866+
struct IrInstructionCoroEnd {
2867+
IrInstruction base;
2868+
};
2869+
2870+
struct IrInstructionCoroFree {
2871+
IrInstruction base;
2872+
2873+
IrInstruction *coro_id;
2874+
IrInstruction *coro_handle;
2875+
};
2876+
2877+
struct IrInstructionCoroResume {
2878+
IrInstruction base;
2879+
2880+
IrInstruction *awaiter_handle;
2881+
};
2882+
28472883
static const size_t slice_ptr_index = 0;
28482884
static const size_t slice_len_index = 1;
28492885

src/analyze.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -475,9 +475,7 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
475475
if (child_type->zero_bits) {
476476
entry->type_ref = LLVMInt1Type();
477477
entry->di_type = g->builtin_types.entry_bool->di_type;
478-
} else if (child_type->id == TypeTableEntryIdPointer ||
479-
child_type->id == TypeTableEntryIdFn)
480-
{
478+
} else if (type_is_codegen_pointer(child_type)) {
481479
// this is an optimization but also is necessary for calling C
482480
// functions where all pointers are maybe pointers
483481
// function types are technically pointers
@@ -1262,7 +1260,7 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
12621260
case TypeTableEntryIdMaybe:
12631261
{
12641262
TypeTableEntry *child_type = type_entry->data.maybe.child_type;
1265-
return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn;
1263+
return type_is_codegen_pointer(child_type);
12661264
}
12671265
case TypeTableEntryIdEnum:
12681266
return type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr;
@@ -1673,6 +1671,8 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f
16731671
field->src_index = i;
16741672
field->gen_index = i;
16751673

1674+
assert(type_has_bits(field->type_entry));
1675+
16761676
auto prev_entry = struct_type->data.structure.fields_by_name.put_unique(field->name, field);
16771677
assert(prev_entry == nullptr);
16781678
}
@@ -3669,9 +3669,11 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
36693669
TypeTableEntry *get_codegen_ptr_type(TypeTableEntry *type) {
36703670
if (type->id == TypeTableEntryIdPointer) return type;
36713671
if (type->id == TypeTableEntryIdFn) return type;
3672+
if (type->id == TypeTableEntryIdPromise) return type;
36723673
if (type->id == TypeTableEntryIdMaybe) {
36733674
if (type->data.maybe.child_type->id == TypeTableEntryIdPointer) return type->data.maybe.child_type;
36743675
if (type->data.maybe.child_type->id == TypeTableEntryIdFn) return type->data.maybe.child_type;
3676+
if (type->data.maybe.child_type->id == TypeTableEntryIdPromise) return type->data.maybe.child_type;
36753677
}
36763678
return nullptr;
36773679
}

src/analyze.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ VariableTableEntry *find_variable(CodeGen *g, Scope *orig_context, Buf *name);
5151
Tld *find_decl(CodeGen *g, Scope *scope, Buf *name);
5252
void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *source_node);
5353
bool type_is_codegen_pointer(TypeTableEntry *type);
54+
5455
TypeTableEntry *get_codegen_ptr_type(TypeTableEntry *type);
5556
uint32_t get_ptr_align(TypeTableEntry *type);
5657
TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry);

src/codegen.cpp

+34-12
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
542542

543543
if (!type_has_bits(return_type)) {
544544
// nothing to do
545-
} else if (return_type->id == TypeTableEntryIdPointer || return_type->id == TypeTableEntryIdFn) {
545+
} else if (type_is_codegen_pointer(return_type)) {
546546
addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
547547
} else if (handle_is_ptr(return_type) &&
548548
calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc))
@@ -2789,7 +2789,7 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, TypeTableEntry *maybe_type, LLV
27892789
if (child_type->zero_bits) {
27902790
return maybe_handle;
27912791
} else {
2792-
bool maybe_is_ptr = (child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn);
2792+
bool maybe_is_ptr = type_is_codegen_pointer(child_type);
27932793
if (maybe_is_ptr) {
27942794
return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), "");
27952795
} else {
@@ -2829,7 +2829,7 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
28292829
if (child_type->zero_bits) {
28302830
return nullptr;
28312831
} else {
2832-
bool maybe_is_ptr = (child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn);
2832+
bool maybe_is_ptr = type_is_codegen_pointer(child_type);
28332833
if (maybe_is_ptr) {
28342834
return maybe_ptr;
28352835
} else {
@@ -3052,6 +3052,10 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
30523052
{
30533053
align_bytes = target_type->data.maybe.child_type->data.fn.fn_type_id.alignment;
30543054
ptr_val = target_val;
3055+
} else if (target_type->id == TypeTableEntryIdMaybe &&
3056+
target_type->data.maybe.child_type->id == TypeTableEntryIdPromise)
3057+
{
3058+
zig_panic("TODO audit this function");
30553059
} else if (target_type->id == TypeTableEntryIdStruct && target_type->data.structure.is_slice) {
30563060
TypeTableEntry *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index].type_entry;
30573061
align_bytes = slice_ptr_type->data.pointer.alignment;
@@ -3522,9 +3526,7 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I
35223526
}
35233527

35243528
LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);
3525-
if (child_type->id == TypeTableEntryIdPointer ||
3526-
child_type->id == TypeTableEntryIdFn)
3527-
{
3529+
if (type_is_codegen_pointer(child_type)) {
35283530
return payload_val;
35293531
}
35303532

@@ -3716,6 +3718,22 @@ static LLVMValueRef ir_render_coro_alloc_fail(CodeGen *g, IrExecutable *executab
37163718
zig_panic("TODO ir_render_coro_alloc_fail");
37173719
}
37183720

3721+
static LLVMValueRef ir_render_coro_suspend(CodeGen *g, IrExecutable *executable, IrInstructionCoroSuspend *instruction) {
3722+
zig_panic("TODO ir_render_coro_suspend");
3723+
}
3724+
3725+
static LLVMValueRef ir_render_coro_end(CodeGen *g, IrExecutable *executable, IrInstructionCoroEnd *instruction) {
3726+
zig_panic("TODO ir_render_coro_end");
3727+
}
3728+
3729+
static LLVMValueRef ir_render_coro_free(CodeGen *g, IrExecutable *executable, IrInstructionCoroFree *instruction) {
3730+
zig_panic("TODO ir_render_coro_free");
3731+
}
3732+
3733+
static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable, IrInstructionCoroResume *instruction) {
3734+
zig_panic("TODO ir_render_coro_resume");
3735+
}
3736+
37193737
static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
37203738
AstNode *source_node = instruction->source_node;
37213739
Scope *scope = instruction->scope;
@@ -3911,6 +3929,14 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
39113929
return ir_render_coro_begin(g, executable, (IrInstructionCoroBegin *)instruction);
39123930
case IrInstructionIdCoroAllocFail:
39133931
return ir_render_coro_alloc_fail(g, executable, (IrInstructionCoroAllocFail *)instruction);
3932+
case IrInstructionIdCoroSuspend:
3933+
return ir_render_coro_suspend(g, executable, (IrInstructionCoroSuspend *)instruction);
3934+
case IrInstructionIdCoroEnd:
3935+
return ir_render_coro_end(g, executable, (IrInstructionCoroEnd *)instruction);
3936+
case IrInstructionIdCoroFree:
3937+
return ir_render_coro_free(g, executable, (IrInstructionCoroFree *)instruction);
3938+
case IrInstructionIdCoroResume:
3939+
return ir_render_coro_resume(g, executable, (IrInstructionCoroResume *)instruction);
39143940
}
39153941
zig_unreachable();
39163942
}
@@ -4155,9 +4181,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
41554181
TypeTableEntry *child_type = type_entry->data.maybe.child_type;
41564182
if (child_type->zero_bits) {
41574183
return LLVMConstInt(LLVMInt1Type(), const_val->data.x_maybe ? 1 : 0, false);
4158-
} else if (child_type->id == TypeTableEntryIdPointer ||
4159-
child_type->id == TypeTableEntryIdFn)
4160-
{
4184+
} else if (type_is_codegen_pointer(child_type)) {
41614185
if (const_val->data.x_maybe) {
41624186
return gen_const_val(g, const_val->data.x_maybe, "");
41634187
} else {
@@ -6085,9 +6109,7 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf
60856109
if (child_type->zero_bits) {
60866110
buf_init_from_str(out_buf, "bool");
60876111
return;
6088-
} else if (child_type->id == TypeTableEntryIdPointer ||
6089-
child_type->id == TypeTableEntryIdFn)
6090-
{
6112+
} else if (type_is_codegen_pointer(child_type)) {
60916113
return get_c_type(g, gen_h, child_type, out_buf);
60926114
} else {
60936115
zig_unreachable();

0 commit comments

Comments
 (0)