Merge pull request #2435 from amdrexu/feature

HLSL: Add support for printf().
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index d32c646..5b7f89a 100644
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -1720,6 +1720,12 @@
     if (symbol->getType().getQualifier().isSpecConstant())
         spec_constant_op_mode_setter.turnOnSpecConstantOpMode();
 
+#ifdef ENABLE_HLSL
+    // Skip symbol handling if it is string-typed
+    if (symbol->getBasicType() == glslang::EbtString)
+        return;
+#endif
+
     // getSymbolId() will set up all the IO decorations on the first call.
     // Formal function parameters were mapped during makeFunctions().
     spv::Id id = getSymbolId(symbol);
diff --git a/Test/baseResults/hlsl.printf.comp.out b/Test/baseResults/hlsl.printf.comp.out
new file mode 100644
index 0000000..ea31c35
--- /dev/null
+++ b/Test/baseResults/hlsl.printf.comp.out
@@ -0,0 +1,178 @@
+hlsl.printf.comp
+Shader version: 500
+local_size = (1, 1, 1)
+0:? Sequence
+0:4  Function Definition: @main( ( temp void)
+0:4    Function Parameters: 
+0:?     Sequence
+0:5      Debug printf ( temp void)
+0:5        Constant:
+0:5          "first string"
+0:6      Debug printf ( temp void)
+0:6        Constant:
+0:6          "please print this message."
+0:7      Debug printf ( temp void)
+0:7        Constant:
+0:7          "Variables are: %d %d %.2f"
+0:7        Constant:
+0:7          1 (const uint)
+0:7        Constant:
+0:7          2 (const uint)
+0:7        Constant:
+0:7          1.500000
+0:8      Debug printf ( temp void)
+0:8        Constant:
+0:8          "Integers are: %d %d %d"
+0:8        Constant:
+0:8          1 (const int)
+0:8        Constant:
+0:8          2 (const int)
+0:8        Constant:
+0:8          3 (const int)
+0:9      Debug printf ( temp void)
+0:9        Constant:
+0:9          "More: %d %d %d %d %d %d %d %d %d %d"
+0:9        Constant:
+0:9          1 (const int)
+0:9        Constant:
+0:9          2 (const int)
+0:9        Constant:
+0:9          3 (const int)
+0:9        Constant:
+0:9          4 (const int)
+0:9        Constant:
+0:9          5 (const int)
+0:9        Constant:
+0:9          6 (const int)
+0:9        Constant:
+0:9          7 (const int)
+0:9        Constant:
+0:9          8 (const int)
+0:9        Constant:
+0:9          9 (const int)
+0:9        Constant:
+0:9          10 (const int)
+0:4  Function Definition: main( ( temp void)
+0:4    Function Parameters: 
+0:?     Sequence
+0:4      Function Call: @main( ( temp void)
+0:?   Linker Objects
+0:?     'first' ( const string)
+0:?       "first string"
+
+
+Linked compute stage:
+
+
+Shader version: 500
+local_size = (1, 1, 1)
+0:? Sequence
+0:4  Function Definition: @main( ( temp void)
+0:4    Function Parameters: 
+0:?     Sequence
+0:5      Debug printf ( temp void)
+0:5        Constant:
+0:5          "first string"
+0:6      Debug printf ( temp void)
+0:6        Constant:
+0:6          "please print this message."
+0:7      Debug printf ( temp void)
+0:7        Constant:
+0:7          "Variables are: %d %d %.2f"
+0:7        Constant:
+0:7          1 (const uint)
+0:7        Constant:
+0:7          2 (const uint)
+0:7        Constant:
+0:7          1.500000
+0:8      Debug printf ( temp void)
+0:8        Constant:
+0:8          "Integers are: %d %d %d"
+0:8        Constant:
+0:8          1 (const int)
+0:8        Constant:
+0:8          2 (const int)
+0:8        Constant:
+0:8          3 (const int)
+0:9      Debug printf ( temp void)
+0:9        Constant:
+0:9          "More: %d %d %d %d %d %d %d %d %d %d"
+0:9        Constant:
+0:9          1 (const int)
+0:9        Constant:
+0:9          2 (const int)
+0:9        Constant:
+0:9          3 (const int)
+0:9        Constant:
+0:9          4 (const int)
+0:9        Constant:
+0:9          5 (const int)
+0:9        Constant:
+0:9          6 (const int)
+0:9        Constant:
+0:9          7 (const int)
+0:9        Constant:
+0:9          8 (const int)
+0:9        Constant:
+0:9          9 (const int)
+0:9        Constant:
+0:9          10 (const int)
+0:4  Function Definition: main( ( temp void)
+0:4    Function Parameters: 
+0:?     Sequence
+0:4      Function Call: @main( ( temp void)
+0:?   Linker Objects
+0:?     'first' ( const string)
+0:?       "first string"
+
+// Module Version 10000
+// Generated by (magic number): 8000a
+// Id's are bound by 36
+
+                              Capability Shader
+                              Extension  "SPV_KHR_non_semantic_info"
+               1:             ExtInstImport  "GLSL.std.450"
+               9:             ExtInstImport  "NonSemantic.DebugPrintf"
+                              MemoryModel Logical GLSL450
+                              EntryPoint GLCompute 4  "main"
+                              ExecutionMode 4 LocalSize 1 1 1
+               8:             String  "first string"
+              11:             String  "please print this message."
+              13:             String  "Variables are: %d %d %.2f"
+              20:             String  "Integers are: %d %d %d"
+              26:             String  "More: %d %d %d %d %d %d %d %d %d %d"
+                              Source HLSL 500
+                              Name 4  "main"
+                              Name 6  "@main("
+               2:             TypeVoid
+               3:             TypeFunction 2
+              14:             TypeInt 32 0
+              15:     14(int) Constant 1
+              16:     14(int) Constant 2
+              17:             TypeFloat 32
+              18:   17(float) Constant 1069547520
+              21:             TypeInt 32 1
+              22:     21(int) Constant 1
+              23:     21(int) Constant 2
+              24:     21(int) Constant 3
+              27:     21(int) Constant 4
+              28:     21(int) Constant 5
+              29:     21(int) Constant 6
+              30:     21(int) Constant 7
+              31:     21(int) Constant 8
+              32:     21(int) Constant 9
+              33:     21(int) Constant 10
+         4(main):           2 Function None 3
+               5:             Label
+              35:           2 FunctionCall 6(@main()
+                              Return
+                              FunctionEnd
+       6(@main():           2 Function None 3
+               7:             Label
+              10:           2 ExtInst 9(NonSemantic.DebugPrintf) 1(DebugPrintf) 8
+              12:           2 ExtInst 9(NonSemantic.DebugPrintf) 1(DebugPrintf) 11
+              19:           2 ExtInst 9(NonSemantic.DebugPrintf) 1(DebugPrintf) 13 15 16 18
+              25:           2 ExtInst 9(NonSemantic.DebugPrintf) 1(DebugPrintf) 20 22 23 24
+              34:           2 ExtInst 9(NonSemantic.DebugPrintf) 1(DebugPrintf) 26 22 23 24 27 28 29 30 31 32 33
+                              Return
+                              FunctionEnd
diff --git a/Test/hlsl.printf.comp b/Test/hlsl.printf.comp
new file mode 100644
index 0000000..d117299
--- /dev/null
+++ b/Test/hlsl.printf.comp
@@ -0,0 +1,11 @@
+const string first = "first string";

+

+[numthreads(1,1,1)]

+void main() {

+    printf(first);

+    printf("please print this message.");

+    printf("Variables are: %d %d %.2f", 1u, 2u, 1.5f);

+    printf("Integers are: %d %d %d", 1, 2, 3);

+    printf("More: %d %d %d %d %d %d %d %d %d %d", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

+}

+

diff --git a/glslang/HLSL/hlslGrammar.cpp b/glslang/HLSL/hlslGrammar.cpp
index 5bfc53f..f30c640 100644
--- a/glslang/HLSL/hlslGrammar.cpp
+++ b/glslang/HLSL/hlslGrammar.cpp
@@ -480,8 +480,9 @@
             }
 
             // TODO: things scoped within an annotation need their own name space;
-            // TODO: strings are not yet handled.
-            if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) {
+            // TODO: non-constant strings are not yet handled.
+            if (!(variableType.getBasicType() == EbtString && !variableType.getQualifier().isConstant()) &&
+                parseContext.getAnnotationNestingLevel() == 0) {
                 if (typedefDecl)
                     parseContext.declareTypedef(idToken.loc, *fullName, variableType);
                 else if (variableType.getBasicType() == EbtBlock) {
diff --git a/glslang/HLSL/hlslParseHelper.cpp b/glslang/HLSL/hlslParseHelper.cpp
index 3150eac..ea31837 100644
--- a/glslang/HLSL/hlslParseHelper.cpp
+++ b/glslang/HLSL/hlslParseHelper.cpp
@@ -7628,7 +7628,17 @@
     bool tie = false;
 
     // send to the generic selector
-    const TFunction* bestMatch = selectFunction(candidateList, call, convertible, better, tie);
+    const TFunction* bestMatch = nullptr;
+
+    // printf has var args and is in the symbol table as "printf()",
+    // mangled to "printf("
+    if (call.getName() == "printf") {
+        TSymbol* symbol = symbolTable.find("printf(", &builtIn);
+        if (symbol)
+            return symbol->getAsFunction();
+    }
+
+    bestMatch = selectFunction(candidateList, call, convertible, better, tie);
 
     if (bestMatch == nullptr) {
         // If there is nothing selected by allowing only up-conversions (to a larger linearize() value),
diff --git a/glslang/HLSL/hlslParseables.cpp b/glslang/HLSL/hlslParseables.cpp
index 61c820b..025cb5e 100644
--- a/glslang/HLSL/hlslParseables.cpp
+++ b/glslang/HLSL/hlslParseables.cpp
@@ -605,7 +605,7 @@
         { "noise",                            "S",     "F",       "V",              "F",             EShLangPS,     false },
         { "normalize",                        nullptr, nullptr,   "V",              "F",             EShLangAll,    false },
         { "pow",                              nullptr, nullptr,   "SVM,",           "F,",            EShLangAll,    false },
-        // { "printf",                           "-",     "-",       "",            "",              EShLangAll,    false }, TODO: varargs
+        { "printf",                           nullptr, nullptr,   "-",              "-",             EShLangAll,    false },
         { "Process2DQuadTessFactorsAvg",      "-",     "-",       "V4,V2,>V4,>V2,", "F,,,,",         EShLangHS,     false },
         { "Process2DQuadTessFactorsMax",      "-",     "-",       "V4,V2,>V4,>V2,", "F,,,,",         EShLangHS,     false },
         { "Process2DQuadTessFactorsMin",      "-",     "-",       "V4,V2,>V4,>V2,", "F,,,,",         EShLangHS,     false },
@@ -1107,7 +1107,7 @@
     // symbolTable.relateToOperator("noise",                    EOpNoise); // TODO: check return type
     symbolTable.relateToOperator("normalize",                   EOpNormalize);
     symbolTable.relateToOperator("pow",                         EOpPow);
-    // symbolTable.relateToOperator("printf",                     EOpPrintf);
+    symbolTable.relateToOperator("printf",                      EOpDebugPrintf);
     // symbolTable.relateToOperator("Process2DQuadTessFactorsAvg");
     // symbolTable.relateToOperator("Process2DQuadTessFactorsMax");
     // symbolTable.relateToOperator("Process2DQuadTessFactorsMin");
diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h
index 235ea3f..514fa10 100644
--- a/glslang/Include/Types.h
+++ b/glslang/Include/Types.h
@@ -1986,6 +1986,7 @@
         case EbtAccStruct:         return "accelerationStructureNV";
         case EbtRayQuery:          return "rayQueryEXT";
         case EbtReference:         return "reference";
+        case EbtString:            return "string";
 #endif
         default:                   return "unknown type";
         }
diff --git a/glslang/MachineIndependent/intermOut.cpp b/glslang/MachineIndependent/intermOut.cpp
index f23a705..0239e99 100644
--- a/glslang/MachineIndependent/intermOut.cpp
+++ b/glslang/MachineIndependent/intermOut.cpp
@@ -1321,6 +1321,9 @@
                 out.debug << buf << "\n";
             }
             break;
+        case EbtString:
+            out.debug << "\"" << constUnion[i].getSConst()->c_str() << "\"\n";
+            break;
         default:
             out.info.message(EPrefixInternalError, "Unknown constant", node->getLoc());
             break;
diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp
index 224ea59..4d1cb50 100644
--- a/gtests/Hlsl.FromFile.cpp
+++ b/gtests/Hlsl.FromFile.cpp
@@ -308,6 +308,7 @@
         {"hlsl.pp.vert", "main"},
         {"hlsl.pp.line.frag", "main"},
         {"hlsl.precise.frag", "main"},
+        {"hlsl.printf.comp", "main"},
         {"hlsl.promote.atomic.frag", "main"},
         {"hlsl.promote.binary.frag", "main"},
         {"hlsl.promote.vec1.frag", "main"},