OSDN Git Service

2006-11-30 Andrew Pinski <andrew_pinski@playstation.sony.com>
[pf3gnuchains/gcc-fork.git] / gcc / config / spu / spu-c.c
1 /* Copyright (C) 2006 Free Software Foundation, Inc.
2
3    This file is free software; you can redistribute it and/or modify it under
4    the terms of the GNU General Public License as published by the Free
5    Software Foundation; either version 2 of the License, or (at your option) 
6    any later version.
7
8    This file is distributed in the hope that it will be useful, but WITHOUT
9    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11    for more details.
12
13    You should have received a copy of the GNU General Public License
14    along with this file; see the file COPYING.  If not, write to the Free
15    Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
16    02110-1301, USA.  */
17
18 #include "config.h"
19 #include "system.h"
20 #include "coretypes.h"
21 #include "tm.h"
22 #include "cpplib.h"
23 #include "tree.h"
24 #include "c-tree.h"
25 #include "c-pragma.h"
26 #include "function.h"
27 #include "rtl.h"
28 #include "expr.h"
29 #include "errors.h"
30 #include "tm_p.h"
31 #include "langhooks.h"
32 #include "insn-config.h"
33 #include "insn-codes.h"
34 #include "recog.h"
35 #include "optabs.h"
36 #include "spu-builtins.h"
37 \f
38
39 /* Helper for spu_resolve_overloaded_builtin.  */
40 static tree
41 spu_build_overload_builtin (tree fndecl, tree fnargs)
42 {
43   tree param, param_type;
44   tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
45   tree arg, arglist = NULL_TREE;
46   tree val;
47
48   for (param = TYPE_ARG_TYPES (TREE_TYPE (fndecl)), arg = fnargs;
49        param != void_list_node;
50        param = TREE_CHAIN (param), arg = TREE_CHAIN (arg))
51     {
52       gcc_assert (arg != NULL_TREE);
53       param_type = TREE_VALUE (param);
54       val = default_conversion (TREE_VALUE (arg));
55       val = fold_convert (param_type, val);
56
57       arglist = tree_cons (NULL_TREE, val, arglist);
58     }
59   gcc_assert (arg == NULL_TREE);
60   arglist = nreverse (arglist);
61
62   return fold_convert (ret_type, build_function_call_expr (fndecl, arglist));
63 }
64
65 /* target hook for resolve_overloaded_builtin(). Returns a function call
66    RTX if we can resolve the overloaded builtin */
67 tree
68 spu_resolve_overloaded_builtin (tree fndecl, tree fnargs)
69 {
70   spu_function_code new_fcode, fcode =
71     DECL_FUNCTION_CODE (fndecl) - END_BUILTINS;
72   struct spu_builtin_description *desc;
73   tree match = NULL_TREE;
74
75   /* The vector types are not available if the backend is not initalized */
76   gcc_assert (!flag_preprocess_only);
77
78   desc = &spu_builtins[fcode];
79   if (desc->type != B_OVERLOAD)
80     return NULL_TREE;
81
82   /* Compare the signature of each internal builtin function with the
83      function arguments until a match is found. */
84
85   for (new_fcode = fcode + 1; spu_builtins[new_fcode].type == B_INTERNAL;
86        new_fcode++)
87     {
88       tree decl = spu_builtins[new_fcode].fndecl;
89       tree params = TYPE_ARG_TYPES (TREE_TYPE (decl));
90       tree arg, param;
91       int p;
92
93       for (param = params, arg = fnargs, p = 0;
94            param != void_list_node;
95            param = TREE_CHAIN (param), arg = TREE_CHAIN (arg), p++)
96         {
97           tree var, arg_type, param_type = TREE_VALUE (param);
98
99           if (!arg)
100             {
101               error ("insufficient arguments to overloaded function %s",
102                      desc->name);
103               return error_mark_node;
104             }
105
106           var = TREE_VALUE (arg);
107
108           if (TREE_CODE (var) == NON_LVALUE_EXPR)
109             var = TREE_OPERAND (var, 0);
110
111           if (TREE_CODE (var) == ERROR_MARK)
112             return NULL_TREE;   /* Let somebody else deal with the problem. */
113
114           arg_type = TREE_TYPE (var);
115
116           /* The intrinsics spec does not specify precisely how to
117              resolve generic intrinsics.  We require an exact match
118              for vector types and let C do it's usual parameter type
119              checking/promotions for scalar arguments, except for the
120              first argument of intrinsics which don't have a vector
121              parameter. */
122           if ((TREE_CODE (param_type) == VECTOR_TYPE
123                || ((fcode == SPU_SPLATS || fcode == SPU_PROMOTE
124                     || fcode == SPU_HCMPEQ || fcode == SPU_HCMPGT
125                     || fcode == SPU_MASKB || fcode == SPU_MASKH
126                     || fcode == SPU_MASKW) && p == 0))
127               && !comptypes (TYPE_MAIN_VARIANT (param_type),
128                              TYPE_MAIN_VARIANT (arg_type)))
129             break;
130         }
131       if (param == void_list_node)
132         {
133           if (arg)
134             {
135               error ("too many arguments to overloaded function %s",
136                      desc->name);
137               return error_mark_node;
138             }
139
140           match = decl;
141           break;
142         }
143     }
144
145   if (match == NULL_TREE)
146     {
147       error ("parameter list does not match a valid signature for %s()",
148              desc->name);
149       return error_mark_node;
150     }
151
152   return spu_build_overload_builtin (match, fnargs);
153 }
154
155
156 void
157 spu_cpu_cpp_builtins (struct cpp_reader *pfile)
158 {
159   builtin_define_std ("__SPU__");
160   cpp_assert (pfile, "cpu=spu");
161   cpp_assert (pfile, "machine=spu");
162   builtin_define_std ("__vector=__attribute__((__spu_vector__))");
163 }
164