40#define DEBUG_TYPE "arm64eccalllowering"
42STATISTIC(Arm64ECCallsLowered,
"Number of Arm64EC calls lowered");
51enum ThunkArgTranslation :
uint8_t {
60 ThunkArgTranslation Translation;
63class AArch64Arm64ECCallLowering :
public ModulePass {
66 AArch64Arm64ECCallLowering() : ModulePass(ID) {}
68 Function *buildExitThunk(FunctionType *FnTy, AttributeList Attrs);
70 void lowerCall(CallBase *CB);
71 Function *buildGuestExitThunk(Function *
F);
72 Function *buildPatchableThunk(GlobalAlias *UnmangledAlias,
73 GlobalAlias *MangledAlias);
75 DenseMap<GlobalAlias *, GlobalAlias *> &FnsMap);
76 bool runOnModule(
Module &M)
override;
80 FunctionType *GuardFnType =
nullptr;
81 FunctionType *DispatchFnType =
nullptr;
84 Constant *DispatchFnGlobal =
nullptr;
91 void getThunkType(FunctionType *FT, AttributeList AttrList,
93 FunctionType *&Arm64Ty, FunctionType *&X64Ty,
95 void getThunkRetType(FunctionType *FT, AttributeList AttrList,
96 raw_ostream &Out,
Type *&Arm64RetTy,
Type *&X64RetTy,
97 SmallVectorImpl<Type *> &Arm64ArgTypes,
98 SmallVectorImpl<Type *> &X64ArgTypes,
101 void getThunkArgTypes(FunctionType *FT, AttributeList AttrList,
103 SmallVectorImpl<Type *> &Arm64ArgTypes,
104 SmallVectorImpl<Type *> &X64ArgTypes,
105 SmallVectorImpl<ThunkArgTranslation> &ArgTranslations,
107 ThunkArgInfo canonicalizeThunkType(
Type *
T, Align Alignment,
bool Ret,
108 uint64_t ArgSizeBytes, raw_ostream &Out);
113void AArch64Arm64ECCallLowering::getThunkType(
117 Out << (
TT == Arm64ECThunkType::Entry ?
"$ientry_thunk$cdecl$"
118 :
"$iexit_thunk$cdecl$");
129 if (TT == Arm64ECThunkType::Exit)
133 bool HasSretPtr =
false;
134 getThunkRetType(FT, AttrList, Out, Arm64RetTy, X64RetTy, Arm64ArgTypes,
135 X64ArgTypes, ArgTranslations, HasSretPtr);
137 getThunkArgTypes(FT, AttrList, TT, Out, Arm64ArgTypes, X64ArgTypes,
138 ArgTranslations, HasSretPtr);
140 Arm64Ty = FunctionType::get(Arm64RetTy, Arm64ArgTypes,
false);
142 X64Ty = FunctionType::get(X64RetTy, X64ArgTypes,
false);
145void AArch64Arm64ECCallLowering::getThunkArgTypes(
147 raw_ostream &Out, SmallVectorImpl<Type *> &Arm64ArgTypes,
148 SmallVectorImpl<Type *> &X64ArgTypes,
149 SmallVectorImpl<ThunkArgTranslation> &ArgTranslations,
bool HasSretPtr) {
152 if (FT->isVarArg()) {
175 for (
int i = HasSretPtr ? 1 : 0; i < 4; i++) {
178 ArgTranslations.
push_back(ThunkArgTranslation::Direct);
184 ArgTranslations.
push_back(ThunkArgTranslation::Direct);
187 if (TT != Arm64ECThunkType::Entry) {
191 ArgTranslations.
push_back(ThunkArgTranslation::Direct);
200 if (
I == FT->getNumParams()) {
205 for (
unsigned E = FT->getNumParams();
I !=
E; ++
I) {
209 uint64_t ArgSizeBytes = AttrList.getParamArm64ECArgSizeBytes(
I);
210 Align ParamAlign = AttrList.getParamAlignment(
I).valueOrOne();
212 uint64_t ArgSizeBytes = 0;
215 auto [Arm64Ty, X64Ty, ArgTranslation] =
216 canonicalizeThunkType(FT->getParamType(
I), ParamAlign,
217 false, ArgSizeBytes, Out);
220 ArgTranslations.
push_back(ArgTranslation);
224void AArch64Arm64ECCallLowering::getThunkRetType(
225 FunctionType *FT, AttributeList AttrList, raw_ostream &Out,
226 Type *&Arm64RetTy,
Type *&X64RetTy, SmallVectorImpl<Type *> &Arm64ArgTypes,
227 SmallVectorImpl<Type *> &X64ArgTypes,
229 Type *
T = FT->getReturnType();
233 uint64_t ArgSizeBytes = AttrList.getRetArm64ECArgSizeBytes();
235 int64_t ArgSizeBytes = 0;
238 if (FT->getNumParams()) {
239 Attribute SRetAttr0 = AttrList.getParamAttr(0, Attribute::StructRet);
240 Attribute InRegAttr0 = AttrList.getParamAttr(0, Attribute::InReg);
242 if (FT->getNumParams() > 1) {
246 SRetAttr1 = AttrList.getParamAttr(1, Attribute::StructRet);
247 InRegAttr1 = AttrList.getParamAttr(1, Attribute::InReg);
269 Align SRetAlign = AttrList.getParamAlignment(0).valueOrOne();
270 canonicalizeThunkType(SRetType, SRetAlign,
true, ArgSizeBytes,
274 Arm64ArgTypes.
push_back(FT->getParamType(0));
275 X64ArgTypes.
push_back(FT->getParamType(0));
276 ArgTranslations.
push_back(ThunkArgTranslation::Direct);
289 canonicalizeThunkType(
T,
Align(),
true, ArgSizeBytes, Out);
290 Arm64RetTy =
info.Arm64Ty;
291 X64RetTy =
info.X64Ty;
301ThunkArgInfo AArch64Arm64ECCallLowering::canonicalizeThunkType(
302 Type *
T, Align Alignment,
bool Ret, uint64_t ArgSizeBytes,
305 auto direct = [](
Type *
T) {
306 return ThunkArgInfo{
T,
T, ThunkArgTranslation::Direct};
309 auto bitcast = [
this](
Type *Arm64Ty, uint64_t SizeInBytes) {
310 return ThunkArgInfo{Arm64Ty,
312 ThunkArgTranslation::Bitcast};
315 auto pointerIndirection = [
this](
Type *Arm64Ty) {
316 return ThunkArgInfo{Arm64Ty, PtrTy,
317 ThunkArgTranslation::PointerIndirection};
326 if (
T->isBFloatTy()) {
328 Out <<
"__llvm_bf16__";
332 if (
T->isFloatTy()) {
337 if (
T->isDoubleTy()) {
342 if (
T->isFP128Ty()) {
347 return pointerIndirection(
T);
350 if (
T->isFloatingPointTy()) {
352 "Only half, bfloat16, float, double, and fp128 are supported "
353 "for ARM64EC thunks");
359 if (StructTy->getNumElements() == 1)
360 T = StructTy->getElementType(0);
362 if (
T->isArrayTy()) {
363 Type *ElementTy =
T->getArrayElementType();
364 uint64_t ElementCnt =
T->getArrayNumElements();
365 uint64_t ElementSizePerBytes =
DL.getTypeSizeInBits(ElementTy) / 8;
366 uint64_t TotalSizeBytes = ElementCnt * ElementSizePerBytes;
375 Out <<
"__llvm_BF16__";
383 Out << TotalSizeBytes;
384 if (Alignment.
value() >= 16 && !Ret)
385 Out <<
"a" << Alignment.
value();
386 if (TotalSizeBytes <= 8) {
389 return bitcast(
T, TotalSizeBytes);
392 return pointerIndirection(
T);
396 "Only half, bfloat16, float, double, and fp128 are supported "
397 "for ARM64EC thunks");
401 if ((
T->isIntegerTy() ||
T->isPointerTy()) &&
DL.getTypeSizeInBits(
T) <= 64) {
403 return direct(I64Ty);
406 unsigned TypeSize = ArgSizeBytes;
408 TypeSize =
DL.getTypeSizeInBits(
T) / 8;
412 if (Alignment.
value() >= 16 && !Ret)
413 Out <<
"a" << Alignment.
value();
415 if (TypeSize == 1 || TypeSize == 2 || TypeSize == 4 || TypeSize == 8) {
417 return bitcast(
T, TypeSize);
420 return pointerIndirection(
T);
426Function *AArch64Arm64ECCallLowering::buildExitThunk(FunctionType *FT,
427 AttributeList Attrs) {
428 SmallString<256> ExitThunkName;
429 llvm::raw_svector_ostream ExitThunkStream(ExitThunkName);
430 FunctionType *Arm64Ty, *X64Ty;
432 getThunkType(FT, Attrs, Arm64ECThunkType::Exit, ExitThunkStream, Arm64Ty,
433 X64Ty, ArgTranslations);
439 F->setCallingConv(CallingConv::ARM64EC_Thunk_Native);
440 F->setSection(
".wowthk$aa");
443 F->addFnAttr(
"frame-pointer",
"all");
447 if (FT->getNumParams()) {
448 auto SRet =
Attrs.getParamAttr(0, Attribute::StructRet);
449 auto InReg =
Attrs.getParamAttr(0, Attribute::InReg);
450 if (SRet.isValid() && !InReg.isValid())
451 F->addParamAttr(1, SRet);
464 auto X64TyOffset = 1;
465 Args.push_back(
F->arg_begin());
467 Type *RetTy = Arm64Ty->getReturnType();
468 if (RetTy != X64Ty->getReturnType()) {
472 if (
DL.getTypeStoreSize(RetTy) > 8) {
473 Args.push_back(IRB.CreateAlloca(RetTy));
480 make_range(X64Ty->param_begin() + X64TyOffset, X64Ty->param_end()),
496 if (ArgTranslation != ThunkArgTranslation::Direct) {
497 Value *Mem = IRB.CreateAlloca(Arg.getType());
498 IRB.CreateStore(&Arg, Mem);
499 if (ArgTranslation == ThunkArgTranslation::Bitcast) {
500 Type *IntTy = IRB.getIntNTy(
DL.getTypeStoreSizeInBits(Arg.getType()));
501 Args.push_back(IRB.CreateLoad(IntTy, Mem));
503 assert(ArgTranslation == ThunkArgTranslation::PointerIndirection);
507 Args.push_back(&Arg);
513 CallInst *
Call = IRB.CreateCall(X64Ty, Callee, Args);
517 if (RetTy != X64Ty->getReturnType()) {
520 if (
DL.getTypeStoreSize(RetTy) > 8) {
521 RetVal = IRB.CreateLoad(RetTy, Args[1]);
523 Value *CastAlloca = IRB.CreateAlloca(RetTy);
524 IRB.CreateStore(
Call, CastAlloca);
525 RetVal = IRB.CreateLoad(RetTy, CastAlloca);
532 IRB.CreateRet(RetVal);
538Function *AArch64Arm64ECCallLowering::buildEntryThunk(Function *
F) {
539 SmallString<256> EntryThunkName;
540 llvm::raw_svector_ostream EntryThunkStream(EntryThunkName);
541 FunctionType *Arm64Ty, *X64Ty;
543 getThunkType(
F->getFunctionType(),
F->getAttributes(),
544 Arm64ECThunkType::Entry, EntryThunkStream, Arm64Ty, X64Ty,
551 Thunk->setCallingConv(CallingConv::ARM64EC_Thunk_X64);
552 Thunk->setSection(
".wowthk$aa");
555 Thunk->addFnAttr(
"frame-pointer",
"all");
560 Type *RetTy = Arm64Ty->getReturnType();
561 Type *X64RetType = X64Ty->getReturnType();
564 unsigned ThunkArgOffset = TransformDirectToSRet ? 2 : 1;
565 unsigned PassthroughArgSize =
566 (
F->isVarArg() ? 5 :
Thunk->arg_size()) - ThunkArgOffset;
567 assert(ArgTranslations.
size() == (
F->isVarArg() ? 5 : PassthroughArgSize));
571 for (
unsigned i = 0; i != PassthroughArgSize; ++i) {
572 Value *Arg =
Thunk->getArg(i + ThunkArgOffset);
573 Type *ArgTy = Arm64Ty->getParamType(i);
574 ThunkArgTranslation ArgTranslation = ArgTranslations[i];
575 if (ArgTranslation != ThunkArgTranslation::Direct) {
577 if (ArgTranslation == ThunkArgTranslation::Bitcast) {
578 Value *CastAlloca = IRB.CreateAlloca(ArgTy);
579 IRB.CreateStore(Arg, CastAlloca);
580 Arg = IRB.CreateLoad(ArgTy, CastAlloca);
582 assert(ArgTranslation == ThunkArgTranslation::PointerIndirection);
583 Arg = IRB.CreateLoad(ArgTy, Arg);
597 Thunk->addParamAttr(5, Attribute::InReg);
599 Arg = IRB.CreatePtrAdd(Arg, IRB.getInt64(0x20));
603 Args.push_back(IRB.getInt64(0));
608 CallInst *
Call = IRB.CreateCall(Arm64Ty, Callee, Args);
610 auto SRetAttr =
F->
getAttributes().getParamAttr(0, Attribute::StructRet);
611 auto InRegAttr =
F->getAttributes().getParamAttr(0, Attribute::InReg);
612 if (SRetAttr.isValid() && !InRegAttr.isValid()) {
613 Thunk->addParamAttr(1, SRetAttr);
618 if (TransformDirectToSRet) {
623 1, Attribute::getWithStructRetType(M->
getContext(), RetTy));
624 IRB.CreateStore(RetVal,
Thunk->getArg(1));
625 }
else if (X64RetType != RetTy) {
626 Value *CastAlloca = IRB.CreateAlloca(X64RetType);
627 IRB.CreateStore(
Call, CastAlloca);
628 RetVal = IRB.CreateLoad(X64RetType, CastAlloca);
638 IRB.CreateRet(RetVal);
655Function *AArch64Arm64ECCallLowering::buildGuestExitThunk(Function *
F) {
656 llvm::raw_null_ostream NullThunkName;
657 FunctionType *Arm64Ty, *X64Ty;
659 getThunkType(
F->getFunctionType(),
F->getAttributes(),
660 Arm64ECThunkType::GuestExit, NullThunkName, Arm64Ty, X64Ty,
663 assert(MangledName &&
"Can't guest exit to function that's already native");
664 std::string ThunkName = *MangledName;
665 if (ThunkName[0] ==
'?' && ThunkName.find(
"@") != std::string::npos) {
666 ThunkName.insert(ThunkName.find(
"@"),
"$exit_thunk");
668 ThunkName.append(
"$exit_thunk");
675 "arm64ec_unmangled_name",
679 "arm64ec_ecmangled_name",
689 LoadInst *GuardCheckLoad =
B.CreateLoad(PtrTy, GuardFnGlobal);
690 Function *
Thunk = buildExitThunk(
F->getFunctionType(),
F->getAttributes());
691 CallInst *GuardCheck =
B.CreateCall(
692 GuardFnType, GuardCheckLoad, {
F,
Thunk});
693 Value *GuardCheckDest =
B.CreateExtractValue(GuardCheck, 0);
694 Value *GuardFinalDest =
B.CreateExtractValue(GuardCheck, 1);
701 CallInst *
Call =
B.CreateCall(Arm64Ty, GuardCheckDest, Args, OB);
709 auto SRetAttr =
F->getAttributes().getParamAttr(0, Attribute::StructRet);
710 auto InRegAttr =
F->getAttributes().getParamAttr(0, Attribute::InReg);
711 if (SRetAttr.isValid() && !InRegAttr.isValid()) {
720AArch64Arm64ECCallLowering::buildPatchableThunk(GlobalAlias *UnmangledAlias,
721 GlobalAlias *MangledAlias) {
722 llvm::raw_null_ostream NullThunkName;
723 FunctionType *Arm64Ty, *X64Ty;
726 getThunkType(
F->getFunctionType(),
F->getAttributes(),
727 Arm64ECThunkType::GuestExit, NullThunkName, Arm64Ty, X64Ty,
729 std::string ThunkName(MangledAlias->
getName());
730 if (ThunkName[0] ==
'?' && ThunkName.find(
"@") != std::string::npos) {
731 ThunkName.insert(ThunkName.find(
"@"),
"$hybpatch_thunk");
733 ThunkName.append(
"$hybpatch_thunk");
744 LoadInst *DispatchLoad =
B.CreateLoad(PtrTy, DispatchFnGlobal);
748 buildExitThunk(
F->getFunctionType(),
F->getAttributes());
750 B.CreateCall(DispatchFnType, DispatchLoad,
751 {UnmangledAlias, ExitThunk, UnmangledAlias->
getAliasee()});
754 Dispatch->setCallingConv(CallingConv::CFGuard_Check);
765 auto SRetAttr =
F->getAttributes().getParamAttr(0, Attribute::StructRet);
766 auto InRegAttr =
F->getAttributes().getParamAttr(0, Attribute::InReg);
767 if (SRetAttr.isValid() && !InRegAttr.isValid()) {
777void AArch64Arm64ECCallLowering::lowerCall(CallBase *CB) {
789 if ((CFGuardModuleFlag == ControlFlowGuardMode::Enabled) &&
791 GuardFn = GuardFnCFGlobal;
793 GuardFn = GuardFnGlobal;
794 LoadInst *GuardCheckLoad =
B.CreateLoad(PtrTy, GuardFn);
799 CallInst *GuardCheck =
800 B.CreateCall(GuardFnType, GuardCheckLoad, {CalledOperand,
Thunk},
802 Value *GuardCheckDest =
B.CreateExtractValue(GuardCheck, 0);
803 Value *GuardFinalDest =
B.CreateExtractValue(GuardCheck, 1);
814 NewCall->copyMetadata(*CB);
819bool AArch64Arm64ECCallLowering::runOnModule(
Module &
Mod) {
829 if (CFGuardModuleFlag == ControlFlowGuardMode::Enabled) {
831 Mod.getModuleFlag(
"cfguard-mechanism"))) {
832 auto MechanismOverride =
834 if (MechanismOverride != ControlFlowGuardMechanism::Automatic &&
835 MechanismOverride != ControlFlowGuardMechanism::Check)
836 Mod.getContext().diagnose(
837 DiagnosticInfoGeneric(
"only the Check Control Flow Guard mechanism "
838 "is supported for Arm64EC",
843 PtrTy = PointerType::getUnqual(M->
getContext());
848 FunctionType::get(
StructType::get(PtrTy, PtrTy), {PtrTy, PtrTy},
false);
849 DispatchFnType = FunctionType::get(PtrTy, {PtrTy, PtrTy, PtrTy},
false);
858 for (GlobalAlias &
A :
Mod.aliases()) {
862 if (std::optional<std::string> MangledName =
864 F->addMetadata(
"arm64ec_unmangled_name",
867 A.setName(MangledName.value());
871 DenseMap<GlobalAlias *, GlobalAlias *> FnsMap;
872 SetVector<GlobalAlias *> PatchableFns;
874 for (Function &
F :
Mod) {
875 if (
F.hasPersonalityFn()) {
876 GlobalValue *PersFn =
879 if (std::optional<std::string> MangledName =
881 PersFn->
setName(MangledName.value());
886 if (!
F.hasFnAttribute(Attribute::HybridPatchable) ||
887 F.isDeclarationForLinker() ||
F.hasLocalLinkage() ||
893 if (std::optional<std::string> MangledName =
895 std::string OrigName(
F.getName());
907 MangledName.value(), &
F);
908 F.replaceUsesWithIf(AM,
910 F.replaceAllUsesWith(
A);
911 F.setMetadata(
"arm64ec_exp_name",
914 "EXP+" + MangledName.value())));
918 if (
F.hasDLLExportStorageClass()) {
928 SetVector<GlobalValue *> DirectCalledFns;
929 for (Function &
F :
Mod)
930 if (!
F.isDeclarationForLinker() &&
931 F.getCallingConv() != CallingConv::ARM64EC_Thunk_Native &&
932 F.getCallingConv() != CallingConv::ARM64EC_Thunk_X64)
941 for (Function &
F :
Mod) {
942 if (!
F.isDeclarationForLinker() &&
943 (!
F.hasLocalLinkage() ||
F.hasAddressTaken()) &&
944 F.getCallingConv() != CallingConv::ARM64EC_Thunk_Native &&
945 F.getCallingConv() != CallingConv::ARM64EC_Thunk_X64) {
947 F.setComdat(
Mod.getOrInsertComdat(
F.getName()));
949 {&
F, buildEntryThunk(&
F), Arm64ECThunkType::Entry});
952 for (GlobalValue *O : DirectCalledFns) {
956 {
O, buildExitThunk(
F->getFunctionType(),
F->getAttributes()),
957 Arm64ECThunkType::Exit});
958 if (!GA && !
F->hasDLLImportStorageClass())
960 {buildGuestExitThunk(
F),
F, Arm64ECThunkType::GuestExit});
962 for (GlobalAlias *
A : PatchableFns) {
967 if (!ThunkMapping.
empty()) {
969 for (ThunkInfo &Thunk : ThunkMapping) {
976 ThunkMappingArrayElems.
size()),
977 ThunkMappingArrayElems);
978 new GlobalVariable(
Mod, ThunkMappingArray->
getType(),
false,
980 "llvm.arm64ec.symbolmap");
986bool AArch64Arm64ECCallLowering::processFunction(
987 Function &
F, SetVector<GlobalValue *> &DirectCalledFns,
988 DenseMap<GlobalAlias *, GlobalAlias *> &FnsMap) {
998 if (!
F.hasLocalLinkage() ||
F.hasAddressTaken()) {
999 if (std::optional<std::string> MangledName =
1001 F.addMetadata(
"arm64ec_unmangled_name",
1004 if (
F.hasComdat() &&
F.getComdat()->getName() ==
F.getName()) {
1008 for (GlobalObject *User : ComdatUsers)
1009 User->setComdat(MangledComdat);
1011 F.setName(MangledName.value());
1019 for (BasicBlock &BB :
F) {
1020 for (Instruction &
I : BB) {
1022 if (!CB || CB->
getCallingConv() == CallingConv::ARM64EC_Thunk_X64 ||
1033 F->isIntrinsic() || !
F->isDeclarationForLinker())
1043 if (
I != FnsMap.
end()) {
1045 DirectCalledFns.
insert(
I->first);
1051 ++Arm64ECCallsLowered;
1055 if (IndirectCalls.
empty())
1058 for (CallBase *CB : IndirectCalls)
1064char AArch64Arm64ECCallLowering::ID = 0;
1066 "AArch64Arm64ECCallLowering",
false,
false)
1069 return new AArch64Arm64ECCallLowering;
static cl::opt< bool > LowerDirectToIndirect("arm64ec-lower-direct-to-indirect", cl::Hidden, cl::init(true))
static cl::opt< bool > GenerateThunks("arm64ec-generate-thunks", cl::Hidden, cl::init(true))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Module.h This file contains the declarations for the Module class.
Machine Check Debug Module
static bool processFunction(Function &F, NVPTXTargetMachine &TM)
if(auto Err=PB.parsePassPipeline(MPM, Passes)) return wrap(std MPM run * Mod
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallString class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static SymbolRef::Type getType(const Symbol *Sym)
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
bool isValid() const
Return true if the attribute is any kind of attribute.
LLVM_ABI Type * getValueAsType() const
Return the attribute's value as a Type.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
bool isInlineAsm() const
Check if this call is an inline asm statement.
void setCallingConv(CallingConv::ID CC)
std::optional< OperandBundleUse > getOperandBundle(StringRef Name) const
Return an operand bundle by name, if present.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
bool hasFnAttr(Attribute::AttrKind Kind) const
Determine whether this call has the given attribute.
CallingConv::ID getCallingConv() const
static LLVM_ABI CallBase * addOperandBundle(CallBase *CB, uint32_t ID, OperandBundleDef OB, InsertPosition InsertPt=nullptr)
Create a clone of CB with operand bundle OB added.
Value * getCalledOperand() const
FunctionType * getFunctionType() const
void setCalledOperand(Value *V)
AttributeList getAttributes() const
Return the attributes for this call.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
void setTailCallKind(TailCallKind TCK)
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static Constant * getAnon(ArrayRef< Constant * > V, bool Packed=false)
Return an anonymous struct that has the specified elements.
iterator find(const_arg_type_t< KeyT > Val)
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
LLVM_ABI void setAliasee(Constant *Aliasee)
These methods retrieve and set alias target.
const Constant * getAliasee() const
static LLVM_ABI GlobalAlias * create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, Constant *Aliasee, Module *Parent)
If a parent module is specified, the alias is automatically inserted into the end of the specified mo...
@ DLLExportStorageClass
Function to be accessible from DLL.
@ WeakODRLinkage
Same, but only replaced by something equivalent.
@ ExternalLinkage
Externally visible function.
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Type * getValueType() const
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
LLVMContext & getContext() const
Get the global data context.
Function * getFunction(StringRef Name) const
Look up the specified function in the module symbol table.
ControlFlowGuardMode getControlFlowGuardMode() const
Gets the Control Flow Guard mode.
Comdat * getOrInsertComdat(StringRef Name)
Return the Comdat in the module with the specified name.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
GlobalVariable * getOrInsertGlobal(StringRef Name, Type *Ty, function_ref< GlobalVariable *()> CreateGlobalCallback)
Look up the specified global in the module symbol table.
A container for an operand bundle being viewed as a set of values rather than a set of uses.
bool insert(const value_type &X)
Insert a new element into the SetVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
bool isPointerTy() const
True if this is an instance of PointerType.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
bool isBFloatTy() const
Return true if this is 'bfloat', a 16-bit bfloat type.
bool isFP128Ty() const
Return true if this is 'fp128'.
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isFunctionTy() const
True if this is an instance of FunctionType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
bool isVoidTy() const
Return true if this is 'void'.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
self_iterator getIterator()
This class implements an extremely fast bulk output stream that can only output to a stream.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
@ BasicBlock
Various leaf nodes.
@ OB
OB - OneByte - Set if this instruction has a one byte opcode.
initializer< Ty > init(const Ty &Val)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract_or_null(Y &&MD)
Extract a Value from Metadata, if any, allowing null.
@ User
could "use" a pointer
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::optional< std::string > getArm64ECMangledFunctionName(StringRef Name)
Returns the ARM64EC mangled function name unless the input is already mangled.
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto dyn_cast_or_null(const Y &Val)
ModulePass * createAArch64Arm64ECCallLoweringPass()
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
constexpr std::string_view HybridPatchableTargetSuffix
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
OperandBundleDefT< Value * > OperandBundleDef
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
ControlFlowGuardMechanism
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.