aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Glushenkov <foldr@codedgers.com>2008-12-07 16:41:11 +0000
committerMikhail Glushenkov <foldr@codedgers.com>2008-12-07 16:41:11 +0000
commitf915253dfcfbe772ee04872544a4f012c6f851be (patch)
tree37804c93f492340cbffe03d4f709e34d9e1d99e2
parent6290f5cac23399201f8785e5ca8b305e42a1342c (diff)
Use (actions) instead of option properties, support external options.
Also includes a major refactoring. See documentation for more information. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@60656 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/CompilerDriver/Action.h16
-rw-r--r--include/llvm/CompilerDriver/Common.td30
-rw-r--r--include/llvm/CompilerDriver/Tool.h20
-rw-r--r--include/llvm/CompilerDriver/Tools.td85
-rw-r--r--tools/llvmc/driver/CompilationGraph.cpp82
-rw-r--r--tools/llvmc/driver/Tool.cpp74
-rw-r--r--utils/TableGen/LLVMCConfigurationEmitter.cpp1860
7 files changed, 1070 insertions, 1097 deletions
diff --git a/include/llvm/CompilerDriver/Action.h b/include/llvm/CompilerDriver/Action.h
index c3b31d4e55..9cac0aa45b 100644
--- a/include/llvm/CompilerDriver/Action.h
+++ b/include/llvm/CompilerDriver/Action.h
@@ -27,14 +27,22 @@ namespace llvmc {
std::string Command_;
/// Args_ - Command arguments. Stdout redirection ("> file") is allowed.
std::vector<std::string> Args_;
+ /// StopCompilation_ - Should we stop compilation after executing
+ /// this action?
+ bool StopCompilation_;
+ /// OutFile_ - The output file name.
+ std::string OutFile_;
+
public:
- Action() {}
- Action (const std::string& C, const StrVector& A)
- : Command_(C), Args_(A)
+ Action (const std::string& C, const StrVector& A,
+ bool S, const std::string& O)
+ : Command_(C), Args_(A), StopCompilation_(S), OutFile_(O)
{}
/// Execute - Executes the represented action.
- int Execute() const;
+ int Execute () const;
+ bool StopCompilation () const { return StopCompilation_; }
+ const std::string& OutFile() { return OutFile_; }
};
}
diff --git a/include/llvm/CompilerDriver/Common.td b/include/llvm/CompilerDriver/Common.td
index 109a7e5eda..c510956004 100644
--- a/include/llvm/CompilerDriver/Common.td
+++ b/include/llvm/CompilerDriver/Common.td
@@ -15,7 +15,7 @@ class Tool<list<dag> l> {
list<dag> properties = l;
}
-// Possible Tool properties
+// Possible Tool properties.
def in_language;
def out_language;
@@ -23,8 +23,9 @@ def output_suffix;
def cmd_line;
def join;
def sink;
+def actions;
-// Possible option types
+// Possible option types.
def alias_option;
def switch_option;
@@ -33,17 +34,16 @@ def parameter_list_option;
def prefix_option;
def prefix_list_option;
-// Possible option properties
+def extern_switch;
+def extern_parameter;
+def extern_list;
+
+// Possible option properties.
-def append_cmd;
-def forward;
-def forward_as;
def help;
def hidden;
def really_hidden;
def required;
-def stop_compilation;
-def unpack_values;
// Empty DAG marker.
def empty;
@@ -51,6 +51,10 @@ def empty;
// The 'case' construct.
def case;
+// Boolean operators.
+def and;
+def or;
+
// Primitive tests.
def switch_on;
def parameter_equals;
@@ -59,9 +63,13 @@ def input_languages_contain;
def not_empty;
def default;
-// Boolean operators.
-def and;
-def or;
+// Possible actions.
+
+def append_cmd;
+def forward;
+def forward_as;
+def stop_compilation;
+def unpack_values;
// Increase/decrease the edge weight.
def inc_weight;
diff --git a/include/llvm/CompilerDriver/Tool.h b/include/llvm/CompilerDriver/Tool.h
index c422a43992..8e8f6e73c2 100644
--- a/include/llvm/CompilerDriver/Tool.h
+++ b/include/llvm/CompilerDriver/Tool.h
@@ -36,22 +36,29 @@ namespace llvmc {
virtual ~Tool() {}
virtual Action GenerateAction (const PathVector& inFiles,
- const llvm::sys::Path& outFile,
+ bool HasChildren,
+ const llvm::sys::Path& TempDir,
const InputLanguagesSet& InLangs,
const LanguageMap& LangMap) const = 0;
virtual Action GenerateAction (const llvm::sys::Path& inFile,
- const llvm::sys::Path& outFile,
+ bool HasChildren,
+ const llvm::sys::Path& TempDir,
const InputLanguagesSet& InLangs,
const LanguageMap& LangMap) const = 0;
virtual const char* Name() const = 0;
virtual const char** InputLanguages() const = 0;
virtual const char* OutputLanguage() const = 0;
- virtual const char* OutputSuffix() const = 0;
- virtual bool IsLast() const = 0;
virtual bool IsJoin() const = 0;
+
+ protected:
+ /// OutFileName - Generate the output file name.
+ llvm::sys::Path OutFilename(const llvm::sys::Path& In,
+ const llvm::sys::Path& TempDir,
+ bool StopCompilation,
+ const char* OutputSuffix) const;
};
/// JoinTool - A Tool that has an associated input file list.
@@ -61,10 +68,11 @@ namespace llvmc {
void ClearJoinList() { JoinList_.clear(); }
bool JoinListEmpty() const { return JoinList_.empty(); }
- Action GenerateAction(const llvm::sys::Path& outFile,
+ Action GenerateAction(bool HasChildren,
+ const llvm::sys::Path& TempDir,
const InputLanguagesSet& InLangs,
const LanguageMap& LangMap) const {
- return GenerateAction(JoinList_, outFile, InLangs, LangMap);
+ return GenerateAction(JoinList_, HasChildren, TempDir, InLangs, LangMap);
}
// We shouldn't shadow base class's version of GenerateAction.
using Tool::GenerateAction;
diff --git a/include/llvm/CompilerDriver/Tools.td b/include/llvm/CompilerDriver/Tools.td
index e701b47649..d8248acae2 100644
--- a/include/llvm/CompilerDriver/Tools.td
+++ b/include/llvm/CompilerDriver/Tools.td
@@ -11,6 +11,35 @@
//
//===----------------------------------------------------------------------===//
+def OptList : OptionList<[
+ (switch_option "emit-llvm",
+ (help "Emit LLVM bitcode files instead of native object files")),
+ (switch_option "E",
+ (help "Stop after the preprocessing stage, do not run the compiler")),
+ (switch_option "fsyntax-only",
+ (help "Stop after checking the input for syntax errors")),
+ (switch_option "opt",
+ (help "Enable opt")),
+ (switch_option "S",
+ (help "Stop after compilation, do not assemble")),
+ (switch_option "c",
+ (help "Compile and assemble, but do not link")),
+ (parameter_option "linker",
+ (help "Choose linker (possible values: gcc, g++)")),
+ (parameter_list_option "include",
+ (help "Include the named file prior to preprocessing")),
+ (prefix_list_option "I",
+ (help "Add a directory to include path")),
+ (prefix_list_option "Wa,",
+ (help "Pass options to assembler")),
+ (prefix_list_option "L",
+ (help "Add a directory to link path")),
+ (prefix_list_option "l",
+ (help "Search a library when linking")),
+ (prefix_list_option "Wl,",
+ (help "Pass options to linker"))
+]>;
+
class llvm_gcc_based <string cmd_prefix, string in_lang> : Tool<
[(in_language in_lang),
(out_language "llvm-bitcode"),
@@ -25,16 +54,13 @@ class llvm_gcc_based <string cmd_prefix, string in_lang> : Tool<
!strconcat(cmd_prefix, " -fsyntax-only $INFILE"),
(default),
!strconcat(cmd_prefix, " -c $INFILE -o $OUTFILE -emit-llvm"))),
- (switch_option "emit-llvm", (stop_compilation),
- (help "Emit LLVM intermediate files instead of native object files")),
- (switch_option "E", (stop_compilation),
- (help "Stop after the preprocessing stage, do not run the compiler")),
- (switch_option "fsyntax-only", (stop_compilation),
- (help "Stop after checking the input for syntax errors")),
- (parameter_list_option "include", (forward),
- (help "Include the named file prior to preprocessing")),
- (prefix_list_option "I", (forward),
- (help "Add a directory to include path")),
+ (actions
+ (case
+ (switch_on "emit-llvm"), (stop_compilation),
+ (switch_on "E"), (stop_compilation),
+ (switch_on "fsyntax-only"), (stop_compilation),
+ (not_empty "include"), (forward "include"),
+ (not_empty "I"), (forward "include"))),
(sink)
]>;
@@ -46,7 +72,6 @@ def llvm_gcc_mxx : llvm_gcc_based<"llvm-gcc -x objective-c++", "objective-c++">;
def opt : Tool<
[(in_language "llvm-bitcode"),
(out_language "llvm-bitcode"),
- (switch_option "opt", (help "Enable opt")),
(output_suffix "bc"),
(cmd_line "opt -f $INFILE -o $OUTFILE")
]>;
@@ -62,8 +87,8 @@ def llc : Tool<
[(in_language "llvm-bitcode"),
(out_language "assembler"),
(output_suffix "s"),
- (switch_option "S", (stop_compilation),
- (help "Stop after compilation, do not assemble")),
+ (actions (case
+ (switch_on "S"), (stop_compilation))),
(cmd_line "llc -f $INFILE -o $OUTFILE")
]>;
@@ -72,36 +97,28 @@ def llvm_gcc_assembler : Tool<
(out_language "object-code"),
(output_suffix "o"),
(cmd_line "llvm-gcc -c -x assembler $INFILE -o $OUTFILE"),
- (switch_option "c", (stop_compilation),
- (help "Compile and assemble, but do not link")),
- (prefix_list_option "Wa,", (unpack_values), (help "Pass options to assembler"))
+ (actions (case
+ (switch_on "c"), (stop_compilation),
+ (not_empty "Wa,"), (unpack_values "Wa,")))
]>;
-// Default linker
-def llvm_gcc_linker : Tool<
+// Base class for linkers
+class llvm_gcc_based_linker <string cmd_prefix> : Tool<
[(in_language "object-code"),
(out_language "executable"),
(output_suffix "out"),
- (cmd_line "llvm-gcc $INFILE -o $OUTFILE"),
+ (cmd_line !strconcat(cmd_prefix, " $INFILE -o $OUTFILE")),
(join),
- (prefix_list_option "L", (forward), (help "Add a directory to link path")),
- (prefix_list_option "l", (forward), (help "Search a library when linking")),
- (prefix_list_option "Wl,", (unpack_values), (help "Pass options to linker"))
+ (actions (case
+ (not_empty "L"), (forward "L"),
+ (not_empty "l"), (forward "l"),
+ (not_empty "Wl,"), (unpack_values "Wl,")))
]>;
+// Default linker
+def llvm_gcc_linker : llvm_gcc_based_linker<"llvm-gcc">;
// Alternative linker for C++
-def llvm_gcc_cpp_linker : Tool<
-[(in_language "object-code"),
- (out_language "executable"),
- (output_suffix "out"),
- (cmd_line "llvm-g++ $INFILE -o $OUTFILE"),
- (join),
- (parameter_option "linker",
- (help "Choose linker (possible values: gcc, g++)")),
- (prefix_list_option "L", (forward)),
- (prefix_list_option "l", (forward)),
- (prefix_list_option "Wl,", (unpack_values))
-]>;
+def llvm_gcc_cpp_linker : llvm_gcc_based_linker<"llvm-g++">;
// Language map
diff --git a/tools/llvmc/driver/CompilationGraph.cpp b/tools/llvmc/driver/CompilationGraph.cpp
index a4fda4834f..6d7faa3dec 100644
--- a/tools/llvmc/driver/CompilationGraph.cpp
+++ b/tools/llvmc/driver/CompilationGraph.cpp
@@ -29,7 +29,6 @@ using namespace llvm;
using namespace llvmc;
extern cl::list<std::string> InputFilenames;
-extern cl::opt<std::string> OutputFilename;
extern cl::list<std::string> Languages;
namespace llvmc {
@@ -143,30 +142,6 @@ void CompilationGraph::insertEdge(const std::string& A, Edge* Edg) {
B.IncrInEdges();
}
-namespace {
- sys::Path MakeTempFile(const sys::Path& TempDir, const std::string& BaseName,
- const std::string& Suffix) {
- sys::Path Out;
-
- // Make sure we don't end up with path names like '/file.o' if the
- // TempDir is empty.
- if (TempDir.empty()) {
- Out.set(BaseName);
- }
- else {
- Out = TempDir;
- Out.appendComponent(BaseName);
- }
- Out.appendSuffix(Suffix);
- // NOTE: makeUnique always *creates* a unique temporary file,
- // which is good, since there will be no races. However, some
- // tools do not like it when the output file already exists, so
- // they have to be placated with -f or something like that.
- Out.makeUnique(true, NULL);
- return Out;
- }
-}
-
// Pass input file through the chain until we bump into a Join node or
// a node that says that it is the last.
void CompilationGraph::PassThroughGraph (const sys::Path& InFile,
@@ -174,12 +149,10 @@ void CompilationGraph::PassThroughGraph (const sys::Path& InFile,
const InputLanguagesSet& InLangs,
const sys::Path& TempDir,
const LanguageMap& LangMap) const {
- bool Last = false;
sys::Path In = InFile;
const Node* CurNode = StartNode;
- while(!Last) {
- sys::Path Out;
+ while(true) {
Tool* CurTool = CurNode->ToolPtr.getPtr();
if (CurTool->IsJoin()) {
@@ -188,32 +161,19 @@ void CompilationGraph::PassThroughGraph (const sys::Path& InFile,
break;
}
- // Since toolchains do not have to end with a Join node, we should
- // check if this Node is the last.
- if (!CurNode->HasChildren() || CurTool->IsLast()) {
- if (!OutputFilename.empty()) {
- Out.set(OutputFilename);
- }
- else {
- Out.set(In.getBasename());
- Out.appendSuffix(CurTool->OutputSuffix());
- }
- Last = true;
- }
- else {
- Out = MakeTempFile(TempDir, In.getBasename(), CurTool->OutputSuffix());
- }
+ Action CurAction = CurTool->GenerateAction(In, CurNode->HasChildren(),
+ TempDir, InLangs, LangMap);
- if (int ret = CurTool->GenerateAction(In, Out, InLangs, LangMap).Execute())
+ if (int ret = CurAction.Execute())
throw error_code(ret);
- if (Last)
+ if (CurAction.StopCompilation())
return;
CurNode = &getNode(ChooseEdge(CurNode->OutEdges,
InLangs,
CurNode->Name())->ToolName());
- In = Out; Out.clear();
+ In = CurAction.OutFile();
}
}
@@ -351,36 +311,24 @@ int CompilationGraph::Build (const sys::Path& TempDir,
sys::Path Out;
const Node* CurNode = *B;
JoinTool* JT = &dynamic_cast<JoinTool&>(*CurNode->ToolPtr.getPtr());
- bool IsLast = false;
// Are there any files in the join list?
if (JT->JoinListEmpty())
continue;
- // Is this the last tool in the toolchain?
- // NOTE: we can process several toolchains in parallel.
- if (!CurNode->HasChildren() || JT->IsLast()) {
- if (OutputFilename.empty()) {
- Out.set("a");
- Out.appendSuffix(JT->OutputSuffix());
- }
- else
- Out.set(OutputFilename);
- IsLast = true;
- }
- else {
- Out = MakeTempFile(TempDir, "tmp", JT->OutputSuffix());
- }
+ Action CurAction = JT->GenerateAction(CurNode->HasChildren(),
+ TempDir, InLangs, LangMap);
- if (int ret = JT->GenerateAction(Out, InLangs, LangMap).Execute())
+ if (int ret = CurAction.Execute())
throw error_code(ret);
- if (!IsLast) {
- const Node* NextNode =
- &getNode(ChooseEdge(CurNode->OutEdges, InLangs,
- CurNode->Name())->ToolName());
+ if (CurAction.StopCompilation())
+ return 0;
+
+ const Node* NextNode =
+ &getNode(ChooseEdge(CurNode->OutEdges, InLangs,
+ CurNode->Name())->ToolName());
PassThroughGraph(Out, NextNode, InLangs, TempDir, LangMap);
- }
}
return 0;
diff --git a/tools/llvmc/driver/Tool.cpp b/tools/llvmc/driver/Tool.cpp
new file mode 100644
index 0000000000..886b26b5d7
--- /dev/null
+++ b/tools/llvmc/driver/Tool.cpp
@@ -0,0 +1,74 @@
+//===--- Tool.cpp - The LLVM Compiler Driver --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open
+// Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Tool base class - implementation details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CompilerDriver/Tool.h"
+
+#include "llvm/System/Path.h"
+#include "llvm/Support/CommandLine.h"
+
+using namespace llvm;
+using namespace llvmc;
+
+extern cl::opt<std::string> OutputFilename;
+
+namespace {
+ sys::Path MakeTempFile(const sys::Path& TempDir, const std::string& BaseName,
+ const std::string& Suffix) {
+ sys::Path Out;
+
+ // Make sure we don't end up with path names like '/file.o' if the
+ // TempDir is empty.
+ if (TempDir.empty()) {
+ Out.set(BaseName);
+ }
+ else {
+ Out = TempDir;
+ Out.appendComponent(BaseName);
+ }
+ Out.appendSuffix(Suffix);
+ // NOTE: makeUnique always *creates* a unique temporary file,
+ // which is good, since there will be no races. However, some
+ // tools do not like it when the output file already exists, so
+ // they have to be placated with -f or something like that.
+ Out.makeUnique(true, NULL);
+ return Out;
+ }
+}
+
+sys::Path Tool::OutFilename(const sys::Path& In,
+ const sys::Path& TempDir,
+ bool StopCompilation,
+ const char* OutputSuffix) const {
+ sys::Path Out;
+
+ if (StopCompilation) {
+ if (!OutputFilename.empty()) {
+ Out.set(OutputFilename);
+ }
+ else if (IsJoin()) {
+ Out.set("a");
+ Out.appendSuffix(OutputSuffix);
+ }
+ else {
+ Out.set(In.getBasename());
+ Out.appendSuffix(OutputSuffix);
+ }
+ }
+ else {
+ if (IsJoin())
+ Out = MakeTempFile(TempDir, "tmp", OutputSuffix);
+ else
+ Out = MakeTempFile(TempDir, In.getBasename(), OutputSuffix);
+ }
+ return Out;
+}
diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp
index 97ea3d6834..175de45925 100644
--- a/utils/TableGen/LLVMCConfigurationEmitter.cpp
+++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp
@@ -45,7 +45,6 @@ typedef std::vector<std::string> StrVector;
const char * Indent1 = " ";
const char * Indent2 = " ";
const char * Indent3 = " ";
-const char * Indent4 = " ";
// Default help string.
const char * DefaultHelpString = "NO HELP MESSAGE PROVIDED";
@@ -56,6 +55,13 @@ const char * SinkOptionName = "AutoGeneratedSinkOption";
//===----------------------------------------------------------------------===//
/// Helper functions
+/// Id - An 'identity' function object.
+struct Id {
+ template<typename T>
+ void operator()(const T&) const {
+ }
+};
+
int InitPtrToInt(const Init* ptr) {
const IntInit& val = dynamic_cast<const IntInit&>(*ptr);
return val.getValue();
@@ -89,426 +95,330 @@ bool isDagEmpty (const DagInit* d) {
return d->getOperator()->getAsString() == "empty";
}
+// EscapeVariableName - Escape commas and other symbols not allowed
+// in the C++ variable names. Makes it possible to use options named
+// like "Wa," (useful for prefix options).
+std::string EscapeVariableName(const std::string& Var) {
+ std::string ret;
+ for (unsigned i = 0; i != Var.size(); ++i) {
+ char cur_char = Var[i];
+ if (cur_char == ',') {
+ ret += "_comma_";
+ }
+ else if (cur_char == '+') {
+ ret += "_plus_";
+ }
+ else if (cur_char == '-') {
+ ret += "_dash_";
+ }
+ else {
+ ret.push_back(cur_char);
+ }
+ }
+ return ret;
+}
+
//===----------------------------------------------------------------------===//
/// Back-end specific code
-// A command-line option can have one of the following types:
-//
-// Alias - an alias for another option.
-//
-// Switch - a simple switch without arguments, e.g. -O2
-//
-// Parameter - an option that takes one(and only one) argument, e.g. -o file,
-// --output=file
-//
-// ParameterList - same as Parameter, but more than one occurence
-// of the option is allowed, e.g. -lm -lpthread
-//
-// Prefix - argument is everything after the prefix,
-// e.g. -Wa,-foo,-bar, -DNAME=VALUE
-//
-// PrefixList - same as Prefix, but more than one option occurence is
-// allowed.
+/// OptionType - One of six different option types. See the
+/// documentation for detailed description of differences.
+/// Extern* options are those that are defined in some other plugin.
namespace OptionType {
- enum OptionType { Alias, Switch,
- Parameter, ParameterList, Prefix, PrefixList};
+ enum OptionType { Alias, Switch, Parameter, ParameterList,
+ Prefix, PrefixList,
+ ExternSwitch, ExternParameter, ExternList };
+
+bool IsList (OptionType t) {
+ return (t == ParameterList || t == PrefixList || t == ExternList);
}
-bool IsListOptionType (OptionType::OptionType t) {
- return (t == OptionType::ParameterList || t == OptionType::PrefixList);
+bool IsSwitch (OptionType t) {
+ return (t == Switch || t == ExternSwitch);
}
-// Code duplication here is necessary because one option can affect
-// several tools and those tools may have different actions associated
-// with this option. GlobalOptionDescriptions are used to generate
-// the option registration code, while ToolOptionDescriptions are used
-// to generate tool-specific code.
+bool IsParameter (OptionType t) {
+ return (t == Parameter || t == Prefix || t == ExternParameter);
+}
-/// OptionDescription - Base class for option descriptions.
+}
+
+OptionType::OptionType stringToOptionType(const std::string& T) {
+ if (T == "alias_option")
+ return OptionType::Alias;
+ else if (T == "switch_option")
+ return OptionType::Switch;
+ else if (T == "parameter_option")
+ return OptionType::Parameter;
+ else if (T == "parameter_list_option")
+ return OptionType::ParameterList;
+ else if (T == "prefix_option")
+ return OptionType::Prefix;
+ else if (T == "prefix_list_option")
+ return OptionType::PrefixList;
+ else if (T == "extern_switch")
+ return OptionType::ExternSwitch;
+ else if (T == "extern_parameter")
+ return OptionType::ExternParameter;
+ else if (T == "extern_list")
+ return OptionType::ExternList;
+ else
+ throw "Unknown option type: " + T + '!';
+}
+
+namespace OptionDescriptionFlags {
+ enum OptionDescriptionFlags { Required = 0x1, Hidden = 0x2,
+ ReallyHidden = 0x4 };
+}
+
+/// OptionDescription - Represents data contained in a single
+/// OptionList entry.
struct OptionDescription {
OptionType::OptionType Type;
std::string Name;
+ unsigned Flags;
+ std::string Help;
OptionDescription(OptionType::OptionType t = OptionType::Switch,
- const std::string& n = "")
- : Type(t), Name(n)
+ const std::string& n = "",
+ const std::string& h = DefaultHelpString)
+ : Type(t), Name(n), Flags(0x0), Help(h)
{}
- const char* GenTypeDeclaration() const {
- switch (Type) {
- case OptionType::Alias:
- return "cl::alias";
- case OptionType::PrefixList:
- case OptionType::ParameterList:
- return "cl::list<std::string>";
- case OptionType::Switch:
- return "cl::opt<bool>";
- case OptionType::Parameter:
- case OptionType::Prefix:
- default:
- return "cl::opt<std::string>";
- }
- }
+ /// GenTypeDeclaration - Returns the C++ variable type of this
+ /// option.
+ const char* GenTypeDeclaration() const;
- // Escape commas and other symbols not allowed in the C++ variable
- // names. Makes it possible to use options with names like "Wa,"
- // (useful for prefix options).
- std::string EscapeVariableName(const std::string& Var) const {
- std::string ret;
- for (unsigned i = 0; i != Var.size(); ++i) {
- char cur_char = Var[i];
- if (cur_char == ',') {
- ret += "_comma_";
- }
- else if (cur_char == '+') {
- ret += "_plus_";
- }
- else if (cur_char == '-') {
- ret += "_dash_";
- }
- else {
- ret.push_back(cur_char);
- }
- }
- return ret;
- }
+ /// GenVariableName - Returns the variable name used in the
+ /// generated C++ code.
+ std::string GenVariableName() const;
- std::string GenVariableName() const {
- const std::string& EscapedName = EscapeVariableName(Name);
- switch (Type) {
- case OptionType::Alias:
- return "AutoGeneratedAlias" + EscapedName;
- case OptionType::Switch:
- return "AutoGeneratedSwitch" + EscapedName;
- case OptionType::Prefix:
- return "AutoGeneratedPrefix" + EscapedName;
- case OptionType::PrefixList:
- return "AutoGeneratedPrefixList" + EscapedName;
- case OptionType::Parameter:
- return "AutoGeneratedParameter" + EscapedName;
- case OptionType::ParameterList:
- default:
- return "AutoGeneratedParameterList" + EscapedName;
- }
- }
+ /// Merge - Merge two option descriptions.
+ void Merge (const OptionDescription& other);
+
+ // Misc convenient getters/setters.
+
+ bool isAlias() const;
+ bool isExtern() const;
+ bool isRequired() const;
+ void setRequired();
+
+ bool isHidden() const;
+ void setHidden();
+
+ bool isReallyHidden() const;
+ void setReallyHidden();
};
-// Global option description.
+void OptionDescription::Merge (const OptionDescription& other)
+{
+ if (other.Type != Type)
+ throw "Conflicting definitions for the option " + Name + "!";
-namespace GlobalOptionDescriptionFlags {
- enum GlobalOptionDescriptionFlags { Required = 0x1, Hidden = 0x2,
- ReallyHidden = 0x4 };
+ if (Help == other.Help || Help == DefaultHelpString)
+ Help = other.Help;
+ else if (other.Help != DefaultHelpString) {
+ llvm::cerr << "Warning: several different help strings"
+ " defined for option " + Name + "\n";
+ }
+
+ Flags |= other.Flags;
}
-struct GlobalOptionDescription : public OptionDescription {
- std::string Help;
- unsigned Flags;
+bool OptionDescription::isAlias() const {
+ return Type == OptionType::Alias;
+}
- // We need to provide a default constructor because
- // StringMap can only store DefaultConstructible objects.
- GlobalOptionDescription() : OptionDescription(), Flags(0)
- {}
+bool OptionDescription::isExtern() const {
+ return (Type == OptionType::ExternList || Type == OptionType::ExternParameter
+ || Type == OptionType::ExternSwitch);
+}
- GlobalOptionDescription (OptionType::OptionType t, const std::string& n,
- const std::string& h = DefaultHelpString)
- : OptionDescription(t, n), Help(h), Flags(0)
- {}
+bool OptionDescription::isRequired() const {
+ return Flags & OptionDescriptionFlags::Required;
+}
+void OptionDescription::setRequired() {
+ Flags |= OptionDescriptionFlags::Required;
+}
- bool isRequired() const {
- return Flags & GlobalOptionDescriptionFlags::Required;
- }
- void setRequired() {
- Flags |= GlobalOptionDescriptionFlags::Required;
- }
+bool OptionDescription::isHidden() const {
+ return Flags & OptionDescriptionFlags::Hidden;
+}
+void OptionDescription::setHidden() {
+ Flags |= OptionDescriptionFlags::Hidden;
+}
- bool isHidden() const {
- return Flags & GlobalOptionDescriptionFlags::Hidden;
- }
- void setHidden() {
- Flags |= GlobalOptionDescriptionFlags::Hidden;
- }
+bool OptionDescription::isReallyHidden() const {
+ return Flags & OptionDescriptionFlags::ReallyHidden;
+}
+void OptionDescription::setReallyHidden() {
+ Flags |= OptionDescriptionFlags::ReallyHidden;
+}
- bool isReallyHidden() const {
- return Flags & GlobalOptionDescriptionFlags::ReallyHidden;
- }
- void setReallyHidden() {
- Flags |= GlobalOptionDescriptionFlags::ReallyHidden;
+const char* OptionDescription::GenTypeDeclaration() const {
+ switch (Type) {
+ case OptionType::Alias:
+ return "cl::alias";
+ case OptionType::ExternList:
+ case OptionType::PrefixList:
+ case OptionType::ParameterList:
+ return "cl::list<std::string>";
+ case OptionType::Switch:
+ case OptionType::ExternSwitch:
+ return "cl::opt<bool>";
+ case OptionType::ExternParameter:
+ case OptionType::Parameter:
+ case OptionType::Prefix:
+ default:
+ return "cl::opt<std::string>";
}
+}
- /// Merge - Merge two option descriptions.
- void Merge (const GlobalOptionDescription& other)
- {
- if (other.Type != Type)
- throw "Conflicting definitions for the option " + Name + "!";
-
- if (Help == other.Help || Help == DefaultHelpString)
- Help = other.Help;
- else if (other.Help != DefaultHelpString) {
- llvm::cerr << "Warning: several different help strings"
- " defined for option " + Name + "\n";
- }
-
- Flags |= other.Flags;
+std::string OptionDescription::GenVariableName() const {
+ const std::string& EscapedName = EscapeVariableName(Name);
+ switch (Type) {
+ case OptionType::Alias:
+ return "AutoGeneratedAlias_" + EscapedName;
+ case OptionType::PrefixList:
+ case OptionType::ParameterList:
+ case OptionType::ExternList:
+ return "AutoGeneratedList_" + EscapedName;
+ case OptionType::ExternSwitch:
+ case OptionType::Switch:
+ return "AutoGeneratedSwitch_" + EscapedName;
+ case OptionType::ExternParameter:
+ case OptionType::Prefix:
+ case OptionType::Parameter:
+ default:
+ return "AutoGeneratedParameter_" + EscapedName;
}
-};
+}
-/// GlobalOptionDescriptions - A GlobalOptionDescription array
-/// together with some flags affecting generation of option
-/// declarations.
-struct GlobalOptionDescriptions {
- typedef StringMap<GlobalOptionDescription> container_type;
- typedef container_type::const_iterator const_iterator;
+/// OptionDescriptions - An OptionDescription array plus some helper
+/// functions.
+class OptionDescriptions {
+ typedef StringMap<OptionDescription> container_type;
- /// Descriptions - A list of GlobalOptionDescriptions.
+ /// Descriptions - A list of OptionDescriptions.
container_type Descriptions;
- /// HasSink - Should the emitter generate a "cl::sink" option?
- bool HasSink;
+public:
/// FindOption - exception-throwing wrapper for find().
- const GlobalOptionDescription& FindOption(const std::string& OptName) const {
- const_iterator I = Descriptions.find(OptName);
- if (I != Descriptions.end())
- return I->second;
- else
- throw OptName + ": no such option!";
- }
+ const OptionDescription& FindOption(const std::string& OptName) const;
- /// insertDescription - Insert new GlobalOptionDescription into
- /// GlobalOptionDescriptions list
- void insertDescription (const GlobalOptionDescription& o)
- {
- container_type::iterator I = Descriptions.find(o.Name);
- if (I != Descriptions.end()) {
- GlobalOptionDescription& D = I->second;
- D.Merge(o);
- }
- else {
- Descriptions[o.Name] = o;
- }
- }
+ /// insertDescription - Insert new OptionDescription into
+ /// OptionDescriptions list
+ void InsertDescription (const OptionDescription& o);
// Support for STL-style iteration
+ typedef container_type::const_iterator const_iterator;
const_iterator begin() const { return Descriptions.begin(); }
const_iterator end() const { return Descriptions.end(); }
};
-
-// Tool-local option description.
-
-// Properties without arguments are implemented as flags.
-namespace ToolOptionDescriptionFlags {
- enum ToolOptionDescriptionFlags { StopCompilation = 0x1,
- Forward = 0x2, UnpackValues = 0x4};
-}
-namespace OptionPropertyType {
- enum OptionPropertyType { AppendCmd, ForwardAs, OutputSuffix };
+const OptionDescription&
+OptionDescriptions::FindOption(const std::string& OptName) const
+{
+ const_iterator I = Descriptions.find(OptName);
+ if (I != Descriptions.end())
+ return I->second;
+ else
+ throw OptName + ": no such option!";
}
-typedef std::pair<OptionPropertyType::OptionPropertyType, std::string>
-OptionProperty;
-typedef SmallVector<OptionProperty, 4> OptionPropertyList;
-
-struct ToolOptionDescription : public OptionDescription {
- unsigned Flags;
- OptionPropertyList Props;
-
- // StringMap can only store DefaultConstructible objects
- ToolOptionDescription() : OptionDescription(), Flags(0) {}
-
- ToolOptionDescription (OptionType::OptionType t, const std::string& n)
- : OptionDescription(t, n)
- {}
-
- // Various boolean properties
- bool isStopCompilation() const {
- return Flags & ToolOptionDescriptionFlags::StopCompilation;
- }
- void setStopCompilation() {
- Flags |= ToolOptionDescriptionFlags::StopCompilation;
- }
-
- bool isForward() const {
- return Flags & ToolOptionDescriptionFlags::Forward;
+void OptionDescriptions::InsertDescription (const OptionDescription& o)
+{
+ container_type::iterator I = Descriptions.find(o.Name);
+ if (I != Descriptions.end()) {
+ OptionDescription& D = I->second;
+ D.Merge(o);
}
- void setForward() {
- Flags |= ToolOptionDescriptionFlags::Forward;
+ else {