From 3618256c97a9988f7d623eeabb667010ca30656f Mon Sep 17 00:00:00 2001 From: Vexu Date: Mon, 9 Mar 2020 12:31:36 +0200 Subject: [PATCH] implement noasync scopes --- src/all_types.hpp | 6 +++++ src/analyze.cpp | 9 +++++++ src/analyze.hpp | 1 + src/codegen.cpp | 2 ++ src/ir.cpp | 52 +++++++++++++++++++++++++++++++++++++++-- test/compile_errors.zig | 9 +++++++ 6 files changed, 77 insertions(+), 2 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index ec839ffb4..14b99228c 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -2330,6 +2330,7 @@ enum ScopeId { ScopeIdRuntime, ScopeIdTypeOf, ScopeIdExpr, + ScopeIdNoAsync, }; struct Scope { @@ -2462,6 +2463,11 @@ struct ScopeCompTime { Scope base; }; +// This scope is created for a noasync expression. +// NodeTypeNoAsync +struct ScopeNoAsync { + Scope base; +}; // This scope is created for a function definition. // NodeTypeFnDef diff --git a/src/analyze.cpp b/src/analyze.cpp index c7bd7094d..d92400242 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -106,6 +106,7 @@ static ScopeExpr *find_expr_scope(Scope *scope) { case ScopeIdDecls: case ScopeIdFnDef: case ScopeIdCompTime: + case ScopeIdNoAsync: case ScopeIdVarDecl: case ScopeIdCImport: case ScopeIdSuspend: @@ -226,6 +227,12 @@ Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent) { return &scope->base; } +Scope *create_noasync_scope(CodeGen *g, AstNode *node, Scope *parent) { + ScopeNoAsync *scope = heap::c_allocator.create(); + init_scope(g, &scope->base, ScopeIdNoAsync, node, parent); + return &scope->base; +} + Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent) { ScopeTypeOf *scope = heap::c_allocator.create(); init_scope(g, &scope->base, ScopeIdTypeOf, node, parent); @@ -3755,6 +3762,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { case NodeTypeCompTime: preview_comptime_decl(g, node, decls_scope); break; + case NodeTypeNoAsync: case NodeTypeParamDecl: case NodeTypeReturnExpr: case NodeTypeDefer: @@ -6176,6 +6184,7 @@ static void mark_suspension_point(Scope *scope) { case ScopeIdDecls: case ScopeIdFnDef: case ScopeIdCompTime: + case ScopeIdNoAsync: case ScopeIdCImport: case ScopeIdSuspend: case ScopeIdTypeOf: diff --git a/src/analyze.hpp b/src/analyze.hpp index fded1e405..98d09d452 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -125,6 +125,7 @@ ScopeLoop *create_loop_scope(CodeGen *g, AstNode *node, Scope *parent); ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent); ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *fn_entry); Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent); +Scope *create_noasync_scope(CodeGen *g, AstNode *node, Scope *parent); Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstSrc *is_comptime); Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent); ScopeExpr *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent); diff --git a/src/codegen.cpp b/src/codegen.cpp index ef567c27a..52ac2e793 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -687,6 +687,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { case ScopeIdLoop: case ScopeIdSuspend: case ScopeIdCompTime: + case ScopeIdNoAsync: case ScopeIdRuntime: case ScopeIdTypeOf: case ScopeIdExpr: @@ -3934,6 +3935,7 @@ static void render_async_var_decls(CodeGen *g, Scope *scope) { case ScopeIdLoop: case ScopeIdSuspend: case ScopeIdCompTime: + case ScopeIdNoAsync: case ScopeIdRuntime: case ScopeIdTypeOf: case ScopeIdExpr: diff --git a/src/ir.cpp b/src/ir.cpp index 110778fb9..6a387e12e 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -4978,6 +4978,7 @@ static void ir_count_defers(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_ case ScopeIdLoop: case ScopeIdSuspend: case ScopeIdCompTime: + case ScopeIdNoAsync: case ScopeIdRuntime: case ScopeIdTypeOf: case ScopeIdExpr: @@ -5033,6 +5034,7 @@ static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope case ScopeIdLoop: case ScopeIdSuspend: case ScopeIdCompTime: + case ScopeIdNoAsync: case ScopeIdRuntime: case ScopeIdTypeOf: case ScopeIdExpr: @@ -7307,6 +7309,31 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod zig_unreachable(); } +static bool is_noasync_scope(Scope *scope) { + for (;;) { + switch (scope->id) { + case ScopeIdNoAsync: + return true; + case ScopeIdDefer: + case ScopeIdDeferExpr: + case ScopeIdDecls: + case ScopeIdFnDef: + case ScopeIdCompTime: + case ScopeIdVarDecl: + case ScopeIdCImport: + case ScopeIdSuspend: + return false; + case ScopeIdExpr: + case ScopeIdTypeOf: + case ScopeIdBlock: + case ScopeIdLoop: + case ScopeIdRuntime: + scope = scope->parent; + continue; + } + } +} + static IrInstSrc *ir_gen_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node, LVal lval, ResultLoc *result_loc) { @@ -7315,8 +7342,19 @@ static IrInstSrc *ir_gen_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node, if (node->data.fn_call_expr.modifier == CallModifierBuiltin) return ir_gen_builtin_fn_call(irb, scope, node, lval, result_loc); + bool is_noasync = is_noasync_scope(scope); + CallModifier modifier = node->data.fn_call_expr.modifier; + if (is_noasync) { + if (modifier == CallModifierAsync) { + add_node_error(irb->codegen, node, + buf_sprintf("async call in noasync scope")); + return irb->codegen->invalid_inst_src; + } + modifier = CallModifierNoAsync; + } + AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr; - return ir_gen_fn_call_with_args(irb, scope, node, fn_ref_node, node->data.fn_call_expr.modifier, + return ir_gen_fn_call_with_args(irb, scope, node, fn_ref_node, modifier, nullptr, node->data.fn_call_expr.params.items, node->data.fn_call_expr.params.length, lval, result_loc); } @@ -9170,6 +9208,14 @@ static IrInstSrc *ir_gen_comptime(IrBuilderSrc *irb, Scope *parent_scope, AstNod return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval, nullptr); } +static IrInstSrc *ir_gen_noasync(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval) { + assert(node->type == NodeTypeNoAsync); + + Scope *child_scope = create_noasync_scope(irb->codegen, node, parent_scope); + // purposefully pass null for result_loc and let EndExpr handle it + return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval, nullptr); +} + static IrInstSrc *ir_gen_return_from_block(IrBuilderSrc *irb, Scope *break_scope, AstNode *node, ScopeBlock *block_scope) { IrInstSrc *is_comptime; if (ir_should_inline(irb->exec, break_scope)) { @@ -9763,7 +9809,7 @@ static IrInstSrc *ir_gen_await_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no { assert(node->type == NodeTypeAwaitExpr); - bool is_noasync = node->data.await_expr.noasync_token != nullptr; + bool is_noasync = is_noasync_scope(scope); AstNode *expr_node = node->data.await_expr.expr; if (expr_node->type == NodeTypeFnCallExpr && expr_node->data.fn_call_expr.modifier == CallModifierBuiltin) { @@ -9938,6 +9984,8 @@ static IrInstSrc *ir_gen_node_raw(IrBuilderSrc *irb, AstNode *node, Scope *scope return ir_gen_switch_expr(irb, scope, node, lval, result_loc); case NodeTypeCompTime: return ir_expr_wrap(irb, scope, ir_gen_comptime(irb, scope, node, lval), result_loc); + case NodeTypeNoAsync: + return ir_expr_wrap(irb, scope, ir_gen_noasync(irb, scope, node, lval), result_loc); case NodeTypeErrorType: return ir_lval_wrap(irb, scope, ir_gen_error_type(irb, scope, node), lval, result_loc); case NodeTypeBreak: diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 717793baa..7021f8155 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2,6 +2,15 @@ const tests = @import("tests.zig"); const std = @import("std"); pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.addTest("combination of noasync and async", + \\export fn entry() void { + \\ noasync async foo(); + \\} + \\fn foo() void {} + , &[_][]const u8{ + "tmp.zig:2:13: error: async call in noasync scope", + }); + cases.addTest("@TypeOf with no arguments", \\export fn entry() void { \\ _ = @TypeOf();