mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-10 12:00:18 +02:00
124 lines
4.0 KiB
C++
124 lines
4.0 KiB
C++
#pragma once
|
|
|
|
#include <clang/Frontend/FrontendAction.h>
|
|
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <unordered_set>
|
|
#include <vector>
|
|
|
|
struct FunctionParams {
|
|
std::vector<clang::QualType> param_types;
|
|
};
|
|
|
|
struct ThunkedCallback : FunctionParams {
|
|
clang::QualType return_type;
|
|
|
|
bool is_stub = false; // Callback will be replaced by a stub that calls std::abort
|
|
bool is_guest = false; // Callback will never be called on the host
|
|
bool is_variadic = false;
|
|
};
|
|
|
|
/**
|
|
* Guest<->Host transition point.
|
|
*
|
|
* These are normally used to translate the public API of the guest to host
|
|
* function calls (ThunkedAPIFunction), but a thunk library may also define
|
|
* internal thunks that don't correspond to any function in the implemented
|
|
* API.
|
|
*/
|
|
struct ThunkedFunction : FunctionParams {
|
|
std::string function_name;
|
|
clang::QualType return_type;
|
|
|
|
// If true, param_types contains an extra size_t and the valist for marshalling through an internal function
|
|
bool is_variadic = false;
|
|
|
|
// If true, the unpacking function will call a custom fexfn_impl function
|
|
// to be provided manually instead of calling the host library function
|
|
// directly.
|
|
// This is implied e.g. for thunks generated for variadic functions
|
|
bool custom_host_impl = false;
|
|
|
|
std::string GetOriginalFunctionName() const {
|
|
const std::string suffix = "_internal";
|
|
assert(function_name.length() > suffix.size());
|
|
assert((std::string_view { &*function_name.end() - suffix.size(), suffix.size() } == suffix));
|
|
return function_name.substr(0, function_name.size() - suffix.size());
|
|
}
|
|
|
|
// Maps parameter index to ThunkedCallback
|
|
std::unordered_map<unsigned, ThunkedCallback> callbacks;
|
|
|
|
clang::FunctionDecl* decl;
|
|
};
|
|
|
|
/**
|
|
* Function that is part of the API of the thunked library.
|
|
*
|
|
* For each of these, there is:
|
|
* - A publicly visible guest entrypoint (usually auto-generated but may be manually defined)
|
|
* - A pointer to the native host library function loaded through dlsym (or a user-provided function specified via host_loader)
|
|
* - A ThunkedFunction with the same function_name (possibly suffixed with _internal)
|
|
*/
|
|
struct ThunkedAPIFunction : FunctionParams {
|
|
std::string function_name;
|
|
|
|
clang::QualType return_type;
|
|
|
|
// name of the function to load the native host symbol with
|
|
std::string host_loader;
|
|
|
|
// If true, no guest-side implementation of this function will be autogenerated
|
|
bool custom_guest_impl;
|
|
|
|
bool is_variadic;
|
|
|
|
// Index of the symbol table to store this export in (see guest_symtables).
|
|
// If empty, a library export is created, otherwise the function is entered into a function pointer array
|
|
std::optional<std::size_t> symtable_namespace;
|
|
};
|
|
|
|
struct NamespaceInfo {
|
|
clang::DeclContext* context;
|
|
|
|
std::string name;
|
|
|
|
// Function to load native host library functions with.
|
|
// This function must be defined manually with the signature "void* func(void*, const char*)"
|
|
std::string host_loader;
|
|
|
|
bool generate_guest_symtable;
|
|
|
|
bool indirect_guest_calls;
|
|
};
|
|
|
|
class AnalysisAction : public clang::ASTFrontendAction {
|
|
public:
|
|
AnalysisAction() {
|
|
decl_contexts.push_back(nullptr); // global namespace (replaced by getTranslationUnitDecl later)
|
|
}
|
|
|
|
void ExecuteAction() override;
|
|
|
|
std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance&, clang::StringRef /*file*/) override;
|
|
|
|
protected:
|
|
// Build the internal API representation by processing fex_gen_config and other annotated entities
|
|
void ParseInterface(clang::ASTContext&);
|
|
|
|
// Called from ExecuteAction() after parsing is complete
|
|
virtual void EmitOutput(clang::ASTContext&) {};
|
|
|
|
std::vector<clang::DeclContext*> decl_contexts;
|
|
|
|
std::vector<ThunkedFunction> thunks;
|
|
std::vector<ThunkedAPIFunction> thunked_api;
|
|
std::unordered_set<const clang::Type*> funcptr_types;
|
|
|
|
std::optional<unsigned> lib_version;
|
|
std::vector<NamespaceInfo> namespaces;
|
|
};
|