HLSL: Plumb in HLSL parse context and keywords, and most basic HLSL parser and test.

This commit is contained in:
John Kessenich 2016-03-12 20:11:22 -07:00
Родитель b3dc3acd59
Коммит e01a9bc8c0
16 изменённых файлов: 5047 добавлений и 16 удалений

Просмотреть файл

@ -24,3 +24,4 @@ add_subdirectory(glslang)
add_subdirectory(OGLCompilersDLL)
add_subdirectory(StandAlone)
add_subdirectory(SPIRV)
add_subdirectory(hlsl)

Просмотреть файл

@ -10,6 +10,7 @@ set(LIBRARIES
glslang
OGLCompiler
OSDependent
HLSL
SPIRV)
if(WIN32)

Просмотреть файл

@ -0,0 +1,21 @@
hlsl.frag
Linked fragment stage:
// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 6
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 4 "PixelShaderFunction"
ExecutionMode 4 OriginUpperLeft
Source HLSL 100
Name 4 "PixelShaderFunction"
2: TypeVoid
3: TypeFunction 2
4(PixelShaderFunction): 2 Function None 3
5: Label
FunctionEnd

11
Test/hlsl.frag Normal file
Просмотреть файл

@ -0,0 +1,11 @@
//float4x4 World;
//float4x4 View;
//float4x4 Projection;
//
//float4 AmbientColor = float4(1, 1, 1, 1);
//float AmbientIntensity = 0.1;
//
//float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
//{
// return AmbientColor * AmbientIntensity;
//}

Просмотреть файл

@ -55,6 +55,24 @@ while read t; do
done < test-spirv-list
rm -f comp.spv frag.spv geom.spv tesc.spv tese.spv vert.spv
#
# HLSL -> SPIR-V code generation tests
#
while read t; do
case $t in
\#*)
# Skip comment lines in the test list file.
;;
*)
echo Running HLSL-to-SPIR-V $t...
b=`basename $t`
$EXE -D -e PixelShaderFunction -H $t > $TARGETDIR/$b.out
diff -b $BASEDIR/$b.out $TARGETDIR/$b.out || HASERROR=1
;;
esac
done < test-hlsl-spirv-list
rm -f comp.spv frag.spv geom.spv tesc.spv tese.spv vert.spv
#
# Preprocessor tests
#

Просмотреть файл

@ -0,0 +1,4 @@
# Test looping constructs.
# No tests yet for making sure break and continue from a nested loop
# goes to the innermost target.
hlsl.frag

Просмотреть файл

@ -46,6 +46,7 @@
#include <sstream>
#include "SymbolTable.h"
#include "ParseHelper.h"
#include "../../hlsl/hlslParseHelper.h"
#include "Scan.h"
#include "ScanContext.h"
@ -598,26 +599,37 @@ bool ProcessDeferred(
// Now we can process the full shader under proper symbols and rules.
//
TParseContextBase* parseContext;
if (source == EShSourceHlsl) {
parseContext = new HlslParseContext(symbolTable, intermediate, false, version, profile, spv, vulkan,
compiler->getLanguage(), compiler->infoSink, forwardCompatible, messages);
}
else {
intermediate.setEntryPoint("main");
TParseContext parseContext(symbolTable, intermediate, false, version, profile, spv, vulkan, compiler->getLanguage(), compiler->infoSink, forwardCompatible, messages);
glslang::TScanContext scanContext(parseContext);
TPpContext ppContext(parseContext, includer);
parseContext.setScanContext(&scanContext);
parseContext.setPpContext(&ppContext);
parseContext.setLimits(*resources);
parseContext = new TParseContext(symbolTable, intermediate, false, version, profile, spv, vulkan,
compiler->getLanguage(), compiler->infoSink, forwardCompatible, messages);
}
TPpContext ppContext(*parseContext, includer);
// only GLSL (bison triggered, really) needs an externally set scan context
glslang::TScanContext scanContext(*parseContext);
if ((messages & EShMsgReadHlsl) == 0)
parseContext->setScanContext(&scanContext);
parseContext->setPpContext(&ppContext);
parseContext->setLimits(*resources);
if (! goodVersion)
parseContext.addError();
parseContext->addError();
if (warnVersionNotFirst) {
TSourceLoc loc;
loc.init();
parseContext.warn(loc, "Illegal to have non-comment, non-whitespace tokens before #version", "#version", "");
parseContext->warn(loc, "Illegal to have non-comment, non-whitespace tokens before #version", "#version", "");
}
parseContext.initializeExtensionBehavior();
parseContext->initializeExtensionBehavior();
// Fill in the strings as outlined above.
strings[0] = parseContext.getPreamble();
strings[0] = parseContext->getPreamble();
lengths[0] = strlen(strings[0]);
names[0] = nullptr;
strings[1] = customPreamble;
@ -635,14 +647,14 @@ bool ProcessDeferred(
// Push a new symbol allocation scope that will get used for the shader's globals.
symbolTable.push();
bool success = processingContext(parseContext, ppContext, fullInput,
bool success = processingContext(*parseContext, ppContext, fullInput,
versionWillBeError, symbolTable,
intermediate, optLevel, messages);
// Clean up the symbol table. The AST is self-sufficient now.
delete symbolTableMemory;
delete parseContext;
delete [] lengths;
delete [] strings;
delete [] names;

Просмотреть файл

@ -69,6 +69,18 @@ void TIntermediate::error(TInfoSink& infoSink, const char* message)
//
void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
{
if (source == EShSourceNone)
source = unit.source;
if (source != unit.source)
error(infoSink, "can't link compilation units from different source languages");
if (source == EShSourceHlsl && unit.entryPoint.size() > 0) {
if (entryPoint.size() > 0)
error(infoSink, "can't handle multiple entry points per stage");
else
entryPoint = unit.entryPoint;
}
numMains += unit.numMains;
numErrors += unit.numErrors;
numPushConstants += unit.numPushConstants;
@ -356,7 +368,7 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
//
void TIntermediate::finalCheck(TInfoSink& infoSink)
{
if (numMains < 1)
if (source == EShSourceGlsl && numMains < 1)
error(infoSink, "Missing entry point: Each stage requires one \"void main()\" entry point");
if (numPushConstants > 1)

21
hlsl/CMakeLists.txt Executable file
Просмотреть файл

@ -0,0 +1,21 @@
cmake_minimum_required(VERSION 2.8)
set(SOURCES
hlslParseHelper.cpp
hlslScanContext.cpp
hlslGrammar.cpp)
set(HEADERS
hlslParseHelper.h
hlslTokens.h
hlslScanContext.h
hlslGrammar.h)
add_library(HLSL STATIC ${SOURCES} ${HEADERS})
if(WIN32)
source_group("Source" FILES ${SOURCES} ${HEADERS})
endif(WIN32)
install(TARGETS HLSL
ARCHIVE DESTINATION lib)

93
hlsl/hlslGrammar.cpp Executable file
Просмотреть файл

@ -0,0 +1,93 @@
//
//Copyright (C) 2016 Google, 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.
//
#include "hlslTokens.h"
#include "hlslGrammar.h"
namespace glslang {
// Root entry point to this recursive decent parser.
// Return true if compilation unit was successfully accepted.
bool HlslGrammar::parse()
{
advanceToken();
return acceptCompilationUnit();
}
void HlslGrammar::expected(const char* syntax)
{
parseContext.error(token.loc, "Expected", syntax, "");
}
// Load 'token' with the next token in the stream of tokens.
void HlslGrammar::advanceToken()
{
scanContext.tokenize(token);
}
// Return true and advance to the next token if the current token is the
// expected (passed in) token class.
bool HlslGrammar::acceptTokenClass(EHlslTokenClass tokenClass)
{
if (token.tokenClass == tokenClass) {
advanceToken();
return true;
}
return false;
}
// compilationUnit
// : list of externalDeclaration
//
bool HlslGrammar::acceptCompilationUnit()
{
while (token.tokenClass != EHTokNone) {
if (! acceptDeclaration())
return false;
}
return true;
}
// declaration
// : dummy stub
bool HlslGrammar::acceptDeclaration()
{
advanceToken();
return true;
}
} // end namespace glslang

68
hlsl/hlslGrammar.h Executable file
Просмотреть файл

@ -0,0 +1,68 @@
//
//Copyright (C) 2016 Google, 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.
//
#ifndef HLSLGRAMMAR_H_
#define HLSLGRAMMAR_H_
#include "hlslScanContext.h"
#include "hlslParseHelper.h"
namespace glslang {
class HlslGrammar {
public:
HlslGrammar(HlslScanContext& scanContext, HlslParseContext& parseContext)
: scanContext(scanContext), parseContext(parseContext) { }
virtual ~HlslGrammar() { }
bool parse();
protected:
void expected(const char*);
void advanceToken();
bool acceptTokenClass(EHlslTokenClass);
bool acceptCompilationUnit();
bool acceptDeclaration();
HlslScanContext& scanContext;
HlslParseContext& parseContext;
HlslToken token;
};
} // end namespace glslang
#endif // HLSLGRAMMAR_H_

3578
hlsl/hlslParseHelper.cpp Executable file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

222
hlsl/hlslParseHelper.h Executable file
Просмотреть файл

@ -0,0 +1,222 @@
//
//Copyright (C) 2016 Google, 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 3Dlabs Inc. Ltd. 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.
//
#ifndef HLSL_PARSE_INCLUDED_
#define HLSL_PARSE_INCLUDED_
#include "../glslang/MachineIndependent/parseVersions.h"
#include "../glslang/MachineIndependent/ParseHelper.h"
namespace glslang {
class HlslParseContext : public TParseContextBase {
public:
HlslParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins,
int version, EProfile, int spv, int vulkan, EShLanguage, TInfoSink&,
bool forwardCompatible = false, EShMessages messages = EShMsgDefault);
virtual ~HlslParseContext();
void setLimits(const TBuiltInResource&);
bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false);
const char* getPreamble();
void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken,
const char* szExtraInfoFormat, ...);
void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken,
const char* szExtraInfoFormat, ...);
void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken,
const char* szExtraInfoFormat, ...);
void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken,
const char* szExtraInfoFormat, ...);
void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) { }
bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) { return true; }
bool lineDirectiveShouldSetNextLine() const { return true; }
bool builtInName(const TString&);
void handlePragma(const TSourceLoc&, const TVector<TString>&);
TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol, const TString* string);
TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
void checkIndex(const TSourceLoc&, const TType&, int& index);
void makeEditable(TSymbol*&);
TVariable* getEditableVariable(const char* name);
bool isIoResizeArray(const TType&) const;
void fixIoArraySize(const TSourceLoc&, TType&);
void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base);
void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false);
int getIoArrayImplicitSize() const;
void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&);
TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);
TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
void addInputArgumentConversions(const TFunction&, TIntermNode*&) const;
TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const;
void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&);
bool parseVectorFields(const TSourceLoc&, const TString&, int vecSize, TVectorFields&);
void assignError(const TSourceLoc&, const char* op, TString left, TString right);
void unaryOpError(const TSourceLoc&, const char* op, TString operand);
void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);
void variableCheck(TIntermTyped*& nodePtr);
void constantValueCheck(TIntermTyped* node, const char* token);
void integerCheck(const TIntermTyped* node, const char* token);
void globalCheck(const TSourceLoc&, const char* token);
bool constructorError(const TSourceLoc&, TIntermNode*, TFunction&, TOperator, TType&);
bool constructorTextureSamplerError(const TSourceLoc&, const TFunction&);
void arraySizeCheck(const TSourceLoc&, TIntermTyped* expr, TArraySize&);
void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&);
void structArrayCheck(const TSourceLoc&, const TType& structure);
void arrayDimMerge(TType& type, const TArraySizes* sizes);
bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType);
void boolCheck(const TSourceLoc&, const TIntermTyped*);
void boolCheck(const TSourceLoc&, const TPublicType&);
void globalQualifierFix(const TSourceLoc&, TQualifier&);
bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force);
int computeSamplerTypeIndex(TSampler&);
TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&, bool& newDeclaration);
void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes);
void paramCheckFix(const TSourceLoc&, const TStorageQualifier&, TType& type);
void paramCheckFix(const TSourceLoc&, const TQualifier&, TType& type);
void specializationCheck(const TSourceLoc&, const TType&, const char* op);
void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&);
void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&, const TIntermTyped*);
void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly);
void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&);
const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0);
TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&, TOperator);
TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&);
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
void fixBlockXfbOffsets(TQualifier&, TTypeList&);
void fixBlockUniformOffsets(TQualifier&, TTypeList&);
void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier);
void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body);
void updateImplicitArraySize(const TSourceLoc&, TIntermNode*, int index);
protected:
void inheritGlobalDefaults(TQualifier& dst) const;
TVariable* makeInternalVariable(const char* name, const TType&) const;
TVariable* declareNonArray(const TSourceLoc&, TString& identifier, TType&, bool& newDeclaration);
void declareArray(const TSourceLoc&, TString& identifier, const TType&, TSymbol*&, bool& newDeclaration);
TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer);
TOperator mapTypeToConstructorOp(const TType&) const;
void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken,
const char* szExtraInfoFormat, TPrefixType prefix,
va_list args);
// Current state of parsing
struct TPragma contextPragma;
int loopNestingLevel; // 0 if outside all loops
int structNestingLevel; // 0 if outside blocks and structures
int controlFlowNestingLevel; // 0 if outside all flow control
int statementNestingLevel; // 0 if outside all flow control or compound statements
TList<TIntermSequence*> switchSequenceStack; // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting
TList<int> switchLevel; // the statementNestingLevel the current switch statement is at, which must match the level of its case statements
bool inEntrypoint; // if inside a function, true if the function is the entry point
bool postMainReturn; // if inside a function, true if the function is the entry point and this is after a return statement
const TType* currentFunctionType; // the return type of the function that's currently being parsed
bool functionReturnsValue; // true if a non-void function has a return
const TString* blockName;
TQualifier currentBlockQualifier;
TBuiltInResource resources;
TLimits& limits;
HlslParseContext(HlslParseContext&);
HlslParseContext& operator=(HlslParseContext&);
TMap<TString, TExtensionBehavior> extensionBehavior; // for each extension string, what its current behavior is set to
static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2)); // see computeSamplerTypeIndex()
bool afterEOF;
TQualifier globalBufferDefaults;
TQualifier globalUniformDefaults;
TQualifier globalInputDefaults;
TQualifier globalOutputDefaults;
TString currentCaller; // name of last function body entered (not valid when at global scope)
TIdSetType inductiveLoopIds;
TVector<TIntermTyped*> needsIndexLimitationChecking;
//
// Geometry shader input arrays:
// - array sizing is based on input primitive and/or explicit size
//
// Tessellation control output arrays:
// - array sizing is based on output layout(vertices=...) and/or explicit size
//
// Both:
// - array sizing is retroactive
// - built-in block redeclarations interact with this
//
// Design:
// - use a per-context "resize-list", a list of symbols whose array sizes
// can be fixed
//
// - the resize-list starts empty at beginning of user-shader compilation, it does
// not have built-ins in it
//
// - on built-in array use: copyUp() symbol and add it to the resize-list
//
// - on user array declaration: add it to the resize-list
//
// - on block redeclaration: copyUp() symbol and add it to the resize-list
// * note, that appropriately gives an error if redeclaring a block that
// was already used and hence already copied-up
//
// - on seeing a layout declaration that sizes the array, fix everything in the
// resize-list, giving errors for mismatch
//
// - on seeing an array size declaration, give errors on mismatch between it and previous
// array-sizing declarations
//
TVector<TSymbol*> ioArraySymbolResizeList;
};
} // end namespace glslang
#endif // HLSL_PARSE_INCLUDED_

619
hlsl/hlslScanContext.cpp Executable file
Просмотреть файл

@ -0,0 +1,619 @@
//
//Copyright (C) 2016 Google, 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 <string.h>
#include <unordered_map>
#include <unordered_set>
#include "../glslang/Include/Types.h"
#include "../glslang/MachineIndependent/SymbolTable.h"
#include "../glslang/MachineIndependent/ParseHelper.h"
#include "hlslScanContext.h"
#include "hlslTokens.h"
//#include "Scan.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<const char*, glslang::EHlslTokenClass, str_hash, str_eq>* KeywordMap = nullptr;
std::unordered_set<const char*, str_hash, str_eq>* ReservedSet = 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<const char*, EHlslTokenClass, str_hash, str_eq>;
(*KeywordMap)["static"] = EHTokStatic;
(*KeywordMap)["const"] = EHTokConst;
(*KeywordMap)["unorm"] = EHTokUnorm;
(*KeywordMap)["snorm"] = EHTokSNorm;
(*KeywordMap)["extern"] = EHTokExtern;
(*KeywordMap)["uniform"] = EHTokUniform;
(*KeywordMap)["volatile"] = EHTokVolatile;
(*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)["Buffer"] = EHTokBuffer;
(*KeywordMap)["vector"] = EHTokVector;
(*KeywordMap)["matrix"] = EHTokMatrix;
(*KeywordMap)["void"] = EHTokVoid;
(*KeywordMap)["bool"] = EHTokBool;
(*KeywordMap)["int"] = EHTokInt;
(*KeywordMap)["uint"] = EHTokUint;
(*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"] = EHTokMin16int;
(*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)["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)["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)["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)["struct"] = EHTokStruct;
(*KeywordMap)["typedef"] = EHTokTypedef;
(*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<const char*, str_hash, str_eq>;
ReservedSet->insert("common");
ReservedSet->insert("partition");
ReservedSet->insert("active");
ReservedSet->insert("asm");
ReservedSet->insert("class");
ReservedSet->insert("union");
ReservedSet->insert("enum");
ReservedSet->insert("template");
ReservedSet->insert("this");
ReservedSet->insert("goto");
ReservedSet->insert("inline");
ReservedSet->insert("noinline");
ReservedSet->insert("public");
ReservedSet->insert("extern");
ReservedSet->insert("external");
ReservedSet->insert("interface");
ReservedSet->insert("long");
ReservedSet->insert("short");
ReservedSet->insert("half");
ReservedSet->insert("fixed");
ReservedSet->insert("unsigned");
ReservedSet->insert("input");
ReservedSet->insert("output");
ReservedSet->insert("filter");
ReservedSet->insert("sizeof");
ReservedSet->insert("cast");
ReservedSet->insert("namespace");
ReservedSet->insert("using");
}
void HlslScanContext::deleteKeywordMap()
{
delete KeywordMap;
KeywordMap = nullptr;
delete ReservedSet;
ReservedSet = nullptr;
}
// Wrapper for tokenizeClass()"] = to get everything inside the token.
void HlslScanContext::tokenize(HlslToken& token)
{
token.isType = false;
EHlslTokenClass tokenClass = tokenizeClass(token);
token.tokenClass = tokenClass;
if (token.isType)
afterType = true;
}
//
// 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;
tokenText = ppContext.tokenize(&ppToken);
if (tokenText == nullptr)
return EHTokNone;
loc = ppToken.loc;
parserToken->loc = loc;
switch (ppToken.token) {
case ';': afterType = false; return EHTokSemicolon;
case ',': afterType = false; return EHTokComma;
case ':': return EHTokColon;
case '=': afterType = false; return EHTokEqual;
case '(': afterType = false; return EHTokLeftParen;
case ')': afterType = false; return EHTokRightParen;
case '.': field = true; 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 PpAtomAdd: return EHTokAddAssign;
case PpAtomSub: return EHTokSubAssign;
case PpAtomMul: return EHTokMulAssign;
case PpAtomDiv: return EHTokDivAssign;
case PpAtomMod: 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 PpAtomConstInt: parserToken->i = ppToken.ival; return EHTokIntConstant;
case PpAtomConstUint: parserToken->i = ppToken.ival; return EHTokUintConstant;
case PpAtomConstFloat: parserToken->d = ppToken.dval; return EHTokFloatConstant;
case PpAtomConstDouble: parserToken->d = ppToken.dval; return EHTokDoubleConstant;
case PpAtomIdentifier:
{
EHlslTokenClass token = tokenizeIdentifier();
field = false;
return token;
}
case EndOfInput: return EHTokNone;
default:
char buf[2];
buf[0] = (char)ppToken.token;
buf[1] = 0;
parseContext.error(loc, "unexpected token", buf, "");
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:
return keyword;
// template types
case EHTokBuffer:
case EHTokVector:
case EHTokMatrix:
return keyword;
// scalar types
case EHTokVoid:
case EHTokBool:
case EHTokInt:
case EHTokUint:
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:
// matrix types
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 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 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:
parserToken->isType = true;
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:
parserToken->isType = true;
return keyword;
// variable, user type, ...
case EHTokStruct:
case EHTokTypedef:
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);
if (field)
return EHTokIdentifier;
parserToken->symbol = parseContext.symbolTable.find(*parserToken->string);
if (afterType == false && parserToken->symbol) {
if (const TVariable* variable = parserToken->symbol->getAsVariable()) {
if (variable->isUserType()) {
afterType = true;
return EHTokTypeName;
}
}
}
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;
}
EHlslTokenClass HlslScanContext::identifierOrReserved(bool reserved)
{
if (reserved) {
reservedWord();
return EHTokNone;
}
if (parseContext.forwardCompatible)
parseContext.warn(loc, "using future reserved keyword", tokenText, "");
return identifierOrType();
}
// For a keyword that was never reserved, until it suddenly
// showed up.
EHlslTokenClass HlslScanContext::nonreservedKeyword(int version)
{
if (parseContext.version < version)
return identifierOrType();
return keyword;
}
} // end namespace glslang

102
hlsl/hlslScanContext.h Executable file
Просмотреть файл

@ -0,0 +1,102 @@
//
//Copyright (C) 2016 Google, 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.
//
//
// This holds context specific to the GLSL scanner, which
// sits between the preprocessor scanner and parser.
//
#ifndef HLSLSCANCONTEXT_H_
#define HLSLSCANCONTEXT_H_
#include "../glslang/MachineIndependent/ParseHelper.h"
#include "hlslTokens.h"
namespace glslang {
class TPpContext;
class TPpToken;
struct HlslToken {
TSourceLoc loc;
EHlslTokenClass tokenClass;
bool isType;
union {
glslang::TString *string;
int i;
unsigned int u;
bool b;
double d;
};
glslang::TSymbol* symbol;
};
class HlslScanContext {
public:
HlslScanContext(TParseContextBase& parseContext, TPpContext& ppContext)
: parseContext(parseContext), ppContext(ppContext), afterType(false), field(false) { }
virtual ~HlslScanContext() { }
static void fillInKeywordMap();
static void deleteKeywordMap();
void tokenize(HlslToken&);
protected:
HlslScanContext(HlslScanContext&);
HlslScanContext& operator=(HlslScanContext&);
EHlslTokenClass tokenizeClass(HlslToken&);
EHlslTokenClass tokenizeIdentifier();
EHlslTokenClass identifierOrType();
EHlslTokenClass reservedWord();
EHlslTokenClass identifierOrReserved(bool reserved);
EHlslTokenClass nonreservedKeyword(int version);
TParseContextBase& parseContext;
TPpContext& ppContext;
bool afterType; // true if we've recognized a type, so can only be looking for an identifier
bool field; // true if we're on a field, right after a '.'
TSourceLoc loc;
TPpToken* ppToken;
HlslToken* parserToken;
const char* tokenText;
EHlslTokenClass keyword;
};
} // end namespace glslang
#endif // HLSLSCANCONTEXT_H_

248
hlsl/hlslTokens.h Executable file
Просмотреть файл

@ -0,0 +1,248 @@
//
//Copyright (C) 2016 Google, 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.
//
#ifndef EHLSLTOKENS_H_
#define EHLSLTOKENS_H_
namespace glslang {
enum EHlslTokenClass {
EHTokNone = 0,
// qualifiers
EHTokStatic,
EHTokConst,
EHTokSNorm,
EHTokUnorm,
EHTokExtern,
EHTokUniform,
EHTokVolatile,
EHTokShared,
EHTokGroupShared,
EHTokLinear,
EHTokCentroid,
EHTokNointerpolation,
EHTokNoperspective,
EHTokSample,
EHTokRowMajor,
EHTokColumnMajor,
EHTokPackOffset,
// template types
EHTokBuffer,
EHTokVector,
EHTokMatrix,
// scalar types
EHTokVoid,
EHTokBool,
EHTokInt,
EHTokUint,
EHTokDword,
EHTokHalf,
EHTokFloat,
EHTokDouble,
EHTokMin16float,
EHTokMin10float,
EHTokMin16int,
EHTokMin12int,
EHTokMin16uint,
// vector types
EHTokBool1,
EHTokBool2,
EHTokBool3,
EHTokBool4,
EHTokFloat1,
EHTokFloat2,
EHTokFloat3,
EHTokFloat4,
EHTokInt1,
EHTokInt2,
EHTokInt3,
EHTokInt4,
EHTokDouble1,
EHTokDouble2,
EHTokDouble3,
EHTokDouble4,
EHTokUint1,
EHTokUint2,
EHTokUint3,
EHTokUint4,
// matrix types
EHTokInt1x1,
EHTokInt1x2,
EHTokInt1x3,
EHTokInt1x4,
EHTokInt2x1,
EHTokInt2x2,
EHTokInt2x3,
EHTokInt2x4,
EHTokInt3x1,
EHTokInt3x2,
EHTokInt3x3,
EHTokInt3x4,
EHTokInt4x1,
EHTokInt4x2,
EHTokInt4x3,
EHTokInt4x4,
EHTokFloat1x1,
EHTokFloat1x2,
EHTokFloat1x3,
EHTokFloat1x4,
EHTokFloat2x1,
EHTokFloat2x2,
EHTokFloat2x3,
EHTokFloat2x4,
EHTokFloat3x1,
EHTokFloat3x2,
EHTokFloat3x3,
EHTokFloat3x4,
EHTokFloat4x1,
EHTokFloat4x2,
EHTokFloat4x3,
EHTokFloat4x4,
EHTokDouble1x1,
EHTokDouble1x2,
EHTokDouble1x3,
EHTokDouble1x4,
EHTokDouble2x1,
EHTokDouble2x2,
EHTokDouble2x3,
EHTokDouble2x4,
EHTokDouble3x1,
EHTokDouble3x2,
EHTokDouble3x3,
EHTokDouble3x4,
EHTokDouble4x1,
EHTokDouble4x2,
EHTokDouble4x3,
EHTokDouble4x4,
// texturing types
EHTokSampler,
EHTokSampler1d,
EHTokSampler2d,
EHTokSampler3d,
EHTokSamplerCube,
EHTokSamplerState,
EHTokSamplerComparisonState,
EHTokTexture,
EHTokTexture1d,
EHTokTexture1darray,
EHTokTexture2d,
EHTokTexture2darray,
EHTokTexture3d,
EHTokTextureCube,
// variable, user type, ...
EHTokIdentifier,
EHTokTypeName,
EHTokStruct,
EHTokTypedef,
// constant
EHTokFloatConstant,
EHTokDoubleConstant,
EHTokIntConstant,
EHTokUintConstant,
EHTokBoolConstant,
// control flow
EHTokFor,
EHTokDo,
EHTokWhile,
EHTokBreak,
EHTokContinue,
EHTokIf,
EHTokElse,
EHTokDiscard,
EHTokReturn,
EHTokSwitch,
EHTokCase,
EHTokDefault,
// expressions
EHTokLeftOp,
EHTokRightOp,
EHTokIncOp,
EHTokDecOp,
EHTokLeOp,
EHTokGeOp,
EHTokEqOp,
EHTokNeOp,
EHTokAndOp,
EHTokOrOp,
EHTokXorOp,
EHTokMulAssign,
EHTokDivAssign,
EHTokAddAssign,
EHTokModAssign,
EHTokLeftAssign,
EHTokRightAssign,
EHTokAndAssign,
EHTokXorAssign,
EHTokOrAssign,
EHTokSubAssign,
EHTokLeftParen,
EHTokRightParen,
EHTokLeftBracket,
EHTokRightBracket,
EHTokLeftBrace,
EHTokRightBrace,
EHTokDot,
EHTokComma,
EHTokColon,
EHTokEqual,
EHTokSemicolon,
EHTokBang,
EHTokDash,
EHTokTilde,
EHTokPlus,
EHTokStar,
EHTokSlash,
EHTokPercent,
EHTokLeftAngle,
EHTokRightAngle,
EHTokVerticalBar,
EHTokCaret,
EHTokAmpersand,
EHTokQuestion,
};
} // end namespace glslang
#endif // EHLSLTOKENS_H_