update broma

This commit is contained in:
altalk23 2023-08-15 12:46:49 +03:00
parent 26893f1b80
commit 0a584327ff
8 changed files with 33 additions and 232 deletions

View file

@ -4,7 +4,7 @@ project(Codegen LANGUAGES C CXX)
include(../cmake/CPM.cmake) include(../cmake/CPM.cmake)
CPMAddPackage("gh:fmtlib/fmt#9.1.0") CPMAddPackage("gh:fmtlib/fmt#9.1.0")
CPMAddPackage("gh:geode-sdk/Broma#b1adda0") CPMAddPackage("gh:geode-sdk/Broma#a9c1d2e")
file(GLOB SOURCES file(GLOB SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp

View file

@ -1,5 +1,4 @@
#include "Shared.hpp" #include "Shared.hpp"
#include "TypeOpt.hpp"
namespace { namespace {
namespace format_strings { namespace format_strings {
@ -76,9 +75,6 @@ Result<tulip::hook::HandlerMetadata> geode::modifier::handlerMetadataForAddress(
std::string generateAddressHeader(Root& root) { std::string generateAddressHeader(Root& root) {
std::string output; std::string output;
TypeBank bank;
bank.loadFrom(root);
output += format_strings::address_begin; output += format_strings::address_begin;
for (auto& c : root.classes) { for (auto& c : root.classes) {
@ -92,14 +88,12 @@ std::string generateAddressHeader(Root& root) {
} }
if (codegen::getStatus(field) == BindStatus::Binded) { if (codegen::getStatus(field) == BindStatus::Binded) {
auto const ids = bank.getIDs(fn->beginning, c.name);
address_str = fmt::format( address_str = fmt::format(
"addresser::get{}Virtual(Resolve<{}>::func(&{}::{}))", "addresser::get{}Virtual(Resolve<{}>::func(&{}::{}))",
str_if("Non", !fn->beginning.is_virtual), str_if("Non", !fn->prototype.is_virtual),
codegen::getParameterTypes(fn->beginning), codegen::getParameterTypes(fn->prototype),
field.parent, field.parent,
fn->beginning.name fn->prototype.name
); );
} }
else if (codegen::getStatus(field) == BindStatus::NeedsBinding) { else if (codegen::getStatus(field) == BindStatus::NeedsBinding) {

View file

@ -187,7 +187,7 @@ std::string generateBindingHeader(Root& root, ghc::filesystem::path const& singl
bool unimplementedField = false; bool unimplementedField = false;
for (auto field : cls.fields) { for (auto field : cls.fields) {
FunctionBegin* fb; MemberFunctionProto* fb;
char const* used_format = format_strings::function_definition; char const* used_format = format_strings::function_definition;
std::string addressDocs; std::string addressDocs;
@ -212,11 +212,11 @@ std::string generateBindingHeader(Root& root, ghc::filesystem::path const& singl
} }
continue; continue;
} else if (auto fn = field.get_as<OutOfLineField>()) { } else if (auto fn = field.get_as<OutOfLineField>()) {
fb = &fn->beginning; fb = &fn->prototype;
addressDocs = " * @note[short] Out of line\n"; addressDocs = " * @note[short] Out of line\n";
} else if (auto fn = field.get_as<FunctionBindField>()) { } else if (auto fn = field.get_as<FunctionBindField>()) {
fb = &fn->beginning; fb = &fn->prototype;
if (!codegen::platformNumber(fn->binds)) { if (!codegen::platformNumber(fn->binds)) {
used_format = format_strings::error_definition; used_format = format_strings::error_definition;

View file

@ -1,5 +1,4 @@
#include "Shared.hpp" #include "Shared.hpp"
#include "TypeOpt.hpp"
#include <iostream> #include <iostream>
#include <set> #include <set>
@ -58,9 +57,6 @@ namespace geode::modifier {{
std::string generateModifyHeader(Root& root, ghc::filesystem::path const& singleFolder) { std::string generateModifyHeader(Root& root, ghc::filesystem::path const& singleFolder) {
std::string output; std::string output;
TypeBank bank;
bank.loadFrom(root);
for (auto c : root.classes) { for (auto c : root.classes) {
if (c.name == "cocos2d") continue; if (c.name == "cocos2d") continue;
@ -108,7 +104,6 @@ std::string generateModifyHeader(Root& root, ghc::filesystem::path const& single
for (auto& f : c.fields) { for (auto& f : c.fields) {
if (codegen::getStatus(f) != BindStatus::Unbindable) { if (codegen::getStatus(f) != BindStatus::Unbindable) {
auto begin = f.get_fn(); auto begin = f.get_fn();
auto func = TypeBank::makeFunc(*begin, c.name);
std::string format_string; std::string format_string;
@ -127,11 +122,10 @@ std::string generateModifyHeader(Root& root, ghc::filesystem::path const& single
single_output += fmt::format( single_output += fmt::format(
format_string, format_string,
fmt::arg("addr_index", f.field_id), fmt::arg("addr_index", f.field_id),
fmt::arg("pure_index", bank.getPure(*begin, c.name)),
fmt::arg("class_name", c.name), fmt::arg("class_name", c.name),
fmt::arg("function_name", begin->name), fmt::arg("function_name", begin->name),
fmt::arg("function_convention", codegen::getModifyConventionName(f)), fmt::arg("function_convention", codegen::getModifyConventionName(f)),
fmt::arg("parameter_types", fmt::join(func.parameter_types, ", ")) fmt::arg("parameter_types", codegen::getParameterTypes(*begin))
); );
} }
} }

View file

@ -13,6 +13,8 @@ using std::istreambuf_iterator;
#pragma warning(disable : 4996) #pragma warning(disable : 4996)
#endif #endif
using namespace broma;
std::string generateAddressHeader(Root& root); std::string generateAddressHeader(Root& root);
std::string generateModifyHeader(Root& root, ghc::filesystem::path const& singleFolder); std::string generateModifyHeader(Root& root, ghc::filesystem::path const& singleFolder);
std::string generateWrapperHeader(Root& root); std::string generateWrapperHeader(Root& root);
@ -84,15 +86,15 @@ namespace codegen {
} }
inline BindStatus getStatusWithPlatform(Platform p, Field const& field) { inline BindStatus getStatusWithPlatform(Platform p, Field const& field) {
FunctionBegin const* fb; MemberFunctionProto const* fb;
if (auto fn = field.get_as<FunctionBindField>()) { if (auto fn = field.get_as<FunctionBindField>()) {
if (platformNumberWithPlatform(p, fn->binds)) return BindStatus::NeedsBinding; if (platformNumberWithPlatform(p, fn->binds)) return BindStatus::NeedsBinding;
fb = &fn->beginning; fb = &fn->prototype;
} }
else if (auto fn = field.get_as<OutOfLineField>()) { else if (auto fn = field.get_as<OutOfLineField>()) {
fb = &fn->beginning; fb = &fn->prototype;
} }
else return BindStatus::Unbindable; else return BindStatus::Unbindable;
@ -122,7 +124,7 @@ namespace codegen {
return getStatusWithPlatform(codegen::platform, field); return getStatusWithPlatform(codegen::platform, field);
} }
inline std::string getParameters(FunctionBegin const& f) { // int p0, float p1 inline std::string getParameters(FunctionProto const& f) { // int p0, float p1
std::vector<std::string> parameters; std::vector<std::string> parameters;
for (auto& [t, n] : f.args) { for (auto& [t, n] : f.args) {
@ -132,7 +134,7 @@ namespace codegen {
return fmt::format("{}", fmt::join(parameters, ", ")); return fmt::format("{}", fmt::join(parameters, ", "));
} }
inline std::string getParameterTypes(FunctionBegin const& f) { // int, float inline std::string getParameterTypes(FunctionProto const& f) { // int, float
std::vector<std::string> parameters; std::vector<std::string> parameters;
for (auto& [t, n] : f.args) { for (auto& [t, n] : f.args) {
@ -142,7 +144,7 @@ namespace codegen {
return fmt::format("{}", fmt::join(parameters, ", ")); return fmt::format("{}", fmt::join(parameters, ", "));
} }
inline std::string getParameterNames(FunctionBegin const& f) { // p0, p1 inline std::string getParameterNames(FunctionProto const& f) { // p0, p1
std::vector<std::string> parameters; std::vector<std::string> parameters;
for (auto& [t, n] : f.args) { for (auto& [t, n] : f.args) {

View file

@ -1,5 +1,4 @@
#include "Shared.hpp" #include "Shared.hpp"
#include "TypeOpt.hpp"
namespace { namespace format_strings { namespace { namespace format_strings {
char const* source_start = R"CAC( char const* source_start = R"CAC(
@ -118,9 +117,6 @@ auto {class_name}::{function_name}({parameters}){const} -> decltype({function_na
std::string generateBindingSource(Root& root) { std::string generateBindingSource(Root& root) {
std::string output(format_strings::source_start); std::string output(format_strings::source_start);
TypeBank bank;
bank.loadFrom(root);
for (auto& c : root.classes) { for (auto& c : root.classes) {
for (auto& f : c.fields) { for (auto& f : c.fields) {
@ -138,25 +134,25 @@ std::string generateBindingSource(Root& root) {
continue; continue;
} }
switch (fn->beginning.type) { switch (fn->prototype.type) {
case FunctionType::Ctor: case FunctionType::Ctor:
case FunctionType::Dtor: case FunctionType::Dtor:
output += fmt::format(format_strings::ool_structor_function_definition, output += fmt::format(format_strings::ool_structor_function_definition,
fmt::arg("function_name", fn->beginning.name), fmt::arg("function_name", fn->prototype.name),
fmt::arg("const", str_if(" const ", fn->beginning.is_const)), fmt::arg("const", str_if(" const ", fn->prototype.is_const)),
fmt::arg("class_name", c.name), fmt::arg("class_name", c.name),
fmt::arg("parameters", codegen::getParameters(fn->beginning)), fmt::arg("parameters", codegen::getParameters(fn->prototype)),
fmt::arg("definition", fn->inner) fmt::arg("definition", fn->inner)
); );
break; break;
default: default:
output += fmt::format(format_strings::ool_function_definition, output += fmt::format(format_strings::ool_function_definition,
fmt::arg("function_name", fn->beginning.name), fmt::arg("function_name", fn->prototype.name),
fmt::arg("const", str_if(" const ", fn->beginning.is_const)), fmt::arg("const", str_if(" const ", fn->prototype.is_const)),
fmt::arg("class_name", c.name), fmt::arg("class_name", c.name),
fmt::arg("parameters", codegen::getParameters(fn->beginning)), fmt::arg("parameters", codegen::getParameters(fn->prototype)),
fmt::arg("definition", fn->inner), fmt::arg("definition", fn->inner),
fmt::arg("return", fn->beginning.ret.name) fmt::arg("return", fn->prototype.ret.name)
); );
break; break;
} }
@ -172,7 +168,7 @@ std::string generateBindingSource(Root& root) {
char const* used_declare_format; char const* used_declare_format;
switch (fn->beginning.type) { switch (fn->prototype.type) {
case FunctionType::Normal: case FunctionType::Normal:
used_declare_format = format_strings::declare_member; used_declare_format = format_strings::declare_member;
break; break;
@ -184,27 +180,22 @@ std::string generateBindingSource(Root& root) {
break; break;
} }
if (fn->beginning.is_static) if (fn->prototype.is_static)
used_declare_format = format_strings::declare_static; used_declare_format = format_strings::declare_static;
if (fn->beginning.is_virtual && fn->beginning.type != FunctionType::Dtor) if (fn->prototype.is_virtual && fn->prototype.type != FunctionType::Dtor)
used_declare_format = format_strings::declare_virtual; used_declare_format = format_strings::declare_virtual;
auto ids = bank.getIDs(fn->beginning, c.name);
output += fmt::format(used_declare_format, output += fmt::format(used_declare_format,
fmt::arg("class_name", c.name), fmt::arg("class_name", c.name),
fmt::arg("unqualified_class_name", codegen::getUnqualifiedClassName(c.name)), fmt::arg("unqualified_class_name", codegen::getUnqualifiedClassName(c.name)),
fmt::arg("const", str_if(" const ", fn->beginning.is_const)), fmt::arg("const", str_if(" const ", fn->prototype.is_const)),
fmt::arg("convention", codegen::getModifyConventionName(f)), fmt::arg("convention", codegen::getModifyConventionName(f)),
fmt::arg("function_name", fn->beginning.name), fmt::arg("function_name", fn->prototype.name),
fmt::arg("meta_index", ids.meta),
fmt::arg("member_index", ids.member),
fmt::arg("ret_index", ids.ret),
fmt::arg("addr_index", f.field_id), fmt::arg("addr_index", f.field_id),
fmt::arg("parameters", codegen::getParameters(fn->beginning)), fmt::arg("parameters", codegen::getParameters(fn->prototype)),
fmt::arg("parameter_types", codegen::getParameterTypes(fn->beginning)), fmt::arg("parameter_types", codegen::getParameterTypes(fn->prototype)),
fmt::arg("arguments", codegen::getParameterNames(fn->beginning)), fmt::arg("arguments", codegen::getParameterNames(fn->prototype)),
fmt::arg("parameter_comma", str_if(", ", !fn->beginning.args.empty())) fmt::arg("parameter_comma", str_if(", ", !fn->prototype.args.empty()))
); );
} }
} }

View file

@ -1,180 +0,0 @@
#include "Shared.hpp"
#include <set>
#include <algorithm>
namespace {
enum class FuncType : int {
Structor,
Static,
Member
};
struct Func {
std::string return_type;
bool is_const;
std::string class_name;
std::vector<std::string> parameter_types;
FuncType type;
std::string toStr() const {
return fmt::format("{}{}{}{}{}",
return_type,
class_name,
fmt::join(parameter_types, ","),
is_const ? " const " : "",
static_cast<int>(type)
);
}
bool operator<(Func const& f) const {
return toStr() < f.toStr();
}
bool operator==(Func const& f) const {
return (
return_type == f.return_type &&
is_const == f.is_const &&
class_name == f.class_name &&
parameter_types == f.parameter_types &&
type == f.type
);
}
};
struct Ids {
int ret = -1;
int func = -1;
int pure = -1;
int meta = -1;
int member = -1;
};
class TypeBank {
std::vector<Func> m_stuff;
public:
static std::string getReturn(FunctionBegin const& fn, std::string const& parent) {
if (fn.type != FunctionType::Normal)
return "void";
if (fn.ret.name == "auto") {
std::vector<std::string> declvals;
for (auto& [t, n] : fn.args) {
declvals.push_back(fmt::format("std::declval<{}>()", t.name));
}
return fmt::format(
fn.is_static ? "decltype({}::{}({}))" : "decltype(std::declval<{}>().{}({}))",
parent,
fn.name,
fmt::join(declvals, ", ")
);
}
return fn.ret.name;
}
static Func makeFunc(FunctionBegin const& fn, std::string const& parent) {
Func f;
f.return_type = TypeBank::getReturn(fn, parent);
f.is_const = fn.is_const;
f.class_name = parent;
for (auto& arg : fn.args) {
f.parameter_types.push_back(arg.first.name);
}
if (fn.is_static)
f.type = FuncType::Static;
else if (fn.type != FunctionType::Normal)
f.type = FuncType::Structor;
else
f.type = FuncType::Member;
return f;
}
void loadFrom(Root& root) {
for (auto& c : root.classes) {
for (auto& f : c.fields) {
if (codegen::getStatus(f) == BindStatus::Unbindable)
continue;
m_stuff.push_back(TypeBank::makeFunc(*f.get_fn(), c.name));
}
}
std::sort(m_stuff.begin(), m_stuff.end());
m_stuff.erase(std::unique(m_stuff.begin(), m_stuff.end()), m_stuff.end());
}
std::vector<Func> const& typeList() { return m_stuff; }
Ids getIDs(FunctionBegin const& fn, std::string const& parent) {
Ids out;
Func in_f = TypeBank::makeFunc(fn, parent);
int i = 0;
for (auto f : m_stuff) {
if (out.ret == -1 && f.return_type == in_f.return_type) {
out.ret = i;
}
if (out.func == -1) {
if (in_f.type == FuncType::Member) {
if (f == in_f) out.func = i;
} else if (in_f.type == FuncType::Structor) {
if (
f.return_type == in_f.return_type &&
f.class_name == in_f.class_name &&
f.is_const == in_f.is_const &&
f.parameter_types == in_f.parameter_types
) out.func = i;
} else {
if (
f.return_type == in_f.return_type &&
f.parameter_types == in_f.parameter_types &&
f.type == in_f.type
) out.func = i;
}
}
if (out.meta == -1 || out.member == -1) {
Func assume_member = f;
assume_member.type = FuncType::Member;
if (in_f == assume_member) {
out.meta = i;
} else if (out.func != -1) {
out.meta = out.func;
}
}
if (out.pure == -1 && f.return_type == in_f.return_type && f.parameter_types == in_f.parameter_types) {
out.pure = i;
}
if (out.ret != -1 && out.func != -1 && out.pure != -1)
break;
++i;
}
out.member = out.func;
return out;
}
int getPure(FunctionBegin const& fn, std::string const& parent) {
Func in_f = TypeBank::makeFunc(fn, parent);
int i = 0;
for (auto f : m_stuff) {
if (f.return_type == in_f.return_type && f.parameter_types == in_f.parameter_types) {
return i;
}
++i;
}
return -1;
}
};
}