~louis/ubuntu/trusty/clamav/lp799623_fix_logrotate

« back to all changes in this revision

Viewing changes to libclamav/c++/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2010-03-12 11:30:04 UTC
  • mfrom: (0.41.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100312113004-b0fop4bkycszdd0z
Tags: 0.96~rc1+dfsg-0ubuntu1
* New upstream RC - FFE (LP: #537636):
  - Add OfficialDatabaseOnly option to clamav-base.postinst.in
  - Add LocalSocketGroup option to clamav-base.postinst.in
  - Add LocalSocketMode option to clamav-base.postinst.in
  - Add CrossFilesystems option to clamav-base.postinst.in
  - Add ClamukoScannerCount option to clamav-base.postinst.in
  - Add BytecodeSecurity opiton to clamav-base.postinst.in
  - Add DetectionStatsHostID option to clamav-freshclam.postinst.in
  - Add Bytecode option to clamav-freshclam.postinst.in
  - Add MilterSocketGroup option to clamav-milter.postinst.in
  - Add MilterSocketMode option to clamav-milter.postinst.in
  - Add ReportHostname option to clamav-milter.postinst.in
  - Bump libclamav SO version to 6.1.0 in libclamav6.install
  - Drop clamdmon from clamav.examples (no longer shipped by upstream)
  - Drop libclamav.a from libclamav-dev.install (not built by upstream)
  - Update SO version for lintian override for libclamav6
  - Add new Bytecode Testing Tool, usr/bin/clambc, to clamav.install
  - Add build-depends on python and python-setuptools for new test suite
  - Update debian/copyright for the embedded copy of llvm (using the system
    llvm is not currently feasible)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//===- LLVMCConfigurationEmitter.cpp - Generate LLVMC config ----*- C++ -*-===//
 
2
//
 
3
//                     The LLVM Compiler Infrastructure
 
4
//
 
5
// This file is distributed under the University of Illinois Open
 
6
// Source License. See LICENSE.TXT for details.
 
7
//
 
8
//===----------------------------------------------------------------------===//
 
9
//
 
10
// This tablegen backend is responsible for emitting LLVMC configuration code.
 
11
//
 
12
//===----------------------------------------------------------------------===//
 
13
 
 
14
#include "LLVMCConfigurationEmitter.h"
 
15
#include "Record.h"
 
16
 
 
17
#include "llvm/ADT/IntrusiveRefCntPtr.h"
 
18
#include "llvm/ADT/StringMap.h"
 
19
#include "llvm/ADT/StringSet.h"
 
20
 
 
21
#include <algorithm>
 
22
#include <cassert>
 
23
#include <functional>
 
24
#include <stdexcept>
 
25
#include <string>
 
26
#include <typeinfo>
 
27
 
 
28
using namespace llvm;
 
29
 
 
30
namespace {
 
31
 
 
32
//===----------------------------------------------------------------------===//
 
33
/// Typedefs
 
34
 
 
35
typedef std::vector<Record*> RecordVector;
 
36
typedef std::vector<std::string> StrVector;
 
37
 
 
38
//===----------------------------------------------------------------------===//
 
39
/// Constants
 
40
 
 
41
// Indentation.
 
42
const unsigned TabWidth = 4;
 
43
const unsigned Indent1  = TabWidth*1;
 
44
const unsigned Indent2  = TabWidth*2;
 
45
const unsigned Indent3  = TabWidth*3;
 
46
const unsigned Indent4  = TabWidth*4;
 
47
 
 
48
// Default help string.
 
49
const char * const DefaultHelpString = "NO HELP MESSAGE PROVIDED";
 
50
 
 
51
// Name for the "sink" option.
 
52
const char * const SinkOptionName = "AutoGeneratedSinkOption";
 
53
 
 
54
//===----------------------------------------------------------------------===//
 
55
/// Helper functions
 
56
 
 
57
/// Id - An 'identity' function object.
 
58
struct Id {
 
59
  template<typename T0>
 
60
  void operator()(const T0&) const {
 
61
  }
 
62
  template<typename T0, typename T1>
 
63
  void operator()(const T0&, const T1&) const {
 
64
  }
 
65
  template<typename T0, typename T1, typename T2>
 
66
  void operator()(const T0&, const T1&, const T2&) const {
 
67
  }
 
68
};
 
69
 
 
70
int InitPtrToInt(const Init* ptr) {
 
71
  const IntInit& val = dynamic_cast<const IntInit&>(*ptr);
 
72
  return val.getValue();
 
73
}
 
74
 
 
75
const std::string& InitPtrToString(const Init* ptr) {
 
76
  const StringInit& val = dynamic_cast<const StringInit&>(*ptr);
 
77
  return val.getValue();
 
78
}
 
79
 
 
80
const ListInit& InitPtrToList(const Init* ptr) {
 
81
  const ListInit& val = dynamic_cast<const ListInit&>(*ptr);
 
82
  return val;
 
83
}
 
84
 
 
85
const DagInit& InitPtrToDag(const Init* ptr) {
 
86
  const DagInit& val = dynamic_cast<const DagInit&>(*ptr);
 
87
  return val;
 
88
}
 
89
 
 
90
const std::string GetOperatorName(const DagInit& D) {
 
91
  return D.getOperator()->getAsString();
 
92
}
 
93
 
 
94
/// CheckBooleanConstant - Check that the provided value is a boolean constant.
 
95
void CheckBooleanConstant(const Init* I) {
 
96
  const DefInit& val = dynamic_cast<const DefInit&>(*I);
 
97
  const std::string& str = val.getAsString();
 
98
 
 
99
  if (str != "true" && str != "false") {
 
100
    throw "Incorrect boolean value: '" + str +
 
101
      "': must be either 'true' or 'false'";
 
102
  }
 
103
}
 
104
 
 
105
// CheckNumberOfArguments - Ensure that the number of args in d is
 
106
// greater than or equal to min_arguments, otherwise throw an exception.
 
107
void CheckNumberOfArguments (const DagInit& d, unsigned minArgs) {
 
108
  if (d.getNumArgs() < minArgs)
 
109
    throw GetOperatorName(d) + ": too few arguments!";
 
110
}
 
111
 
 
112
// IsDagEmpty - is this DAG marked with an empty marker?
 
113
bool IsDagEmpty (const DagInit& d) {
 
114
  return GetOperatorName(d) == "empty_dag_marker";
 
115
}
 
116
 
 
117
// EscapeVariableName - Escape commas and other symbols not allowed
 
118
// in the C++ variable names. Makes it possible to use options named
 
119
// like "Wa," (useful for prefix options).
 
120
std::string EscapeVariableName (const std::string& Var) {
 
121
  std::string ret;
 
122
  for (unsigned i = 0; i != Var.size(); ++i) {
 
123
    char cur_char = Var[i];
 
124
    if (cur_char == ',') {
 
125
      ret += "_comma_";
 
126
    }
 
127
    else if (cur_char == '+') {
 
128
      ret += "_plus_";
 
129
    }
 
130
    else if (cur_char == '-') {
 
131
      ret += "_dash_";
 
132
    }
 
133
    else {
 
134
      ret.push_back(cur_char);
 
135
    }
 
136
  }
 
137
  return ret;
 
138
}
 
139
 
 
140
/// EscapeQuotes - Replace '"' with '\"'.
 
141
std::string EscapeQuotes (const std::string& Var) {
 
142
  std::string ret;
 
143
  for (unsigned i = 0; i != Var.size(); ++i) {
 
144
    char cur_char = Var[i];
 
145
    if (cur_char == '"') {
 
146
      ret += "\\\"";
 
147
    }
 
148
    else {
 
149
      ret.push_back(cur_char);
 
150
    }
 
151
  }
 
152
  return ret;
 
153
}
 
154
 
 
155
/// OneOf - Does the input string contain this character?
 
156
bool OneOf(const char* lst, char c) {
 
157
  while (*lst) {
 
158
    if (*lst++ == c)
 
159
      return true;
 
160
  }
 
161
  return false;
 
162
}
 
163
 
 
164
template <class I, class S>
 
165
void CheckedIncrement(I& P, I E, S ErrorString) {
 
166
  ++P;
 
167
  if (P == E)
 
168
    throw ErrorString;
 
169
}
 
170
 
 
171
// apply is needed because C++'s syntax doesn't let us construct a function
 
172
// object and call it in the same statement.
 
173
template<typename F, typename T0>
 
174
void apply(F Fun, T0& Arg0) {
 
175
  return Fun(Arg0);
 
176
}
 
177
 
 
178
template<typename F, typename T0, typename T1>
 
179
void apply(F Fun, T0& Arg0, T1& Arg1) {
 
180
  return Fun(Arg0, Arg1);
 
181
}
 
182
 
 
183
//===----------------------------------------------------------------------===//
 
184
/// Back-end specific code
 
185
 
 
186
 
 
187
/// OptionType - One of six different option types. See the
 
188
/// documentation for detailed description of differences.
 
189
namespace OptionType {
 
190
 
 
191
  enum OptionType { Alias, Switch, Parameter, ParameterList,
 
192
                    Prefix, PrefixList};
 
193
 
 
194
  bool IsAlias(OptionType t) {
 
195
    return (t == Alias);
 
196
  }
 
197
 
 
198
  bool IsList (OptionType t) {
 
199
    return (t == ParameterList || t == PrefixList);
 
200
  }
 
201
 
 
202
  bool IsSwitch (OptionType t) {
 
203
    return (t == Switch);
 
204
  }
 
205
 
 
206
  bool IsParameter (OptionType t) {
 
207
    return (t == Parameter || t == Prefix);
 
208
  }
 
209
 
 
210
}
 
211
 
 
212
OptionType::OptionType stringToOptionType(const std::string& T) {
 
213
  if (T == "alias_option")
 
214
    return OptionType::Alias;
 
215
  else if (T == "switch_option")
 
216
    return OptionType::Switch;
 
217
  else if (T == "parameter_option")
 
218
    return OptionType::Parameter;
 
219
  else if (T == "parameter_list_option")
 
220
    return OptionType::ParameterList;
 
221
  else if (T == "prefix_option")
 
222
    return OptionType::Prefix;
 
223
  else if (T == "prefix_list_option")
 
224
    return OptionType::PrefixList;
 
225
  else
 
226
    throw "Unknown option type: " + T + '!';
 
227
}
 
228
 
 
229
namespace OptionDescriptionFlags {
 
230
  enum OptionDescriptionFlags { Required = 0x1, Hidden = 0x2,
 
231
                                ReallyHidden = 0x4, Extern = 0x8,
 
232
                                OneOrMore = 0x10, Optional = 0x20,
 
233
                                CommaSeparated = 0x40, ForwardNotSplit = 0x80,
 
234
                                ZeroOrMore = 0x100 };
 
235
}
 
236
 
 
237
/// OptionDescription - Represents data contained in a single
 
238
/// OptionList entry.
 
239
struct OptionDescription {
 
240
  OptionType::OptionType Type;
 
241
  std::string Name;
 
242
  unsigned Flags;
 
243
  std::string Help;
 
244
  unsigned MultiVal;
 
245
  Init* InitVal;
 
246
 
 
247
  OptionDescription(OptionType::OptionType t = OptionType::Switch,
 
248
                    const std::string& n = "",
 
249
                    const std::string& h = DefaultHelpString)
 
250
    : Type(t), Name(n), Flags(0x0), Help(h), MultiVal(1), InitVal(0)
 
251
  {}
 
252
 
 
253
  /// GenTypeDeclaration - Returns the C++ variable type of this
 
254
  /// option.
 
255
  const char* GenTypeDeclaration() const;
 
256
 
 
257
  /// GenVariableName - Returns the variable name used in the
 
258
  /// generated C++ code.
 
259
  std::string GenVariableName() const;
 
260
 
 
261
  /// Merge - Merge two option descriptions.
 
262
  void Merge (const OptionDescription& other);
 
263
 
 
264
  /// CheckConsistency - Check that the flags are consistent.
 
265
  void CheckConsistency() const;
 
266
 
 
267
  // Misc convenient getters/setters.
 
268
 
 
269
  bool isAlias() const;
 
270
 
 
271
  bool isMultiVal() const;
 
272
 
 
273
  bool isCommaSeparated() const;
 
274
  void setCommaSeparated();
 
275
 
 
276
  bool isExtern() const;
 
277
  void setExtern();
 
278
 
 
279
  bool isForwardNotSplit() const;
 
280
  void setForwardNotSplit();
 
281
 
 
282
  bool isRequired() const;
 
283
  void setRequired();
 
284
 
 
285
  bool isOneOrMore() const;
 
286
  void setOneOrMore();
 
287
 
 
288
  bool isZeroOrMore() const;
 
289
  void setZeroOrMore();
 
290
 
 
291
  bool isOptional() const;
 
292
  void setOptional();
 
293
 
 
294
  bool isHidden() const;
 
295
  void setHidden();
 
296
 
 
297
  bool isReallyHidden() const;
 
298
  void setReallyHidden();
 
299
 
 
300
  bool isSwitch() const
 
301
  { return OptionType::IsSwitch(this->Type); }
 
302
 
 
303
  bool isParameter() const
 
304
  { return OptionType::IsParameter(this->Type); }
 
305
 
 
306
  bool isList() const
 
307
  { return OptionType::IsList(this->Type); }
 
308
 
 
309
};
 
310
 
 
311
void OptionDescription::CheckConsistency() const {
 
312
  unsigned i = 0;
 
313
 
 
314
  i += this->isRequired();
 
315
  i += this->isOptional();
 
316
  i += this->isOneOrMore();
 
317
  i += this->isZeroOrMore();
 
318
 
 
319
  if (i > 1) {
 
320
    throw "Only one of (required), (optional), (one_or_more) or "
 
321
      "(zero_or_more) properties is allowed!";
 
322
  }
 
323
}
 
324
 
 
325
void OptionDescription::Merge (const OptionDescription& other)
 
326
{
 
327
  if (other.Type != Type)
 
328
    throw "Conflicting definitions for the option " + Name + "!";
 
329
 
 
330
  if (Help == other.Help || Help == DefaultHelpString)
 
331
    Help = other.Help;
 
332
  else if (other.Help != DefaultHelpString) {
 
333
    llvm::errs() << "Warning: several different help strings"
 
334
      " defined for option " + Name + "\n";
 
335
  }
 
336
 
 
337
  Flags |= other.Flags;
 
338
}
 
339
 
 
340
bool OptionDescription::isAlias() const {
 
341
  return OptionType::IsAlias(this->Type);
 
342
}
 
343
 
 
344
bool OptionDescription::isMultiVal() const {
 
345
  return MultiVal > 1;
 
346
}
 
347
 
 
348
bool OptionDescription::isCommaSeparated() const {
 
349
  return Flags & OptionDescriptionFlags::CommaSeparated;
 
350
}
 
351
void OptionDescription::setCommaSeparated() {
 
352
  Flags |= OptionDescriptionFlags::CommaSeparated;
 
353
}
 
354
 
 
355
bool OptionDescription::isForwardNotSplit() const {
 
356
  return Flags & OptionDescriptionFlags::ForwardNotSplit;
 
357
}
 
358
void OptionDescription::setForwardNotSplit() {
 
359
  Flags |= OptionDescriptionFlags::ForwardNotSplit;
 
360
}
 
361
 
 
362
bool OptionDescription::isExtern() const {
 
363
  return Flags & OptionDescriptionFlags::Extern;
 
364
}
 
365
void OptionDescription::setExtern() {
 
366
  Flags |= OptionDescriptionFlags::Extern;
 
367
}
 
368
 
 
369
bool OptionDescription::isRequired() const {
 
370
  return Flags & OptionDescriptionFlags::Required;
 
371
}
 
372
void OptionDescription::setRequired() {
 
373
  Flags |= OptionDescriptionFlags::Required;
 
374
}
 
375
 
 
376
bool OptionDescription::isOneOrMore() const {
 
377
  return Flags & OptionDescriptionFlags::OneOrMore;
 
378
}
 
379
void OptionDescription::setOneOrMore() {
 
380
  Flags |= OptionDescriptionFlags::OneOrMore;
 
381
}
 
382
 
 
383
bool OptionDescription::isZeroOrMore() const {
 
384
  return Flags & OptionDescriptionFlags::ZeroOrMore;
 
385
}
 
386
void OptionDescription::setZeroOrMore() {
 
387
  Flags |= OptionDescriptionFlags::ZeroOrMore;
 
388
}
 
389
 
 
390
bool OptionDescription::isOptional() const {
 
391
  return Flags & OptionDescriptionFlags::Optional;
 
392
}
 
393
void OptionDescription::setOptional() {
 
394
  Flags |= OptionDescriptionFlags::Optional;
 
395
}
 
396
 
 
397
bool OptionDescription::isHidden() const {
 
398
  return Flags & OptionDescriptionFlags::Hidden;
 
399
}
 
400
void OptionDescription::setHidden() {
 
401
  Flags |= OptionDescriptionFlags::Hidden;
 
402
}
 
403
 
 
404
bool OptionDescription::isReallyHidden() const {
 
405
  return Flags & OptionDescriptionFlags::ReallyHidden;
 
406
}
 
407
void OptionDescription::setReallyHidden() {
 
408
  Flags |= OptionDescriptionFlags::ReallyHidden;
 
409
}
 
410
 
 
411
const char* OptionDescription::GenTypeDeclaration() const {
 
412
  switch (Type) {
 
413
  case OptionType::Alias:
 
414
    return "cl::alias";
 
415
  case OptionType::PrefixList:
 
416
  case OptionType::ParameterList:
 
417
    return "cl::list<std::string>";
 
418
  case OptionType::Switch:
 
419
    return "cl::opt<bool>";
 
420
  case OptionType::Parameter:
 
421
  case OptionType::Prefix:
 
422
  default:
 
423
    return "cl::opt<std::string>";
 
424
  }
 
425
}
 
426
 
 
427
std::string OptionDescription::GenVariableName() const {
 
428
  const std::string& EscapedName = EscapeVariableName(Name);
 
429
  switch (Type) {
 
430
  case OptionType::Alias:
 
431
    return "AutoGeneratedAlias_" + EscapedName;
 
432
  case OptionType::PrefixList:
 
433
  case OptionType::ParameterList:
 
434
    return "AutoGeneratedList_" + EscapedName;
 
435
  case OptionType::Switch:
 
436
    return "AutoGeneratedSwitch_" + EscapedName;
 
437
  case OptionType::Prefix:
 
438
  case OptionType::Parameter:
 
439
  default:
 
440
    return "AutoGeneratedParameter_" + EscapedName;
 
441
  }
 
442
}
 
443
 
 
444
/// OptionDescriptions - An OptionDescription array plus some helper
 
445
/// functions.
 
446
class OptionDescriptions {
 
447
  typedef StringMap<OptionDescription> container_type;
 
448
 
 
449
  /// Descriptions - A list of OptionDescriptions.
 
450
  container_type Descriptions;
 
451
 
 
452
public:
 
453
  /// FindOption - exception-throwing wrapper for find().
 
454
  const OptionDescription& FindOption(const std::string& OptName) const;
 
455
 
 
456
  // Wrappers for FindOption that throw an exception in case the option has a
 
457
  // wrong type.
 
458
  const OptionDescription& FindSwitch(const std::string& OptName) const;
 
459
  const OptionDescription& FindParameter(const std::string& OptName) const;
 
460
  const OptionDescription& FindList(const std::string& OptName) const;
 
461
  const OptionDescription&
 
462
  FindListOrParameter(const std::string& OptName) const;
 
463
 
 
464
  /// insertDescription - Insert new OptionDescription into
 
465
  /// OptionDescriptions list
 
466
  void InsertDescription (const OptionDescription& o);
 
467
 
 
468
  // Support for STL-style iteration
 
469
  typedef container_type::const_iterator const_iterator;
 
470
  const_iterator begin() const { return Descriptions.begin(); }
 
471
  const_iterator end() const { return Descriptions.end(); }
 
472
};
 
473
 
 
474
const OptionDescription&
 
475
OptionDescriptions::FindOption(const std::string& OptName) const {
 
476
  const_iterator I = Descriptions.find(OptName);
 
477
  if (I != Descriptions.end())
 
478
    return I->second;
 
479
  else
 
480
    throw OptName + ": no such option!";
 
481
}
 
482
 
 
483
const OptionDescription&
 
484
OptionDescriptions::FindSwitch(const std::string& OptName) const {
 
485
  const OptionDescription& OptDesc = this->FindOption(OptName);
 
486
  if (!OptDesc.isSwitch())
 
487
    throw OptName + ": incorrect option type - should be a switch!";
 
488
  return OptDesc;
 
489
}
 
490
 
 
491
const OptionDescription&
 
492
OptionDescriptions::FindList(const std::string& OptName) const {
 
493
  const OptionDescription& OptDesc = this->FindOption(OptName);
 
494
  if (!OptDesc.isList())
 
495
    throw OptName + ": incorrect option type - should be a list!";
 
496
  return OptDesc;
 
497
}
 
498
 
 
499
const OptionDescription&
 
500
OptionDescriptions::FindParameter(const std::string& OptName) const {
 
501
  const OptionDescription& OptDesc = this->FindOption(OptName);
 
502
  if (!OptDesc.isParameter())
 
503
    throw OptName + ": incorrect option type - should be a parameter!";
 
504
  return OptDesc;
 
505
}
 
506
 
 
507
const OptionDescription&
 
508
OptionDescriptions::FindListOrParameter(const std::string& OptName) const {
 
509
  const OptionDescription& OptDesc = this->FindOption(OptName);
 
510
  if (!OptDesc.isList() && !OptDesc.isParameter())
 
511
    throw OptName
 
512
      + ": incorrect option type - should be a list or parameter!";
 
513
  return OptDesc;
 
514
}
 
515
 
 
516
void OptionDescriptions::InsertDescription (const OptionDescription& o) {
 
517
  container_type::iterator I = Descriptions.find(o.Name);
 
518
  if (I != Descriptions.end()) {
 
519
    OptionDescription& D = I->second;
 
520
    D.Merge(o);
 
521
  }
 
522
  else {
 
523
    Descriptions[o.Name] = o;
 
524
  }
 
525
}
 
526
 
 
527
/// HandlerTable - A base class for function objects implemented as
 
528
/// 'tables of handlers'.
 
529
template <typename Handler>
 
530
class HandlerTable {
 
531
protected:
 
532
  // Implementation details.
 
533
 
 
534
  /// HandlerMap - A map from property names to property handlers
 
535
  typedef StringMap<Handler> HandlerMap;
 
536
 
 
537
  static HandlerMap Handlers_;
 
538
  static bool staticMembersInitialized_;
 
539
 
 
540
public:
 
541
 
 
542
  Handler GetHandler (const std::string& HandlerName) const {
 
543
    typename HandlerMap::iterator method = Handlers_.find(HandlerName);
 
544
 
 
545
    if (method != Handlers_.end()) {
 
546
      Handler h = method->second;
 
547
      return h;
 
548
    }
 
549
    else {
 
550
      throw "No handler found for property " + HandlerName + "!";
 
551
    }
 
552
  }
 
553
 
 
554
  void AddHandler(const char* Property, Handler H) {
 
555
    Handlers_[Property] = H;
 
556
  }
 
557
 
 
558
};
 
559
 
 
560
template <class Handler, class FunctionObject>
 
561
Handler GetHandler(FunctionObject* Obj, const DagInit& Dag) {
 
562
  const std::string& HandlerName = GetOperatorName(Dag);
 
563
  return Obj->GetHandler(HandlerName);
 
564
}
 
565
 
 
566
template <class FunctionObject>
 
567
void InvokeDagInitHandler(FunctionObject* Obj, Init* I) {
 
568
  typedef void (FunctionObject::*Handler) (const DagInit&);
 
569
 
 
570
  const DagInit& Dag = InitPtrToDag(I);
 
571
  Handler h = GetHandler<Handler>(Obj, Dag);
 
572
 
 
573
  ((Obj)->*(h))(Dag);
 
574
}
 
575
 
 
576
template <class FunctionObject>
 
577
void InvokeDagInitHandler(const FunctionObject* const Obj,
 
578
                          const Init* I, unsigned IndentLevel, raw_ostream& O)
 
579
{
 
580
  typedef void (FunctionObject::*Handler)
 
581
    (const DagInit&, unsigned IndentLevel, raw_ostream& O) const;
 
582
 
 
583
  const DagInit& Dag = InitPtrToDag(I);
 
584
  Handler h = GetHandler<Handler>(Obj, Dag);
 
585
 
 
586
  ((Obj)->*(h))(Dag, IndentLevel, O);
 
587
}
 
588
 
 
589
 
 
590
template <typename H>
 
591
typename HandlerTable<H>::HandlerMap HandlerTable<H>::Handlers_;
 
592
 
 
593
template <typename H>
 
594
bool HandlerTable<H>::staticMembersInitialized_ = false;
 
595
 
 
596
 
 
597
/// CollectOptionProperties - Function object for iterating over an
 
598
/// option property list.
 
599
class CollectOptionProperties;
 
600
typedef void (CollectOptionProperties::* CollectOptionPropertiesHandler)
 
601
(const DagInit&);
 
602
 
 
603
class CollectOptionProperties
 
604
: public HandlerTable<CollectOptionPropertiesHandler>
 
605
{
 
606
private:
 
607
 
 
608
  /// optDescs_ - OptionDescriptions table. This is where the
 
609
  /// information is stored.
 
610
  OptionDescription& optDesc_;
 
611
 
 
612
public:
 
613
 
 
614
  explicit CollectOptionProperties(OptionDescription& OD)
 
615
    : optDesc_(OD)
 
616
  {
 
617
    if (!staticMembersInitialized_) {
 
618
      AddHandler("extern", &CollectOptionProperties::onExtern);
 
619
      AddHandler("help", &CollectOptionProperties::onHelp);
 
620
      AddHandler("hidden", &CollectOptionProperties::onHidden);
 
621
      AddHandler("init", &CollectOptionProperties::onInit);
 
622
      AddHandler("multi_val", &CollectOptionProperties::onMultiVal);
 
623
      AddHandler("one_or_more", &CollectOptionProperties::onOneOrMore);
 
624
      AddHandler("zero_or_more", &CollectOptionProperties::onZeroOrMore);
 
625
      AddHandler("really_hidden", &CollectOptionProperties::onReallyHidden);
 
626
      AddHandler("required", &CollectOptionProperties::onRequired);
 
627
      AddHandler("optional", &CollectOptionProperties::onOptional);
 
628
      AddHandler("comma_separated", &CollectOptionProperties::onCommaSeparated);
 
629
      AddHandler("forward_not_split",
 
630
                 &CollectOptionProperties::onForwardNotSplit);
 
631
 
 
632
      staticMembersInitialized_ = true;
 
633
    }
 
634
  }
 
635
 
 
636
  /// operator() - Just forwards to the corresponding property
 
637
  /// handler.
 
638
  void operator() (Init* I) {
 
639
    InvokeDagInitHandler(this, I);
 
640
  }
 
641
 
 
642
private:
 
643
 
 
644
  /// Option property handlers --
 
645
  /// Methods that handle option properties such as (help) or (hidden).
 
646
 
 
647
  void onExtern (const DagInit& d) {
 
648
    CheckNumberOfArguments(d, 0);
 
649
    optDesc_.setExtern();
 
650
  }
 
651
 
 
652
  void onHelp (const DagInit& d) {
 
653
    CheckNumberOfArguments(d, 1);
 
654
    optDesc_.Help = EscapeQuotes(InitPtrToString(d.getArg(0)));
 
655
  }
 
656
 
 
657
  void onHidden (const DagInit& d) {
 
658
    CheckNumberOfArguments(d, 0);
 
659
    optDesc_.setHidden();
 
660
  }
 
661
 
 
662
  void onReallyHidden (const DagInit& d) {
 
663
    CheckNumberOfArguments(d, 0);
 
664
    optDesc_.setReallyHidden();
 
665
  }
 
666
 
 
667
  void onCommaSeparated (const DagInit& d) {
 
668
    CheckNumberOfArguments(d, 0);
 
669
    if (!optDesc_.isList())
 
670
      throw "'comma_separated' is valid only on list options!";
 
671
    optDesc_.setCommaSeparated();
 
672
  }
 
673
 
 
674
  void onForwardNotSplit (const DagInit& d) {
 
675
    CheckNumberOfArguments(d, 0);
 
676
    if (!optDesc_.isParameter())
 
677
      throw "'forward_not_split' is valid only for parameter options!";
 
678
    optDesc_.setForwardNotSplit();
 
679
  }
 
680
 
 
681
  void onRequired (const DagInit& d) {
 
682
    CheckNumberOfArguments(d, 0);
 
683
 
 
684
    optDesc_.setRequired();
 
685
    optDesc_.CheckConsistency();
 
686
  }
 
687
 
 
688
  void onInit (const DagInit& d) {
 
689
    CheckNumberOfArguments(d, 1);
 
690
    Init* i = d.getArg(0);
 
691
    const std::string& str = i->getAsString();
 
692
 
 
693
    bool correct = optDesc_.isParameter() && dynamic_cast<StringInit*>(i);
 
694
    correct |= (optDesc_.isSwitch() && (str == "true" || str == "false"));
 
695
 
 
696
    if (!correct)
 
697
      throw "Incorrect usage of the 'init' option property!";
 
698
 
 
699
    optDesc_.InitVal = i;
 
700
  }
 
701
 
 
702
  void onOneOrMore (const DagInit& d) {
 
703
    CheckNumberOfArguments(d, 0);
 
704
 
 
705
    optDesc_.setOneOrMore();
 
706
    optDesc_.CheckConsistency();
 
707
  }
 
708
 
 
709
  void onZeroOrMore (const DagInit& d) {
 
710
    CheckNumberOfArguments(d, 0);
 
711
 
 
712
    if (OptionType::IsList(optDesc_.Type))
 
713
      llvm::errs() << "Warning: specifying the 'zero_or_more' property "
 
714
        "on a list option has no effect.\n";
 
715
 
 
716
    optDesc_.setZeroOrMore();
 
717
    optDesc_.CheckConsistency();
 
718
  }
 
719
 
 
720
  void onOptional (const DagInit& d) {
 
721
    CheckNumberOfArguments(d, 0);
 
722
 
 
723
    if (!OptionType::IsList(optDesc_.Type))
 
724
      llvm::errs() << "Warning: specifying the 'optional' property"
 
725
        "on a non-list option has no effect.\n";
 
726
 
 
727
    optDesc_.setOptional();
 
728
    optDesc_.CheckConsistency();
 
729
  }
 
730
 
 
731
  void onMultiVal (const DagInit& d) {
 
732
    CheckNumberOfArguments(d, 1);
 
733
    int val = InitPtrToInt(d.getArg(0));
 
734
    if (val < 2)
 
735
      throw "Error in the 'multi_val' property: "
 
736
        "the value must be greater than 1!";
 
737
    if (!OptionType::IsList(optDesc_.Type))
 
738
      throw "The multi_val property is valid only on list options!";
 
739
    optDesc_.MultiVal = val;
 
740
  }
 
741
 
 
742
};
 
743
 
 
744
/// AddOption - A function object that is applied to every option
 
745
/// description. Used by CollectOptionDescriptions.
 
746
class AddOption {
 
747
private:
 
748
  OptionDescriptions& OptDescs_;
 
749
 
 
750
public:
 
751
  explicit AddOption(OptionDescriptions& OD) : OptDescs_(OD)
 
752
  {}
 
753
 
 
754
  void operator()(const Init* i) {
 
755
    const DagInit& d = InitPtrToDag(i);
 
756
    CheckNumberOfArguments(d, 1);
 
757
 
 
758
    const OptionType::OptionType Type =
 
759
      stringToOptionType(GetOperatorName(d));
 
760
    const std::string& Name = InitPtrToString(d.getArg(0));
 
761
 
 
762
    OptionDescription OD(Type, Name);
 
763
 
 
764
    if (!OD.isExtern())
 
765
      CheckNumberOfArguments(d, 2);
 
766
 
 
767
    if (OD.isAlias()) {
 
768
      // Aliases store the aliased option name in the 'Help' field.
 
769
      OD.Help = InitPtrToString(d.getArg(1));
 
770
    }
 
771
    else if (!OD.isExtern()) {
 
772
      processOptionProperties(d, OD);
 
773
    }
 
774
    OptDescs_.InsertDescription(OD);
 
775
  }
 
776
 
 
777
private:
 
778
  /// processOptionProperties - Go through the list of option
 
779
  /// properties and call a corresponding handler for each.
 
780
  static void processOptionProperties (const DagInit& d, OptionDescription& o) {
 
781
    CheckNumberOfArguments(d, 2);
 
782
    DagInit::const_arg_iterator B = d.arg_begin();
 
783
    // Skip the first argument: it's always the option name.
 
784
    ++B;
 
785
    std::for_each(B, d.arg_end(), CollectOptionProperties(o));
 
786
  }
 
787
 
 
788
};
 
789
 
 
790
/// CollectOptionDescriptions - Collects option properties from all
 
791
/// OptionLists.
 
792
void CollectOptionDescriptions (RecordVector::const_iterator B,
 
793
                                RecordVector::const_iterator E,
 
794
                                OptionDescriptions& OptDescs)
 
795
{
 
796
  // For every OptionList:
 
797
  for (; B!=E; ++B) {
 
798
    RecordVector::value_type T = *B;
 
799
    // Throws an exception if the value does not exist.
 
800
    ListInit* PropList = T->getValueAsListInit("options");
 
801
 
 
802
    // For every option description in this list:
 
803
    // collect the information and
 
804
    std::for_each(PropList->begin(), PropList->end(), AddOption(OptDescs));
 
805
  }
 
806
}
 
807
 
 
808
// Tool information record
 
809
 
 
810
namespace ToolFlags {
 
811
  enum ToolFlags { Join = 0x1, Sink = 0x2 };
 
812
}
 
813
 
 
814
struct ToolDescription : public RefCountedBase<ToolDescription> {
 
815
  std::string Name;
 
816
  Init* CmdLine;
 
817
  Init* Actions;
 
818
  StrVector InLanguage;
 
819
  std::string InFileOption;
 
820
  std::string OutFileOption;
 
821
  std::string OutLanguage;
 
822
  std::string OutputSuffix;
 
823
  unsigned Flags;
 
824
  const Init* OnEmpty;
 
825
 
 
826
  // Various boolean properties
 
827
  void setSink()      { Flags |= ToolFlags::Sink; }
 
828
  bool isSink() const { return Flags & ToolFlags::Sink; }
 
829
  void setJoin()      { Flags |= ToolFlags::Join; }
 
830
  bool isJoin() const { return Flags & ToolFlags::Join; }
 
831
 
 
832
  // Default ctor here is needed because StringMap can only store
 
833
  // DefaultConstructible objects
 
834
  ToolDescription ()
 
835
    : CmdLine(0), Actions(0), OutFileOption("-o"),
 
836
      Flags(0), OnEmpty(0)
 
837
  {}
 
838
  ToolDescription (const std::string& n)
 
839
    : Name(n), CmdLine(0), Actions(0), OutFileOption("-o"),
 
840
      Flags(0), OnEmpty(0)
 
841
  {}
 
842
};
 
843
 
 
844
/// ToolDescriptions - A list of Tool information records.
 
845
typedef std::vector<IntrusiveRefCntPtr<ToolDescription> > ToolDescriptions;
 
846
 
 
847
 
 
848
/// CollectToolProperties - Function object for iterating over a list of
 
849
/// tool property records.
 
850
 
 
851
class CollectToolProperties;
 
852
typedef void (CollectToolProperties::* CollectToolPropertiesHandler)
 
853
(const DagInit&);
 
854
 
 
855
class CollectToolProperties : public HandlerTable<CollectToolPropertiesHandler>
 
856
{
 
857
private:
 
858
 
 
859
  /// toolDesc_ - Properties of the current Tool. This is where the
 
860
  /// information is stored.
 
861
  ToolDescription& toolDesc_;
 
862
 
 
863
public:
 
864
 
 
865
  explicit CollectToolProperties (ToolDescription& d)
 
866
    : toolDesc_(d)
 
867
  {
 
868
    if (!staticMembersInitialized_) {
 
869
 
 
870
      AddHandler("actions", &CollectToolProperties::onActions);
 
871
      AddHandler("command", &CollectToolProperties::onCommand);
 
872
      AddHandler("in_language", &CollectToolProperties::onInLanguage);
 
873
      AddHandler("join", &CollectToolProperties::onJoin);
 
874
      AddHandler("out_language", &CollectToolProperties::onOutLanguage);
 
875
 
 
876
      AddHandler("out_file_option", &CollectToolProperties::onOutFileOption);
 
877
      AddHandler("in_file_option", &CollectToolProperties::onInFileOption);
 
878
 
 
879
      AddHandler("output_suffix", &CollectToolProperties::onOutputSuffix);
 
880
      AddHandler("sink", &CollectToolProperties::onSink);
 
881
      AddHandler("works_on_empty", &CollectToolProperties::onWorksOnEmpty);
 
882
 
 
883
      staticMembersInitialized_ = true;
 
884
    }
 
885
  }
 
886
 
 
887
  void operator() (Init* I) {
 
888
    InvokeDagInitHandler(this, I);
 
889
  }
 
890
 
 
891
private:
 
892
 
 
893
  /// Property handlers --
 
894
  /// Functions that extract information about tool properties from
 
895
  /// DAG representation.
 
896
 
 
897
  void onActions (const DagInit& d) {
 
898
    CheckNumberOfArguments(d, 1);
 
899
    Init* Case = d.getArg(0);
 
900
    if (typeid(*Case) != typeid(DagInit) ||
 
901
        GetOperatorName(static_cast<DagInit&>(*Case)) != "case")
 
902
      throw "The argument to (actions) should be a 'case' construct!";
 
903
    toolDesc_.Actions = Case;
 
904
  }
 
905
 
 
906
  void onCommand (const DagInit& d) {
 
907
    CheckNumberOfArguments(d, 1);
 
908
    toolDesc_.CmdLine = d.getArg(0);
 
909
  }
 
910
 
 
911
  void onInLanguage (const DagInit& d) {
 
912
    CheckNumberOfArguments(d, 1);
 
913
    Init* arg = d.getArg(0);
 
914
 
 
915
    // Find out the argument's type.
 
916
    if (typeid(*arg) == typeid(StringInit)) {
 
917
      // It's a string.
 
918
      toolDesc_.InLanguage.push_back(InitPtrToString(arg));
 
919
    }
 
920
    else {
 
921
      // It's a list.
 
922
      const ListInit& lst = InitPtrToList(arg);
 
923
      StrVector& out = toolDesc_.InLanguage;
 
924
 
 
925
      // Copy strings to the output vector.
 
926
      for (ListInit::const_iterator B = lst.begin(), E = lst.end();
 
927
           B != E; ++B) {
 
928
        out.push_back(InitPtrToString(*B));
 
929
      }
 
930
 
 
931
      // Remove duplicates.
 
932
      std::sort(out.begin(), out.end());
 
933
      StrVector::iterator newE = std::unique(out.begin(), out.end());
 
934
      out.erase(newE, out.end());
 
935
    }
 
936
  }
 
937
 
 
938
  void onJoin (const DagInit& d) {
 
939
    CheckNumberOfArguments(d, 0);
 
940
    toolDesc_.setJoin();
 
941
  }
 
942
 
 
943
  void onOutLanguage (const DagInit& d) {
 
944
    CheckNumberOfArguments(d, 1);
 
945
    toolDesc_.OutLanguage = InitPtrToString(d.getArg(0));
 
946
  }
 
947
 
 
948
  void onOutFileOption (const DagInit& d) {
 
949
    CheckNumberOfArguments(d, 1);
 
950
    toolDesc_.OutFileOption = InitPtrToString(d.getArg(0));
 
951
  }
 
952
 
 
953
  void onInFileOption (const DagInit& d) {
 
954
    CheckNumberOfArguments(d, 1);
 
955
    toolDesc_.InFileOption = InitPtrToString(d.getArg(0));
 
956
  }
 
957
 
 
958
  void onOutputSuffix (const DagInit& d) {
 
959
    CheckNumberOfArguments(d, 1);
 
960
    toolDesc_.OutputSuffix = InitPtrToString(d.getArg(0));
 
961
  }
 
962
 
 
963
  void onSink (const DagInit& d) {
 
964
    CheckNumberOfArguments(d, 0);
 
965
    toolDesc_.setSink();
 
966
  }
 
967
 
 
968
  void onWorksOnEmpty (const DagInit& d) {
 
969
    toolDesc_.OnEmpty = d.getArg(0);
 
970
  }
 
971
 
 
972
};
 
973
 
 
974
/// CollectToolDescriptions - Gather information about tool properties
 
975
/// from the parsed TableGen data (basically a wrapper for the
 
976
/// CollectToolProperties function object).
 
977
void CollectToolDescriptions (RecordVector::const_iterator B,
 
978
                              RecordVector::const_iterator E,
 
979
                              ToolDescriptions& ToolDescs)
 
980
{
 
981
  // Iterate over a properties list of every Tool definition
 
982
  for (;B!=E;++B) {
 
983
    const Record* T = *B;
 
984
    // Throws an exception if the value does not exist.
 
985
    ListInit* PropList = T->getValueAsListInit("properties");
 
986
 
 
987
    IntrusiveRefCntPtr<ToolDescription>
 
988
      ToolDesc(new ToolDescription(T->getName()));
 
989
 
 
990
    std::for_each(PropList->begin(), PropList->end(),
 
991
                  CollectToolProperties(*ToolDesc));
 
992
    ToolDescs.push_back(ToolDesc);
 
993
  }
 
994
}
 
995
 
 
996
/// FillInEdgeVector - Merge all compilation graph definitions into
 
997
/// one single edge list.
 
998
void FillInEdgeVector(RecordVector::const_iterator B,
 
999
                      RecordVector::const_iterator E, RecordVector& Out) {
 
1000
  for (; B != E; ++B) {
 
1001
    const ListInit* edges = (*B)->getValueAsListInit("edges");
 
1002
 
 
1003
    for (unsigned i = 0; i < edges->size(); ++i)
 
1004
      Out.push_back(edges->getElementAsRecord(i));
 
1005
  }
 
1006
}
 
1007
 
 
1008
/// CalculatePriority - Calculate the priority of this plugin.
 
1009
int CalculatePriority(RecordVector::const_iterator B,
 
1010
                      RecordVector::const_iterator E) {
 
1011
  int priority = 0;
 
1012
 
 
1013
  if (B != E) {
 
1014
    priority  = static_cast<int>((*B)->getValueAsInt("priority"));
 
1015
 
 
1016
    if (++B != E)
 
1017
      throw "More than one 'PluginPriority' instance found: "
 
1018
        "most probably an error!";
 
1019
  }
 
1020
 
 
1021
  return priority;
 
1022
}
 
1023
 
 
1024
/// NotInGraph - Helper function object for FilterNotInGraph.
 
1025
struct NotInGraph {
 
1026
private:
 
1027
  const llvm::StringSet<>& ToolsInGraph_;
 
1028
 
 
1029
public:
 
1030
  NotInGraph(const llvm::StringSet<>& ToolsInGraph)
 
1031
  : ToolsInGraph_(ToolsInGraph)
 
1032
  {}
 
1033
 
 
1034
  bool operator()(const IntrusiveRefCntPtr<ToolDescription>& x) {
 
1035
    return (ToolsInGraph_.count(x->Name) == 0);
 
1036
  }
 
1037
};
 
1038
 
 
1039
/// FilterNotInGraph - Filter out from ToolDescs all Tools not
 
1040
/// mentioned in the compilation graph definition.
 
1041
void FilterNotInGraph (const RecordVector& EdgeVector,
 
1042
                       ToolDescriptions& ToolDescs) {
 
1043
 
 
1044
  // List all tools mentioned in the graph.
 
1045
  llvm::StringSet<> ToolsInGraph;
 
1046
 
 
1047
  for (RecordVector::const_iterator B = EdgeVector.begin(),
 
1048
         E = EdgeVector.end(); B != E; ++B) {
 
1049
 
 
1050
    const Record* Edge = *B;
 
1051
    const std::string& NodeA = Edge->getValueAsString("a");
 
1052
    const std::string& NodeB = Edge->getValueAsString("b");
 
1053
 
 
1054
    if (NodeA != "root")
 
1055
      ToolsInGraph.insert(NodeA);
 
1056
    ToolsInGraph.insert(NodeB);
 
1057
  }
 
1058
 
 
1059
  // Filter ToolPropertiesList.
 
1060
  ToolDescriptions::iterator new_end =
 
1061
    std::remove_if(ToolDescs.begin(), ToolDescs.end(),
 
1062
                   NotInGraph(ToolsInGraph));
 
1063
  ToolDescs.erase(new_end, ToolDescs.end());
 
1064
}
 
1065
 
 
1066
/// FillInToolToLang - Fills in two tables that map tool names to
 
1067
/// (input, output) languages.  Helper function used by TypecheckGraph().
 
1068
void FillInToolToLang (const ToolDescriptions& ToolDescs,
 
1069
                       StringMap<StringSet<> >& ToolToInLang,
 
1070
                       StringMap<std::string>& ToolToOutLang) {
 
1071
  for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
 
1072
         E = ToolDescs.end(); B != E; ++B) {
 
1073
    const ToolDescription& D = *(*B);
 
1074
    for (StrVector::const_iterator B = D.InLanguage.begin(),
 
1075
           E = D.InLanguage.end(); B != E; ++B)
 
1076
      ToolToInLang[D.Name].insert(*B);
 
1077
    ToolToOutLang[D.Name] = D.OutLanguage;
 
1078
  }
 
1079
}
 
1080
 
 
1081
/// TypecheckGraph - Check that names for output and input languages
 
1082
/// on all edges do match. This doesn't do much when the information
 
1083
/// about the whole graph is not available (i.e. when compiling most
 
1084
/// plugins).
 
1085
void TypecheckGraph (const RecordVector& EdgeVector,
 
1086
                     const ToolDescriptions& ToolDescs) {
 
1087
  StringMap<StringSet<> > ToolToInLang;
 
1088
  StringMap<std::string> ToolToOutLang;
 
1089
 
 
1090
  FillInToolToLang(ToolDescs, ToolToInLang, ToolToOutLang);
 
1091
  StringMap<std::string>::iterator IAE = ToolToOutLang.end();
 
1092
  StringMap<StringSet<> >::iterator IBE = ToolToInLang.end();
 
1093
 
 
1094
  for (RecordVector::const_iterator B = EdgeVector.begin(),
 
1095
         E = EdgeVector.end(); B != E; ++B) {
 
1096
    const Record* Edge = *B;
 
1097
    const std::string& NodeA = Edge->getValueAsString("a");
 
1098
    const std::string& NodeB = Edge->getValueAsString("b");
 
1099
    StringMap<std::string>::iterator IA = ToolToOutLang.find(NodeA);
 
1100
    StringMap<StringSet<> >::iterator IB = ToolToInLang.find(NodeB);
 
1101
 
 
1102
    if (NodeA != "root") {
 
1103
      if (IA != IAE && IB != IBE && IB->second.count(IA->second) == 0)
 
1104
        throw "Edge " + NodeA + "->" + NodeB
 
1105
          + ": output->input language mismatch";
 
1106
    }
 
1107
 
 
1108
    if (NodeB == "root")
 
1109
      throw "Edges back to the root are not allowed!";
 
1110
  }
 
1111
}
 
1112
 
 
1113
/// WalkCase - Walks the 'case' expression DAG and invokes
 
1114
/// TestCallback on every test, and StatementCallback on every
 
1115
/// statement. Handles 'case' nesting, but not the 'and' and 'or'
 
1116
/// combinators (that is, they are passed directly to TestCallback).
 
1117
/// TestCallback must have type 'void TestCallback(const DagInit*, unsigned
 
1118
/// IndentLevel, bool FirstTest)'.
 
1119
/// StatementCallback must have type 'void StatementCallback(const Init*,
 
1120
/// unsigned IndentLevel)'.
 
1121
template <typename F1, typename F2>
 
1122
void WalkCase(const Init* Case, F1 TestCallback, F2 StatementCallback,
 
1123
              unsigned IndentLevel = 0)
 
1124
{
 
1125
  const DagInit& d = InitPtrToDag(Case);
 
1126
 
 
1127
  // Error checks.
 
1128
  if (GetOperatorName(d) != "case")
 
1129
    throw "WalkCase should be invoked only on 'case' expressions!";
 
1130
 
 
1131
  if (d.getNumArgs() < 2)
 
1132
    throw "There should be at least one clause in the 'case' expression:\n"
 
1133
      + d.getAsString();
 
1134
 
 
1135
  // Main loop.
 
1136
  bool even = false;
 
1137
  const unsigned numArgs = d.getNumArgs();
 
1138
  unsigned i = 1;
 
1139
  for (DagInit::const_arg_iterator B = d.arg_begin(), E = d.arg_end();
 
1140
       B != E; ++B) {
 
1141
    Init* arg = *B;
 
1142
 
 
1143
    if (!even)
 
1144
    {
 
1145
      // Handle test.
 
1146
      const DagInit& Test = InitPtrToDag(arg);
 
1147
 
 
1148
      if (GetOperatorName(Test) == "default" && (i+1 != numArgs))
 
1149
        throw "The 'default' clause should be the last in the "
 
1150
          "'case' construct!";
 
1151
      if (i == numArgs)
 
1152
        throw "Case construct handler: no corresponding action "
 
1153
          "found for the test " + Test.getAsString() + '!';
 
1154
 
 
1155
      TestCallback(Test, IndentLevel, (i == 1));
 
1156
    }
 
1157
    else
 
1158
    {
 
1159
      if (dynamic_cast<DagInit*>(arg)
 
1160
          && GetOperatorName(static_cast<DagInit&>(*arg)) == "case") {
 
1161
        // Nested 'case'.
 
1162
        WalkCase(arg, TestCallback, StatementCallback, IndentLevel + Indent1);
 
1163
      }
 
1164
 
 
1165
      // Handle statement.
 
1166
      StatementCallback(arg, IndentLevel);
 
1167
    }
 
1168
 
 
1169
    ++i;
 
1170
    even = !even;
 
1171
  }
 
1172
}
 
1173
 
 
1174
/// ExtractOptionNames - A helper function object used by
 
1175
/// CheckForSuperfluousOptions() to walk the 'case' DAG.
 
1176
class ExtractOptionNames {
 
1177
  llvm::StringSet<>& OptionNames_;
 
1178
 
 
1179
  void processDag(const Init* Statement) {
 
1180
    const DagInit& Stmt = InitPtrToDag(Statement);
 
1181
    const std::string& ActionName = GetOperatorName(Stmt);
 
1182
    if (ActionName == "forward" || ActionName == "forward_as" ||
 
1183
        ActionName == "forward_value" ||
 
1184
        ActionName == "forward_transformed_value" ||
 
1185
        ActionName == "switch_on" || ActionName == "any_switch_on" ||
 
1186
        ActionName == "parameter_equals" ||
 
1187
        ActionName == "element_in_list" || ActionName == "not_empty" ||
 
1188
        ActionName == "empty") {
 
1189
      CheckNumberOfArguments(Stmt, 1);
 
1190
 
 
1191
      Init* Arg = Stmt.getArg(0);
 
1192
      if (typeid(*Arg) == typeid(StringInit)) {
 
1193
        const std::string& Name = InitPtrToString(Arg);
 
1194
        OptionNames_.insert(Name);
 
1195
      }
 
1196
      else {
 
1197
        // It's a list.
 
1198
        const ListInit& List = InitPtrToList(Arg);
 
1199
        for (ListInit::const_iterator B = List.begin(), E = List.end();
 
1200
             B != E; ++B) {
 
1201
          const std::string& Name = InitPtrToString(*B);
 
1202
          OptionNames_.insert(Name);
 
1203
        }
 
1204
      }
 
1205
    }
 
1206
    else if (ActionName == "and" || ActionName == "or" || ActionName == "not") {
 
1207
      for (unsigned i = 0, NumArgs = Stmt.getNumArgs(); i < NumArgs; ++i) {
 
1208
        this->processDag(Stmt.getArg(i));
 
1209
      }
 
1210
    }
 
1211
  }
 
1212
 
 
1213
public:
 
1214
  ExtractOptionNames(llvm::StringSet<>& OptionNames) : OptionNames_(OptionNames)
 
1215
  {}
 
1216
 
 
1217
  void operator()(const Init* Statement) {
 
1218
    if (typeid(*Statement) == typeid(ListInit)) {
 
1219
      const ListInit& DagList = *static_cast<const ListInit*>(Statement);
 
1220
      for (ListInit::const_iterator B = DagList.begin(), E = DagList.end();
 
1221
           B != E; ++B)
 
1222
        this->processDag(*B);
 
1223
    }
 
1224
    else {
 
1225
      this->processDag(Statement);
 
1226
    }
 
1227
  }
 
1228
 
 
1229
  void operator()(const DagInit& Test, unsigned, bool) {
 
1230
    this->operator()(&Test);
 
1231
  }
 
1232
  void operator()(const Init* Statement, unsigned) {
 
1233
    this->operator()(Statement);
 
1234
  }
 
1235
};
 
1236
 
 
1237
/// CheckForSuperfluousOptions - Check that there are no side
 
1238
/// effect-free options (specified only in the OptionList). Otherwise,
 
1239
/// output a warning.
 
1240
void CheckForSuperfluousOptions (const RecordVector& Edges,
 
1241
                                 const ToolDescriptions& ToolDescs,
 
1242
                                 const OptionDescriptions& OptDescs) {
 
1243
  llvm::StringSet<> nonSuperfluousOptions;
 
1244
 
 
1245
  // Add all options mentioned in the ToolDesc.Actions to the set of
 
1246
  // non-superfluous options.
 
1247
  for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
 
1248
         E = ToolDescs.end(); B != E; ++B) {
 
1249
    const ToolDescription& TD = *(*B);
 
1250
    ExtractOptionNames Callback(nonSuperfluousOptions);
 
1251
    if (TD.Actions)
 
1252
      WalkCase(TD.Actions, Callback, Callback);
 
1253
  }
 
1254
 
 
1255
  // Add all options mentioned in the 'case' clauses of the
 
1256
  // OptionalEdges of the compilation graph to the set of
 
1257
  // non-superfluous options.
 
1258
  for (RecordVector::const_iterator B = Edges.begin(), E = Edges.end();
 
1259
       B != E; ++B) {
 
1260
    const Record* Edge = *B;
 
1261
    DagInit& Weight = *Edge->getValueAsDag("weight");
 
1262
 
 
1263
    if (!IsDagEmpty(Weight))
 
1264
      WalkCase(&Weight, ExtractOptionNames(nonSuperfluousOptions), Id());
 
1265
  }
 
1266
 
 
1267
  // Check that all options in OptDescs belong to the set of
 
1268
  // non-superfluous options.
 
1269
  for (OptionDescriptions::const_iterator B = OptDescs.begin(),
 
1270
         E = OptDescs.end(); B != E; ++B) {
 
1271
    const OptionDescription& Val = B->second;
 
1272
    if (!nonSuperfluousOptions.count(Val.Name)
 
1273
        && Val.Type != OptionType::Alias)
 
1274
      llvm::errs() << "Warning: option '-" << Val.Name << "' has no effect! "
 
1275
        "Probable cause: this option is specified only in the OptionList.\n";
 
1276
  }
 
1277
}
 
1278
 
 
1279
/// EmitCaseTest0Args - Helper function used by EmitCaseConstructHandler().
 
1280
bool EmitCaseTest0Args(const std::string& TestName, raw_ostream& O) {
 
1281
  if (TestName == "single_input_file") {
 
1282
    O << "InputFilenames.size() == 1";
 
1283
    return true;
 
1284
  }
 
1285
  else if (TestName == "multiple_input_files") {
 
1286
    O << "InputFilenames.size() > 1";
 
1287
    return true;
 
1288
  }
 
1289
 
 
1290
  return false;
 
1291
}
 
1292
 
 
1293
/// EmitListTest - Helper function used by EmitCaseTest1ArgList().
 
1294
template <typename F>
 
1295
void EmitListTest(const ListInit& L, const char* LogicOp,
 
1296
                  F Callback, raw_ostream& O)
 
1297
{
 
1298
  // This is a lot like EmitLogicalOperationTest, but works on ListInits instead
 
1299
  // of Dags...
 
1300
  bool isFirst = true;
 
1301
  for (ListInit::const_iterator B = L.begin(), E = L.end(); B != E; ++B) {
 
1302
    if (isFirst)
 
1303
      isFirst = false;
 
1304
    else
 
1305
      O << ' ' << LogicOp << ' ';
 
1306
    Callback(InitPtrToString(*B), O);
 
1307
  }
 
1308
}
 
1309
 
 
1310
// Callbacks for use with EmitListTest.
 
1311
 
 
1312
class EmitSwitchOn {
 
1313
  const OptionDescriptions& OptDescs_;
 
1314
public:
 
1315
  EmitSwitchOn(const OptionDescriptions& OptDescs) : OptDescs_(OptDescs)
 
1316
  {}
 
1317
 
 
1318
  void operator()(const std::string& OptName, raw_ostream& O) const {
 
1319
    const OptionDescription& OptDesc = OptDescs_.FindSwitch(OptName);
 
1320
    O << OptDesc.GenVariableName();
 
1321
  }
 
1322
};
 
1323
 
 
1324
class EmitEmptyTest {
 
1325
  bool EmitNegate_;
 
1326
  const OptionDescriptions& OptDescs_;
 
1327
public:
 
1328
  EmitEmptyTest(bool EmitNegate, const OptionDescriptions& OptDescs)
 
1329
    : EmitNegate_(EmitNegate), OptDescs_(OptDescs)
 
1330
  {}
 
1331
 
 
1332
  void operator()(const std::string& OptName, raw_ostream& O) const {
 
1333
    const char* Neg = (EmitNegate_ ? "!" : "");
 
1334
    if (OptName == "o") {
 
1335
      O << Neg << "OutputFilename.empty()";
 
1336
    }
 
1337
    else if (OptName == "save-temps") {
 
1338
      O << Neg << "(SaveTemps == SaveTempsEnum::Unset)";
 
1339
    }
 
1340
    else {
 
1341
      const OptionDescription& OptDesc = OptDescs_.FindListOrParameter(OptName);
 
1342
      O << Neg << OptDesc.GenVariableName() << ".empty()";
 
1343
    }
 
1344
  }
 
1345
};
 
1346
 
 
1347
 
 
1348
/// EmitCaseTest1ArgList - Helper function used by EmitCaseTest1Arg();
 
1349
bool EmitCaseTest1ArgList(const std::string& TestName,
 
1350
                          const DagInit& d,
 
1351
                          const OptionDescriptions& OptDescs,
 
1352
                          raw_ostream& O) {
 
1353
  const ListInit& L = InitPtrToList(d.getArg(0));
 
1354
 
 
1355
  if (TestName == "any_switch_on") {
 
1356
    EmitListTest(L, "||", EmitSwitchOn(OptDescs), O);
 
1357
    return true;
 
1358
  }
 
1359
  else if (TestName == "switch_on") {
 
1360
    EmitListTest(L, "&&", EmitSwitchOn(OptDescs), O);
 
1361
    return true;
 
1362
  }
 
1363
  else if (TestName == "any_not_empty") {
 
1364
    EmitListTest(L, "||", EmitEmptyTest(true, OptDescs), O);
 
1365
    return true;
 
1366
  }
 
1367
  else if (TestName == "any_empty") {
 
1368
    EmitListTest(L, "||", EmitEmptyTest(false, OptDescs), O);
 
1369
    return true;
 
1370
  }
 
1371
  else if (TestName == "not_empty") {
 
1372
    EmitListTest(L, "&&", EmitEmptyTest(true, OptDescs), O);
 
1373
    return true;
 
1374
  }
 
1375
  else if (TestName == "empty") {
 
1376
    EmitListTest(L, "&&", EmitEmptyTest(false, OptDescs), O);
 
1377
    return true;
 
1378
  }
 
1379
 
 
1380
  return false;
 
1381
}
 
1382
 
 
1383
/// EmitCaseTest1ArgStr - Helper function used by EmitCaseTest1Arg();
 
1384
bool EmitCaseTest1ArgStr(const std::string& TestName,
 
1385
                         const DagInit& d,
 
1386
                         const OptionDescriptions& OptDescs,
 
1387
                         raw_ostream& O) {
 
1388
  const std::string& OptName = InitPtrToString(d.getArg(0));
 
1389
 
 
1390
  if (TestName == "switch_on") {
 
1391
    apply(EmitSwitchOn(OptDescs), OptName, O);
 
1392
    return true;
 
1393
  }
 
1394
  else if (TestName == "input_languages_contain") {
 
1395
    O << "InLangs.count(\"" << OptName << "\") != 0";
 
1396
    return true;
 
1397
  }
 
1398
  else if (TestName == "in_language") {
 
1399
    // This works only for single-argument Tool::GenerateAction. Join
 
1400
    // tools can process several files in different languages simultaneously.
 
1401
 
 
1402
    // TODO: make this work with Edge::Weight (if possible).
 
1403
    O << "LangMap.GetLanguage(inFile) == \"" << OptName << '\"';
 
1404
    return true;
 
1405
  }
 
1406
  else if (TestName == "not_empty" || TestName == "empty") {
 
1407
    bool EmitNegate = (TestName == "not_empty");
 
1408
    apply(EmitEmptyTest(EmitNegate, OptDescs), OptName, O);
 
1409
    return true;
 
1410
  }
 
1411
 
 
1412
  return false;
 
1413
}
 
1414
 
 
1415
/// EmitCaseTest1Arg - Helper function used by EmitCaseConstructHandler();
 
1416
bool EmitCaseTest1Arg(const std::string& TestName,
 
1417
                      const DagInit& d,
 
1418
                      const OptionDescriptions& OptDescs,
 
1419
                      raw_ostream& O) {
 
1420
  CheckNumberOfArguments(d, 1);
 
1421
  if (typeid(*d.getArg(0)) == typeid(ListInit))
 
1422
    return EmitCaseTest1ArgList(TestName, d, OptDescs, O);
 
1423
  else
 
1424
    return EmitCaseTest1ArgStr(TestName, d, OptDescs, O);
 
1425
}
 
1426
 
 
1427
/// EmitCaseTest2Args - Helper function used by EmitCaseConstructHandler().
 
1428
bool EmitCaseTest2Args(const std::string& TestName,
 
1429
                       const DagInit& d,
 
1430
                       unsigned IndentLevel,
 
1431
                       const OptionDescriptions& OptDescs,
 
1432
                       raw_ostream& O) {
 
1433
  CheckNumberOfArguments(d, 2);
 
1434
  const std::string& OptName = InitPtrToString(d.getArg(0));
 
1435
  const std::string& OptArg = InitPtrToString(d.getArg(1));
 
1436
 
 
1437
  if (TestName == "parameter_equals") {
 
1438
    const OptionDescription& OptDesc = OptDescs.FindParameter(OptName);
 
1439
    O << OptDesc.GenVariableName() << " == \"" << OptArg << "\"";
 
1440
    return true;
 
1441
  }
 
1442
  else if (TestName == "element_in_list") {
 
1443
    const OptionDescription& OptDesc = OptDescs.FindList(OptName);
 
1444
    const std::string& VarName = OptDesc.GenVariableName();
 
1445
    O << "std::find(" << VarName << ".begin(),\n";
 
1446
    O.indent(IndentLevel + Indent1)
 
1447
      << VarName << ".end(), \""
 
1448
      << OptArg << "\") != " << VarName << ".end()";
 
1449
    return true;
 
1450
  }
 
1451
 
 
1452
  return false;
 
1453
}
 
1454
 
 
1455
// Forward declaration.
 
1456
// EmitLogicalOperationTest and EmitCaseTest are mutually recursive.
 
1457
void EmitCaseTest(const DagInit& d, unsigned IndentLevel,
 
1458
                  const OptionDescriptions& OptDescs,
 
1459
                  raw_ostream& O);
 
1460
 
 
1461
/// EmitLogicalOperationTest - Helper function used by
 
1462
/// EmitCaseConstructHandler.
 
1463
void EmitLogicalOperationTest(const DagInit& d, const char* LogicOp,
 
1464
                              unsigned IndentLevel,
 
1465
                              const OptionDescriptions& OptDescs,
 
1466
                              raw_ostream& O) {
 
1467
  O << '(';
 
1468
  for (unsigned j = 0, NumArgs = d.getNumArgs(); j < NumArgs; ++j) {
 
1469
    const DagInit& InnerTest = InitPtrToDag(d.getArg(j));
 
1470
    EmitCaseTest(InnerTest, IndentLevel, OptDescs, O);
 
1471
    if (j != NumArgs - 1) {
 
1472
      O << ")\n";
 
1473
      O.indent(IndentLevel + Indent1) << ' ' << LogicOp << " (";
 
1474
    }
 
1475
    else {
 
1476
      O << ')';
 
1477
    }
 
1478
  }
 
1479
}
 
1480
 
 
1481
void EmitLogicalNot(const DagInit& d, unsigned IndentLevel,
 
1482
                    const OptionDescriptions& OptDescs, raw_ostream& O)
 
1483
{
 
1484
  CheckNumberOfArguments(d, 1);
 
1485
  const DagInit& InnerTest = InitPtrToDag(d.getArg(0));
 
1486
  O << "! (";
 
1487
  EmitCaseTest(InnerTest, IndentLevel, OptDescs, O);
 
1488
  O << ")";
 
1489
}
 
1490
 
 
1491
/// EmitCaseTest - Helper function used by EmitCaseConstructHandler.
 
1492
void EmitCaseTest(const DagInit& d, unsigned IndentLevel,
 
1493
                  const OptionDescriptions& OptDescs,
 
1494
                  raw_ostream& O) {
 
1495
  const std::string& TestName = GetOperatorName(d);
 
1496
 
 
1497
  if (TestName == "and")
 
1498
    EmitLogicalOperationTest(d, "&&", IndentLevel, OptDescs, O);
 
1499
  else if (TestName == "or")
 
1500
    EmitLogicalOperationTest(d, "||", IndentLevel, OptDescs, O);
 
1501
  else if (TestName == "not")
 
1502
    EmitLogicalNot(d, IndentLevel, OptDescs, O);
 
1503
  else if (EmitCaseTest0Args(TestName, O))
 
1504
    return;
 
1505
  else if (EmitCaseTest1Arg(TestName, d, OptDescs, O))
 
1506
    return;
 
1507
  else if (EmitCaseTest2Args(TestName, d, IndentLevel, OptDescs, O))
 
1508
    return;
 
1509
  else
 
1510
    throw "Unknown test '" + TestName + "' used in the 'case' construct!";
 
1511
}
 
1512
 
 
1513
 
 
1514
/// EmitCaseTestCallback - Callback used by EmitCaseConstructHandler.
 
1515
class EmitCaseTestCallback {
 
1516
  bool EmitElseIf_;
 
1517
  const OptionDescriptions& OptDescs_;
 
1518
  raw_ostream& O_;
 
1519
public:
 
1520
 
 
1521
  EmitCaseTestCallback(bool EmitElseIf,
 
1522
                       const OptionDescriptions& OptDescs, raw_ostream& O)
 
1523
    : EmitElseIf_(EmitElseIf), OptDescs_(OptDescs), O_(O)
 
1524
  {}
 
1525
 
 
1526
  void operator()(const DagInit& Test, unsigned IndentLevel, bool FirstTest)
 
1527
  {
 
1528
    if (GetOperatorName(Test) == "default") {
 
1529
      O_.indent(IndentLevel) << "else {\n";
 
1530
    }
 
1531
    else {
 
1532
      O_.indent(IndentLevel)
 
1533
        << ((!FirstTest && EmitElseIf_) ? "else if (" : "if (");
 
1534
      EmitCaseTest(Test, IndentLevel, OptDescs_, O_);
 
1535
      O_ << ") {\n";
 
1536
    }
 
1537
  }
 
1538
};
 
1539
 
 
1540
/// EmitCaseStatementCallback - Callback used by EmitCaseConstructHandler.
 
1541
template <typename F>
 
1542
class EmitCaseStatementCallback {
 
1543
  F Callback_;
 
1544
  raw_ostream& O_;
 
1545
public:
 
1546
 
 
1547
  EmitCaseStatementCallback(F Callback, raw_ostream& O)
 
1548
    : Callback_(Callback), O_(O)
 
1549
  {}
 
1550
 
 
1551
  void operator() (const Init* Statement, unsigned IndentLevel) {
 
1552
 
 
1553
    // Ignore nested 'case' DAG.
 
1554
    if (!(dynamic_cast<const DagInit*>(Statement) &&
 
1555
          GetOperatorName(static_cast<const DagInit&>(*Statement)) == "case")) {
 
1556
      if (typeid(*Statement) == typeid(ListInit)) {
 
1557
        const ListInit& DagList = *static_cast<const ListInit*>(Statement);
 
1558
        for (ListInit::const_iterator B = DagList.begin(), E = DagList.end();
 
1559
             B != E; ++B)
 
1560
          Callback_(*B, (IndentLevel + Indent1), O_);
 
1561
      }
 
1562
      else {
 
1563
        Callback_(Statement, (IndentLevel + Indent1), O_);
 
1564
      }
 
1565
    }
 
1566
    O_.indent(IndentLevel) << "}\n";
 
1567
  }
 
1568
 
 
1569
};
 
1570
 
 
1571
/// EmitCaseConstructHandler - Emit code that handles the 'case'
 
1572
/// construct. Takes a function object that should emit code for every case
 
1573
/// clause. Implemented on top of WalkCase.
 
1574
/// Callback's type is void F(const Init* Statement, unsigned IndentLevel,
 
1575
/// raw_ostream& O).
 
1576
/// EmitElseIf parameter controls the type of condition that is emitted ('if
 
1577
/// (..) {..} else if (..) {} .. else {..}' vs. 'if (..) {..} if(..)  {..}
 
1578
/// .. else {..}').
 
1579
template <typename F>
 
1580
void EmitCaseConstructHandler(const Init* Case, unsigned IndentLevel,
 
1581
                              F Callback, bool EmitElseIf,
 
1582
                              const OptionDescriptions& OptDescs,
 
1583
                              raw_ostream& O) {
 
1584
  WalkCase(Case, EmitCaseTestCallback(EmitElseIf, OptDescs, O),
 
1585
           EmitCaseStatementCallback<F>(Callback, O), IndentLevel);
 
1586
}
 
1587
 
 
1588
/// TokenizeCmdLine - converts from
 
1589
/// "$CALL(HookName, 'Arg1', 'Arg2')/path -arg1 -arg2" to
 
1590
/// ["$CALL(", "HookName", "Arg1", "Arg2", ")/path", "-arg1", "-arg2"].
 
1591
void TokenizeCmdLine(const std::string& CmdLine, StrVector& Out) {
 
1592
  const char* Delimiters = " \t\n\v\f\r";
 
1593
  enum TokenizerState
 
1594
  { Normal, SpecialCommand, InsideSpecialCommand, InsideQuotationMarks }
 
1595
  cur_st  = Normal;
 
1596
 
 
1597
  if (CmdLine.empty())
 
1598
    return;
 
1599
  Out.push_back("");
 
1600
 
 
1601
  std::string::size_type B = CmdLine.find_first_not_of(Delimiters),
 
1602
    E = CmdLine.size();
 
1603
 
 
1604
  for (; B != E; ++B) {
 
1605
    char cur_ch = CmdLine[B];
 
1606
 
 
1607
    switch (cur_st) {
 
1608
    case Normal:
 
1609
      if (cur_ch == '$') {
 
1610
        cur_st = SpecialCommand;
 
1611
        break;
 
1612
      }
 
1613
      if (OneOf(Delimiters, cur_ch)) {
 
1614
        // Skip whitespace
 
1615
        B = CmdLine.find_first_not_of(Delimiters, B);
 
1616
        if (B == std::string::npos) {
 
1617
          B = E-1;
 
1618
          continue;
 
1619
        }
 
1620
        --B;
 
1621
        Out.push_back("");
 
1622
        continue;
 
1623
      }
 
1624
      break;
 
1625
 
 
1626
 
 
1627
    case SpecialCommand:
 
1628
      if (OneOf(Delimiters, cur_ch)) {
 
1629
        cur_st = Normal;
 
1630
        Out.push_back("");
 
1631
        continue;
 
1632
      }
 
1633
      if (cur_ch == '(') {
 
1634
        Out.push_back("");
 
1635
        cur_st = InsideSpecialCommand;
 
1636
        continue;
 
1637
      }
 
1638
      break;
 
1639
 
 
1640
    case InsideSpecialCommand:
 
1641
      if (OneOf(Delimiters, cur_ch)) {
 
1642
        continue;
 
1643
      }
 
1644
      if (cur_ch == '\'') {
 
1645
        cur_st = InsideQuotationMarks;
 
1646
        Out.push_back("");
 
1647
        continue;
 
1648
      }
 
1649
      if (cur_ch == ')') {
 
1650
        cur_st = Normal;
 
1651
        Out.push_back("");
 
1652
      }
 
1653
      if (cur_ch == ',') {
 
1654
        continue;
 
1655
      }
 
1656
 
 
1657
      break;
 
1658
 
 
1659
    case InsideQuotationMarks:
 
1660
      if (cur_ch == '\'') {
 
1661
        cur_st = InsideSpecialCommand;
 
1662
        continue;
 
1663
      }
 
1664
      break;
 
1665
    }
 
1666
 
 
1667
    Out.back().push_back(cur_ch);
 
1668
  }
 
1669
}
 
1670
 
 
1671
/// SubstituteCall - Given "$CALL(HookName, [Arg1 [, Arg2 [...]]])", output
 
1672
/// "hooks::HookName([Arg1 [, Arg2 [, ...]]])". Helper function used by
 
1673
/// SubstituteSpecialCommands().
 
1674
StrVector::const_iterator
 
1675
SubstituteCall (StrVector::const_iterator Pos,
 
1676
                StrVector::const_iterator End,
 
1677
                bool IsJoin, raw_ostream& O)
 
1678
{
 
1679
  const char* errorMessage = "Syntax error in $CALL invocation!";
 
1680
  CheckedIncrement(Pos, End, errorMessage);
 
1681
  const std::string& CmdName = *Pos;
 
1682
 
 
1683
  if (CmdName == ")")
 
1684
    throw "$CALL invocation: empty argument list!";
 
1685
 
 
1686
  O << "hooks::";
 
1687
  O << CmdName << "(";
 
1688
 
 
1689
 
 
1690
  bool firstIteration = true;
 
1691
  while (true) {
 
1692
    CheckedIncrement(Pos, End, errorMessage);
 
1693
    const std::string& Arg = *Pos;
 
1694
    assert(Arg.size() != 0);
 
1695
 
 
1696
    if (Arg[0] == ')')
 
1697
      break;
 
1698
 
 
1699
    if (firstIteration)
 
1700
      firstIteration = false;
 
1701
    else
 
1702
      O << ", ";
 
1703
 
 
1704
    if (Arg == "$INFILE") {
 
1705
      if (IsJoin)
 
1706
        throw "$CALL(Hook, $INFILE) can't be used with a Join tool!";
 
1707
      else
 
1708
        O << "inFile.c_str()";
 
1709
    }
 
1710
    else {
 
1711
      O << '"' << Arg << '"';
 
1712
    }
 
1713
  }
 
1714
 
 
1715
  O << ')';
 
1716
 
 
1717
  return Pos;
 
1718
}
 
1719
 
 
1720
/// SubstituteEnv - Given '$ENV(VAR_NAME)', output 'getenv("VAR_NAME")'. Helper
 
1721
/// function used by SubstituteSpecialCommands().
 
1722
StrVector::const_iterator
 
1723
SubstituteEnv (StrVector::const_iterator Pos,
 
1724
               StrVector::const_iterator End, raw_ostream& O)
 
1725
{
 
1726
  const char* errorMessage = "Syntax error in $ENV invocation!";
 
1727
  CheckedIncrement(Pos, End, errorMessage);
 
1728
  const std::string& EnvName = *Pos;
 
1729
 
 
1730
  if (EnvName == ")")
 
1731
    throw "$ENV invocation: empty argument list!";
 
1732
 
 
1733
  O << "checkCString(std::getenv(\"";
 
1734
  O << EnvName;
 
1735
  O << "\"))";
 
1736
 
 
1737
  CheckedIncrement(Pos, End, errorMessage);
 
1738
 
 
1739
  return Pos;
 
1740
}
 
1741
 
 
1742
/// SubstituteSpecialCommands - Given an invocation of $CALL or $ENV, output
 
1743
/// handler code. Helper function used by EmitCmdLineVecFill().
 
1744
StrVector::const_iterator
 
1745
SubstituteSpecialCommands (StrVector::const_iterator Pos,
 
1746
                           StrVector::const_iterator End,
 
1747
                           bool IsJoin, raw_ostream& O)
 
1748
{
 
1749
 
 
1750
  const std::string& cmd = *Pos;
 
1751
 
 
1752
  // Perform substitution.
 
1753
  if (cmd == "$CALL") {
 
1754
    Pos = SubstituteCall(Pos, End, IsJoin, O);
 
1755
  }
 
1756
  else if (cmd == "$ENV") {
 
1757
    Pos = SubstituteEnv(Pos, End, O);
 
1758
  }
 
1759
  else {
 
1760
    throw "Unknown special command: " + cmd;
 
1761
  }
 
1762
 
 
1763
  // Handle '$CMD(ARG)/additional/text'.
 
1764
  const std::string& Leftover = *Pos;
 
1765
  assert(Leftover.at(0) == ')');
 
1766
  if (Leftover.size() != 1)
 
1767
    O << " + std::string(\"" << (Leftover.c_str() + 1) << "\")";
 
1768
 
 
1769
  return Pos;
 
1770
}
 
1771
 
 
1772
/// EmitCmdLineVecFill - Emit code that fills in the command line
 
1773
/// vector. Helper function used by EmitGenerateActionMethod().
 
1774
void EmitCmdLineVecFill(const Init* CmdLine, const std::string& ToolName,
 
1775
                        bool IsJoin, unsigned IndentLevel,
 
1776
                        raw_ostream& O) {
 
1777
  StrVector StrVec;
 
1778
  TokenizeCmdLine(InitPtrToString(CmdLine), StrVec);
 
1779
 
 
1780
  if (StrVec.empty())
 
1781
    throw "Tool '" + ToolName + "' has empty command line!";
 
1782
 
 
1783
  StrVector::const_iterator B = StrVec.begin(), E = StrVec.end();
 
1784
 
 
1785
  // Emit the command itself.
 
1786
  assert(!StrVec[0].empty());
 
1787
  O.indent(IndentLevel) << "cmd = ";
 
1788
  if (StrVec[0][0] == '$') {
 
1789
    B = SubstituteSpecialCommands(B, E, IsJoin, O);
 
1790
    ++B;
 
1791
  }
 
1792
  else {
 
1793
    O << '"' << StrVec[0] << '"';
 
1794
    ++B;
 
1795
  }
 
1796
  O << ";\n";
 
1797
 
 
1798
  // Go through the command arguments.
 
1799
  assert(B <= E);
 
1800
  for (; B != E; ++B) {
 
1801
    const std::string& cmd = *B;
 
1802
 
 
1803
    assert(!cmd.empty());
 
1804
    O.indent(IndentLevel);
 
1805
 
 
1806
    if (cmd.at(0) == '$') {
 
1807
      O << "vec.push_back(std::make_pair(0, ";
 
1808
      B = SubstituteSpecialCommands(B, E, IsJoin, O);
 
1809
      O << "));\n";
 
1810
    }
 
1811
    else {
 
1812
      O << "vec.push_back(std::make_pair(0, \"" << cmd << "\"));\n";
 
1813
    }
 
1814
  }
 
1815
 
 
1816
}
 
1817
 
 
1818
/// EmitForwardOptionPropertyHandlingCode - Helper function used to
 
1819
/// implement EmitActionHandler. Emits code for
 
1820
/// handling the (forward) and (forward_as) option properties.
 
1821
void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,
 
1822
                                            unsigned IndentLevel,
 
1823
                                            const std::string& NewName,
 
1824
                                            raw_ostream& O) {
 
1825
  const std::string& Name = NewName.empty()
 
1826
    ? ("-" + D.Name)
 
1827
    : NewName;
 
1828
  unsigned IndentLevel1 = IndentLevel + Indent1;
 
1829
 
 
1830
  switch (D.Type) {
 
1831
  case OptionType::Switch:
 
1832
    O.indent(IndentLevel)
 
1833
      << "vec.push_back(std::make_pair(" << D.GenVariableName()
 
1834
      << ".getPosition(), \"" << Name << "\"));\n";
 
1835
    break;
 
1836
  case OptionType::Parameter:
 
1837
    O.indent(IndentLevel) << "vec.push_back(std::make_pair("
 
1838
                          << D.GenVariableName()
 
1839
                          <<".getPosition(), \"" << Name;
 
1840
 
 
1841
    if (!D.isForwardNotSplit()) {
 
1842
      O << "\"));\n";
 
1843
      O.indent(IndentLevel) << "vec.push_back(std::make_pair("
 
1844
                            << D.GenVariableName() << ".getPosition(), "
 
1845
                            << D.GenVariableName() << "));\n";
 
1846
    }
 
1847
    else {
 
1848
      O << "=\" + " << D.GenVariableName() << "));\n";
 
1849
    }
 
1850
    break;
 
1851
  case OptionType::Prefix:
 
1852
    O.indent(IndentLevel) << "vec.push_back(std::make_pair("
 
1853
                          << D.GenVariableName() << ".getPosition(), \""
 
1854
                          << Name << "\" + "
 
1855
                          << D.GenVariableName() << "));\n";
 
1856
    break;
 
1857
  case OptionType::PrefixList:
 
1858
    O.indent(IndentLevel)
 
1859
      << "for (" << D.GenTypeDeclaration()
 
1860
      << "::iterator B = " << D.GenVariableName() << ".begin(),\n";
 
1861
    O.indent(IndentLevel)
 
1862
      << "E = " << D.GenVariableName() << ".end(); B != E;) {\n";
 
1863
    O.indent(IndentLevel1) << "unsigned pos = " << D.GenVariableName()
 
1864
                           << ".getPosition(B - " << D.GenVariableName()
 
1865
                           << ".begin());\n";
 
1866
    O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, \""
 
1867
                           << Name << "\" + " << "*B));\n";
 
1868
    O.indent(IndentLevel1) << "++B;\n";
 
1869
 
 
1870
    for (int i = 1, j = D.MultiVal; i < j; ++i) {
 
1871
      O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, *B));\n";
 
1872
      O.indent(IndentLevel1) << "++B;\n";
 
1873
    }
 
1874
 
 
1875
    O.indent(IndentLevel) << "}\n";
 
1876
    break;
 
1877
  case OptionType::ParameterList:
 
1878
    O.indent(IndentLevel)
 
1879
      << "for (" << D.GenTypeDeclaration() << "::iterator B = "
 
1880
      << D.GenVariableName() << ".begin(),\n";
 
1881
    O.indent(IndentLevel) << "E = " << D.GenVariableName()
 
1882
                          << ".end() ; B != E;) {\n";
 
1883
    O.indent(IndentLevel1) << "unsigned pos = " << D.GenVariableName()
 
1884
                           << ".getPosition(B - " << D.GenVariableName()
 
1885
                           << ".begin());\n";
 
1886
    O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, \""
 
1887
                           << Name << "\"));\n";
 
1888
 
 
1889
    for (int i = 0, j = D.MultiVal; i < j; ++i) {
 
1890
      O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, *B));\n";
 
1891
      O.indent(IndentLevel1) << "++B;\n";
 
1892
    }
 
1893
 
 
1894
    O.indent(IndentLevel) << "}\n";
 
1895
    break;
 
1896
  case OptionType::Alias:
 
1897
  default:
 
1898
    throw "Aliases are not allowed in tool option descriptions!";
 
1899
  }
 
1900
}
 
1901
 
 
1902
/// ActionHandlingCallbackBase - Base class of EmitActionHandlersCallback and
 
1903
/// EmitPreprocessOptionsCallback.
 
1904
struct ActionHandlingCallbackBase
 
1905
{
 
1906
 
 
1907
  void onErrorDag(const DagInit& d,
 
1908
                  unsigned IndentLevel, raw_ostream& O) const
 
1909
  {
 
1910
    O.indent(IndentLevel)
 
1911
      << "throw std::runtime_error(\"" <<
 
1912
      (d.getNumArgs() >= 1 ? InitPtrToString(d.getArg(0))
 
1913
       : "Unknown error!")
 
1914
      << "\");\n";
 
1915
  }
 
1916
 
 
1917
  void onWarningDag(const DagInit& d,
 
1918
                    unsigned IndentLevel, raw_ostream& O) const
 
1919
  {
 
1920
    CheckNumberOfArguments(d, 1);
 
1921
    O.indent(IndentLevel) << "llvm::errs() << \""
 
1922
                          << InitPtrToString(d.getArg(0)) << "\";\n";
 
1923
  }
 
1924
 
 
1925
};
 
1926
 
 
1927
/// EmitActionHandlersCallback - Emit code that handles actions. Used by
 
1928
/// EmitGenerateActionMethod() as an argument to EmitCaseConstructHandler().
 
1929
 
 
1930
class EmitActionHandlersCallback;
 
1931
 
 
1932
typedef void (EmitActionHandlersCallback::* EmitActionHandlersCallbackHandler)
 
1933
(const DagInit&, unsigned, raw_ostream&) const;
 
1934
 
 
1935
class EmitActionHandlersCallback :
 
1936
  public ActionHandlingCallbackBase,
 
1937
  public HandlerTable<EmitActionHandlersCallbackHandler>
 
1938
{
 
1939
  typedef EmitActionHandlersCallbackHandler Handler;
 
1940
 
 
1941
  const OptionDescriptions& OptDescs;
 
1942
 
 
1943
  /// EmitHookInvocation - Common code for hook invocation from actions. Used by
 
1944
  /// onAppendCmd and onOutputSuffix.
 
1945
  void EmitHookInvocation(const std::string& Str,
 
1946
                          const char* BlockOpen, const char* BlockClose,
 
1947
                          unsigned IndentLevel, raw_ostream& O) const
 
1948
  {
 
1949
    StrVector Out;
 
1950
    TokenizeCmdLine(Str, Out);
 
1951
 
 
1952
    for (StrVector::const_iterator B = Out.begin(), E = Out.end();
 
1953
         B != E; ++B) {
 
1954
      const std::string& cmd = *B;
 
1955
 
 
1956
      O.indent(IndentLevel) << BlockOpen;
 
1957
 
 
1958
      if (cmd.at(0) == '$')
 
1959
        B = SubstituteSpecialCommands(B, E,  /* IsJoin = */ true, O);
 
1960
      else
 
1961
        O << '"' << cmd << '"';
 
1962
 
 
1963
      O << BlockClose;
 
1964
    }
 
1965
  }
 
1966
 
 
1967
  void onAppendCmd (const DagInit& Dag,
 
1968
                    unsigned IndentLevel, raw_ostream& O) const
 
1969
  {
 
1970
    CheckNumberOfArguments(Dag, 1);
 
1971
    this->EmitHookInvocation(InitPtrToString(Dag.getArg(0)),
 
1972
                             "vec.push_back(std::make_pair(65536, ", "));\n",
 
1973
                             IndentLevel, O);
 
1974
  }
 
1975
 
 
1976
  void onForward (const DagInit& Dag,
 
1977
                  unsigned IndentLevel, raw_ostream& O) const
 
1978
  {
 
1979
    CheckNumberOfArguments(Dag, 1);
 
1980
    const std::string& Name = InitPtrToString(Dag.getArg(0));
 
1981
    EmitForwardOptionPropertyHandlingCode(OptDescs.FindOption(Name),
 
1982
                                          IndentLevel, "", O);
 
1983
  }
 
1984
 
 
1985
  void onForwardAs (const DagInit& Dag,
 
1986
                    unsigned IndentLevel, raw_ostream& O) const
 
1987
  {
 
1988
    CheckNumberOfArguments(Dag, 2);
 
1989
    const std::string& Name = InitPtrToString(Dag.getArg(0));
 
1990
    const std::string& NewName = InitPtrToString(Dag.getArg(1));
 
1991
    EmitForwardOptionPropertyHandlingCode(OptDescs.FindOption(Name),
 
1992
                                          IndentLevel, NewName, O);
 
1993
  }
 
1994
 
 
1995
  void onForwardValue (const DagInit& Dag,
 
1996
                       unsigned IndentLevel, raw_ostream& O) const
 
1997
  {
 
1998
    CheckNumberOfArguments(Dag, 1);
 
1999
    const std::string& Name = InitPtrToString(Dag.getArg(0));
 
2000
    const OptionDescription& D = OptDescs.FindListOrParameter(Name);
 
2001
 
 
2002
    if (D.isParameter()) {
 
2003
      O.indent(IndentLevel) << "vec.push_back(std::make_pair("
 
2004
                            << D.GenVariableName() << ".getPosition(), "
 
2005
                            << D.GenVariableName() << "));\n";
 
2006
    }
 
2007
    else {
 
2008
      O.indent(IndentLevel) << "for (cl::list<std::string>::iterator B = "
 
2009
                            << D.GenVariableName() << ".begin(), \n";
 
2010
      O.indent(IndentLevel + Indent1) << " E = " << D.GenVariableName()
 
2011
                                      << ".end(); B != E; ++B)\n";
 
2012
      O.indent(IndentLevel) << "{\n";
 
2013
      O.indent(IndentLevel + Indent1)
 
2014
        << "unsigned pos = " << D.GenVariableName()
 
2015
        << ".getPosition(B - " << D.GenVariableName()
 
2016
        << ".begin());\n";
 
2017
      O.indent(IndentLevel + Indent1)
 
2018
        << "vec.push_back(std::make_pair(pos, *B));\n";
 
2019
      O.indent(IndentLevel) << "}\n";
 
2020
    }
 
2021
  }
 
2022
 
 
2023
  void onForwardTransformedValue (const DagInit& Dag,
 
2024
                                  unsigned IndentLevel, raw_ostream& O) const
 
2025
  {
 
2026
    CheckNumberOfArguments(Dag, 2);
 
2027
    const std::string& Name = InitPtrToString(Dag.getArg(0));
 
2028
    const std::string& Hook = InitPtrToString(Dag.getArg(1));
 
2029
    const OptionDescription& D = OptDescs.FindListOrParameter(Name);
 
2030
 
 
2031
    O.indent(IndentLevel) << "vec.push_back(std::make_pair("
 
2032
                          << D.GenVariableName() << ".getPosition("
 
2033
                          << (D.isList() ? "0" : "") << "), "
 
2034
                          << "hooks::" << Hook << "(" << D.GenVariableName()
 
2035
                          << (D.isParameter() ? ".c_str()" : "") << ")));\n";
 
2036
  }
 
2037
 
 
2038
  void onNoOutFile (const DagInit& Dag,
 
2039
                    unsigned IndentLevel, raw_ostream& O) const
 
2040
  {
 
2041
    CheckNumberOfArguments(Dag, 0);
 
2042
    O.indent(IndentLevel) << "no_out_file = true;\n";
 
2043
  }
 
2044
 
 
2045
  void onOutputSuffix (const DagInit& Dag,
 
2046
                       unsigned IndentLevel, raw_ostream& O) const
 
2047
  {
 
2048
    CheckNumberOfArguments(Dag, 1);
 
2049
    this->EmitHookInvocation(InitPtrToString(Dag.getArg(0)),
 
2050
                             "output_suffix = ", ";\n", IndentLevel, O);
 
2051
  }
 
2052
 
 
2053
  void onStopCompilation (const DagInit& Dag,
 
2054
                          unsigned IndentLevel, raw_ostream& O) const
 
2055
  {
 
2056
    O.indent(IndentLevel) << "stop_compilation = true;\n";
 
2057
  }
 
2058
 
 
2059
 
 
2060
  void onUnpackValues (const DagInit& Dag,
 
2061
                       unsigned IndentLevel, raw_ostream& O) const
 
2062
  {
 
2063
    throw "'unpack_values' is deprecated. "
 
2064
      "Use 'comma_separated' + 'forward_value' instead!";
 
2065
  }
 
2066
 
 
2067
 public:
 
2068
 
 
2069
  explicit EmitActionHandlersCallback(const OptionDescriptions& OD)
 
2070
    : OptDescs(OD)
 
2071
  {
 
2072
    if (!staticMembersInitialized_) {
 
2073
      AddHandler("error", &EmitActionHandlersCallback::onErrorDag);
 
2074
      AddHandler("warning", &EmitActionHandlersCallback::onWarningDag);
 
2075
      AddHandler("append_cmd", &EmitActionHandlersCallback::onAppendCmd);
 
2076
      AddHandler("forward", &EmitActionHandlersCallback::onForward);
 
2077
      AddHandler("forward_as", &EmitActionHandlersCallback::onForwardAs);
 
2078
      AddHandler("forward_value", &EmitActionHandlersCallback::onForwardValue);
 
2079
      AddHandler("forward_transformed_value",
 
2080
                 &EmitActionHandlersCallback::onForwardTransformedValue);
 
2081
      AddHandler("no_out_file",
 
2082
                 &EmitActionHandlersCallback::onNoOutFile);
 
2083
      AddHandler("output_suffix", &EmitActionHandlersCallback::onOutputSuffix);
 
2084
      AddHandler("stop_compilation",
 
2085
                 &EmitActionHandlersCallback::onStopCompilation);
 
2086
      AddHandler("unpack_values",
 
2087
                 &EmitActionHandlersCallback::onUnpackValues);
 
2088
 
 
2089
 
 
2090
      staticMembersInitialized_ = true;
 
2091
    }
 
2092
  }
 
2093
 
 
2094
  void operator()(const Init* I,
 
2095
                  unsigned IndentLevel, raw_ostream& O) const
 
2096
  {
 
2097
    InvokeDagInitHandler(this, I, IndentLevel, O);
 
2098
  }
 
2099
};
 
2100
 
 
2101
void EmitGenerateActionMethodHeader(const ToolDescription& D,
 
2102
                                    bool IsJoin, raw_ostream& O)
 
2103
{
 
2104
  if (IsJoin)
 
2105
    O.indent(Indent1) << "Action GenerateAction(const PathVector& inFiles,\n";
 
2106
  else
 
2107
    O.indent(Indent1) << "Action GenerateAction(const sys::Path& inFile,\n";
 
2108
 
 
2109
  O.indent(Indent2) << "bool HasChildren,\n";
 
2110
  O.indent(Indent2) << "const llvm::sys::Path& TempDir,\n";
 
2111
  O.indent(Indent2) << "const InputLanguagesSet& InLangs,\n";
 
2112
  O.indent(Indent2) << "const LanguageMap& LangMap) const\n";
 
2113
  O.indent(Indent1) << "{\n";
 
2114
  O.indent(Indent2) << "std::string cmd;\n";
 
2115
  O.indent(Indent2) << "std::string out_file;\n";
 
2116
  O.indent(Indent2) << "std::vector<std::pair<unsigned, std::string> > vec;\n";
 
2117
  O.indent(Indent2) << "bool stop_compilation = !HasChildren;\n";
 
2118
  O.indent(Indent2) << "bool no_out_file = false;\n";
 
2119
  O.indent(Indent2) << "const char* output_suffix = \""
 
2120
                    << D.OutputSuffix << "\";\n";
 
2121
}
 
2122
 
 
2123
// EmitGenerateActionMethod - Emit either a normal or a "join" version of the
 
2124
// Tool::GenerateAction() method.
 
2125
void EmitGenerateActionMethod (const ToolDescription& D,
 
2126
                               const OptionDescriptions& OptDescs,
 
2127
                               bool IsJoin, raw_ostream& O) {
 
2128
 
 
2129
  EmitGenerateActionMethodHeader(D, IsJoin, O);
 
2130
 
 
2131
  if (!D.CmdLine)
 
2132
    throw "Tool " + D.Name + " has no cmd_line property!";
 
2133
 
 
2134
  // Process the 'command' property.
 
2135
  O << '\n';
 
2136
  EmitCmdLineVecFill(D.CmdLine, D.Name, IsJoin, Indent2, O);
 
2137
  O << '\n';
 
2138
 
 
2139
  // Process the 'actions' list of this tool.
 
2140
  if (D.Actions)
 
2141
    EmitCaseConstructHandler(D.Actions, Indent2,
 
2142
                             EmitActionHandlersCallback(OptDescs),
 
2143
                             false, OptDescs, O);
 
2144
  O << '\n';
 
2145
 
 
2146
  // Input file (s)
 
2147
  if (!D.InFileOption.empty()) {
 
2148
    O.indent(Indent2)
 
2149
      << "vec.push_back(std::make_pair(InputFilenames.getPosition(0), \""
 
2150
      << D.InFileOption << "\");\n";
 
2151
  }
 
2152
 
 
2153
  if (IsJoin) {
 
2154
    O.indent(Indent2)
 
2155
      << "for (PathVector::const_iterator B = inFiles.begin(),\n";
 
2156
    O.indent(Indent3) << "E = inFiles.end(); B != E; ++B)\n";
 
2157
    O.indent(Indent2) << "{\n";
 
2158
    O.indent(Indent3) << "vec.push_back(std::make_pair("
 
2159
                      << "InputFilenames.getPosition(B - inFiles.begin()), "
 
2160
                      << "B->str()));\n";
 
2161
    O.indent(Indent2) << "}\n";
 
2162
  }
 
2163
  else {
 
2164
    O.indent(Indent2) << "vec.push_back(std::make_pair("
 
2165
                      << "InputFilenames.getPosition(0), inFile.str()));\n";
 
2166
  }
 
2167
 
 
2168
  // Output file
 
2169
  O.indent(Indent2) << "if (!no_out_file) {\n";
 
2170
  if (!D.OutFileOption.empty())
 
2171
    O.indent(Indent3) << "vec.push_back(std::make_pair(65536, \""
 
2172
                      << D.OutFileOption << "\"));\n";
 
2173
 
 
2174
  O.indent(Indent3) << "out_file = this->OutFilename("
 
2175
                    << (IsJoin ? "sys::Path(),\n" : "inFile,\n");
 
2176
  O.indent(Indent4) << "TempDir, stop_compilation, output_suffix).str();\n\n";
 
2177
  O.indent(Indent3) << "vec.push_back(std::make_pair(65536, out_file));\n";
 
2178
 
 
2179
  O.indent(Indent2) << "}\n\n";
 
2180
 
 
2181
  // Handle the Sink property.
 
2182
  if (D.isSink()) {
 
2183
    O.indent(Indent2) << "if (!" << SinkOptionName << ".empty()) {\n";
 
2184
    O.indent(Indent3) << "for (cl::list<std::string>::iterator B = "
 
2185
                      << SinkOptionName << ".begin(), E = " << SinkOptionName
 
2186
                      << ".end(); B != E; ++B)\n";
 
2187
    O.indent(Indent4) << "vec.push_back(std::make_pair(" << SinkOptionName
 
2188
                      << ".getPosition(B - " << SinkOptionName
 
2189
                      <<  ".begin()), *B));\n";
 
2190
    O.indent(Indent2) << "}\n";
 
2191
  }
 
2192
 
 
2193
  O.indent(Indent2) << "return Action(cmd, this->SortArgs(vec), "
 
2194
                    << "stop_compilation, out_file);\n";
 
2195
  O.indent(Indent1) << "}\n\n";
 
2196
}
 
2197
 
 
2198
/// EmitGenerateActionMethods - Emit two GenerateAction() methods for
 
2199
/// a given Tool class.
 
2200
void EmitGenerateActionMethods (const ToolDescription& ToolDesc,
 
2201
                                const OptionDescriptions& OptDescs,
 
2202
                                raw_ostream& O) {
 
2203
  if (!ToolDesc.isJoin()) {
 
2204
    O.indent(Indent1) << "Action GenerateAction(const PathVector& inFiles,\n";
 
2205
    O.indent(Indent2) << "bool HasChildren,\n";
 
2206
    O.indent(Indent2) << "const llvm::sys::Path& TempDir,\n";
 
2207
    O.indent(Indent2) << "const InputLanguagesSet& InLangs,\n";
 
2208
    O.indent(Indent2) << "const LanguageMap& LangMap) const\n";
 
2209
    O.indent(Indent1) << "{\n";
 
2210
    O.indent(Indent2) << "throw std::runtime_error(\"" << ToolDesc.Name
 
2211
                      << " is not a Join tool!\");\n";
 
2212
    O.indent(Indent1) << "}\n\n";
 
2213
  }
 
2214
  else {
 
2215
    EmitGenerateActionMethod(ToolDesc, OptDescs, true, O);
 
2216
  }
 
2217
 
 
2218
  EmitGenerateActionMethod(ToolDesc, OptDescs, false, O);
 
2219
}
 
2220
 
 
2221
/// EmitInOutLanguageMethods - Emit the [Input,Output]Language()
 
2222
/// methods for a given Tool class.
 
2223
void EmitInOutLanguageMethods (const ToolDescription& D, raw_ostream& O) {
 
2224
  O.indent(Indent1) << "const char** InputLanguages() const {\n";
 
2225
  O.indent(Indent2) << "return InputLanguages_;\n";
 
2226
  O.indent(Indent1) << "}\n\n";
 
2227
 
 
2228
  if (D.OutLanguage.empty())
 
2229
    throw "Tool " + D.Name + " has no 'out_language' property!";
 
2230
 
 
2231
  O.indent(Indent1) << "const char* OutputLanguage() const {\n";
 
2232
  O.indent(Indent2) << "return \"" << D.OutLanguage << "\";\n";
 
2233
  O.indent(Indent1) << "}\n\n";
 
2234
}
 
2235
 
 
2236
/// EmitNameMethod - Emit the Name() method for a given Tool class.
 
2237
void EmitNameMethod (const ToolDescription& D, raw_ostream& O) {
 
2238
  O.indent(Indent1) << "const char* Name() const {\n";
 
2239
  O.indent(Indent2) << "return \"" << D.Name << "\";\n";
 
2240
  O.indent(Indent1) << "}\n\n";
 
2241
}
 
2242
 
 
2243
/// EmitIsJoinMethod - Emit the IsJoin() method for a given Tool
 
2244
/// class.
 
2245
void EmitIsJoinMethod (const ToolDescription& D, raw_ostream& O) {
 
2246
  O.indent(Indent1) << "bool IsJoin() const {\n";
 
2247
  if (D.isJoin())
 
2248
    O.indent(Indent2) << "return true;\n";
 
2249
  else
 
2250
    O.indent(Indent2) << "return false;\n";
 
2251
  O.indent(Indent1) << "}\n\n";
 
2252
}
 
2253
 
 
2254
/// EmitWorksOnEmptyCallback - Callback used by EmitWorksOnEmptyMethod in
 
2255
/// conjunction with EmitCaseConstructHandler.
 
2256
void EmitWorksOnEmptyCallback (const Init* Value,
 
2257
                               unsigned IndentLevel, raw_ostream& O) {
 
2258
  CheckBooleanConstant(Value);
 
2259
  O.indent(IndentLevel) << "return " << Value->getAsString() << ";\n";
 
2260
}
 
2261
 
 
2262
/// EmitWorksOnEmptyMethod - Emit the WorksOnEmpty() method for a given Tool
 
2263
/// class.
 
2264
void EmitWorksOnEmptyMethod (const ToolDescription& D,
 
2265
                             const OptionDescriptions& OptDescs,
 
2266
                             raw_ostream& O)
 
2267
{
 
2268
  O.indent(Indent1) << "bool WorksOnEmpty() const {\n";
 
2269
  if (D.OnEmpty == 0)
 
2270
    O.indent(Indent2) << "return false;\n";
 
2271
  else
 
2272
    EmitCaseConstructHandler(D.OnEmpty, Indent2, EmitWorksOnEmptyCallback,
 
2273
                             /*EmitElseIf = */ true, OptDescs, O);
 
2274
  O.indent(Indent1) << "}\n\n";
 
2275
}
 
2276
 
 
2277
/// EmitStaticMemberDefinitions - Emit static member definitions for a
 
2278
/// given Tool class.
 
2279
void EmitStaticMemberDefinitions(const ToolDescription& D, raw_ostream& O) {
 
2280
  if (D.InLanguage.empty())
 
2281
    throw "Tool " + D.Name + " has no 'in_language' property!";
 
2282
 
 
2283
  O << "const char* " << D.Name << "::InputLanguages_[] = {";
 
2284
  for (StrVector::const_iterator B = D.InLanguage.begin(),
 
2285
         E = D.InLanguage.end(); B != E; ++B)
 
2286
    O << '\"' << *B << "\", ";
 
2287
  O << "0};\n\n";
 
2288
}
 
2289
 
 
2290
/// EmitToolClassDefinition - Emit a Tool class definition.
 
2291
void EmitToolClassDefinition (const ToolDescription& D,
 
2292
                              const OptionDescriptions& OptDescs,
 
2293
                              raw_ostream& O) {
 
2294
  if (D.Name == "root")
 
2295
    return;
 
2296
 
 
2297
  // Header
 
2298
  O << "class " << D.Name << " : public ";
 
2299
  if (D.isJoin())
 
2300
    O << "JoinTool";
 
2301
  else
 
2302
    O << "Tool";
 
2303
 
 
2304
  O << " {\nprivate:\n";
 
2305
  O.indent(Indent1) << "static const char* InputLanguages_[];\n\n";
 
2306
 
 
2307
  O << "public:\n";
 
2308
  EmitNameMethod(D, O);
 
2309
  EmitInOutLanguageMethods(D, O);
 
2310
  EmitIsJoinMethod(D, O);
 
2311
  EmitWorksOnEmptyMethod(D, OptDescs, O);
 
2312
  EmitGenerateActionMethods(D, OptDescs, O);
 
2313
 
 
2314
  // Close class definition
 
2315
  O << "};\n";
 
2316
 
 
2317
  EmitStaticMemberDefinitions(D, O);
 
2318
 
 
2319
}
 
2320
 
 
2321
/// EmitOptionDefinitions - Iterate over a list of option descriptions
 
2322
/// and emit registration code.
 
2323
void EmitOptionDefinitions (const OptionDescriptions& descs,
 
2324
                            bool HasSink, bool HasExterns,
 
2325
                            raw_ostream& O)
 
2326
{
 
2327
  std::vector<OptionDescription> Aliases;
 
2328
 
 
2329
  // Emit static cl::Option variables.
 
2330
  for (OptionDescriptions::const_iterator B = descs.begin(),
 
2331
         E = descs.end(); B!=E; ++B) {
 
2332
    const OptionDescription& val = B->second;
 
2333
 
 
2334
    if (val.Type == OptionType::Alias) {
 
2335
      Aliases.push_back(val);
 
2336
      continue;
 
2337
    }
 
2338
 
 
2339
    if (val.isExtern())
 
2340
      O << "extern ";
 
2341
 
 
2342
    O << val.GenTypeDeclaration() << ' '
 
2343
      << val.GenVariableName();
 
2344
 
 
2345
    if (val.isExtern()) {
 
2346
      O << ";\n";
 
2347
      continue;
 
2348
    }
 
2349
 
 
2350
    O << "(\"" << val.Name << "\"\n";
 
2351
 
 
2352
    if (val.Type == OptionType::Prefix || val.Type == OptionType::PrefixList)
 
2353
      O << ", cl::Prefix";
 
2354
 
 
2355
    if (val.isRequired()) {
 
2356
      if (val.isList() && !val.isMultiVal())
 
2357
        O << ", cl::OneOrMore";
 
2358
      else
 
2359
        O << ", cl::Required";
 
2360
    }
 
2361
 
 
2362
    if (val.isOptional())
 
2363
        O << ", cl::Optional";
 
2364
 
 
2365
    if (val.isOneOrMore())
 
2366
        O << ", cl::OneOrMore";
 
2367
 
 
2368
    if (val.isZeroOrMore())
 
2369
        O << ", cl::ZeroOrMore";
 
2370
 
 
2371
    if (val.isReallyHidden())
 
2372
      O << ", cl::ReallyHidden";
 
2373
    else if (val.isHidden())
 
2374
      O << ", cl::Hidden";
 
2375
 
 
2376
    if (val.isCommaSeparated())
 
2377
      O << ", cl::CommaSeparated";
 
2378
 
 
2379
    if (val.MultiVal > 1)
 
2380
      O << ", cl::multi_val(" << val.MultiVal << ')';
 
2381
 
 
2382
    if (val.InitVal) {
 
2383
      const std::string& str = val.InitVal->getAsString();
 
2384
      O << ", cl::init(" << str << ')';
 
2385
    }
 
2386
 
 
2387
    if (!val.Help.empty())
 
2388
      O << ", cl::desc(\"" << val.Help << "\")";
 
2389
 
 
2390
    O << ");\n\n";
 
2391
  }
 
2392
 
 
2393
  // Emit the aliases (they should go after all the 'proper' options).
 
2394
  for (std::vector<OptionDescription>::const_iterator
 
2395
         B = Aliases.begin(), E = Aliases.end(); B != E; ++B) {
 
2396
    const OptionDescription& val = *B;
 
2397
 
 
2398
    O << val.GenTypeDeclaration() << ' '
 
2399
      << val.GenVariableName()
 
2400
      << "(\"" << val.Name << '\"';
 
2401
 
 
2402
    const OptionDescription& D = descs.FindOption(val.Help);
 
2403
    O << ", cl::aliasopt(" << D.GenVariableName() << ")";
 
2404
 
 
2405
    O << ", cl::desc(\"" << "An alias for -" + val.Help  << "\"));\n";
 
2406
  }
 
2407
 
 
2408
  // Emit the sink option.
 
2409
  if (HasSink)
 
2410
    O << (HasExterns ? "extern cl" : "cl")
 
2411
      << "::list<std::string> " << SinkOptionName
 
2412
      << (HasExterns ? ";\n" : "(cl::Sink);\n");
 
2413
 
 
2414
  O << '\n';
 
2415
}
 
2416
 
 
2417
/// EmitPreprocessOptionsCallback - Helper function passed to
 
2418
/// EmitCaseConstructHandler() by EmitPreprocessOptions().
 
2419
 
 
2420
class EmitPreprocessOptionsCallback;
 
2421
 
 
2422
typedef void
 
2423
(EmitPreprocessOptionsCallback::* EmitPreprocessOptionsCallbackHandler)
 
2424
(const DagInit&, unsigned, raw_ostream&) const;
 
2425
 
 
2426
class EmitPreprocessOptionsCallback :
 
2427
  public ActionHandlingCallbackBase,
 
2428
  public HandlerTable<EmitPreprocessOptionsCallbackHandler>
 
2429
{
 
2430
  typedef EmitPreprocessOptionsCallbackHandler Handler;
 
2431
  typedef void
 
2432
  (EmitPreprocessOptionsCallback::* HandlerImpl)
 
2433
  (const Init*, unsigned, raw_ostream&) const;
 
2434
 
 
2435
  const OptionDescriptions& OptDescs_;
 
2436
 
 
2437
  void onListOrDag(const DagInit& d, HandlerImpl h,
 
2438
                   unsigned IndentLevel, raw_ostream& O) const
 
2439
  {
 
2440
    CheckNumberOfArguments(d, 1);
 
2441
    const Init* I = d.getArg(0);
 
2442
 
 
2443
    // If I is a list, apply h to each element.
 
2444
    if (typeid(*I) == typeid(ListInit)) {
 
2445
      const ListInit& L = *static_cast<const ListInit*>(I);
 
2446
      for (ListInit::const_iterator B = L.begin(), E = L.end(); B != E; ++B)
 
2447
        ((this)->*(h))(*B, IndentLevel, O);
 
2448
    }
 
2449
    // Otherwise, apply h to I.
 
2450
    else {
 
2451
      ((this)->*(h))(I, IndentLevel, O);
 
2452
    }
 
2453
  }
 
2454
 
 
2455
  void onUnsetOptionImpl(const Init* I,
 
2456
                         unsigned IndentLevel, raw_ostream& O) const
 
2457
  {
 
2458
    const std::string& OptName = InitPtrToString(I);
 
2459
    const OptionDescription& OptDesc = OptDescs_.FindOption(OptName);
 
2460
 
 
2461
    if (OptDesc.isSwitch()) {
 
2462
      O.indent(IndentLevel) << OptDesc.GenVariableName() << " = false;\n";
 
2463
    }
 
2464
    else if (OptDesc.isParameter()) {
 
2465
      O.indent(IndentLevel) << OptDesc.GenVariableName() << " = \"\";\n";
 
2466
    }
 
2467
    else if (OptDesc.isList()) {
 
2468
      O.indent(IndentLevel) << OptDesc.GenVariableName() << ".clear();\n";
 
2469
    }
 
2470
    else {
 
2471
      throw "Can't apply 'unset_option' to alias option '" + OptName + "'!";
 
2472
    }
 
2473
  }
 
2474
 
 
2475
  void onUnsetOption(const DagInit& d,
 
2476
                     unsigned IndentLevel, raw_ostream& O) const
 
2477
  {
 
2478
    this->onListOrDag(d, &EmitPreprocessOptionsCallback::onUnsetOptionImpl,
 
2479
                      IndentLevel, O);
 
2480
  }
 
2481
 
 
2482
  void onSetOptionImpl(const DagInit& d,
 
2483
                       unsigned IndentLevel, raw_ostream& O) const {
 
2484
    CheckNumberOfArguments(d, 2);
 
2485
    const std::string& OptName = InitPtrToString(d.getArg(0));
 
2486
    const Init* Value = d.getArg(1);
 
2487
    const OptionDescription& OptDesc = OptDescs_.FindOption(OptName);
 
2488
 
 
2489
    if (OptDesc.isList()) {
 
2490
      const ListInit& List = InitPtrToList(Value);
 
2491
 
 
2492
      O.indent(IndentLevel) << OptDesc.GenVariableName() << ".clear();\n";
 
2493
      for (ListInit::const_iterator B = List.begin(), E = List.end();
 
2494
           B != E; ++B) {
 
2495
        O.indent(IndentLevel) << OptDesc.GenVariableName() << ".push_back(\""
 
2496
                              << InitPtrToString(*B) << "\");\n";
 
2497
      }
 
2498
    }
 
2499
    else if (OptDesc.isSwitch()) {
 
2500
      CheckBooleanConstant(Value);
 
2501
      O.indent(IndentLevel) << OptDesc.GenVariableName()
 
2502
                            << " = " << Value->getAsString() << ";\n";
 
2503
    }
 
2504
    else if (OptDesc.isParameter()) {
 
2505
      const std::string& Str = InitPtrToString(Value);
 
2506
      O.indent(IndentLevel) << OptDesc.GenVariableName()
 
2507
                            << " = \"" << Str << "\";\n";
 
2508
    }
 
2509
    else {
 
2510
      throw "Can't apply 'set_option' to alias option -" + OptName + " !";
 
2511
    }
 
2512
  }
 
2513
 
 
2514
  void onSetSwitch(const Init* I,
 
2515
                   unsigned IndentLevel, raw_ostream& O) const {
 
2516
    const std::string& OptName = InitPtrToString(I);
 
2517
    const OptionDescription& OptDesc = OptDescs_.FindOption(OptName);
 
2518
 
 
2519
    if (OptDesc.isSwitch())
 
2520
      O.indent(IndentLevel) << OptDesc.GenVariableName() << " = true;\n";
 
2521
    else
 
2522
      throw "set_option: -" + OptName + " is not a switch option!";
 
2523
  }
 
2524
 
 
2525
  void onSetOption(const DagInit& d,
 
2526
                   unsigned IndentLevel, raw_ostream& O) const
 
2527
  {
 
2528
    CheckNumberOfArguments(d, 1);
 
2529
 
 
2530
    // Two arguments: (set_option "parameter", VALUE), where VALUE can be a
 
2531
    // boolean, a string or a string list.
 
2532
    if (d.getNumArgs() > 1)
 
2533
      this->onSetOptionImpl(d, IndentLevel, O);
 
2534
    // One argument: (set_option "switch")
 
2535
    // or (set_option ["switch1", "switch2", ...])
 
2536
    else
 
2537
      this->onListOrDag(d, &EmitPreprocessOptionsCallback::onSetSwitch,
 
2538
                        IndentLevel, O);
 
2539
  }
 
2540
 
 
2541
public:
 
2542
 
 
2543
  EmitPreprocessOptionsCallback(const OptionDescriptions& OptDescs)
 
2544
  : OptDescs_(OptDescs)
 
2545
  {
 
2546
    if (!staticMembersInitialized_) {
 
2547
      AddHandler("error", &EmitPreprocessOptionsCallback::onErrorDag);
 
2548
      AddHandler("warning", &EmitPreprocessOptionsCallback::onWarningDag);
 
2549
      AddHandler("unset_option", &EmitPreprocessOptionsCallback::onUnsetOption);
 
2550
      AddHandler("set_option", &EmitPreprocessOptionsCallback::onSetOption);
 
2551
 
 
2552
      staticMembersInitialized_ = true;
 
2553
    }
 
2554
  }
 
2555
 
 
2556
  void operator()(const Init* I,
 
2557
                  unsigned IndentLevel, raw_ostream& O) const
 
2558
  {
 
2559
    InvokeDagInitHandler(this, I, IndentLevel, O);
 
2560
  }
 
2561
 
 
2562
};
 
2563
 
 
2564
/// EmitPreprocessOptions - Emit the PreprocessOptionsLocal() function.
 
2565
void EmitPreprocessOptions (const RecordKeeper& Records,
 
2566
                            const OptionDescriptions& OptDecs, raw_ostream& O)
 
2567
{
 
2568
  O << "void PreprocessOptionsLocal() {\n";
 
2569
 
 
2570
  const RecordVector& OptionPreprocessors =
 
2571
    Records.getAllDerivedDefinitions("OptionPreprocessor");
 
2572
 
 
2573
  for (RecordVector::const_iterator B = OptionPreprocessors.begin(),
 
2574
         E = OptionPreprocessors.end(); B!=E; ++B) {
 
2575
    DagInit* Case = (*B)->getValueAsDag("preprocessor");
 
2576
    EmitCaseConstructHandler(Case, Indent1,
 
2577
                             EmitPreprocessOptionsCallback(OptDecs),
 
2578
                             false, OptDecs, O);
 
2579
  }
 
2580
 
 
2581
  O << "}\n\n";
 
2582
}
 
2583
 
 
2584
/// EmitPopulateLanguageMap - Emit the PopulateLanguageMapLocal() function.
 
2585
void EmitPopulateLanguageMap (const RecordKeeper& Records, raw_ostream& O)
 
2586
{
 
2587
  O << "void PopulateLanguageMapLocal(LanguageMap& langMap) {\n";
 
2588
 
 
2589
  // Get the relevant field out of RecordKeeper
 
2590
  const Record* LangMapRecord = Records.getDef("LanguageMap");
 
2591
 
 
2592
  // It is allowed for a plugin to have no language map.
 
2593
  if (LangMapRecord) {
 
2594
 
 
2595
    ListInit* LangsToSuffixesList = LangMapRecord->getValueAsListInit("map");
 
2596
    if (!LangsToSuffixesList)
 
2597
      throw "Error in the language map definition!";
 
2598
 
 
2599
    for (unsigned i = 0; i < LangsToSuffixesList->size(); ++i) {
 
2600
      const Record* LangToSuffixes = LangsToSuffixesList->getElementAsRecord(i);
 
2601
 
 
2602
      const std::string& Lang = LangToSuffixes->getValueAsString("lang");
 
2603
      const ListInit* Suffixes = LangToSuffixes->getValueAsListInit("suffixes");
 
2604
 
 
2605
      for (unsigned i = 0; i < Suffixes->size(); ++i)
 
2606
        O.indent(Indent1) << "langMap[\""
 
2607
                          << InitPtrToString(Suffixes->getElement(i))
 
2608
                          << "\"] = \"" << Lang << "\";\n";
 
2609
    }
 
2610
  }
 
2611
 
 
2612
  O << "}\n\n";
 
2613
}
 
2614
 
 
2615
/// IncDecWeight - Helper function passed to EmitCaseConstructHandler()
 
2616
/// by EmitEdgeClass().
 
2617
void IncDecWeight (const Init* i, unsigned IndentLevel,
 
2618
                   raw_ostream& O) {
 
2619
  const DagInit& d = InitPtrToDag(i);
 
2620
  const std::string& OpName = GetOperatorName(d);
 
2621
 
 
2622
  if (OpName == "inc_weight") {
 
2623
    O.indent(IndentLevel) << "ret += ";
 
2624
  }
 
2625
  else if (OpName == "dec_weight") {
 
2626
    O.indent(IndentLevel) << "ret -= ";
 
2627
  }
 
2628
  else if (OpName == "error") {
 
2629
    CheckNumberOfArguments(d, 1);
 
2630
    O.indent(IndentLevel) << "throw std::runtime_error(\""
 
2631
                          << InitPtrToString(d.getArg(0))
 
2632
                          << "\");\n";
 
2633
    return;
 
2634
  }
 
2635
  else {
 
2636
    throw "Unknown operator in edge properties list: '" + OpName + "'!"
 
2637
      "\nOnly 'inc_weight', 'dec_weight' and 'error' are allowed.";
 
2638
  }
 
2639
 
 
2640
  if (d.getNumArgs() > 0)
 
2641
    O << InitPtrToInt(d.getArg(0)) << ";\n";
 
2642
  else
 
2643
    O << "2;\n";
 
2644
 
 
2645
}
 
2646
 
 
2647
/// EmitEdgeClass - Emit a single Edge# class.
 
2648
void EmitEdgeClass (unsigned N, const std::string& Target,
 
2649
                    DagInit* Case, const OptionDescriptions& OptDescs,
 
2650
                    raw_ostream& O) {
 
2651
 
 
2652
  // Class constructor.
 
2653
  O << "class Edge" << N << ": public Edge {\n"
 
2654
    << "public:\n";
 
2655
  O.indent(Indent1) << "Edge" << N << "() : Edge(\"" << Target
 
2656
                    << "\") {}\n\n";
 
2657
 
 
2658
  // Function Weight().
 
2659
  O.indent(Indent1)
 
2660
    << "unsigned Weight(const InputLanguagesSet& InLangs) const {\n";
 
2661
  O.indent(Indent2) << "unsigned ret = 0;\n";
 
2662
 
 
2663
  // Handle the 'case' construct.
 
2664
  EmitCaseConstructHandler(Case, Indent2, IncDecWeight, false, OptDescs, O);
 
2665
 
 
2666
  O.indent(Indent2) << "return ret;\n";
 
2667
  O.indent(Indent1) << "}\n\n};\n\n";
 
2668
}
 
2669
 
 
2670
/// EmitEdgeClasses - Emit Edge* classes that represent graph edges.
 
2671
void EmitEdgeClasses (const RecordVector& EdgeVector,
 
2672
                      const OptionDescriptions& OptDescs,
 
2673
                      raw_ostream& O) {
 
2674
  int i = 0;
 
2675
  for (RecordVector::const_iterator B = EdgeVector.begin(),
 
2676
         E = EdgeVector.end(); B != E; ++B) {
 
2677
    const Record* Edge = *B;
 
2678
    const std::string& NodeB = Edge->getValueAsString("b");
 
2679
    DagInit& Weight = *Edge->getValueAsDag("weight");
 
2680
 
 
2681
    if (!IsDagEmpty(Weight))
 
2682
      EmitEdgeClass(i, NodeB, &Weight, OptDescs, O);
 
2683
    ++i;
 
2684
  }
 
2685
}
 
2686
 
 
2687
/// EmitPopulateCompilationGraph - Emit the PopulateCompilationGraphLocal()
 
2688
/// function.
 
2689
void EmitPopulateCompilationGraph (const RecordVector& EdgeVector,
 
2690
                                   const ToolDescriptions& ToolDescs,
 
2691
                                   raw_ostream& O)
 
2692
{
 
2693
  O << "void PopulateCompilationGraphLocal(CompilationGraph& G) {\n";
 
2694
 
 
2695
  for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
 
2696
         E = ToolDescs.end(); B != E; ++B)
 
2697
    O.indent(Indent1) << "G.insertNode(new " << (*B)->Name << "());\n";
 
2698
 
 
2699
  O << '\n';
 
2700
 
 
2701
  // Insert edges.
 
2702
 
 
2703
  int i = 0;
 
2704
  for (RecordVector::const_iterator B = EdgeVector.begin(),
 
2705
         E = EdgeVector.end(); B != E; ++B) {
 
2706
    const Record* Edge = *B;
 
2707
    const std::string& NodeA = Edge->getValueAsString("a");
 
2708
    const std::string& NodeB = Edge->getValueAsString("b");
 
2709
    DagInit& Weight = *Edge->getValueAsDag("weight");
 
2710
 
 
2711
    O.indent(Indent1) << "G.insertEdge(\"" << NodeA << "\", ";
 
2712
 
 
2713
    if (IsDagEmpty(Weight))
 
2714
      O << "new SimpleEdge(\"" << NodeB << "\")";
 
2715
    else
 
2716
      O << "new Edge" << i << "()";
 
2717
 
 
2718
    O << ");\n";
 
2719
    ++i;
 
2720
  }
 
2721
 
 
2722
  O << "}\n\n";
 
2723
}
 
2724
 
 
2725
/// HookInfo - Information about the hook type and number of arguments.
 
2726
struct HookInfo {
 
2727
 
 
2728
  // A hook can either have a single parameter of type std::vector<std::string>,
 
2729
  // or NumArgs parameters of type const char*.
 
2730
  enum HookType { ListHook, ArgHook };
 
2731
 
 
2732
  HookType Type;
 
2733
  unsigned NumArgs;
 
2734
 
 
2735
  HookInfo() : Type(ArgHook), NumArgs(1)
 
2736
  {}
 
2737
 
 
2738
  HookInfo(HookType T) : Type(T), NumArgs(1)
 
2739
  {}
 
2740
 
 
2741
  HookInfo(unsigned N) : Type(ArgHook), NumArgs(N)
 
2742
  {}
 
2743
};
 
2744
 
 
2745
typedef llvm::StringMap<HookInfo> HookInfoMap;
 
2746
 
 
2747
/// ExtractHookNames - Extract the hook names from all instances of
 
2748
/// $CALL(HookName) in the provided command line string/action. Helper
 
2749
/// function used by FillInHookNames().
 
2750
class ExtractHookNames {
 
2751
  HookInfoMap& HookNames_;
 
2752
  const OptionDescriptions& OptDescs_;
 
2753
public:
 
2754
  ExtractHookNames(HookInfoMap& HookNames, const OptionDescriptions& OptDescs)
 
2755
    : HookNames_(HookNames), OptDescs_(OptDescs)
 
2756
  {}
 
2757
 
 
2758
  void onAction (const DagInit& Dag) {
 
2759
    const std::string& Name = GetOperatorName(Dag);
 
2760
 
 
2761
    if (Name == "forward_transformed_value") {
 
2762
      CheckNumberOfArguments(Dag, 2);
 
2763
      const std::string& OptName = InitPtrToString(Dag.getArg(0));
 
2764
      const std::string& HookName = InitPtrToString(Dag.getArg(1));
 
2765
      const OptionDescription& D = OptDescs_.FindOption(OptName);
 
2766
 
 
2767
      HookNames_[HookName] = HookInfo(D.isList() ? HookInfo::ListHook
 
2768
                                      : HookInfo::ArgHook);
 
2769
    }
 
2770
    else if (Name == "append_cmd" || Name == "output_suffix") {
 
2771
      CheckNumberOfArguments(Dag, 1);
 
2772
      this->onCmdLine(InitPtrToString(Dag.getArg(0)));
 
2773
    }
 
2774
  }
 
2775
 
 
2776
  void onCmdLine(const std::string& Cmd) {
 
2777
    StrVector cmds;
 
2778
    TokenizeCmdLine(Cmd, cmds);
 
2779
 
 
2780
    for (StrVector::const_iterator B = cmds.begin(), E = cmds.end();
 
2781
         B != E; ++B) {
 
2782
      const std::string& cmd = *B;
 
2783
 
 
2784
      if (cmd == "$CALL") {
 
2785
        unsigned NumArgs = 0;
 
2786
        CheckedIncrement(B, E, "Syntax error in $CALL invocation!");
 
2787
        const std::string& HookName = *B;
 
2788
 
 
2789
        if (HookName.at(0) == ')')
 
2790
          throw "$CALL invoked with no arguments!";
 
2791
 
 
2792
        while (++B != E && B->at(0) != ')') {
 
2793
          ++NumArgs;
 
2794
        }
 
2795
 
 
2796
        HookInfoMap::const_iterator H = HookNames_.find(HookName);
 
2797
 
 
2798
        if (H != HookNames_.end() && H->second.NumArgs != NumArgs &&
 
2799
            H->second.Type != HookInfo::ArgHook)
 
2800
          throw "Overloading of hooks is not allowed. Overloaded hook: "
 
2801
            + HookName;
 
2802
        else
 
2803
          HookNames_[HookName] = HookInfo(NumArgs);
 
2804
      }
 
2805
    }
 
2806
  }
 
2807
 
 
2808
  void operator()(const Init* Arg) {
 
2809
 
 
2810
    // We're invoked on an action (either a dag or a dag list).
 
2811
    if (typeid(*Arg) == typeid(DagInit)) {
 
2812
      const DagInit& Dag = InitPtrToDag(Arg);
 
2813
      this->onAction(Dag);
 
2814
      return;
 
2815
    }
 
2816
    else if (typeid(*Arg) == typeid(ListInit)) {
 
2817
      const ListInit& List = InitPtrToList(Arg);
 
2818
      for (ListInit::const_iterator B = List.begin(), E = List.end(); B != E;
 
2819
           ++B) {
 
2820
        const DagInit& Dag = InitPtrToDag(*B);
 
2821
        this->onAction(Dag);
 
2822
      }
 
2823
      return;
 
2824
    }
 
2825
 
 
2826
    // We're invoked on a command line.
 
2827
    this->onCmdLine(InitPtrToString(Arg));
 
2828
  }
 
2829
 
 
2830
  void operator()(const DagInit* Test, unsigned, bool) {
 
2831
    this->operator()(Test);
 
2832
  }
 
2833
  void operator()(const Init* Statement, unsigned) {
 
2834
    this->operator()(Statement);
 
2835
  }
 
2836
};
 
2837
 
 
2838
/// FillInHookNames - Actually extract the hook names from all command
 
2839
/// line strings. Helper function used by EmitHookDeclarations().
 
2840
void FillInHookNames(const ToolDescriptions& ToolDescs,
 
2841
                     const OptionDescriptions& OptDescs,
 
2842
                     HookInfoMap& HookNames)
 
2843
{
 
2844
  // For all tool descriptions:
 
2845
  for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
 
2846
         E = ToolDescs.end(); B != E; ++B) {
 
2847
    const ToolDescription& D = *(*B);
 
2848
 
 
2849
    // Look for 'forward_transformed_value' in 'actions'.
 
2850
    if (D.Actions)
 
2851
      WalkCase(D.Actions, Id(), ExtractHookNames(HookNames, OptDescs));
 
2852
 
 
2853
    // Look for hook invocations in 'cmd_line'.
 
2854
    if (!D.CmdLine)
 
2855
      continue;
 
2856
    if (dynamic_cast<StringInit*>(D.CmdLine))
 
2857
      // This is a string.
 
2858
      ExtractHookNames(HookNames, OptDescs).operator()(D.CmdLine);
 
2859
    else
 
2860
      // This is a 'case' construct.
 
2861
      WalkCase(D.CmdLine, Id(), ExtractHookNames(HookNames, OptDescs));
 
2862
  }
 
2863
}
 
2864
 
 
2865
/// EmitHookDeclarations - Parse CmdLine fields of all the tool
 
2866
/// property records and emit hook function declaration for each
 
2867
/// instance of $CALL(HookName).
 
2868
void EmitHookDeclarations(const ToolDescriptions& ToolDescs,
 
2869
                          const OptionDescriptions& OptDescs, raw_ostream& O) {
 
2870
  HookInfoMap HookNames;
 
2871
 
 
2872
  FillInHookNames(ToolDescs, OptDescs, HookNames);
 
2873
  if (HookNames.empty())
 
2874
    return;
 
2875
 
 
2876
  O << "namespace hooks {\n";
 
2877
  for (HookInfoMap::const_iterator B = HookNames.begin(),
 
2878
         E = HookNames.end(); B != E; ++B) {
 
2879
    const char* HookName = B->first();
 
2880
    const HookInfo& Info = B->second;
 
2881
 
 
2882
    O.indent(Indent1) << "std::string " << HookName << "(";
 
2883
 
 
2884
    if (Info.Type == HookInfo::ArgHook) {
 
2885
      for (unsigned i = 0, j = Info.NumArgs; i < j; ++i) {
 
2886
        O << "const char* Arg" << i << (i+1 == j ? "" : ", ");
 
2887
      }
 
2888
    }
 
2889
    else {
 
2890
      O << "const std::vector<std::string>& Arg";
 
2891
    }
 
2892
 
 
2893
    O <<");\n";
 
2894
  }
 
2895
  O << "}\n\n";
 
2896
}
 
2897
 
 
2898
/// EmitRegisterPlugin - Emit code to register this plugin.
 
2899
void EmitRegisterPlugin(int Priority, raw_ostream& O) {
 
2900
  O << "struct Plugin : public llvmc::BasePlugin {\n\n";
 
2901
  O.indent(Indent1) << "int Priority() const { return "
 
2902
                    << Priority << "; }\n\n";
 
2903
  O.indent(Indent1) << "void PreprocessOptions() const\n";
 
2904
  O.indent(Indent1) << "{ PreprocessOptionsLocal(); }\n\n";
 
2905
  O.indent(Indent1) << "void PopulateLanguageMap(LanguageMap& langMap) const\n";
 
2906
  O.indent(Indent1) << "{ PopulateLanguageMapLocal(langMap); }\n\n";
 
2907
  O.indent(Indent1)
 
2908
    << "void PopulateCompilationGraph(CompilationGraph& graph) const\n";
 
2909
  O.indent(Indent1) << "{ PopulateCompilationGraphLocal(graph); }\n"
 
2910
                    << "};\n\n"
 
2911
                    << "static llvmc::RegisterPlugin<Plugin> RP;\n\n";
 
2912
}
 
2913
 
 
2914
/// EmitIncludes - Emit necessary #include directives and some
 
2915
/// additional declarations.
 
2916
void EmitIncludes(raw_ostream& O) {
 
2917
  O << "#include \"llvm/CompilerDriver/BuiltinOptions.h\"\n"
 
2918
    << "#include \"llvm/CompilerDriver/CompilationGraph.h\"\n"
 
2919
    << "#include \"llvm/CompilerDriver/ForceLinkageMacros.h\"\n"
 
2920
    << "#include \"llvm/CompilerDriver/Plugin.h\"\n"
 
2921
    << "#include \"llvm/CompilerDriver/Tool.h\"\n\n"
 
2922
 
 
2923
    << "#include \"llvm/Support/CommandLine.h\"\n"
 
2924
    << "#include \"llvm/Support/raw_ostream.h\"\n\n"
 
2925
 
 
2926
    << "#include <algorithm>\n"
 
2927
    << "#include <cstdlib>\n"
 
2928
    << "#include <iterator>\n"
 
2929
    << "#include <stdexcept>\n\n"
 
2930
 
 
2931
    << "using namespace llvm;\n"
 
2932
    << "using namespace llvmc;\n\n"
 
2933
 
 
2934
    << "extern cl::opt<std::string> OutputFilename;\n\n"
 
2935
 
 
2936
    << "inline const char* checkCString(const char* s)\n"
 
2937
    << "{ return s == NULL ? \"\" : s; }\n\n";
 
2938
}
 
2939
 
 
2940
 
 
2941
/// PluginData - Holds all information about a plugin.
 
2942
struct PluginData {
 
2943
  OptionDescriptions OptDescs;
 
2944
  bool HasSink;
 
2945
  bool HasExterns;
 
2946
  ToolDescriptions ToolDescs;
 
2947
  RecordVector Edges;
 
2948
  int Priority;
 
2949
};
 
2950
 
 
2951
/// HasSink - Go through the list of tool descriptions and check if
 
2952
/// there are any with the 'sink' property set.
 
2953
bool HasSink(const ToolDescriptions& ToolDescs) {
 
2954
  for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
 
2955
         E = ToolDescs.end(); B != E; ++B)
 
2956
    if ((*B)->isSink())
 
2957
      return true;
 
2958
 
 
2959
  return false;
 
2960
}
 
2961
 
 
2962
/// HasExterns - Go through the list of option descriptions and check
 
2963
/// if there are any external options.
 
2964
bool HasExterns(const OptionDescriptions& OptDescs) {
 
2965
 for (OptionDescriptions::const_iterator B = OptDescs.begin(),
 
2966
         E = OptDescs.end(); B != E; ++B)
 
2967
    if (B->second.isExtern())
 
2968
      return true;
 
2969
 
 
2970
  return false;
 
2971
}
 
2972
 
 
2973
/// CollectPluginData - Collect tool and option properties,
 
2974
/// compilation graph edges and plugin priority from the parse tree.
 
2975
void CollectPluginData (const RecordKeeper& Records, PluginData& Data) {
 
2976
  // Collect option properties.
 
2977
  const RecordVector& OptionLists =
 
2978
    Records.getAllDerivedDefinitions("OptionList");
 
2979
  CollectOptionDescriptions(OptionLists.begin(), OptionLists.end(),
 
2980
                            Data.OptDescs);
 
2981
 
 
2982
  // Collect tool properties.
 
2983
  const RecordVector& Tools = Records.getAllDerivedDefinitions("Tool");
 
2984
  CollectToolDescriptions(Tools.begin(), Tools.end(), Data.ToolDescs);
 
2985
  Data.HasSink = HasSink(Data.ToolDescs);
 
2986
  Data.HasExterns = HasExterns(Data.OptDescs);
 
2987
 
 
2988
  // Collect compilation graph edges.
 
2989
  const RecordVector& CompilationGraphs =
 
2990
    Records.getAllDerivedDefinitions("CompilationGraph");
 
2991
  FillInEdgeVector(CompilationGraphs.begin(), CompilationGraphs.end(),
 
2992
                   Data.Edges);
 
2993
 
 
2994
  // Calculate the priority of this plugin.
 
2995
  const RecordVector& Priorities =
 
2996
    Records.getAllDerivedDefinitions("PluginPriority");
 
2997
  Data.Priority = CalculatePriority(Priorities.begin(), Priorities.end());
 
2998
}
 
2999
 
 
3000
/// CheckPluginData - Perform some sanity checks on the collected data.
 
3001
void CheckPluginData(PluginData& Data) {
 
3002
  // Filter out all tools not mentioned in the compilation graph.
 
3003
  FilterNotInGraph(Data.Edges, Data.ToolDescs);
 
3004
 
 
3005
  // Typecheck the compilation graph.
 
3006
  TypecheckGraph(Data.Edges, Data.ToolDescs);
 
3007
 
 
3008
  // Check that there are no options without side effects (specified
 
3009
  // only in the OptionList).
 
3010
  CheckForSuperfluousOptions(Data.Edges, Data.ToolDescs, Data.OptDescs);
 
3011
}
 
3012
 
 
3013
void EmitPluginCode(const PluginData& Data, raw_ostream& O) {
 
3014
  // Emit file header.
 
3015
  EmitIncludes(O);
 
3016
 
 
3017
  // Emit global option registration code.
 
3018
  EmitOptionDefinitions(Data.OptDescs, Data.HasSink, Data.HasExterns, O);
 
3019
 
 
3020
  // Emit hook declarations.
 
3021
  EmitHookDeclarations(Data.ToolDescs, Data.OptDescs, O);
 
3022
 
 
3023
  O << "namespace {\n\n";
 
3024
 
 
3025
  // Emit PreprocessOptionsLocal() function.
 
3026
  EmitPreprocessOptions(Records, Data.OptDescs, O);
 
3027
 
 
3028
  // Emit PopulateLanguageMapLocal() function
 
3029
  // (language map maps from file extensions to language names).
 
3030
  EmitPopulateLanguageMap(Records, O);
 
3031
 
 
3032
  // Emit Tool classes.
 
3033
  for (ToolDescriptions::const_iterator B = Data.ToolDescs.begin(),
 
3034
         E = Data.ToolDescs.end(); B!=E; ++B)
 
3035
    EmitToolClassDefinition(*(*B), Data.OptDescs, O);
 
3036
 
 
3037
  // Emit Edge# classes.
 
3038
  EmitEdgeClasses(Data.Edges, Data.OptDescs, O);
 
3039
 
 
3040
  // Emit PopulateCompilationGraphLocal() function.
 
3041
  EmitPopulateCompilationGraph(Data.Edges, Data.ToolDescs, O);
 
3042
 
 
3043
  // Emit code for plugin registration.
 
3044
  EmitRegisterPlugin(Data.Priority, O);
 
3045
 
 
3046
  O << "} // End anonymous namespace.\n\n";
 
3047
 
 
3048
  // Force linkage magic.
 
3049
  O << "namespace llvmc {\n";
 
3050
  O << "LLVMC_FORCE_LINKAGE_DECL(LLVMC_PLUGIN_NAME) {}\n";
 
3051
  O << "}\n";
 
3052
 
 
3053
  // EOF
 
3054
}
 
3055
 
 
3056
 
 
3057
// End of anonymous namespace
 
3058
}
 
3059
 
 
3060
/// run - The back-end entry point.
 
3061
void LLVMCConfigurationEmitter::run (raw_ostream &O) {
 
3062
  try {
 
3063
  PluginData Data;
 
3064
 
 
3065
  CollectPluginData(Records, Data);
 
3066
  CheckPluginData(Data);
 
3067
 
 
3068
  this->EmitSourceFileHeader("LLVMC Configuration Library", O);
 
3069
  EmitPluginCode(Data, O);
 
3070
 
 
3071
  } catch (std::exception& Error) {
 
3072
    throw Error.what() + std::string(" - usually this means a syntax error.");
 
3073
  }
 
3074
}