1 //===- Reproduce.cpp - Utilities for creating reproducers -----------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lld/Common/Reproduce.h" 10 #include "llvm/Option/Arg.h" 11 #include "llvm/Support/Error.h" 12 #include "llvm/Support/FileSystem.h" 13 #include "llvm/Support/Path.h" 14 15 using namespace lld; 16 using namespace llvm; 17 using namespace llvm::sys; 18 19 // Makes a given pathname an absolute path first, and then remove 20 // beginning /. For example, "../foo.o" is converted to "home/john/foo.o", 21 // assuming that the current directory is "/home/john/bar". 22 // Returned string is a forward slash separated path even on Windows to avoid 23 // a mess with backslash-as-escape and backslash-as-path-separator. 24 std::string lld::relativeToRoot(StringRef path) { 25 SmallString<128> abs = path; 26 if (fs::make_absolute(abs)) 27 return std::string(path); 28 path::remove_dots(abs, /*remove_dot_dot=*/true); 29 30 // This is Windows specific. root_name() returns a drive letter 31 // (e.g. "c:") or a UNC name (//net). We want to keep it as part 32 // of the result. 33 SmallString<128> res; 34 StringRef root = path::root_name(abs); 35 if (root.ends_with(":")) 36 res = root.drop_back(); 37 else if (root.starts_with("//")) 38 res = root.substr(2); 39 40 path::append(res, path::relative_path(abs)); 41 return path::convert_to_slash(res); 42 } 43 44 // Quote a given string if it contains a space character. 45 std::string lld::quote(StringRef s) { 46 if (s.contains(' ')) 47 return ("\"" + s + "\"").str(); 48 return std::string(s); 49 } 50 51 // Converts an Arg to a string representation suitable for a response file. 52 // To show an Arg in a diagnostic, use Arg::getAsString() instead. 53 std::string lld::toString(const opt::Arg &arg) { 54 std::string k = std::string(arg.getSpelling()); 55 if (arg.getNumValues() == 0) 56 return k; 57 std::string v; 58 for (size_t i = 0; i < arg.getNumValues(); ++i) { 59 if (i > 0) 60 v.push_back(' '); 61 v += quote(arg.getValue(i)); 62 } 63 if (arg.getOption().getRenderStyle() == opt::Option::RenderJoinedStyle) 64 return k + v; 65 return k + " " + v; 66 } 67