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