Ejemplo n.º 1
0
TIntermNode *ElseBlockRewriter::rewriteSelection(TIntermSelection *selection)
{
    ASSERT(selection->getFalseBlock() != NULL);

    TString temporaryName = "cond_" + str(mTemporaryIndex++);
    TIntermTyped *typedCondition = selection->getCondition()->getAsTyped();
    TType resultType(EbtBool, EbpUndefined);
    TIntermSymbol *conditionSymbolA = MakeNewTemporary(temporaryName, EbtBool);
    TIntermSymbol *conditionSymbolB = MakeNewTemporary(temporaryName, EbtBool);
    TIntermSymbol *conditionSymbolC = MakeNewTemporary(temporaryName, EbtBool);
    TIntermBinary *storeCondition = MakeNewBinary(EOpInitialize, conditionSymbolA,
                                                  typedCondition, resultType);
    TIntermUnary *negatedCondition = MakeNewUnary(EOpLogicalNot, conditionSymbolB);
    TIntermSelection *falseBlock = new TIntermSelection(negatedCondition,
                                                        selection->getFalseBlock(), NULL);
    TIntermSelection *newIfElse = new TIntermSelection(conditionSymbolC,
                                                       selection->getTrueBlock(), falseBlock);

    TIntermAggregate *declaration = new TIntermAggregate(EOpDeclaration);
    declaration->getSequence().push_back(storeCondition);

    TIntermAggregate *block = new TIntermAggregate(EOpSequence);
    block->getSequence().push_back(declaration);
    block->getSequence().push_back(newIfElse);

    return block;
}
Ejemplo n.º 2
0
//
// This is the safe way to change the operator on an aggregate, as it
// does lots of error checking and fixing.  Especially for establishing
// a function call's operation on it's set of parameters.  Sequences
// of instructions are also aggregates, but they just direnctly set
// their operator to EOpSequence.
//
// Returns an aggregate node, which could be the one passed in if
// it was already an aggregate but no operator was set.
//
TIntermAggregate *TIntermediate::setAggregateOperator(
    TIntermNode *node, TOperator op, const TSourceLoc &line)
{
    TIntermAggregate *aggNode;

    //
    // Make sure we have an aggregate.  If not turn it into one.
    //
    if (node)
    {
        aggNode = node->getAsAggregate();
        if (aggNode == NULL || aggNode->getOp() != EOpNull)
        {
            //
            // Make an aggregate containing this node.
            //
            aggNode = new TIntermAggregate();
            aggNode->getSequence()->push_back(node);
        }
    }
    else
    {
        aggNode = new TIntermAggregate();
    }

    //
    // Set the operator.
    //
    aggNode->setOp(op);
    aggNode->setLine(line);

    return aggNode;
}
Ejemplo n.º 3
0
bool isChildofMain(TIntermNode *node, TIntermNode *root)
{
    TIntermNode *main = getFunctionBySignature(MAIN_FUNC_SIGNATURE, root);

    if (!main) {
        dbgPrint(DBGLVL_ERROR, "CodeTools - could not find main function\n");
        exit(1);
    }

    TIntermAggregate *aggregate;

    if (!(aggregate = main->getAsAggregate())) {
        dbgPrint(DBGLVL_ERROR, "CodeTools - main is not Aggregate\n");
        exit(1);
    }
    
    TIntermSequence sequence = aggregate->getSequence();
    TIntermSequence::iterator sit;

    for(sit = sequence.begin(); sit != sequence.end(); sit++) {
        if (*sit == node) {
            return true;
        }
    }

    return false;
}
Ejemplo n.º 4
0
void TLValueTrackingTraverser::traverseFunctionDefinition(TIntermFunctionDefinition *node)
{
    TIntermAggregate *params = node->getFunctionParameters();
    ASSERT(params != nullptr);
    ASSERT(params->getOp() == EOpParameters);
    addToFunctionMap(node->getFunctionSymbolInfo()->getNameObj(), params->getSequence());

    TIntermTraverser::traverseFunctionDefinition(node);
}
Ejemplo n.º 5
0
int ValidateLimitations::validateForLoopInit(TIntermLoop *node)
{
    TIntermNode *init = node->getInit();
    if (init == NULL)
    {
        error(node->getLine(), "Missing init declaration", "for");
        return -1;
    }

    //
    // init-declaration has the form:
    //     type-specifier identifier = constant-expression
    //
    TIntermAggregate *decl = init->getAsAggregate();
    if ((decl == NULL) || (decl->getOp() != EOpDeclaration))
    {
        error(init->getLine(), "Invalid init declaration", "for");
        return -1;
    }
    // To keep things simple do not allow declaration list.
    TIntermSequence &declSeq = decl->getSequence();
    if (declSeq.size() != 1)
    {
        error(decl->getLine(), "Invalid init declaration", "for");
        return -1;
    }
    TIntermBinary *declInit = declSeq[0]->getAsBinaryNode();
    if ((declInit == NULL) || (declInit->getOp() != EOpInitialize))
    {
        error(decl->getLine(), "Invalid init declaration", "for");
        return -1;
    }
    TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode();
    if (symbol == NULL)
    {
        error(declInit->getLine(), "Invalid init declaration", "for");
        return -1;
    }
    // The loop index has type int or float.
    TBasicType type = symbol->getBasicType();
    if ((type != EbtInt) && (type != EbtFloat))
    {
        error(symbol->getLine(),
              "Invalid type for loop index", getBasicString(type));
        return -1;
    }
    // The loop index is initialized with constant expression.
    if (!isConstExpr(declInit->getRight()))
    {
        error(declInit->getLine(),
              "Loop index cannot be initialized with non-constant expression",
              symbol->getSymbol().c_str());
        return -1;
    }

    return symbol->getId();
}
Ejemplo n.º 6
0
//
// Turn an existing node into an aggregate.
//
// Returns an aggregate, unless 0 was passed in for the existing node.
//
TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& line)
{
    if (node == 0)
        return 0;

    TIntermAggregate* aggNode = new TIntermAggregate;
    aggNode->getSequence().push_back(node);
    aggNode->setLine(line);

    return aggNode;
}
Ejemplo n.º 7
0
bool TCompiler::pruneUnusedFunctions(TIntermNode *root)
{
    TIntermAggregate *rootNode = root->getAsAggregate();
    ASSERT(rootNode != nullptr);

    UnusedPredicate isUnused(&mCallDag, &functionMetadata);
    TIntermSequence *sequence = rootNode->getSequence();
    sequence->erase(std::remove_if(sequence->begin(), sequence->end(), isUnused), sequence->end());

    return true;
}
Ejemplo n.º 8
0
ParsedHxsl Parser::parse(TIntermNode* e) {
    TIntermAggregate* aggregate = e->getAsAggregate();
    for (auto it = aggregate->getSequence().begin(); it != aggregate->getSequence().end(); ++it) {
        parseDecl(*it);
    }
    if (main == nullptr) error("Missing main function", e->getLine().first_line);
    allowReturn = false;
    ParsedCode s = buildShader(main);
    std::map<std::string, ParsedCode> help;
    allowReturn = true;
    for (auto it = helpers.begin(); it != helpers.end(); ++it) {
        help[it->first] = buildShader(it->second);
    }

    ParsedHxsl hxsl;
    hxsl.shader = s;
    hxsl.globals = globals;
    hxsl.pos = e->getLine().first_line;
    hxsl.helpers = help;
    return hxsl;
}
Ejemplo n.º 9
0
TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier)
{
    ASSERT(initializer != nullptr);
    TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType(), qualifier);
    TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
    TIntermBinary *tempInit = new TIntermBinary(EOpInitialize);
    tempInit->setLeft(tempSymbol);
    tempInit->setRight(initializer);
    tempInit->setType(tempSymbol->getType());
    tempDeclaration->getSequence()->push_back(tempInit);
    return tempDeclaration;
}
Ejemplo n.º 10
0
//
// Safe way to combine two nodes into an aggregate.  Works with null pointers,
// a node that's not a aggregate yet, etc.
//
// Returns the resulting aggregate, unless 0 was passed in for
// both existing nodes.
//
TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& line)
{
    if (left == 0 && right == 0)
        return 0;

    TIntermAggregate* aggNode = 0;
    if (left)
        aggNode = left->getAsAggregate();
    if (!aggNode || aggNode->getOp() != EOpNull) {
        aggNode = new TIntermAggregate;
        if (left)
            aggNode->getSequence().push_back(left);
    }

    if (right)
        aggNode->getSequence().push_back(right);

    aggNode->setLine(line);

    return aggNode;
}
Ejemplo n.º 11
0
TIntermNode* getFunctionBySignature(const char *sig, TIntermNode* root)
// Assumption: 1. roots hold all function definitions.
//                for single file shaders this should hold.
// Todo: Add solution for multiple files compiled in one shader.
{
	TIntermAggregate *aggregate;
	TIntermSequence sequence;
	TIntermSequence::iterator sit;

	// Root must be aggregate
	if (!(aggregate = root->getAsAggregate())) {
		return NULL;
	}
	if (aggregate->getOp() == EOpFunction) {
		// do not stop search at function prototypes
		if (aggregate->getSequence().size() != 0) {
			if (!strcmp(sig, aggregate->getName().c_str())) {
				return aggregate;
			}
		}
	} else {
		sequence = aggregate->getSequence();

		for (sit = sequence.begin(); sit != sequence.end(); sit++) {
			if ((*sit)->getAsAggregate()
					&& (*sit)->getAsAggregate()->getOp() == EOpFunction) {
				// do not stop search at function prototypes
				if ((*sit)->getAsAggregate()->getSequence().size() != 0) {
					if (!strcmp(sig,
							(*sit)->getAsAggregate()->getName().c_str())) {
						return *sit;
					}
				}
			}
		}
	}
	return NULL;
}
TString ScalarizeVecAndMatConstructorArgs::createTempVariable(TIntermTyped *original)
{
    TString tempVarName = "_webgl_tmp_";
    if (original->isScalar())
    {
        tempVarName += "scalar_";
    }
    else if (original->isVector())
    {
        tempVarName += "vec_";
    }
    else
    {
        ASSERT(original->isMatrix());
        tempVarName += "mat_";
    }
    tempVarName += Str(mTempVarCount).c_str();
    mTempVarCount++;

    ASSERT(original);
    TType type = original->getType();
    type.setQualifier(EvqTemporary);

    if (mShaderType == GL_FRAGMENT_SHADER &&
        type.getBasicType() == EbtFloat &&
        type.getPrecision() == EbpUndefined)
    {
        // We use the highest available precision for the temporary variable
        // to avoid computing the actual precision using the rules defined
        // in GLSL ES 1.0 Section 4.5.2.
        type.setPrecision(mFragmentPrecisionHigh ? EbpHigh : EbpMedium);
    }

    TIntermBinary *init = new TIntermBinary(EOpInitialize);
    TIntermSymbol *symbolNode = new TIntermSymbol(-1, tempVarName, type);
    init->setLeft(symbolNode);
    init->setRight(original);
    init->setType(type);

    TIntermAggregate *decl = new TIntermAggregate(EOpDeclaration);
    decl->getSequence()->push_back(init);

    ASSERT(mSequenceStack.size() > 0);
    TIntermSequence &sequence = mSequenceStack.back();
    sequence.push_back(decl);

    return tempVarName;
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
0
//
// This is to be executed once the final root is put on top by the parsing
// process.
//
TIntermAggregate *TIntermediate::postProcess(TIntermNode *root)
{
    if (root == nullptr)
        return nullptr;

    //
    // Finish off the top level sequence, if any
    //
    TIntermAggregate *aggRoot = root->getAsAggregate();
    if (aggRoot != nullptr && aggRoot->getOp() == EOpNull)
    {
        aggRoot->setOp(EOpSequence);
    }
    else if (aggRoot == nullptr || aggRoot->getOp() != EOpSequence)
    {
        aggRoot = new TIntermAggregate(EOpSequence);
        aggRoot->setLine(root->getLine());
        aggRoot->getSequence()->push_back(root);
    }

    return aggRoot;
}
Ejemplo n.º 15
0
void ForLoopUnroll::FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info)
{
    ASSERT(node->getType() == ELoopFor);
    ASSERT(node->getUnrollFlag());

    TIntermNode* init = node->getInit();
    ASSERT(init != NULL);
    TIntermAggregate* decl = init->getAsAggregate();
    ASSERT((decl != NULL) && (decl->getOp() == EOpDeclaration));
    TIntermSequence& declSeq = decl->getSequence();
    ASSERT(declSeq.size() == 1);
    TIntermBinary* declInit = declSeq[0]->getAsBinaryNode();
    ASSERT((declInit != NULL) && (declInit->getOp() == EOpInitialize));
    TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode();
    ASSERT(symbol != NULL);
    ASSERT(symbol->getBasicType() == EbtInt);

    info.id = symbol->getId();

    ASSERT(declInit->getRight() != NULL);
    TIntermConstantUnion* initNode = declInit->getRight()->getAsConstantUnion();
    ASSERT(initNode != NULL);

    info.initValue = evaluateIntConstant(initNode);
    info.currentValue = info.initValue;

    TIntermNode* cond = node->getCondition();
    ASSERT(cond != NULL);
    TIntermBinary* binOp = cond->getAsBinaryNode();
    ASSERT(binOp != NULL);
    ASSERT(binOp->getRight() != NULL);
    ASSERT(binOp->getRight()->getAsConstantUnion() != NULL);

    info.incrementValue = getLoopIncrement(node);
    info.stopValue = evaluateIntConstant(
        binOp->getRight()->getAsConstantUnion());
    info.op = binOp->getOp();
}
Ejemplo n.º 16
0
bool InitializeVariables::visitAggregate(Visit visit, TIntermAggregate *node)
{
    bool visitChildren = !mCodeInserted;
    switch (node->getOp())
    {
      case EOpSequence:
        break;
      case EOpFunction:
      {
        // Function definition.
        ASSERT(visit == PreVisit);
        if (node->getName() == "main(")
        {
            TIntermSequence *sequence = node->getSequence();
            ASSERT((sequence->size() == 1) || (sequence->size() == 2));
            TIntermAggregate *body = NULL;
            if (sequence->size() == 1)
            {
                body = new TIntermAggregate(EOpSequence);
                sequence->push_back(body);
            }
            else
            {
                body = (*sequence)[1]->getAsAggregate();
            }
            ASSERT(body);
            insertInitCode(body->getSequence());
            mCodeInserted = true;
        }
        break;
      }
      default:
        visitChildren = false;
        break;
    }
    return visitChildren;
}
Ejemplo n.º 17
0
bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
{
    bool visitChildren = true;
    TInfoSinkBase& out = objSink();
    switch (node->getOp())
    {
        case EOpInitialize:
            if (visit == InVisit)
            {
                out << " = ";
                // RHS of initialize is not being declared.
                mDeclaringVariables = false;
            }
            break;
        case EOpAssign: writeTriplet(visit, "(", " = ", ")"); break;
        case EOpAddAssign: writeTriplet(visit, "(", " += ", ")"); break;
        case EOpSubAssign: writeTriplet(visit, "(", " -= ", ")"); break;
        case EOpDivAssign: writeTriplet(visit, "(", " /= ", ")"); break;
        // Notice the fall-through.
        case EOpMulAssign: 
        case EOpVectorTimesMatrixAssign:
        case EOpVectorTimesScalarAssign:
        case EOpMatrixTimesScalarAssign:
        case EOpMatrixTimesMatrixAssign:
            writeTriplet(visit, "(", " *= ", ")");
            break;

        case EOpIndexDirect:
        case EOpIndexIndirect:
            writeTriplet(visit, NULL, "[", "]");
            break;
        case EOpIndexDirectStruct:
            if (visit == InVisit)
            {
                out << ".";
                // TODO(alokp): ASSERT
                out << node->getType().getFieldName();
                visitChildren = false;
            }
            break;
        case EOpVectorSwizzle:
            if (visit == InVisit)
            {
                out << ".";
                TIntermAggregate* rightChild = node->getRight()->getAsAggregate();
                TIntermSequence& sequence = rightChild->getSequence();
                for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit)
                {
                    TIntermConstantUnion* element = (*sit)->getAsConstantUnion();
                    ASSERT(element->getBasicType() == EbtInt);
                    ASSERT(element->getNominalSize() == 1);
                    const ConstantUnion& data = element->getUnionArrayPointer()[0];
                    ASSERT(data.getType() == EbtInt);
                    switch (data.getIConst())
                    {
                        case 0: out << "x"; break;
                        case 1: out << "y"; break;
                        case 2: out << "z"; break;
                        case 3: out << "w"; break;
                        default: UNREACHABLE(); break;
                    }
                }
                visitChildren = false;
            }
            break;

        case EOpAdd: writeTriplet(visit, "(", " + ", ")"); break;
        case EOpSub: writeTriplet(visit, "(", " - ", ")"); break;
        case EOpMul: writeTriplet(visit, "(", " * ", ")"); break;
        case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break;
        case EOpMod: UNIMPLEMENTED(); break;
        case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break;
        case EOpNotEqual: writeTriplet(visit, "(", " != ", ")"); break;
        case EOpLessThan: writeTriplet(visit, "(", " < ", ")"); break;
        case EOpGreaterThan: writeTriplet(visit, "(", " > ", ")"); break;
        case EOpLessThanEqual: writeTriplet(visit, "(", " <= ", ")"); break;
        case EOpGreaterThanEqual: writeTriplet(visit, "(", " >= ", ")"); break;

        // Notice the fall-through.
        case EOpVectorTimesScalar:
        case EOpVectorTimesMatrix:
        case EOpMatrixTimesVector:
        case EOpMatrixTimesScalar:
        case EOpMatrixTimesMatrix:
            writeTriplet(visit, "(", " * ", ")");
            break;

        case EOpLogicalOr: writeTriplet(visit, "(", " || ", ")"); break;
        case EOpLogicalXor: writeTriplet(visit, "(", " ^^ ", ")"); break;
        case EOpLogicalAnd: writeTriplet(visit, "(", " && ", ")"); break;
        default: UNREACHABLE(); break;
    }

    return visitChildren;
}
Ejemplo n.º 18
0
void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
{
    bool visit = true;

    TIntermSequence *sequence = node->getSequence();
    switch (node->getOp())
    {
        case EOpFunction:
        {
            TIntermAggregate *params = sequence->front()->getAsAggregate();
            ASSERT(params != nullptr);
            ASSERT(params->getOp() == EOpParameters);
            addToFunctionMap(node->getNameObj(), params->getSequence());
            break;
        }
        case EOpPrototype:
            addToFunctionMap(node->getNameObj(), sequence);
            break;
        default:
            break;
    }

    if (preVisit)
        visit = visitAggregate(PreVisit, node);

    if (visit)
    {
        bool inFunctionMap = false;
        if (node->getOp() == EOpFunctionCall)
        {
            inFunctionMap = isInFunctionMap(node);
            if (!inFunctionMap)
            {
                // The function is not user-defined - it is likely built-in texture function.
                // Assume that those do not have out parameters.
                setInFunctionCallOutParameter(false);
            }
        }

        incrementDepth(node);

        if (inFunctionMap)
        {
            TIntermSequence *params             = getFunctionParameters(node);
            TIntermSequence::iterator paramIter = params->begin();
            for (auto *child : *sequence)
            {
                ASSERT(paramIter != params->end());
                TQualifier qualifier = (*paramIter)->getAsTyped()->getQualifier();
                setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);

                child->traverse(this);
                if (visit && inVisit)
                {
                    if (child != sequence->back())
                        visit = visitAggregate(InVisit, node);
                }

                ++paramIter;
            }

            setInFunctionCallOutParameter(false);
        }
        else
        {
            if (node->getOp() == EOpSequence)
                pushParentBlock(node);
            else if (node->getOp() == EOpFunction)
                mInGlobalScope = false;

            // Find the built-in function corresponding to this op so that we can determine the
            // in/out qualifiers of its parameters.
            TFunction *builtInFunc = nullptr;
            TString opString = GetOperatorString(node->getOp());
            if (!node->isConstructor() && !opString.empty())
            {
                // The return type doesn't affect the mangled name of the function, which is used
                // to look it up from the symbol table.
                TType dummyReturnType;
                TFunction call(&opString, &dummyReturnType, node->getOp());
                for (auto *child : *sequence)
                {
                    TType *paramType = child->getAsTyped()->getTypePointer();
                    TConstParameter p(paramType);
                    call.addParameter(p);
                }

                TSymbol *sym = mSymbolTable.findBuiltIn(call.getMangledName(), mShaderVersion);
                if (sym != nullptr && sym->isFunction())
                {
                    builtInFunc = static_cast<TFunction *>(sym);
                    ASSERT(builtInFunc->getParamCount() == sequence->size());
                }
            }

            size_t paramIndex = 0;

            for (auto *child : *sequence)
            {
                TQualifier qualifier = EvqIn;
                if (builtInFunc != nullptr)
                    qualifier = builtInFunc->getParam(paramIndex).type->getQualifier();
                setInFunctionCallOutParameter(qualifier == EvqOut || qualifier == EvqInOut);
                child->traverse(this);

                if (visit && inVisit)
                {
                    if (child != sequence->back())
                        visit = visitAggregate(InVisit, node);
                }

                if (node->getOp() == EOpSequence)
                    incrementParentBlockPos();

                ++paramIndex;
            }

            setInFunctionCallOutParameter(false);

            if (node->getOp() == EOpSequence)
                popParentBlock();
            else if (node->getOp() == EOpFunction)
                mInGlobalScope = true;
        }

        decrementDepth();
    }

    if (visit && postVisit)
        visitAggregate(PostVisit, node);
}
Ejemplo n.º 19
0
bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node)
{
    bool visitChildren = true;
    switch (node->getOp())
    {
      case EOpSequence:
      case EOpConstructStruct:
        // No special handling
        break;
      case EOpFunction:
        if (visit == PreVisit)
        {
            const TIntermSequence &sequence = *(node->getSequence());
            TIntermSequence::const_iterator seqIter = sequence.begin();
            TIntermAggregate *params = (*seqIter)->getAsAggregate();
            ASSERT(params != NULL);
            ASSERT(params->getOp() == EOpParameters);
            mFunctionMap[node->getName()] = params->getSequence();
        }
        break;
      case EOpPrototype:
        if (visit == PreVisit)
            mFunctionMap[node->getName()] = node->getSequence();
        visitChildren = false;
        break;
      case EOpParameters:
        visitChildren = false;
        break;
      case EOpInvariantDeclaration:
        visitChildren = false;
        break;
      case EOpDeclaration:
        // Variable declaration.
        if (visit == PreVisit)
        {
            mDeclaringVariables = true;
        }
        else if (visit == InVisit)
        {
            mDeclaringVariables = true;
        }
        else
        {
            mDeclaringVariables = false;
        }
        break;
      case EOpFunctionCall:
      {
        // Function call.
        bool inFunctionMap = (mFunctionMap.find(node->getName()) != mFunctionMap.end());
        if (visit == PreVisit)
        {
            // User-defined function return values are not rounded, this relies on that
            // calculations producing the value were rounded.
            TIntermNode *parent = getParentNode();
            if (canRoundFloat(node->getType()) && !inFunctionMap && parentUsesResult(parent, node))
            {
                TIntermNode *replacement = createRoundingFunctionCallNode(node);
                mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
            }

            if (inFunctionMap)
            {
                mSeqIterStack.push_back(mFunctionMap[node->getName()]->begin());
                if (mSeqIterStack.back() != mFunctionMap[node->getName()]->end())
                {
                    TQualifier qualifier = (*mSeqIterStack.back())->getAsTyped()->getQualifier();
                    mInFunctionCallOutParameter = (qualifier == EvqOut || qualifier == EvqInOut);
                }
            }
            else
            {
                // The function is not user-defined - it is likely built-in texture function.
                // Assume that those do not have out parameters.
                mInFunctionCallOutParameter = false;
            }
        }
        else if (visit == InVisit)
        {
            if (inFunctionMap)
            {
                ++mSeqIterStack.back();
                TQualifier qualifier = (*mSeqIterStack.back())->getAsTyped()->getQualifier();
                mInFunctionCallOutParameter = (qualifier == EvqOut || qualifier == EvqInOut);
            }
        }
        else
        {
            if (inFunctionMap)
            {
                mSeqIterStack.pop_back();
                mInFunctionCallOutParameter = false;
            }
        }
        break;
      }
      default:
        TIntermNode *parent = getParentNode();
        if (canRoundFloat(node->getType()) && visit == PreVisit && parentUsesResult(parent, node))
        {
            TIntermNode *replacement = createRoundingFunctionCallNode(node);
            mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
        }
        break;
    }
    return visitChildren;
}
Ejemplo n.º 20
0
bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
{
    bool visitChildren = true;
    TInfoSinkBase &out = objSink();
    switch (node->getOp())
    {
      case EOpInitialize:
        if (visit == InVisit)
        {
            out << " = ";
            // RHS of initialize is not being declared.
            mDeclaringVariables = false;
        }
        break;
      case EOpAssign:
        writeTriplet(visit, "(", " = ", ")");
        break;
      case EOpAddAssign:
        writeTriplet(visit, "(", " += ", ")");
        break;
      case EOpSubAssign:
        writeTriplet(visit, "(", " -= ", ")");
        break;
      case EOpDivAssign:
        writeTriplet(visit, "(", " /= ", ")");
        break;
      case EOpIModAssign:
        writeTriplet(visit, "(", " %= ", ")");
        break;
      // Notice the fall-through.
      case EOpMulAssign:
      case EOpVectorTimesMatrixAssign:
      case EOpVectorTimesScalarAssign:
      case EOpMatrixTimesScalarAssign:
      case EOpMatrixTimesMatrixAssign:
        writeTriplet(visit, "(", " *= ", ")");
        break;
      case EOpBitShiftLeftAssign:
        writeTriplet(visit, "(", " <<= ", ")");
        break;
      case EOpBitShiftRightAssign:
        writeTriplet(visit, "(", " >>= ", ")");
        break;
      case EOpBitwiseAndAssign:
        writeTriplet(visit, "(", " &= ", ")");
        break;
      case EOpBitwiseXorAssign:
        writeTriplet(visit, "(", " ^= ", ")");
        break;
      case EOpBitwiseOrAssign:
        writeTriplet(visit, "(", " |= ", ")");
        break;

      case EOpIndexDirect:
        writeTriplet(visit, NULL, "[", "]");
        break;
      case EOpIndexIndirect:
        if (node->getAddIndexClamp())
        {
            if (visit == InVisit)
            {
                if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
                    out << "[int(clamp(float(";
                else
                    out << "[webgl_int_clamp(";
            }
            else if (visit == PostVisit)
            {
                int maxSize;
                TIntermTyped *left = node->getLeft();
                TType leftType = left->getType();

                if (left->isArray())
                {
                    // The shader will fail validation if the array length is not > 0.
                    maxSize = leftType.getArraySize() - 1;
                }
                else
                {
                    maxSize = leftType.getNominalSize() - 1;
                }

                if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
                    out << "), 0.0, float(" << maxSize << ")))]";
                else
                    out << ", 0, " << maxSize << ")]";
            }
        }
        else
        {
            writeTriplet(visit, NULL, "[", "]");
        }
        break;
      case EOpIndexDirectStruct:
        if (visit == InVisit)
        {
            // Here we are writing out "foo.bar", where "foo" is struct
            // and "bar" is field. In AST, it is represented as a binary
            // node, where left child represents "foo" and right child "bar".
            // The node itself represents ".". The struct field "bar" is
            // actually stored as an index into TStructure::fields.
            out << ".";
            const TStructure *structure = node->getLeft()->getType().getStruct();
            const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
            const TField *field = structure->fields()[index->getIConst(0)];

            TString fieldName = field->name();
            if (!mSymbolTable.findBuiltIn(structure->name(), mShaderVersion))
                fieldName = hashName(fieldName);

            out << fieldName;
            visitChildren = false;
        }
        break;
      case EOpIndexDirectInterfaceBlock:
          if (visit == InVisit)
          {
              out << ".";
              const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock();
              const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
              const TField *field = interfaceBlock->fields()[index->getIConst(0)];

              TString fieldName = field->name();
              ASSERT(!mSymbolTable.findBuiltIn(interfaceBlock->name(), mShaderVersion));
              fieldName = hashName(fieldName);

              out << fieldName;
              visitChildren = false;
          }
          break;
      case EOpVectorSwizzle:
        if (visit == InVisit)
        {
            out << ".";
            TIntermAggregate *rightChild = node->getRight()->getAsAggregate();
            TIntermSequence *sequence = rightChild->getSequence();
            for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); ++sit)
            {
                TIntermConstantUnion *element = (*sit)->getAsConstantUnion();
                ASSERT(element->getBasicType() == EbtInt);
                ASSERT(element->getNominalSize() == 1);
                const TConstantUnion& data = element->getUnionArrayPointer()[0];
                ASSERT(data.getType() == EbtInt);
                switch (data.getIConst())
                {
                  case 0:
                    out << "x";
                    break;
                  case 1:
                    out << "y";
                    break;
                  case 2:
                    out << "z";
                    break;
                  case 3:
                    out << "w";
                    break;
                  default:
                    UNREACHABLE();
                }
            }
            visitChildren = false;
        }
        break;

      case EOpAdd:
        writeTriplet(visit, "(", " + ", ")");
        break;
      case EOpSub:
        writeTriplet(visit, "(", " - ", ")");
        break;
      case EOpMul:
        writeTriplet(visit, "(", " * ", ")");
        break;
      case EOpDiv:
        writeTriplet(visit, "(", " / ", ")");
        break;
      case EOpIMod:
        writeTriplet(visit, "(", " % ", ")");
        break;
      case EOpBitShiftLeft:
        writeTriplet(visit, "(", " << ", ")");
        break;
      case EOpBitShiftRight:
        writeTriplet(visit, "(", " >> ", ")");
        break;
      case EOpBitwiseAnd:
        writeTriplet(visit, "(", " & ", ")");
        break;
      case EOpBitwiseXor:
        writeTriplet(visit, "(", " ^ ", ")");
        break;
      case EOpBitwiseOr:
        writeTriplet(visit, "(", " | ", ")");
        break;

      case EOpEqual:
        writeTriplet(visit, "(", " == ", ")");
        break;
      case EOpNotEqual:
        writeTriplet(visit, "(", " != ", ")");
        break;
      case EOpLessThan:
        writeTriplet(visit, "(", " < ", ")");
        break;
      case EOpGreaterThan:
        writeTriplet(visit, "(", " > ", ")");
        break;
      case EOpLessThanEqual:
        writeTriplet(visit, "(", " <= ", ")");
        break;
      case EOpGreaterThanEqual:
        writeTriplet(visit, "(", " >= ", ")");
        break;

      // Notice the fall-through.
      case EOpVectorTimesScalar:
      case EOpVectorTimesMatrix:
      case EOpMatrixTimesVector:
      case EOpMatrixTimesScalar:
      case EOpMatrixTimesMatrix:
        writeTriplet(visit, "(", " * ", ")");
        break;

      case EOpLogicalOr:
        writeTriplet(visit, "(", " || ", ")");
        break;
      case EOpLogicalXor:
        writeTriplet(visit, "(", " ^^ ", ")");
        break;
      case EOpLogicalAnd:
        writeTriplet(visit, "(", " && ", ")");
        break;
      default:
        UNREACHABLE();
    }

    return visitChildren;
}
Ejemplo n.º 21
0
TIntermAggregate *TIntermTraverser::createTempDeclaration(const TType &type)
{
    TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
    tempDeclaration->getSequence()->push_back(createTempSymbol(type));
    return tempDeclaration;
}
Ejemplo n.º 22
0
// This function is used to test for the correctness of the parameters passed to various constructor functions
// and also convert them to the right datatype if it is allowed and required. 
//
// Returns 0 for an error or the constructed node (aggregate or typed) for no error.
//
TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, TSourceLoc line)
{
    if (node == 0)
        return 0;

    TIntermAggregate* aggrNode = node->getAsAggregate();
    
    TTypeList::const_iterator memberTypes;
    if (op == EOpConstructStruct)
        memberTypes = type->getStruct()->begin();
    
    TType elementType = *type;
    if (type->isArray())
        elementType.clearArrayness();

    bool singleArg;
    if (aggrNode) {
        if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1)
            singleArg = true;
        else
            singleArg = false;
    } else
        singleArg = true;

    TIntermTyped *newNode;
    if (singleArg) {
        // If structure constructor or array constructor is being called 
        // for only one parameter inside the structure, we need to call constructStruct function once.
        if (type->isArray())
            newNode = constructStruct(node, &elementType, 1, node->getLine(), false);
        else if (op == EOpConstructStruct)
            newNode = constructStruct(node, (*memberTypes).type, 1, node->getLine(), false);
        else
            newNode = constructBuiltIn(type, op, node, node->getLine(), false);

        if (newNode && newNode->getAsAggregate()) {
            TIntermTyped* constConstructor = foldConstConstructor(newNode->getAsAggregate(), *type);
            if (constConstructor)
                return constConstructor;
        }

        return newNode;
    }
    
    //
    // Handle list of arguments.
    //
    TIntermSequence &sequenceVector = aggrNode->getSequence() ;    // Stores the information about the parameter to the constructor
    // if the structure constructor contains more than one parameter, then construct
    // each parameter
    
    int paramCount = 0;  // keeps a track of the constructor parameter number being checked    
    
    // for each parameter to the constructor call, check to see if the right type is passed or convert them 
    // to the right type if possible (and allowed).
    // for structure constructors, just check if the right type is passed, no conversion is allowed.
    
    for (TIntermSequence::iterator p = sequenceVector.begin(); 
                                   p != sequenceVector.end(); p++, paramCount++) {
        if (type->isArray())
            newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true);
        else if (op == EOpConstructStruct)
            newNode = constructStruct(*p, (memberTypes[paramCount]).type, paramCount+1, node->getLine(), true);
        else
            newNode = constructBuiltIn(type, op, *p, node->getLine(), true);
        
        if (newNode) {
            *p = newNode;
        }
    }

    TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, line);
    TIntermTyped* constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type);
    if (constConstructor)
        return constConstructor;

    return constructor;
}
Ejemplo n.º 23
0
bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
{
    bool visitChildren = true;
    TInfoSinkBase& out = objSink();
    switch (node->getOp())
    {
        case EOpInitialize:
            if (visit == InVisit)
            {
                out << " = ";
                // RHS of initialize is not being declared.
                mDeclaringVariables = false;
            }
            break;
        case EOpAssign: writeTriplet(visit, "(", " = ", ")"); break;
        case EOpAddAssign: writeTriplet(visit, "(", " += ", ")"); break;
        case EOpSubAssign: writeTriplet(visit, "(", " -= ", ")"); break;
        case EOpDivAssign: writeTriplet(visit, "(", " /= ", ")"); break;
        // Notice the fall-through.
        case EOpMulAssign: 
        case EOpVectorTimesMatrixAssign:
        case EOpVectorTimesScalarAssign:
        case EOpMatrixTimesScalarAssign:
        case EOpMatrixTimesMatrixAssign:
            writeTriplet(visit, "(", " *= ", ")");
            break;

        case EOpIndexDirect:
            writeTriplet(visit, NULL, "[", "]");
            break;
        case EOpIndexIndirect:
            if (node->getAddIndexClamp())
            {
                if (visit == InVisit)
                {
                    if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) {
                        out << "[int(clamp(float(";
                    } else {
                        out << "[webgl_int_clamp(";
                    }
                }
                else if (visit == PostVisit)
                {
                    int maxSize;
                    TIntermTyped *left = node->getLeft();
                    TType leftType = left->getType();

                    if (left->isArray())
                    {
                        // The shader will fail validation if the array length is not > 0.
                        maxSize = leftType.getArraySize() - 1;
                    }
                    else
                    {
                        maxSize = leftType.getNominalSize() - 1;
                    }

                    if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) {
                        out << "), 0.0, float(" << maxSize << ")))]";
                    } else {
                        out << ", 0, " << maxSize << ")]";
                    }
                }
            }
            else
            {
                writeTriplet(visit, NULL, "[", "]");
            }
            break;
        case EOpIndexDirectStruct:
            if (visit == InVisit)
            {
                out << ".";
                // TODO(alokp): ASSERT
                TString fieldName = node->getType().getFieldName();

                const TType& structType = node->getLeft()->getType();
                if (!mSymbolTable.findBuiltIn(structType.getTypeName()))
                    fieldName = hashName(fieldName);

                out << fieldName;
                visitChildren = false;
            }
            break;
        case EOpVectorSwizzle:
            if (visit == InVisit)
            {
                out << ".";
                TIntermAggregate* rightChild = node->getRight()->getAsAggregate();
                TIntermSequence& sequence = rightChild->getSequence();
                for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit)
                {
                    TIntermConstantUnion* element = (*sit)->getAsConstantUnion();
                    ASSERT(element->getBasicType() == EbtInt);
                    ASSERT(element->getNominalSize() == 1);
                    const ConstantUnion& data = element->getUnionArrayPointer()[0];
                    ASSERT(data.getType() == EbtInt);
                    switch (data.getIConst())
                    {
                        case 0: out << "x"; break;
                        case 1: out << "y"; break;
                        case 2: out << "z"; break;
                        case 3: out << "w"; break;
                        default: UNREACHABLE(); break;
                    }
                }
                visitChildren = false;
            }
            break;

        case EOpAdd: writeTriplet(visit, "(", " + ", ")"); break;
        case EOpSub: writeTriplet(visit, "(", " - ", ")"); break;
        case EOpMul: writeTriplet(visit, "(", " * ", ")"); break;
        case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break;
        case EOpMod: UNIMPLEMENTED(); break;
        case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break;
        case EOpNotEqual: writeTriplet(visit, "(", " != ", ")"); break;
        case EOpLessThan: writeTriplet(visit, "(", " < ", ")"); break;
        case EOpGreaterThan: writeTriplet(visit, "(", " > ", ")"); break;
        case EOpLessThanEqual: writeTriplet(visit, "(", " <= ", ")"); break;
        case EOpGreaterThanEqual: writeTriplet(visit, "(", " >= ", ")"); break;

        // Notice the fall-through.
        case EOpVectorTimesScalar:
        case EOpVectorTimesMatrix:
        case EOpMatrixTimesVector:
        case EOpMatrixTimesScalar:
        case EOpMatrixTimesMatrix:
            writeTriplet(visit, "(", " * ", ")");
            break;

        case EOpLogicalOr: writeTriplet(visit, "(", " || ", ")"); break;
        case EOpLogicalXor: writeTriplet(visit, "(", " ^^ ", ")"); break;
        case EOpLogicalAnd: writeTriplet(visit, "(", " && ", ")"); break;
        default: UNREACHABLE(); break;
    }

    return visitChildren;
}
Ejemplo n.º 24
0
//
// Both test and if necessary, spit out an error, to see if the node is really
// an l-value that can be operated on this way.
//
// Returns true if the was an error.
//
bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* node)
{
    TIntermSymbol* symNode = node->getAsSymbolNode();
    TIntermBinary* binaryNode = node->getAsBinaryNode();

    if (binaryNode) {
        bool errorReturn;

        switch(binaryNode->getOp()) {
        case EOpIndexDirect:
        case EOpIndexIndirect:
        case EOpIndexDirectStruct:
            return lValueErrorCheck(line, op, binaryNode->getLeft());
        case EOpVectorSwizzle:
            errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft());
            if (!errorReturn) {
                int offset[4] = {0,0,0,0};

                TIntermTyped* rightNode = binaryNode->getRight();
                TIntermAggregate *aggrNode = rightNode->getAsAggregate();
                
                for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); 
                                               p != aggrNode->getSequence().end(); p++) {
                    int value = (*p)->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getIConst();
                    offset[value]++;     
                    if (offset[value] > 1) {
                        error(line, " l-value of swizzle cannot have duplicate components", op, "", "");

                        return true;
                    }
                }
            } 

            return errorReturn;
        default: 
            break;
        }
        error(line, " l-value required", op, "", "");

        return true;
    }


    const char* symbol = 0;
    if (symNode != 0)
        symbol = symNode->getSymbol().c_str();

    const char* message = 0;
    switch (node->getQualifier()) {
    case EvqConst:          message = "can't modify a const";        break;
    case EvqConstReadOnly:  message = "can't modify a const";        break;
    case EvqAttribute:      message = "can't modify an attribute";   break;
    case EvqUniform:        message = "can't modify a uniform";      break;
    case EvqVaryingIn:      message = "can't modify a varying";      break;
    case EvqInput:          message = "can't modify an input";       break;
    case EvqFragCoord:      message = "can't modify gl_FragCoord";   break;
    case EvqFrontFacing:    message = "can't modify gl_FrontFacing"; break;
    case EvqPointCoord:     message = "can't modify gl_PointCoord";  break;
    default:

        //
        // Type that can't be written to?
        //
        switch (node->getBasicType()) {
        case EbtSampler2D:
        case EbtSamplerCube:
            message = "can't modify a sampler";
            break;
        case EbtVoid:
            message = "can't modify void";
            break;
        default: 
            break;
        }
    }

    if (message == 0 && binaryNode == 0 && symNode == 0) {
        error(line, " l-value required", op, "", "");

        return true;
    }


    //
    // Everything else is okay, no error.
    //
    if (message == 0)
        return false;

    //
    // If we get here, we have an error and a message.
    //
    if (symNode)
        error(line, " l-value required", op, "\"%s\" (%s)", symbol, message);
    else
        error(line, " l-value required", op, "(%s)", message);

    return true;
}