diff options
Diffstat (limited to 'lib/CodeGen/CodeGenModule.cpp')
| -rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 199 | 
1 files changed, 115 insertions, 84 deletions
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 36005430ae4c..d48bff9c30a3 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -24,7 +24,6 @@  #include "CodeGenFunction.h"  #include "CodeGenPGO.h"  #include "CodeGenTBAA.h" -#include "ConstantBuilder.h"  #include "CoverageMappingGen.h"  #include "TargetInfo.h"  #include "clang/AST/ASTContext.h" @@ -42,6 +41,7 @@  #include "clang/Basic/SourceManager.h"  #include "clang/Basic/TargetInfo.h"  #include "clang/Basic/Version.h" +#include "clang/CodeGen/ConstantInitBuilder.h"  #include "clang/Frontend/CodeGenOptions.h"  #include "clang/Sema/SemaDiagnostic.h"  #include "llvm/ADT/Triple.h" @@ -406,8 +406,11 @@ void CodeGenModule::Release() {    EmitDeferredUnusedCoverageMappings();    if (CoverageMapping)      CoverageMapping->emit(); -  if (CodeGenOpts.SanitizeCfiCrossDso) +  if (CodeGenOpts.SanitizeCfiCrossDso) {      CodeGenFunction(*this).EmitCfiCheckFail(); +    CodeGenFunction(*this).EmitCfiCheckStub(); +  } +  emitAtAvailableLinkGuard();    emitLLVMUsed();    if (SanStats)      SanStats->finish(); @@ -416,6 +419,12 @@ void CodeGenModule::Release() {        (Context.getLangOpts().Modules || !LinkerOptionsMetadata.empty())) {      EmitModuleLinkOptions();    } + +  // Record mregparm value now so it is visible through rest of codegen. +  if (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86) +    getModule().addModuleFlag(llvm::Module::Error, "NumRegisterParameters", +                              CodeGenOpts.NumRegisterParameters); +      if (CodeGenOpts.DwarfVersion) {      // We actually want the latest version when there are conflicts.      // We can change from Warning to Latest if such mode is supported. @@ -833,7 +842,7 @@ void CodeGenModule::SetLLVMFunctionAttributes(const Decl *D,    AttributeListType AttributeList;    ConstructAttributeList(F->getName(), Info, D, AttributeList, CallingConv,                           false); -  F->setAttributes(llvm::AttributeSet::get(getLLVMContext(), AttributeList)); +  F->setAttributes(llvm::AttributeList::get(getLLVMContext(), AttributeList));    F->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));  } @@ -882,10 +891,10 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,          CodeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining)        B.addAttribute(llvm::Attribute::NoInline); -    F->addAttributes(llvm::AttributeSet::FunctionIndex, -                     llvm::AttributeSet::get( -                         F->getContext(), -                         llvm::AttributeSet::FunctionIndex, B)); +    F->addAttributes( +        llvm::AttributeList::FunctionIndex, +        llvm::AttributeList::get(F->getContext(), +                                 llvm::AttributeList::FunctionIndex, B));      return;    } @@ -951,9 +960,9 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,        B.addAttribute(llvm::Attribute::MinSize);    } -  F->addAttributes(llvm::AttributeSet::FunctionIndex, -                   llvm::AttributeSet::get( -                       F->getContext(), llvm::AttributeSet::FunctionIndex, B)); +  F->addAttributes(llvm::AttributeList::FunctionIndex, +                   llvm::AttributeList::get( +                       F->getContext(), llvm::AttributeList::FunctionIndex, B));    unsigned alignment = D->getMaxAlignment() / Context.getCharWidth();    if (alignment) @@ -1029,7 +1038,6 @@ static void setLinkageAndVisibilityForGV(llvm::GlobalValue *GV,        GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);      } else if (ND->hasAttr<DLLExportAttr>()) {        GV->setLinkage(llvm::GlobalValue::ExternalLinkage); -      GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);      } else if (ND->hasAttr<WeakAttr>() || ND->isWeakImported()) {        // "extern_weak" is overloaded in LLVM; we probably should have        // separate linkage types for this. @@ -1107,7 +1115,7 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,    if (FD->isReplaceableGlobalAllocationFunction()) {      // A replaceable global allocation function does not act like a builtin by      // default, only if it is invoked by a new-expression or delete-expression. -    F->addAttribute(llvm::AttributeSet::FunctionIndex, +    F->addAttribute(llvm::AttributeList::FunctionIndex,                      llvm::Attribute::NoBuiltin);      // A sane operator new returns a non-aliasing pointer. @@ -1116,7 +1124,7 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD, llvm::Function *F,      auto Kind = FD->getDeclName().getCXXOverloadedOperator();      if (getCodeGenOpts().AssumeSaneOperatorNew &&          (Kind == OO_New || Kind == OO_Array_New)) -      F->addAttribute(llvm::AttributeSet::ReturnIndex, +      F->addAttribute(llvm::AttributeList::ReturnIndex,                        llvm::Attribute::NoAlias);    } @@ -1482,6 +1490,30 @@ bool CodeGenModule::isInSanitizerBlacklist(llvm::GlobalVariable *GV,    return false;  } +bool CodeGenModule::imbueXRayAttrs(llvm::Function *Fn, SourceLocation Loc, +                                   StringRef Category) const { +  if (!LangOpts.XRayInstrument) +    return false; +  const auto &XRayFilter = getContext().getXRayFilter(); +  using ImbueAttr = XRayFunctionFilter::ImbueAttribute; +  auto Attr = XRayFunctionFilter::ImbueAttribute::NONE; +  if (Loc.isValid()) +    Attr = XRayFilter.shouldImbueLocation(Loc, Category); +  if (Attr == ImbueAttr::NONE) +    Attr = XRayFilter.shouldImbueFunction(Fn->getName()); +  switch (Attr) { +  case ImbueAttr::NONE: +    return false; +  case ImbueAttr::ALWAYS: +    Fn->addFnAttr("function-instrument", "xray-always"); +    break; +  case ImbueAttr::NEVER: +    Fn->addFnAttr("function-instrument", "xray-never"); +    break; +  } +  return true; +} +  bool CodeGenModule::MustBeEmitted(const ValueDecl *Global) {    // Never defer when EmitAllDecls is specified.    if (LangOpts.EmitAllDecls) @@ -1693,6 +1725,16 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {    }  } +// Check if T is a class type with a destructor that's not dllimport. +static bool HasNonDllImportDtor(QualType T) { +  if (const auto *RT = T->getBaseElementTypeUnsafe()->getAs<RecordType>()) +    if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) +      if (RD->getDestructor() && !RD->getDestructor()->hasAttr<DLLImportAttr>()) +        return true; + +  return false; +} +  namespace {    struct FunctionIsDirectlyRecursive :      public RecursiveASTVisitor<FunctionIsDirectlyRecursive> { @@ -1726,6 +1768,7 @@ namespace {      }    }; +  // Make sure we're not referencing non-imported vars or functions.    struct DLLImportFunctionVisitor        : public RecursiveASTVisitor<DLLImportFunctionVisitor> {      bool SafeToInline = true; @@ -1733,12 +1776,25 @@ namespace {      bool shouldVisitImplicitCode() const { return true; }      bool VisitVarDecl(VarDecl *VD) { -      // A thread-local variable cannot be imported. -      SafeToInline = !VD->getTLSKind(); +      if (VD->getTLSKind()) { +        // A thread-local variable cannot be imported. +        SafeToInline = false; +        return SafeToInline; +      } + +      // A variable definition might imply a destructor call. +      if (VD->isThisDeclarationADefinition()) +        SafeToInline = !HasNonDllImportDtor(VD->getType()); + +      return SafeToInline; +    } + +    bool VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { +      if (const auto *D = E->getTemporary()->getDestructor()) +        SafeToInline = D->hasAttr<DLLImportAttr>();        return SafeToInline;      } -    // Make sure we're not referencing non-imported vars or functions.      bool VisitDeclRefExpr(DeclRefExpr *E) {        ValueDecl *VD = E->getDecl();        if (isa<FunctionDecl>(VD)) @@ -1747,14 +1803,28 @@ namespace {          SafeToInline = !V->hasGlobalStorage() || V->hasAttr<DLLImportAttr>();        return SafeToInline;      } +      bool VisitCXXConstructExpr(CXXConstructExpr *E) {        SafeToInline = E->getConstructor()->hasAttr<DLLImportAttr>();        return SafeToInline;      } + +    bool VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { +      CXXMethodDecl *M = E->getMethodDecl(); +      if (!M) { +        // Call through a pointer to member function. This is safe to inline. +        SafeToInline = true; +      } else { +        SafeToInline = M->hasAttr<DLLImportAttr>(); +      } +      return SafeToInline; +    } +      bool VisitCXXDeleteExpr(CXXDeleteExpr *E) {        SafeToInline = E->getOperatorDelete()->hasAttr<DLLImportAttr>();        return SafeToInline;      } +      bool VisitCXXNewExpr(CXXNewExpr *E) {        SafeToInline = E->getOperatorNew()->hasAttr<DLLImportAttr>();        return SafeToInline; @@ -1783,16 +1853,6 @@ CodeGenModule::isTriviallyRecursive(const FunctionDecl *FD) {    return Walker.Result;  } -// Check if T is a class type with a destructor that's not dllimport. -static bool HasNonDllImportDtor(QualType T) { -  if (const RecordType *RT = dyn_cast<RecordType>(T)) -    if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) -      if (RD->getDestructor() && !RD->getDestructor()->hasAttr<DLLImportAttr>()) -        return true; - -  return false; -} -  bool CodeGenModule::shouldEmitFunction(GlobalDecl GD) {    if (getFunctionLinkage(GD) != llvm::Function::AvailableExternallyLinkage)      return true; @@ -1828,22 +1888,6 @@ bool CodeGenModule::shouldEmitFunction(GlobalDecl GD) {    return !isTriviallyRecursive(F);  } -/// If the type for the method's class was generated by -/// CGDebugInfo::createContextChain(), the cache contains only a -/// limited DIType without any declarations. Since EmitFunctionStart() -/// needs to find the canonical declaration for each method, we need -/// to construct the complete type prior to emitting the method. -void CodeGenModule::CompleteDIClassType(const CXXMethodDecl* D) { -  if (!D->isInstance()) -    return; - -  if (CGDebugInfo *DI = getModuleDebugInfo()) -    if (getCodeGenOpts().getDebugInfo() >= codegenoptions::LimitedDebugInfo) { -      const auto *ThisPtr = cast<PointerType>(D->getThisType(getContext())); -      DI->getOrCreateRecordType(ThisPtr->getPointeeType(), D->getLocation()); -    } -} -  void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {    const auto *D = cast<ValueDecl>(GD.getDecl()); @@ -1858,7 +1902,6 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {        return;      if (const auto *Method = dyn_cast<CXXMethodDecl>(D)) { -      CompleteDIClassType(Method);        // Make sure to emit the definition(s) before we emit the thunks.        // This is necessary for the generation of certain thunks.        if (const auto *CD = dyn_cast<CXXConstructorDecl>(Method)) @@ -1893,13 +1936,10 @@ static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old,  ///  /// If D is non-null, it specifies a decl that correspond to this.  This is used  /// to set the attributes on the function when it is first created. -llvm::Constant * -CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName, -                                       llvm::Type *Ty, -                                       GlobalDecl GD, bool ForVTable, -                                       bool DontDefer, bool IsThunk, -                                       llvm::AttributeSet ExtraAttrs, -                                       ForDefinition_t IsForDefinition) { +llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( +    StringRef MangledName, llvm::Type *Ty, GlobalDecl GD, bool ForVTable, +    bool DontDefer, bool IsThunk, llvm::AttributeList ExtraAttrs, +    ForDefinition_t IsForDefinition) {    const Decl *D = GD.getDecl();    // Lookup the entry, lazily creating it if necessary. @@ -1989,12 +2029,11 @@ CodeGenModule::GetOrCreateLLVMFunction(StringRef MangledName,    assert(F->getName() == MangledName && "name was uniqued!");    if (D)      SetFunctionAttributes(GD, F, IsIncompleteFunction, IsThunk); -  if (ExtraAttrs.hasAttributes(llvm::AttributeSet::FunctionIndex)) { -    llvm::AttrBuilder B(ExtraAttrs, llvm::AttributeSet::FunctionIndex); -    F->addAttributes(llvm::AttributeSet::FunctionIndex, -                     llvm::AttributeSet::get(VMContext, -                                             llvm::AttributeSet::FunctionIndex, -                                             B)); +  if (ExtraAttrs.hasAttributes(llvm::AttributeList::FunctionIndex)) { +    llvm::AttrBuilder B(ExtraAttrs, llvm::AttributeList::FunctionIndex); +    F->addAttributes(llvm::AttributeList::FunctionIndex, +                     llvm::AttributeList::get( +                         VMContext, llvm::AttributeList::FunctionIndex, B));    }    if (!DontDefer) { @@ -2069,7 +2108,7 @@ llvm::Constant *CodeGenModule::GetAddrOfFunction(GlobalDecl GD,    StringRef MangledName = getMangledName(GD);    return GetOrCreateLLVMFunction(MangledName, Ty, GD, ForVTable, DontDefer, -                                 /*IsThunk=*/false, llvm::AttributeSet(), +                                 /*IsThunk=*/false, llvm::AttributeList(),                                   IsForDefinition);  } @@ -2115,7 +2154,7 @@ GetRuntimeFunctionDecl(ASTContext &C, StringRef Name) {  /// type and name.  llvm::Constant *  CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name, -                                     llvm::AttributeSet ExtraAttrs, +                                     llvm::AttributeList ExtraAttrs,                                       bool Local) {    llvm::Constant *C =        GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false, @@ -2143,9 +2182,8 @@ CodeGenModule::CreateRuntimeFunction(llvm::FunctionType *FTy, StringRef Name,  /// CreateBuiltinFunction - Create a new builtin function with the specified  /// type and name.  llvm::Constant * -CodeGenModule::CreateBuiltinFunction(llvm::FunctionType *FTy, -                                     StringRef Name, -                                     llvm::AttributeSet ExtraAttrs) { +CodeGenModule::CreateBuiltinFunction(llvm::FunctionType *FTy, StringRef Name, +                                     llvm::AttributeList ExtraAttrs) {    llvm::Constant *C =        GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(), /*ForVTable=*/false,                                /*DontDefer=*/false, /*IsThunk=*/false, ExtraAttrs); @@ -2803,7 +2841,7 @@ llvm::GlobalValue::LinkageTypes CodeGenModule::getLLVMLinkageForDeclarator(    // We are guaranteed to have a strong definition somewhere else,    // so we can use available_externally linkage.    if (Linkage == GVA_AvailableExternally) -    return llvm::Function::AvailableExternallyLinkage; +    return llvm::GlobalValue::AvailableExternallyLinkage;    // Note that Apple's kernel linker doesn't support symbol    // coalescing, so we need to avoid linkonce and weak linkages there. @@ -2897,14 +2935,8 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,        continue;      // Get the call site's attribute list. -    SmallVector<llvm::AttributeSet, 8> newAttrs; -    llvm::AttributeSet oldAttrs = callSite.getAttributes(); - -    // Collect any return attributes from the call. -    if (oldAttrs.hasAttributes(llvm::AttributeSet::ReturnIndex)) -      newAttrs.push_back( -        llvm::AttributeSet::get(newFn->getContext(), -                                oldAttrs.getRetAttributes())); +    SmallVector<llvm::AttributeSet, 8> newArgAttrs; +    llvm::AttributeList oldAttrs = callSite.getAttributes();      // If the function was passed too few arguments, don't transform.      unsigned newNumArgs = newFn->arg_size(); @@ -2914,27 +2946,19 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,      // If any of the types mismatch, we don't transform.      unsigned argNo = 0;      bool dontTransform = false; -    for (llvm::Function::arg_iterator ai = newFn->arg_begin(), -           ae = newFn->arg_end(); ai != ae; ++ai, ++argNo) { -      if (callSite.getArgument(argNo)->getType() != ai->getType()) { +    for (llvm::Argument &A : newFn->args()) { +      if (callSite.getArgument(argNo)->getType() != A.getType()) {          dontTransform = true;          break;        }        // Add any parameter attributes. -      if (oldAttrs.hasAttributes(argNo + 1)) -        newAttrs. -          push_back(llvm:: -                    AttributeSet::get(newFn->getContext(), -                                      oldAttrs.getParamAttributes(argNo + 1))); +      newArgAttrs.push_back(oldAttrs.getParamAttributes(argNo)); +      argNo++;      }      if (dontTransform)        continue; -    if (oldAttrs.hasAttributes(llvm::AttributeSet::FunctionIndex)) -      newAttrs.push_back(llvm::AttributeSet::get(newFn->getContext(), -                                                 oldAttrs.getFnAttributes())); -      // Okay, we can transform this.  Create the new call instruction and copy      // over the required information.      newArgs.append(callSite.arg_begin(), callSite.arg_begin() + argNo); @@ -2958,8 +2982,9 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,      if (!newCall->getType()->isVoidTy())        newCall->takeName(callSite.getInstruction()); -    newCall.setAttributes( -                     llvm::AttributeSet::get(newFn->getContext(), newAttrs)); +    newCall.setAttributes(llvm::AttributeList::get( +        newFn->getContext(), oldAttrs.getFnAttributes(), +        oldAttrs.getRetAttributes(), newArgAttrs));      newCall.setCallingConv(callSite.getCallingConv());      // Finally, remove the old call, replacing any uses with the new one. @@ -3341,6 +3366,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) {      llvm_unreachable("unknown file format");    case llvm::Triple::COFF:    case llvm::Triple::ELF: +  case llvm::Triple::Wasm:      GV->setSection("cfstring");      break;    case llvm::Triple::MachO: @@ -3790,6 +3816,11 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {      EmitDeclContext(cast<NamespaceDecl>(D));      break;    case Decl::CXXRecord: +    if (DebugInfo) { +      if (auto *ES = D->getASTContext().getExternalSource()) +        if (ES->hasExternalDefinitions(D) == ExternalASTSource::EK_Never) +          DebugInfo->completeUnusedClass(cast<CXXRecordDecl>(*D)); +    }      // Emit any static data members, they may be definitions.      for (auto *I : cast<CXXRecordDecl>(D)->decls())        if (isa<VarDecl>(I) || isa<CXXRecordDecl>(I))  | 
