251 lines · cpp
1//===--- DragonFly.cpp - DragonFly ToolChain Implementations ----*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "DragonFly.h"10#include "clang/Driver/CommonArgs.h"11#include "clang/Driver/Compilation.h"12#include "clang/Driver/Driver.h"13#include "clang/Options/Options.h"14#include "llvm/Option/ArgList.h"15#include "llvm/Support/Path.h"16 17using namespace clang::driver;18using namespace clang::driver::tools;19using namespace clang::driver::toolchains;20using namespace clang;21using namespace llvm::opt;22 23void dragonfly::Assembler::ConstructJob(Compilation &C, const JobAction &JA,24 const InputInfo &Output,25 const InputInfoList &Inputs,26 const ArgList &Args,27 const char *LinkingOutput) const {28 const auto &ToolChain = static_cast<const DragonFly &>(getToolChain());29 ArgStringList CmdArgs;30 31 claimNoWarnArgs(Args);32 33 // When building 32-bit code on DragonFly/pc64, we have to explicitly34 // instruct as in the base system to assemble 32-bit code.35 if (ToolChain.getArch() == llvm::Triple::x86)36 CmdArgs.push_back("--32");37 38 Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);39 40 CmdArgs.push_back("-o");41 CmdArgs.push_back(Output.getFilename());42 43 for (const auto &II : Inputs)44 CmdArgs.push_back(II.getFilename());45 46 const char *Exec = Args.MakeArgString(ToolChain.GetProgramPath("as"));47 C.addCommand(std::make_unique<Command>(JA, *this,48 ResponseFileSupport::AtFileCurCP(),49 Exec, CmdArgs, Inputs, Output));50}51 52void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,53 const InputInfo &Output,54 const InputInfoList &Inputs,55 const ArgList &Args,56 const char *LinkingOutput) const {57 const auto &ToolChain = static_cast<const DragonFly &>(getToolChain());58 const Driver &D = ToolChain.getDriver();59 const llvm::Triple::ArchType Arch = ToolChain.getArch();60 const bool Static = Args.hasArg(options::OPT_static);61 const bool Shared = Args.hasArg(options::OPT_shared);62 const bool Profiling = Args.hasArg(options::OPT_pg);63 const bool Pie = Args.hasArg(options::OPT_pie);64 ArgStringList CmdArgs;65 66 if (!D.SysRoot.empty())67 CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));68 69 CmdArgs.push_back("--eh-frame-hdr");70 if (Static) {71 CmdArgs.push_back("-Bstatic");72 } else {73 if (Args.hasArg(options::OPT_rdynamic))74 CmdArgs.push_back("-export-dynamic");75 if (Shared)76 CmdArgs.push_back("-shared");77 else if (!Args.hasArg(options::OPT_r)) {78 CmdArgs.push_back("-dynamic-linker");79 CmdArgs.push_back("/usr/libexec/ld-elf.so.2");80 }81 CmdArgs.push_back("--hash-style=gnu");82 CmdArgs.push_back("--enable-new-dtags");83 }84 85 // When building 32-bit code on DragonFly/pc64, we have to explicitly86 // instruct ld in the base system to link 32-bit code.87 if (Arch == llvm::Triple::x86) {88 CmdArgs.push_back("-m");89 CmdArgs.push_back("elf_i386");90 }91 92 assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");93 if (Output.isFilename()) {94 CmdArgs.push_back("-o");95 CmdArgs.push_back(Output.getFilename());96 }97 98 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,99 options::OPT_r)) {100 const char *crt1 = nullptr;101 const char *crtbegin = nullptr;102 if (!Shared) {103 if (Profiling)104 crt1 = "gcrt1.o";105 else {106 if (Pie)107 crt1 = "Scrt1.o";108 else109 crt1 = "crt1.o";110 }111 }112 113 if (Shared || Pie)114 crtbegin = "crtbeginS.o";115 else116 crtbegin = "crtbegin.o";117 118 if (crt1)119 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crt1)));120 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));121 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));122 }123 124 Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,125 options::OPT_s, options::OPT_t});126 ToolChain.AddFilePathLibArgs(Args, CmdArgs);127 128 AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);129 130 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs,131 options::OPT_r)) {132 if (!Static) {133 CmdArgs.push_back("-rpath");134 CmdArgs.push_back("/usr/lib/gcc80");135 }136 137 // Use the static OpenMP runtime with -static-openmp138 bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Static;139 addOpenMPRuntime(C, CmdArgs, ToolChain, Args, StaticOpenMP);140 141 if (D.CCCIsCXX()) {142 if (ToolChain.ShouldLinkCXXStdlib(Args))143 ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);144 CmdArgs.push_back("-lm");145 }146 147 // Silence warnings when linking C code with a C++ '-stdlib' argument.148 Args.ClaimAllArgs(options::OPT_stdlib_EQ);149 150 // Additional linker set-up and flags for Fortran. This is required in order151 // to generate executables. As Fortran runtime depends on the C runtime,152 // these dependencies need to be listed before the C runtime below (i.e.153 // AddRunTimeLibs).154 if (D.IsFlangMode() &&155 !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {156 ToolChain.addFortranRuntimeLibraryPath(Args, CmdArgs);157 ToolChain.addFortranRuntimeLibs(Args, CmdArgs);158 CmdArgs.push_back("-lm");159 }160 161 if (Args.hasArg(options::OPT_pthread))162 CmdArgs.push_back("-lpthread");163 164 if (!Args.hasArg(options::OPT_nolibc))165 CmdArgs.push_back("-lc");166 167 if (Static || Args.hasArg(options::OPT_static_libgcc)) {168 CmdArgs.push_back("-lgcc");169 CmdArgs.push_back("-lgcc_eh");170 } else {171 if (Args.hasArg(options::OPT_shared_libgcc)) {172 CmdArgs.push_back("-lgcc_pic");173 if (!Shared)174 CmdArgs.push_back("-lgcc");175 } else {176 CmdArgs.push_back("-lgcc");177 CmdArgs.push_back("--as-needed");178 CmdArgs.push_back("-lgcc_pic");179 CmdArgs.push_back("--no-as-needed");180 }181 }182 }183 184 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,185 options::OPT_r)) {186 const char *crtend = nullptr;187 if (Shared || Pie)188 crtend ="crtendS.o";189 else190 crtend = "crtend.o";191 192 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));193 CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));194 }195 196 ToolChain.addProfileRTLibs(Args, CmdArgs);197 198 const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());199 C.addCommand(std::make_unique<Command>(JA, *this,200 ResponseFileSupport::AtFileCurCP(),201 Exec, CmdArgs, Inputs, Output));202}203 204/// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly.205 206DragonFly::DragonFly(const Driver &D, const llvm::Triple &Triple,207 const ArgList &Args)208 : Generic_ELF(D, Triple, Args) {209 // Path mangling to find libexec210 getProgramPaths().push_back(getDriver().Dir);211 212 getFilePaths().push_back(getDriver().Dir + "/../lib");213 getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib"));214 getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib/gcc80"));215}216 217void DragonFly::AddClangSystemIncludeArgs(218 const llvm::opt::ArgList &DriverArgs,219 llvm::opt::ArgStringList &CC1Args) const {220 const Driver &D = getDriver();221 222 if (DriverArgs.hasArg(options::OPT_nostdinc))223 return;224 225 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {226 SmallString<128> Dir(D.ResourceDir);227 llvm::sys::path::append(Dir, "include");228 addSystemInclude(DriverArgs, CC1Args, Dir.str());229 }230 231 if (DriverArgs.hasArg(options::OPT_nostdlibinc))232 return;233 234 addExternCSystemInclude(DriverArgs, CC1Args,235 concat(D.SysRoot, "/usr/include"));236}237 238void DragonFly::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,239 llvm::opt::ArgStringList &CC1Args) const {240 addLibStdCXXIncludePaths(concat(getDriver().SysRoot, "/usr/include/c++/8.0"), "", "",241 DriverArgs, CC1Args);242}243 244Tool *DragonFly::buildAssembler() const {245 return new tools::dragonfly::Assembler(*this);246}247 248Tool *DragonFly::buildLinker() const {249 return new tools::dragonfly::Linker(*this);250}251