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
22 #include "ecmascript/compiler/codegen/maple/maple_be/include/litecg/litecg.h"
23 #include "ecmascript/compiler/compiler_log.h"
24 #include "ecmascript/stackmap/litecg/litecg_stackmap_type.h"
25 #ifdef JIT_ENABLE_CODE_SIGN
26 #include "jit_buffer_integrity.h"
27 #include "ecmascript/compiler/jit_signcode.h"
28 #endif
29
30 namespace panda::ecmascript::kungfu {
31 #ifdef JIT_ENABLE_CODE_SIGN
32 using namespace panda::ecmascript::kungfu;
33 using namespace OHOS::Security::CodeSign;
34 #endif
35 class CompilerLog;
36
37 using namespace panda::ecmascript;
38
LiteCGAssembler(LMIRModule & module,CodeInfo::CodeSpaceOnDemand & codeSpaceOnDemand,const std::vector<std::string> & litecgOptions)39 LiteCGAssembler::LiteCGAssembler(LMIRModule &module, CodeInfo::CodeSpaceOnDemand &codeSpaceOnDemand,
40 const std::vector<std::string> &litecgOptions)
41 : Assembler(codeSpaceOnDemand, false), lmirModule(module), litecgOptions(litecgOptions) {}
42
AllocateCodeSection(void * object,uint32_t size,uint32_t alignment,const std::string & sectionName)43 static uint8_t *AllocateCodeSection(void *object, uint32_t size, [[maybe_unused]] uint32_t alignment,
44 const std::string §ionName)
45 {
46 struct CodeInfo &state = *static_cast<struct CodeInfo *>(object);
47 return state.AllocaCodeSection(size, sectionName.c_str());
48 }
49
AllocateCodeSectionOnDemand(void * object,uint32_t size,uint32_t alignment,const std::string & sectionName)50 static uint8_t *AllocateCodeSectionOnDemand(void *object, uint32_t size, [[maybe_unused]] uint32_t alignment,
51 const std::string §ionName)
52 {
53 struct CodeInfo &state = *static_cast<struct CodeInfo *>(object);
54 return state.AllocaCodeSectionOnDemand(size, sectionName.c_str());
55 }
56
SaveFunc2Addr(void * object,std::string funcName,uint32_t address)57 static void SaveFunc2Addr(void *object, std::string funcName, uint32_t address)
58 {
59 struct CodeInfo &state = *static_cast<struct CodeInfo *>(object);
60 state.SaveFunc2Addr(funcName, address);
61 }
62
SaveFunc2FPtoPrevSPDelta(void * object,std::string funcName,int32_t fp2PrevSpDelta)63 static void SaveFunc2FPtoPrevSPDelta(void *object, std::string funcName, int32_t fp2PrevSpDelta)
64 {
65 struct CodeInfo &state = *static_cast<struct CodeInfo *>(object);
66 state.SaveFunc2FPtoPrevSPDelta(funcName, fp2PrevSpDelta);
67 }
68
SaveFunc2CalleeOffsetInfo(void * object,std::string funcName,kungfu::CalleeRegAndOffsetVec calleeRegInfo)69 static void SaveFunc2CalleeOffsetInfo(void *object, std::string funcName, kungfu::CalleeRegAndOffsetVec calleeRegInfo)
70 {
71 struct CodeInfo &state = *static_cast<struct CodeInfo *>(object);
72 state.SaveFunc2CalleeOffsetInfo(funcName, calleeRegInfo);
73 }
74
SavePC2DeoptInfo(void * object,uint64_t pc,std::vector<uint8_t> deoptInfo)75 static void SavePC2DeoptInfo(void *object, uint64_t pc, std::vector<uint8_t> deoptInfo)
76 {
77 struct CodeInfo &state = *static_cast<struct CodeInfo *>(object);
78 state.SavePC2DeoptInfo(pc, deoptInfo);
79 }
80
SavePC2CallSiteInfo(void * object,uint64_t pc,std::vector<uint8_t> callSiteInfo)81 void SavePC2CallSiteInfo(void *object, uint64_t pc, std::vector<uint8_t> callSiteInfo)
82 {
83 struct CodeInfo &state = *static_cast<struct CodeInfo *>(object);
84 state.SavePC2CallSiteInfo(pc, callSiteInfo);
85 }
86
Run(const CompilerLog & log,bool fastCompileMode,bool isJit)87 void LiteCGAssembler::Run(const CompilerLog &log, [[maybe_unused]] bool fastCompileMode, bool isJit)
88 {
89 std::vector<std::string> options(litecgOptions);
90 if (log.OutputASM()) {
91 options.push_back("--verbose-asm");
92 }
93 if (log.OutputLLIR()) {
94 options.push_back("-verbose");
95 }
96 maple::litecg::LiteCG liteCG(*lmirModule.GetModule(), options);
97 #ifdef ARK_LITECG_DEBUG
98 if (log.OutputLLIR()) {
99 std::string irFileName = lmirModule.GetModule()->GetFileName() + ".mpl";
100 liteCG.DumpIRToFile(irFileName);
101 }
102 #endif
103 liteCG.SetupLiteCGEmitMemoryManager(&codeInfo_, isJit ? AllocateCodeSectionOnDemand : AllocateCodeSection,
104 SaveFunc2Addr, SaveFunc2FPtoPrevSPDelta, SaveFunc2CalleeOffsetInfo,
105 SavePC2DeoptInfo, SavePC2CallSiteInfo);
106 liteCG.SetAotCodeCommentFile(GetAotCodeCommentFile());
107 #ifdef JIT_ENABLE_CODE_SIGN
108 isJit &= JitFort::IsResourceAvailable();
109 if (isJit) {
110 JitCodeSigner *jitSigner = CreateJitCodeSigner();
111 JitSignCode *singleton = JitSignCode::GetInstance();
112 singleton->Reset();
113 singleton->SetCodeSigner(jitSigner);
114 singleton->SetKind(1);
115 }
116 #endif
117 liteCG.DoCG(isJit);
118 }
119
GenerateCodeForStub(Circuit * circuit,const ControlFlowGraph & graph,size_t index,const CompilationConfig * cfg)120 void LiteCGIRGeneratorImpl::GenerateCodeForStub(Circuit *circuit, const ControlFlowGraph &graph, size_t index,
121 const CompilationConfig *cfg)
122 {
123 (void)circuit;
124 (void)graph;
125 (void)index;
126 (void)cfg;
127 }
128
GenerateCode(Circuit * circuit,const ControlFlowGraph & graph,const CompilationConfig * cfg,const panda::ecmascript::MethodLiteral * methodLiteral,const JSPandaFile * jsPandaFile,const std::string & methodName,const FrameType frameType,bool enableOptInlining,bool enableBranchProfiling)129 void LiteCGIRGeneratorImpl::GenerateCode(Circuit *circuit, const ControlFlowGraph &graph, const CompilationConfig *cfg,
130 const panda::ecmascript::MethodLiteral *methodLiteral,
131 const JSPandaFile *jsPandaFile, const std::string &methodName,
132 const FrameType frameType,
133 bool enableOptInlining, [[maybe_unused]]bool enableBranchProfiling)
134 {
135 circuit->SetFrameType(frameType);
136 CallSignature::CallConv conv;
137 if (methodLiteral->IsFastCall()) {
138 conv = CallSignature::CallConv::CCallConv;
139 } else {
140 conv = CallSignature::CallConv::WebKitJSCallConv;
141 }
142 LiteCGIRBuilder builder(&graph, circuit, module_, cfg, conv, enableLog_, enableOptInlining, methodLiteral,
143 jsPandaFile, methodName);
144 builder.Build();
145 }
146
CollectAnStackMap(CGStackMapInfo & stackMapInfo)147 void LiteCGAssembler::CollectAnStackMap(CGStackMapInfo &stackMapInfo)
148 {
149 auto &liteCGStackMapInfo = static_cast<LiteCGStackMapInfo&>(stackMapInfo);
150 const auto &codeInfo = GetCodeInfo();
151 liteCGStackMapInfo.AppendCallSiteInfo(codeInfo.GetPC2CallsiteInfo());
152 liteCGStackMapInfo.AppendDeoptInfo(codeInfo.GetPC2DeoptInfo());
153 }
154 } // namespace panda::ecmascript::kungfu
155