brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.0 KiB · eac8f62 Raw
347 lines · cpp
1//===--- ZOS.cpp - z/OS 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 "ZOS.h"10#include "clang/Driver/CommonArgs.h"11#include "clang/Driver/Compilation.h"12#include "clang/Options/Options.h"13#include "llvm/Option/ArgList.h"14#include "llvm/Support/VirtualFileSystem.h"15#include "llvm/Support/WithColor.h"16 17using namespace clang;18using namespace clang::driver;19using namespace clang::driver::tools;20using namespace clang::driver::toolchains;21using namespace llvm;22using namespace llvm::opt;23using namespace llvm::sys;24 25ZOS::ZOS(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)26    : ToolChain(D, Triple, Args) {}27 28ZOS::~ZOS() {}29 30void ZOS::addClangTargetOptions(const ArgList &DriverArgs,31                                ArgStringList &CC1Args,32                                Action::OffloadKind DeviceOffloadKind) const {33  // Pass "-faligned-alloc-unavailable" only when the user hasn't manually34  // enabled or disabled aligned allocations.35  if (!DriverArgs.hasArgNoClaim(options::OPT_faligned_allocation,36                                options::OPT_fno_aligned_allocation))37    CC1Args.push_back("-faligned-alloc-unavailable");38 39  if (DriverArgs.hasFlag(options::OPT_fxl_pragma_pack,40                         options::OPT_fno_xl_pragma_pack, true))41    CC1Args.push_back("-fxl-pragma-pack");42 43  // Pass "-fno-sized-deallocation" only when the user hasn't manually enabled44  // or disabled sized deallocations.45  if (!DriverArgs.hasArgNoClaim(options::OPT_fsized_deallocation,46                                options::OPT_fno_sized_deallocation))47    CC1Args.push_back("-fno-sized-deallocation");48}49 50void zos::Assembler::ConstructJob(Compilation &C, const JobAction &JA,51                                  const InputInfo &Output,52                                  const InputInfoList &Inputs,53                                  const ArgList &Args,54                                  const char *LinkingOutput) const {55  ArgStringList CmdArgs;56 57  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);58 59  // Specify assembler output file.60  assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");61  if (Output.isFilename()) {62    CmdArgs.push_back("-o");63    CmdArgs.push_back(Output.getFilename());64  }65 66  // Specify assembler input file.67  // The system assembler on z/OS takes exactly one input file. The driver is68  // expected to invoke as(1) separately for each assembler source input file.69  if (Inputs.size() != 1)70    llvm_unreachable("Invalid number of input files.");71  const InputInfo &II = Inputs[0];72  assert((II.isFilename() || II.isNothing()) && "Invalid input.");73  if (II.isFilename())74    CmdArgs.push_back(II.getFilename());75 76  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));77  C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),78                                         Exec, CmdArgs, Inputs, Output));79}80 81static std::string getLEHLQ(const ArgList &Args) {82  if (Args.hasArg(options::OPT_mzos_hlq_le_EQ)) {83    Arg *LEHLQArg = Args.getLastArg(options::OPT_mzos_hlq_le_EQ);84    StringRef HLQ = LEHLQArg->getValue();85    if (!HLQ.empty())86      return HLQ.str();87  }88  return "CEE";89}90 91static std::string getClangHLQ(const ArgList &Args) {92  if (Args.hasArg(options::OPT_mzos_hlq_clang_EQ)) {93    Arg *ClangHLQArg = Args.getLastArg(options::OPT_mzos_hlq_clang_EQ);94    StringRef HLQ = ClangHLQArg->getValue();95    if (!HLQ.empty())96      return HLQ.str();97  }98  return getLEHLQ(Args);99}100 101static std::string getCSSHLQ(const ArgList &Args) {102  if (Args.hasArg(options::OPT_mzos_hlq_csslib_EQ)) {103    Arg *CsslibHLQArg = Args.getLastArg(options::OPT_mzos_hlq_csslib_EQ);104    StringRef HLQ = CsslibHLQArg->getValue();105    if (!HLQ.empty())106      return HLQ.str();107  }108  return "SYS1";109}110 111void zos::Linker::ConstructJob(Compilation &C, const JobAction &JA,112                               const InputInfo &Output,113                               const InputInfoList &Inputs, const ArgList &Args,114                               const char *LinkingOutput) const {115  const ZOS &ToolChain = static_cast<const ZOS &>(getToolChain());116  ArgStringList CmdArgs;117 118  const bool IsSharedLib =119      Args.hasFlag(options::OPT_shared, options::OPT_static, false);120 121  assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");122  if (Output.isFilename()) {123    CmdArgs.push_back("-o");124    CmdArgs.push_back(Output.getFilename());125  }126 127  SmallString<128> LinkerOptions;128  LinkerOptions = "AMODE=";129  LinkerOptions += "64";130  LinkerOptions += ",LIST";131  LinkerOptions += ",DYNAM=DLL";132  LinkerOptions += ",MSGLEVEL=4";133  LinkerOptions += ",CASE=MIXED";134  LinkerOptions += ",REUS=RENT";135 136  CmdArgs.push_back("-b");137  CmdArgs.push_back(Args.MakeArgString(LinkerOptions));138 139  if (!IsSharedLib) {140    CmdArgs.push_back("-e");141    CmdArgs.push_back("CELQSTRT");142 143    CmdArgs.push_back("-O");144    CmdArgs.push_back("CELQSTRT");145 146    CmdArgs.push_back("-u");147    CmdArgs.push_back("CELQMAIN");148  }149 150  // Generate side file if -shared option is present.151  if (IsSharedLib) {152    StringRef OutputName = Output.getFilename();153    // Strip away the last file suffix in presence from output name and add154    // a new .x suffix.155    SmallString<128> SideDeckName = OutputName;156    llvm::sys::path::replace_extension(SideDeckName, "x");157    CmdArgs.push_back("-x");158    CmdArgs.push_back(Args.MakeArgString(SideDeckName));159  } else {160    // We need to direct side file to /dev/null to suppress linker warning when161    // the object file contains exported symbols, and -shared or162    // -Wl,-x<sidedeck>.x is not specified.163    CmdArgs.push_back("-x");164    CmdArgs.push_back("/dev/null");165  }166 167  // Add archive library search paths.168  Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_u});169 170  ToolChain.AddFilePathLibArgs(Args, CmdArgs);171 172  // Specify linker input file(s)173  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);174 175  //  z/OS tool chain depends on LE data sets and the CSSLIB data set.176  //  These data sets can have different high level qualifiers (HLQs)177  //  as each installation can define them differently.178 179  std::string LEHLQ = getLEHLQ(Args);180  std::string CsslibHLQ = getCSSHLQ(Args);181 182  StringRef ld_env_var = StringRef(getenv("_LD_SYSLIB")).trim();183  if (ld_env_var.empty()) {184    CmdArgs.push_back("-S");185    CmdArgs.push_back(Args.MakeArgString("//'" + LEHLQ + ".SCEEBND2'"));186    CmdArgs.push_back("-S");187    CmdArgs.push_back(Args.MakeArgString("//'" + CsslibHLQ + ".CSSLIB'"));188  }189 190  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {191    ld_env_var = StringRef(getenv("_LD_SIDE_DECKS")).trim();192    if (ld_env_var.empty()) {193      CmdArgs.push_back(194          Args.MakeArgString("//'" + LEHLQ + ".SCEELIB(CELQS001)'"));195      CmdArgs.push_back(196          Args.MakeArgString("//'" + LEHLQ + ".SCEELIB(CELQS003)'"));197    } else {198      SmallVector<StringRef> ld_side_deck;199      ld_env_var.split(ld_side_deck, ":");200      for (StringRef ld_loc : ld_side_deck) {201        CmdArgs.push_back((ld_loc.str()).c_str());202      }203    }204  }205  // Link libc++ library206  if (ToolChain.ShouldLinkCXXStdlib(Args)) {207    ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);208  }209 210  // Specify compiler-rt library path for linker211  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))212    AddRunTimeLibs(ToolChain, ToolChain.getDriver(), CmdArgs, Args);213 214  const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());215  C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),216                                         Exec, CmdArgs, Inputs, Output));217}218 219ToolChain::RuntimeLibType ZOS::GetDefaultRuntimeLibType() const {220  return ToolChain::RLT_CompilerRT;221}222 223ToolChain::CXXStdlibType ZOS::GetDefaultCXXStdlibType() const {224  return ToolChain::CST_Libcxx;225}226 227void ZOS::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,228                              llvm::opt::ArgStringList &CmdArgs) const {229  switch (GetCXXStdlibType(Args)) {230  case ToolChain::CST_Libstdcxx:231    llvm::report_fatal_error("linking libstdc++ is unimplemented on z/OS");232    break;233  case ToolChain::CST_Libcxx: {234    std::string ClangHLQ = getClangHLQ(Args);235    CmdArgs.push_back(236        Args.MakeArgString("//'" + ClangHLQ + ".SCEELIB(CRTDQCXE)'"));237    CmdArgs.push_back(238        Args.MakeArgString("//'" + ClangHLQ + ".SCEELIB(CRTDQCXS)'"));239    CmdArgs.push_back(240        Args.MakeArgString("//'" + ClangHLQ + ".SCEELIB(CRTDQCXP)'"));241    CmdArgs.push_back(242        Args.MakeArgString("//'" + ClangHLQ + ".SCEELIB(CRTDQCXA)'"));243    CmdArgs.push_back(244        Args.MakeArgString("//'" + ClangHLQ + ".SCEELIB(CRTDQXLA)'"));245    CmdArgs.push_back(246        Args.MakeArgString("//'" + ClangHLQ + ".SCEELIB(CRTDQUNW)'"));247  } break;248  }249}250 251auto ZOS::buildAssembler() const -> Tool * { return new zos::Assembler(*this); }252 253auto ZOS::buildLinker() const -> Tool * { return new zos::Linker(*this); }254 255void ZOS::AddClangSystemIncludeArgs(const ArgList &DriverArgs,256                                    ArgStringList &CC1Args) const {257  if (DriverArgs.hasArg(options::OPT_nostdinc))258    return;259 260  const Driver &D = getDriver();261 262  // resolve ResourceDir263  std::string ResourceDir(D.ResourceDir);264 265  // zos_wrappers must take highest precedence266 267  // - <clang>/lib/clang/<ver>/include/zos_wrappers268  if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {269    SmallString<128> P(ResourceDir);270    path::append(P, "include", "zos_wrappers");271    addSystemInclude(DriverArgs, CC1Args, P.str());272 273    // - <clang>/lib/clang/<ver>/include274    SmallString<128> P2(ResourceDir);275    path::append(P2, "include");276    addSystemInclude(DriverArgs, CC1Args, P2.str());277  }278 279  // - /usr/include280  if (Arg *SysIncludeArg =281          DriverArgs.getLastArg(options::OPT_mzos_sys_include_EQ)) {282    StringRef SysInclude = SysIncludeArg->getValue();283 284    // fall back to the default include path285    if (!SysInclude.empty()) {286 287      // -mzos-sys-include opton can have colon separated288      // list of paths, so we need to parse the value.289      StringRef PathLE(SysInclude);290      size_t Colon = PathLE.find(':');291      if (Colon == StringRef::npos) {292        addSystemInclude(DriverArgs, CC1Args, PathLE.str());293        return;294      }295 296      while (Colon != StringRef::npos) {297        SmallString<128> P = PathLE.substr(0, Colon);298        addSystemInclude(DriverArgs, CC1Args, P.str());299        PathLE = PathLE.substr(Colon + 1);300        Colon = PathLE.find(':');301      }302      if (PathLE.size())303        addSystemInclude(DriverArgs, CC1Args, PathLE.str());304 305      return;306    }307  }308 309  addSystemInclude(DriverArgs, CC1Args, "/usr/include");310}311 312void ZOS::TryAddIncludeFromPath(llvm::SmallString<128> Path,313                                const llvm::opt::ArgList &DriverArgs,314                                llvm::opt::ArgStringList &CC1Args) const {315  if (!getVFS().exists(Path)) {316    if (DriverArgs.hasArg(options::OPT_v))317      WithColor::warning(errs(), "Clang")318          << "ignoring nonexistent directory \"" << Path << "\"\n";319    if (!DriverArgs.hasArg(options::OPT__HASH_HASH_HASH))320      return;321  }322  addSystemInclude(DriverArgs, CC1Args, Path);323}324 325void ZOS::AddClangCXXStdlibIncludeArgs(326    const llvm::opt::ArgList &DriverArgs,327    llvm::opt::ArgStringList &CC1Args) const {328  if (DriverArgs.hasArg(options::OPT_nostdinc) ||329      DriverArgs.hasArg(options::OPT_nostdincxx) ||330      DriverArgs.hasArg(options::OPT_nostdlibinc))331    return;332 333  switch (GetCXXStdlibType(DriverArgs)) {334  case ToolChain::CST_Libcxx: {335    // <install>/bin/../include/c++/v1336    llvm::SmallString<128> InstallBin(getDriver().Dir);337    llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1");338    TryAddIncludeFromPath(InstallBin, DriverArgs, CC1Args);339    break;340  }341  case ToolChain::CST_Libstdcxx:342    llvm::report_fatal_error(343        "picking up libstdc++ headers is unimplemented on z/OS");344    break;345  }346}347