2002-12-02 01:23:04 +00:00
|
|
|
//===- Record.cpp - Record implementation ---------------------------------===//
|
2005-04-22 00:00:37 +00:00
|
|
|
//
|
2003-10-20 20:20:30 +00:00
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-29 20:37:13 +00:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2005-04-22 00:00:37 +00:00
|
|
|
//
|
2003-10-20 20:20:30 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
2002-12-02 01:23:04 +00:00
|
|
|
//
|
2006-03-31 21:53:49 +00:00
|
|
|
// Implement the tablegen record classes.
|
2002-12-02 01:23:04 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-10-01 16:41:13 +00:00
|
|
|
#include "llvm/TableGen/Record.h"
|
2011-07-29 19:07:11 +00:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
|
|
#include "llvm/ADT/FoldingSet.h"
|
2012-03-05 10:36:16 +00:00
|
|
|
#include "llvm/ADT/Hashing.h"
|
2011-07-29 19:07:00 +00:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2012-12-03 16:50:05 +00:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2007-11-20 22:25:16 +00:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2011-07-29 19:07:14 +00:00
|
|
|
#include "llvm/ADT/StringMap.h"
|
2012-12-03 16:50:05 +00:00
|
|
|
#include "llvm/Support/DataTypes.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
#include "llvm/Support/Format.h"
|
|
|
|
#include "llvm/TableGen/Error.h"
|
2005-12-26 05:08:55 +00:00
|
|
|
|
2004-08-01 03:55:39 +00:00
|
|
|
using namespace llvm;
|
2002-12-02 01:23:04 +00:00
|
|
|
|
2011-07-29 19:06:58 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// std::string wrapper for DenseMap purposes
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2012-03-05 10:36:16 +00:00
|
|
|
namespace llvm {
|
|
|
|
|
2011-07-29 19:06:58 +00:00
|
|
|
/// TableGenStringKey - This is a wrapper for std::string suitable for
|
|
|
|
/// using as a key to a DenseMap. Because there isn't a particularly
|
|
|
|
/// good way to indicate tombstone or empty keys for strings, we want
|
|
|
|
/// to wrap std::string to indicate that this is a "special" string
|
|
|
|
/// not expected to take on certain values (those of the tombstone and
|
|
|
|
/// empty keys). This makes things a little safer as it clarifies
|
|
|
|
/// that DenseMap is really not appropriate for general strings.
|
|
|
|
|
|
|
|
class TableGenStringKey {
|
|
|
|
public:
|
|
|
|
TableGenStringKey(const std::string &str) : data(str) {}
|
|
|
|
TableGenStringKey(const char *str) : data(str) {}
|
|
|
|
|
|
|
|
const std::string &str() const { return data; }
|
2012-03-05 10:36:16 +00:00
|
|
|
|
|
|
|
friend hash_code hash_value(const TableGenStringKey &Value) {
|
|
|
|
using llvm::hash_value;
|
|
|
|
return hash_value(Value.str());
|
|
|
|
}
|
2011-07-29 19:06:58 +00:00
|
|
|
private:
|
|
|
|
std::string data;
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Specialize DenseMapInfo for TableGenStringKey.
|
|
|
|
template<> struct DenseMapInfo<TableGenStringKey> {
|
|
|
|
static inline TableGenStringKey getEmptyKey() {
|
|
|
|
TableGenStringKey Empty("<<<EMPTY KEY>>>");
|
|
|
|
return Empty;
|
|
|
|
}
|
|
|
|
static inline TableGenStringKey getTombstoneKey() {
|
|
|
|
TableGenStringKey Tombstone("<<<TOMBSTONE KEY>>>");
|
|
|
|
return Tombstone;
|
|
|
|
}
|
|
|
|
static unsigned getHashValue(const TableGenStringKey& Val) {
|
2012-03-05 10:36:16 +00:00
|
|
|
using llvm::hash_value;
|
|
|
|
return hash_value(Val);
|
2011-07-29 19:06:58 +00:00
|
|
|
}
|
|
|
|
static bool isEqual(const TableGenStringKey& LHS,
|
|
|
|
const TableGenStringKey& RHS) {
|
|
|
|
return LHS.str() == RHS.str();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-03-05 10:36:16 +00:00
|
|
|
} // namespace llvm
|
2011-07-29 19:06:58 +00:00
|
|
|
|
2002-12-02 01:23:04 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Type implementations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-07-18 17:02:57 +00:00
|
|
|
BitRecTy BitRecTy::Shared;
|
|
|
|
IntRecTy IntRecTy::Shared;
|
|
|
|
StringRecTy StringRecTy::Shared;
|
|
|
|
DagRecTy DagRecTy::Shared;
|
|
|
|
|
2011-12-20 02:50:00 +00:00
|
|
|
void RecTy::anchor() { }
|
2009-07-03 00:10:29 +00:00
|
|
|
void RecTy::dump() const { print(errs()); }
|
2002-12-02 01:23:04 +00:00
|
|
|
|
2011-07-18 17:02:57 +00:00
|
|
|
ListRecTy *RecTy::getListTy() {
|
|
|
|
if (!ListTy)
|
|
|
|
ListTy = new ListRecTy(this);
|
|
|
|
return ListTy;
|
|
|
|
}
|
|
|
|
|
2013-01-07 02:30:19 +00:00
|
|
|
bool RecTy::baseClassOf(const RecTy *RHS) const{
|
|
|
|
assert (RHS && "NULL pointer");
|
|
|
|
return Kind == RHS->getRecTyKind();
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *BitRecTy::convertValue(BitsInit *BI) {
|
2002-12-02 01:23:04 +00:00
|
|
|
if (BI->getNumBits() != 1) return 0; // Only accept if just one bit!
|
|
|
|
return BI->getBit(0);
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *BitRecTy::convertValue(IntInit *II) {
|
2008-10-17 01:33:43 +00:00
|
|
|
int64_t Val = II->getValue();
|
2002-12-02 01:23:04 +00:00
|
|
|
if (Val != 0 && Val != 1) return 0; // Only accept 0 or 1 for a bit!
|
2005-04-22 00:00:37 +00:00
|
|
|
|
2011-07-29 19:07:07 +00:00
|
|
|
return BitInit::get(Val != 0);
|
2002-12-02 01:23:04 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *BitRecTy::convertValue(TypedInit *VI) {
|
Re-work bit/bits value resolving in tblgen
- This patch is inspired by the failure of the following code snippet
which is used to convert enumerable values into encoding bits to
improve the readability of td files.
class S<int s> {
bits<2> V = !if(!eq(s, 8), {0, 0},
!if(!eq(s, 16), {0, 1},
!if(!eq(s, 32), {1, 0},
!if(!eq(s, 64), {1, 1}, {?, ?}))));
}
Later, PR8330 is found to report not exactly the same bug relevant
issue to bit/bits values.
- Instead of resolving bit/bits values separately through
resolveBitReference(), this patch adds getBit() for all Inits and
resolves bit value by resolving plus getting the specified bit. This
unifies the resolving of bit with other values and removes redundant
logic for resolving bit only. In addition,
BitsInit::resolveReferences() is optimized to take advantage of this
origanization by resolving VarBitInit's variable reference first and
then getting bits from it.
- The type interference in '!if' operator is revised to support possible
combinations of int and bits/bit in MHS and RHS.
- As there may be illegal assignments from integer value to bit, says
assign 2 to a bit, but we only check this during instantiation in some
cases, e.g.
bit V = !if(!eq(x, 17), 0, 2);
Verbose diagnostic message is generated when invalid value is
resolveed to help locating the error.
- PR8330 is fixed as well.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8
2012-09-06 23:32:48 +00:00
|
|
|
RecTy *Ty = VI->getType();
|
2012-10-05 03:32:00 +00:00
|
|
|
if (isa<BitRecTy>(Ty) || isa<BitsRecTy>(Ty) || isa<IntRecTy>(Ty))
|
2002-12-02 01:23:04 +00:00
|
|
|
return VI; // Accept variable if it is already of bit type!
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-01-07 02:30:19 +00:00
|
|
|
bool BitRecTy::baseClassOf(const RecTy *RHS) const{
|
|
|
|
if(RecTy::baseClassOf(RHS) || getRecTyKind() == IntRecTyKind)
|
|
|
|
return true;
|
|
|
|
if(const BitsRecTy *BitsTy = dyn_cast<BitsRecTy>(RHS))
|
|
|
|
return BitsTy->getNumBits() == 1;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-07-18 17:02:57 +00:00
|
|
|
BitsRecTy *BitsRecTy::get(unsigned Sz) {
|
|
|
|
static std::vector<BitsRecTy*> Shared;
|
|
|
|
if (Sz >= Shared.size())
|
|
|
|
Shared.resize(Sz + 1);
|
|
|
|
BitsRecTy *&Ty = Shared[Sz];
|
|
|
|
if (!Ty)
|
|
|
|
Ty = new BitsRecTy(Sz);
|
|
|
|
return Ty;
|
|
|
|
}
|
|
|
|
|
2007-11-20 22:25:16 +00:00
|
|
|
std::string BitsRecTy::getAsString() const {
|
|
|
|
return "bits<" + utostr(Size) + ">";
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *BitsRecTy::convertValue(UnsetInit *UI) {
|
|
|
|
SmallVector<Init *, 16> NewBits(Size);
|
2002-12-02 01:23:04 +00:00
|
|
|
|
|
|
|
for (unsigned i = 0; i != Size; ++i)
|
2011-07-29 19:07:07 +00:00
|
|
|
NewBits[i] = UnsetInit::get();
|
2011-07-29 19:07:00 +00:00
|
|
|
|
2011-07-29 19:07:07 +00:00
|
|
|
return BitsInit::get(NewBits);
|
2002-12-02 01:23:04 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *BitsRecTy::convertValue(BitInit *UI) {
|
2010-12-10 22:54:30 +00:00
|
|
|
if (Size != 1) return 0; // Can only convert single bit.
|
2011-07-29 19:07:07 +00:00
|
|
|
return BitsInit::get(UI);
|
2002-12-02 01:23:04 +00:00
|
|
|
}
|
|
|
|
|
2010-12-13 01:46:19 +00:00
|
|
|
/// canFitInBitfield - Return true if the number of bits is large enough to hold
|
|
|
|
/// the integer value.
|
|
|
|
static bool canFitInBitfield(int64_t Value, unsigned NumBits) {
|
2011-06-03 08:25:39 +00:00
|
|
|
// For example, with NumBits == 4, we permit Values from [-7 .. 15].
|
|
|
|
return (NumBits >= sizeof(Value) * 8) ||
|
|
|
|
(Value >> NumBits == 0) || (Value >> (NumBits-1) == -1);
|
2010-12-13 01:46:19 +00:00
|
|
|
}
|
|
|
|
|
2011-07-11 23:06:52 +00:00
|
|
|
/// convertValue from Int initializer to bits type: Split the integer up into the
|
|
|
|
/// appropriate bits.
|
2010-12-13 01:46:19 +00:00
|
|
|
///
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *BitsRecTy::convertValue(IntInit *II) {
|
2004-06-21 18:01:47 +00:00
|
|
|
int64_t Value = II->getValue();
|
2010-12-10 22:54:30 +00:00
|
|
|
// Make sure this bitfield is large enough to hold the integer value.
|
2010-12-13 01:46:19 +00:00
|
|
|
if (!canFitInBitfield(Value, Size))
|
|
|
|
return 0;
|
2002-12-02 01:23:04 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
SmallVector<Init *, 16> NewBits(Size);
|
2011-07-29 19:07:00 +00:00
|
|
|
|
2002-12-02 01:23:04 +00:00
|
|
|
for (unsigned i = 0; i != Size; ++i)
|
2011-07-29 19:07:07 +00:00
|
|
|
NewBits[i] = BitInit::get(Value & (1LL << i));
|
2003-08-03 18:24:34 +00:00
|
|
|
|
2011-07-29 19:07:07 +00:00
|
|
|
return BitsInit::get(NewBits);
|
2002-12-02 01:23:04 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *BitsRecTy::convertValue(BitsInit *BI) {
|
2002-12-02 01:23:04 +00:00
|
|
|
// If the number of bits is right, return it. Otherwise we need to expand or
|
2010-12-10 22:54:30 +00:00
|
|
|
// truncate.
|
2002-12-02 01:23:04 +00:00
|
|
|
if (BI->getNumBits() == Size) return BI;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *BitsRecTy::convertValue(TypedInit *VI) {
|
2012-10-05 03:32:00 +00:00
|
|
|
if (Size == 1 && isa<BitRecTy>(VI->getType()))
|
2011-07-29 19:07:07 +00:00
|
|
|
return BitsInit::get(VI);
|
2005-04-22 00:00:37 +00:00
|
|
|
|
Re-work bit/bits value resolving in tblgen
- This patch is inspired by the failure of the following code snippet
which is used to convert enumerable values into encoding bits to
improve the readability of td files.
class S<int s> {
bits<2> V = !if(!eq(s, 8), {0, 0},
!if(!eq(s, 16), {0, 1},
!if(!eq(s, 32), {1, 0},
!if(!eq(s, 64), {1, 1}, {?, ?}))));
}
Later, PR8330 is found to report not exactly the same bug relevant
issue to bit/bits values.
- Instead of resolving bit/bits values separately through
resolveBitReference(), this patch adds getBit() for all Inits and
resolves bit value by resolving plus getting the specified bit. This
unifies the resolving of bit with other values and removes redundant
logic for resolving bit only. In addition,
BitsInit::resolveReferences() is optimized to take advantage of this
origanization by resolving VarBitInit's variable reference first and
then getting bits from it.
- The type interference in '!if' operator is revised to support possible
combinations of int and bits/bit in MHS and RHS.
- As there may be illegal assignments from integer value to bit, says
assign 2 to a bit, but we only check this during instantiation in some
cases, e.g.
bit V = !if(!eq(x, 17), 0, 2);
Verbose diagnostic message is generated when invalid value is
resolveed to help locating the error.
- PR8330 is fixed as well.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8
2012-09-06 23:32:48 +00:00
|
|
|
if (VI->getType()->typeIsConvertibleTo(this)) {
|
|
|
|
SmallVector<Init *, 16> NewBits(Size);
|
2011-07-11 23:06:52 +00:00
|
|
|
|
Re-work bit/bits value resolving in tblgen
- This patch is inspired by the failure of the following code snippet
which is used to convert enumerable values into encoding bits to
improve the readability of td files.
class S<int s> {
bits<2> V = !if(!eq(s, 8), {0, 0},
!if(!eq(s, 16), {0, 1},
!if(!eq(s, 32), {1, 0},
!if(!eq(s, 64), {1, 1}, {?, ?}))));
}
Later, PR8330 is found to report not exactly the same bug relevant
issue to bit/bits values.
- Instead of resolving bit/bits values separately through
resolveBitReference(), this patch adds getBit() for all Inits and
resolves bit value by resolving plus getting the specified bit. This
unifies the resolving of bit with other values and removes redundant
logic for resolving bit only. In addition,
BitsInit::resolveReferences() is optimized to take advantage of this
origanization by resolving VarBitInit's variable reference first and
then getting bits from it.
- The type interference in '!if' operator is revised to support possible
combinations of int and bits/bit in MHS and RHS.
- As there may be illegal assignments from integer value to bit, says
assign 2 to a bit, but we only check this during instantiation in some
cases, e.g.
bit V = !if(!eq(x, 17), 0, 2);
Verbose diagnostic message is generated when invalid value is
resolveed to help locating the error.
- PR8330 is fixed as well.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8
2012-09-06 23:32:48 +00:00
|
|
|
for (unsigned i = 0; i != Size; ++i)
|
|
|
|
NewBits[i] = VarBitInit::get(VI, i);
|
|
|
|
return BitsInit::get(NewBits);
|
2010-12-13 01:46:19 +00:00
|
|
|
}
|
|
|
|
|
2002-12-02 01:23:04 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-01-07 02:30:19 +00:00
|
|
|
bool BitsRecTy::baseClassOf(const RecTy *RHS) const{
|
|
|
|
if (RecTy::baseClassOf(RHS)) //argument and the receiver are the same type
|
|
|
|
return cast<BitsRecTy>(RHS)->Size == Size;
|
|
|
|
RecTyKind kind = RHS->getRecTyKind();
|
|
|
|
return (kind == BitRecTyKind && Size == 1) || (kind == IntRecTyKind);
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *IntRecTy::convertValue(BitInit *BI) {
|
2011-07-29 19:07:07 +00:00
|
|
|
return IntInit::get(BI->getValue());
|
2003-08-03 18:29:51 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *IntRecTy::convertValue(BitsInit *BI) {
|
2008-10-17 01:33:43 +00:00
|
|
|
int64_t Result = 0;
|
2005-04-22 00:00:37 +00:00
|
|
|
for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i)
|
2012-10-10 20:24:43 +00:00
|
|
|
if (BitInit *Bit = dyn_cast<BitInit>(BI->getBit(i))) {
|
2002-12-02 01:23:04 +00:00
|
|
|
Result |= Bit->getValue() << i;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
2011-07-29 19:07:07 +00:00
|
|
|
return IntInit::get(Result);
|
2002-12-02 01:23:04 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *IntRecTy::convertValue(TypedInit *TI) {
|
2003-08-03 18:29:51 +00:00
|
|
|
if (TI->getType()->typeIsConvertibleTo(this))
|
2002-12-02 17:53:54 +00:00
|
|
|
return TI; // Accept variable if already of the right type!
|
2002-12-02 01:23:04 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-01-07 02:30:19 +00:00
|
|
|
bool IntRecTy::baseClassOf(const RecTy *RHS) const{
|
|
|
|
RecTyKind kind = RHS->getRecTyKind();
|
|
|
|
return kind==BitRecTyKind || kind==BitsRecTyKind || kind==IntRecTyKind;
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *StringRecTy::convertValue(UnOpInit *BO) {
|
2009-05-14 21:22:49 +00:00
|
|
|
if (BO->getOpcode() == UnOpInit::CAST) {
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *L = BO->getOperand()->convertInitializerTo(this);
|
2009-05-14 21:22:49 +00:00
|
|
|
if (L == 0) return 0;
|
|
|
|
if (L != BO->getOperand())
|
2011-07-29 19:07:07 +00:00
|
|
|
return UnOpInit::get(UnOpInit::CAST, L, new StringRecTy);
|
2009-05-14 21:22:49 +00:00
|
|
|
return BO;
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
return convertValue((TypedInit*)BO);
|
2009-05-14 21:22:49 +00:00
|
|
|
}
|
2009-05-14 20:54:48 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *StringRecTy::convertValue(BinOpInit *BO) {
|
2006-03-31 21:53:49 +00:00
|
|
|
if (BO->getOpcode() == BinOpInit::STRCONCAT) {
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *L = BO->getLHS()->convertInitializerTo(this);
|
|
|
|
Init *R = BO->getRHS()->convertInitializerTo(this);
|
2006-03-31 21:53:49 +00:00
|
|
|
if (L == 0 || R == 0) return 0;
|
|
|
|
if (L != BO->getLHS() || R != BO->getRHS())
|
2011-07-29 19:07:07 +00:00
|
|
|
return BinOpInit::get(BinOpInit::STRCONCAT, L, R, new StringRecTy);
|
2006-03-31 21:53:49 +00:00
|
|
|
return BO;
|
|
|
|
}
|
2009-04-23 21:25:15 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
return convertValue((TypedInit*)BO);
|
2006-03-31 21:53:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *StringRecTy::convertValue(TypedInit *TI) {
|
2012-10-05 03:32:00 +00:00
|
|
|
if (isa<StringRecTy>(TI->getType()))
|
2002-12-02 17:53:54 +00:00
|
|
|
return TI; // Accept variable if already of the right type!
|
2002-12-02 01:23:04 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-11-20 22:25:16 +00:00
|
|
|
std::string ListRecTy::getAsString() const {
|
|
|
|
return "list<" + Ty->getAsString() + ">";
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *ListRecTy::convertValue(ListInit *LI) {
|
|
|
|
std::vector<Init*> Elements;
|
2003-08-03 18:17:22 +00:00
|
|
|
|
2002-12-02 01:23:04 +00:00
|
|
|
// Verify that all of the elements of the list are subclasses of the
|
2003-08-03 18:17:22 +00:00
|
|
|
// appropriate class!
|
2002-12-02 01:23:04 +00:00
|
|
|
for (unsigned i = 0, e = LI->getSize(); i != e; ++i)
|
2011-07-29 22:43:06 +00:00
|
|
|
if (Init *CI = LI->getElement(i)->convertInitializerTo(Ty))
|
2003-08-03 18:17:22 +00:00
|
|
|
Elements.push_back(CI);
|
|
|
|
else
|
2002-12-02 01:23:04 +00:00
|
|
|
return 0;
|
2003-08-03 18:17:22 +00:00
|
|
|
|
2012-10-05 03:32:00 +00:00
|
|
|
if (!isa<ListRecTy>(LI->getType()))
|
2009-06-08 20:23:18 +00:00
|
|
|
return 0;
|
|
|
|
|
2011-07-29 19:07:07 +00:00
|
|
|
return ListInit::get(Elements, this);
|
2002-12-02 01:23:04 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *ListRecTy::convertValue(TypedInit *TI) {
|
2003-07-30 04:16:52 +00:00
|
|
|
// Ensure that TI is compatible with our class.
|
2012-10-05 03:31:58 +00:00
|
|
|
if (ListRecTy *LRT = dyn_cast<ListRecTy>(TI->getType()))
|
2003-08-03 18:17:22 +00:00
|
|
|
if (LRT->getElementType()->typeIsConvertibleTo(getElementType()))
|
2003-07-30 04:16:52 +00:00
|
|
|
return TI;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-01-07 02:30:19 +00:00
|
|
|
bool ListRecTy::baseClassOf(const RecTy *RHS) const{
|
|
|
|
if(const ListRecTy* ListTy = dyn_cast<ListRecTy>(RHS))
|
|
|
|
return ListTy->getElementType()->typeIsConvertibleTo(Ty);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *DagRecTy::convertValue(TypedInit *TI) {
|
2003-08-04 04:50:57 +00:00
|
|
|
if (TI->getType()->typeIsConvertibleTo(this))
|
|
|
|
return TI;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *DagRecTy::convertValue(UnOpInit *BO) {
|
2009-05-14 21:22:49 +00:00
|
|
|
if (BO->getOpcode() == UnOpInit::CAST) {
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *L = BO->getOperand()->convertInitializerTo(this);
|
2009-05-14 21:22:49 +00:00
|
|
|
if (L == 0) return 0;
|
|
|
|
if (L != BO->getOperand())
|
2011-07-29 19:07:07 +00:00
|
|
|
return UnOpInit::get(UnOpInit::CAST, L, new DagRecTy);
|
2009-05-14 21:22:49 +00:00
|
|
|
return BO;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2009-05-14 20:54:48 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *DagRecTy::convertValue(BinOpInit *BO) {
|
2007-05-15 01:23:24 +00:00
|
|
|
if (BO->getOpcode() == BinOpInit::CONCAT) {
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *L = BO->getLHS()->convertInitializerTo(this);
|
|
|
|
Init *R = BO->getRHS()->convertInitializerTo(this);
|
2007-05-15 01:23:24 +00:00
|
|
|
if (L == 0 || R == 0) return 0;
|
|
|
|
if (L != BO->getLHS() || R != BO->getRHS())
|
2011-07-29 19:07:07 +00:00
|
|
|
return BinOpInit::get(BinOpInit::CONCAT, L, R, new DagRecTy);
|
2007-05-15 01:23:24 +00:00
|
|
|
return BO;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-07-18 17:02:57 +00:00
|
|
|
RecordRecTy *RecordRecTy::get(Record *R) {
|
2012-10-05 03:31:58 +00:00
|
|
|
return dyn_cast<RecordRecTy>(R->getDefInit()->getType());
|
2011-07-18 17:02:57 +00:00
|
|
|
}
|
|
|
|
|
2007-11-20 22:25:16 +00:00
|
|
|
std::string RecordRecTy::getAsString() const {
|
|
|
|
return Rec->getName();
|
|
|
|
}
|
2003-08-04 04:50:57 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *RecordRecTy::convertValue(DefInit *DI) {
|
2002-12-02 01:23:04 +00:00
|
|
|
// Ensure that DI is a subclass of Rec.
|
|
|
|
if (!DI->getDef()->isSubClassOf(Rec))
|
|
|
|
return 0;
|
|
|
|
return DI;
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *RecordRecTy::convertValue(TypedInit *TI) {
|
2003-07-30 04:16:52 +00:00
|
|
|
// Ensure that TI is compatible with Rec.
|
2012-10-05 03:31:58 +00:00
|
|
|
if (RecordRecTy *RRT = dyn_cast<RecordRecTy>(TI->getType()))
|
2003-07-28 03:39:57 +00:00
|
|
|
if (RRT->getRecord()->isSubClassOf(getRecord()) ||
|
|
|
|
RRT->getRecord() == getRecord())
|
2003-07-30 04:16:52 +00:00
|
|
|
return TI;
|
2003-07-28 03:39:57 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-01-07 02:30:19 +00:00
|
|
|
bool RecordRecTy::baseClassOf(const RecTy *RHS) const{
|
|
|
|
const RecordRecTy *RTy = dyn_cast<RecordRecTy>(RHS);
|
|
|
|
if (!RTy)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (Rec == RTy->getRecord() || RTy->getRecord()->isSubClassOf(Rec))
|
2010-06-17 23:00:16 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
const std::vector<Record*> &SC = Rec->getSuperClasses();
|
|
|
|
for (unsigned i = 0, e = SC.size(); i != e; ++i)
|
2013-01-07 02:30:19 +00:00
|
|
|
if (RTy->getRecord()->isSubClassOf(SC[i]))
|
2010-06-17 23:00:16 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
2003-08-03 18:17:22 +00:00
|
|
|
}
|
|
|
|
|
2009-11-22 04:24:42 +00:00
|
|
|
/// resolveTypes - Find a common type that T1 and T2 convert to.
|
2009-06-08 20:23:18 +00:00
|
|
|
/// Return 0 if no such type exists.
|
|
|
|
///
|
|
|
|
RecTy *llvm::resolveTypes(RecTy *T1, RecTy *T2) {
|
2012-09-19 02:14:59 +00:00
|
|
|
if (T1->typeIsConvertibleTo(T2))
|
|
|
|
return T2;
|
|
|
|
if (T2->typeIsConvertibleTo(T1))
|
|
|
|
return T1;
|
|
|
|
|
|
|
|
// If one is a Record type, check superclasses
|
2012-10-05 03:31:58 +00:00
|
|
|
if (RecordRecTy *RecTy1 = dyn_cast<RecordRecTy>(T1)) {
|
2012-09-19 02:14:59 +00:00
|
|
|
// See if T2 inherits from a type T1 also inherits from
|
|
|
|
const std::vector<Record *> &T1SuperClasses =
|
|
|
|
RecTy1->getRecord()->getSuperClasses();
|
|
|
|
for(std::vector<Record *>::const_iterator i = T1SuperClasses.begin(),
|
|
|
|
iend = T1SuperClasses.end();
|
|
|
|
i != iend;
|
|
|
|
++i) {
|
|
|
|
RecordRecTy *SuperRecTy1 = RecordRecTy::get(*i);
|
|
|
|
RecTy *NewType1 = resolveTypes(SuperRecTy1, T2);
|
|
|
|
if (NewType1 != 0) {
|
|
|
|
if (NewType1 != SuperRecTy1) {
|
|
|
|
delete SuperRecTy1;
|
2009-06-08 20:23:18 +00:00
|
|
|
}
|
2012-09-19 02:14:59 +00:00
|
|
|
return NewType1;
|
2009-06-08 20:23:18 +00:00
|
|
|
}
|
2012-09-19 02:14:59 +00:00
|
|
|
}
|
|
|
|
}
|
2012-10-05 03:31:58 +00:00
|
|
|
if (RecordRecTy *RecTy2 = dyn_cast<RecordRecTy>(T2)) {
|
2012-09-19 02:14:59 +00:00
|
|
|
// See if T1 inherits from a type T2 also inherits from
|
|
|
|
const std::vector<Record *> &T2SuperClasses =
|
|
|
|
RecTy2->getRecord()->getSuperClasses();
|
|
|
|
for (std::vector<Record *>::const_iterator i = T2SuperClasses.begin(),
|
|
|
|
iend = T2SuperClasses.end();
|
|
|
|
i != iend;
|
|
|
|
++i) {
|
|
|
|
RecordRecTy *SuperRecTy2 = RecordRecTy::get(*i);
|
|
|
|
RecTy *NewType2 = resolveTypes(T1, SuperRecTy2);
|
|
|
|
if (NewType2 != 0) {
|
|
|
|
if (NewType2 != SuperRecTy2) {
|
|
|
|
delete SuperRecTy2;
|
2009-06-08 20:23:18 +00:00
|
|
|
}
|
2012-09-19 02:14:59 +00:00
|
|
|
return NewType2;
|
2009-06-08 20:23:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-09-19 02:14:59 +00:00
|
|
|
return 0;
|
2009-06-08 20:23:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-12-02 01:23:04 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Initializer implementations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-12-20 02:50:00 +00:00
|
|
|
void Init::anchor() { }
|
2009-07-03 00:10:29 +00:00
|
|
|
void Init::dump() const { return print(errs()); }
|
2002-12-02 01:23:04 +00:00
|
|
|
|
2011-12-20 02:50:00 +00:00
|
|
|
void UnsetInit::anchor() { }
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
UnsetInit *UnsetInit::get() {
|
|
|
|
static UnsetInit TheInit;
|
2011-07-29 19:07:09 +00:00
|
|
|
return &TheInit;
|
2011-07-29 19:07:07 +00:00
|
|
|
}
|
|
|
|
|
2011-12-20 02:50:00 +00:00
|
|
|
void BitInit::anchor() { }
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
BitInit *BitInit::get(bool V) {
|
|
|
|
static BitInit True(true);
|
|
|
|
static BitInit False(false);
|
2011-07-29 19:07:10 +00:00
|
|
|
|
|
|
|
return V ? &True : &False;
|
2011-07-29 19:07:07 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 19:07:11 +00:00
|
|
|
static void
|
2011-07-29 22:43:06 +00:00
|
|
|
ProfileBitsInit(FoldingSetNodeID &ID, ArrayRef<Init *> Range) {
|
2011-07-29 19:07:11 +00:00
|
|
|
ID.AddInteger(Range.size());
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
for (ArrayRef<Init *>::iterator i = Range.begin(),
|
2011-07-29 19:07:11 +00:00
|
|
|
iend = Range.end();
|
|
|
|
i != iend;
|
|
|
|
++i)
|
|
|
|
ID.AddPointer(*i);
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
BitsInit *BitsInit::get(ArrayRef<Init *> Range) {
|
2011-07-29 19:07:11 +00:00
|
|
|
typedef FoldingSet<BitsInit> Pool;
|
|
|
|
static Pool ThePool;
|
|
|
|
|
|
|
|
FoldingSetNodeID ID;
|
|
|
|
ProfileBitsInit(ID, Range);
|
|
|
|
|
|
|
|
void *IP = 0;
|
2011-07-29 22:43:06 +00:00
|
|
|
if (BitsInit *I = ThePool.FindNodeOrInsertPos(ID, IP))
|
2011-07-29 19:07:11 +00:00
|
|
|
return I;
|
|
|
|
|
|
|
|
BitsInit *I = new BitsInit(Range);
|
|
|
|
ThePool.InsertNode(I, IP);
|
|
|
|
|
|
|
|
return I;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BitsInit::Profile(FoldingSetNodeID &ID) const {
|
|
|
|
ProfileBitsInit(ID, Bits);
|
2011-07-29 19:07:07 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *
|
2011-07-29 19:07:05 +00:00
|
|
|
BitsInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) const {
|
2011-07-29 22:43:06 +00:00
|
|
|
SmallVector<Init *, 16> NewBits(Bits.size());
|
2011-07-29 19:07:00 +00:00
|
|
|
|
2002-12-02 01:23:04 +00:00
|
|
|
for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
|
2011-07-29 19:07:00 +00:00
|
|
|
if (Bits[i] >= getNumBits())
|
2002-12-02 01:23:04 +00:00
|
|
|
return 0;
|
2011-07-29 19:07:00 +00:00
|
|
|
NewBits[i] = getBit(Bits[i]);
|
2002-12-02 01:23:04 +00:00
|
|
|
}
|
2011-07-29 19:07:07 +00:00
|
|
|
return BitsInit::get(NewBits);
|
2002-12-02 01:23:04 +00:00
|
|
|
}
|
|
|
|
|
2007-11-22 21:05:25 +00:00
|
|
|
std::string BitsInit::getAsString() const {
|
|
|
|
std::string Result = "{ ";
|
2002-12-02 01:23:04 +00:00
|
|
|
for (unsigned i = 0, e = getNumBits(); i != e; ++i) {
|
2007-11-22 21:05:25 +00:00
|
|
|
if (i) Result += ", ";
|
2011-07-29 22:43:06 +00:00
|
|
|
if (Init *Bit = getBit(e-i-1))
|
2007-11-22 21:05:25 +00:00
|
|
|
Result += Bit->getAsString();
|
2002-12-06 04:42:10 +00:00
|
|
|
else
|
2007-11-22 21:05:25 +00:00
|
|
|
Result += "*";
|
2002-12-02 01:23:04 +00:00
|
|
|
}
|
2007-11-22 21:05:25 +00:00
|
|
|
return Result + " }";
|
2002-12-02 01:23:04 +00:00
|
|
|
}
|
|
|
|
|
Re-work bit/bits value resolving in tblgen
- This patch is inspired by the failure of the following code snippet
which is used to convert enumerable values into encoding bits to
improve the readability of td files.
class S<int s> {
bits<2> V = !if(!eq(s, 8), {0, 0},
!if(!eq(s, 16), {0, 1},
!if(!eq(s, 32), {1, 0},
!if(!eq(s, 64), {1, 1}, {?, ?}))));
}
Later, PR8330 is found to report not exactly the same bug relevant
issue to bit/bits values.
- Instead of resolving bit/bits values separately through
resolveBitReference(), this patch adds getBit() for all Inits and
resolves bit value by resolving plus getting the specified bit. This
unifies the resolving of bit with other values and removes redundant
logic for resolving bit only. In addition,
BitsInit::resolveReferences() is optimized to take advantage of this
origanization by resolving VarBitInit's variable reference first and
then getting bits from it.
- The type interference in '!if' operator is revised to support possible
combinations of int and bits/bit in MHS and RHS.
- As there may be illegal assignments from integer value to bit, says
assign 2 to a bit, but we only check this during instantiation in some
cases, e.g.
bit V = !if(!eq(x, 17), 0, 2);
Verbose diagnostic message is generated when invalid value is
resolveed to help locating the error.
- PR8330 is fixed as well.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8
2012-09-06 23:32:48 +00:00
|
|
|
// Fix bit initializer to preserve the behavior that bit reference from a unset
|
|
|
|
// bits initializer will resolve into VarBitInit to keep the field name and bit
|
|
|
|
// number used in targets with fixed insn length.
|
|
|
|
static Init *fixBitInit(const RecordVal *RV, Init *Before, Init *After) {
|
|
|
|
if (RV || After != UnsetInit::get())
|
|
|
|
return After;
|
|
|
|
return Before;
|
|
|
|
}
|
|
|
|
|
2003-07-30 04:05:07 +00:00
|
|
|
// resolveReferences - If there are any field references that refer to fields
|
|
|
|
// that have been filled in, we can propagate the values now.
|
|
|
|
//
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *BitsInit::resolveReferences(Record &R, const RecordVal *RV) const {
|
2002-12-02 16:43:30 +00:00
|
|
|
bool Changed = false;
|
2011-07-29 22:43:06 +00:00
|
|
|
SmallVector<Init *, 16> NewBits(getNumBits());
|
2002-12-02 16:43:30 +00:00
|
|
|
|
Re-work bit/bits value resolving in tblgen
- This patch is inspired by the failure of the following code snippet
which is used to convert enumerable values into encoding bits to
improve the readability of td files.
class S<int s> {
bits<2> V = !if(!eq(s, 8), {0, 0},
!if(!eq(s, 16), {0, 1},
!if(!eq(s, 32), {1, 0},
!if(!eq(s, 64), {1, 1}, {?, ?}))));
}
Later, PR8330 is found to report not exactly the same bug relevant
issue to bit/bits values.
- Instead of resolving bit/bits values separately through
resolveBitReference(), this patch adds getBit() for all Inits and
resolves bit value by resolving plus getting the specified bit. This
unifies the resolving of bit with other values and removes redundant
logic for resolving bit only. In addition,
BitsInit::resolveReferences() is optimized to take advantage of this
origanization by resolving VarBitInit's variable reference first and
then getting bits from it.
- The type interference in '!if' operator is revised to support possible
combinations of int and bits/bit in MHS and RHS.
- As there may be illegal assignments from integer value to bit, says
assign 2 to a bit, but we only check this during instantiation in some
cases, e.g.
bit V = !if(!eq(x, 17), 0, 2);
Verbose diagnostic message is generated when invalid value is
resolveed to help locating the error.
- PR8330 is fixed as well.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8
2012-09-06 23:32:48 +00:00
|
|
|
Init *CachedInit = 0;
|
|
|
|
Init *CachedBitVar = 0;
|
|
|
|
bool CachedBitVarChanged = false;
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = getNumBits(); i != e; ++i) {
|
|
|
|
Init *CurBit = Bits[i];
|
|
|
|
Init *CurBitVar = CurBit->getBitVar();
|
2002-12-06 03:55:39 +00:00
|
|
|
|
2011-07-29 19:07:00 +00:00
|
|
|
NewBits[i] = CurBit;
|
Re-work bit/bits value resolving in tblgen
- This patch is inspired by the failure of the following code snippet
which is used to convert enumerable values into encoding bits to
improve the readability of td files.
class S<int s> {
bits<2> V = !if(!eq(s, 8), {0, 0},
!if(!eq(s, 16), {0, 1},
!if(!eq(s, 32), {1, 0},
!if(!eq(s, 64), {1, 1}, {?, ?}))));
}
Later, PR8330 is found to report not exactly the same bug relevant
issue to bit/bits values.
- Instead of resolving bit/bits values separately through
resolveBitReference(), this patch adds getBit() for all Inits and
resolves bit value by resolving plus getting the specified bit. This
unifies the resolving of bit with other values and removes redundant
logic for resolving bit only. In addition,
BitsInit::resolveReferences() is optimized to take advantage of this
origanization by resolving VarBitInit's variable reference first and
then getting bits from it.
- The type interference in '!if' operator is revised to support possible
combinations of int and bits/bit in MHS and RHS.
- As there may be illegal assignments from integer value to bit, says
assign 2 to a bit, but we only check this during instantiation in some
cases, e.g.
bit V = !if(!eq(x, 17), 0, 2);
Verbose diagnostic message is generated when invalid value is
resolveed to help locating the error.
- PR8330 is fixed as well.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8
2012-09-06 23:32:48 +00:00
|
|
|
|
|
|
|
if (CurBitVar == CachedBitVar) {
|
|
|
|
if (CachedBitVarChanged) {
|
|
|
|
Init *Bit = CachedInit->getBit(CurBit->getBitNum());
|
|
|
|
NewBits[i] = fixBitInit(RV, CurBit, Bit);
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
CachedBitVar = CurBitVar;
|
|
|
|
CachedBitVarChanged = false;
|
|
|
|
|
|
|
|
Init *B;
|
|
|
|
do {
|
|
|
|
B = CurBitVar;
|
|
|
|
CurBitVar = CurBitVar->resolveReferences(R, RV);
|
|
|
|
CachedBitVarChanged |= B != CurBitVar;
|
|
|
|
Changed |= B != CurBitVar;
|
|
|
|
} while (B != CurBitVar);
|
|
|
|
CachedInit = CurBitVar;
|
|
|
|
|
|
|
|
if (CachedBitVarChanged) {
|
|
|
|
Init *Bit = CurBitVar->getBit(CurBit->getBitNum());
|
|
|
|
NewBits[i] = fixBitInit(RV, CurBit, Bit);
|
|
|
|
}
|
2002-12-02 16:43:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Changed)
|
2011-07-29 19:07:07 +00:00
|
|
|
return BitsInit::get(NewBits);
|
2011-07-29 19:07:00 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
return const_cast<BitsInit *>(this);
|
2002-12-02 16:43:30 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
IntInit *IntInit::get(int64_t V) {
|
2011-07-29 19:07:12 +00:00
|
|
|
typedef DenseMap<int64_t, IntInit *> Pool;
|
|
|
|
static Pool ThePool;
|
|
|
|
|
|
|
|
IntInit *&I = ThePool[V];
|
|
|
|
if (!I) I = new IntInit(V);
|
|
|
|
return I;
|
2011-07-29 19:07:07 +00:00
|
|
|
}
|
|
|
|
|
2007-11-22 21:05:25 +00:00
|
|
|
std::string IntInit::getAsString() const {
|
|
|
|
return itostr(Value);
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *
|
2011-07-29 19:07:05 +00:00
|
|
|
IntInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) const {
|
2011-07-29 22:43:06 +00:00
|
|
|
SmallVector<Init *, 16> NewBits(Bits.size());
|
2002-12-02 01:23:04 +00:00
|
|
|
|
|
|
|
for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
|
2011-07-29 19:07:00 +00:00
|
|
|
if (Bits[i] >= 64)
|
2002-12-02 01:23:04 +00:00
|
|
|
return 0;
|
2011-07-29 19:07:00 +00:00
|
|
|
|
2011-07-29 19:07:07 +00:00
|
|
|
NewBits[i] = BitInit::get(Value & (INT64_C(1) << Bits[i]));
|
2011-07-11 18:25:51 +00:00
|
|
|
}
|
2011-07-29 19:07:07 +00:00
|
|
|
return BitsInit::get(NewBits);
|
|
|
|
}
|
|
|
|
|
2011-12-20 02:50:00 +00:00
|
|
|
void StringInit::anchor() { }
|
|
|
|
|
2012-01-13 03:16:35 +00:00
|
|
|
StringInit *StringInit::get(StringRef V) {
|
2011-07-29 19:07:14 +00:00
|
|
|
typedef StringMap<StringInit *> Pool;
|
|
|
|
static Pool ThePool;
|
|
|
|
|
|
|
|
StringInit *&I = ThePool[V];
|
|
|
|
if (!I) I = new StringInit(V);
|
|
|
|
return I;
|
2011-07-29 19:07:07 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 19:07:16 +00:00
|
|
|
static void ProfileListInit(FoldingSetNodeID &ID,
|
2011-07-29 22:43:06 +00:00
|
|
|
ArrayRef<Init *> Range,
|
2011-07-29 19:07:16 +00:00
|
|
|
RecTy *EltTy) {
|
|
|
|
ID.AddInteger(Range.size());
|
|
|
|
ID.AddPointer(EltTy);
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
for (ArrayRef<Init *>::iterator i = Range.begin(),
|
2011-07-29 19:07:16 +00:00
|
|
|
iend = Range.end();
|
|
|
|
i != iend;
|
|
|
|
++i)
|
|
|
|
ID.AddPointer(*i);
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
ListInit *ListInit::get(ArrayRef<Init *> Range, RecTy *EltTy) {
|
2011-07-29 19:07:16 +00:00
|
|
|
typedef FoldingSet<ListInit> Pool;
|
|
|
|
static Pool ThePool;
|
|
|
|
|
|
|
|
// Just use the FoldingSetNodeID to compute a hash. Use a DenseMap
|
|
|
|
// for actual storage.
|
|
|
|
FoldingSetNodeID ID;
|
|
|
|
ProfileListInit(ID, Range, EltTy);
|
|
|
|
|
|
|
|
void *IP = 0;
|
2011-07-29 22:43:06 +00:00
|
|
|
if (ListInit *I = ThePool.FindNodeOrInsertPos(ID, IP))
|
2011-07-29 19:07:16 +00:00
|
|
|
return I;
|
|
|
|
|
|
|
|
ListInit *I = new ListInit(Range, EltTy);
|
|
|
|
ThePool.InsertNode(I, IP);
|
|
|
|
return I;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ListInit::Profile(FoldingSetNodeID &ID) const {
|
2012-10-05 03:31:58 +00:00
|
|
|
ListRecTy *ListType = dyn_cast<ListRecTy>(getType());
|
2011-07-29 19:07:16 +00:00
|
|
|
assert(ListType && "Bad type for ListInit!");
|
|
|
|
RecTy *EltTy = ListType->getElementType();
|
|
|
|
|
|
|
|
ProfileListInit(ID, Values, EltTy);
|
2011-07-11 18:25:51 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *
|
2011-07-29 19:07:05 +00:00
|
|
|
ListInit::convertInitListSlice(const std::vector<unsigned> &Elements) const {
|
2011-07-29 22:43:06 +00:00
|
|
|
std::vector<Init*> Vals;
|
Add initial support for list slices. This currently allows you to do stuff
like this:
def B {
list<int> X = [10, 20, 30, 4, 1, 1231, 20] [2-4,2,2,0-6];
}
... which isn't particularly useful, but more is to come.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15247 91177308-0d34-0410-b5e6-96231b3b80d8
2004-07-26 23:21:34 +00:00
|
|
|
for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
|
|
|
|
if (Elements[i] >= getSize())
|
|
|
|
return 0;
|
|
|
|
Vals.push_back(getElement(Elements[i]));
|
|
|
|
}
|
2011-07-29 19:07:07 +00:00
|
|
|
return ListInit::get(Vals, getType());
|
Add initial support for list slices. This currently allows you to do stuff
like this:
def B {
list<int> X = [10, 20, 30, 4, 1, 1231, 20] [2-4,2,2,0-6];
}
... which isn't particularly useful, but more is to come.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15247 91177308-0d34-0410-b5e6-96231b3b80d8
2004-07-26 23:21:34 +00:00
|
|
|
}
|
|
|
|
|
2007-02-27 22:08:27 +00:00
|
|
|
Record *ListInit::getElementAsRecord(unsigned i) const {
|
|
|
|
assert(i < Values.size() && "List element index out of range!");
|
2012-10-10 20:24:43 +00:00
|
|
|
DefInit *DI = dyn_cast<DefInit>(Values[i]);
|
2012-10-25 20:33:17 +00:00
|
|
|
if (DI == 0)
|
|
|
|
PrintFatalError("Expected record in list!");
|
2007-02-27 22:08:27 +00:00
|
|
|
return DI->getDef();
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *ListInit::resolveReferences(Record &R, const RecordVal *RV) const {
|
|
|
|
std::vector<Init*> Resolved;
|
2004-07-27 01:01:21 +00:00
|
|
|
Resolved.reserve(getSize());
|
|
|
|
bool Changed = false;
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = getSize(); i != e; ++i) {
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *E;
|
|
|
|
Init *CurElt = getElement(i);
|
2004-07-27 01:01:21 +00:00
|
|
|
|
|
|
|
do {
|
|
|
|
E = CurElt;
|
2005-04-19 03:36:21 +00:00
|
|
|
CurElt = CurElt->resolveReferences(R, RV);
|
2004-07-27 01:01:21 +00:00
|
|
|
Changed |= E != CurElt;
|
|
|
|
} while (E != CurElt);
|
|
|
|
Resolved.push_back(E);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Changed)
|
2011-07-29 19:07:07 +00:00
|
|
|
return ListInit::get(Resolved, getType());
|
2011-07-29 22:43:06 +00:00
|
|
|
return const_cast<ListInit *>(this);
|
2004-07-27 01:01:21 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *ListInit::resolveListElementReference(Record &R, const RecordVal *IRV,
|
|
|
|
unsigned Elt) const {
|
2009-06-08 20:23:18 +00:00
|
|
|
if (Elt >= getSize())
|
|
|
|
return 0; // Out of range reference.
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *E = getElement(Elt);
|
2009-11-22 03:58:57 +00:00
|
|
|
// If the element is set to some value, or if we are resolving a reference
|
|
|
|
// to a specific variable and that variable is explicitly unset, then
|
|
|
|
// replace the VarListElementInit with it.
|
2012-10-10 20:24:47 +00:00
|
|
|
if (IRV || !isa<UnsetInit>(E))
|
2009-11-22 03:58:57 +00:00
|
|
|
return E;
|
2009-06-08 20:23:18 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-11-22 21:05:25 +00:00
|
|
|
std::string ListInit::getAsString() const {
|
|
|
|
std::string Result = "[";
|
2003-08-03 18:17:22 +00:00
|
|
|
for (unsigned i = 0, e = Values.size(); i != e; ++i) {
|
2007-11-22 21:05:25 +00:00
|
|
|
if (i) Result += ", ";
|
|
|
|
Result += Values[i]->getAsString();
|
2002-12-02 01:23:04 +00:00
|
|
|
}
|
2007-11-22 21:05:25 +00:00
|
|
|
return Result + "]";
|
2002-12-02 01:23:04 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *OpInit::resolveListElementReference(Record &R, const RecordVal *IRV,
|
|
|
|
unsigned Elt) const {
|
2011-10-04 18:55:36 +00:00
|
|
|
Init *Resolved = resolveReferences(R, IRV);
|
2012-10-10 20:24:43 +00:00
|
|
|
OpInit *OResolved = dyn_cast<OpInit>(Resolved);
|
2011-10-04 18:55:36 +00:00
|
|
|
if (OResolved) {
|
|
|
|
Resolved = OResolved->Fold(&R, 0);
|
|
|
|
}
|
2009-05-14 20:54:48 +00:00
|
|
|
|
2011-10-04 18:55:36 +00:00
|
|
|
if (Resolved != this) {
|
2012-10-10 20:24:43 +00:00
|
|
|
TypedInit *Typed = dyn_cast<TypedInit>(Resolved);
|
2011-10-04 18:55:36 +00:00
|
|
|
assert(Typed && "Expected typed init for list reference");
|
2009-05-14 20:54:48 +00:00
|
|
|
if (Typed) {
|
2011-10-04 18:55:36 +00:00
|
|
|
Init *New = Typed->resolveListElementReference(R, IRV, Elt);
|
|
|
|
if (New)
|
|
|
|
return New;
|
|
|
|
return VarListElementInit::get(Typed, Elt);
|
2009-11-22 04:24:42 +00:00
|
|
|
}
|
2009-05-14 20:54:48 +00:00
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2009-05-14 20:54:48 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Re-work bit/bits value resolving in tblgen
- This patch is inspired by the failure of the following code snippet
which is used to convert enumerable values into encoding bits to
improve the readability of td files.
class S<int s> {
bits<2> V = !if(!eq(s, 8), {0, 0},
!if(!eq(s, 16), {0, 1},
!if(!eq(s, 32), {1, 0},
!if(!eq(s, 64), {1, 1}, {?, ?}))));
}
Later, PR8330 is found to report not exactly the same bug relevant
issue to bit/bits values.
- Instead of resolving bit/bits values separately through
resolveBitReference(), this patch adds getBit() for all Inits and
resolves bit value by resolving plus getting the specified bit. This
unifies the resolving of bit with other values and removes redundant
logic for resolving bit only. In addition,
BitsInit::resolveReferences() is optimized to take advantage of this
origanization by resolving VarBitInit's variable reference first and
then getting bits from it.
- The type interference in '!if' operator is revised to support possible
combinations of int and bits/bit in MHS and RHS.
- As there may be illegal assignments from integer value to bit, says
assign 2 to a bit, but we only check this during instantiation in some
cases, e.g.
bit V = !if(!eq(x, 17), 0, 2);
Verbose diagnostic message is generated when invalid value is
resolveed to help locating the error.
- PR8330 is fixed as well.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8
2012-09-06 23:32:48 +00:00
|
|
|
Init *OpInit::getBit(unsigned Bit) const {
|
|
|
|
if (getType() == BitRecTy::get())
|
|
|
|
return const_cast<OpInit*>(this);
|
|
|
|
return VarBitInit::get(const_cast<OpInit*>(this), Bit);
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
UnOpInit *UnOpInit::get(UnaryOp opc, Init *lhs, RecTy *Type) {
|
|
|
|
typedef std::pair<std::pair<unsigned, Init *>, RecTy *> Key;
|
2011-07-29 19:07:18 +00:00
|
|
|
|
|
|
|
typedef DenseMap<Key, UnOpInit *> Pool;
|
|
|
|
static Pool ThePool;
|
|
|
|
|
|
|
|
Key TheKey(std::make_pair(std::make_pair(opc, lhs), Type));
|
|
|
|
|
|
|
|
UnOpInit *&I = ThePool[TheKey];
|
|
|
|
if (!I) I = new UnOpInit(opc, lhs, Type);
|
|
|
|
return I;
|
2011-07-29 19:07:07 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const {
|
2009-05-14 21:22:49 +00:00
|
|
|
switch (getOpcode()) {
|
|
|
|
case CAST: {
|
2009-06-29 20:05:29 +00:00
|
|
|
if (getType()->getAsString() == "string") {
|
2012-10-10 20:24:47 +00:00
|
|
|
if (StringInit *LHSs = dyn_cast<StringInit>(LHS))
|
2009-06-29 20:05:29 +00:00
|
|
|
return LHSs;
|
2009-05-14 21:22:49 +00:00
|
|
|
|
2012-10-10 20:24:47 +00:00
|
|
|
if (DefInit *LHSd = dyn_cast<DefInit>(LHS))
|
2011-07-29 19:07:07 +00:00
|
|
|
return StringInit::get(LHSd->getDef()->getName());
|
2012-01-30 20:47:04 +00:00
|
|
|
|
2012-10-10 20:24:47 +00:00
|
|
|
if (IntInit *LHSi = dyn_cast<IntInit>(LHS))
|
2012-01-30 20:47:04 +00:00
|
|
|
return StringInit::get(LHSi->getAsString());
|
2009-11-22 04:24:42 +00:00
|
|
|
} else {
|
2012-10-10 20:24:47 +00:00
|
|
|
if (StringInit *LHSs = dyn_cast<StringInit>(LHS)) {
|
2009-06-29 20:05:29 +00:00
|
|
|
std::string Name = LHSs->getValue();
|
|
|
|
|
|
|
|
// From TGParser::ParseIDValue
|
|
|
|
if (CurRec) {
|
|
|
|
if (const RecordVal *RV = CurRec->getValue(Name)) {
|
2010-10-06 00:19:21 +00:00
|
|
|
if (RV->getType() != getType())
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError("type mismatch in cast");
|
2011-07-29 19:07:07 +00:00
|
|
|
return VarInit::get(Name, RV->getType());
|
2009-05-14 21:22:49 +00:00
|
|
|
}
|
|
|
|
|
2011-10-19 13:02:42 +00:00
|
|
|
Init *TemplateArgName = QualifyName(*CurRec, CurMultiClass, Name,
|
|
|
|
":");
|
|
|
|
|
2009-06-29 20:05:29 +00:00
|
|
|
if (CurRec->isTemplateArg(TemplateArgName)) {
|
|
|
|
const RecordVal *RV = CurRec->getValue(TemplateArgName);
|
|
|
|
assert(RV && "Template arg doesn't exist??");
|
2009-05-14 21:22:49 +00:00
|
|
|
|
2010-10-06 00:19:21 +00:00
|
|
|
if (RV->getType() != getType())
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError("type mismatch in cast");
|
2009-05-14 21:22:49 +00:00
|
|
|
|
2011-07-29 19:07:07 +00:00
|
|
|
return VarInit::get(TemplateArgName, RV->getType());
|
2009-05-14 21:22:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-29 20:05:29 +00:00
|
|
|
if (CurMultiClass) {
|
2011-10-19 13:02:42 +00:00
|
|
|
Init *MCName = QualifyName(CurMultiClass->Rec, CurMultiClass, Name, "::");
|
|
|
|
|
2009-06-29 20:05:29 +00:00
|
|
|
if (CurMultiClass->Rec.isTemplateArg(MCName)) {
|
|
|
|
const RecordVal *RV = CurMultiClass->Rec.getValue(MCName);
|
|
|
|
assert(RV && "Template arg doesn't exist??");
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2010-10-06 00:19:21 +00:00
|
|
|
if (RV->getType() != getType())
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError("type mismatch in cast");
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2011-07-29 19:07:07 +00:00
|
|
|
return VarInit::get(MCName, RV->getType());
|
2009-06-29 20:05:29 +00:00
|
|
|
}
|
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2010-12-13 00:23:57 +00:00
|
|
|
if (Record *D = (CurRec->getRecords()).getDef(Name))
|
2011-07-18 17:02:57 +00:00
|
|
|
return DefInit::get(D);
|
2009-05-14 21:22:49 +00:00
|
|
|
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(CurRec->getLoc(),
|
|
|
|
"Undefined reference:'" + Name + "'\n");
|
2009-06-29 20:05:29 +00:00
|
|
|
}
|
2009-05-14 21:22:49 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2011-01-07 17:05:37 +00:00
|
|
|
case HEAD: {
|
2012-10-10 20:24:47 +00:00
|
|
|
if (ListInit *LHSl = dyn_cast<ListInit>(LHS)) {
|
2009-05-14 22:38:31 +00:00
|
|
|
if (LHSl->getSize() == 0) {
|
|
|
|
assert(0 && "Empty list in car");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return LHSl->getElement(0);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2011-01-07 17:05:37 +00:00
|
|
|
case TAIL: {
|
2012-10-10 20:24:47 +00:00
|
|
|
if (ListInit *LHSl = dyn_cast<ListInit>(LHS)) {
|
2009-05-14 22:38:31 +00:00
|
|
|
if (LHSl->getSize() == 0) {
|
|
|
|
assert(0 && "Empty list in cdr");
|
|
|
|
return 0;
|
|
|
|
}
|
2011-07-29 19:07:07 +00:00
|
|
|
// Note the +1. We can't just pass the result of getValues()
|
|
|
|
// directly.
|
2011-07-29 22:43:06 +00:00
|
|
|
ArrayRef<Init *>::iterator begin = LHSl->getValues().begin()+1;
|
|
|
|
ArrayRef<Init *>::iterator end = LHSl->getValues().end();
|
|
|
|
ListInit *Result =
|
|
|
|
ListInit::get(ArrayRef<Init *>(begin, end - begin),
|
2011-07-29 19:07:07 +00:00
|
|
|
LHSl->getType());
|
2009-05-14 22:38:31 +00:00
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2011-01-07 17:05:37 +00:00
|
|
|
case EMPTY: {
|
2012-10-10 20:24:47 +00:00
|
|
|
if (ListInit *LHSl = dyn_cast<ListInit>(LHS)) {
|
2009-05-14 22:38:31 +00:00
|
|
|
if (LHSl->getSize() == 0) {
|
2011-07-29 19:07:07 +00:00
|
|
|
return IntInit::get(1);
|
2009-11-22 04:24:42 +00:00
|
|
|
} else {
|
2011-07-29 19:07:07 +00:00
|
|
|
return IntInit::get(0);
|
2009-05-14 22:38:31 +00:00
|
|
|
}
|
|
|
|
}
|
2012-10-10 20:24:47 +00:00
|
|
|
if (StringInit *LHSs = dyn_cast<StringInit>(LHS)) {
|
2009-06-08 20:23:18 +00:00
|
|
|
if (LHSs->getValue().empty()) {
|
2011-07-29 19:07:07 +00:00
|
|
|
return IntInit::get(1);
|
2009-11-22 04:24:42 +00:00
|
|
|
} else {
|
2011-07-29 19:07:07 +00:00
|
|
|
return IntInit::get(0);
|
2009-06-08 20:23:18 +00:00
|
|
|
}
|
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2009-05-14 22:38:31 +00:00
|
|
|
break;
|
|
|
|
}
|
2009-05-14 21:22:49 +00:00
|
|
|
}
|
2011-07-29 22:43:06 +00:00
|
|
|
return const_cast<UnOpInit *>(this);
|
2009-05-14 21:22:49 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *UnOpInit::resolveReferences(Record &R, const RecordVal *RV) const {
|
|
|
|
Init *lhs = LHS->resolveReferences(R, RV);
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2009-05-14 21:22:49 +00:00
|
|
|
if (LHS != lhs)
|
2011-07-29 19:07:07 +00:00
|
|
|
return (UnOpInit::get(getOpcode(), lhs, getType()))->Fold(&R, 0);
|
2009-05-14 21:22:49 +00:00
|
|
|
return Fold(&R, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string UnOpInit::getAsString() const {
|
|
|
|
std::string Result;
|
|
|
|
switch (Opc) {
|
|
|
|
case CAST: Result = "!cast<" + getType()->getAsString() + ">"; break;
|
2011-01-07 17:05:37 +00:00
|
|
|
case HEAD: Result = "!head"; break;
|
|
|
|
case TAIL: Result = "!tail"; break;
|
|
|
|
case EMPTY: Result = "!empty"; break;
|
2009-05-14 21:22:49 +00:00
|
|
|
}
|
|
|
|
return Result + "(" + LHS->getAsString() + ")";
|
|
|
|
}
|
2009-05-14 20:54:48 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
BinOpInit *BinOpInit::get(BinaryOp opc, Init *lhs,
|
|
|
|
Init *rhs, RecTy *Type) {
|
2011-07-29 19:07:19 +00:00
|
|
|
typedef std::pair<
|
2011-07-29 22:43:06 +00:00
|
|
|
std::pair<std::pair<unsigned, Init *>, Init *>,
|
2011-07-29 19:07:19 +00:00
|
|
|
RecTy *
|
|
|
|
> Key;
|
|
|
|
|
|
|
|
typedef DenseMap<Key, BinOpInit *> Pool;
|
|
|
|
static Pool ThePool;
|
|
|
|
|
|
|
|
Key TheKey(std::make_pair(std::make_pair(std::make_pair(opc, lhs), rhs),
|
|
|
|
Type));
|
|
|
|
|
|
|
|
BinOpInit *&I = ThePool[TheKey];
|
|
|
|
if (!I) I = new BinOpInit(opc, lhs, rhs, Type);
|
|
|
|
return I;
|
2011-07-29 19:07:07 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const {
|
2006-03-31 21:53:49 +00:00
|
|
|
switch (getOpcode()) {
|
2007-05-15 01:23:24 +00:00
|
|
|
case CONCAT: {
|
2012-10-10 20:24:43 +00:00
|
|
|
DagInit *LHSs = dyn_cast<DagInit>(LHS);
|
|
|
|
DagInit *RHSs = dyn_cast<DagInit>(RHS);
|
2007-05-15 01:23:24 +00:00
|
|
|
if (LHSs && RHSs) {
|
2012-10-10 20:24:43 +00:00
|
|
|
DefInit *LOp = dyn_cast<DefInit>(LHSs->getOperator());
|
|
|
|
DefInit *ROp = dyn_cast<DefInit>(RHSs->getOperator());
|
2010-03-18 21:07:51 +00:00
|
|
|
if (LOp == 0 || ROp == 0 || LOp->getDef() != ROp->getDef())
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError("Concated Dag operators do not match!");
|
2011-07-29 22:43:06 +00:00
|
|
|
std::vector<Init*> Args;
|
2007-05-15 01:23:24 +00:00
|
|
|
std::vector<std::string> ArgNames;
|
|
|
|
for (unsigned i = 0, e = LHSs->getNumArgs(); i != e; ++i) {
|
|
|
|
Args.push_back(LHSs->getArg(i));
|
|
|
|
ArgNames.push_back(LHSs->getArgName(i));
|
|
|
|
}
|
|
|
|
for (unsigned i = 0, e = RHSs->getNumArgs(); i != e; ++i) {
|
|
|
|
Args.push_back(RHSs->getArg(i));
|
|
|
|
ArgNames.push_back(RHSs->getArgName(i));
|
|
|
|
}
|
2011-07-29 19:07:07 +00:00
|
|
|
return DagInit::get(LHSs->getOperator(), "", Args, ArgNames);
|
2007-05-15 01:23:24 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2006-03-31 21:53:49 +00:00
|
|
|
case STRCONCAT: {
|
2012-10-10 20:24:43 +00:00
|
|
|
StringInit *LHSs = dyn_cast<StringInit>(LHS);
|
|
|
|
StringInit *RHSs = dyn_cast<StringInit>(RHS);
|
2006-03-31 21:53:49 +00:00
|
|
|
if (LHSs && RHSs)
|
2011-07-29 19:07:07 +00:00
|
|
|
return StringInit::get(LHSs->getValue() + RHSs->getValue());
|
2006-03-31 21:53:49 +00:00
|
|
|
break;
|
|
|
|
}
|
2010-01-05 19:11:42 +00:00
|
|
|
case EQ: {
|
2010-06-16 23:24:12 +00:00
|
|
|
// try to fold eq comparison for 'bit' and 'int', otherwise fallback
|
|
|
|
// to string objects.
|
Re-work bit/bits value resolving in tblgen
- This patch is inspired by the failure of the following code snippet
which is used to convert enumerable values into encoding bits to
improve the readability of td files.
class S<int s> {
bits<2> V = !if(!eq(s, 8), {0, 0},
!if(!eq(s, 16), {0, 1},
!if(!eq(s, 32), {1, 0},
!if(!eq(s, 64), {1, 1}, {?, ?}))));
}
Later, PR8330 is found to report not exactly the same bug relevant
issue to bit/bits values.
- Instead of resolving bit/bits values separately through
resolveBitReference(), this patch adds getBit() for all Inits and
resolves bit value by resolving plus getting the specified bit. This
unifies the resolving of bit with other values and removes redundant
logic for resolving bit only. In addition,
BitsInit::resolveReferences() is optimized to take advantage of this
origanization by resolving VarBitInit's variable reference first and
then getting bits from it.
- The type interference in '!if' operator is revised to support possible
combinations of int and bits/bit in MHS and RHS.
- As there may be illegal assignments from integer value to bit, says
assign 2 to a bit, but we only check this during instantiation in some
cases, e.g.
bit V = !if(!eq(x, 17), 0, 2);
Verbose diagnostic message is generated when invalid value is
resolveed to help locating the error.
- PR8330 is fixed as well.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8
2012-09-06 23:32:48 +00:00
|
|
|
IntInit *L =
|
2012-10-10 20:24:43 +00:00
|
|
|
dyn_cast_or_null<IntInit>(LHS->convertInitializerTo(IntRecTy::get()));
|
Re-work bit/bits value resolving in tblgen
- This patch is inspired by the failure of the following code snippet
which is used to convert enumerable values into encoding bits to
improve the readability of td files.
class S<int s> {
bits<2> V = !if(!eq(s, 8), {0, 0},
!if(!eq(s, 16), {0, 1},
!if(!eq(s, 32), {1, 0},
!if(!eq(s, 64), {1, 1}, {?, ?}))));
}
Later, PR8330 is found to report not exactly the same bug relevant
issue to bit/bits values.
- Instead of resolving bit/bits values separately through
resolveBitReference(), this patch adds getBit() for all Inits and
resolves bit value by resolving plus getting the specified bit. This
unifies the resolving of bit with other values and removes redundant
logic for resolving bit only. In addition,
BitsInit::resolveReferences() is optimized to take advantage of this
origanization by resolving VarBitInit's variable reference first and
then getting bits from it.
- The type interference in '!if' operator is revised to support possible
combinations of int and bits/bit in MHS and RHS.
- As there may be illegal assignments from integer value to bit, says
assign 2 to a bit, but we only check this during instantiation in some
cases, e.g.
bit V = !if(!eq(x, 17), 0, 2);
Verbose diagnostic message is generated when invalid value is
resolveed to help locating the error.
- PR8330 is fixed as well.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8
2012-09-06 23:32:48 +00:00
|
|
|
IntInit *R =
|
2012-10-10 20:24:43 +00:00
|
|
|
dyn_cast_or_null<IntInit>(RHS->convertInitializerTo(IntRecTy::get()));
|
2010-06-16 23:24:12 +00:00
|
|
|
|
|
|
|
if (L && R)
|
2011-07-29 19:07:07 +00:00
|
|
|
return IntInit::get(L->getValue() == R->getValue());
|
2010-06-16 23:24:12 +00:00
|
|
|
|
2012-10-10 20:24:43 +00:00
|
|
|
StringInit *LHSs = dyn_cast<StringInit>(LHS);
|
|
|
|
StringInit *RHSs = dyn_cast<StringInit>(RHS);
|
2010-06-16 23:24:12 +00:00
|
|
|
|
|
|
|
// Make sure we've resolved
|
2010-01-05 19:11:42 +00:00
|
|
|
if (LHSs && RHSs)
|
2011-07-29 19:07:07 +00:00
|
|
|
return IntInit::get(LHSs->getValue() == RHSs->getValue());
|
2010-01-05 19:11:42 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2013-01-25 14:49:08 +00:00
|
|
|
case ADD:
|
2006-03-31 21:53:49 +00:00
|
|
|
case SHL:
|
|
|
|
case SRA:
|
|
|
|
case SRL: {
|
2012-10-10 20:24:43 +00:00
|
|
|
IntInit *LHSi = dyn_cast<IntInit>(LHS);
|
|
|
|
IntInit *RHSi = dyn_cast<IntInit>(RHS);
|
2006-03-31 21:53:49 +00:00
|
|
|
if (LHSi && RHSi) {
|
2008-10-17 01:33:43 +00:00
|
|
|
int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue();
|
|
|
|
int64_t Result;
|
2006-03-31 21:53:49 +00:00
|
|
|
switch (getOpcode()) {
|
2012-02-07 05:05:23 +00:00
|
|
|
default: llvm_unreachable("Bad opcode!");
|
2013-01-25 14:49:08 +00:00
|
|
|
case ADD: Result = LHSv + RHSv; break;
|
2006-03-31 21:53:49 +00:00
|
|
|
case SHL: Result = LHSv << RHSv; break;
|
|
|
|
case SRA: Result = LHSv >> RHSv; break;
|
2008-10-17 01:33:43 +00:00
|
|
|
case SRL: Result = (uint64_t)LHSv >> (uint64_t)RHSv; break;
|
2006-03-31 21:53:49 +00:00
|
|
|
}
|
2011-07-29 19:07:07 +00:00
|
|
|
return IntInit::get(Result);
|
2006-03-31 21:53:49 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-07-29 22:43:06 +00:00
|
|
|
return const_cast<BinOpInit *>(this);
|
2006-03-31 21:53:49 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *BinOpInit::resolveReferences(Record &R, const RecordVal *RV) const {
|
|
|
|
Init *lhs = LHS->resolveReferences(R, RV);
|
|
|
|
Init *rhs = RHS->resolveReferences(R, RV);
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2006-03-31 21:53:49 +00:00
|
|
|
if (LHS != lhs || RHS != rhs)
|
2011-07-29 19:07:07 +00:00
|
|
|
return (BinOpInit::get(getOpcode(), lhs, rhs, getType()))->Fold(&R, 0);
|
2009-04-22 20:18:10 +00:00
|
|
|
return Fold(&R, 0);
|
2006-03-31 21:53:49 +00:00
|
|
|
}
|
|
|
|
|
2007-11-22 21:05:25 +00:00
|
|
|
std::string BinOpInit::getAsString() const {
|
|
|
|
std::string Result;
|
2006-03-31 21:53:49 +00:00
|
|
|
switch (Opc) {
|
2007-11-22 21:05:25 +00:00
|
|
|
case CONCAT: Result = "!con"; break;
|
2013-01-25 14:49:08 +00:00
|
|
|
case ADD: Result = "!add"; break;
|
2007-11-22 21:05:25 +00:00
|
|
|
case SHL: Result = "!shl"; break;
|
|
|
|
case SRA: Result = "!sra"; break;
|
|
|
|
case SRL: Result = "!srl"; break;
|
2010-01-05 19:11:42 +00:00
|
|
|
case EQ: Result = "!eq"; break;
|
2007-11-22 21:05:25 +00:00
|
|
|
case STRCONCAT: Result = "!strconcat"; break;
|
2006-03-31 21:53:49 +00:00
|
|
|
}
|
2007-11-22 21:05:25 +00:00
|
|
|
return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")";
|
2006-03-31 21:53:49 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
TernOpInit *TernOpInit::get(TernaryOp opc, Init *lhs,
|
|
|
|
Init *mhs, Init *rhs,
|
2011-07-29 19:07:07 +00:00
|
|
|
RecTy *Type) {
|
2011-07-29 19:07:20 +00:00
|
|
|
typedef std::pair<
|
|
|
|
std::pair<
|
2011-07-29 22:43:06 +00:00
|
|
|
std::pair<std::pair<unsigned, RecTy *>, Init *>,
|
|
|
|
Init *
|
2011-07-29 19:07:20 +00:00
|
|
|
>,
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *
|
2011-07-29 19:07:20 +00:00
|
|
|
> Key;
|
|
|
|
|
|
|
|
typedef DenseMap<Key, TernOpInit *> Pool;
|
|
|
|
static Pool ThePool;
|
|
|
|
|
|
|
|
Key TheKey(std::make_pair(std::make_pair(std::make_pair(std::make_pair(opc,
|
|
|
|
Type),
|
|
|
|
lhs),
|
|
|
|
mhs),
|
|
|
|
rhs));
|
|
|
|
|
|
|
|
TernOpInit *&I = ThePool[TheKey];
|
|
|
|
if (!I) I = new TernOpInit(opc, lhs, mhs, rhs, Type);
|
|
|
|
return I;
|
2011-07-29 19:07:07 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type,
|
|
|
|
Record *CurRec, MultiClass *CurMultiClass);
|
2009-05-14 22:23:47 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
static Init *EvaluateOperation(OpInit *RHSo, Init *LHS, Init *Arg,
|
|
|
|
RecTy *Type, Record *CurRec,
|
|
|
|
MultiClass *CurMultiClass) {
|
|
|
|
std::vector<Init *> NewOperands;
|
2009-05-14 22:23:47 +00:00
|
|
|
|
2012-10-10 20:24:43 +00:00
|
|
|
TypedInit *TArg = dyn_cast<TypedInit>(Arg);
|
2009-05-14 22:23:47 +00:00
|
|
|
|
|
|
|
// If this is a dag, recurse
|
|
|
|
if (TArg && TArg->getType()->getAsString() == "dag") {
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *Result = ForeachHelper(LHS, Arg, RHSo, Type,
|
2011-07-11 23:06:52 +00:00
|
|
|
CurRec, CurMultiClass);
|
2009-05-14 22:23:47 +00:00
|
|
|
if (Result != 0) {
|
|
|
|
return Result;
|
2009-11-22 04:24:42 +00:00
|
|
|
} else {
|
2009-05-14 22:23:47 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < RHSo->getNumOperands(); ++i) {
|
2012-10-10 20:24:43 +00:00
|
|
|
OpInit *RHSoo = dyn_cast<OpInit>(RHSo->getOperand(i));
|
2009-05-14 22:23:47 +00:00
|
|
|
|
|
|
|
if (RHSoo) {
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *Result = EvaluateOperation(RHSoo, LHS, Arg,
|
2011-07-11 23:06:52 +00:00
|
|
|
Type, CurRec, CurMultiClass);
|
2009-05-14 22:23:47 +00:00
|
|
|
if (Result != 0) {
|
|
|
|
NewOperands.push_back(Result);
|
2009-11-22 04:24:42 +00:00
|
|
|
} else {
|
2009-05-14 22:23:47 +00:00
|
|
|
NewOperands.push_back(Arg);
|
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
} else if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
|
2009-05-14 22:23:47 +00:00
|
|
|
NewOperands.push_back(Arg);
|
2009-11-22 04:24:42 +00:00
|
|
|
} else {
|
2009-05-14 22:23:47 +00:00
|
|
|
NewOperands.push_back(RHSo->getOperand(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now run the operator and use its result as the new leaf
|
2011-07-29 19:07:05 +00:00
|
|
|
const OpInit *NewOp = RHSo->clone(NewOperands);
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *NewVal = NewOp->Fold(CurRec, CurMultiClass);
|
2011-07-29 19:07:07 +00:00
|
|
|
if (NewVal != NewOp)
|
2009-05-14 22:23:47 +00:00
|
|
|
return NewVal;
|
2011-07-29 19:07:07 +00:00
|
|
|
|
2009-05-14 22:23:47 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type,
|
|
|
|
Record *CurRec, MultiClass *CurMultiClass) {
|
2012-10-10 20:24:43 +00:00
|
|
|
DagInit *MHSd = dyn_cast<DagInit>(MHS);
|
|
|
|
ListInit *MHSl = dyn_cast<ListInit>(MHS);
|
2009-05-14 22:23:47 +00:00
|
|
|
|
2012-10-10 20:24:43 +00:00
|
|
|
OpInit *RHSo = dyn_cast<OpInit>(RHS);
|
2009-05-14 22:23:47 +00:00
|
|
|
|
|
|
|
if (!RHSo) {
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(CurRec->getLoc(), "!foreach requires an operator\n");
|
2009-05-14 22:23:47 +00:00
|
|
|
}
|
|
|
|
|
2012-10-10 20:24:43 +00:00
|
|
|
TypedInit *LHSt = dyn_cast<TypedInit>(LHS);
|
2009-05-14 22:23:47 +00:00
|
|
|
|
2012-10-25 20:33:17 +00:00
|
|
|
if (!LHSt)
|
|
|
|
PrintFatalError(CurRec->getLoc(), "!foreach requires typed variable\n");
|
2009-05-14 22:23:47 +00:00
|
|
|
|
2012-10-05 03:32:00 +00:00
|
|
|
if ((MHSd && isa<DagRecTy>(Type)) || (MHSl && isa<ListRecTy>(Type))) {
|
2009-05-14 22:23:47 +00:00
|
|
|
if (MHSd) {
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *Val = MHSd->getOperator();
|
|
|
|
Init *Result = EvaluateOperation(RHSo, LHS, Val,
|
2011-07-11 23:06:52 +00:00
|
|
|
Type, CurRec, CurMultiClass);
|
2009-05-14 22:23:47 +00:00
|
|
|
if (Result != 0) {
|
|
|
|
Val = Result;
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
std::vector<std::pair<Init *, std::string> > args;
|
2009-05-14 22:23:47 +00:00
|
|
|
for (unsigned int i = 0; i < MHSd->getNumArgs(); ++i) {
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *Arg;
|
2009-05-14 22:23:47 +00:00
|
|
|
std::string ArgName;
|
|
|
|
Arg = MHSd->getArg(i);
|
|
|
|
ArgName = MHSd->getArgName(i);
|
|
|
|
|
|
|
|
// Process args
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *Result = EvaluateOperation(RHSo, LHS, Arg, Type,
|
2011-07-11 23:06:52 +00:00
|
|
|
CurRec, CurMultiClass);
|
2009-05-14 22:23:47 +00:00
|
|
|
if (Result != 0) {
|
|
|
|
Arg = Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Process arg names
|
|
|
|
args.push_back(std::make_pair(Arg, ArgName));
|
|
|
|
}
|
|
|
|
|
2011-07-29 19:07:07 +00:00
|
|
|
return DagInit::get(Val, "", args);
|
2009-05-14 22:23:47 +00:00
|
|
|
}
|
|
|
|
if (MHSl) {
|
2011-07-29 22:43:06 +00:00
|
|
|
std::vector<Init *> NewOperands;
|
|
|
|
std::vector<Init *> NewList(MHSl->begin(), MHSl->end());
|
2009-05-14 22:23:47 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
for (std::vector<Init *>::iterator li = NewList.begin(),
|
2009-05-14 22:23:47 +00:00
|
|
|
liend = NewList.end();
|
|
|
|
li != liend;
|
|
|
|
++li) {
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *Item = *li;
|
2009-05-14 22:23:47 +00:00
|
|
|
NewOperands.clear();
|
|
|
|
for(int i = 0; i < RHSo->getNumOperands(); ++i) {
|
|
|
|
// First, replace the foreach variable with the list item
|
|
|
|
if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) {
|
|
|
|
NewOperands.push_back(Item);
|
2009-11-22 04:24:42 +00:00
|
|
|
} else {
|
2009-05-14 22:23:47 +00:00
|
|
|
NewOperands.push_back(RHSo->getOperand(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now run the operator and use its result as the new list item
|
2011-07-29 19:07:05 +00:00
|
|
|
const OpInit *NewOp = RHSo->clone(NewOperands);
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *NewItem = NewOp->Fold(CurRec, CurMultiClass);
|
2011-07-29 19:07:07 +00:00
|
|
|
if (NewItem != NewOp)
|
2009-05-14 22:23:47 +00:00
|
|
|
*li = NewItem;
|
|
|
|
}
|
2011-07-29 19:07:07 +00:00
|
|
|
return ListInit::get(NewList, MHSl->getType());
|
2009-05-14 22:23:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const {
|
2009-05-14 21:54:42 +00:00
|
|
|
switch (getOpcode()) {
|
|
|
|
case SUBST: {
|
2012-10-10 20:24:43 +00:00
|
|
|
DefInit *LHSd = dyn_cast<DefInit>(LHS);
|
|
|
|
VarInit *LHSv = dyn_cast<VarInit>(LHS);
|
|
|
|
StringInit *LHSs = dyn_cast<StringInit>(LHS);
|
2009-05-14 21:54:42 +00:00
|
|
|
|
2012-10-10 20:24:43 +00:00
|
|
|
DefInit *MHSd = dyn_cast<DefInit>(MHS);
|
|
|
|
VarInit *MHSv = dyn_cast<VarInit>(MHS);
|
|
|
|
StringInit *MHSs = dyn_cast<StringInit>(MHS);
|
2009-05-14 21:54:42 +00:00
|
|
|
|
2012-10-10 20:24:43 +00:00
|
|
|
DefInit *RHSd = dyn_cast<DefInit>(RHS);
|
|
|
|
VarInit *RHSv = dyn_cast<VarInit>(RHS);
|
|
|
|
StringInit *RHSs = dyn_cast<StringInit>(RHS);
|
2009-05-14 21:54:42 +00:00
|
|
|
|
|
|
|
if ((LHSd && MHSd && RHSd)
|
|
|
|
|| (LHSv && MHSv && RHSv)
|
|
|
|
|| (LHSs && MHSs && RHSs)) {
|
|
|
|
if (RHSd) {
|
|
|
|
Record *Val = RHSd->getDef();
|
|
|
|
if (LHSd->getAsString() == RHSd->getAsString()) {
|
|
|
|
Val = MHSd->getDef();
|
|
|
|
}
|
2011-07-18 17:02:57 +00:00
|
|
|
return DefInit::get(Val);
|
2009-05-14 21:54:42 +00:00
|
|
|
}
|
|
|
|
if (RHSv) {
|
|
|
|
std::string Val = RHSv->getName();
|
|
|
|
if (LHSv->getAsString() == RHSv->getAsString()) {
|
|
|
|
Val = MHSv->getName();
|
|
|
|
}
|
2011-07-29 19:07:07 +00:00
|
|
|
return VarInit::get(Val, getType());
|
2009-05-14 21:54:42 +00:00
|
|
|
}
|
|
|
|
if (RHSs) {
|
|
|
|
std::string Val = RHSs->getValue();
|
|
|
|
|
|
|
|
std::string::size_type found;
|
2009-12-21 21:21:34 +00:00
|
|
|
std::string::size_type idx = 0;
|
2009-05-14 21:54:42 +00:00
|
|
|
do {
|
2009-12-21 21:21:34 +00:00
|
|
|
found = Val.find(LHSs->getValue(), idx);
|
2009-05-14 21:54:42 +00:00
|
|
|
if (found != std::string::npos) {
|
|
|
|
Val.replace(found, LHSs->getValue().size(), MHSs->getValue());
|
|
|
|
}
|
2009-12-21 21:21:34 +00:00
|
|
|
idx = found + MHSs->getValue().size();
|
2009-05-14 21:54:42 +00:00
|
|
|
} while (found != std::string::npos);
|
|
|
|
|
2011-07-29 19:07:07 +00:00
|
|
|
return StringInit::get(Val);
|
2009-05-14 21:54:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2009-11-22 04:24:42 +00:00
|
|
|
}
|
2009-05-14 21:54:42 +00:00
|
|
|
|
|
|
|
case FOREACH: {
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *Result = ForeachHelper(LHS, MHS, RHS, getType(),
|
2009-05-14 22:23:47 +00:00
|
|
|
CurRec, CurMultiClass);
|
|
|
|
if (Result != 0) {
|
|
|
|
return Result;
|
2009-05-14 21:54:42 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2009-05-14 23:26:46 +00:00
|
|
|
|
|
|
|
case IF: {
|
2012-10-10 20:24:43 +00:00
|
|
|
IntInit *LHSi = dyn_cast<IntInit>(LHS);
|
2011-07-29 22:43:06 +00:00
|
|
|
if (Init *I = LHS->convertInitializerTo(IntRecTy::get()))
|
2012-10-10 20:24:43 +00:00
|
|
|
LHSi = dyn_cast<IntInit>(I);
|
2009-05-14 23:26:46 +00:00
|
|
|
if (LHSi) {
|
|
|
|
if (LHSi->getValue()) {
|
|
|
|
return MHS;
|
2009-11-22 04:24:42 +00:00
|
|
|
} else {
|
2009-05-14 23:26:46 +00:00
|
|
|
return RHS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2009-05-14 21:54:42 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
return const_cast<TernOpInit *>(this);
|
2009-05-14 21:54:42 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *TernOpInit::resolveReferences(Record &R,
|
|
|
|
const RecordVal *RV) const {
|
|
|
|
Init *lhs = LHS->resolveReferences(R, RV);
|
2009-06-08 19:16:56 +00:00
|
|
|
|
|
|
|
if (Opc == IF && lhs != LHS) {
|
2012-10-10 20:24:43 +00:00
|
|
|
IntInit *Value = dyn_cast<IntInit>(lhs);
|
2011-07-29 22:43:06 +00:00
|
|
|
if (Init *I = lhs->convertInitializerTo(IntRecTy::get()))
|
2012-10-10 20:24:43 +00:00
|
|
|
Value = dyn_cast<IntInit>(I);
|
2009-06-08 19:16:56 +00:00
|
|
|
if (Value != 0) {
|
|
|
|
// Short-circuit
|
|
|
|
if (Value->getValue()) {
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *mhs = MHS->resolveReferences(R, RV);
|
2011-07-29 19:07:07 +00:00
|
|
|
return (TernOpInit::get(getOpcode(), lhs, mhs,
|
|
|
|
RHS, getType()))->Fold(&R, 0);
|
2009-11-22 04:24:42 +00:00
|
|
|
} else {
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *rhs = RHS->resolveReferences(R, RV);
|
2011-07-29 19:07:07 +00:00
|
|
|
return (TernOpInit::get(getOpcode(), lhs, MHS,
|
|
|
|
rhs, getType()))->Fold(&R, 0);
|
2009-06-08 19:16:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *mhs = MHS->resolveReferences(R, RV);
|
|
|
|
Init *rhs = RHS->resolveReferences(R, RV);
|
2009-06-08 19:16:56 +00:00
|
|
|
|
2009-05-14 21:54:42 +00:00
|
|
|
if (LHS != lhs || MHS != mhs || RHS != rhs)
|
2011-07-29 19:07:07 +00:00
|
|
|
return (TernOpInit::get(getOpcode(), lhs, mhs, rhs,
|
|
|
|
getType()))->Fold(&R, 0);
|
2009-05-14 21:54:42 +00:00
|
|
|
return Fold(&R, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string TernOpInit::getAsString() const {
|
|
|
|
std::string Result;
|
|
|
|
switch (Opc) {
|
|
|
|
case SUBST: Result = "!subst"; break;
|
2009-11-22 04:24:42 +00:00
|
|
|
case FOREACH: Result = "!foreach"; break;
|
|
|
|
case IF: Result = "!if"; break;
|
2009-05-14 21:54:42 +00:00
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
return Result + "(" + LHS->getAsString() + ", " + MHS->getAsString() + ", "
|
2009-05-14 21:54:42 +00:00
|
|
|
+ RHS->getAsString() + ")";
|
|
|
|
}
|
2009-04-23 21:25:15 +00:00
|
|
|
|
2010-09-03 21:00:49 +00:00
|
|
|
RecTy *TypedInit::getFieldType(const std::string &FieldName) const {
|
2012-10-05 03:32:00 +00:00
|
|
|
if (RecordRecTy *RecordType = dyn_cast<RecordRecTy>(getType()))
|
|
|
|
if (RecordVal *Field = RecordType->getRecord()->getValue(FieldName))
|
2010-09-03 21:00:49 +00:00
|
|
|
return Field->getType();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *
|
2011-07-29 19:07:05 +00:00
|
|
|
TypedInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) const {
|
2012-10-05 03:31:58 +00:00
|
|
|
BitsRecTy *T = dyn_cast<BitsRecTy>(getType());
|
2010-12-10 22:54:30 +00:00
|
|
|
if (T == 0) return 0; // Cannot subscript a non-bits variable.
|
2002-12-02 01:23:04 +00:00
|
|
|
unsigned NumBits = T->getNumBits();
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
SmallVector<Init *, 16> NewBits(Bits.size());
|
2002-12-02 01:23:04 +00:00
|
|
|
for (unsigned i = 0, e = Bits.size(); i != e; ++i) {
|
2011-07-29 19:07:00 +00:00
|
|
|
if (Bits[i] >= NumBits)
|
2002-12-02 01:23:04 +00:00
|
|
|
return 0;
|
2011-07-29 19:07:00 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
NewBits[i] = VarBitInit::get(const_cast<TypedInit *>(this), Bits[i]);
|
2002-12-02 01:23:04 +00:00
|
|
|
}
|
2011-07-29 19:07:07 +00:00
|
|
|
return BitsInit::get(NewBits);
|
2002-12-02 01:23:04 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *
|
2011-07-29 19:07:05 +00:00
|
|
|
TypedInit::convertInitListSlice(const std::vector<unsigned> &Elements) const {
|
2012-10-05 03:31:58 +00:00
|
|
|
ListRecTy *T = dyn_cast<ListRecTy>(getType());
|
2010-12-10 22:54:30 +00:00
|
|
|
if (T == 0) return 0; // Cannot subscript a non-list variable.
|
2004-07-27 01:01:21 +00:00
|
|
|
|
|
|
|
if (Elements.size() == 1)
|
2011-07-29 22:43:06 +00:00
|
|
|
return VarListElementInit::get(const_cast<TypedInit *>(this), Elements[0]);
|
2004-07-27 01:01:21 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
std::vector<Init*> ListInits;
|
2004-07-27 01:01:21 +00:00
|
|
|
ListInits.reserve(Elements.size());
|
|
|
|
for (unsigned i = 0, e = Elements.size(); i != e; ++i)
|
2011-07-29 22:43:06 +00:00
|
|
|
ListInits.push_back(VarListElementInit::get(const_cast<TypedInit *>(this),
|
|
|
|
Elements[i]));
|
2011-07-29 19:07:07 +00:00
|
|
|
return ListInit::get(ListInits, T);
|
2004-07-27 01:01:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
VarInit *VarInit::get(const std::string &VN, RecTy *T) {
|
2011-10-19 13:02:33 +00:00
|
|
|
Init *Value = StringInit::get(VN);
|
|
|
|
return VarInit::get(Value, T);
|
|
|
|
}
|
|
|
|
|
|
|
|
VarInit *VarInit::get(Init *VN, RecTy *T) {
|
|
|
|
typedef std::pair<RecTy *, Init *> Key;
|
2011-07-29 19:07:21 +00:00
|
|
|
typedef DenseMap<Key, VarInit *> Pool;
|
|
|
|
static Pool ThePool;
|
|
|
|
|
|
|
|
Key TheKey(std::make_pair(T, VN));
|
|
|
|
|
|
|
|
VarInit *&I = ThePool[TheKey];
|
|
|
|
if (!I) I = new VarInit(VN, T);
|
|
|
|
return I;
|
2011-07-29 19:07:07 +00:00
|
|
|
}
|
|
|
|
|
2011-10-19 13:02:33 +00:00
|
|
|
const std::string &VarInit::getName() const {
|
2012-10-10 20:24:47 +00:00
|
|
|
StringInit *NameString = dyn_cast<StringInit>(getNameInit());
|
2011-10-19 13:02:33 +00:00
|
|
|
assert(NameString && "VarInit name is not a string!");
|
|
|
|
return NameString->getValue();
|
|
|
|
}
|
|
|
|
|
Re-work bit/bits value resolving in tblgen
- This patch is inspired by the failure of the following code snippet
which is used to convert enumerable values into encoding bits to
improve the readability of td files.
class S<int s> {
bits<2> V = !if(!eq(s, 8), {0, 0},
!if(!eq(s, 16), {0, 1},
!if(!eq(s, 32), {1, 0},
!if(!eq(s, 64), {1, 1}, {?, ?}))));
}
Later, PR8330 is found to report not exactly the same bug relevant
issue to bit/bits values.
- Instead of resolving bit/bits values separately through
resolveBitReference(), this patch adds getBit() for all Inits and
resolves bit value by resolving plus getting the specified bit. This
unifies the resolving of bit with other values and removes redundant
logic for resolving bit only. In addition,
BitsInit::resolveReferences() is optimized to take advantage of this
origanization by resolving VarBitInit's variable reference first and
then getting bits from it.
- The type interference in '!if' operator is revised to support possible
combinations of int and bits/bit in MHS and RHS.
- As there may be illegal assignments from integer value to bit, says
assign 2 to a bit, but we only check this during instantiation in some
cases, e.g.
bit V = !if(!eq(x, 17), 0, 2);
Verbose diagnostic message is generated when invalid value is
resolveed to help locating the error.
- PR8330 is fixed as well.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8
2012-09-06 23:32:48 +00:00
|
|
|
Init *VarInit::getBit(unsigned Bit) const {
|
|
|
|
if (getType() == BitRecTy::get())
|
|
|
|
return const_cast<VarInit*>(this);
|
|
|
|
return VarBitInit::get(const_cast<VarInit*>(this), Bit);
|
2002-12-02 01:23:04 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *VarInit::resolveListElementReference(Record &R,
|
|
|
|
const RecordVal *IRV,
|
|
|
|
unsigned Elt) const {
|
2012-01-13 03:16:35 +00:00
|
|
|
if (R.isTemplateArg(getNameInit())) return 0;
|
|
|
|
if (IRV && IRV->getNameInit() != getNameInit()) return 0;
|
2004-07-27 01:01:21 +00:00
|
|
|
|
2012-01-13 03:16:35 +00:00
|
|
|
RecordVal *RV = R.getValue(getNameInit());
|
2009-11-21 22:44:20 +00:00
|
|
|
assert(RV && "Reference to a non-existent variable?");
|
2012-10-10 20:24:43 +00:00
|
|
|
ListInit *LI = dyn_cast<ListInit>(RV->getValue());
|
2009-05-14 20:38:52 +00:00
|
|
|
if (!LI) {
|
2012-10-10 20:24:43 +00:00
|
|
|
TypedInit *VI = dyn_cast<TypedInit>(RV->getValue());
|
2009-05-14 20:38:52 +00:00
|
|
|
assert(VI && "Invalid list element!");
|
2011-07-29 19:07:07 +00:00
|
|
|
return VarListElementInit::get(VI, Elt);
|
2009-05-14 20:38:52 +00:00
|
|
|
}
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2004-07-27 01:01:21 +00:00
|
|
|
if (Elt >= LI->getSize())
|
|
|
|
return 0; // Out of range reference.
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *E = LI->getElement(Elt);
|
2009-11-22 03:58:57 +00:00
|
|
|
// If the element is set to some value, or if we are resolving a reference
|
|
|
|
// to a specific variable and that variable is explicitly unset, then
|
|
|
|
// replace the VarListElementInit with it.
|
2012-10-10 20:24:47 +00:00
|
|
|
if (IRV || !isa<UnsetInit>(E))
|
2009-11-22 03:58:57 +00:00
|
|
|
return E;
|
2004-07-27 01:01:21 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-12-03 06:00:33 +00:00
|
|
|
RecTy *VarInit::getFieldType(const std::string &FieldName) const {
|
2012-10-05 03:31:58 +00:00
|
|
|
if (RecordRecTy *RTy = dyn_cast<RecordRecTy>(getType()))
|
2002-12-03 06:00:33 +00:00
|
|
|
if (const RecordVal *RV = RTy->getRecord()->getValue(FieldName))
|
|
|
|
return RV->getType();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *VarInit::getFieldInit(Record &R, const RecordVal *RV,
|
|
|
|
const std::string &FieldName) const {
|
2012-10-05 03:32:00 +00:00
|
|
|
if (isa<RecordRecTy>(getType()))
|
2010-03-25 06:23:34 +00:00
|
|
|
if (const RecordVal *Val = R.getValue(VarName)) {
|
2012-10-10 20:24:47 +00:00
|
|
|
if (RV != Val && (RV || isa<UnsetInit>(Val->getValue())))
|
2010-03-25 06:23:34 +00:00
|
|
|
return 0;
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *TheInit = Val->getValue();
|
2004-02-28 16:31:53 +00:00
|
|
|
assert(TheInit != this && "Infinite loop detected!");
|
2011-07-29 22:43:06 +00:00
|
|
|
if (Init *I = TheInit->getFieldInit(R, RV, FieldName))
|
2002-12-03 06:00:33 +00:00
|
|
|
return I;
|
|
|
|
else
|
2003-08-01 05:58:58 +00:00
|
|
|
return 0;
|
2004-02-28 16:31:53 +00:00
|
|
|
}
|
2002-12-03 06:00:33 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-07-30 04:05:07 +00:00
|
|
|
/// resolveReferences - This method is used by classes that refer to other
|
2009-11-21 22:44:20 +00:00
|
|
|
/// variables which may not be defined at the time the expression is formed.
|
2003-07-30 04:05:07 +00:00
|
|
|
/// 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.
|
|
|
|
///
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *VarInit::resolveReferences(Record &R, const RecordVal *RV) const {
|
2003-07-30 04:05:07 +00:00
|
|
|
if (RecordVal *Val = R.getValue(VarName))
|
2012-10-10 20:24:47 +00:00
|
|
|
if (RV == Val || (RV == 0 && !isa<UnsetInit>(Val->getValue())))
|
2003-07-30 04:05:07 +00:00
|
|
|
return Val->getValue();
|
2011-07-29 22:43:06 +00:00
|
|
|
return const_cast<VarInit *>(this);
|
2003-07-30 04:05:07 +00:00
|
|
|
}
|
2005-04-22 00:00:37 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
VarBitInit *VarBitInit::get(TypedInit *T, unsigned B) {
|
|
|
|
typedef std::pair<TypedInit *, unsigned> Key;
|
2011-07-29 19:07:22 +00:00
|
|
|
typedef DenseMap<Key, VarBitInit *> Pool;
|
|
|
|
|
|
|
|
static Pool ThePool;
|
|
|
|
|
|
|
|
Key TheKey(std::make_pair(T, B));
|
|
|
|
|
|
|
|
VarBitInit *&I = ThePool[TheKey];
|
|
|
|
if (!I) I = new VarBitInit(T, B);
|
|
|
|
return I;
|
2011-07-29 19:07:07 +00:00
|
|
|
}
|
|
|
|
|
2007-11-22 21:05:25 +00:00
|
|
|
std::string VarBitInit::getAsString() const {
|
|
|
|
return TI->getAsString() + "{" + utostr(Bit) + "}";
|
|
|
|
}
|
2002-12-02 17:44:35 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *VarBitInit::resolveReferences(Record &R, const RecordVal *RV) const {
|
Re-work bit/bits value resolving in tblgen
- This patch is inspired by the failure of the following code snippet
which is used to convert enumerable values into encoding bits to
improve the readability of td files.
class S<int s> {
bits<2> V = !if(!eq(s, 8), {0, 0},
!if(!eq(s, 16), {0, 1},
!if(!eq(s, 32), {1, 0},
!if(!eq(s, 64), {1, 1}, {?, ?}))));
}
Later, PR8330 is found to report not exactly the same bug relevant
issue to bit/bits values.
- Instead of resolving bit/bits values separately through
resolveBitReference(), this patch adds getBit() for all Inits and
resolves bit value by resolving plus getting the specified bit. This
unifies the resolving of bit with other values and removes redundant
logic for resolving bit only. In addition,
BitsInit::resolveReferences() is optimized to take advantage of this
origanization by resolving VarBitInit's variable reference first and
then getting bits from it.
- The type interference in '!if' operator is revised to support possible
combinations of int and bits/bit in MHS and RHS.
- As there may be illegal assignments from integer value to bit, says
assign 2 to a bit, but we only check this during instantiation in some
cases, e.g.
bit V = !if(!eq(x, 17), 0, 2);
Verbose diagnostic message is generated when invalid value is
resolveed to help locating the error.
- PR8330 is fixed as well.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8
2012-09-06 23:32:48 +00:00
|
|
|
Init *I = TI->resolveReferences(R, RV);
|
|
|
|
if (TI != I)
|
|
|
|
return I->getBit(getBitNum());
|
|
|
|
|
|
|
|
return const_cast<VarBitInit*>(this);
|
2002-12-02 17:44:35 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
VarListElementInit *VarListElementInit::get(TypedInit *T,
|
|
|
|
unsigned E) {
|
|
|
|
typedef std::pair<TypedInit *, unsigned> Key;
|
2011-07-29 19:07:23 +00:00
|
|
|
typedef DenseMap<Key, VarListElementInit *> Pool;
|
|
|
|
|
|
|
|
static Pool ThePool;
|
|
|
|
|
|
|
|
Key TheKey(std::make_pair(T, E));
|
|
|
|
|
|
|
|
VarListElementInit *&I = ThePool[TheKey];
|
|
|
|
if (!I) I = new VarListElementInit(T, E);
|
|
|
|
return I;
|
2011-07-29 19:07:07 +00:00
|
|
|
}
|
|
|
|
|
2007-11-22 21:05:25 +00:00
|
|
|
std::string VarListElementInit::getAsString() const {
|
|
|
|
return TI->getAsString() + "[" + utostr(Element) + "]";
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *
|
|
|
|
VarListElementInit::resolveReferences(Record &R, const RecordVal *RV) const {
|
|
|
|
if (Init *I = getVariable()->resolveListElementReference(R, RV,
|
2011-07-11 23:06:52 +00:00
|
|
|
getElementNum()))
|
2004-07-27 01:01:21 +00:00
|
|
|
return I;
|
2011-07-29 22:43:06 +00:00
|
|
|
return const_cast<VarListElementInit *>(this);
|
2004-07-27 01:01:21 +00:00
|
|
|
}
|
|
|
|
|
Re-work bit/bits value resolving in tblgen
- This patch is inspired by the failure of the following code snippet
which is used to convert enumerable values into encoding bits to
improve the readability of td files.
class S<int s> {
bits<2> V = !if(!eq(s, 8), {0, 0},
!if(!eq(s, 16), {0, 1},
!if(!eq(s, 32), {1, 0},
!if(!eq(s, 64), {1, 1}, {?, ?}))));
}
Later, PR8330 is found to report not exactly the same bug relevant
issue to bit/bits values.
- Instead of resolving bit/bits values separately through
resolveBitReference(), this patch adds getBit() for all Inits and
resolves bit value by resolving plus getting the specified bit. This
unifies the resolving of bit with other values and removes redundant
logic for resolving bit only. In addition,
BitsInit::resolveReferences() is optimized to take advantage of this
origanization by resolving VarBitInit's variable reference first and
then getting bits from it.
- The type interference in '!if' operator is revised to support possible
combinations of int and bits/bit in MHS and RHS.
- As there may be illegal assignments from integer value to bit, says
assign 2 to a bit, but we only check this during instantiation in some
cases, e.g.
bit V = !if(!eq(x, 17), 0, 2);
Verbose diagnostic message is generated when invalid value is
resolveed to help locating the error.
- PR8330 is fixed as well.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8
2012-09-06 23:32:48 +00:00
|
|
|
Init *VarListElementInit::getBit(unsigned Bit) const {
|
|
|
|
if (getType() == BitRecTy::get())
|
|
|
|
return const_cast<VarListElementInit*>(this);
|
|
|
|
return VarBitInit::get(const_cast<VarListElementInit*>(this), Bit);
|
2004-07-27 01:01:21 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *VarListElementInit:: resolveListElementReference(Record &R,
|
|
|
|
const RecordVal *RV,
|
|
|
|
unsigned Elt) const {
|
2011-09-30 20:59:49 +00:00
|
|
|
Init *Result = TI->resolveListElementReference(R, RV, Element);
|
|
|
|
|
|
|
|
if (Result) {
|
2012-10-10 20:24:47 +00:00
|
|
|
if (TypedInit *TInit = dyn_cast<TypedInit>(Result)) {
|
2011-10-06 21:20:46 +00:00
|
|
|
Init *Result2 = TInit->resolveListElementReference(R, RV, Elt);
|
|
|
|
if (Result2) return Result2;
|
|
|
|
return new VarListElementInit(TInit, Elt);
|
2011-09-30 20:59:49 +00:00
|
|
|
}
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2004-07-27 01:01:21 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
DefInit *DefInit::get(Record *R) {
|
2011-07-18 17:02:57 +00:00
|
|
|
return R->getDefInit();
|
|
|
|
}
|
|
|
|
|
2002-12-03 06:00:33 +00:00
|
|
|
RecTy *DefInit::getFieldType(const std::string &FieldName) const {
|
|
|
|
if (const RecordVal *RV = Def->getValue(FieldName))
|
|
|
|
return RV->getType();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *DefInit::getFieldInit(Record &R, const RecordVal *RV,
|
|
|
|
const std::string &FieldName) const {
|
2002-12-03 06:00:33 +00:00
|
|
|
return Def->getValue(FieldName)->getValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-22 21:05:25 +00:00
|
|
|
std::string DefInit::getAsString() const {
|
|
|
|
return Def->getName();
|
2002-12-02 01:23:04 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
FieldInit *FieldInit::get(Init *R, const std::string &FN) {
|
|
|
|
typedef std::pair<Init *, TableGenStringKey> Key;
|
2011-07-29 19:07:24 +00:00
|
|
|
typedef DenseMap<Key, FieldInit *> Pool;
|
|
|
|
static Pool ThePool;
|
|
|
|
|
|
|
|
Key TheKey(std::make_pair(R, FN));
|
|
|
|
|
|
|
|
FieldInit *&I = ThePool[TheKey];
|
|
|
|
if (!I) I = new FieldInit(R, FN);
|
|
|
|
return I;
|
2011-07-29 19:07:07 +00:00
|
|
|
}
|
|
|
|
|
Re-work bit/bits value resolving in tblgen
- This patch is inspired by the failure of the following code snippet
which is used to convert enumerable values into encoding bits to
improve the readability of td files.
class S<int s> {
bits<2> V = !if(!eq(s, 8), {0, 0},
!if(!eq(s, 16), {0, 1},
!if(!eq(s, 32), {1, 0},
!if(!eq(s, 64), {1, 1}, {?, ?}))));
}
Later, PR8330 is found to report not exactly the same bug relevant
issue to bit/bits values.
- Instead of resolving bit/bits values separately through
resolveBitReference(), this patch adds getBit() for all Inits and
resolves bit value by resolving plus getting the specified bit. This
unifies the resolving of bit with other values and removes redundant
logic for resolving bit only. In addition,
BitsInit::resolveReferences() is optimized to take advantage of this
origanization by resolving VarBitInit's variable reference first and
then getting bits from it.
- The type interference in '!if' operator is revised to support possible
combinations of int and bits/bit in MHS and RHS.
- As there may be illegal assignments from integer value to bit, says
assign 2 to a bit, but we only check this during instantiation in some
cases, e.g.
bit V = !if(!eq(x, 17), 0, 2);
Verbose diagnostic message is generated when invalid value is
resolveed to help locating the error.
- PR8330 is fixed as well.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8
2012-09-06 23:32:48 +00:00
|
|
|
Init *FieldInit::getBit(unsigned Bit) const {
|
|
|
|
if (getType() == BitRecTy::get())
|
|
|
|
return const_cast<FieldInit*>(this);
|
|
|
|
return VarBitInit::get(const_cast<FieldInit*>(this), Bit);
|
2004-07-27 01:01:21 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *FieldInit::resolveListElementReference(Record &R, const RecordVal *RV,
|
|
|
|
unsigned Elt) const {
|
|
|
|
if (Init *ListVal = Rec->getFieldInit(R, RV, FieldName))
|
2012-10-10 20:24:43 +00:00
|
|
|
if (ListInit *LI = dyn_cast<ListInit>(ListVal)) {
|
2004-07-27 01:01:21 +00:00
|
|
|
if (Elt >= LI->getSize()) return 0;
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *E = LI->getElement(Elt);
|
2004-07-27 01:01:21 +00:00
|
|
|
|
2009-11-22 03:58:57 +00:00
|
|
|
// If the element is set to some value, or if we are resolving a
|
|
|
|
// reference to a specific variable and that variable is explicitly
|
|
|
|
// unset, then replace the VarListElementInit with it.
|
2012-10-10 20:24:47 +00:00
|
|
|
if (RV || !isa<UnsetInit>(E))
|
2009-11-22 03:58:57 +00:00
|
|
|
return E;
|
2004-07-27 01:01:21 +00:00
|
|
|
}
|
|
|
|
return 0;
|
2003-08-01 05:58:58 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *FieldInit::resolveReferences(Record &R, const RecordVal *RV) const {
|
|
|
|
Init *NewRec = RV ? Rec->resolveReferences(R, RV) : Rec;
|
2005-04-19 03:36:21 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *BitsVal = NewRec->getFieldInit(R, RV, FieldName);
|
2003-08-01 05:58:58 +00:00
|
|
|
if (BitsVal) {
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *BVR = BitsVal->resolveReferences(R, RV);
|
|
|
|
return BVR->isComplete() ? BVR : const_cast<FieldInit *>(this);
|
2002-12-03 06:00:33 +00:00
|
|
|
}
|
2005-04-19 03:36:21 +00:00
|
|
|
|
|
|
|
if (NewRec != Rec) {
|
2011-07-29 19:07:07 +00:00
|
|
|
return FieldInit::get(NewRec, FieldName);
|
2005-04-19 03:36:21 +00:00
|
|
|
}
|
2011-07-29 22:43:06 +00:00
|
|
|
return const_cast<FieldInit *>(this);
|
2002-12-02 17:44:35 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 19:07:26 +00:00
|
|
|
void ProfileDagInit(FoldingSetNodeID &ID,
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *V,
|
2011-07-29 19:07:26 +00:00
|
|
|
const std::string &VN,
|
2011-07-29 22:43:06 +00:00
|
|
|
ArrayRef<Init *> ArgRange,
|
2011-07-29 19:07:26 +00:00
|
|
|
ArrayRef<std::string> NameRange) {
|
|
|
|
ID.AddPointer(V);
|
|
|
|
ID.AddString(VN);
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
ArrayRef<Init *>::iterator Arg = ArgRange.begin();
|
2011-07-29 19:07:26 +00:00
|
|
|
ArrayRef<std::string>::iterator Name = NameRange.begin();
|
|
|
|
while (Arg != ArgRange.end()) {
|
|
|
|
assert(Name != NameRange.end() && "Arg name underflow!");
|
|
|
|
ID.AddPointer(*Arg++);
|
|
|
|
ID.AddString(*Name++);
|
|
|
|
}
|
|
|
|
assert(Name == NameRange.end() && "Arg name overflow!");
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
DagInit *
|
|
|
|
DagInit::get(Init *V, const std::string &VN,
|
|
|
|
ArrayRef<Init *> ArgRange,
|
2011-07-29 19:07:26 +00:00
|
|
|
ArrayRef<std::string> NameRange) {
|
|
|
|
typedef FoldingSet<DagInit> Pool;
|
|
|
|
static Pool ThePool;
|
|
|
|
|
|
|
|
FoldingSetNodeID ID;
|
|
|
|
ProfileDagInit(ID, V, VN, ArgRange, NameRange);
|
|
|
|
|
|
|
|
void *IP = 0;
|
2011-07-29 22:43:06 +00:00
|
|
|
if (DagInit *I = ThePool.FindNodeOrInsertPos(ID, IP))
|
2011-07-29 19:07:26 +00:00
|
|
|
return I;
|
|
|
|
|
|
|
|
DagInit *I = new DagInit(V, VN, ArgRange, NameRange);
|
|
|
|
ThePool.InsertNode(I, IP);
|
|
|
|
|
|
|
|
return I;
|
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
DagInit *
|
|
|
|
DagInit::get(Init *V, const std::string &VN,
|
|
|
|
const std::vector<std::pair<Init*, std::string> > &args) {
|
|
|
|
typedef std::pair<Init*, std::string> PairType;
|
2011-07-29 19:07:07 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
std::vector<Init *> Args;
|
2011-07-29 19:07:07 +00:00
|
|
|
std::vector<std::string> Names;
|
|
|
|
|
|
|
|
for (std::vector<PairType>::const_iterator i = args.begin(),
|
|
|
|
iend = args.end();
|
|
|
|
i != iend;
|
|
|
|
++i) {
|
|
|
|
Args.push_back(i->first);
|
|
|
|
Names.push_back(i->second);
|
|
|
|
}
|
|
|
|
|
|
|
|
return DagInit::get(V, VN, Args, Names);
|
|
|
|
}
|
|
|
|
|
2011-07-29 19:07:26 +00:00
|
|
|
void DagInit::Profile(FoldingSetNodeID &ID) const {
|
|
|
|
ProfileDagInit(ID, Val, ValName, Args, ArgNames);
|
2011-07-29 19:07:07 +00:00
|
|
|
}
|
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *DagInit::resolveReferences(Record &R, const RecordVal *RV) const {
|
|
|
|
std::vector<Init*> NewArgs;
|
2006-01-31 06:02:35 +00:00
|
|
|
for (unsigned i = 0, e = Args.size(); i != e; ++i)
|
|
|
|
NewArgs.push_back(Args[i]->resolveReferences(R, RV));
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *Op = Val->resolveReferences(R, RV);
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2006-03-30 22:50:40 +00:00
|
|
|
if (Args != NewArgs || Op != Val)
|
2011-07-29 19:07:07 +00:00
|
|
|
return DagInit::get(Op, ValName, NewArgs, ArgNames);
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2011-07-29 22:43:06 +00:00
|
|
|
return const_cast<DagInit *>(this);
|
2006-01-31 06:02:35 +00:00
|
|
|
}
|
|
|
|
|
2002-12-02 17:44:35 +00:00
|
|
|
|
2007-11-22 21:05:25 +00:00
|
|
|
std::string DagInit::getAsString() const {
|
|
|
|
std::string Result = "(" + Val->getAsString();
|
2009-03-19 05:21:56 +00:00
|
|
|
if (!ValName.empty())
|
|
|
|
Result += ":" + ValName;
|
2003-08-04 20:44:17 +00:00
|
|
|
if (Args.size()) {
|
2007-11-22 21:05:25 +00:00
|
|
|
Result += " " + Args[0]->getAsString();
|
|
|
|
if (!ArgNames[0].empty()) Result += ":$" + ArgNames[0];
|
2003-08-10 22:14:13 +00:00
|
|
|
for (unsigned i = 1, e = Args.size(); i != e; ++i) {
|
2007-11-22 21:05:25 +00:00
|
|
|
Result += ", " + Args[i]->getAsString();
|
|
|
|
if (!ArgNames[i].empty()) Result += ":$" + ArgNames[i];
|
2003-08-10 22:14:13 +00:00
|
|
|
}
|
2003-08-04 20:44:17 +00:00
|
|
|
}
|
2007-11-22 21:05:25 +00:00
|
|
|
return Result + ")";
|
2003-08-04 20:44:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-12-02 01:23:04 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Other implementations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-09-02 20:12:07 +00:00
|
|
|
RecordVal::RecordVal(Init *N, RecTy *T, unsigned P)
|
2002-12-02 01:23:04 +00:00
|
|
|
: Name(N), Ty(T), Prefix(P) {
|
2011-07-29 19:07:07 +00:00
|
|
|
Value = Ty->convertValue(UnsetInit::get());
|
2002-12-02 01:23:04 +00:00
|
|
|
assert(Value && "Cannot create unset value for current type!");
|
|
|
|
}
|
|
|
|
|
2011-09-02 20:12:07 +00:00
|
|
|
RecordVal::RecordVal(const std::string &N, RecTy *T, unsigned P)
|
|
|
|
: Name(StringInit::get(N)), Ty(T), Prefix(P) {
|
|
|
|
Value = Ty->convertValue(UnsetInit::get());
|
|
|
|
assert(Value && "Cannot create unset value for current type!");
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::string &RecordVal::getName() const {
|
2012-10-10 20:24:43 +00:00
|
|
|
StringInit *NameString = dyn_cast<StringInit>(Name);
|
2011-09-02 20:12:07 +00:00
|
|
|
assert(NameString && "RecordVal name is not a string!");
|
|
|
|
return NameString->getValue();
|
|
|
|
}
|
|
|
|
|
2009-07-03 00:10:29 +00:00
|
|
|
void RecordVal::dump() const { errs() << *this; }
|
2002-12-02 01:23:04 +00:00
|
|
|
|
2009-07-03 00:10:29 +00:00
|
|
|
void RecordVal::print(raw_ostream &OS, bool PrintSem) const {
|
2002-12-02 01:23:04 +00:00
|
|
|
if (getPrefix()) OS << "field ";
|
2011-10-19 13:02:52 +00:00
|
|
|
OS << *getType() << " " << getNameInitAsString();
|
2005-04-19 03:36:21 +00:00
|
|
|
|
|
|
|
if (getValue())
|
2002-12-02 01:23:04 +00:00
|
|
|
OS << " = " << *getValue();
|
2005-04-19 03:36:21 +00:00
|
|
|
|
2002-12-02 01:23:04 +00:00
|
|
|
if (PrintSem) OS << ";\n";
|
|
|
|
}
|
|
|
|
|
2009-08-23 09:47:37 +00:00
|
|
|
unsigned Record::LastID = 0;
|
|
|
|
|
2011-10-19 13:02:45 +00:00
|
|
|
void Record::init() {
|
|
|
|
checkName();
|
2011-10-19 13:04:13 +00:00
|
|
|
|
|
|
|
// Every record potentially has a def at the top. This value is
|
|
|
|
// replaced with the top-level def name at instantiation time.
|
|
|
|
RecordVal DN("NAME", StringRecTy::get(), 0);
|
|
|
|
addValue(DN);
|
2011-10-19 13:02:45 +00:00
|
|
|
}
|
|
|
|
|
2011-08-10 18:27:46 +00:00
|
|
|
void Record::checkName() {
|
|
|
|
// Ensure the record name has string type.
|
2012-10-10 20:24:43 +00:00
|
|
|
const TypedInit *TypedName = dyn_cast<const TypedInit>(Name);
|
2011-08-10 18:27:46 +00:00
|
|
|
assert(TypedName && "Record name is not typed!");
|
|
|
|
RecTy *Type = TypedName->getType();
|
2012-10-05 03:32:00 +00:00
|
|
|
if (!isa<StringRecTy>(Type))
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Record name is not a string!");
|
2011-08-10 18:27:46 +00:00
|
|
|
}
|
|
|
|
|
2011-07-18 17:02:57 +00:00
|
|
|
DefInit *Record::getDefInit() {
|
|
|
|
if (!TheInit)
|
|
|
|
TheInit = new DefInit(this, new RecordRecTy(this));
|
|
|
|
return TheInit;
|
|
|
|
}
|
|
|
|
|
2011-08-10 18:27:46 +00:00
|
|
|
const std::string &Record::getName() const {
|
2012-10-10 20:24:47 +00:00
|
|
|
const StringInit *NameString = dyn_cast<StringInit>(Name);
|
2011-08-10 18:27:46 +00:00
|
|
|
assert(NameString && "Record name is not a string!");
|
|
|
|
return NameString->getValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Record::setName(Init *NewName) {
|
|
|
|
if (TrackedRecords.getDef(Name->getAsUnquotedString()) == this) {
|
|
|
|
TrackedRecords.removeDef(Name->getAsUnquotedString());
|
2010-12-13 00:23:57 +00:00
|
|
|
TrackedRecords.addDef(this);
|
2011-10-19 13:03:25 +00:00
|
|
|
} else if (TrackedRecords.getClass(Name->getAsUnquotedString()) == this) {
|
2011-08-10 18:27:46 +00:00
|
|
|
TrackedRecords.removeClass(Name->getAsUnquotedString());
|
2010-12-13 00:23:57 +00:00
|
|
|
TrackedRecords.addClass(this);
|
2011-10-19 13:03:25 +00:00
|
|
|
} // Otherwise this isn't yet registered.
|
|
|
|
Name = NewName;
|
2011-08-10 18:27:46 +00:00
|
|
|
checkName();
|
|
|
|
// DO NOT resolve record values to the name at this point because
|
|
|
|
// there might be default values for arguments of this def. Those
|
|
|
|
// arguments might not have been resolved yet so we don't want to
|
|
|
|
// prematurely assume values for those arguments were not passed to
|
|
|
|
// this def.
|
|
|
|
//
|
|
|
|
// Nonetheless, it may be that some of this Record's values
|
|
|
|
// reference the record name. Indeed, the reason for having the
|
|
|
|
// record name be an Init is to provide this flexibility. The extra
|
|
|
|
// resolve steps after completely instantiating defs takes care of
|
|
|
|
// this. See TGParser::ParseDef and TGParser::ParseDefm.
|
|
|
|
}
|
|
|
|
|
|
|
|
void Record::setName(const std::string &Name) {
|
|
|
|
setName(StringInit::get(Name));
|
2011-10-19 13:02:29 +00:00
|
|
|
}
|
|
|
|
|
2005-04-19 03:36:21 +00:00
|
|
|
/// 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 Record::resolveReferencesTo(const RecordVal *RV) {
|
|
|
|
for (unsigned i = 0, e = Values.size(); i != e; ++i) {
|
2012-03-07 16:39:35 +00:00
|
|
|
if (RV == &Values[i]) // Skip resolve the same field as the given one
|
|
|
|
continue;
|
2011-07-29 22:43:06 +00:00
|
|
|
if (Init *V = Values[i].getValue())
|
Re-work bit/bits value resolving in tblgen
- This patch is inspired by the failure of the following code snippet
which is used to convert enumerable values into encoding bits to
improve the readability of td files.
class S<int s> {
bits<2> V = !if(!eq(s, 8), {0, 0},
!if(!eq(s, 16), {0, 1},
!if(!eq(s, 32), {1, 0},
!if(!eq(s, 64), {1, 1}, {?, ?}))));
}
Later, PR8330 is found to report not exactly the same bug relevant
issue to bit/bits values.
- Instead of resolving bit/bits values separately through
resolveBitReference(), this patch adds getBit() for all Inits and
resolves bit value by resolving plus getting the specified bit. This
unifies the resolving of bit with other values and removes redundant
logic for resolving bit only. In addition,
BitsInit::resolveReferences() is optimized to take advantage of this
origanization by resolving VarBitInit's variable reference first and
then getting bits from it.
- The type interference in '!if' operator is revised to support possible
combinations of int and bits/bit in MHS and RHS.
- As there may be illegal assignments from integer value to bit, says
assign 2 to a bit, but we only check this during instantiation in some
cases, e.g.
bit V = !if(!eq(x, 17), 0, 2);
Verbose diagnostic message is generated when invalid value is
resolveed to help locating the error.
- PR8330 is fixed as well.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8
2012-09-06 23:32:48 +00:00
|
|
|
if (Values[i].setValue(V->resolveReferences(*this, RV)))
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Invalid value is found when setting '"
|
Re-work bit/bits value resolving in tblgen
- This patch is inspired by the failure of the following code snippet
which is used to convert enumerable values into encoding bits to
improve the readability of td files.
class S<int s> {
bits<2> V = !if(!eq(s, 8), {0, 0},
!if(!eq(s, 16), {0, 1},
!if(!eq(s, 32), {1, 0},
!if(!eq(s, 64), {1, 1}, {?, ?}))));
}
Later, PR8330 is found to report not exactly the same bug relevant
issue to bit/bits values.
- Instead of resolving bit/bits values separately through
resolveBitReference(), this patch adds getBit() for all Inits and
resolves bit value by resolving plus getting the specified bit. This
unifies the resolving of bit with other values and removes redundant
logic for resolving bit only. In addition,
BitsInit::resolveReferences() is optimized to take advantage of this
origanization by resolving VarBitInit's variable reference first and
then getting bits from it.
- The type interference in '!if' operator is revised to support possible
combinations of int and bits/bit in MHS and RHS.
- As there may be illegal assignments from integer value to bit, says
assign 2 to a bit, but we only check this during instantiation in some
cases, e.g.
bit V = !if(!eq(x, 17), 0, 2);
Verbose diagnostic message is generated when invalid value is
resolveed to help locating the error.
- PR8330 is fixed as well.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163360 91177308-0d34-0410-b5e6-96231b3b80d8
2012-09-06 23:32:48 +00:00
|
|
|
+ Values[i].getNameInitAsString()
|
|
|
|
+ "' after resolving references"
|
|
|
|
+ (RV ? " against '" + RV->getNameInitAsString()
|
|
|
|
+ "' of ("
|
|
|
|
+ RV->getValue()->getAsUnquotedString() + ")"
|
|
|
|
: "")
|
|
|
|
+ "\n");
|
2005-04-19 03:36:21 +00:00
|
|
|
}
|
2011-10-19 13:03:30 +00:00
|
|
|
Init *OldName = getNameInit();
|
|
|
|
Init *NewName = Name->resolveReferences(*this, RV);
|
|
|
|
if (NewName != OldName) {
|
|
|
|
// Re-register with RecordKeeper.
|
|
|
|
setName(NewName);
|
|
|
|
}
|
2002-12-02 01:23:04 +00:00
|
|
|
}
|
|
|
|
|
2009-07-03 00:10:29 +00:00
|
|
|
void Record::dump() const { errs() << *this; }
|
2002-12-02 01:23:04 +00:00
|
|
|
|
2009-07-03 00:10:29 +00:00
|
|
|
raw_ostream &llvm::operator<<(raw_ostream &OS, const Record &R) {
|
2011-10-19 13:02:57 +00:00
|
|
|
OS << R.getNameInitAsString();
|
2002-12-02 01:23:04 +00:00
|
|
|
|
2011-10-19 13:02:42 +00:00
|
|
|
const std::vector<Init *> &TArgs = R.getTemplateArgs();
|
2002-12-02 01:23:04 +00:00
|
|
|
if (!TArgs.empty()) {
|
|
|
|
OS << "<";
|
|
|
|
for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
|
|
|
|
if (i) OS << ", ";
|
|
|
|
const RecordVal *RV = R.getValue(TArgs[i]);
|
|
|
|
assert(RV && "Template argument record not found??");
|
|
|
|
RV->print(OS, false);
|
|
|
|
}
|
|
|
|
OS << ">";
|
|
|
|
}
|
|
|
|
|
|
|
|
OS << " {";
|
|
|
|
const std::vector<Record*> &SC = R.getSuperClasses();
|
|
|
|
if (!SC.empty()) {
|
|
|
|
OS << "\t//";
|
|
|
|
for (unsigned i = 0, e = SC.size(); i != e; ++i)
|
2011-10-19 13:03:02 +00:00
|
|
|
OS << " " << SC[i]->getNameInitAsString();
|
2002-12-02 01:23:04 +00:00
|
|
|
}
|
|
|
|
OS << "\n";
|
|
|
|
|
|
|
|
const std::vector<RecordVal> &Vals = R.getValues();
|
|
|
|
for (unsigned i = 0, e = Vals.size(); i != e; ++i)
|
|
|
|
if (Vals[i].getPrefix() && !R.isTemplateArg(Vals[i].getName()))
|
|
|
|
OS << Vals[i];
|
|
|
|
for (unsigned i = 0, e = Vals.size(); i != e; ++i)
|
|
|
|
if (!Vals[i].getPrefix() && !R.isTemplateArg(Vals[i].getName()))
|
|
|
|
OS << Vals[i];
|
|
|
|
|
|
|
|
return OS << "}\n";
|
|
|
|
}
|
|
|
|
|
2003-08-01 06:27:59 +00:00
|
|
|
/// getValueInit - Return the initializer for a value with the specified name,
|
2012-10-25 20:33:17 +00:00
|
|
|
/// or abort if the field does not exist.
|
2003-08-01 06:27:59 +00:00
|
|
|
///
|
2011-07-29 22:43:06 +00:00
|
|
|
Init *Record::getValueInit(StringRef FieldName) const {
|
2003-08-01 06:27:59 +00:00
|
|
|
const RecordVal *R = getValue(FieldName);
|
|
|
|
if (R == 0 || R->getValue() == 0)
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Record `" + getName() +
|
|
|
|
"' does not have a field named `" + FieldName.str() + "'!\n");
|
2003-08-01 06:27:59 +00:00
|
|
|
return R->getValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-08-01 04:37:57 +00:00
|
|
|
/// getValueAsString - This method looks up the specified field and returns its
|
2012-10-25 20:33:17 +00:00
|
|
|
/// value as a string, aborts if the field does not exist or if
|
2003-08-01 04:37:57 +00:00
|
|
|
/// the value is not a string.
|
|
|
|
///
|
2009-09-18 18:31:37 +00:00
|
|
|
std::string Record::getValueAsString(StringRef FieldName) const {
|
2003-08-01 04:37:57 +00:00
|
|
|
const RecordVal *R = getValue(FieldName);
|
|
|
|
if (R == 0 || R->getValue() == 0)
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Record `" + getName() +
|
|
|
|
"' does not have a field named `" + FieldName.str() + "'!\n");
|
2003-08-01 04:37:57 +00:00
|
|
|
|
2012-10-10 20:24:43 +00:00
|
|
|
if (StringInit *SI = dyn_cast<StringInit>(R->getValue()))
|
2003-08-01 04:37:57 +00:00
|
|
|
return SI->getValue();
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
|
|
|
|
FieldName.str() + "' does not have a string initializer!");
|
2003-08-01 04:37:57 +00:00
|
|
|
}
|
|
|
|
|
2003-08-01 04:46:24 +00:00
|
|
|
/// getValueAsBitsInit - This method looks up the specified field and returns
|
2012-10-25 20:33:17 +00:00
|
|
|
/// its value as a BitsInit, aborts if the field does not exist or if
|
|
|
|
/// the value is not the right type.
|
2003-08-01 04:46:24 +00:00
|
|
|
///
|
2011-07-29 22:43:06 +00:00
|
|
|
BitsInit *Record::getValueAsBitsInit(StringRef FieldName) const {
|
2003-08-01 04:46:24 +00:00
|
|
|
const RecordVal *R = getValue(FieldName);
|
|
|
|
if (R == 0 || R->getValue() == 0)
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Record `" + getName() +
|
|
|
|
"' does not have a field named `" + FieldName.str() + "'!\n");
|
2003-08-01 04:46:24 +00:00
|
|
|
|
2012-10-10 20:24:43 +00:00
|
|
|
if (BitsInit *BI = dyn_cast<BitsInit>(R->getValue()))
|
2003-08-01 04:46:24 +00:00
|
|
|
return BI;
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
|
|
|
|
FieldName.str() + "' does not have a BitsInit initializer!");
|
2003-08-01 04:46:24 +00:00
|
|
|
}
|
|
|
|
|
2003-08-01 06:15:10 +00:00
|
|
|
/// getValueAsListInit - This method looks up the specified field and returns
|
2012-10-25 20:33:17 +00:00
|
|
|
/// its value as a ListInit, aborting if the field does not exist or if
|
|
|
|
/// the value is not the right type.
|
2003-08-01 06:15:10 +00:00
|
|
|
///
|
2011-07-29 22:43:06 +00:00
|
|
|
ListInit *Record::getValueAsListInit(StringRef FieldName) const {
|
2003-08-01 06:15:10 +00:00
|
|
|
const RecordVal *R = getValue(FieldName);
|
|
|
|
if (R == 0 || R->getValue() == 0)
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Record `" + getName() +
|
|
|
|
"' does not have a field named `" + FieldName.str() + "'!\n");
|
2003-08-01 06:15:10 +00:00
|
|
|
|
2012-10-10 20:24:43 +00:00
|
|
|
if (ListInit *LI = dyn_cast<ListInit>(R->getValue()))
|
2003-08-01 06:15:10 +00:00
|
|
|
return LI;
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
|
|
|
|
FieldName.str() + "' does not have a list initializer!");
|
2003-08-01 06:15:10 +00:00
|
|
|
}
|
2003-08-01 04:46:24 +00:00
|
|
|
|
2005-10-28 22:49:02 +00:00
|
|
|
/// getValueAsListOfDefs - This method looks up the specified field and returns
|
2012-10-25 20:33:17 +00:00
|
|
|
/// its value as a vector of records, aborting if the field does not exist
|
|
|
|
/// or if the value is not the right type.
|
2005-10-28 21:46:31 +00:00
|
|
|
///
|
2009-11-22 04:24:42 +00:00
|
|
|
std::vector<Record*>
|
2009-09-18 18:31:37 +00:00
|
|
|
Record::getValueAsListOfDefs(StringRef FieldName) const {
|
2011-07-29 22:43:06 +00:00
|
|
|
ListInit *List = getValueAsListInit(FieldName);
|
2005-10-28 21:46:31 +00:00
|
|
|
std::vector<Record*> Defs;
|
|
|
|
for (unsigned i = 0; i < List->getSize(); i++) {
|
2012-10-10 20:24:43 +00:00
|
|
|
if (DefInit *DI = dyn_cast<DefInit>(List->getElement(i))) {
|
2005-10-28 21:46:31 +00:00
|
|
|
Defs.push_back(DI->getDef());
|
|
|
|
} else {
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
|
|
|
|
FieldName.str() + "' list is not entirely DefInit!");
|
2005-10-28 21:46:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return Defs;
|
|
|
|
}
|
|
|
|
|
2003-08-01 06:15:10 +00:00
|
|
|
/// getValueAsInt - This method looks up the specified field and returns its
|
2012-10-25 20:33:17 +00:00
|
|
|
/// value as an int64_t, aborting if the field does not exist or if the value
|
|
|
|
/// is not the right type.
|
2003-08-01 06:15:10 +00:00
|
|
|
///
|
2009-09-18 18:31:37 +00:00
|
|
|
int64_t Record::getValueAsInt(StringRef FieldName) const {
|
2003-08-01 06:15:10 +00:00
|
|
|
const RecordVal *R = getValue(FieldName);
|
|
|
|
if (R == 0 || R->getValue() == 0)
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Record `" + getName() +
|
|
|
|
"' does not have a field named `" + FieldName.str() + "'!\n");
|
2003-08-01 06:15:10 +00:00
|
|
|
|
2012-10-10 20:24:43 +00:00
|
|
|
if (IntInit *II = dyn_cast<IntInit>(R->getValue()))
|
2003-08-01 06:15:10 +00:00
|
|
|
return II->getValue();
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
|
|
|
|
FieldName.str() + "' does not have an int initializer!");
|
2003-08-01 06:15:10 +00:00
|
|
|
}
|
2003-08-01 04:37:57 +00:00
|
|
|
|
2007-11-11 11:19:37 +00:00
|
|
|
/// getValueAsListOfInts - This method looks up the specified field and returns
|
2012-10-25 20:33:17 +00:00
|
|
|
/// its value as a vector of integers, aborting if the field does not exist or
|
|
|
|
/// if the value is not the right type.
|
2007-11-11 11:19:37 +00:00
|
|
|
///
|
2009-11-22 04:24:42 +00:00
|
|
|
std::vector<int64_t>
|
2009-09-18 18:31:37 +00:00
|
|
|
Record::getValueAsListOfInts(StringRef FieldName) const {
|
2011-07-29 22:43:06 +00:00
|
|
|
ListInit *List = getValueAsListInit(FieldName);
|
2008-10-17 01:33:43 +00:00
|
|
|
std::vector<int64_t> Ints;
|
2007-11-11 11:19:37 +00:00
|
|
|
for (unsigned i = 0; i < List->getSize(); i++) {
|
2012-10-10 20:24:43 +00:00
|
|
|
if (IntInit *II = dyn_cast<IntInit>(List->getElement(i))) {
|
2007-11-11 11:19:37 +00:00
|
|
|
Ints.push_back(II->getValue());
|
|
|
|
} else {
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
|
|
|
|
FieldName.str() + "' does not have a list of ints initializer!");
|
2007-11-11 11:19:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return Ints;
|
|
|
|
}
|
|
|
|
|
2011-06-27 21:06:21 +00:00
|
|
|
/// getValueAsListOfStrings - This method looks up the specified field and
|
2012-10-25 20:33:17 +00:00
|
|
|
/// returns its value as a vector of strings, aborting if the field does not
|
|
|
|
/// exist or if the value is not the right type.
|
2011-06-27 21:06:21 +00:00
|
|
|
///
|
|
|
|
std::vector<std::string>
|
|
|
|
Record::getValueAsListOfStrings(StringRef FieldName) const {
|
2011-07-29 22:43:06 +00:00
|
|
|
ListInit *List = getValueAsListInit(FieldName);
|
2011-06-27 21:06:21 +00:00
|
|
|
std::vector<std::string> Strings;
|
|
|
|
for (unsigned i = 0; i < List->getSize(); i++) {
|
2012-10-10 20:24:43 +00:00
|
|
|
if (StringInit *II = dyn_cast<StringInit>(List->getElement(i))) {
|
2011-06-27 21:06:21 +00:00
|
|
|
Strings.push_back(II->getValue());
|
|
|
|
} else {
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
|
|
|
|
FieldName.str() + "' does not have a list of strings initializer!");
|
2011-06-27 21:06:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return Strings;
|
|
|
|
}
|
|
|
|
|
2003-08-02 01:27:37 +00:00
|
|
|
/// getValueAsDef - This method looks up the specified field and returns its
|
2012-10-25 20:33:17 +00:00
|
|
|
/// value as a Record, aborting if the field does not exist or if the value
|
|
|
|
/// is not the right type.
|
2003-08-02 01:27:37 +00:00
|
|
|
///
|
2009-09-18 18:31:37 +00:00
|
|
|
Record *Record::getValueAsDef(StringRef FieldName) const {
|
2003-08-02 01:27:37 +00:00
|
|
|
const RecordVal *R = getValue(FieldName);
|
|
|
|
if (R == 0 || R->getValue() == 0)
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Record `" + getName() +
|
|
|
|
"' does not have a field named `" + FieldName.str() + "'!\n");
|
2003-08-02 01:27:37 +00:00
|
|
|
|
2012-10-10 20:24:43 +00:00
|
|
|
if (DefInit *DI = dyn_cast<DefInit>(R->getValue()))
|
2003-08-02 01:27:37 +00:00
|
|
|
return DI->getDef();
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
|
|
|
|
FieldName.str() + "' does not have a def initializer!");
|
2003-08-02 01:27:37 +00:00
|
|
|
}
|
|
|
|
|
2003-08-03 21:58:13 +00:00
|
|
|
/// getValueAsBit - This method looks up the specified field and returns its
|
2012-10-25 20:33:17 +00:00
|
|
|
/// value as a bit, aborting if the field does not exist or if the value is
|
|
|
|
/// not the right type.
|
2003-08-03 21:58:13 +00:00
|
|
|
///
|
2009-09-18 18:31:37 +00:00
|
|
|
bool Record::getValueAsBit(StringRef FieldName) const {
|
2003-08-03 21:58:13 +00:00
|
|
|
const RecordVal *R = getValue(FieldName);
|
|
|
|
if (R == 0 || R->getValue() == 0)
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Record `" + getName() +
|
|
|
|
"' does not have a field named `" + FieldName.str() + "'!\n");
|
2003-08-03 21:58:13 +00:00
|
|
|
|
2012-10-10 20:24:43 +00:00
|
|
|
if (BitInit *BI = dyn_cast<BitInit>(R->getValue()))
|
2003-08-07 06:00:43 +00:00
|
|
|
return BI->getValue();
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
|
|
|
|
FieldName.str() + "' does not have a bit initializer!");
|
2003-08-07 06:00:43 +00:00
|
|
|
}
|
|
|
|
|
2012-08-23 19:34:46 +00:00
|
|
|
bool Record::getValueAsBitOrUnset(StringRef FieldName, bool &Unset) const {
|
|
|
|
const RecordVal *R = getValue(FieldName);
|
|
|
|
if (R == 0 || R->getValue() == 0)
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Record `" + getName() +
|
|
|
|
"' does not have a field named `" + FieldName.str() + "'!\n");
|
2012-08-23 19:34:46 +00:00
|
|
|
|
|
|
|
if (R->getValue() == UnsetInit::get()) {
|
|
|
|
Unset = true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
Unset = false;
|
2012-10-10 20:24:43 +00:00
|
|
|
if (BitInit *BI = dyn_cast<BitInit>(R->getValue()))
|
2012-08-23 19:34:46 +00:00
|
|
|
return BI->getValue();
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
|
|
|
|
FieldName.str() + "' does not have a bit initializer!");
|
2012-08-23 19:34:46 +00:00
|
|
|
}
|
|
|
|
|
2003-08-07 06:00:43 +00:00
|
|
|
/// getValueAsDag - This method looks up the specified field and returns its
|
2012-10-25 20:33:17 +00:00
|
|
|
/// value as an Dag, aborting if the field does not exist or if the value is
|
|
|
|
/// not the right type.
|
2003-08-07 06:00:43 +00:00
|
|
|
///
|
2011-07-29 22:43:06 +00:00
|
|
|
DagInit *Record::getValueAsDag(StringRef FieldName) const {
|
2003-08-07 06:00:43 +00:00
|
|
|
const RecordVal *R = getValue(FieldName);
|
|
|
|
if (R == 0 || R->getValue() == 0)
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Record `" + getName() +
|
|
|
|
"' does not have a field named `" + FieldName.str() + "'!\n");
|
2003-08-07 06:00:43 +00:00
|
|
|
|
2012-10-10 20:24:43 +00:00
|
|
|
if (DagInit *DI = dyn_cast<DagInit>(R->getValue()))
|
2003-08-07 06:00:43 +00:00
|
|
|
return DI;
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
|
|
|
|
FieldName.str() + "' does not have a dag initializer!");
|
2003-08-03 21:58:13 +00:00
|
|
|
}
|
|
|
|
|
2003-08-02 01:27:37 +00:00
|
|
|
|
2009-04-24 16:55:41 +00:00
|
|
|
void MultiClass::dump() const {
|
2009-07-03 00:10:29 +00:00
|
|
|
errs() << "Record:\n";
|
2009-04-24 16:55:41 +00:00
|
|
|
Rec.dump();
|
2009-11-22 04:24:42 +00:00
|
|
|
|
2009-07-03 00:10:29 +00:00
|
|
|
errs() << "Defs:\n";
|
2009-04-24 16:55:41 +00:00
|
|
|
for (RecordVector::const_iterator r = DefPrototypes.begin(),
|
|
|
|
rend = DefPrototypes.end();
|
|
|
|
r != rend;
|
|
|
|
++r) {
|
|
|
|
(*r)->dump();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-07-03 00:10:29 +00:00
|
|
|
void RecordKeeper::dump() const { errs() << *this; }
|
2002-12-02 01:23:04 +00:00
|
|
|
|
2009-07-03 00:10:29 +00:00
|
|
|
raw_ostream &llvm::operator<<(raw_ostream &OS, const RecordKeeper &RK) {
|
2002-12-02 01:23:04 +00:00
|
|
|
OS << "------------- Classes -----------------\n";
|
|
|
|
const std::map<std::string, Record*> &Classes = RK.getClasses();
|
|
|
|
for (std::map<std::string, Record*>::const_iterator I = Classes.begin(),
|
2005-04-22 04:13:13 +00:00
|
|
|
E = Classes.end(); I != E; ++I)
|
2002-12-02 01:23:04 +00:00
|
|
|
OS << "class " << *I->second;
|
2005-04-22 00:00:37 +00:00
|
|
|
|
2002-12-02 01:23:04 +00:00
|
|
|
OS << "------------- Defs -----------------\n";
|
|
|
|
const std::map<std::string, Record*> &Defs = RK.getDefs();
|
|
|
|
for (std::map<std::string, Record*>::const_iterator I = Defs.begin(),
|
2005-04-22 04:13:13 +00:00
|
|
|
E = Defs.end(); I != E; ++I)
|
2002-12-02 01:23:04 +00:00
|
|
|
OS << "def " << *I->second;
|
|
|
|
return OS;
|
|
|
|
}
|
2003-08-01 04:09:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
/// getAllDerivedDefinitions - This method returns all concrete definitions
|
|
|
|
/// that derive from the specified class name. If a class with the specified
|
|
|
|
/// name does not exist, an error is printed and true is returned.
|
2003-08-01 04:37:57 +00:00
|
|
|
std::vector<Record*>
|
|
|
|
RecordKeeper::getAllDerivedDefinitions(const std::string &ClassName) const {
|
2010-12-13 00:20:52 +00:00
|
|
|
Record *Class = getClass(ClassName);
|
2003-08-01 04:37:57 +00:00
|
|
|
if (!Class)
|
2012-10-25 20:33:17 +00:00
|
|
|
PrintFatalError("ERROR: Couldn't find the `" + ClassName + "' class!\n");
|
2003-08-01 04:09:58 +00:00
|
|
|
|
2003-08-01 04:37:57 +00:00
|
|
|
std::vector<Record*> Defs;
|
2003-08-01 04:09:58 +00:00
|
|
|
for (std::map<std::string, Record*>::const_iterator I = getDefs().begin(),
|
|
|
|
E = getDefs().end(); I != E; ++I)
|
|
|
|
if (I->second->isSubClassOf(Class))
|
|
|
|
Defs.push_back(I->second);
|
|
|
|
|
2003-08-01 04:37:57 +00:00
|
|
|
return Defs;
|
2003-08-01 04:09:58 +00:00
|
|
|
}
|
2003-11-11 22:41:34 +00:00
|
|
|
|
2011-10-19 13:02:36 +00:00
|
|
|
/// QualifyName - Return an Init with a qualifier prefix referring
|
|
|
|
/// to CurRec's name.
|
|
|
|
Init *llvm::QualifyName(Record &CurRec, MultiClass *CurMultiClass,
|
|
|
|
Init *Name, const std::string &Scoper) {
|
2012-10-10 20:24:43 +00:00
|
|
|
RecTy *Type = dyn_cast<TypedInit>(Name)->getType();
|
2011-10-19 13:02:36 +00:00
|
|
|
|
|
|
|
BinOpInit *NewName =
|
|
|
|
BinOpInit::get(BinOpInit::STRCONCAT,
|
|
|
|
BinOpInit::get(BinOpInit::STRCONCAT,
|
|
|
|
CurRec.getNameInit(),
|
|
|
|
StringInit::get(Scoper),
|
|
|
|
Type)->Fold(&CurRec, CurMultiClass),
|
|
|
|
Name,
|
|
|
|
Type);
|
|
|
|
|
|
|
|
if (CurMultiClass && Scoper != "::") {
|
|
|
|
NewName =
|
|
|
|
BinOpInit::get(BinOpInit::STRCONCAT,
|
|
|
|
BinOpInit::get(BinOpInit::STRCONCAT,
|
|
|
|
CurMultiClass->Rec.getNameInit(),
|
|
|
|
StringInit::get("::"),
|
|
|
|
Type)->Fold(&CurRec, CurMultiClass),
|
|
|
|
NewName->Fold(&CurRec, CurMultiClass),
|
|
|
|
Type);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NewName->Fold(&CurRec, CurMultiClass);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// QualifyName - Return an Init with a qualifier prefix referring
|
|
|
|
/// to CurRec's name.
|
|
|
|
Init *llvm::QualifyName(Record &CurRec, MultiClass *CurMultiClass,
|
|
|
|
const std::string &Name,
|
|
|
|
const std::string &Scoper) {
|
|
|
|
return QualifyName(CurRec, CurMultiClass, StringInit::get(Name), Scoper);
|
|
|
|
}
|