Skip to content

Commit 236bbe1

Browse files
committed
implement IR analysis for async function calls
See #727
1 parent 65a51b4 commit 236bbe1

File tree

8 files changed

+272
-54
lines changed

8 files changed

+272
-54
lines changed

doc/langref.html.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5645,7 +5645,7 @@ UseDecl = "use" Expression ";"
56455645

56465646
ExternDecl = "extern" option(String) (FnProto | VariableDeclaration) ";"
56475647

5648-
FnProto = option("nakedcc" | "stdcallcc" | "extern" | "async") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") TypeExpr
5648+
FnProto = option("nakedcc" | "stdcallcc" | "extern" | ("async" option("(" Expression ")"))) "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("!") TypeExpr
56495649

56505650
FnDef = option("inline" | "export") FnProto Block
56515651

src/all_types.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ struct AstNodeFnProto {
428428
AstNode *section_expr;
429429

430430
bool auto_err_set;
431+
AstNode *async_allocator_type;
431432
};
432433

433434
struct AstNodeFnDef {
@@ -935,6 +936,7 @@ struct FnTypeId {
935936
bool is_var_args;
936937
CallingConvention cc;
937938
uint32_t alignment;
939+
TypeTableEntry *async_allocator_type;
938940
};
939941

940942
uint32_t fn_type_id_hash(FnTypeId*);
@@ -1958,6 +1960,7 @@ enum IrInstructionId {
19581960
IrInstructionIdErrorReturnTrace,
19591961
IrInstructionIdErrorUnion,
19601962
IrInstructionIdCancel,
1963+
IrInstructionIdGetImplicitAllocator,
19611964
};
19621965

19631966
struct IrInstruction {
@@ -2803,6 +2806,10 @@ struct IrInstructionCancel {
28032806
IrInstruction *target;
28042807
};
28052808

2809+
struct IrInstructionGetImplicitAllocator {
2810+
IrInstruction base;
2811+
};
2812+
28062813
static const size_t slice_ptr_index = 0;
28072814
static const size_t slice_len_index = 1;
28082815

src/analyze.cpp

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -954,8 +954,13 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
954954

955955
// populate the name of the type
956956
buf_resize(&fn_type->name, 0);
957-
const char *cc_str = calling_convention_fn_type_str(fn_type->data.fn.fn_type_id.cc);
958-
buf_appendf(&fn_type->name, "%sfn(", cc_str);
957+
if (fn_type->data.fn.fn_type_id.cc == CallingConventionAsync) {
958+
buf_appendf(&fn_type->name, "async(%s) ", buf_ptr(&fn_type_id->async_allocator_type->name));
959+
} else {
960+
const char *cc_str = calling_convention_fn_type_str(fn_type->data.fn.fn_type_id.cc);
961+
buf_appendf(&fn_type->name, "%s", cc_str);
962+
}
963+
buf_appendf(&fn_type->name, "fn(");
959964
for (size_t i = 0; i < fn_type_id->param_count; i += 1) {
960965
FnTypeParamInfo *param_info = &fn_type_id->param_info[i];
961966

@@ -1126,7 +1131,16 @@ TypeTableEntry *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
11261131
TypeTableEntry *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
11271132
TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn);
11281133
fn_type->is_copyable = false;
1129-
buf_init_from_str(&fn_type->name, "fn(");
1134+
buf_resize(&fn_type->name, 0);
1135+
if (fn_type->data.fn.fn_type_id.cc == CallingConventionAsync) {
1136+
const char *async_allocator_type_str = (fn_type->data.fn.fn_type_id.async_allocator_type == nullptr) ?
1137+
"var" : buf_ptr(&fn_type_id->async_allocator_type->name);
1138+
buf_appendf(&fn_type->name, "async(%s) ", async_allocator_type_str);
1139+
} else {
1140+
const char *cc_str = calling_convention_fn_type_str(fn_type->data.fn.fn_type_id.cc);
1141+
buf_appendf(&fn_type->name, "%s", cc_str);
1142+
}
1143+
buf_appendf(&fn_type->name, "fn(");
11301144
size_t i = 0;
11311145
for (; i < fn_type_id->next_param_index; i += 1) {
11321146
const char *comma_str = (i == 0) ? "" : ",";
@@ -1515,6 +1529,16 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
15151529
break;
15161530
}
15171531

1532+
if (fn_type_id.cc == CallingConventionAsync) {
1533+
if (fn_proto->async_allocator_type == nullptr) {
1534+
return get_generic_fn_type(g, &fn_type_id);
1535+
}
1536+
fn_type_id.async_allocator_type = analyze_type_expr(g, child_scope, fn_proto->async_allocator_type);
1537+
if (type_is_invalid(fn_type_id.async_allocator_type)) {
1538+
return g->builtin_types.entry_invalid;
1539+
}
1540+
}
1541+
15181542
return get_fn_type(g, &fn_type_id);
15191543
}
15201544

@@ -3676,7 +3700,7 @@ AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index) {
36763700
return nullptr;
36773701
}
36783702

3679-
void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, VariableTableEntry **arg_vars) {
3703+
static void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, VariableTableEntry **arg_vars) {
36803704
TypeTableEntry *fn_type = fn_table_entry->type_entry;
36813705
assert(!fn_type->data.fn.is_generic);
36823706
FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
@@ -4242,6 +4266,7 @@ uint32_t fn_type_id_hash(FnTypeId *id) {
42424266
result += ((uint32_t)(id->cc)) * (uint32_t)3349388391;
42434267
result += id->is_var_args ? (uint32_t)1931444534 : 0;
42444268
result += hash_ptr(id->return_type);
4269+
result += hash_ptr(id->async_allocator_type);
42454270
result += id->alignment * 0xd3b3f3e2;
42464271
for (size_t i = 0; i < id->param_count; i += 1) {
42474272
FnTypeParamInfo *info = &id->param_info[i];
@@ -4256,7 +4281,8 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {
42564281
a->return_type != b->return_type ||
42574282
a->is_var_args != b->is_var_args ||
42584283
a->param_count != b->param_count ||
4259-
a->alignment != b->alignment)
4284+
a->alignment != b->alignment ||
4285+
a->async_allocator_type != b->async_allocator_type)
42604286
{
42614287
return false;
42624288
}

src/analyze.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *
9393
void eval_min_max_value_int(CodeGen *g, TypeTableEntry *int_type, BigInt *bigint, bool is_max);
9494

9595
void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val);
96-
void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, VariableTableEntry **arg_vars);
9796
void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_type_node);
9897

9998
ScopeBlock *create_block_scope(AstNode *node, Scope *parent);

src/codegen.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2521,6 +2521,10 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
25212521
}
25222522

25232523
FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
2524+
if (fn_type_id->cc == CallingConventionAsync) {
2525+
zig_panic("TODO codegen async function call");
2526+
}
2527+
25242528
TypeTableEntry *src_return_type = fn_type_id->return_type;
25252529
bool ret_has_bits = type_has_bits(src_return_type);
25262530
bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type);
@@ -3094,6 +3098,10 @@ static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrIns
30943098
zig_panic("TODO ir_render_cancel");
30953099
}
30963100

3101+
static LLVMValueRef ir_render_get_implicit_allocator(CodeGen *g, IrExecutable *executable, IrInstructionGetImplicitAllocator *instruction) {
3102+
zig_panic("TODO ir_render_get_implicit_allocator");
3103+
}
3104+
30973105
static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) {
30983106
switch (atomic_order) {
30993107
case AtomicOrderUnordered: return LLVMAtomicOrderingUnordered;
@@ -3752,6 +3760,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
37523760
case IrInstructionIdExport:
37533761
case IrInstructionIdErrorUnion:
37543762
zig_unreachable();
3763+
37553764
case IrInstructionIdReturn:
37563765
return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
37573766
case IrInstructionIdDeclVar:
@@ -3870,6 +3879,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
38703879
return ir_render_error_return_trace(g, executable, (IrInstructionErrorReturnTrace *)instruction);
38713880
case IrInstructionIdCancel:
38723881
return ir_render_cancel(g, executable, (IrInstructionCancel *)instruction);
3882+
case IrInstructionIdGetImplicitAllocator:
3883+
return ir_render_get_implicit_allocator(g, executable, (IrInstructionGetImplicitAllocator *)instruction);
38733884
}
38743885
zig_unreachable();
38753886
}

0 commit comments

Comments
 (0)