bool ValidateLimitations::validateIndexing(TIntermBinary* node)
{
    ASSERT((node->getOp() == EOpIndexDirect) ||
           (node->getOp() == EOpIndexIndirect));

    bool valid = true;
    TIntermTyped* index = node->getRight();
    // The index expression must have integral type.
    if (!index->isScalar() || (index->getBasicType() != EbtInt)) {
        error(index->getLine(),
              "Index expression must have integral type",
              index->getCompleteString().c_str());
        valid = false;
    }
    // The index expession must be a constant-index-expression unless
    // the operand is a uniform in a vertex shader.
    TIntermTyped* operand = node->getLeft();
    bool skip = (mShaderType == SH_VERTEX_SHADER) &&
                (operand->getQualifier() == EvqUniform);
    if (!skip && !isConstIndexExpr(index)) {
        error(index->getLine(), "Index expression must be constant", "[]");
        valid = false;
    }
    return valid;
}
Exemplo n.º 2
0
void TIntermAggregate::setBuiltInFunctionPrecision()
{
    // All built-ins returning bool should be handled as ops, not functions.
    ASSERT(getBasicType() != EbtBool);

    TPrecision precision = EbpUndefined;
    TIntermSequence::iterator childIter = mSequence.begin();
    while (childIter != mSequence.end())
    {
        TIntermTyped *typed = (*childIter)->getAsTyped();
        // ESSL spec section 8: texture functions get their precision from the sampler.
        if (typed && IsSampler(typed->getBasicType()))
        {
            precision = typed->getPrecision();
            break;
        }
        ++childIter;
    }
    // ESSL 3.0 spec section 8: textureSize always gets highp precision.
    // All other functions that take a sampler are assumed to be texture functions.
    if (mName.find("textureSize") == 0)
        mType.setPrecision(EbpHigh);
    else
        mType.setPrecision(precision);
}
Exemplo n.º 3
0
bool IntermNodePatternMatcher::match(TIntermDeclaration *node)
{
    if ((mMask & kMultiDeclaration) != 0)
    {
        if (node->getSequence()->size() > 1)
        {
            return true;
        }
    }
    if ((mMask & kArrayDeclaration) != 0)
    {
        if (node->getSequence()->front()->getAsTyped()->getType().isStructureContainingArrays())
        {
            return true;
        }
        // Need to check from all declarators whether they are arrays since that may vary between
        // declarators.
        for (TIntermNode *declarator : *node->getSequence())
        {
            if (declarator->getAsTyped()->isArray())
            {
                return true;
            }
        }
    }
    if ((mMask & kNamelessStructDeclaration) != 0)
    {
        TIntermTyped *declarator = node->getSequence()->front()->getAsTyped();
        if (declarator->getBasicType() == EbtStruct &&
            declarator->getType().getStruct()->name() == "")
        {
            return true;
        }
    }
    return false;
}
Exemplo n.º 4
0
//
// Make sure there is enough data provided to the constructor to build
// something of the type of the constructor.  Also returns the type of
// the constructor.
//
// Returns true if there was an error in construction.
//
bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
{
    *type = function.getReturnType();

    bool constructingMatrix = false;
    switch(op) {
    case EOpConstructMat2:
    case EOpConstructMat3:
    case EOpConstructMat4:
        constructingMatrix = true;
        break;
    default: 
        break;
    }

    //
    // Note: It's okay to have too many components available, but not okay to have unused
    // arguments.  'full' will go to true when enough args have been seen.  If we loop
    // again, there is an extra argument, so 'overfull' will become true.
    //

    int size = 0;
    bool constType = true;
    bool full = false;
    bool overFull = false;
    bool matrixInMatrix = false;
    bool arrayArg = false;
    for (int i = 0; i < function.getParamCount(); ++i) {
        const TParameter& param = function.getParam(i);
        size += param.type->getObjectSize();
        
        if (constructingMatrix && param.type->isMatrix())
            matrixInMatrix = true;
        if (full)
            overFull = true;
        if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
            full = true;
        if (param.type->getQualifier() != EvqConst)
            constType = false;
        if (param.type->isArray())
            arrayArg = true;
    }
    
    if (constType)
        type->setQualifier(EvqConst);

    if (type->isArray() && type->getArraySize() != function.getParamCount()) {
        error(line, "array constructor needs one argument per array element", "constructor", "");
        return true;
    }

    if (arrayArg && op != EOpConstructStruct) {
        error(line, "constructing from a non-dereferenced array", "constructor", "");
        return true;
    }

    if (matrixInMatrix && !type->isArray()) {
        if (function.getParamCount() != 1) {
          error(line, "constructing matrix from matrix can only take one argument", "constructor", "");
          return true;
        }
    }

    if (overFull) {
        error(line, "too many arguments", "constructor", "");
        return true;
    }
    
    if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->size()) != function.getParamCount()) {
        error(line, "Number of constructor parameters does not match the number of structure fields", "constructor", "");
        return true;
    }

    if (!type->isMatrix() || !matrixInMatrix) {
        if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) ||
            (op == EOpConstructStruct && size < type->getObjectSize())) {
            error(line, "not enough data provided for construction", "constructor", "");
            return true;
        }
    }

    TIntermTyped *typed = node ? node->getAsTyped() : 0;
    if (typed == 0) {
        error(line, "constructor argument does not have a type", "constructor", "");
        return true;
    }
    if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) {
        error(line, "cannot convert a sampler", "constructor", "");
        return true;
    }
    if (typed->getBasicType() == EbtVoid) {
        error(line, "cannot convert a void", "constructor", "");
        return true;
    }

    return false;
}
Exemplo n.º 5
0
bool TSamplerTraverser::traverseAggregate( bool preVisit, TIntermAggregate *node, TIntermTraverser *it)
{
   TSamplerTraverser* sit = static_cast<TSamplerTraverser*>(it);
   TInfoSink &infoSink = sit->infoSink;

   if (sit->abort)
      return false;

   if (! (sit->typing) )
   {
      switch (node->getOp())
      {
      
      case EOpFunction:
         // Store the current function name to use to setup the parameters
         sit->currentFunction = node->getName().c_str(); 
         break;

      case EOpParameters:
         // Store the parameters to the function in the map
         sit->functionMap[sit->currentFunction.c_str()] = &(node->getSequence());
         break;

      case EOpFunctionCall:
         {
            // This is a bit tricky.  Find the function in the map.  Loop over the parameters
            // and see if the parameters have been marked as a typed sampler.  If so, propagate
            // the sampler type to the caller
            if ( sit->functionMap.find ( node->getName().c_str() ) != sit->functionMap.end() )
            {
               // Get the sequence of function parameters
               TIntermSequence *funcSequence = sit->functionMap[node->getName().c_str()];
               
               // Get the sequence of parameters being passed to function
               TIntermSequence &sequence = node->getSequence();

               // Grab iterators to both sequences
               TIntermSequence::iterator it = sequence.begin();
               TIntermSequence::iterator funcIt = funcSequence->begin();

               assert ( sequence.size() == funcSequence->size() );
               if ( sequence.size() == funcSequence->size() )
               {
                  while ( it != sequence.end() )
                  {
                     TIntermSymbol *sym = (*it)->getAsSymbolNode();
                     TIntermSymbol *funcSym = (*funcIt)->getAsSymbolNode();
                     
                     if ( sym != NULL && funcSym != NULL)
                     {
                        // If the parameter is generic, and the sampler to which
                        // it is being passed has been marked, propogate its sampler
                        // type to the caller.
                        if ( sym->getBasicType() == EbtSamplerGeneric &&
                             funcSym->getBasicType() != EbtSamplerGeneric )
                        {
                           sit->typeSampler ( sym, funcSym->getBasicType() );
                        }
                     }
                     it++;
                     funcIt++;
                  }
               }
            }
         }
         break;

         //HLSL texture functions
      case EOpTex1D:
      case EOpTex1DProj:
      case EOpTex1DLod:
      case EOpTex1DBias:
      case EOpTex1DGrad:
         {
            TIntermSequence &sequence = node->getSequence();
            assert( sequence.size());
            TIntermTyped *sampArg = sequence[0]->getAsTyped();
            if ( sampArg)
            {
               if (sampArg->getBasicType() == EbtSamplerGeneric)
               {
                  //type the sampler
                  sit->typeSampler( sampArg, EbtSampler1D);
               }
               else if (sampArg->getBasicType() != EbtSampler1D)
               {
                  //We have a sampler mismatch error
                  infoSink.info << "Error: " << node->getLine() << ": Sampler type mismatch, likely using a generic sampler as two types\n";
               }
            }
            else
            {
               assert(0);
            }

         }
         // We need to continue the traverse here, because the calls could be nested 
         break;


      case EOpTex2D:
      case EOpTex2DProj:
      case EOpTex2DLod:
      case EOpTex2DBias:
      case EOpTex2DGrad:
         {
            TIntermSequence &sequence = node->getSequence();
            assert( sequence.size());
            TIntermTyped *sampArg = sequence[0]->getAsTyped();
            if ( sampArg)
            {
               if (sampArg->getBasicType() == EbtSamplerGeneric)
               {
                  //type the sampler
                  sit->typeSampler( sampArg, EbtSampler2D);
               }
               else if (sampArg->getBasicType() != EbtSampler2D)
               {
                  //We have a sampler mismatch error
                  infoSink.info << "Error: " << node->getLine() << ": Sampler type mismatch, likely using a generic sampler as two types\n";
               }
            }
            else
            {
               assert(0);
            }

         }
         // We need to continue the traverse here, because the calls could be nested 
         break;

	  case EOpTexRect:
	  case EOpTexRectProj:
		  {
			  TIntermSequence &sequence = node->getSequence();
			  assert( sequence.size());
			  TIntermTyped *sampArg = sequence[0]->getAsTyped();
			  if ( sampArg)
			  {
				  if (sampArg->getBasicType() == EbtSamplerGeneric)
				  {
					  //type the sampler
					  sit->typeSampler( sampArg, EbtSamplerRect);
				  }
				  else if (sampArg->getBasicType() != EbtSamplerRect)
				  {
					  //We have a sampler mismatch error
					  infoSink.info << "Error: " << node->getLine() << ": Sampler type mismatch, likely using a generic sampler as two types\n";
				  }
			  }
			  else
			  {
				  assert(0);
			  }
			  
		  }
		  // We need to continue the traverse here, because the calls could be nested 
		  break;
			  
			  
      case EOpTex3D:
      case EOpTex3DProj:
      case EOpTex3DLod:
      case EOpTex3DBias:
      case EOpTex3DGrad:
         {
            TIntermSequence &sequence = node->getSequence();
            assert( sequence.size());
            TIntermTyped *sampArg = sequence[0]->getAsTyped();
            if ( sampArg)
            {
               if (sampArg->getBasicType() == EbtSamplerGeneric)
               {
                  //type the sampler
                  sit->typeSampler( sampArg, EbtSampler3D);
               }
               else if (sampArg->getBasicType() != EbtSampler3D)
               {
                  //We have a sampler mismatch error
                  infoSink.info << "Error: " << node->getLine() << ": Sampler type mismatch, likely using a generic sampler as two types\n";
               }
            }
            else
            {
               assert(0);
            }

         }
         // We need to continue the traverse here, because the calls could be nested 
         break;

      case EOpTexCube:
      case EOpTexCubeProj:
      case EOpTexCubeLod:
      case EOpTexCubeBias:
      case EOpTexCubeGrad:
         {
            TIntermSequence &sequence = node->getSequence();
            assert( sequence.size());
            TIntermTyped *sampArg = sequence[0]->getAsTyped();
            if ( sampArg)
            {
               if (sampArg->getBasicType() == EbtSamplerGeneric)
               {
                  //type the sampler
                  sit->typeSampler( sampArg, EbtSamplerCube);
               }
               else if (sampArg->getBasicType() != EbtSamplerCube)
               {
                  //We have a sampler mismatch error
                  infoSink.info << "Error: " << node->getLine() << ": Sampler type mismatch, likely using a generic sampler as two types\n";
               }
            }
            else
            {
               assert(0);
            }

         }
         // We need to continue the traverse here, because the calls could be nested 
         break;

      default: 
         break;
      }
   }


   return !(sit->abort);
}