From a0c578a6df33de107e3fb73753394263f9530223 Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Wed, 12 Apr 2017 16:31:15 -0600 Subject: [PATCH] HLSL: Fix #758: Support character literals (except for numeric escape sequences). --- Test/baseResults/hlsl.charLit.vert.out | 233 +++++++++++++++++++++ Test/hlsl.charLit.vert | 17 ++ glslang/Include/revision.h | 2 +- .../MachineIndependent/preprocessor/PpContext.h | 1 + .../MachineIndependent/preprocessor/PpScanner.cpp | 78 +++++++ gtests/Hlsl.FromFile.cpp | 1 + 6 files changed, 331 insertions(+), 1 deletion(-) create mode 100755 Test/baseResults/hlsl.charLit.vert.out create mode 100755 Test/hlsl.charLit.vert diff --git a/Test/baseResults/hlsl.charLit.vert.out b/Test/baseResults/hlsl.charLit.vert.out new file mode 100755 index 0000000..cc8388a --- /dev/null +++ b/Test/baseResults/hlsl.charLit.vert.out @@ -0,0 +1,233 @@ +hlsl.charLit.vert +Shader version: 500 +0:? Sequence +0:2 Function Definition: @main( ( temp 4-component vector of float) +0:2 Function Parameters: +0:? Sequence +0:3 Sequence +0:3 move second child to first child ( temp uint) +0:3 'a1' ( temp uint) +0:3 Constant: +0:3 65 (const uint) +0:4 Sequence +0:4 move second child to first child ( temp int) +0:4 'a2' ( temp int) +0:4 Constant: +0:4 48 (const int) +0:6 Sequence +0:6 move second child to first child ( temp int) +0:6 'a3' ( temp int) +0:6 Constant: +0:6 7 (const int) +0:7 add second child into first child ( temp int) +0:7 'a3' ( temp int) +0:7 Constant: +0:7 8 (const int) +0:8 add second child into first child ( temp int) +0:8 'a3' ( temp int) +0:8 Constant: +0:8 9 (const int) +0:9 add second child into first child ( temp int) +0:9 'a3' ( temp int) +0:9 Constant: +0:9 10 (const int) +0:10 add second child into first child ( temp int) +0:10 'a3' ( temp int) +0:10 Constant: +0:10 11 (const int) +0:11 add second child into first child ( temp int) +0:11 'a3' ( temp int) +0:11 Constant: +0:11 12 (const int) +0:12 add second child into first child ( temp int) +0:12 'a3' ( temp int) +0:12 Constant: +0:12 13 (const int) +0:14 Sequence +0:14 move second child to first child ( temp int) +0:14 'a10' ( temp int) +0:14 Constant: +0:14 99 (const int) +0:16 Branch: Return with expression +0:16 Construct vec4 ( temp 4-component vector of float) +0:16 Convert uint to float ( temp float) +0:16 add ( temp uint) +0:16 add ( temp uint) +0:16 add ( temp uint) +0:16 'a1' ( temp uint) +0:16 Convert int to uint ( temp uint) +0:16 'a2' ( temp int) +0:16 Convert int to uint ( temp uint) +0:16 'a3' ( temp int) +0:16 Convert int to uint ( temp uint) +0:16 'a10' ( temp int) +0:2 Function Definition: main( ( temp void) +0:2 Function Parameters: +0:? Sequence +0:2 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' ( out 4-component vector of float Position) +0:2 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? '@entryPointOutput' ( out 4-component vector of float Position) + + +Linked vertex stage: + + +Shader version: 500 +0:? Sequence +0:2 Function Definition: @main( ( temp 4-component vector of float) +0:2 Function Parameters: +0:? Sequence +0:3 Sequence +0:3 move second child to first child ( temp uint) +0:3 'a1' ( temp uint) +0:3 Constant: +0:3 65 (const uint) +0:4 Sequence +0:4 move second child to first child ( temp int) +0:4 'a2' ( temp int) +0:4 Constant: +0:4 48 (const int) +0:6 Sequence +0:6 move second child to first child ( temp int) +0:6 'a3' ( temp int) +0:6 Constant: +0:6 7 (const int) +0:7 add second child into first child ( temp int) +0:7 'a3' ( temp int) +0:7 Constant: +0:7 8 (const int) +0:8 add second child into first child ( temp int) +0:8 'a3' ( temp int) +0:8 Constant: +0:8 9 (const int) +0:9 add second child into first child ( temp int) +0:9 'a3' ( temp int) +0:9 Constant: +0:9 10 (const int) +0:10 add second child into first child ( temp int) +0:10 'a3' ( temp int) +0:10 Constant: +0:10 11 (const int) +0:11 add second child into first child ( temp int) +0:11 'a3' ( temp int) +0:11 Constant: +0:11 12 (const int) +0:12 add second child into first child ( temp int) +0:12 'a3' ( temp int) +0:12 Constant: +0:12 13 (const int) +0:14 Sequence +0:14 move second child to first child ( temp int) +0:14 'a10' ( temp int) +0:14 Constant: +0:14 99 (const int) +0:16 Branch: Return with expression +0:16 Construct vec4 ( temp 4-component vector of float) +0:16 Convert uint to float ( temp float) +0:16 add ( temp uint) +0:16 add ( temp uint) +0:16 add ( temp uint) +0:16 'a1' ( temp uint) +0:16 Convert int to uint ( temp uint) +0:16 'a2' ( temp int) +0:16 Convert int to uint ( temp uint) +0:16 'a3' ( temp int) +0:16 Convert int to uint ( temp uint) +0:16 'a10' ( temp int) +0:2 Function Definition: main( ( temp void) +0:2 Function Parameters: +0:? Sequence +0:2 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' ( out 4-component vector of float Position) +0:2 Function Call: @main( ( temp 4-component vector of float) +0:? Linker Objects +0:? '@entryPointOutput' ( out 4-component vector of float Position) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 58 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Vertex 4 "main" 56 + Source HLSL 500 + Name 4 "main" + Name 9 "@main(" + Name 13 "a1" + Name 17 "a2" + Name 19 "a3" + Name 39 "a10" + Name 56 "@entryPointOutput" + Decorate 56(@entryPointOutput) BuiltIn Position + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeVector 6(float) 4 + 8: TypeFunction 7(fvec4) + 11: TypeInt 32 0 + 12: TypePointer Function 11(int) + 14: 11(int) Constant 65 + 15: TypeInt 32 1 + 16: TypePointer Function 15(int) + 18: 15(int) Constant 48 + 20: 15(int) Constant 7 + 21: 15(int) Constant 8 + 24: 15(int) Constant 9 + 27: 15(int) Constant 10 + 30: 15(int) Constant 11 + 33: 15(int) Constant 12 + 36: 15(int) Constant 13 + 40: 15(int) Constant 99 + 55: TypePointer Output 7(fvec4) +56(@entryPointOutput): 55(ptr) Variable Output + 4(main): 2 Function None 3 + 5: Label + 57: 7(fvec4) FunctionCall 9(@main() + Store 56(@entryPointOutput) 57 + Return + FunctionEnd + 9(@main(): 7(fvec4) Function None 8 + 10: Label + 13(a1): 12(ptr) Variable Function + 17(a2): 16(ptr) Variable Function + 19(a3): 16(ptr) Variable Function + 39(a10): 16(ptr) Variable Function + Store 13(a1) 14 + Store 17(a2) 18 + Store 19(a3) 20 + 22: 15(int) Load 19(a3) + 23: 15(int) IAdd 22 21 + Store 19(a3) 23 + 25: 15(int) Load 19(a3) + 26: 15(int) IAdd 25 24 + Store 19(a3) 26 + 28: 15(int) Load 19(a3) + 29: 15(int) IAdd 28 27 + Store 19(a3) 29 + 31: 15(int) Load 19(a3) + 32: 15(int) IAdd 31 30 + Store 19(a3) 32 + 34: 15(int) Load 19(a3) + 35: 15(int) IAdd 34 33 + Store 19(a3) 35 + 37: 15(int) Load 19(a3) + 38: 15(int) IAdd 37 36 + Store 19(a3) 38 + Store 39(a10) 40 + 41: 11(int) Load 13(a1) + 42: 15(int) Load 17(a2) + 43: 11(int) Bitcast 42 + 44: 11(int) IAdd 41 43 + 45: 15(int) Load 19(a3) + 46: 11(int) Bitcast 45 + 47: 11(int) IAdd 44 46 + 48: 15(int) Load 39(a10) + 49: 11(int) Bitcast 48 + 50: 11(int) IAdd 47 49 + 51: 6(float) ConvertUToF 50 + 52: 7(fvec4) CompositeConstruct 51 51 51 51 + ReturnValue 52 + FunctionEnd diff --git a/Test/hlsl.charLit.vert b/Test/hlsl.charLit.vert new file mode 100755 index 0000000..36c4a1e --- /dev/null +++ b/Test/hlsl.charLit.vert @@ -0,0 +1,17 @@ +float4 main() : SV_Position +{ + uint a1 = 'A'; + int a2 = '0'; + + int a3 = '\a'; + a3 += '\b'; + a3 += '\t'; + a3 += '\n'; + a3 += '\v'; + a3 += '\f'; + a3 += '\r'; + + int a10 = '\c'; + + return a1 + a2 + a3 + a10; +} diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h index 5c9566b..a7b6230 100644 --- a/glslang/Include/revision.h +++ b/glslang/Include/revision.h @@ -2,5 +2,5 @@ // For the version, it uses the latest git tag followed by the number of commits. // For the date, it uses the current date (when then script is run). -#define GLSLANG_REVISION "Overload400-PrecQual.1996" +#define GLSLANG_REVISION "Overload400-PrecQual.1998" #define GLSLANG_DATE "12-Apr-2017" diff --git a/glslang/MachineIndependent/preprocessor/PpContext.h b/glslang/MachineIndependent/preprocessor/PpContext.h index c14f22e..a459d9a 100644 --- a/glslang/MachineIndependent/preprocessor/PpContext.h +++ b/glslang/MachineIndependent/preprocessor/PpContext.h @@ -588,6 +588,7 @@ protected: int ScanFromString(char* s); void missingEndifCheck(); int lFloatConst(int len, int ch, TPpToken* ppToken); + int characterLiteral(TPpToken* ppToken); void push_include(TShader::Includer::IncludeResult* result) { diff --git a/glslang/MachineIndependent/preprocessor/PpScanner.cpp b/glslang/MachineIndependent/preprocessor/PpScanner.cpp index f711ad6..e72efc0 100644 --- a/glslang/MachineIndependent/preprocessor/PpScanner.cpp +++ b/glslang/MachineIndependent/preprocessor/PpScanner.cpp @@ -245,6 +245,82 @@ int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken) return PpAtomConstFloat; } +// Recognize a character literal. +// +// The first ' has already been accepted, read the rest, through the closing '. +// +// Always returns PpAtomConstInt. +// +int TPpContext::characterLiteral(TPpToken* ppToken) +{ + ppToken->name[0] = 0; + ppToken->ival = 0; + + if (parseContext.intermediate.getSource() != EShSourceHlsl) { + // illegal, except in macro definition, for which case we report the character + return '\''; + } + + int ch = getChar(); + switch (ch) { + case '\'': + // As empty sequence: '' + parseContext.ppError(ppToken->loc, "unexpected", "\'", ""); + return PpAtomConstInt; + case '\\': + // As escape sequence: '\XXX' + switch (ch = getChar()) { + case 'a': + ppToken->ival = 7; + break; + case 'b': + ppToken->ival = 8; + break; + case 't': + ppToken->ival = 9; + break; + case 'n': + ppToken->ival = 10; + break; + case 'v': + ppToken->ival = 11; + break; + case 'f': + ppToken->ival = 12; + break; + case 'r': + ppToken->ival = 13; + break; + case 'x': + case '0': + parseContext.ppError(ppToken->loc, "octal and hex sequences not supported", "\\", ""); + break; + default: + // This catches '\'', '\"', '\?', etc. + // Also, things like '\C' mean the same thing as 'C' + // (after the above cases are filtered out). + ppToken->ival = ch; + break; + } + break; + default: + ppToken->ival = ch; + break; + } + ppToken->name[0] = (char)ppToken->ival; + ppToken->name[1] = '\0'; + ch = getChar(); + if (ch != '\'') { + parseContext.ppError(ppToken->loc, "expected", "\'", ""); + // Look ahead for a closing ' + do { + ch = getChar(); + } while (ch != '\'' && ch != EndOfInput && ch != '\n'); + } + + return PpAtomConstInt; +} + // // Scanner used to tokenize source stream. // @@ -701,6 +777,8 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken) return '/'; } break; + case '\'': + return pp->characterLiteral(ppToken); case '"': // TODO: If this gets enhanced to handle escape sequences, or // anything that is different than what #include needs, then diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp index 22368c1..59c09f8 100644 --- a/gtests/Hlsl.FromFile.cpp +++ b/gtests/Hlsl.FromFile.cpp @@ -93,6 +93,7 @@ INSTANTIATE_TEST_CASE_P( {"hlsl.calculatelod.dx10.frag", "main"}, {"hlsl.calculatelodunclamped.dx10.frag", "main"}, {"hlsl.cast.frag", "PixelShaderFunction"}, + {"hlsl.charLit.vert", "main"}, {"hlsl.clip.frag", "main"}, {"hlsl.comparison.vec.frag", "main"}, {"hlsl.conditional.frag", "PixelShaderFunction"}, -- 2.7.4