[llvm-commits] CVS: llvm/tools/gccld/GenerateCode.cpp gccld.cpp gccld.h

Reid Spencer reid at x10sys.com
Mon Feb 28 00:45:46 PST 2005



Changes in directory llvm/tools/gccld:

GenerateCode.cpp updated: 1.43 -> 1.44
gccld.cpp updated: 1.96 -> 1.97
gccld.h updated: 1.12 -> 1.13
---
Log message:

Changes to enable creation of native executables directly from gccld and to
ensure that -L paths don't contain both bytecode and native libraries. 
This patch contributed by Adam Treat.


---
Diffs of the changes:  (+182 -73)

 GenerateCode.cpp |   91 ++++++++++++++++++++++++++++++++
 gccld.cpp        |  152 ++++++++++++++++++++++++++++++-------------------------
 gccld.h          |   12 +++-
 3 files changed, 182 insertions(+), 73 deletions(-)


Index: llvm/tools/gccld/GenerateCode.cpp
diff -u llvm/tools/gccld/GenerateCode.cpp:1.43 llvm/tools/gccld/GenerateCode.cpp:1.44
--- llvm/tools/gccld/GenerateCode.cpp:1.43	Sun Feb 13 17:02:34 2005
+++ llvm/tools/gccld/GenerateCode.cpp	Mon Feb 28 02:45:35 2005
@@ -20,6 +20,7 @@
 #include "llvm/Analysis/LoadValueNumbering.h"
 #include "llvm/Analysis/Passes.h"
 #include "llvm/Analysis/Verifier.h"
+#include "llvm/Bytecode/Archive.h"
 #include "llvm/Bytecode/WriteBytecodePass.h"
 #include "llvm/Target/TargetData.h"
 #include "llvm/Transforms/IPO.h"
@@ -127,6 +128,62 @@
   if (Verify) PM.add(createVerifierPass());
 }
 
+static bool isBytecodeLibrary(const sys::Path &FullPath) {
+  // Check for a bytecode file
+  if (FullPath.isBytecodeFile()) return true;
+  // Check for a dynamic library file
+  if (FullPath.isDynamicLibrary()) return false;
+  // Check for a true bytecode archive file
+  if (FullPath.isArchive() ) {
+    std::string ErrorMessage;
+    Archive* ar = Archive::OpenAndLoadSymbols( FullPath, &ErrorMessage );
+    return ar->isBytecodeArchive();    
+  }
+  return false;
+}
+
+static bool isBytecodeLPath(const std::string &LibPath) {                        
+  bool isBytecodeLPath = false;
+
+  // Make sure the -L path has a '/' character
+  // because llvm-g++ passes them without the ending
+  // '/' char and sys::Path doesn't think it is a 
+  // directory (see: sys::Path::isDirectory) without it 
+  std::string dir = LibPath;
+  if ( dir[dir.length()-1] != '/' )
+  dir.append("/");
+
+  sys::Path LPath(dir);
+
+  // Grab the contents of the -L path
+  std::set<sys::Path> Files;
+  LPath.getDirectoryContents(Files);
+
+  // Iterate over the contents one by one to determine
+  // if this -L path has any bytecode shared libraries
+  // or archives
+  std::set<sys::Path>::iterator File = Files.begin();
+  for (; File != Files.end(); ++File) {
+
+    if ( File->isDirectory() )
+      continue;
+    
+    std::string path = File->toString();
+    std::string dllsuffix = sys::Path::GetDLLSuffix();
+
+    // Check for an ending '.dll,.so' or '.a' suffix as all
+    // other files are not of interest to us here
+    if ( path.find(dllsuffix, path.size()-dllsuffix.size()) == std::string::npos
+        && path.find(".a", path.size()-2) == std::string::npos )
+      continue;
+     
+    // Finally, check to see if the file is a true bytecode file
+    if (isBytecodeLibrary(*File))
+      isBytecodeLPath = true;
+  }
+  return isBytecodeLPath;
+}
+
 /// GenerateBytecode - generates a bytecode file from the specified module.
 ///
 /// Inputs:
@@ -285,8 +342,12 @@
 ///
 int llvm::GenerateNative(const std::string &OutputFilename,
                          const std::string &InputFilename,
+                         const std::vector<std::string> &LibPaths,
                          const std::vector<std::string> &Libraries,
-                         const sys::Path &gcc, char ** const envp) {
+                         const sys::Path &gcc, char ** const envp,
+                         bool Shared,
+                         const std::string &RPath,
+                         const std::string &SOName) {
   // Remove these environment variables from the environment of the
   // programs that we will execute.  It appears that GCC sets these
   // environment variables so that the programs it uses can configure
@@ -316,7 +377,33 @@
   args.push_back("-o");
   args.push_back(OutputFilename.c_str());
   args.push_back(InputFilename.c_str());
-
+  
+  if (Shared) args.push_back("-shared");
+  if (!RPath.empty()) {
+    std::string rp = "-Wl,-rpath," + RPath;
+    args.push_back(rp.c_str());
+  }
+  if (!SOName.empty()) {
+    std::string so = "-Wl,-soname," + SOName;
+    args.push_back(so.c_str());
+  }
+  
+  // Add in the libpaths to find the libraries.
+  //
+  // Note:
+  //  When gccld is called from the llvm-gxx frontends, the -L paths for
+  //  the LLVM cfrontend install paths are appended.  We don't want the 
+  //  native linker to use these -L paths as they contain bytecode files.
+  //  Further, we don't want any -L paths that contain bytecode shared
+  //  libraries or true bytecode archive files.  We omit them in all such
+  //  cases.
+  for (unsigned index = 0; index < LibPaths.size(); index++) {
+    if (!isBytecodeLPath( LibPaths[index]) ) {
+      args.push_back("-L");
+      args.push_back(LibPaths[index].c_str());
+    }
+  }
+ 
   // Add in the libraries to link.
   for (unsigned index = 0; index < Libraries.size(); index++) {
     if (Libraries[index] != "crtend") {


Index: llvm/tools/gccld/gccld.cpp
diff -u llvm/tools/gccld/gccld.cpp:1.96 llvm/tools/gccld/gccld.cpp:1.97
--- llvm/tools/gccld/gccld.cpp:1.96	Sun Feb 13 17:02:34 2005
+++ llvm/tools/gccld/gccld.cpp	Mon Feb 28 02:45:35 2005
@@ -83,11 +83,21 @@
   cl::opt<bool>    
   NativeCBE("native-cbe",
             cl::desc("Generate a native binary with the C backend and GCC"));
+            
+  cl::opt<std::string>
+  RPath("rpath",
+        cl::desc("Set runtime shared library search path (requires -native or"
+                 " -native-cbe)"), 
+        cl::Prefix, cl::value_desc("directory"));
+        
+  cl::opt<std::string>
+  SOName("soname",
+         cl::desc("Set internal name of shared library (requires -native or"
+                 " -native-cbe)"), 
+         cl::Prefix, cl::value_desc("name"));
   
   // Compatibility options that are ignored but supported by LD
   cl::opt<std::string>
-  CO3("soname", cl::Hidden, cl::desc("Compatibility option: ignored"));
-  cl::opt<std::string>
   CO4("version-script", cl::Hidden, cl::desc("Compatibility option: ignored"));
   cl::opt<bool>
   CO5("eh-frame-hdr", cl::Hidden, cl::desc("Compatibility option: ignored"));
@@ -237,7 +247,7 @@
 
     // Create the output file.
     std::string RealBytecodeOutput = OutputFilename;
-    if (!LinkAsLibrary) RealBytecodeOutput += ".bc";
+    if (!LinkAsLibrary || Native || NativeCBE) RealBytecodeOutput += ".bc";
     std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
                                  std::ios::binary;
     std::ofstream Out(RealBytecodeOutput.c_str(), io_mode);
@@ -266,77 +276,83 @@
     // Close the bytecode file.
     Out.close();
 
-    // If we are not linking a library, generate either a native executable
-    // or a JIT shell script, depending upon what the user wants.
-    if (!LinkAsLibrary) {
-      // If the user wants to generate a native executable, compile it from the
-      // bytecode file.
-      //
-      // Otherwise, create a script that will run the bytecode through the JIT.
-      if (Native) {
-        // Name of the Assembly Language output file
-        sys::Path AssemblyFile ( OutputFilename);
-        AssemblyFile.appendSuffix("s");
-
-        // Mark the output files for removal if we get an interrupt.
-        sys::RemoveFileOnSignal(AssemblyFile);
-        sys::RemoveFileOnSignal(sys::Path(OutputFilename));
-
-        // Determine the locations of the llc and gcc programs.
-        sys::Path llc = FindExecutable("llc", argv[0]);
-        if (llc.isEmpty())
-          return PrintAndReturn(argv[0], "Failed to find llc");
-
-        sys::Path gcc = FindExecutable("gcc", argv[0]);
-        if (gcc.isEmpty())
-          return PrintAndReturn(argv[0], "Failed to find gcc");
-
-        // Generate an assembly language file for the bytecode.
-        if (Verbose) std::cout << "Generating Assembly Code\n";
-        GenerateAssembly(AssemblyFile.toString(), RealBytecodeOutput, llc);
-        if (Verbose) std::cout << "Generating Native Code\n";
-        GenerateNative(OutputFilename, AssemblyFile.toString(), 
-                       Libraries, gcc, envp );
-
-        // Remove the assembly language file.
-        AssemblyFile.destroyFile();
-      } else if (NativeCBE) {
-        sys::Path CFile (OutputFilename);
-        CFile.appendSuffix("cbe.c");
-
-        // Mark the output files for removal if we get an interrupt.
-        sys::RemoveFileOnSignal(CFile);
-        sys::RemoveFileOnSignal(sys::Path(OutputFilename));
-
-        // Determine the locations of the llc and gcc programs.
-        sys::Path llc = FindExecutable("llc", argv[0]);
-        if (llc.isEmpty())
-          return PrintAndReturn(argv[0], "Failed to find llc");
-
-        sys::Path gcc = FindExecutable("gcc", argv[0]);
-        if (gcc.isEmpty())
-          return PrintAndReturn(argv[0], "Failed to find gcc");
-
-        // Generate an assembly language file for the bytecode.
-        if (Verbose) std::cout << "Generating Assembly Code\n";
-        GenerateCFile(CFile.toString(), RealBytecodeOutput, llc);
-        if (Verbose) std::cout << "Generating Native Code\n";
-        GenerateNative(OutputFilename, CFile.toString(), Libraries, gcc, envp );
-
-        // Remove the assembly language file.
-        CFile.destroyFile();
+    // Generate either a native file or a JIT shell script.  If the user wants
+    // to generate a native file, compile it from the bytecode file. Otherwise, 
+    // if the target is not a library, create a script that will run the 
+    // bytecode through the JIT.
+    if (Native) {
+      // Name of the Assembly Language output file
+      sys::Path AssemblyFile (OutputFilename);
+      AssemblyFile.appendSuffix("s");
+
+      // Mark the output files for removal if we get an interrupt.
+      sys::RemoveFileOnSignal(AssemblyFile);
+      sys::RemoveFileOnSignal(sys::Path(OutputFilename));
+
+      // Determine the locations of the llc and gcc programs.
+      sys::Path llc = FindExecutable("llc", argv[0]);
+      if (llc.isEmpty())
+        return PrintAndReturn(argv[0], "Failed to find llc");
+
+      sys::Path gcc = FindExecutable("gcc", argv[0]);
+      if (gcc.isEmpty())
+        return PrintAndReturn(argv[0], "Failed to find gcc");
+
+      // Generate an assembly language file for the bytecode.
+      if (Verbose) std::cout << "Generating Assembly Code\n";
+      GenerateAssembly(AssemblyFile.toString(), RealBytecodeOutput, llc);
+      if (Verbose) std::cout << "Generating Native Code\n";
+      GenerateNative(OutputFilename, AssemblyFile.toString(), 
+                     LibPaths, Libraries, gcc, envp, LinkAsLibrary, RPath,
+                     SOName );
+
+      // Remove the assembly language file.
+      AssemblyFile.destroyFile();
+      // Remove the bytecode language file.
+      sys::Path(RealBytecodeOutput).destroyFile();
+    
+    } else if (NativeCBE) {
+      sys::Path CFile (OutputFilename);
+      CFile.appendSuffix("cbe.c");
+
+      // Mark the output files for removal if we get an interrupt.
+      sys::RemoveFileOnSignal(CFile);
+      sys::RemoveFileOnSignal(sys::Path(OutputFilename));
+
+      // Determine the locations of the llc and gcc programs.
+      sys::Path llc = FindExecutable("llc", argv[0]);
+      if (llc.isEmpty())
+        return PrintAndReturn(argv[0], "Failed to find llc");
+
+      sys::Path gcc = FindExecutable("gcc", argv[0]);
+      if (gcc.isEmpty())
+        return PrintAndReturn(argv[0], "Failed to find gcc");
+
+      // Generate an assembly language file for the bytecode.
+      if (Verbose) std::cout << "Generating Assembly Code\n";
+      GenerateCFile(CFile.toString(), RealBytecodeOutput, llc);
+      if (Verbose) std::cout << "Generating Native Code\n";
+      GenerateNative(OutputFilename, CFile.toString(),
+                     LibPaths, Libraries, gcc, envp, LinkAsLibrary, RPath,
+                     SOName );
 
-      } else {
-        EmitShellScript(argv);
-      }
+      // Remove the assembly language file.
+      CFile.destroyFile();
     
-      // Make the script executable...
-      sys::Path(OutputFilename).makeExecutable();
+      // Remove the bytecode language file.
+      sys::Path(RealBytecodeOutput).destroyFile();
 
-      // Make the bytecode file readable and directly executable in LLEE as well
+    } else if (!LinkAsLibrary) {
+      EmitShellScript(argv);
+      
+      // Make the bytecode file readable and directly executable in LLEE
       sys::Path(RealBytecodeOutput).makeExecutable();
       sys::Path(RealBytecodeOutput).makeReadable();
     }
+
+    // Make the output, whether native or script, executable as well...
+    sys::Path(OutputFilename).makeExecutable();
+  
   } catch (const char*msg) {
     std::cerr << argv[0] << ": " << msg << "\n";
     exitCode = 1;


Index: llvm/tools/gccld/gccld.h
diff -u llvm/tools/gccld/gccld.h:1.12 llvm/tools/gccld/gccld.h:1.13
--- llvm/tools/gccld/gccld.h:1.12	Mon Dec 13 22:20:07 2004
+++ llvm/tools/gccld/gccld.h	Mon Feb 28 02:45:35 2005
@@ -31,13 +31,19 @@
                   const std::string & InputFilename,
                   const sys::Path & llc);
 
-int GenerateCFile(const std::string &OutputFile, const std::string &InputFile,
-                  const sys::Path &llc);
+int 
+GenerateCFile (const std::string &OutputFile, 
+               const std::string &InputFile,
+               const sys::Path &llc);
 int
 GenerateNative (const std::string & OutputFilename,
                 const std::string & InputFilename,
+                const std::vector<std::string> & LibPaths,
                 const std::vector<std::string> & Libraries,
                 const sys::Path & gcc,
-                char ** const envp);
+                char ** const envp,
+                bool Shared,
+                const std::string & RPath,
+                const std::string & SOName);
 
 } // End llvm namespace






More information about the llvm-commits mailing list