|
@@ -11,6 +11,7 @@
|
|
|
#include "dxc/Support/SPIRVOptions.h"
|
|
|
#include "spirv/unified1/GLSL.std.450.h"
|
|
|
#include "spirv/unified1/spirv.hpp11"
|
|
|
+#include "clang/AST/APValue.h"
|
|
|
#include "clang/AST/Type.h"
|
|
|
#include "clang/Basic/SourceLocation.h"
|
|
|
#include "llvm/ADT/APFloat.h"
|
|
@@ -31,6 +32,9 @@ class SpirvType;
|
|
|
class SpirvVariable;
|
|
|
class SpirvString;
|
|
|
class Visitor;
|
|
|
+class DebugTypeComposite;
|
|
|
+class SpirvDebugDeclare;
|
|
|
+class FunctionType;
|
|
|
|
|
|
#define DEFINE_RELEASE_MEMORY_FOR_CLASS(cls) \
|
|
|
void releaseMemory() override { this->~cls(); }
|
|
@@ -50,9 +54,7 @@ public:
|
|
|
IK_ExecutionMode, // OpExecutionMode
|
|
|
IK_String, // OpString (debug)
|
|
|
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
|
|
@@ -123,6 +125,28 @@ public:
|
|
|
IK_Store, // OpStore
|
|
|
IK_UnaryOp, // Unary operations
|
|
|
IK_VectorShuffle, // OpVectorShuffle
|
|
|
+
|
|
|
+ // For DebugInfo instructions defined in OpenCL.DebugInfo.100
|
|
|
+ IK_DebugInfoNone,
|
|
|
+ IK_DebugCompilationUnit,
|
|
|
+ IK_DebugSource,
|
|
|
+ IK_DebugFunctionDecl,
|
|
|
+ IK_DebugFunction,
|
|
|
+ IK_DebugLocalVariable,
|
|
|
+ IK_DebugGlobalVariable,
|
|
|
+ IK_DebugOperation,
|
|
|
+ IK_DebugExpression,
|
|
|
+ IK_DebugDeclare,
|
|
|
+ IK_DebugLexicalBlock,
|
|
|
+ IK_DebugScope,
|
|
|
+ IK_DebugTypeBasic,
|
|
|
+ IK_DebugTypeArray,
|
|
|
+ IK_DebugTypeVector,
|
|
|
+ IK_DebugTypeFunction,
|
|
|
+ IK_DebugTypeComposite,
|
|
|
+ IK_DebugTypeMember,
|
|
|
+ IK_DebugTypeTemplate,
|
|
|
+ IK_DebugTypeTemplateParameter,
|
|
|
};
|
|
|
|
|
|
// All instruction classes should include a releaseMemory method.
|
|
@@ -527,6 +551,17 @@ public:
|
|
|
}
|
|
|
|
|
|
bool invokeVisitor(Visitor *v) override;
|
|
|
+
|
|
|
+ void setDebugDeclare(SpirvDebugDeclare *decl) { debugDecl = decl; }
|
|
|
+ SpirvDebugDeclare *getDebugDeclare() const { return debugDecl; }
|
|
|
+
|
|
|
+private:
|
|
|
+ // When we turn on the rich debug info generation option, we want
|
|
|
+ // to keep the function parameter information (like a local
|
|
|
+ // variable). Since DebugDeclare instruction maps a
|
|
|
+ // DebugLocalVariable instruction to OpFunctionParameter instruction,
|
|
|
+ // we keep a pointer to SpirvDebugDeclare in SpirvFunctionParameter.
|
|
|
+ SpirvDebugDeclare *debugDecl;
|
|
|
};
|
|
|
|
|
|
/// \brief Merge instructions include OpLoopMerge and OpSelectionMerge
|
|
@@ -1943,6 +1978,730 @@ public:
|
|
|
bool invokeVisitor(Visitor *v) override;
|
|
|
};
|
|
|
|
|
|
+/// \breif Base class for all OpenCL.DebugInfo.100 extension instructions.
|
|
|
+/// Note that all of these instructions should be added to the SPIR-V module as
|
|
|
+/// an OpExtInst instructions. So, all of these instructions must:
|
|
|
+/// 1) contain the result-id of the extended instruction set
|
|
|
+/// 2) have OpTypeVoid as their Result Type.
|
|
|
+/// 3) contain additional QualType and SpirvType for the debug type.
|
|
|
+class SpirvDebugInstruction : public SpirvInstruction {
|
|
|
+public:
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() >= IK_DebugInfoNone &&
|
|
|
+ inst->getKind() <= IK_DebugTypeTemplateParameter;
|
|
|
+ }
|
|
|
+
|
|
|
+ void setDebugType(SpirvDebugInstruction *type) { debugType = type; }
|
|
|
+ void setInstructionSet(SpirvExtInstImport *set) { instructionSet = set; }
|
|
|
+ SpirvExtInstImport *getInstructionSet() const { return instructionSet; }
|
|
|
+ uint32_t getDebugOpcode() const { return debugOpcode; }
|
|
|
+ QualType getDebugQualType() const { return debugQualType; }
|
|
|
+ const SpirvType *getDebugSpirvType() const { return debugSpirvType; }
|
|
|
+ SpirvDebugInstruction *getDebugType() const { return debugType; }
|
|
|
+ void setDebugQualType(QualType type) { debugQualType = type; }
|
|
|
+ void setDebugSpirvType(const SpirvType *type) { debugSpirvType = type; }
|
|
|
+
|
|
|
+ virtual SpirvDebugInstruction *getParentScope() const { return nullptr; }
|
|
|
+
|
|
|
+protected:
|
|
|
+ // TODO: Replace opcode type with an enum, when it is available in
|
|
|
+ // SPIRV-Headers.
|
|
|
+ SpirvDebugInstruction(Kind kind, uint32_t opcode);
|
|
|
+
|
|
|
+private:
|
|
|
+ // TODO: Replace this with an enum, when it is available in SPIRV-Headers.
|
|
|
+ uint32_t debugOpcode;
|
|
|
+
|
|
|
+ QualType debugQualType;
|
|
|
+ const SpirvType *debugSpirvType;
|
|
|
+
|
|
|
+ // The constructor for SpirvDebugInstruction sets the debug type to nullptr.
|
|
|
+ // A type lowering IMR pass will set debug types for all debug instructions
|
|
|
+ // that do contain a debug type.
|
|
|
+ SpirvDebugInstruction *debugType;
|
|
|
+
|
|
|
+ // The pointer to the debug info extended instruction set.
|
|
|
+ // This is not required by the constructor, and can be set via any IMR pass.
|
|
|
+ SpirvExtInstImport *instructionSet;
|
|
|
+};
|
|
|
+
|
|
|
+class SpirvDebugInfoNone : public SpirvDebugInstruction {
|
|
|
+public:
|
|
|
+ SpirvDebugInfoNone();
|
|
|
+
|
|
|
+ DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvDebugInfoNone)
|
|
|
+
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() == IK_DebugInfoNone;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool invokeVisitor(Visitor *v) override;
|
|
|
+};
|
|
|
+
|
|
|
+class SpirvDebugSource : public SpirvDebugInstruction {
|
|
|
+public:
|
|
|
+ SpirvDebugSource(llvm::StringRef file, llvm::StringRef text);
|
|
|
+
|
|
|
+ DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvDebugSource)
|
|
|
+
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() == IK_DebugSource;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool invokeVisitor(Visitor *v) override;
|
|
|
+
|
|
|
+ llvm::StringRef getFile() const { return file; }
|
|
|
+ llvm::StringRef getContent() const { return text; }
|
|
|
+
|
|
|
+private:
|
|
|
+ std::string file;
|
|
|
+ std::string text;
|
|
|
+};
|
|
|
+
|
|
|
+class SpirvDebugCompilationUnit : public SpirvDebugInstruction {
|
|
|
+public:
|
|
|
+ SpirvDebugCompilationUnit(uint32_t spirvVersion, uint32_t dwarfVersion,
|
|
|
+ SpirvDebugSource *src);
|
|
|
+
|
|
|
+ DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvDebugCompilationUnit)
|
|
|
+
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() == IK_DebugCompilationUnit;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool invokeVisitor(Visitor *v) override;
|
|
|
+
|
|
|
+ uint32_t getSpirvVersion() const { return spirvVersion; }
|
|
|
+ uint32_t getDwarfVersion() const { return dwarfVersion; }
|
|
|
+ SpirvDebugSource *getDebugSource() const { return source; }
|
|
|
+ spv::SourceLanguage getLanguage() const { return lang; }
|
|
|
+
|
|
|
+private:
|
|
|
+ uint32_t spirvVersion;
|
|
|
+ uint32_t dwarfVersion;
|
|
|
+ SpirvDebugSource *source;
|
|
|
+ spv::SourceLanguage lang;
|
|
|
+};
|
|
|
+
|
|
|
+// This class is not actually used. It can be cleaned up.
|
|
|
+class SpirvDebugFunctionDeclaration : public SpirvDebugInstruction {
|
|
|
+public:
|
|
|
+ SpirvDebugFunctionDeclaration(llvm::StringRef name, SpirvDebugSource *src,
|
|
|
+ uint32_t fnLine, uint32_t fnColumn,
|
|
|
+ SpirvDebugInstruction *parentScope,
|
|
|
+ llvm::StringRef linkageName, uint32_t flags);
|
|
|
+
|
|
|
+ DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvDebugFunctionDeclaration)
|
|
|
+
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() == IK_DebugFunctionDecl;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool invokeVisitor(Visitor *v) override;
|
|
|
+
|
|
|
+ SpirvDebugSource *getSource() const { return source; }
|
|
|
+ uint32_t getLine() const { return fnLine; }
|
|
|
+ uint32_t getColumn() const { return fnColumn; }
|
|
|
+ void setParent(SpirvDebugInstruction *scope) { parentScope = scope; }
|
|
|
+ SpirvDebugInstruction *getParentScope() const override { return parentScope; }
|
|
|
+ llvm::StringRef getLinkageName() const { return linkageName; }
|
|
|
+ uint32_t getFlags() const { return flags; }
|
|
|
+
|
|
|
+private:
|
|
|
+ SpirvDebugSource *source;
|
|
|
+ // Source line number at which the function appears
|
|
|
+ uint32_t fnLine;
|
|
|
+ // Source column number at which the function appears
|
|
|
+ uint32_t fnColumn;
|
|
|
+ // Debug instruction which represents the parent lexical scope
|
|
|
+ SpirvDebugInstruction *parentScope;
|
|
|
+ std::string linkageName;
|
|
|
+ // TODO: Replace this with an enum, when it is available in SPIRV-Headers
|
|
|
+ uint32_t flags;
|
|
|
+};
|
|
|
+
|
|
|
+class SpirvDebugFunction : public SpirvDebugInstruction {
|
|
|
+public:
|
|
|
+ SpirvDebugFunction(llvm::StringRef name, SpirvDebugSource *src,
|
|
|
+ uint32_t fnLine, uint32_t fnColumn,
|
|
|
+ SpirvDebugInstruction *parentScope,
|
|
|
+ llvm::StringRef linkageName, uint32_t flags,
|
|
|
+ uint32_t scopeLine, SpirvFunction *fn);
|
|
|
+
|
|
|
+ DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvDebugFunction)
|
|
|
+
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() == IK_DebugFunction;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool invokeVisitor(Visitor *v) override;
|
|
|
+
|
|
|
+ SpirvDebugSource *getSource() const { return source; }
|
|
|
+ uint32_t getLine() const { return fnLine; }
|
|
|
+ uint32_t getColumn() const { return fnColumn; }
|
|
|
+ void setParent(SpirvDebugInstruction *scope) { parentScope = scope; }
|
|
|
+ SpirvDebugInstruction *getParentScope() const override { return parentScope; }
|
|
|
+ llvm::StringRef getLinkageName() const { return linkageName; }
|
|
|
+ uint32_t getFlags() const { return flags; }
|
|
|
+ uint32_t getScopeLine() const { return scopeLine; }
|
|
|
+ SpirvFunction *getSpirvFunction() const { return fn; }
|
|
|
+
|
|
|
+ void setFunctionType(clang::spirv::FunctionType *t) { fnType = t; }
|
|
|
+ clang::spirv::FunctionType *getFunctionType() const { return fnType; }
|
|
|
+
|
|
|
+ void setDebugInfoNone(SpirvDebugInfoNone *none) { debugNone = none; }
|
|
|
+ SpirvDebugInfoNone *getDebugInfoNone() const { return debugNone; }
|
|
|
+
|
|
|
+private:
|
|
|
+ SpirvDebugSource *source;
|
|
|
+ // Source line number at which the function appears
|
|
|
+ uint32_t fnLine;
|
|
|
+ // Source column number at which the function appears
|
|
|
+ uint32_t fnColumn;
|
|
|
+ // Debug instruction which represents the parent lexical scope
|
|
|
+ SpirvDebugInstruction *parentScope;
|
|
|
+ std::string linkageName;
|
|
|
+ // TODO: Replace this with an enum, when it is available in SPIRV-Headers
|
|
|
+ uint32_t flags;
|
|
|
+ // Line number in the source program at which the function scope begins
|
|
|
+ uint32_t scopeLine;
|
|
|
+ // The function to which this debug instruction belongs
|
|
|
+ SpirvFunction *fn;
|
|
|
+
|
|
|
+ // When fn is nullptr, we want to put DebugInfoNone for Function operand
|
|
|
+ // of DebugFunction. Note that the spec must allow it (which will be
|
|
|
+ // discussed). We can consider this debugNone is a fallback of fn.
|
|
|
+ SpirvDebugInfoNone *debugNone;
|
|
|
+
|
|
|
+ // When the function debug info is generated by LowerTypeVisitor (not
|
|
|
+ // SpirvEmitter), we do not generate SpirvFunction. We only generate
|
|
|
+ // SpirvDebugFunction. Similar to fnType of SpirvFunction, we want to
|
|
|
+ // keep the function type info in this fnType.
|
|
|
+ clang::spirv::FunctionType *fnType;
|
|
|
+};
|
|
|
+
|
|
|
+class SpirvDebugLocalVariable : public SpirvDebugInstruction {
|
|
|
+public:
|
|
|
+ SpirvDebugLocalVariable(QualType debugQualType, llvm::StringRef varName,
|
|
|
+ SpirvDebugSource *src, uint32_t line, uint32_t column,
|
|
|
+ SpirvDebugInstruction *parentScope, uint32_t flags,
|
|
|
+ llvm::Optional<uint32_t> argNumber = llvm::None);
|
|
|
+
|
|
|
+ DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvDebugLocalVariable)
|
|
|
+
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() == IK_DebugLocalVariable;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool invokeVisitor(Visitor *v) override;
|
|
|
+
|
|
|
+ SpirvDebugSource *getSource() const { return source; }
|
|
|
+ uint32_t getLine() const { return line; }
|
|
|
+ uint32_t getColumn() const { return column; }
|
|
|
+ SpirvDebugInstruction *getParentScope() const override { return parentScope; }
|
|
|
+ uint32_t getFlags() const { return flags; }
|
|
|
+ llvm::Optional<uint32_t> getArgNumber() const { return argNumber; }
|
|
|
+
|
|
|
+private:
|
|
|
+ SpirvDebugSource *source;
|
|
|
+ uint32_t line;
|
|
|
+ uint32_t column;
|
|
|
+ SpirvDebugInstruction *parentScope;
|
|
|
+ // TODO: Replace this with an enum, when it is available in SPIRV-Headers
|
|
|
+ uint32_t flags;
|
|
|
+ llvm::Optional<uint32_t> argNumber;
|
|
|
+};
|
|
|
+
|
|
|
+class SpirvDebugGlobalVariable : public SpirvDebugInstruction {
|
|
|
+public:
|
|
|
+ SpirvDebugGlobalVariable(
|
|
|
+ QualType debugQualType, llvm::StringRef varName, SpirvDebugSource *src,
|
|
|
+ uint32_t line, uint32_t column, SpirvDebugInstruction *parentScope,
|
|
|
+ llvm::StringRef linkageName, SpirvVariable *var, uint32_t flags,
|
|
|
+ llvm::Optional<SpirvInstruction *> staticMemberDebugType = llvm::None);
|
|
|
+
|
|
|
+ DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvDebugGlobalVariable)
|
|
|
+
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() == IK_DebugGlobalVariable;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool invokeVisitor(Visitor *v) override;
|
|
|
+
|
|
|
+ SpirvDebugSource *getSource() const { return source; }
|
|
|
+ uint32_t getLine() const { return line; }
|
|
|
+ uint32_t getColumn() const { return column; }
|
|
|
+ SpirvDebugInstruction *getParentScope() const override { return parentScope; }
|
|
|
+ llvm::StringRef getLinkageName() const { return linkageName; }
|
|
|
+ uint32_t getFlags() const { return flags; }
|
|
|
+ SpirvInstruction *getVariable() const { return var; }
|
|
|
+ llvm::Optional<SpirvInstruction *> getStaticMemberDebugDecl() const {
|
|
|
+ return staticMemberDebugDecl;
|
|
|
+ }
|
|
|
+
|
|
|
+private:
|
|
|
+ SpirvDebugSource *source;
|
|
|
+ uint32_t line;
|
|
|
+ uint32_t column;
|
|
|
+ SpirvDebugInstruction *parentScope;
|
|
|
+ std::string linkageName;
|
|
|
+ SpirvVariable *var;
|
|
|
+ // TODO: Replace this with an enum, when it is available in SPIRV-Headers
|
|
|
+ uint32_t flags;
|
|
|
+ llvm::Optional<SpirvInstruction *> staticMemberDebugDecl;
|
|
|
+};
|
|
|
+
|
|
|
+class SpirvDebugOperation : public SpirvDebugInstruction {
|
|
|
+public:
|
|
|
+ SpirvDebugOperation(uint32_t operationOpCode,
|
|
|
+ llvm::ArrayRef<int32_t> operands = {});
|
|
|
+
|
|
|
+ DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvDebugOperation)
|
|
|
+
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() == IK_DebugOperation;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool invokeVisitor(Visitor *v) override;
|
|
|
+
|
|
|
+ uint32_t getOperationOpcode() { return operationOpcode; }
|
|
|
+
|
|
|
+private:
|
|
|
+ uint32_t operationOpcode;
|
|
|
+ llvm::SmallVector<int32_t, 2> operands;
|
|
|
+};
|
|
|
+
|
|
|
+class SpirvDebugExpression : public SpirvDebugInstruction {
|
|
|
+public:
|
|
|
+ SpirvDebugExpression(llvm::ArrayRef<SpirvDebugOperation *> operations = {});
|
|
|
+
|
|
|
+ DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvDebugExpression)
|
|
|
+
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() == IK_DebugExpression;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool invokeVisitor(Visitor *v) override;
|
|
|
+
|
|
|
+ llvm::ArrayRef<SpirvDebugOperation *> getOperations() const {
|
|
|
+ return operations;
|
|
|
+ }
|
|
|
+
|
|
|
+private:
|
|
|
+ llvm::SmallVector<SpirvDebugOperation *, 4> operations;
|
|
|
+};
|
|
|
+
|
|
|
+class SpirvDebugDeclare : public SpirvDebugInstruction {
|
|
|
+public:
|
|
|
+ SpirvDebugDeclare(SpirvDebugLocalVariable *, SpirvInstruction *,
|
|
|
+ SpirvDebugExpression *);
|
|
|
+
|
|
|
+ DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvDebugDeclare)
|
|
|
+
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() == IK_DebugDeclare;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool invokeVisitor(Visitor *v) override;
|
|
|
+
|
|
|
+ SpirvDebugLocalVariable *getDebugLocalVariable() const { return debugVar; }
|
|
|
+ SpirvInstruction *getVariable() const { return var; }
|
|
|
+ SpirvDebugExpression *getDebugExpression() const { return expression; }
|
|
|
+
|
|
|
+private:
|
|
|
+ SpirvDebugLocalVariable *debugVar;
|
|
|
+ SpirvInstruction *var;
|
|
|
+ SpirvDebugExpression *expression;
|
|
|
+};
|
|
|
+
|
|
|
+class SpirvDebugLexicalBlock : public SpirvDebugInstruction {
|
|
|
+public:
|
|
|
+ SpirvDebugLexicalBlock(SpirvDebugSource *source, uint32_t line,
|
|
|
+ uint32_t column, SpirvDebugInstruction *parent);
|
|
|
+
|
|
|
+ DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvDebugLexicalBlock)
|
|
|
+
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() == IK_DebugLexicalBlock;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool invokeVisitor(Visitor *v) override;
|
|
|
+
|
|
|
+ SpirvDebugSource *getSource() const { return source; }
|
|
|
+ uint32_t getLine() const { return line; }
|
|
|
+ uint32_t getColumn() const { return column; }
|
|
|
+ SpirvDebugInstruction *getParentScope() const override { return parent; }
|
|
|
+
|
|
|
+private:
|
|
|
+ SpirvDebugSource *source;
|
|
|
+ uint32_t line;
|
|
|
+ uint32_t column;
|
|
|
+ SpirvDebugInstruction *parent;
|
|
|
+};
|
|
|
+
|
|
|
+/// Represent DebugScope. DebugScope has two operands: a lexical scope
|
|
|
+/// and DebugInlinedAt. The DebugInlinedAt is an optional argument
|
|
|
+/// and it is only used when we inline a function. Since DXC does not
|
|
|
+/// conduct the inlining, we do not add DebugInlinedAt operand.
|
|
|
+class SpirvDebugScope : public SpirvDebugInstruction {
|
|
|
+public:
|
|
|
+ SpirvDebugScope(SpirvDebugInstruction *);
|
|
|
+
|
|
|
+ DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvDebugScope)
|
|
|
+
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() == IK_DebugScope;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool invokeVisitor(Visitor *v) override;
|
|
|
+
|
|
|
+ SpirvDebugInstruction *getScope() const { return scope; }
|
|
|
+
|
|
|
+private:
|
|
|
+ SpirvDebugInstruction *scope;
|
|
|
+};
|
|
|
+
|
|
|
+/// The following classes represent debug types defined in the
|
|
|
+/// OpenCL.DebugInfo.100 spec.
|
|
|
+///
|
|
|
+/// Note: While debug type and SPIR-V type are very similar, they are not quite
|
|
|
+/// identical. For example: the debug type contains the HLL string name of the
|
|
|
+/// type. Another example: two structs with similar definitions in different
|
|
|
+/// lexical scopes translate into 1 SPIR-V type, but translate into 2 different
|
|
|
+/// debug type instructions.
|
|
|
+///
|
|
|
+/// Note: DebugTypeComposite contains a vector of its members, which can be
|
|
|
+/// DebugTypeMember or DebugFunction. The former is a type, and the latter is a
|
|
|
+/// SPIR-V instruction. This somewhat tips the sclae in favor of using the
|
|
|
+/// SpirvInstruction base class for representing debug types.
|
|
|
+///
|
|
|
+/// TODO: Add support for the following debug types:
|
|
|
+/// DebugTypePointer,
|
|
|
+/// DebugTypeQualifier,
|
|
|
+/// DebugTypedef,
|
|
|
+/// DebugTypeEnum,
|
|
|
+/// DebugTypeInheritance,
|
|
|
+/// DebugTypePtrToMember,
|
|
|
+/// DebugTypeTemplate,
|
|
|
+/// DebugTypeTemplateParameter,
|
|
|
+/// DebugTypeTemplateTemplateParameter,
|
|
|
+/// DebugTypeTemplateParameterPack,
|
|
|
+
|
|
|
+class SpirvDebugType : public SpirvDebugInstruction {
|
|
|
+public:
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() >= IK_DebugTypeBasic &&
|
|
|
+ inst->getKind() <= IK_DebugTypeTemplateParameter;
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual uint32_t getSizeInBits() const { return 0u; }
|
|
|
+
|
|
|
+protected:
|
|
|
+ SpirvDebugType(Kind kind, uint32_t opcode)
|
|
|
+ : SpirvDebugInstruction(kind, opcode) {}
|
|
|
+};
|
|
|
+
|
|
|
+/// Represents basic debug types, including boolean, float, integer.
|
|
|
+class SpirvDebugTypeBasic : public SpirvDebugType {
|
|
|
+public:
|
|
|
+ SpirvDebugTypeBasic(llvm::StringRef name, SpirvConstant *size,
|
|
|
+ uint32_t encoding);
|
|
|
+
|
|
|
+ DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvDebugTypeBasic)
|
|
|
+
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() == IK_DebugTypeBasic;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool invokeVisitor(Visitor *v) override;
|
|
|
+
|
|
|
+ SpirvConstant *getSize() const { return size; }
|
|
|
+ uint32_t getEncoding() const { return encoding; }
|
|
|
+ uint32_t getSizeInBits() const override;
|
|
|
+
|
|
|
+private:
|
|
|
+ SpirvConstant *size;
|
|
|
+ // TODO: Replace uint32_t with enum from SPIRV-Headers once available.
|
|
|
+ // 0, Unspecified
|
|
|
+ // 1, Address
|
|
|
+ // 2, Boolean
|
|
|
+ // 3, Float
|
|
|
+ // 4, Signed
|
|
|
+ // 5, SignedChar
|
|
|
+ // 6, Unsigned
|
|
|
+ // 7, UnsignedChar
|
|
|
+ uint32_t encoding;
|
|
|
+};
|
|
|
+
|
|
|
+/// Represents array debug types
|
|
|
+class SpirvDebugTypeArray : public SpirvDebugType {
|
|
|
+public:
|
|
|
+ SpirvDebugTypeArray(SpirvDebugType *elemType,
|
|
|
+ llvm::ArrayRef<uint32_t> elemCount);
|
|
|
+
|
|
|
+ DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvDebugTypeArray)
|
|
|
+
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() == IK_DebugTypeArray;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool invokeVisitor(Visitor *v) override;
|
|
|
+
|
|
|
+ SpirvDebugType *getElementType() const { return elementType; }
|
|
|
+ llvm::SmallVector<uint32_t, 2> &getElementCount() { return elementCount; }
|
|
|
+
|
|
|
+ uint32_t getSizeInBits() const override {
|
|
|
+ // TODO: avoid integer overflow
|
|
|
+ uint32_t nElem = elementType->getSizeInBits();
|
|
|
+ for (auto k : elementCount)
|
|
|
+ nElem *= k;
|
|
|
+ return nElem;
|
|
|
+ }
|
|
|
+
|
|
|
+private:
|
|
|
+ SpirvDebugType *elementType;
|
|
|
+ llvm::SmallVector<uint32_t, 2> elementCount;
|
|
|
+};
|
|
|
+
|
|
|
+/// Represents vector debug types
|
|
|
+class SpirvDebugTypeVector : public SpirvDebugType {
|
|
|
+public:
|
|
|
+ SpirvDebugTypeVector(SpirvDebugType *elemType, uint32_t elemCount);
|
|
|
+
|
|
|
+ DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvDebugTypeVector)
|
|
|
+
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() == IK_DebugTypeVector;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool invokeVisitor(Visitor *v) override;
|
|
|
+
|
|
|
+ SpirvDebugType *getElementType() const { return elementType; }
|
|
|
+ uint32_t getElementCount() const { return elementCount; }
|
|
|
+
|
|
|
+ uint32_t getSizeInBits() const override {
|
|
|
+ return elementCount * elementType->getSizeInBits();
|
|
|
+ }
|
|
|
+
|
|
|
+private:
|
|
|
+ SpirvDebugType *elementType;
|
|
|
+ uint32_t elementCount;
|
|
|
+};
|
|
|
+
|
|
|
+/// Represents a function debug type. Includes the function return type and
|
|
|
+/// parameter types.
|
|
|
+class SpirvDebugTypeFunction : public SpirvDebugType {
|
|
|
+public:
|
|
|
+ SpirvDebugTypeFunction(uint32_t flags, SpirvDebugType *ret,
|
|
|
+ llvm::ArrayRef<SpirvDebugType *> params);
|
|
|
+
|
|
|
+ DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvDebugTypeFunction)
|
|
|
+
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() == IK_DebugTypeFunction;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool invokeVisitor(Visitor *v) override;
|
|
|
+
|
|
|
+ uint32_t getDebugFlags() const { return debugFlags; }
|
|
|
+ SpirvDebugType *getReturnType() const { return returnType; }
|
|
|
+ llvm::ArrayRef<SpirvDebugType *> getParamTypes() const { return paramTypes; }
|
|
|
+
|
|
|
+private:
|
|
|
+ // TODO: Replace uint32_t with enum in the SPIRV-Headers once it is available.
|
|
|
+ uint32_t debugFlags;
|
|
|
+ // Return Type is a debug instruction which represents type of return value of
|
|
|
+ // the function. If the function has no return value, this operand is
|
|
|
+ // OpTypeVoid, in which case we will use nullptr for this member.
|
|
|
+ SpirvDebugType *returnType;
|
|
|
+ llvm::SmallVector<SpirvDebugType *, 4> paramTypes;
|
|
|
+};
|
|
|
+
|
|
|
+/// Represents debug information for a template type parameter.
|
|
|
+class SpirvDebugTypeTemplateParameter : public SpirvDebugType {
|
|
|
+public:
|
|
|
+ SpirvDebugTypeTemplateParameter(llvm::StringRef name, SpirvDebugType *type,
|
|
|
+ SpirvInstruction *value,
|
|
|
+ SpirvDebugSource *source, uint32_t line,
|
|
|
+ uint32_t column);
|
|
|
+
|
|
|
+ DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvDebugTypeTemplateParameter)
|
|
|
+
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() == IK_DebugTypeTemplateParameter;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool invokeVisitor(Visitor *v) override;
|
|
|
+
|
|
|
+ SpirvDebugType *getActualType() const { return actualType; }
|
|
|
+ void setValue(SpirvInstruction *c) { value = c; }
|
|
|
+ SpirvInstruction *getValue() const { return value; }
|
|
|
+ SpirvDebugSource *getSource() const { return source; }
|
|
|
+ uint32_t getLine() const { return line; }
|
|
|
+ uint32_t getColumn() const { return column; }
|
|
|
+
|
|
|
+private:
|
|
|
+ SpirvDebugType *actualType; //< Type for type param
|
|
|
+ SpirvInstruction *value; //< Value. It must be null for type.
|
|
|
+ SpirvDebugSource *source; //< DebugSource containing this type
|
|
|
+ uint32_t line; //< Line number
|
|
|
+ uint32_t column; //< Column number
|
|
|
+};
|
|
|
+
|
|
|
+/// Represents debug information for a template type.
|
|
|
+class SpirvDebugTypeTemplate : public SpirvDebugType {
|
|
|
+public:
|
|
|
+ SpirvDebugTypeTemplate(
|
|
|
+ SpirvDebugInstruction *target,
|
|
|
+ const llvm::SmallVector<SpirvDebugTypeTemplateParameter *, 2> ¶ms);
|
|
|
+
|
|
|
+ DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvDebugTypeTemplate)
|
|
|
+
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() == IK_DebugTypeTemplate;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool invokeVisitor(Visitor *v) override;
|
|
|
+
|
|
|
+ llvm::SmallVector<SpirvDebugTypeTemplateParameter *, 2> getParams() {
|
|
|
+ return params;
|
|
|
+ }
|
|
|
+ SpirvDebugInstruction *getTarget() const { return target; }
|
|
|
+
|
|
|
+private:
|
|
|
+ // A debug instruction representing class, struct or function which has
|
|
|
+ // template parameter(s).
|
|
|
+ SpirvDebugInstruction *target;
|
|
|
+
|
|
|
+ // Debug instructions representing the template parameters for this
|
|
|
+ // particular instantiation. It must be DebugTypeTemplateParameter
|
|
|
+ // or DebugTypeTemplateTemplateParameter.
|
|
|
+ // TODO: change the type to SpirvDebugType * when we support
|
|
|
+ // DebugTypeTemplateTemplateParameter.
|
|
|
+ llvm::SmallVector<SpirvDebugTypeTemplateParameter *, 2> params;
|
|
|
+};
|
|
|
+
|
|
|
+/// Represents the debug type of a struct/union/class member.
|
|
|
+/// Note: We have intentionally left out the pointer to the parent composite
|
|
|
+/// type.
|
|
|
+class SpirvDebugTypeMember : public SpirvDebugType {
|
|
|
+public:
|
|
|
+ SpirvDebugTypeMember(llvm::StringRef name, SpirvDebugType *type,
|
|
|
+ SpirvDebugSource *source, uint32_t line_,
|
|
|
+ uint32_t column_, SpirvDebugInstruction *parent,
|
|
|
+ uint32_t flags, uint32_t offsetInBits,
|
|
|
+ uint32_t sizeInBits, const APValue *value = nullptr);
|
|
|
+
|
|
|
+ DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvDebugTypeMember)
|
|
|
+
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() == IK_DebugTypeMember;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool invokeVisitor(Visitor *v) override;
|
|
|
+
|
|
|
+ SpirvDebugInstruction *getParentScope() const override { return parent; }
|
|
|
+
|
|
|
+ SpirvDebugSource *getSource() const { return source; }
|
|
|
+ uint32_t getLine() const { return line; }
|
|
|
+ uint32_t getColumn() const { return column; }
|
|
|
+ uint32_t getOffsetInBits() const { return offsetInBits; }
|
|
|
+ uint32_t getDebugFlags() const { return debugFlags; }
|
|
|
+ uint32_t getSizeInBits() const override { return sizeInBits; }
|
|
|
+ const APValue *getValue() const { return value; }
|
|
|
+
|
|
|
+private:
|
|
|
+ SpirvDebugSource *source; //< DebugSource
|
|
|
+ uint32_t line; //< Line number
|
|
|
+ uint32_t column; //< Column number
|
|
|
+
|
|
|
+ SpirvDebugInstruction *parent; //< The parent DebugTypeComposite
|
|
|
+
|
|
|
+ uint32_t offsetInBits; //< Offset (in bits) of this member in the struct
|
|
|
+ uint32_t sizeInBits; //< Size (in bits) of this member in the struct
|
|
|
+ // TODO: Replace uint32_t with enum in the SPIRV-Headers once it is
|
|
|
+ // available.
|
|
|
+ uint32_t debugFlags;
|
|
|
+ const APValue *value; //< Value (if static member)
|
|
|
+};
|
|
|
+
|
|
|
+class SpirvDebugTypeComposite : public SpirvDebugType {
|
|
|
+public:
|
|
|
+ SpirvDebugTypeComposite(llvm::StringRef name, SpirvDebugSource *source,
|
|
|
+ uint32_t line, uint32_t column,
|
|
|
+ SpirvDebugInstruction *parent,
|
|
|
+ llvm::StringRef linkageName, uint32_t flags,
|
|
|
+ uint32_t tag);
|
|
|
+
|
|
|
+ DEFINE_RELEASE_MEMORY_FOR_CLASS(SpirvDebugTypeComposite)
|
|
|
+
|
|
|
+ static bool classof(const SpirvInstruction *inst) {
|
|
|
+ return inst->getKind() == IK_DebugTypeComposite;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool invokeVisitor(Visitor *v) override;
|
|
|
+
|
|
|
+ llvm::SmallVector<SpirvDebugInstruction *, 4> getMembers() { return members; }
|
|
|
+ void appendMember(SpirvDebugInstruction *member) {
|
|
|
+ members.push_back(member);
|
|
|
+ }
|
|
|
+ void
|
|
|
+ setMembers(const llvm::SmallVector<SpirvDebugInstruction *, 4> &memberTypes) {
|
|
|
+ members = memberTypes;
|
|
|
+ }
|
|
|
+
|
|
|
+ SpirvDebugInstruction *getParentScope() const override { return parent; }
|
|
|
+ uint32_t getTag() const { return tag; }
|
|
|
+ SpirvDebugSource *getSource() const { return source; }
|
|
|
+ uint32_t getLine() const { return line; }
|
|
|
+ uint32_t getColumn() const { return column; }
|
|
|
+ llvm::StringRef getLinkageName() const { return linkageName; }
|
|
|
+ uint32_t getDebugFlags() const { return debugFlags; }
|
|
|
+
|
|
|
+ void setSizeInBits(uint32_t size_) { sizeInBits = size_; }
|
|
|
+ uint32_t getSizeInBits() const override { return sizeInBits; }
|
|
|
+
|
|
|
+ void markAsOpaqueType(SpirvDebugInfoNone *none) {
|
|
|
+ // If it was already marked as a opaque type, just return. For example,
|
|
|
+ // `debugName` can be "@@Texture2D" if we call this method twice.
|
|
|
+ if (debugNone == none && !debugName.empty() && debugName[0] == '@')
|
|
|
+ return;
|
|
|
+ debugName = std::string("@") + debugName;
|
|
|
+ debugNone = none;
|
|
|
+ }
|
|
|
+ SpirvDebugInfoNone *getDebugInfoNone() const { return debugNone; }
|
|
|
+
|
|
|
+private:
|
|
|
+ SpirvDebugSource *source; //< DebugSource containing this type
|
|
|
+ uint32_t line; //< Line number
|
|
|
+ uint32_t column; //< Column number
|
|
|
+
|
|
|
+ // The parent lexical scope. Must be one of the following:
|
|
|
+ // DebugCompilationUnit, DebugFunction, DebugLexicalBlock or other
|
|
|
+ // DebugTypeComposite
|
|
|
+ SpirvDebugInstruction *parent; //< The parent lexical scope
|
|
|
+
|
|
|
+ std::string linkageName; //< Linkage name
|
|
|
+ uint32_t sizeInBits; //< Size (in bits) of an instance of composite
|
|
|
+
|
|
|
+ // TODO: Replace uint32_t with enum in the SPIRV-Headers once it is
|
|
|
+ // available.
|
|
|
+ uint32_t debugFlags;
|
|
|
+ // TODO: Replace uint32_t with enum in the SPIRV-Headers once it is
|
|
|
+ // available.
|
|
|
+ uint32_t tag;
|
|
|
+
|
|
|
+ // Pointer to members inside this composite type.
|
|
|
+ // Note: Members must be ids of DebugTypeMember, DebugFunction or
|
|
|
+ // DebugTypeInheritance. Since DebugFunction may be a member, we cannot use a
|
|
|
+ // vector of SpirvDebugType.
|
|
|
+ llvm::SmallVector<SpirvDebugInstruction *, 4> members;
|
|
|
+
|
|
|
+ // When it is DebugTypeComposite for HLSL resource type i.e., opaque
|
|
|
+ // type, we must put DebugInfoNone for Size operand.
|
|
|
+ SpirvDebugInfoNone *debugNone;
|
|
|
+};
|
|
|
+
|
|
|
#undef DECLARE_INVOKE_VISITOR_FOR_CLASS
|
|
|
|
|
|
} // namespace spirv
|