#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"
#include "llvm/Support/Path.h"
using AIX = clang::driver::toolchains::AIX;
using namespace clang::driver;
using namespace clang::driver::tools;
using namespace clang::driver::toolchains;
using namespace llvm::opt;
using namespace llvm::sys;
void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const ArgList &Args,
const char *LinkingOutput) const {
ArgStringList CmdArgs;
const bool IsArch32Bit = getToolChain().getTriple().isArch32Bit();
const bool IsArch64Bit = getToolChain().getTriple().isArch64Bit();
if (!IsArch32Bit && !IsArch64Bit)
llvm_unreachable("Unsupported bit width value.");
if (IsArch32Bit) {
CmdArgs.push_back("-a32");
} else {
CmdArgs.push_back("-a64");
}
CmdArgs.push_back("-many");
Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
}
if (Inputs.size() != 1)
llvm_unreachable("Invalid number of input files.");
const InputInfo &II = Inputs[0];
assert((II.isFilename() || II.isNothing()) && "Invalid input.");
if (II.isFilename())
CmdArgs.push_back(II.getFilename());
const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
Exec, CmdArgs, Inputs, Output));
}
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());
const Driver &D = ToolChain.getDriver();
ArgStringList CmdArgs;
const bool IsArch32Bit = ToolChain.getTriple().isArch32Bit();
const bool IsArch64Bit = ToolChain.getTriple().isArch64Bit();
if (!(IsArch32Bit || IsArch64Bit))
llvm_unreachable("Unsupported bit width value.");
if (Args.hasArg(options::OPT_static))
CmdArgs.push_back("-bnso");
if (Args.hasArg(options::OPT_shared)) {
CmdArgs.push_back("-bM:SRE");
CmdArgs.push_back("-bnoentry");
}
if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
false) ||
Args.hasFlag(options::OPT_fprofile_generate,
options::OPT_fno_profile_generate, false) ||
Args.hasFlag(options::OPT_fprofile_generate_EQ,
options::OPT_fno_profile_generate, false) ||
Args.hasFlag(options::OPT_fprofile_instr_generate,
options::OPT_fno_profile_instr_generate, false) ||
Args.hasFlag(options::OPT_fprofile_instr_generate_EQ,
options::OPT_fno_profile_instr_generate, false) ||
Args.hasFlag(options::OPT_fcs_profile_generate,
options::OPT_fno_profile_generate, false) ||
Args.hasFlag(options::OPT_fcs_profile_generate_EQ,
options::OPT_fno_profile_generate, false) ||
Args.hasArg(options::OPT_fcreate_profile) ||
Args.hasArg(options::OPT_coverage))
CmdArgs.push_back("-bdbg:namedsects:ss");
assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
if (Output.isFilename()) {
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
}
if (IsArch32Bit) {
CmdArgs.push_back("-b32");
CmdArgs.push_back("-bpT:0x10000000");
CmdArgs.push_back("-bpD:0x20000000");
} else {
CmdArgs.push_back("-b64");
CmdArgs.push_back("-bpT:0x100000000");
CmdArgs.push_back("-bpD:0x110000000");
}
auto getCrt0Basename = [&Args, IsArch32Bit] {
if (Args.hasArg(options::OPT_pg))
return IsArch32Bit ? "gcrt0.o" : "gcrt0_64.o";
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, options::OPT_nostartfiles,
options::OPT_shared)) {
CmdArgs.push_back(
Args.MakeArgString(ToolChain.GetFilePath(getCrt0Basename())));
CmdArgs.push_back(Args.MakeArgString(
ToolChain.GetFilePath(IsArch32Bit ? "crti.o" : "crti_64.o")));
}
CmdArgs.push_back("-bcdtors:all:0:s");
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
Args.AddAllArgs(CmdArgs, options::OPT_L);
ToolChain.AddFilePathLibArgs(Args, CmdArgs);
ToolChain.addProfileRTLibs(Args, CmdArgs);
if (getToolChain().ShouldLinkCXXStdlib(Args))
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
if (Args.hasArg(options::OPT_pthreads, options::OPT_pthread))
CmdArgs.push_back("-lpthreads");
if (D.CCCIsCXX())
CmdArgs.push_back("-lm");
CmdArgs.push_back("-lc");
}
const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
Exec, CmdArgs, Inputs, Output));
}
AIX::AIX(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
: ToolChain(D, Triple, Args) {
ParseInlineAsmUsingAsmParser = Args.hasFlag(
options::OPT_fintegrated_as, options::OPT_fno_integrated_as, true);
getLibraryPaths().push_back(getDriver().SysRoot + "/usr/lib");
}
llvm::StringRef
AIX::GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const {
if (DriverArgs.hasArg(options::OPT_isysroot))
return DriverArgs.getLastArgValue(options::OPT_isysroot);
if (!getDriver().SysRoot.empty())
return getDriver().SysRoot;
return "/";
}
void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdinc))
return;
llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs);
const Driver &D = getDriver();
if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
SmallString<128> P(D.ResourceDir);
path::append(P, "include", "ppc_wrappers");
addSystemInclude(DriverArgs, CC1Args, P);
addSystemInclude(DriverArgs, CC1Args, path::parent_path(P.str()));
}
if (DriverArgs.hasArg(options::OPT_nostdlibinc))
return;
SmallString<128> UP(Sysroot);
path::append(UP, "/usr/include");
addSystemInclude(DriverArgs, CC1Args, UP.str());
}
void AIX::AddClangCXXStdlibIncludeArgs(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
if (DriverArgs.hasArg(options::OPT_nostdinc) ||
DriverArgs.hasArg(options::OPT_nostdincxx) ||
DriverArgs.hasArg(options::OPT_nostdlibinc))
return;
switch (GetCXXStdlibType(DriverArgs)) {
case ToolChain::CST_Libstdcxx:
llvm::report_fatal_error(
"picking up libstdc++ headers is unimplemented on AIX");
case ToolChain::CST_Libcxx: {
llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs);
SmallString<128> PathCPP(Sysroot);
llvm::sys::path::append(PathCPP, "opt/IBM/openxlCSDK", "include", "c++",
"v1");
addSystemInclude(DriverArgs, CC1Args, PathCPP.str());
CC1Args.push_back("-D__LIBC_NO_CPP_MATH_OVERLOADS__");
return;
}
}
llvm_unreachable("Unexpected C++ library type; only libc++ is supported.");
}
void AIX::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const {
switch (GetCXXStdlibType(Args)) {
case ToolChain::CST_Libstdcxx:
llvm::report_fatal_error("linking libstdc++ unimplemented on AIX");
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
if (Args.hasArg(options::OPT_fexperimental_library))
CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
return;
}
llvm_unreachable("Unexpected C++ library type; only libc++ is supported.");
}
ToolChain::CXXStdlibType AIX::GetDefaultCXXStdlibType() const {
return ToolChain::CST_Libcxx;
}
ToolChain::RuntimeLibType AIX::GetDefaultRuntimeLibType() const {
return ToolChain::RLT_CompilerRT;
}
auto AIX::buildAssembler() const -> Tool * { return new aix::Assembler(*this); }
auto AIX::buildLinker() const -> Tool * { return new aix::Linker(*this); }