aboutsummaryrefslogtreecommitdiff
path: root/source/val/validate_cfg.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/val/validate_cfg.cpp')
-rw-r--r--source/val/validate_cfg.cpp29
1 files changed, 24 insertions, 5 deletions
diff --git a/source/val/validate_cfg.cpp b/source/val/validate_cfg.cpp
index 36f632a8..88abd754 100644
--- a/source/val/validate_cfg.cpp
+++ b/source/val/validate_cfg.cpp
@@ -27,6 +27,7 @@
#include "source/cfa.h"
#include "source/opcode.h"
+#include "source/spirv_constant.h"
#include "source/spirv_target_env.h"
#include "source/spirv_validator_options.h"
#include "source/val/basic_block.h"
@@ -191,6 +192,12 @@ spv_result_t ValidateBranchConditional(ValidationState_t& _,
"ID of an OpLabel instruction";
}
+ if (_.version() >= SPV_SPIRV_VERSION_WORD(1, 6) && true_id == false_id) {
+ return _.diag(SPV_ERROR_INVALID_ID, inst)
+ << "In SPIR-V 1.6 or later, True Label and False Label must be "
+ "different labels";
+ }
+
return SPV_SUCCESS;
}
@@ -199,6 +206,18 @@ spv_result_t ValidateSwitch(ValidationState_t& _, const Instruction* inst) {
// At least two operands (selector, default), any more than that are
// literal/target.
+ const auto sel_type_id = _.GetOperandTypeId(inst, 0);
+ if (!_.IsIntScalarType(sel_type_id)) {
+ return _.diag(SPV_ERROR_INVALID_ID, inst)
+ << "Selector type must be OpTypeInt";
+ }
+
+ const auto default_label = _.FindDef(inst->GetOperandAs<uint32_t>(1));
+ if (default_label->opcode() != SpvOpLabel) {
+ return _.diag(SPV_ERROR_INVALID_ID, inst)
+ << "Default must be an OpLabel instruction";
+ }
+
// target operands must be OpLabel
for (size_t i = 2; i < num_operands; i += 2) {
// literal, id
@@ -647,16 +666,16 @@ spv_result_t ValidateStructuredSelections(
// Mark the upcoming blocks as seen now, but only error out if this block
// was missing a merge instruction and both labels hadn't been seen
// previously.
- const bool both_unseen =
- seen.insert(true_label).second && seen.insert(false_label).second;
- if (!merge && both_unseen) {
+ const bool true_label_unseen = seen.insert(true_label).second;
+ const bool false_label_unseen = seen.insert(false_label).second;
+ if (!merge && true_label_unseen && false_label_unseen) {
return _.diag(SPV_ERROR_INVALID_CFG, terminator)
<< "Selection must be structured";
}
} else if (terminator->opcode() == SpvOpSwitch) {
if (!merge) {
return _.diag(SPV_ERROR_INVALID_CFG, terminator)
- << "OpSwitch must be preceeded by an OpSelectionMerge "
+ << "OpSwitch must be preceded by an OpSelectionMerge "
"instruction";
}
// Mark the targets as seen.
@@ -898,7 +917,7 @@ spv_result_t PerformCfgChecks(ValidationState_t& _) {
}
}
}
- // If we have structed control flow, check that no block has a control
+ // If we have structured control flow, check that no block has a control
// flow nesting depth larger than the limit.
if (_.HasCapability(SpvCapabilityShader)) {
const int control_flow_nesting_depth_limit =