#pragma once // // This file is distributed under the MIT License. See LICENSE.md for details. // #include "revng/ADT/Concepts.h" #include "revng/Support/FunctionTags.h" // We use a template here in order to instantiate `FunctionType` both as // `Function` and `const Function` template ModuleType> inline typename std::conditional_t, const llvm::Function, llvm::Function> * getUniqueFunctionWithTag(FunctionTags::Tag &MarkerFunctionTag, ModuleType *M) { using FunctionType = typename std::conditional_t, const llvm::Function, llvm::Function>; FunctionType *MarkerCallFunction = nullptr; // We could early break from this loop but we would loose the ability of // asserting that a single marker function is present for (FunctionType &F : MarkerFunctionTag.functions(M)) { revng_assert(not MarkerCallFunction); MarkerCallFunction = &F; } return MarkerCallFunction; } /// A class that wraps all the logic for injecting goto edges and scope closer /// edges on LLVM IR. Such edges are then necessary for the ScopeGraph view on /// LLVM IR class ScopeGraphBuilder { private: llvm::Function *ScopeCloserFunction = nullptr; llvm::Function *GotoBlockFunction = nullptr; public: ScopeGraphBuilder(llvm::Function *F); public: void makeGoto(llvm::BasicBlock *GotoBlock); void eraseGoto(llvm::BasicBlock *GotoBlock); void addScopeCloser(llvm::BasicBlock *Source, llvm::BasicBlock *Target); /// Helper method which erase a `scope_closer`, and returns the block which /// was target of the `scope_closer` llvm::BasicBlock *eraseScopeCloser(llvm::BasicBlock *Source); /// With the usage of this helper, all the successor in the `Terminator` of /// the `Source` block pointing to `Target` will be redirected to the newly /// inserted `goto` block llvm::BasicBlock *makeGotoEdge(llvm::BasicBlock *Source, llvm::BasicBlock *Target); }; template BasicBlockType> llvm::SmallVector, const llvm::Instruction, llvm::Instruction> *, 2> getLast2InstructionsBeforeTerminator(BasicBlockType *BB); /// Helper function to retrieve the `BasicBlock` target of the marker llvm::BasicBlock *getScopeCloserTarget(const llvm::BasicBlock *BB); /// Helper function to determine if `BB` contains a `scope_closer` marker bool isScopeCloserBlock(const llvm::BasicBlock *BB); /// Helper function to determine if `BB` contains a `goto_block` marker bool isGotoBlock(const llvm::BasicBlock *BB); void verifyScopeGraphAnnotationsImpl(FunctionTags::Tag &Tag, const llvm::BasicBlock *BB); void verifyScopeGraphAnnotations(const llvm::BasicBlock *BB);