I have been looking at asm_fprintf in final.c, and I think there's a
design flaw. But since the change affects ARM and since I have no
access to an ARM system, I need a second opinion.
asm_fprintf allows platforms to add support for new format specifiers by
using the ASM_FPRINTF_EXTENSIONS macro. ARM uses this to add support
for %@ and %r specifiers. Pretty straight-forward.
However, it isn't enough to add these two items to the case statement in
asm_fprintf. Over in c-format.c, there is compile-time checking that is
done against calls to asm_fprintf to validate the format string. %@ and
%r have been added to this checking (see asm_fprintf_char_table), but
NOT in a platform-specific way.
This means that using %r or %@ will successfully pass the format
checking on all platforms, but will ICE on non-ARM platforms since there
are no case statements in asm_fprintf to support them.
Compiling the code in asm_fprintf-1.c (see the patch) with this patch
correctly reports "unknown conversion type character" for both 'r' and
'@' in x86_64-pc-cygwin. It would be helpful if someone could confirm
that it still compiles without error under ARM after applying this
patch. I'm reluctant to post this to gcc-patches when it has never been
run.
dw
Index: gcc/c-family/c-format.c
===================================================================
--- gcc/c-family/c-format.c (revision 212900)
+++ gcc/c-family/c-format.c (working copy)
@@ -637,8 +637,9 @@
{ "I", 0, STD_C89, NOARGUMENTS, "", "", NULL },
{ "L", 0, STD_C89, NOARGUMENTS, "", "", NULL },
{ "U", 0, STD_C89, NOARGUMENTS, "", "", NULL },
- { "r", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", NULL },
- { "@", 0, STD_C89, NOARGUMENTS, "", "", NULL },
+#ifdef ASM_FPRINTF_TABLE
+ ASM_FPRINTF_TABLE
+#endif
{ NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
};
Index: gcc/config/arm/arm.h
===================================================================
--- gcc/config/arm/arm.h (revision 212900)
+++ gcc/config/arm/arm.h (working copy)
@@ -888,6 +888,12 @@
fputs (reg_names [va_arg (ARGS, int)], FILE); \
break;
+/* Used in c-format.c to add entries to the table used to validate calls
+ to asm_fprintf. */
+#define ASM_FPRINTF_TABLE \
+ { "r", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", NULL }, \
+ { "@", 0, STD_C89, NOARGUMENTS, "", "", NULL },
+
/* Round X up to the nearest word. */
#define ROUND_UP_WORD(X) (((X) + 3) & ~3)
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi (revision 212900)
+++ gcc/doc/tm.texi (working copy)
@@ -8611,8 +8611,39 @@
The varargs input pointer is @var{argptr} and the rest of the format
string, starting the character after the one that is being switched
upon, is pointed to by @var{format}.
+See also ASM_FPRINTF_TABLE.
+
+Example:
+@smallexample
+#define ASM_FPRINTF_EXTENSIONS(FILE, ARGS, P) \
+ case '@': \
+ fputs (ASM_COMMENT_START, FILE); \
+ break; \
+ \
+ case 'r': \
+ fputs (REGISTER_PREFIX, FILE); \
+ fputs (reg_names [va_arg (ARGS, int)], FILE); \
+ break;
+@end smallexample
@end defmac
+@defmac ASM_FPRINTF_TABLE
+When using ASM_FPRINTF_EXTENSIONS, you must also use this macro to define
+table entries for the printf format checking performed in c-format.c.
+This macro must contain format_char_info entries for each printf format
+being added.
+
+Example:
+@smallexample
+#define ASM_FPRINTF_TABLE \
+ @{ "r", 0, STD_C89, \
+ @{ T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, \
+ BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN @}, \
+ "", "", NULL @}, \
+ @{ "@", 0, STD_C89, NOARGUMENTS, "", "", NULL @},
+@end smallexample
+@end defmac
+
@defmac ASSEMBLER_DIALECT
If your target supports multiple dialects of assembler language (such as
different opcodes), define this macro as a C expression that gives the
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in (revision 212900)
+++ gcc/doc/tm.texi.in (working copy)
@@ -6370,8 +6370,39 @@
The varargs input pointer is @var{argptr} and the rest of the format
string, starting the character after the one that is being switched
upon, is pointed to by @var{format}.
+See also ASM_FPRINTF_TABLE.
+
+Example:
+@smallexample
+#define ASM_FPRINTF_EXTENSIONS(FILE, ARGS, P) \
+ case '@': \
+ fputs (ASM_COMMENT_START, FILE); \
+ break; \
+ \
+ case 'r': \
+ fputs (REGISTER_PREFIX, FILE); \
+ fputs (reg_names [va_arg (ARGS, int)], FILE); \
+ break;
+@end smallexample
@end defmac
+@defmac ASM_FPRINTF_TABLE
+When using ASM_FPRINTF_EXTENSIONS, you must also use this macro to define
+table entries for the printf format checking performed in c-format.c.
+This macro must contain format_char_info entries for each printf format
+being added.
+
+Example:
+@smallexample
+#define ASM_FPRINTF_TABLE \
+ @{ "r", 0, STD_C89, \
+ @{ T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, \
+ BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN @}, \
+ "", "", NULL @}, \
+ @{ "@", 0, STD_C89, NOARGUMENTS, "", "", NULL @},
+@end smallexample
+@end defmac
+
@defmac ASSEMBLER_DIALECT
If your target supports multiple dialects of assembler language (such as
different opcodes), define this macro as a C expression that gives the
Index: gcc/testsuite/gcc.dg/format/asm_fprintf-1.c
===================================================================
--- gcc/testsuite/gcc.dg/format/asm_fprintf-1.c (revision 212900)
+++ gcc/testsuite/gcc.dg/format/asm_fprintf-1.c (working copy)
@@ -37,10 +37,14 @@
asm_fprintf ("%d %lu\n", i, ul);
/* Extensions provided in asm_fprintf. */
- asm_fprintf ("%O%R%I%L%U%@");
- asm_fprintf ("%r", i);
+ asm_fprintf ("%O%R%I%L%U");
asm_fprintf ("%wd%wi%wo%wu%wx%wX", ll, ll, ull, ull, ull, ull);
+ /* These 2 format specifiers are only available on arm. */
+#ifdef __arm__
+ asm_fprintf("%@%r", i);
+#endif
+
/* Standard specifiers not accepted in asm_fprintf. */
asm_fprintf ("%f\n", d); /* { dg-warning "format" "float" } */
asm_fprintf ("%e\n", d); /* { dg-warning "format" "float" } */