mojoshader_compiler.c
changeset 990 a6f58e240fe6
parent 989 b3dacb4c2804
child 991 8999b4b9eaa6
equal deleted inserted replaced
989:b3dacb4c2804 990:a6f58e240fe6
  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 int datatype_size(const MOJOSHADER_astDataType *dt)
       
  2225 {
       
  2226     switch (dt->type)
       
  2227     {
       
  2228         case MOJOSHADER_AST_DATATYPE_BOOL: return 1;
       
  2229         case MOJOSHADER_AST_DATATYPE_INT: return 4;
       
  2230         case MOJOSHADER_AST_DATATYPE_UINT: return 4;
       
  2231         case MOJOSHADER_AST_DATATYPE_FLOAT: return 4;
       
  2232         case MOJOSHADER_AST_DATATYPE_FLOAT_SNORM: return 4;
       
  2233         case MOJOSHADER_AST_DATATYPE_FLOAT_UNORM: return 4;
       
  2234         case MOJOSHADER_AST_DATATYPE_HALF: return 2;
       
  2235         case MOJOSHADER_AST_DATATYPE_DOUBLE: return 8;
       
  2236             return 1;
       
  2237         default:
       
  2238             assert(0 && "Maybe should have used reduce_datatype()?");
       
  2239             return 0;
       
  2240     } // switch
       
  2241 } // datatype_size
       
  2242 
  2224 static inline int is_scalar_datatype(const MOJOSHADER_astDataType *dt)
  2243 static inline int is_scalar_datatype(const MOJOSHADER_astDataType *dt)
  2225 {
  2244 {
  2226     switch (dt->type)
  2245     switch (dt->type)
  2227     {
  2246     {
  2228         case MOJOSHADER_AST_DATATYPE_BOOL:
  2247         case MOJOSHADER_AST_DATATYPE_BOOL:
  2237         default:
  2256         default:
  2238             return 0;
  2257             return 0;
  2239     } // switch
  2258     } // switch
  2240 } // is_scalar_datatype
  2259 } // is_scalar_datatype
  2241 
  2260 
       
  2261 static int compatible_arg_datatype(Context *ctx,
       
  2262                                    const MOJOSHADER_astDataType *arg,
       
  2263                                    const MOJOSHADER_astDataType *param)
       
  2264 {
       
  2265     // The matching rules for HLSL function overloading, as far as I can
       
  2266     //  tell from experimenting with Microsoft's compiler, seem to be this:
       
  2267     //
       
  2268     // - All parameters of a function must match what the caller specified
       
  2269     //   after possible type promotion via the following rules.
       
  2270     // - Scalars can be promoted to vectors to make a parameter match.
       
  2271     // - Scalars can promote to other scalars (short to int, etc).
       
  2272     // - Vectors may NOT be promoted (a float2 can't extend to a float4).
       
  2273     // - Vectors with the same elements can promote (a half2 can become a float2...I _think_ it can't downcast here.).
       
  2274     // - If more than one function matches after this (all params that
       
  2275     //   would be different between two functions are passed scalars)
       
  2276     //   then fail().
       
  2277 
       
  2278     if (datatypes_match(arg, param))
       
  2279         return 1;  // that was easy.
       
  2280 
       
  2281     arg = reduce_datatype(ctx, arg);
       
  2282     param = reduce_datatype(ctx, param);
       
  2283 
       
  2284     // we let this go for now if we passed a scalar.
       
  2285     //  !!! FIXME: should warn when downcasting.
       
  2286     //  !!! FIXME: also, being a bit more picky would be good.
       
  2287     if (is_scalar_datatype(arg))
       
  2288         return 1;
       
  2289 
       
  2290     else if (arg->type == param->type)
       
  2291     {
       
  2292         if (arg->type == MOJOSHADER_AST_DATATYPE_VECTOR)
       
  2293         {
       
  2294             if (arg->vector.elements == param->vector.elements)
       
  2295                 return datatype_size(arg->vector.base) <= datatype_size(param->vector.base);
       
  2296         } // if
       
  2297         else if (arg->type == MOJOSHADER_AST_DATATYPE_MATRIX)
       
  2298         {
       
  2299             if ((arg->matrix.rows == param->matrix.rows) &&
       
  2300                 (arg->matrix.columns == param->matrix.columns))
       
  2301                 return datatype_size(arg->matrix.base) <= datatype_size(param->matrix.base);
       
  2302         } // if
       
  2303     } // if
       
  2304 
       
  2305     return 0;
       
  2306 } // compatible_arg_datatype
       
  2307 
       
  2308 
  2242 static const MOJOSHADER_astDataType *type_check_ast(Context *ctx, void *_ast);
  2309 static const MOJOSHADER_astDataType *type_check_ast(Context *ctx, void *_ast);
  2243 
  2310 
  2244 // !!! FIXME: this function sucks.
  2311 // !!! FIXME: this function sucks.
  2245 static const MOJOSHADER_astDataType *match_func_to_call(Context *ctx,
  2312 static const MOJOSHADER_astDataType *match_func_to_call(Context *ctx,
  2246                                     MOJOSHADER_astExpressionCallFunction *ast)
  2313                                     MOJOSHADER_astExpressionCallFunction *ast)
  2268         const MOJOSHADER_astDataType *dt = item->datatype;
  2335         const MOJOSHADER_astDataType *dt = item->datatype;
  2269         dt = reduce_datatype(ctx, dt);
  2336         dt = reduce_datatype(ctx, dt);
  2270         // there's a locally-scoped symbol with this name? It takes precedence.
  2337         // there's a locally-scoped symbol with this name? It takes precedence.
  2271         if (dt->type != MOJOSHADER_AST_DATATYPE_FUNCTION)
  2338         if (dt->type != MOJOSHADER_AST_DATATYPE_FUNCTION)
  2272             return dt;
  2339             return dt;
  2273 
       
  2274         // The matching rules for HLSL function overloading, as far as I can
       
  2275         //  tell from experimenting with Microsoft's compiler, seem to be this:
       
  2276         //
       
  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 
  2340 
  2285         const MOJOSHADER_astDataTypeFunction *dtfn = (MOJOSHADER_astDataTypeFunction *) dt;
  2341         const MOJOSHADER_astDataTypeFunction *dtfn = (MOJOSHADER_astDataTypeFunction *) dt;
  2286         int this_match = 1;
  2342         int this_match = 1;
  2287         int i;
  2343         int i;
  2288 
  2344 
  2294             for (i = 0; i < argcount; i++)
  2350             for (i = 0; i < argcount; i++)
  2295             {
  2351             {
  2296                 assert(args != NULL);
  2352                 assert(args != NULL);
  2297                 dt = args->argument->datatype;
  2353                 dt = args->argument->datatype;
  2298                 args = args->next;
  2354                 args = args->next;
  2299 
  2355                 if (!compatible_arg_datatype(ctx, 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)))
       
  2306                 {
  2356                 {
  2307                     this_match = 0;  // can't be perfect match.
  2357                     this_match = 0;  // can't be perfect match.
  2308                     break;
  2358                     break;
  2309                 } // if
  2359                 } // if
  2310             } // for
  2360             } // for