LibDriver, llvm-lib: introduce.

llvm-lib is intended to be a lib.exe compatible utility that also
understands bitcode. The implementation lives in a library so that
lld can use it to implement /lib.

Differential Revision: http://reviews.llvm.org/D10297

llvm-svn: 239434
This commit is contained in:
Peter Collingbourne 2015-06-09 21:50:22 +00:00
parent f12c030f48
commit bc05163f15
16 changed files with 270 additions and 10 deletions

View File

@ -0,0 +1,24 @@
//===- llvm/LibDriver/LibDriver.h - lib.exe-compatible driver ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Defines an interface to a lib.exe-compatible driver that also understands
// bitcode files. Used by llvm-lib and lld-link2 /lib.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBDRIVER_LIBDRIVER_H
#define LLVM_LIBDRIVER_LIBDRIVER_H
namespace llvm {
int libDriverMain(int argc, const char **argv);
}
#endif

View File

@ -19,3 +19,4 @@ add_subdirectory(LineEditor)
add_subdirectory(ProfileData) add_subdirectory(ProfileData)
add_subdirectory(Fuzzer) add_subdirectory(Fuzzer)
add_subdirectory(Passes) add_subdirectory(Passes)
add_subdirectory(LibDriver)

View File

@ -17,8 +17,8 @@
[common] [common]
subdirectories = Analysis AsmParser Bitcode CodeGen DebugInfo ExecutionEngine subdirectories = Analysis AsmParser Bitcode CodeGen DebugInfo ExecutionEngine
LineEditor Linker IR IRReader LTO MC Object Option Passes ProfileData Support LibDriver LineEditor Linker IR IRReader LTO MC Object Option Passes ProfileData
TableGen Target Transforms Support TableGen Target Transforms
[component_0] [component_0]
type = Group type = Group

View File

@ -0,0 +1,8 @@
set(LLVM_TARGET_DEFINITIONS Options.td)
tablegen(LLVM Options.inc -gen-opt-parser-defs)
add_public_tablegen_target(LibOptionsTableGen)
add_llvm_library(LLVMLibDriver
LibDriver.cpp
)
add_dependencies(LLVMLibDriver LibOptionsTableGen)

View File

@ -0,0 +1,22 @@
;===- ./lib/LibDriver/LLVMBuild.txt ----------------------------*- Conf -*--===;
;
; The LLVM Compiler Infrastructure
;
; This file is distributed under the University of Illinois Open Source
; License. See LICENSE.TXT for details.
;
;===------------------------------------------------------------------------===;
;
; This is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;
[component_0]
type = Library
name = LibDriver
parent = Libraries
required_libraries = Object Option Support

View File

@ -0,0 +1,133 @@
//===- LibDriver.cpp - lib.exe-compatible driver --------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Defines an interface to a lib.exe-compatible driver that also understands
// bitcode files. Used by llvm-lib and lld-link2 /lib.
//
//===----------------------------------------------------------------------===//
#include "llvm/LibDriver/LibDriver.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Object/ArchiveWriter.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
namespace {
enum {
OPT_INVALID = 0,
#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11) OPT_##ID,
#include "Options.inc"
#undef OPTION
};
#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
#include "Options.inc"
#undef PREFIX
static const llvm::opt::OptTable::Info infoTable[] = {
#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \
{ \
X1, X2, X9, X10, OPT_##ID, llvm::opt::Option::KIND##Class, X8, X7, \
OPT_##GROUP, OPT_##ALIAS, X6 \
},
#include "Options.inc"
#undef OPTION
};
class LibOptTable : public llvm::opt::OptTable {
public:
LibOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable), true) {}
};
}
static std::string getOutputPath(llvm::opt::InputArgList *Args) {
if (auto *Arg = Args->getLastArg(OPT_out))
return Arg->getValue();
for (auto *Arg : Args->filtered(OPT_INPUT)) {
if (!StringRef(Arg->getValue()).endswith_lower(".obj"))
continue;
SmallString<128> Val = StringRef(Arg->getValue());
llvm::sys::path::replace_extension(Val, ".lib");
return Val.str();
}
llvm_unreachable("internal error");
}
namespace {
// FIXME: Should re-use StringSaver from lld.
class StrDupSaver : public cl::StringSaver {
std::vector<char *> Dups;
public:
~StrDupSaver() override {
for (std::vector<char *>::iterator I = Dups.begin(), E = Dups.end(); I != E;
++I) {
char *Dup = *I;
free(Dup);
}
}
const char *SaveString(const char *Str) override {
char *Dup = strdup(Str);
Dups.push_back(Dup);
return Dup;
}
};
}
int llvm::libDriverMain(int Argc, const char **Argv) {
SmallVector<const char *, 20> NewArgv(Argv, Argv + Argc);
StrDupSaver Saver;
cl::ExpandResponseFiles(Saver, cl::TokenizeWindowsCommandLine, NewArgv);
Argv = &NewArgv[0];
Argc = static_cast<int>(NewArgv.size());
LibOptTable Table;
unsigned MissingIndex;
unsigned MissingCount;
std::unique_ptr<llvm::opt::InputArgList> Args(
Table.ParseArgs(&Argv[1], &Argv[Argc], MissingIndex, MissingCount));
if (MissingCount) {
llvm::errs() << "missing arg value for \""
<< Args->getArgString(MissingIndex)
<< "\", expected " << MissingCount
<< (MissingCount == 1 ? " argument.\n" : " arguments.\n");
return 1;
}
for (auto *Arg : Args->filtered(OPT_UNKNOWN))
llvm::errs() << "ignoring unknown argument: " << Arg->getSpelling() << "\n";
if (Args->filtered_begin(OPT_INPUT) == Args->filtered_end()) {
llvm::errs() << "no input files.\n";
return 1;
}
std::vector<llvm::NewArchiveIterator> Members;
for (auto *Arg : Args->filtered(OPT_INPUT))
Members.emplace_back(Arg->getValue(),
llvm::sys::path::filename(Arg->getValue()));
std::pair<StringRef, std::error_code> Result = llvm::writeArchive(
getOutputPath(Args.get()), Members, /*WriteSymtab=*/true);
if (Result.second) {
if (Result.first.empty())
Result.first = Argv[0];
llvm::errs() << Result.first << ": " << Result.second.message() << "\n";
return 1;
}
return 0;
}

View File

@ -0,0 +1,20 @@
##===- lib/LibDriver/Makefile ------------------------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
LEVEL = ../..
LIBRARYNAME = LLVMLibDriver
BUILD_ARCHIVE := 1
BUILT_SOURCES = Options.inc
TABLEGEN_INC_FILES_COMMON = 1
include $(LEVEL)/Makefile.common
$(ObjDir)/Options.inc.tmp : Options.td $(LLVM_TBLGEN) $(ObjDir)/.dir
$(Echo) "Building lib Driver Option tables with tblgen"
$(Verb) $(LLVMTableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $<

View File

@ -0,0 +1,17 @@
include "llvm/Option/OptParser.td"
// lib.exe accepts options starting with either a dash or a slash.
// Flag that takes no arguments.
class F<string name> : Flag<["/", "-", "-?"], name>;
// Flag that takes one argument after ":".
class P<string name, string help> :
Joined<["/", "-", "-?"], name#":">, HelpText<help>;
def out : P<"out", "Path to file to write output">;
//==============================================================================
// The flags below do nothing. They are defined only for lib.exe compatibility.
//==============================================================================
def nologo : F<"nologo">;

View File

@ -12,6 +12,6 @@ include $(LEVEL)/Makefile.config
PARALLEL_DIRS := IR AsmParser Bitcode Analysis Transforms CodeGen Target \ PARALLEL_DIRS := IR AsmParser Bitcode Analysis Transforms CodeGen Target \
ExecutionEngine Linker LTO MC Object Option DebugInfo \ ExecutionEngine Linker LTO MC Object Option DebugInfo \
IRReader LineEditor ProfileData Passes IRReader LineEditor ProfileData Passes LibDriver
include $(LEVEL)/Makefile.common include $(LEVEL)/Makefile.common

View File

@ -34,6 +34,7 @@ set(LLVM_TEST_DEPENDS
llvm-dsymutil llvm-dsymutil
llvm-dwarfdump llvm-dwarfdump
llvm-extract llvm-extract
llvm-lib
llvm-link llvm-link
llvm-lto llvm-lto
llvm-mc llvm-mc

View File

@ -24,6 +24,15 @@ RUN: rm -f %t2
RUN: llvm-ar rcs %t2 %t1 RUN: llvm-ar rcs %t2 %t1
RUN: llvm-nm %t2 | FileCheck %s -check-prefix BITCODE RUN: llvm-nm %t2 | FileCheck %s -check-prefix BITCODE
RUN: rm -f %t2
RUN: llvm-lib /out:%t2 %t1
RUN: llvm-nm %t2 | FileCheck %s -check-prefix BITCODE
RUN: rm -f %t2
RUN: echo /out:%t2 %t1 > %t.rsp
RUN: llvm-lib @%t.rsp
RUN: llvm-nm %t2 | FileCheck %s -check-prefix BITCODE
BITCODE: U SomeOtherFunction BITCODE: U SomeOtherFunction
BITCODE-NEXT: T main BITCODE-NEXT: T main
BITCODE-NEXT: U puts BITCODE-NEXT: U puts

View File

@ -236,6 +236,7 @@ for pattern in [r"\bbugpoint\b(?!-)",
r"\bllvm-dwarfdump\b", r"\bllvm-dwarfdump\b",
r"\bllvm-extract\b", r"\bllvm-extract\b",
r"\bllvm-go\b", r"\bllvm-go\b",
r"\bllvm-lib\b",
r"\bllvm-link\b", r"\bllvm-link\b",
r"\bllvm-lto\b", r"\bllvm-lto\b",
r"\bllvm-mc\b", r"\bllvm-mc\b",

View File

@ -1,6 +1,7 @@
set(LLVM_LINK_COMPONENTS set(LLVM_LINK_COMPONENTS
${LLVM_TARGETS_TO_BUILD} ${LLVM_TARGETS_TO_BUILD}
Core Core
LibDriver
Object Object
Support Support
) )
@ -26,4 +27,13 @@ add_custom_command(OUTPUT ${llvm_ranlib}
add_custom_target(llvm-ranlib ALL DEPENDS ${llvm_ranlib}) add_custom_target(llvm-ranlib ALL DEPENDS ${llvm_ranlib})
set_target_properties(llvm-ranlib PROPERTIES FOLDER Tools) set_target_properties(llvm-ranlib PROPERTIES FOLDER Tools)
set(llvm_lib "${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-lib${CMAKE_EXECUTABLE_SUFFIX}")
add_custom_command(OUTPUT ${llvm_lib}
COMMAND ${CMAKE_COMMAND} -E ${LLVM_LINK_OR_COPY} "${llvm_ar_binary}" "${llvm_lib}"
DEPENDS llvm-ar)
add_custom_target(llvm-lib ALL DEPENDS ${llvm_lib})
set_target_properties(llvm-lib PROPERTIES FOLDER Tools)
install(SCRIPT install_symlink.cmake -DCMAKE_INSTALL_PREFIX=\"${CMAKE_INSTALL_PREFIX}\") install(SCRIPT install_symlink.cmake -DCMAKE_INSTALL_PREFIX=\"${CMAKE_INSTALL_PREFIX}\")

View File

@ -10,9 +10,12 @@
LEVEL := ../.. LEVEL := ../..
TOOLNAME := llvm-ar TOOLNAME := llvm-ar
TOOLALIAS = llvm-ranlib TOOLALIAS = llvm-ranlib
LINK_COMPONENTS := all-targets bitreader support object LINK_COMPONENTS := all-targets bitreader libdriver support object
# This tool has no plugins, optimize startup time. # This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS := 1 TOOL_NO_EXPORTS := 1
include $(LEVEL)/Makefile.common include $(LEVEL)/Makefile.common
all-local::
$(Verb) $(AliasTool) $(notdir $(ToolBuildPath)) $(ToolDir)/llvm-lib$(EXEEXT)

View File

@ -23,3 +23,9 @@ message("Creating llvm-ranlib")
execute_process( execute_process(
COMMAND "${CMAKE_COMMAND}" -E ${LINK_OR_COPY} "llvm-ar${EXECUTABLE_SUFFIX}" "llvm-ranlib${EXECUTABLE_SUFFIX}" COMMAND "${CMAKE_COMMAND}" -E ${LINK_OR_COPY} "llvm-ar${EXECUTABLE_SUFFIX}" "llvm-ranlib${EXECUTABLE_SUFFIX}"
WORKING_DIRECTORY "${bindir}") WORKING_DIRECTORY "${bindir}")
message("Creating llvm-lib")
execute_process(
COMMAND "${CMAKE_COMMAND}" -E ${LINK_OR_COPY} "llvm-ar${EXECUTABLE_SUFFIX}" "llvm-lib${EXECUTABLE_SUFFIX}"
WORKING_DIRECTORY "${bindir}")

View File

@ -15,6 +15,7 @@
#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/StringSwitch.h"
#include "llvm/IR/LLVMContext.h" #include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/LibDriver/LibDriver.h"
#include "llvm/Object/Archive.h" #include "llvm/Object/Archive.h"
#include "llvm/Object/ArchiveWriter.h" #include "llvm/Object/ArchiveWriter.h"
#include "llvm/Object/ObjectFile.h" #include "llvm/Object/ObjectFile.h"
@ -716,6 +717,15 @@ int main(int argc, char **argv) {
PrettyStackTraceProgram X(argc, argv); PrettyStackTraceProgram X(argc, argv);
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
llvm::InitializeAllTargetInfos();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmParsers();
StringRef Stem = sys::path::stem(ToolName);
if (Stem.find("ranlib") == StringRef::npos &&
Stem.find("lib") != StringRef::npos)
return libDriverMain(argc, const_cast<const char **>(argv));
// Have the command line options parsed and handle things // Have the command line options parsed and handle things
// like --help and --version. // like --help and --version.
cl::ParseCommandLineOptions(argc, argv, cl::ParseCommandLineOptions(argc, argv,
@ -723,14 +733,9 @@ int main(int argc, char **argv) {
" This program archives bitcode files into single libraries\n" " This program archives bitcode files into single libraries\n"
); );
llvm::InitializeAllTargetInfos();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmParsers();
StringRef Stem = sys::path::stem(ToolName);
if (Stem.find("ar") != StringRef::npos) if (Stem.find("ar") != StringRef::npos)
return ar_main(); return ar_main();
if (Stem.find("ranlib") != StringRef::npos) if (Stem.find("ranlib") != StringRef::npos)
return ranlib_main(); return ranlib_main();
fail("Not ranlib or ar!"); fail("Not ranlib, ar or lib!");
} }