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 bool InitPtrToBool(const Init
* ptr
) {
79 const DefInit
& val
= dynamic_cast<const DefInit
&>(*ptr
);
80 const std::string
& str
= val
.getAsString();
85 else if (str
== "false") {
89 throw "Incorrect boolean value: '" + str
+
90 "': must be either 'true' or 'false'";
96 const std::string
& InitPtrToString(const Init
* ptr
) {
97 const StringInit
& val
= dynamic_cast<const StringInit
&>(*ptr
);
98 return val
.getValue();
101 const ListInit
& InitPtrToList(const Init
* ptr
) {
102 const ListInit
& val
= dynamic_cast<const ListInit
&>(*ptr
);
106 const DagInit
& InitPtrToDag(const Init
* ptr
) {
107 const DagInit
& val
= dynamic_cast<const DagInit
&>(*ptr
);
111 const std::string
GetOperatorName(const DagInit
& D
) {
112 return D
.getOperator()->getAsString();
115 /// CheckBooleanConstant - Check that the provided value is a boolean constant.
116 void CheckBooleanConstant(const Init
* I
) {
120 // CheckNumberOfArguments - Ensure that the number of args in d is
121 // greater than or equal to min_arguments, otherwise throw an exception.
122 void CheckNumberOfArguments (const DagInit
& d
, unsigned minArgs
) {
123 if (d
.getNumArgs() < minArgs
)
124 throw GetOperatorName(d
) + ": too few arguments!";
127 // EscapeVariableName - Escape commas and other symbols not allowed
128 // in the C++ variable names. Makes it possible to use options named
129 // like "Wa," (useful for prefix options).
130 std::string
EscapeVariableName (const std::string
& Var
) {
132 for (unsigned i
= 0; i
!= Var
.size(); ++i
) {
133 char cur_char
= Var
[i
];
134 if (cur_char
== ',') {
137 else if (cur_char
== '+') {
140 else if (cur_char
== '-') {
144 ret
.push_back(cur_char
);
150 /// EscapeQuotes - Replace '"' with '\"'.
151 std::string
EscapeQuotes (const std::string
& Var
) {
153 for (unsigned i
= 0; i
!= Var
.size(); ++i
) {
154 char cur_char
= Var
[i
];
155 if (cur_char
== '"') {
159 ret
.push_back(cur_char
);
165 /// OneOf - Does the input string contain this character?
166 bool OneOf(const char* lst
, char c
) {
174 template <class I
, class S
>
175 void CheckedIncrement(I
& P
, I E
, S ErrorString
) {
181 //===----------------------------------------------------------------------===//
182 /// Back-end specific code
185 /// OptionType - One of six different option types. See the
186 /// documentation for detailed description of differences.
187 namespace OptionType
{
189 enum OptionType
{ Alias
, Switch
, SwitchList
,
190 Parameter
, ParameterList
, Prefix
, PrefixList
};
192 bool IsAlias(OptionType t
) {
196 bool IsList (OptionType t
) {
197 return (t
== SwitchList
|| t
== ParameterList
|| t
== PrefixList
);
200 bool IsSwitch (OptionType t
) {
201 return (t
== Switch
);
204 bool IsSwitchList (OptionType t
) {
205 return (t
== SwitchList
);
208 bool IsParameter (OptionType t
) {
209 return (t
== Parameter
|| t
== Prefix
);
214 OptionType::OptionType
stringToOptionType(const std::string
& T
) {
215 if (T
== "alias_option")
216 return OptionType::Alias
;
217 else if (T
== "switch_option")
218 return OptionType::Switch
;
219 else if (T
== "switch_list_option")
220 return OptionType::SwitchList
;
221 else if (T
== "parameter_option")
222 return OptionType::Parameter
;
223 else if (T
== "parameter_list_option")
224 return OptionType::ParameterList
;
225 else if (T
== "prefix_option")
226 return OptionType::Prefix
;
227 else if (T
== "prefix_list_option")
228 return OptionType::PrefixList
;
230 throw "Unknown option type: " + T
+ '!';
233 namespace OptionDescriptionFlags
{
234 enum OptionDescriptionFlags
{ Required
= 0x1, Hidden
= 0x2,
235 ReallyHidden
= 0x4, OneOrMore
= 0x8,
236 Optional
= 0x10, CommaSeparated
= 0x20,
237 ForwardNotSplit
= 0x40, ZeroOrMore
= 0x80 };
240 /// OptionDescription - Represents data contained in a single
241 /// OptionList entry.
242 struct OptionDescription
{
243 OptionType::OptionType Type
;
250 OptionDescription(OptionType::OptionType t
= OptionType::Switch
,
251 const std::string
& n
= "",
252 const std::string
& h
= DefaultHelpString
)
253 : Type(t
), Name(n
), Flags(0x0), Help(h
), MultiVal(1), InitVal(0)
256 /// GenTypeDeclaration - Returns the C++ variable type of this
258 const char* GenTypeDeclaration() const;
260 /// GenVariableName - Returns the variable name used in the
261 /// generated C++ code.
262 std::string
GenVariableName() const
263 { return "autogenerated::" + GenOptionType() + EscapeVariableName(Name
); }
265 /// GenPlainVariableName - Returns the variable name without the namespace
267 std::string
GenPlainVariableName() const
268 { return GenOptionType() + EscapeVariableName(Name
); }
270 /// Merge - Merge two option descriptions.
271 void Merge (const OptionDescription
& other
);
273 /// CheckConsistency - Check that the flags are consistent.
274 void CheckConsistency() const;
276 // Misc convenient getters/setters.
278 bool isAlias() const;
280 bool isMultiVal() const;
282 bool isCommaSeparated() const;
283 void setCommaSeparated();
285 bool isForwardNotSplit() const;
286 void setForwardNotSplit();
288 bool isRequired() const;
291 bool isOneOrMore() const;
294 bool isZeroOrMore() const;
295 void setZeroOrMore();
297 bool isOptional() const;
300 bool isHidden() const;
303 bool isReallyHidden() const;
304 void setReallyHidden();
306 bool isSwitch() const
307 { return OptionType::IsSwitch(this->Type
); }
309 bool isSwitchList() const
310 { return OptionType::IsSwitchList(this->Type
); }
312 bool isParameter() const
313 { return OptionType::IsParameter(this->Type
); }
316 { return OptionType::IsList(this->Type
); }
318 bool isParameterList() const
319 { return (OptionType::IsList(this->Type
)
320 && !OptionType::IsSwitchList(this->Type
)); }
324 // GenOptionType - Helper function used by GenVariableName().
325 std::string
GenOptionType() const;
328 void OptionDescription::CheckConsistency() const {
331 i
+= this->isRequired();
332 i
+= this->isOptional();
333 i
+= this->isOneOrMore();
334 i
+= this->isZeroOrMore();
337 throw "Only one of (required), (optional), (one_or_more) or "
338 "(zero_or_more) properties is allowed!";
342 void OptionDescription::Merge (const OptionDescription
& other
)
344 if (other
.Type
!= Type
)
345 throw "Conflicting definitions for the option " + Name
+ "!";
347 if (Help
== other
.Help
|| Help
== DefaultHelpString
)
349 else if (other
.Help
!= DefaultHelpString
) {
350 llvm::errs() << "Warning: several different help strings"
351 " defined for option " + Name
+ "\n";
354 Flags
|= other
.Flags
;
357 bool OptionDescription::isAlias() const {
358 return OptionType::IsAlias(this->Type
);
361 bool OptionDescription::isMultiVal() const {
365 bool OptionDescription::isCommaSeparated() const {
366 return Flags
& OptionDescriptionFlags::CommaSeparated
;
368 void OptionDescription::setCommaSeparated() {
369 Flags
|= OptionDescriptionFlags::CommaSeparated
;
372 bool OptionDescription::isForwardNotSplit() const {
373 return Flags
& OptionDescriptionFlags::ForwardNotSplit
;
375 void OptionDescription::setForwardNotSplit() {
376 Flags
|= OptionDescriptionFlags::ForwardNotSplit
;
379 bool OptionDescription::isRequired() const {
380 return Flags
& OptionDescriptionFlags::Required
;
382 void OptionDescription::setRequired() {
383 Flags
|= OptionDescriptionFlags::Required
;
386 bool OptionDescription::isOneOrMore() const {
387 return Flags
& OptionDescriptionFlags::OneOrMore
;
389 void OptionDescription::setOneOrMore() {
390 Flags
|= OptionDescriptionFlags::OneOrMore
;
393 bool OptionDescription::isZeroOrMore() const {
394 return Flags
& OptionDescriptionFlags::ZeroOrMore
;
396 void OptionDescription::setZeroOrMore() {
397 Flags
|= OptionDescriptionFlags::ZeroOrMore
;
400 bool OptionDescription::isOptional() const {
401 return Flags
& OptionDescriptionFlags::Optional
;
403 void OptionDescription::setOptional() {
404 Flags
|= OptionDescriptionFlags::Optional
;
407 bool OptionDescription::isHidden() const {
408 return Flags
& OptionDescriptionFlags::Hidden
;
410 void OptionDescription::setHidden() {
411 Flags
|= OptionDescriptionFlags::Hidden
;
414 bool OptionDescription::isReallyHidden() const {
415 return Flags
& OptionDescriptionFlags::ReallyHidden
;
417 void OptionDescription::setReallyHidden() {
418 Flags
|= OptionDescriptionFlags::ReallyHidden
;
421 const char* OptionDescription::GenTypeDeclaration() const {
423 case OptionType::Alias
:
425 case OptionType::PrefixList
:
426 case OptionType::ParameterList
:
427 return "cl::list<std::string>";
428 case OptionType::Switch
:
429 return "cl::opt<bool>";
430 case OptionType::SwitchList
:
431 return "cl::list<bool>";
432 case OptionType::Parameter
:
433 case OptionType::Prefix
:
435 return "cl::opt<std::string>";
439 std::string
OptionDescription::GenOptionType() const {
441 case OptionType::Alias
:
443 case OptionType::PrefixList
:
444 case OptionType::ParameterList
:
446 case OptionType::Switch
:
448 case OptionType::SwitchList
:
449 return "SwitchList_";
450 case OptionType::Prefix
:
451 case OptionType::Parameter
:
457 /// OptionDescriptions - An OptionDescription array plus some helper
459 class OptionDescriptions
{
460 typedef StringMap
<OptionDescription
> container_type
;
462 /// Descriptions - A list of OptionDescriptions.
463 container_type Descriptions
;
466 /// FindOption - exception-throwing wrapper for find().
467 const OptionDescription
& FindOption(const std::string
& OptName
) const;
469 // Wrappers for FindOption that throw an exception in case the option has a
471 const OptionDescription
& FindSwitch(const std::string
& OptName
) const;
472 const OptionDescription
& FindParameter(const std::string
& OptName
) const;
473 const OptionDescription
& FindParameterList(const std::string
& OptName
) const;
474 const OptionDescription
&
475 FindListOrParameter(const std::string
& OptName
) const;
476 const OptionDescription
&
477 FindParameterListOrParameter(const std::string
& OptName
) const;
479 /// insertDescription - Insert new OptionDescription into
480 /// OptionDescriptions list
481 void InsertDescription (const OptionDescription
& o
);
483 // Support for STL-style iteration
484 typedef container_type::const_iterator const_iterator
;
485 const_iterator
begin() const { return Descriptions
.begin(); }
486 const_iterator
end() const { return Descriptions
.end(); }
489 const OptionDescription
&
490 OptionDescriptions::FindOption(const std::string
& OptName
) const {
491 const_iterator I
= Descriptions
.find(OptName
);
492 if (I
!= Descriptions
.end())
495 throw OptName
+ ": no such option!";
498 const OptionDescription
&
499 OptionDescriptions::FindSwitch(const std::string
& OptName
) const {
500 const OptionDescription
& OptDesc
= this->FindOption(OptName
);
501 if (!OptDesc
.isSwitch())
502 throw OptName
+ ": incorrect option type - should be a switch!";
506 const OptionDescription
&
507 OptionDescriptions::FindParameterList(const std::string
& OptName
) const {
508 const OptionDescription
& OptDesc
= this->FindOption(OptName
);
509 if (!OptDesc
.isList() || OptDesc
.isSwitchList())
510 throw OptName
+ ": incorrect option type - should be a parameter list!";
514 const OptionDescription
&
515 OptionDescriptions::FindParameter(const std::string
& OptName
) const {
516 const OptionDescription
& OptDesc
= this->FindOption(OptName
);
517 if (!OptDesc
.isParameter())
518 throw OptName
+ ": incorrect option type - should be a parameter!";
522 const OptionDescription
&
523 OptionDescriptions::FindListOrParameter(const std::string
& OptName
) const {
524 const OptionDescription
& OptDesc
= this->FindOption(OptName
);
525 if (!OptDesc
.isList() && !OptDesc
.isParameter())
527 + ": incorrect option type - should be a list or parameter!";
531 const OptionDescription
&
532 OptionDescriptions::FindParameterListOrParameter
533 (const std::string
& OptName
) const {
534 const OptionDescription
& OptDesc
= this->FindOption(OptName
);
535 if ((!OptDesc
.isList() && !OptDesc
.isParameter()) || OptDesc
.isSwitchList())
537 + ": incorrect option type - should be a parameter list or parameter!";
541 void OptionDescriptions::InsertDescription (const OptionDescription
& o
) {
542 container_type::iterator I
= Descriptions
.find(o
.Name
);
543 if (I
!= Descriptions
.end()) {
544 OptionDescription
& D
= I
->second
;
548 Descriptions
[o
.Name
] = o
;
552 /// HandlerTable - A base class for function objects implemented as
553 /// 'tables of handlers'.
554 template <typename Handler
>
557 // Implementation details.
559 /// HandlerMap - A map from property names to property handlers
560 typedef StringMap
<Handler
> HandlerMap
;
562 static HandlerMap Handlers_
;
563 static bool staticMembersInitialized_
;
567 Handler
GetHandler (const std::string
& HandlerName
) const {
568 typename
HandlerMap::iterator method
= Handlers_
.find(HandlerName
);
570 if (method
!= Handlers_
.end()) {
571 Handler h
= method
->second
;
575 throw "No handler found for property " + HandlerName
+ "!";
579 void AddHandler(const char* Property
, Handler H
) {
580 Handlers_
[Property
] = H
;
585 template <class Handler
, class FunctionObject
>
586 Handler
GetHandler(FunctionObject
* Obj
, const DagInit
& Dag
) {
587 const std::string
& HandlerName
= GetOperatorName(Dag
);
588 return Obj
->GetHandler(HandlerName
);
591 template <class FunctionObject
>
592 void InvokeDagInitHandler(FunctionObject
* Obj
, Init
* I
) {
593 typedef void (FunctionObject::*Handler
) (const DagInit
&);
595 const DagInit
& Dag
= InitPtrToDag(I
);
596 Handler h
= GetHandler
<Handler
>(Obj
, Dag
);
601 template <class FunctionObject
>
602 void InvokeDagInitHandler(const FunctionObject
* const Obj
,
603 const Init
* I
, unsigned IndentLevel
, raw_ostream
& O
)
605 typedef void (FunctionObject::*Handler
)
606 (const DagInit
&, unsigned IndentLevel
, raw_ostream
& O
) const;
608 const DagInit
& Dag
= InitPtrToDag(I
);
609 Handler h
= GetHandler
<Handler
>(Obj
, Dag
);
611 ((Obj
)->*(h
))(Dag
, IndentLevel
, O
);
614 template <typename H
>
615 typename HandlerTable
<H
>::HandlerMap HandlerTable
<H
>::Handlers_
;
617 template <typename H
>
618 bool HandlerTable
<H
>::staticMembersInitialized_
= false;
621 /// CollectOptionProperties - Function object for iterating over an
622 /// option property list.
623 class CollectOptionProperties
;
624 typedef void (CollectOptionProperties::* CollectOptionPropertiesHandler
)
627 class CollectOptionProperties
628 : public HandlerTable
<CollectOptionPropertiesHandler
>
632 /// optDescs_ - OptionDescriptions table. This is where the
633 /// information is stored.
634 OptionDescription
& optDesc_
;
638 explicit CollectOptionProperties(OptionDescription
& OD
)
641 if (!staticMembersInitialized_
) {
642 AddHandler("help", &CollectOptionProperties::onHelp
);
643 AddHandler("hidden", &CollectOptionProperties::onHidden
);
644 AddHandler("init", &CollectOptionProperties::onInit
);
645 AddHandler("multi_val", &CollectOptionProperties::onMultiVal
);
646 AddHandler("one_or_more", &CollectOptionProperties::onOneOrMore
);
647 AddHandler("zero_or_more", &CollectOptionProperties::onZeroOrMore
);
648 AddHandler("really_hidden", &CollectOptionProperties::onReallyHidden
);
649 AddHandler("required", &CollectOptionProperties::onRequired
);
650 AddHandler("optional", &CollectOptionProperties::onOptional
);
651 AddHandler("comma_separated", &CollectOptionProperties::onCommaSeparated
);
652 AddHandler("forward_not_split",
653 &CollectOptionProperties::onForwardNotSplit
);
655 staticMembersInitialized_
= true;
659 /// operator() - Just forwards to the corresponding property
661 void operator() (Init
* I
) {
662 InvokeDagInitHandler(this, I
);
667 /// Option property handlers --
668 /// Methods that handle option properties such as (help) or (hidden).
670 void onHelp (const DagInit
& d
) {
671 CheckNumberOfArguments(d
, 1);
672 optDesc_
.Help
= EscapeQuotes(InitPtrToString(d
.getArg(0)));
675 void onHidden (const DagInit
& d
) {
676 CheckNumberOfArguments(d
, 0);
677 optDesc_
.setHidden();
680 void onReallyHidden (const DagInit
& d
) {
681 CheckNumberOfArguments(d
, 0);
682 optDesc_
.setReallyHidden();
685 void onCommaSeparated (const DagInit
& d
) {
686 CheckNumberOfArguments(d
, 0);
687 if (!optDesc_
.isParameterList())
688 throw "'comma_separated' is valid only on parameter list options!";
689 optDesc_
.setCommaSeparated();
692 void onForwardNotSplit (const DagInit
& d
) {
693 CheckNumberOfArguments(d
, 0);
694 if (!optDesc_
.isParameter())
695 throw "'forward_not_split' is valid only for parameter options!";
696 optDesc_
.setForwardNotSplit();
699 void onRequired (const DagInit
& d
) {
700 CheckNumberOfArguments(d
, 0);
702 optDesc_
.setRequired();
703 optDesc_
.CheckConsistency();
706 void onInit (const DagInit
& d
) {
707 CheckNumberOfArguments(d
, 1);
708 Init
* i
= d
.getArg(0);
709 const std::string
& str
= i
->getAsString();
711 bool correct
= optDesc_
.isParameter() && dynamic_cast<StringInit
*>(i
);
712 correct
|= (optDesc_
.isSwitch() && (str
== "true" || str
== "false"));
715 throw "Incorrect usage of the 'init' option property!";
717 optDesc_
.InitVal
= i
;
720 void onOneOrMore (const DagInit
& d
) {
721 CheckNumberOfArguments(d
, 0);
723 optDesc_
.setOneOrMore();
724 optDesc_
.CheckConsistency();
727 void onZeroOrMore (const DagInit
& d
) {
728 CheckNumberOfArguments(d
, 0);
730 if (optDesc_
.isList())
731 llvm::errs() << "Warning: specifying the 'zero_or_more' property "
732 "on a list option has no effect.\n";
734 optDesc_
.setZeroOrMore();
735 optDesc_
.CheckConsistency();
738 void onOptional (const DagInit
& d
) {
739 CheckNumberOfArguments(d
, 0);
741 if (!optDesc_
.isList())
742 llvm::errs() << "Warning: specifying the 'optional' property"
743 "on a non-list option has no effect.\n";
745 optDesc_
.setOptional();
746 optDesc_
.CheckConsistency();
749 void onMultiVal (const DagInit
& d
) {
750 CheckNumberOfArguments(d
, 1);
751 int val
= InitPtrToInt(d
.getArg(0));
753 throw "Error in the 'multi_val' property: "
754 "the value must be greater than 1!";
755 if (!optDesc_
.isParameterList())
756 throw "The multi_val property is valid only on list options!";
757 optDesc_
.MultiVal
= val
;
762 /// AddOption - A function object that is applied to every option
763 /// description. Used by CollectOptionDescriptions.
766 OptionDescriptions
& OptDescs_
;
769 explicit AddOption(OptionDescriptions
& OD
) : OptDescs_(OD
)
772 void operator()(const Init
* i
) {
773 const DagInit
& d
= InitPtrToDag(i
);
774 CheckNumberOfArguments(d
, 1);
776 const OptionType::OptionType Type
=
777 stringToOptionType(GetOperatorName(d
));
778 const std::string
& Name
= InitPtrToString(d
.getArg(0));
780 OptionDescription
OD(Type
, Name
);
782 CheckNumberOfArguments(d
, 2);
784 // Alias option store the aliased option name in the 'Help' field and do not
785 // have any properties.
787 OD
.Help
= InitPtrToString(d
.getArg(1));
790 processOptionProperties(d
, OD
);
793 // Switch options are ZeroOrMore by default.
795 if (!(OD
.isOptional() || OD
.isOneOrMore() || OD
.isRequired()))
799 OptDescs_
.InsertDescription(OD
);
803 /// processOptionProperties - Go through the list of option
804 /// properties and call a corresponding handler for each.
805 static void processOptionProperties (const DagInit
& d
, OptionDescription
& o
) {
806 CheckNumberOfArguments(d
, 2);
807 DagInit::const_arg_iterator B
= d
.arg_begin();
808 // Skip the first argument: it's always the option name.
810 std::for_each(B
, d
.arg_end(), CollectOptionProperties(o
));
815 /// CollectOptionDescriptions - Collects option properties from all
817 void CollectOptionDescriptions (const RecordVector
& V
,
818 OptionDescriptions
& OptDescs
)
820 // For every OptionList:
821 for (RecordVector::const_iterator B
= V
.begin(), E
= V
.end(); B
!=E
; ++B
)
823 // Throws an exception if the value does not exist.
824 ListInit
* PropList
= (*B
)->getValueAsListInit("options");
826 // For every option description in this list: invoke AddOption.
827 std::for_each(PropList
->begin(), PropList
->end(), AddOption(OptDescs
));
831 // Tool information record
833 namespace ToolFlags
{
834 enum ToolFlags
{ Join
= 0x1, Sink
= 0x2 };
837 struct ToolDescription
: public RefCountedBase
<ToolDescription
> {
841 StrVector InLanguage
;
842 std::string InFileOption
;
843 std::string OutFileOption
;
844 StrVector OutLanguage
;
845 std::string OutputSuffix
;
849 // Various boolean properties
850 void setSink() { Flags
|= ToolFlags::Sink
; }
851 bool isSink() const { return Flags
& ToolFlags::Sink
; }
852 void setJoin() { Flags
|= ToolFlags::Join
; }
853 bool isJoin() const { return Flags
& ToolFlags::Join
; }
855 // Default ctor here is needed because StringMap can only store
856 // DefaultConstructible objects
857 ToolDescription (const std::string
&n
= "")
858 : Name(n
), CmdLine(0), Actions(0), OutFileOption("-o"),
863 /// ToolDescriptions - A list of Tool information records.
864 typedef std::vector
<IntrusiveRefCntPtr
<ToolDescription
> > ToolDescriptions
;
867 /// CollectToolProperties - Function object for iterating over a list of
868 /// tool property records.
870 class CollectToolProperties
;
871 typedef void (CollectToolProperties::* CollectToolPropertiesHandler
)
874 class CollectToolProperties
: public HandlerTable
<CollectToolPropertiesHandler
>
878 /// toolDesc_ - Properties of the current Tool. This is where the
879 /// information is stored.
880 ToolDescription
& toolDesc_
;
884 explicit CollectToolProperties (ToolDescription
& d
)
887 if (!staticMembersInitialized_
) {
889 AddHandler("actions", &CollectToolProperties::onActions
);
890 AddHandler("command", &CollectToolProperties::onCommand
);
891 AddHandler("in_language", &CollectToolProperties::onInLanguage
);
892 AddHandler("join", &CollectToolProperties::onJoin
);
893 AddHandler("out_language", &CollectToolProperties::onOutLanguage
);
895 AddHandler("out_file_option", &CollectToolProperties::onOutFileOption
);
896 AddHandler("in_file_option", &CollectToolProperties::onInFileOption
);
898 AddHandler("output_suffix", &CollectToolProperties::onOutputSuffix
);
899 AddHandler("sink", &CollectToolProperties::onSink
);
900 AddHandler("works_on_empty", &CollectToolProperties::onWorksOnEmpty
);
902 staticMembersInitialized_
= true;
906 void operator() (Init
* I
) {
907 InvokeDagInitHandler(this, I
);
912 /// Property handlers --
913 /// Functions that extract information about tool properties from
914 /// DAG representation.
916 void onActions (const DagInit
& d
) {
917 CheckNumberOfArguments(d
, 1);
918 Init
* Case
= d
.getArg(0);
919 if (typeid(*Case
) != typeid(DagInit
) ||
920 GetOperatorName(static_cast<DagInit
&>(*Case
)) != "case")
921 throw "The argument to (actions) should be a 'case' construct!";
922 toolDesc_
.Actions
= Case
;
925 void onCommand (const DagInit
& d
) {
926 CheckNumberOfArguments(d
, 1);
927 toolDesc_
.CmdLine
= d
.getArg(0);
930 /// onInOutLanguage - Common implementation of on{In,Out}Language().
931 void onInOutLanguage (const DagInit
& d
, StrVector
& OutVec
) {
932 CheckNumberOfArguments(d
, 1);
934 // Copy strings to the output vector.
935 for (unsigned i
= 0, NumArgs
= d
.getNumArgs(); i
< NumArgs
; ++i
) {
936 OutVec
.push_back(InitPtrToString(d
.getArg(i
)));
939 // Remove duplicates.
940 std::sort(OutVec
.begin(), OutVec
.end());
941 StrVector::iterator newE
= std::unique(OutVec
.begin(), OutVec
.end());
942 OutVec
.erase(newE
, OutVec
.end());
946 void onInLanguage (const DagInit
& d
) {
947 this->onInOutLanguage(d
, toolDesc_
.InLanguage
);
950 void onJoin (const DagInit
& d
) {
951 bool isReallyJoin
= false;
953 if (d
.getNumArgs() == 0) {
957 Init
* I
= d
.getArg(0);
958 isReallyJoin
= InitPtrToBool(I
);
961 // Is this *really* a join tool? We allow (join false) for generating two
962 // tool descriptions from a single generic one.
963 // TOFIX: come up with a cleaner solution.
969 void onOutLanguage (const DagInit
& d
) {
970 this->onInOutLanguage(d
, toolDesc_
.OutLanguage
);
973 void onOutFileOption (const DagInit
& d
) {
974 CheckNumberOfArguments(d
, 1);
975 toolDesc_
.OutFileOption
= InitPtrToString(d
.getArg(0));
978 void onInFileOption (const DagInit
& d
) {
979 CheckNumberOfArguments(d
, 1);
980 toolDesc_
.InFileOption
= InitPtrToString(d
.getArg(0));
983 void onOutputSuffix (const DagInit
& d
) {
984 CheckNumberOfArguments(d
, 1);
985 toolDesc_
.OutputSuffix
= InitPtrToString(d
.getArg(0));
988 void onSink (const DagInit
& d
) {
989 CheckNumberOfArguments(d
, 0);
993 void onWorksOnEmpty (const DagInit
& d
) {
994 toolDesc_
.OnEmpty
= d
.getArg(0);
999 /// CollectToolDescriptions - Gather information about tool properties
1000 /// from the parsed TableGen data (basically a wrapper for the
1001 /// CollectToolProperties function object).
1002 void CollectToolDescriptions (const RecordVector
& Tools
,
1003 ToolDescriptions
& ToolDescs
)
1005 // Iterate over a properties list of every Tool definition
1006 for (RecordVector::const_iterator B
= Tools
.begin(),
1007 E
= Tools
.end(); B
!=E
; ++B
) {
1008 const Record
* T
= *B
;
1009 // Throws an exception if the value does not exist.
1010 ListInit
* PropList
= T
->getValueAsListInit("properties");
1012 IntrusiveRefCntPtr
<ToolDescription
>
1013 ToolDesc(new ToolDescription(T
->getName()));
1015 std::for_each(PropList
->begin(), PropList
->end(),
1016 CollectToolProperties(*ToolDesc
));
1017 ToolDescs
.push_back(ToolDesc
);
1021 /// FillInEdgeVector - Merge all compilation graph definitions into
1022 /// one single edge list.
1023 void FillInEdgeVector(const RecordVector
& CompilationGraphs
,
1025 for (RecordVector::const_iterator B
= CompilationGraphs
.begin(),
1026 E
= CompilationGraphs
.end(); B
!= E
; ++B
) {
1027 const ListInit
* Edges
= (*B
)->getValueAsListInit("edges");
1029 for (ListInit::const_iterator B
= Edges
->begin(),
1030 E
= Edges
->end(); B
!= E
; ++B
) {
1031 Out
.push_back(&InitPtrToDag(*B
));
1036 /// NotInGraph - Helper function object for FilterNotInGraph.
1039 const llvm::StringSet
<>& ToolsInGraph_
;
1042 NotInGraph(const llvm::StringSet
<>& ToolsInGraph
)
1043 : ToolsInGraph_(ToolsInGraph
)
1046 bool operator()(const IntrusiveRefCntPtr
<ToolDescription
>& x
) {
1047 return (ToolsInGraph_
.count(x
->Name
) == 0);
1051 /// FilterNotInGraph - Filter out from ToolDescs all Tools not
1052 /// mentioned in the compilation graph definition.
1053 void FilterNotInGraph (const DagVector
& EdgeVector
,
1054 ToolDescriptions
& ToolDescs
) {
1056 // List all tools mentioned in the graph.
1057 llvm::StringSet
<> ToolsInGraph
;
1059 for (DagVector::const_iterator B
= EdgeVector
.begin(),
1060 E
= EdgeVector
.end(); B
!= E
; ++B
) {
1062 const DagInit
* Edge
= *B
;
1063 const std::string
& NodeA
= InitPtrToString(Edge
->getArg(0));
1064 const std::string
& NodeB
= InitPtrToString(Edge
->getArg(1));
1066 if (NodeA
!= "root")
1067 ToolsInGraph
.insert(NodeA
);
1068 ToolsInGraph
.insert(NodeB
);
1071 // Filter ToolPropertiesList.
1072 ToolDescriptions::iterator new_end
=
1073 std::remove_if(ToolDescs
.begin(), ToolDescs
.end(),
1074 NotInGraph(ToolsInGraph
));
1075 ToolDescs
.erase(new_end
, ToolDescs
.end());
1078 /// FillInToolToLang - Fills in two tables that map tool names to
1079 /// input & output language names. Helper function used by TypecheckGraph().
1080 void FillInToolToLang (const ToolDescriptions
& ToolDescs
,
1081 StringMap
<StringSet
<> >& ToolToInLang
,
1082 StringMap
<StringSet
<> >& ToolToOutLang
) {
1083 for (ToolDescriptions::const_iterator B
= ToolDescs
.begin(),
1084 E
= ToolDescs
.end(); B
!= E
; ++B
) {
1085 const ToolDescription
& D
= *(*B
);
1086 for (StrVector::const_iterator B
= D
.InLanguage
.begin(),
1087 E
= D
.InLanguage
.end(); B
!= E
; ++B
)
1088 ToolToInLang
[D
.Name
].insert(*B
);
1089 for (StrVector::const_iterator B
= D
.OutLanguage
.begin(),
1090 E
= D
.OutLanguage
.end(); B
!= E
; ++B
)
1091 ToolToOutLang
[D
.Name
].insert(*B
);
1095 /// Intersect - Is set intersection non-empty?
1096 bool Intersect (const StringSet
<>& S1
, const StringSet
<>& S2
) {
1097 for (StringSet
<>::const_iterator B
= S1
.begin(), E
= S1
.end(); B
!= E
; ++B
) {
1098 if (S2
.count(B
->first()) != 0)
1104 /// TypecheckGraph - Check that names for output and input languages
1105 /// on all edges do match.
1106 void TypecheckGraph (const DagVector
& EdgeVector
,
1107 const ToolDescriptions
& ToolDescs
) {
1108 StringMap
<StringSet
<> > ToolToInLang
;
1109 StringMap
<StringSet
<> > ToolToOutLang
;
1111 FillInToolToLang(ToolDescs
, ToolToInLang
, ToolToOutLang
);
1113 for (DagVector::const_iterator B
= EdgeVector
.begin(),
1114 E
= EdgeVector
.end(); B
!= E
; ++B
) {
1115 const DagInit
* Edge
= *B
;
1116 const std::string
& NodeA
= InitPtrToString(Edge
->getArg(0));
1117 const std::string
& NodeB
= InitPtrToString(Edge
->getArg(1));
1118 StringMap
<StringSet
<> >::iterator IA
= ToolToOutLang
.find(NodeA
);
1119 StringMap
<StringSet
<> >::iterator IB
= ToolToInLang
.find(NodeB
);
1121 if (NodeB
== "root")
1122 throw "Edges back to the root are not allowed!";
1124 if (NodeA
!= "root") {
1125 if (IA
== ToolToOutLang
.end())
1126 throw NodeA
+ ": no output language defined!";
1127 if (IB
== ToolToInLang
.end())
1128 throw NodeB
+ ": no input language defined!";
1130 if (!Intersect(IA
->second
, IB
->second
)) {
1131 throw "Edge " + NodeA
+ "->" + NodeB
1132 + ": output->input language mismatch";
1138 /// WalkCase - Walks the 'case' expression DAG and invokes
1139 /// TestCallback on every test, and StatementCallback on every
1140 /// statement. Handles 'case' nesting, but not the 'and' and 'or'
1141 /// combinators (that is, they are passed directly to TestCallback).
1142 /// TestCallback must have type 'void TestCallback(const DagInit*, unsigned
1143 /// IndentLevel, bool FirstTest)'.
1144 /// StatementCallback must have type 'void StatementCallback(const Init*,
1145 /// unsigned IndentLevel)'.
1146 template <typename F1
, typename F2
>
1147 void WalkCase(const Init
* Case
, F1 TestCallback
, F2 StatementCallback
,
1148 unsigned IndentLevel
= 0)
1150 const DagInit
& d
= InitPtrToDag(Case
);
1153 if (GetOperatorName(d
) != "case")
1154 throw "WalkCase should be invoked only on 'case' expressions!";
1156 if (d
.getNumArgs() < 2)
1157 throw "There should be at least one clause in the 'case' expression:\n"
1162 const unsigned numArgs
= d
.getNumArgs();
1164 for (DagInit::const_arg_iterator B
= d
.arg_begin(), E
= d
.arg_end();
1171 const DagInit
& Test
= InitPtrToDag(arg
);
1173 if (GetOperatorName(Test
) == "default" && (i
+1 != numArgs
))
1174 throw "The 'default' clause should be the last in the "
1175 "'case' construct!";
1177 throw "Case construct handler: no corresponding action "
1178 "found for the test " + Test
.getAsString() + '!';
1180 TestCallback(Test
, IndentLevel
, (i
== 1));
1184 if (dynamic_cast<DagInit
*>(arg
)
1185 && GetOperatorName(static_cast<DagInit
&>(*arg
)) == "case") {
1187 WalkCase(arg
, TestCallback
, StatementCallback
, IndentLevel
+ Indent1
);
1190 // Handle statement.
1191 StatementCallback(arg
, IndentLevel
);
1199 /// ExtractOptionNames - A helper function object used by
1200 /// CheckForSuperfluousOptions() to walk the 'case' DAG.
1201 class ExtractOptionNames
{
1202 llvm::StringSet
<>& OptionNames_
;
1204 void processDag(const Init
* Statement
) {
1205 const DagInit
& Stmt
= InitPtrToDag(Statement
);
1206 const std::string
& ActionName
= GetOperatorName(Stmt
);
1207 if (ActionName
== "forward" || ActionName
== "forward_as" ||
1208 ActionName
== "forward_value" ||
1209 ActionName
== "forward_transformed_value" ||
1210 ActionName
== "parameter_equals" || ActionName
== "element_in_list") {
1211 CheckNumberOfArguments(Stmt
, 1);
1213 Init
* Arg
= Stmt
.getArg(0);
1214 if (typeid(*Arg
) == typeid(StringInit
))
1215 OptionNames_
.insert(InitPtrToString(Arg
));
1217 else if (ActionName
== "any_switch_on" || ActionName
== "switch_on" ||
1218 ActionName
== "any_not_empty" || ActionName
== "any_empty" ||
1219 ActionName
== "not_empty" || ActionName
== "empty") {
1220 for (unsigned i
= 0, NumArgs
= Stmt
.getNumArgs(); i
< NumArgs
; ++i
) {
1221 Init
* Arg
= Stmt
.getArg(i
);
1222 if (typeid(*Arg
) == typeid(StringInit
))
1223 OptionNames_
.insert(InitPtrToString(Arg
));
1226 else if (ActionName
== "and" || ActionName
== "or" || ActionName
== "not") {
1227 for (unsigned i
= 0, NumArgs
= Stmt
.getNumArgs(); i
< NumArgs
; ++i
) {
1228 this->processDag(Stmt
.getArg(i
));
1234 ExtractOptionNames(llvm::StringSet
<>& OptionNames
) : OptionNames_(OptionNames
)
1237 void operator()(const Init
* Statement
) {
1238 // Statement is either a dag, or a list of dags.
1239 if (typeid(*Statement
) == typeid(ListInit
)) {
1240 const ListInit
& DagList
= *static_cast<const ListInit
*>(Statement
);
1241 for (ListInit::const_iterator B
= DagList
.begin(), E
= DagList
.end();
1243 this->processDag(*B
);
1246 this->processDag(Statement
);
1250 void operator()(const DagInit
& Test
, unsigned, bool) {
1251 this->operator()(&Test
);
1253 void operator()(const Init
* Statement
, unsigned) {
1254 this->operator()(Statement
);
1258 /// IsOptionalEdge - Validate that the 'optional_edge' has proper structure.
1259 bool IsOptionalEdge (const DagInit
& Edg
) {
1260 return (GetOperatorName(Edg
) == "optional_edge") && (Edg
.getNumArgs() > 2);
1263 /// CheckForSuperfluousOptions - Check that there are no side
1264 /// effect-free options (specified only in the OptionList). Otherwise,
1265 /// output a warning.
1266 void CheckForSuperfluousOptions (const DagVector
& EdgeVector
,
1267 const ToolDescriptions
& ToolDescs
,
1268 const OptionDescriptions
& OptDescs
) {
1269 llvm::StringSet
<> nonSuperfluousOptions
;
1271 // Add all options mentioned in the ToolDesc.Actions to the set of
1272 // non-superfluous options.
1273 for (ToolDescriptions::const_iterator B
= ToolDescs
.begin(),
1274 E
= ToolDescs
.end(); B
!= E
; ++B
) {
1275 const ToolDescription
& TD
= *(*B
);
1276 ExtractOptionNames
Callback(nonSuperfluousOptions
);
1278 WalkCase(TD
.Actions
, Callback
, Callback
);
1281 // Add all options mentioned in the 'case' clauses of the
1282 // OptionalEdges of the compilation graph to the set of
1283 // non-superfluous options.
1284 for (DagVector::const_iterator B
= EdgeVector
.begin(),
1285 E
= EdgeVector
.end(); B
!= E
; ++B
) {
1286 const DagInit
& Edge
= **B
;
1287 if (IsOptionalEdge(Edge
)) {
1288 const DagInit
& Weight
= InitPtrToDag(Edge
.getArg(2));
1289 WalkCase(&Weight
, ExtractOptionNames(nonSuperfluousOptions
), Id());
1293 // Check that all options in OptDescs belong to the set of
1294 // non-superfluous options.
1295 for (OptionDescriptions::const_iterator B
= OptDescs
.begin(),
1296 E
= OptDescs
.end(); B
!= E
; ++B
) {
1297 const OptionDescription
& Val
= B
->second
;
1298 if (!nonSuperfluousOptions
.count(Val
.Name
)
1299 && Val
.Type
!= OptionType::Alias
)
1300 llvm::errs() << "Warning: option '-" << Val
.Name
<< "' has no effect! "
1301 "Probable cause: this option is specified only in the OptionList.\n";
1305 /// EmitCaseTest0Args - Helper function used by EmitCaseConstructHandler().
1306 bool EmitCaseTest0Args(const std::string
& TestName
, raw_ostream
& O
) {
1307 if (TestName
== "single_input_file") {
1308 O
<< "InputFilenames.size() == 1";
1311 else if (TestName
== "multiple_input_files") {
1312 O
<< "InputFilenames.size() > 1";
1319 /// EmitMultipleArgumentTest - Helper function used by
1320 /// EmitCaseTestMultipleArgs()
1321 template <typename F
>
1322 void EmitMultipleArgumentTest(const DagInit
& D
, const char* LogicOp
,
1323 F Callback
, raw_ostream
& O
)
1325 for (unsigned i
= 0, NumArgs
= D
.getNumArgs(); i
< NumArgs
; ++i
) {
1327 O
<< ' ' << LogicOp
<< ' ';
1328 Callback(InitPtrToString(D
.getArg(i
)), O
);
1332 // Callbacks for use with EmitMultipleArgumentTest
1334 class EmitSwitchOn
{
1335 const OptionDescriptions
& OptDescs_
;
1337 EmitSwitchOn(const OptionDescriptions
& OptDescs
) : OptDescs_(OptDescs
)
1340 void operator()(const std::string
& OptName
, raw_ostream
& O
) const {
1341 const OptionDescription
& OptDesc
= OptDescs_
.FindSwitch(OptName
);
1342 O
<< OptDesc
.GenVariableName();
1346 class EmitEmptyTest
{
1348 const OptionDescriptions
& OptDescs_
;
1350 EmitEmptyTest(bool EmitNegate
, const OptionDescriptions
& OptDescs
)
1351 : EmitNegate_(EmitNegate
), OptDescs_(OptDescs
)
1354 void operator()(const std::string
& OptName
, raw_ostream
& O
) const {
1355 const char* Neg
= (EmitNegate_
? "!" : "");
1356 if (OptName
== "o") {
1357 O
<< Neg
<< "OutputFilename.empty()";
1359 else if (OptName
== "save-temps") {
1360 O
<< Neg
<< "(SaveTemps == SaveTempsEnum::Unset)";
1363 const OptionDescription
& OptDesc
= OptDescs_
.FindListOrParameter(OptName
);
1364 O
<< Neg
<< OptDesc
.GenVariableName() << ".empty()";
1370 /// EmitCaseTestMultipleArgs - Helper function used by EmitCaseTest1Arg()
1371 bool EmitCaseTestMultipleArgs (const std::string
& TestName
,
1373 const OptionDescriptions
& OptDescs
,
1375 if (TestName
== "any_switch_on") {
1376 EmitMultipleArgumentTest(d
, "||", EmitSwitchOn(OptDescs
), O
);
1379 else if (TestName
== "switch_on") {
1380 EmitMultipleArgumentTest(d
, "&&", EmitSwitchOn(OptDescs
), O
);
1383 else if (TestName
== "any_not_empty") {
1384 EmitMultipleArgumentTest(d
, "||", EmitEmptyTest(true, OptDescs
), O
);
1387 else if (TestName
== "any_empty") {
1388 EmitMultipleArgumentTest(d
, "||", EmitEmptyTest(false, OptDescs
), O
);
1391 else if (TestName
== "not_empty") {
1392 EmitMultipleArgumentTest(d
, "&&", EmitEmptyTest(true, OptDescs
), O
);
1395 else if (TestName
== "empty") {
1396 EmitMultipleArgumentTest(d
, "&&", EmitEmptyTest(false, OptDescs
), O
);
1403 /// EmitCaseTest1Arg - Helper function used by EmitCaseTest1OrMoreArgs()
1404 bool EmitCaseTest1Arg (const std::string
& TestName
,
1406 const OptionDescriptions
& OptDescs
,
1408 const std::string
& Arg
= InitPtrToString(d
.getArg(0));
1410 if (TestName
== "input_languages_contain") {
1411 O
<< "InLangs.count(\"" << Arg
<< "\") != 0";
1414 else if (TestName
== "in_language") {
1415 // This works only for single-argument Tool::GenerateAction. Join
1416 // tools can process several files in different languages simultaneously.
1418 // TODO: make this work with Edge::Weight (if possible).
1419 O
<< "LangMap.GetLanguage(inFile) == \"" << Arg
<< '\"';
1426 /// EmitCaseTest1OrMoreArgs - Helper function used by
1427 /// EmitCaseConstructHandler()
1428 bool EmitCaseTest1OrMoreArgs(const std::string
& TestName
,
1430 const OptionDescriptions
& OptDescs
,
1432 CheckNumberOfArguments(d
, 1);
1433 return EmitCaseTest1Arg(TestName
, d
, OptDescs
, O
) ||
1434 EmitCaseTestMultipleArgs(TestName
, d
, OptDescs
, O
);
1437 /// EmitCaseTest2Args - Helper function used by EmitCaseConstructHandler().
1438 bool EmitCaseTest2Args(const std::string
& TestName
,
1440 unsigned IndentLevel
,
1441 const OptionDescriptions
& OptDescs
,
1443 CheckNumberOfArguments(d
, 2);
1444 const std::string
& OptName
= InitPtrToString(d
.getArg(0));
1445 const std::string
& OptArg
= InitPtrToString(d
.getArg(1));
1447 if (TestName
== "parameter_equals") {
1448 const OptionDescription
& OptDesc
= OptDescs
.FindParameter(OptName
);
1449 O
<< OptDesc
.GenVariableName() << " == \"" << OptArg
<< "\"";
1452 else if (TestName
== "element_in_list") {
1453 const OptionDescription
& OptDesc
= OptDescs
.FindParameterList(OptName
);
1454 const std::string
& VarName
= OptDesc
.GenVariableName();
1455 O
<< "std::find(" << VarName
<< ".begin(),\n";
1456 O
.indent(IndentLevel
+ Indent1
)
1457 << VarName
<< ".end(), \""
1458 << OptArg
<< "\") != " << VarName
<< ".end()";
1465 // Forward declaration.
1466 // EmitLogicalOperationTest and EmitCaseTest are mutually recursive.
1467 void EmitCaseTest(const DagInit
& d
, unsigned IndentLevel
,
1468 const OptionDescriptions
& OptDescs
,
1471 /// EmitLogicalOperationTest - Helper function used by
1472 /// EmitCaseConstructHandler.
1473 void EmitLogicalOperationTest(const DagInit
& d
, const char* LogicOp
,
1474 unsigned IndentLevel
,
1475 const OptionDescriptions
& OptDescs
,
1478 for (unsigned i
= 0, NumArgs
= d
.getNumArgs(); i
< NumArgs
; ++i
) {
1479 const DagInit
& InnerTest
= InitPtrToDag(d
.getArg(i
));
1480 EmitCaseTest(InnerTest
, IndentLevel
, OptDescs
, O
);
1481 if (i
!= NumArgs
- 1) {
1483 O
.indent(IndentLevel
+ Indent1
) << ' ' << LogicOp
<< " (";
1491 void EmitLogicalNot(const DagInit
& d
, unsigned IndentLevel
,
1492 const OptionDescriptions
& OptDescs
, raw_ostream
& O
)
1494 CheckNumberOfArguments(d
, 1);
1495 const DagInit
& InnerTest
= InitPtrToDag(d
.getArg(0));
1497 EmitCaseTest(InnerTest
, IndentLevel
, OptDescs
, O
);
1501 /// EmitCaseTest - Helper function used by EmitCaseConstructHandler.
1502 void EmitCaseTest(const DagInit
& d
, unsigned IndentLevel
,
1503 const OptionDescriptions
& OptDescs
,
1505 const std::string
& TestName
= GetOperatorName(d
);
1507 if (TestName
== "and")
1508 EmitLogicalOperationTest(d
, "&&", IndentLevel
, OptDescs
, O
);
1509 else if (TestName
== "or")
1510 EmitLogicalOperationTest(d
, "||", IndentLevel
, OptDescs
, O
);
1511 else if (TestName
== "not")
1512 EmitLogicalNot(d
, IndentLevel
, OptDescs
, O
);
1513 else if (EmitCaseTest0Args(TestName
, O
))
1515 else if (EmitCaseTest1OrMoreArgs(TestName
, d
, OptDescs
, O
))
1517 else if (EmitCaseTest2Args(TestName
, d
, IndentLevel
, OptDescs
, O
))
1520 throw "Unknown test '" + TestName
+ "' used in the 'case' construct!";
1524 /// EmitCaseTestCallback - Callback used by EmitCaseConstructHandler.
1525 class EmitCaseTestCallback
{
1527 const OptionDescriptions
& OptDescs_
;
1531 EmitCaseTestCallback(bool EmitElseIf
,
1532 const OptionDescriptions
& OptDescs
, raw_ostream
& O
)
1533 : EmitElseIf_(EmitElseIf
), OptDescs_(OptDescs
), O_(O
)
1536 void operator()(const DagInit
& Test
, unsigned IndentLevel
, bool FirstTest
)
1538 if (GetOperatorName(Test
) == "default") {
1539 O_
.indent(IndentLevel
) << "else {\n";
1542 O_
.indent(IndentLevel
)
1543 << ((!FirstTest
&& EmitElseIf_
) ? "else if (" : "if (");
1544 EmitCaseTest(Test
, IndentLevel
, OptDescs_
, O_
);
1550 /// EmitCaseStatementCallback - Callback used by EmitCaseConstructHandler.
1551 template <typename F
>
1552 class EmitCaseStatementCallback
{
1557 EmitCaseStatementCallback(F Callback
, raw_ostream
& O
)
1558 : Callback_(Callback
), O_(O
)
1561 void operator() (const Init
* Statement
, unsigned IndentLevel
) {
1562 // Is this a nested 'case'?
1563 bool IsCase
= dynamic_cast<const DagInit
*>(Statement
) &&
1564 GetOperatorName(static_cast<const DagInit
&>(*Statement
)) == "case";
1566 // If so, ignore it, it is handled by our caller, WalkCase.
1568 if (typeid(*Statement
) == typeid(ListInit
)) {
1569 const ListInit
& DagList
= *static_cast<const ListInit
*>(Statement
);
1570 for (ListInit::const_iterator B
= DagList
.begin(), E
= DagList
.end();
1572 Callback_(*B
, (IndentLevel
+ Indent1
), O_
);
1575 Callback_(Statement
, (IndentLevel
+ Indent1
), O_
);
1578 O_
.indent(IndentLevel
) << "}\n";
1583 /// EmitCaseConstructHandler - Emit code that handles the 'case'
1584 /// construct. Takes a function object that should emit code for every case
1585 /// clause. Implemented on top of WalkCase.
1586 /// Callback's type is void F(const Init* Statement, unsigned IndentLevel,
1587 /// raw_ostream& O).
1588 /// EmitElseIf parameter controls the type of condition that is emitted ('if
1589 /// (..) {..} else if (..) {} .. else {..}' vs. 'if (..) {..} if(..) {..}
1591 template <typename F
>
1592 void EmitCaseConstructHandler(const Init
* Case
, unsigned IndentLevel
,
1593 F Callback
, bool EmitElseIf
,
1594 const OptionDescriptions
& OptDescs
,
1596 WalkCase(Case
, EmitCaseTestCallback(EmitElseIf
, OptDescs
, O
),
1597 EmitCaseStatementCallback
<F
>(Callback
, O
), IndentLevel
);
1600 /// TokenizeCmdLine - converts from
1601 /// "$CALL(HookName, 'Arg1', 'Arg2')/path -arg1 -arg2" to
1602 /// ["$CALL(", "HookName", "Arg1", "Arg2", ")/path", "-arg1", "-arg2"].
1603 void TokenizeCmdLine(const std::string
& CmdLine
, StrVector
& Out
) {
1604 const char* Delimiters
= " \t\n\v\f\r";
1606 { Normal
, SpecialCommand
, InsideSpecialCommand
, InsideQuotationMarks
}
1609 if (CmdLine
.empty())
1613 std::string::size_type B
= CmdLine
.find_first_not_of(Delimiters
),
1616 for (; B
!= E
; ++B
) {
1617 char cur_ch
= CmdLine
[B
];
1621 if (cur_ch
== '$') {
1622 cur_st
= SpecialCommand
;
1625 if (OneOf(Delimiters
, cur_ch
)) {
1627 B
= CmdLine
.find_first_not_of(Delimiters
, B
);
1628 if (B
== std::string::npos
) {
1639 case SpecialCommand
:
1640 if (OneOf(Delimiters
, cur_ch
)) {
1645 if (cur_ch
== '(') {
1647 cur_st
= InsideSpecialCommand
;
1652 case InsideSpecialCommand
:
1653 if (OneOf(Delimiters
, cur_ch
)) {
1656 if (cur_ch
== '\'') {
1657 cur_st
= InsideQuotationMarks
;
1661 if (cur_ch
== ')') {
1665 if (cur_ch
== ',') {
1671 case InsideQuotationMarks
:
1672 if (cur_ch
== '\'') {
1673 cur_st
= InsideSpecialCommand
;
1679 Out
.back().push_back(cur_ch
);
1683 /// SubstituteCall - Given "$CALL(HookName, [Arg1 [, Arg2 [...]]])", output
1684 /// "hooks::HookName([Arg1 [, Arg2 [, ...]]])". Helper function used by
1685 /// SubstituteSpecialCommands().
1686 StrVector::const_iterator
1687 SubstituteCall (StrVector::const_iterator Pos
,
1688 StrVector::const_iterator End
,
1689 bool IsJoin
, raw_ostream
& O
)
1691 const char* errorMessage
= "Syntax error in $CALL invocation!";
1692 CheckedIncrement(Pos
, End
, errorMessage
);
1693 const std::string
& CmdName
= *Pos
;
1696 throw "$CALL invocation: empty argument list!";
1699 O
<< CmdName
<< "(";
1702 bool firstIteration
= true;
1704 CheckedIncrement(Pos
, End
, errorMessage
);
1705 const std::string
& Arg
= *Pos
;
1706 assert(Arg
.size() != 0);
1712 firstIteration
= false;
1716 if (Arg
== "$INFILE") {
1718 throw "$CALL(Hook, $INFILE) can't be used with a Join tool!";
1720 O
<< "inFile.c_str()";
1723 O
<< '"' << Arg
<< '"';
1732 /// SubstituteEnv - Given '$ENV(VAR_NAME)', output 'getenv("VAR_NAME")'. Helper
1733 /// function used by SubstituteSpecialCommands().
1734 StrVector::const_iterator
1735 SubstituteEnv (StrVector::const_iterator Pos
,
1736 StrVector::const_iterator End
, raw_ostream
& O
)
1738 const char* errorMessage
= "Syntax error in $ENV invocation!";
1739 CheckedIncrement(Pos
, End
, errorMessage
);
1740 const std::string
& EnvName
= *Pos
;
1743 throw "$ENV invocation: empty argument list!";
1745 O
<< "checkCString(std::getenv(\"";
1749 CheckedIncrement(Pos
, End
, errorMessage
);
1754 /// SubstituteSpecialCommands - Given an invocation of $CALL or $ENV, output
1755 /// handler code. Helper function used by EmitCmdLineVecFill().
1756 StrVector::const_iterator
1757 SubstituteSpecialCommands (StrVector::const_iterator Pos
,
1758 StrVector::const_iterator End
,
1759 bool IsJoin
, raw_ostream
& O
)
1762 const std::string
& cmd
= *Pos
;
1764 // Perform substitution.
1765 if (cmd
== "$CALL") {
1766 Pos
= SubstituteCall(Pos
, End
, IsJoin
, O
);
1768 else if (cmd
== "$ENV") {
1769 Pos
= SubstituteEnv(Pos
, End
, O
);
1772 throw "Unknown special command: " + cmd
;
1775 // Handle '$CMD(ARG)/additional/text'.
1776 const std::string
& Leftover
= *Pos
;
1777 assert(Leftover
.at(0) == ')');
1778 if (Leftover
.size() != 1)
1779 O
<< " + std::string(\"" << (Leftover
.c_str() + 1) << "\")";
1784 /// EmitCmdLineVecFill - Emit code that fills in the command line
1785 /// vector. Helper function used by EmitGenerateActionMethod().
1786 void EmitCmdLineVecFill(const Init
* CmdLine
, const std::string
& ToolName
,
1787 bool IsJoin
, unsigned IndentLevel
,
1790 TokenizeCmdLine(InitPtrToString(CmdLine
), StrVec
);
1793 throw "Tool '" + ToolName
+ "' has empty command line!";
1795 StrVector::const_iterator B
= StrVec
.begin(), E
= StrVec
.end();
1797 // Emit the command itself.
1798 assert(!StrVec
[0].empty());
1799 O
.indent(IndentLevel
) << "cmd = ";
1800 if (StrVec
[0][0] == '$') {
1801 B
= SubstituteSpecialCommands(B
, E
, IsJoin
, O
);
1805 O
<< '"' << StrVec
[0] << '"';
1810 // Go through the command arguments.
1812 for (; B
!= E
; ++B
) {
1813 const std::string
& cmd
= *B
;
1815 assert(!cmd
.empty());
1816 O
.indent(IndentLevel
);
1818 if (cmd
.at(0) == '$') {
1819 O
<< "vec.push_back(std::make_pair(0, ";
1820 B
= SubstituteSpecialCommands(B
, E
, IsJoin
, O
);
1824 O
<< "vec.push_back(std::make_pair(0, \"" << cmd
<< "\"));\n";
1830 /// EmitForEachListElementCycleHeader - Emit common code for iterating through
1831 /// all elements of a list. Helper function used by
1832 /// EmitForwardOptionPropertyHandlingCode.
1833 void EmitForEachListElementCycleHeader (const OptionDescription
& D
,
1834 unsigned IndentLevel
,
1836 unsigned IndentLevel1
= IndentLevel
+ Indent1
;
1838 O
.indent(IndentLevel
)
1839 << "for (" << D
.GenTypeDeclaration()
1840 << "::iterator B = " << D
.GenVariableName() << ".begin(),\n";
1841 O
.indent(IndentLevel
)
1842 << "E = " << D
.GenVariableName() << ".end(); B != E;) {\n";
1843 O
.indent(IndentLevel1
) << "unsigned pos = " << D
.GenVariableName()
1844 << ".getPosition(B - " << D
.GenVariableName()
1848 /// EmitForwardOptionPropertyHandlingCode - Helper function used to
1849 /// implement EmitActionHandler. Emits code for
1850 /// handling the (forward) and (forward_as) option properties.
1851 void EmitForwardOptionPropertyHandlingCode (const OptionDescription
& D
,
1852 unsigned IndentLevel
,
1853 const std::string
& NewName
,
1855 const std::string
& Name
= NewName
.empty()
1858 unsigned IndentLevel1
= IndentLevel
+ Indent1
;
1861 case OptionType::Switch
:
1862 O
.indent(IndentLevel
)
1863 << "vec.push_back(std::make_pair(" << D
.GenVariableName()
1864 << ".getPosition(), \"" << Name
<< "\"));\n";
1866 case OptionType::Parameter
:
1867 O
.indent(IndentLevel
) << "vec.push_back(std::make_pair("
1868 << D
.GenVariableName()
1869 <<".getPosition(), \"" << Name
;
1871 if (!D
.isForwardNotSplit()) {
1873 O
.indent(IndentLevel
) << "vec.push_back(std::make_pair("
1874 << D
.GenVariableName() << ".getPosition(), "
1875 << D
.GenVariableName() << "));\n";
1878 O
<< "=\" + " << D
.GenVariableName() << "));\n";
1881 case OptionType::Prefix
:
1882 O
.indent(IndentLevel
) << "vec.push_back(std::make_pair("
1883 << D
.GenVariableName() << ".getPosition(), \""
1885 << D
.GenVariableName() << "));\n";
1887 case OptionType::PrefixList
:
1888 EmitForEachListElementCycleHeader(D
, IndentLevel
, O
);
1889 O
.indent(IndentLevel1
) << "vec.push_back(std::make_pair(pos, \""
1890 << Name
<< "\" + " << "*B));\n";
1891 O
.indent(IndentLevel1
) << "++B;\n";
1893 for (int i
= 1, j
= D
.MultiVal
; i
< j
; ++i
) {
1894 O
.indent(IndentLevel1
) << "vec.push_back(std::make_pair(pos, *B));\n";
1895 O
.indent(IndentLevel1
) << "++B;\n";
1898 O
.indent(IndentLevel
) << "}\n";
1900 case OptionType::ParameterList
:
1901 EmitForEachListElementCycleHeader(D
, IndentLevel
, O
);
1902 O
.indent(IndentLevel1
) << "vec.push_back(std::make_pair(pos, \""
1903 << Name
<< "\"));\n";
1905 for (int i
= 0, j
= D
.MultiVal
; i
< j
; ++i
) {
1906 O
.indent(IndentLevel1
) << "vec.push_back(std::make_pair(pos, *B));\n";
1907 O
.indent(IndentLevel1
) << "++B;\n";
1910 O
.indent(IndentLevel
) << "}\n";
1912 case OptionType::SwitchList
:
1913 EmitForEachListElementCycleHeader(D
, IndentLevel
, O
);
1914 O
.indent(IndentLevel1
) << "vec.push_back(std::make_pair(pos, \""
1915 << Name
<< "\"));\n";
1916 O
.indent(IndentLevel1
) << "++B;\n";
1917 O
.indent(IndentLevel
) << "}\n";
1919 case OptionType::Alias
:
1921 throw "Aliases are not allowed in tool option descriptions!";
1925 /// ActionHandlingCallbackBase - Base class of EmitActionHandlersCallback and
1926 /// EmitPreprocessOptionsCallback.
1927 struct ActionHandlingCallbackBase
1930 void onErrorDag(const DagInit
& d
,
1931 unsigned IndentLevel
, raw_ostream
& O
) const
1933 O
.indent(IndentLevel
)
1935 << (d
.getNumArgs() >= 1 ? InitPtrToString(d
.getArg(0)) : "Unknown error!")
1937 O
.indent(IndentLevel
) << "return 1;\n";
1940 void onWarningDag(const DagInit
& d
,
1941 unsigned IndentLevel
, raw_ostream
& O
) const
1943 CheckNumberOfArguments(d
, 1);
1944 O
.indent(IndentLevel
) << "llvm::errs() << \""
1945 << InitPtrToString(d
.getArg(0)) << "\";\n";
1950 /// EmitActionHandlersCallback - Emit code that handles actions. Used by
1951 /// EmitGenerateActionMethod() as an argument to EmitCaseConstructHandler().
1952 class EmitActionHandlersCallback
;
1954 typedef void (EmitActionHandlersCallback::* EmitActionHandlersCallbackHandler
)
1955 (const DagInit
&, unsigned, raw_ostream
&) const;
1957 class EmitActionHandlersCallback
:
1958 public ActionHandlingCallbackBase
,
1959 public HandlerTable
<EmitActionHandlersCallbackHandler
>
1961 typedef EmitActionHandlersCallbackHandler Handler
;
1963 const OptionDescriptions
& OptDescs
;
1965 /// EmitHookInvocation - Common code for hook invocation from actions. Used by
1966 /// onAppendCmd and onOutputSuffix.
1967 void EmitHookInvocation(const std::string
& Str
,
1968 const char* BlockOpen
, const char* BlockClose
,
1969 unsigned IndentLevel
, raw_ostream
& O
) const
1972 TokenizeCmdLine(Str
, Out
);
1974 for (StrVector::const_iterator B
= Out
.begin(), E
= Out
.end();
1976 const std::string
& cmd
= *B
;
1978 O
.indent(IndentLevel
) << BlockOpen
;
1980 if (cmd
.at(0) == '$')
1981 B
= SubstituteSpecialCommands(B
, E
, /* IsJoin = */ true, O
);
1983 O
<< '"' << cmd
<< '"';
1989 void onAppendCmd (const DagInit
& Dag
,
1990 unsigned IndentLevel
, raw_ostream
& O
) const
1992 CheckNumberOfArguments(Dag
, 1);
1993 this->EmitHookInvocation(InitPtrToString(Dag
.getArg(0)),
1994 "vec.push_back(std::make_pair(65536, ", "));\n",
1998 void onForward (const DagInit
& Dag
,
1999 unsigned IndentLevel
, raw_ostream
& O
) const
2001 CheckNumberOfArguments(Dag
, 1);
2002 const std::string
& Name
= InitPtrToString(Dag
.getArg(0));
2003 EmitForwardOptionPropertyHandlingCode(OptDescs
.FindOption(Name
),
2004 IndentLevel
, "", O
);
2007 void onForwardAs (const DagInit
& Dag
,
2008 unsigned IndentLevel
, raw_ostream
& O
) const
2010 CheckNumberOfArguments(Dag
, 2);
2011 const std::string
& Name
= InitPtrToString(Dag
.getArg(0));
2012 const std::string
& NewName
= InitPtrToString(Dag
.getArg(1));
2013 EmitForwardOptionPropertyHandlingCode(OptDescs
.FindOption(Name
),
2014 IndentLevel
, NewName
, O
);
2017 void onForwardValue (const DagInit
& Dag
,
2018 unsigned IndentLevel
, raw_ostream
& O
) const
2020 CheckNumberOfArguments(Dag
, 1);
2021 const std::string
& Name
= InitPtrToString(Dag
.getArg(0));
2022 const OptionDescription
& D
= OptDescs
.FindParameterListOrParameter(Name
);
2024 if (D
.isSwitchList()) {
2025 throw std::runtime_error
2026 ("forward_value is not allowed with switch_list");
2029 if (D
.isParameter()) {
2030 O
.indent(IndentLevel
) << "vec.push_back(std::make_pair("
2031 << D
.GenVariableName() << ".getPosition(), "
2032 << D
.GenVariableName() << "));\n";
2035 O
.indent(IndentLevel
) << "for (" << D
.GenTypeDeclaration()
2036 << "::iterator B = " << D
.GenVariableName()
2038 O
.indent(IndentLevel
+ Indent1
) << " E = " << D
.GenVariableName()
2039 << ".end(); B != E; ++B)\n";
2040 O
.indent(IndentLevel
) << "{\n";
2041 O
.indent(IndentLevel
+ Indent1
)
2042 << "unsigned pos = " << D
.GenVariableName()
2043 << ".getPosition(B - " << D
.GenVariableName()
2045 O
.indent(IndentLevel
+ Indent1
)
2046 << "vec.push_back(std::make_pair(pos, *B));\n";
2047 O
.indent(IndentLevel
) << "}\n";
2051 void onForwardTransformedValue (const DagInit
& Dag
,
2052 unsigned IndentLevel
, raw_ostream
& O
) const
2054 CheckNumberOfArguments(Dag
, 2);
2055 const std::string
& Name
= InitPtrToString(Dag
.getArg(0));
2056 const std::string
& Hook
= InitPtrToString(Dag
.getArg(1));
2057 const OptionDescription
& D
= OptDescs
.FindParameterListOrParameter(Name
);
2059 O
.indent(IndentLevel
) << "vec.push_back(std::make_pair("
2060 << D
.GenVariableName() << ".getPosition("
2061 << (D
.isList() ? "0" : "") << "), "
2062 << "hooks::" << Hook
<< "(" << D
.GenVariableName()
2063 << (D
.isParameter() ? ".c_str()" : "") << ")));\n";
2066 void onNoOutFile (const DagInit
& Dag
,
2067 unsigned IndentLevel
, raw_ostream
& O
) const
2069 CheckNumberOfArguments(Dag
, 0);
2070 O
.indent(IndentLevel
) << "no_out_file = true;\n";
2073 void onOutputSuffix (const DagInit
& Dag
,
2074 unsigned IndentLevel
, raw_ostream
& O
) const
2076 CheckNumberOfArguments(Dag
, 1);
2077 this->EmitHookInvocation(InitPtrToString(Dag
.getArg(0)),
2078 "output_suffix = ", ";\n", IndentLevel
, O
);
2081 void onStopCompilation (const DagInit
& Dag
,
2082 unsigned IndentLevel
, raw_ostream
& O
) const
2084 O
.indent(IndentLevel
) << "stop_compilation = true;\n";
2088 void onUnpackValues (const DagInit
& Dag
,
2089 unsigned IndentLevel
, raw_ostream
& O
) const
2091 throw "'unpack_values' is deprecated. "
2092 "Use 'comma_separated' + 'forward_value' instead!";
2097 explicit EmitActionHandlersCallback(const OptionDescriptions
& OD
)
2100 if (!staticMembersInitialized_
) {
2101 AddHandler("error", &EmitActionHandlersCallback::onErrorDag
);
2102 AddHandler("warning", &EmitActionHandlersCallback::onWarningDag
);
2103 AddHandler("append_cmd", &EmitActionHandlersCallback::onAppendCmd
);
2104 AddHandler("forward", &EmitActionHandlersCallback::onForward
);
2105 AddHandler("forward_as", &EmitActionHandlersCallback::onForwardAs
);
2106 AddHandler("forward_value", &EmitActionHandlersCallback::onForwardValue
);
2107 AddHandler("forward_transformed_value",
2108 &EmitActionHandlersCallback::onForwardTransformedValue
);
2109 AddHandler("no_out_file",
2110 &EmitActionHandlersCallback::onNoOutFile
);
2111 AddHandler("output_suffix", &EmitActionHandlersCallback::onOutputSuffix
);
2112 AddHandler("stop_compilation",
2113 &EmitActionHandlersCallback::onStopCompilation
);
2114 AddHandler("unpack_values",
2115 &EmitActionHandlersCallback::onUnpackValues
);
2118 staticMembersInitialized_
= true;
2122 void operator()(const Init
* I
,
2123 unsigned IndentLevel
, raw_ostream
& O
) const
2125 InvokeDagInitHandler(this, I
, IndentLevel
, O
);
2129 void EmitGenerateActionMethodHeader(const ToolDescription
& D
,
2130 bool IsJoin
, bool Naked
,
2133 O
.indent(Indent1
) << "int GenerateAction(Action& Out,\n";
2136 O
.indent(Indent2
) << "const PathVector& inFiles,\n";
2138 O
.indent(Indent2
) << "const sys::Path& inFile,\n";
2140 O
.indent(Indent2
) << "const bool HasChildren,\n";
2141 O
.indent(Indent2
) << "const llvm::sys::Path& TempDir,\n";
2142 O
.indent(Indent2
) << "const InputLanguagesSet& InLangs,\n";
2143 O
.indent(Indent2
) << "const LanguageMap& LangMap) const\n";
2144 O
.indent(Indent1
) << "{\n";
2147 O
.indent(Indent2
) << "std::string cmd;\n";
2148 O
.indent(Indent2
) << "std::string out_file;\n";
2150 << "std::vector<std::pair<unsigned, std::string> > vec;\n";
2151 O
.indent(Indent2
) << "bool stop_compilation = !HasChildren;\n";
2152 O
.indent(Indent2
) << "bool no_out_file = false;\n";
2153 O
.indent(Indent2
) << "std::string output_suffix(\""
2154 << D
.OutputSuffix
<< "\");\n";
2158 // EmitGenerateActionMethod - Emit either a normal or a "join" version of the
2159 // Tool::GenerateAction() method.
2160 void EmitGenerateActionMethod (const ToolDescription
& D
,
2161 const OptionDescriptions
& OptDescs
,
2162 bool IsJoin
, raw_ostream
& O
) {
2164 EmitGenerateActionMethodHeader(D
, IsJoin
, /* Naked = */ false, O
);
2167 throw "Tool " + D
.Name
+ " has no cmd_line property!";
2169 // Process the 'command' property.
2171 EmitCmdLineVecFill(D
.CmdLine
, D
.Name
, IsJoin
, Indent2
, O
);
2174 // Process the 'actions' list of this tool.
2176 EmitCaseConstructHandler(D
.Actions
, Indent2
,
2177 EmitActionHandlersCallback(OptDescs
),
2178 false, OptDescs
, O
);
2182 if (!D
.InFileOption
.empty()) {
2184 << "vec.push_back(std::make_pair(InputFilenames.getPosition(0), \""
2185 << D
.InFileOption
<< "\");\n";
2190 << "for (PathVector::const_iterator B = inFiles.begin(),\n";
2191 O
.indent(Indent3
) << "E = inFiles.end(); B != E; ++B)\n";
2192 O
.indent(Indent2
) << "{\n";
2193 O
.indent(Indent3
) << "vec.push_back(std::make_pair("
2194 << "InputFilenames.getPosition(B - inFiles.begin()), "
2196 O
.indent(Indent2
) << "}\n";
2199 O
.indent(Indent2
) << "vec.push_back(std::make_pair("
2200 << "InputFilenames.getPosition(0), inFile.str()));\n";
2204 O
.indent(Indent2
) << "if (!no_out_file) {\n";
2205 if (!D
.OutFileOption
.empty())
2206 O
.indent(Indent3
) << "vec.push_back(std::make_pair(65536, \""
2207 << D
.OutFileOption
<< "\"));\n";
2209 O
.indent(Indent3
) << "out_file = this->OutFilename("
2210 << (IsJoin
? "sys::Path(),\n" : "inFile,\n");
2211 O
.indent(Indent4
) <<
2212 "TempDir, stop_compilation, output_suffix.c_str()).str();\n\n";
2213 O
.indent(Indent3
) << "vec.push_back(std::make_pair(65536, out_file));\n";
2215 O
.indent(Indent2
) << "}\n\n";
2217 // Handle the Sink property.
2218 std::string
SinkOption("autogenerated::");
2219 SinkOption
+= SinkOptionName
;
2221 O
.indent(Indent2
) << "if (!" << SinkOption
<< ".empty()) {\n";
2222 O
.indent(Indent3
) << "for (cl::list<std::string>::iterator B = "
2223 << SinkOption
<< ".begin(), E = " << SinkOption
2224 << ".end(); B != E; ++B)\n";
2225 O
.indent(Indent4
) << "vec.push_back(std::make_pair(" << SinkOption
2226 << ".getPosition(B - " << SinkOption
2227 << ".begin()), *B));\n";
2228 O
.indent(Indent2
) << "}\n";
2231 O
.indent(Indent2
) << "Out.Construct(cmd, this->SortArgs(vec), "
2232 << "stop_compilation, out_file);\n";
2233 O
.indent(Indent2
) << "return 0;\n";
2234 O
.indent(Indent1
) << "}\n\n";
2237 /// EmitGenerateActionMethods - Emit two GenerateAction() methods for
2238 /// a given Tool class.
2239 void EmitGenerateActionMethods (const ToolDescription
& ToolDesc
,
2240 const OptionDescriptions
& OptDescs
,
2242 if (!ToolDesc
.isJoin()) {
2243 EmitGenerateActionMethodHeader(ToolDesc
, /* IsJoin = */ true,
2244 /* Naked = */ true, O
);
2245 O
.indent(Indent2
) << "PrintError(\"" << ToolDesc
.Name
2246 << " is not a Join tool!\");\n";
2247 O
.indent(Indent2
) << "return -1;\n";
2248 O
.indent(Indent1
) << "}\n\n";
2251 EmitGenerateActionMethod(ToolDesc
, OptDescs
, true, O
);
2254 EmitGenerateActionMethod(ToolDesc
, OptDescs
, false, O
);
2257 /// EmitInOutLanguageMethods - Emit the [Input,Output]Language()
2258 /// methods for a given Tool class.
2259 void EmitInOutLanguageMethods (const ToolDescription
& D
, raw_ostream
& O
) {
2260 O
.indent(Indent1
) << "const char** InputLanguages() const {\n";
2261 O
.indent(Indent2
) << "return InputLanguages_;\n";
2262 O
.indent(Indent1
) << "}\n\n";
2264 O
.indent(Indent1
) << "const char** OutputLanguages() const {\n";
2265 O
.indent(Indent2
) << "return OutputLanguages_;\n";
2266 O
.indent(Indent1
) << "}\n\n";
2269 /// EmitNameMethod - Emit the Name() method for a given Tool class.
2270 void EmitNameMethod (const ToolDescription
& D
, raw_ostream
& O
) {
2271 O
.indent(Indent1
) << "const char* Name() const {\n";
2272 O
.indent(Indent2
) << "return \"" << D
.Name
<< "\";\n";
2273 O
.indent(Indent1
) << "}\n\n";
2276 /// EmitIsJoinMethod - Emit the IsJoin() method for a given Tool
2278 void EmitIsJoinMethod (const ToolDescription
& D
, raw_ostream
& O
) {
2279 O
.indent(Indent1
) << "bool IsJoin() const {\n";
2281 O
.indent(Indent2
) << "return true;\n";
2283 O
.indent(Indent2
) << "return false;\n";
2284 O
.indent(Indent1
) << "}\n\n";
2287 /// EmitWorksOnEmptyCallback - Callback used by EmitWorksOnEmptyMethod in
2288 /// conjunction with EmitCaseConstructHandler.
2289 void EmitWorksOnEmptyCallback (const Init
* Value
,
2290 unsigned IndentLevel
, raw_ostream
& O
) {
2291 CheckBooleanConstant(Value
);
2292 O
.indent(IndentLevel
) << "return " << Value
->getAsString() << ";\n";
2295 /// EmitWorksOnEmptyMethod - Emit the WorksOnEmpty() method for a given Tool
2297 void EmitWorksOnEmptyMethod (const ToolDescription
& D
,
2298 const OptionDescriptions
& OptDescs
,
2301 O
.indent(Indent1
) << "bool WorksOnEmpty() const {\n";
2303 O
.indent(Indent2
) << "return false;\n";
2305 EmitCaseConstructHandler(D
.OnEmpty
, Indent2
, EmitWorksOnEmptyCallback
,
2306 /*EmitElseIf = */ true, OptDescs
, O
);
2307 O
.indent(Indent1
) << "}\n\n";
2310 /// EmitStrArray - Emit definition of a 'const char**' static member
2311 /// variable. Helper used by EmitStaticMemberDefinitions();
2312 void EmitStrArray(const std::string
& Name
, const std::string
& VarName
,
2313 const StrVector
& StrVec
, raw_ostream
& O
) {
2314 O
<< "const char* " << Name
<< "::" << VarName
<< "[] = {";
2315 for (StrVector::const_iterator B
= StrVec
.begin(), E
= StrVec
.end();
2317 O
<< '\"' << *B
<< "\", ";
2321 /// EmitStaticMemberDefinitions - Emit static member definitions for a
2322 /// given Tool class.
2323 void EmitStaticMemberDefinitions(const ToolDescription
& D
, raw_ostream
& O
) {
2324 if (D
.InLanguage
.empty())
2325 throw "Tool " + D
.Name
+ " has no 'in_language' property!";
2326 if (D
.OutLanguage
.empty())
2327 throw "Tool " + D
.Name
+ " has no 'out_language' property!";
2329 EmitStrArray(D
.Name
, "InputLanguages_", D
.InLanguage
, O
);
2330 EmitStrArray(D
.Name
, "OutputLanguages_", D
.OutLanguage
, O
);
2334 /// EmitToolClassDefinition - Emit a Tool class definition.
2335 void EmitToolClassDefinition (const ToolDescription
& D
,
2336 const OptionDescriptions
& OptDescs
,
2338 if (D
.Name
== "root")
2342 O
<< "class " << D
.Name
<< " : public ";
2348 O
<< " {\nprivate:\n";
2349 O
.indent(Indent1
) << "static const char* InputLanguages_[];\n";
2350 O
.indent(Indent1
) << "static const char* OutputLanguages_[];\n\n";
2353 EmitNameMethod(D
, O
);
2354 EmitInOutLanguageMethods(D
, O
);
2355 EmitIsJoinMethod(D
, O
);
2356 EmitWorksOnEmptyMethod(D
, OptDescs
, O
);
2357 EmitGenerateActionMethods(D
, OptDescs
, O
);
2359 // Close class definition
2362 EmitStaticMemberDefinitions(D
, O
);
2366 /// EmitOptionDefinitions - Iterate over a list of option descriptions
2367 /// and emit registration code.
2368 void EmitOptionDefinitions (const OptionDescriptions
& descs
,
2369 bool HasSink
, raw_ostream
& O
)
2371 std::vector
<OptionDescription
> Aliases
;
2373 // Emit static cl::Option variables.
2374 for (OptionDescriptions::const_iterator B
= descs
.begin(),
2375 E
= descs
.end(); B
!=E
; ++B
) {
2376 const OptionDescription
& val
= B
->second
;
2378 if (val
.Type
== OptionType::Alias
) {
2379 Aliases
.push_back(val
);
2383 O
<< val
.GenTypeDeclaration() << ' '
2384 << val
.GenPlainVariableName();
2386 O
<< "(\"" << val
.Name
<< "\"\n";
2388 if (val
.Type
== OptionType::Prefix
|| val
.Type
== OptionType::PrefixList
)
2389 O
<< ", cl::Prefix";
2391 if (val
.isRequired()) {
2392 if (val
.isList() && !val
.isMultiVal())
2393 O
<< ", cl::OneOrMore";
2395 O
<< ", cl::Required";
2398 if (val
.isOptional())
2399 O
<< ", cl::Optional";
2401 if (val
.isOneOrMore())
2402 O
<< ", cl::OneOrMore";
2404 if (val
.isZeroOrMore())
2405 O
<< ", cl::ZeroOrMore";
2407 if (val
.isReallyHidden())
2408 O
<< ", cl::ReallyHidden";
2409 else if (val
.isHidden())
2410 O
<< ", cl::Hidden";
2412 if (val
.isCommaSeparated())
2413 O
<< ", cl::CommaSeparated";
2415 if (val
.MultiVal
> 1)
2416 O
<< ", cl::multi_val(" << val
.MultiVal
<< ')';
2419 const std::string
& str
= val
.InitVal
->getAsString();
2420 O
<< ", cl::init(" << str
<< ')';
2423 if (!val
.Help
.empty())
2424 O
<< ", cl::desc(\"" << val
.Help
<< "\")";
2429 // Emit the aliases (they should go after all the 'proper' options).
2430 for (std::vector
<OptionDescription
>::const_iterator
2431 B
= Aliases
.begin(), E
= Aliases
.end(); B
!= E
; ++B
) {
2432 const OptionDescription
& val
= *B
;
2434 O
<< val
.GenTypeDeclaration() << ' '
2435 << val
.GenPlainVariableName()
2436 << "(\"" << val
.Name
<< '\"';
2438 const OptionDescription
& D
= descs
.FindOption(val
.Help
);
2439 O
<< ", cl::aliasopt(" << D
.GenVariableName() << ")";
2441 O
<< ", cl::desc(\"" << "An alias for -" + val
.Help
<< "\"));\n";
2444 // Emit the sink option.
2446 O
<< "cl::list<std::string> " << SinkOptionName
<< "(cl::Sink);\n";
2451 /// EmitPreprocessOptionsCallback - Helper function passed to
2452 /// EmitCaseConstructHandler() by EmitPreprocessOptions().
2454 class EmitPreprocessOptionsCallback
;
2457 (EmitPreprocessOptionsCallback::* EmitPreprocessOptionsCallbackHandler
)
2458 (const DagInit
&, unsigned, raw_ostream
&) const;
2460 class EmitPreprocessOptionsCallback
:
2461 public ActionHandlingCallbackBase
,
2462 public HandlerTable
<EmitPreprocessOptionsCallbackHandler
>
2464 typedef EmitPreprocessOptionsCallbackHandler Handler
;
2466 (EmitPreprocessOptionsCallback::* HandlerImpl
)
2467 (const Init
*, unsigned, raw_ostream
&) const;
2469 const OptionDescriptions
& OptDescs_
;
2471 void onEachArgument(const DagInit
& d
, HandlerImpl h
,
2472 unsigned IndentLevel
, raw_ostream
& O
) const
2474 CheckNumberOfArguments(d
, 1);
2476 for (unsigned i
= 0, NumArgs
= d
.getNumArgs(); i
< NumArgs
; ++i
) {
2477 ((this)->*(h
))(d
.getArg(i
), IndentLevel
, O
);
2481 void onUnsetOptionImpl(const Init
* I
,
2482 unsigned IndentLevel
, raw_ostream
& O
) const
2484 const std::string
& OptName
= InitPtrToString(I
);
2485 const OptionDescription
& OptDesc
= OptDescs_
.FindOption(OptName
);
2487 if (OptDesc
.isSwitch()) {
2488 O
.indent(IndentLevel
) << OptDesc
.GenVariableName() << " = false;\n";
2490 else if (OptDesc
.isParameter()) {
2491 O
.indent(IndentLevel
) << OptDesc
.GenVariableName() << " = \"\";\n";
2493 else if (OptDesc
.isList()) {
2494 O
.indent(IndentLevel
) << OptDesc
.GenVariableName() << ".clear();\n";
2497 throw "Can't apply 'unset_option' to alias option '" + OptName
+ "'!";
2501 void onUnsetOption(const DagInit
& d
,
2502 unsigned IndentLevel
, raw_ostream
& O
) const
2504 this->onEachArgument(d
, &EmitPreprocessOptionsCallback::onUnsetOptionImpl
,
2508 void onSetOptionImpl(const DagInit
& D
,
2509 unsigned IndentLevel
, raw_ostream
& O
) const {
2510 CheckNumberOfArguments(D
, 2);
2512 const std::string
& OptName
= InitPtrToString(D
.getArg(0));
2513 const OptionDescription
& OptDesc
= OptDescs_
.FindOption(OptName
);
2514 const Init
* Value
= D
.getArg(1);
2516 if (OptDesc
.isList()) {
2517 const ListInit
& List
= InitPtrToList(Value
);
2519 O
.indent(IndentLevel
) << OptDesc
.GenVariableName() << ".clear();\n";
2520 for (ListInit::const_iterator B
= List
.begin(), E
= List
.end();
2522 const Init
* CurElem
= *B
;
2523 if (OptDesc
.isSwitchList())
2524 CheckBooleanConstant(CurElem
);
2526 O
.indent(IndentLevel
)
2527 << OptDesc
.GenVariableName() << ".push_back(\""
2528 << (OptDesc
.isSwitchList() ? CurElem
->getAsString()
2529 : InitPtrToString(CurElem
))
2533 else if (OptDesc
.isSwitch()) {
2534 CheckBooleanConstant(Value
);
2535 O
.indent(IndentLevel
) << OptDesc
.GenVariableName()
2536 << " = " << Value
->getAsString() << ";\n";
2538 else if (OptDesc
.isParameter()) {
2539 const std::string
& Str
= InitPtrToString(Value
);
2540 O
.indent(IndentLevel
) << OptDesc
.GenVariableName()
2541 << " = \"" << Str
<< "\";\n";
2544 throw "Can't apply 'set_option' to alias option '" + OptName
+ "'!";
2548 void onSetSwitch(const Init
* I
,
2549 unsigned IndentLevel
, raw_ostream
& O
) const {
2550 const std::string
& OptName
= InitPtrToString(I
);
2551 const OptionDescription
& OptDesc
= OptDescs_
.FindOption(OptName
);
2553 if (OptDesc
.isSwitch())
2554 O
.indent(IndentLevel
) << OptDesc
.GenVariableName() << " = true;\n";
2556 throw "set_option: -" + OptName
+ " is not a switch option!";
2559 void onSetOption(const DagInit
& d
,
2560 unsigned IndentLevel
, raw_ostream
& O
) const
2562 CheckNumberOfArguments(d
, 1);
2564 // 2-argument form: (set_option "A", true), (set_option "B", "C"),
2565 // (set_option "D", ["E", "F"])
2566 if (d
.getNumArgs() == 2) {
2567 const OptionDescription
& OptDesc
=
2568 OptDescs_
.FindOption(InitPtrToString(d
.getArg(0)));
2569 const Init
* Opt2
= d
.getArg(1);
2571 if (!OptDesc
.isSwitch() || typeid(*Opt2
) != typeid(StringInit
)) {
2572 this->onSetOptionImpl(d
, IndentLevel
, O
);
2577 // Multiple argument form: (set_option "A"), (set_option "B", "C", "D")
2578 this->onEachArgument(d
, &EmitPreprocessOptionsCallback::onSetSwitch
,
2584 EmitPreprocessOptionsCallback(const OptionDescriptions
& OptDescs
)
2585 : OptDescs_(OptDescs
)
2587 if (!staticMembersInitialized_
) {
2588 AddHandler("error", &EmitPreprocessOptionsCallback::onErrorDag
);
2589 AddHandler("warning", &EmitPreprocessOptionsCallback::onWarningDag
);
2590 AddHandler("unset_option", &EmitPreprocessOptionsCallback::onUnsetOption
);
2591 AddHandler("set_option", &EmitPreprocessOptionsCallback::onSetOption
);
2593 staticMembersInitialized_
= true;
2597 void operator()(const Init
* I
,
2598 unsigned IndentLevel
, raw_ostream
& O
) const
2600 InvokeDagInitHandler(this, I
, IndentLevel
, O
);
2605 /// EmitPreprocessOptions - Emit the PreprocessOptions() function.
2606 void EmitPreprocessOptions (const RecordKeeper
& Records
,
2607 const OptionDescriptions
& OptDecs
, raw_ostream
& O
)
2609 O
<< "int PreprocessOptions () {\n";
2611 const RecordVector
& OptionPreprocessors
=
2612 Records
.getAllDerivedDefinitions("OptionPreprocessor");
2614 for (RecordVector::const_iterator B
= OptionPreprocessors
.begin(),
2615 E
= OptionPreprocessors
.end(); B
!=E
; ++B
) {
2616 DagInit
* Case
= (*B
)->getValueAsDag("preprocessor");
2617 EmitCaseConstructHandler(Case
, Indent1
,
2618 EmitPreprocessOptionsCallback(OptDecs
),
2623 O
.indent(Indent1
) << "return 0;\n";
2627 class DoEmitPopulateLanguageMap
;
2628 typedef void (DoEmitPopulateLanguageMap::* DoEmitPopulateLanguageMapHandler
)
2631 class DoEmitPopulateLanguageMap
2632 : public HandlerTable
<DoEmitPopulateLanguageMapHandler
>
2639 explicit DoEmitPopulateLanguageMap (raw_ostream
& O
) : O_(O
) {
2640 if (!staticMembersInitialized_
) {
2641 AddHandler("lang_to_suffixes",
2642 &DoEmitPopulateLanguageMap::onLangToSuffixes
);
2644 staticMembersInitialized_
= true;
2648 void operator() (Init
* I
) {
2649 InvokeDagInitHandler(this, I
);
2654 void onLangToSuffixes (const DagInit
& d
) {
2655 CheckNumberOfArguments(d
, 2);
2657 const std::string
& Lang
= InitPtrToString(d
.getArg(0));
2658 Init
* Suffixes
= d
.getArg(1);
2660 // Second argument to lang_to_suffixes is either a single string...
2661 if (typeid(*Suffixes
) == typeid(StringInit
)) {
2662 O_
.indent(Indent1
) << "langMap[\"" << InitPtrToString(Suffixes
)
2663 << "\"] = \"" << Lang
<< "\";\n";
2665 // ...or a list of strings.
2667 const ListInit
& Lst
= InitPtrToList(Suffixes
);
2668 assert(Lst
.size() != 0);
2669 for (ListInit::const_iterator B
= Lst
.begin(), E
= Lst
.end();
2671 O_
.indent(Indent1
) << "langMap[\"" << InitPtrToString(*B
)
2672 << "\"] = \"" << Lang
<< "\";\n";
2679 /// EmitPopulateLanguageMap - Emit the PopulateLanguageMap() function.
2680 void EmitPopulateLanguageMap (const RecordKeeper
& Records
, raw_ostream
& O
)
2682 O
<< "int PopulateLanguageMap (LanguageMap& langMap) {\n";
2684 // For each LanguageMap:
2685 const RecordVector
& LangMaps
=
2686 Records
.getAllDerivedDefinitions("LanguageMap");
2688 // Call DoEmitPopulateLanguageMap.
2689 for (RecordVector::const_iterator B
= LangMaps
.begin(),
2690 E
= LangMaps
.end(); B
!=E
; ++B
) {
2691 ListInit
* LangMap
= (*B
)->getValueAsListInit("map");
2692 std::for_each(LangMap
->begin(), LangMap
->end(),
2693 DoEmitPopulateLanguageMap(O
));
2697 O
.indent(Indent1
) << "return 0;\n";
2701 /// EmitEdgePropertyHandlerCallback - Emits code that handles edge
2702 /// properties. Helper function passed to EmitCaseConstructHandler() by
2703 /// EmitEdgeClass().
2704 void EmitEdgePropertyHandlerCallback (const Init
* i
, unsigned IndentLevel
,
2706 const DagInit
& d
= InitPtrToDag(i
);
2707 const std::string
& OpName
= GetOperatorName(d
);
2709 if (OpName
== "inc_weight") {
2710 O
.indent(IndentLevel
) << "ret += ";
2712 else if (OpName
== "error") {
2713 CheckNumberOfArguments(d
, 1);
2714 O
.indent(IndentLevel
) << "PrintError(\""
2715 << InitPtrToString(d
.getArg(0))
2717 O
.indent(IndentLevel
) << "return -1;\n";
2721 throw "Unknown operator in edge properties list: '" + OpName
+ "'!"
2722 "\nOnly 'inc_weight', 'dec_weight' and 'error' are allowed.";
2725 if (d
.getNumArgs() > 0)
2726 O
<< InitPtrToInt(d
.getArg(0)) << ";\n";
2732 /// EmitEdgeClass - Emit a single Edge# class.
2733 void EmitEdgeClass (unsigned N
, const std::string
& Target
,
2734 const DagInit
& Case
, const OptionDescriptions
& OptDescs
,
2737 // Class constructor.
2738 O
<< "class Edge" << N
<< ": public Edge {\n"
2740 O
.indent(Indent1
) << "Edge" << N
<< "() : Edge(\"" << Target
2743 // Function Weight().
2745 << "int Weight(const InputLanguagesSet& InLangs) const {\n";
2746 O
.indent(Indent2
) << "unsigned ret = 0;\n";
2748 // Handle the 'case' construct.
2749 EmitCaseConstructHandler(&Case
, Indent2
, EmitEdgePropertyHandlerCallback
,
2750 false, OptDescs
, O
);
2752 O
.indent(Indent2
) << "return ret;\n";
2753 O
.indent(Indent1
) << "}\n\n};\n\n";
2756 /// EmitEdgeClasses - Emit Edge* classes that represent graph edges.
2757 void EmitEdgeClasses (const DagVector
& EdgeVector
,
2758 const OptionDescriptions
& OptDescs
,
2761 for (DagVector::const_iterator B
= EdgeVector
.begin(),
2762 E
= EdgeVector
.end(); B
!= E
; ++B
) {
2763 const DagInit
& Edge
= **B
;
2764 const std::string
& Name
= GetOperatorName(Edge
);
2766 if (Name
== "optional_edge") {
2767 assert(IsOptionalEdge(Edge
));
2768 const std::string
& NodeB
= InitPtrToString(Edge
.getArg(1));
2770 const DagInit
& Weight
= InitPtrToDag(Edge
.getArg(2));
2771 EmitEdgeClass(i
, NodeB
, Weight
, OptDescs
, O
);
2773 else if (Name
!= "edge") {
2774 throw "Unknown edge class: '" + Name
+ "'!";
2781 /// EmitPopulateCompilationGraph - Emit the PopulateCompilationGraph() function.
2782 void EmitPopulateCompilationGraph (const DagVector
& EdgeVector
,
2783 const ToolDescriptions
& ToolDescs
,
2786 O
<< "int PopulateCompilationGraph (CompilationGraph& G) {\n";
2788 for (ToolDescriptions::const_iterator B
= ToolDescs
.begin(),
2789 E
= ToolDescs
.end(); B
!= E
; ++B
)
2790 O
.indent(Indent1
) << "G.insertNode(new " << (*B
)->Name
<< "());\n";
2797 for (DagVector::const_iterator B
= EdgeVector
.begin(),
2798 E
= EdgeVector
.end(); B
!= E
; ++B
) {
2799 const DagInit
& Edge
= **B
;
2800 const std::string
& NodeA
= InitPtrToString(Edge
.getArg(0));
2801 const std::string
& NodeB
= InitPtrToString(Edge
.getArg(1));
2803 O
.indent(Indent1
) << "if (int ret = G.insertEdge(\"" << NodeA
<< "\", ";
2805 if (IsOptionalEdge(Edge
))
2806 O
<< "new Edge" << i
<< "()";
2808 O
<< "new SimpleEdge(\"" << NodeB
<< "\")";
2811 O
.indent(Indent2
) << "return ret;\n";
2817 O
.indent(Indent1
) << "return 0;\n";
2821 /// HookInfo - Information about the hook type and number of arguments.
2824 // A hook can either have a single parameter of type std::vector<std::string>,
2825 // or NumArgs parameters of type const char*.
2826 enum HookType
{ ListHook
, ArgHook
};
2831 HookInfo() : Type(ArgHook
), NumArgs(1)
2834 HookInfo(HookType T
) : Type(T
), NumArgs(1)
2837 HookInfo(unsigned N
) : Type(ArgHook
), NumArgs(N
)
2841 typedef llvm::StringMap
<HookInfo
> HookInfoMap
;
2843 /// ExtractHookNames - Extract the hook names from all instances of
2844 /// $CALL(HookName) in the provided command line string/action. Helper
2845 /// function used by FillInHookNames().
2846 class ExtractHookNames
{
2847 HookInfoMap
& HookNames_
;
2848 const OptionDescriptions
& OptDescs_
;
2850 ExtractHookNames(HookInfoMap
& HookNames
, const OptionDescriptions
& OptDescs
)
2851 : HookNames_(HookNames
), OptDescs_(OptDescs
)
2854 void onAction (const DagInit
& Dag
) {
2855 const std::string
& Name
= GetOperatorName(Dag
);
2857 if (Name
== "forward_transformed_value") {
2858 CheckNumberOfArguments(Dag
, 2);
2859 const std::string
& OptName
= InitPtrToString(Dag
.getArg(0));
2860 const std::string
& HookName
= InitPtrToString(Dag
.getArg(1));
2861 const OptionDescription
& D
=
2862 OptDescs_
.FindParameterListOrParameter(OptName
);
2864 HookNames_
[HookName
] = HookInfo(D
.isList() ? HookInfo::ListHook
2865 : HookInfo::ArgHook
);
2867 else if (Name
== "append_cmd" || Name
== "output_suffix") {
2868 CheckNumberOfArguments(Dag
, 1);
2869 this->onCmdLine(InitPtrToString(Dag
.getArg(0)));
2873 void onCmdLine(const std::string
& Cmd
) {
2875 TokenizeCmdLine(Cmd
, cmds
);
2877 for (StrVector::const_iterator B
= cmds
.begin(), E
= cmds
.end();
2879 const std::string
& cmd
= *B
;
2881 if (cmd
== "$CALL") {
2882 unsigned NumArgs
= 0;
2883 CheckedIncrement(B
, E
, "Syntax error in $CALL invocation!");
2884 const std::string
& HookName
= *B
;
2886 if (HookName
.at(0) == ')')
2887 throw "$CALL invoked with no arguments!";
2889 while (++B
!= E
&& B
->at(0) != ')') {
2893 HookInfoMap::const_iterator H
= HookNames_
.find(HookName
);
2895 if (H
!= HookNames_
.end() && H
->second
.NumArgs
!= NumArgs
&&
2896 H
->second
.Type
!= HookInfo::ArgHook
)
2897 throw "Overloading of hooks is not allowed. Overloaded hook: "
2900 HookNames_
[HookName
] = HookInfo(NumArgs
);
2905 void operator()(const Init
* Arg
) {
2907 // We're invoked on an action (either a dag or a dag list).
2908 if (typeid(*Arg
) == typeid(DagInit
)) {
2909 const DagInit
& Dag
= InitPtrToDag(Arg
);
2910 this->onAction(Dag
);
2913 else if (typeid(*Arg
) == typeid(ListInit
)) {
2914 const ListInit
& List
= InitPtrToList(Arg
);
2915 for (ListInit::const_iterator B
= List
.begin(), E
= List
.end(); B
!= E
;
2917 const DagInit
& Dag
= InitPtrToDag(*B
);
2918 this->onAction(Dag
);
2923 // We're invoked on a command line string.
2924 this->onCmdLine(InitPtrToString(Arg
));
2927 void operator()(const Init
* Statement
, unsigned) {
2928 this->operator()(Statement
);
2932 /// FillInHookNames - Actually extract the hook names from all command
2933 /// line strings. Helper function used by EmitHookDeclarations().
2934 void FillInHookNames(const ToolDescriptions
& ToolDescs
,
2935 const OptionDescriptions
& OptDescs
,
2936 HookInfoMap
& HookNames
)
2938 // For all tool descriptions:
2939 for (ToolDescriptions::const_iterator B
= ToolDescs
.begin(),
2940 E
= ToolDescs
.end(); B
!= E
; ++B
) {
2941 const ToolDescription
& D
= *(*B
);
2943 // Look for 'forward_transformed_value' in 'actions'.
2945 WalkCase(D
.Actions
, Id(), ExtractHookNames(HookNames
, OptDescs
));
2947 // Look for hook invocations in 'cmd_line'.
2950 if (dynamic_cast<StringInit
*>(D
.CmdLine
))
2951 // This is a string.
2952 ExtractHookNames(HookNames
, OptDescs
).operator()(D
.CmdLine
);
2954 // This is a 'case' construct.
2955 WalkCase(D
.CmdLine
, Id(), ExtractHookNames(HookNames
, OptDescs
));
2959 /// EmitHookDeclarations - Parse CmdLine fields of all the tool
2960 /// property records and emit hook function declaration for each
2961 /// instance of $CALL(HookName).
2962 void EmitHookDeclarations(const ToolDescriptions
& ToolDescs
,
2963 const OptionDescriptions
& OptDescs
, raw_ostream
& O
) {
2964 HookInfoMap HookNames
;
2966 FillInHookNames(ToolDescs
, OptDescs
, HookNames
);
2967 if (HookNames
.empty())
2970 for (HookInfoMap::const_iterator B
= HookNames
.begin(),
2971 E
= HookNames
.end(); B
!= E
; ++B
) {
2972 const char* HookName
= B
->first();
2973 const HookInfo
& Info
= B
->second
;
2975 O
.indent(Indent1
) << "std::string " << HookName
<< "(";
2977 if (Info
.Type
== HookInfo::ArgHook
) {
2978 for (unsigned i
= 0, j
= Info
.NumArgs
; i
< j
; ++i
) {
2979 O
<< "const char* Arg" << i
<< (i
+1 == j
? "" : ", ");
2983 O
<< "const std::vector<std::string>& Arg";
2990 /// EmitIncludes - Emit necessary #include directives and some
2991 /// additional declarations.
2992 void EmitIncludes(raw_ostream
& O
) {
2993 O
<< "#include \"llvm/CompilerDriver/BuiltinOptions.h\"\n"
2994 << "#include \"llvm/CompilerDriver/CompilationGraph.h\"\n"
2995 << "#include \"llvm/CompilerDriver/Error.h\"\n"
2996 << "#include \"llvm/CompilerDriver/Tool.h\"\n\n"
2998 << "#include \"llvm/Support/CommandLine.h\"\n"
2999 << "#include \"llvm/Support/raw_ostream.h\"\n\n"
3001 << "#include <algorithm>\n"
3002 << "#include <cstdlib>\n"
3003 << "#include <iterator>\n"
3004 << "#include <stdexcept>\n\n"
3006 << "using namespace llvm;\n"
3007 << "using namespace llvmc;\n\n"
3009 << "inline const char* checkCString(const char* s)\n"
3010 << "{ return s == NULL ? \"\" : s; }\n\n";
3014 /// DriverData - Holds all information about the driver.
3016 OptionDescriptions OptDescs
;
3017 ToolDescriptions ToolDescs
;
3022 /// HasSink - Go through the list of tool descriptions and check if
3023 /// there are any with the 'sink' property set.
3024 bool HasSink(const ToolDescriptions
& ToolDescs
) {
3025 for (ToolDescriptions::const_iterator B
= ToolDescs
.begin(),
3026 E
= ToolDescs
.end(); B
!= E
; ++B
)
3033 /// CollectDriverData - Collect compilation graph edges, tool properties and
3034 /// option properties from the parse tree.
3035 void CollectDriverData (const RecordKeeper
& Records
, DriverData
& Data
) {
3036 // Collect option properties.
3037 const RecordVector
& OptionLists
=
3038 Records
.getAllDerivedDefinitions("OptionList");
3039 CollectOptionDescriptions(OptionLists
, Data
.OptDescs
);
3041 // Collect tool properties.
3042 const RecordVector
& Tools
= Records
.getAllDerivedDefinitions("Tool");
3043 CollectToolDescriptions(Tools
, Data
.ToolDescs
);
3044 Data
.HasSink
= HasSink(Data
.ToolDescs
);
3046 // Collect compilation graph edges.
3047 const RecordVector
& CompilationGraphs
=
3048 Records
.getAllDerivedDefinitions("CompilationGraph");
3049 FillInEdgeVector(CompilationGraphs
, Data
.Edges
);
3052 /// CheckDriverData - Perform some sanity checks on the collected data.
3053 void CheckDriverData(DriverData
& Data
) {
3054 // Filter out all tools not mentioned in the compilation graph.
3055 FilterNotInGraph(Data
.Edges
, Data
.ToolDescs
);
3057 // Typecheck the compilation graph.
3058 // TODO: use a genuine graph representation instead of a vector and check for
3060 TypecheckGraph(Data
.Edges
, Data
.ToolDescs
);
3062 // Check that there are no options without side effects (specified
3063 // only in the OptionList).
3064 CheckForSuperfluousOptions(Data
.Edges
, Data
.ToolDescs
, Data
.OptDescs
);
3067 void EmitDriverCode(const DriverData
& Data
,
3068 raw_ostream
& O
, RecordKeeper
&Records
) {
3069 // Emit file header.
3072 // Emit global option registration code.
3073 O
<< "namespace llvmc {\n"
3074 << "namespace autogenerated {\n\n";
3075 EmitOptionDefinitions(Data
.OptDescs
, Data
.HasSink
, O
);
3076 O
<< "} // End namespace autogenerated.\n"
3077 << "} // End namespace llvmc.\n\n";
3079 // Emit hook declarations.
3080 O
<< "namespace hooks {\n";
3081 EmitHookDeclarations(Data
.ToolDescs
, Data
.OptDescs
, O
);
3082 O
<< "} // End namespace hooks.\n\n";
3084 O
<< "namespace {\n\n";
3085 O
<< "using namespace llvmc::autogenerated;\n\n";
3087 // Emit Tool classes.
3088 for (ToolDescriptions::const_iterator B
= Data
.ToolDescs
.begin(),
3089 E
= Data
.ToolDescs
.end(); B
!=E
; ++B
)
3090 EmitToolClassDefinition(*(*B
), Data
.OptDescs
, O
);
3092 // Emit Edge# classes.
3093 EmitEdgeClasses(Data
.Edges
, Data
.OptDescs
, O
);
3095 O
<< "} // End anonymous namespace.\n\n";
3097 O
<< "namespace llvmc {\n";
3098 O
<< "namespace autogenerated {\n\n";
3100 // Emit PreprocessOptions() function.
3101 EmitPreprocessOptions(Records
, Data
.OptDescs
, O
);
3103 // Emit PopulateLanguageMap() function
3104 // (language map maps from file extensions to language names).
3105 EmitPopulateLanguageMap(Records
, O
);
3107 // Emit PopulateCompilationGraph() function.
3108 EmitPopulateCompilationGraph(Data
.Edges
, Data
.ToolDescs
, O
);
3110 O
<< "} // End namespace autogenerated.\n";
3111 O
<< "} // End namespace llvmc.\n\n";
3117 // End of anonymous namespace
3120 /// run - The back-end entry point.
3121 void LLVMCConfigurationEmitter::run (raw_ostream
&O
) {
3125 CollectDriverData(Records
, Data
);
3126 CheckDriverData(Data
);
3128 this->EmitSourceFileHeader("llvmc-based driver: auto-generated code", O
);
3129 EmitDriverCode(Data
, O
, Records
);
3131 } catch (std::exception
& Error
) {
3132 throw Error
.what() + std::string(" - usually this means a syntax error.");