Skip to content

Commit 5a0f74a

Browse files
committed
refactoring
1 parent 4521d03 commit 5a0f74a

File tree

3 files changed

+76
-24
lines changed

3 files changed

+76
-24
lines changed

parser-tests/parser-tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ namespace parsertests
121121
parser.parse(argc, argv);
122122

123123
Assert::IsTrue(parser.do_record.get());
124-
Assert::AreEqual(std::wstring(L"notepad.exe test_arg"), parser.record_commandline);
124+
Assert::AreEqual(std::wstring(L"notepad.exe test_arg"), parser.record_commandline.get());
125125
Assert::AreEqual(std::wstring(L"notepad.exe"), parser.sample_pe_file.get());
126126
Assert::AreEqual(std::wstring(L"notepad.pdb"), parser.sample_pdb_file.get());
127127
Assert::IsTrue(COMMAND_CLASS::RECORD == parser.command);

parser/arg-parser.cpp

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,27 +50,29 @@ void arg_parser::parse(
5050
arg_array.push_back(argv[i]);
5151

5252
}
53+
try_match_and_set_arg(raw_args, do_list);
54+
try_match_and_set_arg(raw_args, do_help);
55+
try_match_and_set_arg(raw_args, do_version);
56+
try_match_and_set_arg(raw_args, do_test);
57+
try_match_and_set_arg(raw_args, do_detect);
58+
try_match_and_set_arg(raw_args, do_sample);
59+
try_match_and_set_arg(raw_args, do_record);
60+
try_match_and_set_arg(raw_args, do_count);
5361

5462
while (raw_args.size() > 0)
5563
{
5664
size_t initial_size = raw_args.size();
5765
if (command == COMMAND_CLASS::NO_COMMAND) {
58-
try_match_and_set_arg(raw_args, do_list);
59-
try_match_and_set_arg(raw_args, do_help);
60-
try_match_and_set_arg(raw_args, do_version);
61-
try_match_and_set_arg(raw_args, do_test);
62-
try_match_and_set_arg(raw_args, do_detect);
63-
try_match_and_set_arg(raw_args, do_sample);
64-
try_match_and_set_arg(raw_args, do_record);
65-
try_match_and_set_arg(raw_args, do_count);
66+
throw_invalid_arg(raw_args.front(), L"Error: at least one command is needed ");
6667
}
67-
68+
6869
if (command == COMMAND_CLASS::SAMPLE || command == COMMAND_CLASS::RECORD)
6970
parse_sampling_args(raw_args);
71+
7072

7173
if (commands_with_no_args.find(command) != commands_with_no_args.end()) goto standard_arguments;
7274

73-
if (try_match_and_set_bool_flag(raw_args, record_commandline_separator)) {
75+
if (try_match_arg(raw_args, record_commandline)) {
7476
if (command != COMMAND_CLASS::RECORD && command != COMMAND_CLASS::STAT && command != COMMAND_CLASS::TIMELINE && command != COMMAND_CLASS::SPE)
7577
throw_invalid_arg(raw_args.front(), L"warning: only `stat` and `record` support process spawn!");
7678

@@ -203,17 +205,43 @@ void arg_parser::parse_sampling_args(wstr_vec& raw_args_vect)
203205
raw_args_vect.erase(raw_args_vect.begin());
204206
}
205207

208+
if (try_match_arg(raw_args_vect, events_string)) {
209+
check_flag_value_existance(raw_args_vect);
210+
211+
raw_args_vect.erase(raw_args_vect.begin());
212+
213+
}
214+
206215
if (initial_size == raw_args_vect.size()) break;
207216
}
208217
}
209218

219+
void arg_parser::parse_event_list(wstring i_events) {
220+
events_string.value = i_events;
221+
if (command == COMMAND_CLASS::SAMPLE || command == COMMAND_CLASS::RECORD) {
222+
if (i_events.rfind(ARM_SPE_EVENT_PREFIX)) command = COMMAND_CLASS::SPE;
223+
224+
if (i_events.rfind(L"{") != std::wstring::npos) {
225+
throw_invalid_arg(L"{", L"Error: Event groups are only available in the stat command");
226+
}
227+
}
228+
if (command == COMMAND_CLASS::STAT) {
229+
if (i_events.rfind(ARM_SPE_EVENT_PREFIX))
230+
throw_invalid_arg(ARM_SPE_EVENT_PREFIX, L"Error: SPE sampling is not available with the stat command");
231+
}
232+
if (commands_with_events_and_metrics.find(command) == commands_with_events_and_metrics.end()) {
233+
throw_invalid_arg(events_string.key, L"Error: Event list is only supported with the commands: stat, record, sample");
234+
}
235+
}
236+
210237
void arg_parser::parse_cpu_core(wstr_vec& raw_args_vect, uint8_t MAX_CPU_CORES)
211238
{
212239
wstring cores = raw_args_vect.front();
213240
if (TokenizeWideStringOfInts(cores.c_str(), L',', cores_idx.value) == false)
214241
{
215242
throw_invalid_arg(raw_args_vect.front());
216243
}
244+
// TODO: add CPU core ranges
217245
if (cores_idx.value.size() > MAX_CPU_CORES)
218246
{
219247
std::wostringstream error_message;
@@ -255,12 +283,12 @@ void arg_parser::parse_record_commandline(wstr_vec& raw_args_vect)
255283
if (sample_pe_file.value.empty())
256284
{
257285
sample_pe_file.value = arg;
258-
record_commandline = arg;
286+
record_commandline.value = arg;
259287
fill_pdb_and_image_name_if_empty();
260288

261289
}
262290
else
263-
record_commandline += L" " + arg;
291+
record_commandline.value += L" " + arg;
264292

265293
raw_args_vect.erase(raw_args_vect.begin());
266294
}

parser/arg-parser.h

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ using namespace std;
4343

4444
typedef std::vector<std::wstring> wstr_vec;
4545

46+
#define ARM_SPE_EVENT_PREFIX L"arm_spe_0"
47+
4648
#pragma region arg structs
4749
enum COMMAND_CLASS {
4850
STAT,
@@ -58,8 +60,15 @@ enum COMMAND_CLASS {
5860
TIMELINE,
5961
NO_COMMAND
6062
};
63+
static const std::set<COMMAND_CLASS> commands_with_events_and_metrics = {
64+
COMMAND_CLASS::STAT,
65+
COMMAND_CLASS::SAMPLE,
66+
COMMAND_CLASS::RECORD,
67+
COMMAND_CLASS::TIMELINE,
68+
COMMAND_CLASS::SPE
69+
};
6170

62-
const std::set<COMMAND_CLASS> commands_with_no_args = {
71+
static const std::set<COMMAND_CLASS> commands_with_no_args = {
6372
COMMAND_CLASS::HELP,
6473
COMMAND_CLASS::VERSION,
6574
COMMAND_CLASS::LIST,
@@ -154,11 +163,11 @@ class arg_parser
154163
COMMAND_CLASS::RECORD
155164
};
156165
arg_type do_count = {
157-
L"stat",
158-
L"",
159-
L"",
160-
false,
161-
COMMAND_CLASS::STAT
166+
L"stat",
167+
L"",
168+
L"",
169+
false,
170+
COMMAND_CLASS::STAT
162171
};
163172

164173
#pragma endregion
@@ -214,12 +223,12 @@ class arg_parser
214223
L"Enable disassemble output on sampling mode. Implies 'annotate'.",
215224
false,
216225
};
217-
flag_type<bool> record_commandline_separator = {
226+
flag_type<wstring> record_commandline = {
218227
L"--",
219228
L"",
220229
L"-- Process name is defined by COMMAND. User can pass verbatim arguments to the process with[ARGS].",
221-
false,
222-
};
230+
L"",
231+
}; // <sample_pe_file> <arg> <arg> <arg> ...
223232

224233
flag_type<std::vector<uint8_t>> cores_idx = {
225234
L"-c",
@@ -275,6 +284,21 @@ class arg_parser
275284
L"Specify the PDB filename (and path), PDB file should directly corresponds to a PE file set with `- - pe_file`.",
276285
L"",
277286
};
287+
flag_type<std::wstring> events_string = {
288+
L"-e",
289+
L"",
290+
LR"( Specify comma separated list of event names (or raw events) to count, for
291+
example `ld_spec,vfp_spec,r10`. Use curly braces to group events.
292+
Specify comma separated list of event names with sampling frequency to
293+
sample, for example `ld_spec:100000`.
294+
295+
Raw events: specify raw evens with `r<VALUE>` where `<VALUE>` is a 16-bit
296+
hexadecimal event index value without leading `0x`. For example `r10` is
297+
event with index `0x10`.
298+
299+
Note: see list of available event names using `list` command.)",
300+
L"",
301+
};
278302
#pragma endregion
279303

280304
#pragma region Attributes
@@ -288,15 +312,14 @@ class arg_parser
288312
bool do_timeline;
289313
bool do_man;
290314
bool do_export_perf_data;
291-
bool do_cwd = false; // Set current working dir for storing output files
315+
bool do_cwd = false; // Set current working dir for storing output files
292316
bool report_l3_cache_metric;
293317
bool report_ddr_bw_metric;
294318
uint8_t dmc_idx;
295319
double count_interval;
296320
int count_timeline;
297321
std::wstring man_query_args;
298322

299-
std::wstring record_commandline; // <sample_pe_file> <arg> <arg> <arg> ...
300323
std::wstring timeline_output_file;
301324
std::wstring m_cwd; // Current working dir for storing output files
302325
std::map<uint32_t, uint32_t> sampling_inverval; //!< [event_index] -> event_sampling_interval
@@ -317,6 +340,7 @@ class arg_parser
317340
void fill_pdb_and_image_name_if_empty();
318341
void check_record_required_args();
319342
void parse_sampling_args(wstr_vec& raw_args_vect);
343+
void parse_event_list(wstring events_string);
320344
void parse_cpu_core(wstr_vec& raw_args_vect, uint8_t MAX_CPU_CORES);
321345
bool try_match_and_set_bool_flag(wstr_vec& raw_args_vect, flag_type<bool>& flag);
322346
bool try_match_and_set_arg(wstr_vec& raw_args_vect, arg_type& flag);

0 commit comments

Comments
 (0)