25#include "llvm/IR/IntrinsicsDirectX.h"
34#define DEBUG_TYPE "dxil-op-lower"
52 : M(M), OpBuilder(M), DRM(DRM), DRTM(DRTM), MMDI(MMDI) {}
64 if (
Error E = ReplaceCall(CI)) {
65 std::string Message(
toString(std::move(
E)));
77 struct IntrinArgSelect {
79#define DXIL_OP_INTRINSIC_ARG_SELECT_TYPE(name) name,
80#include "DXILOperation.inc"
90 Error replaceNamedStructUses(CallInst *Intrin, CallInst *DXILOp) {
93 if (!IntrinTy->isLayoutIdentical(DXILOpTy))
95 "Type mismatch between intrinsic and DXIL op",
100 EVI->setOperand(0, DXILOp);
102 IVI->setOperand(0, DXILOp);
105 "be used by insert- and extractvalue",
113 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
114 OpBuilder.getIRB().SetInsertPoint(CI);
116 if (ArgSelects.
size()) {
117 for (
const IntrinArgSelect &
A : ArgSelects) {
119 case IntrinArgSelect::Type::Index:
122 case IntrinArgSelect::Type::I8:
123 Args.push_back(OpBuilder.getIRB().getInt8((uint8_t)
A.Value));
125 case IntrinArgSelect::Type::I32:
126 Args.push_back(OpBuilder.getIRB().getInt32(
A.Value));
134 Expected<CallInst *> OpCall =
135 OpBuilder.tryCreateOp(DXILOp, Args, CI->
getName(),
F.getReturnType());
140 if (
Error E = replaceNamedStructUses(CI, *OpCall))
156 CallInst *Cast = OpBuilder.getIRB().CreateIntrinsic(
157 Intrinsic::dx_resource_casthandle, {Ty,
V->getType()}, {
V});
158 CleanupCasts.push_back(Cast);
162 void cleanupHandleCasts() {
166 for (CallInst *Cast : CleanupCasts) {
175 if (Cast->
getType() != OpBuilder.getHandleType()) {
182 assert(
Def->getIntrinsicID() == Intrinsic::dx_resource_casthandle &&
183 "Unbalanced pair of temporary handle casts");
195 for (Function *
F : CastFns)
196 F->eraseFromParent();
198 CleanupCasts.clear();
201 void cleanupNonUniformResourceIndexCalls() {
212 CleanupNURI->eraseFromParent();
213 CleanupNURI =
nullptr;
221 void removeResourceGlobals(CallInst *CI) {
225 Store->eraseFromParent();
227 if (GV->use_empty()) {
228 GV->removeDeadConstantUsers();
229 GV->eraseFromParent();
235 void replaceHandleFromBindingCall(CallInst *CI,
Value *Replacement) {
237 Intrinsic::dx_resource_handlefrombinding);
239 removeResourceGlobals(CI);
246 if (NameGlobal && NameGlobal->use_empty())
247 NameGlobal->removeFromParent();
250 bool hasNonUniformIndex(
Value *IndexOp) {
257 while (!WorkList.
empty()) {
261 Intrinsic::dx_resource_nonuniformindex)
275 Error validateRawBufferElementIndex(
Value *Resource,
Value *ElementIndex) {
280 if (IsStructured && IsPoison)
282 "Element index of structured buffer may not be poison",
285 if (!IsStructured && !IsPoison)
287 "Element index of raw buffer must be poison",
293 [[nodiscard]]
bool lowerToCreateHandle(Function &
F) {
299 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
302 auto *It = DRM.find(CI);
303 assert(It != DRM.end() &&
"Resource not in map?");
304 dxil::ResourceInfo &RI = *It;
314 bool HasNonUniformIndex =
315 (
Binding.Size == 1) ?
false : hasNonUniformIndex(IndexOp);
316 std::array<Value *, 4>
Args{
319 ConstantInt::get(Int1Ty, HasNonUniformIndex)};
320 Expected<CallInst *> OpCall =
321 OpBuilder.tryCreateOp(OpCode::CreateHandle, Args, CI->
getName());
325 Value *Cast = createTmpHandleCast(*OpCall, CI->
getType());
326 replaceHandleFromBindingCall(CI, Cast);
331 [[nodiscard]]
bool lowerToBindAndAnnotateHandle(Function &
F) {
336 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
339 auto *It = DRM.find(CI);
340 assert(It != DRM.end() &&
"Resource not in map?");
341 dxil::ResourceInfo &RI = *It;
344 dxil::ResourceTypeInfo &RTI = DRTM[RI.
getHandleTy()];
352 std::pair<uint32_t, uint32_t> Props =
357 uint32_t Unbounded = std::numeric_limits<uint32_t>::max();
358 uint32_t UpperBound =
Binding.Size == Unbounded
361 Constant *ResBind = OpBuilder.getResBind(
Binding.LowerBound, UpperBound,
363 bool NonUniformIndex =
364 (
Binding.Size == 1) ?
false : hasNonUniformIndex(IndexOp);
365 Constant *NonUniformOp = ConstantInt::get(Int1Ty, NonUniformIndex);
366 std::array<Value *, 3> BindArgs{ResBind, IndexOp, NonUniformOp};
367 Expected<CallInst *> OpBind = OpBuilder.tryCreateOp(
368 OpCode::CreateHandleFromBinding, BindArgs, CI->
getName());
372 std::array<Value *, 2> AnnotateArgs{
373 *OpBind, OpBuilder.getResProps(Props.first, Props.second)};
374 Expected<CallInst *> OpAnnotate = OpBuilder.tryCreateOp(
375 OpCode::AnnotateHandle, AnnotateArgs,
380 Value *Cast = createTmpHandleCast(*OpAnnotate, CI->
getType());
381 replaceHandleFromBindingCall(CI, Cast);
389 bool lowerHandleFromBinding(Function &
F) {
390 if (MMDI.DXILVersion < VersionTuple(1, 6))
391 return lowerToCreateHandle(
F);
392 return lowerToBindAndAnnotateHandle(
F);
397 Error replaceResRetUses(CallInst *Intrin, CallInst *
Op,
bool HasCheckBit) {
406 Value *CheckOp =
nullptr;
410 ArrayRef<unsigned> Indices = EVI->getIndices();
417 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(
418 OpCode::CheckAccessFullyMapped, {NewEVI},
426 EVI->replaceAllUsesWith(CheckOp);
427 EVI->eraseFromParent();
439 "Expected only use to be extract of first element");
441 OldTy =
ST->getElementType(0);
449 if (OldResult != Intrin) {
456 std::array<Value *, 4> Extracts = {};
464 size_t IndexVal = IndexOp->getZExtValue();
465 assert(IndexVal < 4 &&
"Index into buffer load out of range");
466 if (!Extracts[IndexVal])
469 EEI->eraseFromParent();
477 const unsigned N = VecTy->getNumElements();
481 if (!DynamicAccesses.
empty()) {
485 Type *ElTy = VecTy->getElementType();
486 Type *ArrayTy = ArrayType::get(ElTy,
N);
489 for (
int I = 0,
E =
N;
I !=
E; ++
I) {
497 for (ExtractElementInst *EEI : DynamicAccesses) {
499 {
Zero, EEI->getIndexOperand()});
502 EEI->eraseFromParent();
510 for (
int I = 0,
E =
N;
I !=
E; ++
I)
515 for (
int I = 0,
E =
N;
I !=
E; ++
I)
521 if (OldResult != Intrin) {
529 [[nodiscard]]
bool lowerTypedBufferLoad(Function &
F,
bool HasCheckBit) {
533 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
537 createTmpHandleCast(CI->
getArgOperand(0), OpBuilder.getHandleType());
546 std::array<Value *, 3>
Args{Handle, Index0, Index1};
547 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(
548 OpCode::BufferLoad, Args, CI->
getName(), NewRetTy);
551 if (
Error E = replaceResRetUses(CI, *OpCall, HasCheckBit))
558 [[nodiscard]]
bool lowerRawBufferLoad(Function &
F) {
559 const DataLayout &
DL =
F.getDataLayout();
564 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
569 Type *NewRetTy = OpBuilder.getResRetType(ScalarTy);
572 createTmpHandleCast(CI->
getArgOperand(0), OpBuilder.getHandleType());
575 uint64_t NumElements =
576 DL.getTypeSizeInBits(OldTy) /
DL.getTypeSizeInBits(ScalarTy);
577 Value *
Mask = ConstantInt::get(Int8Ty, ~(~0U << NumElements));
579 ConstantInt::get(
Int32Ty,
DL.getPrefTypeAlign(ScalarTy).value());
586 Expected<CallInst *> OpCall =
587 MMDI.DXILVersion >= VersionTuple(1, 2)
588 ? OpBuilder.tryCreateOp(OpCode::RawBufferLoad,
591 : OpBuilder.tryCreateOp(OpCode::BufferLoad,
592 {Handle, Index0, Index1}, CI->
getName(),
596 if (
Error E = replaceResRetUses(CI, *OpCall,
true))
603 [[nodiscard]]
bool lowerCBufferLoad(Function &
F) {
606 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
611 Type *NewRetTy = OpBuilder.getCBufRetType(ScalarTy);
614 createTmpHandleCast(CI->
getArgOperand(0), OpBuilder.getHandleType());
617 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(
618 OpCode::CBufferLoadLegacy, {Handle,
Index}, CI->
getName(), NewRetTy);
621 if (
Error E = replaceNamedStructUses(CI, *OpCall))
629 [[nodiscard]]
bool lowerUpdateCounter(Function &
F) {
633 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
636 createTmpHandleCast(CI->
getArgOperand(0), OpBuilder.getHandleType());
639 std::array<Value *, 2>
Args{Handle, Op1};
641 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(
653 [[nodiscard]]
bool lowerGetDimensionsX(Function &
F) {
657 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
660 createTmpHandleCast(CI->
getArgOperand(0), OpBuilder.getHandleType());
663 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(
675 [[nodiscard]]
bool lowerGetPointer(Function &
F) {
678 assert(
F.user_empty() &&
"getpointer operations should have been removed");
683 [[nodiscard]]
bool lowerBufferStore(Function &
F,
bool IsRaw) {
684 const DataLayout &
DL =
F.getDataLayout();
689 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
693 createTmpHandleCast(CI->
getArgOperand(0), OpBuilder.getHandleType());
708 uint64_t NumElements =
709 DL.getTypeSizeInBits(DataTy) /
DL.getTypeSizeInBits(ScalarTy);
711 ConstantInt::get(Int8Ty, IsRaw ? ~(~0U << NumElements) : 15U);
716 "Buffer store data must have at most 4 elements",
719 std::array<Value *, 4> DataElements{
nullptr,
nullptr,
nullptr,
nullptr};
720 if (DataTy == ScalarTy)
721 DataElements[0] =
Data;
731 size_t IndexVal = IndexOp->getZExtValue();
732 assert(IndexVal < 4 &&
"Too many elements for buffer store");
733 DataElements[IndexVal] = IEI->getOperand(1);
741 for (
int I = 0,
E = NumElements;
I <
E; ++
I)
742 if (DataElements[
I] ==
nullptr)
749 for (
int I = NumElements,
E = 4;
I <
E; ++
I)
750 if (DataElements[
I] ==
nullptr)
755 Handle, Index0, Index1, DataElements[0],
756 DataElements[1], DataElements[2], DataElements[3],
Mask};
757 if (IsRaw && MMDI.DXILVersion >= VersionTuple(1, 2)) {
758 Op = OpCode::RawBufferStore;
761 ConstantInt::get(
Int32Ty,
DL.getPrefTypeAlign(ScalarTy).value()));
763 Expected<CallInst *> OpCall =
764 OpBuilder.tryCreateOp(
Op, Args, CI->
getName());
771 while (IEI && IEI->use_empty()) {
772 InsertElementInst *Tmp = IEI;
781 [[nodiscard]]
bool lowerCtpopToCountBits(Function &
F) {
785 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
791 Type *FRT =
F.getReturnType();
793 RetTy = VectorType::get(RetTy, VT);
795 Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(
796 dxil::OpCode::CountBits, Args, CI->
getName(), RetTy);
810 CastOp = Instruction::ZExt;
811 CastOp2 = Instruction::SExt;
814 "Currently only lowering 16, 32, or 64 bit ctpop to CountBits \
816 CastOp = Instruction::Trunc;
817 CastOp2 = Instruction::Trunc;
822 bool NeedsCast =
false;
825 if (
I && (
I->getOpcode() == CastOp ||
I->getOpcode() == CastOp2) &&
826 I->getType() == RetTy) {
827 I->replaceAllUsesWith(*OpCall);
828 I->eraseFromParent();
848 [[nodiscard]]
bool lowerLifetimeIntrinsic(Function &
F) {
850 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
854 "Expected operand of lifetime intrinsic to be a pointer");
856 auto ZeroOrUndef = [&](
Type *Ty) {
857 return MMDI.ValidatorVersion < VersionTuple(1, 6)
859 : UndefValue::
get(Ty);
862 Value *Val =
nullptr;
864 if (GV->hasInitializer() || GV->isExternallyInitialized())
866 Val = ZeroOrUndef(GV->getValueType());
868 Val = ZeroOrUndef(AI->getAllocatedType());
870 assert(Val &&
"Expected operand of lifetime intrinsic to be a global "
871 "variable or alloca instruction");
879 [[nodiscard]]
bool lowerIsFPClass(Function &
F) {
883 return replaceFunction(
F, [&](CallInst *CI) ->
Error {
892 switch (TCI->getZExtValue()) {
893 case FPClassTest::fcInf:
894 OpCode = dxil::OpCode::IsInf;
896 case FPClassTest::fcNan:
897 OpCode = dxil::OpCode::IsNaN;
899 case FPClassTest::fcNormal:
900 OpCode = dxil::OpCode::IsNormal;
902 case FPClassTest::fcFinite:
903 OpCode = dxil::OpCode::IsFinite;
906 SmallString<128> Msg =
907 formatv(
"Unsupported FPClassTest {0} for DXIL Op Lowering",
908 TCI->getZExtValue());
912 Expected<CallInst *> OpCall =
923 bool lowerIntrinsics() {
924 bool Updated =
false;
925 bool HasErrors =
false;
928 if (!
F.isDeclaration())
934 case Intrinsic::dx_resource_casthandle:
936 case Intrinsic::dbg_value:
945 SmallString<128> Msg =
formatv(
946 "Unsupported intrinsic {0} for DXIL lowering",
F.getName());
947 M.getContext().emitError(Msg);
952#define DXIL_OP_INTRINSIC(OpCode, Intrin, ...) \
954 HasErrors |= replaceFunctionWithOp( \
955 F, OpCode, ArrayRef<IntrinArgSelect>{__VA_ARGS__}); \
957#include "DXILOperation.inc"
958 case Intrinsic::dx_resource_handlefrombinding:
959 HasErrors |= lowerHandleFromBinding(
F);
961 case Intrinsic::dx_resource_getpointer:
962 HasErrors |= lowerGetPointer(
F);
964 case Intrinsic::dx_resource_nonuniformindex:
966 "overloaded llvm.dx.resource.nonuniformindex intrinsics?");
969 case Intrinsic::dx_resource_load_typedbuffer:
970 HasErrors |= lowerTypedBufferLoad(
F,
true);
972 case Intrinsic::dx_resource_store_typedbuffer:
973 HasErrors |= lowerBufferStore(
F,
false);
975 case Intrinsic::dx_resource_load_rawbuffer:
976 HasErrors |= lowerRawBufferLoad(
F);
978 case Intrinsic::dx_resource_store_rawbuffer:
979 HasErrors |= lowerBufferStore(
F,
true);
981 case Intrinsic::dx_resource_load_cbufferrow_2:
982 case Intrinsic::dx_resource_load_cbufferrow_4:
983 case Intrinsic::dx_resource_load_cbufferrow_8:
984 HasErrors |= lowerCBufferLoad(
F);
986 case Intrinsic::dx_resource_updatecounter:
987 HasErrors |= lowerUpdateCounter(
F);
989 case Intrinsic::dx_resource_getdimensions_x:
990 HasErrors |= lowerGetDimensionsX(
F);
992 case Intrinsic::ctpop:
993 HasErrors |= lowerCtpopToCountBits(
F);
995 case Intrinsic::lifetime_start:
996 case Intrinsic::lifetime_end:
1000 if (MMDI.DXILVersion < VersionTuple(1, 6))
1001 HasErrors |= lowerLifetimeIntrinsic(
F);
1006 case Intrinsic::is_fpclass:
1007 HasErrors |= lowerIsFPClass(
F);
1012 if (Updated && !HasErrors) {
1013 cleanupHandleCasts();
1014 cleanupNonUniformResourceIndexCalls();
1027 const bool MadeChanges = OpLowerer(M, DRM, DRTM, MMDI).lowerIntrinsics();
1039class DXILOpLoweringLegacy :
public ModulePass {
1041 bool runOnModule(
Module &M)
override {
1043 getAnalysis<DXILResourceWrapperPass>().getResourceMap();
1045 getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
1047 getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata();
1049 return OpLowerer(M, DRM, DRTM, MMDI).lowerIntrinsics();
1051 StringRef getPassName()
const override {
return "DXIL Op Lowering"; }
1052 DXILOpLoweringLegacy() : ModulePass(
ID) {}
1055 void getAnalysisUsage(llvm::AnalysisUsage &AU)
const override {
1058 AU.
addRequired<DXILMetadataAnalysisWrapperPass>();
1065char DXILOpLoweringLegacy::ID = 0;
1076 return new DXILOpLoweringLegacy();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefInfo InstSet & ToRemove
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
DXIL Resource Implicit Binding
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
This defines the Use class.
ModuleAnalysisManager MAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file defines the SmallVector class.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
size_t size() const
size - Get the array size.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
Value * getArgOperand(unsigned i) const
User::op_iterator arg_end()
Return the iterator pointing to the end of the argument list.
This class represents a function call, abstracting a target machine's calling convention.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
Diagnostic information for unsupported feature in backend.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Error takeError()
Take ownership of the stored error.
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
AllocaInst * CreateAlloca(Type *Ty, unsigned AddrSpace, Value *ArraySize=nullptr, const Twine &Name="")
IntegerType * getInt1Ty()
Fetch the type representing a single bit.
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Value * CreateZExtOrTrunc(Value *V, Type *DestTy, const Twine &Name="")
Create a ZExt or Trunc from the integer value V to DestTy.
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Value * CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="")
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
A Module instance is used to store all the information related to an LLVM module.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isIntOrIntVectorTy() const
Return true if this is an integer type or a vector of integer types.
bool isPointerTy() const
True if this is an instance of PointerType.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Value * getOperand(unsigned i) const
Type * getType() const
All values are typed, get the type of this value.
user_iterator user_begin()
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
TargetExtType * getHandleTy() const
LLVM_ABI std::pair< uint32_t, uint32_t > getAnnotateProps(Module &M, dxil::ResourceTypeInfo &RTI) const
const ResourceBinding & getBinding() const
dxil::ResourceClass getResourceClass() const
An efficient, type-erasing, non-owning reference to a callable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Undef
Value of the register doesn't matter.
NodeAddr< DefNode * > Def
NodeAddr< UseNode * > Use
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
auto unique(Range &&R, Predicate P)
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
constexpr std::underlying_type_t< Enum > to_underlying(Enum E)
Returns underlying integer value of an enum.
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...
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
ModulePass * createDXILOpLoweringLegacyPass()
Pass to lowering LLVM intrinsic call to DXIL op function call.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.