#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSet.h"
-#include "llvm/Support/Streams.h"
-
#include <algorithm>
#include <cassert>
#include <functional>
}
// checkNumberOfArguments - Ensure that the number of args in d is
-// less than or equal to min_arguments, otherwise throw an exception.
+// greater than or equal to min_arguments, otherwise throw an exception.
void checkNumberOfArguments (const DagInit* d, unsigned min_arguments) {
if (!d || d->getNumArgs() < min_arguments)
- throw d->getOperator()->getAsString()
- + ": too few arguments!";
+ throw d->getOperator()->getAsString() + ": too few arguments!";
}
// isDagEmpty - is this DAG marked with an empty marker?
/// OptionType - One of six different option types. See the
/// documentation for detailed description of differences.
namespace OptionType {
+
enum OptionType { Alias, Switch, Parameter, ParameterList,
Prefix, PrefixList};
-bool IsList (OptionType t) {
- return (t == ParameterList || t == PrefixList);
-}
+ bool IsList (OptionType t) {
+ return (t == ParameterList || t == PrefixList);
+ }
-bool IsSwitch (OptionType t) {
- return (t == Switch);
-}
+ bool IsSwitch (OptionType t) {
+ return (t == Switch);
+ }
-bool IsParameter (OptionType t) {
- return (t == Parameter || t == Prefix);
-}
+ bool IsParameter (OptionType t) {
+ return (t == Parameter || t == Prefix);
+ }
}
unsigned Flags;
std::string Help;
unsigned MultiVal;
+ Init* InitVal;
OptionDescription(OptionType::OptionType t = OptionType::Switch,
const std::string& n = "",
const std::string& h = DefaultHelpString)
- : Type(t), Name(n), Flags(0x0), Help(h), MultiVal(1)
+ : Type(t), Name(n), Flags(0x0), Help(h), MultiVal(1), InitVal(0)
{}
/// GenTypeDeclaration - Returns the C++ variable type of this
bool isReallyHidden() const;
void setReallyHidden();
+ bool isParameter() const
+ { return OptionType::IsParameter(this->Type); }
+
+ bool isSwitch() const
+ { return OptionType::IsSwitch(this->Type); }
+
+ bool isList() const
+ { return OptionType::IsList(this->Type); }
+
};
void OptionDescription::Merge (const OptionDescription& other)
if (Help == other.Help || Help == DefaultHelpString)
Help = other.Help;
else if (other.Help != DefaultHelpString) {
- llvm::cerr << "Warning: several different help strings"
+ llvm::errs() << "Warning: several different help strings"
" defined for option " + Name + "\n";
}
AddHandler("extern", &CollectOptionProperties::onExtern);
AddHandler("help", &CollectOptionProperties::onHelp);
AddHandler("hidden", &CollectOptionProperties::onHidden);
+ AddHandler("init", &CollectOptionProperties::onInit);
AddHandler("multi_val", &CollectOptionProperties::onMultiVal);
AddHandler("one_or_more", &CollectOptionProperties::onOneOrMore);
AddHandler("really_hidden", &CollectOptionProperties::onReallyHidden);
optDesc_.setRequired();
}
+ void onInit (const DagInit* d) {
+ checkNumberOfArguments(d, 1);
+ Init* i = d->getArg(0);
+ const std::string& str = i->getAsString();
+
+ bool correct = optDesc_.isParameter() && dynamic_cast<StringInit*>(i);
+ correct |= (optDesc_.isSwitch() && (str == "true" || str == "false"));
+
+ if (!correct)
+ throw std::string("Incorrect usage of the 'init' option property!");
+
+ optDesc_.InitVal = i;
+ }
+
void onOneOrMore (const DagInit* d) {
checkNumberOfArguments(d, 0);
if (optDesc_.isRequired() || optDesc_.isZeroOrOne())
throw std::string("Only one of (required), (zero_or_one) or "
"(one_or_more) properties is allowed!");
if (!OptionType::IsList(optDesc_.Type))
- llvm::cerr << "Warning: specifying the 'one_or_more' property "
+ llvm::errs() << "Warning: specifying the 'one_or_more' property "
"on a non-list option will have no effect.\n";
optDesc_.setOneOrMore();
}
throw std::string("Only one of (required), (zero_or_one) or "
"(one_or_more) properties is allowed!");
if (!OptionType::IsList(optDesc_.Type))
- llvm::cerr << "Warning: specifying the 'zero_or_one' property"
+ llvm::errs() << "Warning: specifying the 'zero_or_one' property"
"on a non-list option will have no effect.\n";
optDesc_.setZeroOrOne();
}
const OptionDescription& Val = B->second;
if (!nonSuperfluousOptions.count(Val.Name)
&& Val.Type != OptionType::Alias)
- llvm::cerr << "Warning: option '-" << Val.Name << "' has no effect! "
+ llvm::errs() << "Warning: option '-" << Val.Name << "' has no effect! "
"Probable cause: this option is specified only in the OptionList.\n";
}
}
bool EmitCaseTest1Arg(const std::string& TestName,
const DagInit& d,
const OptionDescriptions& OptDescs,
- std::ostream& O) {
+ raw_ostream& O) {
checkNumberOfArguments(&d, 1);
const std::string& OptName = InitPtrToString(d.getArg(0));
if (TestName == "switch_on") {
const OptionDescription& OptDesc = OptDescs.FindOption(OptName);
- if (!OptionType::IsSwitch(OptDesc.Type))
+ if (!OptDesc.isSwitch())
throw OptName + ": incorrect option type - should be a switch!";
O << OptDesc.GenVariableName();
return true;
}
else {
const OptionDescription& OptDesc = OptDescs.FindOption(OptName);
- if (OptionType::IsSwitch(OptDesc.Type))
+ if (OptDesc.isSwitch())
throw OptName
+ ": incorrect option type - should be a list or parameter!";
O << Test << OptDesc.GenVariableName() << ".empty()";
const DagInit& d,
const char* IndentLevel,
const OptionDescriptions& OptDescs,
- std::ostream& O) {
+ raw_ostream& O) {
checkNumberOfArguments(&d, 2);
const std::string& OptName = InitPtrToString(d.getArg(0));
const std::string& OptArg = InitPtrToString(d.getArg(1));
const OptionDescription& OptDesc = OptDescs.FindOption(OptName);
if (TestName == "parameter_equals") {
- if (!OptionType::IsParameter(OptDesc.Type))
+ if (!OptDesc.isParameter())
throw OptName + ": incorrect option type - should be a parameter!";
O << OptDesc.GenVariableName() << " == \"" << OptArg << "\"";
return true;
}
else if (TestName == "element_in_list") {
- if (!OptionType::IsList(OptDesc.Type))
+ if (!OptDesc.isList())
throw OptName + ": incorrect option type - should be a list!";
const std::string& VarName = OptDesc.GenVariableName();
O << "std::find(" << VarName << ".begin(),\n"
// EmitLogicalOperationTest and EmitCaseTest are mutually recursive.
void EmitCaseTest(const DagInit& d, const char* IndentLevel,
const OptionDescriptions& OptDescs,
- std::ostream& O);
+ raw_ostream& O);
/// EmitLogicalOperationTest - Helper function used by
/// EmitCaseConstructHandler.
void EmitLogicalOperationTest(const DagInit& d, const char* LogicOp,
const char* IndentLevel,
const OptionDescriptions& OptDescs,
- std::ostream& O) {
+ raw_ostream& O) {
O << '(';
for (unsigned j = 0, NumArgs = d.getNumArgs(); j < NumArgs; ++j) {
const DagInit& InnerTest = InitPtrToDag(d.getArg(j));
/// EmitCaseTest - Helper function used by EmitCaseConstructHandler.
void EmitCaseTest(const DagInit& d, const char* IndentLevel,
const OptionDescriptions& OptDescs,
- std::ostream& O) {
+ raw_ostream& O) {
const std::string& TestName = d.getOperator()->getAsString();
if (TestName == "and")
// Emit code that handles the 'case' construct.
// Takes a function object that should emit code for every case clause.
// Callback's type is
-// void F(Init* Statement, const char* IndentLevel, std::ostream& O).
+// void F(Init* Statement, const char* IndentLevel, raw_ostream& O).
template <typename F>
void EmitCaseConstructHandler(const Init* Dag, const char* IndentLevel,
F Callback, bool EmitElseIf,
const OptionDescriptions& OptDescs,
- std::ostream& O) {
+ raw_ostream& O) {
const DagInit* d = &InitPtrToDag(Dag);
if (d->getOperator()->getAsString() != "case")
throw std::string("EmitCaseConstructHandler should be invoked"
enum TokenizerState
{ Normal, SpecialCommand, InsideSpecialCommand, InsideQuotationMarks }
cur_st = Normal;
+
+ if (CmdLine.empty())
+ return;
Out.push_back("");
std::string::size_type B = CmdLine.find_first_not_of(Delimiters),
E = CmdLine.size();
- if (B == std::string::npos)
- throw "Empty command-line string!";
+
for (; B != E; ++B) {
char cur_ch = CmdLine[B];
/// SubstituteSpecialCommands - Perform string substitution for $CALL
/// and $ENV. Helper function used by EmitCmdLineVecFill().
StrVector::const_iterator SubstituteSpecialCommands
-(StrVector::const_iterator Pos, StrVector::const_iterator End, std::ostream& O)
+(StrVector::const_iterator Pos, StrVector::const_iterator End, raw_ostream& O)
{
const std::string& cmd = *Pos;
/// vector. Helper function used by EmitGenerateActionMethod().
void EmitCmdLineVecFill(const Init* CmdLine, const std::string& ToolName,
bool IsJoin, const char* IndentLevel,
- std::ostream& O) {
+ raw_ostream& O) {
StrVector StrVec;
TokenizeCmdline(InitPtrToString(CmdLine), StrVec);
if (StrVec.empty())
- throw "Tool " + ToolName + " has empty command line!";
+ throw "Tool '" + ToolName + "' has empty command line!";
StrVector::const_iterator I = StrVec.begin(), E = StrVec.end();
O << "for (PathVector::const_iterator B = inFiles.begin()"
<< ", E = inFiles.end();\n"
<< IndentLevel << "B != E; ++B)\n"
- << IndentLevel << Indent1 << "vec.push_back(B->toString());\n";
+ << IndentLevel << Indent1 << "vec.push_back(B->str());\n";
else
- O << "vec.push_back(inFile.toString());\n";
+ O << "vec.push_back(inFile.str());\n";
}
else if (cmd == "$OUTFILE") {
O << "vec.push_back(out_file);\n";
: IsJoin(J), ToolName(TN) {}
void operator()(const Init* Statement, const char* IndentLevel,
- std::ostream& O) const
+ raw_ostream& O) const
{
EmitCmdLineVecFill(Statement, ToolName, IsJoin,
IndentLevel, O);
void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,
const char* Indent,
const std::string& NewName,
- std::ostream& O) {
+ raw_ostream& O) {
const std::string& Name = NewName.empty()
? ("-" + D.Name)
: NewName;
const OptionDescriptions& OptDescs;
void processActionDag(const Init* Statement, const char* IndentLevel,
- std::ostream& O) const
+ raw_ostream& O) const
{
const DagInit& Dag = InitPtrToDag(Statement);
const std::string& ActionName = Dag.getOperator()->getAsString();
if (D.isMultiVal())
throw std::string("Can't use unpack_values with multi-valued options!");
- if (OptionType::IsList(D.Type)) {
+ if (D.isList()) {
O << IndentLevel << "for (" << D.GenTypeDeclaration()
<< "::iterator B = " << D.GenVariableName() << ".begin(),\n"
<< IndentLevel << "E = " << D.GenVariableName()
<< ".end(); B != E; ++B)\n"
<< IndentLevel << Indent1 << "llvm::SplitString(*B, vec, \",\");\n";
}
- else if (OptionType::IsParameter(D.Type)){
+ else if (D.isParameter()){
O << Indent3 << "llvm::SplitString("
<< D.GenVariableName() << ", vec, \",\");\n";
}
: OptDescs(OD) {}
void operator()(const Init* Statement, const char* IndentLevel,
- std::ostream& O) const
+ raw_ostream& O) const
{
if (typeid(*Statement) == typeid(ListInit)) {
const ListInit& DagList = *static_cast<const ListInit*>(Statement);
// Tool::GenerateAction() method.
void EmitGenerateActionMethod (const ToolDescription& D,
const OptionDescriptions& OptDescs,
- bool IsJoin, std::ostream& O) {
+ bool IsJoin, raw_ostream& O) {
if (IsJoin)
O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n";
else
O << '\n' << Indent2
<< "out_file = OutFilename(" << (IsJoin ? "sys::Path(),\n" : "inFile,\n")
- << Indent3 << "TempDir, stop_compilation, output_suffix).toString();\n\n";
+ << Indent3 << "TempDir, stop_compilation, output_suffix).str();\n\n";
// cmd_line is either a string or a 'case' construct.
if (!D.CmdLine)
/// a given Tool class.
void EmitGenerateActionMethods (const ToolDescription& ToolDesc,
const OptionDescriptions& OptDescs,
- std::ostream& O) {
+ raw_ostream& O) {
if (!ToolDesc.isJoin())
O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n"
<< Indent2 << "bool HasChildren,\n"
/// EmitInOutLanguageMethods - Emit the [Input,Output]Language()
/// methods for a given Tool class.
-void EmitInOutLanguageMethods (const ToolDescription& D, std::ostream& O) {
+void EmitInOutLanguageMethods (const ToolDescription& D, raw_ostream& O) {
O << Indent1 << "const char** InputLanguages() const {\n"
<< Indent2 << "return InputLanguages_;\n"
<< Indent1 << "}\n\n";
}
/// EmitNameMethod - Emit the Name() method for a given Tool class.
-void EmitNameMethod (const ToolDescription& D, std::ostream& O) {
+void EmitNameMethod (const ToolDescription& D, raw_ostream& O) {
O << Indent1 << "const char* Name() const {\n"
<< Indent2 << "return \"" << D.Name << "\";\n"
<< Indent1 << "}\n\n";
/// EmitIsJoinMethod - Emit the IsJoin() method for a given Tool
/// class.
-void EmitIsJoinMethod (const ToolDescription& D, std::ostream& O) {
+void EmitIsJoinMethod (const ToolDescription& D, raw_ostream& O) {
O << Indent1 << "bool IsJoin() const {\n";
if (D.isJoin())
O << Indent2 << "return true;\n";
/// EmitStaticMemberDefinitions - Emit static member definitions for a
/// given Tool class.
-void EmitStaticMemberDefinitions(const ToolDescription& D, std::ostream& O) {
+void EmitStaticMemberDefinitions(const ToolDescription& D, raw_ostream& O) {
if (D.InLanguage.empty())
throw "Tool " + D.Name + " has no 'in_language' property!";
/// EmitToolClassDefinition - Emit a Tool class definition.
void EmitToolClassDefinition (const ToolDescription& D,
const OptionDescriptions& OptDescs,
- std::ostream& O) {
+ raw_ostream& O) {
if (D.Name == "root")
return;
/// and emit registration code.
void EmitOptionDefinitions (const OptionDescriptions& descs,
bool HasSink, bool HasExterns,
- std::ostream& O)
+ raw_ostream& O)
{
std::vector<OptionDescription> Aliases;
continue;
}
- O << "(\"" << val.Name << '\"';
+ O << "(\"" << val.Name << "\"\n";
if (val.Type == OptionType::Prefix || val.Type == OptionType::PrefixList)
O << ", cl::Prefix";
if (val.isRequired()) {
- if (OptionType::IsList(val.Type) && !val.isMultiVal())
+ if (val.isList() && !val.isMultiVal())
O << ", cl::OneOrMore";
else
O << ", cl::Required";
}
- else if (val.isOneOrMore() && OptionType::IsList(val.Type)) {
+ else if (val.isOneOrMore() && val.isList()) {
O << ", cl::OneOrMore";
}
- else if (val.isZeroOrOne() && OptionType::IsList(val.Type)) {
+ else if (val.isZeroOrOne() && val.isList()) {
O << ", cl::ZeroOrOne";
}
}
if (val.MultiVal > 1)
- O << ", cl::multi_val(" << val.MultiVal << ")";
+ O << ", cl::multi_val(" << val.MultiVal << ')';
+
+ if (val.InitVal) {
+ const std::string& str = val.InitVal->getAsString();
+ O << ", cl::init(" << str << ')';
+ }
if (!val.Help.empty())
O << ", cl::desc(\"" << val.Help << "\")";
- O << ");\n";
+ O << ");\n\n";
}
// Emit the aliases (they should go after all the 'proper' options).
}
/// EmitPopulateLanguageMap - Emit the PopulateLanguageMap() function.
-void EmitPopulateLanguageMap (const RecordKeeper& Records, std::ostream& O)
+void EmitPopulateLanguageMap (const RecordKeeper& Records, raw_ostream& O)
{
// Generate code
O << "void PopulateLanguageMapLocal(LanguageMap& langMap) {\n";
/// IncDecWeight - Helper function passed to EmitCaseConstructHandler()
/// by EmitEdgeClass().
void IncDecWeight (const Init* i, const char* IndentLevel,
- std::ostream& O) {
+ raw_ostream& O) {
const DagInit& d = InitPtrToDag(i);
const std::string& OpName = d.getOperator()->getAsString();
/// EmitEdgeClass - Emit a single Edge# class.
void EmitEdgeClass (unsigned N, const std::string& Target,
DagInit* Case, const OptionDescriptions& OptDescs,
- std::ostream& O) {
+ raw_ostream& O) {
// Class constructor.
O << "class Edge" << N << ": public Edge {\n"
/// EmitEdgeClasses - Emit Edge* classes that represent graph edges.
void EmitEdgeClasses (const RecordVector& EdgeVector,
const OptionDescriptions& OptDescs,
- std::ostream& O) {
+ raw_ostream& O) {
int i = 0;
for (RecordVector::const_iterator B = EdgeVector.begin(),
E = EdgeVector.end(); B != E; ++B) {
/// function.
void EmitPopulateCompilationGraph (const RecordVector& EdgeVector,
const ToolDescriptions& ToolDescs,
- std::ostream& O)
+ raw_ostream& O)
{
O << "void PopulateCompilationGraphLocal(CompilationGraph& G) {\n";
/// EmitHookDeclarations - Parse CmdLine fields of all the tool
/// property records and emit hook function declaration for each
/// instance of $CALL(HookName).
-void EmitHookDeclarations(const ToolDescriptions& ToolDescs, std::ostream& O) {
+void EmitHookDeclarations(const ToolDescriptions& ToolDescs, raw_ostream& O) {
llvm::StringMap<unsigned> HookNames;
FillInHookNames(ToolDescs, HookNames);
}
/// EmitRegisterPlugin - Emit code to register this plugin.
-void EmitRegisterPlugin(int Priority, std::ostream& O) {
+void EmitRegisterPlugin(int Priority, raw_ostream& O) {
O << "struct Plugin : public llvmc::BasePlugin {\n\n"
<< Indent1 << "int Priority() const { return " << Priority << "; }\n\n"
<< Indent1 << "void PopulateLanguageMap(LanguageMap& langMap) const\n"
/// EmitIncludes - Emit necessary #include directives and some
/// additional declarations.
-void EmitIncludes(std::ostream& O) {
+void EmitIncludes(raw_ostream& O) {
O << "#include \"llvm/CompilerDriver/CompilationGraph.h\"\n"
+ << "#include \"llvm/CompilerDriver/ForceLinkageMacros.h\"\n"
<< "#include \"llvm/CompilerDriver/Plugin.h\"\n"
<< "#include \"llvm/CompilerDriver/Tool.h\"\n\n"
}
-void EmitPluginCode(const PluginData& Data, std::ostream& O) {
+void EmitPluginCode(const PluginData& Data, raw_ostream& O) {
// Emit file header.
EmitIncludes(O);
// Emit code for plugin registration.
EmitRegisterPlugin(Data.Priority, O);
- O << "} // End anonymous namespace.\n";
+ O << "} // End anonymous namespace.\n\n";
+
+ // Force linkage magic.
+ O << "namespace llvmc {\n";
+ O << "LLVMC_FORCE_LINKAGE_DECL(LLVMC_PLUGIN_NAME) {}\n";
+ O << "}\n";
+
// EOF
}
}
/// run - The back-end entry point.
-void LLVMCConfigurationEmitter::run (std::ostream &O) {
+void LLVMCConfigurationEmitter::run (raw_ostream &O) {
try {
PluginData Data;