xref: /llvm-project/lld/Common/Reproduce.cpp (revision 8d85c96e0e3a058ae82930cf6767d9a1c8cc7c1d)
13f851704SRui Ueyama //===- Reproduce.cpp - Utilities for creating reproducers -----------------===//
23f851704SRui Ueyama //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63f851704SRui Ueyama //
73f851704SRui Ueyama //===----------------------------------------------------------------------===//
83f851704SRui Ueyama 
93f851704SRui Ueyama #include "lld/Common/Reproduce.h"
103f851704SRui Ueyama #include "llvm/Option/Arg.h"
113f851704SRui Ueyama #include "llvm/Support/Error.h"
123f851704SRui Ueyama #include "llvm/Support/FileSystem.h"
133f851704SRui Ueyama #include "llvm/Support/Path.h"
143f851704SRui Ueyama 
153f851704SRui Ueyama using namespace lld;
163f851704SRui Ueyama using namespace llvm;
173f851704SRui Ueyama using namespace llvm::sys;
183f851704SRui Ueyama 
193f851704SRui Ueyama // Makes a given pathname an absolute path first, and then remove
203f851704SRui Ueyama // beginning /. For example, "../foo.o" is converted to "home/john/foo.o",
213f851704SRui Ueyama // assuming that the current directory is "/home/john/bar".
223f851704SRui Ueyama // Returned string is a forward slash separated path even on Windows to avoid
233f851704SRui Ueyama // a mess with backslash-as-escape and backslash-as-path-separator.
relativeToRoot(StringRef path)24136d27abSRui Ueyama std::string lld::relativeToRoot(StringRef path) {
25136d27abSRui Ueyama   SmallString<128> abs = path;
26136d27abSRui Ueyama   if (fs::make_absolute(abs))
27adcd0268SBenjamin Kramer     return std::string(path);
28136d27abSRui Ueyama   path::remove_dots(abs, /*remove_dot_dot=*/true);
293f851704SRui Ueyama 
303f851704SRui Ueyama   // This is Windows specific. root_name() returns a drive letter
313f851704SRui Ueyama   // (e.g. "c:") or a UNC name (//net). We want to keep it as part
323f851704SRui Ueyama   // of the result.
33136d27abSRui Ueyama   SmallString<128> res;
34136d27abSRui Ueyama   StringRef root = path::root_name(abs);
35*8d85c96eSFangrui Song   if (root.ends_with(":"))
36136d27abSRui Ueyama     res = root.drop_back();
37*8d85c96eSFangrui Song   else if (root.starts_with("//"))
38136d27abSRui Ueyama     res = root.substr(2);
393f851704SRui Ueyama 
40136d27abSRui Ueyama   path::append(res, path::relative_path(abs));
41136d27abSRui Ueyama   return path::convert_to_slash(res);
423f851704SRui Ueyama }
433f851704SRui Ueyama 
443f851704SRui Ueyama // Quote a given string if it contains a space character.
quote(StringRef s)45136d27abSRui Ueyama std::string lld::quote(StringRef s) {
46136d27abSRui Ueyama   if (s.contains(' '))
47136d27abSRui Ueyama     return ("\"" + s + "\"").str();
48adcd0268SBenjamin Kramer   return std::string(s);
493f851704SRui Ueyama }
503f851704SRui Ueyama 
51e3f06b47SNico Weber // Converts an Arg to a string representation suitable for a response file.
52e3f06b47SNico Weber // To show an Arg in a diagnostic, use Arg::getAsString() instead.
toString(const opt::Arg & arg)53136d27abSRui Ueyama std::string lld::toString(const opt::Arg &arg) {
54adcd0268SBenjamin Kramer   std::string k = std::string(arg.getSpelling());
55136d27abSRui Ueyama   if (arg.getNumValues() == 0)
56136d27abSRui Ueyama     return k;
5783e60f5aSNico Weber   std::string v;
5883e60f5aSNico Weber   for (size_t i = 0; i < arg.getNumValues(); ++i) {
5983e60f5aSNico Weber     if (i > 0)
6083e60f5aSNico Weber       v.push_back(' ');
6183e60f5aSNico Weber     v += quote(arg.getValue(i));
6283e60f5aSNico Weber   }
63136d27abSRui Ueyama   if (arg.getOption().getRenderStyle() == opt::Option::RenderJoinedStyle)
64136d27abSRui Ueyama     return k + v;
65136d27abSRui Ueyama   return k + " " + v;
663f851704SRui Ueyama }
67