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);
771 // Alias option store the aliased option name in the 'Help' field and do not
772 // have any properties.
774 OD
.Help
= InitPtrToString(d
.getArg(1));
777 processOptionProperties(d
, OD
);
780 // Switch options are ZeroOrMore by default.
782 if (!(OD
.isOptional() || OD
.isOneOrMore() || OD
.isRequired()))
786 OptDescs_
.InsertDescription(OD
);
790 /// processOptionProperties - Go through the list of option
791 /// properties and call a corresponding handler for each.
792 static void processOptionProperties (const DagInit
& d
, OptionDescription
& o
) {
793 CheckNumberOfArguments(d
, 2);
794 DagInit::const_arg_iterator B
= d
.arg_begin();
795 // Skip the first argument: it's always the option name.
797 std::for_each(B
, d
.arg_end(), CollectOptionProperties(o
));
802 /// CollectOptionDescriptions - Collects option properties from all
804 void CollectOptionDescriptions (const RecordVector
& V
,
805 OptionDescriptions
& OptDescs
)
807 // For every OptionList:
808 for (RecordVector::const_iterator B
= V
.begin(), E
= V
.end(); B
!=E
; ++B
)
810 // Throws an exception if the value does not exist.
811 ListInit
* PropList
= (*B
)->getValueAsListInit("options");
813 // For every option description in this list: invoke AddOption.
814 std::for_each(PropList
->begin(), PropList
->end(), AddOption(OptDescs
));
818 // Tool information record
820 namespace ToolFlags
{
821 enum ToolFlags
{ Join
= 0x1, Sink
= 0x2 };
824 struct ToolDescription
: public RefCountedBase
<ToolDescription
> {
828 StrVector InLanguage
;
829 std::string InFileOption
;
830 std::string OutFileOption
;
831 StrVector OutLanguage
;
832 std::string OutputSuffix
;
836 // Various boolean properties
837 void setSink() { Flags
|= ToolFlags::Sink
; }
838 bool isSink() const { return Flags
& ToolFlags::Sink
; }
839 void setJoin() { Flags
|= ToolFlags::Join
; }
840 bool isJoin() const { return Flags
& ToolFlags::Join
; }
842 // Default ctor here is needed because StringMap can only store
843 // DefaultConstructible objects
844 ToolDescription (const std::string
&n
= "")
845 : Name(n
), CmdLine(0), Actions(0), OutFileOption("-o"),
850 /// ToolDescriptions - A list of Tool information records.
851 typedef std::vector
<IntrusiveRefCntPtr
<ToolDescription
> > ToolDescriptions
;
854 /// CollectToolProperties - Function object for iterating over a list of
855 /// tool property records.
857 class CollectToolProperties
;
858 typedef void (CollectToolProperties::* CollectToolPropertiesHandler
)
861 class CollectToolProperties
: public HandlerTable
<CollectToolPropertiesHandler
>
865 /// toolDesc_ - Properties of the current Tool. This is where the
866 /// information is stored.
867 ToolDescription
& toolDesc_
;
871 explicit CollectToolProperties (ToolDescription
& d
)
874 if (!staticMembersInitialized_
) {
876 AddHandler("actions", &CollectToolProperties::onActions
);
877 AddHandler("command", &CollectToolProperties::onCommand
);
878 AddHandler("in_language", &CollectToolProperties::onInLanguage
);
879 AddHandler("join", &CollectToolProperties::onJoin
);
880 AddHandler("out_language", &CollectToolProperties::onOutLanguage
);
882 AddHandler("out_file_option", &CollectToolProperties::onOutFileOption
);
883 AddHandler("in_file_option", &CollectToolProperties::onInFileOption
);
885 AddHandler("output_suffix", &CollectToolProperties::onOutputSuffix
);
886 AddHandler("sink", &CollectToolProperties::onSink
);
887 AddHandler("works_on_empty", &CollectToolProperties::onWorksOnEmpty
);
889 staticMembersInitialized_
= true;
893 void operator() (Init
* I
) {
894 InvokeDagInitHandler(this, I
);
899 /// Property handlers --
900 /// Functions that extract information about tool properties from
901 /// DAG representation.
903 void onActions (const DagInit
& d
) {
904 CheckNumberOfArguments(d
, 1);
905 Init
* Case
= d
.getArg(0);
906 if (typeid(*Case
) != typeid(DagInit
) ||
907 GetOperatorName(static_cast<DagInit
&>(*Case
)) != "case")
908 throw "The argument to (actions) should be a 'case' construct!";
909 toolDesc_
.Actions
= Case
;
912 void onCommand (const DagInit
& d
) {
913 CheckNumberOfArguments(d
, 1);
914 toolDesc_
.CmdLine
= d
.getArg(0);
917 /// onInOutLanguage - Common implementation of on{In,Out}Language().
918 void onInOutLanguage (const DagInit
& d
, StrVector
& OutVec
) {
919 CheckNumberOfArguments(d
, 1);
921 // Copy strings to the output vector.
922 for (unsigned i
= 0, NumArgs
= d
.getNumArgs(); i
< NumArgs
; ++i
) {
923 OutVec
.push_back(InitPtrToString(d
.getArg(i
)));
926 // Remove duplicates.
927 std::sort(OutVec
.begin(), OutVec
.end());
928 StrVector::iterator newE
= std::unique(OutVec
.begin(), OutVec
.end());
929 OutVec
.erase(newE
, OutVec
.end());
933 void onInLanguage (const DagInit
& d
) {
934 this->onInOutLanguage(d
, toolDesc_
.InLanguage
);
937 void onJoin (const DagInit
& d
) {
938 CheckNumberOfArguments(d
, 0);
942 void onOutLanguage (const DagInit
& d
) {
943 this->onInOutLanguage(d
, toolDesc_
.OutLanguage
);
946 void onOutFileOption (const DagInit
& d
) {
947 CheckNumberOfArguments(d
, 1);
948 toolDesc_
.OutFileOption
= InitPtrToString(d
.getArg(0));
951 void onInFileOption (const DagInit
& d
) {
952 CheckNumberOfArguments(d
, 1);
953 toolDesc_
.InFileOption
= InitPtrToString(d
.getArg(0));
956 void onOutputSuffix (const DagInit
& d
) {
957 CheckNumberOfArguments(d
, 1);
958 toolDesc_
.OutputSuffix
= InitPtrToString(d
.getArg(0));
961 void onSink (const DagInit
& d
) {
962 CheckNumberOfArguments(d
, 0);
966 void onWorksOnEmpty (const DagInit
& d
) {
967 toolDesc_
.OnEmpty
= d
.getArg(0);
972 /// CollectToolDescriptions - Gather information about tool properties
973 /// from the parsed TableGen data (basically a wrapper for the
974 /// CollectToolProperties function object).
975 void CollectToolDescriptions (const RecordVector
& Tools
,
976 ToolDescriptions
& ToolDescs
)
978 // Iterate over a properties list of every Tool definition
979 for (RecordVector::const_iterator B
= Tools
.begin(),
980 E
= Tools
.end(); B
!=E
; ++B
) {
981 const Record
* T
= *B
;
982 // Throws an exception if the value does not exist.
983 ListInit
* PropList
= T
->getValueAsListInit("properties");
985 IntrusiveRefCntPtr
<ToolDescription
>
986 ToolDesc(new ToolDescription(T
->getName()));
988 std::for_each(PropList
->begin(), PropList
->end(),
989 CollectToolProperties(*ToolDesc
));
990 ToolDescs
.push_back(ToolDesc
);
994 /// FillInEdgeVector - Merge all compilation graph definitions into
995 /// one single edge list.
996 void FillInEdgeVector(const RecordVector
& CompilationGraphs
,
998 for (RecordVector::const_iterator B
= CompilationGraphs
.begin(),
999 E
= CompilationGraphs
.end(); B
!= E
; ++B
) {
1000 const ListInit
* Edges
= (*B
)->getValueAsListInit("edges");
1002 for (ListInit::const_iterator B
= Edges
->begin(),
1003 E
= Edges
->end(); B
!= E
; ++B
) {
1004 Out
.push_back(&InitPtrToDag(*B
));
1009 /// NotInGraph - Helper function object for FilterNotInGraph.
1012 const llvm::StringSet
<>& ToolsInGraph_
;
1015 NotInGraph(const llvm::StringSet
<>& ToolsInGraph
)
1016 : ToolsInGraph_(ToolsInGraph
)
1019 bool operator()(const IntrusiveRefCntPtr
<ToolDescription
>& x
) {
1020 return (ToolsInGraph_
.count(x
->Name
) == 0);
1024 /// FilterNotInGraph - Filter out from ToolDescs all Tools not
1025 /// mentioned in the compilation graph definition.
1026 void FilterNotInGraph (const DagVector
& EdgeVector
,
1027 ToolDescriptions
& ToolDescs
) {
1029 // List all tools mentioned in the graph.
1030 llvm::StringSet
<> ToolsInGraph
;
1032 for (DagVector::const_iterator B
= EdgeVector
.begin(),
1033 E
= EdgeVector
.end(); B
!= E
; ++B
) {
1035 const DagInit
* Edge
= *B
;
1036 const std::string
& NodeA
= InitPtrToString(Edge
->getArg(0));
1037 const std::string
& NodeB
= InitPtrToString(Edge
->getArg(1));
1039 if (NodeA
!= "root")
1040 ToolsInGraph
.insert(NodeA
);
1041 ToolsInGraph
.insert(NodeB
);
1044 // Filter ToolPropertiesList.
1045 ToolDescriptions::iterator new_end
=
1046 std::remove_if(ToolDescs
.begin(), ToolDescs
.end(),
1047 NotInGraph(ToolsInGraph
));
1048 ToolDescs
.erase(new_end
, ToolDescs
.end());
1051 /// FillInToolToLang - Fills in two tables that map tool names to
1052 /// input & output language names. Helper function used by TypecheckGraph().
1053 void FillInToolToLang (const ToolDescriptions
& ToolDescs
,
1054 StringMap
<StringSet
<> >& ToolToInLang
,
1055 StringMap
<StringSet
<> >& ToolToOutLang
) {
1056 for (ToolDescriptions::const_iterator B
= ToolDescs
.begin(),
1057 E
= ToolDescs
.end(); B
!= E
; ++B
) {
1058 const ToolDescription
& D
= *(*B
);
1059 for (StrVector::const_iterator B
= D
.InLanguage
.begin(),
1060 E
= D
.InLanguage
.end(); B
!= E
; ++B
)
1061 ToolToInLang
[D
.Name
].insert(*B
);
1062 for (StrVector::const_iterator B
= D
.OutLanguage
.begin(),
1063 E
= D
.OutLanguage
.end(); B
!= E
; ++B
)
1064 ToolToOutLang
[D
.Name
].insert(*B
);
1068 /// Intersect - Is set intersection non-empty?
1069 bool Intersect (const StringSet
<>& S1
, const StringSet
<>& S2
) {
1070 for (StringSet
<>::const_iterator B
= S1
.begin(), E
= S1
.end(); B
!= E
; ++B
) {
1071 if (S2
.count(B
->first()) != 0)
1077 /// TypecheckGraph - Check that names for output and input languages
1078 /// on all edges do match.
1079 void TypecheckGraph (const DagVector
& EdgeVector
,
1080 const ToolDescriptions
& ToolDescs
) {
1081 StringMap
<StringSet
<> > ToolToInLang
;
1082 StringMap
<StringSet
<> > ToolToOutLang
;
1084 FillInToolToLang(ToolDescs
, ToolToInLang
, ToolToOutLang
);
1086 for (DagVector::const_iterator B
= EdgeVector
.begin(),
1087 E
= EdgeVector
.end(); B
!= E
; ++B
) {
1088 const DagInit
* Edge
= *B
;
1089 const std::string
& NodeA
= InitPtrToString(Edge
->getArg(0));
1090 const std::string
& NodeB
= InitPtrToString(Edge
->getArg(1));
1091 StringMap
<StringSet
<> >::iterator IA
= ToolToOutLang
.find(NodeA
);
1092 StringMap
<StringSet
<> >::iterator IB
= ToolToInLang
.find(NodeB
);
1094 if (NodeB
== "root")
1095 throw "Edges back to the root are not allowed!";
1097 if (NodeA
!= "root") {
1098 if (IA
== ToolToOutLang
.end())
1099 throw NodeA
+ ": no output language defined!";
1100 if (IB
== ToolToInLang
.end())
1101 throw NodeB
+ ": no input language defined!";
1103 if (!Intersect(IA
->second
, IB
->second
)) {
1104 throw "Edge " + NodeA
+ "->" + NodeB
1105 + ": output->input language mismatch";
1111 /// WalkCase - Walks the 'case' expression DAG and invokes
1112 /// TestCallback on every test, and StatementCallback on every
1113 /// statement. Handles 'case' nesting, but not the 'and' and 'or'
1114 /// combinators (that is, they are passed directly to TestCallback).
1115 /// TestCallback must have type 'void TestCallback(const DagInit*, unsigned
1116 /// IndentLevel, bool FirstTest)'.
1117 /// StatementCallback must have type 'void StatementCallback(const Init*,
1118 /// unsigned IndentLevel)'.
1119 template <typename F1
, typename F2
>
1120 void WalkCase(const Init
* Case
, F1 TestCallback
, F2 StatementCallback
,
1121 unsigned IndentLevel
= 0)
1123 const DagInit
& d
= InitPtrToDag(Case
);
1126 if (GetOperatorName(d
) != "case")
1127 throw "WalkCase should be invoked only on 'case' expressions!";
1129 if (d
.getNumArgs() < 2)
1130 throw "There should be at least one clause in the 'case' expression:\n"
1135 const unsigned numArgs
= d
.getNumArgs();
1137 for (DagInit::const_arg_iterator B
= d
.arg_begin(), E
= d
.arg_end();
1144 const DagInit
& Test
= InitPtrToDag(arg
);
1146 if (GetOperatorName(Test
) == "default" && (i
+1 != numArgs
))
1147 throw "The 'default' clause should be the last in the "
1148 "'case' construct!";
1150 throw "Case construct handler: no corresponding action "
1151 "found for the test " + Test
.getAsString() + '!';
1153 TestCallback(Test
, IndentLevel
, (i
== 1));
1157 if (dynamic_cast<DagInit
*>(arg
)
1158 && GetOperatorName(static_cast<DagInit
&>(*arg
)) == "case") {
1160 WalkCase(arg
, TestCallback
, StatementCallback
, IndentLevel
+ Indent1
);
1163 // Handle statement.
1164 StatementCallback(arg
, IndentLevel
);
1172 /// ExtractOptionNames - A helper function object used by
1173 /// CheckForSuperfluousOptions() to walk the 'case' DAG.
1174 class ExtractOptionNames
{
1175 llvm::StringSet
<>& OptionNames_
;
1177 void processDag(const Init
* Statement
) {
1178 const DagInit
& Stmt
= InitPtrToDag(Statement
);
1179 const std::string
& ActionName
= GetOperatorName(Stmt
);
1180 if (ActionName
== "forward" || ActionName
== "forward_as" ||
1181 ActionName
== "forward_value" ||
1182 ActionName
== "forward_transformed_value" ||
1183 ActionName
== "parameter_equals" || ActionName
== "element_in_list") {
1184 CheckNumberOfArguments(Stmt
, 1);
1186 Init
* Arg
= Stmt
.getArg(0);
1187 if (typeid(*Arg
) == typeid(StringInit
))
1188 OptionNames_
.insert(InitPtrToString(Arg
));
1190 else if (ActionName
== "any_switch_on" || ActionName
== "switch_on" ||
1191 ActionName
== "any_not_empty" || ActionName
== "any_empty" ||
1192 ActionName
== "not_empty" || ActionName
== "empty") {
1193 for (unsigned i
= 0, NumArgs
= Stmt
.getNumArgs(); i
< NumArgs
; ++i
) {
1194 Init
* Arg
= Stmt
.getArg(i
);
1195 if (typeid(*Arg
) == typeid(StringInit
))
1196 OptionNames_
.insert(InitPtrToString(Arg
));
1199 else if (ActionName
== "and" || ActionName
== "or" || ActionName
== "not") {
1200 for (unsigned i
= 0, NumArgs
= Stmt
.getNumArgs(); i
< NumArgs
; ++i
) {
1201 this->processDag(Stmt
.getArg(i
));
1207 ExtractOptionNames(llvm::StringSet
<>& OptionNames
) : OptionNames_(OptionNames
)
1210 void operator()(const Init
* Statement
) {
1211 // Statement is either a dag, or a list of dags.
1212 if (typeid(*Statement
) == typeid(ListInit
)) {
1213 const ListInit
& DagList
= *static_cast<const ListInit
*>(Statement
);
1214 for (ListInit::const_iterator B
= DagList
.begin(), E
= DagList
.end();
1216 this->processDag(*B
);
1219 this->processDag(Statement
);
1223 void operator()(const DagInit
& Test
, unsigned, bool) {
1224 this->operator()(&Test
);
1226 void operator()(const Init
* Statement
, unsigned) {
1227 this->operator()(Statement
);
1231 /// IsOptionalEdge - Validate that the 'optional_edge' has proper structure.
1232 bool IsOptionalEdge (const DagInit
& Edg
) {
1233 return (GetOperatorName(Edg
) == "optional_edge") && (Edg
.getNumArgs() > 2);
1236 /// CheckForSuperfluousOptions - Check that there are no side
1237 /// effect-free options (specified only in the OptionList). Otherwise,
1238 /// output a warning.
1239 void CheckForSuperfluousOptions (const DagVector
& EdgeVector
,
1240 const ToolDescriptions
& ToolDescs
,
1241 const OptionDescriptions
& OptDescs
) {
1242 llvm::StringSet
<> nonSuperfluousOptions
;
1244 // Add all options mentioned in the ToolDesc.Actions to the set of
1245 // non-superfluous options.
1246 for (ToolDescriptions::const_iterator B
= ToolDescs
.begin(),
1247 E
= ToolDescs
.end(); B
!= E
; ++B
) {
1248 const ToolDescription
& TD
= *(*B
);
1249 ExtractOptionNames
Callback(nonSuperfluousOptions
);
1251 WalkCase(TD
.Actions
, Callback
, Callback
);
1254 // Add all options mentioned in the 'case' clauses of the
1255 // OptionalEdges of the compilation graph to the set of
1256 // non-superfluous options.
1257 for (DagVector::const_iterator B
= EdgeVector
.begin(),
1258 E
= EdgeVector
.end(); B
!= E
; ++B
) {
1259 const DagInit
& Edge
= **B
;
1260 if (IsOptionalEdge(Edge
)) {
1261 const DagInit
& Weight
= InitPtrToDag(Edge
.getArg(2));
1262 WalkCase(&Weight
, ExtractOptionNames(nonSuperfluousOptions
), Id());
1266 // Check that all options in OptDescs belong to the set of
1267 // non-superfluous options.
1268 for (OptionDescriptions::const_iterator B
= OptDescs
.begin(),
1269 E
= OptDescs
.end(); B
!= E
; ++B
) {
1270 const OptionDescription
& Val
= B
->second
;
1271 if (!nonSuperfluousOptions
.count(Val
.Name
)
1272 && Val
.Type
!= OptionType::Alias
)
1273 llvm::errs() << "Warning: option '-" << Val
.Name
<< "' has no effect! "
1274 "Probable cause: this option is specified only in the OptionList.\n";
1278 /// EmitCaseTest0Args - Helper function used by EmitCaseConstructHandler().
1279 bool EmitCaseTest0Args(const std::string
& TestName
, raw_ostream
& O
) {
1280 if (TestName
== "single_input_file") {
1281 O
<< "InputFilenames.size() == 1";
1284 else if (TestName
== "multiple_input_files") {
1285 O
<< "InputFilenames.size() > 1";
1292 /// EmitMultipleArgumentTest - Helper function used by
1293 /// EmitCaseTestMultipleArgs()
1294 template <typename F
>
1295 void EmitMultipleArgumentTest(const DagInit
& D
, const char* LogicOp
,
1296 F Callback
, raw_ostream
& O
)
1298 for (unsigned i
= 0, NumArgs
= D
.getNumArgs(); i
< NumArgs
; ++i
) {
1300 O
<< ' ' << LogicOp
<< ' ';
1301 Callback(InitPtrToString(D
.getArg(i
)), O
);
1305 // Callbacks for use with EmitMultipleArgumentTest
1307 class EmitSwitchOn
{
1308 const OptionDescriptions
& OptDescs_
;
1310 EmitSwitchOn(const OptionDescriptions
& OptDescs
) : OptDescs_(OptDescs
)
1313 void operator()(const std::string
& OptName
, raw_ostream
& O
) const {
1314 const OptionDescription
& OptDesc
= OptDescs_
.FindSwitch(OptName
);
1315 O
<< OptDesc
.GenVariableName();
1319 class EmitEmptyTest
{
1321 const OptionDescriptions
& OptDescs_
;
1323 EmitEmptyTest(bool EmitNegate
, const OptionDescriptions
& OptDescs
)
1324 : EmitNegate_(EmitNegate
), OptDescs_(OptDescs
)
1327 void operator()(const std::string
& OptName
, raw_ostream
& O
) const {
1328 const char* Neg
= (EmitNegate_
? "!" : "");
1329 if (OptName
== "o") {
1330 O
<< Neg
<< "OutputFilename.empty()";
1332 else if (OptName
== "save-temps") {
1333 O
<< Neg
<< "(SaveTemps == SaveTempsEnum::Unset)";
1336 const OptionDescription
& OptDesc
= OptDescs_
.FindListOrParameter(OptName
);
1337 O
<< Neg
<< OptDesc
.GenVariableName() << ".empty()";
1343 /// EmitCaseTestMultipleArgs - Helper function used by EmitCaseTest1Arg()
1344 bool EmitCaseTestMultipleArgs (const std::string
& TestName
,
1346 const OptionDescriptions
& OptDescs
,
1348 if (TestName
== "any_switch_on") {
1349 EmitMultipleArgumentTest(d
, "||", EmitSwitchOn(OptDescs
), O
);
1352 else if (TestName
== "switch_on") {
1353 EmitMultipleArgumentTest(d
, "&&", EmitSwitchOn(OptDescs
), O
);
1356 else if (TestName
== "any_not_empty") {
1357 EmitMultipleArgumentTest(d
, "||", EmitEmptyTest(true, OptDescs
), O
);
1360 else if (TestName
== "any_empty") {
1361 EmitMultipleArgumentTest(d
, "||", EmitEmptyTest(false, OptDescs
), O
);
1364 else if (TestName
== "not_empty") {
1365 EmitMultipleArgumentTest(d
, "&&", EmitEmptyTest(true, OptDescs
), O
);
1368 else if (TestName
== "empty") {
1369 EmitMultipleArgumentTest(d
, "&&", EmitEmptyTest(false, OptDescs
), O
);
1376 /// EmitCaseTest1Arg - Helper function used by EmitCaseTest1OrMoreArgs()
1377 bool EmitCaseTest1Arg (const std::string
& TestName
,
1379 const OptionDescriptions
& OptDescs
,
1381 const std::string
& Arg
= InitPtrToString(d
.getArg(0));
1383 if (TestName
== "input_languages_contain") {
1384 O
<< "InLangs.count(\"" << Arg
<< "\") != 0";
1387 else if (TestName
== "in_language") {
1388 // This works only for single-argument Tool::GenerateAction. Join
1389 // tools can process several files in different languages simultaneously.
1391 // TODO: make this work with Edge::Weight (if possible).
1392 O
<< "LangMap.GetLanguage(inFile) == \"" << Arg
<< '\"';
1399 /// EmitCaseTest1OrMoreArgs - Helper function used by
1400 /// EmitCaseConstructHandler()
1401 bool EmitCaseTest1OrMoreArgs(const std::string
& TestName
,
1403 const OptionDescriptions
& OptDescs
,
1405 CheckNumberOfArguments(d
, 1);
1406 return EmitCaseTest1Arg(TestName
, d
, OptDescs
, O
) ||
1407 EmitCaseTestMultipleArgs(TestName
, d
, OptDescs
, O
);
1410 /// EmitCaseTest2Args - Helper function used by EmitCaseConstructHandler().
1411 bool EmitCaseTest2Args(const std::string
& TestName
,
1413 unsigned IndentLevel
,
1414 const OptionDescriptions
& OptDescs
,
1416 CheckNumberOfArguments(d
, 2);
1417 const std::string
& OptName
= InitPtrToString(d
.getArg(0));
1418 const std::string
& OptArg
= InitPtrToString(d
.getArg(1));
1420 if (TestName
== "parameter_equals") {
1421 const OptionDescription
& OptDesc
= OptDescs
.FindParameter(OptName
);
1422 O
<< OptDesc
.GenVariableName() << " == \"" << OptArg
<< "\"";
1425 else if (TestName
== "element_in_list") {
1426 const OptionDescription
& OptDesc
= OptDescs
.FindParameterList(OptName
);
1427 const std::string
& VarName
= OptDesc
.GenVariableName();
1428 O
<< "std::find(" << VarName
<< ".begin(),\n";
1429 O
.indent(IndentLevel
+ Indent1
)
1430 << VarName
<< ".end(), \""
1431 << OptArg
<< "\") != " << VarName
<< ".end()";
1438 // Forward declaration.
1439 // EmitLogicalOperationTest and EmitCaseTest are mutually recursive.
1440 void EmitCaseTest(const DagInit
& d
, unsigned IndentLevel
,
1441 const OptionDescriptions
& OptDescs
,
1444 /// EmitLogicalOperationTest - Helper function used by
1445 /// EmitCaseConstructHandler.
1446 void EmitLogicalOperationTest(const DagInit
& d
, const char* LogicOp
,
1447 unsigned IndentLevel
,
1448 const OptionDescriptions
& OptDescs
,
1451 for (unsigned i
= 0, NumArgs
= d
.getNumArgs(); i
< NumArgs
; ++i
) {
1452 const DagInit
& InnerTest
= InitPtrToDag(d
.getArg(i
));
1453 EmitCaseTest(InnerTest
, IndentLevel
, OptDescs
, O
);
1454 if (i
!= NumArgs
- 1) {
1456 O
.indent(IndentLevel
+ Indent1
) << ' ' << LogicOp
<< " (";
1464 void EmitLogicalNot(const DagInit
& d
, unsigned IndentLevel
,
1465 const OptionDescriptions
& OptDescs
, raw_ostream
& O
)
1467 CheckNumberOfArguments(d
, 1);
1468 const DagInit
& InnerTest
= InitPtrToDag(d
.getArg(0));
1470 EmitCaseTest(InnerTest
, IndentLevel
, OptDescs
, O
);
1474 /// EmitCaseTest - Helper function used by EmitCaseConstructHandler.
1475 void EmitCaseTest(const DagInit
& d
, unsigned IndentLevel
,
1476 const OptionDescriptions
& OptDescs
,
1478 const std::string
& TestName
= GetOperatorName(d
);
1480 if (TestName
== "and")
1481 EmitLogicalOperationTest(d
, "&&", IndentLevel
, OptDescs
, O
);
1482 else if (TestName
== "or")
1483 EmitLogicalOperationTest(d
, "||", IndentLevel
, OptDescs
, O
);
1484 else if (TestName
== "not")
1485 EmitLogicalNot(d
, IndentLevel
, OptDescs
, O
);
1486 else if (EmitCaseTest0Args(TestName
, O
))
1488 else if (EmitCaseTest1OrMoreArgs(TestName
, d
, OptDescs
, O
))
1490 else if (EmitCaseTest2Args(TestName
, d
, IndentLevel
, OptDescs
, O
))
1493 throw "Unknown test '" + TestName
+ "' used in the 'case' construct!";
1497 /// EmitCaseTestCallback - Callback used by EmitCaseConstructHandler.
1498 class EmitCaseTestCallback
{
1500 const OptionDescriptions
& OptDescs_
;
1504 EmitCaseTestCallback(bool EmitElseIf
,
1505 const OptionDescriptions
& OptDescs
, raw_ostream
& O
)
1506 : EmitElseIf_(EmitElseIf
), OptDescs_(OptDescs
), O_(O
)
1509 void operator()(const DagInit
& Test
, unsigned IndentLevel
, bool FirstTest
)
1511 if (GetOperatorName(Test
) == "default") {
1512 O_
.indent(IndentLevel
) << "else {\n";
1515 O_
.indent(IndentLevel
)
1516 << ((!FirstTest
&& EmitElseIf_
) ? "else if (" : "if (");
1517 EmitCaseTest(Test
, IndentLevel
, OptDescs_
, O_
);
1523 /// EmitCaseStatementCallback - Callback used by EmitCaseConstructHandler.
1524 template <typename F
>
1525 class EmitCaseStatementCallback
{
1530 EmitCaseStatementCallback(F Callback
, raw_ostream
& O
)
1531 : Callback_(Callback
), O_(O
)
1534 void operator() (const Init
* Statement
, unsigned IndentLevel
) {
1535 // Is this a nested 'case'?
1536 bool IsCase
= dynamic_cast<const DagInit
*>(Statement
) &&
1537 GetOperatorName(static_cast<const DagInit
&>(*Statement
)) == "case";
1539 // If so, ignore it, it is handled by our caller, WalkCase.
1541 if (typeid(*Statement
) == typeid(ListInit
)) {
1542 const ListInit
& DagList
= *static_cast<const ListInit
*>(Statement
);
1543 for (ListInit::const_iterator B
= DagList
.begin(), E
= DagList
.end();
1545 Callback_(*B
, (IndentLevel
+ Indent1
), O_
);
1548 Callback_(Statement
, (IndentLevel
+ Indent1
), O_
);
1551 O_
.indent(IndentLevel
) << "}\n";
1556 /// EmitCaseConstructHandler - Emit code that handles the 'case'
1557 /// construct. Takes a function object that should emit code for every case
1558 /// clause. Implemented on top of WalkCase.
1559 /// Callback's type is void F(const Init* Statement, unsigned IndentLevel,
1560 /// raw_ostream& O).
1561 /// EmitElseIf parameter controls the type of condition that is emitted ('if
1562 /// (..) {..} else if (..) {} .. else {..}' vs. 'if (..) {..} if(..) {..}
1564 template <typename F
>
1565 void EmitCaseConstructHandler(const Init
* Case
, unsigned IndentLevel
,
1566 F Callback
, bool EmitElseIf
,
1567 const OptionDescriptions
& OptDescs
,
1569 WalkCase(Case
, EmitCaseTestCallback(EmitElseIf
, OptDescs
, O
),
1570 EmitCaseStatementCallback
<F
>(Callback
, O
), IndentLevel
);
1573 /// TokenizeCmdLine - converts from
1574 /// "$CALL(HookName, 'Arg1', 'Arg2')/path -arg1 -arg2" to
1575 /// ["$CALL(", "HookName", "Arg1", "Arg2", ")/path", "-arg1", "-arg2"].
1576 void TokenizeCmdLine(const std::string
& CmdLine
, StrVector
& Out
) {
1577 const char* Delimiters
= " \t\n\v\f\r";
1579 { Normal
, SpecialCommand
, InsideSpecialCommand
, InsideQuotationMarks
}
1582 if (CmdLine
.empty())
1586 std::string::size_type B
= CmdLine
.find_first_not_of(Delimiters
),
1589 for (; B
!= E
; ++B
) {
1590 char cur_ch
= CmdLine
[B
];
1594 if (cur_ch
== '$') {
1595 cur_st
= SpecialCommand
;
1598 if (OneOf(Delimiters
, cur_ch
)) {
1600 B
= CmdLine
.find_first_not_of(Delimiters
, B
);
1601 if (B
== std::string::npos
) {
1612 case SpecialCommand
:
1613 if (OneOf(Delimiters
, cur_ch
)) {
1618 if (cur_ch
== '(') {
1620 cur_st
= InsideSpecialCommand
;
1625 case InsideSpecialCommand
:
1626 if (OneOf(Delimiters
, cur_ch
)) {
1629 if (cur_ch
== '\'') {
1630 cur_st
= InsideQuotationMarks
;
1634 if (cur_ch
== ')') {
1638 if (cur_ch
== ',') {
1644 case InsideQuotationMarks
:
1645 if (cur_ch
== '\'') {
1646 cur_st
= InsideSpecialCommand
;
1652 Out
.back().push_back(cur_ch
);
1656 /// SubstituteCall - Given "$CALL(HookName, [Arg1 [, Arg2 [...]]])", output
1657 /// "hooks::HookName([Arg1 [, Arg2 [, ...]]])". Helper function used by
1658 /// SubstituteSpecialCommands().
1659 StrVector::const_iterator
1660 SubstituteCall (StrVector::const_iterator Pos
,
1661 StrVector::const_iterator End
,
1662 bool IsJoin
, raw_ostream
& O
)
1664 const char* errorMessage
= "Syntax error in $CALL invocation!";
1665 CheckedIncrement(Pos
, End
, errorMessage
);
1666 const std::string
& CmdName
= *Pos
;
1669 throw "$CALL invocation: empty argument list!";
1672 O
<< CmdName
<< "(";
1675 bool firstIteration
= true;
1677 CheckedIncrement(Pos
, End
, errorMessage
);
1678 const std::string
& Arg
= *Pos
;
1679 assert(Arg
.size() != 0);
1685 firstIteration
= false;
1689 if (Arg
== "$INFILE") {
1691 throw "$CALL(Hook, $INFILE) can't be used with a Join tool!";
1693 O
<< "inFile.c_str()";
1696 O
<< '"' << Arg
<< '"';
1705 /// SubstituteEnv - Given '$ENV(VAR_NAME)', output 'getenv("VAR_NAME")'. Helper
1706 /// function used by SubstituteSpecialCommands().
1707 StrVector::const_iterator
1708 SubstituteEnv (StrVector::const_iterator Pos
,
1709 StrVector::const_iterator End
, raw_ostream
& O
)
1711 const char* errorMessage
= "Syntax error in $ENV invocation!";
1712 CheckedIncrement(Pos
, End
, errorMessage
);
1713 const std::string
& EnvName
= *Pos
;
1716 throw "$ENV invocation: empty argument list!";
1718 O
<< "checkCString(std::getenv(\"";
1722 CheckedIncrement(Pos
, End
, errorMessage
);
1727 /// SubstituteSpecialCommands - Given an invocation of $CALL or $ENV, output
1728 /// handler code. Helper function used by EmitCmdLineVecFill().
1729 StrVector::const_iterator
1730 SubstituteSpecialCommands (StrVector::const_iterator Pos
,
1731 StrVector::const_iterator End
,
1732 bool IsJoin
, raw_ostream
& O
)
1735 const std::string
& cmd
= *Pos
;
1737 // Perform substitution.
1738 if (cmd
== "$CALL") {
1739 Pos
= SubstituteCall(Pos
, End
, IsJoin
, O
);
1741 else if (cmd
== "$ENV") {
1742 Pos
= SubstituteEnv(Pos
, End
, O
);
1745 throw "Unknown special command: " + cmd
;
1748 // Handle '$CMD(ARG)/additional/text'.
1749 const std::string
& Leftover
= *Pos
;
1750 assert(Leftover
.at(0) == ')');
1751 if (Leftover
.size() != 1)
1752 O
<< " + std::string(\"" << (Leftover
.c_str() + 1) << "\")";
1757 /// EmitCmdLineVecFill - Emit code that fills in the command line
1758 /// vector. Helper function used by EmitGenerateActionMethod().
1759 void EmitCmdLineVecFill(const Init
* CmdLine
, const std::string
& ToolName
,
1760 bool IsJoin
, unsigned IndentLevel
,
1763 TokenizeCmdLine(InitPtrToString(CmdLine
), StrVec
);
1766 throw "Tool '" + ToolName
+ "' has empty command line!";
1768 StrVector::const_iterator B
= StrVec
.begin(), E
= StrVec
.end();
1770 // Emit the command itself.
1771 assert(!StrVec
[0].empty());
1772 O
.indent(IndentLevel
) << "cmd = ";
1773 if (StrVec
[0][0] == '$') {
1774 B
= SubstituteSpecialCommands(B
, E
, IsJoin
, O
);
1778 O
<< '"' << StrVec
[0] << '"';
1783 // Go through the command arguments.
1785 for (; B
!= E
; ++B
) {
1786 const std::string
& cmd
= *B
;
1788 assert(!cmd
.empty());
1789 O
.indent(IndentLevel
);
1791 if (cmd
.at(0) == '$') {
1792 O
<< "vec.push_back(std::make_pair(0, ";
1793 B
= SubstituteSpecialCommands(B
, E
, IsJoin
, O
);
1797 O
<< "vec.push_back(std::make_pair(0, \"" << cmd
<< "\"));\n";
1803 /// EmitForEachListElementCycleHeader - Emit common code for iterating through
1804 /// all elements of a list. Helper function used by
1805 /// EmitForwardOptionPropertyHandlingCode.
1806 void EmitForEachListElementCycleHeader (const OptionDescription
& D
,
1807 unsigned IndentLevel
,
1809 unsigned IndentLevel1
= IndentLevel
+ Indent1
;
1811 O
.indent(IndentLevel
)
1812 << "for (" << D
.GenTypeDeclaration()
1813 << "::iterator B = " << D
.GenVariableName() << ".begin(),\n";
1814 O
.indent(IndentLevel
)
1815 << "E = " << D
.GenVariableName() << ".end(); B != E;) {\n";
1816 O
.indent(IndentLevel1
) << "unsigned pos = " << D
.GenVariableName()
1817 << ".getPosition(B - " << D
.GenVariableName()
1821 /// EmitForwardOptionPropertyHandlingCode - Helper function used to
1822 /// implement EmitActionHandler. Emits code for
1823 /// handling the (forward) and (forward_as) option properties.
1824 void EmitForwardOptionPropertyHandlingCode (const OptionDescription
& D
,
1825 unsigned IndentLevel
,
1826 const std::string
& NewName
,
1828 const std::string
& Name
= NewName
.empty()
1831 unsigned IndentLevel1
= IndentLevel
+ Indent1
;
1834 case OptionType::Switch
:
1835 O
.indent(IndentLevel
)
1836 << "vec.push_back(std::make_pair(" << D
.GenVariableName()
1837 << ".getPosition(), \"" << Name
<< "\"));\n";
1839 case OptionType::Parameter
:
1840 O
.indent(IndentLevel
) << "vec.push_back(std::make_pair("
1841 << D
.GenVariableName()
1842 <<".getPosition(), \"" << Name
;
1844 if (!D
.isForwardNotSplit()) {
1846 O
.indent(IndentLevel
) << "vec.push_back(std::make_pair("
1847 << D
.GenVariableName() << ".getPosition(), "
1848 << D
.GenVariableName() << "));\n";
1851 O
<< "=\" + " << D
.GenVariableName() << "));\n";
1854 case OptionType::Prefix
:
1855 O
.indent(IndentLevel
) << "vec.push_back(std::make_pair("
1856 << D
.GenVariableName() << ".getPosition(), \""
1858 << D
.GenVariableName() << "));\n";
1860 case OptionType::PrefixList
:
1861 EmitForEachListElementCycleHeader(D
, IndentLevel
, O
);
1862 O
.indent(IndentLevel1
) << "vec.push_back(std::make_pair(pos, \""
1863 << Name
<< "\" + " << "*B));\n";
1864 O
.indent(IndentLevel1
) << "++B;\n";
1866 for (int i
= 1, j
= D
.MultiVal
; i
< j
; ++i
) {
1867 O
.indent(IndentLevel1
) << "vec.push_back(std::make_pair(pos, *B));\n";
1868 O
.indent(IndentLevel1
) << "++B;\n";
1871 O
.indent(IndentLevel
) << "}\n";
1873 case OptionType::ParameterList
:
1874 EmitForEachListElementCycleHeader(D
, IndentLevel
, O
);
1875 O
.indent(IndentLevel1
) << "vec.push_back(std::make_pair(pos, \""
1876 << Name
<< "\"));\n";
1878 for (int i
= 0, j
= D
.MultiVal
; i
< j
; ++i
) {
1879 O
.indent(IndentLevel1
) << "vec.push_back(std::make_pair(pos, *B));\n";
1880 O
.indent(IndentLevel1
) << "++B;\n";
1883 O
.indent(IndentLevel
) << "}\n";
1885 case OptionType::SwitchList
:
1886 EmitForEachListElementCycleHeader(D
, IndentLevel
, O
);
1887 O
.indent(IndentLevel1
) << "vec.push_back(std::make_pair(pos, \""
1888 << Name
<< "\"));\n";
1889 O
.indent(IndentLevel1
) << "++B;\n";
1890 O
.indent(IndentLevel
) << "}\n";
1892 case OptionType::Alias
:
1894 throw "Aliases are not allowed in tool option descriptions!";
1898 /// ActionHandlingCallbackBase - Base class of EmitActionHandlersCallback and
1899 /// EmitPreprocessOptionsCallback.
1900 struct ActionHandlingCallbackBase
1903 void onErrorDag(const DagInit
& d
,
1904 unsigned IndentLevel
, raw_ostream
& O
) const
1906 O
.indent(IndentLevel
)
1908 << (d
.getNumArgs() >= 1 ? InitPtrToString(d
.getArg(0)) : "Unknown error!")
1910 O
.indent(IndentLevel
) << "return 1;\n";
1913 void onWarningDag(const DagInit
& d
,
1914 unsigned IndentLevel
, raw_ostream
& O
) const
1916 CheckNumberOfArguments(d
, 1);
1917 O
.indent(IndentLevel
) << "llvm::errs() << \""
1918 << InitPtrToString(d
.getArg(0)) << "\";\n";
1923 /// EmitActionHandlersCallback - Emit code that handles actions. Used by
1924 /// EmitGenerateActionMethod() as an argument to EmitCaseConstructHandler().
1925 class EmitActionHandlersCallback
;
1927 typedef void (EmitActionHandlersCallback::* EmitActionHandlersCallbackHandler
)
1928 (const DagInit
&, unsigned, raw_ostream
&) const;
1930 class EmitActionHandlersCallback
:
1931 public ActionHandlingCallbackBase
,
1932 public HandlerTable
<EmitActionHandlersCallbackHandler
>
1934 typedef EmitActionHandlersCallbackHandler Handler
;
1936 const OptionDescriptions
& OptDescs
;
1938 /// EmitHookInvocation - Common code for hook invocation from actions. Used by
1939 /// onAppendCmd and onOutputSuffix.
1940 void EmitHookInvocation(const std::string
& Str
,
1941 const char* BlockOpen
, const char* BlockClose
,
1942 unsigned IndentLevel
, raw_ostream
& O
) const
1945 TokenizeCmdLine(Str
, Out
);
1947 for (StrVector::const_iterator B
= Out
.begin(), E
= Out
.end();
1949 const std::string
& cmd
= *B
;
1951 O
.indent(IndentLevel
) << BlockOpen
;
1953 if (cmd
.at(0) == '$')
1954 B
= SubstituteSpecialCommands(B
, E
, /* IsJoin = */ true, O
);
1956 O
<< '"' << cmd
<< '"';
1962 void onAppendCmd (const DagInit
& Dag
,
1963 unsigned IndentLevel
, raw_ostream
& O
) const
1965 CheckNumberOfArguments(Dag
, 1);
1966 this->EmitHookInvocation(InitPtrToString(Dag
.getArg(0)),
1967 "vec.push_back(std::make_pair(65536, ", "));\n",
1971 void onForward (const DagInit
& Dag
,
1972 unsigned IndentLevel
, raw_ostream
& O
) const
1974 CheckNumberOfArguments(Dag
, 1);
1975 const std::string
& Name
= InitPtrToString(Dag
.getArg(0));
1976 EmitForwardOptionPropertyHandlingCode(OptDescs
.FindOption(Name
),
1977 IndentLevel
, "", O
);
1980 void onForwardAs (const DagInit
& Dag
,
1981 unsigned IndentLevel
, raw_ostream
& O
) const
1983 CheckNumberOfArguments(Dag
, 2);
1984 const std::string
& Name
= InitPtrToString(Dag
.getArg(0));
1985 const std::string
& NewName
= InitPtrToString(Dag
.getArg(1));
1986 EmitForwardOptionPropertyHandlingCode(OptDescs
.FindOption(Name
),
1987 IndentLevel
, NewName
, O
);
1990 void onForwardValue (const DagInit
& Dag
,
1991 unsigned IndentLevel
, raw_ostream
& O
) const
1993 CheckNumberOfArguments(Dag
, 1);
1994 const std::string
& Name
= InitPtrToString(Dag
.getArg(0));
1995 const OptionDescription
& D
= OptDescs
.FindParameterListOrParameter(Name
);
1997 if (D
.isSwitchList()) {
1998 throw std::runtime_error
1999 ("forward_value is not allowed with switch_list");
2002 if (D
.isParameter()) {
2003 O
.indent(IndentLevel
) << "vec.push_back(std::make_pair("
2004 << D
.GenVariableName() << ".getPosition(), "
2005 << D
.GenVariableName() << "));\n";
2008 O
.indent(IndentLevel
) << "for (" << D
.GenTypeDeclaration()
2009 << "::iterator B = " << D
.GenVariableName()
2011 O
.indent(IndentLevel
+ Indent1
) << " E = " << D
.GenVariableName()
2012 << ".end(); B != E; ++B)\n";
2013 O
.indent(IndentLevel
) << "{\n";
2014 O
.indent(IndentLevel
+ Indent1
)
2015 << "unsigned pos = " << D
.GenVariableName()
2016 << ".getPosition(B - " << D
.GenVariableName()
2018 O
.indent(IndentLevel
+ Indent1
)
2019 << "vec.push_back(std::make_pair(pos, *B));\n";
2020 O
.indent(IndentLevel
) << "}\n";
2024 void onForwardTransformedValue (const DagInit
& Dag
,
2025 unsigned IndentLevel
, raw_ostream
& O
) const
2027 CheckNumberOfArguments(Dag
, 2);
2028 const std::string
& Name
= InitPtrToString(Dag
.getArg(0));
2029 const std::string
& Hook
= InitPtrToString(Dag
.getArg(1));
2030 const OptionDescription
& D
= OptDescs
.FindParameterListOrParameter(Name
);
2032 O
.indent(IndentLevel
) << "vec.push_back(std::make_pair("
2033 << D
.GenVariableName() << ".getPosition("
2034 << (D
.isList() ? "0" : "") << "), "
2035 << "hooks::" << Hook
<< "(" << D
.GenVariableName()
2036 << (D
.isParameter() ? ".c_str()" : "") << ")));\n";
2039 void onNoOutFile (const DagInit
& Dag
,
2040 unsigned IndentLevel
, raw_ostream
& O
) const
2042 CheckNumberOfArguments(Dag
, 0);
2043 O
.indent(IndentLevel
) << "no_out_file = true;\n";
2046 void onOutputSuffix (const DagInit
& Dag
,
2047 unsigned IndentLevel
, raw_ostream
& O
) const
2049 CheckNumberOfArguments(Dag
, 1);
2050 this->EmitHookInvocation(InitPtrToString(Dag
.getArg(0)),
2051 "output_suffix = ", ";\n", IndentLevel
, O
);
2054 void onStopCompilation (const DagInit
& Dag
,
2055 unsigned IndentLevel
, raw_ostream
& O
) const
2057 O
.indent(IndentLevel
) << "stop_compilation = true;\n";
2061 void onUnpackValues (const DagInit
& Dag
,
2062 unsigned IndentLevel
, raw_ostream
& O
) const
2064 throw "'unpack_values' is deprecated. "
2065 "Use 'comma_separated' + 'forward_value' instead!";
2070 explicit EmitActionHandlersCallback(const OptionDescriptions
& OD
)
2073 if (!staticMembersInitialized_
) {
2074 AddHandler("error", &EmitActionHandlersCallback::onErrorDag
);
2075 AddHandler("warning", &EmitActionHandlersCallback::onWarningDag
);
2076 AddHandler("append_cmd", &EmitActionHandlersCallback::onAppendCmd
);
2077 AddHandler("forward", &EmitActionHandlersCallback::onForward
);
2078 AddHandler("forward_as", &EmitActionHandlersCallback::onForwardAs
);
2079 AddHandler("forward_value", &EmitActionHandlersCallback::onForwardValue
);
2080 AddHandler("forward_transformed_value",
2081 &EmitActionHandlersCallback::onForwardTransformedValue
);
2082 AddHandler("no_out_file",
2083 &EmitActionHandlersCallback::onNoOutFile
);
2084 AddHandler("output_suffix", &EmitActionHandlersCallback::onOutputSuffix
);
2085 AddHandler("stop_compilation",
2086 &EmitActionHandlersCallback::onStopCompilation
);
2087 AddHandler("unpack_values",
2088 &EmitActionHandlersCallback::onUnpackValues
);
2091 staticMembersInitialized_
= true;
2095 void operator()(const Init
* I
,
2096 unsigned IndentLevel
, raw_ostream
& O
) const
2098 InvokeDagInitHandler(this, I
, IndentLevel
, O
);
2102 void EmitGenerateActionMethodHeader(const ToolDescription
& D
,
2103 bool IsJoin
, bool Naked
,
2106 O
.indent(Indent1
) << "int GenerateAction(Action& Out,\n";
2109 O
.indent(Indent2
) << "const PathVector& inFiles,\n";
2111 O
.indent(Indent2
) << "const sys::Path& inFile,\n";
2113 O
.indent(Indent2
) << "const bool HasChildren,\n";
2114 O
.indent(Indent2
) << "const llvm::sys::Path& TempDir,\n";
2115 O
.indent(Indent2
) << "const InputLanguagesSet& InLangs,\n";
2116 O
.indent(Indent2
) << "const LanguageMap& LangMap) const\n";
2117 O
.indent(Indent1
) << "{\n";
2120 O
.indent(Indent2
) << "std::string cmd;\n";
2121 O
.indent(Indent2
) << "std::string out_file;\n";
2123 << "std::vector<std::pair<unsigned, std::string> > vec;\n";
2124 O
.indent(Indent2
) << "bool stop_compilation = !HasChildren;\n";
2125 O
.indent(Indent2
) << "bool no_out_file = false;\n";
2126 O
.indent(Indent2
) << "std::string output_suffix(\""
2127 << D
.OutputSuffix
<< "\");\n";
2131 // EmitGenerateActionMethod - Emit either a normal or a "join" version of the
2132 // Tool::GenerateAction() method.
2133 void EmitGenerateActionMethod (const ToolDescription
& D
,
2134 const OptionDescriptions
& OptDescs
,
2135 bool IsJoin
, raw_ostream
& O
) {
2137 EmitGenerateActionMethodHeader(D
, IsJoin
, /* Naked = */ false, O
);
2140 throw "Tool " + D
.Name
+ " has no cmd_line property!";
2142 // Process the 'command' property.
2144 EmitCmdLineVecFill(D
.CmdLine
, D
.Name
, IsJoin
, Indent2
, O
);
2147 // Process the 'actions' list of this tool.
2149 EmitCaseConstructHandler(D
.Actions
, Indent2
,
2150 EmitActionHandlersCallback(OptDescs
),
2151 false, OptDescs
, O
);
2155 if (!D
.InFileOption
.empty()) {
2157 << "vec.push_back(std::make_pair(InputFilenames.getPosition(0), \""
2158 << D
.InFileOption
<< "\");\n";
2163 << "for (PathVector::const_iterator B = inFiles.begin(),\n";
2164 O
.indent(Indent3
) << "E = inFiles.end(); B != E; ++B)\n";
2165 O
.indent(Indent2
) << "{\n";
2166 O
.indent(Indent3
) << "vec.push_back(std::make_pair("
2167 << "InputFilenames.getPosition(B - inFiles.begin()), "
2169 O
.indent(Indent2
) << "}\n";
2172 O
.indent(Indent2
) << "vec.push_back(std::make_pair("
2173 << "InputFilenames.getPosition(0), inFile.str()));\n";
2177 O
.indent(Indent2
) << "if (!no_out_file) {\n";
2178 if (!D
.OutFileOption
.empty())
2179 O
.indent(Indent3
) << "vec.push_back(std::make_pair(65536, \""
2180 << D
.OutFileOption
<< "\"));\n";
2182 O
.indent(Indent3
) << "out_file = this->OutFilename("
2183 << (IsJoin
? "sys::Path(),\n" : "inFile,\n");
2184 O
.indent(Indent4
) <<
2185 "TempDir, stop_compilation, output_suffix.c_str()).str();\n\n";
2186 O
.indent(Indent3
) << "vec.push_back(std::make_pair(65536, out_file));\n";
2188 O
.indent(Indent2
) << "}\n\n";
2190 // Handle the Sink property.
2191 std::string
SinkOption("autogenerated::");
2192 SinkOption
+= SinkOptionName
;
2194 O
.indent(Indent2
) << "if (!" << SinkOption
<< ".empty()) {\n";
2195 O
.indent(Indent3
) << "for (cl::list<std::string>::iterator B = "
2196 << SinkOption
<< ".begin(), E = " << SinkOption
2197 << ".end(); B != E; ++B)\n";
2198 O
.indent(Indent4
) << "vec.push_back(std::make_pair(" << SinkOption
2199 << ".getPosition(B - " << SinkOption
2200 << ".begin()), *B));\n";
2201 O
.indent(Indent2
) << "}\n";
2204 O
.indent(Indent2
) << "Out.Construct(cmd, this->SortArgs(vec), "
2205 << "stop_compilation, out_file);\n";
2206 O
.indent(Indent2
) << "return 0;\n";
2207 O
.indent(Indent1
) << "}\n\n";
2210 /// EmitGenerateActionMethods - Emit two GenerateAction() methods for
2211 /// a given Tool class.
2212 void EmitGenerateActionMethods (const ToolDescription
& ToolDesc
,
2213 const OptionDescriptions
& OptDescs
,
2215 if (!ToolDesc
.isJoin()) {
2216 EmitGenerateActionMethodHeader(ToolDesc
, /* IsJoin = */ true,
2217 /* Naked = */ true, O
);
2218 O
.indent(Indent2
) << "PrintError(\"" << ToolDesc
.Name
2219 << " is not a Join tool!\");\n";
2220 O
.indent(Indent2
) << "return -1;\n";
2221 O
.indent(Indent1
) << "}\n\n";
2224 EmitGenerateActionMethod(ToolDesc
, OptDescs
, true, O
);
2227 EmitGenerateActionMethod(ToolDesc
, OptDescs
, false, O
);
2230 /// EmitInOutLanguageMethods - Emit the [Input,Output]Language()
2231 /// methods for a given Tool class.
2232 void EmitInOutLanguageMethods (const ToolDescription
& D
, raw_ostream
& O
) {
2233 O
.indent(Indent1
) << "const char** InputLanguages() const {\n";
2234 O
.indent(Indent2
) << "return InputLanguages_;\n";
2235 O
.indent(Indent1
) << "}\n\n";
2237 O
.indent(Indent1
) << "const char** OutputLanguages() const {\n";
2238 O
.indent(Indent2
) << "return OutputLanguages_;\n";
2239 O
.indent(Indent1
) << "}\n\n";
2242 /// EmitNameMethod - Emit the Name() method for a given Tool class.
2243 void EmitNameMethod (const ToolDescription
& D
, raw_ostream
& O
) {
2244 O
.indent(Indent1
) << "const char* Name() const {\n";
2245 O
.indent(Indent2
) << "return \"" << D
.Name
<< "\";\n";
2246 O
.indent(Indent1
) << "}\n\n";
2249 /// EmitIsJoinMethod - Emit the IsJoin() method for a given Tool
2251 void EmitIsJoinMethod (const ToolDescription
& D
, raw_ostream
& O
) {
2252 O
.indent(Indent1
) << "bool IsJoin() const {\n";
2254 O
.indent(Indent2
) << "return true;\n";
2256 O
.indent(Indent2
) << "return false;\n";
2257 O
.indent(Indent1
) << "}\n\n";
2260 /// EmitWorksOnEmptyCallback - Callback used by EmitWorksOnEmptyMethod in
2261 /// conjunction with EmitCaseConstructHandler.
2262 void EmitWorksOnEmptyCallback (const Init
* Value
,
2263 unsigned IndentLevel
, raw_ostream
& O
) {
2264 CheckBooleanConstant(Value
);
2265 O
.indent(IndentLevel
) << "return " << Value
->getAsString() << ";\n";
2268 /// EmitWorksOnEmptyMethod - Emit the WorksOnEmpty() method for a given Tool
2270 void EmitWorksOnEmptyMethod (const ToolDescription
& D
,
2271 const OptionDescriptions
& OptDescs
,
2274 O
.indent(Indent1
) << "bool WorksOnEmpty() const {\n";
2276 O
.indent(Indent2
) << "return false;\n";
2278 EmitCaseConstructHandler(D
.OnEmpty
, Indent2
, EmitWorksOnEmptyCallback
,
2279 /*EmitElseIf = */ true, OptDescs
, O
);
2280 O
.indent(Indent1
) << "}\n\n";
2283 /// EmitStrArray - Emit definition of a 'const char**' static member
2284 /// variable. Helper used by EmitStaticMemberDefinitions();
2285 void EmitStrArray(const std::string
& Name
, const std::string
& VarName
,
2286 const StrVector
& StrVec
, raw_ostream
& O
) {
2287 O
<< "const char* " << Name
<< "::" << VarName
<< "[] = {";
2288 for (StrVector::const_iterator B
= StrVec
.begin(), E
= StrVec
.end();
2290 O
<< '\"' << *B
<< "\", ";
2294 /// EmitStaticMemberDefinitions - Emit static member definitions for a
2295 /// given Tool class.
2296 void EmitStaticMemberDefinitions(const ToolDescription
& D
, raw_ostream
& O
) {
2297 if (D
.InLanguage
.empty())
2298 throw "Tool " + D
.Name
+ " has no 'in_language' property!";
2299 if (D
.OutLanguage
.empty())
2300 throw "Tool " + D
.Name
+ " has no 'out_language' property!";
2302 EmitStrArray(D
.Name
, "InputLanguages_", D
.InLanguage
, O
);
2303 EmitStrArray(D
.Name
, "OutputLanguages_", D
.OutLanguage
, O
);
2307 /// EmitToolClassDefinition - Emit a Tool class definition.
2308 void EmitToolClassDefinition (const ToolDescription
& D
,
2309 const OptionDescriptions
& OptDescs
,
2311 if (D
.Name
== "root")
2315 O
<< "class " << D
.Name
<< " : public ";
2321 O
<< " {\nprivate:\n";
2322 O
.indent(Indent1
) << "static const char* InputLanguages_[];\n";
2323 O
.indent(Indent1
) << "static const char* OutputLanguages_[];\n\n";
2326 EmitNameMethod(D
, O
);
2327 EmitInOutLanguageMethods(D
, O
);
2328 EmitIsJoinMethod(D
, O
);
2329 EmitWorksOnEmptyMethod(D
, OptDescs
, O
);
2330 EmitGenerateActionMethods(D
, OptDescs
, O
);
2332 // Close class definition
2335 EmitStaticMemberDefinitions(D
, O
);
2339 /// EmitOptionDefinitions - Iterate over a list of option descriptions
2340 /// and emit registration code.
2341 void EmitOptionDefinitions (const OptionDescriptions
& descs
,
2342 bool HasSink
, raw_ostream
& O
)
2344 std::vector
<OptionDescription
> Aliases
;
2346 // Emit static cl::Option variables.
2347 for (OptionDescriptions::const_iterator B
= descs
.begin(),
2348 E
= descs
.end(); B
!=E
; ++B
) {
2349 const OptionDescription
& val
= B
->second
;
2351 if (val
.Type
== OptionType::Alias
) {
2352 Aliases
.push_back(val
);
2356 O
<< val
.GenTypeDeclaration() << ' '
2357 << val
.GenPlainVariableName();
2359 O
<< "(\"" << val
.Name
<< "\"\n";
2361 if (val
.Type
== OptionType::Prefix
|| val
.Type
== OptionType::PrefixList
)
2362 O
<< ", cl::Prefix";
2364 if (val
.isRequired()) {
2365 if (val
.isList() && !val
.isMultiVal())
2366 O
<< ", cl::OneOrMore";
2368 O
<< ", cl::Required";
2371 if (val
.isOptional())
2372 O
<< ", cl::Optional";
2374 if (val
.isOneOrMore())
2375 O
<< ", cl::OneOrMore";
2377 if (val
.isZeroOrMore())
2378 O
<< ", cl::ZeroOrMore";
2380 if (val
.isReallyHidden())
2381 O
<< ", cl::ReallyHidden";
2382 else if (val
.isHidden())
2383 O
<< ", cl::Hidden";
2385 if (val
.isCommaSeparated())
2386 O
<< ", cl::CommaSeparated";
2388 if (val
.MultiVal
> 1)
2389 O
<< ", cl::multi_val(" << val
.MultiVal
<< ')';
2392 const std::string
& str
= val
.InitVal
->getAsString();
2393 O
<< ", cl::init(" << str
<< ')';
2396 if (!val
.Help
.empty())
2397 O
<< ", cl::desc(\"" << val
.Help
<< "\")";
2402 // Emit the aliases (they should go after all the 'proper' options).
2403 for (std::vector
<OptionDescription
>::const_iterator
2404 B
= Aliases
.begin(), E
= Aliases
.end(); B
!= E
; ++B
) {
2405 const OptionDescription
& val
= *B
;
2407 O
<< val
.GenTypeDeclaration() << ' '
2408 << val
.GenPlainVariableName()
2409 << "(\"" << val
.Name
<< '\"';
2411 const OptionDescription
& D
= descs
.FindOption(val
.Help
);
2412 O
<< ", cl::aliasopt(" << D
.GenVariableName() << ")";
2414 O
<< ", cl::desc(\"" << "An alias for -" + val
.Help
<< "\"));\n";
2417 // Emit the sink option.
2419 O
<< "cl::list<std::string> " << SinkOptionName
<< "(cl::Sink);\n";
2424 /// EmitPreprocessOptionsCallback - Helper function passed to
2425 /// EmitCaseConstructHandler() by EmitPreprocessOptions().
2427 class EmitPreprocessOptionsCallback
;
2430 (EmitPreprocessOptionsCallback::* EmitPreprocessOptionsCallbackHandler
)
2431 (const DagInit
&, unsigned, raw_ostream
&) const;
2433 class EmitPreprocessOptionsCallback
:
2434 public ActionHandlingCallbackBase
,
2435 public HandlerTable
<EmitPreprocessOptionsCallbackHandler
>
2437 typedef EmitPreprocessOptionsCallbackHandler Handler
;
2439 (EmitPreprocessOptionsCallback::* HandlerImpl
)
2440 (const Init
*, unsigned, raw_ostream
&) const;
2442 const OptionDescriptions
& OptDescs_
;
2444 void onEachArgument(const DagInit
& d
, HandlerImpl h
,
2445 unsigned IndentLevel
, raw_ostream
& O
) const
2447 CheckNumberOfArguments(d
, 1);
2449 for (unsigned i
= 0, NumArgs
= d
.getNumArgs(); i
< NumArgs
; ++i
) {
2450 ((this)->*(h
))(d
.getArg(i
), IndentLevel
, O
);
2454 void onUnsetOptionImpl(const Init
* I
,
2455 unsigned IndentLevel
, raw_ostream
& O
) const
2457 const std::string
& OptName
= InitPtrToString(I
);
2458 const OptionDescription
& OptDesc
= OptDescs_
.FindOption(OptName
);
2460 if (OptDesc
.isSwitch()) {
2461 O
.indent(IndentLevel
) << OptDesc
.GenVariableName() << " = false;\n";
2463 else if (OptDesc
.isParameter()) {
2464 O
.indent(IndentLevel
) << OptDesc
.GenVariableName() << " = \"\";\n";
2466 else if (OptDesc
.isList()) {
2467 O
.indent(IndentLevel
) << OptDesc
.GenVariableName() << ".clear();\n";
2470 throw "Can't apply 'unset_option' to alias option '" + OptName
+ "'!";
2474 void onUnsetOption(const DagInit
& d
,
2475 unsigned IndentLevel
, raw_ostream
& O
) const
2477 this->onEachArgument(d
, &EmitPreprocessOptionsCallback::onUnsetOptionImpl
,
2481 void onSetOptionImpl(const DagInit
& D
,
2482 unsigned IndentLevel
, raw_ostream
& O
) const {
2483 CheckNumberOfArguments(D
, 2);
2485 const std::string
& OptName
= InitPtrToString(D
.getArg(0));
2486 const OptionDescription
& OptDesc
= OptDescs_
.FindOption(OptName
);
2487 const Init
* Value
= D
.getArg(1);
2489 if (OptDesc
.isList()) {
2490 const ListInit
& List
= InitPtrToList(Value
);
2492 O
.indent(IndentLevel
) << OptDesc
.GenVariableName() << ".clear();\n";
2493 for (ListInit::const_iterator B
= List
.begin(), E
= List
.end();
2495 const Init
* CurElem
= *B
;
2496 if (OptDesc
.isSwitchList())
2497 CheckBooleanConstant(CurElem
);
2499 O
.indent(IndentLevel
)
2500 << OptDesc
.GenVariableName() << ".push_back(\""
2501 << (OptDesc
.isSwitchList() ? CurElem
->getAsString()
2502 : InitPtrToString(CurElem
))
2506 else if (OptDesc
.isSwitch()) {
2507 CheckBooleanConstant(Value
);
2508 O
.indent(IndentLevel
) << OptDesc
.GenVariableName()
2509 << " = " << Value
->getAsString() << ";\n";
2511 else if (OptDesc
.isParameter()) {
2512 const std::string
& Str
= InitPtrToString(Value
);
2513 O
.indent(IndentLevel
) << OptDesc
.GenVariableName()
2514 << " = \"" << Str
<< "\";\n";
2517 throw "Can't apply 'set_option' to alias option '" + OptName
+ "'!";
2521 void onSetSwitch(const Init
* I
,
2522 unsigned IndentLevel
, raw_ostream
& O
) const {
2523 const std::string
& OptName
= InitPtrToString(I
);
2524 const OptionDescription
& OptDesc
= OptDescs_
.FindOption(OptName
);
2526 if (OptDesc
.isSwitch())
2527 O
.indent(IndentLevel
) << OptDesc
.GenVariableName() << " = true;\n";
2529 throw "set_option: -" + OptName
+ " is not a switch option!";
2532 void onSetOption(const DagInit
& d
,
2533 unsigned IndentLevel
, raw_ostream
& O
) const
2535 CheckNumberOfArguments(d
, 1);
2537 // 2-argument form: (set_option "A", true), (set_option "B", "C"),
2538 // (set_option "D", ["E", "F"])
2539 if (d
.getNumArgs() == 2) {
2540 const OptionDescription
& OptDesc
=
2541 OptDescs_
.FindOption(InitPtrToString(d
.getArg(0)));
2542 const Init
* Opt2
= d
.getArg(1);
2544 if (!OptDesc
.isSwitch() || typeid(*Opt2
) != typeid(StringInit
)) {
2545 this->onSetOptionImpl(d
, IndentLevel
, O
);
2550 // Multiple argument form: (set_option "A"), (set_option "B", "C", "D")
2551 this->onEachArgument(d
, &EmitPreprocessOptionsCallback::onSetSwitch
,
2557 EmitPreprocessOptionsCallback(const OptionDescriptions
& OptDescs
)
2558 : OptDescs_(OptDescs
)
2560 if (!staticMembersInitialized_
) {
2561 AddHandler("error", &EmitPreprocessOptionsCallback::onErrorDag
);
2562 AddHandler("warning", &EmitPreprocessOptionsCallback::onWarningDag
);
2563 AddHandler("unset_option", &EmitPreprocessOptionsCallback::onUnsetOption
);
2564 AddHandler("set_option", &EmitPreprocessOptionsCallback::onSetOption
);
2566 staticMembersInitialized_
= true;
2570 void operator()(const Init
* I
,
2571 unsigned IndentLevel
, raw_ostream
& O
) const
2573 InvokeDagInitHandler(this, I
, IndentLevel
, O
);
2578 /// EmitPreprocessOptions - Emit the PreprocessOptions() function.
2579 void EmitPreprocessOptions (const RecordKeeper
& Records
,
2580 const OptionDescriptions
& OptDecs
, raw_ostream
& O
)
2582 O
<< "int PreprocessOptions () {\n";
2584 const RecordVector
& OptionPreprocessors
=
2585 Records
.getAllDerivedDefinitions("OptionPreprocessor");
2587 for (RecordVector::const_iterator B
= OptionPreprocessors
.begin(),
2588 E
= OptionPreprocessors
.end(); B
!=E
; ++B
) {
2589 DagInit
* Case
= (*B
)->getValueAsDag("preprocessor");
2590 EmitCaseConstructHandler(Case
, Indent1
,
2591 EmitPreprocessOptionsCallback(OptDecs
),
2596 O
.indent(Indent1
) << "return 0;\n";
2600 class DoEmitPopulateLanguageMap
;
2601 typedef void (DoEmitPopulateLanguageMap::* DoEmitPopulateLanguageMapHandler
)
2604 class DoEmitPopulateLanguageMap
2605 : public HandlerTable
<DoEmitPopulateLanguageMapHandler
>
2612 explicit DoEmitPopulateLanguageMap (raw_ostream
& O
) : O_(O
) {
2613 if (!staticMembersInitialized_
) {
2614 AddHandler("lang_to_suffixes",
2615 &DoEmitPopulateLanguageMap::onLangToSuffixes
);
2617 staticMembersInitialized_
= true;
2621 void operator() (Init
* I
) {
2622 InvokeDagInitHandler(this, I
);
2627 void onLangToSuffixes (const DagInit
& d
) {
2628 CheckNumberOfArguments(d
, 2);
2630 const std::string
& Lang
= InitPtrToString(d
.getArg(0));
2631 Init
* Suffixes
= d
.getArg(1);
2633 // Second argument to lang_to_suffixes is either a single string...
2634 if (typeid(*Suffixes
) == typeid(StringInit
)) {
2635 O_
.indent(Indent1
) << "langMap[\"" << InitPtrToString(Suffixes
)
2636 << "\"] = \"" << Lang
<< "\";\n";
2638 // ...or a list of strings.
2640 const ListInit
& Lst
= InitPtrToList(Suffixes
);
2641 assert(Lst
.size() != 0);
2642 for (ListInit::const_iterator B
= Lst
.begin(), E
= Lst
.end();
2644 O_
.indent(Indent1
) << "langMap[\"" << InitPtrToString(*B
)
2645 << "\"] = \"" << Lang
<< "\";\n";
2652 /// EmitPopulateLanguageMap - Emit the PopulateLanguageMap() function.
2653 void EmitPopulateLanguageMap (const RecordKeeper
& Records
, raw_ostream
& O
)
2655 O
<< "int PopulateLanguageMap (LanguageMap& langMap) {\n";
2657 // For each LanguageMap:
2658 const RecordVector
& LangMaps
=
2659 Records
.getAllDerivedDefinitions("LanguageMap");
2661 // Call DoEmitPopulateLanguageMap.
2662 for (RecordVector::const_iterator B
= LangMaps
.begin(),
2663 E
= LangMaps
.end(); B
!=E
; ++B
) {
2664 ListInit
* LangMap
= (*B
)->getValueAsListInit("map");
2665 std::for_each(LangMap
->begin(), LangMap
->end(),
2666 DoEmitPopulateLanguageMap(O
));
2670 O
.indent(Indent1
) << "return 0;\n";
2674 /// EmitEdgePropertyHandlerCallback - Emits code that handles edge
2675 /// properties. Helper function passed to EmitCaseConstructHandler() by
2676 /// EmitEdgeClass().
2677 void EmitEdgePropertyHandlerCallback (const Init
* i
, unsigned IndentLevel
,
2679 const DagInit
& d
= InitPtrToDag(i
);
2680 const std::string
& OpName
= GetOperatorName(d
);
2682 if (OpName
== "inc_weight") {
2683 O
.indent(IndentLevel
) << "ret += ";
2685 else if (OpName
== "error") {
2686 CheckNumberOfArguments(d
, 1);
2687 O
.indent(IndentLevel
) << "PrintError(\""
2688 << InitPtrToString(d
.getArg(0))
2690 O
.indent(IndentLevel
) << "return -1;\n";
2694 throw "Unknown operator in edge properties list: '" + OpName
+ "'!"
2695 "\nOnly 'inc_weight', 'dec_weight' and 'error' are allowed.";
2698 if (d
.getNumArgs() > 0)
2699 O
<< InitPtrToInt(d
.getArg(0)) << ";\n";
2705 /// EmitEdgeClass - Emit a single Edge# class.
2706 void EmitEdgeClass (unsigned N
, const std::string
& Target
,
2707 const DagInit
& Case
, const OptionDescriptions
& OptDescs
,
2710 // Class constructor.
2711 O
<< "class Edge" << N
<< ": public Edge {\n"
2713 O
.indent(Indent1
) << "Edge" << N
<< "() : Edge(\"" << Target
2716 // Function Weight().
2718 << "int Weight(const InputLanguagesSet& InLangs) const {\n";
2719 O
.indent(Indent2
) << "unsigned ret = 0;\n";
2721 // Handle the 'case' construct.
2722 EmitCaseConstructHandler(&Case
, Indent2
, EmitEdgePropertyHandlerCallback
,
2723 false, OptDescs
, O
);
2725 O
.indent(Indent2
) << "return ret;\n";
2726 O
.indent(Indent1
) << "}\n\n};\n\n";
2729 /// EmitEdgeClasses - Emit Edge* classes that represent graph edges.
2730 void EmitEdgeClasses (const DagVector
& EdgeVector
,
2731 const OptionDescriptions
& OptDescs
,
2734 for (DagVector::const_iterator B
= EdgeVector
.begin(),
2735 E
= EdgeVector
.end(); B
!= E
; ++B
) {
2736 const DagInit
& Edge
= **B
;
2737 const std::string
& Name
= GetOperatorName(Edge
);
2739 if (Name
== "optional_edge") {
2740 assert(IsOptionalEdge(Edge
));
2741 const std::string
& NodeB
= InitPtrToString(Edge
.getArg(1));
2743 const DagInit
& Weight
= InitPtrToDag(Edge
.getArg(2));
2744 EmitEdgeClass(i
, NodeB
, Weight
, OptDescs
, O
);
2746 else if (Name
!= "edge") {
2747 throw "Unknown edge class: '" + Name
+ "'!";
2754 /// EmitPopulateCompilationGraph - Emit the PopulateCompilationGraph() function.
2755 void EmitPopulateCompilationGraph (const DagVector
& EdgeVector
,
2756 const ToolDescriptions
& ToolDescs
,
2759 O
<< "int PopulateCompilationGraph (CompilationGraph& G) {\n";
2761 for (ToolDescriptions::const_iterator B
= ToolDescs
.begin(),
2762 E
= ToolDescs
.end(); B
!= E
; ++B
)
2763 O
.indent(Indent1
) << "G.insertNode(new " << (*B
)->Name
<< "());\n";
2770 for (DagVector::const_iterator B
= EdgeVector
.begin(),
2771 E
= EdgeVector
.end(); B
!= E
; ++B
) {
2772 const DagInit
& Edge
= **B
;
2773 const std::string
& NodeA
= InitPtrToString(Edge
.getArg(0));
2774 const std::string
& NodeB
= InitPtrToString(Edge
.getArg(1));
2776 O
.indent(Indent1
) << "if (int ret = G.insertEdge(\"" << NodeA
<< "\", ";
2778 if (IsOptionalEdge(Edge
))
2779 O
<< "new Edge" << i
<< "()";
2781 O
<< "new SimpleEdge(\"" << NodeB
<< "\")";
2784 O
.indent(Indent2
) << "return ret;\n";
2790 O
.indent(Indent1
) << "return 0;\n";
2794 /// HookInfo - Information about the hook type and number of arguments.
2797 // A hook can either have a single parameter of type std::vector<std::string>,
2798 // or NumArgs parameters of type const char*.
2799 enum HookType
{ ListHook
, ArgHook
};
2804 HookInfo() : Type(ArgHook
), NumArgs(1)
2807 HookInfo(HookType T
) : Type(T
), NumArgs(1)
2810 HookInfo(unsigned N
) : Type(ArgHook
), NumArgs(N
)
2814 typedef llvm::StringMap
<HookInfo
> HookInfoMap
;
2816 /// ExtractHookNames - Extract the hook names from all instances of
2817 /// $CALL(HookName) in the provided command line string/action. Helper
2818 /// function used by FillInHookNames().
2819 class ExtractHookNames
{
2820 HookInfoMap
& HookNames_
;
2821 const OptionDescriptions
& OptDescs_
;
2823 ExtractHookNames(HookInfoMap
& HookNames
, const OptionDescriptions
& OptDescs
)
2824 : HookNames_(HookNames
), OptDescs_(OptDescs
)
2827 void onAction (const DagInit
& Dag
) {
2828 const std::string
& Name
= GetOperatorName(Dag
);
2830 if (Name
== "forward_transformed_value") {
2831 CheckNumberOfArguments(Dag
, 2);
2832 const std::string
& OptName
= InitPtrToString(Dag
.getArg(0));
2833 const std::string
& HookName
= InitPtrToString(Dag
.getArg(1));
2834 const OptionDescription
& D
=
2835 OptDescs_
.FindParameterListOrParameter(OptName
);
2837 HookNames_
[HookName
] = HookInfo(D
.isList() ? HookInfo::ListHook
2838 : HookInfo::ArgHook
);
2840 else if (Name
== "append_cmd" || Name
== "output_suffix") {
2841 CheckNumberOfArguments(Dag
, 1);
2842 this->onCmdLine(InitPtrToString(Dag
.getArg(0)));
2846 void onCmdLine(const std::string
& Cmd
) {
2848 TokenizeCmdLine(Cmd
, cmds
);
2850 for (StrVector::const_iterator B
= cmds
.begin(), E
= cmds
.end();
2852 const std::string
& cmd
= *B
;
2854 if (cmd
== "$CALL") {
2855 unsigned NumArgs
= 0;
2856 CheckedIncrement(B
, E
, "Syntax error in $CALL invocation!");
2857 const std::string
& HookName
= *B
;
2859 if (HookName
.at(0) == ')')
2860 throw "$CALL invoked with no arguments!";
2862 while (++B
!= E
&& B
->at(0) != ')') {
2866 HookInfoMap::const_iterator H
= HookNames_
.find(HookName
);
2868 if (H
!= HookNames_
.end() && H
->second
.NumArgs
!= NumArgs
&&
2869 H
->second
.Type
!= HookInfo::ArgHook
)
2870 throw "Overloading of hooks is not allowed. Overloaded hook: "
2873 HookNames_
[HookName
] = HookInfo(NumArgs
);
2878 void operator()(const Init
* Arg
) {
2880 // We're invoked on an action (either a dag or a dag list).
2881 if (typeid(*Arg
) == typeid(DagInit
)) {
2882 const DagInit
& Dag
= InitPtrToDag(Arg
);
2883 this->onAction(Dag
);
2886 else if (typeid(*Arg
) == typeid(ListInit
)) {
2887 const ListInit
& List
= InitPtrToList(Arg
);
2888 for (ListInit::const_iterator B
= List
.begin(), E
= List
.end(); B
!= E
;
2890 const DagInit
& Dag
= InitPtrToDag(*B
);
2891 this->onAction(Dag
);
2896 // We're invoked on a command line string.
2897 this->onCmdLine(InitPtrToString(Arg
));
2900 void operator()(const Init
* Statement
, unsigned) {
2901 this->operator()(Statement
);
2905 /// FillInHookNames - Actually extract the hook names from all command
2906 /// line strings. Helper function used by EmitHookDeclarations().
2907 void FillInHookNames(const ToolDescriptions
& ToolDescs
,
2908 const OptionDescriptions
& OptDescs
,
2909 HookInfoMap
& HookNames
)
2911 // For all tool descriptions:
2912 for (ToolDescriptions::const_iterator B
= ToolDescs
.begin(),
2913 E
= ToolDescs
.end(); B
!= E
; ++B
) {
2914 const ToolDescription
& D
= *(*B
);
2916 // Look for 'forward_transformed_value' in 'actions'.
2918 WalkCase(D
.Actions
, Id(), ExtractHookNames(HookNames
, OptDescs
));
2920 // Look for hook invocations in 'cmd_line'.
2923 if (dynamic_cast<StringInit
*>(D
.CmdLine
))
2924 // This is a string.
2925 ExtractHookNames(HookNames
, OptDescs
).operator()(D
.CmdLine
);
2927 // This is a 'case' construct.
2928 WalkCase(D
.CmdLine
, Id(), ExtractHookNames(HookNames
, OptDescs
));
2932 /// EmitHookDeclarations - Parse CmdLine fields of all the tool
2933 /// property records and emit hook function declaration for each
2934 /// instance of $CALL(HookName).
2935 void EmitHookDeclarations(const ToolDescriptions
& ToolDescs
,
2936 const OptionDescriptions
& OptDescs
, raw_ostream
& O
) {
2937 HookInfoMap HookNames
;
2939 FillInHookNames(ToolDescs
, OptDescs
, HookNames
);
2940 if (HookNames
.empty())
2943 for (HookInfoMap::const_iterator B
= HookNames
.begin(),
2944 E
= HookNames
.end(); B
!= E
; ++B
) {
2945 const char* HookName
= B
->first();
2946 const HookInfo
& Info
= B
->second
;
2948 O
.indent(Indent1
) << "std::string " << HookName
<< "(";
2950 if (Info
.Type
== HookInfo::ArgHook
) {
2951 for (unsigned i
= 0, j
= Info
.NumArgs
; i
< j
; ++i
) {
2952 O
<< "const char* Arg" << i
<< (i
+1 == j
? "" : ", ");
2956 O
<< "const std::vector<std::string>& Arg";
2963 /// EmitIncludes - Emit necessary #include directives and some
2964 /// additional declarations.
2965 void EmitIncludes(raw_ostream
& O
) {
2966 O
<< "#include \"llvm/CompilerDriver/BuiltinOptions.h\"\n"
2967 << "#include \"llvm/CompilerDriver/CompilationGraph.h\"\n"
2968 << "#include \"llvm/CompilerDriver/Error.h\"\n"
2969 << "#include \"llvm/CompilerDriver/Tool.h\"\n\n"
2971 << "#include \"llvm/Support/CommandLine.h\"\n"
2972 << "#include \"llvm/Support/raw_ostream.h\"\n\n"
2974 << "#include <algorithm>\n"
2975 << "#include <cstdlib>\n"
2976 << "#include <iterator>\n"
2977 << "#include <stdexcept>\n\n"
2979 << "using namespace llvm;\n"
2980 << "using namespace llvmc;\n\n"
2982 << "inline const char* checkCString(const char* s)\n"
2983 << "{ return s == NULL ? \"\" : s; }\n\n";
2987 /// DriverData - Holds all information about the driver.
2989 OptionDescriptions OptDescs
;
2990 ToolDescriptions ToolDescs
;
2995 /// HasSink - Go through the list of tool descriptions and check if
2996 /// there are any with the 'sink' property set.
2997 bool HasSink(const ToolDescriptions
& ToolDescs
) {
2998 for (ToolDescriptions::const_iterator B
= ToolDescs
.begin(),
2999 E
= ToolDescs
.end(); B
!= E
; ++B
)
3006 /// CollectDriverData - Collect compilation graph edges, tool properties and
3007 /// option properties from the parse tree.
3008 void CollectDriverData (const RecordKeeper
& Records
, DriverData
& Data
) {
3009 // Collect option properties.
3010 const RecordVector
& OptionLists
=
3011 Records
.getAllDerivedDefinitions("OptionList");
3012 CollectOptionDescriptions(OptionLists
, Data
.OptDescs
);
3014 // Collect tool properties.
3015 const RecordVector
& Tools
= Records
.getAllDerivedDefinitions("Tool");
3016 CollectToolDescriptions(Tools
, Data
.ToolDescs
);
3017 Data
.HasSink
= HasSink(Data
.ToolDescs
);
3019 // Collect compilation graph edges.
3020 const RecordVector
& CompilationGraphs
=
3021 Records
.getAllDerivedDefinitions("CompilationGraph");
3022 FillInEdgeVector(CompilationGraphs
, Data
.Edges
);
3025 /// CheckDriverData - Perform some sanity checks on the collected data.
3026 void CheckDriverData(DriverData
& Data
) {
3027 // Filter out all tools not mentioned in the compilation graph.
3028 FilterNotInGraph(Data
.Edges
, Data
.ToolDescs
);
3030 // Typecheck the compilation graph.
3031 TypecheckGraph(Data
.Edges
, Data
.ToolDescs
);
3033 // Check that there are no options without side effects (specified
3034 // only in the OptionList).
3035 CheckForSuperfluousOptions(Data
.Edges
, Data
.ToolDescs
, Data
.OptDescs
);
3038 void EmitDriverCode(const DriverData
& Data
,
3039 raw_ostream
& O
, RecordKeeper
&Records
) {
3040 // Emit file header.
3043 // Emit global option registration code.
3044 O
<< "namespace llvmc {\n"
3045 << "namespace autogenerated {\n\n";
3046 EmitOptionDefinitions(Data
.OptDescs
, Data
.HasSink
, O
);
3047 O
<< "} // End namespace autogenerated.\n"
3048 << "} // End namespace llvmc.\n\n";
3050 // Emit hook declarations.
3051 O
<< "namespace hooks {\n";
3052 EmitHookDeclarations(Data
.ToolDescs
, Data
.OptDescs
, O
);
3053 O
<< "} // End namespace hooks.\n\n";
3055 O
<< "namespace {\n\n";
3056 O
<< "using namespace llvmc::autogenerated;\n\n";
3058 // Emit Tool classes.
3059 for (ToolDescriptions::const_iterator B
= Data
.ToolDescs
.begin(),
3060 E
= Data
.ToolDescs
.end(); B
!=E
; ++B
)
3061 EmitToolClassDefinition(*(*B
), Data
.OptDescs
, O
);
3063 // Emit Edge# classes.
3064 EmitEdgeClasses(Data
.Edges
, Data
.OptDescs
, O
);
3066 O
<< "} // End anonymous namespace.\n\n";
3068 O
<< "namespace llvmc {\n";
3069 O
<< "namespace autogenerated {\n\n";
3071 // Emit PreprocessOptions() function.
3072 EmitPreprocessOptions(Records
, Data
.OptDescs
, O
);
3074 // Emit PopulateLanguageMap() function
3075 // (language map maps from file extensions to language names).
3076 EmitPopulateLanguageMap(Records
, O
);
3078 // Emit PopulateCompilationGraph() function.
3079 EmitPopulateCompilationGraph(Data
.Edges
, Data
.ToolDescs
, O
);
3081 O
<< "} // End namespace autogenerated.\n";
3082 O
<< "} // End namespace llvmc.\n\n";
3088 // End of anonymous namespace
3091 /// run - The back-end entry point.
3092 void LLVMCConfigurationEmitter::run (raw_ostream
&O
) {
3096 CollectDriverData(Records
, Data
);
3097 CheckDriverData(Data
);
3099 this->EmitSourceFileHeader("llvmc-based driver: auto-generated code", O
);
3100 EmitDriverCode(Data
, O
, Records
);
3102 } catch (std::exception
& Error
) {
3103 throw Error
.what() + std::string(" - usually this means a syntax error.");