// // Copyright (C) 2016 Google, Inc. // Copyright (C) 2016 LunarG, Inc. // // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials provided // with the distribution. // // Neither the name of Google, Inc., nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // // // HLSL scanning, leveraging the scanning done by the preprocessor. // #include #include #include #include "../glslang/Include/Types.h" #include "../glslang/MachineIndependent/SymbolTable.h" #include "../glslang/MachineIndependent/ParseHelper.h" #include "hlslScanContext.h" #include "hlslTokens.h" // preprocessor includes #include "../glslang/MachineIndependent/preprocessor/PpContext.h" #include "../glslang/MachineIndependent/preprocessor/PpTokens.h" namespace { struct str_eq { bool operator()(const char* lhs, const char* rhs) const { return strcmp(lhs, rhs) == 0; } }; struct str_hash { size_t operator()(const char* str) const { // djb2 unsigned long hash = 5381; int c; while ((c = *str++) != 0) hash = ((hash << 5) + hash) + c; return hash; } }; // A single global usable by all threads, by all versions, by all languages. // After a single process-level initialization, this is read only and thread safe std::unordered_map* KeywordMap = nullptr; std::unordered_set* ReservedSet = nullptr; std::unordered_map* SemanticMap = nullptr; }; namespace glslang { void HlslScanContext::fillInKeywordMap() { if (KeywordMap != nullptr) { // this is really an error, as this should called only once per process // but, the only risk is if two threads called simultaneously return; } KeywordMap = new std::unordered_map; (*KeywordMap)["static"] = EHTokStatic; (*KeywordMap)["const"] = EHTokConst; (*KeywordMap)["unorm"] = EHTokUnorm; (*KeywordMap)["snorm"] = EHTokSNorm; (*KeywordMap)["extern"] = EHTokExtern; (*KeywordMap)["uniform"] = EHTokUniform; (*KeywordMap)["volatile"] = EHTokVolatile; (*KeywordMap)["precise"] = EHTokPrecise; (*KeywordMap)["shared"] = EHTokShared; (*KeywordMap)["groupshared"] = EHTokGroupShared; (*KeywordMap)["linear"] = EHTokLinear; (*KeywordMap)["centroid"] = EHTokCentroid; (*KeywordMap)["nointerpolation"] = EHTokNointerpolation; (*KeywordMap)["noperspective"] = EHTokNoperspective; (*KeywordMap)["sample"] = EHTokSample; (*KeywordMap)["row_major"] = EHTokRowMajor; (*KeywordMap)["column_major"] = EHTokColumnMajor; (*KeywordMap)["packoffset"] = EHTokPackOffset; (*KeywordMap)["in"] = EHTokIn; (*KeywordMap)["out"] = EHTokOut; (*KeywordMap)["inout"] = EHTokInOut; (*KeywordMap)["layout"] = EHTokLayout; (*KeywordMap)["globallycoherent"] = EHTokGloballyCoherent; (*KeywordMap)["inline"] = EHTokInline; (*KeywordMap)["point"] = EHTokPoint; (*KeywordMap)["line"] = EHTokLine; (*KeywordMap)["triangle"] = EHTokTriangle; (*KeywordMap)["lineadj"] = EHTokLineAdj; (*KeywordMap)["triangleadj"] = EHTokTriangleAdj; (*KeywordMap)["PointStream"] = EHTokPointStream; (*KeywordMap)["LineStream"] = EHTokLineStream; (*KeywordMap)["TriangleStream"] = EHTokTriangleStream; (*KeywordMap)["InputPatch"] = EHTokInputPatch; (*KeywordMap)["OutputPatch"] = EHTokOutputPatch; (*KeywordMap)["Buffer"] = EHTokBuffer; (*KeywordMap)["vector"] = EHTokVector; (*KeywordMap)["matrix"] = EHTokMatrix; (*KeywordMap)["void"] = EHTokVoid; (*KeywordMap)["string"] = EHTokString; (*KeywordMap)["bool"] = EHTokBool; (*KeywordMap)["int"] = EHTokInt; (*KeywordMap)["uint"] = EHTokUint; (*KeywordMap)["uint64_t"] = EHTokUint64; (*KeywordMap)["dword"] = EHTokDword; (*KeywordMap)["half"] = EHTokHalf; (*KeywordMap)["float"] = EHTokFloat; (*KeywordMap)["double"] = EHTokDouble; (*KeywordMap)["min16float"] = EHTokMin16float; (*KeywordMap)["min10float"] = EHTokMin10float; (*KeywordMap)["min16int"] = EHTokMin16int; (*KeywordMap)["min12int"] = EHTokMin12int; (*KeywordMap)["min16uint"] = EHTokMin16uint; (*KeywordMap)["bool1"] = EHTokBool1; (*KeywordMap)["bool2"] = EHTokBool2; (*KeywordMap)["bool3"] = EHTokBool3; (*KeywordMap)["bool4"] = EHTokBool4; (*KeywordMap)["float1"] = EHTokFloat1; (*KeywordMap)["float2"] = EHTokFloat2; (*KeywordMap)["float3"] = EHTokFloat3; (*KeywordMap)["float4"] = EHTokFloat4; (*KeywordMap)["int1"] = EHTokInt1; (*KeywordMap)["int2"] = EHTokInt2; (*KeywordMap)["int3"] = EHTokInt3; (*KeywordMap)["int4"] = EHTokInt4; (*KeywordMap)["double1"] = EHTokDouble1; (*KeywordMap)["double2"] = EHTokDouble2; (*KeywordMap)["double3"] = EHTokDouble3; (*KeywordMap)["double4"] = EHTokDouble4; (*KeywordMap)["uint1"] = EHTokUint1; (*KeywordMap)["uint2"] = EHTokUint2; (*KeywordMap)["uint3"] = EHTokUint3; (*KeywordMap)["uint4"] = EHTokUint4; (*KeywordMap)["half1"] = EHTokHalf1; (*KeywordMap)["half2"] = EHTokHalf2; (*KeywordMap)["half3"] = EHTokHalf3; (*KeywordMap)["half4"] = EHTokHalf4; (*KeywordMap)["min16float1"] = EHTokMin16float1; (*KeywordMap)["min16float2"] = EHTokMin16float2; (*KeywordMap)["min16float3"] = EHTokMin16float3; (*KeywordMap)["min16float4"] = EHTokMin16float4; (*KeywordMap)["min10float1"] = EHTokMin10float1; (*KeywordMap)["min10float2"] = EHTokMin10float2; (*KeywordMap)["min10float3"] = EHTokMin10float3; (*KeywordMap)["min10float4"] = EHTokMin10float4; (*KeywordMap)["min16int1"] = EHTokMin16int1; (*KeywordMap)["min16int2"] = EHTokMin16int2; (*KeywordMap)["min16int3"] = EHTokMin16int3; (*KeywordMap)["min16int4"] = EHTokMin16int4; (*KeywordMap)["min12int1"] = EHTokMin12int1; (*KeywordMap)["min12int2"] = EHTokMin12int2; (*KeywordMap)["min12int3"] = EHTokMin12int3; (*KeywordMap)["min12int4"] = EHTokMin12int4; (*KeywordMap)["min16uint1"] = EHTokMin16uint1; (*KeywordMap)["min16uint2"] = EHTokMin16uint2; (*KeywordMap)["min16uint3"] = EHTokMin16uint3; (*KeywordMap)["min16uint4"] = EHTokMin16uint4; (*KeywordMap)["bool1x1"] = EHTokBool1x1; (*KeywordMap)["bool1x2"] = EHTokBool1x2; (*KeywordMap)["bool1x3"] = EHTokBool1x3; (*KeywordMap)["bool1x4"] = EHTokBool1x4; (*KeywordMap)["bool2x1"] = EHTokBool2x1; (*KeywordMap)["bool2x2"] = EHTokBool2x2; (*KeywordMap)["bool2x3"] = EHTokBool2x3; (*KeywordMap)["bool2x4"] = EHTokBool2x4; (*KeywordMap)["bool3x1"] = EHTokBool3x1; (*KeywordMap)["bool3x2"] = EHTokBool3x2; (*KeywordMap)["bool3x3"] = EHTokBool3x3; (*KeywordMap)["bool3x4"] = EHTokBool3x4; (*KeywordMap)["bool4x1"] = EHTokBool4x1; (*KeywordMap)["bool4x2"] = EHTokBool4x2; (*KeywordMap)["bool4x3"] = EHTokBool4x3; (*KeywordMap)["bool4x4"] = EHTokBool4x4; (*KeywordMap)["int1x1"] = EHTokInt1x1; (*KeywordMap)["int1x2"] = EHTokInt1x2; (*KeywordMap)["int1x3"] = EHTokInt1x3; (*KeywordMap)["int1x4"] = EHTokInt1x4; (*KeywordMap)["int2x1"] = EHTokInt2x1; (*KeywordMap)["int2x2"] = EHTokInt2x2; (*KeywordMap)["int2x3"] = EHTokInt2x3; (*KeywordMap)["int2x4"] = EHTokInt2x4; (*KeywordMap)["int3x1"] = EHTokInt3x1; (*KeywordMap)["int3x2"] = EHTokInt3x2; (*KeywordMap)["int3x3"] = EHTokInt3x3; (*KeywordMap)["int3x4"] = EHTokInt3x4; (*KeywordMap)["int4x1"] = EHTokInt4x1; (*KeywordMap)["int4x2"] = EHTokInt4x2; (*KeywordMap)["int4x3"] = EHTokInt4x3; (*KeywordMap)["int4x4"] = EHTokInt4x4; (*KeywordMap)["uint1x1"] = EHTokUint1x1; (*KeywordMap)["uint1x2"] = EHTokUint1x2; (*KeywordMap)["uint1x3"] = EHTokUint1x3; (*KeywordMap)["uint1x4"] = EHTokUint1x4; (*KeywordMap)["uint2x1"] = EHTokUint2x1; (*KeywordMap)["uint2x2"] = EHTokUint2x2; (*KeywordMap)["uint2x3"] = EHTokUint2x3; (*KeywordMap)["uint2x4"] = EHTokUint2x4; (*KeywordMap)["uint3x1"] = EHTokUint3x1; (*KeywordMap)["uint3x2"] = EHTokUint3x2; (*KeywordMap)["uint3x3"] = EHTokUint3x3; (*KeywordMap)["uint3x4"] = EHTokUint3x4; (*KeywordMap)["uint4x1"] = EHTokUint4x1; (*KeywordMap)["uint4x2"] = EHTokUint4x2; (*KeywordMap)["uint4x3"] = EHTokUint4x3; (*KeywordMap)["uint4x4"] = EHTokUint4x4; (*KeywordMap)["bool1x1"] = EHTokBool1x1; (*KeywordMap)["bool1x2"] = EHTokBool1x2; (*KeywordMap)["bool1x3"] = EHTokBool1x3; (*KeywordMap)["bool1x4"] = EHTokBool1x4; (*KeywordMap)["bool2x1"] = EHTokBool2x1; (*KeywordMap)["bool2x2"] = EHTokBool2x2; (*KeywordMap)["bool2x3"] = EHTokBool2x3; (*KeywordMap)["bool2x4"] = EHTokBool2x4; (*KeywordMap)["bool3x1"] = EHTokBool3x1; (*KeywordMap)["bool3x2"] = EHTokBool3x2; (*KeywordMap)["bool3x3"] = EHTokBool3x3; (*KeywordMap)["bool3x4"] = EHTokBool3x4; (*KeywordMap)["bool4x1"] = EHTokBool4x1; (*KeywordMap)["bool4x2"] = EHTokBool4x2; (*KeywordMap)["bool4x3"] = EHTokBool4x3; (*KeywordMap)["bool4x4"] = EHTokBool4x4; (*KeywordMap)["float1x1"] = EHTokFloat1x1; (*KeywordMap)["float1x2"] = EHTokFloat1x2; (*KeywordMap)["float1x3"] = EHTokFloat1x3; (*KeywordMap)["float1x4"] = EHTokFloat1x4; (*KeywordMap)["float2x1"] = EHTokFloat2x1; (*KeywordMap)["float2x2"] = EHTokFloat2x2; (*KeywordMap)["float2x3"] = EHTokFloat2x3; (*KeywordMap)["float2x4"] = EHTokFloat2x4; (*KeywordMap)["float3x1"] = EHTokFloat3x1; (*KeywordMap)["float3x2"] = EHTokFloat3x2; (*KeywordMap)["float3x3"] = EHTokFloat3x3; (*KeywordMap)["float3x4"] = EHTokFloat3x4; (*KeywordMap)["float4x1"] = EHTokFloat4x1; (*KeywordMap)["float4x2"] = EHTokFloat4x2; (*KeywordMap)["float4x3"] = EHTokFloat4x3; (*KeywordMap)["float4x4"] = EHTokFloat4x4; (*KeywordMap)["half1x1"] = EHTokHalf1x1; (*KeywordMap)["half1x2"] = EHTokHalf1x2; (*KeywordMap)["half1x3"] = EHTokHalf1x3; (*KeywordMap)["half1x4"] = EHTokHalf1x4; (*KeywordMap)["half2x1"] = EHTokHalf2x1; (*KeywordMap)["half2x2"] = EHTokHalf2x2; (*KeywordMap)["half2x3"] = EHTokHalf2x3; (*KeywordMap)["half2x4"] = EHTokHalf2x4; (*KeywordMap)["half3x1"] = EHTokHalf3x1; (*KeywordMap)["half3x2"] = EHTokHalf3x2; (*KeywordMap)["half3x3"] = EHTokHalf3x3; (*KeywordMap)["half3x4"] = EHTokHalf3x4; (*KeywordMap)["half4x1"] = EHTokHalf4x1; (*KeywordMap)["half4x2"] = EHTokHalf4x2; (*KeywordMap)["half4x3"] = EHTokHalf4x3; (*KeywordMap)["half4x4"] = EHTokHalf4x4; (*KeywordMap)["double1x1"] = EHTokDouble1x1; (*KeywordMap)["double1x2"] = EHTokDouble1x2; (*KeywordMap)["double1x3"] = EHTokDouble1x3; (*KeywordMap)["double1x4"] = EHTokDouble1x4; (*KeywordMap)["double2x1"] = EHTokDouble2x1; (*KeywordMap)["double2x2"] = EHTokDouble2x2; (*KeywordMap)["double2x3"] = EHTokDouble2x3; (*KeywordMap)["double2x4"] = EHTokDouble2x4; (*KeywordMap)["double3x1"] = EHTokDouble3x1; (*KeywordMap)["double3x2"] = EHTokDouble3x2; (*KeywordMap)["double3x3"] = EHTokDouble3x3; (*KeywordMap)["double3x4"] = EHTokDouble3x4; (*KeywordMap)["double4x1"] = EHTokDouble4x1; (*KeywordMap)["double4x2"] = EHTokDouble4x2; (*KeywordMap)["double4x3"] = EHTokDouble4x3; (*KeywordMap)["double4x4"] = EHTokDouble4x4; (*KeywordMap)["sampler"] = EHTokSampler; (*KeywordMap)["sampler1D"] = EHTokSampler1d; (*KeywordMap)["sampler2D"] = EHTokSampler2d; (*KeywordMap)["sampler3D"] = EHTokSampler3d; (*KeywordMap)["samplerCube"] = EHTokSamplerCube; (*KeywordMap)["sampler_state"] = EHTokSamplerState; (*KeywordMap)["SamplerState"] = EHTokSamplerState; (*KeywordMap)["SamplerComparisonState"] = EHTokSamplerComparisonState; (*KeywordMap)["texture"] = EHTokTexture; (*KeywordMap)["Texture1D"] = EHTokTexture1d; (*KeywordMap)["Texture1DArray"] = EHTokTexture1darray; (*KeywordMap)["Texture2D"] = EHTokTexture2d; (*KeywordMap)["Texture2DArray"] = EHTokTexture2darray; (*KeywordMap)["Texture3D"] = EHTokTexture3d; (*KeywordMap)["TextureCube"] = EHTokTextureCube; (*KeywordMap)["TextureCubeArray"] = EHTokTextureCubearray; (*KeywordMap)["Texture2DMS"] = EHTokTexture2DMS; (*KeywordMap)["Texture2DMSArray"] = EHTokTexture2DMSarray; (*KeywordMap)["RWTexture1D"] = EHTokRWTexture1d; (*KeywordMap)["RWTexture1DArray"] = EHTokRWTexture1darray; (*KeywordMap)["RWTexture2D"] = EHTokRWTexture2d; (*KeywordMap)["RWTexture2DArray"] = EHTokRWTexture2darray; (*KeywordMap)["RWTexture3D"] = EHTokRWTexture3d; (*KeywordMap)["RWBuffer"] = EHTokRWBuffer; (*KeywordMap)["SubpassInput"] = EHTokSubpassInput; (*KeywordMap)["SubpassInputMS"] = EHTokSubpassInputMS; (*KeywordMap)["AppendStructuredBuffer"] = EHTokAppendStructuredBuffer; (*KeywordMap)["ByteAddressBuffer"] = EHTokByteAddressBuffer; (*KeywordMap)["ConsumeStructuredBuffer"] = EHTokConsumeStructuredBuffer; (*KeywordMap)["RWByteAddressBuffer"] = EHTokRWByteAddressBuffer; (*KeywordMap)["RWStructuredBuffer"] = EHTokRWStructuredBuffer; (*KeywordMap)["StructuredBuffer"] = EHTokStructuredBuffer; (*KeywordMap)["TextureBuffer"] = EHTokTextureBuffer; (*KeywordMap)["class"] = EHTokClass; (*KeywordMap)["struct"] = EHTokStruct; (*KeywordMap)["cbuffer"] = EHTokCBuffer; (*KeywordMap)["ConstantBuffer"] = EHTokConstantBuffer; (*KeywordMap)["tbuffer"] = EHTokTBuffer; (*KeywordMap)["typedef"] = EHTokTypedef; (*KeywordMap)["this"] = EHTokThis; (*KeywordMap)["namespace"] = EHTokNamespace; (*KeywordMap)["true"] = EHTokBoolConstant; (*KeywordMap)["false"] = EHTokBoolConstant; (*KeywordMap)["for"] = EHTokFor; (*KeywordMap)["do"] = EHTokDo; (*KeywordMap)["while"] = EHTokWhile; (*KeywordMap)["break"] = EHTokBreak; (*KeywordMap)["continue"] = EHTokContinue; (*KeywordMap)["if"] = EHTokIf; (*KeywordMap)["else"] = EHTokElse; (*KeywordMap)["discard"] = EHTokDiscard; (*KeywordMap)["return"] = EHTokReturn; (*KeywordMap)["switch"] = EHTokSwitch; (*KeywordMap)["case"] = EHTokCase; (*KeywordMap)["default"] = EHTokDefault; // TODO: get correct set here ReservedSet = new std::unordered_set; ReservedSet->insert("auto"); ReservedSet->insert("catch"); ReservedSet->insert("char"); ReservedSet->insert("const_cast"); ReservedSet->insert("enum"); ReservedSet->insert("explicit"); ReservedSet->insert("friend"); ReservedSet->insert("goto"); ReservedSet->insert("long"); ReservedSet->insert("mutable"); ReservedSet->insert("new"); ReservedSet->insert("operator"); ReservedSet->insert("private"); ReservedSet->insert("protected"); ReservedSet->insert("public"); ReservedSet->insert("reinterpret_cast"); ReservedSet->insert("short"); ReservedSet->insert("signed"); ReservedSet->insert("sizeof"); ReservedSet->insert("static_cast"); ReservedSet->insert("template"); ReservedSet->insert("throw"); ReservedSet->insert("try"); ReservedSet->insert("typename"); ReservedSet->insert("union"); ReservedSet->insert("unsigned"); ReservedSet->insert("using"); ReservedSet->insert("virtual"); SemanticMap = new std::unordered_map; // in DX9, all outputs had to have a semantic associated with them, that was either consumed // by the system or was a specific register assignment // in DX10+, only semantics with the SV_ prefix have any meaning beyond decoration // Fxc will only accept DX9 style semantics in compat mode // Also, in DX10 if a SV value is present as the input of a stage, but isn't appropriate for that // stage, it would just be ignored as it is likely there as part of an output struct from one stage // to the next bool bParseDX9 = false; if (bParseDX9) { (*SemanticMap)["PSIZE"] = EbvPointSize; (*SemanticMap)["FOG"] = EbvFogFragCoord; (*SemanticMap)["DEPTH"] = EbvFragDepth; (*SemanticMap)["VFACE"] = EbvFace; (*SemanticMap)["VPOS"] = EbvFragCoord; } (*SemanticMap)["SV_POSITION"] = EbvPosition; (*SemanticMap)["SV_VERTEXID"] = EbvVertexIndex; (*SemanticMap)["SV_VIEWPORTARRAYINDEX"] = EbvViewportIndex; (*SemanticMap)["SV_TESSFACTOR"] = EbvTessLevelOuter; (*SemanticMap)["SV_SAMPLEINDEX"] = EbvSampleId; (*SemanticMap)["SV_RENDERTARGETARRAYINDEX"] = EbvLayer; (*SemanticMap)["SV_PRIMITIVEID"] = EbvPrimitiveId; (*SemanticMap)["SV_OUTPUTCONTROLPOINTID"] = EbvInvocationId; (*SemanticMap)["SV_ISFRONTFACE"] = EbvFace; (*SemanticMap)["SV_INSTANCEID"] = EbvInstanceIndex; (*SemanticMap)["SV_INSIDETESSFACTOR"] = EbvTessLevelInner; (*SemanticMap)["SV_GSINSTANCEID"] = EbvInvocationId; (*SemanticMap)["SV_DISPATCHTHREADID"] = EbvGlobalInvocationId; (*SemanticMap)["SV_GROUPTHREADID"] = EbvLocalInvocationId; (*SemanticMap)["SV_GROUPINDEX"] = EbvLocalInvocationIndex; (*SemanticMap)["SV_GROUPID"] = EbvWorkGroupId; (*SemanticMap)["SV_DOMAINLOCATION"] = EbvTessCoord; (*SemanticMap)["SV_DEPTH"] = EbvFragDepth; (*SemanticMap)["SV_COVERAGE"] = EbvSampleMask; (*SemanticMap)["SV_DEPTHGREATEREQUAL"] = EbvFragDepthGreater; (*SemanticMap)["SV_DEPTHLESSEQUAL"] = EbvFragDepthLesser; (*SemanticMap)["SV_STENCILREF"] = EbvFragStencilRef; } void HlslScanContext::deleteKeywordMap() { delete KeywordMap; KeywordMap = nullptr; delete ReservedSet; ReservedSet = nullptr; delete SemanticMap; SemanticMap = nullptr; } // Wrapper for tokenizeClass() to get everything inside the token. void HlslScanContext::tokenize(HlslToken& token) { EHlslTokenClass tokenClass = tokenizeClass(token); token.tokenClass = tokenClass; } glslang::TBuiltInVariable HlslScanContext::mapSemantic(const char* upperCase) { auto it = SemanticMap->find(upperCase); if (it != SemanticMap->end()) return it->second; else return glslang::EbvNone; } // // Fill in token information for the next token, except for the token class. // Returns the enum value of the token class of the next token found. // Return 0 (EndOfTokens) on end of input. // EHlslTokenClass HlslScanContext::tokenizeClass(HlslToken& token) { do { parserToken = &token; TPpToken ppToken; int token = ppContext.tokenize(ppToken); if (token == EndOfInput) return EHTokNone; tokenText = ppToken.name; loc = ppToken.loc; parserToken->loc = loc; switch (token) { case ';': return EHTokSemicolon; case ',': return EHTokComma; case ':': return EHTokColon; case '=': return EHTokAssign; case '(': return EHTokLeftParen; case ')': return EHTokRightParen; case '.': return EHTokDot; case '!': return EHTokBang; case '-': return EHTokDash; case '~': return EHTokTilde; case '+': return EHTokPlus; case '*': return EHTokStar; case '/': return EHTokSlash; case '%': return EHTokPercent; case '<': return EHTokLeftAngle; case '>': return EHTokRightAngle; case '|': return EHTokVerticalBar; case '^': return EHTokCaret; case '&': return EHTokAmpersand; case '?': return EHTokQuestion; case '[': return EHTokLeftBracket; case ']': return EHTokRightBracket; case '{': return EHTokLeftBrace; case '}': return EHTokRightBrace; case '\\': parseContext.error(loc, "illegal use of escape character", "\\", ""); break; case PPAtomAddAssign: return EHTokAddAssign; case PPAtomSubAssign: return EHTokSubAssign; case PPAtomMulAssign: return EHTokMulAssign; case PPAtomDivAssign: return EHTokDivAssign; case PPAtomModAssign: return EHTokModAssign; case PpAtomRight: return EHTokRightOp; case PpAtomLeft: return EHTokLeftOp; case PpAtomRightAssign: return EHTokRightAssign; case PpAtomLeftAssign: return EHTokLeftAssign; case PpAtomAndAssign: return EHTokAndAssign; case PpAtomOrAssign: return EHTokOrAssign; case PpAtomXorAssign: return EHTokXorAssign; case PpAtomAnd: return EHTokAndOp; case PpAtomOr: return EHTokOrOp; case PpAtomXor: return EHTokXorOp; case PpAtomEQ: return EHTokEqOp; case PpAtomGE: return EHTokGeOp; case PpAtomNE: return EHTokNeOp; case PpAtomLE: return EHTokLeOp; case PpAtomDecrement: return EHTokDecOp; case PpAtomIncrement: return EHTokIncOp; case PpAtomColonColon: return EHTokColonColon; case PpAtomConstInt: parserToken->i = ppToken.ival; return EHTokIntConstant; case PpAtomConstUint: parserToken->i = ppToken.ival; return EHTokUintConstant; case PpAtomConstFloat16: parserToken->d = ppToken.dval; return EHTokFloat16Constant; case PpAtomConstFloat: parserToken->d = ppToken.dval; return EHTokFloatConstant; case PpAtomConstDouble: parserToken->d = ppToken.dval; return EHTokDoubleConstant; case PpAtomIdentifier: { EHlslTokenClass token = tokenizeIdentifier(); return token; } case PpAtomConstString: { parserToken->string = NewPoolTString(tokenText); return EHTokStringConstant; } case EndOfInput: return EHTokNone; default: if (token < PpAtomMaxSingle) { char buf[2]; buf[0] = (char)token; buf[1] = 0; parseContext.error(loc, "unexpected token", buf, ""); } else if (tokenText[0] != 0) parseContext.error(loc, "unexpected token", tokenText, ""); else parseContext.error(loc, "unexpected token", "", ""); break; } } while (true); } EHlslTokenClass HlslScanContext::tokenizeIdentifier() { if (ReservedSet->find(tokenText) != ReservedSet->end()) return reservedWord(); auto it = KeywordMap->find(tokenText); if (it == KeywordMap->end()) { // Should have an identifier of some sort return identifierOrType(); } keyword = it->second; switch (keyword) { // qualifiers case EHTokStatic: case EHTokConst: case EHTokSNorm: case EHTokUnorm: case EHTokExtern: case EHTokUniform: case EHTokVolatile: case EHTokShared: case EHTokGroupShared: case EHTokLinear: case EHTokCentroid: case EHTokNointerpolation: case EHTokNoperspective: case EHTokSample: case EHTokRowMajor: case EHTokColumnMajor: case EHTokPackOffset: case EHTokIn: case EHTokOut: case EHTokInOut: case EHTokPrecise: case EHTokLayout: case EHTokGloballyCoherent: case EHTokInline: return keyword; // primitive types case EHTokPoint: case EHTokLine: case EHTokTriangle: case EHTokLineAdj: case EHTokTriangleAdj: return keyword; // stream out types case EHTokPointStream: case EHTokLineStream: case EHTokTriangleStream: return keyword; // Tessellation patches case EHTokInputPatch: case EHTokOutputPatch: return keyword; case EHTokBuffer: case EHTokVector: case EHTokMatrix: return keyword; // scalar types case EHTokVoid: case EHTokString: case EHTokBool: case EHTokInt: case EHTokUint: case EHTokUint64: case EHTokDword: case EHTokHalf: case EHTokFloat: case EHTokDouble: case EHTokMin16float: case EHTokMin10float: case EHTokMin16int: case EHTokMin12int: case EHTokMin16uint: // vector types case EHTokBool1: case EHTokBool2: case EHTokBool3: case EHTokBool4: case EHTokFloat1: case EHTokFloat2: case EHTokFloat3: case EHTokFloat4: case EHTokInt1: case EHTokInt2: case EHTokInt3: case EHTokInt4: case EHTokDouble1: case EHTokDouble2: case EHTokDouble3: case EHTokDouble4: case EHTokUint1: case EHTokUint2: case EHTokUint3: case EHTokUint4: case EHTokHalf1: case EHTokHalf2: case EHTokHalf3: case EHTokHalf4: case EHTokMin16float1: case EHTokMin16float2: case EHTokMin16float3: case EHTokMin16float4: case EHTokMin10float1: case EHTokMin10float2: case EHTokMin10float3: case EHTokMin10float4: case EHTokMin16int1: case EHTokMin16int2: case EHTokMin16int3: case EHTokMin16int4: case EHTokMin12int1: case EHTokMin12int2: case EHTokMin12int3: case EHTokMin12int4: case EHTokMin16uint1: case EHTokMin16uint2: case EHTokMin16uint3: case EHTokMin16uint4: // matrix types case EHTokBool1x1: case EHTokBool1x2: case EHTokBool1x3: case EHTokBool1x4: case EHTokBool2x1: case EHTokBool2x2: case EHTokBool2x3: case EHTokBool2x4: case EHTokBool3x1: case EHTokBool3x2: case EHTokBool3x3: case EHTokBool3x4: case EHTokBool4x1: case EHTokBool4x2: case EHTokBool4x3: case EHTokBool4x4: case EHTokInt1x1: case EHTokInt1x2: case EHTokInt1x3: case EHTokInt1x4: case EHTokInt2x1: case EHTokInt2x2: case EHTokInt2x3: case EHTokInt2x4: case EHTokInt3x1: case EHTokInt3x2: case EHTokInt3x3: case EHTokInt3x4: case EHTokInt4x1: case EHTokInt4x2: case EHTokInt4x3: case EHTokInt4x4: case EHTokUint1x1: case EHTokUint1x2: case EHTokUint1x3: case EHTokUint1x4: case EHTokUint2x1: case EHTokUint2x2: case EHTokUint2x3: case EHTokUint2x4: case EHTokUint3x1: case EHTokUint3x2: case EHTokUint3x3: case EHTokUint3x4: case EHTokUint4x1: case EHTokUint4x2: case EHTokUint4x3: case EHTokUint4x4: case EHTokFloat1x1: case EHTokFloat1x2: case EHTokFloat1x3: case EHTokFloat1x4: case EHTokFloat2x1: case EHTokFloat2x2: case EHTokFloat2x3: case EHTokFloat2x4: case EHTokFloat3x1: case EHTokFloat3x2: case EHTokFloat3x3: case EHTokFloat3x4: case EHTokFloat4x1: case EHTokFloat4x2: case EHTokFloat4x3: case EHTokFloat4x4: case EHTokHalf1x1: case EHTokHalf1x2: case EHTokHalf1x3: case EHTokHalf1x4: case EHTokHalf2x1: case EHTokHalf2x2: case EHTokHalf2x3: case EHTokHalf2x4: case EHTokHalf3x1: case EHTokHalf3x2: case EHTokHalf3x3: case EHTokHalf3x4: case EHTokHalf4x1: case EHTokHalf4x2: case EHTokHalf4x3: case EHTokHalf4x4: case EHTokDouble1x1: case EHTokDouble1x2: case EHTokDouble1x3: case EHTokDouble1x4: case EHTokDouble2x1: case EHTokDouble2x2: case EHTokDouble2x3: case EHTokDouble2x4: case EHTokDouble3x1: case EHTokDouble3x2: case EHTokDouble3x3: case EHTokDouble3x4: case EHTokDouble4x1: case EHTokDouble4x2: case EHTokDouble4x3: case EHTokDouble4x4: return keyword; // texturing types case EHTokSampler: case EHTokSampler1d: case EHTokSampler2d: case EHTokSampler3d: case EHTokSamplerCube: case EHTokSamplerState: case EHTokSamplerComparisonState: case EHTokTexture: case EHTokTexture1d: case EHTokTexture1darray: case EHTokTexture2d: case EHTokTexture2darray: case EHTokTexture3d: case EHTokTextureCube: case EHTokTextureCubearray: case EHTokTexture2DMS: case EHTokTexture2DMSarray: case EHTokRWTexture1d: case EHTokRWTexture1darray: case EHTokRWTexture2d: case EHTokRWTexture2darray: case EHTokRWTexture3d: case EHTokRWBuffer: case EHTokAppendStructuredBuffer: case EHTokByteAddressBuffer: case EHTokConsumeStructuredBuffer: case EHTokRWByteAddressBuffer: case EHTokRWStructuredBuffer: case EHTokStructuredBuffer: case EHTokTextureBuffer: case EHTokSubpassInput: case EHTokSubpassInputMS: return keyword; // variable, user type, ... case EHTokClass: case EHTokStruct: case EHTokTypedef: case EHTokCBuffer: case EHTokConstantBuffer: case EHTokTBuffer: case EHTokThis: case EHTokNamespace: return keyword; case EHTokBoolConstant: if (strcmp("true", tokenText) == 0) parserToken->b = true; else parserToken->b = false; return keyword; // control flow case EHTokFor: case EHTokDo: case EHTokWhile: case EHTokBreak: case EHTokContinue: case EHTokIf: case EHTokElse: case EHTokDiscard: case EHTokReturn: case EHTokCase: case EHTokSwitch: case EHTokDefault: return keyword; default: parseContext.infoSink.info.message(EPrefixInternalError, "Unknown glslang keyword", loc); return EHTokNone; } } EHlslTokenClass HlslScanContext::identifierOrType() { parserToken->string = NewPoolTString(tokenText); return EHTokIdentifier; } // Give an error for use of a reserved symbol. // However, allow built-in declarations to use reserved words, to allow // extension support before the extension is enabled. EHlslTokenClass HlslScanContext::reservedWord() { if (! parseContext.symbolTable.atBuiltInLevel()) parseContext.error(loc, "Reserved word.", tokenText, "", ""); return EHTokNone; } } // end namespace glslang