Handle conflict between debug info and existing validation rule (#3104)
* Allow OpExtInst for DebugInfo between secion 9 and 10 Fixes #3086 * Handle spirv-opt errors on DebugInfo Ext * Add IR Loader test * Fix ir loader bug * Handle DebugFunction/DebugTypeMember forward reference * Add test cases (forward reference to function) * Support old DebugInfo extension * Validate local debug info out of function
This commit is contained in:
Родитель
b97057e7f7
Коммит
dd37d73c5e
|
@ -239,7 +239,8 @@ $(1)/$(2).h : \
|
|||
--extinst-grammar=$(3) \
|
||||
--extinst-output-base=$(1)/$(2)
|
||||
@echo "[$(TARGET_ARCH_ABI)] Generate language specific header for $(2): headers <= grammar"
|
||||
$(LOCAL_PATH)/source/ext_inst.cpp: $(1)/$(2).h
|
||||
$(foreach F,$(SPVTOOLS_SRC_FILES) $(SPVTOOLS_OPT_SRC_FILES),$(LOCAL_PATH)/$F ) \
|
||||
: $(1)/$(2).h
|
||||
endef
|
||||
# We generate language-specific headers for DebugInfo and OpenCL.DebugInfo.100
|
||||
$(eval $(call gen_spvtools_lang_headers,$(SPVTOOLS_OUT_PATH),DebugInfo,$(SPV_DEBUGINFO_GRAMMAR)))
|
||||
|
|
|
@ -138,6 +138,14 @@ bool spvExtInstIsNonSemantic(const spv_ext_inst_type_t type) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool spvExtInstIsDebugInfo(const spv_ext_inst_type_t type) {
|
||||
if (type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 ||
|
||||
type == SPV_EXT_INST_TYPE_DEBUGINFO) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
spv_result_t spvExtInstTableNameLookup(const spv_ext_inst_table table,
|
||||
const spv_ext_inst_type_t type,
|
||||
const char* name,
|
||||
|
|
|
@ -24,6 +24,9 @@ spv_ext_inst_type_t spvExtInstImportTypeGet(const char* name);
|
|||
// Returns true if the extended instruction set is non-semantic
|
||||
bool spvExtInstIsNonSemantic(const spv_ext_inst_type_t type);
|
||||
|
||||
// Returns true if the extended instruction set is debug info
|
||||
bool spvExtInstIsDebugInfo(const spv_ext_inst_type_t type);
|
||||
|
||||
// Finds the named extented instruction of the given type in the given extended
|
||||
// instruction table. On success, returns SPV_SUCCESS and writes a handle of
|
||||
// the instruction entry into *entry.
|
||||
|
|
|
@ -324,6 +324,11 @@ spv_result_t MergeModules(const MessageConsumer& consumer,
|
|||
linked_module->AddDebug3Inst(
|
||||
std::unique_ptr<Instruction>(inst.Clone(linked_context)));
|
||||
|
||||
for (const auto& module : input_modules)
|
||||
for (const auto& inst : module->ext_inst_debuginfo())
|
||||
linked_module->AddExtInstDebugInfo(
|
||||
std::unique_ptr<Instruction>(inst.Clone(linked_context)));
|
||||
|
||||
// If the generated module uses SPIR-V 1.1 or higher, add an
|
||||
// OpModuleProcessed instruction about the linking step.
|
||||
if (linked_module->version() >= 0x10100) {
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#include "DebugInfo.h"
|
||||
#include "OpenCLDebugInfo100.h"
|
||||
#include "source/macro.h"
|
||||
#include "source/spirv_constant.h"
|
||||
#include "source/spirv_target_env.h"
|
||||
|
@ -512,3 +514,37 @@ std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction(
|
|||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::function<bool(unsigned)> spvDbgInfoExtOperandCanBeForwardDeclaredFunction(
|
||||
spv_ext_inst_type_t ext_type, uint32_t key) {
|
||||
// TODO(https://gitlab.khronos.org/spirv/SPIR-V/issues/532): Forward
|
||||
// references for debug info instructions are still in discussion. We must
|
||||
// update the following lines of code when we conclude the spec.
|
||||
std::function<bool(unsigned index)> out;
|
||||
if (ext_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) {
|
||||
switch (OpenCLDebugInfo100Instructions(key)) {
|
||||
case OpenCLDebugInfo100DebugFunction:
|
||||
out = [](unsigned index) { return index == 13; };
|
||||
break;
|
||||
case OpenCLDebugInfo100DebugTypeComposite:
|
||||
out = [](unsigned index) { return index >= 13; };
|
||||
break;
|
||||
default:
|
||||
out = [](unsigned) { return false; };
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (DebugInfoInstructions(key)) {
|
||||
case DebugInfoDebugFunction:
|
||||
out = [](unsigned index) { return index == 13; };
|
||||
break;
|
||||
case DebugInfoDebugTypeComposite:
|
||||
out = [](unsigned index) { return index >= 12; };
|
||||
break;
|
||||
default:
|
||||
out = [](unsigned) { return false; };
|
||||
break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -141,4 +141,11 @@ bool spvIsInIdType(spv_operand_type_t type);
|
|||
std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction(
|
||||
SpvOp opcode);
|
||||
|
||||
// Takes the instruction key of a debug info extension instruction
|
||||
// and returns a function object that will return true if the index
|
||||
// of the operand can be forward declared. This function will
|
||||
// used in the SSA validation stage of the pipeline
|
||||
std::function<bool(unsigned)> spvDbgInfoExtOperandCanBeForwardDeclaredFunction(
|
||||
spv_ext_inst_type_t ext_type, uint32_t key);
|
||||
|
||||
#endif // SOURCE_OPERAND_H_
|
||||
|
|
|
@ -988,6 +988,10 @@ void InstrumentPass::InitializeInstrument() {
|
|||
(void)i;
|
||||
++module_offset;
|
||||
}
|
||||
for (auto& i : module->ext_inst_debuginfo()) {
|
||||
(void)i;
|
||||
++module_offset;
|
||||
}
|
||||
for (auto& i : module->annotations()) {
|
||||
(void)i;
|
||||
++module_offset;
|
||||
|
|
|
@ -187,6 +187,14 @@ class IRContext {
|
|||
inline IteratorRange<Module::inst_iterator> debugs3();
|
||||
inline IteratorRange<Module::const_inst_iterator> debugs3() const;
|
||||
|
||||
// Iterators for debug info instructions (excluding OpLine & OpNoLine)
|
||||
// contained in this module. These are OpExtInst for OpenCL.DebugInfo.100
|
||||
// or DebugInfo extension placed between section 9 and 10.
|
||||
inline Module::inst_iterator ext_inst_debuginfo_begin();
|
||||
inline Module::inst_iterator ext_inst_debuginfo_end();
|
||||
inline IteratorRange<Module::inst_iterator> ext_inst_debuginfo();
|
||||
inline IteratorRange<Module::const_inst_iterator> ext_inst_debuginfo() const;
|
||||
|
||||
// Add |capability| to the module, if it is not already enabled.
|
||||
inline void AddCapability(SpvCapability capability);
|
||||
|
||||
|
@ -215,6 +223,8 @@ class IRContext {
|
|||
// Appends a debug 3 instruction (OpModuleProcessed) to this module.
|
||||
// This is due to decision by the SPIR Working Group, pending publication.
|
||||
inline void AddDebug3Inst(std::unique_ptr<Instruction>&& d);
|
||||
// Appends a OpExtInst for DebugInfo to this module.
|
||||
inline void AddExtInstDebugInfo(std::unique_ptr<Instruction>&& d);
|
||||
// Appends an annotation instruction to this module.
|
||||
inline void AddAnnotationInst(std::unique_ptr<Instruction>&& a);
|
||||
// Appends a type-declaration instruction to this module.
|
||||
|
@ -925,6 +935,23 @@ IteratorRange<Module::const_inst_iterator> IRContext::debugs3() const {
|
|||
return ((const Module*)module_.get())->debugs3();
|
||||
}
|
||||
|
||||
Module::inst_iterator IRContext::ext_inst_debuginfo_begin() {
|
||||
return module()->ext_inst_debuginfo_begin();
|
||||
}
|
||||
|
||||
Module::inst_iterator IRContext::ext_inst_debuginfo_end() {
|
||||
return module()->ext_inst_debuginfo_end();
|
||||
}
|
||||
|
||||
IteratorRange<Module::inst_iterator> IRContext::ext_inst_debuginfo() {
|
||||
return module()->ext_inst_debuginfo();
|
||||
}
|
||||
|
||||
IteratorRange<Module::const_inst_iterator> IRContext::ext_inst_debuginfo()
|
||||
const {
|
||||
return ((const Module*)module_.get())->ext_inst_debuginfo();
|
||||
}
|
||||
|
||||
void IRContext::AddCapability(SpvCapability capability) {
|
||||
if (!get_feature_mgr()->HasCapability(capability)) {
|
||||
std::unique_ptr<Instruction> capability_inst(new Instruction(
|
||||
|
@ -1018,6 +1045,10 @@ void IRContext::AddDebug3Inst(std::unique_ptr<Instruction>&& d) {
|
|||
module()->AddDebug3Inst(std::move(d));
|
||||
}
|
||||
|
||||
void IRContext::AddExtInstDebugInfo(std::unique_ptr<Instruction>&& d) {
|
||||
module()->AddExtInstDebugInfo(std::move(d));
|
||||
}
|
||||
|
||||
void IRContext::AddAnnotationInst(std::unique_ptr<Instruction>&& a) {
|
||||
if (AreAnalysesValid(kAnalysisDecorations)) {
|
||||
get_decoration_mgr()->AddDecoration(a.get());
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
#include <utility>
|
||||
|
||||
#include "DebugInfo.h"
|
||||
#include "OpenCLDebugInfo100.h"
|
||||
#include "source/ext_inst.h"
|
||||
#include "source/opt/log.h"
|
||||
#include "source/opt/reflect.h"
|
||||
|
@ -118,6 +120,9 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
|
|||
(opcode == SpvOpExtInst &&
|
||||
spvExtInstIsNonSemantic(inst->ext_inst_type))) {
|
||||
module_->AddGlobalValue(std::move(spv_inst));
|
||||
} else if (opcode == SpvOpExtInst &&
|
||||
spvExtInstIsDebugInfo(inst->ext_inst_type)) {
|
||||
module_->AddExtInstDebugInfo(std::move(spv_inst));
|
||||
} else {
|
||||
Errorf(consumer_, src, loc,
|
||||
"Unhandled inst type (opcode: %d) found outside function "
|
||||
|
@ -136,6 +141,39 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
|
|||
}
|
||||
function_->AddParameter(std::move(spv_inst));
|
||||
} else {
|
||||
if (opcode == SpvOpExtInst &&
|
||||
spvExtInstIsDebugInfo(inst->ext_inst_type)) {
|
||||
const uint32_t ext_inst_index = inst->words[4];
|
||||
if (inst->ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) {
|
||||
const OpenCLDebugInfo100Instructions ext_inst_key =
|
||||
OpenCLDebugInfo100Instructions(ext_inst_index);
|
||||
if (ext_inst_key != OpenCLDebugInfo100DebugScope &&
|
||||
ext_inst_key != OpenCLDebugInfo100DebugNoScope &&
|
||||
ext_inst_key != OpenCLDebugInfo100DebugDeclare &&
|
||||
ext_inst_key != OpenCLDebugInfo100DebugValue) {
|
||||
Errorf(consumer_, src, loc,
|
||||
"Debug info extension instruction other than DebugScope, "
|
||||
"DebugNoScope, DebugDeclare, and DebugValue found inside "
|
||||
"function",
|
||||
opcode);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const DebugInfoInstructions ext_inst_key =
|
||||
DebugInfoInstructions(ext_inst_index);
|
||||
if (ext_inst_key != DebugInfoDebugScope &&
|
||||
ext_inst_key != DebugInfoDebugNoScope &&
|
||||
ext_inst_key != DebugInfoDebugDeclare &&
|
||||
ext_inst_key != DebugInfoDebugValue) {
|
||||
Errorf(consumer_, src, loc,
|
||||
"Debug info extension instruction other than DebugScope, "
|
||||
"DebugNoScope, DebugDeclare, and DebugValue found inside "
|
||||
"function",
|
||||
opcode);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
block_->AddInstruction(std::move(spv_inst));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,6 +95,7 @@ void Module::ForEachInst(const std::function<void(Instruction*)>& f,
|
|||
DELEGATE(debugs1_);
|
||||
DELEGATE(debugs2_);
|
||||
DELEGATE(debugs3_);
|
||||
DELEGATE(ext_inst_debuginfo_);
|
||||
DELEGATE(annotations_);
|
||||
DELEGATE(types_values_);
|
||||
for (auto& i : functions_) i->ForEachInst(f, run_on_debug_line_insts);
|
||||
|
@ -117,6 +118,7 @@ void Module::ForEachInst(const std::function<void(const Instruction*)>& f,
|
|||
for (auto& i : debugs3_) DELEGATE(i);
|
||||
for (auto& i : annotations_) DELEGATE(i);
|
||||
for (auto& i : types_values_) DELEGATE(i);
|
||||
for (auto& i : ext_inst_debuginfo_) DELEGATE(i);
|
||||
for (auto& i : functions_) {
|
||||
static_cast<const Function*>(i.get())->ForEachInst(f,
|
||||
run_on_debug_line_insts);
|
||||
|
|
|
@ -102,6 +102,10 @@ class Module {
|
|||
// This is due to decision by the SPIR Working Group, pending publication.
|
||||
inline void AddDebug3Inst(std::unique_ptr<Instruction> d);
|
||||
|
||||
// Appends a debug info extension (OpenCL.DebugInfo.100 or DebugInfo)
|
||||
// instruction to this module.
|
||||
inline void AddExtInstDebugInfo(std::unique_ptr<Instruction> d);
|
||||
|
||||
// Appends an annotation instruction to this module.
|
||||
inline void AddAnnotationInst(std::unique_ptr<Instruction> a);
|
||||
|
||||
|
@ -182,6 +186,14 @@ class Module {
|
|||
inline IteratorRange<inst_iterator> debugs3();
|
||||
inline IteratorRange<const_inst_iterator> debugs3() const;
|
||||
|
||||
// Iterators for debug info instructions (excluding OpLine & OpNoLine)
|
||||
// contained in this module. These are OpExtInst for OpenCL.DebugInfo.100
|
||||
// or DebugInfo extension placed between section 9 and 10.
|
||||
inline inst_iterator ext_inst_debuginfo_begin();
|
||||
inline inst_iterator ext_inst_debuginfo_end();
|
||||
inline IteratorRange<inst_iterator> ext_inst_debuginfo();
|
||||
inline IteratorRange<const_inst_iterator> ext_inst_debuginfo() const;
|
||||
|
||||
// Iterators for entry point instructions contained in this module
|
||||
inline IteratorRange<inst_iterator> entry_points();
|
||||
inline IteratorRange<const_inst_iterator> entry_points() const;
|
||||
|
@ -274,6 +286,7 @@ class Module {
|
|||
InstructionList debugs1_;
|
||||
InstructionList debugs2_;
|
||||
InstructionList debugs3_;
|
||||
InstructionList ext_inst_debuginfo_;
|
||||
InstructionList annotations_;
|
||||
// Type declarations, constants, and global variable declarations.
|
||||
InstructionList types_values_;
|
||||
|
@ -323,6 +336,10 @@ inline void Module::AddDebug3Inst(std::unique_ptr<Instruction> d) {
|
|||
debugs3_.push_back(std::move(d));
|
||||
}
|
||||
|
||||
inline void Module::AddExtInstDebugInfo(std::unique_ptr<Instruction> d) {
|
||||
ext_inst_debuginfo_.push_back(std::move(d));
|
||||
}
|
||||
|
||||
inline void Module::AddAnnotationInst(std::unique_ptr<Instruction> a) {
|
||||
annotations_.push_back(std::move(a));
|
||||
}
|
||||
|
@ -403,6 +420,22 @@ inline IteratorRange<Module::const_inst_iterator> Module::debugs3() const {
|
|||
return make_range(debugs3_.begin(), debugs3_.end());
|
||||
}
|
||||
|
||||
inline Module::inst_iterator Module::ext_inst_debuginfo_begin() {
|
||||
return ext_inst_debuginfo_.begin();
|
||||
}
|
||||
inline Module::inst_iterator Module::ext_inst_debuginfo_end() {
|
||||
return ext_inst_debuginfo_.end();
|
||||
}
|
||||
|
||||
inline IteratorRange<Module::inst_iterator> Module::ext_inst_debuginfo() {
|
||||
return make_range(ext_inst_debuginfo_.begin(), ext_inst_debuginfo_.end());
|
||||
}
|
||||
|
||||
inline IteratorRange<Module::const_inst_iterator> Module::ext_inst_debuginfo()
|
||||
const {
|
||||
return make_range(ext_inst_debuginfo_.begin(), ext_inst_debuginfo_.end());
|
||||
}
|
||||
|
||||
inline IteratorRange<Module::inst_iterator> Module::entry_points() {
|
||||
return make_range(entry_points_.begin(), entry_points_.end());
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ Pass::Status StripDebugInfoPass::Process() {
|
|||
|
||||
for (auto& dbg : context()->debugs2()) to_kill.push_back(&dbg);
|
||||
for (auto& dbg : context()->debugs3()) to_kill.push_back(&dbg);
|
||||
for (auto& dbg : context()->ext_inst_debuginfo()) to_kill.push_back(&dbg);
|
||||
|
||||
// OpName must come first, since they may refer to other debug instructions.
|
||||
// If they are after the instructions that refer to, then they will be killed
|
||||
|
|
|
@ -77,6 +77,7 @@ Pass::Status StripReflectInfoPass::Process() {
|
|||
for (auto& dbg : context()->debugs1()) to_remove.push_back(&dbg);
|
||||
for (auto& dbg : context()->debugs2()) to_remove.push_back(&dbg);
|
||||
for (auto& dbg : context()->debugs3()) to_remove.push_back(&dbg);
|
||||
for (auto& dbg : context()->ext_inst_debuginfo()) to_remove.push_back(&dbg);
|
||||
|
||||
// remove any extended inst imports that are non semantic
|
||||
std::unordered_set<uint32_t> non_semantic_sets;
|
||||
|
|
|
@ -52,6 +52,13 @@ RemoveUnreferencedInstructionReductionOpportunityFinder::
|
|||
result.push_back(MakeUnique<RemoveInstructionReductionOpportunity>(&inst));
|
||||
}
|
||||
|
||||
for (auto& inst : context->module()->ext_inst_debuginfo()) {
|
||||
if (context->get_def_use_mgr()->NumUses(&inst) > 0) {
|
||||
continue;
|
||||
}
|
||||
result.push_back(MakeUnique<RemoveInstructionReductionOpportunity>(&inst));
|
||||
}
|
||||
|
||||
for (auto& inst : context->module()->types_values()) {
|
||||
if (context->get_def_use_mgr()->NumUsers(&inst) > 0) {
|
||||
continue;
|
||||
|
|
|
@ -91,6 +91,12 @@ class Instruction {
|
|||
spvExtInstIsNonSemantic(inst_.ext_inst_type);
|
||||
}
|
||||
|
||||
/// True if this is an OpExtInst for debug info extension.
|
||||
bool IsDebugInfo() const {
|
||||
return opcode() == SpvOp::SpvOpExtInst &&
|
||||
spvExtInstIsDebugInfo(inst_.ext_inst_type);
|
||||
}
|
||||
|
||||
// Casts the words belonging to the operand under |index| to |T| and returns.
|
||||
template <typename T>
|
||||
T GetOperandAs(size_t index) const {
|
||||
|
|
|
@ -54,6 +54,16 @@ spv_result_t ValidateAdjacency(ValidationState_t& _) {
|
|||
adjacency_status =
|
||||
adjacency_status == IN_NEW_FUNCTION ? IN_ENTRY_BLOCK : PHI_VALID;
|
||||
break;
|
||||
case SpvOpExtInst:
|
||||
// If it is a debug info instruction, we do not change the status to
|
||||
// allow debug info instructions before OpVariable in a function.
|
||||
// TODO(https://gitlab.khronos.org/spirv/SPIR-V/issues/533): We need
|
||||
// to discuss the location of DebugScope, DebugNoScope, DebugDeclare,
|
||||
// and DebugValue.
|
||||
if (!spvExtInstIsDebugInfo(inst.ext_inst_type())) {
|
||||
adjacency_status = PHI_AND_VAR_INVALID;
|
||||
}
|
||||
break;
|
||||
case SpvOpPhi:
|
||||
if (adjacency_status != PHI_VALID) {
|
||||
return _.diag(SPV_ERROR_INVALID_DATA, &inst)
|
||||
|
|
|
@ -88,7 +88,7 @@ spv_result_t ValidateFunction(ValidationState_t& _, const Instruction* inst) {
|
|||
const auto* use = pair.first;
|
||||
if (std::find(acceptable.begin(), acceptable.end(), use->opcode()) ==
|
||||
acceptable.end() &&
|
||||
!use->IsNonSemantic()) {
|
||||
!use->IsNonSemantic() && !use->IsDebugInfo()) {
|
||||
return _.diag(SPV_ERROR_INVALID_ID, use)
|
||||
<< "Invalid use of function result id " << _.getIdName(inst->id())
|
||||
<< ".";
|
||||
|
|
|
@ -131,7 +131,11 @@ spv_result_t CheckIdDefinitionDominateUse(ValidationState_t& _) {
|
|||
// instruction operand's ID can be forward referenced.
|
||||
spv_result_t IdPass(ValidationState_t& _, Instruction* inst) {
|
||||
auto can_have_forward_declared_ids =
|
||||
spvOperandCanBeForwardDeclaredFunction(inst->opcode());
|
||||
inst->opcode() == SpvOpExtInst &&
|
||||
spvExtInstIsDebugInfo(inst->ext_inst_type())
|
||||
? spvDbgInfoExtOperandCanBeForwardDeclaredFunction(
|
||||
inst->ext_inst_type(), inst->word(4))
|
||||
: spvOperandCanBeForwardDeclaredFunction(inst->opcode());
|
||||
|
||||
// Keep track of a result id defined by this instruction. 0 means it
|
||||
// does not define an id.
|
||||
|
|
|
@ -14,15 +14,16 @@
|
|||
|
||||
// Source code for logical layout validation as described in section 2.4
|
||||
|
||||
#include "source/val/validate.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "DebugInfo.h"
|
||||
#include "OpenCLDebugInfo100.h"
|
||||
#include "source/diagnostic.h"
|
||||
#include "source/opcode.h"
|
||||
#include "source/operand.h"
|
||||
#include "source/val/function.h"
|
||||
#include "source/val/instruction.h"
|
||||
#include "source/val/validate.h"
|
||||
#include "source/val/validation_state.h"
|
||||
|
||||
namespace spvtools {
|
||||
|
@ -46,6 +47,53 @@ spv_result_t ModuleScopedInstructions(ValidationState_t& _,
|
|||
<< "Non-semantic OpExtInst must not appear before types "
|
||||
<< "section";
|
||||
}
|
||||
} else if (spvExtInstIsDebugInfo(inst->ext_inst_type())) {
|
||||
const uint32_t ext_inst_index = inst->word(4);
|
||||
bool local_debug_info = false;
|
||||
if (inst->ext_inst_type() == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) {
|
||||
const OpenCLDebugInfo100Instructions ext_inst_key =
|
||||
OpenCLDebugInfo100Instructions(ext_inst_index);
|
||||
if (ext_inst_key == OpenCLDebugInfo100DebugScope ||
|
||||
ext_inst_key == OpenCLDebugInfo100DebugNoScope ||
|
||||
ext_inst_key == OpenCLDebugInfo100DebugDeclare ||
|
||||
ext_inst_key == OpenCLDebugInfo100DebugValue) {
|
||||
local_debug_info = true;
|
||||
}
|
||||
} else {
|
||||
const DebugInfoInstructions ext_inst_key =
|
||||
DebugInfoInstructions(ext_inst_index);
|
||||
if (ext_inst_key == DebugInfoDebugScope ||
|
||||
ext_inst_key == DebugInfoDebugNoScope ||
|
||||
ext_inst_key == DebugInfoDebugDeclare ||
|
||||
ext_inst_key == DebugInfoDebugValue) {
|
||||
local_debug_info = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (local_debug_info) {
|
||||
if (_.in_function_body() == false) {
|
||||
// DebugScope, DebugNoScope, DebugDeclare, DebugValue must
|
||||
// appear in a function body.
|
||||
return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
|
||||
<< "DebugScope, DebugNoScope, DebugDeclare, DebugValue "
|
||||
<< "of debug info extension must appear in a function "
|
||||
<< "body";
|
||||
}
|
||||
} else {
|
||||
// Debug info extinst opcodes other than DebugScope, DebugNoScope,
|
||||
// DebugDeclare, DebugValue must be placed between section 9 (types,
|
||||
// constants, global variables) and section 10 (function
|
||||
// declarations).
|
||||
if (_.current_layout_section() < kLayoutTypes ||
|
||||
_.current_layout_section() >= kLayoutFunctionDeclarations) {
|
||||
return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
|
||||
<< "Debug info extension instructions other than "
|
||||
<< "DebugScope, DebugNoScope, DebugDeclare, DebugValue "
|
||||
<< "must appear between section 9 (types, constants, "
|
||||
<< "global variables) and section 10 (function "
|
||||
<< "declarations)";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// otherwise they must be used in a block
|
||||
if (_.current_layout_section() < kLayoutFunctionDefinitions) {
|
||||
|
@ -182,6 +230,53 @@ spv_result_t FunctionScopedInstructions(ValidationState_t& _,
|
|||
<< "Non-semantic OpExtInst within function definition must "
|
||||
"appear in a block";
|
||||
}
|
||||
} else if (spvExtInstIsDebugInfo(inst->ext_inst_type())) {
|
||||
const uint32_t ext_inst_index = inst->word(4);
|
||||
bool local_debug_info = false;
|
||||
if (inst->ext_inst_type() == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) {
|
||||
const OpenCLDebugInfo100Instructions ext_inst_key =
|
||||
OpenCLDebugInfo100Instructions(ext_inst_index);
|
||||
if (ext_inst_key == OpenCLDebugInfo100DebugScope ||
|
||||
ext_inst_key == OpenCLDebugInfo100DebugNoScope ||
|
||||
ext_inst_key == OpenCLDebugInfo100DebugDeclare ||
|
||||
ext_inst_key == OpenCLDebugInfo100DebugValue) {
|
||||
local_debug_info = true;
|
||||
}
|
||||
} else {
|
||||
const DebugInfoInstructions ext_inst_key =
|
||||
DebugInfoInstructions(ext_inst_index);
|
||||
if (ext_inst_key == DebugInfoDebugScope ||
|
||||
ext_inst_key == DebugInfoDebugNoScope ||
|
||||
ext_inst_key == DebugInfoDebugDeclare ||
|
||||
ext_inst_key == DebugInfoDebugValue) {
|
||||
local_debug_info = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (local_debug_info) {
|
||||
if (_.in_function_body() == false) {
|
||||
// DebugScope, DebugNoScope, DebugDeclare, DebugValue must
|
||||
// appear in a function body.
|
||||
return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
|
||||
<< "DebugScope, DebugNoScope, DebugDeclare, DebugValue "
|
||||
<< "of debug info extension must appear in a function "
|
||||
<< "body";
|
||||
}
|
||||
} else {
|
||||
// Debug info extinst opcodes other than DebugScope, DebugNoScope,
|
||||
// DebugDeclare, DebugValue must be placed between section 9 (types,
|
||||
// constants, global variables) and section 10 (function
|
||||
// declarations).
|
||||
if (_.current_layout_section() < kLayoutTypes ||
|
||||
_.current_layout_section() >= kLayoutFunctionDeclarations) {
|
||||
return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
|
||||
<< "Debug info extension instructions other than "
|
||||
<< "DebugScope, DebugNoScope, DebugDeclare, DebugValue "
|
||||
<< "must appear between section 9 (types, constants, "
|
||||
<< "global variables) and section 10 (function "
|
||||
<< "declarations)";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// otherwise they must be used in a block
|
||||
if (_.in_block() == false) {
|
||||
|
|
|
@ -129,6 +129,621 @@ TEST(IrBuilder, KeepLineDebugInfo) {
|
|||
// clang-format on
|
||||
}
|
||||
|
||||
TEST(IrBuilder, ConsumeDebugInfoInst) {
|
||||
// /* HLSL */
|
||||
//
|
||||
// struct VS_OUTPUT {
|
||||
// float4 pos : SV_POSITION;
|
||||
// float4 color : COLOR;
|
||||
// };
|
||||
//
|
||||
// VS_OUTPUT main(float4 pos : POSITION,
|
||||
// float4 color : COLOR) {
|
||||
// VS_OUTPUT vout;
|
||||
// vout.pos = pos;
|
||||
// vout.color = color;
|
||||
// return vout;
|
||||
// }
|
||||
DoRoundTripCheck(R"(OpCapability Shader
|
||||
%1 = OpExtInstImport "OpenCL.DebugInfo.100"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Vertex %main "main" %pos %color %gl_Position %out_var_COLOR
|
||||
%7 = OpString "simple_vs.hlsl"
|
||||
%8 = OpString "#line 1 \"simple_vs.hlsl\"
|
||||
struct VS_OUTPUT {
|
||||
float4 pos : SV_POSITION;
|
||||
float4 color : COLOR;
|
||||
};
|
||||
|
||||
VS_OUTPUT main(float4 pos : POSITION,
|
||||
float4 color : COLOR) {
|
||||
VS_OUTPUT vout;
|
||||
vout.pos = pos;
|
||||
vout.color = color;
|
||||
return vout;
|
||||
}
|
||||
"
|
||||
OpSource HLSL 600 %7 "#line 1 \"simple_vs.hlsl\"
|
||||
struct VS_OUTPUT {
|
||||
float4 pos : SV_POSITION;
|
||||
float4 color : COLOR;
|
||||
};
|
||||
|
||||
VS_OUTPUT main(float4 pos : POSITION,
|
||||
float4 color : COLOR) {
|
||||
VS_OUTPUT vout;
|
||||
vout.pos = pos;
|
||||
vout.color = color;
|
||||
return vout;
|
||||
}
|
||||
"
|
||||
%9 = OpString "struct VS_OUTPUT"
|
||||
%10 = OpString "float"
|
||||
%11 = OpString "pos : SV_POSITION"
|
||||
%12 = OpString "color : COLOR"
|
||||
%13 = OpString "VS_OUTPUT"
|
||||
%14 = OpString "main"
|
||||
%15 = OpString "VS_OUTPUT_main_v4f_v4f"
|
||||
%16 = OpString "pos : POSITION"
|
||||
%17 = OpString "color : COLOR"
|
||||
%18 = OpString "vout"
|
||||
OpName %out_var_COLOR "out.var.COLOR"
|
||||
OpName %main "main"
|
||||
OpName %VS_OUTPUT "VS_OUTPUT"
|
||||
OpMemberName %VS_OUTPUT 0 "pos"
|
||||
OpMemberName %VS_OUTPUT 1 "color"
|
||||
OpName %pos "pos"
|
||||
OpName %color "color"
|
||||
OpName %vout "vout"
|
||||
OpDecorate %gl_Position BuiltIn Position
|
||||
OpDecorate %pos Location 0
|
||||
OpDecorate %color Location 1
|
||||
OpDecorate %out_var_COLOR Location 0
|
||||
%int = OpTypeInt 32 1
|
||||
%int_0 = OpConstant %int 0
|
||||
%int_1 = OpConstant %int 1
|
||||
%int_32 = OpConstant %int 32
|
||||
%int_128 = OpConstant %int 128
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%void = OpTypeVoid
|
||||
%31 = OpTypeFunction %void
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%VS_OUTPUT = OpTypeStruct %v4float %v4float
|
||||
%_ptr_Function_VS_OUTPUT = OpTypePointer Function %VS_OUTPUT
|
||||
OpLine %7 6 23
|
||||
%pos = OpVariable %_ptr_Input_v4float Input
|
||||
OpLine %7 7 23
|
||||
%color = OpVariable %_ptr_Input_v4float Input
|
||||
OpLine %7 2 16
|
||||
%gl_Position = OpVariable %_ptr_Output_v4float Output
|
||||
OpLine %7 3 18
|
||||
%out_var_COLOR = OpVariable %_ptr_Output_v4float Output
|
||||
%34 = OpExtInst %void %1 DebugSource %7 %8
|
||||
%35 = OpExtInst %void %1 DebugCompilationUnit 2 4 %34 HLSL
|
||||
%36 = OpExtInst %void %1 DebugTypeComposite %9 Structure %34 1 1 %35 %13 %int_128 FlagIsProtected|FlagIsPrivate %37 %38
|
||||
%39 = OpExtInst %void %1 DebugTypeBasic %10 %int_32 Float
|
||||
%40 = OpExtInst %void %1 DebugTypeVector %39 4
|
||||
%37 = OpExtInst %void %1 DebugTypeMember %11 %40 %34 2 3 %36 %int_0 %int_128 FlagIsProtected|FlagIsPrivate
|
||||
%38 = OpExtInst %void %1 DebugTypeMember %12 %40 %34 3 3 %36 %int_128 %int_128 FlagIsProtected|FlagIsPrivate
|
||||
%41 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %36 %40 %40
|
||||
%42 = OpExtInst %void %1 DebugExpression
|
||||
%43 = OpExtInst %void %1 DebugFunction %14 %41 %34 6 1 %35 %15 FlagIsProtected|FlagIsPrivate 7 %main
|
||||
%44 = OpExtInst %void %1 DebugLocalVariable %16 %40 %34 6 16 %43 FlagIsLocal 0
|
||||
%45 = OpExtInst %void %1 DebugLocalVariable %17 %40 %34 7 16 %43 FlagIsLocal 1
|
||||
%46 = OpExtInst %void %1 DebugLocalVariable %18 %36 %34 8 3 %43 FlagIsLocal
|
||||
%47 = OpExtInst %void %1 DebugDeclare %44 %pos %42
|
||||
%48 = OpExtInst %void %1 DebugDeclare %45 %color %42
|
||||
OpLine %7 6 1
|
||||
%main = OpFunction %void None %31
|
||||
%49 = OpLabel
|
||||
%50 = OpExtInst %void %1 DebugScope %43
|
||||
OpLine %7 8 13
|
||||
%vout = OpVariable %_ptr_Function_VS_OUTPUT Function
|
||||
%51 = OpExtInst %void %1 DebugDeclare %46 %vout %42
|
||||
OpLine %7 9 14
|
||||
%52 = OpLoad %v4float %pos
|
||||
OpLine %7 9 3
|
||||
%53 = OpAccessChain %_ptr_Function_v4float %vout %int_0
|
||||
%54 = OpExtInst %void %1 DebugValue %46 %53 %42 %int_0
|
||||
OpStore %53 %52
|
||||
OpLine %7 10 16
|
||||
%55 = OpLoad %v4float %color
|
||||
OpLine %7 10 3
|
||||
%56 = OpAccessChain %_ptr_Function_v4float %vout %int_1
|
||||
%57 = OpExtInst %void %1 DebugValue %46 %56 %42 %int_1
|
||||
OpStore %56 %55
|
||||
OpLine %7 11 10
|
||||
%58 = OpLoad %VS_OUTPUT %vout
|
||||
OpLine %7 11 3
|
||||
%59 = OpCompositeExtract %v4float %58 0
|
||||
OpStore %gl_Position %59
|
||||
%60 = OpCompositeExtract %v4float %58 1
|
||||
OpStore %out_var_COLOR %60
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(IrBuilder, ConsumeDebugInfoLexicalScopeInst) {
|
||||
// /* HLSL */
|
||||
//
|
||||
// float4 func2(float arg2) { // func2_block
|
||||
// return float4(arg2, 0, 0, 0);
|
||||
// }
|
||||
//
|
||||
// float4 func1(float arg1) { // func1_block
|
||||
// if (arg1 > 1) { // if_true_block
|
||||
// return float4(0, 0, 0, 0);
|
||||
// }
|
||||
// return func2(arg1); // if_merge_block
|
||||
// }
|
||||
//
|
||||
// float4 main(float pos : POSITION) : SV_POSITION { // main
|
||||
// return func1(pos);
|
||||
// }
|
||||
DoRoundTripCheck(R"(OpCapability Shader
|
||||
%1 = OpExtInstImport "OpenCL.DebugInfo.100"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Vertex %main "main" %pos %gl_Position
|
||||
%5 = OpString "block/block.hlsl"
|
||||
%6 = OpString "#line 1 \"block/block.hlsl\"
|
||||
float4 func2(float arg2) {
|
||||
return float4(arg2, 0, 0, 0);
|
||||
}
|
||||
|
||||
float4 func1(float arg1) {
|
||||
if (arg1 > 1) {
|
||||
return float4(0, 0, 0, 0);
|
||||
}
|
||||
return func2(arg1);
|
||||
}
|
||||
|
||||
float4 main(float pos : POSITION) : SV_POSITION {
|
||||
return func1(pos);
|
||||
}
|
||||
"
|
||||
OpSource HLSL 600 %5 "#line 1 \"block/block.hlsl\"
|
||||
float4 func2(float arg2) {
|
||||
return float4(arg2, 0, 0, 0);
|
||||
}
|
||||
|
||||
float4 func1(float arg1) {
|
||||
if (arg1 > 1) {
|
||||
return float4(0, 0, 0, 0);
|
||||
}
|
||||
return func2(arg1);
|
||||
}
|
||||
|
||||
float4 main(float pos : POSITION) : SV_POSITION {
|
||||
return func1(pos);
|
||||
}
|
||||
"
|
||||
%7 = OpString "float"
|
||||
%8 = OpString "main"
|
||||
%9 = OpString "v4f_main_f"
|
||||
%10 = OpString "v4f_func1_f"
|
||||
%11 = OpString "v4f_func2_f"
|
||||
%12 = OpString "pos : POSITION"
|
||||
%13 = OpString "func1"
|
||||
%14 = OpString "func2"
|
||||
OpName %main "main"
|
||||
OpName %pos "pos"
|
||||
OpName %bb_entry "bb.entry"
|
||||
OpName %param_var_arg1 "param.var.arg1"
|
||||
OpName %func1 "func1"
|
||||
OpName %arg1 "arg1"
|
||||
OpName %bb_entry_0 "bb.entry"
|
||||
OpName %param_var_arg2 "param.var.arg2"
|
||||
OpName %if_true "if.true"
|
||||
OpName %if_merge "if.merge"
|
||||
OpName %func2 "func2"
|
||||
OpName %arg2 "arg2"
|
||||
OpName %bb_entry_1 "bb.entry"
|
||||
OpDecorate %gl_Position BuiltIn Position
|
||||
OpDecorate %pos Location 0
|
||||
%float = OpTypeFloat 32
|
||||
%int = OpTypeInt 32 1
|
||||
%float_1 = OpConstant %float 1
|
||||
%float_0 = OpConstant %float 0
|
||||
%int_32 = OpConstant %int 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%32 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
|
||||
%_ptr_Input_float = OpTypePointer Input %float
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%void = OpTypeVoid
|
||||
%36 = OpTypeFunction %void
|
||||
%_ptr_Function_float = OpTypePointer Function %float
|
||||
%38 = OpTypeFunction %v4float %_ptr_Function_float
|
||||
%bool = OpTypeBool
|
||||
OpLine %5 12 25
|
||||
%pos = OpVariable %_ptr_Input_float Input
|
||||
OpLine %5 12 37
|
||||
%gl_Position = OpVariable %_ptr_Output_v4float Output
|
||||
%40 = OpExtInst %void %1 DebugSource %5 %6
|
||||
%41 = OpExtInst %void %1 DebugCompilationUnit 2 4 %40 HLSL
|
||||
%42 = OpExtInst %void %1 DebugTypeBasic %7 %int_32 Float
|
||||
%43 = OpExtInst %void %1 DebugTypeVector %42 4
|
||||
%44 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %43 %42
|
||||
%45 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %43 %42
|
||||
%46 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %43 %42
|
||||
%47 = OpExtInst %void %1 DebugFunction %8 %44 %40 12 1 %41 %9 FlagIsProtected|FlagIsPrivate 13 %main
|
||||
%48 = OpExtInst %void %1 DebugFunction %13 %45 %40 5 1 %41 %10 FlagIsProtected|FlagIsPrivate 13 %func1
|
||||
%49 = OpExtInst %void %1 DebugFunction %14 %46 %40 1 1 %41 %11 FlagIsProtected|FlagIsPrivate 13 %func2
|
||||
%50 = OpExtInst %void %1 DebugLexicalBlock %40 6 17 %48
|
||||
%51 = OpExtInst %void %1 DebugLexicalBlock %40 9 3 %48
|
||||
OpLine %5 12 1
|
||||
%main = OpFunction %void None %36
|
||||
%bb_entry = OpLabel
|
||||
%52 = OpExtInst %void %1 DebugScope %47
|
||||
OpLine %5 13 16
|
||||
%param_var_arg1 = OpVariable %_ptr_Function_float Function
|
||||
%53 = OpLoad %float %pos
|
||||
OpStore %param_var_arg1 %53
|
||||
OpLine %5 13 10
|
||||
%54 = OpFunctionCall %v4float %func1 %param_var_arg1
|
||||
OpLine %5 13 3
|
||||
OpStore %gl_Position %54
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
OpLine %5 5 1
|
||||
%func1 = OpFunction %v4float None %38
|
||||
OpLine %5 5 20
|
||||
%arg1 = OpFunctionParameter %_ptr_Function_float
|
||||
%bb_entry_0 = OpLabel
|
||||
%55 = OpExtInst %void %1 DebugScope %48
|
||||
OpLine %5 9 16
|
||||
%param_var_arg2 = OpVariable %_ptr_Function_float Function
|
||||
OpLine %5 6 7
|
||||
%56 = OpLoad %float %arg1
|
||||
OpLine %5 6 12
|
||||
%57 = OpFOrdGreaterThan %bool %56 %float_1
|
||||
OpLine %5 6 17
|
||||
OpSelectionMerge %if_merge None
|
||||
OpBranchConditional %57 %if_true %if_merge
|
||||
%if_true = OpLabel
|
||||
%58 = OpExtInst %void %1 DebugScope %50
|
||||
OpLine %5 7 5
|
||||
OpReturnValue %32
|
||||
%if_merge = OpLabel
|
||||
%59 = OpExtInst %void %1 DebugScope %51
|
||||
OpLine %5 9 16
|
||||
%60 = OpLoad %float %arg1
|
||||
OpStore %param_var_arg2 %60
|
||||
OpLine %5 9 10
|
||||
%61 = OpFunctionCall %v4float %func2 %param_var_arg2
|
||||
OpLine %5 9 3
|
||||
OpReturnValue %61
|
||||
OpFunctionEnd
|
||||
OpLine %5 1 1
|
||||
%func2 = OpFunction %v4float None %38
|
||||
OpLine %5 1 20
|
||||
%arg2 = OpFunctionParameter %_ptr_Function_float
|
||||
%bb_entry_1 = OpLabel
|
||||
%62 = OpExtInst %void %1 DebugScope %49
|
||||
OpLine %5 2 17
|
||||
%63 = OpLoad %float %arg2
|
||||
%64 = OpCompositeConstruct %v4float %63 %float_0 %float_0 %float_0
|
||||
OpLine %5 2 3
|
||||
OpReturnValue %64
|
||||
OpFunctionEnd
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(IrBuilder, ConsumeDebugInlinedAt) {
|
||||
// /* HLSL */
|
||||
//
|
||||
// float4 func2(float arg2) { // func2_block
|
||||
// return float4(arg2, 0, 0, 0);
|
||||
// }
|
||||
//
|
||||
// float4 func1(float arg1) { // func1_block
|
||||
// if (arg1 > 1) { // if_true_block
|
||||
// return float4(0, 0, 0, 0);
|
||||
// }
|
||||
// return func2(arg1); // if_merge_block
|
||||
// }
|
||||
//
|
||||
// float4 main(float pos : POSITION) : SV_POSITION { // main
|
||||
// return func1(pos);
|
||||
// }
|
||||
//
|
||||
// TODO(https://gitlab.khronos.org/spirv/SPIR-V/issues/533): In the following
|
||||
// SPIRV code, we use DebugInfoNone to reference opted-out function from
|
||||
// DebugFunction similar to opted-out global variable for DebugGlobalVariable,
|
||||
// but this is not a part of the spec yet. We are still in discussion and we
|
||||
// must correct it if our decision is different.
|
||||
DoRoundTripCheck(R"(OpCapability Shader
|
||||
%1 = OpExtInstImport "OpenCL.DebugInfo.100"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Vertex %main "main" %pos %gl_Position
|
||||
%5 = OpString "block/block.hlsl"
|
||||
%6 = OpString "#line 1 \"block/block.hlsl\"
|
||||
float4 func2(float arg2) {
|
||||
return float4(arg2, 0, 0, 0);
|
||||
}
|
||||
|
||||
float4 func1(float arg1) {
|
||||
if (arg1 > 1) {
|
||||
return float4(0, 0, 0, 0);
|
||||
}
|
||||
return func2(arg1);
|
||||
}
|
||||
|
||||
float4 main(float pos : POSITION) : SV_POSITION {
|
||||
return func1(pos);
|
||||
}
|
||||
"
|
||||
OpSource HLSL 600 %5 "#line 1 \"block/block.hlsl\"
|
||||
float4 func2(float arg2) {
|
||||
return float4(arg2, 0, 0, 0);
|
||||
}
|
||||
|
||||
float4 func1(float arg1) {
|
||||
if (arg1 > 1) {
|
||||
return float4(0, 0, 0, 0);
|
||||
}
|
||||
return func2(arg1);
|
||||
}
|
||||
|
||||
float4 main(float pos : POSITION) : SV_POSITION {
|
||||
return func1(pos);
|
||||
}
|
||||
"
|
||||
%7 = OpString "float"
|
||||
%8 = OpString "main"
|
||||
%9 = OpString "v4f_main_f"
|
||||
%10 = OpString "v4f_func1_f"
|
||||
%11 = OpString "v4f_func2_f"
|
||||
%12 = OpString "pos : POSITION"
|
||||
%13 = OpString "func1"
|
||||
%14 = OpString "func2"
|
||||
OpName %main "main"
|
||||
OpName %pos "pos"
|
||||
OpName %bb_entry "bb.entry"
|
||||
OpName %if_true "if.true"
|
||||
OpName %if_merge "if.merge"
|
||||
OpDecorate %gl_Position BuiltIn Position
|
||||
OpDecorate %pos Location 0
|
||||
%float = OpTypeFloat 32
|
||||
%int = OpTypeInt 32 1
|
||||
%float_1 = OpConstant %float 1
|
||||
%float_0 = OpConstant %float 0
|
||||
%int_32 = OpConstant %int 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%24 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
|
||||
%_ptr_Input_float = OpTypePointer Input %float
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%void = OpTypeVoid
|
||||
%28 = OpTypeFunction %void
|
||||
%_ptr_Function_float = OpTypePointer Function %float
|
||||
%30 = OpTypeFunction %v4float %_ptr_Function_float
|
||||
%bool = OpTypeBool
|
||||
OpLine %5 12 25
|
||||
%pos = OpVariable %_ptr_Input_float Input
|
||||
OpLine %5 12 37
|
||||
%gl_Position = OpVariable %_ptr_Output_v4float Output
|
||||
%32 = OpExtInst %void %1 DebugInfoNone
|
||||
%33 = OpExtInst %void %1 DebugSource %5 %6
|
||||
%34 = OpExtInst %void %1 DebugCompilationUnit 2 4 %33 HLSL
|
||||
%35 = OpExtInst %void %1 DebugTypeBasic %7 %int_32 Float
|
||||
%36 = OpExtInst %void %1 DebugTypeVector %35 4
|
||||
%37 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %36 %35
|
||||
%38 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %36 %35
|
||||
%39 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %36 %35
|
||||
%40 = OpExtInst %void %1 DebugFunction %8 %37 %33 12 1 %34 %9 FlagIsProtected|FlagIsPrivate 13 %main
|
||||
%41 = OpExtInst %void %1 DebugFunction %13 %38 %33 5 1 %34 %10 FlagIsProtected|FlagIsPrivate 13 %32
|
||||
%42 = OpExtInst %void %1 DebugFunction %14 %39 %33 1 1 %34 %11 FlagIsProtected|FlagIsPrivate 13 %32
|
||||
%43 = OpExtInst %void %1 DebugLexicalBlock %33 12 49 %40
|
||||
%44 = OpExtInst %void %1 DebugLexicalBlock %33 5 26 %41
|
||||
%45 = OpExtInst %void %1 DebugLexicalBlock %33 1 26 %42
|
||||
%46 = OpExtInst %void %1 DebugLexicalBlock %33 6 17 %44
|
||||
%47 = OpExtInst %void %1 DebugLexicalBlock %33 9 3 %44
|
||||
%48 = OpExtInst %void %1 DebugInlinedAt 9 %47
|
||||
%49 = OpExtInst %void %1 DebugInlinedAt 13 %43
|
||||
%50 = OpExtInst %void %1 DebugInlinedAt 13 %43 %48
|
||||
OpLine %5 12 1
|
||||
%main = OpFunction %void None %28
|
||||
%bb_entry = OpLabel
|
||||
%51 = OpExtInst %void %1 DebugScope %44 %49
|
||||
OpLine %5 6 7
|
||||
%52 = OpLoad %float %pos
|
||||
OpLine %5 6 12
|
||||
%53 = OpFOrdGreaterThan %bool %52 %float_1
|
||||
OpLine %5 6 17
|
||||
OpSelectionMerge %if_merge None
|
||||
OpBranchConditional %53 %if_true %if_merge
|
||||
%if_true = OpLabel
|
||||
%54 = OpExtInst %void %1 DebugScope %46 %49
|
||||
OpLine %5 7 5
|
||||
OpStore %gl_Position %24
|
||||
OpReturn
|
||||
%if_merge = OpLabel
|
||||
%55 = OpExtInst %void %1 DebugScope %45 %50
|
||||
OpLine %5 2 17
|
||||
%56 = OpLoad %float %pos
|
||||
OpLine %5 2 10
|
||||
%57 = OpCompositeConstruct %v4float %56 %float_0 %float_0 %float_0
|
||||
%58 = OpExtInst %void %1 DebugScope %43
|
||||
OpLine %5 13 3
|
||||
OpStore %gl_Position %57
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(IrBuilder, DebugInfoInstInFunctionOutOfBlock) {
|
||||
// /* HLSL */
|
||||
//
|
||||
// float4 func2(float arg2) { // func2_block
|
||||
// return float4(arg2, 0, 0, 0);
|
||||
// }
|
||||
//
|
||||
// float4 func1(float arg1) { // func1_block
|
||||
// if (arg1 > 1) { // if_true_block
|
||||
// return float4(0, 0, 0, 0);
|
||||
// }
|
||||
// return func2(arg1); // if_merge_block
|
||||
// }
|
||||
//
|
||||
// float4 main(float pos : POSITION) : SV_POSITION { // main
|
||||
// return func1(pos);
|
||||
// }
|
||||
const std::string text = R"(OpCapability Shader
|
||||
%1 = OpExtInstImport "OpenCL.DebugInfo.100"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Vertex %main "main" %pos %gl_Position
|
||||
%5 = OpString "block/block.hlsl"
|
||||
%6 = OpString "#line 1 \"block/block.hlsl\"
|
||||
float4 func2(float arg2) {
|
||||
return float4(arg2, 0, 0, 0);
|
||||
}
|
||||
|
||||
float4 func1(float arg1) {
|
||||
if (arg1 > 1) {
|
||||
return float4(0, 0, 0, 0);
|
||||
}
|
||||
return func2(arg1);
|
||||
}
|
||||
|
||||
float4 main(float pos : POSITION) : SV_POSITION {
|
||||
return func1(pos);
|
||||
}
|
||||
"
|
||||
OpSource HLSL 600 %5 "#line 1 \"block/block.hlsl\"
|
||||
float4 func2(float arg2) {
|
||||
return float4(arg2, 0, 0, 0);
|
||||
}
|
||||
|
||||
float4 func1(float arg1) {
|
||||
if (arg1 > 1) {
|
||||
return float4(0, 0, 0, 0);
|
||||
}
|
||||
return func2(arg1);
|
||||
}
|
||||
|
||||
float4 main(float pos : POSITION) : SV_POSITION {
|
||||
return func1(pos);
|
||||
}
|
||||
"
|
||||
%7 = OpString "float"
|
||||
%8 = OpString "main"
|
||||
%9 = OpString "v4f_main_f"
|
||||
%10 = OpString "v4f_func1_f"
|
||||
%11 = OpString "v4f_func2_f"
|
||||
%12 = OpString "pos : POSITION"
|
||||
%13 = OpString "func1"
|
||||
%14 = OpString "func2"
|
||||
OpName %main "main"
|
||||
OpName %pos "pos"
|
||||
OpName %bb_entry "bb.entry"
|
||||
OpName %param_var_arg1 "param.var.arg1"
|
||||
OpName %func1 "func1"
|
||||
OpName %arg1 "arg1"
|
||||
OpName %bb_entry_0 "bb.entry"
|
||||
OpName %param_var_arg2 "param.var.arg2"
|
||||
OpName %if_true "if.true"
|
||||
OpName %if_merge "if.merge"
|
||||
OpName %func2 "func2"
|
||||
OpName %arg2 "arg2"
|
||||
OpName %bb_entry_1 "bb.entry"
|
||||
OpDecorate %gl_Position BuiltIn Position
|
||||
OpDecorate %pos Location 0
|
||||
%float = OpTypeFloat 32
|
||||
%int = OpTypeInt 32 1
|
||||
%float_1 = OpConstant %float 1
|
||||
%float_0 = OpConstant %float 0
|
||||
%int_32 = OpConstant %int 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%32 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
|
||||
%_ptr_Input_float = OpTypePointer Input %float
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%void = OpTypeVoid
|
||||
%36 = OpTypeFunction %void
|
||||
%_ptr_Function_float = OpTypePointer Function %float
|
||||
%38 = OpTypeFunction %v4float %_ptr_Function_float
|
||||
%bool = OpTypeBool
|
||||
OpLine %5 12 25
|
||||
%pos = OpVariable %_ptr_Input_float Input
|
||||
OpLine %5 12 37
|
||||
%gl_Position = OpVariable %_ptr_Output_v4float Output
|
||||
%40 = OpExtInst %void %1 DebugSource %5 %6
|
||||
%41 = OpExtInst %void %1 DebugCompilationUnit 2 4 %40 HLSL
|
||||
%42 = OpExtInst %void %1 DebugTypeBasic %7 %int_32 Float
|
||||
%43 = OpExtInst %void %1 DebugTypeVector %42 4
|
||||
%44 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %43 %42
|
||||
%45 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %43 %42
|
||||
%46 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %43 %42
|
||||
%47 = OpExtInst %void %1 DebugFunction %8 %44 %40 12 1 %41 %9 FlagIsProtected|FlagIsPrivate 13 %main
|
||||
%48 = OpExtInst %void %1 DebugFunction %13 %45 %40 5 1 %41 %10 FlagIsProtected|FlagIsPrivate 13 %func1
|
||||
%49 = OpExtInst %void %1 DebugFunction %14 %46 %40 1 1 %41 %11 FlagIsProtected|FlagIsPrivate 13 %func2
|
||||
%50 = OpExtInst %void %1 DebugLexicalBlock %40 6 17 %48
|
||||
%51 = OpExtInst %void %1 DebugLexicalBlock %40 9 3 %48
|
||||
OpLine %5 12 1
|
||||
%main = OpFunction %void None %36
|
||||
%52 = OpExtInst %void %1 DebugScope %47
|
||||
%bb_entry = OpLabel
|
||||
OpLine %5 13 16
|
||||
%param_var_arg1 = OpVariable %_ptr_Function_float Function
|
||||
%53 = OpLoad %float %pos
|
||||
OpStore %param_var_arg1 %53
|
||||
OpLine %5 13 10
|
||||
%54 = OpFunctionCall %v4float %func1 %param_var_arg1
|
||||
OpLine %5 13 3
|
||||
OpStore %gl_Position %54
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
OpLine %5 5 1
|
||||
%func1 = OpFunction %v4float None %38
|
||||
OpLine %5 5 20
|
||||
%arg1 = OpFunctionParameter %_ptr_Function_float
|
||||
%bb_entry_0 = OpLabel
|
||||
%55 = OpExtInst %void %1 DebugScope %48
|
||||
OpLine %5 9 16
|
||||
%param_var_arg2 = OpVariable %_ptr_Function_float Function
|
||||
OpLine %5 6 7
|
||||
%56 = OpLoad %float %arg1
|
||||
OpLine %5 6 12
|
||||
%57 = OpFOrdGreaterThan %bool %56 %float_1
|
||||
OpLine %5 6 17
|
||||
OpSelectionMerge %if_merge None
|
||||
OpBranchConditional %57 %if_true %if_merge
|
||||
%if_true = OpLabel
|
||||
%58 = OpExtInst %void %1 DebugScope %50
|
||||
OpLine %5 7 5
|
||||
OpReturnValue %32
|
||||
%if_merge = OpLabel
|
||||
%59 = OpExtInst %void %1 DebugScope %51
|
||||
OpLine %5 9 16
|
||||
%60 = OpLoad %float %arg1
|
||||
OpStore %param_var_arg2 %60
|
||||
OpLine %5 9 10
|
||||
%61 = OpFunctionCall %v4float %func2 %param_var_arg2
|
||||
OpLine %5 9 3
|
||||
OpReturnValue %61
|
||||
OpFunctionEnd
|
||||
OpLine %5 1 1
|
||||
%func2 = OpFunction %v4float None %38
|
||||
OpLine %5 1 20
|
||||
%arg2 = OpFunctionParameter %_ptr_Function_float
|
||||
%bb_entry_1 = OpLabel
|
||||
%62 = OpExtInst %void %1 DebugScope %49
|
||||
OpLine %5 2 17
|
||||
%63 = OpLoad %float %arg2
|
||||
%64 = OpCompositeConstruct %v4float %63 %float_0 %float_0 %float_0
|
||||
OpLine %5 2 3
|
||||
OpReturnValue %64
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SpirvTools t(SPV_ENV_UNIVERSAL_1_1);
|
||||
std::unique_ptr<IRContext> context =
|
||||
BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text);
|
||||
ASSERT_EQ(nullptr, context);
|
||||
}
|
||||
|
||||
TEST(IrBuilder, LocalGlobalVariables) {
|
||||
// #version 310 es
|
||||
//
|
||||
|
|
|
@ -33,6 +33,9 @@ using ::testing::HasSubstr;
|
|||
using ::testing::Not;
|
||||
|
||||
using ValidateExtInst = spvtest::ValidateBase<bool>;
|
||||
using ValidateOldDebugInfo = spvtest::ValidateBase<std::string>;
|
||||
using ValidateOpenCL100DebugInfo = spvtest::ValidateBase<std::string>;
|
||||
using ValidateLocalDebugInfoOutOfFunction = spvtest::ValidateBase<std::string>;
|
||||
using ValidateGlslStd450SqrtLike = spvtest::ValidateBase<std::string>;
|
||||
using ValidateGlslStd450FMinLike = spvtest::ValidateBase<std::string>;
|
||||
using ValidateGlslStd450FClampLike = spvtest::ValidateBase<std::string>;
|
||||
|
@ -460,6 +463,462 @@ OpFunctionEnd)";
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
std::string GenerateShaderCodeForDebugInfo(
|
||||
const std::string& op_string_instructions,
|
||||
const std::string& op_const_instructions,
|
||||
const std::string& debug_instructions_before_main, const std::string& body,
|
||||
const std::string& capabilities_and_extensions = "",
|
||||
const std::string& execution_model = "Fragment") {
|
||||
std::ostringstream ss;
|
||||
ss << R"(
|
||||
OpCapability Shader
|
||||
OpCapability Float16
|
||||
OpCapability Float64
|
||||
OpCapability Int16
|
||||
OpCapability Int64
|
||||
)";
|
||||
|
||||
ss << capabilities_and_extensions;
|
||||
ss << "%extinst = OpExtInstImport \"GLSL.std.450\"\n";
|
||||
ss << "OpMemoryModel Logical GLSL450\n";
|
||||
ss << "OpEntryPoint " << execution_model << " %main \"main\""
|
||||
<< " %f32_output"
|
||||
<< " %f32vec2_output"
|
||||
<< " %u32_output"
|
||||
<< " %u32vec2_output"
|
||||
<< " %u64_output"
|
||||
<< " %f32_input"
|
||||
<< " %f32vec2_input"
|
||||
<< " %u32_input"
|
||||
<< " %u32vec2_input"
|
||||
<< " %u64_input"
|
||||
<< "\n";
|
||||
if (execution_model == "Fragment") {
|
||||
ss << "OpExecutionMode %main OriginUpperLeft\n";
|
||||
}
|
||||
|
||||
ss << op_string_instructions;
|
||||
|
||||
ss << R"(
|
||||
%void = OpTypeVoid
|
||||
%func = OpTypeFunction %void
|
||||
%bool = OpTypeBool
|
||||
%f16 = OpTypeFloat 16
|
||||
%f32 = OpTypeFloat 32
|
||||
%f64 = OpTypeFloat 64
|
||||
%u32 = OpTypeInt 32 0
|
||||
%s32 = OpTypeInt 32 1
|
||||
%u64 = OpTypeInt 64 0
|
||||
%s64 = OpTypeInt 64 1
|
||||
%u16 = OpTypeInt 16 0
|
||||
%s16 = OpTypeInt 16 1
|
||||
%f32vec2 = OpTypeVector %f32 2
|
||||
%f32vec3 = OpTypeVector %f32 3
|
||||
%f32vec4 = OpTypeVector %f32 4
|
||||
%f64vec2 = OpTypeVector %f64 2
|
||||
%f64vec3 = OpTypeVector %f64 3
|
||||
%f64vec4 = OpTypeVector %f64 4
|
||||
%u32vec2 = OpTypeVector %u32 2
|
||||
%u32vec3 = OpTypeVector %u32 3
|
||||
%s32vec2 = OpTypeVector %s32 2
|
||||
%u32vec4 = OpTypeVector %u32 4
|
||||
%s32vec4 = OpTypeVector %s32 4
|
||||
%u64vec2 = OpTypeVector %u64 2
|
||||
%s64vec2 = OpTypeVector %s64 2
|
||||
%f64mat22 = OpTypeMatrix %f64vec2 2
|
||||
%f32mat22 = OpTypeMatrix %f32vec2 2
|
||||
%f32mat23 = OpTypeMatrix %f32vec2 3
|
||||
%f32mat32 = OpTypeMatrix %f32vec3 2
|
||||
%f32mat33 = OpTypeMatrix %f32vec3 3
|
||||
|
||||
%f32_0 = OpConstant %f32 0
|
||||
%f32_1 = OpConstant %f32 1
|
||||
%f32_2 = OpConstant %f32 2
|
||||
%f32_3 = OpConstant %f32 3
|
||||
%f32_4 = OpConstant %f32 4
|
||||
%f32_h = OpConstant %f32 0.5
|
||||
%f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
|
||||
%f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2
|
||||
%f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2
|
||||
%f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3
|
||||
%f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
|
||||
%f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4
|
||||
|
||||
%f64_0 = OpConstant %f64 0
|
||||
%f64_1 = OpConstant %f64 1
|
||||
%f64_2 = OpConstant %f64 2
|
||||
%f64_3 = OpConstant %f64 3
|
||||
%f64vec2_01 = OpConstantComposite %f64vec2 %f64_0 %f64_1
|
||||
%f64vec3_012 = OpConstantComposite %f64vec3 %f64_0 %f64_1 %f64_2
|
||||
%f64vec4_0123 = OpConstantComposite %f64vec4 %f64_0 %f64_1 %f64_2 %f64_3
|
||||
|
||||
%f16_0 = OpConstant %f16 0
|
||||
%f16_1 = OpConstant %f16 1
|
||||
%f16_h = OpConstant %f16 0.5
|
||||
|
||||
%u32_0 = OpConstant %u32 0
|
||||
%u32_1 = OpConstant %u32 1
|
||||
%u32_2 = OpConstant %u32 2
|
||||
%u32_3 = OpConstant %u32 3
|
||||
|
||||
%s32_0 = OpConstant %s32 0
|
||||
%s32_1 = OpConstant %s32 1
|
||||
%s32_2 = OpConstant %s32 2
|
||||
%s32_3 = OpConstant %s32 3
|
||||
|
||||
%u64_0 = OpConstant %u64 0
|
||||
%u64_1 = OpConstant %u64 1
|
||||
%u64_2 = OpConstant %u64 2
|
||||
%u64_3 = OpConstant %u64 3
|
||||
|
||||
%s64_0 = OpConstant %s64 0
|
||||
%s64_1 = OpConstant %s64 1
|
||||
%s64_2 = OpConstant %s64 2
|
||||
%s64_3 = OpConstant %s64 3
|
||||
)";
|
||||
|
||||
ss << op_const_instructions;
|
||||
|
||||
ss << R"(
|
||||
%s32vec2_01 = OpConstantComposite %s32vec2 %s32_0 %s32_1
|
||||
%u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
|
||||
|
||||
%s32vec2_12 = OpConstantComposite %s32vec2 %s32_1 %s32_2
|
||||
%u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2
|
||||
|
||||
%s32vec4_0123 = OpConstantComposite %s32vec4 %s32_0 %s32_1 %s32_2 %s32_3
|
||||
%u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
|
||||
|
||||
%s64vec2_01 = OpConstantComposite %s64vec2 %s64_0 %s64_1
|
||||
%u64vec2_01 = OpConstantComposite %u64vec2 %u64_0 %u64_1
|
||||
|
||||
%f32mat22_1212 = OpConstantComposite %f32mat22 %f32vec2_12 %f32vec2_12
|
||||
%f32mat23_121212 = OpConstantComposite %f32mat23 %f32vec2_12 %f32vec2_12 %f32vec2_12
|
||||
|
||||
%f32_ptr_output = OpTypePointer Output %f32
|
||||
%f32vec2_ptr_output = OpTypePointer Output %f32vec2
|
||||
|
||||
%u32_ptr_output = OpTypePointer Output %u32
|
||||
%u32vec2_ptr_output = OpTypePointer Output %u32vec2
|
||||
|
||||
%u64_ptr_output = OpTypePointer Output %u64
|
||||
|
||||
%f32_output = OpVariable %f32_ptr_output Output
|
||||
%f32vec2_output = OpVariable %f32vec2_ptr_output Output
|
||||
|
||||
%u32_output = OpVariable %u32_ptr_output Output
|
||||
%u32vec2_output = OpVariable %u32vec2_ptr_output Output
|
||||
|
||||
%u64_output = OpVariable %u64_ptr_output Output
|
||||
|
||||
%f32_ptr_input = OpTypePointer Input %f32
|
||||
%f32vec2_ptr_input = OpTypePointer Input %f32vec2
|
||||
|
||||
%u32_ptr_input = OpTypePointer Input %u32
|
||||
%u32vec2_ptr_input = OpTypePointer Input %u32vec2
|
||||
|
||||
%u64_ptr_input = OpTypePointer Input %u64
|
||||
|
||||
%f32_ptr_function = OpTypePointer Function %f32
|
||||
|
||||
%f32_input = OpVariable %f32_ptr_input Input
|
||||
%f32vec2_input = OpVariable %f32vec2_ptr_input Input
|
||||
|
||||
%u32_input = OpVariable %u32_ptr_input Input
|
||||
%u32vec2_input = OpVariable %u32vec2_ptr_input Input
|
||||
|
||||
%u64_input = OpVariable %u64_ptr_input Input
|
||||
|
||||
%u32_ptr_function = OpTypePointer Function %u32
|
||||
|
||||
%struct_f16_u16 = OpTypeStruct %f16 %u16
|
||||
%struct_f32_f32 = OpTypeStruct %f32 %f32
|
||||
%struct_f32_f32_f32 = OpTypeStruct %f32 %f32 %f32
|
||||
%struct_f32_u32 = OpTypeStruct %f32 %u32
|
||||
%struct_f32_u32_f32 = OpTypeStruct %f32 %u32 %f32
|
||||
%struct_u32_f32 = OpTypeStruct %u32 %f32
|
||||
%struct_u32_u32 = OpTypeStruct %u32 %u32
|
||||
%struct_f32_f64 = OpTypeStruct %f32 %f64
|
||||
%struct_f32vec2_f32vec2 = OpTypeStruct %f32vec2 %f32vec2
|
||||
%struct_f32vec2_u32vec2 = OpTypeStruct %f32vec2 %u32vec2
|
||||
)";
|
||||
|
||||
ss << debug_instructions_before_main;
|
||||
|
||||
ss << R"(
|
||||
%main = OpFunction %void None %func
|
||||
%main_entry = OpLabel
|
||||
)";
|
||||
|
||||
ss << body;
|
||||
|
||||
ss << R"(
|
||||
OpReturn
|
||||
OpFunctionEnd)";
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
TEST_F(ValidateOldDebugInfo, UseDebugInstructionOutOfFunction) {
|
||||
const std::string src = R"(
|
||||
%code = OpString "main() {}"
|
||||
)";
|
||||
|
||||
const std::string dbg_inst = R"(
|
||||
%cu = OpExtInst %void %DbgExt DebugCompilationUnit %code 1 1
|
||||
)";
|
||||
|
||||
const std::string extension = R"(
|
||||
%DbgExt = OpExtInstImport "DebugInfo"
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCodeForDebugInfo(src, "", dbg_inst, "",
|
||||
extension, "Vertex"));
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateOpenCL100DebugInfo, UseDebugInstructionOutOfFunction) {
|
||||
const std::string src = R"(
|
||||
%src = OpString "simple.hlsl"
|
||||
%code = OpString "main() {}"
|
||||
)";
|
||||
|
||||
const std::string dbg_inst = R"(
|
||||
%dbg_src = OpExtInst %void %DbgExt DebugSource %src %code
|
||||
)";
|
||||
|
||||
const std::string extension = R"(
|
||||
%DbgExt = OpExtInstImport "OpenCL.DebugInfo.100"
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCodeForDebugInfo(src, "", dbg_inst, "",
|
||||
extension, "Vertex"));
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateOpenCL100DebugInfo, DebugSourceInFunction) {
|
||||
const std::string src = R"(
|
||||
%src = OpString "simple.hlsl"
|
||||
%code = OpString "main() {}"
|
||||
)";
|
||||
|
||||
const std::string dbg_inst = R"(
|
||||
%dbg_src = OpExtInst %void %DbgExt DebugSource %src %code
|
||||
)";
|
||||
|
||||
const std::string extension = R"(
|
||||
%DbgExt = OpExtInstImport "OpenCL.DebugInfo.100"
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCodeForDebugInfo(src, "", "", dbg_inst,
|
||||
extension, "Vertex"));
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("Debug info extension instructions other than DebugScope, "
|
||||
"DebugNoScope, DebugDeclare, DebugValue must appear between "
|
||||
"section 9 (types, constants, global variables) and section 10 "
|
||||
"(function declarations)"));
|
||||
}
|
||||
|
||||
TEST_P(ValidateLocalDebugInfoOutOfFunction, OpenCLDebugInfo100DebugScope) {
|
||||
const std::string src = R"(
|
||||
%src = OpString "simple.hlsl"
|
||||
%code = OpString "void main() {}"
|
||||
%void_name = OpString "void"
|
||||
%main_name = OpString "main"
|
||||
%main_linkage_name = OpString "v_main"
|
||||
%int_name = OpString "int"
|
||||
%foo_name = OpString "foo"
|
||||
)";
|
||||
|
||||
const std::string dbg_inst_header = R"(
|
||||
%dbg_src = OpExtInst %void %DbgExt DebugSource %src %code
|
||||
%comp_unit = OpExtInst %void %DbgExt DebugCompilationUnit 2 4 %dbg_src HLSL
|
||||
%void_info = OpExtInst %void %DbgExt DebugTypeBasic %void_name %u32_0 Unspecified
|
||||
%int_info = OpExtInst %void %DbgExt DebugTypeBasic %int_name %u32_0 Signed
|
||||
%main_type_info = OpExtInst %void %DbgExt DebugTypeFunction FlagIsPublic %void_info %void_info
|
||||
%main_info = OpExtInst %void %DbgExt DebugFunction %main_name %main_type_info %dbg_src 1 1 %comp_unit %main_linkage_name FlagIsPublic 1 %main
|
||||
%foo_info = OpExtInst %void %DbgExt DebugLocalVariable %foo_name %int_info %dbg_src 1 1 %main_info FlagIsLocal
|
||||
%expr = OpExtInst %void %DbgExt DebugExpression
|
||||
)";
|
||||
|
||||
const std::string body = R"(
|
||||
%foo = OpVariable %u32_ptr_function Function
|
||||
%foo_val = OpLoad %u32 %foo
|
||||
)";
|
||||
|
||||
const std::string extension = R"(
|
||||
%DbgExt = OpExtInstImport "OpenCL.DebugInfo.100"
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCodeForDebugInfo(
|
||||
src, "", dbg_inst_header + GetParam(), body, extension, "Vertex"));
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("DebugScope, DebugNoScope, DebugDeclare, DebugValue "
|
||||
"of debug info extension must appear in a function "
|
||||
"body"));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
AllLocalDebugInfo, ValidateLocalDebugInfoOutOfFunction,
|
||||
::testing::ValuesIn(std::vector<std::string>{
|
||||
"%main_scope = OpExtInst %void %DbgExt DebugScope %main_info",
|
||||
"%no_scope = OpExtInst %void %DbgExt DebugNoScope",
|
||||
}));
|
||||
|
||||
TEST_F(ValidateOpenCL100DebugInfo, DebugFunctionForwardReference) {
|
||||
const std::string src = R"(
|
||||
%src = OpString "simple.hlsl"
|
||||
%code = OpString "void main() {}"
|
||||
%void_name = OpString "void"
|
||||
%main_name = OpString "main"
|
||||
%main_linkage_name = OpString "v_main"
|
||||
)";
|
||||
|
||||
const std::string dbg_inst_header = R"(
|
||||
%dbg_src = OpExtInst %void %DbgExt DebugSource %src %code
|
||||
%comp_unit = OpExtInst %void %DbgExt DebugCompilationUnit 2 4 %dbg_src HLSL
|
||||
%void_info = OpExtInst %void %DbgExt DebugTypeBasic %void_name %u32_0 Unspecified
|
||||
%main_type_info = OpExtInst %void %DbgExt DebugTypeFunction FlagIsPublic %void_info %void_info
|
||||
%main_info = OpExtInst %void %DbgExt DebugFunction %main_name %main_type_info %dbg_src 1 1 %comp_unit %main_linkage_name FlagIsPublic 1 %main
|
||||
)";
|
||||
|
||||
const std::string body = R"(
|
||||
%main_scope = OpExtInst %void %DbgExt DebugScope %main_info
|
||||
)";
|
||||
|
||||
const std::string extension = R"(
|
||||
%DbgExt = OpExtInstImport "OpenCL.DebugInfo.100"
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCodeForDebugInfo(
|
||||
src, "", dbg_inst_header, body, extension, "Vertex"));
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateOpenCL100DebugInfo, DebugScopeBeforeOpVariableInFunction) {
|
||||
const std::string src = R"(
|
||||
%src = OpString "simple.hlsl"
|
||||
%code = OpString "float4 main(float arg) {
|
||||
float foo;
|
||||
return float4(0, 0, 0, 0);
|
||||
}
|
||||
"
|
||||
%float_name = OpString "float"
|
||||
%main_name = OpString "main"
|
||||
%main_linkage_name = OpString "v4f_main_f"
|
||||
)";
|
||||
|
||||
const std::string size_const = R"(
|
||||
%int_32 = OpConstant %u32 32
|
||||
)";
|
||||
|
||||
const std::string dbg_inst_header = R"(
|
||||
%dbg_src = OpExtInst %void %DbgExt DebugSource %src %code
|
||||
%comp_unit = OpExtInst %void %DbgExt DebugCompilationUnit 2 4 %dbg_src HLSL
|
||||
%float_info = OpExtInst %void %DbgExt DebugTypeBasic %float_name %int_32 Float
|
||||
%v4float_info = OpExtInst %void %DbgExt DebugTypeVector %float_info 4
|
||||
%main_type_info = OpExtInst %void %DbgExt DebugTypeFunction FlagIsPublic %v4float_info %float_info
|
||||
%main_info = OpExtInst %void %DbgExt DebugFunction %main_name %main_type_info %dbg_src 12 1 %comp_unit %main_linkage_name FlagIsPublic 13 %main
|
||||
)";
|
||||
|
||||
const std::string body = R"(
|
||||
%main_scope = OpExtInst %void %DbgExt DebugScope %main_info
|
||||
%foo = OpVariable %f32_ptr_function Function
|
||||
)";
|
||||
|
||||
const std::string extension = R"(
|
||||
%DbgExt = OpExtInstImport "OpenCL.DebugInfo.100"
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCodeForDebugInfo(
|
||||
src, size_const, dbg_inst_header, body, extension, "Vertex"));
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateOpenCL100DebugInfo, DebugTypeCompositeForwardReference) {
|
||||
const std::string src = R"(
|
||||
%src = OpString "simple.hlsl"
|
||||
%code = OpString "struct VS_OUTPUT {
|
||||
float4 pos : SV_POSITION;
|
||||
float4 color : COLOR;
|
||||
};
|
||||
main() {}
|
||||
"
|
||||
%VS_OUTPUT_name = OpString "struct VS_OUTPUT"
|
||||
%float_name = OpString "float"
|
||||
%VS_OUTPUT_pos_name = OpString "pos : SV_POSITION"
|
||||
%VS_OUTPUT_color_name = OpString "color : COLOR"
|
||||
%VS_OUTPUT_linkage_name = OpString "VS_OUTPUT"
|
||||
)";
|
||||
|
||||
const std::string size_const = R"(
|
||||
%int_32 = OpConstant %u32 32
|
||||
%int_128 = OpConstant %u32 128
|
||||
)";
|
||||
|
||||
const std::string dbg_inst_header = R"(
|
||||
%dbg_src = OpExtInst %void %DbgExt DebugSource %src %code
|
||||
%comp_unit = OpExtInst %void %DbgExt DebugCompilationUnit 2 4 %dbg_src HLSL
|
||||
%VS_OUTPUT_info = OpExtInst %void %DbgExt DebugTypeComposite %VS_OUTPUT_name Structure %dbg_src 1 1 %comp_unit %VS_OUTPUT_linkage_name %int_128 FlagIsPublic %VS_OUTPUT_pos_info %VS_OUTPUT_color_info
|
||||
%float_info = OpExtInst %void %DbgExt DebugTypeBasic %float_name %int_32 Float
|
||||
%v4float_info = OpExtInst %void %DbgExt DebugTypeVector %float_info 4
|
||||
%VS_OUTPUT_pos_info = OpExtInst %void %DbgExt DebugTypeMember %VS_OUTPUT_pos_name %v4float_info %dbg_src 2 3 %VS_OUTPUT_info %u32_0 %int_128 FlagIsPublic
|
||||
%VS_OUTPUT_color_info = OpExtInst %void %DbgExt DebugTypeMember %VS_OUTPUT_color_name %v4float_info %dbg_src 3 3 %VS_OUTPUT_info %int_128 %int_128 FlagIsPublic
|
||||
)";
|
||||
|
||||
const std::string extension = R"(
|
||||
%DbgExt = OpExtInstImport "OpenCL.DebugInfo.100"
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCodeForDebugInfo(
|
||||
src, size_const, dbg_inst_header, "", extension, "Vertex"));
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
}
|
||||
|
||||
TEST_F(ValidateOpenCL100DebugInfo, DebugTypeCompositeMissingReference) {
|
||||
const std::string src = R"(
|
||||
%src = OpString "simple.hlsl"
|
||||
%code = OpString "struct VS_OUTPUT {
|
||||
float4 pos : SV_POSITION;
|
||||
float4 color : COLOR;
|
||||
};
|
||||
main() {}
|
||||
"
|
||||
%VS_OUTPUT_name = OpString "struct VS_OUTPUT"
|
||||
%float_name = OpString "float"
|
||||
%VS_OUTPUT_pos_name = OpString "pos : SV_POSITION"
|
||||
%VS_OUTPUT_color_name = OpString "color : COLOR"
|
||||
%VS_OUTPUT_linkage_name = OpString "VS_OUTPUT"
|
||||
)";
|
||||
|
||||
const std::string size_const = R"(
|
||||
%int_32 = OpConstant %u32 32
|
||||
%int_128 = OpConstant %u32 128
|
||||
)";
|
||||
|
||||
const std::string dbg_inst_header = R"(
|
||||
%dbg_src = OpExtInst %void %DbgExt DebugSource %src %code
|
||||
%comp_unit = OpExtInst %void %DbgExt DebugCompilationUnit 2 4 %dbg_src HLSL
|
||||
%VS_OUTPUT_info = OpExtInst %void %DbgExt DebugTypeComposite %VS_OUTPUT_name Structure %dbg_src 1 1 %comp_unit %VS_OUTPUT_linkage_name %int_128 FlagIsPublic %VS_OUTPUT_pos_info %VS_OUTPUT_color_info
|
||||
%float_info = OpExtInst %void %DbgExt DebugTypeBasic %float_name %int_32 Float
|
||||
%v4float_info = OpExtInst %void %DbgExt DebugTypeVector %float_info 4
|
||||
%VS_OUTPUT_pos_info = OpExtInst %void %DbgExt DebugTypeMember %VS_OUTPUT_pos_name %v4float_info %dbg_src 2 3 %VS_OUTPUT_info %u32_0 %int_128 FlagIsPublic
|
||||
)";
|
||||
|
||||
const std::string extension = R"(
|
||||
%DbgExt = OpExtInstImport "OpenCL.DebugInfo.100"
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCodeForDebugInfo(
|
||||
src, size_const, dbg_inst_header, "", extension, "Vertex"));
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("forward referenced IDs have not been defined"));
|
||||
}
|
||||
|
||||
TEST_P(ValidateGlslStd450SqrtLike, Success) {
|
||||
const std::string ext_inst_name = GetParam();
|
||||
std::ostringstream ss;
|
||||
|
|
Загрузка…
Ссылка в новой задаче