1 /* Mapping from optabs to underlying library functions
2    Copyright (C) 1987-2019 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   /* Zap the nonsensical SYMBOL_REF_DECL for this.  What we're left with
739      are the flags assigned by targetm.encode_section_info.  */
740   SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
741 
742   return decl;
743 }
744 
745 /* Build a decl for a libfunc named NAME.  */
746 
747 tree
build_libfunc_function(const char * name)748 build_libfunc_function (const char *name)
749 {
750   return build_libfunc_function_visibility (name, VISIBILITY_DEFAULT);
751 }
752 
753 /* Return a libfunc for NAME, creating one if we don't already have one.
754    The decl is given visibility VIS.  The returned rtx is a SYMBOL_REF.  */
755 
756 rtx
init_one_libfunc_visibility(const char * name,symbol_visibility vis)757 init_one_libfunc_visibility (const char *name, symbol_visibility vis)
758 {
759   tree id, decl;
760   hashval_t hash;
761 
762   if (libfunc_decls == NULL)
763     libfunc_decls = hash_table<libfunc_decl_hasher>::create_ggc (37);
764 
765   /* See if we have already created a libfunc decl for this function.  */
766   id = get_identifier (name);
767   hash = IDENTIFIER_HASH_VALUE (id);
768   tree *slot = libfunc_decls->find_slot_with_hash (id, hash, INSERT);
769   decl = *slot;
770   if (decl == NULL)
771     {
772       /* Create a new decl, so that it can be passed to
773 	 targetm.encode_section_info.  */
774       decl = build_libfunc_function_visibility (name, vis);
775       *slot = decl;
776     }
777   return XEXP (DECL_RTL (decl), 0);
778 }
779 
780 rtx
init_one_libfunc(const char * name)781 init_one_libfunc (const char *name)
782 {
783   return init_one_libfunc_visibility (name, VISIBILITY_DEFAULT);
784 }
785 
786 /* Adjust the assembler name of libfunc NAME to ASMSPEC.  */
787 
788 rtx
set_user_assembler_libfunc(const char * name,const char * asmspec)789 set_user_assembler_libfunc (const char *name, const char *asmspec)
790 {
791   tree id, decl;
792   hashval_t hash;
793 
794   id = get_identifier (name);
795   hash = IDENTIFIER_HASH_VALUE (id);
796   tree *slot = libfunc_decls->find_slot_with_hash (id, hash, NO_INSERT);
797   gcc_assert (slot);
798   decl = (tree) *slot;
799   set_user_assembler_name (decl, asmspec);
800   return XEXP (DECL_RTL (decl), 0);
801 }
802 
803 /* Call this to reset the function entry for one optab (OPTABLE) in mode
804    MODE to NAME, which should be either 0 or a string constant.  */
805 
806 void
set_optab_libfunc(optab op,machine_mode mode,const char * name)807 set_optab_libfunc (optab op, machine_mode mode, const char *name)
808 {
809   rtx val;
810   struct libfunc_entry e;
811   struct libfunc_entry **slot;
812 
813   e.op = op;
814   e.mode1 = mode;
815   e.mode2 = VOIDmode;
816 
817   if (name)
818     val = init_one_libfunc (name);
819   else
820     val = 0;
821   slot = libfunc_hash->find_slot (&e, INSERT);
822   if (*slot == NULL)
823     *slot = ggc_alloc<libfunc_entry> ();
824   (*slot)->op = op;
825   (*slot)->mode1 = mode;
826   (*slot)->mode2 = VOIDmode;
827   (*slot)->libfunc = val;
828 }
829 
830 /* Call this to reset the function entry for one conversion optab
831    (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be
832    either 0 or a string constant.  */
833 
834 void
set_conv_libfunc(convert_optab optab,machine_mode tmode,machine_mode fmode,const char * name)835 set_conv_libfunc (convert_optab optab, machine_mode tmode,
836 		  machine_mode fmode, const char *name)
837 {
838   rtx val;
839   struct libfunc_entry e;
840   struct libfunc_entry **slot;
841 
842   e.op = optab;
843   e.mode1 = tmode;
844   e.mode2 = fmode;
845 
846   if (name)
847     val = init_one_libfunc (name);
848   else
849     val = 0;
850   slot = libfunc_hash->find_slot (&e, INSERT);
851   if (*slot == NULL)
852     *slot = ggc_alloc<libfunc_entry> ();
853   (*slot)->op = optab;
854   (*slot)->mode1 = tmode;
855   (*slot)->mode2 = fmode;
856   (*slot)->libfunc = val;
857 }
858 
859 /* Call this to initialize the contents of the optabs
860    appropriately for the current target machine.  */
861 
862 void
init_optabs(void)863 init_optabs (void)
864 {
865   if (libfunc_hash)
866     libfunc_hash->empty ();
867   else
868     libfunc_hash = hash_table<libfunc_hasher>::create_ggc (10);
869 
870   /* Fill in the optabs with the insns we support.  */
871   init_all_optabs (this_fn_optabs);
872 
873   /* The ffs function operates on `int'.  Fall back on it if we do not
874      have a libgcc2 function for that width.  */
875   if (INT_TYPE_SIZE < BITS_PER_WORD)
876     {
877       scalar_int_mode mode = int_mode_for_size (INT_TYPE_SIZE, 0).require ();
878       set_optab_libfunc (ffs_optab, mode, "ffs");
879     }
880 
881   /* Explicitly initialize the bswap libfuncs since we need them to be
882      valid for things other than word_mode.  */
883   if (targetm.libfunc_gnu_prefix)
884     {
885       set_optab_libfunc (bswap_optab, SImode, "__gnu_bswapsi2");
886       set_optab_libfunc (bswap_optab, DImode, "__gnu_bswapdi2");
887     }
888   else
889     {
890       set_optab_libfunc (bswap_optab, SImode, "__bswapsi2");
891       set_optab_libfunc (bswap_optab, DImode, "__bswapdi2");
892     }
893 
894   /* Use cabs for double complex abs, since systems generally have cabs.
895      Don't define any libcall for float complex, so that cabs will be used.  */
896   if (complex_double_type_node)
897     set_optab_libfunc (abs_optab, TYPE_MODE (complex_double_type_node),
898 		       "cabs");
899 
900   unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
901   unwind_sjlj_unregister_libfunc
902     = init_one_libfunc ("_Unwind_SjLj_Unregister");
903 
904   /* Allow the target to add more libcalls or rename some, etc.  */
905   targetm.init_libfuncs ();
906 }
907 
908 /* A helper function for init_sync_libfuncs.  Using the basename BASE,
909    install libfuncs into TAB for BASE_N for 1 <= N <= MAX.  */
910 
911 static void
init_sync_libfuncs_1(optab tab,const char * base,int max)912 init_sync_libfuncs_1 (optab tab, const char *base, int max)
913 {
914   machine_mode mode;
915   char buf[64];
916   size_t len = strlen (base);
917   int i;
918 
919   gcc_assert (max <= 8);
920   gcc_assert (len + 3 < sizeof (buf));
921 
922   memcpy (buf, base, len);
923   buf[len] = '_';
924   buf[len + 1] = '0';
925   buf[len + 2] = '\0';
926 
927   mode = QImode;
928   for (i = 1; i <= max; i *= 2)
929     {
930       if (i > 1)
931 	mode = GET_MODE_2XWIDER_MODE (mode).require ();
932       buf[len + 1] = '0' + i;
933       set_optab_libfunc (tab, mode, buf);
934     }
935 }
936 
937 void
init_sync_libfuncs(int max)938 init_sync_libfuncs (int max)
939 {
940   if (!flag_sync_libcalls)
941     return;
942 
943   init_sync_libfuncs_1 (sync_compare_and_swap_optab,
944 			"__sync_val_compare_and_swap", max);
945   init_sync_libfuncs_1 (sync_lock_test_and_set_optab,
946 			"__sync_lock_test_and_set", max);
947 
948   init_sync_libfuncs_1 (sync_old_add_optab, "__sync_fetch_and_add", max);
949   init_sync_libfuncs_1 (sync_old_sub_optab, "__sync_fetch_and_sub", max);
950   init_sync_libfuncs_1 (sync_old_ior_optab, "__sync_fetch_and_or", max);
951   init_sync_libfuncs_1 (sync_old_and_optab, "__sync_fetch_and_and", max);
952   init_sync_libfuncs_1 (sync_old_xor_optab, "__sync_fetch_and_xor", max);
953   init_sync_libfuncs_1 (sync_old_nand_optab, "__sync_fetch_and_nand", max);
954 
955   init_sync_libfuncs_1 (sync_new_add_optab, "__sync_add_and_fetch", max);
956   init_sync_libfuncs_1 (sync_new_sub_optab, "__sync_sub_and_fetch", max);
957   init_sync_libfuncs_1 (sync_new_ior_optab, "__sync_or_and_fetch", max);
958   init_sync_libfuncs_1 (sync_new_and_optab, "__sync_and_and_fetch", max);
959   init_sync_libfuncs_1 (sync_new_xor_optab, "__sync_xor_and_fetch", max);
960   init_sync_libfuncs_1 (sync_new_nand_optab, "__sync_nand_and_fetch", max);
961 }
962 
963 #include "gt-optabs-libfuncs.h"
964