llvm-6502/utils/TableGen/OptParserEmitter.cpp
David Greene d4a9066c93 [AVX] Make Inits Foldable
Manage Inits in a FoldingSet.  This provides several benefits:

- Memory for Inits is properly managed

- Duplicate Inits are folded into Flyweights, saving memory

- It enforces const-correctness, protecting against certain classes
  of bugs

The above benefits allow Inits to be used in more contexts, which in
turn provides more dynamism to TableGen.  This enhanced capability
will be used by the AVX code generator to a fold common patterns
together.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134907 91177308-0d34-0410-b5e6-96231b3b80d8
2011-07-11 18:25:51 +00:00

195 lines
5.5 KiB
C++

//===- 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 "OptParserEmitter.h"
#include "Record.h"
#include "llvm/ADT/STLExtras.h"
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 = *(Record**) Av;
const Record *B = *(Record**) 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;
// Then by the kind precedence;
int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence");
int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence");
assert(APrec != BPrec && "Options are equivalent!");
return APrec < BPrec ? -1 : 1;
}
static const std::string getOptionName(const Record &R) {
// Use the record name unless EnumName is defined.
if (dynamic_cast<const 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;
}
void OptParserEmitter::run(raw_ostream &OS) {
// Get the option groups and options.
const std::vector<Record*> &Groups =
Records.getAllDerivedDefinitions("OptionGroup");
std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");
if (GenDefs)
EmitSourceFileHeader("Option Parsing Definitions", OS);
else
EmitSourceFileHeader("Option Parsing Table", OS);
array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
if (GenDefs) {
OS << "#ifndef OPTION\n";
OS << "#error \"Define OPTION prior to including this file!\"\n";
OS << "#endif\n\n";
OS << "/////////\n";
OS << "// Groups\n\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 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 = dynamic_cast<const 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 (!dynamic_cast<const 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 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 = dynamic_cast<const DefInit*>(R.getValueInit("Group")))
OS << getOptionName(*DI->getDef());
else
OS << "INVALID";
// The option alias (if any).
OS << ", ";
if (const DefInit *DI = dynamic_cast<const 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 << dynamic_cast<const DefInit*>(LI->getElement(i))->getDef()->getName();
}
}
// The option parameter field.
OS << ", " << R.getValueAsInt("NumArgs");
// The option help text.
if (!dynamic_cast<const UnsetInit*>(R.getValueInit("HelpText"))) {
OS << ",\n";
OS << " ";
write_cstring(OS, R.getValueAsString("HelpText"));
} else
OS << ", 0";
// The option meta-variable name.
OS << ", ";
if (!dynamic_cast<const UnsetInit*>(R.getValueInit("MetaVarName")))
write_cstring(OS, R.getValueAsString("MetaVarName"));
else
OS << "0";
OS << ")\n";
}
}
}