Merge from mainline
[official-gcc.git] / gcc / f / intrin.c
blob0bc6d0e0c93a7dd2027b683edc84f6739b77991a
1 /* intrin.c -- Recognize references to intrinsics
2 Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
3 Contributed by James Craig Burley.
5 This file is part of GNU Fortran.
7 GNU Fortran is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Fortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Fortran; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.
24 #include "proj.h"
25 #include "intrin.h"
26 #include "expr.h"
27 #include "info.h"
28 #include "src.h"
29 #include "symbol.h"
30 #include "target.h"
31 #include "top.h"
33 struct _ffeintrin_name_
35 const char *name_uc;
36 const char *name_lc;
37 const char *name_ic;
38 ffeintrinGen generic;
39 ffeintrinSpec specific;
42 struct _ffeintrin_gen_
44 const char *name; /* Name as seen in program. */
45 ffeintrinSpec specs[2];
48 struct _ffeintrin_spec_
50 const char *name; /* Uppercase name as seen in source code,
51 lowercase if no source name, "none" if no
52 name at all (NONE case). */
53 bool is_actualarg; /* Ok to pass as actual arg if -pedantic. */
54 ffeintrinFamily family;
55 ffeintrinImp implementation;
58 struct _ffeintrin_imp_
60 const char *name; /* Name of implementation. */
61 #if FFECOM_targetCURRENT == FFECOM_targetGCC
62 ffecomGfrt gfrt_direct; /* library routine, direct-callable form. */
63 ffecomGfrt gfrt_f2c; /* library routine, f2c-callable form. */
64 ffecomGfrt gfrt_gnu; /* library routine, gnu-callable form. */
65 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
66 const char *control;
67 char y2kbad;
70 static ffebad ffeintrin_check_ (ffeintrinImp imp, ffebldOp op,
71 ffebld args, ffeinfoBasictype *xbt,
72 ffeinfoKindtype *xkt,
73 ffetargetCharacterSize *xsz,
74 bool *check_intrin,
75 ffelexToken t,
76 bool commit);
77 static bool ffeintrin_check_any_ (ffebld arglist);
78 static int ffeintrin_cmp_name_ (const void *name, const void *intrinsic);
80 static struct _ffeintrin_name_ ffeintrin_names_[]
82 { /* Alpha order. */
83 #define DEFNAME(UPPER,LOWER,MIXED,GEN,SPEC) \
84 { UPPER, LOWER, MIXED, FFEINTRIN_ ## GEN, FFEINTRIN_ ## SPEC },
85 #define DEFGEN(CODE,NAME,SPEC1,SPEC2)
86 #define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP)
87 #define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL)
88 #define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD)
89 #include "intrin.def"
90 #undef DEFNAME
91 #undef DEFGEN
92 #undef DEFSPEC
93 #undef DEFIMP
94 #undef DEFIMPY
97 static struct _ffeintrin_gen_ ffeintrin_gens_[]
100 #define DEFNAME(UPPER,LOWER,MIXED,GEN,SPEC)
101 #define DEFGEN(CODE,NAME,SPEC1,SPEC2) \
102 { NAME, { SPEC1, SPEC2, }, },
103 #define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP)
104 #define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL)
105 #define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD)
106 #include "intrin.def"
107 #undef DEFNAME
108 #undef DEFGEN
109 #undef DEFSPEC
110 #undef DEFIMP
111 #undef DEFIMPY
114 static struct _ffeintrin_imp_ ffeintrin_imps_[]
117 #define DEFNAME(UPPER,LOWER,MIXED,GEN,SPEC)
118 #define DEFGEN(CODE,NAME,SPEC1,SPEC2)
119 #define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP)
120 #if FFECOM_targetCURRENT == FFECOM_targetGCC
121 #define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL) \
122 { NAME, FFECOM_gfrt ## GFRTDIRECT, FFECOM_gfrt ## GFRTF2C, \
123 FFECOM_gfrt ## GFRTGNU, CONTROL, FALSE },
124 #define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD) \
125 { NAME, FFECOM_gfrt ## GFRTDIRECT, FFECOM_gfrt ## GFRTF2C, \
126 FFECOM_gfrt ## GFRTGNU, CONTROL, Y2KBAD },
127 #elif FFECOM_targetCURRENT == FFECOM_targetFFE
128 #define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL) \
129 { NAME, CONTROL, FALSE },
130 #define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD) \
131 { NAME, CONTROL, Y2KBAD },
132 #else
133 #error
134 #endif
135 #include "intrin.def"
136 #undef DEFNAME
137 #undef DEFGEN
138 #undef DEFSPEC
139 #undef DEFIMP
140 #undef DEFIMPY
143 static struct _ffeintrin_spec_ ffeintrin_specs_[]
146 #define DEFNAME(UPPER,LOWER,MIXED,GEN,SPEC)
147 #define DEFGEN(CODE,NAME,SPEC1,SPEC2)
148 #define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP) \
149 { NAME, CALLABLE, FAMILY, IMP, },
150 #define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL)
151 #define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD)
152 #include "intrin.def"
153 #undef DEFGEN
154 #undef DEFSPEC
155 #undef DEFIMP
156 #undef DEFIMPY
160 static ffebad
161 ffeintrin_check_ (ffeintrinImp imp, ffebldOp op,
162 ffebld args, ffeinfoBasictype *xbt,
163 ffeinfoKindtype *xkt,
164 ffetargetCharacterSize *xsz,
165 bool *check_intrin,
166 ffelexToken t,
167 bool commit)
169 const char *c = ffeintrin_imps_[imp].control;
170 bool subr = (c[0] == '-');
171 const char *argc;
172 ffebld arg;
173 ffeinfoBasictype bt;
174 ffeinfoKindtype kt;
175 ffetargetCharacterSize sz = FFETARGET_charactersizeNONE;
176 ffeinfoKindtype firstarg_kt;
177 bool need_col;
178 ffeinfoBasictype col_bt = FFEINFO_basictypeNONE;
179 ffeinfoKindtype col_kt = FFEINFO_kindtypeNONE;
180 int colon = (c[2] == ':') ? 2 : 3;
181 int argno;
183 /* Check procedure type (function vs. subroutine) against
184 invocation. */
186 if (op == FFEBLD_opSUBRREF)
188 if (!subr)
189 return FFEBAD_INTRINSIC_IS_FUNC;
191 else if (op == FFEBLD_opFUNCREF)
193 if (subr)
194 return FFEBAD_INTRINSIC_IS_SUBR;
196 else
197 return FFEBAD_INTRINSIC_REF;
199 /* Check the arglist for validity. */
201 if ((args != NULL)
202 && (ffebld_head (args) != NULL))
203 firstarg_kt = ffeinfo_kindtype (ffebld_info (ffebld_head (args)));
204 else
205 firstarg_kt = FFEINFO_kindtype;
207 for (argc = &c[colon + 3],
208 arg = args;
209 *argc != '\0';
212 char optional = '\0';
213 char required = '\0';
214 char extra = '\0';
215 char basic;
216 char kind;
217 int length;
218 int elements;
219 bool lastarg_complex = FALSE;
221 /* We don't do anything with keywords yet. */
224 } while (*(++argc) != '=');
226 ++argc;
227 if ((*argc == '?')
228 || (*argc == '!')
229 || (*argc == '*'))
230 optional = *(argc++);
231 if ((*argc == '+')
232 || (*argc == 'n')
233 || (*argc == 'p'))
234 required = *(argc++);
235 basic = *(argc++);
236 kind = *(argc++);
237 if (*argc == '[')
239 length = *++argc - '0';
240 if (*++argc != ']')
241 length = 10 * length + (*(argc++) - '0');
242 ++argc;
244 else
245 length = -1;
246 if (*argc == '(')
248 elements = *++argc - '0';
249 if (*++argc != ')')
250 elements = 10 * elements + (*(argc++) - '0');
251 ++argc;
253 else if (*argc == '&')
255 elements = -1;
256 ++argc;
258 else
259 elements = 0;
260 if ((*argc == '&')
261 || (*argc == 'i')
262 || (*argc == 'w')
263 || (*argc == 'x'))
264 extra = *(argc++);
265 if (*argc == ',')
266 ++argc;
268 /* Break out of this loop only when current arg spec completely
269 processed. */
273 bool okay;
274 ffebld a;
275 ffeinfo i;
276 bool anynum;
277 ffeinfoBasictype abt = FFEINFO_basictypeNONE;
278 ffeinfoKindtype akt = FFEINFO_kindtypeNONE;
280 if ((arg == NULL)
281 || (ffebld_head (arg) == NULL))
283 if (required != '\0')
284 return FFEBAD_INTRINSIC_TOOFEW;
285 if (optional == '\0')
286 return FFEBAD_INTRINSIC_TOOFEW;
287 if (arg != NULL)
288 arg = ffebld_trail (arg);
289 break; /* Try next argspec. */
292 a = ffebld_head (arg);
293 i = ffebld_info (a);
294 anynum = (ffeinfo_basictype (i) == FFEINFO_basictypeHOLLERITH)
295 || (ffeinfo_basictype (i) == FFEINFO_basictypeTYPELESS);
297 /* See how well the arg matches up to the spec. */
299 switch (basic)
301 case 'A':
302 okay = (ffeinfo_basictype (i) == FFEINFO_basictypeCHARACTER)
303 && ((length == -1)
304 || (ffeinfo_size (i) == (ffetargetCharacterSize) length));
305 break;
307 case 'C':
308 okay = anynum
309 || (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX);
310 abt = FFEINFO_basictypeCOMPLEX;
311 break;
313 case 'I':
314 okay = anynum
315 || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER);
316 abt = FFEINFO_basictypeINTEGER;
317 break;
319 case 'L':
320 okay = anynum
321 || (ffeinfo_basictype (i) == FFEINFO_basictypeLOGICAL);
322 abt = FFEINFO_basictypeLOGICAL;
323 break;
325 case 'R':
326 okay = anynum
327 || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
328 abt = FFEINFO_basictypeREAL;
329 break;
331 case 'B':
332 okay = anynum
333 || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
334 || (ffeinfo_basictype (i) == FFEINFO_basictypeLOGICAL);
335 break;
337 case 'F':
338 okay = anynum
339 || (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX)
340 || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
341 break;
343 case 'N':
344 okay = anynum
345 || (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX)
346 || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
347 || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
348 break;
350 case 'S':
351 okay = anynum
352 || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
353 || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
354 break;
356 case 'g':
357 okay = ((ffebld_op (a) == FFEBLD_opLABTER)
358 || (ffebld_op (a) == FFEBLD_opLABTOK));
359 elements = -1;
360 extra = '-';
361 break;
363 case 's':
364 okay = (((((ffeinfo_basictype (i) == FFEINFO_basictypeNONE)
365 && (ffeinfo_kindtype (i) == FFEINFO_kindtypeNONE)
366 && (ffeinfo_kind (i) == FFEINFO_kindSUBROUTINE))
367 || ((ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
368 && (ffeinfo_kindtype (i) == FFEINFO_kindtypeINTEGERDEFAULT)
369 && (ffeinfo_kind (i) == FFEINFO_kindFUNCTION))
370 || (ffeinfo_kind (i) == FFEINFO_kindNONE))
371 && ((ffeinfo_where (i) == FFEINFO_whereDUMMY)
372 || (ffeinfo_where (i) == FFEINFO_whereGLOBAL)))
373 || ((ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
374 && (ffeinfo_kind (i) == FFEINFO_kindENTITY)));
375 elements = -1;
376 extra = '-';
377 break;
379 case '-':
380 default:
381 okay = TRUE;
382 break;
385 switch (kind)
387 case '1': case '2': case '3': case '4': case '5':
388 case '6': case '7': case '8': case '9':
389 akt = (kind - '0');
390 if ((ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
391 || (ffeinfo_basictype (i) == FFEINFO_basictypeLOGICAL))
393 switch (akt)
394 { /* Translate to internal kinds for now! */
395 default:
396 break;
398 case 2:
399 akt = 4;
400 break;
402 case 3:
403 akt = 2;
404 break;
406 case 4:
407 akt = 5;
408 break;
410 case 6:
411 akt = 3;
412 break;
414 case 7:
415 akt = ffecom_pointer_kind ();
416 break;
419 okay &= anynum || (ffeinfo_kindtype (i) == akt);
420 break;
422 case 'A':
423 okay &= anynum || (ffeinfo_kindtype (i) == firstarg_kt);
424 akt = (firstarg_kt == FFEINFO_kindtype) ? FFEINFO_kindtypeNONE
425 : firstarg_kt;
426 break;
428 case '*':
429 default:
430 break;
433 switch (elements)
435 ffebld b;
437 case -1:
438 break;
440 case 0:
441 if (ffeinfo_rank (i) != 0)
442 okay = FALSE;
443 break;
445 default:
446 if ((ffeinfo_rank (i) != 1)
447 || (ffebld_op (a) != FFEBLD_opSYMTER)
448 || ((b = ffesymbol_arraysize (ffebld_symter (a))) == NULL)
449 || (ffebld_op (b) != FFEBLD_opCONTER)
450 || (ffeinfo_basictype (ffebld_info (b)) != FFEINFO_basictypeINTEGER)
451 || (ffeinfo_kindtype (ffebld_info (b)) != FFEINFO_kindtypeINTEGERDEFAULT)
452 || (ffebld_constant_integer1 (ffebld_conter (b)) != elements))
453 okay = FALSE;
454 break;
457 switch (extra)
459 case '&':
460 if ((ffeinfo_kind (i) != FFEINFO_kindENTITY)
461 || ((ffebld_op (a) != FFEBLD_opSYMTER)
462 && (ffebld_op (a) != FFEBLD_opSUBSTR)
463 && (ffebld_op (a) != FFEBLD_opARRAYREF)))
464 okay = FALSE;
465 break;
467 case 'w':
468 case 'x':
469 if ((ffeinfo_kind (i) != FFEINFO_kindENTITY)
470 || ((ffebld_op (a) != FFEBLD_opSYMTER)
471 && (ffebld_op (a) != FFEBLD_opARRAYREF)
472 && (ffebld_op (a) != FFEBLD_opSUBSTR)))
473 okay = FALSE;
474 break;
476 case '-':
477 case 'i':
478 break;
480 default:
481 if (ffeinfo_kind (i) != FFEINFO_kindENTITY)
482 okay = FALSE;
483 break;
486 if ((optional == '!')
487 && lastarg_complex)
488 okay = FALSE;
490 if (!okay)
492 /* If it wasn't optional, it's an error,
493 else maybe it could match a later argspec. */
494 if (optional == '\0')
495 return FFEBAD_INTRINSIC_REF;
496 break; /* Try next argspec. */
499 lastarg_complex
500 = (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX);
502 if (anynum)
504 /* If we know dummy arg type, convert to that now. */
506 if ((abt != FFEINFO_basictypeNONE)
507 && (akt != FFEINFO_kindtypeNONE)
508 && commit)
510 /* We have a known type, convert hollerith/typeless
511 to it. */
513 a = ffeexpr_convert (a, t, NULL,
514 abt, akt, 0,
515 FFETARGET_charactersizeNONE,
516 FFEEXPR_contextLET);
517 ffebld_set_head (arg, a);
521 arg = ffebld_trail (arg); /* Arg accepted, now move on. */
523 if (optional == '*')
524 continue; /* Go ahead and try another arg. */
525 if (required == '\0')
526 break;
527 if ((required == 'n')
528 || (required == '+'))
530 optional = '*';
531 required = '\0';
533 else if (required == 'p')
534 required = 'n';
535 } while (TRUE);
538 if (arg != NULL)
539 return FFEBAD_INTRINSIC_TOOMANY;
541 /* Set up the initial type for the return value of the function. */
543 need_col = FALSE;
544 switch (c[0])
546 case 'A':
547 bt = FFEINFO_basictypeCHARACTER;
548 sz = (c[2] == '*') ? FFETARGET_charactersizeNONE : 1;
549 break;
551 case 'C':
552 bt = FFEINFO_basictypeCOMPLEX;
553 break;
555 case 'I':
556 bt = FFEINFO_basictypeINTEGER;
557 break;
559 case 'L':
560 bt = FFEINFO_basictypeLOGICAL;
561 break;
563 case 'R':
564 bt = FFEINFO_basictypeREAL;
565 break;
567 case 'B':
568 case 'F':
569 case 'N':
570 case 'S':
571 need_col = TRUE;
572 /* Fall through. */
573 case '-':
574 default:
575 bt = FFEINFO_basictypeNONE;
576 break;
579 switch (c[1])
581 case '1': case '2': case '3': case '4': case '5':
582 case '6': case '7': case '8': case '9':
583 kt = (c[1] - '0');
584 if ((bt == FFEINFO_basictypeINTEGER)
585 || (bt == FFEINFO_basictypeLOGICAL))
587 switch (kt)
588 { /* Translate to internal kinds for now! */
589 default:
590 break;
592 case 2:
593 kt = 4;
594 break;
596 case 3:
597 kt = 2;
598 break;
600 case 4:
601 kt = 5;
602 break;
604 case 6:
605 kt = 3;
606 break;
608 case 7:
609 kt = ffecom_pointer_kind ();
610 break;
613 break;
615 case 'C':
616 if (ffe_is_90 ())
617 need_col = TRUE;
618 kt = 1;
619 break;
621 case '=':
622 need_col = TRUE;
623 /* Fall through. */
624 case '-':
625 default:
626 kt = FFEINFO_kindtypeNONE;
627 break;
630 /* Determine collective type of COL, if there is one. */
632 if (need_col || c[colon + 1] != '-')
634 bool okay = TRUE;
635 bool have_anynum = FALSE;
637 for (arg = args;
638 arg != NULL;
639 arg = (c[colon + 1] == '*') ? ffebld_trail (arg) : NULL)
641 ffebld a = ffebld_head (arg);
642 ffeinfo i;
643 bool anynum;
645 if (a == NULL)
646 continue;
647 i = ffebld_info (a);
649 anynum = (ffeinfo_basictype (i) == FFEINFO_basictypeHOLLERITH)
650 || (ffeinfo_basictype (i) == FFEINFO_basictypeTYPELESS);
651 if (anynum)
653 have_anynum = TRUE;
654 continue;
657 if ((col_bt == FFEINFO_basictypeNONE)
658 && (col_kt == FFEINFO_kindtypeNONE))
660 col_bt = ffeinfo_basictype (i);
661 col_kt = ffeinfo_kindtype (i);
663 else
665 ffeexpr_type_combine (&col_bt, &col_kt,
666 col_bt, col_kt,
667 ffeinfo_basictype (i),
668 ffeinfo_kindtype (i),
669 NULL);
670 if ((col_bt == FFEINFO_basictypeNONE)
671 || (col_kt == FFEINFO_kindtypeNONE))
672 return FFEBAD_INTRINSIC_REF;
676 if (have_anynum
677 && ((col_bt == FFEINFO_basictypeNONE)
678 || (col_kt == FFEINFO_kindtypeNONE)))
680 /* No type, but have hollerith/typeless. Use type of return
681 value to determine type of COL. */
683 switch (c[0])
685 case 'A':
686 return FFEBAD_INTRINSIC_REF;
688 case 'B':
689 case 'I':
690 case 'L':
691 if ((col_bt != FFEINFO_basictypeNONE)
692 && (col_bt != FFEINFO_basictypeINTEGER))
693 return FFEBAD_INTRINSIC_REF;
694 /* Fall through. */
695 case 'N':
696 case 'S':
697 case '-':
698 default:
699 col_bt = FFEINFO_basictypeINTEGER;
700 col_kt = FFEINFO_kindtypeINTEGER1;
701 break;
703 case 'C':
704 if ((col_bt != FFEINFO_basictypeNONE)
705 && (col_bt != FFEINFO_basictypeCOMPLEX))
706 return FFEBAD_INTRINSIC_REF;
707 col_bt = FFEINFO_basictypeCOMPLEX;
708 col_kt = FFEINFO_kindtypeREAL1;
709 break;
711 case 'R':
712 if ((col_bt != FFEINFO_basictypeNONE)
713 && (col_bt != FFEINFO_basictypeREAL))
714 return FFEBAD_INTRINSIC_REF;
715 /* Fall through. */
716 case 'F':
717 col_bt = FFEINFO_basictypeREAL;
718 col_kt = FFEINFO_kindtypeREAL1;
719 break;
723 switch (c[0])
725 case 'B':
726 okay = (col_bt == FFEINFO_basictypeINTEGER)
727 || (col_bt == FFEINFO_basictypeLOGICAL);
728 if (need_col)
729 bt = col_bt;
730 break;
732 case 'F':
733 okay = (col_bt == FFEINFO_basictypeCOMPLEX)
734 || (col_bt == FFEINFO_basictypeREAL);
735 if (need_col)
736 bt = col_bt;
737 break;
739 case 'N':
740 okay = (col_bt == FFEINFO_basictypeCOMPLEX)
741 || (col_bt == FFEINFO_basictypeINTEGER)
742 || (col_bt == FFEINFO_basictypeREAL);
743 if (need_col)
744 bt = col_bt;
745 break;
747 case 'S':
748 okay = (col_bt == FFEINFO_basictypeINTEGER)
749 || (col_bt == FFEINFO_basictypeREAL)
750 || (col_bt == FFEINFO_basictypeCOMPLEX);
751 if (need_col)
752 bt = ((col_bt != FFEINFO_basictypeCOMPLEX) ? col_bt
753 : FFEINFO_basictypeREAL);
754 break;
757 switch (c[1])
759 case '=':
760 if (need_col)
761 kt = col_kt;
762 break;
764 case 'C':
765 if (col_bt == FFEINFO_basictypeCOMPLEX)
767 if (col_kt != FFEINFO_kindtypeREALDEFAULT)
768 *check_intrin = TRUE;
769 if (need_col)
770 kt = col_kt;
772 break;
775 if (!okay)
776 return FFEBAD_INTRINSIC_REF;
779 /* Now, convert args in the arglist to the final type of the COL. */
781 for (argno = 0, argc = &c[colon + 3],
782 arg = args;
783 *argc != '\0';
784 ++argno)
786 char optional = '\0';
787 char required = '\0';
788 char extra = '\0';
789 char basic;
790 char kind;
791 int length;
792 int elements;
793 bool lastarg_complex = FALSE;
795 /* We don't do anything with keywords yet. */
798 } while (*(++argc) != '=');
800 ++argc;
801 if ((*argc == '?')
802 || (*argc == '!')
803 || (*argc == '*'))
804 optional = *(argc++);
805 if ((*argc == '+')
806 || (*argc == 'n')
807 || (*argc == 'p'))
808 required = *(argc++);
809 basic = *(argc++);
810 kind = *(argc++);
811 if (*argc == '[')
813 length = *++argc - '0';
814 if (*++argc != ']')
815 length = 10 * length + (*(argc++) - '0');
816 ++argc;
818 else
819 length = -1;
820 if (*argc == '(')
822 elements = *++argc - '0';
823 if (*++argc != ')')
824 elements = 10 * elements + (*(argc++) - '0');
825 ++argc;
827 else if (*argc == '&')
829 elements = -1;
830 ++argc;
832 else
833 elements = 0;
834 if ((*argc == '&')
835 || (*argc == 'i')
836 || (*argc == 'w')
837 || (*argc == 'x'))
838 extra = *(argc++);
839 if (*argc == ',')
840 ++argc;
842 /* Break out of this loop only when current arg spec completely
843 processed. */
847 bool okay;
848 ffebld a;
849 ffeinfo i;
850 bool anynum;
851 ffeinfoBasictype abt = FFEINFO_basictypeNONE;
852 ffeinfoKindtype akt = FFEINFO_kindtypeNONE;
854 if ((arg == NULL)
855 || (ffebld_head (arg) == NULL))
857 if (arg != NULL)
858 arg = ffebld_trail (arg);
859 break; /* Try next argspec. */
862 a = ffebld_head (arg);
863 i = ffebld_info (a);
864 anynum = (ffeinfo_basictype (i) == FFEINFO_basictypeHOLLERITH)
865 || (ffeinfo_basictype (i) == FFEINFO_basictypeTYPELESS);
867 /* Determine what the default type for anynum would be. */
869 if (anynum)
871 switch (c[colon + 1])
873 case '-':
874 break;
875 case '0': case '1': case '2': case '3': case '4':
876 case '5': case '6': case '7': case '8': case '9':
877 if (argno != (c[colon + 1] - '0'))
878 break;
879 case '*':
880 abt = col_bt;
881 akt = col_kt;
882 break;
886 /* Again, match arg up to the spec. We go through all of
887 this again to properly follow the contour of optional
888 arguments. Probably this level of flexibility is not
889 needed, perhaps it's even downright naughty. */
891 switch (basic)
893 case 'A':
894 okay = (ffeinfo_basictype (i) == FFEINFO_basictypeCHARACTER)
895 && ((length == -1)
896 || (ffeinfo_size (i) == (ffetargetCharacterSize) length));
897 break;
899 case 'C':
900 okay = anynum
901 || (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX);
902 abt = FFEINFO_basictypeCOMPLEX;
903 break;
905 case 'I':
906 okay = anynum
907 || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER);
908 abt = FFEINFO_basictypeINTEGER;
909 break;
911 case 'L':
912 okay = anynum
913 || (ffeinfo_basictype (i) == FFEINFO_basictypeLOGICAL);
914 abt = FFEINFO_basictypeLOGICAL;
915 break;
917 case 'R':
918 okay = anynum
919 || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
920 abt = FFEINFO_basictypeREAL;
921 break;
923 case 'B':
924 okay = anynum
925 || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
926 || (ffeinfo_basictype (i) == FFEINFO_basictypeLOGICAL);
927 break;
929 case 'F':
930 okay = anynum
931 || (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX)
932 || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
933 break;
935 case 'N':
936 okay = anynum
937 || (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX)
938 || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
939 || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
940 break;
942 case 'S':
943 okay = anynum
944 || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
945 || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
946 break;
948 case 'g':
949 okay = ((ffebld_op (a) == FFEBLD_opLABTER)
950 || (ffebld_op (a) == FFEBLD_opLABTOK));
951 elements = -1;
952 extra = '-';
953 break;
955 case 's':
956 okay = (((((ffeinfo_basictype (i) == FFEINFO_basictypeNONE)
957 && (ffeinfo_kindtype (i) == FFEINFO_kindtypeNONE)
958 && (ffeinfo_kind (i) == FFEINFO_kindSUBROUTINE))
959 || ((ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
960 && (ffeinfo_kindtype (i) == FFEINFO_kindtypeINTEGERDEFAULT)
961 && (ffeinfo_kind (i) == FFEINFO_kindFUNCTION))
962 || (ffeinfo_kind (i) == FFEINFO_kindNONE))
963 && ((ffeinfo_where (i) == FFEINFO_whereDUMMY)
964 || (ffeinfo_where (i) == FFEINFO_whereGLOBAL)))
965 || ((ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
966 && (ffeinfo_kind (i) == FFEINFO_kindENTITY)));
967 elements = -1;
968 extra = '-';
969 break;
971 case '-':
972 default:
973 okay = TRUE;
974 break;
977 switch (kind)
979 case '1': case '2': case '3': case '4': case '5':
980 case '6': case '7': case '8': case '9':
981 akt = (kind - '0');
982 if ((ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
983 || (ffeinfo_basictype (i) == FFEINFO_basictypeLOGICAL))
985 switch (akt)
986 { /* Translate to internal kinds for now! */
987 default:
988 break;
990 case 2:
991 akt = 4;
992 break;
994 case 3:
995 akt = 2;
996 break;
998 case 4:
999 akt = 5;
1000 break;
1002 case 6:
1003 akt = 3;
1004 break;
1006 case 7:
1007 akt = ffecom_pointer_kind ();
1008 break;
1011 okay &= anynum || (ffeinfo_kindtype (i) == akt);
1012 break;
1014 case 'A':
1015 okay &= anynum || (ffeinfo_kindtype (i) == firstarg_kt);
1016 akt = (firstarg_kt == FFEINFO_kindtype) ? FFEINFO_kindtypeNONE
1017 : firstarg_kt;
1018 break;
1020 case '*':
1021 default:
1022 break;
1025 switch (elements)
1027 ffebld b;
1029 case -1:
1030 break;
1032 case 0:
1033 if (ffeinfo_rank (i) != 0)
1034 okay = FALSE;
1035 break;
1037 default:
1038 if ((ffeinfo_rank (i) != 1)
1039 || (ffebld_op (a) != FFEBLD_opSYMTER)
1040 || ((b = ffesymbol_arraysize (ffebld_symter (a))) == NULL)
1041 || (ffebld_op (b) != FFEBLD_opCONTER)
1042 || (ffeinfo_basictype (ffebld_info (b)) != FFEINFO_basictypeINTEGER)
1043 || (ffeinfo_kindtype (ffebld_info (b)) != FFEINFO_kindtypeINTEGERDEFAULT)
1044 || (ffebld_constant_integer1 (ffebld_conter (b)) != elements))
1045 okay = FALSE;
1046 break;
1049 switch (extra)
1051 case '&':
1052 if ((ffeinfo_kind (i) != FFEINFO_kindENTITY)
1053 || ((ffebld_op (a) != FFEBLD_opSYMTER)
1054 && (ffebld_op (a) != FFEBLD_opSUBSTR)
1055 && (ffebld_op (a) != FFEBLD_opARRAYREF)))
1056 okay = FALSE;
1057 break;
1059 case 'w':
1060 case 'x':
1061 if ((ffeinfo_kind (i) != FFEINFO_kindENTITY)
1062 || ((ffebld_op (a) != FFEBLD_opSYMTER)
1063 && (ffebld_op (a) != FFEBLD_opARRAYREF)
1064 && (ffebld_op (a) != FFEBLD_opSUBSTR)))
1065 okay = FALSE;
1066 break;
1068 case '-':
1069 case 'i':
1070 break;
1072 default:
1073 if (ffeinfo_kind (i) != FFEINFO_kindENTITY)
1074 okay = FALSE;
1075 break;
1078 if ((optional == '!')
1079 && lastarg_complex)
1080 okay = FALSE;
1082 if (!okay)
1084 /* If it wasn't optional, it's an error,
1085 else maybe it could match a later argspec. */
1086 if (optional == '\0')
1087 return FFEBAD_INTRINSIC_REF;
1088 break; /* Try next argspec. */
1091 lastarg_complex
1092 = (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX);
1094 if (anynum && commit)
1096 /* If we know dummy arg type, convert to that now. */
1098 if (abt == FFEINFO_basictypeNONE)
1099 abt = FFEINFO_basictypeINTEGER;
1100 if (akt == FFEINFO_kindtypeNONE)
1101 akt = FFEINFO_kindtypeINTEGER1;
1103 /* We have a known type, convert hollerith/typeless to it. */
1105 a = ffeexpr_convert (a, t, NULL,
1106 abt, akt, 0,
1107 FFETARGET_charactersizeNONE,
1108 FFEEXPR_contextLET);
1109 ffebld_set_head (arg, a);
1111 else if ((c[colon + 1] == '*') && commit)
1113 /* This is where we promote types to the consensus
1114 type for the COL. Maybe this is where -fpedantic
1115 should issue a warning as well. */
1117 a = ffeexpr_convert (a, t, NULL,
1118 col_bt, col_kt, 0,
1119 ffeinfo_size (i),
1120 FFEEXPR_contextLET);
1121 ffebld_set_head (arg, a);
1124 arg = ffebld_trail (arg); /* Arg accepted, now move on. */
1126 if (optional == '*')
1127 continue; /* Go ahead and try another arg. */
1128 if (required == '\0')
1129 break;
1130 if ((required == 'n')
1131 || (required == '+'))
1133 optional = '*';
1134 required = '\0';
1136 else if (required == 'p')
1137 required = 'n';
1138 } while (TRUE);
1141 *xbt = bt;
1142 *xkt = kt;
1143 *xsz = sz;
1144 return FFEBAD;
1147 static bool
1148 ffeintrin_check_any_ (ffebld arglist)
1150 ffebld item;
1152 for (; arglist != NULL; arglist = ffebld_trail (arglist))
1154 item = ffebld_head (arglist);
1155 if ((item != NULL)
1156 && (ffebld_op (item) == FFEBLD_opANY))
1157 return TRUE;
1160 return FALSE;
1163 /* Compare name to intrinsic's name. Uses strcmp on arguments' names. */
1165 static int
1166 ffeintrin_cmp_name_ (const void *name, const void *intrinsic)
1168 const char *uc = ((const struct _ffeintrin_name_ *) intrinsic)->name_uc;
1169 const char *lc = ((const struct _ffeintrin_name_ *) intrinsic)->name_lc;
1170 const char *ic = ((const struct _ffeintrin_name_ *) intrinsic)->name_ic;
1172 return ffesrc_strcmp_2c (ffe_case_intrin (), name, uc, lc, ic);
1175 /* Return basic type of intrinsic implementation, based on its
1176 run-time implementation *only*. (This is used only when
1177 the type of an intrinsic name is needed without having a
1178 list of arguments, i.e. an interface signature, such as when
1179 passing the intrinsic itself, or really the run-time-library
1180 function, as an argument.)
1182 If there's no eligible intrinsic implementation, there must be
1183 a bug somewhere else; no such reference should have been permitted
1184 to go this far. (Well, this might be wrong.) */
1186 ffeinfoBasictype
1187 ffeintrin_basictype (ffeintrinSpec spec)
1189 ffeintrinImp imp;
1190 ffecomGfrt gfrt;
1192 assert (spec < FFEINTRIN_spec);
1193 imp = ffeintrin_specs_[spec].implementation;
1194 assert (imp < FFEINTRIN_imp);
1196 if (ffe_is_f2c ())
1197 gfrt = ffeintrin_imps_[imp].gfrt_f2c;
1198 else
1199 gfrt = ffeintrin_imps_[imp].gfrt_gnu;
1201 assert (gfrt != FFECOM_gfrt);
1203 return ffecom_gfrt_basictype (gfrt);
1206 /* Return family to which specific intrinsic belongs. */
1208 ffeintrinFamily
1209 ffeintrin_family (ffeintrinSpec spec)
1211 if (spec >= FFEINTRIN_spec)
1212 return FALSE;
1213 return ffeintrin_specs_[spec].family;
1216 /* Check and fill in info on func/subr ref node.
1218 ffebld expr; // FUNCREF or SUBRREF with no info (caller
1219 // gets it from the modified info structure).
1220 ffeinfo info; // Already filled in, will be overwritten.
1221 ffelexToken token; // Used for error message.
1222 ffeintrin_fulfill_generic (&expr, &info, token);
1224 Based on the generic id, figure out which specific procedure is meant and
1225 pick that one. Else return an error, a la _specific. */
1227 void
1228 ffeintrin_fulfill_generic (ffebld *expr, ffeinfo *info, ffelexToken t)
1230 ffebld symter;
1231 ffebldOp op;
1232 ffeintrinGen gen;
1233 ffeintrinSpec spec = FFEINTRIN_specNONE;
1234 ffeinfoBasictype bt = FFEINFO_basictypeNONE;
1235 ffeinfoKindtype kt = FFEINFO_kindtypeNONE;
1236 ffetargetCharacterSize sz = FFETARGET_charactersizeNONE;
1237 ffeintrinImp imp;
1238 ffeintrinSpec tspec;
1239 ffeintrinImp nimp = FFEINTRIN_impNONE;
1240 ffebad error;
1241 bool any = FALSE;
1242 bool highly_specific = FALSE;
1243 int i;
1245 op = ffebld_op (*expr);
1246 assert ((op == FFEBLD_opFUNCREF) || (op == FFEBLD_opSUBRREF));
1247 assert (ffebld_op (ffebld_left (*expr)) == FFEBLD_opSYMTER);
1249 gen = ffebld_symter_generic (ffebld_left (*expr));
1250 assert (gen != FFEINTRIN_genNONE);
1252 imp = FFEINTRIN_impNONE;
1253 error = FFEBAD;
1255 any = ffeintrin_check_any_ (ffebld_right (*expr));
1257 for (i = 0;
1258 (((size_t) i) < ARRAY_SIZE (ffeintrin_gens_[gen].specs))
1259 && ((tspec = ffeintrin_gens_[gen].specs[i]) != FFEINTRIN_specNONE)
1260 && !any;
1261 ++i)
1263 ffeintrinImp timp = ffeintrin_specs_[tspec].implementation;
1264 ffeinfoBasictype tbt;
1265 ffeinfoKindtype tkt;
1266 ffetargetCharacterSize tsz;
1267 ffeIntrinsicState state
1268 = ffeintrin_state_family (ffeintrin_specs_[tspec].family);
1269 ffebad terror;
1271 if (state == FFE_intrinsicstateDELETED)
1272 continue;
1274 if (timp != FFEINTRIN_impNONE)
1276 if (!(ffeintrin_imps_[timp].control[0] == '-')
1277 != !(ffebld_op (*expr) == FFEBLD_opSUBRREF))
1278 continue; /* Form of reference must match form of specific. */
1281 if (state == FFE_intrinsicstateDISABLED)
1282 terror = FFEBAD_INTRINSIC_DISABLED;
1283 else if (timp == FFEINTRIN_impNONE)
1284 terror = FFEBAD_INTRINSIC_UNIMPL;
1285 else
1287 terror = ffeintrin_check_ (timp, ffebld_op (*expr),
1288 ffebld_right (*expr),
1289 &tbt, &tkt, &tsz, NULL, t, FALSE);
1290 if (terror == FFEBAD)
1292 if (imp != FFEINTRIN_impNONE)
1294 ffebad_start (FFEBAD_INTRINSIC_AMBIG);
1295 ffebad_here (0, ffelex_token_where_line (t),
1296 ffelex_token_where_column (t));
1297 ffebad_string (ffeintrin_gens_[gen].name);
1298 ffebad_string (ffeintrin_specs_[spec].name);
1299 ffebad_string (ffeintrin_specs_[tspec].name);
1300 ffebad_finish ();
1302 else
1304 if (ffebld_symter_specific (ffebld_left (*expr))
1305 == tspec)
1306 highly_specific = TRUE;
1307 imp = timp;
1308 spec = tspec;
1309 bt = tbt;
1310 kt = tkt;
1311 sz = tkt;
1312 error = terror;
1315 else if (terror != FFEBAD)
1316 { /* This error has precedence over others. */
1317 if ((error == FFEBAD_INTRINSIC_DISABLED)
1318 || (error == FFEBAD_INTRINSIC_UNIMPL))
1319 error = FFEBAD;
1323 if (error == FFEBAD)
1324 error = terror;
1327 if (any || (imp == FFEINTRIN_impNONE))
1329 if (!any)
1331 if (error == FFEBAD)
1332 error = FFEBAD_INTRINSIC_REF;
1333 ffebad_start (error);
1334 ffebad_here (0, ffelex_token_where_line (t),
1335 ffelex_token_where_column (t));
1336 ffebad_string (ffeintrin_gens_[gen].name);
1337 ffebad_finish ();
1340 *expr = ffebld_new_any ();
1341 *info = ffeinfo_new_any ();
1343 else
1345 if (!highly_specific && (nimp != FFEINTRIN_impNONE))
1347 fprintf (stderr, "lineno=%ld, gen=%s, imp=%s, timp=%s\n",
1348 (long) lineno,
1349 ffeintrin_gens_[gen].name,
1350 ffeintrin_imps_[imp].name,
1351 ffeintrin_imps_[nimp].name);
1352 assert ("Ambiguous generic reference" == NULL);
1353 abort ();
1355 error = ffeintrin_check_ (imp, ffebld_op (*expr),
1356 ffebld_right (*expr),
1357 &bt, &kt, &sz, NULL, t, TRUE);
1358 assert (error == FFEBAD);
1359 *info = ffeinfo_new (bt,
1362 FFEINFO_kindENTITY,
1363 FFEINFO_whereFLEETING,
1364 sz);
1365 symter = ffebld_left (*expr);
1366 ffebld_symter_set_specific (symter, spec);
1367 ffebld_symter_set_implementation (symter, imp);
1368 ffebld_set_info (symter,
1369 ffeinfo_new (bt,
1372 (bt == FFEINFO_basictypeNONE)
1373 ? FFEINFO_kindSUBROUTINE
1374 : FFEINFO_kindFUNCTION,
1375 FFEINFO_whereINTRINSIC,
1376 sz));
1378 if ((ffesymbol_attrs (ffebld_symter (symter)) & FFESYMBOL_attrsTYPE)
1379 && (((bt != ffesymbol_basictype (ffebld_symter (symter)))
1380 || (kt != ffesymbol_kindtype (ffebld_symter (symter)))
1381 || ((sz != FFETARGET_charactersizeNONE)
1382 && (sz != ffesymbol_size (ffebld_symter (symter)))))))
1384 ffebad_start (FFEBAD_INTRINSIC_TYPE);
1385 ffebad_here (0, ffelex_token_where_line (t),
1386 ffelex_token_where_column (t));
1387 ffebad_string (ffeintrin_gens_[gen].name);
1388 ffebad_finish ();
1390 if (ffeintrin_imps_[imp].y2kbad)
1392 ffebad_start (FFEBAD_INTRINSIC_Y2KBAD);
1393 ffebad_here (0, ffelex_token_where_line (t),
1394 ffelex_token_where_column (t));
1395 ffebad_string (ffeintrin_gens_[gen].name);
1396 ffebad_finish ();
1401 /* Check and fill in info on func/subr ref node.
1403 ffebld expr; // FUNCREF or SUBRREF with no info (caller
1404 // gets it from the modified info structure).
1405 ffeinfo info; // Already filled in, will be overwritten.
1406 bool check_intrin; // May be omitted, else set TRUE if intrinsic needs checking.
1407 ffelexToken token; // Used for error message.
1408 ffeintrin_fulfill_specific (&expr, &info, &check_intrin, token);
1410 Based on the specific id, determine whether the arg list is valid
1411 (number, type, rank, and kind of args) and fill in the info structure
1412 accordingly. Currently don't rewrite the expression, but perhaps
1413 someday do so for constant collapsing, except when an error occurs,
1414 in which case it is overwritten with ANY and info is also overwritten
1415 accordingly. */
1417 void
1418 ffeintrin_fulfill_specific (ffebld *expr, ffeinfo *info,
1419 bool *check_intrin, ffelexToken t)
1421 ffebld symter;
1422 ffebldOp op;
1423 ffeintrinGen gen;
1424 ffeintrinSpec spec;
1425 ffeintrinImp imp;
1426 ffeinfoBasictype bt = FFEINFO_basictypeNONE;
1427 ffeinfoKindtype kt = FFEINFO_kindtypeNONE;
1428 ffetargetCharacterSize sz = FFETARGET_charactersizeNONE;
1429 ffeIntrinsicState state;
1430 ffebad error;
1431 bool any = FALSE;
1432 const char *name;
1434 op = ffebld_op (*expr);
1435 assert ((op == FFEBLD_opFUNCREF) || (op == FFEBLD_opSUBRREF));
1436 assert (ffebld_op (ffebld_left (*expr)) == FFEBLD_opSYMTER);
1438 gen = ffebld_symter_generic (ffebld_left (*expr));
1439 spec = ffebld_symter_specific (ffebld_left (*expr));
1440 assert (spec != FFEINTRIN_specNONE);
1442 if (gen != FFEINTRIN_genNONE)
1443 name = ffeintrin_gens_[gen].name;
1444 else
1445 name = ffeintrin_specs_[spec].name;
1447 state = ffeintrin_state_family (ffeintrin_specs_[spec].family);
1449 imp = ffeintrin_specs_[spec].implementation;
1450 if (check_intrin != NULL)
1451 *check_intrin = FALSE;
1453 any = ffeintrin_check_any_ (ffebld_right (*expr));
1455 if (state == FFE_intrinsicstateDISABLED)
1456 error = FFEBAD_INTRINSIC_DISABLED;
1457 else if (imp == FFEINTRIN_impNONE)
1458 error = FFEBAD_INTRINSIC_UNIMPL;
1459 else if (!any)
1461 error = ffeintrin_check_ (imp, ffebld_op (*expr),
1462 ffebld_right (*expr),
1463 &bt, &kt, &sz, check_intrin, t, TRUE);
1465 else
1466 error = FFEBAD; /* Not really needed, but quiet -Wuninitialized. */
1468 if (any || (error != FFEBAD))
1470 if (!any)
1473 ffebad_start (error);
1474 ffebad_here (0, ffelex_token_where_line (t),
1475 ffelex_token_where_column (t));
1476 ffebad_string (name);
1477 ffebad_finish ();
1480 *expr = ffebld_new_any ();
1481 *info = ffeinfo_new_any ();
1483 else
1485 *info = ffeinfo_new (bt,
1488 FFEINFO_kindENTITY,
1489 FFEINFO_whereFLEETING,
1490 sz);
1491 symter = ffebld_left (*expr);
1492 ffebld_set_info (symter,
1493 ffeinfo_new (bt,
1496 (bt == FFEINFO_basictypeNONE)
1497 ? FFEINFO_kindSUBROUTINE
1498 : FFEINFO_kindFUNCTION,
1499 FFEINFO_whereINTRINSIC,
1500 sz));
1502 if ((ffesymbol_attrs (ffebld_symter (symter)) & FFESYMBOL_attrsTYPE)
1503 && (((bt != ffesymbol_basictype (ffebld_symter (symter)))
1504 || (kt != ffesymbol_kindtype (ffebld_symter (symter)))
1505 || (sz != ffesymbol_size (ffebld_symter (symter))))))
1507 ffebad_start (FFEBAD_INTRINSIC_TYPE);
1508 ffebad_here (0, ffelex_token_where_line (t),
1509 ffelex_token_where_column (t));
1510 ffebad_string (name);
1511 ffebad_finish ();
1513 if (ffeintrin_imps_[imp].y2kbad)
1515 ffebad_start (FFEBAD_INTRINSIC_Y2KBAD);
1516 ffebad_here (0, ffelex_token_where_line (t),
1517 ffelex_token_where_column (t));
1518 ffebad_string (name);
1519 ffebad_finish ();
1524 /* Return run-time index of intrinsic implementation as direct call. */
1526 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1527 ffecomGfrt
1528 ffeintrin_gfrt_direct (ffeintrinImp imp)
1530 assert (imp < FFEINTRIN_imp);
1532 return ffeintrin_imps_[imp].gfrt_direct;
1534 #endif
1536 /* Return run-time index of intrinsic implementation as actual argument. */
1538 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1539 ffecomGfrt
1540 ffeintrin_gfrt_indirect (ffeintrinImp imp)
1542 assert (imp < FFEINTRIN_imp);
1544 if (! ffe_is_f2c ())
1545 return ffeintrin_imps_[imp].gfrt_gnu;
1546 return ffeintrin_imps_[imp].gfrt_f2c;
1548 #endif
1550 void
1551 ffeintrin_init_0 ()
1553 int i;
1554 const char *p1;
1555 const char *p2;
1556 const char *p3;
1557 int colon;
1559 if (!ffe_is_do_internal_checks ())
1560 return;
1562 assert (FFEINTRIN_gen == ARRAY_SIZE (ffeintrin_gens_));
1563 assert (FFEINTRIN_imp == ARRAY_SIZE (ffeintrin_imps_));
1564 assert (FFEINTRIN_spec == ARRAY_SIZE (ffeintrin_specs_));
1566 for (i = 1; ((size_t) i) < ARRAY_SIZE (ffeintrin_names_); ++i)
1567 { /* Make sure binary-searched list is in alpha
1568 order. */
1569 if (strcmp (ffeintrin_names_[i - 1].name_uc,
1570 ffeintrin_names_[i].name_uc) >= 0)
1571 assert ("name list out of order" == NULL);
1574 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffeintrin_names_); ++i)
1576 assert ((ffeintrin_names_[i].generic == FFEINTRIN_genNONE)
1577 || (ffeintrin_names_[i].specific == FFEINTRIN_specNONE));
1579 p1 = ffeintrin_names_[i].name_uc;
1580 p2 = ffeintrin_names_[i].name_lc;
1581 p3 = ffeintrin_names_[i].name_ic;
1582 for (; *p1 != '\0' && *p2 != '\0' && *p3 != '\0'; ++p1, ++p2, ++p3)
1584 if ((ISDIGIT (*p1) || (*p1 == '_')) && (*p1 == *p2) && (*p1 == *p3))
1585 continue;
1586 if (! ISUPPER ((unsigned char)*p1) || ! ISLOWER ((unsigned char)*p2)
1587 || (*p1 != TOUPPER (*p2))
1588 || ((*p3 != *p1) && (*p3 != *p2)))
1589 break;
1591 assert ((*p1 == *p2) && (*p1 == *p3) && (*p1 == '\0'));
1594 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffeintrin_imps_); ++i)
1596 const char *c = ffeintrin_imps_[i].control;
1598 if (c[0] == '\0')
1599 continue;
1601 if ((c[0] != '-')
1602 && (c[0] != 'A')
1603 && (c[0] != 'C')
1604 && (c[0] != 'I')
1605 && (c[0] != 'L')
1606 && (c[0] != 'R')
1607 && (c[0] != 'B')
1608 && (c[0] != 'F')
1609 && (c[0] != 'N')
1610 && (c[0] != 'S'))
1612 fprintf (stderr, "%s: bad return-base-type\n",
1613 ffeintrin_imps_[i].name);
1614 continue;
1616 if ((c[1] != '-')
1617 && (c[1] != '=')
1618 && ((c[1] < '1')
1619 || (c[1] > '9'))
1620 && (c[1] != 'C'))
1622 fprintf (stderr, "%s: bad return-kind-type\n",
1623 ffeintrin_imps_[i].name);
1624 continue;
1626 if (c[2] == ':')
1627 colon = 2;
1628 else
1630 if (c[2] != '*')
1632 fprintf (stderr, "%s: bad return-modifier\n",
1633 ffeintrin_imps_[i].name);
1634 continue;
1636 colon = 3;
1638 if ((c[colon] != ':') || (c[colon + 2] != ':'))
1640 fprintf (stderr, "%s: bad control\n",
1641 ffeintrin_imps_[i].name);
1642 continue;
1644 if ((c[colon + 1] != '-')
1645 && (c[colon + 1] != '*')
1646 && ((c[colon + 1] < '0')
1647 || (c[colon + 1] > '9')))
1649 fprintf (stderr, "%s: bad COL-spec\n",
1650 ffeintrin_imps_[i].name);
1651 continue;
1653 c += (colon + 3);
1654 while (c[0] != '\0')
1656 while ((c[0] != '=')
1657 && (c[0] != ',')
1658 && (c[0] != '\0'))
1659 ++c;
1660 if (c[0] != '=')
1662 fprintf (stderr, "%s: bad keyword\n",
1663 ffeintrin_imps_[i].name);
1664 break;
1666 if ((c[1] == '?')
1667 || (c[1] == '!')
1668 || (c[1] == '+')
1669 || (c[1] == '*')
1670 || (c[1] == 'n')
1671 || (c[1] == 'p'))
1672 ++c;
1673 if ((c[1] != '-')
1674 && (c[1] != 'A')
1675 && (c[1] != 'C')
1676 && (c[1] != 'I')
1677 && (c[1] != 'L')
1678 && (c[1] != 'R')
1679 && (c[1] != 'B')
1680 && (c[1] != 'F')
1681 && (c[1] != 'N')
1682 && (c[1] != 'S')
1683 && (c[1] != 'g')
1684 && (c[1] != 's'))
1686 fprintf (stderr, "%s: bad arg-base-type\n",
1687 ffeintrin_imps_[i].name);
1688 break;
1690 if ((c[2] != '*')
1691 && ((c[2] < '1')
1692 || (c[2] > '9'))
1693 && (c[2] != 'A'))
1695 fprintf (stderr, "%s: bad arg-kind-type\n",
1696 ffeintrin_imps_[i].name);
1697 break;
1699 if (c[3] == '[')
1701 if (((c[4] < '0') || (c[4] > '9'))
1702 || ((c[5] != ']')
1703 && (++c, (c[4] < '0') || (c[4] > '9')
1704 || (c[5] != ']'))))
1706 fprintf (stderr, "%s: bad arg-len\n",
1707 ffeintrin_imps_[i].name);
1708 break;
1710 c += 3;
1712 if (c[3] == '(')
1714 if (((c[4] < '0') || (c[4] > '9'))
1715 || ((c[5] != ')')
1716 && (++c, (c[4] < '0') || (c[4] > '9')
1717 || (c[5] != ')'))))
1719 fprintf (stderr, "%s: bad arg-rank\n",
1720 ffeintrin_imps_[i].name);
1721 break;
1723 c += 3;
1725 else if ((c[3] == '&')
1726 && (c[4] == '&'))
1727 ++c;
1728 if ((c[3] == '&')
1729 || (c[3] == 'i')
1730 || (c[3] == 'w')
1731 || (c[3] == 'x'))
1732 ++c;
1733 if (c[3] == ',')
1735 c += 4;
1736 continue;
1738 if (c[3] != '\0')
1740 fprintf (stderr, "%s: bad arg-list\n",
1741 ffeintrin_imps_[i].name);
1743 break;
1748 /* Determine whether intrinsic is okay as an actual argument. */
1750 bool
1751 ffeintrin_is_actualarg (ffeintrinSpec spec)
1753 ffeIntrinsicState state;
1755 if (spec >= FFEINTRIN_spec)
1756 return FALSE;
1758 state = ffeintrin_state_family (ffeintrin_specs_[spec].family);
1760 return (!ffe_is_pedantic () || ffeintrin_specs_[spec].is_actualarg)
1761 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1762 && (ffe_is_f2c ()
1763 ? (ffeintrin_imps_[ffeintrin_specs_[spec].implementation].gfrt_f2c
1764 != FFECOM_gfrt)
1765 : (ffeintrin_imps_[ffeintrin_specs_[spec].implementation].gfrt_gnu
1766 != FFECOM_gfrt))
1767 #endif
1768 && ((state == FFE_intrinsicstateENABLED)
1769 || (state == FFE_intrinsicstateHIDDEN));
1772 /* Determine if name is intrinsic, return info.
1774 const char *name; // C-string name of possible intrinsic.
1775 ffelexToken t; // NULL if no diagnostic to be given.
1776 bool explicit; // TRUE if INTRINSIC name.
1777 ffeintrinGen gen; // (TRUE only) Generic id of intrinsic.
1778 ffeintrinSpec spec; // (TRUE only) Specific id of intrinsic.
1779 ffeintrinImp imp; // (TRUE only) Implementation id of intrinsic.
1780 if (ffeintrin_is_intrinsic (name, t, explicit,
1781 &gen, &spec, &imp))
1782 // is an intrinsic, use gen, spec, imp, and
1783 // kind accordingly. */
1785 bool
1786 ffeintrin_is_intrinsic (const char *name, ffelexToken t, bool explicit,
1787 ffeintrinGen *xgen, ffeintrinSpec *xspec,
1788 ffeintrinImp *ximp)
1790 struct _ffeintrin_name_ *intrinsic;
1791 ffeintrinGen gen;
1792 ffeintrinSpec spec;
1793 ffeintrinImp imp;
1794 ffeIntrinsicState state;
1795 bool disabled = FALSE;
1796 bool unimpl = FALSE;
1798 intrinsic = bsearch (name, &ffeintrin_names_[0],
1799 ARRAY_SIZE (ffeintrin_names_),
1800 sizeof (struct _ffeintrin_name_),
1801 (void *) ffeintrin_cmp_name_);
1803 if (intrinsic == NULL)
1804 return FALSE;
1806 gen = intrinsic->generic;
1807 spec = intrinsic->specific;
1808 imp = ffeintrin_specs_[spec].implementation;
1810 /* Generic is okay only if at least one of its specifics is okay. */
1812 if (gen != FFEINTRIN_genNONE)
1814 int i;
1815 ffeintrinSpec tspec;
1816 bool ok = FALSE;
1818 name = ffeintrin_gens_[gen].name;
1820 for (i = 0;
1821 (((size_t) i) < ARRAY_SIZE (ffeintrin_gens_[gen].specs))
1822 && ((tspec
1823 = ffeintrin_gens_[gen].specs[i]) != FFEINTRIN_specNONE);
1824 ++i)
1826 state = ffeintrin_state_family (ffeintrin_specs_[tspec].family);
1828 if (state == FFE_intrinsicstateDELETED)
1829 continue;
1831 if (state == FFE_intrinsicstateDISABLED)
1833 disabled = TRUE;
1834 continue;
1837 if (ffeintrin_specs_[tspec].implementation == FFEINTRIN_impNONE)
1839 unimpl = TRUE;
1840 continue;
1843 if ((state == FFE_intrinsicstateENABLED)
1844 || (explicit
1845 && (state == FFE_intrinsicstateHIDDEN)))
1847 ok = TRUE;
1848 break;
1851 if (!ok)
1852 gen = FFEINTRIN_genNONE;
1855 /* Specific is okay only if not: unimplemented, disabled, deleted, or
1856 hidden and not explicit. */
1858 if (spec != FFEINTRIN_specNONE)
1860 if (gen != FFEINTRIN_genNONE)
1861 name = ffeintrin_gens_[gen].name;
1862 else
1863 name = ffeintrin_specs_[spec].name;
1865 if (((state = ffeintrin_state_family (ffeintrin_specs_[spec].family))
1866 == FFE_intrinsicstateDELETED)
1867 || (!explicit
1868 && (state == FFE_intrinsicstateHIDDEN)))
1869 spec = FFEINTRIN_specNONE;
1870 else if (state == FFE_intrinsicstateDISABLED)
1872 disabled = TRUE;
1873 spec = FFEINTRIN_specNONE;
1875 else if (imp == FFEINTRIN_impNONE)
1877 unimpl = TRUE;
1878 spec = FFEINTRIN_specNONE;
1882 /* If neither is okay, not an intrinsic. */
1884 if ((gen == FFEINTRIN_genNONE) && (spec == FFEINTRIN_specNONE))
1886 /* Here is where we produce a diagnostic about a reference to a
1887 disabled or unimplemented intrinsic, if the diagnostic is desired. */
1889 if ((disabled || unimpl)
1890 && (t != NULL))
1892 ffebad_start (disabled
1893 ? FFEBAD_INTRINSIC_DISABLED
1894 : FFEBAD_INTRINSIC_UNIMPLW);
1895 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
1896 ffebad_string (name);
1897 ffebad_finish ();
1900 return FALSE;
1903 /* Determine whether intrinsic is function or subroutine. If no specific
1904 id, scan list of possible specifics for generic to get consensus. If
1905 not unanimous, or clear from the context, return NONE. */
1907 if (spec == FFEINTRIN_specNONE)
1909 int i;
1910 ffeintrinSpec tspec;
1911 ffeintrinImp timp;
1912 bool at_least_one_ok = FALSE;
1914 for (i = 0;
1915 (((size_t) i) < ARRAY_SIZE (ffeintrin_gens_[gen].specs))
1916 && ((tspec
1917 = ffeintrin_gens_[gen].specs[i]) != FFEINTRIN_specNONE);
1918 ++i)
1920 if (((state = ffeintrin_state_family (ffeintrin_specs_[tspec].family))
1921 == FFE_intrinsicstateDELETED)
1922 || (state == FFE_intrinsicstateDISABLED))
1923 continue;
1925 if ((timp = ffeintrin_specs_[tspec].implementation)
1926 == FFEINTRIN_impNONE)
1927 continue;
1929 at_least_one_ok = TRUE;
1930 break;
1933 if (!at_least_one_ok)
1935 *xgen = FFEINTRIN_genNONE;
1936 *xspec = FFEINTRIN_specNONE;
1937 *ximp = FFEINTRIN_impNONE;
1938 return FALSE;
1942 *xgen = gen;
1943 *xspec = spec;
1944 *ximp = imp;
1945 return TRUE;
1948 /* Return TRUE if intrinsic is standard F77 (or, if -ff90, F90). */
1950 bool
1951 ffeintrin_is_standard (ffeintrinGen gen, ffeintrinSpec spec)
1953 if (spec == FFEINTRIN_specNONE)
1955 if (gen == FFEINTRIN_genNONE)
1956 return FALSE;
1958 spec = ffeintrin_gens_[gen].specs[0];
1959 if (spec == FFEINTRIN_specNONE)
1960 return FALSE;
1963 if ((ffeintrin_specs_[spec].family == FFEINTRIN_familyF77)
1964 || (ffe_is_90 ()
1965 && ((ffeintrin_specs_[spec].family == FFEINTRIN_familyF90)
1966 || (ffeintrin_specs_[spec].family == FFEINTRIN_familyMIL)
1967 || (ffeintrin_specs_[spec].family == FFEINTRIN_familyASC))))
1968 return TRUE;
1969 return FALSE;
1972 /* Return kind type of intrinsic implementation. See ffeintrin_basictype,
1973 its sibling. */
1975 ffeinfoKindtype
1976 ffeintrin_kindtype (ffeintrinSpec spec)
1978 ffeintrinImp imp;
1979 ffecomGfrt gfrt;
1981 assert (spec < FFEINTRIN_spec);
1982 imp = ffeintrin_specs_[spec].implementation;
1983 assert (imp < FFEINTRIN_imp);
1985 if (ffe_is_f2c ())
1986 gfrt = ffeintrin_imps_[imp].gfrt_f2c;
1987 else
1988 gfrt = ffeintrin_imps_[imp].gfrt_gnu;
1990 assert (gfrt != FFECOM_gfrt);
1992 return ffecom_gfrt_kindtype (gfrt);
1995 /* Return name of generic intrinsic. */
1997 const char *
1998 ffeintrin_name_generic (ffeintrinGen gen)
2000 assert (gen < FFEINTRIN_gen);
2001 return ffeintrin_gens_[gen].name;
2004 /* Return name of intrinsic implementation. */
2006 const char *
2007 ffeintrin_name_implementation (ffeintrinImp imp)
2009 assert (imp < FFEINTRIN_imp);
2010 return ffeintrin_imps_[imp].name;
2013 /* Return external/internal name of specific intrinsic. */
2015 const char *
2016 ffeintrin_name_specific (ffeintrinSpec spec)
2018 assert (spec < FFEINTRIN_spec);
2019 return ffeintrin_specs_[spec].name;
2022 /* Return state of family. */
2024 ffeIntrinsicState
2025 ffeintrin_state_family (ffeintrinFamily family)
2027 ffeIntrinsicState state;
2029 switch (family)
2031 case FFEINTRIN_familyNONE:
2032 return FFE_intrinsicstateDELETED;
2034 case FFEINTRIN_familyF77:
2035 return FFE_intrinsicstateENABLED;
2037 case FFEINTRIN_familyASC:
2038 state = ffe_intrinsic_state_f2c ();
2039 state = ffe_state_max (state, ffe_intrinsic_state_f90 ());
2040 return state;
2042 case FFEINTRIN_familyMIL:
2043 state = ffe_intrinsic_state_vxt ();
2044 state = ffe_state_max (state, ffe_intrinsic_state_f90 ());
2045 state = ffe_state_max (state, ffe_intrinsic_state_mil ());
2046 return state;
2048 case FFEINTRIN_familyGNU:
2049 state = ffe_intrinsic_state_gnu ();
2050 return state;
2052 case FFEINTRIN_familyF90:
2053 state = ffe_intrinsic_state_f90 ();
2054 return state;
2056 case FFEINTRIN_familyVXT:
2057 state = ffe_intrinsic_state_vxt ();
2058 return state;
2060 case FFEINTRIN_familyFVZ:
2061 state = ffe_intrinsic_state_f2c ();
2062 state = ffe_state_max (state, ffe_intrinsic_state_vxt ());
2063 return state;
2065 case FFEINTRIN_familyF2C:
2066 state = ffe_intrinsic_state_f2c ();
2067 return state;
2069 case FFEINTRIN_familyF2U:
2070 state = ffe_intrinsic_state_unix ();
2071 return state;
2073 case FFEINTRIN_familyBADU77:
2074 state = ffe_intrinsic_state_badu77 ();
2075 return state;
2077 default:
2078 assert ("bad family" == NULL);
2079 return FFE_intrinsicstateDELETED;