14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_COMPILER_CODE_GENERATOR_H 174514f5e3Sopenharmony_ci#define ECMASCRIPT_COMPILER_CODE_GENERATOR_H 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_ci#include "ecmascript/compiler/circuit.h" 204514f5e3Sopenharmony_ci#include "ecmascript/compiler/binary_section.h" 214514f5e3Sopenharmony_ci#include "ecmascript/jspandafile/method_literal.h" 224514f5e3Sopenharmony_ci 234514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu { 244514f5e3Sopenharmony_ciusing ControlFlowGraph = std::vector<std::vector<GateRef>>; 254514f5e3Sopenharmony_ciclass CompilationConfig; 264514f5e3Sopenharmony_ciclass CompilerLog; 274514f5e3Sopenharmony_ci 284514f5e3Sopenharmony_cistruct CodeInfo { 294514f5e3Sopenharmony_ci using sectionInfo = std::pair<uint8_t *, size_t>; 304514f5e3Sopenharmony_ci typedef uint8_t *(CodeInfo::*AllocaSectionCallback)(uintptr_t size, size_t alignSize); 314514f5e3Sopenharmony_ci 324514f5e3Sopenharmony_ci class CodeSpace { 334514f5e3Sopenharmony_ci public: 344514f5e3Sopenharmony_ci static CodeSpace *GetInstance(); 354514f5e3Sopenharmony_ci 364514f5e3Sopenharmony_ci uint8_t *Alloca(uintptr_t size, bool isReq, size_t alignSize); 374514f5e3Sopenharmony_ci 384514f5e3Sopenharmony_ci private: 394514f5e3Sopenharmony_ci CodeSpace(); 404514f5e3Sopenharmony_ci ~CodeSpace(); 414514f5e3Sopenharmony_ci 424514f5e3Sopenharmony_ci static constexpr size_t REQUIRED_SECS_LIMIT = (1 << 29); // 512M 434514f5e3Sopenharmony_ci static constexpr size_t UNREQUIRED_SECS_LIMIT = (1 << 28); // 256M 444514f5e3Sopenharmony_ci 454514f5e3Sopenharmony_ci // start point of the buffer reserved for sections required in executing phase 464514f5e3Sopenharmony_ci uint8_t *reqSecs_ {nullptr}; 474514f5e3Sopenharmony_ci size_t reqBufPos_ {0}; 484514f5e3Sopenharmony_ci // start point of the buffer reserved for sections not required in executing phase 494514f5e3Sopenharmony_ci uint8_t *unreqSecs_ {nullptr}; 504514f5e3Sopenharmony_ci size_t unreqBufPos_ {0}; 514514f5e3Sopenharmony_ci }; 524514f5e3Sopenharmony_ci 534514f5e3Sopenharmony_ci class CodeSpaceOnDemand { 544514f5e3Sopenharmony_ci public: 554514f5e3Sopenharmony_ci CodeSpaceOnDemand() = default; 564514f5e3Sopenharmony_ci 574514f5e3Sopenharmony_ci uint8_t *Alloca(uintptr_t size, bool isReq, size_t alignSize); 584514f5e3Sopenharmony_ci 594514f5e3Sopenharmony_ci ~CodeSpaceOnDemand(); 604514f5e3Sopenharmony_ci 614514f5e3Sopenharmony_ci private: 624514f5e3Sopenharmony_ci static constexpr size_t SECTION_LIMIT = (1 << 29); // 512M 634514f5e3Sopenharmony_ci 644514f5e3Sopenharmony_ci // record all memory blocks requested. 654514f5e3Sopenharmony_ci std::vector<std::pair<uint8_t *, uintptr_t>> sections_; 664514f5e3Sopenharmony_ci }; 674514f5e3Sopenharmony_ci 684514f5e3Sopenharmony_ci struct FuncInfo { 694514f5e3Sopenharmony_ci uint32_t addr = 0; 704514f5e3Sopenharmony_ci int32_t fp2PrevFrameSpDelta = 0; 714514f5e3Sopenharmony_ci kungfu::CalleeRegAndOffsetVec calleeRegInfo; 724514f5e3Sopenharmony_ci }; 734514f5e3Sopenharmony_ci 744514f5e3Sopenharmony_ci CodeInfo(CodeSpaceOnDemand &codeSpaceOnDemand); 754514f5e3Sopenharmony_ci 764514f5e3Sopenharmony_ci ~CodeInfo(); 774514f5e3Sopenharmony_ci 784514f5e3Sopenharmony_ci uint8_t *AllocaOnDemand(uintptr_t size, size_t alignSize = 0); 794514f5e3Sopenharmony_ci 804514f5e3Sopenharmony_ci uint8_t *AllocaInReqSecBuffer(uintptr_t size, size_t alignSize = 0); 814514f5e3Sopenharmony_ci 824514f5e3Sopenharmony_ci uint8_t *AllocaInNotReqSecBuffer(uintptr_t size, size_t alignSize = 0); 834514f5e3Sopenharmony_ci 844514f5e3Sopenharmony_ci uint8_t *AllocaCodeSectionImp(uintptr_t size, const char *sectionName, AllocaSectionCallback allocaInReqSecBuffer); 854514f5e3Sopenharmony_ci 864514f5e3Sopenharmony_ci uint8_t *AllocaCodeSection(uintptr_t size, const char *sectionName); 874514f5e3Sopenharmony_ci 884514f5e3Sopenharmony_ci uint8_t *AllocaCodeSectionOnDemand(uintptr_t size, const char *sectionName); 894514f5e3Sopenharmony_ci 904514f5e3Sopenharmony_ci uint8_t *AllocaDataSectionImp(uintptr_t size, const char *sectionName, AllocaSectionCallback allocaInReqSecBuffer, 914514f5e3Sopenharmony_ci AllocaSectionCallback allocaInNotReqSecBuffer); 924514f5e3Sopenharmony_ci 934514f5e3Sopenharmony_ci uint8_t *AllocaDataSection(uintptr_t size, const char *sectionName); 944514f5e3Sopenharmony_ci 954514f5e3Sopenharmony_ci uint8_t *AllocaDataSectionOnDemand(uintptr_t size, const char *sectionName); 964514f5e3Sopenharmony_ci 974514f5e3Sopenharmony_ci void SaveFunc2Addr(std::string funcName, uint32_t address); 984514f5e3Sopenharmony_ci 994514f5e3Sopenharmony_ci void SaveFunc2FPtoPrevSPDelta(std::string funcName, int32_t fp2PrevSpDelta); 1004514f5e3Sopenharmony_ci 1014514f5e3Sopenharmony_ci void SaveFunc2CalleeOffsetInfo(std::string funcName, kungfu::CalleeRegAndOffsetVec calleeRegInfo); 1024514f5e3Sopenharmony_ci 1034514f5e3Sopenharmony_ci void SavePC2DeoptInfo(uint64_t pc, std::vector<uint8_t> pc2DeoptInfo); 1044514f5e3Sopenharmony_ci 1054514f5e3Sopenharmony_ci void SavePC2CallSiteInfo(uint64_t pc, std::vector<uint8_t> callSiteInfo); 1064514f5e3Sopenharmony_ci 1074514f5e3Sopenharmony_ci const std::map<std::string, FuncInfo> &GetFuncInfos() const; 1084514f5e3Sopenharmony_ci 1094514f5e3Sopenharmony_ci const std::map<uint64_t, std::vector<uint8_t>> &GetPC2DeoptInfo() const; 1104514f5e3Sopenharmony_ci 1114514f5e3Sopenharmony_ci const std::unordered_map<uint64_t, std::vector<uint8_t>> &GetPC2CallsiteInfo() const; 1124514f5e3Sopenharmony_ci 1134514f5e3Sopenharmony_ci void Reset(); 1144514f5e3Sopenharmony_ci 1154514f5e3Sopenharmony_ci uint8_t *GetSectionAddr(ElfSecName sec) const; 1164514f5e3Sopenharmony_ci 1174514f5e3Sopenharmony_ci size_t GetSectionSize(ElfSecName sec) const; 1184514f5e3Sopenharmony_ci 1194514f5e3Sopenharmony_ci std::vector<std::pair<uint8_t *, uintptr_t>> GetCodeInfo() const; 1204514f5e3Sopenharmony_ci 1214514f5e3Sopenharmony_ci template <class Callback> 1224514f5e3Sopenharmony_ci void IterateSecInfos(const Callback &cb) const 1234514f5e3Sopenharmony_ci { 1244514f5e3Sopenharmony_ci for (size_t i = 0; i < secInfos_.size(); i++) { 1254514f5e3Sopenharmony_ci if (secInfos_[i].second == 0) { 1264514f5e3Sopenharmony_ci continue; 1274514f5e3Sopenharmony_ci } 1284514f5e3Sopenharmony_ci cb(i, secInfos_[i]); 1294514f5e3Sopenharmony_ci } 1304514f5e3Sopenharmony_ci } 1314514f5e3Sopenharmony_ci 1324514f5e3Sopenharmony_ciprivate: 1334514f5e3Sopenharmony_ci std::array<sectionInfo, static_cast<int>(ElfSecName::SIZE)> secInfos_; 1344514f5e3Sopenharmony_ci std::vector<std::pair<uint8_t *, uintptr_t>> codeInfo_ {}; // info for disasssembler, planed to be deprecated 1354514f5e3Sopenharmony_ci std::map<std::string, FuncInfo> func2FuncInfo; 1364514f5e3Sopenharmony_ci std::map<uint64_t, std::vector<uint8_t>> pc2DeoptInfo; 1374514f5e3Sopenharmony_ci std::unordered_map<uint64_t, std::vector<uint8_t>> pc2CallsiteInfo; 1384514f5e3Sopenharmony_ci bool alreadyPageAlign_ {false}; 1394514f5e3Sopenharmony_ci CodeSpaceOnDemand &codeSpaceOnDemand_; 1404514f5e3Sopenharmony_ci}; 1414514f5e3Sopenharmony_ci 1424514f5e3Sopenharmony_ciclass Assembler { 1434514f5e3Sopenharmony_cipublic: 1444514f5e3Sopenharmony_ci explicit Assembler(CodeInfo::CodeSpaceOnDemand &codeSpaceOnDemand) : codeInfo_(codeSpaceOnDemand) 1454514f5e3Sopenharmony_ci {} 1464514f5e3Sopenharmony_ci virtual ~Assembler() = default; 1474514f5e3Sopenharmony_ci virtual void Run(const CompilerLog &log, bool fastCompileMode, bool isJit = false) = 0; 1484514f5e3Sopenharmony_ci 1494514f5e3Sopenharmony_ci uintptr_t GetSectionAddr(ElfSecName sec) const 1504514f5e3Sopenharmony_ci { 1514514f5e3Sopenharmony_ci return reinterpret_cast<uintptr_t>(codeInfo_.GetSectionAddr(sec)); 1524514f5e3Sopenharmony_ci } 1534514f5e3Sopenharmony_ci 1544514f5e3Sopenharmony_ci uint32_t GetSectionSize(ElfSecName sec) const 1554514f5e3Sopenharmony_ci { 1564514f5e3Sopenharmony_ci return static_cast<uint32_t>(codeInfo_.GetSectionSize(sec)); 1574514f5e3Sopenharmony_ci } 1584514f5e3Sopenharmony_ci 1594514f5e3Sopenharmony_ci template <class Callback> 1604514f5e3Sopenharmony_ci void IterateSecInfos(const Callback &cb) const 1614514f5e3Sopenharmony_ci { 1624514f5e3Sopenharmony_ci codeInfo_.IterateSecInfos(cb); 1634514f5e3Sopenharmony_ci } 1644514f5e3Sopenharmony_ci 1654514f5e3Sopenharmony_ci const CodeInfo &GetCodeInfo() const 1664514f5e3Sopenharmony_ci { 1674514f5e3Sopenharmony_ci return codeInfo_; 1684514f5e3Sopenharmony_ci } 1694514f5e3Sopenharmony_ciprotected: 1704514f5e3Sopenharmony_ci CodeInfo codeInfo_; 1714514f5e3Sopenharmony_ci}; 1724514f5e3Sopenharmony_ci 1734514f5e3Sopenharmony_ciclass CodeGeneratorImpl { 1744514f5e3Sopenharmony_cipublic: 1754514f5e3Sopenharmony_ci CodeGeneratorImpl() = default; 1764514f5e3Sopenharmony_ci 1774514f5e3Sopenharmony_ci virtual ~CodeGeneratorImpl() = default; 1784514f5e3Sopenharmony_ci 1794514f5e3Sopenharmony_ci virtual void GenerateCodeForStub(Circuit *circuit, const ControlFlowGraph &graph, size_t index, 1804514f5e3Sopenharmony_ci const CompilationConfig *cfg) = 0; 1814514f5e3Sopenharmony_ci 1824514f5e3Sopenharmony_ci virtual void GenerateCode(Circuit *circuit, const ControlFlowGraph &graph, const CompilationConfig *cfg, 1834514f5e3Sopenharmony_ci const MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile, 1844514f5e3Sopenharmony_ci const std::string &methodName, const FrameType frameType, 1854514f5e3Sopenharmony_ci bool enableOptInlining, bool enableBranchProfiling) = 0; 1864514f5e3Sopenharmony_ci}; 1874514f5e3Sopenharmony_ci 1884514f5e3Sopenharmony_ciclass CodeGenerator { 1894514f5e3Sopenharmony_cipublic: 1904514f5e3Sopenharmony_ci CodeGenerator(std::unique_ptr<CodeGeneratorImpl> &impl, const std::string& methodName) 1914514f5e3Sopenharmony_ci : impl_(std::move(impl)), methodName_(methodName) 1924514f5e3Sopenharmony_ci { 1934514f5e3Sopenharmony_ci } 1944514f5e3Sopenharmony_ci 1954514f5e3Sopenharmony_ci ~CodeGenerator() = default; 1964514f5e3Sopenharmony_ci 1974514f5e3Sopenharmony_ci void RunForStub(Circuit *circuit, const ControlFlowGraph &graph, size_t index, const CompilationConfig *cfg) 1984514f5e3Sopenharmony_ci { 1994514f5e3Sopenharmony_ci impl_->GenerateCodeForStub(circuit, graph, index, cfg); 2004514f5e3Sopenharmony_ci } 2014514f5e3Sopenharmony_ci 2024514f5e3Sopenharmony_ci const std::string& GetMethodName() const 2034514f5e3Sopenharmony_ci { 2044514f5e3Sopenharmony_ci return methodName_; 2054514f5e3Sopenharmony_ci } 2064514f5e3Sopenharmony_ci 2074514f5e3Sopenharmony_ci void Run(Circuit *circuit, const ControlFlowGraph &graph, const CompilationConfig *cfg, 2084514f5e3Sopenharmony_ci const MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile, const FrameType frameType, 2094514f5e3Sopenharmony_ci bool enableOptInlining, bool enableOptBranchProfiling) 2104514f5e3Sopenharmony_ci { 2114514f5e3Sopenharmony_ci impl_->GenerateCode(circuit, graph, cfg, methodLiteral, jsPandaFile, methodName_, frameType, 2124514f5e3Sopenharmony_ci enableOptInlining, enableOptBranchProfiling); 2134514f5e3Sopenharmony_ci } 2144514f5e3Sopenharmony_ci 2154514f5e3Sopenharmony_ciprivate: 2164514f5e3Sopenharmony_ci std::unique_ptr<CodeGeneratorImpl> impl_{nullptr}; 2174514f5e3Sopenharmony_ci std::string methodName_; 2184514f5e3Sopenharmony_ci}; 2194514f5e3Sopenharmony_ci} // namespace panda::ecmascript::kungfu 2204514f5e3Sopenharmony_ci#endif // ECMASCRIPT_COMPILER_CODE_GENERATOR_H 221