1/* Target code for NVPTX.
2   Copyright (C) 2014-2015 Free Software Foundation, Inc.
3   Contributed by Bernd Schmidt <bernds@codesourcery.com>
4
5   This file is part of GCC.
6
7   GCC is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published
9   by the Free Software Foundation; either version 3, or (at your
10   option) any later version.
11
12   GCC is distributed in the hope that it will be useful, but WITHOUT
13   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15   License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with GCC; see the file COPYING3.  If not see
19   <http://www.gnu.org/licenses/>.  */
20
21#include "config.h"
22#include <sstream>
23#include "system.h"
24#include "coretypes.h"
25#include "tm.h"
26#include "rtl.h"
27#include "hash-set.h"
28#include "machmode.h"
29#include "vec.h"
30#include "double-int.h"
31#include "input.h"
32#include "alias.h"
33#include "symtab.h"
34#include "wide-int.h"
35#include "inchash.h"
36#include "tree.h"
37#include "insn-flags.h"
38#include "output.h"
39#include "insn-attr.h"
40#include "insn-codes.h"
41#include "hashtab.h"
42#include "hard-reg-set.h"
43#include "function.h"
44#include "flags.h"
45#include "statistics.h"
46#include "real.h"
47#include "fixed-value.h"
48#include "insn-config.h"
49#include "expmed.h"
50#include "dojump.h"
51#include "explow.h"
52#include "calls.h"
53#include "emit-rtl.h"
54#include "varasm.h"
55#include "stmt.h"
56#include "expr.h"
57#include "regs.h"
58#include "optabs.h"
59#include "recog.h"
60#include "ggc.h"
61#include "timevar.h"
62#include "tm_p.h"
63#include "tm-preds.h"
64#include "tm-constrs.h"
65#include "langhooks.h"
66#include "dbxout.h"
67#include "target.h"
68#include "target-def.h"
69#include "diagnostic.h"
70#include "predict.h"
71#include "basic-block.h"
72#include "cfgrtl.h"
73#include "stor-layout.h"
74#include "df.h"
75#include "builtins.h"
76
77/* Record the function decls we've written, and the libfuncs and function
78   decls corresponding to them.  */
79static std::stringstream func_decls;
80
81struct declared_libfunc_hasher : ggc_cache_hasher<rtx>
82{
83  static hashval_t hash (rtx x) { return htab_hash_pointer (x); }
84  static bool equal (rtx a, rtx b) { return a == b; }
85};
86
87static GTY((cache))
88  hash_table<declared_libfunc_hasher> *declared_libfuncs_htab;
89
90  struct tree_hasher : ggc_cache_hasher<tree>
91{
92  static hashval_t hash (tree t) { return htab_hash_pointer (t); }
93  static bool equal (tree a, tree b) { return a == b; }
94};
95
96static GTY((cache)) hash_table<tree_hasher> *declared_fndecls_htab;
97static GTY((cache)) hash_table<tree_hasher> *needed_fndecls_htab;
98
99/* Allocate a new, cleared machine_function structure.  */
100
101static struct machine_function *
102nvptx_init_machine_status (void)
103{
104  struct machine_function *p = ggc_cleared_alloc<machine_function> ();
105  p->ret_reg_mode = VOIDmode;
106  return p;
107}
108
109/* Implement TARGET_OPTION_OVERRIDE.  */
110
111static void
112nvptx_option_override (void)
113{
114  init_machine_status = nvptx_init_machine_status;
115  /* Gives us a predictable order, which we need especially for variables.  */
116  flag_toplevel_reorder = 1;
117  /* Assumes that it will see only hard registers.  */
118  flag_var_tracking = 0;
119  write_symbols = NO_DEBUG;
120  debug_info_level = DINFO_LEVEL_NONE;
121
122  declared_fndecls_htab = hash_table<tree_hasher>::create_ggc (17);
123  needed_fndecls_htab = hash_table<tree_hasher>::create_ggc (17);
124  declared_libfuncs_htab
125    = hash_table<declared_libfunc_hasher>::create_ggc (17);
126}
127
128/* Return the mode to be used when declaring a ptx object for OBJ.
129   For objects with subparts such as complex modes this is the mode
130   of the subpart.  */
131
132machine_mode
133nvptx_underlying_object_mode (rtx obj)
134{
135  if (GET_CODE (obj) == SUBREG)
136    obj = SUBREG_REG (obj);
137  machine_mode mode = GET_MODE (obj);
138  if (mode == TImode)
139    return DImode;
140  if (COMPLEX_MODE_P (mode))
141    return GET_MODE_INNER (mode);
142  return mode;
143}
144
145/* Return a ptx type for MODE.  If PROMOTE, then use .u32 for QImode to
146   deal with ptx ideosyncracies.  */
147
148const char *
149nvptx_ptx_type_from_mode (machine_mode mode, bool promote)
150{
151  switch (mode)
152    {
153    case BLKmode:
154      return ".b8";
155    case BImode:
156      return ".pred";
157    case QImode:
158      if (promote)
159	return ".u32";
160      else
161	return ".u8";
162    case HImode:
163      return ".u16";
164    case SImode:
165      return ".u32";
166    case DImode:
167      return ".u64";
168
169    case SFmode:
170      return ".f32";
171    case DFmode:
172      return ".f64";
173
174    default:
175      gcc_unreachable ();
176    }
177}
178
179/* Return the number of pieces to use when dealing with a pseudo of *PMODE.
180   Alter *PMODE if we return a number greater than one.  */
181
182static int
183maybe_split_mode (machine_mode *pmode)
184{
185  machine_mode mode = *pmode;
186
187  if (COMPLEX_MODE_P (mode))
188    {
189      *pmode = GET_MODE_INNER (mode);
190      return 2;
191    }
192  else if (mode == TImode)
193    {
194      *pmode = DImode;
195      return 2;
196    }
197  return 1;
198}
199
200/* Like maybe_split_mode, but only return whether or not the mode
201   needs to be split.  */
202static bool
203nvptx_split_reg_p (machine_mode mode)
204{
205  if (COMPLEX_MODE_P (mode))
206    return true;
207  if (mode == TImode)
208    return true;
209  return false;
210}
211
212#define PASS_IN_REG_P(MODE, TYPE)				\
213  ((GET_MODE_CLASS (MODE) == MODE_INT				\
214    || GET_MODE_CLASS (MODE) == MODE_FLOAT			\
215    || ((GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT		\
216	 || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)	\
217	&& !AGGREGATE_TYPE_P (TYPE)))				\
218   && (MODE) != TImode)
219
220#define RETURN_IN_REG_P(MODE)			\
221  ((GET_MODE_CLASS (MODE) == MODE_INT		\
222    || GET_MODE_CLASS (MODE) == MODE_FLOAT)	\
223   && GET_MODE_SIZE (MODE) <= 8)
224
225/* Perform a mode promotion for a function argument with MODE.  Return
226   the promoted mode.  */
227
228static machine_mode
229arg_promotion (machine_mode mode)
230{
231  if (mode == QImode || mode == HImode)
232    return SImode;
233  return mode;
234}
235
236/* Write the declaration of a function arg of TYPE to S.  I is the index
237   of the argument, MODE its mode.  NO_ARG_TYPES is true if this is for
238   a decl with zero TYPE_ARG_TYPES, i.e. an old-style C decl.  */
239
240static int
241write_one_arg (std::stringstream &s, tree type, int i, machine_mode mode,
242	       bool no_arg_types)
243{
244  if (!PASS_IN_REG_P (mode, type))
245    mode = Pmode;
246
247  int count = maybe_split_mode (&mode);
248
249  if (count == 2)
250    {
251      write_one_arg (s, NULL_TREE, i, mode, false);
252      write_one_arg (s, NULL_TREE, i + 1, mode, false);
253      return i + 1;
254    }
255
256  if (no_arg_types && !AGGREGATE_TYPE_P (type))
257    {
258      if (mode == SFmode)
259	mode = DFmode;
260      mode = arg_promotion (mode);
261    }
262
263  if (i > 0)
264    s << ", ";
265  s << ".param" << nvptx_ptx_type_from_mode (mode, false) << " %in_ar"
266    << (i + 1) << (mode == QImode || mode == HImode ? "[1]" : "");
267  if (mode == BLKmode)
268    s << "[" << int_size_in_bytes (type) << "]";
269  return i;
270}
271
272/* Look for attributes in ATTRS that would indicate we must write a function
273   as a .entry kernel rather than a .func.  Return true if one is found.  */
274
275static bool
276write_as_kernel (tree attrs)
277{
278  return (lookup_attribute ("kernel", attrs) != NULL_TREE
279	  || lookup_attribute ("omp target entrypoint", attrs) != NULL_TREE);
280}
281
282/* Write a function decl for DECL to S, where NAME is the name to be used.  */
283
284static void
285nvptx_write_function_decl (std::stringstream &s, const char *name, const_tree decl)
286{
287  tree fntype = TREE_TYPE (decl);
288  tree result_type = TREE_TYPE (fntype);
289  tree args = TYPE_ARG_TYPES (fntype);
290  tree attrs = DECL_ATTRIBUTES (decl);
291  bool kernel = write_as_kernel (attrs);
292  bool is_main = strcmp (name, "main") == 0;
293  bool args_from_decl = false;
294
295  /* We get:
296     NULL in TYPE_ARG_TYPES, for old-style functions
297     NULL in DECL_ARGUMENTS, for builtin functions without another
298       declaration.
299     So we have to pick the best one we have.  */
300  if (args == 0)
301    {
302      args = DECL_ARGUMENTS (decl);
303      args_from_decl = true;
304    }
305
306  if (DECL_EXTERNAL (decl))
307    s << ".extern ";
308  else if (TREE_PUBLIC (decl))
309    s << ".visible ";
310
311  if (kernel)
312    s << ".entry ";
313  else
314    s << ".func ";
315
316  /* Declare the result.  */
317  bool return_in_mem = false;
318  if (TYPE_MODE (result_type) != VOIDmode)
319    {
320      machine_mode mode = TYPE_MODE (result_type);
321      if (!RETURN_IN_REG_P (mode))
322	return_in_mem = true;
323      else
324	{
325	  mode = arg_promotion (mode);
326	  s << "(.param" << nvptx_ptx_type_from_mode (mode, false)
327	    << " %out_retval)";
328	}
329    }
330
331  if (name[0] == '*')
332    s << (name + 1);
333  else
334    s << name;
335
336  /* Declare argument types.  */
337  if ((args != NULL_TREE
338       && !(TREE_CODE (args) == TREE_LIST && TREE_VALUE (args) == void_type_node))
339      || is_main
340      || return_in_mem
341      || DECL_STATIC_CHAIN (decl))
342    {
343      s << "(";
344      int i = 0;
345      bool any_args = false;
346      if (return_in_mem)
347	{
348	  s << ".param.u" << GET_MODE_BITSIZE (Pmode) << " %in_ar1";
349	  i++;
350	}
351      while (args != NULL_TREE)
352	{
353	  tree type = args_from_decl ? TREE_TYPE (args) : TREE_VALUE (args);
354	  machine_mode mode = TYPE_MODE (type);
355
356	  if (mode != VOIDmode)
357	    {
358	      i = write_one_arg (s, type, i, mode,
359				 TYPE_ARG_TYPES (fntype) == 0);
360	      any_args = true;
361	      i++;
362	    }
363	  args = TREE_CHAIN (args);
364	}
365      if (stdarg_p (fntype))
366	{
367	  gcc_assert (i > 0);
368	  s << ", .param.u" << GET_MODE_BITSIZE (Pmode) << " %in_argp";
369	}
370      if (DECL_STATIC_CHAIN (decl))
371	{
372	  if (i > 0)
373	    s << ", ";
374	  s << ".reg.u" << GET_MODE_BITSIZE (Pmode)
375	    << reg_names [STATIC_CHAIN_REGNUM];
376	}
377      if (!any_args && is_main)
378	s << ".param.u32 %argc, .param.u" << GET_MODE_BITSIZE (Pmode)
379	  << " %argv";
380      s << ")";
381    }
382}
383
384/* Walk either ARGTYPES or ARGS if the former is null, and write out part of
385   the function header to FILE.  If WRITE_COPY is false, write reg
386   declarations, otherwise write the copy from the incoming argument to that
387   reg.  RETURN_IN_MEM indicates whether to start counting arg numbers at 1
388   instead of 0.  */
389
390static void
391walk_args_for_param (FILE *file, tree argtypes, tree args, bool write_copy,
392		     bool return_in_mem)
393{
394  int i;
395
396  bool args_from_decl = false;
397  if (argtypes == 0)
398    args_from_decl = true;
399  else
400    args = argtypes;
401
402  for (i = return_in_mem ? 1 : 0; args != NULL_TREE; args = TREE_CHAIN (args))
403    {
404      tree type = args_from_decl ? TREE_TYPE (args) : TREE_VALUE (args);
405      machine_mode mode = TYPE_MODE (type);
406
407      if (mode == VOIDmode)
408	break;
409
410      if (!PASS_IN_REG_P (mode, type))
411	mode = Pmode;
412
413      int count = maybe_split_mode (&mode);
414      if (count == 1)
415	{
416	  if (argtypes == NULL && !AGGREGATE_TYPE_P (type))
417	    {
418	      if (mode == SFmode)
419		mode = DFmode;
420
421	    }
422	  mode = arg_promotion (mode);
423	}
424      while (count-- > 0)
425	{
426	  i++;
427	  if (write_copy)
428	    fprintf (file, "\tld.param%s %%ar%d, [%%in_ar%d];\n",
429		     nvptx_ptx_type_from_mode (mode, false), i, i);
430	  else
431	    fprintf (file, "\t.reg%s %%ar%d;\n",
432		     nvptx_ptx_type_from_mode (mode, false), i);
433	}
434    }
435}
436
437/* Write a .func or .kernel declaration (not a definition) along with
438   a helper comment for use by ld.  S is the stream to write to, DECL
439   the decl for the function with name NAME.  */
440
441static void
442write_function_decl_and_comment (std::stringstream &s, const char *name, const_tree decl)
443{
444  s << "// BEGIN";
445  if (TREE_PUBLIC (decl))
446    s << " GLOBAL";
447  s << " FUNCTION DECL: ";
448  if (name[0] == '*')
449    s << (name + 1);
450  else
451    s << name;
452  s << "\n";
453  nvptx_write_function_decl (s, name, decl);
454  s << ";\n";
455}
456
457/* Check NAME for special function names and redirect them by returning a
458   replacement.  This applies to malloc, free and realloc, for which we
459   want to use libgcc wrappers, and call, which triggers a bug in ptxas.  */
460
461static const char *
462nvptx_name_replacement (const char *name)
463{
464  if (strcmp (name, "call") == 0)
465    return "__nvptx_call";
466  if (strcmp (name, "malloc") == 0)
467    return "__nvptx_malloc";
468  if (strcmp (name, "free") == 0)
469    return "__nvptx_free";
470  if (strcmp (name, "realloc") == 0)
471    return "__nvptx_realloc";
472  return name;
473}
474
475/* If DECL is a FUNCTION_DECL, check the hash table to see if we
476   already encountered it, and if not, insert it and write a ptx
477   declarations that will be output at the end of compilation.  */
478
479static bool
480nvptx_record_fndecl (tree decl, bool force = false)
481{
482  if (decl == NULL_TREE || TREE_CODE (decl) != FUNCTION_DECL
483      || !DECL_EXTERNAL (decl))
484    return true;
485
486  if (!force && TYPE_ARG_TYPES (TREE_TYPE (decl)) == NULL_TREE)
487    return false;
488
489  tree *slot = declared_fndecls_htab->find_slot (decl, INSERT);
490  if (*slot == NULL)
491    {
492      *slot = decl;
493      const char *name = get_fnname_from_decl (decl);
494      name = nvptx_name_replacement (name);
495      write_function_decl_and_comment (func_decls, name, decl);
496    }
497  return true;
498}
499
500/* Record that we need to emit a ptx decl for DECL.  Either do it now, or
501   record it for later in case we have no argument information at this
502   point.  */
503
504void
505nvptx_record_needed_fndecl (tree decl)
506{
507  if (nvptx_record_fndecl (decl))
508    return;
509
510  tree *slot = needed_fndecls_htab->find_slot (decl, INSERT);
511  if (*slot == NULL)
512    *slot = decl;
513}
514
515/* Implement ASM_DECLARE_FUNCTION_NAME.  Writes the start of a ptx
516   function, including local var decls and copies from the arguments to
517   local regs.  */
518
519void
520nvptx_declare_function_name (FILE *file, const char *name, const_tree decl)
521{
522  tree fntype = TREE_TYPE (decl);
523  tree result_type = TREE_TYPE (fntype);
524
525  name = nvptx_name_replacement (name);
526
527  std::stringstream s;
528  write_function_decl_and_comment (s, name, decl);
529  s << "// BEGIN";
530  if (TREE_PUBLIC (decl))
531    s << " GLOBAL";
532  s << " FUNCTION DEF: ";
533
534  if (name[0] == '*')
535    s << (name + 1);
536  else
537    s << name;
538  s << "\n";
539
540  nvptx_write_function_decl (s, name, decl);
541  fprintf (file, "%s", s.str().c_str());
542
543  bool return_in_mem = false;
544  if (TYPE_MODE (result_type) != VOIDmode)
545    {
546      machine_mode mode = TYPE_MODE (result_type);
547      if (!RETURN_IN_REG_P (mode))
548	return_in_mem = true;
549    }
550
551  fprintf (file, "\n{\n");
552
553  /* Ensure all arguments that should live in a register have one
554     declared.  We'll emit the copies below.  */
555  walk_args_for_param (file, TYPE_ARG_TYPES (fntype), DECL_ARGUMENTS (decl),
556		       false, return_in_mem);
557  if (return_in_mem)
558    fprintf (file, "\t.reg.u%d %%ar1;\n", GET_MODE_BITSIZE (Pmode));
559  else if (TYPE_MODE (result_type) != VOIDmode)
560    {
561      machine_mode mode = arg_promotion (TYPE_MODE (result_type));
562      fprintf (file, ".reg%s %%retval;\n",
563	       nvptx_ptx_type_from_mode (mode, false));
564    }
565
566  if (stdarg_p (fntype))
567    fprintf (file, "\t.reg.u%d %%argp;\n", GET_MODE_BITSIZE (Pmode));
568
569  fprintf (file, "\t.reg.u%d %s;\n", GET_MODE_BITSIZE (Pmode),
570	   reg_names[OUTGOING_STATIC_CHAIN_REGNUM]);
571
572  /* Declare the pseudos we have as ptx registers.  */
573  int maxregs = max_reg_num ();
574  for (int i = LAST_VIRTUAL_REGISTER + 1; i < maxregs; i++)
575    {
576      if (regno_reg_rtx[i] != const0_rtx)
577	{
578	  machine_mode mode = PSEUDO_REGNO_MODE (i);
579	  int count = maybe_split_mode (&mode);
580	  if (count > 1)
581	    {
582	      while (count-- > 0)
583		fprintf (file, "\t.reg%s %%r%d$%d;\n",
584			 nvptx_ptx_type_from_mode (mode, true),
585			 i, count);
586	    }
587	  else
588	    fprintf (file, "\t.reg%s %%r%d;\n",
589		     nvptx_ptx_type_from_mode (mode, true),
590		     i);
591	}
592    }
593
594  /* The only reason we might be using outgoing args is if we call a stdargs
595     function.  Allocate the space for this.  If we called varargs functions
596     without passing any variadic arguments, we'll see a reference to outargs
597     even with a zero outgoing_args_size.  */
598  HOST_WIDE_INT sz = crtl->outgoing_args_size;
599  if (sz == 0)
600    sz = 1;
601  if (cfun->machine->has_call_with_varargs)
602    fprintf (file, "\t.reg.u%d %%outargs;\n"
603	     "\t.local.align 8 .b8 %%outargs_ar["HOST_WIDE_INT_PRINT_DEC"];\n",
604	     BITS_PER_WORD, sz);
605  if (cfun->machine->punning_buffer_size > 0)
606    fprintf (file, "\t.reg.u%d %%punbuffer;\n"
607	     "\t.local.align 8 .b8 %%punbuffer_ar[%d];\n",
608	     BITS_PER_WORD, cfun->machine->punning_buffer_size);
609
610  /* Declare a local variable for the frame.  */
611  sz = get_frame_size ();
612  if (sz > 0 || cfun->machine->has_call_with_sc)
613    {
614      fprintf (file, "\t.reg.u%d %%frame;\n"
615	       "\t.local.align 8 .b8 %%farray["HOST_WIDE_INT_PRINT_DEC"];\n",
616	       BITS_PER_WORD, sz == 0 ? 1 : sz);
617      fprintf (file, "\tcvta.local.u%d %%frame, %%farray;\n",
618	       BITS_PER_WORD);
619    }
620
621  if (cfun->machine->has_call_with_varargs)
622      fprintf (file, "\tcvta.local.u%d %%outargs, %%outargs_ar;\n",
623	       BITS_PER_WORD);
624  if (cfun->machine->punning_buffer_size > 0)
625      fprintf (file, "\tcvta.local.u%d %%punbuffer, %%punbuffer_ar;\n",
626	       BITS_PER_WORD);
627
628  /* Now emit any copies necessary for arguments.  */
629  walk_args_for_param (file, TYPE_ARG_TYPES (fntype), DECL_ARGUMENTS (decl),
630		       true, return_in_mem);
631  if (return_in_mem)
632    fprintf (file, "ld.param.u%d %%ar1, [%%in_ar1];\n",
633	     GET_MODE_BITSIZE (Pmode));
634  if (stdarg_p (fntype))
635    fprintf (file, "ld.param.u%d %%argp, [%%in_argp];\n",
636	     GET_MODE_BITSIZE (Pmode));
637}
638
639/* Output a return instruction.  Also copy the return value to its outgoing
640   location.  */
641
642const char *
643nvptx_output_return (void)
644{
645  tree fntype = TREE_TYPE (current_function_decl);
646  tree result_type = TREE_TYPE (fntype);
647  if (TYPE_MODE (result_type) != VOIDmode)
648    {
649      machine_mode mode = TYPE_MODE (result_type);
650      if (RETURN_IN_REG_P (mode))
651	{
652	  mode = arg_promotion (mode);
653	  fprintf (asm_out_file, "\tst.param%s\t[%%out_retval], %%retval;\n",
654		   nvptx_ptx_type_from_mode (mode, false));
655	}
656    }
657
658  return "ret;";
659}
660
661/* Construct a function declaration from a call insn.  This can be
662   necessary for two reasons - either we have an indirect call which
663   requires a .callprototype declaration, or we have a libcall
664   generated by emit_library_call for which no decl exists.  */
665
666static void
667write_func_decl_from_insn (std::stringstream &s, rtx result, rtx pat,
668			   rtx callee)
669{
670  bool callprototype = register_operand (callee, Pmode);
671  const char *name = "_";
672  if (!callprototype)
673    {
674      name = XSTR (callee, 0);
675      name = nvptx_name_replacement (name);
676      s << "// BEGIN GLOBAL FUNCTION DECL: " << name << "\n";
677    }
678  s << (callprototype ? "\t.callprototype\t" : "\t.extern .func ");
679
680  if (result != NULL_RTX)
681    {
682      s << "(.param";
683      s << nvptx_ptx_type_from_mode (arg_promotion (GET_MODE (result)),
684				     false);
685      s << " ";
686      if (callprototype)
687	s << "_";
688      else
689	s << "%out_retval";
690      s << ")";
691    }
692
693  s << name;
694
695  int nargs = XVECLEN (pat, 0) - 1;
696  if (nargs > 0)
697    {
698      s << " (";
699      for (int i = 0; i < nargs; i++)
700	{
701	  rtx t = XEXP (XVECEXP (pat, 0, i + 1), 0);
702	  machine_mode mode = GET_MODE (t);
703	  int count = maybe_split_mode (&mode);
704
705	  while (count-- > 0)
706	    {
707	      s << ".param";
708	      s << nvptx_ptx_type_from_mode (mode, false);
709	      s << " ";
710	      if (callprototype)
711		s << "_";
712	      else
713		s << "%arg" << i;
714	      if (mode == QImode || mode == HImode)
715		s << "[1]";
716	      if (i + 1 < nargs || count > 0)
717		s << ", ";
718	    }
719	}
720      s << ")";
721    }
722  s << ";\n";
723}
724
725/* Terminate a function by writing a closing brace to FILE.  */
726
727void
728nvptx_function_end (FILE *file)
729{
730  fprintf (file, "\t}\n");
731}
732
733/* Decide whether we can make a sibling call to a function.  For ptx, we
734   can't.  */
735
736static bool
737nvptx_function_ok_for_sibcall (tree, tree)
738{
739  return false;
740}
741
742/* Implement the TARGET_CALL_ARGS hook.  Record information about one
743   argument to the next call.  */
744
745static void
746nvptx_call_args (rtx arg, tree funtype)
747{
748  if (cfun->machine->start_call == NULL_RTX)
749    {
750      cfun->machine->call_args = NULL;
751      cfun->machine->funtype = funtype;
752      cfun->machine->start_call = const0_rtx;
753    }
754  if (arg == pc_rtx)
755    return;
756
757  rtx_expr_list *args_so_far = cfun->machine->call_args;
758  if (REG_P (arg))
759    cfun->machine->call_args = alloc_EXPR_LIST (VOIDmode, arg, args_so_far);
760}
761
762/* Implement the corresponding END_CALL_ARGS hook.  Clear and free the
763   information we recorded.  */
764
765static void
766nvptx_end_call_args (void)
767{
768  cfun->machine->start_call = NULL_RTX;
769  free_EXPR_LIST_list (&cfun->machine->call_args);
770}
771
772/* Emit the sequence for a call.  */
773
774void
775nvptx_expand_call (rtx retval, rtx address)
776{
777  int nargs;
778  rtx callee = XEXP (address, 0);
779  rtx pat, t;
780  rtvec vec;
781  bool external_decl = false;
782
783  nargs = 0;
784  for (t = cfun->machine->call_args; t; t = XEXP (t, 1))
785    nargs++;
786
787  bool has_varargs = false;
788  tree decl_type = NULL_TREE;
789
790  if (!call_insn_operand (callee, Pmode))
791    {
792      callee = force_reg (Pmode, callee);
793      address = change_address (address, QImode, callee);
794    }
795
796  if (GET_CODE (callee) == SYMBOL_REF)
797    {
798      tree decl = SYMBOL_REF_DECL (callee);
799      if (decl != NULL_TREE)
800	{
801	  decl_type = TREE_TYPE (decl);
802	  if (DECL_STATIC_CHAIN (decl))
803	    cfun->machine->has_call_with_sc = true;
804	  if (DECL_EXTERNAL (decl))
805	    external_decl = true;
806	}
807    }
808  if (cfun->machine->funtype
809      /* It's possible to construct testcases where we call a variable.
810	 See compile/20020129-1.c.  stdarg_p will crash so avoid calling it
811	 in such a case.  */
812      && (TREE_CODE (cfun->machine->funtype) == FUNCTION_TYPE
813	  || TREE_CODE (cfun->machine->funtype) == METHOD_TYPE)
814      && stdarg_p (cfun->machine->funtype))
815    {
816      has_varargs = true;
817      cfun->machine->has_call_with_varargs = true;
818    }
819  vec = rtvec_alloc (nargs + 1 + (has_varargs ? 1 : 0));
820  pat = gen_rtx_PARALLEL (VOIDmode, vec);
821  if (has_varargs)
822    {
823      rtx this_arg = gen_reg_rtx (Pmode);
824      if (Pmode == DImode)
825	emit_move_insn (this_arg, stack_pointer_rtx);
826      else
827	emit_move_insn (this_arg, stack_pointer_rtx);
828      XVECEXP (pat, 0, nargs + 1) = gen_rtx_USE (VOIDmode, this_arg);
829    }
830
831  int i;
832  rtx arg;
833  for (i = 1, arg = cfun->machine->call_args; arg; arg = XEXP (arg, 1), i++)
834    {
835      rtx this_arg = XEXP (arg, 0);
836      XVECEXP (pat, 0, i) = gen_rtx_USE (VOIDmode, this_arg);
837    }
838
839  rtx tmp_retval = retval;
840  t = gen_rtx_CALL (VOIDmode, address, const0_rtx);
841  if (retval != NULL_RTX)
842    {
843      if (!nvptx_register_operand (retval, GET_MODE (retval)))
844	tmp_retval = gen_reg_rtx (GET_MODE (retval));
845      t = gen_rtx_SET (VOIDmode, tmp_retval, t);
846    }
847  XVECEXP (pat, 0, 0) = t;
848  if (!REG_P (callee)
849      && (decl_type == NULL_TREE
850	  || (external_decl && TYPE_ARG_TYPES (decl_type) == NULL_TREE)))
851    {
852      rtx *slot = declared_libfuncs_htab->find_slot (callee, INSERT);
853      if (*slot == NULL)
854	{
855	  *slot = callee;
856	  write_func_decl_from_insn (func_decls, retval, pat, callee);
857	}
858    }
859  emit_call_insn (pat);
860  if (tmp_retval != retval)
861    emit_move_insn (retval, tmp_retval);
862}
863
864/* Implement TARGET_FUNCTION_ARG.  */
865
866static rtx
867nvptx_function_arg (cumulative_args_t, machine_mode mode,
868		    const_tree, bool named)
869{
870  if (mode == VOIDmode)
871    return NULL_RTX;
872
873  if (named)
874    return gen_reg_rtx (mode);
875  return NULL_RTX;
876}
877
878/* Implement TARGET_FUNCTION_INCOMING_ARG.  */
879
880static rtx
881nvptx_function_incoming_arg (cumulative_args_t cum_v, machine_mode mode,
882			     const_tree, bool named)
883{
884  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
885  if (mode == VOIDmode)
886    return NULL_RTX;
887
888  if (!named)
889    return NULL_RTX;
890
891  /* No need to deal with split modes here, the only case that can
892     happen is complex modes and those are dealt with by
893     TARGET_SPLIT_COMPLEX_ARG.  */
894  return gen_rtx_UNSPEC (mode,
895			 gen_rtvec (1, GEN_INT (1 + cum->count)),
896			 UNSPEC_ARG_REG);
897}
898
899/* Implement TARGET_FUNCTION_ARG_ADVANCE.  */
900
901static void
902nvptx_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
903			    const_tree type ATTRIBUTE_UNUSED,
904			    bool named ATTRIBUTE_UNUSED)
905{
906  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
907  if (mode == TImode)
908    cum->count += 2;
909  else
910    cum->count++;
911}
912
913/* Handle the TARGET_STRICT_ARGUMENT_NAMING target hook.
914
915   For nvptx, we know how to handle functions declared as stdarg: by
916   passing an extra pointer to the unnamed arguments.  However, the
917   Fortran frontend can produce a different situation, where a
918   function pointer is declared with no arguments, but the actual
919   function and calls to it take more arguments.  In that case, we
920   want to ensure the call matches the definition of the function.  */
921
922static bool
923nvptx_strict_argument_naming (cumulative_args_t cum_v)
924{
925  CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
926  return cum->fntype == NULL_TREE || stdarg_p (cum->fntype);
927}
928
929/* Implement TARGET_FUNCTION_ARG_BOUNDARY.  */
930
931static unsigned int
932nvptx_function_arg_boundary (machine_mode mode, const_tree type)
933{
934  unsigned int boundary = type ? TYPE_ALIGN (type) : GET_MODE_BITSIZE (mode);
935
936  if (boundary > BITS_PER_WORD)
937    return 2 * BITS_PER_WORD;
938
939  if (mode == BLKmode)
940    {
941      HOST_WIDE_INT size = int_size_in_bytes (type);
942      if (size > 4)
943        return 2 * BITS_PER_WORD;
944      if (boundary < BITS_PER_WORD)
945        {
946          if (size >= 3)
947            return BITS_PER_WORD;
948          if (size >= 2)
949            return 2 * BITS_PER_UNIT;
950        }
951    }
952  return boundary;
953}
954
955/* TARGET_FUNCTION_VALUE implementation.  Returns an RTX representing the place
956   where function FUNC returns or receives a value of data type TYPE.  */
957
958static rtx
959nvptx_function_value (const_tree type, const_tree func ATTRIBUTE_UNUSED,
960		      bool outgoing)
961{
962  int unsignedp = TYPE_UNSIGNED (type);
963  machine_mode orig_mode = TYPE_MODE (type);
964  machine_mode mode = promote_function_mode (type, orig_mode,
965					     &unsignedp, NULL_TREE, 1);
966  if (outgoing)
967    return gen_rtx_REG (mode, NVPTX_RETURN_REGNUM);
968  if (cfun->machine->start_call == NULL_RTX)
969    /* Pretend to return in a hard reg for early uses before pseudos can be
970       generated.  */
971    return gen_rtx_REG (mode, NVPTX_RETURN_REGNUM);
972  return gen_reg_rtx (mode);
973}
974
975/* Implement TARGET_LIBCALL_VALUE.  */
976
977static rtx
978nvptx_libcall_value (machine_mode mode, const_rtx)
979{
980  if (cfun->machine->start_call == NULL_RTX)
981    /* Pretend to return in a hard reg for early uses before pseudos can be
982       generated.  */
983    return gen_rtx_REG (mode, NVPTX_RETURN_REGNUM);
984  return gen_reg_rtx (mode);
985}
986
987/* Implement TARGET_FUNCTION_VALUE_REGNO_P.  */
988
989static bool
990nvptx_function_value_regno_p (const unsigned int regno)
991{
992  return regno == NVPTX_RETURN_REGNUM;
993}
994
995/* Types with a mode other than those supported by the machine are passed by
996   reference in memory.  */
997
998static bool
999nvptx_pass_by_reference (cumulative_args_t, machine_mode mode,
1000			 const_tree type, bool)
1001{
1002  return !PASS_IN_REG_P (mode, type);
1003}
1004
1005/* Implement TARGET_RETURN_IN_MEMORY.  */
1006
1007static bool
1008nvptx_return_in_memory (const_tree type, const_tree)
1009{
1010  machine_mode mode = TYPE_MODE (type);
1011  if (!RETURN_IN_REG_P (mode))
1012    return true;
1013  return false;
1014}
1015
1016/* Implement TARGET_PROMOTE_FUNCTION_MODE.  */
1017
1018static machine_mode
1019nvptx_promote_function_mode (const_tree type, machine_mode mode,
1020			     int *punsignedp,
1021			     const_tree funtype, int for_return)
1022{
1023  if (type == NULL_TREE)
1024    return mode;
1025  if (for_return)
1026    return promote_mode (type, mode, punsignedp);
1027  /* For K&R-style functions, try to match the language promotion rules to
1028     minimize type mismatches at assembly time.  */
1029  if (TYPE_ARG_TYPES (funtype) == NULL_TREE
1030      && type != NULL_TREE
1031      && !AGGREGATE_TYPE_P (type))
1032    {
1033      if (mode == SFmode)
1034	mode = DFmode;
1035      mode = arg_promotion (mode);
1036    }
1037
1038  return mode;
1039}
1040
1041/* Implement TARGET_STATIC_CHAIN.  */
1042
1043static rtx
1044nvptx_static_chain (const_tree fndecl, bool incoming_p)
1045{
1046  if (!DECL_STATIC_CHAIN (fndecl))
1047    return NULL;
1048
1049  if (incoming_p)
1050    return gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
1051  else
1052    return gen_rtx_REG (Pmode, OUTGOING_STATIC_CHAIN_REGNUM);
1053}
1054
1055/* Emit a comparison COMPARE, and return the new test to be used in the
1056   jump.  */
1057
1058rtx
1059nvptx_expand_compare (rtx compare)
1060{
1061  rtx pred = gen_reg_rtx (BImode);
1062  rtx cmp = gen_rtx_fmt_ee (GET_CODE (compare), BImode,
1063			    XEXP (compare, 0), XEXP (compare, 1));
1064  emit_insn (gen_rtx_SET (VOIDmode, pred, cmp));
1065  return gen_rtx_NE (BImode, pred, const0_rtx);
1066}
1067
1068/* When loading an operand ORIG_OP, verify whether an address space
1069   conversion to generic is required, and if so, perform it.  Also
1070   check for SYMBOL_REFs for function decls and call
1071   nvptx_record_needed_fndecl as needed.
1072   Return either the original operand, or the converted one.  */
1073
1074rtx
1075nvptx_maybe_convert_symbolic_operand (rtx orig_op)
1076{
1077  if (GET_MODE (orig_op) != Pmode)
1078    return orig_op;
1079
1080  rtx op = orig_op;
1081  while (GET_CODE (op) == PLUS || GET_CODE (op) == CONST)
1082    op = XEXP (op, 0);
1083  if (GET_CODE (op) != SYMBOL_REF)
1084    return orig_op;
1085
1086  tree decl = SYMBOL_REF_DECL (op);
1087  if (decl && TREE_CODE (decl) == FUNCTION_DECL)
1088    {
1089      nvptx_record_needed_fndecl (decl);
1090      return orig_op;
1091    }
1092
1093  addr_space_t as = nvptx_addr_space_from_address (op);
1094  if (as == ADDR_SPACE_GENERIC)
1095    return orig_op;
1096
1097  enum unspec code;
1098  code = (as == ADDR_SPACE_GLOBAL ? UNSPEC_FROM_GLOBAL
1099	  : as == ADDR_SPACE_LOCAL ? UNSPEC_FROM_LOCAL
1100	  : as == ADDR_SPACE_SHARED ? UNSPEC_FROM_SHARED
1101	  : as == ADDR_SPACE_CONST ? UNSPEC_FROM_CONST
1102	  : UNSPEC_FROM_PARAM);
1103  rtx dest = gen_reg_rtx (Pmode);
1104  emit_insn (gen_rtx_SET (VOIDmode, dest,
1105			  gen_rtx_UNSPEC (Pmode, gen_rtvec (1, orig_op),
1106					  code)));
1107  return dest;
1108}
1109
1110/* Returns true if X is a valid address for use in a memory reference.  */
1111
1112static bool
1113nvptx_legitimate_address_p (machine_mode, rtx x, bool)
1114{
1115  enum rtx_code code = GET_CODE (x);
1116
1117  switch (code)
1118    {
1119    case REG:
1120      return true;
1121
1122    case PLUS:
1123      if (REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1)))
1124	return true;
1125      return false;
1126
1127    case CONST:
1128    case SYMBOL_REF:
1129    case LABEL_REF:
1130      return true;
1131
1132    default:
1133      return false;
1134    }
1135}
1136
1137/* Implement HARD_REGNO_MODE_OK.  We barely use hard regs, but we want
1138   to ensure that the return register's mode isn't changed.  */
1139
1140bool
1141nvptx_hard_regno_mode_ok (int regno, machine_mode mode)
1142{
1143  if (regno != NVPTX_RETURN_REGNUM
1144      || cfun == NULL || cfun->machine->ret_reg_mode == VOIDmode)
1145    return true;
1146  return mode == cfun->machine->ret_reg_mode;
1147}
1148
1149/* Convert an address space AS to the corresponding ptx string.  */
1150
1151const char *
1152nvptx_section_from_addr_space (addr_space_t as)
1153{
1154  switch (as)
1155    {
1156    case ADDR_SPACE_CONST:
1157      return ".const";
1158
1159    case ADDR_SPACE_GLOBAL:
1160      return ".global";
1161
1162    case ADDR_SPACE_SHARED:
1163      return ".shared";
1164
1165    case ADDR_SPACE_GENERIC:
1166      return "";
1167
1168    default:
1169      gcc_unreachable ();
1170    }
1171}
1172
1173/* Determine whether DECL goes into .const or .global.  */
1174
1175const char *
1176nvptx_section_for_decl (const_tree decl)
1177{
1178  bool is_const = (CONSTANT_CLASS_P (decl)
1179		   || TREE_CODE (decl) == CONST_DECL
1180		   || TREE_READONLY (decl));
1181  if (is_const)
1182    return ".const";
1183
1184  return ".global";
1185}
1186
1187/* Look for a SYMBOL_REF in ADDR and return the address space to be used
1188   for the insn referencing this address.  */
1189
1190addr_space_t
1191nvptx_addr_space_from_address (rtx addr)
1192{
1193  while (GET_CODE (addr) == PLUS || GET_CODE (addr) == CONST)
1194    addr = XEXP (addr, 0);
1195  if (GET_CODE (addr) != SYMBOL_REF)
1196    return ADDR_SPACE_GENERIC;
1197
1198  tree decl = SYMBOL_REF_DECL (addr);
1199  if (decl == NULL_TREE || TREE_CODE (decl) == FUNCTION_DECL)
1200    return ADDR_SPACE_GENERIC;
1201
1202  bool is_const = (CONSTANT_CLASS_P (decl)
1203		   || TREE_CODE (decl) == CONST_DECL
1204		   || TREE_READONLY (decl));
1205  if (is_const)
1206    return ADDR_SPACE_CONST;
1207
1208  return ADDR_SPACE_GLOBAL;
1209}
1210
1211/* Machinery to output constant initializers.  */
1212
1213/* Used when assembling integers to ensure data is emitted in
1214   pieces whose size matches the declaration we printed.  */
1215static unsigned int decl_chunk_size;
1216static machine_mode decl_chunk_mode;
1217/* Used in the same situation, to keep track of the byte offset
1218   into the initializer.  */
1219static unsigned HOST_WIDE_INT decl_offset;
1220/* The initializer part we are currently processing.  */
1221static HOST_WIDE_INT init_part;
1222/* The total size of the object.  */
1223static unsigned HOST_WIDE_INT object_size;
1224/* True if we found a skip extending to the end of the object.  Used to
1225   assert that no data follows.  */
1226static bool object_finished;
1227
1228/* Write the necessary separator string to begin a new initializer value.  */
1229
1230static void
1231begin_decl_field (void)
1232{
1233  /* We never see decl_offset at zero by the time we get here.  */
1234  if (decl_offset == decl_chunk_size)
1235    fprintf (asm_out_file, " = { ");
1236  else
1237    fprintf (asm_out_file, ", ");
1238}
1239
1240/* Output the currently stored chunk as an initializer value.  */
1241
1242static void
1243output_decl_chunk (void)
1244{
1245  begin_decl_field ();
1246  output_address (gen_int_mode (init_part, decl_chunk_mode));
1247  init_part = 0;
1248}
1249
1250/* Add value VAL sized SIZE to the data we're emitting, and keep writing
1251   out chunks as they fill up.  */
1252
1253static void
1254nvptx_assemble_value (HOST_WIDE_INT val, unsigned int size)
1255{
1256  unsigned HOST_WIDE_INT chunk_offset = decl_offset % decl_chunk_size;
1257  gcc_assert (!object_finished);
1258  while (size > 0)
1259    {
1260      int this_part = size;
1261      if (chunk_offset + this_part > decl_chunk_size)
1262	this_part = decl_chunk_size - chunk_offset;
1263      HOST_WIDE_INT val_part;
1264      HOST_WIDE_INT mask = 2;
1265      mask <<= this_part * BITS_PER_UNIT - 1;
1266      val_part = val & (mask - 1);
1267      init_part |= val_part << (BITS_PER_UNIT * chunk_offset);
1268      val >>= BITS_PER_UNIT * this_part;
1269      size -= this_part;
1270      decl_offset += this_part;
1271      if (decl_offset % decl_chunk_size == 0)
1272	output_decl_chunk ();
1273
1274      chunk_offset = 0;
1275    }
1276}
1277
1278/* Target hook for assembling integer object X of size SIZE.  */
1279
1280static bool
1281nvptx_assemble_integer (rtx x, unsigned int size, int ARG_UNUSED (aligned_p))
1282{
1283  if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == CONST)
1284    {
1285      gcc_assert (size = decl_chunk_size);
1286      if (decl_offset % decl_chunk_size != 0)
1287	sorry ("cannot emit unaligned pointers in ptx assembly");
1288      decl_offset += size;
1289      begin_decl_field ();
1290
1291      HOST_WIDE_INT off = 0;
1292      if (GET_CODE (x) == CONST)
1293	x = XEXP (x, 0);
1294      if (GET_CODE (x) == PLUS)
1295	{
1296	  off = INTVAL (XEXP (x, 1));
1297	  x = XEXP (x, 0);
1298	}
1299      if (GET_CODE (x) == SYMBOL_REF)
1300	{
1301	  nvptx_record_needed_fndecl (SYMBOL_REF_DECL (x));
1302	  fprintf (asm_out_file, "generic(");
1303	  output_address (x);
1304	  fprintf (asm_out_file, ")");
1305	}
1306      if (off != 0)
1307	fprintf (asm_out_file, " + " HOST_WIDE_INT_PRINT_DEC, off);
1308      return true;
1309    }
1310
1311  HOST_WIDE_INT val;
1312  switch (GET_CODE (x))
1313    {
1314    case CONST_INT:
1315      val = INTVAL (x);
1316      break;
1317    case CONST_DOUBLE:
1318      gcc_unreachable ();
1319      break;
1320    default:
1321      gcc_unreachable ();
1322    }
1323
1324  nvptx_assemble_value (val, size);
1325  return true;
1326}
1327
1328/* Output SIZE zero bytes.  We ignore the FILE argument since the
1329   functions we're calling to perform the output just use
1330   asm_out_file.  */
1331
1332void
1333nvptx_output_skip (FILE *, unsigned HOST_WIDE_INT size)
1334{
1335  if (decl_offset + size >= object_size)
1336    {
1337      if (decl_offset % decl_chunk_size != 0)
1338	nvptx_assemble_value (0, decl_chunk_size);
1339      object_finished = true;
1340      return;
1341    }
1342
1343  while (size > decl_chunk_size)
1344    {
1345      nvptx_assemble_value (0, decl_chunk_size);
1346      size -= decl_chunk_size;
1347    }
1348  while (size-- > 0)
1349    nvptx_assemble_value (0, 1);
1350}
1351
1352/* Output a string STR with length SIZE.  As in nvptx_output_skip we
1353   ignore the FILE arg.  */
1354
1355void
1356nvptx_output_ascii (FILE *, const char *str, unsigned HOST_WIDE_INT size)
1357{
1358  for (unsigned HOST_WIDE_INT i = 0; i < size; i++)
1359    nvptx_assemble_value (str[i], 1);
1360}
1361
1362/* Called when the initializer for a decl has been completely output through
1363   combinations of the three functions above.  */
1364
1365static void
1366nvptx_assemble_decl_end (void)
1367{
1368  if (decl_offset != 0)
1369    {
1370      if (!object_finished && decl_offset % decl_chunk_size != 0)
1371	nvptx_assemble_value (0, decl_chunk_size);
1372
1373      fprintf (asm_out_file, " }");
1374    }
1375  fprintf (asm_out_file, ";\n");
1376}
1377
1378/* Start a declaration of a variable of TYPE with NAME to
1379   FILE.  IS_PUBLIC says whether this will be externally visible.
1380   Here we just write the linker hint and decide on the chunk size
1381   to use.  */
1382
1383static void
1384init_output_initializer (FILE *file, const char *name, const_tree type,
1385			 bool is_public)
1386{
1387  fprintf (file, "// BEGIN%s VAR DEF: ", is_public ? " GLOBAL" : "");
1388  assemble_name_raw (file, name);
1389  fputc ('\n', file);
1390
1391  if (TREE_CODE (type) == ARRAY_TYPE)
1392    type = TREE_TYPE (type);
1393  int sz = int_size_in_bytes (type);
1394  if ((TREE_CODE (type) != INTEGER_TYPE
1395       && TREE_CODE (type) != ENUMERAL_TYPE
1396       && TREE_CODE (type) != REAL_TYPE)
1397      || sz < 0
1398      || sz > HOST_BITS_PER_WIDE_INT)
1399    type = ptr_type_node;
1400  decl_chunk_size = int_size_in_bytes (type);
1401  decl_chunk_mode = int_mode_for_mode (TYPE_MODE (type));
1402  decl_offset = 0;
1403  init_part = 0;
1404  object_finished = false;
1405}
1406
1407/* Implement TARGET_ASM_DECLARE_CONSTANT_NAME.  Begin the process of
1408   writing a constant variable EXP with NAME and SIZE and its
1409   initializer to FILE.  */
1410
1411static void
1412nvptx_asm_declare_constant_name (FILE *file, const char *name,
1413				 const_tree exp, HOST_WIDE_INT size)
1414{
1415  tree type = TREE_TYPE (exp);
1416  init_output_initializer (file, name, type, false);
1417  fprintf (file, "\t.const .align %d .u%d ",
1418	   TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT,
1419	   decl_chunk_size * BITS_PER_UNIT);
1420  assemble_name (file, name);
1421  fprintf (file, "[" HOST_WIDE_INT_PRINT_DEC "]",
1422	   (size + decl_chunk_size - 1) / decl_chunk_size);
1423  object_size = size;
1424}
1425
1426/* Implement the ASM_DECLARE_OBJECT_NAME macro.  Used to start writing
1427   a variable DECL with NAME to FILE.  */
1428
1429void
1430nvptx_declare_object_name (FILE *file, const char *name, const_tree decl)
1431{
1432  if (decl && DECL_SIZE (decl))
1433    {
1434      tree type = TREE_TYPE (decl);
1435      unsigned HOST_WIDE_INT size;
1436
1437      init_output_initializer (file, name, type, TREE_PUBLIC (decl));
1438      size = tree_to_uhwi (DECL_SIZE_UNIT (decl));
1439      const char *section = nvptx_section_for_decl (decl);
1440      fprintf (file, "\t%s%s .align %d .u%d ",
1441	       TREE_PUBLIC (decl) ? " .visible" : "", section,
1442	       DECL_ALIGN (decl) / BITS_PER_UNIT,
1443	       decl_chunk_size * BITS_PER_UNIT);
1444      assemble_name (file, name);
1445      if (size > 0)
1446	fprintf (file, "[" HOST_WIDE_INT_PRINT_DEC "]",
1447		 (size + decl_chunk_size - 1) / decl_chunk_size);
1448      else
1449	object_finished = true;
1450      object_size = size;
1451    }
1452}
1453
1454/* Implement TARGET_ASM_GLOBALIZE_LABEL by doing nothing.  */
1455
1456static void
1457nvptx_globalize_label (FILE *, const char *)
1458{
1459}
1460
1461/* Implement TARGET_ASM_ASSEMBLE_UNDEFINED_DECL.  Write an extern
1462   declaration only for variable DECL with NAME to FILE.  */
1463static void
1464nvptx_assemble_undefined_decl (FILE *file, const char *name, const_tree decl)
1465{
1466  if (TREE_CODE (decl) != VAR_DECL)
1467    return;
1468  const char *section = nvptx_section_for_decl (decl);
1469  fprintf (file, "// BEGIN%s VAR DECL: ", TREE_PUBLIC (decl) ? " GLOBAL" : "");
1470  assemble_name_raw (file, name);
1471  fputs ("\n", file);
1472  HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
1473  fprintf (file, ".extern %s .b8 ", section);
1474  assemble_name_raw (file, name);
1475  if (size > 0)
1476    fprintf (file, "["HOST_WIDE_INT_PRINT_DEC"]", size);
1477  fprintf (file, ";\n\n");
1478}
1479
1480/* Output INSN, which is a call to CALLEE with result RESULT.  For ptx, this
1481   involves writing .param declarations and in/out copies into them.  */
1482
1483const char *
1484nvptx_output_call_insn (rtx_insn *insn, rtx result, rtx callee)
1485{
1486  char buf[256];
1487  static int labelno;
1488  bool needs_tgt = register_operand (callee, Pmode);
1489  rtx pat = PATTERN (insn);
1490  int nargs = XVECLEN (pat, 0) - 1;
1491  tree decl = NULL_TREE;
1492
1493  fprintf (asm_out_file, "\t{\n");
1494  if (result != NULL)
1495    {
1496      fprintf (asm_out_file, "\t\t.param%s %%retval_in;\n",
1497	       nvptx_ptx_type_from_mode (arg_promotion (GET_MODE (result)),
1498					 false));
1499    }
1500
1501  if (GET_CODE (callee) == SYMBOL_REF)
1502    {
1503      decl = SYMBOL_REF_DECL (callee);
1504      if (decl && DECL_EXTERNAL (decl))
1505	nvptx_record_fndecl (decl);
1506    }
1507
1508  if (needs_tgt)
1509    {
1510      ASM_GENERATE_INTERNAL_LABEL (buf, "LCT", labelno);
1511      labelno++;
1512      ASM_OUTPUT_LABEL (asm_out_file, buf);
1513      std::stringstream s;
1514      write_func_decl_from_insn (s, result, pat, callee);
1515      fputs (s.str().c_str(), asm_out_file);
1516    }
1517
1518  for (int i = 0, argno = 0; i < nargs; i++)
1519    {
1520      rtx t = XEXP (XVECEXP (pat, 0, i + 1), 0);
1521      machine_mode mode = GET_MODE (t);
1522      int count = maybe_split_mode (&mode);
1523
1524      while (count-- > 0)
1525	fprintf (asm_out_file, "\t\t.param%s %%out_arg%d%s;\n",
1526		 nvptx_ptx_type_from_mode (mode, false), argno++,
1527		 mode == QImode || mode == HImode ? "[1]" : "");
1528    }
1529  for (int i = 0, argno = 0; i < nargs; i++)
1530    {
1531      rtx t = XEXP (XVECEXP (pat, 0, i + 1), 0);
1532      gcc_assert (REG_P (t));
1533      machine_mode mode = GET_MODE (t);
1534      int count = maybe_split_mode (&mode);
1535
1536      if (count == 1)
1537	fprintf (asm_out_file, "\t\tst.param%s [%%out_arg%d], %%r%d;\n",
1538		 nvptx_ptx_type_from_mode (mode, false), argno++,
1539		 REGNO (t));
1540      else
1541	{
1542	  int n = 0;
1543	  while (count-- > 0)
1544	    fprintf (asm_out_file, "\t\tst.param%s [%%out_arg%d], %%r%d$%d;\n",
1545		     nvptx_ptx_type_from_mode (mode, false), argno++,
1546		     REGNO (t), n++);
1547	}
1548    }
1549
1550  fprintf (asm_out_file, "\t\tcall ");
1551  if (result != NULL_RTX)
1552    fprintf (asm_out_file, "(%%retval_in), ");
1553
1554  if (decl)
1555    {
1556      const char *name = get_fnname_from_decl (decl);
1557      name = nvptx_name_replacement (name);
1558      assemble_name (asm_out_file, name);
1559    }
1560  else
1561    output_address (callee);
1562
1563  if (nargs > 0 || (decl && DECL_STATIC_CHAIN (decl)))
1564    {
1565      fprintf (asm_out_file, ", (");
1566      int i, argno;
1567      for (i = 0, argno = 0; i < nargs; i++)
1568	{
1569	  rtx t = XEXP (XVECEXP (pat, 0, i + 1), 0);
1570	  machine_mode mode = GET_MODE (t);
1571	  int count = maybe_split_mode (&mode);
1572
1573	  while (count-- > 0)
1574	    {
1575	      fprintf (asm_out_file, "%%out_arg%d", argno++);
1576	      if (i + 1 < nargs || count > 0)
1577		fprintf (asm_out_file, ", ");
1578	    }
1579	}
1580      if (decl && DECL_STATIC_CHAIN (decl))
1581	{
1582	  if (i > 0)
1583	    fprintf (asm_out_file, ", ");
1584	  fprintf (asm_out_file, "%s",
1585		   reg_names [OUTGOING_STATIC_CHAIN_REGNUM]);
1586	}
1587
1588      fprintf (asm_out_file, ")");
1589    }
1590  if (needs_tgt)
1591    {
1592      fprintf (asm_out_file, ", ");
1593      assemble_name (asm_out_file, buf);
1594    }
1595  fprintf (asm_out_file, ";\n");
1596  if (result != NULL_RTX)
1597    return "ld.param%t0\t%0, [%%retval_in];\n\t}";
1598
1599  return "}";
1600}
1601
1602/* Implement TARGET_PRINT_OPERAND_PUNCT_VALID_P.  */
1603
1604static bool
1605nvptx_print_operand_punct_valid_p (unsigned char c)
1606{
1607  return c == '.' || c== '#';
1608}
1609
1610static void nvptx_print_operand (FILE *, rtx, int);
1611
1612/* Subroutine of nvptx_print_operand; used to print a memory reference X to FILE.  */
1613
1614static void
1615nvptx_print_address_operand (FILE *file, rtx x, machine_mode)
1616{
1617  rtx off;
1618  if (GET_CODE (x) == CONST)
1619    x = XEXP (x, 0);
1620  switch (GET_CODE (x))
1621    {
1622    case PLUS:
1623      off = XEXP (x, 1);
1624      output_address (XEXP (x, 0));
1625      fprintf (file, "+");
1626      output_address (off);
1627      break;
1628
1629    case SYMBOL_REF:
1630    case LABEL_REF:
1631      output_addr_const (file, x);
1632      break;
1633
1634    default:
1635      gcc_assert (GET_CODE (x) != MEM);
1636      nvptx_print_operand (file, x, 0);
1637      break;
1638    }
1639}
1640
1641/* Write assembly language output for the address ADDR to FILE.  */
1642
1643static void
1644nvptx_print_operand_address (FILE *file, rtx addr)
1645{
1646  nvptx_print_address_operand (file, addr, VOIDmode);
1647}
1648
1649/* Print an operand, X, to FILE, with an optional modifier in CODE.
1650
1651   Meaning of CODE:
1652   . -- print the predicate for the instruction or an emptry string for an
1653        unconditional one.
1654   # -- print a rounding mode for the instruction
1655
1656   A -- print an address space identifier for a MEM
1657   c -- print an opcode suffix for a comparison operator, including a type code
1658   d -- print a CONST_INT as a vector dimension (x, y, or z)
1659   f -- print a full reg even for something that must always be split
1660   t -- print a type opcode suffix, promoting QImode to 32 bits
1661   T -- print a type size in bits
1662   u -- print a type opcode suffix without promotions.  */
1663
1664static void
1665nvptx_print_operand (FILE *file, rtx x, int code)
1666{
1667  rtx orig_x = x;
1668  machine_mode op_mode;
1669
1670  if (code == '.')
1671    {
1672      x = current_insn_predicate;
1673      if (x)
1674	{
1675	  unsigned int regno = REGNO (XEXP (x, 0));
1676	  fputs ("[", file);
1677	  if (GET_CODE (x) == EQ)
1678	    fputs ("!", file);
1679	  fputs (reg_names [regno], file);
1680	  fputs ("]", file);
1681	}
1682      return;
1683    }
1684  else if (code == '#')
1685    {
1686      fputs (".rn", file);
1687      return;
1688    }
1689
1690  enum rtx_code x_code = GET_CODE (x);
1691
1692  switch (code)
1693    {
1694    case 'A':
1695      {
1696	addr_space_t as = nvptx_addr_space_from_address (XEXP (x, 0));
1697	fputs (nvptx_section_from_addr_space (as), file);
1698      }
1699      break;
1700
1701    case 'd':
1702      gcc_assert (x_code == CONST_INT);
1703      if (INTVAL (x) == 0)
1704	fputs (".x", file);
1705      else if (INTVAL (x) == 1)
1706	fputs (".y", file);
1707      else if (INTVAL (x) == 2)
1708	fputs (".z", file);
1709      else
1710	gcc_unreachable ();
1711      break;
1712
1713    case 't':
1714      op_mode = nvptx_underlying_object_mode (x);
1715      fprintf (file, "%s", nvptx_ptx_type_from_mode (op_mode, true));
1716      break;
1717
1718    case 'u':
1719      op_mode = nvptx_underlying_object_mode (x);
1720      fprintf (file, "%s", nvptx_ptx_type_from_mode (op_mode, false));
1721      break;
1722
1723    case 'T':
1724      fprintf (file, "%d", GET_MODE_BITSIZE (GET_MODE (x)));
1725      break;
1726
1727    case 'j':
1728      fprintf (file, "@");
1729      goto common;
1730
1731    case 'J':
1732      fprintf (file, "@!");
1733      goto common;
1734
1735    case 'c':
1736      op_mode = GET_MODE (XEXP (x, 0));
1737      switch (x_code)
1738	{
1739	case EQ:
1740	  fputs (".eq", file);
1741	  break;
1742	case NE:
1743	  if (FLOAT_MODE_P (op_mode))
1744	    fputs (".neu", file);
1745	  else
1746	    fputs (".ne", file);
1747	  break;
1748	case LE:
1749	  fputs (".le", file);
1750	  break;
1751	case GE:
1752	  fputs (".ge", file);
1753	  break;
1754	case LT:
1755	  fputs (".lt", file);
1756	  break;
1757	case GT:
1758	  fputs (".gt", file);
1759	  break;
1760	case LEU:
1761	  fputs (".ls", file);
1762	  break;
1763	case GEU:
1764	  fputs (".hs", file);
1765	  break;
1766	case LTU:
1767	  fputs (".lo", file);
1768	  break;
1769	case GTU:
1770	  fputs (".hi", file);
1771	  break;
1772	case LTGT:
1773	  fputs (".ne", file);
1774	  break;
1775	case UNEQ:
1776	  fputs (".equ", file);
1777	  break;
1778	case UNLE:
1779	  fputs (".leu", file);
1780	  break;
1781	case UNGE:
1782	  fputs (".geu", file);
1783	  break;
1784	case UNLT:
1785	  fputs (".ltu", file);
1786	  break;
1787	case UNGT:
1788	  fputs (".gtu", file);
1789	  break;
1790	case UNORDERED:
1791	  fputs (".nan", file);
1792	  break;
1793	case ORDERED:
1794	  fputs (".num", file);
1795	  break;
1796	default:
1797	  gcc_unreachable ();
1798	}
1799      if (FLOAT_MODE_P (op_mode)
1800	  || x_code == EQ || x_code == NE
1801	  || x_code == GEU || x_code == GTU
1802	  || x_code == LEU || x_code == LTU)
1803	fputs (nvptx_ptx_type_from_mode (op_mode, true), file);
1804      else
1805	fprintf (file, ".s%d", GET_MODE_BITSIZE (op_mode));
1806      break;
1807    default:
1808    common:
1809      switch (x_code)
1810	{
1811	case SUBREG:
1812	  x = SUBREG_REG (x);
1813	  /* fall through */
1814
1815	case REG:
1816	  if (HARD_REGISTER_P (x))
1817	    fprintf (file, "%s", reg_names[REGNO (x)]);
1818	  else
1819	    fprintf (file, "%%r%d", REGNO (x));
1820	  if (code != 'f' && nvptx_split_reg_p (GET_MODE (x)))
1821	    {
1822	      gcc_assert (GET_CODE (orig_x) == SUBREG
1823			  && !nvptx_split_reg_p (GET_MODE (orig_x)));
1824	      fprintf (file, "$%d", SUBREG_BYTE (orig_x) / UNITS_PER_WORD);
1825	    }
1826	  break;
1827
1828	case MEM:
1829	  fputc ('[', file);
1830	  nvptx_print_address_operand (file, XEXP (x, 0), GET_MODE (x));
1831	  fputc (']', file);
1832	  break;
1833
1834	case CONST_INT:
1835	  output_addr_const (file, x);
1836	  break;
1837
1838	case CONST:
1839	case SYMBOL_REF:
1840	case LABEL_REF:
1841	  /* We could use output_addr_const, but that can print things like
1842	     "x-8", which breaks ptxas.  Need to ensure it is output as
1843	     "x+-8".  */
1844	  nvptx_print_address_operand (file, x, VOIDmode);
1845	  break;
1846
1847	case CONST_DOUBLE:
1848	  long vals[2];
1849	  REAL_VALUE_TYPE real;
1850	  REAL_VALUE_FROM_CONST_DOUBLE (real, x);
1851	  real_to_target (vals, &real, GET_MODE (x));
1852	  vals[0] &= 0xffffffff;
1853	  vals[1] &= 0xffffffff;
1854	  if (GET_MODE (x) == SFmode)
1855	    fprintf (file, "0f%08lx", vals[0]);
1856	  else
1857	    fprintf (file, "0d%08lx%08lx", vals[1], vals[0]);
1858	  break;
1859
1860	default:
1861	  output_addr_const (file, x);
1862	}
1863    }
1864}
1865
1866/* Record replacement regs used to deal with subreg operands.  */
1867struct reg_replace
1868{
1869  rtx replacement[MAX_RECOG_OPERANDS];
1870  machine_mode mode;
1871  int n_allocated;
1872  int n_in_use;
1873};
1874
1875/* Allocate or reuse a replacement in R and return the rtx.  */
1876
1877static rtx
1878get_replacement (struct reg_replace *r)
1879{
1880  if (r->n_allocated == r->n_in_use)
1881    r->replacement[r->n_allocated++] = gen_reg_rtx (r->mode);
1882  return r->replacement[r->n_in_use++];
1883}
1884
1885/* Clean up subreg operands.  In ptx assembly, everything is typed, and
1886   the presence of subregs would break the rules for most instructions.
1887   Replace them with a suitable new register of the right size, plus
1888   conversion copyin/copyout instructions.  */
1889
1890static void
1891nvptx_reorg (void)
1892{
1893  struct reg_replace qiregs, hiregs, siregs, diregs;
1894  rtx_insn *insn, *next;
1895
1896  /* We are freeing block_for_insn in the toplev to keep compatibility
1897     with old MDEP_REORGS that are not CFG based.  Recompute it now.  */
1898  compute_bb_for_insn ();
1899
1900  df_clear_flags (DF_LR_RUN_DCE);
1901  df_analyze ();
1902
1903  thread_prologue_and_epilogue_insns ();
1904
1905  qiregs.n_allocated = 0;
1906  hiregs.n_allocated = 0;
1907  siregs.n_allocated = 0;
1908  diregs.n_allocated = 0;
1909  qiregs.mode = QImode;
1910  hiregs.mode = HImode;
1911  siregs.mode = SImode;
1912  diregs.mode = DImode;
1913
1914  for (insn = get_insns (); insn; insn = next)
1915    {
1916      next = NEXT_INSN (insn);
1917      if (!NONDEBUG_INSN_P (insn)
1918	  || asm_noperands (insn) >= 0
1919	  || GET_CODE (PATTERN (insn)) == USE
1920	  || GET_CODE (PATTERN (insn)) == CLOBBER)
1921	continue;
1922      qiregs.n_in_use = 0;
1923      hiregs.n_in_use = 0;
1924      siregs.n_in_use = 0;
1925      diregs.n_in_use = 0;
1926      extract_insn (insn);
1927      enum attr_subregs_ok s_ok = get_attr_subregs_ok (insn);
1928      for (int i = 0; i < recog_data.n_operands; i++)
1929	{
1930	  rtx op = recog_data.operand[i];
1931	  if (GET_CODE (op) != SUBREG)
1932	    continue;
1933
1934	  rtx inner = SUBREG_REG (op);
1935
1936	  machine_mode outer_mode = GET_MODE (op);
1937	  machine_mode inner_mode = GET_MODE (inner);
1938	  gcc_assert (s_ok);
1939	  if (s_ok
1940	      && (GET_MODE_PRECISION (inner_mode)
1941		  >= GET_MODE_PRECISION (outer_mode)))
1942	    continue;
1943	  gcc_assert (SCALAR_INT_MODE_P (outer_mode));
1944	  struct reg_replace *r = (outer_mode == QImode ? &qiregs
1945				   : outer_mode == HImode ? &hiregs
1946				   : outer_mode == SImode ? &siregs
1947				   : &diregs);
1948	  rtx new_reg = get_replacement (r);
1949
1950	  if (recog_data.operand_type[i] != OP_OUT)
1951	    {
1952	      enum rtx_code code;
1953	      if (GET_MODE_PRECISION (inner_mode)
1954		  < GET_MODE_PRECISION (outer_mode))
1955		code = ZERO_EXTEND;
1956	      else
1957		code = TRUNCATE;
1958
1959	      rtx pat = gen_rtx_SET (VOIDmode, new_reg,
1960				     gen_rtx_fmt_e (code, outer_mode, inner));
1961	      emit_insn_before (pat, insn);
1962	    }
1963
1964	  if (recog_data.operand_type[i] != OP_IN)
1965	    {
1966	      enum rtx_code code;
1967	      if (GET_MODE_PRECISION (inner_mode)
1968		  < GET_MODE_PRECISION (outer_mode))
1969		code = TRUNCATE;
1970	      else
1971		code = ZERO_EXTEND;
1972
1973	      rtx pat = gen_rtx_SET (VOIDmode, inner,
1974				     gen_rtx_fmt_e (code, inner_mode, new_reg));
1975	      emit_insn_after (pat, insn);
1976	    }
1977	  validate_change (insn, recog_data.operand_loc[i], new_reg, false);
1978	}
1979    }
1980
1981  int maxregs = max_reg_num ();
1982  regstat_init_n_sets_and_refs ();
1983
1984  for (int i = LAST_VIRTUAL_REGISTER + 1; i < maxregs; i++)
1985    if (REG_N_SETS (i) == 0 && REG_N_REFS (i) == 0)
1986      regno_reg_rtx[i] = const0_rtx;
1987  regstat_free_n_sets_and_refs ();
1988}
1989
1990/* Handle a "kernel" attribute; arguments as in
1991   struct attribute_spec.handler.  */
1992
1993static tree
1994nvptx_handle_kernel_attribute (tree *node, tree name, tree ARG_UNUSED (args),
1995			       int ARG_UNUSED (flags), bool *no_add_attrs)
1996{
1997  tree decl = *node;
1998
1999  if (TREE_CODE (decl) != FUNCTION_DECL)
2000    {
2001      error ("%qE attribute only applies to functions", name);
2002      *no_add_attrs = true;
2003    }
2004
2005  else if (TREE_TYPE (TREE_TYPE (decl)) != void_type_node)
2006    {
2007      error ("%qE attribute requires a void return type", name);
2008      *no_add_attrs = true;
2009    }
2010
2011  return NULL_TREE;
2012}
2013
2014/* Table of valid machine attributes.  */
2015static const struct attribute_spec nvptx_attribute_table[] =
2016{
2017  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
2018       affects_type_identity } */
2019  { "kernel", 0, 0, true, false,  false, nvptx_handle_kernel_attribute, false },
2020  { NULL, 0, 0, false, false, false, NULL, false }
2021};
2022
2023/* Limit vector alignments to BIGGEST_ALIGNMENT.  */
2024
2025static HOST_WIDE_INT
2026nvptx_vector_alignment (const_tree type)
2027{
2028  HOST_WIDE_INT align = tree_to_shwi (TYPE_SIZE (type));
2029
2030  return MIN (align, BIGGEST_ALIGNMENT);
2031}
2032
2033/* Record a symbol for mkoffload to enter into the mapping table.  */
2034
2035static void
2036nvptx_record_offload_symbol (tree decl)
2037{
2038  fprintf (asm_out_file, "//:%s_MAP %s\n",
2039	   TREE_CODE (decl) == VAR_DECL ? "VAR" : "FUNC",
2040	   IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
2041}
2042
2043/* Implement TARGET_ASM_FILE_START.  Write the kinds of things ptxas expects
2044   at the start of a file.  */
2045
2046static void
2047nvptx_file_start (void)
2048{
2049  fputs ("// BEGIN PREAMBLE\n", asm_out_file);
2050  fputs ("\t.version\t3.1\n", asm_out_file);
2051  fputs ("\t.target\tsm_30\n", asm_out_file);
2052  fprintf (asm_out_file, "\t.address_size %d\n", GET_MODE_BITSIZE (Pmode));
2053  fputs ("// END PREAMBLE\n", asm_out_file);
2054}
2055
2056/* Write out the function declarations we've collected.  */
2057
2058static void
2059nvptx_file_end (void)
2060{
2061  hash_table<tree_hasher>::iterator iter;
2062  tree decl;
2063  FOR_EACH_HASH_TABLE_ELEMENT (*needed_fndecls_htab, decl, tree, iter)
2064    nvptx_record_fndecl (decl, true);
2065  fputs (func_decls.str().c_str(), asm_out_file);
2066}
2067
2068#undef TARGET_OPTION_OVERRIDE
2069#define TARGET_OPTION_OVERRIDE nvptx_option_override
2070
2071#undef TARGET_ATTRIBUTE_TABLE
2072#define TARGET_ATTRIBUTE_TABLE nvptx_attribute_table
2073
2074#undef TARGET_LEGITIMATE_ADDRESS_P
2075#define TARGET_LEGITIMATE_ADDRESS_P nvptx_legitimate_address_p
2076
2077#undef  TARGET_PROMOTE_FUNCTION_MODE
2078#define TARGET_PROMOTE_FUNCTION_MODE nvptx_promote_function_mode
2079
2080#undef TARGET_FUNCTION_ARG
2081#define TARGET_FUNCTION_ARG nvptx_function_arg
2082#undef TARGET_FUNCTION_INCOMING_ARG
2083#define TARGET_FUNCTION_INCOMING_ARG nvptx_function_incoming_arg
2084#undef TARGET_FUNCTION_ARG_ADVANCE
2085#define TARGET_FUNCTION_ARG_ADVANCE nvptx_function_arg_advance
2086#undef TARGET_FUNCTION_ARG_BOUNDARY
2087#define TARGET_FUNCTION_ARG_BOUNDARY nvptx_function_arg_boundary
2088#undef TARGET_FUNCTION_ARG_ROUND_BOUNDARY
2089#define TARGET_FUNCTION_ARG_ROUND_BOUNDARY nvptx_function_arg_boundary
2090#undef TARGET_PASS_BY_REFERENCE
2091#define TARGET_PASS_BY_REFERENCE nvptx_pass_by_reference
2092#undef TARGET_FUNCTION_VALUE_REGNO_P
2093#define TARGET_FUNCTION_VALUE_REGNO_P nvptx_function_value_regno_p
2094#undef TARGET_FUNCTION_VALUE
2095#define TARGET_FUNCTION_VALUE nvptx_function_value
2096#undef TARGET_LIBCALL_VALUE
2097#define TARGET_LIBCALL_VALUE nvptx_libcall_value
2098#undef TARGET_FUNCTION_OK_FOR_SIBCALL
2099#define TARGET_FUNCTION_OK_FOR_SIBCALL nvptx_function_ok_for_sibcall
2100#undef TARGET_SPLIT_COMPLEX_ARG
2101#define TARGET_SPLIT_COMPLEX_ARG hook_bool_const_tree_true
2102#undef TARGET_RETURN_IN_MEMORY
2103#define TARGET_RETURN_IN_MEMORY nvptx_return_in_memory
2104#undef TARGET_OMIT_STRUCT_RETURN_REG
2105#define TARGET_OMIT_STRUCT_RETURN_REG true
2106#undef TARGET_STRICT_ARGUMENT_NAMING
2107#define TARGET_STRICT_ARGUMENT_NAMING nvptx_strict_argument_naming
2108#undef TARGET_STATIC_CHAIN
2109#define TARGET_STATIC_CHAIN nvptx_static_chain
2110
2111#undef TARGET_CALL_ARGS
2112#define TARGET_CALL_ARGS nvptx_call_args
2113#undef TARGET_END_CALL_ARGS
2114#define TARGET_END_CALL_ARGS nvptx_end_call_args
2115
2116#undef TARGET_ASM_FILE_START
2117#define TARGET_ASM_FILE_START nvptx_file_start
2118#undef TARGET_ASM_FILE_END
2119#define TARGET_ASM_FILE_END nvptx_file_end
2120#undef TARGET_ASM_GLOBALIZE_LABEL
2121#define TARGET_ASM_GLOBALIZE_LABEL nvptx_globalize_label
2122#undef TARGET_ASM_ASSEMBLE_UNDEFINED_DECL
2123#define TARGET_ASM_ASSEMBLE_UNDEFINED_DECL nvptx_assemble_undefined_decl
2124#undef  TARGET_PRINT_OPERAND
2125#define TARGET_PRINT_OPERAND nvptx_print_operand
2126#undef  TARGET_PRINT_OPERAND_ADDRESS
2127#define TARGET_PRINT_OPERAND_ADDRESS nvptx_print_operand_address
2128#undef  TARGET_PRINT_OPERAND_PUNCT_VALID_P
2129#define TARGET_PRINT_OPERAND_PUNCT_VALID_P nvptx_print_operand_punct_valid_p
2130#undef TARGET_ASM_INTEGER
2131#define TARGET_ASM_INTEGER nvptx_assemble_integer
2132#undef TARGET_ASM_DECL_END
2133#define TARGET_ASM_DECL_END nvptx_assemble_decl_end
2134#undef TARGET_ASM_DECLARE_CONSTANT_NAME
2135#define TARGET_ASM_DECLARE_CONSTANT_NAME nvptx_asm_declare_constant_name
2136#undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
2137#define TARGET_USE_BLOCKS_FOR_CONSTANT_P hook_bool_mode_const_rtx_true
2138#undef TARGET_ASM_NEED_VAR_DECL_BEFORE_USE
2139#define TARGET_ASM_NEED_VAR_DECL_BEFORE_USE true
2140
2141#undef TARGET_MACHINE_DEPENDENT_REORG
2142#define TARGET_MACHINE_DEPENDENT_REORG nvptx_reorg
2143#undef TARGET_NO_REGISTER_ALLOCATION
2144#define TARGET_NO_REGISTER_ALLOCATION true
2145
2146#undef TARGET_RECORD_OFFLOAD_SYMBOL
2147#define TARGET_RECORD_OFFLOAD_SYMBOL nvptx_record_offload_symbol
2148
2149#undef TARGET_VECTOR_ALIGNMENT
2150#define TARGET_VECTOR_ALIGNMENT nvptx_vector_alignment
2151
2152struct gcc_target targetm = TARGET_INITIALIZER;
2153
2154#include "gt-nvptx.h"
2155