diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp | 176 |
1 files changed, 125 insertions, 51 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp index 11e4ad9..e142a21 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CodeGenFunction.cpp @@ -38,20 +38,38 @@ using namespace clang; using namespace CodeGen; +/// shouldEmitLifetimeMarkers - Decide whether we need emit the life-time +/// markers. +static bool shouldEmitLifetimeMarkers(const CodeGenOptions &CGOpts, + const LangOptions &LangOpts) { + if (CGOpts.DisableLifetimeMarkers) + return false; + + // Asan uses markers for use-after-scope checks. + if (CGOpts.SanitizeAddressUseAfterScope) + return true; + + // Disable lifetime markers in msan builds. + // FIXME: Remove this when msan works with lifetime markers. + if (LangOpts.Sanitize.has(SanitizerKind::Memory)) + return false; + + // For now, only in optimized builds. + return CGOpts.OptimizationLevel != 0; +} + CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) : CodeGenTypeCache(cgm), CGM(cgm), Target(cgm.getTarget()), Builder(cgm, cgm.getModule().getContext(), llvm::ConstantFolder(), CGBuilderInserterTy(this)), CurFn(nullptr), ReturnValue(Address::invalid()), - CapturedStmtInfo(nullptr), - SanOpts(CGM.getLangOpts().Sanitize), IsSanitizerScope(false), - CurFuncIsThunk(false), AutoreleaseResult(false), SawAsmBlock(false), - IsOutlinedSEHHelper(false), - BlockInfo(nullptr), BlockPointer(nullptr), - LambdaThisCaptureField(nullptr), NormalCleanupDest(nullptr), - NextCleanupDestIndex(1), FirstBlockInfo(nullptr), EHResumeBlock(nullptr), - ExceptionSlot(nullptr), EHSelectorSlot(nullptr), - DebugInfo(CGM.getModuleDebugInfo()), + CapturedStmtInfo(nullptr), SanOpts(CGM.getLangOpts().Sanitize), + IsSanitizerScope(false), CurFuncIsThunk(false), AutoreleaseResult(false), + SawAsmBlock(false), IsOutlinedSEHHelper(false), BlockInfo(nullptr), + BlockPointer(nullptr), LambdaThisCaptureField(nullptr), + NormalCleanupDest(nullptr), NextCleanupDestIndex(1), + FirstBlockInfo(nullptr), EHResumeBlock(nullptr), ExceptionSlot(nullptr), + EHSelectorSlot(nullptr), DebugInfo(CGM.getModuleDebugInfo()), DisableDebugInfo(false), DidCallStackSave(false), IndirectBranch(nullptr), PGO(cgm), SwitchInsn(nullptr), SwitchWeights(nullptr), CaseRangeBlock(nullptr), UnreachableBlock(nullptr), NumReturnExprs(0), @@ -60,7 +78,9 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) CXXStructorImplicitParamDecl(nullptr), CXXStructorImplicitParamValue(nullptr), OutermostConditional(nullptr), CurLexicalScope(nullptr), TerminateLandingPad(nullptr), - TerminateHandler(nullptr), TrapBB(nullptr) { + TerminateHandler(nullptr), TrapBB(nullptr), + ShouldEmitLifetimeMarkers( + shouldEmitLifetimeMarkers(CGM.getCodeGenOpts(), CGM.getLangOpts())) { if (!suppressNewContext) CGM.getCXXABI().getMangleContext().startNewFunction(); @@ -92,9 +112,8 @@ CodeGenFunction::~CodeGenFunction() { if (FirstBlockInfo) destroyBlockInfos(FirstBlockInfo); - if (getLangOpts().OpenMP) { + if (getLangOpts().OpenMP && CurFn) CGM.getOpenMPRuntime().functionFinished(*this); - } } CharUnits CodeGenFunction::getNaturalPointeeTypeAlignment(QualType T, @@ -429,12 +448,24 @@ void CodeGenFunction::EmitFunctionInstrumentation(const char *Fn) { EmitNounwindRuntimeCall(F, args); } -void CodeGenFunction::EmitMCountInstrumentation() { - llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); - - llvm::Constant *MCountFn = - CGM.CreateRuntimeFunction(FTy, getTarget().getMCountName()); - EmitNounwindRuntimeCall(MCountFn); +static void removeImageAccessQualifier(std::string& TyName) { + std::string ReadOnlyQual("__read_only"); + std::string::size_type ReadOnlyPos = TyName.find(ReadOnlyQual); + if (ReadOnlyPos != std::string::npos) + // "+ 1" for the space after access qualifier. + TyName.erase(ReadOnlyPos, ReadOnlyQual.size() + 1); + else { + std::string WriteOnlyQual("__write_only"); + std::string::size_type WriteOnlyPos = TyName.find(WriteOnlyQual); + if (WriteOnlyPos != std::string::npos) + TyName.erase(WriteOnlyPos, WriteOnlyQual.size() + 1); + else { + std::string ReadWriteQual("__read_write"); + std::string::size_type ReadWritePos = TyName.find(ReadWriteQual); + if (ReadWritePos != std::string::npos) + TyName.erase(ReadWritePos, ReadWriteQual.size() + 1); + } + } } // Returns the address space id that should be produced to the @@ -549,8 +580,6 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn, if (ty.isCanonical() && pos != std::string::npos) typeName.erase(pos+1, 8); - argTypeNames.push_back(llvm::MDString::get(Context, typeName)); - std::string baseTypeName; if (isPipe) baseTypeName = ty.getCanonicalType()->getAs<PipeType>() @@ -560,6 +589,17 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn, baseTypeName = ty.getUnqualifiedType().getCanonicalType().getAsString(Policy); + // Remove access qualifiers on images + // (as they are inseparable from type in clang implementation, + // but OpenCL spec provides a special query to get access qualifier + // via clGetKernelArgInfo with CL_KERNEL_ARG_ACCESS_QUALIFIER): + if (ty->isImageType()) { + removeImageAccessQualifier(typeName); + removeImageAccessQualifier(baseTypeName); + } + + argTypeNames.push_back(llvm::MDString::get(Context, typeName)); + // Turn "unsigned type" to "utype" pos = baseTypeName.find("unsigned"); if (pos != std::string::npos) @@ -709,6 +749,20 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, if (SanOpts.has(SanitizerKind::SafeStack)) Fn->addFnAttr(llvm::Attribute::SafeStack); + // Ignore TSan memory acesses from within ObjC/ObjC++ dealloc, initialize, + // .cxx_destruct and all of their calees at run time. + if (SanOpts.has(SanitizerKind::Thread)) { + if (const auto *OMD = dyn_cast_or_null<ObjCMethodDecl>(D)) { + IdentifierInfo *II = OMD->getSelector().getIdentifierInfoForSlot(0); + if (OMD->getMethodFamily() == OMF_dealloc || + OMD->getMethodFamily() == OMF_initialize || + (OMD->getSelector().isUnarySelector() && II->isStr(".cxx_destruct"))) { + Fn->addFnAttr("sanitize_thread_no_checking_at_run_time"); + Fn->removeFnAttr(llvm::Attribute::SanitizeThread); + } + } + } + // Apply xray attributes to the function (as a string, for now) if (D && ShouldXRayInstrumentFunction()) { if (const auto *XRayAttr = D->getAttr<XRayInstrumentAttr>()) { @@ -723,27 +777,9 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, } } - // Pass inline keyword to optimizer if it appears explicitly on any - // declaration. Also, in the case of -fno-inline attach NoInline - // attribute to all functions that are not marked AlwaysInline, or - // to all functions that are not marked inline or implicitly inline - // in the case of -finline-hint-functions. - if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) { - const CodeGenOptions& CodeGenOpts = CGM.getCodeGenOpts(); - if (!CodeGenOpts.NoInline) { - for (auto RI : FD->redecls()) - if (RI->isInlineSpecified()) { - Fn->addFnAttr(llvm::Attribute::InlineHint); - break; - } - if (CodeGenOpts.getInlining() == CodeGenOptions::OnlyHintInlining && - !FD->isInlined() && !Fn->hasFnAttribute(llvm::Attribute::InlineHint)) - Fn->addFnAttr(llvm::Attribute::NoInline); - } else if (!FD->hasAttr<AlwaysInlineAttr>()) - Fn->addFnAttr(llvm::Attribute::NoInline); + if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) if (CGM.getLangOpts().OpenMP && FD->hasAttr<OMPDeclareSimdDeclAttr>()) CGM.getOpenMPRuntime().emitDeclareSimdFunction(FD, Fn); - } // Add no-jump-tables value. Fn->addFnAttr("no-jump-tables", @@ -778,7 +814,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) if (FD->isMain()) Fn->addFnAttr(llvm::Attribute::NoRecurse); - + llvm::BasicBlock *EntryBB = createBasicBlock("entry", CurFn); // Create a marker to make it easy to insert allocas into the entryblock @@ -811,8 +847,12 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, if (ShouldInstrumentFunction()) EmitFunctionInstrumentation("__cyg_profile_func_enter"); + // Since emitting the mcount call here impacts optimizations such as function + // inlining, we just add an attribute to insert a mcount call in backend. + // The attribute "counting-function" is set to mcount function name which is + // architecture dependent. if (CGM.getCodeGenOpts().InstrumentForProfiling) - EmitMCountInstrumentation(); + Fn->addFnAttr("counting-function", getTarget().getMCountName()); if (RetTy->isVoidType()) { // Void type; nothing to return. @@ -1011,6 +1051,19 @@ QualType CodeGenFunction::BuildFunctionArgList(GlobalDecl GD, return ResTy; } +static bool +shouldUseUndefinedBehaviorReturnOptimization(const FunctionDecl *FD, + const ASTContext &Context) { + QualType T = FD->getReturnType(); + // Avoid the optimization for functions that return a record type with a + // trivial destructor or another trivially copyable type. + if (const RecordType *RT = T.getCanonicalType()->getAs<RecordType>()) { + if (const auto *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) + return !ClassDecl->hasTrivialDestructor(); + } + return !T.isTriviallyCopyableType(Context); +} + void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, const CGFunctionInfo &FnInfo) { const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); @@ -1040,6 +1093,13 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, if (SpecDecl->hasBody(SpecDecl)) Loc = SpecDecl->getLocation(); + Stmt *Body = FD->getBody(); + + // Initialize helper which will detect jumps which can cause invalid lifetime + // markers. + if (Body && ShouldEmitLifetimeMarkers) + Bypasses.Init(Body); + // Emit the standard function prologue. StartFunction(GD, ResTy, Fn, FnInfo, Args, Loc, BodyRange.getBegin()); @@ -1069,7 +1129,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, // Implicit copy-assignment gets the same special treatment as implicit // copy-constructors. emitImplicitAssignmentOperatorBody(Args); - } else if (Stmt *Body = FD->getBody()) { + } else if (Body) { EmitFunctionBody(Args, Body); } else llvm_unreachable("no definition for emitted function"); @@ -1082,17 +1142,23 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, // function call is used by the caller, the behavior is undefined. if (getLangOpts().CPlusPlus && !FD->hasImplicitReturnZero() && !SawAsmBlock && !FD->getReturnType()->isVoidType() && Builder.GetInsertBlock()) { + bool ShouldEmitUnreachable = + CGM.getCodeGenOpts().StrictReturn || + shouldUseUndefinedBehaviorReturnOptimization(FD, getContext()); if (SanOpts.has(SanitizerKind::Return)) { SanitizerScope SanScope(this); llvm::Value *IsFalse = Builder.getFalse(); EmitCheck(std::make_pair(IsFalse, SanitizerKind::Return), - "missing_return", EmitCheckSourceLocation(FD->getLocation()), - None); - } else if (CGM.getCodeGenOpts().OptimizationLevel == 0) { - EmitTrapCall(llvm::Intrinsic::trap); + SanitizerHandler::MissingReturn, + EmitCheckSourceLocation(FD->getLocation()), None); + } else if (ShouldEmitUnreachable) { + if (CGM.getCodeGenOpts().OptimizationLevel == 0) + EmitTrapCall(llvm::Intrinsic::trap); + } + if (SanOpts.has(SanitizerKind::Return) || ShouldEmitUnreachable) { + Builder.CreateUnreachable(); + Builder.ClearInsertionPoint(); } - Builder.CreateUnreachable(); - Builder.ClearInsertionPoint(); } // Emit the standard function epilogue. @@ -1731,6 +1797,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) { case Type::Enum: case Type::Elaborated: case Type::TemplateSpecialization: + case Type::ObjCTypeParam: case Type::ObjCObject: case Type::ObjCInterface: case Type::ObjCObjectPointer: @@ -1794,7 +1861,7 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) { }; EmitCheck(std::make_pair(Builder.CreateICmpSGT(Size, Zero), SanitizerKind::VLABound), - "vla_bound_not_positive", StaticArgs, Size); + SanitizerHandler::VLABoundNotPositive, StaticArgs, Size); } // Always zexting here would be wrong if it weren't @@ -1854,8 +1921,8 @@ Address CodeGenFunction::EmitMSVAListRef(const Expr *E) { } void CodeGenFunction::EmitDeclRefExprDbgValue(const DeclRefExpr *E, - llvm::Constant *Init) { - assert (Init && "Invalid DeclRefExpr initializer!"); + const APValue &Init) { + assert(!Init.isUninit() && "Invalid DeclRefExpr initializer!"); if (CGDebugInfo *Dbg = getDebugInfo()) if (CGM.getCodeGenOpts().getDebugInfo() >= codegenoptions::LimitedDebugInfo) Dbg->EmitGlobalVariable(E->getDecl(), Init); @@ -2046,3 +2113,10 @@ void CodeGenFunction::EmitSanitizerStatReport(llvm::SanitizerStatKind SSK) { IRB.SetCurrentDebugLocation(Builder.getCurrentDebugLocation()); CGM.getSanStats().create(IRB, SSK); } + +llvm::DebugLoc CodeGenFunction::SourceLocToDebugLoc(SourceLocation Location) { + if (CGDebugInfo *DI = getDebugInfo()) + return DI->SourceLocToDebugLoc(Location); + + return llvm::DebugLoc(); +} |