Files
revng-revng/include/revng/Model/NameBuilder.h
2025-02-13 13:09:50 +02:00

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