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;
75 FunctionType *GuardFnType =
nullptr;
76 FunctionType *DispatchFnType =
nullptr;
79 Constant *DispatchFnGlobal =
nullptr;
86 void getThunkType(FunctionType *FT, AttributeList AttrList,
88 FunctionType *&Arm64Ty, FunctionType *&X64Ty,
90 void getThunkRetType(FunctionType *FT, AttributeList AttrList,
91 raw_ostream &Out,
Type *&Arm64RetTy,
Type *&X64RetTy,
92 SmallVectorImpl<Type *> &Arm64ArgTypes,
93 SmallVectorImpl<Type *> &X64ArgTypes,
96 void getThunkArgTypes(FunctionType *FT, AttributeList AttrList,
98 SmallVectorImpl<Type *> &Arm64ArgTypes,
99 SmallVectorImpl<Type *> &X64ArgTypes,
100 SmallVectorImpl<ThunkArgTranslation> &ArgTranslations,
102 ThunkArgInfo canonicalizeThunkType(
Type *
T, Align Alignment,
bool Ret,
103 uint64_t ArgSizeBytes, raw_ostream &Out);
108void AArch64Arm64ECCallLowering::getThunkType(
112 Out << (
TT == Arm64ECThunkType::Entry ?
"$ientry_thunk$cdecl$"
113 :
"$iexit_thunk$cdecl$");
124 if (TT == Arm64ECThunkType::Exit)
128 bool HasSretPtr =
false;
129 getThunkRetType(FT, AttrList, Out, Arm64RetTy, X64RetTy, Arm64ArgTypes,
130 X64ArgTypes, ArgTranslations, HasSretPtr);
132 getThunkArgTypes(FT, AttrList, TT, Out, Arm64ArgTypes, X64ArgTypes,
133 ArgTranslations, HasSretPtr);
135 Arm64Ty = FunctionType::get(Arm64RetTy, Arm64ArgTypes,
false);
137 X64Ty = FunctionType::get(X64RetTy, X64ArgTypes,
false);
140void AArch64Arm64ECCallLowering::getThunkArgTypes(
142 raw_ostream &Out, SmallVectorImpl<Type *> &Arm64ArgTypes,
143 SmallVectorImpl<Type *> &X64ArgTypes,
144 SmallVectorImpl<ThunkArgTranslation> &ArgTranslations,
bool HasSretPtr) {
147 if (FT->isVarArg()) {
170 for (
int i = HasSretPtr ? 1 : 0; i < 4; i++) {
173 ArgTranslations.
push_back(ThunkArgTranslation::Direct);
179 ArgTranslations.
push_back(ThunkArgTranslation::Direct);
182 if (TT != Arm64ECThunkType::Entry) {
186 ArgTranslations.
push_back(ThunkArgTranslation::Direct);
195 if (
I == FT->getNumParams()) {
200 for (
unsigned E = FT->getNumParams();
I !=
E; ++
I) {
204 uint64_t ArgSizeBytes = AttrList.getParamArm64ECArgSizeBytes(
I);
205 Align ParamAlign = AttrList.getParamAlignment(
I).valueOrOne();
210 auto [Arm64Ty, X64Ty, ArgTranslation] =
211 canonicalizeThunkType(FT->getParamType(
I), ParamAlign,
212 false, ArgSizeBytes, Out);
215 ArgTranslations.
push_back(ArgTranslation);
219void AArch64Arm64ECCallLowering::getThunkRetType(
220 FunctionType *FT, AttributeList AttrList, raw_ostream &Out,
221 Type *&Arm64RetTy,
Type *&X64RetTy, SmallVectorImpl<Type *> &Arm64ArgTypes,
222 SmallVectorImpl<Type *> &X64ArgTypes,
224 Type *
T = FT->getReturnType();
228 uint64_t ArgSizeBytes = AttrList.getRetArm64ECArgSizeBytes();
230 int64_t ArgSizeBytes = 0;
233 if (FT->getNumParams()) {
234 Attribute SRetAttr0 = AttrList.getParamAttr(0, Attribute::StructRet);
235 Attribute InRegAttr0 = AttrList.getParamAttr(0, Attribute::InReg);
237 if (FT->getNumParams() > 1) {
241 SRetAttr1 = AttrList.getParamAttr(1, Attribute::StructRet);
242 InRegAttr1 = AttrList.getParamAttr(1, Attribute::InReg);
264 Align SRetAlign = AttrList.getParamAlignment(0).valueOrOne();
265 canonicalizeThunkType(SRetType, SRetAlign,
true, ArgSizeBytes,
269 Arm64ArgTypes.
push_back(FT->getParamType(0));
270 X64ArgTypes.
push_back(FT->getParamType(0));
271 ArgTranslations.
push_back(ThunkArgTranslation::Direct);
284 canonicalizeThunkType(
T,
Align(),
true, ArgSizeBytes, Out);
285 Arm64RetTy =
info.Arm64Ty;
286 X64RetTy =
info.X64Ty;
296ThunkArgInfo AArch64Arm64ECCallLowering::canonicalizeThunkType(
300 auto direct = [](
Type *
T) {
301 return ThunkArgInfo{
T,
T, ThunkArgTranslation::Direct};
304 auto bitcast = [
this](
Type *Arm64Ty,
uint64_t SizeInBytes) {
305 return ThunkArgInfo{Arm64Ty,
307 ThunkArgTranslation::Bitcast};
310 auto pointerIndirection = [
this](
Type *Arm64Ty) {
311 return ThunkArgInfo{Arm64Ty, PtrTy,
312 ThunkArgTranslation::PointerIndirection};
321 if (
T->isBFloatTy()) {
323 Out <<
"__llvm_bf16__";
327 if (
T->isFloatTy()) {
332 if (
T->isDoubleTy()) {
337 if (
T->isFP128Ty()) {
342 return pointerIndirection(
T);
345 if (
T->isFloatingPointTy()) {
347 "Only half, bfloat16, float, double, and fp128 are supported "
348 "for ARM64EC thunks");
354 if (StructTy->getNumElements() == 1)
355 T = StructTy->getElementType(0);
357 if (
T->isArrayTy()) {
358 Type *ElementTy =
T->getArrayElementType();
359 uint64_t ElementCnt =
T->getArrayNumElements();
360 uint64_t ElementSizePerBytes =
DL.getTypeSizeInBits(ElementTy) / 8;
361 uint64_t TotalSizeBytes = ElementCnt * ElementSizePerBytes;
370 Out <<
"__llvm_BF16__";
378 Out << TotalSizeBytes;
381 if (TotalSizeBytes <= 8) {
384 return bitcast(
T, TotalSizeBytes);
387 return pointerIndirection(
T);
391 "Only half, bfloat16, float, double, and fp128 are supported "
392 "for ARM64EC thunks");
396 if ((
T->isIntegerTy() ||
T->isPointerTy()) &&
DL.getTypeSizeInBits(
T) <= 64) {
398 return direct(I64Ty);
401 unsigned TypeSize = ArgSizeBytes;
403 TypeSize =
DL.getTypeSizeInBits(
T) / 8;
410 if (TypeSize == 1 || TypeSize == 2 || TypeSize == 4 || TypeSize == 8) {
412 return bitcast(
T, TypeSize);
415 return pointerIndirection(
T);
421Function *AArch64Arm64ECCallLowering::buildExitThunk(FunctionType *FT,
422 AttributeList Attrs) {
423 SmallString<256> ExitThunkName;
424 llvm::raw_svector_ostream ExitThunkStream(ExitThunkName);
425 FunctionType *Arm64Ty, *X64Ty;
427 getThunkType(FT, Attrs, Arm64ECThunkType::Exit, ExitThunkStream, Arm64Ty,
428 X64Ty, ArgTranslations);
434 F->setCallingConv(CallingConv::ARM64EC_Thunk_Native);
435 F->setSection(
".wowthk$aa");
438 F->addFnAttr(
"frame-pointer",
"all");
442 if (FT->getNumParams()) {
443 auto SRet =
Attrs.getParamAttr(0, Attribute::StructRet);
444 auto InReg =
Attrs.getParamAttr(0, Attribute::InReg);
445 if (SRet.isValid() && !InReg.isValid())
446 F->addParamAttr(1, SRet);
457 FunctionType *DispatcherCallTy = X64Ty;
463 FunctionType::get(X64Ty->getReturnType(), X64Ty->params(),
467 auto X64TyOffset = 1;
468 Args.push_back(
F->arg_begin());
470 Type *RetTy = Arm64Ty->getReturnType();
471 if (RetTy != X64Ty->getReturnType()) {
475 if (
DL.getTypeStoreSize(RetTy) > 8) {
476 Args.push_back(IRB.CreateAlloca(RetTy));
483 make_range(X64Ty->param_begin() + X64TyOffset, X64Ty->param_end()),
499 if (ArgTranslation != ThunkArgTranslation::Direct) {
500 Value *Mem = IRB.CreateAlloca(Arg.getType());
501 IRB.CreateStore(&Arg, Mem);
502 if (ArgTranslation == ThunkArgTranslation::Bitcast) {
503 Type *IntTy = IRB.getIntNTy(
DL.getTypeStoreSizeInBits(Arg.getType()));
504 Args.push_back(IRB.CreateLoad(IntTy, Mem));
506 assert(ArgTranslation == ThunkArgTranslation::PointerIndirection);
510 Args.push_back(&Arg);
516 CallInst *
Call = IRB.CreateCall(DispatcherCallTy, Callee, Args);
520 if (RetTy != X64Ty->getReturnType()) {
523 if (
DL.getTypeStoreSize(RetTy) > 8) {
524 RetVal = IRB.CreateLoad(RetTy, Args[1]);
526 Value *CastAlloca = IRB.CreateAlloca(RetTy);
527 IRB.CreateStore(
Call, CastAlloca);
528 RetVal = IRB.CreateLoad(RetTy, CastAlloca);
535 IRB.CreateRet(RetVal);
542 SmallString<256> EntryThunkName;
543 llvm::raw_svector_ostream EntryThunkStream(EntryThunkName);
544 FunctionType *Arm64Ty, *X64Ty;
546 getThunkType(
F->getFunctionType(),
F->getAttributes(),
547 Arm64ECThunkType::Entry, EntryThunkStream, Arm64Ty, X64Ty,
554 Thunk->setCallingConv(CallingConv::ARM64EC_Thunk_X64);
555 Thunk->setSection(
".wowthk$aa");
558 Thunk->addFnAttr(
"frame-pointer",
"all");
563 Type *RetTy = Arm64Ty->getReturnType();
564 Type *X64RetType = X64Ty->getReturnType();
567 unsigned ThunkArgOffset = TransformDirectToSRet ? 2 : 1;
568 unsigned PassthroughArgSize =
569 (
F->isVarArg() ? 5 :
Thunk->arg_size()) - ThunkArgOffset;
570 assert(ArgTranslations.
size() == (
F->isVarArg() ? 5 : PassthroughArgSize));
574 for (
unsigned i = 0; i != PassthroughArgSize; ++i) {
575 Value *Arg =
Thunk->getArg(i + ThunkArgOffset);
576 Type *ArgTy = Arm64Ty->getParamType(i);
577 ThunkArgTranslation ArgTranslation = ArgTranslations[i];
578 if (ArgTranslation != ThunkArgTranslation::Direct) {
580 if (ArgTranslation == ThunkArgTranslation::Bitcast) {
581 Value *CastAlloca = IRB.CreateAlloca(ArgTy);
582 IRB.CreateStore(Arg, CastAlloca);
583 Arg = IRB.CreateLoad(ArgTy, CastAlloca);
585 assert(ArgTranslation == ThunkArgTranslation::PointerIndirection);
586 Arg = IRB.CreateLoad(ArgTy, Arg);
600 Thunk->addParamAttr(5, Attribute::InReg);
602 Arg = IRB.CreatePtrAdd(Arg, IRB.getInt64(0x20));
606 Args.push_back(IRB.getInt64(0));
611 CallInst *
Call = IRB.CreateCall(Arm64Ty, Callee, Args);
613 auto SRetAttr =
F->
getAttributes().getParamAttr(0, Attribute::StructRet);
614 auto InRegAttr =
F->getAttributes().getParamAttr(0, Attribute::InReg);
615 if (SRetAttr.isValid() && !InRegAttr.isValid()) {
616 Thunk->addParamAttr(1, SRetAttr);
621 if (TransformDirectToSRet) {
626 1, Attribute::getWithStructRetType(M->
getContext(), RetTy));
627 IRB.CreateStore(RetVal,
Thunk->getArg(1));
628 }
else if (X64RetType != RetTy) {
629 Value *CastAlloca = IRB.CreateAlloca(X64RetType);
630 IRB.CreateStore(
Call, CastAlloca);
631 RetVal = IRB.CreateLoad(X64RetType, CastAlloca);
641 IRB.CreateRet(RetVal);
659 llvm::raw_null_ostream NullThunkName;
660 FunctionType *Arm64Ty, *X64Ty;
662 getThunkType(
F->getFunctionType(),
F->getAttributes(),
663 Arm64ECThunkType::GuestExit, NullThunkName, Arm64Ty, X64Ty,
666 assert(MangledName &&
"Can't guest exit to function that's already native");
667 std::string ThunkName = *MangledName;
668 if (ThunkName[0] ==
'?' && ThunkName.find(
"@") != std::string::npos) {
669 ThunkName.insert(ThunkName.find(
"@"),
"$exit_thunk");
671 ThunkName.append(
"$exit_thunk");
678 "arm64ec_unmangled_name",
682 "arm64ec_ecmangled_name",
692 LoadInst *GuardCheckLoad =
B.CreateLoad(PtrTy, GuardFnGlobal);
693 Function *
Thunk = buildExitThunk(
F->getFunctionType(),
F->getAttributes());
694 CallInst *GuardCheck =
B.CreateCall(
695 GuardFnType, GuardCheckLoad, {
F,
Thunk});
696 Value *GuardCheckDest =
B.CreateExtractValue(GuardCheck, 0);
697 Value *GuardFinalDest =
B.CreateExtractValue(GuardCheck, 1);
704 CallInst *
Call =
B.CreateCall(Arm64Ty, GuardCheckDest, Args, OB);
712 auto SRetAttr =
F->getAttributes().getParamAttr(0, Attribute::StructRet);
713 auto InRegAttr =
F->getAttributes().getParamAttr(0, Attribute::InReg);
714 if (SRetAttr.isValid() && !InRegAttr.isValid()) {
723AArch64Arm64ECCallLowering::buildPatchableThunk(GlobalAlias *UnmangledAlias,
724 GlobalAlias *MangledAlias) {
725 llvm::raw_null_ostream NullThunkName;
726 FunctionType *Arm64Ty, *X64Ty;
729 getThunkType(
F->getFunctionType(),
F->getAttributes(),
730 Arm64ECThunkType::GuestExit, NullThunkName, Arm64Ty, X64Ty,
732 std::string ThunkName(MangledAlias->
getName());
733 if (ThunkName[0] ==
'?' && ThunkName.find(
"@") != std::string::npos) {
734 ThunkName.insert(ThunkName.find(
"@"),
"$hybpatch_thunk");
736 ThunkName.append(
"$hybpatch_thunk");
747 LoadInst *DispatchLoad =
B.CreateLoad(PtrTy, DispatchFnGlobal);
751 buildExitThunk(
F->getFunctionType(),
F->getAttributes());
753 B.CreateCall(DispatchFnType, DispatchLoad,
754 {UnmangledAlias, ExitThunk, UnmangledAlias->
getAliasee()});
757 Dispatch->setCallingConv(CallingConv::CFGuard_Check);
768 auto SRetAttr =
F->getAttributes().getParamAttr(0, Attribute::StructRet);
769 auto InRegAttr =
F->getAttributes().getParamAttr(0, Attribute::InReg);
770 if (SRetAttr.isValid() && !InRegAttr.isValid()) {
780void AArch64Arm64ECCallLowering::lowerCall(CallBase *CB) {
792 if ((CFGuardModuleFlag == ControlFlowGuardMode::Enabled) &&
794 GuardFn = GuardFnCFGlobal;
796 GuardFn = GuardFnGlobal;
797 LoadInst *GuardCheckLoad =
B.CreateLoad(PtrTy, GuardFn);
802 CallInst *GuardCheck =
803 B.CreateCall(GuardFnType, GuardCheckLoad, {CalledOperand,
Thunk},
805 Value *GuardCheckDest =
B.CreateExtractValue(GuardCheck, 0);
806 Value *GuardFinalDest =
B.CreateExtractValue(GuardCheck, 1);
817 NewCall->copyMetadata(*CB);
822bool AArch64Arm64ECCallLowering::runOnModule(
Module &
Mod) {
823 if (!AArch64Options::Global.arm64ec_generate_thunks)
832 if (CFGuardModuleFlag == ControlFlowGuardMode::Enabled) {
834 Mod.getModuleFlag(
"cfguard-mechanism"))) {
835 auto MechanismOverride =
837 if (MechanismOverride != ControlFlowGuardMechanism::Automatic &&
838 MechanismOverride != ControlFlowGuardMechanism::Check)
839 Mod.getContext().diagnose(
840 DiagnosticInfoGeneric(
"only the Check Control Flow Guard mechanism "
841 "is supported for Arm64EC",
846 PtrTy = PointerType::getUnqual(M->
getContext());
851 FunctionType::get(
StructType::get(PtrTy, PtrTy), {PtrTy, PtrTy},
false);
852 DispatchFnType = FunctionType::get(PtrTy, {PtrTy, PtrTy, PtrTy},
false);
861 for (GlobalAlias &
A :
Mod.aliases()) {
865 if (std::optional<std::string> MangledName =
867 F->addMetadata(
"arm64ec_unmangled_name",
870 A.setName(MangledName.value());
874 DenseMap<GlobalAlias *, GlobalAlias *> FnsMap;
875 SetVector<GlobalAlias *> PatchableFns;
878 if (
F.hasPersonalityFn()) {
879 GlobalValue *PersFn =
882 if (std::optional<std::string> MangledName =
884 PersFn->
setName(MangledName.value());
889 if (!
F.hasFnAttribute(Attribute::HybridPatchable) ||
890 F.isDeclarationForLinker() ||
F.hasLocalLinkage() ||
896 if (std::optional<std::string> MangledName =
898 std::string OrigName(
F.getName());
910 MangledName.value(), &
F);
911 F.replaceUsesWithIf(AM,
913 F.replaceAllUsesWith(
A);
914 F.setMetadata(
"arm64ec_exp_name",
917 "EXP+" + MangledName.value())));
921 if (
F.hasDLLExportStorageClass()) {
931 SetVector<GlobalValue *> DirectCalledFns;
933 if (!
F.isDeclarationForLinker() &&
934 F.getCallingConv() != CallingConv::ARM64EC_Thunk_Native &&
935 F.getCallingConv() != CallingConv::ARM64EC_Thunk_X64)
945 if (!
F.isDeclarationForLinker() &&
946 (!
F.hasLocalLinkage() ||
F.hasAddressTaken()) &&
947 F.getCallingConv() != CallingConv::ARM64EC_Thunk_Native &&
948 F.getCallingConv() != CallingConv::ARM64EC_Thunk_X64) {
950 F.setComdat(
Mod.getOrInsertComdat(
F.getName()));
952 {&
F, buildEntryThunk(&
F), Arm64ECThunkType::Entry});
955 for (GlobalValue *O : DirectCalledFns) {
959 {
O, buildExitThunk(
F->getFunctionType(),
F->getAttributes()),
960 Arm64ECThunkType::Exit});
961 if (!GA && !
F->hasDLLImportStorageClass())
963 {buildGuestExitThunk(
F),
F, Arm64ECThunkType::GuestExit});
965 for (GlobalAlias *
A : PatchableFns) {
970 if (!ThunkMapping.
empty()) {
972 for (ThunkInfo &Thunk : ThunkMapping) {
979 ThunkMappingArrayElems.
size()),
980 ThunkMappingArrayElems);
981 new GlobalVariable(
Mod, ThunkMappingArray->
getType(),
false,
983 "llvm.arm64ec.symbolmap");
989bool AArch64Arm64ECCallLowering::processFunction(
990 Function &
F, SetVector<GlobalValue *> &DirectCalledFns,
991 DenseMap<GlobalAlias *, GlobalAlias *> &FnsMap) {
1001 if (!
F.hasLocalLinkage() ||
F.hasAddressTaken()) {
1002 if (std::optional<std::string> MangledName =
1004 F.addMetadata(
"arm64ec_unmangled_name",
1007 if (
F.hasComdat() &&
F.getComdat()->getName() ==
F.getName()) {
1011 for (GlobalObject *User : ComdatUsers)
1012 User->setComdat(MangledComdat);
1014 F.setName(MangledName.value());
1022 for (BasicBlock &BB :
F) {
1023 for (Instruction &
I : BB) {
1025 if (!CB || CB->
getCallingConv() == CallingConv::ARM64EC_Thunk_X64 ||
1035 if (!AArch64Options::Global.arm64ec_lower_direct_to_indirect ||
1036 F->hasLocalLinkage() ||
F->isIntrinsic() ||
1037 !
F->isDeclarationForLinker())
1047 if (
I != FnsMap.
end()) {
1049 DirectCalledFns.
insert(
I->first);
1055 ++Arm64ECCallsLowered;
1059 if (IndirectCalls.
empty())
1062 for (CallBase *CB : IndirectCalls)
1068char AArch64Arm64ECCallLowering::ID = 0;
1070 "AArch64Arm64ECCallLowering",
false,
false)
1073 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