Revert "(glslang) Get rid of all asserts"

This reverts commit d2b161ee86735f34052cef3a3ba86731f50735bb.
This commit is contained in:
libretroadmin 2024-06-15 06:22:16 +02:00
parent 3401f124cc
commit 2d4f31bc0a
33 changed files with 443 additions and 100 deletions

View File

@ -369,6 +369,7 @@ spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::T
switch (type.getBasicType()) {
default:
return spv::DecorationMax;
break;
case glslang::EbtBlock:
switch (type.getQualifier().storage) {
case glslang::EvqUniform:
@ -381,6 +382,8 @@ spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::T
}
case glslang::EvqVaryingIn:
case glslang::EvqVaryingOut:
assert(type.getQualifier().layoutPacking == glslang::ElpNone);
return spv::DecorationMax;
default:
return spv::DecorationMax;
}
@ -734,6 +737,8 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
// Translate glslang image layout format to SPIR-V image format.
spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TType& type)
{
assert(type.getBasicType() == glslang::EbtSampler);
// Check for capabilities
switch (type.getQualifier().layoutFormat) {
case glslang::ElfRg32f:
@ -1314,6 +1319,9 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
rValue = createBinaryOperation(node->getOp(), decorations,
convertGlslangToSpvType(node->getType()), leftRValue, rValue,
node->getType().getBasicType());
// these all need their counterparts in createBinaryOperation()
assert(rValue != spv::NoResult);
}
// store the result
@ -1350,6 +1358,7 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
// This may be, e.g., an anonymous block-member selection, which generally need
// index remapping due to hidden members in anonymous blocks.
std::vector<int>& remapper = memberRemapper[node->getLeft()->getType().getStruct()];
assert(remapper.size() > 0);
spvIndex = remapper[glslangIndex];
}
@ -1579,6 +1588,7 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI
spv::Id result = createBinaryOperation(op, decorations,
convertGlslangToSpvType(node->getType()), operand, one,
node->getType().getBasicType());
assert(result != spv::NoResult);
// The result of operation is always stored, but conditionally the
// consumed result. The consumed result is always an r-value.
@ -1638,6 +1648,8 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
bool noReturnValue = false;
bool atomic = false;
assert(node->getOp());
spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision());
switch (node->getOp()) {
@ -1713,6 +1725,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
builder.setLine(node->getLoc().line);
if (node->isUserDefined())
result = handleUserFunctionCall(node);
// assert(result); // this can happen for bad shaders because the call graph completeness checking is not yet done
if (result) {
builder.clearAccessChain();
builder.setAccessChainRValue(result);
@ -1949,6 +1962,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
if (binOp != glslang::EOpNull) {
glslang::TIntermTyped* left = node->getSequence()[0]->getAsTyped();
glslang::TIntermTyped* right = node->getSequence()[1]->getAsTyped();
assert(left && right);
builder.clearAccessChain();
left->traverse(this);
@ -1967,6 +1981,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
left->getType().getBasicType(), reduceComparison);
// code above should only make binOp that exists in createBinaryOperation
assert(result != spv::NoResult);
builder.clearAccessChain();
builder.setAccessChainRValue(result);
@ -2124,6 +2139,9 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
node->getBasicType() == glslang::EbtVoid)
return false;
assert(node->getType() == node->getTrueBlock() ->getAsTyped()->getType() &&
node->getType() == node->getFalseBlock()->getAsTyped()->getType());
// return true if a single operand to ? : is okay for OpSelect
const auto operandOkay = [](glslang::TIntermTyped* node) {
return node->getAsSymbolNode() || node->getType().getQualifier().isConstant();
@ -2535,6 +2553,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
switch (type.getBasicType()) {
case glslang::EbtVoid:
spvType = builder.makeVoidType();
assert (! type.isArray());
break;
case glslang::EbtFloat:
spvType = builder.makeFloatType(32);
@ -2914,6 +2933,7 @@ spv::Id TGlslangToSpvTraverser::makeArraySizeId(const glslang::TArraySizes& arra
// Otherwise, need a compile-time (front end) size, get it:
int size = arraySizes.getDimSize(dim);
assert(size > 0);
return builder.makeUintConstant(size);
}
@ -3034,6 +3054,8 @@ void TGlslangToSpvTraverser::multiTypeStore(const glslang::TType& type, spv::Id
multiTypeStore(glslangElementType, elementRValue);
}
} else {
assert(type.isStruct());
// loop over structure members
const glslang::TTypeList& members = *type.getStruct();
for (int m = 0; m < (int)members.size(); ++m) {
@ -3201,6 +3223,10 @@ bool TGlslangToSpvTraverser::isShaderEntryPoint(const glslang::TIntermAggregate*
// qualifiers such that we should have only in/out/inout/constreadonly here.
bool TGlslangToSpvTraverser::writableParam(glslang::TStorageQualifier qualifier) const
{
assert(qualifier == glslang::EvqIn ||
qualifier == glslang::EvqOut ||
qualifier == glslang::EvqInOut ||
qualifier == glslang::EvqConstReadOnly);
return qualifier != glslang::EvqConstReadOnly;
}
@ -3678,6 +3704,8 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO
#ifdef AMD_EXTENSIONS
// Check for fragment mask functions other than queries
if (cracked.fragMask) {
assert(sampler.ms);
auto opIt = arguments.begin();
std::vector<spv::Id> operands;
@ -4027,6 +4055,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, OpD
if (isFloat && (builder.isVector(left) || builder.isVector(right))) {
if (builder.isVector(right))
std::swap(left, right);
assert(builder.isScalar(right));
needMatchingVectors = false;
binOp = spv::OpVectorTimesScalar;
} else
@ -4122,6 +4151,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, OpD
// handle mapped binary operations (should be non-comparison)
if (binOp != spv::OpNop) {
assert(comparison == false);
if (builder.isMatrix(left) || builder.isMatrix(right))
return createBinaryMatrixOperation(binOp, decorations, typeId, left, right);
@ -4245,10 +4275,19 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, OpDecora
case spv::OpMatrixTimesScalar:
if (builder.isMatrix(right))
std::swap(left, right);
assert(builder.isScalar(right));
break;
case spv::OpVectorTimesMatrix:
assert(builder.isVector(left));
assert(builder.isMatrix(right));
break;
case spv::OpMatrixTimesVector:
assert(builder.isMatrix(left));
assert(builder.isVector(right));
break;
case spv::OpMatrixTimesMatrix:
assert(builder.isMatrix(left));
assert(builder.isMatrix(right));
break;
default:
firstClass = false;
@ -4797,6 +4836,7 @@ spv::Id TGlslangToSpvTraverser::createIntWidthConversion(glslang::TOperator op,
break;
default:
assert(false && "Default missing");
break;
}
@ -5142,6 +5182,7 @@ spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, OpDecora
zero = builder.makeUint64Constant(0);
break;
default:
assert(false && "Default missing");
break;
}
zero = makeSmearedConstant(zero, vectorSize);
@ -5490,12 +5531,28 @@ spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op
return spv::NoResult;
}
assert(opCode != spv::OpNop);
return builder.createOp(opCode, typeId, spvGroupOperands);
}
// Create group invocation operations on a vector
spv::Id TGlslangToSpvTraverser::CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, spv::Id typeId, std::vector<spv::Id>& operands)
{
#ifdef AMD_EXTENSIONS
assert(op == spv::OpGroupFMin || op == spv::OpGroupUMin || op == spv::OpGroupSMin ||
op == spv::OpGroupFMax || op == spv::OpGroupUMax || op == spv::OpGroupSMax ||
op == spv::OpGroupFAdd || op == spv::OpGroupIAdd || op == spv::OpGroupBroadcast ||
op == spv::OpSubgroupReadInvocationKHR ||
op == spv::OpGroupFMinNonUniformAMD || op == spv::OpGroupUMinNonUniformAMD || op == spv::OpGroupSMinNonUniformAMD ||
op == spv::OpGroupFMaxNonUniformAMD || op == spv::OpGroupUMaxNonUniformAMD || op == spv::OpGroupSMaxNonUniformAMD ||
op == spv::OpGroupFAddNonUniformAMD || op == spv::OpGroupIAddNonUniformAMD);
#else
assert(op == spv::OpGroupFMin || op == spv::OpGroupUMin || op == spv::OpGroupSMin ||
op == spv::OpGroupFMax || op == spv::OpGroupUMax || op == spv::OpGroupSMax ||
op == spv::OpGroupFAdd || op == spv::OpGroupIAdd || op == spv::OpGroupBroadcast ||
op == spv::OpSubgroupReadInvocationKHR);
#endif
// Handle group invocation operations scalar by scalar.
// The result type is the same type as the original type.
// The algorithm is to:
@ -5937,10 +5994,10 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
builder.promoteScalar(precision, operands.front(), operands[2]);
break;
case glslang::EOpMix:
if (! builder.isBoolType(builder.getScalarTypeId(builder.getTypeId(operands.back()))))
if (! builder.isBoolType(builder.getScalarTypeId(builder.getTypeId(operands.back())))) {
assert(isFloat);
libCall = spv::GLSLstd450FMix;
else
{
} else {
opCode = spv::OpSelect;
std::swap(operands.front(), operands.back());
}
@ -6023,6 +6080,7 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
case glslang::EOpFrexp:
{
libCall = spv::GLSLstd450FrexpStruct;
assert(builder.isPointerType(typeId1));
typeId1 = builder.getContainedTypeId(typeId1);
int width = builder.getScalarTypeWidth(typeId1);
#ifdef AMD_EXTENSIONS
@ -6163,6 +6221,7 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
break;
default:
// anything 3 or over doesn't have l-value operands, so all should be consumed
assert(consumedOperands == operands.size());
id = builder.createOp(opCode, typeId, operands);
break;
}
@ -6182,6 +6241,7 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
break;
case glslang::EOpFrexp:
{
assert(operands.size() == 2);
if (builder.isFloatType(builder.getScalarTypeId(typeId1))) {
// "exp" is floating-point type (from HLSL intrinsic)
spv::Id member1 = builder.createCompositeExtract(id, frexpIntType, 1);
@ -6441,9 +6501,12 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
// - when running into a non-spec-constant, switch to createSpvConstant()
spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& node)
{
assert(node.getQualifier().isConstant());
// Handle front-end constants first (non-specialization constants).
if (! node.getQualifier().specConstant) {
// hand off to the non-spec-constant path
assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr);
int nextConst = 0;
return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(),
nextConst, false);

View File

@ -50,6 +50,7 @@
#include "spvIR.h"
#include <cassert>
#include <unordered_set>
using spv::Block;
@ -67,6 +68,7 @@ public:
// the branches have been completed.
void visit(Block* block)
{
assert(block);
if (visited_.count(block) || delayed_.count(block))
return;
callback_(block);

View File

@ -41,6 +41,7 @@
#else // defined (use_cpp11)
#include <algorithm>
#include <cassert>
#include "../glslang/Include/Common.h"
namespace spv {
@ -316,6 +317,8 @@ namespace spv {
if (errorLatch)
return;
assert(id != unused && id != unmapped);
}
);
}
@ -456,6 +459,7 @@ namespace spv {
fnStart = start;
fnRes = asId(start + 2);
} else if (opCode == spv::Op::OpFunctionEnd) {
assert(fnRes != spv::NoResult);
if (fnStart == 0) {
error("function end without function start");
return false;
@ -467,9 +471,12 @@ namespace spv {
if (errorLatch)
return false;
assert(asId(start + 2) != spv::NoResult);
typeConstPos.insert(start);
} else if (isTypeOp(opCode))
} else if (isTypeOp(opCode)) {
assert(asId(start + 1) != spv::NoResult);
typeConstPos.insert(start);
}
return false;
},
@ -1223,6 +1230,8 @@ namespace spv {
gdata.begin() + range.first);
};
assert(isTypeOp(opCode) || isConstOp(opCode));
switch (opCode) {
case spv::OpTypeOpaque: // TODO: disable until we compare the literal strings.
case spv::OpTypeQueue: return false;

View File

@ -38,6 +38,7 @@
// SpvBuilder.h.
//
#include <cassert>
#include <cstdlib>
#include <unordered_set>
@ -308,6 +309,8 @@ Id Builder::makeVectorType(Id component, int size)
Id Builder::makeMatrixType(Id component, int cols, int rows)
{
assert(cols <= maxMatrixSize && rows <= maxMatrixSize);
Id column = makeVectorType(component, rows);
// try to find it
@ -401,6 +404,8 @@ Id Builder::makeFunctionType(Id returnType, const std::vector<Id>& paramTypes)
Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format)
{
assert(sampled == 1 || sampled == 2);
// try to find it
Instruction* type;
for (int t = 0; t < (int)groupedTypes[OpTypeImage].size(); ++t) {
@ -502,6 +507,8 @@ Id Builder::makeSampledImageType(Id imageType)
Id Builder::getDerefTypeId(Id resultId) const
{
Id typeId = getTypeId(resultId);
assert(isPointerType(typeId));
return module.getInstruction(typeId)->getImmediateOperand(1);
}
@ -842,6 +849,8 @@ Id Builder::makeFloat16Constant(float f16, bool specConstant)
Id Builder::makeFpConstant(Id type, double d, bool specConstant)
{
assert(isFloatType(type));
switch (getScalarTypeWidth(type)) {
case 16:
return makeFloat16Constant((float)d, specConstant);
@ -912,6 +921,7 @@ Id Builder::findStructConstant(Id typeId, const std::vector<Id>& comps)
Id Builder::makeCompositeConstant(Id typeId, const std::vector<Id>& members, bool specConstant)
{
Op opcode = specConstant ? OpSpecConstantComposite : OpConstantComposite;
assert(typeId);
Op typeClass = getTypeClass(typeId);
switch (typeClass) {
@ -1067,6 +1077,8 @@ void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decorat
// Comments in header
Function* Builder::makeEntryPoint(const char* entryPoint)
{
assert(! entryPointFunction);
Block* entry;
std::vector<Id> params;
std::vector<std::vector<Decoration>> decorations;
@ -1126,6 +1138,7 @@ void Builder::leaveFunction()
{
Block* block = buildPoint;
Function& function = buildPoint->getParent();
assert(block);
// If our function did not contain a return, add a return void now.
if (! block->isTerminated()) {
@ -1201,11 +1214,13 @@ Id Builder::createAccessChain(StorageClass storageClass, Id base, const std::vec
{
// Figure out the final resulting type.
spv::Id typeId = getTypeId(base);
assert(isPointerType(typeId) && offsets.size() > 0);
typeId = getContainedTypeId(typeId);
for (int i = 0; i < (int)offsets.size(); ++i) {
if (isStructType(typeId))
if (isStructType(typeId)) {
assert(isConstantScalar(offsets[i]));
typeId = getContainedTypeId(typeId, getConstantScalar(offsets[i]));
else
} else
typeId = getContainedTypeId(typeId, offsets[i]);
}
typeId = makePointer(storageClass, typeId);
@ -1447,6 +1462,7 @@ Id Builder::createRvalueSwizzle(Decoration precision, Id typeId, Id source, cons
return setPrecision(createSpecConstantOp(OpVectorShuffle, typeId, operands, channels), precision);
}
Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle);
assert(isVector(source));
swizzle->addIdOperand(source);
swizzle->addIdOperand(source);
for (int i = 0; i < (int)channels.size(); ++i)
@ -1464,8 +1480,11 @@ Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, const std::vect
Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle);
assert(isVector(target));
swizzle->addIdOperand(target);
assert(getNumComponents(source) == (int)channels.size());
assert(isVector(source));
swizzle->addIdOperand(source);
// Set up an identity shuffle from the base value to the result value
@ -1502,6 +1521,9 @@ void Builder::promoteScalar(Decoration precision, Id& left, Id& right)
// Comments in header
Id Builder::smearScalar(Decoration precision, Id scalar, Id vectorType)
{
assert(getNumComponents(scalar) == 1);
assert(getTypeId(scalar) == getScalarTypeId(vectorType));
int numComponents = getNumTypeComponents(vectorType);
if (numComponents == 1)
return scalar;
@ -1828,6 +1850,7 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
// Scalars and Vectors
if (isScalarType(valueType) || isVectorType(valueType)) {
assert(valueType == getTypeId(value2));
// These just need a single comparison, just have
// to figure out what it is.
Op op;
@ -1859,6 +1882,10 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
return setPrecision(resultId, precision);
}
// Only structs, arrays, and matrices should be left.
// They share in common the reduction operation across their constituents.
assert(isAggregateType(valueType) || isMatrixType(valueType));
// Compare each pair of constituents
for (int constituent = 0; constituent < numConstituents; ++constituent) {
std::vector<unsigned> indexes(1, constituent);
@ -1881,6 +1908,8 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
// OpCompositeConstruct
Id Builder::createCompositeConstruct(Id typeId, const std::vector<Id>& constituents)
{
assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && getNumTypeConstituents(typeId) == (int)constituents.size()));
if (generatingOpCodeForSpecConst) {
// Sometime, even in spec-constant-op mode, the constant composite to be
// constructed may not be a specialization constant.
@ -2264,6 +2293,7 @@ void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizz
std::vector<unsigned> oldSwizzle = accessChain.swizzle;
accessChain.swizzle.resize(0);
for (unsigned int i = 0; i < swizzle.size(); ++i) {
assert(swizzle[i] < oldSwizzle.size());
accessChain.swizzle.push_back(oldSwizzle[swizzle[i]]);
}
} else
@ -2276,10 +2306,15 @@ void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizz
// Comments in header
void Builder::accessChainStore(Id rvalue)
{
assert(accessChain.isRValue == false);
transferAccessChainSwizzle(true);
Id base = collapseAccessChain();
Id source = rvalue;
// dynamic component should be gone
assert(accessChain.component == NoResult);
// If swizzle still exists, it is out-of-order or not full, we must load the target vector,
// extract and insert elements to perform writeMask and/or swizzle.
if (accessChain.swizzle.size() > 0) {
@ -2364,8 +2399,18 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
Id Builder::accessChainGetLValue()
{
assert(accessChain.isRValue == false);
transferAccessChainSwizzle(true);
return collapseAccessChain();
Id lvalue = collapseAccessChain();
// If swizzle exists, it is out-of-order or not full, we must load the target vector,
// extract and insert elements to perform writeMask and/or swizzle. This does not
// go with getting a direct l-value pointer.
assert(accessChain.swizzle.size() == 0);
assert(accessChain.component == NoResult);
return lvalue;
}
// comment in header
@ -2501,6 +2546,8 @@ void Builder::dump(std::vector<unsigned int>& out) const
// Can generate code.
Id Builder::collapseAccessChain()
{
assert(accessChain.isRValue == false);
// did we already emit an access chain for this?
if (accessChain.instr != NoResult)
return accessChain.instr;
@ -2594,11 +2641,13 @@ void Builder::transferAccessChainSwizzle(bool dynamic)
// single component, either in the swizzle and/or dynamic component
if (accessChain.swizzle.size() == 1) {
assert(accessChain.component == NoResult);
// handle static component selection
accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle.front()));
accessChain.swizzle.clear();
accessChain.preSwizzleBaseType = NoType;
} else if (dynamic && accessChain.component != NoResult) {
assert(accessChain.swizzle.size() == 0);
// handle dynamic component
accessChain.indexChain.push_back(accessChain.component);
accessChain.preSwizzleBaseType = NoType;

View File

@ -179,31 +179,37 @@ public:
int getScalarTypeWidth(Id typeId) const
{
Id scalarTypeId = getScalarTypeId(typeId);
assert(getTypeClass(scalarTypeId) == OpTypeInt || getTypeClass(scalarTypeId) == OpTypeFloat);
return module.getInstruction(scalarTypeId)->getImmediateOperand(0);
}
int getTypeNumColumns(Id typeId) const
{
assert(isMatrixType(typeId));
return getNumTypeConstituents(typeId);
}
int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); }
int getTypeNumRows(Id typeId) const
{
assert(isMatrixType(typeId));
return getNumTypeComponents(getContainedTypeId(typeId));
}
int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); }
Dim getTypeDimensionality(Id typeId) const
{
assert(isImageType(typeId));
return (Dim)module.getInstruction(typeId)->getImmediateOperand(1);
}
Id getImageType(Id resultId) const
{
Id typeId = getTypeId(resultId);
assert(isImageType(typeId) || isSampledImageType(typeId));
return isSampledImageType(typeId) ? module.getInstruction(typeId)->getIdOperand(0) : typeId;
}
bool isArrayedImageType(Id typeId) const
{
assert(isImageType(typeId));
return module.getInstruction(typeId)->getImmediateOperand(3) != 0;
}
@ -513,6 +519,7 @@ public:
// set new base as an l-value base
void setAccessChainLValue(Id lValue)
{
assert(isPointer(lValue));
accessChain.base = lValue;
}

View File

@ -24,6 +24,8 @@ namespace spvutils {
template <typename Dest, typename Src>
Dest BitwiseCast(Src source) {
Dest dest;
static_assert(sizeof(source) == sizeof(dest),
"BitwiseCast: Source and destination must have the same size");
std::memcpy(static_cast<void*>(&dest), static_cast<void*>(&source), sizeof(dest));
return dest;
}
@ -35,6 +37,8 @@ Dest BitwiseCast(Src source) {
// a bit that will not fit in the underlying type is set.
template <typename T, size_t First = 0, size_t Num = 0>
struct SetBits {
static_assert(First < sizeof(T) * 8,
"Tried to set a bit that is shifted too far.");
const static T get = (T(1) << First) | SetBits<T, First + 1, Num - 1>::get;
};
@ -43,6 +47,35 @@ struct SetBits<T, Last, 0> {
const static T get = T(0);
};
// This is all compile-time so we can put our tests right here.
static_assert(SetBits<uint32_t, 0, 0>::get == uint32_t(0x00000000),
"SetBits failed");
static_assert(SetBits<uint32_t, 0, 1>::get == uint32_t(0x00000001),
"SetBits failed");
static_assert(SetBits<uint32_t, 31, 1>::get == uint32_t(0x80000000),
"SetBits failed");
static_assert(SetBits<uint32_t, 1, 2>::get == uint32_t(0x00000006),
"SetBits failed");
static_assert(SetBits<uint32_t, 30, 2>::get == uint32_t(0xc0000000),
"SetBits failed");
static_assert(SetBits<uint32_t, 0, 31>::get == uint32_t(0x7FFFFFFF),
"SetBits failed");
static_assert(SetBits<uint32_t, 0, 32>::get == uint32_t(0xFFFFFFFF),
"SetBits failed");
static_assert(SetBits<uint32_t, 16, 16>::get == uint32_t(0xFFFF0000),
"SetBits failed");
static_assert(SetBits<uint64_t, 0, 1>::get == uint64_t(0x0000000000000001LL),
"SetBits failed");
static_assert(SetBits<uint64_t, 63, 1>::get == uint64_t(0x8000000000000000LL),
"SetBits failed");
static_assert(SetBits<uint64_t, 62, 2>::get == uint64_t(0xc000000000000000LL),
"SetBits failed");
static_assert(SetBits<uint64_t, 31, 1>::get == uint64_t(0x0000000080000000LL),
"SetBits failed");
static_assert(SetBits<uint64_t, 16, 16>::get == uint64_t(0x00000000FFFF0000LL),
"SetBits failed");
} // namespace spvutils
#endif // LIBSPIRV_UTIL_BITUTILS_H_

View File

@ -38,6 +38,7 @@
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <iomanip>
#include <stack>
#include <sstream>
@ -534,6 +535,8 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
numOperands -= disassembleString();
break;
default:
assert(operandClass >= OperandSource && operandClass < OperandOpcode);
if (OperandClassParams[operandClass].bitmask)
outputMask(operandClass, stream[word++]);
else

View File

@ -15,6 +15,7 @@
#ifndef LIBSPIRV_UTIL_HEX_FLOAT_H_
#define LIBSPIRV_UTIL_HEX_FLOAT_H_
#include <cassert>
#include <cctype>
#include <cmath>
#include <cstdint>
@ -420,6 +421,7 @@ class HexFloat {
new_value = static_cast<uint_type>(new_value | sign_mask);
}
exponent = static_cast<int_type>(exponent + exponent_bias);
assert(exponent >= 0);
// put it all together
exponent = static_cast<uint_type>((exponent << exponent_left_shift) &
@ -636,6 +638,11 @@ class HexFloat {
private:
T value_;
static_assert(num_used_bits ==
Traits::num_exponent_bits + Traits::num_fraction_bits + 1,
"The number of bits do not fit");
static_assert(sizeof(T) == sizeof(uint_type), "The type sizes do not match");
};
// Returns 4 bits represented by the hex character.
@ -644,13 +651,15 @@ inline uint8_t get_nibble_from_character(int character) {
const char* lower = "abcdef";
const char* upper = "ABCDEF";
const char* p = nullptr;
if ((p = strchr(dec, character)))
if ((p = strchr(dec, character))) {
return static_cast<uint8_t>(p - dec);
else if ((p = strchr(lower, character)))
} else if ((p = strchr(lower, character))) {
return static_cast<uint8_t>(p - lower + 0xa);
else if ((p = strchr(upper, character)))
} else if ((p = strchr(upper, character))) {
return static_cast<uint8_t>(p - upper + 0xa);
}
assert(false && "This was called with a non-hex character");
return 0;
}
@ -661,6 +670,13 @@ std::ostream& operator<<(std::ostream& os, const HexFloat<T, Traits>& value) {
typedef typename HF::uint_type uint_type;
typedef typename HF::int_type int_type;
static_assert(HF::num_used_bits != 0,
"num_used_bits must be non-zero for a valid float");
static_assert(HF::num_exponent_bits != 0,
"num_exponent_bits must be non-zero for a valid float");
static_assert(HF::num_fraction_bits != 0,
"num_fractin_bits must be non-zero for a valid float");
const uint_type bits = spvutils::BitwiseCast<uint_type>(value.value());
const char* const sign = (bits & HF::sign_mask) ? "-" : "";
const uint_type exponent = static_cast<uint_type>(

View File

@ -49,6 +49,7 @@
#include "spirv.hpp"
#include <algorithm>
#include <cassert>
#include <functional>
#include <iostream>
#include <memory>
@ -264,6 +265,7 @@ public:
void removeBlock(Block* block)
{
auto found = find(blocks.begin(), blocks.end(), block);
assert(found != blocks.end());
blocks.erase(found);
delete block;
}
@ -332,6 +334,7 @@ public:
spv::Id getTypeId(Id resultId) const { return idToInstruction[resultId]->getTypeId(); }
StorageClass getStorageClass(Id typeId) const
{
assert(idToInstruction[typeId]->getOpCode() == spv::OpTypePointer);
return (StorageClass)idToInstruction[typeId]->getImmediateOperand(0);
}

View File

@ -227,7 +227,7 @@ enum TBuiltInVariable {
EbvPositionPerViewNV,
EbvViewportMaskPerViewNV,
EbvFragFullyCoveredNV,
#endif
#endif
// HLSL built-ins that live only temporarily, until they get remapped
// to one of the above.
@ -365,7 +365,7 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
case EbvPositionPerViewNV: return "PositionPerViewNV";
case EbvViewportMaskPerViewNV: return "ViewportMaskPerViewNV";
case EbvFragFullyCoveredNV: return "FragFullyCoveredNV";
#endif
#endif
default: return "unknown built-in variable";
}
}
@ -453,6 +453,7 @@ __inline int getTypeRank(TBasicType type) {
res = 3;
break;
default:
assert(false);
break;
}
return res;

View File

@ -102,6 +102,7 @@ std::string to_string(const T& val) {
#include <algorithm>
#include <string>
#include <cstdio>
#include <cassert>
#include "PoolAlloc.h"
@ -256,11 +257,13 @@ template <class T> bool IsPow2(T powerOf2)
// a power, just a number that must be a power of 2.
template <class T> void RoundToPow2(T& number, int powerOf2)
{
assert(IsPow2(powerOf2));
number = (number + powerOf2 - 1) & ~(powerOf2 - 1);
}
template <class T> bool IsMultipleOfPow2(T number, int powerOf2)
{
assert(IsPow2(powerOf2));
return ! (number & (powerOf2 - 1));
}

View File

@ -264,7 +264,7 @@ public:
break;
default:
break;
assert(false && "Default missing");
}
return false;
@ -327,97 +327,118 @@ public:
bool operator>(const TConstUnion& constant) const
{
assert(type == constant.type);
switch (type) {
case EbtInt8:
if (i8Const > constant.i8Const)
return true;
break;
return false;
case EbtUint8:
if (u8Const > constant.u8Const)
return true;
break;
return false;
case EbtInt16:
if (i16Const > constant.i16Const)
return true;
break;
return false;
case EbtUint16:
if (u16Const > constant.u16Const)
return true;
break;
return false;
case EbtInt:
if (iConst > constant.iConst)
return true;
break;
return false;
case EbtUint:
if (uConst > constant.uConst)
return true;
break;
return false;
case EbtInt64:
if (i64Const > constant.i64Const)
return true;
break;
return false;
case EbtUint64:
if (u64Const > constant.u64Const)
return true;
break;
return false;
case EbtDouble:
if (dConst > constant.dConst)
return true;
break;
return false;
default:
break;
assert(false && "Default missing");
return false;
}
return false;
}
bool operator<(const TConstUnion& constant) const
{
assert(type == constant.type);
switch (type) {
case EbtInt8:
if (i8Const < constant.i8Const)
return true;
break;
return false;
case EbtUint8:
if (u8Const < constant.u8Const)
return true;
break;
return false;
case EbtInt16:
if (i16Const < constant.i16Const)
return true;
break;
return false;
case EbtUint16:
if (u16Const < constant.u16Const)
return true;
break;
return false;
case EbtInt:
if (iConst < constant.iConst)
return true;
break;
return false;
case EbtUint:
if (uConst < constant.uConst)
return true;
break;
return false;
case EbtInt64:
if (i64Const < constant.i64Const)
return true;
break;
return false;
case EbtUint64:
if (u64Const < constant.u64Const)
return true;
break;
return false;
case EbtDouble:
if (dConst < constant.dConst)
return true;
break;
return false;
default:
break;
assert(false && "Default missing");
return false;
}
return false;
}
TConstUnion operator+(const TConstUnion& constant) const
{
TConstUnion returnValue;
assert(type == constant.type);
switch (type) {
case EbtInt8: returnValue.setI8Const(i8Const + constant.i8Const); break;
case EbtInt16: returnValue.setI16Const(i16Const + constant.i16Const); break;
@ -428,7 +449,7 @@ public:
case EbtUint: returnValue.setUConst(uConst + constant.uConst); break;
case EbtUint64: returnValue.setU64Const(u64Const + constant.u64Const); break;
case EbtDouble: returnValue.setDConst(dConst + constant.dConst); break;
default: break;
default: assert(false && "Default missing");
}
return returnValue;
@ -437,6 +458,7 @@ public:
TConstUnion operator-(const TConstUnion& constant) const
{
TConstUnion returnValue;
assert(type == constant.type);
switch (type) {
case EbtInt8: returnValue.setI8Const(i8Const - constant.i8Const); break;
case EbtInt16: returnValue.setI16Const(i16Const - constant.i16Const); break;
@ -447,7 +469,7 @@ public:
case EbtUint: returnValue.setUConst(uConst - constant.uConst); break;
case EbtUint64: returnValue.setU64Const(u64Const - constant.u64Const); break;
case EbtDouble: returnValue.setDConst(dConst - constant.dConst); break;
default: break;
default: assert(false && "Default missing");
}
return returnValue;
@ -456,6 +478,7 @@ public:
TConstUnion operator*(const TConstUnion& constant) const
{
TConstUnion returnValue;
assert(type == constant.type);
switch (type) {
case EbtInt8: returnValue.setI8Const(i8Const * constant.i8Const); break;
case EbtInt16: returnValue.setI16Const(i16Const * constant.i16Const); break;
@ -466,7 +489,7 @@ public:
case EbtUint: returnValue.setUConst(uConst * constant.uConst); break;
case EbtUint64: returnValue.setU64Const(u64Const * constant.u64Const); break;
case EbtDouble: returnValue.setDConst(dConst * constant.dConst); break;
default: break;
default: assert(false && "Default missing");
}
return returnValue;
@ -475,6 +498,7 @@ public:
TConstUnion operator%(const TConstUnion& constant) const
{
TConstUnion returnValue;
assert(type == constant.type);
switch (type) {
case EbtInt8: returnValue.setI8Const(i8Const % constant.i8Const); break;
case EbtInt16: returnValue.setI8Const(i8Const % constant.i16Const); break;
@ -484,7 +508,7 @@ public:
case EbtUint16: returnValue.setU16Const(u16Const % constant.u16Const); break;
case EbtUint: returnValue.setUConst(uConst % constant.uConst); break;
case EbtUint64: returnValue.setU64Const(u64Const % constant.u64Const); break;
default: break;
default: assert(false && "Default missing");
}
return returnValue;
@ -504,7 +528,7 @@ public:
case EbtUint: returnValue.setI8Const(i8Const >> constant.uConst); break;
case EbtInt64: returnValue.setI8Const(i8Const >> constant.i64Const); break;
case EbtUint64: returnValue.setI8Const(i8Const >> constant.u64Const); break;
default: break;
default: assert(false && "Default missing");
}
break;
case EbtUint8:
@ -517,7 +541,7 @@ public:
case EbtUint: returnValue.setU8Const(u8Const >> constant.uConst); break;
case EbtInt64: returnValue.setU8Const(u8Const >> constant.i64Const); break;
case EbtUint64: returnValue.setU8Const(u8Const >> constant.u64Const); break;
default: break;
default: assert(false && "Default missing");
}
break;
case EbtInt16:
@ -530,7 +554,7 @@ public:
case EbtUint: returnValue.setI16Const(i16Const >> constant.uConst); break;
case EbtInt64: returnValue.setI16Const(i16Const >> constant.i64Const); break;
case EbtUint64: returnValue.setI16Const(i16Const >> constant.u64Const); break;
default: break;
default: assert(false && "Default missing");
}
break;
case EbtUint16:
@ -543,7 +567,7 @@ public:
case EbtUint: returnValue.setU16Const(u16Const >> constant.uConst); break;
case EbtInt64: returnValue.setU16Const(u16Const >> constant.i64Const); break;
case EbtUint64: returnValue.setU16Const(u16Const >> constant.u64Const); break;
default: break;
default: assert(false && "Default missing");
}
break;
case EbtInt:
@ -556,7 +580,7 @@ public:
case EbtUint: returnValue.setIConst(iConst >> constant.uConst); break;
case EbtInt64: returnValue.setIConst(iConst >> constant.i64Const); break;
case EbtUint64: returnValue.setIConst(iConst >> constant.u64Const); break;
default: break;
default: assert(false && "Default missing");
}
break;
case EbtUint:
@ -569,7 +593,7 @@ public:
case EbtUint: returnValue.setUConst(uConst >> constant.uConst); break;
case EbtInt64: returnValue.setUConst(uConst >> constant.i64Const); break;
case EbtUint64: returnValue.setUConst(uConst >> constant.u64Const); break;
default: break;
default: assert(false && "Default missing");
}
break;
case EbtInt64:
@ -582,7 +606,7 @@ public:
case EbtUint: returnValue.setI64Const(i64Const >> constant.uConst); break;
case EbtInt64: returnValue.setI64Const(i64Const >> constant.i64Const); break;
case EbtUint64: returnValue.setI64Const(i64Const >> constant.u64Const); break;
default: break;
default: assert(false && "Default missing");
}
break;
case EbtUint64:
@ -595,10 +619,10 @@ public:
case EbtUint: returnValue.setU64Const(u64Const >> constant.uConst); break;
case EbtInt64: returnValue.setU64Const(u64Const >> constant.i64Const); break;
case EbtUint64: returnValue.setU64Const(u64Const >> constant.u64Const); break;
default: break;
default: assert(false && "Default missing");
}
break;
default: break;
default: assert(false && "Default missing");
}
return returnValue;
@ -618,7 +642,7 @@ public:
case EbtUint: returnValue.setI8Const(i8Const << constant.uConst); break;
case EbtInt64: returnValue.setI8Const(i8Const << constant.i64Const); break;
case EbtUint64: returnValue.setI8Const(i8Const << constant.u64Const); break;
default: break;
default: assert(false && "Default missing");
}
break;
case EbtUint8:
@ -631,7 +655,7 @@ public:
case EbtUint: returnValue.setU8Const(u8Const << constant.uConst); break;
case EbtInt64: returnValue.setU8Const(u8Const << constant.i64Const); break;
case EbtUint64: returnValue.setU8Const(u8Const << constant.u64Const); break;
default: break;
default: assert(false && "Default missing");
}
break;
case EbtInt16:
@ -644,7 +668,7 @@ public:
case EbtUint: returnValue.setI16Const(i16Const << constant.uConst); break;
case EbtInt64: returnValue.setI16Const(i16Const << constant.i64Const); break;
case EbtUint64: returnValue.setI16Const(i16Const << constant.u64Const); break;
default: break;
default: assert(false && "Default missing");
}
break;
case EbtUint16:
@ -657,7 +681,7 @@ public:
case EbtUint: returnValue.setU16Const(u16Const << constant.uConst); break;
case EbtInt64: returnValue.setU16Const(u16Const << constant.i64Const); break;
case EbtUint64: returnValue.setU16Const(u16Const << constant.u64Const); break;
default: break;
default: assert(false && "Default missing");
}
break;
case EbtInt:
@ -670,7 +694,7 @@ public:
case EbtUint: returnValue.setIConst(iConst << constant.uConst); break;
case EbtInt64: returnValue.setIConst(iConst << constant.i64Const); break;
case EbtUint64: returnValue.setIConst(iConst << constant.u64Const); break;
default: break;
default: assert(false && "Default missing");
}
break;
case EbtUint:
@ -683,7 +707,7 @@ public:
case EbtUint: returnValue.setUConst(uConst << constant.uConst); break;
case EbtInt64: returnValue.setUConst(uConst << constant.i64Const); break;
case EbtUint64: returnValue.setUConst(uConst << constant.u64Const); break;
default: break;
default: assert(false && "Default missing");
}
break;
case EbtInt64:
@ -696,7 +720,7 @@ public:
case EbtUint: returnValue.setI64Const(i64Const << constant.uConst); break;
case EbtInt64: returnValue.setI64Const(i64Const << constant.i64Const); break;
case EbtUint64: returnValue.setI64Const(i64Const << constant.u64Const); break;
default: break;
default: assert(false && "Default missing");
}
break;
case EbtUint64:
@ -709,10 +733,10 @@ public:
case EbtUint: returnValue.setU64Const(u64Const << constant.uConst); break;
case EbtInt64: returnValue.setU64Const(u64Const << constant.i64Const); break;
case EbtUint64: returnValue.setU64Const(u64Const << constant.u64Const); break;
default: break;
default: assert(false && "Default missing");
}
break;
default: break;
default: assert(false && "Default missing");
}
return returnValue;
@ -721,6 +745,7 @@ public:
TConstUnion operator&(const TConstUnion& constant) const
{
TConstUnion returnValue;
assert(type == constant.type);
switch (type) {
case EbtInt8: returnValue.setI8Const(i8Const & constant.i8Const); break;
case EbtUint8: returnValue.setU8Const(u8Const & constant.u8Const); break;
@ -730,7 +755,7 @@ public:
case EbtUint: returnValue.setUConst(uConst & constant.uConst); break;
case EbtInt64: returnValue.setI64Const(i64Const & constant.i64Const); break;
case EbtUint64: returnValue.setU64Const(u64Const & constant.u64Const); break;
default: break;
default: assert(false && "Default missing");
}
return returnValue;
@ -739,6 +764,7 @@ public:
TConstUnion operator|(const TConstUnion& constant) const
{
TConstUnion returnValue;
assert(type == constant.type);
switch (type) {
case EbtInt8: returnValue.setI8Const(i8Const | constant.i8Const); break;
case EbtUint8: returnValue.setU8Const(u8Const | constant.u8Const); break;
@ -748,7 +774,7 @@ public:
case EbtUint: returnValue.setUConst(uConst | constant.uConst); break;
case EbtInt64: returnValue.setI64Const(i64Const | constant.i64Const); break;
case EbtUint64: returnValue.setU64Const(u64Const | constant.u64Const); break;
default: break;
default: assert(false && "Default missing");
}
return returnValue;
@ -757,6 +783,7 @@ public:
TConstUnion operator^(const TConstUnion& constant) const
{
TConstUnion returnValue;
assert(type == constant.type);
switch (type) {
case EbtInt8: returnValue.setI8Const(i8Const ^ constant.i8Const); break;
case EbtUint8: returnValue.setU8Const(u8Const ^ constant.u8Const); break;
@ -766,7 +793,7 @@ public:
case EbtUint: returnValue.setUConst(uConst ^ constant.uConst); break;
case EbtInt64: returnValue.setI64Const(i64Const ^ constant.i64Const); break;
case EbtUint64: returnValue.setU64Const(u64Const ^ constant.u64Const); break;
default: break;
default: assert(false && "Default missing");
}
return returnValue;
@ -784,7 +811,7 @@ public:
case EbtUint: returnValue.setUConst(~uConst); break;
case EbtInt64: returnValue.setI64Const(~i64Const); break;
case EbtUint64: returnValue.setU64Const(~u64Const); break;
default: break;
default: assert(false && "Default missing");
}
return returnValue;
@ -793,9 +820,10 @@ public:
TConstUnion operator&&(const TConstUnion& constant) const
{
TConstUnion returnValue;
assert(type == constant.type);
switch (type) {
case EbtBool: returnValue.setBConst(bConst && constant.bConst); break;
default: break;
default: assert(false && "Default missing");
}
return returnValue;
@ -804,9 +832,10 @@ public:
TConstUnion operator||(const TConstUnion& constant) const
{
TConstUnion returnValue;
assert(type == constant.type);
switch (type) {
case EbtBool: returnValue.setBConst(bConst || constant.bConst); break;
default: break;
default: assert(false && "Default missing");
}
return returnValue;
@ -888,9 +917,12 @@ public:
double dot(const TConstUnionArray& rhs)
{
assert(rhs.unionArray->size() == unionArray->size());
double sum = 0.0;
for (size_t comp = 0; comp < unionArray->size(); ++comp)
sum += (*this)[comp].getDConst() * rhs[comp].getDConst();
return sum;
}

View File

@ -187,7 +187,7 @@ struct TSampler { // misnomer now; includes images, textures without sampler,
sampler == right.sampler &&
external == right.external &&
vectorSize == right.vectorSize &&
structReturnIndex == right.structReturnIndex;
structReturnIndex == right.structReturnIndex;
}
bool operator!=(const TSampler& right) const
@ -1179,6 +1179,7 @@ public:
sampler.clear();
qualifier.clear();
qualifier.storage = q;
assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices
}
// for explicit precision qualifier
TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0,
@ -1190,6 +1191,8 @@ public:
qualifier.clear();
qualifier.storage = q;
qualifier.precision = p;
assert(p >= EpqNone && p <= EpqHigh);
assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices
}
// for turning a TPublicType into a TType, using a shallow copy
explicit TType(const TPublicType& p) :
@ -1325,11 +1328,13 @@ public:
virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); }
virtual const TString& getTypeName() const
{
assert(typeName);
return *typeName;
}
virtual const TString& getFieldName() const
{
assert(fieldName);
return *fieldName;
}
@ -1358,9 +1363,9 @@ public:
virtual bool isArray() const { return arraySizes != nullptr; }
virtual bool isSizedArray() const { return isArray() && arraySizes->isSized(); }
virtual bool isUnsizedArray() const { return isArray() && !arraySizes->isSized(); }
virtual bool isArrayVariablyIndexed() const { return arraySizes->isVariablyIndexed(); }
virtual void setArrayVariablyIndexed() { arraySizes->setVariablyIndexed(); }
virtual void updateImplicitArraySize(int size) { arraySizes->updateImplicitSize(size); }
virtual bool isArrayVariablyIndexed() const { assert(isArray()); return arraySizes->isVariablyIndexed(); }
virtual void setArrayVariablyIndexed() { assert(isArray()); arraySizes->setVariablyIndexed(); }
virtual void updateImplicitArraySize(int size) { assert(isArray()); arraySizes->updateImplicitSize(size); }
virtual bool isStruct() const { return structure != nullptr; }
virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; }
virtual bool isIntegerDomain() const
@ -1482,6 +1487,8 @@ public:
{
// For when we may already be sharing existing array descriptors,
// keeping the pointers the same, just updating the contents.
assert(arraySizes != nullptr);
assert(type.arraySizes != nullptr);
*arraySizes = *type.arraySizes;
}
void copyArraySizes(const TArraySizes& s)
@ -1848,6 +1855,7 @@ public:
// See if two type's arrayness match in everything except their outer dimension
bool sameInnerArrayness(const TType& right) const
{
assert(arraySizes != nullptr && right.arraySizes != nullptr);
return arraySizes->sameInnerArrayness(*right.arraySizes);
}

View File

@ -107,16 +107,21 @@ struct TSmallArrayVector {
unsigned int frontSize() const
{
assert(sizes != nullptr && sizes->size() > 0);
return sizes->front().size;
}
TIntermTyped* frontNode() const
{
assert(sizes != nullptr && sizes->size() > 0);
return sizes->front().node;
}
void changeFront(unsigned int s)
{
assert(sizes != nullptr);
// this should only happen for implicitly sized arrays, not specialization constants
assert(sizes->front().node == nullptr);
sizes->front().size = s;
}
@ -135,6 +140,7 @@ struct TSmallArrayVector {
void pop_front()
{
assert(sizes != nullptr && sizes->size() > 0);
if (sizes->size() == 1)
dealloc();
else
@ -147,6 +153,7 @@ struct TSmallArrayVector {
// one dimension.)
void copyNonFront(const TSmallArrayVector& rhs)
{
assert(sizes == nullptr);
if (rhs.size() > 1) {
alloc();
sizes->insert(sizes->begin(), rhs.sizes->begin() + 1, rhs.sizes->end());
@ -155,16 +162,20 @@ struct TSmallArrayVector {
unsigned int getDimSize(int i) const
{
assert(sizes != nullptr && (int)sizes->size() > i);
return (*sizes)[i].size;
}
void setDimSize(int i, unsigned int size) const
{
assert(sizes != nullptr && (int)sizes->size() > i);
assert((*sizes)[i].node == nullptr);
(*sizes)[i].size = size;
}
TIntermTyped* getDimNode(int i) const
{
assert(sizes != nullptr && (int)sizes->size() > i);
return (*sizes)[i].node;
}
@ -235,6 +246,7 @@ struct TArraySizes {
int size = 1;
for (int d = 0; d < sizes.size(); ++d) {
// this only makes sense in paths that have a known array size
assert(sizes.getDimSize(d) != UnsizedArraySize);
size *= sizes.getDimSize(d);
}
return size;
@ -284,6 +296,7 @@ struct TArraySizes {
void dereference() { sizes.pop_front(); }
void copyDereferenced(const TArraySizes& rhs)
{
assert(sizes.size() == 0);
if (rhs.sizes.size() > 1)
sizes.copyNonFront(rhs.sizes);
}

View File

@ -342,7 +342,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* right
for (int i = 0; i < newComps; i++) {
switch (getType().getBasicType()) {
case EbtBool: newConstArray[i].setBConst((leftUnionArray[i] == rightUnionArray[i]) ? false : true); break;
default: break;
default: assert(false && "Default missing");
}
}
break;
@ -505,6 +505,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
return 0;
default:
assert(componentWise);
break;
}
@ -816,7 +817,7 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
case EbtUint64:
newConstArray[comp].setU64Const(std::min(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
break;
default: break;
default: assert(false && "Default missing");
}
break;
case EOpMax:
@ -850,7 +851,7 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
case EbtUint64:
newConstArray[comp].setU64Const(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()));
break;
default: break;
default: assert(false && "Default missing");
}
break;
case EOpClamp:
@ -893,7 +894,7 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
newConstArray[comp].setU64Const(std::min(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()),
childConstUnions[2][arg2comp].getU64Const()));
break;
default: break;
default: assert(false && "Default missing");
}
break;
case EOpLessThan:
@ -1076,6 +1077,7 @@ TIntermTyped* TIntermediate::foldDereference(TIntermTyped* node, int index, cons
start = size * index;
else {
// it is a structure
assert(node->isStruct());
start = 0;
for (int i = 0; i < index; ++i)
start += (*node->getType().getStruct())[i].type->computeNumComponents();

View File

@ -6255,6 +6255,7 @@ void TBuiltIns::addSamplingFunctions(TSampler sampler, const TString& typeName,
compare = true;
totalDims = 4;
}
assert(totalDims <= 4);
if (extraProj && ! proj)
continue;
@ -8058,6 +8059,7 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
break;
default:
assert(false && "Language not supported");
break;
}
@ -8566,7 +8568,7 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
break;
default:
break;
assert(false && "Language not supported");
}
}

View File

@ -1582,8 +1582,10 @@ static bool canSignedIntTypeRepresentAllUnsignedValues(TBasicType sintType, TBas
case EbtUint16:
case EbtUint:
case EbtUint64:
return false;
default:
break;
assert(false);
return false;
}
break;
case EbtInt16:
@ -1593,8 +1595,10 @@ static bool canSignedIntTypeRepresentAllUnsignedValues(TBasicType sintType, TBas
case EbtUint16:
case EbtUint:
case EbtUint64:
return false;
default:
break;
assert(false);
return false;
}
break;
case EbtInt:
@ -1603,8 +1607,10 @@ static bool canSignedIntTypeRepresentAllUnsignedValues(TBasicType sintType, TBas
case EbtUint16:
return true;
case EbtUint:
return false;
default:
break;
assert(false);
return false;
}
break;
case EbtInt64:
@ -1614,14 +1620,16 @@ static bool canSignedIntTypeRepresentAllUnsignedValues(TBasicType sintType, TBas
case EbtUint:
return true;
case EbtUint64:
return false;
default:
break;
assert(false);
return false;
}
break;
default:
break;
assert(false);
return false;
}
return false;
}
@ -1636,9 +1644,9 @@ static TBasicType getCorrespondingUnsignedType(TBasicType type) {
case EbtInt64:
return EbtUint64;
default:
break;
assert(false);
return EbtNumTypes;
}
return EbtNumTypes;
}
// Implements the following rules
@ -2355,6 +2363,8 @@ TIntermConstantUnion* TIntermediate::addConstantUnion(bool b, const TSourceLoc&
TIntermConstantUnion* TIntermediate::addConstantUnion(double d, TBasicType baseType, const TSourceLoc& loc, bool literal) const
{
assert(baseType == EbtFloat || baseType == EbtDouble || baseType == EbtFloat16);
TConstUnionArray unionArray(1);
unionArray[0].setDConst(d);
@ -3732,6 +3742,7 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC
void TIntermAggregate::setPragmaTable(const TPragmaTable& pTable)
{
assert(pragmaTable == nullptr);
pragmaTable = new TPragmaTable;
*pragmaTable = pTable;
}
@ -3757,6 +3768,8 @@ struct TextureUpgradeAndSamplerRemovalTransform : public TIntermTraverser {
TQualifierList& qual = ag->getQualifierList();
// qual and seq are indexed using the same indices, so we have to modify both in lock-step
assert(seq.size() == qual.size() || qual.empty());
size_t write = 0;
for (size_t i = 0; i < seq.size(); ++i) {
TIntermSymbol* symbol = seq[i]->getAsSymbolNode();

View File

@ -283,6 +283,8 @@ TVariable* TParseContextBase::getEditableVariable(const char* name)
{
bool builtIn;
TSymbol* symbol = symbolTable.find(name, &builtIn);
assert(symbol != nullptr);
if (symbol == nullptr)
return nullptr;

View File

@ -491,6 +491,8 @@ void TParseContext::fixIoArraySize(const TSourceLoc& loc, TType& type)
if (! type.isArray() || type.getQualifier().patch || symbolTable.atBuiltInLevel())
return;
assert(! isIoResizeArray(type));
if (type.getQualifier().storage != EvqVaryingIn || type.getQualifier().patch)
return;
@ -524,6 +526,7 @@ void TParseContext::ioArrayCheck(const TSourceLoc& loc, const TType& type, const
void TParseContext::handleIoResizeArrayAccess(const TSourceLoc& /*loc*/, TIntermTyped* base)
{
TIntermSymbol* symbolNode = base->getAsSymbolNode();
assert(symbolNode);
if (! symbolNode)
return;
@ -1392,6 +1395,7 @@ void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCan
if (argp->size() > 0)
arg0 = (*argp)[0]->getAsTyped();
} else {
assert(callNode.getAsUnaryNode());
unaryArg = callNode.getAsUnaryNode()->getOperand();
arg0 = unaryArg;
}
@ -1723,6 +1727,8 @@ void TParseContext::nonOpBuiltInCheck(const TSourceLoc& loc, const TFunction& fn
// If PureOperatorBuiltins == true, then all built-ins should be mapped
// to a TOperator, and this function would then never get called.
assert(PureOperatorBuiltins == false);
// built-in texturing functions get their return value precision from the precision of the sampler
if (fnCandidate.getType().getQualifier().precision == EpqNone &&
fnCandidate.getParamCount() > 0 && fnCandidate[0].type->getBasicType() == EbtSampler)
@ -2963,6 +2969,8 @@ int TParseContext::computeSamplerTypeIndex(TSampler& sampler)
int flattened = EsdNumDims * (EbtNumTypes * (2 * (2 * (2 * (2 * arrayIndex + msIndex) + imageIndex) + shadowIndex) +
externalIndex) + sampler.type) + sampler.dim;
assert(flattened < maxSamplerIndex);
return flattened;
}
@ -3128,6 +3136,8 @@ void TParseContext::structArrayCheck(const TSourceLoc& /*loc*/, const TType& typ
void TParseContext::arraySizesCheck(const TSourceLoc& loc, const TQualifier& qualifier, TArraySizes* arraySizes,
const TIntermTyped* initializer, bool lastMember)
{
assert(arraySizes);
// always allow special built-in ins/outs sized to topologies
if (parsingBuiltins)
return;
@ -3935,7 +3945,9 @@ void TParseContext::arrayLimitCheck(const TSourceLoc& loc, const TString& identi
void TParseContext::limitCheck(const TSourceLoc& loc, int value, const char* limit, const char* feature)
{
TSymbol* symbol = symbolTable.find(limit);
assert(symbol->getAsVariable());
const TConstUnionArray& constArray = symbol->getAsVariable()->getConstArray();
assert(! constArray.empty());
if (value > constArray[0].getIConst())
error(loc, "must be less than or equal to", feature, "%s (%d)", limit, constArray[0].getIConst());
}
@ -4100,6 +4112,8 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi
}
#endif
} else {
assert(language == EShLangTessEvaluation);
// input primitive
if (id == TQualifier::getGeometryString(ElgTriangles)) {
publicType.shaderQualifiers.geometry = ElgTriangles;
@ -5584,6 +5598,7 @@ TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyp
// We either have a folded constant in getAsConstantUnion, or we have to use
// the initializer's subtree in the AST to represent the computation of a
// specialization constant.
assert(initializer->getAsConstantUnion() || initializer->getType().getQualifier().isSpecConstant());
if (initializer->getAsConstantUnion())
variable->setConstArray(initializer->getAsConstantUnion()->getConstArray());
else {
@ -6472,6 +6487,7 @@ void TParseContext::invariantCheck(const TSourceLoc& loc, const TQualifier& qual
void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, const TPublicType& publicType)
{
if (publicType.shaderQualifiers.vertices != TQualifier::layoutNotSet) {
assert(language == EShLangTessControl || language == EShLangGeometry);
const char* id = (language == EShLangTessControl) ? "vertices" : "max_vertices";
if (publicType.qualifier.storage != EvqVaryingOut)

View File

@ -131,6 +131,9 @@ int MapVersionToIndex(int version)
case 460: index = 16; break;
default: break;
}
assert(index < VersionCount);
return index;
}
@ -144,6 +147,9 @@ int MapSpvVersionToIndex(const SpvVersion& spvVersion)
index = 1;
else if (spvVersion.vulkan > 0)
index = 2;
assert(index < SpvVersionCount);
return index;
}
@ -160,6 +166,9 @@ int MapProfileToIndex(EProfile profile)
case EEsProfile: index = 3; break;
default: break;
}
assert(index < ProfileCount);
return index;
}
@ -174,6 +183,9 @@ int MapSourceToIndex(EShSource source)
case EShSourceHlsl: index = 1; break;
default: break;
}
assert(index < SourceCount);
return index;
}
@ -854,6 +866,7 @@ bool ProcessDeferred(
strings[1] = customPreamble;
lengths[1] = strlen(strings[1]);
names[1] = nullptr;
assert(2 == numPre);
if (requireNonempty) {
const int postIndex = numStrings + numPre;
strings[postIndex] = "\n int;";
@ -1240,6 +1253,7 @@ int __fastcall ShFinalize()
{
glslang::GetGlobalLock();
--NumberOfClients;
assert(NumberOfClients >= 0);
bool finalize = NumberOfClients == 0;
glslang::ReleaseGlobalLock();
if (! finalize)

View File

@ -289,6 +289,7 @@ TVariable::TVariable(const TVariable& copyOf) : TSymbol(copyOf)
setExtensions(copyOf.numExtensions, copyOf.extensions);
if (! copyOf.constArray.empty()) {
assert(! copyOf.type.isStruct());
TConstUnionArray newArray(copyOf.constArray, 0, copyOf.constArray.size());
constArray = newArray;
}
@ -367,6 +368,8 @@ TSymbolTableLevel* TSymbolTableLevel::clone() const
void TSymbolTable::copyTable(const TSymbolTable& copyOf)
{
assert(adoptedLevels == copyOf.adoptedLevels);
uniqueId = copyOf.uniqueId;
noBuiltInRedeclarations = copyOf.noBuiltInRedeclarations;
separateNameSpaces = copyOf.separateNameSpaces;

View File

@ -105,6 +105,8 @@ public:
virtual int getUniqueId() const { return uniqueId; }
virtual void setExtensions(int num, const char* const exts[])
{
assert(extensions == 0);
assert(num > 0);
numExtensions = num;
extensions = NewPoolObject(exts[0], num);
for (int e = 0; e < num; ++e)
@ -159,10 +161,10 @@ public:
virtual TVariable* getAsVariable() { return this; }
virtual const TVariable* getAsVariable() const { return this; }
virtual const TType& getType() const { return type; }
virtual TType& getWritableType() { return type; }
virtual TType& getWritableType() { assert(writable); return type; }
virtual bool isUserType() const { return userType; }
virtual const TConstUnionArray& getConstArray() const { return constArray; }
virtual TConstUnionArray& getWritableConstArray() { return constArray; }
virtual TConstUnionArray& getWritableConstArray() { assert(writable); return constArray; }
virtual void setConstArray(const TConstUnionArray& array) { constArray = array; }
virtual void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; }
virtual TIntermTyped* getConstSubtree() const { return constSubtree; }
@ -237,6 +239,7 @@ public:
// mangled name.
virtual void addParameter(TParameter& p)
{
assert(writable);
parameters.push_back(p);
p.type->appendMangledName(mangledName);
@ -261,6 +264,7 @@ public:
virtual void removePrefix(const TString& prefix)
{
assert(mangledName.compare(0, prefix.size(), prefix) == 0);
mangledName.erase(0, prefix.size());
}
@ -268,15 +272,15 @@ public:
virtual const TType& getType() const override { return returnType; }
virtual TBuiltInVariable getDeclaredBuiltInType() const { return declaredBuiltIn; }
virtual TType& getWritableType() override { return returnType; }
virtual void relateToOperator(TOperator o) { op = o; }
virtual void relateToOperator(TOperator o) { assert(writable); op = o; }
virtual TOperator getBuiltInOp() const { return op; }
virtual void setDefined() { defined = true; }
virtual void setDefined() { assert(writable); defined = true; }
virtual bool isDefined() const { return defined; }
virtual void setPrototyped() { prototyped = true; }
virtual void setPrototyped() { assert(writable); prototyped = true; }
virtual bool isPrototyped() const { return prototyped; }
virtual void setImplicitThis() { implicitThis = true; }
virtual void setImplicitThis() { assert(writable); implicitThis = true; }
virtual bool hasImplicitThis() const { return implicitThis; }
virtual void setIllegalImplicitThis() { illegalImplicitThis = true; }
virtual void setIllegalImplicitThis() { assert(writable); illegalImplicitThis = true; }
virtual bool hasIllegalImplicitThis() const { return illegalImplicitThis; }
// Return total number of parameters
@ -286,7 +290,7 @@ public:
// Return number of fixed parameters (without default values)
virtual int getFixedParamCount() const { return getParamCount() - getDefaultParamCount(); }
virtual TParameter& operator[](int i) { return parameters[i]; }
virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; }
virtual const TParameter& operator[](int i) const { return parameters[i]; }
virtual void dump(TInfoSink &infoSink) const override;
@ -336,6 +340,7 @@ public:
virtual TType& getWritableType()
{
assert(writable);
const TTypeList& types = *anonContainer.getType().getStruct();
return *types[memberNumber].type;
}
@ -593,6 +598,7 @@ public:
// symbol finds.
void pushThis(TSymbol& thisSymbol)
{
assert(thisSymbol.getName().size() == 0);
table.push_back(new TSymbolTableLevel);
table.back()->setThisLevel();
insert(thisSymbol);
@ -664,6 +670,7 @@ public:
return copy;
} else {
const TAnonMember* anon = shared->getAsAnonMember();
assert(anon);
TVariable* container = anon->getAnonContainer().clone();
container->changeName(NewPoolTString(""));
container->setUniqueId(anon->getAnonContainer().getUniqueId());

View File

@ -1112,6 +1112,7 @@ static void OutputDouble(TInfoSink& out, double value, TOutputTraverser::EExtraO
if (fabs(value) > 0.0 && (fabs(value) < 1e-5 || fabs(value) > 1e12))
format = "%-.13e";
int len = snprintf(buf, maxSize, format, value);
assert(len < maxSize);
// remove a leading zero in the 100s slot in exponent; it is not portable
// pattern: XX...XXXe+0XX or XX...XXXe-0XX

View File

@ -235,6 +235,7 @@ void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& lin
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;
@ -719,6 +720,10 @@ TIntermSequence& TIntermediate::findLinkerObjects() const
{
// Get the top-level globals
TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence();
// Get the last member of the sequences, expected to be the linker-object lists
assert(globals.back()->getAsAggregate()->getOp() == EOpLinkerObjects);
return globals.back()->getAsAggregate()->getSequence();
}
@ -1003,6 +1008,7 @@ int TIntermediate::addXfbBufferOffset(const TType& type)
{
const TQualifier& qualifier = type.getQualifier();
assert(qualifier.hasXfbOffset() && qualifier.hasXfbBuffer());
TXfbBuffer& buffer = xfbBuffers[qualifier.layoutXfbBuffer];
// compute the range
@ -1038,6 +1044,7 @@ unsigned int TIntermediate::computeTypeXfbSize(const TType& type, bool& contains
if (type.isArray()) {
// TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
assert(type.isSizedArray());
TType elementType(type, 0);
return type.getOuterArraySize() * computeTypeXfbSize(elementType, containsDouble);
}

View File

@ -70,11 +70,13 @@ public:
}
void resize(int s)
{
assert(s <= size_);
size_ = s;
}
int size() const { return size_; }
selectorType operator[](int i) const
{
assert(i < MaxSwizzleSelectors);
return components[i];
}

View File

@ -855,6 +855,7 @@ int TPpContext::CPPextension(TPpToken* ppToken)
if (token != PpAtomIdentifier)
_parseContext.ppError(ppToken->loc, "extension name expected", "#extension", "");
assert(strlen(ppToken->name) <= MaxTokenLength);
strcpy(extensionName, ppToken->name);
token = scanToken(ppToken);
@ -1062,6 +1063,7 @@ int TPpContext::tMacroInput::scan(TPpToken* ppToken)
if (prepaste) {
// already know we should be on a ##, verify
assert(token == PpAtomPaste);
prepaste = false;
postpaste = true;
}

View File

@ -80,6 +80,7 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <cassert>
#include <cstdlib>
#include <cstring>

View File

@ -107,6 +107,8 @@ TPpContext::~TPpContext()
void TPpContext::setInput(TInputScanner& input, bool versionWillBeError)
{
assert(inputStack.size() == 0);
pushInput(new tStringInput(this, input));
errorOnVersion = versionWillBeError;

View File

@ -666,7 +666,7 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
#ifdef AMD_EXTENSIONS
nextCh = getch();
if ((nextCh == 's' || nextCh == 'S') &&
if ((nextCh == 's' || nextCh == 'S') &&
pp->_parseContext.intermediate.getSource() == EShSourceGlsl) {
if (len < MaxTokenLength)
ppToken->name[len++] = (char)nextCh;
@ -679,7 +679,7 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
ppToken->name[len++] = (char)ch;
isInt64 = true;
#ifdef AMD_EXTENSIONS
} else if ((ch == 's' || ch == 'S') &&
} else if ((ch == 's' || ch == 'S') &&
pp->_parseContext.intermediate.getSource() == EShSourceGlsl) {
if (len < MaxTokenLength)
ppToken->name[len++] = (char)ch;
@ -1118,6 +1118,7 @@ int TPpContext::tokenPaste(int token, TPpToken& ppToken)
// next token has to be ##
token = scanToken(&pastedPpToken);
assert(token == PpAtomPaste);
// This covers end of macro expansion
if (endOfReplacementList()) {

View File

@ -89,6 +89,7 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif
#endif
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <cctype>
@ -175,6 +176,7 @@ void TPpContext::TokenStream::ungetSubtoken()
void TPpContext::TokenStream::putToken(int atom, TPpToken* ppToken)
{
// save the atom
assert((atom & ~0xff) == 0);
putSubtoken(static_cast<char>(atom));
// save the backing name string

View File

@ -131,6 +131,7 @@ bool isAssignOperation(glslang::TOperator op)
// Note the node should only hold a uint scalar.
unsigned getStructIndexFromConstantUnion(glslang::TIntermTyped* node)
{
assert(node->getAsConstantUnion() && node->getAsConstantUnion()->isScalar());
unsigned struct_dereference_index = node->getAsConstantUnion()->getConstArray()[0].getUConst();
return struct_dereference_index;
}
@ -332,6 +333,7 @@ bool TSymbolDefinitionCollectingTraverser::visitUnary(glslang::TVisit /* visit *
node->getOperand()->traverse(this);
if (isAssignOperation(node->getOp())) {
// We should always be able to get an access chain of the operand node.
assert(!current_object_.empty());
// If the operand node object is 'precise', we collect its access chain
// for the initial set of 'precise' objects.
@ -363,6 +365,7 @@ bool TSymbolDefinitionCollectingTraverser::visitBinary(glslang::TVisit /* visit
if (isAssignOperation(node->getOp())) {
// We should always be able to get an access chain for the left node.
assert(!current_object_.empty());
// If the left node object is 'precise', it is an initial precise object
// specified in the shader source. Adds it to the initial work list to
@ -482,19 +485,22 @@ public:
getPrecisenessAndRemainedAccessChain(glslang::TIntermOperator* node,
const ObjectAccessChain& precise_object)
{
assert(isAssignOperation(node->getOp()));
precise_object_ = &precise_object;
ObjectAccessChain assignee_object;
if (glslang::TIntermBinary* BN = node->getAsBinaryNode()) {
// This is a binary assignment node, we need to check the
// preciseness of the left node.
assert(accesschain_mapping_.count(BN->getLeft()));
// The left node (assignee node) is an object node, traverse the
// node to let the 'precise' of nesting objects being transfered to
// nested objects.
BN->getLeft()->traverse(this);
// After traversing the left node, if the left node is 'precise',
// we can conclude this assignment should propagate 'precise'.
if (isPreciseObjectNode(BN->getLeft()))
if (isPreciseObjectNode(BN->getLeft())) {
return make_tuple(true, ObjectAccessChain());
}
// If the preciseness of the left node (assignee node) can not
// be determined by now, we need to compare the access chain string
// of the assignee object with the given precise object.
@ -504,7 +510,7 @@ public:
// This is a unary assignment node, we need to check the
// preciseness of the operand node. For unary assignment node, the
// operand node should always be an object node.
assert(accesschain_mapping_.count(UN->getOperand()));
// Traverse the operand node to let the 'precise' being propagated
// from lower nodes to upper nodes.
UN->getOperand()->traverse(this);
@ -517,6 +523,9 @@ public:
// be determined by now, we need to compare the access chain string
// of the assignee object with the given precise object.
assignee_object = accesschain_mapping_.at(UN->getOperand());
} else {
// Not a binary or unary node, should not happen.
assert(false);
}
// Compare the access chain string of the assignee node with the given
@ -569,15 +578,16 @@ bool TNoContractionAssigneeCheckingTraverser::visitBinary(glslang::TVisit,
// accesschain_mapping_.
if (accesschain_mapping_.count(node)) {
// A binary object node must be a dereference node.
assert(isDereferenceOperation(node->getOp()));
// If the left node is 'precise', this node should also be precise,
// otherwise, compare with the given precise_object_. If the
// access chain of this node matches with the given precise_object_,
// this node should be marked as 'precise'.
if (isPreciseObjectNode(node->getLeft()))
if (isPreciseObjectNode(node->getLeft())) {
node->getWritableType().getQualifier().noContraction = true;
else if (accesschain_mapping_.at(node) == *precise_object_)
} else if (accesschain_mapping_.at(node) == *precise_object_) {
node->getWritableType().getQualifier().noContraction = true;
}
}
return false;
}
@ -588,8 +598,10 @@ void TNoContractionAssigneeCheckingTraverser::visitSymbol(glslang::TIntermSymbol
{
// A symbol node should always be an object node, and should have been added
// to the map from object nodes to their access chain strings.
if (accesschain_mapping_.at(node) == *precise_object_)
assert(accesschain_mapping_.count(node));
if (accesschain_mapping_.at(node) == *precise_object_) {
node->getWritableType().getQualifier().noContraction = true;
}
}
//
@ -618,13 +630,17 @@ public:
{
remained_accesschain_ = assignee_remained_accesschain;
if (glslang::TIntermBinary* BN = defining_node->getAsBinaryNode()) {
assert(isAssignOperation(BN->getOp()));
BN->getRight()->traverse(this);
if (isArithmeticOperation(BN->getOp()))
if (isArithmeticOperation(BN->getOp())) {
BN->getWritableType().getQualifier().noContraction = true;
}
} else if (glslang::TIntermUnary* UN = defining_node->getAsUnaryNode()) {
assert(isAssignOperation(UN->getOp()));
UN->getOperand()->traverse(this);
if (isArithmeticOperation(UN->getOp()))
if (isArithmeticOperation(UN->getOp())) {
UN->getWritableType().getQualifier().noContraction = true;
}
}
}
@ -632,6 +648,7 @@ public:
void propagateNoContractionInReturnNode(glslang::TIntermBranch* return_node)
{
remained_accesschain_ = "";
assert(return_node->getFlowOp() == glslang::EOpReturn && return_node->getExpression());
return_node->getExpression()->traverse(this);
}
@ -658,6 +675,7 @@ protected:
// Gets the node pointed by the access chain index extracted before.
glslang::TIntermTyped* potential_precise_node =
node->getSequence()[precise_accesschain_index]->getAsTyped();
assert(potential_precise_node);
// Pop the front access chain index from the path, and visit the nested node.
{
ObjectAccessChain next_level_accesschain =
@ -727,15 +745,17 @@ protected:
{
// Symbol nodes are object nodes and should always have an
// access chain collected before matches with it.
assert(accesschain_mapping_.count(node));
ObjectAccessChain new_precise_accesschain = accesschain_mapping_.at(node);
// If the unused access chain is empty, this symbol node should be
// marked as 'precise'. Otherwise, the unused access chain should be
// appended to the symbol ID to build a new access chain which points to
// the nested 'precise' object in this symbol object.
if (remained_accesschain_.empty())
if (remained_accesschain_.empty()) {
node->getWritableType().getQualifier().noContraction = true;
else
} else {
new_precise_accesschain += ObjectAccesschainDelimiter + remained_accesschain_;
}
// Add the new 'precise' access chain to the work list and make sure we
// don't visit it again.
if (!added_precise_object_ids_.count(new_precise_accesschain)) {

View File

@ -306,6 +306,8 @@ public:
if (base->getType().isArray()) {
TType derefType(base->getType(), 0);
assert(! anonymous);
for (int e = 0; e < base->getType().getCumulativeArraySize(); ++e)
blockIndex = addBlockName(blockName + "[" + String(e) + "]", derefType,
getBlockSize(base->getType()));

View File

@ -38,6 +38,7 @@
#define STRICT
#define VC_EXTRALEAN 1
#include <windows.h>
#include <cassert>
#include <process.h>
#include <psapi.h>
#include <cstdio>
@ -85,6 +86,7 @@ bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
void* OS_GetTLSValue(OS_TLSIndex nIndex)
{
assert(nIndex != OS_INVALID_TLS_INDEX);
return TlsGetValue(ToNativeTLSIndex(nIndex));
}