mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-09-02 11:30:10 +00:00
Add some data structures to represent for loops. These will be referenced during object processing to do any needed iteration and instantiation. Add foreach keyword support to the lexer. Add a mode to indicate that we're parsing a foreach loop. This allows the value parser to early-out when processing the foreach value list. Add a routine to parse foreach iteration declarations. This is separate from ParseDeclaration because the type of the named value (the iterator) doesn't match the type of the initializer value (the value list). It also needs to add two values to the foreach record: the iterator and the value list. Add parsing support for foreach. Add the code to process foreach loops and create defs based on iterator values. Allow foreach loops to be matched at the top level. When parsing an IDValue check if it is a foreach loop iterator for one of the active loops. If so, return a VarInit for it. Add Emacs keyword support for foreach. Add VIM keyword support for foreach. Add tests to check foreach operation. Add TableGen documentation for foreach. Support foreach with multiple objects. Support non-braced foreach body with one object. Do not require types for the foreach declaration. Assume the iterator type from the iteration list element type. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151164 91177308-0d34-0410-b5e6-96231b3b80d8
1626 lines
57 KiB
C++
1626 lines
57 KiB
C++
//===- llvm/TableGen/Record.h - Classes for Table Records -------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the main TableGen data structures, including the TableGen
|
|
// types, values, and high-level data structures.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_TABLEGEN_RECORD_H
|
|
#define LLVM_TABLEGEN_RECORD_H
|
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
#include "llvm/ADT/FoldingSet.h"
|
|
#include "llvm/Support/Allocator.h"
|
|
#include "llvm/Support/SourceMgr.h"
|
|
#include "llvm/Support/DataTypes.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include <map>
|
|
|
|
namespace llvm {
|
|
class raw_ostream;
|
|
|
|
// RecTy subclasses.
|
|
class BitRecTy;
|
|
class BitsRecTy;
|
|
class IntRecTy;
|
|
class StringRecTy;
|
|
class ListRecTy;
|
|
class DagRecTy;
|
|
class RecordRecTy;
|
|
|
|
// Init subclasses.
|
|
class Init;
|
|
class UnsetInit;
|
|
class BitInit;
|
|
class BitsInit;
|
|
class IntInit;
|
|
class StringInit;
|
|
class ListInit;
|
|
class UnOpInit;
|
|
class BinOpInit;
|
|
class TernOpInit;
|
|
class DefInit;
|
|
class DagInit;
|
|
class TypedInit;
|
|
class VarInit;
|
|
class FieldInit;
|
|
class VarBitInit;
|
|
class VarListElementInit;
|
|
|
|
// Other classes.
|
|
class Record;
|
|
class RecordVal;
|
|
struct MultiClass;
|
|
class RecordKeeper;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Type Classes
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
class RecTy {
|
|
ListRecTy *ListTy;
|
|
virtual void anchor();
|
|
public:
|
|
RecTy() : ListTy(0) {}
|
|
virtual ~RecTy() {}
|
|
|
|
virtual std::string getAsString() const = 0;
|
|
void print(raw_ostream &OS) const { OS << getAsString(); }
|
|
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;
|
|
|
|
/// getListTy - Returns the type representing list<this>.
|
|
ListRecTy *getListTy();
|
|
|
|
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( UnOpInit *UI) {
|
|
return convertValue((TypedInit*)UI);
|
|
}
|
|
virtual Init *convertValue( BinOpInit *UI) {
|
|
return convertValue((TypedInit*)UI);
|
|
}
|
|
virtual Init *convertValue( TernOpInit *UI) {
|
|
return convertValue((TypedInit*)UI);
|
|
}
|
|
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 DagRecTy *RHS) const { return false; }
|
|
virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
|
|
};
|
|
|
|
inline raw_ostream &operator<<(raw_ostream &OS, const RecTy &Ty) {
|
|
Ty.print(OS);
|
|
return OS;
|
|
}
|
|
|
|
|
|
/// BitRecTy - 'bit' - Represent a single bit
|
|
///
|
|
class BitRecTy : public RecTy {
|
|
static BitRecTy Shared;
|
|
BitRecTy() {}
|
|
public:
|
|
static BitRecTy *get() { return &Shared; }
|
|
|
|
virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
|
|
virtual Init *convertValue( BitInit *BI) { return (Init*)BI; }
|
|
virtual Init *convertValue( BitsInit *BI);
|
|
virtual Init *convertValue( IntInit *II);
|
|
virtual Init *convertValue(StringInit *SI) { return 0; }
|
|
virtual Init *convertValue( ListInit *LI) { return 0; }
|
|
virtual Init *convertValue(VarBitInit *VB) { return (Init*)VB; }
|
|
virtual Init *convertValue( DefInit *DI) { return 0; }
|
|
virtual Init *convertValue( DagInit *DI) { return 0; }
|
|
virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
|
|
virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
|
|
virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
|
|
virtual Init *convertValue( TypedInit *TI);
|
|
virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
|
|
virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
|
|
|
|
std::string getAsString() const { return "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; }
|
|
virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
|
|
virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
|
|
virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
|
|
virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
|
|
|
|
};
|
|
|
|
|
|
// BitsRecTy - 'bits<n>' - Represent a fixed number of bits
|
|
/// BitsRecTy - 'bits<n>' - Represent a fixed number of bits
|
|
///
|
|
class BitsRecTy : public RecTy {
|
|
unsigned Size;
|
|
explicit BitsRecTy(unsigned Sz) : Size(Sz) {}
|
|
public:
|
|
static BitsRecTy *get(unsigned Sz);
|
|
|
|
unsigned getNumBits() const { return Size; }
|
|
|
|
virtual Init *convertValue( UnsetInit *UI);
|
|
virtual Init *convertValue( BitInit *UI);
|
|
virtual Init *convertValue( BitsInit *BI);
|
|
virtual Init *convertValue( IntInit *II);
|
|
virtual Init *convertValue(StringInit *SI) { return 0; }
|
|
virtual Init *convertValue( ListInit *LI) { 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( UnOpInit *UI) { return RecTy::convertValue(UI);}
|
|
virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
|
|
virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
|
|
virtual Init *convertValue( TypedInit *TI);
|
|
virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
|
|
virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
|
|
|
|
std::string getAsString() const;
|
|
|
|
bool typeIsConvertibleTo(const RecTy *RHS) const {
|
|
return RHS->baseClassOf(this);
|
|
}
|
|
virtual bool baseClassOf(const BitRecTy *RHS) const { return Size == 1; }
|
|
virtual bool baseClassOf(const BitsRecTy *RHS) const {
|
|
return RHS->Size == Size;
|
|
}
|
|
virtual bool baseClassOf(const IntRecTy *RHS) const { return true; }
|
|
virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
|
|
virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
|
|
virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
|
|
virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
|
|
|
|
};
|
|
|
|
|
|
/// IntRecTy - 'int' - Represent an integer value of no particular size
|
|
///
|
|
class IntRecTy : public RecTy {
|
|
static IntRecTy Shared;
|
|
IntRecTy() {}
|
|
public:
|
|
static IntRecTy *get() { return &Shared; }
|
|
|
|
virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
|
|
virtual Init *convertValue( BitInit *BI);
|
|
virtual Init *convertValue( BitsInit *BI);
|
|
virtual Init *convertValue( IntInit *II) { return (Init*)II; }
|
|
virtual Init *convertValue(StringInit *SI) { return 0; }
|
|
virtual Init *convertValue( ListInit *LI) { 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( UnOpInit *UI) { return RecTy::convertValue(UI);}
|
|
virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
|
|
virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
|
|
virtual Init *convertValue( TypedInit *TI);
|
|
virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
|
|
virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
|
|
|
|
std::string getAsString() const { return "int"; }
|
|
|
|
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 { return true; }
|
|
virtual bool baseClassOf(const IntRecTy *RHS) const { return true; }
|
|
virtual bool baseClassOf(const StringRecTy *RHS) const { return false; }
|
|
virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
|
|
virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
|
|
virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
|
|
|
|
};
|
|
|
|
/// StringRecTy - 'string' - Represent an string value
|
|
///
|
|
class StringRecTy : public RecTy {
|
|
static StringRecTy Shared;
|
|
StringRecTy() {}
|
|
public:
|
|
static StringRecTy *get() { return &Shared; }
|
|
|
|
virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
|
|
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 (Init*)SI; }
|
|
virtual Init *convertValue( ListInit *LI) { return 0; }
|
|
virtual Init *convertValue( UnOpInit *BO);
|
|
virtual Init *convertValue( BinOpInit *BO);
|
|
virtual Init *convertValue( TernOpInit *BO) { return RecTy::convertValue(BO);}
|
|
|
|
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);
|
|
virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
|
|
virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
|
|
|
|
std::string getAsString() const { return "string"; }
|
|
|
|
bool typeIsConvertibleTo(const RecTy *RHS) const {
|
|
return RHS->baseClassOf(this);
|
|
}
|
|
|
|
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 true; }
|
|
virtual bool baseClassOf(const ListRecTy *RHS) const { return false; }
|
|
virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
|
|
virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
|
|
};
|
|
|
|
// ListRecTy - 'list<Ty>' - Represent a list of values, all of which must be of
|
|
// the specified type.
|
|
/// ListRecTy - 'list<Ty>' - Represent a list of values, all of which must
|
|
/// be of the specified type.
|
|
///
|
|
class ListRecTy : public RecTy {
|
|
RecTy *Ty;
|
|
explicit ListRecTy(RecTy *T) : Ty(T) {}
|
|
friend ListRecTy *RecTy::getListTy();
|
|
public:
|
|
static ListRecTy *get(RecTy *T) { return T->getListTy(); }
|
|
RecTy *getElementType() const { return Ty; }
|
|
|
|
virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
|
|
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);
|
|
virtual Init *convertValue(VarBitInit *VB) { return 0; }
|
|
virtual Init *convertValue( DefInit *DI) { return 0; }
|
|
virtual Init *convertValue( DagInit *DI) { return 0; }
|
|
virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
|
|
virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
|
|
virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
|
|
virtual Init *convertValue( TypedInit *TI);
|
|
virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
|
|
virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
|
|
|
|
std::string getAsString() const;
|
|
|
|
bool typeIsConvertibleTo(const RecTy *RHS) const {
|
|
return RHS->baseClassOf(this);
|
|
}
|
|
|
|
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 RHS->getElementType()->typeIsConvertibleTo(Ty);
|
|
}
|
|
virtual bool baseClassOf(const DagRecTy *RHS) const { return false; }
|
|
virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
|
|
};
|
|
|
|
/// DagRecTy - 'dag' - Represent a dag fragment
|
|
///
|
|
class DagRecTy : public RecTy {
|
|
static DagRecTy Shared;
|
|
DagRecTy() {}
|
|
public:
|
|
static DagRecTy *get() { return &Shared; }
|
|
|
|
virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
|
|
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(VarBitInit *VB) { return 0; }
|
|
virtual Init *convertValue( DefInit *DI) { return 0; }
|
|
virtual Init *convertValue( UnOpInit *BO);
|
|
virtual Init *convertValue( BinOpInit *BO);
|
|
virtual Init *convertValue( TernOpInit *BO) { return RecTy::convertValue(BO);}
|
|
virtual Init *convertValue( DagInit *CI) { return (Init*)CI; }
|
|
virtual Init *convertValue( TypedInit *TI);
|
|
virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
|
|
virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
|
|
|
|
std::string getAsString() const { return "dag"; }
|
|
|
|
bool typeIsConvertibleTo(const RecTy *RHS) const {
|
|
return RHS->baseClassOf(this);
|
|
}
|
|
|
|
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 DagRecTy *RHS) const { return true; }
|
|
virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; }
|
|
};
|
|
|
|
|
|
/// RecordRecTy - '[classname]' - Represent an instance of a class, such as:
|
|
/// (R32 X = EAX).
|
|
///
|
|
class RecordRecTy : public RecTy {
|
|
Record *Rec;
|
|
explicit RecordRecTy(Record *R) : Rec(R) {}
|
|
friend class Record;
|
|
public:
|
|
static RecordRecTy *get(Record *R);
|
|
|
|
Record *getRecord() const { return Rec; }
|
|
|
|
virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; }
|
|
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(VarBitInit *VB) { return 0; }
|
|
virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);}
|
|
virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);}
|
|
virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);}
|
|
virtual Init *convertValue( DefInit *DI);
|
|
virtual Init *convertValue( DagInit *DI) { return 0; }
|
|
virtual Init *convertValue( TypedInit *VI);
|
|
virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);}
|
|
virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);}
|
|
|
|
std::string getAsString() const;
|
|
|
|
bool typeIsConvertibleTo(const RecTy *RHS) const {
|
|
return RHS->baseClassOf(this);
|
|
}
|
|
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 DagRecTy *RHS) const { return false; }
|
|
virtual bool baseClassOf(const RecordRecTy *RHS) const;
|
|
};
|
|
|
|
/// resolveTypes - Find a common type that T1 and T2 convert to.
|
|
/// Return 0 if no such type exists.
|
|
///
|
|
RecTy *resolveTypes(RecTy *T1, RecTy *T2);
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Initializer Classes
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
class Init {
|
|
Init(const Init &); // Do not define.
|
|
Init &operator=(const Init &); // Do not define.
|
|
virtual void anchor();
|
|
|
|
protected:
|
|
Init(void) {}
|
|
|
|
public:
|
|
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.
|
|
void print(raw_ostream &OS) const { OS << getAsString(); }
|
|
|
|
/// getAsString - Convert this value to a string form.
|
|
virtual std::string getAsString() const = 0;
|
|
/// getAsUnquotedString - Convert this value to a string form,
|
|
/// without adding quote markers. This primaruly affects
|
|
/// StringInits where we will not surround the string value with
|
|
/// quotes.
|
|
virtual std::string getAsUnquotedString() const { return getAsString(); }
|
|
|
|
/// dump - Debugging method that may be called through a debugger, just
|
|
/// invokes print on stderr.
|
|
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) const = 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) const {
|
|
return 0;
|
|
}
|
|
|
|
/// convertInitListSlice - This method is used to implement the list slice
|
|
/// selection operator. Given an initializer, it selects the specified list
|
|
/// elements, returning them as a new init of list type. If it is not legal
|
|
/// to take a slice of this, return null.
|
|
///
|
|
virtual Init *
|
|
convertInitListSlice(const std::vector<unsigned> &Elements) const {
|
|
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 RecordVal *RV,
|
|
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 the 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, const RecordVal *RV) const {
|
|
return const_cast<Init *>(this);
|
|
}
|
|
};
|
|
|
|
inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) {
|
|
I.print(OS); return OS;
|
|
}
|
|
|
|
/// TypedInit - This is the common super-class of types that have a specific,
|
|
/// explicit, type.
|
|
///
|
|
class TypedInit : public Init {
|
|
RecTy *Ty;
|
|
|
|
TypedInit(const TypedInit &Other); // Do not define.
|
|
TypedInit &operator=(const TypedInit &Other); // Do not define.
|
|
|
|
protected:
|
|
explicit TypedInit(RecTy *T) : Ty(T) {}
|
|
|
|
public:
|
|
RecTy *getType() const { return Ty; }
|
|
|
|
virtual Init *
|
|
convertInitializerBitRange(const std::vector<unsigned> &Bits) const;
|
|
virtual Init *
|
|
convertInitListSlice(const std::vector<unsigned> &Elements) const;
|
|
|
|
/// 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;
|
|
|
|
/// 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 null.
|
|
///
|
|
virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
|
|
unsigned Bit) const = 0;
|
|
|
|
/// resolveListElementReference - This method is used to implement
|
|
/// VarListElementInit::resolveReferences. If the list element is resolvable
|
|
/// now, we return the resolved value, otherwise we return null.
|
|
virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
|
unsigned Elt) const = 0;
|
|
};
|
|
|
|
|
|
/// UnsetInit - ? - Represents an uninitialized value
|
|
///
|
|
class UnsetInit : public Init {
|
|
UnsetInit() : Init() {}
|
|
UnsetInit(const UnsetInit &); // Do not define.
|
|
UnsetInit &operator=(const UnsetInit &Other); // Do not define.
|
|
virtual void anchor();
|
|
|
|
public:
|
|
static UnsetInit *get();
|
|
|
|
virtual Init *convertInitializerTo(RecTy *Ty) const {
|
|
return Ty->convertValue(const_cast<UnsetInit *>(this));
|
|
}
|
|
|
|
virtual bool isComplete() const { return false; }
|
|
virtual std::string getAsString() const { return "?"; }
|
|
};
|
|
|
|
|
|
/// BitInit - true/false - Represent a concrete initializer for a bit.
|
|
///
|
|
class BitInit : public Init {
|
|
bool Value;
|
|
|
|
explicit BitInit(bool V) : Value(V) {}
|
|
BitInit(const BitInit &Other); // Do not define.
|
|
BitInit &operator=(BitInit &Other); // Do not define.
|
|
virtual void anchor();
|
|
|
|
public:
|
|
static BitInit *get(bool V);
|
|
|
|
bool getValue() const { return Value; }
|
|
|
|
virtual Init *convertInitializerTo(RecTy *Ty) const {
|
|
return Ty->convertValue(const_cast<BitInit *>(this));
|
|
}
|
|
|
|
virtual std::string getAsString() const { return 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, public FoldingSetNode {
|
|
std::vector<Init*> Bits;
|
|
|
|
BitsInit(ArrayRef<Init *> Range) : Bits(Range.begin(), Range.end()) {}
|
|
|
|
BitsInit(const BitsInit &Other); // Do not define.
|
|
BitsInit &operator=(const BitsInit &Other); // Do not define.
|
|
|
|
public:
|
|
static BitsInit *get(ArrayRef<Init *> Range);
|
|
|
|
void Profile(FoldingSetNodeID &ID) const;
|
|
|
|
unsigned getNumBits() const { return Bits.size(); }
|
|
|
|
Init *getBit(unsigned Bit) const {
|
|
assert(Bit < Bits.size() && "Bit index out of range!");
|
|
return Bits[Bit];
|
|
}
|
|
|
|
virtual Init *convertInitializerTo(RecTy *Ty) const {
|
|
return Ty->convertValue(const_cast<BitsInit *>(this));
|
|
}
|
|
virtual Init *
|
|
convertInitializerBitRange(const std::vector<unsigned> &Bits) const;
|
|
|
|
virtual bool isComplete() const {
|
|
for (unsigned i = 0; i != getNumBits(); ++i)
|
|
if (!getBit(i)->isComplete()) return false;
|
|
return true;
|
|
}
|
|
bool allInComplete() const {
|
|
for (unsigned i = 0; i != getNumBits(); ++i)
|
|
if (getBit(i)->isComplete()) return false;
|
|
return true;
|
|
}
|
|
virtual std::string getAsString() const;
|
|
|
|
virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
|
|
};
|
|
|
|
|
|
/// IntInit - 7 - Represent an initalization by a literal integer value.
|
|
///
|
|
class IntInit : public TypedInit {
|
|
int64_t Value;
|
|
|
|
explicit IntInit(int64_t V) : TypedInit(IntRecTy::get()), Value(V) {}
|
|
|
|
IntInit(const IntInit &Other); // Do not define.
|
|
IntInit &operator=(const IntInit &Other); // Do note define.
|
|
|
|
public:
|
|
static IntInit *get(int64_t V);
|
|
|
|
int64_t getValue() const { return Value; }
|
|
|
|
virtual Init *convertInitializerTo(RecTy *Ty) const {
|
|
return Ty->convertValue(const_cast<IntInit *>(this));
|
|
}
|
|
virtual Init *
|
|
convertInitializerBitRange(const std::vector<unsigned> &Bits) const;
|
|
|
|
virtual std::string getAsString() const;
|
|
|
|
/// 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 null.
|
|
///
|
|
virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
|
|
unsigned Bit) const {
|
|
llvm_unreachable("Illegal bit reference off int");
|
|
}
|
|
|
|
/// resolveListElementReference - This method is used to implement
|
|
/// VarListElementInit::resolveReferences. If the list element is resolvable
|
|
/// now, we return the resolved value, otherwise we return null.
|
|
virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
|
unsigned Elt) const {
|
|
llvm_unreachable("Illegal element reference off int");
|
|
}
|
|
};
|
|
|
|
|
|
/// StringInit - "foo" - Represent an initialization by a string value.
|
|
///
|
|
class StringInit : public TypedInit {
|
|
std::string Value;
|
|
|
|
explicit StringInit(const std::string &V)
|
|
: TypedInit(StringRecTy::get()), Value(V) {}
|
|
|
|
StringInit(const StringInit &Other); // Do not define.
|
|
StringInit &operator=(const StringInit &Other); // Do not define.
|
|
virtual void anchor();
|
|
|
|
public:
|
|
static StringInit *get(StringRef);
|
|
|
|
const std::string &getValue() const { return Value; }
|
|
|
|
virtual Init *convertInitializerTo(RecTy *Ty) const {
|
|
return Ty->convertValue(const_cast<StringInit *>(this));
|
|
}
|
|
|
|
virtual std::string getAsString() const { return "\"" + Value + "\""; }
|
|
virtual std::string getAsUnquotedString() const { return Value; }
|
|
|
|
/// 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 null.
|
|
///
|
|
virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
|
|
unsigned Bit) const {
|
|
llvm_unreachable("Illegal bit reference off string");
|
|
}
|
|
|
|
/// resolveListElementReference - This method is used to implement
|
|
/// VarListElementInit::resolveReferences. If the list element is resolvable
|
|
/// now, we return the resolved value, otherwise we return null.
|
|
virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
|
unsigned Elt) const {
|
|
llvm_unreachable("Illegal element reference off string");
|
|
}
|
|
};
|
|
|
|
/// ListInit - [AL, AH, CL] - Represent a list of defs
|
|
///
|
|
class ListInit : public TypedInit, public FoldingSetNode {
|
|
std::vector<Init*> Values;
|
|
public:
|
|
typedef std::vector<Init*>::const_iterator const_iterator;
|
|
|
|
private:
|
|
explicit ListInit(ArrayRef<Init *> Range, RecTy *EltTy)
|
|
: TypedInit(ListRecTy::get(EltTy)), Values(Range.begin(), Range.end()) {}
|
|
|
|
ListInit(const ListInit &Other); // Do not define.
|
|
ListInit &operator=(const ListInit &Other); // Do not define.
|
|
|
|
public:
|
|
static ListInit *get(ArrayRef<Init *> Range, RecTy *EltTy);
|
|
|
|
void Profile(FoldingSetNodeID &ID) const;
|
|
|
|
unsigned getSize() const { return Values.size(); }
|
|
Init *getElement(unsigned i) const {
|
|
assert(i < Values.size() && "List element index out of range!");
|
|
return Values[i];
|
|
}
|
|
|
|
Record *getElementAsRecord(unsigned i) const;
|
|
|
|
Init *convertInitListSlice(const std::vector<unsigned> &Elements) const;
|
|
|
|
virtual Init *convertInitializerTo(RecTy *Ty) const {
|
|
return Ty->convertValue(const_cast<ListInit *>(this));
|
|
}
|
|
|
|
/// 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, const RecordVal *RV) const;
|
|
|
|
virtual std::string getAsString() const;
|
|
|
|
ArrayRef<Init*> getValues() const { return Values; }
|
|
|
|
inline const_iterator begin() const { return Values.begin(); }
|
|
inline const_iterator end () const { return Values.end(); }
|
|
|
|
inline size_t size () const { return Values.size(); }
|
|
inline bool empty() const { return Values.empty(); }
|
|
|
|
/// 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 null.
|
|
///
|
|
virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
|
|
unsigned Bit) const {
|
|
llvm_unreachable("Illegal bit reference off list");
|
|
}
|
|
|
|
/// resolveListElementReference - This method is used to implement
|
|
/// VarListElementInit::resolveReferences. If the list element is resolvable
|
|
/// now, we return the resolved value, otherwise we return null.
|
|
virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
|
unsigned Elt) const;
|
|
};
|
|
|
|
|
|
/// OpInit - Base class for operators
|
|
///
|
|
class OpInit : public TypedInit {
|
|
OpInit(const OpInit &Other); // Do not define.
|
|
OpInit &operator=(OpInit &Other); // Do not define.
|
|
|
|
protected:
|
|
explicit OpInit(RecTy *Type) : TypedInit(Type) {}
|
|
|
|
public:
|
|
// Clone - Clone this operator, replacing arguments with the new list
|
|
virtual OpInit *clone(std::vector<Init *> &Operands) const = 0;
|
|
|
|
virtual int getNumOperands() const = 0;
|
|
virtual Init *getOperand(int i) const = 0;
|
|
|
|
// Fold - If possible, fold this to a simpler init. Return this if not
|
|
// possible to fold.
|
|
virtual Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const = 0;
|
|
|
|
virtual Init *convertInitializerTo(RecTy *Ty) const {
|
|
return Ty->convertValue(const_cast<OpInit *>(this));
|
|
}
|
|
|
|
virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
|
|
unsigned Bit) const;
|
|
virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
|
unsigned Elt) const;
|
|
};
|
|
|
|
|
|
/// UnOpInit - !op (X) - Transform an init.
|
|
///
|
|
class UnOpInit : public OpInit {
|
|
public:
|
|
enum UnaryOp { CAST, HEAD, TAIL, EMPTY };
|
|
private:
|
|
UnaryOp Opc;
|
|
Init *LHS;
|
|
|
|
UnOpInit(UnaryOp opc, Init *lhs, RecTy *Type)
|
|
: OpInit(Type), Opc(opc), LHS(lhs) {}
|
|
|
|
UnOpInit(const UnOpInit &Other); // Do not define.
|
|
UnOpInit &operator=(const UnOpInit &Other); // Do not define.
|
|
|
|
public:
|
|
static UnOpInit *get(UnaryOp opc, Init *lhs, RecTy *Type);
|
|
|
|
// Clone - Clone this operator, replacing arguments with the new list
|
|
virtual OpInit *clone(std::vector<Init *> &Operands) const {
|
|
assert(Operands.size() == 1 &&
|
|
"Wrong number of operands for unary operation");
|
|
return UnOpInit::get(getOpcode(), *Operands.begin(), getType());
|
|
}
|
|
|
|
int getNumOperands() const { return 1; }
|
|
Init *getOperand(int i) const {
|
|
assert(i == 0 && "Invalid operand id for unary operator");
|
|
return getOperand();
|
|
}
|
|
|
|
UnaryOp getOpcode() const { return Opc; }
|
|
Init *getOperand() const { return LHS; }
|
|
|
|
// Fold - If possible, fold this to a simpler init. Return this if not
|
|
// possible to fold.
|
|
Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const;
|
|
|
|
virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
|
|
|
|
virtual std::string getAsString() const;
|
|
};
|
|
|
|
/// BinOpInit - !op (X, Y) - Combine two inits.
|
|
///
|
|
class BinOpInit : public OpInit {
|
|
public:
|
|
enum BinaryOp { SHL, SRA, SRL, STRCONCAT, CONCAT, EQ };
|
|
private:
|
|
BinaryOp Opc;
|
|
Init *LHS, *RHS;
|
|
|
|
BinOpInit(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type) :
|
|
OpInit(Type), Opc(opc), LHS(lhs), RHS(rhs) {}
|
|
|
|
BinOpInit(const BinOpInit &Other); // Do not define.
|
|
BinOpInit &operator=(const BinOpInit &Other); // Do not define.
|
|
|
|
public:
|
|
static BinOpInit *get(BinaryOp opc, Init *lhs, Init *rhs,
|
|
RecTy *Type);
|
|
|
|
// Clone - Clone this operator, replacing arguments with the new list
|
|
virtual OpInit *clone(std::vector<Init *> &Operands) const {
|
|
assert(Operands.size() == 2 &&
|
|
"Wrong number of operands for binary operation");
|
|
return BinOpInit::get(getOpcode(), Operands[0], Operands[1], getType());
|
|
}
|
|
|
|
int getNumOperands() const { return 2; }
|
|
Init *getOperand(int i) const {
|
|
assert((i == 0 || i == 1) && "Invalid operand id for binary operator");
|
|
if (i == 0) {
|
|
return getLHS();
|
|
} else {
|
|
return getRHS();
|
|
}
|
|
}
|
|
|
|
BinaryOp getOpcode() const { return Opc; }
|
|
Init *getLHS() const { return LHS; }
|
|
Init *getRHS() const { return RHS; }
|
|
|
|
// Fold - If possible, fold this to a simpler init. Return this if not
|
|
// possible to fold.
|
|
Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const;
|
|
|
|
virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
|
|
|
|
virtual std::string getAsString() const;
|
|
};
|
|
|
|
/// TernOpInit - !op (X, Y, Z) - Combine two inits.
|
|
///
|
|
class TernOpInit : public OpInit {
|
|
public:
|
|
enum TernaryOp { SUBST, FOREACH, IF };
|
|
private:
|
|
TernaryOp Opc;
|
|
Init *LHS, *MHS, *RHS;
|
|
|
|
TernOpInit(TernaryOp opc, Init *lhs, Init *mhs, Init *rhs,
|
|
RecTy *Type) :
|
|
OpInit(Type), Opc(opc), LHS(lhs), MHS(mhs), RHS(rhs) {}
|
|
|
|
TernOpInit(const TernOpInit &Other); // Do not define.
|
|
TernOpInit &operator=(const TernOpInit &Other); // Do not define.
|
|
|
|
public:
|
|
static TernOpInit *get(TernaryOp opc, Init *lhs,
|
|
Init *mhs, Init *rhs,
|
|
RecTy *Type);
|
|
|
|
// Clone - Clone this operator, replacing arguments with the new list
|
|
virtual OpInit *clone(std::vector<Init *> &Operands) const {
|
|
assert(Operands.size() == 3 &&
|
|
"Wrong number of operands for ternary operation");
|
|
return TernOpInit::get(getOpcode(), Operands[0], Operands[1], Operands[2],
|
|
getType());
|
|
}
|
|
|
|
int getNumOperands() const { return 3; }
|
|
Init *getOperand(int i) const {
|
|
assert((i == 0 || i == 1 || i == 2) &&
|
|
"Invalid operand id for ternary operator");
|
|
if (i == 0) {
|
|
return getLHS();
|
|
} else if (i == 1) {
|
|
return getMHS();
|
|
} else {
|
|
return getRHS();
|
|
}
|
|
}
|
|
|
|
TernaryOp getOpcode() const { return Opc; }
|
|
Init *getLHS() const { return LHS; }
|
|
Init *getMHS() const { return MHS; }
|
|
Init *getRHS() const { return RHS; }
|
|
|
|
// Fold - If possible, fold this to a simpler init. Return this if not
|
|
// possible to fold.
|
|
Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const;
|
|
|
|
virtual bool isComplete() const { return false; }
|
|
|
|
virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
|
|
|
|
virtual std::string getAsString() const;
|
|
};
|
|
|
|
|
|
/// VarInit - 'Opcode' - Represent a reference to an entire variable object.
|
|
///
|
|
class VarInit : public TypedInit {
|
|
Init *VarName;
|
|
|
|
explicit VarInit(const std::string &VN, RecTy *T)
|
|
: TypedInit(T), VarName(StringInit::get(VN)) {}
|
|
explicit VarInit(Init *VN, RecTy *T)
|
|
: TypedInit(T), VarName(VN) {}
|
|
|
|
VarInit(const VarInit &Other); // Do not define.
|
|
VarInit &operator=(const VarInit &Other); // Do not define.
|
|
|
|
public:
|
|
static VarInit *get(const std::string &VN, RecTy *T);
|
|
static VarInit *get(Init *VN, RecTy *T);
|
|
|
|
virtual Init *convertInitializerTo(RecTy *Ty) const {
|
|
return Ty->convertValue(const_cast<VarInit *>(this));
|
|
}
|
|
|
|
const std::string &getName() const;
|
|
Init *getNameInit() const { return VarName; }
|
|
std::string getNameInitAsString() const {
|
|
return getNameInit()->getAsUnquotedString();
|
|
}
|
|
|
|
virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
|
|
unsigned Bit) const;
|
|
virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
|
unsigned Elt) const;
|
|
|
|
virtual RecTy *getFieldType(const std::string &FieldName) const;
|
|
virtual Init *getFieldInit(Record &R, const RecordVal *RV,
|
|
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, const RecordVal *RV) const;
|
|
|
|
virtual std::string getAsString() const { return getName(); }
|
|
};
|
|
|
|
|
|
/// VarBitInit - Opcode{0} - Represent access to one bit of a variable or field.
|
|
///
|
|
class VarBitInit : public Init {
|
|
TypedInit *TI;
|
|
unsigned Bit;
|
|
|
|
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!");
|
|
}
|
|
|
|
VarBitInit(const VarBitInit &Other); // Do not define.
|
|
VarBitInit &operator=(const VarBitInit &Other); // Do not define.
|
|
|
|
public:
|
|
static VarBitInit *get(TypedInit *T, unsigned B);
|
|
|
|
virtual Init *convertInitializerTo(RecTy *Ty) const {
|
|
return Ty->convertValue(const_cast<VarBitInit *>(this));
|
|
}
|
|
|
|
TypedInit *getVariable() const { return TI; }
|
|
unsigned getBitNum() const { return Bit; }
|
|
|
|
virtual std::string getAsString() const;
|
|
virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
|
|
};
|
|
|
|
/// VarListElementInit - List[4] - Represent access to one element of a var or
|
|
/// field.
|
|
class VarListElementInit : public TypedInit {
|
|
TypedInit *TI;
|
|
unsigned Element;
|
|
|
|
VarListElementInit(TypedInit *T, unsigned E)
|
|
: TypedInit(dynamic_cast<ListRecTy*>(T->getType())->getElementType()),
|
|
TI(T), Element(E) {
|
|
assert(T->getType() && dynamic_cast<ListRecTy*>(T->getType()) &&
|
|
"Illegal VarBitInit expression!");
|
|
}
|
|
|
|
VarListElementInit(const VarListElementInit &Other); // Do not define.
|
|
VarListElementInit &operator=(const VarListElementInit &Other); // Do
|
|
// not
|
|
// define.
|
|
|
|
public:
|
|
static VarListElementInit *get(TypedInit *T, unsigned E);
|
|
|
|
virtual Init *convertInitializerTo(RecTy *Ty) const {
|
|
return Ty->convertValue(const_cast<VarListElementInit *>(this));
|
|
}
|
|
|
|
TypedInit *getVariable() const { return TI; }
|
|
unsigned getElementNum() const { return Element; }
|
|
|
|
virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
|
|
unsigned Bit) const;
|
|
|
|
/// resolveListElementReference - This method is used to implement
|
|
/// VarListElementInit::resolveReferences. If the list element is resolvable
|
|
/// now, we return the resolved value, otherwise we return null.
|
|
virtual Init *resolveListElementReference(Record &R,
|
|
const RecordVal *RV,
|
|
unsigned Elt) const;
|
|
|
|
virtual std::string getAsString() const;
|
|
virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
|
|
};
|
|
|
|
/// DefInit - AL - Represent a reference to a 'def' in the description
|
|
///
|
|
class DefInit : public TypedInit {
|
|
Record *Def;
|
|
|
|
DefInit(Record *D, RecordRecTy *T) : TypedInit(T), Def(D) {}
|
|
friend class Record;
|
|
|
|
DefInit(const DefInit &Other); // Do not define.
|
|
DefInit &operator=(const DefInit &Other); // Do not define.
|
|
|
|
public:
|
|
static DefInit *get(Record*);
|
|
|
|
virtual Init *convertInitializerTo(RecTy *Ty) const {
|
|
return Ty->convertValue(const_cast<DefInit *>(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 RecordVal *RV,
|
|
const std::string &FieldName) const;
|
|
|
|
virtual std::string getAsString() const;
|
|
|
|
/// 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 null.
|
|
///
|
|
virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
|
|
unsigned Bit) const {
|
|
llvm_unreachable("Illegal bit reference off def");
|
|
}
|
|
|
|
/// resolveListElementReference - This method is used to implement
|
|
/// VarListElementInit::resolveReferences. If the list element is resolvable
|
|
/// now, we return the resolved value, otherwise we return null.
|
|
virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
|
unsigned Elt) const {
|
|
llvm_unreachable("Illegal element reference off def");
|
|
}
|
|
};
|
|
|
|
|
|
/// 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
|
|
|
|
FieldInit(Init *R, const std::string &FN)
|
|
: TypedInit(R->getFieldType(FN)), Rec(R), FieldName(FN) {
|
|
assert(getType() && "FieldInit with non-record type!");
|
|
}
|
|
|
|
FieldInit(const FieldInit &Other); // Do not define.
|
|
FieldInit &operator=(const FieldInit &Other); // Do not define.
|
|
|
|
public:
|
|
static FieldInit *get(Init *R, const std::string &FN);
|
|
static FieldInit *get(Init *R, const Init *FN);
|
|
|
|
virtual Init *convertInitializerTo(RecTy *Ty) const {
|
|
return Ty->convertValue(const_cast<FieldInit *>(this));
|
|
}
|
|
|
|
virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
|
|
unsigned Bit) const;
|
|
virtual Init *resolveListElementReference(Record &R,
|
|
const RecordVal *RV,
|
|
unsigned Elt) const;
|
|
|
|
virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
|
|
|
|
virtual std::string getAsString() const {
|
|
return Rec->getAsString() + "." + FieldName;
|
|
}
|
|
};
|
|
|
|
/// DagInit - (v a, b) - Represent a DAG tree value. DAG inits are required
|
|
/// to have at least one value then a (possibly empty) list of arguments. Each
|
|
/// argument can have a name associated with it.
|
|
///
|
|
class DagInit : public TypedInit, public FoldingSetNode {
|
|
Init *Val;
|
|
std::string ValName;
|
|
std::vector<Init*> Args;
|
|
std::vector<std::string> ArgNames;
|
|
|
|
DagInit(Init *V, const std::string &VN,
|
|
ArrayRef<Init *> ArgRange,
|
|
ArrayRef<std::string> NameRange)
|
|
: TypedInit(DagRecTy::get()), Val(V), ValName(VN),
|
|
Args(ArgRange.begin(), ArgRange.end()),
|
|
ArgNames(NameRange.begin(), NameRange.end()) {}
|
|
|
|
DagInit(const DagInit &Other); // Do not define.
|
|
DagInit &operator=(const DagInit &Other); // Do not define.
|
|
|
|
public:
|
|
static DagInit *get(Init *V, const std::string &VN,
|
|
ArrayRef<Init *> ArgRange,
|
|
ArrayRef<std::string> NameRange);
|
|
static DagInit *get(Init *V, const std::string &VN,
|
|
const std::vector<
|
|
std::pair<Init*, std::string> > &args);
|
|
|
|
void Profile(FoldingSetNodeID &ID) const;
|
|
|
|
virtual Init *convertInitializerTo(RecTy *Ty) const {
|
|
return Ty->convertValue(const_cast<DagInit *>(this));
|
|
}
|
|
|
|
Init *getOperator() const { return Val; }
|
|
|
|
const std::string &getName() const { return ValName; }
|
|
|
|
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];
|
|
}
|
|
|
|
virtual Init *resolveReferences(Record &R, const RecordVal *RV) const;
|
|
|
|
virtual std::string getAsString() const;
|
|
|
|
typedef std::vector<Init*>::const_iterator const_arg_iterator;
|
|
typedef std::vector<std::string>::const_iterator const_name_iterator;
|
|
|
|
inline const_arg_iterator arg_begin() const { return Args.begin(); }
|
|
inline const_arg_iterator arg_end () const { return Args.end(); }
|
|
|
|
inline size_t arg_size () const { return Args.size(); }
|
|
inline bool arg_empty() const { return Args.empty(); }
|
|
|
|
inline const_name_iterator name_begin() const { return ArgNames.begin(); }
|
|
inline const_name_iterator name_end () const { return ArgNames.end(); }
|
|
|
|
inline size_t name_size () const { return ArgNames.size(); }
|
|
inline bool name_empty() const { return ArgNames.empty(); }
|
|
|
|
virtual Init *resolveBitReference(Record &R, const RecordVal *RV,
|
|
unsigned Bit) const {
|
|
llvm_unreachable("Illegal bit reference off dag");
|
|
}
|
|
|
|
virtual Init *resolveListElementReference(Record &R, const RecordVal *RV,
|
|
unsigned Elt) const {
|
|
llvm_unreachable("Illegal element reference off dag");
|
|
}
|
|
};
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// High-Level Classes
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
class RecordVal {
|
|
Init *Name;
|
|
RecTy *Ty;
|
|
unsigned Prefix;
|
|
Init *Value;
|
|
public:
|
|
RecordVal(Init *N, RecTy *T, unsigned P);
|
|
RecordVal(const std::string &N, RecTy *T, unsigned P);
|
|
|
|
const std::string &getName() const;
|
|
const Init *getNameInit() const { return Name; }
|
|
std::string getNameInitAsString() const {
|
|
return getNameInit()->getAsUnquotedString();
|
|
}
|
|
|
|
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(raw_ostream &OS, bool PrintSem = true) const;
|
|
};
|
|
|
|
inline raw_ostream &operator<<(raw_ostream &OS, const RecordVal &RV) {
|
|
RV.print(OS << " ");
|
|
return OS;
|
|
}
|
|
|
|
class Record {
|
|
static unsigned LastID;
|
|
|
|
// Unique record ID.
|
|
unsigned ID;
|
|
Init *Name;
|
|
SMLoc Loc;
|
|
std::vector<Init *> TemplateArgs;
|
|
std::vector<RecordVal> Values;
|
|
std::vector<Record*> SuperClasses;
|
|
|
|
// Tracks Record instances. Not owned by Record.
|
|
RecordKeeper &TrackedRecords;
|
|
|
|
DefInit *TheInit;
|
|
|
|
void init();
|
|
void checkName();
|
|
|
|
public:
|
|
|
|
// Constructs a record.
|
|
explicit Record(const std::string &N, SMLoc loc, RecordKeeper &records) :
|
|
ID(LastID++), Name(StringInit::get(N)), Loc(loc), TrackedRecords(records),
|
|
TheInit(0) {
|
|
init();
|
|
}
|
|
explicit Record(Init *N, SMLoc loc, RecordKeeper &records) :
|
|
ID(LastID++), Name(N), Loc(loc), TrackedRecords(records), TheInit(0) {
|
|
init();
|
|
}
|
|
~Record() {}
|
|
|
|
|
|
static unsigned getNewUID() { return LastID++; }
|
|
|
|
|
|
unsigned getID() const { return ID; }
|
|
|
|
const std::string &getName() const;
|
|
Init *getNameInit() const {
|
|
return Name;
|
|
}
|
|
const std::string getNameInitAsString() const {
|
|
return getNameInit()->getAsUnquotedString();
|
|
}
|
|
|
|
void setName(Init *Name); // Also updates RecordKeeper.
|
|
void setName(const std::string &Name); // Also updates RecordKeeper.
|
|
|
|
SMLoc getLoc() const { return Loc; }
|
|
|
|
/// get the corresponding DefInit.
|
|
DefInit *getDefInit();
|
|
|
|
const std::vector<Init *> &getTemplateArgs() const {
|
|
return TemplateArgs;
|
|
}
|
|
const std::vector<RecordVal> &getValues() const { return Values; }
|
|
const std::vector<Record*> &getSuperClasses() const { return SuperClasses; }
|
|
|
|
bool isTemplateArg(Init *Name) const {
|
|
for (unsigned i = 0, e = TemplateArgs.size(); i != e; ++i)
|
|
if (TemplateArgs[i] == Name) return true;
|
|
return false;
|
|
}
|
|
bool isTemplateArg(StringRef Name) const {
|
|
return isTemplateArg(StringInit::get(Name.str()));
|
|
}
|
|
|
|
const RecordVal *getValue(const Init *Name) const {
|
|
for (unsigned i = 0, e = Values.size(); i != e; ++i)
|
|
if (Values[i].getNameInit() == Name) return &Values[i];
|
|
return 0;
|
|
}
|
|
const RecordVal *getValue(StringRef Name) const {
|
|
return getValue(StringInit::get(Name));
|
|
}
|
|
RecordVal *getValue(const Init *Name) {
|
|
for (unsigned i = 0, e = Values.size(); i != e; ++i)
|
|
if (Values[i].getNameInit() == Name) return &Values[i];
|
|
return 0;
|
|
}
|
|
RecordVal *getValue(StringRef Name) {
|
|
return getValue(StringInit::get(Name));
|
|
}
|
|
|
|
void addTemplateArg(Init *Name) {
|
|
assert(!isTemplateArg(Name) && "Template arg already defined!");
|
|
TemplateArgs.push_back(Name);
|
|
}
|
|
void addTemplateArg(StringRef Name) {
|
|
addTemplateArg(StringInit::get(Name.str()));
|
|
}
|
|
|
|
void addValue(const RecordVal &RV) {
|
|
assert(getValue(RV.getNameInit()) == 0 && "Value already added!");
|
|
Values.push_back(RV);
|
|
if (Values.size() > 1)
|
|
// Keep NAME at the end of the list. It makes record dumps a
|
|
// bit prettier and allows TableGen tests to be written more
|
|
// naturally. Tests can use CHECK-NEXT to look for Record
|
|
// fields they expect to see after a def. They can't do that if
|
|
// NAME is the first Record field.
|
|
std::swap(Values[Values.size() - 2], Values[Values.size() - 1]);
|
|
}
|
|
|
|
void removeValue(Init *Name) {
|
|
for (unsigned i = 0, e = Values.size(); i != e; ++i)
|
|
if (Values[i].getNameInit() == Name) {
|
|
Values.erase(Values.begin()+i);
|
|
return;
|
|
}
|
|
llvm_unreachable("Cannot remove an entry that does not exist!");
|
|
}
|
|
|
|
void removeValue(StringRef Name) {
|
|
removeValue(StringInit::get(Name.str()));
|
|
}
|
|
|
|
bool isSubClassOf(const Record *R) const {
|
|
for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
|
|
if (SuperClasses[i] == R)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
bool isSubClassOf(StringRef Name) const {
|
|
for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
|
|
if (SuperClasses[i]->getNameInitAsString() == 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() { resolveReferencesTo(0); }
|
|
|
|
/// resolveReferencesTo - If anything in this record refers to RV, replace the
|
|
/// reference to RV with the RHS of RV. If RV is null, we resolve all
|
|
/// possible references.
|
|
void resolveReferencesTo(const RecordVal *RV);
|
|
|
|
RecordKeeper &getRecords() const {
|
|
return TrackedRecords;
|
|
}
|
|
|
|
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(StringRef 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(StringRef 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(StringRef 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(StringRef FieldName) const;
|
|
|
|
/// getValueAsListOfDefs - This method looks up the specified field and
|
|
/// returns its value as a vector of records, throwing an exception if the
|
|
/// field does not exist or if the value is not the right type.
|
|
///
|
|
std::vector<Record*> getValueAsListOfDefs(StringRef FieldName) const;
|
|
|
|
/// getValueAsListOfInts - This method looks up the specified field and
|
|
/// returns its value as a vector of integers, throwing an exception if the
|
|
/// field does not exist or if the value is not the right type.
|
|
///
|
|
std::vector<int64_t> getValueAsListOfInts(StringRef FieldName) const;
|
|
|
|
/// getValueAsListOfStrings - This method looks up the specified field and
|
|
/// returns its value as a vector of strings, throwing an exception if the
|
|
/// field does not exist or if the value is not the right type.
|
|
///
|
|
std::vector<std::string> getValueAsListOfStrings(StringRef 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(StringRef 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(StringRef FieldName) const;
|
|
|
|
/// getValueAsInt - This method looks up the specified field and returns its
|
|
/// value as an int64_t, throwing an exception if the field does not exist or
|
|
/// if the value is not the right type.
|
|
///
|
|
int64_t getValueAsInt(StringRef 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(StringRef FieldName) const;
|
|
};
|
|
|
|
raw_ostream &operator<<(raw_ostream &OS, const Record &R);
|
|
|
|
struct MultiClass {
|
|
Record Rec; // Placeholder for template args and Name.
|
|
typedef std::vector<Record*> RecordVector;
|
|
RecordVector DefPrototypes;
|
|
|
|
void dump() const;
|
|
|
|
MultiClass(const std::string &Name, SMLoc Loc, RecordKeeper &Records) :
|
|
Rec(Name, Loc, Records) {}
|
|
};
|
|
|
|
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->getNameInitAsString()) == 0 && "Class already exists!");
|
|
Classes.insert(std::make_pair(R->getNameInitAsString(), R));
|
|
}
|
|
void addDef(Record *R) {
|
|
assert(getDef(R->getNameInitAsString()) == 0 && "Def already exists!");
|
|
Defs.insert(std::make_pair(R->getNameInitAsString(), R));
|
|
}
|
|
|
|
/// removeClass - Remove, but do not delete, the specified record.
|
|
///
|
|
void removeClass(const std::string &Name) {
|
|
assert(Classes.count(Name) && "Class does not exist!");
|
|
Classes.erase(Name);
|
|
}
|
|
/// removeDef - Remove, but do not delete, the specified record.
|
|
///
|
|
void removeDef(const std::string &Name) {
|
|
assert(Defs.count(Name) && "Def does not exist!");
|
|
Defs.erase(Name);
|
|
}
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// 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;
|
|
};
|
|
|
|
/// LessRecord - Sorting predicate to sort record pointers by name.
|
|
///
|
|
struct LessRecord {
|
|
bool operator()(const Record *Rec1, const Record *Rec2) const {
|
|
return StringRef(Rec1->getName()).compare_numeric(Rec2->getName()) < 0;
|
|
}
|
|
};
|
|
|
|
/// LessRecordFieldName - Sorting predicate to sort record pointers by their
|
|
/// name field.
|
|
///
|
|
struct LessRecordFieldName {
|
|
bool operator()(const Record *Rec1, const Record *Rec2) const {
|
|
return Rec1->getValueAsString("Name") < Rec2->getValueAsString("Name");
|
|
}
|
|
};
|
|
|
|
raw_ostream &operator<<(raw_ostream &OS, const RecordKeeper &RK);
|
|
|
|
/// QualifyName - Return an Init with a qualifier prefix referring
|
|
/// to CurRec's name.
|
|
Init *QualifyName(Record &CurRec, MultiClass *CurMultiClass,
|
|
Init *Name, const std::string &Scoper);
|
|
|
|
/// QualifyName - Return an Init with a qualifier prefix referring
|
|
/// to CurRec's name.
|
|
Init *QualifyName(Record &CurRec, MultiClass *CurMultiClass,
|
|
const std::string &Name, const std::string &Scoper);
|
|
|
|
} // End llvm namespace
|
|
|
|
#endif
|