diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2015-12-02 09:06:28 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2015-12-02 09:06:28 +0000 |
commit | 886456e210ef12d77f625ace8f312ab23d208aff (patch) | |
tree | 5b44d07d2d4f3d21be039ca6d049269722224bbf /gcc/gensupport.c | |
parent | e970b4b0002d0bc24cf4461fb0eadd7ee2241cab (diff) | |
download | gcc-886456e210ef12d77f625ace8f312ab23d208aff.zip gcc-886456e210ef12d77f625ace8f312ab23d208aff.tar.gz gcc-886456e210ef12d77f625ace8f312ab23d208aff.tar.bz2 |
Check for invalid FAILs
This patch makes it a compile-time error for an internal-fn optab
to FAIL. There are certainly other optabs and patterns besides these
that aren't allowed to fail, but this at least deals with the immediate
point of controversy.
Tested normally on x86_64-linux-gnu. Also tested by building one
configuration per cpu directory. arc-elf and pdp11 didn't build
for unrelated reasons, but I checked that insn-emit.o built for
both without error.
gcc/
* Makefile.in (GENSUPPORT_H): New macro.
(build/gensupport.o, build/read-rtl.o, build/genattr.o)
(build/genattr-common.o, build/genattrtab.o, build/genautomata.o)
(build/gencodes.o, build/genconditions.o, build/genconfig.o)
(build/genconstants.o, build/genextract.o, build/genflags.o)
(build/gentarget-def.o): Use it.
(build/genemit.o): Likewise. Depend on internal-fn.def.
* genopinit.c: Move block comment to optabs.def.
(optab_tag, optab_def): Move to gensupport.h
(pattern): Likewise, renaming to optab_pattern.
(match_pattern): Move to gensupport.c
(gen_insn): Use find_optab.
(patterns, pattern_cmp): Replace pattern with optab_pattern.
(main): Likewise. Use num_optabs.
* optabs.def: Add comment that was previously in genopinit.c.
* gensupport.h (optab_tag): Moved from genopinit.c
(optab_def): Likewise, expanding commentary.
(optab_pattern): Likewise, after renaming from pattern.
(optabs, num_optabs, find_optab): Declare.
* gensupport.c (optabs): Moved from genopinit.c.
(num_optabs): New variable.
(match_pattern): Moved from genopinit.c.
(find_optab): New function, extracted from genopinit.c:gen_insn.
* genemit.c (nofail_optabs): New variable.
(emit_c_code): New function.
(gen_expand): Check whether the instruction is an optab that isn't
allowed to fail. Call emit_c_code.
(gen_split): Call emit_c_code here too.
(main): Initialize nofail_optabs. Don't emit FAIL and DONE here.
From-SVN: r231160
Diffstat (limited to 'gcc/gensupport.c')
-rw-r--r-- | gcc/gensupport.c | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/gcc/gensupport.c b/gcc/gensupport.c index 484ead2..7969060 100644 --- a/gcc/gensupport.c +++ b/gcc/gensupport.c @@ -3061,3 +3061,161 @@ needs_barrier_p (rtx x) && GET_CODE (SET_DEST (x)) == PC && GET_CODE (SET_SRC (x)) == LABEL_REF); } + +#define NS "NULL" +#define ZS "'\\0'" +#define OPTAB_CL(o, p, c, b, l) { #o, p, #b, ZS, #l, o, c, UNKNOWN, 1 }, +#define OPTAB_CX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 1 }, +#define OPTAB_CD(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 2 }, +#define OPTAB_NL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, c, 3 }, +#define OPTAB_NC(o, p, c) { #o, p, NS, ZS, NS, o, c, c, 3 }, +#define OPTAB_NX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 }, +#define OPTAB_VL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, UNKNOWN, 3 }, +#define OPTAB_VC(o, p, c) { #o, p, NS, ZS, NS, o, c, UNKNOWN, 3 }, +#define OPTAB_VX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 }, +#define OPTAB_DC(o, p, c) { #o, p, NS, ZS, NS, o, c, c, 4 }, +#define OPTAB_D(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 4 }, + +/* An array of all optabs. Note that the same optab can appear more + than once, with a different pattern. */ +optab_def optabs[] = { + { "unknown_optab", NULL, NS, ZS, NS, unknown_optab, UNKNOWN, UNKNOWN, 0 }, +#include "optabs.def" +}; + +/* The number of entries in optabs[]. */ +unsigned int num_optabs = ARRAY_SIZE (optabs); + +#undef OPTAB_CL +#undef OPTAB_CX +#undef OPTAB_CD +#undef OPTAB_NL +#undef OPTAB_NC +#undef OPTAB_NX +#undef OPTAB_VL +#undef OPTAB_VC +#undef OPTAB_VX +#undef OPTAB_DC +#undef OPTAB_D + +/* Return true if instruction NAME matches pattern PAT, storing information + about the match in P if so. */ + +static bool +match_pattern (optab_pattern *p, const char *name, const char *pat) +{ + bool force_float = false; + bool force_int = false; + bool force_partial_int = false; + bool force_fixed = false; + + if (pat == NULL) + return false; + for (; ; ++pat) + { + if (*pat != '$') + { + if (*pat != *name++) + return false; + if (*pat == '\0') + return true; + continue; + } + switch (*++pat) + { + case 'I': + force_int = 1; + break; + case 'P': + force_partial_int = 1; + break; + case 'F': + force_float = 1; + break; + case 'Q': + force_fixed = 1; + break; + + case 'a': + case 'b': + { + int i; + + /* This loop will stop at the first prefix match, so + look through the modes in reverse order, in case + there are extra CC modes and CC is a prefix of the + CC modes (as it should be). */ + for (i = (MAX_MACHINE_MODE) - 1; i >= 0; i--) + { + const char *p, *q; + for (p = GET_MODE_NAME (i), q = name; *p; p++, q++) + if (TOLOWER (*p) != *q) + break; + if (*p == 0 + && (! force_int || mode_class[i] == MODE_INT + || mode_class[i] == MODE_VECTOR_INT) + && (! force_partial_int + || mode_class[i] == MODE_INT + || mode_class[i] == MODE_PARTIAL_INT + || mode_class[i] == MODE_VECTOR_INT) + && (! force_float + || mode_class[i] == MODE_FLOAT + || mode_class[i] == MODE_DECIMAL_FLOAT + || mode_class[i] == MODE_COMPLEX_FLOAT + || mode_class[i] == MODE_VECTOR_FLOAT) + && (! force_fixed + || mode_class[i] == MODE_FRACT + || mode_class[i] == MODE_UFRACT + || mode_class[i] == MODE_ACCUM + || mode_class[i] == MODE_UACCUM + || mode_class[i] == MODE_VECTOR_FRACT + || mode_class[i] == MODE_VECTOR_UFRACT + || mode_class[i] == MODE_VECTOR_ACCUM + || mode_class[i] == MODE_VECTOR_UACCUM)) + break; + } + + if (i < 0) + return false; + name += strlen (GET_MODE_NAME (i)); + if (*pat == 'a') + p->m1 = i; + else + p->m2 = i; + + force_int = false; + force_partial_int = false; + force_float = false; + force_fixed = false; + } + break; + + default: + gcc_unreachable (); + } + } +} + +/* Return true if NAME is the name of an optab, describing it in P if so. */ + +bool +find_optab (optab_pattern *p, const char *name) +{ + if (*name == 0 || *name == '*') + return false; + + /* See if NAME matches one of the patterns we have for the optabs + we know about. */ + for (unsigned int pindex = 0; pindex < ARRAY_SIZE (optabs); pindex++) + { + p->m1 = p->m2 = 0; + if (match_pattern (p, name, optabs[pindex].pattern)) + { + p->name = name; + p->op = optabs[pindex].op; + p->sort_num = (p->op << 16) | (p->m2 << 8) | p->m1; + return true; + } + } + return false; +} |