mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
193 lines
6.2 KiB
C++
193 lines
6.2 KiB
C++
#pragma once
|
|
|
|
//
|
|
// This file is distributed under the MIT License. See LICENSE.md for details.
|
|
//
|
|
|
|
#include "revng/ADT/RecursiveCoroutine.h"
|
|
#include "revng/Model/ArrayType.h"
|
|
#include "revng/Model/CABIFunctionDefinition.h"
|
|
#include "revng/Model/EnumDefinition.h"
|
|
#include "revng/Model/Function.h"
|
|
#include "revng/Model/Identifier.h"
|
|
#include "revng/Model/NamingConfiguration.h"
|
|
#include "revng/Model/RawFunctionDefinition.h"
|
|
#include "revng/Model/StructDefinition.h"
|
|
#include "revng/Model/UnionDefinition.h"
|
|
#include "revng/Support/CommonOptions.h"
|
|
|
|
namespace model {
|
|
|
|
namespace detail {
|
|
|
|
struct TransparentStringHash {
|
|
using is_transparent = void;
|
|
|
|
std::size_t operator()(const char *Value) const {
|
|
return std::hash<std::string_view>{}(Value);
|
|
}
|
|
std::size_t operator()(const std::string &Value) const {
|
|
return std::hash<std::string_view>{}(Value);
|
|
}
|
|
std::size_t operator()(std::string_view Value) const {
|
|
return std::hash<std::string_view>{}(Value);
|
|
}
|
|
std::size_t operator()(llvm::StringRef Value) const {
|
|
return std::hash<std::string_view>{}(Value);
|
|
}
|
|
std::size_t operator()(const model::Identifier &Value) const {
|
|
return std::hash<std::string_view>{}(Value.str());
|
|
}
|
|
};
|
|
|
|
} // namespace detail
|
|
|
|
class Binary;
|
|
class VerifyHelper;
|
|
|
|
class NameBuilder {
|
|
private:
|
|
using GlobalNamespaceMap = std::unordered_map<std::string,
|
|
std::string,
|
|
detail::TransparentStringHash,
|
|
std::equal_to<>>;
|
|
|
|
std::optional<GlobalNamespaceMap> GlobalNamespace = std::nullopt;
|
|
|
|
public:
|
|
const Binary &Binary;
|
|
|
|
private:
|
|
using RFT = model::RawFunctionDefinition;
|
|
|
|
public:
|
|
NameBuilder(const model::Binary &Binary) : Binary(Binary) {}
|
|
|
|
private:
|
|
llvm::Error isNameForbidden(llvm::StringRef Name);
|
|
|
|
public:
|
|
const model::NamingConfiguration &configuration() const;
|
|
|
|
public:
|
|
// This function is triggered automatically the first time a name is
|
|
// requested.
|
|
//
|
|
// There's no need to call it manually unless you expect it to fail,
|
|
// for example, when verifying a binary.
|
|
llvm::Error populateGlobalNamespace();
|
|
|
|
bool isGlobalNamespacePopulated() const {
|
|
return GlobalNamespace.has_value();
|
|
}
|
|
|
|
private:
|
|
const GlobalNamespaceMap &globalNamespace() {
|
|
if (not GlobalNamespace.has_value()) {
|
|
auto MaybeError = populateGlobalNamespace();
|
|
revng_check(not MaybeError);
|
|
revng_assert(GlobalNamespace.has_value());
|
|
}
|
|
|
|
return *GlobalNamespace;
|
|
}
|
|
|
|
public:
|
|
[[nodiscard]] bool isGlobalSymbol(llvm::StringRef Name) {
|
|
return globalNamespace().contains(Name);
|
|
}
|
|
|
|
public:
|
|
Identifier name(const model::Segment &Segment);
|
|
Identifier name(const model::Function &Function);
|
|
Identifier name(const model::DynamicFunction &Function);
|
|
|
|
std::string llvmName(const model::Function &Function) {
|
|
std::string Result = "local_";
|
|
if (DebugNames)
|
|
Result += name(Function).str().str();
|
|
else
|
|
Result += Function.Entry().toString();
|
|
|
|
return Result;
|
|
}
|
|
|
|
public:
|
|
Identifier name(const model::TypeDefinition &Definition);
|
|
|
|
Identifier name(const model::EnumDefinition &Definition,
|
|
const model::EnumEntry &Entry);
|
|
Identifier name(const model::EnumDefinition &Definition, uint64_t Value) {
|
|
return name(Definition, Definition.Entries().at(Value));
|
|
}
|
|
|
|
Identifier name(const model::StructDefinition &Definition,
|
|
const model::StructField &Field);
|
|
Identifier name(const model::StructDefinition &Definition, uint64_t Offset) {
|
|
revng_assert(Offset <= Definition.Size());
|
|
return name(Definition, Definition.Fields().at(Offset));
|
|
}
|
|
|
|
Identifier name(const model::UnionDefinition &Definition,
|
|
const model::UnionField &Field);
|
|
Identifier name(const model::UnionDefinition &Definition, uint64_t Index) {
|
|
revng_assert(Index <= Definition.Fields().size());
|
|
return name(Definition, Definition.Fields().at(Index));
|
|
}
|
|
|
|
Identifier paddingFieldName(uint64_t Offset) const {
|
|
// Not checking anything here since the relevant checks should have already
|
|
// been done when constructing the helper.
|
|
return Identifier(std::string(configuration().structPaddingPrefix())
|
|
+ std::to_string(Offset));
|
|
}
|
|
|
|
public:
|
|
Identifier argumentName(const model::CABIFunctionDefinition &Function,
|
|
const model::Argument &Argument);
|
|
Identifier argumentName(const model::CABIFunctionDefinition &Function,
|
|
uint64_t ArgumentIndex) {
|
|
revng_assert(ArgumentIndex <= Function.Arguments().size());
|
|
return argumentName(Function, Function.Arguments().at(ArgumentIndex));
|
|
}
|
|
|
|
Identifier argumentName(const model::RawFunctionDefinition &Function,
|
|
const model::NamedTypedRegister &Argument);
|
|
Identifier argumentName(const model::RawFunctionDefinition &Function,
|
|
const model::Register::Values &Register) {
|
|
return argumentName(Function, Function.Arguments().at(Register));
|
|
}
|
|
|
|
Identifier returnValueName(const model::RawFunctionDefinition &Function,
|
|
const model::NamedTypedRegister &ReturnValue);
|
|
Identifier returnValueName(const model::RawFunctionDefinition &Function,
|
|
const model::Register::Values &Register) {
|
|
return returnValueName(Function, Function.ReturnValues().at(Register));
|
|
}
|
|
|
|
public:
|
|
Identifier artificialReturnValueWrapperName(const RFT &Function) {
|
|
// Not checking anything here since the relevant checks should have already
|
|
// been done when constructing the helper.
|
|
auto R = configuration().artificialReturnValuePrefix() + name(Function);
|
|
return Identifier(R.str());
|
|
}
|
|
|
|
private:
|
|
RecursiveCoroutine<std::string>
|
|
artificialArrayWrapperNameImpl(const model::Type &Type);
|
|
|
|
public:
|
|
Identifier artificialArrayWrapperName(const model::ArrayType &Type) {
|
|
// Not checking anything here since the relevant checks should have already
|
|
// been done when constructing the helper.
|
|
llvm::StringRef Prefix = configuration().artificialArrayWrapperPrefix();
|
|
return Identifier(std::string(Prefix)
|
|
+ std::string(artificialArrayWrapperNameImpl(Type)));
|
|
}
|
|
|
|
Identifier artificialArrayWrapperFieldName();
|
|
};
|
|
|
|
} // namespace model
|