From 7c788888872233748da10a8177a9a1eb176c1bc8 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Sat, 1 Oct 2011 16:41:13 +0000 Subject: Move TableGen's parser and entry point into a library This is the first step towards splitting LLVM and Clang's tblgen executables. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@140951 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 1 + Makefile | 6 +- include/llvm/TableGen/Error.h | 43 + include/llvm/TableGen/Main.h | 26 + include/llvm/TableGen/Record.h | 1655 +++++++++++++++++++++ include/llvm/TableGen/TableGenAction.h | 34 + include/llvm/TableGen/TableGenBackend.h | 43 + lib/CMakeLists.txt | 2 +- lib/TableGen/CMakeLists.txt | 16 + lib/TableGen/Error.cpp | 39 + lib/TableGen/Main.cpp | 124 ++ lib/TableGen/Makefile | 18 + lib/TableGen/Record.cpp | 2009 ++++++++++++++++++++++++++ lib/TableGen/TGLexer.cpp | 435 ++++++ lib/TableGen/TGLexer.h | 125 ++ lib/TableGen/TGParser.cpp | 2163 ++++++++++++++++++++++++++++ lib/TableGen/TGParser.h | 122 ++ lib/TableGen/TableGenBackend.cpp | 25 + utils/TableGen/ARMDecoderEmitter.cpp | 2 +- utils/TableGen/ARMDecoderEmitter.h | 3 +- utils/TableGen/AsmMatcherEmitter.cpp | 4 +- utils/TableGen/AsmMatcherEmitter.h | 2 +- utils/TableGen/AsmWriterEmitter.cpp | 4 +- utils/TableGen/AsmWriterEmitter.h | 2 +- utils/TableGen/AsmWriterInst.cpp | 2 +- utils/TableGen/CMakeLists.txt | 8 +- utils/TableGen/CallingConvEmitter.cpp | 2 +- utils/TableGen/CallingConvEmitter.h | 2 +- utils/TableGen/ClangASTNodesEmitter.h | 4 +- utils/TableGen/ClangAttrEmitter.cpp | 2 +- utils/TableGen/ClangAttrEmitter.h | 2 +- utils/TableGen/ClangDiagnosticsEmitter.cpp | 2 +- utils/TableGen/ClangDiagnosticsEmitter.h | 2 +- utils/TableGen/ClangSACheckersEmitter.cpp | 2 +- utils/TableGen/ClangSACheckersEmitter.h | 2 +- utils/TableGen/CodeEmitterGen.cpp | 2 +- utils/TableGen/CodeEmitterGen.h | 2 +- utils/TableGen/CodeGenDAGPatterns.cpp | 4 +- utils/TableGen/CodeGenInstruction.cpp | 4 +- utils/TableGen/CodeGenRegisters.cpp | 2 +- utils/TableGen/CodeGenRegisters.h | 2 +- utils/TableGen/CodeGenTarget.cpp | 2 +- utils/TableGen/CodeGenTarget.h | 2 +- utils/TableGen/DAGISelEmitter.cpp | 2 +- utils/TableGen/DAGISelEmitter.h | 2 +- utils/TableGen/DAGISelMatcher.cpp | 2 +- utils/TableGen/DAGISelMatcherEmitter.cpp | 2 +- utils/TableGen/DAGISelMatcherGen.cpp | 2 +- utils/TableGen/DisassemblerEmitter.cpp | 4 +- utils/TableGen/DisassemblerEmitter.h | 2 +- utils/TableGen/EDEmitter.cpp | 2 +- utils/TableGen/EDEmitter.h | 2 +- utils/TableGen/Error.cpp | 39 - utils/TableGen/Error.h | 43 - utils/TableGen/FastISelEmitter.cpp | 4 +- utils/TableGen/FastISelEmitter.h | 2 +- utils/TableGen/FixedLenDecoderEmitter.cpp | 2 +- utils/TableGen/FixedLenDecoderEmitter.h | 2 +- utils/TableGen/InstrEnumEmitter.cpp | 2 +- utils/TableGen/InstrEnumEmitter.h | 2 +- utils/TableGen/InstrInfoEmitter.cpp | 2 +- utils/TableGen/InstrInfoEmitter.h | 2 +- utils/TableGen/IntrinsicEmitter.cpp | 2 +- utils/TableGen/IntrinsicEmitter.h | 2 +- utils/TableGen/Makefile | 2 +- utils/TableGen/NeonEmitter.cpp | 2 +- utils/TableGen/NeonEmitter.h | 4 +- utils/TableGen/OptParserEmitter.cpp | 2 +- utils/TableGen/OptParserEmitter.h | 2 +- utils/TableGen/PseudoLoweringEmitter.cpp | 4 +- utils/TableGen/PseudoLoweringEmitter.h | 2 +- utils/TableGen/Record.cpp | 2009 -------------------------- utils/TableGen/Record.h | 1656 --------------------- utils/TableGen/RegisterInfoEmitter.cpp | 2 +- utils/TableGen/RegisterInfoEmitter.h | 2 +- utils/TableGen/SetTheory.cpp | 4 +- utils/TableGen/SubtargetEmitter.cpp | 2 +- utils/TableGen/SubtargetEmitter.h | 2 +- utils/TableGen/TGLexer.cpp | 435 ------ utils/TableGen/TGLexer.h | 125 -- utils/TableGen/TGParser.cpp | 2163 ---------------------------- utils/TableGen/TGParser.h | 122 -- utils/TableGen/TableGen.cpp | 205 +-- utils/TableGen/TableGenBackend.cpp | 25 - utils/TableGen/TableGenBackend.h | 43 - utils/TableGen/X86DisassemblerTables.cpp | 2 +- utils/TableGen/X86RecognizableInstr.h | 2 +- 87 files changed, 7011 insertions(+), 6883 deletions(-) create mode 100644 include/llvm/TableGen/Error.h create mode 100644 include/llvm/TableGen/Main.h create mode 100644 include/llvm/TableGen/Record.h create mode 100644 include/llvm/TableGen/TableGenAction.h create mode 100644 include/llvm/TableGen/TableGenBackend.h create mode 100644 lib/TableGen/CMakeLists.txt create mode 100644 lib/TableGen/Error.cpp create mode 100644 lib/TableGen/Main.cpp create mode 100644 lib/TableGen/Makefile create mode 100644 lib/TableGen/Record.cpp create mode 100644 lib/TableGen/TGLexer.cpp create mode 100644 lib/TableGen/TGLexer.h create mode 100644 lib/TableGen/TGParser.cpp create mode 100644 lib/TableGen/TGParser.h create mode 100644 lib/TableGen/TableGenBackend.cpp delete mode 100644 utils/TableGen/Error.cpp delete mode 100644 utils/TableGen/Error.h delete mode 100644 utils/TableGen/Record.cpp delete mode 100644 utils/TableGen/Record.h delete mode 100644 utils/TableGen/TGLexer.cpp delete mode 100644 utils/TableGen/TGLexer.h delete mode 100644 utils/TableGen/TGParser.cpp delete mode 100644 utils/TableGen/TGParser.h delete mode 100644 utils/TableGen/TableGenBackend.cpp delete mode 100644 utils/TableGen/TableGenBackend.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e767ce0d24f..874f381a21c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -195,6 +195,7 @@ endif() # Put this before tblgen. Else we have a circular dependence. add_subdirectory(lib/Support) +add_subdirectory(lib/TableGen) set(LLVM_TABLEGEN "tblgen" CACHE STRING "Native TableGen executable. Saves building one when cross-compiling.") diff --git a/Makefile b/Makefile index 610deba36bb..2a36a7a26ee 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ LEVEL := . # Top-Level LLVM Build Stages: -# 1. Build lib/Support, which is used by utils (tblgen). +# 1. Build lib/Support and lib/TableGen, which are used by utils (tblgen). # 2. Build utils, which is used by VMCore. # 3. Build VMCore, which builds the Intrinsics.inc file used by libs. # 4. Build libs, which are needed by llvm-config. @@ -27,10 +27,10 @@ LEVEL := . ifneq ($(findstring llvmCore, $(RC_ProjectName)),llvmCore) # Normal build (not "Apple-style"). ifeq ($(BUILD_DIRS_ONLY),1) - DIRS := lib/Support utils + DIRS := lib/Support lib/TableGen utils OPTIONAL_DIRS := else - DIRS := lib/Support utils lib/VMCore lib tools/llvm-shlib \ + DIRS := lib/Support lib/TableGen utils lib/VMCore lib tools/llvm-shlib \ tools/llvm-config tools runtime docs unittests OPTIONAL_DIRS := projects bindings endif diff --git a/include/llvm/TableGen/Error.h b/include/llvm/TableGen/Error.h new file mode 100644 index 00000000000..c01b32b1c2d --- /dev/null +++ b/include/llvm/TableGen/Error.h @@ -0,0 +1,43 @@ +//===- llvm/TableGen/Error.h - tblgen error handling helpers ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains error handling helper routines to pretty-print diagnostic +// messages from tblgen. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TABLEGEN_ERROR_H +#define LLVM_TABLEGEN_ERROR_H + +#include "llvm/Support/SourceMgr.h" + +namespace llvm { + +class TGError { + SMLoc Loc; + std::string Message; +public: + TGError(SMLoc loc, const std::string &message) : Loc(loc), Message(message) {} + + SMLoc getLoc() const { return Loc; } + const std::string &getMessage() const { return Message; } +}; + +void PrintError(SMLoc ErrorLoc, const Twine &Msg); +void PrintError(const char *Loc, const Twine &Msg); +void PrintError(const Twine &Msg); +void PrintError(const TGError &Error); + + +extern SourceMgr SrcMgr; + + +} // end namespace "llvm" + +#endif diff --git a/include/llvm/TableGen/Main.h b/include/llvm/TableGen/Main.h new file mode 100644 index 00000000000..deaef4a9908 --- /dev/null +++ b/include/llvm/TableGen/Main.h @@ -0,0 +1,26 @@ +//===- llvm/TableGen/Main.h - tblgen entry point ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the common entry point for tblgen tools. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TABLEGEN_MAIN_H +#define LLVM_TABLEGEN_MAIN_H + +namespace llvm { + +class TableGenAction; + +/// Run the table generator, performing the specified Action on parsed records. +int TableGenMain(char *argv0, TableGenAction &Action); + +} + +#endif diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h new file mode 100644 index 00000000000..afce7609986 --- /dev/null +++ b/include/llvm/TableGen/Record.h @@ -0,0 +1,1655 @@ +//===- llvm/TableGen/Record.h - Classes for Table Records -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the main TableGen data structures, including the TableGen +// types, values, and high-level data structures. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TABLEGEN_RECORD_H +#define LLVM_TABLEGEN_RECORD_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/raw_ostream.h" +#include + +namespace llvm { +class raw_ostream; + +// RecTy subclasses. +class BitRecTy; +class BitsRecTy; +class IntRecTy; +class StringRecTy; +class ListRecTy; +class CodeRecTy; +class DagRecTy; +class RecordRecTy; + +// Init subclasses. +class Init; +class UnsetInit; +class BitInit; +class BitsInit; +class IntInit; +class StringInit; +class CodeInit; +class ListInit; +class UnOpInit; +class BinOpInit; +class TernOpInit; +class DefInit; +class DagInit; +class TypedInit; +class VarInit; +class FieldInit; +class VarBitInit; +class VarListElementInit; + +// Other classes. +class Record; +class RecordVal; +struct MultiClass; +class RecordKeeper; + +//===----------------------------------------------------------------------===// +// Type Classes +//===----------------------------------------------------------------------===// + +class RecTy { + ListRecTy *ListTy; +public: + RecTy() : ListTy(0) {} + virtual ~RecTy() {} + + virtual std::string getAsString() const = 0; + void print(raw_ostream &OS) const { OS << getAsString(); } + void dump() const; + + /// typeIsConvertibleTo - Return true if all values of 'this' type can be + /// converted to the specified type. + virtual bool typeIsConvertibleTo(const RecTy *RHS) const = 0; + + /// getListTy - Returns the type representing list. + ListRecTy *getListTy(); + +public: // These methods should only be called from subclasses of Init + virtual Init *convertValue( UnsetInit *UI) { return 0; } + virtual Init *convertValue( BitInit *BI) { return 0; } + virtual Init *convertValue( BitsInit *BI) { return 0; } + virtual Init *convertValue( IntInit *II) { return 0; } + virtual Init *convertValue(StringInit *SI) { return 0; } + virtual Init *convertValue( ListInit *LI) { return 0; } + virtual Init *convertValue( UnOpInit *UI) { + return convertValue((TypedInit*)UI); + } + virtual Init *convertValue( BinOpInit *UI) { + return convertValue((TypedInit*)UI); + } + virtual Init *convertValue( TernOpInit *UI) { + return convertValue((TypedInit*)UI); + } + virtual Init *convertValue( CodeInit *CI) { return 0; } + virtual Init *convertValue(VarBitInit *VB) { return 0; } + virtual Init *convertValue( DefInit *DI) { return 0; } + virtual Init *convertValue( DagInit *DI) { return 0; } + virtual Init *convertValue( TypedInit *TI) { return 0; } + virtual Init *convertValue( VarInit *VI) { + return convertValue((TypedInit*)VI); + } + virtual Init *convertValue( FieldInit *FI) { + return convertValue((TypedInit*)FI); + } + +public: // These methods should only be called by subclasses of RecTy. + // baseClassOf - These virtual methods should be overloaded to return true iff + // all values of type 'RHS' can be converted to the 'this' type. + virtual bool baseClassOf(const BitRecTy *RHS) const { return false; } + virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; } + virtual bool baseClassOf(const IntRecTy *RHS) const { return false; } + virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } + virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } + virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; } + virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } + virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const RecTy &Ty) { + Ty.print(OS); + return OS; +} + + +/// BitRecTy - 'bit' - Represent a single bit +/// +class BitRecTy : public RecTy { + static BitRecTy Shared; + BitRecTy() {} +public: + static BitRecTy *get() { return &Shared; } + + virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } + virtual Init *convertValue( BitInit *BI) { return (Init*)BI; } + virtual Init *convertValue( BitsInit *BI); + virtual Init *convertValue( IntInit *II); + virtual Init *convertValue(StringInit *SI) { return 0; } + virtual Init *convertValue( ListInit *LI) { return 0; } + virtual Init *convertValue( CodeInit *CI) { return 0; } + virtual Init *convertValue(VarBitInit *VB) { return (Init*)VB; } + virtual Init *convertValue( DefInit *DI) { return 0; } + virtual Init *convertValue( DagInit *DI) { return 0; } + virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);} + virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} + virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);} + virtual Init *convertValue( TypedInit *TI); + virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} + virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} + + std::string getAsString() const { return "bit"; } + + bool typeIsConvertibleTo(const RecTy *RHS) const { + return RHS->baseClassOf(this); + } + virtual bool baseClassOf(const BitRecTy *RHS) const { return true; } + virtual bool baseClassOf(const BitsRecTy *RHS) const; + virtual bool baseClassOf(const IntRecTy *RHS) const { return true; } + virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } + virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } + virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; } + virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } + virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } + +}; + + +// BitsRecTy - 'bits' - Represent a fixed number of bits +/// BitsRecTy - 'bits<n>' - Represent a fixed number of bits +/// +class BitsRecTy : public RecTy { + unsigned Size; + explicit BitsRecTy(unsigned Sz) : Size(Sz) {} +public: + static BitsRecTy *get(unsigned Sz); + + unsigned getNumBits() const { return Size; } + + virtual Init *convertValue( UnsetInit *UI); + virtual Init *convertValue( BitInit *UI); + virtual Init *convertValue( BitsInit *BI); + virtual Init *convertValue( IntInit *II); + virtual Init *convertValue(StringInit *SI) { return 0; } + virtual Init *convertValue( ListInit *LI) { return 0; } + virtual Init *convertValue( CodeInit *CI) { return 0; } + virtual Init *convertValue(VarBitInit *VB) { return 0; } + virtual Init *convertValue( DefInit *DI) { return 0; } + virtual Init *convertValue( DagInit *DI) { return 0; } + virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);} + virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} + virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);} + virtual Init *convertValue( TypedInit *TI); + virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} + virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} + + std::string getAsString() const; + + bool typeIsConvertibleTo(const RecTy *RHS) const { + return RHS->baseClassOf(this); + } + virtual bool baseClassOf(const BitRecTy *RHS) const { return Size == 1; } + virtual bool baseClassOf(const BitsRecTy *RHS) const { + return RHS->Size == Size; + } + virtual bool baseClassOf(const IntRecTy *RHS) const { return true; } + virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } + virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } + virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; } + virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } + virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } + +}; + + +/// IntRecTy - 'int' - Represent an integer value of no particular size +/// +class IntRecTy : public RecTy { + static IntRecTy Shared; + IntRecTy() {} +public: + static IntRecTy *get() { return &Shared; } + + virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } + virtual Init *convertValue( BitInit *BI); + virtual Init *convertValue( BitsInit *BI); + virtual Init *convertValue( IntInit *II) { return (Init*)II; } + virtual Init *convertValue(StringInit *SI) { return 0; } + virtual Init *convertValue( ListInit *LI) { return 0; } + virtual Init *convertValue( CodeInit *CI) { return 0; } + virtual Init *convertValue(VarBitInit *VB) { return 0; } + virtual Init *convertValue( DefInit *DI) { return 0; } + virtual Init *convertValue( DagInit *DI) { return 0; } + virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);} + virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} + virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);} + virtual Init *convertValue( TypedInit *TI); + virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} + virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} + + std::string getAsString() const { return "int"; } + + bool typeIsConvertibleTo(const RecTy *RHS) const { + return RHS->baseClassOf(this); + } + + virtual bool baseClassOf(const BitRecTy *RHS) const { return true; } + virtual bool baseClassOf(const BitsRecTy *RHS) const { return true; } + virtual bool baseClassOf(const IntRecTy *RHS) const { return true; } + virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } + virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } + virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; } + virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } + virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } + +}; + +/// StringRecTy - 'string' - Represent an string value +/// +class StringRecTy : public RecTy { + static StringRecTy Shared; + StringRecTy() {} +public: + static StringRecTy *get() { return &Shared; } + + virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } + virtual Init *convertValue( BitInit *BI) { return 0; } + virtual Init *convertValue( BitsInit *BI) { return 0; } + virtual Init *convertValue( IntInit *II) { return 0; } + virtual Init *convertValue(StringInit *SI) { return (Init*)SI; } + virtual Init *convertValue( ListInit *LI) { return 0; } + virtual Init *convertValue( UnOpInit *BO); + virtual Init *convertValue( BinOpInit *BO); + virtual Init *convertValue( TernOpInit *BO) { return RecTy::convertValue(BO);} + + virtual Init *convertValue( CodeInit *CI) { return 0; } + virtual Init *convertValue(VarBitInit *VB) { return 0; } + virtual Init *convertValue( DefInit *DI) { return 0; } + virtual Init *convertValue( DagInit *DI) { return 0; } + virtual Init *convertValue( TypedInit *TI); + virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} + virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} + + std::string getAsString() const { return "string"; } + + bool typeIsConvertibleTo(const RecTy *RHS) const { + return RHS->baseClassOf(this); + } + + virtual bool baseClassOf(const BitRecTy *RHS) const { return false; } + virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; } + virtual bool baseClassOf(const IntRecTy *RHS) const { return false; } + virtual bool baseClassOf(const StringRecTy *RHS) const { return true; } + virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } + virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; } + virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } + virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } +}; + +// ListRecTy - 'list' - Represent a list of values, all of which must be of +// the specified type. +/// ListRecTy - 'list<Ty>' - Represent a list of values, all of which must +/// be of the specified type. +/// +class ListRecTy : public RecTy { + RecTy *Ty; + explicit ListRecTy(RecTy *T) : Ty(T) {} + friend ListRecTy *RecTy::getListTy(); +public: + static ListRecTy *get(RecTy *T) { return T->getListTy(); } + RecTy *getElementType() const { return Ty; } + + virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } + virtual Init *convertValue( BitInit *BI) { return 0; } + virtual Init *convertValue( BitsInit *BI) { return 0; } + virtual Init *convertValue( IntInit *II) { return 0; } + virtual Init *convertValue(StringInit *SI) { return 0; } + virtual Init *convertValue( ListInit *LI); + virtual Init *convertValue( CodeInit *CI) { return 0; } + virtual Init *convertValue(VarBitInit *VB) { return 0; } + virtual Init *convertValue( DefInit *DI) { return 0; } + virtual Init *convertValue( DagInit *DI) { return 0; } + virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);} + virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} + virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);} + virtual Init *convertValue( TypedInit *TI); + virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} + virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} + + std::string getAsString() const; + + bool typeIsConvertibleTo(const RecTy *RHS) const { + return RHS->baseClassOf(this); + } + + virtual bool baseClassOf(const BitRecTy *RHS) const { return false; } + virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; } + virtual bool baseClassOf(const IntRecTy *RHS) const { return false; } + virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } + virtual bool baseClassOf(const ListRecTy *RHS) const { + return RHS->getElementType()->typeIsConvertibleTo(Ty); + } + virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; } + virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } + virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } +}; + +/// CodeRecTy - 'code' - Represent an code fragment, function or method. +/// +class CodeRecTy : public RecTy { + static CodeRecTy Shared; + CodeRecTy() {} +public: + static CodeRecTy *get() { return &Shared; } + + virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } + virtual Init *convertValue( BitInit *BI) { return 0; } + virtual Init *convertValue( BitsInit *BI) { return 0; } + virtual Init *convertValue( IntInit *II) { return 0; } + virtual Init *convertValue(StringInit *SI) { return 0; } + virtual Init *convertValue( ListInit *LI) { return 0; } + virtual Init *convertValue( CodeInit *CI) { return (Init*)CI; } + virtual Init *convertValue(VarBitInit *VB) { return 0; } + virtual Init *convertValue( DefInit *DI) { return 0; } + virtual Init *convertValue( DagInit *DI) { return 0; } + virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);} + virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} + virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);} + virtual Init *convertValue( TypedInit *TI); + virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} + virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} + + std::string getAsString() const { return "code"; } + + bool typeIsConvertibleTo(const RecTy *RHS) const { + return RHS->baseClassOf(this); + } + virtual bool baseClassOf(const BitRecTy *RHS) const { return false; } + virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; } + virtual bool baseClassOf(const IntRecTy *RHS) const { return false; } + virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } + virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } + virtual bool baseClassOf(const CodeRecTy *RHS) const { return true; } + virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } + virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } +}; + +/// DagRecTy - 'dag' - Represent a dag fragment +/// +class DagRecTy : public RecTy { + static DagRecTy Shared; + DagRecTy() {} +public: + static DagRecTy *get() { return &Shared; } + + virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } + virtual Init *convertValue( BitInit *BI) { return 0; } + virtual Init *convertValue( BitsInit *BI) { return 0; } + virtual Init *convertValue( IntInit *II) { return 0; } + virtual Init *convertValue(StringInit *SI) { return 0; } + virtual Init *convertValue( ListInit *LI) { return 0; } + virtual Init *convertValue( CodeInit *CI) { return 0; } + virtual Init *convertValue(VarBitInit *VB) { return 0; } + virtual Init *convertValue( DefInit *DI) { return 0; } + virtual Init *convertValue( UnOpInit *BO); + virtual Init *convertValue( BinOpInit *BO); + virtual Init *convertValue( TernOpInit *BO) { return RecTy::convertValue(BO);} + virtual Init *convertValue( DagInit *CI) { return (Init*)CI; } + virtual Init *convertValue( TypedInit *TI); + virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} + virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} + + std::string getAsString() const { return "dag"; } + + bool typeIsConvertibleTo(const RecTy *RHS) const { + return RHS->baseClassOf(this); + } + + virtual bool baseClassOf(const BitRecTy *RHS) const { return false; } + virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; } + virtual bool baseClassOf(const IntRecTy *RHS) const { return false; } + virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } + virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } + virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; } + virtual bool baseClassOf(const DagRecTy *RHS) const { return true; } + virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } +}; + + +/// RecordRecTy - '[classname]' - Represent an instance of a class, such as: +/// (R32 X = EAX). +/// +class RecordRecTy : public RecTy { + Record *Rec; + explicit RecordRecTy(Record *R) : Rec(R) {} + friend class Record; +public: + static RecordRecTy *get(Record *R); + + Record *getRecord() const { return Rec; } + + virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } + virtual Init *convertValue( BitInit *BI) { return 0; } + virtual Init *convertValue( BitsInit *BI) { return 0; } + virtual Init *convertValue( IntInit *II) { return 0; } + virtual Init *convertValue(StringInit *SI) { return 0; } + virtual Init *convertValue( ListInit *LI) { return 0; } + virtual Init *convertValue( CodeInit *CI) { return 0; } + virtual Init *convertValue(VarBitInit *VB) { return 0; } + virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);} + virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} + virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);} + virtual Init *convertValue( DefInit *DI); + virtual Init *convertValue( DagInit *DI) { return 0; } + virtual Init *convertValue( TypedInit *VI); + virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} + virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} + + std::string getAsString() const; + + bool typeIsConvertibleTo(const RecTy *RHS) const { + return RHS->baseClassOf(this); + } + virtual bool baseClassOf(const BitRecTy *RHS) const { return false; } + virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; } + virtual bool baseClassOf(const IntRecTy *RHS) const { return false; } + virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } + virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } + virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; } + virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } + virtual bool baseClassOf(const RecordRecTy *RHS) const; +}; + +/// resolveTypes - Find a common type that T1 and T2 convert to. +/// Return 0 if no such type exists. +/// +RecTy *resolveTypes(RecTy *T1, RecTy *T2); + +//===----------------------------------------------------------------------===// +// Initializer Classes +//===----------------------------------------------------------------------===// + +class Init { + Init(const Init &); // Do not define. + Init &operator=(const Init &); // Do not define. + +protected: + Init(void) {} + +public: + virtual ~Init() {} + + /// isComplete - This virtual method should be overridden by values that may + /// not be completely specified yet. + virtual bool isComplete() const { return true; } + + /// print - Print out this value. + void print(raw_ostream &OS) const { OS << getAsString(); } + + /// getAsString - Convert this value to a string form. + virtual std::string getAsString() const = 0; + /// getAsUnquotedString - Convert this value to a string form, + /// without adding quote markers. This primaruly affects + /// StringInits where we will not surround the string value with + /// quotes. + virtual std::string getAsUnquotedString() const { return getAsString(); } + + /// dump - Debugging method that may be called through a debugger, just + /// invokes print on stderr. + void dump() const; + + /// convertInitializerTo - This virtual function is a simple call-back + /// function that should be overridden to call the appropriate + /// RecTy::convertValue method. + /// + virtual Init *convertInitializerTo(RecTy *Ty) const = 0; + + /// convertInitializerBitRange - This method is used to implement the bitrange + /// selection operator. Given an initializer, it selects the specified bits + /// out, returning them as a new init of bits type. If it is not legal to use + /// the bit subscript operator on this initializer, return null. + /// + virtual Init * + convertInitializerBitRange(const std::vector &Bits) const { + return 0; + } + + /// convertInitListSlice - This method is used to implement the list slice + /// selection operator. Given an initializer, it selects the specified list + /// elements, returning them as a new init of list type. If it is not legal + /// to take a slice of this, return null. + /// + virtual Init * + convertInitListSlice(const std::vector &Elements) const { + return 0; + } + + /// getFieldType - This method is used to implement the FieldInit class. + /// Implementors of this method should return the type of the named field if + /// they are of record type. + /// + virtual RecTy *getFieldType(const std::string &FieldName) const { return 0; } + + /// getFieldInit - This method complements getFieldType to return the + /// initializer for the specified field. If getFieldType returns non-null + /// this method should return non-null, otherwise it returns null. + /// + virtual Init *getFieldInit(Record &R, const RecordVal *RV, + const std::string &FieldName) const { + return 0; + } + + /// resolveReferences - This method is used by classes that refer to other + /// variables which may not be defined at the time the expression is formed. + /// If a value is set for the variable later, this method will be called on + /// users of the value to allow the value to propagate out. + /// + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const { + return const_cast(this); + } +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) { + I.print(OS); return OS; +} + +/// TypedInit - This is the common super-class of types that have a specific, +/// explicit, type. +/// +class TypedInit : public Init { + RecTy *Ty; + + TypedInit(const TypedInit &Other); // Do not define. + TypedInit &operator=(const TypedInit &Other); // Do not define. + +protected: + explicit TypedInit(RecTy *T) : Ty(T) {} + +public: + RecTy *getType() const { return Ty; } + + virtual Init * + convertInitializerBitRange(const std::vector &Bits) const; + virtual Init * + convertInitListSlice(const std::vector &Elements) const; + + /// getFieldType - This method is used to implement the FieldInit class. + /// Implementors of this method should return the type of the named field if + /// they are of record type. + /// + virtual RecTy *getFieldType(const std::string &FieldName) const; + + /// resolveBitReference - This method is used to implement + /// VarBitInit::resolveReferences. If the bit is able to be resolved, we + /// simply return the resolved value, otherwise we return null. + /// + virtual Init *resolveBitReference(Record &R, const RecordVal *RV, + unsigned Bit) const = 0; + + /// resolveListElementReference - This method is used to implement + /// VarListElementInit::resolveReferences. If the list element is resolvable + /// now, we return the resolved value, otherwise we return null. + virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) const = 0; +}; + + +/// UnsetInit - ? - Represents an uninitialized value +/// +class UnsetInit : public Init { + UnsetInit() : Init() {} + UnsetInit(const UnsetInit &); // Do not define. + UnsetInit &operator=(const UnsetInit &Other); // Do not define. + +public: + static UnsetInit *get(); + + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); + } + + virtual bool isComplete() const { return false; } + virtual std::string getAsString() const { return "?"; } +}; + + +/// BitInit - true/false - Represent a concrete initializer for a bit. +/// +class BitInit : public Init { + bool Value; + + explicit BitInit(bool V) : Value(V) {} + BitInit(const BitInit &Other); // Do not define. + BitInit &operator=(BitInit &Other); // Do not define. + +public: + static BitInit *get(bool V); + + bool getValue() const { return Value; } + + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); + } + + virtual std::string getAsString() const { return Value ? "1" : "0"; } +}; + +/// BitsInit - { a, b, c } - Represents an initializer for a BitsRecTy value. +/// It contains a vector of bits, whose size is determined by the type. +/// +class BitsInit : public Init, public FoldingSetNode { + std::vector Bits; + + BitsInit(ArrayRef Range) : Bits(Range.begin(), Range.end()) {} + + BitsInit(const BitsInit &Other); // Do not define. + BitsInit &operator=(const BitsInit &Other); // Do not define. + +public: + static BitsInit *get(ArrayRef Range); + + void Profile(FoldingSetNodeID &ID) const; + + unsigned getNumBits() const { return Bits.size(); } + + Init *getBit(unsigned Bit) const { + assert(Bit < Bits.size() && "Bit index out of range!"); + return Bits[Bit]; + } + + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); + } + virtual Init * + convertInitializerBitRange(const std::vector &Bits) const; + + virtual bool isComplete() const { + for (unsigned i = 0; i != getNumBits(); ++i) + if (!getBit(i)->isComplete()) return false; + return true; + } + bool allInComplete() const { + for (unsigned i = 0; i != getNumBits(); ++i) + if (getBit(i)->isComplete()) return false; + return true; + } + virtual std::string getAsString() const; + + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; +}; + + +/// IntInit - 7 - Represent an initalization by a literal integer value. +/// +class IntInit : public TypedInit { + int64_t Value; + + explicit IntInit(int64_t V) : TypedInit(IntRecTy::get()), Value(V) {} + + IntInit(const IntInit &Other); // Do not define. + IntInit &operator=(const IntInit &Other); // Do note define. + +public: + static IntInit *get(int64_t V); + + int64_t getValue() const { return Value; } + + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); + } + virtual Init * + convertInitializerBitRange(const std::vector &Bits) const; + + virtual std::string getAsString() const; + + /// resolveBitReference - This method is used to implement + /// VarBitInit::resolveReferences. If the bit is able to be resolved, we + /// simply return the resolved value, otherwise we return null. + /// + virtual Init *resolveBitReference(Record &R, const RecordVal *RV, + unsigned Bit) const { + assert(0 && "Illegal bit reference off int"); + return 0; + } + + /// resolveListElementReference - This method is used to implement + /// VarListElementInit::resolveReferences. If the list element is resolvable + /// now, we return the resolved value, otherwise we return null. + virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) const { + assert(0 && "Illegal element reference off int"); + return 0; + } +}; + + +/// StringInit - "foo" - Represent an initialization by a string value. +/// +class StringInit : public TypedInit { + std::string Value; + + explicit StringInit(const std::string &V) + : TypedInit(StringRecTy::get()), Value(V) {} + + StringInit(const StringInit &Other); // Do not define. + StringInit &operator=(const StringInit &Other); // Do not define. + +public: + static StringInit *get(const std::string &V); + + const std::string &getValue() const { return Value; } + + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); + } + + virtual std::string getAsString() const { return "\"" + Value + "\""; } + virtual std::string getAsUnquotedString() const { return Value; } + + /// resolveBitReference - This method is used to implement + /// VarBitInit::resolveReferences. If the bit is able to be resolved, we + /// simply return the resolved value, otherwise we return null. + /// + virtual Init *resolveBitReference(Record &R, const RecordVal *RV, + unsigned Bit) const { + assert(0 && "Illegal bit reference off string"); + return 0; + } + + /// resolveListElementReference - This method is used to implement + /// VarListElementInit::resolveReferences. If the list element is resolvable + /// now, we return the resolved value, otherwise we return null. + virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) const { + assert(0 && "Illegal element reference off string"); + return 0; + } +}; + +/// CodeInit - "[{...}]" - Represent a code fragment. +/// +class CodeInit : public Init { + std::string Value; + + explicit CodeInit(const std::string &V) : Value(V) {} + + CodeInit(const CodeInit &Other); // Do not define. + CodeInit &operator=(const CodeInit &Other); // Do not define. + +public: + static CodeInit *get(const std::string &V); + + const std::string &getValue() const { return Value; } + + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); + } + + virtual std::string getAsString() const { return "[{" + Value + "}]"; } +}; + +/// ListInit - [AL, AH, CL] - Represent a list of defs +/// +class ListInit : public TypedInit, public FoldingSetNode { + std::vector Values; +public: + typedef std::vector::const_iterator const_iterator; + +private: + explicit ListInit(ArrayRef Range, RecTy *EltTy) + : TypedInit(ListRecTy::get(EltTy)), Values(Range.begin(), Range.end()) {} + + ListInit(const ListInit &Other); // Do not define. + ListInit &operator=(const ListInit &Other); // Do not define. + +public: + static ListInit *get(ArrayRef Range, RecTy *EltTy); + + void Profile(FoldingSetNodeID &ID) const; + + unsigned getSize() const { return Values.size(); } + Init *getElement(unsigned i) const { + assert(i < Values.size() && "List element index out of range!"); + return Values[i]; + } + + Record *getElementAsRecord(unsigned i) const; + + Init *convertInitListSlice(const std::vector &Elements) const; + + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); + } + + /// resolveReferences - This method is used by classes that refer to other + /// variables which may not be defined at the time they expression is formed. + /// If a value is set for the variable later, this method will be called on + /// users of the value to allow the value to propagate out. + /// + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; + + virtual std::string getAsString() const; + + ArrayRef getValues() const { return Values; } + + inline const_iterator begin() const { return Values.begin(); } + inline const_iterator end () const { return Values.end(); } + + inline size_t size () const { return Values.size(); } + inline bool empty() const { return Values.empty(); } + + /// resolveBitReference - This method is used to implement + /// VarBitInit::resolveReferences. If the bit is able to be resolved, we + /// simply return the resolved value, otherwise we return null. + /// + virtual Init *resolveBitReference(Record &R, const RecordVal *RV, + unsigned Bit) const { + assert(0 && "Illegal bit reference off list"); + return 0; + } + + /// resolveListElementReference - This method is used to implement + /// VarListElementInit::resolveReferences. If the list element is resolvable + /// now, we return the resolved value, otherwise we return null. + virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) const; +}; + + +/// OpInit - Base class for operators +/// +class OpInit : public TypedInit { + OpInit(const OpInit &Other); // Do not define. + OpInit &operator=(OpInit &Other); // Do not define. + +protected: + explicit OpInit(RecTy *Type) : TypedInit(Type) {} + +public: + // Clone - Clone this operator, replacing arguments with the new list + virtual OpInit *clone(std::vector &Operands) const = 0; + + virtual int getNumOperands() const = 0; + virtual Init *getOperand(int i) const = 0; + + // Fold - If possible, fold this to a simpler init. Return this if not + // possible to fold. + virtual Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const = 0; + + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); + } + + virtual Init *resolveBitReference(Record &R, const RecordVal *RV, + unsigned Bit) const; + virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) const; +}; + + +/// UnOpInit - !op (X) - Transform an init. +/// +class UnOpInit : public OpInit { +public: + enum UnaryOp { CAST, HEAD, TAIL, EMPTY }; +private: + UnaryOp Opc; + Init *LHS; + + UnOpInit(UnaryOp opc, Init *lhs, RecTy *Type) + : OpInit(Type), Opc(opc), LHS(lhs) {} + + UnOpInit(const UnOpInit &Other); // Do not define. + UnOpInit &operator=(const UnOpInit &Other); // Do not define. + +public: + static UnOpInit *get(UnaryOp opc, Init *lhs, RecTy *Type); + + // Clone - Clone this operator, replacing arguments with the new list + virtual OpInit *clone(std::vector &Operands) const { + assert(Operands.size() == 1 && + "Wrong number of operands for unary operation"); + return UnOpInit::get(getOpcode(), *Operands.begin(), getType()); + } + + int getNumOperands() const { return 1; } + Init *getOperand(int i) const { + assert(i == 0 && "Invalid operand id for unary operator"); + return getOperand(); + } + + UnaryOp getOpcode() const { return Opc; } + Init *getOperand() const { return LHS; } + + // Fold - If possible, fold this to a simpler init. Return this if not + // possible to fold. + Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const; + + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; + + virtual std::string getAsString() const; +}; + +/// BinOpInit - !op (X, Y) - Combine two inits. +/// +class BinOpInit : public OpInit { +public: + enum BinaryOp { SHL, SRA, SRL, STRCONCAT, CONCAT, EQ }; +private: + BinaryOp Opc; + Init *LHS, *RHS; + + BinOpInit(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type) : + OpInit(Type), Opc(opc), LHS(lhs), RHS(rhs) {} + + BinOpInit(const BinOpInit &Other); // Do not define. + BinOpInit &operator=(const BinOpInit &Other); // Do not define. + +public: + static BinOpInit *get(BinaryOp opc, Init *lhs, Init *rhs, + RecTy *Type); + + // Clone - Clone this operator, replacing arguments with the new list + virtual OpInit *clone(std::vector &Operands) const { + assert(Operands.size() == 2 && + "Wrong number of operands for binary operation"); + return BinOpInit::get(getOpcode(), Operands[0], Operands[1], getType()); + } + + int getNumOperands() const { return 2; } + Init *getOperand(int i) const { + assert((i == 0 || i == 1) && "Invalid operand id for binary operator"); + if (i == 0) { + return getLHS(); + } else { + return getRHS(); + } + } + + BinaryOp getOpcode() const { return Opc; } + Init *getLHS() const { return LHS; } + Init *getRHS() const { return RHS; } + + // Fold - If possible, fold this to a simpler init. Return this if not + // possible to fold. + Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const; + + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; + + virtual std::string getAsString() const; +}; + +/// TernOpInit - !op (X, Y, Z) - Combine two inits. +/// +class TernOpInit : public OpInit { +public: + enum TernaryOp { SUBST, FOREACH, IF }; +private: + TernaryOp Opc; + Init *LHS, *MHS, *RHS; + + TernOpInit(TernaryOp opc, Init *lhs, Init *mhs, Init *rhs, + RecTy *Type) : + OpInit(Type), Opc(opc), LHS(lhs), MHS(mhs), RHS(rhs) {} + + TernOpInit(const TernOpInit &Other); // Do not define. + TernOpInit &operator=(const TernOpInit &Other); // Do not define. + +public: + static TernOpInit *get(TernaryOp opc, Init *lhs, + Init *mhs, Init *rhs, + RecTy *Type); + + // Clone - Clone this operator, replacing arguments with the new list + virtual OpInit *clone(std::vector &Operands) const { + assert(Operands.size() == 3 && + "Wrong number of operands for ternary operation"); + return TernOpInit::get(getOpcode(), Operands[0], Operands[1], Operands[2], + getType()); + } + + int getNumOperands() const { return 3; } + Init *getOperand(int i) const { + assert((i == 0 || i == 1 || i == 2) && + "Invalid operand id for ternary operator"); + if (i == 0) { + return getLHS(); + } else if (i == 1) { + return getMHS(); + } else { + return getRHS(); + } + } + + TernaryOp getOpcode() const { return Opc; } + Init *getLHS() const { return LHS; } + Init *getMHS() const { return MHS; } + Init *getRHS() const { return RHS; } + + // Fold - If possible, fold this to a simpler init. Return this if not + // possible to fold. + Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const; + + virtual bool isComplete() const { return false; } + + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; + + virtual std::string getAsString() const; +}; + + +/// VarInit - 'Opcode' - Represent a reference to an entire variable object. +/// +class VarInit : public TypedInit { + std::string VarName; + + explicit VarInit(const std::string &VN, RecTy *T) + : TypedInit(T), VarName(VN) {} + + VarInit(const VarInit &Other); // Do not define. + VarInit &operator=(const VarInit &Other); // Do not define. + +public: + static VarInit *get(const std::string &VN, RecTy *T); + static VarInit *get(Init *VN, RecTy *T); + + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); + } + + const std::string &getName() const { return VarName; } + + virtual Init *resolveBitReference(Record &R, const RecordVal *RV, + unsigned Bit) const; + virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) const; + + virtual RecTy *getFieldType(const std::string &FieldName) const; + virtual Init *getFieldInit(Record &R, const RecordVal *RV, + const std::string &FieldName) const; + + /// resolveReferences - This method is used by classes that refer to other + /// variables which may not be defined at the time they expression is formed. + /// If a value is set for the variable later, this method will be called on + /// users of the value to allow the value to propagate out. + /// + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; + + virtual std::string getAsString() const { return VarName; } +}; + + +/// VarBitInit - Opcode{0} - Represent access to one bit of a variable or field. +/// +class VarBitInit : public Init { + TypedInit *TI; + unsigned Bit; + + VarBitInit(TypedInit *T, unsigned B) : TI(T), Bit(B) { + assert(T->getType() && dynamic_cast(T->getType()) && + ((BitsRecTy*)T->getType())->getNumBits() > B && + "Illegal VarBitInit expression!"); + } + + VarBitInit(const VarBitInit &Other); // Do not define. + VarBitInit &operator=(const VarBitInit &Other); // Do not define. + +public: + static VarBitInit *get(TypedInit *T, unsigned B); + + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); + } + + TypedInit *getVariable() const { return TI; } + unsigned getBitNum() const { return Bit; } + + virtual std::string getAsString() const; + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; +}; + +/// VarListElementInit - List[4] - Represent access to one element of a var or +/// field. +class VarListElementInit : public TypedInit { + TypedInit *TI; + unsigned Element; + + VarListElementInit(TypedInit *T, unsigned E) + : TypedInit(dynamic_cast(T->getType())->getElementType()), + TI(T), Element(E) { + assert(T->getType() && dynamic_cast(T->getType()) && + "Illegal VarBitInit expression!"); + } + + VarListElementInit(const VarListElementInit &Other); // Do not define. + VarListElementInit &operator=(const VarListElementInit &Other); // Do + // not + // define. + +public: + static VarListElementInit *get(TypedInit *T, unsigned E); + + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); + } + + TypedInit *getVariable() const { return TI; } + unsigned getElementNum() const { return Element; } + + virtual Init *resolveBitReference(Record &R, const RecordVal *RV, + unsigned Bit) const; + + /// resolveListElementReference - This method is used to implement + /// VarListElementInit::resolveReferences. If the list element is resolvable + /// now, we return the resolved value, otherwise we return null. + virtual Init *resolveListElementReference(Record &R, + const RecordVal *RV, + unsigned Elt) const; + + virtual std::string getAsString() const; + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; +}; + +/// DefInit - AL - Represent a reference to a 'def' in the description +/// +class DefInit : public TypedInit { + Record *Def; + + DefInit(Record *D, RecordRecTy *T) : TypedInit(T), Def(D) {} + friend class Record; + + DefInit(const DefInit &Other); // Do not define. + DefInit &operator=(const DefInit &Other); // Do not define. + +public: + static DefInit *get(Record*); + + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); + } + + Record *getDef() const { return Def; } + + //virtual Init *convertInitializerBitRange(const std::vector &Bits); + + virtual RecTy *getFieldType(const std::string &FieldName) const; + virtual Init *getFieldInit(Record &R, const RecordVal *RV, + const std::string &FieldName) const; + + virtual std::string getAsString() const; + + /// resolveBitReference - This method is used to implement + /// VarBitInit::resolveReferences. If the bit is able to be resolved, we + /// simply return the resolved value, otherwise we return null. + /// + virtual Init *resolveBitReference(Record &R, const RecordVal *RV, + unsigned Bit) const { + assert(0 && "Illegal bit reference off def"); + return 0; + } + + /// resolveListElementReference - This method is used to implement + /// VarListElementInit::resolveReferences. If the list element is resolvable + /// now, we return the resolved value, otherwise we return null. + virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) const { + assert(0 && "Illegal element reference off def"); + return 0; + } +}; + + +/// FieldInit - X.Y - Represent a reference to a subfield of a variable +/// +class FieldInit : public TypedInit { + Init *Rec; // Record we are referring to + std::string FieldName; // Field we are accessing + + FieldInit(Init *R, const std::string &FN) + : TypedInit(R->getFieldType(FN)), Rec(R), FieldName(FN) { + assert(getType() && "FieldInit with non-record type!"); + } + + FieldInit(const FieldInit &Other); // Do not define. + FieldInit &operator=(const FieldInit &Other); // Do not define. + +public: + static FieldInit *get(Init *R, const std::string &FN); + static FieldInit *get(Init *R, const Init *FN); + + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); + } + + virtual Init *resolveBitReference(Record &R, const RecordVal *RV, + unsigned Bit) const; + virtual Init *resolveListElementReference(Record &R, + const RecordVal *RV, + unsigned Elt) const; + + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; + + virtual std::string getAsString() const { + return Rec->getAsString() + "." + FieldName; + } +}; + +/// DagInit - (v a, b) - Represent a DAG tree value. DAG inits are required +/// to have at least one value then a (possibly empty) list of arguments. Each +/// argument can have a name associated with it. +/// +class DagInit : public TypedInit, public FoldingSetNode { + Init *Val; + std::string ValName; + std::vector Args; + std::vector ArgNames; + + DagInit(Init *V, const std::string &VN, + ArrayRef ArgRange, + ArrayRef NameRange) + : TypedInit(DagRecTy::get()), Val(V), ValName(VN), + Args(ArgRange.begin(), ArgRange.end()), + ArgNames(NameRange.begin(), NameRange.end()) {} + + DagInit(const DagInit &Other); // Do not define. + DagInit &operator=(const DagInit &Other); // Do not define. + +public: + static DagInit *get(Init *V, const std::string &VN, + ArrayRef ArgRange, + ArrayRef NameRange); + static DagInit *get(Init *V, const std::string &VN, + const std::vector< + std::pair > &args); + + void Profile(FoldingSetNodeID &ID) const; + + virtual Init *convertInitializerTo(RecTy *Ty) const { + return Ty->convertValue(const_cast(this)); + } + + Init *getOperator() const { return Val; } + + const std::string &getName() const { return ValName; } + + unsigned getNumArgs() const { return Args.size(); } + Init *getArg(unsigned Num) const { + assert(Num < Args.size() && "Arg number out of range!"); + return Args[Num]; + } + const std::string &getArgName(unsigned Num) const { + assert(Num < ArgNames.size() && "Arg number out of range!"); + return ArgNames[Num]; + } + + virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; + + virtual std::string getAsString() const; + + typedef std::vector::const_iterator const_arg_iterator; + typedef std::vector::const_iterator const_name_iterator; + + inline const_arg_iterator arg_begin() const { return Args.begin(); } + inline const_arg_iterator arg_end () const { return Args.end(); } + + inline size_t arg_size () const { return Args.size(); } + inline bool arg_empty() const { return Args.empty(); } + + inline const_name_iterator name_begin() const { return ArgNames.begin(); } + inline const_name_iterator name_end () const { return ArgNames.end(); } + + inline size_t name_size () const { return ArgNames.size(); } + inline bool name_empty() const { return ArgNames.empty(); } + + virtual Init *resolveBitReference(Record &R, const RecordVal *RV, + unsigned Bit) const { + assert(0 && "Illegal bit reference off dag"); + return 0; + } + + virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) const { + assert(0 && "Illegal element reference off dag"); + return 0; + } +}; + +//===----------------------------------------------------------------------===// +// High-Level Classes +//===----------------------------------------------------------------------===// + +class RecordVal { + Init *Name; + RecTy *Ty; + unsigned Prefix; + Init *Value; +public: + RecordVal(Init *N, RecTy *T, unsigned P); + RecordVal(const std::string &N, RecTy *T, unsigned P); + + const std::string &getName() const; + + unsigned getPrefix() const { return Prefix; } + RecTy *getType() const { return Ty; } + Init *getValue() const { return Value; } + + bool setValue(Init *V) { + if (V) { + Value = V->convertInitializerTo(Ty); + return Value == 0; + } + Value = 0; + return false; + } + + void dump() const; + void print(raw_ostream &OS, bool PrintSem = true) const; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const RecordVal &RV) { + RV.print(OS << " "); + return OS; +} + +class Record { + static unsigned LastID; + + // Unique record ID. + unsigned ID; + Init *Name; + SMLoc Loc; + std::vector TemplateArgs; + std::vector Values; + std::vector SuperClasses; + + // Tracks Record instances. Not owned by Record. + RecordKeeper &TrackedRecords; + + DefInit *TheInit; + + void checkName(); + +public: + + // Constructs a record. + explicit Record(const std::string &N, SMLoc loc, RecordKeeper &records) : + ID(LastID++), Name(StringInit::get(N)), Loc(loc), TrackedRecords(records), TheInit(0) {} + ~Record() {} + + + static unsigned getNewUID() { return LastID++; } + + + unsigned getID() const { return ID; } + + const std::string &getName() const; + void setName(Init *Name); // Also updates RecordKeeper. + void setName(const std::string &Name); // Also updates RecordKeeper. + + SMLoc getLoc() const { return Loc; } + + /// get the corresponding DefInit. + DefInit *getDefInit(); + + const std::vector &getTemplateArgs() const { + return TemplateArgs; + } + const std::vector &getValues() const { return Values; } + const std::vector &getSuperClasses() const { return SuperClasses; } + + bool isTemplateArg(StringRef Name) const { + for (unsigned i = 0, e = TemplateArgs.size(); i != e; ++i) + if (TemplateArgs[i] == Name) return true; + return false; + } + + const RecordVal *getValue(StringRef Name) const { + for (unsigned i = 0, e = Values.size(); i != e; ++i) + if (Values[i].getName() == Name) return &Values[i]; + return 0; + } + RecordVal *getValue(StringRef Name) { + for (unsigned i = 0, e = Values.size(); i != e; ++i) + if (Values[i].getName() == Name) return &Values[i]; + return 0; + } + + void addTemplateArg(StringRef Name) { + assert(!isTemplateArg(Name) && "Template arg already defined!"); + TemplateArgs.push_back(Name); + } + + void addValue(const RecordVal &RV) { + assert(getValue(RV.getName()) == 0 && "Value already added!"); + Values.push_back(RV); + } + + void removeValue(StringRef Name) { + for (unsigned i = 0, e = Values.size(); i != e; ++i) + if (Values[i].getName() == Name) { + Values.erase(Values.begin()+i); + return; + } + assert(0 && "Cannot remove an entry that does not exist!"); + } + + bool isSubClassOf(const Record *R) const { + for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i) + if (SuperClasses[i] == R) + return true; + return false; + } + + bool isSubClassOf(StringRef Name) const { + for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i) + if (SuperClasses[i]->getName() == Name) + return true; + return false; + } + + void addSuperClass(Record *R) { + assert(!isSubClassOf(R) && "Already subclassing record!"); + SuperClasses.push_back(R); + } + + /// resolveReferences - If there are any field references that refer to fields + /// that have been filled in, we can propagate the values now. + /// + void resolveReferences() { resolveReferencesTo(0); } + + /// resolveReferencesTo - If anything in this record refers to RV, replace the + /// reference to RV with the RHS of RV. If RV is null, we resolve all + /// possible references. + void resolveReferencesTo(const RecordVal *RV); + + RecordKeeper &getRecords() const { + return TrackedRecords; + } + + void dump() const; + + //===--------------------------------------------------------------------===// + // High-level methods useful to tablegen back-ends + // + + /// getValueInit - Return the initializer for a value with the specified name, + /// or throw an exception if the field does not exist. + /// + Init *getValueInit(StringRef FieldName) const; + + /// getValueAsString - This method looks up the specified field and returns + /// its value as a string, throwing an exception if the field does not exist + /// or if the value is not a string. + /// + std::string getValueAsString(StringRef FieldName) const; + + /// getValueAsBitsInit - This method looks up the specified field and returns + /// its value as a BitsInit, throwing an exception if the field does not exist + /// or if the value is not the right type. + /// + BitsInit *getValueAsBitsInit(StringRef FieldName) const; + + /// getValueAsListInit - This method looks up the specified field and returns + /// its value as a ListInit, throwing an exception if the field does not exist + /// or if the value is not the right type. + /// + ListInit *getValueAsListInit(StringRef FieldName) const; + + /// getValueAsListOfDefs - This method looks up the specified field and + /// returns its value as a vector of records, throwing an exception if the + /// field does not exist or if the value is not the right type. + /// + std::vector getValueAsListOfDefs(StringRef FieldName) const; + + /// getValueAsListOfInts - This method looks up the specified field and + /// returns its value as a vector of integers, throwing an exception if the + /// field does not exist or if the value is not the right type. + /// + std::vector getValueAsListOfInts(StringRef FieldName) const; + + /// getValueAsListOfStrings - This method looks up the specified field and + /// returns its value as a vector of strings, throwing an exception if the + /// field does not exist or if the value is not the right type. + /// + std::vector getValueAsListOfStrings(StringRef FieldName) const; + + /// getValueAsDef - This method looks up the specified field and returns its + /// value as a Record, throwing an exception if the field does not exist or if + /// the value is not the right type. + /// + Record *getValueAsDef(StringRef FieldName) const; + + /// getValueAsBit - This method looks up the specified field and returns its + /// value as a bit, throwing an exception if the field does not exist or if + /// the value is not the right type. + /// + bool getValueAsBit(StringRef FieldName) const; + + /// getValueAsInt - This method looks up the specified field and returns its + /// value as an int64_t, throwing an exception if the field does not exist or + /// if the value is not the right type. + /// + int64_t getValueAsInt(StringRef FieldName) const; + + /// getValueAsDag - This method looks up the specified field and returns its + /// value as an Dag, throwing an exception if the field does not exist or if + /// the value is not the right type. + /// + DagInit *getValueAsDag(StringRef FieldName) const; + + /// getValueAsCode - This method looks up the specified field and returns + /// its value as the string data in a CodeInit, throwing an exception if the + /// field does not exist or if the value is not a code object. + /// + std::string getValueAsCode(StringRef FieldName) const; +}; + +raw_ostream &operator<<(raw_ostream &OS, const Record &R); + +struct MultiClass { + Record Rec; // Placeholder for template args and Name. + typedef std::vector RecordVector; + RecordVector DefPrototypes; + + void dump() const; + + MultiClass(const std::string &Name, SMLoc Loc, RecordKeeper &Records) : + Rec(Name, Loc, Records) {} +}; + +class RecordKeeper { + std::map Classes, Defs; +public: + ~RecordKeeper() { + for (std::map::iterator I = Classes.begin(), + E = Classes.end(); I != E; ++I) + delete I->second; + for (std::map::iterator I = Defs.begin(), + E = Defs.end(); I != E; ++I) + delete I->second; + } + + const std::map &getClasses() const { return Classes; } + const std::map &getDefs() const { return Defs; } + + Record *getClass(const std::string &Name) const { + std::map::const_iterator I = Classes.find(Name); + return I == Classes.end() ? 0 : I->second; + } + Record *getDef(const std::string &Name) const { + std::map::const_iterator I = Defs.find(Name); + return I == Defs.end() ? 0 : I->second; + } + void addClass(Record *R) { + assert(getClass(R->getName()) == 0 && "Class already exists!"); + Classes.insert(std::make_pair(R->getName(), R)); + } + void addDef(Record *R) { + assert(getDef(R->getName()) == 0 && "Def already exists!"); + Defs.insert(std::make_pair(R->getName(), R)); + } + + /// removeClass - Remove, but do not delete, the specified record. + /// + void removeClass(const std::string &Name) { + assert(Classes.count(Name) && "Class does not exist!"); + Classes.erase(Name); + } + /// removeDef - Remove, but do not delete, the specified record. + /// + void removeDef(const std::string &Name) { + assert(Defs.count(Name) && "Def does not exist!"); + Defs.erase(Name); + } + + //===--------------------------------------------------------------------===// + // High-level helper methods, useful for tablegen backends... + + /// getAllDerivedDefinitions - This method returns all concrete definitions + /// that derive from the specified class name. If a class with the specified + /// name does not exist, an exception is thrown. + std::vector + getAllDerivedDefinitions(const std::string &ClassName) const; + + void dump() const; +}; + +/// LessRecord - Sorting predicate to sort record pointers by name. +/// +struct LessRecord { + bool operator()(const Record *Rec1, const Record *Rec2) const { + return StringRef(Rec1->getName()).compare_numeric(Rec2->getName()) < 0; + } +}; + +/// LessRecordFieldName - Sorting predicate to sort record pointers by their +/// name field. +/// +struct LessRecordFieldName { + bool operator()(const Record *Rec1, const Record *Rec2) const { + return Rec1->getValueAsString("Name") < Rec2->getValueAsString("Name"); + } +}; + +raw_ostream &operator<<(raw_ostream &OS, const RecordKeeper &RK); + +} // End llvm namespace + +#endif diff --git a/include/llvm/TableGen/TableGenAction.h b/include/llvm/TableGen/TableGenAction.h new file mode 100644 index 00000000000..9f1c23c5b45 --- /dev/null +++ b/include/llvm/TableGen/TableGenAction.h @@ -0,0 +1,34 @@ +//===- llvm/TableGen/TableGenAction.h - defines TableGenAction --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the TableGenAction base class to be derived from by +// tblgen tools. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TABLEGEN_TABLEGENACTION_H +#define LLVM_TABLEGEN_TABLEGENACTION_H + +namespace llvm { + +class raw_ostream; +class RecordKeeper; + +class TableGenAction { +public: + virtual ~TableGenAction() {} + + /// Perform the action using Records, and write output to OS. + /// @returns true on error, false otherwise + virtual bool operator()(raw_ostream &OS, RecordKeeper &Records) = 0; +}; + +} + +#endif diff --git a/include/llvm/TableGen/TableGenBackend.h b/include/llvm/TableGen/TableGenBackend.h new file mode 100644 index 00000000000..853f92e406f --- /dev/null +++ b/include/llvm/TableGen/TableGenBackend.h @@ -0,0 +1,43 @@ +//===- llvm/TableGen/TableGenBackend.h - Backend base class -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The TableGenBackend class is provided as a common interface for all TableGen +// backends. It provides useful services and an standardized interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TABLEGEN_TABLEGENBACKEND_H +#define LLVM_TABLEGEN_TABLEGENBACKEND_H + +#include "llvm/Support/raw_ostream.h" +#include + +namespace llvm { + +class Record; +class RecordKeeper; + +struct TableGenBackend { + virtual ~TableGenBackend() {} + + // run - All TableGen backends should implement the run method, which should + // be the main entry point. + virtual void run(raw_ostream &OS) = 0; + + +public: // Useful helper routines... + /// EmitSourceFileHeader - Output a LLVM style file header to the specified + /// ostream. + void EmitSourceFileHeader(const std::string &Desc, raw_ostream &OS) const; + +}; + +} // End llvm namespace + +#endif diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index d8a9b7365bf..fb63c63f327 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -1,4 +1,4 @@ -# `Support' library is added on the top-level CMakeLists.txt +# `Support' and `TableGen' libraries are added on the top-level CMakeLists.txt add_subdirectory(VMCore) add_subdirectory(CodeGen) diff --git a/lib/TableGen/CMakeLists.txt b/lib/TableGen/CMakeLists.txt new file mode 100644 index 00000000000..0db41346911 --- /dev/null +++ b/lib/TableGen/CMakeLists.txt @@ -0,0 +1,16 @@ +## FIXME: This only requires RTTI because tblgen uses it. Fix that. +set(LLVM_REQUIRES_RTTI 1) +set(LLVM_REQUIRES_EH 1) + +add_llvm_library(LLVMTableGen + Error.cpp + Main.cpp + Record.cpp + TableGenBackend.cpp + TGLexer.cpp + TGParser.cpp + ) + +add_llvm_library_dependencies(LLVMTableGen + LLVMSupport + ) diff --git a/lib/TableGen/Error.cpp b/lib/TableGen/Error.cpp new file mode 100644 index 00000000000..5b2cbbfec4b --- /dev/null +++ b/lib/TableGen/Error.cpp @@ -0,0 +1,39 @@ +//===- Error.cpp - tblgen error handling helper routines --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains error handling helper routines to pretty-print diagnostic +// messages from tblgen. +// +//===----------------------------------------------------------------------===// + +#include "llvm/TableGen/Error.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +SourceMgr SrcMgr; + +void PrintError(SMLoc ErrorLoc, const Twine &Msg) { + SrcMgr.PrintMessage(ErrorLoc, Msg, "error"); +} + +void PrintError(const char *Loc, const Twine &Msg) { + SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), Msg, "error"); +} + +void PrintError(const Twine &Msg) { + errs() << "error:" << Msg << "\n"; +} + +void PrintError(const TGError &Error) { + PrintError(Error.getLoc(), Error.getMessage()); +} + +} // end namespace llvm diff --git a/lib/TableGen/Main.cpp b/lib/TableGen/Main.cpp new file mode 100644 index 00000000000..01bc55e9898 --- /dev/null +++ b/lib/TableGen/Main.cpp @@ -0,0 +1,124 @@ +//===- Main.cpp - Top-Level TableGen implementation -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// TableGen is a tool which can be used to build up a description of something, +// then invoke one or more "tablegen backends" to emit information about the +// description in some predefined format. In practice, this is used by the LLVM +// code generators to automate generation of a code generator through a +// high-level description of the target. +// +//===----------------------------------------------------------------------===// + +#include "TGParser.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/system_error.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/TableGenAction.h" +#include +#include +using namespace llvm; + +namespace { + cl::opt + OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"), + cl::init("-")); + + cl::opt + DependFilename("d", cl::desc("Dependency filename"), cl::value_desc("filename"), + cl::init("")); + + cl::opt + InputFilename(cl::Positional, cl::desc(""), cl::init("-")); + + cl::list + IncludeDirs("I", cl::desc("Directory of include files"), + cl::value_desc("directory"), cl::Prefix); +} + +namespace llvm { + +int TableGenMain(char *argv0, TableGenAction &Action) { + RecordKeeper Records; + + try { + // Parse the input file. + OwningPtr File; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), File)) { + errs() << "Could not open input file '" << InputFilename << "': " + << ec.message() <<"\n"; + return 1; + } + MemoryBuffer *F = File.take(); + + // Tell SrcMgr about this buffer, which is what TGParser will pick up. + SrcMgr.AddNewSourceBuffer(F, SMLoc()); + + // Record the location of the include directory so that the lexer can find + // it later. + SrcMgr.setIncludeDirs(IncludeDirs); + + TGParser Parser(SrcMgr, Records); + + if (Parser.ParseFile()) + return 1; + + std::string Error; + tool_output_file Out(OutputFilename.c_str(), Error); + if (!Error.empty()) { + errs() << argv0 << ": error opening " << OutputFilename + << ":" << Error << "\n"; + return 1; + } + if (!DependFilename.empty()) { + if (OutputFilename == "-") { + errs() << argv0 << ": the option -d must be used together with -o\n"; + return 1; + } + tool_output_file DepOut(DependFilename.c_str(), Error); + if (!Error.empty()) { + errs() << argv0 << ": error opening " << DependFilename + << ":" << Error << "\n"; + return 1; + } + DepOut.os() << OutputFilename << ":"; + const std::vector &Dependencies = Parser.getDependencies(); + for (std::vector::const_iterator I = Dependencies.begin(), + E = Dependencies.end(); + I != E; ++I) { + DepOut.os() << " " << (*I); + } + DepOut.os() << "\n"; + DepOut.keep(); + } + + if (Action(Out.os(), Records)) + return 1; + + // Declare success. + Out.keep(); + return 0; + + } catch (const TGError &Error) { + PrintError(Error); + } catch (const std::string &Error) { + PrintError(Error); + } catch (const char *Error) { + PrintError(Error); + } catch (...) { + errs() << argv0 << ": Unknown unexpected exception occurred.\n"; + } + + return 1; +} + +} diff --git a/lib/TableGen/Makefile b/lib/TableGen/Makefile new file mode 100644 index 00000000000..44724389e1d --- /dev/null +++ b/lib/TableGen/Makefile @@ -0,0 +1,18 @@ +##===- lib/TableGen/Makefile -------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +LIBRARYNAME = LLVMTableGen +BUILD_ARCHIVE = 1 + +## FIXME: This only requires RTTI because tblgen uses it. Fix that. +REQUIRES_RTTI = 1 +REQUIRES_EH = 1 + +include $(LEVEL)/Makefile.common diff --git a/lib/TableGen/Record.cpp b/lib/TableGen/Record.cpp new file mode 100644 index 00000000000..b4277973b57 --- /dev/null +++ b/lib/TableGen/Record.cpp @@ -0,0 +1,2009 @@ +//===- Record.cpp - Record implementation ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implement the tablegen record classes. +// +//===----------------------------------------------------------------------===// + +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/Error.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h" + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// std::string wrapper for DenseMap purposes +//===----------------------------------------------------------------------===// + +/// 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; } + +private: + std::string data; +}; + +/// Specialize DenseMapInfo for TableGenStringKey. +namespace llvm { + +template<> struct DenseMapInfo { + static inline TableGenStringKey getEmptyKey() { + TableGenStringKey Empty("<<>>"); + return Empty; + } + static inline TableGenStringKey getTombstoneKey() { + TableGenStringKey Tombstone("<<>>"); + return Tombstone; + } + static unsigned getHashValue(const TableGenStringKey& Val) { + return HashString(Val.str()); + } + static bool isEqual(const TableGenStringKey& LHS, + const TableGenStringKey& RHS) { + return LHS.str() == RHS.str(); + } +}; + +} + +//===----------------------------------------------------------------------===// +// Type implementations +//===----------------------------------------------------------------------===// + +BitRecTy BitRecTy::Shared; +IntRecTy IntRecTy::Shared; +StringRecTy StringRecTy::Shared; +CodeRecTy CodeRecTy::Shared; +DagRecTy DagRecTy::Shared; + +void RecTy::dump() const { print(errs()); } + +ListRecTy *RecTy::getListTy() { + if (!ListTy) + ListTy = new ListRecTy(this); + return ListTy; +} + +Init *BitRecTy::convertValue(BitsInit *BI) { + if (BI->getNumBits() != 1) return 0; // Only accept if just one bit! + return BI->getBit(0); +} + +bool BitRecTy::baseClassOf(const BitsRecTy *RHS) const { + return RHS->getNumBits() == 1; +} + +Init *BitRecTy::convertValue(IntInit *II) { + int64_t Val = II->getValue(); + if (Val != 0 && Val != 1) return 0; // Only accept 0 or 1 for a bit! + + return BitInit::get(Val != 0); +} + +Init *BitRecTy::convertValue(TypedInit *VI) { + if (dynamic_cast(VI->getType())) + return VI; // Accept variable if it is already of bit type! + return 0; +} + +BitsRecTy *BitsRecTy::get(unsigned Sz) { + static std::vector Shared; + if (Sz >= Shared.size()) + Shared.resize(Sz + 1); + BitsRecTy *&Ty = Shared[Sz]; + if (!Ty) + Ty = new BitsRecTy(Sz); + return Ty; +} + +std::string BitsRecTy::getAsString() const { + return "bits<" + utostr(Size) + ">"; +} + +Init *BitsRecTy::convertValue(UnsetInit *UI) { + SmallVector NewBits(Size); + + for (unsigned i = 0; i != Size; ++i) + NewBits[i] = UnsetInit::get(); + + return BitsInit::get(NewBits); +} + +Init *BitsRecTy::convertValue(BitInit *UI) { + if (Size != 1) return 0; // Can only convert single bit. + return BitsInit::get(UI); +} + +/// canFitInBitfield - Return true if the number of bits is large enough to hold +/// the integer value. +static bool canFitInBitfield(int64_t Value, unsigned NumBits) { + // For example, with NumBits == 4, we permit Values from [-7 .. 15]. + return (NumBits >= sizeof(Value) * 8) || + (Value >> NumBits == 0) || (Value >> (NumBits-1) == -1); +} + +/// convertValue from Int initializer to bits type: Split the integer up into the +/// appropriate bits. +/// +Init *BitsRecTy::convertValue(IntInit *II) { + int64_t Value = II->getValue(); + // Make sure this bitfield is large enough to hold the integer value. + if (!canFitInBitfield(Value, Size)) + return 0; + + SmallVector NewBits(Size); + + for (unsigned i = 0; i != Size; ++i) + NewBits[i] = BitInit::get(Value & (1LL << i)); + + return BitsInit::get(NewBits); +} + +Init *BitsRecTy::convertValue(BitsInit *BI) { + // If the number of bits is right, return it. Otherwise we need to expand or + // truncate. + if (BI->getNumBits() == Size) return BI; + return 0; +} + +Init *BitsRecTy::convertValue(TypedInit *VI) { + if (BitsRecTy *BRT = dynamic_cast(VI->getType())) + if (BRT->Size == Size) { + SmallVector NewBits(Size); + + for (unsigned i = 0; i != Size; ++i) + NewBits[i] = VarBitInit::get(VI, i); + return BitsInit::get(NewBits); + } + + if (Size == 1 && dynamic_cast(VI->getType())) + return BitsInit::get(VI); + + if (TernOpInit *Tern = dynamic_cast(VI)) { + if (Tern->getOpcode() == TernOpInit::IF) { + Init *LHS = Tern->getLHS(); + Init *MHS = Tern->getMHS(); + Init *RHS = Tern->getRHS(); + + IntInit *MHSi = dynamic_cast(MHS); + IntInit *RHSi = dynamic_cast(RHS); + + if (MHSi && RHSi) { + int64_t MHSVal = MHSi->getValue(); + int64_t RHSVal = RHSi->getValue(); + + if (canFitInBitfield(MHSVal, Size) && canFitInBitfield(RHSVal, Size)) { + SmallVector NewBits(Size); + + for (unsigned i = 0; i != Size; ++i) + NewBits[i] = + TernOpInit::get(TernOpInit::IF, LHS, + IntInit::get((MHSVal & (1LL << i)) ? 1 : 0), + IntInit::get((RHSVal & (1LL << i)) ? 1 : 0), + VI->getType()); + + return BitsInit::get(NewBits); + } + } else { + BitsInit *MHSbs = dynamic_cast(MHS); + BitsInit *RHSbs = dynamic_cast(RHS); + + if (MHSbs && RHSbs) { + SmallVector NewBits(Size); + + for (unsigned i = 0; i != Size; ++i) + NewBits[i] = TernOpInit::get(TernOpInit::IF, LHS, + MHSbs->getBit(i), + RHSbs->getBit(i), + VI->getType()); + + return BitsInit::get(NewBits); + } + } + } + } + + return 0; +} + +Init *IntRecTy::convertValue(BitInit *BI) { + return IntInit::get(BI->getValue()); +} + +Init *IntRecTy::convertValue(BitsInit *BI) { + int64_t Result = 0; + for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) + if (BitInit *Bit = dynamic_cast(BI->getBit(i))) { + Result |= Bit->getValue() << i; + } else { + return 0; + } + return IntInit::get(Result); +} + +Init *IntRecTy::convertValue(TypedInit *TI) { + if (TI->getType()->typeIsConvertibleTo(this)) + return TI; // Accept variable if already of the right type! + return 0; +} + +Init *StringRecTy::convertValue(UnOpInit *BO) { + if (BO->getOpcode() == UnOpInit::CAST) { + Init *L = BO->getOperand()->convertInitializerTo(this); + if (L == 0) return 0; + if (L != BO->getOperand()) + return UnOpInit::get(UnOpInit::CAST, L, new StringRecTy); + return BO; + } + + return convertValue((TypedInit*)BO); +} + +Init *StringRecTy::convertValue(BinOpInit *BO) { + if (BO->getOpcode() == BinOpInit::STRCONCAT) { + Init *L = BO->getLHS()->convertInitializerTo(this); + Init *R = BO->getRHS()->convertInitializerTo(this); + if (L == 0 || R == 0) return 0; + if (L != BO->getLHS() || R != BO->getRHS()) + return BinOpInit::get(BinOpInit::STRCONCAT, L, R, new StringRecTy); + return BO; + } + + return convertValue((TypedInit*)BO); +} + + +Init *StringRecTy::convertValue(TypedInit *TI) { + if (dynamic_cast(TI->getType())) + return TI; // Accept variable if already of the right type! + return 0; +} + +std::string ListRecTy::getAsString() const { + return "list<" + Ty->getAsString() + ">"; +} + +Init *ListRecTy::convertValue(ListInit *LI) { + std::vector Elements; + + // Verify that all of the elements of the list are subclasses of the + // appropriate class! + for (unsigned i = 0, e = LI->getSize(); i != e; ++i) + if (Init *CI = LI->getElement(i)->convertInitializerTo(Ty)) + Elements.push_back(CI); + else + return 0; + + ListRecTy *LType = dynamic_cast(LI->getType()); + if (LType == 0) { + return 0; + } + + return ListInit::get(Elements, this); +} + +Init *ListRecTy::convertValue(TypedInit *TI) { + // Ensure that TI is compatible with our class. + if (ListRecTy *LRT = dynamic_cast(TI->getType())) + if (LRT->getElementType()->typeIsConvertibleTo(getElementType())) + return TI; + return 0; +} + +Init *CodeRecTy::convertValue(TypedInit *TI) { + if (TI->getType()->typeIsConvertibleTo(this)) + return TI; + return 0; +} + +Init *DagRecTy::convertValue(TypedInit *TI) { + if (TI->getType()->typeIsConvertibleTo(this)) + return TI; + return 0; +} + +Init *DagRecTy::convertValue(UnOpInit *BO) { + if (BO->getOpcode() == UnOpInit::CAST) { + Init *L = BO->getOperand()->convertInitializerTo(this); + if (L == 0) return 0; + if (L != BO->getOperand()) + return UnOpInit::get(UnOpInit::CAST, L, new DagRecTy); + return BO; + } + return 0; +} + +Init *DagRecTy::convertValue(BinOpInit *BO) { + if (BO->getOpcode() == BinOpInit::CONCAT) { + Init *L = BO->getLHS()->convertInitializerTo(this); + Init *R = BO->getRHS()->convertInitializerTo(this); + if (L == 0 || R == 0) return 0; + if (L != BO->getLHS() || R != BO->getRHS()) + return BinOpInit::get(BinOpInit::CONCAT, L, R, new DagRecTy); + return BO; + } + return 0; +} + +RecordRecTy *RecordRecTy::get(Record *R) { + return &dynamic_cast(*R->getDefInit()->getType()); +} + +std::string RecordRecTy::getAsString() const { + return Rec->getName(); +} + +Init *RecordRecTy::convertValue(DefInit *DI) { + // Ensure that DI is a subclass of Rec. + if (!DI->getDef()->isSubClassOf(Rec)) + return 0; + return DI; +} + +Init *RecordRecTy::convertValue(TypedInit *TI) { + // Ensure that TI is compatible with Rec. + if (RecordRecTy *RRT = dynamic_cast(TI->getType())) + if (RRT->getRecord()->isSubClassOf(getRecord()) || + RRT->getRecord() == getRecord()) + return TI; + return 0; +} + +bool RecordRecTy::baseClassOf(const RecordRecTy *RHS) const { + if (Rec == RHS->getRecord() || RHS->getRecord()->isSubClassOf(Rec)) + return true; + + const std::vector &SC = Rec->getSuperClasses(); + for (unsigned i = 0, e = SC.size(); i != e; ++i) + if (RHS->getRecord()->isSubClassOf(SC[i])) + return true; + + return false; +} + + +/// resolveTypes - Find a common type that T1 and T2 convert to. +/// Return 0 if no such type exists. +/// +RecTy *llvm::resolveTypes(RecTy *T1, RecTy *T2) { + if (!T1->typeIsConvertibleTo(T2)) { + if (!T2->typeIsConvertibleTo(T1)) { + // If one is a Record type, check superclasses + RecordRecTy *RecTy1 = dynamic_cast(T1); + if (RecTy1) { + // See if T2 inherits from a type T1 also inherits from + const std::vector &T1SuperClasses = + RecTy1->getRecord()->getSuperClasses(); + for(std::vector::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; + } + return NewType1; + } + } + } + RecordRecTy *RecTy2 = dynamic_cast(T2); + if (RecTy2) { + // See if T1 inherits from a type T2 also inherits from + const std::vector &T2SuperClasses = + RecTy2->getRecord()->getSuperClasses(); + for (std::vector::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; + } + return NewType2; + } + } + } + return 0; + } + return T2; + } + return T1; +} + + +//===----------------------------------------------------------------------===// +// Initializer implementations +//===----------------------------------------------------------------------===// + +void Init::dump() const { return print(errs()); } + +UnsetInit *UnsetInit::get() { + static UnsetInit TheInit; + return &TheInit; +} + +BitInit *BitInit::get(bool V) { + static BitInit True(true); + static BitInit False(false); + + return V ? &True : &False; +} + +static void +ProfileBitsInit(FoldingSetNodeID &ID, ArrayRef Range) { + ID.AddInteger(Range.size()); + + for (ArrayRef::iterator i = Range.begin(), + iend = Range.end(); + i != iend; + ++i) + ID.AddPointer(*i); +} + +BitsInit *BitsInit::get(ArrayRef Range) { + typedef FoldingSet Pool; + static Pool ThePool; + + FoldingSetNodeID ID; + ProfileBitsInit(ID, Range); + + void *IP = 0; + if (BitsInit *I = ThePool.FindNodeOrInsertPos(ID, IP)) + return I; + + BitsInit *I = new BitsInit(Range); + ThePool.InsertNode(I, IP); + + return I; +} + +void BitsInit::Profile(FoldingSetNodeID &ID) const { + ProfileBitsInit(ID, Bits); +} + +Init * +BitsInit::convertInitializerBitRange(const std::vector &Bits) const { + SmallVector NewBits(Bits.size()); + + for (unsigned i = 0, e = Bits.size(); i != e; ++i) { + if (Bits[i] >= getNumBits()) + return 0; + NewBits[i] = getBit(Bits[i]); + } + return BitsInit::get(NewBits); +} + +std::string BitsInit::getAsString() const { + std::string Result = "{ "; + for (unsigned i = 0, e = getNumBits(); i != e; ++i) { + if (i) Result += ", "; + if (Init *Bit = getBit(e-i-1)) + Result += Bit->getAsString(); + else + Result += "*"; + } + return Result + " }"; +} + +// resolveReferences - If there are any field references that refer to fields +// that have been filled in, we can propagate the values now. +// +Init *BitsInit::resolveReferences(Record &R, const RecordVal *RV) const { + bool Changed = false; + SmallVector NewBits(getNumBits()); + + for (unsigned i = 0, e = Bits.size(); i != e; ++i) { + Init *B; + Init *CurBit = getBit(i); + + do { + B = CurBit; + CurBit = CurBit->resolveReferences(R, RV); + Changed |= B != CurBit; + } while (B != CurBit); + NewBits[i] = CurBit; + } + + if (Changed) + return BitsInit::get(NewBits); + + return const_cast(this); +} + +IntInit *IntInit::get(int64_t V) { + typedef DenseMap Pool; + static Pool ThePool; + + IntInit *&I = ThePool[V]; + if (!I) I = new IntInit(V); + return I; +} + +std::string IntInit::getAsString() const { + return itostr(Value); +} + +Init * +IntInit::convertInitializerBitRange(const std::vector &Bits) const { + SmallVector NewBits(Bits.size()); + + for (unsigned i = 0, e = Bits.size(); i != e; ++i) { + if (Bits[i] >= 64) + return 0; + + NewBits[i] = BitInit::get(Value & (INT64_C(1) << Bits[i])); + } + return BitsInit::get(NewBits); +} + +StringInit *StringInit::get(const std::string &V) { + typedef StringMap Pool; + static Pool ThePool; + + StringInit *&I = ThePool[V]; + if (!I) I = new StringInit(V); + return I; +} + +CodeInit *CodeInit::get(const std::string &V) { + typedef StringMap Pool; + static Pool ThePool; + + CodeInit *&I = ThePool[V]; + if (!I) I = new CodeInit(V); + return I; +} + +static void ProfileListInit(FoldingSetNodeID &ID, + ArrayRef Range, + RecTy *EltTy) { + ID.AddInteger(Range.size()); + ID.AddPointer(EltTy); + + for (ArrayRef::iterator i = Range.begin(), + iend = Range.end(); + i != iend; + ++i) + ID.AddPointer(*i); +} + +ListInit *ListInit::get(ArrayRef Range, RecTy *EltTy) { + typedef FoldingSet 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; + if (ListInit *I = ThePool.FindNodeOrInsertPos(ID, IP)) + return I; + + ListInit *I = new ListInit(Range, EltTy); + ThePool.InsertNode(I, IP); + return I; +} + +void ListInit::Profile(FoldingSetNodeID &ID) const { + ListRecTy *ListType = dynamic_cast(getType()); + assert(ListType && "Bad type for ListInit!"); + RecTy *EltTy = ListType->getElementType(); + + ProfileListInit(ID, Values, EltTy); +} + +Init * +ListInit::convertInitListSlice(const std::vector &Elements) const { + std::vector Vals; + for (unsigned i = 0, e = Elements.size(); i != e; ++i) { + if (Elements[i] >= getSize()) + return 0; + Vals.push_back(getElement(Elements[i])); + } + return ListInit::get(Vals, getType()); +} + +Record *ListInit::getElementAsRecord(unsigned i) const { + assert(i < Values.size() && "List element index out of range!"); + DefInit *DI = dynamic_cast(Values[i]); + if (DI == 0) throw "Expected record in list!"; + return DI->getDef(); +} + +Init *ListInit::resolveReferences(Record &R, const RecordVal *RV) const { + std::vector Resolved; + Resolved.reserve(getSize()); + bool Changed = false; + + for (unsigned i = 0, e = getSize(); i != e; ++i) { + Init *E; + Init *CurElt = getElement(i); + + do { + E = CurElt; + CurElt = CurElt->resolveReferences(R, RV); + Changed |= E != CurElt; + } while (E != CurElt); + Resolved.push_back(E); + } + + if (Changed) + return ListInit::get(Resolved, getType()); + return const_cast(this); +} + +Init *ListInit::resolveListElementReference(Record &R, const RecordVal *IRV, + unsigned Elt) const { + if (Elt >= getSize()) + return 0; // Out of range reference. + Init *E = getElement(Elt); + // 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. + if (IRV || !dynamic_cast(E)) + return E; + return 0; +} + +std::string ListInit::getAsString() const { + std::string Result = "["; + for (unsigned i = 0, e = Values.size(); i != e; ++i) { + if (i) Result += ", "; + Result += Values[i]->getAsString(); + } + return Result + "]"; +} + +Init *OpInit::resolveBitReference(Record &R, const RecordVal *IRV, + unsigned Bit) const { + Init *Folded = Fold(&R, 0); + + if (Folded != this) { + TypedInit *Typed = dynamic_cast(Folded); + if (Typed) { + return Typed->resolveBitReference(R, IRV, Bit); + } + } + + return 0; +} + +Init *OpInit::resolveListElementReference(Record &R, const RecordVal *IRV, + unsigned Elt) const { + Init *Folded = Fold(&R, 0); + + if (Folded != this) { + TypedInit *Typed = dynamic_cast(Folded); + if (Typed) { + return Typed->resolveListElementReference(R, IRV, Elt); + } + } + + return 0; +} + +UnOpInit *UnOpInit::get(UnaryOp opc, Init *lhs, RecTy *Type) { + typedef std::pair, RecTy *> Key; + + typedef DenseMap 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; +} + +Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { + switch (getOpcode()) { + default: assert(0 && "Unknown unop"); + case CAST: { + if (getType()->getAsString() == "string") { + StringInit *LHSs = dynamic_cast(LHS); + if (LHSs) { + return LHSs; + } + + DefInit *LHSd = dynamic_cast(LHS); + if (LHSd) { + return StringInit::get(LHSd->getDef()->getName()); + } + } else { + StringInit *LHSs = dynamic_cast(LHS); + if (LHSs) { + std::string Name = LHSs->getValue(); + + // From TGParser::ParseIDValue + if (CurRec) { + if (const RecordVal *RV = CurRec->getValue(Name)) { + if (RV->getType() != getType()) + throw "type mismatch in cast"; + return VarInit::get(Name, RV->getType()); + } + + std::string TemplateArgName = CurRec->getName()+":"+Name; + if (CurRec->isTemplateArg(TemplateArgName)) { + const RecordVal *RV = CurRec->getValue(TemplateArgName); + assert(RV && "Template arg doesn't exist??"); + + if (RV->getType() != getType()) + throw "type mismatch in cast"; + + return VarInit::get(TemplateArgName, RV->getType()); + } + } + + if (CurMultiClass) { + std::string MCName = CurMultiClass->Rec.getName()+"::"+Name; + if (CurMultiClass->Rec.isTemplateArg(MCName)) { + const RecordVal *RV = CurMultiClass->Rec.getValue(MCName); + assert(RV && "Template arg doesn't exist??"); + + if (RV->getType() != getType()) + throw "type mismatch in cast"; + + return VarInit::get(MCName, RV->getType()); + } + } + + if (Record *D = (CurRec->getRecords()).getDef(Name)) + return DefInit::get(D); + + throw TGError(CurRec->getLoc(), "Undefined reference:'" + Name + "'\n"); + } + } + break; + } + case HEAD: { + ListInit *LHSl = dynamic_cast(LHS); + if (LHSl) { + if (LHSl->getSize() == 0) { + assert(0 && "Empty list in car"); + return 0; + } + return LHSl->getElement(0); + } + break; + } + case TAIL: { + ListInit *LHSl = dynamic_cast(LHS); + if (LHSl) { + if (LHSl->getSize() == 0) { + assert(0 && "Empty list in cdr"); + return 0; + } + // Note the +1. We can't just pass the result of getValues() + // directly. + ArrayRef::iterator begin = LHSl->getValues().begin()+1; + ArrayRef::iterator end = LHSl->getValues().end(); + ListInit *Result = + ListInit::get(ArrayRef(begin, end - begin), + LHSl->getType()); + return Result; + } + break; + } + case EMPTY: { + ListInit *LHSl = dynamic_cast(LHS); + if (LHSl) { + if (LHSl->getSize() == 0) { + return IntInit::get(1); + } else { + return IntInit::get(0); + } + } + StringInit *LHSs = dynamic_cast(LHS); + if (LHSs) { + if (LHSs->getValue().empty()) { + return IntInit::get(1); + } else { + return IntInit::get(0); + } + } + + break; + } + } + return const_cast(this); +} + +Init *UnOpInit::resolveReferences(Record &R, const RecordVal *RV) const { + Init *lhs = LHS->resolveReferences(R, RV); + + if (LHS != lhs) + return (UnOpInit::get(getOpcode(), lhs, getType()))->Fold(&R, 0); + return Fold(&R, 0); +} + +std::string UnOpInit::getAsString() const { + std::string Result; + switch (Opc) { + case CAST: Result = "!cast<" + getType()->getAsString() + ">"; break; + case HEAD: Result = "!head"; break; + case TAIL: Result = "!tail"; break; + case EMPTY: Result = "!empty"; break; + } + return Result + "(" + LHS->getAsString() + ")"; +} + +BinOpInit *BinOpInit::get(BinaryOp opc, Init *lhs, + Init *rhs, RecTy *Type) { + typedef std::pair< + std::pair, Init *>, + RecTy * + > Key; + + typedef DenseMap 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; +} + +Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { + switch (getOpcode()) { + default: assert(0 && "Unknown binop"); + case CONCAT: { + DagInit *LHSs = dynamic_cast(LHS); + DagInit *RHSs = dynamic_cast(RHS); + if (LHSs && RHSs) { + DefInit *LOp = dynamic_cast(LHSs->getOperator()); + DefInit *ROp = dynamic_cast(RHSs->getOperator()); + if (LOp == 0 || ROp == 0 || LOp->getDef() != ROp->getDef()) + throw "Concated Dag operators do not match!"; + std::vector Args; + std::vector 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)); + } + return DagInit::get(LHSs->getOperator(), "", Args, ArgNames); + } + break; + } + case STRCONCAT: { + StringInit *LHSs = dynamic_cast(LHS); + StringInit *RHSs = dynamic_cast(RHS); + if (LHSs && RHSs) + return StringInit::get(LHSs->getValue() + RHSs->getValue()); + break; + } + case EQ: { + // try to fold eq comparison for 'bit' and 'int', otherwise fallback + // to string objects. + IntInit* L = + dynamic_cast(LHS->convertInitializerTo(IntRecTy::get())); + IntInit* R = + dynamic_cast(RHS->convertInitializerTo(IntRecTy::get())); + + if (L && R) + return IntInit::get(L->getValue() == R->getValue()); + + StringInit *LHSs = dynamic_cast(LHS); + StringInit *RHSs = dynamic_cast(RHS); + + // Make sure we've resolved + if (LHSs && RHSs) + return IntInit::get(LHSs->getValue() == RHSs->getValue()); + + break; + } + case SHL: + case SRA: + case SRL: { + IntInit *LHSi = dynamic_cast(LHS); + IntInit *RHSi = dynamic_cast(RHS); + if (LHSi && RHSi) { + int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue(); + int64_t Result; + switch (getOpcode()) { + default: assert(0 && "Bad opcode!"); + case SHL: Result = LHSv << RHSv; break; + case SRA: Result = LHSv >> RHSv; break; + case SRL: Result = (uint64_t)LHSv >> (uint64_t)RHSv; break; + } + return IntInit::get(Result); + } + break; + } + } + return const_cast(this); +} + +Init *BinOpInit::resolveReferences(Record &R, const RecordVal *RV) const { + Init *lhs = LHS->resolveReferences(R, RV); + Init *rhs = RHS->resolveReferences(R, RV); + + if (LHS != lhs || RHS != rhs) + return (BinOpInit::get(getOpcode(), lhs, rhs, getType()))->Fold(&R, 0); + return Fold(&R, 0); +} + +std::string BinOpInit::getAsString() const { + std::string Result; + switch (Opc) { + case CONCAT: Result = "!con"; break; + case SHL: Result = "!shl"; break; + case SRA: Result = "!sra"; break; + case SRL: Result = "!srl"; break; + case EQ: Result = "!eq"; break; + case STRCONCAT: Result = "!strconcat"; break; + } + return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")"; +} + +TernOpInit *TernOpInit::get(TernaryOp opc, Init *lhs, + Init *mhs, Init *rhs, + RecTy *Type) { + typedef std::pair< + std::pair< + std::pair, Init *>, + Init * + >, + Init * + > Key; + + typedef DenseMap 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; +} + +static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type, + Record *CurRec, MultiClass *CurMultiClass); + +static Init *EvaluateOperation(OpInit *RHSo, Init *LHS, Init *Arg, + RecTy *Type, Record *CurRec, + MultiClass *CurMultiClass) { + std::vector NewOperands; + + TypedInit *TArg = dynamic_cast(Arg); + + // If this is a dag, recurse + if (TArg && TArg->getType()->getAsString() == "dag") { + Init *Result = ForeachHelper(LHS, Arg, RHSo, Type, + CurRec, CurMultiClass); + if (Result != 0) { + return Result; + } else { + return 0; + } + } + + for (int i = 0; i < RHSo->getNumOperands(); ++i) { + OpInit *RHSoo = dynamic_cast(RHSo->getOperand(i)); + + if (RHSoo) { + Init *Result = EvaluateOperation(RHSoo, LHS, Arg, + Type, CurRec, CurMultiClass); + if (Result != 0) { + NewOperands.push_back(Result); + } else { + NewOperands.push_back(Arg); + } + } else if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) { + NewOperands.push_back(Arg); + } else { + NewOperands.push_back(RHSo->getOperand(i)); + } + } + + // Now run the operator and use its result as the new leaf + const OpInit *NewOp = RHSo->clone(NewOperands); + Init *NewVal = NewOp->Fold(CurRec, CurMultiClass); + if (NewVal != NewOp) + return NewVal; + + return 0; +} + +static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type, + Record *CurRec, MultiClass *CurMultiClass) { + DagInit *MHSd = dynamic_cast(MHS); + ListInit *MHSl = dynamic_cast(MHS); + + DagRecTy *DagType = dynamic_cast(Type); + ListRecTy *ListType = dynamic_cast(Type); + + OpInit *RHSo = dynamic_cast(RHS); + + if (!RHSo) { + throw TGError(CurRec->getLoc(), "!foreach requires an operator\n"); + } + + TypedInit *LHSt = dynamic_cast(LHS); + + if (!LHSt) { + throw TGError(CurRec->getLoc(), "!foreach requires typed variable\n"); + } + + if ((MHSd && DagType) || (MHSl && ListType)) { + if (MHSd) { + Init *Val = MHSd->getOperator(); + Init *Result = EvaluateOperation(RHSo, LHS, Val, + Type, CurRec, CurMultiClass); + if (Result != 0) { + Val = Result; + } + + std::vector > args; + for (unsigned int i = 0; i < MHSd->getNumArgs(); ++i) { + Init *Arg; + std::string ArgName; + Arg = MHSd->getArg(i); + ArgName = MHSd->getArgName(i); + + // Process args + Init *Result = EvaluateOperation(RHSo, LHS, Arg, Type, + CurRec, CurMultiClass); + if (Result != 0) { + Arg = Result; + } + + // TODO: Process arg names + args.push_back(std::make_pair(Arg, ArgName)); + } + + return DagInit::get(Val, "", args); + } + if (MHSl) { + std::vector NewOperands; + std::vector NewList(MHSl->begin(), MHSl->end()); + + for (std::vector::iterator li = NewList.begin(), + liend = NewList.end(); + li != liend; + ++li) { + Init *Item = *li; + 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); + } else { + NewOperands.push_back(RHSo->getOperand(i)); + } + } + + // Now run the operator and use its result as the new list item + const OpInit *NewOp = RHSo->clone(NewOperands); + Init *NewItem = NewOp->Fold(CurRec, CurMultiClass); + if (NewItem != NewOp) + *li = NewItem; + } + return ListInit::get(NewList, MHSl->getType()); + } + } + return 0; +} + +Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { + switch (getOpcode()) { + default: assert(0 && "Unknown binop"); + case SUBST: { + DefInit *LHSd = dynamic_cast(LHS); + VarInit *LHSv = dynamic_cast(LHS); + StringInit *LHSs = dynamic_cast(LHS); + + DefInit *MHSd = dynamic_cast(MHS); + VarInit *MHSv = dynamic_cast(MHS); + StringInit *MHSs = dynamic_cast(MHS); + + DefInit *RHSd = dynamic_cast(RHS); + VarInit *RHSv = dynamic_cast(RHS); + StringInit *RHSs = dynamic_cast(RHS); + + if ((LHSd && MHSd && RHSd) + || (LHSv && MHSv && RHSv) + || (LHSs && MHSs && RHSs)) { + if (RHSd) { + Record *Val = RHSd->getDef(); + if (LHSd->getAsString() == RHSd->getAsString()) { + Val = MHSd->getDef(); + } + return DefInit::get(Val); + } + if (RHSv) { + std::string Val = RHSv->getName(); + if (LHSv->getAsString() == RHSv->getAsString()) { + Val = MHSv->getName(); + } + return VarInit::get(Val, getType()); + } + if (RHSs) { + std::string Val = RHSs->getValue(); + + std::string::size_type found; + std::string::size_type idx = 0; + do { + found = Val.find(LHSs->getValue(), idx); + if (found != std::string::npos) { + Val.replace(found, LHSs->getValue().size(), MHSs->getValue()); + } + idx = found + MHSs->getValue().size(); + } while (found != std::string::npos); + + return StringInit::get(Val); + } + } + break; + } + + case FOREACH: { + Init *Result = ForeachHelper(LHS, MHS, RHS, getType(), + CurRec, CurMultiClass); + if (Result != 0) { + return Result; + } + break; + } + + case IF: { + IntInit *LHSi = dynamic_cast(LHS); + if (Init *I = LHS->convertInitializerTo(IntRecTy::get())) + LHSi = dynamic_cast(I); + if (LHSi) { + if (LHSi->getValue()) { + return MHS; + } else { + return RHS; + } + } + break; + } + } + + return const_cast(this); +} + +Init *TernOpInit::resolveReferences(Record &R, + const RecordVal *RV) const { + Init *lhs = LHS->resolveReferences(R, RV); + + if (Opc == IF && lhs != LHS) { + IntInit *Value = dynamic_cast(lhs); + if (Init *I = lhs->convertInitializerTo(IntRecTy::get())) + Value = dynamic_cast(I); + if (Value != 0) { + // Short-circuit + if (Value->getValue()) { + Init *mhs = MHS->resolveReferences(R, RV); + return (TernOpInit::get(getOpcode(), lhs, mhs, + RHS, getType()))->Fold(&R, 0); + } else { + Init *rhs = RHS->resolveReferences(R, RV); + return (TernOpInit::get(getOpcode(), lhs, MHS, + rhs, getType()))->Fold(&R, 0); + } + } + } + + Init *mhs = MHS->resolveReferences(R, RV); + Init *rhs = RHS->resolveReferences(R, RV); + + if (LHS != lhs || MHS != mhs || RHS != rhs) + return (TernOpInit::get(getOpcode(), lhs, mhs, rhs, + getType()))->Fold(&R, 0); + return Fold(&R, 0); +} + +std::string TernOpInit::getAsString() const { + std::string Result; + switch (Opc) { + case SUBST: Result = "!subst"; break; + case FOREACH: Result = "!foreach"; break; + case IF: Result = "!if"; break; + } + return Result + "(" + LHS->getAsString() + ", " + MHS->getAsString() + ", " + + RHS->getAsString() + ")"; +} + +RecTy *TypedInit::getFieldType(const std::string &FieldName) const { + RecordRecTy *RecordType = dynamic_cast(getType()); + if (RecordType) { + RecordVal *Field = RecordType->getRecord()->getValue(FieldName); + if (Field) { + return Field->getType(); + } + } + return 0; +} + +Init * +TypedInit::convertInitializerBitRange(const std::vector &Bits) const { + BitsRecTy *T = dynamic_cast(getType()); + if (T == 0) return 0; // Cannot subscript a non-bits variable. + unsigned NumBits = T->getNumBits(); + + SmallVector NewBits(Bits.size()); + for (unsigned i = 0, e = Bits.size(); i != e; ++i) { + if (Bits[i] >= NumBits) + return 0; + + NewBits[i] = VarBitInit::get(const_cast(this), Bits[i]); + } + return BitsInit::get(NewBits); +} + +Init * +TypedInit::convertInitListSlice(const std::vector &Elements) const { + ListRecTy *T = dynamic_cast(getType()); + if (T == 0) return 0; // Cannot subscript a non-list variable. + + if (Elements.size() == 1) + return VarListElementInit::get(const_cast(this), Elements[0]); + + std::vector ListInits; + ListInits.reserve(Elements.size()); + for (unsigned i = 0, e = Elements.size(); i != e; ++i) + ListInits.push_back(VarListElementInit::get(const_cast(this), + Elements[i])); + return ListInit::get(ListInits, T); +} + + +VarInit *VarInit::get(const std::string &VN, RecTy *T) { + typedef std::pair Key; + typedef DenseMap Pool; + static Pool ThePool; + + Key TheKey(std::make_pair(T, VN)); + + VarInit *&I = ThePool[TheKey]; + if (!I) I = new VarInit(VN, T); + return I; +} + +Init *VarInit::resolveBitReference(Record &R, const RecordVal *IRV, + unsigned Bit) const { + if (R.isTemplateArg(getName())) return 0; + if (IRV && IRV->getName() != getName()) return 0; + + RecordVal *RV = R.getValue(getName()); + assert(RV && "Reference to a non-existent variable?"); + assert(dynamic_cast(RV->getValue())); + BitsInit *BI = (BitsInit*)RV->getValue(); + + assert(Bit < BI->getNumBits() && "Bit reference out of range!"); + Init *B = BI->getBit(Bit); + + // If the bit 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 + // VarBitInit with it. + if (IRV || !dynamic_cast(B)) + return B; + return 0; +} + +Init *VarInit::resolveListElementReference(Record &R, + const RecordVal *IRV, + unsigned Elt) const { + if (R.isTemplateArg(getName())) return 0; + if (IRV && IRV->getName() != getName()) return 0; + + RecordVal *RV = R.getValue(getName()); + assert(RV && "Reference to a non-existent variable?"); + ListInit *LI = dynamic_cast(RV->getValue()); + if (!LI) { + VarInit *VI = dynamic_cast(RV->getValue()); + assert(VI && "Invalid list element!"); + return VarListElementInit::get(VI, Elt); + } + + if (Elt >= LI->getSize()) + return 0; // Out of range reference. + Init *E = LI->getElement(Elt); + // 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. + if (IRV || !dynamic_cast(E)) + return E; + return 0; +} + + +RecTy *VarInit::getFieldType(const std::string &FieldName) const { + if (RecordRecTy *RTy = dynamic_cast(getType())) + if (const RecordVal *RV = RTy->getRecord()->getValue(FieldName)) + return RV->getType(); + return 0; +} + +Init *VarInit::getFieldInit(Record &R, const RecordVal *RV, + const std::string &FieldName) const { + if (dynamic_cast(getType())) + if (const RecordVal *Val = R.getValue(VarName)) { + if (RV != Val && (RV || dynamic_cast(Val->getValue()))) + return 0; + Init *TheInit = Val->getValue(); + assert(TheInit != this && "Infinite loop detected!"); + if (Init *I = TheInit->getFieldInit(R, RV, FieldName)) + return I; + else + return 0; + } + return 0; +} + +/// resolveReferences - This method is used by classes that refer to other +/// variables which may not be defined at the time the expression is formed. +/// If a value is set for the variable later, this method will be called on +/// users of the value to allow the value to propagate out. +/// +Init *VarInit::resolveReferences(Record &R, const RecordVal *RV) const { + if (RecordVal *Val = R.getValue(VarName)) + if (RV == Val || (RV == 0 && !dynamic_cast(Val->getValue()))) + return Val->getValue(); + return const_cast(this); +} + +VarBitInit *VarBitInit::get(TypedInit *T, unsigned B) { + typedef std::pair Key; + typedef DenseMap Pool; + + static Pool ThePool; + + Key TheKey(std::make_pair(T, B)); + + VarBitInit *&I = ThePool[TheKey]; + if (!I) I = new VarBitInit(T, B); + return I; +} + +std::string VarBitInit::getAsString() const { + return TI->getAsString() + "{" + utostr(Bit) + "}"; +} + +Init *VarBitInit::resolveReferences(Record &R, const RecordVal *RV) const { + if (Init *I = getVariable()->resolveBitReference(R, RV, getBitNum())) + return I; + return const_cast(this); +} + +VarListElementInit *VarListElementInit::get(TypedInit *T, + unsigned E) { + typedef std::pair Key; + typedef DenseMap Pool; + + static Pool ThePool; + + Key TheKey(std::make_pair(T, E)); + + VarListElementInit *&I = ThePool[TheKey]; + if (!I) I = new VarListElementInit(T, E); + return I; +} + +std::string VarListElementInit::getAsString() const { + return TI->getAsString() + "[" + utostr(Element) + "]"; +} + +Init * +VarListElementInit::resolveReferences(Record &R, const RecordVal *RV) const { + if (Init *I = getVariable()->resolveListElementReference(R, RV, + getElementNum())) + return I; + return const_cast(this); +} + +Init *VarListElementInit::resolveBitReference(Record &R, const RecordVal *RV, + unsigned Bit) const { + // FIXME: This should be implemented, to support references like: + // bit B = AA[0]{1}; + return 0; +} + +Init *VarListElementInit:: resolveListElementReference(Record &R, + const RecordVal *RV, + unsigned Elt) const { + Init *Result = TI->resolveListElementReference(R, RV, Element); + + if (Result) { + TypedInit *TInit = dynamic_cast(Result); + if (TInit) { + return TInit->resolveListElementReference(R, RV, Elt); + } + return Result; + } + + return 0; +} + +DefInit *DefInit::get(Record *R) { + return R->getDefInit(); +} + +RecTy *DefInit::getFieldType(const std::string &FieldName) const { + if (const RecordVal *RV = Def->getValue(FieldName)) + return RV->getType(); + return 0; +} + +Init *DefInit::getFieldInit(Record &R, const RecordVal *RV, + const std::string &FieldName) const { + return Def->getValue(FieldName)->getValue(); +} + + +std::string DefInit::getAsString() const { + return Def->getName(); +} + +FieldInit *FieldInit::get(Init *R, const std::string &FN) { + typedef std::pair Key; + typedef DenseMap Pool; + static Pool ThePool; + + Key TheKey(std::make_pair(R, FN)); + + FieldInit *&I = ThePool[TheKey]; + if (!I) I = new FieldInit(R, FN); + return I; +} + +Init *FieldInit::resolveBitReference(Record &R, const RecordVal *RV, + unsigned Bit) const { + if (Init *BitsVal = Rec->getFieldInit(R, RV, FieldName)) + if (BitsInit *BI = dynamic_cast(BitsVal)) { + assert(Bit < BI->getNumBits() && "Bit reference out of range!"); + Init *B = BI->getBit(Bit); + + if (dynamic_cast(B)) // If the bit is set. + return B; // Replace the VarBitInit with it. + } + return 0; +} + +Init *FieldInit::resolveListElementReference(Record &R, const RecordVal *RV, + unsigned Elt) const { + if (Init *ListVal = Rec->getFieldInit(R, RV, FieldName)) + if (ListInit *LI = dynamic_cast(ListVal)) { + if (Elt >= LI->getSize()) return 0; + Init *E = LI->getElement(Elt); + + // 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. + if (RV || !dynamic_cast(E)) + return E; + } + return 0; +} + +Init *FieldInit::resolveReferences(Record &R, const RecordVal *RV) const { + Init *NewRec = RV ? Rec->resolveReferences(R, RV) : Rec; + + Init *BitsVal = NewRec->getFieldInit(R, RV, FieldName); + if (BitsVal) { + Init *BVR = BitsVal->resolveReferences(R, RV); + return BVR->isComplete() ? BVR : const_cast(this); + } + + if (NewRec != Rec) { + return FieldInit::get(NewRec, FieldName); + } + return const_cast(this); +} + +void ProfileDagInit(FoldingSetNodeID &ID, + Init *V, + const std::string &VN, + ArrayRef ArgRange, + ArrayRef NameRange) { + ID.AddPointer(V); + ID.AddString(VN); + + ArrayRef::iterator Arg = ArgRange.begin(); + ArrayRef::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!"); +} + +DagInit * +DagInit::get(Init *V, const std::string &VN, + ArrayRef ArgRange, + ArrayRef NameRange) { + typedef FoldingSet Pool; + static Pool ThePool; + + FoldingSetNodeID ID; + ProfileDagInit(ID, V, VN, ArgRange, NameRange); + + void *IP = 0; + if (DagInit *I = ThePool.FindNodeOrInsertPos(ID, IP)) + return I; + + DagInit *I = new DagInit(V, VN, ArgRange, NameRange); + ThePool.InsertNode(I, IP); + + return I; +} + +DagInit * +DagInit::get(Init *V, const std::string &VN, + const std::vector > &args) { + typedef std::pair PairType; + + std::vector Args; + std::vector Names; + + for (std::vector::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); +} + +void DagInit::Profile(FoldingSetNodeID &ID) const { + ProfileDagInit(ID, Val, ValName, Args, ArgNames); +} + +Init *DagInit::resolveReferences(Record &R, const RecordVal *RV) const { + std::vector NewArgs; + for (unsigned i = 0, e = Args.size(); i != e; ++i) + NewArgs.push_back(Args[i]->resolveReferences(R, RV)); + + Init *Op = Val->resolveReferences(R, RV); + + if (Args != NewArgs || Op != Val) + return DagInit::get(Op, ValName, NewArgs, ArgNames); + + return const_cast(this); +} + + +std::string DagInit::getAsString() const { + std::string Result = "(" + Val->getAsString(); + if (!ValName.empty()) + Result += ":" + ValName; + if (Args.size()) { + Result += " " + Args[0]->getAsString(); + if (!ArgNames[0].empty()) Result += ":$" + ArgNames[0]; + for (unsigned i = 1, e = Args.size(); i != e; ++i) { + Result += ", " + Args[i]->getAsString(); + if (!ArgNames[i].empty()) Result += ":$" + ArgNames[i]; + } + } + return Result + ")"; +} + + +//===----------------------------------------------------------------------===// +// Other implementations +//===----------------------------------------------------------------------===// + +RecordVal::RecordVal(Init *N, RecTy *T, unsigned P) + : Name(N), Ty(T), Prefix(P) { + Value = Ty->convertValue(UnsetInit::get()); + assert(Value && "Cannot create unset value for current type!"); +} + +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 { + StringInit *NameString = dynamic_cast(Name); + assert(NameString && "RecordVal name is not a string!"); + return NameString->getValue(); +} + +void RecordVal::dump() const { errs() << *this; } + +void RecordVal::print(raw_ostream &OS, bool PrintSem) const { + if (getPrefix()) OS << "field "; + OS << *getType() << " " << getName(); + + if (getValue()) + OS << " = " << *getValue(); + + if (PrintSem) OS << ";\n"; +} + +unsigned Record::LastID = 0; + +void Record::checkName() { + // Ensure the record name has string type. + const TypedInit *TypedName = dynamic_cast(Name); + assert(TypedName && "Record name is not typed!"); + RecTy *Type = TypedName->getType(); + if (dynamic_cast(Type) == 0) { + llvm_unreachable("Record name is not a string!"); + } +} + +DefInit *Record::getDefInit() { + if (!TheInit) + TheInit = new DefInit(this, new RecordRecTy(this)); + return TheInit; +} + +const std::string &Record::getName() const { + const StringInit *NameString = + dynamic_cast(Name); + 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()); + Name = NewName; + TrackedRecords.addDef(this); + } else { + TrackedRecords.removeClass(Name->getAsUnquotedString()); + Name = NewName; + TrackedRecords.addClass(this); + } + checkName(); + // Since the Init for the name was changed, see if we can resolve + // any of it using members of the Record. + Init *ComputedName = Name->resolveReferences(*this, 0); + if (ComputedName != Name) { + setName(ComputedName); + } + // 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)); +} + +/// 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) { + if (Init *V = Values[i].getValue()) + Values[i].setValue(V->resolveReferences(*this, RV)); + } +} + +void Record::dump() const { errs() << *this; } + +raw_ostream &llvm::operator<<(raw_ostream &OS, const Record &R) { + OS << R.getName(); + + const std::vector &TArgs = R.getTemplateArgs(); + 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 &SC = R.getSuperClasses(); + if (!SC.empty()) { + OS << "\t//"; + for (unsigned i = 0, e = SC.size(); i != e; ++i) + OS << " " << SC[i]->getName(); + } + OS << "\n"; + + const std::vector &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"; +} + +/// getValueInit - Return the initializer for a value with the specified name, +/// or throw an exception if the field does not exist. +/// +Init *Record::getValueInit(StringRef FieldName) const { + const RecordVal *R = getValue(FieldName); + if (R == 0 || R->getValue() == 0) + throw "Record `" + getName() + "' does not have a field named `" + + FieldName.str() + "'!\n"; + return R->getValue(); +} + + +/// getValueAsString - This method looks up the specified field and returns its +/// value as a string, throwing an exception if the field does not exist or if +/// the value is not a string. +/// +std::string Record::getValueAsString(StringRef FieldName) const { + const RecordVal *R = getValue(FieldName); + if (R == 0 || R->getValue() == 0) + throw "Record `" + getName() + "' does not have a field named `" + + FieldName.str() + "'!\n"; + + if (StringInit *SI = dynamic_cast(R->getValue())) + return SI->getValue(); + throw "Record `" + getName() + "', field `" + FieldName.str() + + "' does not have a string initializer!"; +} + +/// getValueAsBitsInit - This method looks up the specified field and returns +/// its value as a BitsInit, throwing an exception if the field does not exist +/// or if the value is not the right type. +/// +BitsInit *Record::getValueAsBitsInit(StringRef FieldName) const { + const RecordVal *R = getValue(FieldName); + if (R == 0 || R->getValue() == 0) + throw "Record `" + getName() + "' does not have a field named `" + + FieldName.str() + "'!\n"; + + if (BitsInit *BI = dynamic_cast(R->getValue())) + return BI; + throw "Record `" + getName() + "', field `" + FieldName.str() + + "' does not have a BitsInit initializer!"; +} + +/// getValueAsListInit - This method looks up the specified field and returns +/// its value as a ListInit, throwing an exception if the field does not exist +/// or if the value is not the right type. +/// +ListInit *Record::getValueAsListInit(StringRef FieldName) const { + const RecordVal *R = getValue(FieldName); + if (R == 0 || R->getValue() == 0) + throw "Record `" + getName() + "' does not have a field named `" + + FieldName.str() + "'!\n"; + + if (ListInit *LI = dynamic_cast(R->getValue())) + return LI; + throw "Record `" + getName() + "', field `" + FieldName.str() + + "' does not have a list initializer!"; +} + +/// getValueAsListOfDefs - This method looks up the specified field and returns +/// its value as a vector of records, throwing an exception if the field does +/// not exist or if the value is not the right type. +/// +std::vector +Record::getValueAsListOfDefs(StringRef FieldName) const { + ListInit *List = getValueAsListInit(FieldName); + std::vector Defs; + for (unsigned i = 0; i < List->getSize(); i++) { + if (DefInit *DI = dynamic_cast(List->getElement(i))) { + Defs.push_back(DI->getDef()); + } else { + throw "Record `" + getName() + "', field `" + FieldName.str() + + "' list is not entirely DefInit!"; + } + } + return Defs; +} + +/// getValueAsInt - This method looks up the specified field and returns its +/// value as an int64_t, throwing an exception if the field does not exist or if +/// the value is not the right type. +/// +int64_t Record::getValueAsInt(StringRef FieldName) const { + const RecordVal *R = getValue(FieldName); + if (R == 0 || R->getValue() == 0) + throw "Record `" + getName() + "' does not have a field named `" + + FieldName.str() + "'!\n"; + + if (IntInit *II = dynamic_cast(R->getValue())) + return II->getValue(); + throw "Record `" + getName() + "', field `" + FieldName.str() + + "' does not have an int initializer!"; +} + +/// getValueAsListOfInts - This method looks up the specified field and returns +/// its value as a vector of integers, throwing an exception if the field does +/// not exist or if the value is not the right type. +/// +std::vector +Record::getValueAsListOfInts(StringRef FieldName) const { + ListInit *List = getValueAsListInit(FieldName); + std::vector Ints; + for (unsigned i = 0; i < List->getSize(); i++) { + if (IntInit *II = dynamic_cast(List->getElement(i))) { + Ints.push_back(II->getValue()); + } else { + throw "Record `" + getName() + "', field `" + FieldName.str() + + "' does not have a list of ints initializer!"; + } + } + return Ints; +} + +/// getValueAsListOfStrings - This method looks up the specified field and +/// returns its value as a vector of strings, throwing an exception if the +/// field does not exist or if the value is not the right type. +/// +std::vector +Record::getValueAsListOfStrings(StringRef FieldName) const { + ListInit *List = getValueAsListInit(FieldName); + std::vector Strings; + for (unsigned i = 0; i < List->getSize(); i++) { + if (StringInit *II = dynamic_cast(List->getElement(i))) { + Strings.push_back(II->getValue()); + } else { + throw "Record `" + getName() + "', field `" + FieldName.str() + + "' does not have a list of strings initializer!"; + } + } + return Strings; +} + +/// getValueAsDef - This method looks up the specified field and returns its +/// value as a Record, throwing an exception if the field does not exist or if +/// the value is not the right type. +/// +Record *Record::getValueAsDef(StringRef FieldName) const { + const RecordVal *R = getValue(FieldName); + if (R == 0 || R->getValue() == 0) + throw "Record `" + getName() + "' does not have a field named `" + + FieldName.str() + "'!\n"; + + if (DefInit *DI = dynamic_cast(R->getValue())) + return DI->getDef(); + throw "Record `" + getName() + "', field `" + FieldName.str() + + "' does not have a def initializer!"; +} + +/// getValueAsBit - This method looks up the specified field and returns its +/// value as a bit, throwing an exception if the field does not exist or if +/// the value is not the right type. +/// +bool Record::getValueAsBit(StringRef FieldName) const { + const RecordVal *R = getValue(FieldName); + if (R == 0 || R->getValue() == 0) + throw "Record `" + getName() + "' does not have a field named `" + + FieldName.str() + "'!\n"; + + if (BitInit *BI = dynamic_cast(R->getValue())) + return BI->getValue(); + throw "Record `" + getName() + "', field `" + FieldName.str() + + "' does not have a bit initializer!"; +} + +/// getValueAsDag - This method looks up the specified field and returns its +/// value as an Dag, throwing an exception if the field does not exist or if +/// the value is not the right type. +/// +DagInit *Record::getValueAsDag(StringRef FieldName) const { + const RecordVal *R = getValue(FieldName); + if (R == 0 || R->getValue() == 0) + throw "Record `" + getName() + "' does not have a field named `" + + FieldName.str() + "'!\n"; + + if (DagInit *DI = dynamic_cast(R->getValue())) + return DI; + throw "Record `" + getName() + "', field `" + FieldName.str() + + "' does not have a dag initializer!"; +} + +std::string Record::getValueAsCode(StringRef FieldName) const { + const RecordVal *R = getValue(FieldName); + if (R == 0 || R->getValue() == 0) + throw "Record `" + getName() + "' does not have a field named `" + + FieldName.str() + "'!\n"; + + if (CodeInit *CI = dynamic_cast(R->getValue())) + return CI->getValue(); + throw "Record `" + getName() + "', field `" + FieldName.str() + + "' does not have a code initializer!"; +} + + +void MultiClass::dump() const { + errs() << "Record:\n"; + Rec.dump(); + + errs() << "Defs:\n"; + for (RecordVector::const_iterator r = DefPrototypes.begin(), + rend = DefPrototypes.end(); + r != rend; + ++r) { + (*r)->dump(); + } +} + + +void RecordKeeper::dump() const { errs() << *this; } + +raw_ostream &llvm::operator<<(raw_ostream &OS, const RecordKeeper &RK) { + OS << "------------- Classes -----------------\n"; + const std::map &Classes = RK.getClasses(); + for (std::map::const_iterator I = Classes.begin(), + E = Classes.end(); I != E; ++I) + OS << "class " << *I->second; + + OS << "------------- Defs -----------------\n"; + const std::map &Defs = RK.getDefs(); + for (std::map::const_iterator I = Defs.begin(), + E = Defs.end(); I != E; ++I) + OS << "def " << *I->second; + return OS; +} + + +/// 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. +std::vector +RecordKeeper::getAllDerivedDefinitions(const std::string &ClassName) const { + Record *Class = getClass(ClassName); + if (!Class) + throw "ERROR: Couldn't find the `" + ClassName + "' class!\n"; + + std::vector Defs; + for (std::map::const_iterator I = getDefs().begin(), + E = getDefs().end(); I != E; ++I) + if (I->second->isSubClassOf(Class)) + Defs.push_back(I->second); + + return Defs; +} + diff --git a/lib/TableGen/TGLexer.cpp b/lib/TableGen/TGLexer.cpp new file mode 100644 index 00000000000..0dc1c70136b --- /dev/null +++ b/lib/TableGen/TGLexer.cpp @@ -0,0 +1,435 @@ +//===- TGLexer.cpp - Lexer for TableGen -----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implement the Lexer for TableGen. +// +//===----------------------------------------------------------------------===// + +#include "TGLexer.h" +#include "llvm/TableGen/Error.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Config/config.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" +#include +#include +#include +#include +#include +using namespace llvm; + +TGLexer::TGLexer(SourceMgr &SM) : SrcMgr(SM) { + CurBuffer = 0; + CurBuf = SrcMgr.getMemoryBuffer(CurBuffer); + CurPtr = CurBuf->getBufferStart(); + TokStart = 0; +} + +SMLoc TGLexer::getLoc() const { + return SMLoc::getFromPointer(TokStart); +} + +/// ReturnError - Set the error to the specified string at the specified +/// location. This is defined to always return tgtok::Error. +tgtok::TokKind TGLexer::ReturnError(const char *Loc, const Twine &Msg) { + PrintError(Loc, Msg); + return tgtok::Error; +} + +int TGLexer::getNextChar() { + char CurChar = *CurPtr++; + switch (CurChar) { + default: + return (unsigned char)CurChar; + case 0: { + // A nul character in the stream is either the end of the current buffer or + // a random nul in the file. Disambiguate that here. + if (CurPtr-1 != CurBuf->getBufferEnd()) + return 0; // Just whitespace. + + // If this is the end of an included file, pop the parent file off the + // include stack. + SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer); + if (ParentIncludeLoc != SMLoc()) { + CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc); + CurBuf = SrcMgr.getMemoryBuffer(CurBuffer); + CurPtr = ParentIncludeLoc.getPointer(); + return getNextChar(); + } + + // Otherwise, return end of file. + --CurPtr; // Another call to lex will return EOF again. + return EOF; + } + case '\n': + case '\r': + // Handle the newline character by ignoring it and incrementing the line + // count. However, be careful about 'dos style' files with \n\r in them. + // Only treat a \n\r or \r\n as a single line. + if ((*CurPtr == '\n' || (*CurPtr == '\r')) && + *CurPtr != CurChar) + ++CurPtr; // Eat the two char newline sequence. + return '\n'; + } +} + +tgtok::TokKind TGLexer::LexToken() { + TokStart = CurPtr; + // This always consumes at least one character. + int CurChar = getNextChar(); + + switch (CurChar) { + default: + // Handle letters: [a-zA-Z_#] + if (isalpha(CurChar) || CurChar == '_' || CurChar == '#') + return LexIdentifier(); + + // Unknown character, emit an error. + return ReturnError(TokStart, "Unexpected character"); + case EOF: return tgtok::Eof; + case ':': return tgtok::colon; + case ';': return tgtok::semi; + case '.': return tgtok::period; + case ',': return tgtok::comma; + case '<': return tgtok::less; + case '>': return tgtok::greater; + case ']': return tgtok::r_square; + case '{': return tgtok::l_brace; + case '}': return tgtok::r_brace; + case '(': return tgtok::l_paren; + case ')': return tgtok::r_paren; + case '=': return tgtok::equal; + case '?': return tgtok::question; + + case 0: + case ' ': + case '\t': + case '\n': + case '\r': + // Ignore whitespace. + return LexToken(); + case '/': + // If this is the start of a // comment, skip until the end of the line or + // the end of the buffer. + if (*CurPtr == '/') + SkipBCPLComment(); + else if (*CurPtr == '*') { + if (SkipCComment()) + return tgtok::Error; + } else // Otherwise, this is an error. + return ReturnError(TokStart, "Unexpected character"); + return LexToken(); + case '-': case '+': + case '0': case '1': case '2': case '3': case '4': case '5': case '6': + case '7': case '8': case '9': + return LexNumber(); + case '"': return LexString(); + case '$': return LexVarName(); + case '[': return LexBracket(); + case '!': return LexExclaim(); + } +} + +/// LexString - Lex "[^"]*" +tgtok::TokKind TGLexer::LexString() { + const char *StrStart = CurPtr; + + CurStrVal = ""; + + while (*CurPtr != '"') { + // If we hit the end of the buffer, report an error. + if (*CurPtr == 0 && CurPtr == CurBuf->getBufferEnd()) + return ReturnError(StrStart, "End of file in string literal"); + + if (*CurPtr == '\n' || *CurPtr == '\r') + return ReturnError(StrStart, "End of line in string literal"); + + if (*CurPtr != '\\') { + CurStrVal += *CurPtr++; + continue; + } + + ++CurPtr; + + switch (*CurPtr) { + case '\\': case '\'': case '"': + // These turn into their literal character. + CurStrVal += *CurPtr++; + break; + case 't': + CurStrVal += '\t'; + ++CurPtr; + break; + case 'n': + CurStrVal += '\n'; + ++CurPtr; + break; + + case '\n': + case '\r': + return ReturnError(CurPtr, "escaped newlines not supported in tblgen"); + + // If we hit the end of the buffer, report an error. + case '\0': + if (CurPtr == CurBuf->getBufferEnd()) + return ReturnError(StrStart, "End of file in string literal"); + // FALL THROUGH + default: + return ReturnError(CurPtr, "invalid escape in string literal"); + } + } + + ++CurPtr; + return tgtok::StrVal; +} + +tgtok::TokKind TGLexer::LexVarName() { + if (!isalpha(CurPtr[0]) && CurPtr[0] != '_') + return ReturnError(TokStart, "Invalid variable name"); + + // Otherwise, we're ok, consume the rest of the characters. + const char *VarNameStart = CurPtr++; + + while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_') + ++CurPtr; + + CurStrVal.assign(VarNameStart, CurPtr); + return tgtok::VarName; +} + + +tgtok::TokKind TGLexer::LexIdentifier() { + // The first letter is [a-zA-Z_#]. + const char *IdentStart = TokStart; + + // Match the rest of the identifier regex: [0-9a-zA-Z_#]* + while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_' || + *CurPtr == '#') + ++CurPtr; + + + // Check to see if this identifier is a keyword. + unsigned Len = CurPtr-IdentStart; + + if (Len == 3 && !memcmp(IdentStart, "int", 3)) return tgtok::Int; + if (Len == 3 && !memcmp(IdentStart, "bit", 3)) return tgtok::Bit; + if (Len == 4 && !memcmp(IdentStart, "bits", 4)) return tgtok::Bits; + if (Len == 6 && !memcmp(IdentStart, "string", 6)) return tgtok::String; + if (Len == 4 && !memcmp(IdentStart, "list", 4)) return tgtok::List; + if (Len == 4 && !memcmp(IdentStart, "code", 4)) return tgtok::Code; + if (Len == 3 && !memcmp(IdentStart, "dag", 3)) return tgtok::Dag; + + if (Len == 5 && !memcmp(IdentStart, "class", 5)) return tgtok::Class; + if (Len == 3 && !memcmp(IdentStart, "def", 3)) return tgtok::Def; + if (Len == 4 && !memcmp(IdentStart, "defm", 4)) return tgtok::Defm; + if (Len == 10 && !memcmp(IdentStart, "multiclass", 10)) + return tgtok::MultiClass; + if (Len == 5 && !memcmp(IdentStart, "field", 5)) return tgtok::Field; + if (Len == 3 && !memcmp(IdentStart, "let", 3)) return tgtok::Let; + if (Len == 2 && !memcmp(IdentStart, "in", 2)) return tgtok::In; + + if (Len == 7 && !memcmp(IdentStart, "include", 7)) { + if (LexInclude()) return tgtok::Error; + return Lex(); + } + + CurStrVal.assign(IdentStart, CurPtr); + return tgtok::Id; +} + +/// LexInclude - We just read the "include" token. Get the string token that +/// comes next and enter the include. +bool TGLexer::LexInclude() { + // The token after the include must be a string. + tgtok::TokKind Tok = LexToken(); + if (Tok == tgtok::Error) return true; + if (Tok != tgtok::StrVal) { + PrintError(getLoc(), "Expected filename after include"); + return true; + } + + // Get the string. + std::string Filename = CurStrVal; + std::string IncludedFile; + + + CurBuffer = SrcMgr.AddIncludeFile(Filename, SMLoc::getFromPointer(CurPtr), + IncludedFile); + if (CurBuffer == -1) { + PrintError(getLoc(), "Could not find include file '" + Filename + "'"); + return true; + } + + Dependencies.push_back(IncludedFile); + // Save the line number and lex buffer of the includer. + CurBuf = SrcMgr.getMemoryBuffer(CurBuffer); + CurPtr = CurBuf->getBufferStart(); + return false; +} + +void TGLexer::SkipBCPLComment() { + ++CurPtr; // skip the second slash. + while (1) { + switch (*CurPtr) { + case '\n': + case '\r': + return; // Newline is end of comment. + case 0: + // If this is the end of the buffer, end the comment. + if (CurPtr == CurBuf->getBufferEnd()) + return; + break; + } + // Otherwise, skip the character. + ++CurPtr; + } +} + +/// SkipCComment - This skips C-style /**/ comments. The only difference from C +/// is that we allow nesting. +bool TGLexer::SkipCComment() { + ++CurPtr; // skip the star. + unsigned CommentDepth = 1; + + while (1) { + int CurChar = getNextChar(); + switch (CurChar) { + case EOF: + PrintError(TokStart, "Unterminated comment!"); + return true; + case '*': + // End of the comment? + if (CurPtr[0] != '/') break; + + ++CurPtr; // End the */. + if (--CommentDepth == 0) + return false; + break; + case '/': + // Start of a nested comment? + if (CurPtr[0] != '*') break; + ++CurPtr; + ++CommentDepth; + break; + } + } +} + +/// LexNumber - Lex: +/// [-+]?[0-9]+ +/// 0x[0-9a-fA-F]+ +/// 0b[01]+ +tgtok::TokKind TGLexer::LexNumber() { + if (CurPtr[-1] == '0') { + if (CurPtr[0] == 'x') { + ++CurPtr; + const char *NumStart = CurPtr; + while (isxdigit(CurPtr[0])) + ++CurPtr; + + // Requires at least one hex digit. + if (CurPtr == NumStart) + return ReturnError(TokStart, "Invalid hexadecimal number"); + + errno = 0; + CurIntVal = strtoll(NumStart, 0, 16); + if (errno == EINVAL) + return ReturnError(TokStart, "Invalid hexadecimal number"); + if (errno == ERANGE) { + errno = 0; + CurIntVal = (int64_t)strtoull(NumStart, 0, 16); + if (errno == EINVAL) + return ReturnError(TokStart, "Invalid hexadecimal number"); + if (errno == ERANGE) + return ReturnError(TokStart, "Hexadecimal number out of range"); + } + return tgtok::IntVal; + } else if (CurPtr[0] == 'b') { + ++CurPtr; + const char *NumStart = CurPtr; + while (CurPtr[0] == '0' || CurPtr[0] == '1') + ++CurPtr; + + // Requires at least one binary digit. + if (CurPtr == NumStart) + return ReturnError(CurPtr-2, "Invalid binary number"); + CurIntVal = strtoll(NumStart, 0, 2); + return tgtok::IntVal; + } + } + + // Check for a sign without a digit. + if (!isdigit(CurPtr[0])) { + if (CurPtr[-1] == '-') + return tgtok::minus; + else if (CurPtr[-1] == '+') + return tgtok::plus; + } + + while (isdigit(CurPtr[0])) + ++CurPtr; + CurIntVal = strtoll(TokStart, 0, 10); + return tgtok::IntVal; +} + +/// LexBracket - We just read '['. If this is a code block, return it, +/// otherwise return the bracket. Match: '[' and '[{ ( [^}]+ | }[^]] )* }]' +tgtok::TokKind TGLexer::LexBracket() { + if (CurPtr[0] != '{') + return tgtok::l_square; + ++CurPtr; + const char *CodeStart = CurPtr; + while (1) { + int Char = getNextChar(); + if (Char == EOF) break; + + if (Char != '}') continue; + + Char = getNextChar(); + if (Char == EOF) break; + if (Char == ']') { + CurStrVal.assign(CodeStart, CurPtr-2); + return tgtok::CodeFragment; + } + } + + return ReturnError(CodeStart-2, "Unterminated Code Block"); +} + +/// LexExclaim - Lex '!' and '![a-zA-Z]+'. +tgtok::TokKind TGLexer::LexExclaim() { + if (!isalpha(*CurPtr)) + return ReturnError(CurPtr - 1, "Invalid \"!operator\""); + + const char *Start = CurPtr++; + while (isalpha(*CurPtr)) + ++CurPtr; + + // Check to see which operator this is. + tgtok::TokKind Kind = + StringSwitch(StringRef(Start, CurPtr - Start)) + .Case("eq", tgtok::XEq) + .Case("if", tgtok::XIf) + .Case("head", tgtok::XHead) + .Case("tail", tgtok::XTail) + .Case("con", tgtok::XConcat) + .Case("shl", tgtok::XSHL) + .Case("sra", tgtok::XSRA) + .Case("srl", tgtok::XSRL) + .Case("cast", tgtok::XCast) + .Case("empty", tgtok::XEmpty) + .Case("subst", tgtok::XSubst) + .Case("foreach", tgtok::XForEach) + .Case("strconcat", tgtok::XStrConcat) + .Default(tgtok::Error); + + return Kind != tgtok::Error ? Kind : ReturnError(Start-1, "Unknown operator"); +} + diff --git a/lib/TableGen/TGLexer.h b/lib/TableGen/TGLexer.h new file mode 100644 index 00000000000..84d328b12d9 --- /dev/null +++ b/lib/TableGen/TGLexer.h @@ -0,0 +1,125 @@ +//===- TGLexer.h - Lexer for TableGen Files ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class represents the Lexer for tablegen files. +// +//===----------------------------------------------------------------------===// + +#ifndef TGLEXER_H +#define TGLEXER_H + +#include "llvm/Support/DataTypes.h" +#include +#include +#include + +namespace llvm { +class MemoryBuffer; +class SourceMgr; +class SMLoc; +class Twine; + +namespace tgtok { + enum TokKind { + // Markers + Eof, Error, + + // Tokens with no info. + minus, plus, // - + + l_square, r_square, // [ ] + l_brace, r_brace, // { } + l_paren, r_paren, // ( ) + less, greater, // < > + colon, semi, // : ; + comma, period, // , . + equal, question, // = ? + + // Keywords. + Bit, Bits, Class, Code, Dag, Def, Defm, Field, In, Int, Let, List, + MultiClass, String, + + // !keywords. + XConcat, XSRA, XSRL, XSHL, XStrConcat, XCast, XSubst, + XForEach, XHead, XTail, XEmpty, XIf, XEq, + + // Integer value. + IntVal, + + // String valued tokens. + Id, StrVal, VarName, CodeFragment + }; +} + +/// TGLexer - TableGen Lexer class. +class TGLexer { + SourceMgr &SrcMgr; + + const char *CurPtr; + const MemoryBuffer *CurBuf; + + // Information about the current token. + const char *TokStart; + tgtok::TokKind CurCode; + std::string CurStrVal; // This is valid for ID, STRVAL, VARNAME, CODEFRAGMENT + int64_t CurIntVal; // This is valid for INTVAL. + + /// CurBuffer - This is the current buffer index we're lexing from as managed + /// by the SourceMgr object. + int CurBuffer; + /// Dependencies - This is the list of all included files. + std::vector Dependencies; + +public: + TGLexer(SourceMgr &SrcMgr); + ~TGLexer() {} + + tgtok::TokKind Lex() { + return CurCode = LexToken(); + } + + const std::vector &getDependencies() const { + return Dependencies; + } + + tgtok::TokKind getCode() const { return CurCode; } + + const std::string &getCurStrVal() const { + assert((CurCode == tgtok::Id || CurCode == tgtok::StrVal || + CurCode == tgtok::VarName || CurCode == tgtok::CodeFragment) && + "This token doesn't have a string value"); + return CurStrVal; + } + int64_t getCurIntVal() const { + assert(CurCode == tgtok::IntVal && "This token isn't an integer"); + return CurIntVal; + } + + SMLoc getLoc() const; + +private: + /// LexToken - Read the next token and return its code. + tgtok::TokKind LexToken(); + + tgtok::TokKind ReturnError(const char *Loc, const Twine &Msg); + + int getNextChar(); + void SkipBCPLComment(); + bool SkipCComment(); + tgtok::TokKind LexIdentifier(); + bool LexInclude(); + tgtok::TokKind LexString(); + tgtok::TokKind LexVarName(); + tgtok::TokKind LexNumber(); + tgtok::TokKind LexBracket(); + tgtok::TokKind LexExclaim(); +}; + +} // end namespace llvm + +#endif diff --git a/lib/TableGen/TGParser.cpp b/lib/TableGen/TGParser.cpp new file mode 100644 index 00000000000..1601a530b18 --- /dev/null +++ b/lib/TableGen/TGParser.cpp @@ -0,0 +1,2163 @@ +//===- TGParser.cpp - Parser for TableGen Files ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implement the Parser for TableGen. +// +//===----------------------------------------------------------------------===// + +#include "TGParser.h" +#include "llvm/TableGen/Record.h" +#include "llvm/ADT/StringExtras.h" +#include +#include +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/CommandLine.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Support Code for the Semantic Actions. +//===----------------------------------------------------------------------===// + +namespace llvm { +struct SubClassReference { + SMLoc RefLoc; + Record *Rec; + std::vector TemplateArgs; + SubClassReference() : Rec(0) {} + + bool isInvalid() const { return Rec == 0; } +}; + +struct SubMultiClassReference { + SMLoc RefLoc; + MultiClass *MC; + std::vector TemplateArgs; + SubMultiClassReference() : MC(0) {} + + bool isInvalid() const { return MC == 0; } + void dump() const; +}; + +void SubMultiClassReference::dump() const { + errs() << "Multiclass:\n"; + + MC->dump(); + + errs() << "Template args:\n"; + for (std::vector::const_iterator i = TemplateArgs.begin(), + iend = TemplateArgs.end(); + i != iend; + ++i) { + (*i)->dump(); + } +} + +} // end namespace llvm + +bool TGParser::AddValue(Record *CurRec, SMLoc Loc, const RecordVal &RV) { + if (CurRec == 0) + CurRec = &CurMultiClass->Rec; + + if (RecordVal *ERV = CurRec->getValue(RV.getName())) { + // The value already exists in the class, treat this as a set. + if (ERV->setValue(RV.getValue())) + return Error(Loc, "New definition of '" + RV.getName() + "' of type '" + + RV.getType()->getAsString() + "' is incompatible with " + + "previous definition of type '" + + ERV->getType()->getAsString() + "'"); + } else { + CurRec->addValue(RV); + } + return false; +} + +/// SetValue - +/// Return true on error, false on success. +bool TGParser::SetValue(Record *CurRec, SMLoc Loc, const std::string &ValName, + const std::vector &BitList, Init *V) { + if (!V) return false; + + if (CurRec == 0) CurRec = &CurMultiClass->Rec; + + RecordVal *RV = CurRec->getValue(ValName); + if (RV == 0) + return Error(Loc, "Value '" + ValName + "' unknown!"); + + // Do not allow assignments like 'X = X'. This will just cause infinite loops + // in the resolution machinery. + if (BitList.empty()) + if (VarInit *VI = dynamic_cast(V)) + if (VI->getName() == ValName) + return false; + + // If we are assigning to a subset of the bits in the value... then we must be + // assigning to a field of BitsRecTy, which must have a BitsInit + // initializer. + // + if (!BitList.empty()) { + BitsInit *CurVal = dynamic_cast(RV->getValue()); + if (CurVal == 0) + return Error(Loc, "Value '" + ValName + "' is not a bits type"); + + // Convert the incoming value to a bits type of the appropriate size... + Init *BI = V->convertInitializerTo(BitsRecTy::get(BitList.size())); + if (BI == 0) { + V->convertInitializerTo(BitsRecTy::get(BitList.size())); + return Error(Loc, "Initializer is not compatible with bit range"); + } + + // We should have a BitsInit type now. + BitsInit *BInit = dynamic_cast(BI); + assert(BInit != 0); + + SmallVector NewBits(CurVal->getNumBits()); + + // Loop over bits, assigning values as appropriate. + for (unsigned i = 0, e = BitList.size(); i != e; ++i) { + unsigned Bit = BitList[i]; + if (NewBits[Bit]) + return Error(Loc, "Cannot set bit #" + utostr(Bit) + " of value '" + + ValName + "' more than once"); + NewBits[Bit] = BInit->getBit(i); + } + + for (unsigned i = 0, e = CurVal->getNumBits(); i != e; ++i) + if (NewBits[i] == 0) + NewBits[i] = CurVal->getBit(i); + + V = BitsInit::get(NewBits); + } + + if (RV->setValue(V)) + return Error(Loc, "Value '" + ValName + "' of type '" + + RV->getType()->getAsString() + + "' is incompatible with initializer '" + V->getAsString() +"'"); + return false; +} + +/// AddSubClass - Add SubClass as a subclass to CurRec, resolving its template +/// args as SubClass's template arguments. +bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) { + Record *SC = SubClass.Rec; + // Add all of the values in the subclass into the current class. + const std::vector &Vals = SC->getValues(); + for (unsigned i = 0, e = Vals.size(); i != e; ++i) + if (AddValue(CurRec, SubClass.RefLoc, Vals[i])) + return true; + + const std::vector &TArgs = SC->getTemplateArgs(); + + // Ensure that an appropriate number of template arguments are specified. + if (TArgs.size() < SubClass.TemplateArgs.size()) + return Error(SubClass.RefLoc, "More template args specified than expected"); + + // Loop over all of the template arguments, setting them to the specified + // value or leaving them as the default if necessary. + for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { + if (i < SubClass.TemplateArgs.size()) { + // If a value is specified for this template arg, set it now. + if (SetValue(CurRec, SubClass.RefLoc, TArgs[i], std::vector(), + SubClass.TemplateArgs[i])) + return true; + + // Resolve it next. + CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i])); + + // Now remove it. + CurRec->removeValue(TArgs[i]); + + } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) { + return Error(SubClass.RefLoc,"Value not specified for template argument #" + + utostr(i) + " (" + TArgs[i] + ") of subclass '" + + SC->getName() + "'!"); + } + } + + // Since everything went well, we can now set the "superclass" list for the + // current record. + const std::vector &SCs = SC->getSuperClasses(); + for (unsigned i = 0, e = SCs.size(); i != e; ++i) { + if (CurRec->isSubClassOf(SCs[i])) + return Error(SubClass.RefLoc, + "Already subclass of '" + SCs[i]->getName() + "'!\n"); + CurRec->addSuperClass(SCs[i]); + } + + if (CurRec->isSubClassOf(SC)) + return Error(SubClass.RefLoc, + "Already subclass of '" + SC->getName() + "'!\n"); + CurRec->addSuperClass(SC); + return false; +} + +/// AddSubMultiClass - Add SubMultiClass as a subclass to +/// CurMC, resolving its template args as SubMultiClass's +/// template arguments. +bool TGParser::AddSubMultiClass(MultiClass *CurMC, + SubMultiClassReference &SubMultiClass) { + MultiClass *SMC = SubMultiClass.MC; + Record *CurRec = &CurMC->Rec; + + const std::vector &MCVals = CurRec->getValues(); + + // Add all of the values in the subclass into the current class. + const std::vector &SMCVals = SMC->Rec.getValues(); + for (unsigned i = 0, e = SMCVals.size(); i != e; ++i) + if (AddValue(CurRec, SubMultiClass.RefLoc, SMCVals[i])) + return true; + + int newDefStart = CurMC->DefPrototypes.size(); + + // Add all of the defs in the subclass into the current multiclass. + for (MultiClass::RecordVector::const_iterator i = SMC->DefPrototypes.begin(), + iend = SMC->DefPrototypes.end(); + i != iend; + ++i) { + // Clone the def and add it to the current multiclass + Record *NewDef = new Record(**i); + + // Add all of the values in the superclass into the current def. + for (unsigned i = 0, e = MCVals.size(); i != e; ++i) + if (AddValue(NewDef, SubMultiClass.RefLoc, MCVals[i])) + return true; + + CurMC->DefPrototypes.push_back(NewDef); + } + + const std::vector &SMCTArgs = SMC->Rec.getTemplateArgs(); + + // Ensure that an appropriate number of template arguments are + // specified. + if (SMCTArgs.size() < SubMultiClass.TemplateArgs.size()) + return Error(SubMultiClass.RefLoc, + "More template args specified than expected"); + + // Loop over all of the template arguments, setting them to the specified + // value or leaving them as the default if necessary. + for (unsigned i = 0, e = SMCTArgs.size(); i != e; ++i) { + if (i < SubMultiClass.TemplateArgs.size()) { + // If a value is specified for this template arg, set it in the + // superclass now. + if (SetValue(CurRec, SubMultiClass.RefLoc, SMCTArgs[i], + std::vector(), + SubMultiClass.TemplateArgs[i])) + return true; + + // Resolve it next. + CurRec->resolveReferencesTo(CurRec->getValue(SMCTArgs[i])); + + // Now remove it. + CurRec->removeValue(SMCTArgs[i]); + + // If a value is specified for this template arg, set it in the + // new defs now. + for (MultiClass::RecordVector::iterator j = + CurMC->DefPrototypes.begin() + newDefStart, + jend = CurMC->DefPrototypes.end(); + j != jend; + ++j) { + Record *Def = *j; + + if (SetValue(Def, SubMultiClass.RefLoc, SMCTArgs[i], + std::vector(), + SubMultiClass.TemplateArgs[i])) + return true; + + // Resolve it next. + Def->resolveReferencesTo(Def->getValue(SMCTArgs[i])); + + // Now remove it + Def->removeValue(SMCTArgs[i]); + } + } else if (!CurRec->getValue(SMCTArgs[i])->getValue()->isComplete()) { + return Error(SubMultiClass.RefLoc, + "Value not specified for template argument #" + + utostr(i) + " (" + SMCTArgs[i] + ") of subclass '" + + SMC->Rec.getName() + "'!"); + } + } + + return false; +} + +//===----------------------------------------------------------------------===// +// Parser Code +//===----------------------------------------------------------------------===// + +/// isObjectStart - Return true if this is a valid first token for an Object. +static bool isObjectStart(tgtok::TokKind K) { + return K == tgtok::Class || K == tgtok::Def || + K == tgtok::Defm || K == tgtok::Let || K == tgtok::MultiClass; +} + +static std::string GetNewAnonymousName() { + static unsigned AnonCounter = 0; + return "anonymous."+utostr(AnonCounter++); +} + +/// ParseObjectName - If an object name is specified, return it. Otherwise, +/// return an anonymous name. +/// ObjectName ::= ID +/// ObjectName ::= /*empty*/ +/// +std::string TGParser::ParseObjectName() { + if (Lex.getCode() != tgtok::Id) + return GetNewAnonymousName(); + + std::string Ret = Lex.getCurStrVal(); + Lex.Lex(); + return Ret; +} + + +/// ParseClassID - Parse and resolve a reference to a class name. This returns +/// null on error. +/// +/// ClassID ::= ID +/// +Record *TGParser::ParseClassID() { + if (Lex.getCode() != tgtok::Id) { + TokError("expected name for ClassID"); + return 0; + } + + Record *Result = Records.getClass(Lex.getCurStrVal()); + if (Result == 0) + TokError("Couldn't find class '" + Lex.getCurStrVal() + "'"); + + Lex.Lex(); + return Result; +} + +/// ParseMultiClassID - Parse and resolve a reference to a multiclass name. +/// This returns null on error. +/// +/// MultiClassID ::= ID +/// +MultiClass *TGParser::ParseMultiClassID() { + if (Lex.getCode() != tgtok::Id) { + TokError("expected name for ClassID"); + return 0; + } + + MultiClass *Result = MultiClasses[Lex.getCurStrVal()]; + if (Result == 0) + TokError("Couldn't find class '" + Lex.getCurStrVal() + "'"); + + Lex.Lex(); + return Result; +} + +Record *TGParser::ParseDefmID() { + if (Lex.getCode() != tgtok::Id) { + TokError("expected multiclass name"); + return 0; + } + + MultiClass *MC = MultiClasses[Lex.getCurStrVal()]; + if (MC == 0) { + TokError("Couldn't find multiclass '" + Lex.getCurStrVal() + "'"); + return 0; + } + + Lex.Lex(); + return &MC->Rec; +} + + +/// ParseSubClassReference - Parse a reference to a subclass or to a templated +/// subclass. This returns a SubClassRefTy with a null Record* on error. +/// +/// SubClassRef ::= ClassID +/// SubClassRef ::= ClassID '<' ValueList '>' +/// +SubClassReference TGParser:: +ParseSubClassReference(Record *CurRec, bool isDefm) { + SubClassReference Result; + Result.RefLoc = Lex.getLoc(); + + if (isDefm) + Result.Rec = ParseDefmID(); + else + Result.Rec = ParseClassID(); + if (Result.Rec == 0) return Result; + + // If there is no template arg list, we're done. + if (Lex.getCode() != tgtok::less) + return Result; + Lex.Lex(); // Eat the '<' + + if (Lex.getCode() == tgtok::greater) { + TokError("subclass reference requires a non-empty list of template values"); + Result.Rec = 0; + return Result; + } + + Result.TemplateArgs = ParseValueList(CurRec, Result.Rec); + if (Result.TemplateArgs.empty()) { + Result.Rec = 0; // Error parsing value list. + return Result; + } + + if (Lex.getCode() != tgtok::greater) { + TokError("expected '>' in template value list"); + Result.Rec = 0; + return Result; + } + Lex.Lex(); + + return Result; +} + +/// ParseSubMultiClassReference - Parse a reference to a subclass or to a +/// templated submulticlass. This returns a SubMultiClassRefTy with a null +/// Record* on error. +/// +/// SubMultiClassRef ::= MultiClassID +/// SubMultiClassRef ::= MultiClassID '<' ValueList '>' +/// +SubMultiClassReference TGParser:: +ParseSubMultiClassReference(MultiClass *CurMC) { + SubMultiClassReference Result; + Result.RefLoc = Lex.getLoc(); + + Result.MC = ParseMultiClassID(); + if (Result.MC == 0) return Result; + + // If there is no template arg list, we're done. + if (Lex.getCode() != tgtok::less) + return Result; + Lex.Lex(); // Eat the '<' + + if (Lex.getCode() == tgtok::greater) { + TokError("subclass reference requires a non-empty list of template values"); + Result.MC = 0; + return Result; + } + + Result.TemplateArgs = ParseValueList(&CurMC->Rec, &Result.MC->Rec); + if (Result.TemplateArgs.empty()) { + Result.MC = 0; // Error parsing value list. + return Result; + } + + if (Lex.getCode() != tgtok::greater) { + TokError("expected '>' in template value list"); + Result.MC = 0; + return Result; + } + Lex.Lex(); + + return Result; +} + +/// ParseRangePiece - Parse a bit/value range. +/// RangePiece ::= INTVAL +/// RangePiece ::= INTVAL '-' INTVAL +/// RangePiece ::= INTVAL INTVAL +bool TGParser::ParseRangePiece(std::vector &Ranges) { + if (Lex.getCode() != tgtok::IntVal) { + TokError("expected integer or bitrange"); + return true; + } + int64_t Start = Lex.getCurIntVal(); + int64_t End; + + if (Start < 0) + return TokError("invalid range, cannot be negative"); + + switch (Lex.Lex()) { // eat first character. + default: + Ranges.push_back(Start); + return false; + case tgtok::minus: + if (Lex.Lex() != tgtok::IntVal) { + TokError("expected integer value as end of range"); + return true; + } + End = Lex.getCurIntVal(); + break; + case tgtok::IntVal: + End = -Lex.getCurIntVal(); + break; + } + if (End < 0) + return TokError("invalid range, cannot be negative"); + Lex.Lex(); + + // Add to the range. + if (Start < End) { + for (; Start <= End; ++Start) + Ranges.push_back(Start); + } else { + for (; Start >= End; --Start) + Ranges.push_back(Start); + } + return false; +} + +/// ParseRangeList - Parse a list of scalars and ranges into scalar values. +/// +/// RangeList ::= RangePiece (',' RangePiece)* +/// +std::vector TGParser::ParseRangeList() { + std::vector Result; + + // Parse the first piece. + if (ParseRangePiece(Result)) + return std::vector(); + while (Lex.getCode() == tgtok::comma) { + Lex.Lex(); // Eat the comma. + + // Parse the next range piece. + if (ParseRangePiece(Result)) + return std::vector(); + } + return Result; +} + +/// ParseOptionalRangeList - Parse either a range list in <>'s or nothing. +/// OptionalRangeList ::= '<' RangeList '>' +/// OptionalRangeList ::= /*empty*/ +bool TGParser::ParseOptionalRangeList(std::vector &Ranges) { + if (Lex.getCode() != tgtok::less) + return false; + + SMLoc StartLoc = Lex.getLoc(); + Lex.Lex(); // eat the '<' + + // Parse the range list. + Ranges = ParseRangeList(); + if (Ranges.empty()) return true; + + if (Lex.getCode() != tgtok::greater) { + TokError("expected '>' at end of range list"); + return Error(StartLoc, "to match this '<'"); + } + Lex.Lex(); // eat the '>'. + return false; +} + +/// ParseOptionalBitList - Parse either a bit list in {}'s or nothing. +/// OptionalBitList ::= '{' RangeList '}' +/// OptionalBitList ::= /*empty*/ +bool TGParser::ParseOptionalBitList(std::vector &Ranges) { + if (Lex.getCode() != tgtok::l_brace) + return false; + + SMLoc StartLoc = Lex.getLoc(); + Lex.Lex(); // eat the '{' + + // Parse the range list. + Ranges = ParseRangeList(); + if (Ranges.empty()) return true; + + if (Lex.getCode() != tgtok::r_brace) { + TokError("expected '}' at end of bit list"); + return Error(StartLoc, "to match this '{'"); + } + Lex.Lex(); // eat the '}'. + return false; +} + + +/// ParseType - Parse and return a tblgen type. This returns null on error. +/// +/// Type ::= STRING // string type +/// Type ::= BIT // bit type +/// Type ::= BITS '<' INTVAL '>' // bits type +/// Type ::= INT // int type +/// Type ::= LIST '<' Type '>' // list type +/// Type ::= CODE // code type +/// Type ::= DAG // dag type +/// Type ::= ClassID // Record Type +/// +RecTy *TGParser::ParseType() { + switch (Lex.getCode()) { + default: TokError("Unknown token when expecting a type"); return 0; + case tgtok::String: Lex.Lex(); return StringRecTy::get(); + case tgtok::Bit: Lex.Lex(); return BitRecTy::get(); + case tgtok::Int: Lex.Lex(); return IntRecTy::get(); + case tgtok::Code: Lex.Lex(); return CodeRecTy::get(); + case tgtok::Dag: Lex.Lex(); return DagRecTy::get(); + case tgtok::Id: + if (Record *R = ParseClassID()) return RecordRecTy::get(R); + return 0; + case tgtok::Bits: { + if (Lex.Lex() != tgtok::less) { // Eat 'bits' + TokError("expected '<' after bits type"); + return 0; + } + if (Lex.Lex() != tgtok::IntVal) { // Eat '<' + TokError("expected integer in bits type"); + return 0; + } + uint64_t Val = Lex.getCurIntVal(); + if (Lex.Lex() != tgtok::greater) { // Eat count. + TokError("expected '>' at end of bits type"); + return 0; + } + Lex.Lex(); // Eat '>' + return BitsRecTy::get(Val); + } + case tgtok::List: { + if (Lex.Lex() != tgtok::less) { // Eat 'bits' + TokError("expected '<' after list type"); + return 0; + } + Lex.Lex(); // Eat '<' + RecTy *SubType = ParseType(); + if (SubType == 0) return 0; + + if (Lex.getCode() != tgtok::greater) { + TokError("expected '>' at end of list type"); + return 0; + } + Lex.Lex(); // Eat '>' + return ListRecTy::get(SubType); + } + } +} + +/// ParseIDValue - Parse an ID as a value and decode what it means. +/// +/// IDValue ::= ID [def local value] +/// IDValue ::= ID [def template arg] +/// IDValue ::= ID [multiclass local value] +/// IDValue ::= ID [multiclass template argument] +/// IDValue ::= ID [def name] +/// +Init *TGParser::ParseIDValue(Record *CurRec) { + assert(Lex.getCode() == tgtok::Id && "Expected ID in ParseIDValue"); + std::string Name = Lex.getCurStrVal(); + SMLoc Loc = Lex.getLoc(); + Lex.Lex(); + return ParseIDValue(CurRec, Name, Loc); +} + +/// ParseIDValue - This is just like ParseIDValue above, but it assumes the ID +/// has already been read. +Init *TGParser::ParseIDValue(Record *CurRec, + const std::string &Name, SMLoc NameLoc) { + if (CurRec) { + if (const RecordVal *RV = CurRec->getValue(Name)) + return VarInit::get(Name, RV->getType()); + + std::string TemplateArgName = CurRec->getName()+":"+Name; + if (CurRec->isTemplateArg(TemplateArgName)) { + const RecordVal *RV = CurRec->getValue(TemplateArgName); + assert(RV && "Template arg doesn't exist??"); + return VarInit::get(TemplateArgName, RV->getType()); + } + } + + if (CurMultiClass) { + std::string MCName = CurMultiClass->Rec.getName()+"::"+Name; + if (CurMultiClass->Rec.isTemplateArg(MCName)) { + const RecordVal *RV = CurMultiClass->Rec.getValue(MCName); + assert(RV && "Template arg doesn't exist??"); + return VarInit::get(MCName, RV->getType()); + } + } + + if (Record *D = Records.getDef(Name)) + return DefInit::get(D); + + Error(NameLoc, "Variable not defined: '" + Name + "'"); + return 0; +} + +/// ParseOperation - Parse an operator. This returns null on error. +/// +/// Operation ::= XOperator ['<' Type '>'] '(' Args ')' +/// +Init *TGParser::ParseOperation(Record *CurRec) { + switch (Lex.getCode()) { + default: + TokError("unknown operation"); + return 0; + break; + case tgtok::XHead: + case tgtok::XTail: + case tgtok::XEmpty: + case tgtok::XCast: { // Value ::= !unop '(' Value ')' + UnOpInit::UnaryOp Code; + RecTy *Type = 0; + + switch (Lex.getCode()) { + default: assert(0 && "Unhandled code!"); + case tgtok::XCast: + Lex.Lex(); // eat the operation + Code = UnOpInit::CAST; + + Type = ParseOperatorType(); + + if (Type == 0) { + TokError("did not get type for unary operator"); + return 0; + } + + break; + case tgtok::XHead: + Lex.Lex(); // eat the operation + Code = UnOpInit::HEAD; + break; + case tgtok::XTail: + Lex.Lex(); // eat the operation + Code = UnOpInit::TAIL; + break; + case tgtok::XEmpty: + Lex.Lex(); // eat the operation + Code = UnOpInit::EMPTY; + Type = IntRecTy::get(); + break; + } + if (Lex.getCode() != tgtok::l_paren) { + TokError("expected '(' after unary operator"); + return 0; + } + Lex.Lex(); // eat the '(' + + Init *LHS = ParseValue(CurRec); + if (LHS == 0) return 0; + + if (Code == UnOpInit::HEAD + || Code == UnOpInit::TAIL + || Code == UnOpInit::EMPTY) { + ListInit *LHSl = dynamic_cast(LHS); + StringInit *LHSs = dynamic_cast(LHS); + TypedInit *LHSt = dynamic_cast(LHS); + if (LHSl == 0 && LHSs == 0 && LHSt == 0) { + TokError("expected list or string type argument in unary operator"); + return 0; + } + if (LHSt) { + ListRecTy *LType = dynamic_cast(LHSt->getType()); + StringRecTy *SType = dynamic_cast(LHSt->getType()); + if (LType == 0 && SType == 0) { + TokError("expected list or string type argumnet in unary operator"); + return 0; + } + } + + if (Code == UnOpInit::HEAD + || Code == UnOpInit::TAIL) { + if (LHSl == 0 && LHSt == 0) { + TokError("expected list type argumnet in unary operator"); + return 0; + } + + if (LHSl && LHSl->getSize() == 0) { + TokError("empty list argument in unary operator"); + return 0; + } + if (LHSl) { + Init *Item = LHSl->getElement(0); + TypedInit *Itemt = dynamic_cast(Item); + if (Itemt == 0) { + TokError("untyped list element in unary operator"); + return 0; + } + if (Code == UnOpInit::HEAD) { + Type = Itemt->getType(); + } else { + Type = ListRecTy::get(Itemt->getType()); + } + } else { + assert(LHSt && "expected list type argument in unary operator"); + ListRecTy *LType = dynamic_cast(LHSt->getType()); + if (LType == 0) { + TokError("expected list type argumnet in unary operator"); + return 0; + } + if (Code == UnOpInit::HEAD) { + Type = LType->getElementType(); + } else { + Type = LType; + } + } + } + } + + if (Lex.getCode() != tgtok::r_paren) { + TokError("expected ')' in unary operator"); + return 0; + } + Lex.Lex(); // eat the ')' + return (UnOpInit::get(Code, LHS, Type))->Fold(CurRec, CurMultiClass); + } + + case tgtok::XConcat: + case tgtok::XSRA: + case tgtok::XSRL: + case tgtok::XSHL: + case tgtok::XEq: + case tgtok::XStrConcat: { // Value ::= !binop '(' Value ',' Value ')' + tgtok::TokKind OpTok = Lex.getCode(); + SMLoc OpLoc = Lex.getLoc(); + Lex.Lex(); // eat the operation + + BinOpInit::BinaryOp Code; + RecTy *Type = 0; + + switch (OpTok) { + default: assert(0 && "Unhandled code!"); + case tgtok::XConcat: Code = BinOpInit::CONCAT;Type = DagRecTy::get(); break; + case tgtok::XSRA: Code = BinOpInit::SRA; Type = IntRecTy::get(); break; + case tgtok::XSRL: Code = BinOpInit::SRL; Type = IntRecTy::get(); break; + case tgtok::XSHL: Code = BinOpInit::SHL; Type = IntRecTy::get(); break; + case tgtok::XEq: Code = BinOpInit::EQ; Type = BitRecTy::get(); break; + case tgtok::XStrConcat: + Code = BinOpInit::STRCONCAT; + Type = StringRecTy::get(); + break; + } + + if (Lex.getCode() != tgtok::l_paren) { + TokError("expected '(' after binary operator"); + return 0; + } + Lex.Lex(); // eat the '(' + + SmallVector InitList; + + InitList.push_back(ParseValue(CurRec)); + if (InitList.back() == 0) return 0; + + while (Lex.getCode() == tgtok::comma) { + Lex.Lex(); // eat the ',' + + InitList.push_back(ParseValue(CurRec)); + if (InitList.back() == 0) return 0; + } + + if (Lex.getCode() != tgtok::r_paren) { + TokError("expected ')' in operator"); + return 0; + } + Lex.Lex(); // eat the ')' + + // We allow multiple operands to associative operators like !strconcat as + // shorthand for nesting them. + if (Code == BinOpInit::STRCONCAT) { + while (InitList.size() > 2) { + Init *RHS = InitList.pop_back_val(); + RHS = (BinOpInit::get(Code, InitList.back(), RHS, Type)) + ->Fold(CurRec, CurMultiClass); + InitList.back() = RHS; + } + } + + if (InitList.size() == 2) + return (BinOpInit::get(Code, InitList[0], InitList[1], Type)) + ->Fold(CurRec, CurMultiClass); + + Error(OpLoc, "expected two operands to operator"); + return 0; + } + + case tgtok::XIf: + case tgtok::XForEach: + case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')' + TernOpInit::TernaryOp Code; + RecTy *Type = 0; + + tgtok::TokKind LexCode = Lex.getCode(); + Lex.Lex(); // eat the operation + switch (LexCode) { + default: assert(0 && "Unhandled code!"); + case tgtok::XIf: + Code = TernOpInit::IF; + break; + case tgtok::XForEach: + Code = TernOpInit::FOREACH; + break; + case tgtok::XSubst: + Code = TernOpInit::SUBST; + break; + } + if (Lex.getCode() != tgtok::l_paren) { + TokError("expected '(' after ternary operator"); + return 0; + } + Lex.Lex(); // eat the '(' + + Init *LHS = ParseValue(CurRec); + if (LHS == 0) return 0; + + if (Lex.getCode() != tgtok::comma) { + TokError("expected ',' in ternary operator"); + return 0; + } + Lex.Lex(); // eat the ',' + + Init *MHS = ParseValue(CurRec); + if (MHS == 0) return 0; + + if (Lex.getCode() != tgtok::comma) { + TokError("expected ',' in ternary operator"); + return 0; + } + Lex.Lex(); // eat the ',' + + Init *RHS = ParseValue(CurRec); + if (RHS == 0) return 0; + + if (Lex.getCode() != tgtok::r_paren) { + TokError("expected ')' in binary operator"); + return 0; + } + Lex.Lex(); // eat the ')' + + switch (LexCode) { + default: assert(0 && "Unhandled code!"); + case tgtok::XIf: { + // FIXME: The `!if' operator doesn't handle non-TypedInit well at + // all. This can be made much more robust. + TypedInit *MHSt = dynamic_cast(MHS); + TypedInit *RHSt = dynamic_cast(RHS); + + RecTy *MHSTy = 0; + RecTy *RHSTy = 0; + + if (MHSt == 0 && RHSt == 0) { + BitsInit *MHSbits = dynamic_cast(MHS); + BitsInit *RHSbits = dynamic_cast(RHS); + + if (MHSbits && RHSbits && + MHSbits->getNumBits() == RHSbits->getNumBits()) { + Type = BitRecTy::get(); + break; + } else { + BitInit *MHSbit = dynamic_cast(MHS); + BitInit *RHSbit = dynamic_cast(RHS); + + if (MHSbit && RHSbit) { + Type = BitRecTy::get(); + break; + } + } + } else if (MHSt != 0 && RHSt != 0) { + MHSTy = MHSt->getType(); + RHSTy = RHSt->getType(); + } + + if (!MHSTy || !RHSTy) { + TokError("could not get type for !if"); + return 0; + } + + if (MHSTy->typeIsConvertibleTo(RHSTy)) { + Type = RHSTy; + } else if (RHSTy->typeIsConvertibleTo(MHSTy)) { + Type = MHSTy; + } else { + TokError("inconsistent types for !if"); + return 0; + } + break; + } + case tgtok::XForEach: { + TypedInit *MHSt = dynamic_cast(MHS); + if (MHSt == 0) { + TokError("could not get type for !foreach"); + return 0; + } + Type = MHSt->getType(); + break; + } + case tgtok::XSubst: { + TypedInit *RHSt = dynamic_cast(RHS); + if (RHSt == 0) { + TokError("could not get type for !subst"); + return 0; + } + Type = RHSt->getType(); + break; + } + } + return (TernOpInit::get(Code, LHS, MHS, RHS, Type))->Fold(CurRec, + CurMultiClass); + } + } + TokError("could not parse operation"); + return 0; +} + +/// ParseOperatorType - Parse a type for an operator. This returns +/// null on error. +/// +/// OperatorType ::= '<' Type '>' +/// +RecTy *TGParser::ParseOperatorType() { + RecTy *Type = 0; + + if (Lex.getCode() != tgtok::less) { + TokError("expected type name for operator"); + return 0; + } + Lex.Lex(); // eat the < + + Type = ParseType(); + + if (Type == 0) { + TokError("expected type name for operator"); + return 0; + } + + if (Lex.getCode() != tgtok::greater) { + TokError("expected type name for operator"); + return 0; + } + Lex.Lex(); // eat the > + + return Type; +} + + +/// ParseSimpleValue - Parse a tblgen value. This returns null on error. +/// +/// SimpleValue ::= IDValue +/// SimpleValue ::= INTVAL +/// SimpleValue ::= STRVAL+ +/// SimpleValue ::= CODEFRAGMENT +/// SimpleValue ::= '?' +/// SimpleValue ::= '{' ValueList '}' +/// SimpleValue ::= ID '<' ValueListNE '>' +/// SimpleValue ::= '[' ValueList ']' +/// SimpleValue ::= '(' IDValue DagArgList ')' +/// SimpleValue ::= CONCATTOK '(' Value ',' Value ')' +/// SimpleValue ::= SHLTOK '(' Value ',' Value ')' +/// SimpleValue ::= SRATOK '(' Value ',' Value ')' +/// SimpleValue ::= SRLTOK '(' Value ',' Value ')' +/// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')' +/// +Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { + Init *R = 0; + switch (Lex.getCode()) { + default: TokError("Unknown token when parsing a value"); break; + case tgtok::IntVal: R = IntInit::get(Lex.getCurIntVal()); Lex.Lex(); break; + case tgtok::StrVal: { + std::string Val = Lex.getCurStrVal(); + Lex.Lex(); + + // Handle multiple consecutive concatenated strings. + while (Lex.getCode() == tgtok::StrVal) { + Val += Lex.getCurStrVal(); + Lex.Lex(); + } + + R = StringInit::get(Val); + break; + } + case tgtok::CodeFragment: + R = CodeInit::get(Lex.getCurStrVal()); + Lex.Lex(); + break; + case tgtok::question: + R = UnsetInit::get(); + Lex.Lex(); + break; + case tgtok::Id: { + SMLoc NameLoc = Lex.getLoc(); + std::string Name = Lex.getCurStrVal(); + if (Lex.Lex() != tgtok::less) // consume the Id. + return ParseIDValue(CurRec, Name, NameLoc); // Value ::= IDValue + + // Value ::= ID '<' ValueListNE '>' + if (Lex.Lex() == tgtok::greater) { + TokError("expected non-empty value list"); + return 0; + } + + // This is a CLASS expression. This is supposed to synthesize + // a new anonymous definition, deriving from CLASS with no + // body. + Record *Class = Records.getClass(Name); + if (!Class) { + Error(NameLoc, "Expected a class name, got '" + Name + "'"); + return 0; + } + + std::vector ValueList = ParseValueList(CurRec, Class); + if (ValueList.empty()) return 0; + + if (Lex.getCode() != tgtok::greater) { + TokError("expected '>' at end of value list"); + return 0; + } + Lex.Lex(); // eat the '>' + + // Create the new record, set it as CurRec temporarily. + static unsigned AnonCounter = 0; + Record *NewRec = new Record("anonymous.val."+utostr(AnonCounter++), + NameLoc, + Records); + SubClassReference SCRef; + SCRef.RefLoc = NameLoc; + SCRef.Rec = Class; + SCRef.TemplateArgs = ValueList; + // Add info about the subclass to NewRec. + if (AddSubClass(NewRec, SCRef)) + return 0; + NewRec->resolveReferences(); + Records.addDef(NewRec); + + // The result of the expression is a reference to the new record. + return DefInit::get(NewRec); + } + case tgtok::l_brace: { // Value ::= '{' ValueList '}' + SMLoc BraceLoc = Lex.getLoc(); + Lex.Lex(); // eat the '{' + std::vector Vals; + + if (Lex.getCode() != tgtok::r_brace) { + Vals = ParseValueList(CurRec); + if (Vals.empty()) return 0; + } + if (Lex.getCode() != tgtok::r_brace) { + TokError("expected '}' at end of bit list value"); + return 0; + } + Lex.Lex(); // eat the '}' + + SmallVector NewBits(Vals.size()); + + for (unsigned i = 0, e = Vals.size(); i != e; ++i) { + Init *Bit = Vals[i]->convertInitializerTo(BitRecTy::get()); + if (Bit == 0) { + Error(BraceLoc, "Element #" + utostr(i) + " (" + Vals[i]->getAsString()+ + ") is not convertable to a bit"); + return 0; + } + NewBits[Vals.size()-i-1] = Bit; + } + return BitsInit::get(NewBits); + } + case tgtok::l_square: { // Value ::= '[' ValueList ']' + Lex.Lex(); // eat the '[' + std::vector Vals; + + RecTy *DeducedEltTy = 0; + ListRecTy *GivenListTy = 0; + + if (ItemType != 0) { + ListRecTy *ListType = dynamic_cast(ItemType); + if (ListType == 0) { + std::stringstream s; + s << "Type mismatch for list, expected list type, got " + << ItemType->getAsString(); + TokError(s.str()); + return 0; + } + GivenListTy = ListType; + } + + if (Lex.getCode() != tgtok::r_square) { + Vals = ParseValueList(CurRec, 0, + GivenListTy ? GivenListTy->getElementType() : 0); + if (Vals.empty()) return 0; + } + if (Lex.getCode() != tgtok::r_square) { + TokError("expected ']' at end of list value"); + return 0; + } + Lex.Lex(); // eat the ']' + + RecTy *GivenEltTy = 0; + if (Lex.getCode() == tgtok::less) { + // Optional list element type + Lex.Lex(); // eat the '<' + + GivenEltTy = ParseType(); + if (GivenEltTy == 0) { + // Couldn't parse element type + return 0; + } + + if (Lex.getCode() != tgtok::greater) { + TokError("expected '>' at end of list element type"); + return 0; + } + Lex.Lex(); // eat the '>' + } + + // Check elements + RecTy *EltTy = 0; + for (std::vector::iterator i = Vals.begin(), ie = Vals.end(); + i != ie; + ++i) { + TypedInit *TArg = dynamic_cast(*i); + if (TArg == 0) { + TokError("Untyped list element"); + return 0; + } + if (EltTy != 0) { + EltTy = resolveTypes(EltTy, TArg->getType()); + if (EltTy == 0) { + TokError("Incompatible types in list elements"); + return 0; + } + } else { + EltTy = TArg->getType(); + } + } + + if (GivenEltTy != 0) { + if (EltTy != 0) { + // Verify consistency + if (!EltTy->typeIsConvertibleTo(GivenEltTy)) { + TokError("Incompatible types in list elements"); + return 0; + } + } + EltTy = GivenEltTy; + } + + if (EltTy == 0) { + if (ItemType == 0) { + TokError("No type for list"); + return 0; + } + DeducedEltTy = GivenListTy->getElementType(); + } else { + // Make sure the deduced type is compatible with the given type + if (GivenListTy) { + if (!EltTy->typeIsConvertibleTo(GivenListTy->getElementType())) { + TokError("Element type mismatch for list"); + return 0; + } + } + DeducedEltTy = EltTy; + } + + return ListInit::get(Vals, DeducedEltTy); + } + case tgtok::l_paren: { // Value ::= '(' IDValue DagArgList ')' + Lex.Lex(); // eat the '(' + if (Lex.getCode() != tgtok::Id && Lex.getCode() != tgtok::XCast) { + TokError("expected identifier in dag init"); + return 0; + } + + Init *Operator = ParseValue(CurRec); + if (Operator == 0) return 0; + + // If the operator name is present, parse it. + std::string OperatorName; + if (Lex.getCode() == tgtok::colon) { + if (Lex.Lex() != tgtok::VarName) { // eat the ':' + TokError("expected variable name in dag operator"); + return 0; + } + OperatorName = Lex.getCurStrVal(); + Lex.Lex(); // eat the VarName. + } + + std::vector > DagArgs; + if (Lex.getCode() != tgtok::r_paren) { + DagArgs = ParseDagArgList(CurRec); + if (DagArgs.empty()) return 0; + } + + if (Lex.getCode() != tgtok::r_paren) { + TokError("expected ')' in dag init"); + return 0; + } + Lex.Lex(); // eat the ')' + + return DagInit::get(Operator, OperatorName, DagArgs); + } + + case tgtok::XHead: + case tgtok::XTail: + case tgtok::XEmpty: + case tgtok::XCast: // Value ::= !unop '(' Value ')' + case tgtok::XConcat: + case tgtok::XSRA: + case tgtok::XSRL: + case tgtok::XSHL: + case tgtok::XEq: + case tgtok::XStrConcat: // Value ::= !binop '(' Value ',' Value ')' + case tgtok::XIf: + case tgtok::XForEach: + case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')' + return ParseOperation(CurRec); + } + } + + return R; +} + +/// ParseValue - Parse a tblgen value. This returns null on error. +/// +/// Value ::= SimpleValue ValueSuffix* +/// ValueSuffix ::= '{' BitList '}' +/// ValueSuffix ::= '[' BitList ']' +/// ValueSuffix ::= '.' ID +/// +Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType) { + Init *Result = ParseSimpleValue(CurRec, ItemType); + if (Result == 0) return 0; + + // Parse the suffixes now if present. + while (1) { + switch (Lex.getCode()) { + default: return Result; + case tgtok::l_brace: { + SMLoc CurlyLoc = Lex.getLoc(); + Lex.Lex(); // eat the '{' + std::vector Ranges = ParseRangeList(); + if (Ranges.empty()) return 0; + + // Reverse the bitlist. + std::reverse(Ranges.begin(), Ranges.end()); + Result = Result->convertInitializerBitRange(Ranges); + if (Result == 0) { + Error(CurlyLoc, "Invalid bit range for value"); + return 0; + } + + // Eat the '}'. + if (Lex.getCode() != tgtok::r_brace) { + TokError("expected '}' at end of bit range list"); + return 0; + } + Lex.Lex(); + break; + } + case tgtok::l_square: { + SMLoc SquareLoc = Lex.getLoc(); + Lex.Lex(); // eat the '[' + std::vector Ranges = ParseRangeList(); + if (Ranges.empty()) return 0; + + Result = Result->convertInitListSlice(Ranges); + if (Result == 0) { + Error(SquareLoc, "Invalid range for list slice"); + return 0; + } + + // Eat the ']'. + if (Lex.getCode() != tgtok::r_square) { + TokError("expected ']' at end of list slice"); + return 0; + } + Lex.Lex(); + break; + } + case tgtok::period: + if (Lex.Lex() != tgtok::Id) { // eat the . + TokError("expected field identifier after '.'"); + return 0; + } + if (!Result->getFieldType(Lex.getCurStrVal())) { + TokError("Cannot access field '" + Lex.getCurStrVal() + "' of value '" + + Result->getAsString() + "'"); + return 0; + } + Result = FieldInit::get(Result, Lex.getCurStrVal()); + Lex.Lex(); // eat field name + break; + } + } +} + +/// ParseDagArgList - Parse the argument list for a dag literal expression. +/// +/// ParseDagArgList ::= Value (':' VARNAME)? +/// ParseDagArgList ::= ParseDagArgList ',' Value (':' VARNAME)? +std::vector > +TGParser::ParseDagArgList(Record *CurRec) { + std::vector > Result; + + while (1) { + Init *Val = ParseValue(CurRec); + if (Val == 0) return std::vector >(); + + // If the variable name is present, add it. + std::string VarName; + if (Lex.getCode() == tgtok::colon) { + if (Lex.Lex() != tgtok::VarName) { // eat the ':' + TokError("expected variable name in dag literal"); + return std::vector >(); + } + VarName = Lex.getCurStrVal(); + Lex.Lex(); // eat the VarName. + } + + Result.push_back(std::make_pair(Val, VarName)); + + if (Lex.getCode() != tgtok::comma) break; + Lex.Lex(); // eat the ',' + } + + return Result; +} + + +/// ParseValueList - Parse a comma separated list of values, returning them as a +/// vector. Note that this always expects to be able to parse at least one +/// value. It returns an empty list if this is not possible. +/// +/// ValueList ::= Value (',' Value) +/// +std::vector TGParser::ParseValueList(Record *CurRec, Record *ArgsRec, + RecTy *EltTy) { + std::vector Result; + RecTy *ItemType = EltTy; + unsigned int ArgN = 0; + if (ArgsRec != 0 && EltTy == 0) { + const std::vector &TArgs = ArgsRec->getTemplateArgs(); + const RecordVal *RV = ArgsRec->getValue(TArgs[ArgN]); + if (!RV) { + errs() << "Cannot find template arg " << ArgN << " (" << TArgs[ArgN] + << ")\n"; + } + assert(RV && "Template argument record not found??"); + ItemType = RV->getType(); + ++ArgN; + } + Result.push_back(ParseValue(CurRec, ItemType)); + if (Result.back() == 0) return std::vector(); + + while (Lex.getCode() == tgtok::comma) { + Lex.Lex(); // Eat the comma + + if (ArgsRec != 0 && EltTy == 0) { + const std::vector &TArgs = ArgsRec->getTemplateArgs(); + if (ArgN >= TArgs.size()) { + TokError("too many template arguments"); + return std::vector(); + } + const RecordVal *RV = ArgsRec->getValue(TArgs[ArgN]); + assert(RV && "Template argument record not found??"); + ItemType = RV->getType(); + ++ArgN; + } + Result.push_back(ParseValue(CurRec, ItemType)); + if (Result.back() == 0) return std::vector(); + } + + return Result; +} + + +/// ParseDeclaration - Read a declaration, returning the name of field ID, or an +/// empty string on error. This can happen in a number of different context's, +/// including within a def or in the template args for a def (which which case +/// CurRec will be non-null) and within the template args for a multiclass (in +/// which case CurRec will be null, but CurMultiClass will be set). This can +/// also happen within a def that is within a multiclass, which will set both +/// CurRec and CurMultiClass. +/// +/// Declaration ::= FIELD? Type ID ('=' Value)? +/// +std::string TGParser::ParseDeclaration(Record *CurRec, + bool ParsingTemplateArgs) { + // Read the field prefix if present. + bool HasField = Lex.getCode() == tgtok::Field; + if (HasField) Lex.Lex(); + + RecTy *Type = ParseType(); + if (Type == 0) return ""; + + if (Lex.getCode() != tgtok::Id) { + TokError("Expected identifier in declaration"); + return ""; + } + + SMLoc IdLoc = Lex.getLoc(); + std::string DeclName = Lex.getCurStrVal(); + Lex.Lex(); + + if (ParsingTemplateArgs) { + if (CurRec) { + DeclName = CurRec->getName() + ":" + DeclName; + } else { + assert(CurMultiClass); + } + if (CurMultiClass) + DeclName = CurMultiClass->Rec.getName() + "::" + DeclName; + } + + // Add the value. + if (AddValue(CurRec, IdLoc, RecordVal(DeclName, Type, HasField))) + return ""; + + // If a value is present, parse it. + if (Lex.getCode() == tgtok::equal) { + Lex.Lex(); + SMLoc ValLoc = Lex.getLoc(); + Init *Val = ParseValue(CurRec, Type); + if (Val == 0 || + SetValue(CurRec, ValLoc, DeclName, std::vector(), Val)) + return ""; + } + + return DeclName; +} + +/// ParseTemplateArgList - Read a template argument list, which is a non-empty +/// sequence of template-declarations in <>'s. If CurRec is non-null, these are +/// template args for a def, which may or may not be in a multiclass. If null, +/// these are the template args for a multiclass. +/// +/// TemplateArgList ::= '<' Declaration (',' Declaration)* '>' +/// +bool TGParser::ParseTemplateArgList(Record *CurRec) { + assert(Lex.getCode() == tgtok::less && "Not a template arg list!"); + Lex.Lex(); // eat the '<' + + Record *TheRecToAddTo = CurRec ? CurRec : &CurMultiClass->Rec; + + // Read the first declaration. + std::string TemplArg = ParseDeclaration(CurRec, true/*templateargs*/); + if (TemplArg.empty()) + return true; + + TheRecToAddTo->addTemplateArg(TemplArg); + + while (Lex.getCode() == tgtok::comma) { + Lex.Lex(); // eat the ',' + + // Read the following declarations. + TemplArg = ParseDeclaration(CurRec, true/*templateargs*/); + if (TemplArg.empty()) + return true; + TheRecToAddTo->addTemplateArg(TemplArg); + } + + if (Lex.getCode() != tgtok::greater) + return TokError("expected '>' at end of template argument list"); + Lex.Lex(); // eat the '>'. + return false; +} + + +/// ParseBodyItem - Parse a single item at within the body of a def or class. +/// +/// BodyItem ::= Declaration ';' +/// BodyItem ::= LET ID OptionalBitList '=' Value ';' +bool TGParser::ParseBodyItem(Record *CurRec) { + if (Lex.getCode() != tgtok::Let) { + if (ParseDeclaration(CurRec, false).empty()) + return true; + + if (Lex.getCode() != tgtok::semi) + return TokError("expected ';' after declaration"); + Lex.Lex(); + return false; + } + + // LET ID OptionalRangeList '=' Value ';' + if (Lex.Lex() != tgtok::Id) + return TokError("expected field identifier after let"); + + SMLoc IdLoc = Lex.getLoc(); + std::string FieldName = Lex.getCurStrVal(); + Lex.Lex(); // eat the field name. + + std::vector BitList; + if (ParseOptionalBitList(BitList)) + return true; + std::reverse(BitList.begin(), BitList.end()); + + if (Lex.getCode() != tgtok::equal) + return TokError("expected '=' in let expression"); + Lex.Lex(); // eat the '='. + + RecordVal *Field = CurRec->getValue(FieldName); + if (Field == 0) + return TokError("Value '" + FieldName + "' unknown!"); + + RecTy *Type = Field->getType(); + + Init *Val = ParseValue(CurRec, Type); + if (Val == 0) return true; + + if (Lex.getCode() != tgtok::semi) + return TokError("expected ';' after let expression"); + Lex.Lex(); + + return SetValue(CurRec, IdLoc, FieldName, BitList, Val); +} + +/// ParseBody - Read the body of a class or def. Return true on error, false on +/// success. +/// +/// Body ::= ';' +/// Body ::= '{' BodyList '}' +/// BodyList BodyItem* +/// +bool TGParser::ParseBody(Record *CurRec) { + // If this is a null definition, just eat the semi and return. + if (Lex.getCode() == tgtok::semi) { + Lex.Lex(); + return false; + } + + if (Lex.getCode() != tgtok::l_brace) + return TokError("Expected ';' or '{' to start body"); + // Eat the '{'. + Lex.Lex(); + + while (Lex.getCode() != tgtok::r_brace) + if (ParseBodyItem(CurRec)) + return true; + + // Eat the '}'. + Lex.Lex(); + return false; +} + +/// ParseObjectBody - Parse the body of a def or class. This consists of an +/// optional ClassList followed by a Body. CurRec is the current def or class +/// that is being parsed. +/// +/// ObjectBody ::= BaseClassList Body +/// BaseClassList ::= /*empty*/ +/// BaseClassList ::= ':' BaseClassListNE +/// BaseClassListNE ::= SubClassRef (',' SubClassRef)* +/// +bool TGParser::ParseObjectBody(Record *CurRec) { + // If there is a baseclass list, read it. + if (Lex.getCode() == tgtok::colon) { + Lex.Lex(); + + // Read all of the subclasses. + SubClassReference SubClass = ParseSubClassReference(CurRec, false); + while (1) { + // Check for error. + if (SubClass.Rec == 0) return true; + + // Add it. + if (AddSubClass(CurRec, SubClass)) + return true; + + if (Lex.getCode() != tgtok::comma) break; + Lex.Lex(); // eat ','. + SubClass = ParseSubClassReference(CurRec, false); + } + } + + // Process any variables on the let stack. + for (unsigned i = 0, e = LetStack.size(); i != e; ++i) + for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j) + if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name, + LetStack[i][j].Bits, LetStack[i][j].Value)) + return true; + + return ParseBody(CurRec); +} + +/// ParseDef - Parse and return a top level or multiclass def, return the record +/// corresponding to it. This returns null on error. +/// +/// DefInst ::= DEF ObjectName ObjectBody +/// +bool TGParser::ParseDef(MultiClass *CurMultiClass) { + SMLoc DefLoc = Lex.getLoc(); + assert(Lex.getCode() == tgtok::Def && "Unknown tok"); + Lex.Lex(); // Eat the 'def' token. + + // Parse ObjectName and make a record for it. + Record *CurRec = new Record(ParseObjectName(), DefLoc, Records); + + if (!CurMultiClass) { + // Top-level def definition. + + // Ensure redefinition doesn't happen. + if (Records.getDef(CurRec->getName())) { + Error(DefLoc, "def '" + CurRec->getName() + "' already defined"); + return true; + } + Records.addDef(CurRec); + } else { + // Otherwise, a def inside a multiclass, add it to the multiclass. + for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size(); i != e; ++i) + if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) { + Error(DefLoc, "def '" + CurRec->getName() + + "' already defined in this multiclass!"); + return true; + } + CurMultiClass->DefPrototypes.push_back(CurRec); + } + + if (ParseObjectBody(CurRec)) + return true; + + if (CurMultiClass == 0) // Def's in multiclasses aren't really defs. + // See Record::setName(). This resolve step will see any new name + // for the def that might have been created when resolving + // inheritance, values and arguments above. + CurRec->resolveReferences(); + + // If ObjectBody has template arguments, it's an error. + assert(CurRec->getTemplateArgs().empty() && "How'd this get template args?"); + + if (CurMultiClass) { + // Copy the template arguments for the multiclass into the def. + const std::vector &TArgs = + CurMultiClass->Rec.getTemplateArgs(); + + for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { + const RecordVal *RV = CurMultiClass->Rec.getValue(TArgs[i]); + assert(RV && "Template arg doesn't exist?"); + CurRec->addValue(*RV); + } + } + + return false; +} + + +/// ParseClass - Parse a tblgen class definition. +/// +/// ClassInst ::= CLASS ID TemplateArgList? ObjectBody +/// +bool TGParser::ParseClass() { + assert(Lex.getCode() == tgtok::Class && "Unexpected token!"); + Lex.Lex(); + + if (Lex.getCode() != tgtok::Id) + return TokError("expected class name after 'class' keyword"); + + Record *CurRec = Records.getClass(Lex.getCurStrVal()); + if (CurRec) { + // If the body was previously defined, this is an error. + if (!CurRec->getValues().empty() || + !CurRec->getSuperClasses().empty() || + !CurRec->getTemplateArgs().empty()) + return TokError("Class '" + CurRec->getName() + "' already defined"); + } else { + // If this is the first reference to this class, create and add it. + CurRec = new Record(Lex.getCurStrVal(), Lex.getLoc(), Records); + Records.addClass(CurRec); + } + Lex.Lex(); // eat the name. + + // If there are template args, parse them. + if (Lex.getCode() == tgtok::less) + if (ParseTemplateArgList(CurRec)) + return true; + + // Finally, parse the object body. + return ParseObjectBody(CurRec); +} + +/// ParseLetList - Parse a non-empty list of assignment expressions into a list +/// of LetRecords. +/// +/// LetList ::= LetItem (',' LetItem)* +/// LetItem ::= ID OptionalRangeList '=' Value +/// +std::vector TGParser::ParseLetList() { + std::vector Result; + + while (1) { + if (Lex.getCode() != tgtok::Id) { + TokError("expected identifier in let definition"); + return std::vector(); + } + std::string Name = Lex.getCurStrVal(); + SMLoc NameLoc = Lex.getLoc(); + Lex.Lex(); // Eat the identifier. + + // Check for an optional RangeList. + std::vector Bits; + if (ParseOptionalRangeList(Bits)) + return std::vector(); + std::reverse(Bits.begin(), Bits.end()); + + if (Lex.getCode() != tgtok::equal) { + TokError("expected '=' in let expression"); + return std::vector(); + } + Lex.Lex(); // eat the '='. + + Init *Val = ParseValue(0); + if (Val == 0) return std::vector(); + + // Now that we have everything, add the record. + Result.push_back(LetRecord(Name, Bits, Val, NameLoc)); + + if (Lex.getCode() != tgtok::comma) + return Result; + Lex.Lex(); // eat the comma. + } +} + +/// ParseTopLevelLet - Parse a 'let' at top level. This can be a couple of +/// different related productions. This works inside multiclasses too. +/// +/// Object ::= LET LetList IN '{' ObjectList '}' +/// Object ::= LET LetList IN Object +/// +bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) { + assert(Lex.getCode() == tgtok::Let && "Unexpected token"); + Lex.Lex(); + + // Add this entry to the let stack. + std::vector LetInfo = ParseLetList(); + if (LetInfo.empty()) return true; + LetStack.push_back(LetInfo); + + if (Lex.getCode() != tgtok::In) + return TokError("expected 'in' at end of top-level 'let'"); + Lex.Lex(); + + // If this is a scalar let, just handle it now + if (Lex.getCode() != tgtok::l_brace) { + // LET LetList IN Object + if (ParseObject(CurMultiClass)) + return true; + } else { // Object ::= LETCommand '{' ObjectList '}' + SMLoc BraceLoc = Lex.getLoc(); + // Otherwise, this is a group let. + Lex.Lex(); // eat the '{'. + + // Parse the object list. + if (ParseObjectList(CurMultiClass)) + return true; + + if (Lex.getCode() != tgtok::r_brace) { + TokError("expected '}' at end of top level let command"); + return Error(BraceLoc, "to match this '{'"); + } + Lex.Lex(); + } + + // Outside this let scope, this let block is not active. + LetStack.pop_back(); + return false; +} + +/// ParseMultiClass - Parse a multiclass definition. +/// +/// MultiClassInst ::= MULTICLASS ID TemplateArgList? +/// ':' BaseMultiClassList '{' MultiClassDef+ '}' +/// +bool TGParser::ParseMultiClass() { + assert(Lex.getCode() == tgtok::MultiClass && "Unexpected token"); + Lex.Lex(); // Eat the multiclass token. + + if (Lex.getCode() != tgtok::Id) + return TokError("expected identifier after multiclass for name"); + std::string Name = Lex.getCurStrVal(); + + if (MultiClasses.count(Name)) + return TokError("multiclass '" + Name + "' already defined"); + + CurMultiClass = MultiClasses[Name] = new MultiClass(Name, + Lex.getLoc(), Records); + Lex.Lex(); // Eat the identifier. + + // If there are template args, parse them. + if (Lex.getCode() == tgtok::less) + if (ParseTemplateArgList(0)) + return true; + + bool inherits = false; + + // If there are submulticlasses, parse them. + if (Lex.getCode() == tgtok::colon) { + inherits = true; + + Lex.Lex(); + + // Read all of the submulticlasses. + SubMultiClassReference SubMultiClass = + ParseSubMultiClassReference(CurMultiClass); + while (1) { + // Check for error. + if (SubMultiClass.MC == 0) return true; + + // Add it. + if (AddSubMultiClass(CurMultiClass, SubMultiClass)) + return true; + + if (Lex.getCode() != tgtok::comma) break; + Lex.Lex(); // eat ','. + SubMultiClass = ParseSubMultiClassReference(CurMultiClass); + } + } + + if (Lex.getCode() != tgtok::l_brace) { + if (!inherits) + return TokError("expected '{' in multiclass definition"); + else if (Lex.getCode() != tgtok::semi) + return TokError("expected ';' in multiclass definition"); + else + Lex.Lex(); // eat the ';'. + } else { + if (Lex.Lex() == tgtok::r_brace) // eat the '{'. + return TokError("multiclass must contain at least one def"); + + while (Lex.getCode() != tgtok::r_brace) { + switch (Lex.getCode()) { + default: + return TokError("expected 'let', 'def' or 'defm' in multiclass body"); + case tgtok::Let: + case tgtok::Def: + case tgtok::Defm: + if (ParseObject(CurMultiClass)) + return true; + break; + } + } + Lex.Lex(); // eat the '}'. + } + + CurMultiClass = 0; + return false; +} + +/// ParseDefm - Parse the instantiation of a multiclass. +/// +/// DefMInst ::= DEFM ID ':' DefmSubClassRef ';' +/// +bool TGParser::ParseDefm(MultiClass *CurMultiClass) { + assert(Lex.getCode() == tgtok::Defm && "Unexpected token!"); + + std::string DefmPrefix; + if (Lex.Lex() == tgtok::Id) { // eat the defm. + DefmPrefix = Lex.getCurStrVal(); + Lex.Lex(); // Eat the defm prefix. + } + + SMLoc DefmPrefixLoc = Lex.getLoc(); + if (Lex.getCode() != tgtok::colon) + return TokError("expected ':' after defm identifier"); + + // Keep track of the new generated record definitions. + std::vector NewRecDefs; + + // This record also inherits from a regular class (non-multiclass)? + bool InheritFromClass = false; + + // eat the colon. + Lex.Lex(); + + SMLoc SubClassLoc = Lex.getLoc(); + SubClassReference Ref = ParseSubClassReference(0, true); + + while (1) { + if (Ref.Rec == 0) return true; + + // To instantiate a multiclass, we need to first get the multiclass, then + // instantiate each def contained in the multiclass with the SubClassRef + // template parameters. + MultiClass *MC = MultiClasses[Ref.Rec->getName()]; + assert(MC && "Didn't lookup multiclass correctly?"); + std::vector &TemplateVals = Ref.TemplateArgs; + + // Verify that the correct number of template arguments were specified. + const std::vector &TArgs = MC->Rec.getTemplateArgs(); + if (TArgs.size() < TemplateVals.size()) + return Error(SubClassLoc, + "more template args specified than multiclass expects"); + + // Loop over all the def's in the multiclass, instantiating each one. + for (unsigned i = 0, e = MC->DefPrototypes.size(); i != e; ++i) { + Record *DefProto = MC->DefPrototypes[i]; + + // Add in the defm name. If the defm prefix is empty, give each + // instantiated def a unique name. Otherwise, if "#NAME#" exists in the + // name, substitute the prefix for #NAME#. Otherwise, use the defm name + // as a prefix. + std::string DefName = DefProto->getName(); + if (DefmPrefix.empty()) { + DefName = GetNewAnonymousName(); + } else { + std::string::size_type idx = DefName.find("#NAME#"); + if (idx != std::string::npos) { + DefName.replace(idx, 6, DefmPrefix); + } else { + // Add the suffix to the defm name to get the new name. + DefName = DefmPrefix + DefName; + } + } + + Record *CurRec = new Record(DefName, DefmPrefixLoc, Records); + + SubClassReference Ref; + Ref.RefLoc = DefmPrefixLoc; + Ref.Rec = DefProto; + AddSubClass(CurRec, Ref); + + // Loop over all of the template arguments, setting them to the specified + // value or leaving them as the default if necessary. + for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { + // Check if a value is specified for this temp-arg. + if (i < TemplateVals.size()) { + // Set it now. + if (SetValue(CurRec, DefmPrefixLoc, TArgs[i], std::vector(), + TemplateVals[i])) + return true; + + // Resolve it next. + CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i])); + + // Now remove it. + CurRec->removeValue(TArgs[i]); + + } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) { + return Error(SubClassLoc, + "value not specified for template argument #"+ + utostr(i) + " (" + TArgs[i] + ") of multiclassclass '" + + MC->Rec.getName() + "'"); + } + } + + // If the mdef is inside a 'let' expression, add to each def. + for (unsigned i = 0, e = LetStack.size(); i != e; ++i) + for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j) + if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name, + LetStack[i][j].Bits, LetStack[i][j].Value)) { + Error(DefmPrefixLoc, "when instantiating this defm"); + return true; + } + + // Ensure redefinition doesn't happen. + if (Records.getDef(CurRec->getName())) + return Error(DefmPrefixLoc, "def '" + CurRec->getName() + + "' already defined, instantiating defm with subdef '" + + DefProto->getName() + "'"); + + // Don't create a top level definition for defm inside multiclasses, + // instead, only update the prototypes and bind the template args + // with the new created definition. + if (CurMultiClass) { + for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size(); + i != e; ++i) { + if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) { + Error(DefmPrefixLoc, "defm '" + CurRec->getName() + + "' already defined in this multiclass!"); + return 0; + } + } + CurMultiClass->DefPrototypes.push_back(CurRec); + + // Copy the template arguments for the multiclass into the new def. + const std::vector &TA = + CurMultiClass->Rec.getTemplateArgs(); + + for (unsigned i = 0, e = TA.size(); i != e; ++i) { + const RecordVal *RV = CurMultiClass->Rec.getValue(TA[i]); + assert(RV && "Template arg doesn't exist?"); + CurRec->addValue(*RV); + } + } else { + Records.addDef(CurRec); + } + + NewRecDefs.push_back(CurRec); + } + + if (Lex.getCode() != tgtok::comma) break; + Lex.Lex(); // eat ','. + + SubClassLoc = Lex.getLoc(); + + // A defm can inherit from regular classes (non-multiclass) as + // long as they come in the end of the inheritance list. + InheritFromClass = (Records.getClass(Lex.getCurStrVal()) != 0); + + if (InheritFromClass) + break; + + Ref = ParseSubClassReference(0, true); + } + + if (InheritFromClass) { + // Process all the classes to inherit as if they were part of a + // regular 'def' and inherit all record values. + SubClassReference SubClass = ParseSubClassReference(0, false); + while (1) { + // Check for error. + if (SubClass.Rec == 0) return true; + + // Get the expanded definition prototypes and teach them about + // the record values the current class to inherit has + for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i) { + Record *CurRec = NewRecDefs[i]; + + // Add it. + if (AddSubClass(CurRec, SubClass)) + return true; + + // Process any variables on the let stack. + for (unsigned i = 0, e = LetStack.size(); i != e; ++i) + for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j) + if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name, + LetStack[i][j].Bits, LetStack[i][j].Value)) + return true; + } + + if (Lex.getCode() != tgtok::comma) break; + Lex.Lex(); // eat ','. + SubClass = ParseSubClassReference(0, false); + } + } + + if (!CurMultiClass) + for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i) + // See Record::setName(). This resolve step will see any new + // name for the def that might have been created when resolving + // inheritance, values and arguments above. + NewRecDefs[i]->resolveReferences(); + + if (Lex.getCode() != tgtok::semi) + return TokError("expected ';' at end of defm"); + Lex.Lex(); + + return false; +} + +/// ParseObject +/// Object ::= ClassInst +/// Object ::= DefInst +/// Object ::= MultiClassInst +/// Object ::= DefMInst +/// Object ::= LETCommand '{' ObjectList '}' +/// Object ::= LETCommand Object +bool TGParser::ParseObject(MultiClass *MC) { + switch (Lex.getCode()) { + default: + return TokError("Expected class, def, defm, multiclass or let definition"); + case tgtok::Let: return ParseTopLevelLet(MC); + case tgtok::Def: return ParseDef(MC); + case tgtok::Defm: return ParseDefm(MC); + case tgtok::Class: return ParseClass(); + case tgtok::MultiClass: return ParseMultiClass(); + } +} + +/// ParseObjectList +/// ObjectList :== Object* +bool TGParser::ParseObjectList(MultiClass *MC) { + while (isObjectStart(Lex.getCode())) { + if (ParseObject(MC)) + return true; + } + return false; +} + +bool TGParser::ParseFile() { + Lex.Lex(); // Prime the lexer. + if (ParseObjectList()) return true; + + // If we have unread input at the end of the file, report it. + if (Lex.getCode() == tgtok::Eof) + return false; + + return TokError("Unexpected input at top level"); +} + diff --git a/lib/TableGen/TGParser.h b/lib/TableGen/TGParser.h new file mode 100644 index 00000000000..b408c80b7a1 --- /dev/null +++ b/lib/TableGen/TGParser.h @@ -0,0 +1,122 @@ +//===- TGParser.h - Parser for TableGen Files -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class represents the Parser for tablegen files. +// +//===----------------------------------------------------------------------===// + +#ifndef TGPARSER_H +#define TGPARSER_H + +#include "TGLexer.h" +#include "llvm/TableGen/Error.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/SourceMgr.h" +#include + +namespace llvm { + class Record; + class RecordVal; + class RecordKeeper; + class RecTy; + class Init; + struct MultiClass; + struct SubClassReference; + struct SubMultiClassReference; + + struct LetRecord { + std::string Name; + std::vector Bits; + Init *Value; + SMLoc Loc; + LetRecord(const std::string &N, const std::vector &B, Init *V, + SMLoc L) + : Name(N), Bits(B), Value(V), Loc(L) { + } + }; + +class TGParser { + TGLexer Lex; + std::vector > LetStack; + std::map MultiClasses; + + /// CurMultiClass - If we are parsing a 'multiclass' definition, this is the + /// current value. + MultiClass *CurMultiClass; + + // Record tracker + RecordKeeper &Records; +public: + TGParser(SourceMgr &SrcMgr, RecordKeeper &records) : + Lex(SrcMgr), CurMultiClass(0), Records(records) {} + + /// ParseFile - Main entrypoint for parsing a tblgen file. These parser + /// routines return true on error, or false on success. + bool ParseFile(); + + bool Error(SMLoc L, const Twine &Msg) const { + PrintError(L, Msg); + return true; + } + bool TokError(const Twine &Msg) const { + return Error(Lex.getLoc(), Msg); + } + const std::vector &getDependencies() const { + return Lex.getDependencies(); + } +private: // Semantic analysis methods. + bool AddValue(Record *TheRec, SMLoc Loc, const RecordVal &RV); + bool SetValue(Record *TheRec, SMLoc Loc, const std::string &ValName, + const std::vector &BitList, Init *V); + bool AddSubClass(Record *Rec, SubClassReference &SubClass); + bool AddSubMultiClass(MultiClass *CurMC, + SubMultiClassReference &SubMultiClass); + +private: // Parser methods. + bool ParseObjectList(MultiClass *MC = 0); + bool ParseObject(MultiClass *MC); + bool ParseClass(); + bool ParseMultiClass(); + bool ParseDefm(MultiClass *CurMultiClass); + bool ParseDef(MultiClass *CurMultiClass); + bool ParseTopLevelLet(MultiClass *CurMultiClass); + std::vector ParseLetList(); + + bool ParseObjectBody(Record *CurRec); + bool ParseBody(Record *CurRec); + bool ParseBodyItem(Record *CurRec); + + bool ParseTemplateArgList(Record *CurRec); + std::string ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs); + + SubClassReference ParseSubClassReference(Record *CurRec, bool isDefm); + SubMultiClassReference ParseSubMultiClassReference(MultiClass *CurMC); + + Init *ParseIDValue(Record *CurRec); + Init *ParseIDValue(Record *CurRec, const std::string &Name, SMLoc NameLoc); + Init *ParseSimpleValue(Record *CurRec, RecTy *ItemType = 0); + Init *ParseValue(Record *CurRec, RecTy *ItemType = 0); + std::vector ParseValueList(Record *CurRec, Record *ArgsRec = 0, RecTy *EltTy = 0); + std::vector > ParseDagArgList(Record *); + bool ParseOptionalRangeList(std::vector &Ranges); + bool ParseOptionalBitList(std::vector &Ranges); + std::vector ParseRangeList(); + bool ParseRangePiece(std::vector &Ranges); + RecTy *ParseType(); + Init *ParseOperation(Record *CurRec); + RecTy *ParseOperatorType(); + std::string ParseObjectName(); + Record *ParseClassID(); + MultiClass *ParseMultiClassID(); + Record *ParseDefmID(); +}; + +} // end namespace llvm + +#endif diff --git a/lib/TableGen/TableGenBackend.cpp b/lib/TableGen/TableGenBackend.cpp new file mode 100644 index 00000000000..29588db324c --- /dev/null +++ b/lib/TableGen/TableGenBackend.cpp @@ -0,0 +1,25 @@ +//===- TableGenBackend.cpp - Base class for TableGen Backends ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides useful services for TableGen backends... +// +//===----------------------------------------------------------------------===// + +#include "llvm/TableGen/TableGenBackend.h" +#include "llvm/TableGen/Record.h" +using namespace llvm; + +void TableGenBackend::EmitSourceFileHeader(const std::string &Desc, + raw_ostream &OS) const { + OS << "//===- TableGen'erated file -------------------------------------*-" + " C++ -*-===//\n//\n// " << Desc << "\n//\n// Automatically generate" + "d file, do not edit!\n//\n//===------------------------------------" + "----------------------------------===//\n\n"; +} + diff --git a/utils/TableGen/ARMDecoderEmitter.cpp b/utils/TableGen/ARMDecoderEmitter.cpp index c4bac10cfb2..145b96df98e 100644 --- a/utils/TableGen/ARMDecoderEmitter.cpp +++ b/utils/TableGen/ARMDecoderEmitter.cpp @@ -18,10 +18,10 @@ #include "ARMDecoderEmitter.h" #include "CodeGenTarget.h" -#include "Record.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/TableGen/Record.h" #include #include diff --git a/utils/TableGen/ARMDecoderEmitter.h b/utils/TableGen/ARMDecoderEmitter.h index 1faeb91fae8..486f899354f 100644 --- a/utils/TableGen/ARMDecoderEmitter.h +++ b/utils/TableGen/ARMDecoderEmitter.h @@ -15,9 +15,8 @@ #ifndef ARMDECODEREMITTER_H #define ARMDECODEREMITTER_H -#include "TableGenBackend.h" - #include "llvm/Support/DataTypes.h" +#include "llvm/TableGen/TableGenBackend.h" namespace llvm { diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 6d5d2de2019..e43f8311a8b 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -98,8 +98,6 @@ #include "AsmMatcherEmitter.h" #include "CodeGenTarget.h" -#include "Error.h" -#include "Record.h" #include "StringMatcher.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/PointerUnion.h" @@ -109,6 +107,8 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" #include #include using namespace llvm; diff --git a/utils/TableGen/AsmMatcherEmitter.h b/utils/TableGen/AsmMatcherEmitter.h index c13adf3dc53..e04ac103a40 100644 --- a/utils/TableGen/AsmMatcherEmitter.h +++ b/utils/TableGen/AsmMatcherEmitter.h @@ -15,7 +15,7 @@ #ifndef ASMMATCHER_EMITTER_H #define ASMMATCHER_EMITTER_H -#include "TableGenBackend.h" +#include "llvm/TableGen/TableGenBackend.h" #include namespace llvm { diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index 0f011de7100..bb91cd0415c 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -14,13 +14,13 @@ #include "AsmWriterEmitter.h" #include "AsmWriterInst.h" -#include "Error.h" #include "CodeGenTarget.h" -#include "Record.h" #include "StringToOffsetTable.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" #include using namespace llvm; diff --git a/utils/TableGen/AsmWriterEmitter.h b/utils/TableGen/AsmWriterEmitter.h index 84c925b66e8..731e31cc746 100644 --- a/utils/TableGen/AsmWriterEmitter.h +++ b/utils/TableGen/AsmWriterEmitter.h @@ -15,7 +15,7 @@ #ifndef ASMWRITER_EMITTER_H #define ASMWRITER_EMITTER_H -#include "TableGenBackend.h" +#include "llvm/TableGen/TableGenBackend.h" #include #include #include diff --git a/utils/TableGen/AsmWriterInst.cpp b/utils/TableGen/AsmWriterInst.cpp index fdf447f2aaf..350a2ccfcc2 100644 --- a/utils/TableGen/AsmWriterInst.cpp +++ b/utils/TableGen/AsmWriterInst.cpp @@ -13,8 +13,8 @@ #include "AsmWriterInst.h" #include "CodeGenTarget.h" -#include "Record.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/TableGen/Record.h" using namespace llvm; diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt index 0202f53c427..9e9a3a1d0d7 100644 --- a/utils/TableGen/CMakeLists.txt +++ b/utils/TableGen/CMakeLists.txt @@ -25,7 +25,6 @@ add_llvm_utility(tblgen DAGISelMatcher.cpp DisassemblerEmitter.cpp EDEmitter.cpp - Error.cpp FastISelEmitter.cpp FixedLenDecoderEmitter.cpp InstrEnumEmitter.cpp @@ -34,21 +33,16 @@ add_llvm_utility(tblgen NeonEmitter.cpp OptParserEmitter.cpp PseudoLoweringEmitter.cpp - Record.cpp RegisterInfoEmitter.cpp SetTheory.cpp StringMatcher.cpp SubtargetEmitter.cpp - TGLexer.cpp - TGParser.cpp TGValueTypes.cpp TableGen.cpp - TableGenBackend.cpp X86DisassemblerTables.cpp X86RecognizableInstr.cpp ) - -target_link_libraries(tblgen LLVMSupport) +target_link_libraries(tblgen LLVMSupport LLVMTableGen) if( MINGW ) target_link_libraries(tblgen imagehlp psapi) if(CMAKE_SIZEOF_VOID_P MATCHES "8") diff --git a/utils/TableGen/CallingConvEmitter.cpp b/utils/TableGen/CallingConvEmitter.cpp index c51afd82a37..fcdaa082fb2 100644 --- a/utils/TableGen/CallingConvEmitter.cpp +++ b/utils/TableGen/CallingConvEmitter.cpp @@ -13,8 +13,8 @@ //===----------------------------------------------------------------------===// #include "CallingConvEmitter.h" -#include "Record.h" #include "CodeGenTarget.h" +#include "llvm/TableGen/Record.h" using namespace llvm; void CallingConvEmitter::run(raw_ostream &O) { diff --git a/utils/TableGen/CallingConvEmitter.h b/utils/TableGen/CallingConvEmitter.h index 431c33bcc0d..7bddd6c93ef 100644 --- a/utils/TableGen/CallingConvEmitter.h +++ b/utils/TableGen/CallingConvEmitter.h @@ -15,7 +15,7 @@ #ifndef CALLINGCONV_EMITTER_H #define CALLINGCONV_EMITTER_H -#include "TableGenBackend.h" +#include "llvm/TableGen/TableGenBackend.h" #include namespace llvm { diff --git a/utils/TableGen/ClangASTNodesEmitter.h b/utils/TableGen/ClangASTNodesEmitter.h index 712333bd2d2..edd9316544e 100644 --- a/utils/TableGen/ClangASTNodesEmitter.h +++ b/utils/TableGen/ClangASTNodesEmitter.h @@ -14,8 +14,8 @@ #ifndef CLANGAST_EMITTER_H #define CLANGAST_EMITTER_H -#include "TableGenBackend.h" -#include "Record.h" +#include "llvm/TableGen/TableGenBackend.h" +#include "llvm/TableGen/Record.h" #include #include #include diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp index 68cd87dcdc9..5f25b8fa568 100644 --- a/utils/TableGen/ClangAttrEmitter.cpp +++ b/utils/TableGen/ClangAttrEmitter.cpp @@ -12,8 +12,8 @@ //===----------------------------------------------------------------------===// #include "ClangAttrEmitter.h" -#include "Record.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/TableGen/Record.h" #include #include diff --git a/utils/TableGen/ClangAttrEmitter.h b/utils/TableGen/ClangAttrEmitter.h index d6c00d6e23a..5acca560f01 100644 --- a/utils/TableGen/ClangAttrEmitter.h +++ b/utils/TableGen/ClangAttrEmitter.h @@ -14,7 +14,7 @@ #ifndef CLANGATTR_EMITTER_H #define CLANGATTR_EMITTER_H -#include "TableGenBackend.h" +#include "llvm/TableGen/TableGenBackend.h" namespace llvm { diff --git a/utils/TableGen/ClangDiagnosticsEmitter.cpp b/utils/TableGen/ClangDiagnosticsEmitter.cpp index 130f3e1e763..da2fb70b4a5 100644 --- a/utils/TableGen/ClangDiagnosticsEmitter.cpp +++ b/utils/TableGen/ClangDiagnosticsEmitter.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "ClangDiagnosticsEmitter.h" -#include "Record.h" +#include "llvm/TableGen/Record.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Compiler.h" #include "llvm/ADT/DenseSet.h" diff --git a/utils/TableGen/ClangDiagnosticsEmitter.h b/utils/TableGen/ClangDiagnosticsEmitter.h index 1e4c8b70c26..73d3c4dc0e9 100644 --- a/utils/TableGen/ClangDiagnosticsEmitter.h +++ b/utils/TableGen/ClangDiagnosticsEmitter.h @@ -14,7 +14,7 @@ #ifndef CLANGDIAGS_EMITTER_H #define CLANGDIAGS_EMITTER_H -#include "TableGenBackend.h" +#include "llvm/TableGen/TableGenBackend.h" namespace llvm { diff --git a/utils/TableGen/ClangSACheckersEmitter.cpp b/utils/TableGen/ClangSACheckersEmitter.cpp index 97739c6b3f4..423b68a6484 100644 --- a/utils/TableGen/ClangSACheckersEmitter.cpp +++ b/utils/TableGen/ClangSACheckersEmitter.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "ClangSACheckersEmitter.h" -#include "Record.h" +#include "llvm/TableGen/Record.h" #include "llvm/ADT/DenseSet.h" #include #include diff --git a/utils/TableGen/ClangSACheckersEmitter.h b/utils/TableGen/ClangSACheckersEmitter.h index 6bd16354732..5a0e1481112 100644 --- a/utils/TableGen/ClangSACheckersEmitter.h +++ b/utils/TableGen/ClangSACheckersEmitter.h @@ -14,7 +14,7 @@ #ifndef CLANGSACHECKERS_EMITTER_H #define CLANGSACHECKERS_EMITTER_H -#include "TableGenBackend.h" +#include "llvm/TableGen/TableGenBackend.h" namespace llvm { diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index 81551a7cfeb..c5a152665b0 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/utils/TableGen/CodeEmitterGen.cpp @@ -15,7 +15,7 @@ #include "CodeEmitterGen.h" #include "CodeGenTarget.h" -#include "Record.h" +#include "llvm/TableGen/Record.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" diff --git a/utils/TableGen/CodeEmitterGen.h b/utils/TableGen/CodeEmitterGen.h index a874d970fea..7f6ee2a1b40 100644 --- a/utils/TableGen/CodeEmitterGen.h +++ b/utils/TableGen/CodeEmitterGen.h @@ -14,7 +14,7 @@ #ifndef CODEMITTERGEN_H #define CODEMITTERGEN_H -#include "TableGenBackend.h" +#include "llvm/TableGen/TableGenBackend.h" #include #include diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index ef6634ea561..4954f339869 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -13,8 +13,8 @@ //===----------------------------------------------------------------------===// #include "CodeGenDAGPatterns.h" -#include "Error.h" -#include "Record.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Debug.h" diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 4b252774f00..53d499f3955 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -13,8 +13,8 @@ #include "CodeGenInstruction.h" #include "CodeGenTarget.h" -#include "Error.h" -#include "Record.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/STLExtras.h" diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp index 6e98d0ca911..a5bb5c2e63a 100644 --- a/utils/TableGen/CodeGenRegisters.cpp +++ b/utils/TableGen/CodeGenRegisters.cpp @@ -14,7 +14,7 @@ #include "CodeGenRegisters.h" #include "CodeGenTarget.h" -#include "Error.h" +#include "llvm/TableGen/Error.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h index c3af5593c16..f5759b557dc 100644 --- a/utils/TableGen/CodeGenRegisters.h +++ b/utils/TableGen/CodeGenRegisters.h @@ -15,8 +15,8 @@ #ifndef CODEGEN_REGISTERS_H #define CODEGEN_REGISTERS_H -#include "Record.h" #include "SetTheory.h" +#include "llvm/TableGen/Record.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index e8d376d9432..4a7bad7e6d8 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -16,7 +16,7 @@ #include "CodeGenTarget.h" #include "CodeGenIntrinsics.h" -#include "Record.h" +#include "llvm/TableGen/Record.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/CommandLine.h" diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h index bfd086346c8..730216c331b 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -19,7 +19,7 @@ #include "CodeGenRegisters.h" #include "CodeGenInstruction.h" -#include "Record.h" +#include "llvm/TableGen/Record.h" #include "llvm/Support/raw_ostream.h" #include diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index d66ae96cbc9..7db90034999 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -13,7 +13,7 @@ #include "DAGISelEmitter.h" #include "DAGISelMatcher.h" -#include "Record.h" +#include "llvm/TableGen/Record.h" #include "llvm/Support/Debug.h" using namespace llvm; diff --git a/utils/TableGen/DAGISelEmitter.h b/utils/TableGen/DAGISelEmitter.h index 35ab5503430..9c9fe4273fe 100644 --- a/utils/TableGen/DAGISelEmitter.h +++ b/utils/TableGen/DAGISelEmitter.h @@ -14,7 +14,7 @@ #ifndef DAGISEL_EMITTER_H #define DAGISEL_EMITTER_H -#include "TableGenBackend.h" +#include "llvm/TableGen/TableGenBackend.h" #include "CodeGenDAGPatterns.h" namespace llvm { diff --git a/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp index b12e1015c33..1367e8dd6e8 100644 --- a/utils/TableGen/DAGISelMatcher.cpp +++ b/utils/TableGen/DAGISelMatcher.cpp @@ -10,7 +10,7 @@ #include "DAGISelMatcher.h" #include "CodeGenDAGPatterns.h" #include "CodeGenTarget.h" -#include "Record.h" +#include "llvm/TableGen/Record.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/StringExtras.h" using namespace llvm; diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp index acb0135422e..3b65b2a6de0 100644 --- a/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -13,7 +13,7 @@ #include "DAGISelMatcher.h" #include "CodeGenDAGPatterns.h" -#include "Record.h" +#include "llvm/TableGen/Record.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index 85a4266a703..49ad956f886 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -10,7 +10,7 @@ #include "DAGISelMatcher.h" #include "CodeGenDAGPatterns.h" #include "CodeGenRegisters.h" -#include "Record.h" +#include "llvm/TableGen/Record.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" diff --git a/utils/TableGen/DisassemblerEmitter.cpp b/utils/TableGen/DisassemblerEmitter.cpp index 24db080b263..ff314e9c4f2 100644 --- a/utils/TableGen/DisassemblerEmitter.cpp +++ b/utils/TableGen/DisassemblerEmitter.cpp @@ -9,12 +9,12 @@ #include "DisassemblerEmitter.h" #include "CodeGenTarget.h" -#include "Error.h" -#include "Record.h" #include "X86DisassemblerTables.h" #include "X86RecognizableInstr.h" #include "ARMDecoderEmitter.h" #include "FixedLenDecoderEmitter.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" using namespace llvm; using namespace llvm::X86Disassembler; diff --git a/utils/TableGen/DisassemblerEmitter.h b/utils/TableGen/DisassemblerEmitter.h index 7229d81649e..63ee55264ad 100644 --- a/utils/TableGen/DisassemblerEmitter.h +++ b/utils/TableGen/DisassemblerEmitter.h @@ -10,7 +10,7 @@ #ifndef DISASSEMBLEREMITTER_H #define DISASSEMBLEREMITTER_H -#include "TableGenBackend.h" +#include "llvm/TableGen/TableGenBackend.h" namespace llvm { diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index e866487d256..85f7e1f26ca 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -17,8 +17,8 @@ #include "AsmWriterInst.h" #include "CodeGenTarget.h" -#include "Record.h" +#include "llvm/TableGen/Record.h" #include "llvm/MC/EDInstInfo.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" diff --git a/utils/TableGen/EDEmitter.h b/utils/TableGen/EDEmitter.h index e30373fed2e..f2683755472 100644 --- a/utils/TableGen/EDEmitter.h +++ b/utils/TableGen/EDEmitter.h @@ -16,7 +16,7 @@ #ifndef SEMANTIC_INFO_EMITTER_H #define SEMANTIC_INFO_EMITTER_H -#include "TableGenBackend.h" +#include "llvm/TableGen/TableGenBackend.h" namespace llvm { diff --git a/utils/TableGen/Error.cpp b/utils/TableGen/Error.cpp deleted file mode 100644 index 3f6cda89772..00000000000 --- a/utils/TableGen/Error.cpp +++ /dev/null @@ -1,39 +0,0 @@ -//===- Error.cpp - tblgen error handling helper routines --------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains error handling helper routines to pretty-print diagnostic -// messages from tblgen. -// -//===----------------------------------------------------------------------===// - -#include "Error.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Support/raw_ostream.h" - -namespace llvm { - -SourceMgr SrcMgr; - -void PrintError(SMLoc ErrorLoc, const Twine &Msg) { - SrcMgr.PrintMessage(ErrorLoc, Msg, "error"); -} - -void PrintError(const char *Loc, const Twine &Msg) { - SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), Msg, "error"); -} - -void PrintError(const Twine &Msg) { - errs() << "error:" << Msg << "\n"; -} - -void PrintError(const TGError &Error) { - PrintError(Error.getLoc(), Error.getMessage()); -} - -} // end namespace llvm diff --git a/utils/TableGen/Error.h b/utils/TableGen/Error.h deleted file mode 100644 index b3a01461940..00000000000 --- a/utils/TableGen/Error.h +++ /dev/null @@ -1,43 +0,0 @@ -//===- Error.h - tblgen error handling helper routines ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains error handling helper routines to pretty-print diagnostic -// messages from tblgen. -// -//===----------------------------------------------------------------------===// - -#ifndef ERROR_H -#define ERROR_H - -#include "llvm/Support/SourceMgr.h" - -namespace llvm { - -class TGError { - SMLoc Loc; - std::string Message; -public: - TGError(SMLoc loc, const std::string &message) : Loc(loc), Message(message) {} - - SMLoc getLoc() const { return Loc; } - const std::string &getMessage() const { return Message; } -}; - -void PrintError(SMLoc ErrorLoc, const Twine &Msg); -void PrintError(const char *Loc, const Twine &Msg); -void PrintError(const Twine &Msg); -void PrintError(const TGError &Error); - - -extern SourceMgr SrcMgr; - - -} // end namespace "llvm" - -#endif diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp index 66fc9a68ba8..9fdc2e33a54 100644 --- a/utils/TableGen/FastISelEmitter.cpp +++ b/utils/TableGen/FastISelEmitter.cpp @@ -18,8 +18,8 @@ //===----------------------------------------------------------------------===// #include "FastISelEmitter.h" -#include "Error.h" -#include "Record.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/VectorExtras.h" #include "llvm/Support/Debug.h" diff --git a/utils/TableGen/FastISelEmitter.h b/utils/TableGen/FastISelEmitter.h index ce4e77e6f8f..4f75ac1fd9d 100644 --- a/utils/TableGen/FastISelEmitter.h +++ b/utils/TableGen/FastISelEmitter.h @@ -14,8 +14,8 @@ #ifndef FASTISEL_EMITTER_H #define FASTISEL_EMITTER_H -#include "TableGenBackend.h" #include "CodeGenDAGPatterns.h" +#include "llvm/TableGen/TableGenBackend.h" namespace llvm { diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp index a3255a06e92..02b966a2143 100644 --- a/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -16,7 +16,7 @@ #include "FixedLenDecoderEmitter.h" #include "CodeGenTarget.h" -#include "Record.h" +#include "llvm/TableGen/Record.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" diff --git a/utils/TableGen/FixedLenDecoderEmitter.h b/utils/TableGen/FixedLenDecoderEmitter.h index 7460f83c69b..2df5448aa8d 100644 --- a/utils/TableGen/FixedLenDecoderEmitter.h +++ b/utils/TableGen/FixedLenDecoderEmitter.h @@ -16,8 +16,8 @@ #define FixedLenDECODEREMITTER_H #include "CodeGenTarget.h" -#include "TableGenBackend.h" +#include "llvm/TableGen/TableGenBackend.h" #include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/utils/TableGen/InstrEnumEmitter.cpp b/utils/TableGen/InstrEnumEmitter.cpp index aa596892f52..5981afde0e7 100644 --- a/utils/TableGen/InstrEnumEmitter.cpp +++ b/utils/TableGen/InstrEnumEmitter.cpp @@ -14,7 +14,7 @@ #include "InstrEnumEmitter.h" #include "CodeGenTarget.h" -#include "Record.h" +#include "llvm/TableGen/Record.h" #include using namespace llvm; diff --git a/utils/TableGen/InstrEnumEmitter.h b/utils/TableGen/InstrEnumEmitter.h index 89f8b659d70..c29a30938d3 100644 --- a/utils/TableGen/InstrEnumEmitter.h +++ b/utils/TableGen/InstrEnumEmitter.h @@ -15,7 +15,7 @@ #ifndef INSTRENUM_EMITTER_H #define INSTRENUM_EMITTER_H -#include "TableGenBackend.h" +#include "llvm/TableGen/TableGenBackend.h" namespace llvm { diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 35fe728f9e4..8341724a73e 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -14,7 +14,7 @@ #include "InstrInfoEmitter.h" #include "CodeGenTarget.h" -#include "Record.h" +#include "llvm/TableGen/Record.h" #include "llvm/ADT/StringExtras.h" #include using namespace llvm; diff --git a/utils/TableGen/InstrInfoEmitter.h b/utils/TableGen/InstrInfoEmitter.h index 165ce423ab6..1461e2c5f7c 100644 --- a/utils/TableGen/InstrInfoEmitter.h +++ b/utils/TableGen/InstrInfoEmitter.h @@ -15,8 +15,8 @@ #ifndef INSTRINFO_EMITTER_H #define INSTRINFO_EMITTER_H -#include "TableGenBackend.h" #include "CodeGenDAGPatterns.h" +#include "llvm/TableGen/TableGenBackend.h" #include #include diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index e5e7cea1200..782b89ede2e 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -13,8 +13,8 @@ #include "CodeGenTarget.h" #include "IntrinsicEmitter.h" -#include "Record.h" #include "StringMatcher.h" +#include "llvm/TableGen/Record.h" #include "llvm/ADT/StringExtras.h" #include using namespace llvm; diff --git a/utils/TableGen/IntrinsicEmitter.h b/utils/TableGen/IntrinsicEmitter.h index b1efecb92ee..eb6379cc741 100644 --- a/utils/TableGen/IntrinsicEmitter.h +++ b/utils/TableGen/IntrinsicEmitter.h @@ -15,7 +15,7 @@ #define INTRINSIC_EMITTER_H #include "CodeGenIntrinsics.h" -#include "TableGenBackend.h" +#include "llvm/TableGen/TableGenBackend.h" namespace llvm { class IntrinsicEmitter : public TableGenBackend { diff --git a/utils/TableGen/Makefile b/utils/TableGen/Makefile index c01b6602faa..17e94eacc38 100644 --- a/utils/TableGen/Makefile +++ b/utils/TableGen/Makefile @@ -9,7 +9,7 @@ LEVEL = ../.. TOOLNAME = tblgen -USEDLIBS = LLVMSupport.a +USEDLIBS = LLVMTableGen.a LLVMSupport.a REQUIRES_EH := 1 REQUIRES_RTTI := 1 diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp index 1e96da7f64d..0b5665fdc2b 100644 --- a/utils/TableGen/NeonEmitter.cpp +++ b/utils/TableGen/NeonEmitter.cpp @@ -24,7 +24,7 @@ //===----------------------------------------------------------------------===// #include "NeonEmitter.h" -#include "Error.h" +#include "llvm/TableGen/Error.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" diff --git a/utils/TableGen/NeonEmitter.h b/utils/TableGen/NeonEmitter.h index 12e4e867990..708ad3c06a0 100644 --- a/utils/TableGen/NeonEmitter.h +++ b/utils/TableGen/NeonEmitter.h @@ -16,8 +16,8 @@ #ifndef NEON_EMITTER_H #define NEON_EMITTER_H -#include "Record.h" -#include "TableGenBackend.h" +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/TableGenBackend.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" diff --git a/utils/TableGen/OptParserEmitter.cpp b/utils/TableGen/OptParserEmitter.cpp index 431026c669c..dea22d38861 100644 --- a/utils/TableGen/OptParserEmitter.cpp +++ b/utils/TableGen/OptParserEmitter.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// #include "OptParserEmitter.h" -#include "Record.h" +#include "llvm/TableGen/Record.h" #include "llvm/ADT/STLExtras.h" using namespace llvm; diff --git a/utils/TableGen/OptParserEmitter.h b/utils/TableGen/OptParserEmitter.h index 241a3f2b4a0..ca667caf439 100644 --- a/utils/TableGen/OptParserEmitter.h +++ b/utils/TableGen/OptParserEmitter.h @@ -10,7 +10,7 @@ #ifndef UTILS_TABLEGEN_OPTPARSEREMITTER_H #define UTILS_TABLEGEN_OPTPARSEREMITTER_H -#include "TableGenBackend.h" +#include "llvm/TableGen/TableGenBackend.h" namespace llvm { /// OptParserEmitter - This tablegen backend takes an input .td file diff --git a/utils/TableGen/PseudoLoweringEmitter.cpp b/utils/TableGen/PseudoLoweringEmitter.cpp index db33c1f7f68..c685527a140 100644 --- a/utils/TableGen/PseudoLoweringEmitter.cpp +++ b/utils/TableGen/PseudoLoweringEmitter.cpp @@ -8,10 +8,10 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "pseudo-lowering" -#include "Error.h" #include "CodeGenInstruction.h" #include "PseudoLoweringEmitter.h" -#include "Record.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/ErrorHandling.h" diff --git a/utils/TableGen/PseudoLoweringEmitter.h b/utils/TableGen/PseudoLoweringEmitter.h index 2749280e6a9..325bc8be146 100644 --- a/utils/TableGen/PseudoLoweringEmitter.h +++ b/utils/TableGen/PseudoLoweringEmitter.h @@ -12,7 +12,7 @@ #include "CodeGenInstruction.h" #include "CodeGenTarget.h" -#include "TableGenBackend.h" +#include "llvm/TableGen/TableGenBackend.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/SmallVector.h" diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp deleted file mode 100644 index 3d42a5233cf..00000000000 --- a/utils/TableGen/Record.cpp +++ /dev/null @@ -1,2009 +0,0 @@ -//===- Record.cpp - Record implementation ---------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Implement the tablegen record classes. -// -//===----------------------------------------------------------------------===// - -#include "Record.h" -#include "Error.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Format.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringMap.h" - -using namespace llvm; - -//===----------------------------------------------------------------------===// -// std::string wrapper for DenseMap purposes -//===----------------------------------------------------------------------===// - -/// 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; } - -private: - std::string data; -}; - -/// Specialize DenseMapInfo for TableGenStringKey. -namespace llvm { - -template<> struct DenseMapInfo { - static inline TableGenStringKey getEmptyKey() { - TableGenStringKey Empty("<<>>"); - return Empty; - } - static inline TableGenStringKey getTombstoneKey() { - TableGenStringKey Tombstone("<<>>"); - return Tombstone; - } - static unsigned getHashValue(const TableGenStringKey& Val) { - return HashString(Val.str()); - } - static bool isEqual(const TableGenStringKey& LHS, - const TableGenStringKey& RHS) { - return LHS.str() == RHS.str(); - } -}; - -} - -//===----------------------------------------------------------------------===// -// Type implementations -//===----------------------------------------------------------------------===// - -BitRecTy BitRecTy::Shared; -IntRecTy IntRecTy::Shared; -StringRecTy StringRecTy::Shared; -CodeRecTy CodeRecTy::Shared; -DagRecTy DagRecTy::Shared; - -void RecTy::dump() const { print(errs()); } - -ListRecTy *RecTy::getListTy() { - if (!ListTy) - ListTy = new ListRecTy(this); - return ListTy; -} - -Init *BitRecTy::convertValue(BitsInit *BI) { - if (BI->getNumBits() != 1) return 0; // Only accept if just one bit! - return BI->getBit(0); -} - -bool BitRecTy::baseClassOf(const BitsRecTy *RHS) const { - return RHS->getNumBits() == 1; -} - -Init *BitRecTy::convertValue(IntInit *II) { - int64_t Val = II->getValue(); - if (Val != 0 && Val != 1) return 0; // Only accept 0 or 1 for a bit! - - return BitInit::get(Val != 0); -} - -Init *BitRecTy::convertValue(TypedInit *VI) { - if (dynamic_cast(VI->getType())) - return VI; // Accept variable if it is already of bit type! - return 0; -} - -BitsRecTy *BitsRecTy::get(unsigned Sz) { - static std::vector Shared; - if (Sz >= Shared.size()) - Shared.resize(Sz + 1); - BitsRecTy *&Ty = Shared[Sz]; - if (!Ty) - Ty = new BitsRecTy(Sz); - return Ty; -} - -std::string BitsRecTy::getAsString() const { - return "bits<" + utostr(Size) + ">"; -} - -Init *BitsRecTy::convertValue(UnsetInit *UI) { - SmallVector NewBits(Size); - - for (unsigned i = 0; i != Size; ++i) - NewBits[i] = UnsetInit::get(); - - return BitsInit::get(NewBits); -} - -Init *BitsRecTy::convertValue(BitInit *UI) { - if (Size != 1) return 0; // Can only convert single bit. - return BitsInit::get(UI); -} - -/// canFitInBitfield - Return true if the number of bits is large enough to hold -/// the integer value. -static bool canFitInBitfield(int64_t Value, unsigned NumBits) { - // For example, with NumBits == 4, we permit Values from [-7 .. 15]. - return (NumBits >= sizeof(Value) * 8) || - (Value >> NumBits == 0) || (Value >> (NumBits-1) == -1); -} - -/// convertValue from Int initializer to bits type: Split the integer up into the -/// appropriate bits. -/// -Init *BitsRecTy::convertValue(IntInit *II) { - int64_t Value = II->getValue(); - // Make sure this bitfield is large enough to hold the integer value. - if (!canFitInBitfield(Value, Size)) - return 0; - - SmallVector NewBits(Size); - - for (unsigned i = 0; i != Size; ++i) - NewBits[i] = BitInit::get(Value & (1LL << i)); - - return BitsInit::get(NewBits); -} - -Init *BitsRecTy::convertValue(BitsInit *BI) { - // If the number of bits is right, return it. Otherwise we need to expand or - // truncate. - if (BI->getNumBits() == Size) return BI; - return 0; -} - -Init *BitsRecTy::convertValue(TypedInit *VI) { - if (BitsRecTy *BRT = dynamic_cast(VI->getType())) - if (BRT->Size == Size) { - SmallVector NewBits(Size); - - for (unsigned i = 0; i != Size; ++i) - NewBits[i] = VarBitInit::get(VI, i); - return BitsInit::get(NewBits); - } - - if (Size == 1 && dynamic_cast(VI->getType())) - return BitsInit::get(VI); - - if (TernOpInit *Tern = dynamic_cast(VI)) { - if (Tern->getOpcode() == TernOpInit::IF) { - Init *LHS = Tern->getLHS(); - Init *MHS = Tern->getMHS(); - Init *RHS = Tern->getRHS(); - - IntInit *MHSi = dynamic_cast(MHS); - IntInit *RHSi = dynamic_cast(RHS); - - if (MHSi && RHSi) { - int64_t MHSVal = MHSi->getValue(); - int64_t RHSVal = RHSi->getValue(); - - if (canFitInBitfield(MHSVal, Size) && canFitInBitfield(RHSVal, Size)) { - SmallVector NewBits(Size); - - for (unsigned i = 0; i != Size; ++i) - NewBits[i] = - TernOpInit::get(TernOpInit::IF, LHS, - IntInit::get((MHSVal & (1LL << i)) ? 1 : 0), - IntInit::get((RHSVal & (1LL << i)) ? 1 : 0), - VI->getType()); - - return BitsInit::get(NewBits); - } - } else { - BitsInit *MHSbs = dynamic_cast(MHS); - BitsInit *RHSbs = dynamic_cast(RHS); - - if (MHSbs && RHSbs) { - SmallVector NewBits(Size); - - for (unsigned i = 0; i != Size; ++i) - NewBits[i] = TernOpInit::get(TernOpInit::IF, LHS, - MHSbs->getBit(i), - RHSbs->getBit(i), - VI->getType()); - - return BitsInit::get(NewBits); - } - } - } - } - - return 0; -} - -Init *IntRecTy::convertValue(BitInit *BI) { - return IntInit::get(BI->getValue()); -} - -Init *IntRecTy::convertValue(BitsInit *BI) { - int64_t Result = 0; - for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) - if (BitInit *Bit = dynamic_cast(BI->getBit(i))) { - Result |= Bit->getValue() << i; - } else { - return 0; - } - return IntInit::get(Result); -} - -Init *IntRecTy::convertValue(TypedInit *TI) { - if (TI->getType()->typeIsConvertibleTo(this)) - return TI; // Accept variable if already of the right type! - return 0; -} - -Init *StringRecTy::convertValue(UnOpInit *BO) { - if (BO->getOpcode() == UnOpInit::CAST) { - Init *L = BO->getOperand()->convertInitializerTo(this); - if (L == 0) return 0; - if (L != BO->getOperand()) - return UnOpInit::get(UnOpInit::CAST, L, new StringRecTy); - return BO; - } - - return convertValue((TypedInit*)BO); -} - -Init *StringRecTy::convertValue(BinOpInit *BO) { - if (BO->getOpcode() == BinOpInit::STRCONCAT) { - Init *L = BO->getLHS()->convertInitializerTo(this); - Init *R = BO->getRHS()->convertInitializerTo(this); - if (L == 0 || R == 0) return 0; - if (L != BO->getLHS() || R != BO->getRHS()) - return BinOpInit::get(BinOpInit::STRCONCAT, L, R, new StringRecTy); - return BO; - } - - return convertValue((TypedInit*)BO); -} - - -Init *StringRecTy::convertValue(TypedInit *TI) { - if (dynamic_cast(TI->getType())) - return TI; // Accept variable if already of the right type! - return 0; -} - -std::string ListRecTy::getAsString() const { - return "list<" + Ty->getAsString() + ">"; -} - -Init *ListRecTy::convertValue(ListInit *LI) { - std::vector Elements; - - // Verify that all of the elements of the list are subclasses of the - // appropriate class! - for (unsigned i = 0, e = LI->getSize(); i != e; ++i) - if (Init *CI = LI->getElement(i)->convertInitializerTo(Ty)) - Elements.push_back(CI); - else - return 0; - - ListRecTy *LType = dynamic_cast(LI->getType()); - if (LType == 0) { - return 0; - } - - return ListInit::get(Elements, this); -} - -Init *ListRecTy::convertValue(TypedInit *TI) { - // Ensure that TI is compatible with our class. - if (ListRecTy *LRT = dynamic_cast(TI->getType())) - if (LRT->getElementType()->typeIsConvertibleTo(getElementType())) - return TI; - return 0; -} - -Init *CodeRecTy::convertValue(TypedInit *TI) { - if (TI->getType()->typeIsConvertibleTo(this)) - return TI; - return 0; -} - -Init *DagRecTy::convertValue(TypedInit *TI) { - if (TI->getType()->typeIsConvertibleTo(this)) - return TI; - return 0; -} - -Init *DagRecTy::convertValue(UnOpInit *BO) { - if (BO->getOpcode() == UnOpInit::CAST) { - Init *L = BO->getOperand()->convertInitializerTo(this); - if (L == 0) return 0; - if (L != BO->getOperand()) - return UnOpInit::get(UnOpInit::CAST, L, new DagRecTy); - return BO; - } - return 0; -} - -Init *DagRecTy::convertValue(BinOpInit *BO) { - if (BO->getOpcode() == BinOpInit::CONCAT) { - Init *L = BO->getLHS()->convertInitializerTo(this); - Init *R = BO->getRHS()->convertInitializerTo(this); - if (L == 0 || R == 0) return 0; - if (L != BO->getLHS() || R != BO->getRHS()) - return BinOpInit::get(BinOpInit::CONCAT, L, R, new DagRecTy); - return BO; - } - return 0; -} - -RecordRecTy *RecordRecTy::get(Record *R) { - return &dynamic_cast(*R->getDefInit()->getType()); -} - -std::string RecordRecTy::getAsString() const { - return Rec->getName(); -} - -Init *RecordRecTy::convertValue(DefInit *DI) { - // Ensure that DI is a subclass of Rec. - if (!DI->getDef()->isSubClassOf(Rec)) - return 0; - return DI; -} - -Init *RecordRecTy::convertValue(TypedInit *TI) { - // Ensure that TI is compatible with Rec. - if (RecordRecTy *RRT = dynamic_cast(TI->getType())) - if (RRT->getRecord()->isSubClassOf(getRecord()) || - RRT->getRecord() == getRecord()) - return TI; - return 0; -} - -bool RecordRecTy::baseClassOf(const RecordRecTy *RHS) const { - if (Rec == RHS->getRecord() || RHS->getRecord()->isSubClassOf(Rec)) - return true; - - const std::vector &SC = Rec->getSuperClasses(); - for (unsigned i = 0, e = SC.size(); i != e; ++i) - if (RHS->getRecord()->isSubClassOf(SC[i])) - return true; - - return false; -} - - -/// resolveTypes - Find a common type that T1 and T2 convert to. -/// Return 0 if no such type exists. -/// -RecTy *llvm::resolveTypes(RecTy *T1, RecTy *T2) { - if (!T1->typeIsConvertibleTo(T2)) { - if (!T2->typeIsConvertibleTo(T1)) { - // If one is a Record type, check superclasses - RecordRecTy *RecTy1 = dynamic_cast(T1); - if (RecTy1) { - // See if T2 inherits from a type T1 also inherits from - const std::vector &T1SuperClasses = - RecTy1->getRecord()->getSuperClasses(); - for(std::vector::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; - } - return NewType1; - } - } - } - RecordRecTy *RecTy2 = dynamic_cast(T2); - if (RecTy2) { - // See if T1 inherits from a type T2 also inherits from - const std::vector &T2SuperClasses = - RecTy2->getRecord()->getSuperClasses(); - for (std::vector::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; - } - return NewType2; - } - } - } - return 0; - } - return T2; - } - return T1; -} - - -//===----------------------------------------------------------------------===// -// Initializer implementations -//===----------------------------------------------------------------------===// - -void Init::dump() const { return print(errs()); } - -UnsetInit *UnsetInit::get() { - static UnsetInit TheInit; - return &TheInit; -} - -BitInit *BitInit::get(bool V) { - static BitInit True(true); - static BitInit False(false); - - return V ? &True : &False; -} - -static void -ProfileBitsInit(FoldingSetNodeID &ID, ArrayRef Range) { - ID.AddInteger(Range.size()); - - for (ArrayRef::iterator i = Range.begin(), - iend = Range.end(); - i != iend; - ++i) - ID.AddPointer(*i); -} - -BitsInit *BitsInit::get(ArrayRef Range) { - typedef FoldingSet Pool; - static Pool ThePool; - - FoldingSetNodeID ID; - ProfileBitsInit(ID, Range); - - void *IP = 0; - if (BitsInit *I = ThePool.FindNodeOrInsertPos(ID, IP)) - return I; - - BitsInit *I = new BitsInit(Range); - ThePool.InsertNode(I, IP); - - return I; -} - -void BitsInit::Profile(FoldingSetNodeID &ID) const { - ProfileBitsInit(ID, Bits); -} - -Init * -BitsInit::convertInitializerBitRange(const std::vector &Bits) const { - SmallVector NewBits(Bits.size()); - - for (unsigned i = 0, e = Bits.size(); i != e; ++i) { - if (Bits[i] >= getNumBits()) - return 0; - NewBits[i] = getBit(Bits[i]); - } - return BitsInit::get(NewBits); -} - -std::string BitsInit::getAsString() const { - std::string Result = "{ "; - for (unsigned i = 0, e = getNumBits(); i != e; ++i) { - if (i) Result += ", "; - if (Init *Bit = getBit(e-i-1)) - Result += Bit->getAsString(); - else - Result += "*"; - } - return Result + " }"; -} - -// resolveReferences - If there are any field references that refer to fields -// that have been filled in, we can propagate the values now. -// -Init *BitsInit::resolveReferences(Record &R, const RecordVal *RV) const { - bool Changed = false; - SmallVector NewBits(getNumBits()); - - for (unsigned i = 0, e = Bits.size(); i != e; ++i) { - Init *B; - Init *CurBit = getBit(i); - - do { - B = CurBit; - CurBit = CurBit->resolveReferences(R, RV); - Changed |= B != CurBit; - } while (B != CurBit); - NewBits[i] = CurBit; - } - - if (Changed) - return BitsInit::get(NewBits); - - return const_cast(this); -} - -IntInit *IntInit::get(int64_t V) { - typedef DenseMap Pool; - static Pool ThePool; - - IntInit *&I = ThePool[V]; - if (!I) I = new IntInit(V); - return I; -} - -std::string IntInit::getAsString() const { - return itostr(Value); -} - -Init * -IntInit::convertInitializerBitRange(const std::vector &Bits) const { - SmallVector NewBits(Bits.size()); - - for (unsigned i = 0, e = Bits.size(); i != e; ++i) { - if (Bits[i] >= 64) - return 0; - - NewBits[i] = BitInit::get(Value & (INT64_C(1) << Bits[i])); - } - return BitsInit::get(NewBits); -} - -StringInit *StringInit::get(const std::string &V) { - typedef StringMap Pool; - static Pool ThePool; - - StringInit *&I = ThePool[V]; - if (!I) I = new StringInit(V); - return I; -} - -CodeInit *CodeInit::get(const std::string &V) { - typedef StringMap Pool; - static Pool ThePool; - - CodeInit *&I = ThePool[V]; - if (!I) I = new CodeInit(V); - return I; -} - -static void ProfileListInit(FoldingSetNodeID &ID, - ArrayRef Range, - RecTy *EltTy) { - ID.AddInteger(Range.size()); - ID.AddPointer(EltTy); - - for (ArrayRef::iterator i = Range.begin(), - iend = Range.end(); - i != iend; - ++i) - ID.AddPointer(*i); -} - -ListInit *ListInit::get(ArrayRef Range, RecTy *EltTy) { - typedef FoldingSet 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; - if (ListInit *I = ThePool.FindNodeOrInsertPos(ID, IP)) - return I; - - ListInit *I = new ListInit(Range, EltTy); - ThePool.InsertNode(I, IP); - return I; -} - -void ListInit::Profile(FoldingSetNodeID &ID) const { - ListRecTy *ListType = dynamic_cast(getType()); - assert(ListType && "Bad type for ListInit!"); - RecTy *EltTy = ListType->getElementType(); - - ProfileListInit(ID, Values, EltTy); -} - -Init * -ListInit::convertInitListSlice(const std::vector &Elements) const { - std::vector Vals; - for (unsigned i = 0, e = Elements.size(); i != e; ++i) { - if (Elements[i] >= getSize()) - return 0; - Vals.push_back(getElement(Elements[i])); - } - return ListInit::get(Vals, getType()); -} - -Record *ListInit::getElementAsRecord(unsigned i) const { - assert(i < Values.size() && "List element index out of range!"); - DefInit *DI = dynamic_cast(Values[i]); - if (DI == 0) throw "Expected record in list!"; - return DI->getDef(); -} - -Init *ListInit::resolveReferences(Record &R, const RecordVal *RV) const { - std::vector Resolved; - Resolved.reserve(getSize()); - bool Changed = false; - - for (unsigned i = 0, e = getSize(); i != e; ++i) { - Init *E; - Init *CurElt = getElement(i); - - do { - E = CurElt; - CurElt = CurElt->resolveReferences(R, RV); - Changed |= E != CurElt; - } while (E != CurElt); - Resolved.push_back(E); - } - - if (Changed) - return ListInit::get(Resolved, getType()); - return const_cast(this); -} - -Init *ListInit::resolveListElementReference(Record &R, const RecordVal *IRV, - unsigned Elt) const { - if (Elt >= getSize()) - return 0; // Out of range reference. - Init *E = getElement(Elt); - // 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. - if (IRV || !dynamic_cast(E)) - return E; - return 0; -} - -std::string ListInit::getAsString() const { - std::string Result = "["; - for (unsigned i = 0, e = Values.size(); i != e; ++i) { - if (i) Result += ", "; - Result += Values[i]->getAsString(); - } - return Result + "]"; -} - -Init *OpInit::resolveBitReference(Record &R, const RecordVal *IRV, - unsigned Bit) const { - Init *Folded = Fold(&R, 0); - - if (Folded != this) { - TypedInit *Typed = dynamic_cast(Folded); - if (Typed) { - return Typed->resolveBitReference(R, IRV, Bit); - } - } - - return 0; -} - -Init *OpInit::resolveListElementReference(Record &R, const RecordVal *IRV, - unsigned Elt) const { - Init *Folded = Fold(&R, 0); - - if (Folded != this) { - TypedInit *Typed = dynamic_cast(Folded); - if (Typed) { - return Typed->resolveListElementReference(R, IRV, Elt); - } - } - - return 0; -} - -UnOpInit *UnOpInit::get(UnaryOp opc, Init *lhs, RecTy *Type) { - typedef std::pair, RecTy *> Key; - - typedef DenseMap 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; -} - -Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { - switch (getOpcode()) { - default: assert(0 && "Unknown unop"); - case CAST: { - if (getType()->getAsString() == "string") { - StringInit *LHSs = dynamic_cast(LHS); - if (LHSs) { - return LHSs; - } - - DefInit *LHSd = dynamic_cast(LHS); - if (LHSd) { - return StringInit::get(LHSd->getDef()->getName()); - } - } else { - StringInit *LHSs = dynamic_cast(LHS); - if (LHSs) { - std::string Name = LHSs->getValue(); - - // From TGParser::ParseIDValue - if (CurRec) { - if (const RecordVal *RV = CurRec->getValue(Name)) { - if (RV->getType() != getType()) - throw "type mismatch in cast"; - return VarInit::get(Name, RV->getType()); - } - - std::string TemplateArgName = CurRec->getName()+":"+Name; - if (CurRec->isTemplateArg(TemplateArgName)) { - const RecordVal *RV = CurRec->getValue(TemplateArgName); - assert(RV && "Template arg doesn't exist??"); - - if (RV->getType() != getType()) - throw "type mismatch in cast"; - - return VarInit::get(TemplateArgName, RV->getType()); - } - } - - if (CurMultiClass) { - std::string MCName = CurMultiClass->Rec.getName()+"::"+Name; - if (CurMultiClass->Rec.isTemplateArg(MCName)) { - const RecordVal *RV = CurMultiClass->Rec.getValue(MCName); - assert(RV && "Template arg doesn't exist??"); - - if (RV->getType() != getType()) - throw "type mismatch in cast"; - - return VarInit::get(MCName, RV->getType()); - } - } - - if (Record *D = (CurRec->getRecords()).getDef(Name)) - return DefInit::get(D); - - throw TGError(CurRec->getLoc(), "Undefined reference:'" + Name + "'\n"); - } - } - break; - } - case HEAD: { - ListInit *LHSl = dynamic_cast(LHS); - if (LHSl) { - if (LHSl->getSize() == 0) { - assert(0 && "Empty list in car"); - return 0; - } - return LHSl->getElement(0); - } - break; - } - case TAIL: { - ListInit *LHSl = dynamic_cast(LHS); - if (LHSl) { - if (LHSl->getSize() == 0) { - assert(0 && "Empty list in cdr"); - return 0; - } - // Note the +1. We can't just pass the result of getValues() - // directly. - ArrayRef::iterator begin = LHSl->getValues().begin()+1; - ArrayRef::iterator end = LHSl->getValues().end(); - ListInit *Result = - ListInit::get(ArrayRef(begin, end - begin), - LHSl->getType()); - return Result; - } - break; - } - case EMPTY: { - ListInit *LHSl = dynamic_cast(LHS); - if (LHSl) { - if (LHSl->getSize() == 0) { - return IntInit::get(1); - } else { - return IntInit::get(0); - } - } - StringInit *LHSs = dynamic_cast(LHS); - if (LHSs) { - if (LHSs->getValue().empty()) { - return IntInit::get(1); - } else { - return IntInit::get(0); - } - } - - break; - } - } - return const_cast(this); -} - -Init *UnOpInit::resolveReferences(Record &R, const RecordVal *RV) const { - Init *lhs = LHS->resolveReferences(R, RV); - - if (LHS != lhs) - return (UnOpInit::get(getOpcode(), lhs, getType()))->Fold(&R, 0); - return Fold(&R, 0); -} - -std::string UnOpInit::getAsString() const { - std::string Result; - switch (Opc) { - case CAST: Result = "!cast<" + getType()->getAsString() + ">"; break; - case HEAD: Result = "!head"; break; - case TAIL: Result = "!tail"; break; - case EMPTY: Result = "!empty"; break; - } - return Result + "(" + LHS->getAsString() + ")"; -} - -BinOpInit *BinOpInit::get(BinaryOp opc, Init *lhs, - Init *rhs, RecTy *Type) { - typedef std::pair< - std::pair, Init *>, - RecTy * - > Key; - - typedef DenseMap 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; -} - -Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { - switch (getOpcode()) { - default: assert(0 && "Unknown binop"); - case CONCAT: { - DagInit *LHSs = dynamic_cast(LHS); - DagInit *RHSs = dynamic_cast(RHS); - if (LHSs && RHSs) { - DefInit *LOp = dynamic_cast(LHSs->getOperator()); - DefInit *ROp = dynamic_cast(RHSs->getOperator()); - if (LOp == 0 || ROp == 0 || LOp->getDef() != ROp->getDef()) - throw "Concated Dag operators do not match!"; - std::vector Args; - std::vector 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)); - } - return DagInit::get(LHSs->getOperator(), "", Args, ArgNames); - } - break; - } - case STRCONCAT: { - StringInit *LHSs = dynamic_cast(LHS); - StringInit *RHSs = dynamic_cast(RHS); - if (LHSs && RHSs) - return StringInit::get(LHSs->getValue() + RHSs->getValue()); - break; - } - case EQ: { - // try to fold eq comparison for 'bit' and 'int', otherwise fallback - // to string objects. - IntInit* L = - dynamic_cast(LHS->convertInitializerTo(IntRecTy::get())); - IntInit* R = - dynamic_cast(RHS->convertInitializerTo(IntRecTy::get())); - - if (L && R) - return IntInit::get(L->getValue() == R->getValue()); - - StringInit *LHSs = dynamic_cast(LHS); - StringInit *RHSs = dynamic_cast(RHS); - - // Make sure we've resolved - if (LHSs && RHSs) - return IntInit::get(LHSs->getValue() == RHSs->getValue()); - - break; - } - case SHL: - case SRA: - case SRL: { - IntInit *LHSi = dynamic_cast(LHS); - IntInit *RHSi = dynamic_cast(RHS); - if (LHSi && RHSi) { - int64_t LHSv = LHSi->getValue(), RHSv = RHSi->getValue(); - int64_t Result; - switch (getOpcode()) { - default: assert(0 && "Bad opcode!"); - case SHL: Result = LHSv << RHSv; break; - case SRA: Result = LHSv >> RHSv; break; - case SRL: Result = (uint64_t)LHSv >> (uint64_t)RHSv; break; - } - return IntInit::get(Result); - } - break; - } - } - return const_cast(this); -} - -Init *BinOpInit::resolveReferences(Record &R, const RecordVal *RV) const { - Init *lhs = LHS->resolveReferences(R, RV); - Init *rhs = RHS->resolveReferences(R, RV); - - if (LHS != lhs || RHS != rhs) - return (BinOpInit::get(getOpcode(), lhs, rhs, getType()))->Fold(&R, 0); - return Fold(&R, 0); -} - -std::string BinOpInit::getAsString() const { - std::string Result; - switch (Opc) { - case CONCAT: Result = "!con"; break; - case SHL: Result = "!shl"; break; - case SRA: Result = "!sra"; break; - case SRL: Result = "!srl"; break; - case EQ: Result = "!eq"; break; - case STRCONCAT: Result = "!strconcat"; break; - } - return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")"; -} - -TernOpInit *TernOpInit::get(TernaryOp opc, Init *lhs, - Init *mhs, Init *rhs, - RecTy *Type) { - typedef std::pair< - std::pair< - std::pair, Init *>, - Init * - >, - Init * - > Key; - - typedef DenseMap 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; -} - -static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type, - Record *CurRec, MultiClass *CurMultiClass); - -static Init *EvaluateOperation(OpInit *RHSo, Init *LHS, Init *Arg, - RecTy *Type, Record *CurRec, - MultiClass *CurMultiClass) { - std::vector NewOperands; - - TypedInit *TArg = dynamic_cast(Arg); - - // If this is a dag, recurse - if (TArg && TArg->getType()->getAsString() == "dag") { - Init *Result = ForeachHelper(LHS, Arg, RHSo, Type, - CurRec, CurMultiClass); - if (Result != 0) { - return Result; - } else { - return 0; - } - } - - for (int i = 0; i < RHSo->getNumOperands(); ++i) { - OpInit *RHSoo = dynamic_cast(RHSo->getOperand(i)); - - if (RHSoo) { - Init *Result = EvaluateOperation(RHSoo, LHS, Arg, - Type, CurRec, CurMultiClass); - if (Result != 0) { - NewOperands.push_back(Result); - } else { - NewOperands.push_back(Arg); - } - } else if (LHS->getAsString() == RHSo->getOperand(i)->getAsString()) { - NewOperands.push_back(Arg); - } else { - NewOperands.push_back(RHSo->getOperand(i)); - } - } - - // Now run the operator and use its result as the new leaf - const OpInit *NewOp = RHSo->clone(NewOperands); - Init *NewVal = NewOp->Fold(CurRec, CurMultiClass); - if (NewVal != NewOp) - return NewVal; - - return 0; -} - -static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type, - Record *CurRec, MultiClass *CurMultiClass) { - DagInit *MHSd = dynamic_cast(MHS); - ListInit *MHSl = dynamic_cast(MHS); - - DagRecTy *DagType = dynamic_cast(Type); - ListRecTy *ListType = dynamic_cast(Type); - - OpInit *RHSo = dynamic_cast(RHS); - - if (!RHSo) { - throw TGError(CurRec->getLoc(), "!foreach requires an operator\n"); - } - - TypedInit *LHSt = dynamic_cast(LHS); - - if (!LHSt) { - throw TGError(CurRec->getLoc(), "!foreach requires typed variable\n"); - } - - if ((MHSd && DagType) || (MHSl && ListType)) { - if (MHSd) { - Init *Val = MHSd->getOperator(); - Init *Result = EvaluateOperation(RHSo, LHS, Val, - Type, CurRec, CurMultiClass); - if (Result != 0) { - Val = Result; - } - - std::vector > args; - for (unsigned int i = 0; i < MHSd->getNumArgs(); ++i) { - Init *Arg; - std::string ArgName; - Arg = MHSd->getArg(i); - ArgName = MHSd->getArgName(i); - - // Process args - Init *Result = EvaluateOperation(RHSo, LHS, Arg, Type, - CurRec, CurMultiClass); - if (Result != 0) { - Arg = Result; - } - - // TODO: Process arg names - args.push_back(std::make_pair(Arg, ArgName)); - } - - return DagInit::get(Val, "", args); - } - if (MHSl) { - std::vector NewOperands; - std::vector NewList(MHSl->begin(), MHSl->end()); - - for (std::vector::iterator li = NewList.begin(), - liend = NewList.end(); - li != liend; - ++li) { - Init *Item = *li; - 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); - } else { - NewOperands.push_back(RHSo->getOperand(i)); - } - } - - // Now run the operator and use its result as the new list item - const OpInit *NewOp = RHSo->clone(NewOperands); - Init *NewItem = NewOp->Fold(CurRec, CurMultiClass); - if (NewItem != NewOp) - *li = NewItem; - } - return ListInit::get(NewList, MHSl->getType()); - } - } - return 0; -} - -Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const { - switch (getOpcode()) { - default: assert(0 && "Unknown binop"); - case SUBST: { - DefInit *LHSd = dynamic_cast(LHS); - VarInit *LHSv = dynamic_cast(LHS); - StringInit *LHSs = dynamic_cast(LHS); - - DefInit *MHSd = dynamic_cast(MHS); - VarInit *MHSv = dynamic_cast(MHS); - StringInit *MHSs = dynamic_cast(MHS); - - DefInit *RHSd = dynamic_cast(RHS); - VarInit *RHSv = dynamic_cast(RHS); - StringInit *RHSs = dynamic_cast(RHS); - - if ((LHSd && MHSd && RHSd) - || (LHSv && MHSv && RHSv) - || (LHSs && MHSs && RHSs)) { - if (RHSd) { - Record *Val = RHSd->getDef(); - if (LHSd->getAsString() == RHSd->getAsString()) { - Val = MHSd->getDef(); - } - return DefInit::get(Val); - } - if (RHSv) { - std::string Val = RHSv->getName(); - if (LHSv->getAsString() == RHSv->getAsString()) { - Val = MHSv->getName(); - } - return VarInit::get(Val, getType()); - } - if (RHSs) { - std::string Val = RHSs->getValue(); - - std::string::size_type found; - std::string::size_type idx = 0; - do { - found = Val.find(LHSs->getValue(), idx); - if (found != std::string::npos) { - Val.replace(found, LHSs->getValue().size(), MHSs->getValue()); - } - idx = found + MHSs->getValue().size(); - } while (found != std::string::npos); - - return StringInit::get(Val); - } - } - break; - } - - case FOREACH: { - Init *Result = ForeachHelper(LHS, MHS, RHS, getType(), - CurRec, CurMultiClass); - if (Result != 0) { - return Result; - } - break; - } - - case IF: { - IntInit *LHSi = dynamic_cast(LHS); - if (Init *I = LHS->convertInitializerTo(IntRecTy::get())) - LHSi = dynamic_cast(I); - if (LHSi) { - if (LHSi->getValue()) { - return MHS; - } else { - return RHS; - } - } - break; - } - } - - return const_cast(this); -} - -Init *TernOpInit::resolveReferences(Record &R, - const RecordVal *RV) const { - Init *lhs = LHS->resolveReferences(R, RV); - - if (Opc == IF && lhs != LHS) { - IntInit *Value = dynamic_cast(lhs); - if (Init *I = lhs->convertInitializerTo(IntRecTy::get())) - Value = dynamic_cast(I); - if (Value != 0) { - // Short-circuit - if (Value->getValue()) { - Init *mhs = MHS->resolveReferences(R, RV); - return (TernOpInit::get(getOpcode(), lhs, mhs, - RHS, getType()))->Fold(&R, 0); - } else { - Init *rhs = RHS->resolveReferences(R, RV); - return (TernOpInit::get(getOpcode(), lhs, MHS, - rhs, getType()))->Fold(&R, 0); - } - } - } - - Init *mhs = MHS->resolveReferences(R, RV); - Init *rhs = RHS->resolveReferences(R, RV); - - if (LHS != lhs || MHS != mhs || RHS != rhs) - return (TernOpInit::get(getOpcode(), lhs, mhs, rhs, - getType()))->Fold(&R, 0); - return Fold(&R, 0); -} - -std::string TernOpInit::getAsString() const { - std::string Result; - switch (Opc) { - case SUBST: Result = "!subst"; break; - case FOREACH: Result = "!foreach"; break; - case IF: Result = "!if"; break; - } - return Result + "(" + LHS->getAsString() + ", " + MHS->getAsString() + ", " - + RHS->getAsString() + ")"; -} - -RecTy *TypedInit::getFieldType(const std::string &FieldName) const { - RecordRecTy *RecordType = dynamic_cast(getType()); - if (RecordType) { - RecordVal *Field = RecordType->getRecord()->getValue(FieldName); - if (Field) { - return Field->getType(); - } - } - return 0; -} - -Init * -TypedInit::convertInitializerBitRange(const std::vector &Bits) const { - BitsRecTy *T = dynamic_cast(getType()); - if (T == 0) return 0; // Cannot subscript a non-bits variable. - unsigned NumBits = T->getNumBits(); - - SmallVector NewBits(Bits.size()); - for (unsigned i = 0, e = Bits.size(); i != e; ++i) { - if (Bits[i] >= NumBits) - return 0; - - NewBits[i] = VarBitInit::get(const_cast(this), Bits[i]); - } - return BitsInit::get(NewBits); -} - -Init * -TypedInit::convertInitListSlice(const std::vector &Elements) const { - ListRecTy *T = dynamic_cast(getType()); - if (T == 0) return 0; // Cannot subscript a non-list variable. - - if (Elements.size() == 1) - return VarListElementInit::get(const_cast(this), Elements[0]); - - std::vector ListInits; - ListInits.reserve(Elements.size()); - for (unsigned i = 0, e = Elements.size(); i != e; ++i) - ListInits.push_back(VarListElementInit::get(const_cast(this), - Elements[i])); - return ListInit::get(ListInits, T); -} - - -VarInit *VarInit::get(const std::string &VN, RecTy *T) { - typedef std::pair Key; - typedef DenseMap Pool; - static Pool ThePool; - - Key TheKey(std::make_pair(T, VN)); - - VarInit *&I = ThePool[TheKey]; - if (!I) I = new VarInit(VN, T); - return I; -} - -Init *VarInit::resolveBitReference(Record &R, const RecordVal *IRV, - unsigned Bit) const { - if (R.isTemplateArg(getName())) return 0; - if (IRV && IRV->getName() != getName()) return 0; - - RecordVal *RV = R.getValue(getName()); - assert(RV && "Reference to a non-existent variable?"); - assert(dynamic_cast(RV->getValue())); - BitsInit *BI = (BitsInit*)RV->getValue(); - - assert(Bit < BI->getNumBits() && "Bit reference out of range!"); - Init *B = BI->getBit(Bit); - - // If the bit 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 - // VarBitInit with it. - if (IRV || !dynamic_cast(B)) - return B; - return 0; -} - -Init *VarInit::resolveListElementReference(Record &R, - const RecordVal *IRV, - unsigned Elt) const { - if (R.isTemplateArg(getName())) return 0; - if (IRV && IRV->getName() != getName()) return 0; - - RecordVal *RV = R.getValue(getName()); - assert(RV && "Reference to a non-existent variable?"); - ListInit *LI = dynamic_cast(RV->getValue()); - if (!LI) { - VarInit *VI = dynamic_cast(RV->getValue()); - assert(VI && "Invalid list element!"); - return VarListElementInit::get(VI, Elt); - } - - if (Elt >= LI->getSize()) - return 0; // Out of range reference. - Init *E = LI->getElement(Elt); - // 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. - if (IRV || !dynamic_cast(E)) - return E; - return 0; -} - - -RecTy *VarInit::getFieldType(const std::string &FieldName) const { - if (RecordRecTy *RTy = dynamic_cast(getType())) - if (const RecordVal *RV = RTy->getRecord()->getValue(FieldName)) - return RV->getType(); - return 0; -} - -Init *VarInit::getFieldInit(Record &R, const RecordVal *RV, - const std::string &FieldName) const { - if (dynamic_cast(getType())) - if (const RecordVal *Val = R.getValue(VarName)) { - if (RV != Val && (RV || dynamic_cast(Val->getValue()))) - return 0; - Init *TheInit = Val->getValue(); - assert(TheInit != this && "Infinite loop detected!"); - if (Init *I = TheInit->getFieldInit(R, RV, FieldName)) - return I; - else - return 0; - } - return 0; -} - -/// resolveReferences - This method is used by classes that refer to other -/// variables which may not be defined at the time the expression is formed. -/// If a value is set for the variable later, this method will be called on -/// users of the value to allow the value to propagate out. -/// -Init *VarInit::resolveReferences(Record &R, const RecordVal *RV) const { - if (RecordVal *Val = R.getValue(VarName)) - if (RV == Val || (RV == 0 && !dynamic_cast(Val->getValue()))) - return Val->getValue(); - return const_cast(this); -} - -VarBitInit *VarBitInit::get(TypedInit *T, unsigned B) { - typedef std::pair Key; - typedef DenseMap Pool; - - static Pool ThePool; - - Key TheKey(std::make_pair(T, B)); - - VarBitInit *&I = ThePool[TheKey]; - if (!I) I = new VarBitInit(T, B); - return I; -} - -std::string VarBitInit::getAsString() const { - return TI->getAsString() + "{" + utostr(Bit) + "}"; -} - -Init *VarBitInit::resolveReferences(Record &R, const RecordVal *RV) const { - if (Init *I = getVariable()->resolveBitReference(R, RV, getBitNum())) - return I; - return const_cast(this); -} - -VarListElementInit *VarListElementInit::get(TypedInit *T, - unsigned E) { - typedef std::pair Key; - typedef DenseMap Pool; - - static Pool ThePool; - - Key TheKey(std::make_pair(T, E)); - - VarListElementInit *&I = ThePool[TheKey]; - if (!I) I = new VarListElementInit(T, E); - return I; -} - -std::string VarListElementInit::getAsString() const { - return TI->getAsString() + "[" + utostr(Element) + "]"; -} - -Init * -VarListElementInit::resolveReferences(Record &R, const RecordVal *RV) const { - if (Init *I = getVariable()->resolveListElementReference(R, RV, - getElementNum())) - return I; - return const_cast(this); -} - -Init *VarListElementInit::resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit) const { - // FIXME: This should be implemented, to support references like: - // bit B = AA[0]{1}; - return 0; -} - -Init *VarListElementInit:: resolveListElementReference(Record &R, - const RecordVal *RV, - unsigned Elt) const { - Init *Result = TI->resolveListElementReference(R, RV, Element); - - if (Result) { - TypedInit *TInit = dynamic_cast(Result); - if (TInit) { - return TInit->resolveListElementReference(R, RV, Elt); - } - return Result; - } - - return 0; -} - -DefInit *DefInit::get(Record *R) { - return R->getDefInit(); -} - -RecTy *DefInit::getFieldType(const std::string &FieldName) const { - if (const RecordVal *RV = Def->getValue(FieldName)) - return RV->getType(); - return 0; -} - -Init *DefInit::getFieldInit(Record &R, const RecordVal *RV, - const std::string &FieldName) const { - return Def->getValue(FieldName)->getValue(); -} - - -std::string DefInit::getAsString() const { - return Def->getName(); -} - -FieldInit *FieldInit::get(Init *R, const std::string &FN) { - typedef std::pair Key; - typedef DenseMap Pool; - static Pool ThePool; - - Key TheKey(std::make_pair(R, FN)); - - FieldInit *&I = ThePool[TheKey]; - if (!I) I = new FieldInit(R, FN); - return I; -} - -Init *FieldInit::resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit) const { - if (Init *BitsVal = Rec->getFieldInit(R, RV, FieldName)) - if (BitsInit *BI = dynamic_cast(BitsVal)) { - assert(Bit < BI->getNumBits() && "Bit reference out of range!"); - Init *B = BI->getBit(Bit); - - if (dynamic_cast(B)) // If the bit is set. - return B; // Replace the VarBitInit with it. - } - return 0; -} - -Init *FieldInit::resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const { - if (Init *ListVal = Rec->getFieldInit(R, RV, FieldName)) - if (ListInit *LI = dynamic_cast(ListVal)) { - if (Elt >= LI->getSize()) return 0; - Init *E = LI->getElement(Elt); - - // 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. - if (RV || !dynamic_cast(E)) - return E; - } - return 0; -} - -Init *FieldInit::resolveReferences(Record &R, const RecordVal *RV) const { - Init *NewRec = RV ? Rec->resolveReferences(R, RV) : Rec; - - Init *BitsVal = NewRec->getFieldInit(R, RV, FieldName); - if (BitsVal) { - Init *BVR = BitsVal->resolveReferences(R, RV); - return BVR->isComplete() ? BVR : const_cast(this); - } - - if (NewRec != Rec) { - return FieldInit::get(NewRec, FieldName); - } - return const_cast(this); -} - -void ProfileDagInit(FoldingSetNodeID &ID, - Init *V, - const std::string &VN, - ArrayRef ArgRange, - ArrayRef NameRange) { - ID.AddPointer(V); - ID.AddString(VN); - - ArrayRef::iterator Arg = ArgRange.begin(); - ArrayRef::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!"); -} - -DagInit * -DagInit::get(Init *V, const std::string &VN, - ArrayRef ArgRange, - ArrayRef NameRange) { - typedef FoldingSet Pool; - static Pool ThePool; - - FoldingSetNodeID ID; - ProfileDagInit(ID, V, VN, ArgRange, NameRange); - - void *IP = 0; - if (DagInit *I = ThePool.FindNodeOrInsertPos(ID, IP)) - return I; - - DagInit *I = new DagInit(V, VN, ArgRange, NameRange); - ThePool.InsertNode(I, IP); - - return I; -} - -DagInit * -DagInit::get(Init *V, const std::string &VN, - const std::vector > &args) { - typedef std::pair PairType; - - std::vector Args; - std::vector Names; - - for (std::vector::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); -} - -void DagInit::Profile(FoldingSetNodeID &ID) const { - ProfileDagInit(ID, Val, ValName, Args, ArgNames); -} - -Init *DagInit::resolveReferences(Record &R, const RecordVal *RV) const { - std::vector NewArgs; - for (unsigned i = 0, e = Args.size(); i != e; ++i) - NewArgs.push_back(Args[i]->resolveReferences(R, RV)); - - Init *Op = Val->resolveReferences(R, RV); - - if (Args != NewArgs || Op != Val) - return DagInit::get(Op, ValName, NewArgs, ArgNames); - - return const_cast(this); -} - - -std::string DagInit::getAsString() const { - std::string Result = "(" + Val->getAsString(); - if (!ValName.empty()) - Result += ":" + ValName; - if (Args.size()) { - Result += " " + Args[0]->getAsString(); - if (!ArgNames[0].empty()) Result += ":$" + ArgNames[0]; - for (unsigned i = 1, e = Args.size(); i != e; ++i) { - Result += ", " + Args[i]->getAsString(); - if (!ArgNames[i].empty()) Result += ":$" + ArgNames[i]; - } - } - return Result + ")"; -} - - -//===----------------------------------------------------------------------===// -// Other implementations -//===----------------------------------------------------------------------===// - -RecordVal::RecordVal(Init *N, RecTy *T, unsigned P) - : Name(N), Ty(T), Prefix(P) { - Value = Ty->convertValue(UnsetInit::get()); - assert(Value && "Cannot create unset value for current type!"); -} - -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 { - StringInit *NameString = dynamic_cast(Name); - assert(NameString && "RecordVal name is not a string!"); - return NameString->getValue(); -} - -void RecordVal::dump() const { errs() << *this; } - -void RecordVal::print(raw_ostream &OS, bool PrintSem) const { - if (getPrefix()) OS << "field "; - OS << *getType() << " " << getName(); - - if (getValue()) - OS << " = " << *getValue(); - - if (PrintSem) OS << ";\n"; -} - -unsigned Record::LastID = 0; - -void Record::checkName() { - // Ensure the record name has string type. - const TypedInit *TypedName = dynamic_cast(Name); - assert(TypedName && "Record name is not typed!"); - RecTy *Type = TypedName->getType(); - if (dynamic_cast(Type) == 0) { - llvm_unreachable("Record name is not a string!"); - } -} - -DefInit *Record::getDefInit() { - if (!TheInit) - TheInit = new DefInit(this, new RecordRecTy(this)); - return TheInit; -} - -const std::string &Record::getName() const { - const StringInit *NameString = - dynamic_cast(Name); - 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()); - Name = NewName; - TrackedRecords.addDef(this); - } else { - TrackedRecords.removeClass(Name->getAsUnquotedString()); - Name = NewName; - TrackedRecords.addClass(this); - } - checkName(); - // Since the Init for the name was changed, see if we can resolve - // any of it using members of the Record. - Init *ComputedName = Name->resolveReferences(*this, 0); - if (ComputedName != Name) { - setName(ComputedName); - } - // 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)); -} - -/// 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) { - if (Init *V = Values[i].getValue()) - Values[i].setValue(V->resolveReferences(*this, RV)); - } -} - -void Record::dump() const { errs() << *this; } - -raw_ostream &llvm::operator<<(raw_ostream &OS, const Record &R) { - OS << R.getName(); - - const std::vector &TArgs = R.getTemplateArgs(); - 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 &SC = R.getSuperClasses(); - if (!SC.empty()) { - OS << "\t//"; - for (unsigned i = 0, e = SC.size(); i != e; ++i) - OS << " " << SC[i]->getName(); - } - OS << "\n"; - - const std::vector &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"; -} - -/// getValueInit - Return the initializer for a value with the specified name, -/// or throw an exception if the field does not exist. -/// -Init *Record::getValueInit(StringRef FieldName) const { - const RecordVal *R = getValue(FieldName); - if (R == 0 || R->getValue() == 0) - throw "Record `" + getName() + "' does not have a field named `" + - FieldName.str() + "'!\n"; - return R->getValue(); -} - - -/// getValueAsString - This method looks up the specified field and returns its -/// value as a string, throwing an exception if the field does not exist or if -/// the value is not a string. -/// -std::string Record::getValueAsString(StringRef FieldName) const { - const RecordVal *R = getValue(FieldName); - if (R == 0 || R->getValue() == 0) - throw "Record `" + getName() + "' does not have a field named `" + - FieldName.str() + "'!\n"; - - if (StringInit *SI = dynamic_cast(R->getValue())) - return SI->getValue(); - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' does not have a string initializer!"; -} - -/// getValueAsBitsInit - This method looks up the specified field and returns -/// its value as a BitsInit, throwing an exception if the field does not exist -/// or if the value is not the right type. -/// -BitsInit *Record::getValueAsBitsInit(StringRef FieldName) const { - const RecordVal *R = getValue(FieldName); - if (R == 0 || R->getValue() == 0) - throw "Record `" + getName() + "' does not have a field named `" + - FieldName.str() + "'!\n"; - - if (BitsInit *BI = dynamic_cast(R->getValue())) - return BI; - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' does not have a BitsInit initializer!"; -} - -/// getValueAsListInit - This method looks up the specified field and returns -/// its value as a ListInit, throwing an exception if the field does not exist -/// or if the value is not the right type. -/// -ListInit *Record::getValueAsListInit(StringRef FieldName) const { - const RecordVal *R = getValue(FieldName); - if (R == 0 || R->getValue() == 0) - throw "Record `" + getName() + "' does not have a field named `" + - FieldName.str() + "'!\n"; - - if (ListInit *LI = dynamic_cast(R->getValue())) - return LI; - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' does not have a list initializer!"; -} - -/// getValueAsListOfDefs - This method looks up the specified field and returns -/// its value as a vector of records, throwing an exception if the field does -/// not exist or if the value is not the right type. -/// -std::vector -Record::getValueAsListOfDefs(StringRef FieldName) const { - ListInit *List = getValueAsListInit(FieldName); - std::vector Defs; - for (unsigned i = 0; i < List->getSize(); i++) { - if (DefInit *DI = dynamic_cast(List->getElement(i))) { - Defs.push_back(DI->getDef()); - } else { - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' list is not entirely DefInit!"; - } - } - return Defs; -} - -/// getValueAsInt - This method looks up the specified field and returns its -/// value as an int64_t, throwing an exception if the field does not exist or if -/// the value is not the right type. -/// -int64_t Record::getValueAsInt(StringRef FieldName) const { - const RecordVal *R = getValue(FieldName); - if (R == 0 || R->getValue() == 0) - throw "Record `" + getName() + "' does not have a field named `" + - FieldName.str() + "'!\n"; - - if (IntInit *II = dynamic_cast(R->getValue())) - return II->getValue(); - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' does not have an int initializer!"; -} - -/// getValueAsListOfInts - This method looks up the specified field and returns -/// its value as a vector of integers, throwing an exception if the field does -/// not exist or if the value is not the right type. -/// -std::vector -Record::getValueAsListOfInts(StringRef FieldName) const { - ListInit *List = getValueAsListInit(FieldName); - std::vector Ints; - for (unsigned i = 0; i < List->getSize(); i++) { - if (IntInit *II = dynamic_cast(List->getElement(i))) { - Ints.push_back(II->getValue()); - } else { - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' does not have a list of ints initializer!"; - } - } - return Ints; -} - -/// getValueAsListOfStrings - This method looks up the specified field and -/// returns its value as a vector of strings, throwing an exception if the -/// field does not exist or if the value is not the right type. -/// -std::vector -Record::getValueAsListOfStrings(StringRef FieldName) const { - ListInit *List = getValueAsListInit(FieldName); - std::vector Strings; - for (unsigned i = 0; i < List->getSize(); i++) { - if (StringInit *II = dynamic_cast(List->getElement(i))) { - Strings.push_back(II->getValue()); - } else { - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' does not have a list of strings initializer!"; - } - } - return Strings; -} - -/// getValueAsDef - This method looks up the specified field and returns its -/// value as a Record, throwing an exception if the field does not exist or if -/// the value is not the right type. -/// -Record *Record::getValueAsDef(StringRef FieldName) const { - const RecordVal *R = getValue(FieldName); - if (R == 0 || R->getValue() == 0) - throw "Record `" + getName() + "' does not have a field named `" + - FieldName.str() + "'!\n"; - - if (DefInit *DI = dynamic_cast(R->getValue())) - return DI->getDef(); - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' does not have a def initializer!"; -} - -/// getValueAsBit - This method looks up the specified field and returns its -/// value as a bit, throwing an exception if the field does not exist or if -/// the value is not the right type. -/// -bool Record::getValueAsBit(StringRef FieldName) const { - const RecordVal *R = getValue(FieldName); - if (R == 0 || R->getValue() == 0) - throw "Record `" + getName() + "' does not have a field named `" + - FieldName.str() + "'!\n"; - - if (BitInit *BI = dynamic_cast(R->getValue())) - return BI->getValue(); - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' does not have a bit initializer!"; -} - -/// getValueAsDag - This method looks up the specified field and returns its -/// value as an Dag, throwing an exception if the field does not exist or if -/// the value is not the right type. -/// -DagInit *Record::getValueAsDag(StringRef FieldName) const { - const RecordVal *R = getValue(FieldName); - if (R == 0 || R->getValue() == 0) - throw "Record `" + getName() + "' does not have a field named `" + - FieldName.str() + "'!\n"; - - if (DagInit *DI = dynamic_cast(R->getValue())) - return DI; - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' does not have a dag initializer!"; -} - -std::string Record::getValueAsCode(StringRef FieldName) const { - const RecordVal *R = getValue(FieldName); - if (R == 0 || R->getValue() == 0) - throw "Record `" + getName() + "' does not have a field named `" + - FieldName.str() + "'!\n"; - - if (CodeInit *CI = dynamic_cast(R->getValue())) - return CI->getValue(); - throw "Record `" + getName() + "', field `" + FieldName.str() + - "' does not have a code initializer!"; -} - - -void MultiClass::dump() const { - errs() << "Record:\n"; - Rec.dump(); - - errs() << "Defs:\n"; - for (RecordVector::const_iterator r = DefPrototypes.begin(), - rend = DefPrototypes.end(); - r != rend; - ++r) { - (*r)->dump(); - } -} - - -void RecordKeeper::dump() const { errs() << *this; } - -raw_ostream &llvm::operator<<(raw_ostream &OS, const RecordKeeper &RK) { - OS << "------------- Classes -----------------\n"; - const std::map &Classes = RK.getClasses(); - for (std::map::const_iterator I = Classes.begin(), - E = Classes.end(); I != E; ++I) - OS << "class " << *I->second; - - OS << "------------- Defs -----------------\n"; - const std::map &Defs = RK.getDefs(); - for (std::map::const_iterator I = Defs.begin(), - E = Defs.end(); I != E; ++I) - OS << "def " << *I->second; - return OS; -} - - -/// 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. -std::vector -RecordKeeper::getAllDerivedDefinitions(const std::string &ClassName) const { - Record *Class = getClass(ClassName); - if (!Class) - throw "ERROR: Couldn't find the `" + ClassName + "' class!\n"; - - std::vector Defs; - for (std::map::const_iterator I = getDefs().begin(), - E = getDefs().end(); I != E; ++I) - if (I->second->isSubClassOf(Class)) - Defs.push_back(I->second); - - return Defs; -} - diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h deleted file mode 100644 index 84313e66d58..00000000000 --- a/utils/TableGen/Record.h +++ /dev/null @@ -1,1656 +0,0 @@ - -//===- Record.h - Classes to represent Table Records ------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the main TableGen data structures, including the TableGen -// types, values, and high-level data structures. -// -//===----------------------------------------------------------------------===// - -#ifndef RECORD_H -#define RECORD_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/raw_ostream.h" -#include - -namespace llvm { -class raw_ostream; - -// RecTy subclasses. -class BitRecTy; -class BitsRecTy; -class IntRecTy; -class StringRecTy; -class ListRecTy; -class CodeRecTy; -class DagRecTy; -class RecordRecTy; - -// Init subclasses. -class Init; -class UnsetInit; -class BitInit; -class BitsInit; -class IntInit; -class StringInit; -class CodeInit; -class ListInit; -class UnOpInit; -class BinOpInit; -class TernOpInit; -class DefInit; -class DagInit; -class TypedInit; -class VarInit; -class FieldInit; -class VarBitInit; -class VarListElementInit; - -// Other classes. -class Record; -class RecordVal; -struct MultiClass; -class RecordKeeper; - -//===----------------------------------------------------------------------===// -// Type Classes -//===----------------------------------------------------------------------===// - -class RecTy { - ListRecTy *ListTy; -public: - RecTy() : ListTy(0) {} - virtual ~RecTy() {} - - virtual std::string getAsString() const = 0; - void print(raw_ostream &OS) const { OS << getAsString(); } - void dump() const; - - /// typeIsConvertibleTo - Return true if all values of 'this' type can be - /// converted to the specified type. - virtual bool typeIsConvertibleTo(const RecTy *RHS) const = 0; - - /// getListTy - Returns the type representing list. - ListRecTy *getListTy(); - -public: // These methods should only be called from subclasses of Init - virtual Init *convertValue( UnsetInit *UI) { return 0; } - virtual Init *convertValue( BitInit *BI) { return 0; } - virtual Init *convertValue( BitsInit *BI) { return 0; } - virtual Init *convertValue( IntInit *II) { return 0; } - virtual Init *convertValue(StringInit *SI) { return 0; } - virtual Init *convertValue( ListInit *LI) { return 0; } - virtual Init *convertValue( UnOpInit *UI) { - return convertValue((TypedInit*)UI); - } - virtual Init *convertValue( BinOpInit *UI) { - return convertValue((TypedInit*)UI); - } - virtual Init *convertValue( TernOpInit *UI) { - return convertValue((TypedInit*)UI); - } - virtual Init *convertValue( CodeInit *CI) { return 0; } - virtual Init *convertValue(VarBitInit *VB) { return 0; } - virtual Init *convertValue( DefInit *DI) { return 0; } - virtual Init *convertValue( DagInit *DI) { return 0; } - virtual Init *convertValue( TypedInit *TI) { return 0; } - virtual Init *convertValue( VarInit *VI) { - return convertValue((TypedInit*)VI); - } - virtual Init *convertValue( FieldInit *FI) { - return convertValue((TypedInit*)FI); - } - -public: // These methods should only be called by subclasses of RecTy. - // baseClassOf - These virtual methods should be overloaded to return true iff - // all values of type 'RHS' can be converted to the 'this' type. - virtual bool baseClassOf(const BitRecTy *RHS) const { return false; } - virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; } - virtual bool baseClassOf(const IntRecTy *RHS) const { return false; } - virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } - virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } - virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; } - virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } - virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } -}; - -inline raw_ostream &operator<<(raw_ostream &OS, const RecTy &Ty) { - Ty.print(OS); - return OS; -} - - -/// BitRecTy - 'bit' - Represent a single bit -/// -class BitRecTy : public RecTy { - static BitRecTy Shared; - BitRecTy() {} -public: - static BitRecTy *get() { return &Shared; } - - virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } - virtual Init *convertValue( BitInit *BI) { return (Init*)BI; } - virtual Init *convertValue( BitsInit *BI); - virtual Init *convertValue( IntInit *II); - virtual Init *convertValue(StringInit *SI) { return 0; } - virtual Init *convertValue( ListInit *LI) { return 0; } - virtual Init *convertValue( CodeInit *CI) { return 0; } - virtual Init *convertValue(VarBitInit *VB) { return (Init*)VB; } - virtual Init *convertValue( DefInit *DI) { return 0; } - virtual Init *convertValue( DagInit *DI) { return 0; } - virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( TypedInit *TI); - virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} - virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - - std::string getAsString() const { return "bit"; } - - bool typeIsConvertibleTo(const RecTy *RHS) const { - return RHS->baseClassOf(this); - } - virtual bool baseClassOf(const BitRecTy *RHS) const { return true; } - virtual bool baseClassOf(const BitsRecTy *RHS) const; - virtual bool baseClassOf(const IntRecTy *RHS) const { return true; } - virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } - virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } - virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; } - virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } - virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } - -}; - - -// BitsRecTy - 'bits' - Represent a fixed number of bits -/// BitsRecTy - 'bits<n>' - Represent a fixed number of bits -/// -class BitsRecTy : public RecTy { - unsigned Size; - explicit BitsRecTy(unsigned Sz) : Size(Sz) {} -public: - static BitsRecTy *get(unsigned Sz); - - unsigned getNumBits() const { return Size; } - - virtual Init *convertValue( UnsetInit *UI); - virtual Init *convertValue( BitInit *UI); - virtual Init *convertValue( BitsInit *BI); - virtual Init *convertValue( IntInit *II); - virtual Init *convertValue(StringInit *SI) { return 0; } - virtual Init *convertValue( ListInit *LI) { return 0; } - virtual Init *convertValue( CodeInit *CI) { return 0; } - virtual Init *convertValue(VarBitInit *VB) { return 0; } - virtual Init *convertValue( DefInit *DI) { return 0; } - virtual Init *convertValue( DagInit *DI) { return 0; } - virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( TypedInit *TI); - virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} - virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - - std::string getAsString() const; - - bool typeIsConvertibleTo(const RecTy *RHS) const { - return RHS->baseClassOf(this); - } - virtual bool baseClassOf(const BitRecTy *RHS) const { return Size == 1; } - virtual bool baseClassOf(const BitsRecTy *RHS) const { - return RHS->Size == Size; - } - virtual bool baseClassOf(const IntRecTy *RHS) const { return true; } - virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } - virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } - virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; } - virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } - virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } - -}; - - -/// IntRecTy - 'int' - Represent an integer value of no particular size -/// -class IntRecTy : public RecTy { - static IntRecTy Shared; - IntRecTy() {} -public: - static IntRecTy *get() { return &Shared; } - - virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } - virtual Init *convertValue( BitInit *BI); - virtual Init *convertValue( BitsInit *BI); - virtual Init *convertValue( IntInit *II) { return (Init*)II; } - virtual Init *convertValue(StringInit *SI) { return 0; } - virtual Init *convertValue( ListInit *LI) { return 0; } - virtual Init *convertValue( CodeInit *CI) { return 0; } - virtual Init *convertValue(VarBitInit *VB) { return 0; } - virtual Init *convertValue( DefInit *DI) { return 0; } - virtual Init *convertValue( DagInit *DI) { return 0; } - virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( TypedInit *TI); - virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} - virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - - std::string getAsString() const { return "int"; } - - bool typeIsConvertibleTo(const RecTy *RHS) const { - return RHS->baseClassOf(this); - } - - virtual bool baseClassOf(const BitRecTy *RHS) const { return true; } - virtual bool baseClassOf(const BitsRecTy *RHS) const { return true; } - virtual bool baseClassOf(const IntRecTy *RHS) const { return true; } - virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } - virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } - virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; } - virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } - virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } - -}; - -/// StringRecTy - 'string' - Represent an string value -/// -class StringRecTy : public RecTy { - static StringRecTy Shared; - StringRecTy() {} -public: - static StringRecTy *get() { return &Shared; } - - virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } - virtual Init *convertValue( BitInit *BI) { return 0; } - virtual Init *convertValue( BitsInit *BI) { return 0; } - virtual Init *convertValue( IntInit *II) { return 0; } - virtual Init *convertValue(StringInit *SI) { return (Init*)SI; } - virtual Init *convertValue( ListInit *LI) { return 0; } - virtual Init *convertValue( UnOpInit *BO); - virtual Init *convertValue( BinOpInit *BO); - virtual Init *convertValue( TernOpInit *BO) { return RecTy::convertValue(BO);} - - virtual Init *convertValue( CodeInit *CI) { return 0; } - virtual Init *convertValue(VarBitInit *VB) { return 0; } - virtual Init *convertValue( DefInit *DI) { return 0; } - virtual Init *convertValue( DagInit *DI) { return 0; } - virtual Init *convertValue( TypedInit *TI); - virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} - virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - - std::string getAsString() const { return "string"; } - - bool typeIsConvertibleTo(const RecTy *RHS) const { - return RHS->baseClassOf(this); - } - - virtual bool baseClassOf(const BitRecTy *RHS) const { return false; } - virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; } - virtual bool baseClassOf(const IntRecTy *RHS) const { return false; } - virtual bool baseClassOf(const StringRecTy *RHS) const { return true; } - virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } - virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; } - virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } - virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } -}; - -// ListRecTy - 'list' - Represent a list of values, all of which must be of -// the specified type. -/// ListRecTy - 'list<Ty>' - Represent a list of values, all of which must -/// be of the specified type. -/// -class ListRecTy : public RecTy { - RecTy *Ty; - explicit ListRecTy(RecTy *T) : Ty(T) {} - friend ListRecTy *RecTy::getListTy(); -public: - static ListRecTy *get(RecTy *T) { return T->getListTy(); } - RecTy *getElementType() const { return Ty; } - - virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } - virtual Init *convertValue( BitInit *BI) { return 0; } - virtual Init *convertValue( BitsInit *BI) { return 0; } - virtual Init *convertValue( IntInit *II) { return 0; } - virtual Init *convertValue(StringInit *SI) { return 0; } - virtual Init *convertValue( ListInit *LI); - virtual Init *convertValue( CodeInit *CI) { return 0; } - virtual Init *convertValue(VarBitInit *VB) { return 0; } - virtual Init *convertValue( DefInit *DI) { return 0; } - virtual Init *convertValue( DagInit *DI) { return 0; } - virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( TypedInit *TI); - virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} - virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - - std::string getAsString() const; - - bool typeIsConvertibleTo(const RecTy *RHS) const { - return RHS->baseClassOf(this); - } - - virtual bool baseClassOf(const BitRecTy *RHS) const { return false; } - virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; } - virtual bool baseClassOf(const IntRecTy *RHS) const { return false; } - virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } - virtual bool baseClassOf(const ListRecTy *RHS) const { - return RHS->getElementType()->typeIsConvertibleTo(Ty); - } - virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; } - virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } - virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } -}; - -/// CodeRecTy - 'code' - Represent an code fragment, function or method. -/// -class CodeRecTy : public RecTy { - static CodeRecTy Shared; - CodeRecTy() {} -public: - static CodeRecTy *get() { return &Shared; } - - virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } - virtual Init *convertValue( BitInit *BI) { return 0; } - virtual Init *convertValue( BitsInit *BI) { return 0; } - virtual Init *convertValue( IntInit *II) { return 0; } - virtual Init *convertValue(StringInit *SI) { return 0; } - virtual Init *convertValue( ListInit *LI) { return 0; } - virtual Init *convertValue( CodeInit *CI) { return (Init*)CI; } - virtual Init *convertValue(VarBitInit *VB) { return 0; } - virtual Init *convertValue( DefInit *DI) { return 0; } - virtual Init *convertValue( DagInit *DI) { return 0; } - virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( TypedInit *TI); - virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} - virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - - std::string getAsString() const { return "code"; } - - bool typeIsConvertibleTo(const RecTy *RHS) const { - return RHS->baseClassOf(this); - } - virtual bool baseClassOf(const BitRecTy *RHS) const { return false; } - virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; } - virtual bool baseClassOf(const IntRecTy *RHS) const { return false; } - virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } - virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } - virtual bool baseClassOf(const CodeRecTy *RHS) const { return true; } - virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } - virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } -}; - -/// DagRecTy - 'dag' - Represent a dag fragment -/// -class DagRecTy : public RecTy { - static DagRecTy Shared; - DagRecTy() {} -public: - static DagRecTy *get() { return &Shared; } - - virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } - virtual Init *convertValue( BitInit *BI) { return 0; } - virtual Init *convertValue( BitsInit *BI) { return 0; } - virtual Init *convertValue( IntInit *II) { return 0; } - virtual Init *convertValue(StringInit *SI) { return 0; } - virtual Init *convertValue( ListInit *LI) { return 0; } - virtual Init *convertValue( CodeInit *CI) { return 0; } - virtual Init *convertValue(VarBitInit *VB) { return 0; } - virtual Init *convertValue( DefInit *DI) { return 0; } - virtual Init *convertValue( UnOpInit *BO); - virtual Init *convertValue( BinOpInit *BO); - virtual Init *convertValue( TernOpInit *BO) { return RecTy::convertValue(BO);} - virtual Init *convertValue( DagInit *CI) { return (Init*)CI; } - virtual Init *convertValue( TypedInit *TI); - virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} - virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - - std::string getAsString() const { return "dag"; } - - bool typeIsConvertibleTo(const RecTy *RHS) const { - return RHS->baseClassOf(this); - } - - virtual bool baseClassOf(const BitRecTy *RHS) const { return false; } - virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; } - virtual bool baseClassOf(const IntRecTy *RHS) const { return false; } - virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } - virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } - virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; } - virtual bool baseClassOf(const DagRecTy *RHS) const { return true; } - virtual bool baseClassOf(const RecordRecTy *RHS) const { return false; } -}; - - -/// RecordRecTy - '[classname]' - Represent an instance of a class, such as: -/// (R32 X = EAX). -/// -class RecordRecTy : public RecTy { - Record *Rec; - explicit RecordRecTy(Record *R) : Rec(R) {} - friend class Record; -public: - static RecordRecTy *get(Record *R); - - Record *getRecord() const { return Rec; } - - virtual Init *convertValue( UnsetInit *UI) { return (Init*)UI; } - virtual Init *convertValue( BitInit *BI) { return 0; } - virtual Init *convertValue( BitsInit *BI) { return 0; } - virtual Init *convertValue( IntInit *II) { return 0; } - virtual Init *convertValue(StringInit *SI) { return 0; } - virtual Init *convertValue( ListInit *LI) { return 0; } - virtual Init *convertValue( CodeInit *CI) { return 0; } - virtual Init *convertValue(VarBitInit *VB) { return 0; } - virtual Init *convertValue( UnOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( BinOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( TernOpInit *UI) { return RecTy::convertValue(UI);} - virtual Init *convertValue( DefInit *DI); - virtual Init *convertValue( DagInit *DI) { return 0; } - virtual Init *convertValue( TypedInit *VI); - virtual Init *convertValue( VarInit *VI) { return RecTy::convertValue(VI);} - virtual Init *convertValue( FieldInit *FI) { return RecTy::convertValue(FI);} - - std::string getAsString() const; - - bool typeIsConvertibleTo(const RecTy *RHS) const { - return RHS->baseClassOf(this); - } - virtual bool baseClassOf(const BitRecTy *RHS) const { return false; } - virtual bool baseClassOf(const BitsRecTy *RHS) const { return false; } - virtual bool baseClassOf(const IntRecTy *RHS) const { return false; } - virtual bool baseClassOf(const StringRecTy *RHS) const { return false; } - virtual bool baseClassOf(const ListRecTy *RHS) const { return false; } - virtual bool baseClassOf(const CodeRecTy *RHS) const { return false; } - virtual bool baseClassOf(const DagRecTy *RHS) const { return false; } - virtual bool baseClassOf(const RecordRecTy *RHS) const; -}; - -/// resolveTypes - Find a common type that T1 and T2 convert to. -/// Return 0 if no such type exists. -/// -RecTy *resolveTypes(RecTy *T1, RecTy *T2); - -//===----------------------------------------------------------------------===// -// Initializer Classes -//===----------------------------------------------------------------------===// - -class Init { - Init(const Init &); // Do not define. - Init &operator=(const Init &); // Do not define. - -protected: - Init(void) {} - -public: - virtual ~Init() {} - - /// isComplete - This virtual method should be overridden by values that may - /// not be completely specified yet. - virtual bool isComplete() const { return true; } - - /// print - Print out this value. - void print(raw_ostream &OS) const { OS << getAsString(); } - - /// getAsString - Convert this value to a string form. - virtual std::string getAsString() const = 0; - /// getAsUnquotedString - Convert this value to a string form, - /// without adding quote markers. This primaruly affects - /// StringInits where we will not surround the string value with - /// quotes. - virtual std::string getAsUnquotedString() const { return getAsString(); } - - /// dump - Debugging method that may be called through a debugger, just - /// invokes print on stderr. - void dump() const; - - /// convertInitializerTo - This virtual function is a simple call-back - /// function that should be overridden to call the appropriate - /// RecTy::convertValue method. - /// - virtual Init *convertInitializerTo(RecTy *Ty) const = 0; - - /// convertInitializerBitRange - This method is used to implement the bitrange - /// selection operator. Given an initializer, it selects the specified bits - /// out, returning them as a new init of bits type. If it is not legal to use - /// the bit subscript operator on this initializer, return null. - /// - virtual Init * - convertInitializerBitRange(const std::vector &Bits) const { - return 0; - } - - /// convertInitListSlice - This method is used to implement the list slice - /// selection operator. Given an initializer, it selects the specified list - /// elements, returning them as a new init of list type. If it is not legal - /// to take a slice of this, return null. - /// - virtual Init * - convertInitListSlice(const std::vector &Elements) const { - return 0; - } - - /// getFieldType - This method is used to implement the FieldInit class. - /// Implementors of this method should return the type of the named field if - /// they are of record type. - /// - virtual RecTy *getFieldType(const std::string &FieldName) const { return 0; } - - /// getFieldInit - This method complements getFieldType to return the - /// initializer for the specified field. If getFieldType returns non-null - /// this method should return non-null, otherwise it returns null. - /// - virtual Init *getFieldInit(Record &R, const RecordVal *RV, - const std::string &FieldName) const { - return 0; - } - - /// resolveReferences - This method is used by classes that refer to other - /// variables which may not be defined at the time the expression is formed. - /// If a value is set for the variable later, this method will be called on - /// users of the value to allow the value to propagate out. - /// - virtual Init *resolveReferences(Record &R, const RecordVal *RV) const { - return const_cast(this); - } -}; - -inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) { - I.print(OS); return OS; -} - -/// TypedInit - This is the common super-class of types that have a specific, -/// explicit, type. -/// -class TypedInit : public Init { - RecTy *Ty; - - TypedInit(const TypedInit &Other); // Do not define. - TypedInit &operator=(const TypedInit &Other); // Do not define. - -protected: - explicit TypedInit(RecTy *T) : Ty(T) {} - -public: - RecTy *getType() const { return Ty; } - - virtual Init * - convertInitializerBitRange(const std::vector &Bits) const; - virtual Init * - convertInitListSlice(const std::vector &Elements) const; - - /// getFieldType - This method is used to implement the FieldInit class. - /// Implementors of this method should return the type of the named field if - /// they are of record type. - /// - virtual RecTy *getFieldType(const std::string &FieldName) const; - - /// resolveBitReference - This method is used to implement - /// VarBitInit::resolveReferences. If the bit is able to be resolved, we - /// simply return the resolved value, otherwise we return null. - /// - virtual Init *resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit) const = 0; - - /// resolveListElementReference - This method is used to implement - /// VarListElementInit::resolveReferences. If the list element is resolvable - /// now, we return the resolved value, otherwise we return null. - virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const = 0; -}; - - -/// UnsetInit - ? - Represents an uninitialized value -/// -class UnsetInit : public Init { - UnsetInit() : Init() {} - UnsetInit(const UnsetInit &); // Do not define. - UnsetInit &operator=(const UnsetInit &Other); // Do not define. - -public: - static UnsetInit *get(); - - virtual Init *convertInitializerTo(RecTy *Ty) const { - return Ty->convertValue(const_cast(this)); - } - - virtual bool isComplete() const { return false; } - virtual std::string getAsString() const { return "?"; } -}; - - -/// BitInit - true/false - Represent a concrete initializer for a bit. -/// -class BitInit : public Init { - bool Value; - - explicit BitInit(bool V) : Value(V) {} - BitInit(const BitInit &Other); // Do not define. - BitInit &operator=(BitInit &Other); // Do not define. - -public: - static BitInit *get(bool V); - - bool getValue() const { return Value; } - - virtual Init *convertInitializerTo(RecTy *Ty) const { - return Ty->convertValue(const_cast(this)); - } - - virtual std::string getAsString() const { return Value ? "1" : "0"; } -}; - -/// BitsInit - { a, b, c } - Represents an initializer for a BitsRecTy value. -/// It contains a vector of bits, whose size is determined by the type. -/// -class BitsInit : public Init, public FoldingSetNode { - std::vector Bits; - - BitsInit(ArrayRef Range) : Bits(Range.begin(), Range.end()) {} - - BitsInit(const BitsInit &Other); // Do not define. - BitsInit &operator=(const BitsInit &Other); // Do not define. - -public: - static BitsInit *get(ArrayRef Range); - - void Profile(FoldingSetNodeID &ID) const; - - unsigned getNumBits() const { return Bits.size(); } - - Init *getBit(unsigned Bit) const { - assert(Bit < Bits.size() && "Bit index out of range!"); - return Bits[Bit]; - } - - virtual Init *convertInitializerTo(RecTy *Ty) const { - return Ty->convertValue(const_cast(this)); - } - virtual Init * - convertInitializerBitRange(const std::vector &Bits) const; - - virtual bool isComplete() const { - for (unsigned i = 0; i != getNumBits(); ++i) - if (!getBit(i)->isComplete()) return false; - return true; - } - bool allInComplete() const { - for (unsigned i = 0; i != getNumBits(); ++i) - if (getBit(i)->isComplete()) return false; - return true; - } - virtual std::string getAsString() const; - - virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; -}; - - -/// IntInit - 7 - Represent an initalization by a literal integer value. -/// -class IntInit : public TypedInit { - int64_t Value; - - explicit IntInit(int64_t V) : TypedInit(IntRecTy::get()), Value(V) {} - - IntInit(const IntInit &Other); // Do not define. - IntInit &operator=(const IntInit &Other); // Do note define. - -public: - static IntInit *get(int64_t V); - - int64_t getValue() const { return Value; } - - virtual Init *convertInitializerTo(RecTy *Ty) const { - return Ty->convertValue(const_cast(this)); - } - virtual Init * - convertInitializerBitRange(const std::vector &Bits) const; - - virtual std::string getAsString() const; - - /// resolveBitReference - This method is used to implement - /// VarBitInit::resolveReferences. If the bit is able to be resolved, we - /// simply return the resolved value, otherwise we return null. - /// - virtual Init *resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit) const { - assert(0 && "Illegal bit reference off int"); - return 0; - } - - /// resolveListElementReference - This method is used to implement - /// VarListElementInit::resolveReferences. If the list element is resolvable - /// now, we return the resolved value, otherwise we return null. - virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const { - assert(0 && "Illegal element reference off int"); - return 0; - } -}; - - -/// StringInit - "foo" - Represent an initialization by a string value. -/// -class StringInit : public TypedInit { - std::string Value; - - explicit StringInit(const std::string &V) - : TypedInit(StringRecTy::get()), Value(V) {} - - StringInit(const StringInit &Other); // Do not define. - StringInit &operator=(const StringInit &Other); // Do not define. - -public: - static StringInit *get(const std::string &V); - - const std::string &getValue() const { return Value; } - - virtual Init *convertInitializerTo(RecTy *Ty) const { - return Ty->convertValue(const_cast(this)); - } - - virtual std::string getAsString() const { return "\"" + Value + "\""; } - virtual std::string getAsUnquotedString() const { return Value; } - - /// resolveBitReference - This method is used to implement - /// VarBitInit::resolveReferences. If the bit is able to be resolved, we - /// simply return the resolved value, otherwise we return null. - /// - virtual Init *resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit) const { - assert(0 && "Illegal bit reference off string"); - return 0; - } - - /// resolveListElementReference - This method is used to implement - /// VarListElementInit::resolveReferences. If the list element is resolvable - /// now, we return the resolved value, otherwise we return null. - virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const { - assert(0 && "Illegal element reference off string"); - return 0; - } -}; - -/// CodeInit - "[{...}]" - Represent a code fragment. -/// -class CodeInit : public Init { - std::string Value; - - explicit CodeInit(const std::string &V) : Value(V) {} - - CodeInit(const CodeInit &Other); // Do not define. - CodeInit &operator=(const CodeInit &Other); // Do not define. - -public: - static CodeInit *get(const std::string &V); - - const std::string &getValue() const { return Value; } - - virtual Init *convertInitializerTo(RecTy *Ty) const { - return Ty->convertValue(const_cast(this)); - } - - virtual std::string getAsString() const { return "[{" + Value + "}]"; } -}; - -/// ListInit - [AL, AH, CL] - Represent a list of defs -/// -class ListInit : public TypedInit, public FoldingSetNode { - std::vector Values; -public: - typedef std::vector::const_iterator const_iterator; - -private: - explicit ListInit(ArrayRef Range, RecTy *EltTy) - : TypedInit(ListRecTy::get(EltTy)), Values(Range.begin(), Range.end()) {} - - ListInit(const ListInit &Other); // Do not define. - ListInit &operator=(const ListInit &Other); // Do not define. - -public: - static ListInit *get(ArrayRef Range, RecTy *EltTy); - - void Profile(FoldingSetNodeID &ID) const; - - unsigned getSize() const { return Values.size(); } - Init *getElement(unsigned i) const { - assert(i < Values.size() && "List element index out of range!"); - return Values[i]; - } - - Record *getElementAsRecord(unsigned i) const; - - Init *convertInitListSlice(const std::vector &Elements) const; - - virtual Init *convertInitializerTo(RecTy *Ty) const { - return Ty->convertValue(const_cast(this)); - } - - /// resolveReferences - This method is used by classes that refer to other - /// variables which may not be defined at the time they expression is formed. - /// If a value is set for the variable later, this method will be called on - /// users of the value to allow the value to propagate out. - /// - virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; - - virtual std::string getAsString() const; - - ArrayRef getValues() const { return Values; } - - inline const_iterator begin() const { return Values.begin(); } - inline const_iterator end () const { return Values.end(); } - - inline size_t size () const { return Values.size(); } - inline bool empty() const { return Values.empty(); } - - /// resolveBitReference - This method is used to implement - /// VarBitInit::resolveReferences. If the bit is able to be resolved, we - /// simply return the resolved value, otherwise we return null. - /// - virtual Init *resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit) const { - assert(0 && "Illegal bit reference off list"); - return 0; - } - - /// resolveListElementReference - This method is used to implement - /// VarListElementInit::resolveReferences. If the list element is resolvable - /// now, we return the resolved value, otherwise we return null. - virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const; -}; - - -/// OpInit - Base class for operators -/// -class OpInit : public TypedInit { - OpInit(const OpInit &Other); // Do not define. - OpInit &operator=(OpInit &Other); // Do not define. - -protected: - explicit OpInit(RecTy *Type) : TypedInit(Type) {} - -public: - // Clone - Clone this operator, replacing arguments with the new list - virtual OpInit *clone(std::vector &Operands) const = 0; - - virtual int getNumOperands() const = 0; - virtual Init *getOperand(int i) const = 0; - - // Fold - If possible, fold this to a simpler init. Return this if not - // possible to fold. - virtual Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const = 0; - - virtual Init *convertInitializerTo(RecTy *Ty) const { - return Ty->convertValue(const_cast(this)); - } - - virtual Init *resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit) const; - virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const; -}; - - -/// UnOpInit - !op (X) - Transform an init. -/// -class UnOpInit : public OpInit { -public: - enum UnaryOp { CAST, HEAD, TAIL, EMPTY }; -private: - UnaryOp Opc; - Init *LHS; - - UnOpInit(UnaryOp opc, Init *lhs, RecTy *Type) - : OpInit(Type), Opc(opc), LHS(lhs) {} - - UnOpInit(const UnOpInit &Other); // Do not define. - UnOpInit &operator=(const UnOpInit &Other); // Do not define. - -public: - static UnOpInit *get(UnaryOp opc, Init *lhs, RecTy *Type); - - // Clone - Clone this operator, replacing arguments with the new list - virtual OpInit *clone(std::vector &Operands) const { - assert(Operands.size() == 1 && - "Wrong number of operands for unary operation"); - return UnOpInit::get(getOpcode(), *Operands.begin(), getType()); - } - - int getNumOperands() const { return 1; } - Init *getOperand(int i) const { - assert(i == 0 && "Invalid operand id for unary operator"); - return getOperand(); - } - - UnaryOp getOpcode() const { return Opc; } - Init *getOperand() const { return LHS; } - - // Fold - If possible, fold this to a simpler init. Return this if not - // possible to fold. - Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const; - - virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; - - virtual std::string getAsString() const; -}; - -/// BinOpInit - !op (X, Y) - Combine two inits. -/// -class BinOpInit : public OpInit { -public: - enum BinaryOp { SHL, SRA, SRL, STRCONCAT, CONCAT, EQ }; -private: - BinaryOp Opc; - Init *LHS, *RHS; - - BinOpInit(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type) : - OpInit(Type), Opc(opc), LHS(lhs), RHS(rhs) {} - - BinOpInit(const BinOpInit &Other); // Do not define. - BinOpInit &operator=(const BinOpInit &Other); // Do not define. - -public: - static BinOpInit *get(BinaryOp opc, Init *lhs, Init *rhs, - RecTy *Type); - - // Clone - Clone this operator, replacing arguments with the new list - virtual OpInit *clone(std::vector &Operands) const { - assert(Operands.size() == 2 && - "Wrong number of operands for binary operation"); - return BinOpInit::get(getOpcode(), Operands[0], Operands[1], getType()); - } - - int getNumOperands() const { return 2; } - Init *getOperand(int i) const { - assert((i == 0 || i == 1) && "Invalid operand id for binary operator"); - if (i == 0) { - return getLHS(); - } else { - return getRHS(); - } - } - - BinaryOp getOpcode() const { return Opc; } - Init *getLHS() const { return LHS; } - Init *getRHS() const { return RHS; } - - // Fold - If possible, fold this to a simpler init. Return this if not - // possible to fold. - Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const; - - virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; - - virtual std::string getAsString() const; -}; - -/// TernOpInit - !op (X, Y, Z) - Combine two inits. -/// -class TernOpInit : public OpInit { -public: - enum TernaryOp { SUBST, FOREACH, IF }; -private: - TernaryOp Opc; - Init *LHS, *MHS, *RHS; - - TernOpInit(TernaryOp opc, Init *lhs, Init *mhs, Init *rhs, - RecTy *Type) : - OpInit(Type), Opc(opc), LHS(lhs), MHS(mhs), RHS(rhs) {} - - TernOpInit(const TernOpInit &Other); // Do not define. - TernOpInit &operator=(const TernOpInit &Other); // Do not define. - -public: - static TernOpInit *get(TernaryOp opc, Init *lhs, - Init *mhs, Init *rhs, - RecTy *Type); - - // Clone - Clone this operator, replacing arguments with the new list - virtual OpInit *clone(std::vector &Operands) const { - assert(Operands.size() == 3 && - "Wrong number of operands for ternary operation"); - return TernOpInit::get(getOpcode(), Operands[0], Operands[1], Operands[2], - getType()); - } - - int getNumOperands() const { return 3; } - Init *getOperand(int i) const { - assert((i == 0 || i == 1 || i == 2) && - "Invalid operand id for ternary operator"); - if (i == 0) { - return getLHS(); - } else if (i == 1) { - return getMHS(); - } else { - return getRHS(); - } - } - - TernaryOp getOpcode() const { return Opc; } - Init *getLHS() const { return LHS; } - Init *getMHS() const { return MHS; } - Init *getRHS() const { return RHS; } - - // Fold - If possible, fold this to a simpler init. Return this if not - // possible to fold. - Init *Fold(Record *CurRec, MultiClass *CurMultiClass) const; - - virtual bool isComplete() const { return false; } - - virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; - - virtual std::string getAsString() const; -}; - - -/// VarInit - 'Opcode' - Represent a reference to an entire variable object. -/// -class VarInit : public TypedInit { - std::string VarName; - - explicit VarInit(const std::string &VN, RecTy *T) - : TypedInit(T), VarName(VN) {} - - VarInit(const VarInit &Other); // Do not define. - VarInit &operator=(const VarInit &Other); // Do not define. - -public: - static VarInit *get(const std::string &VN, RecTy *T); - static VarInit *get(Init *VN, RecTy *T); - - virtual Init *convertInitializerTo(RecTy *Ty) const { - return Ty->convertValue(const_cast(this)); - } - - const std::string &getName() const { return VarName; } - - virtual Init *resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit) const; - virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const; - - virtual RecTy *getFieldType(const std::string &FieldName) const; - virtual Init *getFieldInit(Record &R, const RecordVal *RV, - const std::string &FieldName) const; - - /// resolveReferences - This method is used by classes that refer to other - /// variables which may not be defined at the time they expression is formed. - /// If a value is set for the variable later, this method will be called on - /// users of the value to allow the value to propagate out. - /// - virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; - - virtual std::string getAsString() const { return VarName; } -}; - - -/// VarBitInit - Opcode{0} - Represent access to one bit of a variable or field. -/// -class VarBitInit : public Init { - TypedInit *TI; - unsigned Bit; - - VarBitInit(TypedInit *T, unsigned B) : TI(T), Bit(B) { - assert(T->getType() && dynamic_cast(T->getType()) && - ((BitsRecTy*)T->getType())->getNumBits() > B && - "Illegal VarBitInit expression!"); - } - - VarBitInit(const VarBitInit &Other); // Do not define. - VarBitInit &operator=(const VarBitInit &Other); // Do not define. - -public: - static VarBitInit *get(TypedInit *T, unsigned B); - - virtual Init *convertInitializerTo(RecTy *Ty) const { - return Ty->convertValue(const_cast(this)); - } - - TypedInit *getVariable() const { return TI; } - unsigned getBitNum() const { return Bit; } - - virtual std::string getAsString() const; - virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; -}; - -/// VarListElementInit - List[4] - Represent access to one element of a var or -/// field. -class VarListElementInit : public TypedInit { - TypedInit *TI; - unsigned Element; - - VarListElementInit(TypedInit *T, unsigned E) - : TypedInit(dynamic_cast(T->getType())->getElementType()), - TI(T), Element(E) { - assert(T->getType() && dynamic_cast(T->getType()) && - "Illegal VarBitInit expression!"); - } - - VarListElementInit(const VarListElementInit &Other); // Do not define. - VarListElementInit &operator=(const VarListElementInit &Other); // Do - // not - // define. - -public: - static VarListElementInit *get(TypedInit *T, unsigned E); - - virtual Init *convertInitializerTo(RecTy *Ty) const { - return Ty->convertValue(const_cast(this)); - } - - TypedInit *getVariable() const { return TI; } - unsigned getElementNum() const { return Element; } - - virtual Init *resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit) const; - - /// resolveListElementReference - This method is used to implement - /// VarListElementInit::resolveReferences. If the list element is resolvable - /// now, we return the resolved value, otherwise we return null. - virtual Init *resolveListElementReference(Record &R, - const RecordVal *RV, - unsigned Elt) const; - - virtual std::string getAsString() const; - virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; -}; - -/// DefInit - AL - Represent a reference to a 'def' in the description -/// -class DefInit : public TypedInit { - Record *Def; - - DefInit(Record *D, RecordRecTy *T) : TypedInit(T), Def(D) {} - friend class Record; - - DefInit(const DefInit &Other); // Do not define. - DefInit &operator=(const DefInit &Other); // Do not define. - -public: - static DefInit *get(Record*); - - virtual Init *convertInitializerTo(RecTy *Ty) const { - return Ty->convertValue(const_cast(this)); - } - - Record *getDef() const { return Def; } - - //virtual Init *convertInitializerBitRange(const std::vector &Bits); - - virtual RecTy *getFieldType(const std::string &FieldName) const; - virtual Init *getFieldInit(Record &R, const RecordVal *RV, - const std::string &FieldName) const; - - virtual std::string getAsString() const; - - /// resolveBitReference - This method is used to implement - /// VarBitInit::resolveReferences. If the bit is able to be resolved, we - /// simply return the resolved value, otherwise we return null. - /// - virtual Init *resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit) const { - assert(0 && "Illegal bit reference off def"); - return 0; - } - - /// resolveListElementReference - This method is used to implement - /// VarListElementInit::resolveReferences. If the list element is resolvable - /// now, we return the resolved value, otherwise we return null. - virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const { - assert(0 && "Illegal element reference off def"); - return 0; - } -}; - - -/// FieldInit - X.Y - Represent a reference to a subfield of a variable -/// -class FieldInit : public TypedInit { - Init *Rec; // Record we are referring to - std::string FieldName; // Field we are accessing - - FieldInit(Init *R, const std::string &FN) - : TypedInit(R->getFieldType(FN)), Rec(R), FieldName(FN) { - assert(getType() && "FieldInit with non-record type!"); - } - - FieldInit(const FieldInit &Other); // Do not define. - FieldInit &operator=(const FieldInit &Other); // Do not define. - -public: - static FieldInit *get(Init *R, const std::string &FN); - static FieldInit *get(Init *R, const Init *FN); - - virtual Init *convertInitializerTo(RecTy *Ty) const { - return Ty->convertValue(const_cast(this)); - } - - virtual Init *resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit) const; - virtual Init *resolveListElementReference(Record &R, - const RecordVal *RV, - unsigned Elt) const; - - virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; - - virtual std::string getAsString() const { - return Rec->getAsString() + "." + FieldName; - } -}; - -/// DagInit - (v a, b) - Represent a DAG tree value. DAG inits are required -/// to have at least one value then a (possibly empty) list of arguments. Each -/// argument can have a name associated with it. -/// -class DagInit : public TypedInit, public FoldingSetNode { - Init *Val; - std::string ValName; - std::vector Args; - std::vector ArgNames; - - DagInit(Init *V, const std::string &VN, - ArrayRef ArgRange, - ArrayRef NameRange) - : TypedInit(DagRecTy::get()), Val(V), ValName(VN), - Args(ArgRange.begin(), ArgRange.end()), - ArgNames(NameRange.begin(), NameRange.end()) {} - - DagInit(const DagInit &Other); // Do not define. - DagInit &operator=(const DagInit &Other); // Do not define. - -public: - static DagInit *get(Init *V, const std::string &VN, - ArrayRef ArgRange, - ArrayRef NameRange); - static DagInit *get(Init *V, const std::string &VN, - const std::vector< - std::pair > &args); - - void Profile(FoldingSetNodeID &ID) const; - - virtual Init *convertInitializerTo(RecTy *Ty) const { - return Ty->convertValue(const_cast(this)); - } - - Init *getOperator() const { return Val; } - - const std::string &getName() const { return ValName; } - - unsigned getNumArgs() const { return Args.size(); } - Init *getArg(unsigned Num) const { - assert(Num < Args.size() && "Arg number out of range!"); - return Args[Num]; - } - const std::string &getArgName(unsigned Num) const { - assert(Num < ArgNames.size() && "Arg number out of range!"); - return ArgNames[Num]; - } - - virtual Init *resolveReferences(Record &R, const RecordVal *RV) const; - - virtual std::string getAsString() const; - - typedef std::vector::const_iterator const_arg_iterator; - typedef std::vector::const_iterator const_name_iterator; - - inline const_arg_iterator arg_begin() const { return Args.begin(); } - inline const_arg_iterator arg_end () const { return Args.end(); } - - inline size_t arg_size () const { return Args.size(); } - inline bool arg_empty() const { return Args.empty(); } - - inline const_name_iterator name_begin() const { return ArgNames.begin(); } - inline const_name_iterator name_end () const { return ArgNames.end(); } - - inline size_t name_size () const { return ArgNames.size(); } - inline bool name_empty() const { return ArgNames.empty(); } - - virtual Init *resolveBitReference(Record &R, const RecordVal *RV, - unsigned Bit) const { - assert(0 && "Illegal bit reference off dag"); - return 0; - } - - virtual Init *resolveListElementReference(Record &R, const RecordVal *RV, - unsigned Elt) const { - assert(0 && "Illegal element reference off dag"); - return 0; - } -}; - -//===----------------------------------------------------------------------===// -// High-Level Classes -//===----------------------------------------------------------------------===// - -class RecordVal { - Init *Name; - RecTy *Ty; - unsigned Prefix; - Init *Value; -public: - RecordVal(Init *N, RecTy *T, unsigned P); - RecordVal(const std::string &N, RecTy *T, unsigned P); - - const std::string &getName() const; - - unsigned getPrefix() const { return Prefix; } - RecTy *getType() const { return Ty; } - Init *getValue() const { return Value; } - - bool setValue(Init *V) { - if (V) { - Value = V->convertInitializerTo(Ty); - return Value == 0; - } - Value = 0; - return false; - } - - void dump() const; - void print(raw_ostream &OS, bool PrintSem = true) const; -}; - -inline raw_ostream &operator<<(raw_ostream &OS, const RecordVal &RV) { - RV.print(OS << " "); - return OS; -} - -class Record { - static unsigned LastID; - - // Unique record ID. - unsigned ID; - Init *Name; - SMLoc Loc; - std::vector TemplateArgs; - std::vector Values; - std::vector SuperClasses; - - // Tracks Record instances. Not owned by Record. - RecordKeeper &TrackedRecords; - - DefInit *TheInit; - - void checkName(); - -public: - - // Constructs a record. - explicit Record(const std::string &N, SMLoc loc, RecordKeeper &records) : - ID(LastID++), Name(StringInit::get(N)), Loc(loc), TrackedRecords(records), TheInit(0) {} - ~Record() {} - - - static unsigned getNewUID() { return LastID++; } - - - unsigned getID() const { return ID; } - - const std::string &getName() const; - void setName(Init *Name); // Also updates RecordKeeper. - void setName(const std::string &Name); // Also updates RecordKeeper. - - SMLoc getLoc() const { return Loc; } - - /// get the corresponding DefInit. - DefInit *getDefInit(); - - const std::vector &getTemplateArgs() const { - return TemplateArgs; - } - const std::vector &getValues() const { return Values; } - const std::vector &getSuperClasses() const { return SuperClasses; } - - bool isTemplateArg(StringRef Name) const { - for (unsigned i = 0, e = TemplateArgs.size(); i != e; ++i) - if (TemplateArgs[i] == Name) return true; - return false; - } - - const RecordVal *getValue(StringRef Name) const { - for (unsigned i = 0, e = Values.size(); i != e; ++i) - if (Values[i].getName() == Name) return &Values[i]; - return 0; - } - RecordVal *getValue(StringRef Name) { - for (unsigned i = 0, e = Values.size(); i != e; ++i) - if (Values[i].getName() == Name) return &Values[i]; - return 0; - } - - void addTemplateArg(StringRef Name) { - assert(!isTemplateArg(Name) && "Template arg already defined!"); - TemplateArgs.push_back(Name); - } - - void addValue(const RecordVal &RV) { - assert(getValue(RV.getName()) == 0 && "Value already added!"); - Values.push_back(RV); - } - - void removeValue(StringRef Name) { - for (unsigned i = 0, e = Values.size(); i != e; ++i) - if (Values[i].getName() == Name) { - Values.erase(Values.begin()+i); - return; - } - assert(0 && "Cannot remove an entry that does not exist!"); - } - - bool isSubClassOf(const Record *R) const { - for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i) - if (SuperClasses[i] == R) - return true; - return false; - } - - bool isSubClassOf(StringRef Name) const { - for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i) - if (SuperClasses[i]->getName() == Name) - return true; - return false; - } - - void addSuperClass(Record *R) { - assert(!isSubClassOf(R) && "Already subclassing record!"); - SuperClasses.push_back(R); - } - - /// resolveReferences - If there are any field references that refer to fields - /// that have been filled in, we can propagate the values now. - /// - void resolveReferences() { resolveReferencesTo(0); } - - /// resolveReferencesTo - If anything in this record refers to RV, replace the - /// reference to RV with the RHS of RV. If RV is null, we resolve all - /// possible references. - void resolveReferencesTo(const RecordVal *RV); - - RecordKeeper &getRecords() const { - return TrackedRecords; - } - - void dump() const; - - //===--------------------------------------------------------------------===// - // High-level methods useful to tablegen back-ends - // - - /// getValueInit - Return the initializer for a value with the specified name, - /// or throw an exception if the field does not exist. - /// - Init *getValueInit(StringRef FieldName) const; - - /// getValueAsString - This method looks up the specified field and returns - /// its value as a string, throwing an exception if the field does not exist - /// or if the value is not a string. - /// - std::string getValueAsString(StringRef FieldName) const; - - /// getValueAsBitsInit - This method looks up the specified field and returns - /// its value as a BitsInit, throwing an exception if the field does not exist - /// or if the value is not the right type. - /// - BitsInit *getValueAsBitsInit(StringRef FieldName) const; - - /// getValueAsListInit - This method looks up the specified field and returns - /// its value as a ListInit, throwing an exception if the field does not exist - /// or if the value is not the right type. - /// - ListInit *getValueAsListInit(StringRef FieldName) const; - - /// getValueAsListOfDefs - This method looks up the specified field and - /// returns its value as a vector of records, throwing an exception if the - /// field does not exist or if the value is not the right type. - /// - std::vector getValueAsListOfDefs(StringRef FieldName) const; - - /// getValueAsListOfInts - This method looks up the specified field and - /// returns its value as a vector of integers, throwing an exception if the - /// field does not exist or if the value is not the right type. - /// - std::vector getValueAsListOfInts(StringRef FieldName) const; - - /// getValueAsListOfStrings - This method looks up the specified field and - /// returns its value as a vector of strings, throwing an exception if the - /// field does not exist or if the value is not the right type. - /// - std::vector getValueAsListOfStrings(StringRef FieldName) const; - - /// getValueAsDef - This method looks up the specified field and returns its - /// value as a Record, throwing an exception if the field does not exist or if - /// the value is not the right type. - /// - Record *getValueAsDef(StringRef FieldName) const; - - /// getValueAsBit - This method looks up the specified field and returns its - /// value as a bit, throwing an exception if the field does not exist or if - /// the value is not the right type. - /// - bool getValueAsBit(StringRef FieldName) const; - - /// getValueAsInt - This method looks up the specified field and returns its - /// value as an int64_t, throwing an exception if the field does not exist or - /// if the value is not the right type. - /// - int64_t getValueAsInt(StringRef FieldName) const; - - /// getValueAsDag - This method looks up the specified field and returns its - /// value as an Dag, throwing an exception if the field does not exist or if - /// the value is not the right type. - /// - DagInit *getValueAsDag(StringRef FieldName) const; - - /// getValueAsCode - This method looks up the specified field and returns - /// its value as the string data in a CodeInit, throwing an exception if the - /// field does not exist or if the value is not a code object. - /// - std::string getValueAsCode(StringRef FieldName) const; -}; - -raw_ostream &operator<<(raw_ostream &OS, const Record &R); - -struct MultiClass { - Record Rec; // Placeholder for template args and Name. - typedef std::vector RecordVector; - RecordVector DefPrototypes; - - void dump() const; - - MultiClass(const std::string &Name, SMLoc Loc, RecordKeeper &Records) : - Rec(Name, Loc, Records) {} -}; - -class RecordKeeper { - std::map Classes, Defs; -public: - ~RecordKeeper() { - for (std::map::iterator I = Classes.begin(), - E = Classes.end(); I != E; ++I) - delete I->second; - for (std::map::iterator I = Defs.begin(), - E = Defs.end(); I != E; ++I) - delete I->second; - } - - const std::map &getClasses() const { return Classes; } - const std::map &getDefs() const { return Defs; } - - Record *getClass(const std::string &Name) const { - std::map::const_iterator I = Classes.find(Name); - return I == Classes.end() ? 0 : I->second; - } - Record *getDef(const std::string &Name) const { - std::map::const_iterator I = Defs.find(Name); - return I == Defs.end() ? 0 : I->second; - } - void addClass(Record *R) { - assert(getClass(R->getName()) == 0 && "Class already exists!"); - Classes.insert(std::make_pair(R->getName(), R)); - } - void addDef(Record *R) { - assert(getDef(R->getName()) == 0 && "Def already exists!"); - Defs.insert(std::make_pair(R->getName(), R)); - } - - /// removeClass - Remove, but do not delete, the specified record. - /// - void removeClass(const std::string &Name) { - assert(Classes.count(Name) && "Class does not exist!"); - Classes.erase(Name); - } - /// removeDef - Remove, but do not delete, the specified record. - /// - void removeDef(const std::string &Name) { - assert(Defs.count(Name) && "Def does not exist!"); - Defs.erase(Name); - } - - //===--------------------------------------------------------------------===// - // High-level helper methods, useful for tablegen backends... - - /// getAllDerivedDefinitions - This method returns all concrete definitions - /// that derive from the specified class name. If a class with the specified - /// name does not exist, an exception is thrown. - std::vector - getAllDerivedDefinitions(const std::string &ClassName) const; - - void dump() const; -}; - -/// LessRecord - Sorting predicate to sort record pointers by name. -/// -struct LessRecord { - bool operator()(const Record *Rec1, const Record *Rec2) const { - return StringRef(Rec1->getName()).compare_numeric(Rec2->getName()) < 0; - } -}; - -/// LessRecordFieldName - Sorting predicate to sort record pointers by their -/// name field. -/// -struct LessRecordFieldName { - bool operator()(const Record *Rec1, const Record *Rec2) const { - return Rec1->getValueAsString("Name") < Rec2->getValueAsString("Name"); - } -}; - -raw_ostream &operator<<(raw_ostream &OS, const RecordKeeper &RK); - -} // End llvm namespace - -#endif diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index e5185020b7c..19b45f86677 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -16,7 +16,7 @@ #include "RegisterInfoEmitter.h" #include "CodeGenTarget.h" #include "CodeGenRegisters.h" -#include "Record.h" +#include "llvm/TableGen/Record.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" diff --git a/utils/TableGen/RegisterInfoEmitter.h b/utils/TableGen/RegisterInfoEmitter.h index 4ad9cfa97f2..0fd4d079ebc 100644 --- a/utils/TableGen/RegisterInfoEmitter.h +++ b/utils/TableGen/RegisterInfoEmitter.h @@ -16,7 +16,7 @@ #ifndef REGISTER_INFO_EMITTER_H #define REGISTER_INFO_EMITTER_H -#include "TableGenBackend.h" +#include "llvm/TableGen/TableGenBackend.h" #include namespace llvm { diff --git a/utils/TableGen/SetTheory.cpp b/utils/TableGen/SetTheory.cpp index 21ac09cb662..bef73f33eff 100644 --- a/utils/TableGen/SetTheory.cpp +++ b/utils/TableGen/SetTheory.cpp @@ -13,8 +13,8 @@ //===----------------------------------------------------------------------===// #include "SetTheory.h" -#include "Error.h" -#include "Record.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" #include "llvm/Support/Format.h" using namespace llvm; diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index 978e91a1d6c..103a4032b02 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -13,7 +13,7 @@ #include "SubtargetEmitter.h" #include "CodeGenTarget.h" -#include "Record.h" +#include "llvm/TableGen/Record.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Debug.h" #include diff --git a/utils/TableGen/SubtargetEmitter.h b/utils/TableGen/SubtargetEmitter.h index b239f3dda76..ff01274bd1a 100644 --- a/utils/TableGen/SubtargetEmitter.h +++ b/utils/TableGen/SubtargetEmitter.h @@ -14,7 +14,7 @@ #ifndef SUBTARGET_EMITTER_H #define SUBTARGET_EMITTER_H -#include "TableGenBackend.h" +#include "llvm/TableGen/TableGenBackend.h" #include "llvm/MC/MCInstrItineraries.h" #include #include diff --git a/utils/TableGen/TGLexer.cpp b/utils/TableGen/TGLexer.cpp deleted file mode 100644 index b4b90ff64eb..00000000000 --- a/utils/TableGen/TGLexer.cpp +++ /dev/null @@ -1,435 +0,0 @@ -//===- TGLexer.cpp - Lexer for TableGen -----------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Implement the Lexer for TableGen. -// -//===----------------------------------------------------------------------===// - -#include "TGLexer.h" -#include "Error.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Config/config.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/Twine.h" -#include -#include -#include -#include -#include -using namespace llvm; - -TGLexer::TGLexer(SourceMgr &SM) : SrcMgr(SM) { - CurBuffer = 0; - CurBuf = SrcMgr.getMemoryBuffer(CurBuffer); - CurPtr = CurBuf->getBufferStart(); - TokStart = 0; -} - -SMLoc TGLexer::getLoc() const { - return SMLoc::getFromPointer(TokStart); -} - -/// ReturnError - Set the error to the specified string at the specified -/// location. This is defined to always return tgtok::Error. -tgtok::TokKind TGLexer::ReturnError(const char *Loc, const Twine &Msg) { - PrintError(Loc, Msg); - return tgtok::Error; -} - -int TGLexer::getNextChar() { - char CurChar = *CurPtr++; - switch (CurChar) { - default: - return (unsigned char)CurChar; - case 0: { - // A nul character in the stream is either the end of the current buffer or - // a random nul in the file. Disambiguate that here. - if (CurPtr-1 != CurBuf->getBufferEnd()) - return 0; // Just whitespace. - - // If this is the end of an included file, pop the parent file off the - // include stack. - SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer); - if (ParentIncludeLoc != SMLoc()) { - CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc); - CurBuf = SrcMgr.getMemoryBuffer(CurBuffer); - CurPtr = ParentIncludeLoc.getPointer(); - return getNextChar(); - } - - // Otherwise, return end of file. - --CurPtr; // Another call to lex will return EOF again. - return EOF; - } - case '\n': - case '\r': - // Handle the newline character by ignoring it and incrementing the line - // count. However, be careful about 'dos style' files with \n\r in them. - // Only treat a \n\r or \r\n as a single line. - if ((*CurPtr == '\n' || (*CurPtr == '\r')) && - *CurPtr != CurChar) - ++CurPtr; // Eat the two char newline sequence. - return '\n'; - } -} - -tgtok::TokKind TGLexer::LexToken() { - TokStart = CurPtr; - // This always consumes at least one character. - int CurChar = getNextChar(); - - switch (CurChar) { - default: - // Handle letters: [a-zA-Z_#] - if (isalpha(CurChar) || CurChar == '_' || CurChar == '#') - return LexIdentifier(); - - // Unknown character, emit an error. - return ReturnError(TokStart, "Unexpected character"); - case EOF: return tgtok::Eof; - case ':': return tgtok::colon; - case ';': return tgtok::semi; - case '.': return tgtok::period; - case ',': return tgtok::comma; - case '<': return tgtok::less; - case '>': return tgtok::greater; - case ']': return tgtok::r_square; - case '{': return tgtok::l_brace; - case '}': return tgtok::r_brace; - case '(': return tgtok::l_paren; - case ')': return tgtok::r_paren; - case '=': return tgtok::equal; - case '?': return tgtok::question; - - case 0: - case ' ': - case '\t': - case '\n': - case '\r': - // Ignore whitespace. - return LexToken(); - case '/': - // If this is the start of a // comment, skip until the end of the line or - // the end of the buffer. - if (*CurPtr == '/') - SkipBCPLComment(); - else if (*CurPtr == '*') { - if (SkipCComment()) - return tgtok::Error; - } else // Otherwise, this is an error. - return ReturnError(TokStart, "Unexpected character"); - return LexToken(); - case '-': case '+': - case '0': case '1': case '2': case '3': case '4': case '5': case '6': - case '7': case '8': case '9': - return LexNumber(); - case '"': return LexString(); - case '$': return LexVarName(); - case '[': return LexBracket(); - case '!': return LexExclaim(); - } -} - -/// LexString - Lex "[^"]*" -tgtok::TokKind TGLexer::LexString() { - const char *StrStart = CurPtr; - - CurStrVal = ""; - - while (*CurPtr != '"') { - // If we hit the end of the buffer, report an error. - if (*CurPtr == 0 && CurPtr == CurBuf->getBufferEnd()) - return ReturnError(StrStart, "End of file in string literal"); - - if (*CurPtr == '\n' || *CurPtr == '\r') - return ReturnError(StrStart, "End of line in string literal"); - - if (*CurPtr != '\\') { - CurStrVal += *CurPtr++; - continue; - } - - ++CurPtr; - - switch (*CurPtr) { - case '\\': case '\'': case '"': - // These turn into their literal character. - CurStrVal += *CurPtr++; - break; - case 't': - CurStrVal += '\t'; - ++CurPtr; - break; - case 'n': - CurStrVal += '\n'; - ++CurPtr; - break; - - case '\n': - case '\r': - return ReturnError(CurPtr, "escaped newlines not supported in tblgen"); - - // If we hit the end of the buffer, report an error. - case '\0': - if (CurPtr == CurBuf->getBufferEnd()) - return ReturnError(StrStart, "End of file in string literal"); - // FALL THROUGH - default: - return ReturnError(CurPtr, "invalid escape in string literal"); - } - } - - ++CurPtr; - return tgtok::StrVal; -} - -tgtok::TokKind TGLexer::LexVarName() { - if (!isalpha(CurPtr[0]) && CurPtr[0] != '_') - return ReturnError(TokStart, "Invalid variable name"); - - // Otherwise, we're ok, consume the rest of the characters. - const char *VarNameStart = CurPtr++; - - while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_') - ++CurPtr; - - CurStrVal.assign(VarNameStart, CurPtr); - return tgtok::VarName; -} - - -tgtok::TokKind TGLexer::LexIdentifier() { - // The first letter is [a-zA-Z_#]. - const char *IdentStart = TokStart; - - // Match the rest of the identifier regex: [0-9a-zA-Z_#]* - while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_' || - *CurPtr == '#') - ++CurPtr; - - - // Check to see if this identifier is a keyword. - unsigned Len = CurPtr-IdentStart; - - if (Len == 3 && !memcmp(IdentStart, "int", 3)) return tgtok::Int; - if (Len == 3 && !memcmp(IdentStart, "bit", 3)) return tgtok::Bit; - if (Len == 4 && !memcmp(IdentStart, "bits", 4)) return tgtok::Bits; - if (Len == 6 && !memcmp(IdentStart, "string", 6)) return tgtok::String; - if (Len == 4 && !memcmp(IdentStart, "list", 4)) return tgtok::List; - if (Len == 4 && !memcmp(IdentStart, "code", 4)) return tgtok::Code; - if (Len == 3 && !memcmp(IdentStart, "dag", 3)) return tgtok::Dag; - - if (Len == 5 && !memcmp(IdentStart, "class", 5)) return tgtok::Class; - if (Len == 3 && !memcmp(IdentStart, "def", 3)) return tgtok::Def; - if (Len == 4 && !memcmp(IdentStart, "defm", 4)) return tgtok::Defm; - if (Len == 10 && !memcmp(IdentStart, "multiclass", 10)) - return tgtok::MultiClass; - if (Len == 5 && !memcmp(IdentStart, "field", 5)) return tgtok::Field; - if (Len == 3 && !memcmp(IdentStart, "let", 3)) return tgtok::Let; - if (Len == 2 && !memcmp(IdentStart, "in", 2)) return tgtok::In; - - if (Len == 7 && !memcmp(IdentStart, "include", 7)) { - if (LexInclude()) return tgtok::Error; - return Lex(); - } - - CurStrVal.assign(IdentStart, CurPtr); - return tgtok::Id; -} - -/// LexInclude - We just read the "include" token. Get the string token that -/// comes next and enter the include. -bool TGLexer::LexInclude() { - // The token after the include must be a string. - tgtok::TokKind Tok = LexToken(); - if (Tok == tgtok::Error) return true; - if (Tok != tgtok::StrVal) { - PrintError(getLoc(), "Expected filename after include"); - return true; - } - - // Get the string. - std::string Filename = CurStrVal; - std::string IncludedFile; - - - CurBuffer = SrcMgr.AddIncludeFile(Filename, SMLoc::getFromPointer(CurPtr), - IncludedFile); - if (CurBuffer == -1) { - PrintError(getLoc(), "Could not find include file '" + Filename + "'"); - return true; - } - - Dependencies.push_back(IncludedFile); - // Save the line number and lex buffer of the includer. - CurBuf = SrcMgr.getMemoryBuffer(CurBuffer); - CurPtr = CurBuf->getBufferStart(); - return false; -} - -void TGLexer::SkipBCPLComment() { - ++CurPtr; // skip the second slash. - while (1) { - switch (*CurPtr) { - case '\n': - case '\r': - return; // Newline is end of comment. - case 0: - // If this is the end of the buffer, end the comment. - if (CurPtr == CurBuf->getBufferEnd()) - return; - break; - } - // Otherwise, skip the character. - ++CurPtr; - } -} - -/// SkipCComment - This skips C-style /**/ comments. The only difference from C -/// is that we allow nesting. -bool TGLexer::SkipCComment() { - ++CurPtr; // skip the star. - unsigned CommentDepth = 1; - - while (1) { - int CurChar = getNextChar(); - switch (CurChar) { - case EOF: - PrintError(TokStart, "Unterminated comment!"); - return true; - case '*': - // End of the comment? - if (CurPtr[0] != '/') break; - - ++CurPtr; // End the */. - if (--CommentDepth == 0) - return false; - break; - case '/': - // Start of a nested comment? - if (CurPtr[0] != '*') break; - ++CurPtr; - ++CommentDepth; - break; - } - } -} - -/// LexNumber - Lex: -/// [-+]?[0-9]+ -/// 0x[0-9a-fA-F]+ -/// 0b[01]+ -tgtok::TokKind TGLexer::LexNumber() { - if (CurPtr[-1] == '0') { - if (CurPtr[0] == 'x') { - ++CurPtr; - const char *NumStart = CurPtr; - while (isxdigit(CurPtr[0])) - ++CurPtr; - - // Requires at least one hex digit. - if (CurPtr == NumStart) - return ReturnError(TokStart, "Invalid hexadecimal number"); - - errno = 0; - CurIntVal = strtoll(NumStart, 0, 16); - if (errno == EINVAL) - return ReturnError(TokStart, "Invalid hexadecimal number"); - if (errno == ERANGE) { - errno = 0; - CurIntVal = (int64_t)strtoull(NumStart, 0, 16); - if (errno == EINVAL) - return ReturnError(TokStart, "Invalid hexadecimal number"); - if (errno == ERANGE) - return ReturnError(TokStart, "Hexadecimal number out of range"); - } - return tgtok::IntVal; - } else if (CurPtr[0] == 'b') { - ++CurPtr; - const char *NumStart = CurPtr; - while (CurPtr[0] == '0' || CurPtr[0] == '1') - ++CurPtr; - - // Requires at least one binary digit. - if (CurPtr == NumStart) - return ReturnError(CurPtr-2, "Invalid binary number"); - CurIntVal = strtoll(NumStart, 0, 2); - return tgtok::IntVal; - } - } - - // Check for a sign without a digit. - if (!isdigit(CurPtr[0])) { - if (CurPtr[-1] == '-') - return tgtok::minus; - else if (CurPtr[-1] == '+') - return tgtok::plus; - } - - while (isdigit(CurPtr[0])) - ++CurPtr; - CurIntVal = strtoll(TokStart, 0, 10); - return tgtok::IntVal; -} - -/// LexBracket - We just read '['. If this is a code block, return it, -/// otherwise return the bracket. Match: '[' and '[{ ( [^}]+ | }[^]] )* }]' -tgtok::TokKind TGLexer::LexBracket() { - if (CurPtr[0] != '{') - return tgtok::l_square; - ++CurPtr; - const char *CodeStart = CurPtr; - while (1) { - int Char = getNextChar(); - if (Char == EOF) break; - - if (Char != '}') continue; - - Char = getNextChar(); - if (Char == EOF) break; - if (Char == ']') { - CurStrVal.assign(CodeStart, CurPtr-2); - return tgtok::CodeFragment; - } - } - - return ReturnError(CodeStart-2, "Unterminated Code Block"); -} - -/// LexExclaim - Lex '!' and '![a-zA-Z]+'. -tgtok::TokKind TGLexer::LexExclaim() { - if (!isalpha(*CurPtr)) - return ReturnError(CurPtr - 1, "Invalid \"!operator\""); - - const char *Start = CurPtr++; - while (isalpha(*CurPtr)) - ++CurPtr; - - // Check to see which operator this is. - tgtok::TokKind Kind = - StringSwitch(StringRef(Start, CurPtr - Start)) - .Case("eq", tgtok::XEq) - .Case("if", tgtok::XIf) - .Case("head", tgtok::XHead) - .Case("tail", tgtok::XTail) - .Case("con", tgtok::XConcat) - .Case("shl", tgtok::XSHL) - .Case("sra", tgtok::XSRA) - .Case("srl", tgtok::XSRL) - .Case("cast", tgtok::XCast) - .Case("empty", tgtok::XEmpty) - .Case("subst", tgtok::XSubst) - .Case("foreach", tgtok::XForEach) - .Case("strconcat", tgtok::XStrConcat) - .Default(tgtok::Error); - - return Kind != tgtok::Error ? Kind : ReturnError(Start-1, "Unknown operator"); -} - diff --git a/utils/TableGen/TGLexer.h b/utils/TableGen/TGLexer.h deleted file mode 100644 index 84d328b12d9..00000000000 --- a/utils/TableGen/TGLexer.h +++ /dev/null @@ -1,125 +0,0 @@ -//===- TGLexer.h - Lexer for TableGen Files ---------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This class represents the Lexer for tablegen files. -// -//===----------------------------------------------------------------------===// - -#ifndef TGLEXER_H -#define TGLEXER_H - -#include "llvm/Support/DataTypes.h" -#include -#include -#include - -namespace llvm { -class MemoryBuffer; -class SourceMgr; -class SMLoc; -class Twine; - -namespace tgtok { - enum TokKind { - // Markers - Eof, Error, - - // Tokens with no info. - minus, plus, // - + - l_square, r_square, // [ ] - l_brace, r_brace, // { } - l_paren, r_paren, // ( ) - less, greater, // < > - colon, semi, // : ; - comma, period, // , . - equal, question, // = ? - - // Keywords. - Bit, Bits, Class, Code, Dag, Def, Defm, Field, In, Int, Let, List, - MultiClass, String, - - // !keywords. - XConcat, XSRA, XSRL, XSHL, XStrConcat, XCast, XSubst, - XForEach, XHead, XTail, XEmpty, XIf, XEq, - - // Integer value. - IntVal, - - // String valued tokens. - Id, StrVal, VarName, CodeFragment - }; -} - -/// TGLexer - TableGen Lexer class. -class TGLexer { - SourceMgr &SrcMgr; - - const char *CurPtr; - const MemoryBuffer *CurBuf; - - // Information about the current token. - const char *TokStart; - tgtok::TokKind CurCode; - std::string CurStrVal; // This is valid for ID, STRVAL, VARNAME, CODEFRAGMENT - int64_t CurIntVal; // This is valid for INTVAL. - - /// CurBuffer - This is the current buffer index we're lexing from as managed - /// by the SourceMgr object. - int CurBuffer; - /// Dependencies - This is the list of all included files. - std::vector Dependencies; - -public: - TGLexer(SourceMgr &SrcMgr); - ~TGLexer() {} - - tgtok::TokKind Lex() { - return CurCode = LexToken(); - } - - const std::vector &getDependencies() const { - return Dependencies; - } - - tgtok::TokKind getCode() const { return CurCode; } - - const std::string &getCurStrVal() const { - assert((CurCode == tgtok::Id || CurCode == tgtok::StrVal || - CurCode == tgtok::VarName || CurCode == tgtok::CodeFragment) && - "This token doesn't have a string value"); - return CurStrVal; - } - int64_t getCurIntVal() const { - assert(CurCode == tgtok::IntVal && "This token isn't an integer"); - return CurIntVal; - } - - SMLoc getLoc() const; - -private: - /// LexToken - Read the next token and return its code. - tgtok::TokKind LexToken(); - - tgtok::TokKind ReturnError(const char *Loc, const Twine &Msg); - - int getNextChar(); - void SkipBCPLComment(); - bool SkipCComment(); - tgtok::TokKind LexIdentifier(); - bool LexInclude(); - tgtok::TokKind LexString(); - tgtok::TokKind LexVarName(); - tgtok::TokKind LexNumber(); - tgtok::TokKind LexBracket(); - tgtok::TokKind LexExclaim(); -}; - -} // end namespace llvm - -#endif diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp deleted file mode 100644 index f734b984e18..00000000000 --- a/utils/TableGen/TGParser.cpp +++ /dev/null @@ -1,2163 +0,0 @@ -//===- TGParser.cpp - Parser for TableGen Files ---------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Implement the Parser for TableGen. -// -//===----------------------------------------------------------------------===// - -#include "TGParser.h" -#include "Record.h" -#include "llvm/ADT/StringExtras.h" -#include -#include -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/CommandLine.h" -using namespace llvm; - -//===----------------------------------------------------------------------===// -// Support Code for the Semantic Actions. -//===----------------------------------------------------------------------===// - -namespace llvm { -struct SubClassReference { - SMLoc RefLoc; - Record *Rec; - std::vector TemplateArgs; - SubClassReference() : Rec(0) {} - - bool isInvalid() const { return Rec == 0; } -}; - -struct SubMultiClassReference { - SMLoc RefLoc; - MultiClass *MC; - std::vector TemplateArgs; - SubMultiClassReference() : MC(0) {} - - bool isInvalid() const { return MC == 0; } - void dump() const; -}; - -void SubMultiClassReference::dump() const { - errs() << "Multiclass:\n"; - - MC->dump(); - - errs() << "Template args:\n"; - for (std::vector::const_iterator i = TemplateArgs.begin(), - iend = TemplateArgs.end(); - i != iend; - ++i) { - (*i)->dump(); - } -} - -} // end namespace llvm - -bool TGParser::AddValue(Record *CurRec, SMLoc Loc, const RecordVal &RV) { - if (CurRec == 0) - CurRec = &CurMultiClass->Rec; - - if (RecordVal *ERV = CurRec->getValue(RV.getName())) { - // The value already exists in the class, treat this as a set. - if (ERV->setValue(RV.getValue())) - return Error(Loc, "New definition of '" + RV.getName() + "' of type '" + - RV.getType()->getAsString() + "' is incompatible with " + - "previous definition of type '" + - ERV->getType()->getAsString() + "'"); - } else { - CurRec->addValue(RV); - } - return false; -} - -/// SetValue - -/// Return true on error, false on success. -bool TGParser::SetValue(Record *CurRec, SMLoc Loc, const std::string &ValName, - const std::vector &BitList, Init *V) { - if (!V) return false; - - if (CurRec == 0) CurRec = &CurMultiClass->Rec; - - RecordVal *RV = CurRec->getValue(ValName); - if (RV == 0) - return Error(Loc, "Value '" + ValName + "' unknown!"); - - // Do not allow assignments like 'X = X'. This will just cause infinite loops - // in the resolution machinery. - if (BitList.empty()) - if (VarInit *VI = dynamic_cast(V)) - if (VI->getName() == ValName) - return false; - - // If we are assigning to a subset of the bits in the value... then we must be - // assigning to a field of BitsRecTy, which must have a BitsInit - // initializer. - // - if (!BitList.empty()) { - BitsInit *CurVal = dynamic_cast(RV->getValue()); - if (CurVal == 0) - return Error(Loc, "Value '" + ValName + "' is not a bits type"); - - // Convert the incoming value to a bits type of the appropriate size... - Init *BI = V->convertInitializerTo(BitsRecTy::get(BitList.size())); - if (BI == 0) { - V->convertInitializerTo(BitsRecTy::get(BitList.size())); - return Error(Loc, "Initializer is not compatible with bit range"); - } - - // We should have a BitsInit type now. - BitsInit *BInit = dynamic_cast(BI); - assert(BInit != 0); - - SmallVector NewBits(CurVal->getNumBits()); - - // Loop over bits, assigning values as appropriate. - for (unsigned i = 0, e = BitList.size(); i != e; ++i) { - unsigned Bit = BitList[i]; - if (NewBits[Bit]) - return Error(Loc, "Cannot set bit #" + utostr(Bit) + " of value '" + - ValName + "' more than once"); - NewBits[Bit] = BInit->getBit(i); - } - - for (unsigned i = 0, e = CurVal->getNumBits(); i != e; ++i) - if (NewBits[i] == 0) - NewBits[i] = CurVal->getBit(i); - - V = BitsInit::get(NewBits); - } - - if (RV->setValue(V)) - return Error(Loc, "Value '" + ValName + "' of type '" + - RV->getType()->getAsString() + - "' is incompatible with initializer '" + V->getAsString() +"'"); - return false; -} - -/// AddSubClass - Add SubClass as a subclass to CurRec, resolving its template -/// args as SubClass's template arguments. -bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) { - Record *SC = SubClass.Rec; - // Add all of the values in the subclass into the current class. - const std::vector &Vals = SC->getValues(); - for (unsigned i = 0, e = Vals.size(); i != e; ++i) - if (AddValue(CurRec, SubClass.RefLoc, Vals[i])) - return true; - - const std::vector &TArgs = SC->getTemplateArgs(); - - // Ensure that an appropriate number of template arguments are specified. - if (TArgs.size() < SubClass.TemplateArgs.size()) - return Error(SubClass.RefLoc, "More template args specified than expected"); - - // Loop over all of the template arguments, setting them to the specified - // value or leaving them as the default if necessary. - for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { - if (i < SubClass.TemplateArgs.size()) { - // If a value is specified for this template arg, set it now. - if (SetValue(CurRec, SubClass.RefLoc, TArgs[i], std::vector(), - SubClass.TemplateArgs[i])) - return true; - - // Resolve it next. - CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i])); - - // Now remove it. - CurRec->removeValue(TArgs[i]); - - } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) { - return Error(SubClass.RefLoc,"Value not specified for template argument #" - + utostr(i) + " (" + TArgs[i] + ") of subclass '" + - SC->getName() + "'!"); - } - } - - // Since everything went well, we can now set the "superclass" list for the - // current record. - const std::vector &SCs = SC->getSuperClasses(); - for (unsigned i = 0, e = SCs.size(); i != e; ++i) { - if (CurRec->isSubClassOf(SCs[i])) - return Error(SubClass.RefLoc, - "Already subclass of '" + SCs[i]->getName() + "'!\n"); - CurRec->addSuperClass(SCs[i]); - } - - if (CurRec->isSubClassOf(SC)) - return Error(SubClass.RefLoc, - "Already subclass of '" + SC->getName() + "'!\n"); - CurRec->addSuperClass(SC); - return false; -} - -/// AddSubMultiClass - Add SubMultiClass as a subclass to -/// CurMC, resolving its template args as SubMultiClass's -/// template arguments. -bool TGParser::AddSubMultiClass(MultiClass *CurMC, - SubMultiClassReference &SubMultiClass) { - MultiClass *SMC = SubMultiClass.MC; - Record *CurRec = &CurMC->Rec; - - const std::vector &MCVals = CurRec->getValues(); - - // Add all of the values in the subclass into the current class. - const std::vector &SMCVals = SMC->Rec.getValues(); - for (unsigned i = 0, e = SMCVals.size(); i != e; ++i) - if (AddValue(CurRec, SubMultiClass.RefLoc, SMCVals[i])) - return true; - - int newDefStart = CurMC->DefPrototypes.size(); - - // Add all of the defs in the subclass into the current multiclass. - for (MultiClass::RecordVector::const_iterator i = SMC->DefPrototypes.begin(), - iend = SMC->DefPrototypes.end(); - i != iend; - ++i) { - // Clone the def and add it to the current multiclass - Record *NewDef = new Record(**i); - - // Add all of the values in the superclass into the current def. - for (unsigned i = 0, e = MCVals.size(); i != e; ++i) - if (AddValue(NewDef, SubMultiClass.RefLoc, MCVals[i])) - return true; - - CurMC->DefPrototypes.push_back(NewDef); - } - - const std::vector &SMCTArgs = SMC->Rec.getTemplateArgs(); - - // Ensure that an appropriate number of template arguments are - // specified. - if (SMCTArgs.size() < SubMultiClass.TemplateArgs.size()) - return Error(SubMultiClass.RefLoc, - "More template args specified than expected"); - - // Loop over all of the template arguments, setting them to the specified - // value or leaving them as the default if necessary. - for (unsigned i = 0, e = SMCTArgs.size(); i != e; ++i) { - if (i < SubMultiClass.TemplateArgs.size()) { - // If a value is specified for this template arg, set it in the - // superclass now. - if (SetValue(CurRec, SubMultiClass.RefLoc, SMCTArgs[i], - std::vector(), - SubMultiClass.TemplateArgs[i])) - return true; - - // Resolve it next. - CurRec->resolveReferencesTo(CurRec->getValue(SMCTArgs[i])); - - // Now remove it. - CurRec->removeValue(SMCTArgs[i]); - - // If a value is specified for this template arg, set it in the - // new defs now. - for (MultiClass::RecordVector::iterator j = - CurMC->DefPrototypes.begin() + newDefStart, - jend = CurMC->DefPrototypes.end(); - j != jend; - ++j) { - Record *Def = *j; - - if (SetValue(Def, SubMultiClass.RefLoc, SMCTArgs[i], - std::vector(), - SubMultiClass.TemplateArgs[i])) - return true; - - // Resolve it next. - Def->resolveReferencesTo(Def->getValue(SMCTArgs[i])); - - // Now remove it - Def->removeValue(SMCTArgs[i]); - } - } else if (!CurRec->getValue(SMCTArgs[i])->getValue()->isComplete()) { - return Error(SubMultiClass.RefLoc, - "Value not specified for template argument #" - + utostr(i) + " (" + SMCTArgs[i] + ") of subclass '" + - SMC->Rec.getName() + "'!"); - } - } - - return false; -} - -//===----------------------------------------------------------------------===// -// Parser Code -//===----------------------------------------------------------------------===// - -/// isObjectStart - Return true if this is a valid first token for an Object. -static bool isObjectStart(tgtok::TokKind K) { - return K == tgtok::Class || K == tgtok::Def || - K == tgtok::Defm || K == tgtok::Let || K == tgtok::MultiClass; -} - -static std::string GetNewAnonymousName() { - static unsigned AnonCounter = 0; - return "anonymous."+utostr(AnonCounter++); -} - -/// ParseObjectName - If an object name is specified, return it. Otherwise, -/// return an anonymous name. -/// ObjectName ::= ID -/// ObjectName ::= /*empty*/ -/// -std::string TGParser::ParseObjectName() { - if (Lex.getCode() != tgtok::Id) - return GetNewAnonymousName(); - - std::string Ret = Lex.getCurStrVal(); - Lex.Lex(); - return Ret; -} - - -/// ParseClassID - Parse and resolve a reference to a class name. This returns -/// null on error. -/// -/// ClassID ::= ID -/// -Record *TGParser::ParseClassID() { - if (Lex.getCode() != tgtok::Id) { - TokError("expected name for ClassID"); - return 0; - } - - Record *Result = Records.getClass(Lex.getCurStrVal()); - if (Result == 0) - TokError("Couldn't find class '" + Lex.getCurStrVal() + "'"); - - Lex.Lex(); - return Result; -} - -/// ParseMultiClassID - Parse and resolve a reference to a multiclass name. -/// This returns null on error. -/// -/// MultiClassID ::= ID -/// -MultiClass *TGParser::ParseMultiClassID() { - if (Lex.getCode() != tgtok::Id) { - TokError("expected name for ClassID"); - return 0; - } - - MultiClass *Result = MultiClasses[Lex.getCurStrVal()]; - if (Result == 0) - TokError("Couldn't find class '" + Lex.getCurStrVal() + "'"); - - Lex.Lex(); - return Result; -} - -Record *TGParser::ParseDefmID() { - if (Lex.getCode() != tgtok::Id) { - TokError("expected multiclass name"); - return 0; - } - - MultiClass *MC = MultiClasses[Lex.getCurStrVal()]; - if (MC == 0) { - TokError("Couldn't find multiclass '" + Lex.getCurStrVal() + "'"); - return 0; - } - - Lex.Lex(); - return &MC->Rec; -} - - -/// ParseSubClassReference - Parse a reference to a subclass or to a templated -/// subclass. This returns a SubClassRefTy with a null Record* on error. -/// -/// SubClassRef ::= ClassID -/// SubClassRef ::= ClassID '<' ValueList '>' -/// -SubClassReference TGParser:: -ParseSubClassReference(Record *CurRec, bool isDefm) { - SubClassReference Result; - Result.RefLoc = Lex.getLoc(); - - if (isDefm) - Result.Rec = ParseDefmID(); - else - Result.Rec = ParseClassID(); - if (Result.Rec == 0) return Result; - - // If there is no template arg list, we're done. - if (Lex.getCode() != tgtok::less) - return Result; - Lex.Lex(); // Eat the '<' - - if (Lex.getCode() == tgtok::greater) { - TokError("subclass reference requires a non-empty list of template values"); - Result.Rec = 0; - return Result; - } - - Result.TemplateArgs = ParseValueList(CurRec, Result.Rec); - if (Result.TemplateArgs.empty()) { - Result.Rec = 0; // Error parsing value list. - return Result; - } - - if (Lex.getCode() != tgtok::greater) { - TokError("expected '>' in template value list"); - Result.Rec = 0; - return Result; - } - Lex.Lex(); - - return Result; -} - -/// ParseSubMultiClassReference - Parse a reference to a subclass or to a -/// templated submulticlass. This returns a SubMultiClassRefTy with a null -/// Record* on error. -/// -/// SubMultiClassRef ::= MultiClassID -/// SubMultiClassRef ::= MultiClassID '<' ValueList '>' -/// -SubMultiClassReference TGParser:: -ParseSubMultiClassReference(MultiClass *CurMC) { - SubMultiClassReference Result; - Result.RefLoc = Lex.getLoc(); - - Result.MC = ParseMultiClassID(); - if (Result.MC == 0) return Result; - - // If there is no template arg list, we're done. - if (Lex.getCode() != tgtok::less) - return Result; - Lex.Lex(); // Eat the '<' - - if (Lex.getCode() == tgtok::greater) { - TokError("subclass reference requires a non-empty list of template values"); - Result.MC = 0; - return Result; - } - - Result.TemplateArgs = ParseValueList(&CurMC->Rec, &Result.MC->Rec); - if (Result.TemplateArgs.empty()) { - Result.MC = 0; // Error parsing value list. - return Result; - } - - if (Lex.getCode() != tgtok::greater) { - TokError("expected '>' in template value list"); - Result.MC = 0; - return Result; - } - Lex.Lex(); - - return Result; -} - -/// ParseRangePiece - Parse a bit/value range. -/// RangePiece ::= INTVAL -/// RangePiece ::= INTVAL '-' INTVAL -/// RangePiece ::= INTVAL INTVAL -bool TGParser::ParseRangePiece(std::vector &Ranges) { - if (Lex.getCode() != tgtok::IntVal) { - TokError("expected integer or bitrange"); - return true; - } - int64_t Start = Lex.getCurIntVal(); - int64_t End; - - if (Start < 0) - return TokError("invalid range, cannot be negative"); - - switch (Lex.Lex()) { // eat first character. - default: - Ranges.push_back(Start); - return false; - case tgtok::minus: - if (Lex.Lex() != tgtok::IntVal) { - TokError("expected integer value as end of range"); - return true; - } - End = Lex.getCurIntVal(); - break; - case tgtok::IntVal: - End = -Lex.getCurIntVal(); - break; - } - if (End < 0) - return TokError("invalid range, cannot be negative"); - Lex.Lex(); - - // Add to the range. - if (Start < End) { - for (; Start <= End; ++Start) - Ranges.push_back(Start); - } else { - for (; Start >= End; --Start) - Ranges.push_back(Start); - } - return false; -} - -/// ParseRangeList - Parse a list of scalars and ranges into scalar values. -/// -/// RangeList ::= RangePiece (',' RangePiece)* -/// -std::vector TGParser::ParseRangeList() { - std::vector Result; - - // Parse the first piece. - if (ParseRangePiece(Result)) - return std::vector(); - while (Lex.getCode() == tgtok::comma) { - Lex.Lex(); // Eat the comma. - - // Parse the next range piece. - if (ParseRangePiece(Result)) - return std::vector(); - } - return Result; -} - -/// ParseOptionalRangeList - Parse either a range list in <>'s or nothing. -/// OptionalRangeList ::= '<' RangeList '>' -/// OptionalRangeList ::= /*empty*/ -bool TGParser::ParseOptionalRangeList(std::vector &Ranges) { - if (Lex.getCode() != tgtok::less) - return false; - - SMLoc StartLoc = Lex.getLoc(); - Lex.Lex(); // eat the '<' - - // Parse the range list. - Ranges = ParseRangeList(); - if (Ranges.empty()) return true; - - if (Lex.getCode() != tgtok::greater) { - TokError("expected '>' at end of range list"); - return Error(StartLoc, "to match this '<'"); - } - Lex.Lex(); // eat the '>'. - return false; -} - -/// ParseOptionalBitList - Parse either a bit list in {}'s or nothing. -/// OptionalBitList ::= '{' RangeList '}' -/// OptionalBitList ::= /*empty*/ -bool TGParser::ParseOptionalBitList(std::vector &Ranges) { - if (Lex.getCode() != tgtok::l_brace) - return false; - - SMLoc StartLoc = Lex.getLoc(); - Lex.Lex(); // eat the '{' - - // Parse the range list. - Ranges = ParseRangeList(); - if (Ranges.empty()) return true; - - if (Lex.getCode() != tgtok::r_brace) { - TokError("expected '}' at end of bit list"); - return Error(StartLoc, "to match this '{'"); - } - Lex.Lex(); // eat the '}'. - return false; -} - - -/// ParseType - Parse and return a tblgen type. This returns null on error. -/// -/// Type ::= STRING // string type -/// Type ::= BIT // bit type -/// Type ::= BITS '<' INTVAL '>' // bits type -/// Type ::= INT // int type -/// Type ::= LIST '<' Type '>' // list type -/// Type ::= CODE // code type -/// Type ::= DAG // dag type -/// Type ::= ClassID // Record Type -/// -RecTy *TGParser::ParseType() { - switch (Lex.getCode()) { - default: TokError("Unknown token when expecting a type"); return 0; - case tgtok::String: Lex.Lex(); return StringRecTy::get(); - case tgtok::Bit: Lex.Lex(); return BitRecTy::get(); - case tgtok::Int: Lex.Lex(); return IntRecTy::get(); - case tgtok::Code: Lex.Lex(); return CodeRecTy::get(); - case tgtok::Dag: Lex.Lex(); return DagRecTy::get(); - case tgtok::Id: - if (Record *R = ParseClassID()) return RecordRecTy::get(R); - return 0; - case tgtok::Bits: { - if (Lex.Lex() != tgtok::less) { // Eat 'bits' - TokError("expected '<' after bits type"); - return 0; - } - if (Lex.Lex() != tgtok::IntVal) { // Eat '<' - TokError("expected integer in bits type"); - return 0; - } - uint64_t Val = Lex.getCurIntVal(); - if (Lex.Lex() != tgtok::greater) { // Eat count. - TokError("expected '>' at end of bits type"); - return 0; - } - Lex.Lex(); // Eat '>' - return BitsRecTy::get(Val); - } - case tgtok::List: { - if (Lex.Lex() != tgtok::less) { // Eat 'bits' - TokError("expected '<' after list type"); - return 0; - } - Lex.Lex(); // Eat '<' - RecTy *SubType = ParseType(); - if (SubType == 0) return 0; - - if (Lex.getCode() != tgtok::greater) { - TokError("expected '>' at end of list type"); - return 0; - } - Lex.Lex(); // Eat '>' - return ListRecTy::get(SubType); - } - } -} - -/// ParseIDValue - Parse an ID as a value and decode what it means. -/// -/// IDValue ::= ID [def local value] -/// IDValue ::= ID [def template arg] -/// IDValue ::= ID [multiclass local value] -/// IDValue ::= ID [multiclass template argument] -/// IDValue ::= ID [def name] -/// -Init *TGParser::ParseIDValue(Record *CurRec) { - assert(Lex.getCode() == tgtok::Id && "Expected ID in ParseIDValue"); - std::string Name = Lex.getCurStrVal(); - SMLoc Loc = Lex.getLoc(); - Lex.Lex(); - return ParseIDValue(CurRec, Name, Loc); -} - -/// ParseIDValue - This is just like ParseIDValue above, but it assumes the ID -/// has already been read. -Init *TGParser::ParseIDValue(Record *CurRec, - const std::string &Name, SMLoc NameLoc) { - if (CurRec) { - if (const RecordVal *RV = CurRec->getValue(Name)) - return VarInit::get(Name, RV->getType()); - - std::string TemplateArgName = CurRec->getName()+":"+Name; - if (CurRec->isTemplateArg(TemplateArgName)) { - const RecordVal *RV = CurRec->getValue(TemplateArgName); - assert(RV && "Template arg doesn't exist??"); - return VarInit::get(TemplateArgName, RV->getType()); - } - } - - if (CurMultiClass) { - std::string MCName = CurMultiClass->Rec.getName()+"::"+Name; - if (CurMultiClass->Rec.isTemplateArg(MCName)) { - const RecordVal *RV = CurMultiClass->Rec.getValue(MCName); - assert(RV && "Template arg doesn't exist??"); - return VarInit::get(MCName, RV->getType()); - } - } - - if (Record *D = Records.getDef(Name)) - return DefInit::get(D); - - Error(NameLoc, "Variable not defined: '" + Name + "'"); - return 0; -} - -/// ParseOperation - Parse an operator. This returns null on error. -/// -/// Operation ::= XOperator ['<' Type '>'] '(' Args ')' -/// -Init *TGParser::ParseOperation(Record *CurRec) { - switch (Lex.getCode()) { - default: - TokError("unknown operation"); - return 0; - break; - case tgtok::XHead: - case tgtok::XTail: - case tgtok::XEmpty: - case tgtok::XCast: { // Value ::= !unop '(' Value ')' - UnOpInit::UnaryOp Code; - RecTy *Type = 0; - - switch (Lex.getCode()) { - default: assert(0 && "Unhandled code!"); - case tgtok::XCast: - Lex.Lex(); // eat the operation - Code = UnOpInit::CAST; - - Type = ParseOperatorType(); - - if (Type == 0) { - TokError("did not get type for unary operator"); - return 0; - } - - break; - case tgtok::XHead: - Lex.Lex(); // eat the operation - Code = UnOpInit::HEAD; - break; - case tgtok::XTail: - Lex.Lex(); // eat the operation - Code = UnOpInit::TAIL; - break; - case tgtok::XEmpty: - Lex.Lex(); // eat the operation - Code = UnOpInit::EMPTY; - Type = IntRecTy::get(); - break; - } - if (Lex.getCode() != tgtok::l_paren) { - TokError("expected '(' after unary operator"); - return 0; - } - Lex.Lex(); // eat the '(' - - Init *LHS = ParseValue(CurRec); - if (LHS == 0) return 0; - - if (Code == UnOpInit::HEAD - || Code == UnOpInit::TAIL - || Code == UnOpInit::EMPTY) { - ListInit *LHSl = dynamic_cast(LHS); - StringInit *LHSs = dynamic_cast(LHS); - TypedInit *LHSt = dynamic_cast(LHS); - if (LHSl == 0 && LHSs == 0 && LHSt == 0) { - TokError("expected list or string type argument in unary operator"); - return 0; - } - if (LHSt) { - ListRecTy *LType = dynamic_cast(LHSt->getType()); - StringRecTy *SType = dynamic_cast(LHSt->getType()); - if (LType == 0 && SType == 0) { - TokError("expected list or string type argumnet in unary operator"); - return 0; - } - } - - if (Code == UnOpInit::HEAD - || Code == UnOpInit::TAIL) { - if (LHSl == 0 && LHSt == 0) { - TokError("expected list type argumnet in unary operator"); - return 0; - } - - if (LHSl && LHSl->getSize() == 0) { - TokError("empty list argument in unary operator"); - return 0; - } - if (LHSl) { - Init *Item = LHSl->getElement(0); - TypedInit *Itemt = dynamic_cast(Item); - if (Itemt == 0) { - TokError("untyped list element in unary operator"); - return 0; - } - if (Code == UnOpInit::HEAD) { - Type = Itemt->getType(); - } else { - Type = ListRecTy::get(Itemt->getType()); - } - } else { - assert(LHSt && "expected list type argument in unary operator"); - ListRecTy *LType = dynamic_cast(LHSt->getType()); - if (LType == 0) { - TokError("expected list type argumnet in unary operator"); - return 0; - } - if (Code == UnOpInit::HEAD) { - Type = LType->getElementType(); - } else { - Type = LType; - } - } - } - } - - if (Lex.getCode() != tgtok::r_paren) { - TokError("expected ')' in unary operator"); - return 0; - } - Lex.Lex(); // eat the ')' - return (UnOpInit::get(Code, LHS, Type))->Fold(CurRec, CurMultiClass); - } - - case tgtok::XConcat: - case tgtok::XSRA: - case tgtok::XSRL: - case tgtok::XSHL: - case tgtok::XEq: - case tgtok::XStrConcat: { // Value ::= !binop '(' Value ',' Value ')' - tgtok::TokKind OpTok = Lex.getCode(); - SMLoc OpLoc = Lex.getLoc(); - Lex.Lex(); // eat the operation - - BinOpInit::BinaryOp Code; - RecTy *Type = 0; - - switch (OpTok) { - default: assert(0 && "Unhandled code!"); - case tgtok::XConcat: Code = BinOpInit::CONCAT;Type = DagRecTy::get(); break; - case tgtok::XSRA: Code = BinOpInit::SRA; Type = IntRecTy::get(); break; - case tgtok::XSRL: Code = BinOpInit::SRL; Type = IntRecTy::get(); break; - case tgtok::XSHL: Code = BinOpInit::SHL; Type = IntRecTy::get(); break; - case tgtok::XEq: Code = BinOpInit::EQ; Type = BitRecTy::get(); break; - case tgtok::XStrConcat: - Code = BinOpInit::STRCONCAT; - Type = StringRecTy::get(); - break; - } - - if (Lex.getCode() != tgtok::l_paren) { - TokError("expected '(' after binary operator"); - return 0; - } - Lex.Lex(); // eat the '(' - - SmallVector InitList; - - InitList.push_back(ParseValue(CurRec)); - if (InitList.back() == 0) return 0; - - while (Lex.getCode() == tgtok::comma) { - Lex.Lex(); // eat the ',' - - InitList.push_back(ParseValue(CurRec)); - if (InitList.back() == 0) return 0; - } - - if (Lex.getCode() != tgtok::r_paren) { - TokError("expected ')' in operator"); - return 0; - } - Lex.Lex(); // eat the ')' - - // We allow multiple operands to associative operators like !strconcat as - // shorthand for nesting them. - if (Code == BinOpInit::STRCONCAT) { - while (InitList.size() > 2) { - Init *RHS = InitList.pop_back_val(); - RHS = (BinOpInit::get(Code, InitList.back(), RHS, Type)) - ->Fold(CurRec, CurMultiClass); - InitList.back() = RHS; - } - } - - if (InitList.size() == 2) - return (BinOpInit::get(Code, InitList[0], InitList[1], Type)) - ->Fold(CurRec, CurMultiClass); - - Error(OpLoc, "expected two operands to operator"); - return 0; - } - - case tgtok::XIf: - case tgtok::XForEach: - case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')' - TernOpInit::TernaryOp Code; - RecTy *Type = 0; - - tgtok::TokKind LexCode = Lex.getCode(); - Lex.Lex(); // eat the operation - switch (LexCode) { - default: assert(0 && "Unhandled code!"); - case tgtok::XIf: - Code = TernOpInit::IF; - break; - case tgtok::XForEach: - Code = TernOpInit::FOREACH; - break; - case tgtok::XSubst: - Code = TernOpInit::SUBST; - break; - } - if (Lex.getCode() != tgtok::l_paren) { - TokError("expected '(' after ternary operator"); - return 0; - } - Lex.Lex(); // eat the '(' - - Init *LHS = ParseValue(CurRec); - if (LHS == 0) return 0; - - if (Lex.getCode() != tgtok::comma) { - TokError("expected ',' in ternary operator"); - return 0; - } - Lex.Lex(); // eat the ',' - - Init *MHS = ParseValue(CurRec); - if (MHS == 0) return 0; - - if (Lex.getCode() != tgtok::comma) { - TokError("expected ',' in ternary operator"); - return 0; - } - Lex.Lex(); // eat the ',' - - Init *RHS = ParseValue(CurRec); - if (RHS == 0) return 0; - - if (Lex.getCode() != tgtok::r_paren) { - TokError("expected ')' in binary operator"); - return 0; - } - Lex.Lex(); // eat the ')' - - switch (LexCode) { - default: assert(0 && "Unhandled code!"); - case tgtok::XIf: { - // FIXME: The `!if' operator doesn't handle non-TypedInit well at - // all. This can be made much more robust. - TypedInit *MHSt = dynamic_cast(MHS); - TypedInit *RHSt = dynamic_cast(RHS); - - RecTy *MHSTy = 0; - RecTy *RHSTy = 0; - - if (MHSt == 0 && RHSt == 0) { - BitsInit *MHSbits = dynamic_cast(MHS); - BitsInit *RHSbits = dynamic_cast(RHS); - - if (MHSbits && RHSbits && - MHSbits->getNumBits() == RHSbits->getNumBits()) { - Type = BitRecTy::get(); - break; - } else { - BitInit *MHSbit = dynamic_cast(MHS); - BitInit *RHSbit = dynamic_cast(RHS); - - if (MHSbit && RHSbit) { - Type = BitRecTy::get(); - break; - } - } - } else if (MHSt != 0 && RHSt != 0) { - MHSTy = MHSt->getType(); - RHSTy = RHSt->getType(); - } - - if (!MHSTy || !RHSTy) { - TokError("could not get type for !if"); - return 0; - } - - if (MHSTy->typeIsConvertibleTo(RHSTy)) { - Type = RHSTy; - } else if (RHSTy->typeIsConvertibleTo(MHSTy)) { - Type = MHSTy; - } else { - TokError("inconsistent types for !if"); - return 0; - } - break; - } - case tgtok::XForEach: { - TypedInit *MHSt = dynamic_cast(MHS); - if (MHSt == 0) { - TokError("could not get type for !foreach"); - return 0; - } - Type = MHSt->getType(); - break; - } - case tgtok::XSubst: { - TypedInit *RHSt = dynamic_cast(RHS); - if (RHSt == 0) { - TokError("could not get type for !subst"); - return 0; - } - Type = RHSt->getType(); - break; - } - } - return (TernOpInit::get(Code, LHS, MHS, RHS, Type))->Fold(CurRec, - CurMultiClass); - } - } - TokError("could not parse operation"); - return 0; -} - -/// ParseOperatorType - Parse a type for an operator. This returns -/// null on error. -/// -/// OperatorType ::= '<' Type '>' -/// -RecTy *TGParser::ParseOperatorType() { - RecTy *Type = 0; - - if (Lex.getCode() != tgtok::less) { - TokError("expected type name for operator"); - return 0; - } - Lex.Lex(); // eat the < - - Type = ParseType(); - - if (Type == 0) { - TokError("expected type name for operator"); - return 0; - } - - if (Lex.getCode() != tgtok::greater) { - TokError("expected type name for operator"); - return 0; - } - Lex.Lex(); // eat the > - - return Type; -} - - -/// ParseSimpleValue - Parse a tblgen value. This returns null on error. -/// -/// SimpleValue ::= IDValue -/// SimpleValue ::= INTVAL -/// SimpleValue ::= STRVAL+ -/// SimpleValue ::= CODEFRAGMENT -/// SimpleValue ::= '?' -/// SimpleValue ::= '{' ValueList '}' -/// SimpleValue ::= ID '<' ValueListNE '>' -/// SimpleValue ::= '[' ValueList ']' -/// SimpleValue ::= '(' IDValue DagArgList ')' -/// SimpleValue ::= CONCATTOK '(' Value ',' Value ')' -/// SimpleValue ::= SHLTOK '(' Value ',' Value ')' -/// SimpleValue ::= SRATOK '(' Value ',' Value ')' -/// SimpleValue ::= SRLTOK '(' Value ',' Value ')' -/// SimpleValue ::= STRCONCATTOK '(' Value ',' Value ')' -/// -Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { - Init *R = 0; - switch (Lex.getCode()) { - default: TokError("Unknown token when parsing a value"); break; - case tgtok::IntVal: R = IntInit::get(Lex.getCurIntVal()); Lex.Lex(); break; - case tgtok::StrVal: { - std::string Val = Lex.getCurStrVal(); - Lex.Lex(); - - // Handle multiple consecutive concatenated strings. - while (Lex.getCode() == tgtok::StrVal) { - Val += Lex.getCurStrVal(); - Lex.Lex(); - } - - R = StringInit::get(Val); - break; - } - case tgtok::CodeFragment: - R = CodeInit::get(Lex.getCurStrVal()); - Lex.Lex(); - break; - case tgtok::question: - R = UnsetInit::get(); - Lex.Lex(); - break; - case tgtok::Id: { - SMLoc NameLoc = Lex.getLoc(); - std::string Name = Lex.getCurStrVal(); - if (Lex.Lex() != tgtok::less) // consume the Id. - return ParseIDValue(CurRec, Name, NameLoc); // Value ::= IDValue - - // Value ::= ID '<' ValueListNE '>' - if (Lex.Lex() == tgtok::greater) { - TokError("expected non-empty value list"); - return 0; - } - - // This is a CLASS expression. This is supposed to synthesize - // a new anonymous definition, deriving from CLASS with no - // body. - Record *Class = Records.getClass(Name); - if (!Class) { - Error(NameLoc, "Expected a class name, got '" + Name + "'"); - return 0; - } - - std::vector ValueList = ParseValueList(CurRec, Class); - if (ValueList.empty()) return 0; - - if (Lex.getCode() != tgtok::greater) { - TokError("expected '>' at end of value list"); - return 0; - } - Lex.Lex(); // eat the '>' - - // Create the new record, set it as CurRec temporarily. - static unsigned AnonCounter = 0; - Record *NewRec = new Record("anonymous.val."+utostr(AnonCounter++), - NameLoc, - Records); - SubClassReference SCRef; - SCRef.RefLoc = NameLoc; - SCRef.Rec = Class; - SCRef.TemplateArgs = ValueList; - // Add info about the subclass to NewRec. - if (AddSubClass(NewRec, SCRef)) - return 0; - NewRec->resolveReferences(); - Records.addDef(NewRec); - - // The result of the expression is a reference to the new record. - return DefInit::get(NewRec); - } - case tgtok::l_brace: { // Value ::= '{' ValueList '}' - SMLoc BraceLoc = Lex.getLoc(); - Lex.Lex(); // eat the '{' - std::vector Vals; - - if (Lex.getCode() != tgtok::r_brace) { - Vals = ParseValueList(CurRec); - if (Vals.empty()) return 0; - } - if (Lex.getCode() != tgtok::r_brace) { - TokError("expected '}' at end of bit list value"); - return 0; - } - Lex.Lex(); // eat the '}' - - SmallVector NewBits(Vals.size()); - - for (unsigned i = 0, e = Vals.size(); i != e; ++i) { - Init *Bit = Vals[i]->convertInitializerTo(BitRecTy::get()); - if (Bit == 0) { - Error(BraceLoc, "Element #" + utostr(i) + " (" + Vals[i]->getAsString()+ - ") is not convertable to a bit"); - return 0; - } - NewBits[Vals.size()-i-1] = Bit; - } - return BitsInit::get(NewBits); - } - case tgtok::l_square: { // Value ::= '[' ValueList ']' - Lex.Lex(); // eat the '[' - std::vector Vals; - - RecTy *DeducedEltTy = 0; - ListRecTy *GivenListTy = 0; - - if (ItemType != 0) { - ListRecTy *ListType = dynamic_cast(ItemType); - if (ListType == 0) { - std::stringstream s; - s << "Type mismatch for list, expected list type, got " - << ItemType->getAsString(); - TokError(s.str()); - return 0; - } - GivenListTy = ListType; - } - - if (Lex.getCode() != tgtok::r_square) { - Vals = ParseValueList(CurRec, 0, - GivenListTy ? GivenListTy->getElementType() : 0); - if (Vals.empty()) return 0; - } - if (Lex.getCode() != tgtok::r_square) { - TokError("expected ']' at end of list value"); - return 0; - } - Lex.Lex(); // eat the ']' - - RecTy *GivenEltTy = 0; - if (Lex.getCode() == tgtok::less) { - // Optional list element type - Lex.Lex(); // eat the '<' - - GivenEltTy = ParseType(); - if (GivenEltTy == 0) { - // Couldn't parse element type - return 0; - } - - if (Lex.getCode() != tgtok::greater) { - TokError("expected '>' at end of list element type"); - return 0; - } - Lex.Lex(); // eat the '>' - } - - // Check elements - RecTy *EltTy = 0; - for (std::vector::iterator i = Vals.begin(), ie = Vals.end(); - i != ie; - ++i) { - TypedInit *TArg = dynamic_cast(*i); - if (TArg == 0) { - TokError("Untyped list element"); - return 0; - } - if (EltTy != 0) { - EltTy = resolveTypes(EltTy, TArg->getType()); - if (EltTy == 0) { - TokError("Incompatible types in list elements"); - return 0; - } - } else { - EltTy = TArg->getType(); - } - } - - if (GivenEltTy != 0) { - if (EltTy != 0) { - // Verify consistency - if (!EltTy->typeIsConvertibleTo(GivenEltTy)) { - TokError("Incompatible types in list elements"); - return 0; - } - } - EltTy = GivenEltTy; - } - - if (EltTy == 0) { - if (ItemType == 0) { - TokError("No type for list"); - return 0; - } - DeducedEltTy = GivenListTy->getElementType(); - } else { - // Make sure the deduced type is compatible with the given type - if (GivenListTy) { - if (!EltTy->typeIsConvertibleTo(GivenListTy->getElementType())) { - TokError("Element type mismatch for list"); - return 0; - } - } - DeducedEltTy = EltTy; - } - - return ListInit::get(Vals, DeducedEltTy); - } - case tgtok::l_paren: { // Value ::= '(' IDValue DagArgList ')' - Lex.Lex(); // eat the '(' - if (Lex.getCode() != tgtok::Id && Lex.getCode() != tgtok::XCast) { - TokError("expected identifier in dag init"); - return 0; - } - - Init *Operator = ParseValue(CurRec); - if (Operator == 0) return 0; - - // If the operator name is present, parse it. - std::string OperatorName; - if (Lex.getCode() == tgtok::colon) { - if (Lex.Lex() != tgtok::VarName) { // eat the ':' - TokError("expected variable name in dag operator"); - return 0; - } - OperatorName = Lex.getCurStrVal(); - Lex.Lex(); // eat the VarName. - } - - std::vector > DagArgs; - if (Lex.getCode() != tgtok::r_paren) { - DagArgs = ParseDagArgList(CurRec); - if (DagArgs.empty()) return 0; - } - - if (Lex.getCode() != tgtok::r_paren) { - TokError("expected ')' in dag init"); - return 0; - } - Lex.Lex(); // eat the ')' - - return DagInit::get(Operator, OperatorName, DagArgs); - } - - case tgtok::XHead: - case tgtok::XTail: - case tgtok::XEmpty: - case tgtok::XCast: // Value ::= !unop '(' Value ')' - case tgtok::XConcat: - case tgtok::XSRA: - case tgtok::XSRL: - case tgtok::XSHL: - case tgtok::XEq: - case tgtok::XStrConcat: // Value ::= !binop '(' Value ',' Value ')' - case tgtok::XIf: - case tgtok::XForEach: - case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')' - return ParseOperation(CurRec); - } - } - - return R; -} - -/// ParseValue - Parse a tblgen value. This returns null on error. -/// -/// Value ::= SimpleValue ValueSuffix* -/// ValueSuffix ::= '{' BitList '}' -/// ValueSuffix ::= '[' BitList ']' -/// ValueSuffix ::= '.' ID -/// -Init *TGParser::ParseValue(Record *CurRec, RecTy *ItemType) { - Init *Result = ParseSimpleValue(CurRec, ItemType); - if (Result == 0) return 0; - - // Parse the suffixes now if present. - while (1) { - switch (Lex.getCode()) { - default: return Result; - case tgtok::l_brace: { - SMLoc CurlyLoc = Lex.getLoc(); - Lex.Lex(); // eat the '{' - std::vector Ranges = ParseRangeList(); - if (Ranges.empty()) return 0; - - // Reverse the bitlist. - std::reverse(Ranges.begin(), Ranges.end()); - Result = Result->convertInitializerBitRange(Ranges); - if (Result == 0) { - Error(CurlyLoc, "Invalid bit range for value"); - return 0; - } - - // Eat the '}'. - if (Lex.getCode() != tgtok::r_brace) { - TokError("expected '}' at end of bit range list"); - return 0; - } - Lex.Lex(); - break; - } - case tgtok::l_square: { - SMLoc SquareLoc = Lex.getLoc(); - Lex.Lex(); // eat the '[' - std::vector Ranges = ParseRangeList(); - if (Ranges.empty()) return 0; - - Result = Result->convertInitListSlice(Ranges); - if (Result == 0) { - Error(SquareLoc, "Invalid range for list slice"); - return 0; - } - - // Eat the ']'. - if (Lex.getCode() != tgtok::r_square) { - TokError("expected ']' at end of list slice"); - return 0; - } - Lex.Lex(); - break; - } - case tgtok::period: - if (Lex.Lex() != tgtok::Id) { // eat the . - TokError("expected field identifier after '.'"); - return 0; - } - if (!Result->getFieldType(Lex.getCurStrVal())) { - TokError("Cannot access field '" + Lex.getCurStrVal() + "' of value '" + - Result->getAsString() + "'"); - return 0; - } - Result = FieldInit::get(Result, Lex.getCurStrVal()); - Lex.Lex(); // eat field name - break; - } - } -} - -/// ParseDagArgList - Parse the argument list for a dag literal expression. -/// -/// ParseDagArgList ::= Value (':' VARNAME)? -/// ParseDagArgList ::= ParseDagArgList ',' Value (':' VARNAME)? -std::vector > -TGParser::ParseDagArgList(Record *CurRec) { - std::vector > Result; - - while (1) { - Init *Val = ParseValue(CurRec); - if (Val == 0) return std::vector >(); - - // If the variable name is present, add it. - std::string VarName; - if (Lex.getCode() == tgtok::colon) { - if (Lex.Lex() != tgtok::VarName) { // eat the ':' - TokError("expected variable name in dag literal"); - return std::vector >(); - } - VarName = Lex.getCurStrVal(); - Lex.Lex(); // eat the VarName. - } - - Result.push_back(std::make_pair(Val, VarName)); - - if (Lex.getCode() != tgtok::comma) break; - Lex.Lex(); // eat the ',' - } - - return Result; -} - - -/// ParseValueList - Parse a comma separated list of values, returning them as a -/// vector. Note that this always expects to be able to parse at least one -/// value. It returns an empty list if this is not possible. -/// -/// ValueList ::= Value (',' Value) -/// -std::vector TGParser::ParseValueList(Record *CurRec, Record *ArgsRec, - RecTy *EltTy) { - std::vector Result; - RecTy *ItemType = EltTy; - unsigned int ArgN = 0; - if (ArgsRec != 0 && EltTy == 0) { - const std::vector &TArgs = ArgsRec->getTemplateArgs(); - const RecordVal *RV = ArgsRec->getValue(TArgs[ArgN]); - if (!RV) { - errs() << "Cannot find template arg " << ArgN << " (" << TArgs[ArgN] - << ")\n"; - } - assert(RV && "Template argument record not found??"); - ItemType = RV->getType(); - ++ArgN; - } - Result.push_back(ParseValue(CurRec, ItemType)); - if (Result.back() == 0) return std::vector(); - - while (Lex.getCode() == tgtok::comma) { - Lex.Lex(); // Eat the comma - - if (ArgsRec != 0 && EltTy == 0) { - const std::vector &TArgs = ArgsRec->getTemplateArgs(); - if (ArgN >= TArgs.size()) { - TokError("too many template arguments"); - return std::vector(); - } - const RecordVal *RV = ArgsRec->getValue(TArgs[ArgN]); - assert(RV && "Template argument record not found??"); - ItemType = RV->getType(); - ++ArgN; - } - Result.push_back(ParseValue(CurRec, ItemType)); - if (Result.back() == 0) return std::vector(); - } - - return Result; -} - - -/// ParseDeclaration - Read a declaration, returning the name of field ID, or an -/// empty string on error. This can happen in a number of different context's, -/// including within a def or in the template args for a def (which which case -/// CurRec will be non-null) and within the template args for a multiclass (in -/// which case CurRec will be null, but CurMultiClass will be set). This can -/// also happen within a def that is within a multiclass, which will set both -/// CurRec and CurMultiClass. -/// -/// Declaration ::= FIELD? Type ID ('=' Value)? -/// -std::string TGParser::ParseDeclaration(Record *CurRec, - bool ParsingTemplateArgs) { - // Read the field prefix if present. - bool HasField = Lex.getCode() == tgtok::Field; - if (HasField) Lex.Lex(); - - RecTy *Type = ParseType(); - if (Type == 0) return ""; - - if (Lex.getCode() != tgtok::Id) { - TokError("Expected identifier in declaration"); - return ""; - } - - SMLoc IdLoc = Lex.getLoc(); - std::string DeclName = Lex.getCurStrVal(); - Lex.Lex(); - - if (ParsingTemplateArgs) { - if (CurRec) { - DeclName = CurRec->getName() + ":" + DeclName; - } else { - assert(CurMultiClass); - } - if (CurMultiClass) - DeclName = CurMultiClass->Rec.getName() + "::" + DeclName; - } - - // Add the value. - if (AddValue(CurRec, IdLoc, RecordVal(DeclName, Type, HasField))) - return ""; - - // If a value is present, parse it. - if (Lex.getCode() == tgtok::equal) { - Lex.Lex(); - SMLoc ValLoc = Lex.getLoc(); - Init *Val = ParseValue(CurRec, Type); - if (Val == 0 || - SetValue(CurRec, ValLoc, DeclName, std::vector(), Val)) - return ""; - } - - return DeclName; -} - -/// ParseTemplateArgList - Read a template argument list, which is a non-empty -/// sequence of template-declarations in <>'s. If CurRec is non-null, these are -/// template args for a def, which may or may not be in a multiclass. If null, -/// these are the template args for a multiclass. -/// -/// TemplateArgList ::= '<' Declaration (',' Declaration)* '>' -/// -bool TGParser::ParseTemplateArgList(Record *CurRec) { - assert(Lex.getCode() == tgtok::less && "Not a template arg list!"); - Lex.Lex(); // eat the '<' - - Record *TheRecToAddTo = CurRec ? CurRec : &CurMultiClass->Rec; - - // Read the first declaration. - std::string TemplArg = ParseDeclaration(CurRec, true/*templateargs*/); - if (TemplArg.empty()) - return true; - - TheRecToAddTo->addTemplateArg(TemplArg); - - while (Lex.getCode() == tgtok::comma) { - Lex.Lex(); // eat the ',' - - // Read the following declarations. - TemplArg = ParseDeclaration(CurRec, true/*templateargs*/); - if (TemplArg.empty()) - return true; - TheRecToAddTo->addTemplateArg(TemplArg); - } - - if (Lex.getCode() != tgtok::greater) - return TokError("expected '>' at end of template argument list"); - Lex.Lex(); // eat the '>'. - return false; -} - - -/// ParseBodyItem - Parse a single item at within the body of a def or class. -/// -/// BodyItem ::= Declaration ';' -/// BodyItem ::= LET ID OptionalBitList '=' Value ';' -bool TGParser::ParseBodyItem(Record *CurRec) { - if (Lex.getCode() != tgtok::Let) { - if (ParseDeclaration(CurRec, false).empty()) - return true; - - if (Lex.getCode() != tgtok::semi) - return TokError("expected ';' after declaration"); - Lex.Lex(); - return false; - } - - // LET ID OptionalRangeList '=' Value ';' - if (Lex.Lex() != tgtok::Id) - return TokError("expected field identifier after let"); - - SMLoc IdLoc = Lex.getLoc(); - std::string FieldName = Lex.getCurStrVal(); - Lex.Lex(); // eat the field name. - - std::vector BitList; - if (ParseOptionalBitList(BitList)) - return true; - std::reverse(BitList.begin(), BitList.end()); - - if (Lex.getCode() != tgtok::equal) - return TokError("expected '=' in let expression"); - Lex.Lex(); // eat the '='. - - RecordVal *Field = CurRec->getValue(FieldName); - if (Field == 0) - return TokError("Value '" + FieldName + "' unknown!"); - - RecTy *Type = Field->getType(); - - Init *Val = ParseValue(CurRec, Type); - if (Val == 0) return true; - - if (Lex.getCode() != tgtok::semi) - return TokError("expected ';' after let expression"); - Lex.Lex(); - - return SetValue(CurRec, IdLoc, FieldName, BitList, Val); -} - -/// ParseBody - Read the body of a class or def. Return true on error, false on -/// success. -/// -/// Body ::= ';' -/// Body ::= '{' BodyList '}' -/// BodyList BodyItem* -/// -bool TGParser::ParseBody(Record *CurRec) { - // If this is a null definition, just eat the semi and return. - if (Lex.getCode() == tgtok::semi) { - Lex.Lex(); - return false; - } - - if (Lex.getCode() != tgtok::l_brace) - return TokError("Expected ';' or '{' to start body"); - // Eat the '{'. - Lex.Lex(); - - while (Lex.getCode() != tgtok::r_brace) - if (ParseBodyItem(CurRec)) - return true; - - // Eat the '}'. - Lex.Lex(); - return false; -} - -/// ParseObjectBody - Parse the body of a def or class. This consists of an -/// optional ClassList followed by a Body. CurRec is the current def or class -/// that is being parsed. -/// -/// ObjectBody ::= BaseClassList Body -/// BaseClassList ::= /*empty*/ -/// BaseClassList ::= ':' BaseClassListNE -/// BaseClassListNE ::= SubClassRef (',' SubClassRef)* -/// -bool TGParser::ParseObjectBody(Record *CurRec) { - // If there is a baseclass list, read it. - if (Lex.getCode() == tgtok::colon) { - Lex.Lex(); - - // Read all of the subclasses. - SubClassReference SubClass = ParseSubClassReference(CurRec, false); - while (1) { - // Check for error. - if (SubClass.Rec == 0) return true; - - // Add it. - if (AddSubClass(CurRec, SubClass)) - return true; - - if (Lex.getCode() != tgtok::comma) break; - Lex.Lex(); // eat ','. - SubClass = ParseSubClassReference(CurRec, false); - } - } - - // Process any variables on the let stack. - for (unsigned i = 0, e = LetStack.size(); i != e; ++i) - for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j) - if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name, - LetStack[i][j].Bits, LetStack[i][j].Value)) - return true; - - return ParseBody(CurRec); -} - -/// ParseDef - Parse and return a top level or multiclass def, return the record -/// corresponding to it. This returns null on error. -/// -/// DefInst ::= DEF ObjectName ObjectBody -/// -bool TGParser::ParseDef(MultiClass *CurMultiClass) { - SMLoc DefLoc = Lex.getLoc(); - assert(Lex.getCode() == tgtok::Def && "Unknown tok"); - Lex.Lex(); // Eat the 'def' token. - - // Parse ObjectName and make a record for it. - Record *CurRec = new Record(ParseObjectName(), DefLoc, Records); - - if (!CurMultiClass) { - // Top-level def definition. - - // Ensure redefinition doesn't happen. - if (Records.getDef(CurRec->getName())) { - Error(DefLoc, "def '" + CurRec->getName() + "' already defined"); - return true; - } - Records.addDef(CurRec); - } else { - // Otherwise, a def inside a multiclass, add it to the multiclass. - for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size(); i != e; ++i) - if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) { - Error(DefLoc, "def '" + CurRec->getName() + - "' already defined in this multiclass!"); - return true; - } - CurMultiClass->DefPrototypes.push_back(CurRec); - } - - if (ParseObjectBody(CurRec)) - return true; - - if (CurMultiClass == 0) // Def's in multiclasses aren't really defs. - // See Record::setName(). This resolve step will see any new name - // for the def that might have been created when resolving - // inheritance, values and arguments above. - CurRec->resolveReferences(); - - // If ObjectBody has template arguments, it's an error. - assert(CurRec->getTemplateArgs().empty() && "How'd this get template args?"); - - if (CurMultiClass) { - // Copy the template arguments for the multiclass into the def. - const std::vector &TArgs = - CurMultiClass->Rec.getTemplateArgs(); - - for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { - const RecordVal *RV = CurMultiClass->Rec.getValue(TArgs[i]); - assert(RV && "Template arg doesn't exist?"); - CurRec->addValue(*RV); - } - } - - return false; -} - - -/// ParseClass - Parse a tblgen class definition. -/// -/// ClassInst ::= CLASS ID TemplateArgList? ObjectBody -/// -bool TGParser::ParseClass() { - assert(Lex.getCode() == tgtok::Class && "Unexpected token!"); - Lex.Lex(); - - if (Lex.getCode() != tgtok::Id) - return TokError("expected class name after 'class' keyword"); - - Record *CurRec = Records.getClass(Lex.getCurStrVal()); - if (CurRec) { - // If the body was previously defined, this is an error. - if (!CurRec->getValues().empty() || - !CurRec->getSuperClasses().empty() || - !CurRec->getTemplateArgs().empty()) - return TokError("Class '" + CurRec->getName() + "' already defined"); - } else { - // If this is the first reference to this class, create and add it. - CurRec = new Record(Lex.getCurStrVal(), Lex.getLoc(), Records); - Records.addClass(CurRec); - } - Lex.Lex(); // eat the name. - - // If there are template args, parse them. - if (Lex.getCode() == tgtok::less) - if (ParseTemplateArgList(CurRec)) - return true; - - // Finally, parse the object body. - return ParseObjectBody(CurRec); -} - -/// ParseLetList - Parse a non-empty list of assignment expressions into a list -/// of LetRecords. -/// -/// LetList ::= LetItem (',' LetItem)* -/// LetItem ::= ID OptionalRangeList '=' Value -/// -std::vector TGParser::ParseLetList() { - std::vector Result; - - while (1) { - if (Lex.getCode() != tgtok::Id) { - TokError("expected identifier in let definition"); - return std::vector(); - } - std::string Name = Lex.getCurStrVal(); - SMLoc NameLoc = Lex.getLoc(); - Lex.Lex(); // Eat the identifier. - - // Check for an optional RangeList. - std::vector Bits; - if (ParseOptionalRangeList(Bits)) - return std::vector(); - std::reverse(Bits.begin(), Bits.end()); - - if (Lex.getCode() != tgtok::equal) { - TokError("expected '=' in let expression"); - return std::vector(); - } - Lex.Lex(); // eat the '='. - - Init *Val = ParseValue(0); - if (Val == 0) return std::vector(); - - // Now that we have everything, add the record. - Result.push_back(LetRecord(Name, Bits, Val, NameLoc)); - - if (Lex.getCode() != tgtok::comma) - return Result; - Lex.Lex(); // eat the comma. - } -} - -/// ParseTopLevelLet - Parse a 'let' at top level. This can be a couple of -/// different related productions. This works inside multiclasses too. -/// -/// Object ::= LET LetList IN '{' ObjectList '}' -/// Object ::= LET LetList IN Object -/// -bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) { - assert(Lex.getCode() == tgtok::Let && "Unexpected token"); - Lex.Lex(); - - // Add this entry to the let stack. - std::vector LetInfo = ParseLetList(); - if (LetInfo.empty()) return true; - LetStack.push_back(LetInfo); - - if (Lex.getCode() != tgtok::In) - return TokError("expected 'in' at end of top-level 'let'"); - Lex.Lex(); - - // If this is a scalar let, just handle it now - if (Lex.getCode() != tgtok::l_brace) { - // LET LetList IN Object - if (ParseObject(CurMultiClass)) - return true; - } else { // Object ::= LETCommand '{' ObjectList '}' - SMLoc BraceLoc = Lex.getLoc(); - // Otherwise, this is a group let. - Lex.Lex(); // eat the '{'. - - // Parse the object list. - if (ParseObjectList(CurMultiClass)) - return true; - - if (Lex.getCode() != tgtok::r_brace) { - TokError("expected '}' at end of top level let command"); - return Error(BraceLoc, "to match this '{'"); - } - Lex.Lex(); - } - - // Outside this let scope, this let block is not active. - LetStack.pop_back(); - return false; -} - -/// ParseMultiClass - Parse a multiclass definition. -/// -/// MultiClassInst ::= MULTICLASS ID TemplateArgList? -/// ':' BaseMultiClassList '{' MultiClassDef+ '}' -/// -bool TGParser::ParseMultiClass() { - assert(Lex.getCode() == tgtok::MultiClass && "Unexpected token"); - Lex.Lex(); // Eat the multiclass token. - - if (Lex.getCode() != tgtok::Id) - return TokError("expected identifier after multiclass for name"); - std::string Name = Lex.getCurStrVal(); - - if (MultiClasses.count(Name)) - return TokError("multiclass '" + Name + "' already defined"); - - CurMultiClass = MultiClasses[Name] = new MultiClass(Name, - Lex.getLoc(), Records); - Lex.Lex(); // Eat the identifier. - - // If there are template args, parse them. - if (Lex.getCode() == tgtok::less) - if (ParseTemplateArgList(0)) - return true; - - bool inherits = false; - - // If there are submulticlasses, parse them. - if (Lex.getCode() == tgtok::colon) { - inherits = true; - - Lex.Lex(); - - // Read all of the submulticlasses. - SubMultiClassReference SubMultiClass = - ParseSubMultiClassReference(CurMultiClass); - while (1) { - // Check for error. - if (SubMultiClass.MC == 0) return true; - - // Add it. - if (AddSubMultiClass(CurMultiClass, SubMultiClass)) - return true; - - if (Lex.getCode() != tgtok::comma) break; - Lex.Lex(); // eat ','. - SubMultiClass = ParseSubMultiClassReference(CurMultiClass); - } - } - - if (Lex.getCode() != tgtok::l_brace) { - if (!inherits) - return TokError("expected '{' in multiclass definition"); - else if (Lex.getCode() != tgtok::semi) - return TokError("expected ';' in multiclass definition"); - else - Lex.Lex(); // eat the ';'. - } else { - if (Lex.Lex() == tgtok::r_brace) // eat the '{'. - return TokError("multiclass must contain at least one def"); - - while (Lex.getCode() != tgtok::r_brace) { - switch (Lex.getCode()) { - default: - return TokError("expected 'let', 'def' or 'defm' in multiclass body"); - case tgtok::Let: - case tgtok::Def: - case tgtok::Defm: - if (ParseObject(CurMultiClass)) - return true; - break; - } - } - Lex.Lex(); // eat the '}'. - } - - CurMultiClass = 0; - return false; -} - -/// ParseDefm - Parse the instantiation of a multiclass. -/// -/// DefMInst ::= DEFM ID ':' DefmSubClassRef ';' -/// -bool TGParser::ParseDefm(MultiClass *CurMultiClass) { - assert(Lex.getCode() == tgtok::Defm && "Unexpected token!"); - - std::string DefmPrefix; - if (Lex.Lex() == tgtok::Id) { // eat the defm. - DefmPrefix = Lex.getCurStrVal(); - Lex.Lex(); // Eat the defm prefix. - } - - SMLoc DefmPrefixLoc = Lex.getLoc(); - if (Lex.getCode() != tgtok::colon) - return TokError("expected ':' after defm identifier"); - - // Keep track of the new generated record definitions. - std::vector NewRecDefs; - - // This record also inherits from a regular class (non-multiclass)? - bool InheritFromClass = false; - - // eat the colon. - Lex.Lex(); - - SMLoc SubClassLoc = Lex.getLoc(); - SubClassReference Ref = ParseSubClassReference(0, true); - - while (1) { - if (Ref.Rec == 0) return true; - - // To instantiate a multiclass, we need to first get the multiclass, then - // instantiate each def contained in the multiclass with the SubClassRef - // template parameters. - MultiClass *MC = MultiClasses[Ref.Rec->getName()]; - assert(MC && "Didn't lookup multiclass correctly?"); - std::vector &TemplateVals = Ref.TemplateArgs; - - // Verify that the correct number of template arguments were specified. - const std::vector &TArgs = MC->Rec.getTemplateArgs(); - if (TArgs.size() < TemplateVals.size()) - return Error(SubClassLoc, - "more template args specified than multiclass expects"); - - // Loop over all the def's in the multiclass, instantiating each one. - for (unsigned i = 0, e = MC->DefPrototypes.size(); i != e; ++i) { - Record *DefProto = MC->DefPrototypes[i]; - - // Add in the defm name. If the defm prefix is empty, give each - // instantiated def a unique name. Otherwise, if "#NAME#" exists in the - // name, substitute the prefix for #NAME#. Otherwise, use the defm name - // as a prefix. - std::string DefName = DefProto->getName(); - if (DefmPrefix.empty()) { - DefName = GetNewAnonymousName(); - } else { - std::string::size_type idx = DefName.find("#NAME#"); - if (idx != std::string::npos) { - DefName.replace(idx, 6, DefmPrefix); - } else { - // Add the suffix to the defm name to get the new name. - DefName = DefmPrefix + DefName; - } - } - - Record *CurRec = new Record(DefName, DefmPrefixLoc, Records); - - SubClassReference Ref; - Ref.RefLoc = DefmPrefixLoc; - Ref.Rec = DefProto; - AddSubClass(CurRec, Ref); - - // Loop over all of the template arguments, setting them to the specified - // value or leaving them as the default if necessary. - for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { - // Check if a value is specified for this temp-arg. - if (i < TemplateVals.size()) { - // Set it now. - if (SetValue(CurRec, DefmPrefixLoc, TArgs[i], std::vector(), - TemplateVals[i])) - return true; - - // Resolve it next. - CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i])); - - // Now remove it. - CurRec->removeValue(TArgs[i]); - - } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) { - return Error(SubClassLoc, - "value not specified for template argument #"+ - utostr(i) + " (" + TArgs[i] + ") of multiclassclass '" + - MC->Rec.getName() + "'"); - } - } - - // If the mdef is inside a 'let' expression, add to each def. - for (unsigned i = 0, e = LetStack.size(); i != e; ++i) - for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j) - if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name, - LetStack[i][j].Bits, LetStack[i][j].Value)) { - Error(DefmPrefixLoc, "when instantiating this defm"); - return true; - } - - // Ensure redefinition doesn't happen. - if (Records.getDef(CurRec->getName())) - return Error(DefmPrefixLoc, "def '" + CurRec->getName() + - "' already defined, instantiating defm with subdef '" + - DefProto->getName() + "'"); - - // Don't create a top level definition for defm inside multiclasses, - // instead, only update the prototypes and bind the template args - // with the new created definition. - if (CurMultiClass) { - for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size(); - i != e; ++i) { - if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) { - Error(DefmPrefixLoc, "defm '" + CurRec->getName() + - "' already defined in this multiclass!"); - return 0; - } - } - CurMultiClass->DefPrototypes.push_back(CurRec); - - // Copy the template arguments for the multiclass into the new def. - const std::vector &TA = - CurMultiClass->Rec.getTemplateArgs(); - - for (unsigned i = 0, e = TA.size(); i != e; ++i) { - const RecordVal *RV = CurMultiClass->Rec.getValue(TA[i]); - assert(RV && "Template arg doesn't exist?"); - CurRec->addValue(*RV); - } - } else { - Records.addDef(CurRec); - } - - NewRecDefs.push_back(CurRec); - } - - if (Lex.getCode() != tgtok::comma) break; - Lex.Lex(); // eat ','. - - SubClassLoc = Lex.getLoc(); - - // A defm can inherit from regular classes (non-multiclass) as - // long as they come in the end of the inheritance list. - InheritFromClass = (Records.getClass(Lex.getCurStrVal()) != 0); - - if (InheritFromClass) - break; - - Ref = ParseSubClassReference(0, true); - } - - if (InheritFromClass) { - // Process all the classes to inherit as if they were part of a - // regular 'def' and inherit all record values. - SubClassReference SubClass = ParseSubClassReference(0, false); - while (1) { - // Check for error. - if (SubClass.Rec == 0) return true; - - // Get the expanded definition prototypes and teach them about - // the record values the current class to inherit has - for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i) { - Record *CurRec = NewRecDefs[i]; - - // Add it. - if (AddSubClass(CurRec, SubClass)) - return true; - - // Process any variables on the let stack. - for (unsigned i = 0, e = LetStack.size(); i != e; ++i) - for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j) - if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name, - LetStack[i][j].Bits, LetStack[i][j].Value)) - return true; - } - - if (Lex.getCode() != tgtok::comma) break; - Lex.Lex(); // eat ','. - SubClass = ParseSubClassReference(0, false); - } - } - - if (!CurMultiClass) - for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i) - // See Record::setName(). This resolve step will see any new - // name for the def that might have been created when resolving - // inheritance, values and arguments above. - NewRecDefs[i]->resolveReferences(); - - if (Lex.getCode() != tgtok::semi) - return TokError("expected ';' at end of defm"); - Lex.Lex(); - - return false; -} - -/// ParseObject -/// Object ::= ClassInst -/// Object ::= DefInst -/// Object ::= MultiClassInst -/// Object ::= DefMInst -/// Object ::= LETCommand '{' ObjectList '}' -/// Object ::= LETCommand Object -bool TGParser::ParseObject(MultiClass *MC) { - switch (Lex.getCode()) { - default: - return TokError("Expected class, def, defm, multiclass or let definition"); - case tgtok::Let: return ParseTopLevelLet(MC); - case tgtok::Def: return ParseDef(MC); - case tgtok::Defm: return ParseDefm(MC); - case tgtok::Class: return ParseClass(); - case tgtok::MultiClass: return ParseMultiClass(); - } -} - -/// ParseObjectList -/// ObjectList :== Object* -bool TGParser::ParseObjectList(MultiClass *MC) { - while (isObjectStart(Lex.getCode())) { - if (ParseObject(MC)) - return true; - } - return false; -} - -bool TGParser::ParseFile() { - Lex.Lex(); // Prime the lexer. - if (ParseObjectList()) return true; - - // If we have unread input at the end of the file, report it. - if (Lex.getCode() == tgtok::Eof) - return false; - - return TokError("Unexpected input at top level"); -} - diff --git a/utils/TableGen/TGParser.h b/utils/TableGen/TGParser.h deleted file mode 100644 index 8b56b8a3290..00000000000 --- a/utils/TableGen/TGParser.h +++ /dev/null @@ -1,122 +0,0 @@ -//===- TGParser.h - Parser for TableGen Files -------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This class represents the Parser for tablegen files. -// -//===----------------------------------------------------------------------===// - -#ifndef TGPARSER_H -#define TGPARSER_H - -#include "TGLexer.h" -#include "Error.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Support/SourceMgr.h" -#include - -namespace llvm { - class Record; - class RecordVal; - class RecordKeeper; - class RecTy; - class Init; - struct MultiClass; - struct SubClassReference; - struct SubMultiClassReference; - - struct LetRecord { - std::string Name; - std::vector Bits; - Init *Value; - SMLoc Loc; - LetRecord(const std::string &N, const std::vector &B, Init *V, - SMLoc L) - : Name(N), Bits(B), Value(V), Loc(L) { - } - }; - -class TGParser { - TGLexer Lex; - std::vector > LetStack; - std::map MultiClasses; - - /// CurMultiClass - If we are parsing a 'multiclass' definition, this is the - /// current value. - MultiClass *CurMultiClass; - - // Record tracker - RecordKeeper &Records; -public: - TGParser(SourceMgr &SrcMgr, RecordKeeper &records) : - Lex(SrcMgr), CurMultiClass(0), Records(records) {} - - /// ParseFile - Main entrypoint for parsing a tblgen file. These parser - /// routines return true on error, or false on success. - bool ParseFile(); - - bool Error(SMLoc L, const Twine &Msg) const { - PrintError(L, Msg); - return true; - } - bool TokError(const Twine &Msg) const { - return Error(Lex.getLoc(), Msg); - } - const std::vector &getDependencies() const { - return Lex.getDependencies(); - } -private: // Semantic analysis methods. - bool AddValue(Record *TheRec, SMLoc Loc, const RecordVal &RV); - bool SetValue(Record *TheRec, SMLoc Loc, const std::string &ValName, - const std::vector &BitList, Init *V); - bool AddSubClass(Record *Rec, SubClassReference &SubClass); - bool AddSubMultiClass(MultiClass *CurMC, - SubMultiClassReference &SubMultiClass); - -private: // Parser methods. - bool ParseObjectList(MultiClass *MC = 0); - bool ParseObject(MultiClass *MC); - bool ParseClass(); - bool ParseMultiClass(); - bool ParseDefm(MultiClass *CurMultiClass); - bool ParseDef(MultiClass *CurMultiClass); - bool ParseTopLevelLet(MultiClass *CurMultiClass); - std::vector ParseLetList(); - - bool ParseObjectBody(Record *CurRec); - bool ParseBody(Record *CurRec); - bool ParseBodyItem(Record *CurRec); - - bool ParseTemplateArgList(Record *CurRec); - std::string ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs); - - SubClassReference ParseSubClassReference(Record *CurRec, bool isDefm); - SubMultiClassReference ParseSubMultiClassReference(MultiClass *CurMC); - - Init *ParseIDValue(Record *CurRec); - Init *ParseIDValue(Record *CurRec, const std::string &Name, SMLoc NameLoc); - Init *ParseSimpleValue(Record *CurRec, RecTy *ItemType = 0); - Init *ParseValue(Record *CurRec, RecTy *ItemType = 0); - std::vector ParseValueList(Record *CurRec, Record *ArgsRec = 0, RecTy *EltTy = 0); - std::vector > ParseDagArgList(Record *); - bool ParseOptionalRangeList(std::vector &Ranges); - bool ParseOptionalBitList(std::vector &Ranges); - std::vector ParseRangeList(); - bool ParseRangePiece(std::vector &Ranges); - RecTy *ParseType(); - Init *ParseOperation(Record *CurRec); - RecTy *ParseOperatorType(); - std::string ParseObjectName(); - Record *ParseClassID(); - MultiClass *ParseMultiClassID(); - Record *ParseDefmID(); -}; - -} // end namespace llvm - -#endif diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index f0607112007..a1cb4272deb 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -1,4 +1,4 @@ -//===- TableGen.cpp - Top-Level TableGen implementation -------------------===// +//===- TableGen.cpp - Top-Level TableGen implementation for LLVM ----------===// // // The LLVM Compiler Infrastructure // @@ -7,11 +7,7 @@ // //===----------------------------------------------------------------------===// // -// TableGen is a tool which can be used to build up a description of something, -// then invoke one or more "tablegen backends" to emit information about the -// description in some predefined format. In practice, this is used by the LLVM -// code generators to automate generation of a code generator through a -// high-level description of the target. +// This file contains the main function for LLVM's TableGen. // //===----------------------------------------------------------------------===// @@ -26,28 +22,25 @@ #include "DAGISelEmitter.h" #include "DisassemblerEmitter.h" #include "EDEmitter.h" -#include "Error.h" #include "FastISelEmitter.h" #include "InstrInfoEmitter.h" #include "IntrinsicEmitter.h" #include "NeonEmitter.h" #include "OptParserEmitter.h" #include "PseudoLoweringEmitter.h" -#include "Record.h" #include "RegisterInfoEmitter.h" #include "ARMDecoderEmitter.h" #include "SubtargetEmitter.h" #include "SetTheory.h" -#include "TGParser.h" -#include "llvm/ADT/OwningPtr.h" + #include "llvm/Support/CommandLine.h" -#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/Signals.h" -#include "llvm/Support/system_error.h" -#include -#include +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Main.h" +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/TableGenAction.h" + using namespace llvm; enum ActionType { @@ -172,197 +165,125 @@ namespace { Class("class", cl::desc("Print Enum list for this class"), cl::value_desc("class name")); - cl::opt - OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"), - cl::init("-")); - - cl::opt - DependFilename("d", cl::desc("Dependency filename"), cl::value_desc("filename"), - cl::init("")); - - cl::opt - InputFilename(cl::Positional, cl::desc(""), cl::init("-")); - - cl::list - IncludeDirs("I", cl::desc("Directory of include files"), - cl::value_desc("directory"), cl::Prefix); - cl::opt ClangComponent("clang-component", cl::desc("Only use warnings from specified component"), cl::value_desc("component"), cl::Hidden); } - -int main(int argc, char **argv) { - RecordKeeper Records; - - sys::PrintStackTraceOnErrorSignal(); - PrettyStackTraceProgram X(argc, argv); - cl::ParseCommandLineOptions(argc, argv); - - - try { - // Parse the input file. - OwningPtr File; - if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), File)) { - errs() << "Could not open input file '" << InputFilename << "': " - << ec.message() <<"\n"; - return 1; - } - MemoryBuffer *F = File.take(); - - // Tell SrcMgr about this buffer, which is what TGParser will pick up. - SrcMgr.AddNewSourceBuffer(F, SMLoc()); - - // Record the location of the include directory so that the lexer can find - // it later. - SrcMgr.setIncludeDirs(IncludeDirs); - - TGParser Parser(SrcMgr, Records); - - if (Parser.ParseFile()) - return 1; - - std::string Error; - tool_output_file Out(OutputFilename.c_str(), Error); - if (!Error.empty()) { - errs() << argv[0] << ": error opening " << OutputFilename - << ":" << Error << "\n"; - return 1; - } - if (!DependFilename.empty()) { - if (OutputFilename == "-") { - errs() << argv[0] << ": the option -d must be used together with -o\n"; - return 1; - } - tool_output_file DepOut(DependFilename.c_str(), Error); - if (!Error.empty()) { - errs() << argv[0] << ": error opening " << DependFilename - << ":" << Error << "\n"; - return 1; - } - DepOut.os() << OutputFilename << ":"; - const std::vector &Dependencies = Parser.getDependencies(); - for (std::vector::const_iterator I = Dependencies.begin(), - E = Dependencies.end(); - I != E; ++I) { - DepOut.os() << " " << (*I); - } - DepOut.os() << "\n"; - DepOut.keep(); - } - +class LLVMTableGenAction : public TableGenAction { +public: + bool operator()(raw_ostream &OS, RecordKeeper &Records) { switch (Action) { case PrintRecords: - Out.os() << Records; // No argument, dump all contents + OS << Records; // No argument, dump all contents break; case GenEmitter: - CodeEmitterGen(Records).run(Out.os()); + CodeEmitterGen(Records).run(OS); break; case GenRegisterInfo: - RegisterInfoEmitter(Records).run(Out.os()); + RegisterInfoEmitter(Records).run(OS); break; case GenInstrInfo: - InstrInfoEmitter(Records).run(Out.os()); + InstrInfoEmitter(Records).run(OS); break; case GenCallingConv: - CallingConvEmitter(Records).run(Out.os()); + CallingConvEmitter(Records).run(OS); break; case GenAsmWriter: - AsmWriterEmitter(Records).run(Out.os()); + AsmWriterEmitter(Records).run(OS); break; case GenARMDecoder: - ARMDecoderEmitter(Records).run(Out.os()); + ARMDecoderEmitter(Records).run(OS); break; case GenAsmMatcher: - AsmMatcherEmitter(Records).run(Out.os()); + AsmMatcherEmitter(Records).run(OS); break; case GenClangAttrClasses: - ClangAttrClassEmitter(Records).run(Out.os()); + ClangAttrClassEmitter(Records).run(OS); break; case GenClangAttrImpl: - ClangAttrImplEmitter(Records).run(Out.os()); + ClangAttrImplEmitter(Records).run(OS); break; case GenClangAttrList: - ClangAttrListEmitter(Records).run(Out.os()); + ClangAttrListEmitter(Records).run(OS); break; case GenClangAttrPCHRead: - ClangAttrPCHReadEmitter(Records).run(Out.os()); + ClangAttrPCHReadEmitter(Records).run(OS); break; case GenClangAttrPCHWrite: - ClangAttrPCHWriteEmitter(Records).run(Out.os()); + ClangAttrPCHWriteEmitter(Records).run(OS); break; case GenClangAttrSpellingList: - ClangAttrSpellingListEmitter(Records).run(Out.os()); + ClangAttrSpellingListEmitter(Records).run(OS); break; case GenClangAttrLateParsedList: - ClangAttrLateParsedListEmitter(Records).run(Out.os()); + ClangAttrLateParsedListEmitter(Records).run(OS); break; case GenClangDiagsDefs: - ClangDiagsDefsEmitter(Records, ClangComponent).run(Out.os()); + ClangDiagsDefsEmitter(Records, ClangComponent).run(OS); break; case GenClangDiagGroups: - ClangDiagGroupsEmitter(Records).run(Out.os()); + ClangDiagGroupsEmitter(Records).run(OS); break; case GenClangDiagsIndexName: - ClangDiagsIndexNameEmitter(Records).run(Out.os()); + ClangDiagsIndexNameEmitter(Records).run(OS); break; case GenClangDeclNodes: - ClangASTNodesEmitter(Records, "Decl", "Decl").run(Out.os()); - ClangDeclContextEmitter(Records).run(Out.os()); + ClangASTNodesEmitter(Records, "Decl", "Decl").run(OS); + ClangDeclContextEmitter(Records).run(OS); break; case GenClangStmtNodes: - ClangASTNodesEmitter(Records, "Stmt", "").run(Out.os()); + ClangASTNodesEmitter(Records, "Stmt", "").run(OS); break; case GenClangSACheckers: - ClangSACheckersEmitter(Records).run(Out.os()); + ClangSACheckersEmitter(Records).run(OS); break; case GenDisassembler: - DisassemblerEmitter(Records).run(Out.os()); + DisassemblerEmitter(Records).run(OS); break; case GenPseudoLowering: - PseudoLoweringEmitter(Records).run(Out.os()); + PseudoLoweringEmitter(Records).run(OS); break; case GenOptParserDefs: - OptParserEmitter(Records, true).run(Out.os()); + OptParserEmitter(Records, true).run(OS); break; case GenOptParserImpl: - OptParserEmitter(Records, false).run(Out.os()); + OptParserEmitter(Records, false).run(OS); break; case GenDAGISel: - DAGISelEmitter(Records).run(Out.os()); + DAGISelEmitter(Records).run(OS); break; case GenFastISel: - FastISelEmitter(Records).run(Out.os()); + FastISelEmitter(Records).run(OS); break; case GenSubtarget: - SubtargetEmitter(Records).run(Out.os()); + SubtargetEmitter(Records).run(OS); break; case GenIntrinsic: - IntrinsicEmitter(Records).run(Out.os()); + IntrinsicEmitter(Records).run(OS); break; case GenTgtIntrinsic: - IntrinsicEmitter(Records, true).run(Out.os()); + IntrinsicEmitter(Records, true).run(OS); break; case GenEDInfo: - EDEmitter(Records).run(Out.os()); + EDEmitter(Records).run(OS); break; case GenArmNeon: - NeonEmitter(Records).run(Out.os()); + NeonEmitter(Records).run(OS); break; case GenArmNeonSema: - NeonEmitter(Records).runHeader(Out.os()); + NeonEmitter(Records).runHeader(OS); break; case GenArmNeonTest: - NeonEmitter(Records).runTests(Out.os()); + NeonEmitter(Records).runTests(OS); break; case PrintEnums: { std::vector Recs = Records.getAllDerivedDefinitions(Class); for (unsigned i = 0, e = Recs.size(); i != e; ++i) - Out.os() << Recs[i]->getName() << ", "; - Out.os() << "\n"; + OS << Recs[i]->getName() << ", "; + OS << "\n"; break; } case PrintSets: @@ -371,33 +292,29 @@ int main(int argc, char **argv) { Sets.addFieldExpander("Set", "Elements"); std::vector Recs = Records.getAllDerivedDefinitions("Set"); for (unsigned i = 0, e = Recs.size(); i != e; ++i) { - Out.os() << Recs[i]->getName() << " = ["; + OS << Recs[i]->getName() << " = ["; const std::vector *Elts = Sets.expand(Recs[i]); assert(Elts && "Couldn't expand Set instance"); for (unsigned ei = 0, ee = Elts->size(); ei != ee; ++ei) - Out.os() << ' ' << (*Elts)[ei]->getName(); - Out.os() << " ]\n"; + OS << ' ' << (*Elts)[ei]->getName(); + OS << " ]\n"; } break; } default: assert(1 && "Invalid Action"); - return 1; + return true; } - // Declare success. - Out.keep(); - return 0; - - } catch (const TGError &Error) { - PrintError(Error); - } catch (const std::string &Error) { - PrintError(Error); - } catch (const char *Error) { - PrintError(Error); - } catch (...) { - errs() << argv[0] << ": Unknown unexpected exception occurred.\n"; + return false; } +}; + +int main(int argc, char **argv) { + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + cl::ParseCommandLineOptions(argc, argv); - return 1; + LLVMTableGenAction Action; + return TableGenMain(argv[0], Action); } diff --git a/utils/TableGen/TableGenBackend.cpp b/utils/TableGen/TableGenBackend.cpp deleted file mode 100644 index b3e33b5f9c2..00000000000 --- a/utils/TableGen/TableGenBackend.cpp +++ /dev/null @@ -1,25 +0,0 @@ -//===- TableGenBackend.cpp - Base class for TableGen Backends ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides useful services for TableGen backends... -// -//===----------------------------------------------------------------------===// - -#include "TableGenBackend.h" -#include "Record.h" -using namespace llvm; - -void TableGenBackend::EmitSourceFileHeader(const std::string &Desc, - raw_ostream &OS) const { - OS << "//===- TableGen'erated file -------------------------------------*-" - " C++ -*-===//\n//\n// " << Desc << "\n//\n// Automatically generate" - "d file, do not edit!\n//\n//===------------------------------------" - "----------------------------------===//\n\n"; -} - diff --git a/utils/TableGen/TableGenBackend.h b/utils/TableGen/TableGenBackend.h deleted file mode 100644 index 9c2b948b0df..00000000000 --- a/utils/TableGen/TableGenBackend.h +++ /dev/null @@ -1,43 +0,0 @@ -//===- TableGenBackend.h - Base class for TableGen Backends -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// The TableGenBackend class is provided as a common interface for all TableGen -// backends. It provides useful services and an standardized interface. -// -//===----------------------------------------------------------------------===// - -#ifndef TABLEGENBACKEND_H -#define TABLEGENBACKEND_H - -#include "llvm/Support/raw_ostream.h" -#include - -namespace llvm { - -class Record; -class RecordKeeper; - -struct TableGenBackend { - virtual ~TableGenBackend() {} - - // run - All TableGen backends should implement the run method, which should - // be the main entry point. - virtual void run(raw_ostream &OS) = 0; - - -public: // Useful helper routines... - /// EmitSourceFileHeader - Output a LLVM style file header to the specified - /// ostream. - void EmitSourceFileHeader(const std::string &Desc, raw_ostream &OS) const; - -}; - -} // End llvm namespace - -#endif diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp index b12660eea21..e7b608306c8 100644 --- a/utils/TableGen/X86DisassemblerTables.cpp +++ b/utils/TableGen/X86DisassemblerTables.cpp @@ -17,7 +17,7 @@ #include "X86DisassemblerShared.h" #include "X86DisassemblerTables.h" -#include "TableGenBackend.h" +#include "llvm/TableGen/TableGenBackend.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" diff --git a/utils/TableGen/X86RecognizableInstr.h b/utils/TableGen/X86RecognizableInstr.h index 390b89e0326..0b600df8725 100644 --- a/utils/TableGen/X86RecognizableInstr.h +++ b/utils/TableGen/X86RecognizableInstr.h @@ -20,8 +20,8 @@ #include "X86DisassemblerTables.h" #include "CodeGenTarget.h" -#include "Record.h" +#include "llvm/TableGen/Record.h" #include "llvm/Support/DataTypes.h" #include "llvm/ADT/SmallVector.h" -- cgit v1.2.3