#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gen.h" #include "utils.h" static void ParseParameter(clang::ASTContext* AST, WrapperGenerator* Gen, clang::QualType ParmType, FuncInfo* Func) { using namespace clang; (void)AST; (void)Func; if (ParmType->isFunctionPointerType()) { auto ProtoType = ParmType->getPointeeType()->getAs(); for (unsigned i = 0; i < ProtoType->getNumParams(); i++) { ParseParameter(AST, Gen, ProtoType->getParamType(i), Func); } } else if (ParmType->isPointerType()) { auto PointeeType = ParmType->getPointeeType(); if (PointeeType->isRecordType()) { if (Gen->records.find(StripTypedef(PointeeType)) == Gen->records.end()) { auto Record = &Gen->records[StripTypedef(PointeeType)]; if (PointeeType->isUnionType()) { Record->is_union = true; } Record->type = StripTypedef(PointeeType); Record->decl = PointeeType->getAs()->getDecl(); Record->type_name = Record->decl->getIdentifier() ? Record->decl->getIdentifier()->getName().str() : ""; } } else if (PointeeType->isPointerType()) { PointeeType = PointeeType->getPointeeType(); if (PointeeType->isRecordType()) { if (Gen->records.find(StripTypedef(PointeeType)) == Gen->records.end()) { auto Record = &Gen->records[StripTypedef(PointeeType)]; if (PointeeType->isUnionType()) { Record->is_union = true; } Record->type = StripTypedef(PointeeType); Record->decl = PointeeType->getAs()->getDecl(); Record->type_name = Record->decl->getIdentifier() ? Record->decl->getIdentifier()->getName().str() : ""; } } } } else if (ParmType->isRecordType()) { if (Gen->records.find(StripTypedef(ParmType)) == Gen->records.end()) { auto Record = &Gen->records[StripTypedef(ParmType)]; if (ParmType->isUnionType()) { Record->is_union = true; } Record->type = StripTypedef(ParmType); Record->decl = ParmType->getAs()->getDecl(); Record->type_name = Record->decl->getIdentifier() ? Record->decl->getIdentifier()->getName().str() : ""; } } } static void ParseFunction(clang::ASTContext* AST, WrapperGenerator* Gen, clang::FunctionDecl* Decl) { using namespace clang; auto Type = Decl->getType().getTypePtr(); auto FuncInfo = &Gen->funcs[Type]; FuncInfo->type = Type; FuncInfo->func_name = Decl->getNameAsString(); FuncInfo->decl = Decl; FuncInfo->callback_args.resize(Decl->getNumParams()); if (Decl->getAttr()) { FuncInfo->is_weak = true; } if (Decl->isVariadic()) { FuncInfo->is_variadaic = true; } for (unsigned i = 0; i < Decl->getNumParams(); i++) { auto ParmDecl = Decl->getParamDecl(i); if (ParmDecl->getType()->isFunctionPointerType()) { FuncInfo->callback_args[i] = ParmDecl->getType().getTypePtr(); FuncInfo->has_callback_arg = true; } else { FuncInfo->callback_args[i] = nullptr; } ParseParameter(AST, Gen, ParmDecl->getType(), FuncInfo); } } class MyASTVisitor : public clang::RecursiveASTVisitor { public: MyASTVisitor(clang::ASTContext* ctx) : Ctx(ctx) {} MyASTVisitor(clang::ASTContext* ctx, WrapperGenerator* gen) : Ctx(ctx), Gen(gen) {} bool VisitFunctionDecl(clang::FunctionDecl* Decl) { ParseFunction(Ctx, Gen, Decl); return true; } private: clang::ASTContext* Ctx; WrapperGenerator* Gen; }; class MyASTConsumer : public clang::ASTConsumer { public: MyASTConsumer(clang::ASTContext* Context, const std::string& libname, const std::string& host_triple, const std::string& guest_triple) : Visitor(Context, &Generator) { Generator.Init(libname, host_triple, guest_triple); } void HandleTranslationUnit(clang::ASTContext &Ctx) override { Visitor.TraverseDecl(Ctx.getTranslationUnitDecl()); std::cout << "--------------- Libclangtooling parse complete -----------------\n"; Generator.Prepare(&Ctx); std::cout << "--------------- Generator prepare complete -----------------\n"; std::ofstream FuncDeclFile("wrapped" + Generator.libname + "_private.h", std::ios::out); FuncDeclFile << Generator.GenFuncDeclare(&Ctx); FuncDeclFile.close(); std::ofstream FuncDefineFile("wrapped" + Generator.libname + ".c", std::ios::out); FuncDefineFile << "#include \n" "#include \n" "#include \n" "#define _GNU_SOURCE /* See feature_test_macros(7) */\n" "#include \n" "\n" "#include \"wrappedlibs.h\"\n" "\n" "#include \"debug.h\"\n" "#include \"wrapper.h\"\n" "#include \"bridge.h\"\n" "#include \"x64emu.h\"\n" "#include \"box64context.h\"\n" "\n" "const char* " + Generator.libname + "Name = \"" + Generator.libname + "\";\n" "#define LIBNAME " + Generator.libname + "\n" "\n" "#define ADDED_FUNCTIONS() \\\n" "\n" "#include \"generated/wrapped" + Generator.libname + "types.h\"\n"; FuncDefineFile << Generator.GenRecordDeclare(&Ctx); FuncDefineFile << Generator.GenRecordConvert(&Ctx); FuncDefineFile << Generator.GenCallbackWrap(&Ctx); FuncDefineFile << Generator.GenFuncDefine(&Ctx); FuncDefineFile.close(); std::cout << "--------------- Generator gen complete -----------------\n"; } private: MyASTVisitor Visitor; WrapperGenerator Generator; }; class MyGenAction : public clang::ASTFrontendAction { public: MyGenAction(const std::string& libname, const std::string& host_triple, const std::string& guest_triple) : libname(libname), host_triple(host_triple), guest_triple(guest_triple) {} std::unique_ptr CreateASTConsumer(clang::CompilerInstance& Compiler, clang::StringRef file) override { (void)file; return std::make_unique(&Compiler.getASTContext(), libname, host_triple, guest_triple); } private: std::string libname; std::string host_triple; std::string guest_triple; }; class MyFrontendActionFactory : public clang::tooling::FrontendActionFactory { public: MyFrontendActionFactory(const std::string& libname, const std::string& host_triple, const std::string& guest_triple) : libname(libname), host_triple(host_triple), guest_triple(guest_triple) {} private: std::unique_ptr create() override { return std::make_unique(libname, host_triple, guest_triple); } private: std::string libname; std::string host_triple; std::string guest_triple; };