Esempio n. 1
0
StringRef swift::getPlatformNameForTriple(const llvm::Triple &triple) {
  if (triple.isOSDarwin())
    return getPlatformNameForDarwin(getDarwinPlatformKind(triple));

  if (triple.isAndroid())
    return "android";

  if (triple.isOSLinux())
    return "linux";

  if (triple.isOSFreeBSD())
    return "freebsd";
	
  if (triple.isOSWindows())
    return  "windows";

  return "";
}
Esempio n. 2
0
ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
                             const TargetOptions &Opts)
    : TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0),
      HW_FP(0) {
  bool IsOpenBSD = Triple.isOSOpenBSD();
  bool IsNetBSD = Triple.isOSNetBSD();

  // FIXME: the isOSBinFormatMachO is a workaround for identifying a Darwin-like
  // environment where size_t is `unsigned long` rather than `unsigned int`

  PtrDiffType = IntPtrType =
      (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||
       IsNetBSD)
          ? SignedLong
          : SignedInt;

  SizeType = (Triple.isOSDarwin() || Triple.isOSBinFormatMachO() || IsOpenBSD ||
              IsNetBSD)
                 ? UnsignedLong
                 : UnsignedInt;

  // ptrdiff_t is inconsistent on Darwin
  if ((Triple.isOSDarwin() || Triple.isOSBinFormatMachO()) &&
      !Triple.isWatchABI())
    PtrDiffType = SignedInt;

  // Cache arch related info.
  setArchInfo();

  // {} in inline assembly are neon specifiers, not assembly variant
  // specifiers.
  NoAsmVariants = true;

  // FIXME: This duplicates code from the driver that sets the -target-abi
  // option - this code is used if -target-abi isn't passed and should
  // be unified in some way.
  if (Triple.isOSBinFormatMachO()) {
    // The backend is hardwired to assume AAPCS for M-class processors, ensure
    // the frontend matches that.
    if (Triple.getEnvironment() == llvm::Triple::EABI ||
        Triple.getOS() == llvm::Triple::UnknownOS ||
        ArchProfile == llvm::ARM::ProfileKind::M) {
      setABI("aapcs");
    } else if (Triple.isWatchABI()) {
      setABI("aapcs16");
    } else {
      setABI("apcs-gnu");
    }
  } else if (Triple.isOSWindows()) {
    // FIXME: this is invalid for WindowsCE
    setABI("aapcs");
  } else {
    // Select the default based on the platform.
    switch (Triple.getEnvironment()) {
    case llvm::Triple::Android:
    case llvm::Triple::GNUEABI:
    case llvm::Triple::GNUEABIHF:
    case llvm::Triple::MuslEABI:
    case llvm::Triple::MuslEABIHF:
      setABI("aapcs-linux");
      break;
    case llvm::Triple::EABIHF:
    case llvm::Triple::EABI:
      setABI("aapcs");
      break;
    case llvm::Triple::GNU:
      setABI("apcs-gnu");
      break;
    default:
      if (IsNetBSD)
        setABI("apcs-gnu");
      else if (IsOpenBSD)
        setABI("aapcs-linux");
      else
        setABI("aapcs");
      break;
    }
  }

  // ARM targets default to using the ARM C++ ABI.
  TheCXXABI.set(TargetCXXABI::GenericARM);

  // ARM has atomics up to 8 bytes
  setAtomic();

  // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS)
  if (IsAAPCS && (Triple.getEnvironment() != llvm::Triple::Android))
    MaxVectorAlign = 64;

  // Do force alignment of members that follow zero length bitfields.  If
  // the alignment of the zero-length bitfield is greater than the member
  // that follows it, `bar', `bar' will be aligned as the  type of the
  // zero length bitfield.
  UseZeroLengthBitfieldAlignment = true;

  if (Triple.getOS() == llvm::Triple::Linux ||
      Triple.getOS() == llvm::Triple::UnknownOS)
    this->MCountName = Opts.EABIVersion == llvm::EABI::GNU
                           ? "\01__gnu_mcount_nc"
                           : "\01mcount";
}
Esempio n. 3
0
std::pair<bool, bool> LangOptions::setTarget(llvm::Triple triple) {
  clearAllPlatformConditionValues();

  if (triple.getOS() == llvm::Triple::Darwin &&
      triple.getVendor() == llvm::Triple::Apple) {
    // Rewrite darwinX.Y triples to macosx10.X'.Y ones.
    // It affects code generation on our platform.
    llvm::SmallString<16> osxBuf;
    llvm::raw_svector_ostream osx(osxBuf);
    osx << llvm::Triple::getOSTypeName(llvm::Triple::MacOSX);

    unsigned major, minor, micro;
    triple.getMacOSXVersion(major, minor, micro);
    osx << major << "." << minor;
    if (micro != 0)
      osx << "." << micro;

    triple.setOSName(osx.str());
  }
  Target = std::move(triple);

  bool UnsupportedOS = false;

  // Set the "os" platform condition.
  if (Target.isMacOSX())
    addPlatformConditionValue(PlatformConditionKind::OS, "OSX");
  else if (triple.isTvOS())
    addPlatformConditionValue(PlatformConditionKind::OS, "tvOS");
  else if (triple.isWatchOS())
    addPlatformConditionValue(PlatformConditionKind::OS, "watchOS");
  else if (triple.isiOS())
    addPlatformConditionValue(PlatformConditionKind::OS, "iOS");
  else if (triple.isAndroid())
    addPlatformConditionValue(PlatformConditionKind::OS, "Android");
  else if (triple.isOSLinux())
    addPlatformConditionValue(PlatformConditionKind::OS, "Linux");
  else if (triple.isOSFreeBSD())
    addPlatformConditionValue(PlatformConditionKind::OS, "FreeBSD");
  else if (triple.isOSWindows())
    addPlatformConditionValue(PlatformConditionKind::OS, "Windows");
  else if (triple.isWindowsCygwinEnvironment())
    addPlatformConditionValue(PlatformConditionKind::OS, "Cygwin");
  else if (triple.isPS4())
    addPlatformConditionValue(PlatformConditionKind::OS, "PS4");
  else
    UnsupportedOS = true;

  bool UnsupportedArch = false;

  // Set the "arch" platform condition.
  switch (Target.getArch()) {
  case llvm::Triple::ArchType::arm:
  case llvm::Triple::ArchType::thumb:
    addPlatformConditionValue(PlatformConditionKind::Arch, "arm");
    break;
  case llvm::Triple::ArchType::aarch64:
    addPlatformConditionValue(PlatformConditionKind::Arch, "arm64");
    break;
  case llvm::Triple::ArchType::ppc64:
    addPlatformConditionValue(PlatformConditionKind::Arch, "powerpc64");
    break;
  case llvm::Triple::ArchType::ppc64le:
    addPlatformConditionValue(PlatformConditionKind::Arch, "powerpc64le");
    break;
  case llvm::Triple::ArchType::x86:
    addPlatformConditionValue(PlatformConditionKind::Arch, "i386");
    break;
  case llvm::Triple::ArchType::x86_64:
    addPlatformConditionValue(PlatformConditionKind::Arch, "x86_64");
    break;
  case llvm::Triple::ArchType::systemz:
    addPlatformConditionValue(PlatformConditionKind::Arch, "s390x");
    break;
  default:
    UnsupportedArch = true;
  }

  if (UnsupportedOS || UnsupportedArch)
    return { UnsupportedOS, UnsupportedArch };

  // Set the "_endian" platform condition.
  switch (Target.getArch()) {
  case llvm::Triple::ArchType::arm:
  case llvm::Triple::ArchType::thumb:
    addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
    break;
  case llvm::Triple::ArchType::aarch64:
    addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
    break;
  case llvm::Triple::ArchType::ppc64:
    addPlatformConditionValue(PlatformConditionKind::Endianness, "big");
    break;
  case llvm::Triple::ArchType::ppc64le:
    addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
    break;
  case llvm::Triple::ArchType::x86:
    addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
    break;
  case llvm::Triple::ArchType::x86_64:
    addPlatformConditionValue(PlatformConditionKind::Endianness, "little");
    break;
  case llvm::Triple::ArchType::systemz:
    addPlatformConditionValue(PlatformConditionKind::Endianness, "big");
    break;
  default:
    llvm_unreachable("undefined architecture endianness");
  }

  // Set the "runtime" platform condition.
  if (EnableObjCInterop)
    addPlatformConditionValue(PlatformConditionKind::Runtime, "_ObjC");
  else
    addPlatformConditionValue(PlatformConditionKind::Runtime, "_Native");

  // If you add anything to this list, change the default size of
  // PlatformConditionValues to not require an extra allocation
  // in the common case.

  return { false, false };
}
Esempio n. 4
0
CudaInstallationDetector::CudaInstallationDetector(
    const Driver &D, const llvm::Triple &HostTriple,
    const llvm::opt::ArgList &Args)
    : D(D) {
  struct Candidate {
    std::string Path;
    bool StrictChecking;

    Candidate(std::string Path, bool StrictChecking = false)
        : Path(Path), StrictChecking(StrictChecking) {}
  };
  SmallVector<Candidate, 4> Candidates;

  // In decreasing order so we prefer newer versions to older versions.
  std::initializer_list<const char *> Versions = {"8.0", "7.5", "7.0"};

  if (Args.hasArg(clang::driver::options::OPT_cuda_path_EQ)) {
    Candidates.emplace_back(
        Args.getLastArgValue(clang::driver::options::OPT_cuda_path_EQ).str());
  } else if (HostTriple.isOSWindows()) {
    for (const char *Ver : Versions)
      Candidates.emplace_back(
          D.SysRoot + "/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v" +
          Ver);
  } else {
    if (!Args.hasArg(clang::driver::options::OPT_cuda_path_ignore_env)) {
      // Try to find ptxas binary. If the executable is located in a directory
      // called 'bin/', its parent directory might be a good guess for a valid
      // CUDA installation.
      // However, some distributions might installs 'ptxas' to /usr/bin. In that
      // case the candidate would be '/usr' which passes the following checks
      // because '/usr/include' exists as well. To avoid this case, we always
      // check for the directory potentially containing files for libdevice,
      // even if the user passes -nocudalib.
      if (llvm::ErrorOr<std::string> ptxas =
              llvm::sys::findProgramByName("ptxas")) {
        SmallString<256> ptxasAbsolutePath;
        llvm::sys::fs::real_path(*ptxas, ptxasAbsolutePath);

        StringRef ptxasDir = llvm::sys::path::parent_path(ptxasAbsolutePath);
        if (llvm::sys::path::filename(ptxasDir) == "bin")
          Candidates.emplace_back(llvm::sys::path::parent_path(ptxasDir),
                                  /*StrictChecking=*/true);
      }
    }

    Candidates.emplace_back(D.SysRoot + "/usr/local/cuda");
    for (const char *Ver : Versions)
      Candidates.emplace_back(D.SysRoot + "/usr/local/cuda-" + Ver);

    if (Distro(D.getVFS()).IsDebian())
      // Special case for Debian to have nvidia-cuda-toolkit work
      // out of the box. More info on http://bugs.debian.org/882505
      Candidates.emplace_back(D.SysRoot + "/usr/lib/cuda");
  }

  bool NoCudaLib = Args.hasArg(options::OPT_nocudalib);

  for (const auto &Candidate : Candidates) {
    InstallPath = Candidate.Path;
    if (InstallPath.empty() || !D.getVFS().exists(InstallPath))
      continue;

    BinPath = InstallPath + "/bin";
    IncludePath = InstallPath + "/include";
    LibDevicePath = InstallPath + "/nvvm/libdevice";

    auto &FS = D.getVFS();
    if (!(FS.exists(IncludePath) && FS.exists(BinPath)))
      continue;
    bool CheckLibDevice = (!NoCudaLib || Candidate.StrictChecking);
    if (CheckLibDevice && !FS.exists(LibDevicePath))
      continue;

    // On Linux, we have both lib and lib64 directories, and we need to choose
    // based on our triple.  On MacOS, we have only a lib directory.
    //
    // It's sufficient for our purposes to be flexible: If both lib and lib64
    // exist, we choose whichever one matches our triple.  Otherwise, if only
    // lib exists, we use it.
    if (HostTriple.isArch64Bit() && FS.exists(InstallPath + "/lib64"))
      LibPath = InstallPath + "/lib64";
    else if (FS.exists(InstallPath + "/lib"))
      LibPath = InstallPath + "/lib";
    else
      continue;

    llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> VersionFile =
        FS.getBufferForFile(InstallPath + "/version.txt");
    if (!VersionFile) {
      // CUDA 7.0 doesn't have a version.txt, so guess that's our version if
      // version.txt isn't present.
      Version = CudaVersion::CUDA_70;
    } else {
      Version = ParseCudaVersionFile((*VersionFile)->getBuffer());
    }

    if (Version >= CudaVersion::CUDA_90) {
      // CUDA-9+ uses single libdevice file for all GPU variants.
      std::string FilePath = LibDevicePath + "/libdevice.10.bc";
      if (FS.exists(FilePath)) {
        for (const char *GpuArchName :
             {"sm_20", "sm_30", "sm_32", "sm_35", "sm_50", "sm_52", "sm_53",
                   "sm_60", "sm_61", "sm_62", "sm_70", "sm_72"}) {
          const CudaArch GpuArch = StringToCudaArch(GpuArchName);
          if (Version >= MinVersionForCudaArch(GpuArch) &&
              Version <= MaxVersionForCudaArch(GpuArch))
            LibDeviceMap[GpuArchName] = FilePath;
        }
      }
    } else {
      std::error_code EC;
      for (llvm::sys::fs::directory_iterator LI(LibDevicePath, EC), LE;
           !EC && LI != LE; LI = LI.increment(EC)) {
        StringRef FilePath = LI->path();
        StringRef FileName = llvm::sys::path::filename(FilePath);
        // Process all bitcode filenames that look like
        // libdevice.compute_XX.YY.bc
        const StringRef LibDeviceName = "libdevice.";
        if (!(FileName.startswith(LibDeviceName) && FileName.endswith(".bc")))
          continue;
        StringRef GpuArch = FileName.slice(
            LibDeviceName.size(), FileName.find('.', LibDeviceName.size()));
        LibDeviceMap[GpuArch] = FilePath.str();
        // Insert map entries for specifc devices with this compute
        // capability. NVCC's choice of the libdevice library version is
        // rather peculiar and depends on the CUDA version.
        if (GpuArch == "compute_20") {
          LibDeviceMap["sm_20"] = FilePath;
          LibDeviceMap["sm_21"] = FilePath;
          LibDeviceMap["sm_32"] = FilePath;
        } else if (GpuArch == "compute_30") {
          LibDeviceMap["sm_30"] = FilePath;
          if (Version < CudaVersion::CUDA_80) {
            LibDeviceMap["sm_50"] = FilePath;
            LibDeviceMap["sm_52"] = FilePath;
            LibDeviceMap["sm_53"] = FilePath;
          }
          LibDeviceMap["sm_60"] = FilePath;
          LibDeviceMap["sm_61"] = FilePath;
          LibDeviceMap["sm_62"] = FilePath;
        } else if (GpuArch == "compute_35") {
          LibDeviceMap["sm_35"] = FilePath;
          LibDeviceMap["sm_37"] = FilePath;
        } else if (GpuArch == "compute_50") {
          if (Version >= CudaVersion::CUDA_80) {
            LibDeviceMap["sm_50"] = FilePath;
            LibDeviceMap["sm_52"] = FilePath;
            LibDeviceMap["sm_53"] = FilePath;
          }
        }
      }
    }

    // Check that we have found at least one libdevice that we can link in if
    // -nocudalib hasn't been specified.
    if (LibDeviceMap.empty() && !NoCudaLib)
      continue;

    IsValid = true;
    break;
  }
}
Esempio n. 5
0
CudaInstallationDetector::CudaInstallationDetector(
    const Driver &D, const llvm::Triple &HostTriple,
    const llvm::opt::ArgList &Args)
    : D(D) {
  SmallVector<std::string, 4> CudaPathCandidates;

  // In decreasing order so we prefer newer versions to older versions.
  std::initializer_list<const char *> Versions = {"8.0", "7.5", "7.0"};

  if (Args.hasArg(clang::driver::options::OPT_cuda_path_EQ)) {
    CudaPathCandidates.push_back(
        Args.getLastArgValue(clang::driver::options::OPT_cuda_path_EQ));
  } else if (HostTriple.isOSWindows()) {
    for (const char *Ver : Versions)
      CudaPathCandidates.push_back(
          D.SysRoot + "/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v" +
          Ver);
  } else {
    CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda");
    for (const char *Ver : Versions)
      CudaPathCandidates.push_back(D.SysRoot + "/usr/local/cuda-" + Ver);
  }

  for (const auto &CudaPath : CudaPathCandidates) {
    if (CudaPath.empty() || !D.getVFS().exists(CudaPath))
      continue;

    InstallPath = CudaPath;
    BinPath = CudaPath + "/bin";
    IncludePath = InstallPath + "/include";
    LibDevicePath = InstallPath + "/nvvm/libdevice";

    auto &FS = D.getVFS();
    if (!(FS.exists(IncludePath) && FS.exists(BinPath) &&
          FS.exists(LibDevicePath)))
      continue;

    // On Linux, we have both lib and lib64 directories, and we need to choose
    // based on our triple.  On MacOS, we have only a lib directory.
    //
    // It's sufficient for our purposes to be flexible: If both lib and lib64
    // exist, we choose whichever one matches our triple.  Otherwise, if only
    // lib exists, we use it.
    if (HostTriple.isArch64Bit() && FS.exists(InstallPath + "/lib64"))
      LibPath = InstallPath + "/lib64";
    else if (FS.exists(InstallPath + "/lib"))
      LibPath = InstallPath + "/lib";
    else
      continue;

    llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> VersionFile =
        FS.getBufferForFile(InstallPath + "/version.txt");
    if (!VersionFile) {
      // CUDA 7.0 doesn't have a version.txt, so guess that's our version if
      // version.txt isn't present.
      Version = CudaVersion::CUDA_70;
    } else {
      Version = ParseCudaVersionFile((*VersionFile)->getBuffer());
    }

    std::error_code EC;
    for (llvm::sys::fs::directory_iterator LI(LibDevicePath, EC), LE;
         !EC && LI != LE; LI = LI.increment(EC)) {
      StringRef FilePath = LI->path();
      StringRef FileName = llvm::sys::path::filename(FilePath);
      // Process all bitcode filenames that look like libdevice.compute_XX.YY.bc
      const StringRef LibDeviceName = "libdevice.";
      if (!(FileName.startswith(LibDeviceName) && FileName.endswith(".bc")))
        continue;
      StringRef GpuArch = FileName.slice(
          LibDeviceName.size(), FileName.find('.', LibDeviceName.size()));
      LibDeviceMap[GpuArch] = FilePath.str();
      // Insert map entries for specifc devices with this compute
      // capability. NVCC's choice of the libdevice library version is
      // rather peculiar and depends on the CUDA version.
      if (GpuArch == "compute_20") {
        LibDeviceMap["sm_20"] = FilePath;
        LibDeviceMap["sm_21"] = FilePath;
        LibDeviceMap["sm_32"] = FilePath;
      } else if (GpuArch == "compute_30") {
        LibDeviceMap["sm_30"] = FilePath;
        if (Version < CudaVersion::CUDA_80) {
          LibDeviceMap["sm_50"] = FilePath;
          LibDeviceMap["sm_52"] = FilePath;
          LibDeviceMap["sm_53"] = FilePath;
        }
        LibDeviceMap["sm_60"] = FilePath;
        LibDeviceMap["sm_61"] = FilePath;
        LibDeviceMap["sm_62"] = FilePath;
      } else if (GpuArch == "compute_35") {
        LibDeviceMap["sm_35"] = FilePath;
        LibDeviceMap["sm_37"] = FilePath;
      } else if (GpuArch == "compute_50") {
        if (Version >= CudaVersion::CUDA_80) {
          LibDeviceMap["sm_50"] = FilePath;
          LibDeviceMap["sm_52"] = FilePath;
          LibDeviceMap["sm_53"] = FilePath;
        }
      }
    }

    IsValid = true;
    break;
  }
}
Esempio n. 6
0
OptionSet<SanitizerKind> swift::parseSanitizerArgValues(
    const llvm::opt::ArgList &Args,
    const llvm::opt::Arg *A,
    const llvm::Triple &Triple,
    DiagnosticEngine &Diags,
    llvm::function_ref<bool(llvm::StringRef, bool)> sanitizerRuntimeLibExists) {
  OptionSet<SanitizerKind> sanitizerSet;

  // Find the sanitizer kind.
  for (int i = 0, n = A->getNumValues(); i != n; ++i) {
    auto kind = llvm::StringSwitch<Optional<SanitizerKind>>(A->getValue(i))
        .Case("address", SanitizerKind::Address)
        .Case("thread", SanitizerKind::Thread)
        .Case("fuzzer", SanitizerKind::Fuzzer)
        .Default(None);
    bool isShared = kind && *kind != SanitizerKind::Fuzzer;
    if (!kind) {
      Diags.diagnose(SourceLoc(), diag::error_unsupported_option_argument,
          A->getOption().getPrefixedName(), A->getValue(i));
    } else {
      // Support is determined by existance of the sanitizer library.
      bool sanitizerSupported =
          sanitizerRuntimeLibExists(toFileName(*kind), isShared);

      // TSan is explicitly not supported for 32 bits.
      if (*kind == SanitizerKind::Thread && !Triple.isArch64Bit())
        sanitizerSupported = false;

      if (!sanitizerSupported) {
        SmallString<128> b;
        Diags.diagnose(SourceLoc(), diag::error_unsupported_opt_for_target,
                       (A->getOption().getPrefixedName() + toStringRef(*kind))
                           .toStringRef(b),
                       Triple.getTriple());
      } else {
        sanitizerSet |= *kind;
      }
    }
  }

  // Check that we're one of the known supported targets for sanitizers.
  if (!(Triple.isOSDarwin() || Triple.isOSLinux() || Triple.isOSWindows())) {
    SmallString<128> b;
    Diags.diagnose(SourceLoc(), diag::error_unsupported_opt_for_target,
      (A->getOption().getPrefixedName() +
          StringRef(A->getAsString(Args))).toStringRef(b),
      Triple.getTriple());
  }

  // Address and thread sanitizers can not be enabled concurrently.
  if ((sanitizerSet & SanitizerKind::Thread)
        && (sanitizerSet & SanitizerKind::Address)) {
    SmallString<128> b1;
    SmallString<128> b2;
    Diags.diagnose(SourceLoc(), diag::error_argument_not_allowed_with,
        (A->getOption().getPrefixedName()
            + toStringRef(SanitizerKind::Address)).toStringRef(b1),
        (A->getOption().getPrefixedName()
            + toStringRef(SanitizerKind::Thread)).toStringRef(b2));
  }

  return sanitizerSet;
}