diff --git a/include/revng/ABI/FunctionType/Layout.h b/include/revng/ABI/FunctionType/Layout.h index 830cc9699..ea304e44f 100644 --- a/include/revng/ABI/FunctionType/Layout.h +++ b/include/revng/ABI/FunctionType/Layout.h @@ -11,6 +11,7 @@ #include "revng/ABI/Definition.h" #include "revng/ADT/STLExtras.h" #include "revng/Model/Binary.h" +#include "revng/Support/YAMLTraits.h" namespace abi::FunctionType { @@ -88,12 +89,11 @@ public: public: struct StackSpan { - uint64_t Offset; - uint64_t Size; - - StackSpan operator+(uint64_t Offset) const { - return { this->Offset + Offset, Size }; - } + /// The offset should be interpreted as an offset within the struct + /// containing the stack arguments. It's not an offset from some reference + /// stack pointer value. + uint64_t Offset = 0; + uint64_t Size = 0; }; public: @@ -196,9 +196,25 @@ public: } public: - void dump() const debug_function; + void dump() const debug_function { dump(dbg); } + + template + void dump(T &Stream) const { + // TODO: accept an arbitrary stream + serialize(Stream, *this); + } }; +inline Layout::Argument::StackSpan +operator+(const Layout::Argument::StackSpan &This, uint64_t Offset) { + return { This.Offset + Offset, This.Size }; +} + +inline Layout::Argument::StackSpan +operator+(uint64_t Offset, const Layout::Argument::StackSpan &This) { + return { This.Offset + Offset, This.Size }; +} + inline std::span calleeSavedRegisters(const model::CABIFunctionDefinition &Prototype) { return abi::Definition::get(Prototype.ABI()).CalleeSavedRegisters(); @@ -276,3 +292,49 @@ inline UsedRegisters usedRegisters(const model::UpcastableType &FunctionType) { } } // namespace abi::FunctionType + +using FTL = abi::FunctionType::Layout; +namespace FTAK = abi::FunctionType::ArgumentKind; + +template<> +struct llvm::yaml::ScalarEnumerationTraits + : public NamedEnumScalarTraits {}; + +template<> +struct llvm::yaml::MappingTraits { + static void mapping(IO &IO, FTL::Argument::StackSpan &SS) { + IO.mapRequired("Offset", SS.Offset); + IO.mapRequired("Size", SS.Size); + } +}; +LLVM_YAML_IS_SEQUENCE_VECTOR(FTL::Argument::StackSpan) + +template<> +struct llvm::yaml::MappingTraits { + static void mapping(IO &IO, FTL::ReturnValue &RV) { + IO.mapRequired("Type", RV.Type); + IO.mapRequired("Registers", RV.Registers); + } +}; +LLVM_YAML_IS_SEQUENCE_VECTOR(FTL::ReturnValue) + +template<> +struct llvm::yaml::MappingTraits { + static void mapping(IO &IO, FTL::Argument &A) { + IO.mapRequired("Type", A.Type); + IO.mapRequired("Kind", A.Kind); + IO.mapRequired("Registers", A.Registers); + IO.mapOptional("Stack", A.Stack); + } +}; +LLVM_YAML_IS_SEQUENCE_VECTOR(FTL::Argument) + +template<> +struct llvm::yaml::MappingTraits { + static void mapping(IO &IO, FTL &L) { + IO.mapRequired("Arguments", L.Arguments); + IO.mapRequired("ReturnValues", L.ReturnValues); + IO.mapRequired("CalleeSavedRegisters", L.CalleeSavedRegisters); + IO.mapRequired("FinalStackOffset", L.FinalStackOffset); + } +}; diff --git a/include/revng/ABI/ModelHelpers.h b/include/revng/ABI/ModelHelpers.h index 3e1bb3b77..307b41b84 100644 --- a/include/revng/ABI/ModelHelpers.h +++ b/include/revng/ABI/ModelHelpers.h @@ -120,14 +120,10 @@ layoutToLLVMFunctionType(llvm::LLVMContext &Context, if constexpr (LegacyLocalVariables) { ReturnType = TargetPointerSizedInteger; } else { - if (Layout.hasSPTAR()) { - ReturnType = TargetPointerSizedInteger; - } else { - const model::Type &ReturnAggregate = Layout.returnValueAggregateType(); - size_t ReturnSize = *ReturnAggregate.size(); - auto *Int8 = llvm::IntegerType::getInt8Ty(Context); - ReturnType = llvm::ArrayType::get(Int8, ReturnSize); - } + const model::Type &ReturnAggregate = Layout.returnValueAggregateType(); + size_t ReturnSize = *ReturnAggregate.size(); + auto *Int8 = llvm::IntegerType::getInt8Ty(Context); + ReturnType = llvm::ArrayType::get(Int8, ReturnSize); } } break; diff --git a/include/revng/ADT/GenericGraph.h b/include/revng/ADT/GenericGraph.h index c7bb06f48..a5832af2a 100644 --- a/include/revng/ADT/GenericGraph.h +++ b/include/revng/ADT/GenericGraph.h @@ -1615,8 +1615,9 @@ struct GraphTraits> typename T::nodes_iterator>; static NodeRef getEntryNode(llvm::Inverse Inv) { - // TODO: we might want to consider an option of having optional - // `ExitNode`s as well, for consistency. + // NOTE: this is clearly misguided, however it's coherent with what happens + // for Inverse. + // Don't use this. return Inv.Graph->getEntryNode(); } diff --git a/include/revng/ADT/ReversePostOrderTraversal.h b/include/revng/ADT/ReversePostOrderTraversal.h index a60980b0e..72fe7147a 100644 --- a/include/revng/ADT/ReversePostOrderTraversal.h +++ b/include/revng/ADT/ReversePostOrderTraversal.h @@ -16,8 +16,9 @@ class ReversePostOrderTraversalExt { NodeVec Blocks; // Block list in normal RPO order void initialize(GraphT G, SetType &WhiteList) { - std::copy(po_ext_begin(G, WhiteList), - po_ext_end(G, WhiteList), + using ExtIter = llvm::po_ext_iterator; + std::copy(ExtIter::begin(G, WhiteList), + ExtIter::end(G, WhiteList), std::back_inserter(Blocks)); } diff --git a/include/revng/FunctionIsolation/StructInitializers.h b/include/revng/FunctionIsolation/StructInitializers.h index bd5b88fbc..2e787b9f3 100644 --- a/include/revng/FunctionIsolation/StructInitializers.h +++ b/include/revng/FunctionIsolation/StructInitializers.h @@ -14,11 +14,16 @@ class StructInitializers { private: OpaqueFunctionsPool Pool; llvm::LLVMContext &Context; + bool EmitBody = true; public: - StructInitializers(llvm::Module *M); + StructInitializers(llvm::Module *M, bool EmitBody = true); public: + llvm::CallInst *createCall(revng::IRBuilder &Builder, + llvm::StructType *ReturnType, + llvm::ArrayRef Values); + llvm::Instruction *createReturn(revng::IRBuilder &Builder, llvm::ArrayRef Values); }; diff --git a/include/revng/MFP/DOTGraphTraits.h b/include/revng/MFP/DOTGraphTraits.h index ab8d18509..76803bb2f 100644 --- a/include/revng/MFP/DOTGraphTraits.h +++ b/include/revng/MFP/DOTGraphTraits.h @@ -13,9 +13,9 @@ namespace llvm { class Instruction; } -template -struct llvm::DOTGraphTraits *> { - using GraphType = const MFP::Graph *; +template +struct llvm::DOTGraphTraits *> { + using GraphType = const mfp::Graph *; using UnderlyingGraphType = MFI::GraphType; using UnderlyingDOTGraphTraits = llvm::DOTGraphTraits; using NodeRef = llvm::GraphTraits::NodeRef; @@ -63,7 +63,7 @@ struct llvm::DOTGraphTraits *> { llvm::raw_string_ostream Stream(Result); Stream << Name.str() << " value:" << "\n"; - MFP::dump(Stream, 1, ToDump); + mfp::dump(Stream, 1, ToDump); } replaceAll(Result, "\n", Newline); @@ -141,6 +141,6 @@ struct llvm::DOTGraphTraits *> { } }; -template -struct llvm::DOTGraphTraits *> - : llvm::DOTGraphTraits *> {}; +template +struct llvm::DOTGraphTraits *> + : llvm::DOTGraphTraits *> {}; diff --git a/include/revng/MFP/Graph.h b/include/revng/MFP/Graph.h index d9064964b..db9d4310c 100644 --- a/include/revng/MFP/Graph.h +++ b/include/revng/MFP/Graph.h @@ -6,7 +6,7 @@ #include "revng/MFP/MFP.h" -namespace MFP { +namespace mfp { template class Graph { @@ -28,12 +28,12 @@ public: const auto &results() const { return Results; } }; -} // namespace MFP +} // namespace mfp /// \note This implementation of GraphTraits forwards everything 1-to-1 -template -struct llvm::GraphTraits *> { - using GraphType = MFP::Graph *; +template +struct llvm::GraphTraits *> { + using GraphType = mfp::Graph *; using UnderlyingGraphTraits = llvm::GraphTraits; using NodeRef = typename UnderlyingGraphTraits::NodeRef; using EdgeRef = typename UnderlyingGraphTraits::EdgeRef; @@ -76,9 +76,9 @@ struct llvm::GraphTraits *> { }; /// \note This implementation of GraphTraits forwards everything 1-to-1 -template -struct llvm::GraphTraits *> { - using GraphType = const MFP::Graph *; +template +struct llvm::GraphTraits *> { + using GraphType = const mfp::Graph *; using UnderlyingGraphTraits = llvm::GraphTraits; using NodeRef = const typename UnderlyingGraphTraits::NodeRef; using EdgeRef = typename UnderlyingGraphTraits::EdgeRef; diff --git a/include/revng/MFP/MFP.h b/include/revng/MFP/MFP.h index fdaf5e2be..678e543ec 100644 --- a/include/revng/MFP/MFP.h +++ b/include/revng/MFP/MFP.h @@ -1,5 +1,8 @@ #pragma once +#include "revng/ADT/STLExtras.h" +#include "revng/Support/Debug.h" + // // This file is distributed under the MIT License. See LICENSE.md for details. // @@ -9,8 +12,13 @@ #include #include #include +#include +#include +#include +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/Hashing.h" #include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/iterator_range.h" @@ -20,22 +28,133 @@ #include "revng/ADT/GenericGraph.h" #include "revng/ADT/ReversePostOrderTraversal.h" -namespace MFP { +namespace mfp { inline Logger NullLogger(""); -template -void dump(llvm::raw_ostream &Stream, unsigned Indent, const T &Element) { +/// @{ +/// Tag types selecting how `MFPConfiguration::EntryLabels` is computed when +/// the caller does not provide an explicit `std::vector