Lines Matching +full:guest +full:- +full:side
1 //===-- AArch64Arm64ECCallLowering.cpp - Lower Arm64EC calls ----*- C++ -*-===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
16 //===----------------------------------------------------------------------===//
44 static cl::opt<bool> LowerDirectToIndirect("arm64ec-lower-direct-to-indirect",
46 static cl::opt<bool> GenerateThunks("arm64ec-generate-thunks", cl::Hidden,
132 // for entry/guest exit thunks, we just call the Arm64 function directly.
156 if (FT->isVarArg()) {
158 // with the following type on the ARM side:
164 // x0-x3 is the arguments be stored in registers.
168 // On the x64 side, it's the same except that x5 isn't set.
173 // If the X64 side is sret, but the ARM side isn't, we pass an extra value
174 // to/from the X64 side, and let SelectionDAG transform it into a memory
178 // x0-x3
192 // FIXME: x5 isn't actually used by the x64 side; revisit once we
204 if (I == FT->getNumParams()) {
209 for (unsigned E = FT->getNumParams(); I != E; ++I) {
220 canonicalizeThunkType(FT->getParamType(I), ParamAlign,
233 Type *T = FT->getReturnType();
241 if (T->isVoidTy()) {
242 if (FT->getNumParams()) {
246 if (FT->getNumParams() > 1) {
266 // FIXME: Sanity-check the sret type; if it's an integer or pointer,
278 Arm64ArgTypes.push_back(FT->getParamType(0));
279 X64ArgTypes.push_back(FT->getParamType(0));
296 if (X64RetTy->isPointerTy()) {
315 llvm::Type::getIntNTy(M->getContext(), SizeInBytes * 8),
324 if (T->isFloatTy()) {
329 if (T->isDoubleTy()) {
334 if (T->isFloatingPointTy()) {
339 auto &DL = M->getDataLayout();
342 if (StructTy->getNumElements() == 1)
343 T = StructTy->getElementType(0);
345 if (T->isArrayTy()) {
346 Type *ElementTy = T->getArrayElementType();
347 uint64_t ElementCnt = T->getArrayNumElements();
350 if (ElementTy->isFloatTy() || ElementTy->isDoubleTy()) {
351 Out << (ElementTy->isFloatTy() ? "F" : "D") << TotalSizeBytes;
362 } else if (T->isFloatingPointTy()) {
368 if ((T->isIntegerTy() || T->isPointerTy()) && DL.getTypeSizeInBits(T) <= 64) {
401 if (Function *F = M->getFunction(ExitThunkName))
406 F->setCallingConv(CallingConv::ARM64EC_Thunk_Native);
407 F->setSection(".wowthk$aa");
408 F->setComdat(M->getOrInsertComdat(ExitThunkName));
410 F->addFnAttr("frame-pointer", "all");
414 if (FT->getNumParams()) {
418 F->addParamAttr(1, SRet);
422 BasicBlock *BB = BasicBlock::Create(M->getContext(), "", F);
425 M->getOrInsertGlobal("__os_arm64x_dispatch_call_no_redirect", PtrTy);
427 auto &DL = M->getDataLayout();
432 Args.push_back(F->arg_begin());
434 Type *RetTy = Arm64Ty->getReturnType();
435 if (RetTy != X64Ty->getReturnType()) {
446 make_range(F->arg_begin() + 1, F->arg_end()),
447 make_range(X64Ty->param_begin() + X64TyOffset, X64Ty->param_end()),
476 assert(Args.back()->getType() == X64ArgType);
482 Call->setCallingConv(CallingConv::ARM64EC_Thunk_X64);
485 if (RetTy != X64Ty->getReturnType()) {
497 if (RetTy->isVoidTy())
511 getThunkType(F->getFunctionType(), F->getAttributes(),
514 if (Function *F = M->getFunction(EntryThunkName))
519 Thunk->setCallingConv(CallingConv::ARM64EC_Thunk_X64);
520 Thunk->setSection(".wowthk$aa");
521 Thunk->setComdat(M->getOrInsertComdat(EntryThunkName));
523 Thunk->addFnAttr("frame-pointer", "all");
525 BasicBlock *BB = BasicBlock::Create(M->getContext(), "", Thunk);
528 Type *RetTy = Arm64Ty->getReturnType();
529 Type *X64RetType = X64Ty->getReturnType();
531 bool TransformDirectToSRet = X64RetType->isVoidTy() && !RetTy->isVoidTy();
534 (F->isVarArg() ? 5 : Thunk->arg_size()) - ThunkArgOffset;
535 assert(ArgTranslations.size() == (F->isVarArg() ? 5 : PassthroughArgSize));
540 Value *Arg = Thunk->getArg(i + ThunkArgOffset);
541 Type *ArgTy = Arm64Ty->getParamType(i);
554 assert(Arg->getType() == ArgTy);
558 if (F->isVarArg()) {
565 Thunk->addParamAttr(5, Attribute::InReg);
566 Value *Arg = Thunk->getArg(5);
575 Value *Callee = Thunk->getArg(0);
579 auto SRetAttr = F->getAttributes().getParamAttr(0, Attribute::StructRet);
580 auto InRegAttr = F->getAttributes().getParamAttr(0, Attribute::InReg);
582 Thunk->addParamAttr(1, SRetAttr);
583 Call->addParamAttr(0, SRetAttr);
588 IRB.CreateStore(RetVal, IRB.CreateBitCast(Thunk->getArg(1), PtrTy));
599 if (X64RetType->isVoidTy())
607 // Builds the "guest exit thunk", a helper to call a function which may or may
608 // not be an exit thunk. (We optimistically assume non-dllimport function
615 getThunkType(F->getFunctionType(), F->getAttributes(),
618 auto MangledName = getArm64ECMangledFunctionName(F->getName().str());
619 assert(MangledName && "Can't guest exit to function that's already native");
628 GuestExit->setComdat(M->getOrInsertComdat(ThunkName));
629 GuestExit->setSection(".wowthk$aa");
630 GuestExit->setMetadata(
632 MDNode::get(M->getContext(),
633 MDString::get(M->getContext(), F->getName())));
634 GuestExit->setMetadata(
636 MDNode::get(M->getContext(),
637 MDString::get(M->getContext(), *MangledName)));
638 F->setMetadata("arm64ec_hasguestexit", MDNode::get(M->getContext(), {}));
639 BasicBlock *BB = BasicBlock::Create(M->getContext(), "", GuestExit);
644 if (cfguard_module_flag == 2 && !F->hasFnAttribute("guard_nocf"))
652 Function *Thunk = buildExitThunk(F->getFunctionType(), F->getAttributes());
658 GuardCheck->setCallingConv(CallingConv::CFGuard_Check);
662 for (Argument &Arg : GuestExit->args())
665 Call->setTailCallKind(llvm::CallInst::TCK_MustTail);
667 if (Call->getType()->isVoidTy())
672 auto SRetAttr = F->getAttributes().getParamAttr(0, Attribute::StructRet);
673 auto InRegAttr = F->getAttributes().getParamAttr(0, Attribute::InReg);
675 GuestExit->addParamAttr(0, SRetAttr);
676 Call->addParamAttr(0, SRetAttr);
687 Function *F = cast<Function>(MangledAlias->getAliasee());
689 getThunkType(F->getFunctionType(), F->getAttributes(),
692 std::string ThunkName(MangledAlias->getName());
701 GuestExit->setComdat(M->getOrInsertComdat(ThunkName));
702 GuestExit->setSection(".wowthk$aa");
703 BasicBlock *BB = BasicBlock::Create(M->getContext(), "", GuestExit);
711 buildExitThunk(F->getFunctionType(), F->getAttributes());
714 {UnmangledAlias, ExitThunk, UnmangledAlias->getAliasee()});
717 Dispatch->setCallingConv(CallingConv::CFGuard_Check);
721 for (Argument &Arg : GuestExit->args())
724 Call->setTailCallKind(llvm::CallInst::TCK_MustTail);
726 if (Call->getType()->isVoidTy())
731 auto SRetAttr = F->getAttributes().getParamAttr(0, Attribute::StructRet);
732 auto InRegAttr = F->getAttributes().getParamAttr(0, Attribute::InReg);
734 GuestExit->addParamAttr(0, SRetAttr);
735 Call->addParamAttr(0, SRetAttr);
738 MangledAlias->setAliasee(GuestExit);
744 assert(Triple(CB->getModule()->getTargetTriple()).isOSWindows() &&
748 Value *CalledOperand = CB->getCalledOperand();
753 if (auto Bundle = CB->getOperandBundle(LLVMContext::OB_funclet))
758 if (cfguard_module_flag == 2 && !CB->hasFnAttr("guard_nocf"))
766 Function *Thunk = buildExitThunk(CB->getFunctionType(), CB->getAttributes());
774 GuardCheck->setCallingConv(CallingConv::CFGuard_Check);
776 Value *GuardRetVal = B.CreateBitCast(GuardCheck, CalledOperand->getType());
777 CB->setCalledOperand(GuardRetVal);
788 mdconst::extract_or_null<ConstantInt>(M->getModuleFlag("cfguard")))
789 cfguard_module_flag = MD->getZExtValue();
791 PtrTy = PointerType::getUnqual(M->getContext());
792 I64Ty = Type::getInt64Ty(M->getContext());
793 VoidTy = Type::getVoidTy(M->getContext());
800 M->getOrInsertGlobal("__os_arm64x_check_icall_cfg", GuardFnPtrType);
802 M->getOrInsertGlobal("__os_arm64x_check_icall", GuardFnPtrType);
804 M->getOrInsertGlobal("__os_arm64x_dispatch_call", DispatchFnPtrType);
831 MDNode::get(M->getContext(),
832 MDString::get(M->getContext(),
834 A->setAliasee(&F);
837 A->setDLLStorageClass(GlobalValue::DLLExportStorageClass);
872 auto F = dyn_cast<Function>(GA ? GA->getAliasee() : O);
874 {O, buildExitThunk(F->getFunctionType(), F->getAttributes()),
876 if (!GA && !F->hasDLLImportStorageClass())
891 ConstantInt::get(M->getContext(), APInt(32, uint8_t(Thunk.Kind)))}));
894 llvm::ArrayType::get(ThunkMappingArrayElems[0]->getType(),
897 new GlobalVariable(Mod, ThunkMappingArray->getType(), /*isConstant*/ false,
921 MDNode::get(M->getContext(),
922 MDString::get(M->getContext(), F.getName())));
923 if (F.hasComdat() && F.getComdat()->getName() == F.getName()) {
924 Comdat *MangledComdat = M->getOrInsertComdat(MangledName.value());
926 to_vector(F.getComdat()->getUsers());
928 User->setComdat(MangledComdat);
941 if (!CB || CB->getCallingConv() == CallingConv::ARM64EC_Thunk_X64 ||
942 CB->isInlineAsm())
950 if (Function *F = CB->getCalledFunction()) {
951 if (!LowerDirectToIndirect || F->hasLocalLinkage() ||
952 F->isIntrinsic() || !F->isDeclaration())
960 if (GlobalAlias *A = dyn_cast<GlobalAlias>(CB->getCalledOperand())) {
963 CB->setCalledOperand(I->second);
964 DirectCalledFns.insert(I->first);