1 //===- LLVMCConfigurationEmitter.cpp - Generate LLVMCC config -------------===//
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 LLVMCC configuration code.
12 //===----------------------------------------------------------------------===//
14 #include "LLVMCCConfigurationEmitter.h"
17 #include "llvm/ADT/IntrusiveRefCntPtr.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/ADT/StringMap.h"
21 #include "llvm/Support/Streams.h"
32 //===----------------------------------------------------------------------===//
35 typedef std::vector<Record*> RecordVector;
36 typedef std::vector<std::string> StrVector;
38 //===----------------------------------------------------------------------===//
41 // Indentation strings
42 const char * Indent1 = " ";
43 const char * Indent2 = " ";
44 const char * Indent3 = " ";
45 const char * Indent4 = " ";
47 // Default help string
48 const char * DefaultHelpString = "NO HELP MESSAGE PROVIDED";
50 // Name for the "sink" option
51 const char * SinkOptionName = "AutoGeneratedSinkOption";
53 //===----------------------------------------------------------------------===//
56 std::string InitPtrToString(Init* ptr) {
57 StringInit& val = dynamic_cast<StringInit&>(*ptr);
58 return val.getValue();
61 //===----------------------------------------------------------------------===//
62 /// Back-end specific code
64 // A command-line option can have one of the following types:
66 // Switch - a simple switch w/o arguments, e.g. -O2
68 // Parameter - an option that takes one(and only one) argument, e.g. -o file,
71 // ParameterList - same as Parameter, but more than one occurence
72 // of the option is allowed, e.g. -lm -lpthread
74 // Prefix - argument is everything after the prefix,
75 // e.g. -Wa,-foo,-bar, -DNAME=VALUE
77 // PrefixList - same as Prefix, but more than one option occurence is
80 namespace OptionType {
81 enum OptionType { Switch, Parameter, ParameterList, Prefix, PrefixList};
84 bool IsListOptionType (OptionType::OptionType t) {
85 return (t == OptionType::ParameterList || t == OptionType::PrefixList);
88 // Code duplication here is necessary because one option can affect
89 // several tools and those tools may have different actions associated
90 // with this option. GlobalOptionDescriptions are used to generate
91 // the option registration code, while ToolOptionDescriptions are used
92 // to generate tool-specific code.
94 // Base class for option descriptions
96 struct OptionDescription {
97 OptionType::OptionType Type;
100 OptionDescription(OptionType::OptionType t = OptionType::Switch,
101 const std::string& n = "")
105 const char* GenTypeDeclaration() const {
107 case OptionType::PrefixList:
108 case OptionType::ParameterList:
109 return "cl::list<std::string>";
110 case OptionType::Switch:
111 return "cl::opt<bool>";
112 case OptionType::Parameter:
113 case OptionType::Prefix:
115 return "cl::opt<std::string>";
119 std::string GenVariableName() const {
121 case OptionType::Switch:
122 return "AutoGeneratedSwitch" + Name;
123 case OptionType::Prefix:
124 return "AutoGeneratedPrefix" + Name;
125 case OptionType::PrefixList:
126 return "AutoGeneratedPrefixList" + Name;
127 case OptionType::Parameter:
128 return "AutoGeneratedParameter" + Name;
129 case OptionType::ParameterList:
131 return "AutoGeneratedParameterList" + Name;
137 // Global option description
139 namespace GlobalOptionDescriptionFlags {
140 enum GlobalOptionDescriptionFlags { Required = 0x1 };
143 struct GlobalOptionDescription : public OptionDescription {
147 // StringMap can only store DefaultConstructible objects
148 GlobalOptionDescription() : OptionDescription(), Flags(0)
151 GlobalOptionDescription (OptionType::OptionType t, const std::string& n)
152 : OptionDescription(t, n), Help(DefaultHelpString), Flags(0)
155 bool isRequired() const {
156 return Flags & GlobalOptionDescriptionFlags::Required;
159 Flags |= GlobalOptionDescriptionFlags::Required;
162 // Merge two option descriptions
163 void Merge (const GlobalOptionDescription& other)
165 if (other.Type != Type)
166 throw "Conflicting definitions for the option " + Name + "!";
168 if (Help.empty() && !other.Help.empty())
170 else if (!Help.empty() && !other.Help.empty())
171 cerr << "Warning: more than one help string defined for option "
174 Flags |= other.Flags;
178 // A GlobalOptionDescription array
179 // + some flags affecting generation of option declarations
180 struct GlobalOptionDescriptions {
181 typedef StringMap<GlobalOptionDescription> container_type;
182 typedef container_type::const_iterator const_iterator;
184 // A list of GlobalOptionDescriptions
185 container_type Descriptions;
186 // Should the emitter generate a "cl::sink" option?
189 // Support for STL-style iteration
190 const_iterator begin() const { return Descriptions.begin(); }
191 const_iterator end() const { return Descriptions.end(); }
195 // Tool-local option description
197 // Properties without arguments are implemented as flags
198 namespace ToolOptionDescriptionFlags {
199 enum ToolOptionDescriptionFlags { StopCompilation = 0x1,
200 Forward = 0x2, UnpackValues = 0x4};
202 namespace OptionPropertyType {
203 enum OptionPropertyType { AppendCmd };
206 typedef std::pair<OptionPropertyType::OptionPropertyType, std::string>
208 typedef SmallVector<OptionProperty, 4> OptionPropertyList;
210 struct ToolOptionDescription : public OptionDescription {
212 OptionPropertyList Props;
214 // StringMap can only store DefaultConstructible objects
215 ToolOptionDescription() : OptionDescription() {}
217 ToolOptionDescription (OptionType::OptionType t, const std::string& n)
218 : OptionDescription(t, n)
221 // Various boolean properties
222 bool isStopCompilation() const {
223 return Flags & ToolOptionDescriptionFlags::StopCompilation;
225 void setStopCompilation() {
226 Flags |= ToolOptionDescriptionFlags::StopCompilation;
229 bool isForward() const {
230 return Flags & ToolOptionDescriptionFlags::Forward;
233 Flags |= ToolOptionDescriptionFlags::Forward;
236 bool isUnpackValues() const {
237 return Flags & ToolOptionDescriptionFlags::UnpackValues;
239 void setUnpackValues() {
240 Flags |= ToolOptionDescriptionFlags::UnpackValues;
243 void AddProperty (OptionPropertyType::OptionPropertyType t,
244 const std::string& val)
246 Props.push_back(std::make_pair(t, val));
250 typedef StringMap<ToolOptionDescription> ToolOptionDescriptions;
252 // Tool information record
254 namespace ToolFlags {
255 enum ToolFlags { Join = 0x1, Sink = 0x2 };
258 struct ToolProperties : public RefCountedBase<ToolProperties> {
261 std::string InLanguage;
262 std::string OutLanguage;
263 std::string OutputSuffix;
265 ToolOptionDescriptions OptDescs;
267 // Various boolean properties
268 void setSink() { Flags |= ToolFlags::Sink; }
269 bool isSink() const { return Flags & ToolFlags::Sink; }
270 void setJoin() { Flags |= ToolFlags::Join; }
271 bool isJoin() const { return Flags & ToolFlags::Join; }
273 // Default ctor here is needed because StringMap can only store
274 // DefaultConstructible objects
276 ToolProperties (const std::string& n) : Name(n) {}
280 // A list of Tool information records
281 // IntrusiveRefCntPtrs are used because StringMap has no copy constructor
282 // (and we want to avoid copying ToolProperties anyway)
283 typedef std::vector<IntrusiveRefCntPtr<ToolProperties> > ToolPropertiesList;
286 // Function object for iterating over a list of tool property records
287 class CollectProperties {
290 /// Implementation details
292 // "Property handler" - a function that extracts information
293 // about a given tool property from its DAG representation
294 typedef void (CollectProperties::*PropertyHandler)(DagInit*);
296 // Map from property names -> property handlers
297 typedef StringMap<PropertyHandler> PropertyHandlerMap;
299 // "Option property handler" - a function that extracts information
300 // about a given option property from its DAG representation
301 typedef void (CollectProperties::*
302 OptionPropertyHandler)(DagInit*, GlobalOptionDescription &);
304 // Map from option property names -> option property handlers
305 typedef StringMap<OptionPropertyHandler> OptionPropertyHandlerMap;
307 // Static maps from strings to CollectProperties methods("handlers")
308 static PropertyHandlerMap propertyHandlers_;
309 static OptionPropertyHandlerMap optionPropertyHandlers_;
310 static bool staticMembersInitialized_;
313 /// This is where the information is stored
315 // Current Tool properties
316 ToolProperties& toolProps_;
317 // OptionDescriptions table(used to register options globally)
318 GlobalOptionDescriptions& optDescs_;
322 explicit CollectProperties (ToolProperties& p, GlobalOptionDescriptions& d)
323 : toolProps_(p), optDescs_(d)
325 if (!staticMembersInitialized_) {
326 // Init tool property handlers
327 propertyHandlers_["cmd_line"] = &CollectProperties::onCmdLine;
328 propertyHandlers_["in_language"] = &CollectProperties::onInLanguage;
329 propertyHandlers_["join"] = &CollectProperties::onJoin;
330 propertyHandlers_["out_language"] = &CollectProperties::onOutLanguage;
331 propertyHandlers_["output_suffix"] = &CollectProperties::onOutputSuffix;
332 propertyHandlers_["parameter_option"]
333 = &CollectProperties::onParameter;
334 propertyHandlers_["parameter_list_option"] =
335 &CollectProperties::onParameterList;
336 propertyHandlers_["prefix_option"] = &CollectProperties::onPrefix;
337 propertyHandlers_["prefix_list_option"] =
338 &CollectProperties::onPrefixList;
339 propertyHandlers_["sink"] = &CollectProperties::onSink;
340 propertyHandlers_["switch_option"] = &CollectProperties::onSwitch;
342 // Init option property handlers
343 optionPropertyHandlers_["append_cmd"] = &CollectProperties::onAppendCmd;
344 optionPropertyHandlers_["forward"] = &CollectProperties::onForward;
345 optionPropertyHandlers_["help"] = &CollectProperties::onHelp;
346 optionPropertyHandlers_["required"] = &CollectProperties::onRequired;
347 optionPropertyHandlers_["stop_compilation"] =
348 &CollectProperties::onStopCompilation;
349 optionPropertyHandlers_["unpack_values"] =
350 &CollectProperties::onUnpackValues;
352 staticMembersInitialized_ = true;
356 // Gets called for every tool property;
357 // Just forwards to the corresponding property handler.
358 void operator() (Init* i) {
359 DagInit& d = dynamic_cast<DagInit&>(*i);
360 std::string property_name = d.getOperator()->getAsString();
361 PropertyHandlerMap::iterator method
362 = propertyHandlers_.find(property_name);
364 if (method != propertyHandlers_.end()) {
365 PropertyHandler h = method->second;
369 throw "Unknown tool property: " + property_name + "!";
375 /// Property handlers --
376 /// Functions that extract information about tool properties from
377 /// DAG representation.
379 void onCmdLine (DagInit* d) {
380 checkNumberOfArguments(d, 1);
381 SplitString(InitPtrToString(d->getArg(0)), toolProps_.CmdLine);
382 if (toolProps_.CmdLine.empty())
383 throw std::string("Tool " + toolProps_.Name + " has empty command line!");
386 void onInLanguage (DagInit* d) {
387 checkNumberOfArguments(d, 1);
388 toolProps_.InLanguage = InitPtrToString(d->getArg(0));
391 void onJoin (DagInit* d) {
392 checkNumberOfArguments(d, 0);
393 toolProps_.setJoin();
396 void onOutLanguage (DagInit* d) {
397 checkNumberOfArguments(d, 1);
398 toolProps_.OutLanguage = InitPtrToString(d->getArg(0));
401 void onOutputSuffix (DagInit* d) {
402 checkNumberOfArguments(d, 1);
403 toolProps_.OutputSuffix = InitPtrToString(d->getArg(0));
406 void onSink (DagInit* d) {
407 checkNumberOfArguments(d, 0);
408 optDescs_.HasSink = true;
409 toolProps_.setSink();
412 void onSwitch (DagInit* d) { addOption(d, OptionType::Switch); }
413 void onParameter (DagInit* d) { addOption(d, OptionType::Parameter); }
414 void onParameterList (DagInit* d) { addOption(d, OptionType::ParameterList); }
415 void onPrefix (DagInit* d) { addOption(d, OptionType::Prefix); }
416 void onPrefixList (DagInit* d) { addOption(d, OptionType::PrefixList); }
418 /// Option property handlers --
419 /// Methods that handle properties that are common for all types of
420 /// options (like append_cmd, stop_compilation)
422 void onAppendCmd (DagInit* d, GlobalOptionDescription& o) {
423 checkNumberOfArguments(d, 1);
424 std::string const& cmd = InitPtrToString(d->getArg(0));
426 toolProps_.OptDescs[o.Name].AddProperty(OptionPropertyType::AppendCmd, cmd);
429 void onForward (DagInit* d, GlobalOptionDescription& o) {
430 checkNumberOfArguments(d, 0);
431 toolProps_.OptDescs[o.Name].setForward();
434 void onHelp (DagInit* d, GlobalOptionDescription& o) {
435 checkNumberOfArguments(d, 1);
436 const std::string& help_message = InitPtrToString(d->getArg(0));
438 o.Help = help_message;
441 void onRequired (DagInit* d, GlobalOptionDescription& o) {
442 checkNumberOfArguments(d, 0);
446 void onStopCompilation (DagInit* d, GlobalOptionDescription& o) {
447 checkNumberOfArguments(d, 0);
448 if (o.Type != OptionType::Switch)
449 throw std::string("Only options of type Switch can stop compilation!");
450 toolProps_.OptDescs[o.Name].setStopCompilation();
453 void onUnpackValues (DagInit* d, GlobalOptionDescription& o) {
454 checkNumberOfArguments(d, 0);
455 toolProps_.OptDescs[o.Name].setUnpackValues();
460 // Add an option of type t
461 void addOption (DagInit* d, OptionType::OptionType t) {
462 checkNumberOfArguments(d, 2);
463 const std::string& name = InitPtrToString(d->getArg(0));
465 GlobalOptionDescription o(t, name);
466 toolProps_.OptDescs[name].Type = t;
467 toolProps_.OptDescs[name].Name = name;
468 processOptionProperties(d, o);
469 insertDescription(o);
472 // Ensure that the number of args in d is <= min_arguments,
473 // throw exception otherwise
474 void checkNumberOfArguments (DagInit* d, unsigned min_arguments) {
475 if (d->getNumArgs() < min_arguments)
476 throw "Property " + d->getOperator()->getAsString()
477 + " has too few arguments!";
480 // Insert new GlobalOptionDescription into GlobalOptionDescriptions list
481 void insertDescription (const GlobalOptionDescription& o)
483 if (optDescs_.Descriptions.count(o.Name)) {
484 GlobalOptionDescription& D = optDescs_.Descriptions[o.Name];
488 optDescs_.Descriptions[o.Name] = o;
492 // Go through the list of option properties and call a corresponding
496 // name - option name
497 // d - option property list
498 void processOptionProperties (DagInit* d, GlobalOptionDescription& o) {
499 // First argument is option name
500 checkNumberOfArguments(d, 2);
502 for (unsigned B = 1, E = d->getNumArgs(); B!=E; ++B) {
503 DagInit& option_property
504 = dynamic_cast<DagInit&>(*d->getArg(B));
505 const std::string& option_property_name
506 = option_property.getOperator()->getAsString();
507 OptionPropertyHandlerMap::iterator method
508 = optionPropertyHandlers_.find(option_property_name);
510 if (method != optionPropertyHandlers_.end()) {
511 OptionPropertyHandler h = method->second;
512 (this->*h)(&option_property, o);
515 throw "Unknown option property: " + option_property_name + "!";
521 // Static members of CollectProperties
522 CollectProperties::PropertyHandlerMap
523 CollectProperties::propertyHandlers_;
525 CollectProperties::OptionPropertyHandlerMap
526 CollectProperties::optionPropertyHandlers_;
528 bool CollectProperties::staticMembersInitialized_ = false;
531 // Gather information from the parsed TableGen data
532 // (Basically a wrapper for CollectProperties)
533 void CollectToolProperties (RecordVector::const_iterator B,
534 RecordVector::const_iterator E,
535 ToolPropertiesList& TPList,
536 GlobalOptionDescriptions& OptDescs)
538 // Iterate over a properties list of every Tool definition
540 RecordVector::value_type T = *B;
541 ListInit* PropList = T->getValueAsListInit("properties");
543 throw std::string("Tool has no property list!");
545 IntrusiveRefCntPtr<ToolProperties>
546 ToolProps(new ToolProperties(T->getName()));
548 std::for_each(PropList->begin(), PropList->end(),
549 CollectProperties(*ToolProps, OptDescs));
550 TPList.push_back(ToolProps);
554 // Used by EmitGenerateActionMethod
555 void EmitOptionPropertyHandlingCode (const ToolProperties& P,
556 const ToolOptionDescription& D,
560 O << Indent2 << "if (";
561 if (D.Type == OptionType::Switch)
562 O << D.GenVariableName();
564 O << '!' << D.GenVariableName() << ".empty()";
568 // Handle option properties that take an argument
569 for (OptionPropertyList::const_iterator B = D.Props.begin(),
570 E = D.Props.end(); B!=E; ++B) {
571 const OptionProperty& val = *B;
574 // (append_cmd cmd) property
575 case OptionPropertyType::AppendCmd:
576 O << Indent3 << "vec.push_back(\"" << val.second << "\");\n";
578 // Other properties with argument
586 // (forward) property
589 case OptionType::Switch:
590 O << Indent3 << "vec.push_back(\"-" << D.Name << "\");\n";
592 case OptionType::Parameter:
593 O << Indent3 << "vec.push_back(\"-" << D.Name << "\");\n";
594 O << Indent3 << "vec.push_back(" << D.GenVariableName() << ");\n";
596 case OptionType::Prefix:
597 O << Indent3 << "vec.push_back(\"-" << D.Name << "\" + "
598 << D.GenVariableName() << ");\n";
600 case OptionType::PrefixList:
601 O << Indent3 << "for (" << D.GenTypeDeclaration()
602 << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
603 << Indent3 << "E = " << D.GenVariableName() << ".end(); B != E; ++B)\n"
604 << Indent4 << "vec.push_back(\"-" << D.Name << "\" + "
607 case OptionType::ParameterList:
608 O << Indent3 << "for (" << D.GenTypeDeclaration()
609 << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
610 << Indent3 << "E = " << D.GenVariableName()
611 << ".end() ; B != E; ++B) {\n"
612 << Indent4 << "vec.push_back(\"-" << D.Name << "\");\n"
613 << Indent4 << "vec.push_back(*B);\n"
619 // (unpack_values) property
620 if (D.isUnpackValues()) {
621 if (IsListOptionType(D.Type)) {
622 O << Indent3 << "for (" << D.GenTypeDeclaration()
623 << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
624 << Indent3 << "E = " << D.GenVariableName()
625 << ".end(); B != E; ++B)\n"
626 << Indent4 << "UnpackValues(*B, vec);\n";
628 else if (D.Type == OptionType::Prefix || D.Type == OptionType::Parameter){
629 O << Indent3 << "UnpackValues("
630 << D.GenVariableName() << ", vec);\n";
633 // TOFIX: move this to the type-checking phase
634 throw std::string("Switches can't have unpack_values property!");
639 O << Indent2 << "}\n";
642 // Emite one of two versions of GenerateAction method
643 void EmitGenerateActionMethod (const ToolProperties& P, int V, std::ostream& O)
645 assert(V==1 || V==2);
647 O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n";
649 O << Indent1 << "Action GenerateAction(const sys::Path& inFile,\n";
651 O << Indent2 << "const sys::Path& outFile) const\n"
653 << Indent2 << "std::vector<std::string> vec;\n";
655 // Parse CmdLine tool property
656 StrVector::const_iterator I = P.CmdLine.begin();
658 for (StrVector::const_iterator E = P.CmdLine.end(); I != E; ++I) {
659 const std::string& cmd = *I;
661 if (cmd == "$INFILE") {
663 O << "for (PathVector::const_iterator B = inFiles.begin()"
664 << ", E = inFiles.end();\n"
665 << Indent2 << "B != E; ++B)\n"
666 << Indent3 << "vec.push_back(B->toString());\n";
668 O << "vec.push_back(inFile.toString());\n";
670 else if (cmd == "$OUTFILE") {
671 O << "vec.push_back(outFile.toString());\n";
674 O << "vec.push_back(\"" << cmd << "\");\n";
678 // For every understood option, emit handling code
679 for (ToolOptionDescriptions::const_iterator B = P.OptDescs.begin(),
680 E = P.OptDescs.end(); B != E; ++B) {
681 const ToolOptionDescription& val = B->second;
682 EmitOptionPropertyHandlingCode(P, val, O);
685 // Handle Sink property
687 O << Indent2 << "if (!" << SinkOptionName << ".empty()) {\n"
688 << Indent3 << "vec.insert(vec.end(), "
689 << SinkOptionName << ".begin(), " << SinkOptionName << ".end());\n"
693 O << Indent2 << "return Action(\"" << P.CmdLine.at(0) << "\", vec);\n"
694 << Indent1 << "}\n\n";
697 // Emit GenerateAction methods for Tool classes
698 void EmitGenerateActionMethods (const ToolProperties& P, std::ostream& O) {
701 O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n"
702 << Indent2 << "const llvm::sys::Path& outFile) const\n"
704 << Indent2 << "throw std::runtime_error(\"" << P.Name
705 << " is not a Join tool!\");\n"
706 << Indent1 << "}\n\n";
708 EmitGenerateActionMethod(P, 1, O);
710 EmitGenerateActionMethod(P, 2, O);
713 // Emit IsLast() method for Tool classes
714 void EmitIsLastMethod (const ToolProperties& P, std::ostream& O) {
715 O << Indent1 << "bool IsLast() const {\n"
716 << Indent2 << "bool last = false;\n";
718 for (ToolOptionDescriptions::const_iterator B = P.OptDescs.begin(),
719 E = P.OptDescs.end(); B != E; ++B) {
720 const ToolOptionDescription& val = B->second;
722 if (val.isStopCompilation())
724 << "if (" << val.GenVariableName()
725 << ")\n" << Indent3 << "last = true;\n";
728 O << Indent2 << "return last;\n"
729 << Indent1 << "}\n\n";
732 // Emit static [Input,Output]Language() methods for Tool classes
733 void EmitInOutLanguageMethods (const ToolProperties& P, std::ostream& O) {
734 O << Indent1 << "std::string InputLanguage() const {\n"
735 << Indent2 << "return \"" << P.InLanguage << "\";\n"
736 << Indent1 << "}\n\n";
738 O << Indent1 << "std::string OutputLanguage() const {\n"
739 << Indent2 << "return \"" << P.OutLanguage << "\";\n"
740 << Indent1 << "}\n\n";
743 // Emit static [Input,Output]Language() methods for Tool classes
744 void EmitOutputSuffixMethod (const ToolProperties& P, std::ostream& O) {
745 O << Indent1 << "std::string OutputSuffix() const {\n"
746 << Indent2 << "return \"" << P.OutputSuffix << "\";\n"
747 << Indent1 << "}\n\n";
750 // Emit static Name() method for Tool classes
751 void EmitNameMethod (const ToolProperties& P, std::ostream& O) {
752 O << Indent1 << "std::string Name() const {\n"
753 << Indent2 << "return \"" << P.Name << "\";\n"
754 << Indent1 << "}\n\n";
757 // Emit static Name() method for Tool classes
758 void EmitIsJoinMethod (const ToolProperties& P, std::ostream& O) {
759 O << Indent1 << "bool IsJoin() const {\n";
761 O << Indent2 << "return true;\n";
763 O << Indent2 << "return false;\n";
764 O << Indent1 << "}\n\n";
767 // Emit a Tool class definition
768 void EmitToolClassDefinition (const ToolProperties& P, std::ostream& O) {
770 O << "class " << P.Name << " : public Tool {\n"
773 EmitNameMethod(P, O);
774 EmitInOutLanguageMethods(P, O);
775 EmitOutputSuffixMethod(P, O);
776 EmitIsJoinMethod(P, O);
777 EmitGenerateActionMethods(P, O);
778 EmitIsLastMethod(P, O);
780 // Close class definition
784 // Iterate over a list of option descriptions and emit registration code
785 void EmitOptionDescriptions (const GlobalOptionDescriptions& descs,
788 // Emit static cl::Option variables
789 for (GlobalOptionDescriptions::const_iterator B = descs.begin(),
790 E = descs.end(); B!=E; ++B) {
791 const GlobalOptionDescription& val = B->second;
793 O << val.GenTypeDeclaration() << ' '
794 << val.GenVariableName()
795 << "(\"" << val.Name << '\"';
797 if (val.Type == OptionType::Prefix || val.Type == OptionType::PrefixList)
800 if (val.isRequired()) {
802 case OptionType::PrefixList:
803 case OptionType::ParameterList:
804 O << ", cl::OneOrMore";
807 O << ", cl::Required";
811 O << ", cl::desc(\"" << val.Help << "\"));\n";
815 O << "cl::list<std::string> " << SinkOptionName << "(cl::Sink);\n";
820 void EmitPopulateLanguageMap (const RecordKeeper& Records, std::ostream& O)
822 // Get the relevant field out of RecordKeeper
823 Record* LangMapRecord = Records.getDef("LanguageMap");
825 throw std::string("Language map definition not found!");
827 ListInit* LangsToSuffixesList = LangMapRecord->getValueAsListInit("map");
828 if (!LangsToSuffixesList)
829 throw std::string("Error in the language map definition!");
832 O << "void llvmcc::PopulateLanguageMap(LanguageMap& language_map) {\n";
834 for (unsigned i = 0; i < LangsToSuffixesList->size(); ++i) {
835 Record* LangToSuffixes = LangsToSuffixesList->getElementAsRecord(i);
837 const std::string& Lang = LangToSuffixes->getValueAsString("lang");
838 const ListInit* Suffixes = LangToSuffixes->getValueAsListInit("suffixes");
840 for (unsigned i = 0; i < Suffixes->size(); ++i)
841 O << Indent1 << "language_map[\""
842 << InitPtrToString(Suffixes->getElement(i))
843 << "\"] = \"" << Lang << "\";\n";
849 void EmitPopulateCompilationGraph (const RecordKeeper& Records,
850 StringMap<std::string>& ToolToLang,
853 // Get the relevant field out of RecordKeeper
854 Record* ToolChains = Records.getDef("ToolChains");
856 throw std::string("No ToolChains specification found!");
857 ListInit* chains = ToolChains->getValueAsListInit("chains");
859 throw std::string("Error in toolchain list definition!");
862 O << "void llvmcc::PopulateCompilationGraph(CompilationGraph& G) {\n"
863 << Indent1 << "PopulateLanguageMap(G.ExtsToLangs);\n"
864 << Indent1 << "std::vector<IntrusiveRefCntPtr<Tool> > vec;\n\n";
866 for (unsigned i = 0; i < chains->size(); ++i) {
867 Record* ToolChain = chains->getElementAsRecord(i);
868 ListInit* Tools = ToolChain->getValueAsListInit("tools");
870 // Get name of the first tool in the list
871 const std::string& firstTool =
872 dynamic_cast<DefInit&>(**Tools->begin()).getDef()->getName();
874 for (ListInit::iterator B = Tools->begin(),
875 E = Tools->end(); B != E; ++B) {
876 Record* val = dynamic_cast<DefInit&>(**B).getDef();
877 O << Indent1 << "vec.push_back(IntrusiveRefCntPtr<Tool>(new "
878 << val->getName() << "()));\n";
880 O << Indent1 << "G.ToolChains[\"" << ToolToLang[firstTool]
882 O << Indent1 << "vec.clear();\n\n";
888 void FillInToolToLang (const ToolPropertiesList& T,
889 StringMap<std::string>& M) {
890 for (ToolPropertiesList::const_iterator B = T.begin(), E = T.end();
892 const ToolProperties& P = *(*B);
893 M[P.Name] = P.InLanguage;
897 // End of anonymous namespace
900 // Back-end entry point
901 void LLVMCCConfigurationEmitter::run (std::ostream &O) {
903 EmitSourceFileHeader("LLVMCC Configuration Library", O);
905 // Get a list of all defined Tools
906 RecordVector Tools = Records.getAllDerivedDefinitions("Tool");
908 throw std::string("No tool definitions found!");
910 // Gather information from the Tool descriptions
911 ToolPropertiesList tool_props;
912 GlobalOptionDescriptions opt_descs;
913 CollectToolProperties(Tools.begin(), Tools.end(), tool_props, opt_descs);
915 // Emit global option registration code
916 EmitOptionDescriptions(opt_descs, O);
918 // Emit PopulateLanguageMap function
919 // (a language map maps from file extensions to language names)
920 EmitPopulateLanguageMap(Records, O);
923 for (ToolPropertiesList::const_iterator B = tool_props.begin(),
924 E = tool_props.end(); B!=E; ++B)
925 EmitToolClassDefinition(*(*B), O);
927 // Fill in table that maps tool names to languages
928 StringMap<std::string> ToolToLang;
929 FillInToolToLang(tool_props, ToolToLang);
931 // Emit PopulateCompilationGraph function
932 EmitPopulateCompilationGraph(Records, ToolToLang, O);