/// \file DefaultPrototype.cpp /// \brief // // This file is distributed under the MIT License. See LICENSE.md for details. // #include "revng/ABI/DefaultFunctionPrototype.h" #include "revng/ABI/Trait.h" #include "revng/Support/EnumSwitch.h" using namespace model; constexpr static PrimitiveTypeKind::Values selectTypeKind(Register::Values) { // TODO: implement a way to determine the register type. At the very least // we should be able to differentiate GPRs from the vector registers. return PrimitiveTypeKind::PointerOrNumber; } static QualifiedType buildType(Register::Values Register, Binary &TheBinary) { PrimitiveTypeKind::Values Kind = selectTypeKind(Register); size_t Size = Register::getSize(Register); return QualifiedType(TheBinary.getPrimitiveType(Kind, Size), {}); } template TypePath defaultPrototype(Binary &TheBinary) { UpcastableType NewType = makeType(); TypePath TypePath = TheBinary.recordNewType(std::move(NewType)); auto &Prototype = *llvm::cast(TypePath.get()); for (const auto &Reg : abi::Trait::GeneralPurposeArgumentRegisters) { NamedTypedRegister Argument(Reg); Argument.Type() = buildType(Reg, TheBinary); Prototype.Arguments().insert(Argument); } for (const auto &Rg : abi::Trait::GeneralPurposeReturnValueRegisters) { TypedRegister ReturnValue(Rg); ReturnValue.Type() = buildType(Rg, TheBinary); Prototype.ReturnValues().insert(ReturnValue); } for (const auto &Register : abi::Trait::CalleeSavedRegisters) Prototype.PreservedRegisters().insert(Register); using namespace Architecture; Prototype.FinalStackOffset() = getCallPushSize(TheBinary.Architecture()); return TypePath; } model::TypePath abi::registerDefaultFunctionPrototype(Binary &Binary, std::optional MaybeABI) { if (!MaybeABI.has_value()) MaybeABI = Binary.DefaultABI(); revng_assert(*MaybeABI != ABI::Invalid); return skippingEnumSwitch<1>(*MaybeABI, [&]() { return defaultPrototype(Binary); }); }