[BRIGFE] Changed pure attributes to const for the brig-builtins
[gcc.git] / gcc / brig / brig-lang.c
1 /* brig-lang.c -- brig (HSAIL) input gcc interface.
2 Copyright (C) 2016-2017 Free Software Foundation, Inc.
3 Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
4 for General Processor Tech.
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
21
22 #include "config.h"
23 #include "system.h"
24 #include "ansidecl.h"
25 #include "coretypes.h"
26 #include "opts.h"
27 #include "tree.h"
28 #include "tree-iterator.h"
29 #include "print-tree.h"
30 #include "stringpool.h"
31 #include "basic-block.h"
32 #include "gimple-expr.h"
33 #include "gimplify.h"
34 #include "dumpfile.h"
35 #include "stor-layout.h"
36 #include "toplev.h"
37 #include "debug.h"
38 #include "options.h"
39 #include "flags.h"
40 #include "convert.h"
41 #include "diagnostic.h"
42 #include "langhooks.h"
43 #include "langhooks-def.h"
44 #include "target.h"
45 #include "vec.h"
46 #include "brigfrontend/brig-to-generic.h"
47 #include "machmode.h"
48 #include "fold-const.h"
49 #include "common/common-target.h"
50 #include <mpfr.h>
51 #include "brig-c.h"
52 #include "brig-builtins.h"
53
54 static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
55 static tree handle_const_attribute (tree *, tree, tree, int, bool *);
56 static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
57 static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
58 static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
59
60 /* This file is based on Go frontent'd go-lang.c and gogo-tree.cc. */
61
62 /* If -v set. */
63
64 int gccbrig_verbose = 0;
65
66 /* Language-dependent contents of a type. */
67
68 struct GTY (()) lang_type
69 {
70 char dummy;
71 };
72
73 /* Language-dependent contents of a decl. */
74
75 struct GTY ((variable_size)) lang_decl
76 {
77 char dummy;
78 };
79
80 /* Language-dependent contents of an identifier. This must include a
81 tree_identifier. */
82
83 struct GTY (()) lang_identifier
84 {
85 struct tree_identifier common;
86 };
87
88 /* The resulting tree type. */
89
90 union GTY ((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
91 chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), "
92 "TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN "
93 "(&%h.generic)) : NULL"))) lang_tree_node
94 {
95 union tree_node GTY ((tag ("0"), desc ("tree_node_structure (&%h)"))) generic;
96 struct lang_identifier GTY ((tag ("1"))) identifier;
97 };
98
99 /* We don't use language_function. */
100
101 struct GTY (()) language_function
102 {
103 int dummy;
104 };
105
106
107 /* The option mask. */
108
109 static unsigned int
110 brig_langhook_option_lang_mask (void)
111 {
112 return CL_BRIG;
113 }
114
115 /* Initialize the options structure. */
116
117 static void
118 brig_langhook_init_options_struct (struct gcc_options *opts)
119 {
120 /* Signed overflow is precisely defined. */
121 opts->x_flag_wrapv = 1;
122
123 /* If we set this to one, the whole program optimizations internalize
124 all global variables, making them invisible to the dyn loader (and
125 thus the HSA runtime implementation). */
126 opts->x_flag_whole_program = 0;
127
128 /* The builtin math functions should not set errno. */
129 opts->x_flag_errno_math = 0;
130 opts->frontend_set_flag_errno_math = false;
131
132 opts->x_flag_exceptions = 0;
133 opts->x_flag_non_call_exceptions = 0;
134
135 opts->x_flag_finite_math_only = 0;
136 opts->x_flag_signed_zeros = 1;
137
138 opts->x_optimize = 3;
139 }
140
141 /* Handle Brig specific options. Return 0 if we didn't do anything. */
142
143 static bool
144 brig_langhook_handle_option
145 (size_t scode, const char *arg ATTRIBUTE_UNUSED,
146 int value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED,
147 location_t loc ATTRIBUTE_UNUSED,
148 const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
149 {
150 enum opt_code code = (enum opt_code) scode;
151 switch (code)
152 {
153 case OPT_v:
154 gccbrig_verbose = 1;
155 break;
156 default:
157 break;
158 }
159 return 1;
160 }
161
162 /* Run after parsing options. */
163
164 static bool
165 brig_langhook_post_options (const char **pfilename ATTRIBUTE_UNUSED)
166 {
167 if (flag_excess_precision_cmdline == EXCESS_PRECISION_DEFAULT)
168 flag_excess_precision_cmdline = EXCESS_PRECISION_STANDARD;
169
170 /* gccbrig casts pointers around like crazy, TBAA produces
171 broken code if not force disabling it. */
172 flag_strict_aliasing = 0;
173
174 /* Returning false means that the backend should be used. */
175 return false;
176 }
177
178 static size_t
179 get_file_size (FILE *file)
180 {
181 size_t size;
182 fseek (file, 0, SEEK_END);
183 size = (size_t) ftell (file);
184 fseek (file, 0, SEEK_SET);
185 return size;
186 }
187
188 static void
189 brig_langhook_parse_file (void)
190 {
191 brig_to_generic brig_to_gen;
192
193 std::vector <char*> brig_blobs;
194
195 for (unsigned int i = 0; i < num_in_fnames; ++i)
196 {
197
198 FILE *f;
199 f = fopen (in_fnames[i], "r");
200 size_t fsize = get_file_size (f);
201 char *brig_blob = new char[fsize];
202 if (fread (brig_blob, 1, fsize, f) != fsize)
203 {
204 error ("could not read the BRIG file");
205 exit (1);
206 }
207 fclose (f);
208
209 brig_to_gen.analyze (brig_blob);
210 brig_blobs.push_back (brig_blob);
211 }
212
213 for (size_t i = 0; i < brig_blobs.size(); ++i)
214 {
215 char *brig_blob = brig_blobs.at(i);
216 brig_to_gen.parse (brig_blob);
217 }
218
219 brig_to_gen.write_globals ();
220
221 for (size_t i = 0; i < brig_blobs.size (); ++i)
222 delete brig_blobs[i];
223 }
224
225 static tree
226 brig_langhook_type_for_size (unsigned int bits,
227 int unsignedp)
228 {
229 /* Copied from go-lang.c */
230 tree type;
231 if (unsignedp)
232 {
233 if (bits == INT_TYPE_SIZE)
234 type = unsigned_type_node;
235 else if (bits == CHAR_TYPE_SIZE)
236 type = unsigned_char_type_node;
237 else if (bits == SHORT_TYPE_SIZE)
238 type = short_unsigned_type_node;
239 else if (bits == LONG_TYPE_SIZE)
240 type = long_unsigned_type_node;
241 else if (bits == LONG_LONG_TYPE_SIZE)
242 type = long_long_unsigned_type_node;
243 else
244 type = make_unsigned_type(bits);
245 }
246 else
247 {
248 if (bits == INT_TYPE_SIZE)
249 type = integer_type_node;
250 else if (bits == CHAR_TYPE_SIZE)
251 type = signed_char_type_node;
252 else if (bits == SHORT_TYPE_SIZE)
253 type = short_integer_type_node;
254 else if (bits == LONG_TYPE_SIZE)
255 type = long_integer_type_node;
256 else if (bits == LONG_LONG_TYPE_SIZE)
257 type = long_long_integer_type_node;
258 else
259 type = make_signed_type(bits);
260 }
261 return type;
262 }
263
264 static tree
265 brig_langhook_type_for_mode (machine_mode mode, int unsignedp)
266 {
267 if (mode == TYPE_MODE (void_type_node))
268 return void_type_node;
269
270 if (VECTOR_MODE_P (mode))
271 {
272 tree inner;
273
274 inner = brig_langhook_type_for_mode (GET_MODE_INNER (mode), unsignedp);
275 if (inner != NULL_TREE)
276 return build_vector_type_for_mode (inner, mode);
277 gcc_unreachable ();
278 return NULL_TREE;
279 }
280
281 enum mode_class mc = GET_MODE_CLASS (mode);
282 if (mc == MODE_FLOAT)
283 {
284 switch (GET_MODE_BITSIZE (mode))
285 {
286 case 32:
287 return float_type_node;
288 case 64:
289 return double_type_node;
290 default:
291 /* We have to check for long double in order to support
292 i386 excess precision. */
293 if (mode == TYPE_MODE (long_double_type_node))
294 return long_double_type_node;
295
296 gcc_unreachable ();
297 return NULL_TREE;
298 }
299 }
300 else if (mc == MODE_INT)
301 return brig_langhook_type_for_size(GET_MODE_BITSIZE(mode), unsignedp);
302 else
303 {
304 /* E.g., build_common_builtin_nodes () asks for modes/builtins
305 we do not generate or need. Just ignore them silently for now.
306 */
307 return NULL_TREE;
308 }
309 return NULL_TREE;
310 }
311
312 static tree
313 brig_langhook_builtin_function (tree decl)
314 {
315 return decl;
316 }
317
318 static GTY(()) tree registered_builtin_types;
319
320 static void
321 brig_langhook_register_builtin_type (tree type, const char *name)
322 {
323 tree decl;
324
325 if (!TYPE_NAME (type))
326 {
327 decl = build_decl (UNKNOWN_LOCATION, TYPE_DECL,
328 get_identifier (name), type);
329 DECL_ARTIFICIAL (decl) = 1;
330 TYPE_NAME (type) = decl;
331 }
332
333 registered_builtin_types = tree_cons (0, type, registered_builtin_types);
334 }
335
336
337 /* Return true if we are in the global binding level. */
338
339 static bool
340 brig_langhook_global_bindings_p (void)
341 {
342 return current_function_decl == NULL_TREE;
343 }
344
345 /* Push a declaration into the current binding level. From Go: We can't
346 usefully implement this since we don't want to convert from tree
347 back to one of our internal data structures. I think the only way
348 this is used is to record a decl which is to be returned by
349 getdecls, and we could implement it for that purpose if
350 necessary. */
351
352 static tree
353 brig_langhook_pushdecl (tree decl ATTRIBUTE_UNUSED)
354 {
355 gcc_unreachable ();
356 }
357
358 /* This hook is used to get the current list of declarations as trees.
359 From Go: We don't support that; instead we use the write_globals hook.
360 This can't simply crash because it is called by -gstabs. */
361
362 static tree
363 brig_langhook_getdecls (void)
364 {
365 return NULL;
366 }
367
368 static int
369 brig_langhook_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
370 gimple_seq *post_p ATTRIBUTE_UNUSED)
371 {
372
373 /* Strip off the static chain info that appears to function
374 calls for some strange reason even though we don't add
375 nested functions. Maybe something wrong with the function
376 declaration contexts? */
377 if (TREE_CODE (*expr_p) == CALL_EXPR
378 && CALL_EXPR_STATIC_CHAIN (*expr_p) != NULL_TREE)
379 CALL_EXPR_STATIC_CHAIN (*expr_p) = NULL_TREE;
380 return GS_UNHANDLED;
381 }
382
383 static tree
384 brig_langhook_eh_personality (void)
385 {
386 gcc_unreachable ();
387 }
388
389 /* Functions called directly by the generic backend.
390 Adapted from go-lang.c. */
391
392 tree
393 convert (tree type, tree expr)
394 {
395 if (type == error_mark_node || expr == error_mark_node
396 || TREE_TYPE (expr) == error_mark_node)
397 return error_mark_node;
398
399 if (type == TREE_TYPE (expr))
400 return expr;
401
402 if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr)))
403 return fold_convert (type, expr);
404
405 switch (TREE_CODE (type))
406 {
407 case VOID_TYPE:
408 case BOOLEAN_TYPE:
409 return fold_convert (type, expr);
410 case INTEGER_TYPE:
411 return fold (convert_to_integer (type, expr));
412 case REAL_TYPE:
413 return fold (convert_to_real (type, expr));
414 case VECTOR_TYPE:
415 return fold (convert_to_vector (type, expr));
416 case POINTER_TYPE:
417 return build1 (VIEW_CONVERT_EXPR, type, convert (size_type_node, expr));
418 default:
419 break;
420 }
421
422 gcc_unreachable ();
423 }
424
425 static GTY (()) tree brig_gc_root;
426
427 /* Preserve trees that we create from the garbage collector. */
428
429 void
430 brig_preserve_from_gc (tree t)
431 {
432 brig_gc_root = tree_cons (NULL_TREE, t, brig_gc_root);
433 }
434
435 /* Convert an identifier for use in an error message. */
436
437 const char *
438 brig_localize_identifier (const char *ident)
439 {
440 return identifier_to_locale (ident);
441 }
442
443 /* Define supported attributes and their handlers. Code copied from
444 lto-lang.c */
445
446 /* Table of machine-independent attributes supported in GIMPLE. */
447 const struct attribute_spec brig_attribute_table[] =
448 {
449 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
450 do_diagnostic } */
451 { "leaf", 0, 0, true, false, false,
452 handle_leaf_attribute, false },
453 { "const", 0, 0, true, false, false,
454 handle_const_attribute, false },
455 { "pure", 0, 0, true, false, false,
456 handle_pure_attribute, false },
457 { "nothrow", 0, 0, true, false, false,
458 handle_nothrow_attribute, false },
459 { "returns_twice", 0, 0, true, false, false,
460 handle_returns_twice_attribute, false },
461 { NULL, 0, 0, false, false, false, NULL, false }
462 };
463
464 /* Attribute handlers. */
465 /* Handle a "leaf" attribute; arguments as in
466 struct attribute_spec.handler. */
467
468 static tree
469 handle_leaf_attribute (tree *node, tree name,
470 tree ARG_UNUSED (args),
471 int ARG_UNUSED (flags), bool *no_add_attrs)
472 {
473 if (TREE_CODE (*node) != FUNCTION_DECL)
474 {
475 warning (OPT_Wattributes, "%qE attribute ignored", name);
476 *no_add_attrs = true;
477 }
478 if (!TREE_PUBLIC (*node))
479 {
480 warning (OPT_Wattributes,
481 "%qE attribute has no effect on unit local functions", name);
482 *no_add_attrs = true;
483 }
484
485 return NULL_TREE;
486 }
487
488 /* Handle a "const" attribute; arguments as in
489 struct attribute_spec.handler. */
490
491 static tree
492 handle_const_attribute (tree *node, tree ARG_UNUSED (name),
493 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
494 bool * ARG_UNUSED (no_add_attrs))
495 {
496 tree type = TREE_TYPE (*node);
497
498 /* See FIXME comment on noreturn in c_common_attribute_table. */
499 if (TREE_CODE (*node) == FUNCTION_DECL)
500 TREE_READONLY (*node) = 1;
501 else if (TREE_CODE (type) == POINTER_TYPE
502 && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
503 TREE_TYPE (*node)
504 = build_pointer_type
505 (build_type_variant (TREE_TYPE (type), 1,
506 TREE_THIS_VOLATILE (TREE_TYPE (type))));
507 else
508 gcc_unreachable ();
509
510 return NULL_TREE;
511 }
512
513 /* Handle a "pure" attribute; arguments as in
514 struct attribute_spec.handler. */
515
516 static tree
517 handle_pure_attribute (tree *node, tree ARG_UNUSED (name),
518 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
519 bool * ARG_UNUSED (no_add_attrs))
520 {
521 if (TREE_CODE (*node) == FUNCTION_DECL)
522 DECL_PURE_P (*node) = 1;
523 else
524 gcc_unreachable ();
525
526 return NULL_TREE;
527 }
528
529 /* Handle a "nothrow" attribute; arguments as in
530 struct attribute_spec.handler. */
531
532 static tree
533 handle_nothrow_attribute (tree *node, tree ARG_UNUSED (name),
534 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
535 bool * ARG_UNUSED (no_add_attrs))
536 {
537 if (TREE_CODE (*node) == FUNCTION_DECL)
538 TREE_NOTHROW (*node) = 1;
539 else
540 gcc_unreachable ();
541
542 return NULL_TREE;
543 }
544
545 /* Handle a "returns_twice" attribute. */
546
547 static tree
548 handle_returns_twice_attribute (tree *node, tree ARG_UNUSED (name),
549 tree ARG_UNUSED (args),
550 int ARG_UNUSED (flags),
551 bool * ARG_UNUSED (no_add_attrs))
552 {
553 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
554
555 DECL_IS_RETURNS_TWICE (*node) = 1;
556
557 return NULL_TREE;
558 }
559
560
561 /* Built-in initialization code cribbed from lto-lang.c which cribbed it
562 from c-common.c. */
563
564
565 static GTY(()) tree built_in_attributes[(int) ATTR_LAST];
566
567
568 static GTY(()) tree builtin_types[(int) BT_LAST + 1];
569
570 static GTY(()) tree string_type_node;
571 static GTY(()) tree const_string_type_node;
572 static GTY(()) tree wint_type_node;
573 static GTY(()) tree intmax_type_node;
574 static GTY(()) tree uintmax_type_node;
575 static GTY(()) tree signed_size_type_node;
576
577 /* Flags needed to process builtins.def. */
578 int flag_isoc94;
579 int flag_isoc99;
580 int flag_isoc11;
581
582 static void
583 def_fn_type (builtin_type def, builtin_type ret, bool var, int n, ...)
584 {
585 tree t;
586 tree *args = XALLOCAVEC (tree, n);
587 va_list list;
588 int i;
589 bool err = false;
590
591 va_start (list, n);
592 for (i = 0; i < n; ++i)
593 {
594 builtin_type a = (builtin_type) va_arg (list, int);
595 t = builtin_types[a];
596 if (t == error_mark_node)
597 err = true;
598 args[i] = t;
599 }
600 va_end (list);
601
602 t = builtin_types[ret];
603 if (err)
604 t = error_mark_node;
605 if (t == error_mark_node)
606 ;
607 else if (var)
608 t = build_varargs_function_type_array (t, n, args);
609 else
610 t = build_function_type_array (t, n, args);
611
612 builtin_types[def] = t;
613 }
614
615 /* Used to help initialize the builtin-types.def table. When a type of
616 the correct size doesn't exist, use error_mark_node instead of NULL.
617 The later results in segfaults even when a decl using the type doesn't
618 get invoked. */
619
620 static tree
621 builtin_type_for_size (int size, bool unsignedp)
622 {
623 tree type = brig_langhook_type_for_size (size, unsignedp);
624 return type ? type : error_mark_node;
625 }
626
627 /* Support for DEF_BUILTIN. */
628
629 static void
630 def_builtin_1 (enum built_in_function fncode, const char *name,
631 enum built_in_class fnclass, tree fntype, tree libtype,
632 bool both_p, bool fallback_p, bool nonansi_p,
633 tree fnattrs, bool implicit_p)
634 {
635 tree decl;
636 const char *libname;
637
638 if (fntype == error_mark_node)
639 return;
640
641 libname = name + strlen ("__builtin_");
642 decl = add_builtin_function (name, fntype, fncode, fnclass,
643 (fallback_p ? libname : NULL),
644 fnattrs);
645
646 if (both_p
647 && !flag_no_builtin
648 && !(nonansi_p && flag_no_nonansi_builtin))
649 add_builtin_function (libname, libtype, fncode, fnclass,
650 NULL, fnattrs);
651
652 set_builtin_decl (fncode, decl, implicit_p);
653 }
654
655
656 /* Initialize the attribute table for all the supported builtins. */
657
658 static void
659 brig_init_attributes (void)
660 {
661 /* Fill in the built_in_attributes array. */
662 #define DEF_ATTR_NULL_TREE(ENUM) \
663 built_in_attributes[(int) ENUM] = NULL_TREE;
664 #define DEF_ATTR_INT(ENUM, VALUE) \
665 built_in_attributes[(int) ENUM] = build_int_cst (NULL_TREE, VALUE);
666 #define DEF_ATTR_STRING(ENUM, VALUE) \
667 built_in_attributes[(int) ENUM] = build_string (strlen (VALUE), VALUE);
668 #define DEF_ATTR_IDENT(ENUM, STRING) \
669 built_in_attributes[(int) ENUM] = get_identifier (STRING);
670 #define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) \
671 built_in_attributes[(int) ENUM] \
672 = tree_cons (built_in_attributes[(int) PURPOSE], \
673 built_in_attributes[(int) VALUE], \
674 built_in_attributes[(int) CHAIN]);
675 #include "builtin-attrs.def"
676 #undef DEF_ATTR_NULL_TREE
677 #undef DEF_ATTR_INT
678 #undef DEF_ATTR_STRING
679 #undef DEF_ATTR_IDENT
680 #undef DEF_ATTR_TREE_LIST
681 }
682
683 /* Create builtin types and functions. VA_LIST_REF_TYPE_NODE and
684 VA_LIST_ARG_TYPE_NODE are used in builtin-types.def. */
685
686 static void
687 brig_define_builtins (tree va_list_ref_type_node ATTRIBUTE_UNUSED,
688 tree va_list_arg_type_node ATTRIBUTE_UNUSED)
689 {
690 #define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \
691 builtin_types[ENUM] = VALUE;
692 #define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \
693 def_fn_type (ENUM, RETURN, 0, 0);
694 #define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \
695 def_fn_type (ENUM, RETURN, 0, 1, ARG1);
696 #define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \
697 def_fn_type (ENUM, RETURN, 0, 2, ARG1, ARG2);
698 #define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
699 def_fn_type (ENUM, RETURN, 0, 3, ARG1, ARG2, ARG3);
700 #define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
701 def_fn_type (ENUM, RETURN, 0, 4, ARG1, ARG2, ARG3, ARG4);
702 #define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
703 def_fn_type (ENUM, RETURN, 0, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
704 #define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
705 ARG6) \
706 def_fn_type (ENUM, RETURN, 0, 6, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
707 #define DEF_FUNCTION_TYPE_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
708 ARG6, ARG7) \
709 def_fn_type (ENUM, RETURN, 0, 7, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
710 #define DEF_FUNCTION_TYPE_8(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
711 ARG6, ARG7, ARG8) \
712 def_fn_type (ENUM, RETURN, 0, 8, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \
713 ARG7, ARG8);
714 #define DEF_FUNCTION_TYPE_9(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
715 ARG6, ARG7, ARG8, ARG9) \
716 def_fn_type (ENUM, RETURN, 0, 9, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \
717 ARG7, ARG8, ARG9);
718 #define DEF_FUNCTION_TYPE_10(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
719 ARG6, ARG7, ARG8, ARG9, ARG10) \
720 def_fn_type (ENUM, RETURN, 0, 10, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \
721 ARG7, ARG8, ARG9, ARG10);
722 #define DEF_FUNCTION_TYPE_11(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
723 ARG6, ARG7, ARG8, ARG9, ARG10, ARG11) \
724 def_fn_type (ENUM, RETURN, 0, 11, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \
725 ARG7, ARG8, ARG9, ARG10, ARG11);
726 #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
727 def_fn_type (ENUM, RETURN, 1, 0);
728 #define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \
729 def_fn_type (ENUM, RETURN, 1, 1, ARG1);
730 #define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) \
731 def_fn_type (ENUM, RETURN, 1, 2, ARG1, ARG2);
732 #define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
733 def_fn_type (ENUM, RETURN, 1, 3, ARG1, ARG2, ARG3);
734 #define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
735 def_fn_type (ENUM, RETURN, 1, 4, ARG1, ARG2, ARG3, ARG4);
736 #define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
737 def_fn_type (ENUM, RETURN, 1, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
738 #define DEF_FUNCTION_TYPE_VAR_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
739 ARG6) \
740 def_fn_type (ENUM, RETURN, 1, 6, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
741 #define DEF_FUNCTION_TYPE_VAR_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
742 ARG6, ARG7) \
743 def_fn_type (ENUM, RETURN, 1, 7, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
744 #define DEF_POINTER_TYPE(ENUM, TYPE) \
745 builtin_types[(int) ENUM] = build_pointer_type (builtin_types[(int) TYPE]);
746
747 #include "builtin-types.def"
748
749 #undef DEF_PRIMITIVE_TYPE
750 #undef DEF_FUNCTION_TYPE_0
751 #undef DEF_FUNCTION_TYPE_1
752 #undef DEF_FUNCTION_TYPE_2
753 #undef DEF_FUNCTION_TYPE_3
754 #undef DEF_FUNCTION_TYPE_4
755 #undef DEF_FUNCTION_TYPE_5
756 #undef DEF_FUNCTION_TYPE_6
757 #undef DEF_FUNCTION_TYPE_7
758 #undef DEF_FUNCTION_TYPE_8
759 #undef DEF_FUNCTION_TYPE_9
760 #undef DEF_FUNCTION_TYPE_10
761 #undef DEF_FUNCTION_TYPE_11
762 #undef DEF_FUNCTION_TYPE_VAR_0
763 #undef DEF_FUNCTION_TYPE_VAR_1
764 #undef DEF_FUNCTION_TYPE_VAR_2
765 #undef DEF_FUNCTION_TYPE_VAR_3
766 #undef DEF_FUNCTION_TYPE_VAR_4
767 #undef DEF_FUNCTION_TYPE_VAR_5
768 #undef DEF_FUNCTION_TYPE_VAR_6
769 #undef DEF_FUNCTION_TYPE_VAR_7
770 #undef DEF_POINTER_TYPE
771 builtin_types[(int) BT_LAST] = NULL_TREE;
772
773 brig_init_attributes ();
774
775 #define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P,\
776 NONANSI_P, ATTRS, IMPLICIT, COND) \
777 if (NAME && COND) \
778 def_builtin_1 (ENUM, NAME, CLASS, builtin_types[(int) TYPE], \
779 builtin_types[(int) LIBTYPE], BOTH_P, FALLBACK_P, \
780 NONANSI_P, built_in_attributes[(int) ATTRS], IMPLICIT);
781
782 #undef DEF_HSAIL_BUILTIN
783 #define DEF_HSAIL_BUILTIN(ENUM, HSAIL_OPCODE, HSAIL_TYPE, NAME, TYPE, ATTRS) \
784 DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
785 false, true, true, ATTRS, false, true)
786
787 /* HSAIL atomic builtins do not have separate identifying opcodes. */
788
789 #undef DEF_HSAIL_ATOMIC_BUILTIN
790 #define DEF_HSAIL_ATOMIC_BUILTIN(ENUM, ATOMIC_OPCODE, HSAIL_TYPE, NAME, \
791 TYPE, ATTRS) \
792 DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
793 false, true, true, ATTRS, false, true)
794
795 /* HSAIL saturating arithmetics builtins. */
796
797 #undef DEF_HSAIL_SAT_BUILTIN
798 #define DEF_HSAIL_SAT_BUILTIN(ENUM, BRIG_OPCODE, HSAIL_TYPE, NAME, \
799 TYPE, ATTRS) \
800 DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
801 false, true, true, ATTRS, false, true)
802
803 /* HSAIL builtins used internally by the frontend. */
804
805 #undef DEF_HSAIL_INTR_BUILTIN
806 #define DEF_HSAIL_INTR_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
807 DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
808 false, true, true, ATTRS, false, true)
809
810 /* HSAIL saturated conversions. */
811
812 #undef DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN
813 #define DEF_HSAIL_CVT_ZEROI_SAT_BUILTIN(ENUM, HSAIL_DEST_TYPE, HSAIL_SRC_TYPE, \
814 NAME, TYPE, ATTRS) \
815 DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
816 false, true, true, ATTRS, false, true)
817
818 #include "builtins.def"
819 }
820
821 /* Build nodes that would have be created by the C front-end; necessary
822 for including builtin-types.def and ultimately builtins.def. Borrowed
823 from lto-lang.c. */
824
825 static void
826 brig_build_c_type_nodes (void)
827 {
828 gcc_assert (void_type_node);
829
830 void_list_node = build_tree_list (NULL_TREE, void_type_node);
831 string_type_node = build_pointer_type (char_type_node);
832 const_string_type_node
833 = build_pointer_type (build_qualified_type (char_type_node,
834 TYPE_QUAL_CONST));
835
836 if (strcmp (SIZE_TYPE, "unsigned int") == 0)
837 {
838 intmax_type_node = integer_type_node;
839 uintmax_type_node = unsigned_type_node;
840 signed_size_type_node = integer_type_node;
841 }
842 else if (strcmp (SIZE_TYPE, "long unsigned int") == 0)
843 {
844 intmax_type_node = long_integer_type_node;
845 uintmax_type_node = long_unsigned_type_node;
846 signed_size_type_node = long_integer_type_node;
847 }
848 else if (strcmp (SIZE_TYPE, "long long unsigned int") == 0)
849 {
850 intmax_type_node = long_long_integer_type_node;
851 uintmax_type_node = long_long_unsigned_type_node;
852 signed_size_type_node = long_long_integer_type_node;
853 }
854 else
855 {
856 int i;
857
858 signed_size_type_node = NULL_TREE;
859 for (i = 0; i < NUM_INT_N_ENTS; i++)
860 if (int_n_enabled_p[i])
861 {
862 char name[50];
863 sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
864
865 if (strcmp (name, SIZE_TYPE) == 0)
866 {
867 intmax_type_node = int_n_trees[i].signed_type;
868 uintmax_type_node = int_n_trees[i].unsigned_type;
869 signed_size_type_node = int_n_trees[i].signed_type;
870 }
871 }
872 if (signed_size_type_node == NULL_TREE)
873 gcc_unreachable ();
874 }
875
876 wint_type_node = unsigned_type_node;
877 pid_type_node = integer_type_node;
878 }
879
880
881 static bool
882 brig_langhook_init (void)
883 {
884 build_common_tree_nodes (false);
885
886 /* Builtin initialization related code borrowed from lto-lang.c. */
887 void_list_node = build_tree_list (NULL_TREE, void_type_node);
888
889 brig_build_c_type_nodes ();
890
891 if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
892 {
893 tree x = build_pointer_type (TREE_TYPE (va_list_type_node));
894 brig_define_builtins (x, x);
895 }
896 else
897 {
898 brig_define_builtins (build_reference_type (va_list_type_node),
899 va_list_type_node);
900 }
901
902 targetm.init_builtins ();
903 build_common_builtin_nodes ();
904
905 return true;
906 }
907
908 #undef LANG_HOOKS_NAME
909 #undef LANG_HOOKS_INIT
910 #undef LANG_HOOKS_OPTION_LANG_MASK
911 #undef LANG_HOOKS_INIT_OPTIONS_STRUCT
912 #undef LANG_HOOKS_HANDLE_OPTION
913 #undef LANG_HOOKS_POST_OPTIONS
914 #undef LANG_HOOKS_PARSE_FILE
915 #undef LANG_HOOKS_TYPE_FOR_MODE
916 #undef LANG_HOOKS_TYPE_FOR_SIZE
917 #undef LANG_HOOKS_REGISTER_BUILTIN_TYPE
918 #undef LANG_HOOKS_BUILTIN_FUNCTION
919 #undef LANG_HOOKS_GLOBAL_BINDINGS_P
920 #undef LANG_HOOKS_PUSHDECL
921 #undef LANG_HOOKS_GETDECLS
922 #undef LANG_HOOKS_WRITE_GLOBALS
923 #undef LANG_HOOKS_GIMPLIFY_EXPR
924 #undef LANG_HOOKS_EH_PERSONALITY
925
926 #define LANG_HOOKS_NAME "GNU Brig"
927 #define LANG_HOOKS_INIT brig_langhook_init
928 #define LANG_HOOKS_OPTION_LANG_MASK brig_langhook_option_lang_mask
929 #define LANG_HOOKS_INIT_OPTIONS_STRUCT brig_langhook_init_options_struct
930 #define LANG_HOOKS_HANDLE_OPTION brig_langhook_handle_option
931 #define LANG_HOOKS_POST_OPTIONS brig_langhook_post_options
932 #define LANG_HOOKS_PARSE_FILE brig_langhook_parse_file
933 #define LANG_HOOKS_TYPE_FOR_MODE brig_langhook_type_for_mode
934 #define LANG_HOOKS_TYPE_FOR_SIZE brig_langhook_type_for_size
935 #define LANG_HOOKS_REGISTER_BUILTIN_TYPE brig_langhook_register_builtin_type
936 #define LANG_HOOKS_BUILTIN_FUNCTION brig_langhook_builtin_function
937 #define LANG_HOOKS_GLOBAL_BINDINGS_P brig_langhook_global_bindings_p
938 #define LANG_HOOKS_PUSHDECL brig_langhook_pushdecl
939 #define LANG_HOOKS_GETDECLS brig_langhook_getdecls
940 #define LANG_HOOKS_GIMPLIFY_EXPR brig_langhook_gimplify_expr
941 #define LANG_HOOKS_EH_PERSONALITY brig_langhook_eh_personality
942
943 /* Attribute hooks. */
944 #undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
945 #define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE brig_attribute_table
946
947 struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
948
949 #include "gt-brig-brig-lang.h"
950 #include "gtype-brig.h"