diff --git a/src/c/apply.d b/src/c/apply.d index 520e83d64..1dd21511a 100644 --- a/src/c/apply.d +++ b/src/c/apply.d @@ -665,7 +665,7 @@ APPLY_fixed(cl_narg n, cl_object (*fn)(), cl_object *x) x[50],x[51],x[52],x[53],x[54],x[55],x[56], x[57],x[58],x[59],x[60],x[61],x[62],x[63]); default: - FEprogram_error("Too many arguments", 0); + FEprogram_error_noreturn("Too many arguments", 0); } } #endif diff --git a/src/c/cfun.d b/src/c/cfun.d index 6c1716832..f2118a05a 100644 --- a/src/c/cfun.d +++ b/src/c/cfun.d @@ -33,8 +33,9 @@ ecl_make_cfun(cl_objectfn_fixed c_function, cl_object name, cl_object cblock, in cf->cfunfixed.file = Cnil; cf->cfunfixed.file_position = MAKE_FIXNUM(-1); cf->cfunfixed.narg = narg; - if (narg < 0 || narg > C_ARGUMENTS_LIMIT) - FEprogram_error("ecl_make_cfun: function requires too many arguments.",0); + if (__builtin_expect(narg < 0 || narg > C_ARGUMENTS_LIMIT, 0)) + FEprogram_error_noreturn("ecl_make_cfun: function requires " + "too many arguments.",0); return cf; } diff --git a/src/c/cmpaux.d b/src/c/cmpaux.d index b0fb022b1..493fa2ae9 100644 --- a/src/c/cmpaux.d +++ b/src/c/cmpaux.d @@ -231,8 +231,9 @@ cl_parse_key( for (; args[0].narg > 1; ) { cl_object keyword = cl_va_arg(args); cl_object value = cl_va_arg(args); - if (!SYMBOLP(keyword)) - FEprogram_error("LAMBDA: Keyword expected, got ~S.", 1, keyword); + if (__builtin_expect(!SYMBOLP(keyword), 0)) + FEprogram_error_noreturn("LAMBDA: Keyword expected, got ~S.", + 1, keyword); if (rest != NULL) { rest = &ECL_CONS_CDR(*rest = ecl_list1(keyword)); rest = &ECL_CONS_CDR(*rest = ecl_list1(value)); @@ -254,10 +255,10 @@ cl_parse_key( unknown_keyword = keyword; goon:; } - if (args[0].narg != 0) - FEprogram_error("Odd number of keys", 0); - if (unknown_keyword != OBJNULL && !allow_other_keys && - (supplied_allow_other_keys == Cnil || - supplied_allow_other_keys == OBJNULL)) + if (__builtin_expect(args[0].narg != 0, 0)) + FEprogram_error_noreturn("Odd number of keys", 0); + if (__builtin_expect(unknown_keyword != OBJNULL && !allow_other_keys && + (supplied_allow_other_keys == Cnil || + supplied_allow_other_keys == OBJNULL), 0)) FEprogram_error("Unknown keyword ~S", 1, unknown_keyword); } diff --git a/src/c/compiler.d b/src/c/compiler.d index 08771c5d2..7f1af4ea3 100644 --- a/src/c/compiler.d +++ b/src/c/compiler.d @@ -216,8 +216,8 @@ asm_clear(cl_env_ptr env, cl_index h) { static void asm_op2(cl_env_ptr env, int code, int n) { - if (n < -MAX_OPARG || MAX_OPARG < n) - FEprogram_error("Argument to bytecode is too large", 0); + if (__builtin_expect(n < -MAX_OPARG || MAX_OPARG < n, 0)) + FEprogram_error_noreturn("Argument to bytecode is too large", 0); asm_op(env, code); asm_arg(env, n); } @@ -241,10 +241,10 @@ asm_jmp(cl_env_ptr env, int op) { static void asm_complete(cl_env_ptr env, int op, cl_index pc) { cl_fixnum delta = current_pc(env) - pc; /* [1] */ - if (op && (asm_ref(env, pc-1) != op)) - FEprogram_error("Non matching codes in ASM-COMPLETE2", 0); - else if (delta < -MAX_OPARG || delta > MAX_OPARG) - FEprogram_error("Too large jump", 0); + if (__builtin_expect(op && (asm_ref(env, pc-1) != op), 0)) + FEprogram_error_noreturn("Non matching codes in ASM-COMPLETE2", 0); + else if (__builtin_expect(delta < -MAX_OPARG || delta > MAX_OPARG, 0)) + FEprogram_error_noreturn("Too large jump", 0); else { #ifdef ECL_SMALL_BYTECODES unsigned char low = delta & 0xFF; @@ -329,19 +329,19 @@ static void assert_type_symbol(cl_object v) { if (type_of(v) != t_symbol) - FEprogram_error("Expected a symbol, found ~S.", 1, v); + FEprogram_error_noreturn("Expected a symbol, found ~S.", 1, v); } static void FEillegal_variable_name(cl_object v) { - FEprogram_error("Not a valid variable name ~S.", 1, v); + FEprogram_error_noreturn("Not a valid variable name ~S.", 1, v); } static void FEill_formed_input() { - FEprogram_error("Syntax error: list with too few elements or improperly terminated.", 0); + FEprogram_error_noreturn("Syntax error: list with too few elements or improperly terminated.", 0); } static int @@ -633,8 +633,9 @@ c_var_ref(cl_env_ptr env, cl_object var, int allow_symbol_macro, bool ensure_def symbol macro */ if (allow_symbol_macro) return -1; - FEprogram_error("Internal error: symbol macro ~S used as variable", - 1, var); + FEprogram_error_noreturn("Internal error: symbol macro ~S" + " used as variable", + 1, var); } else if (Null(special)) { return n; } else { @@ -845,7 +846,7 @@ c_block(cl_env_ptr env, cl_object body, int old_flags) { int flags; if (!SYMBOLP(name)) - FEprogram_error("BLOCK: Not a valid block name, ~S", 1, name); + FEprogram_error_noreturn("BLOCK: Not a valid block name, ~S", 1, name); old_env = *(env->c_env); pc = current_pc(env); @@ -939,14 +940,14 @@ c_funcall(cl_env_ptr env, cl_object args, int flags) { cl_object kind = ECL_CONS_CAR(name); if (kind == @'function') { if (cl_list_length(name) != MAKE_FIXNUM(2)) - FEprogram_error("FUNCALL: Invalid function name ~S", - 1, name); + FEprogram_error_noreturn("FUNCALL: Invalid function name ~S", + 1, name); return c_call(env, CONS(CADR(name), args), flags); } if (kind == @'quote') { if (cl_list_length(name) != MAKE_FIXNUM(2)) - FEprogram_error("FUNCALL: Invalid function name ~S", - 1, name); + FEprogram_error_noreturn("FUNCALL: Invalid function name ~S", + 1, name); return c_call(env, CONS(CADR(name), args), flags | FLAG_GLOBAL); } } @@ -972,7 +973,7 @@ perform_c_case(cl_env_ptr env, cl_object args, int flags) { return compile_body(env, Cnil, flags); clause = pop(&args); if (ATOM(clause)) - FEprogram_error("CASE: Illegal clause ~S.",1,clause); + FEprogram_error_noreturn("CASE: Illegal clause ~S.",1,clause); test = pop(&clause); } while (test == Cnil); @@ -1099,7 +1100,7 @@ c_cond(cl_env_ptr env, cl_object args, int flags) { return compile_form(env, Cnil, flags); clause = pop(&args); if (ATOM(clause)) - FEprogram_error("COND: Illegal clause ~S.",1,clause); + FEprogram_error_noreturn("COND: Illegal clause ~S.",1,clause); test = pop(&clause); flags = maybe_values_or_reg0(flags); if (Ct == test) { @@ -1337,7 +1338,7 @@ static int c_function(cl_env_ptr env, cl_object args, int flags) { cl_object function = pop(&args); if (!ecl_endp(args)) - FEprogram_error("FUNCTION: Too many arguments.", 0); + FEprogram_error_noreturn("FUNCTION: Too many arguments.", 0); return asm_function(env, function, flags); } @@ -1368,7 +1369,7 @@ asm_function(cl_env_ptr env, cl_object function, int flags) { return FLAG_REG0; } } - FEprogram_error("FUNCTION: Not a valid argument ~S.", 1, function); + FEprogram_error_noreturn("FUNCTION: Not a valid argument ~S.", 1, function); return FLAG_REG0; } @@ -1378,9 +1379,9 @@ c_go(cl_env_ptr env, cl_object args, int flags) { cl_object tag = pop(&args); cl_object info = c_tag_ref(env, tag, @':tag'); if (Null(info)) - FEprogram_error("GO: Unknown tag ~S.", 1, tag); + FEprogram_error_noreturn("GO: Unknown tag ~S.", 1, tag); if (!Null(args)) - FEprogram_error("GO: Too many arguments.",0); + FEprogram_error_noreturn("GO: Too many arguments.",0); asm_op2(env, OP_GO, fix(CAR(info))); asm_arg(env, fix(CDR(info))); return flags; @@ -1471,7 +1472,7 @@ c_let_leta(cl_env_ptr env, int op, cl_object args, int flags) { var = pop(&aux); value = pop_maybe_nil(&aux); if (!Null(aux)) - FEprogram_error("LET: Ill formed declaration.",0); + FEprogram_error_noreturn("LET: Ill formed declaration.",0); } if (!SYMBOLP(var)) FEillegal_variable_name(var); @@ -1511,7 +1512,7 @@ static int c_load_time_value(cl_env_ptr env, cl_object args, int flags) { if (cl_rest(args) != Cnil) - FEprogram_error("LOAD-TIME-VALUE: Too many arguments.", 0); + FEprogram_error_noreturn("LOAD-TIME-VALUE: Too many arguments.", 0); return c_values(env, args, flags); } @@ -1670,7 +1671,7 @@ c_multiple_value_setq(cl_env_ptr env, cl_object orig_args, int flags) { /* Compile values */ values = pop(&args); if (args != Cnil) - FEprogram_error("MULTIPLE-VALUE-SETQ: Too many arguments.", 0); + FEprogram_error_noreturn("MULTIPLE-VALUE-SETQ: Too many arguments.", 0); if (nvars == 0) { /* No variables */ return compile_form(env, cl_list(2, @'values', values), flags); @@ -1707,7 +1708,7 @@ c_not(cl_env_ptr env, cl_object args, int flags) { flags = compile_form(env, pop(&args), flags); } if (!Null(args)) - FEprogram_error("NOT/NULL: Too many arguments.", 0); + FEprogram_error_noreturn("NOT/NULL: Too many arguments.", 0); return flags; } @@ -1722,7 +1723,7 @@ c_nth_value(cl_env_ptr env, cl_object args, int flags) { compile_form(env, pop(&args), FLAG_PUSH); /* INDEX */ compile_form(env, pop(&args), FLAG_VALUES); /* VALUES */ if (args != Cnil) - FEprogram_error("NTH-VALUE: Too many arguments.",0); + FEprogram_error_noreturn("NTH-VALUE: Too many arguments.",0); asm_op(env, OP_NTHVAL); return FLAG_REG0; } @@ -1852,9 +1853,9 @@ c_return_aux(cl_env_ptr env, cl_object name, cl_object stmt, int flags) cl_object output = pop_maybe_nil(&stmt); if (!SYMBOLP(name) || Null(ndx)) - FEprogram_error("RETURN-FROM: Unknown block name ~S.", 1, name); + FEprogram_error_noreturn("RETURN-FROM: Unknown block name ~S.", 1, name); if (stmt != Cnil) - FEprogram_error("RETURN-FROM: Too many arguments.", 0); + FEprogram_error_noreturn("RETURN-FROM: Too many arguments.", 0); compile_form(env, output, FLAG_VALUES); asm_op2(env, OP_RETURN, fix(ndx)); return FLAG_VALUES; @@ -1916,7 +1917,7 @@ c_symbol_macrolet(cl_env_ptr env, cl_object args, int flags) if ((ecl_symbol_type(name) & (stp_special | stp_constant)) || c_var_ref(env, name,1,FALSE) == -2) { - FEprogram_error("SYMBOL-MACROLET: Symbol ~A cannot be \ + FEprogram_error_noreturn("SYMBOL-MACROLET: Symbol ~A cannot be \ declared special and appear in a symbol-macrolet.", 1, name); } definition = cl_list(2, arglist, cl_list(2, @'quote', expansion)); @@ -1986,7 +1987,7 @@ c_throw(cl_env_ptr env, cl_object stmt, int flags) { cl_object tag = pop(&stmt); cl_object form = pop(&stmt); if (stmt != Cnil) - FEprogram_error("THROW: Too many arguments.",0); + FEprogram_error_noreturn("THROW: Too many arguments.",0); compile_form(env, tag, FLAG_PUSH); compile_form(env, form, FLAG_VALUES); asm_op(env, OP_THROW); @@ -2109,7 +2110,7 @@ compile_form(cl_env_ptr env, cl_object stmt, int flags) { if (function == @'quote') { stmt = ECL_CONS_CDR(stmt); if (ATOM(stmt) || ECL_CONS_CDR(stmt) != Cnil) - FEprogram_error("QUOTE: Ill formed.",0); + FEprogram_error_noreturn("QUOTE: Ill formed.",0); stmt = ECL_CONS_CAR(stmt); goto QUOTED; } @@ -2138,7 +2139,7 @@ compile_form(cl_env_ptr env, cl_object stmt, int flags) { } } if (ecl_symbol_type(function) & stp_special_form) - FEprogram_error("BYTECOMPILE-FORM: Found no macroexpander \ + FEprogram_error_noreturn("BYTECOMPILE-FORM: Found no macroexpander \ for special form ~S.", 1, function); ORDINARY_CALL: /* @@ -2260,7 +2261,7 @@ static int c_cons(cl_env_ptr env, cl_object args, int flags) { if (ecl_length(args) != 2) { - FEprogram_error("CONS: Wrong number of arguments", 0); + FEprogram_error_noreturn("CONS: Wrong number of arguments", 0); } compile_form(env, cl_first(args), FLAG_PUSH); compile_form(env, cl_second(args), FLAG_REG0); @@ -2273,7 +2274,7 @@ c_endp(cl_env_ptr env, cl_object args, int flags) { cl_object list = pop(&args); if (args != Cnil) { - FEprogram_error("ENDP: Too many arguments", 0); + FEprogram_error_noreturn("ENDP: Too many arguments", 0); } compile_form(env, list, FLAG_REG0); asm_op(env, OP_ENDP); @@ -2285,7 +2286,7 @@ c_car(cl_env_ptr env, cl_object args, int flags) { cl_object list = pop(&args); if (args != Cnil) { - FEprogram_error("CAR: Too many arguments", 0); + FEprogram_error_noreturn("CAR: Too many arguments", 0); } compile_form(env, list, FLAG_REG0); asm_op(env, OP_CAR); @@ -2297,7 +2298,7 @@ c_cdr(cl_env_ptr env, cl_object args, int flags) { cl_object list = pop(&args); if (args != Cnil) { - FEprogram_error("CDR: Too many arguments", 0); + FEprogram_error_noreturn("CDR: Too many arguments", 0); } compile_form(env, list, FLAG_REG0); asm_op(env, OP_CDR); @@ -2414,7 +2415,7 @@ si_process_lambda(cl_object lambda) cl_object lambda_list, body; if (ATOM(lambda)) - FEprogram_error("LAMBDA: No lambda list.", 0); + FEprogram_error_noreturn("LAMBDA: No lambda list.", 0); lambda_list = ECL_CONS_CAR(lambda); declarations = @si::process-declarations(2, CDR(lambda), Ct); @@ -2620,7 +2621,7 @@ REST: if (stage >= AT_REST) OUTPUT: if ((nreq+nopt+(!Null(rest))+nkey) >= CALL_ARGUMENTS_LIMIT) - FEprogram_error("LAMBDA: Argument list ist too long, ~S.", 1, + FEprogram_error_noreturn("LAMBDA: Argument list ist too long, ~S.", 1, org_lambda_list); @(return CONS(MAKE_FIXNUM(nreq), cl_nreverse(reqs)) CONS(MAKE_FIXNUM(nopt), cl_nreverse(opts)) @@ -2631,7 +2632,7 @@ OUTPUT: cl_nreverse(auxs)) ILLEGAL_LAMBDA: - FEprogram_error("LAMBDA: Illegal lambda list ~S.", 1, org_lambda_list); + FEprogram_error_noreturn("LAMBDA: Illegal lambda list ~S.", 1, org_lambda_list); } static void @@ -2683,7 +2684,7 @@ ecl_make_lambda(cl_env_ptr env, cl_object name, cl_object lambda) { /* Transform (SETF fname) => fname */ if (!Null(name) && Null(si_valid_function_name_p(name))) - FEprogram_error("LAMBDA: Not a valid function name ~S",1,name); + FEprogram_error_noreturn("LAMBDA: Not a valid function name ~S",1,name); /* We register as special variable a symbol which is not * to be used. We use this to mark the boundary of a function diff --git a/src/c/error.d b/src/c/error.d index 6c0626df3..99e736280 100644 --- a/src/c/error.d +++ b/src/c/error.d @@ -98,6 +98,31 @@ FEprogram_error(const char *s, int narg, ...) real_args); } +void +FEprogram_error_noreturn(const char *s, int narg, ...) +{ + cl_object real_args, text; + cl_va_list args; + cl_va_start(args, narg, narg, 0); + text = make_constant_base_string(s); + real_args = cl_grab_rest_args(args); + if (cl_boundp(@'si::*current-form*') != Cnil) { + /* When FEprogram_error is invoked from the compiler, we can + * provide information about the offending form. + */ + cl_object stmt = ecl_symbol_value(@'si::*current-form*'); + if (stmt != Cnil) { + real_args = @list(3, stmt, text, real_args); + text = make_constant_base_string("In form~%~S~%~?"); + } + } + si_signal_simple_error(4, + @'program-error', /* condition name */ + Cnil, /* not correctable */ + text, + real_args); +} + void FEcontrol_error(const char *s, int narg, ...) { diff --git a/src/c/eval.d b/src/c/eval.d index 06294e24c..4d4b4565c 100644 --- a/src/c/eval.d +++ b/src/c/eval.d @@ -153,9 +153,9 @@ cl_funcall(cl_narg narg, cl_object function, ...) ecl_stack_frame_push(frame, lastarg->frame.base[i]); } } else loop_for_in (lastarg) { - if (i >= CALL_ARGUMENTS_LIMIT) { + if (__builtin_expect(i >= CALL_ARGUMENTS_LIMIT, 0)) { ecl_stack_frame_close(frame); - FEprogram_error("CALL-ARGUMENTS-LIMIT exceeded",0); + FEprogram_error_noreturn("CALL-ARGUMENTS-LIMIT exceeded",0); } ecl_stack_frame_push(frame, CAR(lastarg)); i++; diff --git a/src/c/macros.d b/src/c/macros.d index dc4a6d91c..44a19ff0c 100644 --- a/src/c/macros.d +++ b/src/c/macros.d @@ -174,8 +174,8 @@ static cl_object when_macro(cl_object whole, cl_object env) { cl_object args = CDR(whole); - if (ecl_endp(args)) - FEprogram_error("Syntax error: ~S.", 1, whole); + if (__builtin_expect(ecl_endp(args), 0)) + FEprogram_error_noreturn("Syntax error: ~S.", 1, whole); return cl_list(3, @'if', CAR(args), CONS(@'progn', CDR(args))); } diff --git a/src/c/mapfun.d b/src/c/mapfun.d index 0f935b93c..bdc5a0602 100644 --- a/src/c/mapfun.d +++ b/src/c/mapfun.d @@ -19,15 +19,15 @@ #include #include -#define PREPARE_MAP(env, list, cdrs_frame, cars_frame, narg) \ - struct ecl_stack_frame frames_aux[2]; \ - const cl_object cdrs_frame = (cl_object)frames_aux; \ - const cl_object cars_frame = (cl_object)(frames_aux+1); \ - ECL_STACK_FRAME_FROM_VA_LIST(env,cdrs_frame,list); \ - ECL_STACK_FRAME_COPY(cars_frame, cdrs_frame); \ - narg = cars_frame->frame.size; \ - if (narg == 0) { \ - FEprogram_error("MAP*: Too few arguments", 0); \ +#define PREPARE_MAP(env, list, cdrs_frame, cars_frame, narg) \ + struct ecl_stack_frame frames_aux[2]; \ + const cl_object cdrs_frame = (cl_object)frames_aux; \ + const cl_object cars_frame = (cl_object)(frames_aux+1); \ + ECL_STACK_FRAME_FROM_VA_LIST(env,cdrs_frame,list); \ + ECL_STACK_FRAME_COPY(cars_frame, cdrs_frame); \ + narg = cars_frame->frame.size; \ + if (__builtin_expect(narg == 0, 0)) { \ + FEprogram_error_noreturn("MAP*: Too few arguments", 0); \ } @(defun mapcar (fun &rest lists) diff --git a/src/h/external.h b/src/h/external.h index 4a116da67..379424c5e 100755 --- a/src/h/external.h +++ b/src/h/external.h @@ -541,6 +541,7 @@ extern ECL_API cl_object cl_cerror _ARGS((cl_narg narg, cl_object cformat, cl_ob extern ECL_API void ecl_internal_error(const char *s) /*__attribute__((noreturn))*/; extern ECL_API void ecl_cs_overflow(void) /*__attribute__((noreturn))*/; extern ECL_API void FEprogram_error(const char *s, int narg, ...) /*__attribute__((noreturn))*/; +extern ECL_API void FEprogram_error_noreturn(const char *s, int narg, ...) __attribute__((noreturn)); extern ECL_API void FEcontrol_error(const char *s, int narg, ...) /*__attribute__((noreturn))*/; extern ECL_API void FEreader_error(const char *s, cl_object stream, int narg, ...) /*__attribute__((noreturn))*/; #define FEparse_error FEreader_error