Files
FEX-Emu--FEX/ThunkLibs/Generator/data_layout.h
T
Paulo Matos 2b4ec88dae Whole-tree reformat
This follows discussions from #3413.
Followup commits add clang-format file, script and blame ignore lists.
2024-04-12 16:26:02 +02:00

132 lines
4.3 KiB
C++

#pragma once
#include "analysis.h"
#include <clang/Frontend/FrontendAction.h>
#include <cstdint>
#include <optional>
#include <string>
#include <unordered_map>
#include <variant>
#include <vector>
struct SimpleTypeInfo {
uint64_t size_bits;
uint64_t alignment_bits;
bool operator==(const SimpleTypeInfo& other) const {
return size_bits == other.size_bits && alignment_bits == other.alignment_bits;
}
};
struct StructInfo : SimpleTypeInfo {
struct MemberInfo {
uint64_t size_bits; // size of this member. For arrays, total size of all elements
uint64_t offset_bits;
std::string type_name;
std::string member_name;
std::optional<uint64_t> array_size;
bool is_function_pointer;
bool is_integral;
bool is_signed_integer;
bool operator==(const MemberInfo& other) const {
return size_bits == other.size_bits && offset_bits == other.offset_bits &&
// The type name may differ for integral types if all other parameters are equal
(type_name == other.type_name || (is_integral && other.is_integral)) && member_name == other.member_name &&
array_size == other.array_size && is_function_pointer == other.is_function_pointer && is_integral == other.is_integral;
}
};
std::vector<MemberInfo> members;
bool operator==(const StructInfo& other) const {
return (const SimpleTypeInfo&)*this == (const SimpleTypeInfo&)other &&
std::equal(members.begin(), members.end(), other.members.begin(), other.members.end());
}
};
struct TypeInfo : std::variant<std::monostate, SimpleTypeInfo, StructInfo> {
using Parent = std::variant<std::monostate, SimpleTypeInfo, StructInfo>;
TypeInfo() = default;
TypeInfo(const SimpleTypeInfo& info)
: Parent(info) {}
TypeInfo(const StructInfo& info)
: Parent(info) {}
// Opaque declaration with no full definition.
// Pointers to these can still be passed along ABI boundaries assuming
// implementation details are only ever accessed on one side.
bool is_opaque() const {
return std::holds_alternative<std::monostate>(*this);
}
const StructInfo* get_if_struct() const {
return std::get_if<StructInfo>(this);
}
StructInfo* get_if_struct() {
return std::get_if<StructInfo>(this);
}
const SimpleTypeInfo* get_if_simple_or_struct() const {
auto as_struct = std::get_if<StructInfo>(this);
if (as_struct) {
return as_struct;
}
return std::get_if<SimpleTypeInfo>(this);
}
};
struct FuncPtrInfo {
std::array<uint8_t, 32> sha256;
std::string result;
std::vector<std::string> args;
};
struct ABI : std::unordered_map<std::string, TypeInfo> {
std::unordered_map<std::string, FuncPtrInfo> thunked_funcptrs;
int pointer_size; // in bytes
};
std::unordered_map<const clang::Type*, TypeInfo>
ComputeDataLayout(const clang::ASTContext& context, const std::unordered_map<const clang::Type*, AnalysisAction::RepackedType>& types);
// Convert the output of ComputeDataLayout to a format that isn't tied to a libclang session.
// As a consequence, type information is indexed by type name instead of clang::Type.
ABI GetStableLayout(const clang::ASTContext& context, const std::unordered_map<const clang::Type*, TypeInfo>& data_layout);
/**
* Returns the type of the given name, but replaces any mentions of integer
* types with fixed-size equivalents.
*
* Examples:
* - int -> int32_t
* - unsigned long long* -> uint64_t*
* - MyStruct -> MyStruct (no change)
*/
std::string GetTypeNameWithFixedSizeIntegers(clang::ASTContext&, clang::QualType);
enum class TypeCompatibility {
Full, // Type has matching data layout across architectures
Repackable, // Type has different data layout but can be repacked automatically
None, // Type has different data layout and cannot be repacked automatically
};
class DataLayoutCompareAction : public AnalysisAction {
public:
DataLayoutCompareAction(const ABI& guest_abi)
: guest_abi(guest_abi) {}
TypeCompatibility GetTypeCompatibility(const clang::ASTContext&, const clang::Type*,
const std::unordered_map<const clang::Type*, TypeInfo> host_abi,
std::unordered_map<const clang::Type*, TypeCompatibility>& type_compat);
FuncPtrInfo LookupGuestFuncPtrInfo(const char* funcptr_id);
protected:
const ABI& guest_abi;
};