[PATCH] D56650: [lld] [ELF] Support customizing behavior on target triple

2019-07-02 Thread Kamil Rytarowski via Phabricator via cfe-commits
krytarowski added a comment.

> Personally I am opposed to this change. The compiler driver (gcc,clang) has a 
> set of arch/OS dependent defaults. It seems weird/redundant to add another 
> sets of defaults on the linker side.

The NetBSD toolchain relies on internal knowledge in a linker that can be used 
as a standalone program. This is our design choice and this was decided 
internally to be kept. You might not be nice from some point of view, but it is 
our real-world use-case, we wrote set of patches for it, we maintain a buildbot 
building and running lld tests... we try to upstream it.

A similar customization is actually done for (at least) Darwin (as the only OS 
using MachO) and FreeBSD (by an accident it's possible to differentiate FreeBSD 
on emul name). Please see that Darwin appends default paths (last time I 
checked) and for FreeBSD there are some fixups based on detecting FreeBSD. For 
OpenBSD there is an accident that it works thanks to embedding 'openbsd' in 
customization parts. For NetBSD we don't have such escape detection viable to 
include fixups and we shall detect triple target based on lld executable name.

If you don't like to see this code by defaut in lld, we can include it under 
`#ifdef` or overload the 'elf' namespace into 'netbsdelf'.

We need to unearth from our local patches and get upstream version of lld 
functional.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56650/new/

https://reviews.llvm.org/D56650



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56650: [lld] [ELF] Support customizing behavior on target triple

2019-07-01 Thread Fangrui Song via Phabricator via cfe-commits
MaskRay requested changes to this revision.
MaskRay added a comment.

> krytarowski: The discussion is ongoing since 2017 and we have an impasse.
> 
>> peter.smith: I think this might be better raised on lllvm-dev as I suspect 
>> that we need to give this wider visibility. I'm not totally opposed to this 
>> as I can see that --target has some advantages over adding extra emulations, 
>> or relying on the --target in the compiler driver but I think we need to be 
>> careful to define how this will interact with the emulation, and what the 
>> bounds of what we can customise with the option are?

Peter suggested raising your problem on the llvm-dev mailing list. Have you 
done that?

Personally I am opposed to this change. The compiler driver (gcc,clang) has a 
set of arch/OS dependent defaults. It seems weird/redundant to add another sets 
of defaults on the linker side.

A few replies to some bullet points you raised in a previous comment.

> GCC to pass lld flags

Compiler drivers have more information (OS version, toolchain path, linker 
name, etc) to decide if some linker flags are needed. Some `-f` options can 
generate linker options as well.

> rpath behavior

From my reading of https://blog.netbsd.org/tnf/entry/the_first_report_on_lld , 
I don't see why NetBSD must maintain the --disable-new-dtags local patch.

> GNU stack generation

`-z nognustack` makes sense to me. I commented on D56554 
.

> specify default target/emulation search paths

This job should be done in the compiler drivers.

> disable 3 segments

Personally I don't think it is really necessary to change the default.. But you 
can add --no-rosegment if you are really bothered by the layout.

I think your requirement can be simply accomplished with a shell script wrapper 
called `ld`:

  #!/bin/sh
  # customization
  exec ld.lld 


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56650/new/

https://reviews.llvm.org/D56650



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56650: [lld] [ELF] Support customizing behavior on target triple

2019-07-01 Thread Kamil Rytarowski via Phabricator via cfe-commits
krytarowski added a comment.
Herald added a subscriber: MaskRay.

@ruiu ping?

LLVM 9 is branching soon and we would like to unearth from local patches.

From the internal discussions it was decided that we want to maintain our 
current behavior that differs to Linux.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56650/new/

https://reviews.llvm.org/D56650



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56650: [lld] [ELF] Support customizing behavior on target triple

2019-01-30 Thread Kamil Rytarowski via Phabricator via cfe-commits
krytarowski added a comment.

> chandlerc added a comment.
> 
> There was a long discussion between two NetBSD maintainers about this (both 
> already in the reviewers list of this patch). I'm not sure if there is an 
> existing thread that would be better to follow up on as opposed to starting a 
> fresh thread.

The discussion is ongoing since 2017 and we have an impasse.

> I think the question was: should the path search logic be handled in the 
> `clang` driver or in LLD itself. FWIW, I prefer that NetBSD follow the same 
> design as every other platform here with the (somewhat C and C++ specific) 
> search logic provided by the `clang` driver.

Path logic is unfortunately just the tip of iceberg of customization we need, 
but it's true that its the first problem to encounter when attempting to use 
lld/NetBSD. Depending on the approach of solving it we can follow up with other 
changes.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56650/new/

https://reviews.llvm.org/D56650



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56650: [lld] [ELF] Support customizing behavior on target triple

2019-01-30 Thread Kamil Rytarowski via Phabricator via cfe-commits
krytarowski added a comment.

In D56650#1377546 , @ruiu wrote:

> If you still need to patch GNU ld, it doesn't seems like this patch makes 
> things easier for you. (But even if this would make it easier for you, this 
> patch's approach is not okay by design though.)


If we can get standalone lld functional out of the box and respecting target, 
we no longer need to patch GCC/LD/distribution/3rd-party-software.

If there is a strong feeling to retain lld ELF target as it is, we can grow a 
custom target like Darwin/Windows and specify customization there. The 
mentioned Darwin adds /usr/lib in the linker directly.  We need analogous 
opportunity on our end.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56650/new/

https://reviews.llvm.org/D56650



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56650: [lld] [ELF] Support customizing behavior on target triple

2019-01-30 Thread Kamil Rytarowski via Phabricator via cfe-commits
krytarowski added a comment.

If we pass flags from clang, we sacrifice:

- lld usable as a standalone executable
- gcc capable to use lld as a functional linker
- clang driver not capable to call unpatched gnu ld/gold as we grow local flags 
to workaroud the customization (such as -z nognustack)
- compat with a number of programs programs that call linker directly and we 
customize the passed flags (gcc itself is one of them)

We just gain clang+lld tandem to work and we must retain GCC/LD 
interoperability (which as I understand isn't a priority/interesting for other 
OSes).

In theory we can patch:

- GCC to pass lld flags
- GNU LD (/gold) to accept new flags
- all the programs using linker to stop doing so (like the GCC project)

We need to tune in lld at least for start (out of my head, likely not a 
finished list):

- tune the DT_NEEDED behavior,
- rpath behavior,
- GNU stack generation
- specify default target/emulation search paths
- disable 3 segments (disable ro one)

We can address all the issues either in lld or in all the other projects around 
which certainly doesn't scale (and I expect in particular problems to push e.g. 
-z nognustack to GNU ld(1)).

OpenBSD indeed patches downstream their linkers for additional flags and 
accidentally it works better in the lld design. In NetBSD we struggle to get 
sane defaults rather than a set of additional flags. GNU stack is unwanted also 
on at least OpenBSD(/Fuchsia..) and there is no way to disable it in lld as of 
now (a proposal is to grow a custom flag). All OSes need to pass default paths 
for standalone linker usage (I've listed a dozen of examples from FreeBSD ports 
in other review).

The current feeling in the project is that if we cannot set the defaults we 
should fork the lld driver downstream and patch it there, which is a lose as 
the upstream version will keep to be unusable.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56650/new/

https://reviews.llvm.org/D56650



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56650: [lld] [ELF] Support customizing behavior on target triple

2019-01-30 Thread Rui Ueyama via Phabricator via cfe-commits
ruiu added a comment.

If you still need to patch GNU ld, it doesn't seems like this patch makes 
things easier for you. (But even if this would make it easier for you, this 
patch's approach is not okay by design though.)


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56650/new/

https://reviews.llvm.org/D56650



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56650: [lld] [ELF] Support customizing behavior on target triple

2019-01-30 Thread Michał Górny via Phabricator via cfe-commits
mgorny added a comment.

In D56650#1377494 , @ruiu wrote:

> But that's only adding missing `-L` and perhaps a few more, no? That doesn't 
> seem too hard to do in gcc.


Probably not, provided nobody will block it. I'm not the one opposed to it.

> I don't want to repeat what compiler drivers do in the linker. Also, even 
> with this patch, you need to make a change to gcc to pass `--target` 
> parameter to the linker, right?

Well, no, since gcc doesn't really support cross-compiling the way clang does, 
so it will just be happy with LLVM's default triple. We will probably want to 
patch GNU ld to accept/ignore `--target` though.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56650/new/

https://reviews.llvm.org/D56650



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56650: [lld] [ELF] Support customizing behavior on target triple

2019-01-30 Thread Rui Ueyama via Phabricator via cfe-commits
ruiu added a comment.

But that's only adding missing `-L` and perhaps a few more, no? That doesn't 
seem too hard to do in gcc. I don't want to repeat what compiler drivers do in 
the linker. Also, even with this patch, you need to make a change to gcc to 
pass `--target` parameter to the linker, right?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56650/new/

https://reviews.llvm.org/D56650



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56650: [lld] [ELF] Support customizing behavior on target triple

2019-01-30 Thread Michał Górny via Phabricator via cfe-commits
mgorny added a comment.

I think the main concern is that if we link `ld -> ld.lld`, gcc will no longer 
work out of the box. So we would have to repeat all the logic in gcc and in any 
other compiler that calls `ld` directly.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56650/new/

https://reviews.llvm.org/D56650



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56650: [lld] [ELF] Support customizing behavior on target triple

2019-01-30 Thread Rui Ueyama via Phabricator via cfe-commits
ruiu added a comment.

Kamil,

I understand how adding `--target` option to the linker would make 
target-specific customization easier, but that's as I said not acceptable by 
design in lld. The code we have for FreeBSD just sets one bit in the output 
file, and that's fundamentally different from adding a "master switch" to turn 
on all customization for some specific target. We've been making changes to lld 
to make it work for many targets, but the features we've added are on by 
default (such as the code for Android TLS layout or supporting 
`.openbsd.randomdata` section for OpenBSD) or enabled by per-feature basis by a 
command line flag (such as *-freebsd emulation name). There's no flag like 
"turning lld into FreeBSD mode" or something like that. It seems to be working 
pretty well, and I'm happy about that design. So, I'm sorry, but I don't think 
I can support this patch's approach at all.

Honestly what's special about NetBSD from the lld's perspective seems to be the 
code ownership of the compiler driver. I can help you solve technical issues, 
but I don't think I should accept a patch that's against one of the lld's 
fundamental design choices to solve non-technical problems.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56650/new/

https://reviews.llvm.org/D56650



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56650: [lld] [ELF] Support customizing behavior on target triple

2019-01-30 Thread Kamil Rytarowski via Phabricator via cfe-commits
krytarowski added a comment.

@rui we need some resolution here. We have stronger feelings from the community 
to customize the linker directly based on detected triple.

At least other !GNU platforms will benefit from it too (at least FreeBSD, 
OpenBSD and other BSD derivations like mentioned CheriBSD).
FreeBSD already adds such target customization based on an emulation name hack, 
we cannot repeat it on NetBSD in the same way.

In the worst case we can even produce a new flavor of lld target that 
resembles/duplicates original ELF and targets (Net)BSD.

Under what circumstances and what model will you let to support this approach?

It does allow us better customization with keeping compat with other toolchain 
components, especially from the the GNU world.

Ideally we would get something for LLVM 8.0.. as it could be still backportable 
at least for downstream purposes. RC2 is planned for Feburary 6th and we need 
unpatched lld functional out of the box.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56650/new/

https://reviews.llvm.org/D56650



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56650: [lld] [ELF] Support customizing behavior on target triple

2019-01-14 Thread Rui Ueyama via Phabricator via cfe-commits
ruiu accepted this revision.
ruiu added a comment.
This revision is now accepted and ready to land.

Let me make it clear again that I'm *not* okay with this approach. Please 
explicitly pass command line arguments from the compiler driver to the linker.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56650/new/

https://reviews.llvm.org/D56650



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56650: [lld] [ELF] Support customizing behavior on target triple

2019-01-14 Thread Peter Smith via Phabricator via cfe-commits
peter.smith added a comment.

I think we need to be very careful here. If I've understood this correctly then 
if this functionality is used for anything critical then a manually supplied 
target will be needed when doing cross-linking. For example my host LLD is 
x86_64, is just called ld.lld and will have an inferred x86_64 target triple. 
If someone customises the behaviour of LLD on the triple in a way that doesn't 
get caught by the test suite then we could get some strange breakages when 
doing cross-linking. I personally would prefer to see any option like this not 
try and auto-infer the target unless it can do it reliably and accurately from 
the input objects and I don't know if that is possible for all supported 
targets.

I think this might be better raised on lllvm-dev as I suspect that we need to 
give this wider visibility. I'm not totally opposed to this as I can see that 
--target has some advantages over adding extra emulations, or relying on the 
--target in the compiler driver but I think we need to be careful to define how 
this will interact with the emulation, and what the bounds of what we can 
customise with the option are?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56650/new/

https://reviews.llvm.org/D56650



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56650: [lld] [ELF] Support customizing behavior on target triple

2019-01-14 Thread Michał Górny via Phabricator via cfe-commits
mgorny updated this revision to Diff 181554.
mgorny marked an inline comment as done.
mgorny added a comment.

Fixed leaving triple unset on invalid `--target`.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56650/new/

https://reviews.llvm.org/D56650

Files:
  ELF/Config.h
  ELF/Driver.cpp
  ELF/Driver.h
  ELF/Options.td

Index: ELF/Options.td
===
--- ELF/Options.td
+++ ELF/Options.td
@@ -313,6 +313,8 @@
 
 defm sysroot: Eq<"sysroot", "Set the system root">;
 
+defm target: Eq<"target", "Apply configuration defaults for a given target">;
+
 def target1_rel: F<"target1-rel">, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_REL32">;
 
 def target1_abs: F<"target1-abs">, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_ABS32 (default)">;
Index: ELF/Driver.h
===
--- ELF/Driver.h
+++ ELF/Driver.h
@@ -31,6 +31,7 @@
   void addLibrary(StringRef Name);
 
 private:
+  void setTargetTriple(StringRef argv0, llvm::opt::InputArgList &Args);
   void readConfigs(llvm::opt::InputArgList &Args);
   void createFiles(llvm::opt::InputArgList &Args);
   void inferMachineType();
Index: ELF/Driver.cpp
===
--- ELF/Driver.cpp
+++ ELF/Driver.cpp
@@ -54,6 +54,7 @@
 #include "llvm/Support/LEB128.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/TarWriter.h"
+#include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/raw_ostream.h"
 #include 
@@ -378,6 +379,25 @@
 return;
   }
 
+  if (const char *Path = getReproduceOption(Args)) {
+// Note that --reproduce is a debug option so you can ignore it
+// if you are trying to understand the whole picture of the code.
+Expected> ErrOrWriter =
+TarWriter::create(Path, path::stem(Path));
+if (ErrOrWriter) {
+  Tar = std::move(*ErrOrWriter);
+  Tar->append("response.txt", createResponseFile(Args));
+  Tar->append("version.txt", getLLDVersion() + "\n");
+} else {
+  error("--reproduce: " + toString(ErrOrWriter.takeError()));
+}
+  }
+
+  initLLVM();
+  setTargetTriple(ArgsArr[0], Args);
+  readConfigs(Args);
+  checkZOptions(Args);
+
   // Handle -v or -version.
   //
   // A note about "compatible with GNU linkers" message: this is a hack for
@@ -393,26 +413,11 @@
   // lot of "configure" scripts out there that are generated by old version
   // of Libtool. We cannot convince every software developer to migrate to
   // the latest version and re-generate scripts. So we have this hack.
-  if (Args.hasArg(OPT_v) || Args.hasArg(OPT_version))
+  if (Args.hasArg(OPT_v) || Args.hasArg(OPT_version)) {
 message(getLLDVersion() + " (compatible with GNU linkers)");
-
-  if (const char *Path = getReproduceOption(Args)) {
-// Note that --reproduce is a debug option so you can ignore it
-// if you are trying to understand the whole picture of the code.
-Expected> ErrOrWriter =
-TarWriter::create(Path, path::stem(Path));
-if (ErrOrWriter) {
-  Tar = std::move(*ErrOrWriter);
-  Tar->append("response.txt", createResponseFile(Args));
-  Tar->append("version.txt", getLLDVersion() + "\n");
-} else {
-  error("--reproduce: " + toString(ErrOrWriter.takeError()));
-}
+message("Target: " + Config->TargetTriple.str());
   }
 
-  readConfigs(Args);
-  checkZOptions(Args);
-
   // The behavior of -v or --version is a bit strange, but this is
   // needed for compatibility with GNU linkers.
   if (Args.hasArg(OPT_v) && !Args.hasArg(OPT_INPUT))
@@ -420,7 +425,6 @@
   if (Args.hasArg(OPT_version))
 return;
 
-  initLLVM();
   createFiles(Args);
   if (errorCount())
 return;
@@ -746,6 +750,34 @@
   error(Msg + ": " + StringRef(Err).trim());
 }
 
+void LinkerDriver::setTargetTriple(StringRef argv0, opt::InputArgList &Args) {
+  std::string TargetError;
+
+  // Firstly, see if user specified explicit --target
+  StringRef TargetOpt = Args.getLastArgValue(OPT_target);
+  if (!TargetOpt.empty()) {
+if (llvm::TargetRegistry::lookupTarget(TargetOpt, TargetError)) {
+  Config->TargetTriple = llvm::Triple(TargetOpt);
+  return;
+} else
+  error("Unsupported --target=" + TargetOpt + ": " + TargetError);
+  }
+
+  // Secondly, try to get it from program name prefix
+  std::string ProgName = llvm::sys::path::stem(argv0);
+  size_t LastComponent = ProgName.rfind('-');
+  if (LastComponent != std::string::npos) {
+std::string Prefix = ProgName.substr(0, LastComponent);
+if (llvm::TargetRegistry::lookupTarget(Prefix, TargetError)) {
+  Config->TargetTriple = llvm::Triple(Prefix);
+  return;
+}
+  }
+
+  // Finally, use the default target triple
+  Config->TargetTriple = llvm::Triple(getDefaultTargetTriple());
+}
+
 // Initializes Config members by the command line options.
 void LinkerDriver::readConfigs(opt::InputArgList &Args) {
   errorHand

[PATCH] D56650: [lld] [ELF] Support customizing behavior on target triple

2019-01-14 Thread Michał Górny via Phabricator via cfe-commits
mgorny marked 2 inline comments as done.
mgorny added inline comments.



Comment at: ELF/Driver.cpp:757
+  if (!TargetOpt.empty()) {
+// TODO: do we want to verify it and fail on unsupported?
+Config->TargetTriple = llvm::Triple(TargetOpt);

arichardson wrote:
> I think failing on an unknown triple would be good since it can avoid user 
> error where the wrong defaults are chosen just because of a small typo.
Somewhat done. Note that LLD apparently doesn't fail on errors immediately, so 
it behaves a bit weird.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56650/new/

https://reviews.llvm.org/D56650



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56650: [lld] [ELF] Support customizing behavior on target triple

2019-01-14 Thread Michał Górny via Phabricator via cfe-commits
mgorny updated this revision to Diff 181552.
mgorny retitled this revision from "[lld] [ELF] Support inferring target triple 
from filename" to "[lld] [ELF] Support customizing behavior on target triple".
mgorny edited the summary of this revision.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56650/new/

https://reviews.llvm.org/D56650

Files:
  ELF/Config.h
  ELF/Driver.cpp
  ELF/Driver.h
  ELF/Options.td

Index: ELF/Options.td
===
--- ELF/Options.td
+++ ELF/Options.td
@@ -313,6 +313,8 @@
 
 defm sysroot: Eq<"sysroot", "Set the system root">;
 
+defm target: Eq<"target", "Apply configuration defaults for a given target">;
+
 def target1_rel: F<"target1-rel">, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_REL32">;
 
 def target1_abs: F<"target1-abs">, HelpText<"Interpret R_ARM_TARGET1 as R_ARM_ABS32 (default)">;
Index: ELF/Driver.h
===
--- ELF/Driver.h
+++ ELF/Driver.h
@@ -31,6 +31,7 @@
   void addLibrary(StringRef Name);
 
 private:
+  void setTargetTriple(StringRef argv0, llvm::opt::InputArgList &Args);
   void readConfigs(llvm::opt::InputArgList &Args);
   void createFiles(llvm::opt::InputArgList &Args);
   void inferMachineType();
Index: ELF/Driver.cpp
===
--- ELF/Driver.cpp
+++ ELF/Driver.cpp
@@ -54,6 +54,7 @@
 #include "llvm/Support/LEB128.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/TarWriter.h"
+#include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/raw_ostream.h"
 #include 
@@ -378,6 +379,25 @@
 return;
   }
 
+  if (const char *Path = getReproduceOption(Args)) {
+// Note that --reproduce is a debug option so you can ignore it
+// if you are trying to understand the whole picture of the code.
+Expected> ErrOrWriter =
+TarWriter::create(Path, path::stem(Path));
+if (ErrOrWriter) {
+  Tar = std::move(*ErrOrWriter);
+  Tar->append("response.txt", createResponseFile(Args));
+  Tar->append("version.txt", getLLDVersion() + "\n");
+} else {
+  error("--reproduce: " + toString(ErrOrWriter.takeError()));
+}
+  }
+
+  initLLVM();
+  setTargetTriple(ArgsArr[0], Args);
+  readConfigs(Args);
+  checkZOptions(Args);
+
   // Handle -v or -version.
   //
   // A note about "compatible with GNU linkers" message: this is a hack for
@@ -393,26 +413,11 @@
   // lot of "configure" scripts out there that are generated by old version
   // of Libtool. We cannot convince every software developer to migrate to
   // the latest version and re-generate scripts. So we have this hack.
-  if (Args.hasArg(OPT_v) || Args.hasArg(OPT_version))
+  if (Args.hasArg(OPT_v) || Args.hasArg(OPT_version)) {
 message(getLLDVersion() + " (compatible with GNU linkers)");
-
-  if (const char *Path = getReproduceOption(Args)) {
-// Note that --reproduce is a debug option so you can ignore it
-// if you are trying to understand the whole picture of the code.
-Expected> ErrOrWriter =
-TarWriter::create(Path, path::stem(Path));
-if (ErrOrWriter) {
-  Tar = std::move(*ErrOrWriter);
-  Tar->append("response.txt", createResponseFile(Args));
-  Tar->append("version.txt", getLLDVersion() + "\n");
-} else {
-  error("--reproduce: " + toString(ErrOrWriter.takeError()));
-}
+message("Target: " + Config->TargetTriple.str());
   }
 
-  readConfigs(Args);
-  checkZOptions(Args);
-
   // The behavior of -v or --version is a bit strange, but this is
   // needed for compatibility with GNU linkers.
   if (Args.hasArg(OPT_v) && !Args.hasArg(OPT_INPUT))
@@ -420,7 +425,6 @@
   if (Args.hasArg(OPT_version))
 return;
 
-  initLLVM();
   createFiles(Args);
   if (errorCount())
 return;
@@ -746,6 +750,34 @@
   error(Msg + ": " + StringRef(Err).trim());
 }
 
+void LinkerDriver::setTargetTriple(StringRef argv0, opt::InputArgList &Args) {
+  std::string TargetError;
+
+  // Firstly, see if user specified explicit --target
+  StringRef TargetOpt = Args.getLastArgValue(OPT_target);
+  if (!TargetOpt.empty()) {
+if (llvm::TargetRegistry::lookupTarget(TargetOpt, TargetError))
+  Config->TargetTriple = llvm::Triple(TargetOpt);
+else
+  error("Unsupported --target=" + TargetOpt + ": " + TargetError);
+return;
+  }
+
+  // Secondly, try to get it from program name prefix
+  std::string ProgName = llvm::sys::path::stem(argv0);
+  size_t LastComponent = ProgName.rfind('-');
+  if (LastComponent != std::string::npos) {
+std::string Prefix = ProgName.substr(0, LastComponent);
+if (llvm::TargetRegistry::lookupTarget(Prefix, TargetError)) {
+  Config->TargetTriple = llvm::Triple(Prefix);
+  return;
+}
+  }
+
+  // Finally, use the default target triple
+  Config->TargetTriple = llvm::Triple(getDefaultTargetTriple());
+}
+
 // Initializes Config members by the command line