mojoshader_compiler.c
changeset 988 018e77a5ba67
parent 987 109aeb1b6409
child 989 b3dacb4c2804
equal deleted inserted replaced
987:109aeb1b6409 988:018e77a5ba67
  2219     if (*str != '\0')  // must be end of string here.
  2219     if (*str != '\0')  // must be end of string here.
  2220         return 0;  // not a swizzle.
  2220         return 0;  // not a swizzle.
  2221     return ((is_rgba + is_xyzw) == 1);  // can only be one or the other.
  2221     return ((is_rgba + is_xyzw) == 1);  // can only be one or the other.
  2222 } // is_swizzle_str
  2222 } // is_swizzle_str
  2223 
  2223 
       
  2224 static inline int is_scalar_datatype(const MOJOSHADER_astDataType *dt)
       
  2225 {
       
  2226     switch (dt->type)
       
  2227     {
       
  2228         case MOJOSHADER_AST_DATATYPE_BOOL:
       
  2229         case MOJOSHADER_AST_DATATYPE_INT:
       
  2230         case MOJOSHADER_AST_DATATYPE_UINT:
       
  2231         case MOJOSHADER_AST_DATATYPE_FLOAT:
       
  2232         case MOJOSHADER_AST_DATATYPE_FLOAT_SNORM:
       
  2233         case MOJOSHADER_AST_DATATYPE_FLOAT_UNORM:
       
  2234         case MOJOSHADER_AST_DATATYPE_HALF:
       
  2235         case MOJOSHADER_AST_DATATYPE_DOUBLE:
       
  2236             return 1;
       
  2237         default:
       
  2238             return 0;
       
  2239     } // switch
       
  2240 } // is_scalar_datatype
       
  2241 
  2224 static const MOJOSHADER_astDataType *type_check_ast(Context *ctx, void *_ast);
  2242 static const MOJOSHADER_astDataType *type_check_ast(Context *ctx, void *_ast);
  2225 
  2243 
  2226 // !!! FIXME: this function sucks.
  2244 // !!! FIXME: this function sucks.
  2227 static const MOJOSHADER_astDataType *match_func_to_call(Context *ctx,
  2245 static const MOJOSHADER_astDataType *match_func_to_call(Context *ctx,
  2228                                     MOJOSHADER_astExpressionCallFunction *ast)
  2246                                     MOJOSHADER_astExpressionCallFunction *ast)
  2241         type_check_ast(ctx, args->argument);
  2259         type_check_ast(ctx, args->argument);
  2242         args = args->next;
  2260         args = args->next;
  2243     } // while;
  2261     } // while;
  2244 
  2262 
  2245     // we do some tapdancing to handle function overloading here.
  2263     // we do some tapdancing to handle function overloading here.
       
  2264     int match = 0;
  2246     while (hash_iter(ctx->variables.hash, sym, &value, &iter))
  2265     while (hash_iter(ctx->variables.hash, sym, &value, &iter))
  2247     {
  2266     {
  2248         SymbolScope *item = (SymbolScope *) value;
  2267         SymbolScope *item = (SymbolScope *) value;
  2249         const MOJOSHADER_astDataType *dt = item->datatype;
  2268         const MOJOSHADER_astDataType *dt = item->datatype;
  2250         dt = reduce_datatype(ctx, dt);
  2269         dt = reduce_datatype(ctx, dt);
  2251         // there's a locally-scoped symbol with this name? It takes precedence.
  2270         // there's a locally-scoped symbol with this name? It takes precedence.
  2252         if (dt->type != MOJOSHADER_AST_DATATYPE_FUNCTION)
  2271         if (dt->type != MOJOSHADER_AST_DATATYPE_FUNCTION)
  2253             return dt;
  2272             return dt;
  2254 
  2273 
  2255         // !!! FIXME: this needs to find functions that implicit casts would catch:
  2274         // The matching rules for HLSL function overloading, as far as I can
  2256         //          void fn(int x);
  2275         //  tell from experimenting with Microsoft's compiler, seem to be this:
  2257         //          needs to match:
  2276         //
  2258         //          short q = 2; fn(q);
  2277         // - All parameters of a function must match what the caller specified.
       
  2278         // - Scalars can be promoted to vectors to make a parameter match.
       
  2279         // - Scalars can promote to other scalars (short to int, etc).
       
  2280         // - Vectors may NOT be promoted (a float2 can't extend to a float4).
       
  2281         // - If more than one function matches after this (all params that
       
  2282         //   would be different between two functions are passed scalars)
       
  2283         //   then fail().
       
  2284 
  2259         const MOJOSHADER_astDataTypeFunction *dtfn = (MOJOSHADER_astDataTypeFunction *) dt;
  2285         const MOJOSHADER_astDataTypeFunction *dtfn = (MOJOSHADER_astDataTypeFunction *) dt;
  2260         int match = 1;
  2286         int this_match = 1;
  2261         int i;
  2287         int i;
  2262 
  2288 
  2263         if (argcount != dtfn->num_params)  // !!! FIXME: default args.
  2289         if (argcount != dtfn->num_params)  // !!! FIXME: default args.
  2264             match = 0;
  2290             this_match = 0;
  2265         else
  2291         else
  2266         {
  2292         {
  2267             args = ast->args;
  2293             args = ast->args;
  2268             for (i = 0; i < argcount; i++)
  2294             for (i = 0; i < argcount; i++)
  2269             {
  2295             {
  2270                 assert(args != NULL);
  2296                 assert(args != NULL);
  2271                 dt = args->argument->datatype;
  2297                 dt = args->argument->datatype;
  2272                 args = args->next;
  2298                 args = args->next;
  2273 
  2299 
  2274                 if (!datatypes_match(dt, dtfn->params[i]))
  2300                 if (datatypes_match(dt, dtfn->params[i]))
       
  2301                     continue;  // so far, so good!
       
  2302 
       
  2303                 // we let this go for now if we passed a scalar.
       
  2304                 //  !!! FIXME: should warn when downcasting.
       
  2305                 if (!is_scalar_datatype(reduce_datatype(ctx, dt)))
  2275                 {
  2306                 {
  2276                     match = 0;  // can't be perfect match.
  2307                     this_match = 0;  // can't be perfect match.
  2277                     break;
  2308                     break;
  2278                 } // if
  2309                 } // if
  2279             } // for
  2310             } // for
  2280 
  2311 
  2281             if (args != NULL)
  2312             if (args != NULL)
  2282                 match = 0;  // too many arguments supplied. No match.
  2313                 this_match = 0;  // too many arguments supplied. No match.
  2283         } // else
  2314         } // else
  2284 
  2315 
  2285         if (match)
  2316         if (this_match)
  2286         {
  2317         {
  2287             best = item;
  2318             if (match++ == 0)
  2288             break;
  2319                 best = item;
       
  2320             else
       
  2321             {
       
  2322                 if (match++ == 1)
       
  2323                     failf(ctx, "Ambiguous function call to '%s'", sym);
       
  2324                 // !!! FIXME: list each possible function in a fail() here.
       
  2325             } // else
  2289         } // if
  2326         } // if
  2290     } // while
  2327     } // while
  2291 
  2328 
  2292     if (best == NULL)
  2329     if (best == NULL)
  2293         failf(ctx, "No matching function named '%s'", sym);
  2330         failf(ctx, "No matching function named '%s'", sym);
  2300     return ident->datatype;
  2337     return ident->datatype;
  2301 } // match_func_to_call
  2338 } // match_func_to_call
  2302 
  2339 
  2303 
  2340 
  2304 static const MOJOSHADER_astDataType *vectype_from_base(Context *ctx,
  2341 static const MOJOSHADER_astDataType *vectype_from_base(Context *ctx,
  2305                                             const MOJOSHADER_astDataTypeType base,
  2342                                             const MOJOSHADER_astDataType *base,
  2306                                             const int len)
  2343                                             const int len)
  2307 {
  2344 {
  2308     assert(len > 0);
  2345     assert(len > 0);
  2309     assert(len <= 4);
  2346     assert(len <= 4);
  2310 
  2347 
       
  2348     if (len == 1)  // return "float" and not "float1"
       
  2349         return base;
       
  2350 
  2311     const char *typestr = NULL;
  2351     const char *typestr = NULL;
  2312     switch (base)
  2352     switch (base->type)
  2313     {
  2353     {
  2314         case MOJOSHADER_AST_DATATYPE_BOOL: typestr = "bool"; break;
  2354         case MOJOSHADER_AST_DATATYPE_BOOL: typestr = "bool"; break;
  2315         case MOJOSHADER_AST_DATATYPE_INT: typestr = "int"; break;
  2355         case MOJOSHADER_AST_DATATYPE_INT: typestr = "int"; break;
  2316         case MOJOSHADER_AST_DATATYPE_UINT: typestr = "uint"; break;
  2356         case MOJOSHADER_AST_DATATYPE_UINT: typestr = "uint"; break;
  2317         case MOJOSHADER_AST_DATATYPE_HALF: typestr = "half"; break;
  2357         case MOJOSHADER_AST_DATATYPE_HALF: typestr = "half"; break;
  2376 
  2416 
  2377             datatype = reduce_datatype(ctx, datatype);
  2417             datatype = reduce_datatype(ctx, datatype);
  2378             if (datatype->type == MOJOSHADER_AST_DATATYPE_VECTOR)
  2418             if (datatype->type == MOJOSHADER_AST_DATATYPE_VECTOR)
  2379                 ast->binary.datatype = datatype->vector.base;
  2419                 ast->binary.datatype = datatype->vector.base;
  2380             else if (datatype->type == MOJOSHADER_AST_DATATYPE_MATRIX)
  2420             else if (datatype->type == MOJOSHADER_AST_DATATYPE_MATRIX)
  2381                 ast->binary.datatype = vectype_from_base(ctx, datatype->matrix.base->type, datatype->matrix.columns);  // !!! FIXME: rows?
  2421                 ast->binary.datatype = vectype_from_base(ctx, datatype->matrix.base, datatype->matrix.columns);  // !!! FIXME: rows?
  2382             else
  2422             else
  2383             {
  2423             {
  2384                 require_array_datatype(ctx, datatype);
  2424                 require_array_datatype(ctx, datatype);
  2385                 ast->binary.datatype = array_element_datatype(ctx, datatype);
  2425                 ast->binary.datatype = array_element_datatype(ctx, datatype);
  2386             } // else
  2426             } // else
  2406                     member = ast->derefstruct.member = sane_swiz;
  2446                     member = ast->derefstruct.member = sane_swiz;
  2407                 } // if
  2447                 } // if
  2408 
  2448 
  2409                 const int swizlen = (int) strlen(member);
  2449                 const int swizlen = (int) strlen(member);
  2410                 if (swizlen != veclen)
  2450                 if (swizlen != veclen)
  2411                     datatype = vectype_from_base(ctx, reduced->vector.base->type, swizlen);
  2451                     datatype = vectype_from_base(ctx, reduced->vector.base, swizlen);
  2412 
  2452 
  2413                 ast->derefstruct.datatype = datatype;
  2453                 ast->derefstruct.datatype = datatype;
  2414                 return ast->derefstruct.datatype;
  2454                 return ast->derefstruct.datatype;
  2415             } // if
  2455             } // if
  2416 
  2456 
  2649                 reduced = reduce_datatype(ctx, datatype2);
  2689                 reduced = reduce_datatype(ctx, datatype2);
  2650                 if (reduced->type == MOJOSHADER_AST_DATATYPE_VECTOR)
  2690                 if (reduced->type == MOJOSHADER_AST_DATATYPE_VECTOR)
  2651                 {
  2691                 {
  2652                     // make sure things like float4(half3(1,2,3),1) convert that half3 to float3.
  2692                     // make sure things like float4(half3(1,2,3),1) convert that half3 to float3.
  2653                     const int count = reduced->vector.elements;
  2693                     const int count = reduced->vector.elements;
  2654                     datatype3 = vectype_from_base(ctx, base_dt->type, count);
  2694                     datatype3 = vectype_from_base(ctx, base_dt, count);
  2655                     add_type_coercion(ctx, NULL, datatype3, &arg->argument, datatype2);
  2695                     add_type_coercion(ctx, NULL, datatype3, &arg->argument, datatype2);
  2656                     i += count - 1;
  2696                     i += count - 1;
  2657                 } // else
  2697                 } // else
  2658                 else
  2698                 else
  2659                 {
  2699                 {