[mlir][int-range] Limit xor int range inference to i1 (#116968)
[llvm-project.git] / lldb / source / Commands / CommandObjectLog.cpp
blob5fb2dfaab8de03135428cb688e9fab54f3dd4d02
1 //===-- CommandObjectLog.cpp ----------------------------------------------===//
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 //===----------------------------------------------------------------------===//
9 #include "CommandObjectLog.h"
10 #include "lldb/Core/Debugger.h"
11 #include "lldb/Host/OptionParser.h"
12 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
13 #include "lldb/Interpreter/CommandReturnObject.h"
14 #include "lldb/Interpreter/OptionArgParser.h"
15 #include "lldb/Interpreter/OptionValueEnumeration.h"
16 #include "lldb/Interpreter/OptionValueUInt64.h"
17 #include "lldb/Interpreter/Options.h"
18 #include "lldb/Utility/Args.h"
19 #include "lldb/Utility/FileSpec.h"
20 #include "lldb/Utility/Log.h"
21 #include "lldb/Utility/Stream.h"
22 #include "lldb/Utility/Timer.h"
24 using namespace lldb;
25 using namespace lldb_private;
27 #define LLDB_OPTIONS_log_enable
28 #include "CommandOptions.inc"
30 #define LLDB_OPTIONS_log_dump
31 #include "CommandOptions.inc"
33 /// Common completion logic for log enable/disable.
34 static void CompleteEnableDisable(CompletionRequest &request) {
35 size_t arg_index = request.GetCursorIndex();
36 if (arg_index == 0) { // We got: log enable/disable x[tab]
37 for (llvm::StringRef channel : Log::ListChannels())
38 request.TryCompleteCurrentArg(channel);
39 } else if (arg_index >= 1) { // We got: log enable/disable channel x[tab]
40 llvm::StringRef channel = request.GetParsedLine().GetArgumentAtIndex(0);
41 Log::ForEachChannelCategory(
42 channel, [&request](llvm::StringRef name, llvm::StringRef desc) {
43 request.TryCompleteCurrentArg(name, desc);
44 });
48 class CommandObjectLogEnable : public CommandObjectParsed {
49 public:
50 // Constructors and Destructors
51 CommandObjectLogEnable(CommandInterpreter &interpreter)
52 : CommandObjectParsed(interpreter, "log enable",
53 "Enable logging for a single log channel.",
54 nullptr) {
55 CommandArgumentEntry arg1;
56 CommandArgumentEntry arg2;
57 CommandArgumentData channel_arg;
58 CommandArgumentData category_arg;
60 // Define the first (and only) variant of this arg.
61 channel_arg.arg_type = eArgTypeLogChannel;
62 channel_arg.arg_repetition = eArgRepeatPlain;
64 // There is only one variant this argument could be; put it into the
65 // argument entry.
66 arg1.push_back(channel_arg);
68 category_arg.arg_type = eArgTypeLogCategory;
69 category_arg.arg_repetition = eArgRepeatPlus;
71 arg2.push_back(category_arg);
73 // Push the data for the first argument into the m_arguments vector.
74 m_arguments.push_back(arg1);
75 m_arguments.push_back(arg2);
78 ~CommandObjectLogEnable() override = default;
80 Options *GetOptions() override { return &m_options; }
82 class CommandOptions : public Options {
83 public:
84 CommandOptions() = default;
86 ~CommandOptions() override = default;
88 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
89 ExecutionContext *execution_context) override {
90 Status error;
91 const int short_option = m_getopt_table[option_idx].val;
93 switch (short_option) {
94 case 'f':
95 log_file.SetFile(option_arg, FileSpec::Style::native);
96 FileSystem::Instance().Resolve(log_file);
97 break;
98 case 'h':
99 handler = (LogHandlerKind)OptionArgParser::ToOptionEnum(
100 option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
101 if (!error.Success())
102 return Status::FromErrorStringWithFormatv(
103 "unrecognized value for log handler '{0}'", option_arg);
104 break;
105 case 'b':
106 return buffer_size.SetValueFromString(option_arg,
107 eVarSetOperationAssign);
108 case 'v':
109 log_options |= LLDB_LOG_OPTION_VERBOSE;
110 break;
111 case 's':
112 log_options |= LLDB_LOG_OPTION_PREPEND_SEQUENCE;
113 break;
114 case 'T':
115 log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP;
116 break;
117 case 'p':
118 log_options |= LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD;
119 break;
120 case 'n':
121 log_options |= LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
122 break;
123 case 'S':
124 log_options |= LLDB_LOG_OPTION_BACKTRACE;
125 break;
126 case 'a':
127 log_options |= LLDB_LOG_OPTION_APPEND;
128 break;
129 case 'F':
130 log_options |= LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION;
131 break;
132 default:
133 llvm_unreachable("Unimplemented option");
136 return error;
139 void OptionParsingStarting(ExecutionContext *execution_context) override {
140 log_file.Clear();
141 buffer_size.Clear();
142 handler = eLogHandlerStream;
143 log_options = 0;
146 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
147 return llvm::ArrayRef(g_log_enable_options);
150 FileSpec log_file;
151 OptionValueUInt64 buffer_size;
152 LogHandlerKind handler = eLogHandlerStream;
153 uint32_t log_options = 0;
156 void
157 HandleArgumentCompletion(CompletionRequest &request,
158 OptionElementVector &opt_element_vector) override {
159 CompleteEnableDisable(request);
162 protected:
163 void DoExecute(Args &args, CommandReturnObject &result) override {
164 if (args.GetArgumentCount() < 2) {
165 result.AppendErrorWithFormat(
166 "%s takes a log channel and one or more log types.\n",
167 m_cmd_name.c_str());
168 return;
171 if (m_options.handler == eLogHandlerCircular &&
172 m_options.buffer_size.GetCurrentValue() == 0) {
173 result.AppendError(
174 "the circular buffer handler requires a non-zero buffer size.\n");
175 return;
178 if ((m_options.handler != eLogHandlerCircular &&
179 m_options.handler != eLogHandlerStream) &&
180 m_options.buffer_size.GetCurrentValue() != 0) {
181 result.AppendError("a buffer size can only be specified for the circular "
182 "and stream buffer handler.\n");
183 return;
186 if (m_options.handler != eLogHandlerStream && m_options.log_file) {
187 result.AppendError(
188 "a file name can only be specified for the stream handler.\n");
189 return;
192 // Store into a std::string since we're about to shift the channel off.
193 const std::string channel = std::string(args[0].ref());
194 args.Shift(); // Shift off the channel
195 char log_file[PATH_MAX];
196 if (m_options.log_file)
197 m_options.log_file.GetPath(log_file, sizeof(log_file));
198 else
199 log_file[0] = '\0';
201 std::string error;
202 llvm::raw_string_ostream error_stream(error);
203 bool success = GetDebugger().EnableLog(
204 channel, args.GetArgumentArrayRef(), log_file, m_options.log_options,
205 m_options.buffer_size.GetCurrentValue(), m_options.handler,
206 error_stream);
207 result.GetErrorStream() << error;
209 if (success)
210 result.SetStatus(eReturnStatusSuccessFinishNoResult);
211 else
212 result.SetStatus(eReturnStatusFailed);
215 CommandOptions m_options;
218 class CommandObjectLogDisable : public CommandObjectParsed {
219 public:
220 // Constructors and Destructors
221 CommandObjectLogDisable(CommandInterpreter &interpreter)
222 : CommandObjectParsed(interpreter, "log disable",
223 "Disable one or more log channel categories.",
224 nullptr) {
225 CommandArgumentEntry arg1;
226 CommandArgumentEntry arg2;
227 CommandArgumentData channel_arg;
228 CommandArgumentData category_arg;
230 // Define the first (and only) variant of this arg.
231 channel_arg.arg_type = eArgTypeLogChannel;
232 channel_arg.arg_repetition = eArgRepeatPlain;
234 // There is only one variant this argument could be; put it into the
235 // argument entry.
236 arg1.push_back(channel_arg);
238 category_arg.arg_type = eArgTypeLogCategory;
239 category_arg.arg_repetition = eArgRepeatPlus;
241 arg2.push_back(category_arg);
243 // Push the data for the first argument into the m_arguments vector.
244 m_arguments.push_back(arg1);
245 m_arguments.push_back(arg2);
248 ~CommandObjectLogDisable() override = default;
250 void
251 HandleArgumentCompletion(CompletionRequest &request,
252 OptionElementVector &opt_element_vector) override {
253 CompleteEnableDisable(request);
256 protected:
257 void DoExecute(Args &args, CommandReturnObject &result) override {
258 if (args.empty()) {
259 result.AppendErrorWithFormat(
260 "%s takes a log channel and one or more log types.\n",
261 m_cmd_name.c_str());
262 return;
265 const std::string channel = std::string(args[0].ref());
266 args.Shift(); // Shift off the channel
267 if (channel == "all") {
268 Log::DisableAllLogChannels();
269 result.SetStatus(eReturnStatusSuccessFinishNoResult);
270 } else {
271 std::string error;
272 llvm::raw_string_ostream error_stream(error);
273 if (Log::DisableLogChannel(channel, args.GetArgumentArrayRef(),
274 error_stream))
275 result.SetStatus(eReturnStatusSuccessFinishNoResult);
276 result.GetErrorStream() << error;
281 class CommandObjectLogList : public CommandObjectParsed {
282 public:
283 // Constructors and Destructors
284 CommandObjectLogList(CommandInterpreter &interpreter)
285 : CommandObjectParsed(interpreter, "log list",
286 "List the log categories for one or more log "
287 "channels. If none specified, lists them all.",
288 nullptr) {
289 AddSimpleArgumentList(eArgTypeLogChannel, eArgRepeatStar);
292 ~CommandObjectLogList() override = default;
294 void
295 HandleArgumentCompletion(CompletionRequest &request,
296 OptionElementVector &opt_element_vector) override {
297 for (llvm::StringRef channel : Log::ListChannels())
298 request.TryCompleteCurrentArg(channel);
301 protected:
302 void DoExecute(Args &args, CommandReturnObject &result) override {
303 std::string output;
304 llvm::raw_string_ostream output_stream(output);
305 if (args.empty()) {
306 Log::ListAllLogChannels(output_stream);
307 result.SetStatus(eReturnStatusSuccessFinishResult);
308 } else {
309 bool success = true;
310 for (const auto &entry : args.entries())
311 success =
312 success && Log::ListChannelCategories(entry.ref(), output_stream);
313 if (success)
314 result.SetStatus(eReturnStatusSuccessFinishResult);
316 result.GetOutputStream() << output;
319 class CommandObjectLogDump : public CommandObjectParsed {
320 public:
321 CommandObjectLogDump(CommandInterpreter &interpreter)
322 : CommandObjectParsed(interpreter, "log dump",
323 "dump circular buffer logs", nullptr) {
324 AddSimpleArgumentList(eArgTypeLogChannel);
327 ~CommandObjectLogDump() override = default;
329 Options *GetOptions() override { return &m_options; }
331 class CommandOptions : public Options {
332 public:
333 CommandOptions() = default;
335 ~CommandOptions() override = default;
337 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
338 ExecutionContext *execution_context) override {
339 Status error;
340 const int short_option = m_getopt_table[option_idx].val;
342 switch (short_option) {
343 case 'f':
344 log_file.SetFile(option_arg, FileSpec::Style::native);
345 FileSystem::Instance().Resolve(log_file);
346 break;
347 default:
348 llvm_unreachable("Unimplemented option");
351 return error;
354 void OptionParsingStarting(ExecutionContext *execution_context) override {
355 log_file.Clear();
358 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
359 return llvm::ArrayRef(g_log_dump_options);
362 FileSpec log_file;
365 void
366 HandleArgumentCompletion(CompletionRequest &request,
367 OptionElementVector &opt_element_vector) override {
368 CompleteEnableDisable(request);
371 protected:
372 void DoExecute(Args &args, CommandReturnObject &result) override {
373 if (args.empty()) {
374 result.AppendErrorWithFormat(
375 "%s takes a log channel and one or more log types.\n",
376 m_cmd_name.c_str());
377 return;
380 std::unique_ptr<llvm::raw_ostream> stream_up;
381 if (m_options.log_file) {
382 const File::OpenOptions flags = File::eOpenOptionWriteOnly |
383 File::eOpenOptionCanCreate |
384 File::eOpenOptionTruncate;
385 llvm::Expected<FileUP> file = FileSystem::Instance().Open(
386 m_options.log_file, flags, lldb::eFilePermissionsFileDefault, false);
387 if (!file) {
388 result.AppendErrorWithFormat("Unable to open log file '%s': %s",
389 m_options.log_file.GetPath().c_str(),
390 llvm::toString(file.takeError()).c_str());
391 return;
393 stream_up = std::make_unique<llvm::raw_fd_ostream>(
394 (*file)->GetDescriptor(), /*shouldClose=*/true);
395 } else {
396 stream_up = std::make_unique<llvm::raw_fd_ostream>(
397 GetDebugger().GetOutputFile().GetDescriptor(), /*shouldClose=*/false);
400 const std::string channel = std::string(args[0].ref());
401 std::string error;
402 llvm::raw_string_ostream error_stream(error);
403 if (Log::DumpLogChannel(channel, *stream_up, error_stream)) {
404 result.SetStatus(eReturnStatusSuccessFinishNoResult);
405 } else {
406 result.SetStatus(eReturnStatusFailed);
407 result.GetErrorStream() << error;
411 CommandOptions m_options;
414 class CommandObjectLogTimerEnable : public CommandObjectParsed {
415 public:
416 // Constructors and Destructors
417 CommandObjectLogTimerEnable(CommandInterpreter &interpreter)
418 : CommandObjectParsed(interpreter, "log timers enable",
419 "enable LLDB internal performance timers",
420 "log timers enable <depth>") {
421 AddSimpleArgumentList(eArgTypeCount, eArgRepeatOptional);
424 ~CommandObjectLogTimerEnable() override = default;
426 protected:
427 void DoExecute(Args &args, CommandReturnObject &result) override {
428 result.SetStatus(eReturnStatusFailed);
430 if (args.GetArgumentCount() == 0) {
431 Timer::SetDisplayDepth(UINT32_MAX);
432 result.SetStatus(eReturnStatusSuccessFinishNoResult);
433 } else if (args.GetArgumentCount() == 1) {
434 uint32_t depth;
435 if (args[0].ref().consumeInteger(0, depth)) {
436 result.AppendError(
437 "Could not convert enable depth to an unsigned integer.");
438 } else {
439 Timer::SetDisplayDepth(depth);
440 result.SetStatus(eReturnStatusSuccessFinishNoResult);
444 if (!result.Succeeded()) {
445 result.AppendError("Missing subcommand");
446 result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
451 class CommandObjectLogTimerDisable : public CommandObjectParsed {
452 public:
453 // Constructors and Destructors
454 CommandObjectLogTimerDisable(CommandInterpreter &interpreter)
455 : CommandObjectParsed(interpreter, "log timers disable",
456 "disable LLDB internal performance timers",
457 nullptr) {}
459 ~CommandObjectLogTimerDisable() override = default;
461 protected:
462 void DoExecute(Args &args, CommandReturnObject &result) override {
463 Timer::DumpCategoryTimes(result.GetOutputStream());
464 Timer::SetDisplayDepth(0);
465 result.SetStatus(eReturnStatusSuccessFinishResult);
467 if (!result.Succeeded()) {
468 result.AppendError("Missing subcommand");
469 result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
474 class CommandObjectLogTimerDump : public CommandObjectParsed {
475 public:
476 // Constructors and Destructors
477 CommandObjectLogTimerDump(CommandInterpreter &interpreter)
478 : CommandObjectParsed(interpreter, "log timers dump",
479 "dump LLDB internal performance timers", nullptr) {}
481 ~CommandObjectLogTimerDump() override = default;
483 protected:
484 void DoExecute(Args &args, CommandReturnObject &result) override {
485 Timer::DumpCategoryTimes(result.GetOutputStream());
486 result.SetStatus(eReturnStatusSuccessFinishResult);
488 if (!result.Succeeded()) {
489 result.AppendError("Missing subcommand");
490 result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
495 class CommandObjectLogTimerReset : public CommandObjectParsed {
496 public:
497 // Constructors and Destructors
498 CommandObjectLogTimerReset(CommandInterpreter &interpreter)
499 : CommandObjectParsed(interpreter, "log timers reset",
500 "reset LLDB internal performance timers", nullptr) {
503 ~CommandObjectLogTimerReset() override = default;
505 protected:
506 void DoExecute(Args &args, CommandReturnObject &result) override {
507 Timer::ResetCategoryTimes();
508 result.SetStatus(eReturnStatusSuccessFinishResult);
510 if (!result.Succeeded()) {
511 result.AppendError("Missing subcommand");
512 result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
517 class CommandObjectLogTimerIncrement : public CommandObjectParsed {
518 public:
519 // Constructors and Destructors
520 CommandObjectLogTimerIncrement(CommandInterpreter &interpreter)
521 : CommandObjectParsed(interpreter, "log timers increment",
522 "increment LLDB internal performance timers",
523 "log timers increment <bool>") {
524 AddSimpleArgumentList(eArgTypeBoolean);
527 ~CommandObjectLogTimerIncrement() override = default;
529 void
530 HandleArgumentCompletion(CompletionRequest &request,
531 OptionElementVector &opt_element_vector) override {
532 request.TryCompleteCurrentArg("true");
533 request.TryCompleteCurrentArg("false");
536 protected:
537 void DoExecute(Args &args, CommandReturnObject &result) override {
538 result.SetStatus(eReturnStatusFailed);
540 if (args.GetArgumentCount() == 1) {
541 bool success;
542 bool increment =
543 OptionArgParser::ToBoolean(args[0].ref(), false, &success);
545 if (success) {
546 Timer::SetQuiet(!increment);
547 result.SetStatus(eReturnStatusSuccessFinishNoResult);
548 } else
549 result.AppendError("Could not convert increment value to boolean.");
552 if (!result.Succeeded()) {
553 result.AppendError("Missing subcommand");
554 result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
559 class CommandObjectLogTimer : public CommandObjectMultiword {
560 public:
561 CommandObjectLogTimer(CommandInterpreter &interpreter)
562 : CommandObjectMultiword(interpreter, "log timers",
563 "Enable, disable, dump, and reset LLDB internal "
564 "performance timers.",
565 "log timers < enable <depth> | disable | dump | "
566 "increment <bool> | reset >") {
567 LoadSubCommand("enable", CommandObjectSP(
568 new CommandObjectLogTimerEnable(interpreter)));
569 LoadSubCommand("disable", CommandObjectSP(new CommandObjectLogTimerDisable(
570 interpreter)));
571 LoadSubCommand("dump",
572 CommandObjectSP(new CommandObjectLogTimerDump(interpreter)));
573 LoadSubCommand(
574 "reset", CommandObjectSP(new CommandObjectLogTimerReset(interpreter)));
575 LoadSubCommand(
576 "increment",
577 CommandObjectSP(new CommandObjectLogTimerIncrement(interpreter)));
580 ~CommandObjectLogTimer() override = default;
583 CommandObjectLog::CommandObjectLog(CommandInterpreter &interpreter)
584 : CommandObjectMultiword(interpreter, "log",
585 "Commands controlling LLDB internal logging.",
586 "log <subcommand> [<command-options>]") {
587 LoadSubCommand("enable",
588 CommandObjectSP(new CommandObjectLogEnable(interpreter)));
589 LoadSubCommand("disable",
590 CommandObjectSP(new CommandObjectLogDisable(interpreter)));
591 LoadSubCommand("list",
592 CommandObjectSP(new CommandObjectLogList(interpreter)));
593 LoadSubCommand("dump",
594 CommandObjectSP(new CommandObjectLogDump(interpreter)));
595 LoadSubCommand("timers",
596 CommandObjectSP(new CommandObjectLogTimer(interpreter)));
599 CommandObjectLog::~CommandObjectLog() = default;