diff options
author | dim <dim@FreeBSD.org> | 2015-01-18 16:23:48 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2015-01-18 16:23:48 +0000 |
commit | c86b984ea8ecb3e944dc3de48539f4c1f65851ea (patch) | |
tree | 3eb853da77d46cc77c4b017525a422f9ddb1385b /lib/CodeGen/CodeGenFunction.h | |
parent | c696171ff15f0ee60dea4abfd99a135473c95656 (diff) | |
download | FreeBSD-src-c86b984ea8ecb3e944dc3de48539f4c1f65851ea.zip FreeBSD-src-c86b984ea8ecb3e944dc3de48539f4c1f65851ea.tar.gz |
Vendor import of clang RELEASE_360/rc1 tag r226102 (effectively, 3.6.0 RC1):
https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_360/rc1@226102
Diffstat (limited to 'lib/CodeGen/CodeGenFunction.h')
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 396 |
1 files changed, 236 insertions, 160 deletions
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 59cc30d..3a990d2 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_CODEGEN_CODEGENFUNCTION_H -#define CLANG_CODEGEN_CODEGENFUNCTION_H +#ifndef LLVM_CLANG_LIB_CODEGEN_CODEGENFUNCTION_H +#define LLVM_CLANG_LIB_CODEGEN_CODEGENFUNCTION_H #include "CGBuilder.h" #include "CGDebugInfo.h" @@ -93,19 +93,6 @@ enum TypeEvaluationKind { TEK_Aggregate }; -class SuppressDebugLocation { - llvm::DebugLoc CurLoc; - llvm::IRBuilderBase &Builder; -public: - SuppressDebugLocation(llvm::IRBuilderBase &Builder) - : CurLoc(Builder.getCurrentDebugLocation()), Builder(Builder) { - Builder.SetCurrentDebugLocation(llvm::DebugLoc()); - } - ~SuppressDebugLocation() { - Builder.SetCurrentDebugLocation(CurLoc); - } -}; - /// CodeGenFunction - This class organizes the per-function state that is used /// while generating LLVM code. class CodeGenFunction : public CodeGenTypeCache { @@ -182,6 +169,8 @@ public: /// \brief API for captured statement code generation. class CGCapturedStmtInfo { public: + explicit CGCapturedStmtInfo(CapturedRegionKind K = CR_Default) + : Kind(K), ThisValue(nullptr), CXXThisFieldDecl(nullptr) {} explicit CGCapturedStmtInfo(const CapturedStmt &S, CapturedRegionKind K = CR_Default) : Kind(K), ThisValue(nullptr), CXXThisFieldDecl(nullptr) { @@ -193,7 +182,7 @@ public: I != E; ++I, ++Field) { if (I->capturesThis()) CXXThisFieldDecl = *Field; - else + else if (I->capturesVariable()) CaptureFields[I->getCapturedVar()] = *Field; } } @@ -214,6 +203,10 @@ public: bool isCXXThisExprCaptured() const { return CXXThisFieldDecl != nullptr; } FieldDecl *getThisFieldDecl() const { return CXXThisFieldDecl; } + static bool classof(const CGCapturedStmtInfo *) { + return true; + } + /// \brief Emit the captured statement body. virtual void EmitBody(CodeGenFunction &CGF, Stmt *S) { RegionCounter Cnt = CGF.getPGORegionCounter(S); @@ -244,8 +237,8 @@ public: /// potentially higher performance penalties. unsigned char BoundsChecking; - /// \brief Sanitizer options to use for this function. - const SanitizerOptions *SanOpts; + /// \brief Sanitizers enabled for this function. + SanitizerSet SanOpts; /// \brief True if CodeGen currently emits code implementing sanitizer checks. bool IsSanitizerScope; @@ -258,9 +251,17 @@ public: ~SanitizerScope(); }; + /// In C++, whether we are code generating a thunk. This controls whether we + /// should emit cleanups. + bool CurFuncIsThunk; + /// In ARC, whether we should autorelease the return value. bool AutoreleaseResult; + /// Whether we processed a Microsoft-style asm block during CodeGen. These can + /// potentially set the return value. + bool SawAsmBlock; + const CodeGen::CGBlockInfo *BlockInfo; llvm::Value *BlockPointer; @@ -277,11 +278,11 @@ public: /// Header for data within LifetimeExtendedCleanupStack. struct LifetimeExtendedCleanupHeader { /// The size of the following cleanup object. - size_t Size : 29; + unsigned Size : 29; /// The kind of cleanup to push: a value from the CleanupKind enumeration. unsigned Kind : 3; - size_t getSize() const { return Size; } + size_t getSize() const { return size_t(Size); } CleanupKind getKind() const { return static_cast<CleanupKind>(Kind); } }; @@ -531,7 +532,7 @@ public: } }; - class LexicalScope: protected RunCleanupsScope { + class LexicalScope : public RunCleanupsScope { SourceRange Range; SmallVector<const LabelDecl*, 4> Labels; LexicalScope *ParentScope; @@ -577,6 +578,67 @@ public: void rescopeLabels(); }; + /// \brief The scope used to remap some variables as private in the OpenMP + /// loop body (or other captured region emitted without outlining), and to + /// restore old vars back on exit. + class OMPPrivateScope : public RunCleanupsScope { + typedef llvm::DenseMap<const VarDecl *, llvm::Value *> VarDeclMapTy; + VarDeclMapTy SavedLocals; + VarDeclMapTy SavedPrivates; + + private: + OMPPrivateScope(const OMPPrivateScope &) LLVM_DELETED_FUNCTION; + void operator=(const OMPPrivateScope &) LLVM_DELETED_FUNCTION; + + public: + /// \brief Enter a new OpenMP private scope. + explicit OMPPrivateScope(CodeGenFunction &CGF) : RunCleanupsScope(CGF) {} + + /// \brief Registers \a LocalVD variable as a private and apply \a + /// PrivateGen function for it to generate corresponding private variable. + /// \a PrivateGen returns an address of the generated private variable. + /// \return true if the variable is registered as private, false if it has + /// been privatized already. + bool + addPrivate(const VarDecl *LocalVD, + const std::function<llvm::Value *()> &PrivateGen) { + assert(PerformCleanup && "adding private to dead scope"); + if (SavedLocals.count(LocalVD) > 0) return false; + SavedLocals[LocalVD] = CGF.LocalDeclMap.lookup(LocalVD); + CGF.LocalDeclMap.erase(LocalVD); + SavedPrivates[LocalVD] = PrivateGen(); + CGF.LocalDeclMap[LocalVD] = SavedLocals[LocalVD]; + return true; + } + + /// \brief Privatizes local variables previously registered as private. + /// Registration is separate from the actual privatization to allow + /// initializers use values of the original variables, not the private one. + /// This is important, for example, if the private variable is a class + /// variable initialized by a constructor that references other private + /// variables. But at initialization original variables must be used, not + /// private copies. + /// \return true if at least one variable was privatized, false otherwise. + bool Privatize() { + for (auto VDPair : SavedPrivates) { + CGF.LocalDeclMap[VDPair.first] = VDPair.second; + } + SavedPrivates.clear(); + return !SavedLocals.empty(); + } + + void ForceCleanup() { + RunCleanupsScope::ForceCleanup(); + // Remap vars back to the original values. + for (auto I : SavedLocals) { + CGF.LocalDeclMap[I.first] = I.second; + } + SavedLocals.clear(); + } + + /// \brief Exit scope - all the mapped variables are restored. + ~OMPPrivateScope() { ForceCleanup(); } + }; /// \brief Takes the old cleanup stack size and emits the cleanup blocks /// that have been added. @@ -1062,6 +1124,9 @@ public: void pushLifetimeExtendedDestroy(CleanupKind kind, llvm::Value *addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray); + void pushCallObjectDeleteCleanup(const FunctionDecl *OperatorDelete, + llvm::Value *CompletePtr, + QualType ElementType); void pushStackRestore(CleanupKind kind, llvm::Value *SPMem); void emitDestroy(llvm::Value *addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray); @@ -1101,9 +1166,7 @@ public: void GenerateObjCMethod(const ObjCMethodDecl *OMD); - void StartObjCMethod(const ObjCMethodDecl *MD, - const ObjCContainerDecl *CD, - SourceLocation StartLoc); + void StartObjCMethod(const ObjCMethodDecl *MD, const ObjCContainerDecl *CD); /// GenerateObjCGetter - Synthesize an Objective-C property getter function. void GenerateObjCGetter(ObjCImplementationDecl *IMP, @@ -1193,10 +1256,11 @@ public: void EmitLambdaBlockInvokeBody(); void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD); void EmitLambdaStaticInvokeFunction(const CXXMethodDecl *MD); + void EmitAsanPrologueOrEpilogue(bool Prologue); /// EmitReturnBlock - Emit the unified return block, trying to avoid its /// emission when possible. - void EmitReturnBlock(); + llvm::DebugLoc EmitReturnBlock(); /// FinishFunction - Complete IR generation of the current function. It is /// legal to call this function even if there is no current insertion point. @@ -1204,8 +1268,11 @@ public: void StartThunk(llvm::Function *Fn, GlobalDecl GD, const CGFunctionInfo &FnInfo); - void EmitCallAndReturnForThunk(GlobalDecl GD, llvm::Value *Callee, - const ThunkInfo *Thunk); + void EmitCallAndReturnForThunk(llvm::Value *Callee, const ThunkInfo *Thunk); + + /// Emit a musttail call for a thunk with a potentially adjusted this pointer. + void EmitMustTailThunk(const CXXMethodDecl *MD, llvm::Value *AdjustedThisPtr, + llvm::Value *Callee); /// GenerateThunk - Generate a thunk for the given method. void GenerateThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo, @@ -1390,13 +1457,7 @@ public: CGM.getTBAAInfo(T)); } - LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T) { - CharUnits Alignment; - if (!T->isIncompleteType()) - Alignment = getContext().getTypeAlignInChars(T); - return LValue::MakeAddr(V, T, Alignment, getContext(), - CGM.getTBAAInfo(T)); - } + LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T); /// CreateTempAlloca - This creates a alloca and inserts it into the entry /// block. The caller is responsible for setting an appropriate alignment on @@ -1468,8 +1529,8 @@ public: /// EmitExprAsInit - Emits the code necessary to initialize a /// location in memory with the given initializer. - void EmitExprAsInit(const Expr *init, const ValueDecl *D, - LValue lvalue, bool capturedByInit); + void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, + bool capturedByInit); /// hasVolatileMember - returns true if aggregate type has a volatile /// member. @@ -1610,7 +1671,7 @@ public: const CXXRecordDecl *Derived, CastExpr::path_const_iterator PathBegin, CastExpr::path_const_iterator PathEnd, - bool NullCheckValue); + bool NullCheckValue, SourceLocation Loc); llvm::Value *GetAddressOfDerivedClass(llvm::Value *Value, const CXXRecordDecl *Derived, @@ -1637,27 +1698,22 @@ public: const FunctionArgList &Args); void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase, bool Delegating, - llvm::Value *This, - CallExpr::const_arg_iterator ArgBeg, - CallExpr::const_arg_iterator ArgEnd); - + llvm::Value *This, const CXXConstructExpr *E); + void EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, llvm::Value *This, llvm::Value *Src, - CallExpr::const_arg_iterator ArgBeg, - CallExpr::const_arg_iterator ArgEnd); + const CXXConstructExpr *E); void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, const ConstantArrayType *ArrayTy, llvm::Value *ArrayPtr, - CallExpr::const_arg_iterator ArgBeg, - CallExpr::const_arg_iterator ArgEnd, + const CXXConstructExpr *E, bool ZeroInitialization = false); void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, llvm::Value *NumElements, llvm::Value *ArrayPtr, - CallExpr::const_arg_iterator ArgBeg, - CallExpr::const_arg_iterator ArgEnd, + const CXXConstructExpr *E, bool ZeroInitialization = false); static Destroyer destroyCXXObject; @@ -1710,7 +1766,13 @@ public: TCK_DowncastPointer, /// Checking the operand of a static_cast to a derived reference type. Must /// be an object within its lifetime. - TCK_DowncastReference + TCK_DowncastReference, + /// Checking the operand of a cast to a base object. Must be suitably sized + /// and aligned. + TCK_Upcast, + /// Checking the operand of a cast to a virtual base object. Must be an + /// object within its lifetime. + TCK_UpcastToVirtualBase }; /// \brief Whether any type-checking sanitizers are enabled. If \c false, @@ -1720,7 +1782,8 @@ public: /// \brief Emit a check that \p V is the address of storage of the /// appropriate size and alignment for an object of type \p Type. void EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc, llvm::Value *V, - QualType Type, CharUnits Alignment = CharUnits::Zero()); + QualType Type, CharUnits Alignment = CharUnits::Zero(), + bool SkipNullCheck = false); /// \brief Emit a check that \p Base points into an array object, which /// we can access at index \p Index. \p Accessed should be \c false if we @@ -1732,6 +1795,13 @@ public: bool isInc, bool isPre); ComplexPairTy EmitComplexPrePostIncDec(const UnaryOperator *E, LValue LV, bool isInc, bool isPre); + + void EmitAlignmentAssumption(llvm::Value *PtrValue, unsigned Alignment, + llvm::Value *OffsetValue = nullptr) { + Builder.CreateAlignmentAssumption(CGM.getDataLayout(), PtrValue, Alignment, + OffsetValue); + } + //===--------------------------------------------------------------------===// // Declaration Emission //===--------------------------------------------------------------------===// @@ -1746,13 +1816,17 @@ public: /// This function can be called with a null (unreachable) insert point. void EmitVarDecl(const VarDecl &D); - void EmitScalarInit(const Expr *init, const ValueDecl *D, - LValue lvalue, bool capturedByInit); + void EmitScalarInit(const Expr *init, const ValueDecl *D, LValue lvalue, + bool capturedByInit); void EmitScalarInit(llvm::Value *init, LValue lvalue); typedef void SpecialInitFn(CodeGenFunction &Init, const VarDecl &D, llvm::Value *Address); + /// \brief Determine whether the given initializer is trivial in the sense + /// that it requires no code to be generated. + bool isTrivialInitializer(const Expr *Init); + /// EmitAutoVarDecl - Emit an auto variable declaration. /// /// This function can be called with a null (unreachable) insert point. @@ -1886,12 +1960,12 @@ public: void EmitIfStmt(const IfStmt &S); void EmitCondBrHints(llvm::LLVMContext &Context, llvm::BranchInst *CondBr, - const ArrayRef<const Attr *> &Attrs); + ArrayRef<const Attr *> Attrs); void EmitWhileStmt(const WhileStmt &S, - const ArrayRef<const Attr *> &Attrs = None); - void EmitDoStmt(const DoStmt &S, const ArrayRef<const Attr *> &Attrs = None); + ArrayRef<const Attr *> Attrs = None); + void EmitDoStmt(const DoStmt &S, ArrayRef<const Attr *> Attrs = None); void EmitForStmt(const ForStmt &S, - const ArrayRef<const Attr *> &Attrs = None); + ArrayRef<const Attr *> Attrs = None); void EmitReturnStmt(const ReturnStmt &S); void EmitDeclStmt(const DeclStmt &S); void EmitBreakStmt(const BreakStmt &S); @@ -1915,27 +1989,55 @@ public: void EmitSEHTryStmt(const SEHTryStmt &S); void EmitSEHLeaveStmt(const SEHLeaveStmt &S); void EmitCXXForRangeStmt(const CXXForRangeStmt &S, - const ArrayRef<const Attr *> &Attrs = None); + ArrayRef<const Attr *> Attrs = None); + LValue InitCapturedStruct(const CapturedStmt &S); llvm::Function *EmitCapturedStmt(const CapturedStmt &S, CapturedRegionKind K); + void GenerateCapturedStmtFunctionProlog(const CapturedStmt &S); + llvm::Function *GenerateCapturedStmtFunctionEpilog(const CapturedStmt &S); llvm::Function *GenerateCapturedStmtFunction(const CapturedStmt &S); llvm::Value *GenerateCapturedStmtArgument(const CapturedStmt &S); + void EmitOMPAggregateAssign(LValue OriginalAddr, llvm::Value *PrivateAddr, + const Expr *AssignExpr, QualType Type, + const VarDecl *VDInit); + void EmitOMPFirstprivateClause(const OMPExecutableDirective &D, + OMPPrivateScope &PrivateScope); + void EmitOMPPrivateClause(const OMPExecutableDirective &D, + OMPPrivateScope &PrivateScope); void EmitOMPParallelDirective(const OMPParallelDirective &S); void EmitOMPSimdDirective(const OMPSimdDirective &S); void EmitOMPForDirective(const OMPForDirective &S); + void EmitOMPForSimdDirective(const OMPForSimdDirective &S); void EmitOMPSectionsDirective(const OMPSectionsDirective &S); void EmitOMPSectionDirective(const OMPSectionDirective &S); void EmitOMPSingleDirective(const OMPSingleDirective &S); void EmitOMPMasterDirective(const OMPMasterDirective &S); void EmitOMPCriticalDirective(const OMPCriticalDirective &S); void EmitOMPParallelForDirective(const OMPParallelForDirective &S); + void EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &S); void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S); void EmitOMPTaskDirective(const OMPTaskDirective &S); void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S); void EmitOMPBarrierDirective(const OMPBarrierDirective &S); void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S); void EmitOMPFlushDirective(const OMPFlushDirective &S); + void EmitOMPOrderedDirective(const OMPOrderedDirective &S); + void EmitOMPAtomicDirective(const OMPAtomicDirective &S); + void EmitOMPTargetDirective(const OMPTargetDirective &S); + void EmitOMPTeamsDirective(const OMPTeamsDirective &S); + +private: + + /// Helpers for the OpenMP loop directives. + void EmitOMPLoopBody(const OMPLoopDirective &Directive, + bool SeparateIter = false); + void EmitOMPInnerLoop(const OMPLoopDirective &S, OMPPrivateScope &LoopScope, + bool SeparateIter = false); + void EmitOMPSimdFinal(const OMPLoopDirective &S); + void EmitOMPWorksharingLoop(const OMPLoopDirective &S); + +public: //===--------------------------------------------------------------------===// // LValue Expression Emission @@ -1988,6 +2090,12 @@ public: void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit); + std::pair<RValue, RValue> EmitAtomicCompareExchange( + LValue Obj, RValue Expected, RValue Desired, SourceLocation Loc, + llvm::AtomicOrdering Success = llvm::SequentiallyConsistent, + llvm::AtomicOrdering Failure = llvm::SequentiallyConsistent, + bool IsWeak = false, AggValueSlot Slot = AggValueSlot::ignored()); + /// EmitToMemory - Change a scalar value from its value /// representation to its in-memory representation. llvm::Value *EmitToMemory(llvm::Value *Value, QualType Ty); @@ -2039,7 +2147,7 @@ public: /// EmitStoreThroughLValue - Store the specified rvalue into the specified /// lvalue, where both are guaranteed to the have the same type, and that type /// is 'Ty'. - void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false); + void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit = false); void EmitStoreThroughExtVectorComponentLValue(RValue Src, LValue Dst); void EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst); @@ -2082,6 +2190,8 @@ public: LValue EmitCastLValue(const CastExpr *E); LValue EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E); LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e); + + llvm::Value *EmitExtVectorElementLValue(LValue V); RValue EmitRValueForField(LValue LV, const FieldDecl *FD, SourceLocation Loc); @@ -2166,12 +2276,10 @@ public: const Decl *TargetDecl = nullptr, llvm::Instruction **callOrInvoke = nullptr); - RValue EmitCall(QualType FnType, llvm::Value *Callee, - SourceLocation CallLoc, + RValue EmitCall(QualType FnType, llvm::Value *Callee, const CallExpr *E, ReturnValueSlot ReturnValue, - CallExpr::const_arg_iterator ArgBeg, - CallExpr::const_arg_iterator ArgEnd, - const Decl *TargetDecl = nullptr); + const Decl *TargetDecl = nullptr, + llvm::Value *Chain = nullptr); RValue EmitCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue = ReturnValueSlot()); @@ -2207,23 +2315,28 @@ public: CXXDtorType Type, const CXXRecordDecl *RD); - RValue EmitCXXMemberCall(const CXXMethodDecl *MD, - SourceLocation CallLoc, - llvm::Value *Callee, - ReturnValueSlot ReturnValue, - llvm::Value *This, - llvm::Value *ImplicitParam, - QualType ImplicitParamTy, - CallExpr::const_arg_iterator ArgBeg, - CallExpr::const_arg_iterator ArgEnd); + RValue + EmitCXXMemberOrOperatorCall(const CXXMethodDecl *MD, llvm::Value *Callee, + ReturnValueSlot ReturnValue, llvm::Value *This, + llvm::Value *ImplicitParam, + QualType ImplicitParamTy, const CallExpr *E); + RValue EmitCXXStructorCall(const CXXMethodDecl *MD, llvm::Value *Callee, + ReturnValueSlot ReturnValue, llvm::Value *This, + llvm::Value *ImplicitParam, + QualType ImplicitParamTy, const CallExpr *E, + StructorType Type); RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E, ReturnValueSlot ReturnValue); + RValue EmitCXXMemberOrOperatorMemberCallExpr(const CallExpr *CE, + const CXXMethodDecl *MD, + ReturnValueSlot ReturnValue, + bool HasQualifier, + NestedNameSpecifier *Qualifier, + bool IsArrow, const Expr *Base); + // Compute the object pointer. RValue EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, ReturnValueSlot ReturnValue); - llvm::Value *EmitCXXOperatorMemberCallee(const CXXOperatorCallExpr *E, - const CXXMethodDecl *MD, - llvm::Value *This); RValue EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, const CXXMethodDecl *MD, ReturnValueSlot ReturnValue); @@ -2233,7 +2346,8 @@ public: RValue EmitBuiltinExpr(const FunctionDecl *FD, - unsigned BuiltinID, const CallExpr *E); + unsigned BuiltinID, const CallExpr *E, + ReturnValueSlot ReturnValue); RValue EmitBlockCallExpr(const CallExpr *E, ReturnValueSlot ReturnValue); @@ -2413,12 +2527,6 @@ public: /// EmitLoadOfComplex - Load a complex number from the specified l-value. ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc); - /// CreateStaticVarDecl - Create a zero-initialized LLVM global for - /// a static local variable. - llvm::Constant *CreateStaticVarDecl(const VarDecl &D, - const char *Separator, - llvm::GlobalValue::LinkageTypes Linkage); - /// AddInitializerToStaticVarDecl - Add the initializer for 'D' to the /// global variable that has already been created for it. If the initializer /// has a different type than GV does, this may free GV and return a different @@ -2433,6 +2541,9 @@ public: void EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::Constant *DeclPtr, bool PerformInit); + llvm::Constant *createAtExitStub(const VarDecl &VD, llvm::Constant *Dtor, + llvm::Constant *Addr); + /// Call atexit() with a function that passes the given argument to /// the given function. void registerGlobalDtorWithAtExit(const VarDecl &D, llvm::Constant *fn, @@ -2449,7 +2560,7 @@ public: /// GenerateCXXGlobalInitFunc - Generates code for initializing global /// variables. void GenerateCXXGlobalInitFunc(llvm::Function *Fn, - ArrayRef<llvm::Constant *> Decls, + ArrayRef<llvm::Function *> CXXThreadLocals, llvm::GlobalVariable *Guard = nullptr); /// GenerateCXXGlobalDtorsFunc - Generates code for destroying global @@ -2541,23 +2652,12 @@ public: /// passing to a runtime sanitizer handler. llvm::Constant *EmitCheckSourceLocation(SourceLocation Loc); - /// \brief Specify under what conditions this check can be recovered - enum CheckRecoverableKind { - /// Always terminate program execution if this check fails - CRK_Unrecoverable, - /// Check supports recovering, allows user to specify which - CRK_Recoverable, - /// Runtime conditionally aborts, always need to support recovery. - CRK_AlwaysRecoverable - }; - /// \brief Create a basic block that will call a handler function in a /// sanitizer runtime with the provided arguments, and create a conditional /// branch to it. - void EmitCheck(llvm::Value *Checked, StringRef CheckName, - ArrayRef<llvm::Constant *> StaticArgs, - ArrayRef<llvm::Value *> DynamicArgs, - CheckRecoverableKind Recoverable); + void EmitCheck(ArrayRef<std::pair<llvm::Value *, SanitizerKind>> Checked, + StringRef CheckName, ArrayRef<llvm::Constant *> StaticArgs, + ArrayRef<llvm::Value *> DynamicArgs); /// \brief Create a basic block that will call the trap intrinsic, and emit a /// conditional branch to it, for the -ftrapv checks. @@ -2589,18 +2689,15 @@ private: /// from function arguments into \arg Dst. See ABIArgInfo::Expand. /// /// \param AI - The first function argument of the expansion. - /// \return The argument following the last expanded function - /// argument. - llvm::Function::arg_iterator - ExpandTypeFromArgs(QualType Ty, LValue Dst, - llvm::Function::arg_iterator AI); - - /// ExpandTypeToArgs - Expand an RValue \arg Src, with the LLVM type for \arg - /// Ty, into individual arguments on the provided vector \arg Args. See - /// ABIArgInfo::Expand. - void ExpandTypeToArgs(QualType Ty, RValue Src, - SmallVectorImpl<llvm::Value *> &Args, - llvm::FunctionType *IRFuncTy); + void ExpandTypeFromArgs(QualType Ty, LValue Dst, + SmallVectorImpl<llvm::Argument *>::iterator &AI); + + /// ExpandTypeToArgs - Expand an RValue \arg RV, with the LLVM type for \arg + /// Ty, into individual arguments on the provided vector \arg IRCallArgs, + /// starting at index \arg IRCallArgPos. See ABIArgInfo::Expand. + void ExpandTypeToArgs(QualType Ty, RValue RV, llvm::FunctionType *IRFuncTy, + SmallVectorImpl<llvm::Value *> &IRCallArgs, + unsigned &IRCallArgPos); llvm::Value* EmitAsmInput(const TargetInfo::ConstraintInfo &Info, const Expr *InputExpr, std::string &ConstraintStr); @@ -2616,76 +2713,53 @@ public: void EmitCallArgs(CallArgList &Args, const T *CallArgTypeInfo, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd, - bool ForceColumnInfo = false) { - if (CallArgTypeInfo) { - EmitCallArgs(Args, CallArgTypeInfo->isVariadic(), - CallArgTypeInfo->param_type_begin(), - CallArgTypeInfo->param_type_end(), ArgBeg, ArgEnd, - ForceColumnInfo); - } else { - // T::param_type_iterator might not have a default ctor. - const QualType *NoIter = nullptr; - EmitCallArgs(Args, /*AllowExtraArguments=*/true, NoIter, NoIter, ArgBeg, - ArgEnd, ForceColumnInfo); - } - } - - template<typename ArgTypeIterator> - void EmitCallArgs(CallArgList& Args, - bool AllowExtraArguments, - ArgTypeIterator ArgTypeBeg, - ArgTypeIterator ArgTypeEnd, - CallExpr::const_arg_iterator ArgBeg, - CallExpr::const_arg_iterator ArgEnd, - bool ForceColumnInfo = false) { + const FunctionDecl *CalleeDecl = nullptr, + unsigned ParamsToSkip = 0, bool ForceColumnInfo = false) { SmallVector<QualType, 16> ArgTypes; CallExpr::const_arg_iterator Arg = ArgBeg; - // First, use the argument types that the type info knows about - for (ArgTypeIterator I = ArgTypeBeg, E = ArgTypeEnd; I != E; ++I, ++Arg) { - assert(Arg != ArgEnd && "Running over edge of argument list!"); -#ifndef NDEBUG - QualType ArgType = *I; - QualType ActualArgType = Arg->getType(); - if (ArgType->isPointerType() && ActualArgType->isPointerType()) { - QualType ActualBaseType = - ActualArgType->getAs<PointerType>()->getPointeeType(); - QualType ArgBaseType = - ArgType->getAs<PointerType>()->getPointeeType(); - if (ArgBaseType->isVariableArrayType()) { - if (const VariableArrayType *VAT = - getContext().getAsVariableArrayType(ActualBaseType)) { - if (!VAT->getSizeExpr()) - ActualArgType = ArgType; - } - } + assert((ParamsToSkip == 0 || CallArgTypeInfo) && + "Can't skip parameters if type info is not provided"); + if (CallArgTypeInfo) { + // First, use the argument types that the type info knows about + for (auto I = CallArgTypeInfo->param_type_begin() + ParamsToSkip, + E = CallArgTypeInfo->param_type_end(); + I != E; ++I, ++Arg) { + assert(Arg != ArgEnd && "Running over edge of argument list!"); + assert( + ((*I)->isVariablyModifiedType() || + getContext() + .getCanonicalType((*I).getNonReferenceType()) + .getTypePtr() == + getContext().getCanonicalType(Arg->getType()).getTypePtr()) && + "type mismatch in call argument!"); + ArgTypes.push_back(*I); } - assert(getContext().getCanonicalType(ArgType.getNonReferenceType()). - getTypePtr() == - getContext().getCanonicalType(ActualArgType).getTypePtr() && - "type mismatch in call argument!"); -#endif - ArgTypes.push_back(*I); } // Either we've emitted all the call args, or we have a call to variadic - // function or some other call that allows extra arguments. - assert((Arg == ArgEnd || AllowExtraArguments) && - "Extra arguments in non-variadic function!"); + // function. + assert( + (Arg == ArgEnd || !CallArgTypeInfo || CallArgTypeInfo->isVariadic()) && + "Extra arguments in non-variadic function!"); // If we still have any arguments, emit them using the type of the argument. for (; Arg != ArgEnd; ++Arg) - ArgTypes.push_back(Arg->getType()); + ArgTypes.push_back(getVarArgType(*Arg)); - EmitCallArgs(Args, ArgTypes, ArgBeg, ArgEnd, ForceColumnInfo); + EmitCallArgs(Args, ArgTypes, ArgBeg, ArgEnd, CalleeDecl, ParamsToSkip, + ForceColumnInfo); } void EmitCallArgs(CallArgList &Args, ArrayRef<QualType> ArgTypes, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd, - bool ForceColumnInfo = false); + const FunctionDecl *CalleeDecl = nullptr, + unsigned ParamsToSkip = 0, bool ForceColumnInfo = false); private: + QualType getVarArgType(const Expr *Arg); + const TargetCodeGenInfo &getTargetHooks() const { return CGM.getTargetCodeGenInfo(); } @@ -2701,6 +2775,8 @@ private: /// GetPointeeAlignment - Given an expression with a pointer type, emit the /// value and compute our best estimate of the alignment of the pointee. std::pair<llvm::Value*, unsigned> EmitPointerWithAlignment(const Expr *Addr); + + llvm::Value *GetValueForARMHint(unsigned BuiltinID); }; /// Helper class with most of the code for saving a value for a |