Commit bb6a27fc authored by stevewan's avatar stevewan Committed by David Tenty
Browse files

Add AIX toolchain and basic linker functionality

Summary:
This patch adds AIX toolchain infrastructure into driver, and enables AIX
system linker invocation with some basic functionality support

Reviewers: daltenty, hubert.reinterpretcast, jasonliu, Xiangling_L

Reviewed By: jasonliu

Subscribers: Xiangling_L, jasonliu, ormris, wuzish, nemanjai, mgorny, kbarton, jfb, jsji, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D68340
parent 7b3de1e8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ add_clang_library(clangDriver
  ToolChains/Arch/Sparc.cpp
  ToolChains/Arch/SystemZ.cpp
  ToolChains/Arch/X86.cpp
  ToolChains/AIX.cpp
  ToolChains/Ananas.cpp
  ToolChains/AMDGPU.cpp
  ToolChains/AVR.cpp
+4 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@

#include "clang/Driver/Driver.h"
#include "InputInfo.h"
#include "ToolChains/AIX.h"
#include "ToolChains/AMDGPU.h"
#include "ToolChains/AVR.h"
#include "ToolChains/Ananas.h"
@@ -4699,6 +4700,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
  auto &TC = ToolChains[Target.str()];
  if (!TC) {
    switch (Target.getOS()) {
    case llvm::Triple::AIX:
      TC = std::make_unique<toolchains::AIX>(*this, Target, Args);
      break;
    case llvm::Triple::Haiku:
      TC = std::make_unique<toolchains::Haiku>(*this, Target, Args);
      break;
+101 −0
Original line number Diff line number Diff line
//===--- AIX.cpp - AIX ToolChain Implementations ----------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "AIX.h"
#include "Arch/PPC.h"
#include "CommonArgs.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/SanitizerArgs.h"
#include "llvm/Option/ArgList.h"

namespace aix = clang::driver::tools::aix;
using AIX = clang::driver::toolchains::AIX;

using namespace llvm::opt;

void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                               const InputInfo &Output,
                               const InputInfoList &Inputs, const ArgList &Args,
                               const char *LinkingOutput) const {
  const AIX &ToolChain = static_cast<const AIX &>(getToolChain());
  ArgStringList CmdArgs;

  const bool IsArch32Bit = ToolChain.getTriple().isArch32Bit();
  const bool IsArch64Bit = ToolChain.getTriple().isArch64Bit();
  // Only support 32 and 64 bit.
  if (!(IsArch32Bit || IsArch64Bit))
    llvm_unreachable("Unsupported bit width value.");

  // Force static linking when "-static" is present.
  if (Args.hasArg(options::OPT_static))
    CmdArgs.push_back("-bnso");

  // Specify linker output file.
  assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
  if (Output.isFilename()) {
    CmdArgs.push_back("-o");
    CmdArgs.push_back(Output.getFilename());
  } 

  // Set linking mode (i.e., 32/64-bit) and the address of
  // text and data sections based on arch bit width.
  if (IsArch32Bit) {
    CmdArgs.push_back("-b32");
    CmdArgs.push_back("-bpT:0x10000000");
    CmdArgs.push_back("-bpD:0x20000000");
  } else {
    // Must be 64-bit, otherwise asserted already.
    CmdArgs.push_back("-b64");
    CmdArgs.push_back("-bpT:0x100000000");
    CmdArgs.push_back("-bpD:0x110000000");
  }

  auto getCrt0Basename = [&Args, IsArch32Bit] {
    // Enable gprofiling when "-pg" is specified.
    if (Args.hasArg(options::OPT_pg))
      return IsArch32Bit ? "gcrt0.o" : "gcrt0_64.o";
    // Enable profiling when "-p" is specified.
    else if (Args.hasArg(options::OPT_p))
      return IsArch32Bit ? "mcrt0.o" : "mcrt0_64.o";
    else
      return IsArch32Bit ? "crt0.o" : "crt0_64.o";
  };

  if (!Args.hasArg(options::OPT_nostdlib)) {
    CmdArgs.push_back(
        Args.MakeArgString(ToolChain.GetFilePath(getCrt0Basename())));
  }

  // Specify linker input file(s).
  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);

  // Add directory to library search path.
  Args.AddAllArgs(CmdArgs, options::OPT_L);
  ToolChain.AddFilePathLibArgs(Args, CmdArgs);

  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
    // Support POSIX threads if "-pthreads" or "-pthread" is present.
    if (Args.hasArg(options::OPT_pthreads, options::OPT_pthread))
      CmdArgs.push_back("-lpthreads");

    CmdArgs.push_back("-lc");
  }

  const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
  C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
}

/// AIX - AIX tool chain which can call ld(1) directly.
// TODO: Enable direct call to as(1).
AIX::AIX(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
    : ToolChain(D, Triple, Args) {
  getFilePaths().push_back(getDriver().SysRoot + "/usr/lib");
}

auto AIX::buildLinker() const -> Tool * { return new aix::Linker(*this); }
+63 −0
Original line number Diff line number Diff line
//===--- AIX.h - AIX ToolChain Implementations ------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_AIX_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_AIX_H

#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"

namespace clang {
namespace driver {
namespace tools {

/// aix -- Directly call system default linker.
// TODO: Enable direct call to system default assembler.
namespace aix {

class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
public:
  Linker(const ToolChain &TC) : Tool("aix::Linker", "linker", TC) {}

  bool hasIntegratedCPP() const override { return false; }
  bool isLinkJob() const override { return true; }

  void ConstructJob(Compilation &C, const JobAction &JA,
                    const InputInfo &Output, const InputInfoList &Inputs,
                    const llvm::opt::ArgList &TCArgs,
                    const char *LinkingOutput) const override;
};

} // end namespace aix

} // end namespace tools
} // end namespace driver
} // end namespace clang

namespace clang {
namespace driver {
namespace toolchains {

class LLVM_LIBRARY_VISIBILITY AIX : public ToolChain {
public:
  AIX(const Driver &D, const llvm::Triple &Triple,
      const llvm::opt::ArgList &Args);

  bool isPICDefault() const override { return true; }
  bool isPIEDefault() const override { return false; }
  bool isPICDefaultForced() const override { return true; }

protected:
  Tool *buildLinker() const override;
};

} // end namespace toolchains
} // end namespace driver
} // end namespace clang

#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_AIX_H
+0 −0

Empty file added.

Loading