spu-c.c revision 1.5 1 /* Copyright (C) 2006-2015 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 3 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 GCC; see the file COPYING3. If not see
15 <http://www.gnu.org/licenses/>. */
16
17 #include "config.h"
18 #include "system.h"
19 #include "coretypes.h"
20 #include "tm.h"
21 #include "cpplib.h"
22 #include "hash-set.h"
23 #include "machmode.h"
24 #include "vec.h"
25 #include "double-int.h"
26 #include "input.h"
27 #include "alias.h"
28 #include "symtab.h"
29 #include "wide-int.h"
30 #include "inchash.h"
31 #include "tree.h"
32 #include "stringpool.h"
33 #include "c-family/c-common.h"
34 #include "c-family/c-pragma.h"
35 #include "tm_p.h"
36 #include "langhooks.h"
37 #include "target.h"
38
39
41 /* Keep the vector keywords handy for fast comparisons. */
42 static GTY(()) tree __vector_keyword;
43 static GTY(()) tree vector_keyword;
44
45 static cpp_hashnode *
46 spu_categorize_keyword (const cpp_token *tok)
47 {
48 if (tok->type == CPP_NAME)
49 {
50 cpp_hashnode *ident = tok->val.node.node;
51
52 if (ident == C_CPP_HASHNODE (vector_keyword)
53 || ident == C_CPP_HASHNODE (__vector_keyword))
54 return C_CPP_HASHNODE (__vector_keyword);
55 else
56 return ident;
57 }
58 return 0;
59 }
60
61 /* Called to decide whether a conditional macro should be expanded.
62 Since we have exactly one such macro (i.e, 'vector'), we do not
63 need to examine the 'tok' parameter. */
64
65 static cpp_hashnode *
66 spu_macro_to_expand (cpp_reader *pfile, const cpp_token *tok)
67 {
68 cpp_hashnode *expand_this = tok->val.node.node;
69 cpp_hashnode *ident;
70
71 ident = spu_categorize_keyword (tok);
72 if (ident == C_CPP_HASHNODE (__vector_keyword))
73 {
74 tok = cpp_peek_token (pfile, 0);
75 ident = spu_categorize_keyword (tok);
76
77 if (ident)
78 {
79 enum rid rid_code = (enum rid)(ident->rid_code);
80 if (ident->type == NT_MACRO)
81 {
82 (void) cpp_get_token (pfile);
83 tok = cpp_peek_token (pfile, 0);
84 ident = spu_categorize_keyword (tok);
85 if (ident)
86 rid_code = (enum rid)(ident->rid_code);
87 }
88
89 if (rid_code == RID_UNSIGNED || rid_code == RID_LONG
90 || rid_code == RID_SHORT || rid_code == RID_SIGNED
91 || rid_code == RID_INT || rid_code == RID_CHAR
92 || rid_code == RID_FLOAT || rid_code == RID_DOUBLE)
93 expand_this = C_CPP_HASHNODE (__vector_keyword);
94 }
95 }
96 return expand_this;
97 }
98
99 /* target hook for resolve_overloaded_builtin(). Returns a function call
100 RTX if we can resolve the overloaded builtin */
101 tree
102 spu_resolve_overloaded_builtin (location_t loc, tree fndecl, void *passed_args)
103 {
104 #define SCALAR_TYPE_P(t) (INTEGRAL_TYPE_P (t) \
105 || SCALAR_FLOAT_TYPE_P (t) \
106 || POINTER_TYPE_P (t))
107 vec<tree, va_gc> *fnargs = static_cast <vec<tree, va_gc> *> (passed_args);
108 unsigned int nargs = vec_safe_length (fnargs);
109 int new_fcode, fcode = DECL_FUNCTION_CODE (fndecl);
110 struct spu_builtin_description *desc;
111 tree match = NULL_TREE;
112
113 /* The vector types are not available if the backend is not initialized. */
114 gcc_assert (!flag_preprocess_only);
115
116 desc = &spu_builtins[fcode];
117 if (desc->type != B_OVERLOAD)
118 return NULL_TREE;
119
120 /* Compare the signature of each internal builtin function with the
121 function arguments until a match is found. */
122
123 for (new_fcode = fcode + 1; spu_builtins[new_fcode].type == B_INTERNAL;
124 new_fcode++)
125 {
126 tree decl = targetm.builtin_decl (new_fcode, true);
127 tree params = TYPE_ARG_TYPES (TREE_TYPE (decl));
128 tree param;
129 bool all_scalar;
130 unsigned int p;
131
132 /* Check whether all parameters are scalar. */
133 all_scalar = true;
134 for (param = params; param != void_list_node; param = TREE_CHAIN (param))
135 if (!SCALAR_TYPE_P (TREE_VALUE (param)))
136 all_scalar = false;
137
138 for (param = params, p = 0;
139 param != void_list_node;
140 param = TREE_CHAIN (param), p++)
141 {
142 tree var, arg_type, param_type = TREE_VALUE (param);
143
144 if (p >= nargs)
145 {
146 error ("insufficient arguments to overloaded function %s",
147 desc->name);
148 return error_mark_node;
149 }
150
151 var = (*fnargs)[p];
152
153 if (TREE_CODE (var) == NON_LVALUE_EXPR)
154 var = TREE_OPERAND (var, 0);
155
156 if (TREE_CODE (var) == ERROR_MARK)
157 return NULL_TREE; /* Let somebody else deal with the problem. */
158
159 arg_type = TREE_TYPE (var);
160
161 /* The intrinsics spec does not specify precisely how to
162 resolve generic intrinsics. We require an exact match
163 for vector types and let C do it's usual parameter type
164 checking/promotions for scalar arguments, except for the
165 first argument of intrinsics which don't have a vector
166 parameter. */
167 if ((!SCALAR_TYPE_P (param_type)
168 || !SCALAR_TYPE_P (arg_type)
169 || (all_scalar && p == 0))
170 && !lang_hooks.types_compatible_p (param_type, arg_type))
171 break;
172 }
173 if (param == void_list_node)
174 {
175 if (p != nargs)
176 {
177 error ("too many arguments to overloaded function %s",
178 desc->name);
179 return error_mark_node;
180 }
181
182 match = decl;
183 break;
184 }
185 }
186
187 if (match == NULL_TREE)
188 {
189 error ("parameter list does not match a valid signature for %s()",
190 desc->name);
191 return error_mark_node;
192 }
193
194 return build_function_call_vec (loc, vNULL, match, fnargs, NULL);
195 #undef SCALAR_TYPE_P
196 }
197
198
199 void
200 spu_cpu_cpp_builtins (struct cpp_reader *pfile)
201 {
202 cpp_define (pfile, "__SPU__");
203 cpp_assert (pfile, "cpu=spu");
204 cpp_assert (pfile, "machine=spu");
205 if (spu_arch == PROCESSOR_CELLEDP)
206 cpp_define (pfile, "__SPU_EDP__");
207 if (cpp_get_options (pfile)->lang != CLK_ASM)
208 cpp_define (pfile, "__vector=__attribute__((__spu_vector__))");
209 switch (spu_ea_model)
210 {
211 case 32:
212 cpp_define (pfile, "__EA32__");
213 break;
214 case 64:
215 cpp_define (pfile, "__EA64__");
216 break;
217 default:
218 gcc_unreachable ();
219 }
220
221 if (!flag_iso && cpp_get_options (pfile)->lang != CLK_ASM)
222 {
223 /* Define this when supporting context-sensitive keywords. */
224 cpp_define (pfile, "__VECTOR_KEYWORD_SUPPORTED__");
225 cpp_define (pfile, "vector=vector");
226
227 /* Initialize vector keywords. */
228 __vector_keyword = get_identifier ("__vector");
229 C_CPP_HASHNODE (__vector_keyword)->flags |= NODE_CONDITIONAL;
230 vector_keyword = get_identifier ("vector");
231 C_CPP_HASHNODE (vector_keyword)->flags |= NODE_CONDITIONAL;
232
233 /* Enable context-sensitive macros. */
234 cpp_get_callbacks (pfile)->macro_to_expand = spu_macro_to_expand;
235 }
236 }
237
238 void
239 spu_c_common_override_options (void)
240 {
241 if (!TARGET_STD_MAIN)
242 {
243 /* Don't give warnings about the main() function. */
244 warn_main = 0;
245 }
246 }
247