Esempio n. 1
0
//
// Do size checking for an array type's size.
//
// Returns true if there was an error.
//
bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
{
    TIntermConstantUnion* constant = expr->getAsConstantUnion();
    if (constant == 0 || constant->getBasicType() != EbtInt) {
        error(line, "array size must be a constant integer expression", "", "");
        return true;
    }

    size = constant->getUnionArrayPointer()->getIConst();

    if (size <= 0) {
        error(line, "array size must be a positive integer", "", "");
        size = 1;
        return true;
    }

    return false;
}
Esempio n. 2
0
//
// This function returns the tree representation for the vector field(s) being accessed from contant vector.
// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of 
// a constant matrix.
//
TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc line)
{
    TIntermTyped* typedNode;
    TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();

    ConstantUnion *unionArray;
    if (tempConstantNode) {
        unionArray = tempConstantNode->getUnionArrayPointer();
        ASSERT(unionArray);

        if (!unionArray) {
            return node;
        }
    } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
        error(line, "Cannot offset into the vector", "Error");
        recover();

        return 0;
    }

    ConstantUnion* constArray = new ConstantUnion[fields.num];

    for (int i = 0; i < fields.num; i++) {
        if (fields.offsets[i] >= node->getType().getObjectSize()) {
            std::stringstream extraInfoStream;
            extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'";
            std::string extraInfo = extraInfoStream.str();
            error(line, "", "[", extraInfo.c_str());
            recover();
            fields.offsets[i] = 0;
        }
        
        constArray[i] = unionArray[fields.offsets[i]];

    } 
    typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
    return typedNode;
}
Esempio n. 3
0
//
// This function returns the tree representation for the vector field(s) being accessed from contant vector.
// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of 
// a constant matrix.
//
TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc line)
{
    TIntermTyped* typedNode;
    TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();

    ConstantUnion *unionArray;
    if (tempConstantNode) {
        unionArray = tempConstantNode->getUnionArrayPointer();

        if (!unionArray) {  // this error message should never be raised
            infoSink.info.message(EPrefixInternalError, "ConstantUnion not initialized in addConstVectorNode function", line);
            recover();

            return node;
        }
    } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
        error(line, "Cannot offset into the vector", "Error", "");
        recover();

        return 0;
    }

    ConstantUnion* constArray = new ConstantUnion[fields.num];

    for (int i = 0; i < fields.num; i++) {
        if (fields.offsets[i] >= node->getType().getObjectSize()) {
            error(line, "", "[", "vector field selection out of range '%d'", fields.offsets[i]);
            recover();
            fields.offsets[i] = 0;
        }
        
        constArray[i] = unionArray[fields.offsets[i]];

    } 
    typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
    return typedNode;
}
Esempio n. 4
0
//
// This function returns the column being accessed from a constant matrix. The values are retrieved from
// the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input 
// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a 
// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
//
TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line)
{
    TIntermTyped* typedNode;
    TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();

    if (index >= node->getType().getNominalSize()) {
        error(line, "", "[", "matrix field selection out of range '%d'", index);
        recover();
        index = 0;
    }

    if (tempConstantNode) {
         ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
         int size = tempConstantNode->getType().getNominalSize();
         typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
    } else {
        error(line, "Cannot offset into the matrix", "Error", "");
        recover();

        return 0;
    }

    return typedNode;
}
Esempio n. 5
0
bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode)
{
    if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
    {
        // NOTE: we do not determine static use for individual blocks of an array
        TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
        ASSERT(blockNode);

        TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
        ASSERT(constantUnion);

        const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
        InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
        ASSERT(namedBlock);
        namedBlock->staticUse = true;

        unsigned int fieldIndex = constantUnion->getUConst(0);
        ASSERT(fieldIndex < namedBlock->fields.size());
        namedBlock->fields[fieldIndex].staticUse = true;
        return false;
    }

    return true;
}
Esempio n. 6
0
//
// Connect two nodes with a new parent that does a binary operation on the nodes.
//
// Returns the added node.
//
TIntermTyped *TIntermediate::addBinaryMath(
    TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
{
    switch (op)
    {
      case EOpEqual:
      case EOpNotEqual:
        if (left->isArray())
            return NULL;
        break;
      case EOpLessThan:
      case EOpGreaterThan:
      case EOpLessThanEqual:
      case EOpGreaterThanEqual:
        if (left->isMatrix() || left->isArray() || left->isVector() ||
            left->getBasicType() == EbtStruct)
        {
            return NULL;
        }
        break;
      case EOpLogicalOr:
      case EOpLogicalXor:
      case EOpLogicalAnd:
        if (left->getBasicType() != EbtBool ||
            left->isMatrix() || left->isArray() || left->isVector())
        {
            return NULL;
        }
        break;
      case EOpAdd:
      case EOpSub:
      case EOpDiv:
      case EOpMul:
        if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
            return NULL;
      default:
        break;
    }

    if (left->getBasicType() != right->getBasicType())
    {
        return NULL;
    }

    //
    // Need a new node holding things together then.  Make
    // one and promote it to the right type.
    //
    TIntermBinary *node = new TIntermBinary(op);
    node->setLine(line);

    node->setLeft(left);
    node->setRight(right);
    if (!node->promote(mInfoSink))
        return NULL;

    //
    // See if we can fold constants.
    //
    TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
    TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
    if (leftTempConstant && rightTempConstant)
    {
        TIntermTyped *typedReturnNode =
            leftTempConstant->fold(node->getOp(), rightTempConstant, mInfoSink);

        if (typedReturnNode)
            return typedReturnNode;
    }

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

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

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

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

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

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

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

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

        if (newChild)
            return newChild;
    }

    return node;
}
Esempio n. 8
0
bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
{
    TInfoSinkBase& out = sink;

    OutputTreeText(out, node, mDepth);

    switch (node->getOp())
    {
    case EOpAssign:
        out << "move second child to first child";
        break;
    case EOpInitialize:
        out << "initialize first child with second child";
        break;
    case EOpAddAssign:
        out << "add second child into first child";
        break;
    case EOpSubAssign:
        out << "subtract second child into first child";
        break;
    case EOpMulAssign:
        out << "multiply second child into first child";
        break;
    case EOpVectorTimesMatrixAssign:
        out << "matrix mult second child into first child";
        break;
    case EOpVectorTimesScalarAssign:
        out << "vector scale second child into first child";
        break;
    case EOpMatrixTimesScalarAssign:
        out << "matrix scale second child into first child";
        break;
    case EOpMatrixTimesMatrixAssign:
        out << "matrix mult second child into first child";
        break;
    case EOpDivAssign:
        out << "divide second child into first child";
        break;
    case EOpIModAssign:
        out << "modulo second child into first child";
        break;
    case EOpBitShiftLeftAssign:
        out << "bit-wise shift first child left by second child";
        break;
    case EOpBitShiftRightAssign:
        out << "bit-wise shift first child right by second child";
        break;
    case EOpBitwiseAndAssign:
        out << "bit-wise and second child into first child";
        break;
    case EOpBitwiseXorAssign:
        out << "bit-wise xor second child into first child";
        break;
    case EOpBitwiseOrAssign:
        out << "bit-wise or second child into first child";
        break;

    case EOpIndexDirect:
        out << "direct index";
        break;
    case EOpIndexIndirect:
        out << "indirect index";
        break;
    case EOpIndexDirectStruct:
        out << "direct index for structure";
        break;
    case EOpIndexDirectInterfaceBlock:
        out << "direct index for interface block";
        break;
    case EOpVectorSwizzle:
        out << "vector swizzle";
        break;

    case EOpAdd:
        out << "add";
        break;
    case EOpSub:
        out << "subtract";
        break;
    case EOpMul:
        out << "component-wise multiply";
        break;
    case EOpDiv:
        out << "divide";
        break;
    case EOpIMod:
        out << "modulo";
        break;
    case EOpBitShiftLeft:
        out << "bit-wise shift left";
        break;
    case EOpBitShiftRight:
        out << "bit-wise shift right";
        break;
    case EOpBitwiseAnd:
        out << "bit-wise and";
        break;
    case EOpBitwiseXor:
        out << "bit-wise xor";
        break;
    case EOpBitwiseOr:
        out << "bit-wise or";
        break;

    case EOpEqual:
        out << "Compare Equal";
        break;
    case EOpNotEqual:
        out << "Compare Not Equal";
        break;
    case EOpLessThan:
        out << "Compare Less Than";
        break;
    case EOpGreaterThan:
        out << "Compare Greater Than";
        break;
    case EOpLessThanEqual:
        out << "Compare Less Than or Equal";
        break;
    case EOpGreaterThanEqual:
        out << "Compare Greater Than or Equal";
        break;

    case EOpVectorTimesScalar:
        out << "vector-scale";
        break;
    case EOpVectorTimesMatrix:
        out << "vector-times-matrix";
        break;
    case EOpMatrixTimesVector:
        out << "matrix-times-vector";
        break;
    case EOpMatrixTimesScalar:
        out << "matrix-scale";
        break;
    case EOpMatrixTimesMatrix:
        out << "matrix-multiply";
        break;

    case EOpLogicalOr:
        out << "logical-or";
        break;
    case EOpLogicalXor:
        out << "logical-xor";
        break;
    case EOpLogicalAnd:
        out << "logical-and";
        break;
    default:
        out << "<unknown op>";
    }

    out << " (" << node->getCompleteString() << ")";

    out << "\n";

    // Special handling for direct indexes. Because constant
    // unions are not aware they are struct indexes, treat them
    // here where we have that contextual knowledge.
    if (node->getOp() == EOpIndexDirectStruct ||
            node->getOp() == EOpIndexDirectInterfaceBlock)
    {
        mDepth++;
        node->getLeft()->traverse(this);
        mDepth--;

        TIntermConstantUnion *intermConstantUnion = node->getRight()->getAsConstantUnion();
        ASSERT(intermConstantUnion);

        OutputTreeText(out, intermConstantUnion, mDepth + 1);

        // The following code finds the field name from the constant union
        const ConstantUnion *constantUnion = intermConstantUnion->getUnionArrayPointer();
        const TStructure *structure = node->getLeft()->getType().getStruct();
        const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock();
        ASSERT(structure || interfaceBlock);

        const TFieldList &fields = structure ? structure->fields() : interfaceBlock->fields();

        const TField *field = fields[constantUnion->getIConst()];

        out << constantUnion->getIConst() << " (field '" << field->name() << "')";

        return false;
    }

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

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

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

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

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

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

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

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

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

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

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

        if (newChild)
            return newChild;
    }

    return node;
}
Esempio n. 10
0
//
// Connect two nodes with a new parent that does a binary operation on the nodes.
//
// Returns the added node.
//
TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TSymbolTable& symbolTable)
{
    switch (op) {
        case EOpEqual:
        case EOpNotEqual:
            if (left->isArray())
                return 0;
            break;
        case EOpLessThan:
        case EOpGreaterThan:
        case EOpLessThanEqual:
        case EOpGreaterThanEqual:
            if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) {
                return 0;
            }
            break;
        case EOpLogicalOr:
        case EOpLogicalXor:
        case EOpLogicalAnd:
            if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) {
                return 0;
            }
            break;
        case EOpAdd:
        case EOpSub:
        case EOpDiv:
        case EOpMul:
            if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
                return 0;
        default: break;
    }

    //
    // First try converting the children to compatible types.
    //
    if (left->getType().getStruct() && right->getType().getStruct()) {
        if (left->getType() != right->getType())
            return 0;
    } else {
        TIntermTyped* child = addConversion(op, left->getType(), right);
        if (child)
            right = child;
        else {
            child = addConversion(op, right->getType(), left);
            if (child)
                left = child;
            else
                return 0;
        }
    }

    //
    // Need a new node holding things together then.  Make
    // one and promote it to the right type.
    //
    TIntermBinary* node = new TIntermBinary(op);
    if (line == 0)
        line = right->getLine();
    node->setLine(line);

    node->setLeft(left);
    node->setRight(right);
    if (!node->promote(infoSink))
        return 0;

    //
    // See if we can fold constants.
    //
    TIntermTyped* typedReturnNode = 0;
    TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
    TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
    if (leftTempConstant && rightTempConstant) {
        typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);

        if (typedReturnNode)
            return typedReturnNode;
    }

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

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

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

        ConstantUnion* tempConstArray = 0;
        TIntermConstantUnion *tempNode;

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

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

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

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

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

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

                return tempNode;

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

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

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

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

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

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

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

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

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

                return tempNode;

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

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

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

                return tempNode;

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

        return tempNode;
    } else {
        //
        // Do unary operations
        //
        TIntermConstantUnion *newNode = 0;
        ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
        for (int i = 0; i < objectSize; i++) {
            switch(op) {
                case EOpNegative:
                    switch (getType().getBasicType()) {
                        case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
                        case EbtInt:   tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
                        default:
                            infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
                            return 0;
                    }
                    break;
                case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
                    switch (getType().getBasicType()) {
                        case EbtBool:  tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
                        default:
                            infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
                            return 0;
                    }
                    break;
                default:
                    return 0;
            }
        }
        newNode = new TIntermConstantUnion(tempConstArray, getType());
        newNode->setLine(getLine());
        return newNode;
    }
}
Esempio n. 12
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;
}
Esempio n. 13
0
//
// Do constant folding for an aggregate node that has all its children
// as constants and an operator that requires constant folding.
// 
TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
{
    if (! areAllChildConst(aggrNode))
        return aggrNode;

    if (aggrNode->isConstructor())
        return foldConstructor(aggrNode);

    TIntermSequence& children = aggrNode->getSequence();

    // First, see if this is an operation to constant fold, kick out if not,
    // see what size the result is if so.

    bool componentwise = false;  // will also say componentwise if a scalar argument gets repeated to make per-component results
    int objectSize;
    switch (aggrNode->getOp()) {
    case EOpAtan:
    case EOpPow:
    case EOpMin:
    case EOpMax:
    case EOpMix:
    case EOpClamp:
    case EOpLessThan:
    case EOpGreaterThan:
    case EOpLessThanEqual:
    case EOpGreaterThanEqual:
    case EOpVectorEqual:
    case EOpVectorNotEqual:
        componentwise = true;
        objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
        break;
    case EOpCross:
    case EOpReflect:
    case EOpRefract:
    case EOpFaceForward:
        objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents();
        break;
    case EOpDistance:
    case EOpDot:
        objectSize = 1;
        break;
    case EOpOuterProduct:
        objectSize = children[0]->getAsTyped()->getType().getVectorSize() *
                     children[1]->getAsTyped()->getType().getVectorSize();
        break;
    case EOpStep:
        componentwise = true;
        objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
                              children[1]->getAsTyped()->getType().getVectorSize());
        break;
    case EOpSmoothStep:
        componentwise = true;
        objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
                              children[2]->getAsTyped()->getType().getVectorSize());
        break;
    default:
        return aggrNode;
    }
    TConstUnionArray newConstArray(objectSize);

    TVector<TConstUnionArray> childConstUnions;
    for (unsigned int arg = 0; arg < children.size(); ++arg)
        childConstUnions.push_back(children[arg]->getAsConstantUnion()->getConstArray());

    // Second, do the actual folding

    bool isFloatingPoint = children[0]->getAsTyped()->getBasicType() == EbtFloat ||
                           children[0]->getAsTyped()->getBasicType() == EbtDouble;
    bool isSigned = children[0]->getAsTyped()->getBasicType() == EbtInt;
    if (componentwise) {
        for (int comp = 0; comp < objectSize; comp++) {

            // some arguments are scalars instead of matching vectors; simulate a smear
            int arg0comp = std::min(comp, children[0]->getAsTyped()->getType().getVectorSize() - 1);
            int arg1comp = 0;
            if (children.size() > 1)
                arg1comp = std::min(comp, children[1]->getAsTyped()->getType().getVectorSize() - 1);
            int arg2comp = 0;
            if (children.size() > 2)
                arg2comp = std::min(comp, children[2]->getAsTyped()->getType().getVectorSize() - 1);

            switch (aggrNode->getOp()) {
            case EOpAtan:
                newConstArray[comp].setDConst(atan2(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
                break;
            case EOpPow:
                newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
                break;
            case EOpMin:
                if (isFloatingPoint)
                    newConstArray[comp].setDConst(std::min(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
                else if (isSigned)
                    newConstArray[comp].setIConst(std::min(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
                else
                    newConstArray[comp].setUConst(std::min(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
                break;
            case EOpMax:
                if (isFloatingPoint)
                    newConstArray[comp].setDConst(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
                else if (isSigned)
                    newConstArray[comp].setIConst(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
                else
                    newConstArray[comp].setUConst(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
                break;
            case EOpClamp:
                if (isFloatingPoint)
                    newConstArray[comp].setDConst(std::min(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()), 
                                                                                                               childConstUnions[2][arg2comp].getDConst()));
                else if (isSigned)
                    newConstArray[comp].setIConst(std::min(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()), 
                                                                                                               childConstUnions[2][arg2comp].getIConst()));
                else
                    newConstArray[comp].setUConst(std::min(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()), 
                                                                                                               childConstUnions[2][arg2comp].getUConst()));
                break;
            case EOpLessThan:
                newConstArray[comp].setBConst(childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]);
                break;
            case EOpGreaterThan:
                newConstArray[comp].setBConst(childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]);
                break;
            case EOpLessThanEqual:
                newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]));
                break;
            case EOpGreaterThanEqual:
                newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]));
                break;
            case EOpVectorEqual:
                newConstArray[comp].setBConst(childConstUnions[0][arg0comp] == childConstUnions[1][arg1comp]);
                break;
            case EOpVectorNotEqual:
                newConstArray[comp].setBConst(childConstUnions[0][arg0comp] != childConstUnions[1][arg1comp]);
                break;
            case EOpMix:
                if (children[2]->getAsTyped()->getBasicType() == EbtBool)
                    newConstArray[comp].setDConst(childConstUnions[2][arg2comp].getBConst() ? childConstUnions[1][arg1comp].getDConst() :
                                                                                              childConstUnions[0][arg0comp].getDConst());
                else
                    newConstArray[comp].setDConst(childConstUnions[0][arg0comp].getDConst() * (1.0 - childConstUnions[2][arg2comp].getDConst()) +
                                                  childConstUnions[1][arg1comp].getDConst() *        childConstUnions[2][arg2comp].getDConst());
                break;
            case EOpStep:
                newConstArray[comp].setDConst(childConstUnions[1][arg1comp].getDConst() < childConstUnions[0][arg0comp].getDConst() ? 0.0 : 1.0);
                break;
            case EOpSmoothStep:
            {
                double t = (childConstUnions[2][arg2comp].getDConst() - childConstUnions[0][arg0comp].getDConst()) / 
                           (childConstUnions[1][arg1comp].getDConst() - childConstUnions[0][arg0comp].getDConst());
                if (t < 0.0)
                    t = 0.0;
                if (t > 1.0)
                    t = 1.0;
                newConstArray[comp].setDConst(t * t * (3.0 - 2.0 * t));
                break;
            }
            default:
                return aggrNode;
            }
        }
    } else {
        // Non-componentwise...

        int numComps = children[0]->getAsConstantUnion()->getType().computeNumComponents();
        double dot;

        switch (aggrNode->getOp()) {
        case EOpDistance:
        {
            double sum = 0.0;
            for (int comp = 0; comp < numComps; ++comp) {
                double diff = childConstUnions[1][comp].getDConst() - childConstUnions[0][comp].getDConst();
                sum += diff * diff;
            }
            newConstArray[0].setDConst(sqrt(sum));
            break;
        }
        case EOpDot:
            newConstArray[0].setDConst(childConstUnions[0].dot(childConstUnions[1]));
            break;
        case EOpCross:
            newConstArray[0] = childConstUnions[0][1] * childConstUnions[1][2] - childConstUnions[0][2] * childConstUnions[1][1];
            newConstArray[1] = childConstUnions[0][2] * childConstUnions[1][0] - childConstUnions[0][0] * childConstUnions[1][2];
            newConstArray[2] = childConstUnions[0][0] * childConstUnions[1][1] - childConstUnions[0][1] * childConstUnions[1][0];
            break;
        case EOpFaceForward:
            // If dot(Nref, I) < 0 return N, otherwise return –N:  Arguments are (N, I, Nref).
            dot = childConstUnions[1].dot(childConstUnions[2]);
            for (int comp = 0; comp < numComps; ++comp) {
                if (dot < 0.0)
                    newConstArray[comp] = childConstUnions[0][comp];
                else
                    newConstArray[comp].setDConst(-childConstUnions[0][comp].getDConst());
            }
            break;
        case EOpReflect:
            // I – 2 * dot(N, I) * N:  Arguments are (I, N).
            dot = childConstUnions[0].dot(childConstUnions[1]);
            dot *= 2.0;
            for (int comp = 0; comp < numComps; ++comp)
                newConstArray[comp].setDConst(childConstUnions[0][comp].getDConst() - dot * childConstUnions[1][comp].getDConst());
            break;
        case EOpRefract:
        {
            // Arguments are (I, N, eta).
            // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
            // if (k < 0.0)
            //     return dvec(0.0)
            // else
            //     return eta * I - (eta * dot(N, I) + sqrt(k)) * N
            dot = childConstUnions[0].dot(childConstUnions[1]);
            double eta = childConstUnions[2][0].getDConst();
            double k = 1.0 - eta * eta * (1.0 - dot * dot);
            if (k < 0.0) {
                for (int comp = 0; comp < numComps; ++comp)
                    newConstArray[comp].setDConst(0.0);
            } else {
                for (int comp = 0; comp < numComps; ++comp)
                    newConstArray[comp].setDConst(eta * childConstUnions[0][comp].getDConst() - (eta * dot + sqrt(k)) * childConstUnions[1][comp].getDConst());
            }
            break;
        }
        case EOpOuterProduct:
        {
            int numRows = numComps;
            int numCols = children[1]->getAsConstantUnion()->getType().computeNumComponents();
            for (int row = 0; row < numRows; ++row)
                for (int col = 0; col < numCols; ++col)
                    newConstArray[col * numRows + row] = childConstUnions[0][row] * childConstUnions[1][col];
            break;
        }
        default:
            return aggrNode;
        }
    }

    TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, aggrNode->getType());
    newNode->getWritableType().getQualifier().storage = EvqConst;
    newNode->setLoc(aggrNode->getLoc());

    return newNode;
}
Esempio n. 14
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;
}
Esempio n. 15
0
//
// Do folding between a pair of nodes
//
TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode)
{
    TConstUnion *unionArray = getUnionArrayPointer();
    int objectSize = getType().getObjectSize();
    TConstUnion* newConstArray = 0;

    // For most cases, the return type matches the argument type, so set that
    // up and just code to exceptions below.
    TType returnType;
    returnType.shallowCopy(getType());

    //
    // A pair of nodes is to be folded together
    //

    TIntermConstantUnion *node = constantNode->getAsConstantUnion();
    TConstUnion *rightUnionArray = node->getUnionArrayPointer();

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

    int index = 0;
    bool boolNodeFlag = false;
    switch(op) {
    case EOpAdd:
        newConstArray = new TConstUnion[objectSize];
        for (int i = 0; i < objectSize; i++)
            newConstArray[i] = unionArray[i] + rightUnionArray[i];
        break;
    case EOpSub:
        newConstArray = new TConstUnion[objectSize];
        for (int i = 0; i < objectSize; i++)
            newConstArray[i] = unionArray[i] - rightUnionArray[i];
        break;

    case EOpMul:
    case EOpVectorTimesScalar:
    case EOpMatrixTimesScalar:
        newConstArray = new TConstUnion[objectSize];
        for (int i = 0; i < objectSize; i++)
            newConstArray[i] = unionArray[i] * rightUnionArray[i];
        break;
    case EOpMatrixTimesMatrix:
        newConstArray = new TConstUnion[getMatrixRows() * node->getMatrixCols()];
        for (int row = 0; row < getMatrixRows(); row++) {
            for (int column = 0; column < node->getMatrixCols(); column++) {
                double sum = 0.0f;
                for (int i = 0; i < node->getMatrixRows(); i++)
                    sum += unionArray[i * getMatrixRows() + row].getDConst() * rightUnionArray[column * node->getMatrixRows() + i].getDConst();
                newConstArray[column * getMatrixRows() + row].setDConst(sum);
            }
        }
        returnType.shallowCopy(TType(getType().getBasicType(), EvqConst, 0, getMatrixRows(), node->getMatrixCols()));
        break;
    case EOpDiv:
        newConstArray = new TConstUnion[objectSize];
        for (int i = 0; i < objectSize; i++) {
            switch (getType().getBasicType()) {
            case EbtDouble:
            case EbtFloat:
                newConstArray[i].setDConst(unionArray[i].getDConst() / rightUnionArray[i].getDConst());
                break;

            case EbtInt:
                if (rightUnionArray[i] == 0) {
                    newConstArray[i].setIConst(0xEFFFFFFF);
                } else
                    newConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
                break;

            case EbtUint:
                if (rightUnionArray[i] == 0) {
                    newConstArray[i].setUConst(0xFFFFFFFF);
                } else
                    newConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst());
                break;
            default:
                return 0;
            }
        }
        break;

    case EOpMatrixTimesVector:
        newConstArray = new TConstUnion[getMatrixRows()];
        for (int i = 0; i < getMatrixRows(); i++) {
            double sum = 0.0f;
            for (int j = 0; j < node->getVectorSize(); j++) {
                sum += unionArray[j*getMatrixRows() + i].getDConst() * rightUnionArray[j].getDConst();
            }
            newConstArray[i].setDConst(sum);
        }

        returnType.shallowCopy(TType(getBasicType(), EvqConst, getMatrixRows()));
        break;

    case EOpVectorTimesMatrix:
        newConstArray = new TConstUnion[node->getMatrixCols()];
        for (int i = 0; i < node->getMatrixCols(); i++) {
            double sum = 0.0f;
            for (int j = 0; j < getVectorSize(); j++)
                sum += unionArray[j].getDConst() * rightUnionArray[i*node->getMatrixRows() + j].getDConst();
            newConstArray[i].setDConst(sum);
        }

        returnType.shallowCopy(TType(getBasicType(), EvqConst, node->getMatrixCols()));
        break;

    case EOpMod:
        newConstArray = new TConstUnion[objectSize];
        for (int i = 0; i < objectSize; i++)
            newConstArray[i] = unionArray[i] % rightUnionArray[i];
        break;

    case EOpRightShift:
        newConstArray = new TConstUnion[objectSize];
        for (int i = 0; i < objectSize; i++)
            newConstArray[i] = unionArray[i] >> rightUnionArray[i];
        break;

    case EOpLeftShift:
        newConstArray = new TConstUnion[objectSize];
        for (int i = 0; i < objectSize; i++)
            newConstArray[i] = unionArray[i] << rightUnionArray[i];
        break;

    case EOpAnd:
        newConstArray = new TConstUnion[objectSize];
        for (int i = 0; i < objectSize; i++)
            newConstArray[i] = unionArray[i] & rightUnionArray[i];
        break;
    case EOpInclusiveOr:
        newConstArray = new TConstUnion[objectSize];
        for (int i = 0; i < objectSize; i++)
            newConstArray[i] = unionArray[i] | rightUnionArray[i];
        break;
    case EOpExclusiveOr:
        newConstArray = new TConstUnion[objectSize];
        for (int i = 0; i < objectSize; i++)
            newConstArray[i] = unionArray[i] ^ rightUnionArray[i];
        break;

    case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
        newConstArray = new TConstUnion[objectSize];
        for (int i = 0; i < objectSize; i++)
            newConstArray[i] = unionArray[i] && rightUnionArray[i];
        break;

    case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
        newConstArray = new TConstUnion[objectSize];
        for (int i = 0; i < objectSize; i++)
            newConstArray[i] = unionArray[i] || rightUnionArray[i];
        break;

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

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

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

        newConstArray = new TConstUnion[1];
        newConstArray->setBConst(! boolNodeFlag);
        returnType.shallowCopy(TType(EbtBool, EvqConst));
        break;

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

        newConstArray = new TConstUnion[1];
        newConstArray->setBConst(! boolNodeFlag);
        returnType.shallowCopy(TType(EbtBool, EvqConst));
        break;

    default:
        return 0;
    }

    TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
    newNode->setLoc(getLoc());

    return newNode;
}
Esempio n. 16
0
//
// The fold functions see if an operation on a constant can be done in place,
// without generating run-time code.
//
// Returns the node to keep using, which may or may not be the node passed in.
//
TIntermTyped *TIntermConstantUnion::fold(
    TOperator op, TIntermTyped *constantNode, TInfoSink &infoSink)
{
    ConstantUnion *unionArray = getUnionArrayPointer();

    if (!unionArray)
        return NULL;

    size_t objectSize = getType().getObjectSize();

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

        if (!rightUnionArray)
            return NULL;

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

        ConstantUnion *tempConstArray = NULL;
        TIntermConstantUnion *tempNode;

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

          case EOpMul:
          case EOpVectorTimesScalar:
          case EOpMatrixTimesScalar:
            tempConstArray = new ConstantUnion[objectSize];
            for (size_t i = 0; i < objectSize; i++)
                tempConstArray[i] = unionArray[i] * rightUnionArray[i];
            break;

          case EOpMatrixTimesMatrix:
            {
                if (getType().getBasicType() != EbtFloat ||
                    node->getBasicType() != EbtFloat)
                {
                    infoSink.info.message(
                        EPrefixInternalError, getLine(),
                        "Constant Folding cannot be done for matrix multiply");
                    return NULL;
                }

                const int leftCols = getCols();
                const int leftRows = getRows();
                const int rightCols = constantNode->getType().getCols();
                const int rightRows = constantNode->getType().getRows();
                const int resultCols = rightCols;
                const int resultRows = leftRows;

                tempConstArray = new ConstantUnion[resultCols*resultRows];
                for (int row = 0; row < resultRows; row++)
                {
                    for (int column = 0; column < resultCols; column++)
                    {
                        tempConstArray[resultRows * column + row].setFConst(0.0f);
                        for (int i = 0; i < leftCols; i++)
                        {
                            tempConstArray[resultRows * column + row].setFConst(
                                tempConstArray[resultRows * column + row].getFConst() +
                                unionArray[i * leftRows + row].getFConst() *
                                rightUnionArray[column * rightRows + i].getFConst());
                        }
                    }
                }

                // update return type for matrix product
                returnType.setPrimarySize(resultCols);
                returnType.setSecondarySize(resultRows);
            }
            break;

          case EOpDiv:
            {
                tempConstArray = new ConstantUnion[objectSize];
                for (size_t i = 0; i < objectSize; i++)
                {
                    switch (getType().getBasicType())
                    {
                      case EbtFloat:
                        if (rightUnionArray[i] == 0.0f)
                        {
                            infoSink.info.message(
                                EPrefixWarning, getLine(),
                                "Divide by zero error during constant folding");
                            tempConstArray[i].setFConst(
                                unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX);
                        }
                        else
                        {
                            tempConstArray[i].setFConst(
                                unionArray[i].getFConst() /
                                rightUnionArray[i].getFConst());
                        }
                        break;

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

                      case EbtUInt:
                        if (rightUnionArray[i] == 0)
                        {
                            infoSink.info.message(
                                EPrefixWarning, getLine(),
                                "Divide by zero error during constant folding");
                            tempConstArray[i].setUConst(UINT_MAX);
                        }
                        else
                        {
                            tempConstArray[i].setUConst(
                                unionArray[i].getUConst() /
                                rightUnionArray[i].getUConst());
                        }
                        break;

                      default:
                        infoSink.info.message(
                            EPrefixInternalError, getLine(),
                            "Constant folding cannot be done for \"/\"");
                        return NULL;
                    }
                }
            }
            break;

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

                const int matrixCols = getCols();
                const int matrixRows = getRows();

                tempConstArray = new ConstantUnion[matrixRows];

                for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
                {
                    tempConstArray[matrixRow].setFConst(0.0f);
                    for (int col = 0; col < matrixCols; col++)
                    {
                        tempConstArray[matrixRow].setFConst(
                            tempConstArray[matrixRow].getFConst() +
                            unionArray[col * matrixRows + matrixRow].getFConst() *
                            rightUnionArray[col].getFConst());
                    }
                }

                returnType = node->getType();
                returnType.setPrimarySize(matrixRows);

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

                return tempNode;
            }

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

                const int matrixCols = constantNode->getType().getCols();
                const int matrixRows = constantNode->getType().getRows();

                tempConstArray = new ConstantUnion[matrixCols];

                for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++)
                {
                    tempConstArray[matrixCol].setFConst(0.0f);
                    for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
                    {
                        tempConstArray[matrixCol].setFConst(
                            tempConstArray[matrixCol].getFConst() +
                            unionArray[matrixRow].getFConst() *
                            rightUnionArray[matrixCol * matrixRows + matrixRow].getFConst());
                    }
                }

                returnType.setPrimarySize(matrixCols);
            }
            break;

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

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

          case EOpLogicalXor:
            {
                tempConstArray = new ConstantUnion[objectSize];
                for (size_t i = 0; i < objectSize; i++)
                {
                    switch (getType().getBasicType())
                    {
                      case EbtBool:
                        tempConstArray[i].setBConst(
                            unionArray[i] == rightUnionArray[i] ? false : true);
                        break;
                      default:
                        UNREACHABLE();
                        break;
                    }
                }
            }
            break;

          case EOpLessThan:
            ASSERT(objectSize == 1);
            tempConstArray = new ConstantUnion[1];
            tempConstArray->setBConst(*unionArray < *rightUnionArray);
            returnType = TType(EbtBool, EbpUndefined, EvqConst);
            break;

          case EOpGreaterThan:
            ASSERT(objectSize == 1);
            tempConstArray = new ConstantUnion[1];
            tempConstArray->setBConst(*unionArray > *rightUnionArray);
            returnType = TType(EbtBool, EbpUndefined, EvqConst);
            break;

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

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

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

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

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

            return tempNode;

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

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

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

            return tempNode;

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

        return tempNode;
    }
    else
    {
        //
        // Do unary operations
        //
        TIntermConstantUnion *newNode = 0;
        ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
        for (size_t i = 0; i < objectSize; i++)
        {
            switch(op)
            {
              case EOpNegative:
                switch (getType().getBasicType())
                {
                  case EbtFloat:
                    tempConstArray[i].setFConst(-unionArray[i].getFConst());
                    break;
                  case EbtInt:
                    tempConstArray[i].setIConst(-unionArray[i].getIConst());
                    break;
                  case EbtUInt:
                    tempConstArray[i].setUConst(static_cast<unsigned int>(
                        -static_cast<int>(unionArray[i].getUConst())));
                    break;
                  default:
                    infoSink.info.message(
                        EPrefixInternalError, getLine(),
                        "Unary operation not folded into constant");
                    return NULL;
                }
                break;

              case EOpPositive:
                switch (getType().getBasicType())
                {
                  case EbtFloat:
                    tempConstArray[i].setFConst(unionArray[i].getFConst());
                    break;
                  case EbtInt:
                    tempConstArray[i].setIConst(unionArray[i].getIConst());
                    break;
                  case EbtUInt:
                    tempConstArray[i].setUConst(static_cast<unsigned int>(
                        static_cast<int>(unionArray[i].getUConst())));
                    break;
                  default:
                    infoSink.info.message(
                        EPrefixInternalError, getLine(),
                        "Unary operation not folded into constant");
                    return NULL;
                }
                break;

              case EOpLogicalNot:
                // this code is written for possible future use,
                // will not get executed currently
                switch (getType().getBasicType())
                {
                  case EbtBool:
                    tempConstArray[i].setBConst(!unionArray[i].getBConst());
                    break;
                  default:
                    infoSink.info.message(
                        EPrefixInternalError, getLine(),
                        "Unary operation not folded into constant");
                    return NULL;
                }
                break;

              default:
                return NULL;
            }
        }
        newNode = new TIntermConstantUnion(tempConstArray, getType());
        newNode->setLine(getLine());
        return newNode;
    }
}
Esempio n. 17
0
//
// Do constant folding for an aggregate node that has all its children
// as constants and an operator that requires constant folding.
// 
TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
{
    if (! areAllChildConst(aggrNode))
        return aggrNode;

    if (aggrNode->isConstructor())
        return foldConstructor(aggrNode);

    TIntermSequence& children = aggrNode->getSequence();

    // First, see if this is an operation to constant fold, kick out if not,
    // see what size the result is if so.

    bool componentwise = false;  // will also say componentwise if a scalar argument gets repeated to make per-component results
    int objectSize;
    switch (aggrNode->getOp()) {
    case EOpAtan:
    case EOpPow:
    case EOpMin:
    case EOpMax:
    case EOpMix:
    case EOpClamp:
        componentwise = true;
        objectSize = children[0]->getAsConstantUnion()->getType().getObjectSize();
        break;
    case EOpCross:
    case EOpReflect:
    case EOpRefract:
    case EOpFaceForward:
        objectSize = children[0]->getAsConstantUnion()->getType().getObjectSize();
        break;
    case EOpDistance:
    case EOpDot:
        objectSize = 1;
        break;
    case EOpOuterProduct:
        objectSize = children[0]->getAsTyped()->getType().getVectorSize() *
                     children[1]->getAsTyped()->getType().getVectorSize();
        break;
    case EOpStep:
        componentwise = true;
        objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
                              children[1]->getAsTyped()->getType().getVectorSize());
        break;
    case EOpSmoothStep:
        componentwise = true;
        objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(),
                              children[2]->getAsTyped()->getType().getVectorSize());
        break;
    default:
        return aggrNode;
    }
    TConstUnion* newConstArray = new TConstUnion[objectSize];

    TVector<TConstUnion*> childConstUnions;
    for (unsigned int arg = 0; arg < children.size(); ++arg)
        childConstUnions.push_back(children[arg]->getAsConstantUnion()->getUnionArrayPointer());

    // Second, do the actual folding

    bool isFloatingPoint = children[0]->getAsTyped()->getBasicType() == EbtFloat ||
                           children[0]->getAsTyped()->getBasicType() == EbtDouble;
    bool isSigned = children[0]->getAsTyped()->getBasicType() == EbtInt;
    if (componentwise) {
        for (int comp = 0; comp < objectSize; comp++) {

            // some arguments are scalars instead of matching vectors; simulate a smear
            int arg0comp = std::min(comp, children[0]->getAsTyped()->getType().getVectorSize() - 1);
            int arg1comp;
            if (children.size() > 1)
                arg1comp = std::min(comp, children[1]->getAsTyped()->getType().getVectorSize() - 1);
            int arg2comp;
            if (children.size() > 2)
                arg2comp = std::min(comp, children[2]->getAsTyped()->getType().getVectorSize() - 1);

            switch (aggrNode->getOp()) {
            case EOpAtan:
                newConstArray[comp].setDConst(atan2(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
                break;
            case EOpPow:
                newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
                break;
            case EOpMin:
                if (isFloatingPoint)
                    newConstArray[comp].setDConst(std::min(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
                else if (isSigned)
                    newConstArray[comp].setIConst(std::min(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
                else
                    newConstArray[comp].setUConst(std::min(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
                break;
            case EOpMax:
                if (isFloatingPoint)
                    newConstArray[comp].setDConst(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
                else if (isSigned)
                    newConstArray[comp].setIConst(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()));
                else
                    newConstArray[comp].setUConst(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()));
                break;
            case EOpClamp:
                if (isFloatingPoint)
                    newConstArray[comp].setDConst(std::min(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()), 
                                                                                                               childConstUnions[2][arg2comp].getDConst()));
                else if (isSigned)
                    newConstArray[comp].setIConst(std::min(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()), 
                                                                                                               childConstUnions[2][arg2comp].getIConst()));
                else
                    newConstArray[comp].setUConst(std::min(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()), 
                                                                                                               childConstUnions[2][arg2comp].getUConst()));
                break;
            case EOpMix:
                if (children[2]->getAsTyped()->getBasicType() == EbtBool)
                    newConstArray[comp].setDConst(childConstUnions[2][arg2comp].getBConst() ? childConstUnions[1][arg1comp].getDConst() :
                                                                                              childConstUnions[0][arg0comp].getDConst());
                else
                    newConstArray[comp].setDConst(childConstUnions[0][arg0comp].getDConst() * (1.0 - childConstUnions[2][arg2comp].getDConst()) +
                                                  childConstUnions[1][arg1comp].getDConst() *        childConstUnions[2][arg2comp].getDConst());
                break;
            case EOpStep:
                newConstArray[comp].setDConst(childConstUnions[1][arg1comp].getDConst() < childConstUnions[0][arg0comp].getDConst() ? 0.0 : 1.0);
                break;
            case EOpSmoothStep:
            {
                double t = (childConstUnions[2][arg2comp].getDConst() - childConstUnions[0][arg0comp].getDConst()) / 
                           (childConstUnions[1][arg1comp].getDConst() - childConstUnions[0][arg0comp].getDConst());
                if (t < 0.0)
                    t = 0.0;
                if (t > 1.0)
                    t = 1.0;
                newConstArray[comp].setDConst(t * t * (3.0 - 2.0 * t));
                break;
            }
            default:
                return aggrNode;
            }
        }
    } else {
        // Non-componentwise...

        switch (aggrNode->getOp()) {

        // TODO: Functionality: constant folding: the rest of the ops have to be fleshed out

        case EOpModf:
        case EOpDistance:
        case EOpDot:
        case EOpCross:
        case EOpFaceForward:
        case EOpReflect:
        case EOpRefract:
        case EOpOuterProduct:
            return aggrNode;

        default:
            return aggrNode;
        }
    }

    TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, aggrNode->getType());
    newNode->getWritableType().getQualifier().storage = EvqConst;
    newNode->setLoc(aggrNode->getLoc());

    return newNode;
}
Esempio n. 18
0
//
// Do single unary node folding
//
TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
{
    TConstUnion *unionArray = getUnionArrayPointer();
    int objectSize = getType().getObjectSize();

    // First, size the result, which is mostly the same as the argument's size,
    // but not always.
    TConstUnion* newConstArray;
    switch (op) {
    // TODO: functionality: constant folding: finish listing exceptions to size here
    case EOpDeterminant:
    case EOpAny:
    case EOpAll:
    case EOpLength:
        newConstArray = new TConstUnion[1];
        break;

    case EOpEmitStreamVertex:
    case EOpEndStreamPrimitive:
        // These don't actually fold
        return 0;

    default:
        newConstArray = new TConstUnion[objectSize];
    }

    // Process non-component-wise operations
    switch (op) {
    case EOpLength:
    case EOpNormalize:
    {
        double sum = 0;
        for (int i = 0; i < objectSize; i++)
            sum += double(unionArray[i].getDConst()) * unionArray[i].getDConst();
        double length = sqrt(sum);
        if (op == EOpLength)
            newConstArray[0].setDConst(length);
        else {
            for (int i = 0; i < objectSize; i++)
                newConstArray[i].setDConst(unionArray[i].getDConst() / length);
        }
        break;
    }
    default:
        break;
    }

    for (int i = 0; i < objectSize; i++) {
        switch (op) {
        case EOpNegative:
            switch (getType().getBasicType()) {
            case EbtDouble:
            case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break;
            case EbtInt:   newConstArray[i].setIConst(-unionArray[i].getIConst()); break;
            case EbtUint:  newConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst())));  break;
            default:
                return 0;
            }
            break;
        case EOpLogicalNot:
        case EOpVectorLogicalNot:
            switch (getType().getBasicType()) {
            case EbtBool:  newConstArray[i].setBConst(!unionArray[i].getBConst()); break;
            default:
                return 0;
            }
            break;
        case EOpBitwiseNot:
            newConstArray[i] = ~unionArray[i];
            break;
        case EOpRadians:
            newConstArray[i].setDConst(unionArray[i].getDConst() * pi / 180.0);
            break;
        case EOpDegrees:
            newConstArray[i].setDConst(unionArray[i].getDConst() * 180.0 / pi);
            break;
        case EOpSin:
            newConstArray[i].setDConst(sin(unionArray[i].getDConst()));
            break;
        case EOpCos:
            newConstArray[i].setDConst(cos(unionArray[i].getDConst()));
            break;
        case EOpTan:
            newConstArray[i].setDConst(tan(unionArray[i].getDConst()));
            break;
        case EOpAsin:
            newConstArray[i].setDConst(asin(unionArray[i].getDConst()));
            break;
        case EOpAcos:
            newConstArray[i].setDConst(acos(unionArray[i].getDConst()));
            break;
        case EOpAtan:
            newConstArray[i].setDConst(atan(unionArray[i].getDConst()));
            break;

        case EOpLength:
        case EOpNormalize:
            // handled above as special case
            break;

        case EOpDPdx:
        case EOpDPdy:
        case EOpFwidth:
            // The derivatives are all mandated to create a constant 0.
            newConstArray[i].setDConst(0.0);
            break;

        case EOpExp:
            newConstArray[i].setDConst(exp(unionArray[i].getDConst()));
            break;
        case EOpLog:
            newConstArray[i].setDConst(log(unionArray[i].getDConst()));
            break;
        case EOpExp2:
            {
                const double inv_log2_e = 0.69314718055994530941723212145818;
                newConstArray[i].setDConst(exp(unionArray[i].getDConst() * inv_log2_e));
                break;
            }
        case EOpLog2:
            {
                const double log2_e = 1.4426950408889634073599246810019;
                newConstArray[i].setDConst(log2_e * log(unionArray[i].getDConst()));
                break;
            }
        case EOpSqrt:
            newConstArray[i].setDConst(sqrt(unionArray[i].getDConst()));
            break;
        case EOpInverseSqrt:
            newConstArray[i].setDConst(1.0 / sqrt(unionArray[i].getDConst()));
            break;

        case EOpAbs:
            if (unionArray[i].getType() == EbtDouble)
                newConstArray[i].setDConst(fabs(unionArray[i].getDConst()));
            else if (unionArray[i].getType() == EbtInt)
                newConstArray[i].setIConst(abs(unionArray[i].getIConst()));
            else
                newConstArray[i] = unionArray[i];
            break;
        case EOpSign:
            #define SIGN(X) (X == 0 ? 0 : (X < 0 ? -1 : 1))
            if (unionArray[i].getType() == EbtDouble)
                newConstArray[i].setDConst(SIGN(unionArray[i].getDConst()));
            else
                newConstArray[i].setIConst(SIGN(unionArray[i].getIConst()));
            break;
        case EOpFloor:
            newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
            break;
        case EOpTrunc:
            if (unionArray[i].getDConst() > 0)
                newConstArray[i].setDConst(floor(unionArray[i].getDConst()));
            else
                newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
            break;
        case EOpRound:
            newConstArray[i].setDConst(floor(0.5 + unionArray[i].getDConst()));
            break;
        case EOpRoundEven:
        {
            double flr = floor(unionArray[i].getDConst());
            bool even = flr / 2.0 == floor(flr / 2.0);
            double rounded = even ? ceil(unionArray[i].getDConst() - 0.5) : floor(unionArray[i].getDConst() + 0.5);
            newConstArray[i].setDConst(rounded);
            break;
        }
        case EOpCeil:
            newConstArray[i].setDConst(ceil(unionArray[i].getDConst()));
            break;
        case EOpFract:
        {
            double x = unionArray[i].getDConst();
            newConstArray[i].setDConst(x - floor(x));
            break;
        }

        case EOpIsNan:
        {
            newConstArray[i].setBConst(isNan(unionArray[i].getDConst()));
            break;
        }
        case EOpIsInf:
        {
            newConstArray[i].setBConst(isInf(unionArray[i].getDConst()));
            break;
        }

        // TODO: Functionality: constant folding: the rest of the ops have to be fleshed out

        case EOpSinh:
        case EOpCosh:
        case EOpTanh:
        case EOpAsinh:
        case EOpAcosh:
        case EOpAtanh:

        case EOpFloatBitsToInt:
        case EOpFloatBitsToUint:
        case EOpIntBitsToFloat:
        case EOpUintBitsToFloat:

        case EOpPackSnorm2x16:
        case EOpUnpackSnorm2x16:
        case EOpPackUnorm2x16:
        case EOpUnpackUnorm2x16:
        case EOpPackHalf2x16:
        case EOpUnpackHalf2x16:

        case EOpDeterminant:
        case EOpMatrixInverse:
        case EOpTranspose:

        case EOpAny:
        case EOpAll:

        default:
            return 0;
        }
    }

    TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType);
    newNode->getWritableType().getQualifier().storage = EvqConst;
    newNode->setLoc(getLoc());

    return newNode;
}
Esempio n. 19
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;
}
Esempio n. 20
0
ParsedValue Parser::parseValue(TIntermTyped* e) {
    auto binary = e->getAsBinaryNode();
    auto symbol = e->getAsSymbolNode();
    auto aggregate = e->getAsAggregate();
    TIntermConstantUnion* constunion = e->getAsConstantUnion();
    if (binary != nullptr) {
        CodeOp op;
        switch (binary->getOp()) {
        case EOpAdd:
            op = CAdd;
            break;
        case EOpSub:
            op = CSub;
            break;
        case EOpMul:
            op = CMul;
            break;
        case EOpDiv:
            op = CDiv;
            break;
        case EOpLessThan:
            op = CLt;
            break;
        case EOpGreaterThan:
            op = CGt;
            break;
        case EOpLessThanEqual:
            op = CLte;
            break;
        case EOpGreaterThanEqual:
            op = CGte;
            break;
        case EOpEqual:
            op = CEq;
            break;
        case EOpNotEqual:
            op = CNeq;
            break;
        case EOpLogicalOr:
            op = COr;
            break;
        case EOpLogicalAnd:
            op = COr;
            break;
        case EOpMatrixTimesVector:
            op = CMul;
            break;
        case EOpVectorSwizzle: {
            auto field = new PField;
            field->e = parseValue(binary->getLeft());
            for (unsigned i = 0; i < binary->getRight()->getAsAggregate()->getSequence().size(); ++i) {
                int num = binary->getRight()->getAsAggregate()->getSequence()[i]->getAsConstantUnion()->getUnionArrayPointer()->getIConst();
                switch (num) {
                case 0:
                    field->field += "x";
                    break;
                case 1:
                    field->field += "y";
                    break;
                case 2:
                    field->field += "z";
                    break;
                case 3:
                    field->field += "w";
                    break;
                }
            }
            ParsedValue value;
            value.v = field;
            value.p = binary->getLine().first_line;
            return value;
        }
        //case OpMod: CMod;
        //case OpInterval: CInterval;
        default:
            error("Unsupported operation", e->getLine().first_line);
        }
        ParsedValue value;
        value.v = new POp(op, parseValue(binary->getLeft()), parseValue(binary->getRight()));
        value.p = e->getLine().first_line;
        return value;
    }
    else if (symbol != nullptr) {
        ParsedValue value;
        auto var = new PVar;
        var->v = symbol->getSymbol().c_str();
        value.v = var;
        value.p = e->getLine().first_line;
        return value;
    }
    else if (constunion != nullptr) {
        ParsedValue value;
        value.p = constunion->getLine().first_line;
        auto constVar = new PConst;
        switch (constunion->getType().getBasicType()) {
        case EbtFloat:
            constVar->c = new ConstFloat(constunion->getUnionArrayPointer()->getFConst());
            break;
        default:
            error("Unknown type", constunion->getLine().first_line);
        }
        value.v = constVar;
        return value;
    }
    else if (aggregate != nullptr) {
        switch (aggregate->getOp()) {
        case EOpConstructVec4: {
            auto vector = new PVector;
            for (size_t i = 0; i < aggregate->getSequence().size(); ++i) {
                vector->el.push_back(parseValue(aggregate->getSequence()[i]->getAsTyped()));
            }
            ParsedValue value;
            value.v = vector;
            value.p = aggregate->getLine().first_line;
            return value;
        }
        default:
            error("Unknown aggregate", constunion->getLine().first_line);
        }
    }

    error("Unsupported value expression", e->getLine().first_line);
    ParsedValue value;
    value.v = nullptr;
    value.p = e->getLine().first_line;
    return value;

    /*switch (e.expr) {
    case EField(ef, s):
    	return { v : PField(parseValue(ef),s), p : e.pos };
    case EConst(c):
    	switch( c ) {
    	case CIdent(i) #if !haxe3 , CType(i) #end:
    		switch( i ) {
    		case "null":
    			return { v : PConst(CNull), p : e.pos };
    		case "true":
    			return { v : PConst(CBool(true)), p : e.pos };
    		case "false":
    			return { v : PConst(CBool(false)), p : e.pos };
    		default:
    			return { v : PVar(i), p : e.pos };
    		}
    	case CInt(v):
    		return { v : PConst(CInt(Std.parseInt(v))), p : e.pos };
    	case CFloat(f):
    		return { v : PConst(CFloat(Std.parseFloat(f))), p : e.pos };
    	default:
    	}
    case EUnop(OpNeg, _, { expr : EConst(CInt(v)) } ):
    	return { v : PConst(CInt(-Std.parseInt(v))), p : e.pos };
    case EUnop(op, _, e1):
    	var op = switch( op ) {
    	case OpNeg: CNeg;
    	case OpNot: CNot;
    	default: error("Unsupported operation", e.pos);
    	}
    	return { v : PUnop(op,parseValue(e1)), p : e.pos };
    case ECall(c, params):
    	switch( c.expr ) {
    	case EField(v, f):
    		return makeCall(f, [v].concat(params), e.pos);
    	case EConst(c):
    		switch( c ) {
    		case CIdent(i) #if !haxe3 , CType(i) #end:
    			return makeCall(i, params, e.pos);
    		default:
    		}
    	default:
    	}
    case EArrayDecl(values):
    	var vl = [];
    	for( v in values )
    		vl.push(parseValue(v));
    	return { v : PVector(vl), p : e.pos };
    case EParenthesis(k):
    	var v = parseValue(k);
    	v.p = e.pos;
    	return v;
    case EIf(ec, eif, eelse), ETernary(ec,eif,eelse):
    	var vcond = parseValue(ec);
    	var vif = parseValue(eif);
    	if( eelse == null ) error("'if' needs an 'else'", e.pos);
    	var velse = parseValue(eelse);
    	return { v : PCond(vcond, vif, velse), p : e.pos };
    case EArray(e1, e2):
    	var e1 = parseValue(e1);
    	var e2 = parseValue(e2);
    	return { v : PRow(e1, e2), p : e.pos };
    default:
    }
    */
}