Skip to content
This repository has been archived by the owner on Apr 23, 2020. It is now read-only.

Commit

Permalink
Add Hurd target to Clang driver (2/2)
Browse files Browse the repository at this point in the history
This adds Hurd toolchain support to Clang's driver in addition
to handling translating the triple from Hurd-compatible form to
the actual triple registered in LLVM.

(Phabricator was stripping the empty files from the patch so I 
manually created them)

Patch by sthibaul (Samuel Thibault)

Differential Revision: https://reviews.llvm.org/D54379



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@347833 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Kristina Brooks committed Nov 29, 2018
1 parent 7704e06 commit 2709c8b
Show file tree
Hide file tree
Showing 16 changed files with 324 additions and 2 deletions.
2 changes: 2 additions & 0 deletions lib/Basic/Targets.cpp
Expand Up @@ -499,6 +499,8 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple,
return new NaClTargetInfo<X86_32TargetInfo>(Triple, Opts);
case llvm::Triple::ELFIAMCU:
return new MCUX86_32TargetInfo(Triple, Opts);
case llvm::Triple::Hurd:
return new HurdTargetInfo<X86_32TargetInfo>(Triple, Opts);
default:
return new X86_32TargetInfo(Triple, Opts);
}
Expand Down
23 changes: 23 additions & 0 deletions lib/Basic/Targets/OSTargets.h
Expand Up @@ -270,6 +270,29 @@ class LLVM_LIBRARY_VISIBILITY HaikuTargetInfo : public OSTargetInfo<Target> {
}
};

// Hurd target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY HurdTargetInfo : public OSTargetInfo<Target> {
protected:
void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
MacroBuilder &Builder) const override {
// Hurd defines; list based off of gcc output.
DefineStd(Builder, "unix", Opts);
Builder.defineMacro("__GNU__");
Builder.defineMacro("__gnu_hurd__");
Builder.defineMacro("__MACH__");
Builder.defineMacro("__GLIBC__");
Builder.defineMacro("__ELF__");
if (Opts.POSIXThreads)
Builder.defineMacro("_REENTRANT");
if (Opts.CPlusPlus)
Builder.defineMacro("_GNU_SOURCE");
}
public:
HurdTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: OSTargetInfo<Target>(Triple, Opts) {}
};

// Minix Target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY MinixTargetInfo : public OSTargetInfo<Target> {
Expand Down
1 change: 1 addition & 0 deletions lib/Driver/CMakeLists.txt
Expand Up @@ -47,6 +47,7 @@ add_clang_library(clangDriver
ToolChains/Haiku.cpp
ToolChains/HIP.cpp
ToolChains/Hexagon.cpp
ToolChains/Hurd.cpp
ToolChains/Linux.cpp
ToolChains/MipsLinux.cpp
ToolChains/MinGW.cpp
Expand Down
11 changes: 11 additions & 0 deletions lib/Driver/Driver.cpp
Expand Up @@ -26,6 +26,7 @@
#include "ToolChains/HIP.h"
#include "ToolChains/Haiku.h"
#include "ToolChains/Hexagon.h"
#include "ToolChains/Hurd.h"
#include "ToolChains/Lanai.h"
#include "ToolChains/Linux.h"
#include "ToolChains/MSVC.h"
Expand Down Expand Up @@ -402,6 +403,13 @@ static llvm::Triple computeTargetTriple(const Driver &D,

llvm::Triple Target(llvm::Triple::normalize(TargetTriple));

// GNU/Hurd's triples should have been -hurd-gnu*, but were historically made
// -gnu* only, and we can not change this, so we have to detect that case as
// being the Hurd OS.
if (TargetTriple.find("-unknown-gnu") != StringRef::npos ||
TargetTriple.find("-pc-gnu") != StringRef::npos)
Target.setOSName("hurd");

// Handle Apple-specific options available here.
if (Target.isOSBinFormatMachO()) {
// If an explicit Darwin arch name is given, that trumps all.
Expand Down Expand Up @@ -4574,6 +4582,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::Contiki:
TC = llvm::make_unique<toolchains::Contiki>(*this, Target, Args);
break;
case llvm::Triple::Hurd:
TC = llvm::make_unique<toolchains::Hurd>(*this, Target, Args);
break;
default:
// Of these targets, Hexagon is the only one that might have
// an OS of Linux, in which case it got handled above already.
Expand Down
3 changes: 2 additions & 1 deletion lib/Driver/ToolChains/Clang.cpp
Expand Up @@ -530,7 +530,8 @@ static bool useFramePointerForTargetByDefault(const ArgList &Args,
return !areOptimizationsEnabled(Args);
}

if (Triple.isOSLinux() || Triple.getOS() == llvm::Triple::CloudABI) {
if (Triple.isOSLinux() || Triple.getOS() == llvm::Triple::CloudABI ||
Triple.isOSHurd()) {
switch (Triple.getArch()) {
// Don't use a frame pointer on linux if optimizing for certain targets.
case llvm::Triple::mips64:
Expand Down
6 changes: 5 additions & 1 deletion lib/Driver/ToolChains/Gnu.cpp
Expand Up @@ -1880,7 +1880,8 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
"i386-linux-gnu", "i386-redhat-linux6E", "i686-redhat-linux",
"i586-redhat-linux", "i386-redhat-linux", "i586-suse-linux",
"i486-slackware-linux", "i686-montavista-linux", "i586-linux-gnu",
"i686-linux-android"};
"i686-linux-android", "i386-gnu", "i486-gnu",
"i586-gnu", "i686-gnu"};

static const char *const MIPSLibDirs[] = {"/lib"};
static const char *const MIPSTriples[] = {
Expand Down Expand Up @@ -2259,6 +2260,9 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple(
// FIXME: It may be worthwhile to generalize this and look for a second
// triple.
{"i386-linux-gnu/gcc/" + CandidateTriple.str(), "../../..",
(TargetArch == llvm::Triple::x86 &&
TargetTriple.getOS() != llvm::Triple::Solaris)},
{"i386-gnu/gcc/" + CandidateTriple.str(), "../../..",
(TargetArch == llvm::Triple::x86 &&
TargetTriple.getOS() != llvm::Triple::Solaris)}};

Expand Down
169 changes: 169 additions & 0 deletions lib/Driver/ToolChains/Hurd.cpp
@@ -0,0 +1,169 @@
//===--- Hurd.cpp - Hurd ToolChain Implementations --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "Hurd.h"
#include "CommonArgs.h"
#include "clang/Config/config.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Options.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/VirtualFileSystem.h"

using namespace clang::driver;
using namespace clang::driver::toolchains;
using namespace clang;
using namespace llvm::opt;

using tools::addPathIfExists;

/// Get our best guess at the multiarch triple for a target.
///
/// Debian-based systems are starting to use a multiarch setup where they use
/// a target-triple directory in the library and header search paths.
/// Unfortunately, this triple does not align with the vanilla target triple,
/// so we provide a rough mapping here.
static std::string getMultiarchTriple(const Driver &D,
const llvm::Triple &TargetTriple,
StringRef SysRoot) {
if (TargetTriple.getArch() == llvm::Triple::x86) {
// We use the existence of '/lib/<triple>' as a directory to detect some
// common hurd triples that don't quite match the Clang triple for both
// 32-bit and 64-bit targets. Multiarch fixes its install triples to these
// regardless of what the actual target triple is.
if (D.getVFS().exists(SysRoot + "/lib/i386-gnu"))
return "i386-gnu";
}

// For most architectures, just use whatever we have rather than trying to be
// clever.
return TargetTriple.str();
}

static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
// It happens that only x86 and PPC use the 'lib32' variant of oslibdir, and
// using that variant while targeting other architectures causes problems
// because the libraries are laid out in shared system roots that can't cope
// with a 'lib32' library search path being considered. So we only enable
// them when we know we may need it.
//
// FIXME: This is a bit of a hack. We should really unify this code for
// reasoning about oslibdir spellings with the lib dir spellings in the
// GCCInstallationDetector, but that is a more significant refactoring.

if (Triple.getArch() == llvm::Triple::x86)
return "lib32";

return Triple.isArch32Bit() ? "lib" : "lib64";
}

Hurd::Hurd(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: Generic_ELF(D, Triple, Args) {
std::string SysRoot = computeSysRoot();
path_list &Paths = getFilePaths();

const std::string OSLibDir = getOSLibDir(Triple, Args);
const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot);

// If we are currently running Clang inside of the requested system root, add
// its parent library paths to those searched.
// FIXME: It's not clear whether we should use the driver's installed
// directory ('Dir' below) or the ResourceDir.
if (StringRef(D.Dir).startswith(SysRoot)) {
addPathIfExists(D, D.Dir + "/../lib/" + MultiarchTriple, Paths);
addPathIfExists(D, D.Dir + "/../" + OSLibDir, Paths);
}

addPathIfExists(D, SysRoot + "/lib/" + MultiarchTriple, Paths);
addPathIfExists(D, SysRoot + "/lib/../" + OSLibDir, Paths);

addPathIfExists(D, SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
addPathIfExists(D, SysRoot + "/usr/lib/../" + OSLibDir, Paths);

// If we are currently running Clang inside of the requested system root, add
// its parent library path to those searched.
// FIXME: It's not clear whether we should use the driver's installed
// directory ('Dir' below) or the ResourceDir.
if (StringRef(D.Dir).startswith(SysRoot))
addPathIfExists(D, D.Dir + "/../lib", Paths);

addPathIfExists(D, SysRoot + "/lib", Paths);
addPathIfExists(D, SysRoot + "/usr/lib", Paths);
}

bool Hurd::HasNativeLLVMSupport() const { return true; }

Tool *Hurd::buildLinker() const { return new tools::gnutools::Linker(*this); }

Tool *Hurd::buildAssembler() const {
return new tools::gnutools::Assembler(*this);
}

std::string Hurd::computeSysRoot() const {
if (!getDriver().SysRoot.empty())
return getDriver().SysRoot;

return std::string();
}

std::string Hurd::getDynamicLinker(const ArgList &Args) const {
if (getArch() == llvm::Triple::x86)
return "/lib/ld.so";

llvm_unreachable("unsupported architecture");
}

void Hurd::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
const Driver &D = getDriver();
std::string SysRoot = computeSysRoot();

if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc))
return;

if (!DriverArgs.hasArg(options::OPT_nostdlibinc))
addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");

if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
SmallString<128> P(D.ResourceDir);
llvm::sys::path::append(P, "include");
addSystemInclude(DriverArgs, CC1Args, P);
}

if (DriverArgs.hasArg(options::OPT_nostdlibinc))
return;

// Check for configure-time C include directories.
StringRef CIncludeDirs(C_INCLUDE_DIRS);
if (CIncludeDirs != "") {
SmallVector<StringRef, 5> Dirs;
CIncludeDirs.split(Dirs, ":");
for (StringRef Dir : Dirs) {
StringRef Prefix =
llvm::sys::path::is_absolute(Dir) ? StringRef(SysRoot) : "";
addExternCSystemInclude(DriverArgs, CC1Args, Prefix + Dir);
}
return;
}

// Lacking those, try to detect the correct set of system includes for the
// target triple.
if (getTriple().getArch() == llvm::Triple::x86) {
std::string Path = SysRoot + "/usr/include/i386-gnu";
if (D.getVFS().exists(Path))
addExternCSystemInclude(DriverArgs, CC1Args, Path);
}

// Add an include of '/include' directly. This isn't provided by default by
// system GCCs, but is often used with cross-compiling GCCs, and harmless to
// add even when Clang is acting as-if it were a system compiler.
addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");

addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
}
46 changes: 46 additions & 0 deletions lib/Driver/ToolChains/Hurd.h
@@ -0,0 +1,46 @@
//===--- Hurd.h - Hurd ToolChain Implementations ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Hurd_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Hurd_H

#include "Gnu.h"
#include "clang/Driver/ToolChain.h"

namespace clang {
namespace driver {
namespace toolchains {

class LLVM_LIBRARY_VISIBILITY Hurd : public Generic_ELF {
public:
Hurd(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args);

bool HasNativeLLVMSupport() const override;

void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;

virtual std::string computeSysRoot() const;

virtual std::string getDynamicLinker(const llvm::opt::ArgList &Args) const;

std::vector<std::string> ExtraOpts;

protected:
Tool *buildAssembler() const override;
Tool *buildLinker() const override;
};

} // end namespace toolchains
} // end namespace driver
} // end namespace clang

#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_Hurd_H
3 changes: 3 additions & 0 deletions lib/Frontend/InitHeaderSearch.cpp
Expand Up @@ -260,6 +260,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple,

switch (os) {
case llvm::Triple::Linux:
case llvm::Triple::Hurd:
case llvm::Triple::Solaris:
llvm_unreachable("Include management is handled in the driver.");

Expand Down Expand Up @@ -412,6 +413,7 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths(

switch (os) {
case llvm::Triple::Linux:
case llvm::Triple::Hurd:
case llvm::Triple::Solaris:
llvm_unreachable("Include management is handled in the driver.");
break;
Expand Down Expand Up @@ -460,6 +462,7 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang,
break; // Everything else continues to use this routine's logic.

case llvm::Triple::Linux:
case llvm::Triple::Hurd:
case llvm::Triple::Solaris:
return;

Expand Down
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.

0 comments on commit 2709c8b

Please sign in to comment.