blob: 9c6f064460100788d62aaf97b19a2ce84443cb17 [file] [log] [blame]
Anton Korobeynikovac67b7e2008-03-23 08:57:20 +00001//===- LLVMCConfigurationEmitter.cpp - Generate LLVMCC config -------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open
6// Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This tablegen backend is responsible for emitting LLVMCC configuration code.
11//
12//===----------------------------------------------------------------------===//
13
14#include "LLVMCCConfigurationEmitter.h"
15#include "Record.h"
16
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"
22
23#include <algorithm>
24#include <cassert>
25#include <functional>
26#include <string>
27
28using namespace llvm;
29
30namespace {
31
32//===----------------------------------------------------------------------===//
33/// Typedefs
34
35typedef std::vector<Record*> RecordVector;
36typedef std::vector<std::string> StrVector;
37
38//===----------------------------------------------------------------------===//
39/// Constants
40
41// Indentation strings
42const char * Indent1 = " ";
43const char * Indent2 = " ";
44const char * Indent3 = " ";
45const char * Indent4 = " ";
46
47// Default help string
48const char * DefaultHelpString = "NO HELP MESSAGE PROVIDED";
49
50// Name for the "sink" option
51const char * SinkOptionName = "AutoGeneratedSinkOption";
52
53//===----------------------------------------------------------------------===//
54/// Helper functions
55
56std::string InitPtrToString(Init* ptr) {
57 StringInit& val = dynamic_cast<StringInit&>(*ptr);
58 return val.getValue();
59}
60
61//===----------------------------------------------------------------------===//
62/// Back-end specific code
63
64// A command-line option can have one of the following types:
65//
66// Switch - a simple switch w/o arguments, e.g. -O2
67//
68// Parameter - an option that takes one(and only one) argument, e.g. -o file,
69// --output=file
70//
71// ParameterList - same as Parameter, but more than one occurence
72// of the option is allowed, e.g. -lm -lpthread
73//
74// Prefix - argument is everything after the prefix,
75// e.g. -Wa,-foo,-bar, -DNAME=VALUE
76//
77// PrefixList - same as Prefix, but more than one option occurence is
78// allowed
79
80namespace OptionType {
81 enum OptionType { Switch, Parameter, ParameterList, Prefix, PrefixList};
82}
83
84bool IsListOptionType (OptionType::OptionType t) {
85 return (t == OptionType::ParameterList || t == OptionType::PrefixList);
86}
87
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.
93
94// Base class for option descriptions
95
96struct OptionDescription {
97 OptionType::OptionType Type;
98 std::string Name;
99
100 OptionDescription(OptionType::OptionType t = OptionType::Switch,
101 const std::string& n = "")
102 : Type(t), Name(n)
103 {}
104
105 const char* GenTypeDeclaration() const {
106 switch (Type) {
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:
114 default:
115 return "cl::opt<std::string>";
116 }
117 }
118
119 std::string GenVariableName() const {
120 switch (Type) {
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:
130 default:
131 return "AutoGeneratedParameterList" + Name;
132 }
133 }
134
135};
136
137// Global option description
138
139namespace GlobalOptionDescriptionFlags {
140 enum GlobalOptionDescriptionFlags { Required = 0x1 };
141}
142
143struct GlobalOptionDescription : public OptionDescription {
144 std::string Help;
145 unsigned Flags;
146
147 // StringMap can only store DefaultConstructible objects
148 GlobalOptionDescription() : OptionDescription(), Flags(0)
149 {}
150
151 GlobalOptionDescription (OptionType::OptionType t, const std::string& n)
152 : OptionDescription(t, n), Help(DefaultHelpString), Flags(0)
153 {}
154
155 bool isRequired() const {
156 return Flags & GlobalOptionDescriptionFlags::Required;
157 }
158 void setRequired() {
159 Flags |= GlobalOptionDescriptionFlags::Required;
160 }
161
162 // Merge two option descriptions
163 void Merge (const GlobalOptionDescription& other)
164 {
165 if (other.Type != Type)
166 throw "Conflicting definitions for the option " + Name + "!";
167
168 if (Help.empty() && !other.Help.empty())
169 Help = other.Help;
170 else if (!Help.empty() && !other.Help.empty())
171 cerr << "Warning: more than one help string defined for option "
172 + Name + "\n";
173
174 Flags |= other.Flags;
175 }
176};
177
178// A GlobalOptionDescription array
179// + some flags affecting generation of option declarations
180struct GlobalOptionDescriptions {
181 typedef StringMap<GlobalOptionDescription> container_type;
182 typedef container_type::const_iterator const_iterator;
183
184 // A list of GlobalOptionDescriptions
185 container_type Descriptions;
186 // Should the emitter generate a "cl::sink" option?
187 bool HasSink;
188
189 // Support for STL-style iteration
190 const_iterator begin() const { return Descriptions.begin(); }
191 const_iterator end() const { return Descriptions.end(); }
192};
193
194
195// Tool-local option description
196
197// Properties without arguments are implemented as flags
198namespace ToolOptionDescriptionFlags {
199 enum ToolOptionDescriptionFlags { StopCompilation = 0x1,
200 Forward = 0x2, UnpackValues = 0x4};
201}
202namespace OptionPropertyType {
203 enum OptionPropertyType { AppendCmd };
204}
205
206typedef std::pair<OptionPropertyType::OptionPropertyType, std::string>
207OptionProperty;
208typedef SmallVector<OptionProperty, 4> OptionPropertyList;
209
210struct ToolOptionDescription : public OptionDescription {
211 unsigned Flags;
212 OptionPropertyList Props;
213
214 // StringMap can only store DefaultConstructible objects
Mikhail Glushenkov3ee84022008-03-27 09:53:47 +0000215 ToolOptionDescription() : OptionDescription(), Flags(0) {}
Anton Korobeynikovac67b7e2008-03-23 08:57:20 +0000216
217 ToolOptionDescription (OptionType::OptionType t, const std::string& n)
218 : OptionDescription(t, n)
219 {}
220
221 // Various boolean properties
222 bool isStopCompilation() const {
223 return Flags & ToolOptionDescriptionFlags::StopCompilation;
224 }
225 void setStopCompilation() {
226 Flags |= ToolOptionDescriptionFlags::StopCompilation;
227 }
228
229 bool isForward() const {
230 return Flags & ToolOptionDescriptionFlags::Forward;
231 }
232 void setForward() {
233 Flags |= ToolOptionDescriptionFlags::Forward;
234 }
235
236 bool isUnpackValues() const {
237 return Flags & ToolOptionDescriptionFlags::UnpackValues;
238 }
239 void setUnpackValues() {
240 Flags |= ToolOptionDescriptionFlags::UnpackValues;
241 }
242
243 void AddProperty (OptionPropertyType::OptionPropertyType t,
244 const std::string& val)
245 {
246 Props.push_back(std::make_pair(t, val));
247 }
248};
249
250typedef StringMap<ToolOptionDescription> ToolOptionDescriptions;
251
252// Tool information record
253
254namespace ToolFlags {
255 enum ToolFlags { Join = 0x1, Sink = 0x2 };
256}
257
258struct ToolProperties : public RefCountedBase<ToolProperties> {
259 std::string Name;
260 StrVector CmdLine;
261 std::string InLanguage;
262 std::string OutLanguage;
263 std::string OutputSuffix;
264 unsigned Flags;
265 ToolOptionDescriptions OptDescs;
266
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; }
272
273 // Default ctor here is needed because StringMap can only store
274 // DefaultConstructible objects
275 ToolProperties() {}
276 ToolProperties (const std::string& n) : Name(n) {}
277};
278
279
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)
283typedef std::vector<IntrusiveRefCntPtr<ToolProperties> > ToolPropertiesList;
284
285
286// Function object for iterating over a list of tool property records
287class CollectProperties {
288private:
289
290 /// Implementation details
291
292 // "Property handler" - a function that extracts information
293 // about a given tool property from its DAG representation
294 typedef void (CollectProperties::*PropertyHandler)(DagInit*);
295
296 // Map from property names -> property handlers
297 typedef StringMap<PropertyHandler> PropertyHandlerMap;
298
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 &);
303
304 // Map from option property names -> option property handlers
305 typedef StringMap<OptionPropertyHandler> OptionPropertyHandlerMap;
306
307 // Static maps from strings to CollectProperties methods("handlers")
308 static PropertyHandlerMap propertyHandlers_;
309 static OptionPropertyHandlerMap optionPropertyHandlers_;
310 static bool staticMembersInitialized_;
311
312
313 /// This is where the information is stored
314
315 // Current Tool properties
316 ToolProperties& toolProps_;
317 // OptionDescriptions table(used to register options globally)
318 GlobalOptionDescriptions& optDescs_;
319
320public:
321
322 explicit CollectProperties (ToolProperties& p, GlobalOptionDescriptions& d)
323 : toolProps_(p), optDescs_(d)
324 {
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;
341
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;
351
352 staticMembersInitialized_ = true;
353 }
354 }
355
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);
363
364 if (method != propertyHandlers_.end()) {
365 PropertyHandler h = method->second;
366 (this->*h)(&d);
367 }
368 else {
369 throw "Unknown tool property: " + property_name + "!";
370 }
371 }
372
373private:
374
375 /// Property handlers --
376 /// Functions that extract information about tool properties from
377 /// DAG representation.
378
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!");
384 }
385
386 void onInLanguage (DagInit* d) {
387 checkNumberOfArguments(d, 1);
388 toolProps_.InLanguage = InitPtrToString(d->getArg(0));
389 }
390
391 void onJoin (DagInit* d) {
392 checkNumberOfArguments(d, 0);
393 toolProps_.setJoin();
394 }
395
396 void onOutLanguage (DagInit* d) {
397 checkNumberOfArguments(d, 1);
398 toolProps_.OutLanguage = InitPtrToString(d->getArg(0));
399 }
400
401 void onOutputSuffix (DagInit* d) {
402 checkNumberOfArguments(d, 1);
403 toolProps_.OutputSuffix = InitPtrToString(d->getArg(0));
404 }
405
406 void onSink (DagInit* d) {
407 checkNumberOfArguments(d, 0);
408 optDescs_.HasSink = true;
409 toolProps_.setSink();
410 }
411
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); }
417
418 /// Option property handlers --
419 /// Methods that handle properties that are common for all types of
420 /// options (like append_cmd, stop_compilation)
421
422 void onAppendCmd (DagInit* d, GlobalOptionDescription& o) {
423 checkNumberOfArguments(d, 1);
424 std::string const& cmd = InitPtrToString(d->getArg(0));
425
426 toolProps_.OptDescs[o.Name].AddProperty(OptionPropertyType::AppendCmd, cmd);
427 }
428
429 void onForward (DagInit* d, GlobalOptionDescription& o) {
430 checkNumberOfArguments(d, 0);
431 toolProps_.OptDescs[o.Name].setForward();
432 }
433
434 void onHelp (DagInit* d, GlobalOptionDescription& o) {
435 checkNumberOfArguments(d, 1);
436 const std::string& help_message = InitPtrToString(d->getArg(0));
437
438 o.Help = help_message;
439 }
440
441 void onRequired (DagInit* d, GlobalOptionDescription& o) {
442 checkNumberOfArguments(d, 0);
443 o.setRequired();
444 }
445
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();
451 }
452
453 void onUnpackValues (DagInit* d, GlobalOptionDescription& o) {
454 checkNumberOfArguments(d, 0);
455 toolProps_.OptDescs[o.Name].setUnpackValues();
456 }
457
458 /// Helper functions
459
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));
464
465 GlobalOptionDescription o(t, name);
466 toolProps_.OptDescs[name].Type = t;
467 toolProps_.OptDescs[name].Name = name;
468 processOptionProperties(d, o);
469 insertDescription(o);
470 }
471
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!";
478 }
479
480 // Insert new GlobalOptionDescription into GlobalOptionDescriptions list
481 void insertDescription (const GlobalOptionDescription& o)
482 {
483 if (optDescs_.Descriptions.count(o.Name)) {
484 GlobalOptionDescription& D = optDescs_.Descriptions[o.Name];
485 D.Merge(o);
486 }
487 else {
488 optDescs_.Descriptions[o.Name] = o;
489 }
490 }
491
492 // Go through the list of option properties and call a corresponding
493 // handler for each.
494 //
495 // Parameters:
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);
501
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);
509
510 if (method != optionPropertyHandlers_.end()) {
511 OptionPropertyHandler h = method->second;
512 (this->*h)(&option_property, o);
513 }
514 else {
515 throw "Unknown option property: " + option_property_name + "!";
516 }
517 }
518 }
519};
520
521// Static members of CollectProperties
522CollectProperties::PropertyHandlerMap
523CollectProperties::propertyHandlers_;
524
525CollectProperties::OptionPropertyHandlerMap
526CollectProperties::optionPropertyHandlers_;
527
528bool CollectProperties::staticMembersInitialized_ = false;
529
530
531// Gather information from the parsed TableGen data
532// (Basically a wrapper for CollectProperties)
533void CollectToolProperties (RecordVector::const_iterator B,
534 RecordVector::const_iterator E,
535 ToolPropertiesList& TPList,
536 GlobalOptionDescriptions& OptDescs)
537{
538 // Iterate over a properties list of every Tool definition
539 for (;B!=E;++B) {
540 RecordVector::value_type T = *B;
541 ListInit* PropList = T->getValueAsListInit("properties");
542 if (!PropList)
543 throw std::string("Tool has no property list!");
544
545 IntrusiveRefCntPtr<ToolProperties>
546 ToolProps(new ToolProperties(T->getName()));
547
548 std::for_each(PropList->begin(), PropList->end(),
549 CollectProperties(*ToolProps, OptDescs));
550 TPList.push_back(ToolProps);
551 }
552}
553
554// Used by EmitGenerateActionMethod
555void EmitOptionPropertyHandlingCode (const ToolProperties& P,
556 const ToolOptionDescription& D,
557 std::ostream& O)
558{
559 // if clause
560 O << Indent2 << "if (";
561 if (D.Type == OptionType::Switch)
562 O << D.GenVariableName();
563 else
564 O << '!' << D.GenVariableName() << ".empty()";
565
566 O <<") {\n";
567
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;
572
573 switch (val.first) {
574 // (append_cmd cmd) property
575 case OptionPropertyType::AppendCmd:
576 O << Indent3 << "vec.push_back(\"" << val.second << "\");\n";
577 break;
578 // Other properties with argument
579 default:
580 break;
581 }
582 }
583
584 // Handle flags
585
586 // (forward) property
587 if (D.isForward()) {
588 switch (D.Type) {
589 case OptionType::Switch:
590 O << Indent3 << "vec.push_back(\"-" << D.Name << "\");\n";
591 break;
592 case OptionType::Parameter:
593 O << Indent3 << "vec.push_back(\"-" << D.Name << "\");\n";
594 O << Indent3 << "vec.push_back(" << D.GenVariableName() << ");\n";
595 break;
596 case OptionType::Prefix:
597 O << Indent3 << "vec.push_back(\"-" << D.Name << "\" + "
598 << D.GenVariableName() << ");\n";
599 break;
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 << "\" + "
605 << "*B);\n";
606 break;
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"
614 << Indent3 << "}\n";
615 break;
616 }
617 }
618
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";
627 }
628 else if (D.Type == OptionType::Prefix || D.Type == OptionType::Parameter){
629 O << Indent3 << "UnpackValues("
630 << D.GenVariableName() << ", vec);\n";
631 }
632 else {
633 // TOFIX: move this to the type-checking phase
634 throw std::string("Switches can't have unpack_values property!");
635 }
636 }
637
638 // close if clause
639 O << Indent2 << "}\n";
640}
641
642// Emite one of two versions of GenerateAction method
643void EmitGenerateActionMethod (const ToolProperties& P, int V, std::ostream& O)
644{
645 assert(V==1 || V==2);
646 if (V==1)
647 O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n";
648 else
649 O << Indent1 << "Action GenerateAction(const sys::Path& inFile,\n";
650
651 O << Indent2 << "const sys::Path& outFile) const\n"
652 << Indent1 << "{\n"
653 << Indent2 << "std::vector<std::string> vec;\n";
654
655 // Parse CmdLine tool property
656 StrVector::const_iterator I = P.CmdLine.begin();
657 ++I;
658 for (StrVector::const_iterator E = P.CmdLine.end(); I != E; ++I) {
659 const std::string& cmd = *I;
660 O << Indent2;
661 if (cmd == "$INFILE") {
662 if (V==1)
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";
667 else
668 O << "vec.push_back(inFile.toString());\n";
669 }
670 else if (cmd == "$OUTFILE") {
671 O << "vec.push_back(outFile.toString());\n";
672 }
673 else {
674 O << "vec.push_back(\"" << cmd << "\");\n";
675 }
676 }
677
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);
683 }
684
685 // Handle Sink property
686 if (P.isSink()) {
687 O << Indent2 << "if (!" << SinkOptionName << ".empty()) {\n"
688 << Indent3 << "vec.insert(vec.end(), "
689 << SinkOptionName << ".begin(), " << SinkOptionName << ".end());\n"
690 << Indent2 << "}\n";
691 }
692
693 O << Indent2 << "return Action(\"" << P.CmdLine.at(0) << "\", vec);\n"
694 << Indent1 << "}\n\n";
695}
696
697// Emit GenerateAction methods for Tool classes
698void EmitGenerateActionMethods (const ToolProperties& P, std::ostream& O) {
699
700 if (!P.isJoin())
701 O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n"
702 << Indent2 << "const llvm::sys::Path& outFile) const\n"
703 << Indent1 << "{\n"
704 << Indent2 << "throw std::runtime_error(\"" << P.Name
705 << " is not a Join tool!\");\n"
706 << Indent1 << "}\n\n";
707 else
708 EmitGenerateActionMethod(P, 1, O);
709
710 EmitGenerateActionMethod(P, 2, O);
711}
712
713// Emit IsLast() method for Tool classes
714void EmitIsLastMethod (const ToolProperties& P, std::ostream& O) {
715 O << Indent1 << "bool IsLast() const {\n"
716 << Indent2 << "bool last = false;\n";
717
718 for (ToolOptionDescriptions::const_iterator B = P.OptDescs.begin(),
719 E = P.OptDescs.end(); B != E; ++B) {
720 const ToolOptionDescription& val = B->second;
721
722 if (val.isStopCompilation())
723 O << Indent2
724 << "if (" << val.GenVariableName()
725 << ")\n" << Indent3 << "last = true;\n";
726 }
727
728 O << Indent2 << "return last;\n"
729 << Indent1 << "}\n\n";
730}
731
732// Emit static [Input,Output]Language() methods for Tool classes
733void 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";
737
738 O << Indent1 << "std::string OutputLanguage() const {\n"
739 << Indent2 << "return \"" << P.OutLanguage << "\";\n"
740 << Indent1 << "}\n\n";
741}
742
743// Emit static [Input,Output]Language() methods for Tool classes
744void 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";
748}
749
750// Emit static Name() method for Tool classes
751void 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";
755}
756
757// Emit static Name() method for Tool classes
758void EmitIsJoinMethod (const ToolProperties& P, std::ostream& O) {
759 O << Indent1 << "bool IsJoin() const {\n";
760 if (P.isJoin())
761 O << Indent2 << "return true;\n";
762 else
763 O << Indent2 << "return false;\n";
764 O << Indent1 << "}\n\n";
765}
766
767// Emit a Tool class definition
768void EmitToolClassDefinition (const ToolProperties& P, std::ostream& O) {
769 // Header
770 O << "class " << P.Name << " : public Tool {\n"
771 << "public:\n";
772
773 EmitNameMethod(P, O);
774 EmitInOutLanguageMethods(P, O);
775 EmitOutputSuffixMethod(P, O);
776 EmitIsJoinMethod(P, O);
777 EmitGenerateActionMethods(P, O);
778 EmitIsLastMethod(P, O);
779
780 // Close class definition
781 O << "};\n\n";
782}
783
784// Iterate over a list of option descriptions and emit registration code
785void EmitOptionDescriptions (const GlobalOptionDescriptions& descs,
786 std::ostream& O)
787{
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;
792
793 O << val.GenTypeDeclaration() << ' '
794 << val.GenVariableName()
795 << "(\"" << val.Name << '\"';
796
797 if (val.Type == OptionType::Prefix || val.Type == OptionType::PrefixList)
798 O << ", cl::Prefix";
799
800 if (val.isRequired()) {
801 switch (val.Type) {
802 case OptionType::PrefixList:
803 case OptionType::ParameterList:
804 O << ", cl::OneOrMore";
805 break;
806 default:
807 O << ", cl::Required";
808 }
809 }
810
811 O << ", cl::desc(\"" << val.Help << "\"));\n";
812 }
813
814 if (descs.HasSink)
815 O << "cl::list<std::string> " << SinkOptionName << "(cl::Sink);\n";
816
817 O << '\n';
818}
819
820void EmitPopulateLanguageMap (const RecordKeeper& Records, std::ostream& O)
821{
822 // Get the relevant field out of RecordKeeper
823 Record* LangMapRecord = Records.getDef("LanguageMap");
824 if (!LangMapRecord)
825 throw std::string("Language map definition not found!");
826
827 ListInit* LangsToSuffixesList = LangMapRecord->getValueAsListInit("map");
828 if (!LangsToSuffixesList)
829 throw std::string("Error in the language map definition!");
830
831 // Generate code
832 O << "void llvmcc::PopulateLanguageMap(LanguageMap& language_map) {\n";
833
834 for (unsigned i = 0; i < LangsToSuffixesList->size(); ++i) {
835 Record* LangToSuffixes = LangsToSuffixesList->getElementAsRecord(i);
836
837 const std::string& Lang = LangToSuffixes->getValueAsString("lang");
838 const ListInit* Suffixes = LangToSuffixes->getValueAsListInit("suffixes");
839
840 for (unsigned i = 0; i < Suffixes->size(); ++i)
841 O << Indent1 << "language_map[\""
842 << InitPtrToString(Suffixes->getElement(i))
843 << "\"] = \"" << Lang << "\";\n";
844 }
845
846 O << "}\n\n";
847}
848
849void EmitPopulateCompilationGraph (const RecordKeeper& Records,
850 StringMap<std::string>& ToolToLang,
851 std::ostream& O)
852{
853 // Get the relevant field out of RecordKeeper
854 Record* ToolChains = Records.getDef("ToolChains");
855 if (!ToolChains)
856 throw std::string("No ToolChains specification found!");
857 ListInit* chains = ToolChains->getValueAsListInit("chains");
858 if (!chains)
859 throw std::string("Error in toolchain list definition!");
860
861 // Generate code
862 O << "void llvmcc::PopulateCompilationGraph(CompilationGraph& G) {\n"
863 << Indent1 << "PopulateLanguageMap(G.ExtsToLangs);\n"
864 << Indent1 << "std::vector<IntrusiveRefCntPtr<Tool> > vec;\n\n";
865
866 for (unsigned i = 0; i < chains->size(); ++i) {
867 Record* ToolChain = chains->getElementAsRecord(i);
868 ListInit* Tools = ToolChain->getValueAsListInit("tools");
869
870 // Get name of the first tool in the list
871 const std::string& firstTool =
872 dynamic_cast<DefInit&>(**Tools->begin()).getDef()->getName();
873
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";
879 }
880 O << Indent1 << "G.ToolChains[\"" << ToolToLang[firstTool]
881 << "\"] = vec;\n";
882 O << Indent1 << "vec.clear();\n\n";
883 }
884
885 O << "}\n\n";
886}
887
888void FillInToolToLang (const ToolPropertiesList& T,
889 StringMap<std::string>& M) {
890 for (ToolPropertiesList::const_iterator B = T.begin(), E = T.end();
891 B != E; ++B) {
892 const ToolProperties& P = *(*B);
893 M[P.Name] = P.InLanguage;
894 }
895}
896
897// End of anonymous namespace
898}
899
900// Back-end entry point
901void LLVMCCConfigurationEmitter::run (std::ostream &O) {
902 // Emit file header
903 EmitSourceFileHeader("LLVMCC Configuration Library", O);
904
905 // Get a list of all defined Tools
906 RecordVector Tools = Records.getAllDerivedDefinitions("Tool");
907 if (Tools.empty())
908 throw std::string("No tool definitions found!");
909
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);
914
915 // Emit global option registration code
916 EmitOptionDescriptions(opt_descs, O);
917
918 // Emit PopulateLanguageMap function
919 // (a language map maps from file extensions to language names)
920 EmitPopulateLanguageMap(Records, O);
921
922 // Emit Tool classes
923 for (ToolPropertiesList::const_iterator B = tool_props.begin(),
924 E = tool_props.end(); B!=E; ++B)
925 EmitToolClassDefinition(*(*B), O);
926
927 // Fill in table that maps tool names to languages
928 StringMap<std::string> ToolToLang;
929 FillInToolToLang(tool_props, ToolToLang);
930
931 // Emit PopulateCompilationGraph function
932 EmitPopulateCompilationGraph(Records, ToolToLang, O);
933
934 // EOF
935}