TableGen: promote "code" type from syntactic sugar.

It's being immediately converted to a "string", but being able to tell what
type the field was originally can be useful in backends.

llvm-svn: 274575
This commit is contained in:
Tim Northover 2016-07-05 21:22:55 +00:00
parent aaa0191be6
commit 88403d7a84
4 changed files with 89 additions and 5 deletions

View File

@ -44,6 +44,7 @@ public:
enum RecTyKind { enum RecTyKind {
BitRecTyKind, BitRecTyKind,
BitsRecTyKind, BitsRecTyKind,
CodeRecTyKind,
IntRecTyKind, IntRecTyKind,
StringRecTyKind, StringRecTyKind,
ListRecTyKind, ListRecTyKind,
@ -116,6 +117,22 @@ public:
bool typeIsConvertibleTo(const RecTy *RHS) const override; bool typeIsConvertibleTo(const RecTy *RHS) const override;
}; };
/// CodeRecTy - 'code' - Represent a code fragment
///
class CodeRecTy : public RecTy {
static CodeRecTy Shared;
CodeRecTy() : RecTy(CodeRecTyKind) {}
public:
static bool classof(const RecTy *RT) {
return RT->getRecTyKind() == CodeRecTyKind;
}
static CodeRecTy *get() { return &Shared; }
std::string getAsString() const override { return "code"; }
};
/// IntRecTy - 'int' - Represent an integer value of no particular size /// IntRecTy - 'int' - Represent an integer value of no particular size
/// ///
class IntRecTy : public RecTy { class IntRecTy : public RecTy {
@ -142,7 +159,8 @@ class StringRecTy : public RecTy {
public: public:
static bool classof(const RecTy *RT) { static bool classof(const RecTy *RT) {
return RT->getRecTyKind() == StringRecTyKind; return RT->getRecTyKind() == StringRecTyKind ||
RT->getRecTyKind() == CodeRecTyKind;
} }
static StringRecTy *get() { return &Shared; } static StringRecTy *get() { return &Shared; }
@ -237,6 +255,7 @@ protected:
IK_BitInit, IK_BitInit,
IK_FirstTypedInit, IK_FirstTypedInit,
IK_BitsInit, IK_BitsInit,
IK_CodeInit,
IK_DagInit, IK_DagInit,
IK_DefInit, IK_DefInit,
IK_FieldInit, IK_FieldInit,
@ -572,6 +591,46 @@ public:
Init *convertInitializerTo(RecTy *Ty) const override; Init *convertInitializerTo(RecTy *Ty) const override;
std::string getAsString() const override { return "\"" + Value + "\""; } std::string getAsString() const override { return "\"" + Value + "\""; }
std::string getAsUnquotedString() const override { return Value; }
/// resolveListElementReference - This method is used to implement
/// VarListElementInit::resolveReferences. If the list element is resolvable
/// now, we return the resolved value, otherwise we return null.
Init *resolveListElementReference(Record &R, const RecordVal *RV,
unsigned Elt) const override {
llvm_unreachable("Illegal element reference off string");
}
Init *getBit(unsigned Bit) const override {
llvm_unreachable("Illegal bit reference off string");
}
};
class CodeInit : public TypedInit {
std::string Value;
explicit CodeInit(StringRef V)
: TypedInit(IK_CodeInit, static_cast<RecTy *>(CodeRecTy::get())),
Value(V) {}
CodeInit(const StringInit &Other) = delete;
CodeInit &operator=(const StringInit &Other) = delete;
public:
static bool classof(const Init *I) {
return I->getKind() == IK_CodeInit;
}
static CodeInit *get(StringRef);
const std::string &getValue() const { return Value; }
Init *convertInitializerTo(RecTy *Ty) const override;
std::string getAsString() const override {
return "[{" + Value + "}]";
}
std::string getAsUnquotedString() const override { return Value; } std::string getAsUnquotedString() const override { return Value; }
/// resolveListElementReference - This method is used to implement /// resolveListElementReference - This method is used to implement

View File

@ -82,6 +82,7 @@ template<> struct DenseMapInfo<TableGenStringKey> {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
BitRecTy BitRecTy::Shared; BitRecTy BitRecTy::Shared;
CodeRecTy CodeRecTy::Shared;
IntRecTy IntRecTy::Shared; IntRecTy IntRecTy::Shared;
StringRecTy StringRecTy::Shared; StringRecTy StringRecTy::Shared;
DagRecTy DagRecTy::Shared; DagRecTy DagRecTy::Shared;
@ -453,6 +454,14 @@ IntInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) const {
return BitsInit::get(NewBits); return BitsInit::get(NewBits);
} }
CodeInit *CodeInit::get(StringRef V) {
static StringMap<std::unique_ptr<CodeInit>> ThePool;
std::unique_ptr<CodeInit> &I = ThePool[V];
if (!I) I.reset(new CodeInit(V));
return I.get();
}
StringInit *StringInit::get(StringRef V) { StringInit *StringInit::get(StringRef V) {
static StringMap<std::unique_ptr<StringInit>> ThePool; static StringMap<std::unique_ptr<StringInit>> ThePool;
@ -468,6 +477,13 @@ Init *StringInit::convertInitializerTo(RecTy *Ty) const {
return nullptr; return nullptr;
} }
Init *CodeInit::convertInitializerTo(RecTy *Ty) const {
if (isa<CodeRecTy>(Ty))
return const_cast<CodeInit *>(this);
return nullptr;
}
static void ProfileListInit(FoldingSetNodeID &ID, static void ProfileListInit(FoldingSetNodeID &ID,
ArrayRef<Init *> Range, ArrayRef<Init *> Range,
RecTy *EltTy) { RecTy *EltTy) {
@ -1158,6 +1174,12 @@ TypedInit::convertInitializerTo(RecTy *Ty) const {
return nullptr; return nullptr;
} }
if (isa<CodeRecTy>(Ty)) {
if (isa<CodeRecTy>(getType()))
return const_cast<TypedInit *>(this);
return nullptr;
}
if (isa<BitRecTy>(Ty)) { if (isa<BitRecTy>(Ty)) {
// Accept variable if it is already of bit type! // Accept variable if it is already of bit type!
if (isa<BitRecTy>(getType())) if (isa<BitRecTy>(getType()))
@ -1744,6 +1766,9 @@ std::string Record::getValueAsString(StringRef FieldName) const {
if (StringInit *SI = dyn_cast<StringInit>(R->getValue())) if (StringInit *SI = dyn_cast<StringInit>(R->getValue()))
return SI->getValue(); return SI->getValue();
if (CodeInit *CI = dyn_cast<CodeInit>(R->getValue()))
return CI->getValue();
PrintFatalError(getLoc(), "Record `" + getName() + "', field `" + PrintFatalError(getLoc(), "Record `" + getName() + "', field `" +
FieldName + "' does not have a string initializer!"); FieldName + "' does not have a string initializer!");
} }

View File

@ -660,7 +660,7 @@ RecTy *TGParser::ParseType() {
switch (Lex.getCode()) { switch (Lex.getCode()) {
default: TokError("Unknown token when expecting a type"); return nullptr; default: TokError("Unknown token when expecting a type"); return nullptr;
case tgtok::String: Lex.Lex(); return StringRecTy::get(); case tgtok::String: Lex.Lex(); return StringRecTy::get();
case tgtok::Code: Lex.Lex(); return StringRecTy::get(); case tgtok::Code: Lex.Lex(); return CodeRecTy::get();
case tgtok::Bit: Lex.Lex(); return BitRecTy::get(); case tgtok::Bit: Lex.Lex(); return BitRecTy::get();
case tgtok::Int: Lex.Lex(); return IntRecTy::get(); case tgtok::Int: Lex.Lex(); return IntRecTy::get();
case tgtok::Dag: Lex.Lex(); return DagRecTy::get(); case tgtok::Dag: Lex.Lex(); return DagRecTy::get();
@ -1164,7 +1164,7 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType,
break; break;
} }
case tgtok::CodeFragment: case tgtok::CodeFragment:
R = StringInit::get(Lex.getCurStrVal()); R = CodeInit::get(Lex.getCurStrVal());
Lex.Lex(); Lex.Lex();
break; break;
case tgtok::question: case tgtok::question:

View File

@ -1078,7 +1078,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
for (unsigned i = 0; i < MCOpPredicates.size(); ++i) { for (unsigned i = 0; i < MCOpPredicates.size(); ++i) {
Init *MCOpPred = MCOpPredicates[i]->getValueInit("MCOperandPredicate"); Init *MCOpPred = MCOpPredicates[i]->getValueInit("MCOperandPredicate");
if (StringInit *SI = dyn_cast<StringInit>(MCOpPred)) { if (CodeInit *SI = dyn_cast<CodeInit>(MCOpPred)) {
O << " case " << i + 1 << ": {\n" O << " case " << i + 1 << ": {\n"
<< SI->getValue() << "\n" << SI->getValue() << "\n"
<< " }\n"; << " }\n";