TIntermTyped* ir_add_vector_swizzle(TVectorFields& fields, TIntermTyped* arg, TSourceLoc lineDot, TSourceLoc lineIndex)
{	
	// swizzle on a constant -> fold it
	if (arg->getType().getQualifier() == EvqConst)
	{
		TIntermTyped* res = ir_add_const_vector_swizzle(fields, arg, lineIndex);
		if (res)
			return res;
	}
		
	TIntermTyped* res = NULL;
	if (fields.num == 1)
	{
		TIntermConstant* index = ir_add_constant(TType(EbtInt, EbpUndefined, EvqConst), lineIndex);
		index->setValue(fields.offsets[0]);
		res = ir_add_index(EOpIndexDirect, arg, index, lineDot);
		res->setType(TType(arg->getBasicType(), arg->getPrecision()));
	}
	else
	{
		TIntermTyped* index = ir_add_swizzle(fields, lineIndex);
		res = ir_add_index(EOpVectorSwizzle, arg, index, lineDot);
		res->setType(TType(arg->getBasicType(), arg->getPrecision(), EvqTemporary, 1, fields.num));
	}
	return res;
}
Example #2
0
//
// See if this qualifier can be an array.
//
// Returns true if there is an error.
//
bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type)
{
    if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConst)) {
        error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str(), "");
        return true;
    }

    return false;
}
Example #3
0
void TCompiler::initializeGLPosition(TIntermNode* root)
{
    InitializeVariables::InitVariableInfoList variables;
    InitializeVariables::InitVariableInfo var(
        "gl_Position", TType(EbtFloat, EbpUndefined, EvqPosition, 4));
    variables.push_back(var);
    InitializeVariables initializer(variables);
    root->traverse(&initializer);
}
Example #4
0
//
// See if this type can be an array.
//
// Returns true if there is an error.
//
bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type)
{
    //
    // Can the type be an array?
    //
    if (type.array) {
        error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str(), "");
        return true;
    }

    return false;
}
Example #5
0
//
// See if this qualifier can be an array.
//
// Returns true if there is an error.
//
bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type)
{
    if (type.qualifier == EvqAttribute) {
        error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str(), "");
        return true;
    }

    if (type.qualifier == EvqConst && extensionErrorCheck(line, "GL_3DL_array_objects"))
        return true;

    return false;
}
Example #6
0
// The function_call identifier was already recognized, and passed in as idToken.
//
// function_call
//      : [idToken] arguments
//
bool HlslGrammar::acceptFunctionCall(HlslToken idToken, TIntermTyped*& node)
{
    // arguments
    TFunction* function = new TFunction(idToken.string, TType(EbtVoid));
    TIntermTyped* arguments = nullptr;
    if (! acceptArguments(function, arguments))
        return false;

    node = parseContext.handleFunctionCall(idToken.loc, function, arguments);

    return true;
}
bool TIntermSelection::promoteTernary(TInfoSink& infoSink)
{
	if (!condition->isVector())
		return true;
	
	int size = condition->getRowsCount();
	TIntermTyped* trueb = trueBlock->getAsTyped();
	TIntermTyped* falseb = falseBlock->getAsTyped();
	if (!trueb || !falseb)
		return false;
	
	if (trueb->getRowsCount() == size && falseb->getRowsCount() == size)
		return true;
	
	// Base assumption: just make the type a float vector
	TPrecision higherPrecision = GetHigherPrecision(trueb->getPrecision(), falseb->getPrecision());
	setType(TType(EbtFloat, higherPrecision, EvqTemporary, 1, size, condition->isMatrix()));
	
	TOperator convert = EOpNull;	
	{
		convert = TOperator( EOpConstructVec2 + size - 2);
		TIntermAggregate *node = new TIntermAggregate(convert);
		node->setLine(trueb->getLine());
		node->setType(TType(condition->getBasicType(), higherPrecision, trueb->getQualifier() == EvqConst ? EvqConst : EvqTemporary, 1, size, condition->isMatrix()));
		node->getNodes().push_back(trueb);
		trueBlock = node;
	}
	{
		convert = TOperator( EOpConstructVec2 + size - 2);
		TIntermAggregate *node = new TIntermAggregate(convert);
		node->setLine(falseb->getLine());
		node->setType(TType(condition->getBasicType(), higherPrecision, falseb->getQualifier() == EvqConst ? EvqConst : EvqTemporary, 1, size, condition->isMatrix()));
		node->getNodes().push_back(falseb);
		falseBlock = node;
	}
	
	return true;
}
// For "if" test nodes.  There are three children; a condition,
// a true path, and a false path.  The two paths are in the
// nodePair.
TIntermNode* ir_add_selection(TIntermTyped* cond, TIntermNodePair nodePair, TSourceLoc line, TInfoSink& infoSink)
{   
   // Convert float/int to bool
   if ( cond->getBasicType() != EbtBool)
   {
      cond = ir_add_conversion (EOpConstructBool,
                             TType (EbtBool, cond->getPrecision(), cond->getQualifier(), cond->getColsCount(), cond->getRowsCount(), cond->isMatrix(), cond->isArray()),
                             cond, infoSink);
   }

   TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
   node->setLine(line);

   return node;
}
TIntermTyped* ir_add_swizzle(TVectorFields& fields, TSourceLoc line)
{
	TIntermAggregate* node = new TIntermAggregate(EOpSequence);

	node->setLine(line);
	TNodeArray& nodes = node->getNodes();

	for (int i = 0; i < fields.num; i++)
	{
		TIntermConstant* constant = ir_add_constant(TType(EbtInt, EbpUndefined, EvqConst), line);
		constant->setValue(fields.offsets[i]);
		nodes.push_back(constant);
	}

	return node;
}
Example #10
0
//
// Make a constant vector node or constant scalar node, representing a given 
// constant vector and constant swizzle into it.
//
TIntermTyped* TIntermediate::foldSwizzle(TIntermTyped* node, TVectorFields& fields, const TSourceLoc& loc)
{
    const TConstUnionArray& unionArray = node->getAsConstantUnion()->getConstArray();
    TConstUnionArray constArray(fields.num);

    for (int i = 0; i < fields.num; i++)
        constArray[i] = unionArray[fields.offsets[i]];

    TIntermTyped* result = addConstantUnion(constArray, node->getType(), loc);

    if (result == 0)
        result = node;
    else
        result->setType(TType(node->getBasicType(), EvqConst, fields.num));

    return result;
}
Example #11
0
//
// Do semantic checking for a variable declaration that has no initializer,
// and update the symbol table.
//
// Returns true if there was an error.
//
bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type)
{
    if (reservedErrorCheck(line, identifier))
        recover();

    TVariable* variable = new TVariable(&identifier, TType(type));

    if (! symbolTable.insert(*variable)) {
        error(line, "redefinition", variable->getName().c_str(), "");
        delete variable;
        return true;
    }

    if (voidErrorCheck(line, identifier, type))
        return true;

    return false;
}
Example #12
0
// This function returns the tree representation for the vector field(s) being accessed from contant vector.
// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of 
// a constant matrix.
TIntermTyped* ir_add_const_vector_swizzle(const TVectorFields& fields, TIntermTyped* node, TSourceLoc line)
{
	TIntermConstant* constNode = node->getAsConstant();
	if (!constNode)
		return NULL;
	
	TIntermConstant* res = ir_add_constant(node->getType(), line);
	for (int i = 0; i < fields.num; ++i)
	{
		int index = fields.offsets[i];
		assert(index >= 0 && index < constNode->getCount());
		res->setValue(i, constNode->getValue (index));
	}
	
	res->setType(TType(node->getBasicType(), node->getPrecision(), EvqConst, fields.num));
	
	return res;
}
TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line)
{

    TIntermAggregate* node = new TIntermAggregate(EOpSequence);

    node->setLine(line);
    TIntermConstantUnion* constIntNode;
    TIntermSequence &sequenceVector = node->getSequence();
    ConstantUnion* unionArray;

    for (int i = 0; i < fields.num; i++) {
        unionArray = new ConstantUnion[1];
        unionArray->setIConst(fields.offsets[i]);
        constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
        sequenceVector.push_back(constIntNode);
    }

    return node;
}
Example #14
0
// For "if" test nodes.  There are three children; a condition,
// a true path, and a false path.  The two paths are in the
// nodePair.
TIntermNode* ir_add_selection(TIntermTyped* cond, TIntermNodePair nodePair, TSourceLoc line, TInfoSink& infoSink)
{   
   // Convert float/int to bool
   switch ( cond->getBasicType() )
   {
   case EbtFloat:
   case EbtInt:
      cond = ir_add_conversion (EOpConstructBool, 
                             TType (EbtBool, cond->getPrecision(), cond->getQualifier(), cond->getNominalSize(), cond->isMatrix(), cond->isArray()),
                             cond, infoSink);
      break;
   default:
      // Do nothing
      break;
   }

   TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
   node->setLine(line);

   return node;
}
Example #15
0
// For "?:" test nodes.  There are three children; a condition,
// a true path, and a false path.  The two paths are specified
// as separate parameters.
TIntermTyped* ir_add_selection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc line, TInfoSink& infoSink)
{
   bool bPromoteFromTrueBlockType = true;

   if (cond->getBasicType() != EbtBool)
   {
	   cond = ir_add_conversion (EOpConstructBool, 
		   TType (EbtBool, cond->getPrecision(), cond->getQualifier(), cond->getColsCount(), cond->getRowsCount(), cond->isMatrix(), cond->isArray()),
		   cond, infoSink);
   }

   // Choose which one to try to promote to based on which has more precision
   // By default, it will promote from the falseBlock type to the trueBlock type.  However,
   // what we want to do is promote to the type with the most precision of the two.  So here,
   // check whether the false block has more precision than the true block, and if so use
   // its type instead.
   if ( trueBlock->getBasicType() == EbtBool )
   {
      if ( falseBlock->getBasicType() == EbtInt ||
           falseBlock->getBasicType() == EbtFloat )
      {
         bPromoteFromTrueBlockType = false;
      }
   }
   else if ( trueBlock->getBasicType() == EbtInt )
   {
      if ( falseBlock->getBasicType() == EbtFloat )
      {
         bPromoteFromTrueBlockType = false;
      }
   }

   //
   // Get compatible types.
   //
   if ( bPromoteFromTrueBlockType )
   {
      TIntermTyped* child = ir_add_conversion(EOpSequence, trueBlock->getType(), falseBlock, infoSink);
      if (child)
         falseBlock = child;
      else
      {
         child = ir_add_conversion(EOpSequence, falseBlock->getType(), trueBlock, infoSink);
         if (child)
            trueBlock = child;
         else
            return 0;
      }
   }
   else
   {
      TIntermTyped* child = ir_add_conversion(EOpSequence, falseBlock->getType(), trueBlock, infoSink);
      if (child)
         trueBlock = child;
      else
      {
         child = ir_add_conversion(EOpSequence, trueBlock->getType(), falseBlock, infoSink);
         if (child)
            falseBlock = child;
         else
            return 0;
      }
   }

   //
   // Make a selection node.
   //
   TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
   node->setLine(line);

    if (!node->promoteTernary(infoSink))
        return 0;


   return node;
}
Example #16
0
 TType atomic_inc( TType * p ) { return TType(); }
Example #17
0
// Connect two nodes with a new parent that does a binary operation on the nodes.
TIntermTyped* ir_add_binary_math(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TParseContext& ctx)
{
	if (!left || !right)
		return 0;
	
	switch (op)
	{
	case EOpLessThan:
	case EOpGreaterThan:
	case EOpLessThanEqual:
	case EOpGreaterThanEqual:
		if (left->getType().isMatrix() || left->getType().isArray() || left->getType().getBasicType() == EbtStruct)
		{
			return 0;
		}
		break;
	case EOpLogicalOr:
	case EOpLogicalXor:
	case EOpLogicalAnd:
		if (left->getType().isMatrix() || left->getType().isArray())
			return 0;
		
		if ( left->getBasicType() != EbtBool )
		{
			if ( left->getType().getBasicType() != EbtInt && left->getType().getBasicType() != EbtFloat )
				return 0;
			else
			{
				// If the left is a float or int, convert to a bool.  This is the conversion that HLSL
				// does
				left = ir_add_conversion(EOpConstructBool, 
									 TType ( EbtBool, left->getPrecision(), left->getQualifier(),
											left->getColsCount(), left->getRowsCount(), left->isMatrix(), left->isArray()), 
									 left, ctx.infoSink);
				
				if ( left == 0 )
					return 0;
			}
			
		}
		
		if (right->getType().isMatrix() || right->getType().isArray() || right->getType().isVector())
			return 0;
		
		if ( right->getBasicType() != EbtBool )
		{
			if ( right->getType().getBasicType() != EbtInt && right->getType().getBasicType() != EbtFloat )
				return 0;
			else
			{
				// If the right is a float or int, convert to a bool.  This is the conversion that HLSL
				// does
				right = ir_add_conversion(EOpConstructBool, 
									  TType ( EbtBool, right->getPrecision(), right->getQualifier(),
											 right->getColsCount(), right->getRowsCount(), right->isMatrix(), right->isArray()), 
									  right, ctx.infoSink);
				
				if ( right == 0 )
					return 0;
			}
			
		}
		break;
	case EOpAdd:
	case EOpSub:
	case EOpDiv:
	case EOpMul:
	case EOpMod:
		{
			TBasicType ltype = left->getType().getBasicType();
			TBasicType rtype = right->getType().getBasicType();
			if (ltype == EbtStruct)
				return 0;
			
			// If left or right type is a bool, convert to float.
			bool leftToFloat = (ltype == EbtBool);
			bool rightToFloat = (rtype == EbtBool);
			// For modulus, if either is an integer, convert to float as well.
			if (op == EOpMod)
			{
				leftToFloat |= (ltype == EbtInt);
				rightToFloat |= (rtype == EbtInt);
			}
				
			if (leftToFloat)
			{
				left = ir_add_conversion (EOpConstructFloat, TType (EbtFloat, left->getPrecision(), left->getQualifier(), left->getColsCount(), left->getRowsCount(), left->isMatrix(), left->isArray()), left, ctx.infoSink);
				if (left == 0)
					return 0;
			}
			if (rightToFloat)
			{
				right = ir_add_conversion (EOpConstructFloat, TType (EbtFloat, right->getPrecision(), right->getQualifier(), right->getColsCount(), right->getRowsCount(), right->isMatrix(), right->isArray()), right, ctx.infoSink);
				if (right == 0)
					return 0;
			}
		}
		break;
	default:
		break;
	}
	
	// 
	// First try converting the children to compatible types.
	//
	
	if (!(left->getType().getStruct() && right->getType().getStruct()))
	{
		TIntermTyped* child = 0;
		bool useLeft = true; //default to using the left child as the type to promote to
		
		//need to always convert up
		if ( left->getType().getBasicType() != EbtFloat)
		{
			if ( right->getType().getBasicType() == EbtFloat)
			{
				useLeft = false;
			}
			else
			{
				if ( left->getType().getBasicType() != EbtInt)
				{
					if ( right->getType().getBasicType() == EbtInt)
						useLeft = false;
				}
			}
		}
		
		if (useLeft)
		{
			child = ir_add_conversion(op, left->getType(), right, ctx.infoSink);
			if (child)
				right = child;
			else
			{
				child = ir_add_conversion(op, right->getType(), left, ctx.infoSink);
				if (child)
					left = child;
				else
					return 0;
			}
		}
		else
		{
			child = ir_add_conversion(op, right->getType(), left, ctx.infoSink);
			if (child)
				left = child;
			else
			{
				child = ir_add_conversion(op, left->getType(), right, ctx.infoSink);
				if (child)
					right = child;
				else
					return 0;
			}
		}
		
	}
	else
	{
		if (left->getType() != right->getType())
			return 0;
	}
	
	
	//
	// Need a new node holding things together then.  Make
	// one and promote it to the right type.
	//
	TIntermBinary* node = new TIntermBinary(op);
	if (line.line == 0)
		line = right->getLine();
	node->setLine(line);
	
	node->setLeft(left);
	node->setRight(right);
	if (! node->promote(ctx))
		return 0;
	
	//
	// See if we can fold constants
	
	TIntermConstant* constA = left->getAsConstant();
	TIntermConstant* constB = right->getAsConstant();
	
	if (constA && constB)
	{
		TIntermConstant* FoldBinaryConstantExpression(TOperator op, TIntermConstant* nodeA, TIntermConstant* nodeB);
		TIntermConstant* res = FoldBinaryConstantExpression(node->getOp(), constA, constB);
		if (res)
		{
			delete node;
			return res;
		}
	}
	
	return node;
}
Example #18
0
// Add one node as the parent of another that it operates on.
TIntermTyped* ir_add_unary_math(TOperator op, TIntermNode* childNode, TSourceLoc line, TParseContext& ctx)
{
   TIntermUnary* node;
   TIntermTyped* child = childNode->getAsTyped();

   if (child == 0)
   {
      ctx.infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
      return 0;
   }

   switch (op)
   {
   case EOpLogicalNot:
      if (!child->isScalar())
         return 0;
      break;

   case EOpPostIncrement:
   case EOpPreIncrement:
   case EOpPostDecrement:
   case EOpPreDecrement:
   case EOpNegative:
      if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
         return 0;
   default: break;
   }

   //
   // Do we need to promote the operand?
   //
   // Note: Implicit promotions were removed from the language.
   //
   TBasicType newType = EbtVoid;
   switch (op)
   {
   case EOpConstructInt:   newType = EbtInt;   break;
   case EOpConstructBool:  newType = EbtBool;  break;
   case EOpConstructFloat: newType = EbtFloat; break;
   case EOpLogicalNot:     newType = EbtBool; break;
   default: break;
   }

   if (newType != EbtVoid)
   {
      child = ir_add_conversion(op, TType(newType, child->getPrecision(), EvqTemporary, child->getColsCount(), child->getRowsCount(), 
                                      child->isMatrix(), 
                                      child->isArray()),
                            child, ctx.infoSink);
      if (child == 0)
         return 0;
   }

   //
   // For constructors, we are now done, it's all in the conversion.
   //
   switch (op)
   {
   case EOpConstructInt:
   case EOpConstructBool:
   case EOpConstructFloat:
      return child;
   default: break;
   }

   TIntermConstant* childConst = child->getAsConstant();

   //
   // Make a new node for the operator.
   //
   node = new TIntermUnary(op);
   if (line.line == 0)
      line = child->getLine();
   node->setLine(line);
   node->setOperand(child);

   if (! node->promote(ctx))
      return 0;
	
	
	//
	// See if we can fold constants
	
	if (childConst)
	{
		TIntermConstant* FoldUnaryConstantExpression(TOperator op, TIntermConstant* node);
		TIntermConstant* res = FoldUnaryConstantExpression(node->getOp(), childConst);
		if (res)
		{
			delete node;
			return res;
		}
	}
	

	return node;
}
Example #19
0
TIntermTyped* ir_promote_constant(TBasicType promoteTo, TIntermConstant* right, TInfoSink& infoSink)
{
	unsigned size = right->getCount();
	const TType& t = right->getType();
	TIntermConstant* left = ir_add_constant(TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getColsCount(), t.getRowsCount(), t.isMatrix(), t.isArray()), right->getLine());
	for (unsigned i = 0; i != size; ++i) {
		TIntermConstant::Value& value = right->getValue(i);
		
		switch (promoteTo)
		{
		case EbtFloat:
			switch (value.type) {
			case EbtInt:
				left->setValue(i, (float)value.asInt);
				break;
			case EbtBool:
				left->setValue(i, (float)value.asBool);
				break;
			case EbtFloat:
				left->setValue(i, value.asFloat);
				break;
			default: 
				infoSink.info.message(EPrefixInternalError, "Cannot promote", right->getLine());
				return 0;
			}                
			break;
		case EbtInt:
			switch (value.type) {
			case EbtInt:
				left->setValue(i, value.asInt);
				break;
			case EbtBool:
				left->setValue(i, (int)value.asBool);
				break;
			case EbtFloat:
				left->setValue(i, (int)value.asFloat);
				break;
			default: 
				infoSink.info.message(EPrefixInternalError, "Cannot promote", right->getLine());
				return 0;
			}                
			break;
		case EbtBool:
			switch (value.type) {
			case EbtInt:
				left->setValue(i, value.asInt != 0);
				break;
			case EbtBool:
				left->setValue(i, value.asBool);
				break;
			case EbtFloat:
				left->setValue(i, value.asFloat != 0.0f);
				break;
			default: 
				infoSink.info.message(EPrefixInternalError, "Cannot promote", right->getLine());
				return 0;
			}                
			break;
		default:
			infoSink.info.message(EPrefixInternalError, "Incorrect data type found", right->getLine());
			return 0;
		}
	}

	return left;
}
Example #20
0
 TType atomic_max( TType * p, TType v ) { return TType(); }
//
// Establishes the type of the resultant operation, as well as
// makes the operator the correct one for the operands.
//
// Returns false if operator can't work on operands.
//
bool TIntermBinary::promote(TInfoSink& infoSink)
{
    // This function only handles scalars, vectors, and matrices.
    if (left->isArray() || right->isArray()) {
        infoSink.info.message(EPrefixInternalError, "Invalid operation for arrays", getLine());
        return false;
    }

    // GLSL ES 2.0 does not support implicit type casting.
    // So the basic type should always match.
    if (left->getBasicType() != right->getBasicType())
        return false;

    //
    // Base assumption:  just make the type the same as the left
    // operand.  Then only deviations from this need be coded.
    //
    setType(left->getType());

    // The result gets promoted to the highest precision.
    TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
    getTypePointer()->setPrecision(higherPrecision);

    // Binary operations results in temporary variables unless both
    // operands are const.
    if (left->getQualifier() != EvqConst || right->getQualifier() != EvqConst) {
        getTypePointer()->setQualifier(EvqTemporary);
    }

    int size = std::max(left->getNominalSize(), right->getNominalSize());

    //
    // All scalars. Code after this test assumes this case is removed!
    //
    if (size == 1) {
        switch (op) {
            //
            // Promote to conditional
            //
            case EOpEqual:
            case EOpNotEqual:
            case EOpLessThan:
            case EOpGreaterThan:
            case EOpLessThanEqual:
            case EOpGreaterThanEqual:
                setType(TType(EbtBool, EbpUndefined));
                break;

            //
            // And and Or operate on conditionals
            //
            case EOpLogicalAnd:
            case EOpLogicalOr:
                // Both operands must be of type bool.
                if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
                    return false;
                setType(TType(EbtBool, EbpUndefined));
                break;

            default:
                break;
        }
        return true;
    }

    // If we reach here, at least one of the operands is vector or matrix.
    // The other operand could be a scalar, vector, or matrix.
    // Are the sizes compatible?
    //
    if (left->getNominalSize() != right->getNominalSize()) {
        // If the nominal size of operands do not match:
        // One of them must be scalar.
        if (left->getNominalSize() != 1 && right->getNominalSize() != 1)
            return false;
        // Operator cannot be of type pure assignment.
        if (op == EOpAssign || op == EOpInitialize)
            return false;
    }

    //
    // Can these two operands be combined?
    //
    TBasicType basicType = left->getBasicType();
    switch (op) {
        case EOpMul:
            if (!left->isMatrix() && right->isMatrix()) {
                if (left->isVector())
                    op = EOpVectorTimesMatrix;
                else {
                    op = EOpMatrixTimesScalar;
                    setType(TType(basicType, higherPrecision, EvqTemporary, size, true));
                }
            } else if (left->isMatrix() && !right->isMatrix()) {
                if (right->isVector()) {
                    op = EOpMatrixTimesVector;
                    setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
                } else {
                    op = EOpMatrixTimesScalar;
                }
            } else if (left->isMatrix() && right->isMatrix()) {
                op = EOpMatrixTimesMatrix;
            } else if (!left->isMatrix() && !right->isMatrix()) {
                if (left->isVector() && right->isVector()) {
                    // leave as component product
                } else if (left->isVector() || right->isVector()) {
                    op = EOpVectorTimesScalar;
                    setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
                }
            } else {
                infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
                return false;
            }
            break;
        case EOpMulAssign:
            if (!left->isMatrix() && right->isMatrix()) {
                if (left->isVector())
                    op = EOpVectorTimesMatrixAssign;
                else {
                    return false;
                }
            } else if (left->isMatrix() && !right->isMatrix()) {
                if (right->isVector()) {
                    return false;
                } else {
                    op = EOpMatrixTimesScalarAssign;
                }
            } else if (left->isMatrix() && right->isMatrix()) {
                op = EOpMatrixTimesMatrixAssign;
            } else if (!left->isMatrix() && !right->isMatrix()) {
                if (left->isVector() && right->isVector()) {
                    // leave as component product
                } else if (left->isVector() || right->isVector()) {
                    if (! left->isVector())
                        return false;
                    op = EOpVectorTimesScalarAssign;
                    setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
                }
            } else {
                infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
                return false;
            }
            break;

        case EOpAssign:
        case EOpInitialize:
        case EOpAdd:
        case EOpSub:
        case EOpDiv:
        case EOpAddAssign:
        case EOpSubAssign:
        case EOpDivAssign:
            if ((left->isMatrix() && right->isVector()) ||
                (left->isVector() && right->isMatrix()))
                return false;
            setType(TType(basicType, higherPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix()));
            break;

        case EOpEqual:
        case EOpNotEqual:
        case EOpLessThan:
        case EOpGreaterThan:
        case EOpLessThanEqual:
        case EOpGreaterThanEqual:
            if ((left->isMatrix() && right->isVector()) ||
                (left->isVector() && right->isMatrix()))
                return false;
            setType(TType(EbtBool, EbpUndefined));
            break;

        default:
            return false;
    }
    
    return true;
}
//
// Add one node as the parent of another that it operates on.
//
// Returns the added node.
//
TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line, TSymbolTable& symbolTable)
{
    TIntermUnary* node;
    TIntermTyped* child = childNode->getAsTyped();

    if (child == 0) {
        infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
        return 0;
    }

    switch (op) {
        case EOpLogicalNot:
            if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
                return 0;
            }
            break;

        case EOpPostIncrement:
        case EOpPreIncrement:
        case EOpPostDecrement:
        case EOpPreDecrement:
        case EOpNegative:
            if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
                return 0;
        default: break;
    }

    //
    // Do we need to promote the operand?
    //
    // Note: Implicit promotions were removed from the language.
    //
    TBasicType newType = EbtVoid;
    switch (op) {
        case EOpConstructInt:   newType = EbtInt;   break;
        case EOpConstructBool:  newType = EbtBool;  break;
        case EOpConstructFloat: newType = EbtFloat; break;
        default: break;
    }

    if (newType != EbtVoid) {
        child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary,
            child->getNominalSize(),
            child->isMatrix(),
            child->isArray()),
            child);
        if (child == 0)
            return 0;
    }

    //
    // For constructors, we are now done, it's all in the conversion.
    //
    switch (op) {
        case EOpConstructInt:
        case EOpConstructBool:
        case EOpConstructFloat:
            return child;
        default: break;
    }

    TIntermConstantUnion *childTempConstant = 0;
    if (child->getAsConstantUnion())
        childTempConstant = child->getAsConstantUnion();

    //
    // Make a new node for the operator.
    //
    node = new TIntermUnary(op);
    if (line == 0)
        line = child->getLine();
    node->setLine(line);
    node->setOperand(child);

    if (! node->promote(infoSink))
        return 0;

    if (childTempConstant)  {
        TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);

        if (newChild)
            return newChild;
    }

    return node;
}
TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
{
    ConstantUnion *unionArray = getUnionArrayPointer();
    int objectSize = getType().getObjectSize();

    if (constantNode) {  // binary operations
        TIntermConstantUnion *node = constantNode->getAsConstantUnion();
        ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
        TType returnType = getType();

        // for a case like float f = 1.2 + vec4(2,3,4,5);
        if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
            rightUnionArray = new ConstantUnion[objectSize];
            for (int i = 0; i < objectSize; ++i)
                rightUnionArray[i] = *node->getUnionArrayPointer();
            returnType = getType();
        } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
            // for a case like float f = vec4(2,3,4,5) + 1.2;
            unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
            for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
                unionArray[i] = *getUnionArrayPointer();
            returnType = node->getType();
            objectSize = constantNode->getType().getObjectSize();
        }

        ConstantUnion* tempConstArray = 0;
        TIntermConstantUnion *tempNode;

        bool boolNodeFlag = false;
        switch(op) {
            case EOpAdd:
                tempConstArray = new ConstantUnion[objectSize];
                {// support MSVC++6.0
                    for (int i = 0; i < objectSize; i++)
                        tempConstArray[i] = unionArray[i] + rightUnionArray[i];
                }
                break;
            case EOpSub:
                tempConstArray = new ConstantUnion[objectSize];
                {// support MSVC++6.0
                    for (int i = 0; i < objectSize; i++)
                        tempConstArray[i] = unionArray[i] - rightUnionArray[i];
                }
                break;

            case EOpMul:
            case EOpVectorTimesScalar:
            case EOpMatrixTimesScalar:
                tempConstArray = new ConstantUnion[objectSize];
                {// support MSVC++6.0
                    for (int i = 0; i < objectSize; i++)
                        tempConstArray[i] = unionArray[i] * rightUnionArray[i];
                }
                break;
            case EOpMatrixTimesMatrix:
                if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
                    infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
                    return 0;
                }
                {// support MSVC++6.0
                    int size = getNominalSize();
                    tempConstArray = new ConstantUnion[size*size];
                    for (int row = 0; row < size; row++) {
                        for (int column = 0; column < size; column++) {
                            tempConstArray[size * column + row].setFConst(0.0f);
                            for (int i = 0; i < size; i++) {
                                tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst()));
                            }
                        }
                    }
                }
                break;
            case EOpDiv:
                tempConstArray = new ConstantUnion[objectSize];
                {// support MSVC++6.0
                    for (int i = 0; i < objectSize; i++) {
                        switch (getType().getBasicType()) {
            case EbtFloat:
                if (rightUnionArray[i] == 0.0f) {
                    infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
                    tempConstArray[i].setFConst(FLT_MAX);
                } else
                    tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
                break;

            case EbtInt:
                if (rightUnionArray[i] == 0) {
                    infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
                    tempConstArray[i].setIConst(INT_MAX);
                } else
                    tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
                break;
            default:
                infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
                return 0;
                        }
                    }
                }
                break;

            case EOpMatrixTimesVector:
                if (node->getBasicType() != EbtFloat) {
                    infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
                    return 0;
                }
                tempConstArray = new ConstantUnion[getNominalSize()];

                {// support MSVC++6.0
                    for (int size = getNominalSize(), i = 0; i < size; i++) {
                        tempConstArray[i].setFConst(0.0f);
                        for (int j = 0; j < size; j++) {
                            tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
                        }
                    }
                }

                tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
                tempNode->setLine(getLine());

                return tempNode;

            case EOpVectorTimesMatrix:
                if (getType().getBasicType() != EbtFloat) {
                    infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
                    return 0;
                }

                tempConstArray = new ConstantUnion[getNominalSize()];
                {// support MSVC++6.0
                    for (int size = getNominalSize(), i = 0; i < size; i++) {
                        tempConstArray[i].setFConst(0.0f);
                        for (int j = 0; j < size; j++) {
                            tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
                        }
                    }
                }
                break;

            case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
                tempConstArray = new ConstantUnion[objectSize];
                {// support MSVC++6.0
                    for (int i = 0; i < objectSize; i++)
                        tempConstArray[i] = unionArray[i] && rightUnionArray[i];
                }
                break;

            case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
                tempConstArray = new ConstantUnion[objectSize];
                {// support MSVC++6.0
                    for (int i = 0; i < objectSize; i++)
                        tempConstArray[i] = unionArray[i] || rightUnionArray[i];
                }
                break;

            case EOpLogicalXor:
                tempConstArray = new ConstantUnion[objectSize];
                {// support MSVC++6.0
                    for (int i = 0; i < objectSize; i++)
                        switch (getType().getBasicType()) {
            case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
            default: assert(false && "Default missing");
                    }
                }
                break;

            case EOpLessThan:
                assert(objectSize == 1);
                tempConstArray = new ConstantUnion[1];
                tempConstArray->setBConst(*unionArray < *rightUnionArray);
                returnType = TType(EbtBool, EbpUndefined, EvqConst);
                break;
            case EOpGreaterThan:
                assert(objectSize == 1);
                tempConstArray = new ConstantUnion[1];
                tempConstArray->setBConst(*unionArray > *rightUnionArray);
                returnType = TType(EbtBool, EbpUndefined, EvqConst);
                break;
            case EOpLessThanEqual:
                {
                    assert(objectSize == 1);
                    ConstantUnion constant;
                    constant.setBConst(*unionArray > *rightUnionArray);
                    tempConstArray = new ConstantUnion[1];
                    tempConstArray->setBConst(!constant.getBConst());
                    returnType = TType(EbtBool, EbpUndefined, EvqConst);
                    break;
                }
            case EOpGreaterThanEqual:
                {
                    assert(objectSize == 1);
                    ConstantUnion constant;
                    constant.setBConst(*unionArray < *rightUnionArray);
                    tempConstArray = new ConstantUnion[1];
                    tempConstArray->setBConst(!constant.getBConst());
                    returnType = TType(EbtBool, EbpUndefined, EvqConst);
                    break;
                }

            case EOpEqual:
                if (getType().getBasicType() == EbtStruct) {
                    if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
                        boolNodeFlag = true;
                } else {
                    for (int i = 0; i < objectSize; i++) {
                        if (unionArray[i] != rightUnionArray[i]) {
                            boolNodeFlag = true;
                            break;  // break out of for loop
                        }
                    }
                }

                tempConstArray = new ConstantUnion[1];
                if (!boolNodeFlag) {
                    tempConstArray->setBConst(true);
                }
                else {
                    tempConstArray->setBConst(false);
                }

                tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
                tempNode->setLine(getLine());

                return tempNode;

            case EOpNotEqual:
                if (getType().getBasicType() == EbtStruct) {
                    if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
                        boolNodeFlag = true;
                } else {
                    for (int i = 0; i < objectSize; i++) {
                        if (unionArray[i] == rightUnionArray[i]) {
                            boolNodeFlag = true;
                            break;  // break out of for loop
                        }
                    }
                }

                tempConstArray = new ConstantUnion[1];
                if (!boolNodeFlag) {
                    tempConstArray->setBConst(true);
                }
                else {
                    tempConstArray->setBConst(false);
                }

                tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
                tempNode->setLine(getLine());

                return tempNode;

            default:
                infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine());
                return 0;
        }
        tempNode = new TIntermConstantUnion(tempConstArray, returnType);
        tempNode->setLine(getLine());

        return tempNode;
    } else {
        //
        // Do unary operations
        //
        TIntermConstantUnion *newNode = 0;
        ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
        for (int i = 0; i < objectSize; i++) {
            switch(op) {
                case EOpNegative:
                    switch (getType().getBasicType()) {
                        case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
                        case EbtInt:   tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
                        default:
                            infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
                            return 0;
                    }
                    break;
                case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
                    switch (getType().getBasicType()) {
                        case EbtBool:  tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
                        default:
                            infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
                            return 0;
                    }
                    break;
                default:
                    return 0;
            }
        }
        newNode = new TIntermConstantUnion(tempConstArray, getType());
        newNode->setLine(getLine());
        return newNode;
    }
}
Example #24
0
//
// Initializers show up in several places in the grammar.  Have one set of
// code to handle them here.
//
bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, 
                                       TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
{
    TType type = TType(pType);

    if (variable == 0) {
        if (reservedErrorCheck(line, identifier))
            return true;

        if (voidErrorCheck(line, identifier, pType))
            return true;

        //
        // add variable to symbol table
        //
        variable = new TVariable(&identifier, type);
        if (! symbolTable.insert(*variable)) {
            error(line, "redefinition", variable->getName().c_str(), "");
            return true;
            // don't delete variable, it's used by error recovery, and the pool 
            // pop will take care of the memory
        }
    }

    //
    // identifier must be of type constant, a global, or a temporary
    //
    TQualifier qualifier = variable->getType().getQualifier();
    if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) {
        error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString(), "");
        return true;
    }
    //
    // test for and propagate constant
    //

    if (qualifier == EvqConst) {
        if (qualifier != initializer->getType().getQualifier()) {
            error(line, " assigning non-constant to", "=", "'%s'", variable->getType().getCompleteString().c_str());
            variable->getType().setQualifier(EvqTemporary);
            return true;
        }
        if (type != initializer->getType()) {
            error(line, " non-matching types for const initializer ", 
                variable->getType().getQualifierString(), "");
            variable->getType().setQualifier(EvqTemporary);
            return true;
        }
        if (initializer->getAsConstantUnion()) { 
            ConstantUnion* unionArray = variable->getConstPointer();

            if (type.getObjectSize() == 1 && type.getBasicType() != EbtStruct) {
                *unionArray = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0];
            } else {
                variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
            }
        } else if (initializer->getAsSymbolNode()) {
            const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol());
            const TVariable* tVar = static_cast<const TVariable*>(symbol);

            ConstantUnion* constArray = tVar->getConstPointer();
            variable->shareConstPointer(constArray);
        } else {
            error(line, " cannot assign to", "=", "'%s'", variable->getType().getCompleteString().c_str());
            variable->getType().setQualifier(EvqTemporary);
            return true;
        }
    }
 
    if (qualifier != EvqConst) {
        TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
        intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line);
        if (intermNode == 0) {
            assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
            return true;
        }
    } else 
        intermNode = 0;

    return false;
}
Example #25
0
//
// Do all the semantic checking for declaring an array, with and 
// without a size, and make the right changes to the symbol table.
//
// size == 0 means no specified size.
//
// Returns true if there was an error.
//
bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable)
{
    //
    // Don't check for reserved word use until after we know it's not in the symbol table,
    // because reserved arrays can be redeclared.
    //

    bool builtIn = false; 
    bool sameScope = false;
    TSymbol* symbol = symbolTable.find(identifier, &builtIn, &sameScope);
    if (symbol == 0 || !sameScope) {
        if (reservedErrorCheck(line, identifier))
            return true;
        
        variable = new TVariable(&identifier, TType(type));

        if (type.arraySize)
            variable->getType().setArraySize(type.arraySize);

        if (! symbolTable.insert(*variable)) {
            delete variable;
            error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str(), "");
            return true;
        }
    } else {
        if (! symbol->isVariable()) {
            error(line, "variable expected", identifier.c_str(), "");
            return true;
        }

        variable = static_cast<TVariable*>(symbol);
        if (! variable->getType().isArray()) {
            error(line, "redeclaring non-array as array", identifier.c_str(), "");
            return true;
        }
        if (variable->getType().getArraySize() > 0) {
            error(line, "redeclaration of array with size", identifier.c_str(), "");
            return true;
        }
        
        if (! variable->getType().sameElementType(TType(type))) {
            error(line, "redeclaration of array with a different type", identifier.c_str(), "");
            return true;
        }

        TType* t = variable->getArrayInformationType();
        while (t != 0) {
            if (t->getMaxArraySize() > type.arraySize) {
                error(line, "higher index value already used for the array", identifier.c_str(), "");
                return true;
            }
            t->setArraySize(type.arraySize);
            t = t->getArrayInformationType();
        }

        if (type.arraySize)
            variable->getType().setArraySize(type.arraySize);
    } 

    if (voidErrorCheck(line, identifier, type))
        return true;

    return false;
}
void IdentifyBuiltIns(sh::GLenum type, ShShaderSpec spec,
                      const ShBuiltInResources &resources,
                      TSymbolTable &symbolTable)
{
    //
    // Insert some special built-in variables that are not in
    // the built-in header files.
    //
    switch (type)
    {
      case GL_FRAGMENT_SHADER:
        symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FragCoord"),
            TType(EbtFloat, EbpMedium, EvqFragCoord, 4)));
        symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FrontFacing"),
            TType(EbtBool,  EbpUndefined, EvqFrontFacing, 1)));
        symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointCoord"),
            TType(EbtFloat, EbpMedium, EvqPointCoord, 2)));

        {
            symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragColor"),
                TType(EbtFloat, EbpMedium, EvqFragColor, 4)));
            TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, 1, true);
            fragData.setArraySize(resources.MaxDrawBuffers);
            symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragData"), fragData));

            if (resources.EXT_blend_func_extended)
            {
                symbolTable.insert(
                    ESSL1_BUILTINS, "GL_EXT_blend_func_extended",
                    new TVariable(NewPoolTString("gl_SecondaryFragColorEXT"),
                                  TType(EbtFloat, EbpMedium, EvqSecondaryFragColorEXT, 4)));
                TType secondaryFragData(EbtFloat, EbpMedium, EvqSecondaryFragDataEXT, 4, 1, true);
                secondaryFragData.setArraySize(resources.MaxDualSourceDrawBuffers);
                symbolTable.insert(
                    ESSL1_BUILTINS, "GL_EXT_blend_func_extended",
                    new TVariable(NewPoolTString("gl_SecondaryFragDataEXT"), secondaryFragData));
            }

            if (resources.EXT_frag_depth)
            {
                symbolTable.insert(ESSL1_BUILTINS, "GL_EXT_frag_depth", new TVariable(NewPoolTString("gl_FragDepthEXT"),
                    TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1)));
            }

            if (resources.EXT_shader_framebuffer_fetch || resources.NV_shader_framebuffer_fetch)
            {
                TType lastFragData(EbtFloat, EbpMedium, EvqLastFragData, 4, 1, true);
                lastFragData.setArraySize(resources.MaxDrawBuffers);

                if (resources.EXT_shader_framebuffer_fetch)
                {
                    symbolTable.insert(ESSL1_BUILTINS, "GL_EXT_shader_framebuffer_fetch",
                        new TVariable(NewPoolTString("gl_LastFragData"), lastFragData));
                }
                else if (resources.NV_shader_framebuffer_fetch)
                {
                    symbolTable.insert(ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch",
                        new TVariable(NewPoolTString("gl_LastFragColor"),
                        TType(EbtFloat, EbpMedium, EvqLastFragColor, 4)));
                    symbolTable.insert(ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch",
                        new TVariable(NewPoolTString("gl_LastFragData"), lastFragData));
                }
            }
            else if (resources.ARM_shader_framebuffer_fetch)
            {
                symbolTable.insert(ESSL1_BUILTINS, "GL_ARM_shader_framebuffer_fetch",
                    new TVariable(NewPoolTString("gl_LastFragColorARM"),
                    TType(EbtFloat, EbpMedium, EvqLastFragColor, 4)));
            }
        }

        break;

      case GL_VERTEX_SHADER:
        symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_Position"),
            TType(EbtFloat, EbpHigh, EvqPosition, 4)));
        symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointSize"),
            TType(EbtFloat, EbpMedium, EvqPointSize, 1)));
        symbolTable.insert(ESSL3_BUILTINS, new TVariable(NewPoolTString("gl_InstanceID"),
            TType(EbtInt, EbpHigh, EvqInstanceID, 1)));
        break;

      default:
        assert(false && "Language not supported");
    }
}
Example #27
0
//
// Establishes the type of the resultant operation, as well as
// makes the operator the correct one for the operands.
//
// Returns false if operator can't work on operands.
//
bool TIntermBinary::promote(TParseContext& ctx)
{
   TBasicType type = left->getBasicType();

   //
   // Arrays have to be exact matches.
   //
   if ((left->isArray() || right->isArray()) && (left->getType() != right->getType()))
      return false;

   //
   // Base assumption:  just make the type the same as the left
   // operand.  Then only deviations from this need be coded.
   //
   setType(TType(type, left->getPrecision(), EvqTemporary, left->getColsCount(), left->getRowsCount(), left->isMatrix()));

   // The result gets promoted to the highest precision.
   TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
   getTypePointer()->setPrecision(higherPrecision);


   //
   // Array operations.
   //
   if (left->isArray())
   {

      switch (op)
      {

      //
      // Promote to conditional
      //
      case EOpEqual:
      case EOpNotEqual:
         setType(TType(EbtBool, EbpUndefined));
         break;

         //
         // Set array information.
         //
      case EOpAssign:
         getType().setArraySize(left->getType().getArraySize());
         getType().setArrayInformationType(left->getType().getArrayInformationType());
         break;

      default:
         return false;
      }

      return true;
   }

   //
   // All scalars.  Code after this test assumes this case is removed!
   //
   if (left->isScalar() && right->isScalar())
   {

      switch (op)
      {

      //
      // Promote to conditional
      //
      case EOpEqual:
      case EOpNotEqual:
      case EOpLessThan:
      case EOpGreaterThan:
      case EOpLessThanEqual:
      case EOpGreaterThanEqual:
         setType(TType(EbtBool, EbpUndefined));
         break;

         //
         // And and Or operate on conditionals
         //
      case EOpLogicalAnd:
      case EOpLogicalOr:
         if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
            return false;
         setType(TType(EbtBool, EbpUndefined));
         break;

         //
         // Check for integer only operands.
         //
      case EOpRightShift:
      case EOpLeftShift:
      case EOpAnd:
      case EOpInclusiveOr:
      case EOpExclusiveOr:
         if (left->getBasicType() != EbtInt || right->getBasicType() != EbtInt)
            return false;
         break;
      case EOpModAssign:
      case EOpAndAssign:
      case EOpInclusiveOrAssign:
      case EOpExclusiveOrAssign:
      case EOpLeftShiftAssign:
      case EOpRightShiftAssign:
         if (left->getBasicType() != EbtInt || right->getBasicType() != EbtInt)
            return false;
         // fall through

         //
         // Everything else should have matching types
         //
      default:
         if (left->getBasicType() != right->getBasicType() ||
             left->isMatrix()     != right->isMatrix())
            return false;
      }

      return true;
   }

   // this is not an allowed promotion : float3x4 * float4x3
   if (left->getRowsCount() != right->getRowsCount() && left->getColsCount() != right->getColsCount() &&
       (left->getRowsCount() > right->getRowsCount()) != (left->getColsCount() > right->getColsCount()))
       return false;

   //determine if this is an assignment
   bool assignment = ( op >= EOpAssign && op <= EOpRightShiftAssign) ? true : false;

   // find size of the resulting value
   int cols = 0;
   int rows = 0;

   if (!left->isScalar() && !right->isScalar()) // no scalars, so downcast of the larger type
   {
       cols = std::min(left->getColsCount(), right->getColsCount());
       rows = std::min(left->getRowsCount(), right->getRowsCount());
   }
   else
   {
       cols = std::max(left->getColsCount(), right->getColsCount());
       rows = std::max(left->getRowsCount(), right->getRowsCount());
   }
   assert(cols > 0);
   assert(rows > 0);

   //
   // Downcast needed ?
   //
   if ( left->getColsCount() > cols || left->getRowsCount() > rows)
   {
       if (assignment)
           return false; //can't promote the destination

       //down convert left to match right
       TOperator convert = EOpNull;
       if (left->getTypePointer()->isMatrix())
       {
           convert = getMatrixConstructOp(*right, ctx);
		   if (convert == EOpNull)
			   return false;
       }
       else if (left->getTypePointer()->isVector())
       {
           switch (right->getTypePointer()->getBasicType())
           {
           case EbtBool:  convert = TOperator( EOpConstructBVec2 + rows - 2); break;
           case EbtInt:   convert = TOperator( EOpConstructIVec2 + rows - 2); break;
           case EbtFloat: convert = TOperator( EOpConstructVec2 +  rows - 2); break;
           default: break;
           }
       }
       else
       {
           assert(0); //size 1 case should have been handled
       }
       TIntermAggregate *node = new TIntermAggregate(convert);
       node->setLine(left->getLine());
       node->setType(TType(left->getBasicType(), left->getPrecision(), EvqTemporary,
                           right->getColsCount(), right->getRowsCount(), left->isMatrix()));
       node->getNodes().push_back(left);
       left = node;
       //now reset this node's type
       setType(TType(left->getBasicType(), left->getPrecision(), EvqTemporary,
                     right->getColsCount(), right->getRowsCount(), left->isMatrix()));
   }
   else if ( right->getColsCount() > cols || right->getRowsCount() > rows)
   {
       //down convert right to match left
       TOperator convert = EOpNull;
       if (right->getTypePointer()->isMatrix())
       {
           convert = getMatrixConstructOp(*left, ctx);
		   if (convert == EOpNull)
			   return false;
       }
       else if (right->getTypePointer()->isVector())
       {
           switch (left->getTypePointer()->getBasicType())
           {
           case EbtBool:  convert = TOperator( EOpConstructBVec2 + rows - 2); break;
           case EbtInt:   convert = TOperator( EOpConstructIVec2 + rows - 2); break;
           case EbtFloat: convert = TOperator( EOpConstructVec2  + rows - 2); break;
           default: break;
           }
       }
       else
       {
           assert(0); //size 1 case should have been handled
       }
       TIntermAggregate *node = new TIntermAggregate(convert);
       node->setLine(right->getLine());
       node->setType(TType(right->getBasicType(), right->getPrecision(), EvqTemporary,
                           left->getColsCount(), left->getRowsCount(), right->isMatrix()));
       node->getNodes().push_back(right);
       right = node;
   }

   //
   // Can these two operands be combined?
   //
   switch (op)
   {
   case EOpMul:
      if (!left->isMatrix() && right->isMatrix())
      {
         if (left->isVector())
            op = EOpVectorTimesMatrix;
         else
         {
            op = EOpMatrixTimesScalar;
            setType(TType(type, higherPrecision, EvqTemporary, cols, rows, true));
         }
      }
      else if (left->isMatrix() && !right->isMatrix())
      {
         if (right->isVector())
         {
            op = EOpMatrixTimesVector;
            setType(TType(type, higherPrecision, EvqTemporary, cols, rows, false));
         }
         else
         {
            op = EOpMatrixTimesScalar;
         }
      }
      else if (left->isMatrix() && right->isMatrix())
      {
         op = EOpMatrixTimesMatrix;
      }
      else if (!left->isMatrix() && !right->isMatrix())
      {
         if (left->isVector() && right->isVector())
         {
            // leave as component product
         }
         else if (left->isVector() || right->isVector())
         {
            op = EOpVectorTimesScalar;
            setType(TType(type, higherPrecision, EvqTemporary, cols, rows, false));
         }
      }
      else
      {
         ctx.infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
         return false;
      }
      break;
   case EOpMulAssign:
      if (!left->isMatrix() && right->isMatrix())
      {
         if (left->isVector())
            op = EOpVectorTimesMatrixAssign;
         else
         {
            return false;
         }
      }
      else if (left->isMatrix() && !right->isMatrix())
      {
         if (right->isVector())
         {
            return false;
         }
         else
         {
            op = EOpMatrixTimesScalarAssign;
         }
      }
      else if (left->isMatrix() && right->isMatrix())
      {
         op = EOpMatrixTimesMatrixAssign;
      }
      else if (!left->isMatrix() && !right->isMatrix())
      {
         if (left->isVector() && right->isVector())
         {
            // leave as component product
         }
         else if (left->isVector() || right->isVector())
         {
            if (! left->isVector())
               return false;
            op = EOpVectorTimesScalarAssign;
            setType(TType(type, higherPrecision, EvqTemporary, cols, rows, false));
         }
      }
      else
      {
         ctx.infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
         return false;
      }
      break;
   case EOpAssign:
      if ( left->getColsCount() != right->getColsCount() ||
           left->getRowsCount() != right->getRowsCount())
      {
         //right needs to be forced to match left
         TOperator convert = EOpNull;

         if (left->isMatrix() )
         {
             convert = getMatrixConstructOp(*left, ctx);
			 if (convert == EOpNull)
				 return false;
         }
         else if (left->isVector() )
         {
            switch (left->getTypePointer()->getBasicType())
            {
            case EbtBool:  convert = TOperator( EOpConstructBVec2 + left->getRowsCount() - 2); break;
            case EbtInt:   convert = TOperator( EOpConstructIVec2 + left->getRowsCount() - 2); break;
            case EbtFloat: convert = TOperator( EOpConstructVec2  + left->getRowsCount() - 2); break;
            default: break;
            }
         }
         else
         {
            switch (left->getTypePointer()->getBasicType())
            {
            case EbtBool:  convert = EOpConstructBool; break;
            case EbtInt:   convert = EOpConstructInt; break;
            case EbtFloat: convert = EOpConstructFloat; break;
            default: break;
            }
         }

         assert( convert != EOpNull);
         TIntermAggregate *node = new TIntermAggregate(convert);
         node->setLine(right->getLine());
         node->setType(TType(left->getBasicType(), left->getPrecision(), right->getQualifier() == EvqConst ? EvqConst : EvqTemporary,
                             left->getColsCount(), left->getRowsCount(), left->isMatrix()));
         node->getNodes().push_back(right);
         right = node;
         cols = right->getColsCount();
         rows = right->getRowsCount();
      }
      // fall through
   case EOpMod:
   case EOpAdd:
   case EOpSub:
   case EOpDiv:
   case EOpAddAssign:
   case EOpSubAssign:
   case EOpDivAssign:
   case EOpModAssign:
      if (op == EOpMod)
		  type = EbtFloat;
      if ((left->isMatrix() && right->isVector()) ||
          (left->isVector() && right->isMatrix()) ||
          left->getBasicType() != right->getBasicType())
         return false;
      setType(TType(type, left->getPrecision(), EvqTemporary, cols, rows, left->isMatrix() || right->isMatrix()));
      break;

   case EOpEqual:
   case EOpNotEqual:
   case EOpLessThan:
   case EOpGreaterThan:
   case EOpLessThanEqual:
   case EOpGreaterThanEqual:
      if ((left->isMatrix() && right->isVector()) ||
          (left->isVector() && right->isMatrix()) ||
          left->getBasicType() != right->getBasicType())
         return false;
      setType(TType(EbtBool, higherPrecision, EvqTemporary, cols, rows, false));
      break;

   default:
      return false;
   }

   //
   // One more check for assignment.  The Resulting type has to match the left operand.
   //
   switch (op)
   {
   case EOpAssign:
   case EOpAddAssign:
   case EOpSubAssign:
   case EOpMulAssign:
   case EOpDivAssign:
   case EOpModAssign:
   case EOpAndAssign:
   case EOpInclusiveOrAssign:
   case EOpExclusiveOrAssign:
   case EOpLeftShiftAssign:
   case EOpRightShiftAssign:
      if (getType() != left->getType())
         return false;
      break;
   default:
      break;
   }

   return true;
}
Example #28
0
 TType atomic_add( TType * p, TType v ) { return TType(); }
TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
{
    ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
    int size = node->getType().getObjectSize();

    ConstantUnion *leftUnionArray = new ConstantUnion[size];

    for (int i=0; i < size; i++) {

        switch (promoteTo) {
            case EbtFloat:
                switch (node->getType().getBasicType()) {
                    case EbtInt:
                        leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getIConst()));
                        break;
                    case EbtBool:
                        leftUnionArray[i].setFConst(static_cast<float>(rightUnionArray[i].getBConst()));
                        break;
                    case EbtFloat:
                        leftUnionArray[i] = rightUnionArray[i];
                        break;
                    default:
                        infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
                        return 0;
                }
                break;
            case EbtInt:
                switch (node->getType().getBasicType()) {
                    case EbtInt:
                        leftUnionArray[i] = rightUnionArray[i];
                        break;
                    case EbtBool:
                        leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getBConst()));
                        break;
                    case EbtFloat:
                        leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getFConst()));
                        break;
                    default:
                        infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
                        return 0;
                }
                break;
            case EbtBool:
                switch (node->getType().getBasicType()) {
                    case EbtInt:
                        leftUnionArray[i].setBConst(rightUnionArray[i].getIConst() != 0);
                        break;
                    case EbtBool:
                        leftUnionArray[i] = rightUnionArray[i];
                        break;
                    case EbtFloat:
                        leftUnionArray[i].setBConst(rightUnionArray[i].getFConst() != 0.0f);
                        break;
                    default:
                        infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
                        return 0;
                }

                break;
            default:
                infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
                return 0;
        }

    }

    const TType& t = node->getType();

    return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine());
}
Example #30
0
 TType abs_diff( TType, TType ) { return TType(); }