Jonathan.Crowther updated this revision to Diff 239198.
Jonathan.Crowther added a comment.

Addressed comments by moving `getLoadModuleFilnameForFunction` to 
`llvm/lib/Support/SystemUtils.cpp`


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D72736/new/

https://reviews.llvm.org/D72736

Files:
  clang/lib/Tooling/CompilationDatabase.cpp
  clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp
  clang/tools/libclang/CIndexer.cpp
  llvm/include/llvm/Support/SystemUtils.h
  llvm/lib/Support/SystemUtils.cpp
  llvm/lib/Support/Unix/Path.inc
  llvm/unittests/Support/ProgramTest.cpp

Index: llvm/unittests/Support/ProgramTest.cpp
===================================================================
--- llvm/unittests/Support/ProgramTest.cpp
+++ llvm/unittests/Support/ProgramTest.cpp
@@ -58,6 +58,8 @@
 static cl::opt<std::string>
 ProgramTestStringArg2("program-test-string-arg2");
 
+void DummyFunction() {}
+
 class ProgramEnvTest : public testing::Test {
   std::vector<StringRef> EnvTable;
   std::vector<std::string> EnvStorage;
@@ -114,8 +116,8 @@
     exit(0);
 
   // getMainExecutable returns an absolute path; prepend the long-path prefix.
-  std::string MyAbsExe =
-      sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
+  void *MainAddr = (void *)(intptr_t)DummyFunction;
+  std::string MyAbsExe = sys::fs::getMainExecutable(TestMainArgv0, MainAddr);
   std::string MyExe;
   if (!StringRef(MyAbsExe).startswith("\\\\?\\"))
     MyExe.append("\\\\?\\");
@@ -160,8 +162,8 @@
     exit(1);
   }
 
-  std::string my_exe =
-      sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
+  void *MainAddr = (void *)(intptr_t)DummyFunction;
+  std::string my_exe = sys::fs::getMainExecutable(TestMainArgv0, MainAddr);
   StringRef argv[] = {
       my_exe,
       "--gtest_filter=ProgramEnvTest.CreateProcessTrailingSlash",
@@ -197,8 +199,8 @@
     exit(0);
   }
 
-  std::string Executable =
-      sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
+  void *MainAddr = (void *)(intptr_t)DummyFunction;
+  std::string Executable = sys::fs::getMainExecutable(TestMainArgv0, MainAddr);
   StringRef argv[] = {Executable,
                       "--gtest_filter=ProgramEnvTest.TestExecuteNoWait"};
 
@@ -252,8 +254,8 @@
     exit(0);
   }
 
-  std::string Executable =
-      sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
+  void *MainAddr = (void *)(intptr_t)DummyFunction;
+  std::string Executable = sys::fs::getMainExecutable(TestMainArgv0, MainAddr);
   StringRef argv[] = {
       Executable, "--gtest_filter=ProgramEnvTest.TestExecuteAndWaitTimeout"};
 
Index: llvm/lib/Support/Unix/Path.inc
===================================================================
--- llvm/lib/Support/Unix/Path.inc
+++ llvm/lib/Support/Unix/Path.inc
@@ -87,6 +87,7 @@
 #include <sys/vfs.h>
 #elif defined(_AIX)
 #include <sys/statfs.h>
+#include <llvm/Support/SystemUtils.h>
 
 // <sys/vmount.h> depends on `uint` to be a typedef from <sys/types.h> to
 // `uint_t`; however, <sys/types.h> does not always declare `uint`. We provide
@@ -222,7 +223,7 @@
   if (getprogpath(exe_path, argv0) != NULL)
     return exe_path;
 #elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__minix) ||       \
-    defined(__DragonFly__) || defined(__FreeBSD_kernel__) || defined(_AIX)
+    defined(__DragonFly__) || defined(__FreeBSD_kernel__)
   const char *curproc = "/proc/curproc/file";
   char exe_path[PATH_MAX];
   if (sys::fs::exists(curproc)) {
@@ -238,6 +239,8 @@
   // If we don't have procfs mounted, fall back to argv[0]
   if (getprogpath(exe_path, argv0) != NULL)
     return exe_path;
+#elif defined(_AIX)
+  return getLoadModuleFilenameForFunction(MainAddr)->c_str();
 #elif defined(__linux__) || defined(__CYGWIN__) || defined(__gnu_hurd__)
   char exe_path[MAXPATHLEN];
   const char *aPath = "/proc/self/exe";
Index: llvm/lib/Support/SystemUtils.cpp
===================================================================
--- llvm/lib/Support/SystemUtils.cpp
+++ llvm/lib/Support/SystemUtils.cpp
@@ -13,6 +13,17 @@
 
 #include "llvm/Support/SystemUtils.h"
 #include "llvm/Support/raw_ostream.h"
+
+// These typedefs are needed for sys/ldr.h to work on AIX
+#if defined(_AIX)
+typedef unsigned int uint;
+typedef unsigned short ushort;
+typedef void *__ptr64;
+static_assert(sizeof(__ptr64) == 8u, "__ptr64 size error.");
+#include <sys/ldr.h>
+#include <errno.h>
+#endif
+
 using namespace llvm;
 
 bool llvm::CheckBitcodeOutputToConsole(raw_ostream &stream_to_check,
@@ -28,3 +39,66 @@
   }
   return false;
 }
+
+#if defined(_AIX)
+// Returns the name of the load module that contains the entry point of the
+// function referenced by fp.
+static SmallString<128> getLoadModuleFilenameForFunctionAIX(void (*fp)(void)) {
+  int PrevErrno = errno;
+
+  size_t BufSize = 2048u;
+  std::unique_ptr<char[]> Buf;
+  while (true) {
+    Buf = std::make_unique<char []>(BufSize);
+    errno = 0;
+    int Ret = loadquery(L_GETXINFO, Buf.get(), (unsigned int)BufSize);
+    if (Ret != -1)
+      break; // loadquery() was successful.
+    if (errno != ENOMEM)
+      llvm_unreachable("Encountered an unexpected loadquery() failure");
+
+    // errno == ENOMEM; try to allocate more memory.
+    if ((BufSize & ~((-1u) >> 1u)) != 0u)
+      llvm::report_fatal_error("BufSize needed for loadquery() too large");
+
+    Buf.release();
+    BufSize <<= 1u;
+  }
+
+  // Extract the function entry point from the function descriptor.
+  uint64_t EntryAddr = *reinterpret_cast<uintptr_t *>(fp);
+
+  // Loop to locate the function entry point in the loadquery() results.
+  ld_xinfo *CurInfo = reinterpret_cast<ld_xinfo *>(Buf.get());
+  while (true) {
+    uint64_t CurTextStart = (uint64_t)CurInfo->ldinfo_textorg;
+    uint64_t CurTextEnd = CurTextStart + CurInfo->ldinfo_textsize;
+    if (CurTextStart <= EntryAddr && EntryAddr < CurTextEnd)
+      break; // Successfully located.
+
+    if (CurInfo->ldinfo_next == 0u)
+      llvm::report_fatal_error("Cannot locate entry point in "
+                               "the loadquery() results");
+    CurInfo = reinterpret_cast<ld_xinfo *>(reinterpret_cast<char *>(CurInfo) +
+                                           CurInfo->ldinfo_next);
+  }
+
+  errno = PrevErrno;
+  char *filename = reinterpret_cast<char *>(CurInfo) + CurInfo->ldinfo_filename;
+  return SmallString<128>(filename);
+}
+#endif
+
+llvm::Expected<SmallString<128>>
+llvm::getLoadModuleFilenameForFunctionImpl(void (*fp)(void)) {
+  if (!fp) {
+    return createStringError(std::errc::invalid_argument,
+		             "Function address can not be found");
+  }
+#if defined(_AIX)
+  return getLoadModuleFilenameForFunctionAIX(fp);
+#endif
+  llvm::report_fatal_error(
+      "getLoadModuleFilenameForFunction not implemented on this platform");
+}
+
Index: llvm/include/llvm/Support/SystemUtils.h
===================================================================
--- llvm/include/llvm/Support/SystemUtils.h
+++ llvm/include/llvm/Support/SystemUtils.h
@@ -14,6 +14,8 @@
 #ifndef LLVM_SUPPORT_SYSTEMUTILS_H
 #define LLVM_SUPPORT_SYSTEMUTILS_H
 
+#include <llvm/Support/Error.h>
+
 namespace llvm {
   class raw_ostream;
 
@@ -26,6 +28,16 @@
   bool print_warning = true     ///< Control whether warnings are printed
 );
 
+llvm::Expected<SmallString<128>>
+getLoadModuleFilenameForFunctionImpl(void (*Func)(void));
+
+template <typename FuncAddrType>
+llvm::Expected<SmallString<128>>
+getLoadModuleFilenameForFunction(FuncAddrType FuncAddr) {
+  void (*FP)(void) = reinterpret_cast<void (*)(void)>(FuncAddr);
+  return getLoadModuleFilenameForFunctionImpl(FP);
+}
+
 } // End llvm namespace
 
 #endif
Index: clang/tools/libclang/CIndexer.cpp
===================================================================
--- clang/tools/libclang/CIndexer.cpp
+++ clang/tools/libclang/CIndexer.cpp
@@ -38,63 +38,10 @@
 #else
 #include <dlfcn.h>
 #endif
+#include <llvm/Support/SystemUtils.h>
 
 using namespace clang;
 
-#ifdef _AIX
-namespace clang {
-namespace {
-
-template <typename LibClangPathType>
-void getClangResourcesPathImplAIX(LibClangPathType &LibClangPath) {
-  int PrevErrno = errno;
-
-  size_t BufSize = 2048u;
-  std::unique_ptr<char[]> Buf;
-  while (true) {
-    Buf = std::make_unique<char []>(BufSize);
-    errno = 0;
-    int Ret = loadquery(L_GETXINFO, Buf.get(), (unsigned int)BufSize);
-    if (Ret != -1)
-      break; // loadquery() was successful.
-    if (errno != ENOMEM)
-      llvm_unreachable("Encountered an unexpected loadquery() failure");
-
-    // errno == ENOMEM; try to allocate more memory.
-    if ((BufSize & ~((-1u) >> 1u)) != 0u)
-      llvm::report_fatal_error("BufSize needed for loadquery() too large");
-
-    Buf.release();
-    BufSize <<= 1u;
-  }
-
-  // Extract the function entry point from the function descriptor.
-  uint64_t EntryAddr =
-      reinterpret_cast<uintptr_t &>(clang_createTranslationUnit);
-
-  // Loop to locate the function entry point in the loadquery() results.
-  ld_xinfo *CurInfo = reinterpret_cast<ld_xinfo *>(Buf.get());
-  while (true) {
-    uint64_t CurTextStart = (uint64_t)CurInfo->ldinfo_textorg;
-    uint64_t CurTextEnd = CurTextStart + CurInfo->ldinfo_textsize;
-    if (CurTextStart <= EntryAddr && EntryAddr < CurTextEnd)
-      break; // Successfully located.
-
-    if (CurInfo->ldinfo_next == 0u)
-      llvm::report_fatal_error("Cannot locate entry point in "
-                               "the loadquery() results");
-    CurInfo = reinterpret_cast<ld_xinfo *>(reinterpret_cast<char *>(CurInfo) +
-                                           CurInfo->ldinfo_next);
-  }
-
-  LibClangPath += reinterpret_cast<char *>(CurInfo) + CurInfo->ldinfo_filename;
-  errno = PrevErrno;
-}
-
-} // end anonymous namespace
-} // end namespace clang
-#endif
-
 const std::string &CIndexer::getClangResourcesPath() {
   // Did we already compute the path?
   if (!ResourcesPath.empty())
@@ -122,7 +69,9 @@
 
   LibClangPath += path;
 #elif defined(_AIX)
-  getClangResourcesPathImplAIX(LibClangPath);
+  LibClangPath +=
+      llvm::getLoadModuleFilenameForFunction(clang_createTranslationUnit)
+      ->c_str();
 #else
   // This silly cast below avoids a C++ warning.
   Dl_info info;
Index: clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp
===================================================================
--- clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp
+++ clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp
@@ -921,7 +921,8 @@
 
   // Save the current executable directory as it will be useful to find other
   // tools.
-  BundlerExecutable = sys::fs::getMainExecutable(argv[0], &BundlerExecutable);
+  void *MainAddr = (void *)(intptr_t)PrintVersion;
+  BundlerExecutable = sys::fs::getMainExecutable(argv[0], MainAddr);
 
   if (llvm::Error Err = Unbundle ? UnbundleFiles() : BundleFiles()) {
     reportError(std::move(Err));
Index: clang/lib/Tooling/CompilationDatabase.cpp
===================================================================
--- clang/lib/Tooling/CompilationDatabase.cpp
+++ clang/lib/Tooling/CompilationDatabase.cpp
@@ -227,9 +227,9 @@
 };
 
 std::string GetClangToolCommand() {
-  static int Dummy;
+  void *MainAddr = (void *)(intptr_t)GetClangToolCommand;
   std::string ClangExecutable =
-      llvm::sys::fs::getMainExecutable("clang", (void *)&Dummy);
+      llvm::sys::fs::getMainExecutable("clang", MainAddr);
   SmallString<128> ClangToolPath;
   ClangToolPath = llvm::sys::path::parent_path(ClangExecutable);
   llvm::sys::path::append(ClangToolPath, "clang-tool");
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to