X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FLLVMCConfigurationEmitter.cpp;h=7330dd3fc592737fa5d6d4fb5fb6e8e37390bc21;hb=21607fa63c3294f7417834133d9482141e19200e;hp=aaa10992d99e357ab9a0d0e75c2954a4cad47459;hpb=895820da243713e78ff3ee66ba54c4db4ee121ac;p=oota-llvm.git diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp index aaa10992d99..7330dd3fc59 100644 --- a/utils/TableGen/LLVMCConfigurationEmitter.cpp +++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp @@ -38,16 +38,16 @@ typedef std::vector StrVector; //===----------------------------------------------------------------------===// /// Constants -// Indentation strings +// Indentation strings. const char * Indent1 = " "; const char * Indent2 = " "; const char * Indent3 = " "; const char * Indent4 = " "; -// Default help string +// Default help string. const char * DefaultHelpString = "NO HELP MESSAGE PROVIDED"; -// Name for the "sink" option +// Name for the "sink" option. const char * SinkOptionName = "AutoGeneratedSinkOption"; //===----------------------------------------------------------------------===// @@ -58,8 +58,19 @@ std::string InitPtrToString(Init* ptr) { return val.getValue(); } -// Ensure that the number of args in d is <= min_arguments, -// throw exception otherwise +int InitPtrToInt(Init* ptr) { + IntInit& val = dynamic_cast(*ptr); + return val.getValue(); +} + +const DagInit& InitPtrToDagInitRef(Init* ptr) { + DagInit& val = dynamic_cast(*ptr); + return val; +} + + +// checkNumberOfArguments - Ensure that the number of args in d is +// less than or equal to min_arguments, otherwise throw an exception . void checkNumberOfArguments (const DagInit* d, unsigned min_arguments) { if (d->getNumArgs() < min_arguments) throw "Property " + d->getOperator()->getAsString() @@ -100,8 +111,7 @@ bool IsListOptionType (OptionType::OptionType t) { // the option registration code, while ToolOptionDescriptions are used // to generate tool-specific code. -// Base class for option descriptions - +/// OptionDescription - Base class for option descriptions. struct OptionDescription { OptionType::OptionType Type; std::string Name; @@ -143,7 +153,7 @@ struct OptionDescription { }; -// Global option description +// Global option description. namespace GlobalOptionDescriptionFlags { enum GlobalOptionDescriptionFlags { Required = 0x1 }; @@ -153,8 +163,8 @@ struct GlobalOptionDescription : public OptionDescription { std::string Help; unsigned Flags; - // We need t provide a default constructor since - // StringMap can only store DefaultConstructible objects + // We need to provide a default constructor because + // StringMap can only store DefaultConstructible objects. GlobalOptionDescription() : OptionDescription(), Flags(0) {} @@ -169,31 +179,33 @@ struct GlobalOptionDescription : public OptionDescription { Flags |= GlobalOptionDescriptionFlags::Required; } - // Merge two option descriptions + /// Merge - Merge two option descriptions. void Merge (const GlobalOptionDescription& other) { if (other.Type != Type) throw "Conflicting definitions for the option " + Name + "!"; - if (Help.empty() && !other.Help.empty()) + if (Help == DefaultHelpString) Help = other.Help; - else if (!Help.empty() && !other.Help.empty()) - cerr << "Warning: more than one help string defined for option " + else if (other.Help != DefaultHelpString) { + llvm::cerr << "Warning: more than one help string defined for option " + Name + "\n"; + } Flags |= other.Flags; } }; -// A GlobalOptionDescription array -// + some flags affecting generation of option declarations +/// GlobalOptionDescriptions - A GlobalOptionDescription array +/// together with some flags affecting generation of option +/// declarations. struct GlobalOptionDescriptions { typedef StringMap container_type; typedef container_type::const_iterator const_iterator; - // A list of GlobalOptionDescriptions + /// Descriptions - A list of GlobalOptionDescriptions. container_type Descriptions; - // Should the emitter generate a "cl::sink" option? + /// HasSink - Should the emitter generate a "cl::sink" option? bool HasSink; const GlobalOptionDescription& FindOption(const std::string& OptName) const { @@ -210,9 +222,9 @@ struct GlobalOptionDescriptions { }; -// Tool-local option description +// Tool-local option description. -// Properties without arguments are implemented as flags +// Properties without arguments are implemented as flags. namespace ToolOptionDescriptionFlags { enum ToolOptionDescriptionFlags { StopCompilation = 0x1, Forward = 0x2, UnpackValues = 0x4}; @@ -290,36 +302,39 @@ struct ToolProperties : public RefCountedBase { // Default ctor here is needed because StringMap can only store // DefaultConstructible objects - ToolProperties() {} - ToolProperties (const std::string& n) : Name(n) {} + ToolProperties() : Flags(0) {} + ToolProperties (const std::string& n) : Name(n), Flags(0) {} }; -// A list of Tool information records -// IntrusiveRefCntPtrs are used because StringMap has no copy constructor -// (and we want to avoid copying ToolProperties anyway) +/// ToolPropertiesList - A list of Tool information records +/// IntrusiveRefCntPtrs are used here because StringMap has no copy +/// constructor (and we want to avoid copying ToolProperties anyway). typedef std::vector > ToolPropertiesList; -// Function object for iterating over a list of tool property records +/// CollectProperties - Function object for iterating over a list of +/// tool property records. class CollectProperties { private: /// Implementation details - // "Property handler" - a function that extracts information - // about a given tool property from its DAG representation - typedef void (CollectProperties::*PropertyHandler)(DagInit*); + /// PropertyHandler - a function that extracts information + /// about a given tool property from its DAG representation + typedef void (CollectProperties::*PropertyHandler)(const DagInit*); - // Map from property names -> property handlers + /// PropertyHandlerMap - A map from property names to property + /// handlers. typedef StringMap PropertyHandlerMap; - // "Option property handler" - a function that extracts information - // about a given option property from its DAG representation - typedef void (CollectProperties::* - OptionPropertyHandler)(DagInit*, GlobalOptionDescription &); + /// OptionPropertyHandler - a function that extracts information + /// about a given option property from its DAG representation. + typedef void (CollectProperties::* OptionPropertyHandler) + (const DagInit*, GlobalOptionDescription &); - // Map from option property names -> option property handlers + /// OptionPropertyHandlerMap - A map from option property names to + /// option property handlers typedef StringMap OptionPropertyHandlerMap; // Static maps from strings to CollectProperties methods("handlers") @@ -330,9 +345,10 @@ private: /// This is where the information is stored - // Current Tool properties + /// toolProps_ - Properties of the current Tool. ToolProperties& toolProps_; - // OptionDescriptions table(used to register options globally) + /// optDescs_ - OptionDescriptions table (used to register options + /// globally). GlobalOptionDescriptions& optDescs_; public: @@ -371,10 +387,10 @@ public: } } - // Gets called for every tool property; - // Just forwards to the corresponding property handler. + /// operator() - Gets called for every tool property; Just forwards + /// to the corresponding property handler. void operator() (Init* i) { - DagInit& d = dynamic_cast(*i); + const DagInit& d = InitPtrToDagInitRef(i); const std::string& property_name = d.getOperator()->getAsString(); PropertyHandlerMap::iterator method = propertyHandlers_.find(property_name); @@ -394,81 +410,95 @@ private: /// Functions that extract information about tool properties from /// DAG representation. - void onCmdLine (DagInit* d) { + void onCmdLine (const DagInit* d) { checkNumberOfArguments(d, 1); SplitString(InitPtrToString(d->getArg(0)), toolProps_.CmdLine); if (toolProps_.CmdLine.empty()) throw "Tool " + toolProps_.Name + " has empty command line!"; } - void onInLanguage (DagInit* d) { + void onInLanguage (const DagInit* d) { checkNumberOfArguments(d, 1); toolProps_.InLanguage = InitPtrToString(d->getArg(0)); } - void onJoin (DagInit* d) { + void onJoin (const DagInit* d) { checkNumberOfArguments(d, 0); toolProps_.setJoin(); } - void onOutLanguage (DagInit* d) { + void onOutLanguage (const DagInit* d) { checkNumberOfArguments(d, 1); toolProps_.OutLanguage = InitPtrToString(d->getArg(0)); } - void onOutputSuffix (DagInit* d) { + void onOutputSuffix (const DagInit* d) { checkNumberOfArguments(d, 1); toolProps_.OutputSuffix = InitPtrToString(d->getArg(0)); } - void onSink (DagInit* d) { + void onSink (const DagInit* d) { checkNumberOfArguments(d, 0); optDescs_.HasSink = true; toolProps_.setSink(); } - void onSwitch (DagInit* d) { addOption(d, OptionType::Switch); } - void onParameter (DagInit* d) { addOption(d, OptionType::Parameter); } - void onParameterList (DagInit* d) { addOption(d, OptionType::ParameterList); } - void onPrefix (DagInit* d) { addOption(d, OptionType::Prefix); } - void onPrefixList (DagInit* d) { addOption(d, OptionType::PrefixList); } + void onSwitch (const DagInit* d) { + addOption(d, OptionType::Switch); + } + + void onParameter (const DagInit* d) { + addOption(d, OptionType::Parameter); + } + + void onParameterList (const DagInit* d) { + addOption(d, OptionType::ParameterList); + } + + void onPrefix (const DagInit* d) { + addOption(d, OptionType::Prefix); + } + + void onPrefixList (const DagInit* d) { + addOption(d, OptionType::PrefixList); + } /// Option property handlers -- /// Methods that handle properties that are common for all types of /// options (like append_cmd, stop_compilation) - void onAppendCmd (DagInit* d, GlobalOptionDescription& o) { + void onAppendCmd (const DagInit* d, GlobalOptionDescription& o) { checkNumberOfArguments(d, 1); std::string const& cmd = InitPtrToString(d->getArg(0)); toolProps_.OptDescs[o.Name].AddProperty(OptionPropertyType::AppendCmd, cmd); } - void onForward (DagInit* d, GlobalOptionDescription& o) { + void onForward (const DagInit* d, GlobalOptionDescription& o) { checkNumberOfArguments(d, 0); toolProps_.OptDescs[o.Name].setForward(); } - void onHelp (DagInit* d, GlobalOptionDescription& o) { + void onHelp (const DagInit* d, GlobalOptionDescription& o) { checkNumberOfArguments(d, 1); const std::string& help_message = InitPtrToString(d->getArg(0)); o.Help = help_message; } - void onRequired (DagInit* d, GlobalOptionDescription& o) { + void onRequired (const DagInit* d, GlobalOptionDescription& o) { checkNumberOfArguments(d, 0); o.setRequired(); } - void onStopCompilation (DagInit* d, GlobalOptionDescription& o) { + void onStopCompilation (const DagInit* d, GlobalOptionDescription& o) { checkNumberOfArguments(d, 0); if (o.Type != OptionType::Switch) throw std::string("Only options of type Switch can stop compilation!"); toolProps_.OptDescs[o.Name].setStopCompilation(); } - void onUnpackValues (DagInit* d, GlobalOptionDescription& o) { + void onUnpackValues (const DagInit* d, GlobalOptionDescription& o) { checkNumberOfArguments(d, 0); toolProps_.OptDescs[o.Name].setUnpackValues(); } @@ -476,7 +506,7 @@ private: /// Helper functions // Add an option of type t - void addOption (DagInit* d, OptionType::OptionType t) { + void addOption (const DagInit* d, OptionType::OptionType t) { checkNumberOfArguments(d, 2); const std::string& name = InitPtrToString(d->getArg(0)); @@ -499,19 +529,19 @@ private: } } - // Go through the list of option properties and call a corresponding - // handler for each. - // - // Parameters: - // name - option name - // d - option property list - void processOptionProperties (DagInit* d, GlobalOptionDescription& o) { + /// processOptionProperties - Go through the list of option + /// properties and call a corresponding handler for each. + /// + /// Parameters: + /// name - option name + /// d - option property list + void processOptionProperties (const DagInit* d, GlobalOptionDescription& o) { // First argument is option name checkNumberOfArguments(d, 2); for (unsigned B = 1, E = d->getNumArgs(); B!=E; ++B) { - DagInit& option_property - = dynamic_cast(*d->getArg(B)); + const DagInit& option_property + = InitPtrToDagInitRef(d->getArg(B)); const std::string& option_property_name = option_property.getOperator()->getAsString(); OptionPropertyHandlerMap::iterator method @@ -538,8 +568,9 @@ CollectProperties::optionPropertyHandlers_; bool CollectProperties::staticMembersInitialized_ = false; -// Gather information from the parsed TableGen data -// (Basically a wrapper for CollectProperties) +/// CollectToolProperties - Gather information from the parsed +/// TableGen data (basically a wrapper for the CollectProperties +/// function object). void CollectToolProperties (RecordVector::const_iterator B, RecordVector::const_iterator E, ToolPropertiesList& TPList, @@ -559,12 +590,50 @@ void CollectToolProperties (RecordVector::const_iterator B, } } -// Used by EmitGenerateActionMethod +/// EmitForwardOptionPropertyHandlingCode - Helper function used to +/// implement EmitOptionPropertyHandlingCode(). Emits code for +/// handling the (forward) option property. +void EmitForwardOptionPropertyHandlingCode (const ToolOptionDescription& D, + std::ostream& O) { + switch (D.Type) { + case OptionType::Switch: + O << Indent3 << "vec.push_back(\"-" << D.Name << "\");\n"; + break; + case OptionType::Parameter: + O << Indent3 << "vec.push_back(\"-" << D.Name << "\");\n"; + O << Indent3 << "vec.push_back(" << D.GenVariableName() << ");\n"; + break; + case OptionType::Prefix: + O << Indent3 << "vec.push_back(\"-" << D.Name << "\" + " + << D.GenVariableName() << ");\n"; + break; + case OptionType::PrefixList: + O << Indent3 << "for (" << D.GenTypeDeclaration() + << "::iterator B = " << D.GenVariableName() << ".begin(),\n" + << Indent3 << "E = " << D.GenVariableName() << ".end(); B != E; ++B)\n" + << Indent4 << "vec.push_back(\"-" << D.Name << "\" + " + << "*B);\n"; + break; + case OptionType::ParameterList: + O << Indent3 << "for (" << D.GenTypeDeclaration() + << "::iterator B = " << D.GenVariableName() << ".begin(),\n" + << Indent3 << "E = " << D.GenVariableName() + << ".end() ; B != E; ++B) {\n" + << Indent4 << "vec.push_back(\"-" << D.Name << "\");\n" + << Indent4 << "vec.push_back(*B);\n" + << Indent3 << "}\n"; + break; + } +} + +/// EmitOptionPropertyHandlingCode - Helper function used by +/// EmitGenerateActionMethod(). Emits code that handles option +/// properties. void EmitOptionPropertyHandlingCode (const ToolProperties& P, const ToolOptionDescription& D, std::ostream& O) { - // if clause + // Start of the if-clause. O << Indent2 << "if ("; if (D.Type == OptionType::Switch) O << D.GenVariableName(); @@ -573,7 +642,7 @@ void EmitOptionPropertyHandlingCode (const ToolProperties& P, O <<") {\n"; - // Handle option properties that take an argument + // Handle option properties that take an argument. for (OptionPropertyList::const_iterator B = D.Props.begin(), E = D.Props.end(); B!=E; ++B) { const OptionProperty& val = *B; @@ -592,37 +661,8 @@ void EmitOptionPropertyHandlingCode (const ToolProperties& P, // Handle flags // (forward) property - if (D.isForward()) { - switch (D.Type) { - case OptionType::Switch: - O << Indent3 << "vec.push_back(\"-" << D.Name << "\");\n"; - break; - case OptionType::Parameter: - O << Indent3 << "vec.push_back(\"-" << D.Name << "\");\n"; - O << Indent3 << "vec.push_back(" << D.GenVariableName() << ");\n"; - break; - case OptionType::Prefix: - O << Indent3 << "vec.push_back(\"-" << D.Name << "\" + " - << D.GenVariableName() << ");\n"; - break; - case OptionType::PrefixList: - O << Indent3 << "for (" << D.GenTypeDeclaration() - << "::iterator B = " << D.GenVariableName() << ".begin(),\n" - << Indent3 << "E = " << D.GenVariableName() << ".end(); B != E; ++B)\n" - << Indent4 << "vec.push_back(\"-" << D.Name << "\" + " - << "*B);\n"; - break; - case OptionType::ParameterList: - O << Indent3 << "for (" << D.GenTypeDeclaration() - << "::iterator B = " << D.GenVariableName() << ".begin(),\n" - << Indent3 << "E = " << D.GenVariableName() - << ".end() ; B != E; ++B) {\n" - << Indent4 << "vec.push_back(\"-" << D.Name << "\");\n" - << Indent4 << "vec.push_back(*B);\n" - << Indent3 << "}\n"; - break; - } - } + if (D.isForward()) + HandleForwardPropertyy(O); // (unpack_values) property if (D.isUnpackValues()) { @@ -631,11 +671,11 @@ void EmitOptionPropertyHandlingCode (const ToolProperties& P, << "::iterator B = " << D.GenVariableName() << ".begin(),\n" << Indent3 << "E = " << D.GenVariableName() << ".end(); B != E; ++B)\n" - << Indent4 << "Tool::UnpackValues(*B, vec);\n"; + << Indent4 << "llvm::SplitString(*B, vec, \",\");\n"; } else if (D.Type == OptionType::Prefix || D.Type == OptionType::Parameter){ - O << Indent3 << "Tool::UnpackValues(" - << D.GenVariableName() << ", vec);\n"; + O << Indent3 << "llvm::SplitString(" + << D.GenVariableName() << ", vec, \",\");\n"; } else { // TOFIX: move this to the type-checking phase @@ -643,15 +683,15 @@ void EmitOptionPropertyHandlingCode (const ToolProperties& P, } } - // close if clause + // End of the if-clause. O << Indent2 << "}\n"; } -// Emite one of two versions of GenerateAction method -void EmitGenerateActionMethod (const ToolProperties& P, int V, std::ostream& O) +// EmitGenerateActionMethod - Emit one of two versions of the +// Tool::GenerateAction() method. +void EmitGenerateActionMethod (const ToolProperties& P, bool V, std::ostream& O) { - assert(V==1 || V==2); - if (V==1) + if (V) O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n"; else O << Indent1 << "Action GenerateAction(const sys::Path& inFile,\n"; @@ -670,7 +710,7 @@ void EmitGenerateActionMethod (const ToolProperties& P, int V, std::ostream& O) const std::string& cmd = *I; O << Indent2; if (cmd == "$INFILE") { - if (V==1) + if (V) O << "for (PathVector::const_iterator B = inFiles.begin()" << ", E = inFiles.end();\n" << Indent2 << "B != E; ++B)\n" @@ -686,14 +726,14 @@ void EmitGenerateActionMethod (const ToolProperties& P, int V, std::ostream& O) } } - // For every understood option, emit handling code + // For every understood option, emit handling code. for (ToolOptionDescriptions::const_iterator B = P.OptDescs.begin(), E = P.OptDescs.end(); B != E; ++B) { const ToolOptionDescription& val = B->second; EmitOptionPropertyHandlingCode(P, val, O); } - // Handle Sink property + // Handle the Sink property. if (P.isSink()) { O << Indent2 << "if (!" << SinkOptionName << ".empty()) {\n" << Indent3 << "vec.insert(vec.end(), " @@ -705,7 +745,8 @@ void EmitGenerateActionMethod (const ToolProperties& P, int V, std::ostream& O) << Indent1 << "}\n\n"; } -// Emit GenerateAction methods for Tool classes +/// EmitGenerateActionMethods - Emit two GenerateAction() methods for +/// a given Tool class. void EmitGenerateActionMethods (const ToolProperties& P, std::ostream& O) { if (!P.isJoin()) @@ -721,7 +762,8 @@ void EmitGenerateActionMethods (const ToolProperties& P, std::ostream& O) { EmitGenerateActionMethod(P, 2, O); } -// Emit IsLast() method for Tool classes +/// EmitIsLastMethod - Emit the IsLast() method for a given Tool +/// class. void EmitIsLastMethod (const ToolProperties& P, std::ostream& O) { O << Indent1 << "bool IsLast() const {\n" << Indent2 << "bool last = false;\n"; @@ -740,7 +782,8 @@ void EmitIsLastMethod (const ToolProperties& P, std::ostream& O) { << Indent1 << "}\n\n"; } -// Emit static [Input,Output]Language() methods for Tool classes +/// EmitInOutLanguageMethods - Emit the [Input,Output]Language() +/// methods for a given Tool class. void EmitInOutLanguageMethods (const ToolProperties& P, std::ostream& O) { O << Indent1 << "const char* InputLanguage() const {\n" << Indent2 << "return \"" << P.InLanguage << "\";\n" @@ -751,21 +794,23 @@ void EmitInOutLanguageMethods (const ToolProperties& P, std::ostream& O) { << Indent1 << "}\n\n"; } -// Emit static [Input,Output]Language() methods for Tool classes +/// EmitOutputSuffixMethod - Emit the OutputSuffix() method for a +/// given Tool class. void EmitOutputSuffixMethod (const ToolProperties& P, std::ostream& O) { O << Indent1 << "const char* OutputSuffix() const {\n" << Indent2 << "return \"" << P.OutputSuffix << "\";\n" << Indent1 << "}\n\n"; } -// Emit static Name() method for Tool classes +/// EmitNameMethod - Emit the Name() method for a given Tool class. void EmitNameMethod (const ToolProperties& P, std::ostream& O) { O << Indent1 << "const char* Name() const {\n" << Indent2 << "return \"" << P.Name << "\";\n" << Indent1 << "}\n\n"; } -// Emit static Name() method for Tool classes +/// EmitIsJoinMethod - Emit the IsJoin() method for a given Tool +/// class. void EmitIsJoinMethod (const ToolProperties& P, std::ostream& O) { O << Indent1 << "bool IsJoin() const {\n"; if (P.isJoin()) @@ -775,7 +820,7 @@ void EmitIsJoinMethod (const ToolProperties& P, std::ostream& O) { O << Indent1 << "}\n\n"; } -// Emit a Tool class definition +/// EmitToolClassDefinition - Emit a Tool class definition. void EmitToolClassDefinition (const ToolProperties& P, std::ostream& O) { if(P.Name == "root") @@ -800,7 +845,8 @@ void EmitToolClassDefinition (const ToolProperties& P, std::ostream& O) { O << "};\n\n"; } -// Iterate over a list of option descriptions and emit registration code +/// EmitOptionDescriptions - Iterate over a list of option +/// descriptions and emit registration code. void EmitOptionDescriptions (const GlobalOptionDescriptions& descs, std::ostream& O) { @@ -836,6 +882,7 @@ void EmitOptionDescriptions (const GlobalOptionDescriptions& descs, O << '\n'; } +/// EmitPopulateLanguageMap - Emit the PopulateLanguageMap() function. void EmitPopulateLanguageMap (const RecordKeeper& Records, std::ostream& O) { // Get the relevant field out of RecordKeeper @@ -865,8 +912,8 @@ void EmitPopulateLanguageMap (const RecordKeeper& Records, std::ostream& O) O << "}\n\n"; } -// Fills in two tables that map tool names to (input, output) languages. -// Used by the typechecker. +/// FillInToolToLang - Fills in two tables that map tool names to +/// (input, output) languages. Used by the typechecker. void FillInToolToLang (const ToolPropertiesList& TPList, StringMap& ToolToInLang, StringMap& ToolToOutLang) { @@ -878,7 +925,8 @@ void FillInToolToLang (const ToolPropertiesList& TPList, } } -// Check that all output and input language names match. +/// TypecheckGraph - Check that names for output and input languages +/// on all edges do match. // TOFIX: check for cycles. // TOFIX: check for multiple default edges. void TypecheckGraph (Record* CompilationGraph, @@ -909,20 +957,31 @@ void TypecheckGraph (Record* CompilationGraph, } } -// Helper function used by EmitEdgePropertyTest. -void EmitEdgePropertyTest1Arg(const DagInit& Prop, +/// EmitEdgePropertyTest1Arg - Helper function used by +/// EmitEdgePropertyTest. +bool EmitEdgePropertyTest1Arg(const std::string& PropName, + const DagInit& Prop, const GlobalOptionDescriptions& OptDescs, std::ostream& O) { checkNumberOfArguments(&Prop, 1); const std::string& OptName = InitPtrToString(Prop.getArg(0)); - const GlobalOptionDescription& OptDesc = OptDescs.FindOption(OptName); - if (OptDesc.Type != OptionType::Switch) - throw OptName + ": incorrect option type!"; - O << OptDesc.GenVariableName(); + if (PropName == "switch_on") { + const GlobalOptionDescription& OptDesc = OptDescs.FindOption(OptName); + if (OptDesc.Type != OptionType::Switch) + throw OptName + ": incorrect option type!"; + O << OptDesc.GenVariableName(); + return true; + } else if (PropName == "if_input_languages_contain") { + O << "InLangs.count(\"" << OptName << "\") != 0"; + return true; + } + + return false; } -// Helper function used by EmitEdgePropertyTest. -void EmitEdgePropertyTest2Args(const std::string& PropName, +/// EmitEdgePropertyTest2Args - Helper function used by +/// EmitEdgePropertyTest. +bool EmitEdgePropertyTest2Args(const std::string& PropName, const DagInit& Prop, const GlobalOptionDescriptions& OptDescs, std::ostream& O) { @@ -936,6 +995,7 @@ void EmitEdgePropertyTest2Args(const std::string& PropName, && OptDesc.Type != OptionType::Prefix) throw OptName + ": incorrect option type!"; O << OptDesc.GenVariableName() << " == \"" << OptArg << "\""; + return true; } else if (PropName == "element_in_list") { if (OptDesc.Type != OptionType::ParameterList @@ -945,27 +1005,55 @@ void EmitEdgePropertyTest2Args(const std::string& PropName, O << "std::find(" << VarName << ".begin(),\n" << Indent3 << VarName << ".end(), \"" << OptArg << "\") != " << VarName << ".end()"; + return true; } - else - throw PropName + ": unknown edge property!"; + + return false; } -// Helper function used by EmitEdgeClass. -void EmitEdgePropertyTest(const std::string& PropName, - const DagInit& Prop, +// Forward declaration. +void EmitEdgePropertyTest(const DagInit& Prop, + const GlobalOptionDescriptions& OptDescs, + std::ostream& O); + +/// EmitLogicalOperationTest - Helper function used by +/// EmitEdgePropertyTest. +void EmitLogicalOperationTest(const DagInit& Prop, const char* LogicOp, + const GlobalOptionDescriptions& OptDescs, + std::ostream& O) { + O << '('; + for (unsigned j = 0, NumArgs = Prop.getNumArgs(); j < NumArgs; ++j) { + const DagInit& InnerProp = InitPtrToDagInitRef(Prop.getArg(j)); + EmitEdgePropertyTest(InnerProp, OptDescs, O); + if (j != NumArgs - 1) + O << ")\n" << Indent3 << ' ' << LogicOp << " ("; + else + O << ')'; + } +} + +/// EmitEdgePropertyTest - Helper function used by EmitEdgeClass. +void EmitEdgePropertyTest(const DagInit& Prop, const GlobalOptionDescriptions& OptDescs, std::ostream& O) { - if (PropName == "switch_on") - EmitEdgePropertyTest1Arg(Prop, OptDescs, O); + const std::string& PropName = Prop.getOperator()->getAsString(); + + if (PropName == "and") + EmitLogicalOperationTest(Prop, "&&", OptDescs, O); + else if (PropName == "or") + EmitLogicalOperationTest(Prop, "||", OptDescs, O); + else if (EmitEdgePropertyTest1Arg(PropName, Prop, OptDescs, O)) + return; + else if (EmitEdgePropertyTest2Args(PropName, Prop, OptDescs, O)) + return; else - EmitEdgePropertyTest2Args(PropName, Prop, OptDescs, O); + throw PropName + ": unknown edge property!"; } -// Emit a single Edge* class. +/// EmitEdgeClass - Emit a single Edge# class. void EmitEdgeClass(unsigned N, const std::string& Target, ListInit* Props, const GlobalOptionDescriptions& OptDescs, std::ostream& O) { - bool IsDefault = false; // Class constructor. O << "class Edge" << N << ": public Edge {\n" @@ -973,47 +1061,33 @@ void EmitEdgeClass(unsigned N, const std::string& Target, << Indent1 << "Edge" << N << "() : Edge(\"" << Target << "\") {}\n\n" - // Function isEnabled(). - << Indent1 << "bool isEnabled() const {\n" - << Indent2 << "bool ret = false;\n"; + // Function Weight(). + << Indent1 << "unsigned Weight(const InputLanguagesSet& InLangs) const {\n" + << Indent2 << "unsigned ret = 0;\n"; + // Emit tests for every edge property. for (size_t i = 0, PropsSize = Props->size(); i < PropsSize; ++i) { - const DagInit& Prop = dynamic_cast(*Props->getElement(i)); + const DagInit& Prop = InitPtrToDagInitRef(Props->getElement(i)); const std::string& PropName = Prop.getOperator()->getAsString(); + unsigned N = 2; - if (PropName == "default") - IsDefault = true; - - O << Indent2 << "if (ret || ("; - if (PropName == "and") { - O << '('; - for (unsigned j = 0, NumArgs = Prop.getNumArgs(); j < NumArgs; ++j) { - const DagInit& InnerProp = dynamic_cast(*Prop.getArg(j)); - const std::string& InnerPropName = - InnerProp.getOperator()->getAsString(); - EmitEdgePropertyTest(InnerPropName, InnerProp, OptDescs, O); - if (j != NumArgs - 1) - O << ")\n" << Indent3 << " && ("; - else - O << ')'; - } + O << Indent2 << "if ("; + + if (PropName == "weight") { + checkNumberOfArguments(&Prop, 2); + N = InitPtrToInt(Prop.getArg(0)); + const DagInit& InnerProp = InitPtrToDagInitRef(Prop.getArg(1)); + EmitEdgePropertyTest(InnerProp, OptDescs, O); } else { - EmitEdgePropertyTest(PropName, Prop, OptDescs, O); + EmitEdgePropertyTest(Prop, OptDescs, O); } - O << "))\n" << Indent3 << "ret = true;\n"; + + O << ")\n" << Indent3 << "ret += " << N << ";\n"; } O << Indent2 << "return ret;\n" - << Indent1 << "};\n\n" - - // Function isDefault(). - << Indent1 << "bool isDefault() const { return "; - if (IsDefault) - O << "true"; - else - O << "false"; - O <<"; }\n};\n\n"; + << Indent1 << "};\n\n};\n\n"; } // Emit Edge* classes that represent graph edges. @@ -1034,6 +1108,8 @@ void EmitEdgeClasses (Record* CompilationGraph, } } +/// EmitPopulateCompilationGraph - Emit the PopulateCompilationGraph() +/// function. void EmitPopulateCompilationGraph (Record* CompilationGraph, std::ostream& O) { @@ -1082,29 +1158,30 @@ void EmitPopulateCompilationGraph (Record* CompilationGraph, // End of anonymous namespace } -// Back-end entry point +/// run - The back-end entry point. void LLVMCConfigurationEmitter::run (std::ostream &O) { - // Emit file header + + // Emit file header. EmitSourceFileHeader("LLVMC Configuration Library", O); - // Get a list of all defined Tools + // Get a list of all defined Tools. RecordVector Tools = Records.getAllDerivedDefinitions("Tool"); if (Tools.empty()) throw std::string("No tool definitions found!"); - // Gather information from the Tool descriptions + // Gather information from the Tool description dags. ToolPropertiesList tool_props; GlobalOptionDescriptions opt_descs; CollectToolProperties(Tools.begin(), Tools.end(), tool_props, opt_descs); - // Emit global option registration code + // Emit global option registration code. EmitOptionDescriptions(opt_descs, O); - // Emit PopulateLanguageMap function - // (a language map maps from file extensions to language names) + // Emit PopulateLanguageMap() function + // (a language map maps from file extensions to language names). EmitPopulateLanguageMap(Records, O); - // Emit Tool classes + // Emit Tool classes. for (ToolPropertiesList::const_iterator B = tool_props.begin(), E = tool_props.end(); B!=E; ++B) EmitToolClassDefinition(*(*B), O); @@ -1116,10 +1193,10 @@ void LLVMCConfigurationEmitter::run (std::ostream &O) { // Typecheck the compilation graph. TypecheckGraph(CompilationGraphRecord, tool_props); - // Emit Edge* classes. + // Emit Edge# classes. EmitEdgeClasses(CompilationGraphRecord, opt_descs, O); - // Emit PopulateCompilationGraph function + // Emit PopulateCompilationGraph() function. EmitPopulateCompilationGraph(CompilationGraphRecord, O); // EOF