MSP430.cpp revision 343173
124269Speter//===--- MSP430.cpp - MSP430 Helpers for Tools ------------------*- C++ -*-===//
224269Speter//
324269Speter//                     The LLVM Compiler Infrastructure
424269Speter//
528345Sdyson// This file is distributed under the University of Illinois Open Source
628345Sdyson// License. See LICENSE.TXT for details.
728345Sdyson//
824269Speter//===----------------------------------------------------------------------===//
924269Speter
1024269Speter#include "MSP430.h"
1124269Speter#include "CommonArgs.h"
1224269Speter#include "Gnu.h"
1324269Speter#include "InputInfo.h"
1424269Speter#include "clang/Driver/Compilation.h"
1524269Speter#include "clang/Driver/Multilib.h"
1624269Speter#include "clang/Driver/Options.h"
1724269Speter#include "llvm/Option/ArgList.h"
1824269Speter#include "llvm/Support/FileSystem.h"
1924269Speter#include "llvm/Support/Path.h"
2024269Speter
2124269Speterusing namespace clang::driver;
2224269Speterusing namespace clang::driver::toolchains;
2324269Speterusing namespace clang::driver::tools;
2424269Speterusing namespace clang;
2524269Speterusing namespace llvm::opt;
2624269Speter
2724269Speterstatic bool isSupportedMCU(const StringRef MCU) {
2824269Speter  return llvm::StringSwitch<bool>(MCU)
2924269Speter#define MSP430_MCU(NAME) .Case(NAME, true)
3024269Speter#include "clang/Basic/MSP430Target.def"
3124269Speter      .Default(false);
3224269Speter}
3324269Speter
3424269Speterstatic StringRef getSupportedHWMult(const Arg *MCU) {
3524269Speter  if (!MCU)
3624269Speter    return "none";
3724269Speter
3824269Speter  return llvm::StringSwitch<StringRef>(MCU->getValue())
3924269Speter#define MSP430_MCU_FEAT(NAME, HWMULT) .Case(NAME, HWMULT)
4024269Speter#include "clang/Basic/MSP430Target.def"
4124269Speter      .Default("none");
4224269Speter}
43116182Sobrien
44116182Sobrienstatic StringRef getHWMultLib(const ArgList &Args) {
45116182Sobrien  StringRef HWMult = Args.getLastArgValue(options::OPT_mhwmult_EQ, "auto");
4624269Speter  if (HWMult == "auto") {
4767046Sjasone    HWMult = getSupportedHWMult(Args.getLastArg(options::OPT_mmcu_EQ));
4884812Sjhb  }
4924269Speter
50102477Sbde  return llvm::StringSwitch<StringRef>(HWMult)
5167353Sjhb      .Case("16bit", "-lmul_16")
52102477Sbde      .Case("32bit", "-lmul_32")
5324273Speter      .Case("f5series", "-lmul_f5")
5424269Speter      .Default("-lmul_none");
5524269Speter}
5624269Speter
5724269Spetervoid msp430::getMSP430TargetFeatures(const Driver &D, const ArgList &Args,
5824269Speter                                     std::vector<StringRef> &Features) {
5924269Speter  const Arg *MCU = Args.getLastArg(options::OPT_mmcu_EQ);
6028345Sdyson  if (MCU && !isSupportedMCU(MCU->getValue())) {
6128345Sdyson    D.Diag(diag::err_drv_clang_unsupported) << MCU->getValue();
6224269Speter    return;
6328345Sdyson  }
6428345Sdyson
6528345Sdyson  const Arg *HWMultArg = Args.getLastArg(options::OPT_mhwmult_EQ);
6635242Sbde  if (!MCU && !HWMultArg)
6728345Sdyson    return;
6824269Speter
6929653Sdyson  StringRef HWMult = HWMultArg ? HWMultArg->getValue() : "auto";
7029653Sdyson  StringRef SupportedHWMult = getSupportedHWMult(MCU);
7129653Sdyson
7267046Sjasone  if (HWMult == "auto") {
7367046Sjasone    // 'auto' - deduce hw multiplier support based on mcu name provided.
7467046Sjasone    // If no mcu name is provided, assume no hw multiplier is supported.
7567046Sjasone    if (!MCU)
7667046Sjasone      D.Diag(clang::diag::warn_drv_msp430_hwmult_no_device);
7771320Sjasone    HWMult = SupportedHWMult;
7867046Sjasone  }
79107414Smckusick
8029653Sdyson  if (HWMult == "none") {
8129653Sdyson    // 'none' - disable hw multiplier.
8224269Speter    Features.push_back("-hwmult16");
8367046Sjasone    Features.push_back("-hwmult32");
8467046Sjasone    Features.push_back("-hwmultf5");
8567046Sjasone    return;
86117660Struckman  }
8767046Sjasone
88117660Struckman  if (MCU && SupportedHWMult == "none")
8967046Sjasone    D.Diag(clang::diag::warn_drv_msp430_hwmult_unsupported) << HWMult;
9028345Sdyson  if (MCU && HWMult != SupportedHWMult)
9128345Sdyson    D.Diag(clang::diag::warn_drv_msp430_hwmult_mismatch)
9228345Sdyson        << SupportedHWMult << HWMult;
9328345Sdyson
9428345Sdyson  if (HWMult == "16bit") {
9524269Speter    // '16bit' - for 16-bit only hw multiplier.
9628345Sdyson    Features.push_back("+hwmult16");
9728345Sdyson  } else if (HWMult == "32bit") {
9842453Seivind    // '32bit' - for 16/32-bit hw multiplier.
9942408Seivind    Features.push_back("+hwmult32");
10024269Speter  } else if (HWMult == "f5series") {
10134194Sdyson    // 'f5series' - for 16/32-bit hw multiplier supported by F5 series mcus.
10228345Sdyson    Features.push_back("+hwmultf5");
10334194Sdyson  } else {
10434194Sdyson    D.Diag(clang::diag::err_drv_unsupported_option_argument)
10534194Sdyson        << HWMultArg->getAsString(Args) << HWMult;
10634194Sdyson  }
10734194Sdyson}
10834194Sdyson
10934194Sdyson/// MSP430 Toolchain
11028345SdysonMSP430ToolChain::MSP430ToolChain(const Driver &D, const llvm::Triple &Triple,
11128345Sdyson                                 const ArgList &Args)
11229653Sdyson    : Generic_ELF(D, Triple, Args) {
11371576Sjasone
11429653Sdyson  StringRef MultilibSuf = "";
11528345Sdyson
11653090Salc  GCCInstallation.init(Triple, Args);
11753090Salc  if (GCCInstallation.isValid()) {
11853090Salc    MultilibSuf = GCCInstallation.getMultilib().gccSuffix();
11953090Salc
12053090Salc    SmallString<128> GCCBinPath;
12153090Salc    llvm::sys::path::append(GCCBinPath,
12253090Salc                            GCCInstallation.getParentLibPath(), "..", "bin");
12353090Salc    addPathIfExists(D, GCCBinPath, getProgramPaths());
12453090Salc
12553090Salc    SmallString<128> GCCRtPath;
12672200Sbmilekic    llvm::sys::path::append(GCCRtPath,
12753090Salc                            GCCInstallation.getInstallPath(), MultilibSuf);
12853090Salc    addPathIfExists(D, GCCRtPath, getFilePaths());
12953090Salc  }
13072200Sbmilekic
13128345Sdyson  SmallString<128> SysRootDir(computeSysRoot());
13228345Sdyson  llvm::sys::path::append(SysRootDir, "lib", MultilibSuf);
13324269Speter  addPathIfExists(D, SysRootDir, getFilePaths());
13453090Salc}
13528345Sdyson
13628345Sdysonstd::string MSP430ToolChain::computeSysRoot() const {
13724269Speter  if (!getDriver().SysRoot.empty())
13828345Sdyson    return getDriver().SysRoot;
139107414Smckusick
140107414Smckusick  SmallString<128> Dir;
14134194Sdyson  if (GCCInstallation.isValid())
14228345Sdyson    llvm::sys::path::append(Dir, GCCInstallation.getParentLibPath(), "..",
143112106Sjhb                            GCCInstallation.getTriple().str());
144132587Srwatson  else
14566615Sjasone    llvm::sys::path::append(Dir, getDriver().Dir, "..", getTriple().str());
14666615Sjasone
14728345Sdyson  return Dir.str();
14828345Sdyson}
14928345Sdyson
15028345Sdysonvoid MSP430ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
15129653Sdyson                                                ArgStringList &CC1Args) const {
15229653Sdyson  if (DriverArgs.hasArg(options::OPT_nostdinc) ||
15329653Sdyson      DriverArgs.hasArg(options::OPT_nostdlibinc))
15429653Sdyson    return;
15529653Sdyson
15628345Sdyson  SmallString<128> Dir(computeSysRoot());
15734194Sdyson  llvm::sys::path::append(Dir, "include");
15828345Sdyson  addSystemInclude(DriverArgs, CC1Args, Dir.str());
15928345Sdyson}
16028345Sdyson
16169432Sjakevoid MSP430ToolChain::addClangTargetOptions(const ArgList &DriverArgs,
16288318Sdillon                                            ArgStringList &CC1Args,
16388318Sdillon                                            Action::OffloadKind) const {
16434194Sdyson  CC1Args.push_back("-nostdsysteminc");
16528345Sdyson
16634194Sdyson  const auto *MCUArg = DriverArgs.getLastArg(options::OPT_mmcu_EQ);
16734194Sdyson  if (!MCUArg)
16834194Sdyson    return;
16934194Sdyson
17034194Sdyson  const StringRef MCU = MCUArg->getValue();
17134194Sdyson  if (MCU.startswith("msp430i")) {
17228345Sdyson    // 'i' should be in lower case as it's defined in TI MSP430-GCC headers
17334194Sdyson    CC1Args.push_back(DriverArgs.MakeArgString(
17428345Sdyson        "-D__MSP430i" + MCU.drop_front(7).upper() + "__"));
17534194Sdyson  } else {
17628345Sdyson    CC1Args.push_back(DriverArgs.MakeArgString("-D__" + MCU.upper() + "__"));
17728345Sdyson  }
178107414Smckusick}
179107414Smckusick
180107414SmckusickTool *MSP430ToolChain::buildLinker() const {
181107414Smckusick  return new tools::msp430::Linker(*this);
182107414Smckusick}
183107414Smckusick
184107414Smckusickvoid msp430::Linker::ConstructJob(Compilation &C, const JobAction &JA,
18528345Sdyson                                  const InputInfo &Output,
18634194Sdyson                                  const InputInfoList &Inputs,
18728345Sdyson                                  const ArgList &Args,
18828345Sdyson                                  const char *LinkingOutput) const {
18928345Sdyson  const ToolChain &ToolChain = getToolChain();
19024269Speter  const Driver &D = ToolChain.getDriver();
19124269Speter  std::string Linker = ToolChain.GetProgramPath(getShortName());
19224269Speter  ArgStringList CmdArgs;
19324269Speter
19424269Speter  if (!D.SysRoot.empty())
19524269Speter    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
19624269Speter
19724269Speter  Args.AddAllArgs(CmdArgs, options::OPT_L);
19842900Seivind  ToolChain.AddFilePathLibArgs(Args, CmdArgs);
19983366Sjulian
20042900Seivind  if (!Args.hasArg(options::OPT_T)) {
20183366Sjulian    if (const Arg *MCUArg = Args.getLastArg(options::OPT_mmcu_EQ))
20242900Seivind      CmdArgs.push_back(
20327894Sfsmp          Args.MakeArgString("-T" + StringRef(MCUArg->getValue()) + ".ld"));
20424269Speter  } else {
20566615Sjasone    Args.AddAllArgs(CmdArgs, options::OPT_T);
20683366Sjulian  }
20742900Seivind
20842900Seivind  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
20942900Seivind    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
21042900Seivind    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbegin.o")));
21142900Seivind  }
21224269Speter
21324269Speter  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA);
214110414Sjulian
21572227Sjhb  CmdArgs.push_back("--start-group");
21624269Speter  CmdArgs.push_back(Args.MakeArgString(getHWMultLib(Args)));
217112106Sjhb  CmdArgs.push_back("-lgcc");
21866615Sjasone  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
21983366Sjulian    CmdArgs.push_back("-lc");
22066615Sjasone    CmdArgs.push_back("-lcrt");
22124269Speter    CmdArgs.push_back("-lnosys");
22283366Sjulian  }
223110414Sjulian  CmdArgs.push_back("--end-group");
22428393Sdyson
225110414Sjulian  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
22628345Sdyson    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o")));
227111463Sjeff    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
228111463Sjeff  }
22975740Salfred  CmdArgs.push_back("-o");
23076100Salfred  CmdArgs.push_back(Output.getFilename());
23172200Sbmilekic  C.addCommand(llvm::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
23275740Salfred                                          CmdArgs, Inputs));
23328345Sdyson}
234111463Sjeff