diff --git a/gcc/jit/docs/topics/contexts.rst b/gcc/jit/docs/topics/contexts.rst index 10a0e50f9f620df4ec9de18b661dc4fca144c36b..ba075cd71d351c646d7b4d95bfe68cb45a26b54e 100644 --- a/gcc/jit/docs/topics/contexts.rst +++ b/gcc/jit/docs/topics/contexts.rst @@ -317,13 +317,18 @@ String Options copy of the underlying string, so it is valid to pass in a pointer to an on-stack buffer. - There is just one string option specified this way: - .. macro:: GCC_JIT_STR_OPTION_PROGNAME The name of the program, for use as a prefix when printing error messages to stderr. If `NULL`, or default, "libgccjit.so" is used. + .. macro:: GCC_JIT_STR_OPTION_SPECIAL_CHARS_IN_FUNC_NAMES + + Alphabetic ASCII characters and underscores are always valid. Numeric + ASCII characters are always valid after the initial character of the + string. Use this entrypoint to specify additional ASCII characters that + are valid throughout function names (ex.: ".$"). + Boolean options *************** diff --git a/gcc/jit/jit-recording.cc b/gcc/jit/jit-recording.cc index 7cbe383c79db85e3012e1c63a537419233a2cfb8..90ac5bdafffcacdae16b28d728b5367277d5f434 100644 --- a/gcc/jit/jit-recording.cc +++ b/gcc/jit/jit-recording.cc @@ -1424,6 +1424,18 @@ recording::context::set_str_option (enum gcc_jit_str_option opt, log_str_option (opt); } +const char* +recording::context::get_str_option (enum gcc_jit_str_option opt) +{ + if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS) + { + add_error (NULL, + "unrecognized (enum gcc_jit_str_option) value: %i", opt); + return NULL; + } + return m_str_options[opt]; +} + /* Set the given integer option for this context, or add an error if it's not recognized. @@ -1765,7 +1777,8 @@ recording::context::dump_to_file (const char *path, bool update_locations) static const char * const str_option_reproducer_strings[GCC_JIT_NUM_STR_OPTIONS] = { - "GCC_JIT_STR_OPTION_PROGNAME" + "GCC_JIT_STR_OPTION_PROGNAME", + "GCC_JIT_STR_OPTION_SPECIAL_CHARS_IN_FUNC_NAMES", }; static const char * const @@ -1782,7 +1795,7 @@ static const char * const "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY", "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING", "GCC_JIT_BOOL_OPTION_SELFCHECK_GC", - "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES" + "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES", }; static const char * const diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h index e5a920fac4995557d95c0e68811599ba0352d99f..13c2ea73502793407c20ff9e3ac24a350c0cd3cf 100644 --- a/gcc/jit/jit-recording.h +++ b/gcc/jit/jit-recording.h @@ -255,6 +255,9 @@ public: set_str_option (enum gcc_jit_str_option opt, const char *value); + const char* + get_str_option (enum gcc_jit_str_option opt); + void set_int_option (enum gcc_jit_int_option opt, int value); diff --git a/gcc/jit/libgccjit.cc b/gcc/jit/libgccjit.cc index 63dee7049af914bf3fc4836dc6953167a70362cb..3a7a4e26931f08a7e47c66939051ea849073498f 100644 --- a/gcc/jit/libgccjit.cc +++ b/gcc/jit/libgccjit.cc @@ -1201,10 +1201,13 @@ gcc_jit_context_new_function (gcc_jit_context *ctxt, Eventually we'll need some way to interact with e.g. C++ name mangling. */ { + const char* special_chars_allowed + = ctxt->get_str_option (GCC_JIT_STR_OPTION_SPECIAL_CHARS_IN_FUNC_NAMES); /* Leading char: */ char ch = *name; RETURN_NULL_IF_FAIL_PRINTF2 ( - ISALPHA (ch) || ch == '_', + ISALPHA (ch) || ch == '_' || (special_chars_allowed + && strchr (special_chars_allowed, ch)), ctxt, loc, "name \"%s\" contains invalid character: '%c'", name, ch); @@ -1212,7 +1215,8 @@ gcc_jit_context_new_function (gcc_jit_context *ctxt, for (const char *ptr = name + 1; (ch = *ptr); ptr++) { RETURN_NULL_IF_FAIL_PRINTF2 ( - ISALNUM (ch) || ch == '_', + ISALNUM (ch) || ch == '_' || (special_chars_allowed + && strchr (special_chars_allowed, ch)), ctxt, loc, "name \"%s\" contains invalid character: '%c'", name, ch); diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index ae3745a91aa318751ad0c6123aeeabd74b4d47d6..1274a1bb61b6c3db86de3d1ee21885c3f708062e 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -177,6 +177,9 @@ enum gcc_jit_str_option messages to stderr. If NULL, or default, "libgccjit.so" is used. */ GCC_JIT_STR_OPTION_PROGNAME, + /* Special characters to allow in function names. */ + GCC_JIT_STR_OPTION_SPECIAL_CHARS_IN_FUNC_NAMES, + GCC_JIT_NUM_STR_OPTIONS }; diff --git a/gcc/testsuite/jit.dg/test-special-chars.c b/gcc/testsuite/jit.dg/test-special-chars.c new file mode 100644 index 0000000000000000000000000000000000000000..8cd77323050a30b445b529f00c3f7f4450343248 --- /dev/null +++ b/gcc/testsuite/jit.dg/test-special-chars.c @@ -0,0 +1,41 @@ +#include <stdlib.h> +#include <stdio.h> + +#include "libgccjit.h" + +#include "harness.h" + +void +create_code (gcc_jit_context *ctxt, void *user_data) +{ + gcc_jit_context_set_str_option (ctxt, + GCC_JIT_STR_OPTION_SPECIAL_CHARS_IN_FUNC_NAMES, "$."); + + /* Let's try to inject the equivalent of: + void + name$with.special_chars (void) + { + } + */ + gcc_jit_type *void_type = + gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID); + + /* Build the test_fn. */ + gcc_jit_function *test_fn = + gcc_jit_context_new_function (ctxt, NULL, + GCC_JIT_FUNCTION_EXPORTED, + void_type, + "name$with.special_chars", + 0, NULL, + 0); + + gcc_jit_block *block = gcc_jit_function_new_block (test_fn, NULL); + gcc_jit_block_end_with_void_return ( + block, NULL); +} + +void +verify_code (gcc_jit_context *ctxt, gcc_jit_result *result) +{ + CHECK_NON_NULL (result); +}