Prechádzať zdrojové kódy

[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 rokov pred
rodič
commit
732f05c0ab

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

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

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

@@ -415,6 +415,8 @@ public:
                                       SpirvInstruction *structure,
                                       uint32_t arrayMember);
 
+  void createLineInfo(SpirvString *file, uint32_t line, uint32_t column);
+
   // === SPIR-V Module Structure ===
 
   inline void requireCapability(spv::Capability, SourceLocation loc = {});
@@ -429,9 +431,10 @@ public:
                             SourceLocation loc = {});
 
   /// \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.
   inline void addExecutionMode(SpirvFunction *entryPoint, spv::ExecutionMode em,
@@ -442,6 +445,10 @@ public:
   /// the given target at the given source location.
   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
   /// instruction set) of the GLSL instruction set. Returns the  the imported
   /// GLSL instruction set.
@@ -699,9 +706,9 @@ void SpirvBuilder::addEntryPoint(spv::ExecutionModel em, SpirvFunction *target,
       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;
 
   SpirvString *fileString =
@@ -713,6 +720,8 @@ void SpirvBuilder::setDebugSource(uint32_t major, uint32_t minor,
                   fileString, content);
 
   module->addDebugSource(debugSource);
+
+  return fileString;
 }
 
 void SpirvBuilder::addExecutionMode(SpirvFunction *entryPoint,

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

@@ -27,6 +27,7 @@ class SpirvBasicBlock;
 class SpirvFunction;
 class SpirvType;
 class SpirvVariable;
+class SpirvString;
 class Visitor;
 
 /// \brief The base class for representing SPIR-V instructions.
@@ -46,6 +47,7 @@ public:
     IK_Source,          // OpSource (debug)
     IK_Name,            // Op*Name (debug)
     IK_ModuleProcessed, // OpModuleProcessed (debug)
+    IK_LineInfo,        // OpLine (debug)
     IK_Decoration,      // Op*Decorate
     IK_Type,            // OpType*
     IK_Variable,        // OpVariable
@@ -1766,6 +1768,26 @@ private:
   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
 

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

@@ -88,6 +88,9 @@ public:
   // Adds the debug source to the module.
   void addDebugSource(SpirvSource *);
 
+  // Adds the given OpModuleProcessed to the module.
+  void addModuleProcessed(SpirvModuleProcessed *);
+
 private:
   // "Metadata" instructions
   llvm::SmallVector<SpirvCapability *, 8> capabilities;
@@ -97,6 +100,7 @@ private:
   llvm::SmallVector<SpirvEntryPoint *, 1> entryPoints;
   llvm::SmallVector<SpirvExecutionMode *, 4> executionModes;
   SpirvSource *debugSource;
+  std::vector<SpirvModuleProcessed *> moduleProcesses;
   std::vector<SpirvDecoration *> decorations;
   std::vector<SpirvConstant *> constants;
   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(SpirvSource)
   DEFINE_VISIT_METHOD(SpirvModuleProcessed)
+  DEFINE_VISIT_METHOD(SpirvLineInfo)
   DEFINE_VISIT_METHOD(SpirvDecoration)
   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) {
+  // Emit the result type if the instruction has a result type.
   if (inst->hasResultType()) {
     const uint32_t resultTypeId =
         typeHandler.emitType(inst->getResultType(), inst->getLayoutRule());
     inst->setResultTypeId(resultTypeId);
   }
+
+  // Initialize the current instruction for emitting.
   curInst.clear();
   curInst.push_back(static_cast<uint32_t>(inst->getopcode()));
 }
@@ -178,9 +181,9 @@ void EmitVisitor::finalizeInstruction() {
   case spv::Op::OpSourceContinued:
   case spv::Op::OpName:
   case spv::Op::OpMemberName:
-  case spv::Op::OpModuleProcessed:
     debugBinary.insert(debugBinary.end(), curInst.begin(), curInst.end());
     break;
+  case spv::Op::OpModuleProcessed:
   case spv::Op::OpDecorate:
   case spv::Op::OpDecorateId:
   case spv::Op::OpMemberDecorate:
@@ -401,6 +404,24 @@ bool EmitVisitor::visit(SpirvModuleProcessed *inst) {
   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) {
   initInstruction(inst);
   curInst.push_back(getOrAssignResultId<SpirvInstruction>(inst->getTarget()));
@@ -1714,7 +1735,6 @@ void EmitTypeHandler::getLayoutDecorations(const StructType *structType,
                 DecorationInfo(spv::Decoration::ColMajor, {}, index));
           }
         }
-
       }
     }
 

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

@@ -20,6 +20,15 @@
 
 #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 spirv {
 
@@ -539,10 +548,10 @@ SPIRVEmitter::SPIRVEmitter(CompilerInstance &ci)
       typeTranslator(astContext, theBuilder, diags, spirvOptions),
       declIdMapper(shaderModel, astContext, spvContext, spvBuilder, *this,
                    featureManager, spirvOptions),
-      entryFunction(nullptr), curFunction(nullptr), curThis(0),
+      entryFunction(nullptr), curFunction(nullptr), curThis(nullptr),
       seenPushConstantAt(), isSpecConstantMode(false),
       foundNonUniformResourceIndex(false), needsLegalization(false),
-      mainSourceFileId(0) {
+      mainSourceFile(nullptr) {
   if (shaderModel.GetKind() == hlsl::ShaderModel::Kind::Invalid)
     emitError("unknown shader module: %0", {}) << shaderModel.GetName();
 
@@ -588,8 +597,23 @@ SPIRVEmitter::SPIRVEmitter(CompilerInstance &ci)
         sm.getBuffer(sm.getMainFileID(), SourceLocation());
     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) {
@@ -3913,7 +3937,7 @@ SPIRVEmitter::processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
     return nullptr;
   }
 
-  if(retVal)
+  if (retVal)
     retVal->setRValue();
   return retVal;
 }
@@ -9900,10 +9924,11 @@ SpirvInstruction *SPIRVEmitter::extractVecFromVec4(SpirvInstruction *from,
 }
 
 void SPIRVEmitter::emitDebugLine(SourceLocation loc) {
-  if (spirvOptions.debugInfoLine && mainSourceFileId != 0) {
+  if (spirvOptions.debugInfoLine && mainSourceFile != nullptr) {
     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;
 
   /// The <result-id> of the OpString containing the main source file's path.
-  uint32_t mainSourceFileId;
+  SpirvString *mainSourceFile;
 };
 
 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;
 }
 
+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,
                                 SourceLocation loc) {
   // 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 *glslSet = module->getGLSLExtInstSet();
   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(SpirvSource)
 DEFINE_INVOKE_VISITOR_FOR_CLASS(SpirvModuleProcessed)
+DEFINE_INVOKE_VISITOR_FOR_CLASS(SpirvLineInfo)
 DEFINE_INVOKE_VISITOR_FOR_CLASS(SpirvDecoration)
 DEFINE_INVOKE_VISITOR_FOR_CLASS(SpirvVariable)
 
@@ -155,6 +156,11 @@ SpirvModuleProcessed::SpirvModuleProcessed(SourceLocation loc,
                        /*resultId=*/0, loc),
       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,
                                  SpirvInstruction *targetInst,
                                  spv::Decoration decor,

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

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