MCLinker upstream commit 0459e386785c.
Change-Id: Ide6790f5a354b7fcc03d812d6c8cf43b1e309ba3
diff --git a/tools/llvm-mcld/llvm-mcld.cpp b/tools/llvm-mcld/llvm-mcld.cpp
index f4201d2..28a18c6 100644
--- a/tools/llvm-mcld/llvm-mcld.cpp
+++ b/tools/llvm-mcld/llvm-mcld.cpp
@@ -6,20 +6,21 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+#include <mcld/Module.h>
+#include <mcld/LinkerConfig.h>
#include <mcld/Target/TargetMachine.h>
#include <mcld/Support/TargetSelect.h>
#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/FileHandle.h>
#include <mcld/Support/FileSystem.h>
#include <mcld/Support/raw_ostream.h>
+#include <mcld/Support/ToolOutputFile.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>
#include <llvm/PassManager.h>
@@ -36,11 +37,28 @@
#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>
+#if defined(HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#if defined(_MSC_VER)
+#include <io.h>
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+# define STDOUT_FILENO 1
+#endif
+#ifndef STDERR_FILENO
+# define STDERR_FILENO 2
+#endif
+#endif
+
+
using namespace llvm;
#ifdef ENABLE_UNITTEST
@@ -230,19 +248,25 @@
//===----------------------------------------------------------------------===//
// Command Line Options
// There are four kinds of command line options:
-// 1. input, (may be a file, such as -m and /tmp/XXXX.o.)
-// 2. attribute of inputs, (describing the attributes of inputs, such as
-// --as-needed and --whole-archive. usually be positional.)
-// 3. scripting options, (represent a subset of link scripting language, such
-// as --defsym.)
-// 4. and general options. (the rest of options)
+// 1. Bitcode option. Used to represent a bitcode.
+// 2. Attribute options. Attributes describes the input file after them. For
+// example, --as-needed affects the input file after this option. Attribute
+// options are not attributes. Attribute options are the options that is
+// used to define a legal attribute.
+// 3. Scripting options, Used to represent a subset of link scripting
+// language, such as --defsym.
+// 4. General options. (the rest of options)
//===----------------------------------------------------------------------===//
-// General Options
+// Bitcode 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"));
+//===----------------------------------------------------------------------===//
+// General Options
+//===----------------------------------------------------------------------===//
static cl::opt<mcld::sys::fs::Path, false, llvm::cl::parser<mcld::sys::fs::Path> >
ArgOutputFilename("o",
cl::desc("Output filename"),
@@ -259,7 +283,7 @@
cl::value_desc("directory"),
cl::ValueRequired);
-static cl::list<mcld::MCLDDirectory, bool, llvm::cl::parser<mcld::MCLDDirectory> >
+static cl::list<std::string>
ArgSearchDirList("L",
cl::ZeroOrMore,
cl::desc("Add path searchdir to the list of paths that ld will search for archive libraries and ld control scripts."),
@@ -379,6 +403,16 @@
cl::desc("Emit a position-independent executable file"),
cl::init(false));
+static cl::opt<bool>
+ArgRelocatable("relocatable",
+ cl::desc("Generate relocatable output"),
+ cl::init(false));
+
+static cl::alias
+ArgRelocatableAlias("r",
+ cl::desc("alias for --relocatable"),
+ cl::aliasopt(ArgRelocatable));
+
static cl::opt<Reloc::Model>
ArgRelocModel("relocation-model",
cl::desc("Choose relocation model"),
@@ -401,6 +435,7 @@
static cl::opt<std::string>
ArgDyld("dynamic-linker",
+ cl::ZeroOrMore,
cl::desc("Set the name of the dynamic linker."),
cl::value_desc("Program"));
@@ -426,114 +461,154 @@
"surround result strings only if the output is a tty"),
clEnumValEnd));
-//===----------------------------------------------------------------------===//
-// Inputs
-static cl::list<mcld::sys::fs::Path>
-ArgInputObjectFiles(cl::Positional,
- cl::desc("[input object files]"),
- cl::ZeroOrMore);
+/// @{
+/// @name FIXME: begin of unsupported options
+/// @}
+static cl::opt<bool>
+ArgGCSections("gc-sections",
+ cl::desc("Enable garbage collection of unused input sections."),
+ cl::init(false));
+
+static cl::opt<bool>
+ArgNoGCSections("no-gc-sections",
+ cl::desc("disable garbage collection of unused input sections."),
+ cl::init(false));
+
+namespace icf {
+enum Mode {
+ None,
+ All,
+ Safe
+};
+} // namespace of icf
+
+static cl::opt<icf::Mode>
+ArgICF("icf",
+ cl::desc("Identical Code Folding"),
+ cl::init(icf::None),
+ cl::values(
+ clEnumValN(icf::None, "none",
+ "do not perform cold folding"),
+ clEnumValN(icf::All, "all",
+ "always preform cold folding"),
+ clEnumValN(icf::Safe, "safe",
+ "Folds ctors, dtors and functions whose pointers are definitely not taken."),
+ clEnumValEnd));
+
+// FIXME: add this to target options?
+static cl::opt<bool>
+ArgFIXCA8("fix-cortex-a8",
+ cl::desc("Enable Cortex-A8 Thumb-2 branch erratum fix"),
+ cl::init(false));
+
+static cl::opt<bool>
+ArgDiscardLocals("discard-locals",
+ cl::desc("Delete all temporary local symbols."),
+ cl::init(false));
+
+static cl::alias
+ArgDiscardLocalsAlias("X",
+ cl::desc("alias for --discard-locals"),
+ cl::aliasopt(ArgDiscardLocals));
+
+static cl::opt<bool>
+ArgDiscardAll("discard-all",
+ cl::desc("Delete all local symbols."),
+ cl::init(false));
+
+static cl::alias
+ArgDiscardAllAlias("x",
+ cl::desc("alias for --discard-all"),
+ cl::aliasopt(ArgDiscardAll));
+
+static cl::opt<bool>
+ArgNMagic("nmagic",
+ cl::desc("Do not page align data"),
+ cl::init(false));
+
+static cl::alias
+ArgNMagicAlias("n",
+ cl::desc("alias for --nmagic"),
+ cl::aliasopt(ArgNMagic));
+
+static cl::opt<bool>
+ArgOMagic("omagic",
+ cl::desc("Do not page align data, do not make text readonly"),
+ cl::init(false));
+
+static cl::alias
+ArgOMagicAlias("N",
+ cl::desc("alias for --omagic"),
+ cl::aliasopt(ArgOMagic));
+
+static cl::opt<bool>
+ArgStripDebug("strip-debug",
+ cl::desc("Omit debugger symbol information from the output file."),
+ cl::init(false));
+
+static cl::alias
+ArgStripDebugAlias("S",
+ cl::desc("alias for --strip-debug"),
+ cl::aliasopt(ArgStripDebug));
+
+static cl::opt<bool>
+ArgExportDynamic("export-dynamic",
+ cl::desc("Export all dynamic symbols"),
+ cl::init(false));
+
+static cl::alias
+ArgExportDynamicAlias("E",
+ cl::desc("alias for --export-dynamic"),
+ cl::aliasopt(ArgExportDynamic));
+
+static cl::opt<std::string>
+ArgEmulation("m",
+ cl::desc("Set GNU linker emulation"),
+ cl::value_desc("emulation"));
+
+static cl::opt<std::string>
+ArgRuntimePath("rpath",
+ cl::desc("Add a directory to the runtime library search path"),
+ cl::value_desc("dir"));
+
+static cl::opt<std::string>
+ArgRuntimePathLink("rpath-link",
+ cl::desc("Add a directory to the link time library search path"),
+ cl::value_desc("dir"));
static cl::list<std::string>
-ArgNameSpecList("l",
- cl::ZeroOrMore,
- cl::desc("Add the archive or object file specified by namespec to the list of files to link."),
- cl::value_desc("namespec"),
- cl::Prefix);
+ArgExcludeLIBS("exclude-libs",
+ cl::CommaSeparated,
+ cl::desc("Exclude libraries from automatic export"),
+ cl::value_desc("lib1,lib2,..."));
+
+static cl::opt<std::string>
+ArgBuildID("build-id",
+ cl::desc("Request creation of \".note.gnu.build-id\" ELF note section."),
+ cl::value_desc("style"));
+
+static cl::opt<std::string>
+ArgForceUndefined("u",
+ cl::desc("Force symbol to be undefined in the output file"),
+ cl::value_desc("symbol"));
static cl::alias
-ArgNameSpecListAlias("library",
- cl::desc("alias for -l"),
- cl::aliasopt(ArgNameSpecList));
+ArgForceUndefinedAlias("undefined",
+ cl::desc("alias for -u"),
+ cl::aliasopt(ArgForceUndefined));
-static cl::list<bool>
-ArgStartGroupList("start-group",
- cl::ValueDisallowed,
- cl::desc("start to record a group of archives"));
+/// @{
+/// @name FIXME: end of unsupported options
+/// @}
-static cl::alias
-ArgStartGroupListAlias("(",
- cl::desc("alias for --start-group"),
- cl::aliasopt(ArgStartGroupList));
-
-static cl::list<bool>
-ArgEndGroupList("end-group",
- cl::ValueDisallowed,
- cl::desc("stop recording a group of archives"));
-
-static cl::alias
-ArgEndGroupListAlias(")",
- cl::desc("alias for --end-group"),
- cl::aliasopt(ArgEndGroupList));
-
-//===----------------------------------------------------------------------===//
-// Attributes of Inputs
-static cl::list<bool>
-ArgWholeArchiveList("whole-archive",
- cl::ValueDisallowed,
- cl::desc("For each archive mentioned on the command line after the --whole-archive option, include all object files in the archive."));
-
-static cl::list<bool>
-ArgNoWholeArchiveList("no-whole-archive",
- cl::ValueDisallowed,
- cl::desc("Turn off the effect of the --whole-archive option for subsequent archive files."));
-
-static cl::list<bool>
-ArgAsNeededList("as-needed",
- cl::ValueDisallowed,
- cl::desc("This option affects ELF DT_NEEDED tags for dynamic libraries mentioned on the command line after the --as-needed option."));
-
-static cl::list<bool>
-ArgNoAsNeededList("no-as-needed",
- cl::ValueDisallowed,
- cl::desc("Turn off the effect of the --as-needed option for subsequent dynamic libraries"));
-
-static cl::list<bool>
-ArgAddNeededList("add-needed",
- cl::ValueDisallowed,
- cl::desc("--add-needed causes DT_NEEDED tags are always emitted for those libraries from DT_NEEDED tags. This is the default behavior."));
-
-static cl::list<bool>
-ArgNoAddNeededList("no-add-needed",
- cl::ValueDisallowed,
- cl::desc("--no-add-needed causes DT_NEEDED tags will never be emitted for those libraries from DT_NEEDED tags"));
-
-static cl::list<bool>
-ArgBDynamicList("Bdynamic",
- cl::ValueDisallowed,
- cl::desc("Link against dynamic library"));
-
-static cl::alias
-ArgBDynamicListAlias1("dy",
- cl::desc("alias for --Bdynamic"),
- cl::aliasopt(ArgBDynamicList));
-
-static cl::alias
-ArgBDynamicListAlias2("call_shared",
- cl::desc("alias for --Bdynamic"),
- cl::aliasopt(ArgBDynamicList));
-
-static cl::list<bool>
-ArgBStaticList("Bstatic",
- cl::ValueDisallowed,
- cl::desc("Link against static library"));
-
-static cl::alias
-ArgBStaticListAlias1("dn",
- cl::desc("alias for --Bstatic"),
- cl::aliasopt(ArgBStaticList));
-
-static cl::alias
-ArgBStaticListAlias2("static",
- cl::desc("alias for --Bstatic"),
- cl::aliasopt(ArgBStaticList));
-
-static cl::alias
-ArgBStaticListAlias3("non_shared",
- cl::desc("alias for --Bstatic"),
- cl::aliasopt(ArgBStaticList));
+static cl::opt<bool>
+ArgWarnSharedTextrel("warn-shared-textrel",
+ cl::desc("Warn if adding DT_TEXTREL in a shared object."),
+ cl::init(false));
//===----------------------------------------------------------------------===//
// Scripting Options
+//===----------------------------------------------------------------------===//
static cl::list<std::string>
ArgWrapList("wrap",
cl::ZeroOrMore,
@@ -546,15 +621,37 @@
cl::desc("Use a portable function fo symbol."),
cl::value_desc("symbol"));
-//===----------------------------------------------------------------------===//
-/// non-member functions
+static cl::list<std::string>
+ArgAddressMapList("section-start",
+ cl::ZeroOrMore,
+ cl::desc("Locate a output section at the given absolute address"),
+ cl::value_desc("Set address of section"),
+ cl::Prefix);
+static cl::opt<unsigned long long>
+ArgBssSegAddr("Tbss",
+ cl::desc("Set the address of the bss segment"),
+ cl::init(-1U));
+
+static cl::opt<unsigned long long>
+ArgDataSegAddr("Tdata",
+ cl::desc("Set the address of the data segment"),
+ cl::init(-1U));
+
+static cl::opt<unsigned long long>
+ArgTextSegAddr("Ttext",
+ cl::desc("Set the address of the text segment"),
+ cl::init(-1U));
+
+//===----------------------------------------------------------------------===//
+// non-member functions
+//===----------------------------------------------------------------------===//
/// GetOutputStream - get the output stream.
-static tool_output_file *GetOutputStream(const char* pTargetName,
- Triple::OSType pOSType,
- mcld::CodeGenFileType pFileType,
- const mcld::sys::fs::Path& pInputFilename,
- mcld::sys::fs::Path& pOutputFilename)
+static mcld::ToolOutputFile *GetOutputStream(const char* pTargetName,
+ Triple::OSType pOSType,
+ mcld::CodeGenFileType pFileType,
+ const mcld::sys::fs::Path& pInputFilename,
+ mcld::sys::fs::Path& pOutputFilename)
{
if (pOutputFilename.empty()) {
if (0 == pInputFilename.native().compare("-"))
@@ -589,6 +686,19 @@
}
break;
+ case mcld::CGFT_PARTIAL: {
+ if (Triple::Win32 == pOSType) {
+ if (0 == pInputFilename.native().compare("-"))
+ pOutputFilename.assign("_out");
+ else
+ pOutputFilename.assign(pInputFilename.stem().native());
+ pOutputFilename.native() += ".obj";
+ }
+ else
+ pOutputFilename.assign("a.out");
+ }
+ break;
+
case mcld::CGFT_DSOFile: {
if (Triple::Win32 == pOSType) {
if (0 == pInputFilename.native().compare("-"))
@@ -623,31 +733,28 @@
} // end of ! pInputFilename == "-"
} // end of if empty pOutputFilename
- // Decide if we need "binary" output.
- unsigned int fd_flags = 0x0;
+ mcld::FileHandle::Permission permission;
switch (pFileType) {
default: assert(0 && "Unknown file type");
case mcld::CGFT_ASMFile:
- break;
case mcld::CGFT_OBJFile:
+ case mcld::CGFT_PARTIAL:
+ permission = 0644;
+ break;
case mcld::CGFT_DSOFile:
case mcld::CGFT_EXEFile:
case mcld::CGFT_NULLFile:
- fd_flags |= raw_fd_ostream::F_Binary;
+ permission = 0755;
break;
}
// Open the file.
- 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;
- }
+ mcld::ToolOutputFile* result_output =
+ new mcld::ToolOutputFile(pOutputFilename,
+ mcld::FileHandle::ReadWrite |
+ mcld::FileHandle::Create |
+ mcld::FileHandle::Truncate,
+ permission);
return result_output;
}
@@ -658,46 +765,79 @@
return term && (0 != strcmp(term, "dumb"));
}
-static bool ProcessLinkerOptionsFromCommand(mcld::MCLDInfo& pLDInfo) {
+static bool ProcessLinkerOptionsFromCommand(mcld::LinkerConfig& pConfig) {
// ----- Set up General Options ----- //
+ // set up colorize
+ switch (ArgColor) {
+ case color::Never:
+ pConfig.options().setColor(false);
+ break;
+ case color::Always:
+ pConfig.options().setColor(true);
+ break;
+ case color::Auto:
+ bool color_option = ShouldColorize() &&
+ llvm::sys::Process::FileDescriptorIsDisplayed(STDOUT_FILENO);
+ pConfig.options().setColor(color_option);
+ break;
+ }
+
+ mcld::outs().setColor(pConfig.options().color());
+ mcld::errs().setColor(pConfig.options().color());
+
// set up soname
- pLDInfo.output().setSOName(ArgSOName);
+ pConfig.options().setSOName(ArgSOName);
+
+ // -shared or -pie
+ if (true == ArgShared || true == ArgPIE) {
+ ArgFileType = mcld::CGFT_DSOFile;
+ }
+ else if (true == ArgRelocatable) {
+ ArgFileType = mcld::CGFT_PARTIAL;
+ }
+
+ // -V
+ if (ArgVersion) {
+ mcld::outs() << "MCLinker - "
+ << mcld::LinkerConfig::version()
+ << "\n";
+ }
// set up sysroot
if (!ArgSysRoot.empty()) {
if (exists(ArgSysRoot) && is_directory(ArgSysRoot))
- pLDInfo.options().setSysroot(ArgSysRoot);
+ pConfig.options().setSysroot(ArgSysRoot);
}
// add all search directories
- cl::list<mcld::MCLDDirectory>::iterator sd;
- cl::list<mcld::MCLDDirectory>::iterator sdEnd = ArgSearchDirList.end();
+ cl::list<std::string>::iterator sd;
+ cl::list<std::string>::iterator sdEnd = ArgSearchDirList.end();
for (sd=ArgSearchDirList.begin(); sd!=sdEnd; ++sd) {
- if (sd->isInSysroot())
- sd->setSysroot(pLDInfo.options().sysroot());
- if (exists(sd->path()) && is_directory(sd->path())) {
- pLDInfo.options().directories().add(*sd);
- }
- else {
+ if (!pConfig.options().directories().insert(*sd)) {
// FIXME: need a warning function
errs() << "WARNING: can not open search directory `-L"
- << sd->name()
+ << *sd
<< "'.\n";
}
}
- 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);
+ pConfig.options().setPIE(ArgPIE);
+ pConfig.options().setTrace(ArgTrace);
+ pConfig.options().setVerbose(ArgVerbose);
+ pConfig.options().setMaxErrorNum(ArgMaxErrorNum);
+ pConfig.options().setMaxWarnNum(ArgMaxWarnNum);
+ pConfig.options().setEntry(ArgEntry);
+ pConfig.options().setBsymbolic(ArgBsymbolic);
+ pConfig.options().setBgroup(ArgBgroup);
+ pConfig.options().setDyld(ArgDyld);
+ pConfig.options().setNoUndefined(ArgNoUndefined);
+ pConfig.options().setMulDefs(ArgAllowMulDefs);
+ pConfig.options().setEhFrameHdr(ArgEhFrameHdr);
+ pConfig.options().setNMagic(ArgNMagic);
+ pConfig.options().setOMagic(ArgOMagic);
+ pConfig.options().setStripDebug(ArgStripDebug);
+ pConfig.options().setExportDynamic(ArgExportDynamic);
+ pConfig.options().setWarnSharedTextrel(ArgWarnSharedTextrel);
// set up rename map, for --wrap
cl::list<std::string>::iterator wname;
@@ -707,7 +847,7 @@
// add wname -> __wrap_wname
mcld::StringEntry<llvm::StringRef>* to_wrap =
- pLDInfo.scripts().renameMap().insert(*wname, exist);
+ pConfig.scripts().renameMap().insert(*wname, exist);
std::string to_wrap_str = "__wrap_" + *wname;
to_wrap->setValue(to_wrap_str);
@@ -718,7 +858,7 @@
// 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);
+ pConfig.scripts().renameMap().insert(from_real_str, exist);
from_real->setValue(*wname);
if (exist)
mcld::warning(mcld::diag::rewrap) << *wname << from_real_str;
@@ -732,7 +872,7 @@
// add pname -> pname_portable
mcld::StringEntry<llvm::StringRef>* to_port =
- pLDInfo.scripts().renameMap().insert(*pname, exist);
+ pConfig.scripts().renameMap().insert(*pname, exist);
std::string to_port_str = *pname + "_portable";
to_port->setValue(to_port_str);
@@ -743,154 +883,88 @@
// 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);
+ pConfig.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);
+ pConfig.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;
- cl::list<bool>::iterator sgEnd = ArgStartGroupList.end();
- for (sg=ArgStartGroupList.begin(); sg!=sgEnd; ++sg) {
- // calculate position
- pOption.appendOption(new mcld::StartGroupOption(
- ArgStartGroupList.getPosition(sg-ArgStartGroupList.begin())));
+ if (ArgGCSections) {
+ mcld::warning(mcld::diag::warn_unsupported_option) << ArgGCSections.ArgStr;
}
- // add all end-group
- cl::list<bool>::iterator eg;
- cl::list<bool>::iterator egEnd = ArgEndGroupList.end();
- for (eg=ArgEndGroupList.begin(); eg!=egEnd; ++eg) {
- // calculate position
- pOption.appendOption(new mcld::EndGroupOption(
- ArgEndGroupList.getPosition(eg-ArgEndGroupList.begin())));
+ // set up icf mode
+ switch (ArgICF) {
+ case icf::None:
+ break;
+ case icf::All:
+ case icf::Safe:
+ default:
+ mcld::warning(mcld::diag::warn_unsupported_option) << ArgICF.ArgStr;
+ break;
}
- // add all namespecs
- cl::list<std::string>::iterator ns;
- cl::list<std::string>::iterator nsEnd = ArgNameSpecList.end();
- for (ns=ArgNameSpecList.begin(); ns!=nsEnd; ++ns) {
- // calculate position
- pOption.appendOption(new mcld::NamespecOption(
- ArgNameSpecList.getPosition(ns-ArgNameSpecList.begin()),
- *ns));
+ if (ArgFIXCA8) {
+ mcld::warning(mcld::diag::warn_unsupported_option) << ArgFIXCA8.ArgStr;
}
- // add all object files
- cl::list<mcld::sys::fs::Path>::iterator obj;
- cl::list<mcld::sys::fs::Path>::iterator objEnd = ArgInputObjectFiles.end();
- for (obj=ArgInputObjectFiles.begin(); obj!=objEnd; ++obj) {
- // calculate position
- pOption.appendOption(new mcld::InputFileOption(
- ArgInputObjectFiles.getPosition(obj-ArgInputObjectFiles.begin()),
- *obj));
+ if (ArgDiscardLocals) {
+ mcld::warning(mcld::diag::warn_unsupported_option) << ArgDiscardLocals.ArgStr;
}
- // ----- Set up Attributes of Inputs ----- //
- // --whole-archive
- cl::list<bool>::iterator attr = ArgWholeArchiveList.begin();
- cl::list<bool>::iterator attrEnd = ArgWholeArchiveList.end();
- for (; attr!=attrEnd; ++attr) {
- pOption.appendOption(new mcld::WholeArchiveOption(
- ArgWholeArchiveList.getPosition(attr-ArgWholeArchiveList.begin())));
+ if (ArgDiscardAll) {
+ mcld::warning(mcld::diag::warn_unsupported_option) << ArgDiscardAll.ArgStr;
}
- // --no-whole-archive
- attr = ArgNoWholeArchiveList.begin();
- attrEnd = ArgNoWholeArchiveList.end();
- for (; attr!=attrEnd; ++attr) {
- pOption.appendOption(new mcld::NoWholeArchiveOption(
- ArgNoWholeArchiveList.getPosition(attr-ArgNoWholeArchiveList.begin())));
+ // add address mappings
+ // -Ttext
+ if (-1U != ArgTextSegAddr) {
+ bool exist = false;
+ mcld::StringEntry<uint64_t>* text_mapping =
+ pConfig.scripts().addressMap().insert(".text", exist);
+ text_mapping->setValue(ArgTextSegAddr);
}
-
- // --as-needed
- attr = ArgAsNeededList.begin();
- attrEnd = ArgAsNeededList.end();
- while(attr != attrEnd) {
- pOption.appendOption(new mcld::AsNeededOption(
- ArgAsNeededList.getPosition(attr-ArgAsNeededList.begin())));
- ++attr;
+ // -Tdata
+ if (-1U != ArgDataSegAddr) {
+ bool exist = false;
+ mcld::StringEntry<uint64_t>* data_mapping =
+ pConfig.scripts().addressMap().insert(".data", exist);
+ data_mapping->setValue(ArgDataSegAddr);
}
-
- // --no-as-needed
- attr = ArgNoAsNeededList.begin();
- attrEnd = ArgNoAsNeededList.end();
- while(attr != attrEnd) {
- pOption.appendOption(new mcld::NoAsNeededOption(
- ArgNoAsNeededList.getPosition(attr-ArgNoAsNeededList.begin())));
- ++attr;
+ // -Tbss
+ if (-1U != ArgBssSegAddr) {
+ bool exist = false;
+ mcld::StringEntry<uint64_t>* bss_mapping =
+ pConfig.scripts().addressMap().insert(".bss", exist);
+ bss_mapping->setValue(ArgBssSegAddr);
}
-
- // --add-needed
- attr = ArgAddNeededList.begin();
- attrEnd = ArgAddNeededList.end();
- while(attr != attrEnd) {
- pOption.appendOption(new mcld::AddNeededOption(
- ArgAddNeededList.getPosition(attr-ArgAddNeededList.begin())));
- ++attr;
- }
-
- // --no-add-needed
- attr = ArgNoAddNeededList.begin();
- attrEnd = ArgNoAddNeededList.end();
- while(attr != attrEnd) {
- pOption.appendOption(new mcld::NoAddNeededOption(
- ArgNoAddNeededList.getPosition(attr-ArgNoAddNeededList.begin())));
- ++attr;
- }
-
- // -Bdynamic
- attr = ArgBDynamicList.begin();
- attrEnd = ArgBDynamicList.end();
- while(attr != attrEnd) {
- pOption.appendOption(new mcld::BDynamicOption(
- ArgBDynamicList.getPosition(attr-ArgBDynamicList.begin())));
- }
-
- // -Bstatic
- attr = ArgBStaticList.begin();
- attrEnd = ArgBStaticList.end();
- while(attr != attrEnd) {
- pOption.appendOption(new mcld::BStaticOption(
- ArgBStaticList.getPosition(attr-ArgBStaticList.begin())));
- ++attr;
+ // --section-start SECTION=ADDRESS
+ for (cl::list<std::string>::iterator
+ it = ArgAddressMapList.begin(), ie = ArgAddressMapList.end();
+ it != ie; ++it) {
+ // FIXME: Add a cl::parser
+ size_t pos = (*it).find_last_of('=');
+ llvm::StringRef script(*it);
+ uint64_t address = 0x0;
+ script.substr(pos + 1).getAsInteger(0, address);
+ bool exist = false;
+ mcld::StringEntry<uint64_t>* addr_mapping =
+ pConfig.scripts().addressMap().insert(script.substr(0, pos), exist);
+ addr_mapping->setValue(address);
}
return true;
}
-int main( int argc, char* argv[] )
+int main(int argc, char* argv[])
{
LLVMContext &Context = getGlobalContext();
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
@@ -909,26 +983,27 @@
InitializeAllTargetMCs();
mcld::InitializeAllTargets();
mcld::InitializeAllLinkers();
+ mcld::InitializeAllEmulations();
mcld::InitializeAllDiagnostics();
// Load the module to be compiled...
- std::auto_ptr<Module> M;
+ std::auto_ptr<llvm::Module> M;
- // -shared
- if (true == ArgShared) {
- ArgFileType = mcld::CGFT_DSOFile;
- }
+ // Load the module to be linked...
+ mcld::Module LDIRModule;
- // -V
- if (ArgVersion) {
- outs() << "MCLinker - ";
- outs() << mcld::MCLDInfo::version();
- outs() << "\n";
+ mcld::LinkerConfig LDConfig;
+
+ // Process the linker input from the command line
+ if (!ProcessLinkerOptionsFromCommand(LDConfig)) {
+ errs() << argv[0] << ": failed to process linker options from command line!\n";
+ return 1;
}
if (ArgBitcodeFilename.empty() &&
(mcld::CGFT_DSOFile != ArgFileType &&
- mcld::CGFT_EXEFile != ArgFileType)) {
+ mcld::CGFT_EXEFile != ArgFileType &&
+ mcld::CGFT_PARTIAL != 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"
@@ -1011,6 +1086,8 @@
return 1;
}
}
+ // Set up mcld::LinkerConfig
+ LDConfig.setTriple(TheTriple);
// Package up features to be passed to target/subtarget
std::string FeaturesStr;
@@ -1060,34 +1137,26 @@
Options.TrapFuncName = TrapFuncName;
Options.EnableSegmentedStacks = SegmentedStacks;
- std::auto_ptr<mcld::LLVMTargetMachine> target_machine(
+ std::auto_ptr<mcld::MCLDTargetMachine> target_machine(
TheTarget->createTargetMachine(TheTriple.getTriple(),
MCPU, FeaturesStr, Options,
ArgRelocModel, CMModel, OLvl));
assert(target_machine.get() && "Could not allocate target machine!");
- mcld::LLVMTargetMachine &TheTargetMachine = *target_machine.get();
+ mcld::MCLDTargetMachine &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
+ // FIXME: Move the initialization of LineInfo to mcld::Linker when we
+ // finish LineInfo's implementation.
OwningPtr<mcld::DiagnosticLineInfo>
diag_line_info(TheTarget->createDiagnosticLineInfo(*TheTarget,
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());
-
+ mcld::getDiagnosticEngine().setLineInfo(*diag_line_info.take());
// Figure out where we are going to send the output...
- OwningPtr<tool_output_file>
+ OwningPtr<mcld::ToolOutputFile>
Out(GetOutputStream(TheTarget->get()->getName(),
TheTriple.getOS(),
ArgFileType,
@@ -1110,30 +1179,14 @@
// Override default to generate verbose assembly.
TheTargetMachine.getTM().setAsmVerbosityDefault(true);
- // Process the linker input from the command line
- mcld::SectLinkerOption *LinkerOpt =
- new mcld::SectLinkerOption(TheTargetMachine.getLDInfo());
-
- 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;
- }
-
{
- formatted_raw_ostream FOS(Out->os());
-
// Ask the target to add backend passes as necessary.
if( TheTargetMachine.addPassesToEmitFile(PM,
- FOS,
- ArgOutputFilename.native(),
+ *Out,
ArgFileType,
OLvl,
- LinkerOpt,
+ LDIRModule,
+ LDConfig,
NoVerify)) {
errs() << argv[0] << ": target does not support generation of this"
<< " file type!\n";
@@ -1148,20 +1201,6 @@
// Declare success.
Out->keep();
-
- // 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;
}