Пример #1
0
void TOutputGLSL::writeFunctionParameters(const TIntermSequence& args)
{
    TInfoSinkBase& out = objSink();
    for (TIntermSequence::const_iterator iter = args.begin();
         iter != args.end(); ++iter)
    {
        const TIntermSymbol* arg = (*iter)->getAsSymbolNode();
        ASSERT(arg != NULL);

        const TType& type = arg->getType();
        TQualifier qualifier = type.getQualifier();
        // TODO(alokp): Validate qualifier for function arguments.
        if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal))
            out << type.getQualifierString() << " ";

        out << getTypeName(type);

        const TString& name = arg->getSymbol();
        if (!name.empty())
            out << " " << name;
        if (type.isArray())
            out << arrayBrackets(type);

        // Put a comma if this is not the last argument.
        if (iter != args.end() - 1)
            out << ", ";
    }
}
Пример #2
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;
}
Пример #3
0
int getFunctionDebugParameter(TIntermAggregate *node)
{
    int result = -1;
    int i;

    if (!node)
        return result;

    if ( node->getOp() != EOpFunction) {
        return result;
    }

    TIntermSequence funcDeclSeq = node->getSequence();
    
    if (!funcDeclSeq[0] ||
        !funcDeclSeq[0]->getAsAggregate() ||
        !(funcDeclSeq[0]->getAsAggregate()->getOp() == EOpParameters)) {
        dbgPrint(DBGLVL_ERROR, "CodeTools - function does not comply with assumptions\n");
        exit(1);
    }
    TIntermSequence funcDeclParamSeq = (funcDeclSeq[0]->getAsAggregate())->getSequence();
    TIntermSequence::iterator pD = funcDeclParamSeq.begin();
    
    for (i=0; pD != funcDeclParamSeq.end(); ++pD, ++i) {
        if ((*pD)->getAsFuncParamNode()->getType().getQualifier() == EvqIn) {
            result = i;
        }
    }

    return result;
}
Пример #4
0
TType* getTypeDebugParameter(TIntermAggregate *node, int pnum)
{
	TType *result = NULL;

	if (!node)
		return result;

	if (node->getOp() != EOpFunctionCall)
		return result;

	TIntermSequence funcCallSeq = node->getSequence();

	if ((int) funcCallSeq.size() < pnum) {
		dbgPrint(DBGLVL_ERROR,
				"CodeTools -  function does not have this much parameter\n");
		exit(1);
	}

	if (!funcCallSeq[pnum]->getAsTyped()) {
		dbgPrint(DBGLVL_ERROR,
				"CodeTools -  in parameter is not of type TIntermTyped\n");
		exit(1);
	}

	return funcCallSeq[pnum]->getAsTyped()->getTypePointer();
}
Пример #5
0
// Traverse an aggregate node.  Same comments in binary node apply here.
void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
{
    bool visit = true;

    TIntermSequence *sequence = node->getSequence();

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

    if (visit)
    {
        incrementDepth(node);

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

        decrementDepth();
    }

    if (visit && postVisit)
        visitAggregate(PostVisit, node);
}
Пример #6
0
//
// Merge the linker objects from unitLinkerObjects into linkerObjects.
// Duplication is expected and filtered out, but contradictions are an error.
//
void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects)
{
    // Error check and merge the linker objects (duplicates should not be created)
    std::size_t initialNumLinkerObjects = linkerObjects.size();
    for (unsigned int unitLinkObj = 0; unitLinkObj < unitLinkerObjects.size(); ++unitLinkObj) {
        bool merge = true;
        for (std::size_t linkObj = 0; linkObj < initialNumLinkerObjects; ++linkObj) {
            TIntermSymbol* symbol = linkerObjects[linkObj]->getAsSymbolNode();
            TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode();
            assert(symbol && unitSymbol);
            if (symbol->getName() == unitSymbol->getName()) {
                // filter out copy
                merge = false;

                // but if one has an initializer and the other does not, update
                // the initializer
                if (symbol->getConstArray().empty() && ! unitSymbol->getConstArray().empty())
                    symbol->setConstArray(unitSymbol->getConstArray());

                // Similarly for binding
                if (! symbol->getQualifier().hasBinding() && unitSymbol->getQualifier().hasBinding())
                    symbol->getQualifier().layoutBinding = unitSymbol->getQualifier().layoutBinding;

                // Update implicit array sizes
                mergeImplicitArraySizes(symbol->getWritableType(), unitSymbol->getType());

                // Check for consistent types/qualification/initializers etc.
                mergeErrorCheck(infoSink, *symbol, *unitSymbol, false);
            }
        }
        if (merge)
            linkerObjects.push_back(unitLinkerObjects[unitLinkObj]);
    }
}
Пример #7
0
// Traverse a block node.
void TIntermTraverser::traverseBlock(TIntermBlock *node)
{
    bool visit = true;

    TIntermSequence *sequence = node->getSequence();

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

    if (visit)
    {
        incrementDepth(node);
        pushParentBlock(node);

        for (auto *child : *sequence)
        {
            child->traverse(this);
            if (visit && inVisit)
            {
                if (child != sequence->back())
                    visit = visitBlock(InVisit, node);
            }

            incrementParentBlockPos();
        }

        popParentBlock();
        decrementDepth();
    }

    if (visit && postVisit)
        visitBlock(PostVisit, node);
}
Пример #8
0
TIntermAggregate *EmulatePrecision::createCompoundAssignmentFunctionCallNode(TIntermTyped *left,
                                                                             TIntermTyped *right,
                                                                             const char *opNameStr)
{
    std::stringstream strstr = sh::InitializeStream<std::stringstream>();
    if (left->getPrecision() == EbpMedium)
        strstr << "angle_compound_" << opNameStr << "_frm";
    else
        strstr << "angle_compound_" << opNameStr << "_frl";
    ImmutableString functionName = ImmutableString(strstr.str());
    TIntermSequence *arguments   = new TIntermSequence();
    arguments->push_back(left);
    arguments->push_back(right);

    TVector<const TVariable *> parameters;
    TType *leftParamType = new TType(left->getType());
    leftParamType->setPrecision(EbpHigh);
    leftParamType->setQualifier(EvqOut);
    parameters.push_back(new TVariable(mSymbolTable, kParamXName,
                                       static_cast<const TType *>(leftParamType),
                                       SymbolType::AngleInternal));
    TType *rightParamType = new TType(right->getType());
    rightParamType->setPrecision(EbpHigh);
    rightParamType->setQualifier(EvqIn);
    parameters.push_back(new TVariable(mSymbolTable, kParamYName,
                                       static_cast<const TType *>(rightParamType),
                                       SymbolType::AngleInternal));

    return TIntermAggregate::CreateRawFunctionCall(
        *getInternalFunction(functionName, left->getType(), arguments, parameters, false),
        arguments);
}
Пример #9
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 != EbtUInt) && (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();
}
Пример #10
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;
}
Пример #11
0
bool ValidateLimitations::validateFunctionCall(TIntermAggregate *node)
{
    ASSERT(node->getOp() == EOpFunctionCall);

    // If not within loop body, there is nothing to check.
    if (!withinLoopBody())
        return true;

    // List of param indices for which loop indices are used as argument.
    typedef std::vector<size_t> ParamIndex;
    ParamIndex pIndex;
    TIntermSequence *params = node->getSequence();
    for (TIntermSequence::size_type i = 0; i < params->size(); ++i)
    {
        TIntermSymbol *symbol = (*params)[i]->getAsSymbolNode();
        if (symbol && isLoopIndex(symbol))
            pIndex.push_back(i);
    }
    // If none of the loop indices are used as arguments,
    // there is nothing to check.
    if (pIndex.empty())
        return true;

    bool valid = true;
    TSymbolTable& symbolTable = GetGlobalParseContext()->symbolTable;
    TSymbol *symbol           = symbolTable.find(node->getFunctionSymbolInfo()->getName(),
                                       GetGlobalParseContext()->getShaderVersion());
    ASSERT(symbol && symbol->isFunction());
    TFunction *function = static_cast<TFunction *>(symbol);
    for (ParamIndex::const_iterator i = pIndex.begin();
         i != pIndex.end(); ++i)
    {
        const TConstParameter &param = function->getParam(*i);
        TQualifier qual = param.type->getQualifier();
        if ((qual == EvqOut) || (qual == EvqInOut))
        {
            error((*params)[*i]->getLine(),
                  "Loop index cannot be used as argument to a function out or inout parameter",
                  (*params)[*i]->getAsSymbolNode()->getSymbol().c_str());
            valid = false;
        }
    }

    return valid;
}
Пример #12
0
//
// Traverse an aggregate node.  Same comments in binary node apply here.
//
void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
{
    bool visit = true;

    TIntermSequence *sequence = node->getSequence();

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

    if (visit)
    {
        incrementDepth(node);

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

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

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

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

        decrementDepth();
    }

    if (visit && postVisit)
        visitAggregate(PostVisit, node);
}
Пример #13
0
TIntermAggregate *EmulatePrecision::createRoundingFunctionCallNode(TIntermTyped *roundedChild)
{
    const ImmutableString *roundFunctionName = &kAngleFrmString;
    if (roundedChild->getPrecision() == EbpLow)
        roundFunctionName = &kAngleFrlString;
    TIntermSequence *arguments = new TIntermSequence();
    arguments->push_back(roundedChild);

    TVector<const TVariable *> parameters;
    TType *paramType = new TType(roundedChild->getType());
    paramType->setPrecision(EbpHigh);
    paramType->setQualifier(EvqIn);
    parameters.push_back(new TVariable(mSymbolTable, kParamXName,
                                       static_cast<const TType *>(paramType),
                                       SymbolType::AngleInternal));

    return TIntermAggregate::CreateRawFunctionCall(
        *getInternalFunction(*roundFunctionName, roundedChild->getType(), arguments, parameters,
                             true),
        arguments);
}
Пример #14
0
bool getHasSideEffectsDebugParameter(TIntermAggregate *node, int pnum)
{
    if (!node)
        return false;
    
    if ( node->getOp() != EOpFunctionCall)
        return false;
    
    TIntermSequence funcCallSeq = node->getSequence();
    
    if ((int) funcCallSeq.size() < pnum) {
        dbgPrint(DBGLVL_ERROR, "CodeTools - function does not have this much parameter\n");
        exit(1);
    }
    
    if (!funcCallSeq[pnum]->getAsTyped()) {
        dbgPrint(DBGLVL_ERROR, "CodeTools - in parameter is not of type TIntermTyped\n");
        exit(1);
    }
    
    return funcCallSeq[pnum]->getAsTyped()->hasSideEffects();
}
Пример #15
0
TIntermTyped *TIntermediate::addSwizzle(
    TVectorFields &fields, const 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;
}
Пример #16
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;
}
Пример #17
0
void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence& args)
{
    TInfoSinkBase& out = objSink();
    for (TIntermSequence::const_iterator iter = args.begin();
         iter != args.end(); ++iter)
    {
        const TIntermSymbol* arg = (*iter)->getAsSymbolNode();
        ASSERT(arg != NULL);

        const TType& type = arg->getType();
        writeVariableType(type);

        const TString& name = arg->getSymbol();
        if (!name.empty())
            out << " " << name;
        if (type.isArray())
            out << arrayBrackets(type);

        // Put a comma if this is not the last argument.
        if (iter != args.end() - 1)
            out << ", ";
    }
}
Пример #18
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;
}
Пример #19
0
void DeferGlobalInitializers(TIntermBlock *root,
                             bool initializeUninitializedGlobals,
                             TSymbolTable *symbolTable)
{
    TIntermSequence *deferredInitializers = new TIntermSequence();

    // Loop over all global statements and process the declarations. This is simpler than using a
    // traverser.
    for (TIntermNode *statement : *root->getSequence())
    {
        TIntermDeclaration *declaration = statement->getAsDeclarationNode();
        if (declaration)
        {
            GetDeferredInitializers(declaration, initializeUninitializedGlobals,
                                    deferredInitializers);
        }
    }

    // Add the function with initialization and the call to that.
    if (!deferredInitializers->empty())
    {
        InsertInitCallToMain(root, deferredInitializers, symbolTable);
    }
}
Пример #20
0
void CollectVariables::visitInfoList(const TIntermSequence &sequence,
                                     std::vector<VarT> *infoList) const
{
    for (size_t seqIndex = 0; seqIndex < sequence.size(); seqIndex++)
    {
        const TIntermSymbol *variable = sequence[seqIndex]->getAsSymbolNode();
        // The only case in which the sequence will not contain a
        // TIntermSymbol node is initialization. It will contain a
        // TInterBinary node in that case. Since attributes, uniforms,
        // and varyings cannot be initialized in a shader, we must have
        // only TIntermSymbol nodes in the sequence.
        ASSERT(variable != NULL);
        visitVariable(variable, infoList);
    }
}
Пример #21
0
//
// Merge the function bodies and global-level initializers from unitGlobals into globals.
// Will error check duplication of function bodies for the same signature.
//
void TIntermediate::mergeBodies(TInfoSink& infoSink, TIntermSequence& globals, const TIntermSequence& unitGlobals)
{
    // TODO: link-time performance: Processing in alphabetical order will be faster

    // Error check the global objects, not including the linker objects
    for (unsigned int child = 0; child < globals.size() - 1; ++child) {
        for (unsigned int unitChild = 0; unitChild < unitGlobals.size() - 1; ++unitChild) {
            TIntermAggregate* body = globals[child]->getAsAggregate();
            TIntermAggregate* unitBody = unitGlobals[unitChild]->getAsAggregate();
            if (body && unitBody && body->getOp() == EOpFunction && unitBody->getOp() == EOpFunction && body->getName() == unitBody->getName()) {
                error(infoSink, "Multiple function bodies in multiple compilation units for the same signature in the same stage:");
                infoSink.info << "    " << globals[child]->getAsAggregate()->getName() << "\n";
            }
        }
    }

    // Merge the global objects, just in front of the linker objects
    globals.insert(globals.end() - 1, unitGlobals.begin(), unitGlobals.end() - 1);
}
Пример #22
0
void TIntermTraverser::insertStatementInParentBlock(TIntermNode *statement)
{
    TIntermSequence insertions;
    insertions.push_back(statement);
    insertStatementsInParentBlock(insertions);
}
Пример #23
0
void Parser::parseExpr(TIntermSequence& e) {
    for (auto it = e.begin(); it != e.end(); ++it) {
        auto aggregate = (*it)->getAsAggregate();
        auto binop = (*it)->getAsBinaryNode();
        if (aggregate != nullptr) {
            switch (aggregate->getOp()) {
            case EOpFunctionCall: {
                ParsedExpr expr;
                expr.v = nullptr;
                ParsedValue value;
                value.v = nullptr;
                value.p = aggregate->getLine().first_line;
                std::vector<TIntermTyped*> args;
                for (auto it2 = aggregate->getSequence().begin(); it2 != aggregate->getSequence().end(); ++it2) {
                    args.push_back((*it2)->getAsTyped());
                }
                expr.e = new ParsedValue(makeCall(aggregate->getName().c_str(), args, aggregate->getLine().first_line));
                expr.p = aggregate->getLine().first_line;
                cur.exprs.push_back(expr);
                break;
            }
            case EOpDeclaration: {
                PLocal* local = new PLocal;
                auto var = dynamic_cast<TIntermBinary*>(aggregate->getSequence()[0]);
                if (var->getOp() != EOpInitialize) error("Expected initialization.", var->getLine().first_line);
                local->v = allocVar(var->getLeft()->getAsSymbolNode()->getSymbol().c_str(), var->getLeft()->getTypePointer(), VTmp, var->getLine().first_line);

                ParsedExpr expr;
                ParsedValue* value = new ParsedValue;
                value->v = local;
                value->p = var->getLine().first_line;
                expr.v = value;
                expr.e = new ParsedValue(parseValue(var->getRight()));
                expr.p = var->getLine().first_line;
                cur.exprs.push_back(expr);
                break;
            }
            default:
                break;
            }
        }
        else if (binop != nullptr) {
            switch (binop->getOp()) {
            case EOpAssign:
                addAssign(parseValue(binop->getLeft()), parseValue(binop->getRight()), binop->getLine().first_line);
                break;
            case EOpAddAssign:

                break;
            case EOpSubAssign:

                break;
            case EOpMulAssign:

                break;
            case EOpVectorTimesScalarAssign:

                break;
            case EOpMatrixTimesScalarAssign:

                break;
            case EOpVectorTimesMatrixAssign:

                break;
            case EOpMatrixTimesMatrixAssign:
                //case OpAssignOp(op):
                //	addAssign(parseValue(e1), parseValue( { expr : EBinop(op, e1, e2), pos : e.pos } ), e.pos);
                break;
            default:
                error("Operation should have side-effects", binop->getLine().first_line);
            }
        }

        /*switch (e.expr) {
        case EBlock(el):
        auto eold = cur.exprs;
        auto old = allowReturn;
        auto last = el[el.length - 1];
        cur.exprs = [];
        for (e in el) {
        allowReturn = old && (e == last);
        parseExpr(e);
        }
        allowReturn = old;
        eold.push({ v : null, e : { v : PBlock(cur.exprs), p : e.pos }, p : e.pos });
        cur.exprs = eold;
        case EIf(cond, eif, eelse):
        var pcond = parseValue(cond);

        var eold = cur.exprs;
        cur.exprs = [];
        parseExpr(eif);
        var pif = { v : PBlock(cur.exprs), p : eif.pos };

        var pelse = null;
        if( eelse != null ) {
        cur.exprs = [];
        parseExpr(eelse);
        pelse = { v : PBlock(cur.exprs), p : eelse.pos };
        }
        cur.exprs = eold;
        cur.exprs.push( {v:null, e: { v:PIf(pcond, pif, pelse), p : e.pos }, p : e.pos} );
        case EFor(it, expr):
        var iter = null, vname = null;
        switch( it.expr ) {
        case EIn(v,it):
        switch( v.expr ) {
        case EConst(c):
        	switch( c ) {
        	case CIdent(i) #if !haxe3 , CType(i) #end: vname = i;
        	default:
        	}
        default:
        }
        iter = parseValue(it);
        default:
        }
        if( vname == null )
        error("For should be in the form for( x in it )", it.pos);

        var old = cur.exprs;
        cur.exprs = [];
        parseExpr(expr);
        var pexpr = { v : PBlock(cur.exprs), p : expr.pos };
        cur.exprs = old;
        cur.exprs.push( {v : null, e:{v:PFor(vname, iter, pexpr), p:e.pos}, p:e.pos } );
        case EReturn(r):
        if( r == null ) error("Return must return a value", e.pos);
        if( !allowReturn ) error("Return only allowed as final expression in helper methods", e.pos);
        var v = parseValue(r);
        cur.exprs.push( { v : null, e : { v : PReturn(v), p : e.pos }, p : e.pos } );
        default:
        error("Unsupported expression", e.pos);
        }*/
    }
}
Пример #24
0
TIntermTyped *CreateZeroNode(const TType &type)
{
    TType constType(type);
    constType.setQualifier(EvqConst);

    if (!type.isArray() && type.getBasicType() != EbtStruct)
    {
        size_t size       = constType.getObjectSize();
        TConstantUnion *u = new TConstantUnion[size];
        for (size_t i = 0; i < size; ++i)
        {
            switch (type.getBasicType())
            {
                case EbtFloat:
                    u[i].setFConst(0.0f);
                    break;
                case EbtInt:
                    u[i].setIConst(0);
                    break;
                case EbtUInt:
                    u[i].setUConst(0u);
                    break;
                case EbtBool:
                    u[i].setBConst(false);
                    break;
                default:
                    // CreateZeroNode is called by ParseContext that keeps parsing even when an
                    // error occurs, so it is possible for CreateZeroNode to be called with
                    // non-basic types. This happens only on error condition but CreateZeroNode
                    // needs to return a value with the correct type to continue the typecheck.
                    // That's why we handle non-basic type by setting whatever value, we just need
                    // the type to be right.
                    u[i].setIConst(42);
                    break;
            }
        }

        TIntermConstantUnion *node = new TIntermConstantUnion(u, constType);
        return node;
    }

    if (type.getBasicType() == EbtVoid)
    {
        // Void array. This happens only on error condition, similarly to the case above. We don't
        // have a constructor operator for void, so this needs special handling. We'll end up with a
        // value without the array type, but that should not be a problem.
        while (constType.isArray())
        {
            constType.toArrayElementType();
        }
        return CreateZeroNode(constType);
    }

    TIntermSequence *arguments = new TIntermSequence();

    if (type.isArray())
    {
        TType elementType(type);
        elementType.toArrayElementType();

        size_t arraySize = type.getOutermostArraySize();
        for (size_t i = 0; i < arraySize; ++i)
        {
            arguments->push_back(CreateZeroNode(elementType));
        }
    }
    else
    {
        ASSERT(type.getBasicType() == EbtStruct);

        TStructure *structure = type.getStruct();
        for (const auto &field : structure->fields())
        {
            arguments->push_back(CreateZeroNode(*field->type()));
        }
    }

    return TIntermAggregate::CreateConstructor(constType, arguments);
}
void ScalarizeVecAndMatConstructorArgs::scalarizeArgs(
    TIntermAggregate *aggregate, bool scalarizeVector, bool scalarizeMatrix)
{
    ASSERT(aggregate);
    int size = 0;
    switch (aggregate->getOp())
    {
      case EOpConstructVec2:
      case EOpConstructBVec2:
      case EOpConstructIVec2:
        size = 2;
        break;
      case EOpConstructVec3:
      case EOpConstructBVec3:
      case EOpConstructIVec3:
        size = 3;
        break;
      case EOpConstructVec4:
      case EOpConstructBVec4:
      case EOpConstructIVec4:
      case EOpConstructMat2:
        size = 4;
        break;
      case EOpConstructMat2x3:
      case EOpConstructMat3x2:
        size = 6;
        break;
      case EOpConstructMat2x4:
      case EOpConstructMat4x2:
        size = 8;
        break;
      case EOpConstructMat3:
        size = 9;
        break;
      case EOpConstructMat3x4:
      case EOpConstructMat4x3:
        size = 12;
        break;
      case EOpConstructMat4:
        size = 16;
        break;
      default:
        break;
    }
    TIntermSequence *sequence = aggregate->getSequence();
    TIntermSequence original(*sequence);
    sequence->clear();
    for (size_t ii = 0; ii < original.size(); ++ii)
    {
        ASSERT(size > 0);
        TIntermTyped *node = original[ii]->getAsTyped();
        ASSERT(node);
        TString varName = createTempVariable(node);
        if (node->isScalar())
        {
            TIntermSymbol *symbolNode =
                new TIntermSymbol(-1, varName, node->getType());
            sequence->push_back(symbolNode);
            size--;
        }
        else if (node->isVector())
        {
            if (scalarizeVector)
            {
                int repeat = std::min(size, node->getNominalSize());
                size -= repeat;
                for (int index = 0; index < repeat; ++index)
                {
                    TIntermSymbol *symbolNode =
                        new TIntermSymbol(-1, varName, node->getType());
                    TIntermBinary *newNode = ConstructVectorIndexBinaryNode(
                        symbolNode, index);
                    sequence->push_back(newNode);
                }
            }
            else
            {
                TIntermSymbol *symbolNode =
                    new TIntermSymbol(-1, varName, node->getType());
                sequence->push_back(symbolNode);
                size -= node->getNominalSize();
            }
        }
        else
        {
            ASSERT(node->isMatrix());
            if (scalarizeMatrix)
            {
                int colIndex = 0, rowIndex = 0;
                int repeat = std::min(size, node->getCols() * node->getRows());
                size -= repeat;
                while (repeat > 0)
                {
                    TIntermSymbol *symbolNode =
                        new TIntermSymbol(-1, varName, node->getType());
                    TIntermBinary *newNode = ConstructMatrixIndexBinaryNode(
                        symbolNode, colIndex, rowIndex);
                    sequence->push_back(newNode);
                    rowIndex++;
                    if (rowIndex >= node->getRows())
                    {
                        rowIndex = 0;
                        colIndex++;
                    }
                    repeat--;
                }
            }
            else
            {
                TIntermSymbol *symbolNode =
                    new TIntermSymbol(-1, varName, node->getType());
                sequence->push_back(symbolNode);
                size -= node->getCols() * node->getRows();
            }
        }
    }
}
Пример #26
0
bool TSamplerTraverser::traverseAggregate( bool preVisit, TIntermAggregate *node, TIntermTraverser *it)
{
   TSamplerTraverser* sit = static_cast<TSamplerTraverser*>(it);
   TInfoSink &infoSink = sit->infoSink;

   if (sit->abort)
      return false;

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

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

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

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

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

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

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


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

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

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

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

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

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

      default: 
         break;
      }
   }


   return !(sit->abort);
}
Пример #27
0
void TLValueTrackingTraverser::traverseAggregate(TIntermAggregate *node)
{
    bool visit = true;

    TIntermSequence *sequence = node->getSequence();
    if (node->getOp() == EOpPrototype)
    {
        addToFunctionMap(node->getFunctionSymbolInfo()->getNameObj(), sequence);
    }

    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
        {
            // 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);
                }

                ++paramIndex;
            }

            setInFunctionCallOutParameter(false);
        }

        decrementDepth();
    }

    if (visit && postVisit)
        visitAggregate(PostVisit, node);
}
Пример #28
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;
}