浏览代码

[spirv] Emit names for struct and its members.

Ehsan Nasiri 6 年之前
父节点
当前提交
2482495bf1
共有 2 个文件被更改,包括 40 次插入5 次删除
  1. 12 3
      tools/clang/include/clang/SPIRV/EmitVisitor.h
  2. 28 2
      tools/clang/lib/SPIRV/EmitVisitor.cpp

+ 12 - 3
tools/clang/include/clang/SPIRV/EmitVisitor.h

@@ -42,11 +42,13 @@ struct SpirvLayoutRuleDenseMapInfo {
 class EmitTypeHandler {
 public:
   EmitTypeHandler(ASTContext &astCtx, SpirvBuilder &builder,
+                  std::vector<uint32_t> *debugVec,
                   std::vector<uint32_t> *decVec,
                   std::vector<uint32_t> *typesVec,
                   const std::function<uint32_t()> &takeNextIdFn)
-      : astContext(astCtx), spirvBuilder(builder), annotationsBinary(decVec),
-        typeConstantBinary(typesVec), takeNextIdFunction(takeNextIdFn) {
+      : astContext(astCtx), spirvBuilder(builder), debugBinary(debugVec),
+        annotationsBinary(decVec), typeConstantBinary(typesVec),
+        takeNextIdFunction(takeNextIdFn) {
     assert(decVec);
     assert(typesVec);
   }
@@ -86,6 +88,11 @@ private:
 
   void emitLayoutDecorations(const StructType *, SpirvLayoutRule);
 
+  // Emits an OpName (if memberIndex is not provided) or OpMemberName (if
+  // memberIndex is provided) for the given target result-id.
+  void emitNameForType(llvm::StringRef name, uint32_t targetTypeId,
+                       llvm::Optional<uint32_t> memberIndex = llvm::None);
+
   // There is no guarantee that an instruction or a function or a basic block
   // has been assigned result-id. This method returns the result-id for the
   // given object. If a result-id has not been assigned yet, it'll assign
@@ -112,6 +119,7 @@ private:
   SpirvBuilder &spirvBuilder;
   std::vector<uint32_t> curTypeInst;
   std::vector<uint32_t> curDecorationInst;
+  std::vector<uint32_t> *debugBinary;
   std::vector<uint32_t> *annotationsBinary;
   std::vector<uint32_t> *typeConstantBinary;
   std::function<uint32_t()> takeNextIdFunction;
@@ -146,7 +154,8 @@ public:
   EmitVisitor(ASTContext &astCtx, SpirvContext &spvCtx,
               const SpirvCodeGenOptions &opts, SpirvBuilder &builder)
       : Visitor(opts, spvCtx), id(0),
-        typeHandler(astCtx, builder, &annotationsBinary, &typeConstantBinary,
+        typeHandler(astCtx, builder, &debugBinary, &annotationsBinary,
+                    &typeConstantBinary,
                     [this]() -> uint32_t { return takeNextId(); }) {}
 
   // Visit different SPIR-V constructs for emitting.

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

@@ -1157,8 +1157,18 @@ uint32_t EmitTypeHandler::emitType(const SpirvType *type,
   }
   // Structure types
   else if (const auto *structType = dyn_cast<StructType>(type)) {
+    llvm::ArrayRef<StructType::FieldInfo> fields = structType->getFields();
+    size_t numFields = fields.size();
+
+    // Emit OpName for the struct.
+    emitNameForType(structType->getStructName(), id);
+
+    // Emit OpMemberName for the struct members.
+    for (size_t i = 0; i < numFields; ++i)
+      emitNameForType(fields[i].name, id, i);
+
     llvm::SmallVector<uint32_t, 4> fieldTypeIds;
-    for (auto &field : structType->getFields())
+    for (auto &field : fields)
       fieldTypeIds.push_back(emitType(field.type, rule));
     initTypeInstruction(spv::Op::OpTypeStruct);
     curTypeInst.push_back(id);
@@ -1171,7 +1181,7 @@ uint32_t EmitTypeHandler::emitType(const SpirvType *type,
 
     // Emit NonWritable decorations
     if (structType->isReadOnly())
-      for (size_t i = 0; i < structType->getFields().size(); ++i)
+      for (size_t i = 0; i < numFields; ++i)
         emitDecoration(id, spv::Decoration::NonWritable, {}, i);
 
     // Emit Block or BufferBlock decorations if necessary.
@@ -1611,5 +1621,21 @@ void EmitTypeHandler::emitDecoration(uint32_t typeResultId,
   curDecorationInst.clear();
 }
 
+void EmitTypeHandler::emitNameForType(llvm::StringRef name,
+                                      uint32_t targetTypeId,
+                                      llvm::Optional<uint32_t> memberIndex) {
+  std::vector<uint32_t> nameInstr;
+  auto op =
+      memberIndex.hasValue() ? spv::Op::OpMemberName : spv::Op::OpName;
+  nameInstr.push_back(static_cast<uint32_t>(op));
+  nameInstr.push_back(targetTypeId);
+  if (memberIndex.hasValue())
+    nameInstr.push_back(memberIndex.getValue());
+  const auto &words = string::encodeSPIRVString(name);
+  nameInstr.insert(nameInstr.end(), words.begin(), words.end());
+  nameInstr[0] |= static_cast<uint32_t>(nameInstr.size()) << 16;
+  debugBinary->insert(debugBinary->end(), nameInstr.begin(), nameInstr.end());
+}
+
 } // end namespace spirv
 } // end namespace clang