diff options
author | Chris Lattner <sabre@nondot.org> | 2003-10-05 19:32:12 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2003-10-05 19:32:12 +0000 |
commit | 5516347535ddf0c27cd207135ebf9ce975f30673 (patch) | |
tree | 4b89b4e60378e5864eaa0c27c1febe8246ee2805 | |
parent | 091bbbada30ef4c17e5f66b740adda0acf7cc31a (diff) | |
download | llvm-5516347535ddf0c27cd207135ebf9ce975f30673.tar.gz llvm-5516347535ddf0c27cd207135ebf9ce975f30673.tar.bz2 llvm-5516347535ddf0c27cd207135ebf9ce975f30673.tar.xz |
Move support/lib into lib/Support
Move support/tools into utils
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8878 91177308-0d34-0410-b5e6-96231b3b80d8
71 files changed, 0 insertions, 14629 deletions
diff --git a/support/Makefile b/support/Makefile deleted file mode 100644 index ba074f506c..0000000000 --- a/support/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -LEVEL = .. - -DIRS = lib tools - -include $(LEVEL)/Makefile.common - diff --git a/support/lib/Makefile b/support/lib/Makefile deleted file mode 100644 index f5446d31f6..0000000000 --- a/support/lib/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -LEVEL = ../.. - -DIRS = Support - -include $(LEVEL)/Makefile.common - diff --git a/support/lib/Support/Annotation.cpp b/support/lib/Support/Annotation.cpp deleted file mode 100644 index 9166240b82..0000000000 --- a/support/lib/Support/Annotation.cpp +++ /dev/null @@ -1,89 +0,0 @@ -//===-- Annotation.cpp - Implement the Annotation Classes --------*- C++ -*--=// -// -// This file implements the AnnotationManager class. -// -//===----------------------------------------------------------------------===// - -#include <map> -#include "Support/Annotation.h" - -typedef std::map<const std::string, unsigned> IDMapType; -static unsigned IDCounter = 0; // Unique ID counter - -// Static member to ensure initialiation on demand. -static IDMapType &getIDMap() { static IDMapType TheMap; return TheMap; } - -// On demand annotation creation support... -typedef Annotation *(*AnnFactory)(AnnotationID, const Annotable *, void *); -typedef std::map<unsigned, std::pair<AnnFactory,void*> > FactMapType; - -static FactMapType *TheFactMap = 0; -static FactMapType &getFactMap() { - if (TheFactMap == 0) - TheFactMap = new FactMapType(); - return *TheFactMap; -} - -static void eraseFromFactMap(unsigned ID) { - assert(TheFactMap && "No entries found!"); - TheFactMap->erase(ID); - if (TheFactMap->empty()) { // Delete when empty - delete TheFactMap; - TheFactMap = 0; - } -} - - -AnnotationID AnnotationManager::getID(const std::string &Name) { // Name -> ID - IDMapType::iterator I = getIDMap().find(Name); - if (I == getIDMap().end()) { - getIDMap()[Name] = IDCounter++; // Add a new element - return IDCounter-1; - } - return I->second; -} - -// getID - Name -> ID + registration of a factory function for demand driven -// annotation support. -AnnotationID AnnotationManager::getID(const std::string &Name, Factory Fact, - void *Data) { - AnnotationID Result(getID(Name)); - registerAnnotationFactory(Result, Fact, Data); - return Result; -} - - -// getName - This function is especially slow, but that's okay because it should -// only be used for debugging. -// -const std::string &AnnotationManager::getName(AnnotationID ID) { // ID -> Name - IDMapType &TheMap = getIDMap(); - for (IDMapType::iterator I = TheMap.begin(); ; ++I) { - assert(I != TheMap.end() && "Annotation ID is unknown!"); - if (I->second == ID.ID) return I->first; - } -} - - -// registerAnnotationFactory - This method is used to register a callback -// function used to create an annotation on demand if it is needed by the -// Annotable::findOrCreateAnnotation method. -// -void AnnotationManager::registerAnnotationFactory(AnnotationID ID, - AnnFactory F, - void *ExtraData) { - if (F) - getFactMap()[ID.ID] = std::make_pair(F, ExtraData); - else - eraseFromFactMap(ID.ID); -} - -// createAnnotation - Create an annotation of the specified ID for the -// specified object, using a register annotation creation function. -// -Annotation *AnnotationManager::createAnnotation(AnnotationID ID, - const Annotable *Obj) { - FactMapType::iterator I = getFactMap().find(ID.ID); - if (I == getFactMap().end()) return 0; - return I->second.first(ID, Obj, I->second.second); -} diff --git a/support/lib/Support/CommandLine.cpp b/support/lib/Support/CommandLine.cpp deleted file mode 100644 index c0be0ecb34..0000000000 --- a/support/lib/Support/CommandLine.cpp +++ /dev/null @@ -1,877 +0,0 @@ -//===-- CommandLine.cpp - Command line parser implementation --------------===// -// -// This class implements a command line argument processor that is useful when -// creating a tool. It provides a simple, minimalistic interface that is easily -// extensible and supports nonlocal (library) command line options. -// -// Note that rather than trying to figure out what this code does, you could try -// reading the library documentation located in docs/CommandLine.html -// -//===----------------------------------------------------------------------===// - -#include "Support/CommandLine.h" -#include <algorithm> -#include <map> -#include <set> -#include <iostream> - -using namespace cl; - -//===----------------------------------------------------------------------===// -// Basic, shared command line option processing machinery... -// - -// Return the global command line option vector. Making it a function scoped -// static ensures that it will be initialized correctly before its first use. -// -static std::map<std::string, Option*> *CommandLineOptions = 0; -static std::map<std::string, Option*> &getOpts() { - if (CommandLineOptions == 0) - CommandLineOptions = new std::map<std::string,Option*>(); - return *CommandLineOptions; -} - -static Option *getOption(const std::string &Str) { - if (CommandLineOptions == 0) return 0; - std::map<std::string,Option*>::iterator I = CommandLineOptions->find(Str); - return I != CommandLineOptions->end() ? I->second : 0; -} - -static std::vector<Option*> &getPositionalOpts() { - static std::vector<Option*> Positional; - return Positional; -} - -static void AddArgument(const char *ArgName, Option *Opt) { - if (getOption(ArgName)) { - std::cerr << "CommandLine Error: Argument '" << ArgName - << "' defined more than once!\n"; - } else { - // Add argument to the argument map! - getOpts()[ArgName] = Opt; - } -} - -// RemoveArgument - It's possible that the argument is no longer in the map if -// options have already been processed and the map has been deleted! -// -static void RemoveArgument(const char *ArgName, Option *Opt) { - if (CommandLineOptions == 0) return; - assert(getOption(ArgName) == Opt && "Arg not in map!"); - CommandLineOptions->erase(ArgName); - if (CommandLineOptions->empty()) { - delete CommandLineOptions; - CommandLineOptions = 0; - } -} - -static const char *ProgramName = 0; -static const char *ProgramOverview = 0; - -static inline bool ProvideOption(Option *Handler, const char *ArgName, - const char *Value, int argc, char **argv, - int &i) { - // Enforce value requirements - switch (Handler->getValueExpectedFlag()) { - case ValueRequired: - if (Value == 0 || *Value == 0) { // No value specified? - if (i+1 < argc) { // Steal the next argument, like for '-o filename' - Value = argv[++i]; - } else { - return Handler->error(" requires a value!"); - } - } - break; - case ValueDisallowed: - if (*Value != 0) - return Handler->error(" does not allow a value! '" + - std::string(Value) + "' specified."); - break; - case ValueOptional: break; - default: std::cerr << "Bad ValueMask flag! CommandLine usage error:" - << Handler->getValueExpectedFlag() << "\n"; abort(); - } - - // Run the handler now! - return Handler->addOccurrence(ArgName, Value); -} - -static bool ProvidePositionalOption(Option *Handler, const std::string &Arg) { - int Dummy; - return ProvideOption(Handler, Handler->ArgStr, Arg.c_str(), 0, 0, Dummy); -} - - -// Option predicates... -static inline bool isGrouping(const Option *O) { - return O->getFormattingFlag() == cl::Grouping; -} -static inline bool isPrefixedOrGrouping(const Option *O) { - return isGrouping(O) || O->getFormattingFlag() == cl::Prefix; -} - -// getOptionPred - Check to see if there are any options that satisfy the -// specified predicate with names that are the prefixes in Name. This is -// checked by progressively stripping characters off of the name, checking to -// see if there options that satisfy the predicate. If we find one, return it, -// otherwise return null. -// -static Option *getOptionPred(std::string Name, unsigned &Length, - bool (*Pred)(const Option*)) { - - Option *Op = getOption(Name); - if (Op && Pred(Op)) { - Length = Name.length(); - return Op; - } - - if (Name.size() == 1) return 0; - do { - Name.erase(Name.end()-1, Name.end()); // Chop off the last character... - Op = getOption(Name); - - // Loop while we haven't found an option and Name still has at least two - // characters in it (so that the next iteration will not be the empty - // string... - } while ((Op == 0 || !Pred(Op)) && Name.size() > 1); - - if (Op && Pred(Op)) { - Length = Name.length(); - return Op; // Found one! - } - return 0; // No option found! -} - -static bool RequiresValue(const Option *O) { - return O->getNumOccurrencesFlag() == cl::Required || - O->getNumOccurrencesFlag() == cl::OneOrMore; -} - -static bool EatsUnboundedNumberOfValues(const Option *O) { - return O->getNumOccurrencesFlag() == cl::ZeroOrMore || - O->getNumOccurrencesFlag() == cl::OneOrMore; -} - -/// ParseCStringVector - Break INPUT up wherever one or more -/// whitespace characters are found, and store the resulting tokens in -/// OUTPUT. The tokens stored in OUTPUT are dynamically allocated -/// using strdup (), so it is the caller's responsibility to free () -/// them later. -/// -static void ParseCStringVector (std::vector<char *> &output, - const char *input) { - // Characters which will be treated as token separators: - static const char *delims = " \v\f\t\r\n"; - - std::string work (input); - // Skip past any delims at head of input string. - size_t pos = work.find_first_not_of (delims); - // If the string consists entirely of delims, then exit early. - if (pos == std::string::npos) return; - // Otherwise, jump forward to beginning of first word. - work = work.substr (pos); - // Find position of first delimiter. - pos = work.find_first_of (delims); - - while (!work.empty() && pos != std::string::npos) { - // Everything from 0 to POS is the next word to copy. - output.push_back (strdup (work.substr (0,pos).c_str ())); - // Is there another word in the string? - size_t nextpos = work.find_first_not_of (delims, pos + 1); - if (nextpos != std::string::npos) { - // Yes? Then remove delims from beginning ... - work = work.substr (work.find_first_not_of (delims, pos + 1)); - // and find the end of the word. - pos = work.find_first_of (delims); - } else { - // No? (Remainder of string is delims.) End the loop. - work = ""; - pos = std::string::npos; - } - } - - // If `input' ended with non-delim char, then we'll get here with - // the last word of `input' in `work'; copy it now. - if (!work.empty ()) { - output.push_back (strdup (work.c_str ())); - } -} - -/// ParseEnvironmentOptions - An alternative entry point to the -/// CommandLine library, which allows you to read the program's name -/// from the caller (as PROGNAME) and its command-line arguments from -/// an environment variable (whose name is given in ENVVAR). -/// -void cl::ParseEnvironmentOptions (const char *progName, const char *envVar, - const char *Overview) { - // Check args. - assert (progName && "Program name not specified"); - assert (envVar && "Environment variable name missing"); - - // Get the environment variable they want us to parse options out of. - const char *envValue = getenv (envVar); - if (!envValue) - return; - - // Get program's "name", which we wouldn't know without the caller - // telling us. - std::vector<char *> newArgv; - newArgv.push_back (strdup (progName)); - - // Parse the value of the environment variable into a "command line" - // and hand it off to ParseCommandLineOptions(). - ParseCStringVector (newArgv, envValue); - int newArgc = newArgv.size (); - ParseCommandLineOptions (newArgc, &newArgv[0], Overview); - - // Free all the strdup()ed strings. - for (std::vector<char *>::iterator i = newArgv.begin (), e = newArgv.end (); - i != e; ++i) { - free (*i); - } -} - -void cl::ParseCommandLineOptions(int &argc, char **argv, - const char *Overview) { - assert((!getOpts().empty() || !getPositionalOpts().empty()) && - "No options specified, or ParseCommandLineOptions called more" - " than once!"); - ProgramName = argv[0]; // Save this away safe and snug - ProgramOverview = Overview; - bool ErrorParsing = false; - - std::map<std::string, Option*> &Opts = getOpts(); - std::vector<Option*> &PositionalOpts = getPositionalOpts(); - - // Check out the positional arguments to collect information about them. - unsigned NumPositionalRequired = 0; - Option *ConsumeAfterOpt = 0; - if (!PositionalOpts.empty()) { - if (PositionalOpts[0]->getNumOccurrencesFlag() == cl::ConsumeAfter) { - assert(PositionalOpts.size() > 1 && - "Cannot specify cl::ConsumeAfter without a positional argument!"); - ConsumeAfterOpt = PositionalOpts[0]; - } - - // Calculate how many positional values are _required_. - bool UnboundedFound = false; - for (unsigned i = ConsumeAfterOpt != 0, e = PositionalOpts.size(); - i != e; ++i) { - Option *Opt = PositionalOpts[i]; - if (RequiresValue(Opt)) - ++NumPositionalRequired; - else if (ConsumeAfterOpt) { - // ConsumeAfter cannot be combined with "optional" positional options - // unless there is only one positional argument... - if (PositionalOpts.size() > 2) - ErrorParsing |= - Opt->error(" error - this positional option will never be matched, " - "because it does not Require a value, and a " - "cl::ConsumeAfter option is active!"); - } else if (UnboundedFound && !Opt->ArgStr[0]) { - // This option does not "require" a value... Make sure this option is - // not specified after an option that eats all extra arguments, or this - // one will never get any! - // - ErrorParsing |= Opt->error(" error - option can never match, because " - "another positional argument will match an " - "unbounded number of values, and this option" - " does not require a value!"); - } - UnboundedFound |= EatsUnboundedNumberOfValues(Opt); - } - } - - // PositionalVals - A vector of "positional" arguments we accumulate into to - // processes at the end... - // - std::vector<std::string> PositionalVals; - - // If the program has named positional arguments, and the name has been run - // across, keep track of which positional argument was named. Otherwise put - // the positional args into the PositionalVals list... - Option *ActivePositionalArg = 0; - - // Loop over all of the arguments... processing them. - bool DashDashFound = false; // Have we read '--'? - for (int i = 1; i < argc; ++i) { - Option *Handler = 0; - const char *Value = ""; - const char *ArgName = ""; - - // Check to see if this is a positional argument. This argument is - // considered to be positional if it doesn't start with '-', if it is "-" - // itself, or if we have seen "--" already. - // - if (argv[i][0] != '-' || argv[i][1] == 0 || DashDashFound) { - // Positional argument! - if (ActivePositionalArg) { - ProvidePositionalOption(ActivePositionalArg, argv[i]); - continue; // We are done! - } else if (!PositionalOpts.empty()) { - PositionalVals.push_back(argv[i]); - - // All of the positional arguments have been fulfulled, give the rest to - // the consume after option... if it's specified... - // - if (PositionalVals.size() >= NumPositionalRequired && - ConsumeAfterOpt != 0) { - for (++i; i < argc; ++i) - PositionalVals.push_back(argv[i]); - break; // Handle outside of the argument processing loop... - } - - // Delay processing positional arguments until the end... - continue; - } - } else { // We start with a '-', must be an argument... - ArgName = argv[i]+1; - while (*ArgName == '-') ++ArgName; // Eat leading dashes - - if (*ArgName == 0 && !DashDashFound) { // Is this the mythical "--"? - DashDashFound = true; // Yup, take note of that fact... - continue; // Don't try to process it as an argument itself. - } - - const char *ArgNameEnd = ArgName; - while (*ArgNameEnd && *ArgNameEnd != '=') - ++ArgNameEnd; // Scan till end of argument name... - - Value = ArgNameEnd; - if (*Value) // If we have an equals sign... - ++Value; // Advance to value... - - if (*ArgName != 0) { - std::string RealName(ArgName, ArgNameEnd); - // Extract arg name part - std::map<std::string, Option*>::iterator I = Opts.find(RealName); - - if (I == Opts.end() && !*Value && RealName.size() > 1) { - // Check to see if this "option" is really a prefixed or grouped - // argument... - // - unsigned Length = 0; - Option *PGOpt = getOptionPred(RealName, Length, isPrefixedOrGrouping); - - // If the option is a prefixed option, then the value is simply the - // rest of the name... so fall through to later processing, by - // setting up the argument name flags and value fields. - // - if (PGOpt && PGOpt->getFormattingFlag() == cl::Prefix) { - ArgNameEnd = ArgName+Length; - Value = ArgNameEnd; - I = Opts.find(std::string(ArgName, ArgNameEnd)); - assert(I->second == PGOpt); - } else if (PGOpt) { - // This must be a grouped option... handle all of them now... - assert(isGrouping(PGOpt) && "Broken getOptionPred!"); - - do { - // Move current arg name out of RealName into RealArgName... - std::string RealArgName(RealName.begin(),RealName.begin()+Length); - RealName.erase(RealName.begin(), RealName.begin()+Length); - - // Because ValueRequired is an invalid flag for grouped arguments, - // we don't need to pass argc/argv in... - // - assert(PGOpt->getValueExpectedFlag() != cl::ValueRequired && - "Option can not be cl::Grouping AND cl::ValueRequired!"); - int Dummy; - ErrorParsing |= ProvideOption(PGOpt, RealArgName.c_str(), "", - 0, 0, Dummy); - - // Get the next grouping option... - if (!RealName.empty()) - PGOpt = getOptionPred(RealName, Length, isGrouping); - } while (!RealName.empty() && PGOpt); - - if (RealName.empty()) // Processed all of the options, move on - continue; // to the next argv[] value... - - // If RealName is not empty, that means we did not match one of the - // options! This is an error. - // - I = Opts.end(); - } - } - - Handler = I != Opts.end() ? I->second : 0; - } - } - - if (Handler == 0) { - std::cerr << "Unknown command line argument '" << argv[i] << "'. Try: '" - << argv[0] << " --help'\n"; - ErrorParsing = true; - continue; - } - - // Check to see if this option accepts a comma separated list of values. If - // it does, we have to split up the value into multiple values... - if (Handler->getMiscFlags() & CommaSeparated) { - std::string Val(Value); - std::string::size_type Pos = Val.find(','); - - while (Pos != std::string::npos) { - // Process the portion before the comma... - ErrorParsing |= ProvideOption(Handler, ArgName, - std::string(Val.begin(), - Val.begin()+Pos).c_str(), - argc, argv, i); - // Erase the portion before the comma, AND the comma... - Val.erase(Val.begin(), Val.begin()+Pos+1); - Value += Pos+1; // Increment the original value pointer as well... - - // Check for another comma... - Pos = Val.find(','); - } - } - - // If this is a named positional argument, just remember that it is the - // active one... - if (Handler->getFormattingFlag() == cl::Positional) - ActivePositionalArg = Handler; - else - ErrorParsing |= ProvideOption(Handler, ArgName, Value, argc, argv, i); - } - - // Check and handle positional arguments now... - if (NumPositionalRequired > PositionalVals.size()) { - std::cerr << "Not enough positional command line arguments specified!\n" - << "Must specify at least " << NumPositionalRequired - << " positional arguments: See: " << argv[0] << " --help\n"; - ErrorParsing = true; - - - } else if (ConsumeAfterOpt == 0) { - // Positional args have already been handled if ConsumeAfter is specified... - unsigned ValNo = 0, NumVals = PositionalVals.size(); - for (unsigned i = 0, e = PositionalOpts.size(); i != e; ++i) { - if (RequiresValue(PositionalOpts[i])) { - ProvidePositionalOption(PositionalOpts[i], PositionalVals[ValNo++]); - --NumPositionalRequired; // We fulfilled our duty... - } - - // If we _can_ give this option more arguments, do so now, as long as we - // do not give it values that others need. 'Done' controls whether the - // option even _WANTS_ any more. - // - bool Done = PositionalOpts[i]->getNumOccurrencesFlag() == cl::Required; - while (NumVals-ValNo > NumPositionalRequired && !Done) { - switch (PositionalOpts[i]->getNumOccurrencesFlag()) { - case cl::Optional: - Done = true; // Optional arguments want _at most_ one value - // FALL THROUGH - case cl::ZeroOrMore: // Zero or more will take all they can get... - case cl::OneOrMore: // One or more will take all they can get... - ProvidePositionalOption(PositionalOpts[i], PositionalVals[ValNo++]); - break; - default: - assert(0 && "Internal error, unexpected NumOccurrences flag in " - "positional argument processing!"); - } - } - } - } else { - assert(ConsumeAfterOpt && NumPositionalRequired <= PositionalVals.size()); - unsigned ValNo = 0; - for (unsigned j = 1, e = PositionalOpts.size(); j != e; ++j) - if (RequiresValue(PositionalOpts[j])) - ErrorParsing |= ProvidePositionalOption(PositionalOpts[j], - PositionalVals[ValNo++]); - - // Handle the case where there is just one positional option, and it's - // optional. In this case, we want to give JUST THE FIRST option to the - // positional option and keep the rest for the consume after. The above - // loop would have assigned no values to positional options in this case. - // - if (PositionalOpts.size() == 2 && ValNo == 0 && !PositionalVals.empty()) - ErrorParsing |= ProvidePositionalOption(PositionalOpts[1], - PositionalVals[ValNo++]); - - // Handle over all of the rest of the arguments to the - // cl::ConsumeAfter command line option... - for (; ValNo != PositionalVals.size(); ++ValNo) - ErrorParsing |= ProvidePositionalOption(ConsumeAfterOpt, - PositionalVals[ValNo]); - } - - // Loop over args and make sure all required args are specified! - for (std::map<std::string, Option*>::iterator I = Opts.begin(), - E = Opts.end(); I != E; ++I) { - switch (I->second->getNumOccurrencesFlag()) { - case Required: - case OneOrMore: - if (I->second->getNumOccurrences() == 0) { - I->second->error(" must be specified at least once!"); - ErrorParsing = true; - } - // Fall through - default: - break; - } - } - - // Free all of the memory allocated to the map. Command line options may only - // be processed once! - delete CommandLineOptions; - CommandLineOptions = 0; - PositionalOpts.clear(); - - // If we had an error processing our arguments, don't let the program execute - if (ErrorParsing) exit(1); -} - -//===----------------------------------------------------------------------===// -// Option Base class implementation -// - -bool Option::error(std::string Message, const char *ArgName) { - if (ArgName == 0) ArgName = ArgStr; - if (ArgName[0] == 0) - std::cerr << HelpStr; // Be nice for positional arguments - else - std::cerr << "-" << ArgName; - std::cerr << " option" << Message << "\n"; - return true; -} - -bool Option::addOccurrence(const char *ArgName, const std::string &Value) { - NumOccurrences++; // Increment the number of times we have been seen - - switch (getNumOccurrencesFlag()) { - case Optional: - if (NumOccurrences > 1) - return error(": may only occur zero or one times!", ArgName); - break; - case Required: - if (NumOccurrences > 1) - return error(": must occur exactly one time!", ArgName); - // Fall through - case OneOrMore: - case ZeroOrMore: - case ConsumeAfter: break; - default: return error(": bad num occurrences flag value!"); - } - - return handleOccurrence(ArgName, Value); -} - -// addArgument - Tell the system that this Option subclass will handle all -// occurrences of -ArgStr on the command line. -// -void Option::addArgument(const char *ArgStr) { - if (ArgStr[0]) - AddArgument(ArgStr, this); - - if (getFormattingFlag() == Positional) - getPositionalOpts().push_back(this); - else if (getNumOccurrencesFlag() == ConsumeAfter) { - if (!getPositionalOpts().empty() && - getPositionalOpts().front()->getNumOccurrencesFlag() == ConsumeAfter) - error("Cannot specify more than one option with cl::ConsumeAfter!"); - getPositionalOpts().insert(getPositionalOpts().begin(), this); - } -} - -void Option::removeArgument(const char *ArgStr) { - if (ArgStr[0]) - RemoveArgument(ArgStr, this); - - if (getFormattingFlag() == Positional) { - std::vector<Option*>::iterator I = - std::find(getPositionalOpts().begin(), getPositionalOpts().end(), this); - assert(I != getPositionalOpts().end() && "Arg not registered!"); - getPositionalOpts().erase(I); - } else if (getNumOccurrencesFlag() == ConsumeAfter) { - assert(!getPositionalOpts().empty() && getPositionalOpts()[0] == this && - "Arg not registered correctly!"); - getPositionalOpts().erase(getPositionalOpts().begin()); - } -} - - -// getValueStr - Get the value description string, using "DefaultMsg" if nothing -// has been specified yet. -// -static const char *getValueStr(const Option &O, const char *DefaultMsg) { - if (O.ValueStr[0] == 0) return DefaultMsg; - return O.ValueStr; -} - -//===----------------------------------------------------------------------===// -// cl::alias class implementation -// - -// Return the width of the option tag for printing... -unsigned alias::getOptionWidth() const { - return std::strlen(ArgStr)+6; -} - -// Print out the option for the alias... -void alias::printOptionInfo(unsigned GlobalWidth) const { - unsigned L = std::strlen(ArgStr); - std::cerr << " -" << ArgStr << std::string(GlobalWidth-L-6, ' ') << " - " - << HelpStr << "\n"; -} - - - -//===----------------------------------------------------------------------===// -// Parser Implementation code... -// - -// basic_parser implementation -// - -// Return the width of the option tag for printing... -unsigned basic_parser_impl::getOptionWidth(const Option &O) const { - unsigned Len = std::strlen(O.ArgStr); - if (const char *ValName = getValueName()) - Len += std::strlen(getValueStr(O, ValName))+3; - - return Len + 6; -} - -// printOptionInfo - Print out information about this option. The -// to-be-maintained width is specified. -// -void basic_parser_impl::printOptionInfo(const Option &O, - unsigned GlobalWidth) const { - std::cerr << " -" << O.ArgStr; - - if (const char *ValName = getValueName()) - std::cerr << "=<" << getValueStr(O, ValName) << ">"; - - std::cerr << std::string(GlobalWidth-getOptionWidth(O), ' ') << " - " - << O.HelpStr << "\n"; -} - - - - -// parser<bool> implementation -// -bool parser<bool>::parse(Option &O, const char *ArgName, - const std::string &Arg, bool &Value) { - if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" || - Arg == "1") { - Value = true; - } else if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") { - Value = false; - } else { - return O.error(": '" + Arg + - "' is invalid value for boolean argument! Try 0 or 1"); - } - return false; -} - -// parser<int> implementation -// -bool parser<int>::parse(Option &O, const char *ArgName, - const std::string &Arg, int &Value) { - char *End; - Value = (int)strtol(Arg.c_str(), &End, 0); - if (*End != 0) - return O.error(": '" + Arg + "' value invalid for integer argument!"); - return false; -} - -// parser<unsigned> implementation -// -bool parser<unsigned>::parse(Option &O, const char *ArgName, - const std::string &Arg, unsigned &Value) { - char *End; - long long int V = strtoll(Arg.c_str(), &End, 0); - Value = (unsigned)V; - if (*End != 0 || V < 0 || Value != V) - return O.error(": '" + Arg + "' value invalid for uint argument!"); - return false; -} - -// parser<double>/parser<float> implementation -// -static bool parseDouble(Option &O, const std::string &Arg, double &Value) { - const char *ArgStart = Arg.c_str(); - char *End; - Value = strtod(ArgStart, &End); - if (*End != 0) - return O.error(": '" +Arg+ "' value invalid for floating point argument!"); - return false; -} - -bool parser<double>::parse(Option &O, const char *AN, - const std::string &Arg, double &Val) { - return parseDouble(O, Arg, Val); -} - -bool parser<float>::parse(Option &O, const char *AN, - const std::string &Arg, float &Val) { - double dVal; - if (parseDouble(O, Arg, dVal)) - return true; - Val = (float)dVal; - return false; -} - - - -// generic_parser_base implementation -// - -// findOption - Return the option number corresponding to the specified -// argument string. If the option is not found, getNumOptions() is returned. -// -unsigned generic_parser_base::findOption(const char *Name) { - unsigned i = 0, e = getNumOptions(); - std::string N(Name); - - while (i != e) - if (getOption(i) == N) - return i; - else - ++i; - return e; -} - - -// Return the width of the option tag for printing... -unsigned generic_parser_base::getOptionWidth(const Option &O) const { - if (O.hasArgStr()) { - unsigned Size = std::strlen(O.ArgStr)+6; - for (unsigned i = 0, e = getNumOptions(); i != e; ++i) - Size = std::max(Size, (unsigned)std::strlen(getOption(i))+8); - return Size; - } else { - unsigned BaseSize = 0; - for (unsigned i = 0, e = getNumOptions(); i != e; ++i) - BaseSize = std::max(BaseSize, (unsigned)std::strlen(getOption(i))+8); - return BaseSize; - } -} - -// printOptionInfo - Print out information about this option. The -// to-be-maintained width is specified. -// -void generic_parser_base::printOptionInfo(const Option &O, - unsigned GlobalWidth) const { - if (O.hasArgStr()) { - unsigned L = std::strlen(O.ArgStr); - std::cerr << " -" << O.ArgStr << std::string(GlobalWidth-L-6, ' ') - << " - " << O.HelpStr << "\n"; - - for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { - unsigned NumSpaces = GlobalWidth-strlen(getOption(i))-8; - std::cerr << " =" << getOption(i) << std::string(NumSpaces, ' ') - << " - " << getDescription(i) << "\n"; - } - } else { - if (O.HelpStr[0]) - std::cerr << " " << O.HelpStr << "\n"; - for (unsigned i = 0, e = getNumOptions(); i != e; ++i) { - unsigned L = std::strlen(getOption(i)); - std::cerr << " -" << getOption(i) << std::string(GlobalWidth-L-8, ' ') - << " - " << getDescription(i) << "\n"; - } - } -} - - -//===----------------------------------------------------------------------===// -// --help and --help-hidden option implementation -// -namespace { - -class HelpPrinter { - unsigned MaxArgLen; - const Option *EmptyArg; - const bool ShowHidden; - - // isHidden/isReallyHidden - Predicates to be used to filter down arg lists. - inline static bool isHidden(std::pair<std::string, Option *> &OptPair) { - return OptPair.second->getOptionHiddenFlag() >= Hidden; - } - inline static bool isReallyHidden(std::pair<std::string, Option *> &OptPair) { - return OptPair.second->getOptionHiddenFlag() == ReallyHidden; - } - -public: - HelpPrinter(bool showHidden) : ShowHidden(showHidden) { - EmptyArg = 0; - } - - void operator=(bool Value) { - if (Value == false) return; - - // Copy Options into a vector so we can sort them as we like... - std::vector<std::pair<std::string, Option*> > Options; - copy(getOpts().begin(), getOpts().end(), std::back_inserter(Options)); - - // Eliminate Hidden or ReallyHidden arguments, depending on ShowHidden - Options.erase(std::remove_if(Options.begin(), Options.end(), - std::ptr_fun(ShowHidden ? isReallyHidden : isHidden)), - Options.end()); - - // Eliminate duplicate entries in table (from enum flags options, f.e.) - { // Give OptionSet a scope - std::set<Option*> OptionSet; - for (unsigned i = 0; i != Options.size(); ++i) - if (OptionSet.count(Options[i].second) == 0) - OptionSet.insert(Options[i].second); // Add new entry to set - else - Options.erase(Options.begin()+i--); // Erase duplicate - } - - if (ProgramOverview) - std::cerr << "OVERVIEW:" << ProgramOverview << "\n"; - - std::cerr << "USAGE: " << ProgramName << " [options]"; - - // Print out the positional options... - std::vector<Option*> &PosOpts = getPositionalOpts(); - Option *CAOpt = 0; // The cl::ConsumeAfter option, if it exists... - if (!PosOpts.empty() && PosOpts[0]->getNumOccurrencesFlag() == ConsumeAfter) - CAOpt = PosOpts[0]; - - for (unsigned i = CAOpt != 0, e = PosOpts.size(); i != e; ++i) { - if (PosOpts[i]->ArgStr[0]) - std::cerr << " --" << PosOpts[i]->ArgStr; - std::cerr << " " << PosOpts[i]->HelpStr; - } - - // Print the consume after option info if it exists... - if (CAOpt) std::cerr << " " << CAOpt->HelpStr; - - std::cerr << "\n\n"; - - // Compute the maximum argument length... - MaxArgLen = 0; - for (unsigned i = 0, e = Options.size(); i != e; ++i) - MaxArgLen = std::max(MaxArgLen, Options[i].second->getOptionWidth()); - - std::cerr << "OPTIONS:\n"; - for (unsigned i = 0, e = Options.size(); i != e; ++i) - Options[i].second->printOptionInfo(MaxArgLen); - - // Halt the program if help information is printed - exit(1); - } -}; - - - -// Define the two HelpPrinter instances that are used to print out help, or -// help-hidden... -// -HelpPrinter NormalPrinter(false); -HelpPrinter HiddenPrinter(true); - -cl::opt<HelpPrinter, true, parser<bool> > -HOp("help", cl::desc("display available options (--help-hidden for more)"), - cl::location(NormalPrinter), cl::ValueDisallowed); - -cl::opt<HelpPrinter, true, parser<bool> > -HHOp("help-hidden", cl::desc("display all available options"), - cl::location(HiddenPrinter), cl::Hidden, cl::ValueDisallowed); - -} // End anonymous namespace diff --git a/support/lib/Support/ConstantRange.cpp b/support/lib/Support/ConstantRange.cpp deleted file mode 100644 index c9d8ae6fbb..0000000000 --- a/support/lib/Support/ConstantRange.cpp +++ /dev/null @@ -1,243 +0,0 @@ -//===-- ConstantRange.cpp - ConstantRange implementation ------------------===// -// -// Represent a range of possible values that may occur when the program is run -// for an integral value. This keeps track of a lower and upper bound for the -// constant, which MAY wrap around the end of the numeric range. To do this, it -// keeps track of a [lower, upper) bound, which specifies an interval just like -// STL iterators. When used with boolean values, the following are important -// ranges (other integral ranges use min/max values for special range values): -// -// [F, F) = {} = Empty set -// [T, F) = {T} -// [F, T) = {F} -// [T, T) = {F, T} = Full set -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/ConstantRange.h" -#include "llvm/Type.h" -#include "llvm/Instruction.h" -#include "llvm/ConstantHandling.h" - -/// Initialize a full (the default) or empty set for the specified type. -/// -ConstantRange::ConstantRange(const Type *Ty, bool Full) { - assert(Ty->isIntegral() && - "Cannot make constant range of non-integral type!"); - if (Full) - Lower = Upper = ConstantIntegral::getMaxValue(Ty); - else - Lower = Upper = ConstantIntegral::getMinValue(Ty); -} - -/// Initialize a range of values explicitly... this will assert out if -/// Lower==Upper and Lower != Min or Max for its type (or if the two constants -/// have different types) -/// -ConstantRange::ConstantRange(ConstantIntegral *L, - ConstantIntegral *U) : Lower(L), Upper(U) { - assert(Lower->getType() == Upper->getType() && - "Incompatible types for ConstantRange!"); - - // Make sure that if L & U are equal that they are either Min or Max... - assert((L != U || (L == ConstantIntegral::getMaxValue(L->getType()) || - L == ConstantIntegral::getMinValue(L->getType()))) && - "Lower == Upper, but they aren't min or max for type!"); -} - -static ConstantIntegral *Next(ConstantIntegral *CI) { - if (CI->getType() == Type::BoolTy) - return CI == ConstantBool::True ? ConstantBool::False : ConstantBool::True; - - // Otherwise use operator+ in the ConstantHandling Library. - Constant *Result = *ConstantInt::get(CI->getType(), 1) + *CI; - assert(Result && "ConstantHandling not implemented for integral plus!?"); - return cast<ConstantIntegral>(Result); -} - -/// Initialize a set of values that all satisfy the condition with C. -/// -ConstantRange::ConstantRange(unsigned SetCCOpcode, ConstantIntegral *C) { - switch (SetCCOpcode) { - default: assert(0 && "Invalid SetCC opcode to ConstantRange ctor!"); - case Instruction::SetEQ: Lower = C; Upper = Next(C); return; - case Instruction::SetNE: Upper = C; Lower = Next(C); return; - case Instruction::SetLT: - Lower = ConstantIntegral::getMinValue(C->getType()); - Upper = C; - return; - case Instruction::SetGT: - Lower = Next(C); - Upper = ConstantIntegral::getMinValue(C->getType()); // Min = Next(Max) - return; - case Instruction::SetLE: - Lower = ConstantIntegral::getMinValue(C->getType()); - Upper = Next(C); - return; - case Instruction::SetGE: - Lower = C; - Upper = ConstantIntegral::getMinValue(C->getType()); // Min = Next(Max) - return; - } -} - -/// getType - Return the LLVM data type of this range. -/// -const Type *ConstantRange::getType() const { return Lower->getType(); } - -/// isFullSet - Return true if this set contains all of the elements possible -/// for this data-type -bool ConstantRange::isFullSet() const { - return Lower == Upper && Lower == ConstantIntegral::getMaxValue(getType()); -} - -/// isEmptySet - Return true if this set contains no members. -/// -bool ConstantRange::isEmptySet() const { - return Lower == Upper && Lower == ConstantIntegral::getMinValue(getType()); -} - -/// isWrappedSet - Return true if this set wraps around the top of the range, -/// for example: [100, 8) -/// -bool ConstantRange::isWrappedSet() const { - return (*(Constant*)Lower > *(Constant*)Upper)->getValue(); -} - - -/// getSingleElement - If this set contains a single element, return it, -/// otherwise return null. -ConstantIntegral *ConstantRange::getSingleElement() const { - if (Upper == Next(Lower)) // Is it a single element range? - return Lower; - return 0; -} - -/// getSetSize - Return the number of elements in this set. -/// -uint64_t ConstantRange::getSetSize() const { - if (isEmptySet()) return 0; - if (getType() == Type::BoolTy) { - if (Lower != Upper) // One of T or F in the set... - return 1; - return 2; // Must be full set... - } - - // Simply subtract the bounds... - Constant *Result = *(Constant*)Upper - *(Constant*)Lower; - assert(Result && "Subtraction of constant integers not implemented?"); - return cast<ConstantInt>(Result)->getRawValue(); -} - - - - -// intersect1Wrapped - This helper function is used to intersect two ranges when -// it is known that LHS is wrapped and RHS isn't. -// -static ConstantRange intersect1Wrapped(const ConstantRange &LHS, - const ConstantRange &RHS) { - assert(LHS.isWrappedSet() && !RHS.isWrappedSet()); - - // Check to see if we overlap on the Left side of RHS... - // - if ((*(Constant*)RHS.getLower() < *(Constant*)LHS.getUpper())->getValue()) { - // We do overlap on the left side of RHS, see if we overlap on the right of - // RHS... - if ((*(Constant*)RHS.getUpper() > *(Constant*)LHS.getLower())->getValue()) { - // Ok, the result overlaps on both the left and right sides. See if the - // resultant interval will be smaller if we wrap or not... - // - if (LHS.getSetSize() < RHS.getSetSize()) - return LHS; - else - return RHS; - - } else { - // No overlap on the right, just on the left. - return ConstantRange(RHS.getLower(), LHS.getUpper()); - } - - } else { - // We don't overlap on the left side of RHS, see if we overlap on the right - // of RHS... - if ((*(Constant*)RHS.getUpper() > *(Constant*)LHS.getLower())->getValue()) { - // Simple overlap... - return ConstantRange(LHS.getLower(), RHS.getUpper()); - } else { - // No overlap... - return ConstantRange(LHS.getType(), false); - } - } -} - -static ConstantIntegral *Min(ConstantIntegral *A, ConstantIntegral *B) { - if ((*(Constant*)A < *(Constant*)B)->getValue()) - return A; - return B; -} -static ConstantIntegral *Max(ConstantIntegral *A, ConstantIntegral *B) { - if ((*(Constant*)A > *(Constant*)B)->getValue()) - return A; - return B; -} - - -/// intersect - Return the range that results from the intersection of this -/// range with another range. -/// -ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const { - assert(getType() == CR.getType() && "ConstantRange types don't agree!"); - // Handle common special cases - if (isEmptySet() || CR.isFullSet()) return *this; - if (isFullSet() || CR.isEmptySet()) return CR; - - if (!isWrappedSet()) { - if (!CR.isWrappedSet()) { - ConstantIntegral *L = Max(Lower, CR.Lower); - ConstantIntegral *U = Min(Upper, CR.Upper); - - if ((*L < *U)->getValue()) // If range isn't empty... - return ConstantRange(L, U); - else - return ConstantRange(getType(), false); // Otherwise, return empty set - } else - return intersect1Wrapped(CR, *this); - } else { // We know "this" is wrapped... - if (!CR.isWrappedSet()) - return intersect1Wrapped(*this, CR); - else { - // Both ranges are wrapped... - ConstantIntegral *L = Max(Lower, CR.Lower); - ConstantIntegral *U = Min(Upper, CR.Upper); - return ConstantRange(L, U); - } - } - return *this; -} - -/// union - Return the range that results from the union of this range with -/// another range. The resultant range is guaranteed to include the elements of -/// both sets, but may contain more. For example, [3, 9) union [12,15) is [3, -/// 15), which includes 9, 10, and 11, which were not included in either set -/// before. -/// -ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const { - assert(getType() == CR.getType() && "ConstantRange types don't agree!"); - - assert(0 && "Range union not implemented yet!"); - - return *this; -} - -/// print - Print out the bounds to a stream... -/// -void ConstantRange::print(std::ostream &OS) const { - OS << "[" << Lower << "," << Upper << " )"; -} - -/// dump - Allow printing from a debugger easily... -/// -void ConstantRange::dump() const { - print(std::cerr); -} diff --git a/support/lib/Support/Debug.cpp b/support/lib/Support/Debug.cpp deleted file mode 100644 index f87cddfe4e..0000000000 --- a/support/lib/Support/Debug.cpp +++ /dev/null @@ -1,57 +0,0 @@ -//===-- Debug.cpp - An easy way to add debug output to your code ----------===// -// -// This file implements a handle way of adding debugging information to your -// code, without it being enabled all of the time, and without having to add -// command line options to enable it. -// -// In particular, just wrap your code with the DEBUG() macro, and it will be -// enabled automatically if you specify '-debug' on the command-line. -// Alternatively, you can also use the SET_DEBUG_TYPE("foo") macro to specify -// that your debug code belongs to class "foo". Then, on the command line, you -// can specify '-debug-only=foo' to enable JUST the debug information for the -// foo class. -// -// When compiling in release mode, the -debug-* options and all code in DEBUG() -// statements disappears, so it does not effect the runtime of the code. -// -//===----------------------------------------------------------------------===// - -#include "Support/Statistic.h" -#include "Support/CommandLine.h" - -bool DebugFlag; // DebugFlag - Exported boolean set by the -debug option - -namespace { -#ifndef NDEBUG - // -debug - Command line option to enable the DEBUG statements in the passes. - // This flag may only be enabled in debug builds. - cl::opt<bool, true> - Debug("debug", cl::desc("Enable debug output"), cl::Hidden, - cl::location(DebugFlag)); - - std::string CurrentDebugType; - struct DebugOnlyOpt { - void operator=(const std::string &Val) const { - DebugFlag |= !Val.empty(); - CurrentDebugType = Val; - } - } DebugOnlyOptLoc; - - cl::opt<DebugOnlyOpt, true, cl::parser<std::string> > - DebugOnly("debug-only", cl::desc("Enable a specific type of debug output"), - cl::Hidden, cl::value_desc("debug string"), - cl::location(DebugOnlyOptLoc), cl::ValueRequired); -#endif -} - -// isCurrentDebugType - Return true if the specified string is the debug type -// specified on the command line, or if none was specified on the command line -// with the -debug-only=X option. -// -bool isCurrentDebugType(const char *DebugType) { -#ifndef NDEBUG - return CurrentDebugType.empty() || DebugType == CurrentDebugType; -#else - return false; -#endif -} diff --git a/support/lib/Support/FileUtilities.cpp b/support/lib/Support/FileUtilities.cpp deleted file mode 100644 index ca4603628c..0000000000 --- a/support/lib/Support/FileUtilities.cpp +++ /dev/null @@ -1,203 +0,0 @@ -//===- Support/FileUtilities.cpp - File System Utilities ------------------===// -// -// This file implements a family of utility functions which are useful for doing -// various things with files. -// -//===----------------------------------------------------------------------===// - -#include "Support/FileUtilities.h" -#include "Config/unistd.h" -#include "Config/sys/stat.h" -#include "Config/sys/types.h" -#include <fstream> -#include <iostream> -#include <cstdio> - -/// DiffFiles - Compare the two files specified, returning true if they are -/// different or if there is a file error. If you specify a string to fill in -/// for the error option, it will set the string to an error message if an error -/// occurs, allowing the caller to distinguish between a failed diff and a file -/// system error. -/// -bool DiffFiles(const std::string &FileA, const std::string &FileB, - std::string *Error) { - std::ifstream FileAStream(FileA.c_str()); - if (!FileAStream) { - if (Error) *Error = "Couldn't open file '" + FileA + "'"; - return true; - } - - std::ifstream FileBStream(FileB.c_str()); - if (!FileBStream) { - if (Error) *Error = "Couldn't open file '" + FileB + "'"; - return true; - } - - // Compare the two files... - int C1, C2; - do { - C1 = FileAStream.get(); - C2 = FileBStream.get(); - if (C1 != C2) return true; - } while (C1 != EOF); - - return false; -} - - -/// MoveFileOverIfUpdated - If the file specified by New is different than Old, -/// or if Old does not exist, move the New file over the Old file. Otherwise, -/// remove the New file. -/// -void MoveFileOverIfUpdated(const std::string &New, const std::string &Old) { - if (DiffFiles(New, Old)) { - if (std::rename(New.c_str(), Old.c_str())) - std::cerr << "Error renaming '" << New << "' to '" << Old << "'!\n"; - } else { - std::remove(New.c_str()); - } -} - -/// removeFile - Delete the specified file -/// -void removeFile(const std::string &Filename) { - std::remove(Filename.c_str()); -} - -/// getUniqueFilename - Return a filename with the specified prefix. If the -/// file does not exist yet, return it, otherwise add a suffix to make it -/// unique. -/// -std::string getUniqueFilename(const std::string &FilenameBase) { - if (!std::ifstream(FilenameBase.c_str())) - return FilenameBase; // Couldn't open the file? Use it! - - // Create a pattern for mkstemp... - char *FNBuffer = new char[FilenameBase.size()+8]; - strcpy(FNBuffer, FilenameBase.c_str()); - strcpy(FNBuffer+FilenameBase.size(), "-XXXXXX"); - - // Agree on a temporary file name to use.... - int TempFD; - if ((TempFD = mkstemp(FNBuffer)) == -1) { - std::cerr << "bugpoint: ERROR: Cannot create temporary file in the current " - << " directory!\n"; - exit(1); - } - - // We don't need to hold the temp file descriptor... we will trust that no one - // will overwrite/delete the file while we are working on it... - close(TempFD); - std::string Result(FNBuffer); - delete[] FNBuffer; - return Result; -} - -/// -/// Method: MakeFileExecutable () -/// -/// Description: -/// This method makes the specified filename executable by giving it -/// execute permission. It respects the umask value of the process, and it -/// does not enable any unnecessary access bits. -/// -/// Algorithm: -/// o Get file's current permissions. -/// o Get the process's current umask. -/// o Take the set of all execute bits and disable those found in the umask. -/// o Add the remaining permissions to the file's permissions. -/// -bool -MakeFileExecutable (const std::string & Filename) -{ - // Permissions masking value of the user - mode_t mask; - - // Permissions currently enabled on the file - struct stat fstat; - - // - // Grab the umask value from the operating system. We want to use it when - // changing the file's permissions. - // - // Note: - // Umask() is one of those annoying system calls. You have to call it - // to get the current value and then set it back. - // - mask = umask (0x777); - umask (mask); - - // - // Go fetch the file's current permission bits. We want to *add* execute - // access to the file. - // - if ((stat (Filename.c_str(), &fstat)) == -1) - { - return false; - } - - // - // Make the file executable... - // - if ((chmod(Filename.c_str(), (fstat.st_mode | (0111 & ~mask)))) == -1) - { - return false; - } - - return true; -} - -/// -/// Method: MakeFileReadable () -/// -/// Description: -/// This method makes the specified filename readable by giving it -/// read permission. It respects the umask value of the process, and it -/// does not enable any unnecessary access bits. -/// -/// Algorithm: -/// o Get file's current permissions. -/// o Get the process's current umask. -/// o Take the set of all read bits and disable those found in the umask. -/// o Add the remaining permissions to the file's permissions. -/// -bool -MakeFileReadable (const std::string & Filename) -{ - // Permissions masking value of the user - mode_t mask; - - // Permissions currently enabled on the file - struct stat fstat; - - // - // Grab the umask value from the operating system. We want to use it when - // changing the file's permissions. - // - // Note: - // Umask() is one of those annoying system calls. You have to call it - // to get the current value and then set it back. - // - mask = umask (0x777); - umask (mask); - - // - // Go fetch the file's current permission bits. We want to *add* execute - // access to the file. - // - if ((stat (Filename.c_str(), &fstat)) == -1) - { - return false; - } - - // - // Make the file executable... - // - if ((chmod(Filename.c_str(), (fstat.st_mode | (0444 & ~mask)))) == -1) - { - return false; - } - - return true; -} - diff --git a/support/lib/Support/LeakDetector.cpp b/support/lib/Support/LeakDetector.cpp deleted file mode 100644 index ecc4868d2e..0000000000 --- a/support/lib/Support/LeakDetector.cpp +++ /dev/null @@ -1,82 +0,0 @@ -//===-- LeakDetector.cpp - Implement LeakDetector interface ---------------===// -// -// This file implements the LeakDetector class. -// -//===----------------------------------------------------------------------===// - -#include "Support/LeakDetector.h" -#include "llvm/Value.h" -#include <set> - -// Lazily allocate set so that release build doesn't have to do anything. -static std::set<const void*> *Objects = 0; -static std::set<const Value*> *LLVMObjects = 0; - -// Because the most common usage pattern, by far, is to add a garbage object, -// then remove it immediately, we optimize this case. When an object is added, -// it is not added to the set immediately, it is added to the CachedValue Value. -// If it is immediately removed, no set search need be performed. -// -static const Value *CachedValue; - -void LeakDetector::addGarbageObjectImpl(void *Object) { - if (Objects == 0) - Objects = new std::set<const void*>(); - assert(Objects->count(Object) == 0 && "Object already in set!"); - Objects->insert(Object); -} - -void LeakDetector::removeGarbageObjectImpl(void *Object) { - if (Objects) - Objects->erase(Object); -} - -void LeakDetector::addGarbageObjectImpl(const Value *Object) { - if (CachedValue) { - if (LLVMObjects == 0) - LLVMObjects = new std::set<const Value*>(); - assert(LLVMObjects->count(CachedValue) == 0 && "Object already in set!"); - LLVMObjects->insert(CachedValue); - } - CachedValue = Object; -} - -void LeakDetector::removeGarbageObjectImpl(const Value *Object) { - if (Object == CachedValue) - CachedValue = 0; // Cache hit! - else if (LLVMObjects) - LLVMObjects->erase(Object); -} - -void LeakDetector::checkForGarbageImpl(const std::string &Message) { - if (CachedValue) // Flush the cache to the set... - addGarbageObjectImpl((Value*)0); - - assert(CachedValue == 0 && "No value should be cached anymore!"); - - if ((Objects && !Objects->empty()) || (LLVMObjects && !LLVMObjects->empty())){ - std::cerr << "Leaked objects found: " << Message << "\n"; - - if (Objects && !Objects->empty()) { - std::cerr << " Non-Value objects leaked:"; - for (std::set<const void*>::iterator I = Objects->begin(), - E = Objects->end(); I != E; ++I) - std::cerr << " " << *I; - } - - if (LLVMObjects && !LLVMObjects->empty()) { - std::cerr << " LLVM Value subclasses leaked:"; - for (std::set<const Value*>::iterator I = LLVMObjects->begin(), - E = LLVMObjects->end(); I != E; ++I) - std::cerr << **I << "\n"; - } - - std::cerr << "This is probably because you removed an LLVM value " - << "(Instruction, BasicBlock, \netc), but didn't delete it. " - << "Please check your code for memory leaks.\n"; - - // Clear out results so we don't get duplicate warnings on next call... - delete Objects; delete LLVMObjects; - Objects = 0; LLVMObjects = 0; - } -} diff --git a/support/lib/Support/Makefile b/support/lib/Support/Makefile deleted file mode 100644 index d52d7315bf..0000000000 --- a/support/lib/Support/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -LEVEL = ../../.. -LIBRARYNAME = support -BUILD_ARCHIVE = 1 - -include $(LEVEL)/Makefile.common diff --git a/support/lib/Support/Mangler.cpp b/support/lib/Support/Mangler.cpp deleted file mode 100644 index d9186a9c93..0000000000 --- a/support/lib/Support/Mangler.cpp +++ /dev/null @@ -1,94 +0,0 @@ -//===-- Mangler.cpp - Self-contained c/asm llvm name mangler --------------===// -// -// Unified name mangler for CWriter and assembly backends. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/Mangler.h" -#include "llvm/Module.h" -#include "llvm/Type.h" -#include "Support/StringExtras.h" - -static char HexDigit(int V) { - return V < 10 ? V+'0' : V+'A'-10; -} - -static std::string MangleLetter(unsigned char C) { - return std::string("_")+HexDigit(C >> 4) + HexDigit(C & 15) + "_"; -} - -/// makeNameProper - We don't want identifier names non-C-identifier characters -/// in them, so mangle them as appropriate. -/// -std::string Mangler::makeNameProper(const std::string &X) { - std::string Result; - - // Mangle the first letter specially, don't allow numbers... - if ((X[0] < 'a' || X[0] > 'z') && (X[0] < 'A' || X[0] > 'Z') && X[0] != '_') - Result += MangleLetter(X[0]); - else - Result += X[0]; - - for (std::string::const_iterator I = X.begin()+1, E = X.end(); I != E; ++I) - if ((*I < 'a' || *I > 'z') && (*I < 'A' || *I > 'Z') && - (*I < '0' || *I > '9') && *I != '_') - Result += MangleLetter(*I); - else - Result += *I; - return Result; -} - -std::string Mangler::getValueName(const Value *V) { - // Check to see whether we've already named V. - ValueMap::iterator VI = Memo.find(V); - if (VI != Memo.end()) { - return VI->second; // Return the old name for V. - } - - std::string name; - if (V->hasName()) { // Print out the label if it exists... - // Name mangling occurs as follows: - // - If V is not a global, mangling always occurs. - // - Otherwise, mangling occurs when any of the following are true: - // 1) V has internal linkage - // 2) V's name would collide if it is not mangled. - // - const GlobalValue* gv = dyn_cast<GlobalValue>(V); - if (gv && !gv->hasInternalLinkage() && !MangledGlobals.count(gv)) { - name = makeNameProper(gv->getName()); - if (AddUnderscorePrefix) name = "_" + name; - } else { - // Non-global, or global with internal linkage / colliding name - // -> mangle. - name = "l" + utostr(V->getType()->getUniqueID()) + "_" + - makeNameProper(V->getName()); - } - } else { - name = "ltmp_" + utostr(Count++) + "_" - + utostr(V->getType()->getUniqueID()); - } - - Memo[V] = name; - return name; -} - -Mangler::Mangler(Module &m, bool addUnderscorePrefix) - : M(m), AddUnderscorePrefix(addUnderscorePrefix) { - // Calculate which global values have names that will collide when we throw - // away type information. - std::set<std::string> FoundNames; - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) - if (I->hasName()) // If the global has a name... - if (FoundNames.count(I->getName())) // And the name is already used - MangledGlobals.insert(I); // Mangle the name - else - FoundNames.insert(I->getName()); // Otherwise, keep track of name - - for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I) - if (I->hasName()) // If the global has a name... - if (FoundNames.count(I->getName())) // And the name is already used - MangledGlobals.insert(I); // Mangle the name - else - FoundNames.insert(I->getName()); // Otherwise, keep track of name -} - diff --git a/support/lib/Support/PluginLoader.cpp b/support/lib/Support/PluginLoader.cpp deleted file mode 100644 index 76c5e8197d..0000000000 --- a/support/lib/Support/PluginLoader.cpp +++ /dev/null @@ -1,31 +0,0 @@ -//===-- PluginLoader.cpp - Implement -load command line option ------------===// -// -// This file implements the -load <plugin> command line option processor. When -// linked into a program, this new command line option is available that allows -// users to load shared objects into the running program. -// -// Note that there are no symbols exported by the .o file generated for this -// .cpp file. Because of this, a program must link against support.o instead of -// support.a: otherwise this translation unit will not be included. -// -//===----------------------------------------------------------------------===// - -#include "Support/CommandLine.h" -#include "Config/dlfcn.h" -#include "Config/link.h" -#include <iostream> - -namespace { - struct PluginLoader { - void operator=(const std::string &Filename) { - if (dlopen(Filename.c_str(), RTLD_NOW|RTLD_GLOBAL) == 0) - std::cerr << "Error opening '" << Filename << "': " << dlerror() - << "\n -load request ignored.\n"; - } - }; -} - -// This causes operator= above to be invoked for every -load option. -static cl::opt<PluginLoader, false, cl::parser<std::string> > -LoadOpt("load", cl::ZeroOrMore, cl::value_desc("plugin.so"), - cl::desc("Load the specified plugin")); diff --git a/support/lib/Support/Signals.cpp b/support/lib/Support/Signals.cpp deleted file mode 100644 index 563147eabf..0000000000 --- a/support/lib/Support/Signals.cpp +++ /dev/null @@ -1,57 +0,0 @@ -//===- Signals.cpp - Signal Handling support ------------------------------===// -// -// This file defines some helpful functions for dealing with the possibility of -// Unix signals occuring while your program is running. -// -//===----------------------------------------------------------------------===// - -#include "Support/Signals.h" -#include <vector> -#include <algorithm> -#include <cstdlib> -#include <cstdio> -#include <signal.h> -#include "Config/config.h" // Get the signal handler return type - -static std::vector<std::string> FilesToRemove; - -// IntSigs - Signals that may interrupt the program at any time. -static const int IntSigs[] = { - SIGHUP, SIGINT, SIGQUIT, SIGKILL, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2 -}; -static const int *IntSigsEnd = IntSigs + sizeof(IntSigs)/sizeof(IntSigs[0]); - -// KillSigs - Signals that are synchronous with the program that will cause it -// to die. -static const int KillSigs[] = { - SIGILL, SIGTRAP, SIGABRT, SIGFPE, SIGBUS, SIGSEGV, SIGSYS, SIGXCPU, SIGXFSZ -#ifdef SIGEMT - , SIGEMT -#endif -}; -static const int *KillSigsEnd = KillSigs + sizeof(KillSigs)/sizeof(KillSigs[0]); - - -// SignalHandler - The signal handler that runs... -static RETSIGTYPE SignalHandler(int Sig) { - while (!FilesToRemove.empty()) { - std::remove(FilesToRemove.back().c_str()); - FilesToRemove.pop_back(); - } - - if (std::find(IntSigs, IntSigsEnd, Sig) != IntSigsEnd) - exit(1); // If this is an interrupt signal, exit the program - - // Otherwise if it is a fault (like SEGV) reissue the signal to die... - signal(Sig, SIG_DFL); -} - -static void RegisterHandler(int Signal) { signal(Signal, SignalHandler); } - -// RemoveFileOnSignal - The public API -void RemoveFileOnSignal(const std::string &Filename) { - FilesToRemove.push_back(Filename); - - std::for_each(IntSigs, IntSigsEnd, RegisterHandler); - std::for_each(KillSigs, KillSigsEnd, RegisterHandler); -} diff --git a/support/lib/Support/Statistic.cpp b/support/lib/Support/Statistic.cpp deleted file mode 100644 index ae9f57f80e..0000000000 --- a/support/lib/Support/Statistic.cpp +++ /dev/null @@ -1,99 +0,0 @@ -//===-- Statistic.cpp - Easy way to expose stats information --------------===// -// -// This file implements the 'Statistic' class, which is designed to be an easy -// way to expose various success metrics from passes. These statistics are -// printed at the end of a run, when the -stats command line option is enabled -// on the command line. -// -// This is useful for reporting information like the number of instructions -// simplified, optimized or removed by various transformations, like this: -// -// static Statistic<> NumInstEliminated("GCSE - Number of instructions killed"); -// -// Later, in the code: ++NumInstEliminated; -// -//===----------------------------------------------------------------------===// - -#include "Support/Statistic.h" -#include "Support/CommandLine.h" -#include <sstream> -#include <iostream> -#include <algorithm> - -// GetLibSupportInfoOutputFile - Return a file stream to print our output on... -std::ostream *GetLibSupportInfoOutputFile(); - -unsigned StatisticBase::NumStats = 0; - -// -stats - Command line option to cause transformations to emit stats about -// what they did. -// -static cl::opt<bool> -Enabled("stats", cl::desc("Enable statistics output from program")); - -struct StatRecord { - std::string Value; - const char *Name, *Desc; - - StatRecord(const std::string V, const char *N, const char *D) - : Value(V), Name(N), Desc(D) {} - - bool operator<(const StatRecord &SR) const { - return std::strcmp(Name, SR.Name) < 0; - } - - void print(unsigned ValFieldSize, unsigned NameFieldSize, - std::ostream &OS) { - OS << std::string(ValFieldSize-Value.length(), ' ') - << Value << " " << Name - << std::string(NameFieldSize-std::strlen(Name), ' ') - << " - " << Desc << "\n"; - } -}; - -static std::vector<StatRecord> *AccumStats = 0; - -// Print information when destroyed, iff command line option is specified -void StatisticBase::destroy() const { - if (Enabled && hasSomeData()) { - if (AccumStats == 0) - AccumStats = new std::vector<StatRecord>(); - - std::ostringstream Out; - printValue(Out); - AccumStats->push_back(StatRecord(Out.str(), Name, Desc)); - } - - if (--NumStats == 0 && AccumStats) { - std::ostream *OutStream = GetLibSupportInfoOutputFile(); - - // Figure out how long the biggest Value and Name fields are... - unsigned MaxNameLen = 0, MaxValLen = 0; - for (unsigned i = 0, e = AccumStats->size(); i != e; ++i) { - MaxValLen = std::max(MaxValLen, - (unsigned)(*AccumStats)[i].Value.length()); - MaxNameLen = std::max(MaxNameLen, - (unsigned)std::strlen((*AccumStats)[i].Name)); - } - - // Sort the fields... - std::stable_sort(AccumStats->begin(), AccumStats->end()); - - // Print out the statistics header... - *OutStream << "===" << std::string(73, '-') << "===\n" - << " ... Statistics Collected ...\n" - << "===" << std::string(73, '-') << "===\n\n"; - - // Print all of the statistics accumulated... - for (unsigned i = 0, e = AccumStats->size(); i != e; ++i) - (*AccumStats)[i].print(MaxValLen, MaxNameLen, *OutStream); - - *OutStream << std::endl; // Flush the output stream... - - // Free all accumulated statistics... - delete AccumStats; - AccumStats = 0; - if (OutStream != &std::cerr && OutStream != &std::cout) - delete OutStream; // Close the file... - } -} diff --git a/support/lib/Support/SystemUtils.cpp b/support/lib/Support/SystemUtils.cpp deleted file mode 100644 index e198c7ec06..0000000000 --- a/support/lib/Support/SystemUtils.cpp +++ /dev/null @@ -1,266 +0,0 @@ -//===- SystemUtils.h - Utilities to do low-level system stuff --*- C++ -*--===// -// -// This file contains functions used to do a variety of low-level, often -// system-specific, tasks. -// -//===----------------------------------------------------------------------===// - -#include "Support/SystemUtils.h" -#include <algorithm> -#include <fstream> -#include <iostream> -#include <cstdlib> -#include "Config/sys/types.h" -#include "Config/sys/stat.h" -#include "Config/fcntl.h" -#include "Config/sys/wait.h" -#include "Config/unistd.h" -#include "Config/errno.h" - -/// isExecutableFile - This function returns true if the filename specified -/// exists and is executable. -/// -bool isExecutableFile(const std::string &ExeFileName) { - struct stat Buf; - if (stat(ExeFileName.c_str(), &Buf)) - return false; // Must not be executable! - - if (!(Buf.st_mode & S_IFREG)) - return false; // Not a regular file? - - if (Buf.st_uid == getuid()) // Owner of file? - return Buf.st_mode & S_IXUSR; - else if (Buf.st_gid == getgid()) // In group of file? - return Buf.st_mode & S_IXGRP; - else // Unrelated to file? - return Buf.st_mode & S_IXOTH; -} - -/// FindExecutable - Find a named executable, giving the argv[0] of program -/// being executed. This allows us to find another LLVM tool if it is built -/// into the same directory, but that directory is neither the current -/// directory, nor in the PATH. If the executable cannot be found, return an -/// empty string. -/// -std::string FindExecutable(const std::string &ExeName, - const std::string &ProgramPath) { - // First check the directory that bugpoint is in. We can do this if - // BugPointPath contains at least one / character, indicating that it is a - // relative path to bugpoint itself. - // - std::string Result = ProgramPath; - while (!Result.empty() && Result[Result.size()-1] != '/') - Result.erase(Result.size()-1, 1); - - if (!Result.empty()) { - Result += ExeName; - if (isExecutableFile(Result)) return Result; // Found it? - } - - // Okay, if the path to the program didn't tell us anything, try using the - // PATH environment variable. - const char *PathStr = getenv("PATH"); - if (PathStr == 0) return ""; - - // Now we have a colon separated list of directories to search... try them... - unsigned PathLen = strlen(PathStr); - while (PathLen) { - // Find the first colon... - const char *Colon = std::find(PathStr, PathStr+PathLen, ':'); - - // Check to see if this first directory contains the executable... - std::string FilePath = std::string(PathStr, Colon) + '/' + ExeName; - if (isExecutableFile(FilePath)) - return FilePath; // Found the executable! - - // Nope it wasn't in this directory, check the next range! - PathLen -= Colon-PathStr; - PathStr = Colon; - while (*PathStr == ':') { // Advance past colons - PathStr++; - PathLen--; - } - } - - // If we fell out, we ran out of directories in PATH to search, return failure - return ""; -} - -static void RedirectFD(const std::string &File, int FD) { - if (File.empty()) return; // Noop - - // Open the file - int InFD = open(File.c_str(), FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666); - if (InFD == -1) { - std::cerr << "Error opening file '" << File << "' for " - << (FD == 0 ? "input" : "output") << "!\n"; - exit(1); - } - - dup2(InFD, FD); // Install it as the requested FD - close(InFD); // Close the original FD -} - -/// RunProgramWithTimeout - This function executes the specified program, with -/// the specified null-terminated argument array, with the stdin/out/err fd's -/// redirected, with a timeout specified on the command line. This terminates -/// the calling program if there is an error executing the specified program. -/// It returns the return value of the program, or -1 if a timeout is detected. -/// -int RunProgramWithTimeout(const std::string &ProgramPath, const char **Args, - const std::string &StdInFile, - const std::string &StdOutFile, - const std::string &StdErrFile) { - - // FIXME: install sigalarm handler here for timeout... - - int Child = fork(); - switch (Child) { - case -1: - std::cerr << "ERROR forking!\n"; - exit(1); - case 0: // Child - RedirectFD(StdInFile, 0); // Redirect file descriptors... - RedirectFD(StdOutFile, 1); - RedirectFD(StdErrFile, 2); - - execv(ProgramPath.c_str(), (char *const *)Args); - std::cerr << "Error executing program '" << ProgramPath; - for (; *Args; ++Args) - std::cerr << " " << *Args; - exit(1); - - default: break; - } - - // Make sure all output has been written while waiting - std::cout << std::flush; - - int Status; - if (wait(&Status) != Child) { - if (errno == EINTR) { - static bool FirstTimeout = true; - if (FirstTimeout) { - std::cout << - "*** Program execution timed out! This mechanism is designed to handle\n" - " programs stuck in infinite loops gracefully. The -timeout option\n" - " can be used to change the timeout threshold or disable it completely\n" - " (with -timeout=0). This message is only displayed once.\n"; - FirstTimeout = false; - } - return -1; // Timeout detected - } - - std::cerr << "Error waiting for child process!\n"; - exit(1); - } - return Status; -} - - -// -// Function: ExecWait () -// -// Description: -// This function executes a program with the specified arguments and -// environment. It then waits for the progarm to termiante and then returns -// to the caller. -// -// Inputs: -// argv - The arguments to the program as an array of C strings. The first -// argument should be the name of the program to execute, and the -// last argument should be a pointer to NULL. -// -// envp - The environment passes to the program as an array of C strings in -// the form of "name=value" pairs. The last element should be a -// pointer to NULL. -// -// Outputs: -// None. -// -// Return value: -// 0 - No errors. -// 1 - The program could not be executed. -// 1 - The program returned a non-zero exit status. -// 1 - The program terminated abnormally. -// -// Notes: -// The program will inherit the stdin, stdout, and stderr file descriptors -// as well as other various configuration settings (umask). -// -// This function should not print anything to stdout/stderr on its own. It is -// a generic library function. The caller or executed program should report -// errors in the way it sees fit. -// -// This function does not use $PATH to find programs. -// -int -ExecWait (const char * const old_argv[], const char * const old_envp[]) -{ - // Child process ID - register int child; - - // Status from child process when it exits - int status; - - // - // Create local versions of the parameters that can be passed into execve() - // without creating const problems. - // - char ** const argv = (char ** const) old_argv; - char ** const envp = (char ** const) old_envp; - - // - // Create a child process. - // - switch (child=fork()) - { - // - // An error occured: Return to the caller. - // - case -1: - return 1; - break; - - // - // Child process: Execute the program. - // - case 0: - execve (argv[0], argv, envp); - - // - // If the execve() failed, we should exit and let the parent pick up - // our non-zero exit status. - // - exit (1); - break; - - // - // Parent process: Break out of the switch to do our processing. - // - default: - break; - } - - // - // Parent process: Wait for the child process to termiante. - // - if ((wait (&status)) == -1) - { - return 1; - } - - // - // If the program exited normally with a zero exit status, return success! - // - if (WIFEXITED (status) && (WEXITSTATUS(status) == 0)) - { - return 0; - } - - // - // Otherwise, return failure. - // - return 1; -} - diff --git a/support/lib/Support/Timer.cpp b/support/lib/Support/Timer.cpp deleted file mode 100644 index 98001287d9..0000000000 --- a/support/lib/Support/Timer.cpp +++ /dev/null @@ -1,328 +0,0 @@ -//===-- Timer.cpp - Interval Timing Support -------------------------------===// -// -// Interval Timing implementation. -// -//===----------------------------------------------------------------------===// - -#include "Support/Timer.h" -#include "Support/CommandLine.h" - -#include "Config/sys/resource.h" -#include "Config/sys/time.h" -#include "Config/unistd.h" -#include "Config/malloc.h" -#include "Config/stdio.h" -#include <iostream> -#include <algorithm> -#include <functional> -#include <fstream> - -// getLibSupportInfoOutputFilename - This ugly hack is brought to you courtesy -// of constructor/destructor ordering being unspecified by C++. Basically the -// problem is that a Statistic<> object gets destroyed, which ends up calling -// 'GetLibSupportInfoOutputFile()' (below), which calls this function. -// LibSupportInfoOutputFilename used to be a global variable, but sometimes it -// would get destroyed before the Statistic, causing havoc to ensue. We "fix" -// this by creating the string the first time it is needed and never destroying -// it. -static std::string &getLibSupportInfoOutputFilename() { - static std::string *LibSupportInfoOutputFilename = new std::string(); - return *LibSupportInfoOutputFilename; -} - -namespace { -#ifdef HAVE_MALLINFO - cl::opt<bool> - TrackSpace("track-memory", cl::desc("Enable -time-passes memory " - "tracking (this may be slow)"), - cl::Hidden); -#endif - - cl::opt<std::string, true> - InfoOutputFilename("info-output-file", cl::value_desc("filename"), - cl::desc("File to append -stats and -timer output to"), - cl::Hidden, cl::location(getLibSupportInfoOutputFilename())); -} - -static TimerGroup *DefaultTimerGroup = 0; -static TimerGroup *getDefaultTimerGroup() { - if (DefaultTimerGroup) return DefaultTimerGroup; - return DefaultTimerGroup = new TimerGroup("Miscellaneous Ungrouped Timers"); -} - -Timer::Timer(const std::string &N) - : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N), - Started(false), TG(getDefaultTimerGroup()) { - TG->addTimer(); -} - -Timer::Timer(const std::string &N, TimerGroup &tg) - : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N), - Started(false), TG(&tg) { - TG->addTimer(); -} - -Timer::Timer(const Timer &T) { - TG = T.TG; - if (TG) TG->addTimer(); - operator=(T); -} - - -// Copy ctor, initialize with no TG member. -Timer::Timer(bool, const Timer &T) { - TG = T.TG; // Avoid assertion in operator= - operator=(T); // Copy contents - TG = 0; -} - - -Timer::~Timer() { - if (TG) { - if (Started) { - Started = false; - TG->addTimerToPrint(*this); - } - TG->removeTimer(); - } -} - -static long getMemUsage() { -#ifdef HAVE_MALLINFO - if (TrackSpace) { - struct mallinfo MI = mallinfo(); - return MI.uordblks/*+MI.hblkhd*/; - } -#endif - return 0; -} - -struct TimeRecord { - double Elapsed, UserTime, SystemTime; - long MemUsed; -}; - -static TimeRecord getTimeRecord(bool Start) { - struct rusage RU; - struct timeval T; - long MemUsed = 0; - if (Start) { - MemUsed = getMemUsage(); - if (getrusage(RUSAGE_SELF, &RU)) - perror("getrusage call failed: -time-passes info incorrect!"); - } - gettimeofday(&T, 0); - - if (!Start) { - MemUsed = getMemUsage(); - if (getrusage(RUSAGE_SELF, &RU)) - perror("getrusage call failed: -time-passes info incorrect!"); - } - - TimeRecord Result; - Result.Elapsed = T.tv_sec + T.tv_usec/1000000.0; - Result.UserTime = RU.ru_utime.tv_sec + RU.ru_utime.tv_usec/1000000.0; - Result.SystemTime = RU.ru_stime.tv_sec + RU.ru_stime.tv_usec/1000000.0; - Result.MemUsed = MemUsed; - - return Result; -} - -static std::vector<Timer*> ActiveTimers; - -void Timer::startTimer() { - Started = true; - TimeRecord TR = getTimeRecord(true); - Elapsed -= TR.Elapsed; - UserTime -= TR.UserTime; - SystemTime -= TR.SystemTime; - MemUsed -= TR.MemUsed; - PeakMemBase = TR.MemUsed; - ActiveTimers.push_back(this); -} - -void Timer::stopTimer() { - TimeRecord TR = getTimeRecord(false); - Elapsed += TR.Elapsed; - UserTime += TR.UserTime; - SystemTime += TR.SystemTime; - MemUsed += TR.MemUsed; - - if (ActiveTimers.back() == this) { - ActiveTimers.pop_back(); - } else { - std::vector<Timer*>::iterator I = - std::find(ActiveTimers.begin(), ActiveTimers.end(), this); - assert(I != ActiveTimers.end() && "stop but no startTimer?"); - ActiveTimers.erase(I); - } -} - -void Timer::sum(const Timer &T) { - Elapsed += T.Elapsed; - UserTime += T.UserTime; - SystemTime += T.SystemTime; - MemUsed += T.MemUsed; - PeakMem += T.PeakMem; -} - -/// addPeakMemoryMeasurement - This method should be called whenever memory -/// usage needs to be checked. It adds a peak memory measurement to the -/// currently active timers, which will be printed when the timer group prints -/// -void Timer::addPeakMemoryMeasurement() { - long MemUsed = getMemUsage(); - - for (std::vector<Timer*>::iterator I = ActiveTimers.begin(), - E = ActiveTimers.end(); I != E; ++I) - (*I)->PeakMem = std::max((*I)->PeakMem, MemUsed-(*I)->PeakMemBase); -} - - -//===----------------------------------------------------------------------===// -// TimerGroup Implementation -//===----------------------------------------------------------------------===// - -// printAlignedFP - Simulate the printf "%A.Bf" format, where A is the -// TotalWidth size, and B is the AfterDec size. -// -static void printAlignedFP(double Val, unsigned AfterDec, unsigned TotalWidth, - std::ostream &OS) { - assert(TotalWidth >= AfterDec+1 && "Bad FP Format!"); - OS.width(TotalWidth-AfterDec-1); - char OldFill = OS.fill(); - OS.fill(' '); - OS << (int)Val; // Integer part; - OS << "."; - OS.width(AfterDec); - OS.fill('0'); - unsigned ResultFieldSize = 1; - while (AfterDec--) ResultFieldSize *= 10; - OS << (int)(Val*ResultFieldSize) % ResultFieldSize; - OS.fill(OldFill); -} - -static void printVal(double Val, double Total, std::ostream &OS) { - if (Total < 1e-7) // Avoid dividing by zero... - OS << " ----- "; - else { - OS << " "; - printAlignedFP(Val, 4, 7, OS); - OS << " ("; - printAlignedFP(Val*100/Total, 1, 5, OS); - OS << "%)"; - } -} - -void Timer::print(const Timer &Total, std::ostream &OS) { - if (Total.UserTime) - printVal(UserTime, Total.UserTime, OS); - if (Total.SystemTime) - printVal(SystemTime, Total.SystemTime, OS); - if (Total.getProcessTime()) - printVal(getProcessTime(), Total.getProcessTime(), OS); - printVal(Elapsed, Total.Elapsed, OS); - - OS << " "; - - if (Total.MemUsed) { - OS.width(9); - OS << MemUsed << " "; - } - if (Total.PeakMem) { - if (PeakMem) { - OS.width(9); - OS << PeakMem << " "; - } else - OS << " "; - } - OS << Name << "\n"; - - Started = false; // Once printed, don't print again -} - -// GetLibSupportInfoOutputFile - Return a file stream to print our output on... -std::ostream *GetLibSupportInfoOutputFile() { - std::string &LibSupportInfoOutputFilename = getLibSupportInfoOutputFilename(); - if (LibSupportInfoOutputFilename.empty()) - return &std::cerr; - if (LibSupportInfoOutputFilename == "-") - return &std::cout; - - std::ostream *Result = new std::ofstream(LibSupportInfoOutputFilename.c_str(), - std::ios::app); - if (!Result->good()) { - std::cerr << "Error opening info-output-file '" - << LibSupportInfoOutputFilename << " for appending!\n"; - delete Result; - return &std::cerr; - } - return Result; -} - - -void TimerGroup::removeTimer() { - if (--NumTimers == 0 && !TimersToPrint.empty()) { // Print timing report... - // Sort the timers in descending order by amount of time taken... - std::sort(TimersToPrint.begin(), TimersToPrint.end(), - std::greater<Timer>()); - - // Figure out how many spaces to indent TimerGroup name... - unsigned Padding = (80-Name.length())/2; - if (Padding > 80) Padding = 0; // Don't allow "negative" numbers - - std::ostream *OutStream = GetLibSupportInfoOutputFile(); - - ++NumTimers; - { // Scope to contain Total timer... don't allow total timer to drop us to - // zero timers... - Timer Total("TOTAL"); - - for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) - Total.sum(TimersToPrint[i]); - - // Print out timing header... - *OutStream << "===" << std::string(73, '-') << "===\n" - << std::string(Padding, ' ') << Name << "\n" - << "===" << std::string(73, '-') - << "===\n Total Execution Time: "; - - printAlignedFP(Total.getProcessTime(), 4, 5, *OutStream); - *OutStream << " seconds ("; - printAlignedFP(Total.getWallTime(), 4, 5, *OutStream); - *OutStream << " wall clock)\n\n"; - - if (Total.UserTime) - *OutStream << " ---User Time---"; - if (Total.SystemTime) - *OutStream << " --System Time--"; - if (Total.getProcessTime()) - *OutStream << " --User+System--"; - *OutStream << " ---Wall Time---"; - if (Total.getMemUsed()) - *OutStream << " ---Mem---"; - if (Total.getPeakMem()) - *OutStream << " -PeakMem-"; - *OutStream << " --- Name ---\n"; - - // Loop through all of the timing data, printing it out... - for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) - TimersToPrint[i].print(Total, *OutStream); - - Total.print(Total, *OutStream); - *OutStream << std::endl; // Flush output - } - --NumTimers; - - TimersToPrint.clear(); - - if (OutStream != &std::cerr && OutStream != &std::cout) - delete OutStream; // Close the file... - } - - // Delete default timer group! - if (NumTimers == 0 && this == DefaultTimerGroup) { - delete DefaultTimerGroup; - DefaultTimerGroup = 0; - } -} diff --git a/support/lib/Support/ToolRunner.cpp b/support/lib/Support/ToolRunner.cpp deleted file mode 100644 index 1ae5260bef..0000000000 --- a/support/lib/Support/ToolRunner.cpp +++ /dev/null @@ -1,374 +0,0 @@ -#include "Support/Debug.h" -#include "Support/FileUtilities.h" -#include "Support/ToolRunner.h" - -//===---------------------------------------------------------------------===// -// LLI Implementation of AbstractIntepreter interface -// -class LLI : public AbstractInterpreter { - std::string LLIPath; // The path to the LLI executable -public: - LLI(const std::string &Path) : LLIPath(Path) { } - - - virtual int ExecuteProgram(const std::string &Bytecode, - const cl::list<std::string> &Args, - const std::string &InputFile, - const std::string &OutputFile, - const std::string &SharedLib = ""); -}; - -int LLI::ExecuteProgram(const std::string &Bytecode, - const cl::list<std::string> &Args, - const std::string &InputFile, - const std::string &OutputFile, - const std::string &SharedLib) { - if (!SharedLib.empty()) { - std::cerr << "LLI currently does not support loading shared libraries.\n" - << "Exiting.\n"; - exit(1); - } - - std::vector<const char*> LLIArgs; - LLIArgs.push_back(LLIPath.c_str()); - LLIArgs.push_back("-abort-on-exception"); - LLIArgs.push_back("-quiet"); - LLIArgs.push_back("-force-interpreter=true"); - LLIArgs.push_back(Bytecode.c_str()); - // Add optional parameters to the running program from Argv - for (unsigned i=0, e = Args.size(); i != e; ++i) - LLIArgs.push_back(Args[i].c_str()); - LLIArgs.push_back(0); - - std::cout << "<lli>" << std::flush; - DEBUG(std::cerr << "\nAbout to run:\n\t"; - for (unsigned i=0, e = LLIArgs.size(); i != e; ++i) - std::cerr << " " << LLIArgs[i]; - std::cerr << "\n"; - ); - return RunProgramWithTimeout(LLIPath, &LLIArgs[0], - InputFile, OutputFile, OutputFile); -} - -// LLI create method - Try to find the LLI executable -AbstractInterpreter *createLLItool(const std::string &ProgramPath, - std::string &Message) { - std::string LLIPath = FindExecutable("lli", ProgramPath); - if (!LLIPath.empty()) { - Message = "Found lli: " + LLIPath + "\n"; - return new LLI(LLIPath); - } - - Message = "Cannot find `lli' in executable directory or PATH!\n"; - return 0; -} - -//===----------------------------------------------------------------------===// -// LLC Implementation of AbstractIntepreter interface -// -int LLC::OutputAsm(const std::string &Bytecode, - std::string &OutputAsmFile) { - OutputAsmFile = getUniqueFilename(Bytecode+".llc.s"); - const char *LLCArgs[] = { - LLCPath.c_str(), - "-o", OutputAsmFile.c_str(), // Output to the Asm file - "-f", // Overwrite as necessary... - Bytecode.c_str(), // This is the input bytecode - 0 - }; - - std::cout << "<llc>" << std::flush; - if (RunProgramWithTimeout(LLCPath, LLCArgs, "/dev/null", "/dev/null", - "/dev/null")) { - // If LLC failed on the bytecode, print error... - std::cerr << "Error: `llc' failed!\n"; - removeFile(OutputAsmFile); - return 1; - } - - return 0; -} - -int LLC::ExecuteProgram(const std::string &Bytecode, - const cl::list<std::string> &Args, - const std::string &InputFile, - const std::string &OutputFile, - const std::string &SharedLib) { - - std::string OutputAsmFile; - if (OutputAsm(Bytecode, OutputAsmFile)) { - std::cerr << "Could not generate asm code with `llc', exiting.\n"; - exit(1); - } - - // Assuming LLC worked, compile the result with GCC and run it. - int Result = gcc->ExecuteProgram(OutputAsmFile, Args, AsmFile, - InputFile, OutputFile, SharedLib); - removeFile(OutputAsmFile); - return Result; -} - -/// createLLCtool - Try to find the LLC executable -/// -LLC *createLLCtool(const std::string &ProgramPath, std::string &Message) -{ - std::string LLCPath = FindExecutable("llc", ProgramPath); - if (LLCPath.empty()) { - Message = "Cannot find `llc' in executable directory or PATH!\n"; - return 0; - } - - Message = "Found llc: " + LLCPath + "\n"; - GCC *gcc = createGCCtool(ProgramPath, Message); - if (!gcc) { - std::cerr << Message << "\n"; - exit(1); - } - return new LLC(LLCPath, gcc); -} - -//===---------------------------------------------------------------------===// -// JIT Implementation of AbstractIntepreter interface -// -class JIT : public AbstractInterpreter { - std::string LLIPath; // The path to the LLI executable -public: - JIT(const std::string &Path) : LLIPath(Path) { } - - - virtual int ExecuteProgram(const std::string &Bytecode, - const cl::list<std::string> &Args, - const std::string &InputFile, - const std::string &OutputFile, - const std::string &SharedLib = ""); -}; - -int JIT::ExecuteProgram(const std::string &Bytecode, - const cl::list<std::string> &Args, - const std::string &InputFile, - const std::string &OutputFile, - const std::string &SharedLib) { - // Construct a vector of parameters, incorporating those from the command-line - std::vector<const char*> JITArgs; - JITArgs.push_back(LLIPath.c_str()); - JITArgs.push_back("-quiet"); - JITArgs.push_back("-force-interpreter=false"); - if (!SharedLib.empty()) { - JITArgs.push_back("-load"); - JITArgs.push_back(SharedLib.c_str()); - } - JITArgs.push_back(Bytecode.c_str()); - // Add optional parameters to the running program from Argv - for (unsigned i=0, e = Args.size(); i != e; ++i) - JITArgs.push_back(Args[i].c_str()); - JITArgs.push_back(0); - - std::cout << "<jit>" << std::flush; - DEBUG(std::cerr << "\nAbout to run:\n\t"; - for (unsigned i=0, e = JITArgs.size(); i != e; ++i) - std::cerr << " " << JITArgs[i]; - std::cerr << "\n"; - ); - DEBUG(std::cerr << "\nSending output to " << OutputFile << "\n"); - return RunProgramWithTimeout(LLIPath, &JITArgs[0], - InputFile, OutputFile, OutputFile); -} - -/// createJITtool - Try to find the LLI executable -/// -AbstractInterpreter *createJITtool(const std::string &ProgramPath, - std::string &Message) { - std::string LLIPath = FindExecutable("lli", ProgramPath); - if (!LLIPath.empty()) { - Message = "Found lli: " + LLIPath + "\n"; - return new JIT(LLIPath); - } - - Message = "Cannot find `lli' in executable directory or PATH!\n"; - return 0; -} - -int CBE::OutputC(const std::string &Bytecode, - std::string &OutputCFile) { - OutputCFile = getUniqueFilename(Bytecode+".cbe.c"); - const char *DisArgs[] = { - DISPath.c_str(), - "-o", OutputCFile.c_str(), // Output to the C file - "-c", // Output to C - "-f", // Overwrite as necessary... - Bytecode.c_str(), // This is the input bytecode - 0 - }; - - std::cout << "<cbe>" << std::flush; - if (RunProgramWithTimeout(DISPath, DisArgs, "/dev/null", "/dev/null", - "/dev/null")) { - // If dis failed on the bytecode, print error... - std::cerr << "Error: `llvm-dis -c' failed!\n"; - return 1; - } - - return 0; -} - -int CBE::ExecuteProgram(const std::string &Bytecode, - const cl::list<std::string> &Args, - const std::string &InputFile, - const std::string &OutputFile, - const std::string &SharedLib) { - std::string OutputCFile; - if (OutputC(Bytecode, OutputCFile)) { - std::cerr << "Could not generate C code with `llvm-dis', exiting.\n"; - exit(1); - } - - int Result = gcc->ExecuteProgram(OutputCFile, Args, CFile, - InputFile, OutputFile, SharedLib); - removeFile(OutputCFile); - - return Result; -} - -/// createCBEtool - Try to find the 'dis' executable -/// -CBE *createCBEtool(const std::string &ProgramPath, std::string &Message) { - std::string DISPath = FindExecutable("llvm-dis", ProgramPath); - if (DISPath.empty()) { - Message = - "Cannot find `llvm-dis' in executable directory or PATH!\n"; - return 0; - } - - Message = "Found llvm-dis: " + DISPath + "\n"; - GCC *gcc = createGCCtool(ProgramPath, Message); - if (!gcc) { - std::cerr << Message << "\n"; - exit(1); - } - return new CBE(DISPath, gcc); -} - -//===---------------------------------------------------------------------===// -// GCC abstraction -// -// This is not a *real* AbstractInterpreter as it does not accept bytecode -// files, but only input acceptable to GCC, i.e. C, C++, and assembly files -// -int GCC::ExecuteProgram(const std::string &ProgramFile, - const cl::list<std::string> &Args, - FileType fileType, - const std::string &InputFile, - const std::string &OutputFile, - const std::string &SharedLib) { - std::string OutputBinary = getUniqueFilename(ProgramFile+".gcc.exe"); - std::vector<const char*> GCCArgs; - - GCCArgs.push_back(GCCPath.c_str()); - if (!SharedLib.empty()) // Specify the shared library to link in... - GCCArgs.push_back(SharedLib.c_str()); - GCCArgs.push_back("-x"); - if (fileType == CFile) { - GCCArgs.push_back("c"); - GCCArgs.push_back("-fno-strict-aliasing"); - } else { - GCCArgs.push_back("assembler"); - } - GCCArgs.push_back(ProgramFile.c_str()); // Specify the input filename... - GCCArgs.push_back("-o"); - GCCArgs.push_back(OutputBinary.c_str()); // Output to the right file... - GCCArgs.push_back("-lm"); // Hard-code the math library... - GCCArgs.push_back("-O2"); // Optimize the program a bit... - GCCArgs.push_back(0); // NULL terminator - - std::cout << "<gcc>" << std::flush; - if (RunProgramWithTimeout(GCCPath, &GCCArgs[0], "/dev/null", "/dev/null", - "/dev/null")) { - ProcessFailure(&GCCArgs[0]); - exit(1); - } - - std::vector<const char*> ProgramArgs; - ProgramArgs.push_back(OutputBinary.c_str()); - // Add optional parameters to the running program from Argv - for (unsigned i=0, e = Args.size(); i != e; ++i) - ProgramArgs.push_back(Args[i].c_str()); - ProgramArgs.push_back(0); // NULL terminator - - // Now that we have a binary, run it! - std::cout << "<program>" << std::flush; - DEBUG(std::cerr << "\nAbout to run:\n\t"; - for (unsigned i=0, e = ProgramArgs.size(); i != e; ++i) - std::cerr << " " << ProgramArgs[i]; - std::cerr << "\n"; - ); - int ProgramResult = RunProgramWithTimeout(OutputBinary, &ProgramArgs[0], - InputFile, OutputFile, OutputFile); - removeFile(OutputBinary); - return ProgramResult; -} - -int GCC::MakeSharedObject(const std::string &InputFile, - FileType fileType, - std::string &OutputFile) { - OutputFile = getUniqueFilename(InputFile+".so"); - // Compile the C/asm file into a shared object - const char* GCCArgs[] = { - GCCPath.c_str(), - "-x", (fileType == AsmFile) ? "assembler" : "c", - "-fno-strict-aliasing", - InputFile.c_str(), // Specify the input filename... -#if defined(sparc) || defined(__sparc__) || defined(__sparcv9) - "-G", // Compile a shared library, `-G' for Sparc -#else - "-shared", // `-shared' for Linux/X86, maybe others -#endif - "-o", OutputFile.c_str(), // Output to the right filename... - "-O2", // Optimize the program a bit... - 0 - }; - - std::cout << "<gcc>" << std::flush; - if(RunProgramWithTimeout(GCCPath, GCCArgs, "/dev/null", "/dev/null", - "/dev/null")) { - ProcessFailure(GCCArgs); - exit(1); - } - return 0; -} - -void GCC::ProcessFailure(const char** GCCArgs) { - std::cerr << "\n*** Error: invocation of the C compiler failed!\n"; - for (const char **Arg = GCCArgs; *Arg; ++Arg) - std::cerr << " " << *Arg; - std::cerr << "\n"; - - // Rerun the compiler, capturing any error messages to print them. - std::string ErrorFilename = getUniqueFilename("gcc.errors"); - RunProgramWithTimeout(GCCPath, GCCArgs, "/dev/null", ErrorFilename.c_str(), - ErrorFilename.c_str()); - - // Print out the error messages generated by GCC if possible... - std::ifstream ErrorFile(ErrorFilename.c_str()); - if (ErrorFile) { - std::copy(std::istreambuf_iterator<char>(ErrorFile), - std::istreambuf_iterator<char>(), - std::ostreambuf_iterator<char>(std::cerr)); - ErrorFile.close(); - std::cerr << "\n"; - } - - removeFile(ErrorFilename); -} - -/// createGCCtool - Try to find the `gcc' executable -/// -GCC *createGCCtool(const std::string &ProgramPath, std::string &Message) { - std::string GCCPath = FindExecutable("gcc", ProgramPath); - if (GCCPath.empty()) { - Message = "Cannot find `gcc' in executable directory or PATH!\n"; - return 0; - } - - Message = "Found gcc: " + GCCPath + "\n"; - return new GCC(GCCPath); -} diff --git a/support/lib/Support/ValueHolder.cpp b/support/lib/Support/ValueHolder.cpp deleted file mode 100644 index e0806b538a..0000000000 --- a/support/lib/Support/ValueHolder.cpp +++ /dev/null @@ -1,16 +0,0 @@ -//===-- ValueHolder.cpp - Wrapper for Value implementation ----------------===// -// -// This class defines a simple subclass of User, which keeps a pointer to a -// Value, which automatically updates when Value::replaceAllUsesWith is called. -// This is useful when you have pointers to Value's in your pass, but the -// pointers get invalidated when some other portion of the algorithm is -// replacing Values with other Values. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/ValueHolder.h" -#include "llvm/Type.h" - -ValueHolder::ValueHolder(Value *V) : User(Type::TypeTy, Value::TypeVal) { - Operands.push_back(Use(V, this)); -} diff --git a/support/tools/Burg/COPYRIGHT b/support/tools/Burg/COPYRIGHT deleted file mode 100644 index 1de0aad6f2..0000000000 --- a/support/tools/Burg/COPYRIGHT +++ /dev/null @@ -1,13 +0,0 @@ -Copyright (C) 1991 Todd A. Proebsting -All Rights Reserved. - -This software is in the public domain. You may use and copy this material -freely. This privilege extends to modifications, although any modified -version of this system given to a third party should clearly identify your -modifications as well as the original source. - -The responsibility for the use of this material resides entirely with you. -We make no warranty of any kind concerning this material, nor do we make -any claim as to the suitability of BURG for any application. This software -is experimental in nature and there is no written or implied warranty. Use -it at your own risk. diff --git a/support/tools/Burg/Doc/Makefile b/support/tools/Burg/Doc/Makefile deleted file mode 100644 index 226210d6ca..0000000000 --- a/support/tools/Burg/Doc/Makefile +++ /dev/null @@ -1,84 +0,0 @@ -# $Id$ - -#CFLAGS = -#CFLAGS = -O -#CFLAGS = -O -DNOLEX -CFLAGS = -g -DDEBUG -#CFLAGS = -g -DNOLEX -DDEBUG - -SRCS = \ - be.c \ - burs.c \ - closure.c \ - delta.c \ - fe.c \ - item.c \ - lex.c \ - list.c \ - main.c \ - map.c \ - nonterminal.c \ - operator.c \ - pattern.c \ - plank.c \ - queue.c \ - rule.c \ - string.c \ - symtab.c \ - table.c \ - trim.c \ - zalloc.c - -BU_OBJS = \ - burs.o \ - closure.o \ - delta.o \ - item.o \ - list.o \ - map.o \ - nonterminal.o \ - operator.o \ - pattern.o \ - queue.o \ - rule.o \ - table.o \ - trim.o \ - zalloc.o - -FE_OBJS = \ - be.o \ - fe.o \ - lex.o \ - main.o \ - plank.o \ - string.o \ - symtab.o \ - y.tab.o - -all: test - -burg: $(BU_OBJS) $(FE_OBJS) - $(CC) -o burg $(CFLAGS) $(BU_OBJS) $(FE_OBJS) - -y.tab.c y.tab.h: gram.y - yacc -d gram.y - -clean: - rm -f *.o y.tab.h y.tab.c core burg *.aux *.log *.dvi sample sample.c tmp - -$(FE_OBJS): b.h -$(BU_OBJS): b.h -$(FE_OBJS): fe.h - -lex.o: y.tab.h - -doc.dvi: doc.tex - latex doc; latex doc - -test: burg sample.gr - ./burg -I <sample.gr >sample.c && cc $(CFLAGS) -o sample sample.c && ./sample - ./burg -I sample.gr >tmp && cmp tmp sample.c - ./burg -I <sample.gr -o tmp && cmp tmp sample.c - ./burg -I sample.gr -o tmp && cmp tmp sample.c - ./burg -I -O0 <sample.gr >tmp && cmp tmp sample.c - ./burg -I -= <sample.gr >tmp && cmp tmp sample.c diff --git a/support/tools/Burg/Doc/doc.aux b/support/tools/Burg/Doc/doc.aux deleted file mode 100644 index 0f7c13f020..0000000000 --- a/support/tools/Burg/Doc/doc.aux +++ /dev/null @@ -1,50 +0,0 @@ -\relax -\bibstyle{alpha} -\citation{aho-twig-toplas} -\citation{appel-87} -\citation{balachandran-complang} -\citation{kron-phd} -\citation{hoffmann-jacm} -\citation{hatcher-popl} -\citation{chase-popl} -\citation{pelegri-popl} -\citation{pelegri-phd} -\citation{wilhelm-tr} -\citation{henry-budp} -\citation{fraser-henry-spe-91} -\citation{proebsting-91} -\@writefile{toc}{\contentsline {section}{\numberline {1}Overview}{1}} -\@writefile{toc}{\contentsline {section}{\numberline {2}Input}{1}} -\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces A Sample Tree Grammar}}{2}} -\newlabel{fig-tree-grammar}{{1}{2}} -\@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces EBNF Grammar for Tree Grammars for {\sc Burg}\ }}{3}} -\newlabel{fig-grammar-grammar}{{2}{3}} -\@writefile{toc}{\contentsline {section}{\numberline {3}Output}{3}} -\citation{aho-johnson-dp-classic} -\citation{fraser-henry-spe-91} -\citation{henry-budp} -\citation{pelegri-phd} -\@writefile{toc}{\contentsline {section}{\numberline {4}Debugging}{6}} -\@writefile{toc}{\contentsline {section}{\numberline {5}Running {\sc Burg}\ }{6}} -\newlabel{sec-man-page}{{5}{6}} -\citation{pelegri-popl} -\citation{henry-budp} -\citation{balachandran-complang} -\citation{proebsting-91} -\@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces A Diverging Tree Grammar}}{7}} -\newlabel{fig-diverge-grammar}{{3}{7}} -\@writefile{toc}{\contentsline {section}{\numberline {6}Acknowledgements}{7}} -\bibcite{aho-twig-toplas}{AGT89} -\bibcite{aho-johnson-dp-classic}{AJ76} -\bibcite{appel-87}{App87} -\bibcite{balachandran-complang}{BDB90} -\bibcite{wilhelm-tr}{BMW87} -\bibcite{chase-popl}{Cha87} -\bibcite{fraser-henry-spe-91}{FH91} -\bibcite{hatcher-popl}{HC86} -\bibcite{henry-budp}{Hen89} -\bibcite{hoffmann-jacm}{HO82} -\bibcite{kron-phd}{Kro75} -\bibcite{pelegri-phd}{PL87} -\bibcite{pelegri-popl}{PLG88} -\bibcite{proebsting-91}{Pro91} diff --git a/support/tools/Burg/Doc/doc.dvi b/support/tools/Burg/Doc/doc.dvi Binary files differdeleted file mode 100644 index 3211f32c96..0000000000 --- a/support/tools/Burg/Doc/doc.dvi +++ /dev/null diff --git a/support/tools/Burg/Doc/doc.log b/support/tools/Burg/Doc/doc.log deleted file mode 100644 index a224a4edf7..0000000000 --- a/support/tools/Burg/Doc/doc.log +++ /dev/null @@ -1,157 +0,0 @@ -This is TeX, Version 3.14159 (Web2C 7.3.2) (format=latex 2000.8.30) 4 JUN 2001 13:20 -**doc -(doc.tex -LaTeX2e <2000/06/01> -(/usr/dcs/software/supported/encap/TeX/share/texmf/tex/latex/base/latex209.def -File: latex209.def 1998/05/13 v0.52 Standard LaTeX file - - - Entering LaTeX 2.09 COMPATIBILITY MODE - ************************************************************* - !!WARNING!! !!WARNING!! !!WARNING!! !!WARNING!! - - This mode attempts to provide an emulation of the LaTeX 2.09 - author environment so that OLD documents can be successfully - processed. It should NOT be used for NEW documents! - - New documents should use Standard LaTeX conventions and start - with the \documentclass command. - - Compatibility mode is UNLIKELY TO WORK with LaTeX 2.09 style - files that change any internal macros, especially not with - those that change the FONT SELECTION or OUTPUT ROUTINES. - - Therefore such style files MUST BE UPDATED to use - Current Standard LaTeX: LaTeX2e. - If you suspect that you may be using such a style file, which - is probably very, very old by now, then you should attempt to - get it updated by sending a copy of this error message to the - author of that file. - ************************************************************* - -\footheight=\dimen102 -\@maxsep=\dimen103 -\@dblmaxsep=\dimen104 -\@cla=\count79 -\@clb=\count80 -\mscount=\count81 -(/usr/dcs/software/supported/encap/TeX/share/texmf/tex/latex/base/tracefnt.sty -Package: tracefnt 1997/05/29 v3.0j Standard LaTeX package (font tracing) -\tracingfonts=\count82 -LaTeX Info: Redefining \selectfont on input line 96. -) -\symbold=\mathgroup4 -\symsans=\mathgroup5 -\symtypewriter=\mathgroup6 -\symitalic=\mathgroup7 -\symsmallcaps=\mathgroup8 -\symslanted=\mathgroup9 -LaTeX Font Info: Redeclaring math alphabet \mathbf on input line 288. -LaTeX Font Info: Redeclaring math alphabet \mathsf on input line 289. -LaTeX Font Info: Redeclaring math alphabet \mathtt on input line 290. -LaTeX Font Info: Redeclaring math alphabet \mathit on input line 296. -LaTeX Info: Redefining \em on input line 306. -(/usr/dcs/software/supported/encap/TeX/share/texmf/tex/latex/base/latexsym.sty -Package: latexsym 1998/08/17 v2.2e Standard LaTeX package (lasy symbols) -\symlasy=\mathgroup10 -LaTeX Font Info: Overwriting symbol font `lasy' in version `bold' -(Font) U/lasy/m/n --> U/lasy/b/n on input line 42. -) -LaTeX Font Info: Redeclaring math delimiter \lgroup on input line 370. -LaTeX Font Info: Redeclaring math delimiter \rgroup on input line 372. -LaTeX Font Info: Redeclaring math delimiter \bracevert on input line 374. - -(/usr/dcs/software/supported/encap/TeX/share/texmf/tex/latex/config/latex209.cf -g -(/usr/dcs/software/supported/encap/TeX/share/texmf/tex/latex/tools/rawfonts.sty -Compatibility mode: package `' requested, but `rawfonts' provided. -Package: rawfonts 1994/05/08 Low-level LaTeX 2.09 font compatibility - -(/usr/dcs/software/supported/encap/TeX/share/texmf/tex/latex/tools/somedefs.sty -Package: somedefs 1994/06/01 Toolkit for optional definitions -) -LaTeX Font Info: Try loading font information for U+lasy on input line 44. - (/usr/dcs/software/supported/encap/TeX/share/texmf/tex/latex/base/ulasy.fd -File: ulasy.fd 1998/08/17 v2.2eLaTeX symbol font definitions -)))) (/usr/dcs/software/supported/encap/TeX/share/texmf/tex/latex/base/article. -cls -Document Class: article 2000/05/19 v1.4b Standard LaTeX document class -(/usr/dcs/software/supported/encap/TeX/share/texmf/tex/latex/base/size11.clo -File: size11.clo 2000/05/19 v1.4b Standard LaTeX file (size option) -) -\c@part=\count83 -\c@section=\count84 -\c@subsection=\count85 -\c@subsubsection=\count86 -\c@paragraph=\count87 -\c@subparagraph=\count88 -\c@figure=\count89 -\c@table=\count90 -\abovecaptionskip=\skip41 -\belowcaptionskip=\skip42 -Compatibility mode: definition of \rm ignored. -Compatibility mode: definition of \sf ignored. -Compatibility mode: definition of \tt ignored. -Compatibility mode: definition of \bf ignored. -Compatibility mode: definition of \it ignored. -Compatibility mode: definition of \sl ignored. -Compatibility mode: definition of \sc ignored. -LaTeX Info: Redefining \cal on input line 501. -LaTeX Info: Redefining \mit on input line 502. -\bibindent=\dimen105 -) -(/usr/dcs/software/supported/encap/TeX/share/texmf/tex/latex/pstex/fullpage.sty -) (doc.aux) -\openout1 = `doc.aux'. - -LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 2. -LaTeX Font Info: ... okay on input line 2. -LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 2. -LaTeX Font Info: ... okay on input line 2. -LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 2. -LaTeX Font Info: ... okay on input line 2. -LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 2. -LaTeX Font Info: ... okay on input line 2. -LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 2. -LaTeX Font Info: ... okay on input line 2. -LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 2. -LaTeX Font Info: ... okay on input line 2. -LaTeX Font Info: External font `cmex10' loaded for size -(Font) <12> on input line 33. -LaTeX Font Info: External font `cmex10' loaded for size -(Font) <8> on input line 33. -LaTeX Font Info: External font `cmex10' loaded for size -(Font) <6> on input line 33. -LaTeX Font Info: Try loading font information for OMS+cmtt on input line 100 -. -LaTeX Font Info: No file OMScmtt.fd. on input line 100. -LaTeX Font Warning: Font shape `OMS/cmtt/m/n' undefined -(Font) using `OMS/cmsy/m/n' instead -(Font) for symbol `textbraceleft' on input line 100. - [1 - -] -LaTeX Font Info: External font `cmex10' loaded for size -(Font) <10.95> on input line 150. - [2] [3] [4] [5] [6] -Overfull \hbox (1.38191pt too wide) in paragraph at lines 480--484 -[]\OT1/cmr/m/n/10.95 Emit code for \OT1/cmtt/m/n/10.95 burm[]arity\OT1/cmr/m/n/ -10.95 , \OT1/cmtt/m/n/10.95 burm[]child\OT1/cmr/m/n/10.95 , \OT1/cmtt/m/n/10.95 - burm[]cost\OT1/cmr/m/n/10.95 , \OT1/cmtt/m/n/10.95 burm[]ntname\OT1/cmr/m/n/10 -.95 , \OT1/cmtt/m/n/10.95 burm[]op[]label\OT1/cmr/m/n/10.95 , \OT1/cmtt/m/n/10. -95 burm[]opname\OT1/cmr/m/n/10.95 , - [] - -[7] [8] [9] (doc.aux) -LaTeX Font Warning: Some font shapes were not available, defaults substituted. - ) -Here is how much of TeX's memory you used: - 543 strings out of 12968 - 6147 string characters out of 289029 - 446019 words of memory out of 1453895 - 3433 multiletter control sequences out of 10000+10000 - 23403 words of font info for 87 fonts, out of 400000 for 2000 - 14 hyphenation exceptions out of 1000 - 21i,6n,20p,308b,283s stack positions out of 300i,100n,500p,50000b,4000s - -Output written on doc.dvi (9 pages, 29856 bytes). diff --git a/support/tools/Burg/Doc/doc.tex b/support/tools/Burg/Doc/doc.tex deleted file mode 100644 index 3dc67be317..0000000000 --- a/support/tools/Burg/Doc/doc.tex +++ /dev/null @@ -1,596 +0,0 @@ -\documentstyle[11pt,fullpage]{article} -\begin{document} - -\def\AddSpace#1{\ifcat#1a\ \fi#1} % if next is a letter, add a space -\def\YACC#1{{\sc Yacc}\AddSpace#1} -\def\TWIG#1{{\sc Twig}\AddSpace#1} -\def\PROG#1{{\sc Burg}\AddSpace#1} -\def\PARSER#1{{\sc Burm}\AddSpace#1} -\def\CODEGEN#1{{\sc Codegen}\AddSpace#1} - -\title{{\sc Burg} --- Fast Optimal Instruction Selection and Tree Parsing} -\author{ -Christopher W. Fraser \\ -AT\&T Bell Laboratories \\ -600 Mountain Avenue 2C-464 \\ -Murray Hill, NJ 07974-0636 \\ -{\tt cwf@research.att.com} -\and -Robert R. Henry \\ -Tera Computer Company \\ -400 N. 34th St., Suite 300 \\ -Seattle, WA 98103-8600 \\ -{\tt rrh@tera.com} -\and -Todd A. Proebsting \\ -Dept. of Computer Sciences \\ -University of Wisconsin \\ -Madison, WI 53706 \\ -{\tt todd@cs.wisc.edu} -} -\date{December 1991} - -\maketitle -\bibliographystyle{alpha} -\newcommand\term[1]{{\it #1}} -\newcommand\secref[1]{\S\ref{#1}} -\newcommand\figref[1]{Figure~\ref{#1}} -% -% rationale table making -% -{\catcode`\^^M=13 \gdef\Obeycr{\catcode`\^^M=13 \def^^M{\\}}% -\gdef\Restorecr{\catcode`\^^M=5 }} % - -% -% for printing out options -% -\newcommand\option[1]{% #1=option character -{\tt -#1}% -} -\newcommand\var[1]{% -{\tt #1}% -} -\section{Overview} - -\PROG is a program that generates a fast tree parser using BURS -(Bottom-Up Rewrite System) technology. It accepts a cost-augmented -tree grammar and emits a C program that discovers in linear time an -optimal parse of trees in the language described by the grammar. \PROG -has been used to construct fast optimal instruction selectors for use -in code generation. \PROG addresses many of the problems addressed by -{\sc Twig}~\cite{aho-twig-toplas,appel-87}, but it is somewhat less flexible and -much faster. \PROG is available via anonymous \var{ftp} from -\var{kaese.cs.wisc.edu}. The compressed \var{shar} file -\var{pub/burg.shar.Z} holds the complete distribution. - -This document describes only that fraction of the BURS model that is -required to use \PROG. Readers interested in more detail might start -with Reference~\cite{balachandran-complang}. Other relevant documents -include References~\cite{kron-phd,hoffmann-jacm,hatcher-popl,chase-popl,pelegri-popl,pelegri-phd,wilhelm-tr,henry-budp,fraser-henry-spe-91,proebsting-91}. - -\section{Input} - -\PROG accepts a tree grammar and emits a BURS tree parser. -\figref{fig-tree-grammar} shows a sample grammar that implements a very -simple instruction selector. -\begin{figure} -\begin{verbatim} -%{ -#define NODEPTR_TYPE treepointer -#define OP_LABEL(p) ((p)->op) -#define LEFT_CHILD(p) ((p)->left) -#define RIGHT_CHILD(p) ((p)->right) -#define STATE_LABEL(p) ((p)->state_label) -#define PANIC printf -%} -%start reg -%term Assign=1 Constant=2 Fetch=3 Four=4 Mul=5 Plus=6 -%% -con: Constant = 1 (0); -con: Four = 2 (0); -addr: con = 3 (0); -addr: Plus(con,reg) = 4 (0); -addr: Plus(con,Mul(Four,reg)) = 5 (0); -reg: Fetch(addr) = 6 (1); -reg: Assign(addr,reg) = 7 (1); -\end{verbatim} -\caption{A Sample Tree Grammar\label{fig-tree-grammar}} -\end{figure} -\PROG grammars are structurally similar to \YACC's. Comments follow C -conventions. Text between ``\var{\%\{}'' and ``\var{\%\}}'' is called -the \term{configuration section}; there may be several such segments. -All are concatenated and copied verbatim into the head of the generated -parser, which is called \PARSER. Text after the second ``\var{\%\%}'', -if any, is also copied verbatim into \PARSER, at the end. - -The configuration section configures \PARSER for the trees being parsed -and the client's environment. This section must define -\var{NODEPTR\_TYPE} to be a visible typedef symbol for a pointer to a -node in the subject tree. \PARSER invokes \var{OP\_LABEL(p)}, -\var{LEFT\_CHILD(p)}, and \var{RIGHT\_CHILD(p)} to read the operator -and children from the node pointed to by \var{p}. It invokes -\var{PANIC} when it detects an error. If the configuration section -defines these operations as macros, they are implemented in-line; -otherwise, they must be implemented as functions. The section on -diagnostics elaborates on \var{PANIC}. - -\PARSER computes and stores a single integral \term{state} in each node -of the subject tree. The configuration section must define a macro -\var{STATE\_LABEL(p)} to access the state field of the node pointed to -by \var{p}. A macro is required because \PROG uses it as an lvalue. A -C \var{short} is usually the right choice; typical code generation -grammars require 100--1000 distinct state labels. - -The tree grammar follows the configuration section. -\figref{fig-grammar-grammar} gives an EBNF grammar for \PROG tree -grammars. -\begin{figure} -\begin{verbatim} -grammar: {dcl} '%%' {rule} - -dcl: '%start' Nonterminal -dcl: '%term' { Identifier '=' Integer } - -rule: Nonterminal ':' tree '=' Integer cost ';' -cost: /* empty */ -cost: '(' Integer { ',' Integer } ')' - -tree: Term '(' tree ',' tree ')' -tree: Term '(' tree ')' -tree: Term -tree: Nonterminal -\end{verbatim} -\caption{EBNF Grammar for Tree Grammars for \PROG\ \label{fig-grammar-grammar}} -\end{figure} -Comments, the text between ``\var{\%\{}'' and ``\var{\%\}}'', and the -text after the optional second ``\var{\%\%}'' are treated lexically, so -the figure omits them. In the EBNF grammar, quoted text must appear -literally, \var{Nonterminal} and \var{Integer} are self-explanatory, -and \var{Term} denotes an identifier previously declared as a -terminal. {\tt\{$X$\}} denotes zero or more instances of $X$. - -Text before the first ``\var{\%\%}'' declares the start symbol and the -terminals or operators in subject trees. All terminals must be -declared; each line of such declarations begins with \var{\%term}. -Each terminal has fixed arity, which \PROG infers from the rules using that terminal. -\PROG restricts terminals to have at most two children. Each terminal -is declared with a positive, unique, integral \term{external symbol -number} after a ``\var{=}''. \var{OP\_LABEL(p)} must return the valid -external symbol number for \var{p}. Ideally, external symbol numbers -form a dense enumeration. Non-terminals are not declared, but the -start symbol may be declared with a line that begins with -\var{\%start}. - -Text after the first ``\var{\%\%}'' declares the rules. A tree grammar -is like a context-free grammar: it has rules, non-terminals, -terminals, and a special start non-terminal. The right-hand side of a -rule, called the \term{pattern}, is a tree. Tree patterns appear in -prefix parenthesized form. Every non-terminal denotes a tree. A chain -rule is a rule whose pattern is another non-terminal. If no start -symbol is declared, \PROG uses the non-terminal defined by the first -rule. \PROG needs a single start symbol; grammars for which it is -natural to use multiple start symbols must be augmented with an -artificial start symbol that derives, with zero cost, the grammar's -natural start symbols. \PARSER will automatically select one -that costs least for any given tree. - -\PROG accepts no embedded semantic actions like \YACC's, because no one -format suited all intended applications. Instead, each rule has a -positive, unique, integral \term{external rule number}, after the -pattern and preceded by a ``\var{=}''. Ideally, external rule numbers -form a dense enumeration. \PARSER uses these numbers to report the -matching rule to a user-supplied routine, which must implement any -desired semantic action; see below. Humans may select these integers -by hand, but \PROG is intended as a \term{server} for building BURS -tree parsers. Thus some \PROG clients will consume a richer -description and translate it into \PROG's simpler input. - -Rules end with a vector of non-negative, integer costs, in parentheses -and separated by commas. If the cost vector is omitted, then all -elements are assumed to be zero. \PROG retains only the first four -elements of the list. The cost of a derivation is the sum of the costs -for all rules applied in the derivation. Arithmetic on cost vectors -treats each member of the vector independently. The tree parser finds -the cheapest parse of the subject tree. It breaks ties arbitrarily. -By default, \PROG uses only the \term{principal cost} of each cost -vector, which defaults to the first element, but options described -below provide alternatives. - -\section{Output} - -\PARSER traverses the subject tree twice. The first pass or -\term{labeller} runs bottom-up and left-to-right, visiting each node -exactly once. Each node is labeled with a state, a single number that -encodes all full and partial optimal pattern matches viable at that -node. The second pass or \term{reducer} traverses the subject tree -top-down. The reducer accepts a tree node's state label and a -\term{goal} non-terminal --- initially the root's state label and the -start symbol --- which combine to determine the rule to be applied at -that node. By construction, the rule has the given goal non-terminal -as its left-hand side. The rule's pattern identifies the subject -subtrees and goal non-terminals for all recursive visits. Here, a -``subtree'' is not necessarily an immediate child of the current node. -Patterns with interior operators cause the reducer to skip the -corresponding subject nodes, so the reducer may proceed directly to -grandchildren, great-grandchildren, and so on. On the other hand, -chain rules cause the reducer to revisit the current subject node, with -a new goal -non-terminal, so \term{x} is also regarded as a subtree of \term{x}. - -As the reducer visits (and possibly revisits) each node, user-supplied -code implements semantic action side effects and controls the order in -which subtrees are visited. The labeller is self-contained, but the -reducer combines code from \PROG with code from the user, so \PARSER -does not stand alone. - -The \PARSER that is generated by \PROG provides primitives for -labelling and reducing trees. These mechanisms are a compromise -between expressibility, abstraction, simplicity, flexibility and -efficiency. Clients may combine primitives into labellers and reducers -that can traverse trees in arbitrary ways, and they may call semantic -routines when and how they wish during traversal. Also, \PROG -generates a few higher level routines that implement common -combinations of primitives, and it generates mechanisms that help debug -the tree parse. - -\PROG generates the labeller as a function named \var{burm\_label} with -the signature -\begin{verbatim} -extern int burm_label(NODEPTR_TYPE p); -\end{verbatim} -It labels the entire subject tree pointed to by \var{p} and returns the -root's state label. State zero labels unmatched trees. The trees may -be corrupt or merely inconsistent with the grammar. - -The simpler \var{burm\_state} is \var{burm\_label} without the -code to traverse the tree and to read and write its fields. It may be -used to integrate labelling into user-supplied traversal code. A -typical signature is -\begin{verbatim} -extern int burm_state(int op, int leftstate, int rightstate); -\end{verbatim} -It accepts an external symbol number for a node and the labels for the -node's left and right children. It returns the state label to assign -to that node. For unary operators, the last argument is ignored; for -leaves, the last two arguments are ignored. In general, \PROG -generates a \var{burm\_state} that accepts the maximum number of child -states required by the input grammar. For example, if the grammar -includes no binary operators, then \var{burm\_state} will have the -signature -\begin{verbatim} -extern int burm_state(int op, int leftstate); -\end{verbatim} -This feature is included to permit future expansion to operators with -more than two children. - -The user must write the reducer, but \PARSER writes code and data that -help. Primary is -\begin{verbatim} -extern int burm_rule(int state, int goalnt); -\end{verbatim} -which accepts a tree's state label and a goal non-terminal and returns the -external rule number of a rule. The rule will have matched the tree -and have the goal non-terminal on the left-hand side; \var{burm\_rule} -returns zero when the tree labelled with the given state did not match -the goal non-terminal. For the initial, root-level call, \var{goalnt} -must be one, and \PARSER exports an array that identifies the values -for nested calls: -\begin{verbatim} -extern short *burm_nts[] = { ... }; -\end{verbatim} -is an array indexed by external rule numbers. Each element points to a -zero-terminated vector of short integers, which encode the goal -non-terminals for that rule's pattern, left-to-right. The user needs -only these two externals to write a complete reducer, but a third -external simplifies some applications: -\begin{verbatim} -extern NODEPTR_TYPE *burm_kids(NODEPTR_TYPE p, int eruleno, NODEPTR_TYPE kids[]); -\end{verbatim} -accepts the address of a tree \var{p}, an external rule number, and an -empty vector of pointers to trees. The procedure assumes that \var{p} -matched the given rule, and it fills in the vector with the subtrees (in -the sense described above) of \var{p} that must be reduced recursively. -\var{kids} is returned. It is not zero-terminated. - -The simple user code below labels and then fully reduces a subject tree; -the reducer prints the tree cover. \var{burm\_string} is defined below. -\begin{verbatim} -parse(NODEPTR_TYPE p) { - burm_label(p); /* label the tree */ - reduce(p, 1, 0); /* and reduce it */ -} - -reduce(NODEPTR_TYPE p, int goalnt, int indent) { - int eruleno = burm_rule(STATE_LABEL(p), goalnt); /* matching rule number */ - short *nts = burm_nts[eruleno]; /* subtree goal non-terminals */ - NODEPTR_TYPE kids[10]; /* subtree pointers */ - int i; - - for (i = 0; i < indent; i++) - printf("."); /* print indented ... */ - printf("%s\n", burm_string[eruleno]); /* ... text of rule */ - burm_kids(p, eruleno, kids); /* initialize subtree pointers */ - for (i = 0; nts[i]; i++) /* traverse subtrees left-to-right */ - reduce(kids[i], nts[i], indent+1); /* and print them recursively */ -} -\end{verbatim} -The reducer may recursively traverse subtrees in any order, and it may -interleave arbitrary semantic actions with recursive traversals. -Multiple reducers may be written, to implement multi-pass algorithms -or independent single-pass algorithms. - -For each non-terminal $x$, \PROG emits a preprocessor directive to -equate \var{burm\_}$x$\var{\_NT} with $x$'s integral encoding. It also -defines a macro \var{burm\_}$x$\var{\_rule(a)} that is equivalent to -\var{burm\_rule(a,}$x$\var{)}. For the grammar in -\figref{fig-tree-grammar}, \PROG emits -\begin{verbatim} -#define burm_reg_NT 1 -#define burm_con_NT 2 -#define burm_addr_NT 3 -#define burm_reg_rule(a) ... -#define burm_con_rule(a) ... -#define burm_addr_rule(a) ... -\end{verbatim} -Such symbols are visible only to the code after the second -``\var{\%\%}''. If the symbols \var{burm\_}$x$\var{\_NT} are needed -elsewhere, extract them from the \PARSER source. - -The \option{I} option directs \PROG to emit an encoding of the input -that may help the user produce diagnostics. The vectors -\begin{verbatim} -extern char *burm_opname[]; -extern char burm_arity[]; -\end{verbatim} -hold the name and number of children, respectively, for each terminal. -They are indexed by the terminal's external symbol number. The vectors -\begin{verbatim} -extern char *burm_string[]; -extern short burm_cost[][4]; -\end{verbatim} -hold the text and cost vector for each rule. They are indexed by the -external rule number. The zero-terminated vector -\begin{verbatim} -extern char *burm_ntname[]; -\end{verbatim} -is indexed by \var{burm\_}$x$\var{\_NT} and holds the name of -non-terminal $x$. Finally, the procedures -\begin{verbatim} -extern int burm_op_label(NODEPTR_TYPE p); -extern int burm_state_label(NODEPTR_TYPE p); -extern NODEPTR_TYPE burm_child(NODEPTR_TYPE p, int index); -\end{verbatim} -are callable versions of the configuration macros. -\var{burm\_child(p,0)} implements \var{LEFT\_CHILD(p)}, and -\var{burm\_child(p,1)} implements \var{RIGHT\_CHILD(p)}. A sample use -is the grammar-independent expression -\var{burm\_opname[burm\_op\_label(p)]}, which yields the textual name -for the operator in the tree node pointed to by \var{p}. - -A complete tree parser can be assembled from just \var{burm\_state}, -\var{burm\_rule}, and \var{burm\_nts}, which use none of the -configuration section except \var{PANIC}. The generated routines that -use the rest of the configuration section are compiled only if the -configuration section defines \var{STATE\_LABEL}, so they can be -omitted if the user prefers to hide the tree structure from \PARSER. -This course may be wise if, say, the tree structure is defined in a -large header file with symbols that might collide with \PARSER's. - -\PARSER selects an optimal parse without dynamic programming at compile -time~\cite{aho-johnson-dp-classic}. Instead, \PROG does the dynamic -programming at compile-compile time, as it builds \PARSER. -Consequently, \PARSER parses quickly. Similar labellers have taken as -few as 15 instructions per node, and reducers as few as 35 per node -visited~\cite{fraser-henry-spe-91}. - -\section{Debugging} - -\PARSER invokes \var{PANIC} when an error prevents it from proceeding. -\var{PANIC} has the same signature as \var{printf}. It should pass its -arguments to \var{printf} if diagnostics are desired and then either -abort (say via \var{exit}) or recover (say via \var{longjmp}). If it -returns, \PARSER aborts. Some errors are not caught. - -\PROG assumes a robust preprocessor, so it omits full consistency -checking and error recovery. \PROG constructs a set of states using a -closure algorithm like that used in LR table construction. \PROG -considers all possible trees generated by the tree grammar and -summarizes infinite sets of trees with finite sets. The summary -records the cost of those trees but actually manipulates the -differences in costs between viable alternatives using a dynamic -programming algorithm. Reference~\cite{henry-budp} elaborates. - -Some grammars derive trees whose optimal parses depend on arbitrarily -distant data. When this happens, \PROG and the tree grammar -\term{cost diverge}, and \PROG attempts to build an infinite -set of states; it first thrashes and ultimately exhausts -memory and exits. For example, the tree grammar in -\figref{fig-diverge-grammar} -\begin{figure} -\begin{verbatim} -%term Const=17 RedFetch=20 GreenFetch=21 Plus=22 -%% -reg: GreenFetch(green_reg) = 10 (0); -reg: RedFetch(red_reg) = 11 (0); - -green_reg: Const = 20 (0); -green_reg: Plus(green_reg,green_reg) = 21 (1); - -red_reg: Const = 30 (0); -red_reg: Plus(red_reg,red_reg) = 31 (2); -\end{verbatim} -\caption{A Diverging Tree Grammar\label{fig-diverge-grammar}} -\end{figure} -diverges, since non-terminals \var{green\_reg} and \var{red\_reg} -derive identical infinite trees with different costs. If the cost of -rule 31 is changed to 1, then the grammar does not diverge. - -Practical tree grammars describing instruction selection do not -cost-diverge because infinite trees are derived from non-terminals -that model temporary registers. Machines can move data between -different types of registers for a small bounded cost, and the rules -for these instructions prevent divergence. For example, if -\figref{fig-diverge-grammar} included rules to move data between red -and green registers, the grammar would not diverge. If a bonafide -machine grammar appears to make \PROG loop, try a host with more -memory. To apply \PROG to problems other than instruction selection, -be prepared to consult the literature on -cost-divergence~\cite{pelegri-phd}. - -\section{Running \PROG\ }\label{sec-man-page} - -\PROG reads a tree grammar and writes a \PARSER in C. \PARSER can be -compiled by itself or included in another file. When suitably named -with the \option{p} option, disjoint instances of \PARSER should link -together without name conflicts. The command: -\begin{flushleft} -\var{burg} [ {\it arguments} ] [ {\it file} ] -\end{flushleft} -invokes \PROG. If a {\it file} is named, \PROG expects its grammar -there; otherwise it reads the standard input. The options include: -\def\Empty{} -% -\newcommand\odescr[2]{% #1=option character, #2=optional argument -\gdef\Arg2{#2}% -\item[\option{#1}\ifx\Arg2\Empty\else{{\it #2}}\fi] -} -\begin{description} -% -\odescr{c}{} $N$ -Abort if any relative cost exceeds $N$, which keeps \PROG from looping on -diverging grammars. Several -references~\cite{pelegri-popl,henry-budp,balachandran-complang,proebsting-91} -explain relative costs. -% -\odescr{d}{} -Report a few statistics and flag unused rules and terminals. -% -\odescr{o}{} {\it file} -Write parser into {\it file}. Otherwise it writes to the standard output. -% -\odescr{p}{} {\it prefix} -Start exported names with {\it prefix}. The default is \var{burm}. -% -\odescr{t}{} -Generates smaller tables faster, but all goal non-terminals passed to -\var{burm\_rule} must come from an appropriate \var{burm\_nts}. Using -\var{burm\_}$x$\var{\_NT} instead may give unpredictable results. -% -\odescr{I}{} -Emit code for \var{burm\_arity}, \var{burm\_child}, \var{burm\_cost}, -\var{burm\_ntname}, \var{burm\_op\_label}, \var{burm\_opname}, -\var{burm\_state\_label}, and \var{burm\_string}. -% -\odescr{O}{} $N$ -Change the principal cost to $N$. Elements of each cost vector are -numbered from zero. -% -\odescr{=}{} -Compare costs lexicographically, using all costs in the given order. -This option slows \PROG and may produce a larger parser. Increases -range from small to astronomical. -\end{description} - -\section{Acknowledgements} - -The first \PROG was adapted by the second author from his \CODEGEN -package, which was developed at the University of Washington with -partial support from NSF Grant CCR-88-01806. It was unbundled from -\CODEGEN with the support of Tera Computer. The current \PROG was -written by the third author with the support of NSF grant -CCR-8908355. The interface, documentation, and testing involved -all three authors. - -Comments from a large group at the 1991 Dagstuhl Seminar on Code -Generation improved \PROG's interface. Robert Giegerich and Susan -Graham organized the workshop, and the International Conference and -Research Center for Computer Science, Schloss Dagstuhl, provided an -ideal environment for such collaboration. Beta-testers included Helmut -Emmelmann, Dave Hanson, John Hauser, Hugh Redelmeier, and Bill Waite. - -\begin{thebibliography}{BMW87} - -\bibitem[AGT89]{aho-twig-toplas} -Alfred~V. Aho, Mahadevan Ganapathi, and Steven W.~K. Tjiang. -\newblock Code generation using tree matching and dynamic programming. -\newblock {\em ACM Transactions on Programming Languages and Systems}, - 11(4):491--516, October 1989. - -\bibitem[AJ76]{aho-johnson-dp-classic} -Alfred~V. Aho and Steven~C. Johnson. -\newblock Optimal code generation for expression trees. -\newblock {\em Journal of the ACM}, 23(3):458--501, July 1976. - -\bibitem[App87]{appel-87} -Andrew~W. Appel. -\newblock Concise specification of locally optimal code generators. -\newblock Technical report CS-TR-080-87, Princeton University, 1987. - -\bibitem[BDB90]{balachandran-complang} -A.~Balachandran, D.~M. Dhamdhere, and S.~Biswas. -\newblock Efficient retargetable code generation using bottom-up tree pattern - matching. -\newblock {\em Computer Languages}, 15(3):127--140, 1990. - -\bibitem[BMW87]{wilhelm-tr} -J\"{u}rgen B\"{o}rstler, Ulrich M\"{o}nche, and Reinhard Wilhelm. -\newblock Table compression for tree automata. -\newblock Technical Report Aachener Informatik-Berichte No. 87-12, RWTH Aachen, - Fachgruppe Informatik, Aachen, Fed. Rep. of Germany, 1987. - -\bibitem[Cha87]{chase-popl} -David~R. Chase. -\newblock An improvement to bottom up tree pattern matching. -\newblock {\em Fourteenth Annual ACM Symposium on Principles of Programming - Languages}, pages 168--177, January 1987. - -\bibitem[FH91]{fraser-henry-spe-91} -Christopher~W. Fraser and Robert~R. Henry. -\newblock Hard-coding bottom-up code generation tables to save time and space. -\newblock {\em Software---Practice\&Experience}, 21(1):1--12, January 1991. - -\bibitem[HC86]{hatcher-popl} -Philip~J. Hatcher and Thomas~W. Christopher. -\newblock High-quality code generation via bottom-up tree pattern matching. -\newblock {\em Thirteenth Annual ACM Symposium on Principles of Programming - Languages}, pages 119--130, January 1986. - -\bibitem[Hen89]{henry-budp} -Robert~R. Henry. -\newblock Encoding optimal pattern selection in a table-driven bottom-up - tree-pattern matcher. -\newblock Technical Report 89-02-04, University of Washington Computer Science - Department, Seattle, WA, February 1989. - -\bibitem[HO82]{hoffmann-jacm} -Christoph Hoffmann and Michael~J. O'Donnell. -\newblock Pattern matching in trees. -\newblock {\em Journal of the ACM}, 29(1):68--95, January 1982. - -\bibitem[Kro75]{kron-phd} -H.~H. Kron. -\newblock {\em Tree Templates and Subtree Transformational Grammars}. -\newblock PhD thesis, UC Santa Cruz, December 1975. - -\bibitem[PL87]{pelegri-phd} -Eduardo Pelegri-Llopart. -\newblock {\em Tree Transformations in Compiler Systems}. -\newblock PhD thesis, UC Berkeley, December 1987. - -\bibitem[PLG88]{pelegri-popl} -Eduardo Pelegri-Llopart and Susan~L. Graham. -\newblock Optimal code generation for expression trees: An application of - {BURS} theory. -\newblock {\em Fifteenth Annual ACM Symposium on Principles of Programming - Languages}, pages 294--308, January 1988. - -\bibitem[Pro91]{proebsting-91} -Todd~A. Proebsting. -\newblock Simple and efficient {BURS} table generation. -\newblock Technical report, Department of Computer Sciences, University of - Wisconsin, 1991. - -\end{thebibliography} - -\end{document} - diff --git a/support/tools/Burg/LOG_CHANGES b/support/tools/Burg/LOG_CHANGES deleted file mode 100644 index 804f00378b..0000000000 --- a/support/tools/Burg/LOG_CHANGES +++ /dev/null @@ -1,10 +0,0 @@ -8/20/02 -- Vikram Adve - be.c: Replaced "char*" with "const char*" to avoid compiler warnings. - -9/9/03 -- John Criswell - b.h be.c fe.h gram.y lex.c main.c map.c nontermainl.c plan.c zalloc.c: - A cursory look through our logs and comments indicates that these are - the only modified files. No feature enhancements have been made; - rather, all changes either fix minor programming errors, get rid of - warnings, ANSI-ify the code, or integrate Burg into our build system. - diff --git a/support/tools/Burg/Makefile b/support/tools/Burg/Makefile deleted file mode 100644 index d1b9fe27fd..0000000000 --- a/support/tools/Burg/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -LEVEL = ../../.. -TOOLNAME = burg -ExtraSource = gram.tab.c - -include $(LEVEL)/Makefile.common - -gram.tab.c gram.tab.h:: gram.yc - $(VERB) $(BISON) -o gram.tab.c -d $< - -$(SourceDir)/lex.c: gram.tab.h - -clean:: - rm -rf gram.tab.h gram.tab.c core* *.aux *.log *.dvi sample sample.c tmp - -#$(BUILD_OBJ_DIR)/Release/lex.o $(BUILD_OBJ_DIR)/Profile/lex.o $(BUILD_OBJ_DIR)/Debug/lex.o: gram.tab.h - -doc.dvi: doc.tex - latex doc; latex doc - - -test:: $(TOOLEXENAME_G) sample.gr - $(TOOLEXENAME_G) -I <sample.gr >sample.c && $(CC) $(CFLAGS) -o sample sample.c && ./sample - $(TOOLEXENAME_G) -I sample.gr >tmp && cmp tmp sample.c - $(TOOLEXENAME_G) -I <sample.gr -o tmp && cmp tmp sample.c - $(TOOLEXENAME_G) -I sample.gr -o tmp && cmp tmp sample.c - $(TOOLEXENAME_G) -I -O0 <sample.gr >tmp && cmp tmp sample.c - $(TOOLEXENAME_G) -I -= <sample.gr >tmp && cmp tmp sample.c - $(RM) -f tmp sample.c diff --git a/support/tools/Burg/README b/support/tools/Burg/README deleted file mode 100644 index bc26405727..0000000000 --- a/support/tools/Burg/README +++ /dev/null @@ -1,14 +0,0 @@ -To format the documentation, type "make doc.dvi" and print the result. - -The length of the cost vectors is fixed at 4 for reasons that are -primarily historical. To change it, edit the definition of DELTAWIDTH -in b.h. - -Burg is compiled without optimization by default to avoid problems -with initial installation. To improve burg's performance, add '-O' to -CFLAGS in the Makefile and rebuild burg with a high quality optimizing -compiler. - -To be added to the Burg mailing list, send your preferred electronic -mail address to cwf@research.att.com. - diff --git a/support/tools/Burg/b.h b/support/tools/Burg/b.h deleted file mode 100644 index 164325dc97..0000000000 --- a/support/tools/Burg/b.h +++ /dev/null @@ -1,311 +0,0 @@ -/* $Id$ */ - -#define MAX_ARITY 2 - -typedef int ItemSetNum; -typedef int OperatorNum; -typedef int NonTerminalNum; -typedef int RuleNum; -typedef int ArityNum; -typedef int ERuleNum; - -extern NonTerminalNum last_user_nonterminal; -extern NonTerminalNum max_nonterminal; -extern RuleNum max_rule; -extern ERuleNum max_erule_num; -extern int max_arity; - -#ifdef __STDC__ -#define ARGS(x) x -#else -#define ARGS(x) () -#endif - -#ifndef NOLEX -#define DELTAWIDTH 4 -typedef short DeltaCost[DELTAWIDTH]; -typedef short *DeltaPtr; -extern void ASSIGNCOST ARGS((DeltaPtr, DeltaPtr)); -extern void ADDCOST ARGS((DeltaPtr, DeltaPtr)); -extern void MINUSCOST ARGS((DeltaPtr, DeltaPtr)); -extern void ZEROCOST ARGS((DeltaPtr)); -extern int LESSCOST ARGS((DeltaPtr, DeltaPtr)); -extern int EQUALCOST ARGS((DeltaPtr, DeltaPtr)); -#define PRINCIPLECOST(x) (x[0]) -#else -#define DELTAWIDTH 1 -typedef int DeltaCost; -typedef int DeltaPtr; -#define ASSIGNCOST(l, r) ((l) = (r)) -#define ADDCOST(l, r) ((l) += (r)) -#define MINUSCOST(l, r) ((l) -= (r)) -#define ZEROCOST(x) ((x) = 0) -#define LESSCOST(l, r) ((l) < (r)) -#define EQUALCOST(l, r) ((l) == (r)) -#define PRINCIPLECOST(x) (x) -#endif /* NOLEX */ -#define NODIVERGE(c,state,nt,base) if (prevent_divergence > 0) CHECKDIVERGE(c,state,nt,base); - -struct list { - void *x; - struct list *next; -}; -typedef struct list *List; - -struct intlist { - int x; - struct intlist *next; -}; -typedef struct intlist *IntList; - -struct operator { - char *name; - unsigned int ref:1; - OperatorNum num; - ItemSetNum baseNum; - ItemSetNum stateCount; - ArityNum arity; - struct table *table; -}; -typedef struct operator *Operator; - -struct nonterminal { - char *name; - NonTerminalNum num; - ItemSetNum baseNum; - ItemSetNum ruleCount; - struct plankMap *pmap; - - struct rule *sampleRule; /* diagnostic---gives "a" rule that with this lhs */ -}; -typedef struct nonterminal *NonTerminal; - -struct pattern { - NonTerminal normalizer; - Operator op; /* NULL if NonTerm -> NonTerm */ - NonTerminal children[MAX_ARITY]; -}; -typedef struct pattern *Pattern; - -struct rule { - DeltaCost delta; - ERuleNum erulenum; - RuleNum num; - RuleNum newNum; - NonTerminal lhs; - Pattern pat; - unsigned int used:1; -}; -typedef struct rule *Rule; - -struct item { - DeltaCost delta; - Rule rule; -}; -typedef struct item Item; - -typedef short *Relevant; /* relevant non-terminals */ - -typedef Item *ItemArray; - -struct item_set { /* indexed by NonTerminal */ - ItemSetNum num; - ItemSetNum newNum; - Operator op; - struct item_set *kids[2]; - struct item_set *representative; - Relevant relevant; - ItemArray virgin; - ItemArray closed; -}; -typedef struct item_set *Item_Set; - -#define DIM_MAP_SIZE (1 << 8) -#define GLOBAL_MAP_SIZE (1 << 15) - -struct mapping { /* should be a hash table for TS -> int */ - List *hash; - int hash_size; - int max_size; - ItemSetNum count; - Item_Set *set; /* map: int <-> Item_Set */ -}; -typedef struct mapping *Mapping; - -struct index_map { - ItemSetNum max_size; - Item_Set *class; -}; -typedef struct index_map Index_Map; - -struct dimension { - Relevant relevant; - Index_Map index_map; - Mapping map; - ItemSetNum max_size; - struct plankMap *pmap; -}; -typedef struct dimension *Dimension; - - -struct table { - Operator op; - List rules; - Relevant relevant; - Dimension dimen[MAX_ARITY]; /* 1 for each dimension */ - Item_Set *transition; /* maps local indices to global - itemsets */ -}; -typedef struct table *Table; - -struct relation { - Rule rule; - DeltaCost chain; - NonTerminalNum nextchain; - DeltaCost sibling; - int sibFlag; - int sibComputed; -}; -typedef struct relation *Relation; - -struct queue { - List head; - List tail; -}; -typedef struct queue *Queue; - -struct plank { - char *name; - List fields; - int width; -}; -typedef struct plank *Plank; - -struct except { - short index; - short value; -}; -typedef struct except *Exception; - -struct plankMap { - List exceptions; - int offset; - struct stateMap *values; -}; -typedef struct plankMap *PlankMap; - -struct stateMap { - char *fieldname; - Plank plank; - int width; - short *value; -}; -typedef struct stateMap *StateMap; - -struct stateMapTable { - List maps; -}; - -extern void CHECKDIVERGE ARGS((DeltaPtr, Item_Set, int, int)); -extern void zero ARGS((Item_Set)); -extern ItemArray newItemArray ARGS((void)); -extern ItemArray itemArrayCopy ARGS((ItemArray)); -extern Item_Set newItem_Set ARGS((Relevant)); -extern void freeItem_Set ARGS((Item_Set)); -extern Mapping newMapping ARGS((int)); -extern NonTerminal newNonTerminal ARGS((char *)); -extern int nonTerminalName ARGS((char *, int)); -extern Operator newOperator ARGS((char *, OperatorNum, ArityNum)); -extern Pattern newPattern ARGS((Operator)); -extern Rule newRule ARGS((DeltaPtr, ERuleNum, NonTerminal, Pattern)); -extern List newList ARGS((void *, List)); -extern IntList newIntList ARGS((int, IntList)); -extern int length ARGS((List)); -extern List appendList ARGS((void *, List)); -extern Table newTable ARGS((Operator)); -extern Queue newQ ARGS((void)); -extern void addQ ARGS((Queue, Item_Set)); -extern Item_Set popQ ARGS((Queue)); -extern int equivSet ARGS((Item_Set, Item_Set)); -extern Item_Set decode ARGS((Mapping, ItemSetNum)); -extern Item_Set encode ARGS((Mapping, Item_Set, int *)); -extern void build ARGS((void)); -extern Item_Set *transLval ARGS((Table, int, int)); - -typedef void * (*ListFn) ARGS((void *)); -extern void foreachList ARGS((ListFn, List)); -extern void reveachList ARGS((ListFn, List)); - -extern void addToTable ARGS((Table, Item_Set)); - -extern void closure ARGS((Item_Set)); -extern void trim ARGS((Item_Set)); -extern void findChainRules ARGS((void)); -extern void findAllPairs ARGS((void)); -extern void addRelevant ARGS((Relevant, NonTerminalNum)); - -extern void *zalloc ARGS((unsigned int)); -extern void zfree ARGS((void *)); - -extern NonTerminal start; -extern List rules; -extern List chainrules; -extern List operators; -extern List leaves; -extern List nonterminals; -extern List grammarNts; -extern Queue globalQ; -extern Mapping globalMap; -extern int exceptionTolerance; -extern int prevent_divergence; -extern int principleCost; -extern int lexical; -extern struct rule stub_rule; -extern Relation *allpairs; -extern Item_Set *sortedStates; -extern Item_Set errorState; - -extern void dumpRelevant ARGS((Relevant)); -extern void dumpOperator ARGS((Operator, int)); -extern void dumpOperator_s ARGS((Operator)); -extern void dumpOperator_l ARGS((Operator)); -extern void dumpNonTerminal ARGS((NonTerminal)); -extern void dumpRule ARGS((Rule)); -extern void dumpRuleList ARGS((List)); -extern void dumpItem ARGS((Item *)); -extern void dumpItem_Set ARGS((Item_Set)); -extern void dumpMapping ARGS((Mapping)); -extern void dumpQ ARGS((Queue)); -extern void dumpIndex_Map ARGS((Index_Map *)); -extern void dumpDimension ARGS((Dimension)); -extern void dumpPattern ARGS((Pattern)); -extern void dumpTable ARGS((Table, int)); -extern void dumpTransition ARGS((Table)); -extern void dumpCost ARGS((DeltaCost)); -extern void dumpAllPairs ARGS((void)); -extern void dumpRelation ARGS((Relation)); -extern void dumpSortedStates ARGS((void)); -extern void dumpSortedRules ARGS((void)); -extern int debugTrim; - -#ifdef DEBUG -#define debug(a,b) if (a) b -#else -#define debug(a,b) -#endif -extern int debugTables; - -#define TABLE_INCR 8 -#define STATES_INCR 64 - -#ifdef NDEBUG -#define assert(c) ((void) 0) -#else -#define assert(c) ((void) ((c) || fatal(__FILE__,__LINE__))) -#endif - -extern void doStart ARGS((char *)); -extern void exit ARGS((int)); -extern int fatal ARGS((const char *, int)); -extern void yyerror ARGS((const char *)); -extern void yyerror1 ARGS((const char *)); diff --git a/support/tools/Burg/be.c b/support/tools/Burg/be.c deleted file mode 100644 index defe948d2d..0000000000 --- a/support/tools/Burg/be.c +++ /dev/null @@ -1,1052 +0,0 @@ -char rcsid_be[] = "$Id$"; - -#include <stdio.h> -#include <string.h> -#include "b.h" -#include "fe.h" - -#define ERROR_VAL 0 - -FILE *outfile; -const char *prefix = "burm"; - -static void doKids ARGS((RuleAST)); -static void doLabel ARGS((Operator)); -static void doLayout ARGS((RuleAST)); -static void doMakeTable ARGS((Operator)); -static void doVector ARGS((RuleAST)); -static void layoutNts ARGS((PatternAST)); -static void makeIndex_Map ARGS((Dimension)); -static void makePvector ARGS((void)); -static void makeState ARGS((void)); -static void printPatternAST ARGS((PatternAST)); -static void printPatternAST_int ARGS((PatternAST)); -static void setVectors ARGS((PatternAST)); -static void trailing_zeroes ARGS((int)); -static int seminal ARGS((int from, int to)); -static void printRule ARGS((RuleAST, const char *)); - -static void -doLabel(op) Operator op; -{ - fprintf(outfile, "\tcase %d:\n", op->num); - - switch (op->arity) { - default: - assert(0); - break; - case 0: - fprintf(outfile, "\t\treturn %d;\n", op->table->transition[0]->num); - break; - case 1: - if (op->table->rules) { - fprintf(outfile, "\t\treturn %s_%s_transition[l];\n", prefix, op->name); - } else { - fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL); - } - break; - case 2: - if (op->table->rules) { - fprintf(outfile, "\t\treturn %s_%s_transition[%s_%s_imap_1[l]][%s_%s_imap_2[r]];\n", prefix, op->name, prefix, op->name, prefix, op->name); - } else { - fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL); - } - break; - } -} - -int -opsOfArity(arity) int arity; -{ - int c; - List l; - - c = 0; - for (l = operators; l; l = l->next) { - Operator op = (Operator) l->x; - if (op->arity == arity) { - fprintf(outfile, "\tcase %d:\n", op->num); - c++; - } - } - return c; -} - -static void -trailing_zeroes(z) int z; -{ - int i; - - for (i = 0; i < z; i++) { - fprintf(outfile, ", 0"); - } -} - -void -makeLabel() -{ - int flag; - - fprintf(outfile, "#ifdef __STDC__\n"); - fprintf(outfile, "int %s_label(%s_NODEPTR_TYPE n) {\n", prefix, prefix); - fprintf(outfile, "#else\n"); - fprintf(outfile, "int %s_label(n) %s_NODEPTR_TYPE n; {\n", prefix, prefix); - fprintf(outfile, "#endif\n"); - - fprintf(outfile, - "\t%s_assert(n, %s_PANIC(\"NULL pointer passed to %s_label\\n\"));\n", - prefix, prefix, prefix); - fprintf(outfile, "\tswitch (%s_OP_LABEL(n)) {\n", prefix); - fprintf(outfile, "\tdefault: %s_PANIC(\"Bad op %%d in %s_label\\n\", %s_OP_LABEL(n)); abort(); return 0;\n", - prefix, prefix, prefix); - - flag = opsOfArity(0); - if (flag > 0) { - fprintf(outfile, "\t\treturn %s_STATE_LABEL(n) = %s_state(%s_OP_LABEL(n)", - prefix, prefix, prefix); - trailing_zeroes(max_arity); - fprintf(outfile, ");\n"); - } - flag = opsOfArity(1); - if (flag > 0) { - fprintf(outfile, "\t\treturn %s_STATE_LABEL(n) = %s_state(%s_OP_LABEL(n), %s_label(%s_LEFT_CHILD(n))", - prefix, prefix, prefix, prefix, prefix); - trailing_zeroes(max_arity-1); - fprintf(outfile, ");\n"); - } - flag = opsOfArity(2); - if (flag > 0) { - fprintf(outfile, "\t\treturn %s_STATE_LABEL(n) = %s_state(%s_OP_LABEL(n), %s_label(%s_LEFT_CHILD(n)), %s_label(%s_RIGHT_CHILD(n))", - prefix, prefix, prefix, prefix, prefix, prefix, prefix); - trailing_zeroes(max_arity-2); - fprintf(outfile, ");\n"); - - } - fprintf(outfile, "\t}\n"); - fprintf(outfile, "}\n"); -} - -static void -makeState() -{ - fprintf(outfile, "int %s_state(int op, int l, int r) {\n", prefix); - fprintf(outfile, - "\t%s_assert(l >= 0 && l < %d, PANIC(\"Bad state %%d passed to %s_state\\n\", l));\n", - prefix, globalMap->count, prefix); - fprintf(outfile, - "\t%s_assert(r >= 0 && r < %d, PANIC(\"Bad state %%d passed to %s_state\\n\", r));\n", - prefix, globalMap->count, prefix); - fprintf(outfile, "\tswitch (op) {\n"); - fprintf(outfile, "\tdefault: %s_PANIC(\"Bad op %%d in %s_state\\n\", op); abort(); return 0;\n", prefix, prefix); - - foreachList((ListFn) doLabel, operators); - - fprintf(outfile, "\t}\n"); - fprintf(outfile, "}\n"); -} - -static char cumBuf[4000]; -static int vecIndex; -char vecBuf[4000]; - -static void -setVectors(ast) PatternAST ast; -{ - char old[4000]; - - switch (ast->sym->tag) { - default: - assert(0); - break; - case NONTERMINAL: - sprintf(old, "\t\tkids[%d] = %s;\n", vecIndex, vecBuf); - strcat(cumBuf, old); - vecIndex++; - return; - case OPERATOR: - switch (ast->sym->u.op->arity) { - default: - assert(0); - break; - case 0: - return; - case 1: - strcpy(old, vecBuf); - sprintf(vecBuf, "%s_LEFT_CHILD(%s)", prefix, old); - setVectors((PatternAST) ast->children->x); - strcpy(vecBuf, old); - return; - case 2: - strcpy(old, vecBuf); - sprintf(vecBuf, "%s_LEFT_CHILD(%s)", prefix, old); - setVectors((PatternAST) ast->children->x); - - sprintf(vecBuf, "%s_RIGHT_CHILD(%s)", prefix, old); - setVectors((PatternAST) ast->children->next->x); - strcpy(vecBuf, old); - return; - } - break; - } -} - -#define MAX_VECTOR 10 - -void -makeRuleTable() -{ - int s,nt; - - fprintf(outfile, "static short %s_RuleNo[%d][%d] = {\n", prefix, globalMap->count, last_user_nonterminal-1); - for (s = 0; s < globalMap->count; s++) { - Item_Set ts = globalMap->set[s]; - if (s > 0) { - fprintf(outfile, ",\n"); - } - fprintf(outfile, "/* state %d */\n", s); - fprintf(outfile, "{"); - for (nt = 1; nt < last_user_nonterminal; nt++) { - if (nt > 1) { - fprintf(outfile, ","); - if (nt % 10 == 1) { - fprintf(outfile, "\t/* state %d; Nonterminals %d-%d */\n", s, nt-10, nt-1); - } - } - if (ts->closed[nt].rule) { - ts->closed[nt].rule->used = 1; - fprintf(outfile, "%5d", ts->closed[nt].rule->erulenum); - } else { - fprintf(outfile, "%5d", ERROR_VAL); - } - } - fprintf(outfile, "}"); - } - fprintf(outfile, "};\n"); -} - -static void -makeIndex_Map(d) Dimension d; -{ - int s; - - for (s = 0; s < globalMap->count; s++) { - if (s > 0) { - fprintf(outfile, ","); - if (s % 10 == 0) { - fprintf(outfile, "\t/* %d-%d */\n", s-10, s-1); - } - } - fprintf(outfile, "%5d", d->map->set[d->index_map.class[s]->num]->num); - } - fprintf(outfile, "};\n"); -} - -static void -doMakeTable(op) Operator op; -{ - int s; - int i,j; - Dimension d; - - switch (op->arity) { - default: - assert(0); - break; - case 0: - return; - case 1: - if (!op->table->rules) { - return; - } - d = op->table->dimen[0]; - fprintf(outfile, "static short %s_%s_transition[%d] = {\n", prefix, op->name, globalMap->count); - for (s = 0; s < globalMap->count; s++) { - if (s > 0) { - fprintf(outfile, ", "); - if (s % 10 == 0) { - fprintf(outfile, "\t/* %d-%d */\n", s-10, s-1); - } - } - fprintf(outfile, "%5d", op->table->transition[d->map->set[d->index_map.class[s]->num]->num]->num); - } - fprintf(outfile, "};\n"); - break; - case 2: - if (!op->table->rules) { - return; - } - fprintf(outfile, "static short %s_%s_imap_1[%d] = {\n", prefix, op->name, globalMap->count); - makeIndex_Map(op->table->dimen[0]); - fprintf(outfile, "static short %s_%s_imap_2[%d] = {\n", prefix, op->name, globalMap->count); - makeIndex_Map(op->table->dimen[1]); - - fprintf(outfile, "static short %s_%s_transition[%d][%d] = {", prefix, op->name, - op->table->dimen[0]->map->count, - op->table->dimen[1]->map->count); - for (i = 0; i < op->table->dimen[0]->map->count; i++) { - if (i > 0) { - fprintf(outfile, ","); - } - fprintf(outfile, "\n"); - fprintf(outfile, "{"); - for (j = 0; j < op->table->dimen[1]->map->count; j++) { - Item_Set *ts = transLval(op->table, i, j); - if (j > 0) { - fprintf(outfile, ","); - } - fprintf(outfile, "%5d", (*ts)->num); - } - fprintf(outfile, "}\t/* row %d */", i); - } - fprintf(outfile, "\n};\n"); - - break; - } -} - -void -makeTables() -{ - foreachList((ListFn) doMakeTable, operators); -} - -RuleAST *pVector; - -void -makeLHSmap() -{ - int i; - - if (!pVector) { - makePvector(); - } - - fprintf(outfile, "short %s_lhs[] = {\n", prefix); - for (i = 0; i <= max_erule_num; i++) { - if (pVector[i]) { - fprintf(outfile, "\t%s_%s_NT,\n", prefix, pVector[i]->lhs); - } else { - fprintf(outfile, "\t0,\n"); - } - } - fprintf(outfile, "};\n\n"); -} - -static int seminal(int from, int to) -{ - return allpairs[from][to].rule ? allpairs[from][to].rule->erulenum : 0; - - /* - int tmp, last; - tmp = 0; - for (;;) { - last = tmp; - tmp = allpairs[to][from].rule ? allpairs[to][from].rule->erulenum : 0; - if (!tmp) { - break; - } - assert(pVector[tmp]); - to = pVector[tmp]->rule->pat->children[0]->num; - } - return last; - */ -} - -void -makeClosureArray() -{ - int i, j; - - if (!pVector) { - makePvector(); - } - - fprintf(outfile, "short %s_closure[%d][%d] = {\n", prefix, last_user_nonterminal, last_user_nonterminal); - for (i = 0; i < last_user_nonterminal; i++) { - fprintf(outfile, "\t{"); - for (j = 0; j < last_user_nonterminal; j++) { - if (j > 0 && j%10 == 0) { - fprintf(outfile, "\n\t "); - } - fprintf(outfile, " %4d,", seminal(i,j)); - } - fprintf(outfile, "},\n"); - } - fprintf(outfile, "};\n"); -} - -void -makeCostVector(z,d) int z; DeltaCost d; -{ - fprintf(outfile, "\t{"); -#ifdef NOLEX - if (z) { - fprintf(outfile, "%5d", d); - } else { - fprintf(outfile, "%5d", 0); - } -#else - { - int j; - for (j = 0; j < DELTAWIDTH; j++) { - if (j > 0) { - fprintf(outfile, ","); - } - if (z) { - fprintf(outfile, "%5d", d[j]); - } else { - fprintf(outfile, "%5d", 0); - } - } - } -#endif /* NOLEX */ - fprintf(outfile, "}"); -} - -void -makeCostArray() -{ - int i; - - if (!pVector) { - makePvector(); - } - - fprintf(outfile, "short %s_cost[][%d] = {\n", prefix, DELTAWIDTH); - for (i = 0; i <= max_erule_num; i++) { - makeCostVector(pVector[i], pVector[i] ? pVector[i]->rule->delta : 0); - fprintf(outfile, ", /* "); - printRule(pVector[i], "(none)"); - fprintf(outfile, " = %d */\n", i); - } - fprintf(outfile, "};\n"); -} - -void -makeStateStringArray() -{ - int s; - int nt; - int states; - - states = globalMap->count; - fprintf(outfile, "\nconst char * %s_state_string[] = {\n", prefix); - fprintf(outfile, "\" not a state\", /* state 0 */\n"); - for (s = 0; s < states-1; s++) { - fprintf(outfile, "\t\""); - printRepresentative(outfile, sortedStates[s]); - fprintf(outfile, "\", /* state #%d */\n", s+1); - } - fprintf(outfile, "};\n"); -} - -void -makeDeltaCostArray() -{ - int s; - int nt; - int states; - - states = globalMap->count; - fprintf(outfile, "\nshort %s_delta_cost[%d][%d][%d] = {\n", prefix, states, last_user_nonterminal, DELTAWIDTH); - fprintf(outfile, "{{0}}, /* state 0 */\n"); - for (s = 0; s < states-1; s++) { - fprintf(outfile, "{ /* state #%d: ", s+1); - printRepresentative(outfile, sortedStates[s]); - fprintf(outfile, " */\n"); - fprintf(outfile, "\t{0},\n"); - for (nt = 1; nt < last_user_nonterminal; nt++) { - makeCostVector(1, sortedStates[s]->closed[nt].delta); - fprintf(outfile, ", /* "); - if (sortedStates[s]->closed[nt].rule) { - int erulenum = sortedStates[s]->closed[nt].rule->erulenum; - printRule(pVector[erulenum], "(none)"); - fprintf(outfile, " = %d */", erulenum); - } else { - fprintf(outfile, "(none) */"); - } - fprintf(outfile, "\n"); - } - fprintf(outfile, "},\n"); - } - fprintf(outfile, "};\n"); -} - -static void -printPatternAST_int(p) PatternAST p; -{ - List l; - - if (p) { - switch (p->sym->tag) { - case NONTERMINAL: - fprintf(outfile, "%5d,", -p->sym->u.nt->num); - break; - case OPERATOR: - fprintf(outfile, "%5d,", p->sym->u.op->num); - break; - default: - assert(0); - } - if (p->children) { - for (l = p->children; l; l = l->next) { - PatternAST pat = (PatternAST) l->x; - printPatternAST_int(pat); - } - } - } -} - -static void -printPatternAST(p) PatternAST p; -{ - List l; - - if (p) { - fprintf(outfile, "%s", p->op); - if (p->children) { - fprintf(outfile, "("); - for (l = p->children; l; l = l->next) { - PatternAST pat = (PatternAST) l->x; - if (l != p->children) { - fprintf(outfile, ", "); - } - printPatternAST(pat); - } - fprintf(outfile, ")"); - } - } -} - -static void -layoutNts(ast) PatternAST ast; -{ - char out[30]; - - switch (ast->sym->tag) { - default: - assert(0); - break; - case NONTERMINAL: - sprintf(out, "%d, ", ast->sym->u.nt->num); - strcat(cumBuf, out); - return; - case OPERATOR: - switch (ast->sym->u.op->arity) { - default: - assert(0); - break; - case 0: - return; - case 1: - layoutNts((PatternAST) ast->children->x); - return; - case 2: - layoutNts((PatternAST) ast->children->x); - layoutNts((PatternAST) ast->children->next->x); - return; - } - break; - } -} - -static void -doVector(ast) RuleAST ast; -{ - if (pVector[ast->rule->erulenum]) { - fprintf(stderr, "ERROR: non-unique external rule number: (%d)\n", ast->rule->erulenum); - exit(1); - } - pVector[ast->rule->erulenum] = ast; -} - -static void -makePvector() -{ - pVector = (RuleAST*) zalloc((max_erule_num+1) * sizeof(RuleAST)); - foreachList((ListFn) doVector, ruleASTs); -} - -static void -doLayout(ast) RuleAST ast; -{ - sprintf(cumBuf, "{ "); - layoutNts(ast->pat); - strcat(cumBuf, "0 }"); -} - -void -makeNts() -{ - int i; - int new; - StrTable nts; - - nts = newStrTable(); - - if (!pVector) { - makePvector(); - } - - for (i = 0; i <= max_erule_num; i++) { - if (pVector[i]) { - doLayout(pVector[i]); - pVector[i]->nts = addString(nts, cumBuf, i, &new); - if (new) { - char ename[50]; - - sprintf(ename, "%s_r%d_nts", prefix, i); - pVector[i]->nts->ename = (char*) zalloc(strlen(ename)+1); - strcpy(pVector[i]->nts->ename, ename); - fprintf(outfile, "static short %s[] =", ename); - fprintf(outfile, "%s;\n", cumBuf); - } - } - } - - fprintf(outfile, "short *%s_nts[] = {\n", prefix); - for (i = 0; i <= max_erule_num; i++) { - if (pVector[i]) { - fprintf(outfile, "\t%s,\n", pVector[i]->nts->ename); - } else { - fprintf(outfile, "\t0,\n"); - } - } - fprintf(outfile, "};\n"); -} - -static void -printRule(RuleAST r, const char *d) -{ - if (r) { - fprintf(outfile, "%s: ", r->rule->lhs->name); - printPatternAST(r->pat); - } else { - fprintf(outfile, "%s", d); - } -} - -void -makeRuleDescArray() -{ - int i; - - if (!pVector) { - makePvector(); - } - - if (last_user_nonterminal != max_nonterminal) { - /* not normal form */ - fprintf(outfile, "short %s_rule_descriptor_0[] = { 0, 0 };\n", prefix); - } else { - fprintf(outfile, "short %s_rule_descriptor_0[] = { 0, 1 };\n", prefix); - } - for (i = 1; i <= max_erule_num; i++) { - if (pVector[i]) { - Operator o; - NonTerminal t; - - fprintf(outfile, "short %s_rule_descriptor_%d[] = {", prefix, i); - fprintf(outfile, "%5d,", -pVector[i]->rule->lhs->num); - printPatternAST_int(pVector[i]->pat); - fprintf(outfile, " };\n"); - } - } - - fprintf(outfile, "/* %s_rule_descriptors[0][1] = 1 iff grammar is normal form. */\n", prefix); - fprintf(outfile, "short * %s_rule_descriptors[] = {\n", prefix); - fprintf(outfile, "\t%s_rule_descriptor_0,\n", prefix); - for (i = 1; i <= max_erule_num; i++) { - if (pVector[i]) { - fprintf(outfile, "\t%s_rule_descriptor_%d,\n", prefix, i); - } else { - fprintf(outfile, "\t%s_rule_descriptor_0,\n", prefix); - } - } - fprintf(outfile, "};\n"); -} - - -void -makeRuleDescArray2() -{ - int i; - - if (!pVector) { - makePvector(); - } - - fprintf(outfile, "struct { int lhs, op, left, right; } %s_rule_struct[] = {\n", prefix); - if (last_user_nonterminal != max_nonterminal) { - /* not normal form */ - fprintf(outfile, "\t{-1},"); - } else { - fprintf(outfile, "\t{0},"); - } - fprintf(outfile, " /* 0 if normal form, -1 if not normal form */\n"); - for (i = 1; i <= max_erule_num; i++) { - fprintf(outfile, "\t"); - if (pVector[i]) { - Operator o; - NonTerminal t1, t2; - - fprintf(outfile, "{"); - fprintf(outfile, "%5d, %5d, %5d, %5d", - pVector[i]->rule->lhs->num, - (o = pVector[i]->rule->pat->op) ? o->num : 0, - (t1 = pVector[i]->rule->pat->children[0]) ? t1->num : 0, - (t2 = pVector[i]->rule->pat->children[1]) ? t2->num : 0 - ); - fprintf(outfile, "} /* "); - printRule(pVector[i], "0"); - fprintf(outfile, " = %d */", i); - } else { - fprintf(outfile, "{0}"); - } - fprintf(outfile, ",\n"); - } - fprintf(outfile, "};\n"); -} - -void -makeStringArray() -{ - int i; - - if (!pVector) { - makePvector(); - } - - fprintf(outfile, "const char *%s_string[] = {\n", prefix); - for (i = 0; i <= max_erule_num; i++) { - fprintf(outfile, "\t"); - if (pVector[i]) { - fprintf(outfile, "\""); - printRule(pVector[i], "0"); - fprintf(outfile, "\""); - } else { - fprintf(outfile, "0"); - } - fprintf(outfile, ",\n"); - } - fprintf(outfile, "};\n"); - fprintf(outfile, "int %s_max_rule = %d;\n", prefix, max_erule_num); - fprintf(outfile, "#define %s_Max_rule %d\n", prefix, max_erule_num); -} - -void -makeRule() -{ - fprintf(outfile, "int %s_rule(int state, int goalnt) {\n", prefix); - fprintf(outfile, - "\t%s_assert(state >= 0 && state < %d, PANIC(\"Bad state %%d passed to %s_rule\\n\", state));\n", - prefix, globalMap->count, prefix); - fprintf(outfile, - "\t%s_assert(goalnt >= 1 && goalnt < %d, PANIC(\"Bad goalnt %%d passed to %s_rule\\n\", state));\n", - prefix, max_nonterminal, prefix); - fprintf(outfile, "\treturn %s_RuleNo[state][goalnt-1];\n", prefix); - fprintf(outfile, "};\n"); -} - -static StrTable kids; - -static void -doKids(ast) RuleAST ast; -{ - int new; - - vecIndex = 0; - cumBuf[0] = 0; - strcpy(vecBuf, "p"); - setVectors(ast->pat); - - ast->kids = addString(kids, cumBuf, ast->rule->erulenum, &new); - -} - -void -makeKids() -{ - List e; - IntList r; - - kids = newStrTable(); - - fprintf(outfile, "#ifdef __STDC__\n"); - fprintf(outfile, "%s_NODEPTR_TYPE * %s_kids(%s_NODEPTR_TYPE p, int rulenumber, %s_NODEPTR_TYPE *kids) {\n", prefix, prefix, prefix, prefix); - fprintf(outfile, "#else\n"); - fprintf(outfile, "%s_NODEPTR_TYPE * %s_kids(p, rulenumber, kids) %s_NODEPTR_TYPE p; int rulenumber; %s_NODEPTR_TYPE *kids; {\n", prefix, prefix, prefix, prefix); - fprintf(outfile, "#endif\n"); - - fprintf(outfile, - "\t%s_assert(p, %s_PANIC(\"NULL node pointer passed to %s_kids\\n\"));\n", - prefix, prefix, prefix); - fprintf(outfile, - "\t%s_assert(kids, %s_PANIC(\"NULL kids pointer passed to %s_kids\\n\"));\n", - prefix, prefix, prefix); - fprintf(outfile, "\tswitch (rulenumber) {\n"); - fprintf(outfile, "\tdefault:\n"); - fprintf(outfile, "\t\t%s_PANIC(\"Unknown Rule %%d in %s_kids;\\n\", rulenumber);\n", prefix, prefix); - fprintf(outfile, "\t\tabort();\n"); - fprintf(outfile, "\t\t/* NOTREACHED */\n"); - - foreachList((ListFn) doKids, ruleASTs); - - for (e = kids->elems; e; e = e->next) { - StrTableElement el = (StrTableElement) e->x; - for (r = el->erulenos; r; r = r->next) { - int i = r->x; - fprintf(outfile, "\tcase %d:\n", i); - } - fprintf(outfile, "%s", el->str); - fprintf(outfile, "\t\tbreak;\n"); - } - fprintf(outfile, "\t}\n"); - fprintf(outfile, "\treturn kids;\n"); - fprintf(outfile, "}\n"); -} - -void -makeOpLabel() -{ - fprintf(outfile, "#ifdef __STDC__\n"); - fprintf(outfile, "int %s_op_label(%s_NODEPTR_TYPE p) {\n", prefix, prefix); - fprintf(outfile, "#else\n"); - fprintf(outfile, "int %s_op_label(p) %s_NODEPTR_TYPE p; {\n", prefix, prefix); - fprintf(outfile, "#endif\n"); - fprintf(outfile, - "\t%s_assert(p, %s_PANIC(\"NULL pointer passed to %s_op_label\\n\"));\n", - prefix, prefix, prefix); - fprintf(outfile, "\treturn %s_OP_LABEL(p);\n", prefix); - fprintf(outfile, "}\n"); -} - -void -makeStateLabel() -{ - fprintf(outfile, "#ifdef __STDC__\n"); - fprintf(outfile, "int %s_state_label(%s_NODEPTR_TYPE p) {\n", prefix, prefix); - fprintf(outfile, "#else\n"); - fprintf(outfile, "int %s_state_label(p) %s_NODEPTR_TYPE p; {\n", prefix, prefix); - fprintf(outfile, "#endif\n"); - - fprintf(outfile, - "\t%s_assert(p, %s_PANIC(\"NULL pointer passed to %s_state_label\\n\"));\n", - prefix, prefix, prefix); - fprintf(outfile, "\treturn %s_STATE_LABEL(p);\n", prefix); - fprintf(outfile, "}\n"); -} - -void -makeChild() -{ - fprintf(outfile, "#ifdef __STDC__\n"); - fprintf(outfile, "%s_NODEPTR_TYPE %s_child(%s_NODEPTR_TYPE p, int index) {\n", prefix, prefix, prefix); - fprintf(outfile, "#else\n"); - fprintf(outfile, "%s_NODEPTR_TYPE %s_child(p, index) %s_NODEPTR_TYPE p; int index; {\n", prefix, prefix, prefix); - fprintf(outfile, "#endif\n"); - - fprintf(outfile, - "\t%s_assert(p, %s_PANIC(\"NULL pointer passed to %s_child\\n\"));\n", - prefix, prefix, prefix); - fprintf(outfile, "\tswitch (index) {\n"); - fprintf(outfile, "\tcase 0:\n"); - fprintf(outfile, "\t\treturn %s_LEFT_CHILD(p);\n", prefix); - fprintf(outfile, "\tcase 1:\n"); - fprintf(outfile, "\t\treturn %s_RIGHT_CHILD(p);\n", prefix); - fprintf(outfile, "\t}\n"); - fprintf(outfile, "\t%s_PANIC(\"Bad index %%d in %s_child;\\n\", index);\n", prefix, prefix); - fprintf(outfile, "\tabort();\n"); - fprintf(outfile, "\treturn 0;\n"); - fprintf(outfile, "}\n"); -} - -static Operator *opVector; -static int maxOperator; - -void -makeOperatorVector() -{ - List l; - - maxOperator = 0; - for (l = operators; l; l = l->next) { - Operator op = (Operator) l->x; - if (op->num > maxOperator) { - maxOperator = op->num; - } - } - opVector = (Operator*) zalloc((maxOperator+1) * sizeof(*opVector)); - for (l = operators; l; l = l->next) { - Operator op = (Operator) l->x; - if (opVector[op->num]) { - fprintf(stderr, "ERROR: Non-unique external symbol number (%d)\n", op->num); - exit(1); - } - opVector[op->num] = op; - } -} - -void -makeOperators() -{ - int i; - - if (!opVector) { - makeOperatorVector(); - } - fprintf(outfile, "const char * %s_opname[] = {\n", prefix); - for (i = 0; i <= maxOperator; i++) { - if (i > 0) { - fprintf(outfile, ", /* %d */\n", i-1); - } - if (opVector[i]) { - fprintf(outfile, "\t\"%s\"", opVector[i]->name); - } else { - fprintf(outfile, "\t0"); - } - } - fprintf(outfile, "\n};\n"); - fprintf(outfile, "char %s_arity[] = {\n", prefix); - for (i = 0; i <= maxOperator; i++) { - if (i > 0) { - fprintf(outfile, ", /* %d */\n", i-1); - } - fprintf(outfile, "\t%d", opVector[i] ? opVector[i]->arity : -1); - } - fprintf(outfile, "\n};\n"); - fprintf(outfile, "int %s_max_op = %d;\n", prefix, maxOperator); - fprintf(outfile, "int %s_max_state = %d;\n", prefix, globalMap->count-1); - fprintf(outfile, "#define %s_Max_state %d\n", prefix, globalMap->count-1); -} - -void -makeDebug() -{ - fprintf(outfile, "#ifdef DEBUG\n"); - fprintf(outfile, "int %s_debug;\n", prefix); - fprintf(outfile, "#endif /* DEBUG */\n"); -} - -void -makeSimple() -{ - makeRuleTable(); - makeTables(); - makeRule(); - makeState(); -} - -void -startOptional() -{ - fprintf(outfile, "#ifdef %s_STATE_LABEL\n", prefix); - fprintf(outfile, "#define %s_INCLUDE_EXTRA\n", prefix); - fprintf(outfile, "#else\n"); - fprintf(outfile, "#ifdef STATE_LABEL\n"); - fprintf(outfile, "#define %s_INCLUDE_EXTRA\n", prefix); - fprintf(outfile, "#define %s_STATE_LABEL \tSTATE_LABEL\n", prefix); - fprintf(outfile, "#define %s_NODEPTR_TYPE\tNODEPTR_TYPE\n", prefix); - fprintf(outfile, "#define %s_LEFT_CHILD \tLEFT_CHILD\n", prefix); - fprintf(outfile, "#define %s_OP_LABEL \tOP_LABEL\n", prefix); - fprintf(outfile, "#define %s_RIGHT_CHILD \tRIGHT_CHILD\n", prefix); - fprintf(outfile, "#endif /* STATE_LABEL */\n"); - fprintf(outfile, "#endif /* %s_STATE_LABEL */\n\n", prefix); - - fprintf(outfile, "#ifdef %s_INCLUDE_EXTRA\n\n", prefix); - -} - -void -makeNonterminals() -{ - List l; - - for (l = nonterminals; l; l = l->next) { - NonTerminal nt = (NonTerminal) l->x; - if (nt->num < last_user_nonterminal) { - fprintf(outfile, "#define %s_%s_NT %d\n", prefix, nt->name, nt->num); - } - } - fprintf(outfile, "#define %s_NT %d\n", prefix, last_user_nonterminal-1); -} - -void -makeNonterminalArray() -{ - int i; - List l; - NonTerminal *nta; - - nta = (NonTerminal *) zalloc(sizeof(*nta) * last_user_nonterminal); - - for (l = nonterminals; l; l = l->next) { - NonTerminal nt = (NonTerminal) l->x; - if (nt->num < last_user_nonterminal) { - nta[nt->num] = nt; - } - } - - fprintf(outfile, "const char *%s_ntname[] = {\n", prefix); - fprintf(outfile, "\t\"Error: Nonterminals are > 0\",\n"); - for (i = 1; i < last_user_nonterminal; i++) { - fprintf(outfile, "\t\"%s\",\n", nta[i]->name); - } - fprintf(outfile, "\t0\n"); - fprintf(outfile, "};\n\n"); - - zfree(nta); -} - -void -endOptional() -{ - fprintf(outfile, "#endif /* %s_INCLUDE_EXTRA */\n", prefix); -} - -void -startBurm() -{ - fprintf(outfile, "#ifndef %s_PANIC\n", prefix); - fprintf(outfile, "#define %s_PANIC\tPANIC\n", prefix); - fprintf(outfile, "#endif /* %s_PANIC */\n", prefix); - fprintf(outfile, "#ifdef __STDC__\n"); - fprintf(outfile, "extern void abort(void);\n"); - fprintf(outfile, "#else\n"); - fprintf(outfile, "extern void abort();\n"); - fprintf(outfile, "#endif\n"); - fprintf(outfile, "#ifdef NDEBUG\n"); - fprintf(outfile, "#define %s_assert(x,y)\t;\n", prefix); - fprintf(outfile, "#else\n"); - fprintf(outfile, "#define %s_assert(x,y)\tif(!(x)) {y; abort();}\n", prefix); - fprintf(outfile, "#endif\n"); -} - -void -reportDiagnostics() -{ - List l; - - for (l = operators; l; l = l->next) { - Operator op = (Operator) l->x; - if (!op->ref) { - fprintf(stderr, "warning: Unreferenced Operator: %s\n", op->name); - } - } - for (l = rules; l; l = l->next) { - Rule r = (Rule) l->x; - if (!r->used && r->num < max_ruleAST) { - fprintf(stderr, "warning: Unused Rule: #%d\n", r->erulenum); - } - } - if (!start->pmap) { - fprintf(stderr, "warning: Start Nonterminal (%s) does not appear on LHS.\n", start->name); - } - - fprintf(stderr, "start symbol = \"%s\"\n", start->name); - fprintf(stderr, "# of states = %d\n", globalMap->count-1); - fprintf(stderr, "# of nonterminals = %d\n", max_nonterminal-1); - fprintf(stderr, "# of user nonterminals = %d\n", last_user_nonterminal-1); - fprintf(stderr, "# of rules = %d\n", max_rule); - fprintf(stderr, "# of user rules = %d\n", max_ruleAST); -} diff --git a/support/tools/Burg/burg.shar.gz b/support/tools/Burg/burg.shar.gz Binary files differdeleted file mode 100644 index 173bbfde9f..0000000000 --- a/support/tools/Burg/burg.shar.gz +++ /dev/null diff --git a/support/tools/Burg/burs.c b/support/tools/Burg/burs.c deleted file mode 100644 index b4f8b83d00..0000000000 --- a/support/tools/Burg/burs.c +++ /dev/null @@ -1,71 +0,0 @@ -char rcsid_burs[] = "$Id$"; - -#include "b.h" - -Item_Set errorState; - -static void doLeaf ARGS((Operator)); - -static void -doLeaf(leaf) Operator leaf; -{ - int new; - List pl; - Item_Set ts; - Item_Set tmp; - - assert(leaf->arity == 0); - - ts = newItem_Set(leaf->table->relevant); - - for (pl = rules; pl; pl = pl->next) { - Rule p = (Rule) pl->x; - if (p->pat->op == leaf) { - if (!ts->virgin[p->lhs->num].rule || p->delta < ts->virgin[p->lhs->num].delta) { - ts->virgin[p->lhs->num].rule = p; - ASSIGNCOST(ts->virgin[p->lhs->num].delta, p->delta); - ts->op = leaf; - } - } - } - trim(ts); - zero(ts); - tmp = encode(globalMap, ts, &new); - if (new) { - closure(ts); - leaf->table->transition[0] = ts; - addQ(globalQ, ts); - } else { - leaf->table->transition[0] = tmp; - freeItem_Set(ts); - } -} - -void -build() -{ - int new; - List ol; - Item_Set ts; - - globalQ = newQ(); - globalMap = newMapping(GLOBAL_MAP_SIZE); - - ts = newItem_Set(0); - errorState = encode(globalMap, ts, &new); - ts->closed = ts->virgin; - addQ(globalQ, ts); - - foreachList((ListFn) doLeaf, leaves); - - debug(debugTables, printf("---initial set of states ---\n")); - debug(debugTables, dumpMapping(globalMap)); - debug(debugTables, foreachList((ListFn) dumpItem_Set, globalQ->head)); - - for (ts = popQ(globalQ); ts; ts = popQ(globalQ)) { - for (ol = operators; ol; ol = ol->next) { - Operator op = (Operator) ol->x; - addToTable(op->table, ts); - } - } -} diff --git a/support/tools/Burg/closure.c b/support/tools/Burg/closure.c deleted file mode 100644 index 70e16264eb..0000000000 --- a/support/tools/Burg/closure.c +++ /dev/null @@ -1,95 +0,0 @@ -char rcsid_closure[] = "$Id$"; - -#include <stdio.h> -#include "b.h" - -int prevent_divergence = 0; - -List chainrules; - -void -findChainRules() -{ - List pl; - - assert(!chainrules); - - for (pl = rules; pl; pl = pl->next) { - Rule p = (Rule) pl->x; - if (!p->pat->op) { - chainrules = newList(p, chainrules); - } else { - p->pat->op->table->rules = newList(p, p->pat->op->table->rules); - addRelevant(p->pat->op->table->relevant, p->lhs->num); - } - } -} - -void -zero(t) Item_Set t; -{ - int i; - DeltaCost base; - int exists; - int base_nt; - - assert(!t->closed); - - ZEROCOST(base); - exists = 0; - for (i = 0; i < max_nonterminal; i++) { - if (t->virgin[i].rule) { - if (exists) { - if (LESSCOST(t->virgin[i].delta, base)) { - ASSIGNCOST(base, t->virgin[i].delta); - base_nt = i; - } - } else { - ASSIGNCOST(base, t->virgin[i].delta); - exists = 1; - base_nt = i; - } - } - } - if (!exists) { - return; - } - for (i = 0; i < max_nonterminal; i++) { - if (t->virgin[i].rule) { - MINUSCOST(t->virgin[i].delta, base); - } - NODIVERGE(t->virgin[i].delta, t, i, base_nt); - } -} - -void -closure(t) Item_Set t; -{ - int changes; - List pl; - - assert(!t->closed); - t->closed = itemArrayCopy(t->virgin); - - changes = 1; - while (changes) { - changes = 0; - for (pl = chainrules; pl; pl = pl->next) { - Rule p = (Rule) pl->x; - register Item *rhs_item = &t->closed[p->pat->children[0]->num]; - - if (rhs_item->rule) { /* rhs is active */ - DeltaCost dc; - register Item *lhs_item = &t->closed[p->lhs->num]; - - ASSIGNCOST(dc, rhs_item->delta); - ADDCOST(dc, p->delta); - if (LESSCOST(dc, lhs_item->delta) || !lhs_item->rule) { - ASSIGNCOST(lhs_item->delta, dc); - lhs_item->rule = p; - changes = 1; - } - } - } - } -} diff --git a/support/tools/Burg/delta.c b/support/tools/Burg/delta.c deleted file mode 100644 index d79654910f..0000000000 --- a/support/tools/Burg/delta.c +++ /dev/null @@ -1,143 +0,0 @@ -char rcsid_delta[] = "$Id$"; - -#include <stdio.h> -#include "b.h" -#include "fe.h" - -int principleCost = 0; -int lexical = 0; - -#ifndef NOLEX -void -ASSIGNCOST(l, r) DeltaPtr l; DeltaPtr r; -{ - int i; - - if (lexical) { - for (i = 0; i < DELTAWIDTH; i++) { - l[i] = r[i]; - } - } else { - l[0] = r[0]; - } -} - -void -ADDCOST(l, r) DeltaPtr l; DeltaPtr r; -{ - int i; - - if (lexical) { - for (i = 0; i < DELTAWIDTH; i++) { - l[i] += r[i]; - } - } else { - l[0] += r[0]; - } -} - -void -MINUSCOST(l, r) DeltaPtr l; DeltaPtr r; -{ - int i; - - if (lexical) { - for (i = 0; i < DELTAWIDTH; i++) { - l[i] -= r[i]; - } - } else { - l[0] -= r[0]; - } -} - -void -ZEROCOST(x) DeltaPtr x; -{ - int i; - - if (lexical) { - for (i = 0; i < DELTAWIDTH; i++) { - x[i] = 0; - } - } else { - x[0] = 0; - } -} - -int -LESSCOST(l, r) DeltaPtr l; DeltaPtr r; -{ - int i; - - if (lexical) { - for (i = 0; i < DELTAWIDTH; i++) { - if (l[i] < r[i]) { - return 1; - } else if (l[i] > r[i]) { - return 0; - } - } - return 0; - } else { - return l[0] < r[0]; - } -} - -int -EQUALCOST(l, r) DeltaPtr l; DeltaPtr r; -{ - int i; - - if (lexical) { - for (i = 0; i < DELTAWIDTH; i++) { - if (l[i] != r[i]) { - return 0; - } - } - return 1; - } else { - return l[0] == r[0]; - } -} -#endif /* NOLEX */ - -void -CHECKDIVERGE(c, its, nt, base) DeltaPtr c; Item_Set its; int nt; int base; -{ - int i; - - if (prevent_divergence <= 0) { - return; - } - if (lexical) { -#ifndef NOLEX - for (i = 0; i < DELTAWIDTH; i++) { - if (c[i] > prevent_divergence) { - char ntname[100]; - char basename[100]; - nonTerminalName(ntname, nt); - nonTerminalName(basename, base); - fprintf(stderr, "ERROR: The grammar appears to diverge\n"); - fprintf(stderr, "\tRelative Costs: %s(0), %s(%d)\n", basename, ntname, c[i]); - fprintf(stderr, "\tOffending Operator: %s\n", its->op->name); - fprintf(stderr, "\tOffending Tree: "); - printRepresentative(stderr, its); - fprintf(stderr, "\n"); - exit(1); - } - } -#endif /*NOLEX*/ - } else if (PRINCIPLECOST(c) > prevent_divergence) { - char ntname[100]; - char basename[100]; - nonTerminalName(ntname, nt); - nonTerminalName(basename, base); - fprintf(stderr, "ERROR: The grammar appears to diverge\n"); - fprintf(stderr, "\tRelative Costs: %s(0), %s(%d)\n", basename, ntname, PRINCIPLECOST(c)); - fprintf(stderr, "\tOffending Operator: %s\n", its->op->name); - fprintf(stderr, "\tOffending Tree: "); - printRepresentative(stderr, its); - fprintf(stderr, "\n"); - exit(1); - } -} diff --git a/support/tools/Burg/fe.c b/support/tools/Burg/fe.c deleted file mode 100644 index 36b373dd65..0000000000 --- a/support/tools/Burg/fe.c +++ /dev/null @@ -1,403 +0,0 @@ -char rcsid_fe[] = "$Id$"; - -#include <stdio.h> -#include <string.h> -#include "b.h" -#include "fe.h" - -int grammarflag; - -static int arity; - -List ruleASTs; -List grammarNts; - -static void doBinding ARGS((Binding)); -static void doDecl ARGS((Arity)); -static NonTerminal lookup ARGS((Pattern)); -static NonTerminal normalize ARGS((PatternAST, NonTerminal, Pattern *)); -static void doEnterNonTerm ARGS((RuleAST)); -static void doRule ARGS((RuleAST)); -static void doTable ARGS((Operator)); - -static void -doBinding(b) Binding b; -{ - int new; - Symbol s; - - s = enter(b->name, &new); - if (!new) { - fprintf(stderr, "Non-unique name: %s\n", b->name); - exit(1); - } - s->tag = OPERATOR; - s->u.op = newOperator(b->name, b->opnum, arity); - if (arity == 0) { - leaves = newList(s->u.op, leaves); - } -} - -static void -doDecl(a) Arity a; -{ - if (!a) { - return; - } - arity = a->arity; - foreachList((ListFn) doBinding, a->bindings); -} - - -static List xpatterns; -static int tcount; - -static NonTerminal -lookup(p) Pattern p; -{ - char buf[10]; - char *s; - List l; - NonTerminal n; - DeltaCost dummy; - - for (l = xpatterns; l; l = l->next) { - Pattern x = (Pattern) l->x; - if (x->op == p->op - && x->children[0] == p->children[0] - && x->children[1] == p->children[1]) { - return x->normalizer; - } - } - sprintf(buf, "n%%%d", tcount++); - s = (char *) zalloc(strlen(buf)+1); - strcpy(s, buf); - n = newNonTerminal(s); - p->normalizer = n; - xpatterns = newList(p, xpatterns); - ZEROCOST(dummy); - (void) newRule(dummy, 0, n, p); - return n; -} - -static NonTerminal -normalize(ast, nt, patt) PatternAST ast; NonTerminal nt; Pattern *patt; -{ - Symbol s; - int new; - Pattern dummy; - - s = enter(ast->op, &new); - ast->sym = s; - if (new) { - fprintf(stderr, "Illegal use of %s --- undefined symbol\n", s->name); - exit(1); - return 0; /* shut up compilers */ - } else if (s->tag == NONTERMINAL) { - if (ast->children) { - fprintf(stderr, "Illegal use of %s, a non-terminal, as a terminal\n", s->name); - exit(1); - } - *patt = newPattern(0); - (*patt)->children[0] = s->u.nt; - return s->u.nt; - } else { - s->u.op->ref = 1; - *patt = newPattern(s->u.op); - if (s->u.op->arity == -1) { - if (!ast->children) { - s->u.op->arity = 0; - leaves = newList(s->u.op, leaves); - } else if (!ast->children->next) { - s->u.op->arity = 1; - } else if (!ast->children->next->next) { - s->u.op->arity = 2; - } else { - fprintf(stderr, "ERROR: Too many children (max = 2) for \"%s\"\n", s->name); - exit(1); - } - if (s->u.op->arity > max_arity) { - max_arity = s->u.op->arity; - } - } - switch (s->u.op->arity) { - default: - assert(0); - break; - case 0: - if (ast->children) { - fprintf(stderr, "ERROR: Incorrect number of children for leaf operator, \"%s\"\n", s->name); - exit(1); - } - break; - case 1: - if (!ast->children || ast->children->next) { - fprintf(stderr, "ERROR: Incorrect number of children for unary operator, \"%s\"\n", s->name); - exit(1); - } - (*patt)->children[0] = normalize((PatternAST) ast->children->x, 0, &dummy); - break; - case 2: - if (!ast->children || !ast->children->next) { - fprintf(stderr, "ERROR: Incorrect number of children for binary operator, \"%s\"\n", s->name); - exit(1); - } - (*patt)->children[0] = normalize((PatternAST) ast->children->x, 0, &dummy); - (*patt)->children[1] = normalize((PatternAST) ast->children->next->x, 0, &dummy); - break; - } - if (nt) { - (*patt)->normalizer = nt; - return nt; - } else { - return lookup(*patt); - } - } -} - -static void -doEnterNonTerm(ast) RuleAST ast; -{ - int new; - Symbol s; - DeltaCost delta; - int i; - IntList p; - - - s = enter(ast->lhs, &new); - if (new) { - s->u.nt = newNonTerminal(s->name); - s->tag = NONTERMINAL; - } else { - if (s->tag != NONTERMINAL) { - fprintf(stderr, "Illegal use of %s as a non-terminal\n", s->name); - exit(1); - } - } - ZEROCOST(delta); - for (p = ast->cost, i = 0; p; p = p->next, i++) { - int x = p->x; -#ifndef NOLEX - if (lexical) { - if (i < DELTAWIDTH) { - delta[i] = x; - } - } else -#endif /* NOLEX */ - { - if (i == principleCost) { - PRINCIPLECOST(delta) = x; - } - } - } - ast->rule = newRule(delta, ast->erulenum, s->u.nt, 0); -} - -static void -doRule(ast) RuleAST ast; -{ - Pattern pat; - - (void) normalize(ast->pat, ast->rule->lhs, &pat); - ast->rule->pat = pat; -} - -static void -doTable(op) Operator op; -{ - op->table = newTable(op); -} - -void -doSpec(decls, rules) List decls; List rules; -{ - foreachList((ListFn) doDecl, decls); - debug(debugTables, foreachList((ListFn) dumpOperator_l, operators)); - - ruleASTs = rules; - reveachList((ListFn) doEnterNonTerm, rules); - - last_user_nonterminal = max_nonterminal; - - reveachList((ListFn) doRule, rules); - debug(debugTables, foreachList((ListFn) dumpRule, rules)); - - foreachList((ListFn) doTable, operators); -} - -void -doStart(name) char *name; -{ - Symbol s; - int new; - - if (start) { - yyerror1("Redeclaration of start symbol to be "); - fprintf(stderr, "\"%s\"\n", name); - exit(1); - } - s = enter(name, &new); - if (new) { - s->u.nt = newNonTerminal(s->name); - s->tag = NONTERMINAL; - } else { - if (s->tag != NONTERMINAL) { - fprintf(stderr, "Illegal use of %s as a non-terminal\n", s->name); - exit(1); - } - } -} - -void -doGrammarNts() -{ - List l; - int new; - - for (l = grammarNts; l; l = l->next) { - char *n = (char*) l->x; - Symbol s; - - s = enter(n, &new); - if (new) { - fprintf(stderr, "ERROR: %%gram, unused non-terminal: \"%s\"\n", n); - exit(1); - } - if (s->tag != NONTERMINAL) { - fprintf(stderr, "ERROR: %%gram, Not a non-terminal: \"%s\"\n", n); - exit(1); - } - l->x = s; - } -} - -void -doGram(nts) List nts; -{ - if (grammarNts) { - yyerror1("Redeclaration of %%gram\n"); - exit(1); - } - grammarNts = nts; -} - -Arity -newArity(ar, b) int ar; List b; -{ - Arity a = (Arity) zalloc(sizeof(struct arity)); - a->arity = ar; - a->bindings = b; - return a; -} - -Binding -newBinding(name, opnum) char *name; int opnum; -{ - Binding b = (Binding) zalloc(sizeof(struct binding)); - if (opnum == 0) { - yyerror1("ERROR: Non-positive external symbol number, "); - fprintf(stderr, "%d", opnum); - exit(1); - } - b->name = name; - b->opnum = opnum; - return b; -} - -PatternAST -newPatternAST(op, children) char *op; List children; -{ - PatternAST p = (PatternAST) zalloc(sizeof(struct patternAST)); - p->op = op; - p->children = children; - return p; -} - -int max_ruleAST; - -RuleAST -newRuleAST(lhs, pat, erulenum, cost) char *lhs; PatternAST pat; int erulenum; IntList cost; -{ - RuleAST p = (RuleAST) zalloc(sizeof(struct ruleAST)); - p->lhs = lhs; - p->pat = pat; - if (erulenum <= 0) { - yyerror1("External Rulenumber "); - fprintf(stderr, "(%d) <= 0\n", erulenum); - exit(1); - } - p->erulenum = erulenum; - p->cost = cost; - max_ruleAST++; - return p; -} - -void -dumpBinding(b) Binding b; -{ - printf("%s=%d ", b->name, b->opnum); -} - -void -dumpArity(a) Arity a; -{ - List l; - - printf("Arity(%d) ", a->arity); - for (l = a->bindings; l; l = l->next) { - Binding b = (Binding) l->x; - dumpBinding(b); - } - printf("\n"); -} - -void -dumpPatternAST(p) PatternAST p; -{ - List l; - - printf("%s", p->op); - if (p->children) { - printf("("); - for (l = p->children; l; l = l->next) { - PatternAST past = (PatternAST) l->x; - dumpPatternAST(past); - if (l->next) { - printf(", "); - } - } - printf(")"); - } -} - -void -dumpRuleAST(p) RuleAST p; -{ - printf("%s : ", p->lhs); - dumpPatternAST(p->pat); - printf(" = %d (%ld)\n", p->erulenum, (long) p->cost); -} - -void -dumpDecls(decls) List decls; -{ - List l; - - for (l = decls; l; l = l->next) { - Arity a = (Arity) l->x; - dumpArity(a); - } -} - -void -dumpRules(rules) List rules; -{ - List l; - - for (l = rules; l; l = l->next) { - RuleAST p = (RuleAST) l->x; - dumpRuleAST(p); - } -} - diff --git a/support/tools/Burg/fe.h b/support/tools/Burg/fe.h deleted file mode 100644 index 1c7b2fecbf..0000000000 --- a/support/tools/Burg/fe.h +++ /dev/null @@ -1,132 +0,0 @@ -/* $Id$ */ - -struct binding { - char *name; - int opnum; -}; -typedef struct binding *Binding; - -struct arity { - int arity; - List bindings; -}; -typedef struct arity *Arity; - -struct patternAST { - struct symbol *sym; - char *op; - List children; -}; -typedef struct patternAST *PatternAST; - -struct ruleAST { - char *lhs; - PatternAST pat; - int erulenum; - IntList cost; - struct rule *rule; - struct strTableElement *kids; - struct strTableElement *nts; -}; -typedef struct ruleAST *RuleAST; - -typedef enum { - UNKNOWN, - OPERATOR, - NONTERMINAL -} TagType; - -struct symbol { - char *name; - TagType tag; - union { - NonTerminal nt; - Operator op; - } u; -}; -typedef struct symbol *Symbol; - -struct strTableElement { - char *str; - IntList erulenos; - char *ename; -}; -typedef struct strTableElement *StrTableElement; - -struct strTable { - List elems; -}; -typedef struct strTable *StrTable; - -extern void doGrammarNts ARGS((void)); -void makeRuleDescArray ARGS((void)); -void makeDeltaCostArray ARGS((void)); -void makeStateStringArray ARGS((void)); - -extern StrTable newStrTable ARGS((void)); -extern StrTableElement addString ARGS((StrTable, char *, int, int *)); - -extern void doSpec ARGS((List, List)); -extern Arity newArity ARGS((int, List)); -extern Binding newBinding ARGS((char *, int)); -extern PatternAST newPatternAST ARGS((char *, List)); -extern RuleAST newRuleAST ARGS((char *, PatternAST, int, IntList)); -extern Symbol enter ARGS((char *, int *)); -extern Symbol newSymbol ARGS((char *)); - -extern void makeDebug ARGS((void)); -extern void makeSimple ARGS((void)); -extern void makePlanks ARGS((void)); -extern void makeOpLabel ARGS((void)); -extern void makeChild ARGS((void)); -extern void makeOperators ARGS((void)); -extern void makeLabel ARGS((void)); -extern void makeString ARGS((void)); -extern void makeString ARGS((void)); -extern void makeReduce ARGS((void)); -extern void makeRuleTable ARGS((void)); -extern void makeTables ARGS((void)); -extern void makeTreecost ARGS((void)); -extern void makePrint ARGS((void)); -extern void makeRule ARGS((void)); -extern void makeNts ARGS((void)); -extern void makeKids ARGS((void)); -extern void startBurm ARGS((void)); -extern void startOptional ARGS((void)); -extern void makePlankLabel ARGS((void)); -extern void makeStateLabel ARGS((void)); -extern void makeStringArray ARGS((void)); -extern void makeNonterminalArray ARGS((void)); -extern void makeCostArray ARGS((void)); -extern void makeLHSmap ARGS((void)); -extern void makeClosureArray ARGS((void)); -extern void makeOperatorVector ARGS((void)); -extern void endOptional ARGS((void)); -extern void reportDiagnostics ARGS((void)); -extern void makeNonterminals ARGS((void)); -extern int opsOfArity ARGS((int)); - -extern void yypurge ARGS((void)); -extern void yyfinished ARGS((void)); - -extern void printRepresentative ARGS((FILE *, Item_Set)); - -extern void dumpRules ARGS((List)); -extern void dumpDecls ARGS((List)); -extern void dumpRuleAST ARGS((RuleAST)); -extern void dumpPatternAST ARGS((PatternAST)); -extern void dumpArity ARGS((Arity)); -extern void dumpBinding ARGS((Binding)); -extern void dumpStrTable ARGS((StrTable)); - -extern int yylex ARGS((void)); -extern int yyparse ARGS((void)); - -extern int max_ruleAST; -extern List ruleASTs; - -extern FILE *outfile; -extern const char *prefix; -extern int trimflag; -extern int speedflag; -extern int grammarflag; diff --git a/support/tools/Burg/gram.yc b/support/tools/Burg/gram.yc deleted file mode 100644 index 9d2f9f4e53..0000000000 --- a/support/tools/Burg/gram.yc +++ /dev/null @@ -1,91 +0,0 @@ -%{ -char rcsid_gram[] = "$Id$"; - -#include <stdio.h> -#include "b.h" -#include "fe.h" -int doGram(List); -%} - -%union { - int y_int; - char *y_string; - Arity y_arity; - Binding y_binding; - PatternAST y_patternAST; - RuleAST y_ruleAST; - List y_list; - IntList y_intlist; -} - -%start full - -%term ERROR -%term K_TERM -%term K_GRAM -%term K_START -%term K_PPERCENT -%term INT -%term ID - -%token <y_string> ID -%token <y_int> INT - -%type <y_arity> decl -%type <y_binding> binding -%type <y_intlist> cost costtail -%type <y_ruleAST> rule -%type <y_patternAST> pattern -%type <y_list> decls rules bindinglist grammarlist -%% - - -full : spec - | spec K_PPERCENT - { yyfinished(); } - ; - -spec : decls K_PPERCENT rules - { doSpec($1, $3); } - ; - -decls : /* lambda */ { $$ = 0; } - | decls decl { $$ = newList($2, $1); } - ; - -decl : K_TERM bindinglist { $$ = newArity(-1, $2); } - | K_GRAM grammarlist { $$ = 0; doGram($2); } - | K_START ID { $$ = 0; doStart($2); } /* kludge */ - ; - -grammarlist : /* lambda */ { $$ = 0; } - | grammarlist ID { $$ = newList($2, $1); } - ; - -bindinglist : /* lambda */ { $$ = 0; } - | bindinglist binding { $$ = newList($2, $1); } - ; - -binding : ID '=' INT { $$ = newBinding($1, $3); } - ; - -rules : /* lambda */ { $$ = 0; } - | rules rule { $$ = newList($2, $1); } - ; - -rule : ID ':' pattern '=' INT cost ';' { $$ = newRuleAST($1, $3, $5, $6); } - ; - -pattern : ID { $$ = newPatternAST($1, 0); } - | ID '(' pattern ')' { $$ = newPatternAST($1, newList($3,0)); } - | ID '(' pattern ',' pattern ')' { $$ = newPatternAST($1, newList($3, newList($5, 0))); } - ; - -cost : /* lambda */ { $$ = 0; } - | '(' INT costtail ')' { $$ = newIntList($2, $3); } - ; - -costtail : /* lambda */ { $$ = 0; } - | ',' INT costtail { $$ = newIntList($2, $3); } - | INT costtail { $$ = newIntList($1, $2); } - ; diff --git a/support/tools/Burg/item.c b/support/tools/Burg/item.c deleted file mode 100644 index 4a9f4a320b..0000000000 --- a/support/tools/Burg/item.c +++ /dev/null @@ -1,133 +0,0 @@ -char rcsid_item[] = "$Id$"; - -#include "b.h" -#include <stdio.h> -#include <string.h> -#include "fe.h" - -static Item_Set fptr; - -ItemArray -newItemArray() -{ - ItemArray ia; - ia = (ItemArray) zalloc(max_nonterminal *sizeof(*ia)); - return ia; -} - -ItemArray -itemArrayCopy(src) ItemArray src; -{ - ItemArray dst; - - dst = newItemArray(); - memcpy(dst, src, max_nonterminal * sizeof(*dst)); - return dst; -} - -Item_Set -newItem_Set(relevant) Relevant relevant; -{ - Item_Set ts; - - if (fptr) { - ts = fptr; - fptr = 0; - memset(ts->virgin, 0, max_nonterminal * sizeof(struct item)); - if (ts->closed) { - zfree(ts->closed); - ts->closed = 0; - } - ts->num = 0; - ts->op = 0; - } else { - ts = (Item_Set) zalloc(sizeof(struct item_set)); - ts->virgin = newItemArray(); - } - ts->relevant = relevant; - return ts; -} - -void -freeItem_Set(ts) Item_Set ts; -{ - assert(!fptr); - fptr = ts; -} - -int -equivSet(a, b) Item_Set a; Item_Set b; -{ - register Relevant r; - register int nt; - register Item *aa = a->virgin; - register Item *ba = b->virgin; - - /* - return !bcmp(a->virgin, b->virgin, max_nonterminal * sizeof(Item)); - */ - - r = a->relevant ? a->relevant : b->relevant; - assert(r); - - if (a->op && b->op && a->op != b->op) { - return 0; - } - for (; (nt = *r) != 0; r++) { - if (aa[nt].rule != ba[nt].rule || !EQUALCOST(aa[nt].delta, ba[nt].delta)) { - return 0; - } - } - return 1; -} - -void -printRepresentative(f, s) FILE *f; Item_Set s; -{ - if (!s) { - return; - } - fprintf(f, "%s", s->op->name); - switch (s->op->arity) { - case 1: - fprintf(f, "("); - printRepresentative(f, s->kids[0]); - fprintf(f, ")"); - break; - case 2: - fprintf(f, "("); - printRepresentative(f, s->kids[0]); - fprintf(f, ", "); - printRepresentative(f, s->kids[1]); - fprintf(f, ")"); - break; - } -} - -void -dumpItem(t) Item *t; -{ - printf("[%s #%d]", t->rule->lhs->name, t->rule->num); - dumpCost(t->delta); -} - -void -dumpItem_Set(ts) Item_Set ts; -{ - int i; - - printf("Item_Set #%d: [", ts->num); - for (i = 1; i < max_nonterminal; i++) { - if (ts->virgin[i].rule) { - printf(" %d", i); - dumpCost(ts->virgin[i].delta); - } - } - printf(" ]\n"); -} - -void -dumpCost(dc) DeltaCost dc; -{ - printf("(%ld)", (long) dc); -} diff --git a/support/tools/Burg/lex.c b/support/tools/Burg/lex.c deleted file mode 100644 index 85eb8a738f..0000000000 --- a/support/tools/Burg/lex.c +++ /dev/null @@ -1,259 +0,0 @@ -char rcsid_lex[] = "$Id$"; - -#include <ctype.h> -#include <stdio.h> -#include <string.h> -#include "b.h" -#include "fe.h" -#include "gram.tab.h" - -static char buf[BUFSIZ]; - -static int yyline = 1; - -typedef int (*ReadFn) ARGS((void)); - -static char *StrCopy ARGS((char *)); -static int code_get ARGS((void)); -static int simple_get ARGS((void)); -static void ReadCharString ARGS((ReadFn, int)); -static void ReadCodeBlock ARGS((void)); -static void ReadOldComment ARGS((ReadFn)); - -static char * -StrCopy(s) char *s; -{ - char *t = (char *)zalloc(strlen(s) + 1); - strcpy(t,s); - return t; -} - -static int -simple_get() -{ - int ch; - if ((ch = getchar()) == '\n') { - yyline++; - } - return ch; -} - -static int -code_get() -{ - int ch; - if ((ch = getchar()) == '\n') { - yyline++; - } - if (ch != EOF) { - fputc(ch, outfile); - } - return ch; -} - -void -yypurge() -{ - while (code_get() != EOF) ; -} - - -static void -ReadCharString(rdfn, which) ReadFn rdfn; int which; -{ - int ch; - int backslash = 0; - int firstline = yyline; - - while ((ch = rdfn()) != EOF) { - if (ch == which && !backslash) { - return; - } - if (ch == '\\' && !backslash) { - backslash = 1; - } else { - backslash = 0; - } - } - yyerror1("Unexpected EOF in string on line "); - fprintf(stderr, "%d\n", firstline); - exit(1); -} - -static void -ReadOldComment(rdfn) ReadFn rdfn; -{ - /* will not work for comments delimiter in string */ - - int ch; - int starred = 0; - int firstline = yyline; - - while ((ch = rdfn()) != EOF) { - if (ch == '*') { - starred = 1; - } else if (ch == '/' && starred) { - return; - } else { - starred = 0; - } - } - yyerror1("Unexpected EOF in comment on line "); - fprintf(stderr, "%d\n", firstline); - exit(1); -} - -static void -ReadCodeBlock() -{ - int ch; - int firstline = yyline; - - while ((ch = getchar()) != EOF) { - if (ch == '%') { - ch = getchar(); - if (ch != '}') { - yyerror("bad %%"); - } - return; - } - fputc(ch, outfile); - if (ch == '\n') { - yyline++; - } - if (ch == '"' || ch == '\'') { - ReadCharString(code_get, ch); - } else if (ch == '/') { - ch = getchar(); - if (ch == '*') { - fputc(ch, outfile); - ReadOldComment(code_get); - continue; - } else { - ungetc(ch, stdin); - } - } - } - yyerror1("Unclosed block of C code started on line "); - fprintf(stderr, "%d\n", firstline); - exit(1); -} - -static int done; -void -yyfinished() -{ - done = 1; -} - -int -yylex() -{ - int ch; - char *ptr = buf; - - if (done) return 0; - while ((ch = getchar()) != EOF) { - switch (ch) { - case ' ': - case '\f': - case '\t': - continue; - case '\n': - yyline++; - continue; - case '(': - case ')': - case ',': - case ':': - case ';': - case '=': - return(ch); - case '/': - ch = getchar(); - if (ch == '*') { - ReadOldComment(simple_get); - continue; - } else { - ungetc(ch, stdin); - yyerror("illegal char /"); - continue; - } - case '%': - ch = getchar(); - switch (ch) { - case '%': - return (K_PPERCENT); - case '{': - ReadCodeBlock(); - continue; - case 's': - case 'g': - case 't': - do { - if (ptr >= &buf[BUFSIZ]) { - yyerror("ID too long"); - return(ERROR); - } else { - *ptr++ = ch; - } - ch = getchar(); - } while (isalpha(ch) || isdigit(ch) || ch == '_'); - ungetc(ch, stdin); - *ptr = '\0'; - if (!strcmp(buf, "term")) return K_TERM; - if (!strcmp(buf, "start")) return K_START; - if (!strcmp(buf, "gram")) return K_GRAM; - yyerror("illegal character after %%"); - continue; - default: - yyerror("illegal character after %%"); - continue; - } - default: - if (isalpha(ch) ) { - do { - if (ptr >= &buf[BUFSIZ]) { - yyerror("ID too long"); - return(ERROR); - } else { - *ptr++ = ch; - } - ch = getchar(); - } while (isalpha(ch) || isdigit(ch) || ch == '_'); - ungetc(ch, stdin); - *ptr = '\0'; - yylval.y_string = StrCopy(buf); - return(ID); - } - if (isdigit(ch)) { - int val=0; - do { - val *= 10; - val += (ch - '0'); - ch = getchar(); - } while (isdigit(ch)); - ungetc(ch, stdin); - yylval.y_int = val; - return(INT); - } - yyerror1("illegal char "); - fprintf(stderr, "(\\%03o)\n", ch); - exit(1); - } - } - return(0); -} - -void yyerror1(const char *str) -{ - fprintf(stderr, "line %d: %s", yyline, str); -} - -void -yyerror(const char *str) -{ - yyerror1(str); - fprintf(stderr, "\n"); - exit(1); -} diff --git a/support/tools/Burg/list.c b/support/tools/Burg/list.c deleted file mode 100644 index d3eefa27d0..0000000000 --- a/support/tools/Burg/list.c +++ /dev/null @@ -1,75 +0,0 @@ -char rcsid_list[] = "$Id$"; - -#include "b.h" - -IntList -newIntList(x, next) int x; IntList next; -{ - IntList l; - - l = (IntList) zalloc(sizeof(*l)); - assert(l); - l->x = x; - l->next = next; - - return l; -} - -List -newList(x, next) void *x; List next; -{ - List l; - - l = (List) zalloc(sizeof(*l)); - assert(l); - l->x = x; - l->next = next; - - return l; -} - -List -appendList(x, l) void *x; List l; -{ - List last; - List p; - - last = 0; - for (p = l; p; p = p->next) { - last = p; - } - if (last) { - last->next = newList(x, 0); - return l; - } else { - return newList(x, 0); - } -} - -void -foreachList(f, l) ListFn f; List l; -{ - for (; l; l = l->next) { - (*f)(l->x); - } -} - -void -reveachList(f, l) ListFn f; List l; -{ - if (l) { - reveachList(f, l->next); - (*f)(l->x); - } -} - -int -length(l) List l; -{ - int c = 0; - - for(; l; l = l->next) { - c++; - } - return c; -} diff --git a/support/tools/Burg/main.c b/support/tools/Burg/main.c deleted file mode 100644 index dbfdbf4fac..0000000000 --- a/support/tools/Burg/main.c +++ /dev/null @@ -1,182 +0,0 @@ -char rcsid_main[] = "$Id$"; - -#include <math.h> -#include <stdio.h> -#include "b.h" -#include "fe.h" - -int debugTables = 0; -static int simpleTables = 0; -static int internals = 0; -static int diagnostics = 0; - -static char *inFileName; -static char *outFileName; - -static char version[] = "BURG, Version 1.0"; - -extern int main ARGS((int argc, char **argv)); - -int -main(argc, argv) int argc; char **argv; -{ - int i; - extern int atoi ARGS((char *)); - - for (i = 1; argv[i]; i++) { - char **needStr = 0; - int *needInt = 0; - - if (argv[i][0] == '-') { - switch (argv[i][1]) { - case 'V': - fprintf(stderr, "%s\n", version); - break; - case 'p': - needStr = (char**)&prefix; - break; - case 'o': - needStr = &outFileName; - break; - case 'I': - internals = 1; - break; - case 'T': - simpleTables = 1; - break; - case '=': -#ifdef NOLEX - fprintf(stderr, "'%s' was not compiled to support lexicographic ordering\n", argv[0]); -#else - lexical = 1; -#endif /* NOLEX */ - break; - case 'O': - needInt = &principleCost; - break; - case 'c': - needInt = &prevent_divergence; - break; - case 'e': - needInt = &exceptionTolerance; - break; - case 'd': - diagnostics = 1; - break; - case 'S': - speedflag = 1; - break; - case 't': - trimflag = 1; - break; - case 'G': - grammarflag = 1; - break; - default: - fprintf(stderr, "Bad option (%s)\n", argv[i]); - exit(1); - } - } else { - if (inFileName) { - fprintf(stderr, "Unexpected Filename (%s) after (%s)\n", argv[i], inFileName); - exit(1); - } - inFileName = argv[i]; - } - if (needInt || needStr) { - char *v; - char *opt = argv[i]; - - if (argv[i][2]) { - v = &argv[i][2]; - } else { - v = argv[++i]; - if (!v) { - fprintf(stderr, "Expection argument after %s\n", opt); - exit(1); - } - } - if (needInt) { - *needInt = atoi(v); - } else if (needStr) { - *needStr = v; - } - } - } - - if (inFileName) { - if(freopen(inFileName, "r", stdin)==NULL) { - fprintf(stderr, "Failed opening (%s)", inFileName); - exit(1); - } - } - - if (outFileName) { - if ((outfile = fopen(outFileName, "w")) == NULL) { - fprintf(stderr, "Failed opening (%s)", outFileName); - exit(1); - } - } else { - outfile = stdout; - } - - - yyparse(); - - if (!rules) { - fprintf(stderr, "ERROR: No rules present\n"); - exit(1); - } - - findChainRules(); - findAllPairs(); - doGrammarNts(); - build(); - - debug(debugTables, foreachList((ListFn) dumpOperator_l, operators)); - debug(debugTables, printf("---final set of states ---\n")); - debug(debugTables, dumpMapping(globalMap)); - - - startBurm(); - makeNts(); - if (simpleTables) { - makeSimple(); - } else { - makePlanks(); - } - - startOptional(); - makeLabel(); - makeKids(); - - if (internals) { - makeChild(); - makeOpLabel(); - makeStateLabel(); - } - endOptional(); - - makeOperatorVector(); - makeNonterminals(); - if (internals) { - makeOperators(); - makeStringArray(); - makeRuleDescArray(); - makeCostArray(); - makeDeltaCostArray(); - makeStateStringArray(); - makeNonterminalArray(); - /* - makeLHSmap(); - */ - } - makeClosureArray(); - - if (diagnostics) { - reportDiagnostics(); - } - - yypurge(); - exit(0); -} diff --git a/support/tools/Burg/map.c b/support/tools/Burg/map.c deleted file mode 100644 index 588b485eab..0000000000 --- a/support/tools/Burg/map.c +++ /dev/null @@ -1,135 +0,0 @@ -char rcsid_map[] = "$Id$"; - -#include <stdio.h> -#include <string.h> -#include "b.h" -#include "fe.h" - -Mapping globalMap; - -static void growMapping ARGS((Mapping)); -static int hash ARGS((Item_Set, int)); - -Mapping -newMapping(size) int size; -{ - Mapping m; - - m = (Mapping) zalloc(sizeof(struct mapping)); - assert(m); - - m->count = 0; - m->hash = (List*) zalloc(size * sizeof(List)); - m->hash_size = size; - m->max_size = STATES_INCR; - m->set = (Item_Set*) zalloc(m->max_size * sizeof(Item_Set)); - assert(m->set); - - return m; -} - -static void -growMapping(m) Mapping m; -{ - Item_Set *tmp; - - m->max_size += STATES_INCR; - tmp = (Item_Set*) zalloc(m->max_size * sizeof(Item_Set)); - memcpy(tmp, m->set, m->count * sizeof(Item_Set)); - zfree(m->set); - m->set = tmp; -} - -static int -hash(ts, mod) Item_Set ts; int mod; -{ - register Item *p = ts->virgin; - register int v; - register Relevant r = ts->relevant; - register int nt; - - if (!ts->op) { - return 0; - } - - v = 0; - for (; (nt = *r) != 0; r++) { - v ^= ((long)p[nt].rule) + (PRINCIPLECOST(p[nt].delta)<<4); - } - v >>= 4; - v &= (mod-1); - return v; -} - -Item_Set -encode(m, ts, new) Mapping m; Item_Set ts; int *new; -{ - int h; - List l; - - assert(m); - assert(ts); - assert(m->count <= m->max_size); - - if (grammarNts && errorState && m == globalMap) { - List l; - int found; - - found = 0; - for (l = grammarNts; l; l = l->next) { - Symbol s; - s = (Symbol) l->x; - - if (ts->virgin[s->u.nt->num].rule) { - found = 1; - break; - } - } - if (!found) { - *new = 0; - return errorState; - } - } - - *new = 0; - h = hash(ts, m->hash_size); - for (l = m->hash[h]; l; l = l->next) { - Item_Set s = (Item_Set) l->x; - if (ts->op == s->op && equivSet(ts, s)) { - ts->num = s->num; - return s; - } - } - if (m->count >= m->max_size) { - growMapping(m); - } - assert(m->count < m->max_size); - m->set[m->count] = ts; - ts->num = m->count++; - *new = 1; - m->hash[h] = newList(ts, m->hash[h]); - return ts; -} - -Item_Set -decode(m, t) Mapping m; ItemSetNum t; -{ - assert(m); - assert(t); - assert(m->count < m->max_size); - assert(t < m->count); - - return m->set[t]; -} - -void -dumpMapping(m) Mapping m; -{ - int i; - - printf("BEGIN Mapping: Size=%d\n", m->count); - for (i = 0; i < m->count; i++) { - dumpItem_Set(m->set[i]); - } - printf("END Mapping\n"); -} diff --git a/support/tools/Burg/nonterminal.c b/support/tools/Burg/nonterminal.c deleted file mode 100644 index 71fd7d4944..0000000000 --- a/support/tools/Burg/nonterminal.c +++ /dev/null @@ -1,49 +0,0 @@ -char rcsid_nonterminal[] = "$Id$"; - -#include "b.h" -#include <stdio.h> -#include <string.h> - -NonTerminal start; -NonTerminalNum max_nonterminal = 1; -NonTerminalNum last_user_nonterminal; -List nonterminals; - -NonTerminal -newNonTerminal(name) char *name; -{ - NonTerminal nt; - - nt = (NonTerminal) zalloc(sizeof(struct nonterminal)); - assert(nt); - if (max_nonterminal == 1) { - start = nt; - } - nt->name = name; - nt->num = max_nonterminal++; - nonterminals = newList(nt, nonterminals); - - return nt; -} - -int -nonTerminalName(buf, i) char *buf; int i; -{ - List l; - - for (l = nonterminals; l; l = l->next) { - NonTerminal nt = (NonTerminal) l->x; - if (nt->num == i) { - strcpy(buf, nt->name); - return 1; - } - } - strcpy(buf, "(Unknown NonTerminal)"); - return 0; -} - -void -dumpNonTerminal(n) NonTerminal n; -{ - printf("%s(%d)", n->name, n->num); -} diff --git a/support/tools/Burg/operator.c b/support/tools/Burg/operator.c deleted file mode 100644 index a6df9e304d..0000000000 --- a/support/tools/Burg/operator.c +++ /dev/null @@ -1,48 +0,0 @@ -char rcsid_operator[] = "$Id$"; - -#include "b.h" -#include <stdio.h> - -int max_arity = -1; - -List operators; -List leaves; - -Operator -newOperator(name, num, arity) char *name; OperatorNum num; ArityNum arity; -{ - Operator op; - - assert(arity <= MAX_ARITY); - op = (Operator) zalloc(sizeof(struct operator)); - assert(op); - op->name = name; - op->num = num; - op->arity = arity; - - operators = newList(op, operators); - - return op; -} - -void -dumpOperator_s(op) Operator op; -{ - printf("Op: %s(%d)=%d\n", op->name, op->arity, op->num); -} - -void -dumpOperator(op, full) Operator op; int full; -{ - dumpOperator_s(op); - if (full) { - dumpTable(op->table, 0); - } -} - -void -dumpOperator_l(op) Operator op; -{ - dumpOperator(op, 1); -} - diff --git a/support/tools/Burg/pattern.c b/support/tools/Burg/pattern.c deleted file mode 100644 index 472aca579d..0000000000 --- a/support/tools/Burg/pattern.c +++ /dev/null @@ -1,38 +0,0 @@ -char rcsid_pattern[] = "$Id$"; - -#include <stdio.h> -#include "b.h" - -Pattern -newPattern(op) Operator op; -{ - Pattern p; - - p = (Pattern) zalloc(sizeof(struct pattern)); - p->op = op; - return p; -} - -void -dumpPattern(p) Pattern p; -{ - int i; - - if (!p) { - printf("[no-pattern]"); - return; - } - - if (p->op) { - printf("%s", p->op->name); - if (p->op->arity > 0) { - printf("("); - for (i = 0; i < p->op->arity; i++) { - printf("%s ", p->children[i]->name); - } - printf(")"); - } - } else { - printf("%s", p->children[0]->name); - } -} diff --git a/support/tools/Burg/plank.c b/support/tools/Burg/plank.c deleted file mode 100644 index 1ce006dd01..0000000000 --- a/support/tools/Burg/plank.c +++ /dev/null @@ -1,921 +0,0 @@ -char rcsid_plank[] = "$Id$"; - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include "b.h" -#include "fe.h" - -#define ERROR_VAL 0 - -int speedflag = 0; - -Item_Set *sortedStates; -static struct stateMapTable smt; -int exceptionTolerance = 0; -static int plankSize = 32; - -static Plank newPlank ARGS((void)); -static PlankMap newPlankMap ARGS((int)); -static StateMap newStateMap ARGS((void)); -static Exception newException ARGS((int, int)); -static void enterStateMap ARGS((PlankMap, short *, int, int *)); -static List assemblePlanks ARGS((void)); -static void assignRules ARGS((RuleAST)); -static int stateCompare ARGS((Item_Set *, Item_Set *)); -static int ruleCompare ARGS((RuleAST *, RuleAST *)); -static void renumber ARGS((void)); -static short * newVector ARGS((void)); -static int width ARGS((int)); -static PlankMap mapToPmap ARGS((Dimension)); -static void doDimPmaps ARGS((Operator)); -static void doNonTermPmaps ARGS((NonTerminal)); -static void makePmaps ARGS((void)); -static void outPlank ARGS((Plank)); -static void purgePlanks ARGS((List)); -static void inToEx ARGS((void)); -static void makePlankRuleMacros ARGS((void)); -static void makePlankRule ARGS((void)); -static void exceptionSwitch ARGS((List, const char *, const char *, const char *, int, const char *)); -static void doPlankLabel ARGS((Operator)); -static void doPlankLabelSafely ARGS((Operator)); -static void doPlankLabelMacrosSafely ARGS((Operator)); -static void makePlankState ARGS((void)); - -static Plank -newPlank() -{ - Plank p; - char buf[50]; - static int num = 0; - - p = (Plank) zalloc(sizeof(struct plank)); - sprintf(buf, "%s_plank_%d", prefix, num++); - p->name = (char *) zalloc(strlen(buf)+1); - strcpy(p->name, buf); - return p; -} - -static PlankMap -newPlankMap(offset) int offset; -{ - PlankMap im; - - im = (PlankMap) zalloc(sizeof(struct plankMap)); - im->offset = offset; - return im; -} - -static StateMap -newStateMap() -{ - char buf[50]; - static int num = 0; - - StateMap sm; - - sm = (StateMap) zalloc(sizeof(struct stateMap)); - sprintf(buf, "f%d", num++); - sm->fieldname = (char *) zalloc(strlen(buf)+1); - strcpy(sm->fieldname, buf); - return sm; -} - -static Exception -newException(index, value) int index; int value; -{ - Exception e; - - e = (Exception) zalloc(sizeof(struct except)); - e->index = index; - e->value = value; - return e; -} - -static void -enterStateMap(im, v, width, new) PlankMap im; short * v; int width; int *new; -{ - int i; - StateMap sm; - List l; - int size; - - assert(im); - assert(v); - assert(width > 0); - size = globalMap->count; - - for (l = smt.maps; l; l = l->next) { - int ecount; - - sm = (StateMap) l->x; - ecount = 0; - for (i = 0; i < size; i++) { - if (v[i] != -1 && sm->value[i] != -1 && v[i] != sm->value[i]) { - if (++ecount > exceptionTolerance) { - goto again; - } - } - } - for (i = 0; i < size; i++) { - assert(v[i] >= 0); - assert(sm->value[i] >= 0); - if (v[i] == -1) { - continue; - } - if (sm->value[i] == -1) { - sm->value[i] = v[i]; - } else if (v[i] != sm->value[i]) { - im->exceptions = newList(newException(i,v[i]), im->exceptions); - } - } - im->values = sm; - if (width > sm->width) { - sm->width = width; - } - *new = 0; - return; - again: ; - } - sm = newStateMap(); - im->values = sm; - sm->value = v; - sm->width = width; - *new = 1; - smt.maps = newList(sm, smt.maps); -} - -static List -assemblePlanks() -{ - List planks = 0; - Plank pl; - List p; - List s; - - for (s = smt.maps; s; s = s->next) { - StateMap sm = (StateMap) s->x; - for (p = planks; p; p = p->next) { - pl = (Plank) p->x; - if (sm->width <= plankSize - pl->width) { - pl->width += sm->width; - pl->fields = newList(sm, pl->fields); - sm->plank = pl; - goto next; - } - } - pl = newPlank(); - pl->width = sm->width; - pl->fields = newList(sm, 0); - sm->plank = pl; - planks = appendList(pl, planks); - next: ; - } - return planks; -} - -RuleAST *sortedRules; - -static int count; - -static void -assignRules(ast) RuleAST ast; -{ - sortedRules[count++] = ast; -} - -static int -stateCompare(s, t) Item_Set *s; Item_Set *t; -{ - return strcmp((*s)->op->name, (*t)->op->name); -} - -static int -ruleCompare(s, t) RuleAST *s; RuleAST *t; -{ - return strcmp((*s)->lhs, (*t)->lhs); -} - -void -dumpSortedStates() -{ - int i; - - printf("dump Sorted States: "); - for (i = 0; i < globalMap->count; i++) { - printf("%d ", sortedStates[i]->num); - } - printf("\n"); -} - -void -dumpSortedRules() -{ - int i; - - printf("dump Sorted Rules: "); - for (i = 0; i < max_ruleAST; i++) { - printf("%d ", sortedRules[i]->rule->erulenum); - } - printf("\n"); -} - -static void -renumber() -{ - int i; - Operator previousOp; - NonTerminal previousLHS; - int base_counter; - - sortedStates = (Item_Set*) zalloc(globalMap->count * sizeof(Item_Set)); - for (i = 1; i < globalMap->count; i++) { - sortedStates[i-1] = globalMap->set[i]; - } - qsort(sortedStates, globalMap->count-1, sizeof(Item_Set), (int(*)(const void *, const void *))stateCompare); - previousOp = 0; - for (i = 0; i < globalMap->count-1; i++) { - sortedStates[i]->newNum = i; - sortedStates[i]->op->stateCount++; - if (previousOp != sortedStates[i]->op) { - sortedStates[i]->op->baseNum = i; - previousOp = sortedStates[i]->op; - } - } - - sortedRules = (RuleAST*) zalloc(max_ruleAST * sizeof(RuleAST)); - count = 0; - foreachList((ListFn) assignRules, ruleASTs); - qsort(sortedRules, max_ruleAST, sizeof(RuleAST), (int(*)(const void *, const void *))ruleCompare); - previousLHS = 0; - base_counter = 0; - for (i = 0; i < max_ruleAST; i++) { - if (previousLHS != sortedRules[i]->rule->lhs) { - sortedRules[i]->rule->lhs->baseNum = base_counter; - previousLHS = sortedRules[i]->rule->lhs; - base_counter++; /* make space for 0 */ - } - sortedRules[i]->rule->newNum = base_counter; - sortedRules[i]->rule->lhs->ruleCount++; - sortedRules[i]->rule->lhs->sampleRule = sortedRules[i]->rule; /* kludge for diagnostics */ - base_counter++; - } -} - -static short * -newVector() -{ - short *p; - p = (short *) zalloc(globalMap->count* sizeof(short)); - return p; -} - -static int -width(v) int v; -{ - int c; - - for (c = 0; v; v >>= 1) { - c++; - } - return c; - -} - -static PlankMap -mapToPmap(d) Dimension d; -{ - PlankMap im; - short *v; - int i; - int new; - - if (d->map->count == 1) { - return 0; - } - assert(d->map->count > 1); - im = newPlankMap(0); - v = newVector(); - for (i = 0; i < globalMap->count-1; i++) { - int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num; - assert(index >= 0); - v[i+1] = index; - } - v[0] = 0; - enterStateMap(im, v, width(d->map->count), &new); - if (!new) { - zfree(v); - } - return im; -} - -static void -doDimPmaps(op) Operator op; -{ - int i, j; - Dimension d; - short *v; - PlankMap im; - int new; - - if (!op->table->rules) { - return; - } - switch (op->arity) { - case 0: - break; - case 1: - d = op->table->dimen[0]; - if (d->map->count > 1) { - v = newVector(); - im = newPlankMap(op->baseNum); - for (i = 0; i < globalMap->count-1; i++) { - int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num; - if (index) { - Item_Set *ts = transLval(op->table, index, 0); - v[i+1] = (*ts)->newNum - op->baseNum+1; - assert(v[i+1] >= 0); - } - } - enterStateMap(im, v, width(d->map->count-1), &new); - if (!new) { - zfree(v); - } - d->pmap = im; - } - break; - case 2: - if (op->table->dimen[0]->map->count == 1 && op->table->dimen[1]->map->count == 1) { - op->table->dimen[0]->pmap = 0; - op->table->dimen[1]->pmap = 0; - } else if (op->table->dimen[0]->map->count == 1) { - v = newVector(); - im = newPlankMap(op->baseNum); - d = op->table->dimen[1]; - for (i = 0; i < globalMap->count-1; i++) { - int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num; - if (index) { - Item_Set *ts = transLval(op->table, 1, index); - v[i+1] = (*ts)->newNum - op->baseNum+1; - assert(v[i+1] >= 0); - } - } - enterStateMap(im, v, width(d->map->count-1), &new); - if (!new) { - zfree(v); - } - d->pmap = im; - } else if (op->table->dimen[1]->map->count == 1) { - v = newVector(); - im = newPlankMap(op->baseNum); - d = op->table->dimen[0]; - for (i = 0; i < globalMap->count-1; i++) { - int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num; - if (index) { - Item_Set *ts = transLval(op->table, index, 1); - v[i +1] = (*ts)->newNum - op->baseNum +1; - assert(v[i +1] >= 0); - } - } - enterStateMap(im, v, width(d->map->count-1), &new); - if (!new) { - zfree(v); - } - d->pmap = im; - } else { - op->table->dimen[0]->pmap = mapToPmap(op->table->dimen[0]); - op->table->dimen[1]->pmap = mapToPmap(op->table->dimen[1]); - /* output table */ - fprintf(outfile, "static unsigned %s %s_%s_transition[%d][%d] = {", - op->stateCount <= 255 ? "char" : "short", - prefix, - op->name, - op->table->dimen[0]->map->count, - op->table->dimen[1]->map->count); - for (i = 0; i < op->table->dimen[0]->map->count; i++) { - if (i > 0) { - fprintf(outfile, ","); - } - fprintf(outfile, "\n{"); - for (j = 0; j < op->table->dimen[1]->map->count; j++) { - Item_Set *ts = transLval(op->table, i, j); - short diff; - if (j > 0) { - fprintf(outfile, ","); - if (j % 10 == 0) { - fprintf(outfile, "\t/* row %d, cols %d-%d*/\n", - i, - j-10, - j-1); - } - } - if ((*ts)->num > 0) { - diff = (*ts)->newNum - op->baseNum +1; - } else { - diff = 0; - } - fprintf(outfile, "%5d", diff); - } - fprintf(outfile, "}\t/* row %d */", i); - } - fprintf(outfile, "\n};\n"); - } - break; - default: - assert(0); - } -} - -static NonTerminal *ntVector; - -static void -doNonTermPmaps(n) NonTerminal n; -{ - short *v; - PlankMap im; - int new; - int i; - - ntVector[n->num] = n; - if (n->num >= last_user_nonterminal) { - return; - } - if (n->ruleCount <= 0) { - return; - } - im = newPlankMap(n->baseNum); - v = newVector(); - for (i = 0; i < globalMap->count-1; i++) { - Rule r = globalMap->set[sortedStates[i]->num]->closed[n->num].rule; - if (r) { - r->used = 1; - v[i+1] = r->newNum - n->baseNum /*safely*/; - assert(v[i+1] >= 0); - } - } - enterStateMap(im, v, width(n->ruleCount+1), &new); - if (!new) { - zfree(v); - } - n->pmap = im; -} - -static void -makePmaps() -{ - foreachList((ListFn) doDimPmaps, operators); - ntVector = (NonTerminal*) zalloc((max_nonterminal) * sizeof(NonTerminal)); - foreachList((ListFn) doNonTermPmaps, nonterminals); -} - -static void -outPlank(p) Plank p; -{ - List f; - int i; - - fprintf(outfile, "static struct {\n"); - - for (f = p->fields; f; f = f->next) { - StateMap sm = (StateMap) f->x; - fprintf(outfile, "\tunsigned int %s:%d;\n", sm->fieldname, sm->width); - } - - fprintf(outfile, "} %s[] = {\n", p->name); - - for (i = 0; i < globalMap->count; i++) { - fprintf(outfile, "\t{"); - for (f = p->fields; f; f = f->next) { - StateMap sm = (StateMap) f->x; - fprintf(outfile, "%4d,", sm->value[i] == -1 ? ERROR_VAL : sm->value[i]); - } - fprintf(outfile, "},\t/* row %d */\n", i); - } - - fprintf(outfile, "};\n"); -} - -static void -purgePlanks(planks) List planks; -{ - List p; - - for (p = planks; p; p = p->next) { - Plank x = (Plank) p->x; - outPlank(x); - } -} - -static void -inToEx() -{ - int i; - int counter; - - fprintf(outfile, "static short %s_eruleMap[] = {\n", prefix); - counter = 0; - for (i = 0; i < max_ruleAST; i++) { - if (counter > 0) { - fprintf(outfile, ","); - if (counter % 10 == 0) { - fprintf(outfile, "\t/* %d-%d */\n", counter-10, counter-1); - } - } - if (counter < sortedRules[i]->rule->newNum) { - assert(counter == sortedRules[i]->rule->newNum-1); - fprintf(outfile, "%5d", 0); - counter++; - if (counter > 0) { - fprintf(outfile, ","); - if (counter % 10 == 0) { - fprintf(outfile, "\t/* %d-%d */\n", counter-10, counter-1); - } - } - } - fprintf(outfile, "%5d", sortedRules[i]->rule->erulenum); - counter++; - } - fprintf(outfile, "\n};\n"); -} - -static void -makePlankRuleMacros() -{ - int i; - - for (i = 1; i < last_user_nonterminal; i++) { - List es; - PlankMap im = ntVector[i]->pmap; - fprintf(outfile, "#define %s_%s_rule(state)\t", prefix, ntVector[i]->name); - if (im) { - fprintf(outfile, "%s_eruleMap[", prefix); - for (es = im->exceptions; es; es = es->next) { - Exception e = (Exception) es->x; - fprintf(outfile, "((state) == %d ? %d :", - e->index, e->value); - } - fprintf(outfile, "%s[state].%s", - im->values->plank->name, - im->values->fieldname); - for (es = im->exceptions; es; es = es->next) { - fprintf(outfile, ")"); - } - fprintf(outfile, " +%d]", im->offset); - - } else { - /* nonterminal never appears on LHS. */ - assert(ntVector[i] == start); - fprintf(outfile, "0"); - } - fprintf(outfile, "\n"); - } - fprintf(outfile, "\n"); -} - -static void -makePlankRule() -{ - int i; - - makePlankRuleMacros(); - - fprintf(outfile, "#ifdef __STDC__\n"); - fprintf(outfile, "int %s_rule(int state, int goalnt) {\n", prefix); - fprintf(outfile, "#else\n"); - fprintf(outfile, "int %s_rule(state, goalnt) int state; int goalnt; {\n", prefix); - fprintf(outfile, "#endif\n"); - - fprintf(outfile, - "\t%s_assert(state >= 0 && state < %d, %s_PANIC(\"Bad state %%d passed to %s_rule\\n\", state));\n", - prefix, globalMap->count, prefix, prefix); - fprintf(outfile, "\tswitch(goalnt) {\n"); - - for (i = 1; i < last_user_nonterminal; i++) { - fprintf(outfile, "\tcase %d:\n", i); - fprintf(outfile, "\t\treturn %s_%s_rule(state);\n", prefix, ntVector[i]->name); - } - fprintf(outfile, "\tdefault:\n"); - fprintf(outfile, "\t\t%s_PANIC(\"Unknown nonterminal %%d in %s_rule;\\n\", goalnt);\n", prefix, prefix); - fprintf(outfile, "\t\tabort();\n"); - fprintf(outfile, "\t\treturn 0;\n"); - fprintf(outfile, "\t}\n"); - fprintf(outfile, "}\n"); -} - -static void -exceptionSwitch(es, sw, pre, post, offset, def) List es; const char *sw; const char *pre; const char *post; int offset; const char *def; -{ - if (es) { - fprintf(outfile, "\t\tswitch (%s) {\n", sw); - for (; es; es = es->next) { - Exception e = (Exception) es->x; - fprintf(outfile, "\t\tcase %d: %s %d; %s\n", e->index, pre, e->value+offset, post); - } - if (def) { - fprintf(outfile, "\t\tdefault: %s;\n", def); - } - fprintf(outfile, "\t\t}\n"); - } else { - if (def) { - fprintf(outfile, "\t\t%s;\n", def); - } - } -} - -static void -doPlankLabel(op) Operator op; -{ - PlankMap im0; - PlankMap im1; - char buf[100]; - - fprintf(outfile, "\tcase %d:\n", op->num); - switch (op->arity) { - case 0: - fprintf(outfile, "\t\treturn %d;\n", op->table->transition[0]->newNum); - break; - case 1: - im0 = op->table->dimen[0]->pmap; - if (im0) { - exceptionSwitch(im0->exceptions, "l", "return ", "", im0->offset, 0); - fprintf(outfile, "\t\treturn %s[l].%s + %d;\n", - im0->values->plank->name, im0->values->fieldname, im0->offset); - } else { - Item_Set *ts = transLval(op->table, 1, 0); - if (*ts) { - fprintf(outfile, "\t\treturn %d;\n", (*ts)->newNum); - } else { - fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL); - } - } - break; - case 2: - im0 = op->table->dimen[0]->pmap; - im1 = op->table->dimen[1]->pmap; - if (!im0 && !im1) { - Item_Set *ts = transLval(op->table, 1, 1); - if (*ts) { - fprintf(outfile, "\t\treturn %d;\n", (*ts)->newNum); - } else { - fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL); - } - } else if (!im0) { - exceptionSwitch(im1->exceptions, "r", "return ", "", im1->offset, 0); - fprintf(outfile, "\t\treturn %s[r].%s + %d;\n", - im1->values->plank->name, im1->values->fieldname, im1->offset); - } else if (!im1) { - exceptionSwitch(im0->exceptions, "l", "return ", "", im0->offset, 0); - fprintf(outfile, "\t\treturn %s[l].%s + %d;\n", - im0->values->plank->name, im0->values->fieldname, im0->offset); - } else { - assert(im0->offset == 0); - assert(im1->offset == 0); - sprintf(buf, "l = %s[l].%s", - im0->values->plank->name, im0->values->fieldname); - exceptionSwitch(im0->exceptions, "l", "l =", "break;", 0, buf); - sprintf(buf, "r = %s[r].%s", - im1->values->plank->name, im1->values->fieldname); - exceptionSwitch(im1->exceptions, "r", "r =", "break;", 0, buf); - - fprintf(outfile, "\t\treturn %s_%s_transition[l][r] + %d;\n", - prefix, - op->name, - op->baseNum); - } - break; - default: - assert(0); - } -} - -static void -doPlankLabelMacrosSafely(op) Operator op; -{ - PlankMap im0; - PlankMap im1; - - switch (op->arity) { - case -1: - fprintf(outfile, "#define %s_%s_state\t0\n", prefix, op->name); - break; - case 0: - fprintf(outfile, "#define %s_%s_state", prefix, op->name); - fprintf(outfile, "\t%d\n", op->table->transition[0]->newNum+1); - break; - case 1: - fprintf(outfile, "#define %s_%s_state(l)", prefix, op->name); - im0 = op->table->dimen[0]->pmap; - if (im0) { - if (im0->exceptions) { - List es = im0->exceptions; - assert(0); - fprintf(outfile, "\t\tswitch (l) {\n"); - for (; es; es = es->next) { - Exception e = (Exception) es->x; - fprintf(outfile, "\t\tcase %d: return %d;\n", e->index, e->value ? e->value+im0->offset : 0); - } - fprintf(outfile, "\t\t}\n"); - } - if (speedflag) { - fprintf(outfile, "\t( %s[l].%s + %d )\n", - im0->values->plank->name, im0->values->fieldname, - im0->offset); - } else { - fprintf(outfile, "\t( (%s_TEMP = %s[l].%s) ? %s_TEMP + %d : 0 )\n", - prefix, - im0->values->plank->name, im0->values->fieldname, - prefix, - im0->offset); - } - } else { - Item_Set *ts = transLval(op->table, 1, 0); - if (*ts) { - fprintf(outfile, "\t%d\n", (*ts)->newNum+1); - } else { - fprintf(outfile, "\t%d\n", 0); - } - } - break; - case 2: - fprintf(outfile, "#define %s_%s_state(l,r)", prefix, op->name); - - im0 = op->table->dimen[0]->pmap; - im1 = op->table->dimen[1]->pmap; - if (!im0 && !im1) { - Item_Set *ts = transLval(op->table, 1, 1); - assert(0); - if (*ts) { - fprintf(outfile, "\t\treturn %d;\n", (*ts)->newNum+1); - } else { - fprintf(outfile, "\t\treturn %d;\n", 0); - } - } else if (!im0) { - assert(0); - if (im1->exceptions) { - List es = im1->exceptions; - fprintf(outfile, "\t\tswitch (r) {\n"); - for (; es; es = es->next) { - Exception e = (Exception) es->x; - fprintf(outfile, "\t\tcase %d: return %d;\n", e->index, e->value ? e->value+im1->offset : 0); - } - fprintf(outfile, "\t\t}\n"); - } - fprintf(outfile, "\t\tstate = %s[r].%s; offset = %d;\n", - im1->values->plank->name, im1->values->fieldname, im1->offset); - fprintf(outfile, "\t\tbreak;\n"); - } else if (!im1) { - assert(0); - if (im0->exceptions) { - List es = im0->exceptions; - fprintf(outfile, "\t\tswitch (l) {\n"); - for (; es; es = es->next) { - Exception e = (Exception) es->x; - fprintf(outfile, "\t\tcase %d: return %d;\n", e->index, e->value ? e->value+im0->offset : 0); - } - fprintf(outfile, "\t\t}\n"); - } - fprintf(outfile, "\t\tstate = %s[l].%s; offset = %d;\n", - im0->values->plank->name, im0->values->fieldname, im0->offset); - fprintf(outfile, "\t\tbreak;\n"); - } else { - assert(im0->offset == 0); - assert(im1->offset == 0); - /* - sprintf(buf, "l = %s[l].%s", - im0->values->plank->name, im0->values->fieldname); - exceptionSwitch(im0->exceptions, "l", "l =", "break;", 0, buf); - sprintf(buf, "r = %s[r].%s", - im1->values->plank->name, im1->values->fieldname); - exceptionSwitch(im1->exceptions, "r", "r =", "break;", 0, buf); - - fprintf(outfile, "\t\tstate = %s_%s_transition[l][r]; offset = %d;\n", - prefix, - op->name, - op->baseNum); - fprintf(outfile, "\t\tbreak;\n"); - */ - - if (speedflag) { - fprintf(outfile, "\t( %s_%s_transition[%s[l].%s][%s[r].%s] + %d)\n", - prefix, - op->name, - im0->values->plank->name, im0->values->fieldname, - im1->values->plank->name, im1->values->fieldname, - op->baseNum); - } else { - fprintf(outfile, "\t( (%s_TEMP = %s_%s_transition[%s[l].%s][%s[r].%s]) ? ", - prefix, - prefix, - op->name, - im0->values->plank->name, im0->values->fieldname, - im1->values->plank->name, im1->values->fieldname); - fprintf(outfile, "%s_TEMP + %d : 0 )\n", - prefix, - op->baseNum); - } - } - break; - default: - assert(0); - } -} -static void -doPlankLabelSafely(op) Operator op; -{ - fprintf(outfile, "\tcase %d:\n", op->num); - switch (op->arity) { - case -1: - fprintf(outfile, "\t\treturn 0;\n"); - break; - case 0: - fprintf(outfile, "\t\treturn %s_%s_state;\n", prefix, op->name); - break; - case 1: - fprintf(outfile, "\t\treturn %s_%s_state(l);\n", prefix, op->name); - break; - case 2: - fprintf(outfile, "\t\treturn %s_%s_state(l,r);\n", prefix, op->name); - break; - default: - assert(0); - } -} - -static void -makePlankState() -{ - fprintf(outfile, "\n"); - fprintf(outfile, "int %s_TEMP;\n", prefix); - foreachList((ListFn) doPlankLabelMacrosSafely, operators); - fprintf(outfile, "\n"); - - fprintf(outfile, "#ifdef __STDC__\n"); - switch (max_arity) { - case -1: - fprintf(stderr, "ERROR: no terminals in grammar.\n"); - exit(1); - case 0: - fprintf(outfile, "int %s_state(int op) {\n", prefix); - fprintf(outfile, "#else\n"); - fprintf(outfile, "int %s_state(op) int op; {\n", prefix); - break; - case 1: - fprintf(outfile, "int %s_state(int op, int l) {\n", prefix); - fprintf(outfile, "#else\n"); - fprintf(outfile, "int %s_state(op, l) int op; int l; {\n", prefix); - break; - case 2: - fprintf(outfile, "int %s_state(int op, int l, int r) {\n", prefix); - fprintf(outfile, "#else\n"); - fprintf(outfile, "int %s_state(op, l, r) int op; int l; int r; {\n", prefix); - break; - default: - assert(0); - } - fprintf(outfile, "#endif\n"); - - fprintf(outfile, "\tregister int %s_TEMP;\n", prefix); - - fprintf(outfile, "#ifndef NDEBUG\n"); - - fprintf(outfile, "\tswitch (op) {\n"); - opsOfArity(2); - if (max_arity >= 2) { - fprintf(outfile, - "\t\t%s_assert(r >= 0 && r < %d, %s_PANIC(\"Bad state %%d passed to %s_state\\n\", r));\n", - prefix, globalMap->count, prefix, prefix); - fprintf(outfile, "\t\t/*FALLTHROUGH*/\n"); - } - opsOfArity(1); - if (max_arity > 1) { - fprintf(outfile, - "\t\t%s_assert(l >= 0 && l < %d, %s_PANIC(\"Bad state %%d passed to %s_state\\n\", l));\n", - prefix, globalMap->count, prefix, prefix); - fprintf(outfile, "\t\t/*FALLTHROUGH*/\n"); - } - opsOfArity(0); - fprintf(outfile, "\t\tbreak;\n"); - fprintf(outfile, "\t}\n"); - fprintf(outfile, "#endif\n"); - - fprintf(outfile, "\tswitch (op) {\n"); - fprintf(outfile,"\tdefault: %s_PANIC(\"Unknown op %%d in %s_state\\n\", op); abort(); return 0;\n", - prefix, prefix); - foreachList((ListFn) doPlankLabelSafely, operators); - fprintf(outfile, "\t}\n"); - - fprintf(outfile, "}\n"); -} - -void -makePlanks() -{ - List planks; - renumber(); - makePmaps(); - planks = assemblePlanks(); - purgePlanks(planks); - inToEx(); - makePlankRule(); - makePlankState(); -} diff --git a/support/tools/Burg/queue.c b/support/tools/Burg/queue.c deleted file mode 100644 index 76e5ea9b57..0000000000 --- a/support/tools/Burg/queue.c +++ /dev/null @@ -1,64 +0,0 @@ -char rcsid_queue[] = "$Id$"; - -#include "b.h" -#include <stdio.h> - -Queue globalQ; - -Queue -newQ() -{ - Queue q; - - q = (Queue) zalloc(sizeof(struct queue)); - assert(q); - q->head = 0; - q->tail = 0; - - return q; -} - -void -addQ(q, ts) Queue q; Item_Set ts; -{ - List qe; - - assert(q); - assert(ts); - - qe = newList(ts, 0); - if (q->head) { - assert(q->tail); - q->tail->next = qe; - q->tail = qe; - } else { - q->head = q->tail = qe; - } -} - -Item_Set -popQ(q) Queue q; -{ - List qe; - Item_Set ts; - - assert(q); - - if (q->head) { - qe = q->head; - q->head = q->head->next; - ts = (Item_Set) qe->x; - zfree(qe); - return ts; - } else { - return 0; - } -} - -void -dumpQ(q) Queue q; -{ - printf("Begin Queue\n"); - foreachList((ListFn)dumpItem_Set, q->head); - printf("End Queue\n"); -} diff --git a/support/tools/Burg/rule.c b/support/tools/Burg/rule.c deleted file mode 100644 index ee5c89e893..0000000000 --- a/support/tools/Burg/rule.c +++ /dev/null @@ -1,49 +0,0 @@ -char rcsid_rule[] = "$Id$"; - -#include "b.h" -#include <stdio.h> - -RuleNum max_rule; -int max_erule_num; - -struct rule stub_rule; - -List rules; - -Rule -newRule(delta, erulenum, lhs, pat) DeltaPtr delta; ERuleNum erulenum; NonTerminal lhs; Pattern pat; -{ - Rule p; - - p = (Rule) zalloc(sizeof(struct rule)); - assert(p); - ASSIGNCOST(p->delta, delta); - p->erulenum = erulenum; - if (erulenum > max_erule_num) { - max_erule_num = erulenum; - } - p->num = max_rule++; - p->lhs = lhs; - p->pat = pat; - - rules = newList(p, rules); - - return p; -} - -void -dumpRule(p) Rule p; -{ - dumpNonTerminal(p->lhs); - printf(" : "); - dumpPattern(p->pat); - printf(" "); - dumpCost(p->delta); - printf("\n"); -} - -void -dumpRuleList(l) List l; -{ - foreachList((ListFn)dumpRule, l); -} diff --git a/support/tools/Burg/sample.gr b/support/tools/Burg/sample.gr deleted file mode 100644 index e1f7283b6d..0000000000 --- a/support/tools/Burg/sample.gr +++ /dev/null @@ -1,150 +0,0 @@ -%{ -#include <stdio.h> - -typedef struct node *NODEPTR_TYPE; - -struct node { - int op, state_label; - NODEPTR_TYPE left, right; -}; - -#define OP_LABEL(p) ((p)->op) -#define STATE_LABEL(p) ((p)->state_label) -#define LEFT_CHILD(p) ((p)->left) -#define RIGHT_CHILD(p) ((p)->right) -#define PANIC printf -%} - -%start reg -%term Assign=1 Constant=2 Fetch=3 Four=4 Mul=5 Plus=6 -%% -con: Constant = 1 (0); -con: Four = 2 (0); -addr: con = 3 (0); -addr: Plus(con,reg) = 4 (0); -addr: Plus(con,Mul(Four,reg)) = 5 (0); -reg: Fetch(addr) = 6 (1); -reg: Assign(addr,reg) = 7 (1); - -%% - -#define Assign 1 -#define Constant 2 -#define Fetch 3 -#define Four 4 -#define Mul 5 -#define Plus 6 - -#ifdef __STDC__ -#define ARGS(x) x -#else -#define ARGS(x) () -#endif - -NODEPTR_TYPE buildtree ARGS((int, NODEPTR_TYPE, NODEPTR_TYPE)); -void printcover ARGS((NODEPTR_TYPE, int, int)); -void printtree ARGS((NODEPTR_TYPE)); -int treecost ARGS((NODEPTR_TYPE, int, int)); -void printMatches ARGS((NODEPTR_TYPE)); -int main ARGS((void)); - -NODEPTR_TYPE buildtree(op, left, right) int op; NODEPTR_TYPE left; NODEPTR_TYPE right; { - NODEPTR_TYPE p; - extern void *malloc ARGS((unsigned)); - - p = (NODEPTR_TYPE) malloc(sizeof *p); - p->op = op; - p->left = left; - p->right = right; - return p; -} - -void printcover(p, goalnt, indent) NODEPTR_TYPE p; int goalnt; int indent; { - int eruleno = burm_rule(STATE_LABEL(p), goalnt); - short *nts = burm_nts[eruleno]; - NODEPTR_TYPE kids[10]; - int i; - - if (eruleno == 0) { - printf("no cover\n"); - return; - } - for (i = 0; i < indent; i++) - printf("."); - printf("%s\n", burm_string[eruleno]); - burm_kids(p, eruleno, kids); - for (i = 0; nts[i]; i++) - printcover(kids[i], nts[i], indent+1); -} - -void printtree(p) NODEPTR_TYPE p; { - int op = burm_op_label(p); - - printf("%s", burm_opname[op]); - switch (burm_arity[op]) { - case 0: - break; - case 1: - printf("("); - printtree(burm_child(p, 0)); - printf(")"); - break; - case 2: - printf("("); - printtree(burm_child(p, 0)); - printf(", "); - printtree(burm_child(p, 1)); - printf(")"); - break; - } -} - -int treecost(p, goalnt, costindex) NODEPTR_TYPE p; int goalnt; int costindex; { - int eruleno = burm_rule(STATE_LABEL(p), goalnt); - int cost = burm_cost[eruleno][costindex], i; - short *nts = burm_nts[eruleno]; - NODEPTR_TYPE kids[10]; - - burm_kids(p, eruleno, kids); - for (i = 0; nts[i]; i++) - cost += treecost(kids[i], nts[i], costindex); - return cost; -} - -void printMatches(p) NODEPTR_TYPE p; { - int nt; - int eruleno; - - printf("Node 0x%lx= ", (unsigned long)p); - printtree(p); - printf(" matched rules:\n"); - for (nt = 1; burm_ntname[nt] != (char*)NULL; nt++) - if ((eruleno = burm_rule(STATE_LABEL(p), nt)) != 0) - printf("\t%s\n", burm_string[eruleno]); -} - -main() { - NODEPTR_TYPE p; - - p = buildtree(Assign, - buildtree(Constant, 0, 0), - buildtree(Fetch, - buildtree(Plus, - buildtree(Constant, 0, 0), - buildtree(Mul, - buildtree(Four, 0, 0), - buildtree(Fetch, buildtree(Constant, 0, 0), 0) - ) - ), - 0 - ) - ); - printtree(p); - printf("\n\n"); - burm_label(p); - printcover(p, 1, 0); - printf("\nCover cost == %d\n\n", treecost(p, 1, 0)); - printMatches(p); - return 0; -} - diff --git a/support/tools/Burg/string.c b/support/tools/Burg/string.c deleted file mode 100644 index 9b69c3045f..0000000000 --- a/support/tools/Burg/string.c +++ /dev/null @@ -1,65 +0,0 @@ -char rcsid_string[] = "$Id$"; - -#include <stdio.h> -#include <string.h> -#include "b.h" -#include "fe.h" - -static StrTableElement newStrTableElement ARGS((void)); - -StrTable -newStrTable() -{ - return (StrTable) zalloc(sizeof(struct strTable)); -} - -static StrTableElement -newStrTableElement() -{ - return (StrTableElement) zalloc(sizeof(struct strTableElement)); -} - -void -dumpStrTable(t) StrTable t; -{ - List e; - IntList r; - - printf("Begin StrTable\n"); - for (e = t->elems; e; e = e->next) { - StrTableElement el = (StrTableElement) e->x; - printf("%s: ", el->str); - for (r = el->erulenos; r; r = r->next) { - int i = r->x; - printf("(%d)", i); - } - printf("\n"); - } - printf("End StrTable\n"); -} - -StrTableElement -addString(t, s, eruleno, new) StrTable t; char *s; int eruleno; int *new; -{ - List l; - StrTableElement ste; - - assert(t); - for (l = t->elems; l; l = l->next) { - StrTableElement e = (StrTableElement) l->x; - - assert(e); - if (!strcmp(s, e->str)) { - e->erulenos = newIntList(eruleno, e->erulenos); - *new = 0; - return e; - } - } - ste = newStrTableElement(); - ste->erulenos = newIntList(eruleno, 0); - ste->str = (char *) zalloc(strlen(s) + 1); - strcpy(ste->str, s); - t->elems = newList(ste, t->elems); - *new = 1; - return ste; -} diff --git a/support/tools/Burg/symtab.c b/support/tools/Burg/symtab.c deleted file mode 100644 index 3ecab2fc5f..0000000000 --- a/support/tools/Burg/symtab.c +++ /dev/null @@ -1,38 +0,0 @@ -char rcsid_symtab[] = "$Id$"; - -#include <stdio.h> -#include <string.h> -#include "b.h" -#include "fe.h" - -static List symtab; - -Symbol -newSymbol(name) char *name; -{ - Symbol s; - - s = (Symbol) zalloc(sizeof(struct symbol)); - assert(s); - s->name = name; - return s; -} - -Symbol -enter(name, new) char *name; int *new; -{ - List l; - Symbol s; - - *new = 0; - for (l = symtab; l; l = l->next) { - s = (Symbol) l->x; - if (!strcmp(name, s->name)) { - return s; - } - } - *new = 1; - s = newSymbol(name); - symtab = newList(s, symtab); - return s; -} diff --git a/support/tools/Burg/table.c b/support/tools/Burg/table.c deleted file mode 100644 index 1de74f9a10..0000000000 --- a/support/tools/Burg/table.c +++ /dev/null @@ -1,552 +0,0 @@ -char rcsid_table[] = "$Id$"; - -#include "b.h" -#include <string.h> -#include <stdio.h> - -static void growIndex_Map ARGS((Index_Map *)); -static Relevant newRelevant ARGS((void)); -static Dimension newDimension ARGS((Operator, int)); -static void GT_1 ARGS((Table)); -static void GT_2_0 ARGS((Table)); -static void GT_2_1 ARGS((Table)); -static void growTransition ARGS((Table, int)); -static Item_Set restrict ARGS((Dimension, Item_Set)); -static void addHP_1 ARGS((Table, Item_Set)); -static void addHP_2_0 ARGS((Table, Item_Set)); -static void addHP_2_1 ARGS((Table, Item_Set)); -static void addHyperPlane ARGS((Table, int, Item_Set)); - -static void -growIndex_Map(r) Index_Map *r; -{ - Index_Map new; - - new.max_size = r->max_size + STATES_INCR; - new.class = (Item_Set*) zalloc(new.max_size * sizeof(Item_Set)); - assert(new.class); - memcpy(new.class, r->class, r->max_size * sizeof(Item_Set)); - zfree(r->class); - *r = new; -} - -static Relevant -newRelevant() -{ - Relevant r = (Relevant) zalloc(max_nonterminal * sizeof(*r)); - return r; -} - -void -addRelevant(r, nt) Relevant r; NonTerminalNum nt; -{ - int i; - - for (i = 0; r[i]; i++) { - if (r[i] == nt) { - break; - } - } - if (!r[i]) { - r[i] = nt; - } -} - -static Dimension -newDimension(op, index) Operator op; ArityNum index; -{ - Dimension d; - List pl; - Relevant r; - - assert(op); - assert(index >= 0 && index < op->arity); - d = (Dimension) zalloc(sizeof(struct dimension)); - assert(d); - - r = d->relevant = newRelevant(); - for (pl = rules; pl; pl = pl->next) { - Rule pr = (Rule) pl->x; - if (pr->pat->op == op) { - addRelevant(r, pr->pat->children[index]->num); - } - } - - d->index_map.max_size = STATES_INCR; - d->index_map.class = (Item_Set*) - zalloc(d->index_map.max_size * sizeof(Item_Set)); - d->map = newMapping(DIM_MAP_SIZE); - d->max_size = TABLE_INCR; - - return d; -} - -Table -newTable(op) Operator op; -{ - Table t; - int i, size; - - assert(op); - - t = (Table) zalloc(sizeof(struct table)); - assert(t); - - t->op = op; - - for (i = 0; i < op->arity; i++) { - t->dimen[i] = newDimension(op, i); - } - - size = 1; - for (i = 0; i < op->arity; i++) { - size *= t->dimen[i]->max_size; - } - t->transition = (Item_Set*) zalloc(size * sizeof(Item_Set)); - t->relevant = newRelevant(); - assert(t->transition); - - return t; -} - -static void -GT_1(t) Table t; -{ - Item_Set *ts; - ItemSetNum oldsize = t->dimen[0]->max_size; - ItemSetNum newsize = t->dimen[0]->max_size + TABLE_INCR; - - t->dimen[0]->max_size = newsize; - - ts = (Item_Set*) zalloc(newsize * sizeof(Item_Set)); - assert(ts); - memcpy(ts, t->transition, oldsize * sizeof(Item_Set)); - zfree(t->transition); - t->transition = ts; -} - -static void -GT_2_0(t) Table t; -{ - Item_Set *ts; - ItemSetNum oldsize = t->dimen[0]->max_size; - ItemSetNum newsize = t->dimen[0]->max_size + TABLE_INCR; - int size; - - t->dimen[0]->max_size = newsize; - - size = newsize * t->dimen[1]->max_size; - - ts = (Item_Set*) zalloc(size * sizeof(Item_Set)); - assert(ts); - memcpy(ts, t->transition, oldsize*t->dimen[1]->max_size * sizeof(Item_Set)); - zfree(t->transition); - t->transition = ts; -} - -static void -GT_2_1(t) Table t; -{ - Item_Set *ts; - ItemSetNum oldsize = t->dimen[1]->max_size; - ItemSetNum newsize = t->dimen[1]->max_size + TABLE_INCR; - int size; - Item_Set *from; - Item_Set *to; - int i1, i2; - - t->dimen[1]->max_size = newsize; - - size = newsize * t->dimen[0]->max_size; - - ts = (Item_Set*) zalloc(size * sizeof(Item_Set)); - assert(ts); - - from = t->transition; - to = ts; - for (i1 = 0; i1 < t->dimen[0]->max_size; i1++) { - for (i2 = 0; i2 < oldsize; i2++) { - to[i2] = from[i2]; - } - to += newsize; - from += oldsize; - } - zfree(t->transition); - t->transition = ts; -} - -static void -growTransition(t, dim) Table t; ArityNum dim; -{ - - assert(t); - assert(t->op); - assert(dim < t->op->arity); - - switch (t->op->arity) { - default: - assert(0); - break; - case 1: - GT_1(t); - return; - case 2: - switch (dim) { - default: - assert(0); - break; - case 0: - GT_2_0(t); - return; - case 1: - GT_2_1(t); - return; - } - } -} - -static Item_Set -restrict(d, ts) Dimension d; Item_Set ts; -{ - DeltaCost base; - Item_Set r; - int found; - register Relevant r_ptr = d->relevant; - register Item *ts_current = ts->closed; - register Item *r_current; - register int i; - register int nt; - - ZEROCOST(base); - found = 0; - r = newItem_Set(d->relevant); - r_current = r->virgin; - for (i = 0; (nt = r_ptr[i]) != 0; i++) { - if (ts_current[nt].rule) { - r_current[nt].rule = &stub_rule; - if (!found) { - found = 1; - ASSIGNCOST(base, ts_current[nt].delta); - } else { - if (LESSCOST(ts_current[nt].delta, base)) { - ASSIGNCOST(base, ts_current[nt].delta); - } - } - } - } - - /* zero align */ - for (i = 0; (nt = r_ptr[i]) != 0; i++) { - if (r_current[nt].rule) { - ASSIGNCOST(r_current[nt].delta, ts_current[nt].delta); - MINUSCOST(r_current[nt].delta, base); - } - } - assert(!r->closed); - r->representative = ts; - return r; -} - -static void -addHP_1(t, ts) Table t; Item_Set ts; -{ - List pl; - Item_Set e; - Item_Set tmp; - int new; - - e = newItem_Set(t->relevant); - assert(e); - e->kids[0] = ts->representative; - for (pl = t->rules; pl; pl = pl->next) { - Rule p = (Rule) pl->x; - if (t->op == p->pat->op && ts->virgin[p->pat->children[0]->num].rule) { - DeltaCost dc; - ASSIGNCOST(dc, ts->virgin[p->pat->children[0]->num].delta); - ADDCOST(dc, p->delta); - if (!e->virgin[p->lhs->num].rule || LESSCOST(dc, e->virgin[p->lhs->num].delta)) { - e->virgin[p->lhs->num].rule = p; - ASSIGNCOST(e->virgin[p->lhs->num].delta, dc); - e->op = t->op; - } - } - } - trim(e); - zero(e); - tmp = encode(globalMap, e, &new); - assert(ts->num < t->dimen[0]->map->max_size); - t->transition[ts->num] = tmp; - if (new) { - closure(e); - addQ(globalQ, tmp); - } else { - freeItem_Set(e); - } -} - -static void -addHP_2_0(t, ts) Table t; Item_Set ts; -{ - List pl; - register Item_Set e; - Item_Set tmp; - int new; - int i2; - - assert(t->dimen[1]->map->count <= t->dimen[1]->map->max_size); - for (i2 = 0; i2 < t->dimen[1]->map->count; i2++) { - e = newItem_Set(t->relevant); - assert(e); - e->kids[0] = ts->representative; - e->kids[1] = t->dimen[1]->map->set[i2]->representative; - for (pl = t->rules; pl; pl = pl->next) { - register Rule p = (Rule) pl->x; - - if (t->op == p->pat->op - && ts->virgin[p->pat->children[0]->num].rule - && t->dimen[1]->map->set[i2]->virgin[p->pat->children[1]->num].rule){ - DeltaCost dc; - ASSIGNCOST(dc, p->delta); - ADDCOST(dc, ts->virgin[p->pat->children[0]->num].delta); - ADDCOST(dc, t->dimen[1]->map->set[i2]->virgin[p->pat->children[1]->num].delta); - - if (!e->virgin[p->lhs->num].rule || LESSCOST(dc, e->virgin[p->lhs->num].delta)) { - e->virgin[p->lhs->num].rule = p; - ASSIGNCOST(e->virgin[p->lhs->num].delta, dc); - e->op = t->op; - } - } - } - trim(e); - zero(e); - tmp = encode(globalMap, e, &new); - assert(ts->num < t->dimen[0]->map->max_size); - t->transition[ts->num * t->dimen[1]->max_size + i2] = tmp; - if (new) { - closure(e); - addQ(globalQ, tmp); - } else { - freeItem_Set(e); - } - } -} - -static void -addHP_2_1(t, ts) Table t; Item_Set ts; -{ - List pl; - register Item_Set e; - Item_Set tmp; - int new; - int i1; - - assert(t->dimen[0]->map->count <= t->dimen[0]->map->max_size); - for (i1 = 0; i1 < t->dimen[0]->map->count; i1++) { - e = newItem_Set(t->relevant); - assert(e); - e->kids[0] = t->dimen[0]->map->set[i1]->representative; - e->kids[1] = ts->representative; - for (pl = t->rules; pl; pl = pl->next) { - register Rule p = (Rule) pl->x; - - if (t->op == p->pat->op - && ts->virgin[p->pat->children[1]->num].rule - && t->dimen[0]->map->set[i1]->virgin[p->pat->children[0]->num].rule){ - DeltaCost dc; - ASSIGNCOST(dc, p->delta ); - ADDCOST(dc, ts->virgin[p->pat->children[1]->num].delta); - ADDCOST(dc, t->dimen[0]->map->set[i1]->virgin[p->pat->children[0]->num].delta); - if (!e->virgin[p->lhs->num].rule || LESSCOST(dc, e->virgin[p->lhs->num].delta)) { - e->virgin[p->lhs->num].rule = p; - ASSIGNCOST(e->virgin[p->lhs->num].delta, dc); - e->op = t->op; - } - } - } - trim(e); - zero(e); - tmp = encode(globalMap, e, &new); - assert(ts->num < t->dimen[1]->map->max_size); - t->transition[i1 * t->dimen[1]->max_size + ts->num] = tmp; - if (new) { - closure(e); - addQ(globalQ, tmp); - } else { - freeItem_Set(e); - } - } -} - -static void -addHyperPlane(t, i, ts) Table t; ArityNum i; Item_Set ts; -{ - switch (t->op->arity) { - default: - assert(0); - break; - case 1: - addHP_1(t, ts); - return; - case 2: - switch (i) { - default: - assert(0); - break; - case 0: - addHP_2_0(t, ts); - return; - case 1: - addHP_2_1(t, ts); - return; - } - } -} - -void -addToTable(t, ts) Table t; Item_Set ts; -{ - ArityNum i; - - assert(t); - assert(ts); - assert(t->op); - - for (i = 0; i < t->op->arity; i++) { - Item_Set r; - Item_Set tmp; - int new; - - r = restrict(t->dimen[i], ts); - tmp = encode(t->dimen[i]->map, r, &new); - if (t->dimen[i]->index_map.max_size <= ts->num) { - growIndex_Map(&t->dimen[i]->index_map); - } - assert(ts->num < t->dimen[i]->index_map.max_size); - t->dimen[i]->index_map.class[ts->num] = tmp; - if (new) { - if (t->dimen[i]->max_size <= r->num) { - growTransition(t, i); - } - addHyperPlane(t, i, r); - } else { - freeItem_Set(r); - } - } -} - -Item_Set * -transLval(t, row, col) Table t; int row; int col; -{ - switch (t->op->arity) { - case 0: - assert(row == 0); - assert(col == 0); - return t->transition; - case 1: - assert(col == 0); - return t->transition + row; - case 2: - return t->transition + row * t->dimen[1]->max_size + col; - default: - assert(0); - } - return 0; -} - -void -dumpRelevant(r) Relevant r; -{ - for (; *r; r++) { - printf("%4d", *r); - } -} - -void -dumpIndex_Map(r) Index_Map *r; -{ - int i; - - printf("BEGIN Index_Map: MaxSize (%d)\n", r->max_size); - for (i = 0; i < globalMap->count; i++) { - printf("\t#%d: -> %d\n", i, r->class[i]->num); - } - printf("END Index_Map:\n"); -} - -void -dumpDimension(d) Dimension d; -{ - printf("BEGIN Dimension:\n"); - printf("Relevant: "); - dumpRelevant(d->relevant); - printf("\n"); - dumpIndex_Map(&d->index_map); - dumpMapping(d->map); - printf("MaxSize of dimension = %d\n", d->max_size); - printf("END Dimension\n"); -} - -void -dumpTable(t, full) Table t; int full; -{ - int i; - - if (!t) { - printf("NO Table yet.\n"); - return; - } - printf("BEGIN Table:\n"); - if (full) { - dumpOperator(t->op, 0); - } - for (i = 0; i < t->op->arity; i++) { - printf("BEGIN dimension(%d)\n", i); - dumpDimension(t->dimen[i]); - printf("END dimension(%d)\n", i); - } - dumpTransition(t); - printf("END Table:\n"); -} - -void -dumpTransition(t) Table t; -{ - int i,j; - - switch (t->op->arity) { - case 0: - printf("{ %d }", t->transition[0]->num); - break; - case 1: - printf("{"); - for (i = 0; i < t->dimen[0]->map->count; i++) { - if (i > 0) { - printf(","); - } - printf("%5d", t->transition[i]->num); - } - printf("}"); - break; - case 2: - printf("{"); - for (i = 0; i < t->dimen[0]->map->count; i++) { - if (i > 0) { - printf(","); - } - printf("\n"); - printf("{"); - for (j = 0; j < t->dimen[1]->map->count; j++) { - Item_Set *ts = transLval(t, i, j); - if (j > 0) { - printf(","); - } - printf("%5d", (*ts)->num); - } - printf("}"); - } - printf("\n}\n"); - break; - default: - assert(0); - } -} diff --git a/support/tools/Burg/trim.c b/support/tools/Burg/trim.c deleted file mode 100644 index 05ee2d0f64..0000000000 --- a/support/tools/Burg/trim.c +++ /dev/null @@ -1,412 +0,0 @@ -char rcsid_trim[] = "$Id$"; - -#include <stdio.h> -#include "b.h" -#include "fe.h" - -Relation *allpairs; - -int trimflag = 0; -int debugTrim = 0; - -static void siblings ARGS((int, int)); -static void findAllNexts ARGS((void)); -static Relation *newAllPairs ARGS((void)); - -static void -siblings(i, j) int i; int j; -{ - int k; - List pl; - DeltaCost Max; - int foundmax; - - allpairs[i][j].sibComputed = 1; - - if (i == 1) { - return; /* never trim start symbol */ - } - if (i==j) { - return; - } - - ZEROCOST(Max); - foundmax = 0; - - for (k = 1; k < max_nonterminal; k++) { - DeltaCost tmp; - - if (k==i || k==j) { - continue; - } - if (!allpairs[k][i].rule) { - continue; - } - if (!allpairs[k][j].rule) { - return; - } - ASSIGNCOST(tmp, allpairs[k][j].chain); - MINUSCOST(tmp, allpairs[k][i].chain); - if (foundmax) { - if (LESSCOST(Max, tmp)) { - ASSIGNCOST(Max, tmp); - } - } else { - foundmax = 1; - ASSIGNCOST(Max, tmp); - } - } - - for (pl = rules; pl; pl = pl->next) { - Rule p = (Rule) pl->x; - Operator op = p->pat->op; - List oprule; - DeltaCost Min; - int foundmin; - - if (!op) { - continue; - } - switch (op->arity) { - case 0: - continue; - case 1: - if (!allpairs[p->pat->children[0]->num ][ i].rule) { - continue; - } - foundmin = 0; - for (oprule = op->table->rules; oprule; oprule = oprule->next) { - Rule s = (Rule) oprule->x; - DeltaPtr Cx; - DeltaPtr Csj; - DeltaPtr Cpi; - DeltaCost tmp; - - if (!allpairs[p->lhs->num ][ s->lhs->num].rule - || !allpairs[s->pat->children[0]->num ][ j].rule) { - continue; - } - Cx = allpairs[p->lhs->num ][ s->lhs->num].chain; - Csj= allpairs[s->pat->children[0]->num ][ j].chain; - Cpi= allpairs[p->pat->children[0]->num ][ i].chain; - ASSIGNCOST(tmp, Cx); - ADDCOST(tmp, s->delta); - ADDCOST(tmp, Csj); - MINUSCOST(tmp, Cpi); - MINUSCOST(tmp, p->delta); - if (foundmin) { - if (LESSCOST(tmp, Min)) { - ASSIGNCOST(Min, tmp); - } - } else { - foundmin = 1; - ASSIGNCOST(Min, tmp); - } - } - if (!foundmin) { - return; - } - if (foundmax) { - if (LESSCOST(Max, Min)) { - ASSIGNCOST(Max, Min); - } - } else { - foundmax = 1; - ASSIGNCOST(Max, Min); - } - break; - case 2: - /* do first dimension */ - if (allpairs[p->pat->children[0]->num ][ i].rule) { - foundmin = 0; - for (oprule = op->table->rules; oprule; oprule = oprule->next) { - Rule s = (Rule) oprule->x; - DeltaPtr Cx; - DeltaPtr Cb; - DeltaPtr Csj; - DeltaPtr Cpi; - DeltaCost tmp; - - if (allpairs[p->lhs->num ][ s->lhs->num].rule - && allpairs[s->pat->children[0]->num ][ j].rule - && allpairs[s->pat->children[1]->num ][ p->pat->children[1]->num].rule) { - Cx = allpairs[p->lhs->num ][ s->lhs->num].chain; - Csj= allpairs[s->pat->children[0]->num ][ j].chain; - Cpi= allpairs[p->pat->children[0]->num ][ i].chain; - Cb = allpairs[s->pat->children[1]->num ][ p->pat->children[1]->num].chain; - ASSIGNCOST(tmp, Cx); - ADDCOST(tmp, s->delta); - ADDCOST(tmp, Csj); - ADDCOST(tmp, Cb); - MINUSCOST(tmp, Cpi); - MINUSCOST(tmp, p->delta); - if (foundmin) { - if (LESSCOST(tmp, Min)) { - ASSIGNCOST(Min, tmp); - } - } else { - foundmin = 1; - ASSIGNCOST(Min, tmp); - } - } - } - if (!foundmin) { - return; - } - if (foundmax) { - if (LESSCOST(Max, Min)) { - ASSIGNCOST(Max, Min); - } - } else { - foundmax = 1; - ASSIGNCOST(Max, Min); - } - } - /* do second dimension */ - if (allpairs[p->pat->children[1]->num ][ i].rule) { - foundmin = 0; - for (oprule = op->table->rules; oprule; oprule = oprule->next) { - Rule s = (Rule) oprule->x; - DeltaPtr Cx; - DeltaPtr Cb; - DeltaPtr Csj; - DeltaPtr Cpi; - DeltaCost tmp; - - if (allpairs[p->lhs->num ][ s->lhs->num].rule - && allpairs[s->pat->children[1]->num ][ j].rule - && allpairs[s->pat->children[0]->num ][ p->pat->children[0]->num].rule) { - Cx = allpairs[p->lhs->num ][ s->lhs->num].chain; - Csj= allpairs[s->pat->children[1]->num ][ j].chain; - Cpi= allpairs[p->pat->children[1]->num ][ i].chain; - Cb = allpairs[s->pat->children[0]->num ][ p->pat->children[0]->num].chain; - ASSIGNCOST(tmp, Cx); - ADDCOST(tmp, s->delta); - ADDCOST(tmp, Csj); - ADDCOST(tmp, Cb); - MINUSCOST(tmp, Cpi); - MINUSCOST(tmp, p->delta); - if (foundmin) { - if (LESSCOST(tmp, Min)) { - ASSIGNCOST(Min, tmp); - } - } else { - foundmin = 1; - ASSIGNCOST(Min, tmp); - } - } - } - if (!foundmin) { - return; - } - if (foundmax) { - if (LESSCOST(Max, Min)) { - ASSIGNCOST(Max, Min); - } - } else { - foundmax = 1; - ASSIGNCOST(Max, Min); - } - } - break; - default: - assert(0); - } - } - allpairs[i ][ j].sibFlag = foundmax; - ASSIGNCOST(allpairs[i ][ j].sibling, Max); -} - -static void -findAllNexts() -{ - int i,j; - int last; - - for (i = 1; i < max_nonterminal; i++) { - last = 0; - for (j = 1; j < max_nonterminal; j++) { - if (allpairs[i ][j].rule) { - allpairs[i ][ last].nextchain = j; - last = j; - } - } - } - /* - for (i = 1; i < max_nonterminal; i++) { - last = 0; - for (j = 1; j < max_nonterminal; j++) { - if (allpairs[i ][j].sibFlag) { - allpairs[i ][ last].nextsibling = j; - last = j; - } - } - } - */ -} - -static Relation * -newAllPairs() -{ - int i; - Relation *rv; - - rv = (Relation*) zalloc(max_nonterminal * sizeof(Relation)); - for (i = 0; i < max_nonterminal; i++) { - rv[i] = (Relation) zalloc(max_nonterminal * sizeof(struct relation)); - } - return rv; -} - -void -findAllPairs() -{ - List pl; - int changes; - int j; - - allpairs = newAllPairs(); - for (pl = chainrules; pl; pl = pl->next) { - Rule p = (Rule) pl->x; - NonTerminalNum rhs = p->pat->children[0]->num; - NonTerminalNum lhs = p->lhs->num; - Relation r = &allpairs[lhs ][ rhs]; - - if (LESSCOST(p->delta, r->chain)) { - ASSIGNCOST(r->chain, p->delta); - r->rule = p; - } - } - for (j = 1; j < max_nonterminal; j++) { - Relation r = &allpairs[j ][ j]; - ZEROCOST(r->chain); - r->rule = &stub_rule; - } - changes = 1; - while (changes) { - changes = 0; - for (pl = chainrules; pl; pl = pl->next) { - Rule p = (Rule) pl->x; - NonTerminalNum rhs = p->pat->children[0]->num; - NonTerminalNum lhs = p->lhs->num; - int i; - - for (i = 1; i < max_nonterminal; i++) { - Relation r = &allpairs[rhs ][ i]; - Relation s = &allpairs[lhs ][ i]; - DeltaCost dc; - if (!r->rule) { - continue; - } - ASSIGNCOST(dc, p->delta); - ADDCOST(dc, r->chain); - if (!s->rule || LESSCOST(dc, s->chain)) { - s->rule = p; - ASSIGNCOST(s->chain, dc); - changes = 1; - } - } - } - } - findAllNexts(); -} - -void -trim(t) Item_Set t; -{ - int m,n; - static short *vec = 0; - int last; - - assert(!t->closed); - debug(debugTrim, printf("Begin Trim\n")); - debug(debugTrim, dumpItem_Set(t)); - - last = 0; - if (!vec) { - vec = (short*) zalloc(max_nonterminal * sizeof(*vec)); - } - for (m = 1; m < max_nonterminal; m++) { - if (t->virgin[m].rule) { - vec[last++] = m; - } - } - for (m = 0; m < last; m++) { - DeltaCost tmp; - int j; - int i; - - i = vec[m]; - - for (j = allpairs[i ][ 0].nextchain; j; j = allpairs[i ][ j].nextchain) { - - if (i == j) { - continue; - } - if (!t->virgin[j].rule) { - continue; - } - ASSIGNCOST(tmp, t->virgin[j].delta); - ADDCOST(tmp, allpairs[i ][ j].chain); - if (!LESSCOST(t->virgin[i].delta, tmp)) { - t->virgin[i].rule = 0; - ZEROCOST(t->virgin[i].delta); - debug(debugTrim, printf("Trimmed Chain (%d,%d)\n", i,j)); - goto outer; - } - - } - if (!trimflag) { - continue; - } - for (n = 0; n < last; n++) { - j = vec[n]; - if (i == j) { - continue; - } - - if (!t->virgin[j].rule) { - continue; - } - - if (!allpairs[i][j].sibComputed) { - siblings(i,j); - } - if (!allpairs[i][j].sibFlag) { - continue; - } - ASSIGNCOST(tmp, t->virgin[j].delta); - ADDCOST(tmp, allpairs[i ][ j].sibling); - if (!LESSCOST(t->virgin[i].delta, tmp)) { - t->virgin[i].rule = 0; - ZEROCOST(t->virgin[i].delta); - goto outer; - } - } - - outer: ; - } - - debug(debugTrim, dumpItem_Set(t)); - debug(debugTrim, printf("End Trim\n")); -} - -void -dumpRelation(r) Relation r; -{ - printf("{ %d %ld %d %ld }", r->rule->erulenum, (long) r->chain, r->sibFlag, (long) r->sibling); -} - -void -dumpAllPairs() -{ - int i,j; - - printf("Dumping AllPairs\n"); - for (i = 1; i < max_nonterminal; i++) { - for (j = 1; j < max_nonterminal; j++) { - dumpRelation(&allpairs[i ][j]); - } - printf("\n"); - } -} diff --git a/support/tools/Burg/zalloc.c b/support/tools/Burg/zalloc.c deleted file mode 100644 index 9128e4280f..0000000000 --- a/support/tools/Burg/zalloc.c +++ /dev/null @@ -1,35 +0,0 @@ -char rcsid_zalloc[] = "$Id$"; - -#include <stdio.h> -#include <string.h> -#include "b.h" - -extern void exit ARGS((int)); -extern void free ARGS((void *)); -extern void *malloc ARGS((unsigned)); - -int -fatal(const char *name, int line) -{ - fprintf(stderr, "assertion failed: file %s, line %d\n", name, line); - exit(1); - return 0; -} - -void * -zalloc(size) unsigned int size; -{ - void *t = (void *) malloc(size); - if (!t) { - fprintf(stderr, "Malloc failed---PROGRAM ABORTED\n"); - exit(1); - } - memset(t, 0, size); - return t; -} - -void -zfree(p) void *p; -{ - free(p); -} diff --git a/support/tools/Makefile b/support/tools/Makefile deleted file mode 100644 index 4772199c8b..0000000000 --- a/support/tools/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -LEVEL = ../.. - -DIRS = Burg TableGen - -include $(LEVEL)/Makefile.common - diff --git a/support/tools/TableGen/CodeEmitterGen.cpp b/support/tools/TableGen/CodeEmitterGen.cpp deleted file mode 100644 index 98976c7336..0000000000 --- a/support/tools/TableGen/CodeEmitterGen.cpp +++ /dev/null @@ -1,217 +0,0 @@ -//===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===// -// -// FIXME: Document. -// -//===----------------------------------------------------------------------===// - -#include "CodeEmitterGen.h" -#include "Record.h" -#include "Support/Debug.h" - -void CodeEmitterGen::run(std::ostream &o) { - std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); - - EmitSourceFileHeader("Machine Code Emitter", o); - - std::string Namespace = "V9::"; - std::string ClassName = "SparcV9CodeEmitter::"; - - //const std::string &Namespace = Inst->getValue("Namespace")->getName(); - o << "unsigned " << ClassName - << "getBinaryCodeForInstr(MachineInstr &MI) {\n" - << " unsigned Value = 0;\n" - << " DEBUG(std::cerr << MI);\n" - << " switch (MI.getOpcode()) {\n"; - for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end(); - I != E; ++I) { - Record *R = *I; - o << " case " << Namespace << R->getName() << ": {\n" - << " DEBUG(std::cerr << \"Emitting " << R->getName() << "\\n\");\n"; - - BitsInit *BI = R->getValueAsBitsInit("Inst"); - - unsigned Value = 0; - const std::vector<RecordVal> &Vals = R->getValues(); - - DEBUG(o << " // prefilling: "); - // Start by filling in fixed values... - for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) { - if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) { - Value |= B->getValue() << (e-i-1); - DEBUG(o << B->getValue()); - } else { - DEBUG(o << "0"); - } - } - DEBUG(o << "\n"); - - DEBUG(o << " // " << *R->getValue("Inst") << "\n"); - o << " Value = " << Value << "U;\n\n"; - - // Loop over all of the fields in the instruction determining which are the - // operands to the instruction. - // - unsigned op = 0; - std::map<std::string, unsigned> OpOrder; - std::map<std::string, bool> OpContinuous; - for (unsigned i = 0, e = Vals.size(); i != e; ++i) { - if (!Vals[i].getPrefix() && !Vals[i].getValue()->isComplete()) { - // Is the operand continuous? If so, we can just mask and OR it in - // instead of doing it bit-by-bit, saving a lot in runtime cost. - const BitsInit *InstInit = BI; - int beginBitInVar = -1, endBitInVar = -1; - int beginBitInInst = -1, endBitInInst = -1; - bool continuous = true; - - for (int bit = InstInit->getNumBits()-1; bit >= 0; --bit) { - if (VarBitInit *VBI = - dynamic_cast<VarBitInit*>(InstInit->getBit(bit))) { - TypedInit *TI = VBI->getVariable(); - if (VarInit *VI = dynamic_cast<VarInit*>(TI)) { - // only process the current variable - if (VI->getName() != Vals[i].getName()) - continue; - - if (beginBitInVar == -1) - beginBitInVar = VBI->getBitNum(); - - if (endBitInVar == -1) - endBitInVar = VBI->getBitNum(); - else { - if (endBitInVar == (int)VBI->getBitNum() + 1) - endBitInVar = VBI->getBitNum(); - else { - continuous = false; - break; - } - } - - if (beginBitInInst == -1) - beginBitInInst = bit; - if (endBitInInst == -1) - endBitInInst = bit; - else { - if (endBitInInst == bit + 1) - endBitInInst = bit; - else { - continuous = false; - break; - } - } - - // maintain same distance between bits in field and bits in - // instruction. if the relative distances stay the same - // throughout, - if (beginBitInVar - (int)VBI->getBitNum() != - beginBitInInst - bit) { - continuous = false; - break; - } - } - } - } - - // If we have found no bit in "Inst" which comes from this field, then - // this is not an operand!! - if (beginBitInInst != -1) { - o << " // op" << op << ": " << Vals[i].getName() << "\n" - << " int64_t op" << op - <<" = getMachineOpValue(MI, MI.getOperand("<<op<<"));\n"; - //<< " MachineOperand &op" << op <<" = MI.getOperand("<<op<<");\n"; - OpOrder[Vals[i].getName()] = op++; - - DEBUG(o << " // Var: begin = " << beginBitInVar - << ", end = " << endBitInVar - << "; Inst: begin = " << beginBitInInst - << ", end = " << endBitInInst << "\n"); - - if (continuous) { - DEBUG(o << " // continuous: op" << OpOrder[Vals[i].getName()] - << "\n"); - - // Mask off the right bits - // Low mask (ie. shift, if necessary) - assert(endBitInVar >= 0 && "Negative shift amount in masking!"); - if (endBitInVar != 0) { - o << " op" << OpOrder[Vals[i].getName()] - << " >>= " << endBitInVar << ";\n"; - beginBitInVar -= endBitInVar; - endBitInVar = 0; - } - - // High mask - o << " op" << OpOrder[Vals[i].getName()] - << " &= (1<<" << beginBitInVar+1 << ") - 1;\n"; - - // Shift the value to the correct place (according to place in inst) - assert(endBitInInst >= 0 && "Negative shift amount in inst position!"); - if (endBitInInst != 0) - o << " op" << OpOrder[Vals[i].getName()] - << " <<= " << endBitInInst << ";\n"; - - // Just OR in the result - o << " Value |= op" << OpOrder[Vals[i].getName()] << ";\n"; - } - - // otherwise, will be taken care of in the loop below using this - // value: - OpContinuous[Vals[i].getName()] = continuous; - } - } - } - - for (unsigned f = 0, e = Vals.size(); f != e; ++f) { - if (Vals[f].getPrefix()) { - BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue(); - - // Scan through the field looking for bit initializers of the current - // variable... - for (int i = FieldInitializer->getNumBits()-1; i >= 0; --i) { - if (BitInit *BI = dynamic_cast<BitInit*>(FieldInitializer->getBit(i))) - { - DEBUG(o << " // bit init: f: " << f << ", i: " << i << "\n"); - } else if (UnsetInit *UI = - dynamic_cast<UnsetInit*>(FieldInitializer->getBit(i))) { - DEBUG(o << " // unset init: f: " << f << ", i: " << i << "\n"); - } else if (VarBitInit *VBI = - dynamic_cast<VarBitInit*>(FieldInitializer->getBit(i))) { - TypedInit *TI = VBI->getVariable(); - if (VarInit *VI = dynamic_cast<VarInit*>(TI)) { - // If the bits of the field are laid out consecutively in the - // instruction, then instead of separately ORing in bits, just - // mask and shift the entire field for efficiency. - if (OpContinuous[VI->getName()]) { - // already taken care of in the loop above, thus there is no - // need to individually OR in the bits - - // for debugging, output the regular version anyway, commented - DEBUG(o << " // Value |= getValueBit(op" - << OpOrder[VI->getName()] << ", " << VBI->getBitNum() - << ")" << " << " << i << ";\n"); - } else { - o << " Value |= getValueBit(op" << OpOrder[VI->getName()] - << ", " << VBI->getBitNum() - << ")" << " << " << i << ";\n"; - } - } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) { - // FIXME: implement this! - o << "FIELD INIT not implemented yet!\n"; - } else { - o << "Error: UNIMPLEMENTED\n"; - } - } - } - } - } - - o << " break;\n" - << " }\n"; - } - - o << " default:\n" - << " std::cerr << \"Not supported instr: \" << MI << \"\\n\";\n" - << " abort();\n" - << " }\n" - << " return Value;\n" - << "}\n"; -} diff --git a/support/tools/TableGen/CodeEmitterGen.h b/support/tools/TableGen/CodeEmitterGen.h deleted file mode 100644 index 4b87da5067..0000000000 --- a/support/tools/TableGen/CodeEmitterGen.h +++ /dev/null @@ -1,24 +0,0 @@ -//===- CodeEmitterGen.h - Code Emitter Generator ----------------*- C++ -*-===// -// -// FIXME: document -// -//===----------------------------------------------------------------------===// - -#ifndef CODEMITTERGEN_H -#define CODEMITTERGEN_H - -#include "TableGenBackend.h" - -class CodeEmitterGen : public TableGenBackend { - RecordKeeper &Records; -public: - CodeEmitterGen(RecordKeeper &R) : Records(R) {} - - // run - Output the code emitter - void run(std::ostream &o); -private: - void emitMachineOpEmitter(std::ostream &o, const std::string &Namespace); - void emitGetValueBit(std::ostream &o, const std::string &Namespace); -}; - -#endif diff --git a/support/tools/TableGen/CodeGenWrappers.cpp b/support/tools/TableGen/CodeGenWrappers.cpp deleted file mode 100644 index 61c3abc297..0000000000 --- a/support/tools/TableGen/CodeGenWrappers.cpp +++ /dev/null @@ -1,89 +0,0 @@ -//===- CodeGenWrappers.cpp - Code Generation Class Wrappers -----*- C++ -*-===// -// -// These classes wrap target description classes used by the various code -// generation TableGen backends. This makes it easier to access the data and -// provides a single place that needs to check it for validity. All of these -// classes throw exceptions on error conditions. -// -//===----------------------------------------------------------------------===// - -#include "CodeGenWrappers.h" -#include "Record.h" - -/// getValueType - Return the MCV::ValueType that the specified TableGen record -/// corresponds to. -MVT::ValueType getValueType(Record *Rec) { - return (MVT::ValueType)Rec->getValueAsInt("Value"); -} - -std::string getName(MVT::ValueType T) { - switch (T) { - case MVT::Other: return "UNKNOWN"; - case MVT::i1: return "i1"; - case MVT::i8: return "i8"; - case MVT::i16: return "i16"; - case MVT::i32: return "i32"; - case MVT::i64: return "i64"; - case MVT::i128: return "i128"; - case MVT::f32: return "f32"; - case MVT::f64: return "f64"; - case MVT::f80: return "f80"; - case MVT::f128: return "f128"; - case MVT::isVoid:return "void"; - default: assert(0 && "ILLEGAL VALUE TYPE!"); return ""; - } -} - -std::string getEnumName(MVT::ValueType T) { - switch (T) { - case MVT::Other: return "Other"; - case MVT::i1: return "i1"; - case MVT::i8: return "i8"; - case MVT::i16: return "i16"; - case MVT::i32: return "i32"; - case MVT::i64: return "i64"; - case MVT::i128: return "i128"; - case MVT::f32: return "f32"; - case MVT::f64: return "f64"; - case MVT::f80: return "f80"; - case MVT::f128: return "f128"; - case MVT::isVoid:return "isVoid"; - default: assert(0 && "ILLEGAL VALUE TYPE!"); return ""; - } -} - - -std::ostream &operator<<(std::ostream &OS, MVT::ValueType T) { - return OS << getName(T); -} - - - -/// getTarget - Return the current instance of the Target class. -/// -CodeGenTarget::CodeGenTarget() { - std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target"); - if (Targets.size() != 1) - throw std::string("ERROR: Multiple subclasses of Target defined!"); - TargetRec = Targets[0]; - - // Read in all of the CalleeSavedRegisters... - ListInit *LI = TargetRec->getValueAsListInit("CalleeSavedRegisters"); - for (unsigned i = 0, e = LI->getSize(); i != e; ++i) - if (DefInit *DI = dynamic_cast<DefInit*>(LI->getElement(i))) - CalleeSavedRegisters.push_back(DI->getDef()); - else - throw "Target: " + TargetRec->getName() + - " expected register definition in CalleeSavedRegisters list!"; - - PointerType = getValueType(TargetRec->getValueAsDef("PointerType")); -} - - -const std::string &CodeGenTarget::getName() const { - return TargetRec->getName(); -} - -Record *CodeGenTarget::getInstructionSet() const { - return TargetRec->getValueAsDef("InstructionSet"); -} diff --git a/support/tools/TableGen/CodeGenWrappers.h b/support/tools/TableGen/CodeGenWrappers.h deleted file mode 100644 index 00ca3fcc60..0000000000 --- a/support/tools/TableGen/CodeGenWrappers.h +++ /dev/null @@ -1,56 +0,0 @@ -//===- CodeGenWrappers.h - Code Generation Class Wrappers -------*- C++ -*-===// -// -// These classes wrap target description classes used by the various code -// generation TableGen backends. This makes it easier to access the data and -// provides a single place that needs to check it for validity. All of these -// classes throw exceptions on error conditions. -// -//===----------------------------------------------------------------------===// - -#ifndef CODEGENWRAPPERS_H -#define CODEGENWRAPPERS_H - -#include "llvm/CodeGen/ValueTypes.h" -#include <iosfwd> -#include <string> -#include <vector> -class Record; -class RecordKeeper; - -/// getValueType - Return the MVT::ValueType that the specified TableGen record -/// corresponds to. -MVT::ValueType getValueType(Record *Rec); - -std::ostream &operator<<(std::ostream &OS, MVT::ValueType T); -std::string getName(MVT::ValueType T); -std::string getEnumName(MVT::ValueType T); - - -/// CodeGenTarget - This class corresponds to the Target class in the .td files. -/// -class CodeGenTarget { - Record *TargetRec; - std::vector<Record*> CalleeSavedRegisters; - MVT::ValueType PointerType; - -public: - CodeGenTarget(); - - Record *getTargetRecord() const { return TargetRec; } - const std::string &getName() const; - - const std::vector<Record*> &getCalleeSavedRegisters() const { - return CalleeSavedRegisters; - } - - MVT::ValueType getPointerType() const { return PointerType; } - - // getInstructionSet - Return the InstructionSet object... - Record *getInstructionSet() const; - - // getInstructionSet - Return the CodeGenInstructionSet object for this - // target, lazily reading it from the record keeper as needed. - // CodeGenInstructionSet *getInstructionSet - -}; - -#endif diff --git a/support/tools/TableGen/FileLexer.l b/support/tools/TableGen/FileLexer.l deleted file mode 100644 index 64ed4c625a..0000000000 --- a/support/tools/TableGen/FileLexer.l +++ /dev/null @@ -1,222 +0,0 @@ -/*===-- FileLexer.l - Scanner for TableGen Files ----------------*- C++ -*-===// -// -// This file defines a simple flex scanner for TableGen files. This is pretty -// straight-forward, except for the magic to handle file inclusion. -// -//===----------------------------------------------------------------------===*/ - -%option prefix="File" -%option yylineno -%option nostdinit -%option never-interactive -%option batch -%option nodefault -%option 8bit -%option outfile="Lexer.cpp" -%option ecs -%option noreject -%option noyymore - -%x comment - -%{ -#include "Record.h" -typedef std::pair<Record*, std::vector<Init*>*> SubClassRefTy; -#include "FileParser.h" - -// Global variable recording the location of the include directory -std::string IncludeDirectory; - -// ParseInt - This has to handle the special case of binary numbers 0b0101 -static int ParseInt(const char *Str) { - if (Str[0] == '0' && Str[1] == 'b') - return strtol(Str+2, 0, 2); - return strtol(Str, 0, 0); -} - -static int CommentDepth = 0; - -struct IncludeRec { - std::string Filename; - FILE *File; - unsigned LineNo; - YY_BUFFER_STATE Buffer; - - IncludeRec(const std::string &FN, FILE *F) - : Filename(FN), File(F), LineNo(0){ - } -}; - -static std::vector<IncludeRec> IncludeStack; - - -std::ostream &err() { - if (IncludeStack.empty()) - return std::cerr << "At end of input: "; - - for (unsigned i = 0, e = IncludeStack.size()-1; i != e; ++i) - std::cerr << "Included from " << IncludeStack[i].Filename << ":" - << IncludeStack[i].LineNo << ":\n"; - return std::cerr << "Parsing " << IncludeStack.back().Filename << ":" - << Filelineno << ": "; -} - - -int Fileparse(); - -// -// Function: ParseFile() -// -// Description: -// This function begins the parsing of the specified tablegen file. -// -// Inputs: -// Filename - A string containing the name of the file to parse. -// IncludeDir - A string containing the directory from which include -// files can be found. -// -void ParseFile(const std::string &Filename, const std::string & IncludeDir) { - FILE *F = stdin; - if (Filename != "-") { - F = fopen(Filename.c_str(), "r"); - - if (F == 0) { - std::cerr << "Could not open input file '" + Filename + "'!\n"; - exit (1); - } - IncludeStack.push_back(IncludeRec(Filename, F)); - } else { - IncludeStack.push_back(IncludeRec("<stdin>", stdin)); - } - - // - // Record the location of the include directory so that the lexer can find - // it later. - // - IncludeDirectory = IncludeDir; - - Filein = F; - Filelineno = 1; - Fileparse(); - Filein = stdin; -} - -// HandleInclude - This function is called when an include directive is -// encountered in the input stream... -static void HandleInclude(const char *Buffer) { - unsigned Length = yyleng; - assert(Buffer[Length-1] == '"'); - Buffer += strlen("include "); - Length -= strlen("include "); - while (*Buffer != '"') { - ++Buffer; - --Length; - } - assert(Length >= 2 && "Double quotes not found?"); - std::string Filename(Buffer+1, Buffer+Length-1); - //std::cerr << "Filename = '" << Filename << "'\n"; - - // Save the line number and lex buffer of the includer... - IncludeStack.back().LineNo = Filelineno; - IncludeStack.back().Buffer = YY_CURRENT_BUFFER; - - // Open the new input file... - yyin = fopen(Filename.c_str(), "r"); - if (yyin == 0) { - // - // If we couldn't find the file in the current directory, look for it in - // the include directories. - // - // NOTE: - // Right now, there is only one directory. We need to eventually add - // support for more. - // - Filename = IncludeDirectory + "/" + Filename; - yyin = fopen(Filename.c_str(), "r"); - if (yyin == 0) { - err() << "Could not find include file '" << Filename << "'!\n"; - abort(); - } - } - - // Add the file to our include stack... - IncludeStack.push_back(IncludeRec(Filename, yyin)); - Filelineno = 1; // Reset line numbering... - //yyrestart(yyin); // Start lexing the new file... - - yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); -} - - -// yywrap - This is called when the lexer runs out of input in one of the files. -// Switch back to an includer if an includee has run out of input. -// -extern "C" -int yywrap() { - if (IncludeStack.back().File != stdin) - fclose(IncludeStack.back().File); - IncludeStack.pop_back(); - if (IncludeStack.empty()) return 1; // Top-level file is done. - - // Otherwise, we need to switch back to a file which included the current one. - Filelineno = IncludeStack.back().LineNo; // Restore current line number - yy_switch_to_buffer(IncludeStack.back().Buffer); - return 0; -} - -%} - -Comment \/\/.* - -Identifier [a-zA-Z_][0-9a-zA-Z_]* -Integer [-+]?[0-9]+|0x[0-9a-fA-F]+|0b[01]+ -CodeFragment \[\{([^}]+|\}[^\]])*\}\] -StringVal \"[^"]*\" -IncludeStr include[ \t\n]+\"[^"]*\" - -%% - -{Comment} { /* Ignore comments */ } - -{IncludeStr} { HandleInclude(yytext); } -{CodeFragment} { Filelval.StrVal = new std::string(yytext+2, yytext+yyleng-2); - return CODEFRAGMENT; } - -int { return INT; } -bit { return BIT; } -bits { return BITS; } -string { return STRING; } -list { return LIST; } -code { return CODE; } -dag { return DAG; } - -class { return CLASS; } -def { return DEF; } -field { return FIELD; } -let { return LET; } -in { return IN; } - -{Identifier} { Filelval.StrVal = new std::string(yytext, yytext+yyleng); - return ID; } -${Identifier} { Filelval.StrVal = new std::string(yytext+1, yytext+yyleng); - return VARNAME; } - -{StringVal} { Filelval.StrVal = new std::string(yytext+1, yytext+yyleng-1); - return STRVAL; } - -{Integer} { Filelval.IntVal = ParseInt(Filetext); return INTVAL; } - -[ \t\n]+ { /* Ignore whitespace */ } - - -"/*" { BEGIN(comment); CommentDepth++; } -<comment>[^*/]* /* eat anything that's not a '*' or '/' */ -<comment>"*"+[^*/]* /* eat up '*'s not followed by '/'s */ -<comment>"/*" { ++CommentDepth; } -<comment>"/"+[^*]* /* eat up /'s not followed by *'s */ -<comment>"*"+"/" { if (!--CommentDepth) { BEGIN(INITIAL); } } -<comment><<EOF>> { err() << "Unterminated comment!\n"; abort(); } - -. { return Filetext[0]; } - -%% diff --git a/support/tools/TableGen/FileParser.y b/support/tools/TableGen/FileParser.y deleted file mode 100644 index 728fcf222c..0000000000 --- a/support/tools/TableGen/FileParser.y +++ /dev/null @@ -1,510 +0,0 @@ -//===-- FileParser.y - Parser for TableGen files ----------------*- C++ -*-===// -// -// This file implements the bison parser for Table Generator files... -// -//===------------------------------------------------------------------------=// - -%{ -#include "Record.h" -#include "Support/StringExtras.h" -#include <algorithm> -#include <cstdio> -#define YYERROR_VERBOSE 1 - -int yyerror(const char *ErrorMsg); -int yylex(); -extern int Filelineno; -static Record *CurRec = 0; - -typedef std::pair<Record*, std::vector<Init*>*> SubClassRefTy; - -struct LetRecord { - std::string Name; - std::vector<unsigned> Bits; - Init *Value; - bool HasBits; - LetRecord(const std::string &N, std::vector<unsigned> *B, Init *V) - : Name(N), Value(V), HasBits(B != 0) { - if (HasBits) Bits = *B; - } -}; - -static std::vector<std::vector<LetRecord> > LetStack; - - -extern std::ostream &err(); - -static void addValue(const RecordVal &RV) { - if (RecordVal *ERV = CurRec->getValue(RV.getName())) { - // The value already exists in the class, treat this as a set... - if (ERV->setValue(RV.getValue())) { - err() << "New definition of '" << RV.getName() << "' of type '" - << *RV.getType() << "' is incompatible with previous " - << "definition of type '" << *ERV->getType() << "'!\n"; - abort(); - } - } else { - CurRec->addValue(RV); - } -} - -static void addSuperClass(Record *SC) { - if (CurRec->isSubClassOf(SC)) { - err() << "Already subclass of '" << SC->getName() << "'!\n"; - abort(); - } - CurRec->addSuperClass(SC); -} - -static void setValue(const std::string &ValName, - std::vector<unsigned> *BitList, Init *V) { - if (!V) return ; - - RecordVal *RV = CurRec->getValue(ValName); - if (RV == 0) { - err() << "Value '" << ValName << "' unknown!\n"; - abort(); - } - - // If we are assigning to a subset of the bits in the value... then we must be - // assigning to a field of BitsRecTy, which must have a BitsInit - // initializer... - // - if (BitList) { - BitsInit *CurVal = dynamic_cast<BitsInit*>(RV->getValue()); - if (CurVal == 0) { - err() << "Value '" << ValName << "' is not a bits type!\n"; - abort(); - } - - // Convert the incoming value to a bits type of the appropriate size... - Init *BI = V->convertInitializerTo(new BitsRecTy(BitList->size())); - if (BI == 0) { - V->convertInitializerTo(new BitsRecTy(BitList->size())); - err() << "Initializer '" << *V << "' not compatible with bit range!\n"; - abort(); - } - - // We should have a BitsInit type now... - assert(dynamic_cast<BitsInit*>(BI) != 0 || &(std::cerr << *BI) == 0); - BitsInit *BInit = (BitsInit*)BI; - - BitsInit *NewVal = new BitsInit(CurVal->getNumBits()); - - // Loop over bits, assigning values as appropriate... - for (unsigned i = 0, e = BitList->size(); i != e; ++i) { - unsigned Bit = (*BitList)[i]; - if (NewVal->getBit(Bit)) { - err() << "Cannot set bit #" << Bit << " of value '" << ValName - << "' more than once!\n"; - abort(); - } - NewVal->setBit(Bit, BInit->getBit(i)); - } - - for (unsigned i = 0, e = CurVal->getNumBits(); i != e; ++i) - if (NewVal->getBit(i) == 0) - NewVal->setBit(i, CurVal->getBit(i)); - - V = NewVal; - } - - if (RV->setValue(V)) { - err() << "Value '" << ValName << "' of type '" << *RV->getType() - << "' is incompatible with initializer '" << *V << "'!\n"; - abort(); - } -} - -static void addSubClass(Record *SC, const std::vector<Init*> &TemplateArgs) { - // Add all of the values in the subclass into the current class... - const std::vector<RecordVal> &Vals = SC->getValues(); - for (unsigned i = 0, e = Vals.size(); i != e; ++i) - addValue(Vals[i]); - - const std::vector<std::string> &TArgs = SC->getTemplateArgs(); - - // Ensure that an appropriate number of template arguments are specified... - if (TArgs.size() < TemplateArgs.size()) { - err() << "ERROR: More template args specified than expected!\n"; - abort(); - } else { // This class expects template arguments... - // Loop over all of the template arguments, setting them to the specified - // value or leaving them as the default as necessary. - for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { - if (i < TemplateArgs.size()) { // A value is specified for this temp-arg? - // Set it now. - setValue(TArgs[i], 0, TemplateArgs[i]); - } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) { - err() << "ERROR: Value not specified for template argument #" - << i << " (" << TArgs[i] << ") of subclass '" << SC->getName() - << "'!\n"; - abort(); - } - } - } - - - // Since everything went well, we can now set the "superclass" list for the - // current record. - const std::vector<Record*> &SCs = SC->getSuperClasses(); - for (unsigned i = 0, e = SCs.size(); i != e; ++i) - addSuperClass(SCs[i]); - addSuperClass(SC); -} - - -%} - -%union { - std::string *StrVal; - int IntVal; - RecTy *Ty; - Init *Initializer; - std::vector<Init*> *FieldList; - std::vector<unsigned>*BitList; - Record *Rec; - SubClassRefTy *SubClassRef; - std::vector<SubClassRefTy> *SubClassList; - std::vector<std::pair<Init*, std::string> > *DagValueList; -}; - -%token INT BIT STRING BITS LIST CODE DAG CLASS DEF FIELD LET IN -%token <IntVal> INTVAL -%token <StrVal> ID VARNAME STRVAL CODEFRAGMENT - -%type <Ty> Type -%type <Rec> ClassInst DefInst Object ObjectBody ClassID - -%type <SubClassRef> SubClassRef -%type <SubClassList> ClassList ClassListNE -%type <IntVal> OptPrefix -%type <Initializer> Value OptValue -%type <DagValueList> DagArgList DagArgListNE -%type <FieldList> ValueList ValueListNE -%type <BitList> BitList OptBitList RBitList -%type <StrVal> Declaration OptID OptVarName - -%start File -%% - -ClassID : ID { - $$ = Records.getClass(*$1); - if ($$ == 0) { - err() << "Couldn't find class '" << *$1 << "'!\n"; - abort(); - } - delete $1; - }; - - -// TableGen types... -Type : STRING { // string type - $$ = new StringRecTy(); - } | BIT { // bit type - $$ = new BitRecTy(); - } | BITS '<' INTVAL '>' { // bits<x> type - $$ = new BitsRecTy($3); - } | INT { // int type - $$ = new IntRecTy(); - } | LIST '<' Type '>' { // list<x> type - $$ = new ListRecTy($3); - } | CODE { // code type - $$ = new CodeRecTy(); - } | DAG { // dag type - $$ = new DagRecTy(); - } | ClassID { // Record Type - $$ = new RecordRecTy($1); - }; - -OptPrefix : /*empty*/ { $$ = 0; } | FIELD { $$ = 1; }; - -OptValue : /*empty*/ { $$ = 0; } | '=' Value { $$ = $2; }; - -Value : INTVAL { - $$ = new IntInit($1); - } | STRVAL { - $$ = new StringInit(*$1); - delete $1; - } | CODEFRAGMENT { - $$ = new CodeInit(*$1); - delete $1; - } | '?' { - $$ = new UnsetInit(); - } | '{' ValueList '}' { - BitsInit *Init = new BitsInit($2->size()); - for (unsigned i = 0, e = $2->size(); i != e; ++i) { - struct Init *Bit = (*$2)[i]->convertInitializerTo(new BitRecTy()); - if (Bit == 0) { - err() << "Element #" << i << " (" << *(*$2)[i] - << ") is not convertable to a bit!\n"; - abort(); - } - Init->setBit($2->size()-i-1, Bit); - } - $$ = Init; - delete $2; - } | ID { - if (const RecordVal *RV = (CurRec ? CurRec->getValue(*$1) : 0)) { - $$ = new VarInit(*$1, RV->getType()); - } else if (Record *D = Records.getDef(*$1)) { - $$ = new DefInit(D); - } else { - err() << "Variable not defined: '" << *$1 << "'!\n"; - abort(); - } - - delete $1; - } | Value '{' BitList '}' { - $$ = $1->convertInitializerBitRange(*$3); - if ($$ == 0) { - err() << "Invalid bit range for value '" << *$1 << "'!\n"; - abort(); - } - delete $3; - } | '[' ValueList ']' { - $$ = new ListInit(*$2); - delete $2; - } | Value '.' ID { - if (!$1->getFieldType(*$3)) { - err() << "Cannot access field '" << *$3 << "' of value '" << *$1 << "!\n"; - abort(); - } - $$ = new FieldInit($1, *$3); - delete $3; - } | '(' ID DagArgList ')' { - Record *D = Records.getDef(*$2); - if (D == 0) { - err() << "Invalid def '" << *$2 << "'!\n"; - abort(); - } - $$ = new DagInit(D, *$3); - delete $2; delete $3; - }; - -OptVarName : /* empty */ { - $$ = new std::string(); - } - | ':' VARNAME { - $$ = $2; - }; - -DagArgListNE : Value OptVarName { - $$ = new std::vector<std::pair<Init*, std::string> >(); - $$->push_back(std::make_pair($1, *$2)); - delete $2; - } - | DagArgListNE ',' Value OptVarName { - $1->push_back(std::make_pair($3, *$4)); - delete $4; - $$ = $1; - }; - -DagArgList : /*empty*/ { - $$ = new std::vector<std::pair<Init*, std::string> >(); - } - | DagArgListNE { $$ = $1; }; - - -RBitList : INTVAL { - $$ = new std::vector<unsigned>(); - $$->push_back($1); - } | INTVAL '-' INTVAL { - if ($1 < $3 || $1 < 0 || $3 < 0) { - err() << "Invalid bit range: " << $1 << "-" << $3 << "!\n"; - abort(); - } - $$ = new std::vector<unsigned>(); - for (int i = $1; i >= $3; --i) - $$->push_back(i); - } | INTVAL INTVAL { - $2 = -$2; - if ($1 < $2 || $1 < 0 || $2 < 0) { - err() << "Invalid bit range: " << $1 << "-" << $2 << "!\n"; - abort(); - } - $$ = new std::vector<unsigned>(); - for (int i = $1; i >= $2; --i) - $$->push_back(i); - } | RBitList ',' INTVAL { - ($$=$1)->push_back($3); - } | RBitList ',' INTVAL '-' INTVAL { - if ($3 < $5 || $3 < 0 || $5 < 0) { - err() << "Invalid bit range: " << $3 << "-" << $5 << "!\n"; - abort(); - } - $$ = $1; - for (int i = $3; i >= $5; --i) - $$->push_back(i); - } | RBitList ',' INTVAL INTVAL { - $4 = -$4; - if ($3 < $4 || $3 < 0 || $4 < 0) { - err() << "Invalid bit range: " << $3 << "-" << $4 << "!\n"; - abort(); - } - $$ = $1; - for (int i = $3; i >= $4; --i) - $$->push_back(i); - }; - -BitList : RBitList { $$ = $1; std::reverse($1->begin(), $1->end()); }; - -OptBitList : /*empty*/ { $$ = 0; } | '{' BitList '}' { $$ = $2; }; - - - -ValueList : /*empty*/ { - $$ = new std::vector<Init*>(); - } | ValueListNE { - $$ = $1; - }; - -ValueListNE : Value { - $$ = new std::vector<Init*>(); - $$->push_back($1); - } | ValueListNE ',' Value { - ($$ = $1)->push_back($3); - }; - -Declaration : OptPrefix Type ID OptValue { - addValue(RecordVal(*$3, $2, $1)); - setValue(*$3, 0, $4); - $$ = $3; -}; - -BodyItem : Declaration ';' { - delete $1; -} | LET ID OptBitList '=' Value ';' { - setValue(*$2, $3, $5); - delete $2; - delete $3; -}; - -BodyList : /*empty*/ | BodyList BodyItem; -Body : ';' | '{' BodyList '}'; - -SubClassRef : ClassID { - $$ = new SubClassRefTy($1, new std::vector<Init*>()); - } | ClassID '<' ValueListNE '>' { - $$ = new SubClassRefTy($1, $3); - }; - -ClassListNE : SubClassRef { - $$ = new std::vector<SubClassRefTy>(); - $$->push_back(*$1); - delete $1; - } - | ClassListNE ',' SubClassRef { - ($$=$1)->push_back(*$3); - delete $3; - }; - -ClassList : /*empty */ { - $$ = new std::vector<SubClassRefTy>(); - } - | ':' ClassListNE { - $$ = $2; - }; - -DeclListNE : Declaration { - CurRec->addTemplateArg(*$1); - delete $1; -} | DeclListNE ',' Declaration { - CurRec->addTemplateArg(*$3); - delete $3; -}; - -TemplateArgList : '<' DeclListNE '>' {}; -OptTemplateArgList : /*empty*/ | TemplateArgList; - -OptID : ID { $$ = $1; } | /*empty*/ { $$ = new std::string(); }; - -ObjectBody : OptID { - static unsigned AnonCounter = 0; - if ($1->empty()) - *$1 = "anonymous."+utostr(AnonCounter++); - CurRec = new Record(*$1); - delete $1; - } OptTemplateArgList ClassList { - for (unsigned i = 0, e = $4->size(); i != e; ++i) { - addSubClass((*$4)[i].first, *(*$4)[i].second); - // Delete the template arg values for the class - delete (*$4)[i].second; - } - - // Process any variables on the set stack... - for (unsigned i = 0, e = LetStack.size(); i != e; ++i) - for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j) - setValue(LetStack[i][j].Name, - LetStack[i][j].HasBits ? &LetStack[i][j].Bits : 0, - LetStack[i][j].Value); - } Body { - CurRec->resolveReferences(); - - // Now that all of the references have been resolved, we can delete template - // arguments for superclasses, so they don't pollute our record, and so that - // their names won't conflict with later uses of the name... - for (unsigned i = 0, e = $4->size(); i != e; ++i) { - Record *SuperClass = (*$4)[i].first; - for (unsigned i = 0, e = SuperClass->getTemplateArgs().size(); i != e; ++i) - CurRec->removeValue(SuperClass->getTemplateArgs()[i]); - } - delete $4; // Delete the class list... - - $$ = CurRec; - CurRec = 0; -}; - -ClassInst : CLASS ObjectBody { - if (Records.getClass($2->getName())) { - err() << "Class '" << $2->getName() << "' already defined!\n"; - abort(); - } - Records.addClass($$ = $2); -}; - -DefInst : DEF ObjectBody { - if (!$2->getTemplateArgs().empty()) { - err() << "Def '" << $2->getName() - << "' is not permitted to have template arguments!\n"; - abort(); - } - // If ObjectBody has template arguments, it's an error. - if (Records.getDef($2->getName())) { - err() << "Def '" << $2->getName() << "' already defined!\n"; - abort(); - } - Records.addDef($$ = $2); -}; - - -Object : ClassInst | DefInst; - -LETItem : ID OptBitList '=' Value { - LetStack.back().push_back(LetRecord(*$1, $2, $4)); - delete $1; delete $2; -}; - -LETList : LETItem | LETList ',' LETItem; - -// LETCommand - A 'LET' statement start... -LETCommand : LET { LetStack.push_back(std::vector<LetRecord>()); } LETList IN; - -// Support Set commands wrapping objects... both with and without braces. -Object : LETCommand '{' ObjectList '}' { - LetStack.pop_back(); - } - | LETCommand Object { - LetStack.pop_back(); - }; - -ObjectList : Object {} | ObjectList Object {}; - -File : ObjectList {}; - -%% - -int yyerror(const char *ErrorMsg) { - err() << "Error parsing: " << ErrorMsg << "\n"; - abort(); -} diff --git a/support/tools/TableGen/InstrInfoEmitter.cpp b/support/tools/TableGen/InstrInfoEmitter.cpp deleted file mode 100644 index c794cd0441..0000000000 --- a/support/tools/TableGen/InstrInfoEmitter.cpp +++ /dev/null @@ -1,160 +0,0 @@ -//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===// -// -// This tablegen backend is responsible for emitting a description of the target -// instruction set for the code generator. -// -//===----------------------------------------------------------------------===// - -#include "InstrInfoEmitter.h" -#include "CodeGenWrappers.h" -#include "Record.h" - -// runEnums - Print out enum values for all of the instructions. -void InstrInfoEmitter::runEnums(std::ostream &OS) { - std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); - - if (Insts.size() == 0) - throw std::string("No 'Instruction' subclasses defined!"); - - std::string Namespace = Insts[0]->getValueAsString("Namespace"); - - EmitSourceFileHeader("Target Instruction Enum Values", OS); - - if (!Namespace.empty()) - OS << "namespace " << Namespace << " {\n"; - OS << " enum {\n"; - - CodeGenTarget Target; - - // We must emit the PHI opcode first... - Record *InstrInfo = Target.getInstructionSet(); - Record *PHI = InstrInfo->getValueAsDef("PHIInst"); - - OS << " " << PHI->getName() << ", \t// 0 (fixed for all targets)\n"; - - // Print out the rest of the instructions now... - for (unsigned i = 0, e = Insts.size(); i != e; ++i) - if (Insts[i] != PHI) - OS << " " << Insts[i]->getName() << ", \t// " << i+1 << "\n"; - - OS << " };\n"; - if (!Namespace.empty()) - OS << "}\n"; -} - -void InstrInfoEmitter::printDefList(ListInit *LI, const std::string &Name, - std::ostream &OS) const { - OS << "static const unsigned " << Name << "[] = { "; - for (unsigned j = 0, e = LI->getSize(); j != e; ++j) - if (DefInit *DI = dynamic_cast<DefInit*>(LI->getElement(j))) - OS << getQualifiedName(DI->getDef()) << ", "; - else - throw "Illegal value in '" + Name + "' list!"; - OS << "0 };\n"; -} - - -// run - Emit the main instruction description records for the target... -void InstrInfoEmitter::run(std::ostream &OS) { - EmitSourceFileHeader("Target Instruction Descriptors", OS); - CodeGenTarget Target; - const std::string &TargetName = Target.getName(); - Record *InstrInfo = Target.getInstructionSet(); - Record *PHI = InstrInfo->getValueAsDef("PHIInst"); - - std::vector<Record*> Instructions = - Records.getAllDerivedDefinitions("Instruction"); - - // Emit all of the instruction's implicit uses and defs... - for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { - Record *Inst = Instructions[i]; - ListInit *LI = Inst->getValueAsListInit("Uses"); - if (LI->getSize()) printDefList(LI, Inst->getName()+"ImpUses", OS); - LI = Inst->getValueAsListInit("Defs"); - if (LI->getSize()) printDefList(LI, Inst->getName()+"ImpDefs", OS); - } - - OS << "\nstatic const TargetInstrDescriptor " << TargetName - << "Insts[] = {\n"; - emitRecord(PHI, 0, InstrInfo, OS); - - for (unsigned i = 0, e = Instructions.size(); i != e; ++i) - if (Instructions[i] != PHI) - emitRecord(Instructions[i], i+1, InstrInfo, OS); - OS << "};\n"; -} - -void InstrInfoEmitter::emitRecord(Record *R, unsigned Num, Record *InstrInfo, - std::ostream &OS) { - OS << " { \"" << R->getValueAsString("Name") - << "\",\t-1, -1, 0, false, 0, 0, 0, 0"; - - // Emit all of the target indepedent flags... - if (R->getValueAsBit("isReturn")) OS << "|M_RET_FLAG"; - if (R->getValueAsBit("isBranch")) OS << "|M_BRANCH_FLAG"; - if (R->getValueAsBit("isCall" )) OS << "|M_CALL_FLAG"; - if (R->getValueAsBit("isTwoAddress")) OS << "|M_2_ADDR_FLAG"; - if (R->getValueAsBit("isTerminator")) OS << "|M_TERMINATOR_FLAG"; - OS << ", 0"; - - // Emit all of the target-specific flags... - ListInit *LI = InstrInfo->getValueAsListInit("TSFlagsFields"); - ListInit *Shift = InstrInfo->getValueAsListInit("TSFlagsShifts"); - if (LI->getSize() != Shift->getSize()) - throw "Lengths of " + InstrInfo->getName() + - ":(TargetInfoFields, TargetInfoPositions) must be equal!"; - - for (unsigned i = 0, e = LI->getSize(); i != e; ++i) - emitShiftedValue(R, dynamic_cast<StringInit*>(LI->getElement(i)), - dynamic_cast<IntInit*>(Shift->getElement(i)), OS); - - OS << ", "; - - // Emit the implicit uses and defs lists... - LI = R->getValueAsListInit("Uses"); - if (!LI->getSize()) - OS << "0, "; - else - OS << R->getName() << "ImpUses, "; - - LI = R->getValueAsListInit("Defs"); - if (!LI->getSize()) - OS << "0 "; - else - OS << R->getName() << "ImpDefs "; - - OS << " }, // Inst #" << Num << " = " << R->getName() << "\n"; -} - -void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val, - IntInit *ShiftInt, std::ostream &OS) { - if (Val == 0 || ShiftInt == 0) - throw std::string("Illegal value or shift amount in TargetInfo*!"); - RecordVal *RV = R->getValue(Val->getValue()); - int Shift = ShiftInt->getValue(); - - if (RV == 0 || RV->getValue() == 0) - throw R->getName() + " doesn't have a field named '" + Val->getValue()+"'!"; - - Init *Value = RV->getValue(); - if (BitInit *BI = dynamic_cast<BitInit*>(Value)) { - if (BI->getValue()) OS << "|(1<<" << Shift << ")"; - return; - } else if (BitsInit *BI = dynamic_cast<BitsInit*>(Value)) { - // Convert the Bits to an integer to print... - Init *I = BI->convertInitializerTo(new IntRecTy()); - if (I) - if (IntInit *II = dynamic_cast<IntInit*>(I)) { - if (II->getValue()) - OS << "|(" << II->getValue() << "<<" << Shift << ")"; - return; - } - - } else if (IntInit *II = dynamic_cast<IntInit*>(Value)) { - if (II->getValue()) OS << "|(" << II->getValue() << "<<" << Shift << ")"; - return; - } - - std::cerr << "Unhandled initializer: " << *Val << "\n"; - throw "In record '" + R->getName() + "' for TSFlag emission."; -} diff --git a/support/tools/TableGen/InstrInfoEmitter.h b/support/tools/TableGen/InstrInfoEmitter.h deleted file mode 100644 index 400c0db16c..0000000000 --- a/support/tools/TableGen/InstrInfoEmitter.h +++ /dev/null @@ -1,34 +0,0 @@ -//===- InstrInfoEmitter.h - Generate a Instruction Set Desc. ----*- C++ -*-===// -// -// This tablegen backend is responsible for emitting a description of the target -// instruction set for the code generator. -// -//===----------------------------------------------------------------------===// - -#ifndef INSTRINFO_EMITTER_H -#define INSTRINFO_EMITTER_H - -#include "TableGenBackend.h" -class StringInit; -class IntInit; -class ListInit; - -class InstrInfoEmitter : public TableGenBackend { - RecordKeeper &Records; -public: - InstrInfoEmitter(RecordKeeper &R) : Records(R) {} - - // run - Output the instruction set description, returning true on failure. - void run(std::ostream &OS); - - // runEnums - Print out enum values for all of the instructions. - void runEnums(std::ostream &OS); -private: - void printDefList(ListInit *LI, const std::string &Name, - std::ostream &OS) const; - void emitRecord(Record *R, unsigned Num, Record *InstrInfo, std::ostream &OS); - void emitShiftedValue(Record *R, StringInit *Val, IntInit *Shift, - std::ostream &OS); -}; - -#endif diff --git a/support/tools/TableGen/InstrSelectorEmitter.cpp b/support/tools/TableGen/InstrSelectorEmitter.cpp deleted file mode 100644 index a3c535cad4..0000000000 --- a/support/tools/TableGen/InstrSelectorEmitter.cpp +++ /dev/null @@ -1,1287 +0,0 @@ -//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===// -// -// This tablegen backend is responsible for emitting a description of the target -// instruction set for the code generator. -// -//===----------------------------------------------------------------------===// - -#include "InstrSelectorEmitter.h" -#include "CodeGenWrappers.h" -#include "Record.h" -#include "Support/Debug.h" -#include "Support/StringExtras.h" -#include <set> - -NodeType::ArgResultTypes NodeType::Translate(Record *R) { - const std::string &Name = R->getName(); - if (Name == "DNVT_any") return Any; - if (Name == "DNVT_void") return Void; - if (Name == "DNVT_val" ) return Val; - if (Name == "DNVT_arg0") return Arg0; - if (Name == "DNVT_arg1") return Arg1; - if (Name == "DNVT_ptr" ) return Ptr; - if (Name == "DNVT_i8" ) return I8; - throw "Unknown DagNodeValType '" + Name + "'!"; -} - - -//===----------------------------------------------------------------------===// -// TreePatternNode implementation -// - -/// getValueRecord - Returns the value of this tree node as a record. For now -/// we only allow DefInit's as our leaf values, so this is used. -Record *TreePatternNode::getValueRecord() const { - DefInit *DI = dynamic_cast<DefInit*>(getValue()); - assert(DI && "Instruction Selector does not yet support non-def leaves!"); - return DI->getDef(); -} - - -// updateNodeType - Set the node type of N to VT if VT contains information. If -// N already contains a conflicting type, then throw an exception -// -bool TreePatternNode::updateNodeType(MVT::ValueType VT, - const std::string &RecName) { - if (VT == MVT::Other || getType() == VT) return false; - if (getType() == MVT::Other) { - setType(VT); - return true; - } - - throw "Type inferfence contradiction found for pattern " + RecName; -} - -/// InstantiateNonterminals - If this pattern refers to any nonterminals which -/// are not themselves completely resolved, clone the nonterminal and resolve it -/// with the using context we provide. -/// -void TreePatternNode::InstantiateNonterminals(InstrSelectorEmitter &ISE) { - if (!isLeaf()) { - for (unsigned i = 0, e = getNumChildren(); i != e; ++i) - getChild(i)->InstantiateNonterminals(ISE); - return; - } - - // If this is a leaf, it might be a reference to a nonterminal! Check now. - Record *R = getValueRecord(); - if (R->isSubClassOf("Nonterminal")) { - Pattern *NT = ISE.getPattern(R); - if (!NT->isResolved()) { - // We found an unresolved nonterminal reference. Ask the ISE to clone - // it for us, then update our reference to the fresh, new, resolved, - // nonterminal. - - Value = new DefInit(ISE.InstantiateNonterminal(NT, getType())); - } - } -} - - -/// clone - Make a copy of this tree and all of its children. -/// -TreePatternNode *TreePatternNode::clone() const { - TreePatternNode *New; - if (isLeaf()) { - New = new TreePatternNode(Value); - } else { - std::vector<std::pair<TreePatternNode*, std::string> > CChildren; - CChildren.reserve(Children.size()); - for (unsigned i = 0, e = getNumChildren(); i != e; ++i) - CChildren.push_back(std::make_pair(getChild(i)->clone(),getChildName(i))); - New = new TreePatternNode(Operator, CChildren); - } - New->setType(Type); - return New; -} - -std::ostream &operator<<(std::ostream &OS, const TreePatternNode &N) { - if (N.isLeaf()) - return OS << N.getType() << ":" << *N.getValue(); - OS << "(" << N.getType() << ":"; - OS << N.getOperator()->getName(); - - if (N.getNumChildren() != 0) { - OS << " " << *N.getChild(0); - for (unsigned i = 1, e = N.getNumChildren(); i != e; ++i) - OS << ", " << *N.getChild(i); - } - return OS << ")"; -} - -void TreePatternNode::dump() const { std::cerr << *this; } - -//===----------------------------------------------------------------------===// -// Pattern implementation -// - -// Parse the specified DagInit into a TreePattern which we can use. -// -Pattern::Pattern(PatternType pty, DagInit *RawPat, Record *TheRec, - InstrSelectorEmitter &ise) - : PTy(pty), ResultNode(0), TheRecord(TheRec), ISE(ise) { - - // First, parse the pattern... - Tree = ParseTreePattern(RawPat); - - // Run the type-inference engine... - InferAllTypes(); - - if (PTy == Instruction || PTy == Expander) { - // Check to make sure there is not any unset types in the tree pattern... - if (!isResolved()) { - std::cerr << "In pattern: " << *Tree << "\n"; - error("Could not infer all types!"); - } - - // Check to see if we have a top-level (set) of a register. - if (Tree->getOperator()->getName() == "set") { - assert(Tree->getNumChildren() == 2 && "Set with != 2 arguments?"); - if (!Tree->getChild(0)->isLeaf()) - error("Arg #0 of set should be a register or register class!"); - ResultNode = Tree->getChild(0); - ResultName = Tree->getChildName(0); - Tree = Tree->getChild(1); - } - } - - calculateArgs(Tree, ""); -} - -void Pattern::error(const std::string &Msg) const { - std::string M = "In "; - switch (PTy) { - case Nonterminal: M += "nonterminal "; break; - case Instruction: M += "instruction "; break; - case Expander : M += "expander "; break; - } - throw M + TheRecord->getName() + ": " + Msg; -} - -/// calculateArgs - Compute the list of all of the arguments to this pattern, -/// which are the non-void leaf nodes in this pattern. -/// -void Pattern::calculateArgs(TreePatternNode *N, const std::string &Name) { - if (N->isLeaf() || N->getNumChildren() == 0) { - if (N->getType() != MVT::isVoid) - Args.push_back(std::make_pair(N, Name)); - } else { - for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) - calculateArgs(N->getChild(i), N->getChildName(i)); - } -} - -/// getIntrinsicType - Check to see if the specified record has an intrinsic -/// type which should be applied to it. This infer the type of register -/// references from the register file information, for example. -/// -MVT::ValueType Pattern::getIntrinsicType(Record *R) const { - // Check to see if this is a register or a register class... - if (R->isSubClassOf("RegisterClass")) - return getValueType(R->getValueAsDef("RegType")); - else if (R->isSubClassOf("Nonterminal")) - return ISE.ReadNonterminal(R)->getTree()->getType(); - else if (R->isSubClassOf("Register")) { - std::cerr << "WARNING: Explicit registers not handled yet!\n"; - return MVT::Other; - } - - error("Unknown value used: " + R->getName()); - return MVT::Other; -} - -TreePatternNode *Pattern::ParseTreePattern(DagInit *Dag) { - Record *Operator = Dag->getNodeType(); - - if (Operator->isSubClassOf("ValueType")) { - // If the operator is a ValueType, then this must be "type cast" of a leaf - // node. - if (Dag->getNumArgs() != 1) - error("Type cast only valid for a leaf node!"); - - Init *Arg = Dag->getArg(0); - TreePatternNode *New; - if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) { - New = new TreePatternNode(DI); - // If it's a regclass or something else known, set the type. - New->setType(getIntrinsicType(DI->getDef())); - } else if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) { - New = ParseTreePattern(DI); - } else { - Arg->dump(); - error("Unknown leaf value for tree pattern!"); - return 0; - } - - // Apply the type cast... - New->updateNodeType(getValueType(Operator), TheRecord->getName()); - return New; - } - - if (!ISE.getNodeTypes().count(Operator)) - error("Unrecognized node '" + Operator->getName() + "'!"); - - std::vector<std::pair<TreePatternNode*, std::string> > Children; - - for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) { - Init *Arg = Dag->getArg(i); - if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) { - Children.push_back(std::make_pair(ParseTreePattern(DI), - Dag->getArgName(i))); - } else if (DefInit *DefI = dynamic_cast<DefInit*>(Arg)) { - Record *R = DefI->getDef(); - // Direct reference to a leaf DagNode? Turn it into a DagNode if its own. - if (R->isSubClassOf("DagNode")) { - Dag->setArg(i, new DagInit(R, - std::vector<std::pair<Init*, std::string> >())); - --i; // Revisit this node... - } else { - Children.push_back(std::make_pair(new TreePatternNode(DefI), - Dag->getArgName(i))); - // If it's a regclass or something else known, set the type. - Children.back().first->setType(getIntrinsicType(R)); - } - } else { - Arg->dump(); - error("Unknown leaf value for tree pattern!"); - } - } - - return new TreePatternNode(Operator, Children); -} - -void Pattern::InferAllTypes() { - bool MadeChange, AnyUnset; - do { - MadeChange = false; - AnyUnset = InferTypes(Tree, MadeChange); - } while ((AnyUnset || MadeChange) && !(AnyUnset && !MadeChange)); - Resolved = !AnyUnset; -} - - -// InferTypes - Perform type inference on the tree, returning true if there -// are any remaining untyped nodes and setting MadeChange if any changes were -// made. -bool Pattern::InferTypes(TreePatternNode *N, bool &MadeChange) { - if (N->isLeaf()) return N->getType() == MVT::Other; - - bool AnyUnset = false; - Record *Operator = N->getOperator(); - const NodeType &NT = ISE.getNodeType(Operator); - - // Check to see if we can infer anything about the argument types from the - // return types... - if (N->getNumChildren() != NT.ArgTypes.size()) - error("Incorrect number of children for " + Operator->getName() + " node!"); - - for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) { - TreePatternNode *Child = N->getChild(i); - AnyUnset |= InferTypes(Child, MadeChange); - - switch (NT.ArgTypes[i]) { - case NodeType::Any: break; - case NodeType::I8: - MadeChange |= Child->updateNodeType(MVT::i1, TheRecord->getName()); - break; - case NodeType::Arg0: - MadeChange |= Child->updateNodeType(N->getChild(0)->getType(), - TheRecord->getName()); - break; - case NodeType::Arg1: - MadeChange |= Child->updateNodeType(N->getChild(1)->getType(), - TheRecord->getName()); - break; - case NodeType::Val: - if (Child->getType() == MVT::isVoid) - error("Inferred a void node in an illegal place!"); - break; - case NodeType::Ptr: - MadeChange |= Child->updateNodeType(ISE.getTarget().getPointerType(), - TheRecord->getName()); - break; - case NodeType::Void: - MadeChange |= Child->updateNodeType(MVT::isVoid, TheRecord->getName()); - break; - default: assert(0 && "Invalid argument ArgType!"); - } - } - - // See if we can infer anything about the return type now... - switch (NT.ResultType) { - case NodeType::Any: break; - case NodeType::Void: - MadeChange |= N->updateNodeType(MVT::isVoid, TheRecord->getName()); - break; - case NodeType::I8: - MadeChange |= N->updateNodeType(MVT::i1, TheRecord->getName()); - break; - case NodeType::Arg0: - MadeChange |= N->updateNodeType(N->getChild(0)->getType(), - TheRecord->getName()); - break; - case NodeType::Arg1: - MadeChange |= N->updateNodeType(N->getChild(1)->getType(), - TheRecord->getName()); - break; - case NodeType::Ptr: - MadeChange |= N->updateNodeType(ISE.getTarget().getPointerType(), - TheRecord->getName()); - break; - case NodeType::Val: - if (N->getType() == MVT::isVoid) - error("Inferred a void node in an illegal place!"); - break; - default: - assert(0 && "Unhandled type constraint!"); - break; - } - - return AnyUnset | N->getType() == MVT::Other; -} - -/// clone - This method is used to make an exact copy of the current pattern, -/// then change the "TheRecord" instance variable to the specified record. -/// -Pattern *Pattern::clone(Record *R) const { - assert(PTy == Nonterminal && "Can only clone nonterminals"); - return new Pattern(Tree->clone(), R, Resolved, ISE); -} - - - -std::ostream &operator<<(std::ostream &OS, const Pattern &P) { - switch (P.getPatternType()) { - case Pattern::Nonterminal: OS << "Nonterminal pattern "; break; - case Pattern::Instruction: OS << "Instruction pattern "; break; - case Pattern::Expander: OS << "Expander pattern "; break; - } - - OS << P.getRecord()->getName() << ":\t"; - - if (Record *Result = P.getResult()) - OS << Result->getName() << " = "; - OS << *P.getTree(); - - if (!P.isResolved()) - OS << " [not completely resolved]"; - return OS; -} - -void Pattern::dump() const { std::cerr << *this; } - - - -/// getSlotName - If this is a leaf node, return the slot name that the operand -/// will update. -std::string Pattern::getSlotName() const { - if (getPatternType() == Pattern::Nonterminal) { - // Just use the nonterminal name, which will already include the type if - // it has been cloned. - return getRecord()->getName(); - } else { - std::string SlotName; - if (getResult()) - SlotName = getResult()->getName()+"_"; - else - SlotName = "Void_"; - return SlotName + getName(getTree()->getType()); - } -} - -/// getSlotName - If this is a leaf node, return the slot name that the -/// operand will update. -std::string Pattern::getSlotName(Record *R) { - if (R->isSubClassOf("Nonterminal")) { - // Just use the nonterminal name, which will already include the type if - // it has been cloned. - return R->getName(); - } else if (R->isSubClassOf("RegisterClass")) { - MVT::ValueType Ty = getValueType(R->getValueAsDef("RegType")); - return R->getName() + "_" + getName(Ty); - } else { - assert(0 && "Don't know how to get a slot name for this!"); - } - return ""; -} - -//===----------------------------------------------------------------------===// -// PatternOrganizer implementation -// - -/// addPattern - Add the specified pattern to the appropriate location in the -/// collection. -void PatternOrganizer::addPattern(Pattern *P) { - NodesForSlot &Nodes = AllPatterns[P->getSlotName()]; - if (!P->getTree()->isLeaf()) - Nodes[P->getTree()->getOperator()].push_back(P); - else { - // Right now we only support DefInit's with node types... - Nodes[P->getTree()->getValueRecord()].push_back(P); - } -} - - - -//===----------------------------------------------------------------------===// -// InstrSelectorEmitter implementation -// - -/// ReadNodeTypes - Read in all of the node types in the current RecordKeeper, -/// turning them into the more accessible NodeTypes data structure. -/// -void InstrSelectorEmitter::ReadNodeTypes() { - std::vector<Record*> Nodes = Records.getAllDerivedDefinitions("DagNode"); - DEBUG(std::cerr << "Getting node types: "); - for (unsigned i = 0, e = Nodes.size(); i != e; ++i) { - Record *Node = Nodes[i]; - - // Translate the return type... - NodeType::ArgResultTypes RetTy = - NodeType::Translate(Node->getValueAsDef("RetType")); - - // Translate the arguments... - ListInit *Args = Node->getValueAsListInit("ArgTypes"); - std::vector<NodeType::ArgResultTypes> ArgTypes; - - for (unsigned a = 0, e = Args->getSize(); a != e; ++a) { - if (DefInit *DI = dynamic_cast<DefInit*>(Args->getElement(a))) - ArgTypes.push_back(NodeType::Translate(DI->getDef())); - else - throw "In node " + Node->getName() + ", argument is not a Def!"; - - if (a == 0 && ArgTypes.back() == NodeType::Arg0) - throw "In node " + Node->getName() + ", arg 0 cannot have type 'arg0'!"; - if (a == 1 && ArgTypes.back() == NodeType::Arg1) - throw "In node " + Node->getName() + ", arg 1 cannot have type 'arg1'!"; - } - if ((RetTy == NodeType::Arg0 && Args->getSize() == 0) || - (RetTy == NodeType::Arg1 && Args->getSize() < 2)) - throw "In node " + Node->getName() + - ", invalid return type for node with this many operands!"; - - // Add the node type mapping now... - NodeTypes[Node] = NodeType(RetTy, ArgTypes); - DEBUG(std::cerr << Node->getName() << ", "); - } - DEBUG(std::cerr << "DONE!\n"); -} - -Pattern *InstrSelectorEmitter::ReadNonterminal(Record *R) { - Pattern *&P = Patterns[R]; - if (P) return P; // Don't reread it! - - DagInit *DI = R->getValueAsDag("Pattern"); - P = new Pattern(Pattern::Nonterminal, DI, R, *this); - DEBUG(std::cerr << "Parsed " << *P << "\n"); - return P; -} - - -// ReadNonTerminals - Read in all nonterminals and incorporate them into our -// pattern database. -void InstrSelectorEmitter::ReadNonterminals() { - std::vector<Record*> NTs = Records.getAllDerivedDefinitions("Nonterminal"); - for (unsigned i = 0, e = NTs.size(); i != e; ++i) - ReadNonterminal(NTs[i]); -} - - -/// ReadInstructionPatterns - Read in all subclasses of Instruction, and process -/// those with a useful Pattern field. -/// -void InstrSelectorEmitter::ReadInstructionPatterns() { - std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); - for (unsigned i = 0, e = Insts.size(); i != e; ++i) { - Record *Inst = Insts[i]; - if (DagInit *DI = dynamic_cast<DagInit*>(Inst->getValueInit("Pattern"))) { - Patterns[Inst] = new Pattern(Pattern::Instruction, DI, Inst, *this); - DEBUG(std::cerr << "Parsed " << *Patterns[Inst] << "\n"); - } - } -} - -/// ReadExpanderPatterns - Read in all expander patterns... -/// -void InstrSelectorEmitter::ReadExpanderPatterns() { - std::vector<Record*> Expanders = Records.getAllDerivedDefinitions("Expander"); - for (unsigned i = 0, e = Expanders.size(); i != e; ++i) { - Record *Expander = Expanders[i]; - DagInit *DI = Expander->getValueAsDag("Pattern"); - Patterns[Expander] = new Pattern(Pattern::Expander, DI, Expander, *this); - DEBUG(std::cerr << "Parsed " << *Patterns[Expander] << "\n"); - } -} - - -// InstantiateNonterminals - Instantiate any unresolved nonterminals with -// information from the context that they are used in. -// -void InstrSelectorEmitter::InstantiateNonterminals() { - DEBUG(std::cerr << "Instantiating nonterminals:\n"); - for (std::map<Record*, Pattern*>::iterator I = Patterns.begin(), - E = Patterns.end(); I != E; ++I) - if (I->second->isResolved()) - I->second->InstantiateNonterminals(); -} - -/// InstantiateNonterminal - This method takes the nonterminal specified by -/// NT, which should not be completely resolved, clones it, applies ResultTy -/// to its root, then runs the type inference stuff on it. This should -/// produce a newly resolved nonterminal, which we make a record for and -/// return. To be extra fancy and efficient, this only makes one clone for -/// each type it is instantiated with. -Record *InstrSelectorEmitter::InstantiateNonterminal(Pattern *NT, - MVT::ValueType ResultTy) { - assert(!NT->isResolved() && "Nonterminal is already resolved!"); - - // Check to see if we have already instantiated this pair... - Record* &Slot = InstantiatedNTs[std::make_pair(NT, ResultTy)]; - if (Slot) return Slot; - - Record *New = new Record(NT->getRecord()->getName()+"_"+getName(ResultTy)); - - // Copy over the superclasses... - const std::vector<Record*> &SCs = NT->getRecord()->getSuperClasses(); - for (unsigned i = 0, e = SCs.size(); i != e; ++i) - New->addSuperClass(SCs[i]); - - DEBUG(std::cerr << " Nonterminal '" << NT->getRecord()->getName() - << "' for type '" << getName(ResultTy) << "', producing '" - << New->getName() << "'\n"); - - // Copy the pattern... - Pattern *NewPat = NT->clone(New); - - // Apply the type to the root... - NewPat->getTree()->updateNodeType(ResultTy, New->getName()); - - // Infer types... - NewPat->InferAllTypes(); - - // Make sure everything is good to go now... - if (!NewPat->isResolved()) - NewPat->error("Instantiating nonterminal did not resolve all types!"); - - // Add the pattern to the patterns map, add the record to the RecordKeeper, - // return the new record. - Patterns[New] = NewPat; - Records.addDef(New); - return Slot = New; -} - -// CalculateComputableValues - Fill in the ComputableValues map through -// analysis of the patterns we are playing with. -void InstrSelectorEmitter::CalculateComputableValues() { - // Loop over all of the patterns, adding them to the ComputableValues map - for (std::map<Record*, Pattern*>::iterator I = Patterns.begin(), - E = Patterns.end(); I != E; ++I) - if (I->second->isResolved()) { - // We don't want to add patterns like R32 = R32. This is a hack working - // around a special case of a general problem, but for now we explicitly - // forbid these patterns. They can never match anyway. - Pattern *P = I->second; - if (!P->getResult() || !P->getTree()->isLeaf() || - P->getResult() != P->getTree()->getValueRecord()) - ComputableValues.addPattern(P); - } -} - -#if 0 -// MoveIdenticalPatterns - Given a tree pattern 'P', move all of the tree -// patterns which have the same top-level structure as P from the 'From' list to -// the 'To' list. -static void MoveIdenticalPatterns(TreePatternNode *P, - std::vector<std::pair<Pattern*, TreePatternNode*> > &From, - std::vector<std::pair<Pattern*, TreePatternNode*> > &To) { - assert(!P->isLeaf() && "All leaves are identical!"); - - const std::vector<TreePatternNode*> &PChildren = P->getChildren(); - for (unsigned i = 0; i != From.size(); ++i) { - TreePatternNode *N = From[i].second; - assert(P->getOperator() == N->getOperator() &&"Differing operators?"); - assert(PChildren.size() == N->getChildren().size() && - "Nodes with different arity??"); - bool isDifferent = false; - for (unsigned c = 0, e = PChildren.size(); c != e; ++c) { - TreePatternNode *PC = PChildren[c]; - TreePatternNode *NC = N->getChild(c); - if (PC->isLeaf() != NC->isLeaf()) { - isDifferent = true; - break; - } - - if (!PC->isLeaf()) { - if (PC->getOperator() != NC->getOperator()) { - isDifferent = true; - break; - } - } else { // It's a leaf! - if (PC->getValueRecord() != NC->getValueRecord()) { - isDifferent = true; - break; - } - } - } - // If it's the same as the reference one, move it over now... - if (!isDifferent) { - To.push_back(std::make_pair(From[i].first, N)); - From.erase(From.begin()+i); - --i; // Don't skip an entry... - } - } -} -#endif - -static std::string getNodeName(Record *R) { - RecordVal *RV = R->getValue("EnumName"); - if (RV) - if (Init *I = RV->getValue()) - if (StringInit *SI = dynamic_cast<StringInit*>(I)) - return SI->getValue(); - return R->getName(); -} - - -static void EmitPatternPredicates(TreePatternNode *Tree, - const std::string &VarName, std::ostream &OS){ - OS << " && " << VarName << "->getNodeType() == ISD::" - << getNodeName(Tree->getOperator()); - - for (unsigned c = 0, e = Tree->getNumChildren(); c != e; ++c) - if (!Tree->getChild(c)->isLeaf()) - EmitPatternPredicates(Tree->getChild(c), - VarName + "->getUse(" + utostr(c)+")", OS); -} - -static void EmitPatternCosts(TreePatternNode *Tree, const std::string &VarName, - std::ostream &OS) { - for (unsigned c = 0, e = Tree->getNumChildren(); c != e; ++c) - if (Tree->getChild(c)->isLeaf()) { - OS << " + Match_" - << Pattern::getSlotName(Tree->getChild(c)->getValueRecord()) << "(" - << VarName << "->getUse(" << c << "))"; - } else { - EmitPatternCosts(Tree->getChild(c), - VarName + "->getUse(" + utostr(c) + ")", OS); - } -} - - -// EmitMatchCosters - Given a list of patterns, which all have the same root -// pattern operator, emit an efficient decision tree to decide which one to -// pick. This is structured this way to avoid reevaluations of non-obvious -// subexpressions. -void InstrSelectorEmitter::EmitMatchCosters(std::ostream &OS, - const std::vector<std::pair<Pattern*, TreePatternNode*> > &Patterns, - const std::string &VarPrefix, - unsigned IndentAmt) { - assert(!Patterns.empty() && "No patterns to emit matchers for!"); - std::string Indent(IndentAmt, ' '); - - // Load all of the operands of the root node into scalars for fast access - const NodeType &ONT = getNodeType(Patterns[0].second->getOperator()); - for (unsigned i = 0, e = ONT.ArgTypes.size(); i != e; ++i) - OS << Indent << "SelectionDAGNode *" << VarPrefix << "_Op" << i - << " = N->getUse(" << i << ");\n"; - - // Compute the costs of computing the various nonterminals/registers, which - // are directly used at this level. - OS << "\n" << Indent << "// Operand matching costs...\n"; - std::set<std::string> ComputedValues; // Avoid duplicate computations... - for (unsigned i = 0, e = Patterns.size(); i != e; ++i) { - TreePatternNode *NParent = Patterns[i].second; - for (unsigned c = 0, e = NParent->getNumChildren(); c != e; ++c) { - TreePatternNode *N = NParent->getChild(c); - if (N->isLeaf()) { - Record *VR = N->getValueRecord(); - const std::string &LeafName = VR->getName(); - std::string OpName = VarPrefix + "_Op" + utostr(c); - std::string ValName = OpName + "_" + LeafName + "_Cost"; - if (!ComputedValues.count(ValName)) { - OS << Indent << "unsigned " << ValName << " = Match_" - << Pattern::getSlotName(VR) << "(" << OpName << ");\n"; - ComputedValues.insert(ValName); - } - } - } - } - OS << "\n"; - - - std::string LocCostName = VarPrefix + "_Cost"; - OS << Indent << "unsigned " << LocCostName << "Min = ~0U >> 1;\n" - << Indent << "unsigned " << VarPrefix << "_PatternMin = NoMatchPattern;\n"; - -#if 0 - // Separate out all of the patterns into groups based on what their top-level - // signature looks like... - std::vector<std::pair<Pattern*, TreePatternNode*> > PatternsLeft(Patterns); - while (!PatternsLeft.empty()) { - // Process all of the patterns that have the same signature as the last - // element... - std::vector<std::pair<Pattern*, TreePatternNode*> > Group; - MoveIdenticalPatterns(PatternsLeft.back().second, PatternsLeft, Group); - assert(!Group.empty() && "Didn't at least pick the source pattern?"); - -#if 0 - OS << "PROCESSING GROUP:\n"; - for (unsigned i = 0, e = Group.size(); i != e; ++i) - OS << " " << *Group[i].first << "\n"; - OS << "\n\n"; -#endif - - OS << Indent << "{ // "; - - if (Group.size() != 1) { - OS << Group.size() << " size group...\n"; - OS << Indent << " unsigned " << VarPrefix << "_Pattern = NoMatch;\n"; - } else { - OS << *Group[0].first << "\n"; - OS << Indent << " unsigned " << VarPrefix << "_Pattern = " - << Group[0].first->getRecord()->getName() << "_Pattern;\n"; - } - - OS << Indent << " unsigned " << LocCostName << " = "; - if (Group.size() == 1) - OS << "1;\n"; // Add inst cost if at individual rec - else - OS << "0;\n"; - - // Loop over all of the operands, adding in their costs... - TreePatternNode *N = Group[0].second; - const std::vector<TreePatternNode*> &Children = N->getChildren(); - - // If necessary, emit conditionals to check for the appropriate tree - // structure here... - for (unsigned i = 0, e = Children.size(); i != e; ++i) { - TreePatternNode *C = Children[i]; - if (C->isLeaf()) { - // We already calculated the cost for this leaf, add it in now... - OS << Indent << " " << LocCostName << " += " - << VarPrefix << "_Op" << utostr(i) << "_" - << C->getValueRecord()->getName() << "_Cost;\n"; - } else { - // If it's not a leaf, we have to check to make sure that the current - // node has the appropriate structure, then recurse into it... - OS << Indent << " if (" << VarPrefix << "_Op" << i - << "->getNodeType() == ISD::" << getNodeName(C->getOperator()) - << ") {\n"; - std::vector<std::pair<Pattern*, TreePatternNode*> > SubPatterns; - for (unsigned n = 0, e = Group.size(); n != e; ++n) - SubPatterns.push_back(std::make_pair(Group[n].first, - Group[n].second->getChild(i))); - EmitMatchCosters(OS, SubPatterns, VarPrefix+"_Op"+utostr(i), - IndentAmt + 4); - OS << Indent << " }\n"; - } - } - - // If the cost for this match is less than the minimum computed cost so far, - // update the minimum cost and selected pattern. - OS << Indent << " if (" << LocCostName << " < " << LocCostName << "Min) { " - << LocCostName << "Min = " << LocCostName << "; " << VarPrefix - << "_PatternMin = " << VarPrefix << "_Pattern; }\n"; - - OS << Indent << "}\n"; - } -#endif - - for (unsigned i = 0, e = Patterns.size(); i != e; ++i) { - Pattern *P = Patterns[i].first; - TreePatternNode *PTree = P->getTree(); - unsigned PatternCost = 1; - - // Check to see if there are any non-leaf elements in the pattern. If so, - // we need to emit a predicate for this match. - bool AnyNonLeaf = false; - for (unsigned c = 0, e = PTree->getNumChildren(); c != e; ++c) - if (!PTree->getChild(c)->isLeaf()) { - AnyNonLeaf = true; - break; - } - - if (!AnyNonLeaf) { // No predicate necessary, just output a scope... - OS << " {// " << *P << "\n"; - } else { - // We need to emit a predicate to make sure the tree pattern matches, do - // so now... - OS << " if (1"; - for (unsigned c = 0, e = PTree->getNumChildren(); c != e; ++c) - if (!PTree->getChild(c)->isLeaf()) - EmitPatternPredicates(PTree->getChild(c), - VarPrefix + "_Op" + utostr(c), OS); - - OS << ") {\n // " << *P << "\n"; - } - - OS << " unsigned PatCost = " << PatternCost; - - for (unsigned c = 0, e = PTree->getNumChildren(); c != e; ++c) - if (PTree->getChild(c)->isLeaf()) { - OS << " + " << VarPrefix << "_Op" << c << "_" - << PTree->getChild(c)->getValueRecord()->getName() << "_Cost"; - } else { - EmitPatternCosts(PTree->getChild(c), VarPrefix + "_Op" + utostr(c), OS); - } - OS << ";\n"; - OS << " if (PatCost < MinCost) { MinCost = PatCost; Pattern = " - << P->getRecord()->getName() << "_Pattern; }\n" - << " }\n"; - } -} - -static void ReduceAllOperands(TreePatternNode *N, const std::string &Name, - std::vector<std::pair<TreePatternNode*, std::string> > &Operands, - std::ostream &OS) { - if (N->isLeaf()) { - // If this is a leaf, register or nonterminal reference... - std::string SlotName = Pattern::getSlotName(N->getValueRecord()); - OS << " ReducedValue_" << SlotName << " *" << Name << "Val = Reduce_" - << SlotName << "(" << Name << ", MBB);\n"; - Operands.push_back(std::make_pair(N, Name+"Val")); - } else if (N->getNumChildren() == 0) { - // This is a reference to a leaf tree node, like an immediate or frame - // index. - if (N->getType() != MVT::isVoid) { - std::string SlotName = - getNodeName(N->getOperator()) + "_" + getName(N->getType()); - OS << " ReducedValue_" << SlotName << " *" << Name << "Val = " - << Name << "->getValue<ReducedValue_" << SlotName << ">(ISD::" - << SlotName << "_Slot);\n"; - Operands.push_back(std::make_pair(N, Name+"Val")); - } - } else { - // Otherwise this is an interior node... - for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) { - std::string ChildName = Name + "_Op" + utostr(i); - OS << " SelectionDAGNode *" << ChildName << " = " << Name - << "->getUse(" << i << ");\n"; - ReduceAllOperands(N->getChild(i), ChildName, Operands, OS); - } - } -} - -/// PrintExpanderOperand - Print out Arg as part of the instruction emission -/// process for the expander pattern P. This argument may be referencing some -/// values defined in P, or may just be physical register references or -/// something like that. If PrintArg is true, we are printing out arguments to -/// the BuildMI call. If it is false, we are printing the result register -/// name. -void InstrSelectorEmitter::PrintExpanderOperand(Init *Arg, - const std::string &NameVar, - TreePatternNode *ArgDeclNode, - Pattern *P, bool PrintArg, - std::ostream &OS) { - if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) { - Record *Arg = DI->getDef(); - if (!ArgDeclNode->isLeaf() && ArgDeclNode->getNumChildren() != 0) - P->error("Expected leaf node as argument!"); - Record *ArgDecl = ArgDeclNode->isLeaf() ? ArgDeclNode->getValueRecord() : - ArgDeclNode->getOperator(); - if (Arg->isSubClassOf("Register")) { - // This is a physical register reference... make sure that the instruction - // requested a register! - if (!ArgDecl->isSubClassOf("RegisterClass")) - P->error("Argument mismatch for instruction pattern!"); - - // FIXME: This should check to see if the register is in the specified - // register class! - if (PrintArg) OS << ".addReg("; - OS << getQualifiedName(Arg); - if (PrintArg) OS << ")"; - return; - } else if (Arg->isSubClassOf("RegisterClass")) { - // If this is a symbolic register class reference, we must be using a - // named value. - if (NameVar.empty()) P->error("Did not specify WHICH register to pass!"); - if (Arg != ArgDecl) P->error("Instruction pattern mismatch!"); - - if (PrintArg) OS << ".addReg("; - OS << NameVar; - if (PrintArg) OS << ")"; - return; - } else if (Arg->getName() == "frameidx") { - if (!PrintArg) P->error("Cannot define a new frameidx value!"); - OS << ".addFrameIndex(" << NameVar << ")"; - return; - } else if (Arg->getName() == "basicblock") { - if (!PrintArg) P->error("Cannot define a new basicblock value!"); - OS << ".addMBB(" << NameVar << ")"; - return; - } - P->error("Unknown operand type '" + Arg->getName() + "' to expander!"); - } else if (IntInit *II = dynamic_cast<IntInit*>(Arg)) { - if (!NameVar.empty()) - P->error("Illegal to specify a name for a constant initializer arg!"); - - // Hack this check to allow R32 values with 0 as the initializer for memory - // references... FIXME! - if (ArgDeclNode->isLeaf() && II->getValue() == 0 && - ArgDeclNode->getValueRecord()->getName() == "R32") { - OS << ".addReg(0)"; - } else { - if (ArgDeclNode->isLeaf() || ArgDeclNode->getOperator()->getName()!="imm") - P->error("Illegal immediate int value '" + itostr(II->getValue()) + - "' operand!"); - OS << ".addZImm(" << II->getValue() << ")"; - } - return; - } - P->error("Unknown operand type to expander!"); -} - -static std::string getArgName(Pattern *P, const std::string &ArgName, - const std::vector<std::pair<TreePatternNode*, std::string> > &Operands) { - assert(P->getNumArgs() == Operands.size() &&"Argument computation mismatch!"); - if (ArgName.empty()) return ""; - - for (unsigned i = 0, e = P->getNumArgs(); i != e; ++i) - if (P->getArgName(i) == ArgName) - return Operands[i].second + "->Val"; - - if (ArgName == P->getResultName()) - return "NewReg"; - P->error("Pattern does not define a value named $" + ArgName + "!"); - return ""; -} - - -void InstrSelectorEmitter::run(std::ostream &OS) { - // Type-check all of the node types to ensure we "understand" them. - ReadNodeTypes(); - - // Read in all of the nonterminals, instructions, and expanders... - ReadNonterminals(); - ReadInstructionPatterns(); - ReadExpanderPatterns(); - - // Instantiate any unresolved nonterminals with information from the context - // that they are used in. - InstantiateNonterminals(); - - // Clear InstantiatedNTs, we don't need it anymore... - InstantiatedNTs.clear(); - - DEBUG(std::cerr << "Patterns acquired:\n"); - for (std::map<Record*, Pattern*>::iterator I = Patterns.begin(), - E = Patterns.end(); I != E; ++I) - if (I->second->isResolved()) - DEBUG(std::cerr << " " << *I->second << "\n"); - - CalculateComputableValues(); - - EmitSourceFileHeader("Instruction Selector for the " + Target.getName() + - " target", OS); - OS << "#include \"llvm/CodeGen/MachineInstrBuilder.h\"\n"; - - // Output the slot number enums... - OS << "\nenum { // Slot numbers...\n" - << " LastBuiltinSlot = ISD::NumBuiltinSlots-1, // Start numbering here\n"; - for (PatternOrganizer::iterator I = ComputableValues.begin(), - E = ComputableValues.end(); I != E; ++I) - OS << " " << I->first << "_Slot,\n"; - OS << " NumSlots\n};\n\n// Reduction value typedefs...\n"; - - // Output the reduction value typedefs... - for (PatternOrganizer::iterator I = ComputableValues.begin(), - E = ComputableValues.end(); I != E; ++I) { - - OS << "typedef ReducedValue<unsigned, " << I->first - << "_Slot> ReducedValue_" << I->first << ";\n"; - } - - // Output the pattern enums... - OS << "\n\n" - << "enum { // Patterns...\n" - << " NotComputed = 0,\n" - << " NoMatchPattern, \n"; - for (PatternOrganizer::iterator I = ComputableValues.begin(), - E = ComputableValues.end(); I != E; ++I) { - OS << " // " << I->first << " patterns...\n"; - for (PatternOrganizer::NodesForSlot::iterator J = I->second.begin(), - E = I->second.end(); J != E; ++J) - for (unsigned i = 0, e = J->second.size(); i != e; ++i) - OS << " " << J->second[i]->getRecord()->getName() << "_Pattern,\n"; - } - OS << "};\n\n"; - - //===--------------------------------------------------------------------===// - // Emit the class definition... - // - OS << "namespace {\n" - << " class " << Target.getName() << "ISel {\n" - << " SelectionDAG &DAG;\n" - << " public:\n" - << " X86ISel(SelectionDAG &D) : DAG(D) {}\n" - << " void generateCode();\n" - << " private:\n" - << " unsigned makeAnotherReg(const TargetRegisterClass *RC) {\n" - << " return DAG.getMachineFunction().getSSARegMap()->createVirt" - "ualRegister(RC);\n" - << " }\n\n" - << " // DAG matching methods for classes... all of these methods" - " return the cost\n" - << " // of producing a value of the specified class and type, which" - " also gets\n" - << " // added to the DAG node.\n"; - - // Output all of the matching prototypes for slots... - for (PatternOrganizer::iterator I = ComputableValues.begin(), - E = ComputableValues.end(); I != E; ++I) - OS << " unsigned Match_" << I->first << "(SelectionDAGNode *N);\n"; - OS << "\n // DAG matching methods for DAG nodes...\n"; - - // Output all of the matching prototypes for slot/node pairs - for (PatternOrganizer::iterator I = ComputableValues.begin(), - E = ComputableValues.end(); I != E; ++I) - for (PatternOrganizer::NodesForSlot::iterator J = I->second.begin(), - E = I->second.end(); J != E; ++J) - OS << " unsigned Match_" << I->first << "_" << getNodeName(J->first) - << "(SelectionDAGNode *N);\n"; - - // Output all of the dag reduction methods prototypes... - OS << "\n // DAG reduction methods...\n"; - for (PatternOrganizer::iterator I = ComputableValues.begin(), - E = ComputableValues.end(); I != E; ++I) - OS << " ReducedValue_" << I->first << " *Reduce_" << I->first - << "(SelectionDAGNode *N,\n" << std::string(27+2*I->first.size(), ' ') - << "MachineBasicBlock *MBB);\n"; - OS << " };\n}\n\n"; - - // Emit the generateCode entry-point... - OS << "void X86ISel::generateCode() {\n" - << " SelectionDAGNode *Root = DAG.getRoot();\n" - << " assert(Root->getValueType() == MVT::isVoid && " - "\"Root of DAG produces value??\");\n\n" - << " std::cerr << \"\\n\";\n" - << " unsigned Cost = Match_Void_void(Root);\n" - << " if (Cost >= ~0U >> 1) {\n" - << " std::cerr << \"Match failed!\\n\";\n" - << " Root->dump();\n" - << " abort();\n" - << " }\n\n" - << " std::cerr << \"Total DAG Cost: \" << Cost << \"\\n\\n\";\n\n" - << " Reduce_Void_void(Root, 0);\n" - << "}\n\n" - << "//===" << std::string(70, '-') << "===//\n" - << "// Matching methods...\n" - << "//\n\n"; - - //===--------------------------------------------------------------------===// - // Emit all of the matcher methods... - // - for (PatternOrganizer::iterator I = ComputableValues.begin(), - E = ComputableValues.end(); I != E; ++I) { - const std::string &SlotName = I->first; - OS << "unsigned " << Target.getName() << "ISel::Match_" << SlotName - << "(SelectionDAGNode *N) {\n" - << " assert(N->getValueType() == MVT::" - << getEnumName((*I->second.begin()).second[0]->getTree()->getType()) - << ");\n" << " // If we already have a cost available for " << SlotName - << " use it!\n" - << " if (N->getPatternFor(" << SlotName << "_Slot))\n" - << " return N->getCostFor(" << SlotName << "_Slot);\n\n" - << " unsigned Cost;\n" - << " switch (N->getNodeType()) {\n" - << " default: Cost = ~0U >> 1; // Match failed\n" - << " N->setPatternCostFor(" << SlotName << "_Slot, NoMatchPattern, Cost, NumSlots);\n" - << " break;\n"; - - for (PatternOrganizer::NodesForSlot::iterator J = I->second.begin(), - E = I->second.end(); J != E; ++J) - if (!J->first->isSubClassOf("Nonterminal")) - OS << " case ISD::" << getNodeName(J->first) << ":\tCost = Match_" - << SlotName << "_" << getNodeName(J->first) << "(N); break;\n"; - OS << " }\n"; // End of the switch statement - - // Emit any patterns which have a nonterminal leaf as the RHS. These may - // match multiple root nodes, so they cannot be handled with the switch... - for (PatternOrganizer::NodesForSlot::iterator J = I->second.begin(), - E = I->second.end(); J != E; ++J) - if (J->first->isSubClassOf("Nonterminal")) { - OS << " unsigned " << J->first->getName() << "_Cost = Match_" - << getNodeName(J->first) << "(N);\n" - << " if (" << getNodeName(J->first) << "_Cost < Cost) Cost = " - << getNodeName(J->first) << "_Cost;\n"; - } - - OS << " return Cost;\n}\n\n"; - - for (PatternOrganizer::NodesForSlot::iterator J = I->second.begin(), - E = I->second.end(); J != E; ++J) { - Record *Operator = J->first; - bool isNonterm = Operator->isSubClassOf("Nonterminal"); - if (!isNonterm) { - OS << "unsigned " << Target.getName() << "ISel::Match_"; - if (!isNonterm) OS << SlotName << "_"; - OS << getNodeName(Operator) << "(SelectionDAGNode *N) {\n" - << " unsigned Pattern = NoMatchPattern;\n" - << " unsigned MinCost = ~0U >> 1;\n"; - - std::vector<std::pair<Pattern*, TreePatternNode*> > Patterns; - for (unsigned i = 0, e = J->second.size(); i != e; ++i) - Patterns.push_back(std::make_pair(J->second[i], - J->second[i]->getTree())); - EmitMatchCosters(OS, Patterns, "N", 2); - - OS << "\n N->setPatternCostFor(" << SlotName - << "_Slot, Pattern, MinCost, NumSlots);\n" - << " return MinCost;\n" - << "}\n"; - } - } - } - - //===--------------------------------------------------------------------===// - // Emit all of the reducer methods... - // - OS << "\n\n//===" << std::string(70, '-') << "===//\n" - << "// Reducer methods...\n" - << "//\n"; - - for (PatternOrganizer::iterator I = ComputableValues.begin(), - E = ComputableValues.end(); I != E; ++I) { - const std::string &SlotName = I->first; - OS << "ReducedValue_" << SlotName << " *" << Target.getName() - << "ISel::Reduce_" << SlotName - << "(SelectionDAGNode *N, MachineBasicBlock *MBB) {\n" - << " ReducedValue_" << SlotName << " *Val = N->hasValue<ReducedValue_" - << SlotName << ">(" << SlotName << "_Slot);\n" - << " if (Val) return Val;\n" - << " if (N->getBB()) MBB = N->getBB();\n\n" - << " switch (N->getPatternFor(" << SlotName << "_Slot)) {\n"; - - // Loop over all of the patterns that can produce a value for this slot... - PatternOrganizer::NodesForSlot &NodesForSlot = I->second; - for (PatternOrganizer::NodesForSlot::iterator J = NodesForSlot.begin(), - E = NodesForSlot.end(); J != E; ++J) - for (unsigned i = 0, e = J->second.size(); i != e; ++i) { - Pattern *P = J->second[i]; - OS << " case " << P->getRecord()->getName() << "_Pattern: {\n" - << " // " << *P << "\n"; - // Loop over the operands, reducing them... - std::vector<std::pair<TreePatternNode*, std::string> > Operands; - ReduceAllOperands(P->getTree(), "N", Operands, OS); - - // Now that we have reduced all of our operands, and have the values - // that reduction produces, perform the reduction action for this - // pattern. - std::string Result; - - // If the pattern produces a register result, generate a new register - // now. - if (Record *R = P->getResult()) { - assert(R->isSubClassOf("RegisterClass") && - "Only handle register class results so far!"); - OS << " unsigned NewReg = makeAnotherReg(" << Target.getName() - << "::" << R->getName() << "RegisterClass);\n"; - Result = "NewReg"; - DEBUG(OS << " std::cerr << \"%reg\" << NewReg << \" =\t\";\n"); - } else { - DEBUG(OS << " std::cerr << \"\t\t\";\n"); - Result = "0"; - } - - // Print out the pattern that matched... - DEBUG(OS << " std::cerr << \" " << P->getRecord()->getName() <<'"'); - DEBUG(for (unsigned i = 0, e = Operands.size(); i != e; ++i) - if (Operands[i].first->isLeaf()) { - Record *RV = Operands[i].first->getValueRecord(); - assert(RV->isSubClassOf("RegisterClass") && - "Only handles registers here so far!"); - OS << " << \" %reg\" << " << Operands[i].second - << "->Val"; - } else { - OS << " << ' ' << " << Operands[i].second - << "->Val"; - }); - DEBUG(OS << " << \"\\n\";\n"); - - // Generate the reduction code appropriate to the particular type of - // pattern that this is... - switch (P->getPatternType()) { - case Pattern::Instruction: - // Instruction patterns just emit a single MachineInstr, using BuildMI - OS << " BuildMI(MBB, " << Target.getName() << "::" - << P->getRecord()->getName() << ", " << Operands.size(); - if (P->getResult()) OS << ", NewReg"; - OS << ")"; - - for (unsigned i = 0, e = Operands.size(); i != e; ++i) { - TreePatternNode *Op = Operands[i].first; - if (Op->isLeaf()) { - Record *RV = Op->getValueRecord(); - assert(RV->isSubClassOf("RegisterClass") && - "Only handles registers here so far!"); - OS << ".addReg(" << Operands[i].second << "->Val)"; - } else if (Op->getOperator()->getName() == "imm") { - OS << ".addZImm(" << Operands[i].second << "->Val)"; - } else if (Op->getOperator()->getName() == "basicblock") { - OS << ".addMBB(" << Operands[i].second << "->Val)"; - } else { - assert(0 && "Unknown value type!"); - } - } - OS << ";\n"; - break; - case Pattern::Expander: { - // Expander patterns emit one machine instr for each instruction in - // the list of instructions expanded to. - ListInit *Insts = P->getRecord()->getValueAsListInit("Result"); - for (unsigned IN = 0, e = Insts->getSize(); IN != e; ++IN) { - DagInit *DIInst = dynamic_cast<DagInit*>(Insts->getElement(IN)); - if (!DIInst) P->error("Result list must contain instructions!"); - Record *InstRec = DIInst->getNodeType(); - Pattern *InstPat = getPattern(InstRec); - if (!InstPat || InstPat->getPatternType() != Pattern::Instruction) - P->error("Instruction list must contain Instruction patterns!"); - - bool hasResult = InstPat->getResult() != 0; - if (InstPat->getNumArgs() != DIInst->getNumArgs()-hasResult) { - P->error("Incorrect number of arguments specified for inst '" + - InstPat->getRecord()->getName() + "' in result list!"); - } - - // Start emission of the instruction... - OS << " BuildMI(MBB, " << Target.getName() << "::" - << InstRec->getName() << ", " - << DIInst->getNumArgs()-hasResult; - // Emit register result if necessary.. - if (hasResult) { - std::string ArgNameVal = - getArgName(P, DIInst->getArgName(0), Operands); - PrintExpanderOperand(DIInst->getArg(0), ArgNameVal, - InstPat->getResultNode(), P, false, - OS << ", "); - } - OS << ")"; - - for (unsigned i = hasResult, e = DIInst->getNumArgs(); i != e; ++i){ - std::string ArgNameVal = - getArgName(P, DIInst->getArgName(i), Operands); - - PrintExpanderOperand(DIInst->getArg(i), ArgNameVal, - InstPat->getArg(i-hasResult), P, true, OS); - } - - OS << ";\n"; - } - break; - } - default: - assert(0 && "Reduction of this type of pattern not implemented!"); - } - - OS << " Val = new ReducedValue_" << SlotName << "(" << Result<<");\n" - << " break;\n" - << " }\n"; - } - - - OS << " default: assert(0 && \"Unknown " << SlotName << " pattern!\");\n" - << " }\n\n N->addValue(Val); // Do not ever recalculate this\n" - << " return Val;\n}\n\n"; - } -} - diff --git a/support/tools/TableGen/InstrSelectorEmitter.h b/support/tools/TableGen/InstrSelectorEmitter.h deleted file mode 100644 index 922aa79dfa..0000000000 --- a/support/tools/TableGen/InstrSelectorEmitter.h +++ /dev/null @@ -1,387 +0,0 @@ -//===- InstrInfoEmitter.h - Generate a Instruction Set Desc. ----*- C++ -*-===// -// -// This tablegen backend is responsible for emitting a description of the target -// instruction set for the code generator. -// -//===----------------------------------------------------------------------===// - -#ifndef INSTRSELECTOR_EMITTER_H -#define INSTRSELECTOR_EMITTER_H - -#include "TableGenBackend.h" -#include "CodeGenWrappers.h" -#include <vector> -#include <map> -#include <cassert> - -class DagInit; -class Init; -class InstrSelectorEmitter; - -/// NodeType - Represents Information parsed from the DagNode entries. -/// -struct NodeType { - enum ArgResultTypes { - Any, // No constraint on type - Val, // A non-void type - Arg0, // Value matches the type of Arg0 - Arg1, // Value matches the type of Arg1 - Ptr, // Tree node is the type of the target pointer - I8, // Always bool - Void, // Tree node always returns void - }; - - ArgResultTypes ResultType; - std::vector<ArgResultTypes> ArgTypes; - - NodeType(ArgResultTypes RT, std::vector<ArgResultTypes> &AT) : ResultType(RT){ - AT.swap(ArgTypes); - } - - NodeType() : ResultType(Val) {} - NodeType(const NodeType &N) : ResultType(N.ResultType), ArgTypes(N.ArgTypes){} - - static ArgResultTypes Translate(Record *R); -}; - - - -/// TreePatternNode - Represent a node of the tree patterns. -/// -class TreePatternNode { - /// Operator - The operation that this node represents... this is null if this - /// is a leaf. - Record *Operator; - - /// Type - The inferred value type... - /// - MVT::ValueType Type; - - /// Children - If this is not a leaf (Operator != 0), this is the subtrees - /// that we contain. - std::vector<std::pair<TreePatternNode*, std::string> > Children; - - /// Value - If this node is a leaf, this indicates what the thing is. - /// - Init *Value; -public: - TreePatternNode(Record *o, const std::vector<std::pair<TreePatternNode*, - std::string> > &c) - : Operator(o), Type(MVT::Other), Children(c), Value(0) {} - TreePatternNode(Init *V) : Operator(0), Type(MVT::Other), Value(V) {} - - Record *getOperator() const { - assert(Operator && "This is a leaf node!"); - return Operator; - } - MVT::ValueType getType() const { return Type; } - void setType(MVT::ValueType T) { Type = T; } - - bool isLeaf() const { return Operator == 0; } - - unsigned getNumChildren() const { return Children.size(); } - TreePatternNode *getChild(unsigned c) const { - assert(Operator != 0 && "This is a leaf node!"); - assert(c < Children.size() && "Child access out of range!"); - return Children[c].first; - } - const std::string &getChildName(unsigned c) const { - assert(Operator != 0 && "This is a leaf node!"); - assert(c < Children.size() && "Child access out of range!"); - return Children[c].second; - } - - Init *getValue() const { - assert(Operator == 0 && "This is not a leaf node!"); - return Value; - } - - /// getValueRecord - Returns the value of this tree node as a record. For now - /// we only allow DefInit's as our leaf values, so this is used. - Record *getValueRecord() const; - - /// clone - Make a copy of this tree and all of its children. - /// - TreePatternNode *clone() const; - - void dump() const; - - /// InstantiateNonterminals - If this pattern refers to any nonterminals which - /// are not themselves completely resolved, clone the nonterminal and resolve - /// it with the using context we provide. - void InstantiateNonterminals(InstrSelectorEmitter &ISE); - - /// UpdateNodeType - Set the node type of N to VT if VT contains information. - /// If N already contains a conflicting type, then throw an exception. This - /// returns true if any information was updated. - /// - bool updateNodeType(MVT::ValueType VT, const std::string &RecName); -}; - -std::ostream &operator<<(std::ostream &OS, const TreePatternNode &N); - - - -/// Pattern - Represent a pattern of one form or another. Currently, three -/// types of patterns are possible: Instruction's, Nonterminals, and Expanders. -/// -struct Pattern { - enum PatternType { - Nonterminal, Instruction, Expander - }; -private: - /// PTy - The type of pattern this is. - /// - PatternType PTy; - - /// Tree - The tree pattern which corresponds to this pattern. Note that if - /// there was a (set) node on the outside level that it has been stripped off. - /// - TreePatternNode *Tree; - - /// Result - If this is an instruction or expander pattern, this is the - /// register result, specified with a (set) in the pattern. - /// - std::string ResultName; // The name of the result value... - TreePatternNode *ResultNode; // The leaf node for the result register... - - /// TheRecord - The actual TableGen record corresponding to this pattern. - /// - Record *TheRecord; - - /// Resolved - This is true of the pattern is useful in practice. In - /// particular, some non-terminals will have non-resolvable types. When a - /// user of the non-terminal is later found, they will have inferred a type - /// for the result of the non-terminal, which cause a clone of an unresolved - /// nonterminal to be made which is "resolved". - /// - bool Resolved; - - /// Args - This is a list of all of the arguments to this pattern, which are - /// the non-void leaf nodes in this pattern. - std::vector<std::pair<TreePatternNode*, std::string> > Args; - - /// ISE - the instruction selector emitter coordinating this madness. - /// - InstrSelectorEmitter &ISE; -public: - - /// Pattern constructor - Parse the specified DagInitializer into the current - /// record. - Pattern(PatternType pty, DagInit *RawPat, Record *TheRec, - InstrSelectorEmitter &ise); - - /// Pattern - Constructor used for cloning nonterminal patterns - Pattern(TreePatternNode *tree, Record *rec, bool res, - InstrSelectorEmitter &ise) - : PTy(Nonterminal), Tree(tree), ResultNode(0), TheRecord(rec), - Resolved(res), ISE(ise) { - calculateArgs(Tree, ""); - } - - /// getPatternType - Return what flavor of Record this pattern originated from - /// - PatternType getPatternType() const { return PTy; } - - /// getTree - Return the tree pattern which corresponds to this pattern. - /// - TreePatternNode *getTree() const { return Tree; } - - Record *getResult() const { - return ResultNode ? ResultNode->getValueRecord() : 0; - } - const std::string &getResultName() const { return ResultName; } - TreePatternNode *getResultNode() const { return ResultNode; } - - /// getRecord - Return the actual TableGen record corresponding to this - /// pattern. - /// - Record *getRecord() const { return TheRecord; } - - unsigned getNumArgs() const { return Args.size(); } - TreePatternNode *getArg(unsigned i) const { - assert(i < Args.size() && "Argument reference out of range!"); - return Args[i].first; - } - Record *getArgRec(unsigned i) const { - return getArg(i)->getValueRecord(); - } - Init *getArgVal(unsigned i) const { - return getArg(i)->getValue(); - } - const std::string &getArgName(unsigned i) const { - assert(i < Args.size() && "Argument reference out of range!"); - return Args[i].second; - } - - bool isResolved() const { return Resolved; } - - /// InferAllTypes - Runs the type inference engine on the current pattern, - /// stopping when nothing can be inferred, then updating the Resolved field. - void InferAllTypes(); - - /// InstantiateNonterminals - If this pattern refers to any nonterminals which - /// are not themselves completely resolved, clone the nonterminal and resolve - /// it with the using context we provide. - void InstantiateNonterminals() { - Tree->InstantiateNonterminals(ISE); - } - - /// clone - This method is used to make an exact copy of the current pattern, - /// then change the "TheRecord" instance variable to the specified record. - /// - Pattern *clone(Record *R) const; - - /// error - Throw an exception, prefixing it with information about this - /// pattern. - void error(const std::string &Msg) const; - - /// getSlotName - If this is a leaf node, return the slot name that the - /// operand will update. - std::string getSlotName() const; - static std::string getSlotName(Record *R); - - void dump() const; - -private: - void calculateArgs(TreePatternNode *N, const std::string &Name); - MVT::ValueType getIntrinsicType(Record *R) const; - TreePatternNode *ParseTreePattern(DagInit *DI); - bool InferTypes(TreePatternNode *N, bool &MadeChange); -}; - -std::ostream &operator<<(std::ostream &OS, const Pattern &P); - - -/// PatternOrganizer - This class represents all of the patterns which are -/// useful for the instruction selector, neatly catagorized in a hierarchical -/// structure. -struct PatternOrganizer { - /// PatternsForNode - The list of patterns which can produce a value of a - /// particular slot type, given a particular root node in the tree. All of - /// the patterns in this vector produce the same value type and have the same - /// root DAG node. - typedef std::vector<Pattern*> PatternsForNode; - - /// NodesForSlot - This map keeps track of all of the root DAG nodes which can - /// lead to the production of a value for this slot. All of the patterns in - /// this data structure produces values of the same slot. - typedef std::map<Record*, PatternsForNode> NodesForSlot; - - /// AllPatterns - This data structure contains all patterns in the instruction - /// selector. - std::map<std::string, NodesForSlot> AllPatterns; - - // Forwarding functions... - typedef std::map<std::string, NodesForSlot>::iterator iterator; - iterator begin() { return AllPatterns.begin(); } - iterator end() { return AllPatterns.end(); } - - - /// addPattern - Add the specified pattern to the appropriate location in the - /// collection. - void addPattern(Pattern *P); -}; - - -/// InstrSelectorEmitter - The top-level class which coordinates construction -/// and emission of the instruction selector. -/// -class InstrSelectorEmitter : public TableGenBackend { - RecordKeeper &Records; - CodeGenTarget Target; - - std::map<Record*, NodeType> NodeTypes; - - /// Patterns - a list of all of the patterns defined by the target description - /// - std::map<Record*, Pattern*> Patterns; - - /// InstantiatedNTs - A data structure to keep track of which nonterminals - /// have been instantiated already... - /// - std::map<std::pair<Pattern*,MVT::ValueType>, Record*> InstantiatedNTs; - - /// ComputableValues - This map indicates which patterns can be used to - /// generate a value that is used by the selector. The keys of this map - /// implicitly define the values that are used by the selector. - /// - PatternOrganizer ComputableValues; - -public: - InstrSelectorEmitter(RecordKeeper &R) : Records(R) {} - - // run - Output the instruction set description, returning true on failure. - void run(std::ostream &OS); - - const CodeGenTarget &getTarget() const { return Target; } - std::map<Record*, NodeType> &getNodeTypes() { return NodeTypes; } - const NodeType &getNodeType(Record *R) const { - std::map<Record*, NodeType>::const_iterator I = NodeTypes.find(R); - assert(I != NodeTypes.end() && "Unknown node type!"); - return I->second; - } - - /// getPattern - return the pattern corresponding to the specified record, or - /// null if there is none. - Pattern *getPattern(Record *R) const { - std::map<Record*, Pattern*>::const_iterator I = Patterns.find(R); - return I != Patterns.end() ? I->second : 0; - } - - /// ReadNonterminal - This method parses the specified record as a - /// nonterminal, but only if it hasn't been read in already. - Pattern *ReadNonterminal(Record *R); - - /// InstantiateNonterminal - This method takes the nonterminal specified by - /// NT, which should not be completely resolved, clones it, applies ResultTy - /// to its root, then runs the type inference stuff on it. This should - /// produce a newly resolved nonterminal, which we make a record for and - /// return. To be extra fancy and efficient, this only makes one clone for - /// each type it is instantiated with. - Record *InstantiateNonterminal(Pattern *NT, MVT::ValueType ResultTy); - -private: - // ReadNodeTypes - Read in all of the node types in the current RecordKeeper, - // turning them into the more accessible NodeTypes data structure. - void ReadNodeTypes(); - - // ReadNonTerminals - Read in all nonterminals and incorporate them into our - // pattern database. - void ReadNonterminals(); - - // ReadInstructionPatterns - Read in all subclasses of Instruction, and - // process those with a useful Pattern field. - void ReadInstructionPatterns(); - - // ReadExpanderPatterns - Read in all of the expanded patterns. - void ReadExpanderPatterns(); - - // InstantiateNonterminals - Instantiate any unresolved nonterminals with - // information from the context that they are used in. - void InstantiateNonterminals(); - - // CalculateComputableValues - Fill in the ComputableValues map through - // analysis of the patterns we are playing with. - void CalculateComputableValues(); - - // EmitMatchCosters - Given a list of patterns, which all have the same root - // pattern operator, emit an efficient decision tree to decide which one to - // pick. This is structured this way to avoid reevaluations of non-obvious - // subexpressions. - void EmitMatchCosters(std::ostream &OS, - const std::vector<std::pair<Pattern*, TreePatternNode*> > &Patterns, - const std::string &VarPrefix, unsigned Indent); - - /// PrintExpanderOperand - Print out Arg as part of the instruction emission - /// process for the expander pattern P. This argument may be referencing some - /// values defined in P, or may just be physical register references or - /// something like that. If PrintArg is true, we are printing out arguments - /// to the BuildMI call. If it is false, we are printing the result register - /// name. - void PrintExpanderOperand(Init *Arg, const std::string &NameVar, - TreePatternNode *ArgDecl, Pattern *P, - bool PrintArg, std::ostream &OS); -}; - -#endif diff --git a/support/tools/TableGen/Makefile b/support/tools/TableGen/Makefile deleted file mode 100644 index b06ca9b7e1..0000000000 --- a/support/tools/TableGen/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -LEVEL = ../../.. -TOOLNAME = tblgen -USEDLIBS = support.a - -.PRECIOUS: FileLexer.cpp FileParser.cpp - -include $(LEVEL)/Makefile.common - -# -# Make the source file depend on the header file. In this way, dependencies -# (which depend on the source file) won't get generated until bison is done -# generating the C source and header files for the parser. -# -FileLexer.cpp: FileParser.h - -clean:: - -rm -f FileParser.cpp FileParser.h FileLexer.cpp CommandLine.cpp - -rm -f FileParser.output diff --git a/support/tools/TableGen/Record.cpp b/support/tools/TableGen/Record.cpp deleted file mode 100644 index 384005081e..0000000000 --- a/support/tools/TableGen/Record.cpp +++ /dev/null @@ -1,676 +0,0 @@ -//===- Record.cpp - Record implementation ---------------------------------===// -// -// -//===----------------------------------------------------------------------===// - -#include "Record.h" - -//===----------------------------------------------------------------------===// -// Type implementations -//===----------------------------------------------------------------------===// - -void RecTy::dump() const { print(std::cerr); } - -Init *BitRecTy::convertValue(BitsInit *BI) { - if (BI->getNumBits() != 1) return 0; // Only accept if just one bit! - return BI->getBit(0); -} - -bool BitRecTy::baseClassOf(const BitsRecTy *RHS) const { - return RHS->getNumBits() == 1; -} - -Init *BitRecTy::convertValue(IntInit *II) { - int Val = II->getValue(); - if (Val != 0 && Val != 1) return 0; // Only accept 0 or 1 for a bit! - - return new BitInit(Val != 0); -} - -Init *BitRecTy::convertValue(TypedInit *VI) { - if (dynamic_cast<BitRecTy*>(VI->getType())) - return VI; // Accept variable if it is already of bit type! - return 0; -} - -Init *BitsRecTy::convertValue(UnsetInit *UI) { - BitsInit *Ret = new BitsInit(Size); - - for (unsigned i = 0; i != Size; ++i) - Ret->setBit(i, new UnsetInit()); - return Ret; -} - -Init *BitsRecTy::convertValue(BitInit *UI) { - if (Size != 1) return 0; // Can only convert single bit... - BitsInit *Ret = new BitsInit(1); - Ret->setBit(0, UI); - return Ret; -} - -// convertValue from Int initializer to bits type: Split the integer up into the -// appropriate bits... -// -Init *BitsRecTy::convertValue(IntInit *II) { - int Value = II->getValue(); - // Make sure this bitfield is large enough to hold the integer value... - if (Value >= 0) { - if (Value & ~((1 << Size)-1)) - return 0; - } else { - if ((Value >> Size) != -1 || ((Value & (1 << Size-1)) == 0)) - return 0; - } - - BitsInit *Ret = new BitsInit(Size); - for (unsigned i = 0; i != Size; ++i) - Ret->setBit(i, new BitInit(Value & (1 << i))); - - return Ret; -} - -Init *BitsRecTy::convertValue(BitsInit *BI) { - // If the number of bits is right, return it. Otherwise we need to expand or - // truncate... - if (BI->getNumBits() == Size) return BI; - return 0; -} - -Init *BitsRecTy::convertValue(TypedInit *VI) { - if (BitsRecTy *BRT = dynamic_cast<BitsRecTy*>(VI->getType())) - if (BRT->Size == Size) { - BitsInit *Ret = new BitsInit(Size); - for (unsigned i = 0; i != Size; ++i) - Ret->setBit(i, new VarBitInit(VI, i)); - return Ret; - } - if (Size == 1 && dynamic_cast<BitRecTy*>(VI->getType())) { - BitsInit *Ret = new BitsInit(1); - Ret->setBit(0, VI); - return Ret; - } - - return 0; -} - -Init *IntRecTy::convertValue(BitInit *BI) { - return new IntInit(BI->getValue()); -} - -Init *IntRecTy::convertValue(BitsInit *BI) { - int Result = 0; - for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) - if (BitInit *Bit = dynamic_cast<BitInit*>(BI->getBit(i))) { - Result |= Bit->getValue() << i; - } else { - return 0; - } - return new IntInit(Result); -} - -Init *IntRecTy::convertValue(TypedInit *TI) { - if (TI->getType()->typeIsConvertibleTo(this)) - return TI; // Accept variable if already of the right type! - return 0; -} - -Init *StringRecTy::convertValue(TypedInit *TI) { - if (dynamic_cast<StringRecTy*>(TI->getType())) - return TI; // Accept variable if already of the right type! - return 0; -} - -void ListRecTy::print(std::ostream &OS) const { - OS << "list<" << *Ty << ">"; -} - -Init *ListRecTy::convertValue(ListInit *LI) { - std::vector<Init*> Elements; - - // Verify that all of the elements of the list are subclasses of the - // appropriate class! - for (unsigned i = 0, e = LI->getSize(); i != e; ++i) - if (Init *CI = LI->getElement(i)->convertInitializerTo(Ty)) - Elements.push_back(CI); - else - return 0; - - return new ListInit(Elements); -} - -Init *ListRecTy::convertValue(TypedInit *TI) { - // Ensure that TI is compatible with our class. - if (ListRecTy *LRT = dynamic_cast<ListRecTy*>(TI->getType())) - if (LRT->getElementType()->typeIsConvertibleTo(getElementType())) - return TI; - return 0; -} - -Init *CodeRecTy::convertValue(TypedInit *TI) { - if (TI->getType()->typeIsConvertibleTo(this)) - return TI; - return 0; -} - -Init *DagRecTy::convertValue(TypedInit *TI) { - if (TI->getType()->typeIsConvertibleTo(this)) - return TI; - return 0; -} - - -void RecordRecTy::print(std::ostream &OS) const { - OS << Rec->getName(); -} - -Init *RecordRecTy::convertValue(DefInit *DI) { - // Ensure that DI is a subclass of Rec. - if (!DI->getDef()->isSubClassOf(Rec)) - return 0; - return DI; -} - -Init *RecordRecTy::convertValue(TypedInit *TI) { - // Ensure that TI is compatible with Rec. - if (RecordRecTy *RRT = dynamic_cast<RecordRecTy*>(TI->getType())) - if (RRT->getRecord()->isSubClassOf(getRecord()) || - RRT->getRecord() == getRecord()) - return TI; - return 0; -} - -bool RecordRecTy::baseClassOf(const RecordRecTy *RHS) const { - return Rec == RHS->getRecord() || RHS->getRecord()->isSubClassOf(Rec); -} - - -//===----------------------------------------------------------------------===// -// Initializer implementations -//===----------------------------------------------------------------------===// - -void Init::dump() const { return print(std::cerr); } - -Init *BitsInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) { - BitsInit *BI = new BitsInit(Bits.size()); - for (unsigned i = 0, e = Bits.size(); i != e; ++i) { - if (Bits[i] >= getNumBits()) { - delete BI; - return 0; - } - BI->setBit(i, getBit(Bits[i])); - } - return BI; -} - -void BitsInit::print(std::ostream &OS) const { - //if (!printInHex(OS)) return; - //if (!printAsVariable(OS)) return; - //if (!printAsUnset(OS)) return; - - OS << "{ "; - for (unsigned i = 0, e = getNumBits(); i != e; ++i) { - if (i) OS << ", "; - if (Init *Bit = getBit(e-i-1)) - Bit->print(OS); - else - OS << "*"; - } - OS << " }"; -} - -bool BitsInit::printInHex(std::ostream &OS) const { - // First, attempt to convert the value into an integer value... - int Result = 0; - for (unsigned i = 0, e = getNumBits(); i != e; ++i) - if (BitInit *Bit = dynamic_cast<BitInit*>(getBit(i))) { - Result |= Bit->getValue() << i; - } else { - return true; - } - - OS << "0x" << std::hex << Result << std::dec; - return false; -} - -bool BitsInit::printAsVariable(std::ostream &OS) const { - // Get the variable that we may be set equal to... - assert(getNumBits() != 0); - VarBitInit *FirstBit = dynamic_cast<VarBitInit*>(getBit(0)); - if (FirstBit == 0) return true; - TypedInit *Var = FirstBit->getVariable(); - - // Check to make sure the types are compatible. - BitsRecTy *Ty = dynamic_cast<BitsRecTy*>(FirstBit->getVariable()->getType()); - if (Ty == 0) return true; - if (Ty->getNumBits() != getNumBits()) return true; // Incompatible types! - - // Check to make sure all bits are referring to the right bits in the variable - for (unsigned i = 0, e = getNumBits(); i != e; ++i) { - VarBitInit *Bit = dynamic_cast<VarBitInit*>(getBit(i)); - if (Bit == 0 || Bit->getVariable() != Var || Bit->getBitNum() != i) - return true; - } - - Var->print(OS); - return false; -} - -bool BitsInit::printAsUnset(std::ostream &OS) const { - for (unsigned i = 0, e = getNumBits(); i != e; ++i) - if (!dynamic_cast<UnsetInit*>(getBit(i))) - return true; - OS << "?"; - return false; -} - -// resolveReferences - If there are any field references that refer to fields -// that have been filled in, we can propagate the values now. -// -Init *BitsInit::resolveReferences(Record &R) { - bool Changed = false; - BitsInit *New = new BitsInit(getNumBits()); - - for (unsigned i = 0, e = Bits.size(); i != e; ++i) { - Init *B; - Init *CurBit = getBit(i); - - do { - B = CurBit; - CurBit = CurBit->resolveReferences(R); - Changed |= B != CurBit; - } while (B != CurBit); - New->setBit(i, CurBit); - } - - if (Changed) - return New; - delete New; - return this; -} - -Init *IntInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) { - BitsInit *BI = new BitsInit(Bits.size()); - - for (unsigned i = 0, e = Bits.size(); i != e; ++i) { - if (Bits[i] >= 32) { - delete BI; - return 0; - } - BI->setBit(i, new BitInit(Value & (1 << Bits[i]))); - } - return BI; -} - -void ListInit::print(std::ostream &OS) const { - OS << "["; - for (unsigned i = 0, e = Values.size(); i != e; ++i) { - if (i) OS << ", "; - OS << *Values[i]; - } - OS << "]"; -} - -Init *VarInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) { - BitsRecTy *T = dynamic_cast<BitsRecTy*>(getType()); - if (T == 0) return 0; // Cannot subscript a non-bits variable... - unsigned NumBits = T->getNumBits(); - - BitsInit *BI = new BitsInit(Bits.size()); - for (unsigned i = 0, e = Bits.size(); i != e; ++i) { - if (Bits[i] >= NumBits) { - delete BI; - return 0; - } - BI->setBit(i, new VarBitInit(this, Bits[i])); - } - return BI; -} - -Init *VarInit::resolveBitReference(Record &R, unsigned Bit) { - if (R.isTemplateArg(getName())) - return this; - - RecordVal *RV = R.getValue(getName()); - assert(RV && "Reference to a non-existant variable?"); - assert(dynamic_cast<BitsInit*>(RV->getValue())); - BitsInit *BI = (BitsInit*)RV->getValue(); - - assert(Bit < BI->getNumBits() && "Bit reference out of range!"); - Init *B = BI->getBit(Bit); - - if (!dynamic_cast<UnsetInit*>(B)) // If the bit is not set... - return B; // Replace the VarBitInit with it. - return this; -} - -RecTy *VarInit::getFieldType(const std::string &FieldName) const { - if (RecordRecTy *RTy = dynamic_cast<RecordRecTy*>(getType())) - if (const RecordVal *RV = RTy->getRecord()->getValue(FieldName)) - return RV->getType(); - return 0; -} - -Init *VarInit::getFieldInit(Record &R, const std::string &FieldName) const { - if (RecordRecTy *RTy = dynamic_cast<RecordRecTy*>(getType())) - if (const RecordVal *RV = R.getValue(VarName)) - if (Init *I = RV->getValue()->getFieldInit(R, FieldName)) - return I; - else - return 0; - return 0; -} - -/// resolveReferences - This method is used by classes that refer to other -/// variables which may not be defined at the time they expression is formed. -/// If a value is set for the variable later, this method will be called on -/// users of the value to allow the value to propagate out. -/// -Init *VarInit::resolveReferences(Record &R) { - if (RecordVal *Val = R.getValue(VarName)) - if (!dynamic_cast<UnsetInit*>(Val->getValue())) - return Val->getValue(); - return this; -} - - -Init *VarBitInit::resolveReferences(Record &R) { - Init *I = getVariable()->resolveBitReference(R, getBitNum()); - if (I != getVariable()) - return I; - return this; -} - -RecTy *DefInit::getFieldType(const std::string &FieldName) const { - if (const RecordVal *RV = Def->getValue(FieldName)) - return RV->getType(); - return 0; -} - -Init *DefInit::getFieldInit(Record &R, const std::string &FieldName) const { - return Def->getValue(FieldName)->getValue(); -} - - -void DefInit::print(std::ostream &OS) const { - OS << Def->getName(); -} - -Init *FieldInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) { - BitsRecTy *T = dynamic_cast<BitsRecTy*>(getType()); - if (T == 0) return 0; // Cannot subscript a non-bits field... - unsigned NumBits = T->getNumBits(); - - BitsInit *BI = new BitsInit(Bits.size()); - for (unsigned i = 0, e = Bits.size(); i != e; ++i) { - if (Bits[i] >= NumBits) { - delete BI; - return 0; - } - BI->setBit(i, new VarBitInit(this, Bits[i])); - } - return BI; -} - -Init *FieldInit::resolveBitReference(Record &R, unsigned Bit) { - Init *BitsVal = Rec->getFieldInit(R, FieldName); - if (BitsVal) - if (BitsInit *BI = dynamic_cast<BitsInit*>(BitsVal)) { - assert(Bit < BI->getNumBits() && "Bit reference out of range!"); - Init *B = BI->getBit(Bit); - - if (dynamic_cast<BitInit*>(B)) // If the bit is set... - return B; // Replace the VarBitInit with it. - } - return this; -} - -Init *FieldInit::resolveReferences(Record &R) { - Init *BitsVal = Rec->getFieldInit(R, FieldName); - if (BitsVal) { - Init *BVR = BitsVal->resolveReferences(R); - return BVR->isComplete() ? BVR : this; - } - return this; -} - - -void DagInit::print(std::ostream &OS) const { - OS << "(" << NodeTypeDef->getName(); - if (Args.size()) { - OS << " " << *Args[0]; - if (!ArgNames[0].empty()) OS << ":$" << ArgNames[0]; - for (unsigned i = 1, e = Args.size(); i != e; ++i) { - OS << ", " << *Args[i]; - if (!ArgNames[i].empty()) OS << ":$" << ArgNames[i]; - } - } - OS << ")"; -} - - -//===----------------------------------------------------------------------===// -// Other implementations -//===----------------------------------------------------------------------===// - -RecordVal::RecordVal(const std::string &N, RecTy *T, unsigned P) - : Name(N), Ty(T), Prefix(P) { - Value = Ty->convertValue(new UnsetInit()); - assert(Value && "Cannot create unset value for current type!"); -} - -void RecordVal::dump() const { std::cerr << *this; } - -void RecordVal::print(std::ostream &OS, bool PrintSem) const { - if (getPrefix()) OS << "field "; - OS << *getType() << " " << getName(); - if (getValue()) { - OS << " = " << *getValue(); - } - if (PrintSem) OS << ";\n"; -} - -// resolveReferences - If there are any field references that refer to fields -// that have been filled in, we can propagate the values now. -// -void Record::resolveReferences() { - for (unsigned i = 0, e = Values.size(); i != e; ++i) - Values[i].setValue(Values[i].getValue()->resolveReferences(*this)); -} - -void Record::dump() const { std::cerr << *this; } - -std::ostream &operator<<(std::ostream &OS, const Record &R) { - OS << R.getName(); - - const std::vector<std::string> &TArgs = R.getTemplateArgs(); - if (!TArgs.empty()) { - OS << "<"; - for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { - if (i) OS << ", "; - const RecordVal *RV = R.getValue(TArgs[i]); - assert(RV && "Template argument record not found??"); - RV->print(OS, false); - } - OS << ">"; - } - - OS << " {"; - const std::vector<Record*> &SC = R.getSuperClasses(); - if (!SC.empty()) { - OS << "\t//"; - for (unsigned i = 0, e = SC.size(); i != e; ++i) - OS << " " << SC[i]->getName(); - } - OS << "\n"; - - const std::vector<RecordVal> &Vals = R.getValues(); - for (unsigned i = 0, e = Vals.size(); i != e; ++i) - if (Vals[i].getPrefix() && !R.isTemplateArg(Vals[i].getName())) - OS << Vals[i]; - for (unsigned i = 0, e = Vals.size(); i != e; ++i) - if (!Vals[i].getPrefix() && !R.isTemplateArg(Vals[i].getName())) - OS << Vals[i]; - - return OS << "}\n"; -} - -/// getValueInit - Return the initializer for a value with the specified name, -/// or throw an exception if the field does not exist. -/// -Init *Record::getValueInit(const std::string &FieldName) const { - const RecordVal *R = getValue(FieldName); - if (R == 0 || R->getValue() == 0) - throw "Record '" + getName() + "' does not have a field named '" + - FieldName + "!\n"; - return R->getValue(); -} - - -/// getValueAsString - This method looks up the specified field and returns its -/// value as a string, throwing an exception if the field does not exist or if -/// the value is not a string. -/// -std::string Record::getValueAsString(const std::string &FieldName) const { - const RecordVal *R = getValue(FieldName); - if (R == 0 || R->getValue() == 0) - throw "Record '" + getName() + "' does not have a field named '" + - FieldName + "!\n"; - - if (const StringInit *SI = dynamic_cast<const StringInit*>(R->getValue())) - return SI->getValue(); - throw "Record '" + getName() + "', field '" + FieldName + - "' does not have a string initializer!"; -} - -/// getValueAsBitsInit - This method looks up the specified field and returns -/// its value as a BitsInit, throwing an exception if the field does not exist -/// or if the value is not the right type. -/// -BitsInit *Record::getValueAsBitsInit(const std::string &FieldName) const { - const RecordVal *R = getValue(FieldName); - if (R == 0 || R->getValue() == 0) - throw "Record '" + getName() + "' does not have a field named '" + - FieldName + "!\n"; - - if (BitsInit *BI = dynamic_cast<BitsInit*>(R->getValue())) - return BI; - throw "Record '" + getName() + "', field '" + FieldName + - "' does not have a BitsInit initializer!"; -} - -/// getValueAsListInit - This method looks up the specified field and returns -/// its value as a ListInit, throwing an exception if the field does not exist -/// or if the value is not the right type. -/// -ListInit *Record::getValueAsListInit(const std::string &FieldName) const { - const RecordVal *R = getValue(FieldName); - if (R == 0 || R->getValue() == 0) - throw "Record '" + getName() + "' does not have a field named '" + - FieldName + "!\n"; - - if (ListInit *LI = dynamic_cast<ListInit*>(R->getValue())) - return LI; - throw "Record '" + getName() + "', field '" + FieldName + - "' does not have a list initializer!"; -} - -/// getValueAsInt - This method looks up the specified field and returns its -/// value as an int, throwing an exception if the field does not exist or if -/// the value is not the right type. -/// -int Record::getValueAsInt(const std::string &FieldName) const { - const RecordVal *R = getValue(FieldName); - if (R == 0 || R->getValue() == 0) - throw "Record '" + getName() + "' does not have a field named '" + - FieldName + "!\n"; - - if (IntInit *II = dynamic_cast<IntInit*>(R->getValue())) - return II->getValue(); - throw "Record '" + getName() + "', field '" + FieldName + - "' does not have a list initializer!"; -} - -/// getValueAsDef - This method looks up the specified field and returns its -/// value as a Record, throwing an exception if the field does not exist or if -/// the value is not the right type. -/// -Record *Record::getValueAsDef(const std::string &FieldName) const { - const RecordVal *R = getValue(FieldName); - if (R == 0 || R->getValue() == 0) - throw "Record '" + getName() + "' does not have a field named '" + - FieldName + "!\n"; - - if (DefInit *DI = dynamic_cast<DefInit*>(R->getValue())) - return DI->getDef(); - throw "Record '" + getName() + "', field '" + FieldName + - "' does not have a list initializer!"; -} - -/// getValueAsBit - This method looks up the specified field and returns its -/// value as a bit, throwing an exception if the field does not exist or if -/// the value is not the right type. -/// -bool Record::getValueAsBit(const std::string &FieldName) const { - const RecordVal *R = getValue(FieldName); - if (R == 0 || R->getValue() == 0) - throw "Record '" + getName() + "' does not have a field named '" + - FieldName + "!\n"; - - if (BitInit *BI = dynamic_cast<BitInit*>(R->getValue())) - return BI->getValue(); - throw "Record '" + getName() + "', field '" + FieldName + - "' does not have a bit initializer!"; -} - -/// getValueAsDag - This method looks up the specified field and returns its -/// value as an Dag, throwing an exception if the field does not exist or if -/// the value is not the right type. -/// -DagInit *Record::getValueAsDag(const std::string &FieldName) const { - const RecordVal *R = getValue(FieldName); - if (R == 0 || R->getValue() == 0) - throw "Record '" + getName() + "' does not have a field named '" + - FieldName + "!\n"; - - if (DagInit *DI = dynamic_cast<DagInit*>(R->getValue())) - return DI; - throw "Record '" + getName() + "', field '" + FieldName + - "' does not have a dag initializer!"; -} - - -void RecordKeeper::dump() const { std::cerr << *this; } - -std::ostream &operator<<(std::ostream &OS, const RecordKeeper &RK) { - OS << "------------- Classes -----------------\n"; - const std::map<std::string, Record*> &Classes = RK.getClasses(); - for (std::map<std::string, Record*>::const_iterator I = Classes.begin(), - E = Classes.end(); I != E; ++I) - OS << "class " << *I->second; - - OS << "------------- Defs -----------------\n"; - const std::map<std::string, Record*> &Defs = RK.getDefs(); - for (std::map<std::string, Record*>::const_iterator I = Defs.begin(), - E = Defs.end(); I != E; ++I) - OS << "def " << *I->second; - return OS; -} - - -/// getAllDerivedDefinitions - This method returns all concrete definitions -/// that derive from the specified class name. If a class with the specified -/// name does not exist, an error is printed and true is returned. -std::vector<Record*> -RecordKeeper::getAllDerivedDefinitions(const std::string &ClassName) const { - Record *Class = Records.getClass(ClassName); - if (!Class) - throw "ERROR: Couldn't find the '" + ClassName + "' class!\n"; - - std::vector<Record*> Defs; - for (std::map<std::string, Record*>::const_iterator I = getDefs().begin(), - E = getDefs().end(); I != E; ++I) - if (I->second->isSubClassOf(Class)) - Defs.push_back(I->second); - - return Defs; -} diff --git a/support/tools/TableGen/Record.h b/support/tools/TableGen/Record.h deleted file mode 100644 index 4a2fa057cf..0000000000 --- a/support/tools/TableGen/Record.h +++ /dev/null @@ -1,849 +0,0 @@ -//===- Record.h - Classes to represent Table Records ------------*- C++ -*-===// -// -// This file defines the main TableGen data structures, including the TableGen -// types, values, and high-level data structures. -// -//===----------------------------------------------------------------------===// - -#ifndef RECORD_H -#define RECORD_H - -#include <string> -#include <vector> -#include <map> -#include <iostream> -#include <cassert> - -// RecTy subclasses... -class BitRecTy; -class BitsRecTy; -class IntRecTy; -class StringRecTy; -class ListRecTy; -class CodeRecTy; -class DagRecTy; -class RecordRecTy; - -// Init subclasses... -class Init; -class UnsetInit; -class BitInit; -class BitsInit; -class IntInit; -class StringInit; -class CodeInit; -class ListInit; -class DefInit; -class DagInit; -class TypedInit; -class VarInit; -class FieldInit; -class VarBitInit; - -// Other classes... -class Record; - -//===----------------------------------------------------------------------===// -// Type Classes -//===----------------------------------------------------------------------===// - -struct RecTy { - virtual ~RecTy() {} - - virtual void print(std::ostream &OS) const = 0; - void dump() const; - - /// typeIsConvertibleTo - Return true if all values of 'this' type can be - /// converted to the specified type. - virtual bool typeIsConvertibleTo(const RecTy *RHS) const = 0; - -public: // These methods should only be called from subclasses of Init - virtual Init *convertValue( UnsetInit *UI) { return 0; } - virtual Init *convertValue( BitInit *BI) { return 0; } - virtual Init *convertValue( BitsInit *BI) { return 0; } - virtual Init *convertValue( IntInit *II) { return 0; } - virtual Init *convertValue(StringInit *SI) { return 0; } - virtual Init *convertValue( ListInit *LI) { return 0; } - virtual Init *convertValue( CodeInit *CI) { return 0; } - virtual Init *convertValue(VarBitInit *VB) { return 0; } - virtual Init *convertValue( DefInit *DI) { return 0; } - virtual Init *convertValue( DagInit *DI) { return 0; } - virtual Init *convertValue( TypedInit *TI) { return 0; } - virtual Init *convertValue( VarInit *VI) { - return convertValue((TypedInit*)VI); - } - virtual Init *convertValue( FieldInit *FI) { - return convertValue((TypedInit*)FI); - } - -public: // These methods should only be called by subclasses of RecTy. - // baseClassOf - These virtual methods should be overloaded to return true iff - // all values of type 'RHS' can be converted to the 'this' type. - virtual bool baseClassOf(const BitRecTy *RHS) const { return false; } - virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; } - virtual bool baseClassOf(const IntRecTy *RHS) const { return false; } - virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } - virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } - virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; } - virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } - virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } -}; - -inline std::ostream &operator<<(std::ostream &OS, const RecTy &Ty) { - Ty.print(OS); - return OS; -} - - -/// BitRecTy - 'bit' - Represent a single bit -/// -struct BitRecTy : public RecTy { - Init *convertValue(UnsetInit *UI) { return (Init*)UI; } - Init *convertValue(BitInit *BI) { return (Init*)BI; } - Init *convertValue(BitsInit *BI); - Init *convertValue(IntInit *II); - Init *convertValue(TypedInit *VI); - Init *convertValue(VarBitInit *VB) { return (Init*)VB; } - - void print(std::ostream &OS) const { OS << "bit"; } - - bool typeIsConvertibleTo(const RecTy *RHS) const { - return RHS->baseClassOf(this); - } - virtual bool baseClassOf(const BitRecTy *RHS) const { return true; } - virtual bool baseClassOf(const BitsRecTy *RHS) const; - virtual bool baseClassOf(const IntRecTy *RHS) const { return true; } -}; - - -/// BitsRecTy - 'bits<n>' - Represent a fixed number of bits -/// -class BitsRecTy : public RecTy { - unsigned Size; -public: - BitsRecTy(unsigned Sz) : Size(Sz) {} - - unsigned getNumBits() const { return Size; } - - Init *convertValue(UnsetInit *UI); - Init *convertValue(BitInit *UI); - Init *convertValue(BitsInit *BI); - Init *convertValue(IntInit *II); - Init *convertValue(TypedInit *VI); - - void print(std::ostream &OS) const { OS << "bits<" << Size << ">"; } - - bool typeIsConvertibleTo(const RecTy *RHS) const { - return RHS->baseClassOf(this); - } - virtual bool baseClassOf(const BitRecTy *RHS) const { return Size == 1; } - virtual bool baseClassOf(const IntRecTy *RHS) const { return true; } - virtual bool baseClassOf(const BitsRecTy *RHS) const { - return RHS->Size == Size; - } -}; - - -/// IntRecTy - 'int' - Represent an integer value of no particular size -/// -struct IntRecTy : public RecTy { - Init *convertValue(UnsetInit *UI) { return (Init*)UI; } - Init *convertValue(IntInit *II) { return (Init*)II; } - Init *convertValue(BitInit *BI); - Init *convertValue(BitsInit *BI); - Init *convertValue(TypedInit *TI); - - void print(std::ostream &OS) const { OS << "int"; } - - bool typeIsConvertibleTo(const RecTy *RHS) const { - return RHS->baseClassOf(this); - } - - virtual bool baseClassOf(const BitRecTy *RHS) const { return true; } - virtual bool baseClassOf(const IntRecTy *RHS) const { return true; } - virtual bool baseClassOf(const BitsRecTy *RHS) const { return true; } -}; - -/// StringRecTy - 'string' - Represent an string value -/// -struct StringRecTy : public RecTy { - Init *convertValue(UnsetInit *UI) { return (Init*)UI; } - Init *convertValue(StringInit *SI) { return (Init*)SI; } - Init *convertValue(TypedInit *TI); - void print(std::ostream &OS) const { OS << "string"; } - - bool typeIsConvertibleTo(const RecTy *RHS) const { - return RHS->baseClassOf(this); - } - - virtual bool baseClassOf(const StringRecTy *RHS) const { return true; } -}; - -/// ListRecTy - 'list<Ty>' - Represent a list of values, all of which must be of -/// the specified type. -/// -class ListRecTy : public RecTy { - RecTy *Ty; -public: - ListRecTy(RecTy *T) : Ty(T) {} - - RecTy *getElementType() const { return Ty; } - - Init *convertValue(UnsetInit *UI) { return (Init*)UI; } - Init *convertValue(ListInit *LI); - Init *convertValue(TypedInit *TI); - - void print(std::ostream &OS) const; - - bool typeIsConvertibleTo(const RecTy *RHS) const { - return RHS->baseClassOf(this); - } - - virtual bool baseClassOf(const ListRecTy *RHS) const { - return RHS->getElementType()->typeIsConvertibleTo(Ty); - } -}; - -/// CodeRecTy - 'code' - Represent an code fragment, function or method. -/// -struct CodeRecTy : public RecTy { - Init *convertValue(UnsetInit *UI) { return (Init*)UI; } - Init *convertValue( CodeInit *CI) { return (Init*)CI; } - Init *convertValue(TypedInit *TI); - - void print(std::ostream &OS) const { OS << "code"; } - - bool typeIsConvertibleTo(const RecTy *RHS) const { - return RHS->baseClassOf(this); - } - virtual bool baseClassOf(const CodeRecTy *RHS) const { return true; } -}; - -/// DagRecTy - 'dag' - Represent a dag fragment -/// -struct DagRecTy : public RecTy { - Init *convertValue(UnsetInit *UI) { return (Init*)UI; } - Init *convertValue( DagInit *CI) { return (Init*)CI; } - Init *convertValue(TypedInit *TI); - - void print(std::ostream &OS) const { OS << "dag"; } - - bool typeIsConvertibleTo(const RecTy *RHS) const { - return RHS->baseClassOf(this); - } - virtual bool baseClassOf(const DagRecTy *RHS) const { return true; } -}; - - -/// RecordRecTy - '<classname>' - Represent an instance of a class, such as: -/// (R32 X = EAX). -/// -class RecordRecTy : public RecTy { - Record *Rec; -public: - RecordRecTy(Record *R) : Rec(R) {} - - Record *getRecord() const { return Rec; } - - Init *convertValue(UnsetInit *UI) { return (Init*)UI; } - Init *convertValue( DefInit *DI); - Init *convertValue(TypedInit *VI); - - void print(std::ostream &OS) const; - - bool typeIsConvertibleTo(const RecTy *RHS) const { - return RHS->baseClassOf(this); - } - virtual bool baseClassOf(const RecordRecTy *RHS) const; -}; - - - -//===----------------------------------------------------------------------===// -// Initializer Classes -//===----------------------------------------------------------------------===// - -struct Init { - virtual ~Init() {} - - /// isComplete - This virtual method should be overridden by values that may - /// not be completely specified yet. - virtual bool isComplete() const { return true; } - - /// print - Print out this value. - virtual void print(std::ostream &OS) const = 0; - - /// dump - Debugging method that may be called through a debugger, just - /// invokes print on cerr. - void dump() const; - - /// convertInitializerTo - This virtual function is a simple call-back - /// function that should be overridden to call the appropriate - /// RecTy::convertValue method. - /// - virtual Init *convertInitializerTo(RecTy *Ty) = 0; - - /// convertInitializerBitRange - This method is used to implement the bitrange - /// selection operator. Given an initializer, it selects the specified bits - /// out, returning them as a new init of bits type. If it is not legal to use - /// the bit subscript operator on this initializer, return null. - /// - virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits) { - return 0; - } - - /// getFieldType - This method is used to implement the FieldInit class. - /// Implementors of this method should return the type of the named field if - /// they are of record type. - /// - virtual RecTy *getFieldType(const std::string &FieldName) const { return 0; } - - /// getFieldInit - This method complements getFieldType to return the - /// initializer for the specified field. If getFieldType returns non-null - /// this method should return non-null, otherwise it returns null. - /// - virtual Init *getFieldInit(Record &R, const std::string &FieldName) const { - return 0; - } - - /// resolveReferences - This method is used by classes that refer to other - /// variables which may not be defined at the time they expression is formed. - /// If a value is set for the variable later, this method will be called on - /// users of the value to allow the value to propagate out. - /// - virtual Init *resolveReferences(Record &R) { return this; } -}; - -inline std::ostream &operator<<(std::ostream &OS, const Init &I) { - I.print(OS); return OS; -} - - -/// UnsetInit - ? - Represents an uninitialized value -/// -struct UnsetInit : public Init { - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); - } - - virtual bool isComplete() const { return false; } - virtual void print(std::ostream &OS) const { OS << "?"; } -}; - - -/// BitInit - true/false - Represent a concrete initializer for a bit. -/// -class BitInit : public Init { - bool Value; -public: - BitInit(bool V) : Value(V) {} - - bool getValue() const { return Value; } - - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); - } - - virtual void print(std::ostream &OS) const { OS << (Value ? "1" : "0"); } -}; - -/// BitsInit - { a, b, c } - Represents an initializer for a BitsRecTy value. -/// It contains a vector of bits, whose size is determined by the type. -/// -class BitsInit : public Init { - std::vector<Init*> Bits; -public: - BitsInit(unsigned Size) : Bits(Size) {} - - unsigned getNumBits() const { return Bits.size(); } - - Init *getBit(unsigned Bit) const { - assert(Bit < Bits.size() && "Bit index out of range!"); - return Bits[Bit]; - } - void setBit(unsigned Bit, Init *V) { - assert(Bit < Bits.size() && "Bit index out of range!"); - assert(Bits[Bit] == 0 && "Bit already set!"); - Bits[Bit] = V; - } - - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); - } - virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits); - - virtual bool isComplete() const { - for (unsigned i = 0; i != getNumBits(); ++i) - if (!getBit(i)->isComplete()) return false; - return true; - } - virtual void print(std::ostream &OS) const; - - virtual Init *resolveReferences(Record &R); - - // printXX - Print this bitstream with the specified format, returning true if - // it is not possible. - bool printInHex(std::ostream &OS) const; - bool printAsVariable(std::ostream &OS) const; - bool printAsUnset(std::ostream &OS) const; -}; - - -/// IntInit - 7 - Represent an initalization by a literal integer value. -/// -class IntInit : public Init { - int Value; -public: - IntInit(int V) : Value(V) {} - - int getValue() const { return Value; } - - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); - } - virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits); - - virtual void print(std::ostream &OS) const { OS << Value; } -}; - - -/// StringInit - "foo" - Represent an initialization by a string value. -/// -class StringInit : public Init { - std::string Value; -public: - StringInit(const std::string &V) : Value(V) {} - - const std::string &getValue() const { return Value; } - - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); - } - - virtual void print(std::ostream &OS) const { OS << "\"" << Value << "\""; } -}; - -/// CodeInit - "[{...}]" - Represent a code fragment. -/// -class CodeInit : public Init { - std::string Value; -public: - CodeInit(const std::string &V) : Value(V) {} - - const std::string getValue() const { return Value; } - - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); - } - - virtual void print(std::ostream &OS) const { OS << "[{" << Value << "}]"; } -}; - -/// ListInit - [AL, AH, CL] - Represent a list of defs -/// -class ListInit : public Init { - std::vector<Init*> Values; -public: - ListInit(std::vector<Init*> &Vs) { - Values.swap(Vs); - } - - unsigned getSize() const { return Values.size(); } - Init *getElement(unsigned i) const { - assert(i < Values.size() && "List element index out of range!"); - return Values[i]; - } - - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); - } - - virtual void print(std::ostream &OS) const; -}; - - -/// TypedInit - This is the common super-class of types that have a specific, -/// explicit, type. -/// -class TypedInit : public Init { - RecTy *Ty; -public: - TypedInit(RecTy *T) : Ty(T) {} - - RecTy *getType() const { return Ty; } - - /// resolveBitReference - This method is used to implement - /// VarBitInit::resolveReferences. If the bit is able to be resolved, we - /// simply return the resolved value, otherwise we return this. - /// - virtual Init *resolveBitReference(Record &R, unsigned Bit) = 0; -}; - -/// VarInit - 'Opcode' - Represent a reference to an entire variable object. -/// -class VarInit : public TypedInit { - std::string VarName; -public: - VarInit(const std::string &VN, RecTy *T) : TypedInit(T), VarName(VN) {} - - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); - } - - const std::string &getName() const { return VarName; } - - virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits); - - virtual Init *resolveBitReference(Record &R, unsigned Bit); - - virtual RecTy *getFieldType(const std::string &FieldName) const; - virtual Init *getFieldInit(Record &R, const std::string &FieldName) const; - - /// resolveReferences - This method is used by classes that refer to other - /// variables which may not be defined at the time they expression is formed. - /// If a value is set for the variable later, this method will be called on - /// users of the value to allow the value to propagate out. - /// - virtual Init *resolveReferences(Record &R); - - virtual void print(std::ostream &OS) const { OS << VarName; } -}; - - -/// VarBitInit - Opcode{0} - Represent access to one bit of a variable or field. -/// -class VarBitInit : public Init { - TypedInit *TI; - unsigned Bit; -public: - VarBitInit(TypedInit *T, unsigned B) : TI(T), Bit(B) { - assert(T->getType() && dynamic_cast<BitsRecTy*>(T->getType()) && - ((BitsRecTy*)T->getType())->getNumBits() > B && - "Illegal VarBitInit expression!"); - } - - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); - } - - TypedInit *getVariable() const { return TI; } - unsigned getBitNum() const { return Bit; } - - virtual void print(std::ostream &OS) const { - TI->print(OS); OS << "{" << Bit << "}"; - } - virtual Init *resolveReferences(Record &R); -}; - - -/// DefInit - AL - Represent a reference to a 'def' in the description -/// -class DefInit : public Init { - Record *Def; -public: - DefInit(Record *D) : Def(D) {} - - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); - } - - Record *getDef() const { return Def; } - - //virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits); - - virtual RecTy *getFieldType(const std::string &FieldName) const; - virtual Init *getFieldInit(Record &R, const std::string &FieldName) const; - - virtual void print(std::ostream &OS) const; -}; - - -/// FieldInit - X.Y - Represent a reference to a subfield of a variable -/// -class FieldInit : public TypedInit { - Init *Rec; // Record we are referring to - std::string FieldName; // Field we are accessing -public: - FieldInit(Init *R, const std::string &FN) - : TypedInit(R->getFieldType(FN)), Rec(R), FieldName(FN) { - assert(getType() && "FieldInit with non-record type!"); - } - - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); - } - - virtual Init *convertInitializerBitRange(const std::vector<unsigned> &Bits); - - virtual Init *resolveBitReference(Record &R, unsigned Bit); - - virtual Init *resolveReferences(Record &R); - - virtual void print(std::ostream &OS) const { - Rec->print(OS); OS << "." << FieldName; - } -}; - -/// DagInit - (def a, b) - Represent a DAG tree value. DAG inits are required -/// to have Records for their first value, after that, any legal Init is -/// possible. -/// -class DagInit : public Init { - Record *NodeTypeDef; - std::vector<Init*> Args; - std::vector<std::string> ArgNames; -public: - DagInit(Record *D, const std::vector<std::pair<Init*, std::string> > &args) - : NodeTypeDef(D) { - Args.reserve(args.size()); - ArgNames.reserve(args.size()); - for (unsigned i = 0, e = args.size(); i != e; ++i) { - Args.push_back(args[i].first); - ArgNames.push_back(args[i].second); - } - } - - virtual Init *convertInitializerTo(RecTy *Ty) { - return Ty->convertValue(this); - } - - Record *getNodeType() const { return NodeTypeDef; } - - unsigned getNumArgs() const { return Args.size(); } - Init *getArg(unsigned Num) const { - assert(Num < Args.size() && "Arg number out of range!"); - return Args[Num]; - } - const std::string &getArgName(unsigned Num) const { - assert(Num < ArgNames.size() && "Arg number out of range!"); - return ArgNames[Num]; - } - - void setArg(unsigned Num, Init *I) { - assert(Num < Args.size() && "Arg number out of range!"); - Args[Num] = I; - } - - virtual void print(std::ostream &OS) const; -}; - -//===----------------------------------------------------------------------===// -// High-Level Classes -//===----------------------------------------------------------------------===// - -class RecordVal { - std::string Name; - RecTy *Ty; - unsigned Prefix; - Init *Value; -public: - RecordVal(const std::string &N, RecTy *T, unsigned P); - - const std::string &getName() const { return Name; } - - unsigned getPrefix() const { return Prefix; } - RecTy *getType() const { return Ty; } - Init *getValue() const { return Value; } - - bool setValue(Init *V) { - if (V) { - Value = V->convertInitializerTo(Ty); - return Value == 0; - } - Value = 0; - return false; - } - - void dump() const; - void print(std::ostream &OS, bool PrintSem = true) const; -}; - -inline std::ostream &operator<<(std::ostream &OS, const RecordVal &RV) { - RV.print(OS << " "); - return OS; -} - -struct Record { - const std::string Name; - std::vector<std::string> TemplateArgs; - std::vector<RecordVal> Values; - std::vector<Record*> SuperClasses; -public: - - Record(const std::string &N) : Name(N) {} - ~Record() {} - - const std::string &getName() const { return Name; } - const std::vector<std::string> &getTemplateArgs() const { - return TemplateArgs; - } - const std::vector<RecordVal> &getValues() const { return Values; } - const std::vector<Record*> &getSuperClasses() const { return SuperClasses; } - - bool isTemplateArg(const std::string &Name) const { - for (unsigned i = 0, e = TemplateArgs.size(); i != e; ++i) - if (TemplateArgs[i] == Name) return true; - return false; - } - - const RecordVal *getValue(const std::string &Name) const { - for (unsigned i = 0, e = Values.size(); i != e; ++i) - if (Values[i].getName() == Name) return &Values[i]; - return 0; - } - RecordVal *getValue(const std::string &Name) { - for (unsigned i = 0, e = Values.size(); i != e; ++i) - if (Values[i].getName() == Name) return &Values[i]; - return 0; - } - - void addTemplateArg(const std::string &Name) { - assert(!isTemplateArg(Name) && "Template arg already defined!"); - TemplateArgs.push_back(Name); - } - - void addValue(const RecordVal &RV) { - assert(getValue(RV.getName()) == 0 && "Value already added!"); - Values.push_back(RV); - } - - void removeValue(const std::string &Name) { - assert(getValue(Name) && "Cannot remove an entry that does not exist!"); - for (unsigned i = 0, e = Values.size(); i != e; ++i) - if (Values[i].getName() == Name) { - Values.erase(Values.begin()+i); - return; - } - assert(0 && "Name does not exist in record!"); - } - - bool isSubClassOf(Record *R) const { - for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i) - if (SuperClasses[i] == R) - return true; - return false; - } - - bool isSubClassOf(const std::string &Name) const { - for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i) - if (SuperClasses[i]->getName() == Name) - return true; - return false; - } - - void addSuperClass(Record *R) { - assert(!isSubClassOf(R) && "Already subclassing record!"); - SuperClasses.push_back(R); - } - - // resolveReferences - If there are any field references that refer to fields - // that have been filled in, we can propagate the values now. - // - void resolveReferences(); - - void dump() const; - - //===--------------------------------------------------------------------===// - // High-level methods useful to tablegen back-ends - // - - /// getValueInit - Return the initializer for a value with the specified name, - /// or throw an exception if the field does not exist. - /// - Init *getValueInit(const std::string &FieldName) const; - - /// getValueAsString - This method looks up the specified field and returns - /// its value as a string, throwing an exception if the field does not exist - /// or if the value is not a string. - /// - std::string getValueAsString(const std::string &FieldName) const; - - /// getValueAsBitsInit - This method looks up the specified field and returns - /// its value as a BitsInit, throwing an exception if the field does not exist - /// or if the value is not the right type. - /// - BitsInit *getValueAsBitsInit(const std::string &FieldName) const; - - /// getValueAsListInit - This method looks up the specified field and returns - /// its value as a ListInit, throwing an exception if the field does not exist - /// or if the value is not the right type. - /// - ListInit *getValueAsListInit(const std::string &FieldName) const; - - /// getValueAsDef - This method looks up the specified field and returns its - /// value as a Record, throwing an exception if the field does not exist or if - /// the value is not the right type. - /// - Record *getValueAsDef(const std::string &FieldName) const; - - /// getValueAsBit - This method looks up the specified field and returns its - /// value as a bit, throwing an exception if the field does not exist or if - /// the value is not the right type. - /// - bool getValueAsBit(const std::string &FieldName) const; - - /// getValueAsInt - This method looks up the specified field and returns its - /// value as an int, throwing an exception if the field does not exist or if - /// the value is not the right type. - /// - int getValueAsInt(const std::string &FieldName) const; - - /// getValueAsDag - This method looks up the specified field and returns its - /// value as an Dag, throwing an exception if the field does not exist or if - /// the value is not the right type. - /// - DagInit *getValueAsDag(const std::string &FieldName) const; -}; - -std::ostream &operator<<(std::ostream &OS, const Record &R); - -class RecordKeeper { - std::map<std::string, Record*> Classes, Defs; -public: - ~RecordKeeper() { - for (std::map<std::string, Record*>::iterator I = Classes.begin(), - E = Classes.end(); I != E; ++I) - delete I->second; - for (std::map<std::string, Record*>::iterator I = Defs.begin(), - E = Defs.end(); I != E; ++I) - delete I->second; - } - - const std::map<std::string, Record*> &getClasses() const { return Classes; } - const std::map<std::string, Record*> &getDefs() const { return Defs; } - - Record *getClass(const std::string &Name) const { - std::map<std::string, Record*>::const_iterator I = Classes.find(Name); - return I == Classes.end() ? 0 : I->second; - } - Record *getDef(const std::string &Name) const { - std::map<std::string, Record*>::const_iterator I = Defs.find(Name); - return I == Defs.end() ? 0 : I->second; - } - void addClass(Record *R) { - assert(getClass(R->getName()) == 0 && "Class already exists!"); - Classes.insert(std::make_pair(R->getName(), R)); - } - void addDef(Record *R) { - assert(getDef(R->getName()) == 0 && "Def already exists!"); - Defs.insert(std::make_pair(R->getName(), R)); - } - - //===--------------------------------------------------------------------===// - // High-level helper methods, useful for tablegen backends... - - /// getAllDerivedDefinitions - This method returns all concrete definitions - /// that derive from the specified class name. If a class with the specified - /// name does not exist, an exception is thrown. - std::vector<Record*> - getAllDerivedDefinitions(const std::string &ClassName) const; - - - void dump() const; -}; - -std::ostream &operator<<(std::ostream &OS, const RecordKeeper &RK); - -extern RecordKeeper Records; - -#endif diff --git a/support/tools/TableGen/RegisterInfoEmitter.cpp b/support/tools/TableGen/RegisterInfoEmitter.cpp deleted file mode 100644 index af3efe3a9c..0000000000 --- a/support/tools/TableGen/RegisterInfoEmitter.cpp +++ /dev/null @@ -1,234 +0,0 @@ -//===- RegisterInfoEmitter.cpp - Generate a Register File Desc. -*- C++ -*-===// -// -// This tablegen backend is responsible for emitting a description of a target -// register file for a code generator. It uses instances of the Register, -// RegisterAliases, and RegisterClass classes to gather this information. -// -//===----------------------------------------------------------------------===// - -#include "RegisterInfoEmitter.h" -#include "CodeGenWrappers.h" -#include "Record.h" -#include "Support/StringExtras.h" -#include <set> - -// runEnums - Print out enum values for all of the registers. -void RegisterInfoEmitter::runEnums(std::ostream &OS) { - std::vector<Record*> Registers = Records.getAllDerivedDefinitions("Register"); - - if (Registers.size() == 0) - throw std::string("No 'Register' subclasses defined!"); - - std::string Namespace = Registers[0]->getValueAsString("Namespace"); - - EmitSourceFileHeader("Target Register Enum Values", OS); - - if (!Namespace.empty()) - OS << "namespace " << Namespace << " {\n"; - OS << " enum {\n NoRegister,\n"; - - for (unsigned i = 0, e = Registers.size(); i != e; ++i) - OS << " " << Registers[i]->getName() << ", \t// " << i+1 << "\n"; - - OS << " };\n"; - if (!Namespace.empty()) - OS << "}\n"; -} - -void RegisterInfoEmitter::runHeader(std::ostream &OS) { - EmitSourceFileHeader("Register Information Header Fragment", OS); - const std::string &TargetName = CodeGenTarget().getName(); - std::string ClassName = TargetName + "GenRegisterInfo"; - - OS << "#include \"llvm/Target/MRegisterInfo.h\"\n\n"; - - OS << "struct " << ClassName << " : public MRegisterInfo {\n" - << " " << ClassName - << "(int CallFrameSetupOpcode = -1, int CallFrameDestroyOpcode = -1);\n" - << " const unsigned* getCalleeSaveRegs() const;\n" - << "};\n\n"; - - std::vector<Record*> RegisterClasses = - Records.getAllDerivedDefinitions("RegisterClass"); - - OS << "namespace " << TargetName << " { // Register classes\n"; - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { - if (RegisterClasses[i]->getValueAsBit("isDummyClass")) - continue; // Ignore dummies - - const std::string &Name = RegisterClasses[i]->getName(); - if (Name.size() < 9 || Name[9] != '.') // Ignore anonymous classes - OS << " extern TargetRegisterClass *" << Name << "RegisterClass;\n"; - } - OS << "} // end of namespace " << TargetName << "\n\n"; -} - -// RegisterInfoEmitter::run - Main register file description emitter. -// -void RegisterInfoEmitter::run(std::ostream &OS) { - EmitSourceFileHeader("Register Information Source Fragment", OS); - - // Start out by emitting each of the register classes... to do this, we build - // a set of registers which belong to a register class, this is to ensure that - // each register is only in a single register class. - // - std::vector<Record*> RegisterClasses = - Records.getAllDerivedDefinitions("RegisterClass"); - - std::vector<Record*> Registers = Records.getAllDerivedDefinitions("Register"); - - std::set<Record*> RegistersFound; - std::vector<std::string> RegClassNames; - - // Loop over all of the register classes... emitting each one. - OS << "namespace { // Register classes...\n"; - - for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { - Record *RC = RegisterClasses[rc]; - if (RC->getValueAsBit("isDummyClass")) continue; // Ignore dummies - - std::string Name = RC->getName(); - if (Name.size() > 9 && Name[9] == '.') { - static unsigned AnonCounter = 0; - Name = "AnonRegClass_"+utostr(AnonCounter++); - } - - RegClassNames.push_back(Name); - - // Emit the register list now... - OS << " // " << Name << " Register Class...\n const unsigned " << Name - << "[] = {\n "; - ListInit *RegList = RC->getValueAsListInit("MemberList"); - for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) { - DefInit *RegDef = dynamic_cast<DefInit*>(RegList->getElement(i)); - if (!RegDef) throw "Register class member is not a record!"; - Record *Reg = RegDef->getDef(); - if (!Reg->isSubClassOf("Register")) - throw "Register Class member '" + Reg->getName() + - " does not derive from the Register class!"; - if (RegistersFound.count(Reg)) - throw "Register '" + Reg->getName() + - "' included in multiple register classes!"; - RegistersFound.insert(Reg); - OS << getQualifiedName(Reg) << ", "; - } - OS << "\n };\n\n"; - - OS << " struct " << Name << "Class : public TargetRegisterClass {\n" - << " " << Name << "Class() : TargetRegisterClass(" - << RC->getValueAsInt("Size")/8 << ", " << RC->getValueAsInt("Alignment") - << ", " << Name << ", " << Name << " + " << RegList->getSize() - << ") {}\n"; - - if (CodeInit *CI = dynamic_cast<CodeInit*>(RC->getValueInit("Methods"))) - OS << CI->getValue(); - else - throw "Expected 'code' fragment for 'Methods' value in register class '"+ - RC->getName() + "'!"; - - OS << " } " << Name << "Instance;\n\n"; - } - - OS << " const TargetRegisterClass* const RegisterClasses[] = {\n"; - for (unsigned i = 0, e = RegClassNames.size(); i != e; ++i) - OS << " &" << RegClassNames[i] << "Instance,\n"; - OS << " };\n"; - - // Emit register class aliases... - std::vector<Record*> RegisterAliasesRecs = - Records.getAllDerivedDefinitions("RegisterAliases"); - std::map<Record*, std::set<Record*> > RegisterAliases; - - for (unsigned i = 0, e = RegisterAliasesRecs.size(); i != e; ++i) { - Record *AS = RegisterAliasesRecs[i]; - Record *R = AS->getValueAsDef("Reg"); - ListInit *LI = AS->getValueAsListInit("Aliases"); - - // Add information that R aliases all of the elements in the list... and - // that everything in the list aliases R. - for (unsigned j = 0, e = LI->getSize(); j != e; ++j) { - DefInit *Reg = dynamic_cast<DefInit*>(LI->getElement(j)); - if (!Reg) throw "ERROR: Alias list element is not a def!"; - if (RegisterAliases[R].count(Reg->getDef())) - std::cerr << "Warning: register alias between " << getQualifiedName(R) - << " and " << getQualifiedName(Reg->getDef()) - << " specified multiple times!\n"; - RegisterAliases[R].insert(Reg->getDef()); - - if (RegisterAliases[Reg->getDef()].count(R)) - std::cerr << "Warning: register alias between " << getQualifiedName(R) - << " and " << getQualifiedName(Reg->getDef()) - << " specified multiple times!\n"; - RegisterAliases[Reg->getDef()].insert(R); - } - } - - if (!RegisterAliases.empty()) - OS << "\n\n // Register Alias Sets...\n"; - - // Loop over all of the registers which have aliases, emitting the alias list - // to memory. - for (std::map<Record*, std::set<Record*> >::iterator - I = RegisterAliases.begin(), E = RegisterAliases.end(); I != E; ++I) { - OS << " const unsigned " << I->first->getName() << "_AliasSet[] = { "; - for (std::set<Record*>::iterator ASI = I->second.begin(), - E = I->second.end(); ASI != E; ++ASI) - OS << getQualifiedName(*ASI) << ", "; - OS << "0 };\n"; - } - - OS << "\n const MRegisterDesc RegisterDescriptors[] = { // Descriptors\n"; - OS << " { \"NOREG\",\t0,\t\t0,\t0 },\n"; - // Now that register alias sets have been emitted, emit the register - // descriptors now. - for (unsigned i = 0, e = Registers.size(); i != e; ++i) { - Record *Reg = Registers[i]; - OS << " { \""; - if (!Reg->getValueAsString("Name").empty()) - OS << Reg->getValueAsString("Name"); - else - OS << Reg->getName(); - OS << "\",\t"; - if (RegisterAliases.count(Reg)) - OS << Reg->getName() << "_AliasSet,\t"; - else - OS << "0,\t\t"; - OS << "0, 0 },\n"; - } - OS << " };\n"; // End of register descriptors... - OS << "}\n\n"; // End of anonymous namespace... - - CodeGenTarget Target; - - OS << "namespace " << Target.getName() << " { // Register classes\n"; - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { - if (RegisterClasses[i]->getValueAsBit("isDummyClass")) - continue; // Ignore dummies - - const std::string &Name = RegisterClasses[i]->getName(); - if (Name.size() < 9 || Name[9] != '.') // Ignore anonymous classes - OS << " TargetRegisterClass *" << Name << "RegisterClass = &" - << Name << "Instance;\n"; - } - OS << "} // end of namespace " << Target.getName() << "\n\n"; - - - - std::string ClassName = Target.getName() + "GenRegisterInfo"; - - // Emit the constructor of the class... - OS << ClassName << "::" << ClassName - << "(int CallFrameSetupOpcode, int CallFrameDestroyOpcode)\n" - << " : MRegisterInfo(RegisterDescriptors, " << Registers.size()+1 - << ", RegisterClasses, RegisterClasses+" << RegClassNames.size() << ",\n " - << " CallFrameSetupOpcode, CallFrameDestroyOpcode) {}\n\n"; - - // Emit the getCalleeSaveRegs method... - OS << "const unsigned* " << ClassName << "::getCalleeSaveRegs() const {\n" - << " static const unsigned CalleeSaveRegs[] = {\n "; - - const std::vector<Record*> &CSR = Target.getCalleeSavedRegisters(); - for (unsigned i = 0, e = CSR.size(); i != e; ++i) - OS << getQualifiedName(CSR[i]) << ", "; - OS << " 0\n };\n return CalleeSaveRegs;\n}\n\n"; -} diff --git a/support/tools/TableGen/RegisterInfoEmitter.h b/support/tools/TableGen/RegisterInfoEmitter.h deleted file mode 100644 index 65a03303cd..0000000000 --- a/support/tools/TableGen/RegisterInfoEmitter.h +++ /dev/null @@ -1,29 +0,0 @@ -//===- RegisterInfoEmitter.h - Generate a Register File Desc. ---*- C++ -*-===// -// -// This tablegen backend is responsible for emitting a description of a target -// register file for a code generator. It uses instances of the Register, -// RegisterAliases, and RegisterClass classes to gather this information. -// -//===----------------------------------------------------------------------===// - -#ifndef REGISTER_INFO_EMITTER_H -#define REGISTER_INFO_EMITTER_H - -#include "TableGenBackend.h" - -class RegisterInfoEmitter : public TableGenBackend { - RecordKeeper &Records; -public: - RegisterInfoEmitter(RecordKeeper &R) : Records(R) {} - - // run - Output the register file description, returning true on failure. - void run(std::ostream &o); - - // runHeader - Emit a header fragment for the register info emitter. - void runHeader(std::ostream &o); - - // runEnums - Print out enum values for all of the registers. - void runEnums(std::ostream &o); -}; - -#endif diff --git a/support/tools/TableGen/TableGen.cpp b/support/tools/TableGen/TableGen.cpp deleted file mode 100644 index 971ac9081a..0000000000 --- a/support/tools/TableGen/TableGen.cpp +++ /dev/null @@ -1,482 +0,0 @@ -//===- TableGen.cpp - Top-Level TableGen implementation -------------------===// -// -// TableGen is a tool which can be used to build up a description of something, -// then invoke one or more "tablegen backends" to emit information about the -// description in some predefined format. In practice, this is used by the LLVM -// code generators to automate generation of a code generator through a -// high-level description of the target. -// -//===----------------------------------------------------------------------===// - -#include "Record.h" -#include "Support/CommandLine.h" -#include "Support/Signals.h" -#include "Support/FileUtilities.h" -#include "CodeEmitterGen.h" -#include "RegisterInfoEmitter.h" -#include "InstrInfoEmitter.h" -#include "InstrSelectorEmitter.h" -#include <algorithm> -#include <cstdio> -#include <fstream> - -enum ActionType { - PrintRecords, - GenEmitter, - GenRegisterEnums, GenRegister, GenRegisterHeader, - GenInstrEnums, GenInstrs, GenInstrSelector, - PrintEnums, - Parse, -}; - -namespace { - cl::opt<ActionType> - Action(cl::desc("Action to perform:"), - cl::values(clEnumValN(PrintRecords, "print-records", - "Print all records to stdout (default)"), - clEnumValN(GenEmitter, "gen-emitter", - "Generate machine code emitter"), - clEnumValN(GenRegisterEnums, "gen-register-enums", - "Generate enum values for registers"), - clEnumValN(GenRegister, "gen-register-desc", - "Generate a register info description"), - clEnumValN(GenRegisterHeader, "gen-register-desc-header", - "Generate a register info description header"), - clEnumValN(GenInstrEnums, "gen-instr-enums", - "Generate enum values for instructions"), - clEnumValN(GenInstrs, "gen-instr-desc", - "Generate instruction descriptions"), - clEnumValN(GenInstrSelector, "gen-instr-selector", - "Generate an instruction selector"), - clEnumValN(PrintEnums, "print-enums", - "Print enum values for a class"), - clEnumValN(Parse, "parse", - "Interpret machine code (testing only)"), - 0)); - - cl::opt<std::string> - Class("class", cl::desc("Print Enum list for this class"), - cl::value_desc("class name")); - - cl::opt<std::string> - OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"), - cl::init("-")); - - cl::opt<std::string> - InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-")); - - cl::opt<std::string> - IncludeDir("I", cl::desc("Directory of include files"), - cl::value_desc("directory"), cl::init("")); -} - - -void ParseFile(const std::string &Filename, const std::string & IncludeDir); - -RecordKeeper Records; - -static Init *getBit(Record *R, unsigned BitNo) { - const std::vector<RecordVal> &V = R->getValues(); - for (unsigned i = 0, e = V.size(); i != e; ++i) - if (V[i].getPrefix()) { - assert(dynamic_cast<BitsInit*>(V[i].getValue()) && - "Can only handle fields of bits<> type!"); - BitsInit *I = (BitsInit*)V[i].getValue(); - if (BitNo < I->getNumBits()) - return I->getBit(BitNo); - BitNo -= I->getNumBits(); - } - - std::cerr << "Cannot find requested bit!\n"; - abort(); - return 0; -} - -static unsigned getNumBits(Record *R) { - const std::vector<RecordVal> &V = R->getValues(); - unsigned Num = 0; - for (unsigned i = 0, e = V.size(); i != e; ++i) - if (V[i].getPrefix()) { - assert(dynamic_cast<BitsInit*>(V[i].getValue()) && - "Can only handle fields of bits<> type!"); - Num += ((BitsInit*)V[i].getValue())->getNumBits(); - } - return Num; -} - -static bool BitsAreFixed(Record *I1, Record *I2, unsigned BitNo) { - return dynamic_cast<BitInit*>(getBit(I1, BitNo)) && - dynamic_cast<BitInit*>(getBit(I2, BitNo)); -} - -static bool BitsAreEqual(Record *I1, Record *I2, unsigned BitNo) { - BitInit *Bit1 = dynamic_cast<BitInit*>(getBit(I1, BitNo)); - BitInit *Bit2 = dynamic_cast<BitInit*>(getBit(I2, BitNo)); - - return Bit1 && Bit2 && Bit1->getValue() == Bit2->getValue(); -} - -static bool BitRangesEqual(Record *I1, Record *I2, - unsigned Start, unsigned End) { - for (unsigned i = Start; i != End; ++i) - if (!BitsAreEqual(I1, I2, i)) - return false; - return true; -} - -static unsigned getFirstFixedBit(Record *R, unsigned FirstFixedBit) { - // Look for the first bit of the pair that are required to be 0 or 1. - while (!dynamic_cast<BitInit*>(getBit(R, FirstFixedBit))) - ++FirstFixedBit; - return FirstFixedBit; -} - -static void FindInstDifferences(Record *I1, Record *I2, - unsigned FirstFixedBit, unsigned MaxBits, - unsigned &FirstVaryingBitOverall, - unsigned &LastFixedBitOverall) { - // Compare the first instruction to the rest of the instructions, looking for - // fields that differ. - // - unsigned FirstVaryingBit = FirstFixedBit; - while (FirstVaryingBit < MaxBits && BitsAreEqual(I1, I2, FirstVaryingBit)) - ++FirstVaryingBit; - - unsigned LastFixedBit = FirstVaryingBit; - while (LastFixedBit < MaxBits && BitsAreFixed(I1, I2, LastFixedBit)) - ++LastFixedBit; - - if (FirstVaryingBit < FirstVaryingBitOverall) - FirstVaryingBitOverall = FirstVaryingBit; - if (LastFixedBit < LastFixedBitOverall) - LastFixedBitOverall = LastFixedBit; -} - -static bool getBitValue(Record *R, unsigned BitNo) { - Init *I = getBit(R, BitNo); - assert(dynamic_cast<BitInit*>(I) && "Bit should be fixed!"); - return ((BitInit*)I)->getValue(); -} - -struct BitComparator { - unsigned BitBegin, BitEnd; - BitComparator(unsigned B, unsigned E) : BitBegin(B), BitEnd(E) {} - - bool operator()(Record *R1, Record *R2) { // Return true if R1 is less than R2 - for (unsigned i = BitBegin; i != BitEnd; ++i) { - bool V1 = getBitValue(R1, i), V2 = getBitValue(R2, i); - if (V1 < V2) - return true; - else if (V2 < V1) - return false; - } - return false; - } -}; - -static void PrintRange(std::vector<Record*>::iterator I, - std::vector<Record*>::iterator E) { - while (I != E) std::cerr << **I++; -} - -static bool getMemoryBit(unsigned char *M, unsigned i) { - return (M[i/8] & (1 << (i&7))) != 0; -} - -static unsigned getFirstFixedBitInSequence(std::vector<Record*>::iterator IB, - std::vector<Record*>::iterator IE, - unsigned StartBit) { - unsigned FirstFixedBit = 0; - for (std::vector<Record*>::iterator I = IB; I != IE; ++I) - FirstFixedBit = std::max(FirstFixedBit, getFirstFixedBit(*I, StartBit)); - return FirstFixedBit; -} - -// ParseMachineCode - Try to split the vector of instructions (which is -// intentionally taken by-copy) in half, narrowing down the possible -// instructions that we may have found. Eventually, this list will get pared -// down to zero or one instruction, in which case we have a match or failure. -// -static Record *ParseMachineCode(std::vector<Record*>::iterator InstsB, - std::vector<Record*>::iterator InstsE, - unsigned char *M) { - assert(InstsB != InstsE && "Empty range?"); - if (InstsB+1 == InstsE) { - // Only a single instruction, see if we match it... - Record *Inst = *InstsB; - for (unsigned i = 0, e = getNumBits(Inst); i != e; ++i) - if (BitInit *BI = dynamic_cast<BitInit*>(getBit(Inst, i))) - if (getMemoryBit(M, i) != BI->getValue()) - throw std::string("Parse failed!\n"); - return Inst; - } - - unsigned MaxBits = ~0; - for (std::vector<Record*>::iterator I = InstsB; I != InstsE; ++I) - MaxBits = std::min(MaxBits, getNumBits(*I)); - - unsigned FirstFixedBit = getFirstFixedBitInSequence(InstsB, InstsE, 0); - unsigned FirstVaryingBit, LastFixedBit; - do { - FirstVaryingBit = ~0; - LastFixedBit = ~0; - for (std::vector<Record*>::iterator I = InstsB+1; I != InstsE; ++I) - FindInstDifferences(*InstsB, *I, FirstFixedBit, MaxBits, - FirstVaryingBit, LastFixedBit); - if (FirstVaryingBit == MaxBits) { - std::cerr << "ERROR: Could not find bit to distinguish between " - << "the following entries!\n"; - PrintRange(InstsB, InstsE); - } - -#if 0 - std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit - << ": " << InstsE-InstsB << "\n"; -#endif - - FirstFixedBit = getFirstFixedBitInSequence(InstsB, InstsE, FirstVaryingBit); - } while (FirstVaryingBit != FirstFixedBit); - - //std::cerr << "\n\nXXXXXXXXXXXXXXXXX\n\n"; - //PrintRange(InstsB, InstsE); - - // Sort the Insts list so that the entries have all of the bits in the range - // [FirstVaryingBit,LastFixedBit) sorted. These bits are all guaranteed to be - // set to either 0 or 1 (BitInit values), which simplifies things. - // - std::sort(InstsB, InstsE, BitComparator(FirstVaryingBit, LastFixedBit)); - - // Once the list is sorted by these bits, split the bit list into smaller - // lists, and recurse on each one. - // - std::vector<Record*>::iterator RangeBegin = InstsB; - Record *Match = 0; - while (RangeBegin != InstsE) { - std::vector<Record*>::iterator RangeEnd = RangeBegin+1; - while (RangeEnd != InstsE && - BitRangesEqual(*RangeBegin, *RangeEnd, FirstVaryingBit, LastFixedBit)) - ++RangeEnd; - - // We just identified a range of equal instructions. If this range is the - // input range, we were not able to distinguish between the instructions in - // the set. Print an error and exit! - // - if (RangeBegin == InstsB && RangeEnd == InstsE) { - std::cerr << "Error: Could not distinguish among the following insts!:\n"; - PrintRange(InstsB, InstsE); - abort(); - } - -#if 0 - std::cerr << "FVB: " << FirstVaryingBit << " - " << LastFixedBit - << ": [" << RangeEnd-RangeBegin << "] - "; - for (int i = LastFixedBit-1; i >= (int)FirstVaryingBit; --i) - std::cerr << (int)((BitInit*)getBit(*RangeBegin, i))->getValue() << " "; - std::cerr << "\n"; -#endif - - if (Record *R = ParseMachineCode(RangeBegin, RangeEnd, M)) { - if (Match) { - std::cerr << "Error: Multiple matches found:\n"; - PrintRange(InstsB, InstsE); - } - - assert(Match == 0 && "Multiple matches??"); - Match = R; - } - RangeBegin = RangeEnd; - } - - return Match; -} - -static void PrintValue(Record *I, unsigned char *Ptr, const RecordVal &Val) { - assert(dynamic_cast<BitsInit*>(Val.getValue()) && - "Can only handle undefined bits<> types!"); - BitsInit *BI = (BitsInit*)Val.getValue(); - assert(BI->getNumBits() <= 32 && "Can only handle fields up to 32 bits!"); - - unsigned Value = 0; - const std::vector<RecordVal> &Vals = I->getValues(); - - // Start by filling in fixed values... - for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) - if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(i))) - Value |= B->getValue() << i; - - // Loop over all of the fields in the instruction adding in any - // contributions to this value (due to bit references). - // - unsigned Offset = 0; - for (unsigned f = 0, e = Vals.size(); f != e; ++f) - if (Vals[f].getPrefix()) { - BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue(); - if (&Vals[f] == &Val) { - // Read the bits directly now... - for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) - Value |= getMemoryBit(Ptr, Offset+i) << i; - break; - } - - // Scan through the field looking for bit initializers of the current - // variable... - for (unsigned i = 0, e = FieldInitializer->getNumBits(); i != e; ++i) - if (VarBitInit *VBI = - dynamic_cast<VarBitInit*>(FieldInitializer->getBit(i))) { - TypedInit *TI = VBI->getVariable(); - if (VarInit *VI = dynamic_cast<VarInit*>(TI)) { - if (VI->getName() == Val.getName()) - Value |= getMemoryBit(Ptr, Offset+i) << VBI->getBitNum(); - } else if (FieldInit *FI = dynamic_cast<FieldInit*>(TI)) { - // FIXME: implement this! - std::cerr << "FIELD INIT not implemented yet!\n"; - } - } - Offset += FieldInitializer->getNumBits(); - } - - std::cout << "0x" << std::hex << Value << std::dec; -} - -static void PrintInstruction(Record *I, unsigned char *Ptr) { - std::cout << "Inst " << getNumBits(I)/8 << " bytes: " - << "\t" << I->getName() << "\t" << *I->getValue("Name")->getValue() - << "\t"; - - const std::vector<RecordVal> &Vals = I->getValues(); - for (unsigned i = 0, e = Vals.size(); i != e; ++i) - if (!Vals[i].getValue()->isComplete()) { - std::cout << Vals[i].getName() << "="; - PrintValue(I, Ptr, Vals[i]); - std::cout << "\t"; - } - - std::cout << "\n";// << *I; -} - -static void ParseMachineCode() { - // X86 code - unsigned char Buffer[] = { - 0x55, // push EBP - 0x89, 0xE5, // mov EBP, ESP - //0x83, 0xEC, 0x08, // sub ESP, 0x8 - 0xE8, 1, 2, 3, 4, // call +0x04030201 - 0x89, 0xEC, // mov ESP, EBP - 0x5D, // pop EBP - 0xC3, // ret - 0x90, // nop - 0xC9, // leave - 0x89, 0xF6, // mov ESI, ESI - 0x68, 1, 2, 3, 4, // push 0x04030201 - 0x5e, // pop ESI - 0xFF, 0xD0, // call EAX - 0xB8, 1, 2, 3, 4, // mov EAX, 0x04030201 - 0x85, 0xC0, // test EAX, EAX - 0xF4, // hlt - }; - -#if 0 - // SparcV9 code - unsigned char Buffer[] = { 0xbf, 0xe0, 0x20, 0x1f, 0x1, 0x0, 0x0, 0x1, - 0x0, 0x0, 0x0, 0x0, 0xc1, 0x0, 0x20, 0x1, 0x1, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x1, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xaf, 0xe8, 0x20, 0x17 - }; -#endif - - std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); - - unsigned char *BuffPtr = Buffer; - while (1) { - Record *R = ParseMachineCode(Insts.begin(), Insts.end(), BuffPtr); - PrintInstruction(R, BuffPtr); - - unsigned Bits = getNumBits(R); - assert((Bits & 7) == 0 && "Instruction is not an even number of bytes!"); - BuffPtr += Bits/8; - } -} - - -int main(int argc, char **argv) { - cl::ParseCommandLineOptions(argc, argv); - ParseFile(InputFilename, IncludeDir); - - std::ostream *Out = &std::cout; - if (OutputFilename != "-") { - // Output to a .tmp file, because we don't actually want to overwrite the - // output file unless the generated file is different or the specified file - // does not exist. - Out = new std::ofstream((OutputFilename+".tmp").c_str()); - - if (!Out->good()) { - std::cerr << argv[0] << ": error opening " << OutputFilename << ".tmp!\n"; - return 1; - } - - // Make sure the file gets removed if *gasp* tablegen crashes... - RemoveFileOnSignal(OutputFilename+".tmp"); - } - - try { - switch (Action) { - case PrintRecords: - *Out << Records; // No argument, dump all contents - break; - case Parse: - ParseMachineCode(); - break; - case GenEmitter: - CodeEmitterGen(Records).run(*Out); - break; - - case GenRegisterEnums: - RegisterInfoEmitter(Records).runEnums(*Out); - break; - case GenRegister: - RegisterInfoEmitter(Records).run(*Out); - break; - case GenRegisterHeader: - RegisterInfoEmitter(Records).runHeader(*Out); - break; - - case GenInstrEnums: - InstrInfoEmitter(Records).runEnums(*Out); - break; - case GenInstrs: - InstrInfoEmitter(Records).run(*Out); - break; - case GenInstrSelector: - InstrSelectorEmitter(Records).run(*Out); - break; - case PrintEnums: - std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class); - for (unsigned i = 0, e = Recs.size(); i != e; ++i) - *Out << Recs[i] << ", "; - *Out << "\n"; - break; - } - } catch (const std::string &Error) { - std::cerr << Error << "\n"; - if (Out != &std::cout) { - delete Out; // Close the file - std::remove(OutputFilename.c_str()); // Remove the file, it's broken - } - return 1; - } - - if (Out != &std::cout) { - delete Out; // Close the file - - // Now that we have generated the result, check to see if we either don't - // have the requested file, or if the requested file is different than the - // file we generated. If so, move the generated file over the requested - // file. Otherwise, just remove the file we just generated, so 'make' - // doesn't try to regenerate tons of dependencies. - // - MoveFileOverIfUpdated(OutputFilename+".tmp", OutputFilename); - } - return 0; -} diff --git a/support/tools/TableGen/TableGenBackend.cpp b/support/tools/TableGen/TableGenBackend.cpp deleted file mode 100644 index b86ae72ce9..0000000000 --- a/support/tools/TableGen/TableGenBackend.cpp +++ /dev/null @@ -1,27 +0,0 @@ -//===- TableGenBackend.cpp - Base class for TableGen Backends ---*- C++ -*-===// -// -// This file provides useful services for TableGen backends... -// -//===----------------------------------------------------------------------===// - -#include "TableGenBackend.h" -#include "Record.h" -#include <iostream> - -void TableGenBackend::EmitSourceFileHeader(const std::string &Desc, - std::ostream &OS) const { - OS << "//===- TableGen'erated file -------------------------------------*-" - " C++ -*-===//\n//\n// " << Desc << "\n//\n// Automatically generate" - "d file, do not edit!\n//\n//===------------------------------------" - "----------------------------------===//\n\n"; -} - -/// getQualifiedName - Return the name of the specified record, with a -/// namespace qualifier if the record contains one. -/// -std::string TableGenBackend::getQualifiedName(Record *R) const { - std::string Namespace = R->getValueAsString("Namespace"); - if (Namespace.empty()) return R->getName(); - return Namespace + "::" + R->getName(); -} - diff --git a/support/tools/TableGen/TableGenBackend.h b/support/tools/TableGen/TableGenBackend.h deleted file mode 100644 index 8dfbaddad1..0000000000 --- a/support/tools/TableGen/TableGenBackend.h +++ /dev/null @@ -1,34 +0,0 @@ -//===- TableGenBackend.h - Base class for TableGen Backends -----*- C++ -*-===// -// -// The TableGenBackend class is provided as a common interface for all TableGen -// backends. It provides useful services and an standardized interface. -// -//===----------------------------------------------------------------------===// - -#ifndef TABLEGENBACKEND_H -#define TABLEGENBACKEND_H - -#include <string> -#include <iosfwd> -class Record; -class RecordKeeper; - -struct TableGenBackend { - virtual ~TableGenBackend() {} - - // run - All TableGen backends should implement the run method, which should - // be the main entry point. - virtual void run(std::ostream &OS) = 0; - - -public: // Useful helper routines... - /// EmitSourceFileHeader - Output a LLVM style file header to the specified - /// ostream. - void EmitSourceFileHeader(const std::string &Desc, std::ostream &OS) const; - - /// getQualifiedName - Return the name of the specified record, with a - /// namespace qualifier if the record contains one. - std::string getQualifiedName(Record *R) const; -}; - -#endif |