diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -30,6 +30,7 @@ ToolChains/Arch/Sparc.cpp ToolChains/Arch/SystemZ.cpp ToolChains/Arch/X86.cpp + ToolChains/AIX.cpp ToolChains/Ananas.cpp ToolChains/AMDGPU.cpp ToolChains/AVR.cpp diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -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 @@ auto &TC = ToolChains[Target.str()]; if (!TC) { switch (Target.getOS()) { + case llvm::Triple::AIX: + TC = std::make_unique(*this, Target, Args); + break; case llvm::Triple::Haiku: TC = std::make_unique(*this, Target, Args); break; diff --git a/clang/lib/Driver/ToolChains/AIX.h b/clang/lib/Driver/ToolChains/AIX.h new file mode 100644 --- /dev/null +++ b/clang/lib/Driver/ToolChains/AIX.h @@ -0,0 +1,63 @@ +//===--- 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 diff --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp new file mode 100644 --- /dev/null +++ b/clang/lib/Driver/ToolChains/AIX.cpp @@ -0,0 +1,101 @@ +//===--- 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(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(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); } diff --git a/clang/test/Driver/Inputs/aix_ppc_tree/powerpc-ibm-aix7.1.0.0/dummy.a b/clang/test/Driver/Inputs/aix_ppc_tree/powerpc-ibm-aix7.1.0.0/dummy.a new file mode 100644 diff --git a/clang/test/Driver/Inputs/aix_ppc_tree/usr/lib/crt0.o b/clang/test/Driver/Inputs/aix_ppc_tree/usr/lib/crt0.o new file mode 100644 diff --git a/clang/test/Driver/Inputs/aix_ppc_tree/usr/lib/crt0_64.o b/clang/test/Driver/Inputs/aix_ppc_tree/usr/lib/crt0_64.o new file mode 100644 diff --git a/clang/test/Driver/Inputs/aix_ppc_tree/usr/lib/crti.o b/clang/test/Driver/Inputs/aix_ppc_tree/usr/lib/crti.o new file mode 100644 diff --git a/clang/test/Driver/Inputs/aix_ppc_tree/usr/lib/crti_64.o b/clang/test/Driver/Inputs/aix_ppc_tree/usr/lib/crti_64.o new file mode 100644 diff --git a/clang/test/Driver/Inputs/aix_ppc_tree/usr/lib/gcrt0.o b/clang/test/Driver/Inputs/aix_ppc_tree/usr/lib/gcrt0.o new file mode 100644 diff --git a/clang/test/Driver/Inputs/aix_ppc_tree/usr/lib/gcrt0_64.o b/clang/test/Driver/Inputs/aix_ppc_tree/usr/lib/gcrt0_64.o new file mode 100644 diff --git a/clang/test/Driver/Inputs/aix_ppc_tree/usr/lib/mcrt0.o b/clang/test/Driver/Inputs/aix_ppc_tree/usr/lib/mcrt0.o new file mode 100644 diff --git a/clang/test/Driver/Inputs/aix_ppc_tree/usr/lib/mcrt0_64.o b/clang/test/Driver/Inputs/aix_ppc_tree/usr/lib/mcrt0_64.o new file mode 100644 diff --git a/clang/test/Driver/aix-ld.c b/clang/test/Driver/aix-ld.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/aix-ld.c @@ -0,0 +1,177 @@ +// General tests that ld invocations on AIX targets are sane. Note that we use +// sysroot to make these tests independent of the host system. + +// Check powerpc-ibm-aix7.1.0.0, 32-bit. +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target powerpc-ibm-aix7.1.0.0 \ +// RUN: --sysroot %S/Inputs/aix_ppc_tree \ +// RUN: | FileCheck --check-prefix=CHECK-LD32 %s +// CHECK-LD32-NOT: warning: +// CHECK-LD32: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "powerpc-ibm-aix7.1.0.0" +// CHECK-LD32: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-LD32: "{{.*}}ld{{(.exe)?}}" +// CHECK-LD32-NOT: "-bnso" +// CHECK-LD32: "-b32" +// CHECK-LD32: "-bpT:0x10000000" "-bpD:0x20000000" +// CHECK-LD32: "[[SYSROOT]]/usr/lib{{/|\\\\}}crt0.o" +// CHECK-LD32: "-L[[SYSROOT]]/usr/lib" +// CHECK-LD32: "-lc" + +// Check powerpc64-ibm-aix7.1.0.0, 64-bit. +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target powerpc64-ibm-aix7.1.0.0 \ +// RUN: --sysroot %S/Inputs/aix_ppc_tree \ +// RUN: | FileCheck --check-prefix=CHECK-LD64 %s +// CHECK-LD64-NOT: warning: +// CHECK-LD64: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "powerpc64-ibm-aix7.1.0.0" +// CHECK-LD64: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-LD64: "{{.*}}ld{{(.exe)?}}" +// CHECK-LD64-NOT: "-bnso" +// CHECK-LD64: "-b64" +// CHECK-LD64: "-bpT:0x100000000" "-bpD:0x110000000" +// CHECK-LD64: "[[SYSROOT]]/usr/lib{{/|\\\\}}crt0_64.o" +// CHECK-LD64: "-L[[SYSROOT]]/usr/lib" +// CHECK-LD64: "-lc" + +// Check powerpc-ibm-aix7.1.0.0, 32-bit. Enable POSIX thread support. +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -pthread \ +// RUN: -target powerpc-ibm-aix7.1.0.0 \ +// RUN: --sysroot %S/Inputs/aix_ppc_tree \ +// RUN: | FileCheck --check-prefix=CHECK-LD32-PTHREAD %s +// CHECK-LD32-PTHREAD-NOT: warning: +// CHECK-LD32-PTHREAD: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "powerpc-ibm-aix7.1.0.0" +// CHECK-LD32-PTHREAD: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-LD32-PTHREAD: "{{.*}}ld{{(.exe)?}}" +// CHECK-LD32-PTHREAD-NOT: "-bnso" +// CHECK-LD32-PTHREAD: "-b32" +// CHECK-LD32-PTHREAD: "-bpT:0x10000000" "-bpD:0x20000000" +// CHECK-LD32-PTHREAD: "[[SYSROOT]]/usr/lib{{/|\\\\}}crt0.o" +// CHECK-LD32-PTHREAD: "-L[[SYSROOT]]/usr/lib" +// CHECK-LD32-PTHREAD: "-lpthreads" +// CHECK-LD32-PTHREAD: "-lc" + +// Check powerpc-ibm-aix7.1.0.0, 64-bit. POSIX thread alias. +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -pthreads \ +// RUN: -target powerpc64-ibm-aix7.1.0.0 \ +// RUN: --sysroot %S/Inputs/aix_ppc_tree \ +// RUN: | FileCheck --check-prefix=CHECK-LD64-PTHREAD %s +// CHECK-LD64-PTHREAD-NOT: warning: +// CHECK-LD64-PTHREAD: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "powerpc64-ibm-aix7.1.0.0" +// CHECK-LD64-PTHREAD: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-LD64-PTHREAD: "{{.*}}ld{{(.exe)?}}" +// CHECK-LD64-PTHREAD-NOT: "-bnso" +// CHECK-LD64-PTHREAD: "-b64" +// CHECK-LD64-PTHREAD: "-bpT:0x100000000" "-bpD:0x110000000" +// CHECK-LD64-PTHREAD: "[[SYSROOT]]/usr/lib{{/|\\\\}}crt0_64.o" +// CHECK-LD64-PTHREAD: "-L[[SYSROOT]]/usr/lib" +// CHECK-LD64-PTHREAD: "-lpthreads" +// CHECK-LD64-PTHREAD: "-lc" + +// Check powerpc-ibm-aix7.1.0.0, 32-bit. Enable profiling. +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -p \ +// RUN: -target powerpc-ibm-aix7.1.0.0 \ +// RUN: --sysroot %S/Inputs/aix_ppc_tree \ +// RUN: | FileCheck --check-prefix=CHECK-LD32-PROF %s +// CHECK-LD32-PROF-NOT: warning: +// CHECK-LD32-PROF: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "powerpc-ibm-aix7.1.0.0" +// CHECK-LD32-PROF: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-LD32-PROF: "{{.*}}ld{{(.exe)?}}" +// CHECK-LD32-PROF-NOT: "-bnso" +// CHECK-LD32-PROF: "-b32" +// CHECK-LD32-PROF: "-bpT:0x10000000" "-bpD:0x20000000" +// CHECK-LD32-PROF: "[[SYSROOT]]/usr/lib{{/|\\\\}}mcrt0.o" +// CHECK-LD32-PROF: "-L[[SYSROOT]]/usr/lib" +// CHECK-LD32-PROF: "-lc" + +// Check powerpc64-ibm-aix7.1.0.0, 64-bit. Enable g-profiling. +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -pg \ +// RUN: -target powerpc64-ibm-aix7.1.0.0 \ +// RUN: --sysroot %S/Inputs/aix_ppc_tree \ +// RUN: | FileCheck --check-prefix=CHECK-LD64-GPROF %s +// CHECK-LD64-GPROF-NOT: warning: +// CHECK-LD64-GPROF: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "powerpc64-ibm-aix7.1.0.0" +// CHECK-LD64-GPROF: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-LD64-GPROF: "{{.*}}ld{{(.exe)?}}" +// CHECK-LD64-GPROF-NOT: "-bnso" +// CHECK-LD64-GPROF: "-b64" +// CHECK-LD64-GPROF: "-bpT:0x100000000" "-bpD:0x110000000" +// CHECK-LD64-GPROF: "[[SYSROOT]]/usr/lib{{/|\\\\}}gcrt0_64.o" +// CHECK-LD64-GPROF: "-L[[SYSROOT]]/usr/lib" +// CHECK-LD64-GPROF: "-lc" + +// Check powerpc-ibm-aix7.1.0.0, 32-bit. Static linking. +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -static \ +// RUN: -target powerpc-ibm-aix7.1.0.0 \ +// RUN: --sysroot %S/Inputs/aix_ppc_tree \ +// RUN: | FileCheck --check-prefix=CHECK-LD32-STATIC %s +// CHECK-LD32-STATIC-NOT: warning: +// CHECK-LD32-STATIC: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "powerpc-ibm-aix7.1.0.0" +// CHECK-LD32-STATIC: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-LD32-STATIC: "{{.*}}ld{{(.exe)?}}" +// CHECK-LD32-STATIC: "-bnso" +// CHECK-LD32-STATIC: "-b32" +// CHECK-LD32-STATIC: "-bpT:0x10000000" "-bpD:0x20000000" +// CHECK-LD32-STATIC: "[[SYSROOT]]/usr/lib{{/|\\\\}}crt0.o" +// CHECK-LD32-STATIC: "-L[[SYSROOT]]/usr/lib" +// CHECK-LD32-STATIC: "-lc" + +// Check powerpc-ibm-aix7.1.0.0, 32-bit. Library search path. +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -L%S/Inputs/aix_ppc_tree/powerpc-ibm-aix7.1.0.0 \ +// RUN: -target powerpc-ibm-aix7.1.0.0 \ +// RUN: --sysroot %S/Inputs/aix_ppc_tree \ +// RUN: | FileCheck --check-prefix=CHECK-LD32-LIBP %s +// CHECK-LD32-LIBP-NOT: warning: +// CHECK-LD32-LIBP: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "powerpc-ibm-aix7.1.0.0" +// CHECK-LD32-LIBP: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-LD32-LIBP: "{{.*}}ld{{(.exe)?}}" +// CHECK-LD32-LIBP-NOT: "-bnso" +// CHECK-LD32-LIBP: "-b32" +// CHECK-LD32-LIBP: "-bpT:0x10000000" "-bpD:0x20000000" +// CHECK-LD32-LIBP: "[[SYSROOT]]/usr/lib{{/|\\\\}}crt0.o" +// CHECK-LD32-LIBP: "-L[[SYSROOT]]/powerpc-ibm-aix7.1.0.0" +// CHECK-LD32-LIBP: "-L[[SYSROOT]]/usr/lib" +// CHECK-LD32-LIBP: "-lc" + +// Check powerpc-ibm-aix7.1.0.0, 32-bit. nostdlib. +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -nostdlib \ +// RUN: -pthread \ +// RUN: -target powerpc-ibm-aix7.1.0.0 \ +// RUN: --sysroot %S/Inputs/aix_ppc_tree \ +// RUN: | FileCheck --check-prefix=CHECK-LD32-NO-STD-LIB %s +// CHECK-LD32-NO-STD-LIB-NOT: warning: +// CHECK-LD32-NO-STD-LIB: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "powerpc-ibm-aix7.1.0.0" +// CHECK-LD32-NO-STD-LIB: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-LD32-NO-STD-LIB: "{{.*}}ld{{(.exe)?}}" +// CHECK-LD32-NO-STD-LIB-NOT: "-bnso" +// CHECK-LD32-NO-STD-LIB: "-b32" +// CHECK-LD32-NO-STD-LIB: "-bpT:0x10000000" "-bpD:0x20000000" +// CHECK-LD32-NO-STD-LIB-NOT: "[[SYSROOT]]/usr/lib{{/|\\\\}}crt0.o" +// CHECK-LD32-NO-STD-LIB: "-L[[SYSROOT]]/usr/lib" +// CHECK-LD32-NO-STD-LIB-NOT: "-lpthreads" +// CHECK-LD32-NO-STD-LIB-NOT: "-lc" + +// Check powerpc-ibm-aix7.1.0.0, 64-bit. nodefaultlibs. +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -nodefaultlibs \ +// RUN: -pthread \ +// RUN: -target powerpc64-ibm-aix7.1.0.0 \ +// RUN: --sysroot %S/Inputs/aix_ppc_tree \ +// RUN: | FileCheck --check-prefix=CHECK-LD64-NO-DEFAULT-LIBS %s +// CHECK-LD64-NO-DEFAULT-LIBS-NOT: warning: +// CHECK-LD64-NO-DEFAULT-LIBS: {{.*}}clang{{(.exe)?}}" "-cc1" "-triple" "powerpc64-ibm-aix7.1.0.0" +// CHECK-LD64-NO-DEFAULT-LIBS: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-LD64-NO-DEFAULT-LIBS: "{{.*}}ld{{(.exe)?}}" +// CHECK-LD64-NO-DEFAULT-LIBS-NOT: "-bnso" +// CHECK-LD64-NO-DEFAULT-LIBS: "-b64" +// CHECK-LD64-NO-DEFAULT-LIBS: "-bpT:0x100000000" "-bpD:0x110000000" +// CHECK-LD64-NO-DEFAULT-LIBS: "[[SYSROOT]]/usr/lib{{/|\\\\}}crt0_64.o" +// CHECK-LD64-NO-DEFAULT-LIBS: "-L[[SYSROOT]]/usr/lib" +// CHECK-LD64-NO-DEFAULT-LIBS-NOT: "-lpthreads" +// CHECK-LD64-NO-DEFAULT-LIBS-NOT: "-lc"