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 "runtime_calls.h"
17 #include "llvm_ark_interface.h"
18
19 #include <llvm/IR/IRBuilder.h>
20
21 #include "libpandabase/macros.h"
22
23 namespace panda::llvmbackend::runtime_calls {
24
GetAddressToTLS(llvm::IRBuilder<> * builder,LLVMArkInterface * arkInterface,uintptr_t tlsOffset)25 llvm::Value *GetAddressToTLS(llvm::IRBuilder<> *builder, LLVMArkInterface *arkInterface, uintptr_t tlsOffset)
26 {
27 auto threadRegValue = GetThreadRegValue(builder, arkInterface);
28 auto threadRegPtr = builder->CreateIntToPtr(threadRegValue, builder->getPtrTy());
29 return builder->CreateConstInBoundsGEP1_64(builder->getInt8Ty(), threadRegPtr, tlsOffset);
30 }
31
LoadTLSValue(llvm::IRBuilder<> * builder,LLVMArkInterface * arkInterface,uintptr_t tlsOffset,llvm::Type * type)32 llvm::Value *LoadTLSValue(llvm::IRBuilder<> *builder, LLVMArkInterface *arkInterface, uintptr_t tlsOffset,
33 llvm::Type *type)
34 {
35 auto addr = GetAddressToTLS(builder, arkInterface, tlsOffset);
36 return builder->CreateLoad(type, addr);
37 }
38
CreateEntrypointCallCommon(llvm::IRBuilder<> * builder,llvm::Value * threadRegValue,LLVMArkInterface * arkInterface,EntrypointId eid,llvm::ArrayRef<llvm::Value * > arguments)39 llvm::CallInst *CreateEntrypointCallCommon(llvm::IRBuilder<> *builder, llvm::Value *threadRegValue,
40 LLVMArkInterface *arkInterface, EntrypointId eid,
41 llvm::ArrayRef<llvm::Value *> arguments)
42 {
43 auto tlsOffset = arkInterface->GetEntrypointTlsOffset(eid);
44 auto [function_proto, function_name] = arkInterface->GetEntrypointCallee(eid);
45
46 auto threadRegPtr = builder->CreateIntToPtr(threadRegValue, builder->getPtrTy());
47 auto addr = builder->CreateConstInBoundsGEP1_64(builder->getInt8Ty(), threadRegPtr, tlsOffset);
48 auto callee = builder->CreateLoad(builder->getPtrTy(), addr, function_name + "_addr");
49
50 auto calleeFuncTy = llvm::cast<llvm::FunctionType>(function_proto);
51 auto call = builder->CreateCall(calleeFuncTy, callee, arguments);
52 return call;
53 }
54
GetThreadRegValue(llvm::IRBuilder<> * builder,LLVMArkInterface * arkInterface)55 llvm::Value *GetThreadRegValue(llvm::IRBuilder<> *builder, LLVMArkInterface *arkInterface)
56 {
57 ASSERT(!arkInterface->IsIrtocMode());
58 auto func = builder->GetInsertBlock()->getParent();
59 auto &ctx = func->getContext();
60 auto regMd = llvm::MDNode::get(ctx, {llvm::MDString::get(ctx, arkInterface->GetThreadRegister())});
61 auto threadReg = llvm::MetadataAsValue::get(ctx, regMd);
62 auto readReg =
63 llvm::Intrinsic::getDeclaration(func->getParent(), llvm::Intrinsic::read_register, builder->getInt64Ty());
64 return builder->CreateCall(readReg, {threadReg});
65 }
66
GetRealFrameRegValue(llvm::IRBuilder<> * builder,LLVMArkInterface * arkInterface)67 llvm::Value *GetRealFrameRegValue(llvm::IRBuilder<> *builder, LLVMArkInterface *arkInterface)
68 {
69 ASSERT(!arkInterface->IsIrtocMode());
70 auto func = builder->GetInsertBlock()->getParent();
71 auto &ctx = func->getContext();
72 auto regMd = llvm::MDNode::get(ctx, {llvm::MDString::get(ctx, arkInterface->GetFramePointerRegister())});
73 auto frameReg = llvm::MetadataAsValue::get(ctx, regMd);
74 auto readReg =
75 llvm::Intrinsic::getDeclaration(func->getParent(), llvm::Intrinsic::read_register, builder->getInt64Ty());
76 return builder->CreateCall(readReg, {frameReg});
77 }
78
79 } // namespace panda::llvmbackend::runtime_calls
80