aboutsummaryrefslogtreecommitdiff
path: root/src/analyze.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-07-25 00:03:06 -0400
committerAndrew Kelley <andrew@ziglang.org>2019-07-25 00:03:06 -0400
commitead2d32be871411685f846e604ec7e4253b9f25a (patch)
treef9e3f930aef5ed60d452c4cf20776879b086acf1 /src/analyze.cpp
parente220812f2f0fe2becd570308971f98e0290835db (diff)
downloadzig-ead2d32be871411685f846e604ec7e4253b9f25a.tar.gz
zig-ead2d32be871411685f846e604ec7e4253b9f25a.zip
calling an inferred async function
Diffstat (limited to 'src/analyze.cpp')
-rw-r--r--src/analyze.cpp220
1 files changed, 135 insertions, 85 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 957e61b198..c8e02a4771 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -1869,80 +1869,6 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) {
return ErrorNone;
}
-static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) {
- if (frame_type->data.frame.locals_struct != nullptr)
- return ErrorNone;
-
- ZigFn *fn = frame_type->data.frame.fn;
- switch (fn->anal_state) {
- case FnAnalStateInvalid:
- return ErrorSemanticAnalyzeFail;
- case FnAnalStateComplete:
- break;
- case FnAnalStateReady:
- analyze_fn_body(g, fn);
- if (fn->anal_state == FnAnalStateInvalid)
- return ErrorSemanticAnalyzeFail;
- break;
- case FnAnalStateProbing:
- add_node_error(g, fn->proto_node,
- buf_sprintf("cannot resolve '%s': function not fully analyzed yet",
- buf_ptr(&frame_type->name)));
- return ErrorSemanticAnalyzeFail;
- }
- // TODO iterate over fn->alloca_gen_list
- ZigList<ZigType *> field_types = {};
- ZigList<const char *> field_names = {};
-
- field_names.append("resume_index");
- field_types.append(g->builtin_types.entry_usize);
-
- FnTypeId *fn_type_id = &fn->type_entry->data.fn.fn_type_id;
- field_names.append("result");
- field_types.append(fn_type_id->return_type);
-
- for (size_t arg_i = 0; arg_i < fn_type_id->param_count; arg_i += 1) {
- FnTypeParamInfo *param_info = &fn_type_id->param_info[arg_i];
- AstNode *param_decl_node = get_param_decl_node(fn, arg_i);
- Buf *param_name;
- bool is_var_args = param_decl_node && param_decl_node->data.param_decl.is_var_args;
- if (param_decl_node && !is_var_args) {
- param_name = param_decl_node->data.param_decl.name;
- } else {
- param_name = buf_sprintf("arg%" ZIG_PRI_usize "", arg_i);
- }
- ZigType *param_type = param_info->type;
- field_names.append(buf_ptr(param_name));
- field_types.append(param_type);
- }
-
- for (size_t alloca_i = 0; alloca_i < fn->alloca_gen_list.length; alloca_i += 1) {
- IrInstructionAllocaGen *instruction = fn->alloca_gen_list.at(alloca_i);
- ZigType *ptr_type = instruction->base.value.type;
- assert(ptr_type->id == ZigTypeIdPointer);
- ZigType *child_type = ptr_type->data.pointer.child_type;
- if (!type_has_bits(child_type))
- continue;
- if (instruction->base.ref_count == 0)
- continue;
- if (instruction->base.value.special != ConstValSpecialRuntime) {
- if (const_ptr_pointee(nullptr, g, &instruction->base.value, nullptr)->special !=
- ConstValSpecialRuntime)
- {
- continue;
- }
- }
- field_names.append(instruction->name_hint);
- field_types.append(child_type);
- }
-
-
- assert(field_names.length == field_types.length);
- frame_type->data.frame.locals_struct = get_struct_type(g, buf_ptr(&frame_type->name),
- field_names.items, field_types.items, field_names.length);
- return ErrorNone;
-}
-
static bool type_is_valid_extern_enum_tag(CodeGen *g, ZigType *ty) {
// Only integer types are allowed by the C ABI
if(ty->id != ZigTypeIdInt)
@@ -3861,18 +3787,24 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn) {
}
for (size_t i = 0; i < fn->call_list.length; i += 1) {
- FnCall *call = &fn->call_list.at(i);
- if (call->callee->type_entry->data.fn.fn_type_id.cc != CallingConventionUnspecified)
+ IrInstructionCallGen *call = fn->call_list.at(i);
+ ZigFn *callee = call->fn_entry;
+ if (callee == nullptr) {
+ // TODO function pointer call here, could be anything
continue;
- assert(call->callee->anal_state == FnAnalStateComplete);
- analyze_fn_async(g, call->callee);
- if (call->callee->anal_state == FnAnalStateInvalid) {
+ }
+
+ if (callee->type_entry->data.fn.fn_type_id.cc != CallingConventionUnspecified)
+ continue;
+ assert(callee->anal_state == FnAnalStateComplete);
+ analyze_fn_async(g, callee);
+ if (callee->anal_state == FnAnalStateInvalid) {
fn->anal_state = FnAnalStateInvalid;
return;
}
- if (fn_is_async(call->callee)) {
- fn->inferred_async_node = call->source_node;
- fn->inferred_async_fn = call->callee;
+ if (fn_is_async(callee)) {
+ fn->inferred_async_node = call->base.source_node;
+ fn->inferred_async_fn = callee;
if (must_not_be_async) {
ErrorMsg *msg = add_node_error(g, fn->proto_node,
buf_sprintf("function with calling convention '%s' cannot be async",
@@ -5147,6 +5079,127 @@ Error ensure_complete_type(CodeGen *g, ZigType *type_entry) {
return type_resolve(g, type_entry, ResolveStatusSizeKnown);
}
+static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) {
+ if (frame_type->data.frame.locals_struct != nullptr)
+ return ErrorNone;
+
+ ZigFn *fn = frame_type->data.frame.fn;
+ switch (fn->anal_state) {
+ case FnAnalStateInvalid:
+ return ErrorSemanticAnalyzeFail;
+ case FnAnalStateComplete:
+ break;
+ case FnAnalStateReady:
+ analyze_fn_body(g, fn);
+ if (fn->anal_state == FnAnalStateInvalid)
+ return ErrorSemanticAnalyzeFail;
+ break;
+ case FnAnalStateProbing:
+ add_node_error(g, fn->proto_node,
+ buf_sprintf("cannot resolve '%s': function not fully analyzed yet",
+ buf_ptr(&frame_type->name)));
+ return ErrorSemanticAnalyzeFail;
+ }
+
+ for (size_t i = 0; i < fn->call_list.length; i += 1) {
+ IrInstructionCallGen *call = fn->call_list.at(i);
+ ZigFn *callee = call->fn_entry;
+ assert(callee != nullptr);
+
+ analyze_fn_body(g, callee);
+ if (callee->anal_state == FnAnalStateInvalid) {
+ frame_type->data.frame.locals_struct = g->builtin_types.entry_invalid;
+ return ErrorSemanticAnalyzeFail;
+ }
+ analyze_fn_async(g, callee);
+ if (!fn_is_async(callee))
+ continue;
+
+ IrBasicBlock *new_resume_block = allocate<IrBasicBlock>(1);
+ new_resume_block->name_hint = "CallResume";
+ new_resume_block->resume_index = fn->resume_blocks.length + coro_extra_resume_block_count;
+ fn->resume_blocks.append(new_resume_block);
+ call->resume_block = new_resume_block;
+ fn->analyzed_executable.basic_block_list.append(new_resume_block);
+
+ ZigType *callee_frame_type = get_coro_frame_type(g, callee);
+
+ IrInstructionAllocaGen *alloca_gen = allocate<IrInstructionAllocaGen>(1);
+ alloca_gen->base.id = IrInstructionIdAllocaGen;
+ alloca_gen->base.source_node = call->base.source_node;
+ alloca_gen->base.scope = call->base.scope;
+ alloca_gen->base.value.type = get_pointer_to_type(g, callee_frame_type, false);
+ alloca_gen->base.ref_count = 1;
+ alloca_gen->name_hint = "";
+ fn->alloca_gen_list.append(alloca_gen);
+ call->frame_result_loc = &alloca_gen->base;
+ }
+
+ ZigList<ZigType *> field_types = {};
+ ZigList<const char *> field_names = {};
+
+ field_names.append("resume_index");
+ field_types.append(g->builtin_types.entry_usize);
+
+ field_names.append("fn_ptr");
+ field_types.append(fn->type_entry);
+
+ field_names.append("awaiter");
+ field_types.append(g->builtin_types.entry_usize);
+
+ FnTypeId *fn_type_id = &fn->type_entry->data.fn.fn_type_id;
+ ZigType *ptr_return_type = get_pointer_to_type(g, fn_type_id->return_type, false);
+ field_names.append("result_ptr");
+ field_types.append(ptr_return_type);
+
+ field_names.append("result");
+ field_types.append(fn_type_id->return_type);
+
+ for (size_t arg_i = 0; arg_i < fn_type_id->param_count; arg_i += 1) {
+ FnTypeParamInfo *param_info = &fn_type_id->param_info[arg_i];
+ AstNode *param_decl_node = get_param_decl_node(fn, arg_i);
+ Buf *param_name;
+ bool is_var_args = param_decl_node && param_decl_node->data.param_decl.is_var_args;
+ if (param_decl_node && !is_var_args) {
+ param_name = param_decl_node->data.param_decl.name;
+ } else {
+ param_name = buf_sprintf("arg%" ZIG_PRI_usize "", arg_i);
+ }
+ ZigType *param_type = param_info->type;
+ field_names.append(buf_ptr(param_name));
+ field_types.append(param_type);
+ }
+
+ for (size_t alloca_i = 0; alloca_i < fn->alloca_gen_list.length; alloca_i += 1) {
+ IrInstructionAllocaGen *instruction = fn->alloca_gen_list.at(alloca_i);
+ ZigType *ptr_type = instruction->base.value.type;
+ assert(ptr_type->id == ZigTypeIdPointer);
+ ZigType *child_type = ptr_type->data.pointer.child_type;
+ if (!type_has_bits(child_type))
+ continue;
+ if (instruction->base.ref_count == 0)
+ continue;
+ if (instruction->base.value.special != ConstValSpecialRuntime) {
+ if (const_ptr_pointee(nullptr, g, &instruction->base.value, nullptr)->special !=
+ ConstValSpecialRuntime)
+ {
+ continue;
+ }
+ }
+ field_names.append(instruction->name_hint);
+ field_types.append(child_type);
+ }
+
+
+ assert(field_names.length == field_types.length);
+ frame_type->data.frame.locals_struct = get_struct_type(g, buf_ptr(&frame_type->name),
+ field_names.items, field_types.items, field_names.length);
+ frame_type->abi_size = frame_type->data.frame.locals_struct->abi_size;
+ frame_type->abi_align = frame_type->data.frame.locals_struct->abi_align;
+ frame_type->size_in_bits = frame_type->data.frame.locals_struct->size_in_bits;
+ return ErrorNone;
+}
+
Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
if (type_is_invalid(ty))
return ErrorSemanticAnalyzeFail;
@@ -7343,9 +7396,6 @@ static void resolve_llvm_types_coro_frame(CodeGen *g, ZigType *frame_type, Resol
resolve_llvm_types_struct(g, frame_type->data.frame.locals_struct, wanted_resolve_status);
frame_type->llvm_type = frame_type->data.frame.locals_struct->llvm_type;
frame_type->llvm_di_type = frame_type->data.frame.locals_struct->llvm_di_type;
- frame_type->abi_size = frame_type->data.frame.locals_struct->abi_size;
- frame_type->abi_align = frame_type->data.frame.locals_struct->abi_align;
- frame_type->size_in_bits = frame_type->data.frame.locals_struct->size_in_bits;
}
static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {