~ubuntu-branches/ubuntu/feisty/clamav/feisty

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2007-02-20 10:33:44 UTC
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: james.westby@ubuntu.com-20070220103344-zgcu2psnx9d98fpa
Tags: upstream-0.90
ImportĀ upstreamĀ versionĀ 0.90

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