TIntermAggregate *EmulatePrecision::createCompoundAssignmentFunctionCallNode(TIntermTyped *left, TIntermTyped *right, const char *opNameStr) { std::stringstream strstr = sh::InitializeStream<std::stringstream>(); if (left->getPrecision() == EbpMedium) strstr << "angle_compound_" << opNameStr << "_frm"; else strstr << "angle_compound_" << opNameStr << "_frl"; ImmutableString functionName = ImmutableString(strstr.str()); TIntermSequence *arguments = new TIntermSequence(); arguments->push_back(left); arguments->push_back(right); TVector<const TVariable *> parameters; TType *leftParamType = new TType(left->getType()); leftParamType->setPrecision(EbpHigh); leftParamType->setQualifier(EvqOut); parameters.push_back(new TVariable(mSymbolTable, kParamXName, static_cast<const TType *>(leftParamType), SymbolType::AngleInternal)); TType *rightParamType = new TType(right->getType()); rightParamType->setPrecision(EbpHigh); rightParamType->setQualifier(EvqIn); parameters.push_back(new TVariable(mSymbolTable, kParamYName, static_cast<const TType *>(rightParamType), SymbolType::AngleInternal)); return TIntermAggregate::CreateRawFunctionCall( *getInternalFunction(functionName, left->getType(), arguments, parameters, false), arguments); }
// // Merge the linker objects from unitLinkerObjects into linkerObjects. // Duplication is expected and filtered out, but contradictions are an error. // void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects) { // Error check and merge the linker objects (duplicates should not be created) std::size_t initialNumLinkerObjects = linkerObjects.size(); for (unsigned int unitLinkObj = 0; unitLinkObj < unitLinkerObjects.size(); ++unitLinkObj) { bool merge = true; for (std::size_t linkObj = 0; linkObj < initialNumLinkerObjects; ++linkObj) { TIntermSymbol* symbol = linkerObjects[linkObj]->getAsSymbolNode(); TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode(); assert(symbol && unitSymbol); if (symbol->getName() == unitSymbol->getName()) { // filter out copy merge = false; // but if one has an initializer and the other does not, update // the initializer if (symbol->getConstArray().empty() && ! unitSymbol->getConstArray().empty()) symbol->setConstArray(unitSymbol->getConstArray()); // Similarly for binding if (! symbol->getQualifier().hasBinding() && unitSymbol->getQualifier().hasBinding()) symbol->getQualifier().layoutBinding = unitSymbol->getQualifier().layoutBinding; // Update implicit array sizes mergeImplicitArraySizes(symbol->getWritableType(), unitSymbol->getType()); // Check for consistent types/qualification/initializers etc. mergeErrorCheck(infoSink, *symbol, *unitSymbol, false); } } if (merge) linkerObjects.push_back(unitLinkerObjects[unitLinkObj]); } }
TIntermAggregate *EmulatePrecision::createRoundingFunctionCallNode(TIntermTyped *roundedChild) { const ImmutableString *roundFunctionName = &kAngleFrmString; if (roundedChild->getPrecision() == EbpLow) roundFunctionName = &kAngleFrlString; TIntermSequence *arguments = new TIntermSequence(); arguments->push_back(roundedChild); TVector<const TVariable *> parameters; TType *paramType = new TType(roundedChild->getType()); paramType->setPrecision(EbpHigh); paramType->setQualifier(EvqIn); parameters.push_back(new TVariable(mSymbolTable, kParamXName, static_cast<const TType *>(paramType), SymbolType::AngleInternal)); return TIntermAggregate::CreateRawFunctionCall( *getInternalFunction(*roundFunctionName, roundedChild->getType(), arguments, parameters, true), arguments); }
TIntermTyped *TIntermediate::addSwizzle( TVectorFields &fields, const TSourceLoc &line) { TIntermAggregate *node = new TIntermAggregate(EOpSequence); node->setLine(line); TIntermConstantUnion *constIntNode; TIntermSequence *sequenceVector = node->getSequence(); ConstantUnion *unionArray; for (int i = 0; i < fields.num; i++) { unionArray = new ConstantUnion[1]; unionArray->setIConst(fields.offsets[i]); constIntNode = addConstantUnion( unionArray, TType(EbtInt, EbpUndefined, EvqConst), line); sequenceVector->push_back(constIntNode); } return node; }
bool InitializeVariables::visitAggregate(Visit visit, TIntermAggregate *node) { bool visitChildren = !mCodeInserted; switch (node->getOp()) { case EOpSequence: break; case EOpFunction: { // Function definition. ASSERT(visit == PreVisit); if (node->getName() == "main(") { TIntermSequence *sequence = node->getSequence(); ASSERT((sequence->size() == 1) || (sequence->size() == 2)); TIntermAggregate *body = NULL; if (sequence->size() == 1) { body = new TIntermAggregate(EOpSequence); sequence->push_back(body); } else { body = (*sequence)[1]->getAsAggregate(); } ASSERT(body); insertInitCode(body->getSequence()); mCodeInserted = true; } break; } default: visitChildren = false; break; } return visitChildren; }
void ScalarizeVecAndMatConstructorArgs::scalarizeArgs( TIntermAggregate *aggregate, bool scalarizeVector, bool scalarizeMatrix) { ASSERT(aggregate); int size = 0; switch (aggregate->getOp()) { case EOpConstructVec2: case EOpConstructBVec2: case EOpConstructIVec2: size = 2; break; case EOpConstructVec3: case EOpConstructBVec3: case EOpConstructIVec3: size = 3; break; case EOpConstructVec4: case EOpConstructBVec4: case EOpConstructIVec4: case EOpConstructMat2: size = 4; break; case EOpConstructMat2x3: case EOpConstructMat3x2: size = 6; break; case EOpConstructMat2x4: case EOpConstructMat4x2: size = 8; break; case EOpConstructMat3: size = 9; break; case EOpConstructMat3x4: case EOpConstructMat4x3: size = 12; break; case EOpConstructMat4: size = 16; break; default: break; } TIntermSequence *sequence = aggregate->getSequence(); TIntermSequence original(*sequence); sequence->clear(); for (size_t ii = 0; ii < original.size(); ++ii) { ASSERT(size > 0); TIntermTyped *node = original[ii]->getAsTyped(); ASSERT(node); TString varName = createTempVariable(node); if (node->isScalar()) { TIntermSymbol *symbolNode = new TIntermSymbol(-1, varName, node->getType()); sequence->push_back(symbolNode); size--; } else if (node->isVector()) { if (scalarizeVector) { int repeat = std::min(size, node->getNominalSize()); size -= repeat; for (int index = 0; index < repeat; ++index) { TIntermSymbol *symbolNode = new TIntermSymbol(-1, varName, node->getType()); TIntermBinary *newNode = ConstructVectorIndexBinaryNode( symbolNode, index); sequence->push_back(newNode); } } else { TIntermSymbol *symbolNode = new TIntermSymbol(-1, varName, node->getType()); sequence->push_back(symbolNode); size -= node->getNominalSize(); } } else { ASSERT(node->isMatrix()); if (scalarizeMatrix) { int colIndex = 0, rowIndex = 0; int repeat = std::min(size, node->getCols() * node->getRows()); size -= repeat; while (repeat > 0) { TIntermSymbol *symbolNode = new TIntermSymbol(-1, varName, node->getType()); TIntermBinary *newNode = ConstructMatrixIndexBinaryNode( symbolNode, colIndex, rowIndex); sequence->push_back(newNode); rowIndex++; if (rowIndex >= node->getRows()) { rowIndex = 0; colIndex++; } repeat--; } } else { TIntermSymbol *symbolNode = new TIntermSymbol(-1, varName, node->getType()); sequence->push_back(symbolNode); size -= node->getCols() * node->getRows(); } } } }
void TIntermTraverser::insertStatementInParentBlock(TIntermNode *statement) { TIntermSequence insertions; insertions.push_back(statement); insertStatementsInParentBlock(insertions); }
TIntermTyped *CreateZeroNode(const TType &type) { TType constType(type); constType.setQualifier(EvqConst); if (!type.isArray() && type.getBasicType() != EbtStruct) { size_t size = constType.getObjectSize(); TConstantUnion *u = new TConstantUnion[size]; for (size_t i = 0; i < size; ++i) { switch (type.getBasicType()) { case EbtFloat: u[i].setFConst(0.0f); break; case EbtInt: u[i].setIConst(0); break; case EbtUInt: u[i].setUConst(0u); break; case EbtBool: u[i].setBConst(false); break; default: // CreateZeroNode is called by ParseContext that keeps parsing even when an // error occurs, so it is possible for CreateZeroNode to be called with // non-basic types. This happens only on error condition but CreateZeroNode // needs to return a value with the correct type to continue the typecheck. // That's why we handle non-basic type by setting whatever value, we just need // the type to be right. u[i].setIConst(42); break; } } TIntermConstantUnion *node = new TIntermConstantUnion(u, constType); return node; } if (type.getBasicType() == EbtVoid) { // Void array. This happens only on error condition, similarly to the case above. We don't // have a constructor operator for void, so this needs special handling. We'll end up with a // value without the array type, but that should not be a problem. while (constType.isArray()) { constType.toArrayElementType(); } return CreateZeroNode(constType); } TIntermSequence *arguments = new TIntermSequence(); if (type.isArray()) { TType elementType(type); elementType.toArrayElementType(); size_t arraySize = type.getOutermostArraySize(); for (size_t i = 0; i < arraySize; ++i) { arguments->push_back(CreateZeroNode(elementType)); } } else { ASSERT(type.getBasicType() == EbtStruct); TStructure *structure = type.getStruct(); for (const auto &field : structure->fields()) { arguments->push_back(CreateZeroNode(*field->type())); } } return TIntermAggregate::CreateConstructor(constType, arguments); }