Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: src/IceRangeSpec.cpp

Issue 1900543002: Subzero: Allow per-method controls. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: More cleanup Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 //===- subzero/src/IceRangeSpec.cpp - Include/exclude specification -------===//
2 //
3 // The Subzero Code Generator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief Implements a class for specifying sets of names and number ranges to
12 /// match against. This is specified as a comma-separated list of clauses.
13 /// Each clause optionally starts with '-' to indicate exclusion instead of
14 /// inclusion. A clause can be a name, or a numeric range X:Y, or a single
15 /// number X. The X:Y form indicates a range of numbers greater than or equal
16 /// to X and strictly less than Y. A missing "X" is taken to be 0, and a
17 /// missing "Y" is taken to be infinite. E.g., "0:" and ":" specify the entire
18 /// set.
19 ///
20 /// This is essentially the same implementation as in szbuild.py, except that
21 /// regular expressions are not used for the names.
22 ///
23 //===----------------------------------------------------------------------===//
24
25 #include "IceRangeSpec.h"
26 #include "IceStringPool.h"
27
28 #include <cctype>
29 #include <string>
30 #include <unordered_set>
31 #include <vector>
32
33 namespace Ice {
34
35 bool RangeSpec::HasNames = false;
36
37 namespace {
38
39 /// Helper function to tokenize a string into a vector of string tokens, given a
40 /// single delimiter character. An empty string produces an empty token vector.
41 /// Zero-length tokens are allowed, e.g. ",a,,,b," may tokenize to
42 /// {"","a","","","b",""}.
43 std::vector<std::string> tokenize(const std::string &Spec, char Delimiter) {
44 std::vector<std::string> Tokens;
45 if (!Spec.empty()) {
46 std::string::size_type StartPos = 0;
47 std::string::size_type DelimPos = 0;
48 while (DelimPos != std::string::npos) {
49 DelimPos = Spec.find(Delimiter, StartPos);
50 Tokens.emplace_back(Spec.substr(StartPos, DelimPos - StartPos));
51 StartPos = DelimPos + 1;
52 }
53 }
54 return Tokens;
55 }
56
57 /// Helper function to parse "X" or "X:Y" into First and Last.
58 /// - "X" is treated as "X:X+1".
59 /// - ":Y" is treated as "0:Y".
60 /// - "X:" is treated as "X:inf"
61 ///
62 /// Behavior is undefined if "X" or "Y" is not a proper number (since std::stoul
63 /// throws an exception).
64 ///
65 /// If the string doesn't contain 1 or 2 ':' delimiters, or X>=Y,
66 /// report_fatal_error is called.
67 void getRange(const std::string &Token, uint32_t *First, uint32_t *Last) {
68 bool Error = false;
69 auto Tokens = tokenize(Token, RangeSpec::DELIM_RANGE);
70 if (Tokens.size() == 1) {
71 *First = std::stoul(Tokens[0]);
72 *Last = *First + 1;
73 } else if (Tokens.size() == 2) {
74 *First = Tokens[0].empty() ? 0 : std::stoul(Tokens[0]);
75 *Last = Tokens[1].empty() ? RangeSpec::RangeMax : std::stoul(Tokens[1]);
76 } else {
77 Error = true;
78 }
79 if (*First >= *Last) {
80 Error = true;
81 }
82 if (Error) {
83 llvm::report_fatal_error("Invalid range " + Token);
84 }
85 }
86
87 /// Helper function to add one token to the include or exclude set. The token
88 /// is examined and then treated as either a numeric range or a single name.
89 void record(const std::string &Token, RangeSpec::Desc *D) {
90 if (Token.empty())
91 return;
92 // Mark that an include or exclude was explicitly given. This affects the
93 // default decision when matching a value that wasn't explicitly provided in
94 // the include or exclude list.
95 D->IsExplicit = true;
96 // A range is identified by starting with a digit or a ':'.
97 if (Token[0] == RangeSpec::DELIM_RANGE || std::isdigit(Token[0])) {
98 uint32_t First, Last;
99 getRange(Token, &First, &Last);
100 if (Last == RangeSpec::RangeMax) {
101 D->AllFrom = std::min(D->AllFrom, First);
102 } else {
103 if (Last >= D->Numbers.size())
104 D->Numbers.resize(Last + 1);
105 D->Numbers.set(First, Last);
106 }
107 } else {
108 // Otherwise treat it as a single name.
109 D->Names.insert(Token);
110 }
111 }
112
113 } // end of anonymous namespace
114
115 /// Initialize the RangeSpec with the given string. Calling init multiple times
116 /// (e.g. init("A");init("B");) is equivalent to init("A,B"); .
117 void RangeSpec::init(const std::string &Spec) {
118 auto Tokens = tokenize(Spec, DELIM_LIST);
119 for (const auto &Token : Tokens) {
120 if (Token[0] == '-') {
121 exclude(Token.substr(1));
122 } else {
123 include(Token);
124 }
125 }
126 if (!Includes.Names.empty() || !Excludes.Names.empty())
127 HasNames = true;
128 }
129
130 /// Determine whether the given Name/Number combo match the specification given
131 /// to the init() method. Explicit excludes take precedence over explicit
132 /// includes. If the combo doesn't match any explicit include or exclude:
133 /// - false if the init() string is empty (no explicit includes or excludes)
134 /// - true if there is at least one explicit exclude and no explicit includes
135 /// - false otherwise (at least one explicit include)
136 bool RangeSpec::match(const std::string &Name, uint32_t Number) const {
137 // No match if it is explicitly excluded by name or number.
138 if (Excludes.Names.find(Name) != Excludes.Names.end())
139 return false;
140 if (Number >= Excludes.AllFrom)
141 return false;
142 if (Number < Excludes.Numbers.size() && Excludes.Numbers[Number])
143 return false;
144
145 // Positive match if it is explicitly included by name or number.
146 if (Includes.Names.find(Name) != Includes.Names.end())
147 return true;
148 if (Number >= Includes.AllFrom)
149 return true;
150 if (Number < Includes.Numbers.size() && Includes.Numbers[Number])
151 return true;
152
153 // Otherwise use the default decision.
154 return Excludes.IsExplicit && !Includes.IsExplicit;
155 }
156
157 void RangeSpec::include(const std::string &Token) { record(Token, &Includes); }
158
159 void RangeSpec::exclude(const std::string &Token) { record(Token, &Excludes); }
160
161 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698