mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +00:00
Teach TableGen to evaluate DAG expressions as set operations.
A TableGen backend can define how certain classes can be expanded into ordered sets of defs, typically by evaluating a specific field in the record. The SetTheory class can then evaluate DAG expressions that refer to these named sets. A number of standard set and list operations are predefined, and the backend can add more specialized operators if needed. The -print-sets backend is used by SetTheory.td to provide examples. This is intended to simplify how register classes are defined: def GR32_NOSP : RegisterClass<"X86", [i32], 32, (sub GR32, ESP)>; git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@132621 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
404b53e38c
commit
1de99829b6
167
test/TableGen/SetTheory.td
Normal file
167
test/TableGen/SetTheory.td
Normal file
@ -0,0 +1,167 @@
|
||||
// Test evaluation of set operations in dags.
|
||||
// RUN: tblgen -print-sets %s | FileCheck %s
|
||||
// XFAIL: vg_leak
|
||||
//
|
||||
// The -print-sets driver configures a primitive SetTheory instance that
|
||||
// understands these sets:
|
||||
|
||||
class Set<dag d> {
|
||||
dag Elements = d;
|
||||
}
|
||||
|
||||
// It prints all Set instances and their ordered set interpretation.
|
||||
|
||||
// Define some elements.
|
||||
def a;
|
||||
def b;
|
||||
def c;
|
||||
def d;
|
||||
|
||||
// The 'add' operator evaluates and concatenates its arguments.
|
||||
def add;
|
||||
def S0a : Set<(add)>;
|
||||
def S0b : Set<(add a)>;
|
||||
def S0c : Set<(add a, b)>;
|
||||
def S0d : Set<(add b, a)>;
|
||||
def S0e : Set<(add a, a)>;
|
||||
def S0f : Set<(add a, a, b, a, c, b, d, a)>;
|
||||
def S0g : Set<(add b, a, b)>;
|
||||
// CHECK: S0a = [ ]
|
||||
// CHECK: S0b = [ a ]
|
||||
// CHECK: S0c = [ a b ]
|
||||
// CHECK: S0d = [ b a ]
|
||||
// CHECK: S0e = [ a ]
|
||||
// CHECK: S0f = [ a b c d ]
|
||||
// CHECK: S0g = [ b a ]
|
||||
|
||||
// Defs of Set class expand into their elements.
|
||||
// Mixed sets and elements are flattened.
|
||||
def S1a : Set<(add S0a)>;
|
||||
def S1b : Set<(add S0a, S0a)>;
|
||||
def S1c : Set<(add S0d, S0f)>;
|
||||
def S1d : Set<(add d, S0d, S0f)>;
|
||||
// CHECK: S1a = [ ]
|
||||
// CHECK: S1b = [ ]
|
||||
// CHECK: S1c = [ b a c d ]
|
||||
// CHECK: S1d = [ d b a c ]
|
||||
|
||||
// The 'sub' operator returns the first argument with the following arguments
|
||||
// removed.
|
||||
def sub;
|
||||
def S2a : Set<(sub S1a, S1c)>;
|
||||
def S2b : Set<(sub S1c, S1d)>;
|
||||
def S2c : Set<(sub S1c, b)>;
|
||||
def S2d : Set<(sub S1c, S0c)>;
|
||||
def S2e : Set<(sub S1c, S2d)>;
|
||||
// CHECK: S2a = [ ]
|
||||
// CHECK: S2b = [ ]
|
||||
// CHECK: S2c = [ a c d ]
|
||||
// CHECK: S2d = [ c d ]
|
||||
// CHECK: S2e = [ b a ]
|
||||
|
||||
// The 'and' operator intersects two sets. The result has the same order as the
|
||||
// first argument.
|
||||
def and;
|
||||
def S3a : Set<(and S2d, S2e)>;
|
||||
def S3b : Set<(and S2d, S1d)>;
|
||||
// CHECK: S3a = [ ]
|
||||
// CHECK: S3b = [ c d ]
|
||||
|
||||
// The 'shl' operator removes the first N elements.
|
||||
def shl;
|
||||
def S4a : Set<(shl S0f, 0)>;
|
||||
def S4b : Set<(shl S0f, 1)>;
|
||||
def S4c : Set<(shl S0f, 3)>;
|
||||
def S4d : Set<(shl S0f, 4)>;
|
||||
def S4e : Set<(shl S0f, 5)>;
|
||||
// CHECK: S4a = [ a b c d ]
|
||||
// CHECK: S4b = [ b c d ]
|
||||
// CHECK: S4c = [ d ]
|
||||
// CHECK: S4d = [ ]
|
||||
// CHECK: S4e = [ ]
|
||||
|
||||
// The 'trunc' operator truncates after the first N elements.
|
||||
def trunc;
|
||||
def S5a : Set<(trunc S0f, 0)>;
|
||||
def S5b : Set<(trunc S0f, 1)>;
|
||||
def S5c : Set<(trunc S0f, 3)>;
|
||||
def S5d : Set<(trunc S0f, 4)>;
|
||||
def S5e : Set<(trunc S0f, 5)>;
|
||||
// CHECK: S5a = [ ]
|
||||
// CHECK: S5b = [ a ]
|
||||
// CHECK: S5c = [ a b c ]
|
||||
// CHECK: S5d = [ a b c d ]
|
||||
// CHECK: S5e = [ a b c d ]
|
||||
|
||||
// The 'rotl' operator rotates left, but also accepts a negative shift.
|
||||
def rotl;
|
||||
def S6a : Set<(rotl S0f, 0)>;
|
||||
def S6b : Set<(rotl S0f, 1)>;
|
||||
def S6c : Set<(rotl S0f, 3)>;
|
||||
def S6d : Set<(rotl S0f, 4)>;
|
||||
def S6e : Set<(rotl S0f, 5)>;
|
||||
def S6f : Set<(rotl S0f, -1)>;
|
||||
def S6g : Set<(rotl S0f, -4)>;
|
||||
def S6h : Set<(rotl S0f, -5)>;
|
||||
// CHECK: S6a = [ a b c d ]
|
||||
// CHECK: S6b = [ b c d a ]
|
||||
// CHECK: S6c = [ d a b c ]
|
||||
// CHECK: S6d = [ a b c d ]
|
||||
// CHECK: S6e = [ b c d a ]
|
||||
// CHECK: S6f = [ d a b c ]
|
||||
// CHECK: S6g = [ a b c d ]
|
||||
// CHECK: S6h = [ d a b c ]
|
||||
|
||||
// The 'rotr' operator rotates right, but also accepts a negative shift.
|
||||
def rotr;
|
||||
def S7a : Set<(rotr S0f, 0)>;
|
||||
def S7b : Set<(rotr S0f, 1)>;
|
||||
def S7c : Set<(rotr S0f, 3)>;
|
||||
def S7d : Set<(rotr S0f, 4)>;
|
||||
def S7e : Set<(rotr S0f, 5)>;
|
||||
def S7f : Set<(rotr S0f, -1)>;
|
||||
def S7g : Set<(rotr S0f, -4)>;
|
||||
def S7h : Set<(rotr S0f, -5)>;
|
||||
// CHECK: S7a = [ a b c d ]
|
||||
// CHECK: S7b = [ d a b c ]
|
||||
// CHECK: S7c = [ b c d a ]
|
||||
// CHECK: S7d = [ a b c d ]
|
||||
// CHECK: S7e = [ d a b c ]
|
||||
// CHECK: S7f = [ b c d a ]
|
||||
// CHECK: S7g = [ a b c d ]
|
||||
// CHECK: S7h = [ b c d a ]
|
||||
|
||||
// The 'decimate' operator picks every N'th element.
|
||||
def decimate;
|
||||
def e0;
|
||||
def e1;
|
||||
def e2;
|
||||
def e3;
|
||||
def e4;
|
||||
def e5;
|
||||
def e6;
|
||||
def e7;
|
||||
def e8;
|
||||
def e9;
|
||||
def E : Set<(add e0, e1, e2, e3, e4, e5, e6, e7, e8, e9)>;
|
||||
def S8a : Set<(decimate E, 3)>;
|
||||
def S8b : Set<(decimate E, 9)>;
|
||||
def S8c : Set<(decimate E, 10)>;
|
||||
def S8d : Set<(decimate (rotl E, 1), 2)>;
|
||||
def S8e : Set<(add (decimate E, 2), (decimate (rotl E, 1), 2))>;
|
||||
// CHECK: S8a = [ e0 e3 e6 e9 ]
|
||||
// CHECK: S8b = [ e0 e9 ]
|
||||
// CHECK: S8c = [ e0 ]
|
||||
// CHECK: S8d = [ e1 e3 e5 e7 e9 ]
|
||||
// CHECK: S8e = [ e0 e2 e4 e6 e8 e1 e3 e5 e7 e9 ]
|
||||
|
||||
// The 'sequence' operator finds a sequence of records from their name.
|
||||
def sequence;
|
||||
def S9a : Set<(sequence "e%u", 3, 7)>;
|
||||
def S9b : Set<(sequence "e%u", 7, 3)>;
|
||||
def S9c : Set<(sequence "e%u", 0, 0)>;
|
||||
def S9d : Set<(sequence "S%ua", 7, 9)>;
|
||||
// CHECK: S9a = [ e3 e4 e5 e6 e7 ]
|
||||
// CHECK: S9b = [ e7 e6 e5 e4 e3 ]
|
||||
// CHECK: S9c = [ e0 ]
|
||||
// CHECK: S9d = [ a b c d e0 e3 e6 e9 e4 e5 e7 ]
|
@ -34,6 +34,7 @@ add_llvm_utility(tblgen
|
||||
OptParserEmitter.cpp
|
||||
Record.cpp
|
||||
RegisterInfoEmitter.cpp
|
||||
SetTheory.cpp
|
||||
StringMatcher.cpp
|
||||
SubtargetEmitter.cpp
|
||||
TGLexer.cpp
|
||||
|
272
utils/TableGen/SetTheory.cpp
Normal file
272
utils/TableGen/SetTheory.cpp
Normal file
@ -0,0 +1,272 @@
|
||||
//===- 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 "Record.h"
|
||||
#include "llvm/Support/Format.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) {
|
||||
ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts);
|
||||
}
|
||||
};
|
||||
|
||||
// (sub Add, Sub, ...) Set difference.
|
||||
struct SubOp : public SetTheory::Operator {
|
||||
void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) {
|
||||
if (Expr->arg_size() < 2)
|
||||
throw "Set difference needs at least two arguments: " +
|
||||
Expr->getAsString();
|
||||
RecSet Add, Sub;
|
||||
ST.evaluate(*Expr->arg_begin(), Add);
|
||||
ST.evaluate(Expr->arg_begin() + 1, Expr->arg_end(), Sub);
|
||||
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) {
|
||||
if (Expr->arg_size() != 2)
|
||||
throw "Set intersection requires two arguments: " + Expr->getAsString();
|
||||
RecSet S1, S2;
|
||||
ST.evaluate(Expr->arg_begin()[0], S1);
|
||||
ST.evaluate(Expr->arg_begin()[1], S2);
|
||||
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 apply(SetTheory &ST, DagInit *Expr,
|
||||
RecSet &Set, int64_t N,
|
||||
RecSet &Elts) =0;
|
||||
|
||||
void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) {
|
||||
if (Expr->arg_size() != 2)
|
||||
throw "Operator requires (Op Set, Int) arguments: " + Expr->getAsString();
|
||||
RecSet Set;
|
||||
ST.evaluate(Expr->arg_begin()[0], Set);
|
||||
IntInit *II = dynamic_cast<IntInit*>(Expr->arg_begin()[1]);
|
||||
if (!II)
|
||||
throw "Second argument must be an integer: " + Expr->getAsString();
|
||||
apply(ST, Expr, Set, II->getValue(), Elts);
|
||||
}
|
||||
};
|
||||
|
||||
// (shl S, N) Shift left, remove the first N elements.
|
||||
struct ShlOp : public SetIntBinOp {
|
||||
void apply(SetTheory &ST, DagInit *Expr,
|
||||
RecSet &Set, int64_t N,
|
||||
RecSet &Elts) {
|
||||
if (N < 0)
|
||||
throw "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 apply(SetTheory &ST, DagInit *Expr,
|
||||
RecSet &Set, int64_t N,
|
||||
RecSet &Elts) {
|
||||
if (N < 0)
|
||||
throw "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 apply(SetTheory &ST, DagInit *Expr,
|
||||
RecSet &Set, int64_t N,
|
||||
RecSet &Elts) {
|
||||
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 apply(SetTheory &ST, DagInit *Expr,
|
||||
RecSet &Set, int64_t N,
|
||||
RecSet &Elts) {
|
||||
if (N <= 0)
|
||||
throw "Positive stride required: " + Expr->getAsString();
|
||||
for (unsigned I = 0; I < Set.size(); I += N)
|
||||
Elts.insert(Set[I]);
|
||||
}
|
||||
};
|
||||
|
||||
// (sequence "Format", From, To) Generate a sequence of records by name.
|
||||
struct SequenceOp : public SetTheory::Operator {
|
||||
RecordKeeper &Records;
|
||||
|
||||
SequenceOp(RecordKeeper&R) : Records(R) {}
|
||||
|
||||
void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) {
|
||||
if (Expr->arg_size() != 3)
|
||||
throw "Bad args to (sequence \"Format\", From, To): " +
|
||||
Expr->getAsString();
|
||||
std::string Format;
|
||||
if (StringInit *SI = dynamic_cast<StringInit*>(Expr->arg_begin()[0]))
|
||||
Format = SI->getValue();
|
||||
else
|
||||
throw "Format must be a string: " + Expr->getAsString();
|
||||
|
||||
int64_t From, To;
|
||||
if (IntInit *II = dynamic_cast<IntInit*>(Expr->arg_begin()[1]))
|
||||
From = II->getValue();
|
||||
else
|
||||
throw "From must be an integer: " + Expr->getAsString();
|
||||
if (IntInit *II = dynamic_cast<IntInit*>(Expr->arg_begin()[2]))
|
||||
To = II->getValue();
|
||||
else
|
||||
throw "From must be an integer: " + Expr->getAsString();
|
||||
|
||||
int Step = From <= To ? 1 : -1;
|
||||
for (To += Step; From != To; From += Step) {
|
||||
std::string Name;
|
||||
raw_string_ostream OS(Name);
|
||||
OS << format(Format.c_str(), From);
|
||||
Record *Rec = Records.getDef(OS.str());
|
||||
if (!Rec)
|
||||
throw "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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 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) {
|
||||
ST.evaluate(Def->getValueInit(FieldName), Elts);
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
SetTheory::SetTheory(RecordKeeper *Records) {
|
||||
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);
|
||||
if (Records)
|
||||
addOperator("sequence", new SequenceOp(*Records));
|
||||
}
|
||||
|
||||
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) {
|
||||
// A def in a list can be a just an element, or it may expand.
|
||||
if (DefInit *Def = dynamic_cast<DefInit*>(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 = dynamic_cast<ListInit*>(Expr))
|
||||
return evaluate(LI->begin(), LI->end(), Elts);
|
||||
|
||||
// Anything else must be a DAG.
|
||||
DagInit *DagExpr = dynamic_cast<DagInit*>(Expr);
|
||||
if (!DagExpr)
|
||||
throw "Invalid set element: " + Expr->getAsString();
|
||||
DefInit *OpInit = dynamic_cast<DefInit*>(DagExpr->getOperator());
|
||||
if (!OpInit)
|
||||
throw "Bad set expression: " + Expr->getAsString();
|
||||
Operator *Op = Operators.lookup(OpInit->getDef()->getName());
|
||||
if (!Op)
|
||||
throw "Unknown set operator: " + Expr->getAsString();
|
||||
Op->apply(*this, DagExpr, Elts);
|
||||
}
|
||||
|
||||
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.
|
||||
try {
|
||||
const std::vector<Record*> &SC = Set->getSuperClasses();
|
||||
for (unsigned i = 0, e = SC.size(); i != e; ++i)
|
||||
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;
|
||||
}
|
||||
} catch (const std::string &Error) {
|
||||
throw TGError(Set->getLoc(), Error);
|
||||
}
|
||||
|
||||
// Set is not expandable.
|
||||
return 0;
|
||||
}
|
||||
|
133
utils/TableGen/SetTheory.h
Normal file
133
utils/TableGen/SetTheory.h
Normal file
@ -0,0 +1,133 @@
|
||||
//===- 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/StringMap.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class DagInit;
|
||||
struct Init;
|
||||
class Record;
|
||||
class RecordKeeper;
|
||||
|
||||
class SetTheory {
|
||||
public:
|
||||
typedef std::vector<Record*> RecVec;
|
||||
typedef SmallSetVector<Record*, 16> RecSet;
|
||||
|
||||
/// Operator - A callback representing a DAG operator.
|
||||
struct Operator {
|
||||
/// apply - Apply this operator to Expr's arguments and insert the result
|
||||
/// in Elts.
|
||||
virtual void apply(SetTheory&, DagInit *Expr, RecSet &Elts) =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.
|
||||
struct 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<Record*, RecVec> ExpandMap;
|
||||
ExpandMap Expansions;
|
||||
|
||||
// Known DAG operators by name.
|
||||
StringMap<Operator*> Operators;
|
||||
|
||||
// Typed expanders by class name.
|
||||
StringMap<Expander*> Expanders;
|
||||
|
||||
public:
|
||||
/// Create a SetTheory instance with only the standard operators.
|
||||
/// A 'sequence' operator will only be added if a RecordKeeper is given.
|
||||
SetTheory(RecordKeeper *Records = 0);
|
||||
|
||||
/// 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 d> {
|
||||
/// 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);
|
||||
|
||||
/// evaluate - Evaluate a sequence of Inits and append to Elts.
|
||||
template<typename Iter>
|
||||
void evaluate(Iter begin, Iter end, RecSet &Elts) {
|
||||
while (begin != end)
|
||||
evaluate(*begin++, Elts);
|
||||
}
|
||||
|
||||
/// 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
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "RegisterInfoEmitter.h"
|
||||
#include "ARMDecoderEmitter.h"
|
||||
#include "SubtargetEmitter.h"
|
||||
#include "SetTheory.h"
|
||||
#include "TGParser.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
@ -80,7 +81,8 @@ enum ActionType {
|
||||
GenArmNeon,
|
||||
GenArmNeonSema,
|
||||
GenArmNeonTest,
|
||||
PrintEnums
|
||||
PrintEnums,
|
||||
PrintSets
|
||||
};
|
||||
|
||||
namespace {
|
||||
@ -162,6 +164,8 @@ namespace {
|
||||
"Generate ARM NEON tests for clang"),
|
||||
clEnumValN(PrintEnums, "print-enums",
|
||||
"Print enum values for a class"),
|
||||
clEnumValN(PrintSets, "print-sets",
|
||||
"Print expanded sets for testing DAG exprs"),
|
||||
clEnumValEnd));
|
||||
|
||||
cl::opt<std::string>
|
||||
@ -374,6 +378,21 @@ int main(int argc, char **argv) {
|
||||
Out.os() << "\n";
|
||||
break;
|
||||
}
|
||||
case PrintSets:
|
||||
{
|
||||
SetTheory Sets(&Records);
|
||||
Sets.addFieldExpander("Set", "Elements");
|
||||
std::vector<Record*> Recs = Records.getAllDerivedDefinitions("Set");
|
||||
for (unsigned i = 0, e = Recs.size(); i != e; ++i) {
|
||||
Out.os() << Recs[i]->getName() << " = [";
|
||||
const std::vector<Record*> *Elts = Sets.expand(Recs[i]);
|
||||
assert(Elts && "Couldn't expand Set instance");
|
||||
for (unsigned ei = 0, ee = Elts->size(); ei != ee; ++ei)
|
||||
Out.os() << ' ' << (*Elts)[ei]->getName();
|
||||
Out.os() << " ]\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(1 && "Invalid Action");
|
||||
return 1;
|
||||
|
Loading…
Reference in New Issue
Block a user