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 <windows.h>
+#elif defined(_AIX)
+#include <sys/param.h>
+#include <stdio.h>
+#include <unistd.h>
 #else
 #include <dlfcn.h>
 #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<Command>(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().GetProgramPath("as"));
+  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+}
+
+void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+                               const InputInfo &Output,
+                               const InputInfoList &Inputs,
+                               const ArgList &Args,
+                               const char *LinkingOutput) const {
+  ArgStringList CmdArgs;
+
+  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_shared)) {
+    CmdArgs.push_back("-e_start");
+  }
+
+  CmdArgs.push_back("-bsvr4");
+
+  if (Args.hasArg(options::OPT_static)) {
+    CmdArgs.push_back("-dn");
+  } else {
+    CmdArgs.push_back("-dy");
+    if (Args.hasArg(options::OPT_shared)) {
+      CmdArgs.push_back("-G");
+    } else {
+      CmdArgs.push_back("-brtl");
+    }
+  }
+
+  if (Output.isFilename()) {
+    CmdArgs.push_back("-o");
+    CmdArgs.push_back(Output.getFilename());
+  } else {
+    assert(Output.isNothing() && "Invalid output.");
+  }
+
+  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
+    if (Args.hasArg(options::OPT_shared))
+      CmdArgs.push_back(
+          Args.MakeArgString(getToolChain().GetFilePath("crtcxa_s.o")));
+    else
+      CmdArgs.push_back(
+          Args.MakeArgString(getToolChain().GetFilePath("crtcxa.o")));
+  }
+
+  getToolChain().AddFilePathLibArgs(Args, CmdArgs);
+
+  Args.AddAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
+                            options::OPT_e, options::OPT_r});
+
+  AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
+
+  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+    if (getToolChain().getDriver().CCCIsCXX())
+      getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
+    CmdArgs.push_back("-lc");
+    if (!Args.hasArg(options::OPT_shared)) {
+      CmdArgs.push_back("-lm");
+    }
+    if (Args.hasArg(options::OPT_shared)) {
+      CmdArgs.push_back("-lgcc_s");
+    } else {
+      CmdArgs.push_back("-lgcc");
+      CmdArgs.push_back("-lgcc_eh");
+    }
+  }
+
+  getToolChain().addProfileRTLibs(Args, CmdArgs);
+
+  const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath());
+  C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
+}
+
 void openbsd::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
                                       const InputInfo &Output,
                                       const InputInfoList &Inputs,
Index: lib/Driver/ToolChains.h
===================================================================
--- lib/Driver/ToolChains.h
+++ lib/Driver/ToolChains.h
@@ -661,6 +661,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/ToolChains.cpp
===================================================================
--- lib/Driver/ToolChains.cpp
+++ lib/Driver/ToolChains.cpp
@@ -2405,6 +2405,40 @@
     Result.Multilibs = AndroidArmMultilibs;
 }
 
+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");
+
+  FilterNonExistent NonExistent(Path, "/crtcxa.o", D.getVFS());
+
+  Result.Multilibs.push_back(Default);
+  Result.Multilibs.push_back(Alt64);
+
+  Result.Multilibs.FilterOut(NonExistent);
+
+  Multilib::flags_list Flags;
+  addMultilibFlag(TargetTriple.isArch64Bit(), "maix64", Flags);
+  addMultilibFlag(TargetTriple.isArch32Bit(), "maix32", Flags);
+
+  if (!Result.Multilibs.select(Flags, Result.SelectedMultilib))
+    return false;
+
+  if (Result.SelectedMultilib == Alt64)
+    Result.BiarchSibling = Default;
+
+  return true;
+}
+
 static bool findBiarchMultilibs(const Driver &D,
                                 const llvm::Triple &TargetTriple,
                                 StringRef Path, const ArgList &Args,
@@ -2607,6 +2641,10 @@
       } else if (isMipsArch(TargetArch)) {
         if (!findMIPSMultilibs(D, TargetTriple, LI->getName(), Args, Detected))
           continue;
+      } else if (TargetTriple.getOS() == llvm::Triple::AIX) {
+        if (!findAIXBiarchMultilibs(D, TargetTriple, LI->getName(), Args,
+                                    NeedsBiarchSuffix, Detected))
+          continue;
       } else if (!findBiarchMultilibs(D, TargetTriple, LI->getName(), Args,
                                       NeedsBiarchSuffix, Detected)) {
         continue;
@@ -3676,21 +3714,89 @@
   // headers.
   addSystemInclude(DriverArgs, CC1Args, "/usr/include/c++/v1/support/solaris");
 
+  // We need a detected GCC installation on Linux to provide libstdc++'s
+  // headers. We handled the libc++ case above.
+  if (!GCCInstallation.isValid())
+    return;
+
+  // By default, look for the C++ headers in an include directory adjacent to
+  // the lib directory of the GCC installation. Note that this is expect to be
+  // equivalent to '/usr/include/c++/X.Y' in almost all cases.
+  StringRef LibDir = GCCInstallation.getParentLibPath();
+  StringRef TripleStr = GCCInstallation.getTriple().str();
+  const Multilib &Multilib = GCCInstallation.getMultilib();
+  const GCCVersion &Version = GCCInstallation.getVersion();
+
+  // The primary search for libstdc++ supports multiarch variants.
+  addLibStdCXXIncludePaths(LibDir.str() + "/../include",
+                           "/c++/" + Version.Text, TripleStr,
+                           /*GCCMultiarchTriple*/ "",
+                           /*TargetMultiarchTriple*/ "",
+                           Multilib.includeSuffix(), DriverArgs, CC1Args);
+}
+
+/// AIX - AIX tool chain which can call as(1) and ld(1) directly.
+
+AIX::AIX(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
+    : Generic_GCC(D, Triple, Args) {
+
+  GCCInstallation.init(Triple, Args);
+
+  path_list &Paths = getFilePaths();
   if (GCCInstallation.isValid()) {
-    GCCVersion Version = GCCInstallation.getVersion();
-    addSystemInclude(DriverArgs, CC1Args,
-                     getDriver().SysRoot + "/usr/gcc/" +
-                     Version.MajorStr + "." +
-                     Version.MinorStr +
-                     "/include/c++/" + Version.Text);
-    addSystemInclude(DriverArgs, CC1Args,
-                     getDriver().SysRoot + "/usr/gcc/" + Version.MajorStr +
-                     "." + Version.MinorStr + "/include/c++/" +
-                     Version.Text + "/" +
-                     GCCInstallation.getTriple().str());
+    addPathIfExists(D, GCCInstallation.getInstallPath(), Paths);
+    addPathIfExists(D, GCCInstallation.getParentLibPath(), Paths);
+  }
+
+  addPathIfExists(D, getDriver().getInstalledDir(), Paths);
+  if (getDriver().getInstalledDir() != getDriver().Dir)
+    addPathIfExists(D, getDriver().Dir, Paths);
+
+  switch (Triple.getArch()) {
+  case llvm::Triple::ppc:
+    addPathIfExists(D, getDriver().SysRoot + getDriver().Dir + "/../lib", Paths);
+    addPathIfExists(D, getDriver().SysRoot + "/usr/lib", Paths);
+    break;
+  case llvm::Triple::ppc64:
+    addPathIfExists(D, getDriver().SysRoot + getDriver().Dir + "/../lib64", Paths);
+    addPathIfExists(D, getDriver().SysRoot + "/usr/lib64", Paths);
+    break;
+  default:
+    llvm_unreachable("Unsupported architecture");
   }
 }
 
+Tool *AIX::buildAssembler() const { return new tools::aix::Assembler(*this); }
+
+Tool *AIX::buildLinker() const { return new tools::aix::Linker(*this); }
+
+void AIX::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+                                       ArgStringList &CC1Args) const {
+  if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+      DriverArgs.hasArg(options::OPT_nostdincxx))
+    return;
+
+  // We need a detected GCC installation on Linux to provide libstdc++'s
+  // headers. We handled the libc++ case above.
+  if (!GCCInstallation.isValid())
+    return;
+
+  // By default, look for the C++ headers in an include directory adjacent to
+  // the lib directory of the GCC installation. Note that this is expect to be
+  // equivalent to '/usr/include/c++/X.Y' in almost all cases.
+  StringRef LibDir = GCCInstallation.getParentLibPath();
+  StringRef TripleStr = GCCInstallation.getTriple().str();
+  const Multilib &Multilib = GCCInstallation.getMultilib();
+  const GCCVersion &Version = GCCInstallation.getVersion();
+
+  // The primary search for libstdc++ supports multiarch variants.
+  addLibStdCXXIncludePaths(LibDir.str() + "/../include",
+                           "/c++/" + Version.Text, TripleStr,
+                           /*GCCMultiarchTriple*/ "",
+                           /*TargetMultiarchTriple*/ "",
+                           Multilib.includeSuffix(), DriverArgs, CC1Args);
+}
+
 /// Distribution (very bare-bones at the moment).
 
 enum Distro {
Index: lib/Driver/Driver.cpp
===================================================================
--- lib/Driver/Driver.cpp
+++ lib/Driver/Driver.cpp
@@ -2648,6 +2648,9 @@
     case llvm::Triple::Solaris:
       TC = new toolchains::Solaris(*this, Target, Args);
       break;
+    case llvm::Triple::AIX:
+      TC = new toolchains::AIX(*this, Target, Args);
+      break;
     case llvm::Triple::AMDHSA:
       TC = new toolchains::AMDGPUToolChain(*this, Target, Args);
       break;
Index: lib/Basic/Targets.cpp
===================================================================
--- lib/Basic/Targets.cpp
+++ lib/Basic/Targets.cpp
@@ -697,6 +697,43 @@
   }
 };
 
+// AIX Target
+template <typename Target>
+class AIXTargetInfo : public OSTargetInfo<Target> {
+protected:
+  void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+                    MacroBuilder &Builder) const override {
+    DefineStd(Builder, "unix", Opts);
+    Builder.defineMacro("_IBMR2");
+    Builder.defineMacro("_POWER");
+    Builder.defineMacro("_AIX");
+    Builder.defineMacro("_AIX32");
+    Builder.defineMacro("_AIX41");
+    Builder.defineMacro("_AIX43");
+    Builder.defineMacro("_AIX51");
+    Builder.defineMacro("_AIX52");
+    Builder.defineMacro("_AIX53");
+    Builder.defineMacro("_AIX61");
+    Builder.defineMacro("_LONG_LONG");
+    Builder.defineMacro("_ALL_SOURCE");
+    Builder.defineMacro("_REENTRANT");
+    if (this->PointerWidth == 64) {
+      Builder.defineMacro("__64BIT__");
+    }
+  }
+
+public:
+  AIXTargetInfo(const llvm::Triple &Triple)
+      : OSTargetInfo<Target>(Triple) {
+    this->UserLabelPrefix = "";
+    if (this->PointerWidth == 64) {
+      this->WCharType = this->UnsignedInt;
+    } else {
+      this->WCharType = this->UnsignedShort;
+    }
+  }
+};
+
 // Windows target
 template<typename Target>
 class WindowsTargetInfo : public OSTargetInfo<Target> {
@@ -1191,8 +1228,10 @@
   Builder.defineMacro("__REGISTER_PREFIX__", "");
 
   // FIXME: Should be controlled by command line option.
-  if (LongDoubleWidth == 128)
+  if (LongDoubleWidth == 128) {
     Builder.defineMacro("__LONG_DOUBLE_128__");
+    Builder.defineMacro("__LONGDOUBLE128");
+  }
 
   if (Opts.AltiVec) {
     Builder.defineMacro("__VEC__", "10206");
@@ -1589,6 +1628,10 @@
       PtrDiffType = SignedInt;
       IntPtrType = SignedInt;
       break;
+    case llvm::Triple::AIX:
+      SizeType = UnsignedLong;
+      PtrDiffType = SignedLong;
+      IntPtrType = SignedLong;
     default:
       break;
     }
@@ -8318,6 +8361,8 @@
       return new OpenBSDTargetInfo<PPC32TargetInfo>(Triple, Opts);
     case llvm::Triple::RTEMS:
       return new RTEMSTargetInfo<PPC32TargetInfo>(Triple, Opts);
+    case llvm::Triple::AIX:
+      return new AIXTargetInfo<PPC32TargetInfo>(Triple);
     default:
       return new PPC32TargetInfo(Triple, Opts);
     }
@@ -8334,6 +8379,8 @@
       return new FreeBSDTargetInfo<PPC64TargetInfo>(Triple, Opts);
     case llvm::Triple::NetBSD:
       return new NetBSDTargetInfo<PPC64TargetInfo>(Triple, Opts);
+    case llvm::Triple::AIX:
+      return new AIXTargetInfo<PPC64TargetInfo>(Triple);
     default:
       return new PPC64TargetInfo(Triple, Opts);
     }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to