From: James Molloy Date: Tue, 17 Jun 2014 13:10:38 +0000 (+0000) Subject: Move SetTheory from utils/TableGen into lib/TableGen so Clang can use it. X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=3b2a2563322161a609fd6672af2d879c6bd65e8d;p=oota-llvm.git Move SetTheory from utils/TableGen into lib/TableGen so Clang can use it. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211100 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/TableGen/SetTheory.h b/include/llvm/TableGen/SetTheory.h new file mode 100644 index 00000000000..5baed79fb76 --- /dev/null +++ b/include/llvm/TableGen/SetTheory.h @@ -0,0 +1,142 @@ +//===- SetTheory.h - Generate ordered sets from DAG expressions -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SetTheory class that computes ordered sets of +// Records from DAG expressions. Operators for standard set operations are +// predefined, and it is possible to add special purpose set operators as well. +// +// The user may define named sets as Records of predefined classes. Set +// expanders can be added to a SetTheory instance to teach it how to find the +// elements of such a named set. +// +// These are the predefined operators. The argument lists can be individual +// elements (defs), other sets (defs of expandable classes), lists, or DAG +// expressions that are evaluated recursively. +// +// - (add S1, S2 ...) Union sets. This is also how sets are created from element +// lists. +// +// - (sub S1, S2, ...) Set difference. Every element in S1 except for the +// elements in S2, ... +// +// - (and S1, S2) Set intersection. Every element in S1 that is also in S2. +// +// - (shl S, N) Shift left. Remove the first N elements from S. +// +// - (trunc S, N) Truncate. The first N elements of S. +// +// - (rotl S, N) Rotate left. Same as (add (shl S, N), (trunc S, N)). +// +// - (rotr S, N) Rotate right. +// +// - (decimate S, N) Decimate S by picking every N'th element, starting with +// the first one. For instance, (decimate S, 2) returns the even elements of +// S. +// +// - (sequence "Format", From, To) Generate a sequence of defs with printf. +// For instance, (sequence "R%u", 0, 3) -> [ R0, R1, R2, R3 ] +// +//===----------------------------------------------------------------------===// + +#ifndef SETTHEORY_H +#define SETTHEORY_H + +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/SourceMgr.h" +#include +#include + +namespace llvm { + +class DagInit; +class Init; +class Record; +class RecordKeeper; + +class SetTheory { +public: + typedef std::vector RecVec; + typedef SmallSetVector RecSet; + + /// Operator - A callback representing a DAG operator. + class Operator { + virtual void anchor(); + public: + virtual ~Operator() {} + + /// apply - Apply this operator to Expr's arguments and insert the result + /// in Elts. + virtual void apply(SetTheory&, DagInit *Expr, RecSet &Elts, + ArrayRef Loc) =0; + }; + + /// Expander - A callback function that can transform a Record representing a + /// set into a fully expanded list of elements. Expanders provide a way for + /// users to define named sets that can be used in DAG expressions. + class Expander { + virtual void anchor(); + public: + virtual ~Expander() {} + + virtual void expand(SetTheory&, Record*, RecSet &Elts) =0; + }; + +private: + // Map set defs to their fully expanded contents. This serves as a memoization + // cache and it makes it possible to return const references on queries. + typedef std::map ExpandMap; + ExpandMap Expansions; + + // Known DAG operators by name. + StringMap Operators; + + // Typed expanders by class name. + StringMap Expanders; + +public: + /// Create a SetTheory instance with only the standard operators. + SetTheory(); + + /// addExpander - Add an expander for Records with the named super class. + void addExpander(StringRef ClassName, Expander*); + + /// addFieldExpander - Add an expander for ClassName that simply evaluates + /// FieldName in the Record to get the set elements. That is all that is + /// needed for a class like: + /// + /// class Set { + /// dag Elts = d; + /// } + /// + void addFieldExpander(StringRef ClassName, StringRef FieldName); + + /// addOperator - Add a DAG operator. + void addOperator(StringRef Name, Operator*); + + /// evaluate - Evaluate Expr and append the resulting set to Elts. + void evaluate(Init *Expr, RecSet &Elts, ArrayRef Loc); + + /// evaluate - Evaluate a sequence of Inits and append to Elts. + template + void evaluate(Iter begin, Iter end, RecSet &Elts, ArrayRef Loc) { + while (begin != end) + evaluate(*begin++, Elts, Loc); + } + + /// expand - Expand a record into a set of elements if possible. Return a + /// pointer to the expanded elements, or NULL if Set cannot be expanded + /// further. + const RecVec *expand(Record *Set); +}; + +} // end namespace llvm + +#endif + diff --git a/lib/TableGen/CMakeLists.txt b/lib/TableGen/CMakeLists.txt index 935d674a360..fb702187d13 100644 --- a/lib/TableGen/CMakeLists.txt +++ b/lib/TableGen/CMakeLists.txt @@ -2,6 +2,7 @@ add_llvm_library(LLVMTableGen Error.cpp Main.cpp Record.cpp + SetTheory.cpp StringMatcher.cpp TableGenBackend.cpp TGLexer.cpp diff --git a/lib/TableGen/SetTheory.cpp b/lib/TableGen/SetTheory.cpp new file mode 100644 index 00000000000..c99c2bab45a --- /dev/null +++ b/lib/TableGen/SetTheory.cpp @@ -0,0 +1,323 @@ +//===- SetTheory.cpp - Generate ordered sets from DAG expressions ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SetTheory class that computes ordered sets of +// Records from DAG expressions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Format.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/SetTheory.h" + +using namespace llvm; + +// Define the standard operators. +namespace { + +typedef SetTheory::RecSet RecSet; +typedef SetTheory::RecVec RecVec; + +// (add a, b, ...) Evaluate and union all arguments. +struct AddOp : public SetTheory::Operator { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, + ArrayRef Loc) override { + ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts, Loc); + } +}; + +// (sub Add, Sub, ...) Set difference. +struct SubOp : public SetTheory::Operator { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, + ArrayRef Loc) override { + if (Expr->arg_size() < 2) + PrintFatalError(Loc, "Set difference needs at least two arguments: " + + Expr->getAsString()); + RecSet Add, Sub; + ST.evaluate(*Expr->arg_begin(), Add, Loc); + ST.evaluate(Expr->arg_begin() + 1, Expr->arg_end(), Sub, Loc); + for (RecSet::iterator I = Add.begin(), E = Add.end(); I != E; ++I) + if (!Sub.count(*I)) + Elts.insert(*I); + } +}; + +// (and S1, S2) Set intersection. +struct AndOp : public SetTheory::Operator { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, + ArrayRef Loc) override { + if (Expr->arg_size() != 2) + PrintFatalError(Loc, "Set intersection requires two arguments: " + + Expr->getAsString()); + RecSet S1, S2; + ST.evaluate(Expr->arg_begin()[0], S1, Loc); + ST.evaluate(Expr->arg_begin()[1], S2, Loc); + for (RecSet::iterator I = S1.begin(), E = S1.end(); I != E; ++I) + if (S2.count(*I)) + Elts.insert(*I); + } +}; + +// SetIntBinOp - Abstract base class for (Op S, N) operators. +struct SetIntBinOp : public SetTheory::Operator { + virtual void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, + RecSet &Elts, ArrayRef Loc) = 0; + + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, + ArrayRef Loc) override { + if (Expr->arg_size() != 2) + PrintFatalError(Loc, "Operator requires (Op Set, Int) arguments: " + + Expr->getAsString()); + RecSet Set; + ST.evaluate(Expr->arg_begin()[0], Set, Loc); + IntInit *II = dyn_cast(Expr->arg_begin()[1]); + if (!II) + PrintFatalError(Loc, "Second argument must be an integer: " + + Expr->getAsString()); + apply2(ST, Expr, Set, II->getValue(), Elts, Loc); + } +}; + +// (shl S, N) Shift left, remove the first N elements. +struct ShlOp : public SetIntBinOp { + void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, + RecSet &Elts, ArrayRef Loc) override { + if (N < 0) + PrintFatalError(Loc, "Positive shift required: " + + Expr->getAsString()); + if (unsigned(N) < Set.size()) + Elts.insert(Set.begin() + N, Set.end()); + } +}; + +// (trunc S, N) Truncate after the first N elements. +struct TruncOp : public SetIntBinOp { + void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, + RecSet &Elts, ArrayRef Loc) override { + if (N < 0) + PrintFatalError(Loc, "Positive length required: " + + Expr->getAsString()); + if (unsigned(N) > Set.size()) + N = Set.size(); + Elts.insert(Set.begin(), Set.begin() + N); + } +}; + +// Left/right rotation. +struct RotOp : public SetIntBinOp { + const bool Reverse; + + RotOp(bool Rev) : Reverse(Rev) {} + + void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, + RecSet &Elts, ArrayRef Loc) override { + if (Reverse) + N = -N; + // N > 0 -> rotate left, N < 0 -> rotate right. + if (Set.empty()) + return; + if (N < 0) + N = Set.size() - (-N % Set.size()); + else + N %= Set.size(); + Elts.insert(Set.begin() + N, Set.end()); + Elts.insert(Set.begin(), Set.begin() + N); + } +}; + +// (decimate S, N) Pick every N'th element of S. +struct DecimateOp : public SetIntBinOp { + void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, + RecSet &Elts, ArrayRef Loc) override { + if (N <= 0) + PrintFatalError(Loc, "Positive stride required: " + + Expr->getAsString()); + for (unsigned I = 0; I < Set.size(); I += N) + Elts.insert(Set[I]); + } +}; + +// (interleave S1, S2, ...) Interleave elements of the arguments. +struct InterleaveOp : public SetTheory::Operator { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, + ArrayRef Loc) override { + // Evaluate the arguments individually. + SmallVector Args(Expr->getNumArgs()); + unsigned MaxSize = 0; + for (unsigned i = 0, e = Expr->getNumArgs(); i != e; ++i) { + ST.evaluate(Expr->getArg(i), Args[i], Loc); + MaxSize = std::max(MaxSize, unsigned(Args[i].size())); + } + // Interleave arguments into Elts. + for (unsigned n = 0; n != MaxSize; ++n) + for (unsigned i = 0, e = Expr->getNumArgs(); i != e; ++i) + if (n < Args[i].size()) + Elts.insert(Args[i][n]); + } +}; + +// (sequence "Format", From, To) Generate a sequence of records by name. +struct SequenceOp : public SetTheory::Operator { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, + ArrayRef Loc) override { + int Step = 1; + if (Expr->arg_size() > 4) + PrintFatalError(Loc, "Bad args to (sequence \"Format\", From, To): " + + Expr->getAsString()); + else if (Expr->arg_size() == 4) { + if (IntInit *II = dyn_cast(Expr->arg_begin()[3])) { + Step = II->getValue(); + } else + PrintFatalError(Loc, "Stride must be an integer: " + + Expr->getAsString()); + } + + std::string Format; + if (StringInit *SI = dyn_cast(Expr->arg_begin()[0])) + Format = SI->getValue(); + else + PrintFatalError(Loc, "Format must be a string: " + Expr->getAsString()); + + int64_t From, To; + if (IntInit *II = dyn_cast(Expr->arg_begin()[1])) + From = II->getValue(); + else + PrintFatalError(Loc, "From must be an integer: " + Expr->getAsString()); + if (From < 0 || From >= (1 << 30)) + PrintFatalError(Loc, "From out of range"); + + if (IntInit *II = dyn_cast(Expr->arg_begin()[2])) + To = II->getValue(); + else + PrintFatalError(Loc, "From must be an integer: " + Expr->getAsString()); + if (To < 0 || To >= (1 << 30)) + PrintFatalError(Loc, "To out of range"); + + RecordKeeper &Records = + cast(Expr->getOperator())->getDef()->getRecords(); + + Step *= From <= To ? 1 : -1; + while (true) { + if (Step > 0 && From > To) + break; + else if (Step < 0 && From < To) + break; + std::string Name; + raw_string_ostream OS(Name); + OS << format(Format.c_str(), unsigned(From)); + Record *Rec = Records.getDef(OS.str()); + if (!Rec) + PrintFatalError(Loc, "No def named '" + Name + "': " + + Expr->getAsString()); + // Try to reevaluate Rec in case it is a set. + if (const RecVec *Result = ST.expand(Rec)) + Elts.insert(Result->begin(), Result->end()); + else + Elts.insert(Rec); + + From += Step; + } + } +}; + +// Expand a Def into a set by evaluating one of its fields. +struct FieldExpander : public SetTheory::Expander { + StringRef FieldName; + + FieldExpander(StringRef fn) : FieldName(fn) {} + + void expand(SetTheory &ST, Record *Def, RecSet &Elts) override { + ST.evaluate(Def->getValueInit(FieldName), Elts, Def->getLoc()); + } +}; +} // end anonymous namespace + +// Pin the vtables to this file. +void SetTheory::Operator::anchor() {} +void SetTheory::Expander::anchor() {} + + +SetTheory::SetTheory() { + addOperator("add", new AddOp); + addOperator("sub", new SubOp); + addOperator("and", new AndOp); + addOperator("shl", new ShlOp); + addOperator("trunc", new TruncOp); + addOperator("rotl", new RotOp(false)); + addOperator("rotr", new RotOp(true)); + addOperator("decimate", new DecimateOp); + addOperator("interleave", new InterleaveOp); + addOperator("sequence", new SequenceOp); +} + +void SetTheory::addOperator(StringRef Name, Operator *Op) { + Operators[Name] = Op; +} + +void SetTheory::addExpander(StringRef ClassName, Expander *E) { + Expanders[ClassName] = E; +} + +void SetTheory::addFieldExpander(StringRef ClassName, StringRef FieldName) { + addExpander(ClassName, new FieldExpander(FieldName)); +} + +void SetTheory::evaluate(Init *Expr, RecSet &Elts, ArrayRef Loc) { + // A def in a list can be a just an element, or it may expand. + if (DefInit *Def = dyn_cast(Expr)) { + if (const RecVec *Result = expand(Def->getDef())) + return Elts.insert(Result->begin(), Result->end()); + Elts.insert(Def->getDef()); + return; + } + + // Lists simply expand. + if (ListInit *LI = dyn_cast(Expr)) + return evaluate(LI->begin(), LI->end(), Elts, Loc); + + // Anything else must be a DAG. + DagInit *DagExpr = dyn_cast(Expr); + if (!DagExpr) + PrintFatalError(Loc, "Invalid set element: " + Expr->getAsString()); + DefInit *OpInit = dyn_cast(DagExpr->getOperator()); + if (!OpInit) + PrintFatalError(Loc, "Bad set expression: " + Expr->getAsString()); + Operator *Op = Operators.lookup(OpInit->getDef()->getName()); + if (!Op) + PrintFatalError(Loc, "Unknown set operator: " + Expr->getAsString()); + Op->apply(*this, DagExpr, Elts, Loc); +} + +const RecVec *SetTheory::expand(Record *Set) { + // Check existing entries for Set and return early. + ExpandMap::iterator I = Expansions.find(Set); + if (I != Expansions.end()) + return &I->second; + + // This is the first time we see Set. Find a suitable expander. + const std::vector &SC = Set->getSuperClasses(); + for (unsigned i = 0, e = SC.size(); i != e; ++i) { + // Skip unnamed superclasses. + if (!dyn_cast(SC[i]->getNameInit())) + continue; + if (Expander *Exp = Expanders.lookup(SC[i]->getName())) { + // This breaks recursive definitions. + RecVec &EltVec = Expansions[Set]; + RecSet Elts; + Exp->expand(*this, Set, Elts); + EltVec.assign(Elts.begin(), Elts.end()); + return &EltVec; + } + } + + // Set is not expandable. + return nullptr; +} + diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt index f277608d2c8..feaa7c75796 100644 --- a/utils/TableGen/CMakeLists.txt +++ b/utils/TableGen/CMakeLists.txt @@ -26,7 +26,6 @@ add_tablegen(llvm-tblgen LLVM OptParserEmitter.cpp PseudoLoweringEmitter.cpp RegisterInfoEmitter.cpp - SetTheory.cpp SubtargetEmitter.cpp TableGen.cpp X86DisassemblerTables.cpp diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h index 30732c8e04d..278315ba47b 100644 --- a/utils/TableGen/CodeGenRegisters.h +++ b/utils/TableGen/CodeGenRegisters.h @@ -15,7 +15,6 @@ #ifndef CODEGEN_REGISTERS_H #define CODEGEN_REGISTERS_H -#include "SetTheory.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" @@ -23,6 +22,7 @@ #include "llvm/CodeGen/MachineValueType.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/TableGen/Record.h" +#include "llvm/TableGen/SetTheory.h" #include #include #include diff --git a/utils/TableGen/CodeGenSchedule.h b/utils/TableGen/CodeGenSchedule.h index 65ac6020747..3fef8adf91e 100644 --- a/utils/TableGen/CodeGenSchedule.h +++ b/utils/TableGen/CodeGenSchedule.h @@ -15,11 +15,11 @@ #ifndef CODEGEN_SCHEDULE_H #define CODEGEN_SCHEDULE_H -#include "SetTheory.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/TableGen/Record.h" +#include "llvm/TableGen/SetTheory.h" namespace llvm { diff --git a/utils/TableGen/SetTheory.cpp b/utils/TableGen/SetTheory.cpp deleted file mode 100644 index 5ead7ed16fd..00000000000 --- a/utils/TableGen/SetTheory.cpp +++ /dev/null @@ -1,323 +0,0 @@ -//===- SetTheory.cpp - Generate ordered sets from DAG expressions ---------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the SetTheory class that computes ordered sets of -// Records from DAG expressions. -// -//===----------------------------------------------------------------------===// - -#include "SetTheory.h" -#include "llvm/Support/Format.h" -#include "llvm/TableGen/Error.h" -#include "llvm/TableGen/Record.h" - -using namespace llvm; - -// Define the standard operators. -namespace { - -typedef SetTheory::RecSet RecSet; -typedef SetTheory::RecVec RecVec; - -// (add a, b, ...) Evaluate and union all arguments. -struct AddOp : public SetTheory::Operator { - void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, - ArrayRef Loc) override { - ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts, Loc); - } -}; - -// (sub Add, Sub, ...) Set difference. -struct SubOp : public SetTheory::Operator { - void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, - ArrayRef Loc) override { - if (Expr->arg_size() < 2) - PrintFatalError(Loc, "Set difference needs at least two arguments: " + - Expr->getAsString()); - RecSet Add, Sub; - ST.evaluate(*Expr->arg_begin(), Add, Loc); - ST.evaluate(Expr->arg_begin() + 1, Expr->arg_end(), Sub, Loc); - for (RecSet::iterator I = Add.begin(), E = Add.end(); I != E; ++I) - if (!Sub.count(*I)) - Elts.insert(*I); - } -}; - -// (and S1, S2) Set intersection. -struct AndOp : public SetTheory::Operator { - void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, - ArrayRef Loc) override { - if (Expr->arg_size() != 2) - PrintFatalError(Loc, "Set intersection requires two arguments: " + - Expr->getAsString()); - RecSet S1, S2; - ST.evaluate(Expr->arg_begin()[0], S1, Loc); - ST.evaluate(Expr->arg_begin()[1], S2, Loc); - for (RecSet::iterator I = S1.begin(), E = S1.end(); I != E; ++I) - if (S2.count(*I)) - Elts.insert(*I); - } -}; - -// SetIntBinOp - Abstract base class for (Op S, N) operators. -struct SetIntBinOp : public SetTheory::Operator { - virtual void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, - RecSet &Elts, ArrayRef Loc) = 0; - - void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, - ArrayRef Loc) override { - if (Expr->arg_size() != 2) - PrintFatalError(Loc, "Operator requires (Op Set, Int) arguments: " + - Expr->getAsString()); - RecSet Set; - ST.evaluate(Expr->arg_begin()[0], Set, Loc); - IntInit *II = dyn_cast(Expr->arg_begin()[1]); - if (!II) - PrintFatalError(Loc, "Second argument must be an integer: " + - Expr->getAsString()); - apply2(ST, Expr, Set, II->getValue(), Elts, Loc); - } -}; - -// (shl S, N) Shift left, remove the first N elements. -struct ShlOp : public SetIntBinOp { - void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, - RecSet &Elts, ArrayRef Loc) override { - if (N < 0) - PrintFatalError(Loc, "Positive shift required: " + - Expr->getAsString()); - if (unsigned(N) < Set.size()) - Elts.insert(Set.begin() + N, Set.end()); - } -}; - -// (trunc S, N) Truncate after the first N elements. -struct TruncOp : public SetIntBinOp { - void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, - RecSet &Elts, ArrayRef Loc) override { - if (N < 0) - PrintFatalError(Loc, "Positive length required: " + - Expr->getAsString()); - if (unsigned(N) > Set.size()) - N = Set.size(); - Elts.insert(Set.begin(), Set.begin() + N); - } -}; - -// Left/right rotation. -struct RotOp : public SetIntBinOp { - const bool Reverse; - - RotOp(bool Rev) : Reverse(Rev) {} - - void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, - RecSet &Elts, ArrayRef Loc) override { - if (Reverse) - N = -N; - // N > 0 -> rotate left, N < 0 -> rotate right. - if (Set.empty()) - return; - if (N < 0) - N = Set.size() - (-N % Set.size()); - else - N %= Set.size(); - Elts.insert(Set.begin() + N, Set.end()); - Elts.insert(Set.begin(), Set.begin() + N); - } -}; - -// (decimate S, N) Pick every N'th element of S. -struct DecimateOp : public SetIntBinOp { - void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, - RecSet &Elts, ArrayRef Loc) override { - if (N <= 0) - PrintFatalError(Loc, "Positive stride required: " + - Expr->getAsString()); - for (unsigned I = 0; I < Set.size(); I += N) - Elts.insert(Set[I]); - } -}; - -// (interleave S1, S2, ...) Interleave elements of the arguments. -struct InterleaveOp : public SetTheory::Operator { - void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, - ArrayRef Loc) override { - // Evaluate the arguments individually. - SmallVector Args(Expr->getNumArgs()); - unsigned MaxSize = 0; - for (unsigned i = 0, e = Expr->getNumArgs(); i != e; ++i) { - ST.evaluate(Expr->getArg(i), Args[i], Loc); - MaxSize = std::max(MaxSize, unsigned(Args[i].size())); - } - // Interleave arguments into Elts. - for (unsigned n = 0; n != MaxSize; ++n) - for (unsigned i = 0, e = Expr->getNumArgs(); i != e; ++i) - if (n < Args[i].size()) - Elts.insert(Args[i][n]); - } -}; - -// (sequence "Format", From, To) Generate a sequence of records by name. -struct SequenceOp : public SetTheory::Operator { - void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, - ArrayRef Loc) override { - int Step = 1; - if (Expr->arg_size() > 4) - PrintFatalError(Loc, "Bad args to (sequence \"Format\", From, To): " + - Expr->getAsString()); - else if (Expr->arg_size() == 4) { - if (IntInit *II = dyn_cast(Expr->arg_begin()[3])) { - Step = II->getValue(); - } else - PrintFatalError(Loc, "Stride must be an integer: " + - Expr->getAsString()); - } - - std::string Format; - if (StringInit *SI = dyn_cast(Expr->arg_begin()[0])) - Format = SI->getValue(); - else - PrintFatalError(Loc, "Format must be a string: " + Expr->getAsString()); - - int64_t From, To; - if (IntInit *II = dyn_cast(Expr->arg_begin()[1])) - From = II->getValue(); - else - PrintFatalError(Loc, "From must be an integer: " + Expr->getAsString()); - if (From < 0 || From >= (1 << 30)) - PrintFatalError(Loc, "From out of range"); - - if (IntInit *II = dyn_cast(Expr->arg_begin()[2])) - To = II->getValue(); - else - PrintFatalError(Loc, "From must be an integer: " + Expr->getAsString()); - if (To < 0 || To >= (1 << 30)) - PrintFatalError(Loc, "To out of range"); - - RecordKeeper &Records = - cast(Expr->getOperator())->getDef()->getRecords(); - - Step *= From <= To ? 1 : -1; - while (true) { - if (Step > 0 && From > To) - break; - else if (Step < 0 && From < To) - break; - std::string Name; - raw_string_ostream OS(Name); - OS << format(Format.c_str(), unsigned(From)); - Record *Rec = Records.getDef(OS.str()); - if (!Rec) - PrintFatalError(Loc, "No def named '" + Name + "': " + - Expr->getAsString()); - // Try to reevaluate Rec in case it is a set. - if (const RecVec *Result = ST.expand(Rec)) - Elts.insert(Result->begin(), Result->end()); - else - Elts.insert(Rec); - - From += Step; - } - } -}; - -// Expand a Def into a set by evaluating one of its fields. -struct FieldExpander : public SetTheory::Expander { - StringRef FieldName; - - FieldExpander(StringRef fn) : FieldName(fn) {} - - void expand(SetTheory &ST, Record *Def, RecSet &Elts) override { - ST.evaluate(Def->getValueInit(FieldName), Elts, Def->getLoc()); - } -}; -} // end anonymous namespace - -// Pin the vtables to this file. -void SetTheory::Operator::anchor() {} -void SetTheory::Expander::anchor() {} - - -SetTheory::SetTheory() { - addOperator("add", new AddOp); - addOperator("sub", new SubOp); - addOperator("and", new AndOp); - addOperator("shl", new ShlOp); - addOperator("trunc", new TruncOp); - addOperator("rotl", new RotOp(false)); - addOperator("rotr", new RotOp(true)); - addOperator("decimate", new DecimateOp); - addOperator("interleave", new InterleaveOp); - addOperator("sequence", new SequenceOp); -} - -void SetTheory::addOperator(StringRef Name, Operator *Op) { - Operators[Name] = Op; -} - -void SetTheory::addExpander(StringRef ClassName, Expander *E) { - Expanders[ClassName] = E; -} - -void SetTheory::addFieldExpander(StringRef ClassName, StringRef FieldName) { - addExpander(ClassName, new FieldExpander(FieldName)); -} - -void SetTheory::evaluate(Init *Expr, RecSet &Elts, ArrayRef Loc) { - // A def in a list can be a just an element, or it may expand. - if (DefInit *Def = dyn_cast(Expr)) { - if (const RecVec *Result = expand(Def->getDef())) - return Elts.insert(Result->begin(), Result->end()); - Elts.insert(Def->getDef()); - return; - } - - // Lists simply expand. - if (ListInit *LI = dyn_cast(Expr)) - return evaluate(LI->begin(), LI->end(), Elts, Loc); - - // Anything else must be a DAG. - DagInit *DagExpr = dyn_cast(Expr); - if (!DagExpr) - PrintFatalError(Loc, "Invalid set element: " + Expr->getAsString()); - DefInit *OpInit = dyn_cast(DagExpr->getOperator()); - if (!OpInit) - PrintFatalError(Loc, "Bad set expression: " + Expr->getAsString()); - Operator *Op = Operators.lookup(OpInit->getDef()->getName()); - if (!Op) - PrintFatalError(Loc, "Unknown set operator: " + Expr->getAsString()); - Op->apply(*this, DagExpr, Elts, Loc); -} - -const RecVec *SetTheory::expand(Record *Set) { - // Check existing entries for Set and return early. - ExpandMap::iterator I = Expansions.find(Set); - if (I != Expansions.end()) - return &I->second; - - // This is the first time we see Set. Find a suitable expander. - const std::vector &SC = Set->getSuperClasses(); - for (unsigned i = 0, e = SC.size(); i != e; ++i) { - // Skip unnamed superclasses. - if (!dyn_cast(SC[i]->getNameInit())) - continue; - if (Expander *Exp = Expanders.lookup(SC[i]->getName())) { - // This breaks recursive definitions. - RecVec &EltVec = Expansions[Set]; - RecSet Elts; - Exp->expand(*this, Set, Elts); - EltVec.assign(Elts.begin(), Elts.end()); - return &EltVec; - } - } - - // Set is not expandable. - return nullptr; -} - diff --git a/utils/TableGen/SetTheory.h b/utils/TableGen/SetTheory.h deleted file mode 100644 index 5baed79fb76..00000000000 --- a/utils/TableGen/SetTheory.h +++ /dev/null @@ -1,142 +0,0 @@ -//===- SetTheory.h - Generate ordered sets from DAG expressions -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the SetTheory class that computes ordered sets of -// Records from DAG expressions. Operators for standard set operations are -// predefined, and it is possible to add special purpose set operators as well. -// -// The user may define named sets as Records of predefined classes. Set -// expanders can be added to a SetTheory instance to teach it how to find the -// elements of such a named set. -// -// These are the predefined operators. The argument lists can be individual -// elements (defs), other sets (defs of expandable classes), lists, or DAG -// expressions that are evaluated recursively. -// -// - (add S1, S2 ...) Union sets. This is also how sets are created from element -// lists. -// -// - (sub S1, S2, ...) Set difference. Every element in S1 except for the -// elements in S2, ... -// -// - (and S1, S2) Set intersection. Every element in S1 that is also in S2. -// -// - (shl S, N) Shift left. Remove the first N elements from S. -// -// - (trunc S, N) Truncate. The first N elements of S. -// -// - (rotl S, N) Rotate left. Same as (add (shl S, N), (trunc S, N)). -// -// - (rotr S, N) Rotate right. -// -// - (decimate S, N) Decimate S by picking every N'th element, starting with -// the first one. For instance, (decimate S, 2) returns the even elements of -// S. -// -// - (sequence "Format", From, To) Generate a sequence of defs with printf. -// For instance, (sequence "R%u", 0, 3) -> [ R0, R1, R2, R3 ] -// -//===----------------------------------------------------------------------===// - -#ifndef SETTHEORY_H -#define SETTHEORY_H - -#include "llvm/ADT/SetVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/Support/SourceMgr.h" -#include -#include - -namespace llvm { - -class DagInit; -class Init; -class Record; -class RecordKeeper; - -class SetTheory { -public: - typedef std::vector RecVec; - typedef SmallSetVector RecSet; - - /// Operator - A callback representing a DAG operator. - class Operator { - virtual void anchor(); - public: - virtual ~Operator() {} - - /// apply - Apply this operator to Expr's arguments and insert the result - /// in Elts. - virtual void apply(SetTheory&, DagInit *Expr, RecSet &Elts, - ArrayRef Loc) =0; - }; - - /// Expander - A callback function that can transform a Record representing a - /// set into a fully expanded list of elements. Expanders provide a way for - /// users to define named sets that can be used in DAG expressions. - class Expander { - virtual void anchor(); - public: - virtual ~Expander() {} - - virtual void expand(SetTheory&, Record*, RecSet &Elts) =0; - }; - -private: - // Map set defs to their fully expanded contents. This serves as a memoization - // cache and it makes it possible to return const references on queries. - typedef std::map ExpandMap; - ExpandMap Expansions; - - // Known DAG operators by name. - StringMap Operators; - - // Typed expanders by class name. - StringMap Expanders; - -public: - /// Create a SetTheory instance with only the standard operators. - SetTheory(); - - /// addExpander - Add an expander for Records with the named super class. - void addExpander(StringRef ClassName, Expander*); - - /// addFieldExpander - Add an expander for ClassName that simply evaluates - /// FieldName in the Record to get the set elements. That is all that is - /// needed for a class like: - /// - /// class Set { - /// dag Elts = d; - /// } - /// - void addFieldExpander(StringRef ClassName, StringRef FieldName); - - /// addOperator - Add a DAG operator. - void addOperator(StringRef Name, Operator*); - - /// evaluate - Evaluate Expr and append the resulting set to Elts. - void evaluate(Init *Expr, RecSet &Elts, ArrayRef Loc); - - /// evaluate - Evaluate a sequence of Inits and append to Elts. - template - void evaluate(Iter begin, Iter end, RecSet &Elts, ArrayRef Loc) { - while (begin != end) - evaluate(*begin++, Elts, Loc); - } - - /// expand - Expand a record into a set of elements if possible. Return a - /// pointer to the expanded elements, or NULL if Set cannot be expanded - /// further. - const RecVec *expand(Record *Set); -}; - -} // end namespace llvm - -#endif - diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index 00c3a6fd91f..bbd61f5fb11 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -12,13 +12,13 @@ //===----------------------------------------------------------------------===// #include "TableGenBackends.h" // Declares all backends. -#include "SetTheory.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Main.h" #include "llvm/TableGen/Record.h" +#include "llvm/TableGen/SetTheory.h" using namespace llvm;