40#define DEBUG_TYPE "arm64eccalllowering"
42STATISTIC(Arm64ECCallsLowered,
"Number of Arm64EC calls lowered");
46enum ThunkArgTranslation :
uint8_t {
55 ThunkArgTranslation Translation;
58class AArch64Arm64ECCallLowering :
public ModulePass {
61 AArch64Arm64ECCallLowering() : ModulePass(ID) {}
63 Function *buildExitThunk(FunctionType *FnTy, AttributeList Attrs);
65 void lowerCall(CallBase *CB);
67 Function *buildPatchableThunk(GlobalAlias *UnmangledAlias,
68 GlobalAlias *MangledAlias);
70 DenseMap<GlobalAlias *, GlobalAlias *> &FnsMap);
71 bool runOnModule(
Module &M)
override;
74 const AArch64Options *CLOpts =
nullptr;
76 FunctionType *GuardFnType =
nullptr;
77 FunctionType *DispatchFnType =
nullptr;
80 Constant *DispatchFnGlobal =
nullptr;
87 void getThunkType(FunctionType *FT, AttributeList AttrList,
89 FunctionType *&Arm64Ty, FunctionType *&X64Ty,
91 void getThunkRetType(FunctionType *FT, AttributeList AttrList,
92 raw_ostream &Out,
Type *&Arm64RetTy,
Type *&X64RetTy,
93 SmallVectorImpl<Type *> &Arm64ArgTypes,
94 SmallVectorImpl<Type *> &X64ArgTypes,
97 void getThunkArgTypes(FunctionType *FT, AttributeList AttrList,
99 SmallVectorImpl<Type *> &Arm64ArgTypes,
100 SmallVectorImpl<Type *> &X64ArgTypes,
101 SmallVectorImpl<ThunkArgTranslation> &ArgTranslations,
103 ThunkArgInfo canonicalizeThunkType(
Type *
T, Align Alignment,
bool Ret,
104 uint64_t ArgSizeBytes, raw_ostream &Out);
109void AArch64Arm64ECCallLowering::getThunkType(
113 Out << (
TT == Arm64ECThunkType::Entry ?
"$ientry_thunk$cdecl$"
114 :
"$iexit_thunk$cdecl$");
125 if (TT == Arm64ECThunkType::Exit)
129 bool HasSretPtr =
false;
130 getThunkRetType(FT, AttrList, Out, Arm64RetTy, X64RetTy, Arm64ArgTypes,
131 X64ArgTypes, ArgTranslations, HasSretPtr);
133 getThunkArgTypes(FT, AttrList, TT, Out, Arm64ArgTypes, X64ArgTypes,
134 ArgTranslations, HasSretPtr);
136 Arm64Ty = FunctionType::get(Arm64RetTy, Arm64ArgTypes,
false);
138 X64Ty = FunctionType::get(X64RetTy, X64ArgTypes,
false);
141void AArch64Arm64ECCallLowering::getThunkArgTypes(
143 raw_ostream &Out, SmallVectorImpl<Type *> &Arm64ArgTypes,
144 SmallVectorImpl<Type *> &X64ArgTypes,
145 SmallVectorImpl<ThunkArgTranslation> &ArgTranslations,
bool HasSretPtr) {
148 if (FT->isVarArg()) {
171 for (
int i = HasSretPtr ? 1 : 0; i < 4; i++) {
174 ArgTranslations.
push_back(ThunkArgTranslation::Direct);
180 ArgTranslations.
push_back(ThunkArgTranslation::Direct);
183 if (TT != Arm64ECThunkType::Entry) {
187 ArgTranslations.
push_back(ThunkArgTranslation::Direct);
196 if (
I == FT->getNumParams()) {
201 for (
unsigned E = FT->getNumParams();
I !=
E; ++
I) {
205 uint64_t ArgSizeBytes = AttrList.getParamArm64ECArgSizeBytes(
I);
206 Align ParamAlign = AttrList.getParamAlignment(
I).valueOrOne();
211 auto [Arm64Ty, X64Ty, ArgTranslation] =
212 canonicalizeThunkType(FT->getParamType(
I), ParamAlign,
213 false, ArgSizeBytes, Out);
216 ArgTranslations.
push_back(ArgTranslation);
220void AArch64Arm64ECCallLowering::getThunkRetType(
221 FunctionType *FT, AttributeList AttrList, raw_ostream &Out,
222 Type *&Arm64RetTy,
Type *&X64RetTy, SmallVectorImpl<Type *> &Arm64ArgTypes,
223 SmallVectorImpl<Type *> &X64ArgTypes,
225 Type *
T = FT->getReturnType();
229 uint64_t ArgSizeBytes = AttrList.getRetArm64ECArgSizeBytes();
231 int64_t ArgSizeBytes = 0;
234 if (FT->getNumParams()) {
235 Attribute SRetAttr0 = AttrList.getParamAttr(0, Attribute::StructRet);
236 Attribute InRegAttr0 = AttrList.getParamAttr(0, Attribute::InReg);
238 if (FT->getNumParams() > 1) {
242 SRetAttr1 = AttrList.getParamAttr(1, Attribute::StructRet);
243 InRegAttr1 = AttrList.getParamAttr(1, Attribute::InReg);
265 Align SRetAlign = AttrList.getParamAlignment(0).valueOrOne();
266 canonicalizeThunkType(SRetType, SRetAlign,
true, ArgSizeBytes,
270 Arm64ArgTypes.
push_back(FT->getParamType(0));
271 X64ArgTypes.
push_back(FT->getParamType(0));
272 ArgTranslations.
push_back(ThunkArgTranslation::Direct);
285 canonicalizeThunkType(
T,
Align(),
true, ArgSizeBytes, Out);
286 Arm64RetTy =
info.Arm64Ty;
287 X64RetTy =
info.X64Ty;
297ThunkArgInfo AArch64Arm64ECCallLowering::canonicalizeThunkType(
301 auto direct = [](
Type *
T) {
302 return ThunkArgInfo{
T,
T, ThunkArgTranslation::Direct};
305 auto bitcast = [
this](
Type *Arm64Ty,
uint64_t SizeInBytes) {
306 return ThunkArgInfo{Arm64Ty,
308 ThunkArgTranslation::Bitcast};
311 auto pointerIndirection = [
this](
Type *Arm64Ty) {
312 return ThunkArgInfo{Arm64Ty, PtrTy,
313 ThunkArgTranslation::PointerIndirection};
322 if (
T->isBFloatTy()) {
324 Out <<
"__llvm_bf16__";
328 if (
T->isFloatTy()) {
333 if (
T->isDoubleTy()) {
338 if (
T->isFP128Ty()) {
343 return pointerIndirection(
T);
346 if (
T->isFloatingPointTy()) {
348 "Only half, bfloat16, float, double, and fp128 are supported "
349 "for ARM64EC thunks");
355 if (StructTy->getNumElements() == 1)
356 T = StructTy->getElementType(0);
358 if (
T->isArrayTy()) {
359 Type *ElementTy =
T->getArrayElementType();
360 uint64_t ElementCnt =
T->getArrayNumElements();
361 uint64_t ElementSizePerBytes =
DL.getTypeSizeInBits(ElementTy) / 8;
362 uint64_t TotalSizeBytes = ElementCnt * ElementSizePerBytes;
371 Out <<
"__llvm_BF16__";
379 Out << TotalSizeBytes;
382 if (TotalSizeBytes <= 8) {
385 return bitcast(
T, TotalSizeBytes);
388 return pointerIndirection(
T);
392 "Only half, bfloat16, float, double, and fp128 are supported "
393 "for ARM64EC thunks");
397 if ((
T->isIntegerTy() ||
T->isPointerTy()) &&
DL.getTypeSizeInBits(
T) <= 64) {
399 return direct(I64Ty);
402 unsigned TypeSize = ArgSizeBytes;
404 TypeSize =
DL.getTypeSizeInBits(
T) / 8;
411 if (TypeSize == 1 || TypeSize == 2 || TypeSize == 4 || TypeSize == 8) {
413 return bitcast(
T, TypeSize);
416 return pointerIndirection(
T);
422Function *AArch64Arm64ECCallLowering::buildExitThunk(FunctionType *FT,
423 AttributeList Attrs) {
424 SmallString<256> ExitThunkName;
425 llvm::raw_svector_ostream ExitThunkStream(ExitThunkName);
426 FunctionType *Arm64Ty, *X64Ty;
428 getThunkType(FT, Attrs, Arm64ECThunkType::Exit, ExitThunkStream, Arm64Ty,
429 X64Ty, ArgTranslations);
435 F->setCallingConv(CallingConv::ARM64EC_Thunk_Native);
436 F->setSection(
".wowthk$aa");
439 F->addFnAttr(
"frame-pointer",
"all");
443 if (FT->getNumParams()) {
444 auto SRet =
Attrs.getParamAttr(0, Attribute::StructRet);
445 auto InReg =
Attrs.getParamAttr(0, Attribute::InReg);
446 if (SRet.isValid() && !InReg.isValid())
447 F->addParamAttr(1, SRet);
458 FunctionType *DispatcherCallTy = X64Ty;
464 FunctionType::get(X64Ty->getReturnType(), X64Ty->params(),
468 auto X64TyOffset = 1;
469 Args.push_back(
F->arg_begin());
471 Type *RetTy = Arm64Ty->getReturnType();
472 if (RetTy != X64Ty->getReturnType()) {
476 if (
DL.getTypeStoreSize(RetTy) > 8) {
477 Args.push_back(IRB.CreateAlloca(RetTy));
484 make_range(X64Ty->param_begin() + X64TyOffset, X64Ty->param_end()),
500 if (ArgTranslation != ThunkArgTranslation::Direct) {
501 Value *Mem = IRB.CreateAlloca(Arg.getType());
502 IRB.CreateStore(&Arg, Mem);
503 if (ArgTranslation == ThunkArgTranslation::Bitcast) {
504 Type *IntTy = IRB.getIntNTy(
DL.getTypeStoreSizeInBits(Arg.getType()));
505 Args.push_back(IRB.CreateLoad(IntTy, Mem));
507 assert(ArgTranslation == ThunkArgTranslation::PointerIndirection);
511 Args.push_back(&Arg);
517 CallInst *
Call = IRB.CreateCall(DispatcherCallTy, Callee, Args);
521 if (RetTy != X64Ty->getReturnType()) {
524 if (
DL.getTypeStoreSize(RetTy) > 8) {
525 RetVal = IRB.CreateLoad(RetTy, Args[1]);
527 Value *CastAlloca = IRB.CreateAlloca(RetTy);
528 IRB.CreateStore(
Call, CastAlloca);
529 RetVal = IRB.CreateLoad(RetTy, CastAlloca);
536 IRB.CreateRet(RetVal);
543 SmallString<256> EntryThunkName;
544 llvm::raw_svector_ostream EntryThunkStream(EntryThunkName);
545 FunctionType *Arm64Ty, *X64Ty;
547 getThunkType(
F->getFunctionType(),
F->getAttributes(),
548 Arm64ECThunkType::Entry, EntryThunkStream, Arm64Ty, X64Ty,
555 Thunk->setCallingConv(CallingConv::ARM64EC_Thunk_X64);
556 Thunk->setSection(
".wowthk$aa");
559 Thunk->addFnAttr(
"frame-pointer",
"all");
564 Type *RetTy = Arm64Ty->getReturnType();
565 Type *X64RetType = X64Ty->getReturnType();
568 unsigned ThunkArgOffset = TransformDirectToSRet ? 2 : 1;
569 unsigned PassthroughArgSize =
570 (
F->isVarArg() ? 5 :
Thunk->arg_size()) - ThunkArgOffset;
571 assert(ArgTranslations.
size() == (
F->isVarArg() ? 5 : PassthroughArgSize));
575 for (
unsigned i = 0; i != PassthroughArgSize; ++i) {
576 Value *Arg =
Thunk->getArg(i + ThunkArgOffset);
577 Type *ArgTy = Arm64Ty->getParamType(i);
578 ThunkArgTranslation ArgTranslation = ArgTranslations[i];
579 if (ArgTranslation != ThunkArgTranslation::Direct) {
581 if (ArgTranslation == ThunkArgTranslation::Bitcast) {
582 Value *CastAlloca = IRB.CreateAlloca(ArgTy);
583 IRB.CreateStore(Arg, CastAlloca);
584 Arg = IRB.CreateLoad(ArgTy, CastAlloca);
586 assert(ArgTranslation == ThunkArgTranslation::PointerIndirection);
587 Arg = IRB.CreateLoad(ArgTy, Arg);
601 Thunk->addParamAttr(5, Attribute::InReg);
603 Arg = IRB.CreatePtrAdd(Arg, IRB.getInt64(0x20));
607 Args.push_back(IRB.getInt64(0));
612 CallInst *
Call = IRB.CreateCall(Arm64Ty, Callee, Args);
614 auto SRetAttr =
F->
getAttributes().getParamAttr(0, Attribute::StructRet);
615 auto InRegAttr =
F->getAttributes().getParamAttr(0, Attribute::InReg);
616 if (SRetAttr.isValid() && !InRegAttr.isValid()) {
617 Thunk->addParamAttr(1, SRetAttr);
622 if (TransformDirectToSRet) {
627 1, Attribute::getWithStructRetType(M->
getContext(), RetTy));
628 IRB.CreateStore(RetVal,
Thunk->getArg(1));
629 }
else if (X64RetType != RetTy) {
630 Value *CastAlloca = IRB.CreateAlloca(X64RetType);
631 IRB.CreateStore(
Call, CastAlloca);
632 RetVal = IRB.CreateLoad(X64RetType, CastAlloca);
642 IRB.CreateRet(RetVal);
660 llvm::raw_null_ostream NullThunkName;
661 FunctionType *Arm64Ty, *X64Ty;
663 getThunkType(
F->getFunctionType(),
F->getAttributes(),
664 Arm64ECThunkType::GuestExit, NullThunkName, Arm64Ty, X64Ty,
667 assert(MangledName &&
"Can't guest exit to function that's already native");
668 std::string ThunkName = *MangledName;
669 if (ThunkName[0] ==
'?' && ThunkName.find(
"@") != std::string::npos) {
670 ThunkName.insert(ThunkName.find(
"@"),
"$exit_thunk");
672 ThunkName.append(
"$exit_thunk");
679 "arm64ec_unmangled_name",
683 "arm64ec_ecmangled_name",
693 LoadInst *GuardCheckLoad =
B.CreateLoad(PtrTy, GuardFnGlobal);
694 Function *
Thunk = buildExitThunk(
F->getFunctionType(),
F->getAttributes());
695 CallInst *GuardCheck =
B.CreateCall(
696 GuardFnType, GuardCheckLoad, {
F,
Thunk});
697 Value *GuardCheckDest =
B.CreateExtractValue(GuardCheck, 0);
698 Value *GuardFinalDest =
B.CreateExtractValue(GuardCheck, 1);
705 CallInst *
Call =
B.CreateCall(Arm64Ty, GuardCheckDest, Args, OB);
713 auto SRetAttr =
F->getAttributes().getParamAttr(0, Attribute::StructRet);
714 auto InRegAttr =
F->getAttributes().getParamAttr(0, Attribute::InReg);
715 if (SRetAttr.isValid() && !InRegAttr.isValid()) {
724AArch64Arm64ECCallLowering::buildPatchableThunk(GlobalAlias *UnmangledAlias,
725 GlobalAlias *MangledAlias) {
726 llvm::raw_null_ostream NullThunkName;
727 FunctionType *Arm64Ty, *X64Ty;
730 getThunkType(
F->getFunctionType(),
F->getAttributes(),
731 Arm64ECThunkType::GuestExit, NullThunkName, Arm64Ty, X64Ty,
733 std::string ThunkName(MangledAlias->
getName());
734 if (ThunkName[0] ==
'?' && ThunkName.find(
"@") != std::string::npos) {
735 ThunkName.insert(ThunkName.find(
"@"),
"$hybpatch_thunk");
737 ThunkName.append(
"$hybpatch_thunk");
748 LoadInst *DispatchLoad =
B.CreateLoad(PtrTy, DispatchFnGlobal);
752 buildExitThunk(
F->getFunctionType(),
F->getAttributes());
754 B.CreateCall(DispatchFnType, DispatchLoad,
755 {UnmangledAlias, ExitThunk, UnmangledAlias->
getAliasee()});
758 Dispatch->setCallingConv(CallingConv::CFGuard_Check);
769 auto SRetAttr =
F->getAttributes().getParamAttr(0, Attribute::StructRet);
770 auto InRegAttr =
F->getAttributes().getParamAttr(0, Attribute::InReg);
771 if (SRetAttr.isValid() && !InRegAttr.isValid()) {
781void AArch64Arm64ECCallLowering::lowerCall(CallBase *CB) {
793 if ((CFGuardModuleFlag == ControlFlowGuardMode::Enabled) &&
795 GuardFn = GuardFnCFGlobal;
797 GuardFn = GuardFnGlobal;
798 LoadInst *GuardCheckLoad =
B.CreateLoad(PtrTy, GuardFn);
803 CallInst *GuardCheck =
804 B.CreateCall(GuardFnType, GuardCheckLoad, {CalledOperand,
Thunk},
806 Value *GuardCheckDest =
B.CreateExtractValue(GuardCheck, 0);
807 Value *GuardFinalDest =
B.CreateExtractValue(GuardCheck, 1);
818 NewCall->copyMetadata(*CB);
823bool AArch64Arm64ECCallLowering::runOnModule(
Module &
Mod) {
824 CLOpts = &
Mod.getContext().getLibraryOptions().get<AArch64Options>();
825 if (!CLOpts->arm64ec_generate_thunks)
834 if (CFGuardModuleFlag == ControlFlowGuardMode::Enabled) {
836 Mod.getModuleFlag(
"cfguard-mechanism"))) {
837 auto MechanismOverride =
839 if (MechanismOverride != ControlFlowGuardMechanism::Automatic &&
840 MechanismOverride != ControlFlowGuardMechanism::Check)
841 Mod.getContext().diagnose(
842 DiagnosticInfoGeneric(
"only the Check Control Flow Guard mechanism "
843 "is supported for Arm64EC",
848 PtrTy = PointerType::getUnqual(M->
getContext());
853 FunctionType::get(
StructType::get(PtrTy, PtrTy), {PtrTy, PtrTy},
false);
854 DispatchFnType = FunctionType::get(PtrTy, {PtrTy, PtrTy, PtrTy},
false);
863 for (GlobalAlias &
A :
Mod.aliases()) {
867 if (std::optional<std::string> MangledName =
869 F->addMetadata(
"arm64ec_unmangled_name",
872 A.setName(MangledName.value());
876 DenseMap<GlobalAlias *, GlobalAlias *> FnsMap;
877 SetVector<GlobalAlias *> PatchableFns;
880 if (
F.hasPersonalityFn()) {
881 GlobalValue *PersFn =
884 if (std::optional<std::string> MangledName =
886 PersFn->
setName(MangledName.value());
891 if (!
F.hasFnAttribute(Attribute::HybridPatchable) ||
892 F.isDeclarationForLinker() ||
F.hasLocalLinkage() ||
898 if (std::optional<std::string> MangledName =
900 std::string OrigName(
F.getName());
912 MangledName.value(), &
F);
913 F.replaceUsesWithIf(AM,
915 F.replaceAllUsesWith(
A);
916 F.setMetadata(
"arm64ec_exp_name",
919 "EXP+" + MangledName.value())));
923 if (
F.hasDLLExportStorageClass()) {
933 SetVector<GlobalValue *> DirectCalledFns;
935 if (!
F.isDeclarationForLinker() &&
936 F.getCallingConv() != CallingConv::ARM64EC_Thunk_Native &&
937 F.getCallingConv() != CallingConv::ARM64EC_Thunk_X64)
947 if (!
F.isDeclarationForLinker() &&
948 (!
F.hasLocalLinkage() ||
F.hasAddressTaken()) &&
949 F.getCallingConv() != CallingConv::ARM64EC_Thunk_Native &&
950 F.getCallingConv() != CallingConv::ARM64EC_Thunk_X64) {
952 F.setComdat(
Mod.getOrInsertComdat(
F.getName()));
954 {&
F, buildEntryThunk(&
F), Arm64ECThunkType::Entry});
957 for (GlobalValue *O : DirectCalledFns) {
961 {
O, buildExitThunk(
F->getFunctionType(),
F->getAttributes()),
962 Arm64ECThunkType::Exit});
963 if (!GA && !
F->hasDLLImportStorageClass())
965 {buildGuestExitThunk(
F),
F, Arm64ECThunkType::GuestExit});
967 for (GlobalAlias *
A : PatchableFns) {
972 if (!ThunkMapping.
empty()) {
974 for (ThunkInfo &Thunk : ThunkMapping) {
981 ThunkMappingArrayElems.
size()),
982 ThunkMappingArrayElems);
983 new GlobalVariable(
Mod, ThunkMappingArray->
getType(),
false,
985 "llvm.arm64ec.symbolmap");
991bool AArch64Arm64ECCallLowering::processFunction(
992 Function &
F, SetVector<GlobalValue *> &DirectCalledFns,
993 DenseMap<GlobalAlias *, GlobalAlias *> &FnsMap) {
1003 if (!
F.hasLocalLinkage() ||
F.hasAddressTaken()) {
1004 if (std::optional<std::string> MangledName =
1006 F.addMetadata(
"arm64ec_unmangled_name",
1009 if (
F.hasComdat() &&
F.getComdat()->getName() ==
F.getName()) {
1013 for (GlobalObject *User : ComdatUsers)
1014 User->setComdat(MangledComdat);
1016 F.setName(MangledName.value());
1024 for (BasicBlock &BB :
F) {
1025 for (Instruction &
I : BB) {
1027 if (!CB || CB->
getCallingConv() == CallingConv::ARM64EC_Thunk_X64 ||
1037 if (!CLOpts->arm64ec_lower_direct_to_indirect ||
F->hasLocalLinkage() ||
1038 F->isIntrinsic() || !
F->isDeclarationForLinker())
1048 if (
I != FnsMap.
end()) {
1050 DirectCalledFns.
insert(
I->first);
1056 ++Arm64ECCallsLowered;
1060 if (IndirectCalls.
empty())
1063 for (CallBase *CB : IndirectCalls)
1069char AArch64Arm64ECCallLowering::ID = 0;
1071 "AArch64Arm64ECCallLowering",
false,
false)
1074 return new AArch64Arm64ECCallLowering;
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.
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()
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
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
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