• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-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 "builtins.h"
17 #include "llvm_ark_interface.h"
18 #include "runtime_calls.h"
19 #include "utils.h"
20 #include "lowering/gc_barriers.h"
21 #include "lowering/metadata.h"
22 
23 #include "compiler/optimizer/ir/basicblock.h"
24 #include "compiler/optimizer/ir/inst.h"
25 
26 #include <llvm/IR/DebugInfoMetadata.h>
27 #include <llvm/IR/MDBuilder.h>
28 #include <llvm/ADT/SmallVector.h>
29 #include <llvm/Transforms/Utils/BasicBlockUtils.h>
30 
31 using ark::llvmbackend::LLVMArkInterface;
32 using ark::llvmbackend::Metadata::BranchWeights::LIKELY_BRANCH_WEIGHT;
33 using ark::llvmbackend::Metadata::BranchWeights::UNLIKELY_BRANCH_WEIGHT;
34 using ark::llvmbackend::runtime_calls::GetThreadRegValue;
35 using ark::llvmbackend::utils::CopyDebugLoc;
36 using ark::llvmbackend::utils::CopyDeoptBundle;
37 
38 namespace {
CreateEntrypointCallHelper(llvm::IRBuilder<> * builder,ark::compiler::RuntimeInterface::EntrypointId id,llvm::ArrayRef<llvm::Value * > arguments,LLVMArkInterface * arkInterface,llvm::CallInst * inst)39 llvm::CallInst *CreateEntrypointCallHelper(llvm::IRBuilder<> *builder, ark::compiler::RuntimeInterface::EntrypointId id,
40                                            llvm::ArrayRef<llvm::Value *> arguments, LLVMArkInterface *arkInterface,
41                                            llvm::CallInst *inst)
42 {
43     auto threadReg = GetThreadRegValue(builder, arkInterface);
44     auto call = ark::llvmbackend::runtime_calls::CreateEntrypointCallCommon(
45         builder, threadReg, arkInterface, static_cast<ark::llvmbackend::runtime_calls::EntrypointId>(id), arguments,
46         CopyDeoptBundle(inst));
47     CopyDebugLoc(inst, call);
48     if (inst->hasFnAttr("inline-info")) {
49         call->addFnAttr(inst->getFnAttr("inline-info"));
50     }
51 
52     return call;
53 }
PostWRBHelper(llvm::IRBuilder<> * builder,llvm::CallInst * inst,LLVMArkInterface * arkInterface)54 llvm::Value *PostWRBHelper(llvm::IRBuilder<> *builder, llvm::CallInst *inst, LLVMArkInterface *arkInterface)
55 {
56     auto mem = inst->getOperand(0U);
57     auto offset = inst->getOperand(1U);
58     auto value = inst->getOperand(2U);
59 
60     ASSERT(!arkInterface->IsIrtocMode());
61     auto threadReg = GetThreadRegValue(builder, arkInterface);
62     ark::llvmbackend::gc_barriers::EmitPostWRB(builder, mem, offset, value, arkInterface, threadReg, nullptr);
63     return nullptr;
64 }
FastClassLoadingHelper(llvm::IRBuilder<> * builder,LLVMArkInterface * arkInterface,llvm::BasicBlock * continuation)65 llvm::Value *FastClassLoadingHelper(llvm::IRBuilder<> *builder, LLVMArkInterface *arkInterface,
66                                     llvm::BasicBlock *continuation)
67 {
68     auto function = continuation->getParent();
69 
70     llvm::Value *methodValue = function->arg_begin();
71 
72     auto offset = arkInterface->GetClassOffset();
73     auto dataPtr = builder->CreateConstInBoundsGEP1_32(builder->getInt8Ty(), methodValue, offset);
74     auto classAddr = builder->CreateLoad(builder->getInt32Ty(), dataPtr);
75     auto result = builder->CreateIntToPtr(classAddr, builder->getPtrTy());
76     builder->CreateBr(continuation);
77     return result;
78 }
79 
SlowClassLoadingHelper(llvm::IRBuilder<> * builder,llvm::CallInst * inst,LLVMArkInterface * arkInterface,llvm::BasicBlock * continuation,bool forceInit)80 llvm::Value *SlowClassLoadingHelper(llvm::IRBuilder<> *builder, llvm::CallInst *inst, LLVMArkInterface *arkInterface,
81                                     llvm::BasicBlock *continuation, bool forceInit)
82 {
83     using llvm::Value;
84     auto eid = forceInit ? ark::compiler::RuntimeInterface::EntrypointId::CLASS_INIT_RESOLVER
85                          : ark::compiler::RuntimeInterface::EntrypointId::CLASS_RESOLVER;
86     auto initialBb = builder->GetInsertBlock();
87     auto function = initialBb->getParent();
88     auto module = function->getParent();
89     auto &ctx = builder->getContext();
90 
91     // Helper functions
92     auto createUniqBasicBlockName = [&initialBb](const std::string &suffix) {
93         return ark::llvmbackend::LLVMArkInterface::GetUniqueBasicBlockName(initialBb->getName().str(), suffix);
94     };
95     auto createBasicBlock = [&ctx, &initialBb, &createUniqBasicBlockName](const std::string &suffix) {
96         auto name = createUniqBasicBlockName(suffix);
97         auto func = initialBb->getParent();
98         return llvm::BasicBlock::Create(ctx, name, func);
99     };
100 
101     // Helper types & variables
102     auto aotGot = module->getGlobalVariable("__aot_got");
103     auto arrayType = llvm::ArrayType::get(builder->getInt64Ty(), 0);
104 
105     // Input args
106     auto slotIdVal = inst->getOperand(1U);
107 
108     /* Start generating code */
109 
110     auto klassPtr = builder->CreateInBoundsGEP(arrayType, aotGot, {builder->getInt32(0), slotIdVal});
111     auto cachedKlassTmp = builder->CreateLoad(builder->getInt64Ty(), klassPtr, "cached_klass");
112     auto cachedKlass = builder->CreateIntToPtr(cachedKlassTmp, builder->getPtrTy());
113     auto resolutionRequired = builder->CreateIsNull(cachedKlass, "resolutionRequired");
114 
115     auto weights = llvm::MDBuilder(ctx).createBranchWeights(UNLIKELY_BRANCH_WEIGHT,  // if resolution_required
116                                                             LIKELY_BRANCH_WEIGHT);   // else
117     auto slowPath = createBasicBlock(std::string("slow_path"));
118     builder->CreateCondBr(resolutionRequired, slowPath, continuation, weights);
119 
120     builder->SetInsertPoint(slowPath);
121 
122     auto freshKlass = CreateEntrypointCallHelper(builder, eid, {klassPtr}, arkInterface, inst);
123     ASSERT(freshKlass->getCallingConv() == llvm::CallingConv::C);
124     freshKlass->setCallingConv(llvm::CallingConv::ArkResolver);
125     builder->CreateBr(continuation);
126 
127     builder->SetInsertPoint(&continuation->front());
128     auto result = builder->CreatePHI(builder->getPtrTy(), 2U, "klass");
129     result->addIncoming(cachedKlass, initialBb);
130     result->addIncoming(freshKlass, slowPath);
131 
132     return result;
133 }
134 
LowerLoadClassHelper(llvm::IRBuilder<> * builder,llvm::CallInst * inst,LLVMArkInterface * arkInterface,bool forceInit)135 llvm::Value *LowerLoadClassHelper(llvm::IRBuilder<> *builder, llvm::CallInst *inst, LLVMArkInterface *arkInterface,
136                                   bool forceInit)
137 {
138     auto initialBb = builder->GetInsertBlock();
139     auto function = initialBb->getParent();
140 
141     auto typeIdVal = inst->getOperand(0U);
142 
143     llvm::BasicBlock *slowPath = initialBb;
144     llvm::BasicBlock *continuation = llvm::SplitBlock(initialBb, inst);
145 
146     slowPath->back().eraseFromParent();
147     builder->SetInsertPoint(slowPath);
148 
149     if (!llvm::isa<llvm::ConstantInt>(typeIdVal)) {
150         return SlowClassLoadingHelper(builder, inst, arkInterface, continuation, forceInit);
151     }
152 
153     // Try simple constant case
154     auto functionMd = function->getMetadata(LLVMArkInterface::FUNCTION_MD_CLASS_ID);
155     ASSERT(functionMd != nullptr);
156     auto functionMdCasted = llvm::dyn_cast<llvm::ConstantAsMetadata>(functionMd->getOperand(0U))->getValue();
157     auto methodKlassId = llvm::cast<llvm::ConstantInt>(functionMdCasted)->getZExtValue();
158     auto requiredKlassId = llvm::cast<llvm::ConstantInt>(typeIdVal)->getZExtValue();
159 
160     return methodKlassId == requiredKlassId
161                ? FastClassLoadingHelper(builder, arkInterface, continuation)
162                : SlowClassLoadingHelper(builder, inst, arkInterface, continuation, forceInit);
163 }
164 
PreWRBHelper(llvm::IRBuilder<> * builder,llvm::CallInst * inst,LLVMArkInterface * arkInterface)165 llvm::Value *PreWRBHelper(llvm::IRBuilder<> *builder, llvm::CallInst *inst, LLVMArkInterface *arkInterface)
166 {
167     ASSERT(!arkInterface->IsIrtocMode());
168     auto initialBb = builder->GetInsertBlock();
169     auto mem = inst->getOperand(0U);
170     auto op1 = inst->getOperand(1U);
171     ASSERT(llvm::isa<llvm::ConstantInt>(op1));
172     auto isConst = llvm::cast<llvm::ConstantInt>(op1);
173     auto isVolatileMem = !isConst->isZero();
174 
175     llvm::BasicBlock *continuation = llvm::SplitBlock(initialBb, inst);
176 
177     initialBb->back().eraseFromParent();
178     builder->SetInsertPoint(initialBb);
179     auto threadRegValue = GetThreadRegValue(builder, arkInterface);
180     ark::llvmbackend::gc_barriers::EmitPreWRB(builder, mem, isVolatileMem, continuation, arkInterface, threadRegValue);
181     return nullptr;
182 }
183 }  // namespace
184 
185 namespace ark::llvmbackend::builtins {
186 
LenArray(llvm::Module * module)187 llvm::Function *LenArray(llvm::Module *module)
188 {
189     auto function = module->getFunction(LEN_ARRAY_BUILTIN);
190     if (function != nullptr) {
191         return function;
192     }
193     auto type = llvm::FunctionType::get(llvm::Type::getInt32Ty(module->getContext()),
194                                         {llvm::PointerType::get(module->getContext(), LLVMArkInterface::GC_ADDR_SPACE),
195                                          llvm::Type::getInt32Ty(module->getContext())},
196                                         false);
197     function = llvm::Function::Create(type, llvm::Function::ExternalLinkage, LEN_ARRAY_BUILTIN, module);
198     function->setDoesNotThrow();
199     function->setSectionPrefix(BUILTIN_SECTION);
200     function->addFnAttr(llvm::Attribute::ReadNone);
201     function->addFnAttr(llvm::Attribute::WillReturn);
202     return function;
203 }
204 
KeepThis(llvm::Module * module)205 llvm::Function *KeepThis(llvm::Module *module)
206 {
207     auto function = module->getFunction(KEEP_THIS_BUILTIN);
208     if (function != nullptr) {
209         return function;
210     }
211 
212     auto type =
213         llvm::FunctionType::get(llvm::Type::getVoidTy(module->getContext()),
214                                 {llvm::PointerType::get(module->getContext(), LLVMArkInterface::GC_ADDR_SPACE)}, false);
215     function = llvm::Function::Create(type, llvm::Function::ExternalLinkage, KEEP_THIS_BUILTIN, module);
216     function->setDoesNotThrow();
217     function->setSectionPrefix(BUILTIN_SECTION);
218     function->addFnAttr(llvm::Attribute::WillReturn);
219     return function;
220 }
221 
BarrierReturnVoid(llvm::Module * module)222 llvm::Function *BarrierReturnVoid(llvm::Module *module)
223 {
224     auto function = module->getFunction(BARRIER_RETURN_VOID_BUILTIN);
225     if (function != nullptr) {
226         return function;
227     }
228 
229     auto type = llvm::FunctionType::get(llvm::Type::getVoidTy(module->getContext()), {}, false);
230     function = llvm::Function::Create(type, llvm::Function::ExternalLinkage, BARRIER_RETURN_VOID_BUILTIN, module);
231     function->setDoesNotThrow();
232     function->setSectionPrefix(BUILTIN_SECTION);
233     function->addFnAttr(llvm::Attribute::WillReturn);
234     return function;
235 }
236 
LoadClass(llvm::Module * module)237 llvm::Function *LoadClass(llvm::Module *module)
238 {
239     auto function = module->getFunction(LOAD_CLASS_BUILTIN);
240     if (function != nullptr) {
241         return function;
242     }
243 
244     auto type = llvm::FunctionType::get(
245         llvm::PointerType::get(module->getContext(), 0),
246         {llvm::Type::getInt32Ty(module->getContext()), llvm::Type::getInt32Ty(module->getContext())}, false);
247     function = llvm::Function::Create(type, llvm::Function::ExternalLinkage, LOAD_CLASS_BUILTIN, module);
248     function->setDoesNotThrow();
249     function->setSectionPrefix(BUILTIN_SECTION);
250     return function;
251 }
252 
LoadInitClass(llvm::Module * module)253 llvm::Function *LoadInitClass(llvm::Module *module)
254 {
255     auto function = module->getFunction(LOAD_INIT_CLASS_BUILTIN);
256     if (function != nullptr) {
257         return function;
258     }
259 
260     auto type = llvm::FunctionType::get(
261         llvm::PointerType::get(module->getContext(), 0),
262         {llvm::Type::getInt32Ty(module->getContext()), llvm::Type::getInt32Ty(module->getContext())}, false);
263     function = llvm::Function::Create(type, llvm::Function::ExternalLinkage, LOAD_INIT_CLASS_BUILTIN, module);
264     function->setDoesNotThrow();
265     function->setSectionPrefix(BUILTIN_SECTION);
266     return function;
267 }
268 
PreWRB(llvm::Module * module,unsigned addrSpace)269 llvm::Function *PreWRB(llvm::Module *module, unsigned addrSpace)
270 {
271     auto builtinName = (addrSpace == LLVMArkInterface::GC_ADDR_SPACE) ? PRE_WRB_GCADR_BUILTIN : PRE_WRB_BUILTIN;
272     auto function = module->getFunction(builtinName);
273     if (function != nullptr) {
274         return function;
275     }
276     auto &ctx = module->getContext();
277     auto type = llvm::FunctionType::get(llvm::Type::getVoidTy(ctx),
278                                         {llvm::PointerType::get(ctx, addrSpace), llvm::Type::getInt1Ty(ctx)}, false);
279     function = llvm::Function::Create(type, llvm::Function::ExternalLinkage, builtinName, module);
280     function->setDoesNotThrow();
281     function->setSectionPrefix(BUILTIN_SECTION);
282     function->addFnAttr(llvm::Attribute::ArgMemOnly);
283     function->addFnAttr(llvm::Attribute::WillReturn);
284     function->addParamAttr(0U, llvm::Attribute::ReadOnly);
285     return function;
286 }
287 
PostWRB(llvm::Module * module,unsigned addrSpace)288 llvm::Function *PostWRB(llvm::Module *module, unsigned addrSpace)
289 {
290     auto builtinName = (addrSpace == LLVMArkInterface::GC_ADDR_SPACE) ? POST_WRB_GCADR_BUILTIN : POST_WRB_BUILTIN;
291     auto function = module->getFunction(builtinName);
292     if (function != nullptr) {
293         return function;
294     }
295     auto &ctx = module->getContext();
296     auto type = llvm::FunctionType::get(llvm::Type::getVoidTy(ctx),
297                                         {llvm::PointerType::get(ctx, addrSpace), llvm::Type::getInt32Ty(ctx),
298                                          llvm::PointerType::get(ctx, LLVMArkInterface::GC_ADDR_SPACE)},
299                                         false);
300     function = llvm::Function::Create(type, llvm::Function::ExternalLinkage, builtinName, module);
301     function->setDoesNotThrow();
302     function->setSectionPrefix(BUILTIN_SECTION);
303     function->addFnAttr(llvm::Attribute::ArgMemOnly);
304     function->addFnAttr(llvm::Attribute::WillReturn);
305     function->addParamAttr(0U, llvm::Attribute::ReadNone);
306     function->addParamAttr(2U, llvm::Attribute::ReadNone);
307     return function;
308 }
309 
LoadString(llvm::Module * module)310 llvm::Function *LoadString(llvm::Module *module)
311 {
312     auto function = module->getFunction(LOAD_STRING_BUILTIN);
313     if (function != nullptr) {
314         return function;
315     }
316 
317     auto type = llvm::FunctionType::get(
318         llvm::PointerType::get(module->getContext(), LLVMArkInterface::GC_ADDR_SPACE),
319         {llvm::Type::getInt32Ty(module->getContext()), llvm::Type::getInt32Ty(module->getContext())}, false);
320     function = llvm::Function::Create(type, llvm::Function::ExternalLinkage, LOAD_STRING_BUILTIN, module);
321     function->setDoesNotThrow();
322     function->setSectionPrefix(BUILTIN_SECTION);
323     return function;
324 }
325 
ResolveVirtual(llvm::Module * module)326 llvm::Function *ResolveVirtual(llvm::Module *module)
327 {
328     auto function = module->getFunction(RESOLVE_VIRTUAL_BUILTIN);
329     if (function != nullptr) {
330         return function;
331     }
332     auto type = llvm::FunctionType::get(llvm::PointerType::get(module->getContext(), 0),
333                                         {llvm::PointerType::get(module->getContext(), LLVMArkInterface::GC_ADDR_SPACE),
334                                          llvm::Type::getInt64Ty(module->getContext()),
335                                          llvm::PointerType::get(module->getContext(), 0)},
336                                         false);
337     function = llvm::Function::Create(type, llvm::Function::ExternalLinkage, RESOLVE_VIRTUAL_BUILTIN, module);
338     function->setDoesNotThrow();
339     function->setSectionPrefix(BUILTIN_SECTION);
340     return function;
341 }
342 
LowerLenArray(llvm::IRBuilder<> * builder,llvm::CallInst * inst)343 llvm::Value *LowerLenArray(llvm::IRBuilder<> *builder, llvm::CallInst *inst)
344 {
345     auto array = inst->getOperand(0U);
346     auto offset = inst->getOperand(1U);
347 
348     auto rawPtr = builder->CreateInBoundsGEP(builder->getInt8Ty(), array, offset);
349 
350     return builder->CreateLoad(builder->getInt32Ty(), rawPtr);
351 }
352 
LowerLoadString(llvm::IRBuilder<> * builder,llvm::CallInst * inst,LLVMArkInterface * arkInterface)353 llvm::Value *LowerLoadString(llvm::IRBuilder<> *builder, llvm::CallInst *inst, LLVMArkInterface *arkInterface)
354 {
355     auto module = inst->getModule();
356     auto function = inst->getFunction();
357     auto aotGot = module->getGlobalVariable("__aot_got");
358     auto arrayType = llvm::ArrayType::get(builder->getInt64Ty(), 0);
359 
360     // Input args
361     auto typeId = inst->getOperand(0U);
362     auto slotId = inst->getOperand(1U);
363 
364     auto slotPtr = builder->CreateInBoundsGEP(arrayType, aotGot, {builder->getInt32(0), slotId});
365     auto str = builder->CreateLoad(builder->getInt64Ty(), slotPtr);
366     auto limit = compiler::RuntimeInterface::RESOLVE_STRING_AOT_COUNTER_LIMIT;
367     auto cmp = builder->CreateICmpULT(str, builder->getInt64(limit));
368 
369     llvm::Instruction *ifi;
370     llvm::Instruction *elsi;
371     auto weights =
372         llvm::MDBuilder(inst->getContext()).createBranchWeights(UNLIKELY_BRANCH_WEIGHT, LIKELY_BRANCH_WEIGHT);
373     SplitBlockAndInsertIfThenElse(cmp, inst, &ifi, &elsi, weights);
374 
375     ifi->getParent()->setName("load_str_slow");
376     elsi->getParent()->setName("load_str_fast");
377 
378     builder->SetInsertPoint(ifi);
379     auto method = function->arg_begin();
380     auto eid = compiler::RuntimeInterface::EntrypointId::RESOLVE_STRING_AOT;
381     auto freshStr = CreateEntrypointCallHelper(builder, eid, {method, typeId, slotPtr}, arkInterface, inst);
382     freshStr->setName("fresh_str");
383 
384     builder->SetInsertPoint(elsi);
385     auto cachedStr = builder->CreateIntToPtr(str, inst->getType());
386     cachedStr->setName("cached_str");
387 
388     builder->SetInsertPoint(inst);
389     auto resStr = builder->CreatePHI(inst->getType(), 2U);
390     resStr->addIncoming(freshStr, ifi->getParent());
391     resStr->addIncoming(cachedStr, elsi->getParent());
392     return resStr;
393 }
394 
LowerResolveVirtual(llvm::IRBuilder<> * builder,llvm::CallInst * inst,LLVMArkInterface * arkInterface)395 llvm::Value *LowerResolveVirtual(llvm::IRBuilder<> *builder, llvm::CallInst *inst, LLVMArkInterface *arkInterface)
396 {
397     llvm::CallInst *entrypointAddress;
398     auto method = inst->getFunction()->arg_begin();
399     auto thiz = inst->getOperand(0U);
400     auto methodId = inst->getOperand(1U);
401     ASSERT(!llvm::isa<llvm::PoisonValue>(thiz));
402     if (!arkInterface->IsArm64() || !llvm::isa<llvm::ConstantInt>(methodId)) {
403         static constexpr auto ENTRYPOINT_ID = compiler::RuntimeInterface::EntrypointId::RESOLVE_VIRTUAL_CALL_AOT;
404         auto offset = builder->getInt64(0);
405         entrypointAddress =
406             CreateEntrypointCallHelper(builder, ENTRYPOINT_ID, {method, thiz, methodId, offset}, arkInterface, inst);
407     } else {
408         auto offset = inst->getOperand(2U);
409         static constexpr auto ENTRYPOINT_ID = compiler::RuntimeInterface::EntrypointId::INTF_INLINE_CACHE;
410         entrypointAddress =
411             CreateEntrypointCallHelper(builder, ENTRYPOINT_ID, {method, thiz, methodId, offset}, arkInterface, inst);
412         ASSERT(entrypointAddress->getCallingConv() == llvm::CallingConv::C);
413         entrypointAddress->setCallingConv(llvm::CallingConv::ArkFast4);
414     }
415 
416     return builder->CreateIntToPtr(entrypointAddress, builder->getPtrTy());
417 }
418 
LowerBuiltin(llvm::IRBuilder<> * builder,llvm::CallInst * inst,LLVMArkInterface * arkInterface)419 llvm::Value *LowerBuiltin(llvm::IRBuilder<> *builder, llvm::CallInst *inst, LLVMArkInterface *arkInterface)
420 {
421     auto function = inst->getCalledFunction();
422     const auto &funcName = function->getName();
423     if (funcName.equals(LEN_ARRAY_BUILTIN)) {
424         return LowerLenArray(builder, inst);
425     }
426     if (funcName.equals(LOAD_CLASS_BUILTIN)) {
427         return LowerLoadClassHelper(builder, inst, arkInterface, false);
428     }
429     if (funcName.equals(LOAD_INIT_CLASS_BUILTIN)) {
430         return LowerLoadClassHelper(builder, inst, arkInterface, true);
431     }
432     if (funcName.equals(PRE_WRB_GCADR_BUILTIN) || funcName.equals(PRE_WRB_BUILTIN)) {
433         return PreWRBHelper(builder, inst, arkInterface);
434     }
435     if (funcName.equals(POST_WRB_GCADR_BUILTIN) || funcName.equals(POST_WRB_BUILTIN)) {
436         return PostWRBHelper(builder, inst, arkInterface);
437     }
438     if (funcName.equals(LOAD_STRING_BUILTIN)) {
439         return LowerLoadString(builder, inst, arkInterface);
440     }
441     if (funcName.equals(RESOLVE_VIRTUAL_BUILTIN)) {
442         return LowerResolveVirtual(builder, inst, arkInterface);
443     }
444     if (funcName.equals(BARRIER_RETURN_VOID_BUILTIN)) {
445         return nullptr;
446     }
447     if (funcName.equals(KEEP_THIS_BUILTIN)) {
448         return nullptr;
449     }
450     UNREACHABLE();
451 }
452 }  // namespace ark::llvmbackend::builtins
453