This patch introduces a new file builtins.def that is used as central registry
to hold built-ins' information.

The file is used by defining DEF_BUILTIN macre and then including the file as
described in the head comment of builtins.def.

Up to here it's all code clean-up and no functional change.

Moreover there are some minor changes and ICE fixes:

* Fold __builtin_avr_swap to rotate <<< 4
* Don't fold __builtin_avr_insert_bits if first arg is non-const (was ICE)
* Don't expand __builtin_avr_delay_cycles if arg is not-const (was ICE)

Ok for trunk?

Johann

gcc/testsuite/
        * gcc.target/avr/torture/builtins-1.c: New test.
        * gcc.target/avr/torture/builtins-error.c: New test.
gcc/
        * config/avr/builtins.def: New file.
        * config/avr/t-avr (avr.o, avr-c.o): Depend on it.
        * config/avr/avr.c (enum avr_builtin_id): Use it.
        (avr_init_builtins): Use it. And use avr_bdesc.
        (bdesc_1arg): Remove.
        (bdesc_2arg): Remove.
        (bdesc_3arg): Remove.
        (struct avr_builtin_description): Add field n_args.
        (avr_bdesc): New static variable using builtins.def.
        (avr_expand_builtin): Use it.
        Don't call avr_expand_delay_cycles if op0 is not CONST_INT.
        (avr_fold_builtin): Fold AVR_BUILTIN_SWAP.
        Don't fold AVR_BUILTIN_INSERT_BITS if arg0 is not INTEGER_CST.
Index: config/avr/builtins.def
===================================================================
--- config/avr/builtins.def	(revision 0)
+++ config/avr/builtins.def	(revision 0)
@@ -0,0 +1,50 @@
+/* Copyright (C) 2012 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This file contains the definitions and documentation for the
+   builtins defined in the AVR part of the GNU compiler.
+   Befor including this file, define a macro
+
+   DEF_BUILTIN(NAME, N_ARGS, ID, TYPE, ICODE)
+
+   NAME:   The name as visible by the user as a C string.
+   ID:     An integer to identify the built-in.
+   N_ARGS: Number of input arguments.  If special treatment is needed,
+           set to -1 and handle it by hand, see avr.c:avr_expand_builtin().
+   TYPE:   A tree node describing the prototype of the built-in.
+   ICODE:  Insn code number for the insn attached to the built-in.
+           If special treatment is needed to expand the built-in, set to -1.
+*/
+
+/* Mapped to respective instruction.  */
+DEF_BUILTIN ("__builtin_avr_nop",  -1, AVR_BUILTIN_NOP, void_ftype_void, -1)
+DEF_BUILTIN ("__builtin_avr_sei",   0, AVR_BUILTIN_SEI, void_ftype_void, CODE_FOR_enable_interrupt)
+DEF_BUILTIN ("__builtin_avr_cli",   0, AVR_BUILTIN_CLI, void_ftype_void, CODE_FOR_disable_interrupt)
+DEF_BUILTIN ("__builtin_avr_wdr",   0, AVR_BUILTIN_WDR,   void_ftype_void, CODE_FOR_wdr)
+DEF_BUILTIN ("__builtin_avr_sleep", 0, AVR_BUILTIN_SLEEP, void_ftype_void, CODE_FOR_sleep)
+
+/* Mapped to respective instruction but might alse be folded away
+   or emit as libgcc call if ISA does not provide the instruction.  */
+DEF_BUILTIN ("__builtin_avr_swap",   1, AVR_BUILTIN_SWAP,   uchar_ftype_uchar,      CODE_FOR_rotlqi3_4)
+DEF_BUILTIN ("__builtin_avr_fmul",   2, AVR_BUILTIN_FMUL,   uint_ftype_uchar_uchar, CODE_FOR_fmul)
+DEF_BUILTIN ("__builtin_avr_fmuls",  2, AVR_BUILTIN_FMULS,  int_ftype_char_char,    CODE_FOR_fmuls)
+DEF_BUILTIN ("__builtin_avr_fmulsu", 2, AVR_BUILTIN_FMULSU, int_ftype_char_uchar,   CODE_FOR_fmulsu)
+
+/* More complex stuff that cannot be mapped 1:1 to an instruction.  */
+DEF_BUILTIN ("__builtin_avr_delay_cycles", -1, AVR_BUILTIN_DELAY_CYCLES, void_ftype_ulong, -1)
+DEF_BUILTIN ("__builtin_avr_insert_bits", 3, AVR_BUILTIN_INSERT_BITS, uchar_ftype_ulong_uchar_uchar, CODE_FOR_insert_bits)
Index: config/avr/avr.c
===================================================================
--- config/avr/avr.c	(revision 184269)
+++ config/avr/avr.c	(working copy)
@@ -10504,17 +10504,12 @@ avr_out_insert_bits (rtx *op, int *plen)
 
 enum avr_builtin_id
   {
-    AVR_BUILTIN_NOP,
-    AVR_BUILTIN_SEI,
-    AVR_BUILTIN_CLI,
-    AVR_BUILTIN_WDR,
-    AVR_BUILTIN_SLEEP,
-    AVR_BUILTIN_SWAP,
-    AVR_BUILTIN_INSERT_BITS,
-    AVR_BUILTIN_FMUL,
-    AVR_BUILTIN_FMULS,
-    AVR_BUILTIN_FMULSU,
-    AVR_BUILTIN_DELAY_CYCLES
+    
+#define DEF_BUILTIN(NAME, N_ARGS, ID, TYPE, CODE) ID,
+#include "builtins.def"  
+#undef DEF_BUILTIN
+
+    AVR_BUILTIN_COUNT
   };
 
 static void
@@ -10527,14 +10522,6 @@ avr_init_builtin_int24 (void)
   (*lang_hooks.types.register_builtin_type) (uint24_type, "__uint24");
 }
 
-#define DEF_BUILTIN(NAME, TYPE, CODE)                                   \
-  do                                                                    \
-    {                                                                   \
-      add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD,        \
-                            NULL, NULL_TREE);                           \
-    } while (0)
-
-
 /* Implement `TARGET_INIT_BUILTINS' */
 /* Set up all builtin functions for this target.  */
 
@@ -10574,58 +10561,36 @@ avr_init_builtins (void)
                                 unsigned_char_type_node,
                                 NULL_TREE);
 
-  DEF_BUILTIN ("__builtin_avr_nop", void_ftype_void, AVR_BUILTIN_NOP);
-  DEF_BUILTIN ("__builtin_avr_sei", void_ftype_void, AVR_BUILTIN_SEI);
-  DEF_BUILTIN ("__builtin_avr_cli", void_ftype_void, AVR_BUILTIN_CLI);
-  DEF_BUILTIN ("__builtin_avr_wdr", void_ftype_void, AVR_BUILTIN_WDR);
-  DEF_BUILTIN ("__builtin_avr_sleep", void_ftype_void, AVR_BUILTIN_SLEEP);
-  DEF_BUILTIN ("__builtin_avr_swap", uchar_ftype_uchar, AVR_BUILTIN_SWAP);
-  DEF_BUILTIN ("__builtin_avr_delay_cycles", void_ftype_ulong, 
-               AVR_BUILTIN_DELAY_CYCLES);
-
-  DEF_BUILTIN ("__builtin_avr_fmul", uint_ftype_uchar_uchar, 
-               AVR_BUILTIN_FMUL);
-  DEF_BUILTIN ("__builtin_avr_fmuls", int_ftype_char_char, 
-               AVR_BUILTIN_FMULS);
-  DEF_BUILTIN ("__builtin_avr_fmulsu", int_ftype_char_uchar, 
-               AVR_BUILTIN_FMULSU);
-
-  DEF_BUILTIN ("__builtin_avr_insert_bits", uchar_ftype_ulong_uchar_uchar,
-               AVR_BUILTIN_INSERT_BITS);
-
+#define DEF_BUILTIN(NAME, N_ARGS, ID, TYPE, CODE)                       \
+  add_builtin_function (NAME, TYPE, ID, BUILT_IN_MD, NULL, NULL_TREE);
+#include "builtins.def"  
+#undef DEF_BUILTIN
+  
   avr_init_builtin_int24 ();
 }
 
-#undef DEF_BUILTIN
 
 struct avr_builtin_description
 {
-  const enum insn_code icode;
-  const char *const name;
-  const enum avr_builtin_id id;
+  enum insn_code icode;
+  const char *name;
+  enum avr_builtin_id id;
+  int n_args;
 };
 
 static const struct avr_builtin_description
-bdesc_1arg[] =
+avr_bdesc[] =
   {
-    { CODE_FOR_rotlqi3_4, "__builtin_avr_swap", AVR_BUILTIN_SWAP }
-  };
 
-static const struct avr_builtin_description
-bdesc_2arg[] =
-  {
-    { CODE_FOR_fmul, "__builtin_avr_fmul", AVR_BUILTIN_FMUL },
-    { CODE_FOR_fmuls, "__builtin_avr_fmuls", AVR_BUILTIN_FMULS },
-    { CODE_FOR_fmulsu, "__builtin_avr_fmulsu", AVR_BUILTIN_FMULSU }
-  };
+#define DEF_BUILTIN(NAME, N_ARGS, ID, TYPE, ICODE)      \
+    { ICODE, NAME, ID, N_ARGS },
+#include "builtins.def"  
+#undef DEF_BUILTIN
 
-static const struct avr_builtin_description
-bdesc_3arg[] =
-  {
-    { CODE_FOR_insert_bits, "__builtin_avr_insert_bits",
-      AVR_BUILTIN_INSERT_BITS }
+    { CODE_FOR_nothing, NULL, 0, -1 }
   };
 
+
 /* Subroutine of avr_expand_builtin to take care of unop insns.  */
 
 static rtx
@@ -10807,7 +10772,6 @@ avr_expand_builtin (tree exp, rtx target
                     int ignore ATTRIBUTE_UNUSED)
 {
   size_t i;
-  const struct avr_builtin_description *d;
   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
   const char* bname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
   unsigned int id = DECL_FUNCTION_CODE (fndecl);
@@ -10820,31 +10784,16 @@ avr_expand_builtin (tree exp, rtx target
       emit_insn (gen_nopv (GEN_INT(1)));
       return 0;
       
-    case AVR_BUILTIN_SEI:
-      emit_insn (gen_enable_interrupt ());
-      return 0;
-      
-    case AVR_BUILTIN_CLI:
-      emit_insn (gen_disable_interrupt ());
-      return 0;
-      
-    case AVR_BUILTIN_WDR:
-      emit_insn (gen_wdr ());
-      return 0;
-      
-    case AVR_BUILTIN_SLEEP:
-      emit_insn (gen_sleep ());
-      return 0;
-      
     case AVR_BUILTIN_DELAY_CYCLES:
       {
         arg0 = CALL_EXPR_ARG (exp, 0);
         op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
 
-        if (! CONST_INT_P (op0))
+        if (!CONST_INT_P (op0))
           error ("%s expects a compile time integer constant", bname);
+        else
+          avr_expand_delay_cycles (op0);
 
-        avr_expand_delay_cycles (op0);
         return 0;
       }
 
@@ -10862,18 +10811,31 @@ avr_expand_builtin (tree exp, rtx target
       }
     }
 
-  for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
-    if (d->id == id)
-      return avr_expand_unop_builtin (d->icode, exp, target);
-
-  for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
-    if (d->id == id)
-      return avr_expand_binop_builtin (d->icode, exp, target);
-
-  for (i = 0, d = bdesc_3arg; i < ARRAY_SIZE (bdesc_3arg); i++, d++)
-    if (d->id == id)
-      return avr_expand_triop_builtin (d->icode, exp, target);
-
+  for (i = 0; avr_bdesc[i].name; i++)
+    {
+      const struct avr_builtin_description *d = &avr_bdesc[i];
+      
+      if (d->id == id)
+        switch (d->n_args)
+          {
+          case 0:
+            emit_insn ((GEN_FCN (d->icode)) (target));
+            return 0;
+            
+          case 1:
+            return avr_expand_unop_builtin (d->icode, exp, target);
+            
+          case 2:
+            return avr_expand_binop_builtin (d->icode, exp, target);
+            
+          case 3:
+            return avr_expand_triop_builtin (d->icode, exp, target);
+            
+          default:
+            gcc_unreachable();
+        }
+    }
+  
   gcc_unreachable ();
 }
 
@@ -10895,17 +10857,32 @@ avr_fold_builtin (tree fndecl, int n_arg
     default:
       break;
 
+    case AVR_BUILTIN_SWAP:
+      {
+        return fold_build2 (LROTATE_EXPR, val_type, arg[0],
+                            build_int_cst (val_type, 4));
+      }
+  
     case AVR_BUILTIN_INSERT_BITS:
       {
         tree tbits = arg[1];
         tree tval = arg[2];
         tree tmap;
         tree map_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
-        double_int map = tree_to_double_int (arg[0]);
+        double_int map;
         bool changed = false;
         unsigned i;
         avr_map_op_t best_g;
+
+        if (TREE_CODE (arg[0]) != INTEGER_CST)
+          {
+            /* No constant as first argument: Don't fold this and run into
+               error in avr_expand_builtin.  */
+            
+            break;
+          }
         
+        map = tree_to_double_int (arg[0]);
         tmap = double_int_to_tree (map_type, map);
 
         if (TREE_CODE (tval) != INTEGER_CST
Index: config/avr/avr-c.c
===================================================================
--- config/avr/avr-c.c	(revision 184269)
+++ config/avr/avr-c.c	(working copy)
@@ -71,9 +71,19 @@ avr_toupper (char *up, const char *lo)
              
 /* Worker function for TARGET_CPU_CPP_BUILTINS.  */
 
+static const char *const avr_builtin_name[] =
+  {
+#define DEF_BUILTIN(NAME, N_ARGS, ID, TYPE, CODE) NAME,
+#include "builtins.def"
+#undef DEF_BUILTIN
+    NULL
+  };
+
 void
 avr_cpu_cpp_builtins (struct cpp_reader *pfile)
 {
+  int i;
+  
   builtin_define_std ("AVR");
 
   if (avr_current_arch->macro)
@@ -140,8 +150,6 @@ avr_cpu_cpp_builtins (struct cpp_reader
   
   if (!strcmp (lang_hooks.name, "GNU C"))
     {
-      int i;
-      
       for (i = 0; avr_addrspace[i].name; i++)
         if (!ADDR_SPACE_GENERIC_P (i))
           {
@@ -157,20 +165,11 @@ avr_cpu_cpp_builtins (struct cpp_reader
      easily query if or if not a specific builtin
      is available. */
 
-  cpp_define (pfile, "__BUILTIN_AVR_NOP");
-  cpp_define (pfile, "__BUILTIN_AVR_SEI");
-  cpp_define (pfile, "__BUILTIN_AVR_CLI");
-  cpp_define (pfile, "__BUILTIN_AVR_WDR");
-  cpp_define (pfile, "__BUILTIN_AVR_SLEEP");
-  cpp_define (pfile, "__BUILTIN_AVR_SWAP");
-  cpp_define (pfile, "__BUILTIN_AVR_INSERT_BITS");
-  cpp_define (pfile, "__BUILTIN_AVR_DELAY_CYCLES");
-
-  cpp_define (pfile, "__BUILTIN_AVR_FMUL");
-  cpp_define (pfile, "__BUILTIN_AVR_FMULS");
-  cpp_define (pfile, "__BUILTIN_AVR_FMULSU");
-
-  cpp_define (pfile, "__INT24_MAX__=8388607L");
-  cpp_define (pfile, "__INT24_MIN__=(-__INT24_MAX__-1)");
-  cpp_define (pfile, "__UINT24_MAX__=16777215UL");
+  for (i = 0; avr_builtin_name[i]; i++)
+    {
+      const char *name = avr_builtin_name[i];
+      char *Name = (char*) alloca (1 + strlen (name));
+
+      cpp_define (pfile, avr_toupper (Name, name));
+    }
 }
Index: config/avr/t-avr
===================================================================
--- config/avr/t-avr	(revision 184266)
+++ config/avr/t-avr	(working copy)
@@ -34,6 +34,8 @@ avr-log.o: $(srcdir)/config/avr/avr-log.
   $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(INPUT_H)
 	$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
 
+avr.o avr-c.o: $(srcdir)/config/avr/builtins.def
+
 # Files and Variables auto-generated from avr-mcus.def
 
 AVR_MCUS = $(srcdir)/config/avr/avr-mcus.def
Index: testsuite/gcc.target/avr/torture/builtins-error.c
===================================================================
--- testsuite/gcc.target/avr/torture/builtins-error.c	(revision 0)
+++ testsuite/gcc.target/avr/torture/builtins-error.c	(revision 0)
@@ -0,0 +1,11 @@
+/* { dg-do assemble } */
+
+char insert (long a)
+{
+    return __builtin_avr_insert_bits (15.3f+a, 0, 0); /* { dg-error "expects a compile time" } */
+}
+
+void delay (long a)
+{
+    __builtin_avr_delay_cycles (a); /* { dg-error "expects a compile time" } */
+}
Index: testsuite/gcc.target/avr/torture/builtins-1.c
===================================================================
--- testsuite/gcc.target/avr/torture/builtins-1.c	(revision 0)
+++ testsuite/gcc.target/avr/torture/builtins-1.c	(revision 0)
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+
+void nop (void)    { __builtin_avr_nop (); }
+void sei (void)    { __builtin_avr_sei (); }
+void cli (void)    { __builtin_avr_cli (); }
+void wdr (void)    { __builtin_avr_wdr (); }
+void sleep (void)  { __builtin_avr_sleep (); }
+
+char fmul (char a, char b)   { return __builtin_avr_fmul (a, b); }
+char fmuls (char a, char b)  { return __builtin_avr_fmuls (a, b); }
+char fmulsu (char a, char b) { return __builtin_avr_fmulsu (a, b); }
+
+char swap1 (char a)
+{
+    return __builtin_avr_swap (a+1);
+}
+
+char swap2 (char a)
+{
+    return __builtin_avr_swap (__builtin_avr_swap (a+1));
+}
+
+char swap15 (void)
+{
+    return __builtin_avr_swap (15);
+}
+
+void delay0 (void)  { __builtin_avr_delay_cycles (0); }
+void delay1 (void)  { __builtin_avr_delay_cycles (1); }
+void delay2 (void)  { __builtin_avr_delay_cycles (2); }
+void delay3 (void)  { __builtin_avr_delay_cycles (3); }
+
+void delay_1 (void)  { __builtin_avr_delay_cycles (44); }
+void delay_2 (void)  { __builtin_avr_delay_cycles (0x1234); }
+void delay_3 (void)  { __builtin_avr_delay_cycles (0x123456); }
+void delay_4 (void)  { __builtin_avr_delay_cycles (-1ul); }
+
+/* { dg-final { scan-assembler-not "__builtin_avr_" } } */

Reply via email to