summaryrefslogtreecommitdiffstats
path: root/source/slang/ir-validate.cpp
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2019-05-31 17:20:37 -0400
committerGitHub <noreply@github.com>2019-05-31 17:20:37 -0400
commit6cbc3929a54d37bd23cb5efa8e3320ba02f78b2f (patch)
tree5a23cb47782e9e2a77762c90dd35da1005eba8d0 /source/slang/ir-validate.cpp
parentb81ff3ef968d1cc4e954b31a1812b3c391d17b02 (diff)
Use slang- prefix on slang compiler and core source (#973)
* Prefixing source files in source/slang with slang- * Prefix source in source/slang with slang- prefix. * Rename core source files with slang- prefix. * Update project files. * Fix problems from automatic merge.
Diffstat (limited to 'source/slang/ir-validate.cpp')
-rw-r--r--source/slang/ir-validate.cpp207
1 files changed, 0 insertions, 207 deletions
diff --git a/source/slang/ir-validate.cpp b/source/slang/ir-validate.cpp
deleted file mode 100644
index 9564873b1..000000000
--- a/source/slang/ir-validate.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-// ir-validate.cpp
-#include "ir-validate.h"
-
-#include "ir.h"
-#include "ir-insts.h"
-
-namespace Slang
-{
- struct IRValidateContext
- {
- // The IR module we are validating.
- IRModule* module;
-
- // A diagnostic sink to send errors to if anything is invalid.
- DiagnosticSink* sink;
-
- DiagnosticSink* getSink() { return sink; }
-
- // A set of instructions we've seen, to help confirm that
- // values are defined before they are used in a given block.
- HashSet<IRInst*> seenInsts;
- };
-
- void validateIRInst(
- IRValidateContext* context,
- IRInst* inst);
-
- void validate(IRValidateContext* context, bool condition, IRInst* inst, char const* message)
- {
- if (!condition)
- {
- context->getSink()->diagnose(inst, Diagnostics::irValidationFailed, message);
- }
- }
-
- void validateIRInstChildren(
- IRValidateContext* context,
- IRInst* parent)
- {
- IRInst* prevChild = nullptr;
- for(auto child : parent->getDecorationsAndChildren() )
- {
- // We need to check the integrity of the parent/next/prev links of
- // all of our instructions
- validate(context, child->parent == parent, child, "parent link");
- validate(context, child->prev == prevChild, child, "next/prev link");
-
- // Recursively validate the instruction itself.
- validateIRInst(context, child);
-
- // Do some extra validation around terminator instructions:
- //
- // * The last instruction of a block should always be a terminator
- // * No other instruction should be a terminator
- //
- if(as<IRBlock>(parent) && (child == parent->getLastDecorationOrChild()))
- {
- validate(context, as<IRTerminatorInst>(child) != nullptr, child, "last instruction in block must be terminator");
- }
- else
- {
- validate(context, !as<IRTerminatorInst>(child), child, "terminator must be last instruction in a block");
- }
-
-
- prevChild = child;
- }
- }
-
- void validateIRInstOperand(
- IRValidateContext* context,
- IRInst* inst,
- IRUse* operandUse)
- {
- // The `IRUse` for the operand had better have `inst` as its user.
- validate(context, operandUse->getUser() == inst, inst, "operand user");
-
- // The value we are using needs to fit into one of a few cases.
- //
- // * If the parent of `inst` and of `operand` is the same block, then
- // we require that `operand` is defined before `inst`
- //
- // * If the parents of `inst` and `operand` are both blocks in the
- // same functin, then the block defining `operand` must dominate
- // the block defining `inst`.
- //
- // * Otherwise, we simply require that the parent of `operand` be
- // an ancestor (transitive parent) of `inst`.
-
- auto instParent = inst->getParent();
-
- auto operandValue = operandUse->get();
-
- if( !operandValue )
- {
- // A null operand should almost always be an error, but
- // we currently have a few cases where this arises.
- //
- // TODO: plug the leaks.
- return;
- }
-
- auto operandParent = operandValue->getParent();
-
- if (auto instParentBlock = as<IRBlock>(instParent))
- {
- if (auto operandParentBlock = as<IRBlock>(operandParent))
- {
- if (instParentBlock == operandParentBlock)
- {
- // If `operandValue` precedes `inst`, then we should
- // have already seen it, because we scan parent instructions
- // in order.
- validate(context, context->seenInsts.Contains(operandValue), inst, "def must come before use in same block");
- return;
- }
-
- auto instFunc = instParentBlock->getParent();
- auto operandFunc = operandParentBlock->getParent();
- if (instFunc == operandFunc)
- {
- // The two instructions are defined in different blocks of
- // the same function (or another value with code). We need
- // to validate that `operandParentBlock` dominates `instParentBlock`.
- //
- // TODO: implement this validation once we compute dominator trees.
- //
- // validate(context, operandParentBlock->dominates(instParentBlock), inst, "def must dominate use");
- return;
- }
- }
- }
-
- // If the special cases above did not trigger, then either the two values
- // are nested in the same parent, but that parent isn't a block, or they
- // are nested in distinct parents, and those parents aren't both children
- // of a function.
- //
- // In either case, we need to enforce that the parent of `operand` needs
- // to be an ancestor of `inst`.
- //
- for (auto pp = instParent; pp; pp = pp->getParent())
- {
- if (pp == operandParent)
- return;
- }
- //
- // We failed to find `operandParent` while walking the ancestors of `inst`,
- // so something had gone wrong.
- validate(context, false, inst, "def must be ancestor of use");
- }
-
- void validateIRInstOperands(
- IRValidateContext* context,
- IRInst* inst)
- {
- if(inst->getFullType())
- validateIRInstOperand(context, inst, &inst->typeUse);
-
- UInt operandCount = inst->getOperandCount();
- for (UInt ii = 0; ii < operandCount; ++ii)
- {
- validateIRInstOperand(context, inst, inst->getOperands() + ii);
- }
- }
-
- void validateIRInst(
- IRValidateContext* context,
- IRInst* inst)
- {
- // Validate that any operands of the instruction are used appropriately
- validateIRInstOperands(context, inst);
- context->seenInsts.Add(inst);
-
- // If `inst` is itself a parent instruction, then we need to recursively
- // validate its children.
- validateIRInstChildren(context, inst);
- }
-
- void validateIRModule(IRModule* module, DiagnosticSink* sink)
- {
- IRValidateContext contextStorage;
- IRValidateContext* context = &contextStorage;
- context->module = module;
- context->sink = sink;
-
- auto moduleInst = module->moduleInst;
-
- validate(context, moduleInst != nullptr, moduleInst, "module instruction");
- validate(context, moduleInst->parent == nullptr, moduleInst, "module instruction parent");
- validate(context, moduleInst->prev == nullptr, moduleInst, "module instruction prev");
- validate(context, moduleInst->next == nullptr, moduleInst, "module instruction next");
-
- validateIRInst(context, module->moduleInst);
- }
-
- void validateIRModuleIfEnabled(
- CompileRequestBase* compileRequest,
- IRModule* module)
- {
- if (!compileRequest->shouldValidateIR)
- return;
-
- auto sink = compileRequest->getSink();
- validateIRModule(module, sink);
- }
-}