diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver/ToolChains/Darwin.cpp')
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/ToolChains/Darwin.cpp | 152 | 
1 files changed, 118 insertions, 34 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Darwin.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Darwin.cpp index 802b89b07002..95ec8d64c2c7 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains/Darwin.cpp @@ -175,7 +175,7 @@ bool darwin::Linker::NeedsTempPath(const InputInfoList &Inputs) const {    return false;  } -/// \brief Pass -no_deduplicate to ld64 under certain conditions: +/// Pass -no_deduplicate to ld64 under certain conditions:  ///  /// - Either -O0 or -O1 is explicitly specified  /// - No -O option is specified *and* this is a compile+link (implicit -O0) @@ -409,7 +409,7 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,    Args.AddLastArg(CmdArgs, options::OPT_Mach);  } -/// \brief Determine whether we are linking the ObjC runtime. +/// Determine whether we are linking the ObjC runtime.  static bool isObjCRuntimeLinked(const ArgList &Args) {    if (isObjCAutoRefCount(Args)) {      Args.ClaimAllArgs(options::OPT_fobjc_link_runtime); @@ -452,7 +452,8 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,    // we follow suite for ease of comparison.    AddLinkArgs(C, Args, CmdArgs, Inputs); -  // For LTO, pass the name of the optimization record file. +  // For LTO, pass the name of the optimization record file and other +  // opt-remarks flags.    if (Args.hasFlag(options::OPT_fsave_optimization_record,                     options::OPT_fno_save_optimization_record, false)) {      CmdArgs.push_back("-mllvm"); @@ -467,6 +468,26 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,      if (getLastProfileUseArg(Args)) {        CmdArgs.push_back("-mllvm");        CmdArgs.push_back("-lto-pass-remarks-with-hotness"); + +      if (const Arg *A = +              Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) { +        CmdArgs.push_back("-mllvm"); +        std::string Opt = +            std::string("-lto-pass-remarks-hotness-threshold=") + A->getValue(); +        CmdArgs.push_back(Args.MakeArgString(Opt)); +      } +    } +  } + +  // Propagate the -moutline flag to the linker in LTO. +  if (Args.hasFlag(options::OPT_moutline, options::OPT_mno_outline, false)) { +    if (getMachOToolChain().getMachOArchName(Args) == "arm64") { +      CmdArgs.push_back("-mllvm"); +      CmdArgs.push_back("-enable-machine-outliner"); + +      // Outline from linkonceodr functions by default in LTO. +      CmdArgs.push_back("-mllvm"); +      CmdArgs.push_back("-enable-linkonceodr-outlining");      }    } @@ -895,13 +916,26 @@ unsigned DarwinClang::GetDefaultDwarfVersion() const {    return 4;  } +SmallString<128> MachO::runtimeLibDir(bool IsEmbedded) const { +  SmallString<128> Dir(getDriver().ResourceDir); +  llvm::sys::path::append( +      Dir, "lib", IsEmbedded ? "macho_embedded" : "darwin"); +  return Dir; +} + +std::string Darwin::getFileNameForSanitizerLib(StringRef SanitizerName, +                                              bool Shared) const { +  return (Twine("libclang_rt.") + SanitizerName + "_" + +                      getOSLibraryNameSuffix() + +                      (Shared ? "_dynamic.dylib" : ".a")).str(); + +} +  void MachO::AddLinkRuntimeLib(const ArgList &Args, ArgStringList &CmdArgs,                                StringRef DarwinLibName,                                RuntimeLinkOptions Opts) const { -  SmallString<128> Dir(getDriver().ResourceDir); -  llvm::sys::path::append( -      Dir, "lib", (Opts & RLO_IsEmbedded) ? "macho_embedded" : "darwin"); +  SmallString<128> Dir = runtimeLibDir(Opts & RLO_IsEmbedded);    SmallString<128> P(Dir);    llvm::sys::path::append(P, DarwinLibName); @@ -979,6 +1013,8 @@ StringRef Darwin::getOSLibraryNameSuffix() const {  /// Check if the link command contains a symbol export directive.  static bool hasExportSymbolDirective(const ArgList &Args) {    for (Arg *A : Args) { +    if (A->getOption().matches(options::OPT_exported__symbols__list)) +      return true;      if (!A->getOption().matches(options::OPT_Wl_COMMA) &&          !A->getOption().matches(options::OPT_Xlinker))        continue; @@ -1008,7 +1044,6 @@ void Darwin::addProfileRTLibs(const ArgList &Args,    // runtime, automatically export symbols necessary to implement some of the    // runtime's functionality.    if (hasExportSymbolDirective(Args)) { -    addExportedSymbol(CmdArgs, "_VPMergeHook");      addExportedSymbol(CmdArgs, "___llvm_profile_filename");      addExportedSymbol(CmdArgs, "___llvm_profile_raw_version");      addExportedSymbol(CmdArgs, "_lprofCurFilename"); @@ -1020,12 +1055,9 @@ void DarwinClang::AddLinkSanitizerLibArgs(const ArgList &Args,                                            StringRef Sanitizer,                                            bool Shared) const {    auto RLO = RuntimeLinkOptions(RLO_AlwaysLink | (Shared ? RLO_AddRPath : 0U)); -  AddLinkRuntimeLib(Args, CmdArgs, -                    (Twine("libclang_rt.") + Sanitizer + "_" + -                     getOSLibraryNameSuffix() + -                     (Shared ? "_dynamic.dylib" : ".a")) -                        .str(), -                    RLO); +  std::string SanitizerRelFilename = +      getFileNameForSanitizerLib(Sanitizer, Shared); +  AddLinkRuntimeLib(Args, CmdArgs, SanitizerRelFilename, RLO);  }  ToolChain::RuntimeLibType DarwinClang::GetRuntimeLibType( @@ -1186,6 +1218,11 @@ struct DarwinPlatform {    DarwinEnvironmentKind getEnvironment() const { return Environment; } +  void setEnvironment(DarwinEnvironmentKind Kind) { +    Environment = Kind; +    InferSimulatorFromArch = false; +  } +    StringRef getOSVersion() const {      if (Kind == OSVersionArg)        return Argument->getValue(); @@ -1202,6 +1239,9 @@ struct DarwinPlatform {    /// Returns true if the target OS was explicitly specified.    bool isExplicitlySpecified() const { return Kind <= DeploymentTargetEnv; } +  /// Returns true if the simulator environment can be inferred from the arch. +  bool canInferSimulatorFromArch() const { return InferSimulatorFromArch; } +    /// Adds the -m<os>-version-min argument to the compiler invocation.    void addOSVersionMinArgument(DerivedArgList &Args, const OptTable &Opts) {      if (Argument) @@ -1271,8 +1311,13 @@ struct DarwinPlatform {      return Result;    }    static DarwinPlatform createFromSDK(DarwinPlatformKind Platform, -                                      StringRef Value) { -    return DarwinPlatform(InferredFromSDK, Platform, Value); +                                      StringRef Value, +                                      bool IsSimulator = false) { +    DarwinPlatform Result(InferredFromSDK, Platform, Value); +    if (IsSimulator) +      Result.Environment = DarwinEnvironmentKind::Simulator; +    Result.InferSimulatorFromArch = false; +    return Result;    }    static DarwinPlatform createFromArch(llvm::Triple::OSType OS,                                         StringRef Value) { @@ -1306,7 +1351,7 @@ private:    DarwinPlatformKind Platform;    DarwinEnvironmentKind Environment = DarwinEnvironmentKind::NativeEnvironment;    std::string OSVersion; -  bool HasOSVersion = true; +  bool HasOSVersion = true, InferSimulatorFromArch = true;    Arg *Argument;    StringRef EnvVarName;  }; @@ -1428,14 +1473,20 @@ Optional<DarwinPlatform> inferDeploymentTargetFromSDK(DerivedArgList &Args) {    if (StartVer != StringRef::npos && EndVer > StartVer) {      StringRef Version = SDK.slice(StartVer, EndVer + 1);      if (SDK.startswith("iPhoneOS") || SDK.startswith("iPhoneSimulator")) -      return DarwinPlatform::createFromSDK(Darwin::IPhoneOS, Version); +      return DarwinPlatform::createFromSDK( +          Darwin::IPhoneOS, Version, +          /*IsSimulator=*/SDK.startswith("iPhoneSimulator"));      else if (SDK.startswith("MacOSX"))        return DarwinPlatform::createFromSDK(Darwin::MacOS,                                             getSystemOrSDKMacOSVersion(Version));      else if (SDK.startswith("WatchOS") || SDK.startswith("WatchSimulator")) -      return DarwinPlatform::createFromSDK(Darwin::WatchOS, Version); +      return DarwinPlatform::createFromSDK( +          Darwin::WatchOS, Version, +          /*IsSimulator=*/SDK.startswith("WatchSimulator"));      else if (SDK.startswith("AppleTVOS") || SDK.startswith("AppleTVSimulator")) -      return DarwinPlatform::createFromSDK(Darwin::TvOS, Version); +      return DarwinPlatform::createFromSDK( +          Darwin::TvOS, Version, +          /*IsSimulator=*/SDK.startswith("AppleTVSimulator"));    }    return None;  } @@ -1443,10 +1494,16 @@ Optional<DarwinPlatform> inferDeploymentTargetFromSDK(DerivedArgList &Args) {  std::string getOSVersion(llvm::Triple::OSType OS, const llvm::Triple &Triple,                           const Driver &TheDriver) {    unsigned Major, Minor, Micro; +  llvm::Triple SystemTriple(llvm::sys::getProcessTriple());    switch (OS) {    case llvm::Triple::Darwin:    case llvm::Triple::MacOSX: -    if (!Triple.getMacOSXVersion(Major, Minor, Micro)) +    // If there is no version specified on triple, and both host and target are +    // macos, use the host triple to infer OS version. +    if (Triple.isMacOSX() && SystemTriple.isMacOSX() && +        !Triple.getOSMajorVersion()) +      SystemTriple.getMacOSXVersion(Major, Minor, Micro); +    else if (!Triple.getMacOSXVersion(Major, Minor, Micro))        TheDriver.Diag(diag::err_drv_invalid_darwin_version)            << Triple.getOSName();      break; @@ -1569,9 +1626,16 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {      OSTarget = getDeploymentTargetFromOSVersionArg(Args, getDriver());      // If no deployment target was specified on the command line, check for      // environment defines. -    if (!OSTarget) +    if (!OSTarget) {        OSTarget =            getDeploymentTargetFromEnvironmentVariables(getDriver(), getTriple()); +      if (OSTarget) { +        // Don't infer simulator from the arch when the SDK is also specified. +        Optional<DarwinPlatform> SDKTarget = inferDeploymentTargetFromSDK(Args); +        if (SDKTarget) +          OSTarget->setEnvironment(SDKTarget->getEnvironment()); +      } +    }      // If there is no command-line argument to specify the Target version and      // no environment variable defined, see if we can set the default based      // on -isysroot. @@ -1636,6 +1700,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const {    DarwinEnvironmentKind Environment = OSTarget->getEnvironment();    // Recognize iOS targets with an x86 architecture as the iOS simulator.    if (Environment == NativeEnvironment && Platform != MacOS && +      OSTarget->canInferSimulatorFromArch() &&        (getTriple().getArch() == llvm::Triple::x86 ||         getTriple().getArch() == llvm::Triple::x86_64))      Environment = Simulator; @@ -2230,24 +2295,43 @@ void Darwin::CheckObjCARC() const {  SanitizerMask Darwin::getSupportedSanitizers() const {    const bool IsX86_64 = getTriple().getArch() == llvm::Triple::x86_64;    SanitizerMask Res = ToolChain::getSupportedSanitizers(); -  Res |= SanitizerKind::Address; -  Res |= SanitizerKind::Leak; -  Res |= SanitizerKind::Fuzzer; -  Res |= SanitizerKind::FuzzerNoLink; + +  { +    using namespace SanitizerKind; +    assert(!(Res & (Address | Leak | Fuzzer | FuzzerNoLink | Thread)) && +           "Sanitizer is already registered as supported"); +  } + +  if (sanitizerRuntimeExists("asan")) +    Res |= SanitizerKind::Address; +  if (sanitizerRuntimeExists("lsan")) +    Res |= SanitizerKind::Leak; +  if (sanitizerRuntimeExists("fuzzer", /*Shared=*/false)) { +    Res |= SanitizerKind::Fuzzer; +    Res |= SanitizerKind::FuzzerNoLink; +  }    Res |= SanitizerKind::Function; -  if (isTargetMacOS()) { -    if (!isMacosxVersionLT(10, 9)) -      Res |= SanitizerKind::Vptr; +  if (isTargetMacOS() && !isMacosxVersionLT(10, 9)) +    Res |= SanitizerKind::Vptr; +  if (isTargetMacOS())      Res |= SanitizerKind::SafeStack; -    if (IsX86_64) -      Res |= SanitizerKind::Thread; -  } else if (isTargetIOSSimulator() || isTargetTvOSSimulator()) { -    if (IsX86_64) -      Res |= SanitizerKind::Thread; -  } + +  if (sanitizerRuntimeExists("tsan") && IsX86_64 && +      (isTargetMacOS() || isTargetIOSSimulator() || isTargetTvOSSimulator())) +    Res |= SanitizerKind::Thread; +    return Res;  }  void Darwin::printVerboseInfo(raw_ostream &OS) const {    CudaInstallation.print(OS);  } + +bool Darwin::sanitizerRuntimeExists(StringRef SanitizerName, +                                    bool Shared) const { +    std::string RelName = getFileNameForSanitizerLib(SanitizerName, Shared); +    SmallString<128> Dir = runtimeLibDir(); +    SmallString<128> AbsName(Dir); +    llvm::sys::path::append(AbsName, RelName); +    return getVFS().exists(AbsName); +}  | 
