1 //===- LLVMCConfigurationEmitter.cpp - Generate LLVMC config ----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open
6 // Source License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This tablegen backend is responsible for emitting LLVMC configuration code.
12 //===----------------------------------------------------------------------===//
14 #include "LLVMCConfigurationEmitter.h"
17 #include "llvm/ADT/IntrusiveRefCntPtr.h"
18 #include "llvm/ADT/StringMap.h"
19 #include "llvm/ADT/StringSet.h"
33 //===----------------------------------------------------------------------===//
36 typedef std::vector
<Record
*> RecordVector
;
37 typedef std::vector
<const DagInit
*> DagVector
;
38 typedef std::vector
<std::string
> StrVector
;
40 //===----------------------------------------------------------------------===//
44 const unsigned TabWidth
= 4;
45 const unsigned Indent1
= TabWidth
*1;
46 const unsigned Indent2
= TabWidth
*2;
47 const unsigned Indent3
= TabWidth
*3;
48 const unsigned Indent4
= TabWidth
*4;
50 // Default help string.
51 const char * const DefaultHelpString
= "NO HELP MESSAGE PROVIDED";
53 // Name for the "sink" option.
54 const char * const SinkOptionName
= "SinkOption";
56 //===----------------------------------------------------------------------===//
59 /// Id - An 'identity' function object.
62 void operator()(const T0
&) const {
64 template<typename T0
, typename T1
>
65 void operator()(const T0
&, const T1
&) const {
67 template<typename T0
, typename T1
, typename T2
>
68 void operator()(const T0
&, const T1
&, const T2
&) const {
72 int InitPtrToInt(const Init
* ptr
) {
73 const IntInit
& val
= dynamic_cast<const IntInit
&>(*ptr
);
74 return val
.getValue();
77 const std::string
& InitPtrToString(const Init
* ptr
) {
78 const StringInit
& val
= dynamic_cast<const StringInit
&>(*ptr
);
79 return val
.getValue();
82 const ListInit
& InitPtrToList(const Init
* ptr
) {
83 const ListInit
& val
= dynamic_cast<const ListInit
&>(*ptr
);
87 const DagInit
& InitPtrToDag(const Init
* ptr
) {
88 const DagInit
& val
= dynamic_cast<const DagInit
&>(*ptr
);
92 const std::string
GetOperatorName(const DagInit
& D
) {
93 return D
.getOperator()->getAsString();
96 /// CheckBooleanConstant - Check that the provided value is a boolean constant.
97 void CheckBooleanConstant(const Init
* I
) {
98 const DefInit
& val
= dynamic_cast<const DefInit
&>(*I
);
99 const std::string
& str
= val
.getAsString();
101 if (str
!= "true" && str
!= "false") {
102 throw "Incorrect boolean value: '" + str
+
103 "': must be either 'true' or 'false'";
107 // CheckNumberOfArguments - Ensure that the number of args in d is
108 // greater than or equal to min_arguments, otherwise throw an exception.
109 void CheckNumberOfArguments (const DagInit
& d
, unsigned minArgs
) {
110 if (d
.getNumArgs() < minArgs
)
111 throw GetOperatorName(d
) + ": too few arguments!";
114 // EscapeVariableName - Escape commas and other symbols not allowed
115 // in the C++ variable names. Makes it possible to use options named
116 // like "Wa," (useful for prefix options).
117 std::string
EscapeVariableName (const std::string
& Var
) {
119 for (unsigned i
= 0; i
!= Var
.size(); ++i
) {
120 char cur_char
= Var
[i
];
121 if (cur_char
== ',') {
124 else if (cur_char
== '+') {
127 else if (cur_char
== '-') {
131 ret
.push_back(cur_char
);
137 /// EscapeQuotes - Replace '"' with '\"'.
138 std::string
EscapeQuotes (const std::string
& Var
) {
140 for (unsigned i
= 0; i
!= Var
.size(); ++i
) {
141 char cur_char
= Var
[i
];
142 if (cur_char
== '"') {
146 ret
.push_back(cur_char
);
152 /// OneOf - Does the input string contain this character?
153 bool OneOf(const char* lst
, char c
) {
161 template <class I
, class S
>
162 void CheckedIncrement(I
& P
, I E
, S ErrorString
) {
168 //===----------------------------------------------------------------------===//
169 /// Back-end specific code
172 /// OptionType - One of six different option types. See the
173 /// documentation for detailed description of differences.
174 namespace OptionType
{
176 enum OptionType
{ Alias
, Switch
, SwitchList
,
177 Parameter
, ParameterList
, Prefix
, PrefixList
};
179 bool IsAlias(OptionType t
) {
183 bool IsList (OptionType t
) {
184 return (t
== SwitchList
|| t
== ParameterList
|| t
== PrefixList
);
187 bool IsSwitch (OptionType t
) {
188 return (t
== Switch
);
191 bool IsSwitchList (OptionType t
) {
192 return (t
== SwitchList
);
195 bool IsParameter (OptionType t
) {
196 return (t
== Parameter
|| t
== Prefix
);
201 OptionType::OptionType
stringToOptionType(const std::string
& T
) {
202 if (T
== "alias_option")
203 return OptionType::Alias
;
204 else if (T
== "switch_option")
205 return OptionType::Switch
;
206 else if (T
== "switch_list_option")
207 return OptionType::SwitchList
;
208 else if (T
== "parameter_option")
209 return OptionType::Parameter
;
210 else if (T
== "parameter_list_option")
211 return OptionType::ParameterList
;
212 else if (T
== "prefix_option")
213 return OptionType::Prefix
;
214 else if (T
== "prefix_list_option")
215 return OptionType::PrefixList
;
217 throw "Unknown option type: " + T
+ '!';
220 namespace OptionDescriptionFlags
{
221 enum OptionDescriptionFlags
{ Required
= 0x1, Hidden
= 0x2,
222 ReallyHidden
= 0x4, OneOrMore
= 0x8,
223 Optional
= 0x10, CommaSeparated
= 0x20,
224 ForwardNotSplit
= 0x40, ZeroOrMore
= 0x80 };
227 /// OptionDescription - Represents data contained in a single
228 /// OptionList entry.
229 struct OptionDescription
{
230 OptionType::OptionType Type
;
237 OptionDescription(OptionType::OptionType t
= OptionType::Switch
,
238 const std::string
& n
= "",
239 const std::string
& h
= DefaultHelpString
)
240 : Type(t
), Name(n
), Flags(0x0), Help(h
), MultiVal(1), InitVal(0)
243 /// GenTypeDeclaration - Returns the C++ variable type of this
245 const char* GenTypeDeclaration() const;
247 /// GenVariableName - Returns the variable name used in the
248 /// generated C++ code.
249 std::string
GenVariableName() const
250 { return "autogenerated::" + GenOptionType() + EscapeVariableName(Name
); }
252 /// GenPlainVariableName - Returns the variable name without the namespace
254 std::string
GenPlainVariableName() const
255 { return GenOptionType() + EscapeVariableName(Name
); }
257 /// Merge - Merge two option descriptions.
258 void Merge (const OptionDescription
& other
);
260 /// CheckConsistency - Check that the flags are consistent.
261 void CheckConsistency() const;
263 // Misc convenient getters/setters.
265 bool isAlias() const;
267 bool isMultiVal() const;
269 bool isCommaSeparated() const;
270 void setCommaSeparated();
272 bool isForwardNotSplit() const;
273 void setForwardNotSplit();
275 bool isRequired() const;
278 bool isOneOrMore() const;
281 bool isZeroOrMore() const;
282 void setZeroOrMore();
284 bool isOptional() const;
287 bool isHidden() const;
290 bool isReallyHidden() const;
291 void setReallyHidden();
293 bool isSwitch() const
294 { return OptionType::IsSwitch(this->Type
); }
296 bool isSwitchList() const
297 { return OptionType::IsSwitchList(this->Type
); }
299 bool isParameter() const
300 { return OptionType::IsParameter(this->Type
); }
303 { return OptionType::IsList(this->Type
); }
305 bool isParameterList() const
306 { return (OptionType::IsList(this->Type
)
307 && !OptionType::IsSwitchList(this->Type
)); }
311 // GenOptionType - Helper function used by GenVariableName().
312 std::string
GenOptionType() const;
315 void OptionDescription::CheckConsistency() const {
318 i
+= this->isRequired();
319 i
+= this->isOptional();
320 i
+= this->isOneOrMore();
321 i
+= this->isZeroOrMore();
324 throw "Only one of (required), (optional), (one_or_more) or "
325 "(zero_or_more) properties is allowed!";
329 void OptionDescription::Merge (const OptionDescription
& other
)
331 if (other
.Type
!= Type
)
332 throw "Conflicting definitions for the option " + Name
+ "!";
334 if (Help
== other
.Help
|| Help
== DefaultHelpString
)
336 else if (other
.Help
!= DefaultHelpString
) {
337 llvm::errs() << "Warning: several different help strings"
338 " defined for option " + Name
+ "\n";
341 Flags
|= other
.Flags
;
344 bool OptionDescription::isAlias() const {
345 return OptionType::IsAlias(this->Type
);
348 bool OptionDescription::isMultiVal() const {
352 bool OptionDescription::isCommaSeparated() const {
353 return Flags
& OptionDescriptionFlags::CommaSeparated
;
355 void OptionDescription::setCommaSeparated() {
356 Flags
|= OptionDescriptionFlags::CommaSeparated
;
359 bool OptionDescription::isForwardNotSplit() const {
360 return Flags
& OptionDescriptionFlags::ForwardNotSplit
;
362 void OptionDescription::setForwardNotSplit() {
363 Flags
|= OptionDescriptionFlags::ForwardNotSplit
;
366 bool OptionDescription::isRequired() const {
367 return Flags
& OptionDescriptionFlags::Required
;
369 void OptionDescription::setRequired() {
370 Flags
|= OptionDescriptionFlags::Required
;
373 bool OptionDescription::isOneOrMore() const {
374 return Flags
& OptionDescriptionFlags::OneOrMore
;
376 void OptionDescription::setOneOrMore() {
377 Flags
|= OptionDescriptionFlags::OneOrMore
;
380 bool OptionDescription::isZeroOrMore() const {
381 return Flags
& OptionDescriptionFlags::ZeroOrMore
;
383 void OptionDescription::setZeroOrMore() {
384 Flags
|= OptionDescriptionFlags::ZeroOrMore
;
387 bool OptionDescription::isOptional() const {
388 return Flags
& OptionDescriptionFlags::Optional
;
390 void OptionDescription::setOptional() {
391 Flags
|= OptionDescriptionFlags::Optional
;
394 bool OptionDescription::isHidden() const {
395 return Flags
& OptionDescriptionFlags::Hidden
;
397 void OptionDescription::setHidden() {
398 Flags
|= OptionDescriptionFlags::Hidden
;
401 bool OptionDescription::isReallyHidden() const {
402 return Flags
& OptionDescriptionFlags::ReallyHidden
;
404 void OptionDescription::setReallyHidden() {
405 Flags
|= OptionDescriptionFlags::ReallyHidden
;
408 const char* OptionDescription::GenTypeDeclaration() const {
410 case OptionType::Alias
:
412 case OptionType::PrefixList
:
413 case OptionType::ParameterList
:
414 return "cl::list<std::string>";
415 case OptionType::Switch
:
416 return "cl::opt<bool>";
417 case OptionType::SwitchList
:
418 return "cl::list<bool>";
419 case OptionType::Parameter
:
420 case OptionType::Prefix
:
422 return "cl::opt<std::string>";
426 std::string
OptionDescription::GenOptionType() const {
428 case OptionType::Alias
:
430 case OptionType::PrefixList
:
431 case OptionType::ParameterList
:
433 case OptionType::Switch
:
435 case OptionType::SwitchList
:
436 return "SwitchList_";
437 case OptionType::Prefix
:
438 case OptionType::Parameter
:
444 /// OptionDescriptions - An OptionDescription array plus some helper
446 class OptionDescriptions
{
447 typedef StringMap
<OptionDescription
> container_type
;
449 /// Descriptions - A list of OptionDescriptions.
450 container_type Descriptions
;
453 /// FindOption - exception-throwing wrapper for find().
454 const OptionDescription
& FindOption(const std::string
& OptName
) const;
456 // Wrappers for FindOption that throw an exception in case the option has a
458 const OptionDescription
& FindSwitch(const std::string
& OptName
) const;
459 const OptionDescription
& FindParameter(const std::string
& OptName
) const;
460 const OptionDescription
& FindParameterList(const std::string
& OptName
) const;
461 const OptionDescription
&
462 FindListOrParameter(const std::string
& OptName
) const;
463 const OptionDescription
&
464 FindParameterListOrParameter(const std::string
& OptName
) const;
466 /// insertDescription - Insert new OptionDescription into
467 /// OptionDescriptions list
468 void InsertDescription (const OptionDescription
& o
);
470 // Support for STL-style iteration
471 typedef container_type::const_iterator const_iterator
;
472 const_iterator
begin() const { return Descriptions
.begin(); }
473 const_iterator
end() const { return Descriptions
.end(); }
476 const OptionDescription
&
477 OptionDescriptions::FindOption(const std::string
& OptName
) const {
478 const_iterator I
= Descriptions
.find(OptName
);
479 if (I
!= Descriptions
.end())
482 throw OptName
+ ": no such option!";
485 const OptionDescription
&
486 OptionDescriptions::FindSwitch(const std::string
& OptName
) const {
487 const OptionDescription
& OptDesc
= this->FindOption(OptName
);
488 if (!OptDesc
.isSwitch())
489 throw OptName
+ ": incorrect option type - should be a switch!";
493 const OptionDescription
&
494 OptionDescriptions::FindParameterList(const std::string
& OptName
) const {
495 const OptionDescription
& OptDesc
= this->FindOption(OptName
);
496 if (!OptDesc
.isList() || OptDesc
.isSwitchList())
497 throw OptName
+ ": incorrect option type - should be a parameter list!";
501 const OptionDescription
&
502 OptionDescriptions::FindParameter(const std::string
& OptName
) const {
503 const OptionDescription
& OptDesc
= this->FindOption(OptName
);
504 if (!OptDesc
.isParameter())
505 throw OptName
+ ": incorrect option type - should be a parameter!";
509 const OptionDescription
&
510 OptionDescriptions::FindListOrParameter(const std::string
& OptName
) const {
511 const OptionDescription
& OptDesc
= this->FindOption(OptName
);
512 if (!OptDesc
.isList() && !OptDesc
.isParameter())
514 + ": incorrect option type - should be a list or parameter!";
518 const OptionDescription
&
519 OptionDescriptions::FindParameterListOrParameter
520 (const std::string
& OptName
) const {
521 const OptionDescription
& OptDesc
= this->FindOption(OptName
);
522 if ((!OptDesc
.isList() && !OptDesc
.isParameter()) || OptDesc
.isSwitchList())
524 + ": incorrect option type - should be a parameter list or parameter!";
528 void OptionDescriptions::InsertDescription (const OptionDescription
& o
) {
529 container_type::iterator I
= Descriptions
.find(o
.Name
);
530 if (I
!= Descriptions
.end()) {
531 OptionDescription
& D
= I
->second
;
535 Descriptions
[o
.Name
] = o
;
539 /// HandlerTable - A base class for function objects implemented as
540 /// 'tables of handlers'.
541 template <typename Handler
>
544 // Implementation details.
546 /// HandlerMap - A map from property names to property handlers
547 typedef StringMap
<Handler
> HandlerMap
;
549 static HandlerMap Handlers_
;
550 static bool staticMembersInitialized_
;
554 Handler
GetHandler (const std::string
& HandlerName
) const {
555 typename
HandlerMap::iterator method
= Handlers_
.find(HandlerName
);
557 if (method
!= Handlers_
.end()) {
558 Handler h
= method
->second
;
562 throw "No handler found for property " + HandlerName
+ "!";
566 void AddHandler(const char* Property
, Handler H
) {
567 Handlers_
[Property
] = H
;
572 template <class Handler
, class FunctionObject
>
573 Handler
GetHandler(FunctionObject
* Obj
, const DagInit
& Dag
) {
574 const std::string
& HandlerName
= GetOperatorName(Dag
);
575 return Obj
->GetHandler(HandlerName
);
578 template <class FunctionObject
>
579 void InvokeDagInitHandler(FunctionObject
* Obj
, Init
* I
) {
580 typedef void (FunctionObject::*Handler
) (const DagInit
&);
582 const DagInit
& Dag
= InitPtrToDag(I
);
583 Handler h
= GetHandler
<Handler
>(Obj
, Dag
);
588 template <class FunctionObject
>
589 void InvokeDagInitHandler(const FunctionObject
* const Obj
,
590 const Init
* I
, unsigned IndentLevel
, raw_ostream
& O
)
592 typedef void (FunctionObject::*Handler
)
593 (const DagInit
&, unsigned IndentLevel
, raw_ostream
& O
) const;
595 const DagInit
& Dag
= InitPtrToDag(I
);
596 Handler h
= GetHandler
<Handler
>(Obj
, Dag
);
598 ((Obj
)->*(h
))(Dag
, IndentLevel
, O
);
601 template <typename H
>
602 typename HandlerTable
<H
>::HandlerMap HandlerTable
<H
>::Handlers_
;
604 template <typename H
>
605 bool HandlerTable
<H
>::staticMembersInitialized_
= false;
608 /// CollectOptionProperties - Function object for iterating over an
609 /// option property list.
610 class CollectOptionProperties
;
611 typedef void (CollectOptionProperties::* CollectOptionPropertiesHandler
)
614 class CollectOptionProperties
615 : public HandlerTable
<CollectOptionPropertiesHandler
>
619 /// optDescs_ - OptionDescriptions table. This is where the
620 /// information is stored.
621 OptionDescription
& optDesc_
;
625 explicit CollectOptionProperties(OptionDescription
& OD
)
628 if (!staticMembersInitialized_
) {
629 AddHandler("help", &CollectOptionProperties::onHelp
);
630 AddHandler("hidden", &CollectOptionProperties::onHidden
);
631 AddHandler("init", &CollectOptionProperties::onInit
);
632 AddHandler("multi_val", &CollectOptionProperties::onMultiVal
);
633 AddHandler("one_or_more", &CollectOptionProperties::onOneOrMore
);
634 AddHandler("zero_or_more", &CollectOptionProperties::onZeroOrMore
);
635 AddHandler("really_hidden", &CollectOptionProperties::onReallyHidden
);
636 AddHandler("required", &CollectOptionProperties::onRequired
);
637 AddHandler("optional", &CollectOptionProperties::onOptional
);
638 AddHandler("comma_separated", &CollectOptionProperties::onCommaSeparated
);
639 AddHandler("forward_not_split",
640 &CollectOptionProperties::onForwardNotSplit
);
642 staticMembersInitialized_
= true;
646 /// operator() - Just forwards to the corresponding property
648 void operator() (Init
* I
) {
649 InvokeDagInitHandler(this, I
);
654 /// Option property handlers --
655 /// Methods that handle option properties such as (help) or (hidden).
657 void onHelp (const DagInit
& d
) {
658 CheckNumberOfArguments(d
, 1);
659 optDesc_
.Help
= EscapeQuotes(InitPtrToString(d
.getArg(0)));
662 void onHidden (const DagInit
& d
) {
663 CheckNumberOfArguments(d
, 0);
664 optDesc_
.setHidden();
667 void onReallyHidden (const DagInit
& d
) {
668 CheckNumberOfArguments(d
, 0);
669 optDesc_
.setReallyHidden();
672 void onCommaSeparated (const DagInit
& d
) {
673 CheckNumberOfArguments(d
, 0);
674 if (!optDesc_
.isParameterList())
675 throw "'comma_separated' is valid only on parameter list options!";
676 optDesc_
.setCommaSeparated();
679 void onForwardNotSplit (const DagInit
& d
) {
680 CheckNumberOfArguments(d
, 0);
681 if (!optDesc_
.isParameter())
682 throw "'forward_not_split' is valid only for parameter options!";
683 optDesc_
.setForwardNotSplit();
686 void onRequired (const DagInit
& d
) {
687 CheckNumberOfArguments(d
, 0);
689 optDesc_
.setRequired();
690 optDesc_
.CheckConsistency();
693 void onInit (const DagInit
& d
) {
694 CheckNumberOfArguments(d
, 1);
695 Init
* i
= d
.getArg(0);
696 const std::string
& str
= i
->getAsString();
698 bool correct
= optDesc_
.isParameter() && dynamic_cast<StringInit
*>(i
);
699 correct
|= (optDesc_
.isSwitch() && (str
== "true" || str
== "false"));
702 throw "Incorrect usage of the 'init' option property!";
704 optDesc_
.InitVal
= i
;
707 void onOneOrMore (const DagInit
& d
) {
708 CheckNumberOfArguments(d
, 0);
710 optDesc_
.setOneOrMore();
711 optDesc_
.CheckConsistency();
714 void onZeroOrMore (const DagInit
& d
) {
715 CheckNumberOfArguments(d
, 0);
717 if (optDesc_
.isList())
718 llvm::errs() << "Warning: specifying the 'zero_or_more' property "
719 "on a list option has no effect.\n";
721 optDesc_
.setZeroOrMore();
722 optDesc_
.CheckConsistency();
725 void onOptional (const DagInit
& d
) {
726 CheckNumberOfArguments(d
, 0);
728 if (!optDesc_
.isList())
729 llvm::errs() << "Warning: specifying the 'optional' property"
730 "on a non-list option has no effect.\n";
732 optDesc_
.setOptional();
733 optDesc_
.CheckConsistency();
736 void onMultiVal (const DagInit
& d
) {
737 CheckNumberOfArguments(d
, 1);
738 int val
= InitPtrToInt(d
.getArg(0));
740 throw "Error in the 'multi_val' property: "
741 "the value must be greater than 1!";
742 if (!optDesc_
.isParameterList())
743 throw "The multi_val property is valid only on list options!";
744 optDesc_
.MultiVal
= val
;
749 /// AddOption - A function object that is applied to every option
750 /// description. Used by CollectOptionDescriptions.
753 OptionDescriptions
& OptDescs_
;
756 explicit AddOption(OptionDescriptions
& OD
) : OptDescs_(OD
)
759 void operator()(const Init
* i
) {
760 const DagInit
& d
= InitPtrToDag(i
);
761 CheckNumberOfArguments(d
, 1);
763 const OptionType::OptionType Type
=
764 stringToOptionType(GetOperatorName(d
));
765 const std::string
& Name
= InitPtrToString(d
.getArg(0));
767 OptionDescription
OD(Type
, Name
);
769 CheckNumberOfArguments(d
, 2);
772 // Aliases store the aliased option name in the 'Help' field.
773 OD
.Help
= InitPtrToString(d
.getArg(1));
776 processOptionProperties(d
, OD
);
779 OptDescs_
.InsertDescription(OD
);
783 /// processOptionProperties - Go through the list of option
784 /// properties and call a corresponding handler for each.
785 static void processOptionProperties (const DagInit
& d
, OptionDescription
& o
) {
786 CheckNumberOfArguments(d
, 2);
787 DagInit::const_arg_iterator B
= d
.arg_begin();
788 // Skip the first argument: it's always the option name.
790 std::for_each(B
, d
.arg_end(), CollectOptionProperties(o
));
795 /// CollectOptionDescriptions - Collects option properties from all
797 void CollectOptionDescriptions (const RecordVector
& V
,
798 OptionDescriptions
& OptDescs
)
800 // For every OptionList:
801 for (RecordVector::const_iterator B
= V
.begin(), E
= V
.end(); B
!=E
; ++B
)
803 // Throws an exception if the value does not exist.
804 ListInit
* PropList
= (*B
)->getValueAsListInit("options");
806 // For every option description in this list: invoke AddOption.
807 std::for_each(PropList
->begin(), PropList
->end(), AddOption(OptDescs
));
811 // Tool information record
813 namespace ToolFlags
{
814 enum ToolFlags
{ Join
= 0x1, Sink
= 0x2 };
817 struct ToolDescription
: public RefCountedBase
<ToolDescription
> {
821 StrVector InLanguage
;
822 std::string InFileOption
;
823 std::string OutFileOption
;
824 StrVector OutLanguage
;
825 std::string OutputSuffix
;
829 // Various boolean properties
830 void setSink() { Flags
|= ToolFlags::Sink
; }
831 bool isSink() const { return Flags
& ToolFlags::Sink
; }
832 void setJoin() { Flags
|= ToolFlags::Join
; }
833 bool isJoin() const { return Flags
& ToolFlags::Join
; }
835 // Default ctor here is needed because StringMap can only store
836 // DefaultConstructible objects
837 ToolDescription (const std::string
&n
= "")
838 : Name(n
), CmdLine(0), Actions(0), OutFileOption("-o"),
843 /// ToolDescriptions - A list of Tool information records.
844 typedef std::vector
<IntrusiveRefCntPtr
<ToolDescription
> > ToolDescriptions
;
847 /// CollectToolProperties - Function object for iterating over a list of
848 /// tool property records.
850 class CollectToolProperties
;
851 typedef void (CollectToolProperties::* CollectToolPropertiesHandler
)
854 class CollectToolProperties
: public HandlerTable
<CollectToolPropertiesHandler
>
858 /// toolDesc_ - Properties of the current Tool. This is where the
859 /// information is stored.
860 ToolDescription
& toolDesc_
;
864 explicit CollectToolProperties (ToolDescription
& d
)
867 if (!staticMembersInitialized_
) {
869 AddHandler("actions", &CollectToolProperties::onActions
);
870 AddHandler("command", &CollectToolProperties::onCommand
);
871 AddHandler("in_language", &CollectToolProperties::onInLanguage
);
872 AddHandler("join", &CollectToolProperties::onJoin
);
873 AddHandler("out_language", &CollectToolProperties::onOutLanguage
);
875 AddHandler("out_file_option", &CollectToolProperties::onOutFileOption
);
876 AddHandler("in_file_option", &CollectToolProperties::onInFileOption
);
878 AddHandler("output_suffix", &CollectToolProperties::onOutputSuffix
);
879 AddHandler("sink", &CollectToolProperties::onSink
);
880 AddHandler("works_on_empty", &CollectToolProperties::onWorksOnEmpty
);
882 staticMembersInitialized_
= true;
886 void operator() (Init
* I
) {
887 InvokeDagInitHandler(this, I
);
892 /// Property handlers --
893 /// Functions that extract information about tool properties from
894 /// DAG representation.
896 void onActions (const DagInit
& d
) {
897 CheckNumberOfArguments(d
, 1);
898 Init
* Case
= d
.getArg(0);
899 if (typeid(*Case
) != typeid(DagInit
) ||
900 GetOperatorName(static_cast<DagInit
&>(*Case
)) != "case")
901 throw "The argument to (actions) should be a 'case' construct!";
902 toolDesc_
.Actions
= Case
;
905 void onCommand (const DagInit
& d
) {
906 CheckNumberOfArguments(d
, 1);
907 toolDesc_
.CmdLine
= d
.getArg(0);
910 /// onInOutLanguage - Common implementation of on{In,Out}Language().
911 void onInOutLanguage (const DagInit
& d
, StrVector
& OutVec
) {
912 CheckNumberOfArguments(d
, 1);
914 // Copy strings to the output vector.
915 for (unsigned i
= 0, NumArgs
= d
.getNumArgs(); i
< NumArgs
; ++i
) {
916 OutVec
.push_back(InitPtrToString(d
.getArg(i
)));
919 // Remove duplicates.
920 std::sort(OutVec
.begin(), OutVec
.end());
921 StrVector::iterator newE
= std::unique(OutVec
.begin(), OutVec
.end());
922 OutVec
.erase(newE
, OutVec
.end());
926 void onInLanguage (const DagInit
& d
) {
927 this->onInOutLanguage(d
, toolDesc_
.InLanguage
);
930 void onJoin (const DagInit
& d
) {
931 CheckNumberOfArguments(d
, 0);
935 void onOutLanguage (const DagInit
& d
) {
936 this->onInOutLanguage(d
, toolDesc_
.OutLanguage
);
939 void onOutFileOption (const DagInit
& d
) {
940 CheckNumberOfArguments(d
, 1);
941 toolDesc_
.OutFileOption
= InitPtrToString(d
.getArg(0));
944 void onInFileOption (const DagInit
& d
) {
945 CheckNumberOfArguments(d
, 1);
946 toolDesc_
.InFileOption
= InitPtrToString(d
.getArg(0));
949 void onOutputSuffix (const DagInit
& d
) {
950 CheckNumberOfArguments(d
, 1);
951 toolDesc_
.OutputSuffix
= InitPtrToString(d
.getArg(0));
954 void onSink (const DagInit
& d
) {
955 CheckNumberOfArguments(d
, 0);
959 void onWorksOnEmpty (const DagInit
& d
) {
960 toolDesc_
.OnEmpty
= d
.getArg(0);
965 /// CollectToolDescriptions - Gather information about tool properties
966 /// from the parsed TableGen data (basically a wrapper for the
967 /// CollectToolProperties function object).
968 void CollectToolDescriptions (const RecordVector
& Tools
,
969 ToolDescriptions
& ToolDescs
)
971 // Iterate over a properties list of every Tool definition
972 for (RecordVector::const_iterator B
= Tools
.begin(),
973 E
= Tools
.end(); B
!=E
; ++B
) {
974 const Record
* T
= *B
;
975 // Throws an exception if the value does not exist.
976 ListInit
* PropList
= T
->getValueAsListInit("properties");
978 IntrusiveRefCntPtr
<ToolDescription
>
979 ToolDesc(new ToolDescription(T
->getName()));
981 std::for_each(PropList
->begin(), PropList
->end(),
982 CollectToolProperties(*ToolDesc
));
983 ToolDescs
.push_back(ToolDesc
);
987 /// FillInEdgeVector - Merge all compilation graph definitions into
988 /// one single edge list.
989 void FillInEdgeVector(const RecordVector
& CompilationGraphs
,
991 for (RecordVector::const_iterator B
= CompilationGraphs
.begin(),
992 E
= CompilationGraphs
.end(); B
!= E
; ++B
) {
993 const ListInit
* Edges
= (*B
)->getValueAsListInit("edges");
995 for (ListInit::const_iterator B
= Edges
->begin(),
996 E
= Edges
->end(); B
!= E
; ++B
) {
997 Out
.push_back(&InitPtrToDag(*B
));
1002 /// NotInGraph - Helper function object for FilterNotInGraph.
1005 const llvm::StringSet
<>& ToolsInGraph_
;
1008 NotInGraph(const llvm::StringSet
<>& ToolsInGraph
)
1009 : ToolsInGraph_(ToolsInGraph
)
1012 bool operator()(const IntrusiveRefCntPtr
<ToolDescription
>& x
) {
1013 return (ToolsInGraph_
.count(x
->Name
) == 0);
1017 /// FilterNotInGraph - Filter out from ToolDescs all Tools not
1018 /// mentioned in the compilation graph definition.
1019 void FilterNotInGraph (const DagVector
& EdgeVector
,
1020 ToolDescriptions
& ToolDescs
) {
1022 // List all tools mentioned in the graph.
1023 llvm::StringSet
<> ToolsInGraph
;
1025 for (DagVector::const_iterator B
= EdgeVector
.begin(),
1026 E
= EdgeVector
.end(); B
!= E
; ++B
) {
1028 const DagInit
* Edge
= *B
;
1029 const std::string
& NodeA
= InitPtrToString(Edge
->getArg(0));
1030 const std::string
& NodeB
= InitPtrToString(Edge
->getArg(1));
1032 if (NodeA
!= "root")
1033 ToolsInGraph
.insert(NodeA
);
1034 ToolsInGraph
.insert(NodeB
);
1037 // Filter ToolPropertiesList.
1038 ToolDescriptions::iterator new_end
=
1039 std::remove_if(ToolDescs
.begin(), ToolDescs
.end(),
1040 NotInGraph(ToolsInGraph
));
1041 ToolDescs
.erase(new_end
, ToolDescs
.end());
1044 /// FillInToolToLang - Fills in two tables that map tool names to
1045 /// input & output language names. Helper function used by TypecheckGraph().
1046 void FillInToolToLang (const ToolDescriptions
& ToolDescs
,
1047 StringMap
<StringSet
<> >& ToolToInLang
,
1048 StringMap
<StringSet
<> >& ToolToOutLang
) {
1049 for (ToolDescriptions::const_iterator B
= ToolDescs
.begin(),
1050 E
= ToolDescs
.end(); B
!= E
; ++B
) {
1051 const ToolDescription
& D
= *(*B
);
1052 for (StrVector::const_iterator B
= D
.InLanguage
.begin(),
1053 E
= D
.InLanguage
.end(); B
!= E
; ++B
)
1054 ToolToInLang
[D
.Name
].insert(*B
);
1055 for (StrVector::const_iterator B
= D
.OutLanguage
.begin(),
1056 E
= D
.OutLanguage
.end(); B
!= E
; ++B
)
1057 ToolToOutLang
[D
.Name
].insert(*B
);
1061 /// Intersect - Is set intersection non-empty?
1062 bool Intersect (const StringSet
<>& S1
, const StringSet
<>& S2
) {
1063 for (StringSet
<>::const_iterator B
= S1
.begin(), E
= S1
.end(); B
!= E
; ++B
) {
1064 if (S2
.count(B
->first()) != 0)
1070 /// TypecheckGraph - Check that names for output and input languages
1071 /// on all edges do match.
1072 void TypecheckGraph (const DagVector
& EdgeVector
,
1073 const ToolDescriptions
& ToolDescs
) {
1074 StringMap
<StringSet
<> > ToolToInLang
;
1075 StringMap
<StringSet
<> > ToolToOutLang
;
1077 FillInToolToLang(ToolDescs
, ToolToInLang
, ToolToOutLang
);
1079 for (DagVector::const_iterator B
= EdgeVector
.begin(),
1080 E
= EdgeVector
.end(); B
!= E
; ++B
) {
1081 const DagInit
* Edge
= *B
;
1082 const std::string
& NodeA
= InitPtrToString(Edge
->getArg(0));
1083 const std::string
& NodeB
= InitPtrToString(Edge
->getArg(1));
1084 StringMap
<StringSet
<> >::iterator IA
= ToolToOutLang
.find(NodeA
);
1085 StringMap
<StringSet
<> >::iterator IB
= ToolToInLang
.find(NodeB
);
1087 if (NodeB
== "root")
1088 throw "Edges back to the root are not allowed!";
1090 if (NodeA
!= "root") {
1091 if (IA
== ToolToOutLang
.end())
1092 throw NodeA
+ ": no output language defined!";
1093 if (IB
== ToolToInLang
.end())
1094 throw NodeB
+ ": no input language defined!";
1096 if (!Intersect(IA
->second
, IB
->second
)) {
1097 throw "Edge " + NodeA
+ "->" + NodeB
1098 + ": output->input language mismatch";
1104 /// WalkCase - Walks the 'case' expression DAG and invokes
1105 /// TestCallback on every test, and StatementCallback on every
1106 /// statement. Handles 'case' nesting, but not the 'and' and 'or'
1107 /// combinators (that is, they are passed directly to TestCallback).
1108 /// TestCallback must have type 'void TestCallback(const DagInit*, unsigned
1109 /// IndentLevel, bool FirstTest)'.
1110 /// StatementCallback must have type 'void StatementCallback(const Init*,
1111 /// unsigned IndentLevel)'.
1112 template <typename F1
, typename F2
>
1113 void WalkCase(const Init
* Case
, F1 TestCallback
, F2 StatementCallback
,
1114 unsigned IndentLevel
= 0)
1116 const DagInit
& d
= InitPtrToDag(Case
);
1119 if (GetOperatorName(d
) != "case")
1120 throw "WalkCase should be invoked only on 'case' expressions!";
1122 if (d
.getNumArgs() < 2)
1123 throw "There should be at least one clause in the 'case' expression:\n"
1128 const unsigned numArgs
= d
.getNumArgs();
1130 for (DagInit::const_arg_iterator B
= d
.arg_begin(), E
= d
.arg_end();
1137 const DagInit
& Test
= InitPtrToDag(arg
);
1139 if (GetOperatorName(Test
) == "default" && (i
+1 != numArgs
))
1140 throw "The 'default' clause should be the last in the "
1141 "'case' construct!";
1143 throw "Case construct handler: no corresponding action "
1144 "found for the test " + Test
.getAsString() + '!';
1146 TestCallback(Test
, IndentLevel
, (i
== 1));
1150 if (dynamic_cast<DagInit
*>(arg
)
1151 && GetOperatorName(static_cast<DagInit
&>(*arg
)) == "case") {
1153 WalkCase(arg
, TestCallback
, StatementCallback
, IndentLevel
+ Indent1
);
1156 // Handle statement.
1157 StatementCallback(arg
, IndentLevel
);
1165 /// ExtractOptionNames - A helper function object used by
1166 /// CheckForSuperfluousOptions() to walk the 'case' DAG.
1167 class ExtractOptionNames
{
1168 llvm::StringSet
<>& OptionNames_
;
1170 void processDag(const Init
* Statement
) {
1171 const DagInit
& Stmt
= InitPtrToDag(Statement
);
1172 const std::string
& ActionName
= GetOperatorName(Stmt
);
1173 if (ActionName
== "forward" || ActionName
== "forward_as" ||
1174 ActionName
== "forward_value" ||
1175 ActionName
== "forward_transformed_value" ||
1176 ActionName
== "parameter_equals" || ActionName
== "element_in_list") {
1177 CheckNumberOfArguments(Stmt
, 1);
1179 Init
* Arg
= Stmt
.getArg(0);
1180 if (typeid(*Arg
) == typeid(StringInit
))
1181 OptionNames_
.insert(InitPtrToString(Arg
));
1183 else if (ActionName
== "any_switch_on" || ActionName
== "switch_on" ||
1184 ActionName
== "any_not_empty" || ActionName
== "any_empty" ||
1185 ActionName
== "not_empty" || ActionName
== "empty") {
1186 for (unsigned i
= 0, NumArgs
= Stmt
.getNumArgs(); i
< NumArgs
; ++i
) {
1187 Init
* Arg
= Stmt
.getArg(i
);
1188 if (typeid(*Arg
) == typeid(StringInit
))
1189 OptionNames_
.insert(InitPtrToString(Arg
));
1192 else if (ActionName
== "and" || ActionName
== "or" || ActionName
== "not") {
1193 for (unsigned i
= 0, NumArgs
= Stmt
.getNumArgs(); i
< NumArgs
; ++i
) {
1194 this->processDag(Stmt
.getArg(i
));
1200 ExtractOptionNames(llvm::StringSet
<>& OptionNames
) : OptionNames_(OptionNames
)
1203 void operator()(const Init
* Statement
) {
1204 // Statement is either a dag, or a list of dags.
1205 if (typeid(*Statement
) == typeid(ListInit
)) {
1206 const ListInit
& DagList
= *static_cast<const ListInit
*>(Statement
);
1207 for (ListInit::const_iterator B
= DagList
.begin(), E
= DagList
.end();
1209 this->processDag(*B
);
1212 this->processDag(Statement
);
1216 void operator()(const DagInit
& Test
, unsigned, bool) {
1217 this->operator()(&Test
);
1219 void operator()(const Init
* Statement
, unsigned) {
1220 this->operator()(Statement
);
1224 /// IsOptionalEdge - Validate that the 'optional_edge' has proper structure.
1225 bool IsOptionalEdge (const DagInit
& Edg
) {
1226 return (GetOperatorName(Edg
) == "optional_edge") && (Edg
.getNumArgs() > 2);
1229 /// CheckForSuperfluousOptions - Check that there are no side
1230 /// effect-free options (specified only in the OptionList). Otherwise,
1231 /// output a warning.
1232 void CheckForSuperfluousOptions (const DagVector
& EdgeVector
,
1233 const ToolDescriptions
& ToolDescs
,
1234 const OptionDescriptions
& OptDescs
) {
1235 llvm::StringSet
<> nonSuperfluousOptions
;
1237 // Add all options mentioned in the ToolDesc.Actions to the set of
1238 // non-superfluous options.
1239 for (ToolDescriptions::const_iterator B
= ToolDescs
.begin(),
1240 E
= ToolDescs
.end(); B
!= E
; ++B
) {
1241 const ToolDescription
& TD
= *(*B
);
1242 ExtractOptionNames
Callback(nonSuperfluousOptions
);
1244 WalkCase(TD
.Actions
, Callback
, Callback
);
1247 // Add all options mentioned in the 'case' clauses of the
1248 // OptionalEdges of the compilation graph to the set of
1249 // non-superfluous options.
1250 for (DagVector::const_iterator B
= EdgeVector
.begin(),
1251 E
= EdgeVector
.end(); B
!= E
; ++B
) {
1252 const DagInit
& Edge
= **B
;
1253 if (IsOptionalEdge(Edge
)) {
1254 const DagInit
& Weight
= InitPtrToDag(Edge
.getArg(2));
1255 WalkCase(&Weight
, ExtractOptionNames(nonSuperfluousOptions
), Id());
1259 // Check that all options in OptDescs belong to the set of
1260 // non-superfluous options.
1261 for (OptionDescriptions::const_iterator B
= OptDescs
.begin(),
1262 E
= OptDescs
.end(); B
!= E
; ++B
) {
1263 const OptionDescription
& Val
= B
->second
;
1264 if (!nonSuperfluousOptions
.count(Val
.Name
)
1265 && Val
.Type
!= OptionType::Alias
)
1266 llvm::errs() << "Warning: option '-" << Val
.Name
<< "' has no effect! "
1267 "Probable cause: this option is specified only in the OptionList.\n";
1271 /// EmitCaseTest0Args - Helper function used by EmitCaseConstructHandler().
1272 bool EmitCaseTest0Args(const std::string
& TestName
, raw_ostream
& O
) {
1273 if (TestName
== "single_input_file") {
1274 O
<< "InputFilenames.size() == 1";
1277 else if (TestName
== "multiple_input_files") {
1278 O
<< "InputFilenames.size() > 1";
1285 /// EmitMultipleArgumentTest - Helper function used by
1286 /// EmitCaseTestMultipleArgs()
1287 template <typename F
>
1288 void EmitMultipleArgumentTest(const DagInit
& D
, const char* LogicOp
,
1289 F Callback
, raw_ostream
& O
)
1291 for (unsigned i
= 0, NumArgs
= D
.getNumArgs(); i
< NumArgs
; ++i
) {
1293 O
<< ' ' << LogicOp
<< ' ';
1294 Callback(InitPtrToString(D
.getArg(i
)), O
);
1298 // Callbacks for use with EmitMultipleArgumentTest
1300 class EmitSwitchOn
{
1301 const OptionDescriptions
& OptDescs_
;
1303 EmitSwitchOn(const OptionDescriptions
& OptDescs
) : OptDescs_(OptDescs
)
1306 void operator()(const std::string
& OptName
, raw_ostream
& O
) const {
1307 const OptionDescription
& OptDesc
= OptDescs_
.FindSwitch(OptName
);
1308 O
<< OptDesc
.GenVariableName();
1312 class EmitEmptyTest
{
1314 const OptionDescriptions
& OptDescs_
;
1316 EmitEmptyTest(bool EmitNegate
, const OptionDescriptions
& OptDescs
)
1317 : EmitNegate_(EmitNegate
), OptDescs_(OptDescs
)
1320 void operator()(const std::string
& OptName
, raw_ostream
& O
) const {
1321 const char* Neg
= (EmitNegate_
? "!" : "");
1322 if (OptName
== "o") {
1323 O
<< Neg
<< "OutputFilename.empty()";
1325 else if (OptName
== "save-temps") {
1326 O
<< Neg
<< "(SaveTemps == SaveTempsEnum::Unset)";
1329 const OptionDescription
& OptDesc
= OptDescs_
.FindListOrParameter(OptName
);
1330 O
<< Neg
<< OptDesc
.GenVariableName() << ".empty()";
1336 /// EmitCaseTestMultipleArgs - Helper function used by EmitCaseTest1Arg()
1337 bool EmitCaseTestMultipleArgs (const std::string
& TestName
,
1339 const OptionDescriptions
& OptDescs
,
1341 if (TestName
== "any_switch_on") {
1342 EmitMultipleArgumentTest(d
, "||", EmitSwitchOn(OptDescs
), O
);
1345 else if (TestName
== "switch_on") {
1346 EmitMultipleArgumentTest(d
, "&&", EmitSwitchOn(OptDescs
), O
);
1349 else if (TestName
== "any_not_empty") {
1350 EmitMultipleArgumentTest(d
, "||", EmitEmptyTest(true, OptDescs
), O
);
1353 else if (TestName
== "any_empty") {
1354 EmitMultipleArgumentTest(d
, "||", EmitEmptyTest(false, OptDescs
), O
);
1357 else if (TestName
== "not_empty") {
1358 EmitMultipleArgumentTest(d
, "&&", EmitEmptyTest(true, OptDescs
), O
);
1361 else if (TestName
== "empty") {
1362 EmitMultipleArgumentTest(d
, "&&", EmitEmptyTest(false, OptDescs
), O
);
1369 /// EmitCaseTest1Arg - Helper function used by EmitCaseTest1OrMoreArgs()
1370 bool EmitCaseTest1Arg (const std::string
& TestName
,
1372 const OptionDescriptions
& OptDescs
,
1374 const std::string
& Arg
= InitPtrToString(d
.getArg(0));
1376 if (TestName
== "input_languages_contain") {
1377 O
<< "InLangs.count(\"" << Arg
<< "\") != 0";
1380 else if (TestName
== "in_language") {
1381 // This works only for single-argument Tool::GenerateAction. Join
1382 // tools can process several files in different languages simultaneously.
1384 // TODO: make this work with Edge::Weight (if possible).
1385 O
<< "LangMap.GetLanguage(inFile) == \"" << Arg
<< '\"';
1392 /// EmitCaseTest1OrMoreArgs - Helper function used by
1393 /// EmitCaseConstructHandler()
1394 bool EmitCaseTest1OrMoreArgs(const std::string
& TestName
,
1396 const OptionDescriptions
& OptDescs
,
1398 CheckNumberOfArguments(d
, 1);
1399 return EmitCaseTest1Arg(TestName
, d
, OptDescs
, O
) ||
1400 EmitCaseTestMultipleArgs(TestName
, d
, OptDescs
, O
);
1403 /// EmitCaseTest2Args - Helper function used by EmitCaseConstructHandler().
1404 bool EmitCaseTest2Args(const std::string
& TestName
,
1406 unsigned IndentLevel
,
1407 const OptionDescriptions
& OptDescs
,
1409 CheckNumberOfArguments(d
, 2);
1410 const std::string
& OptName
= InitPtrToString(d
.getArg(0));
1411 const std::string
& OptArg
= InitPtrToString(d
.getArg(1));
1413 if (TestName
== "parameter_equals") {
1414 const OptionDescription
& OptDesc
= OptDescs
.FindParameter(OptName
);
1415 O
<< OptDesc
.GenVariableName() << " == \"" << OptArg
<< "\"";
1418 else if (TestName
== "element_in_list") {
1419 const OptionDescription
& OptDesc
= OptDescs
.FindParameterList(OptName
);
1420 const std::string
& VarName
= OptDesc
.GenVariableName();
1421 O
<< "std::find(" << VarName
<< ".begin(),\n";
1422 O
.indent(IndentLevel
+ Indent1
)
1423 << VarName
<< ".end(), \""
1424 << OptArg
<< "\") != " << VarName
<< ".end()";
1431 // Forward declaration.
1432 // EmitLogicalOperationTest and EmitCaseTest are mutually recursive.
1433 void EmitCaseTest(const DagInit
& d
, unsigned IndentLevel
,
1434 const OptionDescriptions
& OptDescs
,
1437 /// EmitLogicalOperationTest - Helper function used by
1438 /// EmitCaseConstructHandler.
1439 void EmitLogicalOperationTest(const DagInit
& d
, const char* LogicOp
,
1440 unsigned IndentLevel
,
1441 const OptionDescriptions
& OptDescs
,
1444 for (unsigned i
= 0, NumArgs
= d
.getNumArgs(); i
< NumArgs
; ++i
) {
1445 const DagInit
& InnerTest
= InitPtrToDag(d
.getArg(i
));
1446 EmitCaseTest(InnerTest
, IndentLevel
, OptDescs
, O
);
1447 if (i
!= NumArgs
- 1) {
1449 O
.indent(IndentLevel
+ Indent1
) << ' ' << LogicOp
<< " (";
1457 void EmitLogicalNot(const DagInit
& d
, unsigned IndentLevel
,
1458 const OptionDescriptions
& OptDescs
, raw_ostream
& O
)
1460 CheckNumberOfArguments(d
, 1);
1461 const DagInit
& InnerTest
= InitPtrToDag(d
.getArg(0));
1463 EmitCaseTest(InnerTest
, IndentLevel
, OptDescs
, O
);
1467 /// EmitCaseTest - Helper function used by EmitCaseConstructHandler.
1468 void EmitCaseTest(const DagInit
& d
, unsigned IndentLevel
,
1469 const OptionDescriptions
& OptDescs
,
1471 const std::string
& TestName
= GetOperatorName(d
);
1473 if (TestName
== "and")
1474 EmitLogicalOperationTest(d
, "&&", IndentLevel
, OptDescs
, O
);
1475 else if (TestName
== "or")
1476 EmitLogicalOperationTest(d
, "||", IndentLevel
, OptDescs
, O
);
1477 else if (TestName
== "not")
1478 EmitLogicalNot(d
, IndentLevel
, OptDescs
, O
);
1479 else if (EmitCaseTest0Args(TestName
, O
))
1481 else if (EmitCaseTest1OrMoreArgs(TestName
, d
, OptDescs
, O
))
1483 else if (EmitCaseTest2Args(TestName
, d
, IndentLevel
, OptDescs
, O
))
1486 throw "Unknown test '" + TestName
+ "' used in the 'case' construct!";
1490 /// EmitCaseTestCallback - Callback used by EmitCaseConstructHandler.
1491 class EmitCaseTestCallback
{
1493 const OptionDescriptions
& OptDescs_
;
1497 EmitCaseTestCallback(bool EmitElseIf
,
1498 const OptionDescriptions
& OptDescs
, raw_ostream
& O
)
1499 : EmitElseIf_(EmitElseIf
), OptDescs_(OptDescs
), O_(O
)
1502 void operator()(const DagInit
& Test
, unsigned IndentLevel
, bool FirstTest
)
1504 if (GetOperatorName(Test
) == "default") {
1505 O_
.indent(IndentLevel
) << "else {\n";
1508 O_
.indent(IndentLevel
)
1509 << ((!FirstTest
&& EmitElseIf_
) ? "else if (" : "if (");
1510 EmitCaseTest(Test
, IndentLevel
, OptDescs_
, O_
);
1516 /// EmitCaseStatementCallback - Callback used by EmitCaseConstructHandler.
1517 template <typename F
>
1518 class EmitCaseStatementCallback
{
1523 EmitCaseStatementCallback(F Callback
, raw_ostream
& O
)
1524 : Callback_(Callback
), O_(O
)
1527 void operator() (const Init
* Statement
, unsigned IndentLevel
) {
1528 // Is this a nested 'case'?
1529 bool IsCase
= dynamic_cast<const DagInit
*>(Statement
) &&
1530 GetOperatorName(static_cast<const DagInit
&>(*Statement
)) == "case";
1532 // If so, ignore it, it is handled by our caller, WalkCase.
1534 if (typeid(*Statement
) == typeid(ListInit
)) {
1535 const ListInit
& DagList
= *static_cast<const ListInit
*>(Statement
);
1536 for (ListInit::const_iterator B
= DagList
.begin(), E
= DagList
.end();
1538 Callback_(*B
, (IndentLevel
+ Indent1
), O_
);
1541 Callback_(Statement
, (IndentLevel
+ Indent1
), O_
);
1544 O_
.indent(IndentLevel
) << "}\n";
1549 /// EmitCaseConstructHandler - Emit code that handles the 'case'
1550 /// construct. Takes a function object that should emit code for every case
1551 /// clause. Implemented on top of WalkCase.
1552 /// Callback's type is void F(const Init* Statement, unsigned IndentLevel,
1553 /// raw_ostream& O).
1554 /// EmitElseIf parameter controls the type of condition that is emitted ('if
1555 /// (..) {..} else if (..) {} .. else {..}' vs. 'if (..) {..} if(..) {..}
1557 template <typename F
>
1558 void EmitCaseConstructHandler(const Init
* Case
, unsigned IndentLevel
,
1559 F Callback
, bool EmitElseIf
,
1560 const OptionDescriptions
& OptDescs
,
1562 WalkCase(Case
, EmitCaseTestCallback(EmitElseIf
, OptDescs
, O
),
1563 EmitCaseStatementCallback
<F
>(Callback
, O
), IndentLevel
);
1566 /// TokenizeCmdLine - converts from
1567 /// "$CALL(HookName, 'Arg1', 'Arg2')/path -arg1 -arg2" to
1568 /// ["$CALL(", "HookName", "Arg1", "Arg2", ")/path", "-arg1", "-arg2"].
1569 void TokenizeCmdLine(const std::string
& CmdLine
, StrVector
& Out
) {
1570 const char* Delimiters
= " \t\n\v\f\r";
1572 { Normal
, SpecialCommand
, InsideSpecialCommand
, InsideQuotationMarks
}
1575 if (CmdLine
.empty())
1579 std::string::size_type B
= CmdLine
.find_first_not_of(Delimiters
),
1582 for (; B
!= E
; ++B
) {
1583 char cur_ch
= CmdLine
[B
];
1587 if (cur_ch
== '$') {
1588 cur_st
= SpecialCommand
;
1591 if (OneOf(Delimiters
, cur_ch
)) {
1593 B
= CmdLine
.find_first_not_of(Delimiters
, B
);
1594 if (B
== std::string::npos
) {
1605 case SpecialCommand
:
1606 if (OneOf(Delimiters
, cur_ch
)) {
1611 if (cur_ch
== '(') {
1613 cur_st
= InsideSpecialCommand
;
1618 case InsideSpecialCommand
:
1619 if (OneOf(Delimiters
, cur_ch
)) {
1622 if (cur_ch
== '\'') {
1623 cur_st
= InsideQuotationMarks
;
1627 if (cur_ch
== ')') {
1631 if (cur_ch
== ',') {
1637 case InsideQuotationMarks
:
1638 if (cur_ch
== '\'') {
1639 cur_st
= InsideSpecialCommand
;
1645 Out
.back().push_back(cur_ch
);
1649 /// SubstituteCall - Given "$CALL(HookName, [Arg1 [, Arg2 [...]]])", output
1650 /// "hooks::HookName([Arg1 [, Arg2 [, ...]]])". Helper function used by
1651 /// SubstituteSpecialCommands().
1652 StrVector::const_iterator
1653 SubstituteCall (StrVector::const_iterator Pos
,
1654 StrVector::const_iterator End
,
1655 bool IsJoin
, raw_ostream
& O
)
1657 const char* errorMessage
= "Syntax error in $CALL invocation!";
1658 CheckedIncrement(Pos
, End
, errorMessage
);
1659 const std::string
& CmdName
= *Pos
;
1662 throw "$CALL invocation: empty argument list!";
1665 O
<< CmdName
<< "(";
1668 bool firstIteration
= true;
1670 CheckedIncrement(Pos
, End
, errorMessage
);
1671 const std::string
& Arg
= *Pos
;
1672 assert(Arg
.size() != 0);
1678 firstIteration
= false;
1682 if (Arg
== "$INFILE") {
1684 throw "$CALL(Hook, $INFILE) can't be used with a Join tool!";
1686 O
<< "inFile.c_str()";
1689 O
<< '"' << Arg
<< '"';
1698 /// SubstituteEnv - Given '$ENV(VAR_NAME)', output 'getenv("VAR_NAME")'. Helper
1699 /// function used by SubstituteSpecialCommands().
1700 StrVector::const_iterator
1701 SubstituteEnv (StrVector::const_iterator Pos
,
1702 StrVector::const_iterator End
, raw_ostream
& O
)
1704 const char* errorMessage
= "Syntax error in $ENV invocation!";
1705 CheckedIncrement(Pos
, End
, errorMessage
);
1706 const std::string
& EnvName
= *Pos
;
1709 throw "$ENV invocation: empty argument list!";
1711 O
<< "checkCString(std::getenv(\"";
1715 CheckedIncrement(Pos
, End
, errorMessage
);
1720 /// SubstituteSpecialCommands - Given an invocation of $CALL or $ENV, output
1721 /// handler code. Helper function used by EmitCmdLineVecFill().
1722 StrVector::const_iterator
1723 SubstituteSpecialCommands (StrVector::const_iterator Pos
,
1724 StrVector::const_iterator End
,
1725 bool IsJoin
, raw_ostream
& O
)
1728 const std::string
& cmd
= *Pos
;
1730 // Perform substitution.
1731 if (cmd
== "$CALL") {
1732 Pos
= SubstituteCall(Pos
, End
, IsJoin
, O
);
1734 else if (cmd
== "$ENV") {
1735 Pos
= SubstituteEnv(Pos
, End
, O
);
1738 throw "Unknown special command: " + cmd
;
1741 // Handle '$CMD(ARG)/additional/text'.
1742 const std::string
& Leftover
= *Pos
;
1743 assert(Leftover
.at(0) == ')');
1744 if (Leftover
.size() != 1)
1745 O
<< " + std::string(\"" << (Leftover
.c_str() + 1) << "\")";
1750 /// EmitCmdLineVecFill - Emit code that fills in the command line
1751 /// vector. Helper function used by EmitGenerateActionMethod().
1752 void EmitCmdLineVecFill(const Init
* CmdLine
, const std::string
& ToolName
,
1753 bool IsJoin
, unsigned IndentLevel
,
1756 TokenizeCmdLine(InitPtrToString(CmdLine
), StrVec
);
1759 throw "Tool '" + ToolName
+ "' has empty command line!";
1761 StrVector::const_iterator B
= StrVec
.begin(), E
= StrVec
.end();
1763 // Emit the command itself.
1764 assert(!StrVec
[0].empty());
1765 O
.indent(IndentLevel
) << "cmd = ";
1766 if (StrVec
[0][0] == '$') {
1767 B
= SubstituteSpecialCommands(B
, E
, IsJoin
, O
);
1771 O
<< '"' << StrVec
[0] << '"';
1776 // Go through the command arguments.
1778 for (; B
!= E
; ++B
) {
1779 const std::string
& cmd
= *B
;
1781 assert(!cmd
.empty());
1782 O
.indent(IndentLevel
);
1784 if (cmd
.at(0) == '$') {
1785 O
<< "vec.push_back(std::make_pair(0, ";
1786 B
= SubstituteSpecialCommands(B
, E
, IsJoin
, O
);
1790 O
<< "vec.push_back(std::make_pair(0, \"" << cmd
<< "\"));\n";
1796 /// EmitForEachListElementCycleHeader - Emit common code for iterating through
1797 /// all elements of a list. Helper function used by
1798 /// EmitForwardOptionPropertyHandlingCode.
1799 void EmitForEachListElementCycleHeader (const OptionDescription
& D
,
1800 unsigned IndentLevel
,
1802 unsigned IndentLevel1
= IndentLevel
+ Indent1
;
1804 O
.indent(IndentLevel
)
1805 << "for (" << D
.GenTypeDeclaration()
1806 << "::iterator B = " << D
.GenVariableName() << ".begin(),\n";
1807 O
.indent(IndentLevel
)
1808 << "E = " << D
.GenVariableName() << ".end(); B != E;) {\n";
1809 O
.indent(IndentLevel1
) << "unsigned pos = " << D
.GenVariableName()
1810 << ".getPosition(B - " << D
.GenVariableName()
1814 /// EmitForwardOptionPropertyHandlingCode - Helper function used to
1815 /// implement EmitActionHandler. Emits code for
1816 /// handling the (forward) and (forward_as) option properties.
1817 void EmitForwardOptionPropertyHandlingCode (const OptionDescription
& D
,
1818 unsigned IndentLevel
,
1819 const std::string
& NewName
,
1821 const std::string
& Name
= NewName
.empty()
1824 unsigned IndentLevel1
= IndentLevel
+ Indent1
;
1827 case OptionType::Switch
:
1828 O
.indent(IndentLevel
)
1829 << "vec.push_back(std::make_pair(" << D
.GenVariableName()
1830 << ".getPosition(), \"" << Name
<< "\"));\n";
1832 case OptionType::Parameter
:
1833 O
.indent(IndentLevel
) << "vec.push_back(std::make_pair("
1834 << D
.GenVariableName()
1835 <<".getPosition(), \"" << Name
;
1837 if (!D
.isForwardNotSplit()) {
1839 O
.indent(IndentLevel
) << "vec.push_back(std::make_pair("
1840 << D
.GenVariableName() << ".getPosition(), "
1841 << D
.GenVariableName() << "));\n";
1844 O
<< "=\" + " << D
.GenVariableName() << "));\n";
1847 case OptionType::Prefix
:
1848 O
.indent(IndentLevel
) << "vec.push_back(std::make_pair("
1849 << D
.GenVariableName() << ".getPosition(), \""
1851 << D
.GenVariableName() << "));\n";
1853 case OptionType::PrefixList
:
1854 EmitForEachListElementCycleHeader(D
, IndentLevel
, O
);
1855 O
.indent(IndentLevel1
) << "vec.push_back(std::make_pair(pos, \""
1856 << Name
<< "\" + " << "*B));\n";
1857 O
.indent(IndentLevel1
) << "++B;\n";
1859 for (int i
= 1, j
= D
.MultiVal
; i
< j
; ++i
) {
1860 O
.indent(IndentLevel1
) << "vec.push_back(std::make_pair(pos, *B));\n";
1861 O
.indent(IndentLevel1
) << "++B;\n";
1864 O
.indent(IndentLevel
) << "}\n";
1866 case OptionType::ParameterList
:
1867 EmitForEachListElementCycleHeader(D
, IndentLevel
, O
);
1868 O
.indent(IndentLevel1
) << "vec.push_back(std::make_pair(pos, \""
1869 << Name
<< "\"));\n";
1871 for (int i
= 0, j
= D
.MultiVal
; i
< j
; ++i
) {
1872 O
.indent(IndentLevel1
) << "vec.push_back(std::make_pair(pos, *B));\n";
1873 O
.indent(IndentLevel1
) << "++B;\n";
1876 O
.indent(IndentLevel
) << "}\n";
1878 case OptionType::SwitchList
:
1879 EmitForEachListElementCycleHeader(D
, IndentLevel
, O
);
1880 O
.indent(IndentLevel1
) << "vec.push_back(std::make_pair(pos, \""
1881 << Name
<< "\"));\n";
1882 O
.indent(IndentLevel1
) << "++B;\n";
1883 O
.indent(IndentLevel
) << "}\n";
1885 case OptionType::Alias
:
1887 throw "Aliases are not allowed in tool option descriptions!";
1891 /// ActionHandlingCallbackBase - Base class of EmitActionHandlersCallback and
1892 /// EmitPreprocessOptionsCallback.
1893 struct ActionHandlingCallbackBase
1896 void onErrorDag(const DagInit
& d
,
1897 unsigned IndentLevel
, raw_ostream
& O
) const
1899 O
.indent(IndentLevel
)
1901 << (d
.getNumArgs() >= 1 ? InitPtrToString(d
.getArg(0)) : "Unknown error!")
1903 O
.indent(IndentLevel
) << "return 1;\n";
1906 void onWarningDag(const DagInit
& d
,
1907 unsigned IndentLevel
, raw_ostream
& O
) const
1909 CheckNumberOfArguments(d
, 1);
1910 O
.indent(IndentLevel
) << "llvm::errs() << \""
1911 << InitPtrToString(d
.getArg(0)) << "\";\n";
1916 /// EmitActionHandlersCallback - Emit code that handles actions. Used by
1917 /// EmitGenerateActionMethod() as an argument to EmitCaseConstructHandler().
1918 class EmitActionHandlersCallback
;
1920 typedef void (EmitActionHandlersCallback::* EmitActionHandlersCallbackHandler
)
1921 (const DagInit
&, unsigned, raw_ostream
&) const;
1923 class EmitActionHandlersCallback
:
1924 public ActionHandlingCallbackBase
,
1925 public HandlerTable
<EmitActionHandlersCallbackHandler
>
1927 typedef EmitActionHandlersCallbackHandler Handler
;
1929 const OptionDescriptions
& OptDescs
;
1931 /// EmitHookInvocation - Common code for hook invocation from actions. Used by
1932 /// onAppendCmd and onOutputSuffix.
1933 void EmitHookInvocation(const std::string
& Str
,
1934 const char* BlockOpen
, const char* BlockClose
,
1935 unsigned IndentLevel
, raw_ostream
& O
) const
1938 TokenizeCmdLine(Str
, Out
);
1940 for (StrVector::const_iterator B
= Out
.begin(), E
= Out
.end();
1942 const std::string
& cmd
= *B
;
1944 O
.indent(IndentLevel
) << BlockOpen
;
1946 if (cmd
.at(0) == '$')
1947 B
= SubstituteSpecialCommands(B
, E
, /* IsJoin = */ true, O
);
1949 O
<< '"' << cmd
<< '"';
1955 void onAppendCmd (const DagInit
& Dag
,
1956 unsigned IndentLevel
, raw_ostream
& O
) const
1958 CheckNumberOfArguments(Dag
, 1);
1959 this->EmitHookInvocation(InitPtrToString(Dag
.getArg(0)),
1960 "vec.push_back(std::make_pair(65536, ", "));\n",
1964 void onForward (const DagInit
& Dag
,
1965 unsigned IndentLevel
, raw_ostream
& O
) const
1967 CheckNumberOfArguments(Dag
, 1);
1968 const std::string
& Name
= InitPtrToString(Dag
.getArg(0));
1969 EmitForwardOptionPropertyHandlingCode(OptDescs
.FindOption(Name
),
1970 IndentLevel
, "", O
);
1973 void onForwardAs (const DagInit
& Dag
,
1974 unsigned IndentLevel
, raw_ostream
& O
) const
1976 CheckNumberOfArguments(Dag
, 2);
1977 const std::string
& Name
= InitPtrToString(Dag
.getArg(0));
1978 const std::string
& NewName
= InitPtrToString(Dag
.getArg(1));
1979 EmitForwardOptionPropertyHandlingCode(OptDescs
.FindOption(Name
),
1980 IndentLevel
, NewName
, O
);
1983 void onForwardValue (const DagInit
& Dag
,
1984 unsigned IndentLevel
, raw_ostream
& O
) const
1986 CheckNumberOfArguments(Dag
, 1);
1987 const std::string
& Name
= InitPtrToString(Dag
.getArg(0));
1988 const OptionDescription
& D
= OptDescs
.FindParameterListOrParameter(Name
);
1990 if (D
.isSwitchList()) {
1991 throw std::runtime_error
1992 ("forward_value is not allowed with switch_list");
1995 if (D
.isParameter()) {
1996 O
.indent(IndentLevel
) << "vec.push_back(std::make_pair("
1997 << D
.GenVariableName() << ".getPosition(), "
1998 << D
.GenVariableName() << "));\n";
2001 O
.indent(IndentLevel
) << "for (" << D
.GenTypeDeclaration()
2002 << "::iterator B = " << D
.GenVariableName()
2004 O
.indent(IndentLevel
+ Indent1
) << " E = " << D
.GenVariableName()
2005 << ".end(); B != E; ++B)\n";
2006 O
.indent(IndentLevel
) << "{\n";
2007 O
.indent(IndentLevel
+ Indent1
)
2008 << "unsigned pos = " << D
.GenVariableName()
2009 << ".getPosition(B - " << D
.GenVariableName()
2011 O
.indent(IndentLevel
+ Indent1
)
2012 << "vec.push_back(std::make_pair(pos, *B));\n";
2013 O
.indent(IndentLevel
) << "}\n";
2017 void onForwardTransformedValue (const DagInit
& Dag
,
2018 unsigned IndentLevel
, raw_ostream
& O
) const
2020 CheckNumberOfArguments(Dag
, 2);
2021 const std::string
& Name
= InitPtrToString(Dag
.getArg(0));
2022 const std::string
& Hook
= InitPtrToString(Dag
.getArg(1));
2023 const OptionDescription
& D
= OptDescs
.FindParameterListOrParameter(Name
);
2025 O
.indent(IndentLevel
) << "vec.push_back(std::make_pair("
2026 << D
.GenVariableName() << ".getPosition("
2027 << (D
.isList() ? "0" : "") << "), "
2028 << "hooks::" << Hook
<< "(" << D
.GenVariableName()
2029 << (D
.isParameter() ? ".c_str()" : "") << ")));\n";
2032 void onNoOutFile (const DagInit
& Dag
,
2033 unsigned IndentLevel
, raw_ostream
& O
) const
2035 CheckNumberOfArguments(Dag
, 0);
2036 O
.indent(IndentLevel
) << "no_out_file = true;\n";
2039 void onOutputSuffix (const DagInit
& Dag
,
2040 unsigned IndentLevel
, raw_ostream
& O
) const
2042 CheckNumberOfArguments(Dag
, 1);
2043 this->EmitHookInvocation(InitPtrToString(Dag
.getArg(0)),
2044 "output_suffix = ", ";\n", IndentLevel
, O
);
2047 void onStopCompilation (const DagInit
& Dag
,
2048 unsigned IndentLevel
, raw_ostream
& O
) const
2050 O
.indent(IndentLevel
) << "stop_compilation = true;\n";
2054 void onUnpackValues (const DagInit
& Dag
,
2055 unsigned IndentLevel
, raw_ostream
& O
) const
2057 throw "'unpack_values' is deprecated. "
2058 "Use 'comma_separated' + 'forward_value' instead!";
2063 explicit EmitActionHandlersCallback(const OptionDescriptions
& OD
)
2066 if (!staticMembersInitialized_
) {
2067 AddHandler("error", &EmitActionHandlersCallback::onErrorDag
);
2068 AddHandler("warning", &EmitActionHandlersCallback::onWarningDag
);
2069 AddHandler("append_cmd", &EmitActionHandlersCallback::onAppendCmd
);
2070 AddHandler("forward", &EmitActionHandlersCallback::onForward
);
2071 AddHandler("forward_as", &EmitActionHandlersCallback::onForwardAs
);
2072 AddHandler("forward_value", &EmitActionHandlersCallback::onForwardValue
);
2073 AddHandler("forward_transformed_value",
2074 &EmitActionHandlersCallback::onForwardTransformedValue
);
2075 AddHandler("no_out_file",
2076 &EmitActionHandlersCallback::onNoOutFile
);
2077 AddHandler("output_suffix", &EmitActionHandlersCallback::onOutputSuffix
);
2078 AddHandler("stop_compilation",
2079 &EmitActionHandlersCallback::onStopCompilation
);
2080 AddHandler("unpack_values",
2081 &EmitActionHandlersCallback::onUnpackValues
);
2084 staticMembersInitialized_
= true;
2088 void operator()(const Init
* I
,
2089 unsigned IndentLevel
, raw_ostream
& O
) const
2091 InvokeDagInitHandler(this, I
, IndentLevel
, O
);
2095 void EmitGenerateActionMethodHeader(const ToolDescription
& D
,
2096 bool IsJoin
, bool Naked
,
2099 O
.indent(Indent1
) << "int GenerateAction(Action& Out,\n";
2102 O
.indent(Indent2
) << "const PathVector& inFiles,\n";
2104 O
.indent(Indent2
) << "const sys::Path& inFile,\n";
2106 O
.indent(Indent2
) << "const bool HasChildren,\n";
2107 O
.indent(Indent2
) << "const llvm::sys::Path& TempDir,\n";
2108 O
.indent(Indent2
) << "const InputLanguagesSet& InLangs,\n";
2109 O
.indent(Indent2
) << "const LanguageMap& LangMap) const\n";
2110 O
.indent(Indent1
) << "{\n";
2113 O
.indent(Indent2
) << "std::string cmd;\n";
2114 O
.indent(Indent2
) << "std::string out_file;\n";
2116 << "std::vector<std::pair<unsigned, std::string> > vec;\n";
2117 O
.indent(Indent2
) << "bool stop_compilation = !HasChildren;\n";
2118 O
.indent(Indent2
) << "bool no_out_file = false;\n";
2119 O
.indent(Indent2
) << "std::string output_suffix(\""
2120 << D
.OutputSuffix
<< "\");\n";
2124 // EmitGenerateActionMethod - Emit either a normal or a "join" version of the
2125 // Tool::GenerateAction() method.
2126 void EmitGenerateActionMethod (const ToolDescription
& D
,
2127 const OptionDescriptions
& OptDescs
,
2128 bool IsJoin
, raw_ostream
& O
) {
2130 EmitGenerateActionMethodHeader(D
, IsJoin
, /* Naked = */ false, O
);
2133 throw "Tool " + D
.Name
+ " has no cmd_line property!";
2135 // Process the 'command' property.
2137 EmitCmdLineVecFill(D
.CmdLine
, D
.Name
, IsJoin
, Indent2
, O
);
2140 // Process the 'actions' list of this tool.
2142 EmitCaseConstructHandler(D
.Actions
, Indent2
,
2143 EmitActionHandlersCallback(OptDescs
),
2144 false, OptDescs
, O
);
2148 if (!D
.InFileOption
.empty()) {
2150 << "vec.push_back(std::make_pair(InputFilenames.getPosition(0), \""
2151 << D
.InFileOption
<< "\");\n";
2156 << "for (PathVector::const_iterator B = inFiles.begin(),\n";
2157 O
.indent(Indent3
) << "E = inFiles.end(); B != E; ++B)\n";
2158 O
.indent(Indent2
) << "{\n";
2159 O
.indent(Indent3
) << "vec.push_back(std::make_pair("
2160 << "InputFilenames.getPosition(B - inFiles.begin()), "
2162 O
.indent(Indent2
) << "}\n";
2165 O
.indent(Indent2
) << "vec.push_back(std::make_pair("
2166 << "InputFilenames.getPosition(0), inFile.str()));\n";
2170 O
.indent(Indent2
) << "if (!no_out_file) {\n";
2171 if (!D
.OutFileOption
.empty())
2172 O
.indent(Indent3
) << "vec.push_back(std::make_pair(65536, \""
2173 << D
.OutFileOption
<< "\"));\n";
2175 O
.indent(Indent3
) << "out_file = this->OutFilename("
2176 << (IsJoin
? "sys::Path(),\n" : "inFile,\n");
2177 O
.indent(Indent4
) <<
2178 "TempDir, stop_compilation, output_suffix.c_str()).str();\n\n";
2179 O
.indent(Indent3
) << "vec.push_back(std::make_pair(65536, out_file));\n";
2181 O
.indent(Indent2
) << "}\n\n";
2183 // Handle the Sink property.
2184 std::string
SinkOption("autogenerated::");
2185 SinkOption
+= SinkOptionName
;
2187 O
.indent(Indent2
) << "if (!" << SinkOption
<< ".empty()) {\n";
2188 O
.indent(Indent3
) << "for (cl::list<std::string>::iterator B = "
2189 << SinkOption
<< ".begin(), E = " << SinkOption
2190 << ".end(); B != E; ++B)\n";
2191 O
.indent(Indent4
) << "vec.push_back(std::make_pair(" << SinkOption
2192 << ".getPosition(B - " << SinkOption
2193 << ".begin()), *B));\n";
2194 O
.indent(Indent2
) << "}\n";
2197 O
.indent(Indent2
) << "Out.Construct(cmd, this->SortArgs(vec), "
2198 << "stop_compilation, out_file);\n";
2199 O
.indent(Indent2
) << "return 0;\n";
2200 O
.indent(Indent1
) << "}\n\n";
2203 /// EmitGenerateActionMethods - Emit two GenerateAction() methods for
2204 /// a given Tool class.
2205 void EmitGenerateActionMethods (const ToolDescription
& ToolDesc
,
2206 const OptionDescriptions
& OptDescs
,
2208 if (!ToolDesc
.isJoin()) {
2209 EmitGenerateActionMethodHeader(ToolDesc
, /* IsJoin = */ true,
2210 /* Naked = */ true, O
);
2211 O
.indent(Indent2
) << "PrintError(\"" << ToolDesc
.Name
2212 << " is not a Join tool!\");\n";
2213 O
.indent(Indent2
) << "return -1;\n";
2214 O
.indent(Indent1
) << "}\n\n";
2217 EmitGenerateActionMethod(ToolDesc
, OptDescs
, true, O
);
2220 EmitGenerateActionMethod(ToolDesc
, OptDescs
, false, O
);
2223 /// EmitInOutLanguageMethods - Emit the [Input,Output]Language()
2224 /// methods for a given Tool class.
2225 void EmitInOutLanguageMethods (const ToolDescription
& D
, raw_ostream
& O
) {
2226 O
.indent(Indent1
) << "const char** InputLanguages() const {\n";
2227 O
.indent(Indent2
) << "return InputLanguages_;\n";
2228 O
.indent(Indent1
) << "}\n\n";
2230 O
.indent(Indent1
) << "const char** OutputLanguages() const {\n";
2231 O
.indent(Indent2
) << "return OutputLanguages_;\n";
2232 O
.indent(Indent1
) << "}\n\n";
2235 /// EmitNameMethod - Emit the Name() method for a given Tool class.
2236 void EmitNameMethod (const ToolDescription
& D
, raw_ostream
& O
) {
2237 O
.indent(Indent1
) << "const char* Name() const {\n";
2238 O
.indent(Indent2
) << "return \"" << D
.Name
<< "\";\n";
2239 O
.indent(Indent1
) << "}\n\n";
2242 /// EmitIsJoinMethod - Emit the IsJoin() method for a given Tool
2244 void EmitIsJoinMethod (const ToolDescription
& D
, raw_ostream
& O
) {
2245 O
.indent(Indent1
) << "bool IsJoin() const {\n";
2247 O
.indent(Indent2
) << "return true;\n";
2249 O
.indent(Indent2
) << "return false;\n";
2250 O
.indent(Indent1
) << "}\n\n";
2253 /// EmitWorksOnEmptyCallback - Callback used by EmitWorksOnEmptyMethod in
2254 /// conjunction with EmitCaseConstructHandler.
2255 void EmitWorksOnEmptyCallback (const Init
* Value
,
2256 unsigned IndentLevel
, raw_ostream
& O
) {
2257 CheckBooleanConstant(Value
);
2258 O
.indent(IndentLevel
) << "return " << Value
->getAsString() << ";\n";
2261 /// EmitWorksOnEmptyMethod - Emit the WorksOnEmpty() method for a given Tool
2263 void EmitWorksOnEmptyMethod (const ToolDescription
& D
,
2264 const OptionDescriptions
& OptDescs
,
2267 O
.indent(Indent1
) << "bool WorksOnEmpty() const {\n";
2269 O
.indent(Indent2
) << "return false;\n";
2271 EmitCaseConstructHandler(D
.OnEmpty
, Indent2
, EmitWorksOnEmptyCallback
,
2272 /*EmitElseIf = */ true, OptDescs
, O
);
2273 O
.indent(Indent1
) << "}\n\n";
2276 /// EmitStrArray - Emit definition of a 'const char**' static member
2277 /// variable. Helper used by EmitStaticMemberDefinitions();
2278 void EmitStrArray(const std::string
& Name
, const std::string
& VarName
,
2279 const StrVector
& StrVec
, raw_ostream
& O
) {
2280 O
<< "const char* " << Name
<< "::" << VarName
<< "[] = {";
2281 for (StrVector::const_iterator B
= StrVec
.begin(), E
= StrVec
.end();
2283 O
<< '\"' << *B
<< "\", ";
2287 /// EmitStaticMemberDefinitions - Emit static member definitions for a
2288 /// given Tool class.
2289 void EmitStaticMemberDefinitions(const ToolDescription
& D
, raw_ostream
& O
) {
2290 if (D
.InLanguage
.empty())
2291 throw "Tool " + D
.Name
+ " has no 'in_language' property!";
2292 if (D
.OutLanguage
.empty())
2293 throw "Tool " + D
.Name
+ " has no 'out_language' property!";
2295 EmitStrArray(D
.Name
, "InputLanguages_", D
.InLanguage
, O
);
2296 EmitStrArray(D
.Name
, "OutputLanguages_", D
.OutLanguage
, O
);
2300 /// EmitToolClassDefinition - Emit a Tool class definition.
2301 void EmitToolClassDefinition (const ToolDescription
& D
,
2302 const OptionDescriptions
& OptDescs
,
2304 if (D
.Name
== "root")
2308 O
<< "class " << D
.Name
<< " : public ";
2314 O
<< " {\nprivate:\n";
2315 O
.indent(Indent1
) << "static const char* InputLanguages_[];\n";
2316 O
.indent(Indent1
) << "static const char* OutputLanguages_[];\n\n";
2319 EmitNameMethod(D
, O
);
2320 EmitInOutLanguageMethods(D
, O
);
2321 EmitIsJoinMethod(D
, O
);
2322 EmitWorksOnEmptyMethod(D
, OptDescs
, O
);
2323 EmitGenerateActionMethods(D
, OptDescs
, O
);
2325 // Close class definition
2328 EmitStaticMemberDefinitions(D
, O
);
2332 /// EmitOptionDefinitions - Iterate over a list of option descriptions
2333 /// and emit registration code.
2334 void EmitOptionDefinitions (const OptionDescriptions
& descs
,
2335 bool HasSink
, raw_ostream
& O
)
2337 std::vector
<OptionDescription
> Aliases
;
2339 // Emit static cl::Option variables.
2340 for (OptionDescriptions::const_iterator B
= descs
.begin(),
2341 E
= descs
.end(); B
!=E
; ++B
) {
2342 const OptionDescription
& val
= B
->second
;
2344 if (val
.Type
== OptionType::Alias
) {
2345 Aliases
.push_back(val
);
2349 O
<< val
.GenTypeDeclaration() << ' '
2350 << val
.GenPlainVariableName();
2352 O
<< "(\"" << val
.Name
<< "\"\n";
2354 if (val
.Type
== OptionType::Prefix
|| val
.Type
== OptionType::PrefixList
)
2355 O
<< ", cl::Prefix";
2357 if (val
.isRequired()) {
2358 if (val
.isList() && !val
.isMultiVal())
2359 O
<< ", cl::OneOrMore";
2361 O
<< ", cl::Required";
2364 if (val
.isOptional())
2365 O
<< ", cl::Optional";
2367 if (val
.isOneOrMore())
2368 O
<< ", cl::OneOrMore";
2370 if (val
.isZeroOrMore())
2371 O
<< ", cl::ZeroOrMore";
2373 if (val
.isReallyHidden())
2374 O
<< ", cl::ReallyHidden";
2375 else if (val
.isHidden())
2376 O
<< ", cl::Hidden";
2378 if (val
.isCommaSeparated())
2379 O
<< ", cl::CommaSeparated";
2381 if (val
.MultiVal
> 1)
2382 O
<< ", cl::multi_val(" << val
.MultiVal
<< ')';
2385 const std::string
& str
= val
.InitVal
->getAsString();
2386 O
<< ", cl::init(" << str
<< ')';
2389 if (!val
.Help
.empty())
2390 O
<< ", cl::desc(\"" << val
.Help
<< "\")";
2395 // Emit the aliases (they should go after all the 'proper' options).
2396 for (std::vector
<OptionDescription
>::const_iterator
2397 B
= Aliases
.begin(), E
= Aliases
.end(); B
!= E
; ++B
) {
2398 const OptionDescription
& val
= *B
;
2400 O
<< val
.GenTypeDeclaration() << ' '
2401 << val
.GenPlainVariableName()
2402 << "(\"" << val
.Name
<< '\"';
2404 const OptionDescription
& D
= descs
.FindOption(val
.Help
);
2405 O
<< ", cl::aliasopt(" << D
.GenVariableName() << ")";
2407 O
<< ", cl::desc(\"" << "An alias for -" + val
.Help
<< "\"));\n";
2410 // Emit the sink option.
2412 O
<< "cl::list<std::string> " << SinkOptionName
<< "(cl::Sink);\n";
2417 /// EmitPreprocessOptionsCallback - Helper function passed to
2418 /// EmitCaseConstructHandler() by EmitPreprocessOptions().
2420 class EmitPreprocessOptionsCallback
;
2423 (EmitPreprocessOptionsCallback::* EmitPreprocessOptionsCallbackHandler
)
2424 (const DagInit
&, unsigned, raw_ostream
&) const;
2426 class EmitPreprocessOptionsCallback
:
2427 public ActionHandlingCallbackBase
,
2428 public HandlerTable
<EmitPreprocessOptionsCallbackHandler
>
2430 typedef EmitPreprocessOptionsCallbackHandler Handler
;
2432 (EmitPreprocessOptionsCallback::* HandlerImpl
)
2433 (const Init
*, unsigned, raw_ostream
&) const;
2435 const OptionDescriptions
& OptDescs_
;
2437 void onEachArgument(const DagInit
& d
, HandlerImpl h
,
2438 unsigned IndentLevel
, raw_ostream
& O
) const
2440 CheckNumberOfArguments(d
, 1);
2442 for (unsigned i
= 0, NumArgs
= d
.getNumArgs(); i
< NumArgs
; ++i
) {
2443 ((this)->*(h
))(d
.getArg(i
), IndentLevel
, O
);
2447 void onUnsetOptionImpl(const Init
* I
,
2448 unsigned IndentLevel
, raw_ostream
& O
) const
2450 const std::string
& OptName
= InitPtrToString(I
);
2451 const OptionDescription
& OptDesc
= OptDescs_
.FindOption(OptName
);
2453 if (OptDesc
.isSwitch()) {
2454 O
.indent(IndentLevel
) << OptDesc
.GenVariableName() << " = false;\n";
2456 else if (OptDesc
.isParameter()) {
2457 O
.indent(IndentLevel
) << OptDesc
.GenVariableName() << " = \"\";\n";
2459 else if (OptDesc
.isList()) {
2460 O
.indent(IndentLevel
) << OptDesc
.GenVariableName() << ".clear();\n";
2463 throw "Can't apply 'unset_option' to alias option '" + OptName
+ "'!";
2467 void onUnsetOption(const DagInit
& d
,
2468 unsigned IndentLevel
, raw_ostream
& O
) const
2470 this->onEachArgument(d
, &EmitPreprocessOptionsCallback::onUnsetOptionImpl
,
2474 void onSetOptionImpl(const DagInit
& D
,
2475 unsigned IndentLevel
, raw_ostream
& O
) const {
2476 CheckNumberOfArguments(D
, 2);
2478 const std::string
& OptName
= InitPtrToString(D
.getArg(0));
2479 const OptionDescription
& OptDesc
= OptDescs_
.FindOption(OptName
);
2480 const Init
* Value
= D
.getArg(1);
2482 if (OptDesc
.isList()) {
2483 const ListInit
& List
= InitPtrToList(Value
);
2485 O
.indent(IndentLevel
) << OptDesc
.GenVariableName() << ".clear();\n";
2486 for (ListInit::const_iterator B
= List
.begin(), E
= List
.end();
2488 const Init
* CurElem
= *B
;
2489 if (OptDesc
.isSwitchList())
2490 CheckBooleanConstant(CurElem
);
2492 O
.indent(IndentLevel
)
2493 << OptDesc
.GenVariableName() << ".push_back(\""
2494 << (OptDesc
.isSwitchList() ? CurElem
->getAsString()
2495 : InitPtrToString(CurElem
))
2499 else if (OptDesc
.isSwitch()) {
2500 CheckBooleanConstant(Value
);
2501 O
.indent(IndentLevel
) << OptDesc
.GenVariableName()
2502 << " = " << Value
->getAsString() << ";\n";
2504 else if (OptDesc
.isParameter()) {
2505 const std::string
& Str
= InitPtrToString(Value
);
2506 O
.indent(IndentLevel
) << OptDesc
.GenVariableName()
2507 << " = \"" << Str
<< "\";\n";
2510 throw "Can't apply 'set_option' to alias option '" + OptName
+ "'!";
2514 void onSetSwitch(const Init
* I
,
2515 unsigned IndentLevel
, raw_ostream
& O
) const {
2516 const std::string
& OptName
= InitPtrToString(I
);
2517 const OptionDescription
& OptDesc
= OptDescs_
.FindOption(OptName
);
2519 if (OptDesc
.isSwitch())
2520 O
.indent(IndentLevel
) << OptDesc
.GenVariableName() << " = true;\n";
2522 throw "set_option: -" + OptName
+ " is not a switch option!";
2525 void onSetOption(const DagInit
& d
,
2526 unsigned IndentLevel
, raw_ostream
& O
) const
2528 CheckNumberOfArguments(d
, 1);
2530 // 2-argument form: (set_option "A", true), (set_option "B", "C"),
2531 // (set_option "D", ["E", "F"])
2532 if (d
.getNumArgs() == 2) {
2533 const OptionDescription
& OptDesc
=
2534 OptDescs_
.FindOption(InitPtrToString(d
.getArg(0)));
2535 const Init
* Opt2
= d
.getArg(1);
2537 if (!OptDesc
.isSwitch() || typeid(*Opt2
) != typeid(StringInit
)) {
2538 this->onSetOptionImpl(d
, IndentLevel
, O
);
2543 // Multiple argument form: (set_option "A"), (set_option "B", "C", "D")
2544 this->onEachArgument(d
, &EmitPreprocessOptionsCallback::onSetSwitch
,
2550 EmitPreprocessOptionsCallback(const OptionDescriptions
& OptDescs
)
2551 : OptDescs_(OptDescs
)
2553 if (!staticMembersInitialized_
) {
2554 AddHandler("error", &EmitPreprocessOptionsCallback::onErrorDag
);
2555 AddHandler("warning", &EmitPreprocessOptionsCallback::onWarningDag
);
2556 AddHandler("unset_option", &EmitPreprocessOptionsCallback::onUnsetOption
);
2557 AddHandler("set_option", &EmitPreprocessOptionsCallback::onSetOption
);
2559 staticMembersInitialized_
= true;
2563 void operator()(const Init
* I
,
2564 unsigned IndentLevel
, raw_ostream
& O
) const
2566 InvokeDagInitHandler(this, I
, IndentLevel
, O
);
2571 /// EmitPreprocessOptions - Emit the PreprocessOptions() function.
2572 void EmitPreprocessOptions (const RecordKeeper
& Records
,
2573 const OptionDescriptions
& OptDecs
, raw_ostream
& O
)
2575 O
<< "int PreprocessOptions () {\n";
2577 const RecordVector
& OptionPreprocessors
=
2578 Records
.getAllDerivedDefinitions("OptionPreprocessor");
2580 for (RecordVector::const_iterator B
= OptionPreprocessors
.begin(),
2581 E
= OptionPreprocessors
.end(); B
!=E
; ++B
) {
2582 DagInit
* Case
= (*B
)->getValueAsDag("preprocessor");
2583 EmitCaseConstructHandler(Case
, Indent1
,
2584 EmitPreprocessOptionsCallback(OptDecs
),
2589 O
.indent(Indent1
) << "return 0;\n";
2593 class DoEmitPopulateLanguageMap
;
2594 typedef void (DoEmitPopulateLanguageMap::* DoEmitPopulateLanguageMapHandler
)
2597 class DoEmitPopulateLanguageMap
2598 : public HandlerTable
<DoEmitPopulateLanguageMapHandler
>
2605 explicit DoEmitPopulateLanguageMap (raw_ostream
& O
) : O_(O
) {
2606 if (!staticMembersInitialized_
) {
2607 AddHandler("lang_to_suffixes",
2608 &DoEmitPopulateLanguageMap::onLangToSuffixes
);
2610 staticMembersInitialized_
= true;
2614 void operator() (Init
* I
) {
2615 InvokeDagInitHandler(this, I
);
2620 void onLangToSuffixes (const DagInit
& d
) {
2621 CheckNumberOfArguments(d
, 2);
2623 const std::string
& Lang
= InitPtrToString(d
.getArg(0));
2624 Init
* Suffixes
= d
.getArg(1);
2626 // Second argument to lang_to_suffixes is either a single string...
2627 if (typeid(*Suffixes
) == typeid(StringInit
)) {
2628 O_
.indent(Indent1
) << "langMap[\"" << InitPtrToString(Suffixes
)
2629 << "\"] = \"" << Lang
<< "\";\n";
2631 // ...or a list of strings.
2633 const ListInit
& Lst
= InitPtrToList(Suffixes
);
2634 assert(Lst
.size() != 0);
2635 for (ListInit::const_iterator B
= Lst
.begin(), E
= Lst
.end();
2637 O_
.indent(Indent1
) << "langMap[\"" << InitPtrToString(*B
)
2638 << "\"] = \"" << Lang
<< "\";\n";
2645 /// EmitPopulateLanguageMap - Emit the PopulateLanguageMap() function.
2646 void EmitPopulateLanguageMap (const RecordKeeper
& Records
, raw_ostream
& O
)
2648 O
<< "int PopulateLanguageMap (LanguageMap& langMap) {\n";
2650 // For each LanguageMap:
2651 const RecordVector
& LangMaps
=
2652 Records
.getAllDerivedDefinitions("LanguageMap");
2654 // Call DoEmitPopulateLanguageMap.
2655 for (RecordVector::const_iterator B
= LangMaps
.begin(),
2656 E
= LangMaps
.end(); B
!=E
; ++B
) {
2657 ListInit
* LangMap
= (*B
)->getValueAsListInit("map");
2658 std::for_each(LangMap
->begin(), LangMap
->end(),
2659 DoEmitPopulateLanguageMap(O
));
2663 O
.indent(Indent1
) << "return 0;\n";
2667 /// EmitEdgePropertyHandlerCallback - Emits code that handles edge
2668 /// properties. Helper function passed to EmitCaseConstructHandler() by
2669 /// EmitEdgeClass().
2670 void EmitEdgePropertyHandlerCallback (const Init
* i
, unsigned IndentLevel
,
2672 const DagInit
& d
= InitPtrToDag(i
);
2673 const std::string
& OpName
= GetOperatorName(d
);
2675 if (OpName
== "inc_weight") {
2676 O
.indent(IndentLevel
) << "ret += ";
2678 else if (OpName
== "error") {
2679 CheckNumberOfArguments(d
, 1);
2680 O
.indent(IndentLevel
) << "PrintError(\""
2681 << InitPtrToString(d
.getArg(0))
2683 O
.indent(IndentLevel
) << "return -1;\n";
2687 throw "Unknown operator in edge properties list: '" + OpName
+ "'!"
2688 "\nOnly 'inc_weight', 'dec_weight' and 'error' are allowed.";
2691 if (d
.getNumArgs() > 0)
2692 O
<< InitPtrToInt(d
.getArg(0)) << ";\n";
2698 /// EmitEdgeClass - Emit a single Edge# class.
2699 void EmitEdgeClass (unsigned N
, const std::string
& Target
,
2700 const DagInit
& Case
, const OptionDescriptions
& OptDescs
,
2703 // Class constructor.
2704 O
<< "class Edge" << N
<< ": public Edge {\n"
2706 O
.indent(Indent1
) << "Edge" << N
<< "() : Edge(\"" << Target
2709 // Function Weight().
2711 << "int Weight(const InputLanguagesSet& InLangs) const {\n";
2712 O
.indent(Indent2
) << "unsigned ret = 0;\n";
2714 // Handle the 'case' construct.
2715 EmitCaseConstructHandler(&Case
, Indent2
, EmitEdgePropertyHandlerCallback
,
2716 false, OptDescs
, O
);
2718 O
.indent(Indent2
) << "return ret;\n";
2719 O
.indent(Indent1
) << "}\n\n};\n\n";
2722 /// EmitEdgeClasses - Emit Edge* classes that represent graph edges.
2723 void EmitEdgeClasses (const DagVector
& EdgeVector
,
2724 const OptionDescriptions
& OptDescs
,
2727 for (DagVector::const_iterator B
= EdgeVector
.begin(),
2728 E
= EdgeVector
.end(); B
!= E
; ++B
) {
2729 const DagInit
& Edge
= **B
;
2730 const std::string
& Name
= GetOperatorName(Edge
);
2732 if (Name
== "optional_edge") {
2733 assert(IsOptionalEdge(Edge
));
2734 const std::string
& NodeB
= InitPtrToString(Edge
.getArg(1));
2736 const DagInit
& Weight
= InitPtrToDag(Edge
.getArg(2));
2737 EmitEdgeClass(i
, NodeB
, Weight
, OptDescs
, O
);
2739 else if (Name
!= "edge") {
2740 throw "Unknown edge class: '" + Name
+ "'!";
2747 /// EmitPopulateCompilationGraph - Emit the PopulateCompilationGraph() function.
2748 void EmitPopulateCompilationGraph (const DagVector
& EdgeVector
,
2749 const ToolDescriptions
& ToolDescs
,
2752 O
<< "int PopulateCompilationGraph (CompilationGraph& G) {\n";
2754 for (ToolDescriptions::const_iterator B
= ToolDescs
.begin(),
2755 E
= ToolDescs
.end(); B
!= E
; ++B
)
2756 O
.indent(Indent1
) << "G.insertNode(new " << (*B
)->Name
<< "());\n";
2763 for (DagVector::const_iterator B
= EdgeVector
.begin(),
2764 E
= EdgeVector
.end(); B
!= E
; ++B
) {
2765 const DagInit
& Edge
= **B
;
2766 const std::string
& NodeA
= InitPtrToString(Edge
.getArg(0));
2767 const std::string
& NodeB
= InitPtrToString(Edge
.getArg(1));
2769 O
.indent(Indent1
) << "if (int ret = G.insertEdge(\"" << NodeA
<< "\", ";
2771 if (IsOptionalEdge(Edge
))
2772 O
<< "new Edge" << i
<< "()";
2774 O
<< "new SimpleEdge(\"" << NodeB
<< "\")";
2777 O
.indent(Indent2
) << "return ret;\n";
2783 O
.indent(Indent1
) << "return 0;\n";
2787 /// HookInfo - Information about the hook type and number of arguments.
2790 // A hook can either have a single parameter of type std::vector<std::string>,
2791 // or NumArgs parameters of type const char*.
2792 enum HookType
{ ListHook
, ArgHook
};
2797 HookInfo() : Type(ArgHook
), NumArgs(1)
2800 HookInfo(HookType T
) : Type(T
), NumArgs(1)
2803 HookInfo(unsigned N
) : Type(ArgHook
), NumArgs(N
)
2807 typedef llvm::StringMap
<HookInfo
> HookInfoMap
;
2809 /// ExtractHookNames - Extract the hook names from all instances of
2810 /// $CALL(HookName) in the provided command line string/action. Helper
2811 /// function used by FillInHookNames().
2812 class ExtractHookNames
{
2813 HookInfoMap
& HookNames_
;
2814 const OptionDescriptions
& OptDescs_
;
2816 ExtractHookNames(HookInfoMap
& HookNames
, const OptionDescriptions
& OptDescs
)
2817 : HookNames_(HookNames
), OptDescs_(OptDescs
)
2820 void onAction (const DagInit
& Dag
) {
2821 const std::string
& Name
= GetOperatorName(Dag
);
2823 if (Name
== "forward_transformed_value") {
2824 CheckNumberOfArguments(Dag
, 2);
2825 const std::string
& OptName
= InitPtrToString(Dag
.getArg(0));
2826 const std::string
& HookName
= InitPtrToString(Dag
.getArg(1));
2827 const OptionDescription
& D
=
2828 OptDescs_
.FindParameterListOrParameter(OptName
);
2830 HookNames_
[HookName
] = HookInfo(D
.isList() ? HookInfo::ListHook
2831 : HookInfo::ArgHook
);
2833 else if (Name
== "append_cmd" || Name
== "output_suffix") {
2834 CheckNumberOfArguments(Dag
, 1);
2835 this->onCmdLine(InitPtrToString(Dag
.getArg(0)));
2839 void onCmdLine(const std::string
& Cmd
) {
2841 TokenizeCmdLine(Cmd
, cmds
);
2843 for (StrVector::const_iterator B
= cmds
.begin(), E
= cmds
.end();
2845 const std::string
& cmd
= *B
;
2847 if (cmd
== "$CALL") {
2848 unsigned NumArgs
= 0;
2849 CheckedIncrement(B
, E
, "Syntax error in $CALL invocation!");
2850 const std::string
& HookName
= *B
;
2852 if (HookName
.at(0) == ')')
2853 throw "$CALL invoked with no arguments!";
2855 while (++B
!= E
&& B
->at(0) != ')') {
2859 HookInfoMap::const_iterator H
= HookNames_
.find(HookName
);
2861 if (H
!= HookNames_
.end() && H
->second
.NumArgs
!= NumArgs
&&
2862 H
->second
.Type
!= HookInfo::ArgHook
)
2863 throw "Overloading of hooks is not allowed. Overloaded hook: "
2866 HookNames_
[HookName
] = HookInfo(NumArgs
);
2871 void operator()(const Init
* Arg
) {
2873 // We're invoked on an action (either a dag or a dag list).
2874 if (typeid(*Arg
) == typeid(DagInit
)) {
2875 const DagInit
& Dag
= InitPtrToDag(Arg
);
2876 this->onAction(Dag
);
2879 else if (typeid(*Arg
) == typeid(ListInit
)) {
2880 const ListInit
& List
= InitPtrToList(Arg
);
2881 for (ListInit::const_iterator B
= List
.begin(), E
= List
.end(); B
!= E
;
2883 const DagInit
& Dag
= InitPtrToDag(*B
);
2884 this->onAction(Dag
);
2889 // We're invoked on a command line string.
2890 this->onCmdLine(InitPtrToString(Arg
));
2893 void operator()(const Init
* Statement
, unsigned) {
2894 this->operator()(Statement
);
2898 /// FillInHookNames - Actually extract the hook names from all command
2899 /// line strings. Helper function used by EmitHookDeclarations().
2900 void FillInHookNames(const ToolDescriptions
& ToolDescs
,
2901 const OptionDescriptions
& OptDescs
,
2902 HookInfoMap
& HookNames
)
2904 // For all tool descriptions:
2905 for (ToolDescriptions::const_iterator B
= ToolDescs
.begin(),
2906 E
= ToolDescs
.end(); B
!= E
; ++B
) {
2907 const ToolDescription
& D
= *(*B
);
2909 // Look for 'forward_transformed_value' in 'actions'.
2911 WalkCase(D
.Actions
, Id(), ExtractHookNames(HookNames
, OptDescs
));
2913 // Look for hook invocations in 'cmd_line'.
2916 if (dynamic_cast<StringInit
*>(D
.CmdLine
))
2917 // This is a string.
2918 ExtractHookNames(HookNames
, OptDescs
).operator()(D
.CmdLine
);
2920 // This is a 'case' construct.
2921 WalkCase(D
.CmdLine
, Id(), ExtractHookNames(HookNames
, OptDescs
));
2925 /// EmitHookDeclarations - Parse CmdLine fields of all the tool
2926 /// property records and emit hook function declaration for each
2927 /// instance of $CALL(HookName).
2928 void EmitHookDeclarations(const ToolDescriptions
& ToolDescs
,
2929 const OptionDescriptions
& OptDescs
, raw_ostream
& O
) {
2930 HookInfoMap HookNames
;
2932 FillInHookNames(ToolDescs
, OptDescs
, HookNames
);
2933 if (HookNames
.empty())
2936 for (HookInfoMap::const_iterator B
= HookNames
.begin(),
2937 E
= HookNames
.end(); B
!= E
; ++B
) {
2938 const char* HookName
= B
->first();
2939 const HookInfo
& Info
= B
->second
;
2941 O
.indent(Indent1
) << "std::string " << HookName
<< "(";
2943 if (Info
.Type
== HookInfo::ArgHook
) {
2944 for (unsigned i
= 0, j
= Info
.NumArgs
; i
< j
; ++i
) {
2945 O
<< "const char* Arg" << i
<< (i
+1 == j
? "" : ", ");
2949 O
<< "const std::vector<std::string>& Arg";
2956 /// EmitIncludes - Emit necessary #include directives and some
2957 /// additional declarations.
2958 void EmitIncludes(raw_ostream
& O
) {
2959 O
<< "#include \"llvm/CompilerDriver/BuiltinOptions.h\"\n"
2960 << "#include \"llvm/CompilerDriver/CompilationGraph.h\"\n"
2961 << "#include \"llvm/CompilerDriver/Error.h\"\n"
2962 << "#include \"llvm/CompilerDriver/Tool.h\"\n\n"
2964 << "#include \"llvm/Support/CommandLine.h\"\n"
2965 << "#include \"llvm/Support/raw_ostream.h\"\n\n"
2967 << "#include <algorithm>\n"
2968 << "#include <cstdlib>\n"
2969 << "#include <iterator>\n"
2970 << "#include <stdexcept>\n\n"
2972 << "using namespace llvm;\n"
2973 << "using namespace llvmc;\n\n"
2975 << "inline const char* checkCString(const char* s)\n"
2976 << "{ return s == NULL ? \"\" : s; }\n\n";
2980 /// DriverData - Holds all information about the driver.
2982 OptionDescriptions OptDescs
;
2983 ToolDescriptions ToolDescs
;
2988 /// HasSink - Go through the list of tool descriptions and check if
2989 /// there are any with the 'sink' property set.
2990 bool HasSink(const ToolDescriptions
& ToolDescs
) {
2991 for (ToolDescriptions::const_iterator B
= ToolDescs
.begin(),
2992 E
= ToolDescs
.end(); B
!= E
; ++B
)
2999 /// CollectDriverData - Collect compilation graph edges, tool properties and
3000 /// option properties from the parse tree.
3001 void CollectDriverData (const RecordKeeper
& Records
, DriverData
& Data
) {
3002 // Collect option properties.
3003 const RecordVector
& OptionLists
=
3004 Records
.getAllDerivedDefinitions("OptionList");
3005 CollectOptionDescriptions(OptionLists
, Data
.OptDescs
);
3007 // Collect tool properties.
3008 const RecordVector
& Tools
= Records
.getAllDerivedDefinitions("Tool");
3009 CollectToolDescriptions(Tools
, Data
.ToolDescs
);
3010 Data
.HasSink
= HasSink(Data
.ToolDescs
);
3012 // Collect compilation graph edges.
3013 const RecordVector
& CompilationGraphs
=
3014 Records
.getAllDerivedDefinitions("CompilationGraph");
3015 FillInEdgeVector(CompilationGraphs
, Data
.Edges
);
3018 /// CheckDriverData - Perform some sanity checks on the collected data.
3019 void CheckDriverData(DriverData
& Data
) {
3020 // Filter out all tools not mentioned in the compilation graph.
3021 FilterNotInGraph(Data
.Edges
, Data
.ToolDescs
);
3023 // Typecheck the compilation graph.
3024 TypecheckGraph(Data
.Edges
, Data
.ToolDescs
);
3026 // Check that there are no options without side effects (specified
3027 // only in the OptionList).
3028 CheckForSuperfluousOptions(Data
.Edges
, Data
.ToolDescs
, Data
.OptDescs
);
3031 void EmitDriverCode(const DriverData
& Data
, raw_ostream
& O
) {
3032 // Emit file header.
3035 // Emit global option registration code.
3036 O
<< "namespace llvmc {\n"
3037 << "namespace autogenerated {\n\n";
3038 EmitOptionDefinitions(Data
.OptDescs
, Data
.HasSink
, O
);
3039 O
<< "} // End namespace autogenerated.\n"
3040 << "} // End namespace llvmc.\n\n";
3042 // Emit hook declarations.
3043 O
<< "namespace hooks {\n";
3044 EmitHookDeclarations(Data
.ToolDescs
, Data
.OptDescs
, O
);
3045 O
<< "} // End namespace hooks.\n\n";
3047 O
<< "namespace {\n\n";
3048 O
<< "using namespace llvmc::autogenerated;\n\n";
3050 // Emit Tool classes.
3051 for (ToolDescriptions::const_iterator B
= Data
.ToolDescs
.begin(),
3052 E
= Data
.ToolDescs
.end(); B
!=E
; ++B
)
3053 EmitToolClassDefinition(*(*B
), Data
.OptDescs
, O
);
3055 // Emit Edge# classes.
3056 EmitEdgeClasses(Data
.Edges
, Data
.OptDescs
, O
);
3058 O
<< "} // End anonymous namespace.\n\n";
3060 O
<< "namespace llvmc {\n";
3061 O
<< "namespace autogenerated {\n\n";
3063 // Emit PreprocessOptions() function.
3064 EmitPreprocessOptions(Records
, Data
.OptDescs
, O
);
3066 // Emit PopulateLanguageMap() function
3067 // (language map maps from file extensions to language names).
3068 EmitPopulateLanguageMap(Records
, O
);
3070 // Emit PopulateCompilationGraph() function.
3071 EmitPopulateCompilationGraph(Data
.Edges
, Data
.ToolDescs
, O
);
3073 O
<< "} // End namespace autogenerated.\n";
3074 O
<< "} // End namespace llvmc.\n\n";
3080 // End of anonymous namespace
3083 /// run - The back-end entry point.
3084 void LLVMCConfigurationEmitter::run (raw_ostream
&O
) {
3088 CollectDriverData(Records
, Data
);
3089 CheckDriverData(Data
);
3091 this->EmitSourceFileHeader("llvmc-based driver: auto-generated code", O
);
3092 EmitDriverCode(Data
, O
);
3094 } catch (std::exception
& Error
) {
3095 throw Error
.what() + std::string(" - usually this means a syntax error.");