1 /* Mapping from optabs to underlying library functions
2    Copyright (C) 1987-2020 Free Software Foundation, Inc.
3 
4 This file is part of GCC.
5 
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10 
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3.  If not see
18 <http://www.gnu.org/licenses/>.  */
19 
20 
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "target.h"
25 #include "insn-codes.h"
26 #include "optabs-libfuncs.h"
27 #include "libfuncs.h"
28 #include "optabs-query.h"
29 #include "tree.h"
30 #include "stringpool.h"
31 #include "varasm.h"
32 #include "stor-layout.h"
33 #include "rtl.h"
34 
35 struct target_libfuncs default_target_libfuncs;
36 #if SWITCHABLE_TARGET
37 struct target_libfuncs *this_target_libfuncs = &default_target_libfuncs;
38 #endif
39 
40 #define libfunc_hash \
41   (this_target_libfuncs->x_libfunc_hash)
42 
43 /* Prefixes for the current version of decimal floating point (BID vs. DPD) */
44 #if ENABLE_DECIMAL_BID_FORMAT
45 #define DECIMAL_PREFIX "bid_"
46 #else
47 #define DECIMAL_PREFIX "dpd_"
48 #endif
49 
50 /* Used for libfunc_hash.  */
51 
52 hashval_t
hash(libfunc_entry * e)53 libfunc_hasher::hash (libfunc_entry *e)
54 {
55   return ((e->mode1 + e->mode2 * NUM_MACHINE_MODES) ^ e->op);
56 }
57 
58 /* Used for libfunc_hash.  */
59 
60 bool
equal(libfunc_entry * e1,libfunc_entry * e2)61 libfunc_hasher::equal (libfunc_entry *e1, libfunc_entry *e2)
62 {
63   return e1->op == e2->op && e1->mode1 == e2->mode1 && e1->mode2 == e2->mode2;
64 }
65 
66 /* Return libfunc corresponding operation defined by OPTAB converting
67    from MODE2 to MODE1.  Trigger lazy initialization if needed, return NULL
68    if no libfunc is available.  */
69 rtx
convert_optab_libfunc(convert_optab optab,machine_mode mode1,machine_mode mode2)70 convert_optab_libfunc (convert_optab optab, machine_mode mode1,
71 		       machine_mode mode2)
72 {
73   struct libfunc_entry e;
74   struct libfunc_entry **slot;
75 
76   /* ??? This ought to be an assert, but not all of the places
77      that we expand optabs know about the optabs that got moved
78      to being direct.  */
79   if (!(optab >= FIRST_CONV_OPTAB && optab <= LAST_CONVLIB_OPTAB))
80     return NULL_RTX;
81 
82   e.op = optab;
83   e.mode1 = mode1;
84   e.mode2 = mode2;
85   slot = libfunc_hash->find_slot (&e, NO_INSERT);
86   if (!slot)
87     {
88       const struct convert_optab_libcall_d *d
89 	= &convlib_def[optab - FIRST_CONV_OPTAB];
90 
91       if (d->libcall_gen == NULL)
92 	return NULL;
93 
94       d->libcall_gen (optab, d->libcall_basename, mode1, mode2);
95       slot = libfunc_hash->find_slot (&e, NO_INSERT);
96       if (!slot)
97 	return NULL;
98     }
99   return (*slot)->libfunc;
100 }
101 
102 /* Return libfunc corresponding operation defined by OPTAB in MODE.
103    Trigger lazy initialization if needed, return NULL if no libfunc is
104    available.  */
105 rtx
optab_libfunc(optab optab,machine_mode mode)106 optab_libfunc (optab optab, machine_mode mode)
107 {
108   struct libfunc_entry e;
109   struct libfunc_entry **slot;
110 
111   /* ??? This ought to be an assert, but not all of the places
112      that we expand optabs know about the optabs that got moved
113      to being direct.  */
114   if (!(optab >= FIRST_NORM_OPTAB && optab <= LAST_NORMLIB_OPTAB))
115     return NULL_RTX;
116 
117   e.op = optab;
118   e.mode1 = mode;
119   e.mode2 = VOIDmode;
120   slot = libfunc_hash->find_slot (&e, NO_INSERT);
121   if (!slot)
122     {
123       const struct optab_libcall_d *d
124 	= &normlib_def[optab - FIRST_NORM_OPTAB];
125 
126       if (d->libcall_gen == NULL)
127 	return NULL;
128 
129       d->libcall_gen (optab, d->libcall_basename, d->libcall_suffix, mode);
130       slot = libfunc_hash->find_slot (&e, NO_INSERT);
131       if (!slot)
132 	return NULL;
133     }
134   return (*slot)->libfunc;
135 }
136 
137 /* Initialize the libfunc fields of an entire group of entries in some
138    optab.  Each entry is set equal to a string consisting of a leading
139    pair of underscores followed by a generic operation name followed by
140    a mode name (downshifted to lowercase) followed by a single character
141    representing the number of operands for the given operation (which is
142    usually one of the characters '2', '3', or '4').
143 
144    OPTABLE is the table in which libfunc fields are to be initialized.
145    OPNAME is the generic (string) name of the operation.
146    SUFFIX is the character which specifies the number of operands for
147      the given generic operation.
148    MODE is the mode to generate for.  */
149 
150 static void
gen_libfunc(optab optable,const char * opname,int suffix,machine_mode mode)151 gen_libfunc (optab optable, const char *opname, int suffix,
152 	     machine_mode mode)
153 {
154   unsigned opname_len = strlen (opname);
155   const char *mname = GET_MODE_NAME (mode);
156   unsigned mname_len = strlen (mname);
157   int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
158   int len = prefix_len + opname_len + mname_len + 1 + 1;
159   char *libfunc_name = XALLOCAVEC (char, len);
160   char *p;
161   const char *q;
162 
163   p = libfunc_name;
164   *p++ = '_';
165   *p++ = '_';
166   if (targetm.libfunc_gnu_prefix)
167     {
168       *p++ = 'g';
169       *p++ = 'n';
170       *p++ = 'u';
171       *p++ = '_';
172     }
173   for (q = opname; *q;)
174     *p++ = *q++;
175   for (q = mname; *q; q++)
176     *p++ = TOLOWER (*q);
177   *p++ = suffix;
178   *p = '\0';
179 
180   set_optab_libfunc (optable, mode,
181 		     ggc_alloc_string (libfunc_name, p - libfunc_name));
182 }
183 
184 /* Like gen_libfunc, but verify that integer operation is involved.  */
185 
186 void
gen_int_libfunc(optab optable,const char * opname,char suffix,machine_mode mode)187 gen_int_libfunc (optab optable, const char *opname, char suffix,
188 		 machine_mode mode)
189 {
190   int maxsize = 2 * BITS_PER_WORD;
191   int minsize = BITS_PER_WORD;
192   scalar_int_mode int_mode;
193 
194   if (!is_int_mode (mode, &int_mode))
195     return;
196   if (maxsize < LONG_LONG_TYPE_SIZE)
197     maxsize = LONG_LONG_TYPE_SIZE;
198   if (minsize > INT_TYPE_SIZE
199       && (trapv_binoptab_p (optable)
200 	  || trapv_unoptab_p (optable)))
201     minsize = INT_TYPE_SIZE;
202   if (GET_MODE_BITSIZE (int_mode) < minsize
203       || GET_MODE_BITSIZE (int_mode) > maxsize)
204     return;
205   gen_libfunc (optable, opname, suffix, int_mode);
206 }
207 
208 /* Like gen_libfunc, but verify that FP and set decimal prefix if needed.  */
209 
210 void
gen_fp_libfunc(optab optable,const char * opname,char suffix,machine_mode mode)211 gen_fp_libfunc (optab optable, const char *opname, char suffix,
212 		machine_mode mode)
213 {
214   char *dec_opname;
215 
216   if (GET_MODE_CLASS (mode) == MODE_FLOAT)
217     gen_libfunc (optable, opname, suffix, mode);
218   if (DECIMAL_FLOAT_MODE_P (mode))
219     {
220       dec_opname = XALLOCAVEC (char, sizeof (DECIMAL_PREFIX) + strlen (opname));
221       /* For BID support, change the name to have either a bid_ or dpd_ prefix
222 	 depending on the low level floating format used.  */
223       memcpy (dec_opname, DECIMAL_PREFIX, sizeof (DECIMAL_PREFIX) - 1);
224       strcpy (dec_opname + sizeof (DECIMAL_PREFIX) - 1, opname);
225       gen_libfunc (optable, dec_opname, suffix, mode);
226     }
227 }
228 
229 /* Like gen_libfunc, but verify that fixed-point operation is involved.  */
230 
231 void
gen_fixed_libfunc(optab optable,const char * opname,char suffix,machine_mode mode)232 gen_fixed_libfunc (optab optable, const char *opname, char suffix,
233 		   machine_mode mode)
234 {
235   if (!ALL_FIXED_POINT_MODE_P (mode))
236     return;
237   gen_libfunc (optable, opname, suffix, mode);
238 }
239 
240 /* Like gen_libfunc, but verify that signed fixed-point operation is
241    involved.  */
242 
243 void
gen_signed_fixed_libfunc(optab optable,const char * opname,char suffix,machine_mode mode)244 gen_signed_fixed_libfunc (optab optable, const char *opname, char suffix,
245 			  machine_mode mode)
246 {
247   if (!SIGNED_FIXED_POINT_MODE_P (mode))
248     return;
249   gen_libfunc (optable, opname, suffix, mode);
250 }
251 
252 /* Like gen_libfunc, but verify that unsigned fixed-point operation is
253    involved.  */
254 
255 void
gen_unsigned_fixed_libfunc(optab optable,const char * opname,char suffix,machine_mode mode)256 gen_unsigned_fixed_libfunc (optab optable, const char *opname, char suffix,
257 			    machine_mode mode)
258 {
259   if (!UNSIGNED_FIXED_POINT_MODE_P (mode))
260     return;
261   gen_libfunc (optable, opname, suffix, mode);
262 }
263 
264 /* Like gen_libfunc, but verify that FP or INT operation is involved.  */
265 
266 void
gen_int_fp_libfunc(optab optable,const char * name,char suffix,machine_mode mode)267 gen_int_fp_libfunc (optab optable, const char *name, char suffix,
268 		    machine_mode mode)
269 {
270   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
271     gen_fp_libfunc (optable, name, suffix, mode);
272   if (INTEGRAL_MODE_P (mode))
273     gen_int_libfunc (optable, name, suffix, mode);
274 }
275 
276 /* Like gen_libfunc, but verify that FP or INT operation is involved
277    and add 'v' suffix for integer operation.  */
278 
279 void
gen_intv_fp_libfunc(optab optable,const char * name,char suffix,machine_mode mode)280 gen_intv_fp_libfunc (optab optable, const char *name, char suffix,
281 		     machine_mode mode)
282 {
283   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
284     gen_fp_libfunc (optable, name, suffix, mode);
285   if (GET_MODE_CLASS (mode) == MODE_INT)
286     {
287       int len = strlen (name);
288       char *v_name = XALLOCAVEC (char, len + 2);
289       strcpy (v_name, name);
290       v_name[len] = 'v';
291       v_name[len + 1] = 0;
292       gen_int_libfunc (optable, v_name, suffix, mode);
293     }
294 }
295 
296 /* Like gen_libfunc, but verify that FP or INT or FIXED operation is
297    involved.  */
298 
299 void
gen_int_fp_fixed_libfunc(optab optable,const char * name,char suffix,machine_mode mode)300 gen_int_fp_fixed_libfunc (optab optable, const char *name, char suffix,
301 			  machine_mode mode)
302 {
303   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
304     gen_fp_libfunc (optable, name, suffix, mode);
305   if (INTEGRAL_MODE_P (mode))
306     gen_int_libfunc (optable, name, suffix, mode);
307   if (ALL_FIXED_POINT_MODE_P (mode))
308     gen_fixed_libfunc (optable, name, suffix, mode);
309 }
310 
311 /* Like gen_libfunc, but verify that FP or INT or signed FIXED operation is
312    involved.  */
313 
314 void
gen_int_fp_signed_fixed_libfunc(optab optable,const char * name,char suffix,machine_mode mode)315 gen_int_fp_signed_fixed_libfunc (optab optable, const char *name, char suffix,
316 				 machine_mode mode)
317 {
318   if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
319     gen_fp_libfunc (optable, name, suffix, mode);
320   if (INTEGRAL_MODE_P (mode))
321     gen_int_libfunc (optable, name, suffix, mode);
322   if (SIGNED_FIXED_POINT_MODE_P (mode))
323     gen_signed_fixed_libfunc (optable, name, suffix, mode);
324 }
325 
326 /* Like gen_libfunc, but verify that INT or FIXED operation is
327    involved.  */
328 
329 void
gen_int_fixed_libfunc(optab optable,const char * name,char suffix,machine_mode mode)330 gen_int_fixed_libfunc (optab optable, const char *name, char suffix,
331 		       machine_mode mode)
332 {
333   if (INTEGRAL_MODE_P (mode))
334     gen_int_libfunc (optable, name, suffix, mode);
335   if (ALL_FIXED_POINT_MODE_P (mode))
336     gen_fixed_libfunc (optable, name, suffix, mode);
337 }
338 
339 /* Like gen_libfunc, but verify that INT or signed FIXED operation is
340    involved.  */
341 
342 void
gen_int_signed_fixed_libfunc(optab optable,const char * name,char suffix,machine_mode mode)343 gen_int_signed_fixed_libfunc (optab optable, const char *name, char suffix,
344 			      machine_mode mode)
345 {
346   if (INTEGRAL_MODE_P (mode))
347     gen_int_libfunc (optable, name, suffix, mode);
348   if (SIGNED_FIXED_POINT_MODE_P (mode))
349     gen_signed_fixed_libfunc (optable, name, suffix, mode);
350 }
351 
352 /* Like gen_libfunc, but verify that INT or unsigned FIXED operation is
353    involved.  */
354 
355 void
gen_int_unsigned_fixed_libfunc(optab optable,const char * name,char suffix,machine_mode mode)356 gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix,
357 				machine_mode mode)
358 {
359   if (INTEGRAL_MODE_P (mode))
360     gen_int_libfunc (optable, name, suffix, mode);
361   if (UNSIGNED_FIXED_POINT_MODE_P (mode))
362     gen_unsigned_fixed_libfunc (optable, name, suffix, mode);
363 }
364 
365 /* Initialize the libfunc fields of an entire group of entries of an
366    inter-mode-class conversion optab.  The string formation rules are
367    similar to the ones for init_libfuncs, above, but instead of having
368    a mode name and an operand count these functions have two mode names
369    and no operand count.  */
370 
371 void
gen_interclass_conv_libfunc(convert_optab tab,const char * opname,machine_mode tmode,machine_mode fmode)372 gen_interclass_conv_libfunc (convert_optab tab,
373 			     const char *opname,
374 			     machine_mode tmode,
375 			     machine_mode fmode)
376 {
377   size_t opname_len = strlen (opname);
378   size_t mname_len = 0;
379 
380   const char *fname, *tname;
381   const char *q;
382   int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
383   char *libfunc_name, *suffix;
384   char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
385   char *p;
386 
387   /* If this is a decimal conversion, add the current BID vs. DPD prefix that
388      depends on which underlying decimal floating point format is used.  */
389   const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
390 
391   mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
392 
393   nondec_name = XALLOCAVEC (char, prefix_len + opname_len + mname_len + 1 + 1);
394   nondec_name[0] = '_';
395   nondec_name[1] = '_';
396   if (targetm.libfunc_gnu_prefix)
397     {
398       nondec_name[2] = 'g';
399       nondec_name[3] = 'n';
400       nondec_name[4] = 'u';
401       nondec_name[5] = '_';
402     }
403 
404   memcpy (&nondec_name[prefix_len], opname, opname_len);
405   nondec_suffix = nondec_name + opname_len + prefix_len;
406 
407   dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
408   dec_name[0] = '_';
409   dec_name[1] = '_';
410   memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
411   memcpy (&dec_name[2+dec_len], opname, opname_len);
412   dec_suffix = dec_name + dec_len + opname_len + 2;
413 
414   fname = GET_MODE_NAME (fmode);
415   tname = GET_MODE_NAME (tmode);
416 
417   if (DECIMAL_FLOAT_MODE_P (fmode) || DECIMAL_FLOAT_MODE_P (tmode))
418     {
419       libfunc_name = dec_name;
420       suffix = dec_suffix;
421     }
422   else
423     {
424       libfunc_name = nondec_name;
425       suffix = nondec_suffix;
426     }
427 
428   p = suffix;
429   for (q = fname; *q; p++, q++)
430     *p = TOLOWER (*q);
431   for (q = tname; *q; p++, q++)
432     *p = TOLOWER (*q);
433 
434   *p = '\0';
435 
436   set_conv_libfunc (tab, tmode, fmode,
437 		    ggc_alloc_string (libfunc_name, p - libfunc_name));
438 }
439 
440 /* Same as gen_interclass_conv_libfunc but verify that we are producing
441    int->fp conversion.  */
442 
443 void
gen_int_to_fp_conv_libfunc(convert_optab tab,const char * opname,machine_mode tmode,machine_mode fmode)444 gen_int_to_fp_conv_libfunc (convert_optab tab,
445 			    const char *opname,
446 			    machine_mode tmode,
447 			    machine_mode fmode)
448 {
449   if (GET_MODE_CLASS (fmode) != MODE_INT)
450     return;
451   if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
452     return;
453   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
454 }
455 
456 /* ufloat_optab is special by using floatun for FP and floatuns decimal fp
457    naming scheme.  */
458 
459 void
gen_ufloat_conv_libfunc(convert_optab tab,const char * opname ATTRIBUTE_UNUSED,machine_mode tmode,machine_mode fmode)460 gen_ufloat_conv_libfunc (convert_optab tab,
461 			 const char *opname ATTRIBUTE_UNUSED,
462 			 machine_mode tmode,
463 			 machine_mode fmode)
464 {
465   if (DECIMAL_FLOAT_MODE_P (tmode))
466     gen_int_to_fp_conv_libfunc (tab, "floatuns", tmode, fmode);
467   else
468     gen_int_to_fp_conv_libfunc (tab, "floatun", tmode, fmode);
469 }
470 
471 /* Same as gen_interclass_conv_libfunc but verify that we are producing
472    fp->int conversion.  */
473 
474 void
gen_int_to_fp_nondecimal_conv_libfunc(convert_optab tab,const char * opname,machine_mode tmode,machine_mode fmode)475 gen_int_to_fp_nondecimal_conv_libfunc (convert_optab tab,
476 				       const char *opname,
477 				       machine_mode tmode,
478 				       machine_mode fmode)
479 {
480   if (GET_MODE_CLASS (fmode) != MODE_INT)
481     return;
482   if (GET_MODE_CLASS (tmode) != MODE_FLOAT)
483     return;
484   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
485 }
486 
487 /* Same as gen_interclass_conv_libfunc but verify that we are producing
488    fp->int conversion with no decimal floating point involved.  */
489 
490 void
gen_fp_to_int_conv_libfunc(convert_optab tab,const char * opname,machine_mode tmode,machine_mode fmode)491 gen_fp_to_int_conv_libfunc (convert_optab tab,
492 			    const char *opname,
493 			    machine_mode tmode,
494 			    machine_mode fmode)
495 {
496   if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
497     return;
498   if (GET_MODE_CLASS (tmode) != MODE_INT)
499     return;
500   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
501 }
502 
503 /* Initialize the libfunc fields of an of an intra-mode-class conversion optab.
504    The string formation rules are
505    similar to the ones for init_libfunc, above.  */
506 
507 void
gen_intraclass_conv_libfunc(convert_optab tab,const char * opname,machine_mode tmode,machine_mode fmode)508 gen_intraclass_conv_libfunc (convert_optab tab, const char *opname,
509 			     machine_mode tmode, machine_mode fmode)
510 {
511   size_t opname_len = strlen (opname);
512   size_t mname_len = 0;
513 
514   const char *fname, *tname;
515   const char *q;
516   int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
517   char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
518   char *libfunc_name, *suffix;
519   char *p;
520 
521   /* If this is a decimal conversion, add the current BID vs. DPD prefix that
522      depends on which underlying decimal floating point format is used.  */
523   const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
524 
525   mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
526 
527   nondec_name = XALLOCAVEC (char, 2 + opname_len + mname_len + 1 + 1);
528   nondec_name[0] = '_';
529   nondec_name[1] = '_';
530   if (targetm.libfunc_gnu_prefix)
531     {
532       nondec_name[2] = 'g';
533       nondec_name[3] = 'n';
534       nondec_name[4] = 'u';
535       nondec_name[5] = '_';
536     }
537   memcpy (&nondec_name[prefix_len], opname, opname_len);
538   nondec_suffix = nondec_name + opname_len + prefix_len;
539 
540   dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
541   dec_name[0] = '_';
542   dec_name[1] = '_';
543   memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
544   memcpy (&dec_name[2 + dec_len], opname, opname_len);
545   dec_suffix = dec_name + dec_len + opname_len + 2;
546 
547   fname = GET_MODE_NAME (fmode);
548   tname = GET_MODE_NAME (tmode);
549 
550   if (DECIMAL_FLOAT_MODE_P (fmode) || DECIMAL_FLOAT_MODE_P (tmode))
551     {
552       libfunc_name = dec_name;
553       suffix = dec_suffix;
554     }
555   else
556     {
557       libfunc_name = nondec_name;
558       suffix = nondec_suffix;
559     }
560 
561   p = suffix;
562   for (q = fname; *q; p++, q++)
563     *p = TOLOWER (*q);
564   for (q = tname; *q; p++, q++)
565     *p = TOLOWER (*q);
566 
567   *p++ = '2';
568   *p = '\0';
569 
570   set_conv_libfunc (tab, tmode, fmode,
571 		    ggc_alloc_string (libfunc_name, p - libfunc_name));
572 }
573 
574 /* Pick proper libcall for trunc_optab.  We need to chose if we do
575    truncation or extension and interclass or intraclass.  */
576 
577 void
gen_trunc_conv_libfunc(convert_optab tab,const char * opname,machine_mode tmode,machine_mode fmode)578 gen_trunc_conv_libfunc (convert_optab tab,
579 			const char *opname,
580 			machine_mode tmode,
581 			machine_mode fmode)
582 {
583   scalar_float_mode float_tmode, float_fmode;
584   if (!is_a <scalar_float_mode> (fmode, &float_fmode)
585       || !is_a <scalar_float_mode> (tmode, &float_tmode)
586       || float_tmode == float_fmode)
587     return;
588 
589   if (GET_MODE_CLASS (float_tmode) != GET_MODE_CLASS (float_fmode))
590     gen_interclass_conv_libfunc (tab, opname, float_tmode, float_fmode);
591 
592   if (GET_MODE_PRECISION (float_fmode) <= GET_MODE_PRECISION (float_tmode))
593     return;
594 
595   if (GET_MODE_CLASS (float_tmode) == GET_MODE_CLASS (float_fmode))
596     gen_intraclass_conv_libfunc (tab, opname, float_tmode, float_fmode);
597 }
598 
599 /* Pick proper libcall for extend_optab.  We need to chose if we do
600    truncation or extension and interclass or intraclass.  */
601 
602 void
gen_extend_conv_libfunc(convert_optab tab,const char * opname ATTRIBUTE_UNUSED,machine_mode tmode,machine_mode fmode)603 gen_extend_conv_libfunc (convert_optab tab,
604 			 const char *opname ATTRIBUTE_UNUSED,
605 			 machine_mode tmode,
606 			 machine_mode fmode)
607 {
608   scalar_float_mode float_tmode, float_fmode;
609   if (!is_a <scalar_float_mode> (fmode, &float_fmode)
610       || !is_a <scalar_float_mode> (tmode, &float_tmode)
611       || float_tmode == float_fmode)
612     return;
613 
614   if (GET_MODE_CLASS (float_tmode) != GET_MODE_CLASS (float_fmode))
615     gen_interclass_conv_libfunc (tab, opname, float_tmode, float_fmode);
616 
617   if (GET_MODE_PRECISION (float_fmode) > GET_MODE_PRECISION (float_tmode))
618     return;
619 
620   if (GET_MODE_CLASS (float_tmode) == GET_MODE_CLASS (float_fmode))
621     gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
622 }
623 
624 /* Pick proper libcall for fract_optab.  We need to chose if we do
625    interclass or intraclass.  */
626 
627 void
gen_fract_conv_libfunc(convert_optab tab,const char * opname,machine_mode tmode,machine_mode fmode)628 gen_fract_conv_libfunc (convert_optab tab,
629 			const char *opname,
630 			machine_mode tmode,
631 			machine_mode fmode)
632 {
633   if (tmode == fmode)
634     return;
635   if (!(ALL_FIXED_POINT_MODE_P (tmode) || ALL_FIXED_POINT_MODE_P (fmode)))
636     return;
637 
638   if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
639     gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
640   else
641     gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
642 }
643 
644 /* Pick proper libcall for fractuns_optab.  */
645 
646 void
gen_fractuns_conv_libfunc(convert_optab tab,const char * opname,machine_mode tmode,machine_mode fmode)647 gen_fractuns_conv_libfunc (convert_optab tab,
648 			   const char *opname,
649 			   machine_mode tmode,
650 			   machine_mode fmode)
651 {
652   if (tmode == fmode)
653     return;
654   /* One mode must be a fixed-point mode, and the other must be an integer
655      mode.  */
656   if (!((ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT)
657 	|| (ALL_FIXED_POINT_MODE_P (fmode)
658 	    && GET_MODE_CLASS (tmode) == MODE_INT)))
659     return;
660 
661   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
662 }
663 
664 /* Pick proper libcall for satfract_optab.  We need to chose if we do
665    interclass or intraclass.  */
666 
667 void
gen_satfract_conv_libfunc(convert_optab tab,const char * opname,machine_mode tmode,machine_mode fmode)668 gen_satfract_conv_libfunc (convert_optab tab,
669 			   const char *opname,
670 			   machine_mode tmode,
671 			   machine_mode fmode)
672 {
673   if (tmode == fmode)
674     return;
675   /* TMODE must be a fixed-point mode.  */
676   if (!ALL_FIXED_POINT_MODE_P (tmode))
677     return;
678 
679   if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
680     gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
681   else
682     gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
683 }
684 
685 /* Pick proper libcall for satfractuns_optab.  */
686 
687 void
gen_satfractuns_conv_libfunc(convert_optab tab,const char * opname,machine_mode tmode,machine_mode fmode)688 gen_satfractuns_conv_libfunc (convert_optab tab,
689 			      const char *opname,
690 			      machine_mode tmode,
691 			      machine_mode fmode)
692 {
693   if (tmode == fmode)
694     return;
695   /* TMODE must be a fixed-point mode, and FMODE must be an integer mode.  */
696   if (!(ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT))
697     return;
698 
699   gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
700 }
701 
702 /* Hashtable callbacks for libfunc_decls.  */
703 
704 struct libfunc_decl_hasher : ggc_ptr_hash<tree_node>
705 {
706   static hashval_t
hashlibfunc_decl_hasher707   hash (tree entry)
708   {
709     return IDENTIFIER_HASH_VALUE (DECL_NAME (entry));
710   }
711 
712   static bool
equallibfunc_decl_hasher713   equal (tree decl, tree name)
714   {
715     return DECL_NAME (decl) == name;
716   }
717 };
718 
719 /* A table of previously-created libfuncs, hashed by name.  */
720 static GTY (()) hash_table<libfunc_decl_hasher> *libfunc_decls;
721 
722 /* Build a decl for a libfunc named NAME with visibility VIS.  */
723 
724 tree
build_libfunc_function_visibility(const char * name,symbol_visibility vis)725 build_libfunc_function_visibility (const char *name, symbol_visibility vis)
726 {
727   /* ??? We don't have any type information; pretend this is "int foo ()".  */
728   tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
729 			  get_identifier (name),
730 			  build_function_type (integer_type_node, NULL_TREE));
731   DECL_EXTERNAL (decl) = 1;
732   TREE_PUBLIC (decl) = 1;
733   DECL_ARTIFICIAL (decl) = 1;
734   DECL_VISIBILITY (decl) = vis;
735   DECL_VISIBILITY_SPECIFIED (decl) = 1;
736   gcc_assert (DECL_ASSEMBLER_NAME (decl));
737 
738   return decl;
739 }
740 
741 /* Build a decl for a libfunc named NAME.  */
742 
743 tree
build_libfunc_function(const char * name)744 build_libfunc_function (const char *name)
745 {
746   return build_libfunc_function_visibility (name, VISIBILITY_DEFAULT);
747 }
748 
749 /* Return a libfunc for NAME, creating one if we don't already have one.
750    The decl is given visibility VIS.  The returned rtx is a SYMBOL_REF.  */
751 
752 rtx
init_one_libfunc_visibility(const char * name,symbol_visibility vis)753 init_one_libfunc_visibility (const char *name, symbol_visibility vis)
754 {
755   tree id, decl;
756   hashval_t hash;
757 
758   if (libfunc_decls == NULL)
759     libfunc_decls = hash_table<libfunc_decl_hasher>::create_ggc (37);
760 
761   /* See if we have already created a libfunc decl for this function.  */
762   id = get_identifier (name);
763   hash = IDENTIFIER_HASH_VALUE (id);
764   tree *slot = libfunc_decls->find_slot_with_hash (id, hash, INSERT);
765   decl = *slot;
766   if (decl == NULL)
767     {
768       /* Create a new decl, so that it can be passed to
769 	 targetm.encode_section_info.  */
770       decl = build_libfunc_function_visibility (name, vis);
771       *slot = decl;
772     }
773   return XEXP (DECL_RTL (decl), 0);
774 }
775 
776 rtx
init_one_libfunc(const char * name)777 init_one_libfunc (const char *name)
778 {
779   return init_one_libfunc_visibility (name, VISIBILITY_DEFAULT);
780 }
781 
782 /* Adjust the assembler name of libfunc NAME to ASMSPEC.  */
783 
784 rtx
set_user_assembler_libfunc(const char * name,const char * asmspec)785 set_user_assembler_libfunc (const char *name, const char *asmspec)
786 {
787   tree id, decl;
788   hashval_t hash;
789 
790   id = get_identifier (name);
791   hash = IDENTIFIER_HASH_VALUE (id);
792   tree *slot = libfunc_decls->find_slot_with_hash (id, hash, NO_INSERT);
793   gcc_assert (slot);
794   decl = (tree) *slot;
795   set_user_assembler_name (decl, asmspec);
796   return XEXP (DECL_RTL (decl), 0);
797 }
798 
799 /* Call this to reset the function entry for one optab (OPTABLE) in mode
800    MODE to NAME, which should be either 0 or a string constant.  */
801 
802 void
set_optab_libfunc(optab op,machine_mode mode,const char * name)803 set_optab_libfunc (optab op, machine_mode mode, const char *name)
804 {
805   rtx val;
806   struct libfunc_entry e;
807   struct libfunc_entry **slot;
808 
809   e.op = op;
810   e.mode1 = mode;
811   e.mode2 = VOIDmode;
812 
813   if (name)
814     val = init_one_libfunc (name);
815   else
816     val = 0;
817   slot = libfunc_hash->find_slot (&e, INSERT);
818   if (*slot == NULL)
819     *slot = ggc_alloc<libfunc_entry> ();
820   (*slot)->op = op;
821   (*slot)->mode1 = mode;
822   (*slot)->mode2 = VOIDmode;
823   (*slot)->libfunc = val;
824 }
825 
826 /* Call this to reset the function entry for one conversion optab
827    (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be
828    either 0 or a string constant.  */
829 
830 void
set_conv_libfunc(convert_optab optab,machine_mode tmode,machine_mode fmode,const char * name)831 set_conv_libfunc (convert_optab optab, machine_mode tmode,
832 		  machine_mode fmode, const char *name)
833 {
834   rtx val;
835   struct libfunc_entry e;
836   struct libfunc_entry **slot;
837 
838   e.op = optab;
839   e.mode1 = tmode;
840   e.mode2 = fmode;
841 
842   if (name)
843     val = init_one_libfunc (name);
844   else
845     val = 0;
846   slot = libfunc_hash->find_slot (&e, INSERT);
847   if (*slot == NULL)
848     *slot = ggc_alloc<libfunc_entry> ();
849   (*slot)->op = optab;
850   (*slot)->mode1 = tmode;
851   (*slot)->mode2 = fmode;
852   (*slot)->libfunc = val;
853 }
854 
855 /* Call this to initialize the contents of the optabs
856    appropriately for the current target machine.  */
857 
858 void
init_optabs(void)859 init_optabs (void)
860 {
861   if (libfunc_hash)
862     libfunc_hash->empty ();
863   else
864     libfunc_hash = hash_table<libfunc_hasher>::create_ggc (10);
865 
866   /* Fill in the optabs with the insns we support.  */
867   init_all_optabs (this_fn_optabs);
868 
869   /* The ffs function operates on `int'.  Fall back on it if we do not
870      have a libgcc2 function for that width.  */
871   if (INT_TYPE_SIZE < BITS_PER_WORD)
872     {
873       scalar_int_mode mode = int_mode_for_size (INT_TYPE_SIZE, 0).require ();
874       set_optab_libfunc (ffs_optab, mode, "ffs");
875     }
876 
877   /* Explicitly initialize the bswap libfuncs since we need them to be
878      valid for things other than word_mode.  */
879   if (targetm.libfunc_gnu_prefix)
880     {
881       set_optab_libfunc (bswap_optab, SImode, "__gnu_bswapsi2");
882       set_optab_libfunc (bswap_optab, DImode, "__gnu_bswapdi2");
883     }
884   else
885     {
886       set_optab_libfunc (bswap_optab, SImode, "__bswapsi2");
887       set_optab_libfunc (bswap_optab, DImode, "__bswapdi2");
888     }
889 
890   /* Use cabs for double complex abs, since systems generally have cabs.
891      Don't define any libcall for float complex, so that cabs will be used.  */
892   if (complex_double_type_node)
893     set_optab_libfunc (abs_optab, TYPE_MODE (complex_double_type_node),
894 		       "cabs");
895 
896   unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
897   unwind_sjlj_unregister_libfunc
898     = init_one_libfunc ("_Unwind_SjLj_Unregister");
899 
900   /* Allow the target to add more libcalls or rename some, etc.  */
901   targetm.init_libfuncs ();
902 }
903 
904 /* A helper function for init_sync_libfuncs.  Using the basename BASE,
905    install libfuncs into TAB for BASE_N for 1 <= N <= MAX.  */
906 
907 static void
init_sync_libfuncs_1(optab tab,const char * base,int max)908 init_sync_libfuncs_1 (optab tab, const char *base, int max)
909 {
910   machine_mode mode;
911   char buf[64];
912   size_t len = strlen (base);
913   int i;
914 
915   gcc_assert (max <= 8);
916   gcc_assert (len + 3 < sizeof (buf));
917 
918   memcpy (buf, base, len);
919   buf[len] = '_';
920   buf[len + 1] = '0';
921   buf[len + 2] = '\0';
922 
923   mode = QImode;
924   for (i = 1; i <= max; i *= 2)
925     {
926       if (i > 1)
927 	mode = GET_MODE_2XWIDER_MODE (mode).require ();
928       buf[len + 1] = '0' + i;
929       set_optab_libfunc (tab, mode, buf);
930     }
931 }
932 
933 void
init_sync_libfuncs(int max)934 init_sync_libfuncs (int max)
935 {
936   if (!flag_sync_libcalls)
937     return;
938 
939   init_sync_libfuncs_1 (sync_compare_and_swap_optab,
940 			"__sync_val_compare_and_swap", max);
941   init_sync_libfuncs_1 (sync_lock_test_and_set_optab,
942 			"__sync_lock_test_and_set", max);
943 
944   init_sync_libfuncs_1 (sync_old_add_optab, "__sync_fetch_and_add", max);
945   init_sync_libfuncs_1 (sync_old_sub_optab, "__sync_fetch_and_sub", max);
946   init_sync_libfuncs_1 (sync_old_ior_optab, "__sync_fetch_and_or", max);
947   init_sync_libfuncs_1 (sync_old_and_optab, "__sync_fetch_and_and", max);
948   init_sync_libfuncs_1 (sync_old_xor_optab, "__sync_fetch_and_xor", max);
949   init_sync_libfuncs_1 (sync_old_nand_optab, "__sync_fetch_and_nand", max);
950 
951   init_sync_libfuncs_1 (sync_new_add_optab, "__sync_add_and_fetch", max);
952   init_sync_libfuncs_1 (sync_new_sub_optab, "__sync_sub_and_fetch", max);
953   init_sync_libfuncs_1 (sync_new_ior_optab, "__sync_or_and_fetch", max);
954   init_sync_libfuncs_1 (sync_new_and_optab, "__sync_and_and_fetch", max);
955   init_sync_libfuncs_1 (sync_new_xor_optab, "__sync_xor_and_fetch", max);
956   init_sync_libfuncs_1 (sync_new_nand_optab, "__sync_nand_and_fetch", max);
957 }
958 
959 #include "gt-optabs-libfuncs.h"
960