diff --git a/BUILD.gn b/BUILD.gn index f8c78ee6ccb1382b9669f0c6848eacdd06be8808..bbe7d8a4534cc0ece4d6b4e00e9623ff48635c49 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -17,6 +17,7 @@ import("//build/ohos.gni") group("ets_frontend_build") { deps = [ "./es2panda:es2panda_build", + "./merge_abc:merge_proto_abc_build", "./ts2panda:ark_ts2abc_build", ] } diff --git a/es2panda/BUILD.gn b/es2panda/BUILD.gn index 6bd30c9e88356a4c903933c014cfdfab79c0a1c9..474b1604ead5fd781687a3642aaab202ca9674fe 100644 --- a/es2panda/BUILD.gn +++ b/es2panda/BUILD.gn @@ -239,6 +239,7 @@ es2panda_src = [ "util/bitset.cpp", "util/dumper.cpp", "util/helpers.cpp", + "util/moduleHelpers.cpp", "util/ustring.cpp", ] @@ -383,6 +384,13 @@ ohos_static_library("es2panda_lib") { "//third_party/icu/icu4c:static_icuuc", ] + if (enable_bytecode_optimizer) { + deps += [ + "$ark_root/bytecode_optimizer:libarkbytecodeopt_frontend_static", + "$ark_root/compiler:libarkcompiler_frontend_static", + ] + } + cflags = [ "-Wno-c++20-designator", "-Wno-implicit-fallthrough", @@ -398,9 +406,15 @@ ohos_executable("es2panda") { include_dirs = [ "./aot" ] - configs = [ ":es2abc_config_common" ] + configs = [ + ":es2abc_config_common", + "//arkcompiler/ets_frontend/merge_abc:panda_assembly_proto_public_config", + ] - deps = [ ":es2panda_lib" ] + deps = [ + ":es2panda_lib", + "//arkcompiler/ets_frontend/merge_abc:panda_assembly_proto_static", + ] ldflags = [] if (is_linux) { @@ -428,13 +442,6 @@ ohos_executable("es2panda") { ldflags += [ "-lc++" ] } - if (enable_bytecode_optimizer) { - deps += [ - "$ark_root/bytecode_optimizer:libarkbytecodeopt_frontend_static", - "$ark_root/compiler:libarkcompiler_frontend_static", - ] - } - output_name = "es2abc" install_enable = true subsystem_name = "ark" diff --git a/es2panda/aot/main.cpp b/es2panda/aot/main.cpp index 3bc260f8150e2cd543210d4183f2fad673a5c831..641d85bf87da381488aea293bcdf0ed3d1deadbd 100644 --- a/es2panda/aot/main.cpp +++ b/es2panda/aot/main.cpp @@ -13,28 +13,21 @@ * limitations under the License. */ -#include -#ifdef ENABLE_BYTECODE_OPT -#include -#include -#else -#include #include #include -#endif #include #include #include #include +#include #include +#include +#include #include -#include namespace panda::es2panda::aot { - using mem::MemConfig; - class MemManager { public: explicit MemManager() @@ -87,90 +80,101 @@ static void DumpPandaFileSizeStatistic(std::map &stat) std::cout << "total: " << totalSize << std::endl; } -static int GenerateProgram(panda::pandasm::Program *prog, std::unique_ptr &options) +static bool GenerateProgram(std::vector &progs, + std::unique_ptr &options) { - const std::string output = options->CompilerOutput(); + if (progs.size() == 0) { + std::cerr << "Failed to generate program " << std::endl; + return false; + } + int optLevel = options->OptLevel(); - const es2panda::CompilerOptions compilerOptions = options->CompilerOptions(); bool dumpSize = options->SizeStat(); - std::map stat; - std::map *statp = optLevel != 0 ? &stat : nullptr; - panda::pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps {}; - panda::pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp = optLevel != 0 ? &maps : nullptr; - -#ifdef PANDA_WITH_BYTECODE_OPTIMIZER - if (optLevel != 0) { - const uint32_t COMPONENT_MASK = panda::Logger::Component::ASSEMBLER | - panda::Logger::Component::BYTECODE_OPTIMIZER | - panda::Logger::Component::COMPILER; - panda::Logger::InitializeStdLogging(panda::Logger::Level::ERROR, COMPONENT_MASK); - - if (!panda::pandasm::AsmEmitter::Emit(output, *prog, statp, mapsp, true)) { - return 1; + const std::string output = options->CompilerOutput(); + const es2panda::CompilerOptions compilerOptions = options->CompilerOptions(); + if (compilerOptions.dumpAsm || compilerOptions.dumpLiteralBuffer) { + for (auto *prog : progs) { + if (compilerOptions.dumpAsm) { + es2panda::Compiler::DumpAsm(prog); + } + + if (compilerOptions.dumpLiteralBuffer) { + panda::es2panda::util::Dumper::DumpLiterals(prog->literalarray_table); + } } - - panda::bytecodeopt::options.SetOptLevel(optLevel); - panda::bytecodeopt::OptimizeBytecode(prog, mapsp, output, true, true); - } -#endif - - if (compilerOptions.dumpAsm) { - es2panda::Compiler::DumpAsm(prog); } - if (output.empty()) { - GenerateBase64Output(prog, mapsp); - return 0; - } + if (progs.size() > 1) { + if (!panda::pandasm::AsmEmitter::EmitPrograms(output, progs, true)) { + std::cerr << "Failed to emit merged program " << std::endl; + return false; + } + } else { + auto *prog = progs[0]; + std::map stat; + std::map *statp = optLevel != 0 ? &stat : nullptr; + panda::pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps {}; + panda::pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp = optLevel != 0 ? &maps : nullptr; + + if (output.empty()) { + GenerateBase64Output(prog, mapsp); + return true; + } - if (!panda::pandasm::AsmEmitter::Emit(output, *prog, statp, mapsp, true)) { - return 1; - } + if (options->compilerProtoOutput().size() > 0) { + panda::proto::ProtobufSnapshotGenerator::GenerateSnapshot(*prog, options->compilerProtoOutput()); + return true; + } - if (compilerOptions.dumpLiteralBuffer) { - panda::es2panda::util::Dumper::DumpLiterals(prog->literalarray_table); - } + if (!panda::pandasm::AsmEmitter::Emit(output, *prog, statp, mapsp, true)) { + return false; + } - if (dumpSize && optLevel != 0) { - DumpPandaFileSizeStatistic(stat); + if (dumpSize && optLevel != 0) { + DumpPandaFileSizeStatistic(stat); + } } - return 0; + return true; } int Run(int argc, const char **argv) { auto options = std::make_unique(); - if (!options->Parse(argc, argv)) { std::cerr << options->ErrorMsg() << std::endl; return 1; } - es2panda::Compiler compiler(options->Extension(), options->ThreadCount()); - es2panda::SourceFile input(options->SourceFile(), options->ParserInput(), options->ScriptKind()); + std::vector programs; + std::unordered_map programsInfo; + panda::ArenaAllocator allocator(panda::SpaceType::SPACE_TYPE_COMPILER, nullptr, true); - auto *program = compiler.Compile(input, options->CompilerOptions()); + std::unordered_map *cachePrograms = nullptr; - if (!program) { - const auto &err = compiler.GetError(); + if (!options->CacheFile().empty()) { + cachePrograms = proto::ProtobufSnapshotGenerator::GetCacheContext(options->CacheFile(), + options->CompilerOptions().isDebug, &allocator); + } - if (err.Message().empty() && options->ParseOnly()) { - return 0; - } + Compiler::CompileFiles(options->CompilerOptions(), cachePrograms, programs, programsInfo, &allocator); - std::cerr << err.TypeString() << ": " << err.Message(); - std::cerr << " [" << options->SourceFile() << ":" << err.Line() << ":" << err.Col() << "]" << std::endl; + if (!options->NpmModuleEntryList().empty()) { + es2panda::util::ModuleHelpers::CompileNpmModuleEntryList(options->NpmModuleEntryList(), cachePrograms, + programs, programsInfo, &allocator); + } - return err.ErrorCode(); + if (!GenerateProgram(programs, options)) { + return 1; } - GenerateProgram(program, options); - delete program; + if (!options->CacheFile().empty()) { + proto::ProtobufSnapshotGenerator::UpdateCacheFile(programsInfo, options->CompilerOptions().isDebug, + options->CacheFile()); + } return 0; } - } // namespace panda::es2panda::aot int main(int argc, const char **argv) diff --git a/es2panda/aot/options.cpp b/es2panda/aot/options.cpp index 6ad7b2a8a942bc081511992f65ba5f95070b4f92..fd09afa9999ce9b5163b9415c38e199ddaef0736 100644 --- a/es2panda/aot/options.cpp +++ b/es2panda/aot/options.cpp @@ -15,15 +15,22 @@ #include "options.h" +#include "mergeProgram.h" +#include "os/file.h" #include +#if defined(PANDA_TARGET_WINDOWS) +#include +#else +#include +#endif -#include +#include #include +#include namespace panda::es2panda::aot { - template -T BaseName(T const &path, T const &delims = "/") +T BaseName(T const &path, T const &delims = std::string(panda::os::file::File::GetPathDelim())) { return path.substr(path.find_last_of(delims) + 1); } @@ -35,8 +42,79 @@ T RemoveExtension(T const &filename) return P > 0 && P != T::npos ? filename.substr(0, P) : filename; } -// Options +static std::string FormatRecordName(const std::string &recordName) +{ + return recordName + "."; +} + +static std::vector GetStringItems(std::string &input, const std::string &delimiter) +{ + std::vector items; + size_t pos = 0; + std::string token; + while ((pos = input.find(delimiter)) != std::string::npos) { + token = input.substr(0, pos); + if (!token.empty()) { + items.push_back(token); + } + input.erase(0, pos + delimiter.length()); + } + if (!input.empty()) { + items.push_back(input); + } + return items; +} + +bool Options::CollectInputFilesFromFileList(const std::string &input) +{ + std::ifstream ifs; + std::string line; + ifs.open(input.c_str()); + if (!ifs.is_open()) { + std::cerr << "Failed to open source list: " << input << std::endl; + return false; + } + + constexpr size_t ITEM_COUNT = 3; + while (std::getline(ifs, line)) { + const std::string seperator = ";"; + std::vector itemList = GetStringItems(line, seperator); + if (itemList.size() != ITEM_COUNT) { + std::cerr << "Failed to parse input file" << std::endl; + return false; + } + std::string fileName = itemList[0]; + std::string recordName = FormatRecordName(itemList[1]); + parser::ScriptKind scriptKind; + if (itemList[2] == "script") { + scriptKind = parser::ScriptKind::SCRIPT; + } else if (itemList[2] == "commonjs") { + scriptKind = parser::ScriptKind::COMMONJS; + } else { + scriptKind = parser::ScriptKind::MODULE; + } + + es2panda::SourceFile src(fileName, recordName, scriptKind); + sourceFiles_.push_back(src); + } + return true; +} + +bool Options::CollectInputFilesFromFileDirectory(const std::string &input, const std::string &extension) +{ + std::vector files; + if (!proto::MergeProgram::GetProtoFiles(input, extension, files)) { + return false; + } + for (auto &f : files) { + es2panda::SourceFile src(f, BaseName(f), scriptKind_); + sourceFiles_.push_back(src); + } + return true; +} + +// Options Options::Options() : argparser_(new panda::PandArgParser()) {} Options::~Options() @@ -62,16 +140,22 @@ bool Options::Parse(int argc, const char **argv) panda::PandArg opDebugInfo("debug-info", false, "Compile with debug info"); panda::PandArg opDumpDebugInfo("dump-debug-info", false, "Dump debug info"); panda::PandArg opOptLevel("opt-level", 0, "Compiler optimization level (options: 0 | 1 | 2)"); - panda::PandArg opThreadCount("thread", 0, "Number of worker theads"); + panda::PandArg opFunctionThreadCount("function-threads", 0, "Number of worker threads to compile function"); + panda::PandArg opFileThreadCount("file-threads", 0, "Number of worker threads to compile file"); panda::PandArg opSizeStat("dump-size-stat", false, "Dump size statistics"); panda::PandArg opDumpLiteralBuffer("dump-literal-buffer", false, "Dump literal buffer"); panda::PandArg outputFile("output", "", "Compiler binary output (.abc)"); + panda::PandArg recordName("record-name", "", "Specify the record name"); panda::PandArg debuggerEvaluateExpression("debugger-evaluate-expression", false, "evaluate expression in debugger mode"); panda::PandArg base64Input("base64Input", "", "base64 input of js content"); panda::PandArg base64Output("base64Output", false, "output panda file content as base64 to std out"); panda::PandArg sourceFile("source-file", "", "specify the file path info recorded in generated abc"); + panda::PandArg outputProto("outputProto", "", "compiler proto serialize binary output (.proto)"); + panda::PandArg opCacheFile("cache-file", "", "cache file for incremental compile"); + panda::PandArg opNpmModuleEntryList("npm-module-entry-list", "", "entry list file for module compile"); + panda::PandArg opMergeAbc("merge-abc", false, "Compile as merge abc"); // tail arguments panda::PandArg inputFile("input", "", "input file"); @@ -90,13 +174,19 @@ bool Options::Parse(int argc, const char **argv) argparser_->Add(&base64Output); argparser_->Add(&opOptLevel); - argparser_->Add(&opThreadCount); + argparser_->Add(&opFunctionThreadCount); + argparser_->Add(&opFileThreadCount); argparser_->Add(&opSizeStat); argparser_->Add(&opDumpLiteralBuffer); argparser_->Add(&inputExtension); argparser_->Add(&outputFile); argparser_->Add(&sourceFile); + argparser_->Add(&recordName); + argparser_->Add(&outputProto); + argparser_->Add(&opCacheFile); + argparser_->Add(&opNpmModuleEntryList); + argparser_->Add(&opMergeAbc); argparser_->PushBackTail(&inputFile); argparser_->EnableTail(); @@ -132,41 +222,20 @@ bool Options::Parse(int argc, const char **argv) return false; } - if (!inputIsEmpty) { - // in common mode: passed argument is js file path - sourceFile_ = inputFile.GetValue(); - std::ifstream inputStream(sourceFile_.c_str()); - - if (inputStream.fail()) { - errorMsg_ = "Failed to open file: "; - errorMsg_.append(sourceFile_); - return false; - } - - std::stringstream ss; - ss << inputStream.rdbuf(); - parserInput_ = ss.str(); - - sourceFile_ = BaseName(sourceFile_); - } else { - // input content is base64 string - parserInput_ = ExtractContentFromBase64Input(base64Input.GetValue()); - if (parserInput_.empty()) { - errorMsg_ = "The input string is not a valid base64 data"; - return false; - } + if (opModule.GetValue() && opCommonjs.GetValue()) { + errorMsg_ = "[--module] and [--commonjs] can not be used simultaneously"; + return false; } - if (base64Output.GetValue()) { - compilerOutput_ = ""; - } else if (!outputIsEmpty) { - compilerOutput_ = outputFile.GetValue(); - } else if (outputIsEmpty && !inputIsEmpty) { - compilerOutput_ = RemoveExtension(sourceFile_).append(".abc"); + if (opModule.GetValue()) { + scriptKind_ = es2panda::parser::ScriptKind::MODULE; + } else if (opCommonjs.GetValue()) { + scriptKind_ = es2panda::parser::ScriptKind::COMMONJS; + } else { + scriptKind_ = es2panda::parser::ScriptKind::SCRIPT; } std::string extension = inputExtension.GetValue(); - if (!extension.empty()) { if (extension == "js") { extension_ = es2panda::ScriptExtension::JS; @@ -180,24 +249,72 @@ bool Options::Parse(int argc, const char **argv) } } - optLevel_ = opOptLevel.GetValue(); - threadCount_ = opThreadCount.GetValue(); + bool isInputFileList = false; + if (!inputIsEmpty) { + std::string rawInput = inputFile.GetValue(); + isInputFileList = rawInput[0] == '@'; + std::string input = isInputFileList ? rawInput.substr(1) : rawInput; + sourceFile_ = input; + } - if (opParseOnly.GetValue()) { - options_ |= OptionFlags::PARSE_ONLY; + if (base64Output.GetValue()) { + compilerOutput_ = ""; + } else if (!outputIsEmpty) { + compilerOutput_ = outputFile.GetValue(); + } else if (outputIsEmpty && !inputIsEmpty) { + compilerOutput_ = RemoveExtension(BaseName(sourceFile_)).append(".abc"); } - if (opModule.GetValue() && opCommonjs.GetValue()) { - errorMsg_ = "[--module] and [--commonjs] can not be used simultaneously"; - return false; + if (opMergeAbc.GetValue()) { + recordName_ = recordName.GetValue(); + if (recordName_.empty()) { + recordName_ = compilerOutput_.empty() ? "Base64Output" : RemoveExtension(BaseName(compilerOutput_)); + } + recordName_ = FormatRecordName(recordName_); } - if (opModule.GetValue()) { - scriptKind_ = es2panda::parser::ScriptKind::MODULE; + if (!inputIsEmpty) { + // common mode + auto inputAbs = panda::os::file::File::GetAbsolutePath(sourceFile_); + if (!inputAbs) { + std::cerr << "Failed to find: " << sourceFile_ << std::endl; + return false; + } + + auto fpath = inputAbs.Value(); + if (isInputFileList) { + CollectInputFilesFromFileList(fpath); + } else if (panda::os::file::File::IsDirectory(fpath)) { + CollectInputFilesFromFileDirectory(fpath, extension); + } else { + es2panda::SourceFile src(sourceFile_, recordName_, scriptKind_); + sourceFiles_.push_back(src); + } + } else if (!base64InputIsEmpty) { + // input content is base64 string + base64Input_ = ExtractContentFromBase64Input(base64Input.GetValue()); + if (base64Input_.empty()) { + errorMsg_ = "The input string is not a valid base64 data"; + return false; + } + + es2panda::SourceFile src("", recordName_, es2panda::parser::ScriptKind::SCRIPT); + src.source = base64Input_; + sourceFiles_.push_back(src); } - if (opCommonjs.GetValue()) { - scriptKind_ = es2panda::parser::ScriptKind::COMMONJS; + if (!outputProto.GetValue().empty()) { + compilerProtoOutput_ = outputProto.GetValue(); + } + + optLevel_ = opOptLevel.GetValue(); + functionThreadCount_ = opFunctionThreadCount.GetValue(); + fileThreadCount_ = opFileThreadCount.GetValue(); + npmModuleEntryList_ = opNpmModuleEntryList.GetValue(); + cacheFile_ = opCacheFile.GetValue(); + + if (opParseOnly.GetValue()) { + options_ |= OptionFlags::PARSE_ONLY; } if (opSizeStat.GetValue()) { @@ -212,7 +329,15 @@ bool Options::Parse(int argc, const char **argv) compilerOptions_.enableTypeCheck = opEnableTypeCheck.GetValue(); compilerOptions_.dumpLiteralBuffer = opDumpLiteralBuffer.GetValue(); compilerOptions_.isDebuggerEvaluateExpressionMode = debuggerEvaluateExpression.GetValue(); - compilerOptions_.sourceFile = sourceFile.GetValue(); + + compilerOptions_.extension = extension_; + compilerOptions_.functionThreadCount = functionThreadCount_; + compilerOptions_.fileThreadCount = fileThreadCount_; + compilerOptions_.output = compilerOutput_; + compilerOptions_.debugInfoSourceFile = sourceFile.GetValue(); + compilerOptions_.optLevel = opOptLevel.GetValue(); + compilerOptions_.sourceFiles = sourceFiles_; + compilerOptions_.mergeAbc = opMergeAbc.GetValue(); return true; } @@ -229,5 +354,4 @@ std::string Options::ExtractContentFromBase64Input(const std::string &inputBase6 } return inputContent; } - } // namespace panda::es2panda::aot diff --git a/es2panda/aot/options.h b/es2panda/aot/options.h index 49286015aeafa6792e6d5d492afd29b74dae9a33..0bd501f57cda9ffd70e19e34add86b974a26f87f 100644 --- a/es2panda/aot/options.h +++ b/es2panda/aot/options.h @@ -16,8 +16,8 @@ #ifndef ES2PANDA_AOT_OPTIONS_H #define ES2PANDA_AOT_OPTIONS_H -#include #include +#include #include #include @@ -31,7 +31,6 @@ class PandaArg; } // namespace panda namespace panda::es2panda::aot { - enum class OptionFlags { DEFAULT = 0, PARSE_ONLY = 1 << 1, @@ -71,14 +70,14 @@ public: return compilerOptions_; } - es2panda::parser::ScriptKind ScriptKind() const + es2panda::CompilerOptions &CompilerOptions() { - return scriptKind_; + return compilerOptions_; } - const std::string &ParserInput() const + es2panda::parser::ScriptKind ScriptKind() const { - return parserInput_; + return scriptKind_; } const std::string &CompilerOutput() const @@ -91,6 +90,11 @@ public: return sourceFile_; } + const std::string &RecordName() const + { + return recordName_; + } + const std::string &ErrorMsg() const { return errorMsg_; @@ -101,11 +105,6 @@ public: return optLevel_; } - int ThreadCount() const - { - return threadCount_; - } - bool ParseOnly() const { return (options_ & OptionFlags::PARSE_ONLY) != 0; @@ -118,21 +117,44 @@ public: std::string ExtractContentFromBase64Input(const std::string &inputBase64String); + const std::string &compilerProtoOutput() const + { + return compilerProtoOutput_; + } + + const std::string &CacheFile() const + { + return cacheFile_; + } + + const std::string &NpmModuleEntryList() const + { + return npmModuleEntryList_; + } + + bool CollectInputFilesFromFileList(const std::string &input); + bool CollectInputFilesFromFileDirectory(const std::string &input, const std::string &extension); + private: es2panda::ScriptExtension extension_ {es2panda::ScriptExtension::JS}; es2panda::CompilerOptions compilerOptions_ {}; es2panda::parser::ScriptKind scriptKind_ {es2panda::parser::ScriptKind::SCRIPT}; OptionFlags options_ {OptionFlags::DEFAULT}; panda::PandArgParser *argparser_; - std::string parserInput_; + std::string base64Input_; std::string compilerOutput_; std::string result_; std::string sourceFile_; + std::string recordName_; std::string errorMsg_; + std::string compilerProtoOutput_; int optLevel_ {0}; - int threadCount_ {0}; + int functionThreadCount_ {0}; + int fileThreadCount_ {0}; + std::string cacheFile_; + std::string npmModuleEntryList_; + std::vector sourceFiles_; }; - } // namespace panda::es2panda::aot #endif // AOT_OPTIONS_H diff --git a/es2panda/binder/binder.cpp b/es2panda/binder/binder.cpp index dc6319947090576b159aaa623e93835d2fedae44..63f359f987bc7885c95bc2abe78ef452a0073608 100644 --- a/es2panda/binder/binder.cpp +++ b/es2panda/binder/binder.cpp @@ -200,11 +200,13 @@ void Binder::BuildFunction(FunctionScope *funcScope, util::StringView name) bool funcNameWithoutDot = (name.Find(".") == std::string::npos); bool funcNameWithoutBackslash = (name.Find("\\") == std::string::npos); if (name != ANONYMOUS_FUNC_NAME && funcNameWithoutDot && funcNameWithoutBackslash && !functionNames_.count(name)) { + auto internalName = std::string(program_->RecordName()) + std::string(name); functionNames_.insert(name); - funcScope->BindName(name, name); + funcScope->BindName(name, util::UString(internalName, Allocator()).View()); return; } std::stringstream ss; + ss << std::string(program_->RecordName()); uint32_t idx = functionNameIndex_++; ss << "#" << std::to_string(idx) << "#"; if (funcNameWithoutDot && funcNameWithoutBackslash) { diff --git a/es2panda/compiler/core/compileQueue.cpp b/es2panda/compiler/core/compileQueue.cpp index 67dbd851a2491c201c14381b986ff9b90f571ce8..2e2b5345baf2a9234aaf776069d0b8998c8845ea 100644 --- a/es2panda/compiler/core/compileQueue.cpp +++ b/es2panda/compiler/core/compileQueue.cpp @@ -21,9 +21,34 @@ #include #include #include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include namespace panda::es2panda::compiler { +std::mutex CompileFileJob::global_m_; + void CompileJob::DependsOn(CompileJob *job) { job->dependant_ = this; @@ -75,6 +100,24 @@ void CompileModuleRecordJob::Run() } } +void CompileFileJob::Run() +{ + es2panda::Compiler compiler(options_->extension, options_->functionThreadCount); + + auto *prog = compiler.CompileFile(*options_, src_); + + if (options_->optLevel != 0) { + util::Helpers::OptimizeProgram(prog, options_); + } + + { + std::unique_lock lock(global_m_); + auto *cache = allocator_->New(src_->hash, prog); + progsInfo_.insert({src_->fileName, cache}); + progs_.push_back(prog); + } +} + CompileQueue::CompileQueue(size_t threadCount) { threads_.reserve(threadCount); @@ -98,29 +141,6 @@ CompileQueue::~CompileQueue() } } -void CompileQueue::Schedule(CompilerContext *context) -{ - ASSERT(jobsCount_ == 0); - std::unique_lock lock(m_); - const auto &functions = context->Binder()->Functions(); - - for (auto *function : functions) { - auto *funcJob = new CompileFunctionJob(context); - funcJob->SetFunctionScope(function); - jobs_.push_back(funcJob); - jobsCount_++; - } - - if (context->Binder()->Program()->Kind() == parser::ScriptKind::MODULE) { - auto *moduleRecordJob = new CompileModuleRecordJob(context); - jobs_.push_back(moduleRecordJob); - jobsCount_++; - } - - lock.unlock(); - jobsAvailable_.notify_all(); -} - void CompileQueue::Worker(CompileQueue *queue) { while (true) { @@ -181,4 +201,42 @@ void CompileQueue::Wait() } } +void CompileFuncQueue::Schedule() +{ + ASSERT(jobsCount_ == 0); + std::unique_lock lock(m_); + const auto &functions = context_->Binder()->Functions(); + + for (auto *function : functions) { + auto *funcJob = new CompileFunctionJob(context_); + funcJob->SetFunctionScope(function); + jobs_.push_back(funcJob); + jobsCount_++; + } + + if (context_->Binder()->Program()->Kind() == parser::ScriptKind::MODULE) { + auto *moduleRecordJob = new CompileModuleRecordJob(context_); + jobs_.push_back(moduleRecordJob); + jobsCount_++; + } + + lock.unlock(); + jobsAvailable_.notify_all(); +} + +void CompileFileQueue::Schedule() +{ + ASSERT(jobsCount_ == 0); + std::unique_lock lock(m_); + + for (auto &input: options_->sourceFiles) { + auto *fileJob = new CompileFileJob(&input, options_, progs_, progsInfo_, allocator_); + jobs_.push_back(fileJob); + jobsCount_++; + } + + lock.unlock(); + jobsAvailable_.notify_all(); +} + } // namespace panda::es2panda::compiler diff --git a/es2panda/compiler/core/compileQueue.h b/es2panda/compiler/core/compileQueue.h index f53b8b4c6b03e0ac42b68ddf56c0b083ccf1daa5..63a2834d7e603a153c510dcad5fb48472647db5a 100644 --- a/es2panda/compiler/core/compileQueue.h +++ b/es2panda/compiler/core/compileQueue.h @@ -16,9 +16,9 @@ #ifndef ES2PANDA_COMPILER_CORE_COMPILEQUEUE_H #define ES2PANDA_COMPILER_CORE_COMPILEQUEUE_H +#include #include #include -#include #include #include @@ -33,7 +33,7 @@ class CompilerContext; class CompileJob { public: - explicit CompileJob(CompilerContext *context) : context_(context) {}; + explicit CompileJob() {}; NO_COPY_SEMANTIC(CompileJob); NO_MOVE_SEMANTIC(CompileJob); virtual ~CompileJob() = default; @@ -43,7 +43,6 @@ public: void Signal(); protected: - [[maybe_unused]] CompilerContext *context_ {}; std::mutex m_; std::condition_variable cond_; CompileJob *dependant_ {}; @@ -52,7 +51,7 @@ protected: class CompileFunctionJob : public CompileJob { public: - explicit CompileFunctionJob(CompilerContext *context) : CompileJob(context) {}; + explicit CompileFunctionJob(CompilerContext *context) : context_(context) {}; NO_COPY_SEMANTIC(CompileFunctionJob); NO_MOVE_SEMANTIC(CompileFunctionJob); ~CompileFunctionJob() = default; @@ -68,18 +67,45 @@ public: } void Run() override; + private: + CompilerContext *context_ {}; binder::FunctionScope *scope_ {}; }; class CompileModuleRecordJob : public CompileJob { public: - explicit CompileModuleRecordJob(CompilerContext *context) : CompileJob(context) {}; + explicit CompileModuleRecordJob(CompilerContext *context) : context_(context) {}; NO_COPY_SEMANTIC(CompileModuleRecordJob); NO_MOVE_SEMANTIC(CompileModuleRecordJob); ~CompileModuleRecordJob() = default; void Run() override; + +private: + CompilerContext *context_ {}; +}; + +class CompileFileJob : public CompileJob { +public: + explicit CompileFileJob(es2panda::SourceFile *src, es2panda::CompilerOptions *options, + std::vector &progs, + std::unordered_map &progsInfo, + panda::ArenaAllocator *allocator) + : src_(src), options_(options), progs_(progs), progsInfo_(progsInfo), allocator_(allocator) {}; + NO_COPY_SEMANTIC(CompileFileJob); + NO_MOVE_SEMANTIC(CompileFileJob); + ~CompileFileJob() = default; + + void Run() override; + +private: + static std::mutex global_m_; + es2panda::SourceFile *src_; + es2panda::CompilerOptions *options_; + std::vector &progs_; + std::unordered_map &progsInfo_; + panda::ArenaAllocator *allocator_; }; class CompileQueue { @@ -87,13 +113,13 @@ public: explicit CompileQueue(size_t threadCount); NO_COPY_SEMANTIC(CompileQueue); NO_MOVE_SEMANTIC(CompileQueue); - ~CompileQueue(); + virtual ~CompileQueue(); - void Schedule(CompilerContext *context); + virtual void Schedule() = 0; void Consume(); void Wait(); -private: +protected: static void Worker(CompileQueue *queue); std::vector threads_; @@ -107,6 +133,42 @@ private: bool terminate_ {false}; }; +class CompileFuncQueue : public CompileQueue { +public: + explicit CompileFuncQueue(size_t threadCount, CompilerContext *context) + : CompileQueue(threadCount), context_(context) {} + + NO_COPY_SEMANTIC(CompileFuncQueue); + NO_MOVE_SEMANTIC(CompileFuncQueue); + ~CompileFuncQueue() = default; + + void Schedule() override; + +private: + CompilerContext *context_; +}; + +class CompileFileQueue : public CompileQueue { +public: + explicit CompileFileQueue(size_t threadCount, es2panda::CompilerOptions *options, + std::vector &progs, + std::unordered_map &progsInfo, + panda::ArenaAllocator *allocator) + : CompileQueue(threadCount), options_(options), progs_(progs), progsInfo_(progsInfo), allocator_(allocator) {} + + NO_COPY_SEMANTIC(CompileFileQueue); + NO_MOVE_SEMANTIC(CompileFileQueue); + ~CompileFileQueue() = default; + + void Schedule() override; + +private: + es2panda::CompilerOptions *options_; + std::vector &progs_; + std::unordered_map &progsInfo_; + panda::ArenaAllocator *allocator_; +}; + } // namespace panda::es2panda::compiler #endif diff --git a/es2panda/compiler/core/compilerContext.cpp b/es2panda/compiler/core/compilerContext.cpp index bc82ddcba53576fbc8bfaf6c068f97f1e800ec98..81434e630b0a4cdccc30fa37dc54886355150f91 100644 --- a/es2panda/compiler/core/compilerContext.cpp +++ b/es2panda/compiler/core/compilerContext.cpp @@ -20,9 +20,9 @@ namespace panda::es2panda::compiler { CompilerContext::CompilerContext(binder::Binder *binder, bool isDebug, bool isDebuggerEvaluateExpressionMode, - std::string sourceFile) - : binder_(binder), emitter_(std::make_unique(this)), isDebug_(isDebug), - isDebuggerEvaluateExpressionMode_(isDebuggerEvaluateExpressionMode), sourceFile_(sourceFile) + bool isMergeAbc, std::string sourceFile) + : binder_(binder), isDebug_(isDebug), isDebuggerEvaluateExpressionMode_(isDebuggerEvaluateExpressionMode), + isMergeAbc_(isMergeAbc), sourceFile_(sourceFile), emitter_(std::make_unique(this)) { } diff --git a/es2panda/compiler/core/compilerContext.h b/es2panda/compiler/core/compilerContext.h index 4b94b607279093155951290456fbf1c3365c79f6..9d12993fcc2854586e83c10bd2ddafa5ae8eb5d9 100644 --- a/es2panda/compiler/core/compilerContext.h +++ b/es2panda/compiler/core/compilerContext.h @@ -34,7 +34,7 @@ class Emitter; class CompilerContext { public: CompilerContext(binder::Binder *binder, bool isDebug, bool isDebuggerEvaluateExpressionMode, - std::string sourceFile); + bool isMergeAbc, std::string sourceFile); NO_COPY_SEMANTIC(CompilerContext); NO_MOVE_SEMANTIC(CompilerContext); ~CompilerContext() = default; @@ -75,6 +75,11 @@ public: return isDebuggerEvaluateExpressionMode_; } + bool IsMergeAbc() const + { + return isMergeAbc_; + } + std::string SourceFile() const { return sourceFile_; @@ -82,12 +87,13 @@ public: private: binder::Binder *binder_; - std::unique_ptr emitter_; int32_t literalBufferIdx_ {0}; std::mutex m_; bool isDebug_; bool isDebuggerEvaluateExpressionMode_; + bool isMergeAbc_; std::string sourceFile_; + std::unique_ptr emitter_; }; } // namespace panda::es2panda::compiler diff --git a/es2panda/compiler/core/compilerImpl.cpp b/es2panda/compiler/core/compilerImpl.cpp index a1a79e65afc6d4e5864b00ab2e629f60b1988980..05aeb2c072b1269e2fa8f9c716c66b8bf12b2329 100644 --- a/es2panda/compiler/core/compilerImpl.cpp +++ b/es2panda/compiler/core/compilerImpl.cpp @@ -18,26 +18,28 @@ #include #include #include -#include #include #include +#include #include #include namespace panda::es2panda::compiler { -CompilerImpl::CompilerImpl(size_t threadCount) : queue_(new CompileQueue(threadCount)) {} - CompilerImpl::~CompilerImpl() { - delete queue_; + if (queue_ != nullptr) { + delete queue_; + queue_ = nullptr; + } } -panda::pandasm::Program *CompilerImpl::Compile(parser::Program *program, const es2panda::CompilerOptions &options) +panda::pandasm::Program *CompilerImpl::Compile(parser::Program *program, const es2panda::CompilerOptions &options, + const std::string &debugInfoSourceFile) { CompilerContext context(program->Binder(), options.isDebug, options.isDebuggerEvaluateExpressionMode, - options.sourceFile); + options.mergeAbc, debugInfoSourceFile); if (program->Extension() == ScriptExtension::TS && options.enableTypeCheck) { ArenaAllocator localAllocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true); @@ -49,7 +51,8 @@ panda::pandasm::Program *CompilerImpl::Compile(parser::Program *program, const e return nullptr; } - queue_->Schedule(&context); + queue_ = new CompileFuncQueue(threadCount_, &context); + queue_->Schedule(); /* Main thread can also be used instead of idling */ queue_->Consume(); diff --git a/es2panda/compiler/core/compilerImpl.h b/es2panda/compiler/core/compilerImpl.h index 19c6061347f643e46a5de26d170a800251e019ce..102a7394471ed16d7edb3a66b531a100bacdd433 100644 --- a/es2panda/compiler/core/compilerImpl.h +++ b/es2panda/compiler/core/compilerImpl.h @@ -32,20 +32,22 @@ class Program; } // namespace panda::es2panda::parser namespace panda::es2panda::compiler { -class CompileQueue; +class CompileFuncQueue; class CompilerImpl { public: - explicit CompilerImpl(size_t threadCount); + explicit CompilerImpl(size_t threadCount): threadCount_(threadCount) {} ~CompilerImpl(); NO_COPY_SEMANTIC(CompilerImpl); NO_MOVE_SEMANTIC(CompilerImpl); - panda::pandasm::Program *Compile(parser::Program *program, const es2panda::CompilerOptions &options); + panda::pandasm::Program *Compile(parser::Program *program, const es2panda::CompilerOptions &options, + const std::string &debugInfoSourceFile); static void DumpAsm(const panda::pandasm::Program *prog); private: - CompileQueue *queue_; + size_t threadCount_ {0}; + CompileFuncQueue *queue_ {nullptr}; }; } // namespace panda::es2panda::compiler diff --git a/es2panda/compiler/core/emitter/commonjs.cpp b/es2panda/compiler/core/emitter/commonjs.cpp index aa4a5ce538a9d2ecb9c2f2af5364984785be5f45..397e0d941cea21ba1cdda9be460e8bdafd2befd8 100644 --- a/es2panda/compiler/core/emitter/commonjs.cpp +++ b/es2panda/compiler/core/emitter/commonjs.cpp @@ -20,6 +20,16 @@ namespace panda::es2panda::compiler { constexpr const auto LANG_EXT = panda::pandasm::extensions::Language::ECMASCRIPT; +void Emitter::SetCommonjsField(bool isCommonjs) +{ + auto isCommonJsField = panda::pandasm::Field(LANG_EXT); + isCommonJsField.name = "isCommonjs"; + isCommonJsField.type = panda::pandasm::Type("u8", 0); + isCommonJsField.metadata->SetValue( + panda::pandasm::ScalarValue::Create(static_cast(isCommonjs))); + rec_->field_list.emplace_back(std::move(isCommonJsField)); +} + void Emitter::GenCommonjsRecord() const { auto commonjsRecord = panda::pandasm::Record("_CommonJsRecord", LANG_EXT); @@ -33,4 +43,5 @@ void Emitter::GenCommonjsRecord() const prog_->record_table.emplace(commonjsRecord.name, std::move(commonjsRecord)); } + } // namespace panda::es2panda::compiler \ No newline at end of file diff --git a/es2panda/compiler/core/emitter/emitter.cpp b/es2panda/compiler/core/emitter/emitter.cpp index 166fe985de71a0170df9ad371b304128f4de2f7f..e767eab9af1695fe0bd027f41ff7407d4ebdb0d2 100644 --- a/es2panda/compiler/core/emitter/emitter.cpp +++ b/es2panda/compiler/core/emitter/emitter.cpp @@ -16,7 +16,6 @@ #include "emitter.h" #include -#include #include #include #include @@ -30,6 +29,7 @@ #include #include #include +#include #include #include @@ -61,7 +61,6 @@ void FunctionEmitter::Generate() GenVariablesDebugInfo(); GenSourceFileDebugInfo(); GenFunctionCatchTables(); - GenFunctionICSize(); GenLiteralBuffers(); } @@ -124,6 +123,11 @@ void FunctionEmitter::GenBufferLiterals(const LiteralBuffer *buff) valueLit.value_ = literal->GetMethod().Mutf8(); break; } + case ir::LiteralTag::LITERALBUFFERINDEX: { + valueLit.tag_ = panda::panda_file::LiteralTag::LITERALBUFFERINDEX; + valueLit.value_ = literal->GetInt(); + break; + } // TODO: support ir::LiteralTag::ASYNC_GENERATOR_METHOD case ir::LiteralTag::NULL_VALUE: { valueLit.tag_ = panda::panda_file::LiteralTag::NULLVALUE; @@ -243,29 +247,6 @@ void FunctionEmitter::GenFunctionInstructions() } } -void FunctionEmitter::GenFunctionICSize() -{ - panda::pandasm::AnnotationData funcAnnotationData("_ESAnnotation"); - panda::pandasm::AnnotationElement icSizeAnnotationElement( - "icSize", std::make_unique( - panda::pandasm::ScalarValue::Create(pg_->IcSize()))); - funcAnnotationData.AddElement(std::move(icSizeAnnotationElement)); - - panda::pandasm::AnnotationElement parameterLengthAnnotationElement( - "parameterLength", - std::make_unique( - panda::pandasm::ScalarValue::Create(pg_->FormalParametersCount()))); - funcAnnotationData.AddElement(std::move(parameterLengthAnnotationElement)); - - panda::pandasm::AnnotationElement funcNameAnnotationElement( - "funcName", - std::make_unique( - panda::pandasm::ScalarValue::Create(pg_->FunctionName().Mutf8()))); - funcAnnotationData.AddElement(std::move(funcNameAnnotationElement)); - - func_->metadata->AddAnnotations({funcAnnotationData}); -} - void FunctionEmitter::GenFunctionCatchTables() { func_->catch_blocks.reserve(pg_->CatchList().size()); @@ -356,12 +337,18 @@ void FunctionEmitter::GenVariablesDebugInfo() Emitter::Emitter(const CompilerContext *context) { prog_ = new panda::pandasm::Program(); - prog_->lang = panda::pandasm::extensions::Language::ECMASCRIPT; - + prog_->lang = LANG_EXT; prog_->function_table.reserve(context->Binder()->Functions().size()); - GenESAnnoatationRecord(); - if (context->Binder()->Program()->Kind() == parser::ScriptKind::COMMONJS) { - GenCommonjsRecord(); + + if (context->IsMergeAbc()) { + auto recordName = context->Binder()->Program()->RecordName().Mutf8(); + rec_ = new panda::pandasm::Record(recordName.substr(0, recordName.find_last_of('.')), LANG_EXT); + SetCommonjsField(context->Binder()->Program()->Kind() == parser::ScriptKind::COMMONJS); + } else { + rec_ = nullptr; + if (context->Binder()->Program()->Kind() == parser::ScriptKind::COMMONJS) { + GenCommonjsRecord(); + } } } @@ -370,14 +357,6 @@ Emitter::~Emitter() delete prog_; } -void Emitter::GenESAnnoatationRecord() -{ - auto annotationRecord = panda::pandasm::Record("_ESAnnotation", LANG_EXT); - annotationRecord.metadata->SetAttribute("external"); - annotationRecord.metadata->SetAccessFlags(panda::ACC_ANNOTATION); - prog_->record_table.emplace(annotationRecord.name, std::move(annotationRecord)); -} - void Emitter::AddFunction(FunctionEmitter *func) { std::lock_guard lock(m_); @@ -399,17 +378,25 @@ void Emitter::AddSourceTextModuleRecord(ModuleRecordEmitter *module, const Compi { std::lock_guard lock(m_); - auto ecmaModuleRecord = panda::pandasm::Record("_ESModuleRecord", LANG_EXT); - ecmaModuleRecord.metadata->SetAccessFlags(panda::ACC_PUBLIC); - - auto moduleIdxField = panda::pandasm::Field(LANG_EXT); - moduleIdxField.name = std::string {context->Binder()->Program()->SourceFile()}; - moduleIdxField.type = panda::pandasm::Type("u32", 0); - moduleIdxField.metadata->SetValue(panda::pandasm::ScalarValue::Create( - static_cast(module->Index()))); - ecmaModuleRecord.field_list.emplace_back(std::move(moduleIdxField)); - prog_->record_table.emplace(ecmaModuleRecord.name, std::move(ecmaModuleRecord)); - + if (context->IsMergeAbc()) { + auto moduleIdxField = panda::pandasm::Field(LANG_EXT); + moduleIdxField.name = "moduleRecordIdx"; + moduleIdxField.type = panda::pandasm::Type("u32", 0); + moduleIdxField.metadata->SetValue(panda::pandasm::ScalarValue::Create( + static_cast(module->Index()))); + rec_->field_list.emplace_back(std::move(moduleIdxField)); + } else { + auto ecmaModuleRecord = panda::pandasm::Record("_ESModuleRecord", LANG_EXT); + ecmaModuleRecord.metadata->SetAccessFlags(panda::ACC_PUBLIC); + + auto moduleIdxField = panda::pandasm::Field(LANG_EXT); + moduleIdxField.name = std::string {context->Binder()->Program()->SourceFile()}; + moduleIdxField.type = panda::pandasm::Type("u32", 0); + moduleIdxField.metadata->SetValue(panda::pandasm::ScalarValue::Create( + static_cast(module->Index()))); + ecmaModuleRecord.field_list.emplace_back(std::move(moduleIdxField)); + prog_->record_table.emplace(ecmaModuleRecord.name, std::move(ecmaModuleRecord)); + } auto &moduleLiteralsBuffer = module->Buffer(); auto literalArrayInstance = panda::pandasm::LiteralArray(std::move(moduleLiteralsBuffer)); prog_->literalarray_table.emplace(std::to_string(module->Index()), std::move(literalArrayInstance)); @@ -457,6 +444,12 @@ panda::pandasm::Program *Emitter::Finalize(bool dumpDebugInfo) dumper.Dump(); } + if (rec_) { + prog_->record_table.emplace(rec_->name, std::move(*rec_)); + delete rec_; + rec_ = nullptr; + } + auto *prog = prog_; prog_ = nullptr; return prog; diff --git a/es2panda/compiler/core/emitter/emitter.h b/es2panda/compiler/core/emitter/emitter.h index 8c7a865f88ff7ccd4a4dab5b06af3d7f9a38cde0..2aca67395e904ed75289ba86a8072ffbaedbe013 100644 --- a/es2panda/compiler/core/emitter/emitter.h +++ b/es2panda/compiler/core/emitter/emitter.h @@ -34,6 +34,7 @@ namespace panda::pandasm { struct Program; struct Function; struct Ins; +struct Record; } // namespace panda::pandasm namespace panda::es2panda::ir { @@ -76,7 +77,6 @@ private: void GenInstructionDebugInfo(const IRNode *ins, panda::pandasm::Ins *pandaIns); void GenFunctionInstructions(); void GenFunctionCatchTables(); - void GenFunctionICSize(); void GenScopeVariableInfo(const binder::Scope *scope); void GenSourceFileDebugInfo(); void GenVariablesDebugInfo(); @@ -105,11 +105,12 @@ public: panda::pandasm::Program *Finalize(bool dumpDebugInfo); private: - void GenESAnnoatationRecord(); + void SetCommonjsField(bool isCommonjs); void GenCommonjsRecord() const; std::mutex m_; panda::pandasm::Program *prog_; + panda::pandasm::Record *rec_; }; } // namespace panda::es2panda::compiler diff --git a/es2panda/es2panda.cpp b/es2panda/es2panda.cpp index 3e384a33548935bd72638f2f56cb561413b4cfa8..0dac82455ae0f606f8ade069dcaa7f59c835ba98 100644 --- a/es2panda/es2panda.cpp +++ b/es2panda/es2panda.cpp @@ -21,6 +21,8 @@ #include #include +#include + #include #include @@ -47,16 +49,18 @@ panda::pandasm::Program *Compiler::Compile(const SourceFile &input, const Compil /* TODO(dbatyai): pass string view */ std::string fname(input.fileName); std::string src(input.source); + std::string rname(input.recordName); parser::ScriptKind kind(input.scriptKind); try { - auto ast = parser_->Parse(fname, src, kind); + auto ast = parser_->Parse(fname, src, rname, kind); if (options.dumpAst) { std::cout << ast.Dump() << std::endl; } - auto *prog = compiler_->Compile(&ast, options); + std::string debugInfoSourceFile = options.debugInfoSourceFile.empty() ? fname : options.debugInfoSourceFile; + auto *prog = compiler_->Compile(&ast, options, debugInfoSourceFile); return prog; } catch (const class Error &e) { @@ -69,4 +73,104 @@ void Compiler::DumpAsm(const panda::pandasm::Program *prog) { compiler::CompilerImpl::DumpAsm(prog); } + +static bool ReadFileToBuffer(const std::string &file, std::stringstream &ss) +{ + std::ifstream inputStream(file); + if (inputStream.fail()) { + std::cerr << "Failed to read file to buffer: " << file << std::endl; + return false; + } + ss << inputStream.rdbuf(); + return true; +} + +void Compiler::SelectCompileFile(CompilerOptions &options, + std::unordered_map *cacheProgs, + std::vector &progs, + std::unordered_map &progsInfo, + panda::ArenaAllocator *allocator) +{ + if (cacheProgs == nullptr) { + return; + } + + auto fullList = options.sourceFiles; + std::vector inputList; + + for (auto &input: fullList) { + if (input.fileName.empty()) { + // base64 source + inputList.push_back(input); + continue; + } + + std::stringstream ss; + if (!ReadFileToBuffer(input.fileName, ss)) { + continue; + } + + uint32_t hash = GetHash32String(reinterpret_cast(ss.str().c_str())); + + auto it = cacheProgs->find(input.fileName); + if (it != cacheProgs->end() && hash == it->second->hashCode) { + progs.push_back(it->second->program); + auto *cache = allocator->New(it->second->hashCode, it->second->program); + progsInfo.insert({input.fileName, cache}); + } else { + input.hash = hash; + inputList.push_back(input); + } + } + options.sourceFiles = inputList; +} + +void Compiler::CompileFiles(CompilerOptions &options, + std::unordered_map *cacheProgs, + std::vector &progs, + std::unordered_map &progsInfo, + panda::ArenaAllocator *allocator) +{ + SelectCompileFile(options, cacheProgs, progs, progsInfo, allocator); + + auto queue = new compiler::CompileFileQueue(options.fileThreadCount, &options, progs, progsInfo, allocator); + + queue->Schedule(); + queue->Consume(); + queue->Wait(); + + delete queue; +} + +panda::pandasm::Program *Compiler::CompileFile(CompilerOptions &options, SourceFile *src) +{ + std::string buffer; + if (src->source.empty()) { + std::stringstream ss; + if (!ReadFileToBuffer(src->fileName, ss)) { + return nullptr; + } + buffer = ss.str(); + src->source = buffer; + + if (src->hash == 0) { + src->hash = GetHash32String(reinterpret_cast(buffer.c_str())); + } + } + + auto *program = Compile(*src, options); + if (!program) { + const auto &err = GetError(); + + if (err.Message().empty() && options.parseOnly) { + return nullptr; + } + + std::cerr << err.TypeString() << ": " << err.Message(); + std::cerr << " [" << src->fileName << ":" << err.Line() << ":" << err.Col() << "]" << std::endl; + return nullptr; + } + return program; +} + } // namespace panda::es2panda diff --git a/es2panda/es2panda.h b/es2panda/es2panda.h index 9a82c093edd4a5734272b96a674174b487312533..cddf15d10e458ae1780b943ee09c3f46f6d703ea 100644 --- a/es2panda/es2panda.h +++ b/es2panda/es2panda.h @@ -17,8 +17,11 @@ #define ES2PANDA_PUBLIC_H #include +#include +#include #include +#include namespace panda::pandasm { struct Program; @@ -41,14 +44,16 @@ enum class ScriptExtension { }; struct SourceFile { - SourceFile(std::string_view fn, std::string_view s, parser::ScriptKind sk) - : fileName(fn), source(s), scriptKind(sk) + SourceFile(std::string fn, std::string rn, parser::ScriptKind sk) + : fileName(fn), recordName(rn), scriptKind(sk) { } - std::string_view fileName {}; + std::string fileName {}; + std::string recordName {}; std::string_view source {}; parser::ScriptKind scriptKind {}; + uint32_t hash {0}; }; struct CompilerOptions { @@ -60,7 +65,14 @@ struct CompilerOptions { bool enableTypeCheck {false}; bool dumpLiteralBuffer {false}; bool isDebuggerEvaluateExpressionMode {false}; - std::string sourceFile {}; + bool mergeAbc {false}; + ScriptExtension extension {}; + int fileThreadCount {0}; + int functionThreadCount {0}; + int optLevel {0}; + std::string output {}; + std::string debugInfoSourceFile {}; + std::vector sourceFiles; }; enum class ErrorType { @@ -142,6 +154,19 @@ public: NO_MOVE_SEMANTIC(Compiler); panda::pandasm::Program *Compile(const SourceFile &input, const CompilerOptions &options); + panda::pandasm::Program *CompileFile(CompilerOptions &options, SourceFile *src); + + static void CompileFiles(CompilerOptions &options, + std::unordered_map *cacheProgs, + std::vector &progs, + std::unordered_map &progsInfo, + panda::ArenaAllocator *allocator); + + static void SelectCompileFile(CompilerOptions &options, + std::unordered_map *cacheProgs, + std::vector &progs, + std::unordered_map &progsInfo, + panda::ArenaAllocator *allocator); inline panda::pandasm::Program *Compile(const SourceFile &input) { diff --git a/es2panda/ir/expressions/literal.h b/es2panda/ir/expressions/literal.h index c38869152df2e7338db52a515f8029cdae40e525..57c76603b36e3008f6de894f03377d5fdb982082 100644 --- a/es2panda/ir/expressions/literal.h +++ b/es2panda/ir/expressions/literal.h @@ -41,7 +41,9 @@ enum class LiteralTag { GENERATOR_METHOD, ACCESSOR, METHODAFFILIATE, - ASYNC_GENERATOR_METHOD, + // 0x0a - 0x15 for ARRAY_Type + ASYNC_GENERATOR_METHOD = 22, + LITERALBUFFERINDEX = 23, NULL_VALUE = 255, }; diff --git a/es2panda/parser/commonjs.cpp b/es2panda/parser/commonjs.cpp index 110c378c269c441ae10c7a4b9ffb785e3e4466d3..cd28c9d1988c320138047ce5b9ca5f9f8e659817 100644 --- a/es2panda/parser/commonjs.cpp +++ b/es2panda/parser/commonjs.cpp @@ -53,7 +53,7 @@ void ParserImpl::AddCommonjsArgs(ArenaVector &args) } } -void ParserImpl::ParseCommonjs(const std::string &fileName, const std::string &source) +void ParserImpl::ParseCommonjs() { // create FunctionExpression as callee ir::FunctionExpression *funcExpr = nullptr; diff --git a/es2panda/parser/parserImpl.cpp b/es2panda/parser/parserImpl.cpp index 99ca9bd40454d3a77808297e7509834d6e5798c5..d6bfecb3bff298ac7bf8c16f9ba7f810ad0b806c 100644 --- a/es2panda/parser/parserImpl.cpp +++ b/es2panda/parser/parserImpl.cpp @@ -108,9 +108,11 @@ std::unique_ptr ParserImpl::InitLexer(const std::string &fileName, return lexer; } -Program ParserImpl::Parse(const std::string &fileName, const std::string &source, ScriptKind kind) +Program ParserImpl::Parse(const std::string &fileName, const std::string &source, + const std::string &recordName, ScriptKind kind) { program_.SetKind(kind); + program_.SetRecordName(recordName); /* * In order to make the lexer's memory alive, the return value 'lexer' can not be omitted. @@ -118,15 +120,15 @@ Program ParserImpl::Parse(const std::string &fileName, const std::string &source auto lexer = InitLexer(fileName, source); switch (kind) { case ScriptKind::SCRIPT: { - ParseScript(fileName, source); + ParseScript(); break; } case ScriptKind::MODULE: { - ParseModule(fileName, source); + ParseModule(); break; } case ScriptKind::COMMONJS: { - ParseCommonjs(fileName, source); + ParseCommonjs(); break; } default: { @@ -137,12 +139,12 @@ Program ParserImpl::Parse(const std::string &fileName, const std::string &source return std::move(program_); } -void ParserImpl::ParseScript(const std::string &fileName, const std::string &source) +void ParserImpl::ParseScript() { ParseProgram(ScriptKind::SCRIPT); } -void ParserImpl::ParseModule(const std::string &fileName, const std::string &source) +void ParserImpl::ParseModule() { context_.Status() |= (ParserStatus::MODULE); ParseProgram(ScriptKind::MODULE); diff --git a/es2panda/parser/parserImpl.h b/es2panda/parser/parserImpl.h index 1c27794daf1297c671e41a40026ec38cbc0f29ef..0a70e8e116daf8c91de2a07f63af8088febd089b 100644 --- a/es2panda/parser/parserImpl.h +++ b/es2panda/parser/parserImpl.h @@ -176,7 +176,8 @@ public: NO_MOVE_SEMANTIC(ParserImpl); ~ParserImpl() = default; - Program Parse(const std::string &fileName, const std::string &source, ScriptKind kind); + Program Parse(const std::string &fileName, const std::string &source, + const std::string &recordName, ScriptKind kind); ScriptExtension Extension() const; @@ -205,15 +206,15 @@ private: } [[nodiscard]] std::unique_ptr InitLexer(const std::string &fileName, const std::string &source); - void ParseScript(const std::string &fileName, const std::string &source); - void ParseModule(const std::string &fileName, const std::string &source); + void ParseScript(); + void ParseModule(); /* * Transform the commonjs's AST by wrapping the sourceCode * e.g. (function (exports, require, module, __filename, __dirname) { * [Origin_SourceCode] * })(exports, require, module, __filename, __dirname); */ - void ParseCommonjs(const std::string &fileName, const std::string &source); + void ParseCommonjs(); void AddCommonjsParams(ArenaVector ¶ms); void AddCommonjsArgs(ArenaVector &args); void ParseProgram(ScriptKind kind); diff --git a/es2panda/parser/program/program.h b/es2panda/parser/program/program.h index 667d38cffe0f84a005622c928038c690a16151aa..54a68dcdb82633bb9f0766e6497cfdf8d667eace 100644 --- a/es2panda/parser/program/program.h +++ b/es2panda/parser/program/program.h @@ -84,6 +84,11 @@ public: return sourceFile_.View(); } + util::StringView RecordName() const + { + return recordName_.View(); + } + const lexer::LineIndex &GetLineIndex() const { return lineIndex_; @@ -111,6 +116,11 @@ public: lineIndex_ = lexer::LineIndex(SourceCode()); } + void SetRecordName(const std::string &recordName) + { + recordName_ = util::UString(recordName, Allocator()); + } + std::string Dump() const; void SetKind(ScriptKind kind); @@ -120,6 +130,7 @@ private: ir::BlockStatement *ast_ {}; util::UString sourceCode_ {}; util::UString sourceFile_ {}; + util::UString recordName_ {}; ScriptKind kind_ {}; ScriptExtension extension_ {}; lexer::LineIndex lineIndex_ {}; diff --git a/es2panda/util/helpers.cpp b/es2panda/util/helpers.cpp index f04ee77ddda398431b61fd56e05df28b8e485a84..10c598c4768427b318b971e8ec45d74c3adf0fc5 100644 --- a/es2panda/util/helpers.cpp +++ b/es2panda/util/helpers.cpp @@ -15,6 +15,7 @@ #include "helpers.h" +#include #include #include #include @@ -33,6 +34,15 @@ #include #include +#ifdef ENABLE_BYTECODE_OPT +#include +#include +#else +#include +#include +#include +#endif + namespace panda::es2panda::util { // Helpers @@ -403,4 +413,27 @@ std::tuple Helpers::ParamName(ArenaAllocator *allocator, return {Helpers::ToStringView(allocator, index), true}; } +bool Helpers::OptimizeProgram(panda::pandasm::Program * prog, es2panda::CompilerOptions *options) +{ + std::map stat; + std::map *statp = &stat; + panda::pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps{}; + panda::pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp = &maps; + +#ifdef PANDA_WITH_BYTECODE_OPTIMIZER + const uint32_t COMPONENT_MASK = panda::Logger::Component::ASSEMBLER | + panda::Logger::Component::BYTECODE_OPTIMIZER | + panda::Logger::Component::COMPILER; + panda::Logger::InitializeStdLogging(panda::Logger::Level::ERROR, COMPONENT_MASK); + + if (!panda::pandasm::AsmEmitter::Emit(options->output, *prog, statp, mapsp, true)) { + return false; + } + + panda::bytecodeopt::options.SetOptLevel(options->optLevel); + panda::bytecodeopt::OptimizeBytecode(prog, mapsp, options->output, true, true); +#endif + return true; +} + } // namespace panda::es2panda::util diff --git a/es2panda/util/helpers.h b/es2panda/util/helpers.h index a5dab4112a7c946c80ea5f44d12c08636a75423b..e970162905332f364a6e1fbbf4abe53fd3ed0404 100644 --- a/es2panda/util/helpers.h +++ b/es2panda/util/helpers.h @@ -31,6 +31,15 @@ class Identifier; class AstNode; } // namespace panda::es2panda::ir +namespace panda::es2panda { +struct CompilerOptions; +} // namespace panda::es2panda + +namespace panda::pandasm { +struct Program; +} // namespace panda::pandasm + + namespace panda::es2panda::util { class Helpers { @@ -65,6 +74,8 @@ public: static std::tuple ParamName(ArenaAllocator *allocator, const ir::AstNode *param, uint32_t index); + static bool OptimizeProgram(panda::pandasm::Program *prog, es2panda::CompilerOptions *options); + static const uint32_t INVALID_INDEX = 4294967295L; static const uint32_t MAX_INT32 = 2147483647; }; diff --git a/es2panda/util/moduleHelpers.cpp b/es2panda/util/moduleHelpers.cpp new file mode 100644 index 0000000000000000000000000000000000000000..95ee9d64f38c0b46b04a4f6445918e34b720ad7b --- /dev/null +++ b/es2panda/util/moduleHelpers.cpp @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.Apache.Org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "moduleHelpers.h" + +#include + +namespace panda::es2panda::util { +void ModuleHelpers::CompileNpmModuleEntryList(const std::string &entriesInfo, + std::unordered_map *cacheProgs, + std::vector &progs, + std::unordered_map &progsInfo, + panda::ArenaAllocator *allocator) +{ + std::stringstream ss; + std::ifstream inputStream(entriesInfo); + if (inputStream.fail()) { + std::cerr << "Failed to read file to buffer: " << entriesInfo << std::endl; + return; + } + ss << inputStream.rdbuf(); + + uint32_t hash = GetHash32String(reinterpret_cast(ss.str().c_str())); + + if (cacheProgs != nullptr) { + auto it = cacheProgs->find(entriesInfo); + if (it != cacheProgs->end() && hash == it->second->hashCode) { + progs.push_back(it->second->program); + auto *cache = allocator->New(it->second->hashCode, it->second->program); + progsInfo.insert({entriesInfo, cache}); + return; + } + } + + auto *prog = allocator->New(); + std::string line; + while (getline(ss, line)) { + std::size_t pos = line.find(":"); + std::string recordName = line.substr(0, pos); + std::string field = line.substr(pos + 1); + + auto langExt = panda::pandasm::extensions::Language::ECMASCRIPT; + auto entryNameField = panda::pandasm::Field(langExt); + entryNameField.name = field; + entryNameField.type = panda::pandasm::Type("u8", 0); + entryNameField.metadata->SetValue(panda::pandasm::ScalarValue::Create( + static_cast(0))); + + panda::pandasm::Record *entryRecord = new panda::pandasm::Record(recordName, langExt); + entryRecord->field_list.emplace_back(std::move(entryNameField)); + prog->record_table.emplace(recordName, std::move(*entryRecord)); + } + + progs.push_back(prog); + auto *cache = allocator->New(hash, prog); + progsInfo.insert({entriesInfo, cache}); +} +} // namespace panda::es2panda::util diff --git a/es2panda/util/moduleHelpers.h b/es2panda/util/moduleHelpers.h new file mode 100644 index 0000000000000000000000000000000000000000..5d4035e7b146f0d1d78e53dac3c95ea2bbedbe99 --- /dev/null +++ b/es2panda/util/moduleHelpers.h @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ES2PANDA_UTIL_MODULE_HELPERS_H +#define ES2PANDA_UTIL_MODULE_HELPERS_H + +#include +#include +#include + +namespace panda::es2panda::util { +class ModuleHelpers { +public: + static void CompileNpmModuleEntryList(const std::string &entriesInfo, + std::unordered_map *cacheProgs, + std::vector &progs, + std::unordered_map &progsInfo, + panda::ArenaAllocator *allocator); +}; +} // panda::es2panda::util + +#endif diff --git a/es2panda/util/programCache.h b/es2panda/util/programCache.h new file mode 100644 index 0000000000000000000000000000000000000000..f0512342e2843a2900edf41ebeb86c414ea5ff47 --- /dev/null +++ b/es2panda/util/programCache.h @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ES2PANDA_UTIL_PROGRAM_CACHE_H +#define ES2PANDA_UTIL_PROGRAM_CACHE_H + +#include + +namespace panda::es2panda::util { +struct ProgramCache { + uint32_t hashCode; + panda::pandasm::Program* program; + + ProgramCache(uint32_t hashCode, panda::pandasm::Program* program) : hashCode(hashCode), program(program) + { + } +}; +} //panda::es2panda::util +#endif diff --git a/merge_abc/BUILD.gn b/merge_abc/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..24b6ce535165a334874bcadd18f69ea62deb5379 --- /dev/null +++ b/merge_abc/BUILD.gn @@ -0,0 +1,285 @@ +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_frontend/ets_frontend_config.gni") +import("//arkcompiler/runtime_core/ark_config.gni") +import("//build/config/clang/clang.gni") +import("//build/ohos.gni") +import("//developtools/profiler/build/config.gni") + +proto_base_dir = "protos" +proto_out_dir = "$target_gen_dir" + "/protos_generated" + +protobuf_snapshot_generator_sources = [ + "src/annotationProto.cpp", + "src/assemblyDebugProto.cpp", + "src/assemblyFieldProto.cpp", + "src/assemblyFileLocationProto.cpp", + "src/assemblyFunctionProto.cpp", + "src/assemblyInsProto.cpp", + "src/assemblyLabelProto.cpp", + "src/assemblyLiteralsProto.cpp", + "src/assemblyProgramProto.cpp", + "src/assemblyRecordProto.cpp", + "src/assemblyTypeProto.cpp", + "src/compositeProgramProto.cpp", + "src/ideHelpersProto.cpp", + "src/mergeProgram.cpp", + "src/metaProto.cpp", + "src/protobufSnapshotGenerator.cpp", +] + +config("panda_assembly_proto_public_config") { + include_dirs = [ + "$ark_root/assembler", + "$ark_root/libpandabase", + "$ark_root/libpandabase/mem", + "$ark_root", + "src", + "$proto_out_dir", + "//third_party/protobuf/src", + "//third_party/protobuf/src/google", + "//third_party/protobuf/src/google/protobuf", + "//arkcompiler/ets_frontend/es2panda/util", + ] +} + +assembly_proto_configs = [ + sdk_libc_secshared_config, + "$ark_root:ark_config", + ":panda_assembly_proto_public_config", + "$ark_root/assembler:arkassembler_public_config", + "$ark_root/libpandabase:arkbase_public_config", + "$ark_root/libpandafile:arkfile_public_config", +] + +proto_file_defines = [ + # add your proto file here + "annotation", + "assemblyDebug", + "assemblyField", + "assemblyFileLocation", + "assemblyFunction", + "assemblyIns", + "assemblyLabel", + "assemblyLiterals", + "assemblyProgram", + "assemblyRecord", + "assemblyType", + "compositeProgram", + "ideHelpers", + "meta", +] + +proto_file_sources = [] +proto_generated_header = [] +proto_generated_source = [] + +foreach(proto_file, proto_file_defines) { + proto_generated_header += [ "$proto_out_dir" + "/" + "$proto_file.pb.h" ] + proto_generated_source += [ "$proto_out_dir" + "/" + "$proto_file.pb.cc" ] + proto_file_sources += [ "$proto_base_dir" + "/" + "$proto_file.proto" ] +} + +protoc_binary_out_path = + "${OHOS_PROFILER_SUBSYS_NAME}/${OHOS_PROFILER_PART_NAME}" + +if (default_toolchain == current_toolchain) { + #if target build + host_out_path = "/" + get_label_info(host_toolchain, "name") +} else { + #if host build (for some linke mingw) + host_out_path = "/../" + get_label_info(host_toolchain, "name") +} + +host_protoc_path = + root_out_dir + host_out_path + "/" + protoc_binary_out_path + "/protoc" + +action("arkcompiler_generate_proto") { + deps = [ "//third_party/protobuf:protoc($host_toolchain)" ] + args = [] + sources = [] + outputs = proto_generated_header + proto_generated_source + script = "./script/build_proto.sh" + + args += [ rebase_path(host_protoc_path) ] + args += [ + "--proto_path", + rebase_path(proto_base_dir), + "--cpp_out", + rebase_path(proto_out_dir), + "--experimental_allow_proto3_optional", + ] + + foreach(proto_file_source, proto_file_sources) { + #tell gn to check which files as source time + sources += [ rebase_path(proto_file_source) ] + args += [ rebase_path(proto_file_source) ] + } +} + +config("proto_file_cpp_config") { + include_dirs = [ proto_out_dir ] +} + +ohos_source_set("assembly_proto_static") { + cflags = [ "-Wno-error=zero-length-array" ] + + deps = [ + ":arkcompiler_generate_proto", + "//third_party/protobuf:protobuf_lite_static", + "//third_party/protobuf:protobuf_static", + ] + + sources = proto_generated_header + proto_generated_source + + protobuf_snapshot_generator_sources + public_configs = assembly_proto_configs + public_configs += [ ":proto_file_cpp_config" ] +} + +ohos_static_library("panda_assembly_proto_static") { + deps = [ ":assembly_proto_static" ] +} + +ohos_executable("merge_abc") { + use_exceptions = true + sources = [ + "src/main.cpp", + "src/options.cpp", + ] + + include_dirs = [ "./src" ] + + configs = [ + sdk_libc_secshared_config, + "$ark_root:ark_config", + ":panda_assembly_proto_public_config", + "$ark_root/assembler:arkassembler_public_config", + "$ark_root/libpandabase:arkbase_public_config", + "$ark_root/libpandafile:arkfile_public_config", + ":proto_file_cpp_config", + ] + + deps = [ + ":panda_assembly_proto_static", + "$ark_root/assembler:libarkassembler_frontend_static", + "$ark_root/libpandabase:libarkbase_frontend_static", + "$ark_root/libpandafile:libarkfile_frontend_static", + "$ark_root/libziparchive:libarkziparchive_frontend_static", + "//third_party/icu/icu4c:static_icuuc", + ] + + ldflags = [] + if (is_linux) { + if (build_public_version) { + ldflags += [ "-static-libstdc++" ] + } else { + libs = [ libcpp_static_lib ] + } + + defines = [ "PANDA_TARGET_LINUX" ] + + # for statically linking pthread + ldflags += [ + "-Wl,--whole-archive", + "-lrt", + "-lpthread", + "-Wl,--no-whole-archive", + ] + } else if (is_mac) { + defines = [ "PANDA_TARGET_MACOS" ] + } else if (is_mingw) { + defines = [ "PANDA_TARGET_WINDOWS" ] + } + + if (!is_mac) { + static_link = true + } + + if (!use_musl) { + static_link = false + ldflags += [ "-lc++" ] + } + + output_name = "merge_abc" + install_enable = true + subsystem_name = "ark" +} + +if (is_linux) { + ohos_copy("merge_abc_build") { + deps = [ ":merge_abc" ] + sources = [ "${root_out_dir}/ark/ark/merge_abc" ] + outputs = [ "${target_out_dir}/merge_abc-tmp" ] + module_source_dir = "${root_out_dir}/ark/ark" + module_install_name = "merge_abc" + } + + ohos_copy("merge_abc_build_ets") { + deps = [ ":merge_abc" ] + sources = [ "${root_out_dir}/ark/ark/merge_abc" ] + outputs = [ "${root_out_dir}/ark/ark/merge_abc-ets" ] + module_source_dir = "${root_out_dir}/ark/ark" + module_install_name = "merge_abc" + } +} + +if (is_mingw) { + ohos_copy("merge_abc_build_win") { + deps = [ ":merge_abc" ] + sources = [ "${root_out_dir}/ark/ark/merge_abc.exe" ] + outputs = [ "${target_out_dir}/merge_abc-tmp" ] + module_source_dir = "${root_out_dir}/ark/ark" + module_install_name = "merge_abc.exe" + } + + ohos_copy("merge_abc_build_win_ets") { + deps = [ ":merge_abc" ] + sources = [ "${root_out_dir}/ark/ark/merge_abc.exe" ] + outputs = [ "${root_out_dir}/ark/ark/merge_abc-win-ets" ] + module_source_dir = "${root_out_dir}/ark/ark" + module_install_name = "merge_abc.exe" + } +} + +if (is_mac) { + ohos_copy("merge_abc_build_mac") { + deps = [ ":merge_abc" ] + sources = [ "${root_out_dir}/ark/ark/merge_abc" ] + outputs = [ "${target_out_dir}/merge_abc-tmp" ] + module_source_dir = "${root_out_dir}/ark/ark" + module_install_name = "merge_abc" + } + + ohos_copy("merge_abc_build_mac_ets") { + deps = [ ":merge_abc" ] + sources = [ "${root_out_dir}/ark/ark/merge_abc" ] + outputs = [ "${root_out_dir}/ark/ark/merge_abc-mac-ets" ] + module_source_dir = "${root_out_dir}/ark/ark" + module_install_name = "merge_abc" + } +} + +group("merge_proto_abc_build") { + if (host_os == "linux") { + deps = [ ":merge_abc(${toolchain_linux})" ] + } + + if (host_os == "mac") { + deps = [ ":merge_abc(${toolchain_mac})" ] + } +} + +group("merge_proto_abc_build_win") { + deps = [ ":merge_abc(${toolchain_win})" ] +} diff --git a/merge_abc/protos/annotation.proto b/merge_abc/protos/annotation.proto new file mode 100644 index 0000000000000000000000000000000000000000..91e850d73d2f0c4056699f4466196a5a9bfbcb9f --- /dev/null +++ b/merge_abc/protos/annotation.proto @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; +package protoPanda; + +import "assemblyType.proto"; + +message Value { + uint32 type = 1; +} + +message ScalarValue { + enum VariantValueType { + UINT64 = 0; + FLOAT = 1; + DOUBLE = 2; + STRING = 3; + PANDASM_TYPE = 4; + ANNOTATION_DATA = 5; + } + Value father = 1; + oneof value { + uint64 valueU64 = 2; + float valueFloat = 3; + double valueDouble = 4; + bytes valueStr = 5; + Type valueType = 6; + AnnotationData valueAnno = 7; + } + VariantValueType type = 8; +} + +message ArrayValue { + Value father = 1; + uint32 componentType = 2; + repeated ScalarValue values = 3; +} + +message AnnotationElement { + enum ValueType { + SCALAR = 0; + ARRAY = 1; + } + bytes name = 1; + oneof value { + ScalarValue scalar = 2; + ArrayValue array = 3; + } + ValueType valueType = 4; +} + +message AnnotationData { + bytes recordName = 1; + repeated AnnotationElement elements = 2; +} diff --git a/merge_abc/protos/assemblyDebug.proto b/merge_abc/protos/assemblyDebug.proto new file mode 100644 index 0000000000000000000000000000000000000000..16321f5e191a6f51366737f63fc63a13743926ec --- /dev/null +++ b/merge_abc/protos/assemblyDebug.proto @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; +package protoPanda; + +message DebuginfoIns { + uint64 lineNumber = 1; + uint32 columnNumber = 2; + bytes wholeLine = 3; + uint64 boundLeft = 4; + uint64 boundRight = 5; +} + +message LocalVariable { + bytes name = 1; + bytes signature = 2; + bytes signatureType = 3; + int32 reg = 4; + uint32 start = 5; + uint32 length = 6; +} diff --git a/merge_abc/protos/assemblyField.proto b/merge_abc/protos/assemblyField.proto new file mode 100644 index 0000000000000000000000000000000000000000..70c8d6bbb21fff6fc61cc9b1bab2e45f58686649 --- /dev/null +++ b/merge_abc/protos/assemblyField.proto @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; +package protoPanda; + +import "assemblyType.proto"; +import "meta.proto"; + +message Field { + Type type = 1; + bytes name = 2; + FieldMetadata metadata = 3; + uint64 lineOfDef = 4; + bytes wholeLine = 5; + uint64 boundLeft = 6; + uint64 boundRight = 7; + bool isDefined = 8; +} diff --git a/merge_abc/protos/assemblyFileLocation.proto b/merge_abc/protos/assemblyFileLocation.proto new file mode 100644 index 0000000000000000000000000000000000000000..864a9a960910ac9affd07e863a4b7fa2d46eb8d7 --- /dev/null +++ b/merge_abc/protos/assemblyFileLocation.proto @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; +package protoPanda; + +message FileLocation { + bytes wholeLine = 1; + uint64 boundLeft = 2; + uint64 boundRight = 3; + uint64 lineNumber = 4; + bool isDefined = 5; +} diff --git a/merge_abc/protos/assemblyFunction.proto b/merge_abc/protos/assemblyFunction.proto new file mode 100644 index 0000000000000000000000000000000000000000..8fb3c05943af21b48f4c87d43740fb6a693bd29a --- /dev/null +++ b/merge_abc/protos/assemblyFunction.proto @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; +package protoPanda; + +import "assemblyIns.proto"; +import "assemblyLabel.proto"; +import "assemblyType.proto"; +import "assemblyDebug.proto"; +import "assemblyFileLocation.proto"; +import "ideHelpers.proto"; +import "meta.proto"; + +message CatchBlock { + bytes wholeLine = 1; + bytes exceptionRecord = 2; + bytes tryBeginLabel = 3; + bytes tryEndLabel = 4; + bytes catchBeginLabel = 5; + bytes catchEndLabel = 6; +} + +message TryCatchInfo { + message TryCatchLabel { + bytes key = 1; + uint64 value = 2; + } + message TryCatchMap { + bytes key = 1; + repeated CatchBlock catchBlocks = 2; + } + repeated TryCatchLabel tryCatchLabels = 1; + repeated TryCatchMap tryCatchMap = 2; + repeated bytes tryCatchOrder = 3; +} + +message Parameter { + Type type = 1; + ParamMetadata metadata = 2; +} + +message Function { + message LabelTable { + bytes key = 1; + Label value = 2; + } + + bytes name = 1; + uint32 language = 2; + FunctionMetadata metadata = 3; + repeated LabelTable labelTable = 4; + repeated Ins ins = 5; + repeated LocalVariable localVariableDebug = 6; + bytes sourceFile = 7; + bytes sourceCode = 8; + repeated CatchBlock catchBlocks = 9; + int64 valueOfFirstParam = 10; + uint64 regsNum = 11; + repeated Parameter params = 12; + bool bodyPresence = 13; + Type returnType = 14; + SourceLocation bodyLocation = 15; + optional FileLocation fileLocation = 16; +} + diff --git a/merge_abc/protos/assemblyIns.proto b/merge_abc/protos/assemblyIns.proto new file mode 100644 index 0000000000000000000000000000000000000000..c5b90a1de3b480341ad7ca314e1a0d6f1d1807f3 --- /dev/null +++ b/merge_abc/protos/assemblyIns.proto @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; +package protoPanda; + +import "assemblyDebug.proto"; + +message Ins { + message IType { + oneof type { + int64 valueInt = 1; + double valueDouble = 2; + } + } + + uint32 opcode = 1; + repeated uint32 regs = 2; + repeated bytes ids = 3; + repeated IType imms = 4; + bytes label = 5; + // duplicate name + bool setLabelVal = 6; + DebuginfoIns insDebug = 7; +} diff --git a/merge_abc/protos/assemblyLabel.proto b/merge_abc/protos/assemblyLabel.proto new file mode 100644 index 0000000000000000000000000000000000000000..03e1d212628b02e4ea89c20c903a56a37a7761ee --- /dev/null +++ b/merge_abc/protos/assemblyLabel.proto @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; +package protoPanda; + +import "assemblyFileLocation.proto"; + +message Label { + bytes name = 1; + optional FileLocation fileLocation = 2; +} diff --git a/merge_abc/protos/assemblyLiterals.proto b/merge_abc/protos/assemblyLiterals.proto new file mode 100644 index 0000000000000000000000000000000000000000..e98480ff99fb5756a0182993ae3aca9367da12ce --- /dev/null +++ b/merge_abc/protos/assemblyLiterals.proto @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; +package protoPanda; + +message VariantValue { + enum VariantValueType { + BOOL = 0; + U8 = 1; + U16 = 2; + U32 = 3; + U64 = 4; + F32 = 5; + F64 = 6; + STRING = 7; + } + + oneof value { + uint64 valueInt = 1; + float valueFloat = 2; + double valueDouble = 3; + bytes valueStr = 4; + } + VariantValueType type = 5; +} + +message Literal { + uint32 tag = 1; // LiteralTag + VariantValue value = 2; +} + +message LiteralArray { + repeated Literal literals = 1; +} diff --git a/merge_abc/protos/assemblyProgram.proto b/merge_abc/protos/assemblyProgram.proto new file mode 100644 index 0000000000000000000000000000000000000000..58c93fbf979115dbbefa0cf659d29ae56bd4f2cd --- /dev/null +++ b/merge_abc/protos/assemblyProgram.proto @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; +package protoPanda; + +import "assemblyFunction.proto"; +import "assemblyRecord.proto"; +import "assemblyType.proto"; +import "assemblyLiterals.proto"; + +message Program { + message RecordTable { + bytes key = 1; + Record value = 2; + } + message FunctionTable { + bytes key = 1; + Function value = 2; + } + message FunctionSynnoyms { + bytes key = 1; + repeated bytes value = 2; + } + message LiteralArrayTable { + bytes key = 1; + LiteralArray value = 2; + } + uint32 lang = 1; + repeated RecordTable recordTable = 2; + repeated FunctionTable functionTable = 3; + repeated FunctionSynnoyms functionSynonyms = 4; + repeated LiteralArrayTable literalArrayTable = 5; + repeated bytes strings = 6; + repeated Type arrayTypes = 7; +} diff --git a/merge_abc/protos/assemblyRecord.proto b/merge_abc/protos/assemblyRecord.proto new file mode 100644 index 0000000000000000000000000000000000000000..9996414e59d53338fe49cd3f3145a16a11f92d5e --- /dev/null +++ b/merge_abc/protos/assemblyRecord.proto @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; +package protoPanda; + +import "assemblyField.proto"; +import "assemblyFileLocation.proto"; +import "ideHelpers.proto"; +import "meta.proto"; + +message Record { + bytes name = 1; + bool conflict = 2; + uint32 language = 3; + RecordMetadata metadata = 4; + repeated Field fieldList = 5; + uint64 paramsNum = 6; + bool bodyPresence = 7; + SourceLocation bodyLocation = 8; + bytes sourceFile = 9; + optional FileLocation fileLocation = 10; +} diff --git a/merge_abc/protos/assemblyType.proto b/merge_abc/protos/assemblyType.proto new file mode 100644 index 0000000000000000000000000000000000000000..ea6cb364252111da63a807f0a8ef0cd0695801bf --- /dev/null +++ b/merge_abc/protos/assemblyType.proto @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; +package protoPanda; + +message Type { + bytes componentName = 1; + uint64 rank = 2; + bytes name = 3; + uint32 typeId = 4; +} diff --git a/merge_abc/protos/compositeProgram.proto b/merge_abc/protos/compositeProgram.proto new file mode 100644 index 0000000000000000000000000000000000000000..0177aba504bd216c91aac086f0f8c5a915483146 --- /dev/null +++ b/merge_abc/protos/compositeProgram.proto @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; +package protoPanda; + +import "assemblyProgram.proto"; + +message ProgramCache { + bytes fileName = 1; + uint32 hashCode = 2; + Program program = 3; +} + +message CompositeProgram { + repeated ProgramCache ProgramCache = 1; + bool isDebug = 2; +} diff --git a/merge_abc/protos/ideHelpers.proto b/merge_abc/protos/ideHelpers.proto new file mode 100644 index 0000000000000000000000000000000000000000..e344b9b2825153220de7ed3e64362bebebffbe2c --- /dev/null +++ b/merge_abc/protos/ideHelpers.proto @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; +package protoPanda; + +message SourcePosition { + uint64 line = 1; + uint64 column = 2; +} + +message SourceLocation { + SourcePosition begin = 1; + SourcePosition end = 2; +} diff --git a/merge_abc/protos/meta.proto b/merge_abc/protos/meta.proto new file mode 100644 index 0000000000000000000000000000000000000000..05b4e7e3cee23e3c48b12b4ba3d00687766689cd --- /dev/null +++ b/merge_abc/protos/meta.proto @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; +package protoPanda; + +import "annotation.proto"; +import "assemblyType.proto"; + +message Metadata { + repeated bytes set_attributes = 1; + message Attributes { + bytes key = 1; + repeated bytes value = 2; + } + repeated Attributes attributes = 2; +} + +message AnnotationMetadata { + Metadata father = 1; + repeated AnnotationData annotations = 2; +} + +message ItemMetadata { + AnnotationMetadata father = 1; + uint32 accessFlags = 2; +} + +message RecordMetadata { + ItemMetadata father = 1; +} + +message FieldMetadata { + ItemMetadata father = 1; + Type fieldType = 2; + optional ScalarValue value = 3; +} + +message FunctionMetadata { + ItemMetadata father = 1; +} + +message ParamMetadata { + AnnotationMetadata father = 1; +} diff --git a/merge_abc/script/build_proto.sh b/merge_abc/script/build_proto.sh new file mode 100755 index 0000000000000000000000000000000000000000..6f513160455ee02fc1cc17359073e5a9d7e8b36f --- /dev/null +++ b/merge_abc/script/build_proto.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + +echo "use protoc to do the prebuild" + +echo "pwd $(pwd)" + +protoc_cmdline=$* +echo protoc_cmdline $protoc_cmdline + +cmd="$protoc_cmdline" +echo $cmd +$cmd + \ No newline at end of file diff --git a/merge_abc/src/annotationProto.cpp b/merge_abc/src/annotationProto.cpp new file mode 100644 index 0000000000000000000000000000000000000000..85d13681f20707e70d5fee92c42453318d12329c --- /dev/null +++ b/merge_abc/src/annotationProto.cpp @@ -0,0 +1,268 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "annotationProto.h" + +namespace panda::proto { +void AnnotationData::Serialize(const panda::pandasm::AnnotationData &anno, protoPanda::AnnotationData &protoAnno) +{ + protoAnno.set_recordname(anno.GetName()); + for (const auto &element : anno.GetElements()) { + auto *protoElement = protoAnno.add_elements(); + AnnotationElement::Serialize(element, *protoElement); + } +} + +void AnnotationData::Deserialize(const protoPanda::AnnotationData &protoAnno, panda::pandasm::AnnotationData &anno, + panda::ArenaAllocator *allocator) +{ + for (const auto &protoElement : protoAnno.elements()) { + panda::pandasm::AnnotationElement &element = AnnotationElement::Deserialize(protoElement, allocator); + anno.AddElement(std::move(element)); + } +} + +void AnnotationElement::Serialize(const panda::pandasm::AnnotationElement &element, + protoPanda::AnnotationElement &protoElement) +{ + protoElement.set_name(element.GetName()); + if (element.GetValue()->IsArray()) { + protoElement.set_valuetype(protoPanda::AnnotationElement_ValueType::AnnotationElement_ValueType_ARRAY); + auto *protoArray = protoElement.mutable_array(); + ArrayValue::Serialize(*(element.GetValue()->GetAsArray()), *protoArray); + } else { + protoElement.set_valuetype(protoPanda::AnnotationElement_ValueType::AnnotationElement_ValueType_SCALAR); + auto *protoScalar = protoElement.mutable_scalar(); + ScalarValue::Serialize(*(element.GetValue()->GetAsScalar()), *protoScalar); + } +} + +panda::pandasm::AnnotationElement &AnnotationElement::Deserialize(const protoPanda::AnnotationElement &protoElement, + panda::ArenaAllocator *allocator) +{ + if (protoElement.valuetype() == protoPanda::AnnotationElement_ValueType::AnnotationElement_ValueType_ARRAY) { + panda::pandasm::ArrayValue &array = ArrayValue::Deserialize(protoElement.array(), allocator); + auto *element = allocator->New(protoElement.name(), + std::make_unique(array)); + return *element; + } + panda::pandasm::ScalarValue scalar = ScalarValue::Deserialize(protoElement.scalar(), allocator); + auto *element = allocator->New(protoElement.name(), + std::make_unique(scalar)); + return *element; +} + +void ScalarValue::Serialize(const panda::pandasm::ScalarValue &scalar, protoPanda::ScalarValue &protoScalar) +{ + const auto &valueType = scalar.GetType(); + protoScalar.mutable_father()->set_type(static_cast(valueType)); + auto type = protoPanda::ScalarValue_VariantValueType::ScalarValue_VariantValueType_UINT64; + switch (valueType) { + case panda::pandasm::Value::Type::U1: + case panda::pandasm::Value::Type::U8: + protoScalar.set_valueu64(static_cast(scalar.GetValue())); + break; + case panda::pandasm::Value::Type::U16: + protoScalar.set_valueu64(static_cast(scalar.GetValue())); + break; + case panda::pandasm::Value::Type::STRING_NULLPTR: + case panda::pandasm::Value::Type::U32: + protoScalar.set_valueu64(static_cast(scalar.GetValue())); + break; + case panda::pandasm::Value::Type::U64: + protoScalar.set_valueu64(scalar.GetValue()); + break; + case panda::pandasm::Value::Type::I8: + protoScalar.set_valueu64(static_cast(scalar.GetValue())); + break; + case panda::pandasm::Value::Type::I16: + protoScalar.set_valueu64(static_cast(scalar.GetValue())); + break; + case panda::pandasm::Value::Type::I32: + protoScalar.set_valueu64(static_cast(scalar.GetValue())); + break; + case panda::pandasm::Value::Type::I64: + protoScalar.set_valueu64(static_cast(scalar.GetValue())); + break; + case panda::pandasm::Value::Type::F32: + type = protoPanda::ScalarValue_VariantValueType::ScalarValue_VariantValueType_FLOAT; + protoScalar.set_valuefloat(scalar.GetValue()); + break; + case panda::pandasm::Value::Type::F64: + type = protoPanda::ScalarValue_VariantValueType::ScalarValue_VariantValueType_DOUBLE; + protoScalar.set_valuedouble(scalar.GetValue()); + break; + case panda::pandasm::Value::Type::STRING: + case panda::pandasm::Value::Type::METHOD: + case panda::pandasm::Value::Type::ENUM: + type = protoPanda::ScalarValue_VariantValueType::ScalarValue_VariantValueType_STRING; + protoScalar.set_valuestr(scalar.GetValue()); + break; + case panda::pandasm::Value::Type::RECORD: { + type = protoPanda::ScalarValue_VariantValueType::ScalarValue_VariantValueType_PANDASM_TYPE; + auto *protoType = protoScalar.mutable_valuetype(); + Type::Serialize(scalar.GetValue(), *protoType); + break; + } + case panda::pandasm::Value::Type::ANNOTATION: { + type = protoPanda::ScalarValue_VariantValueType::ScalarValue_VariantValueType_ANNOTATION_DATA; + auto *protoAnno = protoScalar.mutable_valueanno(); + AnnotationData::Serialize(scalar.GetValue(), *protoAnno); + break; + } + default: + UNREACHABLE(); + } + protoScalar.set_type(type); +} + +panda::pandasm::ScalarValue ScalarValue::Deserialize(const protoPanda::ScalarValue &protoScalar, + panda::ArenaAllocator *allocator) +{ + protoPanda::ScalarValue_VariantValueType scalarType = protoScalar.type(); + std::variant value; + switch (scalarType) { + case protoPanda::ScalarValue_VariantValueType::ScalarValue_VariantValueType_UINT64: { + value = static_cast(protoScalar.valueu64()); + break; + } + case protoPanda::ScalarValue_VariantValueType::ScalarValue_VariantValueType_FLOAT: { + value = static_cast(protoScalar.valuefloat()); + break; + } + case protoPanda::ScalarValue_VariantValueType::ScalarValue_VariantValueType_DOUBLE: { + value = static_cast(protoScalar.valuedouble()); + break; + } + case protoPanda::ScalarValue_VariantValueType::ScalarValue_VariantValueType_STRING: { + value = static_cast(protoScalar.valuestr()); + break; + } + case protoPanda::ScalarValue_VariantValueType::ScalarValue_VariantValueType_PANDASM_TYPE: { + value = static_cast(Type::Deserialize(protoScalar.valuetype(), allocator)); + break; + } + case protoPanda::ScalarValue_VariantValueType::ScalarValue_VariantValueType_ANNOTATION_DATA: { + auto &protoAnnotationData = protoScalar.valueanno(); + auto *value = allocator->New(protoAnnotationData.recordname()); + AnnotationData::Deserialize(protoAnnotationData, *value, allocator); + break; + } + default: + UNREACHABLE(); + } + auto scalar = ScalarValue::CreateScalarValue(static_cast( + protoScalar.father().type()), value); + return scalar; +} + +panda::pandasm::ScalarValue ScalarValue::CreateScalarValue(const panda::pandasm::Value::Type &type, + std::variant &value) +{ + switch (type) { + case panda::pandasm::Value::Type::U1: { + return panda::pandasm::ScalarValue::Create(static_cast( + std::get(value))); + } + case panda::pandasm::Value::Type::U8: { + return panda::pandasm::ScalarValue::Create(static_cast( + std::get(value))); + } + case panda::pandasm::Value::Type::U16: { + return panda::pandasm::ScalarValue::Create(static_cast( + std::get(value))); + } + case panda::pandasm::Value::Type::STRING_NULLPTR: { + return panda::pandasm::ScalarValue::Create( + static_cast(std::get(value))); + } + case panda::pandasm::Value::Type::U32: { + return panda::pandasm::ScalarValue::Create(static_cast( + std::get(value))); + } + case panda::pandasm::Value::Type::U64: { + return panda::pandasm::ScalarValue::Create(static_cast( + std::get(value))); + } + case panda::pandasm::Value::Type::I8: { + return panda::pandasm::ScalarValue::Create(static_cast( + std::get(value))); + } + case panda::pandasm::Value::Type::I16: { + return panda::pandasm::ScalarValue::Create(static_cast( + std::get(value))); + } + case panda::pandasm::Value::Type::I32: { + return panda::pandasm::ScalarValue::Create(static_cast( + std::get(value))); + } + case panda::pandasm::Value::Type::I64: { + return panda::pandasm::ScalarValue::Create(static_cast( + std::get(value))); + } + case panda::pandasm::Value::Type::F32: { + return panda::pandasm::ScalarValue::Create(std::get(value)); + } + case panda::pandasm::Value::Type::F64: { + return panda::pandasm::ScalarValue::Create(std::get(value)); + } + case panda::pandasm::Value::Type::STRING: { + return panda::pandasm::ScalarValue::Create( + std::get(value)); + } + case panda::pandasm::Value::Type::METHOD: { + return panda::pandasm::ScalarValue::Create( + std::get(value)); + } + case panda::pandasm::Value::Type::ENUM: { + return panda::pandasm::ScalarValue::Create(std::get(value)); + } + case panda::pandasm::Value::Type::RECORD: { + return panda::pandasm::ScalarValue::Create( + std::get(value)); + } + case panda::pandasm::Value::Type::ANNOTATION: { + return panda::pandasm::ScalarValue::Create( + std::get(value)); + } + default: + UNREACHABLE(); + } +} + +void ArrayValue::Serialize(const panda::pandasm::ArrayValue &array, protoPanda::ArrayValue &protoArray) +{ + protoArray.mutable_father()->set_type(static_cast(array.GetType())); + protoArray.set_componenttype(static_cast(array.GetComponentType())); + for (const auto &val : array.GetValues()) { + auto *protoScalar = protoArray.add_values(); + ScalarValue::Serialize(val, *protoScalar); + } +} + +panda::pandasm::ArrayValue &ArrayValue::Deserialize(const protoPanda::ArrayValue &protoArray, + panda::ArenaAllocator *allocator) +{ + std::vector values; + values.reserve(protoArray.values_size()); + for (const auto &protoValue : protoArray.values()) { + panda::pandasm::ScalarValue scalar = ScalarValue::Deserialize(protoValue, allocator); + values.emplace_back(std::move(scalar)); + } + auto *array = allocator->New( + static_cast(protoArray.componenttype()), values); + return *array; +} +} // panda::proto diff --git a/merge_abc/src/annotationProto.h b/merge_abc/src/annotationProto.h new file mode 100644 index 0000000000000000000000000000000000000000..e34d7bdba6a8b66a7d193d36a5ea95651c401e3d --- /dev/null +++ b/merge_abc/src/annotationProto.h @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MERGE_ABC_ANNOTATION_H +#define MERGE_ABC_ANNOTATION_H + +#include "annotation.pb.h" +#include "arena_allocator.h" +#include "assembly-program.h" +#include "assemblyTypeProto.h" + +namespace panda::proto { +class AnnotationData { +public: + static void Serialize(const panda::pandasm::AnnotationData &anno, protoPanda::AnnotationData &protoAnno); + static void Deserialize(const protoPanda::AnnotationData &protoAnno, panda::pandasm::AnnotationData &anno, + panda::ArenaAllocator *allocator); +}; + +class AnnotationElement { +public: + static void Serialize(const panda::pandasm::AnnotationElement &element, + protoPanda::AnnotationElement &protoElement); + static panda::pandasm::AnnotationElement &Deserialize(const protoPanda::AnnotationElement &protoElement, + panda::ArenaAllocator *allocator); +}; + +class ScalarValue { +public: + static void Serialize(const panda::pandasm::ScalarValue &scalar, protoPanda::ScalarValue &protoScalar); + static panda::pandasm::ScalarValue Deserialize(const protoPanda::ScalarValue &protoScalar, + panda::ArenaAllocator *allocator); + static panda::pandasm::ScalarValue CreateScalarValue(const panda::pandasm::Value::Type &type, + std::variant + &value); +}; + +class ArrayValue { +public: + static void Serialize(const panda::pandasm::ArrayValue &array, protoPanda::ArrayValue &protoArray); + static panda::pandasm::ArrayValue &Deserialize(const protoPanda::ArrayValue &protoArray, + panda::ArenaAllocator *allocator); +}; +} // panda::proto +#endif diff --git a/merge_abc/src/assemblyDebugProto.cpp b/merge_abc/src/assemblyDebugProto.cpp new file mode 100644 index 0000000000000000000000000000000000000000..443d4a2d8011967dc935a91f70f7d21aaa7b8800 --- /dev/null +++ b/merge_abc/src/assemblyDebugProto.cpp @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "assemblyDebugProto.h" + +namespace panda::proto { +void DebuginfoIns::Serialize(const panda::pandasm::debuginfo::Ins &debug, protoPanda::DebuginfoIns &protoDebug) +{ + protoDebug.set_linenumber(debug.line_number); + protoDebug.set_columnnumber(debug.column_number); + protoDebug.set_wholeline(debug.whole_line); + protoDebug.set_boundleft(debug.bound_left); + protoDebug.set_boundright(debug.bound_right); +} + +void DebuginfoIns::Deserialize(const protoPanda::DebuginfoIns &protoDebug, panda::pandasm::debuginfo::Ins &debug) +{ + debug.line_number = protoDebug.linenumber(); + debug.column_number = protoDebug.columnnumber(); + debug.whole_line = protoDebug.wholeline(); + debug.bound_left = protoDebug.boundleft(); + debug.bound_right = protoDebug.boundright(); +} + +void LocalVariable::Serialize(const panda::pandasm::debuginfo::LocalVariable &debug, + protoPanda::LocalVariable &protoDebug) +{ + protoDebug.set_name(debug.name); + protoDebug.set_signature(debug.signature); + protoDebug.set_signaturetype(debug.signature_type); + protoDebug.set_reg(debug.reg); + protoDebug.set_start(debug.start); + protoDebug.set_length(debug.length); +} + +void LocalVariable::Deserialize(const protoPanda::LocalVariable &protoDebug, + panda::pandasm::debuginfo::LocalVariable &debug) +{ + debug.name = protoDebug.name(); + debug.signature = protoDebug.signature(); + debug.signature_type = protoDebug.signaturetype(); + debug.reg = protoDebug.reg(); + debug.start = protoDebug.start(); + debug.length = protoDebug.length(); +} +} // panda::proto diff --git a/merge_abc/src/assemblyDebugProto.h b/merge_abc/src/assemblyDebugProto.h new file mode 100644 index 0000000000000000000000000000000000000000..47e3e3766d0b6ec5e8d1d209a6a4b21c92416446 --- /dev/null +++ b/merge_abc/src/assemblyDebugProto.h @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MERGE_ABC_ASSEMBLY_DEBUG_H +#define MERGE_ABC_ASSEMBLY_DEBUG_H + +#include "assemblyDebug.pb.h" +#include "assembly-program.h" + +namespace panda::proto { +class DebuginfoIns { +public: + static void Serialize(const panda::pandasm::debuginfo::Ins &debug, protoPanda::DebuginfoIns &protoDebug); + static void Deserialize(const protoPanda::DebuginfoIns &protoDebug, panda::pandasm::debuginfo::Ins &debug); +}; + +class LocalVariable { +public: + static void Serialize(const panda::pandasm::debuginfo::LocalVariable &debug, + protoPanda::LocalVariable &protoDebug); + static void Deserialize(const protoPanda::LocalVariable &protoDebug, + panda::pandasm::debuginfo::LocalVariable &debug); +}; +} // panda::proto +#endif diff --git a/merge_abc/src/assemblyFieldProto.cpp b/merge_abc/src/assemblyFieldProto.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e92b8a1f99d5b5922346c9f5b0f7ad8fb02d69d1 --- /dev/null +++ b/merge_abc/src/assemblyFieldProto.cpp @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "assemblyFieldProto.h" + +namespace panda::proto { +void Field::Serialize(const panda::pandasm::Field &field, protoPanda::Field &protoField) +{ + auto *protoType = protoField.mutable_type(); + Type::Serialize(field.type, *protoType); + protoField.set_name(field.name); + auto *protoFieldmeta = protoField.mutable_metadata(); + FieldMetadata::Serialize(*field.metadata, *protoFieldmeta); + protoField.set_lineofdef(field.line_of_def); + protoField.set_wholeline(field.whole_line); + protoField.set_boundleft(field.bound_left); + protoField.set_boundright(field.bound_right); + protoField.set_isdefined(field.is_defined); +} + +void Field::Deserialize(const protoPanda::Field &protoField, panda::pandasm::Field &field, + panda::ArenaAllocator *allocator) +{ + field.type = Type::Deserialize(protoField.type(), allocator); + field.name = protoField.name(); + FieldMetadata::Deserialize(protoField.metadata(), field.metadata, allocator); + field.line_of_def = protoField.lineofdef(); + field.whole_line = protoField.wholeline(); + field.bound_left = protoField.boundleft(); + field.bound_right = protoField.boundright(); + field.is_defined = protoField.isdefined(); +} +} // panda::proto diff --git a/merge_abc/src/assemblyFieldProto.h b/merge_abc/src/assemblyFieldProto.h new file mode 100644 index 0000000000000000000000000000000000000000..81ccab6e555f7daff3e1623ab39a4ab317a11e70 --- /dev/null +++ b/merge_abc/src/assemblyFieldProto.h @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MERGE_ABC_ASSEMBLY_FIELD_H +#define MERGE_ABC_ASSEMBLY_FIELD_H + +#include "assemblyField.pb.h" +#include "assemblyTypeProto.h" +#include "assembly-program.h" +#include "metaProto.h" + +namespace panda::proto { +class Field { +public: + static void Serialize(const panda::pandasm::Field &field, protoPanda::Field &protoField); + static void Deserialize(const protoPanda::Field &protoField, panda::pandasm::Field &field, + panda::ArenaAllocator *allocator); +}; +} // panda::proto +#endif diff --git a/merge_abc/src/assemblyFileLocationProto.cpp b/merge_abc/src/assemblyFileLocationProto.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9f4a0f23bd09b33e9a20c4497a43ff80d3fbb763 --- /dev/null +++ b/merge_abc/src/assemblyFileLocationProto.cpp @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "assemblyFileLocationProto.h" + +namespace panda::proto { +void FileLocation::Serialize(const panda::pandasm::FileLocation &location, protoPanda::FileLocation &protoLocation) +{ + protoLocation.set_wholeline(location.whole_line); + protoLocation.set_boundleft(location.bound_left); + protoLocation.set_boundright(location.bound_right); + protoLocation.set_isdefined(location.is_defined); +} + +void FileLocation::Deserialize(const protoPanda::FileLocation &protoLocation, panda::pandasm::FileLocation &location) +{ + location.whole_line = protoLocation.wholeline(); + location.bound_left = protoLocation.boundleft(); + location.bound_right = protoLocation.boundright(); + location.is_defined = protoLocation.isdefined(); +} +} // panda::proto diff --git a/merge_abc/src/assemblyFileLocationProto.h b/merge_abc/src/assemblyFileLocationProto.h new file mode 100644 index 0000000000000000000000000000000000000000..83afe39022584f2820b3e615a3714085a5b00be2 --- /dev/null +++ b/merge_abc/src/assemblyFileLocationProto.h @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MERGE_ABC_ASSEMBLY_FILE_LOCATION_H +#define MERGE_ABC_ASSEMBLY_FILE_LOCATION_H + +#include "assemblyFileLocation.pb.h" +#include "assembly-program.h" + +namespace panda::proto { +class FileLocation { +public: + static void Serialize(const panda::pandasm::FileLocation &location, protoPanda::FileLocation &protoLocation); + static void Deserialize(const protoPanda::FileLocation &protoLocation, panda::pandasm::FileLocation &location); +}; +} // panda::proto +#endif diff --git a/merge_abc/src/assemblyFunctionProto.cpp b/merge_abc/src/assemblyFunctionProto.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5b3e6387033626342f7b81d95a3e946740a65378 --- /dev/null +++ b/merge_abc/src/assemblyFunctionProto.cpp @@ -0,0 +1,165 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "assemblyFunctionProto.h" + +namespace panda::proto { +void CatchBlock::Serialize(const panda::pandasm::Function::CatchBlock &block, protoPanda::CatchBlock &protoBlock) +{ + protoBlock.set_wholeline(block.whole_line); + protoBlock.set_exceptionrecord(block.exception_record); + protoBlock.set_trybeginlabel(block.try_begin_label); + protoBlock.set_tryendlabel(block.try_end_label); + protoBlock.set_catchbeginlabel(block.catch_begin_label); + protoBlock.set_catchendlabel(block.catch_end_label); +} + +void CatchBlock::Deserialize(const protoPanda::CatchBlock &protoBlock, panda::pandasm::Function::CatchBlock &block) +{ + block.whole_line = protoBlock.wholeline(); + block.exception_record = protoBlock.exceptionrecord(); + block.try_begin_label = protoBlock.trybeginlabel(); + block.try_end_label = protoBlock.tryendlabel(); + block.catch_begin_label = protoBlock.catchbeginlabel(); + block.catch_end_label = protoBlock.catchendlabel(); +} + +void Parameter::Serialize(const panda::pandasm::Function::Parameter ¶m, protoPanda::Parameter &protoParam) +{ + auto *type = protoParam.mutable_type(); + Type::Serialize(param.type, *type); + auto *metadata = protoParam.mutable_metadata(); + ParamMetadata::Serialize(*(param.metadata), *metadata); +} + +void Parameter::Deserialize(const protoPanda::Parameter &protoParam, panda::pandasm::Function::Parameter ¶m, + panda::ArenaAllocator *allocator) +{ + ParamMetadata::Deserialize(protoParam.metadata(), param.metadata, allocator); +} + +void Function::Serialize(const panda::pandasm::Function &function, protoPanda::Function &protoFunction) +{ + protoFunction.set_name(function.name); + protoFunction.set_language(static_cast(function.language)); + + auto *protoFuncMeta = protoFunction.mutable_metadata(); + FunctionMetadata::Serialize(*function.metadata, *protoFuncMeta); + + for (const auto &[name, label] : function.label_table) { + auto *labelMap = protoFunction.add_labeltable(); + labelMap->set_key(name); + auto *protoLabel = labelMap->mutable_value(); + Label::Serialize(label, *protoLabel); + } + + for (const auto &insn : function.ins) { + auto *protoIns = protoFunction.add_ins(); + Ins::Serialize(insn, *protoIns); + } + + for (const auto &debug : function.local_variable_debug) { + auto *protoDebug = protoFunction.add_localvariabledebug(); + LocalVariable::Serialize(debug, *protoDebug); + } + + protoFunction.set_sourcefile(function.source_file); + protoFunction.set_sourcecode(function.source_code); + + for (const auto &block : function.catch_blocks) { + auto *protoBlock = protoFunction.add_catchblocks(); + CatchBlock::Serialize(block, *protoBlock); + } + + protoFunction.set_valueoffirstparam(function.value_of_first_param); + protoFunction.set_regsnum(function.regs_num); + + for (const auto ¶m : function.params) { + auto *protoParam = protoFunction.add_params(); + Parameter::Serialize(param, *protoParam); + } + + protoFunction.set_bodypresence(function.body_presence); + + auto *protoReturnType = protoFunction.mutable_returntype(); + Type::Serialize(function.return_type, *protoReturnType); + + auto *protoBodyLocation = protoFunction.mutable_bodylocation(); + SourceLocation::Serialize(function.body_location, *protoBodyLocation); + + const auto &fileLocation = function.file_location; + if (fileLocation.has_value()) { + auto *protoFileLocation = protoFunction.mutable_filelocation(); + FileLocation::Serialize(fileLocation.value(), *protoFileLocation); + } +} + +void Function::Deserialize(const protoPanda::Function &protoFunction, panda::pandasm::Function &function, + panda::ArenaAllocator *allocator) +{ + FunctionMetadata::Deserialize(protoFunction.metadata(), function.metadata, allocator); + function.label_table.reserve(protoFunction.labeltable_size()); + for (const auto &labelUnit : protoFunction.labeltable()) { + auto &name = labelUnit.key(); + auto &protoLabel = labelUnit.value(); + panda::pandasm::Label label(name); + Label::Deserialize(protoLabel, label); + function.label_table.insert({name, label}); + } + + function.ins.reserve(protoFunction.ins_size()); + for (const auto &protoIns : protoFunction.ins()) { + panda::pandasm::Ins ins; + Ins::Deserialize(protoIns, ins); + function.ins.emplace_back(std::move(ins)); + } + + function.local_variable_debug.reserve(protoFunction.localvariabledebug_size()); + for (const auto &protoLocalVariable : protoFunction.localvariabledebug()) { + panda::pandasm::debuginfo::LocalVariable localVariable; + LocalVariable::Deserialize(protoLocalVariable, localVariable); + function.local_variable_debug.emplace_back(std::move(localVariable)); + } + + function.source_file = protoFunction.sourcefile(); + function.source_code = protoFunction.sourcecode(); + + function.catch_blocks.reserve(protoFunction.catchblocks_size()); + for (const auto &protoCatchBlock : protoFunction.catchblocks()) { + auto *catchBlock = allocator->New(); + CatchBlock::Deserialize(protoCatchBlock, *catchBlock); + function.catch_blocks.emplace_back(std::move(*catchBlock)); + } + + function.value_of_first_param = protoFunction.valueoffirstparam(); + function.regs_num = protoFunction.regsnum(); + + function.params.reserve(protoFunction.params_size()); + for (const auto &protoParam : protoFunction.params()) { + auto ¶mType = Type::Deserialize(protoParam.type(), allocator); + panda::pandasm::Function::Parameter param(paramType, panda::panda_file::SourceLang::ECMASCRIPT); + Parameter::Deserialize(protoParam, param, allocator); + function.params.emplace_back(std::move(param)); + } + + function.body_presence = protoFunction.bodypresence(); + function.return_type = Type::Deserialize(protoFunction.returntype(), allocator); + SourceLocation::Deserialize(protoFunction.bodylocation(), function.body_location); + + if (protoFunction.has_filelocation()) { + FileLocation::Deserialize(protoFunction.filelocation(), function.file_location.value()); + } +} +} // panda::proto diff --git a/merge_abc/src/assemblyFunctionProto.h b/merge_abc/src/assemblyFunctionProto.h new file mode 100644 index 0000000000000000000000000000000000000000..6346cadc52af0de4acdca651092f1691c3580268 --- /dev/null +++ b/merge_abc/src/assemblyFunctionProto.h @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MERGE_ABC_ASSEMBLY_FUNCTION_H +#define MERGE_ABC_ASSEMBLY_FUNCTION_H + +#include "arena_allocator.h" +#include "assemblyDebugProto.h" +#include "assemblyFileLocationProto.h" +#include "assemblyFunction.pb.h" +#include "assemblyInsProto.h" +#include "assemblyLabelProto.h" +#include "assemblyTypeProto.h" +#include "assembly-program.h" +#include "ideHelpersProto.h" +#include "metaProto.h" + +namespace panda::proto { +class CatchBlock { +public: + static void Serialize(const panda::pandasm::Function::CatchBlock &block, protoPanda::CatchBlock &protoBlock); + static void Deserialize(const protoPanda::CatchBlock &protoBlock, panda::pandasm::Function::CatchBlock &block); +}; + +class Parameter { +public: + static void Serialize(const panda::pandasm::Function::Parameter ¶m, protoPanda::Parameter &protoParam); + static void Deserialize(const protoPanda::Parameter &protoParam, panda::pandasm::Function::Parameter ¶m, + panda::ArenaAllocator *allocator_); +}; + +class Function { +public: + static void Serialize(const panda::pandasm::Function &function, protoPanda::Function &protoFunction); + static void Deserialize(const protoPanda::Function &protoFunction, panda::pandasm::Function &function, + panda::ArenaAllocator *allocator_); +}; +} // panda::proto +#endif diff --git a/merge_abc/src/assemblyInsProto.cpp b/merge_abc/src/assemblyInsProto.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c1016ef04aacf1d56943272fe99bbc222e07e1ce --- /dev/null +++ b/merge_abc/src/assemblyInsProto.cpp @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "assemblyInsProto.h" + +namespace panda::proto { +void Ins::Serialize(const panda::pandasm::Ins &insn, protoPanda::Ins &protoInsn) +{ + protoInsn.set_opcode(static_cast(insn.opcode)); + for (const auto ® : insn.regs) { + protoInsn.add_regs(static_cast(reg)); + } + for (const auto &str : insn.ids) { + protoInsn.add_ids(str); + } + for (const auto &imm : insn.imms) { + auto *protoImm = protoInsn.add_imms(); + switch (static_cast(imm.index() + 1)) { // 1: enum TypeCase start from 1 + case protoPanda::Ins_IType::kValueInt: + protoImm->set_valueint(std::get(imm)); + break; + case protoPanda::Ins_IType::kValueDouble: + protoImm->set_valuedouble(std::get(imm)); + break; + default: + UNREACHABLE(); + } + } + protoInsn.set_label(insn.label); + protoInsn.set_setlabelval(insn.set_label); + auto *protoDebug = protoInsn.mutable_insdebug(); + DebuginfoIns::Serialize(insn.ins_debug, *protoDebug); +} + +void Ins::Deserialize(const protoPanda::Ins &protoInsn, panda::pandasm::Ins &insn) +{ + insn.opcode = static_cast(protoInsn.opcode()); + insn.regs.reserve(protoInsn.regs_size()); + for (const auto &protoReg : protoInsn.regs()) { + insn.regs.push_back(static_cast(protoReg)); + } + insn.ids.reserve(protoInsn.ids_size()); + for (const auto &protoId : protoInsn.ids()) { + insn.ids.push_back(protoId); + } + insn.imms.reserve(protoInsn.imms_size()); + for (const auto &protoImm : protoInsn.imms()) { + switch (protoImm.type_case()) { + case protoPanda::Ins_IType::kValueInt: { + insn.imms.push_back(protoImm.valueint()); + break; + } + case protoPanda::Ins_IType::kValueDouble: { + insn.imms.push_back(protoImm.valuedouble()); + break; + } + default: + UNREACHABLE(); + } + } + insn.label = protoInsn.label(); + insn.set_label = protoInsn.setlabelval(); + const protoPanda::DebuginfoIns &protoDebugInfoIns = protoInsn.insdebug(); + DebuginfoIns::Deserialize(protoDebugInfoIns, insn.ins_debug); +} +} // panda::proto diff --git a/merge_abc/src/assemblyInsProto.h b/merge_abc/src/assemblyInsProto.h new file mode 100644 index 0000000000000000000000000000000000000000..05053d5dec5b0aae862d7c8e9235cb3877de7734 --- /dev/null +++ b/merge_abc/src/assemblyInsProto.h @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MERGE_ABC_ASSEMBLY_INS_H +#define MERGE_ABC_ASSEMBLY_INS_H + +#include "assemblyDebugProto.h" +#include "assemblyIns.pb.h" +#include "assembly-program.h" + +namespace panda::proto { +class Ins { +public: + static void Serialize(const panda::pandasm::Ins &insn, protoPanda::Ins &protoInsn); + static void Deserialize(const protoPanda::Ins &protoInsn, panda::pandasm::Ins &insn); +}; +} // panda::proto +#endif diff --git a/merge_abc/src/assemblyLabelProto.cpp b/merge_abc/src/assemblyLabelProto.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f355a80490d50fe5e558267315b95a726058d764 --- /dev/null +++ b/merge_abc/src/assemblyLabelProto.cpp @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "assemblyLabelProto.h" + +namespace panda::proto { +void Label::Serialize(const panda::pandasm::Label &label, protoPanda::Label &protoLabel) +{ + protoLabel.set_name(label.name); + const auto &fileLocation = label.file_location; + if (fileLocation.has_value()) { + auto *protoLocation = protoLabel.mutable_filelocation(); + FileLocation::Serialize(fileLocation.value(), *protoLocation); + } +} + +void Label::Deserialize(const protoPanda::Label &protoLabel, panda::pandasm::Label &label) +{ + label.name = protoLabel.name(); + if (protoLabel.has_filelocation()) { + protoPanda::FileLocation protoLocation = protoLabel.filelocation(); + FileLocation::Deserialize(protoLocation, label.file_location.value()); + } +} +} // panda::proto diff --git a/merge_abc/src/assemblyLabelProto.h b/merge_abc/src/assemblyLabelProto.h new file mode 100644 index 0000000000000000000000000000000000000000..e2c44756ac6483396e5706f6747fbbd870122025 --- /dev/null +++ b/merge_abc/src/assemblyLabelProto.h @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MERGE_ABC_ASSEMBLY_LABEL_H +#define MERGE_ABC_ASSEMBLY_LABEL_H + +#include "assemblyFileLocationProto.h" +#include "assemblyLabel.pb.h" +#include "assembly-program.h" + +namespace panda::proto { +class Label { +public: + static void Serialize(const panda::pandasm::Label &label, protoPanda::Label &protoLabel); + static void Deserialize(const protoPanda::Label &protoLabel, panda::pandasm::Label &label); +}; +} // panda::proto +#endif diff --git a/merge_abc/src/assemblyLiteralsProto.cpp b/merge_abc/src/assemblyLiteralsProto.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1e4542d919a5366601b64f32a73097d00e6bb216 --- /dev/null +++ b/merge_abc/src/assemblyLiteralsProto.cpp @@ -0,0 +1,132 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "assemblyLiteralsProto.h" + +namespace panda::proto { +void VariantValue::Serialize(const LiteralValueType &value, protoPanda::VariantValue &protoValue) +{ + const auto type = static_cast(value.index()); + protoValue.set_type(type); + switch (type) { + case protoPanda::VariantValue_VariantValueType_BOOL: { + protoValue.set_valueint(static_cast(std::get(value))); + return; + } + case protoPanda::VariantValue_VariantValueType_U8: { + protoValue.set_valueint(static_cast(std::get(value))); + return; + } + case protoPanda::VariantValue_VariantValueType_U16: { + protoValue.set_valueint(static_cast(std::get(value))); + return; + } + case protoPanda::VariantValue_VariantValueType_U32: { + protoValue.set_valueint(static_cast(std::get(value))); + return; + } + case protoPanda::VariantValue_VariantValueType_U64: { + protoValue.set_valueint(std::get(value)); + return; + } + case protoPanda::VariantValue_VariantValueType_F32: { + protoValue.set_valuefloat(std::get(value)); + return; + } + case protoPanda::VariantValue_VariantValueType_F64: { + protoValue.set_valuedouble(std::get(value)); + return; + } + case protoPanda::VariantValue_VariantValueType_STRING: { + protoValue.set_valuestr(std::get(value)); + return; + } + default: + UNREACHABLE(); + } +} + +void VariantValue::Deserialize(const protoPanda::VariantValue &protoValue, LiteralValueType &value) +{ + auto type = protoValue.type(); + switch (type) { + case protoPanda::VariantValue_VariantValueType_BOOL: { + value = static_cast(protoValue.valueint()); + return; + } + case protoPanda::VariantValue_VariantValueType_U8: { + value = static_cast(protoValue.valueint()); + return; + } + case protoPanda::VariantValue_VariantValueType_U16: { + value = static_cast(protoValue.valueint()); + return; + } + case protoPanda::VariantValue_VariantValueType_U32: { + value = static_cast(protoValue.valueint()); + return; + } + case protoPanda::VariantValue_VariantValueType_U64: { + value = static_cast(protoValue.valueint()); + return; + } + case protoPanda::VariantValue_VariantValueType_F32: { + value = protoValue.valuefloat(); + return; + } + case protoPanda::VariantValue_VariantValueType_F64: { + value = protoValue.valuedouble(); + return; + } + case protoPanda::VariantValue_VariantValueType_STRING: { + value = protoValue.valuestr(); + return; + } + default: + UNREACHABLE(); + } +} + +void LiteralArray::Serialize(const panda::pandasm::LiteralArray &array, protoPanda::LiteralArray &protoArray) +{ + for (const auto &literal : array.literals_) { + auto *protoLiteral = protoArray.add_literals(); + Literal::Serialize(literal, *protoLiteral); + } +} + +void LiteralArray::Deserialize(const protoPanda::LiteralArray &protoArray, panda::pandasm::LiteralArray &array) +{ + array.literals_.reserve(protoArray.literals_size()); + for (const auto &protoLiteral : protoArray.literals()) { + panda::pandasm::LiteralArray::Literal literal; + Literal::Deserialize(protoLiteral, literal); + array.literals_.emplace_back(literal); + } +} + +void Literal::Serialize(const panda::pandasm::LiteralArray::Literal &literal, protoPanda::Literal &protoLiteral) +{ + protoLiteral.set_tag(static_cast(literal.tag_)); + auto *value = protoLiteral.mutable_value(); + VariantValue::Serialize(literal.value_, *value); +} + +void Literal::Deserialize(const protoPanda::Literal &protoLiteral, panda::pandasm::LiteralArray::Literal &literal) +{ + literal.tag_ = static_cast(protoLiteral.tag()); + VariantValue::Deserialize(protoLiteral.value(), literal.value_); +} +} // panda::proto diff --git a/merge_abc/src/assemblyLiteralsProto.h b/merge_abc/src/assemblyLiteralsProto.h new file mode 100644 index 0000000000000000000000000000000000000000..172a0c3a6956adf122ee8ebd241e5a84eeded1e0 --- /dev/null +++ b/merge_abc/src/assemblyLiteralsProto.h @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MERGE_ABC_ASSEMBLY_LITERALS_H +#define MERGE_ABC_ASSEMBLY_LITERALS_H + +#include "assemblyLiterals.pb.h" +#include "assembly-program.h" + +namespace panda::proto { +class VariantValue { +public: + using LiteralValueType = std::variant; + static void Serialize(const LiteralValueType &value, protoPanda::VariantValue &protoValue); + static void Deserialize(const protoPanda::VariantValue &protoValue, LiteralValueType &value); +}; + +class LiteralArray { +public: + static void Serialize(const panda::pandasm::LiteralArray &array, protoPanda::LiteralArray &protoArray); + static void Deserialize(const protoPanda::LiteralArray &protoArray, panda::pandasm::LiteralArray &array); +}; + +class Literal { +public: + static void Serialize(const panda::pandasm::LiteralArray::Literal &literal, protoPanda::Literal &protoLiteral); + static void Deserialize(const protoPanda::Literal &protoLiteral, panda::pandasm::LiteralArray::Literal &literal); +}; +} // panda::proto +#endif diff --git a/merge_abc/src/assemblyProgramProto.cpp b/merge_abc/src/assemblyProgramProto.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e8f4ad0806291696232d20e9e889befe8aa5e82 --- /dev/null +++ b/merge_abc/src/assemblyProgramProto.cpp @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "assemblyProgramProto.h" + +namespace panda::proto { +void Program::Serialize(const panda::pandasm::Program &program, protoPanda::Program &protoProgram) +{ + protoProgram.set_lang(static_cast(program.lang)); + + for (const auto &[name, record] : program.record_table) { + auto *recordMap = protoProgram.add_recordtable(); + recordMap->set_key(name); + auto *protoRecord = recordMap->mutable_value(); + Record::Serialize(record, *protoRecord); + } + + for (const auto &[name, func] : program.function_table) { + auto *functionMap = protoProgram.add_functiontable(); + functionMap->set_key(name); + auto *protoFunc = functionMap->mutable_value(); + Function::Serialize(func, *protoFunc); + } + + for (const auto &[name, array] : program.literalarray_table) { + auto *literalarrayMap = protoProgram.add_literalarraytable(); + literalarrayMap->set_key(name); + auto *protoArray = literalarrayMap->mutable_value(); + LiteralArray::Serialize(array, *protoArray); + } + for (const auto &str : program.strings) { + protoProgram.add_strings(str); + } + for (const auto &type : program.array_types) { + auto *protoType = protoProgram.add_arraytypes(); + Type::Serialize(type, *protoType); + } +} + +void Program::Deserialize(const protoPanda::Program &protoProgram, panda::pandasm::Program &program, + panda::ArenaAllocator *allocator) +{ + program.lang = static_cast(protoProgram.lang()); + + program.record_table.reserve(protoProgram.recordtable_size()); + for (const auto &recordUnit : protoProgram.recordtable()) { + auto &name = recordUnit.key(); + auto &protoRecord = recordUnit.value(); + auto record = panda::pandasm::Record(protoRecord.name(), + static_cast(protoRecord.language())); + Record::Deserialize(protoRecord, record, allocator); + program.record_table.insert({name, std::move(record)}); + } + + program.function_table.reserve(protoProgram.functiontable_size()); + for (const auto &functionUnit : protoProgram.functiontable()) { + auto &name = functionUnit.key(); + auto &protoFunction = functionUnit.value(); + auto *function = allocator->New(protoFunction.name(), + static_cast(protoFunction.language())); + Function::Deserialize(protoFunction, *function, allocator); + program.function_table.insert({name, std::move(*function)}); + } + + for (const auto &literalUnit : protoProgram.literalarraytable()) { + auto &name = literalUnit.key(); + auto &protoLiteralArray = literalUnit.value(); + panda::pandasm::LiteralArray literalArray; + LiteralArray::Deserialize(protoLiteralArray, literalArray); + program.literalarray_table.insert({name, std::move(literalArray)}); + } + + program.strings.reserve(protoProgram.strings_size()); + for (const auto &protoString : protoProgram.strings()) { + program.strings.insert(protoString); + } + + program.array_types.reserve(protoProgram.arraytypes_size()); + for (const auto &protoArrayType : protoProgram.arraytypes()) { + auto &arrayType = Type::Deserialize(protoArrayType, allocator); + program.array_types.insert(std::move(arrayType)); + } +} +} // panda::proto diff --git a/merge_abc/src/assemblyProgramProto.h b/merge_abc/src/assemblyProgramProto.h new file mode 100644 index 0000000000000000000000000000000000000000..6b5d3e4c1382278842a4937ecd8cfdfe5812648a --- /dev/null +++ b/merge_abc/src/assemblyProgramProto.h @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MERGE_ABC_ASSEMBLY_PROGRAM_H +#define MERGE_ABC_ASSEMBLY_PROGRAM_H + +#include "arena_allocator.h" +#include "assemblyFunctionProto.h" +#include "assemblyLiteralsProto.h" +#include "assemblyProgram.pb.h" +#include "assemblyRecordProto.h" +#include "assembly-program.h" + +namespace panda::proto { +class Program { +public: + static void Serialize(const panda::pandasm::Program &program, protoPanda::Program &protoProgram); + static void Deserialize(const protoPanda::Program &protoProgram, panda::pandasm::Program &program, + panda::ArenaAllocator *allocator); +}; +} // panda::proto +#endif diff --git a/merge_abc/src/assemblyRecordProto.cpp b/merge_abc/src/assemblyRecordProto.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cfd7d34d44076f92dc9c976d744e2f2a04a18040 --- /dev/null +++ b/merge_abc/src/assemblyRecordProto.cpp @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "assemblyRecordProto.h" + +namespace panda::proto { +void Record::Serialize(const panda::pandasm::Record &record, protoPanda::Record &protoRecord) +{ + protoRecord.set_name(record.name); + protoRecord.set_conflict(record.conflict); + protoRecord.set_language(static_cast(record.language)); + auto *proto_record_meta = protoRecord.mutable_metadata(); + RecordMetadata::Serialize(*record.metadata, *proto_record_meta); + + for (const auto &field : record.field_list) { + auto *proto_field = protoRecord.add_fieldlist(); + Field::Serialize(field, *proto_field); + } + + protoRecord.set_paramsnum(record.params_num); + protoRecord.set_bodypresence(record.body_presence); + protoRecord.set_sourcefile(record.source_file); + + const auto &location = record.file_location; + if (location.has_value()) { + auto *proto_location = protoRecord.mutable_filelocation(); + FileLocation::Serialize(location.value(), *proto_location); + } +} + +void Record::Deserialize(const protoPanda::Record &protoRecord, panda::pandasm::Record &record, + panda::ArenaAllocator *allocator) +{ + record.conflict = protoRecord.conflict(); + RecordMetadata::Deserialize(protoRecord.metadata(), record.metadata, allocator); + record.field_list.reserve(protoRecord.fieldlist_size()); + for (const auto &protoField : protoRecord.fieldlist()) { + auto recordField = panda::pandasm::Field(panda::panda_file::SourceLang::ECMASCRIPT); + Field::Deserialize(protoField, recordField, allocator); + record.field_list.emplace_back(std::move(recordField)); + } + record.params_num = protoRecord.paramsnum(); + record.body_presence = protoRecord.bodypresence(); + record.source_file = protoRecord.sourcefile(); + if (protoRecord.has_filelocation()) { + const auto &protoLocation = protoRecord.filelocation(); + FileLocation::Deserialize(protoLocation, record.file_location.value()); + } +} +} // panda::proto diff --git a/merge_abc/src/assemblyRecordProto.h b/merge_abc/src/assemblyRecordProto.h new file mode 100644 index 0000000000000000000000000000000000000000..8a73e058c39ef68ad8cb702b697c81ddff451a83 --- /dev/null +++ b/merge_abc/src/assemblyRecordProto.h @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MERGE_ABC_ASSEMBLY_RECORD_H +#define MERGE_ABC_ASSEMBLY_RECORD_H + +#include "assemblyFieldProto.h" +#include "assemblyFunctionProto.h" +#include "assemblyRecord.pb.h" +#include "assembly-program.h" +#include "metaProto.h" + +namespace panda::proto { +class Record { +public: + static void Serialize(const panda::pandasm::Record &record, protoPanda::Record &protoRecord); + static void Deserialize(const protoPanda::Record &protoRecord, panda::pandasm::Record &record, + panda::ArenaAllocator *allocator); +}; +} // panda::proto +#endif diff --git a/merge_abc/src/assemblyTypeProto.cpp b/merge_abc/src/assemblyTypeProto.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eea55eb4b4c970fa4e83e53c4f572c48c144a736 --- /dev/null +++ b/merge_abc/src/assemblyTypeProto.cpp @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "assemblyTypeProto.h" + +namespace panda::proto { +void Type::Serialize(const panda::pandasm::Type type, protoPanda::Type &protoType) +{ + protoType.set_componentname(type.GetComponentName()); + protoType.set_rank(type.GetRank()); + protoType.set_name(type.GetName()); + protoType.set_typeid_(static_cast(type.GetId())); +} + +panda::pandasm::Type &Type::Deserialize(const protoPanda::Type &protoType, + panda::ArenaAllocator *allocator) +{ + auto *type = allocator->New(protoType.componentname(), protoType.rank()); + return *type; +} +} // panda::proto diff --git a/merge_abc/src/assemblyTypeProto.h b/merge_abc/src/assemblyTypeProto.h new file mode 100644 index 0000000000000000000000000000000000000000..636ceea5d4390636d119f758c464b12fb21eb846 --- /dev/null +++ b/merge_abc/src/assemblyTypeProto.h @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MERGE_ABC_ASSEMBLY_TYPE_H +#define MERGE_ABC_ASSEMBLY_TYPE_H + +#include "arena_allocator.h" +#include "assemblyType.pb.h" +#include "assembly-program.h" + +namespace panda::proto { +class Type { +public: + static void Serialize(const panda::pandasm::Type type, protoPanda::Type &protoType); + static panda::pandasm::Type &Deserialize(const protoPanda::Type &protoType, + panda::ArenaAllocator *allocator); +}; +} // panda::proto +#endif diff --git a/merge_abc/src/compositeProgramProto.cpp b/merge_abc/src/compositeProgramProto.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2fd536387ce7aa4121668216aa7a5e5bb2e467a0 --- /dev/null +++ b/merge_abc/src/compositeProgramProto.cpp @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "compositeProgramProto.h" + +namespace panda::proto { +void CompositeProgram::Serialize( + const std::unordered_map &compositeProgramMap, bool isDebug, + protoPanda::CompositeProgram &protoCompositeProgram) +{ + for (const auto &[fileName, programCache] : compositeProgramMap) { + auto *protoProgramcache = protoCompositeProgram.add_programcache(); + protoProgramcache->set_filename(fileName); + protoProgramcache->set_hashcode(programCache->hashCode); + auto *protoProgram = protoProgramcache->mutable_program(); + Program::Serialize(*(programCache->program), *protoProgram); + } + protoCompositeProgram.set_isdebug(isDebug); +} + +void CompositeProgram::Deserialize(const protoPanda::CompositeProgram &protoCompositeProgram, + std::unordered_map &compositeProgramMap, + panda::ArenaAllocator *allocator) +{ + compositeProgramMap.reserve(protoCompositeProgram.programcache_size()); + for (const auto &protoProgramcache : protoCompositeProgram.programcache()) { + auto &fileName = protoProgramcache.filename(); + auto hashCode = protoProgramcache.hashcode(); + auto &protoProgram = protoProgramcache.program(); + auto *program = allocator->New(); + Program::Deserialize(protoProgram, *program, allocator); + auto *programCache = allocator->New(hashCode, program); + compositeProgramMap.insert({fileName, programCache}); + } +} +} // namespace panda::proto diff --git a/merge_abc/src/compositeProgramProto.h b/merge_abc/src/compositeProgramProto.h new file mode 100644 index 0000000000000000000000000000000000000000..8f72c554722753c6138419a99eb51ea7cc20fba8 --- /dev/null +++ b/merge_abc/src/compositeProgramProto.h @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MERGE_ABC_BUILD_COMPOSITE_PROGRAM_H +#define MERGE_ABC_BUILD_COMPOSITE_PROGRAM_H + +#include "assemblyProgramProto.h" +#include "compositeProgram.pb.h" +#include "programCache.h" + +namespace panda::proto { +class CompositeProgram { +public: + static void Serialize( + const std::unordered_map &compositeProgramMap, bool isDebug, + protoPanda::CompositeProgram &protoCompositeProgram); + static void Deserialize(const protoPanda::CompositeProgram &protoCompositeProgram, + std::unordered_map &compositeProgramMap, + panda::ArenaAllocator *allocator); +}; +} // panda::proto +#endif diff --git a/merge_abc/src/ideHelpersProto.cpp b/merge_abc/src/ideHelpersProto.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d4d5d7dbb1feaef8758c0213771845e401d88b31 --- /dev/null +++ b/merge_abc/src/ideHelpersProto.cpp @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ideHelpersProto.h" + +namespace panda::proto { +void SourceLocation::Serialize(const panda::pandasm::SourceLocation &location, + protoPanda::SourceLocation &protoLocation) +{ + auto *protoBegin = protoLocation.mutable_begin(); + SourcePosition::Serialize(location.begin, *protoBegin); + auto *protoEnd = protoLocation.mutable_end(); + SourcePosition::Serialize(location.end, *protoEnd); +} + +void SourceLocation::Deserialize(const protoPanda::SourceLocation &protoLocation, + panda::pandasm::SourceLocation &location) +{ + if (protoLocation.has_begin()) { + SourcePosition::Deserialize(protoLocation.begin(), location.begin); + } + if (protoLocation.has_end()) { + SourcePosition::Deserialize(protoLocation.end(), location.end); + } +} + +void SourcePosition::Serialize(const panda::pandasm::SourcePosition &position, + protoPanda::SourcePosition &protoPosition) +{ + protoPosition.set_line(position.line); + protoPosition.set_column(position.column); +} + +void SourcePosition::Deserialize(const protoPanda::SourcePosition &protoPosition, + panda::pandasm::SourcePosition &position) +{ + position.line = protoPosition.line(); + position.column = protoPosition.column(); +} +} // panda::proto diff --git a/merge_abc/src/ideHelpersProto.h b/merge_abc/src/ideHelpersProto.h new file mode 100644 index 0000000000000000000000000000000000000000..a6596b3c8f8df70033c18227eec84394811bf440 --- /dev/null +++ b/merge_abc/src/ideHelpersProto.h @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MERGE_ABC_IDE_HELPERS_H +#define MERGE_ABC_IDE_HELPERS_H + +#include "assembly-program.h" +#include "ideHelpers.pb.h" + +namespace panda::proto { +class SourceLocation { +public: + static void Serialize(const panda::pandasm::SourceLocation &location, + protoPanda::SourceLocation &protoLocation); + static void Deserialize(const protoPanda::SourceLocation &protoLocation, panda::pandasm::SourceLocation &location); +}; + +class SourcePosition { +public: + static void Serialize(const panda::pandasm::SourcePosition &position, + protoPanda::SourcePosition &protoPosition); + static void Deserialize(const protoPanda::SourcePosition &protoPosition, panda::pandasm::SourcePosition &position); +}; +} // panda::proto +#endif diff --git a/merge_abc/src/main.cpp b/merge_abc/src/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..00c860a4e79e57f2a6cc3dbe154e6a15296cc380 --- /dev/null +++ b/merge_abc/src/main.cpp @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "arena_allocator.h" +#include "mergeProgram.h" +#include "options.h" +#include "protobufSnapshotGenerator.h" + +#include +#include + +namespace panda::proto { +using mem::MemConfig; + +class ProtoMemManager { +public: + explicit ProtoMemManager() + { + constexpr auto COMPILER_SIZE = 512_MB; + + MemConfig::Initialize(0, 0, COMPILER_SIZE, 0); + PoolManager::Initialize(PoolType::MMAP); + } + + NO_COPY_SEMANTIC(ProtoMemManager); + NO_MOVE_SEMANTIC(ProtoMemManager); + + ~ProtoMemManager() + { + PoolManager::Finalize(); + MemConfig::Finalize(); + } +}; + +int Run(int argc, const char **argv) +{ + auto options = std::make_unique(); + if (!options->Parse(argc, argv)) { + std::cerr << options->ErrorMsg() << std::endl; + return 1; + } + + std::string protoPathInput = options->protoPathInput(); + std::string protoBinSuffix = options->protoBinSuffix(); + std::string outputFilePath = options->outputFilePath(); + if (outputFilePath.empty()) { + outputFilePath = panda::os::file::File::GetExecutablePath().Value(); + } + + std::vector protoFiles; + if (!MergeProgram::CollectProtoFiles(protoPathInput, protoBinSuffix, protoFiles)) { + return 1; + } + + panda::ArenaAllocator allocator(panda::SpaceType::SPACE_TYPE_COMPILER, nullptr, true); + + std::vector programs; + programs.reserve(protoFiles.size()); + for(size_t i = 0; i < protoFiles.size(); i++) { + auto *prog = allocator.New(); + programs.emplace_back(prog); + } + + size_t idx = 0; + for (auto &protoFile : protoFiles) { + proto::ProtobufSnapshotGenerator::GenerateProgram(protoFile, *(programs[idx++]), &allocator); + } + + std::string outputFileName = outputFilePath.append(panda::os::file::File::GetPathDelim()). + append(options->outputFileName()); + if (!panda::pandasm::AsmEmitter::EmitPrograms(outputFileName, programs, true)) { + return 1; + } + + return 0; +} +} // namespace panda::proto + +int main(int argc, const char **argv) +{ + panda::proto::ProtoMemManager mm; + return panda::proto::Run(argc, argv); +} diff --git a/merge_abc/src/mergeProgram.cpp b/merge_abc/src/mergeProgram.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0254e24d195f9c9b594602718b5c9e17d3e52498 --- /dev/null +++ b/merge_abc/src/mergeProgram.cpp @@ -0,0 +1,163 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "assembler/assembly-function.h" +#include "libpandafile/literal_data_accessor.h" +#include "os/file.h" +#include "options.h" + +#include "mergeProgram.h" + +#if defined(PANDA_TARGET_WINDOWS) +#include +#else +#include +#endif + +#include + +namespace panda::proto { +bool MergeProgram::GetProtoFiles(const std::string &protoBinPath, const std::string &protoBinSuffix, + std::vector &directoryFiles) +{ +#if PANDA_TARGET_WINDOWS + int handle = 0; + struct _finddata_t fileInfo; + std::string path; + if ((handle = _findfirst(path.assign(protoBinPath).append("\\*").c_str(), &fileInfo)) == -1) { + return false; + } + do { + if (fileInfo.attrib & _A_SUBDIR) { + if((!strncmp(fileInfo.name, ".", 1)) || (!strncmp(fileInfo.name, "..", 2))) { + continue; + } + if (!GetProtoFiles(path.assign(protoBinPath).append("\\").append(fileInfo.name), protoBinSuffix, + directoryFiles)) { + _findclose(handle); + return false; + } + } else { + std::string fileName(fileInfo.name); + if (fileName.substr(fileName.find_last_of(".") + 1).compare(protoBinSuffix) == 0) { + directoryFiles.emplace_back(path.assign(protoBinPath).append("\\").append(fileName)); + } + } + } while (_findnext(handle, &fileInfo) == 0); + _findclose(handle); +#elif PANDA_TARGET_UNIX + DIR *protoBin = opendir(protoBinPath.c_str()); + if (protoBin == nullptr) { + return false; + } + dirent *dir = nullptr; + std::string pathPrefix = protoBinPath + "/"; + while ((dir = readdir(protoBin)) != nullptr) { + if((!strncmp(dir->d_name, ".", 1)) || (!strncmp(dir->d_name, "..", 2))) { + continue; + } + if (dir->d_type == DT_DIR) { + std::string subDirName = pathPrefix + dir->d_name; + if (!GetProtoFiles(subDirName, protoBinSuffix, directoryFiles)) { + closedir(protoBin); + return false; + } + } else { + std::string fileName = pathPrefix + dir->d_name; + if (fileName.substr(fileName.find_last_of(".") + 1).compare(protoBinSuffix) == 0) { + directoryFiles.emplace_back(fileName); + } + } + } + closedir(protoBin); +#endif + return true; +} + +bool MergeProgram::AppendProtoFiles(const std::string &filePath, const std::string &protoBinSuffix, + std::vector &protoFiles) +{ + auto inputAbs = panda::os::file::File::GetAbsolutePath(filePath); + if (!inputAbs) { + std::cerr << "Failed to open: " << filePath << std::endl; + return false; + } + + auto fPath = inputAbs.Value(); + if (panda::os::file::File::IsRegularFile(fPath)) { + if (filePath.substr(filePath.find_last_of(".") + 1).compare(protoBinSuffix) == 0) { + protoFiles.emplace_back(fPath); + } + } else if (panda::os::file::File::IsDirectory(fPath)) { + std::vector directoryFiles; + if (!GetProtoFiles(fPath, protoBinSuffix, directoryFiles)) { + return false; + } + protoFiles.insert(protoFiles.end(), directoryFiles.begin(), directoryFiles.end()); + } else { + std::cerr << "Input must be either a regular file or directory" << std::endl; + return false; + } + + return true; +} + +bool MergeProgram::CollectProtoFiles(std::string &input, const std::string &protoBinSuffix, + std::vector &protoFiles) +{ + constexpr const char DOGGY = '@'; + std::vector inputs; + bool isList = false; + + if (input[0] == DOGGY) { + input.erase(input.begin() + 0); + isList = true; + } + + auto inputAbs = panda::os::file::File::GetAbsolutePath(input); + if (!inputAbs) { + std::cerr << "Failed to open: " << input << std::endl; + return false; + } + if (isList) { + std::ifstream in(inputAbs.Value()); + std::string line; + constexpr const char CARRIAGE = '\r'; + while (getline(in, line)) { + // erase front spaces + line.erase(line.begin(), + std::find_if(line.begin(), line.end(), [](unsigned char ch) { return std::isspace(ch) == 0; })); + // erase carrige return symbol (Windows workaround) + line.erase(std::find_if(line.rbegin(), line.rend(), [](unsigned char ch) { return ch != CARRIAGE; }).base(), + line.end()); + if (!line.empty()) { + inputs.push_back(line); + } + } + in.close(); + } else { + inputs.push_back(inputAbs.Value()); + } + + protoFiles.reserve(inputs.size()); + for (auto &filePath : inputs) { + if (!AppendProtoFiles(filePath, protoBinSuffix, protoFiles)) { + return false; + } + } + + return true; +} +} // namespace panda::proto diff --git a/merge_abc/src/mergeProgram.h b/merge_abc/src/mergeProgram.h new file mode 100644 index 0000000000000000000000000000000000000000..f730db33e276aab603cd12f9589e71eddc89b4f3 --- /dev/null +++ b/merge_abc/src/mergeProgram.h @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MERGE_ABC_MERGE_PROGRAM_H +#define MERGE_ABC_MERGE_PROGRAM_H + +#include "assembly-function.h" +#include "assembly-ins.h" +#include "assembly-program.h" + +namespace panda::proto { +class MergeProgram { +public: + static bool GetProtoFiles(const std::string &protoBinPath, const std::string &protoBinSuffix, + std::vector &directoryFiles); + static bool AppendProtoFiles(const std::string &filePath, const std::string &protoBinSuffix, + std::vector &protoFiles); + static bool CollectProtoFiles(std::string &input, const std::string &protoBinSuffix, + std::vector &protoFiles); +}; +} // namespace panda::proto +#endif diff --git a/merge_abc/src/metaProto.cpp b/merge_abc/src/metaProto.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fd70b2640699508a349ad681bc8c287e3f120972 --- /dev/null +++ b/merge_abc/src/metaProto.cpp @@ -0,0 +1,169 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "metaProto.h" + +namespace panda::proto { +void RecordMetadata::Serialize(const panda::pandasm::RecordMetadata &meta, protoPanda::RecordMetadata &protoMeta) +{ + auto *protoItemmetadata = protoMeta.mutable_father(); + ItemMetadata::Serialize(static_cast(meta), *protoItemmetadata); +} + +void RecordMetadata::Deserialize(const protoPanda::RecordMetadata &protoMeta, + std::unique_ptr &meta, + panda::ArenaAllocator *allocator) +{ + auto &protoItemMetadata = protoMeta.father(); + ItemMetadata::Deserialize(protoItemMetadata, *meta); + + auto &protoAnnoMetadata = protoItemMetadata.father(); + AnnotationMetadata::Deserialize(protoAnnoMetadata, *meta, allocator); + + auto &protoMetadata = protoAnnoMetadata.father(); + Metadata::Deserialize(protoMetadata, *meta); +} + +void FunctionMetadata::Serialize(const panda::pandasm::FunctionMetadata &meta, + protoPanda::FunctionMetadata &protoMeta) +{ + auto *protoItemmetadata = protoMeta.mutable_father(); + ItemMetadata::Serialize(static_cast(meta), *protoItemmetadata); +} + +void FunctionMetadata::Deserialize(const protoPanda::FunctionMetadata &protoMeta, + std::unique_ptr &meta, + panda::ArenaAllocator *allocator) +{ + auto &protoItemMetadata = protoMeta.father(); + ItemMetadata::Deserialize(protoItemMetadata, *meta); + + auto &protoAnnoMetadata = protoItemMetadata.father(); + AnnotationMetadata::Deserialize(protoAnnoMetadata, *meta, allocator); + + auto &protoMetadata = protoAnnoMetadata.father(); + Metadata::Deserialize(protoMetadata, *meta); +} + +void FieldMetadata::Serialize(const panda::pandasm::FieldMetadata &meta, protoPanda::FieldMetadata &protoMeta) +{ + auto *protoItemmetadata = protoMeta.mutable_father(); + ItemMetadata::Serialize(meta, *protoItemmetadata); + auto *protoType = protoMeta.mutable_fieldtype(); + Type::Serialize(meta.GetFieldType(), *protoType); + const auto val = meta.GetValue(); + if (val.has_value()) { + auto *protoValue = protoMeta.mutable_value(); + ScalarValue::Serialize(val.value(), *protoValue); + } +} + +void FieldMetadata::Deserialize(const protoPanda::FieldMetadata &protoMeta, + std::unique_ptr &meta, + panda::ArenaAllocator *allocator) +{ + auto &protoItemMetadata = protoMeta.father(); + ItemMetadata::Deserialize(protoItemMetadata, *meta); + auto &protoAnnoMetadata = protoItemMetadata.father(); + AnnotationMetadata::Deserialize(protoAnnoMetadata, *meta, allocator); + auto &protoMetadata = protoAnnoMetadata.father(); + Metadata::Deserialize(protoMetadata, *meta); + + auto &fieldType = Type::Deserialize(protoMeta.fieldtype(), allocator); + meta->SetFieldType(fieldType); + ScalarValue scalarValue; + if (protoMeta.has_value()) { + auto scalar = scalarValue.Deserialize(protoMeta.value(), allocator); + meta->SetValue(scalar); + } +} + +void ParamMetadata::Serialize(const panda::pandasm::ParamMetadata &meta, protoPanda::ParamMetadata &protoMeta) +{ + auto *protoAnnometadata = protoMeta.mutable_father(); + AnnotationMetadata::Serialize(static_cast(meta), *protoAnnometadata); +} + +void ParamMetadata::Deserialize(const protoPanda::ParamMetadata &protoMeta, + std::unique_ptr &meta, + panda::ArenaAllocator *allocator) +{ + auto &protoAnnoMetadata = protoMeta.father(); + AnnotationMetadata::Deserialize(protoAnnoMetadata, *meta, allocator); +} + +void ItemMetadata::Serialize(const panda::pandasm::ItemMetadata &meta, protoPanda::ItemMetadata &protoMeta) +{ + auto *protoAnnometadata = protoMeta.mutable_father(); + AnnotationMetadata::Serialize(static_cast(meta), *protoAnnometadata); + protoMeta.set_accessflags(meta.GetAccessFlags()); +} + +void ItemMetadata::Deserialize(const protoPanda::ItemMetadata &protoMeta, panda::pandasm::ItemMetadata &meta) +{ + meta.SetAccessFlags(protoMeta.accessflags()); +} + +void AnnotationMetadata::Serialize(const panda::pandasm::AnnotationMetadata &meta, + protoPanda::AnnotationMetadata &protoMeta) +{ + auto *protoMetadata = protoMeta.mutable_father(); + Metadata::Serialize(static_cast(meta), *protoMetadata); + for (const auto &anno : meta.GetAnnotations()) { + auto *proto_anno = protoMeta.add_annotations(); + AnnotationData::Serialize(anno, *proto_anno); + } +} + +void AnnotationMetadata::Deserialize(const protoPanda::AnnotationMetadata &protoMeta, + panda::pandasm::AnnotationMetadata &meta, + panda::ArenaAllocator *allocator) +{ + std::vector annotations; + annotations.reserve(protoMeta.annotations_size()); + for (const auto &protoAnnotation : protoMeta.annotations()) { + auto *annotation = allocator->New(protoAnnotation.recordname()); + AnnotationData::Deserialize(protoAnnotation, *annotation, allocator); + annotations.emplace_back(std::move(*annotation)); + } + meta.AddAnnotations(annotations); +} + +void Metadata::Serialize(const panda::pandasm::Metadata &meta, protoPanda::Metadata &protoMeta) +{ + for (const auto &attr : meta.GetBoolAttributes()) { + protoMeta.add_set_attributes(attr); + } + for (const auto &[name, attrs] : meta.GetAttributes()) { + auto *protoKeyVal = protoMeta.add_attributes(); + protoKeyVal->set_key(name); + for (const auto &attr : attrs) { + protoKeyVal->add_value(attr); + } + } +} + +void Metadata::Deserialize(const protoPanda::Metadata &protoMeta, panda::pandasm::Metadata &meta) +{ + for (const auto &attr : protoMeta.set_attributes()) { + meta.SetAttribute(attr); + } + for (const auto &protoKeyVal: protoMeta.attributes()) { + auto &key = protoKeyVal.key(); + for (const auto &attr : protoKeyVal.value()) { + meta.SetAttributeValue(key, attr); + } + } +} +} // panda::proto diff --git a/merge_abc/src/metaProto.h b/merge_abc/src/metaProto.h new file mode 100644 index 0000000000000000000000000000000000000000..93d5d1743d8ebf66b428b4cb778a9e2e94da35e7 --- /dev/null +++ b/merge_abc/src/metaProto.h @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MERGE_ABC_META_H +#define MERGE_ABC_META_H + +#include "annotationProto.h" +#include "arena_allocator.h" +#include "assembly-program.h" +#include "assemblyTypeProto.h" +#include "meta.pb.h" + +namespace panda::proto { +class RecordMetadata { +public: + static void Serialize(const panda::pandasm::RecordMetadata &meta, protoPanda::RecordMetadata &protoMeta); + static void Deserialize(const protoPanda::RecordMetadata &protoMeta, + std::unique_ptr &meta, + panda::ArenaAllocator *allocator); +}; + +class FunctionMetadata { +public: + static void Serialize(const panda::pandasm::FunctionMetadata &meta, + protoPanda::FunctionMetadata &protoMeta); + static void Deserialize(const protoPanda::FunctionMetadata &protoMeta, + std::unique_ptr &meta, + panda::ArenaAllocator *allocator); +}; + +class FieldMetadata { +public: + static void Serialize(const panda::pandasm::FieldMetadata &meta, protoPanda::FieldMetadata &protoMeta); + static void Deserialize(const protoPanda::FieldMetadata &protoMeta, + std::unique_ptr &meta, + panda::ArenaAllocator *allocator); +}; + +class ParamMetadata { +public: + static void Serialize(const panda::pandasm::ParamMetadata &meta, protoPanda::ParamMetadata &protoMeta); + static void Deserialize(const protoPanda::ParamMetadata &protoMeta, + std::unique_ptr &meta, + panda::ArenaAllocator *allocator); +}; + +class ItemMetadata { +public: + static void Serialize(const panda::pandasm::ItemMetadata &meta, protoPanda::ItemMetadata &protoMeta); + static void Deserialize(const protoPanda::ItemMetadata &protoMeta, panda::pandasm::ItemMetadata &meta); +}; + +class AnnotationMetadata { +public: + static void Serialize(const panda::pandasm::AnnotationMetadata &meta, + protoPanda::AnnotationMetadata &protoMeta); + static void Deserialize(const protoPanda::AnnotationMetadata &protoMeta, panda::pandasm::AnnotationMetadata &meta, + panda::ArenaAllocator *allocator); +}; + +class Metadata { +public: + static void Serialize(const panda::pandasm::Metadata &meta, protoPanda::Metadata &protoMeta); + static void Deserialize(const protoPanda::Metadata &protoMeta, panda::pandasm::Metadata &meta); +}; +} // panda::proto +#endif diff --git a/merge_abc/src/options.cpp b/merge_abc/src/options.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0745e103d66f06311922fb3a96e6148794193bde --- /dev/null +++ b/merge_abc/src/options.cpp @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "options.h" + +#include + +namespace panda::proto { +// Options +Options::Options() : argparser_(new panda::PandArgParser()) {} + +Options::~Options() +{ + delete argparser_; +} + +bool Options::Parse(int argc, const char **argv) +{ + panda::PandArg opHelp("help", false, "Print this message and exit"); + + panda::PandArg protoPathInput("input", "", + "Path of Proto bin file or directory. If input path starts with '@', " + "it considered as a text file with list of files or directories."); + panda::PandArg protoBinSuffix("suffix", "", "suffix of proto bin file"); + panda::PandArg outputFileName("output", "", "name of merged panda file"); + panda::PandArg outputFilePath("outputFilePath", "", "output path for merged panda file"); + + argparser_->Add(&opHelp); + argparser_->Add(&protoPathInput); + argparser_->Add(&protoBinSuffix); + argparser_->Add(&outputFileName); + argparser_->Add(&outputFilePath); + + if (!argparser_->Parse(argc, argv) || opHelp.GetValue() || protoPathInput.GetValue().empty()) { + std::stringstream ss; + + ss << argparser_->GetErrorString() << std::endl; + ss << "Usage: " + << "merge_abc" + << " [OPTIONS] --input" << std::endl; + ss << std::endl; + ss << "optional arguments:" << std::endl; + ss << argparser_->GetHelpString() << std::endl; + + errorMsg_ = ss.str(); + return false; + } + + protoPathInput_ = protoPathInput.GetValue(); + if (!protoBinSuffix.GetValue().empty()) { + protoBinSuffix_ = protoBinSuffix.GetValue(); + } + if (!outputFileName.GetValue().empty()) { + outputFileName_ = outputFileName.GetValue(); + } + if (!outputFilePath.GetValue().empty()) { + outputFilePath_ = outputFilePath.GetValue(); + } + + return true; +} +} diff --git a/merge_abc/src/options.h b/merge_abc/src/options.h new file mode 100644 index 0000000000000000000000000000000000000000..e1c76e170276edaee7d738adce3965c11b57538c --- /dev/null +++ b/merge_abc/src/options.h @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MERGE_ABC_MERGE_OPTIONS_H +#define MERGE_ABC_MERGE_OPTIONS_H + +#include +#include +#include + +namespace panda::proto { +class Options { +public: + Options(); + NO_COPY_SEMANTIC(Options); + NO_MOVE_SEMANTIC(Options); + ~Options(); + + bool Parse(int argc, const char **argv); + + const std::string &protoPathInput() const + { + return protoPathInput_; + } + + const std::string &protoBinSuffix() const + { + return protoBinSuffix_; + } + + const std::string &outputFileName() const + { + return outputFileName_; + } + + const std::string &outputFilePath() const + { + return outputFilePath_; + } + + const std::string &ErrorMsg() const + { + return errorMsg_; + } + +private: + panda::PandArgParser *argparser_; + std::string errorMsg_; + std::string protoBinSuffix_ {"bin"}; + std::string protoPathInput_; + std::string outputFileName_ {"modules.abc"}; + std::string outputFilePath_; +}; +} // panda::proto +#endif diff --git a/merge_abc/src/protobufSnapshotGenerator.cpp b/merge_abc/src/protobufSnapshotGenerator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7b0af28c2be8ebe85ff4275dfb9253c81e8cc1d3 --- /dev/null +++ b/merge_abc/src/protobufSnapshotGenerator.cpp @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "assemblyProgramProto.h" +#include "assembly-program.h" +#include "protobufSnapshotGenerator.h" + +namespace panda::proto { +void ProtobufSnapshotGenerator::GenerateSnapshot(const panda::pandasm::Program &program, const std::string &outputName) +{ + protoPanda::Program protoProgram; + + Program::Serialize(program, protoProgram); + + std::fstream output(outputName, std::ios::out | std::ios::trunc | std::ios::binary); + if (!output) { + std::cerr << "Failed to create: " << outputName << std::endl; + return; + } + protoProgram.SerializeToOstream(&output); + output.close(); +} + +void ProtobufSnapshotGenerator::GenerateProgram(const std::string &inputName, panda::pandasm::Program &prog, + panda::ArenaAllocator *allocator) +{ + std::fstream input(inputName, std::ios::in | std::ios::binary); + if (!input) { + std::cerr << "Failed to open: " << inputName << std::endl; + return; + } + protoPanda::Program proto_program; + if (!proto_program.ParseFromIstream(&input)) { + std::cerr << "Failed to parse: " << inputName << std::endl; + return; + } + Program::Deserialize(proto_program, prog, allocator); +} + +void ProtobufSnapshotGenerator::UpdateCacheFile( + const std::unordered_map &compositeProgramMap, + bool &isDebug, const std::string &cacheFilePath) +{ + protoPanda::CompositeProgram protoCompositeProgram; + CompositeProgram::Serialize(compositeProgramMap, isDebug, protoCompositeProgram); + std::fstream output(cacheFilePath, std::ios::out | std::ios::trunc | std::ios::binary); + if (!output) { + std::cerr << "Failed to create cache file: " << cacheFilePath << std::endl; + return; + } + protoCompositeProgram.SerializeToOstream(&output); + output.close(); +} + +std::unordered_map *ProtobufSnapshotGenerator::GetCacheContext( + const std::string &cacheFilePath, bool isDebug, panda::ArenaAllocator *allocator) +{ + std::fstream input(cacheFilePath, std::ios::in | std::ios::binary); + if (!input) { + std::cerr << "Cache file: " << cacheFilePath << " doesn't exist" << std::endl; + return nullptr; + } + protoPanda::CompositeProgram protoCompositeProgram; + if (!protoCompositeProgram.ParseFromIstream(&input)) { + std::cerr << "Failed to parse cache file: " << cacheFilePath << std::endl; + return nullptr; + } + + if (protoCompositeProgram.isdebug() != isDebug) { + return nullptr; + } + + auto compositeProgramMap = allocator->New>(); + CompositeProgram::Deserialize(protoCompositeProgram, *compositeProgramMap, allocator); + + return compositeProgramMap; +} +} // panda::proto diff --git a/merge_abc/src/protobufSnapshotGenerator.h b/merge_abc/src/protobufSnapshotGenerator.h new file mode 100644 index 0000000000000000000000000000000000000000..20bb7118e9b57c20531194bfc7de00a273cd070b --- /dev/null +++ b/merge_abc/src/protobufSnapshotGenerator.h @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MERGE_ABC_POROBUFSNAPSHOTGENERATOR_H +#define MERGE_ABC_POROBUFSNAPSHOTGENERATOR_H + +#include "assemblyProgramProto.h" +#include "compositeProgramProto.h" + +namespace panda::proto { +class ProtobufSnapshotGenerator { +public: + static void GenerateSnapshot(const panda::pandasm::Program &prog, const std::string &outputName); + static void GenerateProgram(const std::string &inputName, panda::pandasm::Program &prog, + panda::ArenaAllocator *allocator); + static std::unordered_map *GetCacheContext( + const std::string &cacheFilePath, bool isDebug, panda::ArenaAllocator *allocator); + static void UpdateCacheFile( + const std::unordered_map &compositeProgram, + bool &isDebug, const std::string &cacheFilePath); +}; +} // panda::proto +#endif diff --git a/test262/config.py b/test262/config.py index 435a681031b2c93efca8a54424722d7487b49310..9bcf2ac9f083c037caa659ddc3699f6bb1bbd873 100755 --- a/test262/config.py +++ b/test262/config.py @@ -96,6 +96,7 @@ ARK_FRONTEND_BINARY_LIST = [ DEFAULT_ARK_FRONTEND = ARK_FRONTEND_LIST[0] DEFAULT_ARK_FRONTEND_BINARY = ARK_FRONTEND_BINARY_LIST[0] +DEFAULT_MERGE_ABC_BINARY = os.path.join(ARK_DIR, "merge_abc") ARK_ARCH_LIST = [ "x64", @@ -106,3 +107,4 @@ ARK_ARCH_LIST = [ DEFAULT_ARK_ARCH = ARK_ARCH_LIST[0] DEFAULT_OPT_LEVEL = 2 DEFAULT_ES2ABC_THREAD_COUNT = 0 +DEFAULT_MERGE_ABC_MODE = 0 diff --git a/test262/run_sunspider.py b/test262/run_sunspider.py index 4ca85d98ee823ae39c994a1146123b8e6fe8c4fe..f7f6ea757ac1b824728332a2db959b198383a85f 100755 --- a/test262/run_sunspider.py +++ b/test262/run_sunspider.py @@ -76,6 +76,14 @@ def parse_args(): default=DEFAULT_ES2ABC_THREAD_COUNT, required=False, help="the thread count for es2abc") + parser.add_argument('--merge-abc-binary', + default=DEFAULT_MERGE_ABC_BINARY, + required=False, + help="frontend merge abc binary tool") + parser.add_argument('--merge-abc-mode', + default=DEFAULT_MERGE_ABC_MODE, + required=False, + help="run test for merge abc mode") arguments = parser.parse_args() return arguments @@ -173,6 +181,8 @@ class ArkProgram(): self.arch_root = "" self.opt_level = DEFAULT_OPT_LEVEL self.es2abc_thread_count = DEFAULT_ES2ABC_THREAD_COUNT + self.merge_abc_binary = DEFAULT_MERGE_ABC_BINARY + self.merge_abc_mode = DEFAULT_MERGE_ABC_MODE def proce_parameters(self): if self.args.ark_tool: @@ -199,6 +209,12 @@ class ArkProgram(): if self.args.es2abc_thread_count: self.es2abc_thread_count = self.args.es2abc_thread_count + if self.args.merge_abc_binary: + self.merge_abc_binary = self.args.merge_abc_binary + + if self.args.merge_abc_mode: + self.merge_abc_mode = self.args.merge_abc_mode + self.module_list = MODULE_LIST self.dynamicImport_list = DYNAMIC_IMPORT_LIST @@ -211,10 +227,12 @@ class ArkProgram(): def gen_dependency_abc(self, dependency): cmd_args = [] - output_file = os.path.splitext(os.path.join(BASE_OUT_DIR, os.path.split(dependency)[1]))[0] + output_file = os.path.splitext(os.path.join(BASE_OUT_DIR, + os.path.split(dependency)[1]))[0] output_abc = f"{output_file}.abc" frontend_tool = self.ark_frontend_binary - cmd_args = [frontend_tool, dependency, '--output', output_abc, '--module'] + cmd_args = [frontend_tool, dependency, '--output', output_abc, + '--module'] proc = subprocess.Popen(cmd_args) proc.wait() @@ -222,11 +240,16 @@ class ArkProgram(): js_file = self.js_file file_name_pre = os.path.splitext(js_file)[0] file_name = os.path.basename(js_file) + file_dir = os.path.split(js_file)[0] out_file = f"{file_name_pre}.abc" + proto_bin_file = f"{file_name_pre}.bin" + proto_abc_file = ".".join([os.path.splitext(file_name)[0], "abc"]) self.abc_file = out_file mod_opt_index = 0 cmd_args = [] frontend_tool = self.ark_frontend_binary + merge_abc_binary = self.args.merge_abc_binary + merge_abc_mode = self.merge_abc_mode # pre-generate the dependencies' abc when ark_frontend is [es2panda] if (file_name in self.module_list or file_name in self.dynamicImport_list) and \ @@ -245,8 +268,14 @@ class ArkProgram(): self.module = True elif self.ark_frontend == ARK_FRONTEND_LIST[1]: mod_opt_index = 1 - cmd_args = [frontend_tool, '--opt-level=' + str(self.opt_level), - '--thread=' + str(self.es2abc_thread_count), '--output', out_file, js_file] + if merge_abc_mode != "0": + cmd_args = [frontend_tool, '--outputProto', + proto_bin_file, js_file] + else: + cmd_args = [frontend_tool, '--opt-level=' + str(self.opt_level), + '--function-threads=' + + str(self.es2abc_thread_count), '--output', + out_file, js_file] if file_name in self.module_list: cmd_args.insert(mod_opt_index, "--module") self.module = True @@ -265,6 +294,11 @@ class ArkProgram(): self.abc_file += f':{abc_file}' retcode = exec_command(cmd_args) self.abc_cmd = cmd_args + if self.ark_frontend == ARK_FRONTEND_LIST[1] and merge_abc_mode != "0": + cmd_args = [merge_abc_binary, '--input', proto_bin_file, + '--suffix', "bin", '--outputFilePath', + file_dir, '--output', proto_abc_file] + retcode = exec_command(cmd_args) return retcode def compile_aot(self): diff --git a/test262/run_test262.py b/test262/run_test262.py index 972b10cbfafe9749c839f0158a218397f86736af..39569b3c9f59c6cee4ddabaca9007056f1dd02ab 100755 --- a/test262/run_test262.py +++ b/test262/run_test262.py @@ -98,6 +98,10 @@ def parse_args(): parser.add_argument('--es2abc-thread-count', default=DEFAULT_ES2ABC_THREAD_COUNT, help="the thread count for es2abc") + parser.add_argument('--merge-abc-binary', + help="frontend merge abc binary tool") + parser.add_argument('--merge-abc-mode', + help="run test for merge abc mode") return parser.parse_args() @@ -482,6 +486,8 @@ def get_host_args(args, host_type): ark_arch = DEFAULT_ARK_ARCH opt_level = DEFAULT_OPT_LEVEL es2abc_thread_count = DEFAULT_ES2ABC_THREAD_COUNT + merge_abc_binary = DEFAULT_MERGE_ABC_BINARY + merge_abc_mode = DEFAULT_MERGE_ABC_MODE if args.hostArgs: host_args = args.hostArgs @@ -507,6 +513,12 @@ def get_host_args(args, host_type): if args.es2abc_thread_count: es2abc_thread_count = args.es2abc_thread_count + if args.merge_abc_binary: + merge_abc_binary = args.merge_abc_binary + + if args.merge_abc_mode: + merge_abc_mode = args.merge_abc_mode + if host_type == DEFAULT_HOST_TYPE: host_args = f"-B test262/run_sunspider.py " host_args += f"--ark-tool={ark_tool} " @@ -518,6 +530,8 @@ def get_host_args(args, host_type): host_args += f"--ark-frontend-binary={ark_frontend_binary} " host_args += f"--opt-level={opt_level} " host_args += f"--es2abc-thread-count={es2abc_thread_count} " + host_args += f"--merge-abc-binary={merge_abc_binary} " + host_args += f"--merge-abc-mode={merge_abc_mode} " if args.ark_arch != ark_arch: host_args += f"--ark-arch={args.ark_arch} " diff --git a/ts2panda/src/base/literal.ts b/ts2panda/src/base/literal.ts index a372ef0050162c82f767cf6e28c4661c5c0a8eb4..50d7c9d52c9f9d91839eef7a44b90885d4af03f0 100644 --- a/ts2panda/src/base/literal.ts +++ b/ts2panda/src/base/literal.ts @@ -22,6 +22,9 @@ export enum LiteralTag { GENERATOR = 7, ACCESSOR = 8, METHODAFFILIATE = 9, + // 0x0a - 0x15 for ARRAY_Type + ASYNCGENERATOR = 22, + LITERALBUFFERINDEX = 23, NULLVALUE = 255 } diff --git a/ts2panda/ts2abc/BUILD.gn b/ts2panda/ts2abc/BUILD.gn index 7e723caf01bfcc095669284ce680668e04f63a47..0abc5e79b96348768bde35e4f7872e06a2044319 100755 --- a/ts2panda/ts2abc/BUILD.gn +++ b/ts2panda/ts2abc/BUILD.gn @@ -40,6 +40,7 @@ config("ts2abc_config") { "$ark_root/libpandabase:arkbase_public_config", "$ark_root/runtime:arkruntime_public_config", "$ark_root/assembler:arkassembler_public_config", + "//arkcompiler/ets_frontend/merge_abc:panda_assembly_proto_public_config", ] if (enable_bytecode_optimizer) { @@ -91,7 +92,10 @@ if (!defined(ark_independent_build)) { "-Wno-unknown-warning-option", ] - deps = [ sdk_libc_secshared_dep ] + deps = [ + "//arkcompiler/ets_frontend/merge_abc:panda_assembly_proto_static", + sdk_libc_secshared_dep, + ] if (is_linux || is_mingw || is_mac) { deps += [ diff --git a/ts2panda/ts2abc/main.cpp b/ts2panda/ts2abc/main.cpp index 4a5b3ecd989bf20772b1abc4733ec682ef591368..c2840600589426893f349ab34431cb1ae148d18f 100644 --- a/ts2panda/ts2abc/main.cpp +++ b/ts2panda/ts2abc/main.cpp @@ -92,8 +92,7 @@ int main(int argc, const char *argv[]) return panda::ts2abc::RETURN_FAILED; } - if (!panda::ts2abc::GenerateProgram(data, output, options.GetCompileByPipeArg(), - options.GetOptLevelArg(), optLogLevel)) { + if (!panda::ts2abc::GenerateProgram(data, output, options)) { std::cerr << "call GenerateProgram fail" << std::endl; return panda::ts2abc::RETURN_FAILED; } diff --git a/ts2panda/ts2abc/ts2abc.cpp b/ts2panda/ts2abc/ts2abc.cpp index 2af75f296740f6861ff439e645e6eb8b77d18761..0fdb1b1b4c067b147656d751ba9453a56ef5787f 100644 --- a/ts2panda/ts2abc/ts2abc.cpp +++ b/ts2panda/ts2abc/ts2abc.cpp @@ -26,8 +26,9 @@ #include "json/json.h" #include "securec.h" #include "ts2abc_options.h" -#include "type_adapter.h" #include "ts2abc.h" +#include "type_adapter.h" +#include "protobufSnapshotGenerator.h" #ifdef ENABLE_BYTECODE_OPT #include "optimize_bytecode.h" @@ -46,6 +47,7 @@ bool g_isDtsFile = false; std::string g_optLogLevel = "error"; uint32_t g_literalArrayCount = 0; using ts2abc_type_adapter::TypeAdapter; +std::string g_compilerOutputProto = ""; constexpr std::size_t BOUND_LEFT = 0; constexpr std::size_t BOUND_RIGHT = 0; @@ -60,17 +62,9 @@ std::unordered_map g_opcodeMap = { }; // pandasm helpers -static panda::pandasm::Record MakeRecordDefinition(const std::string &name, const std::string &wholeLine, - size_t boundLeft, size_t boundRight, size_t lineNumber) +static panda::pandasm::Record MakeRecordDefinition(const std::string &name) { - auto record = panda::pandasm::Record( - name, - LANG_EXT, - boundLeft, - boundRight, - wholeLine, - IS_DEFINED, - lineNumber); + auto record = panda::pandasm::Record(name, LANG_EXT); return record; } @@ -270,6 +264,11 @@ static void ParseLiteral(const Json::Value &literal, std::vector(literal["v"].asUInt()); break; } + case static_cast(panda::panda_file::LiteralTag::LITERALBUFFERINDEX): { + valueLiteral.tag_ = panda::panda_file::LiteralTag::LITERALBUFFERINDEX; + valueLiteral.value_ = static_cast(literal["v"].asInt()); + break; + } case static_cast(panda::panda_file::LiteralTag::NULLVALUE): { valueLiteral.tag_ = panda::panda_file::LiteralTag::NULLVALUE; valueLiteral.value_ = static_cast(0); @@ -289,28 +288,7 @@ static panda::pandasm::Record ParseRecord(const Json::Value &record) recordName = record["name"].asString(); } - std::string wholeLine = ""; - if (record.isMember("whole_line") && record["whole_line"].isString()) { - wholeLine = ParseString(record["whole_line"].asString()); - } - - int boundLeft = -1; - if (record.isMember("bound_left") && record["bound_left"].isInt()) { - boundLeft = record["bound_left"].asInt(); - } - - int boundRight = -1; - if (record.isMember("bound_right") && record["bound_right"].isInt()) { - boundRight = record["bound_right"].asInt(); - } - - int lineNumber = -1; - if (record.isMember("line_number") && record["line_number"].isInt()) { - lineNumber = record["line_number"].asInt(); - } - - auto pandaRecord = MakeRecordDefinition(recordName, wholeLine, static_cast(boundLeft), - static_cast(boundRight), static_cast(lineNumber)); + auto pandaRecord = MakeRecordDefinition(recordName); if (record.isMember("metadata") && record["metadata"].isObject()) { auto metadata = record["metadata"]; @@ -927,6 +905,13 @@ static void ParseIsDtsFile(const Json::Value &rootValue) } } +static void ParseCompilerOutputProto(const Json::Value &rootValue) +{ + Logd("-----------------parse compiler output proto-----------------"); + if (rootValue.isMember("output-proto") && rootValue["output-proto"].isString()) { + g_compilerOutputProto = rootValue["output-proto"].asString(); + } +} static void ReplaceAllDistinct(std::string &str, const std::string &oldValue, const std::string &newValue) { for (std::string::size_type pos(0); pos != std::string::npos; pos += newValue.length()) { @@ -950,6 +935,7 @@ static void ParseOptions(const Json::Value &rootValue, panda::pandasm::Program & ParseDisplayTypeinfo(rootValue); ParseOptLogLevel(rootValue); ParseIsDtsFile(rootValue); + ParseCompilerOutputProto(rootValue); } static void ParseSingleFunc(const Json::Value &rootValue, panda::pandasm::Program &prog) @@ -1301,9 +1287,12 @@ static bool ReadFromPipe(panda::pandasm::Program &prog) return true; } -bool GenerateProgram([[maybe_unused]] const std::string &data, const std::string &output, bool isParsingFromPipe, - int optLevel, std::string &optLogLevel) +bool GenerateProgram([[maybe_unused]] const std::string &data, const std::string &output, + panda::ts2abc::Options options) { + bool isParsingFromPipe = options.GetCompileByPipeArg(); + int optLevel = options.GetOptLevelArg(); + std::string optLogLevel = options.GetOptLogLevelArg(); panda::pandasm::Program prog = panda::pandasm::Program(); prog.lang = panda::pandasm::extensions::Language::ECMASCRIPT; @@ -1321,6 +1310,11 @@ bool GenerateProgram([[maybe_unused]] const std::string &data, const std::string Logd("parsing done, calling pandasm\n"); + std::string compilerOutputProto = g_compilerOutputProto; + if (options.GetCompilerOutputProto().size() > 0) { + compilerOutputProto = options.GetCompilerOutputProto(); + } + TypeAdapter ada(g_displayTypeinfo); ada.AdaptTypeForProgram(&prog); @@ -1346,7 +1340,14 @@ bool GenerateProgram([[maybe_unused]] const std::string &data, const std::string std::cerr << "Failed to emit binary data: " << panda::pandasm::AsmEmitter::GetLastError() << std::endl; return false; } + panda::bytecodeopt::OptimizeBytecode(&prog, mapsp, output.c_str(), true); + + if (compilerOutputProto.size() > 0) { + panda::proto::ProtobufSnapshotGenerator::GenerateSnapshot(prog, compilerOutputProto); + return true; + } + if (!panda::pandasm::AsmEmitter::Emit(output.c_str(), prog, statp, mapsp, emitDebugInfo)) { std::cerr << "Failed to emit binary data: " << panda::pandasm::AsmEmitter::GetLastError() << std::endl; return false; @@ -1354,6 +1355,10 @@ bool GenerateProgram([[maybe_unused]] const std::string &data, const std::string return true; } #endif + if (compilerOutputProto.size() > 0) { + panda::proto::ProtobufSnapshotGenerator::GenerateSnapshot(prog, compilerOutputProto); + return true; + } if (!panda::pandasm::AsmEmitter::Emit(output.c_str(), prog, nullptr)) { std::cerr << "Failed to emit binary data: " << panda::pandasm::AsmEmitter::GetLastError() << std::endl; diff --git a/ts2panda/ts2abc/ts2abc.h b/ts2panda/ts2abc/ts2abc.h index 019b5e8c7fdf2e2278ab27dd78b0ba85a7329ea8..421205bb35905ff34455f39acfdbcb1e7b5dbb8b 100644 --- a/ts2panda/ts2abc/ts2abc.h +++ b/ts2panda/ts2abc/ts2abc.h @@ -49,8 +49,7 @@ enum class OptLevel { }; bool HandleJsonFile(const std::string &input, std::string &data); -bool GenerateProgram(const std::string &data, const std::string &output, bool isParsingFromPipe, - int optLevel, std::string &optLogLevel); +bool GenerateProgram(const std::string &data, const std::string &output, panda::ts2abc::Options options); bool GetDebugLog(); void ParseLogEnable(const Json::Value &rootValue); bool GetDebugModeEnabled(); diff --git a/ts2panda/ts2abc/ts2abc_options.h b/ts2panda/ts2abc/ts2abc_options.h index 310c98e707f776fa71e78af2aec2ae00b7852ec0..76f326fe257cdf811b77e5da75b9b759e2d76843 100755 --- a/ts2panda/ts2abc/ts2abc_options.h +++ b/ts2panda/ts2abc/ts2abc_options.h @@ -39,6 +39,7 @@ namespace panda::ts2abc { parser->Add(&bc_version_arg_); parser->Add(&bc_min_version_arg_); parser->Add(&compile_by_pipe_arg_); + parser->Add(&compiler_output_proto_); parser->EnableTail(); parser->PushBackTail(&Tail_Arg1_arg_); parser->PushBackTail(&Tail_Arg2_arg_); @@ -149,6 +150,21 @@ namespace panda::ts2abc { return compile_by_pipe_arg_.WasSet(); } + std::string GetCompilerOutputProto() const + { + return compiler_output_proto_.GetValue(); + } + + void SetCompilerOutputProto(std::string value) + { + compiler_output_proto_.SetValue(value); + } + + bool WasSetCompilerOutputProto() const + { + return compiler_output_proto_.WasSet(); + } + std::string GetTailArg1() const { return Tail_Arg1_arg_.GetValue(); @@ -207,6 +223,8 @@ namespace panda::ts2abc { R"(Print ark bytecode minimum supported version)"}; panda::PandArg compile_by_pipe_arg_{ "compile-by-pipe", false, R"(Compile a json file that is passed by pipe)"}; + panda::PandArg compiler_output_proto_{ "output-proto", "", + R"(compiler proto serialize binary output (.proto))"}; panda::PandArg Tail_Arg1_arg_{ "ARG_1", "", R"(Path to input(json file) or path to output(ark bytecode)" " when 'compile-by-pipe' enabled)"};