Merge pull request #2278 from ShabbyX/master

Add -g0 command line argument
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 24203a1..4800c51 100644
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -8738,10 +8738,14 @@
     // If from HLSL, run spirv-opt to "legalize" the SPIR-V for Vulkan
     // eg. forward and remove memory writes of opaque types.
     bool prelegalization = intermediate.getSource() == EShSourceHlsl;
-    if ((intermediate.getSource() == EShSourceHlsl || options->optimizeSize) && !options->disableOptimizer) {
-        SpirvToolsLegalize(intermediate, spirv, logger, options);
+    if ((prelegalization || options->optimizeSize) && !options->disableOptimizer) {
+        SpirvToolsTransform(intermediate, spirv, logger, options);
         prelegalization = false;
     }
+    else if (options->stripDebugInfo) {
+        // Strip debug info even if optimization is disabled.
+        SpirvToolsStripDebugInfo(intermediate, spirv, logger);
+    }
 
     if (options->validate)
         SpirvToolsValidate(intermediate, spirv, logger, prelegalization);
diff --git a/SPIRV/SpvTools.cpp b/SPIRV/SpvTools.cpp
index 1e968ba..6d4d9ef 100644
--- a/SPIRV/SpvTools.cpp
+++ b/SPIRV/SpvTools.cpp
@@ -80,6 +80,39 @@
     return spv_target_env::SPV_ENV_UNIVERSAL_1_0;
 }
 
+// Callback passed to spvtools::Optimizer::SetMessageConsumer
+void OptimizerMesssageConsumer(spv_message_level_t level, const char *source,
+        const spv_position_t &position, const char *message)
+{
+    auto &out = std::cerr;
+    switch (level)
+    {
+    case SPV_MSG_FATAL:
+    case SPV_MSG_INTERNAL_ERROR:
+    case SPV_MSG_ERROR:
+        out << "error: ";
+        break;
+    case SPV_MSG_WARNING:
+        out << "warning: ";
+        break;
+    case SPV_MSG_INFO:
+    case SPV_MSG_DEBUG:
+        out << "info: ";
+        break;
+    default:
+        break;
+    }
+    if (source)
+    {
+        out << source << ":";
+    }
+    out << position.line << ":" << position.column << ":" << position.index << ":";
+    if (message)
+    {
+        out << " " << message;
+    }
+    out << std::endl;
+}
 
 // Use the SPIRV-Tools disassembler to print SPIR-V.
 void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv)
@@ -128,45 +161,14 @@
     spvContextDestroy(context);
 }
 
-// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of
-// legalizing HLSL SPIR-V.
-void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
-                        spv::SpvBuildLogger* logger, const SpvOptions* options)
+// Apply the SPIRV-Tools optimizer to generated SPIR-V.  HLSL SPIR-V is legalized in the process.
+void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
+                         spv::SpvBuildLogger* logger, const SpvOptions* options)
 {
     spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
 
     spvtools::Optimizer optimizer(target_env);
-    optimizer.SetMessageConsumer(
-        [](spv_message_level_t level, const char *source, const spv_position_t &position, const char *message) {
-            auto &out = std::cerr;
-            switch (level)
-            {
-            case SPV_MSG_FATAL:
-            case SPV_MSG_INTERNAL_ERROR:
-            case SPV_MSG_ERROR:
-                out << "error: ";
-                break;
-            case SPV_MSG_WARNING:
-                out << "warning: ";
-                break;
-            case SPV_MSG_INFO:
-            case SPV_MSG_DEBUG:
-                out << "info: ";
-                break;
-            default:
-                break;
-            }
-            if (source)
-            {
-                out << source << ":";
-            }
-            out << position.line << ":" << position.column << ":" << position.index << ":";
-            if (message)
-            {
-                out << " " << message;
-            }
-            out << std::endl;
-        });
+    optimizer.SetMessageConsumer(OptimizerMesssageConsumer);
 
     // If debug (specifically source line info) is being generated, propagate
     // line information into all SPIR-V instructions. This avoids loss of
@@ -175,6 +177,9 @@
     if (options->generateDebugInfo) {
         optimizer.RegisterPass(spvtools::CreatePropagateLineInfoPass());
     }
+    else if (options->stripDebugInfo) {
+        optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());
+    }
     optimizer.RegisterPass(spvtools::CreateWrapOpKillPass());
     optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass());
     optimizer.RegisterPass(spvtools::CreateMergeReturnPass());
@@ -212,6 +217,25 @@
     optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
 }
 
+// Apply the SPIRV-Tools optimizer to strip debug info from SPIR-V.  This is implicitly done by
+// SpirvToolsTransform if spvOptions->stripDebugInfo is set, but can be called separately if
+// optimization is disabled.
+void SpirvToolsStripDebugInfo(const glslang::TIntermediate& intermediate,
+        std::vector<unsigned int>& spirv, spv::SpvBuildLogger* logger)
+{
+    spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
+
+    spvtools::Optimizer optimizer(target_env);
+    optimizer.SetMessageConsumer(OptimizerMesssageConsumer);
+
+    optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());
+
+    spvtools::OptimizerOptions spvOptOptions;
+    optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
+    spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on
+    optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
+}
+
 }; // end namespace glslang
 
 #endif
diff --git a/SPIRV/SpvTools.h b/SPIRV/SpvTools.h
index 59c914d..7779dfa 100644
--- a/SPIRV/SpvTools.h
+++ b/SPIRV/SpvTools.h
@@ -52,9 +52,10 @@
 namespace glslang {
 
 struct SpvOptions {
-    SpvOptions() : generateDebugInfo(false), disableOptimizer(true),
+    SpvOptions() : generateDebugInfo(false), stripDebugInfo(false), disableOptimizer(true),
         optimizeSize(false), disassemble(false), validate(false) { }
     bool generateDebugInfo;
+    bool stripDebugInfo;
     bool disableOptimizer;
     bool optimizeSize;
     bool disassemble;
@@ -70,10 +71,15 @@
 void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
                         spv::SpvBuildLogger*, bool prelegalization);
 
-// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of
-// legalizing HLSL SPIR-V.
-void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
-                        spv::SpvBuildLogger*, const SpvOptions*);
+// Apply the SPIRV-Tools optimizer to generated SPIR-V.  HLSL SPIR-V is legalized in the process.
+void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
+                         spv::SpvBuildLogger*, const SpvOptions*);
+
+// Apply the SPIRV-Tools optimizer to strip debug info from SPIR-V.  This is implicitly done by
+// SpirvToolsTransform if spvOptions->stripDebugInfo is set, but can be called separately if
+// optimization is disabled.
+void SpirvToolsStripDebugInfo(const glslang::TIntermediate& intermediate,
+        std::vector<unsigned int>& spirv, spv::SpvBuildLogger*);
 
 #endif
 
diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp
index ab8d904..5e17aff 100644
--- a/StandAlone/StandAlone.cpp
+++ b/StandAlone/StandAlone.cpp
@@ -106,6 +106,7 @@
 bool SpvToolsDisassembler = false;
 bool SpvToolsValidate = false;
 bool NaNClamp = false;
+bool stripDebugInfo = false;
 
 //
 // Return codes from main/exit().
@@ -750,7 +751,13 @@
                     Error("-f: expected hlsl_functionality1");
                 break;
             case 'g':
-                Options |= EOptionDebug;
+                // Override previous -g or -g0 argument
+                stripDebugInfo = false;
+                Options &= ~EOptionDebug;
+                if (argv[0][2] == '0')
+                    stripDebugInfo = true;
+                else
+                    Options |= EOptionDebug;
                 break;
             case 'h':
                 usage();
@@ -1150,6 +1157,8 @@
                     glslang::SpvOptions spvOptions;
                     if (Options & EOptionDebug)
                         spvOptions.generateDebugInfo = true;
+                    else if (stripDebugInfo)
+                        spvOptions.stripDebugInfo = true;
                     spvOptions.disableOptimizer = (Options & EOptionOptimizeDisable) != 0;
                     spvOptions.optimizeSize = (Options & EOptionOptimizeSize) != 0;
                     spvOptions.disassemble = SpvToolsDisassembler;
@@ -1568,6 +1577,7 @@
            "              'hlsl_functionality1' enables use of the\n"
            "              SPV_GOOGLE_hlsl_functionality1 extension\n"
            "  -g          generate debug information\n"
+           "  -g0         strip debug information\n"
            "  -h          print this usage message\n"
            "  -i          intermediate tree (glslang AST) is printed out\n"
            "  -l          link all input files together to form a single module\n"