Re: [PATCH] D18360: Add AIX Target/ToolChain to Clang Driver

2016-07-18 Thread Andrew Paprocki via cfe-commits
apaprocki added inline comments.


Comment at: lib/Basic/Targets.cpp:718
@@ +717,3 @@
+Builder.defineMacro("_LONG_LONG");
+Builder.defineMacro("_ALL_SOURCE");
+Builder.defineMacro("_REENTRANT");

majnemer wrote:
> Are we really supposed to define this macro?  Does GCC define this?  I cannot 
> find where it does so in the source.
I defined both `_ALL_SOURCE` and `_REENTRANT` because the `SolarisTargetInfo` 
defines them (`__EXTENSIONS__` is the Solaris equivalent of `_ALL_SOURCE`). If 
that is an oversight in the Solaris work, I'll remove `_ALL_SOURCE` here. GCC 
does not define it by default.


https://reviews.llvm.org/D18360



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18360: Add AIX Target/ToolChain to Clang Driver

2016-07-18 Thread Andrew Paprocki via cfe-commits
apaprocki added inline comments.


Comment at: lib/Basic/Targets.cpp:718
@@ +717,3 @@
+Builder.defineMacro("_LONG_LONG");
+Builder.defineMacro("_ALL_SOURCE");
+Builder.defineMacro("_REENTRANT");

majnemer wrote:
> apaprocki wrote:
> > majnemer wrote:
> > > Are we really supposed to define this macro?  Does GCC define this?  I 
> > > cannot find where it does so in the source.
> > I defined both `_ALL_SOURCE` and `_REENTRANT` because the 
> > `SolarisTargetInfo` defines them (`__EXTENSIONS__` is the Solaris 
> > equivalent of `_ALL_SOURCE`). If that is an oversight in the Solaris work, 
> > I'll remove `_ALL_SOURCE` here. GCC does not define it by default.
> After a closer examination of the gcc sources, it looks like `ALL_SOURCE` is 
> defined if gcc is being used for C++ code (via `CPLUSPLUS_CPP_SPEC`).
> 
> I don't see where `_REENTRANT` is defined for AIX though...
On AIX, when `gcc` is passed `-pthread`, it defines `_THREAD_SAFE`. I think 
this should be changed to

```
if (Opts.POSIXThreads)
  Builder.defineMacro("_THREAD_SAFE");
```

On Solaris, `gcc` defines `_REENTRANT` when `-pthread` is passed. I think it is 
a separate bug (and I can file a separate revision) to put the Solaris use of 
it also on an `Opts.POSIXThreads` check.


https://reviews.llvm.org/D18360



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D18360: Add AIX Target/ToolChain to Clang Driver

2016-07-18 Thread Andrew Paprocki via cfe-commits
apaprocki updated this revision to Diff 64376.

https://reviews.llvm.org/D18360

Files:
  lib/Basic/Targets.cpp
  lib/Driver/Driver.cpp
  lib/Driver/ToolChains.cpp
  lib/Driver/ToolChains.h
  lib/Driver/Tools.cpp
  lib/Driver/Tools.h
  tools/libclang/CIndexer.cpp

Index: tools/libclang/CIndexer.cpp
===
--- tools/libclang/CIndexer.cpp
+++ tools/libclang/CIndexer.cpp
@@ -37,12 +37,71 @@
 
 #ifdef LLVM_ON_WIN32
 #include 
+#elif defined(_AIX)
+#include 
+#include 
+#include 
 #else
 #include 
 #endif
 
 using namespace clang;
 
+#ifdef _AIX
+static int
+test_dir(char ret[PATH_MAX], const char *dir, const char *bin)
+{
+  struct stat sb;
+  char fullpath[PATH_MAX];
+
+  snprintf(fullpath, PATH_MAX, "%s/%s", dir, bin);
+  if (!realpath(fullpath, ret))
+return 1;
+  if (stat(fullpath, &sb) != 0)
+return 1;
+
+  return 0;
+}
+
+static char *
+getprogpath(char ret[PATH_MAX], const char *bin)
+{
+  char *pv, *s, *t;
+
+  /* First approach: absolute path. */
+  if (bin[0] == '/') {
+if (test_dir(ret, "/", bin) == 0)
+  return ret;
+return nullptr;
+  }
+
+  /* Second approach: relative path. */
+  if (strchr(bin, '/')) {
+char cwd[PATH_MAX];
+if (!getcwd(cwd, PATH_MAX))
+  return nullptr;
+if (test_dir(ret, cwd, bin) == 0)
+  return ret;
+return nullptr;
+  }
+
+  /* Third approach: $PATH */
+  if ((pv = getenv("PATH")) == nullptr)
+return nullptr;
+  s = pv = strdup(pv);
+  if (!pv)
+return nullptr;
+  while ((t = strsep(&s, ":")) != nullptr) {
+if (test_dir(ret, t, bin) == 0) {
+  free(pv);
+  return ret;
+}
+  }
+  free(pv);
+  return nullptr;
+}
+#endif
+
 const std::string &CIndexer::getClangResourcesPath() {
   // Did we already compute the path?
   if (!ResourcesPath.empty())
@@ -69,6 +128,11 @@
 #endif
 
   LibClangPath += llvm::sys::path::parent_path(path);
+#elif defined(_AIX)
+  extern char **argv;
+  char exe_path[MAXPATHLEN];
+  if (getprogpath(exe_path, argv[0]) != NULL)
+LibClangPath += llvm::sys::path::parent_path(exe_path);
 #else
   // This silly cast below avoids a C++ warning.
   Dl_info info;
Index: lib/Driver/Tools.h
===
--- lib/Driver/Tools.h
+++ lib/Driver/Tools.h
@@ -652,6 +652,34 @@
 };
 } // end namespace solaris
 
+/// aix -- Directly call AIX assembler and linker
+namespace aix {
+class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
+public:
+  Assembler(const ToolChain &TC) : Tool("aix::Assembler", "assembler", TC) {}
+
+  bool hasIntegratedCPP() const override { return false; }
+
+  void ConstructJob(Compilation &C, const JobAction &JA,
+const InputInfo &Output, const InputInfoList &Inputs,
+const llvm::opt::ArgList &TCArgs,
+const char *LinkingOutput) const override;
+};
+
+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
+
 /// dragonfly -- Directly call GNU Binutils assembler and linker
 namespace dragonfly {
 class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
Index: lib/Driver/Tools.cpp
===
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -5452,6 +5452,7 @@
   options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit,
   !IsWindowsCygnus && !IsWindowsGNU &&
   getToolChain().getTriple().getOS() != llvm::Triple::Solaris &&
+  getToolChain().getTriple().getOS() != llvm::Triple::AIX &&
   getToolChain().getArch() != llvm::Triple::hexagon &&
   getToolChain().getArch() != llvm::Triple::xcore &&
   ((getToolChain().getTriple().getVendor() !=
@@ -8102,6 +8103,94 @@
   C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs));
 }
 
+void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
+  const InputInfo &Output,
+  const InputInfoList &Inputs,
+  const ArgList &Args,
+  const char *LinkingOutput) const {
+  claimNoWarnArgs(Args);
+  ArgStringList CmdArgs;
+
+  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
+
+  CmdArgs.push_back("-o");
+  CmdArgs.push_back(Output.getFilename());
+
+  for (const auto &II : Inputs)
+CmdArgs.push_back(II.getFilename());
+
+  const char *Exec = Args.MakeArgString(getToolChain().GetProgramPat

Re: [PATCH] D18360: Add AIX Target/ToolChain to Clang Driver

2016-07-19 Thread Andrew Paprocki via cfe-commits
apaprocki updated this revision to Diff 64518.
apaprocki added a comment.

Increased context and removed accidental inclusion of Solaris change.


https://reviews.llvm.org/D18360

Files:
  lib/Basic/Targets.cpp
  lib/Driver/Driver.cpp
  lib/Driver/ToolChains.cpp
  lib/Driver/ToolChains.h
  lib/Driver/Tools.cpp
  lib/Driver/Tools.h
  tools/libclang/CIndexer.cpp

Index: tools/libclang/CIndexer.cpp
===
--- tools/libclang/CIndexer.cpp
+++ tools/libclang/CIndexer.cpp
@@ -37,12 +37,71 @@
 
 #ifdef LLVM_ON_WIN32
 #include 
+#elif defined(_AIX)
+#include 
+#include 
+#include 
 #else
 #include 
 #endif
 
 using namespace clang;
 
+#ifdef _AIX
+static int
+test_dir(char ret[PATH_MAX], const char *dir, const char *bin)
+{
+  struct stat sb;
+  char fullpath[PATH_MAX];
+
+  snprintf(fullpath, PATH_MAX, "%s/%s", dir, bin);
+  if (!realpath(fullpath, ret))
+return 1;
+  if (stat(fullpath, &sb) != 0)
+return 1;
+
+  return 0;
+}
+
+static char *
+getprogpath(char ret[PATH_MAX], const char *bin)
+{
+  char *pv, *s, *t;
+
+  /* First approach: absolute path. */
+  if (bin[0] == '/') {
+if (test_dir(ret, "/", bin) == 0)
+  return ret;
+return nullptr;
+  }
+
+  /* Second approach: relative path. */
+  if (strchr(bin, '/')) {
+char cwd[PATH_MAX];
+if (!getcwd(cwd, PATH_MAX))
+  return nullptr;
+if (test_dir(ret, cwd, bin) == 0)
+  return ret;
+return nullptr;
+  }
+
+  /* Third approach: $PATH */
+  if ((pv = getenv("PATH")) == nullptr)
+return nullptr;
+  s = pv = strdup(pv);
+  if (!pv)
+return nullptr;
+  while ((t = strsep(&s, ":")) != nullptr) {
+if (test_dir(ret, t, bin) == 0) {
+  free(pv);
+  return ret;
+}
+  }
+  free(pv);
+  return nullptr;
+}
+#endif
+
 const std::string &CIndexer::getClangResourcesPath() {
   // Did we already compute the path?
   if (!ResourcesPath.empty())
@@ -69,6 +128,11 @@
 #endif
 
   LibClangPath += llvm::sys::path::parent_path(path);
+#elif defined(_AIX)
+  extern char **argv;
+  char exe_path[MAXPATHLEN];
+  if (getprogpath(exe_path, argv[0]) != NULL)
+LibClangPath += llvm::sys::path::parent_path(exe_path);
 #else
   // This silly cast below avoids a C++ warning.
   Dl_info info;
Index: lib/Driver/Tools.h
===
--- lib/Driver/Tools.h
+++ lib/Driver/Tools.h
@@ -652,6 +652,34 @@
 };
 } // end namespace solaris
 
+/// aix -- Directly call AIX assembler and linker
+namespace aix {
+class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
+public:
+  Assembler(const ToolChain &TC) : Tool("aix::Assembler", "assembler", TC) {}
+
+  bool hasIntegratedCPP() const override { return false; }
+
+  void ConstructJob(Compilation &C, const JobAction &JA,
+const InputInfo &Output, const InputInfoList &Inputs,
+const llvm::opt::ArgList &TCArgs,
+const char *LinkingOutput) const override;
+};
+
+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
+
 /// dragonfly -- Directly call GNU Binutils assembler and linker
 namespace dragonfly {
 class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
Index: lib/Driver/Tools.cpp
===
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -5452,6 +5452,7 @@
   options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit,
   !IsWindowsCygnus && !IsWindowsGNU &&
   getToolChain().getTriple().getOS() != llvm::Triple::Solaris &&
+  getToolChain().getTriple().getOS() != llvm::Triple::AIX &&
   getToolChain().getArch() != llvm::Triple::hexagon &&
   getToolChain().getArch() != llvm::Triple::xcore &&
   ((getToolChain().getTriple().getVendor() !=
@@ -8102,6 +8103,94 @@
   C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs));
 }
 
+void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
+  const InputInfo &Output,
+  const InputInfoList &Inputs,
+  const ArgList &Args,
+  const char *LinkingOutput) const {
+  claimNoWarnArgs(Args);
+  ArgStringList CmdArgs;
+
+  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
+
+  CmdArgs.push_back("-o");
+  CmdArgs.push_back(Output.getFilename());
+
+  for (const auto &II : Inputs)
+CmdArgs.p

Re: [PATCH] D18360: Add AIX Target/ToolChain to Clang Driver

2016-07-18 Thread Andrew Paprocki via cfe-commits
apaprocki updated this revision to Diff 64328.
apaprocki added a comment.

Fixed `wchar_t` type.


https://reviews.llvm.org/D18360

Files:
  lib/Basic/Targets.cpp
  lib/Driver/Driver.cpp
  lib/Driver/ToolChains.cpp
  lib/Driver/ToolChains.h
  lib/Driver/Tools.cpp
  lib/Driver/Tools.h
  tools/libclang/CIndexer.cpp

Index: tools/libclang/CIndexer.cpp
===
--- tools/libclang/CIndexer.cpp
+++ tools/libclang/CIndexer.cpp
@@ -37,12 +37,71 @@
 
 #ifdef LLVM_ON_WIN32
 #include 
+#elif defined(_AIX)
+#include 
+#include 
+#include 
 #else
 #include 
 #endif
 
 using namespace clang;
 
+#ifdef _AIX
+static int
+test_dir(char ret[PATH_MAX], const char *dir, const char *bin)
+{
+  struct stat sb;
+  char fullpath[PATH_MAX];
+
+  snprintf(fullpath, PATH_MAX, "%s/%s", dir, bin);
+  if (!realpath(fullpath, ret))
+return 1;
+  if (stat(fullpath, &sb) != 0)
+return 1;
+
+  return 0;
+}
+
+static char *
+getprogpath(char ret[PATH_MAX], const char *bin)
+{
+  char *pv, *s, *t;
+
+  /* First approach: absolute path. */
+  if (bin[0] == '/') {
+if (test_dir(ret, "/", bin) == 0)
+  return ret;
+return nullptr;
+  }
+
+  /* Second approach: relative path. */
+  if (strchr(bin, '/')) {
+char cwd[PATH_MAX];
+if (!getcwd(cwd, PATH_MAX))
+  return nullptr;
+if (test_dir(ret, cwd, bin) == 0)
+  return ret;
+return nullptr;
+  }
+
+  /* Third approach: $PATH */
+  if ((pv = getenv("PATH")) == nullptr)
+return nullptr;
+  s = pv = strdup(pv);
+  if (!pv)
+return nullptr;
+  while ((t = strsep(&s, ":")) != nullptr) {
+if (test_dir(ret, t, bin) == 0) {
+  free(pv);
+  return ret;
+}
+  }
+  free(pv);
+  return nullptr;
+}
+#endif
+
 const std::string &CIndexer::getClangResourcesPath() {
   // Did we already compute the path?
   if (!ResourcesPath.empty())
@@ -69,6 +128,11 @@
 #endif
 
   LibClangPath += llvm::sys::path::parent_path(path);
+#elif defined(_AIX)
+  extern char **argv;
+  char exe_path[MAXPATHLEN];
+  if (getprogpath(exe_path, argv[0]) != NULL)
+LibClangPath += llvm::sys::path::parent_path(exe_path);
 #else
   // This silly cast below avoids a C++ warning.
   Dl_info info;
Index: lib/Driver/Tools.h
===
--- lib/Driver/Tools.h
+++ lib/Driver/Tools.h
@@ -652,6 +652,34 @@
 };
 } // end namespace solaris
 
+/// aix -- Directly call AIX assembler and linker
+namespace aix {
+class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
+public:
+  Assembler(const ToolChain &TC) : Tool("aix::Assembler", "assembler", TC) {}
+
+  bool hasIntegratedCPP() const override { return false; }
+
+  void ConstructJob(Compilation &C, const JobAction &JA,
+const InputInfo &Output, const InputInfoList &Inputs,
+const llvm::opt::ArgList &TCArgs,
+const char *LinkingOutput) const override;
+};
+
+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
+
 /// dragonfly -- Directly call GNU Binutils assembler and linker
 namespace dragonfly {
 class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
Index: lib/Driver/Tools.cpp
===
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -5452,6 +5452,7 @@
   options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit,
   !IsWindowsCygnus && !IsWindowsGNU &&
   getToolChain().getTriple().getOS() != llvm::Triple::Solaris &&
+  getToolChain().getTriple().getOS() != llvm::Triple::AIX &&
   getToolChain().getArch() != llvm::Triple::hexagon &&
   getToolChain().getArch() != llvm::Triple::xcore &&
   ((getToolChain().getTriple().getVendor() !=
@@ -8102,6 +8103,94 @@
   C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs, Inputs));
 }
 
+void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
+  const InputInfo &Output,
+  const InputInfoList &Inputs,
+  const ArgList &Args,
+  const char *LinkingOutput) const {
+  claimNoWarnArgs(Args);
+  ArgStringList CmdArgs;
+
+  Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
+
+  CmdArgs.push_back("-o");
+  CmdArgs.push_back(Output.getFilename());
+
+  for (const auto &II : Inputs)
+CmdArgs.push_back(II.getFilename());
+
+  const char *Exe

Re: [PATCH] D18360: Add AIX Target/ToolChain to Clang Driver

2016-07-18 Thread Andrew Paprocki via cfe-commits
apaprocki added a comment.

(I also re-based the patch on top of `trunk`)


https://reviews.llvm.org/D18360



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D18360: Add AIX Target/ToolChain to Clang Driver

2016-03-22 Thread Andrew Paprocki via cfe-commits
apaprocki created this revision.
apaprocki added a subscriber: cfe-commits.

This patch adds Clang driver support for the AIX platform.  This allows Clang 
to be used for compiling code / checking for errors, but does not allow for 
building executables, as AIX uses XCOFF and not ELF.

After applying this patch and the underlying D18359:

```
$ clang -v
clang version 3.8.0 (tags/RELEASE_380/final)
Target: powerpc-ibm-aix7.1.0.0
Thread model: posix
InstalledDir: /tmp/llvm-3.8/bin
Found candidate GCC installation: 
/tmp/gcc-4.8/lib/gcc/powerpc-ibm-aix7.1.0.0/4.8.5
Selected GCC installation: /tmp/gcc-4.8/lib/gcc/powerpc-ibm-aix7.1.0.0/4.8.5
Candidate multilib: .;@maix32
Candidate multilib: ppc64;@maix64
Selected multilib: .;@maix32
```

http://reviews.llvm.org/D18360

Files:
  lib/Basic/Targets.cpp
  lib/Driver/Driver.cpp
  lib/Driver/ToolChains.cpp
  lib/Driver/ToolChains.h
  lib/Driver/Tools.cpp
  lib/Driver/Tools.h
  tools/libclang/CIndexer.cpp

Index: lib/Driver/ToolChains.h
===
--- lib/Driver/ToolChains.h
+++ lib/Driver/ToolChains.h
@@ -643,6 +643,24 @@
   Tool *buildLinker() const override;
 };
 
+class LLVM_LIBRARY_VISIBILITY AIX : public Generic_GCC {
+public:
+  AIX(const Driver &D, const llvm::Triple &Triple,
+  const llvm::opt::ArgList &Args);
+
+  bool IsIntegratedAssemblerDefault() const override { return true; }
+
+  void AddClangCXXStdlibIncludeArgs(
+  const llvm::opt::ArgList &DriverArgs,
+  llvm::opt::ArgStringList &CC1Args) const override;
+
+  unsigned GetDefaultDwarfVersion() const override { return 2; }
+
+protected:
+  Tool *buildAssembler() const override;
+  Tool *buildLinker() const override;
+};
+
 class LLVM_LIBRARY_VISIBILITY MinGW : public ToolChain {
 public:
   MinGW(const Driver &D, const llvm::Triple &Triple,
Index: lib/Driver/Tools.h
===
--- lib/Driver/Tools.h
+++ lib/Driver/Tools.h
@@ -649,6 +649,34 @@
 };
 } // end namespace solaris
 
+/// aix -- Directly call AIX assembler and linker
+namespace aix {
+class LLVM_LIBRARY_VISIBILITY Assembler : public Tool {
+public:
+  Assembler(const ToolChain &TC) : Tool("aix::Assembler", "assembler", TC) {}
+
+  bool hasIntegratedCPP() const override { return false; }
+
+  void ConstructJob(Compilation &C, const JobAction &JA,
+const InputInfo &Output, const InputInfoList &Inputs,
+const llvm::opt::ArgList &TCArgs,
+const char *LinkingOutput) const override;
+};
+
+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
+
 /// dragonfly -- Directly call GNU Binutils assembler and linker
 namespace dragonfly {
 class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool {
Index: lib/Driver/ToolChains.cpp
===
--- lib/Driver/ToolChains.cpp
+++ lib/Driver/ToolChains.cpp
@@ -1719,13 +1719,14 @@
 // Filter to remove Multilibs that don't exist as a suffix to Path
 class FilterNonExistent {
   StringRef Base;
+  StringRef Crt;
   vfs::FileSystem &VFS;
 
 public:
-  FilterNonExistent(StringRef Base, vfs::FileSystem &VFS)
-  : Base(Base), VFS(VFS) {}
+  FilterNonExistent(StringRef Base, StringRef Crt, vfs::FileSystem &VFS)
+  : Base(Base), Crt(Crt), VFS(VFS) {}
   bool operator()(const Multilib &M) {
-return !VFS.exists(Base + M.gccSuffix() + "/crtbegin.o");
+return !VFS.exists(Base + M.gccSuffix() + Crt);
   }
 };
 } // end anonymous namespace
@@ -1811,7 +1812,7 @@
   // /usr
   //   /lib  <= crt*.o files compiled with '-mips32'
 
-  FilterNonExistent NonExistent(Path, D.getVFS());
+  FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
 
   // Check for FSF toolchain multilibs
   MultilibSet FSFMipsMultilibs;
@@ -2112,6 +2113,40 @@
   return false;
 }
 
+static bool findAIXBiarchMultilibs(const Driver &D,
+   const llvm::Triple &TargetTriple,
+   StringRef Path, const ArgList &Args,
+   bool NeedsBiarchSuffix,
+   DetectedMultilibs &Result) {
+  Multilib Default = Multilib()
+   .flag("+maix32")
+   .flag("-maix64");
+  Multilib Alt64 = Multilib()
+   .gccSuffix("/ppc64")
+   .includeSuffix("/ppc64")
+   .flag("-maix32")
+   .flag("+maix64");
+
+