X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=include%2Fllvm%2FIR%2FIRBuilder.h;h=8d365a0cc9936ca869e96b60a08791e27d4b2921;hp=27f990ed2c288827fead9a1d812bdad29a1b4149;hb=4c12d595707075f400c00f54da56650c9f46b7e3;hpb=0b8c9a80f20772c3793201ab5b251d3520b9cea3 diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index 27f990ed2c2..8d365a0cc99 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -12,26 +12,31 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_IRBUILDER_H -#define LLVM_IRBUILDER_H +#ifndef LLVM_IR_IRBUILDER_H +#define LLVM_IR_IRBUILDER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/IR/BasicBlock.h" +#include "llvm/IR/ConstantFolder.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Operator.h" -#include "llvm/Support/ConstantFolder.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Support/CBindingWrapping.h" namespace llvm { - class MDNode; +class MDNode; -/// IRBuilderDefaultInserter - This provides the default implementation of the -/// IRBuilder 'InsertHelper' method that is called whenever an instruction is -/// created by IRBuilder and needs to be inserted. By default, this inserts the -/// instruction at the insertion point. +/// \brief This provides the default implementation of the IRBuilder +/// 'InsertHelper' method that is called whenever an instruction is created by +/// IRBuilder and needs to be inserted. +/// +/// By default, this inserts the instruction at the insertion point. template class IRBuilderDefaultInserter { protected: @@ -43,17 +48,20 @@ protected: } }; -/// IRBuilderBase - Common base class shared among various IRBuilders. +/// \brief Common base class shared among various IRBuilders. class IRBuilderBase { DebugLoc CurDbgLocation; protected: BasicBlock *BB; BasicBlock::iterator InsertPt; LLVMContext &Context; + + MDNode *DefaultFPMathTag; + FastMathFlags FMF; public: - IRBuilderBase(LLVMContext &context) - : Context(context) { + IRBuilderBase(LLVMContext &context, MDNode *FPMathTag = nullptr) + : Context(context), DefaultFPMathTag(FPMathTag), FMF() { ClearInsertionPoint(); } @@ -61,70 +69,57 @@ public: // Builder configuration methods //===--------------------------------------------------------------------===// - /// ClearInsertionPoint - Clear the insertion point: created instructions will - /// not be inserted into a block. + /// \brief Clear the insertion point: created instructions will not be + /// inserted into a block. void ClearInsertionPoint() { - BB = 0; + BB = nullptr; + InsertPt = nullptr; } BasicBlock *GetInsertBlock() const { return BB; } BasicBlock::iterator GetInsertPoint() const { return InsertPt; } LLVMContext &getContext() const { return Context; } - /// SetInsertPoint - This specifies that created instructions should be - /// appended to the end of the specified block. + /// \brief This specifies that created instructions should be appended to the + /// end of the specified block. void SetInsertPoint(BasicBlock *TheBB) { BB = TheBB; InsertPt = BB->end(); } - /// SetInsertPoint - This specifies that created instructions should be - /// inserted before the specified instruction. + /// \brief This specifies that created instructions should be inserted before + /// the specified instruction. void SetInsertPoint(Instruction *I) { BB = I->getParent(); InsertPt = I; + assert(I != BB->end() && "Can't read debug loc from end()"); SetCurrentDebugLocation(I->getDebugLoc()); } - /// SetInsertPoint - This specifies that created instructions should be - /// inserted at the specified point. + /// \brief This specifies that created instructions should be inserted at the + /// specified point. void SetInsertPoint(BasicBlock *TheBB, BasicBlock::iterator IP) { BB = TheBB; InsertPt = IP; + if (IP != TheBB->end()) + SetCurrentDebugLocation(IP->getDebugLoc()); } - /// SetInsertPoint(Use) - Find the nearest point that dominates this use, and - /// specify that created instructions should be inserted at this point. - void SetInsertPoint(Use &U) { - Instruction *UseInst = cast(U.getUser()); - if (PHINode *Phi = dyn_cast(UseInst)) { - BasicBlock *PredBB = Phi->getIncomingBlock(U); - assert(U != PredBB->getTerminator() && "critical edge not split"); - SetInsertPoint(PredBB, PredBB->getTerminator()); - return; - } - SetInsertPoint(UseInst); - } - - /// SetCurrentDebugLocation - Set location information used by debugging - /// information. - void SetCurrentDebugLocation(const DebugLoc &L) { - CurDbgLocation = L; - } + /// \brief Set location information used by debugging information. + void SetCurrentDebugLocation(DebugLoc L) { CurDbgLocation = std::move(L); } - /// getCurrentDebugLocation - Get location information used by debugging - /// information. - DebugLoc getCurrentDebugLocation() const { return CurDbgLocation; } + /// \brief Get location information used by debugging information. + const DebugLoc &getCurrentDebugLocation() const { return CurDbgLocation; } - /// SetInstDebugLocation - If this builder has a current debug location, set - /// it on the specified instruction. + /// \brief If this builder has a current debug location, set it on the + /// specified instruction. void SetInstDebugLocation(Instruction *I) const { - if (!CurDbgLocation.isUnknown()) + if (CurDbgLocation) I->setDebugLoc(CurDbgLocation); } - /// getCurrentFunctionReturnType - Get the return type of the current function - /// that we're emitting into. + /// \brief Get the return type of the current function that we're emitting + /// into. Type *getCurrentFunctionReturnType() const; /// InsertPoint - A saved insertion point. @@ -133,35 +128,33 @@ public: BasicBlock::iterator Point; public: - /// Creates a new insertion point which doesn't point to anything. - InsertPoint() : Block(0) {} + /// \brief Creates a new insertion point which doesn't point to anything. + InsertPoint() : Block(nullptr) {} - /// Creates a new insertion point at the given location. + /// \brief Creates a new insertion point at the given location. InsertPoint(BasicBlock *InsertBlock, BasicBlock::iterator InsertPoint) : Block(InsertBlock), Point(InsertPoint) {} - /// isSet - Returns true if this insert point is set. - bool isSet() const { return (Block != 0); } + /// \brief Returns true if this insert point is set. + bool isSet() const { return (Block != nullptr); } llvm::BasicBlock *getBlock() const { return Block; } llvm::BasicBlock::iterator getPoint() const { return Point; } }; - /// saveIP - Returns the current insert point. + /// \brief Returns the current insert point. InsertPoint saveIP() const { return InsertPoint(GetInsertBlock(), GetInsertPoint()); } - /// saveAndClearIP - Returns the current insert point, clearing it - /// in the process. + /// \brief Returns the current insert point, clearing it in the process. InsertPoint saveAndClearIP() { InsertPoint IP(GetInsertBlock(), GetInsertPoint()); ClearInsertionPoint(); return IP; } - /// restoreIP - Sets the current insert point to a previously-saved - /// location. + /// \brief Sets the current insert point to a previously-saved location. void restoreIP(InsertPoint IP) { if (IP.isSet()) SetInsertPoint(IP.getBlock(), IP.getPoint()); @@ -169,53 +162,123 @@ public: ClearInsertionPoint(); } + /// \brief Get the floating point math metadata being used. + MDNode *getDefaultFPMathTag() const { return DefaultFPMathTag; } + + /// \brief Get the flags to be applied to created floating point ops + FastMathFlags getFastMathFlags() const { return FMF; } + + /// \brief Clear the fast-math flags. + void clearFastMathFlags() { FMF.clear(); } + + /// \brief Set the floating point math metadata to be used. + void SetDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; } + + /// \brief Set the fast-math flags to be used with generated fp-math operators + void SetFastMathFlags(FastMathFlags NewFMF) { FMF = NewFMF; } + //===--------------------------------------------------------------------===// - // Miscellaneous creation methods. + // RAII helpers. //===--------------------------------------------------------------------===// - /// CreateGlobalString - Make a new global variable with an initializer that - /// has array of i8 type filled in with the nul terminated string value - /// specified. The new global variable will be marked mergable with any - /// others of the same contents. If Name is specified, it is the name of the - /// global variable created. - Value *CreateGlobalString(StringRef Str, const Twine &Name = ""); + // \brief RAII object that stores the current insertion point and restores it + // when the object is destroyed. This includes the debug location. + class InsertPointGuard { + IRBuilderBase &Builder; + AssertingVH Block; + BasicBlock::iterator Point; + DebugLoc DbgLoc; + + InsertPointGuard(const InsertPointGuard &) = delete; + InsertPointGuard &operator=(const InsertPointGuard &) = delete; + + public: + InsertPointGuard(IRBuilderBase &B) + : Builder(B), Block(B.GetInsertBlock()), Point(B.GetInsertPoint()), + DbgLoc(B.getCurrentDebugLocation()) {} + + ~InsertPointGuard() { + Builder.restoreIP(InsertPoint(Block, Point)); + Builder.SetCurrentDebugLocation(DbgLoc); + } + }; + + // \brief RAII object that stores the current fast math settings and restores + // them when the object is destroyed. + class FastMathFlagGuard { + IRBuilderBase &Builder; + FastMathFlags FMF; + MDNode *FPMathTag; + + FastMathFlagGuard(const FastMathFlagGuard &) = delete; + FastMathFlagGuard &operator=( + const FastMathFlagGuard &) = delete; + + public: + FastMathFlagGuard(IRBuilderBase &B) + : Builder(B), FMF(B.FMF), FPMathTag(B.DefaultFPMathTag) {} + + ~FastMathFlagGuard() { + Builder.FMF = FMF; + Builder.DefaultFPMathTag = FPMathTag; + } + }; + + //===--------------------------------------------------------------------===// + // Miscellaneous creation methods. + //===--------------------------------------------------------------------===// - /// getInt1 - Get a constant value representing either true or false. + /// \brief Make a new global variable with initializer type i8* + /// + /// Make a new global variable with an initializer that has array of i8 type + /// filled in with the null terminated string value specified. The new global + /// variable will be marked mergable with any others of the same contents. If + /// Name is specified, it is the name of the global variable created. + GlobalVariable *CreateGlobalString(StringRef Str, const Twine &Name = "", + unsigned AddressSpace = 0); + + /// \brief Get a constant value representing either true or false. ConstantInt *getInt1(bool V) { return ConstantInt::get(getInt1Ty(), V); } - /// getTrue - Get the constant value for i1 true. + /// \brief Get the constant value for i1 true. ConstantInt *getTrue() { return ConstantInt::getTrue(Context); } - /// getFalse - Get the constant value for i1 false. + /// \brief Get the constant value for i1 false. ConstantInt *getFalse() { return ConstantInt::getFalse(Context); } - /// getInt8 - Get a constant 8-bit value. + /// \brief Get a constant 8-bit value. ConstantInt *getInt8(uint8_t C) { return ConstantInt::get(getInt8Ty(), C); } - /// getInt16 - Get a constant 16-bit value. + /// \brief Get a constant 16-bit value. ConstantInt *getInt16(uint16_t C) { return ConstantInt::get(getInt16Ty(), C); } - /// getInt32 - Get a constant 32-bit value. + /// \brief Get a constant 32-bit value. ConstantInt *getInt32(uint32_t C) { return ConstantInt::get(getInt32Ty(), C); } - /// getInt64 - Get a constant 64-bit value. + /// \brief Get a constant 64-bit value. ConstantInt *getInt64(uint64_t C) { return ConstantInt::get(getInt64Ty(), C); } - /// getInt - Get a constant integer value. + /// \brief Get a constant N-bit value, zero extended or truncated from + /// a 64-bit value. + ConstantInt *getIntN(unsigned N, uint64_t C) { + return ConstantInt::get(getIntNTy(N), C); + } + + /// \brief Get a constant integer value. ConstantInt *getInt(const APInt &AI) { return ConstantInt::get(Context, AI); } @@ -224,109 +287,218 @@ public: // Type creation methods //===--------------------------------------------------------------------===// - /// getInt1Ty - Fetch the type representing a single bit + /// \brief Fetch the type representing a single bit IntegerType *getInt1Ty() { return Type::getInt1Ty(Context); } - /// getInt8Ty - Fetch the type representing an 8-bit integer. + /// \brief Fetch the type representing an 8-bit integer. IntegerType *getInt8Ty() { return Type::getInt8Ty(Context); } - /// getInt16Ty - Fetch the type representing a 16-bit integer. + /// \brief Fetch the type representing a 16-bit integer. IntegerType *getInt16Ty() { return Type::getInt16Ty(Context); } - /// getInt32Ty - Fetch the type representing a 32-bit integer. + /// \brief Fetch the type representing a 32-bit integer. IntegerType *getInt32Ty() { return Type::getInt32Ty(Context); } - /// getInt64Ty - Fetch the type representing a 64-bit integer. + /// \brief Fetch the type representing a 64-bit integer. IntegerType *getInt64Ty() { return Type::getInt64Ty(Context); } - /// getFloatTy - Fetch the type representing a 32-bit floating point value. + /// \brief Fetch the type representing a 128-bit integer. + IntegerType *getInt128Ty() { + return Type::getInt128Ty(Context); + } + + /// \brief Fetch the type representing an N-bit integer. + IntegerType *getIntNTy(unsigned N) { + return Type::getIntNTy(Context, N); + } + + /// \brief Fetch the type representing a 16-bit floating point value. + Type *getHalfTy() { + return Type::getHalfTy(Context); + } + + /// \brief Fetch the type representing a 32-bit floating point value. Type *getFloatTy() { return Type::getFloatTy(Context); } - /// getDoubleTy - Fetch the type representing a 64-bit floating point value. + /// \brief Fetch the type representing a 64-bit floating point value. Type *getDoubleTy() { return Type::getDoubleTy(Context); } - /// getVoidTy - Fetch the type representing void. + /// \brief Fetch the type representing void. Type *getVoidTy() { return Type::getVoidTy(Context); } + /// \brief Fetch the type representing a pointer to an 8-bit integer value. PointerType *getInt8PtrTy(unsigned AddrSpace = 0) { return Type::getInt8PtrTy(Context, AddrSpace); } - IntegerType* getIntPtrTy(DataLayout *DL, unsigned AddrSpace = 0) { - return DL->getIntPtrType(Context, AddrSpace); + /// \brief Fetch the type representing a pointer to an integer value. + IntegerType *getIntPtrTy(const DataLayout &DL, unsigned AddrSpace = 0) { + return DL.getIntPtrType(Context, AddrSpace); } //===--------------------------------------------------------------------===// // Intrinsic creation methods //===--------------------------------------------------------------------===// - /// CreateMemSet - Create and insert a memset to the specified pointer and the - /// specified value. If the pointer isn't an i8*, it will be converted. If a - /// TBAA tag is specified, it will be added to the instruction. + /// \brief Create and insert a memset to the specified pointer and the + /// specified value. + /// + /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is + /// specified, it will be added to the instruction. Likewise with alias.scope + /// and noalias tags. CallInst *CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0) { - return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, TBAATag); + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr) { + return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, + TBAATag, ScopeTag, NoAliasTag); } CallInst *CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0); + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr); - /// CreateMemCpy - Create and insert a memcpy between the specified pointers. + /// \brief Create and insert a memcpy between the specified pointers. + /// /// If the pointers aren't i8*, they will be converted. If a TBAA tag is - /// specified, it will be added to the instruction. + /// specified, it will be added to the instruction. Likewise with alias.scope + /// and noalias tags. CallInst *CreateMemCpy(Value *Dst, Value *Src, uint64_t Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0, - MDNode *TBAAStructTag = 0) { + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *TBAAStructTag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr) { return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag, - TBAAStructTag); + TBAAStructTag, ScopeTag, NoAliasTag); } CallInst *CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0, - MDNode *TBAAStructTag = 0); + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *TBAAStructTag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr); - /// CreateMemMove - Create and insert a memmove between the specified - /// pointers. If the pointers aren't i8*, they will be converted. If a TBAA - /// tag is specified, it will be added to the instruction. + /// \brief Create and insert a memmove between the specified + /// pointers. + /// + /// If the pointers aren't i8*, they will be converted. If a TBAA tag is + /// specified, it will be added to the instruction. Likewise with alias.scope + /// and noalias tags. CallInst *CreateMemMove(Value *Dst, Value *Src, uint64_t Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0) { - return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr) { + return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, + TBAATag, ScopeTag, NoAliasTag); } CallInst *CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0); + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr); - /// CreateLifetimeStart - Create a lifetime.start intrinsic. If the pointer - /// isn't i8* it will be converted. - CallInst *CreateLifetimeStart(Value *Ptr, ConstantInt *Size = 0); + /// \brief Create a lifetime.start intrinsic. + /// + /// If the pointer isn't i8* it will be converted. + CallInst *CreateLifetimeStart(Value *Ptr, ConstantInt *Size = nullptr); - /// CreateLifetimeEnd - Create a lifetime.end intrinsic. If the pointer isn't - /// i8* it will be converted. - CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = 0); + /// \brief Create a lifetime.end intrinsic. + /// + /// If the pointer isn't i8* it will be converted. + CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = nullptr); + + /// \brief Create a call to Masked Load intrinsic + CallInst *CreateMaskedLoad(Value *Ptr, unsigned Align, Value *Mask, + Value *PassThru = 0, const Twine &Name = ""); + + /// \brief Create a call to Masked Store intrinsic + CallInst *CreateMaskedStore(Value *Val, Value *Ptr, unsigned Align, + Value *Mask); + + /// \brief Create an assume intrinsic call that allows the optimizer to + /// assume that the provided condition will be true. + CallInst *CreateAssumption(Value *Cond); + + /// \brief Create a call to the experimental.gc.statepoint intrinsic to + /// start a new statepoint sequence. + CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes, + Value *ActualCallee, + ArrayRef CallArgs, + ArrayRef DeoptArgs, + ArrayRef GCArgs, + const Twine &Name = ""); + + // \brief Conveninence function for the common case when CallArgs are filled + // in using makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be + // .get()'ed to get the Value pointer. + CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes, + Value *ActualCallee, ArrayRef CallArgs, + ArrayRef DeoptArgs, + ArrayRef GCArgs, + const Twine &Name = ""); + + /// brief Create an invoke to the experimental.gc.statepoint intrinsic to + /// start a new statepoint sequence. + InvokeInst * + CreateGCStatepointInvoke(uint64_t ID, uint32_t NumPatchBytes, + Value *ActualInvokee, BasicBlock *NormalDest, + BasicBlock *UnwindDest, ArrayRef InvokeArgs, + ArrayRef DeoptArgs, + ArrayRef GCArgs, const Twine &Name = ""); + + // Conveninence function for the common case when CallArgs are filled in using + // makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be .get()'ed to + // get the Value *. + InvokeInst * + CreateGCStatepointInvoke(uint64_t ID, uint32_t NumPatchBytes, + Value *ActualInvokee, BasicBlock *NormalDest, + BasicBlock *UnwindDest, ArrayRef InvokeArgs, + ArrayRef DeoptArgs, + ArrayRef GCArgs, const Twine &Name = ""); + + /// \brief Create a call to the experimental.gc.result intrinsic to extract + /// the result from a call wrapped in a statepoint. + CallInst *CreateGCResult(Instruction *Statepoint, + Type *ResultType, + const Twine &Name = ""); + + /// \brief Create a call to the experimental.gc.relocate intrinsics to + /// project the relocated value of one pointer from the statepoint. + CallInst *CreateGCRelocate(Instruction *Statepoint, + int BaseOffset, + int DerivedOffset, + Type *ResultType, + const Twine &Name = ""); private: + /// \brief Create a call to a masked intrinsic with given Id. + /// Masked intrinsic has only one overloaded type - data type. + CallInst *CreateMaskedIntrinsic(Intrinsic::ID Id, ArrayRef Ops, + Type *DataTy, const Twine &Name = ""); + Value *getCastedInt8PtrValue(Value *Ptr); }; -/// IRBuilder - This provides a uniform API for creating instructions and -/// inserting them into a basic block: either at the end of a BasicBlock, or -/// at a specific iterator location in a block. +/// \brief This provides a uniform API for creating instructions and inserting +/// them into a basic block: either at the end of a BasicBlock, or at a specific +/// iterator location in a block. /// /// Note that the builder does not expose the full generality of LLVM /// instructions. For access to extra instruction properties, use the mutators @@ -337,97 +509,65 @@ private: /// The first template argument handles whether or not to preserve names in the /// final instruction output. This defaults to on. The second template argument /// specifies a class to use for creating constants. This defaults to creating -/// minimally folded constants. The fourth template argument allows clients to +/// minimally folded constants. The third template argument allows clients to /// specify custom insertion hooks that are called on every newly created /// insertion. template > class IRBuilder : public IRBuilderBase, public Inserter { T Folder; - MDNode *DefaultFPMathTag; - FastMathFlags FMF; public: - IRBuilder(LLVMContext &C, const T &F, const Inserter &I = Inserter(), - MDNode *FPMathTag = 0) - : IRBuilderBase(C), Inserter(I), Folder(F), DefaultFPMathTag(FPMathTag), - FMF() { - } + IRBuilder(LLVMContext &C, const T &F, Inserter I = Inserter(), + MDNode *FPMathTag = nullptr) + : IRBuilderBase(C, FPMathTag), Inserter(std::move(I)), Folder(F) {} - explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = 0) - : IRBuilderBase(C), Folder(), DefaultFPMathTag(FPMathTag), FMF() { + explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = nullptr) + : IRBuilderBase(C, FPMathTag), Folder() { } - explicit IRBuilder(BasicBlock *TheBB, const T &F, MDNode *FPMathTag = 0) - : IRBuilderBase(TheBB->getContext()), Folder(F), - DefaultFPMathTag(FPMathTag), FMF() { + explicit IRBuilder(BasicBlock *TheBB, const T &F, MDNode *FPMathTag = nullptr) + : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder(F) { SetInsertPoint(TheBB); } - explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = 0) - : IRBuilderBase(TheBB->getContext()), Folder(), - DefaultFPMathTag(FPMathTag), FMF() { + explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = nullptr) + : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder() { SetInsertPoint(TheBB); } - explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = 0) - : IRBuilderBase(IP->getContext()), Folder(), DefaultFPMathTag(FPMathTag), - FMF() { + explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = nullptr) + : IRBuilderBase(IP->getContext(), FPMathTag), Folder() { SetInsertPoint(IP); - SetCurrentDebugLocation(IP->getDebugLoc()); - } - - explicit IRBuilder(Use &U, MDNode *FPMathTag = 0) - : IRBuilderBase(U->getContext()), Folder(), DefaultFPMathTag(FPMathTag), - FMF() { - SetInsertPoint(U); - SetCurrentDebugLocation(cast(U.getUser())->getDebugLoc()); } IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F, - MDNode *FPMathTag = 0) - : IRBuilderBase(TheBB->getContext()), Folder(F), - DefaultFPMathTag(FPMathTag), FMF() { + MDNode *FPMathTag = nullptr) + : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder(F) { SetInsertPoint(TheBB, IP); } - IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, MDNode *FPMathTag = 0) - : IRBuilderBase(TheBB->getContext()), Folder(), - DefaultFPMathTag(FPMathTag), FMF() { + IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, + MDNode *FPMathTag = nullptr) + : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder() { SetInsertPoint(TheBB, IP); } - /// getFolder - Get the constant folder being used. + /// \brief Get the constant folder being used. const T &getFolder() { return Folder; } - /// getDefaultFPMathTag - Get the floating point math metadata being used. - MDNode *getDefaultFPMathTag() const { return DefaultFPMathTag; } - - /// Get the flags to be applied to created floating point ops - FastMathFlags getFastMathFlags() const { return FMF; } - - /// Clear the fast-math flags. - void clearFastMathFlags() { FMF.clear(); } - - /// SetDefaultFPMathTag - Set the floating point math metadata to be used. - void SetDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; } - - /// Set the fast-math flags to be used with generated fp-math operators - void SetFastMathFlags(FastMathFlags NewFMF) { FMF = NewFMF; } - - /// isNamePreserving - Return true if this builder is configured to actually - /// add the requested names to IR created through it. + /// \brief Return true if this builder is configured to actually add the + /// requested names to IR created through it. bool isNamePreserving() const { return preserveNames; } - /// Insert - Insert and return the specified instruction. + /// \brief Insert and return the specified instruction. template InstTy *Insert(InstTy *I, const Twine &Name = "") const { this->InsertHelper(I, Name, BB, InsertPt); - if (!getCurrentDebugLocation().isUnknown()) - this->SetInstDebugLocation(I); + this->SetInstDebugLocation(I); return I; } - /// Insert - No-op overload to handle constants. + /// \brief No-op overload to handle constants. Constant *Insert(Constant *C, const Twine& = "") const { return C; } @@ -447,25 +587,23 @@ private: } public: - /// CreateRetVoid - Create a 'ret void' instruction. + /// \brief Create a 'ret void' instruction. ReturnInst *CreateRetVoid() { return Insert(ReturnInst::Create(Context)); } - /// @verbatim - /// CreateRet - Create a 'ret ' instruction. - /// @endverbatim + /// \brief Create a 'ret ' instruction. ReturnInst *CreateRet(Value *V) { return Insert(ReturnInst::Create(Context, V)); } - /// CreateAggregateRet - Create a sequence of N insertvalue instructions, + /// \brief Create a sequence of N insertvalue instructions, /// with one Value from the retVals array each, that build a aggregate /// return value one value at a time, and a ret instruction to return - /// the resulting aggregate value. This is a convenience function for - /// code that uses aggregate return values as a vehicle for having - /// multiple return values. + /// the resulting aggregate value. /// + /// This is a convenience function for code that uses aggregate return values + /// as a vehicle for having multiple return values. ReturnInst *CreateAggregateRet(Value *const *retVals, unsigned N) { Value *V = UndefValue::get(getCurrentFunctionReturnType()); for (unsigned i = 0; i != N; ++i) @@ -473,39 +611,38 @@ public: return Insert(ReturnInst::Create(Context, V)); } - /// CreateBr - Create an unconditional 'br label X' instruction. + /// \brief Create an unconditional 'br label X' instruction. BranchInst *CreateBr(BasicBlock *Dest) { return Insert(BranchInst::Create(Dest)); } - /// CreateCondBr - Create a conditional 'br Cond, TrueDest, FalseDest' + /// \brief Create a conditional 'br Cond, TrueDest, FalseDest' /// instruction. BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, - MDNode *BranchWeights = 0) { + MDNode *BranchWeights = nullptr) { return Insert(addBranchWeights(BranchInst::Create(True, False, Cond), BranchWeights)); } - /// CreateSwitch - Create a switch instruction with the specified value, - /// default dest, and with a hint for the number of cases that will be added - /// (for efficient allocation). + /// \brief Create a switch instruction with the specified value, default dest, + /// and with a hint for the number of cases that will be added (for efficient + /// allocation). SwitchInst *CreateSwitch(Value *V, BasicBlock *Dest, unsigned NumCases = 10, - MDNode *BranchWeights = 0) { + MDNode *BranchWeights = nullptr) { return Insert(addBranchWeights(SwitchInst::Create(V, Dest, NumCases), BranchWeights)); } - /// CreateIndirectBr - Create an indirect branch instruction with the - /// specified address operand, with an optional hint for the number of - /// destinations that will be added (for efficient allocation). + /// \brief Create an indirect branch instruction with the specified address + /// operand, with an optional hint for the number of destinations that will be + /// added (for efficient allocation). IndirectBrInst *CreateIndirectBr(Value *Addr, unsigned NumDests = 10) { return Insert(IndirectBrInst::Create(Addr, NumDests)); } InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest, BasicBlock *UnwindDest, const Twine &Name = "") { - return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, - ArrayRef()), + return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, None), Name); } InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest, @@ -522,7 +659,7 @@ public: return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, Args), Name); } - /// CreateInvoke - Create an invoke instruction. + /// \brief Create an invoke instruction. InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest, BasicBlock *UnwindDest, ArrayRef Args, const Twine &Name = "") { @@ -534,6 +671,36 @@ public: return Insert(ResumeInst::Create(Exn)); } + CleanupReturnInst *CreateCleanupRet(BasicBlock *UnwindBB = nullptr, + Value *RetVal = nullptr) { + return Insert(CleanupReturnInst::Create(Context, RetVal, UnwindBB)); + } + + CatchPadInst *CreateCatchPad(Type *Ty, BasicBlock *NormalDest, + BasicBlock *UnwindDest, ArrayRef Args, + const Twine &Name = "") { + return Insert(CatchPadInst::Create(Ty, NormalDest, UnwindDest, Args), Name); + } + + CatchEndPadInst *CreateCatchEndPad(BasicBlock *UnwindBB = nullptr) { + return Insert(CatchEndPadInst::Create(Context, UnwindBB)); + } + + TerminatePadInst *CreateTerminatePad(BasicBlock *UnwindBB = nullptr, + ArrayRef Args = {}, + const Twine &Name = "") { + return Insert(TerminatePadInst::Create(Context, UnwindBB, Args), Name); + } + + CleanupPadInst *CreateCleanupPad(Type *Ty, ArrayRef Args, + const Twine &Name = "") { + return Insert(CleanupPadInst::Create(Ty, Args), Name); + } + + CatchReturnInst *CreateCatchRet(BasicBlock *BB) { + return Insert(CatchReturnInst::Create(BB)); + } + UnreachableInst *CreateUnreachable() { return Insert(new UnreachableInst(Context)); } @@ -578,7 +745,7 @@ public: return CreateAdd(LHS, RHS, Name, true, false); } Value *CreateFAdd(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = 0) { + MDNode *FPMathTag = nullptr) { if (Constant *LC = dyn_cast(LHS)) if (Constant *RC = dyn_cast(RHS)) return Insert(Folder.CreateFAdd(LC, RC), Name); @@ -589,7 +756,7 @@ public: bool HasNUW = false, bool HasNSW = false) { if (Constant *LC = dyn_cast(LHS)) if (Constant *RC = dyn_cast(RHS)) - return Insert(Folder.CreateSub(LC, RC), Name); + return Insert(Folder.CreateSub(LC, RC, HasNUW, HasNSW), Name); return CreateInsertNUWNSWBinOp(Instruction::Sub, LHS, RHS, Name, HasNUW, HasNSW); } @@ -600,7 +767,7 @@ public: return CreateSub(LHS, RHS, Name, true, false); } Value *CreateFSub(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = 0) { + MDNode *FPMathTag = nullptr) { if (Constant *LC = dyn_cast(LHS)) if (Constant *RC = dyn_cast(RHS)) return Insert(Folder.CreateFSub(LC, RC), Name); @@ -611,7 +778,7 @@ public: bool HasNUW = false, bool HasNSW = false) { if (Constant *LC = dyn_cast(LHS)) if (Constant *RC = dyn_cast(RHS)) - return Insert(Folder.CreateMul(LC, RC), Name); + return Insert(Folder.CreateMul(LC, RC, HasNUW, HasNSW), Name); return CreateInsertNUWNSWBinOp(Instruction::Mul, LHS, RHS, Name, HasNUW, HasNSW); } @@ -622,7 +789,7 @@ public: return CreateMul(LHS, RHS, Name, true, false); } Value *CreateFMul(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = 0) { + MDNode *FPMathTag = nullptr) { if (Constant *LC = dyn_cast(LHS)) if (Constant *RC = dyn_cast(RHS)) return Insert(Folder.CreateFMul(LC, RC), Name); @@ -654,7 +821,7 @@ public: return CreateSDiv(LHS, RHS, Name, true); } Value *CreateFDiv(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = 0) { + MDNode *FPMathTag = nullptr) { if (Constant *LC = dyn_cast(LHS)) if (Constant *RC = dyn_cast(RHS)) return Insert(Folder.CreateFDiv(LC, RC), Name); @@ -674,7 +841,7 @@ public: return Insert(BinaryOperator::CreateSRem(LHS, RHS), Name); } Value *CreateFRem(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = 0) { + MDNode *FPMathTag = nullptr) { if (Constant *LC = dyn_cast(LHS)) if (Constant *RC = dyn_cast(RHS)) return Insert(Folder.CreateFRem(LC, RC), Name); @@ -783,11 +950,15 @@ public: } Value *CreateBinOp(Instruction::BinaryOps Opc, - Value *LHS, Value *RHS, const Twine &Name = "") { + Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { if (Constant *LC = dyn_cast(LHS)) if (Constant *RC = dyn_cast(RHS)) return Insert(Folder.CreateBinOp(Opc, LC, RC), Name); - return Insert(BinaryOperator::Create(Opc, LHS, RHS), Name); + llvm::Instruction *BinOp = BinaryOperator::Create(Opc, LHS, RHS); + if (isa(BinOp)) + BinOp = AddFPMathAttributes(BinOp, FPMathTag, FMF); + return Insert(BinOp, Name); } Value *CreateNeg(Value *V, const Twine &Name = "", @@ -805,7 +976,8 @@ public: Value *CreateNUWNeg(Value *V, const Twine &Name = "") { return CreateNeg(V, Name, true, false); } - Value *CreateFNeg(Value *V, const Twine &Name = "", MDNode *FPMathTag = 0) { + Value *CreateFNeg(Value *V, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { if (Constant *VC = dyn_cast(V)) return Insert(Folder.CreateFNeg(VC), Name); return Insert(AddFPMathAttributes(BinaryOperator::CreateFNeg(V), @@ -821,11 +993,11 @@ public: // Instruction creation methods: Memory Instructions //===--------------------------------------------------------------------===// - AllocaInst *CreateAlloca(Type *Ty, Value *ArraySize = 0, + AllocaInst *CreateAlloca(Type *Ty, Value *ArraySize = nullptr, const Twine &Name = "") { return Insert(new AllocaInst(Ty, ArraySize), Name); } - // Provided to resolve 'CreateLoad(Ptr, "...")' correctly, instead of + // \brief Provided to resolve 'CreateLoad(Ptr, "...")' correctly, instead of // converting the string to 'bool' for the isVolatile parameter. LoadInst *CreateLoad(Value *Ptr, const char *Name) { return Insert(new LoadInst(Ptr), Name); @@ -833,14 +1005,18 @@ public: LoadInst *CreateLoad(Value *Ptr, const Twine &Name = "") { return Insert(new LoadInst(Ptr), Name); } + LoadInst *CreateLoad(Type *Ty, Value *Ptr, const Twine &Name = "") { + return Insert(new LoadInst(Ty, Ptr), Name); + } LoadInst *CreateLoad(Value *Ptr, bool isVolatile, const Twine &Name = "") { - return Insert(new LoadInst(Ptr, 0, isVolatile), Name); + return Insert(new LoadInst(Ptr, nullptr, isVolatile), Name); } StoreInst *CreateStore(Value *Val, Value *Ptr, bool isVolatile = false) { return Insert(new StoreInst(Val, Ptr, isVolatile)); } - // Provided to resolve 'CreateAlignedLoad(Ptr, Align, "...")' correctly, - // instead of converting the string to 'bool' for the isVolatile parameter. + // \brief Provided to resolve 'CreateAlignedLoad(Ptr, Align, "...")' + // correctly, instead of converting the string to 'bool' for the isVolatile + // parameter. LoadInst *CreateAlignedLoad(Value *Ptr, unsigned Align, const char *Name) { LoadInst *LI = CreateLoad(Ptr, Name); LI->setAlignment(Align); @@ -865,13 +1041,17 @@ public: return SI; } FenceInst *CreateFence(AtomicOrdering Ordering, - SynchronizationScope SynchScope = CrossThread) { - return Insert(new FenceInst(Context, Ordering, SynchScope)); - } - AtomicCmpXchgInst *CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New, - AtomicOrdering Ordering, - SynchronizationScope SynchScope = CrossThread) { - return Insert(new AtomicCmpXchgInst(Ptr, Cmp, New, Ordering, SynchScope)); + SynchronizationScope SynchScope = CrossThread, + const Twine &Name = "") { + return Insert(new FenceInst(Context, Ordering, SynchScope), Name); + } + AtomicCmpXchgInst * + CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New, + AtomicOrdering SuccessOrdering, + AtomicOrdering FailureOrdering, + SynchronizationScope SynchScope = CrossThread) { + return Insert(new AtomicCmpXchgInst(Ptr, Cmp, New, SuccessOrdering, + FailureOrdering, SynchScope)); } AtomicRMWInst *CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val, AtomicOrdering Ordering, @@ -880,6 +1060,10 @@ public: } Value *CreateGEP(Value *Ptr, ArrayRef IdxList, const Twine &Name = "") { + return CreateGEP(nullptr, Ptr, IdxList, Name); + } + Value *CreateGEP(Type *Ty, Value *Ptr, ArrayRef IdxList, + const Twine &Name = "") { if (Constant *PC = dyn_cast(Ptr)) { // Every index must be constant. size_t i, e; @@ -887,12 +1071,16 @@ public: if (!isa(IdxList[i])) break; if (i == e) - return Insert(Folder.CreateGetElementPtr(PC, IdxList), Name); + return Insert(Folder.CreateGetElementPtr(Ty, PC, IdxList), Name); } - return Insert(GetElementPtrInst::Create(Ptr, IdxList), Name); + return Insert(GetElementPtrInst::Create(Ty, Ptr, IdxList), Name); } Value *CreateInBoundsGEP(Value *Ptr, ArrayRef IdxList, const Twine &Name = "") { + return CreateInBoundsGEP(nullptr, Ptr, IdxList, Name); + } + Value *CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef IdxList, + const Twine &Name = "") { if (Constant *PC = dyn_cast(Ptr)) { // Every index must be constant. size_t i, e; @@ -900,79 +1088,88 @@ public: if (!isa(IdxList[i])) break; if (i == e) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, IdxList), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, IdxList), + Name); } - return Insert(GetElementPtrInst::CreateInBounds(Ptr, IdxList), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, IdxList), Name); } Value *CreateGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { + return CreateGEP(nullptr, Ptr, Idx, Name); + } + Value *CreateGEP(Type *Ty, Value *Ptr, Value *Idx, const Twine &Name = "") { if (Constant *PC = dyn_cast(Ptr)) if (Constant *IC = dyn_cast(Idx)) - return Insert(Folder.CreateGetElementPtr(PC, IC), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); + return Insert(Folder.CreateGetElementPtr(Ty, PC, IC), Name); + return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name); } - Value *CreateInBoundsGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { + Value *CreateInBoundsGEP(Type *Ty, Value *Ptr, Value *Idx, + const Twine &Name = "") { if (Constant *PC = dyn_cast(Ptr)) if (Constant *IC = dyn_cast(Idx)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, IC), Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, IC), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name); } Value *CreateConstGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") { + return CreateConstGEP1_32(nullptr, Ptr, Idx0, Name); + } + Value *CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, + const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); if (Constant *PC = dyn_cast(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idx), Name); + return Insert(Folder.CreateGetElementPtr(Ty, PC, Idx), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); + return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name); } - Value *CreateConstInBoundsGEP1_32(Value *Ptr, unsigned Idx0, + Value *CreateConstInBoundsGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); if (Constant *PC = dyn_cast(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idx), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, Idx), Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name); } - Value *CreateConstGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, - const Twine &Name = "") { + Value *CreateConstGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, unsigned Idx1, + const Twine &Name = "") { Value *Idxs[] = { ConstantInt::get(Type::getInt32Ty(Context), Idx0), ConstantInt::get(Type::getInt32Ty(Context), Idx1) }; if (Constant *PC = dyn_cast(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idxs), Name); + return Insert(Folder.CreateGetElementPtr(Ty, PC, Idxs), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idxs), Name); + return Insert(GetElementPtrInst::Create(Ty, Ptr, Idxs), Name); } - Value *CreateConstInBoundsGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, - const Twine &Name = "") { + Value *CreateConstInBoundsGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, + unsigned Idx1, const Twine &Name = "") { Value *Idxs[] = { ConstantInt::get(Type::getInt32Ty(Context), Idx0), ConstantInt::get(Type::getInt32Ty(Context), Idx1) }; if (Constant *PC = dyn_cast(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, Idxs), Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idxs), Name); } Value *CreateConstGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); if (Constant *PC = dyn_cast(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idx), Name); + return Insert(Folder.CreateGetElementPtr(nullptr, PC, Idx), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); + return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idx), Name); } Value *CreateConstInBoundsGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); if (Constant *PC = dyn_cast(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idx), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(nullptr, PC, Idx), Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); + return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idx), Name); } Value *CreateConstGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name = "") { @@ -982,9 +1179,9 @@ public: }; if (Constant *PC = dyn_cast(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idxs), Name); + return Insert(Folder.CreateGetElementPtr(nullptr, PC, Idxs), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idxs), Name); + return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idxs), Name); } Value *CreateConstInBoundsGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name = "") { @@ -994,21 +1191,24 @@ public: }; if (Constant *PC = dyn_cast(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(nullptr, PC, Idxs), + Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs), Name); + return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idxs), Name); } - Value *CreateStructGEP(Value *Ptr, unsigned Idx, const Twine &Name = "") { - return CreateConstInBoundsGEP2_32(Ptr, 0, Idx, Name); + Value *CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx, + const Twine &Name = "") { + return CreateConstInBoundsGEP2_32(Ty, Ptr, 0, Idx, Name); } - /// CreateGlobalStringPtr - Same as CreateGlobalString, but return a pointer - /// with "i8*" type instead of a pointer to array of i8. - Value *CreateGlobalStringPtr(StringRef Str, const Twine &Name = "") { - Value *gv = CreateGlobalString(Str, Name); + /// \brief Same as CreateGlobalString, but return a pointer with "i8*" type + /// instead of a pointer to array of i8. + Value *CreateGlobalStringPtr(StringRef Str, const Twine &Name = "", + unsigned AddressSpace = 0) { + GlobalVariable *gv = CreateGlobalString(Str, Name, AddressSpace); Value *zero = ConstantInt::get(Type::getInt32Ty(Context), 0); Value *Args[] = { zero, zero }; - return CreateInBoundsGEP(gv, Args, Name); + return CreateInBoundsGEP(gv->getValueType(), gv, Args, Name); } //===--------------------------------------------------------------------===// @@ -1024,27 +1224,31 @@ public: Value *CreateSExt(Value *V, Type *DestTy, const Twine &Name = "") { return CreateCast(Instruction::SExt, V, DestTy, Name); } - /// CreateZExtOrTrunc - Create a ZExt or Trunc from the integer value V to - /// DestTy. Return the value untouched if the type of V is already DestTy. - Value *CreateZExtOrTrunc(Value *V, IntegerType *DestTy, + /// \brief Create a ZExt or Trunc from the integer value V to DestTy. Return + /// the value untouched if the type of V is already DestTy. + Value *CreateZExtOrTrunc(Value *V, Type *DestTy, const Twine &Name = "") { - assert(isa(V->getType()) && "Can only zero extend integers!"); - IntegerType *IntTy = cast(V->getType()); - if (IntTy->getBitWidth() < DestTy->getBitWidth()) + assert(V->getType()->isIntOrIntVectorTy() && + DestTy->isIntOrIntVectorTy() && + "Can only zero extend/truncate integers!"); + Type *VTy = V->getType(); + if (VTy->getScalarSizeInBits() < DestTy->getScalarSizeInBits()) return CreateZExt(V, DestTy, Name); - if (IntTy->getBitWidth() > DestTy->getBitWidth()) + if (VTy->getScalarSizeInBits() > DestTy->getScalarSizeInBits()) return CreateTrunc(V, DestTy, Name); return V; } - /// CreateSExtOrTrunc - Create a SExt or Trunc from the integer value V to - /// DestTy. Return the value untouched if the type of V is already DestTy. - Value *CreateSExtOrTrunc(Value *V, IntegerType *DestTy, + /// \brief Create a SExt or Trunc from the integer value V to DestTy. Return + /// the value untouched if the type of V is already DestTy. + Value *CreateSExtOrTrunc(Value *V, Type *DestTy, const Twine &Name = "") { - assert(isa(V->getType()) && "Can only sign extend integers!"); - IntegerType *IntTy = cast(V->getType()); - if (IntTy->getBitWidth() < DestTy->getBitWidth()) + assert(V->getType()->isIntOrIntVectorTy() && + DestTy->isIntOrIntVectorTy() && + "Can only sign extend/truncate integers!"); + Type *VTy = V->getType(); + if (VTy->getScalarSizeInBits() < DestTy->getScalarSizeInBits()) return CreateSExt(V, DestTy, Name); - if (IntTy->getBitWidth() > DestTy->getBitWidth()) + if (VTy->getScalarSizeInBits() > DestTy->getScalarSizeInBits()) return CreateTrunc(V, DestTy, Name); return V; } @@ -1079,6 +1283,10 @@ public: const Twine &Name = "") { return CreateCast(Instruction::BitCast, V, DestTy, Name); } + Value *CreateAddrSpaceCast(Value *V, Type *DestTy, + const Twine &Name = "") { + return CreateCast(Instruction::AddrSpaceCast, V, DestTy, Name); + } Value *CreateZExtOrBitCast(Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) @@ -1119,6 +1327,21 @@ public: return Insert(Folder.CreatePointerCast(VC, DestTy), Name); return Insert(CastInst::CreatePointerCast(V, DestTy), Name); } + + Value *CreatePointerBitCastOrAddrSpaceCast(Value *V, Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + + if (Constant *VC = dyn_cast(V)) { + return Insert(Folder.CreatePointerBitCastOrAddrSpaceCast(VC, DestTy), + Name); + } + + return Insert(CastInst::CreatePointerBitCastOrAddrSpaceCast(V, DestTy), + Name); + } + Value *CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name = "") { if (V->getType() == DestTy) @@ -1127,10 +1350,23 @@ public: return Insert(Folder.CreateIntCast(VC, DestTy, isSigned), Name); return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name); } + + Value *CreateBitOrPointerCast(Value *V, Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (V->getType()->isPointerTy() && DestTy->isIntegerTy()) + return CreatePtrToInt(V, DestTy, Name); + if (V->getType()->isIntegerTy() && DestTy->isPointerTy()) + return CreateIntToPtr(V, DestTy, Name); + + return CreateBitCast(V, DestTy, Name); + } private: - // Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a compile time - // error, instead of converting the string to bool for the isSigned parameter. - Value *CreateIntCast(Value *, Type *, const char *) LLVM_DELETED_FUNCTION; + // \brief Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a + // compile time error, instead of converting the string to bool for the + // isSigned parameter. + Value *CreateIntCast(Value *, Type *, const char *) = delete; public: Value *CreateFPCast(Value *V, Type *DestTy, const Twine &Name = "") { if (V->getType() == DestTy) @@ -1175,47 +1411,61 @@ public: return CreateICmp(ICmpInst::ICMP_SLE, LHS, RHS, Name); } - Value *CreateFCmpOEQ(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_OEQ, LHS, RHS, Name); + Value *CreateFCmpOEQ(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_OEQ, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpOGT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_OGT, LHS, RHS, Name); + Value *CreateFCmpOGT(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_OGT, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpOGE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_OGE, LHS, RHS, Name); + Value *CreateFCmpOGE(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_OGE, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpOLT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_OLT, LHS, RHS, Name); + Value *CreateFCmpOLT(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_OLT, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpOLE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_OLE, LHS, RHS, Name); + Value *CreateFCmpOLE(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_OLE, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpONE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_ONE, LHS, RHS, Name); + Value *CreateFCmpONE(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_ONE, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpORD(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_ORD, LHS, RHS, Name); + Value *CreateFCmpORD(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_ORD, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpUNO(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_UNO, LHS, RHS, Name); + Value *CreateFCmpUNO(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_UNO, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpUEQ(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_UEQ, LHS, RHS, Name); + Value *CreateFCmpUEQ(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_UEQ, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpUGT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_UGT, LHS, RHS, Name); + Value *CreateFCmpUGT(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_UGT, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpUGE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_UGE, LHS, RHS, Name); + Value *CreateFCmpUGE(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_UGE, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpULT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_ULT, LHS, RHS, Name); + Value *CreateFCmpULT(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_ULT, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpULE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_ULE, LHS, RHS, Name); + Value *CreateFCmpULE(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_ULE, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpUNE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_UNE, LHS, RHS, Name); + Value *CreateFCmpUNE(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_UNE, LHS, RHS, Name, FPMathTag); } Value *CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, @@ -1226,11 +1476,12 @@ public: return Insert(new ICmpInst(P, LHS, RHS), Name); } Value *CreateFCmp(CmpInst::Predicate P, Value *LHS, Value *RHS, - const Twine &Name = "") { + const Twine &Name = "", MDNode *FPMathTag = nullptr) { if (Constant *LC = dyn_cast(LHS)) if (Constant *RC = dyn_cast(RHS)) return Insert(Folder.CreateFCmp(P, LC, RC), Name); - return Insert(new FCmpInst(P, LHS, RHS), Name); + return Insert(AddFPMathAttributes(new FCmpInst(P, LHS, RHS), + FPMathTag, FMF), Name); } //===--------------------------------------------------------------------===// @@ -1242,36 +1493,19 @@ public: return Insert(PHINode::Create(Ty, NumReservedValues), Name); } - CallInst *CreateCall(Value *Callee, const Twine &Name = "") { - return Insert(CallInst::Create(Callee), Name); - } - CallInst *CreateCall(Value *Callee, Value *Arg, const Twine &Name = "") { - return Insert(CallInst::Create(Callee, Arg), Name); - } - CallInst *CreateCall2(Value *Callee, Value *Arg1, Value *Arg2, - const Twine &Name = "") { - Value *Args[] = { Arg1, Arg2 }; - return Insert(CallInst::Create(Callee, Args), Name); - } - CallInst *CreateCall3(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, - const Twine &Name = "") { - Value *Args[] = { Arg1, Arg2, Arg3 }; - return Insert(CallInst::Create(Callee, Args), Name); - } - CallInst *CreateCall4(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, - Value *Arg4, const Twine &Name = "") { - Value *Args[] = { Arg1, Arg2, Arg3, Arg4 }; + CallInst *CreateCall(Value *Callee, ArrayRef Args = None, + const Twine &Name = "") { return Insert(CallInst::Create(Callee, Args), Name); } - CallInst *CreateCall5(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, - Value *Arg4, Value *Arg5, const Twine &Name = "") { - Value *Args[] = { Arg1, Arg2, Arg3, Arg4, Arg5 }; - return Insert(CallInst::Create(Callee, Args), Name); + + CallInst *CreateCall(llvm::FunctionType *FTy, Value *Callee, + ArrayRef Args, const Twine &Name = "") { + return Insert(CallInst::Create(FTy, Callee, Args), Name); } - CallInst *CreateCall(Value *Callee, ArrayRef Args, + CallInst *CreateCall(Function *Callee, ArrayRef Args, const Twine &Name = "") { - return Insert(CallInst::Create(Callee, Args), Name); + return CreateCall(Callee->getFunctionType(), Callee, Args, Name); } Value *CreateSelect(Value *C, Value *True, Value *False, @@ -1295,6 +1529,11 @@ public: return Insert(ExtractElementInst::Create(Vec, Idx), Name); } + Value *CreateExtractElement(Value *Vec, uint64_t Idx, + const Twine &Name = "") { + return CreateExtractElement(Vec, getInt64(Idx), Name); + } + Value *CreateInsertElement(Value *Vec, Value *NewElt, Value *Idx, const Twine &Name = "") { if (Constant *VC = dyn_cast(Vec)) @@ -1304,6 +1543,11 @@ public: return Insert(InsertElementInst::Create(Vec, NewElt, Idx), Name); } + Value *CreateInsertElement(Value *Vec, Value *NewElt, uint64_t Idx, + const Twine &Name = "") { + return CreateInsertElement(Vec, NewElt, getInt64(Idx), Name); + } + Value *CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name = "") { if (Constant *V1C = dyn_cast(V1)) @@ -1313,6 +1557,16 @@ public: return Insert(new ShuffleVectorInst(V1, V2, Mask), Name); } + Value *CreateShuffleVector(Value *V1, Value *V2, ArrayRef IntMask, + const Twine &Name = "") { + size_t MaskSize = IntMask.size(); + SmallVector MaskVec(MaskSize); + for (size_t i = 0; i != MaskSize; ++i) + MaskVec[i] = getInt32(IntMask[i]); + Value *Mask = ConstantVector::get(MaskVec); + return CreateShuffleVector(V1, V2, Mask, Name); + } + Value *CreateExtractValue(Value *Agg, ArrayRef Idxs, const Twine &Name = "") { @@ -1330,32 +1584,33 @@ public: return Insert(InsertValueInst::Create(Agg, Val, Idxs), Name); } - LandingPadInst *CreateLandingPad(Type *Ty, Value *PersFn, unsigned NumClauses, + LandingPadInst *CreateLandingPad(Type *Ty, unsigned NumClauses, const Twine &Name = "") { - return Insert(LandingPadInst::Create(Ty, PersFn, NumClauses), Name); + return Insert(LandingPadInst::Create(Ty, NumClauses), Name); } //===--------------------------------------------------------------------===// // Utility creation methods //===--------------------------------------------------------------------===// - /// CreateIsNull - Return an i1 value testing if \p Arg is null. + /// \brief Return an i1 value testing if \p Arg is null. Value *CreateIsNull(Value *Arg, const Twine &Name = "") { return CreateICmpEQ(Arg, Constant::getNullValue(Arg->getType()), Name); } - /// CreateIsNotNull - Return an i1 value testing if \p Arg is not null. + /// \brief Return an i1 value testing if \p Arg is not null. Value *CreateIsNotNull(Value *Arg, const Twine &Name = "") { return CreateICmpNE(Arg, Constant::getNullValue(Arg->getType()), Name); } - /// CreatePtrDiff - Return the i64 difference between two pointer values, - /// dividing out the size of the pointed-to objects. This is intended to - /// implement C-style pointer subtraction. As such, the pointers must be - /// appropriately aligned for their element types and pointing into the - /// same object. + /// \brief Return the i64 difference between two pointer values, dividing out + /// the size of the pointed-to objects. + /// + /// This is intended to implement C-style pointer subtraction. As such, the + /// pointers must be appropriately aligned for their element types and + /// pointing into the same object. Value *CreatePtrDiff(Value *LHS, Value *RHS, const Twine &Name = "") { assert(LHS->getType() == RHS->getType() && "Pointer subtraction operand types must match!"); @@ -1368,8 +1623,8 @@ public: Name); } - /// CreateVectorSplat - Return a vector value that contains \arg V broadcasted - /// to \p NumElts elements. + /// \brief Return a vector value that contains \arg V broadcasted to \p + /// NumElts elements. Value *CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name = "") { assert(NumElts > 0 && "Cannot splat to an empty vector!"); @@ -1383,8 +1638,73 @@ public: Value *Zeros = ConstantAggregateZero::get(VectorType::get(I32Ty, NumElts)); return CreateShuffleVector(V, Undef, Zeros, Name + ".splat"); } + + /// \brief Return a value that has been extracted from a larger integer type. + Value *CreateExtractInteger(const DataLayout &DL, Value *From, + IntegerType *ExtractedTy, uint64_t Offset, + const Twine &Name) { + IntegerType *IntTy = cast(From->getType()); + assert(DL.getTypeStoreSize(ExtractedTy) + Offset <= + DL.getTypeStoreSize(IntTy) && + "Element extends past full value"); + uint64_t ShAmt = 8 * Offset; + Value *V = From; + if (DL.isBigEndian()) + ShAmt = 8 * (DL.getTypeStoreSize(IntTy) - + DL.getTypeStoreSize(ExtractedTy) - Offset); + if (ShAmt) { + V = CreateLShr(V, ShAmt, Name + ".shift"); + } + assert(ExtractedTy->getBitWidth() <= IntTy->getBitWidth() && + "Cannot extract to a larger integer!"); + if (ExtractedTy != IntTy) { + V = CreateTrunc(V, ExtractedTy, Name + ".trunc"); + } + return V; + } + + /// \brief Create an assume intrinsic call that represents an alignment + /// assumption on the provided pointer. + /// + /// An optional offset can be provided, and if it is provided, the offset + /// must be subtracted from the provided pointer to get the pointer with the + /// specified alignment. + CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue, + unsigned Alignment, + Value *OffsetValue = nullptr) { + assert(isa(PtrValue->getType()) && + "trying to create an alignment assumption on a non-pointer?"); + + PointerType *PtrTy = cast(PtrValue->getType()); + Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace()); + Value *PtrIntValue = CreatePtrToInt(PtrValue, IntPtrTy, "ptrint"); + + Value *Mask = ConstantInt::get(IntPtrTy, + Alignment > 0 ? Alignment - 1 : 0); + if (OffsetValue) { + bool IsOffsetZero = false; + if (ConstantInt *CI = dyn_cast(OffsetValue)) + IsOffsetZero = CI->isZero(); + + if (!IsOffsetZero) { + if (OffsetValue->getType() != IntPtrTy) + OffsetValue = CreateIntCast(OffsetValue, IntPtrTy, /*isSigned*/ true, + "offsetcast"); + PtrIntValue = CreateSub(PtrIntValue, OffsetValue, "offsetptr"); + } + } + + Value *Zero = ConstantInt::get(IntPtrTy, 0); + Value *MaskedPtr = CreateAnd(PtrIntValue, Mask, "maskedptr"); + Value *InvCond = CreateICmpEQ(MaskedPtr, Zero, "maskcond"); + + return CreateAssumption(InvCond); + } }; +// Create wrappers for C Binding types (see CBindingWrapping.h). +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(IRBuilder<>, LLVMBuilderRef) + } #endif