From 292c8150b47f3e6fb65125e08a3b3243dc655c5c Mon Sep 17 00:00:00 2001 From: Dale Weiler Date: Sat, 23 Nov 2013 06:57:40 -0500 Subject: [PATCH] Resolve undefined functions to compiler builtins if they exist. --- doc/gmqcc.1 | 6 ++++++ gmqcc.ini.example | 8 ++++++++ opts.c | 1 + opts.def | 1 + parser.c | 22 ++++++++++++++++++++++ 5 files changed, 38 insertions(+) diff --git a/doc/gmqcc.1 b/doc/gmqcc.1 index 758e08d..2a205bb 100644 --- a/doc/gmqcc.1 +++ b/doc/gmqcc.1 @@ -338,6 +338,12 @@ for QuakeWorld to compile it needs to be treated as a warning instead, as such this warning only works when -std=qcc. .It Fl W Ns Cm directive-inmacro Warn about the use of preprocessor directives inside macros. +.It Fl W Ns Cm builtins +When using a function that is not explicitly defined, the compiler +will search its intrinsics table for something that matches that +function name by appending "__builtin_" to it. This behaviour may +be unexpected, so enabling this will produce a diagnostic when +such a function is resolved to a builtin. .El .Sh COMPILE FLAGS .Bl -tag -width Ds diff --git a/gmqcc.ini.example b/gmqcc.ini.example index acff3b3..0a263df 100644 --- a/gmqcc.ini.example +++ b/gmqcc.ini.example @@ -537,6 +537,14 @@ DIRECTIVE_INMACRO = true + #When using a function that is not explicitly defined, the compiler + #will search its intrinsics table for something that matches that + #function name by appending "__builtin_" to it. This behaviour may + #be unexpected, so enabling this will produce a diagnostic when + #such a function is resolved to a builtin. + + BUILTINS = true + [optimizations] #Some general peephole optimizations. For instance the code `a = b diff --git a/opts.c b/opts.c index e50bd74..e54ec57 100644 --- a/opts.c +++ b/opts.c @@ -92,6 +92,7 @@ static void opts_setdefault(void) { opts_set(opts.warn, WARN_PARENTHESIS, true); opts_set(opts.warn, WARN_CONST_OVERWRITE, true); opts_set(opts.warn, WARN_DIRECTIVE_INMACRO, true); + opts_set(opts.warn, WARN_BUILTINS, true); /* flags */ opts_set(opts.flags, ADJUST_VECTOR_FIELDS, true); diff --git a/opts.def b/opts.def index 57625dd..b209988 100644 --- a/opts.def +++ b/opts.def @@ -96,6 +96,7 @@ GMQCC_DEFINE_FLAG(BREAKDEF) GMQCC_DEFINE_FLAG(CONST_OVERWRITE) GMQCC_DEFINE_FLAG(DIRECTIVE_INMACRO) + GMQCC_DEFINE_FLAG(BUILTINS) #endif #ifdef GMQCC_TYPE_OPTIMIZATIONS diff --git a/parser.c b/parser.c index f030572..bb860a4 100644 --- a/parser.c +++ b/parser.c @@ -1575,6 +1575,8 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels) if (!var && !strcmp(parser_tokval(parser), "__FUNC__")) var = (ast_expression*)fold_constgen_string(parser->fold, parser->function->name, false); if (!var) { + char *tryintrinsic = NULL; + /* * now we try for the real intrinsic hashtable. If the string * begins with __builtin, we simply skip past it, otherwise we @@ -1584,6 +1586,26 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels) var = intrin_func(parser->intrin, parser_tokval(parser)); } + /* + * Try it as an instruction by appending __builtin_ to the token + * and emit a warning if an intrinsic function matching that + * name exists. + */ + if (!var) { + util_asprintf(&tryintrinsic, "__builtin_%s", parser_tokval(parser)); + if ((var = intrin_func(parser->intrin, tryintrinsic))) { + (void)!!compile_warning( + parser_ctx(parser), + WARN_BUILTINS, + "using implicitly defined builtin `%s' for `%s'", + tryintrinsic, + parser_tokval(parser) + ); + } + mem_d(tryintrinsic); + } + + if (!var) { char *correct = NULL; size_t i; -- 2.39.2