1 /* 2 * Copyright (c) 2021 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 #ifndef ECMASCRIPT_COMPILER_LLVM_IR_BUILDER_H 17 #define ECMASCRIPT_COMPILER_LLVM_IR_BUILDER_H 18 19 #include <map> 20 #include <memory> 21 #include <unordered_map> 22 #include <vector> 23 24 #include "ecmascript/compiler/circuit.h" 25 #include "ecmascript/compiler/gate.h" 26 #include "ecmascript/compiler/stub_builder.h" 27 #include "ecmascript/compiler/call_signature.h" 28 #include "ecmascript/compiler/common_stubs.h" 29 #include "ecmascript/compiler/interpreter_stub.h" 30 #include "ecmascript/compiler/rt_call_signature.h" 31 #include "ecmascript/jspandafile/method_literal.h" 32 #include "llvm-c/DebugInfo.h" 33 #include "llvm-c/Core.h" 34 35 namespace panda::ecmascript::kungfu { 36 using OperandsVector = std::set<int>; 37 class BasicBlock; 38 class DebugInfo; 39 using BasicBlockMap = std::map<int, std::unique_ptr<BasicBlock>>; 40 class LLVMIRBuilder; 41 using HandleType = void(LLVMIRBuilder::*)(GateRef gate); 42 43 enum class MachineRep { 44 K_NONE, 45 K_BIT, 46 K_WORD8, 47 K_WORD16, 48 K_WORD32, 49 K_WORD64, 50 // FP representations must be last, and in order of increasing size. 51 K_FLOAT32, 52 K_FLOAT64, 53 K_SIMD128, 54 K_PTR_1, // Tagged Pointer 55 K_META, 56 }; 57 58 class BasicBlock { 59 public: BasicBlock(int id)60 explicit BasicBlock(int id) : id_(id) 61 { 62 predecessors_ = {}; 63 successors_ = {}; 64 impl_ = nullptr; 65 } 66 GetId()67 int GetId() const 68 { 69 return id_; 70 } 71 72 template<class T> GetImpl()73 inline T *GetImpl() const 74 { 75 return static_cast<T *>(impl_); 76 } 77 SetImpl(void * impl)78 inline void SetImpl(void *impl) 79 { 80 impl_ = impl; 81 } 82 83 template<class T> ResetImpl()84 inline void ResetImpl() 85 { 86 if (impl_) { 87 delete GetImpl<T>(); 88 impl_ = nullptr; 89 } 90 } 91 ~BasicBlock() = default; 92 93 private: 94 std::vector<BasicBlock *> predecessors_ {}; 95 std::vector<BasicBlock *> successors_ {}; 96 int id_ {-1}; 97 void *impl_ {nullptr}; 98 }; 99 100 struct NotMergedPhiDesc { 101 int predBBId; 102 GateRef operand; 103 LLVMValueRef phi; 104 }; 105 106 struct BasicBlockImpl { 107 LLVMBasicBlockRef lBB_ = nullptr; 108 LLVMBasicBlockRef continuation = nullptr; 109 bool started = false; 110 bool ended = false; 111 std::vector<NotMergedPhiDesc> unmergedPhis_; 112 }; 113 114 class LLVMModule { 115 public: 116 LLVMModule(NativeAreaAllocator* allocator, const std::string &name, bool logDbg, const std::string &triple); 117 ~LLVMModule(); 118 void SetUpForCommonStubs(); 119 void SetUpForBytecodeHandlerStubs(); 120 void SetUpForBuiltinsStubs(); 121 LLVMValueRef AddFunc(const panda::ecmascript::MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile); GetModule()122 LLVMModuleRef GetModule() const 123 { 124 return module_; 125 } 126 LLVMTypeRef GetFuncType(const CallSignature *stubDescriptor); 127 128 LLVMTypeRef GenerateFuncType(const std::vector<LLVMValueRef> ¶ms, const CallSignature *stubDescriptor); 129 SetFunction(size_t index,LLVMValueRef func,bool isFastCall)130 void SetFunction(size_t index, LLVMValueRef func, bool isFastCall) 131 { 132 funcIndexMap_.emplace_back(std::make_tuple(index, func, isFastCall)); 133 } 134 GetFunction(size_t index)135 LLVMValueRef GetFunction(size_t index) 136 { 137 // next optimization can be performed 138 for (auto &it: funcIndexMap_) { 139 if (std::get<0>(it) == index) { 140 return std::get<1>(it); 141 } 142 } 143 return nullptr; 144 } 145 Is64Bit()146 bool Is64Bit() const 147 { 148 return is64Bit_; 149 } 150 Is32Bit()151 bool Is32Bit() const 152 { 153 return !is64Bit_; 154 } 155 GetFuncCount()156 size_t GetFuncCount() const 157 { 158 return funcIndexMap_.size(); 159 } 160 161 template<class Callback> IteratefuncIndexMap(const Callback & cb)162 void IteratefuncIndexMap(const Callback &cb) const 163 { 164 for (auto record : funcIndexMap_) { 165 // 2: 3nd param 166 cb(std::get<0>(record), std::get<1>(record), std::get<2>(record)); 167 } 168 } 169 GetCSign(size_t index)170 const CallSignature *GetCSign(size_t index) const 171 { 172 return callSigns_[index]; 173 } 174 GetTripleStr()175 const std::string &GetTripleStr() const 176 { 177 return tripleStr_; 178 } 179 GetCSigns()180 const std::vector<const CallSignature*> &GetCSigns() const 181 { 182 return callSigns_; 183 } 184 GetContext()185 LLVMContextRef GetContext() const 186 { 187 return context_; 188 } 189 GetDFileMD()190 LLVMMetadataRef GetDFileMD() const 191 { 192 return dFileMD_; 193 } 194 GetDIBuilder()195 LLVMDIBuilderRef GetDIBuilder() const 196 { 197 return dBuilder_; 198 } 199 200 LLVMValueRef GetDeoptFunction(); 201 GetDebugInfo()202 DebugInfo* GetDebugInfo() const 203 { 204 return debugInfo_; 205 } 206 GetTriple()207 Triple GetTriple() const 208 { 209 return triple_; 210 } 211 212 std::string GetFuncName(const panda::ecmascript::MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile); 213 214 static constexpr int kDeoptEntryOffset = 0; 215 GetVoidT()216 LLVMTypeRef GetVoidT() const 217 { 218 return voidT_; 219 } 220 GetInt1T()221 LLVMTypeRef GetInt1T() const 222 { 223 return int1T_; 224 } 225 GetInt8T()226 LLVMTypeRef GetInt8T() const 227 { 228 return int8T_; 229 } 230 GetInt16T()231 LLVMTypeRef GetInt16T() const 232 { 233 return int16T_; 234 } 235 GetInt32T()236 LLVMTypeRef GetInt32T() const 237 { 238 return int32T_; 239 } 240 GetInt64T()241 LLVMTypeRef GetInt64T() const 242 { 243 return int64T_; 244 } 245 GetFloatT()246 LLVMTypeRef GetFloatT() const 247 { 248 return floatT_; 249 } 250 GetDoubleT()251 LLVMTypeRef GetDoubleT() const 252 { 253 return doubleT_; 254 } 255 GetTaggedPtrT()256 LLVMTypeRef GetTaggedPtrT() const 257 { 258 return taggedPtrT_; 259 } 260 GetTaggedHPtrT()261 LLVMTypeRef GetTaggedHPtrT() const 262 { 263 return taggedHPtrT_; 264 } 265 GetRawPtrT()266 LLVMTypeRef GetRawPtrT() const 267 { 268 return rawPtrT_; 269 } 270 private: 271 LLVMValueRef AddAndGetFunc(const CallSignature *stubDescriptor); 272 void InitialLLVMFuncTypeAndFuncByModuleCSigns(); 273 LLVMTypeRef ConvertLLVMTypeFromVariableType(VariableType type); 274 LLVMTypeRef NewLType(MachineType machineType, GateType gateType); 275 // index: 276 // stub scenario - sequence of function adding to llvmModule 277 // aot scenario - method Id of function generated by panda files 278 std::vector<std::tuple<size_t, LLVMValueRef, bool>> funcIndexMap_; 279 std::vector<const CallSignature *> callSigns_; 280 LLVMModuleRef module_ {nullptr}; 281 LLVMContextRef context_ {nullptr}; 282 LLVMMetadataRef dFileMD_ {nullptr}; 283 LLVMMetadataRef dUnitMD_ {nullptr}; 284 LLVMDIBuilderRef dBuilder_ {nullptr}; 285 DebugInfo* debugInfo_ {nullptr}; 286 287 LLVMTypeRef voidT_ {nullptr}; 288 LLVMTypeRef int1T_ {nullptr}; 289 LLVMTypeRef int8T_ {nullptr}; 290 LLVMTypeRef int16T_ {nullptr}; 291 LLVMTypeRef int32T_ {nullptr}; 292 LLVMTypeRef int64T_ {nullptr}; 293 LLVMTypeRef floatT_ {nullptr}; 294 LLVMTypeRef doubleT_ {nullptr}; 295 LLVMTypeRef taggedHPtrT_ {nullptr}; 296 LLVMTypeRef taggedPtrT_ {nullptr}; 297 LLVMTypeRef rawPtrT_ {nullptr}; 298 299 std::string tripleStr_; 300 bool is64Bit_ {false}; 301 Triple triple_; 302 }; 303 304 305 #define OPCODES(V) \ 306 V(Call, (GateRef gate, const std::vector<GateRef> &inList, OpCode op)) \ 307 V(RuntimeCall, (GateRef gate, const std::vector<GateRef> &inList)) \ 308 V(RuntimeCallWithArgv, (GateRef gate, const std::vector<GateRef> &inList)) \ 309 V(NoGcRuntimeCall, (GateRef gate, const std::vector<GateRef> &inList)) \ 310 V(BytecodeCall, (GateRef gate, const std::vector<GateRef> &inList)) \ 311 V(Alloca, (GateRef gate)) \ 312 V(Block, (int id, const OperandsVector &predecessors)) \ 313 V(Goto, (int block, int bbout)) \ 314 V(Parameter, (GateRef gate)) \ 315 V(Constant, (GateRef gate, std::bitset<64> value)) \ 316 V(ConstString, (GateRef gate, const ChunkVector<char> &str)) \ 317 V(RelocatableData, (GateRef gate, uint64_t value)) \ 318 V(ZExtInt, (GateRef gate, GateRef e1)) \ 319 V(SExtInt, (GateRef gate, GateRef e1)) \ 320 V(FPExt, (GateRef gate, GateRef e1)) \ 321 V(FPTrunc, (GateRef gate, GateRef e1)) \ 322 V(Load, (GateRef gate, GateRef base)) \ 323 V(Store, (GateRef gate, GateRef base, GateRef value)) \ 324 V(IntRev, (GateRef gate, GateRef e1)) \ 325 V(Add, (GateRef gate, GateRef e1, GateRef e2)) \ 326 V(Sub, (GateRef gate, GateRef e1, GateRef e2)) \ 327 V(Mul, (GateRef gate, GateRef e1, GateRef e2)) \ 328 V(FloatDiv, (GateRef gate, GateRef e1, GateRef e2)) \ 329 V(IntDiv, (GateRef gate, GateRef e1, GateRef e2)) \ 330 V(UDiv, (GateRef gate, GateRef e1, GateRef e2)) \ 331 V(IntOr, (GateRef gate, GateRef e1, GateRef e2)) \ 332 V(IntAnd, (GateRef gate, GateRef e1, GateRef e2)) \ 333 V(IntXor, (GateRef gate, GateRef e1, GateRef e2)) \ 334 V(IntLsr, (GateRef gate, GateRef e1, GateRef e2)) \ 335 V(IntAsr, (GateRef gate, GateRef e1, GateRef e2)) \ 336 V(Int32LessThanOrEqual, (GateRef gate, GateRef e1, GateRef e2)) \ 337 V(Cmp, (GateRef gate, GateRef e1, GateRef e2)) \ 338 V(Branch, (GateRef gate, GateRef cmp, GateRef btrue, GateRef bfalse)) \ 339 V(Switch, (GateRef gate, GateRef input, const std::vector<GateRef> &outList)) \ 340 V(SwitchCase, (GateRef gate, GateRef switchBranch, GateRef out)) \ 341 V(Phi, (GateRef gate, const std::vector<GateRef> &srcGates)) \ 342 V(Return, (GateRef gate, GateRef popCount, const std::vector<GateRef> &operands)) \ 343 V(ReturnVoid, (GateRef gate)) \ 344 V(CastIntXToIntY, (GateRef gate, GateRef e1)) \ 345 V(ChangeInt32ToDouble, (GateRef gate, GateRef e1)) \ 346 V(ChangeUInt32ToDouble, (GateRef gate, GateRef e1)) \ 347 V(ChangeDoubleToInt32, (GateRef gate, GateRef e1)) \ 348 V(BitCast, (GateRef gate, GateRef e1)) \ 349 V(IntLsl, (GateRef gate, GateRef e1, GateRef e2)) \ 350 V(Mod, (GateRef gate, GateRef e1, GateRef e2)) \ 351 V(ChangeTaggedPointerToInt64, (GateRef gate, GateRef e1)) \ 352 V(ChangeInt64ToTagged, (GateRef gate, GateRef e1)) \ 353 V(DeoptCheck, (GateRef gate)) \ 354 V(TruncFloatToInt, (GateRef gate, GateRef e1)) \ 355 V(AddWithOverflow, (GateRef gate, GateRef e1, GateRef e2)) \ 356 V(SubWithOverflow, (GateRef gate, GateRef e1, GateRef e2)) \ 357 V(MulWithOverflow, (GateRef gate, GateRef e1, GateRef e2)) \ 358 V(ExtractValue, (GateRef gate, GateRef e1, GateRef e2)) \ 359 V(Sqrt, (GateRef gate, GateRef e1)) \ 360 V(ReadSp, (GateRef gate)) 361 362 // runtime/common stub ID, opcodeOffset for bc stub 363 using StubIdType = std::variant<RuntimeStubCSigns::ID, CommonStubCSigns::ID, LLVMValueRef>; 364 365 class LLVMIRBuilder { 366 public: 367 LLVMIRBuilder(const std::vector<std::vector<GateRef>> *schedule, Circuit *circuit, 368 LLVMModule *module, LLVMValueRef function, const CompilationConfig *cfg, 369 CallSignature::CallConv callConv, bool enableLog, bool isFastCallAot, const std::string &funcName); 370 ~LLVMIRBuilder(); 371 void Build(); 372 373 private: 374 #define DECLAREVISITOPCODE(name, signature) void Visit##name signature; OPCODES(DECLAREVISITOPCODE)375 OPCODES(DECLAREVISITOPCODE) 376 #undef DECLAREVISITOPCODE 377 #define DECLAREHANDLEOPCODE(name, ignore) void Handle##name(GateRef gate); 378 OPCODES(DECLAREHANDLEOPCODE) 379 #undef DECLAREHANDLEOPCODE 380 381 bool IsPrologue(int bbId) const 382 { 383 return bbId == 0; 384 } 385 void LinkToLLVMCfg(int bbId, const OperandsVector &predecessors); 386 BasicBlock *EnsureBB(int id); 387 LLVMValueRef CallingFp(LLVMModuleRef &module, LLVMBuilderRef &builder, bool isCaller); 388 LLVMValueRef GetCurrentSP(); 389 LLVMValueRef ReadRegister(LLVMModuleRef &module, LLVMBuilderRef &builder, LLVMMetadataRef meta); 390 void GenPrologue(); 391 LLVMBasicBlockRef EnsureLBB(BasicBlock *bb) const; 392 BasicBlockImpl *EnsureBBImpl(BasicBlock *bb) const; 393 void SetToCfg(BasicBlock *bb) const; 394 395 LLVMTypeRef GetMachineRepType(MachineRep rep) const; 396 int FindBasicBlock(GateRef gate) const; 397 void EndCurrentBlock() const; 398 void Finish(); 399 400 void ProcessPhiWorkList(); 401 void InitializeHandlers(); 402 std::string LLVMValueToString(LLVMValueRef val) const; 403 404 LLVMTypeRef ConvertLLVMTypeFromGate(GateRef gate) const; 405 int64_t GetBitWidthFromMachineType(MachineType machineType) const; 406 LLVMValueRef PointerAdd(LLVMValueRef baseAddr, LLVMValueRef offsetInByte, LLVMTypeRef rep); 407 LLVMValueRef CanonicalizeToInt(LLVMValueRef value) const; 408 LLVMValueRef CanonicalizeToPtr(LLVMValueRef value) const; 409 LLVMValueRef CanonicalizeToPtr(LLVMValueRef value, LLVMTypeRef ptrType) const; 410 LLVMValueRef GetCurrentFrameType(LLVMValueRef currentSpFrameAddr); 411 void SetFunctionCallConv(); 412 IsLogEnabled()413 bool IsLogEnabled() const 414 { 415 return enableLog_; 416 } 417 LLVMValueRef GetFunction(LLVMValueRef glue, const CallSignature *signature, LLVMValueRef rtbaseoffset, 418 const std::string &realName = "") const; 419 LLVMValueRef GetCallee(const std::vector<GateRef> &inList, const CallSignature *signature, 420 const std::string &realName = ""); 421 LLVMValueRef GetFunctionFromGlobalValue(LLVMValueRef glue, const CallSignature *signature, 422 LLVMValueRef reloc) const; 423 bool IsInterpreted() const; 424 bool IsOptimized() const; 425 bool IsOptimizedJSFunction() const; 426 void SetGCLeafFunction(LLVMValueRef call); 427 void SetCallConvAttr(const CallSignature *calleeDescriptor, LLVMValueRef call); 428 bool IsHeapPointerType(LLVMTypeRef valueType); 429 GetVoidT()430 LLVMTypeRef GetVoidT() const 431 { 432 return llvmModule_->GetVoidT(); 433 } 434 GetInt1T()435 LLVMTypeRef GetInt1T() const 436 { 437 return llvmModule_->GetInt1T(); 438 } 439 GetInt8T()440 LLVMTypeRef GetInt8T() const 441 { 442 return llvmModule_->GetInt8T(); 443 } 444 GetInt16T()445 LLVMTypeRef GetInt16T() const 446 { 447 return llvmModule_->GetInt16T(); 448 } 449 GetInt32T()450 LLVMTypeRef GetInt32T() const 451 { 452 return llvmModule_->GetInt32T(); 453 } 454 GetInt64T()455 LLVMTypeRef GetInt64T() const 456 { 457 return llvmModule_->GetInt64T(); 458 } 459 GetFloatT()460 LLVMTypeRef GetFloatT() const 461 { 462 return llvmModule_->GetFloatT(); 463 } 464 GetDoubleT()465 LLVMTypeRef GetDoubleT() const 466 { 467 return llvmModule_->GetDoubleT(); 468 } 469 GetTaggedPtrT()470 LLVMTypeRef GetTaggedPtrT() const 471 { 472 return llvmModule_->GetTaggedPtrT(); 473 } 474 GetTaggedHPtrT()475 LLVMTypeRef GetTaggedHPtrT() const 476 { 477 return llvmModule_->GetTaggedHPtrT(); 478 } 479 GetRawPtrT()480 LLVMTypeRef GetRawPtrT() const 481 { 482 return llvmModule_->GetRawPtrT(); 483 } 484 485 private: 486 enum class CallInputs : size_t { 487 DEPEND = 0, 488 TARGET, 489 GLUE, 490 FIRST_PARAMETER 491 }; 492 enum class CallExceptionKind : bool { 493 HAS_PC_OFFSET = true, 494 NO_PC_OFFSET = false 495 }; 496 GetDIBuilder()497 LLVMDIBuilderRef GetDIBuilder() const 498 { 499 return llvmModule_ == nullptr ? nullptr : llvmModule_->GetDIBuilder(); 500 } 501 502 unsigned GetPtrAddressSpace(LLVMValueRef v) const; 503 bool IsLInteger(LLVMValueRef v) const; 504 bool IsLPointer(LLVMValueRef v) const; 505 LLVMRealPredicate ConvertLLVMPredicateFromFCMP(FCmpCondition cond); 506 LLVMIntPredicate ConvertLLVMPredicateFromICMP(ICmpCondition cond); 507 LLVMValueRef GetGlue(const std::vector<GateRef> &inList); 508 LLVMValueRef GetLeaveFrameOffset(LLVMValueRef glue); 509 LLVMValueRef GetRTStubOffset(LLVMValueRef glue, int index); 510 LLVMValueRef GetCoStubOffset(LLVMValueRef glue, int index); 511 LLVMValueRef GetBCStubOffset(LLVMValueRef glue); 512 LLVMValueRef GetBCDebugStubOffset(LLVMValueRef glue); 513 LLVMValueRef GetBuiltinsStubOffset(LLVMValueRef glue); 514 LLVMValueRef GetBaseOffset(GateRef gate, LLVMValueRef glue); 515 CallExceptionKind GetCallExceptionKind(size_t index, OpCode op) const; 516 void ComputeArgCountAndPCOffset(size_t &actualNumArgs, LLVMValueRef &pcOffset, 517 const std::vector<GateRef> &inList, CallExceptionKind kind); 518 void SaveLexicalEnvOnOptJSFuncFrame(LLVMValueRef value); 519 void SaveJSFuncOnOptJSFuncFrame(LLVMValueRef value); 520 void SaveFrameTypeOnFrame(FrameType frameType, LLVMBuilderRef builder); 521 void UpdateLeaveFrame(LLVMValueRef glue); 522 LLVMTypeRef GetExperimentalDeoptTy(); 523 LLVMValueRef GetExperimentalDeopt(LLVMModuleRef &module); 524 void GenDeoptEntry(LLVMModuleRef &module); 525 LLVMMetadataRef GetFunctionTypeMD(LLVMMetadataRef dFile); 526 bool SetDebugInfo(GateRef g, LLVMValueRef r); 527 LLVMValueRef ConvertToTagged(GateRef gate); 528 LLVMValueRef ConvertBoolToTaggedBoolean(GateRef gate); 529 LLVMValueRef ConvertInt32ToTaggedInt(GateRef gate); 530 LLVMValueRef ConvertInt32ToTaggedInt(LLVMValueRef value); 531 LLVMValueRef ConvertFloat64ToTaggedDouble(GateRef gate); 532 void SaveDeoptVregInfo(std::vector<LLVMValueRef> &values, int32_t index, size_t curDepth, size_t shift, 533 GateRef gate); 534 void SaveDeoptVregInfoWithI64(std::vector<LLVMValueRef> &values, int32_t index, size_t curDepth, size_t shift, 535 GateRef gate); 536 int LookupPredBB(GateRef start, int bbID); 537 538 const CompilationConfig *compCfg_ {nullptr}; 539 const std::vector<std::vector<GateRef>> *scheduledGates_ {nullptr}; 540 const Circuit *circuit_ {nullptr}; 541 GateAccessor acc_; 542 BasicBlock *currentBb_ {nullptr}; 543 int lineNumber_ {0}; 544 545 LLVMModuleRef module_ {nullptr}; 546 LLVMContextRef context_ {nullptr}; 547 LLVMValueRef function_ {nullptr}; 548 LLVMBuilderRef builder_ {nullptr}; 549 std::map<GateId, int> instID2bbID_; 550 BasicBlockMap bbID2BB_; 551 552 std::vector<BasicBlock *> phiRebuildWorklist_; 553 LLVMModule *llvmModule_ {nullptr}; 554 std::unordered_map<GateRef, LLVMValueRef> gate2LValue_; 555 std::unordered_map<OpCode, HandleType> opHandlers_; 556 std::set<OpCode> illegalOpHandlers_; 557 int slotSize_ {-1}; 558 LLVMTypeRef slotType_ {nullptr}; 559 CallSignature::CallConv callConv_ = CallSignature::CallConv::CCallConv; 560 bool enableLog_ {false}; 561 bool isFastCallAot_ {false}; 562 LLVMMetadataRef dFuncMD_ {nullptr}; 563 }; 564 } // namespace panda::ecmascript::kungfu 565 #endif // ECMASCRIPT_COMPILER_LLVM_IR_BUILDER_H 566