From: Daniel Dunbar Date: Sat, 2 May 2009 18:28:39 +0000 (+0000) Subject: DragonFly ToolChain definition for driver. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=11e1b40d759a643086f590f6ffbd9d68360bad46;p=clang DragonFly ToolChain definition for driver. - Patch by Alex Hornung! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70635 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Driver/HostInfo.h b/include/clang/Driver/HostInfo.h index aed93f750e..343809a433 100644 --- a/include/clang/Driver/HostInfo.h +++ b/include/clang/Driver/HostInfo.h @@ -69,6 +69,8 @@ const HostInfo *createDarwinHostInfo(const Driver &D, const char *Arch, const char *Platform, const char *OS); const HostInfo *createFreeBSDHostInfo(const Driver &D, const char *Arch, const char *Platform, const char *OS); +const HostInfo *createDragonFlyHostInfo(const Driver &D, const char *Arch, + const char *Platform, const char *OS); const HostInfo *createUnknownHostInfo(const Driver &D, const char *Arch, const char *Platform, const char *OS); diff --git a/include/clang/Driver/Options.def b/include/clang/Driver/Options.def index 1351175519..58f6517572 100644 --- a/include/clang/Driver/Options.def +++ b/include/clang/Driver/Options.def @@ -522,6 +522,7 @@ OPTION("-no-integrated-cpp", no_integrated_cpp, Flag, INVALID, INVALID, "d", 0, OPTION("-no_dead_strip_inits_and_terms", no__dead__strip__inits__and__terms, Flag, INVALID, INVALID, "", 0, 0, 0) OPTION("-nodefaultlibs", nodefaultlibs, Flag, INVALID, INVALID, "", 0, 0, 0) OPTION("-nofixprebinding", nofixprebinding, Flag, INVALID, INVALID, "", 0, 0, 0) +OPTION("-nolibc", nolibc, Flag, INVALID, INVALID, "", 0, 0, 0) OPTION("-nomultidefs", nomultidefs, Flag, INVALID, INVALID, "", 0, 0, 0) OPTION("-noprebind", noprebind, Flag, INVALID, INVALID, "", 0, 0, 0) OPTION("-noseglinkedit", noseglinkedit, Flag, INVALID, INVALID, "", 0, 0, 0) diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 6f75d3e7f9..8df64ea618 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1169,7 +1169,10 @@ const HostInfo *Driver::GetHostInfo(const char *Triple) const { if (memcmp(&OS[0], "freebsd", 7) == 0) return createFreeBSDHostInfo(*this, Arch.c_str(), Platform.c_str(), OS.c_str()); - + if (memcmp(&OS[0], "dragonfly", 9) == 0) + return createDragonFlyHostInfo(*this, Arch.c_str(), Platform.c_str(), + OS.c_str()); + return createUnknownHostInfo(*this, Arch.c_str(), Platform.c_str(), OS.c_str()); } diff --git a/lib/Driver/HostInfo.cpp b/lib/Driver/HostInfo.cpp index 8db18d4d38..1bee69fd58 100644 --- a/lib/Driver/HostInfo.cpp +++ b/lib/Driver/HostInfo.cpp @@ -273,6 +273,62 @@ ToolChain *FreeBSDHostInfo::getToolChain(const ArgList &Args, return TC; } +// DragonFly Host Info + +/// DragonFlyHostInfo - DragonFly host information implementation. +class DragonFlyHostInfo : public HostInfo { + /// Cache of tool chains we have created. + mutable llvm::StringMap ToolChains; + +public: + DragonFlyHostInfo(const Driver &D, const char *Arch, + const char *Platform, const char *OS); + ~DragonFlyHostInfo(); + + virtual bool useDriverDriver() const; + + virtual types::ID lookupTypeForExtension(const char *Ext) const { + return types::lookupTypeForExtension(Ext); + } + + virtual ToolChain *getToolChain(const ArgList &Args, + const char *ArchName) const; +}; + +DragonFlyHostInfo::DragonFlyHostInfo(const Driver &D, const char *Arch, + const char *Platform, const char *OS) + : HostInfo(D, Arch, Platform, OS) { +} + +DragonFlyHostInfo::~DragonFlyHostInfo() { + for (llvm::StringMap::iterator + it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) + delete it->second; +} + +bool DragonFlyHostInfo::useDriverDriver() const { + return false; +} + +ToolChain *DragonFlyHostInfo::getToolChain(const ArgList &Args, + const char *ArchName) const { + + assert(!ArchName && + "Unexpected arch name on platform without driver driver support."); + + + ArchName = getArchName().c_str(); + + ToolChain *&TC = ToolChains[ArchName]; + + + if (!TC) + TC = new toolchains::DragonFly(*this, ArchName, + getPlatformName().c_str(), + getOSName().c_str()); + return TC; +} + } const HostInfo *clang::driver::createDarwinHostInfo(const Driver &D, @@ -289,6 +345,13 @@ const HostInfo *clang::driver::createFreeBSDHostInfo(const Driver &D, return new FreeBSDHostInfo(D, Arch, Platform, OS); } +const HostInfo *clang::driver::createDragonFlyHostInfo(const Driver &D, + const char *Arch, + const char *Platform, + const char *OS) { + return new DragonFlyHostInfo(D, Arch, Platform, OS); +} + const HostInfo *clang::driver::createUnknownHostInfo(const Driver &D, const char *Arch, const char *Platform, diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 87927f8fb6..73105355f8 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -31,8 +31,7 @@ Darwin_X86::Darwin_X86(const HostInfo &Host, const char *Arch, const char *Platform, const char *OS, const unsigned (&_DarwinVersion)[3], const unsigned (&_GCCVersion)[3]) - : ToolChain(Host, Arch, Platform, OS) -{ + : ToolChain(Host, Arch, Platform, OS) { DarwinVersion[0] = _DarwinVersion[0]; DarwinVersion[1] = _DarwinVersion[1]; DarwinVersion[2] = _DarwinVersion[2]; @@ -422,3 +421,43 @@ Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA) const { return *T; } + +/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly. + +DragonFly::DragonFly(const HostInfo &Host, const char *Arch, + const char *Platform, const char *OS) + : Generic_GCC(Host, Arch, Platform, OS) { + + // Path mangling to find libexec + std::string Path(getHost().getDriver().Dir); + + Path += "/../libexec"; + getProgramPaths().push_back(Path); + getProgramPaths().push_back(getHost().getDriver().Dir); + + getFilePaths().push_back(getHost().getDriver().Dir + "/../lib"); + getFilePaths().push_back("/usr/lib"); + getFilePaths().push_back("/usr/lib/gcc41"); +} + +Tool &DragonFly::SelectTool(const Compilation &C, const JobAction &JA) const { + Action::ActionClass Key; + if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getArchName())) + Key = Action::AnalyzeJobClass; + else + Key = JA.getKind(); + + Tool *&T = Tools[Key]; + if (!T) { + switch (Key) { + case Action::AssembleJobClass: + T = new tools::dragonfly::Assemble(*this); break; + case Action::LinkJobClass: + T = new tools::dragonfly::Link(*this); break; + default: + T = &Generic_GCC::SelectTool(C, JA); + } + } + + return *T; +} diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h index bbb27dc119..baab99bc5c 100644 --- a/lib/Driver/ToolChains.h +++ b/lib/Driver/ToolChains.h @@ -116,6 +116,14 @@ public: virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; }; +class VISIBILITY_HIDDEN DragonFly : public Generic_GCC { +public: + DragonFly(const HostInfo &Host, const char *Arch, const char *Platform, + const char *OS); + + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; +}; + } // end namespace toolchains } // end namespace driver } // end namespace clang diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 83100248db..c8622284fc 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -1826,3 +1826,159 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.MakeArgString(getToolChain().GetProgramPath(C, "ld").c_str()); Dest.addCommand(new Command(Exec, CmdArgs)); } + +/// DragonFly Tools + +// For now, DragonFly Assemble does just about the same as for +// FreeBSD, but this may change soon. +void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA, + Job &Dest, const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + ArgStringList CmdArgs; + + // When building 32-bit code on DragonFly/pc64, we have to explicitly + // instruct as in the base system to assemble 32-bit code. + if (getToolChain().getArchName() == "i386") + CmdArgs.push_back("--32"); + + Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, + options::OPT_Xassembler); + + CmdArgs.push_back("-o"); + if (Output.isPipe()) + CmdArgs.push_back("-"); + else + CmdArgs.push_back(Output.getFilename()); + + for (InputInfoList::const_iterator + it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { + const InputInfo &II = *it; + if (II.isPipe()) + CmdArgs.push_back("-"); + else + CmdArgs.push_back(II.getFilename()); + } + + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath(C, "as").c_str()); + Dest.addCommand(new Command(Exec, CmdArgs)); +} + +void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA, + Job &Dest, const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + ArgStringList CmdArgs; + + if (Args.hasArg(options::OPT_static)) { + CmdArgs.push_back("-Bstatic"); + } else { + if (Args.hasArg(options::OPT_shared)) + CmdArgs.push_back("-Bshareable"); + else { + CmdArgs.push_back("-dynamic-linker"); + CmdArgs.push_back("/usr/libexec/ld-elf.so.2"); + } + } + + // When building 32-bit code on DragonFly/pc64, we have to explicitly + // instruct ld in the base system to link 32-bit code. + if (getToolChain().getArchName() == "i386") { + CmdArgs.push_back("-m"); + CmdArgs.push_back("elf_i386"); + } + + if (Output.isPipe()) { + CmdArgs.push_back("-o"); + CmdArgs.push_back("-"); + } else if (Output.isFilename()) { + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + } else { + assert(Output.isNothing() && "Invalid output."); + } + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nostartfiles)) { + if (!Args.hasArg(options::OPT_shared)) { + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt1.o").c_str())); + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o").c_str())); + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o").c_str())); + } else { + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o").c_str())); + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o").c_str())); + } + } + + Args.AddAllArgs(CmdArgs, options::OPT_L); + Args.AddAllArgs(CmdArgs, options::OPT_T_Group); + Args.AddAllArgs(CmdArgs, options::OPT_e); + + for (InputInfoList::const_iterator + it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { + const InputInfo &II = *it; + if (II.isPipe()) + CmdArgs.push_back("-"); + else if (II.isFilename()) + CmdArgs.push_back(II.getFilename()); + else + II.getInputArg().renderAsInput(Args, CmdArgs); + } + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nodefaultlibs)) { + // FIXME: GCC passes on -lgcc, -lgcc_pic and a whole lot of + // rpaths + CmdArgs.push_back("-L/usr/lib/gcc41"); + + if (!Args.hasArg(options::OPT_static)) { + CmdArgs.push_back("-rpath"); + CmdArgs.push_back("/usr/lib/gcc41"); + + CmdArgs.push_back("-rpath-link"); + CmdArgs.push_back("/usr/lib/gcc41"); + + CmdArgs.push_back("-rpath"); + CmdArgs.push_back("/usr/lib"); + + CmdArgs.push_back("-rpath-link"); + CmdArgs.push_back("/usr/lib"); + } + + if (Args.hasArg(options::OPT_shared)) { + CmdArgs.push_back("-lgcc_pic"); + } else { + CmdArgs.push_back("-lgcc"); + } + + + if (Args.hasArg(options::OPT_pthread)) + CmdArgs.push_back("-lthread_xu"); + + if (!Args.hasArg(options::OPT_nolibc)) { + CmdArgs.push_back("-lc"); + } + + if (Args.hasArg(options::OPT_shared)) { + CmdArgs.push_back("-lgcc_pic"); + } else { + CmdArgs.push_back("-lgcc"); + } + } + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nostartfiles)) { + if (!Args.hasArg(options::OPT_shared)) + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtend.o").c_str())); + else + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o").c_str())); + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtn.o").c_str())); + } + + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath(C, "ld").c_str()); + Dest.addCommand(new Command(Exec, CmdArgs)); +} diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h index 8b66495f30..db108db2b4 100644 --- a/lib/Driver/Tools.h +++ b/lib/Driver/Tools.h @@ -275,6 +275,40 @@ namespace freebsd { }; } + /// dragonfly -- Directly call GNU Binutils assembler and linker +namespace dragonfly { + class VISIBILITY_HIDDEN Assemble : public Tool { + public: + Assemble(const ToolChain &TC) : Tool("dragonfly::Assemble", TC) {} + + virtual bool acceptsPipedInput() const { return true; } + virtual bool canPipeOutput() const { return true; } + virtual bool hasIntegratedCPP() const { return false; } + + virtual void ConstructJob(Compilation &C, const JobAction &JA, + Job &Dest, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &TCArgs, + const char *LinkingOutput) const; + }; + class VISIBILITY_HIDDEN Link : public Tool { + public: + Link(const ToolChain &TC) : Tool("dragonfly::Link", TC) {} + + virtual bool acceptsPipedInput() const { return true; } + virtual bool canPipeOutput() const { return true; } + virtual bool hasIntegratedCPP() const { return false; } + + virtual void ConstructJob(Compilation &C, const JobAction &JA, + Job &Dest, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &TCArgs, + const char *LinkingOutput) const; + }; +} + } // end namespace toolchains } // end namespace driver } // end namespace clang