Rewrite llvm-rs-link.

1. Default linked library: rslib.bc (using slangdata trick);
2. llvm-rs-link [-nostdlib]
                [-L <additional lib.bc #X>]*
                <unlinked.bc #1> <unlinked.bc #2> ... <unlinked.bc #N>
will does:
  for (i := 1 to #N) {
    M := LoadBitcode(<unlinked.bc #i>);
    if (no -nostdlib specified)
      M := Link(M, rslib.bc);
    for (x in X)
      M := Link(M, <additional lib.bc #x>);
    // Overwrite the input .bc
    SaveBitcode(M, <unlinked.bc #i>)
  }
diff --git a/Android.mk b/Android.mk
index 65e5dee..c0890d6 100644
--- a/Android.mk
+++ b/Android.mk
@@ -75,6 +75,20 @@
 include $(LLVM_GEN_INTRINSICS_MK)
 include $(BUILD_HOST_SHARED_LIBRARY)
 
+# Host static library containing rslib.bc
+# ========================================================
+include $(CLEAR_VARS)
+
+input_data_file := frameworks/compile/slang/rslib.bc
+slangdata_output_var_name := rslib_bc
+
+LOCAL_IS_HOST_MODULE := true
+LOCAL_MODULE := librslib
+LOCAL_MODULE_TAGS := optional
+
+include $(LOCAL_PATH)/SlangData.mk
+include $(BUILD_HOST_STATIC_LIBRARY)
+
 # Executable llvm-rs-link for host
 # ========================================================
 include $(CLEAR_VARS)
@@ -83,6 +97,7 @@
 include $(LLVM_ROOT_PATH)/llvm.mk
 
 LOCAL_MODULE := llvm-rs-link
+LOCAL_MODULE_TAGS := optional
 
 LOCAL_MODULE_CLASS := EXECUTABLES
 
@@ -92,6 +107,9 @@
 LOCAL_SHARED_LIBRARIES :=	\
 	libslang
 
+LOCAL_STATIC_LIBRARIES :=	\
+	librslib
+
 LOCAL_LDLIBS := -ldl -lpthread
 
 include $(LLVM_HOST_BUILD_MK)
diff --git a/llvm-rs-link.cpp b/llvm-rs-link.cpp
index 7b14e26..6eb8417 100644
--- a/llvm-rs-link.cpp
+++ b/llvm-rs-link.cpp
@@ -1,3 +1,4 @@
+#include <list>
 #include <memory>
 #include <string>
 #include <vector>
@@ -30,9 +31,17 @@
 InputFilenames(cl::Positional, cl::OneOrMore,
                cl::desc("<input bitcode files>"));
 
-static cl::opt<std::string>
-OutputFilename("o", cl::Required, cl::desc("Override output filename"),
-               cl::value_desc("<output bitcode file>"));
+static cl::list<std::string>
+OutputFilenames("o", cl::desc("Override output filename"),
+                cl::value_desc("<output bitcode file>"));
+
+static cl::opt<bool>
+NoStdLib("nostdlib", cl::desc("Don't link RS default libraries"));
+
+static cl::list<std::string>
+    AdditionalLibs("l", cl::Prefix,
+                   cl::desc("Specify additional libraries to link to"),
+                   cl::value_desc("<library bitcode>"));
 
 static bool GetExportSymbolNames(NamedMDNode *N,
                                  unsigned NameOpIdx,
@@ -74,80 +83,120 @@
   return Result;
 }
 
-// LoadFile - Read the specified bitcode file in and return it.  This routine
-// searches the link path for the specified file to try to find it...
-//
-static inline std::auto_ptr<Module> LoadFile(const char *argv0,
-                                             const std::string &FN,
-                                             LLVMContext& Context) {
-  sys::Path Filename;
-  if (!Filename.set(FN)) {
-    errs() << "Invalid file name: '" << FN << "'\n";
-    return std::auto_ptr<Module>();
-  }
 
+static inline MemoryBuffer *LoadFileIntoMemory(const std::string &F) {
   std::string Err;
-  Module *Result = 0;
+  MemoryBuffer *MB = MemoryBuffer::getFile(F, &Err);
 
-  const std::string &FNStr = Filename.str();
-  MemoryBuffer *Buffer = MemoryBuffer::getFile(FNStr, &Err);
-  if (!Buffer) {
-    errs() << Err;
-    return std::auto_ptr<Module>();
-  }
-  Result = ParseBitcodeFile(Buffer, Context, &Err);
-  if (Result) return std::auto_ptr<Module>(Result);   // Load successful!
+  if (MB == NULL)
+    errs() << "Failed to load `" << F << "' (" << Err << ")\n";
 
-  errs() << Err;
-  return std::auto_ptr<Module>();
+  return MB;
 }
 
-int main(int argc, char **argv) {
-  llvm_shutdown_obj X;
+static inline Module *ParseBitcodeFromMemoryBuffer(MemoryBuffer *MB,
+                                                   LLVMContext& Context) {
+  std::string Err;
+  Module *M = ParseBitcodeFile(MB, Context, &Err);
 
-  cl::ParseCommandLineOptions(argc, argv, "llvm-rs-link\n");
+  if (M == NULL)
+    errs() << "Corrupted bitcode file `" << MB->getBufferIdentifier()
+           <<  "' (" << Err << ")\n";
 
-  LLVMContext &Context = getGlobalContext();
-  std::auto_ptr<Module> Composite = LoadFile(argv[0], InputFilenames[0],
-                                             Context);
-  std::string ErrorMessage;
-  if (Composite.get() == 0) {
-    errs() << argv[0] << ": error loading file '"
-           << InputFilenames[0] << "'\n";
-    return 1;
-  }
-  for (unsigned i = 1; i < InputFilenames.size(); ++i) {
-    std::auto_ptr<Module> M(LoadFile(argv[0], InputFilenames[i], Context));
-    if (M.get() == 0) {
-      errs() << argv[0] << ": error loading file '"
-             << InputFilenames[i] << "'\n";
-      return 1;
+  return M;
+}
+
+// LoadBitcodeFile - Read the specified bitcode file in and return it.
+static inline Module *LoadBitcodeFile(const std::string &F,
+                                      LLVMContext& Context) {
+  MemoryBuffer *MB = LoadFileIntoMemory(F);
+  if (MB == NULL)
+    return NULL;
+
+  Module *M = ParseBitcodeFromMemoryBuffer(MB, Context);
+  if (M == NULL)
+    delete MB;
+
+  return M;
+}
+
+extern const char rslib_bc[];
+extern unsigned rslib_bc_size;
+
+static bool PreloadLibraries(bool NoStdLib,
+                             const std::vector<std::string> &AdditionalLibs,
+                             std::list<MemoryBuffer *> LibBitcode) {
+  MemoryBuffer *MB;
+
+  LibBitcode.clear();
+
+  if (!NoStdLib) {
+    // rslib.bc
+    MB = MemoryBuffer::getMemBufferCopy(StringRef(rslib_bc, rslib_bc_size),
+                                        "rslib.bc");
+    if (MB == NULL) {
+      errs() << "Failed to load (in-memory) `rslib.bc'!\n";
+      return false;
     }
-    if (Linker::LinkModules(Composite.get(), M.get(), &ErrorMessage)) {
-      errs() << argv[0] << ": link error in '" << InputFilenames[i]
-             << "': " << ErrorMessage << "\n";
-      return 1;
+
+    LibBitcode.push_back(MB);
+  }
+
+  // Load additional libraries
+  for (std::vector<std::string>::const_iterator
+          I = AdditionalLibs.begin(), E = AdditionalLibs.end();
+       I != E;
+       I++) {
+    MB = LoadFileIntoMemory(*I);
+    if (MB == NULL)
+      return false;
+    LibBitcode.push_back(MB);
+  }
+
+  return true;
+}
+
+static void UnloadLibraries(std::list<MemoryBuffer *>& LibBitcode) {
+  for (std::list<MemoryBuffer *>::iterator
+          I = LibBitcode.begin(), E = LibBitcode.end();
+       I != E;
+       I++)
+    delete *I;
+  LibBitcode.clear();
+  return;
+}
+
+Module *PerformLinking(const std::string &InputFile,
+                       const std::list<MemoryBuffer *> &LibBitcode,
+                       LLVMContext &Context) {
+  std::string Err;
+  std::auto_ptr<Module> Composite(LoadBitcodeFile(InputFile, Context));
+
+  if (Composite.get() == NULL)
+    return NULL;
+
+  for (std::list<MemoryBuffer *>::const_iterator I = LibBitcode.begin(),
+          E = LibBitcode.end();
+       I != E;
+       I++) {
+    Module *Lib = ParseBitcodeFromMemoryBuffer(*I, Context);
+    if (Lib == NULL)
+      return NULL;
+
+    if (Linker::LinkModules(Composite.get(), Lib, &Err)) {
+      errs() << "Failed to link `" << InputFile << "' with library bitcode `"
+             << (*I)->getBufferIdentifier() << "' (" << Err << ")\n";
+      return NULL;
     }
   }
 
-  std::string ErrorInfo;
-  std::auto_ptr<raw_ostream>
-  Out(new raw_fd_ostream(OutputFilename.c_str(),
-                         ErrorInfo,
-                         raw_fd_ostream::F_Binary));
-  if (!ErrorInfo.empty()) {
-    errs() << ErrorInfo << '\n';
-    return 1;
-  }
+  return Composite.release();
+}
 
-  if (verifyModule(*Composite)) {
-    errs() << argv[0] << ": linked module is broken!\n";
-    return 1;
-  }
-
+bool OptimizeModule(Module *M) {
   PassManager Passes;
 
-  const std::string &ModuleDataLayout = Composite.get()->getDataLayout();
+  const std::string &ModuleDataLayout = M->getDataLayout();
   if (!ModuleDataLayout.empty())
     if (TargetData *TD = new TargetData(ModuleDataLayout))
       Passes.add(TD);
@@ -157,18 +206,79 @@
   ExportList.push_back("init");
   ExportList.push_back("root");
 
-  if (!GetExportSymbols(Composite.get(), ExportList))
-    return 1;
+  if (!GetExportSymbols(M, ExportList)) {
+    return false;
+  }
 
   Passes.add(createInternalizePass(ExportList));
 
+  // TODO(zonr): Do we need to run all LTO passes?
   createStandardLTOPasses(&Passes,
                           /* Internalize = */false,
                           /* RunInliner = */true,
                           /* VerifyEach = */false);
-  Passes.run(*Composite.get());
+  Passes.run(*M);
 
-  WriteBitcodeToFile(Composite.get(), *Out);
+  return true;
+}
 
-  return 0;
+int main(int argc, char **argv) {
+  llvm_shutdown_obj X;  // Call llvm_shutdown() on exit.
+
+  cl::ParseCommandLineOptions(argc, argv, "llvm-rs-link\n");
+
+  std::list<MemoryBuffer *> LibBitcode;
+
+  if (!PreloadLibraries(NoStdLib, AdditionalLibs, LibBitcode))
+    return 1;
+
+  // No libraries specified to be linked
+  if (LibBitcode.size() == 0)
+    return 0;
+
+  LLVMContext &Context = getGlobalContext();
+  bool HasError = true;
+  std::string Err;
+
+  for (unsigned i = 0, e = InputFilenames.size(); i != e; i++) {
+    std::auto_ptr<Module> Linked(
+        PerformLinking(InputFilenames[i], LibBitcode, Context));
+
+    // Failed to link with InputFilenames[i] with LibBitcode
+    if (Linked.get() == NULL)
+      break;
+
+    // Verify linked module
+    if (verifyModule(*Linked, ReturnStatusAction, &Err)) {
+      errs() << InputFilenames[i] << " linked, but does not verify as "
+                                     "correct! (" << Err << ")\n";
+      break;
+    }
+
+    if (!OptimizeModule(Linked.get()))
+      break;
+
+    // Write out the module
+    tool_output_file Out(InputFilenames[i].c_str(), Err,
+                         raw_fd_ostream::F_Binary);
+
+    if (!Err.empty()) {
+      errs() << InputFilenames[i] << " linked, but failed to write out! "
+                                     "(" << Err << ")\n";
+      break;
+    }
+
+    WriteBitcodeToFile(Linked.get(), Out);
+
+    Out.keep();
+    Linked.reset();
+
+    if (i == (InputFilenames.size() - 1))
+      // This is the last file and no error occured.
+      HasError = false;
+  }
+
+  UnloadLibraries(LibBitcode);
+
+  return HasError;
 }