MCLinker upstream commit e764452.

Change-Id: I5c9ec467ec96a0143e1e67c59365f3b6303e7348
diff --git a/tools/llvm-mcld/llvm-mcld.cpp b/tools/llvm-mcld/llvm-mcld.cpp
index 835bb59..7e6b9c8 100644
--- a/tools/llvm-mcld/llvm-mcld.cpp
+++ b/tools/llvm-mcld/llvm-mcld.cpp
@@ -11,7 +11,14 @@
 #include <mcld/Support/TargetRegistry.h>
 #include <mcld/Support/CommandLine.h>
 #include <mcld/Support/DerivedPositionDependentOptions.h>
+#include <mcld/Support/Path.h>
 #include <mcld/Support/RealPath.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/FileSystem.h>
+#include <mcld/Support/raw_ostream.h>
+#include <mcld/LD/DiagnosticLineInfo.h>
+#include <mcld/LD/TextDiagnosticPrinter.h>
+#include <mcld/MC/MCLDInfo.h>
 #include <mcld/CodeGen/SectLinkerOption.h>
 
 #include <llvm/Module.h>
@@ -26,9 +33,11 @@
 #include <llvm/Support/Host.h>
 #include <llvm/Support/IRReader.h>
 #include <llvm/Support/ManagedStatic.h>
+#include <llvm/Support/Signals.h>
 #include <llvm/Support/TargetRegistry.h>
 #include <llvm/Support/TargetSelect.h>
 #include <llvm/Support/ToolOutputFile.h>
+#include <llvm/Support/Process.h>
 #include <llvm/Target/TargetData.h>
 #include <llvm/Target/TargetMachine.h>
 
@@ -48,21 +57,10 @@
 
 #endif
 
-
 // General options for llc.  Other pass-specific options are specified
 // within the corresponding llc passes, and target-specific options
 // and back-end code generation options are specified with the target machine.
 //
-static cl::opt<std::string>
-InputFilename("dB",
-              cl::desc("set default bitcode"),
-              cl::value_desc("bitcode"));
-
-static cl::opt<std::string>
-OutputFilename("o",
-               cl::desc("Output filename"),
-               cl::value_desc("filename"));
-
 // Determine optimization level.
 static cl::opt<char>
 OptLevel("O",
@@ -90,21 +88,6 @@
   cl::desc("Target specific attributes (-mattr=help for details)"),
   cl::value_desc("a1,+a2,-a3,..."));
 
-static cl::opt<Reloc::Model>
-RelocModel("relocation-model",
-             cl::desc("Choose relocation model"),
-             cl::init(Reloc::Default),
-             cl::values(
-            clEnumValN(Reloc::Default, "default",
-                       "Target default relocation model"),
-            clEnumValN(Reloc::Static, "static",
-                       "Non-relocatable code"),
-            clEnumValN(Reloc::PIC_, "pic",
-                       "Fully relocatable, position independent code"),
-            clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
-                       "Relocatable external references, non-relocatable code"),
-            clEnumValEnd));
-
 static cl::opt<llvm::CodeModel::Model>
 CMModel("code-model",
         cl::desc("Choose code model"),
@@ -121,24 +104,6 @@
                               "Large code model"),
                    clEnumValEnd));
 
-cl::opt<mcld::CodeGenFileType>
-FileType("filetype", cl::init(mcld::CGFT_EXEFile),
-  cl::desc("Choose a file type (not all types are supported by all targets):"),
-  cl::values(
-       clEnumValN(mcld::CGFT_ASMFile, "asm",
-                  "Emit an assembly ('.s') file"),
-       clEnumValN(mcld::CGFT_OBJFile, "obj",
-                  "Emit a relocatable object ('.o') file"),
-       clEnumValN(mcld::CGFT_ARCFile, "arc",
-                  "Emit an archive ('.a') file"),
-       clEnumValN(mcld::CGFT_DSOFile, "dso",
-                  "Emit an dynamic shared object ('.so') file"),
-       clEnumValN(mcld::CGFT_EXEFile, "exe",
-                  "Emit a executable ('.exe') file"),
-       clEnumValN(mcld::CGFT_NULLFile, "null",
-                  "Emit nothing, for performance testing"),
-       clEnumValEnd));
-
 cl::opt<bool> NoVerify("disable-verify", cl::Hidden,
                        cl::desc("Do not verify input module"));
 
@@ -276,6 +241,21 @@
 //===----------------------------------------------------------------------===//
 // General Options
 static cl::opt<mcld::sys::fs::Path, false, llvm::cl::parser<mcld::sys::fs::Path> >
+ArgBitcodeFilename("dB",
+              cl::desc("set default bitcode"),
+              cl::value_desc("bitcode"));
+
+static cl::opt<mcld::sys::fs::Path, false, llvm::cl::parser<mcld::sys::fs::Path> >
+ArgOutputFilename("o",
+               cl::desc("Output filename"),
+               cl::value_desc("filename"));
+
+static cl::alias
+AliasOutputFilename("output",
+                    cl::desc("alias for -o"),
+                    cl::aliasopt(ArgOutputFilename));
+
+static cl::opt<mcld::sys::fs::Path, false, llvm::cl::parser<mcld::sys::fs::Path> >
 ArgSysRoot("sysroot",
            cl::desc("Use directory as the location of the sysroot, overriding the configure-time default."),
            cl::value_desc("directory"),
@@ -302,14 +282,25 @@
               cl::desc("alias for -t"),
               cl::aliasopt(ArgTrace));
 
-static cl::opt<bool>
-ArgVerbose("V",
-          cl::desc("Display the version number for ld and list the linker emulations supported."));
+static cl::opt<int>
+ArgVerbose("verbose",
+           cl::init(-1),
+           cl::desc("Display the version number for ld and list the linker emulations supported."));
 
-static cl::alias
-ArgVerboseAlias("verbose",
-                cl::desc("alias for -V"),
-                cl::aliasopt(ArgVerbose));
+static cl::opt<bool>
+ArgVersion("V",
+           cl::init(false),
+           cl::desc("Display the version number for MCLinker."));
+
+static cl::opt<int>
+ArgMaxErrorNum("error-limit",
+               cl::init(-1),
+               cl::desc("limits the maximum number of erros."));
+
+static cl::opt<int>
+ArgMaxWarnNum("warning-limit",
+               cl::init(-1),
+               cl::desc("limits the maximum number of warnings."));
 
 static cl::opt<std::string>
 ArgEntry("e",
@@ -327,11 +318,116 @@
              cl::desc("Bind references within the shared library."),
              cl::init(false));
 
+static cl::opt<bool>
+ArgBgroup("Bgroup",
+          cl::desc("Info the dynamic linker to perform lookups only inside the group."),
+          cl::init(false));
+
 static cl::opt<std::string>
 ArgSOName("soname",
           cl::desc("Set internal name of shared library"),
           cl::value_desc("name"));
 
+static cl::opt<bool>
+ArgNoUndefined("no-undefined",
+               cl::desc("Do not allow unresolved references"),
+               cl::init(false));
+
+static cl::opt<bool>
+ArgAllowMulDefs("allow-multiple-definition",
+                cl::desc("Allow multiple definition"),
+                cl::init(false));
+
+static cl::opt<bool>
+ArgEhFrameHdr("eh-frame-hdr",
+              cl::desc("Request creation of \".eh_frame_hdr\" section and ELF \"PT_GNU_EH_FRAME\" segment header."),
+              cl::init(false));
+
+static cl::list<mcld::ZOption, bool, llvm::cl::parser<mcld::ZOption> >
+ArgZOptionList("z",
+               cl::ZeroOrMore,
+               cl::desc("The -z options for GNU ld compatibility."),
+               cl::value_desc("keyword"),
+               cl::Prefix);
+
+cl::opt<mcld::CodeGenFileType>
+ArgFileType("filetype", cl::init(mcld::CGFT_EXEFile),
+  cl::desc("Choose a file type (not all types are supported by all targets):"),
+  cl::values(
+       clEnumValN(mcld::CGFT_ASMFile, "asm",
+                  "Emit an assembly ('.s') file"),
+       clEnumValN(mcld::CGFT_OBJFile, "obj",
+                  "Emit a relocatable object ('.o') file"),
+       clEnumValN(mcld::CGFT_DSOFile, "dso",
+                  "Emit an dynamic shared object ('.so') file"),
+       clEnumValN(mcld::CGFT_EXEFile, "exe",
+                  "Emit a executable ('.exe') file"),
+       clEnumValN(mcld::CGFT_NULLFile, "null",
+                  "Emit nothing, for performance testing"),
+       clEnumValEnd));
+
+static cl::opt<bool>
+ArgShared("shared",
+          cl::desc("Create a shared library."),
+          cl::init(false));
+
+static cl::alias
+ArgSharedAlias("Bshareable",
+               cl::desc("alias for -shared"),
+               cl::aliasopt(ArgShared));
+
+static cl::opt<bool>
+ArgPIE("pie",
+       cl::desc("Emit a position-independent executable file"),
+       cl::init(false));
+
+static cl::opt<Reloc::Model>
+ArgRelocModel("relocation-model",
+             cl::desc("Choose relocation model"),
+             cl::init(Reloc::Default),
+             cl::values(
+               clEnumValN(Reloc::Default, "default",
+                       "Target default relocation model"),
+               clEnumValN(Reloc::Static, "static",
+                       "Non-relocatable code"),
+               clEnumValN(Reloc::PIC_, "pic",
+                       "Fully relocatable, position independent code"),
+               clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
+                       "Relocatable external references, non-relocatable code"),
+               clEnumValEnd));
+
+static cl::opt<bool>
+ArgFPIC("fPIC",
+        cl::desc("Set relocation model to pic. The same as -relocation-model=pic."),
+        cl::init(false));
+
+static cl::opt<std::string>
+ArgDyld("dynamic-linker",
+        cl::desc("Set the name of the dynamic linker."),
+        cl::value_desc("Program"));
+
+namespace color {
+enum Color {
+  Never,
+  Always,
+  Auto
+};
+} // namespace of color
+
+static cl::opt<color::Color>
+ArgColor("color",
+  cl::value_desc("WHEN"),
+  cl::desc("Surround the result strings with the marker"),
+  cl::init(color::Auto),
+  cl::values(
+    clEnumValN(color::Never, "never",
+      "do not surround result strings"),
+    clEnumValN(color::Always, "always",
+      "always surround result strings, even the output is a plain file"),
+    clEnumValN(color::Auto, "auto",
+      "surround result strings only if the output is a tty"),
+    clEnumValEnd));
+
 //===----------------------------------------------------------------------===//
 // Inputs
 static cl::list<mcld::sys::fs::Path>
@@ -440,118 +536,139 @@
 
 //===----------------------------------------------------------------------===//
 // Scripting Options
+static cl::list<std::string>
+ArgWrapList("wrap",
+            cl::ZeroOrMore,
+            cl::desc("Use a wrap function fo symbol."),
+            cl::value_desc("symbol"));
 
+static cl::list<std::string>
+ArgPortList("portable",
+            cl::ZeroOrMore,
+            cl::desc("Use a portable function fo symbol."),
+            cl::value_desc("symbol"));
 
 //===----------------------------------------------------------------------===//
 /// non-member functions
 
-// GetFileNameRoot - Helper function to get the basename of a filename.
-static inline void
-GetFileNameRoot(const std::string &pInputFilename, std::string& pFileNameRoot)
-{
-  std::string outputFilename;
-  /* *** */
-  const std::string& IFN = pInputFilename;
-  int Len = IFN.length();
-  if ((Len > 2) &&
-      IFN[Len-3] == '.' &&
-      ((IFN[Len-2] == 'b' && IFN[Len-1] == 'c') ||
-       (IFN[Len-2] == 'l' && IFN[Len-1] == 'l')))
-    pFileNameRoot = std::string(IFN.begin(), IFN.end()-3); // s/.bc/.s/
-  else
-    pFileNameRoot = std::string(IFN);
-}
-
+/// GetOutputStream - get the output stream.
 static tool_output_file *GetOutputStream(const char* pTargetName,
-                          Triple::OSType pOSType,
-                          mcld::CodeGenFileType pFileType,
-                          const std::string& pInputFilename,
-                          std::string& pOutputFilename)
+                                         Triple::OSType pOSType,
+                                         mcld::CodeGenFileType pFileType,
+                                         const mcld::sys::fs::Path& pInputFilename,
+                                         mcld::sys::fs::Path& pOutputFilename)
 {
-  // If we don't yet have an output filename, make one.
   if (pOutputFilename.empty()) {
-    if (pInputFilename == "-")
-      pOutputFilename = "-";
+    if (0 == pInputFilename.native().compare("-"))
+      pOutputFilename.assign("-");
     else {
-      GetFileNameRoot(pInputFilename, pOutputFilename);
+      switch(pFileType) {
+      case mcld::CGFT_ASMFile: {
+        if (0 == pInputFilename.native().compare("-"))
+          pOutputFilename.assign("_out");
+        else
+          pOutputFilename.assign(pInputFilename.stem().native());
 
-      switch (pFileType) {
-      case mcld::CGFT_ASMFile:
-        if (pTargetName[0] == 'c') {
-          if (pTargetName[1] == 0)
-            pOutputFilename += ".cbe.c";
-          else if (pTargetName[1] == 'p' && pTargetName[2] == 'p')
-            pOutputFilename += ".cpp";
+        if (0 == strcmp(pTargetName, "c"))
+          pOutputFilename.native() += ".cbe.c";
+        else if (0 == strcmp(pTargetName, "cpp"))
+          pOutputFilename.native() += ".cpp";
+        else
+          pOutputFilename.native() += ".s";
+      }
+      break;
+
+      case mcld::CGFT_OBJFile: {
+        if (0 == pInputFilename.native().compare("-"))
+          pOutputFilename.assign("_out");
+        else
+          pOutputFilename.assign(pInputFilename.stem().native());
+
+        if (pOSType == Triple::Win32)
+          pOutputFilename.native() += ".obj";
+        else
+          pOutputFilename.native() += ".o";
+      }
+      break;
+
+      case mcld::CGFT_DSOFile: {
+        if (Triple::Win32 == pOSType) {
+          if (0 == pInputFilename.native().compare("-"))
+            pOutputFilename.assign("_out");
           else
-            pOutputFilename += ".s";
+            pOutputFilename.assign(pInputFilename.stem().native());
+          pOutputFilename.native() += ".dll";
         }
         else
-          pOutputFilename += ".s";
-        break;
-      case mcld::CGFT_OBJFile:
-        if (pOSType == Triple::Win32)
-          pOutputFilename += ".obj";
+          pOutputFilename.assign("a.out");
+      }
+      break;
+
+      case mcld::CGFT_EXEFile: {
+        if (Triple::Win32 == pOSType) {
+          if (0 == pInputFilename.native().compare("-"))
+            pOutputFilename.assign("_out");
+          else
+            pOutputFilename.assign(pInputFilename.stem().native());
+          pOutputFilename.native() += ".exe";
+        }
         else
-          pOutputFilename += ".o";
-        break;
-      case mcld::CGFT_DSOFile:
-        if (pOSType == Triple::Win32)
-         pOutputFilename += ".dll";
-        else
-         pOutputFilename += ".so";
-        break;
-      case mcld::CGFT_ARCFile:
-         pOutputFilename += ".a";
-        break;
-      case mcld::CGFT_EXEFile:
+          pOutputFilename.assign("a.out");
+      }
+      break;
+
       case mcld::CGFT_NULLFile:
-        // do nothing
         break;
       default:
-        assert(0 && "Unknown file type");
-      }
-    }
-  }
+        llvm::report_fatal_error("Unknown output file type.\n");
+      } // end of switch
+    } // end of ! pInputFilename == "-"
+  } // end of if empty pOutputFilename
 
   // Decide if we need "binary" output.
-  bool Binary = false;
+  unsigned int fd_flags = 0x0;
   switch (pFileType) {
   default: assert(0 && "Unknown file type");
   case mcld::CGFT_ASMFile:
     break;
-  case mcld::CGFT_ARCFile:
   case mcld::CGFT_OBJFile:
   case mcld::CGFT_DSOFile:
   case mcld::CGFT_EXEFile:
   case mcld::CGFT_NULLFile:
-    Binary = true;
+    fd_flags |= raw_fd_ostream::F_Binary;
     break;
   }
 
   // Open the file.
-  std::string error;
-  unsigned OpenFlags = 0;
-  if (Binary) OpenFlags |= raw_fd_ostream::F_Binary;
-  tool_output_file *FDOut = new tool_output_file(pOutputFilename.c_str(), error,
-                                                 OpenFlags);
-  if (!error.empty()) {
-    errs() << error << '\n';
-    delete FDOut;
-    return 0;
+  std::string err_mesg;
+  tool_output_file *result_output =
+                            new tool_output_file(pOutputFilename.c_str(),
+                                                 err_mesg,
+                                                 fd_flags);
+  if (!err_mesg.empty()) {
+    errs() << err_mesg << '\n';
+    delete result_output;
+    return NULL;
   }
 
-  return FDOut;
+  return result_output;
 }
 
-static bool ProcessLinkerInputsFromCommand(mcld::SectLinkerOption &pOption) {
+static bool ShouldColorize()
+{
+   const char* term = getenv("TERM");
+   return term && (0 != strcmp(term, "dumb"));
+}
+
+static bool ProcessLinkerOptionsFromCommand(mcld::MCLDInfo& pLDInfo) {
   // -----  Set up General Options  ----- //
   // set up soname
-  pOption.info().output().setSOName(ArgSOName);
+  pLDInfo.output().setSOName(ArgSOName);
 
   // set up sysroot
   if (!ArgSysRoot.empty()) {
     if (exists(ArgSysRoot) && is_directory(ArgSysRoot))
-      pOption.info().options().setSysroot(ArgSysRoot);
+      pLDInfo.options().setSysroot(ArgSysRoot);
   }
 
   // add all search directories
@@ -559,9 +676,9 @@
   cl::list<mcld::MCLDDirectory>::iterator sdEnd = ArgSearchDirList.end();
   for (sd=ArgSearchDirList.begin(); sd!=sdEnd; ++sd) {
     if (sd->isInSysroot())
-      sd->setSysroot(pOption.info().options().sysroot());
+      sd->setSysroot(pLDInfo.options().sysroot());
     if (exists(sd->path()) && is_directory(sd->path())) {
-      pOption.info().options().directories().add(*sd);
+      pLDInfo.options().directories().add(*sd);
     }
     else {
       // FIXME: need a warning function
@@ -571,11 +688,98 @@
     }
   }
 
-  pOption.info().options().setTrace(ArgTrace);
-  pOption.info().options().setVerbose(ArgVerbose);
-  pOption.info().options().setEntry(ArgEntry);
-  pOption.info().options().setBsymbolic(ArgBsymbolic);
+  pLDInfo.options().setPIE(ArgPIE);
+  pLDInfo.options().setTrace(ArgTrace);
+  pLDInfo.options().setVerbose(ArgVerbose);
+  pLDInfo.options().setMaxErrorNum(ArgMaxErrorNum);
+  pLDInfo.options().setMaxWarnNum(ArgMaxWarnNum);
+  pLDInfo.options().setEntry(ArgEntry);
+  pLDInfo.options().setBsymbolic(ArgBsymbolic);
+  pLDInfo.options().setBgroup(ArgBgroup);
+  pLDInfo.options().setDyld(ArgDyld);
+  pLDInfo.options().setNoUndefined(ArgNoUndefined);
+  pLDInfo.options().setMulDefs(ArgAllowMulDefs);
+  pLDInfo.options().setEhFrameHdr(ArgEhFrameHdr);
 
+  // set up rename map, for --wrap
+  cl::list<std::string>::iterator wname;
+  cl::list<std::string>::iterator wnameEnd = ArgWrapList.end();
+  for (wname = ArgWrapList.begin(); wname != wnameEnd; ++wname) {
+    bool exist = false;
+
+    // add wname -> __wrap_wname
+    mcld::StringEntry<llvm::StringRef>* to_wrap =
+                    pLDInfo.scripts().renameMap().insert(*wname, exist);
+
+    std::string to_wrap_str = "__wrap_" + *wname;
+    to_wrap->setValue(to_wrap_str);
+
+    if (exist)
+      mcld::warning(mcld::diag::rewrap) << *wname << to_wrap_str;
+
+    // add __real_wname -> wname
+    std::string from_real_str = "__real_" + *wname;
+    mcld::StringEntry<llvm::StringRef>* from_real =
+             pLDInfo.scripts().renameMap().insert(from_real_str, exist);
+    from_real->setValue(*wname);
+    if (exist)
+      mcld::warning(mcld::diag::rewrap) << *wname << from_real_str;
+  } // end of for
+
+  // set up rename map, for --portable
+  cl::list<std::string>::iterator pname;
+  cl::list<std::string>::iterator pnameEnd = ArgPortList.end();
+  for (pname = ArgPortList.begin(); pname != pnameEnd; ++pname) {
+    bool exist = false;
+
+    // add pname -> pname_portable
+    mcld::StringEntry<llvm::StringRef>* to_port =
+                  pLDInfo.scripts().renameMap().insert(*pname, exist);
+
+    std::string to_port_str = *pname + "_portable";
+    to_port->setValue(to_port_str);
+
+    if (exist)
+      mcld::warning(mcld::diag::rewrap) << *pname << to_port_str;
+
+    // add __real_pname -> pname
+    std::string from_real_str = "__real_" + *pname;
+    mcld::StringEntry<llvm::StringRef>* from_real =
+             pLDInfo.scripts().renameMap().insert(from_real_str, exist);
+
+    from_real->setValue(*pname);
+    if (exist)
+      mcld::warning(mcld::diag::rewrap) << *pname << from_real_str;
+  } // end of for
+
+  // set up colorize
+  switch (ArgColor) {
+    case color::Never:
+      pLDInfo.options().setColor(false);
+    break;
+    case color::Always:
+      pLDInfo.options().setColor(true);
+    break;
+    case color::Auto:
+      bool color_option = ShouldColorize() &&
+                 llvm::sys::Process::FileDescriptorIsDisplayed(STDOUT_FILENO);
+      pLDInfo.options().setColor(color_option);
+    break;
+  }
+
+  // add -z options
+  cl::list<mcld::ZOption>::iterator zOpt;
+  cl::list<mcld::ZOption>::iterator zOptEnd = ArgZOptionList.end();
+  for (zOpt = ArgZOptionList.begin(); zOpt != zOptEnd; ++zOpt) {
+    pLDInfo.options().addZOption(*zOpt);
+  }
+
+  // -----  Set up Script Options  ----- //
+
+  return true;
+}
+
+static bool ProcessLinkerInputsFromCommand(mcld::SectLinkerOption &pOption) {
   // -----  Set up Inputs  ----- //
   // add all start-group
   cl::list<bool>::iterator sg;
@@ -685,16 +889,14 @@
     ++attr;
   }
 
-  // -----  Set up Scripting Options  ----- //
-
-  return false;
+  return true;
 }
 
 int main( int argc, char* argv[] )
 {
-
   LLVMContext &Context = getGlobalContext();
   llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
+
   // Initialize targets first, so that --version shows registered targets.
   InitializeAllTargets();
   InitializeAllAsmPrinters();
@@ -702,7 +904,9 @@
   InitializeAllTargetMCs();
   mcld::InitializeAllTargets();
   mcld::InitializeAllLinkers();
-  cl::ParseCommandLineOptions(argc, argv, "llvm MCLinker\n");
+  mcld::InitializeAllDiagnostics();
+
+  cl::ParseCommandLineOptions(argc, argv, "MCLinker\n");
 
 #ifdef ENABLE_UNITTEST
   if (UnitTest) {
@@ -713,25 +917,45 @@
   // Load the module to be compiled...
   std::auto_ptr<Module> M;
 
-  if (InputFilename.empty() && (FileType != mcld::CGFT_DSOFile)) {
-    // Read from stdin
-    InputFilename = "-";
+  // -shared
+  if (true == ArgShared) {
+    ArgFileType = mcld::CGFT_DSOFile;
   }
 
-  if (!InputFilename.empty()) {
+  // -V
+  if (ArgVersion) {
+    outs() << "MCLinker - ";
+    outs() << mcld::MCLDInfo::version();
+    outs() << "\n";
+  }
+
+  if (ArgBitcodeFilename.empty() &&
+      (mcld::CGFT_DSOFile != ArgFileType &&
+       mcld::CGFT_EXEFile != ArgFileType)) {
+    // If the file is not given, forcefully read from stdin
+    if (ArgVerbose >= 0) {
+      errs() << "** The bitcode/llvm asm file is not given. Read from stdin.\n"
+             << "** Specify input bitcode/llvm asm file by\n\n"
+             << "          llvm-mcld -dB [the bitcode/llvm asm]\n\n";
+    }
+
+    ArgBitcodeFilename.assign("-");
+  }
+
+  if (!ArgBitcodeFilename.empty()) {
     SMDiagnostic Err;
-    M.reset(ParseIRFile(InputFilename, Err, Context));
+    M.reset(ParseIRFile(ArgBitcodeFilename.native(), Err, Context));
 
     if (M.get() == 0) {
       Err.print(argv[0], errs());
       errs() << "** Failed to to the given bitcode/llvm asm file '"
-             << InputFilename << "'. **\n";
+             << ArgBitcodeFilename.native() << "'. **\n";
       return 1;
     }
-  } else {
-    // If here, output must be dynamic shared object (mcld::CGFT_DSOFile).
-
-    // Create an empty Module
+  }
+  else {
+    // If here, output must be dynamic shared object (mcld::CGFT_DSOFile) and
+    // executable file (mcld::CGFT_EXEFile).
     M.reset(new Module("Empty Module", Context));
   }
   Module &mod = *M.get();
@@ -782,9 +1006,11 @@
     std::string Err;
     TheTarget = mcld::TargetRegistry::lookupTarget(TheTriple.getTriple(), Err);
     if (TheTarget == 0) {
-      errs() << argv[0] << ": error auto-selecting target for module '"
-             << Err << "'.  Please use the -march option to explicitly "
-             << "pick a target.\n";
+      errs() << "error: auto-selecting target `" << TheTriple.getTriple()
+             << "'\n"
+             << "Please use the -march option to explicitly select a target.\n"
+             << "Example:\n"
+             << "  $ " << argv[0] << " -march=arm\n";
       return 1;
     }
   }
@@ -810,6 +1036,10 @@
   case '3': OLvl = CodeGenOpt::Aggressive; break;
   }
 
+  // set -fPIC
+  if (ArgFPIC)
+    ArgRelocModel = Reloc::PIC_;
+
   TargetOptions Options;
   Options.LessPreciseFPMADOption = EnableFPMAD;
   Options.PrintMachineCode = PrintCode;
@@ -838,21 +1068,40 @@
   std::auto_ptr<mcld::LLVMTargetMachine> target_machine(
           TheTarget->createTargetMachine(TheTriple.getTriple(),
                                          MCPU, FeaturesStr, Options,
-                                         RelocModel, CMModel, OLvl));
+                                         ArgRelocModel, CMModel, OLvl));
   assert(target_machine.get() && "Could not allocate target machine!");
   mcld::LLVMTargetMachine &TheTargetMachine = *target_machine.get();
 
   TheTargetMachine.getTM().setMCUseLoc(false);
   TheTargetMachine.getTM().setMCUseCFI(false);
 
+  // Set up mcld::outs() and mcld::errs()
+  InitializeOStreams(TheTargetMachine.getLDInfo());
+
+  // Set up MsgHandler
+  OwningPtr<mcld::DiagnosticLineInfo>
+    diag_line_info(TheTarget->createDiagnosticLineInfo(*TheTarget->get(),
+                                                       TheTriple.getTriple()));
+  OwningPtr<mcld::DiagnosticPrinter>
+    diag_printer(new mcld::TextDiagnosticPrinter(mcld::errs(),
+                                                TheTargetMachine.getLDInfo()));
+
+  mcld::InitializeDiagnosticEngine(TheTargetMachine.getLDInfo(),
+                                   diag_line_info.take(),
+                                   diag_printer.get());
+
+
   // Figure out where we are going to send the output...
   OwningPtr<tool_output_file>
   Out(GetOutputStream(TheTarget->get()->getName(),
                       TheTriple.getOS(),
-                      FileType,
-                      InputFilename,
-                      OutputFilename));
-  if (!Out) return 1;
+                      ArgFileType,
+                      ArgBitcodeFilename,
+                      ArgOutputFilename));
+  if (!Out) {
+    // FIXME: show some error message pls.
+    return 1;
+  }
 
   // Build up all of the passes that we want to do to the module.
   PassManager PM;
@@ -870,7 +1119,12 @@
   mcld::SectLinkerOption *LinkerOpt =
       new mcld::SectLinkerOption(TheTargetMachine.getLDInfo());
 
-  if (ProcessLinkerInputsFromCommand(*LinkerOpt)) {
+  if (!ProcessLinkerOptionsFromCommand(TheTargetMachine.getLDInfo())) {
+    errs() << argv[0] << ": failed to process linker options from command line!\n";
+    return 1;
+  }
+
+  if (!ProcessLinkerInputsFromCommand(*LinkerOpt)) {
     errs() << argv[0] << ": failed to process inputs from command line!\n";
     return 1;
   }
@@ -881,8 +1135,8 @@
     // Ask the target to add backend passes as necessary.
     if( TheTargetMachine.addPassesToEmitFile(PM,
                                              FOS,
-                                             OutputFilename,
-                                             FileType,
+                                             ArgOutputFilename.native(),
+                                             ArgFileType,
                                              OLvl,
                                              LinkerOpt,
                                              NoVerify)) {
@@ -903,6 +1157,16 @@
   // clean up
   delete LinkerOpt;
 
+  if (0 != diag_printer->getNumErrors()) {
+    // If we reached here, we are failing ungracefully. Run the interrupt handlers
+    // to make sure any special cleanups get done, in particular that we remove
+    // files registered with RemoveFileOnSignal.
+    llvm::sys::RunInterruptHandlers();
+    diag_printer->finish();
+    exit(1);
+  }
+
+  diag_printer->finish();
   return 0;
 }