mojoshader_compiler.c
changeset 996 164238a438e1
parent 995 7e7826e191f5
child 997 a5f4e546b24e
equal deleted inserted replaced
995:7e7826e191f5 996:164238a438e1
  2256         default:
  2256         default:
  2257             return 0;
  2257             return 0;
  2258     } // switch
  2258     } // switch
  2259 } // is_scalar_datatype
  2259 } // is_scalar_datatype
  2260 
  2260 
  2261 static int compatible_arg_datatype(Context *ctx,
  2261 static const MOJOSHADER_astDataType *datatype_base(Context *ctx, const MOJOSHADER_astDataType *dt)
       
  2262 {
       
  2263     dt = reduce_datatype(ctx, dt);
       
  2264     switch (dt->type)
       
  2265     {
       
  2266         case MOJOSHADER_AST_DATATYPE_VECTOR:
       
  2267             dt = dt->vector.base;
       
  2268             break;
       
  2269         case MOJOSHADER_AST_DATATYPE_MATRIX:
       
  2270             dt = dt->matrix.base;
       
  2271             break;
       
  2272         case MOJOSHADER_AST_DATATYPE_BUFFER:
       
  2273             dt = dt->buffer.base;
       
  2274             break;
       
  2275         case MOJOSHADER_AST_DATATYPE_ARRAY:
       
  2276             dt = dt->array.base;
       
  2277             break;
       
  2278         default: break;
       
  2279     } // switch
       
  2280 
       
  2281     return dt;
       
  2282 } // datatype_base
       
  2283 
       
  2284 typedef enum
       
  2285 {
       
  2286     DT_MATCH_INCOMPATIBLE,
       
  2287     DT_MATCH_COMPATIBLE_DOWNCAST,
       
  2288     DT_MATCH_COMPATIBLE_UPCAST,
       
  2289     DT_MATCH_COMPATIBLE,
       
  2290     DT_MATCH_PERFECT
       
  2291 } DatatypeMatch;
       
  2292 
       
  2293 static DatatypeMatch compatible_arg_datatype(Context *ctx,
  2262                                    const MOJOSHADER_astDataType *arg,
  2294                                    const MOJOSHADER_astDataType *arg,
  2263                                    const MOJOSHADER_astDataType *param)
  2295                                    const MOJOSHADER_astDataType *param)
  2264 {
  2296 {
  2265     // The matching rules for HLSL function overloading, as far as I can
  2297     // The matching rules for HLSL function overloading, as far as I can
  2266     //  tell from experimenting with Microsoft's compiler, seem to be this:
  2298     //  tell from experimenting with Microsoft's compiler, seem to be this:
  2267     //
  2299     //
  2268     // - All parameters of a function must match what the caller specified
  2300     // - All parameters of a function must match what the caller specified
  2269     //   after possible type promotion via the following rules.
  2301     //   after possible type promotion via the following rules.
  2270     // - Scalars can be promoted to vectors to make a parameter match.
  2302     // - Scalars can be promoted to vectors to make a parameter match.
  2271     // - Scalars can promote to other scalars (short to int, etc).
  2303     // - Scalars can promote to other scalars (short to int, etc).
  2272     // - Vectors may NOT be promoted (a float2 can't extend to a float4).
  2304     // - Datatypes can downcast, but should generate a warning.
  2273     // - Vectors with the same elements can promote (a half2 can become a float2...I _think_ it can't downcast here.).
  2305     //   (calling void fn(float x); as fn((double)1.0) should warn).
       
  2306     // - Vectors may NOT be extend (a float2 can't implicity extend to a
       
  2307     //   float4).
       
  2308     // - Vectors with the same elements can promote (a half2 can become
       
  2309     //   a float2...I _think_ it can't downcast here.).
  2274     // - A perfect match of all params will be favored over any functions
  2310     // - A perfect match of all params will be favored over any functions
  2275     //   that only match if type promotion is applied.
  2311     //   that only match if type promotion is applied.
       
  2312     // - An imperfect match that doesn't require downcasting will be
       
  2313     //   favored over one that does.
  2276     // - If more than one function matches after this (all params that
  2314     // - If more than one function matches after this (all params that
  2277     //   would be different between two functions are passed scalars)
  2315     //   would be different between two functions can be legally type-promoted)
  2278     //   then fail().
  2316     //   then fail().
  2279 
  2317 
  2280     if (datatypes_match(arg, param))
  2318     if (datatypes_match(arg, param))
  2281         return 1;  // that was easy.
  2319         return DT_MATCH_PERFECT;  // that was easy.
  2282 
  2320 
  2283     arg = reduce_datatype(ctx, arg);
  2321     arg = reduce_datatype(ctx, arg);
  2284     param = reduce_datatype(ctx, param);
  2322     param = reduce_datatype(ctx, param);
  2285 
  2323 
  2286     // we let this go for now if we passed a scalar.
  2324     int do_size_test = 0;
  2287     //  !!! FIXME: should warn when downcasting.
  2325 
  2288     //  !!! FIXME: also, being a bit more picky would be good.
       
  2289     if (is_scalar_datatype(arg))
  2326     if (is_scalar_datatype(arg))
  2290         return 1;
  2327         do_size_test = 1; // we let these all go through for now.
  2291 
  2328 
  2292     else if (arg->type == param->type)
  2329     else if (arg->type == param->type)
  2293     {
  2330     {
  2294         if (arg->type == MOJOSHADER_AST_DATATYPE_VECTOR)
  2331         if (arg->type == MOJOSHADER_AST_DATATYPE_VECTOR)
  2295         {
  2332             do_size_test = (arg->vector.elements == param->vector.elements);
  2296             if (arg->vector.elements == param->vector.elements)
       
  2297                 return datatype_size(arg->vector.base) <= datatype_size(param->vector.base);
       
  2298         } // if
       
  2299         else if (arg->type == MOJOSHADER_AST_DATATYPE_MATRIX)
  2333         else if (arg->type == MOJOSHADER_AST_DATATYPE_MATRIX)
  2300         {
  2334         {
  2301             if ((arg->matrix.rows == param->matrix.rows) &&
  2335             do_size_test =
  2302                 (arg->matrix.columns == param->matrix.columns))
  2336                 ((arg->matrix.rows == param->matrix.rows) &&
  2303                 return datatype_size(arg->matrix.base) <= datatype_size(param->matrix.base);
  2337                  (arg->matrix.columns == param->matrix.columns));
  2304         } // if
  2338         } // if
  2305     } // if
  2339     } // if
  2306 
  2340 
  2307     return 0;
  2341     if (do_size_test)
       
  2342     {
       
  2343         const int argsize = datatype_size(datatype_base(ctx, arg));
       
  2344         const int paramsize = datatype_size(datatype_base(ctx, param));
       
  2345         if (argsize == paramsize)
       
  2346             return DT_MATCH_COMPATIBLE;
       
  2347         else if (argsize < paramsize)
       
  2348             return DT_MATCH_COMPATIBLE_UPCAST;
       
  2349         else /* if (argsize > paramsize) */
       
  2350             return DT_MATCH_COMPATIBLE_DOWNCAST;
       
  2351     } // if
       
  2352 
       
  2353     return DT_MATCH_INCOMPATIBLE;
  2308 } // compatible_arg_datatype
  2354 } // compatible_arg_datatype
       
  2355 
       
  2356 static void print_ast_datatype(FILE *io, const MOJOSHADER_astDataType *dt)
       
  2357 {
       
  2358     int i;
       
  2359 
       
  2360     if (dt == NULL)
       
  2361         return;
       
  2362 
       
  2363     switch (dt->type)
       
  2364     {
       
  2365         case MOJOSHADER_AST_DATATYPE_BOOL:
       
  2366             fprintf(io, "bool");
       
  2367             return;
       
  2368         case MOJOSHADER_AST_DATATYPE_INT:
       
  2369             fprintf(io, "int");
       
  2370             return;
       
  2371         case MOJOSHADER_AST_DATATYPE_UINT:
       
  2372             fprintf(io, "uint");
       
  2373             return;
       
  2374         case MOJOSHADER_AST_DATATYPE_FLOAT:
       
  2375             fprintf(io, "float");
       
  2376             return;
       
  2377         case MOJOSHADER_AST_DATATYPE_FLOAT_SNORM:
       
  2378             fprintf(io, "snorm float");
       
  2379             return;
       
  2380         case MOJOSHADER_AST_DATATYPE_FLOAT_UNORM:
       
  2381             fprintf(io, "unorm float");
       
  2382             return;
       
  2383         case MOJOSHADER_AST_DATATYPE_HALF:
       
  2384             fprintf(io, "half");
       
  2385             return;
       
  2386         case MOJOSHADER_AST_DATATYPE_DOUBLE:
       
  2387             fprintf(io, "double");
       
  2388             return;
       
  2389         case MOJOSHADER_AST_DATATYPE_STRING:
       
  2390             fprintf(io, "string");
       
  2391             return;
       
  2392         case MOJOSHADER_AST_DATATYPE_SAMPLER_1D:
       
  2393             fprintf(io, "sampler1D");
       
  2394             return;
       
  2395         case MOJOSHADER_AST_DATATYPE_SAMPLER_2D:
       
  2396             fprintf(io, "sampler2D");
       
  2397             return;
       
  2398         case MOJOSHADER_AST_DATATYPE_SAMPLER_3D:
       
  2399             fprintf(io, "sampler3D");
       
  2400             return;
       
  2401         case MOJOSHADER_AST_DATATYPE_SAMPLER_CUBE:
       
  2402             fprintf(io, "samplerCUBE");
       
  2403             return;
       
  2404         case MOJOSHADER_AST_DATATYPE_SAMPLER_STATE:
       
  2405             fprintf(io, "sampler_state");
       
  2406             return;
       
  2407         case MOJOSHADER_AST_DATATYPE_SAMPLER_COMPARISON_STATE:
       
  2408             fprintf(io, "SamplerComparisonState");
       
  2409             return;
       
  2410 
       
  2411         case MOJOSHADER_AST_DATATYPE_STRUCT:
       
  2412             fprintf(io, "struct { ");
       
  2413             for (i = 0; i < dt->structure.member_count; i++)
       
  2414             {
       
  2415                 print_ast_datatype(io, dt->structure.members[i].datatype);
       
  2416                 fprintf(io, " %s; ", dt->structure.members[i].identifier);
       
  2417             } // for
       
  2418             fprintf(io, "}");
       
  2419             return;
       
  2420 
       
  2421         case MOJOSHADER_AST_DATATYPE_ARRAY:
       
  2422             print_ast_datatype(io, dt->array.base);
       
  2423             if (dt->array.elements < 0)
       
  2424                 fprintf(io, "[]");
       
  2425             else
       
  2426                 fprintf(io, "[%d]", dt->array.elements);
       
  2427             return;
       
  2428 
       
  2429         case MOJOSHADER_AST_DATATYPE_VECTOR:
       
  2430             fprintf(io, "vector<");
       
  2431             print_ast_datatype(io, dt->vector.base);
       
  2432             fprintf(io, ",%d>", dt->vector.elements);
       
  2433             return;
       
  2434 
       
  2435         case MOJOSHADER_AST_DATATYPE_MATRIX:
       
  2436             fprintf(io, "matrix<");
       
  2437             print_ast_datatype(io, dt->matrix.base);
       
  2438             fprintf(io, ",%d,%d>", dt->matrix.rows, dt->matrix.columns);
       
  2439             return;
       
  2440 
       
  2441         case MOJOSHADER_AST_DATATYPE_BUFFER:
       
  2442             fprintf(io, "buffer<");
       
  2443             print_ast_datatype(io, dt->buffer.base);
       
  2444             fprintf(io, ">");
       
  2445             return;
       
  2446 
       
  2447         case MOJOSHADER_AST_DATATYPE_USER:
       
  2448             fprintf(io, "%s", dt->user.name);
       
  2449             return;
       
  2450 
       
  2451         //case MOJOSHADER_AST_DATATYPE_NONE:
       
  2452         //case MOJOSHADER_AST_DATATYPE_FUNCTION:
       
  2453 
       
  2454         default:
       
  2455             assert(0 && "Unexpected datatype.");
       
  2456             return;
       
  2457     } // switch
       
  2458 } // print_ast_datatype
  2309 
  2459 
  2310 
  2460 
  2311 static const MOJOSHADER_astDataType *type_check_ast(Context *ctx, void *_ast);
  2461 static const MOJOSHADER_astDataType *type_check_ast(Context *ctx, void *_ast);
  2312 
  2462 
  2313 // !!! FIXME: this function sucks.
  2463 // !!! FIXME: this function sucks.
  2314 static const MOJOSHADER_astDataType *match_func_to_call(Context *ctx,
  2464 static const MOJOSHADER_astDataType *match_func_to_call(Context *ctx,
  2315                                     MOJOSHADER_astExpressionCallFunction *ast)
  2465                                     MOJOSHADER_astExpressionCallFunction *ast)
  2316 {
  2466 {
  2317     SymbolScope *best = NULL;  // best choice we find.
  2467     SymbolScope *best = NULL;  // best choice we find.
       
  2468     DatatypeMatch best_match = DT_MATCH_INCOMPATIBLE;
  2318     MOJOSHADER_astExpressionIdentifier *ident = ast->identifier;
  2469     MOJOSHADER_astExpressionIdentifier *ident = ast->identifier;
  2319     const char *sym = ident->identifier;
  2470     const char *sym = ident->identifier;
  2320     const void *value = NULL;
  2471     const void *value = NULL;
  2321     void *iter = NULL;
  2472     void *iter = NULL;
  2322 
  2473 
  2327         argcount++;
  2478         argcount++;
  2328         type_check_ast(ctx, args->argument);
  2479         type_check_ast(ctx, args->argument);
  2329         args = args->next;
  2480         args = args->next;
  2330     } // while;
  2481     } // while;
  2331 
  2482 
       
  2483 printf("Attempt to call function %s(", sym);
       
  2484 args = ast->args;
       
  2485 int qq = 0;
       
  2486 for (qq = 0; qq < argcount; qq++)
       
  2487 {
       
  2488 assert(args != NULL);
       
  2489 const MOJOSHADER_astDataType *x = args->argument->datatype;
       
  2490 args = args->next;
       
  2491 print_ast_datatype(stdout, x);
       
  2492 if (args) printf(", ");
       
  2493 }
       
  2494 printf("); ...\n");
       
  2495 
  2332     // we do some tapdancing to handle function overloading here.
  2496     // we do some tapdancing to handle function overloading here.
  2333     int match = 0;
  2497     DatatypeMatch match = 0;
  2334     while (hash_iter(ctx->variables.hash, sym, &value, &iter))
  2498     while (hash_iter(ctx->variables.hash, sym, &value, &iter))
  2335     {
  2499     {
  2336         SymbolScope *item = (SymbolScope *) value;
  2500         SymbolScope *item = (SymbolScope *) value;
  2337         const MOJOSHADER_astDataType *dt = item->datatype;
  2501         const MOJOSHADER_astDataType *dt = item->datatype;
  2338         dt = reduce_datatype(ctx, dt);
  2502         dt = reduce_datatype(ctx, dt);
  2339         // there's a locally-scoped symbol with this name? It takes precedence.
  2503         // there's a locally-scoped symbol with this name? It takes precedence.
  2340         if (dt->type != MOJOSHADER_AST_DATATYPE_FUNCTION)
  2504         if (dt->type != MOJOSHADER_AST_DATATYPE_FUNCTION)
  2341             return dt;
  2505             return dt;
  2342 
  2506 
  2343         const MOJOSHADER_astDataTypeFunction *dtfn = (MOJOSHADER_astDataTypeFunction *) dt;
  2507         const MOJOSHADER_astDataTypeFunction *dtfn = (MOJOSHADER_astDataTypeFunction *) dt;
  2344         int this_match = 2;  // 2 == perfect, 1 == compatible, 0 == not.
  2508         int this_match = DT_MATCH_PERFECT;
  2345         int i;
  2509         int i;
  2346 
  2510 
  2347         if (argcount != dtfn->num_params)  // !!! FIXME: default args.
  2511         if (argcount != dtfn->num_params)  // !!! FIXME: default args.
  2348             this_match = 0;
  2512             this_match = 0;
  2349         else
  2513         else
  2352             for (i = 0; i < argcount; i++)
  2516             for (i = 0; i < argcount; i++)
  2353             {
  2517             {
  2354                 assert(args != NULL);
  2518                 assert(args != NULL);
  2355                 dt = args->argument->datatype;
  2519                 dt = args->argument->datatype;
  2356                 args = args->next;
  2520                 args = args->next;
  2357                 if (datatypes_match(dt, dtfn->params[i]))
  2521                 const int compatible = compatible_arg_datatype(ctx, dt, dtfn->params[i]);
  2358                     continue;
  2522                 if (this_match > compatible)
  2359 
  2523                     this_match = compatible;
  2360                 // not perfect, but maybe compatible?
       
  2361                 this_match = compatible_arg_datatype(ctx, dt, dtfn->params[i]);
       
  2362                 if (!this_match)
  2524                 if (!this_match)
  2363                     break;
  2525                     break;
  2364             } // for
  2526             } // for
  2365 
  2527 
  2366             if (args != NULL)
  2528             if (args != NULL)
  2367                 this_match = 0;  // too many arguments supplied. No match.
  2529                 this_match = DT_MATCH_INCOMPATIBLE;  // too many arguments supplied. No match.
  2368         } // else
  2530         } // else
  2369 
  2531 
  2370         if (this_match == 2)  // perfect match.
  2532 #if 0
       
  2533         if (this_match == DT_MATCH_PERFECT)  // perfect match.
  2371         {
  2534         {
       
  2535 FILE *io = stdout;
       
  2536 printf("%d PERFECT MATCH: ", ctx->sourceline);
       
  2537 if (dtfn->intrinsic)
       
  2538     printf("/* intrinsic */ ");
       
  2539 print_ast_datatype(io, dt->function.retval);
       
  2540 printf(" %s(", sym);
       
  2541 int i;
       
  2542 for (i = 0; i < dtfn->num_params; i++) {
       
  2543     print_ast_datatype(io, dtfn->params[i]);
       
  2544     if (i < dtfn->num_params-1)
       
  2545         printf(", ");
       
  2546 }
       
  2547 printf(");\n");
  2372             match = 1;  // ignore all other compatible matches.
  2548             match = 1;  // ignore all other compatible matches.
  2373             best = item;
  2549             best = item;
  2374             break;
  2550             break;
  2375         } // if
  2551         } // if
  2376 
  2552 
  2377         else if (this_match == 1)  // compatible, but not perfect, match.
  2553         else
       
  2554 #endif
       
  2555 
       
  2556         if (this_match > DT_MATCH_INCOMPATIBLE)  // compatible, but not perfect, match.
  2378         {
  2557         {
  2379             match++;
  2558 #if 1
  2380             if (match == 1)
  2559 FILE *io = stdout;
  2381                 best = item;
  2560 printf("%d COMPATIBLE MATCH (%d): ", ctx->sourceline, (int) this_match);
  2382             else
  2561 if (dtfn->intrinsic)
       
  2562     printf("/* intrinsic */ ");
       
  2563 if (dt->function.retval)
       
  2564     print_ast_datatype(io, dt->function.retval);
       
  2565 else
       
  2566     printf("void");
       
  2567 printf(" %s(", sym);
       
  2568 int i;
       
  2569 for (i = 0; i < dtfn->num_params; i++) {
       
  2570     print_ast_datatype(io, dtfn->params[i]);
       
  2571     if (i < dtfn->num_params-1)
       
  2572         printf(", ");
       
  2573 }
       
  2574 printf(");\n");
       
  2575 #endif
       
  2576 
       
  2577             if (this_match == best_match)
  2383             {
  2578             {
       
  2579                 match++;
  2384                 // !!! FIXME: list each possible function in a fail(),
  2580                 // !!! FIXME: list each possible function in a fail(),
  2385                 // !!! FIXME:  but you can't actually fail() here, since
  2581                 // !!! FIXME:  but you can't actually fail() here, since
  2386                 // !!! FIXME:  this will cease to be ambiguous if we get
  2582                 // !!! FIXME:  this will cease to be ambiguous if we get
  2387                 // !!! FIXME:  a perfect match on a later overload.
  2583                 // !!! FIXME:  a perfect match on a later overload.
  2388             } // else
  2584             } // if
       
  2585             else if (this_match > best_match)
       
  2586             {
       
  2587                 match = 1;  // reset the ambiguousness count.
       
  2588                 best = item;
       
  2589                 best_match = this_match;
       
  2590             } // if
  2389         } // else if
  2591         } // else if
  2390     } // while
  2592     } // while
  2391 
  2593 
  2392     if (match > 1)
  2594     if (match > 1)
  2393     {
  2595     {