00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "proj.h"
00025 #include "intrin.h"
00026 #include "expr.h"
00027 #include "info.h"
00028 #include "src.h"
00029 #include "symbol.h"
00030 #include "target.h"
00031 #include "top.h"
00032
00033 struct _ffeintrin_name_
00034 {
00035 const char *const name_uc;
00036 const char *const name_lc;
00037 const char *const name_ic;
00038 const ffeintrinGen generic;
00039 const ffeintrinSpec specific;
00040 };
00041
00042 struct _ffeintrin_gen_
00043 {
00044 const char *const name;
00045 const ffeintrinSpec specs[2];
00046 };
00047
00048 struct _ffeintrin_spec_
00049 {
00050 const char *const name;
00051
00052
00053 const bool is_actualarg;
00054 const ffeintrinFamily family;
00055 const ffeintrinImp implementation;
00056 };
00057
00058 struct _ffeintrin_imp_
00059 {
00060 const char *const name;
00061 const ffecomGfrt gfrt_direct;
00062 const ffecomGfrt gfrt_f2c;
00063 const ffecomGfrt gfrt_gnu;
00064 const char *const control;
00065 const char y2kbad;
00066 };
00067
00068 static ffebad ffeintrin_check_ (ffeintrinImp imp, ffebldOp op,
00069 ffebld args, ffeinfoBasictype *xbt,
00070 ffeinfoKindtype *xkt,
00071 ffetargetCharacterSize *xsz,
00072 bool *check_intrin,
00073 ffelexToken t,
00074 bool commit);
00075 static bool ffeintrin_check_any_ (ffebld arglist);
00076 static int ffeintrin_cmp_name_ (const void *name, const void *intrinsic);
00077
00078 static const struct _ffeintrin_name_ ffeintrin_names_[]
00079 =
00080 {
00081 #define DEFNAME(UPPER,LOWER,MIXED,GEN,SPEC) \
00082 { UPPER, LOWER, MIXED, FFEINTRIN_ ## GEN, FFEINTRIN_ ## SPEC },
00083 #define DEFGEN(CODE,NAME,SPEC1,SPEC2)
00084 #define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP)
00085 #define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL)
00086 #define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD)
00087 #include "intrin.def"
00088 #undef DEFNAME
00089 #undef DEFGEN
00090 #undef DEFSPEC
00091 #undef DEFIMP
00092 #undef DEFIMPY
00093 };
00094
00095 static const struct _ffeintrin_gen_ ffeintrin_gens_[]
00096 =
00097 {
00098 #define DEFNAME(UPPER,LOWER,MIXED,GEN,SPEC)
00099 #define DEFGEN(CODE,NAME,SPEC1,SPEC2) \
00100 { NAME, { SPEC1, SPEC2, }, },
00101 #define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP)
00102 #define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL)
00103 #define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD)
00104 #include "intrin.def"
00105 #undef DEFNAME
00106 #undef DEFGEN
00107 #undef DEFSPEC
00108 #undef DEFIMP
00109 #undef DEFIMPY
00110 };
00111
00112 static const struct _ffeintrin_imp_ ffeintrin_imps_[]
00113 =
00114 {
00115 #define DEFNAME(UPPER,LOWER,MIXED,GEN,SPEC)
00116 #define DEFGEN(CODE,NAME,SPEC1,SPEC2)
00117 #define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP)
00118 #define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL) \
00119 { NAME, FFECOM_gfrt ## GFRTDIRECT, FFECOM_gfrt ## GFRTF2C, \
00120 FFECOM_gfrt ## GFRTGNU, CONTROL, FALSE },
00121 #define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD) \
00122 { NAME, FFECOM_gfrt ## GFRTDIRECT, FFECOM_gfrt ## GFRTF2C, \
00123 FFECOM_gfrt ## GFRTGNU, CONTROL, Y2KBAD },
00124 #include "intrin.def"
00125 #undef DEFNAME
00126 #undef DEFGEN
00127 #undef DEFSPEC
00128 #undef DEFIMP
00129 #undef DEFIMPY
00130 };
00131
00132 static const struct _ffeintrin_spec_ ffeintrin_specs_[]
00133 =
00134 {
00135 #define DEFNAME(UPPER,LOWER,MIXED,GEN,SPEC)
00136 #define DEFGEN(CODE,NAME,SPEC1,SPEC2)
00137 #define DEFSPEC(CODE,NAME,CALLABLE,FAMILY,IMP) \
00138 { NAME, CALLABLE, FAMILY, IMP, },
00139 #define DEFIMP(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL)
00140 #define DEFIMPY(CODE,NAME,GFRTDIRECT,GFRTF2C,GFRTGNU,CONTROL,Y2KBAD)
00141 #include "intrin.def"
00142 #undef DEFGEN
00143 #undef DEFSPEC
00144 #undef DEFIMP
00145 #undef DEFIMPY
00146 };
00147
00148
00149 static ffebad
00150 ffeintrin_check_ (ffeintrinImp imp, ffebldOp op,
00151 ffebld args, ffeinfoBasictype *xbt,
00152 ffeinfoKindtype *xkt,
00153 ffetargetCharacterSize *xsz,
00154 bool *check_intrin,
00155 ffelexToken t,
00156 bool commit)
00157 {
00158 const char *c = ffeintrin_imps_[imp].control;
00159 bool subr = (c[0] == '-');
00160 const char *argc;
00161 ffebld arg;
00162 ffeinfoBasictype bt;
00163 ffeinfoKindtype kt;
00164 ffetargetCharacterSize sz = FFETARGET_charactersizeNONE;
00165 ffeinfoKindtype firstarg_kt;
00166 bool need_col;
00167 ffeinfoBasictype col_bt = FFEINFO_basictypeNONE;
00168 ffeinfoKindtype col_kt = FFEINFO_kindtypeNONE;
00169 int colon = (c[2] == ':') ? 2 : 3;
00170 int argno;
00171
00172
00173
00174
00175 if (op == FFEBLD_opSUBRREF)
00176 {
00177 if (!subr)
00178 return FFEBAD_INTRINSIC_IS_FUNC;
00179 }
00180 else if (op == FFEBLD_opFUNCREF)
00181 {
00182 if (subr)
00183 return FFEBAD_INTRINSIC_IS_SUBR;
00184 }
00185 else
00186 return FFEBAD_INTRINSIC_REF;
00187
00188
00189
00190 if ((args != NULL)
00191 && (ffebld_head (args) != NULL))
00192 firstarg_kt = ffeinfo_kindtype (ffebld_info (ffebld_head (args)));
00193 else
00194 firstarg_kt = FFEINFO_kindtype;
00195
00196 for (argc = &c[colon + 3],
00197 arg = args;
00198 *argc != '\0';
00199 )
00200 {
00201 char optional = '\0';
00202 char required = '\0';
00203 char extra = '\0';
00204 char basic;
00205 char kind;
00206 int length;
00207 int elements;
00208 bool lastarg_complex = FALSE;
00209
00210
00211 do
00212 {
00213 } while (*(++argc) != '=');
00214
00215 ++argc;
00216 if ((*argc == '?')
00217 || (*argc == '!')
00218 || (*argc == '*'))
00219 optional = *(argc++);
00220 if ((*argc == '+')
00221 || (*argc == 'n')
00222 || (*argc == 'p'))
00223 required = *(argc++);
00224 basic = *(argc++);
00225 kind = *(argc++);
00226 if (*argc == '[')
00227 {
00228 length = *++argc - '0';
00229 if (*++argc != ']')
00230 length = 10 * length + (*(argc++) - '0');
00231 ++argc;
00232 }
00233 else
00234 length = -1;
00235 if (*argc == '(')
00236 {
00237 elements = *++argc - '0';
00238 if (*++argc != ')')
00239 elements = 10 * elements + (*(argc++) - '0');
00240 ++argc;
00241 }
00242 else if (*argc == '&')
00243 {
00244 elements = -1;
00245 ++argc;
00246 }
00247 else
00248 elements = 0;
00249 if ((*argc == '&')
00250 || (*argc == 'i')
00251 || (*argc == 'w')
00252 || (*argc == 'x'))
00253 extra = *(argc++);
00254 if (*argc == ',')
00255 ++argc;
00256
00257
00258
00259
00260 do
00261 {
00262 bool okay;
00263 ffebld a;
00264 ffeinfo i;
00265 bool anynum;
00266 ffeinfoBasictype abt = FFEINFO_basictypeNONE;
00267 ffeinfoKindtype akt = FFEINFO_kindtypeNONE;
00268
00269 if ((arg == NULL)
00270 || (ffebld_head (arg) == NULL))
00271 {
00272 if (required != '\0')
00273 return FFEBAD_INTRINSIC_TOOFEW;
00274 if (optional == '\0')
00275 return FFEBAD_INTRINSIC_TOOFEW;
00276 if (arg != NULL)
00277 arg = ffebld_trail (arg);
00278 break;
00279 }
00280
00281 a = ffebld_head (arg);
00282 i = ffebld_info (a);
00283 anynum = (ffeinfo_basictype (i) == FFEINFO_basictypeHOLLERITH)
00284 || (ffeinfo_basictype (i) == FFEINFO_basictypeTYPELESS);
00285
00286
00287
00288 switch (basic)
00289 {
00290 case 'A':
00291 okay = (ffeinfo_basictype (i) == FFEINFO_basictypeCHARACTER)
00292 && ((length == -1)
00293 || (ffeinfo_size (i) == (ffetargetCharacterSize) length));
00294 break;
00295
00296 case 'C':
00297 okay = anynum
00298 || (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX);
00299 abt = FFEINFO_basictypeCOMPLEX;
00300 break;
00301
00302 case 'I':
00303 okay = anynum
00304 || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER);
00305 abt = FFEINFO_basictypeINTEGER;
00306 break;
00307
00308 case 'L':
00309 okay = anynum
00310 || (ffeinfo_basictype (i) == FFEINFO_basictypeLOGICAL);
00311 abt = FFEINFO_basictypeLOGICAL;
00312 break;
00313
00314 case 'R':
00315 okay = anynum
00316 || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
00317 abt = FFEINFO_basictypeREAL;
00318 break;
00319
00320 case 'B':
00321 okay = anynum
00322 || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
00323 || (ffeinfo_basictype (i) == FFEINFO_basictypeLOGICAL);
00324 break;
00325
00326 case 'F':
00327 okay = anynum
00328 || (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX)
00329 || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
00330 break;
00331
00332 case 'N':
00333 okay = anynum
00334 || (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX)
00335 || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
00336 || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
00337 break;
00338
00339 case 'S':
00340 okay = anynum
00341 || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
00342 || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
00343 break;
00344
00345 case 'g':
00346 okay = ((ffebld_op (a) == FFEBLD_opLABTER)
00347 || (ffebld_op (a) == FFEBLD_opLABTOK));
00348 elements = -1;
00349 extra = '-';
00350 break;
00351
00352 case 's':
00353 okay = (((((ffeinfo_basictype (i) == FFEINFO_basictypeNONE)
00354 && (ffeinfo_kindtype (i) == FFEINFO_kindtypeNONE)
00355 && (ffeinfo_kind (i) == FFEINFO_kindSUBROUTINE))
00356 || ((ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
00357 && (ffeinfo_kindtype (i) == FFEINFO_kindtypeINTEGERDEFAULT)
00358 && (ffeinfo_kind (i) == FFEINFO_kindFUNCTION))
00359 || (ffeinfo_kind (i) == FFEINFO_kindNONE))
00360 && ((ffeinfo_where (i) == FFEINFO_whereDUMMY)
00361 || (ffeinfo_where (i) == FFEINFO_whereGLOBAL)))
00362 || ((ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
00363 && (ffeinfo_kind (i) == FFEINFO_kindENTITY)));
00364 elements = -1;
00365 extra = '-';
00366 break;
00367
00368 case '-':
00369 default:
00370 okay = TRUE;
00371 break;
00372 }
00373
00374 switch (kind)
00375 {
00376 case '1': case '2': case '3': case '4': case '5':
00377 case '6': case '7': case '8': case '9':
00378 akt = (kind - '0');
00379 if ((ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
00380 || (ffeinfo_basictype (i) == FFEINFO_basictypeLOGICAL))
00381 {
00382 switch (akt)
00383 {
00384 default:
00385 break;
00386
00387 case 2:
00388 akt = 4;
00389 break;
00390
00391 case 3:
00392 akt = 2;
00393 break;
00394
00395 case 4:
00396 akt = 5;
00397 break;
00398
00399 case 6:
00400 akt = 3;
00401 break;
00402
00403 case 7:
00404 akt = ffecom_pointer_kind ();
00405 break;
00406 }
00407 }
00408 okay &= anynum || (ffeinfo_kindtype (i) == akt);
00409 break;
00410
00411 case 'A':
00412 okay &= anynum || (ffeinfo_kindtype (i) == firstarg_kt);
00413 akt = (firstarg_kt == FFEINFO_kindtype) ? FFEINFO_kindtypeNONE
00414 : firstarg_kt;
00415 break;
00416
00417 case 'N':
00418
00419 if (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
00420 {
00421 okay &= anynum || (ffeinfo_kindtype (i) == FFEINFO_kindtypeINTEGER1
00422 || ffeinfo_kindtype (i) == FFEINFO_kindtypeINTEGER2
00423 || ffeinfo_kindtype (i) == FFEINFO_kindtypeINTEGER3);
00424 akt = FFEINFO_kindtypeINTEGER1;
00425 }
00426 else if (ffeinfo_basictype (i) == FFEINFO_basictypeLOGICAL)
00427 {
00428 okay &= anynum || (ffeinfo_kindtype (i) == FFEINFO_kindtypeLOGICAL1
00429 || ffeinfo_kindtype (i) == FFEINFO_kindtypeLOGICAL2
00430 || ffeinfo_kindtype (i) == FFEINFO_kindtypeLOGICAL3);
00431 akt = FFEINFO_kindtypeLOGICAL1;
00432 }
00433 break;
00434
00435 case '*':
00436 default:
00437 break;
00438 }
00439
00440 switch (elements)
00441 {
00442 ffebld b;
00443
00444 case -1:
00445 break;
00446
00447 case 0:
00448 if (ffeinfo_rank (i) != 0)
00449 okay = FALSE;
00450 break;
00451
00452 default:
00453 if ((ffeinfo_rank (i) != 1)
00454 || (ffebld_op (a) != FFEBLD_opSYMTER)
00455 || ((b = ffesymbol_arraysize (ffebld_symter (a))) == NULL)
00456 || (ffebld_op (b) != FFEBLD_opCONTER)
00457 || (ffeinfo_basictype (ffebld_info (b)) != FFEINFO_basictypeINTEGER)
00458 || (ffeinfo_kindtype (ffebld_info (b)) != FFEINFO_kindtypeINTEGERDEFAULT)
00459 || (ffebld_constant_integer1 (ffebld_conter (b)) != elements))
00460 okay = FALSE;
00461 break;
00462 }
00463
00464 switch (extra)
00465 {
00466 case '&':
00467 if ((ffeinfo_kind (i) != FFEINFO_kindENTITY)
00468 || ((ffebld_op (a) != FFEBLD_opSYMTER)
00469 && (ffebld_op (a) != FFEBLD_opSUBSTR)
00470 && (ffebld_op (a) != FFEBLD_opARRAYREF)))
00471 okay = FALSE;
00472 break;
00473
00474 case 'w':
00475 case 'x':
00476 if ((ffeinfo_kind (i) != FFEINFO_kindENTITY)
00477 || ((ffebld_op (a) != FFEBLD_opSYMTER)
00478 && (ffebld_op (a) != FFEBLD_opARRAYREF)
00479 && (ffebld_op (a) != FFEBLD_opSUBSTR)))
00480 okay = FALSE;
00481 break;
00482
00483 case '-':
00484 case 'i':
00485 break;
00486
00487 default:
00488 if (ffeinfo_kind (i) != FFEINFO_kindENTITY)
00489 okay = FALSE;
00490 break;
00491 }
00492
00493 if ((optional == '!')
00494 && lastarg_complex)
00495 okay = FALSE;
00496
00497 if (!okay)
00498 {
00499
00500
00501 if (optional == '\0')
00502 return FFEBAD_INTRINSIC_REF;
00503 break;
00504 }
00505
00506 lastarg_complex
00507 = (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX);
00508
00509 if (anynum)
00510 {
00511
00512
00513 if ((abt != FFEINFO_basictypeNONE)
00514 && (akt != FFEINFO_kindtypeNONE)
00515 && commit)
00516 {
00517
00518
00519
00520 a = ffeexpr_convert (a, t, NULL,
00521 abt, akt, 0,
00522 FFETARGET_charactersizeNONE,
00523 FFEEXPR_contextLET);
00524 ffebld_set_head (arg, a);
00525 }
00526 }
00527
00528 arg = ffebld_trail (arg);
00529
00530 if (optional == '*')
00531 continue;
00532 if (required == '\0')
00533 break;
00534 if ((required == 'n')
00535 || (required == '+'))
00536 {
00537 optional = '*';
00538 required = '\0';
00539 }
00540 else if (required == 'p')
00541 required = 'n';
00542 } while (TRUE);
00543 }
00544
00545 if (arg != NULL)
00546 return FFEBAD_INTRINSIC_TOOMANY;
00547
00548
00549
00550 need_col = FALSE;
00551 switch (c[0])
00552 {
00553 case 'A':
00554 bt = FFEINFO_basictypeCHARACTER;
00555 sz = (c[2] == '*') ? FFETARGET_charactersizeNONE : 1;
00556 break;
00557
00558 case 'C':
00559 bt = FFEINFO_basictypeCOMPLEX;
00560 break;
00561
00562 case 'I':
00563 bt = FFEINFO_basictypeINTEGER;
00564 break;
00565
00566 case 'L':
00567 bt = FFEINFO_basictypeLOGICAL;
00568 break;
00569
00570 case 'R':
00571 bt = FFEINFO_basictypeREAL;
00572 break;
00573
00574 case 'B':
00575 case 'F':
00576 case 'N':
00577 case 'S':
00578 need_col = TRUE;
00579
00580 case '-':
00581 default:
00582 bt = FFEINFO_basictypeNONE;
00583 break;
00584 }
00585
00586 switch (c[1])
00587 {
00588 case '1': case '2': case '3': case '4': case '5':
00589 case '6': case '7': case '8': case '9':
00590 kt = (c[1] - '0');
00591 if ((bt == FFEINFO_basictypeINTEGER)
00592 || (bt == FFEINFO_basictypeLOGICAL))
00593 {
00594 switch (kt)
00595 {
00596 default:
00597 break;
00598
00599 case 2:
00600 kt = 4;
00601 break;
00602
00603 case 3:
00604 kt = 2;
00605 break;
00606
00607 case 4:
00608 kt = 5;
00609 break;
00610
00611 case 6:
00612 kt = 3;
00613 break;
00614
00615 case 7:
00616 kt = ffecom_pointer_kind ();
00617 break;
00618 }
00619 }
00620 break;
00621
00622 case 'C':
00623 if (ffe_is_90 ())
00624 need_col = TRUE;
00625 kt = 1;
00626 break;
00627
00628 case '=':
00629 need_col = TRUE;
00630
00631 case '-':
00632 default:
00633 kt = FFEINFO_kindtypeNONE;
00634 break;
00635 }
00636
00637
00638
00639 if (need_col || c[colon + 1] != '-')
00640 {
00641 bool okay = TRUE;
00642 bool have_anynum = FALSE;
00643 int arg_count=0;
00644
00645 for (arg = args, arg_count=0;
00646 arg != NULL;
00647 arg = ffebld_trail (arg), arg_count++ )
00648 {
00649 ffebld a = ffebld_head (arg);
00650 ffeinfo i;
00651 bool anynum;
00652
00653 if (a == NULL)
00654 continue;
00655 i = ffebld_info (a);
00656
00657 if ( c[colon+1] != '*' && (c[colon+1]-'0') != arg_count )
00658 continue;
00659
00660 anynum = (ffeinfo_basictype (i) == FFEINFO_basictypeHOLLERITH)
00661 || (ffeinfo_basictype (i) == FFEINFO_basictypeTYPELESS);
00662 if (anynum)
00663 {
00664 have_anynum = TRUE;
00665 continue;
00666 }
00667
00668 if ((col_bt == FFEINFO_basictypeNONE)
00669 && (col_kt == FFEINFO_kindtypeNONE))
00670 {
00671 col_bt = ffeinfo_basictype (i);
00672 col_kt = ffeinfo_kindtype (i);
00673 }
00674 else
00675 {
00676 ffeexpr_type_combine (&col_bt, &col_kt,
00677 col_bt, col_kt,
00678 ffeinfo_basictype (i),
00679 ffeinfo_kindtype (i),
00680 NULL);
00681 if ((col_bt == FFEINFO_basictypeNONE)
00682 || (col_kt == FFEINFO_kindtypeNONE))
00683 return FFEBAD_INTRINSIC_REF;
00684 }
00685 }
00686
00687 if (have_anynum
00688 && ((col_bt == FFEINFO_basictypeNONE)
00689 || (col_kt == FFEINFO_kindtypeNONE)))
00690 {
00691
00692
00693
00694 switch (c[0])
00695 {
00696 case 'A':
00697 return FFEBAD_INTRINSIC_REF;
00698
00699 case 'B':
00700 case 'I':
00701 case 'L':
00702 if ((col_bt != FFEINFO_basictypeNONE)
00703 && (col_bt != FFEINFO_basictypeINTEGER))
00704 return FFEBAD_INTRINSIC_REF;
00705
00706 case 'N':
00707 case 'S':
00708 case '-':
00709 default:
00710 col_bt = FFEINFO_basictypeINTEGER;
00711 col_kt = FFEINFO_kindtypeINTEGER1;
00712 break;
00713
00714 case 'C':
00715 if ((col_bt != FFEINFO_basictypeNONE)
00716 && (col_bt != FFEINFO_basictypeCOMPLEX))
00717 return FFEBAD_INTRINSIC_REF;
00718 col_bt = FFEINFO_basictypeCOMPLEX;
00719 col_kt = FFEINFO_kindtypeREAL1;
00720 break;
00721
00722 case 'R':
00723 if ((col_bt != FFEINFO_basictypeNONE)
00724 && (col_bt != FFEINFO_basictypeREAL))
00725 return FFEBAD_INTRINSIC_REF;
00726
00727 case 'F':
00728 col_bt = FFEINFO_basictypeREAL;
00729 col_kt = FFEINFO_kindtypeREAL1;
00730 break;
00731 }
00732 }
00733
00734 switch (c[0])
00735 {
00736 case 'B':
00737 okay = (col_bt == FFEINFO_basictypeINTEGER)
00738 || (col_bt == FFEINFO_basictypeLOGICAL);
00739 if (need_col)
00740 bt = col_bt;
00741 break;
00742
00743 case 'F':
00744 okay = (col_bt == FFEINFO_basictypeCOMPLEX)
00745 || (col_bt == FFEINFO_basictypeREAL);
00746 if (need_col)
00747 bt = col_bt;
00748 break;
00749
00750 case 'N':
00751 okay = (col_bt == FFEINFO_basictypeCOMPLEX)
00752 || (col_bt == FFEINFO_basictypeINTEGER)
00753 || (col_bt == FFEINFO_basictypeREAL);
00754 if (need_col)
00755 bt = col_bt;
00756 break;
00757
00758 case 'S':
00759 okay = (col_bt == FFEINFO_basictypeINTEGER)
00760 || (col_bt == FFEINFO_basictypeREAL)
00761 || (col_bt == FFEINFO_basictypeCOMPLEX);
00762 if (need_col)
00763 bt = ((col_bt != FFEINFO_basictypeCOMPLEX) ? col_bt
00764 : FFEINFO_basictypeREAL);
00765 break;
00766 }
00767
00768 switch (c[1])
00769 {
00770 case '=':
00771 if (need_col)
00772 kt = col_kt;
00773 break;
00774
00775 case 'C':
00776 if (col_bt == FFEINFO_basictypeCOMPLEX)
00777 {
00778 if (col_kt != FFEINFO_kindtypeREALDEFAULT)
00779 *check_intrin = TRUE;
00780 if (need_col)
00781 kt = col_kt;
00782 }
00783 break;
00784 }
00785
00786 if (!okay)
00787 return FFEBAD_INTRINSIC_REF;
00788 }
00789
00790
00791
00792 for (argno = 0, argc = &c[colon + 3],
00793 arg = args;
00794 *argc != '\0';
00795 ++argno)
00796 {
00797 char optional = '\0';
00798 char required = '\0';
00799 char extra = '\0';
00800 char basic;
00801 char kind;
00802 int length;
00803 int elements;
00804 bool lastarg_complex = FALSE;
00805
00806
00807 do
00808 {
00809 } while (*(++argc) != '=');
00810
00811 ++argc;
00812 if ((*argc == '?')
00813 || (*argc == '!')
00814 || (*argc == '*'))
00815 optional = *(argc++);
00816 if ((*argc == '+')
00817 || (*argc == 'n')
00818 || (*argc == 'p'))
00819 required = *(argc++);
00820 basic = *(argc++);
00821 kind = *(argc++);
00822 if (*argc == '[')
00823 {
00824 length = *++argc - '0';
00825 if (*++argc != ']')
00826 length = 10 * length + (*(argc++) - '0');
00827 ++argc;
00828 }
00829 else
00830 length = -1;
00831 if (*argc == '(')
00832 {
00833 elements = *++argc - '0';
00834 if (*++argc != ')')
00835 elements = 10 * elements + (*(argc++) - '0');
00836 ++argc;
00837 }
00838 else if (*argc == '&')
00839 {
00840 elements = -1;
00841 ++argc;
00842 }
00843 else
00844 elements = 0;
00845 if ((*argc == '&')
00846 || (*argc == 'i')
00847 || (*argc == 'w')
00848 || (*argc == 'x'))
00849 extra = *(argc++);
00850 if (*argc == ',')
00851 ++argc;
00852
00853
00854
00855
00856 do
00857 {
00858 bool okay;
00859 ffebld a;
00860 ffeinfo i;
00861 bool anynum;
00862 ffeinfoBasictype abt = FFEINFO_basictypeNONE;
00863 ffeinfoKindtype akt = FFEINFO_kindtypeNONE;
00864
00865 if ((arg == NULL)
00866 || (ffebld_head (arg) == NULL))
00867 {
00868 if (arg != NULL)
00869 arg = ffebld_trail (arg);
00870 break;
00871 }
00872
00873 a = ffebld_head (arg);
00874 i = ffebld_info (a);
00875 anynum = (ffeinfo_basictype (i) == FFEINFO_basictypeHOLLERITH)
00876 || (ffeinfo_basictype (i) == FFEINFO_basictypeTYPELESS);
00877
00878
00879
00880 if (anynum)
00881 {
00882 switch (c[colon + 1])
00883 {
00884 case '-':
00885 break;
00886 case '0': case '1': case '2': case '3': case '4':
00887 case '5': case '6': case '7': case '8': case '9':
00888 if (argno != (c[colon + 1] - '0'))
00889 break;
00890 case '*':
00891 abt = col_bt;
00892 akt = col_kt;
00893 break;
00894 }
00895 }
00896
00897
00898
00899
00900
00901
00902 switch (basic)
00903 {
00904 case 'A':
00905 okay = (ffeinfo_basictype (i) == FFEINFO_basictypeCHARACTER)
00906 && ((length == -1)
00907 || (ffeinfo_size (i) == (ffetargetCharacterSize) length));
00908 break;
00909
00910 case 'C':
00911 okay = anynum
00912 || (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX);
00913 abt = FFEINFO_basictypeCOMPLEX;
00914 break;
00915
00916 case 'I':
00917 okay = anynum
00918 || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER);
00919 abt = FFEINFO_basictypeINTEGER;
00920 break;
00921
00922 case 'L':
00923 okay = anynum
00924 || (ffeinfo_basictype (i) == FFEINFO_basictypeLOGICAL);
00925 abt = FFEINFO_basictypeLOGICAL;
00926 break;
00927
00928 case 'R':
00929 okay = anynum
00930 || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
00931 abt = FFEINFO_basictypeREAL;
00932 break;
00933
00934 case 'B':
00935 okay = anynum
00936 || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
00937 || (ffeinfo_basictype (i) == FFEINFO_basictypeLOGICAL);
00938 break;
00939
00940 case 'F':
00941 okay = anynum
00942 || (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX)
00943 || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
00944 break;
00945
00946 case 'N':
00947 okay = anynum
00948 || (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX)
00949 || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
00950 || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
00951 break;
00952
00953 case 'S':
00954 okay = anynum
00955 || (ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
00956 || (ffeinfo_basictype (i) == FFEINFO_basictypeREAL);
00957 break;
00958
00959 case 'g':
00960 okay = ((ffebld_op (a) == FFEBLD_opLABTER)
00961 || (ffebld_op (a) == FFEBLD_opLABTOK));
00962 elements = -1;
00963 extra = '-';
00964 break;
00965
00966 case 's':
00967 okay = (((((ffeinfo_basictype (i) == FFEINFO_basictypeNONE)
00968 && (ffeinfo_kindtype (i) == FFEINFO_kindtypeNONE)
00969 && (ffeinfo_kind (i) == FFEINFO_kindSUBROUTINE))
00970 || ((ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
00971 && (ffeinfo_kindtype (i) == FFEINFO_kindtypeINTEGERDEFAULT)
00972 && (ffeinfo_kind (i) == FFEINFO_kindFUNCTION))
00973 || (ffeinfo_kind (i) == FFEINFO_kindNONE))
00974 && ((ffeinfo_where (i) == FFEINFO_whereDUMMY)
00975 || (ffeinfo_where (i) == FFEINFO_whereGLOBAL)))
00976 || ((ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
00977 && (ffeinfo_kind (i) == FFEINFO_kindENTITY)));
00978 elements = -1;
00979 extra = '-';
00980 break;
00981
00982 case '-':
00983 default:
00984 okay = TRUE;
00985 break;
00986 }
00987
00988 switch (kind)
00989 {
00990 case '1': case '2': case '3': case '4': case '5':
00991 case '6': case '7': case '8': case '9':
00992 akt = (kind - '0');
00993 if ((ffeinfo_basictype (i) == FFEINFO_basictypeINTEGER)
00994 || (ffeinfo_basictype (i) == FFEINFO_basictypeLOGICAL))
00995 {
00996 switch (akt)
00997 {
00998 default:
00999 break;
01000
01001 case 2:
01002 akt = 4;
01003 break;
01004
01005 case 3:
01006 akt = 2;
01007 break;
01008
01009 case 4:
01010 akt = 5;
01011 break;
01012
01013 case 6:
01014 akt = 3;
01015 break;
01016
01017 case 7:
01018 akt = ffecom_pointer_kind ();
01019 break;
01020 }
01021 }
01022 okay &= anynum || (ffeinfo_kindtype (i) == akt);
01023 break;
01024
01025 case 'A':
01026 okay &= anynum || (ffeinfo_kindtype (i) == firstarg_kt);
01027 akt = (firstarg_kt == FFEINFO_kindtype) ? FFEINFO_kindtypeNONE
01028 : firstarg_kt;
01029 break;
01030
01031 case '*':
01032 default:
01033 break;
01034 }
01035
01036 switch (elements)
01037 {
01038 ffebld b;
01039
01040 case -1:
01041 break;
01042
01043 case 0:
01044 if (ffeinfo_rank (i) != 0)
01045 okay = FALSE;
01046 break;
01047
01048 default:
01049 if ((ffeinfo_rank (i) != 1)
01050 || (ffebld_op (a) != FFEBLD_opSYMTER)
01051 || ((b = ffesymbol_arraysize (ffebld_symter (a))) == NULL)
01052 || (ffebld_op (b) != FFEBLD_opCONTER)
01053 || (ffeinfo_basictype (ffebld_info (b)) != FFEINFO_basictypeINTEGER)
01054 || (ffeinfo_kindtype (ffebld_info (b)) != FFEINFO_kindtypeINTEGERDEFAULT)
01055 || (ffebld_constant_integer1 (ffebld_conter (b)) != elements))
01056 okay = FALSE;
01057 break;
01058 }
01059
01060 switch (extra)
01061 {
01062 case '&':
01063 if ((ffeinfo_kind (i) != FFEINFO_kindENTITY)
01064 || ((ffebld_op (a) != FFEBLD_opSYMTER)
01065 && (ffebld_op (a) != FFEBLD_opSUBSTR)
01066 && (ffebld_op (a) != FFEBLD_opARRAYREF)))
01067 okay = FALSE;
01068 break;
01069
01070 case 'w':
01071 case 'x':
01072 if ((ffeinfo_kind (i) != FFEINFO_kindENTITY)
01073 || ((ffebld_op (a) != FFEBLD_opSYMTER)
01074 && (ffebld_op (a) != FFEBLD_opARRAYREF)
01075 && (ffebld_op (a) != FFEBLD_opSUBSTR)))
01076 okay = FALSE;
01077 break;
01078
01079 case '-':
01080 case 'i':
01081 break;
01082
01083 default:
01084 if (ffeinfo_kind (i) != FFEINFO_kindENTITY)
01085 okay = FALSE;
01086 break;
01087 }
01088
01089 if ((optional == '!')
01090 && lastarg_complex)
01091 okay = FALSE;
01092
01093 if (!okay)
01094 {
01095
01096
01097 if (optional == '\0')
01098 return FFEBAD_INTRINSIC_REF;
01099 break;
01100 }
01101
01102 lastarg_complex
01103 = (ffeinfo_basictype (i) == FFEINFO_basictypeCOMPLEX);
01104
01105 if (anynum && commit)
01106 {
01107
01108
01109 if (abt == FFEINFO_basictypeNONE)
01110 abt = FFEINFO_basictypeINTEGER;
01111 if (akt == FFEINFO_kindtypeNONE)
01112 akt = FFEINFO_kindtypeINTEGER1;
01113
01114
01115
01116 a = ffeexpr_convert (a, t, NULL,
01117 abt, akt, 0,
01118 FFETARGET_charactersizeNONE,
01119 FFEEXPR_contextLET);
01120 ffebld_set_head (arg, a);
01121 }
01122 else if ((c[colon + 1] == '*') && commit)
01123 {
01124
01125
01126
01127
01128 a = ffeexpr_convert (a, t, NULL,
01129 col_bt, col_kt, 0,
01130 ffeinfo_size (i),
01131 FFEEXPR_contextLET);
01132 ffebld_set_head (arg, a);
01133 }
01134
01135 arg = ffebld_trail (arg);
01136
01137 if (optional == '*')
01138 continue;
01139 if (required == '\0')
01140 break;
01141 if ((required == 'n')
01142 || (required == '+'))
01143 {
01144 optional = '*';
01145 required = '\0';
01146 }
01147 else if (required == 'p')
01148 required = 'n';
01149 } while (TRUE);
01150 }
01151
01152 *xbt = bt;
01153 *xkt = kt;
01154 *xsz = sz;
01155 return FFEBAD;
01156 }
01157
01158 static bool
01159 ffeintrin_check_any_ (ffebld arglist)
01160 {
01161 ffebld item;
01162
01163 for (; arglist != NULL; arglist = ffebld_trail (arglist))
01164 {
01165 item = ffebld_head (arglist);
01166 if ((item != NULL)
01167 && (ffebld_op (item) == FFEBLD_opANY))
01168 return TRUE;
01169 }
01170
01171 return FALSE;
01172 }
01173
01174
01175
01176 static int
01177 upcasecmp_ (const char *name, const char *ucname)
01178 {
01179 for ( ; *name != 0 && *ucname != 0; name++, ucname++)
01180 {
01181 int i = TOUPPER(*name) - *ucname;
01182
01183 if (i != 0)
01184 return i;
01185 }
01186
01187 return *name - *ucname;
01188 }
01189
01190
01191
01192
01193
01194
01195 static int
01196 ffeintrin_cmp_name_ (const void *name, const void *intrinsic)
01197 {
01198 const char *const uc = ((const struct _ffeintrin_name_ *) intrinsic)->name_uc;
01199 const char *const lc = ((const struct _ffeintrin_name_ *) intrinsic)->name_lc;
01200 const char *const ic = ((const struct _ffeintrin_name_ *) intrinsic)->name_ic;
01201 int i;
01202
01203 if ((i = upcasecmp_ (name, uc)) == 0)
01204 {
01205 switch (ffe_case_intrin ())
01206 {
01207 case FFE_caseLOWER:
01208 return strcmp(name, lc);
01209 case FFE_caseINITCAP:
01210 return strcmp(name, ic);
01211 default:
01212 return 0;
01213 }
01214 }
01215
01216 return i;
01217 }
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230 ffeinfoBasictype
01231 ffeintrin_basictype (ffeintrinSpec spec)
01232 {
01233 ffeintrinImp imp;
01234 ffecomGfrt gfrt;
01235
01236 assert (spec < FFEINTRIN_spec);
01237 imp = ffeintrin_specs_[spec].implementation;
01238 assert (imp < FFEINTRIN_imp);
01239
01240 if (ffe_is_f2c ())
01241 gfrt = ffeintrin_imps_[imp].gfrt_f2c;
01242 else
01243 gfrt = ffeintrin_imps_[imp].gfrt_gnu;
01244
01245 assert (gfrt != FFECOM_gfrt);
01246
01247 return ffecom_gfrt_basictype (gfrt);
01248 }
01249
01250
01251
01252 ffeintrinFamily
01253 ffeintrin_family (ffeintrinSpec spec)
01254 {
01255 if (spec >= FFEINTRIN_spec)
01256 return FALSE;
01257 return ffeintrin_specs_[spec].family;
01258 }
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271 void
01272 ffeintrin_fulfill_generic (ffebld *expr, ffeinfo *info, ffelexToken t)
01273 {
01274 ffebld symter;
01275 ffebldOp op;
01276 ffeintrinGen gen;
01277 ffeintrinSpec spec = FFEINTRIN_specNONE;
01278 ffeinfoBasictype bt = FFEINFO_basictypeNONE;
01279 ffeinfoKindtype kt = FFEINFO_kindtypeNONE;
01280 ffetargetCharacterSize sz = FFETARGET_charactersizeNONE;
01281 ffeintrinImp imp;
01282 ffeintrinSpec tspec;
01283 ffeintrinImp nimp = FFEINTRIN_impNONE;
01284 ffebad error;
01285 bool any = FALSE;
01286 bool highly_specific = FALSE;
01287 int i;
01288
01289 op = ffebld_op (*expr);
01290 assert ((op == FFEBLD_opFUNCREF) || (op == FFEBLD_opSUBRREF));
01291 assert (ffebld_op (ffebld_left (*expr)) == FFEBLD_opSYMTER);
01292
01293 gen = ffebld_symter_generic (ffebld_left (*expr));
01294 assert (gen != FFEINTRIN_genNONE);
01295
01296 imp = FFEINTRIN_impNONE;
01297 error = FFEBAD;
01298
01299 any = ffeintrin_check_any_ (ffebld_right (*expr));
01300
01301 for (i = 0;
01302 (((size_t) i) < ARRAY_SIZE (ffeintrin_gens_[gen].specs))
01303 && ((tspec = ffeintrin_gens_[gen].specs[i]) != FFEINTRIN_specNONE)
01304 && !any;
01305 ++i)
01306 {
01307 ffeintrinImp timp = ffeintrin_specs_[tspec].implementation;
01308 ffeinfoBasictype tbt;
01309 ffeinfoKindtype tkt;
01310 ffetargetCharacterSize tsz;
01311 ffeIntrinsicState state
01312 = ffeintrin_state_family (ffeintrin_specs_[tspec].family);
01313 ffebad terror;
01314
01315 if (state == FFE_intrinsicstateDELETED)
01316 continue;
01317
01318 if (timp != FFEINTRIN_impNONE)
01319 {
01320 if (!(ffeintrin_imps_[timp].control[0] == '-')
01321 != !(ffebld_op (*expr) == FFEBLD_opSUBRREF))
01322 continue;
01323 }
01324
01325 if (state == FFE_intrinsicstateDISABLED)
01326 terror = FFEBAD_INTRINSIC_DISABLED;
01327 else if (timp == FFEINTRIN_impNONE)
01328 terror = FFEBAD_INTRINSIC_UNIMPL;
01329 else
01330 {
01331 terror = ffeintrin_check_ (timp, ffebld_op (*expr),
01332 ffebld_right (*expr),
01333 &tbt, &tkt, &tsz, NULL, t, FALSE);
01334 if (terror == FFEBAD)
01335 {
01336 if (imp != FFEINTRIN_impNONE)
01337 {
01338 ffebad_start (FFEBAD_INTRINSIC_AMBIG);
01339 ffebad_here (0, ffelex_token_where_line (t),
01340 ffelex_token_where_column (t));
01341 ffebad_string (ffeintrin_gens_[gen].name);
01342 ffebad_string (ffeintrin_specs_[spec].name);
01343 ffebad_string (ffeintrin_specs_[tspec].name);
01344 ffebad_finish ();
01345 }
01346 else
01347 {
01348 if (ffebld_symter_specific (ffebld_left (*expr))
01349 == tspec)
01350 highly_specific = TRUE;
01351 imp = timp;
01352 spec = tspec;
01353 bt = tbt;
01354 kt = tkt;
01355 sz = tkt;
01356 error = terror;
01357 }
01358 }
01359 else if (terror != FFEBAD)
01360 {
01361 if ((error == FFEBAD_INTRINSIC_DISABLED)
01362 || (error == FFEBAD_INTRINSIC_UNIMPL))
01363 error = FFEBAD;
01364 }
01365 }
01366
01367 if (error == FFEBAD)
01368 error = terror;
01369 }
01370
01371 if (any || (imp == FFEINTRIN_impNONE))
01372 {
01373 if (!any)
01374 {
01375 if (error == FFEBAD)
01376 error = FFEBAD_INTRINSIC_REF;
01377 ffebad_start (error);
01378 ffebad_here (0, ffelex_token_where_line (t),
01379 ffelex_token_where_column (t));
01380 ffebad_string (ffeintrin_gens_[gen].name);
01381 ffebad_finish ();
01382 }
01383
01384 *expr = ffebld_new_any ();
01385 *info = ffeinfo_new_any ();
01386 }
01387 else
01388 {
01389 if (!highly_specific && (nimp != FFEINTRIN_impNONE))
01390 {
01391 fprintf (stderr, "lineno=%ld, gen=%s, imp=%s, timp=%s\n",
01392 (long) lineno,
01393 ffeintrin_gens_[gen].name,
01394 ffeintrin_imps_[imp].name,
01395 ffeintrin_imps_[nimp].name);
01396 assert ("Ambiguous generic reference" == NULL);
01397 abort ();
01398 }
01399 error = ffeintrin_check_ (imp, ffebld_op (*expr),
01400 ffebld_right (*expr),
01401 &bt, &kt, &sz, NULL, t, TRUE);
01402 assert (error == FFEBAD);
01403 *info = ffeinfo_new (bt,
01404 kt,
01405 0,
01406 FFEINFO_kindENTITY,
01407 FFEINFO_whereFLEETING,
01408 sz);
01409 symter = ffebld_left (*expr);
01410 ffebld_symter_set_specific (symter, spec);
01411 ffebld_symter_set_implementation (symter, imp);
01412 ffebld_set_info (symter,
01413 ffeinfo_new (bt,
01414 kt,
01415 0,
01416 (bt == FFEINFO_basictypeNONE)
01417 ? FFEINFO_kindSUBROUTINE
01418 : FFEINFO_kindFUNCTION,
01419 FFEINFO_whereINTRINSIC,
01420 sz));
01421
01422 if ((ffesymbol_attrs (ffebld_symter (symter)) & FFESYMBOL_attrsTYPE)
01423 && (((bt != ffesymbol_basictype (ffebld_symter (symter)))
01424 || (kt != ffesymbol_kindtype (ffebld_symter (symter)))
01425 || ((sz != FFETARGET_charactersizeNONE)
01426 && (sz != ffesymbol_size (ffebld_symter (symter)))))))
01427 {
01428 ffebad_start (FFEBAD_INTRINSIC_TYPE);
01429 ffebad_here (0, ffelex_token_where_line (t),
01430 ffelex_token_where_column (t));
01431 ffebad_string (ffeintrin_gens_[gen].name);
01432 ffebad_finish ();
01433 }
01434 if (ffeintrin_imps_[imp].y2kbad)
01435 {
01436 ffebad_start (FFEBAD_INTRINSIC_Y2KBAD);
01437 ffebad_here (0, ffelex_token_where_line (t),
01438 ffelex_token_where_column (t));
01439 ffebad_string (ffeintrin_gens_[gen].name);
01440 ffebad_finish ();
01441 }
01442 }
01443 }
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461 void
01462 ffeintrin_fulfill_specific (ffebld *expr, ffeinfo *info,
01463 bool *check_intrin, ffelexToken t)
01464 {
01465 ffebld symter;
01466 ffebldOp op;
01467 ffeintrinGen gen;
01468 ffeintrinSpec spec;
01469 ffeintrinImp imp;
01470 ffeinfoBasictype bt = FFEINFO_basictypeNONE;
01471 ffeinfoKindtype kt = FFEINFO_kindtypeNONE;
01472 ffetargetCharacterSize sz = FFETARGET_charactersizeNONE;
01473 ffeIntrinsicState state;
01474 ffebad error;
01475 bool any = FALSE;
01476 const char *name;
01477
01478 op = ffebld_op (*expr);
01479 assert ((op == FFEBLD_opFUNCREF) || (op == FFEBLD_opSUBRREF));
01480 assert (ffebld_op (ffebld_left (*expr)) == FFEBLD_opSYMTER);
01481
01482 gen = ffebld_symter_generic (ffebld_left (*expr));
01483 spec = ffebld_symter_specific (ffebld_left (*expr));
01484 assert (spec != FFEINTRIN_specNONE);
01485
01486 if (gen != FFEINTRIN_genNONE)
01487 name = ffeintrin_gens_[gen].name;
01488 else
01489 name = ffeintrin_specs_[spec].name;
01490
01491 state = ffeintrin_state_family (ffeintrin_specs_[spec].family);
01492
01493 imp = ffeintrin_specs_[spec].implementation;
01494 if (check_intrin != NULL)
01495 *check_intrin = FALSE;
01496
01497 any = ffeintrin_check_any_ (ffebld_right (*expr));
01498
01499 if (state == FFE_intrinsicstateDISABLED)
01500 error = FFEBAD_INTRINSIC_DISABLED;
01501 else if (imp == FFEINTRIN_impNONE)
01502 error = FFEBAD_INTRINSIC_UNIMPL;
01503 else if (!any)
01504 {
01505 error = ffeintrin_check_ (imp, ffebld_op (*expr),
01506 ffebld_right (*expr),
01507 &bt, &kt, &sz, check_intrin, t, TRUE);
01508 }
01509 else
01510 error = FFEBAD;
01511
01512 if (any || (error != FFEBAD))
01513 {
01514 if (!any)
01515 {
01516
01517 ffebad_start (error);
01518 ffebad_here (0, ffelex_token_where_line (t),
01519 ffelex_token_where_column (t));
01520 ffebad_string (name);
01521 ffebad_finish ();
01522 }
01523
01524 *expr = ffebld_new_any ();
01525 *info = ffeinfo_new_any ();
01526 }
01527 else
01528 {
01529 *info = ffeinfo_new (bt,
01530 kt,
01531 0,
01532 FFEINFO_kindENTITY,
01533 FFEINFO_whereFLEETING,
01534 sz);
01535 symter = ffebld_left (*expr);
01536 ffebld_set_info (symter,
01537 ffeinfo_new (bt,
01538 kt,
01539 0,
01540 (bt == FFEINFO_basictypeNONE)
01541 ? FFEINFO_kindSUBROUTINE
01542 : FFEINFO_kindFUNCTION,
01543 FFEINFO_whereINTRINSIC,
01544 sz));
01545
01546 if ((ffesymbol_attrs (ffebld_symter (symter)) & FFESYMBOL_attrsTYPE)
01547 && (((bt != ffesymbol_basictype (ffebld_symter (symter)))
01548 || (kt != ffesymbol_kindtype (ffebld_symter (symter)))
01549 || (sz != ffesymbol_size (ffebld_symter (symter))))))
01550 {
01551 ffebad_start (FFEBAD_INTRINSIC_TYPE);
01552 ffebad_here (0, ffelex_token_where_line (t),
01553 ffelex_token_where_column (t));
01554 ffebad_string (name);
01555 ffebad_finish ();
01556 }
01557 if (ffeintrin_imps_[imp].y2kbad)
01558 {
01559 ffebad_start (FFEBAD_INTRINSIC_Y2KBAD);
01560 ffebad_here (0, ffelex_token_where_line (t),
01561 ffelex_token_where_column (t));
01562 ffebad_string (name);
01563 ffebad_finish ();
01564 }
01565 }
01566 }
01567
01568
01569
01570 ffecomGfrt
01571 ffeintrin_gfrt_direct (ffeintrinImp imp)
01572 {
01573 assert (imp < FFEINTRIN_imp);
01574
01575 return ffeintrin_imps_[imp].gfrt_direct;
01576 }
01577
01578
01579
01580 ffecomGfrt
01581 ffeintrin_gfrt_indirect (ffeintrinImp imp)
01582 {
01583 assert (imp < FFEINTRIN_imp);
01584
01585 if (! ffe_is_f2c ())
01586 return ffeintrin_imps_[imp].gfrt_gnu;
01587 return ffeintrin_imps_[imp].gfrt_f2c;
01588 }
01589
01590 void
01591 ffeintrin_init_0 ()
01592 {
01593 int i;
01594 const char *p1;
01595 const char *p2;
01596 const char *p3;
01597 int colon;
01598
01599 if (!ffe_is_do_internal_checks ())
01600 return;
01601
01602 assert (FFEINTRIN_gen == ARRAY_SIZE (ffeintrin_gens_));
01603 assert (FFEINTRIN_imp == ARRAY_SIZE (ffeintrin_imps_));
01604 assert (FFEINTRIN_spec == ARRAY_SIZE (ffeintrin_specs_));
01605
01606 for (i = 1; ((size_t) i) < ARRAY_SIZE (ffeintrin_names_); ++i)
01607 {
01608
01609 if (strcmp (ffeintrin_names_[i - 1].name_uc,
01610 ffeintrin_names_[i].name_uc) >= 0)
01611 assert ("name list out of order" == NULL);
01612 }
01613
01614 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffeintrin_names_); ++i)
01615 {
01616 assert ((ffeintrin_names_[i].generic == FFEINTRIN_genNONE)
01617 || (ffeintrin_names_[i].specific == FFEINTRIN_specNONE));
01618
01619 p1 = ffeintrin_names_[i].name_uc;
01620 p2 = ffeintrin_names_[i].name_lc;
01621 p3 = ffeintrin_names_[i].name_ic;
01622 for (; *p1 != '\0' && *p2 != '\0' && *p3 != '\0'; ++p1, ++p2, ++p3)
01623 {
01624 if ((ISDIGIT (*p1) || (*p1 == '_')) && (*p1 == *p2) && (*p1 == *p3))
01625 continue;
01626 if (! ISUPPER ((unsigned char)*p1) || ! ISLOWER ((unsigned char)*p2)
01627 || (*p1 != TOUPPER (*p2))
01628 || ((*p3 != *p1) && (*p3 != *p2)))
01629 break;
01630 }
01631 assert ((*p1 == *p2) && (*p1 == *p3) && (*p1 == '\0'));
01632 }
01633
01634 for (i = 0; ((size_t) i) < ARRAY_SIZE (ffeintrin_imps_); ++i)
01635 {
01636 const char *c = ffeintrin_imps_[i].control;
01637
01638 if (c[0] == '\0')
01639 continue;
01640
01641 if ((c[0] != '-')
01642 && (c[0] != 'A')
01643 && (c[0] != 'C')
01644 && (c[0] != 'I')
01645 && (c[0] != 'L')
01646 && (c[0] != 'R')
01647 && (c[0] != 'B')
01648 && (c[0] != 'F')
01649 && (c[0] != 'N')
01650 && (c[0] != 'S'))
01651 {
01652 fprintf (stderr, "%s: bad return-base-type\n",
01653 ffeintrin_imps_[i].name);
01654 continue;
01655 }
01656 if ((c[1] != '-')
01657 && (c[1] != '=')
01658 && ((c[1] < '1')
01659 || (c[1] > '9'))
01660 && (c[1] != 'C'))
01661 {
01662 fprintf (stderr, "%s: bad return-kind-type\n",
01663 ffeintrin_imps_[i].name);
01664 continue;
01665 }
01666 if (c[2] == ':')
01667 colon = 2;
01668 else
01669 {
01670 if (c[2] != '*')
01671 {
01672 fprintf (stderr, "%s: bad return-modifier\n",
01673 ffeintrin_imps_[i].name);
01674 continue;
01675 }
01676 colon = 3;
01677 }
01678 if ((c[colon] != ':') || (c[colon + 2] != ':'))
01679 {
01680 fprintf (stderr, "%s: bad control\n",
01681 ffeintrin_imps_[i].name);
01682 continue;
01683 }
01684 if ((c[colon + 1] != '-')
01685 && (c[colon + 1] != '*')
01686 && (! ISDIGIT (c[colon + 1])))
01687 {
01688 fprintf (stderr, "%s: bad COL-spec\n",
01689 ffeintrin_imps_[i].name);
01690 continue;
01691 }
01692 c += (colon + 3);
01693 while (c[0] != '\0')
01694 {
01695 while ((c[0] != '=')
01696 && (c[0] != ',')
01697 && (c[0] != '\0'))
01698 ++c;
01699 if (c[0] != '=')
01700 {
01701 fprintf (stderr, "%s: bad keyword\n",
01702 ffeintrin_imps_[i].name);
01703 break;
01704 }
01705 if ((c[1] == '?')
01706 || (c[1] == '!')
01707 || (c[1] == '+')
01708 || (c[1] == '*')
01709 || (c[1] == 'n')
01710 || (c[1] == 'p'))
01711 ++c;
01712 if ((c[1] != '-')
01713 && (c[1] != 'A')
01714 && (c[1] != 'C')
01715 && (c[1] != 'I')
01716 && (c[1] != 'L')
01717 && (c[1] != 'R')
01718 && (c[1] != 'B')
01719 && (c[1] != 'F')
01720 && (c[1] != 'N')
01721 && (c[1] != 'S')
01722 && (c[1] != 'g')
01723 && (c[1] != 's'))
01724 {
01725 fprintf (stderr, "%s: bad arg-base-type\n",
01726 ffeintrin_imps_[i].name);
01727 break;
01728 }
01729 if ((c[2] != '*')
01730 && ((c[2] < '1')
01731 || (c[2] > '9'))
01732 && (c[2] != 'A'))
01733 {
01734 fprintf (stderr, "%s: bad arg-kind-type\n",
01735 ffeintrin_imps_[i].name);
01736 break;
01737 }
01738 if (c[3] == '[')
01739 {
01740 if ((! ISDIGIT (c[4]))
01741 || ((c[5] != ']')
01742 && (++c, ! ISDIGIT (c[4])
01743 || (c[5] != ']'))))
01744 {
01745 fprintf (stderr, "%s: bad arg-len\n",
01746 ffeintrin_imps_[i].name);
01747 break;
01748 }
01749 c += 3;
01750 }
01751 if (c[3] == '(')
01752 {
01753 if ((! ISDIGIT (c[4]))
01754 || ((c[5] != ')')
01755 && (++c, ! ISDIGIT (c[4])
01756 || (c[5] != ')'))))
01757 {
01758 fprintf (stderr, "%s: bad arg-rank\n",
01759 ffeintrin_imps_[i].name);
01760 break;
01761 }
01762 c += 3;
01763 }
01764 else if ((c[3] == '&')
01765 && (c[4] == '&'))
01766 ++c;
01767 if ((c[3] == '&')
01768 || (c[3] == 'i')
01769 || (c[3] == 'w')
01770 || (c[3] == 'x'))
01771 ++c;
01772 if (c[3] == ',')
01773 {
01774 c += 4;
01775 continue;
01776 }
01777 if (c[3] != '\0')
01778 {
01779 fprintf (stderr, "%s: bad arg-list\n",
01780 ffeintrin_imps_[i].name);
01781 }
01782 break;
01783 }
01784 }
01785 }
01786
01787
01788
01789 bool
01790 ffeintrin_is_actualarg (ffeintrinSpec spec)
01791 {
01792 ffeIntrinsicState state;
01793
01794 if (spec >= FFEINTRIN_spec)
01795 return FALSE;
01796
01797 state = ffeintrin_state_family (ffeintrin_specs_[spec].family);
01798
01799 return (!ffe_is_pedantic () || ffeintrin_specs_[spec].is_actualarg)
01800 && (ffe_is_f2c ()
01801 ? (ffeintrin_imps_[ffeintrin_specs_[spec].implementation].gfrt_f2c
01802 != FFECOM_gfrt)
01803 : (ffeintrin_imps_[ffeintrin_specs_[spec].implementation].gfrt_gnu
01804 != FFECOM_gfrt))
01805 && ((state == FFE_intrinsicstateENABLED)
01806 || (state == FFE_intrinsicstateHIDDEN));
01807 }
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822 bool
01823 ffeintrin_is_intrinsic (const char *name, ffelexToken t, bool explicit,
01824 ffeintrinGen *xgen, ffeintrinSpec *xspec,
01825 ffeintrinImp *ximp)
01826 {
01827 struct _ffeintrin_name_ *intrinsic;
01828 ffeintrinGen gen;
01829 ffeintrinSpec spec;
01830 ffeintrinImp imp;
01831 ffeIntrinsicState state;
01832 bool disabled = FALSE;
01833 bool unimpl = FALSE;
01834
01835 intrinsic = bsearch (name, &ffeintrin_names_[0],
01836 ARRAY_SIZE (ffeintrin_names_),
01837 sizeof (struct _ffeintrin_name_),
01838 (void *) ffeintrin_cmp_name_);
01839
01840 if (intrinsic == NULL)
01841 return FALSE;
01842
01843 gen = intrinsic->generic;
01844 spec = intrinsic->specific;
01845 imp = ffeintrin_specs_[spec].implementation;
01846
01847
01848
01849 if (gen != FFEINTRIN_genNONE)
01850 {
01851 int i;
01852 ffeintrinSpec tspec;
01853 bool ok = FALSE;
01854
01855 name = ffeintrin_gens_[gen].name;
01856
01857 for (i = 0;
01858 (((size_t) i) < ARRAY_SIZE (ffeintrin_gens_[gen].specs))
01859 && ((tspec
01860 = ffeintrin_gens_[gen].specs[i]) != FFEINTRIN_specNONE);
01861 ++i)
01862 {
01863 state = ffeintrin_state_family (ffeintrin_specs_[tspec].family);
01864
01865 if (state == FFE_intrinsicstateDELETED)
01866 continue;
01867
01868 if (state == FFE_intrinsicstateDISABLED)
01869 {
01870 disabled = TRUE;
01871 continue;
01872 }
01873
01874 if (ffeintrin_specs_[tspec].implementation == FFEINTRIN_impNONE)
01875 {
01876 unimpl = TRUE;
01877 continue;
01878 }
01879
01880 if ((state == FFE_intrinsicstateENABLED)
01881 || (explicit
01882 && (state == FFE_intrinsicstateHIDDEN)))
01883 {
01884 ok = TRUE;
01885 break;
01886 }
01887 }
01888 if (!ok)
01889 gen = FFEINTRIN_genNONE;
01890 }
01891
01892
01893
01894
01895 if (spec != FFEINTRIN_specNONE)
01896 {
01897 if (gen != FFEINTRIN_genNONE)
01898 name = ffeintrin_gens_[gen].name;
01899 else
01900 name = ffeintrin_specs_[spec].name;
01901
01902 if (((state = ffeintrin_state_family (ffeintrin_specs_[spec].family))
01903 == FFE_intrinsicstateDELETED)
01904 || (!explicit
01905 && (state == FFE_intrinsicstateHIDDEN)))
01906 spec = FFEINTRIN_specNONE;
01907 else if (state == FFE_intrinsicstateDISABLED)
01908 {
01909 disabled = TRUE;
01910 spec = FFEINTRIN_specNONE;
01911 }
01912 else if (imp == FFEINTRIN_impNONE)
01913 {
01914 unimpl = TRUE;
01915 spec = FFEINTRIN_specNONE;
01916 }
01917 }
01918
01919
01920
01921 if ((gen == FFEINTRIN_genNONE) && (spec == FFEINTRIN_specNONE))
01922 {
01923
01924
01925
01926 if ((disabled || unimpl)
01927 && (t != NULL))
01928 {
01929 ffebad_start (disabled
01930 ? FFEBAD_INTRINSIC_DISABLED
01931 : FFEBAD_INTRINSIC_UNIMPLW);
01932 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
01933 ffebad_string (name);
01934 ffebad_finish ();
01935 }
01936
01937 return FALSE;
01938 }
01939
01940
01941
01942
01943
01944 if (spec == FFEINTRIN_specNONE)
01945 {
01946 int i;
01947 ffeintrinSpec tspec;
01948 ffeintrinImp timp;
01949 bool at_least_one_ok = FALSE;
01950
01951 for (i = 0;
01952 (((size_t) i) < ARRAY_SIZE (ffeintrin_gens_[gen].specs))
01953 && ((tspec
01954 = ffeintrin_gens_[gen].specs[i]) != FFEINTRIN_specNONE);
01955 ++i)
01956 {
01957 if (((state = ffeintrin_state_family (ffeintrin_specs_[tspec].family))
01958 == FFE_intrinsicstateDELETED)
01959 || (state == FFE_intrinsicstateDISABLED))
01960 continue;
01961
01962 if ((timp = ffeintrin_specs_[tspec].implementation)
01963 == FFEINTRIN_impNONE)
01964 continue;
01965
01966 at_least_one_ok = TRUE;
01967 break;
01968 }
01969
01970 if (!at_least_one_ok)
01971 {
01972 *xgen = FFEINTRIN_genNONE;
01973 *xspec = FFEINTRIN_specNONE;
01974 *ximp = FFEINTRIN_impNONE;
01975 return FALSE;
01976 }
01977 }
01978
01979 *xgen = gen;
01980 *xspec = spec;
01981 *ximp = imp;
01982 return TRUE;
01983 }
01984
01985
01986
01987 bool
01988 ffeintrin_is_standard (ffeintrinGen gen, ffeintrinSpec spec)
01989 {
01990 if (spec == FFEINTRIN_specNONE)
01991 {
01992 if (gen == FFEINTRIN_genNONE)
01993 return FALSE;
01994
01995 spec = ffeintrin_gens_[gen].specs[0];
01996 if (spec == FFEINTRIN_specNONE)
01997 return FALSE;
01998 }
01999
02000 if ((ffeintrin_specs_[spec].family == FFEINTRIN_familyF77)
02001 || (ffe_is_90 ()
02002 && ((ffeintrin_specs_[spec].family == FFEINTRIN_familyF90)
02003 || (ffeintrin_specs_[spec].family == FFEINTRIN_familyMIL)
02004 || (ffeintrin_specs_[spec].family == FFEINTRIN_familyASC))))
02005 return TRUE;
02006 return FALSE;
02007 }
02008
02009
02010
02011
02012 ffeinfoKindtype
02013 ffeintrin_kindtype (ffeintrinSpec spec)
02014 {
02015 ffeintrinImp imp;
02016 ffecomGfrt gfrt;
02017
02018 assert (spec < FFEINTRIN_spec);
02019 imp = ffeintrin_specs_[spec].implementation;
02020 assert (imp < FFEINTRIN_imp);
02021
02022 if (ffe_is_f2c ())
02023 gfrt = ffeintrin_imps_[imp].gfrt_f2c;
02024 else
02025 gfrt = ffeintrin_imps_[imp].gfrt_gnu;
02026
02027 assert (gfrt != FFECOM_gfrt);
02028
02029 return ffecom_gfrt_kindtype (gfrt);
02030 }
02031
02032
02033
02034 const char *
02035 ffeintrin_name_generic (ffeintrinGen gen)
02036 {
02037 assert (gen < FFEINTRIN_gen);
02038 return ffeintrin_gens_[gen].name;
02039 }
02040
02041
02042
02043 const char *
02044 ffeintrin_name_implementation (ffeintrinImp imp)
02045 {
02046 assert (imp < FFEINTRIN_imp);
02047 return ffeintrin_imps_[imp].name;
02048 }
02049
02050
02051
02052 const char *
02053 ffeintrin_name_specific (ffeintrinSpec spec)
02054 {
02055 assert (spec < FFEINTRIN_spec);
02056 return ffeintrin_specs_[spec].name;
02057 }
02058
02059
02060
02061 ffeIntrinsicState
02062 ffeintrin_state_family (ffeintrinFamily family)
02063 {
02064 ffeIntrinsicState state;
02065
02066 switch (family)
02067 {
02068 case FFEINTRIN_familyNONE:
02069 return FFE_intrinsicstateDELETED;
02070
02071 case FFEINTRIN_familyF77:
02072 return FFE_intrinsicstateENABLED;
02073
02074 case FFEINTRIN_familyASC:
02075 state = ffe_intrinsic_state_f2c ();
02076 state = ffe_state_max (state, ffe_intrinsic_state_f90 ());
02077 return state;
02078
02079 case FFEINTRIN_familyMIL:
02080 state = ffe_intrinsic_state_vxt ();
02081 state = ffe_state_max (state, ffe_intrinsic_state_f90 ());
02082 state = ffe_state_max (state, ffe_intrinsic_state_mil ());
02083 return state;
02084
02085 case FFEINTRIN_familyGNU:
02086 state = ffe_intrinsic_state_gnu ();
02087 return state;
02088
02089 case FFEINTRIN_familyF90:
02090 state = ffe_intrinsic_state_f90 ();
02091 return state;
02092
02093 case FFEINTRIN_familyVXT:
02094 state = ffe_intrinsic_state_vxt ();
02095 return state;
02096
02097 case FFEINTRIN_familyFVZ:
02098 state = ffe_intrinsic_state_f2c ();
02099 state = ffe_state_max (state, ffe_intrinsic_state_vxt ());
02100 return state;
02101
02102 case FFEINTRIN_familyF2C:
02103 state = ffe_intrinsic_state_f2c ();
02104 return state;
02105
02106 case FFEINTRIN_familyF2U:
02107 state = ffe_intrinsic_state_unix ();
02108 return state;
02109
02110 case FFEINTRIN_familyBADU77:
02111 state = ffe_intrinsic_state_badu77 ();
02112 return state;
02113
02114 default:
02115 assert ("bad family" == NULL);
02116 return FFE_intrinsicstateDELETED;
02117 }
02118 }