From f7b8eec37c8c8012fa525c71fb29a58c9f29beef Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Mon, 29 Jun 2009 20:52:51 +0000 Subject: [PATCH] OpenBSD support. - Patch by Jonathan Gray! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74453 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Driver/HostInfo.h | 2 + lib/Basic/Targets.cpp | 46 +++++++++++++ lib/Driver/Driver.cpp | 2 + lib/Driver/HostInfo.cpp | 57 ++++++++++++++++ lib/Driver/ToolChains.cpp | 30 +++++++++ lib/Driver/ToolChains.h | 7 ++ lib/Driver/Tools.cpp | 112 ++++++++++++++++++++++++++++++++ lib/Driver/Tools.h | 34 ++++++++++ test/Driver/openbsd.c | 6 ++ 9 files changed, 296 insertions(+) create mode 100644 test/Driver/openbsd.c diff --git a/include/clang/Driver/HostInfo.h b/include/clang/Driver/HostInfo.h index 3485f5fbfd..b5e80b0c3b 100644 --- a/include/clang/Driver/HostInfo.h +++ b/include/clang/Driver/HostInfo.h @@ -69,6 +69,8 @@ public: const HostInfo *createDarwinHostInfo(const Driver &D, const llvm::Triple& Triple); +const HostInfo *createOpenBSDHostInfo(const Driver &D, + const llvm::Triple& Triple); const HostInfo *createFreeBSDHostInfo(const Driver &D, const llvm::Triple& Triple); const HostInfo *createDragonFlyHostInfo(const Driver &D, diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 9ca014d4ff..e156e2abd2 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -70,6 +70,19 @@ static void getSolarisDefines(const LangOptions &Opts, std::vector &Defs) Define(Defs, "__SVR4"); } +static void getOpenBSDDefines(const LangOptions &Opts, bool is64Bit, + const char *Triple, std::vector &Defs) { + // OpenBSD defines; list based off of gcc output + + Define(Defs, "__OpenBSD__", "1"); + Define(Defs, "__KPRINTF_ATTRIBUTE__"); + DefineStd(Defs, "unix", Opts); + Define(Defs, "__ELF__", "1"); + if (is64Bit) { + Define(Defs, "__LP64__"); + } +} + static void getFreeBSDDefines(const LangOptions &Opts, bool is64Bit, const char *Triple, std::vector &Defs) { // FreeBSD defines; list based off of gcc output @@ -865,6 +878,20 @@ public: }; } // end anonymous namespace +namespace { +// x86-32 OpenBSD target +class OpenBSDX86_32TargetInfo : public X86_32TargetInfo { +public: + OpenBSDX86_32TargetInfo(const std::string& triple) : + X86_32TargetInfo(triple) { } + virtual void getTargetDefines(const LangOptions &Opts, + std::vector &Defines) const { + X86_32TargetInfo::getTargetDefines(Opts, Defines); + getOpenBSDDefines(Opts, 0, getTargetTriple(), Defines); + } +}; +} // end anonymous namespace + namespace { // x86-32 FreeBSD target class FreeBSDX86_32TargetInfo : public X86_32TargetInfo { @@ -986,6 +1013,20 @@ public: }; } // end anonymous namespace +namespace { +// x86-64 OpenBSD target +class OpenBSDX86_64TargetInfo : public X86_64TargetInfo { +public: + OpenBSDX86_64TargetInfo(const std::string &triple) + : X86_64TargetInfo(triple) {} + virtual void getTargetDefines(const LangOptions &Opts, + std::vector &Defines) const { + X86_64TargetInfo::getTargetDefines(Opts, Defines); + getOpenBSDDefines(Opts, 1, getTargetTriple(), Defines); + } +}; +} // end anonymous namespace + namespace { // x86-64 FreeBSD target class FreeBSDX86_64TargetInfo : public X86_64TargetInfo { @@ -1457,6 +1498,7 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) { // Additions and corrections are welcome. bool isDarwin = T.find("-darwin") != std::string::npos; bool isDragonFly = T.find("-dragonfly") != std::string::npos; + bool isOpenBSD = T.find("-openbsd") != std::string::npos; bool isFreeBSD = T.find("-freebsd") != std::string::npos; bool isSolaris = T.find("-solaris") != std::string::npos; bool isLinux = T.find("-linux") != std::string::npos; @@ -1495,6 +1537,8 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) { return new DarwinX86_64TargetInfo(T); if (isLinux) return new LinuxX86_64TargetInfo(T); + if (isOpenBSD) + return new OpenBSDX86_64TargetInfo(T); if (isFreeBSD) return new FreeBSDX86_64TargetInfo(T); if (isSolaris) @@ -1515,6 +1559,8 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) { return new LinuxX86_32TargetInfo(T); if (isDragonFly) return new DragonFlyX86_32TargetInfo(T); + if (isOpenBSD) + return new OpenBSDX86_32TargetInfo(T); if (isFreeBSD) return new FreeBSDX86_32TargetInfo(T); if (isSolaris) diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 76a5c8b2c1..2e90accf34 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -1205,6 +1205,8 @@ const HostInfo *Driver::GetHostInfo(const char *TripleStr) const { return createDarwinHostInfo(*this, Triple); case llvm::Triple::DragonFly: return createDragonFlyHostInfo(*this, Triple); + case llvm::Triple::OpenBSD: + return createOpenBSDHostInfo(*this, Triple); case llvm::Triple::FreeBSD: return createFreeBSDHostInfo(*this, Triple); case llvm::Triple::Linux: diff --git a/lib/Driver/HostInfo.cpp b/lib/Driver/HostInfo.cpp index 831e11b98e..602a977135 100644 --- a/lib/Driver/HostInfo.cpp +++ b/lib/Driver/HostInfo.cpp @@ -234,6 +234,57 @@ ToolChain *UnknownHostInfo::getToolChain(const ArgList &Args, return TC; } +// OpenBSD Host Info + +/// OpenBSDHostInfo - OpenBSD host information implementation. +class OpenBSDHostInfo : public HostInfo { + /// Cache of tool chains we have created. + mutable llvm::StringMap ToolChains; + +public: + OpenBSDHostInfo(const Driver &D, const llvm::Triple& Triple) + : HostInfo(D, Triple) {} + ~OpenBSDHostInfo(); + + 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; +}; + +OpenBSDHostInfo::~OpenBSDHostInfo() { + for (llvm::StringMap::iterator + it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) + delete it->second; +} + +bool OpenBSDHostInfo::useDriverDriver() const { + return false; +} + +ToolChain *OpenBSDHostInfo::getToolChain(const ArgList &Args, + const char *ArchName) const { + assert(!ArchName && + "Unexpected arch name on platform without driver driver support."); + + std::string Arch = getArchName(); + ArchName = Arch.c_str(); + + ToolChain *&TC = ToolChains[ArchName]; + if (!TC) { + llvm::Triple TCTriple(getTriple()); + TCTriple.setArchName(ArchName); + + TC = new toolchains::OpenBSD(*this, TCTriple); + } + + return TC; +} + // FreeBSD Host Info /// FreeBSDHostInfo - FreeBSD host information implementation. @@ -416,6 +467,12 @@ clang::driver::createDarwinHostInfo(const Driver &D, return new DarwinHostInfo(D, Triple); } +const HostInfo * +clang::driver::createOpenBSDHostInfo(const Driver &D, + const llvm::Triple& Triple) { + return new OpenBSDHostInfo(D, Triple); +} + const HostInfo * clang::driver::createFreeBSDHostInfo(const Driver &D, const llvm::Triple& Triple) { diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 436d343dd0..f663ed4953 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -384,6 +384,36 @@ DerivedArgList *Generic_GCC::TranslateArgs(InputArgList &Args) const { return new DerivedArgList(Args, true); } +/// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly. + +OpenBSD::OpenBSD(const HostInfo &Host, const llvm::Triple& Triple) + : Generic_GCC(Host, Triple) { + getFilePaths().push_back(getHost().getDriver().Dir + "/../lib"); + getFilePaths().push_back("/usr/lib"); +} + +Tool &OpenBSD::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::openbsd::Assemble(*this); break; + case Action::LinkJobClass: + T = new tools::openbsd::Link(*this); break; + default: + T = &Generic_GCC::SelectTool(C, JA); + } + } + + return *T; +} + /// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly. FreeBSD::FreeBSD(const HostInfo &Host, const llvm::Triple& Triple, bool Lib32) diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h index 3ecd1715da..c921d52864 100644 --- a/lib/Driver/ToolChains.h +++ b/lib/Driver/ToolChains.h @@ -107,6 +107,13 @@ public: virtual const char *GetDefaultRelocationModel() const { return "pic"; } }; +class VISIBILITY_HIDDEN OpenBSD : public Generic_GCC { +public: + OpenBSD(const HostInfo &Host, const llvm::Triple& Triple); + + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; +}; + class VISIBILITY_HIDDEN FreeBSD : public Generic_GCC { public: FreeBSD(const HostInfo &Host, const llvm::Triple& Triple, bool Lib32); diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index ac07906c8f..aaec0b4c8a 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -1759,6 +1759,118 @@ void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA, Dest.addCommand(new Command(Exec, CmdArgs)); } +void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, + Job &Dest, const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const +{ + ArgStringList CmdArgs; + + 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 openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, + Job &Dest, const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + const Driver &D = getToolChain().getHost().getDriver(); + ArgStringList CmdArgs; + + if (Args.hasArg(options::OPT_static)) { + CmdArgs.push_back("-Bstatic"); + } else { + CmdArgs.push_back("--eh-frame-hdr"); + if (Args.hasArg(options::OPT_shared)) { + CmdArgs.push_back("-Bshareable"); + } else { + CmdArgs.push_back("-dynamic-linker"); + CmdArgs.push_back("/usr/libexec/ld.so"); + } + } + + 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, "crt0.o").c_str())); + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o").c_str())); + } else { + 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; + + // Don't try to pass LLVM inputs to a generic gcc. + if (II.getType() == types::TY_LLVMBC) + D.Diag(clang::diag::err_drv_no_linker_llvm_support) + << getToolChain().getTripleString().c_str(); + + 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)) { + + if (Args.hasArg(options::OPT_pthread)) + CmdArgs.push_back("-pthread"); + CmdArgs.push_back("-lc"); + } + + 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())); + } + + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath(C, "ld").c_str()); + Dest.addCommand(new Command(Exec, CmdArgs)); +} void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, Job &Dest, const InputInfo &Output, diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h index db108db2b4..ab73496009 100644 --- a/lib/Driver/Tools.h +++ b/lib/Driver/Tools.h @@ -241,6 +241,40 @@ namespace darwin { }; } + /// openbsd -- Directly call GNU Binutils assembler and linker +namespace openbsd { + class VISIBILITY_HIDDEN Assemble : public Tool { + public: + Assemble(const ToolChain &TC) : Tool("openbsd::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("openbsd::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; + }; +} + /// freebsd -- Directly call GNU Binutils assembler and linker namespace freebsd { class VISIBILITY_HIDDEN Assemble : public Tool { diff --git a/test/Driver/openbsd.c b/test/Driver/openbsd.c new file mode 100644 index 0000000000..fd0d4fa21c --- /dev/null +++ b/test/Driver/openbsd.c @@ -0,0 +1,6 @@ +// RUN: clang -ccc-clang-archs "" -ccc-host-triple i686-pc-openbsd %s -### 2> %t.log && +// RUN: grep 'clang-cc" "-triple" "i386-pc-openbsd"' %t.log && +// RUN: grep 'as" "-o" ".*\.o" ".*\.s' %t.log && +// RUN: grep 'ld" "--eh-frame-hdr" "-dynamic-linker" ".*ld.so" "-o" "a\.out" ".*crt0.o" ".*crtbegin.o" ".*\.o" "-lc" ".*crtend.o"' %t.log && +// RUN: true + -- 2.40.0