X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FLLVMCConfigurationEmitter.cpp;h=f30c6ee0a83bf4e78dc89eac1e09cf0f63091c73;hb=4c8c83022b501759d8559e224c84ae2a9921ba41;hp=44a6ff4a402182f29bac33261f1cb5de64ffa54d;hpb=5fe8475e3ab521444193c469cdeaa3a2edf01abb;p=oota-llvm.git diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp index 44a6ff4a402..f30c6ee0a83 100644 --- a/utils/TableGen/LLVMCConfigurationEmitter.cpp +++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp @@ -20,13 +20,12 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/Streams.h" - #include #include #include #include #include - +#include using namespace llvm; namespace { @@ -243,6 +242,7 @@ struct GlobalOptionDescriptions { /// HasSink - Should the emitter generate a "cl::sink" option? bool HasSink; + /// FindOption - exception-throwing wrapper for find(). const GlobalOptionDescription& FindOption(const std::string& OptName) const { const_iterator I = Descriptions.find(OptName); if (I != Descriptions.end()) @@ -251,6 +251,20 @@ struct GlobalOptionDescriptions { throw OptName + ": no such option!"; } + /// insertDescription - Insert new GlobalOptionDescription into + /// GlobalOptionDescriptions list + void insertDescription (const GlobalOptionDescription& o) + { + container_type::iterator I = Descriptions.find(o.Name); + if (I != Descriptions.end()) { + GlobalOptionDescription& D = I->second; + D.Merge(o); + } + else { + Descriptions[o.Name] = o; + } + } + // Support for STL-style iteration const_iterator begin() const { return Descriptions.begin(); } const_iterator end() const { return Descriptions.end(); } @@ -337,8 +351,8 @@ struct ToolProperties : public RefCountedBase { // Default ctor here is needed because StringMap can only store // DefaultConstructible objects - ToolProperties() : Flags(0) {} - ToolProperties (const std::string& n) : Name(n), Flags(0) {} + ToolProperties() : CmdLine(0), Flags(0) {} + ToolProperties (const std::string& n) : Name(n), CmdLine(0), Flags(0) {} }; @@ -348,12 +362,226 @@ struct ToolProperties : public RefCountedBase { typedef std::vector > ToolPropertiesList; +/// CollectOptionProperties - Function object for iterating over a +/// list (usually, a DAG) of option property records. +class CollectOptionProperties { +private: + // Implementation details. + + /// OptionPropertyHandler - a function that extracts information + /// about a given option property from its DAG representation. + typedef void (CollectOptionProperties::* OptionPropertyHandler) + (const DagInit*); + + /// OptionPropertyHandlerMap - A map from option property names to + /// option property handlers + typedef StringMap OptionPropertyHandlerMap; + + static OptionPropertyHandlerMap optionPropertyHandlers_; + static bool staticMembersInitialized_; + + /// This is where the information is stored + + /// toolProps_ - Properties of the current Tool. + ToolProperties* toolProps_; + /// optDescs_ - OptionDescriptions table (used to register options + /// globally). + GlobalOptionDescription& optDesc_; + +public: + + explicit CollectOptionProperties(ToolProperties* TP, + GlobalOptionDescription& OD) + : toolProps_(TP), optDesc_(OD) + { + if (!staticMembersInitialized_) { + optionPropertyHandlers_["append_cmd"] = + &CollectOptionProperties::onAppendCmd; + optionPropertyHandlers_["forward"] = + &CollectOptionProperties::onForward; + optionPropertyHandlers_["help"] = + &CollectOptionProperties::onHelp; + optionPropertyHandlers_["output_suffix"] = + &CollectOptionProperties::onOutputSuffix; + optionPropertyHandlers_["required"] = + &CollectOptionProperties::onRequired; + optionPropertyHandlers_["stop_compilation"] = + &CollectOptionProperties::onStopCompilation; + optionPropertyHandlers_["unpack_values"] = + &CollectOptionProperties::onUnpackValues; + + staticMembersInitialized_ = true; + } + } + + /// operator() - Gets called for every option property; Just forwards + /// to the corresponding property handler. + void operator() (Init* i) { + const DagInit& option_property = InitPtrToDag(i); + const std::string& option_property_name + = option_property.getOperator()->getAsString(); + OptionPropertyHandlerMap::iterator method + = optionPropertyHandlers_.find(option_property_name); + + if (method != optionPropertyHandlers_.end()) { + OptionPropertyHandler h = method->second; + (this->*h)(&option_property); + } + else { + throw "Unknown option property: " + option_property_name + "!"; + } + } + +private: + + /// Option property handlers -- + /// Methods that handle properties that are common for all types of + /// options (like append_cmd, stop_compilation) + + void onAppendCmd (const DagInit* d) { + checkNumberOfArguments(d, 1); + checkToolProps(d); + const std::string& cmd = InitPtrToString(d->getArg(0)); + + toolProps_->OptDescs[optDesc_.Name]. + AddProperty(OptionPropertyType::AppendCmd, cmd); + } + + void onOutputSuffix (const DagInit* d) { + checkNumberOfArguments(d, 1); + checkToolProps(d); + const std::string& suf = InitPtrToString(d->getArg(0)); + + if (toolProps_->OptDescs[optDesc_.Name].Type != OptionType::Switch) + throw "Option " + optDesc_.Name + + " can't have 'output_suffix' property since it isn't a switch!"; + + toolProps_->OptDescs[optDesc_.Name].AddProperty + (OptionPropertyType::OutputSuffix, suf); + } + + void onForward (const DagInit* d) { + checkNumberOfArguments(d, 0); + checkToolProps(d); + toolProps_->OptDescs[optDesc_.Name].setForward(); + } + + void onHelp (const DagInit* d) { + checkNumberOfArguments(d, 1); + const std::string& help_message = InitPtrToString(d->getArg(0)); + + optDesc_.Help = help_message; + } + + void onRequired (const DagInit* d) { + checkNumberOfArguments(d, 0); + checkToolProps(d); + optDesc_.setRequired(); + } + + void onStopCompilation (const DagInit* d) { + checkNumberOfArguments(d, 0); + checkToolProps(d); + if (optDesc_.Type != OptionType::Switch) + throw std::string("Only options of type Switch can stop compilation!"); + toolProps_->OptDescs[optDesc_.Name].setStopCompilation(); + } + + void onUnpackValues (const DagInit* d) { + checkNumberOfArguments(d, 0); + checkToolProps(d); + toolProps_->OptDescs[optDesc_.Name].setUnpackValues(); + } + + // Helper functions + + /// checkToolProps - Throw an error if toolProps_ == 0. + void checkToolProps(const DagInit* d) { + if (!d) + throw "Option property " + d->getOperator()->getAsString() + + " can't be used in this context"; + } + +}; + +CollectOptionProperties::OptionPropertyHandlerMap +CollectOptionProperties::optionPropertyHandlers_; + +bool CollectOptionProperties::staticMembersInitialized_ = false; + + +/// processOptionProperties - Go through the list of option +/// properties and call a corresponding handler for each. +void processOptionProperties (const DagInit* d, ToolProperties* t, + GlobalOptionDescription& o) { + checkNumberOfArguments(d, 2); + DagInit::const_arg_iterator B = d->arg_begin(); + // Skip the first argument: it's always the option name. + ++B; + std::for_each(B, d->arg_end(), CollectOptionProperties(t, o)); +} + +/// AddOption - A function object wrapper for +/// processOptionProperties. Used by CollectProperties and +/// CollectPropertiesFromOptionList. +class AddOption { +private: + GlobalOptionDescriptions& OptDescs_; + ToolProperties* ToolProps_; + +public: + explicit AddOption(GlobalOptionDescriptions& OD, ToolProperties* TP = 0) + : OptDescs_(OD), ToolProps_(TP) + {} + + void operator()(const Init* i) { + const DagInit& d = InitPtrToDag(i); + checkNumberOfArguments(&d, 2); + + const OptionType::OptionType Type = + getOptionType(d.getOperator()->getAsString()); + const std::string& Name = InitPtrToString(d.getArg(0)); + + GlobalOptionDescription OD(Type, Name); + if (Type != OptionType::Alias) { + processOptionProperties(&d, ToolProps_, OD); + if (ToolProps_) { + ToolProps_->OptDescs[Name].Type = Type; + ToolProps_->OptDescs[Name].Name = Name; + } + } + else { + OD.Help = InitPtrToString(d.getArg(1)); + } + OptDescs_.insertDescription(OD); + } + +private: + OptionType::OptionType getOptionType(const std::string& T) const { + if (T == "alias_option") + return OptionType::Alias; + else if (T == "switch_option") + return OptionType::Switch; + else if (T == "parameter_option") + return OptionType::Parameter; + else if (T == "parameter_list_option") + return OptionType::ParameterList; + else if (T == "prefix_option") + return OptionType::Prefix; + else if (T == "prefix_list_option") + return OptionType::PrefixList; + else + throw "Unknown option type: " + T + '!'; + } +}; + + /// CollectProperties - Function object for iterating over a list of /// tool property records. class CollectProperties { private: - /// Implementation details + // Implementation details /// PropertyHandler - a function that extracts information /// about a given tool property from its DAG representation @@ -363,18 +591,8 @@ private: /// handlers. typedef StringMap PropertyHandlerMap; - /// OptionPropertyHandler - a function that extracts information - /// about a given option property from its DAG representation. - typedef void (CollectProperties::* OptionPropertyHandler) - (const DagInit*, GlobalOptionDescription &); - - /// OptionPropertyHandlerMap - A map from option property names to - /// option property handlers - typedef StringMap OptionPropertyHandlerMap; - // Static maps from strings to CollectProperties methods("handlers") static PropertyHandlerMap propertyHandlers_; - static OptionPropertyHandlerMap optionPropertyHandlers_; static bool staticMembersInitialized_; @@ -392,34 +610,21 @@ public: : toolProps_(p), optDescs_(d) { if (!staticMembersInitialized_) { - // Init tool property handlers propertyHandlers_["cmd_line"] = &CollectProperties::onCmdLine; propertyHandlers_["in_language"] = &CollectProperties::onInLanguage; propertyHandlers_["join"] = &CollectProperties::onJoin; propertyHandlers_["out_language"] = &CollectProperties::onOutLanguage; propertyHandlers_["output_suffix"] = &CollectProperties::onOutputSuffix; propertyHandlers_["parameter_option"] - = &CollectProperties::onParameter; + = &CollectProperties::addOption; propertyHandlers_["parameter_list_option"] = - &CollectProperties::onParameterList; - propertyHandlers_["prefix_option"] = &CollectProperties::onPrefix; + &CollectProperties::addOption; + propertyHandlers_["prefix_option"] = &CollectProperties::addOption; propertyHandlers_["prefix_list_option"] = - &CollectProperties::onPrefixList; + &CollectProperties::addOption; propertyHandlers_["sink"] = &CollectProperties::onSink; - propertyHandlers_["switch_option"] = &CollectProperties::onSwitch; - propertyHandlers_["alias_option"] = &CollectProperties::onAlias; - - // Init option property handlers - optionPropertyHandlers_["append_cmd"] = &CollectProperties::onAppendCmd; - optionPropertyHandlers_["forward"] = &CollectProperties::onForward; - optionPropertyHandlers_["help"] = &CollectProperties::onHelp; - optionPropertyHandlers_["output_suffix"] = - &CollectProperties::onOutputSuffixOptionProp; - optionPropertyHandlers_["required"] = &CollectProperties::onRequired; - optionPropertyHandlers_["stop_compilation"] = - &CollectProperties::onStopCompilation; - optionPropertyHandlers_["unpack_values"] = - &CollectProperties::onUnpackValues; + propertyHandlers_["switch_option"] = &CollectProperties::addOption; + propertyHandlers_["alias_option"] = &CollectProperties::addOption; staticMembersInitialized_ = true; } @@ -501,155 +706,23 @@ private: toolProps_.setSink(); } - void onAlias (const DagInit* d) { - checkNumberOfArguments(d, 2); - // We just need a GlobalOptionDescription for the aliases. - insertDescription - (GlobalOptionDescription(OptionType::Alias, - InitPtrToString(d->getArg(0)), - InitPtrToString(d->getArg(1)))); - } - - 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 (const DagInit* d, GlobalOptionDescription& o) { - checkNumberOfArguments(d, 1); - const std::string& cmd = InitPtrToString(d->getArg(0)); - - toolProps_.OptDescs[o.Name].AddProperty(OptionPropertyType::AppendCmd, cmd); - } - - void onOutputSuffixOptionProp (const DagInit* d, GlobalOptionDescription& o) { - checkNumberOfArguments(d, 1); - const std::string& suf = InitPtrToString(d->getArg(0)); - - if (toolProps_.OptDescs[o.Name].Type != OptionType::Switch) - throw "Option " + o.Name - + " can't have 'output_suffix' property since it isn't a switch!"; - - toolProps_.OptDescs[o.Name].AddProperty - (OptionPropertyType::OutputSuffix, suf); - } - - void onForward (const DagInit* d, GlobalOptionDescription& o) { - checkNumberOfArguments(d, 0); - toolProps_.OptDescs[o.Name].setForward(); - } - - 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 (const DagInit* d, GlobalOptionDescription& o) { - checkNumberOfArguments(d, 0); - o.setRequired(); - } - - 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 (const DagInit* d, GlobalOptionDescription& o) { - checkNumberOfArguments(d, 0); - toolProps_.OptDescs[o.Name].setUnpackValues(); - } - - /// Helper functions - - // Add an option of type t - void addOption (const DagInit* d, OptionType::OptionType t) { + // Just forwards to the AddOption function object. Somewhat + // non-optimal, but avoids code duplication. + void addOption (const DagInit* d) { checkNumberOfArguments(d, 2); - const std::string& name = InitPtrToString(d->getArg(0)); - - GlobalOptionDescription o(t, name); - toolProps_.OptDescs[name].Type = t; - toolProps_.OptDescs[name].Name = name; - processOptionProperties(d, o); - insertDescription(o); + AddOption(optDescs_, &toolProps_)(d); } - // Insert new GlobalOptionDescription into GlobalOptionDescriptions list - void insertDescription (const GlobalOptionDescription& o) - { - if (optDescs_.Descriptions.count(o.Name)) { - GlobalOptionDescription& D = optDescs_.Descriptions[o.Name]; - D.Merge(o); - } - else { - optDescs_.Descriptions[o.Name] = 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) { - const DagInit& option_property - = InitPtrToDag(d->getArg(B)); - const std::string& option_property_name - = option_property.getOperator()->getAsString(); - OptionPropertyHandlerMap::iterator method - = optionPropertyHandlers_.find(option_property_name); - - if (method != optionPropertyHandlers_.end()) { - OptionPropertyHandler h = method->second; - (this->*h)(&option_property, o); - } - else { - throw "Unknown option property: " + option_property_name + "!"; - } - } - } }; -// Static members of CollectProperties -CollectProperties::PropertyHandlerMap -CollectProperties::propertyHandlers_; - -CollectProperties::OptionPropertyHandlerMap -CollectProperties::optionPropertyHandlers_; - +// Defintions of static members of CollectProperties. +CollectProperties::PropertyHandlerMap CollectProperties::propertyHandlers_; bool CollectProperties::staticMembersInitialized_ = false; -/// CollectToolProperties - Gather information from the parsed -/// TableGen data (basically a wrapper for the CollectProperties -/// function object). +/// CollectToolProperties - Gather information about tool properties +/// 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, @@ -657,7 +730,8 @@ void CollectToolProperties (RecordVector::const_iterator B, { // Iterate over a properties list of every Tool definition for (;B!=E;++B) { - RecordVector::value_type T = *B; + Record* T = *B; + // Throws an exception if the value does not exist. ListInit* PropList = T->getValueAsListInit("properties"); IntrusiveRefCntPtr @@ -669,12 +743,60 @@ void CollectToolProperties (RecordVector::const_iterator B, } } + +/// CollectPropertiesFromOptionList - Gather information about +/// *global* option properties from the OptionList. +void CollectPropertiesFromOptionList (RecordVector::const_iterator B, + RecordVector::const_iterator E, + GlobalOptionDescriptions& OptDescs) +{ + // Iterate over a properties list of every Tool definition + for (;B!=E;++B) { + RecordVector::value_type T = *B; + // Throws an exception if the value does not exist. + ListInit* PropList = T->getValueAsListInit("options"); + + std::for_each(PropList->begin(), PropList->end(), AddOption(OptDescs)); + } +} + +/// CheckForSuperfluousOptions - Check that there are no side +/// effect-free options (specified only in the OptionList). Otherwise, +/// output a warning. +void CheckForSuperfluousOptions (const ToolPropertiesList& TPList, + const GlobalOptionDescriptions& OptDescs) { + llvm::StringSet<> nonSuperfluousOptions; + + // Add all options mentioned in the TPList to the set of + // non-superfluous options. + for (ToolPropertiesList::const_iterator B = TPList.begin(), + E = TPList.end(); B != E; ++B) { + const ToolProperties& TP = *(*B); + for (ToolOptionDescriptions::const_iterator B = TP.OptDescs.begin(), + E = TP.OptDescs.end(); B != E; ++B) { + nonSuperfluousOptions.insert(B->first()); + } + } + + // Check that all options in OptDescs belong to the set of + // non-superfluous options. + for (GlobalOptionDescriptions::const_iterator B = OptDescs.begin(), + E = OptDescs.end(); B != E; ++B) { + const GlobalOptionDescription& Val = B->second; + if (!nonSuperfluousOptions.count(Val.Name) + && Val.Type != OptionType::Alias) + cerr << "Warning: option '-" << Val.Name << "' has no effect! " + "Probable cause: this option is specified only in the OptionList.\n"; + } +} + /// EmitCaseTest1Arg - Helper function used by /// EmitCaseConstructHandler. bool EmitCaseTest1Arg(const std::string& TestName, const DagInit& d, const GlobalOptionDescriptions& OptDescs, std::ostream& O) { + // TOFIX - Add a mechanism for OS detection. checkNumberOfArguments(&d, 1); const std::string& OptName = InitPtrToString(d.getArg(0)); if (TestName == "switch_on") { @@ -787,7 +909,7 @@ void EmitCaseTest(const DagInit& d, const char* IndentLevel, // void F(Init* Statement, const char* IndentLevel, std::ostream& O). template void EmitCaseConstructHandler(const DagInit* d, const char* IndentLevel, - const F& Callback, bool EmitElseIf, + F Callback, bool EmitElseIf, const GlobalOptionDescriptions& OptDescs, std::ostream& O) { assert(d->getOperator()->getAsString() == "case"); @@ -1571,6 +1693,14 @@ void LLVMCConfigurationEmitter::run (std::ostream &O) { GlobalOptionDescriptions opt_descs; CollectToolProperties(Tools.begin(), Tools.end(), tool_props, opt_descs); + RecordVector OptionLists = Records.getAllDerivedDefinitions("OptionList"); + CollectPropertiesFromOptionList(OptionLists.begin(), OptionLists.end(), + opt_descs); + + // Check that there are no options without side effects (specified + // only in the OptionList). + CheckForSuperfluousOptions(tool_props, opt_descs); + // Emit global option registration code. EmitOptionDescriptions(opt_descs, O);