From 316a2f8d96c8a801613f19c466d342a2e246f7a2 Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Thu, 3 Sep 2020 03:54:54 +1200 Subject: [PATCH] IRValidation: Add arg liveness, numUses checks --- .../Interface/IR/Passes/IRValidation.cpp | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/External/FEXCore/Source/Interface/IR/Passes/IRValidation.cpp b/External/FEXCore/Source/Interface/IR/Passes/IRValidation.cpp index 6cc3607cc..d573b8897 100644 --- a/External/FEXCore/Source/Interface/IR/Passes/IRValidation.cpp +++ b/External/FEXCore/Source/Interface/IR/Passes/IRValidation.cpp @@ -2,6 +2,7 @@ #include "Interface/IR/Passes/RegisterAllocationPass.h" #include "Interface/Context/Context.h" #include "Interface/Core/OpcodeDispatcher.h" +#include "Common/BitSet.h" #include @@ -33,6 +34,11 @@ bool IRValidation::Run(IREmitter *IREmit) { std::ostringstream Errors; std::ostringstream Warnings; + BitSet NodeIsLive; + NodeIsLive.Allocate(CurrentIR.GetSSACount()); + + std::vector Uses(CurrentIR.GetSSACount(), 0); + auto Begin = CurrentIR.begin(); auto Op = Begin(); @@ -52,6 +58,8 @@ bool IRValidation::Run(IREmitter *IREmit) { BlockInfo *CurrentBlock = &OffsetToBlockMap.try_emplace(BlockNode->Wrapped(ListBegin).ID()).first->second; + + // We grab these nodes this way so we can iterate easily auto CodeBegin = CurrentIR.at(BlockIROp->Begin); auto CodeLast = CurrentIR.at(BlockIROp->Last); @@ -106,6 +114,9 @@ bool IRValidation::Run(IREmitter *IREmit) { } uint8_t NumArgs = IR::GetArgs(IROp->Op); + + if (NumArgs != IROp->NumArgs) + Errors << "%ssa" << CodeOp->ID() << ": Has wrong number of Args" << std::endl; for (uint32_t i = 0; i < NumArgs; ++i) { OrderedNodeWrapper Arg = IROp->Args[i]; // Was an argument defined after this node? @@ -113,8 +124,17 @@ bool IRValidation::Run(IREmitter *IREmit) { HadError |= true; Errors << "%ssa" << CodeOp->ID() << ": Arg[" << i << "] has definition after use at %ssa" << Arg.ID() << std::endl; } + + if (!NodeIsLive.Get(Arg.ID())) { + HadError |= true; + Errors << "%ssa" << CodeOp->ID() << ": Arg[" << i << "] refrences dead %ssa" << Arg.ID() << std::endl; + } + + Uses[Arg.ID()]++; } + NodeIsLive.Set(CodeOp->ID()); + switch (IROp->Op) { case IR::OP_EXITFUNCTION: { CurrentBlock->HasExit = true; @@ -231,6 +251,12 @@ bool IRValidation::Run(IREmitter *IREmit) { } } + for (int i = 0; i < CurrentIR.GetSSACount(); i++) { + auto Node = OrderedNodeWrapper::WrapOffset(i * sizeof(IR::OrderedNode)).GetNode(ListBegin); + if (Node->NumUses != Uses[i]) + Errors << "%ssa" << i << " Has " << Uses[i] << " Uses, but reports " << Node->NumUses << std::endl; + } + std::stringstream Out; HadWarning = false;