Updated glslang.

This commit is contained in:
Бранимир Караџић 2023-05-04 22:23:10 -07:00
parent ddfae2f915
commit bf5fda9ae7
9 changed files with 2306 additions and 2182 deletions

View File

@ -2004,6 +2004,10 @@ void TGlslangToSpvTraverser::dumpSpv(std::vector<unsigned int>& out)
//
void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
{
// We update the line information even though no code might be generated here
// This is helpful to yield correct lines for control flow instructions
builder.setLine(symbol->getLoc().line, symbol->getLoc().getFilename());
SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
if (symbol->getType().isStruct())
glslangTypeToIdMap[symbol->getType().getStruct()] = symbol->getId();
@ -2155,6 +2159,9 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
node->getRight()->traverse(this);
spv::Id rValue = accessChainLoad(node->getRight()->getType());
// reset line number for assignment
builder.setLine(node->getLoc().line, node->getLoc().getFilename());
if (node->getOp() != glslang::EOpAssign) {
// the left is also an r-value
builder.setAccessChain(lValue);
@ -3782,10 +3789,11 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
// Find a way of executing both sides and selecting the right result.
const auto executeBothSides = [&]() -> void {
// execute both sides
spv::Id resultType = convertGlslangToSpvType(node->getType());
node->getTrueBlock()->traverse(this);
spv::Id trueValue = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType());
node->getFalseBlock()->traverse(this);
spv::Id falseValue = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType());
spv::Id falseValue = accessChainLoad(node->getFalseBlock()->getAsTyped()->getType());
builder.setLine(node->getLoc().line, node->getLoc().getFilename());
@ -3794,8 +3802,8 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
return;
// emit code to select between trueValue and falseValue
// see if OpSelect can handle it
// see if OpSelect can handle the result type, and that the SPIR-V types
// of the inputs match the result type.
if (isOpSelectable()) {
// Emit OpSelect for this selection.
@ -3807,10 +3815,18 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
builder.getNumComponents(trueValue)));
}
// If the types do not match, it is because of mismatched decorations on aggregates.
// Since isOpSelectable only lets us get here for SPIR-V >= 1.4, we can use OpCopyObject
// to get matching types.
if (builder.getTypeId(trueValue) != resultType) {
trueValue = builder.createUnaryOp(spv::OpCopyLogical, resultType, trueValue);
}
if (builder.getTypeId(falseValue) != resultType) {
falseValue = builder.createUnaryOp(spv::OpCopyLogical, resultType, falseValue);
}
// OpSelect
result = builder.createTriOp(spv::OpSelect,
convertGlslangToSpvType(node->getType()), condition,
trueValue, falseValue);
result = builder.createTriOp(spv::OpSelect, resultType, condition, trueValue, falseValue);
builder.clearAccessChain();
builder.setAccessChainRValue(result);
@ -3818,7 +3834,7 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
// We need control flow to select the result.
// TODO: Once SPIR-V OpSelect allows arbitrary types, eliminate this path.
result = builder.createVariable(TranslatePrecisionDecoration(node->getType()),
spv::StorageClassFunction, convertGlslangToSpvType(node->getType()));
spv::StorageClassFunction, resultType);
// Selection control:
const spv::SelectionControlMask control = TranslateSelectionControl(*node);
@ -3827,10 +3843,15 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
spv::Builder::If ifBuilder(condition, control, builder);
// emit the "then" statement
builder.createStore(trueValue, result);
builder.clearAccessChain();
builder.setAccessChainLValue(result);
multiTypeStore(node->getType(), trueValue);
ifBuilder.makeBeginElse();
// emit the "else" statement
builder.createStore(falseValue, result);
builder.clearAccessChain();
builder.setAccessChainLValue(result);
multiTypeStore(node->getType(), falseValue);
// finish off the control flow
ifBuilder.makeEndIf();
@ -3857,16 +3878,26 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang
// emit the "then" statement
if (node->getTrueBlock() != nullptr) {
node->getTrueBlock()->traverse(this);
if (result != spv::NoResult)
builder.createStore(accessChainLoad(node->getTrueBlock()->getAsTyped()->getType()), result);
if (result != spv::NoResult) {
spv::Id load = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType());
builder.clearAccessChain();
builder.setAccessChainLValue(result);
multiTypeStore(node->getType(), load);
}
}
if (node->getFalseBlock() != nullptr) {
ifBuilder.makeBeginElse();
// emit the "else" statement
node->getFalseBlock()->traverse(this);
if (result != spv::NoResult)
builder.createStore(accessChainLoad(node->getFalseBlock()->getAsTyped()->getType()), result);
if (result != spv::NoResult) {
spv::Id load = accessChainLoad(node->getFalseBlock()->getAsTyped()->getType());
builder.clearAccessChain();
builder.setAccessChainLValue(result);
multiTypeStore(node->getType(), load);
}
}
// finish off the control flow
@ -9418,10 +9449,10 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
std::vector<spv::Id> operandIds;
assert(!decorateId.second.empty());
for (auto extraOperand : decorateId.second) {
if (extraOperand->getQualifier().isSpecConstant())
operandIds.push_back(getSymbolId(extraOperand->getAsSymbolNode()));
else
if (extraOperand->getQualifier().isFrontEndConstant())
operandIds.push_back(createSpvConstant(*extraOperand));
else
operandIds.push_back(getSymbolId(extraOperand->getAsSymbolNode()));
}
builder.addDecorationId(id, static_cast<spv::Decoration>(decorateId.first), operandIds);
}

View File

@ -144,6 +144,7 @@ void Builder::addLine(Id fileName, int lineNum, int column)
void Builder::addDebugScopeAndLine(Id fileName, int lineNum, int column)
{
assert(!currentDebugScopeId.empty());
if (currentDebugScopeId.top() != lastDebugScopeId) {
spv::Id resultId = getUniqueId();
Instruction* scopeInst = new Instruction(resultId, makeVoidType(), OpExtInst);
@ -1071,6 +1072,12 @@ Id Builder::makeDebugCompilationUnit() {
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(sourceInst));
module.mapInstruction(sourceInst);
nonSemanticShaderCompilationUnitId = resultId;
// We can reasonably assume that makeDebugCompilationUnit will be called before any of
// debug-scope stack. Function scopes and lexical scopes will occur afterward.
assert(currentDebugScopeId.empty());
currentDebugScopeId.push(nonSemanticShaderCompilationUnitId);
return resultId;
}
@ -1100,6 +1107,8 @@ Id Builder::createDebugGlobalVariable(Id const type, char const*const name, Id c
Id Builder::createDebugLocalVariable(Id type, char const*const name, size_t const argNumber)
{
assert(name != nullptr);
assert(!currentDebugScopeId.empty());
Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst);
inst->addIdOperand(nonSemanticShaderDebugInfo);
inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugLocalVariable);
@ -2119,6 +2128,8 @@ Id Builder::makeDebugFunction(Function* function, Id nameId, Id funcTypeId) {
}
Id Builder::makeDebugLexicalBlock(uint32_t line) {
assert(!currentDebugScopeId.empty());
Id lexId = getUniqueId();
auto lex = new Instruction(lexId, makeVoidType(), OpExtInst);
lex->addIdOperand(nonSemanticShaderDebugInfo);
@ -2758,52 +2769,49 @@ Id Builder::createBuiltinCall(Id resultType, Id builtins, int entryPoint, const
Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather,
bool noImplicitLod, const TextureParameters& parameters, ImageOperandsMask signExtensionMask)
{
static const int maxTextureArgs = 10;
Id texArgs[maxTextureArgs] = {};
std::vector<Id> texArgs;
//
// Set up the fixed arguments
//
int numArgs = 0;
bool explicitLod = false;
texArgs[numArgs++] = parameters.sampler;
texArgs[numArgs++] = parameters.coords;
texArgs.push_back(parameters.sampler);
texArgs.push_back(parameters.coords);
if (parameters.Dref != NoResult)
texArgs[numArgs++] = parameters.Dref;
texArgs.push_back(parameters.Dref);
if (parameters.component != NoResult)
texArgs[numArgs++] = parameters.component;
texArgs.push_back(parameters.component);
#ifndef GLSLANG_WEB
if (parameters.granularity != NoResult)
texArgs[numArgs++] = parameters.granularity;
texArgs.push_back(parameters.granularity);
if (parameters.coarse != NoResult)
texArgs[numArgs++] = parameters.coarse;
texArgs.push_back(parameters.coarse);
#endif
//
// Set up the optional arguments
//
int optArgNum = numArgs; // track which operand, if it exists, is the mask of optional arguments
++numArgs; // speculatively make room for the mask operand
size_t optArgNum = texArgs.size(); // the position of the mask for the optional arguments, if any.
ImageOperandsMask mask = ImageOperandsMaskNone; // the mask operand
if (parameters.bias) {
mask = (ImageOperandsMask)(mask | ImageOperandsBiasMask);
texArgs[numArgs++] = parameters.bias;
texArgs.push_back(parameters.bias);
}
if (parameters.lod) {
mask = (ImageOperandsMask)(mask | ImageOperandsLodMask);
texArgs[numArgs++] = parameters.lod;
texArgs.push_back(parameters.lod);
explicitLod = true;
} else if (parameters.gradX) {
mask = (ImageOperandsMask)(mask | ImageOperandsGradMask);
texArgs[numArgs++] = parameters.gradX;
texArgs[numArgs++] = parameters.gradY;
texArgs.push_back(parameters.gradX);
texArgs.push_back(parameters.gradY);
explicitLod = true;
} else if (noImplicitLod && ! fetch && ! gather) {
// have to explicitly use lod of 0 if not allowed to have them be implicit, and
// we would otherwise be about to issue an implicit instruction
mask = (ImageOperandsMask)(mask | ImageOperandsLodMask);
texArgs[numArgs++] = makeFloatConstant(0.0);
texArgs.push_back(makeFloatConstant(0.0));
explicitLod = true;
}
if (parameters.offset) {
@ -2813,24 +2821,24 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse,
addCapability(CapabilityImageGatherExtended);
mask = (ImageOperandsMask)(mask | ImageOperandsOffsetMask);
}
texArgs[numArgs++] = parameters.offset;
texArgs.push_back(parameters.offset);
}
if (parameters.offsets) {
addCapability(CapabilityImageGatherExtended);
mask = (ImageOperandsMask)(mask | ImageOperandsConstOffsetsMask);
texArgs[numArgs++] = parameters.offsets;
texArgs.push_back(parameters.offsets);
}
#ifndef GLSLANG_WEB
if (parameters.sample) {
mask = (ImageOperandsMask)(mask | ImageOperandsSampleMask);
texArgs[numArgs++] = parameters.sample;
texArgs.push_back(parameters.sample);
}
if (parameters.lodClamp) {
// capability if this bit is used
addCapability(CapabilityMinLod);
mask = (ImageOperandsMask)(mask | ImageOperandsMinLodMask);
texArgs[numArgs++] = parameters.lodClamp;
texArgs.push_back(parameters.lodClamp);
}
if (parameters.nonprivate) {
mask = mask | ImageOperandsNonPrivateTexelKHRMask;
@ -2840,10 +2848,9 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse,
}
#endif
mask = mask | signExtensionMask;
if (mask == ImageOperandsMaskNone)
--numArgs; // undo speculative reservation for the mask argument
else
texArgs[optArgNum] = mask;
// insert the operand for the mask, if any bits were set.
if (mask != ImageOperandsMaskNone)
texArgs.insert(texArgs.begin() + optArgNum, mask);
//
// Set up the instruction
@ -2947,11 +2954,11 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse,
// Build the SPIR-V instruction
Instruction* textureInst = new Instruction(getUniqueId(), resultType, opCode);
for (int op = 0; op < optArgNum; ++op)
for (size_t op = 0; op < optArgNum; ++op)
textureInst->addIdOperand(texArgs[op]);
if (optArgNum < numArgs)
if (optArgNum < texArgs.size())
textureInst->addImmediateOperand(texArgs[optArgNum]);
for (int op = optArgNum + 1; op < numArgs; ++op)
for (size_t op = optArgNum + 1; op < texArgs.size(); ++op)
textureInst->addIdOperand(texArgs[op]);
setPrecision(textureInst->getResultId(), precision);
buildPoint->addInstruction(std::unique_ptr<Instruction>(textureInst));

View File

@ -258,6 +258,17 @@ public:
text.append("\n");
}
void addText(std::string preambleText)
{
fixLine(preambleText);
Processes.push_back("preamble-text");
Processes.back().append(preambleText);
text.append(preambleText);
text.append("\n");
}
protected:
void fixLine(std::string& line)
{
@ -727,6 +738,13 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
} else if (lowerword == "no-storage-format" || // synonyms
lowerword == "nsf") {
Options |= EOptionNoStorageFormat;
} else if (lowerword == "preamble-text" ||
lowerword == "p") {
if (argc > 1)
UserPreamble.addText(argv[1]);
else
Error("expects <text>", argv[0]);
bumpArg();
} else if (lowerword == "relaxed-errors") {
Options |= EOptionRelaxedErrors;
} else if (lowerword == "reflect-strict-array-suffix") {
@ -926,6 +944,9 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
else
Error("unknown -O option");
break;
case 'P':
UserPreamble.addText(getStringOperand("-P<text>"));
break;
case 'R':
VulkanRulesRelaxed = true;
break;
@ -1832,7 +1853,7 @@ void CompileFile(const char* fileName, ShHandle compiler)
SetMessageOptions(messages);
if (UserPreamble.isSet())
Error("-D and -U options require -l (linking)\n");
Error("-D, -U and -P options require -l (linking)\n");
for (int i = 0; i < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++i) {
for (int j = 0; j < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++j) {
@ -1902,6 +1923,9 @@ void usage()
" is searched first, followed by left-to-right order of -I\n"
" -Od disables optimization; may cause illegal SPIR-V for HLSL\n"
" -Os optimizes SPIR-V to minimize size\n"
" -P<text> | --preamble-text <text> | --P <text>\n"
" inject custom preamble text, which is treated as if it\n"
" appeared immediately after the version declaration (if any).\n"
" -R use relaxed verification rules for generating Vulkan SPIR-V,\n"
" allowing the use of default uniforms, atomic_uints, and\n"
" gl_VertexID and gl_InstanceID keywords.\n"

View File

@ -1177,10 +1177,13 @@ void HlslParseContext::flatten(const TVariable& variable, bool linkage, bool arr
if (type.isBuiltIn() && !type.isStruct())
return;
auto entry = flattenMap.insert(std::make_pair(variable.getUniqueId(),
TFlattenData(type.getQualifier().layoutBinding,
type.getQualifier().layoutLocation)));
if (type.isStruct() && type.getStruct()->size()==0)
return;
// if flattening arrayed io struct, array each member of dereferenced type
if (arrayed) {
const TType dereferencedType(type, 0);
@ -7565,7 +7568,6 @@ const TFunction* HlslParseContext::findFunction(const TSourceLoc& loc, TFunction
candidateList[0]->getBuiltInOp() == EOpMethodRestartStrip ||
candidateList[0]->getBuiltInOp() == EOpMethodIncrementCounter ||
candidateList[0]->getBuiltInOp() == EOpMethodDecrementCounter ||
candidateList[0]->getBuiltInOp() == EOpMethodAppend ||
candidateList[0]->getBuiltInOp() == EOpMethodConsume)) {
return candidateList[0];
}
@ -9046,7 +9048,8 @@ void HlslParseContext::fixBlockUniformOffsets(const TQualifier& qualifier, TType
// "The specified offset must be a multiple
// of the base alignment of the type of the block member it qualifies, or a compile-time error results."
if (! IsMultipleOfPow2(memberQualifier.layoutOffset, memberAlignment))
error(memberLoc, "must be a multiple of the member's alignment", "offset", "");
error(memberLoc, "must be a multiple of the member's alignment", "offset",
"(layout offset = %d | member alignment = %d)", memberQualifier.layoutOffset, memberAlignment);
// "The offset qualifier forces the qualified member to start at or after the specified
// integral-constant expression, which will be its byte offset from the beginning of the buffer.

View File

@ -4013,7 +4013,7 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali
switch (language) {
case EShLangVertex:
if (publicType.basicType == EbtStruct) {
error(loc, "cannot be a structure or array", GetStorageQualifierString(qualifier.storage), "");
error(loc, "cannot be a structure", GetStorageQualifierString(qualifier.storage), "");
return;
}
if (publicType.arraySizes) {
@ -4228,7 +4228,7 @@ void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, cons
if (dstSpirvDecorate.decorates.find(decorateString.first) != dstSpirvDecorate.decorates.end())
error(loc, "too many SPIR-V decorate qualifiers", "spirv_decorate_string", "(decoration=%u)", decorateString.first);
else
dstSpirvDecorate.decorates.insert(decorateString);
dstSpirvDecorate.decorateStrings.insert(decorateString);
}
} else {
dst.spirvDecorate = src.spirvDecorate;
@ -9029,7 +9029,8 @@ void TParseContext::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typ
// "The specified offset must be a multiple
// of the base alignment of the type of the block member it qualifies, or a compile-time error results."
if (! IsMultipleOfPow2(memberQualifier.layoutOffset, memberAlignment))
error(memberLoc, "must be a multiple of the member's alignment", "offset", "");
error(memberLoc, "must be a multiple of the member's alignment", "offset",
"(layout offset = %d | member alignment = %d)", memberQualifier.layoutOffset, memberAlignment);
// GLSL: "It is a compile-time error to specify an offset that is smaller than the offset of the previous
// member in the block or that lies within the previous member of the block"

View File

@ -168,7 +168,7 @@ void TQualifier::setSpirvDecorateId(int decoration, const TIntermAggregate* args
TVector<const TIntermTyped*> extraOperands;
for (auto arg : args->getSequence()) {
auto extraOperand = arg->getAsTyped();
assert(extraOperand != nullptr && extraOperand->getQualifier().isConstant());
assert(extraOperand != nullptr);
extraOperands.push_back(extraOperand);
}
spirvDecorate->decorateIds[decoration] = extraOperands;
@ -202,30 +202,29 @@ TString TQualifier::getSpirvDecorateQualifierString() const
const auto appendStr = [&](const char* s) { qualifierString.append(s); };
const auto appendDecorate = [&](const TIntermTyped* constant) {
auto& constArray = constant->getAsConstantUnion() != nullptr ? constant->getAsConstantUnion()->getConstArray()
: constant->getAsSymbolNode()->getConstArray();
if (constant->getBasicType() == EbtFloat) {
float value = static_cast<float>(constArray[0].getDConst());
appendFloat(value);
if (constant->getAsConstantUnion()) {
auto& constArray = constant->getAsConstantUnion()->getConstArray();
if (constant->getBasicType() == EbtFloat) {
float value = static_cast<float>(constArray[0].getDConst());
appendFloat(value);
} else if (constant->getBasicType() == EbtInt) {
int value = constArray[0].getIConst();
appendInt(value);
} else if (constant->getBasicType() == EbtUint) {
unsigned value = constArray[0].getUConst();
appendUint(value);
} else if (constant->getBasicType() == EbtBool) {
bool value = constArray[0].getBConst();
appendBool(value);
} else if (constant->getBasicType() == EbtString) {
const TString* value = constArray[0].getSConst();
appendStr(value->c_str());
} else
assert(0);
} else {
assert(constant->getAsSymbolNode());
appendStr(constant->getAsSymbolNode()->getName().c_str());
}
else if (constant->getBasicType() == EbtInt) {
int value = constArray[0].getIConst();
appendInt(value);
}
else if (constant->getBasicType() == EbtUint) {
unsigned value = constArray[0].getUConst();
appendUint(value);
}
else if (constant->getBasicType() == EbtBool) {
bool value = constArray[0].getBConst();
appendBool(value);
}
else if (constant->getBasicType() == EbtString) {
const TString* value = constArray[0].getSConst();
appendStr(value->c_str());
}
else
assert(0);
};
for (auto& decorate : spirvDecorate->decorates) {

View File

@ -378,7 +378,7 @@ GLSLANG_WEB_EXCLUDE_ON
%type <interm.type> spirv_storage_class_qualifier
%type <interm.type> spirv_decorate_qualifier
%type <interm.intermNode> spirv_decorate_parameter_list spirv_decorate_parameter
%type <interm.intermNode> spirv_decorate_id_parameter_list
%type <interm.intermNode> spirv_decorate_id_parameter_list spirv_decorate_id_parameter
%type <interm.intermNode> spirv_decorate_string_parameter_list
%type <interm.type> spirv_type_specifier
%type <interm.spirvTypeParams> spirv_type_parameter_list spirv_type_parameter
@ -4347,23 +4347,33 @@ spirv_decorate_parameter
}
spirv_decorate_id_parameter_list
: constant_expression {
if ($1->getBasicType() != EbtFloat &&
$1->getBasicType() != EbtInt &&
$1->getBasicType() != EbtUint &&
$1->getBasicType() != EbtBool)
parseContext.error($1->getLoc(), "this type not allowed", $1->getType().getBasicString(), "");
: spirv_decorate_id_parameter {
$$ = parseContext.intermediate.makeAggregate($1);
}
| spirv_decorate_id_parameter_list COMMA constant_expression {
if ($3->getBasicType() != EbtFloat &&
$3->getBasicType() != EbtInt &&
$3->getBasicType() != EbtUint &&
$3->getBasicType() != EbtBool)
parseContext.error($3->getLoc(), "this type not allowed", $3->getType().getBasicString(), "");
| spirv_decorate_id_parameter_list COMMA spirv_decorate_id_parameter {
$$ = parseContext.intermediate.growAggregate($1, $3);
}
spirv_decorate_id_parameter
: variable_identifier {
if ($1->getAsConstantUnion() || $1->getAsSymbolNode())
$$ = $1;
else
parseContext.error($1->getLoc(), "only allow constants or variables which are not elements of a composite", "", "");
}
| FLOATCONSTANT {
$$ = parseContext.intermediate.addConstantUnion($1.d, EbtFloat, $1.loc, true);
}
| INTCONSTANT {
$$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true);
}
| UINTCONSTANT {
$$ = parseContext.intermediate.addConstantUnion($1.u, $1.loc, true);
}
| BOOLCONSTANT {
$$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true);
}
spirv_decorate_string_parameter_list
: STRING_LITERAL {
$$ = parseContext.intermediate.makeAggregate(

View File

@ -378,7 +378,7 @@ extern int yylex(YYSTYPE*, TParseContext&);
%type <interm.type> spirv_storage_class_qualifier
%type <interm.type> spirv_decorate_qualifier
%type <interm.intermNode> spirv_decorate_parameter_list spirv_decorate_parameter
%type <interm.intermNode> spirv_decorate_id_parameter_list
%type <interm.intermNode> spirv_decorate_id_parameter_list spirv_decorate_id_parameter
%type <interm.intermNode> spirv_decorate_string_parameter_list
%type <interm.type> spirv_type_specifier
%type <interm.spirvTypeParams> spirv_type_parameter_list spirv_type_parameter
@ -4347,23 +4347,33 @@ spirv_decorate_parameter
}
spirv_decorate_id_parameter_list
: constant_expression {
if ($1->getBasicType() != EbtFloat &&
$1->getBasicType() != EbtInt &&
$1->getBasicType() != EbtUint &&
$1->getBasicType() != EbtBool)
parseContext.error($1->getLoc(), "this type not allowed", $1->getType().getBasicString(), "");
: spirv_decorate_id_parameter {
$$ = parseContext.intermediate.makeAggregate($1);
}
| spirv_decorate_id_parameter_list COMMA constant_expression {
if ($3->getBasicType() != EbtFloat &&
$3->getBasicType() != EbtInt &&
$3->getBasicType() != EbtUint &&
$3->getBasicType() != EbtBool)
parseContext.error($3->getLoc(), "this type not allowed", $3->getType().getBasicString(), "");
| spirv_decorate_id_parameter_list COMMA spirv_decorate_id_parameter {
$$ = parseContext.intermediate.growAggregate($1, $3);
}
spirv_decorate_id_parameter
: variable_identifier {
if ($1->getAsConstantUnion() || $1->getAsSymbolNode())
$$ = $1;
else
parseContext.error($1->getLoc(), "only allow constants or variables which are not elements of a composite", "", "");
}
| FLOATCONSTANT {
$$ = parseContext.intermediate.addConstantUnion($1.d, EbtFloat, $1.loc, true);
}
| INTCONSTANT {
$$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true);
}
| UINTCONSTANT {
$$ = parseContext.intermediate.addConstantUnion($1.u, $1.loc, true);
}
| BOOLCONSTANT {
$$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true);
}
spirv_decorate_string_parameter_list
: STRING_LITERAL {
$$ = parseContext.intermediate.makeAggregate(

File diff suppressed because it is too large Load Diff