MCLinker upstream commit c27f2593f4e3.
Change-Id: I41325b6622594ebecd0a494a8d6d298c1c474ac1
diff --git a/tools/llvm-mcld/llvm-mcld.cpp b/tools/llvm-mcld/llvm-mcld.cpp
index 28a18c6..e7a48d0 100644
--- a/tools/llvm-mcld/llvm-mcld.cpp
+++ b/tools/llvm-mcld/llvm-mcld.cpp
@@ -283,7 +283,7 @@
cl::value_desc("directory"),
cl::ValueRequired);
-static cl::list<std::string>
+static cl::list<std::string, bool, llvm::cl::SearchDirParser>
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."),
@@ -597,6 +597,26 @@
cl::desc("alias for -u"),
cl::aliasopt(ArgForceUndefined));
+static cl::opt<std::string>
+ArgVersionScript("version-script",
+ cl::desc("Version script."),
+ cl::value_desc("Version script"));
+
+static cl::opt<bool>
+ArgNoStdLib("nostdlib",
+ cl::desc("Only search lib dirs explicitly specified on cmdline"),
+ cl::init(false));
+
+static cl::opt<bool>
+ArgWarnCommon("warn-common",
+ cl::desc("warn common symbol"),
+ cl::init(false));
+
+static cl::opt<bool>
+ArgFatalWarnings("fatal-warnings",
+ cl::desc("turn all warnings into errors"),
+ cl::init(false));
+
/// @{
/// @name FIXME: end of unsupported options
/// @}
@@ -606,6 +626,54 @@
cl::desc("Warn if adding DT_TEXTREL in a shared object."),
cl::init(false));
+namespace format {
+enum Format {
+ Binary,
+ Unknown // decided by triple
+};
+} // namespace of format
+
+static cl::opt<format::Format>
+ArgFormat("b",
+ cl::value_desc("Format"),
+ cl::desc("set input format"),
+ cl::init(format::Unknown),
+ cl::values(
+ clEnumValN(format::Binary, "binary",
+ "read in binary machine code."),
+ clEnumValEnd));
+
+static cl::alias
+ArgFormatAlias("format",
+ cl::desc("alias for -b"),
+ cl::aliasopt(ArgFormat));
+
+static cl::opt<format::Format>
+ArgOFormat("oformat",
+ cl::value_desc("Format"),
+ cl::desc("set output format"),
+ cl::init(format::Unknown),
+ cl::values(
+ clEnumValN(format::Binary, "binary",
+ "generate binary machine code."),
+ clEnumValEnd));
+
+static cl::opt<bool>
+ArgDefineCommon("d",
+ cl::ZeroOrMore,
+ cl::desc("Define common symbol"),
+ cl::init(false));
+
+static cl::alias
+ArgDefineCommonAlias1("dc",
+ cl::desc("alias for -d"),
+ cl::aliasopt(ArgDefineCommon));
+
+static cl::alias
+ArgDefineCommonAlias2("dp",
+ cl::desc("alias for -d"),
+ cl::aliasopt(ArgDefineCommon));
+
//===----------------------------------------------------------------------===//
// Scripting Options
//===----------------------------------------------------------------------===//
@@ -743,6 +811,7 @@
break;
case mcld::CGFT_DSOFile:
case mcld::CGFT_EXEFile:
+ case mcld::CGFT_BINARY:
case mcld::CGFT_NULLFile:
permission = 0755;
break;
@@ -759,6 +828,44 @@
return result_output;
}
+/// ParseProgName - Parse program name
+/// This function simplifies cross-compiling by reading triple from the program
+/// name. For example, if the program name is `arm-linux-eabi-ld.mcld', we can
+/// get the triple is arm-linux-eabi by the program name.
+static void ParseProgName(const char *progname)
+{
+ static const char *suffixes[] = {
+ "ld",
+ "ld.mcld",
+ };
+
+ std::string ProgName(mcld::sys::fs::Path(progname).stem().native());
+
+ for (size_t i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) {
+ if (ProgName == suffixes[i])
+ return;
+ }
+
+ StringRef ProgNameRef(ProgName);
+ StringRef Prefix;
+
+ for (size_t i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) {
+ if (!ProgNameRef.endswith(suffixes[i]))
+ continue;
+
+ StringRef::size_type LastComponent = ProgNameRef.rfind('-',
+ ProgNameRef.size() - strlen(suffixes[i]));
+ if (LastComponent == StringRef::npos)
+ continue;
+ StringRef Prefix = ProgNameRef.slice(0, LastComponent);
+ std::string IgnoredError;
+ if (!llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError))
+ continue;
+ TargetTriple = Prefix.str();
+ return;
+ }
+}
+
static bool ShouldColorize()
{
const char* term = getenv("TERM");
@@ -788,6 +895,9 @@
// set up soname
pConfig.options().setSOName(ArgSOName);
+ // --fatal-warnings
+ pConfig.options().setFatalWarnings(ArgFatalWarnings);
+
// -shared or -pie
if (true == ArgShared || true == ArgPIE) {
ArgFileType = mcld::CGFT_DSOFile;
@@ -795,6 +905,13 @@
else if (true == ArgRelocatable) {
ArgFileType = mcld::CGFT_PARTIAL;
}
+ else if (format::Binary == ArgOFormat) {
+ ArgFileType = mcld::CGFT_BINARY;
+ }
+
+ // -b [input-format], --format=[input-format]
+ if (format::Binary == ArgFormat)
+ pConfig.options().setBinaryInput();
// -V
if (ArgVersion) {
@@ -838,6 +955,7 @@
pConfig.options().setStripDebug(ArgStripDebug);
pConfig.options().setExportDynamic(ArgExportDynamic);
pConfig.options().setWarnSharedTextrel(ArgWarnSharedTextrel);
+ pConfig.options().setDefineCommon(ArgDefineCommon);
// set up rename map, for --wrap
cl::list<std::string>::iterator wname;
@@ -968,13 +1086,6 @@
{
LLVMContext &Context = getGlobalContext();
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
- cl::ParseCommandLineOptions(argc, argv, "MCLinker\n");
-
-#ifdef ENABLE_UNITTEST
- if (UnitTest) {
- return unit_test( argc, argv );
- }
-#endif
// Initialize targets first, so that --version shows registered targets.
InitializeAllTargets();
@@ -986,6 +1097,15 @@
mcld::InitializeAllEmulations();
mcld::InitializeAllDiagnostics();
+ ParseProgName(argv[0]);
+ cl::ParseCommandLineOptions(argc, argv, "MCLinker\n");
+
+#ifdef ENABLE_UNITTEST
+ if (UnitTest) {
+ return unit_test( argc, argv );
+ }
+#endif
+
// Load the module to be compiled...
std::auto_ptr<llvm::Module> M;
@@ -1003,7 +1123,8 @@
if (ArgBitcodeFilename.empty() &&
(mcld::CGFT_DSOFile != ArgFileType &&
mcld::CGFT_EXEFile != ArgFileType &&
- mcld::CGFT_PARTIAL != ArgFileType)) {
+ mcld::CGFT_PARTIAL != ArgFileType &&
+ mcld::CGFT_BINARY != 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"
@@ -1087,7 +1208,7 @@
}
}
// Set up mcld::LinkerConfig
- LDConfig.setTriple(TheTriple);
+ LDConfig.targets().setTriple(TheTriple);
// Package up features to be passed to target/subtarget
std::string FeaturesStr;
@@ -1199,6 +1320,9 @@
PM.run(mod);
}
+ if (mcld::getDiagnosticEngine().getPrinter()->getNumErrors())
+ return 1;
+
// Declare success.
Out->keep();
return 0;