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);
462 FunctionType *DispatcherCallTy = X64Ty;
468 FunctionType::get(X64Ty->getReturnType(), X64Ty->params(),
472 auto X64TyOffset = 1;
473 Args.push_back(
F->arg_begin());
475 Type *RetTy = Arm64Ty->getReturnType();
476 if (RetTy != X64Ty->getReturnType()) {
480 if (
DL.getTypeStoreSize(RetTy) > 8) {
481 Args.push_back(IRB.CreateAlloca(RetTy));
488 make_range(X64Ty->param_begin() + X64TyOffset, X64Ty->param_end()),
504 if (ArgTranslation != ThunkArgTranslation::Direct) {
505 Value *Mem = IRB.CreateAlloca(Arg.getType());
506 IRB.CreateStore(&Arg, Mem);
507 if (ArgTranslation == ThunkArgTranslation::Bitcast) {
508 Type *IntTy = IRB.getIntNTy(
DL.getTypeStoreSizeInBits(Arg.getType()));
509 Args.push_back(IRB.CreateLoad(IntTy, Mem));
511 assert(ArgTranslation == ThunkArgTranslation::PointerIndirection);
515 Args.push_back(&Arg);
521 CallInst *
Call = IRB.CreateCall(DispatcherCallTy, Callee, Args);
525 if (RetTy != X64Ty->getReturnType()) {
528 if (
DL.getTypeStoreSize(RetTy) > 8) {
529 RetVal = IRB.CreateLoad(RetTy, Args[1]);
531 Value *CastAlloca = IRB.CreateAlloca(RetTy);
532 IRB.CreateStore(
Call, CastAlloca);
533 RetVal = IRB.CreateLoad(RetTy, CastAlloca);
540 IRB.CreateRet(RetVal);
546Function *AArch64Arm64ECCallLowering::buildEntryThunk(Function *
F) {
547 SmallString<256> EntryThunkName;
548 llvm::raw_svector_ostream EntryThunkStream(EntryThunkName);
549 FunctionType *Arm64Ty, *X64Ty;
551 getThunkType(
F->getFunctionType(),
F->getAttributes(),
552 Arm64ECThunkType::Entry, EntryThunkStream, Arm64Ty, X64Ty,
559 Thunk->setCallingConv(CallingConv::ARM64EC_Thunk_X64);
560 Thunk->setSection(
".wowthk$aa");
563 Thunk->addFnAttr(
"frame-pointer",
"all");
568 Type *RetTy = Arm64Ty->getReturnType();
569 Type *X64RetType = X64Ty->getReturnType();
572 unsigned ThunkArgOffset = TransformDirectToSRet ? 2 : 1;
573 unsigned PassthroughArgSize =
574 (
F->isVarArg() ? 5 :
Thunk->arg_size()) - ThunkArgOffset;
575 assert(ArgTranslations.
size() == (
F->isVarArg() ? 5 : PassthroughArgSize));
579 for (
unsigned i = 0; i != PassthroughArgSize; ++i) {
580 Value *Arg =
Thunk->getArg(i + ThunkArgOffset);
581 Type *ArgTy = Arm64Ty->getParamType(i);
582 ThunkArgTranslation ArgTranslation = ArgTranslations[i];
583 if (ArgTranslation != ThunkArgTranslation::Direct) {
585 if (ArgTranslation == ThunkArgTranslation::Bitcast) {
586 Value *CastAlloca = IRB.CreateAlloca(ArgTy);
587 IRB.CreateStore(Arg, CastAlloca);
588 Arg = IRB.CreateLoad(ArgTy, CastAlloca);
590 assert(ArgTranslation == ThunkArgTranslation::PointerIndirection);
591 Arg = IRB.CreateLoad(ArgTy, Arg);
605 Thunk->addParamAttr(5, Attribute::InReg);
607 Arg = IRB.CreatePtrAdd(Arg, IRB.getInt64(0x20));
611 Args.push_back(IRB.getInt64(0));
616 CallInst *
Call = IRB.CreateCall(Arm64Ty, Callee, Args);
618 auto SRetAttr =
F->
getAttributes().getParamAttr(0, Attribute::StructRet);
619 auto InRegAttr =
F->getAttributes().getParamAttr(0, Attribute::InReg);
620 if (SRetAttr.isValid() && !InRegAttr.isValid()) {
621 Thunk->addParamAttr(1, SRetAttr);
626 if (TransformDirectToSRet) {
631 1, Attribute::getWithStructRetType(M->
getContext(), RetTy));
632 IRB.CreateStore(RetVal,
Thunk->getArg(1));
633 }
else if (X64RetType != RetTy) {
634 Value *CastAlloca = IRB.CreateAlloca(X64RetType);
635 IRB.CreateStore(
Call, CastAlloca);
636 RetVal = IRB.CreateLoad(X64RetType, CastAlloca);
646 IRB.CreateRet(RetVal);
663Function *AArch64Arm64ECCallLowering::buildGuestExitThunk(Function *
F) {
664 llvm::raw_null_ostream NullThunkName;
665 FunctionType *Arm64Ty, *X64Ty;
667 getThunkType(
F->getFunctionType(),
F->getAttributes(),
668 Arm64ECThunkType::GuestExit, NullThunkName, Arm64Ty, X64Ty,
671 assert(MangledName &&
"Can't guest exit to function that's already native");
672 std::string ThunkName = *MangledName;
673 if (ThunkName[0] ==
'?' && ThunkName.find(
"@") != std::string::npos) {
674 ThunkName.insert(ThunkName.find(
"@"),
"$exit_thunk");
676 ThunkName.append(
"$exit_thunk");
683 "arm64ec_unmangled_name",
687 "arm64ec_ecmangled_name",
697 LoadInst *GuardCheckLoad =
B.CreateLoad(PtrTy, GuardFnGlobal);
698 Function *
Thunk = buildExitThunk(
F->getFunctionType(),
F->getAttributes());
699 CallInst *GuardCheck =
B.CreateCall(
700 GuardFnType, GuardCheckLoad, {
F,
Thunk});
701 Value *GuardCheckDest =
B.CreateExtractValue(GuardCheck, 0);
702 Value *GuardFinalDest =
B.CreateExtractValue(GuardCheck, 1);
709 CallInst *
Call =
B.CreateCall(Arm64Ty, GuardCheckDest, Args, OB);
717 auto SRetAttr =
F->getAttributes().getParamAttr(0, Attribute::StructRet);
718 auto InRegAttr =
F->getAttributes().getParamAttr(0, Attribute::InReg);
719 if (SRetAttr.isValid() && !InRegAttr.isValid()) {
728AArch64Arm64ECCallLowering::buildPatchableThunk(GlobalAlias *UnmangledAlias,
729 GlobalAlias *MangledAlias) {
730 llvm::raw_null_ostream NullThunkName;
731 FunctionType *Arm64Ty, *X64Ty;
734 getThunkType(
F->getFunctionType(),
F->getAttributes(),
735 Arm64ECThunkType::GuestExit, NullThunkName, Arm64Ty, X64Ty,
737 std::string ThunkName(MangledAlias->
getName());
738 if (ThunkName[0] ==
'?' && ThunkName.find(
"@") != std::string::npos) {
739 ThunkName.insert(ThunkName.find(
"@"),
"$hybpatch_thunk");
741 ThunkName.append(
"$hybpatch_thunk");
752 LoadInst *DispatchLoad =
B.CreateLoad(PtrTy, DispatchFnGlobal);
756 buildExitThunk(
F->getFunctionType(),
F->getAttributes());
758 B.CreateCall(DispatchFnType, DispatchLoad,
759 {UnmangledAlias, ExitThunk, UnmangledAlias->
getAliasee()});
762 Dispatch->setCallingConv(CallingConv::CFGuard_Check);
773 auto SRetAttr =
F->getAttributes().getParamAttr(0, Attribute::StructRet);
774 auto InRegAttr =
F->getAttributes().getParamAttr(0, Attribute::InReg);
775 if (SRetAttr.isValid() && !InRegAttr.isValid()) {
785void AArch64Arm64ECCallLowering::lowerCall(CallBase *CB) {
797 if ((CFGuardModuleFlag == ControlFlowGuardMode::Enabled) &&
799 GuardFn = GuardFnCFGlobal;
801 GuardFn = GuardFnGlobal;
802 LoadInst *GuardCheckLoad =
B.CreateLoad(PtrTy, GuardFn);
807 CallInst *GuardCheck =
808 B.CreateCall(GuardFnType, GuardCheckLoad, {CalledOperand,
Thunk},
810 Value *GuardCheckDest =
B.CreateExtractValue(GuardCheck, 0);
811 Value *GuardFinalDest =
B.CreateExtractValue(GuardCheck, 1);
822 NewCall->copyMetadata(*CB);
827bool AArch64Arm64ECCallLowering::runOnModule(
Module &
Mod) {
837 if (CFGuardModuleFlag == ControlFlowGuardMode::Enabled) {
839 Mod.getModuleFlag(
"cfguard-mechanism"))) {
840 auto MechanismOverride =
842 if (MechanismOverride != ControlFlowGuardMechanism::Automatic &&
843 MechanismOverride != ControlFlowGuardMechanism::Check)
844 Mod.getContext().diagnose(
845 DiagnosticInfoGeneric(
"only the Check Control Flow Guard mechanism "
846 "is supported for Arm64EC",
851 PtrTy = PointerType::getUnqual(M->
getContext());
856 FunctionType::get(
StructType::get(PtrTy, PtrTy), {PtrTy, PtrTy},
false);
857 DispatchFnType = FunctionType::get(PtrTy, {PtrTy, PtrTy, PtrTy},
false);
866 for (GlobalAlias &
A :
Mod.aliases()) {
870 if (std::optional<std::string> MangledName =
872 F->addMetadata(
"arm64ec_unmangled_name",
875 A.setName(MangledName.value());
879 DenseMap<GlobalAlias *, GlobalAlias *> FnsMap;
880 SetVector<GlobalAlias *> PatchableFns;
882 for (Function &
F :
Mod) {
883 if (
F.hasPersonalityFn()) {
884 GlobalValue *PersFn =
887 if (std::optional<std::string> MangledName =
889 PersFn->
setName(MangledName.value());
894 if (!
F.hasFnAttribute(Attribute::HybridPatchable) ||
895 F.isDeclarationForLinker() ||
F.hasLocalLinkage() ||
901 if (std::optional<std::string> MangledName =
903 std::string OrigName(
F.getName());
915 MangledName.value(), &
F);
916 F.replaceUsesWithIf(AM,
918 F.replaceAllUsesWith(
A);
919 F.setMetadata(
"arm64ec_exp_name",
922 "EXP+" + MangledName.value())));
926 if (
F.hasDLLExportStorageClass()) {
936 SetVector<GlobalValue *> DirectCalledFns;
937 for (Function &
F :
Mod)
938 if (!
F.isDeclarationForLinker() &&
939 F.getCallingConv() != CallingConv::ARM64EC_Thunk_Native &&
940 F.getCallingConv() != CallingConv::ARM64EC_Thunk_X64)
949 for (Function &
F :
Mod) {
950 if (!
F.isDeclarationForLinker() &&
951 (!
F.hasLocalLinkage() ||
F.hasAddressTaken()) &&
952 F.getCallingConv() != CallingConv::ARM64EC_Thunk_Native &&
953 F.getCallingConv() != CallingConv::ARM64EC_Thunk_X64) {
955 F.setComdat(
Mod.getOrInsertComdat(
F.getName()));
957 {&
F, buildEntryThunk(&
F), Arm64ECThunkType::Entry});
960 for (GlobalValue *O : DirectCalledFns) {
964 {
O, buildExitThunk(
F->getFunctionType(),
F->getAttributes()),
965 Arm64ECThunkType::Exit});
966 if (!GA && !
F->hasDLLImportStorageClass())
968 {buildGuestExitThunk(
F),
F, Arm64ECThunkType::GuestExit});
970 for (GlobalAlias *
A : PatchableFns) {
975 if (!ThunkMapping.
empty()) {
977 for (ThunkInfo &Thunk : ThunkMapping) {
984 ThunkMappingArrayElems.
size()),
985 ThunkMappingArrayElems);
986 new GlobalVariable(
Mod, ThunkMappingArray->
getType(),
false,
988 "llvm.arm64ec.symbolmap");
994bool AArch64Arm64ECCallLowering::processFunction(
995 Function &
F, SetVector<GlobalValue *> &DirectCalledFns,
996 DenseMap<GlobalAlias *, GlobalAlias *> &FnsMap) {
1006 if (!
F.hasLocalLinkage() ||
F.hasAddressTaken()) {
1007 if (std::optional<std::string> MangledName =
1009 F.addMetadata(
"arm64ec_unmangled_name",
1012 if (
F.hasComdat() &&
F.getComdat()->getName() ==
F.getName()) {
1016 for (GlobalObject *User : ComdatUsers)
1017 User->setComdat(MangledComdat);
1019 F.setName(MangledName.value());
1027 for (BasicBlock &BB :
F) {
1028 for (Instruction &
I : BB) {
1030 if (!CB || CB->
getCallingConv() == CallingConv::ARM64EC_Thunk_X64 ||
1041 F->isIntrinsic() || !
F->isDeclarationForLinker())
1051 if (
I != FnsMap.
end()) {
1053 DirectCalledFns.
insert(
I->first);
1059 ++Arm64ECCallsLowered;
1063 if (IndirectCalls.
empty())
1066 for (CallBase *CB : IndirectCalls)
1072char AArch64Arm64ECCallLowering::ID = 0;
1074 "AArch64Arm64ECCallLowering",
false,
false)
1077 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.