1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "ecmascript/compiler/codegen/maple/litecg_codegen.h" 17#if defined(PANDA_TARGET_MACOS) || defined(PANDA_TARGET_IOS) 18#include "ecmascript/base/llvm_helper.h" 19#endif 20 21#include <cstring> 22#include <iomanip> 23#include <vector> 24 25#include "ecmascript/compiler/call_signature.h" 26#include "ecmascript/compiler/codegen/maple/litecg_ir_builder.h" 27#include "ecmascript/compiler/codegen/maple/maple_be/include/litecg/litecg.h" 28#include "ecmascript/compiler/codegen/maple/maple_be/include/litecg/lmir_builder.h" 29#include "ecmascript/compiler/compiler_log.h" 30#include "ecmascript/ecma_macros.h" 31#include "ecmascript/mem/region.h" 32#include "ecmascript/object_factory.h" 33#include "ecmascript/stackmap/litecg/litecg_stackmap_type.h" 34#include "ecmascript/stackmap/llvm/llvm_stackmap_parser.h" 35#ifdef JIT_ENABLE_CODE_SIGN 36#include "jit_buffer_integrity.h" 37#include "ecmascript/compiler/jit_signcode.h" 38#endif 39 40namespace panda::ecmascript::kungfu { 41#ifdef JIT_ENABLE_CODE_SIGN 42using namespace panda::ecmascript::kungfu; 43using namespace OHOS::Security::CodeSign; 44#endif 45class CompilerLog; 46 47using namespace panda::ecmascript; 48 49LiteCGAssembler::LiteCGAssembler(LMIRModule &module, CodeInfo::CodeSpaceOnDemand &codeSpaceOnDemand, 50 const std::vector<std::string> &litecgOptions) 51 : Assembler(codeSpaceOnDemand), lmirModule(module), litecgOptions(litecgOptions) {} 52 53static uint8_t *AllocateCodeSection(void *object, uint32_t size, [[maybe_unused]] uint32_t alignment, 54 const std::string §ionName) 55{ 56 struct CodeInfo &state = *static_cast<struct CodeInfo *>(object); 57 return state.AllocaCodeSection(size, sectionName.c_str()); 58} 59 60static uint8_t *AllocateCodeSectionOnDemand(void *object, uint32_t size, [[maybe_unused]] uint32_t alignment, 61 const std::string §ionName) 62{ 63 struct CodeInfo &state = *static_cast<struct CodeInfo *>(object); 64 return state.AllocaCodeSectionOnDemand(size, sectionName.c_str()); 65} 66 67static void SaveFunc2Addr(void *object, std::string funcName, uint32_t address) 68{ 69 struct CodeInfo &state = *static_cast<struct CodeInfo *>(object); 70 state.SaveFunc2Addr(funcName, address); 71} 72 73static void SaveFunc2FPtoPrevSPDelta(void *object, std::string funcName, int32_t fp2PrevSpDelta) 74{ 75 struct CodeInfo &state = *static_cast<struct CodeInfo *>(object); 76 state.SaveFunc2FPtoPrevSPDelta(funcName, fp2PrevSpDelta); 77} 78 79static void SaveFunc2CalleeOffsetInfo(void *object, std::string funcName, kungfu::CalleeRegAndOffsetVec calleeRegInfo) 80{ 81 struct CodeInfo &state = *static_cast<struct CodeInfo *>(object); 82 state.SaveFunc2CalleeOffsetInfo(funcName, calleeRegInfo); 83} 84 85static void SavePC2DeoptInfo(void *object, uint64_t pc, std::vector<uint8_t> deoptInfo) 86{ 87 struct CodeInfo &state = *static_cast<struct CodeInfo *>(object); 88 state.SavePC2DeoptInfo(pc, deoptInfo); 89} 90 91void SavePC2CallSiteInfo(void *object, uint64_t pc, std::vector<uint8_t> callSiteInfo) 92{ 93 struct CodeInfo &state = *static_cast<struct CodeInfo *>(object); 94 state.SavePC2CallSiteInfo(pc, callSiteInfo); 95} 96 97void LiteCGAssembler::Run(const CompilerLog &log, [[maybe_unused]] bool fastCompileMode, bool isJit) 98{ 99 std::vector<std::string> options(litecgOptions); 100 if (log.OutputASM()) { 101 options.push_back("--verbose-asm"); 102 } 103 if (log.OutputLLIR()) { 104 options.push_back("-verbose"); 105 } 106 maple::litecg::LiteCG liteCG(*lmirModule.GetModule(), options); 107#ifdef ARK_LITECG_DEBUG 108 if (log.OutputLLIR()) { 109 std::string irFileName = lmirModule.GetModule()->GetFileName() + ".mpl"; 110 liteCG.DumpIRToFile(irFileName); 111 } 112#endif 113 liteCG.SetupLiteCGEmitMemoryManager(&codeInfo_, isJit ? AllocateCodeSectionOnDemand : AllocateCodeSection, 114 SaveFunc2Addr, SaveFunc2FPtoPrevSPDelta, SaveFunc2CalleeOffsetInfo, 115 SavePC2DeoptInfo, SavePC2CallSiteInfo); 116#ifdef JIT_ENABLE_CODE_SIGN 117 isJit &= JitFort::IsResourceAvailable(); 118 if (isJit) { 119 JitCodeSignerBase *jitSigner = CreateJitCodeSigner(JitBufferIntegrityLevel::Level0); 120 JitSignCode *singleton = JitSignCode::GetInstance(); 121 singleton->Reset(); 122 singleton->SetCodeSigner(jitSigner); 123 singleton->SetKind(1); 124 } 125#endif 126 liteCG.DoCG(isJit); 127} 128 129void LiteCGIRGeneratorImpl::GenerateCodeForStub(Circuit *circuit, const ControlFlowGraph &graph, size_t index, 130 const CompilationConfig *cfg) 131{ 132 (void)circuit; 133 (void)graph; 134 (void)index; 135 (void)cfg; 136} 137 138void LiteCGIRGeneratorImpl::GenerateCode(Circuit *circuit, const ControlFlowGraph &graph, const CompilationConfig *cfg, 139 const panda::ecmascript::MethodLiteral *methodLiteral, 140 const JSPandaFile *jsPandaFile, const std::string &methodName, 141 const FrameType frameType, 142 bool enableOptInlining, [[maybe_unused]]bool enableBranchProfiling) 143{ 144 circuit->SetFrameType(frameType); 145 CallSignature::CallConv conv; 146 if (methodLiteral->IsFastCall()) { 147 conv = CallSignature::CallConv::CCallConv; 148 } else { 149 conv = CallSignature::CallConv::WebKitJSCallConv; 150 } 151 LiteCGIRBuilder builder(&graph, circuit, module_, cfg, conv, enableLog_, enableOptInlining, methodLiteral, 152 jsPandaFile, methodName); 153 builder.Build(); 154} 155 156void LiteCGAssembler::CollectAnStackMap(CGStackMapInfo &stackMapInfo) 157{ 158 auto &liteCGStackMapInfo = static_cast<LiteCGStackMapInfo&>(stackMapInfo); 159 const auto &codeInfo = GetCodeInfo(); 160 liteCGStackMapInfo.AppendCallSiteInfo(codeInfo.GetPC2CallsiteInfo()); 161 liteCGStackMapInfo.AppendDeoptInfo(codeInfo.GetPC2DeoptInfo()); 162} 163} // namespace panda::ecmascript::kungfu 164