[Mlir-commits] [mlir] 29b955f - [mlir][spirv] Handle debug information during (de)serialization.
Denis Khalikov
llvmlistbot at llvm.org
Fri May 1 04:13:32 PDT 2020
Author: Denis Khalikov
Date: 2020-05-01T14:11:54+03:00
New Revision: 29b955f97cc6a4b96aba0ccdc033884c51ef466f
URL: https://github.com/llvm/llvm-project/commit/29b955f97cc6a4b96aba0ccdc033884c51ef466f
DIFF: https://github.com/llvm/llvm-project/commit/29b955f97cc6a4b96aba0ccdc033884c51ef466f.diff
LOG: [mlir][spirv] Handle debug information during (de)serialization.
Summary:
This is an initial version, currently supports OpString and OpLine
for autogenerated operations during (de)serialization.
Differential Revision: https://reviews.llvm.org/D79091
Added:
mlir/test/Dialect/SPIRV/Serialization/debug.mlir
Modified:
mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td
mlir/include/mlir/Dialect/SPIRV/Serialization.h
mlir/lib/Dialect/SPIRV/Serialization/Deserializer.cpp
mlir/lib/Dialect/SPIRV/Serialization/Serializer.cpp
mlir/lib/Dialect/SPIRV/Serialization/TranslateRegistration.cpp
mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp
mlir/tools/mlir-translate/mlir-translate.cpp
Removed:
################################################################################
diff --git a/mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td b/mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td
index d63837c585c9..64063cb77d01 100644
--- a/mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td
+++ b/mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td
@@ -3079,6 +3079,7 @@ def SPV_OC_OpSourceExtension : I32EnumAttrCase<"OpSourceExtension", 4>
def SPV_OC_OpName : I32EnumAttrCase<"OpName", 5>;
def SPV_OC_OpMemberName : I32EnumAttrCase<"OpMemberName", 6>;
def SPV_OC_OpString : I32EnumAttrCase<"OpString", 7>;
+def SPV_OC_OpLine : I32EnumAttrCase<"OpLine", 8>;
def SPV_OC_OpExtension : I32EnumAttrCase<"OpExtension", 10>;
def SPV_OC_OpExtInstImport : I32EnumAttrCase<"OpExtInstImport", 11>;
def SPV_OC_OpExtInst : I32EnumAttrCase<"OpExtInst", 12>;
@@ -3204,6 +3205,7 @@ def SPV_OC_OpBranchConditional : I32EnumAttrCase<"OpBranchConditional",
def SPV_OC_OpReturn : I32EnumAttrCase<"OpReturn", 253>;
def SPV_OC_OpReturnValue : I32EnumAttrCase<"OpReturnValue", 254>;
def SPV_OC_OpUnreachable : I32EnumAttrCase<"OpUnreachable", 255>;
+def SPV_OC_OpNoLine : I32EnumAttrCase<"OpNoLine", 317>;
def SPV_OC_OpModuleProcessed : I32EnumAttrCase<"OpModuleProcessed", 330>;
def SPV_OC_OpGroupNonUniformElect : I32EnumAttrCase<"OpGroupNonUniformElect", 333>;
def SPV_OC_OpGroupNonUniformBallot : I32EnumAttrCase<"OpGroupNonUniformBallot", 339>;
@@ -3223,7 +3225,7 @@ def SPV_OpcodeAttr :
SPV_I32EnumAttr<"Opcode", "valid SPIR-V instructions", [
SPV_OC_OpNop, SPV_OC_OpUndef, SPV_OC_OpSourceContinued, SPV_OC_OpSource,
SPV_OC_OpSourceExtension, SPV_OC_OpName, SPV_OC_OpMemberName, SPV_OC_OpString,
- SPV_OC_OpExtension, SPV_OC_OpExtInstImport, SPV_OC_OpExtInst,
+ SPV_OC_OpLine, SPV_OC_OpExtension, SPV_OC_OpExtInstImport, SPV_OC_OpExtInst,
SPV_OC_OpMemoryModel, SPV_OC_OpEntryPoint, SPV_OC_OpExecutionMode,
SPV_OC_OpCapability, SPV_OC_OpTypeVoid, SPV_OC_OpTypeBool, SPV_OC_OpTypeInt,
SPV_OC_OpTypeFloat, SPV_OC_OpTypeVector, SPV_OC_OpTypeArray,
@@ -3262,14 +3264,14 @@ def SPV_OpcodeAttr :
SPV_OC_OpAtomicUMax, SPV_OC_OpAtomicAnd, SPV_OC_OpAtomicOr, SPV_OC_OpAtomicXor,
SPV_OC_OpPhi, SPV_OC_OpLoopMerge, SPV_OC_OpSelectionMerge, SPV_OC_OpLabel,
SPV_OC_OpBranch, SPV_OC_OpBranchConditional, SPV_OC_OpReturn,
- SPV_OC_OpReturnValue, SPV_OC_OpUnreachable, SPV_OC_OpModuleProcessed,
- SPV_OC_OpGroupNonUniformElect, SPV_OC_OpGroupNonUniformBallot,
- SPV_OC_OpGroupNonUniformIAdd, SPV_OC_OpGroupNonUniformFAdd,
- SPV_OC_OpGroupNonUniformIMul, SPV_OC_OpGroupNonUniformFMul,
- SPV_OC_OpGroupNonUniformSMin, SPV_OC_OpGroupNonUniformUMin,
- SPV_OC_OpGroupNonUniformFMin, SPV_OC_OpGroupNonUniformSMax,
- SPV_OC_OpGroupNonUniformUMax, SPV_OC_OpGroupNonUniformFMax,
- SPV_OC_OpSubgroupBallotKHR
+ SPV_OC_OpReturnValue, SPV_OC_OpUnreachable, SPV_OC_OpNoLine,
+ SPV_OC_OpModuleProcessed, SPV_OC_OpGroupNonUniformElect,
+ SPV_OC_OpGroupNonUniformBallot, SPV_OC_OpGroupNonUniformIAdd,
+ SPV_OC_OpGroupNonUniformFAdd, SPV_OC_OpGroupNonUniformIMul,
+ SPV_OC_OpGroupNonUniformFMul, SPV_OC_OpGroupNonUniformSMin,
+ SPV_OC_OpGroupNonUniformUMin, SPV_OC_OpGroupNonUniformFMin,
+ SPV_OC_OpGroupNonUniformSMax, SPV_OC_OpGroupNonUniformUMax,
+ SPV_OC_OpGroupNonUniformFMax, SPV_OC_OpSubgroupBallotKHR
]>;
// End opcode section. Generated from SPIR-V spec; DO NOT MODIFY!
diff --git a/mlir/include/mlir/Dialect/SPIRV/Serialization.h b/mlir/include/mlir/Dialect/SPIRV/Serialization.h
index ef673472cd77..f6370a1b5ec2 100644
--- a/mlir/include/mlir/Dialect/SPIRV/Serialization.h
+++ b/mlir/include/mlir/Dialect/SPIRV/Serialization.h
@@ -26,7 +26,8 @@ class ModuleOp;
/// Serializes the given SPIR-V `module` and writes to `binary`. On failure,
/// reports errors to the error handler registered with the MLIR context for
/// `module`.
-LogicalResult serialize(ModuleOp module, SmallVectorImpl<uint32_t> &binary);
+LogicalResult serialize(ModuleOp module, SmallVectorImpl<uint32_t> &binary,
+ bool emitDebugInfo = false);
/// Deserializes the given SPIR-V `binary` module and creates a MLIR ModuleOp
/// in the given `context`. Returns the ModuleOp on success; otherwise, reports
diff --git a/mlir/lib/Dialect/SPIRV/Serialization/Deserializer.cpp b/mlir/lib/Dialect/SPIRV/Serialization/Deserializer.cpp
index 5a5c2fbcc19f..b46e17a8c6ab 100644
--- a/mlir/lib/Dialect/SPIRV/Serialization/Deserializer.cpp
+++ b/mlir/lib/Dialect/SPIRV/Serialization/Deserializer.cpp
@@ -68,6 +68,16 @@ struct BlockMergeInfo {
: mergeBlock(m), continueBlock(c) {}
};
+/// A struct for containing OpLine instruction information.
+struct DebugLine {
+ uint32_t fileID;
+ uint32_t line;
+ uint32_t col;
+
+ DebugLine(uint32_t fileIDNum, uint32_t lineNum, uint32_t colNum)
+ : fileID(fileIDNum), line(lineNum), col(colNum) {}
+};
+
/// Map from a selection/loop's header block to its merge (and continue) target.
using BlockMergeInfoMap = DenseMap<Block *, BlockMergeInfo>;
@@ -232,6 +242,23 @@ class Deserializer {
/// Processes a SPIR-V OpConstantNull instruction with the given `operands`.
LogicalResult processConstantNull(ArrayRef<uint32_t> operands);
+ //===--------------------------------------------------------------------===//
+ // Debug
+ //===--------------------------------------------------------------------===//
+
+ /// Discontinues any source-level location information that might be active
+ /// from a previous OpLine instruction.
+ LogicalResult clearDebugLine();
+
+ /// Creates a FileLineColLoc with the OpLine location information.
+ Location createFileLineColLoc(OpBuilder opBuilder);
+
+ /// Processes a SPIR-V OpLine instruction with the given `operands`.
+ LogicalResult processDebugLine(ArrayRef<uint32_t> operands);
+
+ /// Processes a SPIR-V OpString instruction with the given `operands`.
+ LogicalResult processDebugString(ArrayRef<uint32_t> operands);
+
//===--------------------------------------------------------------------===//
// Control flow
//===--------------------------------------------------------------------===//
@@ -376,6 +403,10 @@ class Deserializer {
/// The SPIR-V binary module.
ArrayRef<uint32_t> binary;
+ /// Contains the data of the OpLine instruction which precedes the current
+ /// processing instruction.
+ llvm::Optional<DebugLine> debugLine;
+
/// The current word offset into the binary module.
unsigned curOffset = 0;
@@ -444,6 +475,9 @@ class Deserializer {
// Result <id> to name mapping.
DenseMap<uint32_t, StringRef> nameMap;
+ // Result <id> to debug info mapping.
+ DenseMap<uint32_t, StringRef> debugInfoMap;
+
// Result <id> to decorations mapping.
DenseMap<uint32_t, MutableDictionaryAttr> decorations;
@@ -1506,6 +1540,7 @@ LogicalResult Deserializer::processBranch(ArrayRef<uint32_t> operands) {
auto *target = getOrCreateBlock(operands[0]);
opBuilder.create<spirv::BranchOp>(unknownLoc, target);
+ clearDebugLine();
return success();
}
@@ -1536,6 +1571,7 @@ Deserializer::processBranchConditional(ArrayRef<uint32_t> operands) {
/*trueArguments=*/ArrayRef<Value>(), falseBlock,
/*falseArguments=*/ArrayRef<Value>(), weights);
+ clearDebugLine();
return success();
}
@@ -1994,6 +2030,57 @@ LogicalResult Deserializer::structurizeControlFlow() {
return success();
}
+//===----------------------------------------------------------------------===//
+// Debug
+//===----------------------------------------------------------------------===//
+
+Location Deserializer::createFileLineColLoc(OpBuilder opBuilder) {
+ if (!debugLine)
+ return unknownLoc;
+
+ auto fileName = debugInfoMap.lookup(debugLine->fileID).str();
+ if (fileName.empty())
+ fileName = "<unknown>";
+ return opBuilder.getFileLineColLoc(opBuilder.getIdentifier(fileName),
+ debugLine->line, debugLine->col);
+}
+
+LogicalResult Deserializer::processDebugLine(ArrayRef<uint32_t> operands) {
+ // According to SPIR-V spec:
+ // "This location information applies to the instructions physically
+ // following this instruction, up to the first occurrence of any of the
+ // following: the next end of block, the next OpLine instruction, or the next
+ // OpNoLine instruction."
+ if (operands.size() != 3)
+ return emitError(unknownLoc, "OpLine must have 3 operands");
+ debugLine = DebugLine(operands[0], operands[1], operands[2]);
+ return success();
+}
+
+LogicalResult Deserializer::clearDebugLine() {
+ debugLine = llvm::None;
+ return success();
+}
+
+LogicalResult Deserializer::processDebugString(ArrayRef<uint32_t> operands) {
+ if (operands.size() < 2)
+ return emitError(unknownLoc, "OpString needs at least 2 operands");
+
+ if (!debugInfoMap.lookup(operands[0]).empty())
+ return emitError(unknownLoc,
+ "duplicate debug string found for result <id> ")
+ << operands[0];
+
+ unsigned wordIndex = 1;
+ StringRef debugString = decodeStringLiteral(operands, wordIndex);
+ if (wordIndex != operands.size())
+ return emitError(unknownLoc,
+ "unexpected trailing words in OpString instruction");
+
+ debugInfoMap[operands[0]] = debugString;
+ return success();
+}
+
//===----------------------------------------------------------------------===//
// Instruction
//===----------------------------------------------------------------------===//
@@ -2085,10 +2172,15 @@ LogicalResult Deserializer::processInstruction(spirv::Opcode opcode,
return processGlobalVariable(operands);
}
break;
+ case spirv::Opcode::OpLine:
+ return processDebugLine(operands);
+ case spirv::Opcode::OpNoLine:
+ return clearDebugLine();
case spirv::Opcode::OpName:
return processName(operands);
- case spirv::Opcode::OpModuleProcessed:
case spirv::Opcode::OpString:
+ return processDebugString(operands);
+ case spirv::Opcode::OpModuleProcessed:
case spirv::Opcode::OpSource:
case spirv::Opcode::OpSourceContinued:
case spirv::Opcode::OpSourceExtension:
diff --git a/mlir/lib/Dialect/SPIRV/Serialization/Serializer.cpp b/mlir/lib/Dialect/SPIRV/Serialization/Serializer.cpp
index 9db503ea0bdf..cc29bae39c1e 100644
--- a/mlir/lib/Dialect/SPIRV/Serialization/Serializer.cpp
+++ b/mlir/lib/Dialect/SPIRV/Serialization/Serializer.cpp
@@ -41,7 +41,7 @@ static LogicalResult encodeInstructionInto(SmallVectorImpl<uint32_t> &binary,
ArrayRef<uint32_t> operands) {
uint32_t wordCount = 1 + operands.size();
binary.push_back(spirv::getPrefixedOpcode(wordCount, op));
- binary.append(operands.begin(), operands.end());
+ binary.append(operands.begin(), operands.end());
return success();
}
@@ -132,7 +132,7 @@ namespace {
class Serializer {
public:
/// Creates a serializer for the given SPIR-V `module`.
- explicit Serializer(spirv::ModuleOp module);
+ explicit Serializer(spirv::ModuleOp module, bool emitDebugInfo = false);
/// Serializes the remembered SPIR-V module.
LogicalResult serialize();
@@ -189,6 +189,8 @@ class Serializer {
void processCapability();
+ void processDebugInfo();
+
void processExtension();
void processMemoryModel();
@@ -375,6 +377,10 @@ class Serializer {
LogicalResult emitDecoration(uint32_t target, spirv::Decoration decoration,
ArrayRef<uint32_t> params = {});
+ /// Emits an OpLine instruction with the given `loc` location information into
+ /// the given `binary` vector.
+ LogicalResult emitDebugLine(SmallVectorImpl<uint32_t> &binary, Location loc);
+
private:
/// The SPIR-V module to be serialized.
spirv::ModuleOp module;
@@ -382,6 +388,13 @@ class Serializer {
/// An MLIR builder for getting MLIR constructs.
mlir::Builder mlirBuilder;
+ /// A flag which indicates if the debuginfo should be emitted.
+ bool emitDebugInfo = false;
+
+ /// The <id> of the OpString instruction, which specifies a file name, for
+ /// use by other debug instructions.
+ uint32_t fileID = 0;
+
/// The next available result <id>.
uint32_t nextID = 1;
@@ -394,7 +407,7 @@ class Serializer {
SmallVector<uint32_t, 3> memoryModel;
SmallVector<uint32_t, 0> entryPoints;
SmallVector<uint32_t, 4> executionModes;
- // TODO(antiagainst): debug instructions
+ SmallVector<uint32_t, 0> debug;
SmallVector<uint32_t, 0> names;
SmallVector<uint32_t, 0> decorations;
SmallVector<uint32_t, 0> typesGlobalValues;
@@ -482,8 +495,9 @@ class Serializer {
};
} // namespace
-Serializer::Serializer(spirv::ModuleOp module)
- : module(module), mlirBuilder(module.getContext()) {}
+Serializer::Serializer(spirv::ModuleOp module, bool emitDebugInfo)
+ : module(module), mlirBuilder(module.getContext()),
+ emitDebugInfo(emitDebugInfo) {}
LogicalResult Serializer::serialize() {
LLVM_DEBUG(llvm::dbgs() << "+++ starting serialization +++\n");
@@ -495,6 +509,7 @@ LogicalResult Serializer::serialize() {
processCapability();
processExtension();
processMemoryModel();
+ processDebugInfo();
// Iterate over the module body to serialize it. Assumptions are that there is
// only one basic block in the moduleOp
@@ -525,6 +540,7 @@ void Serializer::collect(SmallVectorImpl<uint32_t> &binary) {
binary.append(memoryModel.begin(), memoryModel.end());
binary.append(entryPoints.begin(), entryPoints.end());
binary.append(executionModes.begin(), executionModes.end());
+ binary.append(debug.begin(), debug.end());
binary.append(names.begin(), names.end());
binary.append(decorations.begin(), decorations.end());
binary.append(typesGlobalValues.begin(), typesGlobalValues.end());
@@ -569,6 +585,19 @@ void Serializer::processCapability() {
{static_cast<uint32_t>(cap)});
}
+void Serializer::processDebugInfo() {
+ if (!emitDebugInfo)
+ return;
+ auto fileLoc = module.getLoc().dyn_cast<FileLineColLoc>();
+ auto fileName = fileLoc ? fileLoc.getFilename() : "<unknown>";
+ fileID = getNextID();
+ SmallVector<uint32_t, 16> operands;
+ operands.push_back(fileID);
+ spirv::encodeStringLiteralInto(operands, fileName);
+ encodeInstructionInto(debug, spirv::Opcode::OpString, operands);
+ // TODO: Encode more debug instructions.
+}
+
void Serializer::processExtension() {
llvm::SmallVector<uint32_t, 16> extName;
for (spirv::Extension ext : module.vce_triple()->getExtensions()) {
@@ -1838,13 +1867,26 @@ LogicalResult Serializer::emitDecoration(uint32_t target,
return success();
}
+LogicalResult Serializer::emitDebugLine(SmallVectorImpl<uint32_t> &binary,
+ Location loc) {
+ if (!emitDebugInfo)
+ return success();
+
+ auto fileLoc = loc.dyn_cast<FileLineColLoc>();
+ if (fileLoc)
+ encodeInstructionInto(binary, spirv::Opcode::OpLine,
+ {fileID, fileLoc.getLine(), fileLoc.getColumn()});
+ return success();
+}
+
LogicalResult spirv::serialize(spirv::ModuleOp module,
- SmallVectorImpl<uint32_t> &binary) {
+ SmallVectorImpl<uint32_t> &binary,
+ bool emitDebugInfo) {
if (!module.vce_triple().hasValue())
return module.emitError(
"module must have 'vce_triple' attribute to be serializeable");
- Serializer serializer(module);
+ Serializer serializer(module, emitDebugInfo);
if (failed(serializer.serialize()))
return failure();
diff --git a/mlir/lib/Dialect/SPIRV/Serialization/TranslateRegistration.cpp b/mlir/lib/Dialect/SPIRV/Serialization/TranslateRegistration.cpp
index 85bc95740904..4c3fb1e8d422 100644
--- a/mlir/lib/Dialect/SPIRV/Serialization/TranslateRegistration.cpp
+++ b/mlir/lib/Dialect/SPIRV/Serialization/TranslateRegistration.cpp
@@ -91,7 +91,8 @@ static LogicalResult serializeModule(ModuleOp module, raw_ostream &output) {
if (spirvModules.size() != 1)
return module.emitError("found more than one 'spv.module' op");
- if (failed(spirv::serialize(spirvModules[0], binary)))
+ if (failed(
+ spirv::serialize(spirvModules[0], binary, /*emitDebuginfo=*/false)))
return failure();
output.write(reinterpret_cast<char *>(binary.data()),
@@ -114,7 +115,7 @@ void registerToSPIRVTranslation() {
//===----------------------------------------------------------------------===//
static LogicalResult roundTripModule(llvm::SourceMgr &sourceMgr,
- raw_ostream &output,
+ bool emitDebugInfo, raw_ostream &output,
MLIRContext *context) {
// Parse an MLIR module from the source manager.
auto srcModule = OwningModuleRef(parseSourceFile(sourceMgr, context));
@@ -131,7 +132,7 @@ static LogicalResult roundTripModule(llvm::SourceMgr &sourceMgr,
if (std::next(spirvModules.begin()) != spirvModules.end())
return srcModule->emitError("found more than one 'spv.module' op");
- if (failed(spirv::serialize(*spirvModules.begin(), binary)))
+ if (failed(spirv::serialize(*spirvModules.begin(), binary, emitDebugInfo)))
return failure();
// Then deserialize to get back a SPIR-V module.
@@ -153,7 +154,18 @@ void registerTestRoundtripSPIRV() {
TranslateRegistration roundtrip(
"test-spirv-roundtrip", [](llvm::SourceMgr &sourceMgr,
raw_ostream &output, MLIRContext *context) {
- return roundTripModule(sourceMgr, output, context);
+ return roundTripModule(sourceMgr, /*emitDebugInfo=*/false, output,
+ context);
+ });
+}
+
+void registerTestRoundtripDebugSPIRV() {
+ TranslateRegistration roundtrip(
+ "test-spirv-roundtrip-debug",
+ [](llvm::SourceMgr &sourceMgr, raw_ostream &output,
+ MLIRContext *context) {
+ return roundTripModule(sourceMgr, /*emitDebugInfo=*/true, output,
+ context);
});
}
} // namespace mlir
diff --git a/mlir/test/Dialect/SPIRV/Serialization/debug.mlir b/mlir/test/Dialect/SPIRV/Serialization/debug.mlir
new file mode 100644
index 000000000000..83fcca7dd0fb
--- /dev/null
+++ b/mlir/test/Dialect/SPIRV/Serialization/debug.mlir
@@ -0,0 +1,60 @@
+// RUN: mlir-translate -test-spirv-roundtrip-debug -mlir-print-debuginfo %s | FileCheck %s
+
+spv.module Logical GLSL450 requires #spv.vce<v1.0, [Shader], []> {
+ spv.func @arithmetic(%arg0 : vector<4xf32>, %arg1 : vector<4xf32>) "None" {
+ // CHECK: loc({{".*debug.mlir"}}:6:10)
+ %0 = spv.FAdd %arg0, %arg1 : vector<4xf32>
+ // CHECK: loc({{".*debug.mlir"}}:8:10)
+ %1 = spv.FNegate %arg0 : vector<4xf32>
+ spv.Return
+ }
+
+ spv.func @atomic(%ptr: !spv.ptr<i32, Workgroup>, %value: i32, %comparator: i32) "None" {
+ // CHECK: loc({{".*debug.mlir"}}:14:10)
+ %1 = spv.AtomicAnd "Device" "None" %ptr, %value : !spv.ptr<i32, Workgroup>
+ spv.Return
+ }
+
+ spv.func @bitwiser(%arg0 : i32, %arg1 : i32) "None" {
+ // CHECK: loc({{".*debug.mlir"}}:20:10)
+ %0 = spv.BitwiseAnd %arg0, %arg1 : i32
+ spv.Return
+ }
+
+ spv.func @convert(%arg0 : f32) "None" {
+ // CHECK: loc({{".*debug.mlir"}}:26:10)
+ %0 = spv.ConvertFToU %arg0 : f32 to i32
+ spv.Return
+ }
+
+ spv.func @composite(%arg0 : !spv.struct<f32, !spv.struct<!spv.array<4xf32>, f32>>, %arg1: !spv.array<4xf32>, %arg2 : f32, %arg3 : f32) "None" {
+ // CHECK: loc({{".*debug.mlir"}}:32:10)
+ %0 = spv.CompositeInsert %arg1, %arg0[1 : i32, 0 : i32] : !spv.array<4xf32> into !spv.struct<f32, !spv.struct<!spv.array<4xf32>, f32>>
+ // CHECK: loc({{".*debug.mlir"}}:34:10)
+ %1 = spv.CompositeConstruct %arg2, %arg3 : vector<2xf32>
+ spv.Return
+ }
+
+ spv.func @group_non_uniform(%val: f32) "None" {
+ // CHECK: loc({{".*debug.mlir"}}:40:10)
+ %0 = spv.GroupNonUniformFAdd "Workgroup" "Reduce" %val : f32
+ spv.Return
+ }
+
+ spv.func @logical(%arg0: i32, %arg1: i32) "None" {
+ // CHECK: loc({{".*debug.mlir"}}:46:10)
+ %0 = spv.IEqual %arg0, %arg1 : i32
+ spv.Return
+ }
+
+ spv.func @memory_accesses(%arg0 : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, StorageBuffer>, %arg1 : i32, %arg2 : i32) "None" {
+ // CHECK: loc({{".*debug.mlir"}}:52:10)
+ %2 = spv.AccessChain %arg0[%arg1, %arg2] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, StorageBuffer>
+ // CHECK: loc({{".*debug.mlir"}}:54:10)
+ %3 = spv.Load "StorageBuffer" %2 : f32
+ // CHECK: loc({{.*debug.mlir"}}:56:5)
+ spv.Store "StorageBuffer" %2, %3 : f32
+ // CHECK: loc({{".*debug.mlir"}}:58:5)
+ spv.Return
+ }
+}
diff --git a/mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp b/mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp
index 750b85481878..b4ff1797f843 100644
--- a/mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp
+++ b/mlir/tools/mlir-tblgen/SPIRVUtilsGen.cpp
@@ -660,6 +660,8 @@ static void emitSerializationFunction(const Record *attrClass,
opVar, record->getValueAsString("extendedInstSetName"),
record->getValueAsInt("extendedInstOpcode"), operands);
} else {
+ // Emit debug info.
+ os << formatv(" emitDebugLine(functionBody, {0}.getLoc());\n", opVar);
os << formatv(" encodeInstructionInto("
"functionBody, spirv::getOpcode<{0}>(), {1});\n",
op.getQualCppClassName(), operands);
@@ -900,14 +902,22 @@ static void emitDeserializationFunction(const Record *attrClass,
emitOperandDeserialization(op, record->getLoc(), " ", words, wordIndex,
operands, attributes, os);
- os << formatv(
- " auto {1} = opBuilder.create<{0}>(unknownLoc, {2}, {3}, {4}); "
- "(void){1};\n",
- op.getQualCppClassName(), opVar, resultTypes, operands, attributes);
+ os << formatv(" Location loc = createFileLineColLoc(opBuilder);\n");
+ os << formatv(" auto {1} = opBuilder.create<{0}>(loc, {2}, {3}, {4}); "
+ "(void){1};\n",
+ op.getQualCppClassName(), opVar, resultTypes, operands,
+ attributes);
if (op.getNumResults() == 1) {
os << formatv(" valueMap[{0}] = {1}.getResult();\n\n", valueID, opVar);
}
+ // According to SPIR-V spec:
+ // This location information applies to the instructions physically following
+ // this instruction, up to the first occurrence of any of the following: the
+ // next end of block.
+ os << formatv(" if ({0}.hasTrait<OpTrait::IsTerminator>())\n", opVar);
+ os << formatv(" clearDebugLine();\n");
+
// Decorations
emitDecorationDeserialization(op, " ", valueID, attributes, os);
os << " return success();\n";
diff --git a/mlir/tools/mlir-translate/mlir-translate.cpp b/mlir/tools/mlir-translate/mlir-translate.cpp
index 5de561a85956..914bd340b3f5 100644
--- a/mlir/tools/mlir-translate/mlir-translate.cpp
+++ b/mlir/tools/mlir-translate/mlir-translate.cpp
@@ -50,9 +50,13 @@ static llvm::cl::opt<bool> verifyDiagnostics(
namespace mlir {
// Defined in the test directory, no public header.
void registerTestRoundtripSPIRV();
+void registerTestRoundtripDebugSPIRV();
} // namespace mlir
-static void registerTestTranslations() { registerTestRoundtripSPIRV(); }
+static void registerTestTranslations() {
+ registerTestRoundtripSPIRV();
+ registerTestRoundtripDebugSPIRV();
+}
int main(int argc, char **argv) {
registerAllDialects();
More information about the Mlir-commits
mailing list