• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "libpandabase/macros.h"
17 #include "utils.h"
18 
19 namespace ark::llvmbackend::utils {
20 
GetMethodIdFromAttr(llvm::CallInst * call)21 int64_t GetMethodIdFromAttr(llvm::CallInst *call)
22 {
23     ASSERT(call != nullptr);
24     ASSERT(call->hasFnAttr("original-method-id"));
25     auto attr = call->getFnAttr("original-method-id");
26     int64_t integer = -1;
27     [[maybe_unused]] auto error = attr.getValueAsString().getAsInteger(0, integer);
28     ASSERT(!error);
29     ASSERT(integer >= 0);
30     return integer;
31 }
32 
HasCallsWithDeopt(llvm::Function & func)33 bool HasCallsWithDeopt(llvm::Function &func)
34 {
35     for (auto &block : func) {
36         for (auto &instruction : block) {
37             auto call = llvm::dyn_cast<llvm::CallInst>(&instruction);
38             if (call != nullptr && call->getOperandBundle(llvm::LLVMContext::OB_deopt)) {
39                 return true;
40             }
41         }
42     }
43     return false;
44 }
45 
CopyDeoptBundle(llvm::CallInst * from)46 llvm::SmallVector<llvm::OperandBundleDef> CopyDeoptBundle(llvm::CallInst *from)
47 {
48     llvm::SmallVector<llvm::OperandBundleDef, 1> bundles;
49     auto deoptBundle = from->getOperandBundle(llvm::LLVMContext::OB_deopt);
50     if (deoptBundle) {
51         llvm::SmallVector<llvm::Value *, 0> deoptVals;
52         for (auto &user : deoptBundle->Inputs) {
53             deoptVals.push_back(user.get());
54         }
55         bundles.push_back(llvm::OperandBundleDef {"deopt", deoptVals});
56     }
57     return bundles;
58 }
59 
CopyDebugLoc(llvm::CallInst * from,llvm::CallInst * to)60 void CopyDebugLoc(llvm::CallInst *from, llvm::CallInst *to)
61 {
62     auto &debugLoc = from->getDebugLoc();
63     auto line = debugLoc ? debugLoc.getLine() : 0;
64     auto inlinedAt = debugLoc ? debugLoc.getInlinedAt() : nullptr;
65     auto func = from->getParent()->getParent();
66     to->setDebugLoc(llvm::DILocation::get(func->getContext(), line, 1, func->getSubprogram(), inlinedAt));
67 }
68 
CreateLoadClassFromObject(llvm::Value * object,llvm::IRBuilder<> * builder,ark::llvmbackend::LLVMArkInterface * arkInterface)69 llvm::Value *CreateLoadClassFromObject(llvm::Value *object, llvm::IRBuilder<> *builder,
70                                        ark::llvmbackend::LLVMArkInterface *arkInterface)
71 {
72     ASSERT(object->getType()->isPointerTy());
73 
74     auto dataOff = arkInterface->GetObjectClassOffset();
75     auto ptrData = builder->CreateConstInBoundsGEP1_32(builder->getInt8Ty(), object, dataOff);
76     auto classAddress = builder->CreateLoad(builder->getInt32Ty(), ptrData);
77     return builder->CreateIntToPtr(classAddress, builder->getPtrTy());
78 }
79 
CreateLoadMethodUsingVTable(llvm::Value * thiz,llvm::Function * caller,size_t methodId,llvm::IRBuilder<> * builder,LLVMArkInterface * arkInterface)80 llvm::Value *CreateLoadMethodUsingVTable(llvm::Value *thiz, llvm::Function *caller, size_t methodId,
81                                          llvm::IRBuilder<> *builder, LLVMArkInterface *arkInterface)
82 {
83     ASSERT(thiz != nullptr);
84     ASSERT(caller != nullptr);
85 
86     auto classPtr = CreateLoadClassFromObject(thiz, builder, arkInterface);
87     auto offset = arkInterface->GetVTableOffset(caller, methodId);
88     auto methodPtr = builder->CreateConstInBoundsGEP1_32(builder->getInt8Ty(), classPtr, offset);
89     return builder->CreateLoad(builder->getPtrTy(), methodPtr);
90 }
91 
92 }  // namespace ark::llvmbackend::utils
93