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 Ueyamastd::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 Ueyamastd::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 Ueyamastd::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