Line data Source code
1 : //===- ArgList.cpp - Argument List Management -----------------------------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #include "llvm/ADT/ArrayRef.h"
11 : #include "llvm/ADT/None.h"
12 : #include "llvm/ADT/SmallVector.h"
13 : #include "llvm/ADT/STLExtras.h"
14 : #include "llvm/ADT/StringRef.h"
15 : #include "llvm/ADT/Twine.h"
16 : #include "llvm/Config/llvm-config.h"
17 : #include "llvm/Option/Arg.h"
18 : #include "llvm/Option/ArgList.h"
19 : #include "llvm/Option/Option.h"
20 : #include "llvm/Option/OptSpecifier.h"
21 : #include "llvm/Support/Compiler.h"
22 : #include "llvm/Support/Debug.h"
23 : #include "llvm/Support/raw_ostream.h"
24 : #include <algorithm>
25 : #include <cassert>
26 : #include <memory>
27 : #include <string>
28 : #include <utility>
29 : #include <vector>
30 :
31 : using namespace llvm;
32 : using namespace llvm::opt;
33 :
34 3456717 : void ArgList::append(Arg *A) {
35 3456717 : Args.push_back(A);
36 :
37 : // Update ranges for the option and all of its groups.
38 15906744 : for (Option O = A->getOption().getUnaliasedOption(); O.isValid();
39 : O = O.getGroup()) {
40 : auto &R =
41 17986620 : OptRanges.insert(std::make_pair(O.getID(), emptyRange())).first->second;
42 8993310 : R.first = std::min<unsigned>(R.first, Args.size() - 1);
43 8993310 : R.second = Args.size();
44 : }
45 3456717 : }
46 :
47 2115 : void ArgList::eraseArg(OptSpecifier Id) {
48 : // Zero out the removed entries but keep them around so that we don't
49 : // need to invalidate OptRanges.
50 4252 : for (Arg *const &A : filtered(Id)) {
51 : // Avoid the need for a non-const filtered iterator variant.
52 : Arg **ArgsBegin = Args.data();
53 22 : ArgsBegin[&A - ArgsBegin] = nullptr;
54 : }
55 2115 : OptRanges.erase(Id.getID());
56 2115 : }
57 :
58 : ArgList::OptRange
59 34165840 : ArgList::getRange(std::initializer_list<OptSpecifier> Ids) const {
60 34165840 : OptRange R = emptyRange();
61 78951545 : for (auto Id : Ids) {
62 44785775 : auto I = OptRanges.find(Id.getID());
63 44785705 : if (I != OptRanges.end()) {
64 1032643 : R.first = std::min(R.first, I->second.first);
65 2064943 : R.second = std::max(R.second, I->second.second);
66 : }
67 : }
68 : // Map an empty {-1, 0} range to {0, 0} so it can be used to form iterators.
69 34165770 : if (R.first == -1u)
70 33146111 : R.first = 0;
71 34165770 : return R;
72 : }
73 :
74 3942539 : bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const {
75 3942539 : if (Arg *A = getLastArg(Pos, Neg))
76 40731 : return A->getOption().matches(Pos);
77 : return Default;
78 : }
79 :
80 133311 : bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier PosAlias, OptSpecifier Neg,
81 : bool Default) const {
82 133311 : if (Arg *A = getLastArg(Pos, PosAlias, Neg))
83 2077 : return A->getOption().matches(Pos) || A->getOption().matches(PosAlias);
84 : return Default;
85 : }
86 :
87 1943097 : StringRef ArgList::getLastArgValue(OptSpecifier Id, StringRef Default) const {
88 1943097 : if (Arg *A = getLastArg(Id))
89 124240 : return A->getValue();
90 1818857 : return Default;
91 : }
92 :
93 1146532 : std::vector<std::string> ArgList::getAllArgValues(OptSpecifier Id) const {
94 : SmallVector<const char *, 16> Values;
95 1146532 : AddAllArgValues(Values, Id);
96 1146533 : return std::vector<std::string>(Values.begin(), Values.end());
97 : }
98 :
99 1174205 : void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const {
100 1174205 : if (Arg *A = getLastArg(Id)) {
101 : A->claim();
102 7941 : A->render(*this, Output);
103 : }
104 1174205 : }
105 :
106 177284 : void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id0,
107 : OptSpecifier Id1) const {
108 177284 : if (Arg *A = getLastArg(Id0, Id1)) {
109 : A->claim();
110 145 : A->render(*this, Output);
111 : }
112 177284 : }
113 :
114 21115 : void ArgList::AddAllArgsExcept(ArgStringList &Output,
115 : ArrayRef<OptSpecifier> Ids,
116 : ArrayRef<OptSpecifier> ExcludeIds) const {
117 646671 : for (const Arg *Arg : *this) {
118 : bool Excluded = false;
119 625610 : for (OptSpecifier Id : ExcludeIds) {
120 55 : if (Arg->getOption().matches(Id)) {
121 : Excluded = true;
122 : break;
123 : }
124 : }
125 625556 : if (!Excluded) {
126 1955355 : for (OptSpecifier Id : Ids) {
127 1698130 : if (Arg->getOption().matches(Id)) {
128 : Arg->claim();
129 368330 : Arg->render(*this, Output);
130 368330 : break;
131 : }
132 : }
133 : }
134 : }
135 21115 : }
136 :
137 : /// This is a nicer interface when you don't have a list of Ids to exclude.
138 21108 : void ArgList::AddAllArgs(ArgStringList &Output,
139 : ArrayRef<OptSpecifier> Ids) const {
140 : ArrayRef<OptSpecifier> Exclude = None;
141 21108 : AddAllArgsExcept(Output, Ids, Exclude);
142 21108 : }
143 :
144 : /// This 3-opt variant of AddAllArgs could be eliminated in favor of one
145 : /// that accepts a single specifier, given the above which accepts any number.
146 214947 : void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
147 : OptSpecifier Id1, OptSpecifier Id2) const {
148 553891 : for (auto Arg: filtered(Id0, Id1, Id2)) {
149 : Arg->claim();
150 123997 : Arg->render(*this, Output);
151 : }
152 214947 : }
153 :
154 1197066 : void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
155 : OptSpecifier Id1, OptSpecifier Id2) const {
156 2434688 : for (auto Arg : filtered(Id0, Id1, Id2)) {
157 : Arg->claim();
158 : const auto &Values = Arg->getValues();
159 81110 : Output.append(Values.begin(), Values.end());
160 : }
161 1197067 : }
162 :
163 6794 : void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
164 : const char *Translation,
165 : bool Joined) const {
166 13588 : for (auto Arg: filtered(Id0)) {
167 : Arg->claim();
168 :
169 0 : if (Joined) {
170 0 : Output.push_back(MakeArgString(StringRef(Translation) +
171 : Arg->getValue(0)));
172 : } else {
173 0 : Output.push_back(Translation);
174 0 : Output.push_back(Arg->getValue(0));
175 : }
176 : }
177 6794 : }
178 :
179 407316 : void ArgList::ClaimAllArgs(OptSpecifier Id0) const {
180 1179741 : for (auto *Arg : filtered(Id0))
181 : Arg->claim();
182 407316 : }
183 :
184 17 : void ArgList::ClaimAllArgs() const {
185 111 : for (auto *Arg : *this)
186 94 : if (!Arg->isClaimed())
187 : Arg->claim();
188 17 : }
189 :
190 185454 : const char *ArgList::GetOrMakeJoinedArgString(unsigned Index,
191 : StringRef LHS,
192 : StringRef RHS) const {
193 185454 : StringRef Cur = getArgString(Index);
194 185454 : if (Cur.size() == LHS.size() + RHS.size() &&
195 185454 : Cur.startswith(LHS) && Cur.endswith(RHS))
196 : return Cur.data();
197 :
198 476 : return MakeArgString(LHS + RHS);
199 : }
200 :
201 0 : void ArgList::print(raw_ostream &O) const {
202 0 : for (Arg *A : *this) {
203 0 : O << "* ";
204 0 : A->print(O);
205 : }
206 0 : }
207 :
208 : #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
209 : LLVM_DUMP_METHOD void ArgList::dump() const { print(dbgs()); }
210 : #endif
211 :
212 177066 : void InputArgList::releaseMemory() {
213 : // An InputArgList always owns its arguments.
214 2875819 : for (Arg *A : *this)
215 2698753 : delete A;
216 177066 : }
217 :
218 94160 : InputArgList::InputArgList(const char* const *ArgBegin,
219 94160 : const char* const *ArgEnd)
220 94160 : : NumInputArgStrings(ArgEnd - ArgBegin) {
221 94160 : ArgStrings.append(ArgBegin, ArgEnd);
222 94160 : }
223 :
224 829272 : unsigned InputArgList::MakeIndex(StringRef String0) const {
225 829272 : unsigned Index = ArgStrings.size();
226 :
227 : // Tuck away so we have a reliable const char *.
228 1658544 : SynthesizedStrings.push_back(String0);
229 1658544 : ArgStrings.push_back(SynthesizedStrings.back().c_str());
230 :
231 829272 : return Index;
232 : }
233 :
234 11 : unsigned InputArgList::MakeIndex(StringRef String0,
235 : StringRef String1) const {
236 11 : unsigned Index0 = MakeIndex(String0);
237 11 : unsigned Index1 = MakeIndex(String1);
238 : assert(Index0 + 1 == Index1 && "Unexpected non-consecutive indices!");
239 : (void) Index1;
240 11 : return Index0;
241 : }
242 :
243 826439 : const char *InputArgList::MakeArgStringRef(StringRef Str) const {
244 826439 : return getArgString(MakeIndex(Str));
245 : }
246 :
247 28503 : DerivedArgList::DerivedArgList(const InputArgList &BaseArgs)
248 57006 : : BaseArgs(BaseArgs) {}
249 :
250 801517 : const char *DerivedArgList::MakeArgStringRef(StringRef Str) const {
251 1603034 : return BaseArgs.MakeArgString(Str);
252 : }
253 :
254 512 : void DerivedArgList::AddSynthesizedArg(Arg *A) {
255 1024 : SynthesizedArgs.push_back(std::unique_ptr<Arg>(A));
256 512 : }
257 :
258 614 : Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option Opt) const {
259 614 : SynthesizedArgs.push_back(
260 3070 : make_unique<Arg>(Opt, MakeArgString(Opt.getPrefix() + Opt.getName()),
261 1228 : BaseArgs.MakeIndex(Opt.getName()), BaseArg));
262 614 : return SynthesizedArgs.back().get();
263 : }
264 :
265 0 : Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option Opt,
266 : StringRef Value) const {
267 0 : unsigned Index = BaseArgs.MakeIndex(Value);
268 0 : SynthesizedArgs.push_back(
269 0 : make_unique<Arg>(Opt, MakeArgString(Opt.getPrefix() + Opt.getName()),
270 0 : Index, BaseArgs.getArgString(Index), BaseArg));
271 0 : return SynthesizedArgs.back().get();
272 : }
273 :
274 11 : Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option Opt,
275 : StringRef Value) const {
276 22 : unsigned Index = BaseArgs.MakeIndex(Opt.getName(), Value);
277 11 : SynthesizedArgs.push_back(
278 55 : make_unique<Arg>(Opt, MakeArgString(Opt.getPrefix() + Opt.getName()),
279 11 : Index, BaseArgs.getArgString(Index + 1), BaseArg));
280 11 : return SynthesizedArgs.back().get();
281 : }
282 :
283 1496 : Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option Opt,
284 : StringRef Value) const {
285 2992 : unsigned Index = BaseArgs.MakeIndex((Opt.getName() + Value).str());
286 1496 : SynthesizedArgs.push_back(make_unique<Arg>(
287 4488 : Opt, MakeArgString(Opt.getPrefix() + Opt.getName()), Index,
288 2992 : BaseArgs.getArgString(Index) + Opt.getName().size(), BaseArg));
289 1496 : return SynthesizedArgs.back().get();
290 : }
|