Browse Source

[spirv] Add debug info to the v1 level.

There are better things we can do with v2, such as having more OpLine
instructions. The infrastructure for that is in place. This change is
just to bring things back to the v1 working level. We can add better
debugging features on top later
Ehsan Nasiri 6 years ago
parent
commit
732f05c0ab

+ 1 - 0
tools/clang/include/clang/SPIRV/EmitVisitor.h

@@ -247,6 +247,7 @@ public:
   bool visit(SpirvString *);
   bool visit(SpirvString *);
   bool visit(SpirvSource *);
   bool visit(SpirvSource *);
   bool visit(SpirvModuleProcessed *);
   bool visit(SpirvModuleProcessed *);
+  bool visit(SpirvLineInfo *);
   bool visit(SpirvDecoration *);
   bool visit(SpirvDecoration *);
   bool visit(SpirvVariable *);
   bool visit(SpirvVariable *);
   bool visit(SpirvFunctionParameter *);
   bool visit(SpirvFunctionParameter *);

+ 15 - 6
tools/clang/include/clang/SPIRV/SpirvBuilder.h

@@ -415,6 +415,8 @@ public:
                                       SpirvInstruction *structure,
                                       SpirvInstruction *structure,
                                       uint32_t arrayMember);
                                       uint32_t arrayMember);
 
 
+  void createLineInfo(SpirvString *file, uint32_t line, uint32_t column);
+
   // === SPIR-V Module Structure ===
   // === SPIR-V Module Structure ===
 
 
   inline void requireCapability(spv::Capability, SourceLocation loc = {});
   inline void requireCapability(spv::Capability, SourceLocation loc = {});
@@ -429,9 +431,10 @@ public:
                             SourceLocation loc = {});
                             SourceLocation loc = {});
 
 
   /// \brief Sets the shader model version, source file name, and source file
   /// \brief Sets the shader model version, source file name, and source file
-  /// content.
-  inline void setDebugSource(uint32_t major, uint32_t minor,
-                             llvm::StringRef name, llvm::StringRef content);
+  /// content. Returns the SpirvString instruction of the file name.
+  inline SpirvString *setDebugSource(uint32_t major, uint32_t minor,
+                                     llvm::StringRef name,
+                                     llvm::StringRef content);
 
 
   /// \brief Adds an execution mode to the module under construction.
   /// \brief Adds an execution mode to the module under construction.
   inline void addExecutionMode(SpirvFunction *entryPoint, spv::ExecutionMode em,
   inline void addExecutionMode(SpirvFunction *entryPoint, spv::ExecutionMode em,
@@ -442,6 +445,10 @@ public:
   /// the given target at the given source location.
   /// the given target at the given source location.
   void addExtension(Extension, llvm::StringRef target, SourceLocation);
   void addExtension(Extension, llvm::StringRef target, SourceLocation);
 
 
+  /// \brief Adds an OpModuleProcessed instruction to the module under
+  /// construction.
+  void addModuleProcessed(llvm::StringRef process);
+
   /// \brief If not added already, adds an OpExtInstImport (import of extended
   /// \brief If not added already, adds an OpExtInstImport (import of extended
   /// instruction set) of the GLSL instruction set. Returns the  the imported
   /// instruction set) of the GLSL instruction set. Returns the  the imported
   /// GLSL instruction set.
   /// GLSL instruction set.
@@ -699,9 +706,9 @@ void SpirvBuilder::addEntryPoint(spv::ExecutionModel em, SpirvFunction *target,
       new (context) SpirvEntryPoint(loc, em, target, targetName, interfaces));
       new (context) SpirvEntryPoint(loc, em, target, targetName, interfaces));
 }
 }
 
 
-void SpirvBuilder::setDebugSource(uint32_t major, uint32_t minor,
-                                  llvm::StringRef name,
-                                  llvm::StringRef content) {
+SpirvString *SpirvBuilder::setDebugSource(uint32_t major, uint32_t minor,
+                                          llvm::StringRef name,
+                                          llvm::StringRef content) {
   uint32_t version = 100 * major + 10 * minor;
   uint32_t version = 100 * major + 10 * minor;
 
 
   SpirvString *fileString =
   SpirvString *fileString =
@@ -713,6 +720,8 @@ void SpirvBuilder::setDebugSource(uint32_t major, uint32_t minor,
                   fileString, content);
                   fileString, content);
 
 
   module->addDebugSource(debugSource);
   module->addDebugSource(debugSource);
+
+  return fileString;
 }
 }
 
 
 void SpirvBuilder::addExecutionMode(SpirvFunction *entryPoint,
 void SpirvBuilder::addExecutionMode(SpirvFunction *entryPoint,

+ 22 - 0
tools/clang/include/clang/SPIRV/SpirvInstruction.h

@@ -27,6 +27,7 @@ class SpirvBasicBlock;
 class SpirvFunction;
 class SpirvFunction;
 class SpirvType;
 class SpirvType;
 class SpirvVariable;
 class SpirvVariable;
+class SpirvString;
 class Visitor;
 class Visitor;
 
 
 /// \brief The base class for representing SPIR-V instructions.
 /// \brief The base class for representing SPIR-V instructions.
@@ -46,6 +47,7 @@ public:
     IK_Source,          // OpSource (debug)
     IK_Source,          // OpSource (debug)
     IK_Name,            // Op*Name (debug)
     IK_Name,            // Op*Name (debug)
     IK_ModuleProcessed, // OpModuleProcessed (debug)
     IK_ModuleProcessed, // OpModuleProcessed (debug)
+    IK_LineInfo,        // OpLine (debug)
     IK_Decoration,      // Op*Decorate
     IK_Decoration,      // Op*Decorate
     IK_Type,            // OpType*
     IK_Type,            // OpType*
     IK_Variable,        // OpVariable
     IK_Variable,        // OpVariable
@@ -1766,6 +1768,26 @@ private:
   uint32_t arrayMember;
   uint32_t arrayMember;
 };
 };
 
 
+class SpirvLineInfo : public SpirvInstruction {
+public:
+  SpirvLineInfo(SpirvString *srcFile, uint32_t srcLine, uint32_t srcCol);
+
+  // For LLVM-style RTTI
+  static bool classof(const SpirvInstruction *inst) {
+    return inst->getKind() == IK_LineInfo;
+  }
+
+  DECLARE_INVOKE_VISITOR_FOR_CLASS(SpirvLineInfo)
+
+  SpirvString *getSourceFile() { return file; }
+  uint32_t getSourceLine() { return line; }
+  uint32_t getSourceColumn() { return column; }
+
+private:
+  SpirvString *file;
+  uint32_t line;
+  uint32_t column;
+};
 
 
 #undef DECLARE_INVOKE_VISITOR_FOR_CLASS
 #undef DECLARE_INVOKE_VISITOR_FOR_CLASS
 
 

+ 4 - 0
tools/clang/include/clang/SPIRV/SpirvModule.h

@@ -88,6 +88,9 @@ public:
   // Adds the debug source to the module.
   // Adds the debug source to the module.
   void addDebugSource(SpirvSource *);
   void addDebugSource(SpirvSource *);
 
 
+  // Adds the given OpModuleProcessed to the module.
+  void addModuleProcessed(SpirvModuleProcessed *);
+
 private:
 private:
   // "Metadata" instructions
   // "Metadata" instructions
   llvm::SmallVector<SpirvCapability *, 8> capabilities;
   llvm::SmallVector<SpirvCapability *, 8> capabilities;
@@ -97,6 +100,7 @@ private:
   llvm::SmallVector<SpirvEntryPoint *, 1> entryPoints;
   llvm::SmallVector<SpirvEntryPoint *, 1> entryPoints;
   llvm::SmallVector<SpirvExecutionMode *, 4> executionModes;
   llvm::SmallVector<SpirvExecutionMode *, 4> executionModes;
   SpirvSource *debugSource;
   SpirvSource *debugSource;
+  std::vector<SpirvModuleProcessed *> moduleProcesses;
   std::vector<SpirvDecoration *> decorations;
   std::vector<SpirvDecoration *> decorations;
   std::vector<SpirvConstant *> constants;
   std::vector<SpirvConstant *> constants;
   std::vector<SpirvVariable *> variables;
   std::vector<SpirvVariable *> variables;

+ 1 - 0
tools/clang/include/clang/SPIRV/SpirvVisitor.h

@@ -64,6 +64,7 @@ public:
   DEFINE_VISIT_METHOD(SpirvString)
   DEFINE_VISIT_METHOD(SpirvString)
   DEFINE_VISIT_METHOD(SpirvSource)
   DEFINE_VISIT_METHOD(SpirvSource)
   DEFINE_VISIT_METHOD(SpirvModuleProcessed)
   DEFINE_VISIT_METHOD(SpirvModuleProcessed)
+  DEFINE_VISIT_METHOD(SpirvLineInfo)
   DEFINE_VISIT_METHOD(SpirvDecoration)
   DEFINE_VISIT_METHOD(SpirvDecoration)
   DEFINE_VISIT_METHOD(SpirvVariable)
   DEFINE_VISIT_METHOD(SpirvVariable)
 
 

+ 22 - 2
tools/clang/lib/SPIRV/EmitVisitor.cpp

@@ -145,11 +145,14 @@ void EmitVisitor::emitDebugNameForInstruction(uint32_t resultId,
 }
 }
 
 
 void EmitVisitor::initInstruction(SpirvInstruction *inst) {
 void EmitVisitor::initInstruction(SpirvInstruction *inst) {
+  // Emit the result type if the instruction has a result type.
   if (inst->hasResultType()) {
   if (inst->hasResultType()) {
     const uint32_t resultTypeId =
     const uint32_t resultTypeId =
         typeHandler.emitType(inst->getResultType(), inst->getLayoutRule());
         typeHandler.emitType(inst->getResultType(), inst->getLayoutRule());
     inst->setResultTypeId(resultTypeId);
     inst->setResultTypeId(resultTypeId);
   }
   }
+
+  // Initialize the current instruction for emitting.
   curInst.clear();
   curInst.clear();
   curInst.push_back(static_cast<uint32_t>(inst->getopcode()));
   curInst.push_back(static_cast<uint32_t>(inst->getopcode()));
 }
 }
@@ -178,9 +181,9 @@ void EmitVisitor::finalizeInstruction() {
   case spv::Op::OpSourceContinued:
   case spv::Op::OpSourceContinued:
   case spv::Op::OpName:
   case spv::Op::OpName:
   case spv::Op::OpMemberName:
   case spv::Op::OpMemberName:
-  case spv::Op::OpModuleProcessed:
     debugBinary.insert(debugBinary.end(), curInst.begin(), curInst.end());
     debugBinary.insert(debugBinary.end(), curInst.begin(), curInst.end());
     break;
     break;
+  case spv::Op::OpModuleProcessed:
   case spv::Op::OpDecorate:
   case spv::Op::OpDecorate:
   case spv::Op::OpDecorateId:
   case spv::Op::OpDecorateId:
   case spv::Op::OpMemberDecorate:
   case spv::Op::OpMemberDecorate:
@@ -401,6 +404,24 @@ bool EmitVisitor::visit(SpirvModuleProcessed *inst) {
   return true;
   return true;
 }
 }
 
 
+bool EmitVisitor::visit(SpirvLineInfo *inst) {
+  if (!spvOptions.debugInfoLine)
+    return true;
+
+  SpirvString *file = inst->getSourceFile();
+  uint32_t line = inst->getSourceLine();
+  uint32_t column = inst->getSourceColumn();
+  if (!file || line == 0 || column == 0)
+    return true;
+
+  initInstruction(inst);
+  curInst.push_back(getOrAssignResultId<SpirvInstruction>(file));
+  curInst.push_back(line);
+  curInst.push_back(column);
+  finalizeInstruction();
+  return true;
+}
+
 bool EmitVisitor::visit(SpirvDecoration *inst) {
 bool EmitVisitor::visit(SpirvDecoration *inst) {
   initInstruction(inst);
   initInstruction(inst);
   curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getTarget()));
   curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getTarget()));
@@ -1714,7 +1735,6 @@ void EmitTypeHandler::getLayoutDecorations(const StructType *structType,
                 DecorationInfo(spv::Decoration::ColMajor, {}, index));
                 DecorationInfo(spv::Decoration::ColMajor, {}, index));
           }
           }
         }
         }
-
       }
       }
     }
     }
 
 

+ 33 - 8
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -20,6 +20,15 @@
 
 
 #include "InitListHandler.h"
 #include "InitListHandler.h"
 
 
+#ifdef SUPPORT_QUERY_GIT_COMMIT_INFO
+#include "clang/Basic/Version.h"
+#else
+namespace clang {
+uint32_t getGitCommitCount() { return 0; }
+const char *getGitCommitHash() { return "<unknown-hash>"; }
+} // namespace clang
+#endif // SUPPORT_QUERY_GIT_COMMIT_INFO
+
 namespace clang {
 namespace clang {
 namespace spirv {
 namespace spirv {
 
 
@@ -539,10 +548,10 @@ SPIRVEmitter::SPIRVEmitter(CompilerInstance &ci)
       typeTranslator(astContext, theBuilder, diags, spirvOptions),
       typeTranslator(astContext, theBuilder, diags, spirvOptions),
       declIdMapper(shaderModel, astContext, spvContext, spvBuilder, *this,
       declIdMapper(shaderModel, astContext, spvContext, spvBuilder, *this,
                    featureManager, spirvOptions),
                    featureManager, spirvOptions),
-      entryFunction(nullptr), curFunction(nullptr), curThis(0),
+      entryFunction(nullptr), curFunction(nullptr), curThis(nullptr),
       seenPushConstantAt(), isSpecConstantMode(false),
       seenPushConstantAt(), isSpecConstantMode(false),
       foundNonUniformResourceIndex(false), needsLegalization(false),
       foundNonUniformResourceIndex(false), needsLegalization(false),
-      mainSourceFileId(0) {
+      mainSourceFile(nullptr) {
   if (shaderModel.GetKind() == hlsl::ShaderModel::Kind::Invalid)
   if (shaderModel.GetKind() == hlsl::ShaderModel::Kind::Invalid)
     emitError("unknown shader module: %0", {}) << shaderModel.GetName();
     emitError("unknown shader module: %0", {}) << shaderModel.GetName();
 
 
@@ -588,8 +597,23 @@ SPIRVEmitter::SPIRVEmitter(CompilerInstance &ci)
         sm.getBuffer(sm.getMainFileID(), SourceLocation());
         sm.getBuffer(sm.getMainFileID(), SourceLocation());
     source = StringRef(mainFile->getBufferStart(), mainFile->getBufferSize());
     source = StringRef(mainFile->getBufferStart(), mainFile->getBufferSize());
   }
   }
-  spvBuilder.setDebugSource(shaderModel.GetMajor(), shaderModel.GetMinor(),
-                            fileName, source);
+  mainSourceFile = spvBuilder.setDebugSource(
+      shaderModel.GetMajor(), shaderModel.GetMinor(), fileName, source);
+
+  if (spirvOptions.debugInfoTool && spirvOptions.targetEnv == "vulkan1.1") {
+    // Emit OpModuleProcessed to indicate the commit information.
+    std::string commitHash =
+        std::string("dxc-commit-hash: ") + clang::getGitCommitHash();
+    spvBuilder.addModuleProcessed(commitHash);
+
+    // Emit OpModuleProcessed to indicate the command line options that were
+    // used to generate this module.
+    if (!spirvOptions.clOptions.empty()) {
+      // Using this format: "dxc-cl-option: XXXXXX"
+      std::string clOptionStr = "dxc-cl-option:" + spirvOptions.clOptions;
+      spvBuilder.addModuleProcessed(clOptionStr);
+    }
+  }
 }
 }
 
 
 void SPIRVEmitter::HandleTranslationUnit(ASTContext &context) {
 void SPIRVEmitter::HandleTranslationUnit(ASTContext &context) {
@@ -3913,7 +3937,7 @@ SPIRVEmitter::processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
     return nullptr;
     return nullptr;
   }
   }
 
 
-  if(retVal)
+  if (retVal)
     retVal->setRValue();
     retVal->setRValue();
   return retVal;
   return retVal;
 }
 }
@@ -9900,10 +9924,11 @@ SpirvInstruction *SPIRVEmitter::extractVecFromVec4(SpirvInstruction *from,
 }
 }
 
 
 void SPIRVEmitter::emitDebugLine(SourceLocation loc) {
 void SPIRVEmitter::emitDebugLine(SourceLocation loc) {
-  if (spirvOptions.debugInfoLine && mainSourceFileId != 0) {
+  if (spirvOptions.debugInfoLine && mainSourceFile != nullptr) {
     auto floc = FullSourceLoc(loc, theCompilerInstance.getSourceManager());
     auto floc = FullSourceLoc(loc, theCompilerInstance.getSourceManager());
-    theBuilder.debugLine(mainSourceFileId, floc.getSpellingLineNumber(),
-                         floc.getSpellingColumnNumber());
+    uint32_t line = floc.getSpellingLineNumber();
+    uint32_t column = floc.getSpellingColumnNumber();
+    spvBuilder.createLineInfo(mainSourceFile, line, column);
   }
   }
 }
 }
 
 

+ 1 - 1
tools/clang/lib/SPIRV/SPIRVEmitter.h

@@ -1063,7 +1063,7 @@ private:
   FunctionDecl *patchConstFunc;
   FunctionDecl *patchConstFunc;
 
 
   /// The <result-id> of the OpString containing the main source file's path.
   /// The <result-id> of the OpString containing the main source file's path.
-  uint32_t mainSourceFileId;
+  SpirvString *mainSourceFile;
 };
 };
 
 
 void SPIRVEmitter::doDeclStmt(const DeclStmt *declStmt) {
 void SPIRVEmitter::doDeclStmt(const DeclStmt *declStmt) {

+ 11 - 0
tools/clang/lib/SPIRV/SpirvBuilder.cpp

@@ -765,6 +765,13 @@ SpirvArrayLength *SpirvBuilder::createArrayLength(QualType resultType,
   return inst;
   return inst;
 }
 }
 
 
+void SpirvBuilder::createLineInfo(SpirvString *file, uint32_t line,
+                                  uint32_t column) {
+  assert(insertPoint && "null insert point");
+  auto *inst = new (context) SpirvLineInfo(file, line, column);
+  insertPoint->addInstruction(inst);
+}
+
 void SpirvBuilder::addExtension(Extension ext, llvm::StringRef target,
 void SpirvBuilder::addExtension(Extension ext, llvm::StringRef target,
                                 SourceLocation loc) {
                                 SourceLocation loc) {
   // TODO: The extension management should be removed from here and added as a
   // TODO: The extension management should be removed from here and added as a
@@ -781,6 +788,10 @@ void SpirvBuilder::addExtension(Extension ext, llvm::StringRef target,
   }
   }
 }
 }
 
 
+void SpirvBuilder::addModuleProcessed(llvm::StringRef process) {
+  module->addModuleProcessed(new (context) SpirvModuleProcessed({}, process));
+}
+
 SpirvExtInstImport *SpirvBuilder::getGLSLExtInstSet(SourceLocation loc) {
 SpirvExtInstImport *SpirvBuilder::getGLSLExtInstSet(SourceLocation loc) {
   SpirvExtInstImport *glslSet = module->getGLSLExtInstSet();
   SpirvExtInstImport *glslSet = module->getGLSLExtInstSet();
   if (!glslSet) {
   if (!glslSet) {

+ 6 - 0
tools/clang/lib/SPIRV/SpirvInstruction.cpp

@@ -33,6 +33,7 @@ DEFINE_INVOKE_VISITOR_FOR_CLASS(SpirvExecutionMode)
 DEFINE_INVOKE_VISITOR_FOR_CLASS(SpirvString)
 DEFINE_INVOKE_VISITOR_FOR_CLASS(SpirvString)
 DEFINE_INVOKE_VISITOR_FOR_CLASS(SpirvSource)
 DEFINE_INVOKE_VISITOR_FOR_CLASS(SpirvSource)
 DEFINE_INVOKE_VISITOR_FOR_CLASS(SpirvModuleProcessed)
 DEFINE_INVOKE_VISITOR_FOR_CLASS(SpirvModuleProcessed)
+DEFINE_INVOKE_VISITOR_FOR_CLASS(SpirvLineInfo)
 DEFINE_INVOKE_VISITOR_FOR_CLASS(SpirvDecoration)
 DEFINE_INVOKE_VISITOR_FOR_CLASS(SpirvDecoration)
 DEFINE_INVOKE_VISITOR_FOR_CLASS(SpirvVariable)
 DEFINE_INVOKE_VISITOR_FOR_CLASS(SpirvVariable)
 
 
@@ -155,6 +156,11 @@ SpirvModuleProcessed::SpirvModuleProcessed(SourceLocation loc,
                        /*resultId=*/0, loc),
                        /*resultId=*/0, loc),
       process(processStr) {}
       process(processStr) {}
 
 
+SpirvLineInfo::SpirvLineInfo(SpirvString *srcFile, uint32_t srcLine,
+                             uint32_t srcCol)
+    : SpirvInstruction(IK_LineInfo, spv::Op::OpLine, QualType(), 0, {}),
+      file(srcFile), line(srcLine), column(srcCol) {}
+
 SpirvDecoration::SpirvDecoration(SourceLocation loc,
 SpirvDecoration::SpirvDecoration(SourceLocation loc,
                                  SpirvInstruction *targetInst,
                                  SpirvInstruction *targetInst,
                                  spv::Decoration decor,
                                  spv::Decoration decor,

+ 11 - 1
tools/clang/lib/SPIRV/SpirvModule.cpp

@@ -16,7 +16,8 @@ namespace spirv {
 SpirvModule::SpirvModule()
 SpirvModule::SpirvModule()
     : capabilities({}), extensions({}), extInstSets({}), memoryModel(nullptr),
     : capabilities({}), extensions({}), extInstSets({}), memoryModel(nullptr),
       entryPoints({}), executionModes({}), debugSource(nullptr),
       entryPoints({}), executionModes({}), debugSource(nullptr),
-      decorations({}), constants({}), variables({}), functions({}) {}
+      moduleProcesses({}), decorations({}), constants({}), variables({}),
+      functions({}) {}
 
 
 bool SpirvModule::invokeVisitor(Visitor *visitor) {
 bool SpirvModule::invokeVisitor(Visitor *visitor) {
   if (!visitor->visit(this, Visitor::Phase::Init))
   if (!visitor->visit(this, Visitor::Phase::Init))
@@ -49,6 +50,10 @@ bool SpirvModule::invokeVisitor(Visitor *visitor) {
     if (!debugSource->invokeVisitor(visitor))
     if (!debugSource->invokeVisitor(visitor))
       return false;
       return false;
 
 
+  for (auto moduleProcess : moduleProcesses)
+    if (!moduleProcess->invokeVisitor(visitor))
+      return false;
+
   for (auto decoration : decorations)
   for (auto decoration : decorations)
     if (!decoration->invokeVisitor(visitor))
     if (!decoration->invokeVisitor(visitor))
       return false;
       return false;
@@ -140,5 +145,10 @@ void SpirvModule::addDebugSource(SpirvSource *src) {
   debugSource = src;
   debugSource = src;
 }
 }
 
 
+void SpirvModule::addModuleProcessed(SpirvModuleProcessed *p) {
+  assert(p);
+  moduleProcesses.push_back(p);
+}
+
 } // end namespace spirv
 } // end namespace spirv
 } // end namespace clang
 } // end namespace clang