llvm.org GIT mirror llvm / 0dcc115
Refactor ExecuteAndWait to take StringRefs. This simplifies some code which had StringRefs to begin with, and makes other code more complicated which had const char* to begin with. In the end, I think this makes for a more idiomatic and platform agnostic API. Not all platforms launch process with null terminated c-string arrays for the environment pointer and argv, but the api was designed that way because it allowed easy pass-through for posix-based platforms. There's a little additional overhead now since on posix based platforms we'll be takign StringRefs which were constructed from null terminated strings and then copying them to null terminate them again, but from a readability and usability standpoint of the API user, I think this API signature is strictly better. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@334518 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 1 year, 4 months ago
14 changed file(s) with 233 addition(s) and 242 deletion(s). Raw diff Collapse all Expand all
3636 inline char hexdigit(unsigned X, bool LowerCase = false) {
3737 const char HexChar = LowerCase ? 'a' : 'A';
3838 return X < 10 ? '0' + X : HexChar + X - 10;
39 }
40
41 /// Given an array of c-style strings terminated by a null pointer, construct
42 /// a vector of StringRefs representing the same strings without the terminating
43 /// null string.
44 inline std::vector toStringRefArray(const char *const *Strings) {
45 std::vector Result;
46 while (*Strings)
47 Result.push_back(*Strings++);
48 return Result;
3949 }
4050
4151 /// Construct a string ref from a boolean.
8888 int ExecuteAndWait(
8989 StringRef Program, ///< Path of the program to be executed. It is
9090 ///< presumed this is the result of the findProgramByName method.
91 const char **Args, ///< A vector of strings that are passed to the
91 ArrayRef Args, ///< An array of strings that are passed to the
9292 ///< program. The first element should be the name of the program.
93 ///< The list *must* be terminated by a null char* entry.
94 const char **Env = nullptr, ///< An optional vector of strings to use for
95 ///< the program's environment. If not provided, the current program's
96 ///< environment will be used.
93 ///< The array should **not** be terminated by an empty StringRef.
94 Optional> Env = None, ///< An optional vector of
95 ///< strings to use for the program's environment. If not provided, the
96 ///< current program's environment will be used. If specified, the
97 ///< vector should **not** be terminated by an empty StringRef.
9798 ArrayRef> Redirects = {}, ///<
9899 ///< An array of optional paths. Should have a size of zero or three.
99100 ///< If the array is empty, no redirections are performed.
122123 /// \note On Microsoft Windows systems, users will need to either call
123124 /// \see Wait until the process finished execution or win32 CloseHandle() API
124125 /// on ProcessInfo.ProcessHandle to avoid memory leaks.
125 ProcessInfo ExecuteNoWait(StringRef Program, const char **Args,
126 const char **Env = nullptr,
126 ProcessInfo ExecuteNoWait(StringRef Program, ArrayRef Args,
127 Optional> Env,
127128 ArrayRef> Redirects = {},
128129 unsigned MemoryLimit = 0,
129130 std::string *ErrMsg = nullptr,
9090 }
9191
9292 // Execute the graph viewer. Return true if there were errors.
93 static bool ExecGraphViewer(StringRef ExecPath, std::vector<const char *> &args,
93 static bool ExecGraphViewer(StringRef ExecPath, std::vector<StringRef> &args,
9494 StringRef Filename, bool wait,
9595 std::string &ErrMsg) {
96 assert(args.back() == nullptr);
9796 if (wait) {
98 if (sys::ExecuteAndWait(ExecPath, args.data(), nullptr, {}, 0, 0,
99 &ErrMsg)) {
97 if (sys::ExecuteAndWait(ExecPath, args, None, {}, 0, 0, &ErrMsg)) {
10098 errs() << "Error: " << ErrMsg << "\n";
10199 return true;
102100 }
103101 sys::fs::remove(Filename);
104102 errs() << " done. \n";
105103 } else {
106 sys::ExecuteNoWait(ExecPath, args.data(), nullptr, {}, 0, &ErrMsg);
104 sys::ExecuteNoWait(ExecPath, args, None, {}, 0, &ErrMsg);
107105 errs() << "Remember to erase graph file: " << Filename << "\n";
108106 }
109107 return false;
157155 #ifdef __APPLE__
158156 wait &= !ViewBackground;
159157 if (S.TryFindProgram("open", ViewerPath)) {
160 std::vector args;
161 args.push_back(ViewerPath.c_str());
158 std::vector args;
159 args.push_back(ViewerPath);
162160 if (wait)
163161 args.push_back("-W");
164 args.push_back(Filename.c_str());
165 args.push_back(nullptr);
162 args.push_back(Filename);
166163 errs() << "Trying 'open' program... ";
167164 if (!ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg))
168165 return false;
169166 }
170167 #endif
171168 if (S.TryFindProgram("xdg-open", ViewerPath)) {
172 std::vector args;
173 args.push_back(ViewerPath.c_str());
174 args.push_back(Filename.c_str());
175 args.push_back(nullptr);
169 std::vector args;
170 args.push_back(ViewerPath);
171 args.push_back(Filename);
176172 errs() << "Trying 'xdg-open' program... ";
177173 if (!ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg))
178174 return false;
180176
181177 // Graphviz
182178 if (S.TryFindProgram("Graphviz", ViewerPath)) {
183 std::vector args;
184 args.push_back(ViewerPath.c_str());
185 args.push_back(Filename.c_str());
186 args.push_back(nullptr);
179 std::vector args;
180 args.push_back(ViewerPath);
181 args.push_back(Filename);
187182
188183 errs() << "Running 'Graphviz' program... ";
189184 return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg);
191186
192187 // xdot
193188 if (S.TryFindProgram("xdot|xdot.py", ViewerPath)) {
194 std::vector args;
195 args.push_back(ViewerPath.c_str());
196 args.push_back(Filename.c_str());
189 std::vector args;
190 args.push_back(ViewerPath);
191 args.push_back(Filename);
197192
198193 args.push_back("-f");
199194 args.push_back(getProgramName(program));
200
201 args.push_back(nullptr);
202195
203196 errs() << "Running 'xdot.py' program... ";
204197 return ExecGraphViewer(ViewerPath, args, Filename, wait, ErrMsg);
234227 std::string OutputFilename =
235228 Filename + (Viewer == VK_CmdStart ? ".pdf" : ".ps");
236229
237 std::vector args;
238 args.push_back(GeneratorPath.c_str());
230 std::vector args;
231 args.push_back(GeneratorPath);
239232 if (Viewer == VK_CmdStart)
240233 args.push_back("-Tpdf");
241234 else
242235 args.push_back("-Tps");
243236 args.push_back("-Nfontname=Courier");
244237 args.push_back("-Gsize=7.5,10");
245 args.push_back(Filename.c_str());
238 args.push_back(Filename);
246239 args.push_back("-o");
247 args.push_back(OutputFilename.c_str());
248 args.push_back(nullptr);
240 args.push_back(OutputFilename);
249241
250242 errs() << "Running '" << GeneratorPath << "' program... ";
251243
257249 std::string StartArg;
258250
259251 args.clear();
260 args.push_back(ViewerPath.c_str());
252 args.push_back(ViewerPath);
261253 switch (Viewer) {
262254 case VK_OSXOpen:
263255 args.push_back("-W");
264 args.push_back(OutputFilename.c_str());
256 args.push_back(OutputFilename);
265257 break;
266258 case VK_XDGOpen:
267259 wait = false;
268 args.push_back(OutputFilename.c_str());
260 args.push_back(OutputFilename);
269261 break;
270262 case VK_Ghostview:
271263 args.push_back("--spartan");
272 args.push_back(OutputFilename.c_str());
264 args.push_back(OutputFilename);
273265 break;
274266 case VK_CmdStart:
275267 args.push_back("/S");
276268 args.push_back("/C");
277269 StartArg =
278270 (StringRef("start ") + (wait ? "/WAIT " : "") + OutputFilename).str();
279 args.push_back(StartArg.c_str());
271 args.push_back(StartArg);
280272 break;
281273 case VK_None:
282274 llvm_unreachable("Invalid viewer");
283275 }
284 args.push_back(nullptr);
285276
286277 ErrMsg.clear();
287278 return ExecGraphViewer(ViewerPath, args, OutputFilename, wait, ErrMsg);
289280
290281 // dotty
291282 if (S.TryFindProgram("dotty", ViewerPath)) {
292 std::vector args;
293 args.push_back(ViewerPath.c_str());
294 args.push_back(Filename.c_str());
295 args.push_back(nullptr);
283 std::vector args;
284 args.push_back(ViewerPath);
285 args.push_back(Filename);
296286
297287 // Dotty spawns another app and doesn't wait until it returns
298288 #ifdef _WIN32
2222 //=== independent code.
2323 //===----------------------------------------------------------------------===//
2424
25 static bool Execute(ProcessInfo &PI, StringRef Program, const char **Args,
26 const char **Env, ArrayRef> Redirects,
25 static bool Execute(ProcessInfo &PI, StringRef Program,
26 ArrayRef Args, Optional> Env,
27 ArrayRef> Redirects,
2728 unsigned MemoryLimit, std::string *ErrMsg);
2829
29 int sys::ExecuteAndWait(StringRef Program, const char **Args, const char **Envp,
30 int sys::ExecuteAndWait(StringRef Program, ArrayRef Args,
31 Optional> Env,
3032 ArrayRef> Redirects,
3133 unsigned SecondsToWait, unsigned MemoryLimit,
3234 std::string *ErrMsg, bool *ExecutionFailed) {
3335 assert(Redirects.empty() || Redirects.size() == 3);
3436 ProcessInfo PI;
35 if (Execute(PI, Program, Args, Envp, Redirects, MemoryLimit, ErrMsg)) {
37 if (Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg)) {
3638 if (ExecutionFailed)
3739 *ExecutionFailed = false;
3840 ProcessInfo Result = Wait(
4648 return -1;
4749 }
4850
49 ProcessInfo sys::ExecuteNoWait(StringRef Program, const char **Args,
50 const char **Envp,
51 ProcessInfo sys::ExecuteNoWait(StringRef Program, ArrayRef Args,
52 Optional> Env,
5153 ArrayRef> Redirects,
5254 unsigned MemoryLimit, std::string *ErrMsg,
5355 bool *ExecutionFailed) {
5557 ProcessInfo PI;
5658 if (ExecutionFailed)
5759 *ExecutionFailed = false;
58 if (!Execute(PI, Program, Args, Envp, Redirects, MemoryLimit, ErrMsg))
60 if (!Execute(PI, Program, Args, Env, Redirects, MemoryLimit, ErrMsg))
5961 if (ExecutionFailed)
6062 *ExecutionFailed = true;
6163
153153 }
154154 }
155155
156 Optional Redirects[] = {InputFile.str(), OutputFile.str(), llvm::None};
157 const char *Args[] = {"llvm-symbolizer", "--functions=linkage", "--inlining",
156 Optional Redirects[] = {StringRef(InputFile),
157 StringRef(OutputFile), llvm::None};
158 StringRef Args[] = {"llvm-symbolizer", "--functions=linkage", "--inlining",
158159 #ifdef _WIN32
159 // Pass --relative-address on Windows so that we don't
160 // have to add ImageBase from PE file.
161 // FIXME: Make this the default for llvm-symbolizer.
162 "--relative-address",
160 // Pass --relative-address on Windows so that we don't
161 // have to add ImageBase from PE file.
162 // FIXME: Make this the default for llvm-symbolizer.
163 "--relative-address",
163164 #endif
164 "--demangle", nullptr};
165 "--demangle"};
165166 int RunResult =
166 sys::ExecuteAndWait(LLVMSymbolizerPath, Args, nullptr, Redirects);
167 sys::ExecuteAndWait(LLVMSymbolizerPath, Args, None, Redirects);
167168 if (RunResult != 0)
168169 return false;
169170
2222 #include "llvm/Support/Errc.h"
2323 #include "llvm/Support/FileSystem.h"
2424 #include "llvm/Support/Path.h"
25 #include "llvm/Support/StringSaver.h"
2526 #include "llvm/Support/raw_ostream.h"
2627 #if HAVE_SYS_STAT_H
2728 #include
163164
164165 }
165166
166 static bool Execute(ProcessInfo &PI, StringRef Program, const char **Args,
167 const char **Envp, ArrayRef> Redirects,
167 static std::vector
168 toNullTerminatedCStringArray(ArrayRef Strings, StringSaver &Saver) {
169 std::vector Result;
170 for (StringRef S : Strings)
171 Result.push_back(Saver.save(S).data());
172 Result.push_back(nullptr);
173 return Result;
174 }
175
176 static bool Execute(ProcessInfo &PI, StringRef Program,
177 ArrayRef Args, Optional> Env,
178 ArrayRef> Redirects,
168179 unsigned MemoryLimit, std::string *ErrMsg) {
169180 if (!llvm::sys::fs::exists(Program)) {
170181 if (ErrMsg)
171182 *ErrMsg = std::string("Executable \"") + Program.str() +
172183 std::string("\" doesn't exist!");
173184 return false;
185 }
186
187 BumpPtrAllocator Allocator;
188 StringSaver Saver(Allocator);
189 std::vector ArgVector, EnvVector;
190 const char **Argv = nullptr;
191 const char **Envp = nullptr;
192 ArgVector = toNullTerminatedCStringArray(Args, Saver);
193 Argv = ArgVector.data();
194 if (Env) {
195 EnvVector = toNullTerminatedCStringArray(*Env, Saver);
196 Envp = EnvVector.data();
174197 }
175198
176199 // If this OS has posix_spawn and there is no memory limit being implied, use
226249 // positive.
227250 pid_t PID = 0;
228251 int Err = posix_spawn(&PID, Program.str().c_str(), FileActions,
229 /*attrp*/nullptr, const_cast(Args),
252 /*attrp*/ nullptr, const_cast(Argv),
230253 const_cast(Envp));
231254
232255 if (FileActions)
279302 // Execute!
280303 std::string PathStr = Program;
281304 if (Envp != nullptr)
282 execve(PathStr.c_str(),
283 const_cast(Args),
305 execve(PathStr.c_str(), const_cast(Argv),
284306 const_cast(Envp));
285307 else
286 execv(PathStr.c_str(),
287 const_cast(Args));
308 execv(PathStr.c_str(), const_cast(Argv));
288309 // If the execve() failed, we should exit. Follow Unix protocol and
289310 // return 127 if the executable was not found, and 126 otherwise.
290311 // Use _exit rather than exit so that atexit functions and static
148148
149149 }
150150
151 static SmallVector buildArgVector(const char **Args) {
152 SmallVector Result;
153 for (unsigned I = 0; Args[I]; ++I)
154 Result.push_back(StringRef(Args[I]));
155 return Result;
156 }
157
158 static bool Execute(ProcessInfo &PI, StringRef Program, const char **Args,
159 const char **Envp, ArrayRef> Redirects,
151 static bool Execute(ProcessInfo &PI, StringRef Program,
152 ArrayRef Args, Optional> Env,
153 ArrayRef> Redirects,
160154 unsigned MemoryLimit, std::string *ErrMsg) {
161155 if (!sys::fs::can_execute(Program)) {
162156 if (ErrMsg)
175169 // Windows wants a command line, not an array of args, to pass to the new
176170 // process. We have to concatenate them all, while quoting the args that
177171 // have embedded spaces (or are empty).
178 auto ArgVector = buildArgVector(Args);
179 std::string Command = flattenWindowsCommandLine(ArgVector);
172 std::string Command = flattenWindowsCommandLine(Args);
180173
181174 // The pointer to the environment block for the new process.
182175 std::vector EnvBlock;
183176
184 if (Envp) {
177 if (Env) {
185178 // An environment block consists of a null-terminated block of
186179 // null-terminated strings. Convert the array of environment variables to
187180 // an environment block by concatenating them.
188 for (unsigned i = 0; Envp[i]; ++i) {
181 for (const auto E : *Env) {
189182 SmallVector EnvString;
190 if (std::error_code ec = windows::UTF8ToUTF16(Envp[i], EnvString)) {
183 if (std::error_code ec = windows::UTF8ToUTF16(E, EnvString)) {
191184 SetLastError(ec.value());
192185 MakeErrMsg(ErrMsg, "Unable to convert environment variable to UTF-16");
193186 return false;
193193 }
194194
195195 // setup the child process' arguments
196 SmallVector<const char *, 8> Args;
196 SmallVector<StringRef, 8> Args;
197197 if (UseValgrind) {
198198 Args.push_back("valgrind");
199199 Args.push_back("--error-exitcode=1");
200200 Args.push_back("-q");
201 Args.push_back(tool.c_str());
201 Args.push_back(tool);
202202 } else
203 Args.push_back(tool.c_str());
203 Args.push_back(tool);
204204
205205 for (unsigned i = 0, e = OptArgs.size(); i != e; ++i)
206 Args.push_back(OptArgs[i].c_str());
206 Args.push_back(OptArgs[i]);
207207 Args.push_back("-disable-symbolication");
208208 Args.push_back("-o");
209 Args.push_back(OutputFilename.c_str());
209 Args.push_back(OutputFilename);
210210 std::vector pass_args;
211211 for (unsigned i = 0, e = PluginLoader::getNumPlugins(); i != e; ++i) {
212212 pass_args.push_back(std::string("-load"));
223223 Args.push_back(Temp->TmpName.c_str());
224224 for (unsigned i = 0; i < NumExtraArgs; ++i)
225225 Args.push_back(*ExtraArgs);
226 Args.push_back(nullptr);
227226
228227 LLVM_DEBUG(errs() << "\nAbout to run:\t";
229228 for (unsigned i = 0, e = Args.size() - 1; i != e; ++i) errs()
238237 }
239238
240239 std::string ErrMsg;
241 int result = sys::ExecuteAndWait(Prog, Args.data(), nullptr, Redirects,
242 Timeout, MemoryLimit, &ErrMsg);
240 int result = sys::ExecuteAndWait(Prog, Args, None, Redirects, Timeout,
241 MemoryLimit, &ErrMsg);
243242
244243 // If we are supposed to delete the bitcode file or if the passes crashed,
245244 // remove it now. This may fail if the file was never created, but that's ok.
5252 /// RunProgramWithTimeout - This function provides an alternate interface
5353 /// to the sys::Program::ExecuteAndWait interface.
5454 /// @see sys::Program::ExecuteAndWait
55 static int RunProgramWithTimeout(StringRef ProgramPath, const char **Args,
56 StringRef StdInFile, StringRef StdOutFile,
57 StringRef StdErrFile, unsigned NumSeconds = 0,
55 static int RunProgramWithTimeout(StringRef ProgramPath,
56 ArrayRef Args, StringRef StdInFile,
57 StringRef StdOutFile, StringRef StdErrFile,
58 unsigned NumSeconds = 0,
5859 unsigned MemoryLimit = 0,
5960 std::string *ErrMsg = nullptr) {
6061 Optional Redirects[3] = {StdInFile, StdOutFile, StdErrFile};
61 return sys::ExecuteAndWait(ProgramPath, Args, nullptr, Redirects, NumSeconds,
62 return sys::ExecuteAndWait(ProgramPath, Args, None, Redirects, NumSeconds,
6263 MemoryLimit, ErrMsg);
6364 }
6465
6869 /// fails. Remote client is required to return 255 if it failed or program exit
6970 /// code otherwise.
7071 /// @see sys::Program::ExecuteAndWait
71 static int RunProgramRemotelyWithTimeout(StringRef RemoteClientPath,
72 const char **Args, StringRef StdInFile,
73 StringRef StdOutFile,
74 StringRef StdErrFile,
75 unsigned NumSeconds = 0,
76 unsigned MemoryLimit = 0) {
72 static int RunProgramRemotelyWithTimeout(
73 StringRef RemoteClientPath, ArrayRef Args, StringRef StdInFile,
74 StringRef StdOutFile, StringRef StdErrFile, unsigned NumSeconds = 0,
75 unsigned MemoryLimit = 0) {
7776 Optional Redirects[3] = {StdInFile, StdOutFile, StdErrFile};
7877
7978 // Run the program remotely with the remote client
80 int ReturnCode = sys::ExecuteAndWait(RemoteClientPath, Args, nullptr,
81 Redirects, NumSeconds, MemoryLimit);
79 int ReturnCode = sys::ExecuteAndWait(RemoteClientPath, Args, None, Redirects,
80 NumSeconds, MemoryLimit);
8281
8382 // Has the remote client fail?
8483 if (255 == ReturnCode) {
8584 std::ostringstream OS;
8685 OS << "\nError running remote client:\n ";
87 for (const char **Arg = Args; *Arg; ++Arg)
88 OS << " " << *Arg;
86 for (StringRef Arg : Args)
87 OS << " " << Arg.str();
8988 OS << "\n";
9089
9190 // The error message is in the output file, let's print it out from there.
104103 return ReturnCode;
105104 }
106105
107 static Error ProcessFailure(StringRef ProgPath, const char **Args,
106 static Error ProcessFailure(StringRef ProgPath, ArrayRef Args,
108107 unsigned Timeout = 0, unsigned MemoryLimit = 0) {
109108 std::ostringstream OS;
110109 OS << "\nError running tool:\n ";
111 for (const char **Arg = Args; *Arg; ++Arg)
112 OS << " " << *Arg;
110 for (StringRef Arg : Args)
111 OS << " " << Arg.str();
113112 OS << "\n";
114113
115114 // Rerun the compiler, capturing any error messages to print them.
170169 const std::vector &CCArgs,
171170 const std::vector &SharedLibs,
172171 unsigned Timeout, unsigned MemoryLimit) {
173 std::vector<const char *> LLIArgs;
172 std::vector<StringRef> LLIArgs;
174173 LLIArgs.push_back(LLIPath.c_str());
175174 LLIArgs.push_back("-force-interpreter=true");
176175
178177 e = SharedLibs.end();
179178 i != e; ++i) {
180179 LLIArgs.push_back("-load");
181 LLIArgs.push_back((*i).c_str());
180 LLIArgs.push_back(*i);
182181 }
183182
184183 // Add any extra LLI args.
185184 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
186 LLIArgs.push_back(ToolArgs[i].c_str());
187
188 LLIArgs.push_back(Bitcode.c_str());
185 LLIArgs.push_back(ToolArgs[i]);
186
187 LLIArgs.push_back(Bitcode);
189188 // Add optional parameters to the running program from Argv
190189 for (unsigned i = 0, e = Args.size(); i != e; ++i)
191 LLIArgs.push_back(Args[i].c_str());
192 LLIArgs.push_back(nullptr);
190 LLIArgs.push_back(Args[i]);
193191
194192 outs() << "";
195193 outs().flush();
197195 for (unsigned i = 0, e = LLIArgs.size() - 1; i != e; ++i) errs()
198196 << " " << LLIArgs[i];
199197 errs() << "\n";);
200 return RunProgramWithTimeout(LLIPath, &LLIArgs[0], InputFile, OutputFile,
198 return RunProgramWithTimeout(LLIPath, LLIArgs, InputFile, OutputFile,
201199 OutputFile, Timeout, MemoryLimit);
202200 }
203201
284282 Error CustomCompiler::compileProgram(const std::string &Bitcode,
285283 unsigned Timeout, unsigned MemoryLimit) {
286284
287 std::vector<const char *> ProgramArgs;
285 std::vector<StringRef> ProgramArgs;
288286 ProgramArgs.push_back(CompilerCommand.c_str());
289287
290288 for (std::size_t i = 0; i < CompilerArgs.size(); ++i)
291289 ProgramArgs.push_back(CompilerArgs.at(i).c_str());
292 ProgramArgs.push_back(Bitcode.c_str());
293 ProgramArgs.push_back(nullptr);
290 ProgramArgs.push_back(Bitcode);
294291
295292 // Add optional parameters to the running program from Argv
296293 for (unsigned i = 0, e = CompilerArgs.size(); i != e; ++i)
297294 ProgramArgs.push_back(CompilerArgs[i].c_str());
298295
299 if (RunProgramWithTimeout(CompilerCommand, &ProgramArgs[0], "", "", "",
300 Timeout, MemoryLimit))
301 return ProcessFailure(CompilerCommand, &ProgramArgs[0], Timeout,
302 MemoryLimit);
296 if (RunProgramWithTimeout(CompilerCommand, ProgramArgs, "", "", "", Timeout,
297 MemoryLimit))
298 return ProcessFailure(CompilerCommand, ProgramArgs, Timeout, MemoryLimit);
303299 return Error::success();
304300 }
305301
335331 const std::vector &SharedLibs, unsigned Timeout,
336332 unsigned MemoryLimit) {
337333
338 std::vector ProgramArgs;
339 ProgramArgs.push_back(ExecutionCommand.c_str());
334 std::vector ProgramArgs;
335 ProgramArgs.push_back(ExecutionCommand);
340336
341337 for (std::size_t i = 0; i < ExecutorArgs.size(); ++i)
342 ProgramArgs.push_back(ExecutorArgs.at(i).c_str());
343 ProgramArgs.push_back(Bitcode.c_str());
344 ProgramArgs.push_back(nullptr);
338 ProgramArgs.push_back(ExecutorArgs[i]);
339 ProgramArgs.push_back(Bitcode);
345340
346341 // Add optional parameters to the running program from Argv
347342 for (unsigned i = 0, e = Args.size(); i != e; ++i)
348 ProgramArgs.push_back(Args[i].c_str());
349
350 return RunProgramWithTimeout(ExecutionCommand, &ProgramArgs[0], InputFile,
343 ProgramArgs.push_back(Args[i]);
344
345 return RunProgramWithTimeout(ExecutionCommand, ProgramArgs, InputFile,
351346 OutputFile, OutputFile, Timeout, MemoryLimit);
352347 }
353348
462457 exit(1);
463458 }
464459 OutputAsmFile = UniqueFile.str();
465 std::vector LLCArgs;
466 LLCArgs.push_back(LLCPath.c_str());
460 std::vector LLCArgs;
461 LLCArgs.push_back(LLCPath);
467462
468463 // Add any extra LLC args.
469464 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
470 LLCArgs.push_back(ToolArgs[i].c_str());
465 LLCArgs.push_back(ToolArgs[i]);
471466
472467 LLCArgs.push_back("-o");
473 LLCArgs.push_back(OutputAsmFile.c_str()); // Output to the Asm file
474 LLCArgs.push_back(Bitcode.c_str()); // This is the input bitcode
468 LLCArgs.push_back(OutputAsmFile); // Output to the Asm file
469 LLCArgs.push_back(Bitcode); // This is the input bitcode
475470
476471 if (UseIntegratedAssembler)
477472 LLCArgs.push_back("-filetype=obj");
478
479 LLCArgs.push_back(nullptr);
480473
481474 outs() << (UseIntegratedAssembler ? "" : "");
482475 outs().flush();
484477 for (unsigned i = 0, e = LLCArgs.size() - 1; i != e; ++i) errs()
485478 << " " << LLCArgs[i];
486479 errs() << "\n";);
487 if (RunProgramWithTimeout(LLCPath, &LLCArgs[0], "", "", "", Timeout,
488 MemoryLimit))
489 return ProcessFailure(LLCPath, &LLCArgs[0], Timeout, MemoryLimit);
480 if (RunProgramWithTimeout(LLCPath, LLCArgs, "", "", "", Timeout, MemoryLimit))
481 return ProcessFailure(LLCPath, LLCArgs, Timeout, MemoryLimit);
490482 return UseIntegratedAssembler ? CC::ObjectFile : CC::AsmFile;
491483 }
492484
580572 const std::vector &SharedLibs,
581573 unsigned Timeout, unsigned MemoryLimit) {
582574 // Construct a vector of parameters, incorporating those from the command-line
583 std::vector<const char *> JITArgs;
575 std::vector<StringRef> JITArgs;
584576 JITArgs.push_back(LLIPath.c_str());
585577 JITArgs.push_back("-force-interpreter=false");
586578
587579 // Add any extra LLI args.
588580 for (unsigned i = 0, e = ToolArgs.size(); i != e; ++i)
589 JITArgs.push_back(ToolArgs[i].c_str());
581 JITArgs.push_back(ToolArgs[i]);
590582
591583 for (unsigned i = 0, e = SharedLibs.size(); i != e; ++i) {
592584 JITArgs.push_back("-load");
593 JITArgs.push_back(SharedLibs[i].c_str());
585 JITArgs.push_back(SharedLibs[i]);
594586 }
595587 JITArgs.push_back(Bitcode.c_str());
596588 // Add optional parameters to the running program from Argv
597589 for (unsigned i = 0, e = Args.size(); i != e; ++i)
598 JITArgs.push_back(Args[i].c_str());
599 JITArgs.push_back(nullptr);
590 JITArgs.push_back(Args[i]);
600591
601592 outs() << "";
602593 outs().flush();
605596 << " " << JITArgs[i];
606597 errs() << "\n";);
607598 LLVM_DEBUG(errs() << "\nSending output to " << OutputFile << "\n");
608 return RunProgramWithTimeout(LLIPath, &JITArgs[0], InputFile, OutputFile,
599 return RunProgramWithTimeout(LLIPath, JITArgs, InputFile, OutputFile,
609600 OutputFile, Timeout, MemoryLimit);
610601 }
611602
629620 // CC abstraction
630621 //
631622
632 static bool IsARMArchitecture(std::vector Args) {
633 for (std::vector::const_iterator I = Args.begin(),
634 E = Args.end();
635 I != E; ++I) {
636 if (StringRef(*I).equals_lower("-arch")) {
637 ++I;
638 if (I != E && StringRef(*I).startswith_lower("arm"))
639 return true;
640 }
623 static bool IsARMArchitecture(std::vector Args) {
624 for (size_t I = 0; I < Args.size(); ++I) {
625 if (!Args[I].equals_lower("-arch"))
626 continue;
627 ++I;
628 if (I == Args.size())
629 break;
630 if (Args[I].startswith_lower("arm"))
631 return true;
641632 }
642633
643634 return false;
650641 const std::string &OutputFile,
651642 const std::vector &ArgsForCC,
652643 unsigned Timeout, unsigned MemoryLimit) {
653 std::vector CCArgs;
654
655 CCArgs.push_back(CCPath.c_str());
644 std::vector CCArgs;
645
646 CCArgs.push_back(CCPath);
656647
657648 if (TargetTriple.getArch() == Triple::x86)
658649 CCArgs.push_back("-m32");
660651 for (std::vector::const_iterator I = ccArgs.begin(),
661652 E = ccArgs.end();
662653 I != E; ++I)
663 CCArgs.push_back(I->c_str());
654 CCArgs.push_back(*I);
664655
665656 // Specify -x explicitly in case the extension is wonky
666657 if (fileType != ObjectFile) {
679670 }
680671 }
681672
682 CCArgs.push_back(ProgramFile.c_str()); // Specify the input filename.
673 CCArgs.push_back(ProgramFile); // Specify the input filename.
683674
684675 CCArgs.push_back("-x");
685676 CCArgs.push_back("none");
692683 errs() << "Error making unique filename: " << EC.message() << "\n";
693684 exit(1);
694685 }
695 CCArgs.push_back(OutputBinary.c_str()); // Output to the right file...
686 CCArgs.push_back(OutputBinary); // Output to the right file...
696687
697688 // Add any arguments intended for CC. We locate them here because this is
698689 // most likely -L and -l options that need to come before other libraries but
699690 // after the source. Other options won't be sensitive to placement on the
700691 // command line, so this should be safe.
701692 for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i)
702 CCArgs.push_back(ArgsForCC[i].c_str());
693 CCArgs.push_back(ArgsForCC[i]);
703694
704695 CCArgs.push_back("-lm"); // Hard-code the math library...
705696 CCArgs.push_back("-O2"); // Optimize the program a bit...
706697 if (TargetTriple.getArch() == Triple::sparc)
707698 CCArgs.push_back("-mcpu=v9");
708 CCArgs.push_back(nullptr); // NULL terminator
709699
710700 outs() << "";
711701 outs().flush();
713703 for (unsigned i = 0, e = CCArgs.size() - 1; i != e; ++i) errs()
714704 << " " << CCArgs[i];
715705 errs() << "\n";);
716 if (RunProgramWithTimeout(CCPath, &CCArgs[0], "", "", ""))
717 return ProcessFailure(CCPath, &CCArgs[0]);
718
719 std::vector ProgramArgs;
706 if (RunProgramWithTimeout(CCPath, CCArgs, "", "", ""))
707 return ProcessFailure(CCPath, CCArgs);
708
709 std::vector ProgramArgs;
720710
721711 // Declared here so that the destructor only runs after
722712 // ProgramArgs is used.
723713 std::string Exec;
724714
725715 if (RemoteClientPath.empty())
726 ProgramArgs.push_back(OutputBinary.c_str());
716 ProgramArgs.push_back(OutputBinary);
727717 else {
728 ProgramArgs.push_back(RemoteClientPath.c_str());
729 ProgramArgs.push_back(RemoteHost.c_str());
718 ProgramArgs.push_back(RemoteClientPath);
719 ProgramArgs.push_back(RemoteHost);
730720 if (!RemoteUser.empty()) {
731721 ProgramArgs.push_back("-l");
732 ProgramArgs.push_back(RemoteUser.c_str());
722 ProgramArgs.push_back(RemoteUser);
733723 }
734724 if (!RemotePort.empty()) {
735725 ProgramArgs.push_back("-p");
736 ProgramArgs.push_back(RemotePort.c_str());
726 ProgramArgs.push_back(RemotePort);
737727 }
738728 if (!RemoteExtra.empty()) {
739 ProgramArgs.push_back(RemoteExtra.c_str());
729 ProgramArgs.push_back(RemoteExtra);
740730 }
741731
742732 // Full path to the binary. We need to cd to the exec directory because
746736 Exec += env_pwd;
747737 Exec += "; ./";
748738 Exec += OutputBinary.c_str();
749 ProgramArgs.push_back(Exec.c_str());
739 ProgramArgs.push_back(Exec);
750740 }
751741
752742 // Add optional parameters to the running program from Argv
753743 for (unsigned i = 0, e = Args.size(); i != e; ++i)
754 ProgramArgs.push_back(Args[i].c_str());
755 ProgramArgs.push_back(nullptr); // NULL terminator
744 ProgramArgs.push_back(Args[i]);
756745
757746 // Now that we have a binary, run it!
758747 outs() << "";
768757 if (RemoteClientPath.empty()) {
769758 LLVM_DEBUG(errs() << "");
770759 std::string Error;
771 int ExitCode = RunProgramWithTimeout(OutputBinary.str(), &ProgramArgs[0],
760 int ExitCode = RunProgramWithTimeout(OutputBinary.str(), ProgramArgs,
772761 InputFile, OutputFile, OutputFile,
773762 Timeout, MemoryLimit, &Error);
774763 // Treat a signal (usually SIGSEGV) or timeout as part of the program output
782771 } else {
783772 outs() << "";
784773 outs().flush();
785 return RunProgramRemotelyWithTimeout(RemoteClientPath, &ProgramArgs[0],
774 return RunProgramRemotelyWithTimeout(RemoteClientPath, ProgramArgs,
786775 InputFile, OutputFile, OutputFile,
787776 Timeout, MemoryLimit);
788777 }
800789 }
801790 OutputFile = UniqueFilename.str();
802791
803 std::vector CCArgs;
804
805 CCArgs.push_back(CCPath.c_str());
792 std::vector CCArgs;
793
794 CCArgs.push_back(CCPath);
806795
807796 if (TargetTriple.getArch() == Triple::x86)
808797 CCArgs.push_back("-m32");
810799 for (std::vector::const_iterator I = ccArgs.begin(),
811800 E = ccArgs.end();
812801 I != E; ++I)
813 CCArgs.push_back(I->c_str());
802 CCArgs.push_back(*I);
814803
815804 // Compile the C/asm file into a shared object
816805 if (fileType != ObjectFile) {
818807 CCArgs.push_back(fileType == AsmFile ? "assembler" : "c");
819808 }
820809 CCArgs.push_back("-fno-strict-aliasing");
821 CCArgs.push_back(InputFile.c_str()); // Specify the input filename.
810 CCArgs.push_back(InputFile); // Specify the input filename.
822811 CCArgs.push_back("-x");
823812 CCArgs.push_back("none");
824813 if (TargetTriple.getArch() == Triple::sparc)
842831 CCArgs.push_back("-mcpu=v9");
843832
844833 CCArgs.push_back("-o");
845 CCArgs.push_back(OutputFile.c_str()); // Output to the right filename.
834 CCArgs.push_back(OutputFile); // Output to the right filename.
846835 CCArgs.push_back("-O2"); // Optimize the program a bit.
847836
848837 // Add any arguments intended for CC. We locate them here because this is
850839 // after the source. Other options won't be sensitive to placement on the
851840 // command line, so this should be safe.
852841 for (unsigned i = 0, e = ArgsForCC.size(); i != e; ++i)
853 CCArgs.push_back(ArgsForCC[i].c_str());
854 CCArgs.push_back(nullptr); // NULL terminator
842 CCArgs.push_back(ArgsForCC[i]);
855843
856844 outs() << "";
857845 outs().flush();
859847 for (unsigned i = 0, e = CCArgs.size() - 1; i != e; ++i) errs()
860848 << " " << CCArgs[i];
861849 errs() << "\n";);
862 if (RunProgramWithTimeout(CCPath, &CCArgs[0], "", "", ""))
863 return ProcessFailure(CCPath, &CCArgs[0]);
850 if (RunProgramWithTimeout(CCPath, CCArgs, "", "", ""))
851 return ProcessFailure(CCPath, CCArgs);
864852 return Error::success();
865853 }
866854
3232 return Arch;
3333 }
3434
35 static bool runLipo(StringRef SDKPath, SmallVectorImpl<const char *> &Args) {
35 static bool runLipo(StringRef SDKPath, SmallVectorImpl<StringRef> &Args) {
3636 auto Path = sys::findProgramByName("lipo", makeArrayRef(SDKPath));
3737 if (!Path)
3838 Path = sys::findProgramByName("lipo");
4343 }
4444
4545 std::string ErrMsg;
46 int result =
47 sys::ExecuteAndWait(*Path, Args.data(), nullptr, {}, 0, 0, &ErrMsg);
46 int result = sys::ExecuteAndWait(*Path, Args, None, {}, 0, 0, &ErrMsg);
4847 if (result) {
4948 WithColor::error() << "lipo: " << ErrMsg << "\n";
5049 return false;
7271 return true;
7372 }
7473
75 SmallVector<const char *, 8> Args;
74 SmallVector<StringRef, 8> Args;
7675 Args.push_back("lipo");
7776 Args.push_back("-create");
7877
7978 for (auto &Thin : ArchFiles)
80 Args.push_back(Thin.Path.c_str());
79 Args.push_back(Thin.Path);
8180
8281 // Align segments to match dsymutil-classic alignment
8382 for (auto &Thin : ArchFiles) {
8483 Thin.Arch = getArchName(Thin.Arch);
8584 Args.push_back("-segalign");
86 Args.push_back(Thin.Arch.c_str());
85 Args.push_back(Thin.Arch);
8786 Args.push_back("20");
8887 }
8988
9089 Args.push_back("-output");
9190 Args.push_back(OutputFileName.data());
92 Args.push_back(nullptr);
9391
9492 if (Options.Verbose) {
9593 outs() << "Running lipo\n";
9694 for (auto Arg : Args)
97 outs() << ' ' << ((Arg == nullptr) ? "\n" : Arg);
95 outs() << ' ' << Arg;
96 outs() << "\n";
9897 }
9998
10099 return Options.NoOutput ? true : runLipo(SDKPath, Args);
477477 OutputTOF.os().close();
478478
479479 // Invoke the demangler.
480 std::vector ArgsV;
481 for (const std::string &Arg : ViewOpts.DemanglerOpts)
482 ArgsV.push_back(Arg.c_str());
483 ArgsV.push_back(nullptr);
480 std::vector ArgsV;
481 for (StringRef Arg : ViewOpts.DemanglerOpts)
482 ArgsV.push_back(Arg);
484483 Optional Redirects[] = {InputPath.str(), OutputPath.str(), {""}};
485484 std::string ErrMsg;
486 int RC = sys::ExecuteAndWait(ViewOpts.DemanglerOpts[0], ArgsV.data(),
487 /*env=*/nullptr, Redirects, /*secondsToWait=*/0,
485 int RC = sys::ExecuteAndWait(ViewOpts.DemanglerOpts[0], ArgsV,
486 /*env=*/None, Redirects, /*secondsToWait=*/0,
488487 /*memoryLimit=*/0, &ErrMsg);
489488 if (RC) {
490489 error(ErrMsg, ViewOpts.DemanglerOpts[0]);
184184 path::append(OutputFile, "out");
185185
186186 const char *SwVersPath = "/usr/bin/sw_vers";
187 const char *argv[] = {SwVersPath, "-productVersion", nullptr};
187 StringRef argv[] = {SwVersPath, "-productVersion"};
188188 StringRef OutputPath = OutputFile.str();
189189 const Optional Redirects[] = {/*STDIN=*/None,
190190 /*STDOUT=*/OutputPath,
191191 /*STDERR=*/None};
192 int RetCode = ExecuteAndWait(SwVersPath, argv, /*env=*/nullptr, Redirects);
192 int RetCode = ExecuteAndWait(SwVersPath, argv, /*env=*/llvm::None, Redirects);
193193 ASSERT_EQ(0, RetCode);
194194
195195 int FD = 0;
5959 ProgramTestStringArg2("program-test-string-arg2");
6060
6161 class ProgramEnvTest : public testing::Test {
62 std::vector<const char *> EnvTable;
62 std::vector<StringRef> EnvTable;
6363 std::vector EnvStorage;
6464
6565 protected:
7676 }();
7777 ASSERT_TRUE(EnvP);
7878
79 auto prepareEnvVar = [this](decltype(*EnvP) Var) {
79 auto prepareEnvVar = [this](decltype(*EnvP) Var) -> StringRef {
8080 #if defined(_WIN32)
8181 // On Windows convert UTF16 encoded variable to UTF8
8282 auto Len = wcslen(Var);
8585 EnvStorage.emplace_back();
8686 auto convStatus = convertUTF16ToUTF8String(Ref, EnvStorage.back());
8787 EXPECT_TRUE(convStatus);
88 return EnvStorage.back().c_str();
88 return EnvStorage.back();
8989 #else
9090 (void)this;
91 return Var;
91 return StringRef(Var);
9292 #endif
9393 };
9494
103103 EnvStorage.clear();
104104 }
105105
106 void addEnvVar(const char *Var) {
107 ASSERT_TRUE(EnvTable.empty() || EnvTable.back()) << "Env table sealed";
108 EnvTable.emplace_back(Var);
109 }
110
111 const char **getEnviron() {
112 if (EnvTable.back() != nullptr)
113 EnvTable.emplace_back(nullptr); // Seal table.
114 return &EnvTable[0];
115 }
106 void addEnvVar(StringRef Var) { EnvTable.emplace_back(Var); }
107
108 ArrayRef getEnviron() const { return EnvTable; }
116109 };
117110
118111 #ifdef _WIN32
128121 MyExe.append("\\\\?\\");
129122 MyExe.append(MyAbsExe);
130123
131 const char *ArgV[] = {
132 MyExe.c_str(),
133 "--gtest_filter=ProgramEnvTest.CreateProcessLongPath",
134 nullptr
135 };
124 StringRef ArgV[] = {MyExe,
125 "--gtest_filter=ProgramEnvTest.CreateProcessLongPath"};
136126
137127 // Add LLVM_PROGRAM_TEST_LONG_PATH to the environment of the child.
138128 addEnvVar("LLVM_PROGRAM_TEST_LONG_PATH=1");
172162
173163 std::string my_exe =
174164 sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
175 const char *argv[] = {
176 my_exe.c_str(),
177 "--gtest_filter=ProgramEnvTest.CreateProcessTrailingSlash",
178 "-program-test-string-arg1", "has\\\\ trailing\\",
179 "-program-test-string-arg2", "has\\\\ trailing\\",
180 nullptr
181 };
165 StringRef argv[] = {
166 my_exe,
167 "--gtest_filter=ProgramEnvTest.CreateProcessTrailingSlash",
168 "-program-test-string-arg1",
169 "has\\\\ trailing\\",
170 "-program-test-string-arg2",
171 "has\\\\ trailing\\"};
182172
183173 // Add LLVM_PROGRAM_TEST_CHILD to the environment of the child.
184174 addEnvVar("LLVM_PROGRAM_TEST_CHILD=1");
209199
210200 std::string Executable =
211201 sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
212 const char *argv[] = {
213 Executable.c_str(),
214 "--gtest_filter=ProgramEnvTest.TestExecuteNoWait",
215 nullptr
216 };
202 StringRef argv[] = {Executable,
203 "--gtest_filter=ProgramEnvTest.TestExecuteNoWait"};
217204
218205 // Add LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT to the environment of the child.
219206 addEnvVar("LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT=1");
267254
268255 std::string Executable =
269256 sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
270 const char *argv[] = {
271 Executable.c_str(),
272 "--gtest_filter=ProgramEnvTest.TestExecuteAndWaitTimeout",
273 nullptr
274 };
257 StringRef argv[] = {
258 Executable, "--gtest_filter=ProgramEnvTest.TestExecuteAndWaitTimeout"};
275259
276260 // Add LLVM_PROGRAM_TEST_TIMEOUT to the environment of the child.
277261 addEnvVar("LLVM_PROGRAM_TEST_TIMEOUT=1");
286270
287271 TEST(ProgramTest, TestExecuteNegative) {
288272 std::string Executable = "i_dont_exist";
289 const char *argv[] = { Executable.c_str(), nullptr };
273 StringRef argv[] = {Executable};
290274
291275 {
292276 std::string Error;
293277 bool ExecutionFailed;
294 int RetCode = ExecuteAndWait(Executable, argv, nullptr, {}, 0, 0, &Error,
278 int RetCode = ExecuteAndWait(Executable, argv, llvm::None, {}, 0, 0, &Error,
295279 &ExecutionFailed);
296280 ASSERT_TRUE(RetCode < 0) << "On error ExecuteAndWait should return 0 or "
297281 "positive value indicating the result code";
302286 {
303287 std::string Error;
304288 bool ExecutionFailed;
305 ProcessInfo PI = ExecuteNoWait(Executable, argv, nullptr, {}, 0, &Error,
289 ProcessInfo PI = ExecuteNoWait(Executable, argv, llvm::None, {}, 0, &Error,
306290 &ExecutionFailed);
307291 ASSERT_EQ(PI.Pid, ProcessInfo::InvalidPid)
308292 << "On error ExecuteNoWait should return an invalid ProcessInfo";
3737 return 1;
3838 }
3939
40 std::vector Argv;
41 Argv.reserve(argc);
42 for (int i = 0; i < argc; ++i)
43 Argv.push_back(argv[i]);
4044 std::string ErrMsg;
41 int Result = sys::ExecuteAndWait(*Program, argv, nullptr, {}, 0, 0, &ErrMsg);
45 int Result = sys::ExecuteAndWait(*Program, Argv, None, {}, 0, 0, &ErrMsg);
4246 #ifdef _WIN32
4347 // Handle abort() in msvcrt -- It has exit code as 3. abort(), aka
4448 // unreachable, should be recognized as a crash. However, some binaries use