LCOV - code coverage report
Current view: top level - lib/LibDriver - LibDriver.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 57 71 80.3 %
Date: 2017-05-14 03:40:31 Functions: 4 5 80.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- LibDriver.cpp - lib.exe-compatible driver --------------------------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : //
      10             : // Defines an interface to a lib.exe-compatible driver that also understands
      11             : // bitcode files. Used by llvm-lib and lld-link /lib.
      12             : //
      13             : //===----------------------------------------------------------------------===//
      14             : 
      15             : #include "llvm/LibDriver/LibDriver.h"
      16             : #include "llvm/ADT/STLExtras.h"
      17             : #include "llvm/Object/ArchiveWriter.h"
      18             : #include "llvm/Option/Arg.h"
      19             : #include "llvm/Option/ArgList.h"
      20             : #include "llvm/Option/Option.h"
      21             : #include "llvm/Support/CommandLine.h"
      22             : #include "llvm/Support/StringSaver.h"
      23             : #include "llvm/Support/Path.h"
      24             : #include "llvm/Support/Process.h"
      25             : #include "llvm/Support/raw_ostream.h"
      26             : 
      27             : using namespace llvm;
      28             : 
      29             : namespace {
      30             : 
      31             : enum {
      32             :   OPT_INVALID = 0,
      33             : #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11) OPT_##ID,
      34             : #include "Options.inc"
      35             : #undef OPTION
      36             : };
      37             : 
      38             : #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
      39             : #include "Options.inc"
      40             : #undef PREFIX
      41             : 
      42             : static const llvm::opt::OptTable::Info infoTable[] = {
      43             : #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10)    \
      44             :   {                                                                    \
      45             :     X1, X2, X9, X10, OPT_##ID, llvm::opt::Option::KIND##Class, X8, X7, \
      46             :     OPT_##GROUP, OPT_##ALIAS, X6                                       \
      47             :   },
      48             : #include "Options.inc"
      49             : #undef OPTION
      50             : };
      51             : 
      52          14 : class LibOptTable : public llvm::opt::OptTable {
      53             : public:
      54          28 :   LibOptTable() : OptTable(infoTable, true) {}
      55             : };
      56             : 
      57             : }
      58             : 
      59          12 : static std::string getOutputPath(llvm::opt::InputArgList *Args,
      60             :                                  const llvm::NewArchiveMember &FirstMember) {
      61          12 :   if (auto *Arg = Args->getLastArg(OPT_out))
      62          27 :     return Arg->getValue();
      63           9 :   SmallString<128> Val = StringRef(FirstMember.Buf->getBufferIdentifier());
      64           3 :   llvm::sys::path::replace_extension(Val, ".lib");
      65           6 :   return Val.str();
      66             : }
      67             : 
      68          13 : static std::vector<StringRef> getSearchPaths(llvm::opt::InputArgList *Args,
      69             :                                              StringSaver &Saver) {
      70          13 :   std::vector<StringRef> Ret;
      71             :   // Add current directory as first item of the search path.
      72          26 :   Ret.push_back("");
      73             : 
      74             :   // Add /libpath flags.
      75          44 :   for (auto *Arg : Args->filtered(OPT_libpath))
      76          15 :     Ret.push_back(Arg->getValue());
      77             : 
      78             :   // Add $LIB.
      79          26 :   Optional<std::string> EnvOpt = sys::Process::GetEnv("LIB");
      80          13 :   if (!EnvOpt.hasValue())
      81             :     return Ret;
      82           4 :   StringRef Env = Saver.save(*EnvOpt);
      83           8 :   while (!Env.empty()) {
      84           3 :     StringRef Path;
      85           9 :     std::tie(Path, Env) = Env.split(';');
      86           3 :     Ret.push_back(Path);
      87             :   }
      88             :   return Ret;
      89             : }
      90             : 
      91          14 : static Optional<std::string> findInputFile(StringRef File,
      92             :                                            ArrayRef<StringRef> Paths) {
      93          33 :   for (auto Dir : Paths) {
      94          24 :     SmallString<128> Path = Dir;
      95          76 :     sys::path::append(Path, File);
      96          38 :     if (sys::fs::exists(Path))
      97          56 :       return Path.str().str();
      98             :   }
      99             :   return Optional<std::string>();
     100             : }
     101             : 
     102          14 : int llvm::libDriverMain(llvm::ArrayRef<const char*> ArgsArr) {
     103          42 :   SmallVector<const char *, 20> NewArgs(ArgsArr.begin(), ArgsArr.end());
     104          28 :   BumpPtrAllocator Alloc;
     105          14 :   StringSaver Saver(Alloc);
     106          14 :   cl::ExpandResponseFiles(Saver, cl::TokenizeWindowsCommandLine, NewArgs);
     107          14 :   ArgsArr = NewArgs;
     108             : 
     109          28 :   LibOptTable Table;
     110             :   unsigned MissingIndex;
     111             :   unsigned MissingCount;
     112             :   llvm::opt::InputArgList Args =
     113          28 :       Table.ParseArgs(ArgsArr.slice(1), MissingIndex, MissingCount);
     114          14 :   if (MissingCount) {
     115           0 :     llvm::errs() << "missing arg value for \""
     116           0 :                  << Args.getArgString(MissingIndex) << "\", expected "
     117           0 :                  << MissingCount
     118           0 :                  << (MissingCount == 1 ? " argument.\n" : " arguments.\n");
     119           0 :     return 1;
     120             :   }
     121          42 :   for (auto *Arg : Args.filtered(OPT_UNKNOWN))
     122           0 :     llvm::errs() << "ignoring unknown argument: " << Arg->getSpelling() << "\n";
     123             : 
     124          14 :   if (!Args.hasArgNoClaim(OPT_INPUT)) {
     125             :     // No input files.  To match lib.exe, silently do nothing.
     126             :     return 0;
     127             :   }
     128             : 
     129          13 :   std::vector<StringRef> SearchPaths = getSearchPaths(&Args, Saver);
     130             : 
     131          26 :   std::vector<llvm::NewArchiveMember> Members;
     132          52 :   for (auto *Arg : Args.filtered(OPT_INPUT)) {
     133          55 :     Optional<std::string> Path = findInputFile(Arg->getValue(), SearchPaths);
     134          14 :     if (!Path.hasValue()) {
     135           0 :       llvm::errs() << Arg->getValue() << ": no such file or directory\n";
     136           1 :       return 1;
     137             :     }
     138             :     Expected<NewArchiveMember> MOrErr =
     139          41 :         NewArchiveMember::getFile(Saver.save(*Path), /*Deterministic=*/true);
     140          14 :     if (!MOrErr) {
     141           0 :       handleAllErrors(MOrErr.takeError(), [&](const llvm::ErrorInfoBase &EIB) {
     142           0 :         llvm::errs() << Arg->getValue() << ": " << EIB.message() << "\n";
     143           0 :       });
     144           1 :       return 1;
     145             :     }
     146             :     sys::fs::file_magic Magic =
     147          42 :         sys::fs::identify_magic(MOrErr->Buf->getBuffer());
     148          32 :     if (Magic != sys::fs::file_magic::coff_object &&
     149          16 :         Magic != sys::fs::file_magic::bitcode &&
     150           2 :         Magic != sys::fs::file_magic::windows_resource) {
     151           2 :       llvm::errs() << Arg->getValue()
     152           1 :                    << ": not a COFF object, bitcode or resource file\n";
     153           1 :       return 1;
     154             :     }
     155          13 :     Members.emplace_back(std::move(*MOrErr));
     156             :   }
     157             : 
     158             :   std::pair<StringRef, std::error_code> Result =
     159          24 :       llvm::writeArchive(getOutputPath(&Args, Members[0]), Members,
     160             :                          /*WriteSymtab=*/true, object::Archive::K_GNU,
     161          60 :                          /*Deterministic*/ true, Args.hasArg(OPT_llvmlibthin));
     162             : 
     163          12 :   if (Result.second) {
     164           0 :     if (Result.first.empty())
     165           0 :       Result.first = ArgsArr[0];
     166           0 :     llvm::errs() << Result.first << ": " << Result.second.message() << "\n";
     167           0 :     return 1;
     168             :   }
     169             : 
     170             :   return 0;
     171             : }

Generated by: LCOV version 1.13