[llvm-commits] [llvm] r169344 - in /llvm/trunk: include/llvm/Option/ lib/ lib/Option/ unittests/ unittests/Option/ utils/TableGen/

Sean Silva silvas at purdue.edu
Tue Dec 4 18:26:13 PST 2012


I know this commit is just moving code around, but a quick suggestion:

+    // FIXME: Avoid strlen.
+    if (ArgSize != strlen(Args.getArgString(Index)))

You should be able to do StringRef(...).size() (although internally
that just calls strlen(), but at least that usage is "contained").

-- Sean Silva

On Tue, Dec 4, 2012 at 7:29 PM, Michael J. Spencer
<bigcheesegs at gmail.com> wrote:
> Author: mspencer
> Date: Tue Dec  4 18:29:32 2012
> New Revision: 169344
>
> URL: http://llvm.org/viewvc/llvm-project?rev=169344&view=rev
> Log:
> Copy clang/Driver/<Option parsing stuff> to llvm.
>
> Added:
>     llvm/trunk/include/llvm/Option/
>     llvm/trunk/include/llvm/Option/Arg.h
>     llvm/trunk/include/llvm/Option/ArgList.h
>     llvm/trunk/include/llvm/Option/OptParser.td
>     llvm/trunk/include/llvm/Option/OptSpecifier.h
>     llvm/trunk/include/llvm/Option/OptTable.h
>     llvm/trunk/include/llvm/Option/Option.h
>     llvm/trunk/lib/Option/
>     llvm/trunk/lib/Option/Arg.cpp
>     llvm/trunk/lib/Option/ArgList.cpp
>     llvm/trunk/lib/Option/CMakeLists.txt
>     llvm/trunk/lib/Option/LLVMBuild.txt
>       - copied, changed from r169343, llvm/trunk/lib/LLVMBuild.txt
>     llvm/trunk/lib/Option/Makefile
>       - copied, changed from r169343, llvm/trunk/lib/Makefile
>     llvm/trunk/lib/Option/OptTable.cpp
>     llvm/trunk/lib/Option/Option.cpp
>     llvm/trunk/unittests/Option/
>     llvm/trunk/unittests/Option/CMakeLists.txt
>     llvm/trunk/unittests/Option/OptionParsingTest.cpp
>     llvm/trunk/unittests/Option/Opts.td
>     llvm/trunk/utils/TableGen/OptParserEmitter.cpp
> Modified:
>     llvm/trunk/lib/CMakeLists.txt
>     llvm/trunk/lib/LLVMBuild.txt
>     llvm/trunk/lib/Makefile
>     llvm/trunk/unittests/CMakeLists.txt
>     llvm/trunk/utils/TableGen/CMakeLists.txt
>     llvm/trunk/utils/TableGen/TableGen.cpp
>     llvm/trunk/utils/TableGen/TableGenBackends.h
>
> Added: llvm/trunk/include/llvm/Option/Arg.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Option/Arg.h?rev=169344&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/Option/Arg.h (added)
> +++ llvm/trunk/include/llvm/Option/Arg.h Tue Dec  4 18:29:32 2012
> @@ -0,0 +1,132 @@
> +//===--- Arg.h - Parsed Argument Classes ------------------------*- C++ -*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +///
> +/// \file
> +/// \brief Defines the llvm::Arg class for parsed arguments.
> +///
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_SUPPORT_ARG_H_
> +#define LLVM_SUPPORT_ARG_H_
> +
> +#include "llvm/ADT/SmallVector.h"
> +#include "llvm/ADT/StringRef.h"
> +#include "llvm/Option/Option.h"
> +#include <string>
> +
> +namespace llvm {
> +namespace opt {
> +class ArgList;
> +
> +/// \brief A concrete instance of a particular driver option.
> +///
> +/// The Arg class encodes just enough information to be able to
> +/// derive the argument values efficiently. In addition, Arg
> +/// instances have an intrusive double linked list which is used by
> +/// ArgList to provide efficient iteration over all instances of a
> +/// particular option.
> +class Arg {
> +  Arg(const Arg &) LLVM_DELETED_FUNCTION;
> +  void operator=(const Arg &) LLVM_DELETED_FUNCTION;
> +
> +private:
> +  /// \brief The option this argument is an instance of.
> +  const Option Opt;
> +
> +  /// \brief The argument this argument was derived from (during tool chain
> +  /// argument translation), if any.
> +  const Arg *BaseArg;
> +
> +  /// \brief How this instance of the option was spelled.
> +  StringRef Spelling;
> +
> +  /// \brief The index at which this argument appears in the containing
> +  /// ArgList.
> +  unsigned Index;
> +
> +  /// \brief Was this argument used to effect compilation?
> +  ///
> +  /// This is used for generating "argument unused" diagnostics.
> +  mutable unsigned Claimed : 1;
> +
> +  /// \brief Does this argument own its values?
> +  mutable unsigned OwnsValues : 1;
> +
> +  /// \brief The argument values, as C strings.
> +  SmallVector<const char *, 2> Values;
> +
> +public:
> +  Arg(const Option Opt, StringRef Spelling, unsigned Index,
> +      const Arg *BaseArg = 0);
> +  Arg(const Option Opt, StringRef Spelling, unsigned Index,
> +      const char *Value0, const Arg *BaseArg = 0);
> +  Arg(const Option Opt, StringRef Spelling, unsigned Index,
> +      const char *Value0, const char *Value1, const Arg *BaseArg = 0);
> +  ~Arg();
> +
> +  const Option getOption() const { return Opt; }
> +  StringRef getSpelling() const { return Spelling; }
> +  unsigned getIndex() const { return Index; }
> +
> +  /// \brief Return the base argument which generated this arg.
> +  ///
> +  /// This is either the argument itself or the argument it was
> +  /// derived from during tool chain specific argument translation.
> +  const Arg &getBaseArg() const {
> +    return BaseArg ? *BaseArg : *this;
> +  }
> +  void setBaseArg(const Arg *_BaseArg) {
> +    BaseArg = _BaseArg;
> +  }
> +
> +  bool getOwnsValues() const { return OwnsValues; }
> +  void setOwnsValues(bool Value) const { OwnsValues = Value; }
> +
> +  bool isClaimed() const { return getBaseArg().Claimed; }
> +
> +  /// \brief Set the Arg claimed bit.
> +  void claim() const { getBaseArg().Claimed = true; }
> +
> +  unsigned getNumValues() const { return Values.size(); }
> +  const char *getValue(unsigned N = 0) const {
> +    return Values[N];
> +  }
> +
> +  SmallVectorImpl<const char*> &getValues() {
> +    return Values;
> +  }
> +
> +  bool containsValue(StringRef Value) const {
> +    for (unsigned i = 0, e = getNumValues(); i != e; ++i)
> +      if (Values[i] == Value)
> +        return true;
> +    return false;
> +  }
> +
> +  /// \brief Append the argument onto the given array as strings.
> +  void render(const ArgList &Args, ArgStringList &Output) const;
> +
> +  /// \brief Append the argument, render as an input, onto the given
> +  /// array as strings.
> +  ///
> +  /// The distinction is that some options only render their values
> +  /// when rendered as a input (e.g., Xlinker).
> +  void renderAsInput(const ArgList &Args, ArgStringList &Output) const;
> +
> +  void dump() const;
> +
> +  /// \brief Return a formatted version of the argument and
> +  /// its values, for debugging and diagnostics.
> +  std::string getAsString(const ArgList &Args) const;
> +};
> +
> +} // end namespace opt
> +} // end namespace llvm
> +
> +#endif
>
> Added: llvm/trunk/include/llvm/Option/ArgList.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Option/ArgList.h?rev=169344&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/Option/ArgList.h (added)
> +++ llvm/trunk/include/llvm/Option/ArgList.h Tue Dec  4 18:29:32 2012
> @@ -0,0 +1,415 @@
> +//===--- ArgList.h - Argument List Management -------------------*- C++ -*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_SUPPORT_ARGLIST_H_
> +#define LLVM_SUPPORT_ARGLIST_H_
> +
> +#include "llvm/ADT/SmallVector.h"
> +#include "llvm/ADT/StringRef.h"
> +#include "llvm/Option/Option.h"
> +#include "llvm/Option/OptSpecifier.h"
> +
> +#include <list>
> +#include <string>
> +#include <vector>
> +
> +namespace llvm {
> +namespace opt {
> +class Arg;
> +class ArgList;
> +class Option;
> +
> +/// arg_iterator - Iterates through arguments stored inside an ArgList.
> +class arg_iterator {
> +  /// The current argument.
> +  SmallVectorImpl<Arg*>::const_iterator Current;
> +
> +  /// The argument list we are iterating over.
> +  const ArgList &Args;
> +
> +  /// Optional filters on the arguments which will be match. Most clients
> +  /// should never want to iterate over arguments without filters, so we won't
> +  /// bother to factor this into two separate iterator implementations.
> +  //
> +  // FIXME: Make efficient; the idea is to provide efficient iteration over
> +  // all arguments which match a particular id and then just provide an
> +  // iterator combinator which takes multiple iterators which can be
> +  // efficiently compared and returns them in order.
> +  OptSpecifier Id0, Id1, Id2;
> +
> +  void SkipToNextArg();
> +
> +public:
> +  typedef Arg * const *                 value_type;
> +  typedef Arg * const &                 reference;
> +  typedef Arg * const *                 pointer;
> +  typedef std::forward_iterator_tag   iterator_category;
> +  typedef std::ptrdiff_t              difference_type;
> +
> +  arg_iterator(SmallVectorImpl<Arg*>::const_iterator it,
> +                const ArgList &_Args, OptSpecifier _Id0 = 0U,
> +                OptSpecifier _Id1 = 0U, OptSpecifier _Id2 = 0U)
> +    : Current(it), Args(_Args), Id0(_Id0), Id1(_Id1), Id2(_Id2) {
> +    SkipToNextArg();
> +  }
> +
> +  operator const Arg*() { return *Current; }
> +  reference operator*() const { return *Current; }
> +  pointer operator->() const { return Current; }
> +
> +  arg_iterator &operator++() {
> +    ++Current;
> +    SkipToNextArg();
> +    return *this;
> +  }
> +
> +  arg_iterator operator++(int) {
> +    arg_iterator tmp(*this);
> +    ++(*this);
> +    return tmp;
> +  }
> +
> +  friend bool operator==(arg_iterator LHS, arg_iterator RHS) {
> +    return LHS.Current == RHS.Current;
> +  }
> +  friend bool operator!=(arg_iterator LHS, arg_iterator RHS) {
> +    return !(LHS == RHS);
> +  }
> +};
> +
> +/// ArgList - Ordered collection of driver arguments.
> +///
> +/// The ArgList class manages a list of Arg instances as well as
> +/// auxiliary data and convenience methods to allow Tools to quickly
> +/// check for the presence of Arg instances for a particular Option
> +/// and to iterate over groups of arguments.
> +class ArgList {
> +private:
> +  ArgList(const ArgList &) LLVM_DELETED_FUNCTION;
> +  void operator=(const ArgList &) LLVM_DELETED_FUNCTION;
> +
> +public:
> +  typedef SmallVector<Arg*, 16> arglist_type;
> +  typedef arglist_type::iterator iterator;
> +  typedef arglist_type::const_iterator const_iterator;
> +  typedef arglist_type::reverse_iterator reverse_iterator;
> +  typedef arglist_type::const_reverse_iterator const_reverse_iterator;
> +
> +private:
> +  /// The internal list of arguments.
> +  arglist_type Args;
> +
> +protected:
> +  ArgList();
> +
> +public:
> +  virtual ~ArgList();
> +
> +  /// @name Arg Access
> +  /// @{
> +
> +  /// append - Append \p A to the arg list.
> +  void append(Arg *A);
> +
> +  arglist_type &getArgs() { return Args; }
> +  const arglist_type &getArgs() const { return Args; }
> +
> +  unsigned size() const { return Args.size(); }
> +
> +  /// @}
> +  /// @name Arg Iteration
> +  /// @{
> +
> +  iterator begin() { return Args.begin(); }
> +  iterator end() { return Args.end(); }
> +
> +  reverse_iterator rbegin() { return Args.rbegin(); }
> +  reverse_iterator rend() { return Args.rend(); }
> +
> +  const_iterator begin() const { return Args.begin(); }
> +  const_iterator end() const { return Args.end(); }
> +
> +  const_reverse_iterator rbegin() const { return Args.rbegin(); }
> +  const_reverse_iterator rend() const { return Args.rend(); }
> +
> +  arg_iterator filtered_begin(OptSpecifier Id0 = 0U, OptSpecifier Id1 = 0U,
> +                              OptSpecifier Id2 = 0U) const {
> +    return arg_iterator(Args.begin(), *this, Id0, Id1, Id2);
> +  }
> +  arg_iterator filtered_end() const {
> +    return arg_iterator(Args.end(), *this);
> +  }
> +
> +  /// @}
> +  /// @name Arg Removal
> +  /// @{
> +
> +  /// eraseArg - Remove any option matching \p Id.
> +  void eraseArg(OptSpecifier Id);
> +
> +  /// @}
> +  /// @name Arg Access
> +  /// @{
> +
> +  /// hasArg - Does the arg list contain any option matching \p Id.
> +  ///
> +  /// \p Claim Whether the argument should be claimed, if it exists.
> +  bool hasArgNoClaim(OptSpecifier Id) const {
> +    return getLastArgNoClaim(Id) != 0;
> +  }
> +  bool hasArg(OptSpecifier Id) const {
> +    return getLastArg(Id) != 0;
> +  }
> +  bool hasArg(OptSpecifier Id0, OptSpecifier Id1) const {
> +    return getLastArg(Id0, Id1) != 0;
> +  }
> +  bool hasArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const {
> +    return getLastArg(Id0, Id1, Id2) != 0;
> +  }
> +
> +  /// getLastArg - Return the last argument matching \p Id, or null.
> +  ///
> +  /// \p Claim Whether the argument should be claimed, if it exists.
> +  Arg *getLastArgNoClaim(OptSpecifier Id) const;
> +  Arg *getLastArg(OptSpecifier Id) const;
> +  Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1) const;
> +  Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const;
> +  Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
> +                  OptSpecifier Id3) const;
> +  Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
> +                  OptSpecifier Id3, OptSpecifier Id4) const;
> +  Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
> +                  OptSpecifier Id3, OptSpecifier Id4, OptSpecifier Id5) const;
> +  Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
> +                  OptSpecifier Id3, OptSpecifier Id4, OptSpecifier Id5,
> +                  OptSpecifier Id6) const;
> +  Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2,
> +                  OptSpecifier Id3, OptSpecifier Id4, OptSpecifier Id5,
> +                  OptSpecifier Id6, OptSpecifier Id7) const;
> +
> +  /// getArgString - Return the input argument string at \p Index.
> +  virtual const char *getArgString(unsigned Index) const = 0;
> +
> +  /// getNumInputArgStrings - Return the number of original argument strings,
> +  /// which are guaranteed to be the first strings in the argument string
> +  /// list.
> +  virtual unsigned getNumInputArgStrings() const = 0;
> +
> +  /// @}
> +  /// @name Argument Lookup Utilities
> +  /// @{
> +
> +  /// getLastArgValue - Return the value of the last argument, or a default.
> +  StringRef getLastArgValue(OptSpecifier Id,
> +                                  StringRef Default = "") const;
> +
> +  /// getAllArgValues - Get the values of all instances of the given argument
> +  /// as strings.
> +  std::vector<std::string> getAllArgValues(OptSpecifier Id) const;
> +
> +  /// @}
> +  /// @name Translation Utilities
> +  /// @{
> +
> +  /// hasFlag - Given an option \p Pos and its negative form \p Neg, return
> +  /// true if the option is present, false if the negation is present, and
> +  /// \p Default if neither option is given. If both the option and its
> +  /// negation are present, the last one wins.
> +  bool hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default=true) const;
> +
> +  /// AddLastArg - Render only the last argument match \p Id0, if present.
> +  void AddLastArg(ArgStringList &Output, OptSpecifier Id0) const;
> +
> +  /// AddAllArgs - Render all arguments matching the given ids.
> +  void AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
> +                  OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const;
> +
> +  /// AddAllArgValues - Render the argument values of all arguments
> +  /// matching the given ids.
> +  void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
> +                        OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const;
> +
> +  /// AddAllArgsTranslated - Render all the arguments matching the
> +  /// given ids, but forced to separate args and using the provided
> +  /// name instead of the first option value.
> +  ///
> +  /// \param Joined - If true, render the argument as joined with
> +  /// the option specifier.
> +  void AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
> +                            const char *Translation,
> +                            bool Joined = false) const;
> +
> +  /// ClaimAllArgs - Claim all arguments which match the given
> +  /// option id.
> +  void ClaimAllArgs(OptSpecifier Id0) const;
> +
> +  /// ClaimAllArgs - Claim all arguments.
> +  ///
> +  void ClaimAllArgs() const;
> +
> +  /// @}
> +  /// @name Arg Synthesis
> +  /// @{
> +
> +  /// MakeArgString - Construct a constant string pointer whose
> +  /// lifetime will match that of the ArgList.
> +  virtual const char *MakeArgString(StringRef Str) const = 0;
> +  const char *MakeArgString(const char *Str) const {
> +    return MakeArgString(StringRef(Str));
> +  }
> +  const char *MakeArgString(std::string Str) const {
> +    return MakeArgString(StringRef(Str));
> +  }
> +  const char *MakeArgString(const Twine &Str) const;
> +
> +  /// \brief Create an arg string for (\p LHS + \p RHS), reusing the
> +  /// string at \p Index if possible.
> +  const char *GetOrMakeJoinedArgString(unsigned Index, StringRef LHS,
> +                                        StringRef RHS) const;
> +
> +  /// @}
> +};
> +
> +class InputArgList : public ArgList  {
> +private:
> +  /// List of argument strings used by the contained Args.
> +  ///
> +  /// This is mutable since we treat the ArgList as being the list
> +  /// of Args, and allow routines to add new strings (to have a
> +  /// convenient place to store the memory) via MakeIndex.
> +  mutable ArgStringList ArgStrings;
> +
> +  /// Strings for synthesized arguments.
> +  ///
> +  /// This is mutable since we treat the ArgList as being the list
> +  /// of Args, and allow routines to add new strings (to have a
> +  /// convenient place to store the memory) via MakeIndex.
> +  mutable std::list<std::string> SynthesizedStrings;
> +
> +  /// The number of original input argument strings.
> +  unsigned NumInputArgStrings;
> +
> +public:
> +  InputArgList(const char* const *ArgBegin, const char* const *ArgEnd);
> +  ~InputArgList();
> +
> +  virtual const char *getArgString(unsigned Index) const {
> +    return ArgStrings[Index];
> +  }
> +
> +  virtual unsigned getNumInputArgStrings() const {
> +    return NumInputArgStrings;
> +  }
> +
> +  /// @name Arg Synthesis
> +  /// @{
> +
> +public:
> +  /// MakeIndex - Get an index for the given string(s).
> +  unsigned MakeIndex(StringRef String0) const;
> +  unsigned MakeIndex(StringRef String0, StringRef String1) const;
> +
> +  virtual const char *MakeArgString(StringRef Str) const;
> +
> +  /// @}
> +};
> +
> +/// DerivedArgList - An ordered collection of driver arguments,
> +/// whose storage may be in another argument list.
> +class DerivedArgList : public ArgList {
> +  const InputArgList &BaseArgs;
> +
> +  /// The list of arguments we synthesized.
> +  mutable arglist_type SynthesizedArgs;
> +
> +public:
> +  /// Construct a new derived arg list from \p BaseArgs.
> +  DerivedArgList(const InputArgList &BaseArgs);
> +  ~DerivedArgList();
> +
> +  virtual const char *getArgString(unsigned Index) const {
> +    return BaseArgs.getArgString(Index);
> +  }
> +
> +  virtual unsigned getNumInputArgStrings() const {
> +    return BaseArgs.getNumInputArgStrings();
> +  }
> +
> +  const InputArgList &getBaseArgs() const {
> +    return BaseArgs;
> +  }
> +
> +  /// @name Arg Synthesis
> +  /// @{
> +
> +  /// AddSynthesizedArg - Add a argument to the list of synthesized arguments
> +  /// (to be freed).
> +  void AddSynthesizedArg(Arg *A) {
> +    SynthesizedArgs.push_back(A);
> +  }
> +
> +  virtual const char *MakeArgString(StringRef Str) const;
> +
> +  /// AddFlagArg - Construct a new FlagArg for the given option \p Id and
> +  /// append it to the argument list.
> +  void AddFlagArg(const Arg *BaseArg, const Option Opt) {
> +    append(MakeFlagArg(BaseArg, Opt));
> +  }
> +
> +  /// AddPositionalArg - Construct a new Positional arg for the given option
> +  /// \p Id, with the provided \p Value and append it to the argument
> +  /// list.
> +  void AddPositionalArg(const Arg *BaseArg, const Option Opt,
> +                        StringRef Value) {
> +    append(MakePositionalArg(BaseArg, Opt, Value));
> +  }
> +
> +
> +  /// AddSeparateArg - Construct a new Positional arg for the given option
> +  /// \p Id, with the provided \p Value and append it to the argument
> +  /// list.
> +  void AddSeparateArg(const Arg *BaseArg, const Option Opt,
> +                      StringRef Value) {
> +    append(MakeSeparateArg(BaseArg, Opt, Value));
> +  }
> +
> +
> +  /// AddJoinedArg - Construct a new Positional arg for the given option
> +  /// \p Id, with the provided \p Value and append it to the argument list.
> +  void AddJoinedArg(const Arg *BaseArg, const Option Opt,
> +                    StringRef Value) {
> +    append(MakeJoinedArg(BaseArg, Opt, Value));
> +  }
> +
> +
> +  /// MakeFlagArg - Construct a new FlagArg for the given option \p Id.
> +  Arg *MakeFlagArg(const Arg *BaseArg, const Option Opt) const;
> +
> +  /// MakePositionalArg - Construct a new Positional arg for the
> +  /// given option \p Id, with the provided \p Value.
> +  Arg *MakePositionalArg(const Arg *BaseArg, const Option Opt,
> +                          StringRef Value) const;
> +
> +  /// MakeSeparateArg - Construct a new Positional arg for the
> +  /// given option \p Id, with the provided \p Value.
> +  Arg *MakeSeparateArg(const Arg *BaseArg, const Option Opt,
> +                        StringRef Value) const;
> +
> +  /// MakeJoinedArg - Construct a new Positional arg for the
> +  /// given option \p Id, with the provided \p Value.
> +  Arg *MakeJoinedArg(const Arg *BaseArg, const Option Opt,
> +                      StringRef Value) const;
> +
> +  /// @}
> +};
> +
> +} // end namespace opt
> +} // end namespace llvm
> +
> +#endif
>
> Added: llvm/trunk/include/llvm/Option/OptParser.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Option/OptParser.td?rev=169344&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/Option/OptParser.td (added)
> +++ llvm/trunk/include/llvm/Option/OptParser.td Tue Dec  4 18:29:32 2012
> @@ -0,0 +1,127 @@
> +//===--- OptParser.td - Common Option Parsing Interfaces ------------------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +//  This file defines the common interfaces used by the option parsing TableGen
> +//  backend.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +// Define the kinds of options.
> +
> +class OptionKind<string name, int predecence = 0, bit sentinel = 0> {
> +  string Name = name;
> +  // The kind precedence, kinds with lower precedence are matched first.
> +  int Precedence = predecence;
> +  // Indicate a sentinel option.
> +  bit Sentinel = sentinel;
> +}
> +
> +// An option group.
> +def KIND_GROUP : OptionKind<"Group">;
> +// The input option kind.
> +def KIND_INPUT : OptionKind<"Input", 1, 1>;
> +// The unknown option kind.
> +def KIND_UNKNOWN : OptionKind<"Unknown", 2, 1>;
> +// A flag with no values.
> +def KIND_FLAG : OptionKind<"Flag">;
> +// An option which prefixes its (single) value.
> +def KIND_JOINED : OptionKind<"Joined", 1>;
> +// An option which is followed by its value.
> +def KIND_SEPARATE : OptionKind<"Separate">;
> +// An option followed by its values, which are separated by commas.
> +def KIND_COMMAJOINED : OptionKind<"CommaJoined">;
> +// An option which is which takes multiple (separate) arguments.
> +def KIND_MULTIARG : OptionKind<"MultiArg">;
> +// An option which is either joined to its (non-empty) value, or followed by its
> +// value.
> +def KIND_JOINED_OR_SEPARATE : OptionKind<"JoinedOrSeparate">;
> +// An option which is both joined to its (first) value, and followed by its
> +// (second) value.
> +def KIND_JOINED_AND_SEPARATE : OptionKind<"JoinedAndSeparate">;
> +
> +// Define the option flags.
> +
> +class OptionFlag {}
> +
> +// HelpHidden - The option should not be displayed in --help, even if it has
> +// help text. Clients *can* use this in conjunction with the OptTable::PrintHelp
> +// arguments to implement hidden help groups.
> +def HelpHidden : OptionFlag;
> +
> +// RenderAsInput - The option should not render the name when rendered as an
> +// input (i.e., the option is rendered as values).
> +def RenderAsInput : OptionFlag;
> +
> +// RenderJoined - The option should be rendered joined, even if separate (only
> +// sensible on single value separate options).
> +def RenderJoined : OptionFlag;
> +
> +// RenderSeparate - The option should be rendered separately, even if joined
> +// (only sensible on joined options).
> +def RenderSeparate : OptionFlag;
> +
> +// Define the option group class.
> +
> +class OptionGroup<string name> {
> +  string EnumName = ?; // Uses the def name if undefined.
> +  string Name = name;
> +  string HelpText = ?;
> +  OptionGroup Group = ?;
> +}
> +
> +// Define the option class.
> +
> +class Option<list<string> prefixes, string name, OptionKind kind> {
> +  string EnumName = ?; // Uses the def name if undefined.
> +  list<string> Prefixes = prefixes;
> +  string Name = name;
> +  OptionKind Kind = kind;
> +  // Used by MultiArg option kind.
> +  int NumArgs = 0;
> +  string HelpText = ?;
> +  string MetaVarName = ?;
> +  list<OptionFlag> Flags = [];
> +  OptionGroup Group = ?;
> +  Option Alias = ?;
> +}
> +
> +// Helpers for defining options.
> +
> +class Flag<list<string> prefixes, string name>
> +  : Option<prefixes, name, KIND_FLAG>;
> +class Joined<list<string> prefixes, string name>
> +  : Option<prefixes, name, KIND_JOINED>;
> +class Separate<list<string> prefixes, string name>
> +  : Option<prefixes, name, KIND_SEPARATE>;
> +class CommaJoined<list<string> prefixes, string name>
> +  : Option<prefixes, name, KIND_COMMAJOINED>;
> +class MultiArg<list<string> prefixes, string name, int numargs>
> +  : Option<prefixes, name, KIND_MULTIARG> {
> +  int NumArgs = numargs;
> +}
> +class JoinedOrSeparate<list<string> prefixes, string name>
> +  : Option<prefixes, name, KIND_JOINED_OR_SEPARATE>;
> +class JoinedAndSeparate<list<string> prefixes, string name>
> +  : Option<prefixes, name, KIND_JOINED_AND_SEPARATE>;
> +
> +// Mix-ins for adding optional attributes.
> +
> +class Alias<Option alias> { Option Alias = alias; }
> +class EnumName<string name> { string EnumName = name; }
> +class Flags<list<OptionFlag> flags> { list<OptionFlag> Flags = flags; }
> +class Group<OptionGroup group> { OptionGroup Group = group; }
> +class HelpText<string text> { string HelpText = text; }
> +class MetaVarName<string name> { string MetaVarName = name; }
> +
> +// Predefined options.
> +
> +// FIXME: Have generator validate that these appear in correct position (and
> +// aren't duplicated).
> +def INPUT : Option<[], "<input>", KIND_INPUT>;
> +def UNKNOWN : Option<[], "<unknown>", KIND_UNKNOWN>;
>
> Added: llvm/trunk/include/llvm/Option/OptSpecifier.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Option/OptSpecifier.h?rev=169344&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/Option/OptSpecifier.h (added)
> +++ llvm/trunk/include/llvm/Option/OptSpecifier.h Tue Dec  4 18:29:32 2012
> @@ -0,0 +1,39 @@
> +//===--- OptSpecifier.h - Option Specifiers ---------------------*- C++ -*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_SUPPORT_OPTSPECIFIER_H
> +#define LLVM_SUPPORT_OPTSPECIFIER_H
> +
> +namespace llvm {
> +namespace opt {
> +  class Option;
> +
> +  /// OptSpecifier - Wrapper class for abstracting references to option IDs.
> +  class OptSpecifier {
> +    unsigned ID;
> +
> +  private:
> +    explicit OptSpecifier(bool); // DO NOT IMPLEMENT
> +
> +  public:
> +    OptSpecifier() : ID(0) {}
> +    /*implicit*/ OptSpecifier(unsigned _ID) : ID(_ID) {}
> +    /*implicit*/ OptSpecifier(const Option *Opt);
> +
> +    bool isValid() const { return ID != 0; }
> +
> +    unsigned getID() const { return ID; }
> +
> +    bool operator==(OptSpecifier Opt) const { return ID == Opt.getID(); }
> +    bool operator!=(OptSpecifier Opt) const { return !(*this == Opt); }
> +  };
> +}
> +}
> +
> +#endif
>
> Added: llvm/trunk/include/llvm/Option/OptTable.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Option/OptTable.h?rev=169344&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/Option/OptTable.h (added)
> +++ llvm/trunk/include/llvm/Option/OptTable.h Tue Dec  4 18:29:32 2012
> @@ -0,0 +1,161 @@
> +//===--- OptTable.h - Option Table ------------------------------*- C++ -*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_SUPPORT_OPTTABLE_H
> +#define LLVM_SUPPORT_OPTTABLE_H
> +
> +#include "llvm/ADT/StringSet.h"
> +#include "llvm/Option/OptSpecifier.h"
> +
> +namespace llvm {
> +class raw_ostream;
> +namespace opt {
> +class Arg;
> +class ArgList;
> +class InputArgList;
> +class Option;
> +
> +/// \brief Provide access to the Option info table.
> +///
> +/// The OptTable class provides a layer of indirection which allows Option
> +/// instance to be created lazily. In the common case, only a few options will
> +/// be needed at runtime; the OptTable class maintains enough information to
> +/// parse command lines without instantiating Options, while letting other
> +/// parts of the driver still use Option instances where convenient.
> +class OptTable {
> +public:
> +  /// \brief Entry for a single option instance in the option data table.
> +  struct Info {
> +    /// A null terminated array of prefix strings to apply to name while
> +    /// matching.
> +    const char *const *Prefixes;
> +    const char *Name;
> +    const char *HelpText;
> +    const char *MetaVar;
> +    unsigned ID;
> +    unsigned char Kind;
> +    unsigned char Param;
> +    unsigned short Flags;
> +    unsigned short GroupID;
> +    unsigned short AliasID;
> +  };
> +
> +private:
> +  /// \brief The static option information table.
> +  const Info *OptionInfos;
> +  unsigned NumOptionInfos;
> +
> +  unsigned TheInputOptionID;
> +  unsigned TheUnknownOptionID;
> +
> +  /// The index of the first option which can be parsed (i.e., is not a
> +  /// special option like 'input' or 'unknown', and is not an option group).
> +  unsigned FirstSearchableIndex;
> +
> +  /// The union of all option prefixes. If an argument does not begin with
> +  /// one of these, it is an input.
> +  StringSet<> PrefixesUnion;
> +  std::string PrefixChars;
> +
> +private:
> +  const Info &getInfo(OptSpecifier Opt) const {
> +    unsigned id = Opt.getID();
> +    assert(id > 0 && id - 1 < getNumOptions() && "Invalid Option ID.");
> +    return OptionInfos[id - 1];
> +  }
> +
> +protected:
> +  OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos);
> +public:
> +  ~OptTable();
> +
> +  /// \brief Return the total number of option classes.
> +  unsigned getNumOptions() const { return NumOptionInfos; }
> +
> +  /// \brief Get the given Opt's Option instance, lazily creating it
> +  /// if necessary.
> +  ///
> +  /// \return The option, or null for the INVALID option id.
> +  const Option getOption(OptSpecifier Opt) const;
> +
> +  /// \brief Lookup the name of the given option.
> +  const char *getOptionName(OptSpecifier id) const {
> +    return getInfo(id).Name;
> +  }
> +
> +  /// \brief Get the kind of the given option.
> +  unsigned getOptionKind(OptSpecifier id) const {
> +    return getInfo(id).Kind;
> +  }
> +
> +  /// \brief Get the group id for the given option.
> +  unsigned getOptionGroupID(OptSpecifier id) const {
> +    return getInfo(id).GroupID;
> +  }
> +
> +  /// \brief Should the help for the given option be hidden by default.
> +  bool isOptionHelpHidden(OptSpecifier id) const;
> +
> +  /// \brief Get the help text to use to describe this option.
> +  const char *getOptionHelpText(OptSpecifier id) const {
> +    return getInfo(id).HelpText;
> +  }
> +
> +  /// \brief Get the meta-variable name to use when describing
> +  /// this options values in the help text.
> +  const char *getOptionMetaVar(OptSpecifier id) const {
> +    return getInfo(id).MetaVar;
> +  }
> +
> +  /// \brief Parse a single argument; returning the new argument and
> +  /// updating Index.
> +  ///
> +  /// \param [in,out] Index - The current parsing position in the argument
> +  /// string list; on return this will be the index of the next argument
> +  /// string to parse.
> +  ///
> +  /// \return The parsed argument, or 0 if the argument is missing values
> +  /// (in which case Index still points at the conceptual next argument string
> +  /// to parse).
> +  Arg *ParseOneArg(const ArgList &Args, unsigned &Index) const;
> +
> +  /// \brief Parse an list of arguments into an InputArgList.
> +  ///
> +  /// The resulting InputArgList will reference the strings in [\p ArgBegin,
> +  /// \p ArgEnd), and their lifetime should extend past that of the returned
> +  /// InputArgList.
> +  ///
> +  /// The only error that can occur in this routine is if an argument is
> +  /// missing values; in this case \p MissingArgCount will be non-zero.
> +  ///
> +  /// \param ArgBegin - The beginning of the argument vector.
> +  /// \param ArgEnd - The end of the argument vector.
> +  /// \param MissingArgIndex - On error, the index of the option which could
> +  /// not be parsed.
> +  /// \param MissingArgCount - On error, the number of missing options.
> +  /// \return An InputArgList; on error this will contain all the options
> +  /// which could be parsed.
> +  InputArgList *ParseArgs(const char* const *ArgBegin,
> +                          const char* const *ArgEnd,
> +                          unsigned &MissingArgIndex,
> +                          unsigned &MissingArgCount) const;
> +
> +  /// \brief Render the help text for an option table.
> +  ///
> +  /// \param OS - The stream to write the help text to.
> +  /// \param Name - The name to use in the usage line.
> +  /// \param Title - The title to use in the usage line.
> +  /// \param ShowHidden - Whether help-hidden arguments should be shown.
> +  void PrintHelp(raw_ostream &OS, const char *Name,
> +                  const char *Title, bool ShowHidden = false) const;
> +};
> +} // end namespace opt
> +} // end namespace llvm
> +
> +#endif
>
> Added: llvm/trunk/include/llvm/Option/Option.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Option/Option.h?rev=169344&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/Option/Option.h (added)
> +++ llvm/trunk/include/llvm/Option/Option.h Tue Dec  4 18:29:32 2012
> @@ -0,0 +1,193 @@
> +//===--- Option.h - Abstract Driver Options ---------------------*- C++ -*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_SUPPORT_OPTION_H_
> +#define LLVM_SUPPORT_OPTION_H_
> +
> +#include "llvm/ADT/StringRef.h"
> +#include "llvm/ADT/SmallVector.h"
> +#include "llvm/Option/OptTable.h"
> +#include "llvm/Support/ErrorHandling.h"
> +
> +namespace llvm {
> +namespace opt {
> +class Arg;
> +class ArgList;
> +/// ArgStringList - Type used for constructing argv lists for subprocesses.
> +typedef SmallVector<const char*, 16> ArgStringList;
> +
> +/// Base flags for all options. Custom flags may be added after.
> +enum DriverFlag {
> +  HelpHidden       = (1 << 0),
> +  RenderAsInput    = (1 << 1),
> +  RenderJoined     = (1 << 2),
> +  RenderSeparate   = (1 << 3)
> +};
> +
> +/// Option - Abstract representation for a single form of driver
> +/// argument.
> +///
> +/// An Option class represents a form of option that the driver
> +/// takes, for example how many arguments the option has and how
> +/// they can be provided. Individual option instances store
> +/// additional information about what group the option is a member
> +/// of (if any), if the option is an alias, and a number of
> +/// flags. At runtime the driver parses the command line into
> +/// concrete Arg instances, each of which corresponds to a
> +/// particular Option instance.
> +class Option {
> +public:
> +  enum OptionClass {
> +    GroupClass = 0,
> +    InputClass,
> +    UnknownClass,
> +    FlagClass,
> +    JoinedClass,
> +    SeparateClass,
> +    CommaJoinedClass,
> +    MultiArgClass,
> +    JoinedOrSeparateClass,
> +    JoinedAndSeparateClass
> +  };
> +
> +  enum RenderStyleKind {
> +    RenderCommaJoinedStyle,
> +    RenderJoinedStyle,
> +    RenderSeparateStyle,
> +    RenderValuesStyle
> +  };
> +
> +protected:
> +  const OptTable::Info *Info;
> +  const OptTable *Owner;
> +
> +public:
> +  Option(const OptTable::Info *Info, const OptTable *Owner);
> +  ~Option();
> +
> +  bool isValid() const {
> +    return Info != 0;
> +  }
> +
> +  unsigned getID() const {
> +    assert(Info && "Must have a valid info!");
> +    return Info->ID;
> +  }
> +
> +  OptionClass getKind() const {
> +    assert(Info && "Must have a valid info!");
> +    return OptionClass(Info->Kind);
> +  }
> +
> +  /// \brief Get the name of this option without any prefix.
> +  StringRef getName() const {
> +    assert(Info && "Must have a valid info!");
> +    return Info->Name;
> +  }
> +
> +  const Option getGroup() const {
> +    assert(Info && "Must have a valid info!");
> +    assert(Owner && "Must have a valid owner!");
> +    return Owner->getOption(Info->GroupID);
> +  }
> +
> +  const Option getAlias() const {
> +    assert(Info && "Must have a valid info!");
> +    assert(Owner && "Must have a valid owner!");
> +    return Owner->getOption(Info->AliasID);
> +  }
> +
> +  /// \brief Get the default prefix for this option.
> +  StringRef getPrefix() const {
> +    const char *Prefix = *Info->Prefixes;
> +    return Prefix ? Prefix : StringRef();
> +  }
> +
> +  /// \brief Get the name of this option with the default prefix.
> +  std::string getPrefixedName() const {
> +    std::string Ret = getPrefix();
> +    Ret += getName();
> +    return Ret;
> +  }
> +
> +  unsigned getNumArgs() const { return Info->Param; }
> +
> +  bool hasNoOptAsInput() const { return Info->Flags & RenderAsInput;}
> +
> +  RenderStyleKind getRenderStyle() const {
> +    if (Info->Flags & RenderJoined)
> +      return RenderJoinedStyle;
> +    if (Info->Flags & RenderSeparate)
> +      return RenderSeparateStyle;
> +    switch (getKind()) {
> +    case GroupClass:
> +    case InputClass:
> +    case UnknownClass:
> +      return RenderValuesStyle;
> +    case JoinedClass:
> +    case JoinedAndSeparateClass:
> +      return RenderJoinedStyle;
> +    case CommaJoinedClass:
> +      return RenderCommaJoinedStyle;
> +    case FlagClass:
> +    case SeparateClass:
> +    case MultiArgClass:
> +    case JoinedOrSeparateClass:
> +      return RenderSeparateStyle;
> +    }
> +    llvm_unreachable("Unexpected kind!");
> +  }
> +
> +  /// Test if this option has the flag \a Val.
> +  bool hasFlag(unsigned Val) const {
> +    return Info->Flags & Val;
> +  }
> +
> +  /// getUnaliasedOption - Return the final option this option
> +  /// aliases (itself, if the option has no alias).
> +  const Option getUnaliasedOption() const {
> +    const Option Alias = getAlias();
> +    if (Alias.isValid()) return Alias.getUnaliasedOption();
> +    return *this;
> +  }
> +
> +  /// getRenderName - Return the name to use when rendering this
> +  /// option.
> +  StringRef getRenderName() const {
> +    return getUnaliasedOption().getName();
> +  }
> +
> +  /// matches - Predicate for whether this option is part of the
> +  /// given option (which may be a group).
> +  ///
> +  /// Note that matches against options which are an alias should never be
> +  /// done -- aliases do not participate in matching and so such a query will
> +  /// always be false.
> +  bool matches(OptSpecifier ID) const;
> +
> +  /// accept - Potentially accept the current argument, returning a
> +  /// new Arg instance, or 0 if the option does not accept this
> +  /// argument (or the argument is missing values).
> +  ///
> +  /// If the option accepts the current argument, accept() sets
> +  /// Index to the position where argument parsing should resume
> +  /// (even if the argument is missing values).
> +  ///
> +  /// \parm ArgSize The number of bytes taken up by the matched Option prefix
> +  ///               and name. This is used to determine where joined values
> +  ///               start.
> +  Arg *accept(const ArgList &Args, unsigned &Index, unsigned ArgSize) const;
> +
> +  void dump() const;
> +};
> +
> +} // end namespace opt
> +} // end namespace llvm
> +
> +#endif
>
> Modified: llvm/trunk/lib/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CMakeLists.txt?rev=169344&r1=169343&r2=169344&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CMakeLists.txt (original)
> +++ llvm/trunk/lib/CMakeLists.txt Tue Dec  4 18:29:32 2012
> @@ -8,6 +8,7 @@
>  add_subdirectory(Analysis)
>  add_subdirectory(MC)
>  add_subdirectory(Object)
> +add_subdirectory(Option)
>  add_subdirectory(DebugInfo)
>  add_subdirectory(ExecutionEngine)
>  add_subdirectory(Target)
>
> Modified: llvm/trunk/lib/LLVMBuild.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LLVMBuild.txt?rev=169344&r1=169343&r2=169344&view=diff
> ==============================================================================
> --- llvm/trunk/lib/LLVMBuild.txt (original)
> +++ llvm/trunk/lib/LLVMBuild.txt Tue Dec  4 18:29:32 2012
> @@ -16,7 +16,7 @@
>  ;===------------------------------------------------------------------------===;
>
>  [common]
> -subdirectories = Analysis Archive AsmParser Bitcode CodeGen DebugInfo ExecutionEngine Linker MC Object Support TableGen Target Transforms VMCore
> +subdirectories = Analysis Archive AsmParser Bitcode CodeGen DebugInfo ExecutionEngine Linker MC Object Option Support TableGen Target Transforms VMCore
>
>  [component_0]
>  type = Group
>
> Modified: llvm/trunk/lib/Makefile
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Makefile?rev=169344&r1=169343&r2=169344&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Makefile (original)
> +++ llvm/trunk/lib/Makefile Tue Dec  4 18:29:32 2012
> @@ -11,7 +11,7 @@
>  include $(LEVEL)/Makefile.config
>
>  PARALLEL_DIRS := VMCore AsmParser Bitcode Archive Analysis Transforms CodeGen \
> -                Target ExecutionEngine Linker MC Object DebugInfo
> +                Target ExecutionEngine Linker MC Object Option DebugInfo
>
>  include $(LEVEL)/Makefile.common
>
>
> Added: llvm/trunk/lib/Option/Arg.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Option/Arg.cpp?rev=169344&view=auto
> ==============================================================================
> --- llvm/trunk/lib/Option/Arg.cpp (added)
> +++ llvm/trunk/lib/Option/Arg.cpp Tue Dec  4 18:29:32 2012
> @@ -0,0 +1,123 @@
> +//===--- Arg.cpp - Argument Implementations -------------------------------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "llvm/Option/Arg.h"
> +
> +#include "llvm/ADT/SmallString.h"
> +#include "llvm/ADT/Twine.h"
> +#include "llvm/Option/ArgList.h"
> +#include "llvm/Option/Option.h"
> +#include "llvm/Support/raw_ostream.h"
> +
> +using namespace llvm;
> +using namespace llvm::opt;
> +
> +Arg::Arg(const Option _Opt, StringRef S, unsigned _Index, const Arg *_BaseArg)
> +  : Opt(_Opt), BaseArg(_BaseArg), Spelling(S), Index(_Index),
> +    Claimed(false), OwnsValues(false) {
> +}
> +
> +Arg::Arg(const Option _Opt, StringRef S, unsigned _Index,
> +         const char *Value0, const Arg *_BaseArg)
> +  : Opt(_Opt), BaseArg(_BaseArg), Spelling(S), Index(_Index),
> +    Claimed(false), OwnsValues(false) {
> +  Values.push_back(Value0);
> +}
> +
> +Arg::Arg(const Option _Opt, StringRef S, unsigned _Index,
> +         const char *Value0, const char *Value1, const Arg *_BaseArg)
> +  : Opt(_Opt), BaseArg(_BaseArg), Spelling(S), Index(_Index),
> +    Claimed(false), OwnsValues(false) {
> +  Values.push_back(Value0);
> +  Values.push_back(Value1);
> +}
> +
> +Arg::~Arg() {
> +  if (OwnsValues) {
> +    for (unsigned i = 0, e = Values.size(); i != e; ++i)
> +      delete[] Values[i];
> +  }
> +}
> +
> +void Arg::dump() const {
> +  llvm::errs() << "<";
> +
> +  llvm::errs() << " Opt:";
> +  Opt.dump();
> +
> +  llvm::errs() << " Index:" << Index;
> +
> +  llvm::errs() << " Values: [";
> +  for (unsigned i = 0, e = Values.size(); i != e; ++i) {
> +    if (i) llvm::errs() << ", ";
> +    llvm::errs() << "'" << Values[i] << "'";
> +  }
> +
> +  llvm::errs() << "]>\n";
> +}
> +
> +std::string Arg::getAsString(const ArgList &Args) const {
> +  SmallString<256> Res;
> +  llvm::raw_svector_ostream OS(Res);
> +
> +  ArgStringList ASL;
> +  render(Args, ASL);
> +  for (ArgStringList::iterator
> +         it = ASL.begin(), ie = ASL.end(); it != ie; ++it) {
> +    if (it != ASL.begin())
> +      OS << ' ';
> +    OS << *it;
> +  }
> +
> +  return OS.str();
> +}
> +
> +void Arg::renderAsInput(const ArgList &Args, ArgStringList &Output) const {
> +  if (!getOption().hasNoOptAsInput()) {
> +    render(Args, Output);
> +    return;
> +  }
> +
> +  for (unsigned i = 0, e = getNumValues(); i != e; ++i)
> +    Output.push_back(getValue(i));
> +}
> +
> +void Arg::render(const ArgList &Args, ArgStringList &Output) const {
> +  switch (getOption().getRenderStyle()) {
> +  case Option::RenderValuesStyle:
> +    for (unsigned i = 0, e = getNumValues(); i != e; ++i)
> +      Output.push_back(getValue(i));
> +    break;
> +
> +  case Option::RenderCommaJoinedStyle: {
> +    SmallString<256> Res;
> +    llvm::raw_svector_ostream OS(Res);
> +    OS << getSpelling();
> +    for (unsigned i = 0, e = getNumValues(); i != e; ++i) {
> +      if (i) OS << ',';
> +      OS << getValue(i);
> +    }
> +    Output.push_back(Args.MakeArgString(OS.str()));
> +    break;
> +  }
> +
> + case Option::RenderJoinedStyle:
> +    Output.push_back(Args.GetOrMakeJoinedArgString(
> +                       getIndex(), getSpelling(), getValue(0)));
> +    for (unsigned i = 1, e = getNumValues(); i != e; ++i)
> +      Output.push_back(getValue(i));
> +    break;
> +
> +  case Option::RenderSeparateStyle:
> +    Output.push_back(Args.MakeArgString(getSpelling()));
> +    for (unsigned i = 0, e = getNumValues(); i != e; ++i)
> +      Output.push_back(getValue(i));
> +    break;
> +  }
> +}
>
> Added: llvm/trunk/lib/Option/ArgList.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Option/ArgList.cpp?rev=169344&view=auto
> ==============================================================================
> --- llvm/trunk/lib/Option/ArgList.cpp (added)
> +++ llvm/trunk/lib/Option/ArgList.cpp Tue Dec  4 18:29:32 2012
> @@ -0,0 +1,386 @@
> +//===--- ArgList.cpp - Argument List Management ---------------------------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "llvm/Option/ArgList.h"
> +
> +#include "llvm/ADT/SmallString.h"
> +#include "llvm/ADT/Twine.h"
> +#include "llvm/Option/Arg.h"
> +#include "llvm/Option/Option.h"
> +#include "llvm/Support/raw_ostream.h"
> +
> +using namespace llvm;
> +using namespace llvm::opt;
> +
> +void arg_iterator::SkipToNextArg() {
> +  for (; Current != Args.end(); ++Current) {
> +    // Done if there are no filters.
> +    if (!Id0.isValid())
> +      break;
> +
> +    // Otherwise require a match.
> +    const Option &O = (*Current)->getOption();
> +    if (O.matches(Id0) ||
> +        (Id1.isValid() && O.matches(Id1)) ||
> +        (Id2.isValid() && O.matches(Id2)))
> +      break;
> +  }
> +}
> +
> +//
> +
> +ArgList::ArgList() {
> +}
> +
> +ArgList::~ArgList() {
> +}
> +
> +void ArgList::append(Arg *A) {
> +  Args.push_back(A);
> +}
> +
> +void ArgList::eraseArg(OptSpecifier Id) {
> +  for (iterator it = begin(), ie = end(); it != ie; ) {
> +    if ((*it)->getOption().matches(Id)) {
> +      it = Args.erase(it);
> +      ie = end();
> +    } else {
> +      ++it;
> +    }
> +  }
> +}
> +
> +Arg *ArgList::getLastArgNoClaim(OptSpecifier Id) const {
> +  // FIXME: Make search efficient?
> +  for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it)
> +    if ((*it)->getOption().matches(Id))
> +      return *it;
> +  return 0;
> +}
> +
> +Arg *ArgList::getLastArg(OptSpecifier Id) const {
> +  Arg *Res = 0;
> +  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
> +    if ((*it)->getOption().matches(Id)) {
> +      Res = *it;
> +      Res->claim();
> +    }
> +  }
> +
> +  return Res;
> +}
> +
> +Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1) const {
> +  Arg *Res = 0;
> +  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
> +    if ((*it)->getOption().matches(Id0) ||
> +        (*it)->getOption().matches(Id1)) {
> +      Res = *it;
> +      Res->claim();
> +
> +    }
> +  }
> +
> +  return Res;
> +}
> +
> +Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
> +                         OptSpecifier Id2) const {
> +  Arg *Res = 0;
> +  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
> +    if ((*it)->getOption().matches(Id0) ||
> +        (*it)->getOption().matches(Id1) ||
> +        (*it)->getOption().matches(Id2)) {
> +      Res = *it;
> +      Res->claim();
> +    }
> +  }
> +
> +  return Res;
> +}
> +
> +Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
> +                         OptSpecifier Id2, OptSpecifier Id3) const {
> +  Arg *Res = 0;
> +  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
> +    if ((*it)->getOption().matches(Id0) ||
> +        (*it)->getOption().matches(Id1) ||
> +        (*it)->getOption().matches(Id2) ||
> +        (*it)->getOption().matches(Id3)) {
> +      Res = *it;
> +      Res->claim();
> +    }
> +  }
> +
> +  return Res;
> +}
> +
> +Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
> +                         OptSpecifier Id2, OptSpecifier Id3,
> +                         OptSpecifier Id4) const {
> +  Arg *Res = 0;
> +  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
> +    if ((*it)->getOption().matches(Id0) ||
> +        (*it)->getOption().matches(Id1) ||
> +        (*it)->getOption().matches(Id2) ||
> +        (*it)->getOption().matches(Id3) ||
> +        (*it)->getOption().matches(Id4)) {
> +      Res = *it;
> +      Res->claim();
> +    }
> +  }
> +
> +  return Res;
> +}
> +
> +Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
> +                         OptSpecifier Id2, OptSpecifier Id3,
> +                         OptSpecifier Id4, OptSpecifier Id5) const {
> +  Arg *Res = 0;
> +  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
> +    if ((*it)->getOption().matches(Id0) ||
> +        (*it)->getOption().matches(Id1) ||
> +        (*it)->getOption().matches(Id2) ||
> +        (*it)->getOption().matches(Id3) ||
> +        (*it)->getOption().matches(Id4) ||
> +        (*it)->getOption().matches(Id5)) {
> +      Res = *it;
> +      Res->claim();
> +    }
> +  }
> +
> +  return Res;
> +}
> +
> +Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
> +                         OptSpecifier Id2, OptSpecifier Id3,
> +                         OptSpecifier Id4, OptSpecifier Id5,
> +                         OptSpecifier Id6) const {
> +  Arg *Res = 0;
> +  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
> +    if ((*it)->getOption().matches(Id0) ||
> +        (*it)->getOption().matches(Id1) ||
> +        (*it)->getOption().matches(Id2) ||
> +        (*it)->getOption().matches(Id3) ||
> +        (*it)->getOption().matches(Id4) ||
> +        (*it)->getOption().matches(Id5) ||
> +        (*it)->getOption().matches(Id6)) {
> +      Res = *it;
> +      Res->claim();
> +    }
> +  }
> +
> +  return Res;
> +}
> +
> +Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
> +                         OptSpecifier Id2, OptSpecifier Id3,
> +                         OptSpecifier Id4, OptSpecifier Id5,
> +                         OptSpecifier Id6, OptSpecifier Id7) const {
> +  Arg *Res = 0;
> +  for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
> +    if ((*it)->getOption().matches(Id0) ||
> +        (*it)->getOption().matches(Id1) ||
> +        (*it)->getOption().matches(Id2) ||
> +        (*it)->getOption().matches(Id3) ||
> +        (*it)->getOption().matches(Id4) ||
> +        (*it)->getOption().matches(Id5) ||
> +        (*it)->getOption().matches(Id6) ||
> +        (*it)->getOption().matches(Id7)) {
> +      Res = *it;
> +      Res->claim();
> +    }
> +  }
> +
> +  return Res;
> +}
> +
> +bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const {
> +  if (Arg *A = getLastArg(Pos, Neg))
> +    return A->getOption().matches(Pos);
> +  return Default;
> +}
> +
> +StringRef ArgList::getLastArgValue(OptSpecifier Id,
> +                                         StringRef Default) const {
> +  if (Arg *A = getLastArg(Id))
> +    return A->getValue();
> +  return Default;
> +}
> +
> +std::vector<std::string> ArgList::getAllArgValues(OptSpecifier Id) const {
> +  SmallVector<const char *, 16> Values;
> +  AddAllArgValues(Values, Id);
> +  return std::vector<std::string>(Values.begin(), Values.end());
> +}
> +
> +void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const {
> +  if (Arg *A = getLastArg(Id)) {
> +    A->claim();
> +    A->render(*this, Output);
> +  }
> +}
> +
> +void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
> +                         OptSpecifier Id1, OptSpecifier Id2) const {
> +  for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
> +         ie = filtered_end(); it != ie; ++it) {
> +    (*it)->claim();
> +    (*it)->render(*this, Output);
> +  }
> +}
> +
> +void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
> +                              OptSpecifier Id1, OptSpecifier Id2) const {
> +  for (arg_iterator it = filtered_begin(Id0, Id1, Id2),
> +         ie = filtered_end(); it != ie; ++it) {
> +    (*it)->claim();
> +    for (unsigned i = 0, e = (*it)->getNumValues(); i != e; ++i)
> +      Output.push_back((*it)->getValue(i));
> +  }
> +}
> +
> +void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
> +                                   const char *Translation,
> +                                   bool Joined) const {
> +  for (arg_iterator it = filtered_begin(Id0),
> +         ie = filtered_end(); it != ie; ++it) {
> +    (*it)->claim();
> +
> +    if (Joined) {
> +      Output.push_back(MakeArgString(StringRef(Translation) +
> +                                     (*it)->getValue(0)));
> +    } else {
> +      Output.push_back(Translation);
> +      Output.push_back((*it)->getValue(0));
> +    }
> +  }
> +}
> +
> +void ArgList::ClaimAllArgs(OptSpecifier Id0) const {
> +  for (arg_iterator it = filtered_begin(Id0),
> +         ie = filtered_end(); it != ie; ++it)
> +    (*it)->claim();
> +}
> +
> +void ArgList::ClaimAllArgs() const {
> +  for (const_iterator it = begin(), ie = end(); it != ie; ++it)
> +    if (!(*it)->isClaimed())
> +      (*it)->claim();
> +}
> +
> +const char *ArgList::MakeArgString(const Twine &T) const {
> +  SmallString<256> Str;
> +  T.toVector(Str);
> +  return MakeArgString(Str.str());
> +}
> +
> +const char *ArgList::GetOrMakeJoinedArgString(unsigned Index,
> +                                              StringRef LHS,
> +                                              StringRef RHS) const {
> +  StringRef Cur = getArgString(Index);
> +  if (Cur.size() == LHS.size() + RHS.size() &&
> +      Cur.startswith(LHS) && Cur.endswith(RHS))
> +    return Cur.data();
> +
> +  return MakeArgString(LHS + RHS);
> +}
> +
> +//
> +
> +InputArgList::InputArgList(const char* const *ArgBegin,
> +                           const char* const *ArgEnd)
> +  : NumInputArgStrings(ArgEnd - ArgBegin) {
> +  ArgStrings.append(ArgBegin, ArgEnd);
> +}
> +
> +InputArgList::~InputArgList() {
> +  // An InputArgList always owns its arguments.
> +  for (iterator it = begin(), ie = end(); it != ie; ++it)
> +    delete *it;
> +}
> +
> +unsigned InputArgList::MakeIndex(StringRef String0) const {
> +  unsigned Index = ArgStrings.size();
> +
> +  // Tuck away so we have a reliable const char *.
> +  SynthesizedStrings.push_back(String0);
> +  ArgStrings.push_back(SynthesizedStrings.back().c_str());
> +
> +  return Index;
> +}
> +
> +unsigned InputArgList::MakeIndex(StringRef String0,
> +                                 StringRef String1) const {
> +  unsigned Index0 = MakeIndex(String0);
> +  unsigned Index1 = MakeIndex(String1);
> +  assert(Index0 + 1 == Index1 && "Unexpected non-consecutive indices!");
> +  (void) Index1;
> +  return Index0;
> +}
> +
> +const char *InputArgList::MakeArgString(StringRef Str) const {
> +  return getArgString(MakeIndex(Str));
> +}
> +
> +//
> +
> +DerivedArgList::DerivedArgList(const InputArgList &_BaseArgs)
> +  : BaseArgs(_BaseArgs) {
> +}
> +
> +DerivedArgList::~DerivedArgList() {
> +  // We only own the arguments we explicitly synthesized.
> +  for (iterator it = SynthesizedArgs.begin(), ie = SynthesizedArgs.end();
> +       it != ie; ++it)
> +    delete *it;
> +}
> +
> +const char *DerivedArgList::MakeArgString(StringRef Str) const {
> +  return BaseArgs.MakeArgString(Str);
> +}
> +
> +Arg *DerivedArgList::MakeFlagArg(const Arg *BaseArg, const Option Opt) const {
> +  Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) +
> +                                               Twine(Opt.getName())),
> +                   BaseArgs.MakeIndex(Opt.getName()), BaseArg);
> +  SynthesizedArgs.push_back(A);
> +  return A;
> +}
> +
> +Arg *DerivedArgList::MakePositionalArg(const Arg *BaseArg, const Option Opt,
> +                                       StringRef Value) const {
> +  unsigned Index = BaseArgs.MakeIndex(Value);
> +  Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) +
> +                                               Twine(Opt.getName())),
> +                   Index, BaseArgs.getArgString(Index), BaseArg);
> +  SynthesizedArgs.push_back(A);
> +  return A;
> +}
> +
> +Arg *DerivedArgList::MakeSeparateArg(const Arg *BaseArg, const Option Opt,
> +                                     StringRef Value) const {
> +  unsigned Index = BaseArgs.MakeIndex(Opt.getName(), Value);
> +  Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) +
> +                                               Twine(Opt.getName())),
> +                   Index, BaseArgs.getArgString(Index + 1), BaseArg);
> +  SynthesizedArgs.push_back(A);
> +  return A;
> +}
> +
> +Arg *DerivedArgList::MakeJoinedArg(const Arg *BaseArg, const Option Opt,
> +                                   StringRef Value) const {
> +  unsigned Index = BaseArgs.MakeIndex(Opt.getName().str() + Value.str());
> +  Arg *A = new Arg(Opt, ArgList::MakeArgString(Twine(Opt.getPrefix()) +
> +                                               Twine(Opt.getName())), Index,
> +                   BaseArgs.getArgString(Index) + Opt.getName().size(),
> +                   BaseArg);
> +  SynthesizedArgs.push_back(A);
> +  return A;
> +}
>
> Added: llvm/trunk/lib/Option/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Option/CMakeLists.txt?rev=169344&view=auto
> ==============================================================================
> --- llvm/trunk/lib/Option/CMakeLists.txt (added)
> +++ llvm/trunk/lib/Option/CMakeLists.txt Tue Dec  4 18:29:32 2012
> @@ -0,0 +1,8 @@
> +add_llvm_library(LLVMOption
> +  Arg.cpp
> +  ArgList.cpp
> +  Option.cpp
> +  OptTable.cpp
> +  )
> +
> +target_link_libraries(LLVMOption LLVMSupport)
>
> Copied: llvm/trunk/lib/Option/LLVMBuild.txt (from r169343, llvm/trunk/lib/LLVMBuild.txt)
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Option/LLVMBuild.txt?p2=llvm/trunk/lib/Option/LLVMBuild.txt&p1=llvm/trunk/lib/LLVMBuild.txt&r1=169343&r2=169344&rev=169344&view=diff
> ==============================================================================
> --- llvm/trunk/lib/LLVMBuild.txt (original)
> +++ llvm/trunk/lib/Option/LLVMBuild.txt Tue Dec  4 18:29:32 2012
> @@ -1,4 +1,4 @@
> -;===- ./lib/LLVMBuild.txt --------------------------------------*- Conf -*--===;
> +;===- ./lib/Option/LLVMBuild.txt -------------------------------*- Conf -*--===;
>  ;
>  ;                     The LLVM Compiler Infrastructure
>  ;
> @@ -15,10 +15,8 @@
>  ;
>  ;===------------------------------------------------------------------------===;
>
> -[common]
> -subdirectories = Analysis Archive AsmParser Bitcode CodeGen DebugInfo ExecutionEngine Linker MC Object Support TableGen Target Transforms VMCore
> -
>  [component_0]
> -type = Group
> -name = Libraries
> -parent = $ROOT
> +type = Library
> +name = Option
> +parent = Libraries
> +required_libraries = Support
>
> Copied: llvm/trunk/lib/Option/Makefile (from r169343, llvm/trunk/lib/Makefile)
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Option/Makefile?p2=llvm/trunk/lib/Option/Makefile&p1=llvm/trunk/lib/Makefile&r1=169343&r2=169344&rev=169344&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Makefile (original)
> +++ llvm/trunk/lib/Option/Makefile Tue Dec  4 18:29:32 2012
> @@ -1,4 +1,4 @@
> -##===- lib/Makefile ----------------------------------------*- Makefile -*-===##
> +##===- lib/Option/Makefile ---------------------------------*- Makefile -*-===##
>  #
>  #                     The LLVM Compiler Infrastructure
>  #
> @@ -6,12 +6,9 @@
>  # License. See LICENSE.TXT for details.
>  #
>  ##===----------------------------------------------------------------------===##
> -LEVEL = ..
>
> -include $(LEVEL)/Makefile.config
> -
> -PARALLEL_DIRS := VMCore AsmParser Bitcode Archive Analysis Transforms CodeGen \
> -                Target ExecutionEngine Linker MC Object DebugInfo
> +LEVEL = ../..
> +LIBRARYNAME = LLVMOption
> +BUILD_ARCHIVE := 1
>
>  include $(LEVEL)/Makefile.common
> -
>
> Added: llvm/trunk/lib/Option/OptTable.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Option/OptTable.cpp?rev=169344&view=auto
> ==============================================================================
> --- llvm/trunk/lib/Option/OptTable.cpp (added)
> +++ llvm/trunk/lib/Option/OptTable.cpp Tue Dec  4 18:29:32 2012
> @@ -0,0 +1,388 @@
> +//===--- OptTable.cpp - Option Table Implementation -----------------------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "llvm/Option/OptTable.h"
> +
> +#include "llvm/Option/Arg.h"
> +#include "llvm/Option/ArgList.h"
> +#include "llvm/Option/Option.h"
> +#include "llvm/Support/raw_ostream.h"
> +#include "llvm/Support/ErrorHandling.h"
> +#include <algorithm>
> +#include <map>
> +
> +using namespace llvm;
> +using namespace llvm::opt;
> +
> +// Ordering on Info. The ordering is *almost* lexicographic, with two
> +// exceptions. First, '\0' comes at the end of the alphabet instead of
> +// the beginning (thus options precede any other options which prefix
> +// them). Second, for options with the same name, the less permissive
> +// version should come first; a Flag option should precede a Joined
> +// option, for example.
> +
> +static int StrCmpOptionName(const char *A, const char *B) {
> +  char a = *A, b = *B;
> +  while (a == b) {
> +    if (a == '\0')
> +      return 0;
> +
> +    a = *++A;
> +    b = *++B;
> +  }
> +
> +  if (a == '\0') // A is a prefix of B.
> +    return 1;
> +  if (b == '\0') // B is a prefix of A.
> +    return -1;
> +
> +  // Otherwise lexicographic.
> +  return (a < b) ? -1 : 1;
> +}
> +
> +namespace llvm {
> +namespace opt {
> +
> +static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
> +  if (&A == &B)
> +    return false;
> +
> +  if (int N = StrCmpOptionName(A.Name, B.Name))
> +    return N == -1;
> +
> +  for (const char * const *APre = A.Prefixes,
> +                  * const *BPre = B.Prefixes;
> +                          *APre != 0 && *BPre != 0; ++APre, ++BPre) {
> +    if (int N = StrCmpOptionName(*APre, *BPre))
> +      return N == -1;
> +  }
> +
> +  // Names are the same, check that classes are in order; exactly one
> +  // should be joined, and it should succeed the other.
> +  assert(((A.Kind == Option::JoinedClass) ^ (B.Kind == Option::JoinedClass)) &&
> +         "Unexpected classes for options with same name.");
> +  return B.Kind == Option::JoinedClass;
> +}
> +
> +// Support lower_bound between info and an option name.
> +static inline bool operator<(const OptTable::Info &I, const char *Name) {
> +  return StrCmpOptionName(I.Name, Name) == -1;
> +}
> +static inline bool operator<(const char *Name, const OptTable::Info &I) {
> +  return StrCmpOptionName(Name, I.Name) == -1;
> +}
> +}
> +}
> +
> +OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {}
> +
> +OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos)
> +  : OptionInfos(_OptionInfos),
> +    NumOptionInfos(_NumOptionInfos),
> +    TheInputOptionID(0),
> +    TheUnknownOptionID(0),
> +    FirstSearchableIndex(0)
> +{
> +  // Explicitly zero initialize the error to work around a bug in array
> +  // value-initialization on MinGW with gcc 4.3.5.
> +
> +  // Find start of normal options.
> +  for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
> +    unsigned Kind = getInfo(i + 1).Kind;
> +    if (Kind == Option::InputClass) {
> +      assert(!TheInputOptionID && "Cannot have multiple input options!");
> +      TheInputOptionID = getInfo(i + 1).ID;
> +    } else if (Kind == Option::UnknownClass) {
> +      assert(!TheUnknownOptionID && "Cannot have multiple unknown options!");
> +      TheUnknownOptionID = getInfo(i + 1).ID;
> +    } else if (Kind != Option::GroupClass) {
> +      FirstSearchableIndex = i;
> +      break;
> +    }
> +  }
> +  assert(FirstSearchableIndex != 0 && "No searchable options?");
> +
> +#ifndef NDEBUG
> +  // Check that everything after the first searchable option is a
> +  // regular option class.
> +  for (unsigned i = FirstSearchableIndex, e = getNumOptions(); i != e; ++i) {
> +    Option::OptionClass Kind = (Option::OptionClass) getInfo(i + 1).Kind;
> +    assert((Kind != Option::InputClass && Kind != Option::UnknownClass &&
> +            Kind != Option::GroupClass) &&
> +           "Special options should be defined first!");
> +  }
> +
> +  // Check that options are in order.
> +  for (unsigned i = FirstSearchableIndex + 1, e = getNumOptions(); i != e; ++i){
> +    if (!(getInfo(i) < getInfo(i + 1))) {
> +      getOption(i).dump();
> +      getOption(i + 1).dump();
> +      llvm_unreachable("Options are not in order!");
> +    }
> +  }
> +#endif
> +
> +  // Build prefixes.
> +  for (unsigned i = FirstSearchableIndex + 1, e = getNumOptions() + 1;
> +                i != e; ++i) {
> +    if (const char *const *P = getInfo(i).Prefixes) {
> +      for (; *P != 0; ++P) {
> +        PrefixesUnion.insert(*P);
> +      }
> +    }
> +  }
> +
> +  // Build prefix chars.
> +  for (llvm::StringSet<>::const_iterator I = PrefixesUnion.begin(),
> +                                         E = PrefixesUnion.end(); I != E; ++I) {
> +    StringRef Prefix = I->getKey();
> +    for (StringRef::const_iterator C = Prefix.begin(), CE = Prefix.end();
> +                                   C != CE; ++C)
> +      if (std::find(PrefixChars.begin(), PrefixChars.end(), *C)
> +            == PrefixChars.end())
> +        PrefixChars.push_back(*C);
> +  }
> +}
> +
> +OptTable::~OptTable() {
> +}
> +
> +const Option OptTable::getOption(OptSpecifier Opt) const {
> +  unsigned id = Opt.getID();
> +  if (id == 0)
> +    return Option(0, 0);
> +  assert((unsigned) (id - 1) < getNumOptions() && "Invalid ID.");
> +  return Option(&getInfo(id), this);
> +}
> +
> +bool OptTable::isOptionHelpHidden(OptSpecifier id) const {
> +  return getInfo(id).Flags & HelpHidden;
> +}
> +
> +static bool isInput(const llvm::StringSet<> &Prefixes, StringRef Arg) {
> +  if (Arg == "-")
> +    return true;
> +  for (llvm::StringSet<>::const_iterator I = Prefixes.begin(),
> +                                         E = Prefixes.end(); I != E; ++I)
> +    if (Arg.startswith(I->getKey()))
> +      return false;
> +  return true;
> +}
> +
> +/// \returns Matched size. 0 means no match.
> +static unsigned matchOption(const OptTable::Info *I, StringRef Str) {
> +  for (const char * const *Pre = I->Prefixes; *Pre != 0; ++Pre) {
> +    StringRef Prefix(*Pre);
> +    if (Str.startswith(Prefix) && Str.substr(Prefix.size()).startswith(I->Name))
> +      return Prefix.size() + StringRef(I->Name).size();
> +  }
> +  return 0;
> +}
> +
> +Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index) const {
> +  unsigned Prev = Index;
> +  const char *Str = Args.getArgString(Index);
> +
> +  // Anything that doesn't start with PrefixesUnion is an input, as is '-'
> +  // itself.
> +  if (isInput(PrefixesUnion, Str))
> +    return new Arg(getOption(TheInputOptionID), Str, Index++, Str);
> +
> +  const Info *Start = OptionInfos + FirstSearchableIndex;
> +  const Info *End = OptionInfos + getNumOptions();
> +  StringRef Name = StringRef(Str).ltrim(PrefixChars);
> +
> +  // Search for the first next option which could be a prefix.
> +  Start = std::lower_bound(Start, End, Name.data());
> +
> +  // Options are stored in sorted order, with '\0' at the end of the
> +  // alphabet. Since the only options which can accept a string must
> +  // prefix it, we iteratively search for the next option which could
> +  // be a prefix.
> +  //
> +  // FIXME: This is searching much more than necessary, but I am
> +  // blanking on the simplest way to make it fast. We can solve this
> +  // problem when we move to TableGen.
> +  for (; Start != End; ++Start) {
> +    unsigned ArgSize = 0;
> +    // Scan for first option which is a proper prefix.
> +    for (; Start != End; ++Start)
> +      if ((ArgSize = matchOption(Start, Str)))
> +        break;
> +    if (Start == End)
> +      break;
> +
> +    // See if this option matches.
> +    if (Arg *A = Option(Start, this).accept(Args, Index, ArgSize))
> +      return A;
> +
> +    // Otherwise, see if this argument was missing values.
> +    if (Prev != Index)
> +      return 0;
> +  }
> +
> +  return new Arg(getOption(TheUnknownOptionID), Str, Index++, Str);
> +}
> +
> +InputArgList *OptTable::ParseArgs(const char* const *ArgBegin,
> +                                  const char* const *ArgEnd,
> +                                  unsigned &MissingArgIndex,
> +                                  unsigned &MissingArgCount) const {
> +  InputArgList *Args = new InputArgList(ArgBegin, ArgEnd);
> +
> +  // FIXME: Handle '@' args (or at least error on them).
> +
> +  MissingArgIndex = MissingArgCount = 0;
> +  unsigned Index = 0, End = ArgEnd - ArgBegin;
> +  while (Index < End) {
> +    // Ignore empty arguments (other things may still take them as arguments).
> +    if (Args->getArgString(Index)[0] == '\0') {
> +      ++Index;
> +      continue;
> +    }
> +
> +    unsigned Prev = Index;
> +    Arg *A = ParseOneArg(*Args, Index);
> +    assert(Index > Prev && "Parser failed to consume argument.");
> +
> +    // Check for missing argument error.
> +    if (!A) {
> +      assert(Index >= End && "Unexpected parser error.");
> +      assert(Index - Prev - 1 && "No missing arguments!");
> +      MissingArgIndex = Prev;
> +      MissingArgCount = Index - Prev - 1;
> +      break;
> +    }
> +
> +    Args->append(A);
> +  }
> +
> +  return Args;
> +}
> +
> +static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) {
> +  const Option O = Opts.getOption(Id);
> +  std::string Name = O.getPrefixedName();
> +
> +  // Add metavar, if used.
> +  switch (O.getKind()) {
> +  case Option::GroupClass: case Option::InputClass: case Option::UnknownClass:
> +    llvm_unreachable("Invalid option with help text.");
> +
> +  case Option::MultiArgClass:
> +    llvm_unreachable("Cannot print metavar for this kind of option.");
> +
> +  case Option::FlagClass:
> +    break;
> +
> +  case Option::SeparateClass: case Option::JoinedOrSeparateClass:
> +    Name += ' ';
> +    // FALLTHROUGH
> +  case Option::JoinedClass: case Option::CommaJoinedClass:
> +  case Option::JoinedAndSeparateClass:
> +    if (const char *MetaVarName = Opts.getOptionMetaVar(Id))
> +      Name += MetaVarName;
> +    else
> +      Name += "<value>";
> +    break;
> +  }
> +
> +  return Name;
> +}
> +
> +static void PrintHelpOptionList(raw_ostream &OS, StringRef Title,
> +                                std::vector<std::pair<std::string,
> +                                const char*> > &OptionHelp) {
> +  OS << Title << ":\n";
> +
> +  // Find the maximum option length.
> +  unsigned OptionFieldWidth = 0;
> +  for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
> +    // Skip titles.
> +    if (!OptionHelp[i].second)
> +      continue;
> +
> +    // Limit the amount of padding we are willing to give up for alignment.
> +    unsigned Length = OptionHelp[i].first.size();
> +    if (Length <= 23)
> +      OptionFieldWidth = std::max(OptionFieldWidth, Length);
> +  }
> +
> +  const unsigned InitialPad = 2;
> +  for (unsigned i = 0, e = OptionHelp.size(); i != e; ++i) {
> +    const std::string &Option = OptionHelp[i].first;
> +    int Pad = OptionFieldWidth - int(Option.size());
> +    OS.indent(InitialPad) << Option;
> +
> +    // Break on long option names.
> +    if (Pad < 0) {
> +      OS << "\n";
> +      Pad = OptionFieldWidth + InitialPad;
> +    }
> +    OS.indent(Pad + 1) << OptionHelp[i].second << '\n';
> +  }
> +}
> +
> +static const char *getOptionHelpGroup(const OptTable &Opts, OptSpecifier Id) {
> +  unsigned GroupID = Opts.getOptionGroupID(Id);
> +
> +  // If not in a group, return the default help group.
> +  if (!GroupID)
> +    return "OPTIONS";
> +
> +  // Abuse the help text of the option groups to store the "help group"
> +  // name.
> +  //
> +  // FIXME: Split out option groups.
> +  if (const char *GroupHelp = Opts.getOptionHelpText(GroupID))
> +    return GroupHelp;
> +
> +  // Otherwise keep looking.
> +  return getOptionHelpGroup(Opts, GroupID);
> +}
> +
> +void OptTable::PrintHelp(raw_ostream &OS, const char *Name,
> +                         const char *Title, bool ShowHidden) const {
> +  OS << "OVERVIEW: " << Title << "\n";
> +  OS << '\n';
> +  OS << "USAGE: " << Name << " [options] <inputs>\n";
> +  OS << '\n';
> +
> +  // Render help text into a map of group-name to a list of (option, help)
> +  // pairs.
> +  typedef std::map<std::string,
> +                 std::vector<std::pair<std::string, const char*> > > helpmap_ty;
> +  helpmap_ty GroupedOptionHelp;
> +
> +  for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
> +    unsigned Id = i + 1;
> +
> +    // FIXME: Split out option groups.
> +    if (getOptionKind(Id) == Option::GroupClass)
> +      continue;
> +
> +    if (!ShowHidden && isOptionHelpHidden(Id))
> +      continue;
> +
> +    if (const char *Text = getOptionHelpText(Id)) {
> +      const char *HelpGroup = getOptionHelpGroup(*this, Id);
> +      const std::string &OptName = getOptionHelpName(*this, Id);
> +      GroupedOptionHelp[HelpGroup].push_back(std::make_pair(OptName, Text));
> +    }
> +  }
> +
> +  for (helpmap_ty::iterator it = GroupedOptionHelp .begin(),
> +         ie = GroupedOptionHelp.end(); it != ie; ++it) {
> +    if (it != GroupedOptionHelp .begin())
> +      OS << "\n";
> +    PrintHelpOptionList(OS, it->first, it->second);
> +  }
> +
> +  OS.flush();
> +}
>
> Added: llvm/trunk/lib/Option/Option.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Option/Option.cpp?rev=169344&view=auto
> ==============================================================================
> --- llvm/trunk/lib/Option/Option.cpp (added)
> +++ llvm/trunk/lib/Option/Option.cpp Tue Dec  4 18:29:32 2012
> @@ -0,0 +1,204 @@
> +//===--- Option.cpp - Abstract Driver Options -----------------------------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "llvm/Option/Option.h"
> +
> +#include "llvm/ADT/Twine.h"
> +#include "llvm/Option/Arg.h"
> +#include "llvm/Option/ArgList.h"
> +#include "llvm/Support/raw_ostream.h"
> +#include "llvm/Support/ErrorHandling.h"
> +
> +#include <algorithm>
> +#include <cassert>
> +
> +using namespace llvm;
> +using namespace llvm::opt;
> +
> +Option::Option(const OptTable::Info *info, const OptTable *owner)
> +  : Info(info), Owner(owner) {
> +
> +  // Multi-level aliases are not supported, and alias options cannot
> +  // have groups. This just simplifies option tracking, it is not an
> +  // inherent limitation.
> +  assert((!Info || !getAlias().isValid() || (!getAlias().getAlias().isValid() &&
> +         !getGroup().isValid())) &&
> +         "Multi-level aliases and aliases with groups are unsupported.");
> +}
> +
> +Option::~Option() {
> +}
> +
> +void Option::dump() const {
> +  llvm::errs() << "<";
> +  switch (getKind()) {
> +#define P(N) case N: llvm::errs() << #N; break
> +    P(GroupClass);
> +    P(InputClass);
> +    P(UnknownClass);
> +    P(FlagClass);
> +    P(JoinedClass);
> +    P(SeparateClass);
> +    P(CommaJoinedClass);
> +    P(MultiArgClass);
> +    P(JoinedOrSeparateClass);
> +    P(JoinedAndSeparateClass);
> +#undef P
> +  }
> +
> +  llvm::errs() << " Prefixes:[";
> +  for (const char * const *Pre = Info->Prefixes; *Pre != 0; ++Pre) {
> +    llvm::errs() << '"' << *Pre << (*(Pre + 1) == 0 ? "\"" : "\", ");
> +  }
> +  llvm::errs() << ']';
> +
> +  llvm::errs() << " Name:\"" << getName() << '"';
> +
> +  const Option Group = getGroup();
> +  if (Group.isValid()) {
> +    llvm::errs() << " Group:";
> +    Group.dump();
> +  }
> +
> +  const Option Alias = getAlias();
> +  if (Alias.isValid()) {
> +    llvm::errs() << " Alias:";
> +    Alias.dump();
> +  }
> +
> +  if (getKind() == MultiArgClass)
> +    llvm::errs() << " NumArgs:" << getNumArgs();
> +
> +  llvm::errs() << ">\n";
> +}
> +
> +bool Option::matches(OptSpecifier Opt) const {
> +  // Aliases are never considered in matching, look through them.
> +  const Option Alias = getAlias();
> +  if (Alias.isValid())
> +    return Alias.matches(Opt);
> +
> +  // Check exact match.
> +  if (getID() == Opt.getID())
> +    return true;
> +
> +  const Option Group = getGroup();
> +  if (Group.isValid())
> +    return Group.matches(Opt);
> +  return false;
> +}
> +
> +Arg *Option::accept(const ArgList &Args,
> +                    unsigned &Index,
> +                    unsigned ArgSize) const {
> +  const Option &UnaliasedOption = getUnaliasedOption();
> +  StringRef Spelling;
> +  // If the option was an alias, get the spelling from the unaliased one.
> +  if (getID() == UnaliasedOption.getID()) {
> +    Spelling = StringRef(Args.getArgString(Index), ArgSize);
> +  } else {
> +    Spelling = Args.MakeArgString(Twine(UnaliasedOption.getPrefix()) +
> +                                  Twine(UnaliasedOption.getName()));
> +  }
> +
> +  switch (getKind()) {
> +  case FlagClass:
> +    if (ArgSize != strlen(Args.getArgString(Index)))
> +      return 0;
> +
> +    return new Arg(UnaliasedOption, Spelling, Index++);
> +  case JoinedClass: {
> +    const char *Value = Args.getArgString(Index) + ArgSize;
> +    return new Arg(UnaliasedOption, Spelling, Index++, Value);
> +  }
> +  case CommaJoinedClass: {
> +    // Always matches.
> +    const char *Str = Args.getArgString(Index) + ArgSize;
> +    Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
> +
> +    // Parse out the comma separated values.
> +    const char *Prev = Str;
> +    for (;; ++Str) {
> +      char c = *Str;
> +
> +      if (!c || c == ',') {
> +        if (Prev != Str) {
> +          char *Value = new char[Str - Prev + 1];
> +          memcpy(Value, Prev, Str - Prev);
> +          Value[Str - Prev] = '\0';
> +          A->getValues().push_back(Value);
> +        }
> +
> +        if (!c)
> +          break;
> +
> +        Prev = Str + 1;
> +      }
> +    }
> +    A->setOwnsValues(true);
> +
> +    return A;
> +  }
> +  case SeparateClass:
> +    // Matches iff this is an exact match.
> +    // FIXME: Avoid strlen.
> +    if (ArgSize != strlen(Args.getArgString(Index)))
> +      return 0;
> +
> +    Index += 2;
> +    if (Index > Args.getNumInputArgStrings())
> +      return 0;
> +
> +    return new Arg(UnaliasedOption, Spelling,
> +                   Index - 2, Args.getArgString(Index - 1));
> +  case MultiArgClass: {
> +    // Matches iff this is an exact match.
> +    // FIXME: Avoid strlen.
> +    if (ArgSize != strlen(Args.getArgString(Index)))
> +      return 0;
> +
> +    Index += 1 + getNumArgs();
> +    if (Index > Args.getNumInputArgStrings())
> +      return 0;
> +
> +    Arg *A = new Arg(UnaliasedOption, Spelling, Index - 1 - getNumArgs(),
> +                      Args.getArgString(Index - getNumArgs()));
> +    for (unsigned i = 1; i != getNumArgs(); ++i)
> +      A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
> +    return A;
> +  }
> +  case JoinedOrSeparateClass: {
> +    // If this is not an exact match, it is a joined arg.
> +    // FIXME: Avoid strlen.
> +    if (ArgSize != strlen(Args.getArgString(Index))) {
> +      const char *Value = Args.getArgString(Index) + ArgSize;
> +      return new Arg(*this, Spelling, Index++, Value);
> +    }
> +
> +    // Otherwise it must be separate.
> +    Index += 2;
> +    if (Index > Args.getNumInputArgStrings())
> +      return 0;
> +
> +    return new Arg(UnaliasedOption, Spelling,
> +                   Index - 2, Args.getArgString(Index - 1));
> +  }
> +  case JoinedAndSeparateClass:
> +    // Always matches.
> +    Index += 2;
> +    if (Index > Args.getNumInputArgStrings())
> +      return 0;
> +
> +    return new Arg(UnaliasedOption, Spelling, Index - 2,
> +                   Args.getArgString(Index - 2) + ArgSize,
> +                   Args.getArgString(Index - 1));
> +  default:
> +    llvm_unreachable("Invalid option kind!");
> +  }
> +}
>
> Modified: llvm/trunk/unittests/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/CMakeLists.txt?rev=169344&r1=169343&r2=169344&view=diff
> ==============================================================================
> --- llvm/trunk/unittests/CMakeLists.txt (original)
> +++ llvm/trunk/unittests/CMakeLists.txt Tue Dec  4 18:29:32 2012
> @@ -9,6 +9,7 @@
>  add_subdirectory(Analysis)
>  add_subdirectory(ExecutionEngine)
>  add_subdirectory(Bitcode)
> +add_subdirectory(Option)
>  add_subdirectory(Support)
>  add_subdirectory(Transforms)
>  add_subdirectory(VMCore)
>
> Added: llvm/trunk/unittests/Option/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Option/CMakeLists.txt?rev=169344&view=auto
> ==============================================================================
> --- llvm/trunk/unittests/Option/CMakeLists.txt (added)
> +++ llvm/trunk/unittests/Option/CMakeLists.txt Tue Dec  4 18:29:32 2012
> @@ -0,0 +1,15 @@
> +set(LLVM_LINK_COMPONENTS
> +  Option
> +  Support
> +  )
> +
> +set(LLVM_TARGET_DEFINITIONS Opts.td)
> +
> +tablegen(LLVM Opts.inc -gen-opt-parser-defs)
> +add_public_tablegen_target(OptsTestTableGen)
> +
> +add_llvm_unittest(OptionTests
> +  OptionParsingTest.cpp
> +  )
> +
> +add_dependencies(OptionTests OptsTestTableGen)
>
> Added: llvm/trunk/unittests/Option/OptionParsingTest.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Option/OptionParsingTest.cpp?rev=169344&view=auto
> ==============================================================================
> --- llvm/trunk/unittests/Option/OptionParsingTest.cpp (added)
> +++ llvm/trunk/unittests/Option/OptionParsingTest.cpp Tue Dec  4 18:29:32 2012
> @@ -0,0 +1,102 @@
> +//===- unittest/Support/OptionParsingTest.cpp - OptTable tests ------------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "llvm/Option/Arg.h"
> +#include "llvm/Option/ArgList.h"
> +#include "llvm/Option/Option.h"
> +
> +#include "gtest/gtest.h"
> +
> +using namespace llvm;
> +using namespace llvm::opt;
> +
> +enum ID {
> +  OPT_INVALID = 0, // This is not an option ID.
> +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
> +              HELPTEXT, METAVAR) OPT_##ID,
> +#include "Opts.inc"
> +  LastOption
> +#undef OPTION
> +};
> +
> +#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
> +#include "Opts.inc"
> +#undef PREFIX
> +
> +static const OptTable::Info InfoTable[] = {
> +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
> +               HELPTEXT, METAVAR)   \
> +  { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, PARAM, \
> +    FLAGS, OPT_##GROUP, OPT_##ALIAS },
> +#include "Opts.inc"
> +#undef OPTION
> +};
> +
> +namespace {
> +class TestOptTable : public OptTable {
> +public:
> +  TestOptTable()
> +    : OptTable(InfoTable, sizeof(InfoTable) / sizeof(InfoTable[0])) {}
> +};
> +}
> +
> +const char *Args[] = {
> +  "-A",
> +  "-Bhi",
> +  "--C=desu",
> +  "-C", "bye",
> +  "-D,adena",
> +  "-E", "apple", "bloom",
> +  "-Fblarg",
> +  "-F", "42",
> +  "-Gchuu", "2"
> +  };
> +
> +TEST(Support, OptionParsing) {
> +  TestOptTable T;
> +  unsigned MAI, MAC;
> +  InputArgList *AL = T.ParseArgs(Args, Args + (sizeof(Args) / sizeof(Args[0])), MAI, MAC);
> +
> +  // Check they all exist.
> +  EXPECT_TRUE(AL->hasArg(OPT_A));
> +  EXPECT_TRUE(AL->hasArg(OPT_B));
> +  EXPECT_TRUE(AL->hasArg(OPT_C));
> +  EXPECT_TRUE(AL->hasArg(OPT_D));
> +  EXPECT_TRUE(AL->hasArg(OPT_E));
> +  EXPECT_TRUE(AL->hasArg(OPT_F));
> +  EXPECT_TRUE(AL->hasArg(OPT_G));
> +
> +  // Check the values.
> +  EXPECT_EQ(AL->getLastArgValue(OPT_B), "hi");
> +  EXPECT_EQ(AL->getLastArgValue(OPT_C), "bye");
> +  EXPECT_EQ(AL->getLastArgValue(OPT_D), "adena");
> +  std::vector<std::string> Es = AL->getAllArgValues(OPT_E);
> +  EXPECT_EQ(Es[0], "apple");
> +  EXPECT_EQ(Es[1], "bloom");
> +  EXPECT_EQ(AL->getLastArgValue(OPT_F), "42");
> +  std::vector<std::string> Gs = AL->getAllArgValues(OPT_G);
> +  EXPECT_EQ(Gs[0], "chuu");
> +  EXPECT_EQ(Gs[1], "2");
> +
> +  // Check the help text.
> +  std::string Help;
> +  raw_string_ostream RSO(Help);
> +  T.PrintHelp(RSO, "test", "title!");
> +  EXPECT_NE(Help.find("-A"), std::string::npos);
> +
> +  // Test aliases.
> +  arg_iterator Cs = AL->filtered_begin(OPT_C);
> +  ASSERT_NE(Cs, AL->filtered_end());
> +  EXPECT_EQ(StringRef((*Cs)->getValue()), "desu");
> +  ArgStringList ASL;
> +  (*Cs)->render(*AL, ASL);
> +  ASSERT_EQ(ASL.size(), 2u);
> +  EXPECT_EQ(StringRef(ASL[0]), "-C");
> +  EXPECT_EQ(StringRef(ASL[1]), "desu");
> +}
>
> Added: llvm/trunk/unittests/Option/Opts.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Option/Opts.td?rev=169344&view=auto
> ==============================================================================
> --- llvm/trunk/unittests/Option/Opts.td (added)
> +++ llvm/trunk/unittests/Option/Opts.td Tue Dec  4 18:29:32 2012
> @@ -0,0 +1,13 @@
> +include "llvm/Option/OptParser.td"
> +
> +def A : Flag<["-"], "A">, HelpText<"The A option">;
> +def B : Joined<["-"], "B">, HelpText<"The B option">, MetaVarName<"B">;
> +def C : Separate<["-"], "C">, HelpText<"The C option">, MetaVarName<"C">;
> +def D : CommaJoined<["-"], "D">, HelpText<"The D option">, MetaVarName<"D">;
> +def E : MultiArg<["-"], "E", 2>;
> +def F : JoinedOrSeparate<["-"], "F">, HelpText<"The F option">, MetaVarName<"F">;
> +def G : JoinedAndSeparate<["-"], "G">, HelpText<"The G option">, MetaVarName<"G">;
> +
> +def Ceq : Joined<["-", "--"], "C=">, Alias<C>;
> +
> +def H : Flag<["-"], "H">, Flags<[HelpHidden]>;
>
> Modified: llvm/trunk/utils/TableGen/CMakeLists.txt
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CMakeLists.txt?rev=169344&r1=169343&r2=169344&view=diff
> ==============================================================================
> --- llvm/trunk/utils/TableGen/CMakeLists.txt (original)
> +++ llvm/trunk/utils/TableGen/CMakeLists.txt Tue Dec  4 18:29:32 2012
> @@ -24,6 +24,7 @@
>    FixedLenDecoderEmitter.cpp
>    InstrInfoEmitter.cpp
>    IntrinsicEmitter.cpp
> +  OptParserEmitter.cpp
>    PseudoLoweringEmitter.cpp
>    RegisterInfoEmitter.cpp
>    SetTheory.cpp
>
> Added: llvm/trunk/utils/TableGen/OptParserEmitter.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/OptParserEmitter.cpp?rev=169344&view=auto
> ==============================================================================
> --- llvm/trunk/utils/TableGen/OptParserEmitter.cpp (added)
> +++ llvm/trunk/utils/TableGen/OptParserEmitter.cpp Tue Dec  4 18:29:32 2012
> @@ -0,0 +1,267 @@
> +//===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "llvm/TableGen/Error.h"
> +#include "llvm/TableGen/Record.h"
> +#include "llvm/TableGen/TableGenBackend.h"
> +#include "llvm/ADT/STLExtras.h"
> +#include "llvm/ADT/SmallString.h"
> +#include "llvm/ADT/Twine.h"
> +
> +#include <map>
> +
> +using namespace llvm;
> +
> +static int StrCmpOptionName(const char *A, const char *B) {
> +  char a = *A, b = *B;
> +  while (a == b) {
> +    if (a == '\0')
> +      return 0;
> +
> +    a = *++A;
> +    b = *++B;
> +  }
> +
> +  if (a == '\0') // A is a prefix of B.
> +    return 1;
> +  if (b == '\0') // B is a prefix of A.
> +    return -1;
> +
> +  // Otherwise lexicographic.
> +  return (a < b) ? -1 : 1;
> +}
> +
> +static int CompareOptionRecords(const void *Av, const void *Bv) {
> +  const Record *A = *(const Record*const*) Av;
> +  const Record *B = *(const Record*const*) Bv;
> +
> +  // Sentinel options precede all others and are only ordered by precedence.
> +  bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel");
> +  bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel");
> +  if (ASent != BSent)
> +    return ASent ? -1 : 1;
> +
> +  // Compare options by name, unless they are sentinels.
> +  if (!ASent)
> +    if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").c_str(),
> +                                   B->getValueAsString("Name").c_str()))
> +    return Cmp;
> +
> +  if (!ASent) {
> +    std::vector<std::string> APrefixes = A->getValueAsListOfStrings("Prefixes");
> +    std::vector<std::string> BPrefixes = B->getValueAsListOfStrings("Prefixes");
> +
> +    for (std::vector<std::string>::const_iterator APre = APrefixes.begin(),
> +                                                  AEPre = APrefixes.end(),
> +                                                  BPre = BPrefixes.begin(),
> +                                                  BEPre = BPrefixes.end();
> +                                                  APre != AEPre &&
> +                                                  BPre != BEPre;
> +                                                  ++APre, ++BPre) {
> +      if (int Cmp = StrCmpOptionName(APre->c_str(), BPre->c_str()))
> +        return Cmp;
> +    }
> +  }
> +
> +  // Then by the kind precedence;
> +  int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence");
> +  int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence");
> +  if (APrec == BPrec &&
> +      A->getValueAsListOfStrings("Prefixes") ==
> +      B->getValueAsListOfStrings("Prefixes")) {
> +    PrintError(A->getLoc(), Twine("Option is equivilent to"));
> +    PrintError(B->getLoc(), Twine("Other defined here"));
> +    PrintFatalError("Equivalent Options found.");
> +  }
> +  return APrec < BPrec ? -1 : 1;
> +}
> +
> +static const std::string getOptionName(const Record &R) {
> +  // Use the record name unless EnumName is defined.
> +  if (isa<UnsetInit>(R.getValueInit("EnumName")))
> +    return R.getName();
> +
> +  return R.getValueAsString("EnumName");
> +}
> +
> +static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
> +  OS << '"';
> +  OS.write_escaped(Str);
> +  OS << '"';
> +  return OS;
> +}
> +
> +/// OptParserEmitter - This tablegen backend takes an input .td file
> +/// describing a list of options and emits a data structure for parsing and
> +/// working with those options when given an input command line.
> +namespace llvm {
> +void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
> +  // Get the option groups and options.
> +  const std::vector<Record*> &Groups =
> +    Records.getAllDerivedDefinitions("OptionGroup");
> +  std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");
> +
> +  emitSourceFileHeader("Option Parsing Definitions", OS);
> +
> +  array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
> +  // Generate prefix groups.
> +  typedef SmallVector<SmallString<2>, 2> PrefixKeyT;
> +  typedef std::map<PrefixKeyT, std::string> PrefixesT;
> +  PrefixesT Prefixes;
> +  Prefixes.insert(std::make_pair(PrefixKeyT(), "prefix_0"));
> +  unsigned CurPrefix = 0;
> +  for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
> +    const Record &R = *Opts[i];
> +    std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes");
> +    PrefixKeyT prfkey(prf.begin(), prf.end());
> +    unsigned NewPrefix = CurPrefix + 1;
> +    if (Prefixes.insert(std::make_pair(prfkey, (Twine("prefix_") +
> +                                              Twine(NewPrefix)).str())).second)
> +      CurPrefix = NewPrefix;
> +  }
> +
> +  // Dump prefixes.
> +
> +  OS << "/////////\n";
> +  OS << "// Prefixes\n\n";
> +  OS << "#ifdef PREFIX\n";
> +  OS << "#define COMMA ,\n";
> +  for (PrefixesT::const_iterator I = Prefixes.begin(), E = Prefixes.end();
> +                                  I != E; ++I) {
> +    OS << "PREFIX(";
> +
> +    // Prefix name.
> +    OS << I->second;
> +
> +    // Prefix values.
> +    OS << ", {";
> +    for (PrefixKeyT::const_iterator PI = I->first.begin(),
> +                                    PE = I->first.end(); PI != PE; ++PI) {
> +      OS << "\"" << *PI << "\" COMMA ";
> +    }
> +    OS << "0})\n";
> +  }
> +  OS << "#undef COMMA\n";
> +  OS << "#endif\n\n";
> +
> +  OS << "/////////\n";
> +  OS << "// Groups\n\n";
> +  OS << "#ifdef OPTION\n";
> +  for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
> +    const Record &R = *Groups[i];
> +
> +    // Start a single option entry.
> +    OS << "OPTION(";
> +
> +    // The option prefix;
> +    OS << "0";
> +
> +    // The option string.
> +    OS << ", \"" << R.getValueAsString("Name") << '"';
> +
> +    // The option identifier name.
> +    OS  << ", "<< getOptionName(R);
> +
> +    // The option kind.
> +    OS << ", Group";
> +
> +    // The containing option group (if any).
> +    OS << ", ";
> +    if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
> +      OS << getOptionName(*DI->getDef());
> +    else
> +      OS << "INVALID";
> +
> +    // The other option arguments (unused for groups).
> +    OS << ", INVALID, 0, 0";
> +
> +    // The option help text.
> +    if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
> +      OS << ",\n";
> +      OS << "       ";
> +      write_cstring(OS, R.getValueAsString("HelpText"));
> +    } else
> +      OS << ", 0";
> +
> +    // The option meta-variable name (unused).
> +    OS << ", 0)\n";
> +  }
> +  OS << "\n";
> +
> +  OS << "//////////\n";
> +  OS << "// Options\n\n";
> +  for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
> +    const Record &R = *Opts[i];
> +
> +    // Start a single option entry.
> +    OS << "OPTION(";
> +
> +    // The option prefix;
> +    std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes");
> +    OS << Prefixes[PrefixKeyT(prf.begin(), prf.end())] << ", ";
> +
> +    // The option string.
> +    write_cstring(OS, R.getValueAsString("Name"));
> +
> +    // The option identifier name.
> +    OS  << ", "<< getOptionName(R);
> +
> +    // The option kind.
> +    OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");
> +
> +    // The containing option group (if any).
> +    OS << ", ";
> +    if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
> +      OS << getOptionName(*DI->getDef());
> +    else
> +      OS << "INVALID";
> +
> +    // The option alias (if any).
> +    OS << ", ";
> +    if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias")))
> +      OS << getOptionName(*DI->getDef());
> +    else
> +      OS << "INVALID";
> +
> +    // The option flags.
> +    const ListInit *LI = R.getValueAsListInit("Flags");
> +    if (LI->empty()) {
> +      OS << ", 0";
> +    } else {
> +      OS << ", ";
> +      for (unsigned i = 0, e = LI->size(); i != e; ++i) {
> +        if (i)
> +          OS << " | ";
> +        OS << cast<DefInit>(LI->getElement(i))->getDef()->getName();
> +      }
> +    }
> +
> +    // The option parameter field.
> +    OS << ", " << R.getValueAsInt("NumArgs");
> +
> +    // The option help text.
> +    if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
> +      OS << ",\n";
> +      OS << "       ";
> +      write_cstring(OS, R.getValueAsString("HelpText"));
> +    } else
> +      OS << ", 0";
> +
> +    // The option meta-variable name.
> +    OS << ", ";
> +    if (!isa<UnsetInit>(R.getValueInit("MetaVarName")))
> +      write_cstring(OS, R.getValueAsString("MetaVarName"));
> +    else
> +      OS << "0";
> +
> +    OS << ")\n";
> +  }
> +  OS << "#endif\n";
> +}
> +} // end namespace llvm
>
> Modified: llvm/trunk/utils/TableGen/TableGen.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/TableGen.cpp?rev=169344&r1=169343&r2=169344&view=diff
> ==============================================================================
> --- llvm/trunk/utils/TableGen/TableGen.cpp (original)
> +++ llvm/trunk/utils/TableGen/TableGen.cpp Tue Dec  4 18:29:32 2012
> @@ -40,7 +40,8 @@
>    GenTgtIntrinsic,
>    GenEDInfo,
>    PrintEnums,
> -  PrintSets
> +  PrintSets,
> +  GenOptParserDefs
>  };
>
>  namespace {
> @@ -82,6 +83,8 @@
>                                 "Print enum values for a class"),
>                      clEnumValN(PrintSets, "print-sets",
>                                 "Print expanded sets for testing DAG exprs"),
> +                    clEnumValN(GenOptParserDefs, "gen-opt-parser-defs",
> +                               "Generate option definitions"),
>                      clEnumValEnd));
>
>    cl::opt<std::string>
> @@ -138,6 +141,9 @@
>    case GenEDInfo:
>      EmitEnhancedDisassemblerInfo(Records, OS);
>      break;
> +  case GenOptParserDefs:
> +    EmitOptParser(Records, OS);
> +    break;
>    case PrintEnums:
>    {
>      std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
>
> Modified: llvm/trunk/utils/TableGen/TableGenBackends.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/TableGenBackends.h?rev=169344&r1=169343&r2=169344&view=diff
> ==============================================================================
> --- llvm/trunk/utils/TableGen/TableGenBackends.h (original)
> +++ llvm/trunk/utils/TableGen/TableGenBackends.h Tue Dec  4 18:29:32 2012
> @@ -75,5 +75,6 @@
>  void EmitRegisterInfo(RecordKeeper &RK, raw_ostream &OS);
>  void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS);
>  void EmitMapTable(RecordKeeper &RK, raw_ostream &OS);
> +void EmitOptParser(RecordKeeper &RK, raw_ostream &OS);
>
>  } // End llvm namespace
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits



More information about the llvm-commits mailing list