diff --git a/src/ceval.h b/src/ceval.h index c1af6dde..a056f266 100644 --- a/src/ceval.h +++ b/src/ceval.h @@ -13,7 +13,7 @@ inline PyObject* VM::_run_top_frame(){ while(true){ #if DEBUG_EXTRA_CHECK - if(frame->id < base_id) UNREACHABLE(); + if(frame->id < base_id) FATAL_ERROR(); #endif try{ if(need_raise){ need_raise = false; _raise(); } @@ -498,7 +498,7 @@ __NEXT_STEP:; #if DEBUG_EXTRA_CHECK default: throw std::runtime_error(fmt(OP_NAMES[byte.op], " is not implemented")); #else - default: std::unreachable(); + default: UNREACHABLE(); #endif } #endif diff --git a/src/cffi.h b/src/cffi.h index 7e532117..1cb5e36b 100644 --- a/src/cffi.h +++ b/src/cffi.h @@ -312,7 +312,7 @@ struct Pointer{ CASE(double, f64); CASE(bool, bool); #undef CASE - default: UNREACHABLE(); + default: FATAL_ERROR(); } } diff --git a/src/common.h b/src/common.h index 370954b9..0745f216 100644 --- a/src/common.h +++ b/src/common.h @@ -51,8 +51,10 @@ #if _MSC_VER #define PK_ENABLE_COMPUTED_GOTO 0 +#define UNREACHABLE() __assume(0) #else #define PK_ENABLE_COMPUTED_GOTO 1 +#define UNREACHABLE() __builtin_unreachable() #endif #if defined(__EMSCRIPTEN__) || defined(__arm__) || defined(__i386__) @@ -89,9 +91,9 @@ struct Type { #define CPP_NOT_IMPLEMENTED() ([](VM* vm, Args& args) { vm->NotImplementedError(); return vm->None; }) #ifdef POCKETPY_H -#define UNREACHABLE() throw std::runtime_error( "L" + std::to_string(__LINE__) + " UNREACHABLE()!"); +#define FATAL_ERROR() throw std::runtime_error( "L" + std::to_string(__LINE__) + " FATAL_ERROR()!"); #else -#define UNREACHABLE() throw std::runtime_error( __FILE__ + std::string(":") + std::to_string(__LINE__) + " UNREACHABLE()!"); +#define FATAL_ERROR() throw std::runtime_error( __FILE__ + std::string(":") + std::to_string(__LINE__) + " FATAL_ERROR()!"); #endif inline const float kLocalsLoadFactor = 0.67f; diff --git a/src/compiler.h b/src/compiler.h index 7e9ef870..c56a65ef 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -267,7 +267,7 @@ class Compiler { case TK("*"): ctx()->s_expr.push(make_expr(ctx()->s_expr.popx())); break; - default: UNREACHABLE(); + default: FATAL_ERROR(); } } @@ -464,7 +464,7 @@ __SUBSCR_END: if(is_slice){ e->b = std::move(slice); }else{ - if(state != 1) UNREACHABLE(); + if(state != 1) FATAL_ERROR(); e->b = std::move(slice->start); } ctx()->s_expr.push(std::move(e)); @@ -936,7 +936,7 @@ public: } CodeObject_ compile(){ - if(used) UNREACHABLE(); + if(used) FATAL_ERROR(); used = true; tokens = lexer->run(); diff --git a/src/expr.h b/src/expr.h index d2506da6..d0a53745 100644 --- a/src/expr.h +++ b/src/expr.h @@ -55,7 +55,7 @@ struct CodeEmitContext{ if(co->blocks[curr_block_i].type == FOR_LOOP) for_loop_depth--; co->blocks[curr_block_i].end = co->codes.size(); curr_block_i = co->blocks[curr_block_i].parent; - if(curr_block_i < 0) UNREACHABLE(); + if(curr_block_i < 0) FATAL_ERROR(); } // clear the expression stack and generate bytecode @@ -137,7 +137,7 @@ struct NameExpr: Expr{ case NAME_GLOBAL: ctx->emit(OP_DELETE_GLOBAL, index, line); break; - default: UNREACHABLE(); break; + default: FATAL_ERROR(); break; } return true; } @@ -155,7 +155,7 @@ struct NameExpr: Expr{ case NAME_GLOBAL: ctx->emit(OP_STORE_GLOBAL, index, line); break; - default: UNREACHABLE(); break; + default: FATAL_ERROR(); break; } return true; } @@ -229,7 +229,7 @@ struct Literal0Expr: Expr{ case TK("True"): ctx->emit(OP_LOAD_TRUE, BC_NOARG, line); break; case TK("False"): ctx->emit(OP_LOAD_FALSE, BC_NOARG, line); break; case TK("..."): ctx->emit(OP_LOAD_ELLIPSIS, BC_NOARG, line); break; - default: UNREACHABLE(); + default: FATAL_ERROR(); } } @@ -254,7 +254,7 @@ struct LiteralExpr: Expr{ return s.str(); } - UNREACHABLE(); + FATAL_ERROR(); } PyObject* to_object(CodeEmitContext* ctx){ @@ -274,7 +274,7 @@ struct LiteralExpr: Expr{ void emit(CodeEmitContext* ctx) override { PyObject* obj = to_object(ctx); - if(obj == nullptr) UNREACHABLE(); + if(obj == nullptr) FATAL_ERROR(); int index = ctx->add_const(obj); ctx->emit(OP_LOAD_CONST, index, line); } @@ -448,7 +448,7 @@ struct CompExpr: Expr{ ctx->emit(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE); bool ok = vars->emit_store(ctx); // this error occurs in `vars` instead of this line, but...nevermind - if(!ok) UNREACHABLE(); // TODO: raise a SyntaxError instead + if(!ok) FATAL_ERROR(); // TODO: raise a SyntaxError instead if(cond){ cond->emit(ctx); int patch = ctx->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE); @@ -672,7 +672,7 @@ struct BinaryExpr: Expr{ case TK("&"): ctx->emit(OP_BITWISE_AND, BC_NOARG, line); break; case TK("|"): ctx->emit(OP_BITWISE_OR, BC_NOARG, line); break; case TK("^"): ctx->emit(OP_BITWISE_XOR, BC_NOARG, line); break; - default: UNREACHABLE(); + default: FATAL_ERROR(); } } }; diff --git a/src/gc.h b/src/gc.h index a35f021a..b1c5808d 100644 --- a/src/gc.h +++ b/src/gc.h @@ -101,7 +101,7 @@ struct ManagedHeap{ } int collect(){ - if(_gc_lock_counter > 0) UNREACHABLE(); + if(_gc_lock_counter > 0) FATAL_ERROR(); mark(); int freed = sweep(); return freed; diff --git a/src/lexer.h b/src/lexer.h index 88698729..89f05147 100644 --- a/src/lexer.h +++ b/src/lexer.h @@ -38,7 +38,7 @@ constexpr TokenIndex TK(const char token[]) { while(*i && *j && *i == *j) { i++; j++;} if(*i == *j) return k; } - UNREACHABLE(); + FATAL_ERROR(); } #define TK_STR(t) kTokens[t] @@ -344,7 +344,7 @@ struct Lexer { } else { add_token(TK("@num"), S_TO_INT(m[0], &size, base)); } - if (size != m.length()) UNREACHABLE(); + if (size != m.length()) FATAL_ERROR(); } }catch(std::exception& _){ SyntaxError("invalid number literal"); @@ -448,7 +448,7 @@ struct Lexer { case 2: SyntaxError("invalid utf8 sequence: " + std::string(1, c)); case 3: SyntaxError("@id contains invalid char"); break; case 4: SyntaxError("invalid JSON token"); break; - default: UNREACHABLE(); + default: FATAL_ERROR(); } return true; } @@ -494,7 +494,7 @@ struct Lexer { } std::vector run() { - if(used) UNREACHABLE(); + if(used) FATAL_ERROR(); used = true; while (lex_one_token()); return std::move(nexts); diff --git a/src/namedict.h b/src/namedict.h index 7e2866b9..c98e348e 100644 --- a/src/namedict.h +++ b/src/namedict.h @@ -119,7 +119,7 @@ while(!_items[i].first.empty()) { \ if(old_items[i].first.empty()) continue; bool ok; uint16_t j; HASH_PROBE(old_items[i].first, ok, j); - if(ok) UNREACHABLE(); + if(ok) FATAL_ERROR(); _items[j] = old_items[i]; } pool128.dealloc(old_items); diff --git a/src/obj.h b/src/obj.h index b4644379..c8c11d7a 100644 --- a/src/obj.h +++ b/src/obj.h @@ -183,7 +183,7 @@ inline bool is_type(PyObject* obj, Type type) { } \ static PyObject* register_class(VM* vm, PyObject* mod) { \ PyObject* type = vm->new_type_object(mod, #name, vm->tp_object); \ - if(OBJ_NAME(mod) != #mod) UNREACHABLE(); \ + if(OBJ_NAME(mod) != #mod) FATAL_ERROR(); \ T::_register(vm, mod, type); \ type->attr()._try_perfect_rehash(); \ return type; \ diff --git a/src/pocketpy.h b/src/pocketpy.h index c271e788..6251147d 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -978,7 +978,7 @@ extern "C" { case 'N': f_None(packet); return vm->None; } free(packet); - UNREACHABLE(); + FATAL_ERROR(); return vm->None; }); return strdup(f_header.c_str()); diff --git a/src/vm.h b/src/vm.h index f58a6ba5..b0316c0f 100644 --- a/src/vm.h +++ b/src/vm.h @@ -102,7 +102,7 @@ public: FrameId top_frame() { #if DEBUG_EXTRA_CHECK - if(callstack.empty()) UNREACHABLE(); + if(callstack.empty()) FATAL_ERROR(); #endif return FrameId(&callstack.data(), callstack.size()-1); } @@ -553,7 +553,7 @@ inline PyObject* VM::new_module(StrName name) { obj->attr().set(__name__, VAR(name.sv())); // we do not allow override in order to avoid memory leak // it is because Module objects are not garbage collected - if(_modules.contains(name)) UNREACHABLE(); + if(_modules.contains(name)) FATAL_ERROR(); _modules.set(name, obj); return obj; } @@ -639,7 +639,7 @@ inline void VM::init_builtin_types(){ tp_int = _new_type_object("int"); tp_float = _new_type_object("float"); - if(tp_int.index != kTpIntIndex || tp_float.index != kTpFloatIndex) UNREACHABLE(); + if(tp_int.index != kTpIntIndex || tp_float.index != kTpFloatIndex) FATAL_ERROR(); tp_bool = _new_type_object("bool"); tp_str = _new_type_object("str");