/// \file Verify.cpp // // This file is distributed under the MIT License. See LICENSE.md for details. // #include "revng/Yield/BasicBlock.h" #include "revng/Yield/CallEdge.h" #include "revng/Yield/Function.h" #include "revng/Yield/Instruction.h" bool yield::TaggedString::verify(model::VerifyHelper &VH) const { if (Type() == TagType::Invalid) return VH.fail("The type of this tag is not valid."); if (Content().empty()) return VH.fail("This tag doesn't have any data."); if (Content().find('\n') != std::string::npos) return VH.fail("String is not allowed to break the line, " "use multiple strings instead."); for (const yield::TagAttribute &Attribute : Attributes()) { if (Attribute.Name().empty()) return VH.fail("Attributes without names are not allowed."); if (Attribute.Name().empty()) return VH.fail("Attributes without values are not allowed."); } return true; } bool yield::TaggedLine::verify(model::VerifyHelper &VH) const { for (auto [Index, String] : llvm::enumerate(Tags())) { if (Index != String.Index()) return VH.fail("Tagged string indexing is broken."); if (!String.verify(VH)) return VH.fail(); } return true; } bool yield::Instruction::verify(model::VerifyHelper &VH) const { if (Address().isInvalid()) return VH.fail("An instruction must have a valid address."); if (RawBytes().empty()) return VH.fail("An instruction has to be at least one byte big."); if (Disassembled().empty()) return VH.fail("An instruction must have at least one tag."); for (auto [Index, Tagged] : llvm::enumerate(Disassembled())) { if (Index != Tagged.Index()) return VH.fail("Tagged string indexing is broken."); if (!Tagged.verify(VH)) return VH.fail(); } for (auto [Index, Directive] : llvm::enumerate(PrecedingDirectives())) { if (Index != Directive.Index()) return VH.fail("Preceding directive indexing is broken."); if (!Directive.verify(VH)) return VH.fail(); } for (auto [Index, Directive] : llvm::enumerate(FollowingDirectives())) { if (Index != Directive.Index()) return VH.fail("Following directive indexing is broken."); if (!Directive.verify(VH)) return VH.fail(); } return true; } bool yield::BasicBlock::verify(model::VerifyHelper &VH) const { if (not ID().isValid()) return VH.fail("A basic block has to have a valid start address."); if (End().isInvalid()) return VH.fail("A basic block has to have a valid end address."); if (Instructions().empty()) return VH.fail("A basic block has to store at least a single instruction."); if (IsLabelAlwaysRequired()) if (!Label().verify()) return false; MetaAddress PreviousAddress = MetaAddress::invalid(); for (const auto &Instruction : Instructions()) { if (!Instruction.verify(VH)) return VH.fail("Instruction verification failed."); if (PreviousAddress.isValid() && Instruction.Address() < PreviousAddress) { return VH.fail("Instructions must be strongly ordered and their size " "must be bigger than zero."); } PreviousAddress = Instruction.Address(); } if (PreviousAddress.isInvalid() || PreviousAddress >= End()) { return VH.fail("The size of the last instruction must be bigger than " "zero."); } if (HasDelaySlot() && Instructions().size() < 2) { return VH.fail("A basic block with a delay slot must contain at least two " "instructions."); } return true; } bool yield::Function::verify(model::VerifyHelper &VH) const { if (Entry().isInvalid()) return VH.fail("A function has to have a valid entry point."); if (Blocks().empty()) return VH.fail("A function has to store at least a single basic block."); for (const auto &BasicBlock : Blocks()) if (!BasicBlock.verify(VH)) return VH.fail("Basic block verification failed."); return true; }