// checkNumberOfArguments - Ensure that the number of args in d is
// less than or equal to min_arguments, otherwise throw an exception.
void checkNumberOfArguments (const DagInit* d, unsigned min_arguments) {
- if (d->getNumArgs() < min_arguments)
+ if (!d || d->getNumArgs() < min_arguments)
throw "Property " + d->getOperator()->getAsString()
+ " has too few arguments!";
}
return ret;
}
+/// oneOf - Does the input string contain this character?
+bool oneOf(const char* lst, char c) {
+ while (*lst) {
+ if (*lst++ == c)
+ return true;
+ }
+ return false;
+}
+
+template <class I, class S>
+void checkedIncrement(I& P, I E, S ErrorString) {
+ ++P;
+ if (P == E)
+ throw ErrorString;
+}
+
//===----------------------------------------------------------------------===//
/// Back-end specific code
/// 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,
- ExternSwitch, ExternParameter, ExternList };
+ Prefix, PrefixList};
bool IsList (OptionType t) {
- return (t == ParameterList || t == PrefixList || t == ExternList);
+ return (t == ParameterList || t == PrefixList);
}
bool IsSwitch (OptionType t) {
- return (t == Switch || t == ExternSwitch);
+ return (t == Switch);
}
bool IsParameter (OptionType t) {
- return (t == Parameter || t == Prefix || t == ExternParameter);
+ return (t == Parameter || t == Prefix);
}
}
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 };
+ ReallyHidden = 0x4, Extern = 0x8,
+ OneOrMore = 0x10, ZeroOrOne = 0x20 };
}
/// OptionDescription - Represents data contained in a single
std::string Name;
unsigned Flags;
std::string Help;
+ unsigned MultiVal;
OptionDescription(OptionType::OptionType t = OptionType::Switch,
const std::string& n = "",
const std::string& h = DefaultHelpString)
- : Type(t), Name(n), Flags(0x0), Help(h)
+ : Type(t), Name(n), Flags(0x0), Help(h), MultiVal(1)
{}
/// GenTypeDeclaration - Returns the C++ variable type of this
// Misc convenient getters/setters.
bool isAlias() const;
+
+ bool isMultiVal() const;
+
bool isExtern() const;
+ void setExtern();
bool isRequired() const;
void setRequired();
+ bool isOneOrMore() const;
+ void setOneOrMore();
+
+ bool isZeroOrOne() const;
+ void setZeroOrOne();
+
bool isHidden() const;
void setHidden();
bool isReallyHidden() const;
void setReallyHidden();
+
};
void OptionDescription::Merge (const OptionDescription& other)
return Type == OptionType::Alias;
}
+bool OptionDescription::isMultiVal() const {
+ return MultiVal > 1;
+}
+
bool OptionDescription::isExtern() const {
- return (Type == OptionType::ExternList || Type == OptionType::ExternParameter
- || Type == OptionType::ExternSwitch);
+ return Flags & OptionDescriptionFlags::Extern;
+}
+void OptionDescription::setExtern() {
+ Flags |= OptionDescriptionFlags::Extern;
}
bool OptionDescription::isRequired() const {
Flags |= OptionDescriptionFlags::Required;
}
+bool OptionDescription::isOneOrMore() const {
+ return Flags & OptionDescriptionFlags::OneOrMore;
+}
+void OptionDescription::setOneOrMore() {
+ Flags |= OptionDescriptionFlags::OneOrMore;
+}
+
+bool OptionDescription::isZeroOrOne() const {
+ return Flags & OptionDescriptionFlags::ZeroOrOne;
+}
+void OptionDescription::setZeroOrOne() {
+ Flags |= OptionDescriptionFlags::ZeroOrOne;
+}
+
bool OptionDescription::isHidden() const {
return Flags & OptionDescriptionFlags::Hidden;
}
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 "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:
: HandlerTable<CollectOptionProperties>(this), optDesc_(OD)
{
if (!staticMembersInitialized_) {
+ AddHandler("extern", &CollectOptionProperties::onExtern);
AddHandler("help", &CollectOptionProperties::onHelp);
AddHandler("hidden", &CollectOptionProperties::onHidden);
+ AddHandler("multi_val", &CollectOptionProperties::onMultiVal);
+ AddHandler("one_or_more", &CollectOptionProperties::onOneOrMore);
AddHandler("really_hidden", &CollectOptionProperties::onReallyHidden);
AddHandler("required", &CollectOptionProperties::onRequired);
+ AddHandler("zero_or_one", &CollectOptionProperties::onZeroOrOne);
staticMembersInitialized_ = true;
}
/// Option property handlers --
/// Methods that handle option properties such as (help) or (hidden).
+ void onExtern (const DagInit* d) {
+ checkNumberOfArguments(d, 0);
+ optDesc_.setExtern();
+ }
+
void onHelp (const DagInit* d) {
checkNumberOfArguments(d, 1);
- const std::string& help_message = InitPtrToString(d->getArg(0));
- optDesc_.Help = help_message;
+ optDesc_.Help = InitPtrToString(d->getArg(0));
}
void onHidden (const DagInit* d) {
checkNumberOfArguments(d, 0);
- checkToolProps(d);
optDesc_.setHidden();
}
void onReallyHidden (const DagInit* d) {
checkNumberOfArguments(d, 0);
- checkToolProps(d);
optDesc_.setReallyHidden();
}
void onRequired (const DagInit* d) {
checkNumberOfArguments(d, 0);
- checkToolProps(d);
+ if (optDesc_.isOneOrMore())
+ throw std::string("An option can't have both (required) "
+ "and (one_or_more) properties!");
optDesc_.setRequired();
}
- // Helper functions
+ 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 "
+ "on a non-list option will have no effect.\n";
+ optDesc_.setOneOrMore();
+ }
+
+ void onZeroOrOne (const DagInit* d) {
+ checkNumberOfArguments(d, 0);
+ if (optDesc_.isRequired() || optDesc_.isOneOrMore())
+ 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"
+ "on a non-list option will have no effect.\n";
+ optDesc_.setZeroOrOne();
+ }
- /// checkToolProps - Throw an error if toolProps_ == 0.
- void checkToolProps(const DagInit* d) {
- if (!d)
- throw "Option property " + d->getOperator()->getAsString()
- + " can't be used in this context";
+ void onMultiVal (const DagInit* d) {
+ checkNumberOfArguments(d, 1);
+ int val = InitPtrToInt(d->getArg(0));
+ if (val < 2)
+ throw std::string("Error in the 'multi_val' property: "
+ "the value must be greater than 1!");
+ if (!OptionType::IsList(optDesc_.Type))
+ throw std::string("The multi_val property is valid only "
+ "on list options!");
+ optDesc_.MultiVal = val;
}
};
void onActions (const DagInit* d) {
checkNumberOfArguments(d, 1);
- toolDesc_.Actions = d->getArg(0);
+ Init* Case = d->getArg(0);
+ if (typeid(*Case) != typeid(DagInit) ||
+ static_cast<DagInit*>(Case)->getOperator()->getAsString() != "case")
+ throw
+ std::string("The argument to (actions) should be a 'case' construct!");
+ toolDesc_.Actions = Case;
}
void onCmdLine (const DagInit* d) {
};
-
/// CollectToolDescriptions - Gather information about tool properties
/// from the parsed TableGen data (basically a wrapper for the
/// CollectToolProperties function object).
E = EdgeVector.end(); B != E; ++B) {
const Record* Edge = *B;
- const std::string& A = Edge->getValueAsString("a");
- const std::string& B = Edge->getValueAsString("b");
+ const std::string& NodeA = Edge->getValueAsString("a");
+ const std::string& NodeB = Edge->getValueAsString("b");
- if (A != "root")
- ToolsInGraph.insert(A);
- ToolsInGraph.insert(B);
+ if (NodeA != "root")
+ ToolsInGraph.insert(NodeA);
+ ToolsInGraph.insert(NodeB);
}
// Filter ToolPropertiesList.
for (RecordVector::const_iterator B = EdgeVector.begin(),
E = EdgeVector.end(); B != E; ++B) {
const Record* Edge = *B;
- const std::string& A = Edge->getValueAsString("a");
- const std::string& B = Edge->getValueAsString("b");
- StringMap<std::string>::iterator IA = ToolToOutLang.find(A);
- StringMap<StringSet<> >::iterator IB = ToolToInLang.find(B);
+ const std::string& NodeA = Edge->getValueAsString("a");
+ const std::string& NodeB = Edge->getValueAsString("b");
+ StringMap<std::string>::iterator IA = ToolToOutLang.find(NodeA);
+ StringMap<StringSet<> >::iterator IB = ToolToInLang.find(NodeB);
- if (A != "root") {
+ if (NodeA != "root") {
if (IA != IAE && IB != IBE && IB->second.count(IA->second) == 0)
- throw "Edge " + A + "->" + B
+ throw "Edge " + NodeA + "->" + NodeB
+ ": output->input language mismatch";
}
- if (B == "root")
+ if (NodeB == "root")
throw std::string("Edges back to the root are not allowed!");
}
}
if (ActionName == "forward" || ActionName == "forward_as" ||
ActionName == "unpack_values" || ActionName == "switch_on" ||
ActionName == "parameter_equals" || ActionName == "element_in_list" ||
- ActionName == "not_empty") {
+ ActionName == "not_empty" || ActionName == "empty") {
checkNumberOfArguments(&Stmt, 1);
const std::string& Name = InitPtrToString(Stmt.getArg(0));
OptionNames_.insert(Name);
std::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))
// TODO: make this work with Edge::Weight (if possible).
O << "LangMap.GetLanguage(inFile) == \"" << OptName << '\"';
return true;
- } else if (TestName == "not_empty") {
+ } else if (TestName == "not_empty" || TestName == "empty") {
+ const char* Test = (TestName == "empty") ? "" : "!";
+
if (OptName == "o") {
- O << "!OutputFilename.empty()";
+ O << Test << "OutputFilename.empty()";
return true;
}
else {
if (OptionType::IsSwitch(OptDesc.Type))
throw OptName
+ ": incorrect option type - should be a list or parameter!";
- O << '!' << OptDesc.GenVariableName() << ".empty()";
+ O << Test << OptDesc.GenVariableName() << ".empty()";
return true;
}
}
}
}
+/// TokenizeCmdline - converts from "$CALL(HookName, 'Arg1', 'Arg2')/path" to
+/// ["$CALL(", "HookName", "Arg1", "Arg2", ")/path"] .
+/// Helper function used by EmitCmdLineVecFill and.
+void TokenizeCmdline(const std::string& CmdLine, StrVector& Out) {
+ const char* Delimiters = " \t\n\v\f\r";
+ enum TokenizerState
+ { Normal, SpecialCommand, InsideSpecialCommand, InsideQuotationMarks }
+ cur_st = Normal;
+ 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];
+
+ switch (cur_st) {
+ case Normal:
+ if (cur_ch == '$') {
+ cur_st = SpecialCommand;
+ break;
+ }
+ if (oneOf(Delimiters, cur_ch)) {
+ // Skip whitespace
+ B = CmdLine.find_first_not_of(Delimiters, B);
+ if (B == std::string::npos) {
+ B = E-1;
+ continue;
+ }
+ --B;
+ Out.push_back("");
+ continue;
+ }
+ break;
+
+
+ case SpecialCommand:
+ if (oneOf(Delimiters, cur_ch)) {
+ cur_st = Normal;
+ Out.push_back("");
+ continue;
+ }
+ if (cur_ch == '(') {
+ Out.push_back("");
+ cur_st = InsideSpecialCommand;
+ continue;
+ }
+ break;
+
+ case InsideSpecialCommand:
+ if (oneOf(Delimiters, cur_ch)) {
+ continue;
+ }
+ if (cur_ch == '\'') {
+ cur_st = InsideQuotationMarks;
+ Out.push_back("");
+ continue;
+ }
+ if (cur_ch == ')') {
+ cur_st = Normal;
+ Out.push_back("");
+ }
+ if (cur_ch == ',') {
+ continue;
+ }
+
+ break;
+
+ case InsideQuotationMarks:
+ if (cur_ch == '\'') {
+ cur_st = InsideSpecialCommand;
+ continue;
+ }
+ break;
+ }
+
+ Out.back().push_back(cur_ch);
+ }
+}
+
/// SubstituteSpecialCommands - Perform string substitution for $CALL
/// and $ENV. Helper function used by EmitCmdLineVecFill().
-std::string SubstituteSpecialCommands(const std::string& cmd) {
- size_t cparen = cmd.find(")");
- std::string ret;
+StrVector::const_iterator SubstituteSpecialCommands
+(StrVector::const_iterator Pos, StrVector::const_iterator End, std::ostream& O)
+{
+
+ const std::string& cmd = *Pos;
- if (cmd.find("$CALL(") == 0) {
- if (cmd.size() == 6)
+ if (cmd == "$CALL") {
+ checkedIncrement(Pos, End, "Syntax error in $CALL invocation!");
+ const std::string& CmdName = *Pos;
+
+ if (CmdName == ")")
throw std::string("$CALL invocation: empty argument list!");
- ret += "hooks::";
- ret += std::string(cmd.begin() + 6, cmd.begin() + cparen);
- ret += "()";
+ O << "hooks::";
+ O << CmdName << "(";
+
+
+ bool firstIteration = true;
+ while (true) {
+ checkedIncrement(Pos, End, "Syntax error in $CALL invocation!");
+ const std::string& Arg = *Pos;
+ assert(Arg.size() != 0);
+
+ if (Arg[0] == ')')
+ break;
+
+ if (firstIteration)
+ firstIteration = false;
+ else
+ O << ", ";
+
+ O << '"' << Arg << '"';
+ }
+
+ O << ')';
+
}
- else if (cmd.find("$ENV(") == 0) {
- if (cmd.size() == 5)
- throw std::string("$ENV invocation: empty argument list!");
+ else if (cmd == "$ENV") {
+ checkedIncrement(Pos, End, "Syntax error in $ENV invocation!");
+ const std::string& EnvName = *Pos;
+
+ if (EnvName == ")")
+ throw "$ENV invocation: empty argument list!";
+
+ O << "checkCString(std::getenv(\"";
+ O << EnvName;
+ O << "\"))";
- ret += "checkCString(std::getenv(\"";
- ret += std::string(cmd.begin() + 5, cmd.begin() + cparen);
- ret += "\"))";
+ checkedIncrement(Pos, End, "Syntax error in $ENV invocation!");
}
else {
throw "Unknown special command: " + cmd;
}
- if (cmd.begin() + cparen + 1 != cmd.end()) {
- ret += " + std::string(\"";
- ret += (cmd.c_str() + cparen + 1);
- ret += "\")";
- }
+ const std::string& Leftover = *Pos;
+ assert(Leftover.at(0) == ')');
+ if (Leftover.size() != 1)
+ O << " + std::string(\"" << (Leftover.c_str() + 1) << "\")";
+ O << ')';
- return ret;
+ return Pos;
}
/// EmitCmdLineVecFill - Emit code that fills in the command line
bool IsJoin, const char* IndentLevel,
std::ostream& O) {
StrVector StrVec;
- SplitString(InitPtrToString(CmdLine), StrVec);
+ TokenizeCmdline(InitPtrToString(CmdLine), StrVec);
+
if (StrVec.empty())
throw "Tool " + ToolName + " has empty command line!";
- StrVector::const_iterator I = StrVec.begin();
- ++I;
- for (StrVector::const_iterator E = StrVec.end(); I != E; ++I) {
+ StrVector::const_iterator I = StrVec.begin(), E = StrVec.end();
+
+ // If there is a hook invocation on the place of the first command, skip it.
+ if (StrVec[0][0] == '$') {
+ while (I != E && (*I)[0] != ')' )
+ ++I;
+
+ // Skip the ')' symbol.
+ ++I;
+ }
+ else {
+ ++I;
+ }
+
+ for (; I != E; ++I) {
const std::string& cmd = *I;
+ // std::cerr << cmd;
O << IndentLevel;
if (cmd.at(0) == '$') {
if (cmd == "$INFILE") {
O << "vec.push_back(out_file);\n";
}
else {
- O << "vec.push_back(" << SubstituteSpecialCommands(cmd);
+ O << "vec.push_back(";
+ I = SubstituteSpecialCommands(I, E, O);
O << ");\n";
}
}
O << "vec.push_back(\"" << cmd << "\");\n";
}
}
- O << IndentLevel << "cmd = "
- << ((StrVec[0][0] == '$') ? SubstituteSpecialCommands(StrVec[0])
- : "\"" + StrVec[0] + "\"")
- << ";\n";
+ O << IndentLevel << "cmd = ";
+
+ if (StrVec[0][0] == '$')
+ SubstituteSpecialCommands(StrVec.begin(), StrVec.end(), O);
+ else
+ O << '"' << StrVec[0] << '"';
+ O << ";\n";
}
/// EmitCmdLineVecFillCallback - A function object wrapper around
switch (D.Type) {
case OptionType::Switch:
- case OptionType::ExternSwitch:
O << Indent << "vec.push_back(\"" << Name << "\");\n";
break;
case OptionType::Parameter:
- case OptionType::ExternParameter:
O << Indent << "vec.push_back(\"" << Name << "\");\n";
O << Indent << "vec.push_back(" << D.GenVariableName() << ");\n";
break;
case OptionType::PrefixList:
O << Indent << "for (" << D.GenTypeDeclaration()
<< "::iterator B = " << D.GenVariableName() << ".begin(),\n"
- << Indent << "E = " << D.GenVariableName() << ".end(); B != E; ++B)\n"
+ << Indent << "E = " << D.GenVariableName() << ".end(); B != E;) {\n"
<< Indent << Indent1 << "vec.push_back(\"" << Name << "\" + "
- << "*B);\n";
+ << "*B);\n"
+ << Indent << Indent1 << "++B;\n";
+
+ for (int i = 1, j = D.MultiVal; i < j; ++i) {
+ O << Indent << Indent1 << "vec.push_back(*B);\n"
+ << Indent << Indent1 << "++B;\n";
+ }
+
+ O << Indent << "}\n";
break;
case OptionType::ParameterList:
- case OptionType::ExternList:
O << Indent << "for (" << D.GenTypeDeclaration()
<< "::iterator B = " << D.GenVariableName() << ".begin(),\n"
<< Indent << "E = " << D.GenVariableName()
- << ".end() ; B != E; ++B) {\n"
- << Indent << Indent1 << "vec.push_back(\"" << Name << "\");\n"
- << Indent << Indent1 << "vec.push_back(*B);\n"
- << Indent << "}\n";
+ << ".end() ; B != E;) {\n"
+ << Indent << Indent1 << "vec.push_back(\"" << Name << "\");\n";
+
+ for (int i = 0, j = D.MultiVal; i < j; ++i) {
+ O << Indent << Indent1 << "vec.push_back(*B);\n"
+ << Indent << Indent1 << "++B;\n";
+ }
+
+ O << Indent << "}\n";
break;
case OptionType::Alias:
default:
if (ActionName == "append_cmd") {
checkNumberOfArguments(&Dag, 1);
const std::string& Cmd = InitPtrToString(Dag.getArg(0));
- O << IndentLevel << "vec.push_back(\"" << Cmd << "\");\n";
+ StrVector Out;
+ llvm::SplitString(Cmd, Out);
+
+ for (StrVector::const_iterator B = Out.begin(), E = Out.end();
+ B != E; ++B)
+ O << IndentLevel << "vec.push_back(\"" << *B << "\");\n";
+ }
+ else if (ActionName == "error") {
+ O << IndentLevel << "throw std::runtime_error(\"" <<
+ (Dag.getNumArgs() >= 1 ? InitPtrToString(Dag.getArg(0))
+ : "Unknown error!")
+ << "\");\n";
}
else if (ActionName == "forward") {
checkNumberOfArguments(&Dag, 1);
const std::string& Name = InitPtrToString(Dag.getArg(0));
const OptionDescription& D = OptDescs.FindOption(Name);
+ if (D.isMultiVal())
+ throw std::string("Can't use unpack_values with multi-valued options!");
+
if (OptionType::IsList(D.Type)) {
O << IndentLevel << "for (" << D.GenTypeDeclaration()
<< "::iterator B = " << D.GenVariableName() << ".begin(),\n"
O << ", cl::Prefix";
if (val.isRequired()) {
- switch (val.Type) {
- case OptionType::PrefixList:
- case OptionType::ParameterList:
+ if (OptionType::IsList(val.Type) && !val.isMultiVal())
O << ", cl::OneOrMore";
- break;
- default:
+ else
O << ", cl::Required";
- }
+ }
+ else if (val.isOneOrMore() && OptionType::IsList(val.Type)) {
+ O << ", cl::OneOrMore";
+ }
+ else if (val.isZeroOrOne() && OptionType::IsList(val.Type)) {
+ O << ", cl::ZeroOrOne";
}
- if (val.isReallyHidden() || val.isHidden()) {
- if (val.isRequired())
- O << " |";
- else
- O << ",";
- if (val.isReallyHidden())
- O << " cl::ReallyHidden";
- else
- O << " cl::Hidden";
+ if (val.isReallyHidden()) {
+ O << ", cl::ReallyHidden";
+ }
+ else if (val.isHidden()) {
+ O << ", cl::Hidden";
}
+ if (val.MultiVal > 1)
+ O << ", cl::multi_val(" << val.MultiVal << ")";
+
if (!val.Help.empty())
O << ", cl::desc(\"" << val.Help << "\")";
void EmitPopulateLanguageMap (const RecordKeeper& Records, std::ostream& O)
{
// Generate code
- O << "namespace {\n\n";
O << "void PopulateLanguageMapLocal(LanguageMap& langMap) {\n";
// Get the relevant field out of RecordKeeper
}
}
- O << "}\n\n}\n\n";
+ O << "}\n\n";
}
/// IncDecWeight - Helper function passed to EmitCaseConstructHandler()
const DagInit& d = InitPtrToDag(i);
const std::string& OpName = d.getOperator()->getAsString();
- if (OpName == "inc_weight")
+ if (OpName == "inc_weight") {
O << IndentLevel << "ret += ";
- else if (OpName == "dec_weight")
+ }
+ else if (OpName == "dec_weight") {
O << IndentLevel << "ret -= ";
+ }
+ else if (OpName == "error") {
+ O << IndentLevel << "throw std::runtime_error(\"" <<
+ (d.getNumArgs() >= 1 ? InitPtrToString(d.getArg(0))
+ : "Unknown error!")
+ << "\");\n";
+ return;
+ }
+
else
- throw "Unknown operator in edge properties list: " + OpName + '!';
+ throw "Unknown operator in edge properties list: " + OpName + '!' +
+ "\nOnly 'inc_weight', 'dec_weight' and 'error' are allowed.";
if (d.getNumArgs() > 0)
O << InitPtrToInt(d.getArg(0)) << ";\n";
const OptionDescriptions& OptDescs,
std::ostream& O) {
int i = 0;
- for (RecordVector::const_iterator Beg = EdgeVector.begin(),
- E = EdgeVector.end(); Beg != E; ++Beg) {
- const Record* Edge = *Beg;
- const std::string& B = Edge->getValueAsString("b");
+ for (RecordVector::const_iterator B = EdgeVector.begin(),
+ E = EdgeVector.end(); B != E; ++B) {
+ const Record* Edge = *B;
+ const std::string& NodeB = Edge->getValueAsString("b");
DagInit* Weight = Edge->getValueAsDag("weight");
if (!isDagEmpty(Weight))
- EmitEdgeClass(i, B, Weight, OptDescs, O);
+ EmitEdgeClass(i, NodeB, Weight, OptDescs, O);
++i;
}
}
const ToolDescriptions& ToolDescs,
std::ostream& O)
{
- O << "namespace {\n\n";
O << "void PopulateCompilationGraphLocal(CompilationGraph& G) {\n";
for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
// Insert edges.
int i = 0;
- for (RecordVector::const_iterator Beg = EdgeVector.begin(),
- E = EdgeVector.end(); Beg != E; ++Beg) {
- const Record* Edge = *Beg;
- const std::string& A = Edge->getValueAsString("a");
- const std::string& B = Edge->getValueAsString("b");
+ for (RecordVector::const_iterator B = EdgeVector.begin(),
+ E = EdgeVector.end(); B != E; ++B) {
+ const Record* Edge = *B;
+ const std::string& NodeA = Edge->getValueAsString("a");
+ const std::string& NodeB = Edge->getValueAsString("b");
DagInit* Weight = Edge->getValueAsDag("weight");
- O << Indent1 << "G.insertEdge(\"" << A << "\", ";
+ O << Indent1 << "G.insertEdge(\"" << NodeA << "\", ";
if (isDagEmpty(Weight))
- O << "new SimpleEdge(\"" << B << "\")";
+ O << "new SimpleEdge(\"" << NodeB << "\")";
else
O << "new Edge" << i << "()";
++i;
}
- O << "}\n\n}\n\n";
+ O << "}\n\n";
}
/// ExtractHookNames - Extract the hook names from all instances of
/// $CALL(HookName) in the provided command line string. Helper
/// function used by FillInHookNames().
class ExtractHookNames {
- llvm::StringSet<>& HookNames_;
+ llvm::StringMap<unsigned>& HookNames_;
public:
- ExtractHookNames(llvm::StringSet<>& HookNames)
- : HookNames_(HookNames_) {}
+ ExtractHookNames(llvm::StringMap<unsigned>& HookNames)
+ : HookNames_(HookNames) {}
void operator()(const Init* CmdLine) {
StrVector cmds;
- llvm::SplitString(InitPtrToString(CmdLine), cmds);
+ TokenizeCmdline(InitPtrToString(CmdLine), cmds);
for (StrVector::const_iterator B = cmds.begin(), E = cmds.end();
B != E; ++B) {
const std::string& cmd = *B;
- if (cmd.find("$CALL(") == 0) {
- if (cmd.size() == 6)
- throw std::string("$CALL invocation: empty argument list!");
- HookNames_.insert(std::string(cmd.begin() + 6,
- cmd.begin() + cmd.find(")")));
+
+ if (cmd == "$CALL") {
+ unsigned NumArgs = 0;
+ checkedIncrement(B, E, "Syntax error in $CALL invocation!");
+ const std::string& HookName = *B;
+
+
+ if (HookName.at(0) == ')')
+ throw "$CALL invoked with no arguments!";
+
+ while (++B != E && B->at(0) != ')') {
+ ++NumArgs;
+ }
+
+ StringMap<unsigned>::const_iterator H = HookNames_.find(HookName);
+
+ if (H != HookNames_.end() && H->second != NumArgs)
+ throw "Overloading of hooks is not allowed. Overloaded hook: "
+ + HookName;
+ else
+ HookNames_[HookName] = NumArgs;
+
}
}
}
/// FillInHookNames - Actually extract the hook names from all command
/// line strings. Helper function used by EmitHookDeclarations().
void FillInHookNames(const ToolDescriptions& ToolDescs,
- llvm::StringSet<>& HookNames)
+ llvm::StringMap<unsigned>& HookNames)
{
// For all command lines:
for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
/// property records and emit hook function declaration for each
/// instance of $CALL(HookName).
void EmitHookDeclarations(const ToolDescriptions& ToolDescs, std::ostream& O) {
- llvm::StringSet<> HookNames;
+ llvm::StringMap<unsigned> HookNames;
+
FillInHookNames(ToolDescs, HookNames);
if (HookNames.empty())
return;
O << "namespace hooks {\n";
- for (StringSet<>::const_iterator B = HookNames.begin(), E = HookNames.end();
- B != E; ++B)
- O << Indent1 << "std::string " << B->first() << "();\n";
+ for (StringMap<unsigned>::const_iterator B = HookNames.begin(),
+ E = HookNames.end(); B != E; ++B) {
+ O << Indent1 << "std::string " << B->first() << "(";
+
+ for (unsigned i = 0, j = B->second; i < j; ++i) {
+ O << "const char* Arg" << i << (i+1 == j ? "" : ", ");
+ }
+ O <<");\n";
+ }
O << "}\n\n";
}
/// EmitRegisterPlugin - Emit code to register this plugin.
void EmitRegisterPlugin(int Priority, std::ostream& O) {
- O << "namespace {\n\n"
- << "struct Plugin : public llvmc::BasePlugin {\n\n"
+ O << "struct Plugin : public llvmc::BasePlugin {\n\n"
<< Indent1 << "int Priority() const { return " << Priority << "; }\n\n"
<< Indent1 << "void PopulateLanguageMap(LanguageMap& langMap) const\n"
<< Indent1 << "{ PopulateLanguageMapLocal(langMap); }\n\n"
<< Indent1 << "{ PopulateCompilationGraphLocal(graph); }\n"
<< "};\n\n"
- << "static llvmc::RegisterPlugin<Plugin> RP;\n\n}\n\n";
+ << "static llvmc::RegisterPlugin<Plugin> RP;\n\n";
}
/// EmitIncludes - Emit necessary #include directives and some
// Emit hook declarations.
EmitHookDeclarations(Data.ToolDescs, O);
+ O << "namespace {\n\n";
+
// Emit PopulateLanguageMap() function
// (a language map maps from file extensions to language names).
EmitPopulateLanguageMap(Records, O);
// Emit code for plugin registration.
EmitRegisterPlugin(Data.Priority, O);
+ O << "} // End anonymous namespace.\n";
// EOF
}