From 3825eab989c0911326fd009b96c9768150ff6ac2 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 8 Sep 2018 12:16:03 +0100 Subject: [PATCH] Diverging procedures `proc() -> !` (no return) --- core/runtime/core.odin | 2 +- examples/demo/demo.odin | 10 ++++++++++ src/check_stmt.cpp | 6 +++++- src/check_type.cpp | 1 + src/ir_print.cpp | 7 +++++++ src/parser.cpp | 15 +++++++++++---- src/parser.hpp | 1 + src/types.cpp | 1 + 8 files changed, 37 insertions(+), 6 deletions(-) diff --git a/core/runtime/core.odin b/core/runtime/core.odin index df4dde9f9..4af46a163 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -299,7 +299,7 @@ foreign { debug_trap :: proc() ---; @(link_name="llvm.trap") - trap :: proc() ---; + trap :: proc() -> ! ---; @(link_name="llvm.readcyclecounter") read_cycle_counter :: proc() -> u64 ---; diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index 314475012..749133faa 100644 --- a/examples/demo/demo.odin +++ b/examples/demo/demo.odin @@ -785,6 +785,15 @@ bit_set_type :: proc() { } } +diverging_procedures :: proc() { + // Diverging procedures may never return + foo :: proc() -> ! { + fmt.println("I'm a diverging procedure"); + } + + foo(); +} + main :: proc() { when true { @@ -800,5 +809,6 @@ main :: proc() { cstring_example(); deprecated_attribute(); bit_set_type(); + diverging_procedures(); } } diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 290f2384a..f49f7d322 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1213,13 +1213,17 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { GB_ASSERT(proc_type->kind == Type_Proc); // Type *proc_type = c->proc_stack[c->proc_stack.count-1]; TypeProc *pt = &proc_type->Proc; + if (pt->no_return) { + error(rs->token, "Diverging procedures may not return"); + break; + } + isize result_count = 0; bool has_named_results = pt->has_named_results; if (pt->results) { result_count = proc_type->Proc.results->Tuple.variables.count; } - auto operands = array_make(heap_allocator(), 0, 2*rs->results.count); defer (array_free(&operands)); diff --git a/src/check_type.cpp b/src/check_type.cpp index 757fb7f37..d523b67de 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1951,6 +1951,7 @@ bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node, type->Proc.calling_convention = cc; type->Proc.is_polymorphic = pt->generic; type->Proc.specialization_count = specialization_count; + type->Proc.no_return = pt->no_return; if (param_count > 0) { Entity *end = params->Tuple.variables[param_count-1]; diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 441835922..5c6a9cb0a 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -1475,6 +1475,9 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { } ir_write_str_lit(f, ")"); + if (proc_type->Proc.no_return) { + ir_write_str_lit(f, " noreturn"); + } ir_print_debug_location(f, m, value, instr->block->proc); break; @@ -1624,6 +1627,10 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) { break; } + if (proc_type->no_return) { + ir_write_str_lit(f, "noreturn "); + } + if (m->generate_debug_info && proc->entity != nullptr && proc->body != nullptr) { irDebugInfo **di_ = map_get(&proc->module->debug_info, hash_pointer(proc->entity)); if (di_ != nullptr) { diff --git a/src/parser.cpp b/src/parser.cpp index ab8e3c65b..f0c5d0769 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -866,7 +866,7 @@ Ast *ast_poly_type(AstFile *f, Token token, Ast *type, Ast *specialization) { } -Ast *ast_proc_type(AstFile *f, Token token, Ast *params, Ast *results, u64 tags, ProcCallingConvention calling_convention, bool generic) { +Ast *ast_proc_type(AstFile *f, Token token, Ast *params, Ast *results, u64 tags, ProcCallingConvention calling_convention, bool generic, bool no_return) { Ast *result = alloc_ast_node(f, Ast_ProcType); result->ProcType.token = token; result->ProcType.params = params; @@ -874,6 +874,7 @@ Ast *ast_proc_type(AstFile *f, Token token, Ast *params, Ast *results, u64 tags, result->ProcType.tags = tags; result->ProcType.calling_convention = calling_convention; result->ProcType.generic = generic; + result->ProcType.no_return = no_return; return result; } @@ -2620,11 +2621,16 @@ Ast *parse_block_stmt(AstFile *f, b32 is_when) { -Ast *parse_results(AstFile *f) { +Ast *parse_results(AstFile *f, bool *no_return) { if (!allow_token(f, Token_ArrowRight)) { return nullptr; } + if (allow_token(f, Token_Not)) { + if (no_return) *no_return = true; + return nullptr; + } + isize prev_level = f->expr_level; defer (f->expr_level = prev_level); // f->expr_level = -1; @@ -2661,6 +2667,7 @@ ProcCallingConvention string_to_calling_convention(String s) { Ast *parse_proc_type(AstFile *f, Token proc_token) { Ast *params = nullptr; Ast *results = nullptr; + bool no_return = false; ProcCallingConvention cc = ProcCC_Invalid; if (f->curr_token.kind == Token_String) { @@ -2684,7 +2691,7 @@ Ast *parse_proc_type(AstFile *f, Token proc_token) { expect_token(f, Token_OpenParen); params = parse_field_list(f, nullptr, FieldFlag_Signature, Token_CloseParen, true, true); expect_token_after(f, Token_CloseParen, "parameter list"); - results = parse_results(f); + results = parse_results(f, &no_return); u64 tags = 0; parse_proc_tags(f, &tags); @@ -2710,7 +2717,7 @@ Ast *parse_proc_type(AstFile *f, Token proc_token) { } } end: - return ast_proc_type(f, proc_token, params, results, tags, cc, is_generic); + return ast_proc_type(f, proc_token, params, results, tags, cc, is_generic, no_return); } Ast *parse_var_type(AstFile *f, bool allow_ellipsis, bool allow_type_token) { diff --git a/src/parser.hpp b/src/parser.hpp index f05babfb4..97f484ee1 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -446,6 +446,7 @@ AST_KIND(_TypeBegin, "", bool) \ u64 tags; \ ProcCallingConvention calling_convention; \ bool generic; \ + bool no_return; \ }) \ AST_KIND(PointerType, "pointer type", struct { \ Token token; \ diff --git a/src/types.cpp b/src/types.cpp index 03b204467..2039dda3b 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -174,6 +174,7 @@ struct TypeUnion { bool is_poly_specialized; \ bool has_proc_default_values; \ bool has_named_results; \ + bool no_return; \ isize specialization_count; \ ProcCallingConvention calling_convention; \ }) \