diff options
Diffstat (limited to 'contrib/llvm/utils')
61 files changed, 28396 insertions, 0 deletions
diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp new file mode 100644 index 0000000..dc92a6c --- /dev/null +++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp @@ -0,0 +1,2535 @@ +//===- AsmMatcherEmitter.cpp - Generate an assembly matcher ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend emits a target specifier matcher for converting parsed +// assembly operands in the MCInst structures. It also emits a matcher for +// custom operand parsing. +// +// Converting assembly operands into MCInst structures +// --------------------------------------------------- +// +// The input to the target specific matcher is a list of literal tokens and +// operands. The target specific parser should generally eliminate any syntax +// which is not relevant for matching; for example, comma tokens should have +// already been consumed and eliminated by the parser. Most instructions will +// end up with a single literal token (the instruction name) and some number of +// operands. +// +// Some example inputs, for X86: +// 'addl' (immediate ...) (register ...) +// 'add' (immediate ...) (memory ...) +// 'call' '*' %epc +// +// The assembly matcher is responsible for converting this input into a precise +// machine instruction (i.e., an instruction with a well defined encoding). This +// mapping has several properties which complicate matching: +// +// - It may be ambiguous; many architectures can legally encode particular +// variants of an instruction in different ways (for example, using a smaller +// encoding for small immediates). Such ambiguities should never be +// arbitrarily resolved by the assembler, the assembler is always responsible +// for choosing the "best" available instruction. +// +// - It may depend on the subtarget or the assembler context. Instructions +// which are invalid for the current mode, but otherwise unambiguous (e.g., +// an SSE instruction in a file being assembled for i486) should be accepted +// and rejected by the assembler front end. However, if the proper encoding +// for an instruction is dependent on the assembler context then the matcher +// is responsible for selecting the correct machine instruction for the +// current mode. +// +// The core matching algorithm attempts to exploit the regularity in most +// instruction sets to quickly determine the set of possibly matching +// instructions, and the simplify the generated code. Additionally, this helps +// to ensure that the ambiguities are intentionally resolved by the user. +// +// The matching is divided into two distinct phases: +// +// 1. Classification: Each operand is mapped to the unique set which (a) +// contains it, and (b) is the largest such subset for which a single +// instruction could match all members. +// +// For register classes, we can generate these subgroups automatically. For +// arbitrary operands, we expect the user to define the classes and their +// relations to one another (for example, 8-bit signed immediates as a +// subset of 32-bit immediates). +// +// By partitioning the operands in this way, we guarantee that for any +// tuple of classes, any single instruction must match either all or none +// of the sets of operands which could classify to that tuple. +// +// In addition, the subset relation amongst classes induces a partial order +// on such tuples, which we use to resolve ambiguities. +// +// 2. The input can now be treated as a tuple of classes (static tokens are +// simple singleton sets). Each such tuple should generally map to a single +// instruction (we currently ignore cases where this isn't true, whee!!!), +// which we can emit a simple matcher for. +// +// Custom Operand Parsing +// ---------------------- +// +// Some targets need a custom way to parse operands, some specific instructions +// can contain arguments that can represent processor flags and other kinds of +// identifiers that need to be mapped to specific valeus in the final encoded +// instructions. The target specific custom operand parsing works in the +// following way: +// +// 1. A operand match table is built, each entry contains a mnemonic, an +// operand class, a mask for all operand positions for that same +// class/mnemonic and target features to be checked while trying to match. +// +// 2. The operand matcher will try every possible entry with the same +// mnemonic and will check if the target feature for this mnemonic also +// matches. After that, if the operand to be matched has its index +// present in the mask, a successful match occurs. Otherwise, fallback +// to the regular operand parsing. +// +// 3. For a match success, each operand class that has a 'ParserMethod' +// becomes part of a switch from where the custom method is called. +// +//===----------------------------------------------------------------------===// + +#include "AsmMatcherEmitter.h" +#include "CodeGenTarget.h" +#include "StringMatcher.h" +#include "StringToOffsetTable.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" +#include <map> +#include <set> +using namespace llvm; + +static cl::opt<std::string> +MatchPrefix("match-prefix", cl::init(""), + cl::desc("Only match instructions with the given prefix")); + +namespace { +class AsmMatcherInfo; +struct SubtargetFeatureInfo; + +/// ClassInfo - Helper class for storing the information about a particular +/// class of operands which can be matched. +struct ClassInfo { + enum ClassInfoKind { + /// Invalid kind, for use as a sentinel value. + Invalid = 0, + + /// The class for a particular token. + Token, + + /// The (first) register class, subsequent register classes are + /// RegisterClass0+1, and so on. + RegisterClass0, + + /// The (first) user defined class, subsequent user defined classes are + /// UserClass0+1, and so on. + UserClass0 = 1<<16 + }; + + /// Kind - The class kind, which is either a predefined kind, or (UserClass0 + + /// N) for the Nth user defined class. + unsigned Kind; + + /// SuperClasses - The super classes of this class. Note that for simplicities + /// sake user operands only record their immediate super class, while register + /// operands include all superclasses. + std::vector<ClassInfo*> SuperClasses; + + /// Name - The full class name, suitable for use in an enum. + std::string Name; + + /// ClassName - The unadorned generic name for this class (e.g., Token). + std::string ClassName; + + /// ValueName - The name of the value this class represents; for a token this + /// is the literal token string, for an operand it is the TableGen class (or + /// empty if this is a derived class). + std::string ValueName; + + /// PredicateMethod - The name of the operand method to test whether the + /// operand matches this class; this is not valid for Token or register kinds. + std::string PredicateMethod; + + /// RenderMethod - The name of the operand method to add this operand to an + /// MCInst; this is not valid for Token or register kinds. + std::string RenderMethod; + + /// ParserMethod - The name of the operand method to do a target specific + /// parsing on the operand. + std::string ParserMethod; + + /// For register classes, the records for all the registers in this class. + std::set<Record*> Registers; + +public: + /// isRegisterClass() - Check if this is a register class. + bool isRegisterClass() const { + return Kind >= RegisterClass0 && Kind < UserClass0; + } + + /// isUserClass() - Check if this is a user defined class. + bool isUserClass() const { + return Kind >= UserClass0; + } + + /// isRelatedTo - Check whether this class is "related" to \arg RHS. Classes + /// are related if they are in the same class hierarchy. + bool isRelatedTo(const ClassInfo &RHS) const { + // Tokens are only related to tokens. + if (Kind == Token || RHS.Kind == Token) + return Kind == Token && RHS.Kind == Token; + + // Registers classes are only related to registers classes, and only if + // their intersection is non-empty. + if (isRegisterClass() || RHS.isRegisterClass()) { + if (!isRegisterClass() || !RHS.isRegisterClass()) + return false; + + std::set<Record*> Tmp; + std::insert_iterator< std::set<Record*> > II(Tmp, Tmp.begin()); + std::set_intersection(Registers.begin(), Registers.end(), + RHS.Registers.begin(), RHS.Registers.end(), + II); + + return !Tmp.empty(); + } + + // Otherwise we have two users operands; they are related if they are in the + // same class hierarchy. + // + // FIXME: This is an oversimplification, they should only be related if they + // intersect, however we don't have that information. + assert(isUserClass() && RHS.isUserClass() && "Unexpected class!"); + const ClassInfo *Root = this; + while (!Root->SuperClasses.empty()) + Root = Root->SuperClasses.front(); + + const ClassInfo *RHSRoot = &RHS; + while (!RHSRoot->SuperClasses.empty()) + RHSRoot = RHSRoot->SuperClasses.front(); + + return Root == RHSRoot; + } + + /// isSubsetOf - Test whether this class is a subset of \arg RHS; + bool isSubsetOf(const ClassInfo &RHS) const { + // This is a subset of RHS if it is the same class... + if (this == &RHS) + return true; + + // ... or if any of its super classes are a subset of RHS. + for (std::vector<ClassInfo*>::const_iterator it = SuperClasses.begin(), + ie = SuperClasses.end(); it != ie; ++it) + if ((*it)->isSubsetOf(RHS)) + return true; + + return false; + } + + /// operator< - Compare two classes. + bool operator<(const ClassInfo &RHS) const { + if (this == &RHS) + return false; + + // Unrelated classes can be ordered by kind. + if (!isRelatedTo(RHS)) + return Kind < RHS.Kind; + + switch (Kind) { + case Invalid: + llvm_unreachable("Invalid kind!"); + + default: + // This class precedes the RHS if it is a proper subset of the RHS. + if (isSubsetOf(RHS)) + return true; + if (RHS.isSubsetOf(*this)) + return false; + + // Otherwise, order by name to ensure we have a total ordering. + return ValueName < RHS.ValueName; + } + } +}; + +/// MatchableInfo - Helper class for storing the necessary information for an +/// instruction or alias which is capable of being matched. +struct MatchableInfo { + struct AsmOperand { + /// Token - This is the token that the operand came from. + StringRef Token; + + /// The unique class instance this operand should match. + ClassInfo *Class; + + /// The operand name this is, if anything. + StringRef SrcOpName; + + /// The suboperand index within SrcOpName, or -1 for the entire operand. + int SubOpIdx; + + /// Register record if this token is singleton register. + Record *SingletonReg; + + explicit AsmOperand(StringRef T) : Token(T), Class(0), SubOpIdx(-1), + SingletonReg(0) {} + }; + + /// ResOperand - This represents a single operand in the result instruction + /// generated by the match. In cases (like addressing modes) where a single + /// assembler operand expands to multiple MCOperands, this represents the + /// single assembler operand, not the MCOperand. + struct ResOperand { + enum { + /// RenderAsmOperand - This represents an operand result that is + /// generated by calling the render method on the assembly operand. The + /// corresponding AsmOperand is specified by AsmOperandNum. + RenderAsmOperand, + + /// TiedOperand - This represents a result operand that is a duplicate of + /// a previous result operand. + TiedOperand, + + /// ImmOperand - This represents an immediate value that is dumped into + /// the operand. + ImmOperand, + + /// RegOperand - This represents a fixed register that is dumped in. + RegOperand + } Kind; + + union { + /// This is the operand # in the AsmOperands list that this should be + /// copied from. + unsigned AsmOperandNum; + + /// TiedOperandNum - This is the (earlier) result operand that should be + /// copied from. + unsigned TiedOperandNum; + + /// ImmVal - This is the immediate value added to the instruction. + int64_t ImmVal; + + /// Register - This is the register record. + Record *Register; + }; + + /// MINumOperands - The number of MCInst operands populated by this + /// operand. + unsigned MINumOperands; + + static ResOperand getRenderedOp(unsigned AsmOpNum, unsigned NumOperands) { + ResOperand X; + X.Kind = RenderAsmOperand; + X.AsmOperandNum = AsmOpNum; + X.MINumOperands = NumOperands; + return X; + } + + static ResOperand getTiedOp(unsigned TiedOperandNum) { + ResOperand X; + X.Kind = TiedOperand; + X.TiedOperandNum = TiedOperandNum; + X.MINumOperands = 1; + return X; + } + + static ResOperand getImmOp(int64_t Val) { + ResOperand X; + X.Kind = ImmOperand; + X.ImmVal = Val; + X.MINumOperands = 1; + return X; + } + + static ResOperand getRegOp(Record *Reg) { + ResOperand X; + X.Kind = RegOperand; + X.Register = Reg; + X.MINumOperands = 1; + return X; + } + }; + + /// AsmVariantID - Target's assembly syntax variant no. + int AsmVariantID; + + /// TheDef - This is the definition of the instruction or InstAlias that this + /// matchable came from. + Record *const TheDef; + + /// DefRec - This is the definition that it came from. + PointerUnion<const CodeGenInstruction*, const CodeGenInstAlias*> DefRec; + + const CodeGenInstruction *getResultInst() const { + if (DefRec.is<const CodeGenInstruction*>()) + return DefRec.get<const CodeGenInstruction*>(); + return DefRec.get<const CodeGenInstAlias*>()->ResultInst; + } + + /// ResOperands - This is the operand list that should be built for the result + /// MCInst. + std::vector<ResOperand> ResOperands; + + /// AsmString - The assembly string for this instruction (with variants + /// removed), e.g. "movsx $src, $dst". + std::string AsmString; + + /// Mnemonic - This is the first token of the matched instruction, its + /// mnemonic. + StringRef Mnemonic; + + /// AsmOperands - The textual operands that this instruction matches, + /// annotated with a class and where in the OperandList they were defined. + /// This directly corresponds to the tokenized AsmString after the mnemonic is + /// removed. + SmallVector<AsmOperand, 4> AsmOperands; + + /// Predicates - The required subtarget features to match this instruction. + SmallVector<SubtargetFeatureInfo*, 4> RequiredFeatures; + + /// ConversionFnKind - The enum value which is passed to the generated + /// ConvertToMCInst to convert parsed operands into an MCInst for this + /// function. + std::string ConversionFnKind; + + MatchableInfo(const CodeGenInstruction &CGI) + : AsmVariantID(0), TheDef(CGI.TheDef), DefRec(&CGI), + AsmString(CGI.AsmString) { + } + + MatchableInfo(const CodeGenInstAlias *Alias) + : AsmVariantID(0), TheDef(Alias->TheDef), DefRec(Alias), + AsmString(Alias->AsmString) { + } + + void Initialize(const AsmMatcherInfo &Info, + SmallPtrSet<Record*, 16> &SingletonRegisters, + int AsmVariantNo, std::string &RegisterPrefix); + + /// Validate - Return true if this matchable is a valid thing to match against + /// and perform a bunch of validity checking. + bool Validate(StringRef CommentDelimiter, bool Hack) const; + + /// extractSingletonRegisterForAsmOperand - Extract singleton register, + /// if present, from specified token. + void + extractSingletonRegisterForAsmOperand(unsigned i, const AsmMatcherInfo &Info, + std::string &RegisterPrefix); + + /// FindAsmOperand - Find the AsmOperand with the specified name and + /// suboperand index. + int FindAsmOperand(StringRef N, int SubOpIdx) const { + for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) + if (N == AsmOperands[i].SrcOpName && + SubOpIdx == AsmOperands[i].SubOpIdx) + return i; + return -1; + } + + /// FindAsmOperandNamed - Find the first AsmOperand with the specified name. + /// This does not check the suboperand index. + int FindAsmOperandNamed(StringRef N) const { + for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) + if (N == AsmOperands[i].SrcOpName) + return i; + return -1; + } + + void BuildInstructionResultOperands(); + void BuildAliasResultOperands(); + + /// operator< - Compare two matchables. + bool operator<(const MatchableInfo &RHS) const { + // The primary comparator is the instruction mnemonic. + if (Mnemonic != RHS.Mnemonic) + return Mnemonic < RHS.Mnemonic; + + if (AsmOperands.size() != RHS.AsmOperands.size()) + return AsmOperands.size() < RHS.AsmOperands.size(); + + // Compare lexicographically by operand. The matcher validates that other + // orderings wouldn't be ambiguous using \see CouldMatchAmbiguouslyWith(). + for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { + if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class) + return true; + if (*RHS.AsmOperands[i].Class < *AsmOperands[i].Class) + return false; + } + + return false; + } + + /// CouldMatchAmbiguouslyWith - Check whether this matchable could + /// ambiguously match the same set of operands as \arg RHS (without being a + /// strictly superior match). + bool CouldMatchAmbiguouslyWith(const MatchableInfo &RHS) { + // The primary comparator is the instruction mnemonic. + if (Mnemonic != RHS.Mnemonic) + return false; + + // The number of operands is unambiguous. + if (AsmOperands.size() != RHS.AsmOperands.size()) + return false; + + // Otherwise, make sure the ordering of the two instructions is unambiguous + // by checking that either (a) a token or operand kind discriminates them, + // or (b) the ordering among equivalent kinds is consistent. + + // Tokens and operand kinds are unambiguous (assuming a correct target + // specific parser). + for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) + if (AsmOperands[i].Class->Kind != RHS.AsmOperands[i].Class->Kind || + AsmOperands[i].Class->Kind == ClassInfo::Token) + if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class || + *RHS.AsmOperands[i].Class < *AsmOperands[i].Class) + return false; + + // Otherwise, this operand could commute if all operands are equivalent, or + // there is a pair of operands that compare less than and a pair that + // compare greater than. + bool HasLT = false, HasGT = false; + for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { + if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class) + HasLT = true; + if (*RHS.AsmOperands[i].Class < *AsmOperands[i].Class) + HasGT = true; + } + + return !(HasLT ^ HasGT); + } + + void dump(); + +private: + void TokenizeAsmString(const AsmMatcherInfo &Info); +}; + +/// SubtargetFeatureInfo - Helper class for storing information on a subtarget +/// feature which participates in instruction matching. +struct SubtargetFeatureInfo { + /// \brief The predicate record for this feature. + Record *TheDef; + + /// \brief An unique index assigned to represent this feature. + unsigned Index; + + SubtargetFeatureInfo(Record *D, unsigned Idx) : TheDef(D), Index(Idx) {} + + /// \brief The name of the enumerated constant identifying this feature. + std::string getEnumName() const { + return "Feature_" + TheDef->getName(); + } +}; + +struct OperandMatchEntry { + unsigned OperandMask; + MatchableInfo* MI; + ClassInfo *CI; + + static OperandMatchEntry Create(MatchableInfo* mi, ClassInfo *ci, + unsigned opMask) { + OperandMatchEntry X; + X.OperandMask = opMask; + X.CI = ci; + X.MI = mi; + return X; + } +}; + + +class AsmMatcherInfo { +public: + /// Tracked Records + RecordKeeper &Records; + + /// The tablegen AsmParser record. + Record *AsmParser; + + /// Target - The target information. + CodeGenTarget &Target; + + /// The classes which are needed for matching. + std::vector<ClassInfo*> Classes; + + /// The information on the matchables to match. + std::vector<MatchableInfo*> Matchables; + + /// Info for custom matching operands by user defined methods. + std::vector<OperandMatchEntry> OperandMatchInfo; + + /// Map of Register records to their class information. + std::map<Record*, ClassInfo*> RegisterClasses; + + /// Map of Predicate records to their subtarget information. + std::map<Record*, SubtargetFeatureInfo*> SubtargetFeatures; + +private: + /// Map of token to class information which has already been constructed. + std::map<std::string, ClassInfo*> TokenClasses; + + /// Map of RegisterClass records to their class information. + std::map<Record*, ClassInfo*> RegisterClassClasses; + + /// Map of AsmOperandClass records to their class information. + std::map<Record*, ClassInfo*> AsmOperandClasses; + +private: + /// getTokenClass - Lookup or create the class for the given token. + ClassInfo *getTokenClass(StringRef Token); + + /// getOperandClass - Lookup or create the class for the given operand. + ClassInfo *getOperandClass(const CGIOperandList::OperandInfo &OI, + int SubOpIdx); + ClassInfo *getOperandClass(Record *Rec, int SubOpIdx); + + /// BuildRegisterClasses - Build the ClassInfo* instances for register + /// classes. + void BuildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters); + + /// BuildOperandClasses - Build the ClassInfo* instances for user defined + /// operand classes. + void BuildOperandClasses(); + + void BuildInstructionOperandReference(MatchableInfo *II, StringRef OpName, + unsigned AsmOpIdx); + void BuildAliasOperandReference(MatchableInfo *II, StringRef OpName, + MatchableInfo::AsmOperand &Op); + +public: + AsmMatcherInfo(Record *AsmParser, + CodeGenTarget &Target, + RecordKeeper &Records); + + /// BuildInfo - Construct the various tables used during matching. + void BuildInfo(); + + /// BuildOperandMatchInfo - Build the necessary information to handle user + /// defined operand parsing methods. + void BuildOperandMatchInfo(); + + /// getSubtargetFeature - Lookup or create the subtarget feature info for the + /// given operand. + SubtargetFeatureInfo *getSubtargetFeature(Record *Def) const { + assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!"); + std::map<Record*, SubtargetFeatureInfo*>::const_iterator I = + SubtargetFeatures.find(Def); + return I == SubtargetFeatures.end() ? 0 : I->second; + } + + RecordKeeper &getRecords() const { + return Records; + } +}; + +} + +void MatchableInfo::dump() { + errs() << TheDef->getName() << " -- " << "flattened:\"" << AsmString <<"\"\n"; + + for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { + AsmOperand &Op = AsmOperands[i]; + errs() << " op[" << i << "] = " << Op.Class->ClassName << " - "; + errs() << '\"' << Op.Token << "\"\n"; + } +} + +void MatchableInfo::Initialize(const AsmMatcherInfo &Info, + SmallPtrSet<Record*, 16> &SingletonRegisters, + int AsmVariantNo, std::string &RegisterPrefix) { + AsmVariantID = AsmVariantNo; + AsmString = + CodeGenInstruction::FlattenAsmStringVariants(AsmString, AsmVariantNo); + + TokenizeAsmString(Info); + + // Compute the require features. + std::vector<Record*> Predicates =TheDef->getValueAsListOfDefs("Predicates"); + for (unsigned i = 0, e = Predicates.size(); i != e; ++i) + if (SubtargetFeatureInfo *Feature = + Info.getSubtargetFeature(Predicates[i])) + RequiredFeatures.push_back(Feature); + + // Collect singleton registers, if used. + for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { + extractSingletonRegisterForAsmOperand(i, Info, RegisterPrefix); + if (Record *Reg = AsmOperands[i].SingletonReg) + SingletonRegisters.insert(Reg); + } +} + +/// TokenizeAsmString - Tokenize a simplified assembly string. +void MatchableInfo::TokenizeAsmString(const AsmMatcherInfo &Info) { + StringRef String = AsmString; + unsigned Prev = 0; + bool InTok = true; + for (unsigned i = 0, e = String.size(); i != e; ++i) { + switch (String[i]) { + case '[': + case ']': + case '*': + case '!': + case ' ': + case '\t': + case ',': + if (InTok) { + AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); + InTok = false; + } + if (!isspace(String[i]) && String[i] != ',') + AsmOperands.push_back(AsmOperand(String.substr(i, 1))); + Prev = i + 1; + break; + + case '\\': + if (InTok) { + AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); + InTok = false; + } + ++i; + assert(i != String.size() && "Invalid quoted character"); + AsmOperands.push_back(AsmOperand(String.substr(i, 1))); + Prev = i + 1; + break; + + case '$': { + if (InTok) { + AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); + InTok = false; + } + + // If this isn't "${", treat like a normal token. + if (i + 1 == String.size() || String[i + 1] != '{') { + Prev = i; + break; + } + + StringRef::iterator End = std::find(String.begin() + i, String.end(),'}'); + assert(End != String.end() && "Missing brace in operand reference!"); + size_t EndPos = End - String.begin(); + AsmOperands.push_back(AsmOperand(String.slice(i, EndPos+1))); + Prev = EndPos + 1; + i = EndPos; + break; + } + + case '.': + if (InTok) + AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); + Prev = i; + InTok = true; + break; + + default: + InTok = true; + } + } + if (InTok && Prev != String.size()) + AsmOperands.push_back(AsmOperand(String.substr(Prev))); + + // The first token of the instruction is the mnemonic, which must be a + // simple string, not a $foo variable or a singleton register. + if (AsmOperands.empty()) + throw TGError(TheDef->getLoc(), + "Instruction '" + TheDef->getName() + "' has no tokens"); + Mnemonic = AsmOperands[0].Token; + // FIXME : Check and raise an error if it is a register. + if (Mnemonic[0] == '$') + throw TGError(TheDef->getLoc(), + "Invalid instruction mnemonic '" + Mnemonic.str() + "'!"); + + // Remove the first operand, it is tracked in the mnemonic field. + AsmOperands.erase(AsmOperands.begin()); +} + +bool MatchableInfo::Validate(StringRef CommentDelimiter, bool Hack) const { + // Reject matchables with no .s string. + if (AsmString.empty()) + throw TGError(TheDef->getLoc(), "instruction with empty asm string"); + + // Reject any matchables with a newline in them, they should be marked + // isCodeGenOnly if they are pseudo instructions. + if (AsmString.find('\n') != std::string::npos) + throw TGError(TheDef->getLoc(), + "multiline instruction is not valid for the asmparser, " + "mark it isCodeGenOnly"); + + // Remove comments from the asm string. We know that the asmstring only + // has one line. + if (!CommentDelimiter.empty() && + StringRef(AsmString).find(CommentDelimiter) != StringRef::npos) + throw TGError(TheDef->getLoc(), + "asmstring for instruction has comment character in it, " + "mark it isCodeGenOnly"); + + // Reject matchables with operand modifiers, these aren't something we can + // handle, the target should be refactored to use operands instead of + // modifiers. + // + // Also, check for instructions which reference the operand multiple times; + // this implies a constraint we would not honor. + std::set<std::string> OperandNames; + for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { + StringRef Tok = AsmOperands[i].Token; + if (Tok[0] == '$' && Tok.find(':') != StringRef::npos) + throw TGError(TheDef->getLoc(), + "matchable with operand modifier '" + Tok.str() + + "' not supported by asm matcher. Mark isCodeGenOnly!"); + + // Verify that any operand is only mentioned once. + // We reject aliases and ignore instructions for now. + if (Tok[0] == '$' && !OperandNames.insert(Tok).second) { + if (!Hack) + throw TGError(TheDef->getLoc(), + "ERROR: matchable with tied operand '" + Tok.str() + + "' can never be matched!"); + // FIXME: Should reject these. The ARM backend hits this with $lane in a + // bunch of instructions. It is unclear what the right answer is. + DEBUG({ + errs() << "warning: '" << TheDef->getName() << "': " + << "ignoring instruction with tied operand '" + << Tok.str() << "'\n"; + }); + return false; + } + } + + return true; +} + +/// extractSingletonRegisterForAsmOperand - Extract singleton register, +/// if present, from specified token. +void MatchableInfo:: +extractSingletonRegisterForAsmOperand(unsigned OperandNo, + const AsmMatcherInfo &Info, + std::string &RegisterPrefix) { + StringRef Tok = AsmOperands[OperandNo].Token; + if (RegisterPrefix.empty()) { + std::string LoweredTok = Tok.lower(); + if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(LoweredTok)) + AsmOperands[OperandNo].SingletonReg = Reg->TheDef; + return; + } + + if (!Tok.startswith(RegisterPrefix)) + return; + + StringRef RegName = Tok.substr(RegisterPrefix.size()); + if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(RegName)) + AsmOperands[OperandNo].SingletonReg = Reg->TheDef; + + // If there is no register prefix (i.e. "%" in "%eax"), then this may + // be some random non-register token, just ignore it. + return; +} + +static std::string getEnumNameForToken(StringRef Str) { + std::string Res; + + for (StringRef::iterator it = Str.begin(), ie = Str.end(); it != ie; ++it) { + switch (*it) { + case '*': Res += "_STAR_"; break; + case '%': Res += "_PCT_"; break; + case ':': Res += "_COLON_"; break; + case '!': Res += "_EXCLAIM_"; break; + case '.': Res += "_DOT_"; break; + default: + if (isalnum(*it)) + Res += *it; + else + Res += "_" + utostr((unsigned) *it) + "_"; + } + } + + return Res; +} + +ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) { + ClassInfo *&Entry = TokenClasses[Token]; + + if (!Entry) { + Entry = new ClassInfo(); + Entry->Kind = ClassInfo::Token; + Entry->ClassName = "Token"; + Entry->Name = "MCK_" + getEnumNameForToken(Token); + Entry->ValueName = Token; + Entry->PredicateMethod = "<invalid>"; + Entry->RenderMethod = "<invalid>"; + Entry->ParserMethod = ""; + Classes.push_back(Entry); + } + + return Entry; +} + +ClassInfo * +AsmMatcherInfo::getOperandClass(const CGIOperandList::OperandInfo &OI, + int SubOpIdx) { + Record *Rec = OI.Rec; + if (SubOpIdx != -1) + Rec = dynamic_cast<DefInit*>(OI.MIOperandInfo->getArg(SubOpIdx))->getDef(); + return getOperandClass(Rec, SubOpIdx); +} + +ClassInfo * +AsmMatcherInfo::getOperandClass(Record *Rec, int SubOpIdx) { + if (Rec->isSubClassOf("RegisterOperand")) { + // RegisterOperand may have an associated ParserMatchClass. If it does, + // use it, else just fall back to the underlying register class. + const RecordVal *R = Rec->getValue("ParserMatchClass"); + if (R == 0 || R->getValue() == 0) + throw "Record `" + Rec->getName() + + "' does not have a ParserMatchClass!\n"; + + if (DefInit *DI= dynamic_cast<DefInit*>(R->getValue())) { + Record *MatchClass = DI->getDef(); + if (ClassInfo *CI = AsmOperandClasses[MatchClass]) + return CI; + } + + // No custom match class. Just use the register class. + Record *ClassRec = Rec->getValueAsDef("RegClass"); + if (!ClassRec) + throw TGError(Rec->getLoc(), "RegisterOperand `" + Rec->getName() + + "' has no associated register class!\n"); + if (ClassInfo *CI = RegisterClassClasses[ClassRec]) + return CI; + throw TGError(Rec->getLoc(), "register class has no class info!"); + } + + + if (Rec->isSubClassOf("RegisterClass")) { + if (ClassInfo *CI = RegisterClassClasses[Rec]) + return CI; + throw TGError(Rec->getLoc(), "register class has no class info!"); + } + + assert(Rec->isSubClassOf("Operand") && "Unexpected operand!"); + Record *MatchClass = Rec->getValueAsDef("ParserMatchClass"); + if (ClassInfo *CI = AsmOperandClasses[MatchClass]) + return CI; + + throw TGError(Rec->getLoc(), "operand has no match class!"); +} + +void AsmMatcherInfo:: +BuildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) { + const std::vector<CodeGenRegister*> &Registers = + Target.getRegBank().getRegisters(); + ArrayRef<CodeGenRegisterClass*> RegClassList = + Target.getRegBank().getRegClasses(); + + // The register sets used for matching. + std::set< std::set<Record*> > RegisterSets; + + // Gather the defined sets. + for (ArrayRef<CodeGenRegisterClass*>::const_iterator it = + RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) + RegisterSets.insert(std::set<Record*>( + (*it)->getOrder().begin(), (*it)->getOrder().end())); + + // Add any required singleton sets. + for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(), + ie = SingletonRegisters.end(); it != ie; ++it) { + Record *Rec = *it; + RegisterSets.insert(std::set<Record*>(&Rec, &Rec + 1)); + } + + // Introduce derived sets where necessary (when a register does not determine + // a unique register set class), and build the mapping of registers to the set + // they should classify to. + std::map<Record*, std::set<Record*> > RegisterMap; + for (std::vector<CodeGenRegister*>::const_iterator it = Registers.begin(), + ie = Registers.end(); it != ie; ++it) { + const CodeGenRegister &CGR = **it; + // Compute the intersection of all sets containing this register. + std::set<Record*> ContainingSet; + + for (std::set< std::set<Record*> >::iterator it = RegisterSets.begin(), + ie = RegisterSets.end(); it != ie; ++it) { + if (!it->count(CGR.TheDef)) + continue; + + if (ContainingSet.empty()) { + ContainingSet = *it; + continue; + } + + std::set<Record*> Tmp; + std::swap(Tmp, ContainingSet); + std::insert_iterator< std::set<Record*> > II(ContainingSet, + ContainingSet.begin()); + std::set_intersection(Tmp.begin(), Tmp.end(), it->begin(), it->end(), II); + } + + if (!ContainingSet.empty()) { + RegisterSets.insert(ContainingSet); + RegisterMap.insert(std::make_pair(CGR.TheDef, ContainingSet)); + } + } + + // Construct the register classes. + std::map<std::set<Record*>, ClassInfo*> RegisterSetClasses; + unsigned Index = 0; + for (std::set< std::set<Record*> >::iterator it = RegisterSets.begin(), + ie = RegisterSets.end(); it != ie; ++it, ++Index) { + ClassInfo *CI = new ClassInfo(); + CI->Kind = ClassInfo::RegisterClass0 + Index; + CI->ClassName = "Reg" + utostr(Index); + CI->Name = "MCK_Reg" + utostr(Index); + CI->ValueName = ""; + CI->PredicateMethod = ""; // unused + CI->RenderMethod = "addRegOperands"; + CI->Registers = *it; + Classes.push_back(CI); + RegisterSetClasses.insert(std::make_pair(*it, CI)); + } + + // Find the superclasses; we could compute only the subgroup lattice edges, + // but there isn't really a point. + for (std::set< std::set<Record*> >::iterator it = RegisterSets.begin(), + ie = RegisterSets.end(); it != ie; ++it) { + ClassInfo *CI = RegisterSetClasses[*it]; + for (std::set< std::set<Record*> >::iterator it2 = RegisterSets.begin(), + ie2 = RegisterSets.end(); it2 != ie2; ++it2) + if (*it != *it2 && + std::includes(it2->begin(), it2->end(), it->begin(), it->end())) + CI->SuperClasses.push_back(RegisterSetClasses[*it2]); + } + + // Name the register classes which correspond to a user defined RegisterClass. + for (ArrayRef<CodeGenRegisterClass*>::const_iterator + it = RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) { + const CodeGenRegisterClass &RC = **it; + // Def will be NULL for non-user defined register classes. + Record *Def = RC.getDef(); + if (!Def) + continue; + ClassInfo *CI = RegisterSetClasses[std::set<Record*>(RC.getOrder().begin(), + RC.getOrder().end())]; + if (CI->ValueName.empty()) { + CI->ClassName = RC.getName(); + CI->Name = "MCK_" + RC.getName(); + CI->ValueName = RC.getName(); + } else + CI->ValueName = CI->ValueName + "," + RC.getName(); + + RegisterClassClasses.insert(std::make_pair(Def, CI)); + } + + // Populate the map for individual registers. + for (std::map<Record*, std::set<Record*> >::iterator it = RegisterMap.begin(), + ie = RegisterMap.end(); it != ie; ++it) + RegisterClasses[it->first] = RegisterSetClasses[it->second]; + + // Name the register classes which correspond to singleton registers. + for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(), + ie = SingletonRegisters.end(); it != ie; ++it) { + Record *Rec = *it; + ClassInfo *CI = RegisterClasses[Rec]; + assert(CI && "Missing singleton register class info!"); + + if (CI->ValueName.empty()) { + CI->ClassName = Rec->getName(); + CI->Name = "MCK_" + Rec->getName(); + CI->ValueName = Rec->getName(); + } else + CI->ValueName = CI->ValueName + "," + Rec->getName(); + } +} + +void AsmMatcherInfo::BuildOperandClasses() { + std::vector<Record*> AsmOperands = + Records.getAllDerivedDefinitions("AsmOperandClass"); + + // Pre-populate AsmOperandClasses map. + for (std::vector<Record*>::iterator it = AsmOperands.begin(), + ie = AsmOperands.end(); it != ie; ++it) + AsmOperandClasses[*it] = new ClassInfo(); + + unsigned Index = 0; + for (std::vector<Record*>::iterator it = AsmOperands.begin(), + ie = AsmOperands.end(); it != ie; ++it, ++Index) { + ClassInfo *CI = AsmOperandClasses[*it]; + CI->Kind = ClassInfo::UserClass0 + Index; + + ListInit *Supers = (*it)->getValueAsListInit("SuperClasses"); + for (unsigned i = 0, e = Supers->getSize(); i != e; ++i) { + DefInit *DI = dynamic_cast<DefInit*>(Supers->getElement(i)); + if (!DI) { + PrintError((*it)->getLoc(), "Invalid super class reference!"); + continue; + } + + ClassInfo *SC = AsmOperandClasses[DI->getDef()]; + if (!SC) + PrintError((*it)->getLoc(), "Invalid super class reference!"); + else + CI->SuperClasses.push_back(SC); + } + CI->ClassName = (*it)->getValueAsString("Name"); + CI->Name = "MCK_" + CI->ClassName; + CI->ValueName = (*it)->getName(); + + // Get or construct the predicate method name. + Init *PMName = (*it)->getValueInit("PredicateMethod"); + if (StringInit *SI = dynamic_cast<StringInit*>(PMName)) { + CI->PredicateMethod = SI->getValue(); + } else { + assert(dynamic_cast<UnsetInit*>(PMName) && + "Unexpected PredicateMethod field!"); + CI->PredicateMethod = "is" + CI->ClassName; + } + + // Get or construct the render method name. + Init *RMName = (*it)->getValueInit("RenderMethod"); + if (StringInit *SI = dynamic_cast<StringInit*>(RMName)) { + CI->RenderMethod = SI->getValue(); + } else { + assert(dynamic_cast<UnsetInit*>(RMName) && + "Unexpected RenderMethod field!"); + CI->RenderMethod = "add" + CI->ClassName + "Operands"; + } + + // Get the parse method name or leave it as empty. + Init *PRMName = (*it)->getValueInit("ParserMethod"); + if (StringInit *SI = dynamic_cast<StringInit*>(PRMName)) + CI->ParserMethod = SI->getValue(); + + AsmOperandClasses[*it] = CI; + Classes.push_back(CI); + } +} + +AsmMatcherInfo::AsmMatcherInfo(Record *asmParser, + CodeGenTarget &target, + RecordKeeper &records) + : Records(records), AsmParser(asmParser), Target(target) { +} + +/// BuildOperandMatchInfo - Build the necessary information to handle user +/// defined operand parsing methods. +void AsmMatcherInfo::BuildOperandMatchInfo() { + + /// Map containing a mask with all operands indicies that can be found for + /// that class inside a instruction. + std::map<ClassInfo*, unsigned> OpClassMask; + + for (std::vector<MatchableInfo*>::const_iterator it = + Matchables.begin(), ie = Matchables.end(); + it != ie; ++it) { + MatchableInfo &II = **it; + OpClassMask.clear(); + + // Keep track of all operands of this instructions which belong to the + // same class. + for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) { + MatchableInfo::AsmOperand &Op = II.AsmOperands[i]; + if (Op.Class->ParserMethod.empty()) + continue; + unsigned &OperandMask = OpClassMask[Op.Class]; + OperandMask |= (1 << i); + } + + // Generate operand match info for each mnemonic/operand class pair. + for (std::map<ClassInfo*, unsigned>::iterator iit = OpClassMask.begin(), + iie = OpClassMask.end(); iit != iie; ++iit) { + unsigned OpMask = iit->second; + ClassInfo *CI = iit->first; + OperandMatchInfo.push_back(OperandMatchEntry::Create(&II, CI, OpMask)); + } + } +} + +void AsmMatcherInfo::BuildInfo() { + // Build information about all of the AssemblerPredicates. + std::vector<Record*> AllPredicates = + Records.getAllDerivedDefinitions("Predicate"); + for (unsigned i = 0, e = AllPredicates.size(); i != e; ++i) { + Record *Pred = AllPredicates[i]; + // Ignore predicates that are not intended for the assembler. + if (!Pred->getValueAsBit("AssemblerMatcherPredicate")) + continue; + + if (Pred->getName().empty()) + throw TGError(Pred->getLoc(), "Predicate has no name!"); + + unsigned FeatureNo = SubtargetFeatures.size(); + SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo); + assert(FeatureNo < 32 && "Too many subtarget features!"); + } + + // Parse the instructions; we need to do this first so that we can gather the + // singleton register classes. + SmallPtrSet<Record*, 16> SingletonRegisters; + unsigned VariantCount = Target.getAsmParserVariantCount(); + for (unsigned VC = 0; VC != VariantCount; ++VC) { + Record *AsmVariant = Target.getAsmParserVariant(VC); + std::string CommentDelimiter = + AsmVariant->getValueAsString("CommentDelimiter"); + std::string RegisterPrefix = AsmVariant->getValueAsString("RegisterPrefix"); + int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); + + for (CodeGenTarget::inst_iterator I = Target.inst_begin(), + E = Target.inst_end(); I != E; ++I) { + const CodeGenInstruction &CGI = **I; + + // If the tblgen -match-prefix option is specified (for tblgen hackers), + // filter the set of instructions we consider. + if (!StringRef(CGI.TheDef->getName()).startswith(MatchPrefix)) + continue; + + // Ignore "codegen only" instructions. + if (CGI.TheDef->getValueAsBit("isCodeGenOnly")) + continue; + + // Validate the operand list to ensure we can handle this instruction. + for (unsigned i = 0, e = CGI.Operands.size(); i != e; ++i) { + const CGIOperandList::OperandInfo &OI = CGI.Operands[i]; + + // Validate tied operands. + if (OI.getTiedRegister() != -1) { + // If we have a tied operand that consists of multiple MCOperands, + // reject it. We reject aliases and ignore instructions for now. + if (OI.MINumOperands != 1) { + // FIXME: Should reject these. The ARM backend hits this with $lane + // in a bunch of instructions. The right answer is unclear. + DEBUG({ + errs() << "warning: '" << CGI.TheDef->getName() << "': " + << "ignoring instruction with multi-operand tied operand '" + << OI.Name << "'\n"; + }); + continue; + } + } + } + + OwningPtr<MatchableInfo> II(new MatchableInfo(CGI)); + + II->Initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix); + + // Ignore instructions which shouldn't be matched and diagnose invalid + // instruction definitions with an error. + if (!II->Validate(CommentDelimiter, true)) + continue; + + // Ignore "Int_*" and "*_Int" instructions, which are internal aliases. + // + // FIXME: This is a total hack. + if (StringRef(II->TheDef->getName()).startswith("Int_") || + StringRef(II->TheDef->getName()).endswith("_Int")) + continue; + + Matchables.push_back(II.take()); + } + + // Parse all of the InstAlias definitions and stick them in the list of + // matchables. + std::vector<Record*> AllInstAliases = + Records.getAllDerivedDefinitions("InstAlias"); + for (unsigned i = 0, e = AllInstAliases.size(); i != e; ++i) { + CodeGenInstAlias *Alias = new CodeGenInstAlias(AllInstAliases[i], Target); + + // If the tblgen -match-prefix option is specified (for tblgen hackers), + // filter the set of instruction aliases we consider, based on the target + // instruction. + if (!StringRef(Alias->ResultInst->TheDef->getName()) + .startswith( MatchPrefix)) + continue; + + OwningPtr<MatchableInfo> II(new MatchableInfo(Alias)); + + II->Initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix); + + // Validate the alias definitions. + II->Validate(CommentDelimiter, false); + + Matchables.push_back(II.take()); + } + } + + // Build info for the register classes. + BuildRegisterClasses(SingletonRegisters); + + // Build info for the user defined assembly operand classes. + BuildOperandClasses(); + + // Build the information about matchables, now that we have fully formed + // classes. + for (std::vector<MatchableInfo*>::iterator it = Matchables.begin(), + ie = Matchables.end(); it != ie; ++it) { + MatchableInfo *II = *it; + + // Parse the tokens after the mnemonic. + // Note: BuildInstructionOperandReference may insert new AsmOperands, so + // don't precompute the loop bound. + for (unsigned i = 0; i != II->AsmOperands.size(); ++i) { + MatchableInfo::AsmOperand &Op = II->AsmOperands[i]; + StringRef Token = Op.Token; + + // Check for singleton registers. + if (Record *RegRecord = II->AsmOperands[i].SingletonReg) { + Op.Class = RegisterClasses[RegRecord]; + assert(Op.Class && Op.Class->Registers.size() == 1 && + "Unexpected class for singleton register"); + continue; + } + + // Check for simple tokens. + if (Token[0] != '$') { + Op.Class = getTokenClass(Token); + continue; + } + + if (Token.size() > 1 && isdigit(Token[1])) { + Op.Class = getTokenClass(Token); + continue; + } + + // Otherwise this is an operand reference. + StringRef OperandName; + if (Token[1] == '{') + OperandName = Token.substr(2, Token.size() - 3); + else + OperandName = Token.substr(1); + + if (II->DefRec.is<const CodeGenInstruction*>()) + BuildInstructionOperandReference(II, OperandName, i); + else + BuildAliasOperandReference(II, OperandName, Op); + } + + if (II->DefRec.is<const CodeGenInstruction*>()) + II->BuildInstructionResultOperands(); + else + II->BuildAliasResultOperands(); + } + + // Process token alias definitions and set up the associated superclass + // information. + std::vector<Record*> AllTokenAliases = + Records.getAllDerivedDefinitions("TokenAlias"); + for (unsigned i = 0, e = AllTokenAliases.size(); i != e; ++i) { + Record *Rec = AllTokenAliases[i]; + ClassInfo *FromClass = getTokenClass(Rec->getValueAsString("FromToken")); + ClassInfo *ToClass = getTokenClass(Rec->getValueAsString("ToToken")); + if (FromClass == ToClass) + throw TGError(Rec->getLoc(), + "error: Destination value identical to source value."); + FromClass->SuperClasses.push_back(ToClass); + } + + // Reorder classes so that classes precede super classes. + std::sort(Classes.begin(), Classes.end(), less_ptr<ClassInfo>()); +} + +/// BuildInstructionOperandReference - The specified operand is a reference to a +/// named operand such as $src. Resolve the Class and OperandInfo pointers. +void AsmMatcherInfo:: +BuildInstructionOperandReference(MatchableInfo *II, + StringRef OperandName, + unsigned AsmOpIdx) { + const CodeGenInstruction &CGI = *II->DefRec.get<const CodeGenInstruction*>(); + const CGIOperandList &Operands = CGI.Operands; + MatchableInfo::AsmOperand *Op = &II->AsmOperands[AsmOpIdx]; + + // Map this token to an operand. + unsigned Idx; + if (!Operands.hasOperandNamed(OperandName, Idx)) + throw TGError(II->TheDef->getLoc(), "error: unable to find operand: '" + + OperandName.str() + "'"); + + // If the instruction operand has multiple suboperands, but the parser + // match class for the asm operand is still the default "ImmAsmOperand", + // then handle each suboperand separately. + if (Op->SubOpIdx == -1 && Operands[Idx].MINumOperands > 1) { + Record *Rec = Operands[Idx].Rec; + assert(Rec->isSubClassOf("Operand") && "Unexpected operand!"); + Record *MatchClass = Rec->getValueAsDef("ParserMatchClass"); + if (MatchClass && MatchClass->getValueAsString("Name") == "Imm") { + // Insert remaining suboperands after AsmOpIdx in II->AsmOperands. + StringRef Token = Op->Token; // save this in case Op gets moved + for (unsigned SI = 1, SE = Operands[Idx].MINumOperands; SI != SE; ++SI) { + MatchableInfo::AsmOperand NewAsmOp(Token); + NewAsmOp.SubOpIdx = SI; + II->AsmOperands.insert(II->AsmOperands.begin()+AsmOpIdx+SI, NewAsmOp); + } + // Replace Op with first suboperand. + Op = &II->AsmOperands[AsmOpIdx]; // update the pointer in case it moved + Op->SubOpIdx = 0; + } + } + + // Set up the operand class. + Op->Class = getOperandClass(Operands[Idx], Op->SubOpIdx); + + // If the named operand is tied, canonicalize it to the untied operand. + // For example, something like: + // (outs GPR:$dst), (ins GPR:$src) + // with an asmstring of + // "inc $src" + // we want to canonicalize to: + // "inc $dst" + // so that we know how to provide the $dst operand when filling in the result. + int OITied = Operands[Idx].getTiedRegister(); + if (OITied != -1) { + // The tied operand index is an MIOperand index, find the operand that + // contains it. + std::pair<unsigned, unsigned> Idx = Operands.getSubOperandNumber(OITied); + OperandName = Operands[Idx.first].Name; + Op->SubOpIdx = Idx.second; + } + + Op->SrcOpName = OperandName; +} + +/// BuildAliasOperandReference - When parsing an operand reference out of the +/// matching string (e.g. "movsx $src, $dst"), determine what the class of the +/// operand reference is by looking it up in the result pattern definition. +void AsmMatcherInfo::BuildAliasOperandReference(MatchableInfo *II, + StringRef OperandName, + MatchableInfo::AsmOperand &Op) { + const CodeGenInstAlias &CGA = *II->DefRec.get<const CodeGenInstAlias*>(); + + // Set up the operand class. + for (unsigned i = 0, e = CGA.ResultOperands.size(); i != e; ++i) + if (CGA.ResultOperands[i].isRecord() && + CGA.ResultOperands[i].getName() == OperandName) { + // It's safe to go with the first one we find, because CodeGenInstAlias + // validates that all operands with the same name have the same record. + Op.SubOpIdx = CGA.ResultInstOperandIndex[i].second; + // Use the match class from the Alias definition, not the + // destination instruction, as we may have an immediate that's + // being munged by the match class. + Op.Class = getOperandClass(CGA.ResultOperands[i].getRecord(), + Op.SubOpIdx); + Op.SrcOpName = OperandName; + return; + } + + throw TGError(II->TheDef->getLoc(), "error: unable to find operand: '" + + OperandName.str() + "'"); +} + +void MatchableInfo::BuildInstructionResultOperands() { + const CodeGenInstruction *ResultInst = getResultInst(); + + // Loop over all operands of the result instruction, determining how to + // populate them. + for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) { + const CGIOperandList::OperandInfo &OpInfo = ResultInst->Operands[i]; + + // If this is a tied operand, just copy from the previously handled operand. + int TiedOp = OpInfo.getTiedRegister(); + if (TiedOp != -1) { + ResOperands.push_back(ResOperand::getTiedOp(TiedOp)); + continue; + } + + // Find out what operand from the asmparser this MCInst operand comes from. + int SrcOperand = FindAsmOperandNamed(OpInfo.Name); + if (OpInfo.Name.empty() || SrcOperand == -1) + throw TGError(TheDef->getLoc(), "Instruction '" + + TheDef->getName() + "' has operand '" + OpInfo.Name + + "' that doesn't appear in asm string!"); + + // Check if the one AsmOperand populates the entire operand. + unsigned NumOperands = OpInfo.MINumOperands; + if (AsmOperands[SrcOperand].SubOpIdx == -1) { + ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, NumOperands)); + continue; + } + + // Add a separate ResOperand for each suboperand. + for (unsigned AI = 0; AI < NumOperands; ++AI) { + assert(AsmOperands[SrcOperand+AI].SubOpIdx == (int)AI && + AsmOperands[SrcOperand+AI].SrcOpName == OpInfo.Name && + "unexpected AsmOperands for suboperands"); + ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand + AI, 1)); + } + } +} + +void MatchableInfo::BuildAliasResultOperands() { + const CodeGenInstAlias &CGA = *DefRec.get<const CodeGenInstAlias*>(); + const CodeGenInstruction *ResultInst = getResultInst(); + + // Loop over all operands of the result instruction, determining how to + // populate them. + unsigned AliasOpNo = 0; + unsigned LastOpNo = CGA.ResultInstOperandIndex.size(); + for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) { + const CGIOperandList::OperandInfo *OpInfo = &ResultInst->Operands[i]; + + // If this is a tied operand, just copy from the previously handled operand. + int TiedOp = OpInfo->getTiedRegister(); + if (TiedOp != -1) { + ResOperands.push_back(ResOperand::getTiedOp(TiedOp)); + continue; + } + + // Handle all the suboperands for this operand. + const std::string &OpName = OpInfo->Name; + for ( ; AliasOpNo < LastOpNo && + CGA.ResultInstOperandIndex[AliasOpNo].first == i; ++AliasOpNo) { + int SubIdx = CGA.ResultInstOperandIndex[AliasOpNo].second; + + // Find out what operand from the asmparser that this MCInst operand + // comes from. + switch (CGA.ResultOperands[AliasOpNo].Kind) { + case CodeGenInstAlias::ResultOperand::K_Record: { + StringRef Name = CGA.ResultOperands[AliasOpNo].getName(); + int SrcOperand = FindAsmOperand(Name, SubIdx); + if (SrcOperand == -1) + throw TGError(TheDef->getLoc(), "Instruction '" + + TheDef->getName() + "' has operand '" + OpName + + "' that doesn't appear in asm string!"); + unsigned NumOperands = (SubIdx == -1 ? OpInfo->MINumOperands : 1); + ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, + NumOperands)); + break; + } + case CodeGenInstAlias::ResultOperand::K_Imm: { + int64_t ImmVal = CGA.ResultOperands[AliasOpNo].getImm(); + ResOperands.push_back(ResOperand::getImmOp(ImmVal)); + break; + } + case CodeGenInstAlias::ResultOperand::K_Reg: { + Record *Reg = CGA.ResultOperands[AliasOpNo].getRegister(); + ResOperands.push_back(ResOperand::getRegOp(Reg)); + break; + } + } + } + } +} + +static void EmitConvertToMCInst(CodeGenTarget &Target, StringRef ClassName, + std::vector<MatchableInfo*> &Infos, + raw_ostream &OS) { + // Write the convert function to a separate stream, so we can drop it after + // the enum. + std::string ConvertFnBody; + raw_string_ostream CvtOS(ConvertFnBody); + + // Function we have already generated. + std::set<std::string> GeneratedFns; + + // Start the unified conversion function. + CvtOS << "bool " << Target.getName() << ClassName << "::\n"; + CvtOS << "ConvertToMCInst(unsigned Kind, MCInst &Inst, " + << "unsigned Opcode,\n" + << " const SmallVectorImpl<MCParsedAsmOperand*" + << "> &Operands) {\n"; + CvtOS << " Inst.setOpcode(Opcode);\n"; + CvtOS << " switch (Kind) {\n"; + CvtOS << " default:\n"; + + // Start the enum, which we will generate inline. + + OS << "// Unified function for converting operands to MCInst instances.\n\n"; + OS << "enum ConversionKind {\n"; + + // TargetOperandClass - This is the target's operand class, like X86Operand. + std::string TargetOperandClass = Target.getName() + "Operand"; + + for (std::vector<MatchableInfo*>::const_iterator it = Infos.begin(), + ie = Infos.end(); it != ie; ++it) { + MatchableInfo &II = **it; + + // Check if we have a custom match function. + std::string AsmMatchConverter = + II.getResultInst()->TheDef->getValueAsString("AsmMatchConverter"); + if (!AsmMatchConverter.empty()) { + std::string Signature = "ConvertCustom_" + AsmMatchConverter; + II.ConversionFnKind = Signature; + + // Check if we have already generated this signature. + if (!GeneratedFns.insert(Signature).second) + continue; + + // If not, emit it now. Add to the enum list. + OS << " " << Signature << ",\n"; + + CvtOS << " case " << Signature << ":\n"; + CvtOS << " return " << AsmMatchConverter + << "(Inst, Opcode, Operands);\n"; + continue; + } + + // Build the conversion function signature. + std::string Signature = "Convert"; + std::string CaseBody; + raw_string_ostream CaseOS(CaseBody); + + // Compute the convert enum and the case body. + for (unsigned i = 0, e = II.ResOperands.size(); i != e; ++i) { + const MatchableInfo::ResOperand &OpInfo = II.ResOperands[i]; + + // Generate code to populate each result operand. + switch (OpInfo.Kind) { + case MatchableInfo::ResOperand::RenderAsmOperand: { + // This comes from something we parsed. + MatchableInfo::AsmOperand &Op = II.AsmOperands[OpInfo.AsmOperandNum]; + + // Registers are always converted the same, don't duplicate the + // conversion function based on them. + Signature += "__"; + if (Op.Class->isRegisterClass()) + Signature += "Reg"; + else + Signature += Op.Class->ClassName; + Signature += utostr(OpInfo.MINumOperands); + Signature += "_" + itostr(OpInfo.AsmOperandNum); + + CaseOS << " ((" << TargetOperandClass << "*)Operands[" + << (OpInfo.AsmOperandNum+1) << "])->" << Op.Class->RenderMethod + << "(Inst, " << OpInfo.MINumOperands << ");\n"; + break; + } + + case MatchableInfo::ResOperand::TiedOperand: { + // If this operand is tied to a previous one, just copy the MCInst + // operand from the earlier one.We can only tie single MCOperand values. + //assert(OpInfo.MINumOperands == 1 && "Not a singular MCOperand"); + unsigned TiedOp = OpInfo.TiedOperandNum; + assert(i > TiedOp && "Tied operand precedes its target!"); + CaseOS << " Inst.addOperand(Inst.getOperand(" << TiedOp << "));\n"; + Signature += "__Tie" + utostr(TiedOp); + break; + } + case MatchableInfo::ResOperand::ImmOperand: { + int64_t Val = OpInfo.ImmVal; + CaseOS << " Inst.addOperand(MCOperand::CreateImm(" << Val << "));\n"; + Signature += "__imm" + itostr(Val); + break; + } + case MatchableInfo::ResOperand::RegOperand: { + if (OpInfo.Register == 0) { + CaseOS << " Inst.addOperand(MCOperand::CreateReg(0));\n"; + Signature += "__reg0"; + } else { + std::string N = getQualifiedName(OpInfo.Register); + CaseOS << " Inst.addOperand(MCOperand::CreateReg(" << N << "));\n"; + Signature += "__reg" + OpInfo.Register->getName(); + } + } + } + } + + II.ConversionFnKind = Signature; + + // Check if we have already generated this signature. + if (!GeneratedFns.insert(Signature).second) + continue; + + // If not, emit it now. Add to the enum list. + OS << " " << Signature << ",\n"; + + CvtOS << " case " << Signature << ":\n"; + CvtOS << CaseOS.str(); + CvtOS << " return true;\n"; + } + + // Finish the convert function. + + CvtOS << " }\n"; + CvtOS << " return false;\n"; + CvtOS << "}\n\n"; + + // Finish the enum, and drop the convert function after it. + + OS << " NumConversionVariants\n"; + OS << "};\n\n"; + + OS << CvtOS.str(); +} + +/// EmitMatchClassEnumeration - Emit the enumeration for match class kinds. +static void EmitMatchClassEnumeration(CodeGenTarget &Target, + std::vector<ClassInfo*> &Infos, + raw_ostream &OS) { + OS << "namespace {\n\n"; + + OS << "/// MatchClassKind - The kinds of classes which participate in\n" + << "/// instruction matching.\n"; + OS << "enum MatchClassKind {\n"; + OS << " InvalidMatchClass = 0,\n"; + for (std::vector<ClassInfo*>::iterator it = Infos.begin(), + ie = Infos.end(); it != ie; ++it) { + ClassInfo &CI = **it; + OS << " " << CI.Name << ", // "; + if (CI.Kind == ClassInfo::Token) { + OS << "'" << CI.ValueName << "'\n"; + } else if (CI.isRegisterClass()) { + if (!CI.ValueName.empty()) + OS << "register class '" << CI.ValueName << "'\n"; + else + OS << "derived register class\n"; + } else { + OS << "user defined class '" << CI.ValueName << "'\n"; + } + } + OS << " NumMatchClassKinds\n"; + OS << "};\n\n"; + + OS << "}\n\n"; +} + +/// EmitValidateOperandClass - Emit the function to validate an operand class. +static void EmitValidateOperandClass(AsmMatcherInfo &Info, + raw_ostream &OS) { + OS << "static bool validateOperandClass(MCParsedAsmOperand *GOp, " + << "MatchClassKind Kind) {\n"; + OS << " " << Info.Target.getName() << "Operand &Operand = *(" + << Info.Target.getName() << "Operand*)GOp;\n"; + + // The InvalidMatchClass is not to match any operand. + OS << " if (Kind == InvalidMatchClass)\n"; + OS << " return false;\n\n"; + + // Check for Token operands first. + OS << " if (Operand.isToken())\n"; + OS << " return isSubclass(matchTokenString(Operand.getToken()), Kind);" + << "\n\n"; + + // Check for register operands, including sub-classes. + OS << " if (Operand.isReg()) {\n"; + OS << " MatchClassKind OpKind;\n"; + OS << " switch (Operand.getReg()) {\n"; + OS << " default: OpKind = InvalidMatchClass; break;\n"; + for (std::map<Record*, ClassInfo*>::iterator + it = Info.RegisterClasses.begin(), ie = Info.RegisterClasses.end(); + it != ie; ++it) + OS << " case " << Info.Target.getName() << "::" + << it->first->getName() << ": OpKind = " << it->second->Name + << "; break;\n"; + OS << " }\n"; + OS << " return isSubclass(OpKind, Kind);\n"; + OS << " }\n\n"; + + // Check the user classes. We don't care what order since we're only + // actually matching against one of them. + for (std::vector<ClassInfo*>::iterator it = Info.Classes.begin(), + ie = Info.Classes.end(); it != ie; ++it) { + ClassInfo &CI = **it; + + if (!CI.isUserClass()) + continue; + + OS << " // '" << CI.ClassName << "' class\n"; + OS << " if (Kind == " << CI.Name + << " && Operand." << CI.PredicateMethod << "()) {\n"; + OS << " return true;\n"; + OS << " }\n\n"; + } + + OS << " return false;\n"; + OS << "}\n\n"; +} + +/// EmitIsSubclass - Emit the subclass predicate function. +static void EmitIsSubclass(CodeGenTarget &Target, + std::vector<ClassInfo*> &Infos, + raw_ostream &OS) { + OS << "/// isSubclass - Compute whether \\arg A is a subclass of \\arg B.\n"; + OS << "static bool isSubclass(MatchClassKind A, MatchClassKind B) {\n"; + OS << " if (A == B)\n"; + OS << " return true;\n\n"; + + OS << " switch (A) {\n"; + OS << " default:\n"; + OS << " return false;\n"; + for (std::vector<ClassInfo*>::iterator it = Infos.begin(), + ie = Infos.end(); it != ie; ++it) { + ClassInfo &A = **it; + + std::vector<StringRef> SuperClasses; + for (std::vector<ClassInfo*>::iterator it = Infos.begin(), + ie = Infos.end(); it != ie; ++it) { + ClassInfo &B = **it; + + if (&A != &B && A.isSubsetOf(B)) + SuperClasses.push_back(B.Name); + } + + if (SuperClasses.empty()) + continue; + + OS << "\n case " << A.Name << ":\n"; + + if (SuperClasses.size() == 1) { + OS << " return B == " << SuperClasses.back() << ";\n"; + continue; + } + + OS << " switch (B) {\n"; + OS << " default: return false;\n"; + for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i) + OS << " case " << SuperClasses[i] << ": return true;\n"; + OS << " }\n"; + } + OS << " }\n"; + OS << "}\n\n"; +} + +/// EmitMatchTokenString - Emit the function to match a token string to the +/// appropriate match class value. +static void EmitMatchTokenString(CodeGenTarget &Target, + std::vector<ClassInfo*> &Infos, + raw_ostream &OS) { + // Construct the match list. + std::vector<StringMatcher::StringPair> Matches; + for (std::vector<ClassInfo*>::iterator it = Infos.begin(), + ie = Infos.end(); it != ie; ++it) { + ClassInfo &CI = **it; + + if (CI.Kind == ClassInfo::Token) + Matches.push_back(StringMatcher::StringPair(CI.ValueName, + "return " + CI.Name + ";")); + } + + OS << "static MatchClassKind matchTokenString(StringRef Name) {\n"; + + StringMatcher("Name", Matches, OS).Emit(); + + OS << " return InvalidMatchClass;\n"; + OS << "}\n\n"; +} + +/// EmitMatchRegisterName - Emit the function to match a string to the target +/// specific register enum. +static void EmitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser, + raw_ostream &OS) { + // Construct the match list. + std::vector<StringMatcher::StringPair> Matches; + const std::vector<CodeGenRegister*> &Regs = + Target.getRegBank().getRegisters(); + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister *Reg = Regs[i]; + if (Reg->TheDef->getValueAsString("AsmName").empty()) + continue; + + Matches.push_back(StringMatcher::StringPair( + Reg->TheDef->getValueAsString("AsmName"), + "return " + utostr(Reg->EnumValue) + ";")); + } + + OS << "static unsigned MatchRegisterName(StringRef Name) {\n"; + + StringMatcher("Name", Matches, OS).Emit(); + + OS << " return 0;\n"; + OS << "}\n\n"; +} + +/// EmitSubtargetFeatureFlagEnumeration - Emit the subtarget feature flag +/// definitions. +static void EmitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info, + raw_ostream &OS) { + OS << "// Flags for subtarget features that participate in " + << "instruction matching.\n"; + OS << "enum SubtargetFeatureFlag {\n"; + for (std::map<Record*, SubtargetFeatureInfo*>::const_iterator + it = Info.SubtargetFeatures.begin(), + ie = Info.SubtargetFeatures.end(); it != ie; ++it) { + SubtargetFeatureInfo &SFI = *it->second; + OS << " " << SFI.getEnumName() << " = (1 << " << SFI.Index << "),\n"; + } + OS << " Feature_None = 0\n"; + OS << "};\n\n"; +} + +/// EmitComputeAvailableFeatures - Emit the function to compute the list of +/// available features given a subtarget. +static void EmitComputeAvailableFeatures(AsmMatcherInfo &Info, + raw_ostream &OS) { + std::string ClassName = + Info.AsmParser->getValueAsString("AsmParserClassName"); + + OS << "unsigned " << Info.Target.getName() << ClassName << "::\n" + << "ComputeAvailableFeatures(uint64_t FB) const {\n"; + OS << " unsigned Features = 0;\n"; + for (std::map<Record*, SubtargetFeatureInfo*>::const_iterator + it = Info.SubtargetFeatures.begin(), + ie = Info.SubtargetFeatures.end(); it != ie; ++it) { + SubtargetFeatureInfo &SFI = *it->second; + + OS << " if ("; + std::string CondStorage = + SFI.TheDef->getValueAsString("AssemblerCondString"); + StringRef Conds = CondStorage; + std::pair<StringRef,StringRef> Comma = Conds.split(','); + bool First = true; + do { + if (!First) + OS << " && "; + + bool Neg = false; + StringRef Cond = Comma.first; + if (Cond[0] == '!') { + Neg = true; + Cond = Cond.substr(1); + } + + OS << "((FB & " << Info.Target.getName() << "::" << Cond << ")"; + if (Neg) + OS << " == 0"; + else + OS << " != 0"; + OS << ")"; + + if (Comma.second.empty()) + break; + + First = false; + Comma = Comma.second.split(','); + } while (true); + + OS << ")\n"; + OS << " Features |= " << SFI.getEnumName() << ";\n"; + } + OS << " return Features;\n"; + OS << "}\n\n"; +} + +static std::string GetAliasRequiredFeatures(Record *R, + const AsmMatcherInfo &Info) { + std::vector<Record*> ReqFeatures = R->getValueAsListOfDefs("Predicates"); + std::string Result; + unsigned NumFeatures = 0; + for (unsigned i = 0, e = ReqFeatures.size(); i != e; ++i) { + SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]); + + if (F == 0) + throw TGError(R->getLoc(), "Predicate '" + ReqFeatures[i]->getName() + + "' is not marked as an AssemblerPredicate!"); + + if (NumFeatures) + Result += '|'; + + Result += F->getEnumName(); + ++NumFeatures; + } + + if (NumFeatures > 1) + Result = '(' + Result + ')'; + return Result; +} + +/// EmitMnemonicAliases - If the target has any MnemonicAlias<> definitions, +/// emit a function for them and return true, otherwise return false. +static bool EmitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info) { + // Ignore aliases when match-prefix is set. + if (!MatchPrefix.empty()) + return false; + + std::vector<Record*> Aliases = + Info.getRecords().getAllDerivedDefinitions("MnemonicAlias"); + if (Aliases.empty()) return false; + + OS << "static void applyMnemonicAliases(StringRef &Mnemonic, " + "unsigned Features) {\n"; + + // Keep track of all the aliases from a mnemonic. Use an std::map so that the + // iteration order of the map is stable. + std::map<std::string, std::vector<Record*> > AliasesFromMnemonic; + + for (unsigned i = 0, e = Aliases.size(); i != e; ++i) { + Record *R = Aliases[i]; + AliasesFromMnemonic[R->getValueAsString("FromMnemonic")].push_back(R); + } + + // Process each alias a "from" mnemonic at a time, building the code executed + // by the string remapper. + std::vector<StringMatcher::StringPair> Cases; + for (std::map<std::string, std::vector<Record*> >::iterator + I = AliasesFromMnemonic.begin(), E = AliasesFromMnemonic.end(); + I != E; ++I) { + const std::vector<Record*> &ToVec = I->second; + + // Loop through each alias and emit code that handles each case. If there + // are two instructions without predicates, emit an error. If there is one, + // emit it last. + std::string MatchCode; + int AliasWithNoPredicate = -1; + + for (unsigned i = 0, e = ToVec.size(); i != e; ++i) { + Record *R = ToVec[i]; + std::string FeatureMask = GetAliasRequiredFeatures(R, Info); + + // If this unconditionally matches, remember it for later and diagnose + // duplicates. + if (FeatureMask.empty()) { + if (AliasWithNoPredicate != -1) { + // We can't have two aliases from the same mnemonic with no predicate. + PrintError(ToVec[AliasWithNoPredicate]->getLoc(), + "two MnemonicAliases with the same 'from' mnemonic!"); + throw TGError(R->getLoc(), "this is the other MnemonicAlias."); + } + + AliasWithNoPredicate = i; + continue; + } + if (R->getValueAsString("ToMnemonic") == I->first) + throw TGError(R->getLoc(), "MnemonicAlias to the same string"); + + if (!MatchCode.empty()) + MatchCode += "else "; + MatchCode += "if ((Features & " + FeatureMask + ") == "+FeatureMask+")\n"; + MatchCode += " Mnemonic = \"" +R->getValueAsString("ToMnemonic")+"\";\n"; + } + + if (AliasWithNoPredicate != -1) { + Record *R = ToVec[AliasWithNoPredicate]; + if (!MatchCode.empty()) + MatchCode += "else\n "; + MatchCode += "Mnemonic = \"" + R->getValueAsString("ToMnemonic")+"\";\n"; + } + + MatchCode += "return;"; + + Cases.push_back(std::make_pair(I->first, MatchCode)); + } + + StringMatcher("Mnemonic", Cases, OS).Emit(); + OS << "}\n\n"; + + return true; +} + +static const char *getMinimalTypeForRange(uint64_t Range) { + assert(Range < 0xFFFFFFFFULL && "Enum too large"); + if (Range > 0xFFFF) + return "uint32_t"; + if (Range > 0xFF) + return "uint16_t"; + return "uint8_t"; +} + +static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, + const AsmMatcherInfo &Info, StringRef ClassName) { + // Emit the static custom operand parsing table; + OS << "namespace {\n"; + OS << " struct OperandMatchEntry {\n"; + OS << " static const char *const MnemonicTable;\n"; + OS << " uint32_t OperandMask;\n"; + OS << " uint32_t Mnemonic;\n"; + OS << " " << getMinimalTypeForRange(1ULL << Info.SubtargetFeatures.size()) + << " RequiredFeatures;\n"; + OS << " " << getMinimalTypeForRange(Info.Classes.size()) + << " Class;\n\n"; + OS << " StringRef getMnemonic() const {\n"; + OS << " return StringRef(MnemonicTable + Mnemonic + 1,\n"; + OS << " MnemonicTable[Mnemonic]);\n"; + OS << " }\n"; + OS << " };\n\n"; + + OS << " // Predicate for searching for an opcode.\n"; + OS << " struct LessOpcodeOperand {\n"; + OS << " bool operator()(const OperandMatchEntry &LHS, StringRef RHS) {\n"; + OS << " return LHS.getMnemonic() < RHS;\n"; + OS << " }\n"; + OS << " bool operator()(StringRef LHS, const OperandMatchEntry &RHS) {\n"; + OS << " return LHS < RHS.getMnemonic();\n"; + OS << " }\n"; + OS << " bool operator()(const OperandMatchEntry &LHS,"; + OS << " const OperandMatchEntry &RHS) {\n"; + OS << " return LHS.getMnemonic() < RHS.getMnemonic();\n"; + OS << " }\n"; + OS << " };\n"; + + OS << "} // end anonymous namespace.\n\n"; + + StringToOffsetTable StringTable; + + OS << "static const OperandMatchEntry OperandMatchTable[" + << Info.OperandMatchInfo.size() << "] = {\n"; + + OS << " /* Operand List Mask, Mnemonic, Operand Class, Features */\n"; + for (std::vector<OperandMatchEntry>::const_iterator it = + Info.OperandMatchInfo.begin(), ie = Info.OperandMatchInfo.end(); + it != ie; ++it) { + const OperandMatchEntry &OMI = *it; + const MatchableInfo &II = *OMI.MI; + + OS << " { " << OMI.OperandMask; + + OS << " /* "; + bool printComma = false; + for (int i = 0, e = 31; i !=e; ++i) + if (OMI.OperandMask & (1 << i)) { + if (printComma) + OS << ", "; + OS << i; + printComma = true; + } + OS << " */"; + + // Store a pascal-style length byte in the mnemonic. + std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str(); + OS << ", " << StringTable.GetOrAddStringOffset(LenMnemonic, false) + << " /* " << II.Mnemonic << " */, "; + + // Write the required features mask. + if (!II.RequiredFeatures.empty()) { + for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) { + if (i) OS << "|"; + OS << II.RequiredFeatures[i]->getEnumName(); + } + } else + OS << "0"; + + OS << ", " << OMI.CI->Name; + + OS << " },\n"; + } + OS << "};\n\n"; + + OS << "const char *const OperandMatchEntry::MnemonicTable =\n"; + StringTable.EmitString(OS); + OS << ";\n\n"; + + // Emit the operand class switch to call the correct custom parser for + // the found operand class. + OS << Target.getName() << ClassName << "::OperandMatchResultTy " + << Target.getName() << ClassName << "::\n" + << "tryCustomParseOperand(SmallVectorImpl<MCParsedAsmOperand*>" + << " &Operands,\n unsigned MCK) {\n\n" + << " switch(MCK) {\n"; + + for (std::vector<ClassInfo*>::const_iterator it = Info.Classes.begin(), + ie = Info.Classes.end(); it != ie; ++it) { + ClassInfo *CI = *it; + if (CI->ParserMethod.empty()) + continue; + OS << " case " << CI->Name << ":\n" + << " return " << CI->ParserMethod << "(Operands);\n"; + } + + OS << " default:\n"; + OS << " return MatchOperand_NoMatch;\n"; + OS << " }\n"; + OS << " return MatchOperand_NoMatch;\n"; + OS << "}\n\n"; + + // Emit the static custom operand parser. This code is very similar with + // the other matcher. Also use MatchResultTy here just in case we go for + // a better error handling. + OS << Target.getName() << ClassName << "::OperandMatchResultTy " + << Target.getName() << ClassName << "::\n" + << "MatchOperandParserImpl(SmallVectorImpl<MCParsedAsmOperand*>" + << " &Operands,\n StringRef Mnemonic) {\n"; + + // Emit code to get the available features. + OS << " // Get the current feature set.\n"; + OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n"; + + OS << " // Get the next operand index.\n"; + OS << " unsigned NextOpNum = Operands.size()-1;\n"; + + // Emit code to search the table. + OS << " // Search the table.\n"; + OS << " std::pair<const OperandMatchEntry*, const OperandMatchEntry*>"; + OS << " MnemonicRange =\n"; + OS << " std::equal_range(OperandMatchTable, OperandMatchTable+" + << Info.OperandMatchInfo.size() << ", Mnemonic,\n" + << " LessOpcodeOperand());\n\n"; + + OS << " if (MnemonicRange.first == MnemonicRange.second)\n"; + OS << " return MatchOperand_NoMatch;\n\n"; + + OS << " for (const OperandMatchEntry *it = MnemonicRange.first,\n" + << " *ie = MnemonicRange.second; it != ie; ++it) {\n"; + + OS << " // equal_range guarantees that instruction mnemonic matches.\n"; + OS << " assert(Mnemonic == it->getMnemonic());\n\n"; + + // Emit check that the required features are available. + OS << " // check if the available features match\n"; + OS << " if ((AvailableFeatures & it->RequiredFeatures) " + << "!= it->RequiredFeatures) {\n"; + OS << " continue;\n"; + OS << " }\n\n"; + + // Emit check to ensure the operand number matches. + OS << " // check if the operand in question has a custom parser.\n"; + OS << " if (!(it->OperandMask & (1 << NextOpNum)))\n"; + OS << " continue;\n\n"; + + // Emit call to the custom parser method + OS << " // call custom parse method to handle the operand\n"; + OS << " OperandMatchResultTy Result = "; + OS << "tryCustomParseOperand(Operands, it->Class);\n"; + OS << " if (Result != MatchOperand_NoMatch)\n"; + OS << " return Result;\n"; + OS << " }\n\n"; + + OS << " // Okay, we had no match.\n"; + OS << " return MatchOperand_NoMatch;\n"; + OS << "}\n\n"; +} + +void AsmMatcherEmitter::run(raw_ostream &OS) { + CodeGenTarget Target(Records); + Record *AsmParser = Target.getAsmParser(); + std::string ClassName = AsmParser->getValueAsString("AsmParserClassName"); + + // Compute the information on the instructions to match. + AsmMatcherInfo Info(AsmParser, Target, Records); + Info.BuildInfo(); + + // Sort the instruction table using the partial order on classes. We use + // stable_sort to ensure that ambiguous instructions are still + // deterministically ordered. + std::stable_sort(Info.Matchables.begin(), Info.Matchables.end(), + less_ptr<MatchableInfo>()); + + DEBUG_WITH_TYPE("instruction_info", { + for (std::vector<MatchableInfo*>::iterator + it = Info.Matchables.begin(), ie = Info.Matchables.end(); + it != ie; ++it) + (*it)->dump(); + }); + + // Check for ambiguous matchables. + DEBUG_WITH_TYPE("ambiguous_instrs", { + unsigned NumAmbiguous = 0; + for (unsigned i = 0, e = Info.Matchables.size(); i != e; ++i) { + for (unsigned j = i + 1; j != e; ++j) { + MatchableInfo &A = *Info.Matchables[i]; + MatchableInfo &B = *Info.Matchables[j]; + + if (A.CouldMatchAmbiguouslyWith(B)) { + errs() << "warning: ambiguous matchables:\n"; + A.dump(); + errs() << "\nis incomparable with:\n"; + B.dump(); + errs() << "\n\n"; + ++NumAmbiguous; + } + } + } + if (NumAmbiguous) + errs() << "warning: " << NumAmbiguous + << " ambiguous matchables!\n"; + }); + + // Compute the information on the custom operand parsing. + Info.BuildOperandMatchInfo(); + + // Write the output. + + EmitSourceFileHeader("Assembly Matcher Source Fragment", OS); + + // Information for the class declaration. + OS << "\n#ifdef GET_ASSEMBLER_HEADER\n"; + OS << "#undef GET_ASSEMBLER_HEADER\n"; + OS << " // This should be included into the middle of the declaration of\n"; + OS << " // your subclasses implementation of MCTargetAsmParser.\n"; + OS << " unsigned ComputeAvailableFeatures(uint64_t FeatureBits) const;\n"; + OS << " bool ConvertToMCInst(unsigned Kind, MCInst &Inst, " + << "unsigned Opcode,\n" + << " const SmallVectorImpl<MCParsedAsmOperand*> " + << "&Operands);\n"; + OS << " bool MnemonicIsValid(StringRef Mnemonic);\n"; + OS << " unsigned MatchInstructionImpl(\n"; + OS << " const SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n"; + OS << " MCInst &Inst, unsigned &ErrorInfo, unsigned VariantID = 0);\n"; + + if (Info.OperandMatchInfo.size()) { + OS << "\n enum OperandMatchResultTy {\n"; + OS << " MatchOperand_Success, // operand matched successfully\n"; + OS << " MatchOperand_NoMatch, // operand did not match\n"; + OS << " MatchOperand_ParseFail // operand matched but had errors\n"; + OS << " };\n"; + OS << " OperandMatchResultTy MatchOperandParserImpl(\n"; + OS << " SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n"; + OS << " StringRef Mnemonic);\n"; + + OS << " OperandMatchResultTy tryCustomParseOperand(\n"; + OS << " SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n"; + OS << " unsigned MCK);\n\n"; + } + + OS << "#endif // GET_ASSEMBLER_HEADER_INFO\n\n"; + + OS << "\n#ifdef GET_REGISTER_MATCHER\n"; + OS << "#undef GET_REGISTER_MATCHER\n\n"; + + // Emit the subtarget feature enumeration. + EmitSubtargetFeatureFlagEnumeration(Info, OS); + + // Emit the function to match a register name to number. + EmitMatchRegisterName(Target, AsmParser, OS); + + OS << "#endif // GET_REGISTER_MATCHER\n\n"; + + + OS << "\n#ifdef GET_MATCHER_IMPLEMENTATION\n"; + OS << "#undef GET_MATCHER_IMPLEMENTATION\n\n"; + + // Generate the function that remaps for mnemonic aliases. + bool HasMnemonicAliases = EmitMnemonicAliases(OS, Info); + + // Generate the unified function to convert operands into an MCInst. + EmitConvertToMCInst(Target, ClassName, Info.Matchables, OS); + + // Emit the enumeration for classes which participate in matching. + EmitMatchClassEnumeration(Target, Info.Classes, OS); + + // Emit the routine to match token strings to their match class. + EmitMatchTokenString(Target, Info.Classes, OS); + + // Emit the subclass predicate routine. + EmitIsSubclass(Target, Info.Classes, OS); + + // Emit the routine to validate an operand against a match class. + EmitValidateOperandClass(Info, OS); + + // Emit the available features compute function. + EmitComputeAvailableFeatures(Info, OS); + + + size_t MaxNumOperands = 0; + for (std::vector<MatchableInfo*>::const_iterator it = + Info.Matchables.begin(), ie = Info.Matchables.end(); + it != ie; ++it) + MaxNumOperands = std::max(MaxNumOperands, (*it)->AsmOperands.size()); + + // Emit the static match table; unused classes get initalized to 0 which is + // guaranteed to be InvalidMatchClass. + // + // FIXME: We can reduce the size of this table very easily. First, we change + // it so that store the kinds in separate bit-fields for each index, which + // only needs to be the max width used for classes at that index (we also need + // to reject based on this during classification). If we then make sure to + // order the match kinds appropriately (putting mnemonics last), then we + // should only end up using a few bits for each class, especially the ones + // following the mnemonic. + OS << "namespace {\n"; + OS << " struct MatchEntry {\n"; + OS << " static const char *const MnemonicTable;\n"; + OS << " uint32_t Mnemonic;\n"; + OS << " uint16_t Opcode;\n"; + OS << " " << getMinimalTypeForRange(Info.Matchables.size()) + << " ConvertFn;\n"; + OS << " " << getMinimalTypeForRange(1ULL << Info.SubtargetFeatures.size()) + << " RequiredFeatures;\n"; + OS << " " << getMinimalTypeForRange(Info.Classes.size()) + << " Classes[" << MaxNumOperands << "];\n"; + OS << " uint8_t AsmVariantID;\n\n"; + OS << " StringRef getMnemonic() const {\n"; + OS << " return StringRef(MnemonicTable + Mnemonic + 1,\n"; + OS << " MnemonicTable[Mnemonic]);\n"; + OS << " }\n"; + OS << " };\n\n"; + + OS << " // Predicate for searching for an opcode.\n"; + OS << " struct LessOpcode {\n"; + OS << " bool operator()(const MatchEntry &LHS, StringRef RHS) {\n"; + OS << " return LHS.getMnemonic() < RHS;\n"; + OS << " }\n"; + OS << " bool operator()(StringRef LHS, const MatchEntry &RHS) {\n"; + OS << " return LHS < RHS.getMnemonic();\n"; + OS << " }\n"; + OS << " bool operator()(const MatchEntry &LHS, const MatchEntry &RHS) {\n"; + OS << " return LHS.getMnemonic() < RHS.getMnemonic();\n"; + OS << " }\n"; + OS << " };\n"; + + OS << "} // end anonymous namespace.\n\n"; + + StringToOffsetTable StringTable; + + OS << "static const MatchEntry MatchTable[" + << Info.Matchables.size() << "] = {\n"; + + for (std::vector<MatchableInfo*>::const_iterator it = + Info.Matchables.begin(), ie = Info.Matchables.end(); + it != ie; ++it) { + MatchableInfo &II = **it; + + // Store a pascal-style length byte in the mnemonic. + std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str(); + OS << " { " << StringTable.GetOrAddStringOffset(LenMnemonic, false) + << " /* " << II.Mnemonic << " */, " + << Target.getName() << "::" + << II.getResultInst()->TheDef->getName() << ", " + << II.ConversionFnKind << ", "; + + // Write the required features mask. + if (!II.RequiredFeatures.empty()) { + for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) { + if (i) OS << "|"; + OS << II.RequiredFeatures[i]->getEnumName(); + } + } else + OS << "0"; + + OS << ", { "; + for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) { + MatchableInfo::AsmOperand &Op = II.AsmOperands[i]; + + if (i) OS << ", "; + OS << Op.Class->Name; + } + OS << " }, " << II.AsmVariantID; + OS << "},\n"; + } + + OS << "};\n\n"; + + OS << "const char *const MatchEntry::MnemonicTable =\n"; + StringTable.EmitString(OS); + OS << ";\n\n"; + + // A method to determine if a mnemonic is in the list. + OS << "bool " << Target.getName() << ClassName << "::\n" + << "MnemonicIsValid(StringRef Mnemonic) {\n"; + OS << " // Search the table.\n"; + OS << " std::pair<const MatchEntry*, const MatchEntry*> MnemonicRange =\n"; + OS << " std::equal_range(MatchTable, MatchTable+" + << Info.Matchables.size() << ", Mnemonic, LessOpcode());\n"; + OS << " return MnemonicRange.first != MnemonicRange.second;\n"; + OS << "}\n\n"; + + // Finally, build the match function. + OS << "unsigned " + << Target.getName() << ClassName << "::\n" + << "MatchInstructionImpl(const SmallVectorImpl<MCParsedAsmOperand*>" + << " &Operands,\n"; + OS << " MCInst &Inst, unsigned &ErrorInfo,\n"; + OS << " unsigned VariantID) {\n"; + + // Emit code to get the available features. + OS << " // Get the current feature set.\n"; + OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n"; + + OS << " // Get the instruction mnemonic, which is the first token.\n"; + OS << " StringRef Mnemonic = ((" << Target.getName() + << "Operand*)Operands[0])->getToken();\n\n"; + + if (HasMnemonicAliases) { + OS << " // Process all MnemonicAliases to remap the mnemonic.\n"; + OS << " // FIXME : Add an entry in AsmParserVariant to check this.\n"; + OS << " if (!VariantID)\n"; + OS << " applyMnemonicAliases(Mnemonic, AvailableFeatures);\n\n"; + } + + // Emit code to compute the class list for this operand vector. + OS << " // Eliminate obvious mismatches.\n"; + OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n"; + OS << " ErrorInfo = " << (MaxNumOperands+1) << ";\n"; + OS << " return Match_InvalidOperand;\n"; + OS << " }\n\n"; + + OS << " // Some state to try to produce better error messages.\n"; + OS << " bool HadMatchOtherThanFeatures = false;\n"; + OS << " bool HadMatchOtherThanPredicate = false;\n"; + OS << " unsigned RetCode = Match_InvalidOperand;\n"; + OS << " // Set ErrorInfo to the operand that mismatches if it is\n"; + OS << " // wrong for all instances of the instruction.\n"; + OS << " ErrorInfo = ~0U;\n"; + + // Emit code to search the table. + OS << " // Search the table.\n"; + OS << " std::pair<const MatchEntry*, const MatchEntry*> MnemonicRange =\n"; + OS << " std::equal_range(MatchTable, MatchTable+" + << Info.Matchables.size() << ", Mnemonic, LessOpcode());\n\n"; + + OS << " // Return a more specific error code if no mnemonics match.\n"; + OS << " if (MnemonicRange.first == MnemonicRange.second)\n"; + OS << " return Match_MnemonicFail;\n\n"; + + OS << " for (const MatchEntry *it = MnemonicRange.first, " + << "*ie = MnemonicRange.second;\n"; + OS << " it != ie; ++it) {\n"; + + OS << " // equal_range guarantees that instruction mnemonic matches.\n"; + OS << " assert(Mnemonic == it->getMnemonic());\n"; + + // Emit check that the subclasses match. + OS << " if (VariantID != it->AsmVariantID) continue;\n"; + OS << " bool OperandsValid = true;\n"; + OS << " for (unsigned i = 0; i != " << MaxNumOperands << "; ++i) {\n"; + OS << " if (i + 1 >= Operands.size()) {\n"; + OS << " OperandsValid = (it->Classes[i] == " <<"InvalidMatchClass);\n"; + OS << " break;\n"; + OS << " }\n"; + OS << " if (validateOperandClass(Operands[i+1], " + "(MatchClassKind)it->Classes[i]))\n"; + OS << " continue;\n"; + OS << " // If this operand is broken for all of the instances of this\n"; + OS << " // mnemonic, keep track of it so we can report loc info.\n"; + OS << " if (it == MnemonicRange.first || ErrorInfo <= i+1)\n"; + OS << " ErrorInfo = i+1;\n"; + OS << " // Otherwise, just reject this instance of the mnemonic.\n"; + OS << " OperandsValid = false;\n"; + OS << " break;\n"; + OS << " }\n\n"; + + OS << " if (!OperandsValid) continue;\n"; + + // Emit check that the required features are available. + OS << " if ((AvailableFeatures & it->RequiredFeatures) " + << "!= it->RequiredFeatures) {\n"; + OS << " HadMatchOtherThanFeatures = true;\n"; + OS << " continue;\n"; + OS << " }\n"; + OS << "\n"; + OS << " // We have selected a definite instruction, convert the parsed\n" + << " // operands into the appropriate MCInst.\n"; + OS << " if (!ConvertToMCInst(it->ConvertFn, Inst,\n" + << " it->Opcode, Operands))\n"; + OS << " return Match_ConversionFail;\n"; + OS << "\n"; + + // Verify the instruction with the target-specific match predicate function. + OS << " // We have a potential match. Check the target predicate to\n" + << " // handle any context sensitive constraints.\n" + << " unsigned MatchResult;\n" + << " if ((MatchResult = checkTargetMatchPredicate(Inst)) !=" + << " Match_Success) {\n" + << " Inst.clear();\n" + << " RetCode = MatchResult;\n" + << " HadMatchOtherThanPredicate = true;\n" + << " continue;\n" + << " }\n\n"; + + // Call the post-processing function, if used. + std::string InsnCleanupFn = + AsmParser->getValueAsString("AsmParserInstCleanup"); + if (!InsnCleanupFn.empty()) + OS << " " << InsnCleanupFn << "(Inst);\n"; + + OS << " return Match_Success;\n"; + OS << " }\n\n"; + + OS << " // Okay, we had no match. Try to return a useful error code.\n"; + OS << " if (HadMatchOtherThanPredicate || !HadMatchOtherThanFeatures)"; + OS << " return RetCode;\n"; + OS << " return Match_MissingFeature;\n"; + OS << "}\n\n"; + + if (Info.OperandMatchInfo.size()) + EmitCustomOperandParsing(OS, Target, Info, ClassName); + + OS << "#endif // GET_MATCHER_IMPLEMENTATION\n\n"; +} diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.h b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.h new file mode 100644 index 0000000..e04ac10 --- /dev/null +++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.h @@ -0,0 +1,31 @@ +//===- AsmMatcherEmitter.h - Generate an assembly matcher -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend emits a target specifier matcher for converting parsed +// assembly operands in the MCInst structures. +// +//===----------------------------------------------------------------------===// + +#ifndef ASMMATCHER_EMITTER_H +#define ASMMATCHER_EMITTER_H + +#include "llvm/TableGen/TableGenBackend.h" +#include <cassert> + +namespace llvm { + class AsmMatcherEmitter : public TableGenBackend { + RecordKeeper &Records; + public: + AsmMatcherEmitter(RecordKeeper &R) : Records(R) {} + + // run - Output the matcher, returning true on failure. + void run(raw_ostream &o); + }; +} +#endif diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp new file mode 100644 index 0000000..d079b45 --- /dev/null +++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp @@ -0,0 +1,937 @@ +//===- AsmWriterEmitter.cpp - Generate an assembly writer -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend is emits an assembly printer for the current target. +// Note that this is currently fairly skeletal, but will grow over time. +// +//===----------------------------------------------------------------------===// + +#include "AsmWriterEmitter.h" +#include "AsmWriterInst.h" +#include "CodeGenTarget.h" +#include "StringToOffsetTable.h" +#include "SequenceToOffsetTable.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 <algorithm> +using namespace llvm; + +static void PrintCases(std::vector<std::pair<std::string, + AsmWriterOperand> > &OpsToPrint, raw_ostream &O) { + O << " case " << OpsToPrint.back().first << ": "; + AsmWriterOperand TheOp = OpsToPrint.back().second; + OpsToPrint.pop_back(); + + // Check to see if any other operands are identical in this list, and if so, + // emit a case label for them. + for (unsigned i = OpsToPrint.size(); i != 0; --i) + if (OpsToPrint[i-1].second == TheOp) { + O << "\n case " << OpsToPrint[i-1].first << ": "; + OpsToPrint.erase(OpsToPrint.begin()+i-1); + } + + // Finally, emit the code. + O << TheOp.getCode(); + O << "break;\n"; +} + + +/// EmitInstructions - Emit the last instruction in the vector and any other +/// instructions that are suitably similar to it. +static void EmitInstructions(std::vector<AsmWriterInst> &Insts, + raw_ostream &O) { + AsmWriterInst FirstInst = Insts.back(); + Insts.pop_back(); + + std::vector<AsmWriterInst> SimilarInsts; + unsigned DifferingOperand = ~0; + for (unsigned i = Insts.size(); i != 0; --i) { + unsigned DiffOp = Insts[i-1].MatchesAllButOneOp(FirstInst); + if (DiffOp != ~1U) { + if (DifferingOperand == ~0U) // First match! + DifferingOperand = DiffOp; + + // If this differs in the same operand as the rest of the instructions in + // this class, move it to the SimilarInsts list. + if (DifferingOperand == DiffOp || DiffOp == ~0U) { + SimilarInsts.push_back(Insts[i-1]); + Insts.erase(Insts.begin()+i-1); + } + } + } + + O << " case " << FirstInst.CGI->Namespace << "::" + << FirstInst.CGI->TheDef->getName() << ":\n"; + for (unsigned i = 0, e = SimilarInsts.size(); i != e; ++i) + O << " case " << SimilarInsts[i].CGI->Namespace << "::" + << SimilarInsts[i].CGI->TheDef->getName() << ":\n"; + for (unsigned i = 0, e = FirstInst.Operands.size(); i != e; ++i) { + if (i != DifferingOperand) { + // If the operand is the same for all instructions, just print it. + O << " " << FirstInst.Operands[i].getCode(); + } else { + // If this is the operand that varies between all of the instructions, + // emit a switch for just this operand now. + O << " switch (MI->getOpcode()) {\n"; + std::vector<std::pair<std::string, AsmWriterOperand> > OpsToPrint; + OpsToPrint.push_back(std::make_pair(FirstInst.CGI->Namespace + "::" + + FirstInst.CGI->TheDef->getName(), + FirstInst.Operands[i])); + + for (unsigned si = 0, e = SimilarInsts.size(); si != e; ++si) { + AsmWriterInst &AWI = SimilarInsts[si]; + OpsToPrint.push_back(std::make_pair(AWI.CGI->Namespace+"::"+ + AWI.CGI->TheDef->getName(), + AWI.Operands[i])); + } + std::reverse(OpsToPrint.begin(), OpsToPrint.end()); + while (!OpsToPrint.empty()) + PrintCases(OpsToPrint, O); + O << " }"; + } + O << "\n"; + } + O << " break;\n"; +} + +void AsmWriterEmitter:: +FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands, + std::vector<unsigned> &InstIdxs, + std::vector<unsigned> &InstOpsUsed) const { + InstIdxs.assign(NumberedInstructions.size(), ~0U); + + // This vector parallels UniqueOperandCommands, keeping track of which + // instructions each case are used for. It is a comma separated string of + // enums. + std::vector<std::string> InstrsForCase; + InstrsForCase.resize(UniqueOperandCommands.size()); + InstOpsUsed.assign(UniqueOperandCommands.size(), 0); + + for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { + const AsmWriterInst *Inst = getAsmWriterInstByID(i); + if (Inst == 0) continue; // PHI, INLINEASM, PROLOG_LABEL, etc. + + std::string Command; + if (Inst->Operands.empty()) + continue; // Instruction already done. + + Command = " " + Inst->Operands[0].getCode() + "\n"; + + // Check to see if we already have 'Command' in UniqueOperandCommands. + // If not, add it. + bool FoundIt = false; + for (unsigned idx = 0, e = UniqueOperandCommands.size(); idx != e; ++idx) + if (UniqueOperandCommands[idx] == Command) { + InstIdxs[i] = idx; + InstrsForCase[idx] += ", "; + InstrsForCase[idx] += Inst->CGI->TheDef->getName(); + FoundIt = true; + break; + } + if (!FoundIt) { + InstIdxs[i] = UniqueOperandCommands.size(); + UniqueOperandCommands.push_back(Command); + InstrsForCase.push_back(Inst->CGI->TheDef->getName()); + + // This command matches one operand so far. + InstOpsUsed.push_back(1); + } + } + + // For each entry of UniqueOperandCommands, there is a set of instructions + // that uses it. If the next command of all instructions in the set are + // identical, fold it into the command. + for (unsigned CommandIdx = 0, e = UniqueOperandCommands.size(); + CommandIdx != e; ++CommandIdx) { + + for (unsigned Op = 1; ; ++Op) { + // Scan for the first instruction in the set. + std::vector<unsigned>::iterator NIT = + std::find(InstIdxs.begin(), InstIdxs.end(), CommandIdx); + if (NIT == InstIdxs.end()) break; // No commonality. + + // If this instruction has no more operands, we isn't anything to merge + // into this command. + const AsmWriterInst *FirstInst = + getAsmWriterInstByID(NIT-InstIdxs.begin()); + if (!FirstInst || FirstInst->Operands.size() == Op) + break; + + // Otherwise, scan to see if all of the other instructions in this command + // set share the operand. + bool AllSame = true; + // Keep track of the maximum, number of operands or any + // instruction we see in the group. + size_t MaxSize = FirstInst->Operands.size(); + + for (NIT = std::find(NIT+1, InstIdxs.end(), CommandIdx); + NIT != InstIdxs.end(); + NIT = std::find(NIT+1, InstIdxs.end(), CommandIdx)) { + // Okay, found another instruction in this command set. If the operand + // matches, we're ok, otherwise bail out. + const AsmWriterInst *OtherInst = + getAsmWriterInstByID(NIT-InstIdxs.begin()); + + if (OtherInst && + OtherInst->Operands.size() > FirstInst->Operands.size()) + MaxSize = std::max(MaxSize, OtherInst->Operands.size()); + + if (!OtherInst || OtherInst->Operands.size() == Op || + OtherInst->Operands[Op] != FirstInst->Operands[Op]) { + AllSame = false; + break; + } + } + if (!AllSame) break; + + // Okay, everything in this command set has the same next operand. Add it + // to UniqueOperandCommands and remember that it was consumed. + std::string Command = " " + FirstInst->Operands[Op].getCode() + "\n"; + + UniqueOperandCommands[CommandIdx] += Command; + InstOpsUsed[CommandIdx]++; + } + } + + // Prepend some of the instructions each case is used for onto the case val. + for (unsigned i = 0, e = InstrsForCase.size(); i != e; ++i) { + std::string Instrs = InstrsForCase[i]; + if (Instrs.size() > 70) { + Instrs.erase(Instrs.begin()+70, Instrs.end()); + Instrs += "..."; + } + + if (!Instrs.empty()) + UniqueOperandCommands[i] = " // " + Instrs + "\n" + + UniqueOperandCommands[i]; + } +} + + +static void UnescapeString(std::string &Str) { + for (unsigned i = 0; i != Str.size(); ++i) { + if (Str[i] == '\\' && i != Str.size()-1) { + switch (Str[i+1]) { + default: continue; // Don't execute the code after the switch. + case 'a': Str[i] = '\a'; break; + case 'b': Str[i] = '\b'; break; + case 'e': Str[i] = 27; break; + case 'f': Str[i] = '\f'; break; + case 'n': Str[i] = '\n'; break; + case 'r': Str[i] = '\r'; break; + case 't': Str[i] = '\t'; break; + case 'v': Str[i] = '\v'; break; + case '"': Str[i] = '\"'; break; + case '\'': Str[i] = '\''; break; + case '\\': Str[i] = '\\'; break; + } + // Nuke the second character. + Str.erase(Str.begin()+i+1); + } + } +} + +/// EmitPrintInstruction - Generate the code for the "printInstruction" method +/// implementation. +void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { + CodeGenTarget Target(Records); + Record *AsmWriter = Target.getAsmWriter(); + std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); + bool isMC = AsmWriter->getValueAsBit("isMCAsmWriter"); + const char *MachineInstrClassName = isMC ? "MCInst" : "MachineInstr"; + + O << + "/// printInstruction - This method is automatically generated by tablegen\n" + "/// from the instruction set description.\n" + "void " << Target.getName() << ClassName + << "::printInstruction(const " << MachineInstrClassName + << " *MI, raw_ostream &O) {\n"; + + std::vector<AsmWriterInst> Instructions; + + for (CodeGenTarget::inst_iterator I = Target.inst_begin(), + E = Target.inst_end(); I != E; ++I) + if (!(*I)->AsmString.empty() && + (*I)->TheDef->getName() != "PHI") + Instructions.push_back( + AsmWriterInst(**I, + AsmWriter->getValueAsInt("Variant"), + AsmWriter->getValueAsInt("FirstOperandColumn"), + AsmWriter->getValueAsInt("OperandSpacing"))); + + // Get the instruction numbering. + NumberedInstructions = Target.getInstructionsByEnumValue(); + + // Compute the CodeGenInstruction -> AsmWriterInst mapping. Note that not + // all machine instructions are necessarily being printed, so there may be + // target instructions not in this map. + for (unsigned i = 0, e = Instructions.size(); i != e; ++i) + CGIAWIMap.insert(std::make_pair(Instructions[i].CGI, &Instructions[i])); + + // Build an aggregate string, and build a table of offsets into it. + SequenceToOffsetTable<std::string> StringTable; + + /// OpcodeInfo - This encodes the index of the string to use for the first + /// chunk of the output as well as indices used for operand printing. + std::vector<unsigned> OpcodeInfo; + + // Add all strings to the string table upfront so it can generate an optimized + // representation. + for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { + AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]]; + if (AWI != 0 && + AWI->Operands[0].OperandType == + AsmWriterOperand::isLiteralTextOperand && + !AWI->Operands[0].Str.empty()) { + std::string Str = AWI->Operands[0].Str; + UnescapeString(Str); + StringTable.add(Str); + } + } + + StringTable.layout(); + + unsigned MaxStringIdx = 0; + for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { + AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]]; + unsigned Idx; + if (AWI == 0) { + // Something not handled by the asmwriter printer. + Idx = ~0U; + } else if (AWI->Operands[0].OperandType != + AsmWriterOperand::isLiteralTextOperand || + AWI->Operands[0].Str.empty()) { + // Something handled by the asmwriter printer, but with no leading string. + Idx = StringTable.get(""); + } else { + std::string Str = AWI->Operands[0].Str; + UnescapeString(Str); + Idx = StringTable.get(Str); + MaxStringIdx = std::max(MaxStringIdx, Idx); + + // Nuke the string from the operand list. It is now handled! + AWI->Operands.erase(AWI->Operands.begin()); + } + + // Bias offset by one since we want 0 as a sentinel. + OpcodeInfo.push_back(Idx+1); + } + + // Figure out how many bits we used for the string index. + unsigned AsmStrBits = Log2_32_Ceil(MaxStringIdx+2); + + // To reduce code size, we compactify common instructions into a few bits + // in the opcode-indexed table. + unsigned BitsLeft = 32-AsmStrBits; + + std::vector<std::vector<std::string> > TableDrivenOperandPrinters; + + while (1) { + std::vector<std::string> UniqueOperandCommands; + std::vector<unsigned> InstIdxs; + std::vector<unsigned> NumInstOpsHandled; + FindUniqueOperandCommands(UniqueOperandCommands, InstIdxs, + NumInstOpsHandled); + + // If we ran out of operands to print, we're done. + if (UniqueOperandCommands.empty()) break; + + // Compute the number of bits we need to represent these cases, this is + // ceil(log2(numentries)). + unsigned NumBits = Log2_32_Ceil(UniqueOperandCommands.size()); + + // If we don't have enough bits for this operand, don't include it. + if (NumBits > BitsLeft) { + DEBUG(errs() << "Not enough bits to densely encode " << NumBits + << " more bits\n"); + break; + } + + // Otherwise, we can include this in the initial lookup table. Add it in. + BitsLeft -= NumBits; + for (unsigned i = 0, e = InstIdxs.size(); i != e; ++i) + if (InstIdxs[i] != ~0U) + OpcodeInfo[i] |= InstIdxs[i] << (BitsLeft+AsmStrBits); + + // Remove the info about this operand. + for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { + if (AsmWriterInst *Inst = getAsmWriterInstByID(i)) + if (!Inst->Operands.empty()) { + unsigned NumOps = NumInstOpsHandled[InstIdxs[i]]; + assert(NumOps <= Inst->Operands.size() && + "Can't remove this many ops!"); + Inst->Operands.erase(Inst->Operands.begin(), + Inst->Operands.begin()+NumOps); + } + } + + // Remember the handlers for this set of operands. + TableDrivenOperandPrinters.push_back(UniqueOperandCommands); + } + + + + O<<" static const unsigned OpInfo[] = {\n"; + for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { + O << " " << OpcodeInfo[i] << "U,\t// " + << NumberedInstructions[i]->TheDef->getName() << "\n"; + } + // Add a dummy entry so the array init doesn't end with a comma. + O << " 0U\n"; + O << " };\n\n"; + + // Emit the string itself. + O << " const char AsmStrs[] = {\n"; + StringTable.emit(O, printChar); + O << " };\n\n"; + + O << " O << \"\\t\";\n\n"; + + O << " // Emit the opcode for the instruction.\n" + << " unsigned Bits = OpInfo[MI->getOpcode()];\n" + << " assert(Bits != 0 && \"Cannot print this instruction.\");\n" + << " O << AsmStrs+(Bits & " << (1 << AsmStrBits)-1 << ")-1;\n\n"; + + // Output the table driven operand information. + BitsLeft = 32-AsmStrBits; + for (unsigned i = 0, e = TableDrivenOperandPrinters.size(); i != e; ++i) { + std::vector<std::string> &Commands = TableDrivenOperandPrinters[i]; + + // Compute the number of bits we need to represent these cases, this is + // ceil(log2(numentries)). + unsigned NumBits = Log2_32_Ceil(Commands.size()); + assert(NumBits <= BitsLeft && "consistency error"); + + // Emit code to extract this field from Bits. + BitsLeft -= NumBits; + + O << "\n // Fragment " << i << " encoded into " << NumBits + << " bits for " << Commands.size() << " unique commands.\n"; + + if (Commands.size() == 2) { + // Emit two possibilitys with if/else. + O << " if ((Bits >> " << (BitsLeft+AsmStrBits) << ") & " + << ((1 << NumBits)-1) << ") {\n" + << Commands[1] + << " } else {\n" + << Commands[0] + << " }\n\n"; + } else if (Commands.size() == 1) { + // Emit a single possibility. + O << Commands[0] << "\n\n"; + } else { + O << " switch ((Bits >> " << (BitsLeft+AsmStrBits) << ") & " + << ((1 << NumBits)-1) << ") {\n" + << " default: // unreachable.\n"; + + // Print out all the cases. + for (unsigned i = 0, e = Commands.size(); i != e; ++i) { + O << " case " << i << ":\n"; + O << Commands[i]; + O << " break;\n"; + } + O << " }\n\n"; + } + } + + // Okay, delete instructions with no operand info left. + for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { + // Entire instruction has been emitted? + AsmWriterInst &Inst = Instructions[i]; + if (Inst.Operands.empty()) { + Instructions.erase(Instructions.begin()+i); + --i; --e; + } + } + + + // Because this is a vector, we want to emit from the end. Reverse all of the + // elements in the vector. + std::reverse(Instructions.begin(), Instructions.end()); + + + // Now that we've emitted all of the operand info that fit into 32 bits, emit + // information for those instructions that are left. This is a less dense + // encoding, but we expect the main 32-bit table to handle the majority of + // instructions. + if (!Instructions.empty()) { + // Find the opcode # of inline asm. + O << " switch (MI->getOpcode()) {\n"; + while (!Instructions.empty()) + EmitInstructions(Instructions, O); + + O << " }\n"; + O << " return;\n"; + } + + O << "}\n"; +} + +static void +emitRegisterNameString(raw_ostream &O, StringRef AltName, + const std::vector<CodeGenRegister*> &Registers) { + SequenceToOffsetTable<std::string> StringTable; + SmallVector<std::string, 4> AsmNames(Registers.size()); + for (unsigned i = 0, e = Registers.size(); i != e; ++i) { + const CodeGenRegister &Reg = *Registers[i]; + std::string &AsmName = AsmNames[i]; + + // "NoRegAltName" is special. We don't need to do a lookup for that, + // as it's just a reference to the default register name. + if (AltName == "" || AltName == "NoRegAltName") { + AsmName = Reg.TheDef->getValueAsString("AsmName"); + if (AsmName.empty()) + AsmName = Reg.getName(); + } else { + // Make sure the register has an alternate name for this index. + std::vector<Record*> AltNameList = + Reg.TheDef->getValueAsListOfDefs("RegAltNameIndices"); + unsigned Idx = 0, e; + for (e = AltNameList.size(); + Idx < e && (AltNameList[Idx]->getName() != AltName); + ++Idx) + ; + // If the register has an alternate name for this index, use it. + // Otherwise, leave it empty as an error flag. + if (Idx < e) { + std::vector<std::string> AltNames = + Reg.TheDef->getValueAsListOfStrings("AltNames"); + if (AltNames.size() <= Idx) + throw TGError(Reg.TheDef->getLoc(), + (Twine("Register definition missing alt name for '") + + AltName + "'.").str()); + AsmName = AltNames[Idx]; + } + } + StringTable.add(AsmName); + } + + StringTable.layout(); + O << " static const char AsmStrs" << AltName << "[] = {\n"; + StringTable.emit(O, printChar); + O << " };\n\n"; + + O << " static const unsigned RegAsmOffset" << AltName << "[] = {"; + for (unsigned i = 0, e = Registers.size(); i != e; ++i) { + if ((i % 14) == 0) + O << "\n "; + O << StringTable.get(AsmNames[i]) << ", "; + } + O << "\n };\n" + << "\n"; +} + +void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) { + CodeGenTarget Target(Records); + Record *AsmWriter = Target.getAsmWriter(); + std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); + const std::vector<CodeGenRegister*> &Registers = + Target.getRegBank().getRegisters(); + std::vector<Record*> AltNameIndices = Target.getRegAltNameIndices(); + bool hasAltNames = AltNameIndices.size() > 1; + + O << + "\n\n/// getRegisterName - This method is automatically generated by tblgen\n" + "/// from the register set description. This returns the assembler name\n" + "/// for the specified register.\n" + "const char *" << Target.getName() << ClassName << "::"; + if (hasAltNames) + O << "\ngetRegisterName(unsigned RegNo, unsigned AltIdx) {\n"; + else + O << "getRegisterName(unsigned RegNo) {\n"; + O << " assert(RegNo && RegNo < " << (Registers.size()+1) + << " && \"Invalid register number!\");\n" + << "\n"; + + if (hasAltNames) { + for (unsigned i = 0, e = AltNameIndices.size(); i < e; ++i) + emitRegisterNameString(O, AltNameIndices[i]->getName(), Registers); + } else + emitRegisterNameString(O, "", Registers); + + if (hasAltNames) { + O << " const unsigned *RegAsmOffset;\n" + << " const char *AsmStrs;\n" + << " switch(AltIdx) {\n" + << " default: llvm_unreachable(\"Invalid register alt name index!\");\n"; + for (unsigned i = 0, e = AltNameIndices.size(); i < e; ++i) { + StringRef Namespace = AltNameIndices[1]->getValueAsString("Namespace"); + StringRef AltName(AltNameIndices[i]->getName()); + O << " case " << Namespace << "::" << AltName + << ":\n" + << " AsmStrs = AsmStrs" << AltName << ";\n" + << " RegAsmOffset = RegAsmOffset" << AltName << ";\n" + << " break;\n"; + } + O << "}\n"; + } + + O << " assert (*(AsmStrs+RegAsmOffset[RegNo-1]) &&\n" + << " \"Invalid alt name index for register!\");\n" + << " return AsmStrs+RegAsmOffset[RegNo-1];\n" + << "}\n"; +} + +namespace { +// IAPrinter - Holds information about an InstAlias. Two InstAliases match if +// they both have the same conditionals. In which case, we cannot print out the +// alias for that pattern. +class IAPrinter { + std::vector<std::string> Conds; + std::map<StringRef, unsigned> OpMap; + std::string Result; + std::string AsmString; + SmallVector<Record*, 4> ReqFeatures; +public: + IAPrinter(std::string R, std::string AS) + : Result(R), AsmString(AS) {} + + void addCond(const std::string &C) { Conds.push_back(C); } + + void addOperand(StringRef Op, unsigned Idx) { OpMap[Op] = Idx; } + unsigned getOpIndex(StringRef Op) { return OpMap[Op]; } + bool isOpMapped(StringRef Op) { return OpMap.find(Op) != OpMap.end(); } + + void print(raw_ostream &O) { + if (Conds.empty() && ReqFeatures.empty()) { + O.indent(6) << "return true;\n"; + return; + } + + O << "if ("; + + for (std::vector<std::string>::iterator + I = Conds.begin(), E = Conds.end(); I != E; ++I) { + if (I != Conds.begin()) { + O << " &&\n"; + O.indent(8); + } + + O << *I; + } + + O << ") {\n"; + O.indent(6) << "// " << Result << "\n"; + O.indent(6) << "AsmString = \"" << AsmString << "\";\n"; + + for (std::map<StringRef, unsigned>::iterator + I = OpMap.begin(), E = OpMap.end(); I != E; ++I) + O.indent(6) << "OpMap.push_back(std::make_pair(\"" << I->first << "\", " + << I->second << "));\n"; + + O.indent(6) << "break;\n"; + O.indent(4) << '}'; + } + + bool operator==(const IAPrinter &RHS) { + if (Conds.size() != RHS.Conds.size()) + return false; + + unsigned Idx = 0; + for (std::vector<std::string>::iterator + I = Conds.begin(), E = Conds.end(); I != E; ++I) + if (*I != RHS.Conds[Idx++]) + return false; + + return true; + } + + bool operator()(const IAPrinter &RHS) { + if (Conds.size() < RHS.Conds.size()) + return true; + + unsigned Idx = 0; + for (std::vector<std::string>::iterator + I = Conds.begin(), E = Conds.end(); I != E; ++I) + if (*I != RHS.Conds[Idx++]) + return *I < RHS.Conds[Idx++]; + + return false; + } +}; + +} // end anonymous namespace + +static void EmitGetMapOperandNumber(raw_ostream &O) { + O << "static unsigned getMapOperandNumber(" + << "const SmallVectorImpl<std::pair<StringRef, unsigned> > &OpMap,\n"; + O << " StringRef Name) {\n"; + O << " for (SmallVectorImpl<std::pair<StringRef, unsigned> >::" + << "const_iterator\n"; + O << " I = OpMap.begin(), E = OpMap.end(); I != E; ++I)\n"; + O << " if (I->first == Name)\n"; + O << " return I->second;\n"; + O << " llvm_unreachable(\"Operand not in map!\");\n"; + O << "}\n\n"; +} + +static unsigned CountNumOperands(StringRef AsmString) { + unsigned NumOps = 0; + std::pair<StringRef, StringRef> ASM = AsmString.split(' '); + + while (!ASM.second.empty()) { + ++NumOps; + ASM = ASM.second.split(' '); + } + + return NumOps; +} + +static unsigned CountResultNumOperands(StringRef AsmString) { + unsigned NumOps = 0; + std::pair<StringRef, StringRef> ASM = AsmString.split('\t'); + + if (!ASM.second.empty()) { + size_t I = ASM.second.find('{'); + StringRef Str = ASM.second; + if (I != StringRef::npos) + Str = ASM.second.substr(I, ASM.second.find('|', I)); + + ASM = Str.split(' '); + + do { + ++NumOps; + ASM = ASM.second.split(' '); + } while (!ASM.second.empty()); + } + + return NumOps; +} + +void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { + CodeGenTarget Target(Records); + Record *AsmWriter = Target.getAsmWriter(); + + if (!AsmWriter->getValueAsBit("isMCAsmWriter")) + return; + + O << "\n#ifdef PRINT_ALIAS_INSTR\n"; + O << "#undef PRINT_ALIAS_INSTR\n\n"; + + // Emit the method that prints the alias instruction. + std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); + + std::vector<Record*> AllInstAliases = + Records.getAllDerivedDefinitions("InstAlias"); + + // Create a map from the qualified name to a list of potential matches. + std::map<std::string, std::vector<CodeGenInstAlias*> > AliasMap; + for (std::vector<Record*>::iterator + I = AllInstAliases.begin(), E = AllInstAliases.end(); I != E; ++I) { + CodeGenInstAlias *Alias = new CodeGenInstAlias(*I, Target); + const Record *R = *I; + if (!R->getValueAsBit("EmitAlias")) + continue; // We were told not to emit the alias, but to emit the aliasee. + const DagInit *DI = R->getValueAsDag("ResultInst"); + const DefInit *Op = dynamic_cast<const DefInit*>(DI->getOperator()); + AliasMap[getQualifiedName(Op->getDef())].push_back(Alias); + } + + // A map of which conditions need to be met for each instruction operand + // before it can be matched to the mnemonic. + std::map<std::string, std::vector<IAPrinter*> > IAPrinterMap; + + for (std::map<std::string, std::vector<CodeGenInstAlias*> >::iterator + I = AliasMap.begin(), E = AliasMap.end(); I != E; ++I) { + std::vector<CodeGenInstAlias*> &Aliases = I->second; + + for (std::vector<CodeGenInstAlias*>::iterator + II = Aliases.begin(), IE = Aliases.end(); II != IE; ++II) { + const CodeGenInstAlias *CGA = *II; + unsigned LastOpNo = CGA->ResultInstOperandIndex.size(); + unsigned NumResultOps = + CountResultNumOperands(CGA->ResultInst->AsmString); + + // Don't emit the alias if it has more operands than what it's aliasing. + if (NumResultOps < CountNumOperands(CGA->AsmString)) + continue; + + IAPrinter *IAP = new IAPrinter(CGA->Result->getAsString(), + CGA->AsmString); + + std::string Cond; + Cond = std::string("MI->getNumOperands() == ") + llvm::utostr(LastOpNo); + IAP->addCond(Cond); + + std::map<StringRef, unsigned> OpMap; + bool CantHandle = false; + + for (unsigned i = 0, e = LastOpNo; i != e; ++i) { + const CodeGenInstAlias::ResultOperand &RO = CGA->ResultOperands[i]; + + switch (RO.Kind) { + case CodeGenInstAlias::ResultOperand::K_Record: { + const Record *Rec = RO.getRecord(); + StringRef ROName = RO.getName(); + + + if (Rec->isSubClassOf("RegisterOperand")) + Rec = Rec->getValueAsDef("RegClass"); + if (Rec->isSubClassOf("RegisterClass")) { + Cond = std::string("MI->getOperand(")+llvm::utostr(i)+").isReg()"; + IAP->addCond(Cond); + + if (!IAP->isOpMapped(ROName)) { + IAP->addOperand(ROName, i); + Cond = std::string("MRI.getRegClass(") + Target.getName() + "::" + + CGA->ResultOperands[i].getRecord()->getName() + "RegClassID)" + ".contains(MI->getOperand(" + llvm::utostr(i) + ").getReg())"; + IAP->addCond(Cond); + } else { + Cond = std::string("MI->getOperand(") + + llvm::utostr(i) + ").getReg() == MI->getOperand(" + + llvm::utostr(IAP->getOpIndex(ROName)) + ").getReg()"; + IAP->addCond(Cond); + } + } else { + assert(Rec->isSubClassOf("Operand") && "Unexpected operand!"); + // FIXME: We may need to handle these situations. + delete IAP; + IAP = 0; + CantHandle = true; + break; + } + + break; + } + case CodeGenInstAlias::ResultOperand::K_Imm: + Cond = std::string("MI->getOperand(") + + llvm::utostr(i) + ").getImm() == " + + llvm::utostr(CGA->ResultOperands[i].getImm()); + IAP->addCond(Cond); + break; + case CodeGenInstAlias::ResultOperand::K_Reg: + // If this is zero_reg, something's playing tricks we're not + // equipped to handle. + if (!CGA->ResultOperands[i].getRegister()) { + CantHandle = true; + break; + } + + Cond = std::string("MI->getOperand(") + + llvm::utostr(i) + ").getReg() == " + Target.getName() + + "::" + CGA->ResultOperands[i].getRegister()->getName(); + IAP->addCond(Cond); + break; + } + + if (!IAP) break; + } + + if (CantHandle) continue; + IAPrinterMap[I->first].push_back(IAP); + } + } + + std::string Header; + raw_string_ostream HeaderO(Header); + + HeaderO << "bool " << Target.getName() << ClassName + << "::printAliasInstr(const MCInst" + << " *MI, raw_ostream &OS) {\n"; + + std::string Cases; + raw_string_ostream CasesO(Cases); + + for (std::map<std::string, std::vector<IAPrinter*> >::iterator + I = IAPrinterMap.begin(), E = IAPrinterMap.end(); I != E; ++I) { + std::vector<IAPrinter*> &IAPs = I->second; + std::vector<IAPrinter*> UniqueIAPs; + + for (std::vector<IAPrinter*>::iterator + II = IAPs.begin(), IE = IAPs.end(); II != IE; ++II) { + IAPrinter *LHS = *II; + bool IsDup = false; + for (std::vector<IAPrinter*>::iterator + III = IAPs.begin(), IIE = IAPs.end(); III != IIE; ++III) { + IAPrinter *RHS = *III; + if (LHS != RHS && *LHS == *RHS) { + IsDup = true; + break; + } + } + + if (!IsDup) UniqueIAPs.push_back(LHS); + } + + if (UniqueIAPs.empty()) continue; + + CasesO.indent(2) << "case " << I->first << ":\n"; + + for (std::vector<IAPrinter*>::iterator + II = UniqueIAPs.begin(), IE = UniqueIAPs.end(); II != IE; ++II) { + IAPrinter *IAP = *II; + CasesO.indent(4); + IAP->print(CasesO); + CasesO << '\n'; + } + + CasesO.indent(4) << "return false;\n"; + } + + if (CasesO.str().empty()) { + O << HeaderO.str(); + O << " return false;\n"; + O << "}\n\n"; + O << "#endif // PRINT_ALIAS_INSTR\n"; + return; + } + + EmitGetMapOperandNumber(O); + + O << HeaderO.str(); + O.indent(2) << "StringRef AsmString;\n"; + O.indent(2) << "SmallVector<std::pair<StringRef, unsigned>, 4> OpMap;\n"; + O.indent(2) << "switch (MI->getOpcode()) {\n"; + O.indent(2) << "default: return false;\n"; + O << CasesO.str(); + O.indent(2) << "}\n\n"; + + // Code that prints the alias, replacing the operands with the ones from the + // MCInst. + O << " std::pair<StringRef, StringRef> ASM = AsmString.split(' ');\n"; + O << " OS << '\\t' << ASM.first;\n"; + + O << " if (!ASM.second.empty()) {\n"; + O << " OS << '\\t';\n"; + O << " for (StringRef::iterator\n"; + O << " I = ASM.second.begin(), E = ASM.second.end(); I != E; ) {\n"; + O << " if (*I == '$') {\n"; + O << " StringRef::iterator Start = ++I;\n"; + O << " while (I != E &&\n"; + O << " ((*I >= 'a' && *I <= 'z') ||\n"; + O << " (*I >= 'A' && *I <= 'Z') ||\n"; + O << " (*I >= '0' && *I <= '9') ||\n"; + O << " *I == '_'))\n"; + O << " ++I;\n"; + O << " StringRef Name(Start, I - Start);\n"; + O << " printOperand(MI, getMapOperandNumber(OpMap, Name), OS);\n"; + O << " } else {\n"; + O << " OS << *I++;\n"; + O << " }\n"; + O << " }\n"; + O << " }\n\n"; + + O << " return true;\n"; + O << "}\n\n"; + + O << "#endif // PRINT_ALIAS_INSTR\n"; +} + +void AsmWriterEmitter::run(raw_ostream &O) { + EmitSourceFileHeader("Assembly Writer Source Fragment", O); + + EmitPrintInstruction(O); + EmitGetRegisterName(O); + EmitPrintAliasInstruction(O); +} + diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.h b/contrib/llvm/utils/TableGen/AsmWriterEmitter.h new file mode 100644 index 0000000..9719b20 --- /dev/null +++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.h @@ -0,0 +1,54 @@ +//===- AsmWriterEmitter.h - Generate an assembly writer ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend is responsible for emitting an assembly printer for the +// code generator. +// +//===----------------------------------------------------------------------===// + +#ifndef ASMWRITER_EMITTER_H +#define ASMWRITER_EMITTER_H + +#include "llvm/TableGen/TableGenBackend.h" +#include <map> +#include <vector> +#include <cassert> + +namespace llvm { + class AsmWriterInst; + class CodeGenInstruction; + + class AsmWriterEmitter : public TableGenBackend { + RecordKeeper &Records; + std::map<const CodeGenInstruction*, AsmWriterInst*> CGIAWIMap; + std::vector<const CodeGenInstruction*> NumberedInstructions; + public: + AsmWriterEmitter(RecordKeeper &R) : Records(R) {} + + // run - Output the asmwriter, returning true on failure. + void run(raw_ostream &o); + +private: + void EmitPrintInstruction(raw_ostream &o); + void EmitGetRegisterName(raw_ostream &o); + void EmitPrintAliasInstruction(raw_ostream &O); + + AsmWriterInst *getAsmWriterInstByID(unsigned ID) const { + assert(ID < NumberedInstructions.size()); + std::map<const CodeGenInstruction*, AsmWriterInst*>::const_iterator I = + CGIAWIMap.find(NumberedInstructions[ID]); + assert(I != CGIAWIMap.end() && "Didn't find inst!"); + return I->second; + } + void FindUniqueOperandCommands(std::vector<std::string> &UOC, + std::vector<unsigned> &InstIdxs, + std::vector<unsigned> &InstOpsUsed) const; + }; +} +#endif diff --git a/contrib/llvm/utils/TableGen/AsmWriterInst.cpp b/contrib/llvm/utils/TableGen/AsmWriterInst.cpp new file mode 100644 index 0000000..350a2cc --- /dev/null +++ b/contrib/llvm/utils/TableGen/AsmWriterInst.cpp @@ -0,0 +1,233 @@ +//===- AsmWriterInst.h - Classes encapsulating a printable inst -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// These classes implement a parser for assembly strings. +// +//===----------------------------------------------------------------------===// + +#include "AsmWriterInst.h" +#include "CodeGenTarget.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/TableGen/Record.h" + +using namespace llvm; + +static bool isIdentChar(char C) { + return (C >= 'a' && C <= 'z') || + (C >= 'A' && C <= 'Z') || + (C >= '0' && C <= '9') || + C == '_'; +} + +std::string AsmWriterOperand::getCode() const { + if (OperandType == isLiteralTextOperand) { + if (Str.size() == 1) + return "O << '" + Str + "'; "; + return "O << \"" + Str + "\"; "; + } + + if (OperandType == isLiteralStatementOperand) + return Str; + + std::string Result = Str + "(MI"; + if (MIOpNo != ~0U) + Result += ", " + utostr(MIOpNo); + Result += ", O"; + if (!MiModifier.empty()) + Result += ", \"" + MiModifier + '"'; + return Result + "); "; +} + +/// ParseAsmString - Parse the specified Instruction's AsmString into this +/// AsmWriterInst. +/// +AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, + unsigned Variant, + int FirstOperandColumn, + int OperandSpacing) { + this->CGI = &CGI; + + // This is the number of tabs we've seen if we're doing columnar layout. + unsigned CurColumn = 0; + + + // NOTE: Any extensions to this code need to be mirrored in the + // AsmPrinter::printInlineAsm code that executes as compile time (assuming + // that inline asm strings should also get the new feature)! + std::string AsmString = CGI.FlattenAsmStringVariants(CGI.AsmString, Variant); + std::string::size_type LastEmitted = 0; + while (LastEmitted != AsmString.size()) { + std::string::size_type DollarPos = + AsmString.find_first_of("$\\", LastEmitted); + if (DollarPos == std::string::npos) DollarPos = AsmString.size(); + + // Emit a constant string fragment. + if (DollarPos != LastEmitted) { + for (; LastEmitted != DollarPos; ++LastEmitted) + switch (AsmString[LastEmitted]) { + case '\n': + AddLiteralString("\\n"); + break; + case '\t': + // If the asm writer is not using a columnar layout, \t is not + // magic. + if (FirstOperandColumn == -1 || OperandSpacing == -1) { + AddLiteralString("\\t"); + } else { + // We recognize a tab as an operand delimeter. + unsigned DestColumn = FirstOperandColumn + + CurColumn++ * OperandSpacing; + Operands.push_back( + AsmWriterOperand( + "O.PadToColumn(" + + utostr(DestColumn) + ");\n", + AsmWriterOperand::isLiteralStatementOperand)); + } + break; + case '"': + AddLiteralString("\\\""); + break; + case '\\': + AddLiteralString("\\\\"); + break; + default: + AddLiteralString(std::string(1, AsmString[LastEmitted])); + break; + } + } else if (AsmString[DollarPos] == '\\') { + if (DollarPos+1 != AsmString.size()) { + if (AsmString[DollarPos+1] == 'n') { + AddLiteralString("\\n"); + } else if (AsmString[DollarPos+1] == 't') { + // If the asm writer is not using a columnar layout, \t is not + // magic. + if (FirstOperandColumn == -1 || OperandSpacing == -1) { + AddLiteralString("\\t"); + break; + } + + // We recognize a tab as an operand delimeter. + unsigned DestColumn = FirstOperandColumn + + CurColumn++ * OperandSpacing; + Operands.push_back( + AsmWriterOperand("O.PadToColumn(" + utostr(DestColumn) + ");\n", + AsmWriterOperand::isLiteralStatementOperand)); + break; + } else if (std::string("${|}\\").find(AsmString[DollarPos+1]) + != std::string::npos) { + AddLiteralString(std::string(1, AsmString[DollarPos+1])); + } else { + throw "Non-supported escaped character found in instruction '" + + CGI.TheDef->getName() + "'!"; + } + LastEmitted = DollarPos+2; + continue; + } + } else if (DollarPos+1 != AsmString.size() && + AsmString[DollarPos+1] == '$') { + AddLiteralString("$"); // "$$" -> $ + LastEmitted = DollarPos+2; + } else { + // Get the name of the variable. + std::string::size_type VarEnd = DollarPos+1; + + // handle ${foo}bar as $foo by detecting whether the character following + // the dollar sign is a curly brace. If so, advance VarEnd and DollarPos + // so the variable name does not contain the leading curly brace. + bool hasCurlyBraces = false; + if (VarEnd < AsmString.size() && '{' == AsmString[VarEnd]) { + hasCurlyBraces = true; + ++DollarPos; + ++VarEnd; + } + + while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd])) + ++VarEnd; + std::string VarName(AsmString.begin()+DollarPos+1, + AsmString.begin()+VarEnd); + + // Modifier - Support ${foo:modifier} syntax, where "modifier" is passed + // into printOperand. Also support ${:feature}, which is passed into + // PrintSpecial. + std::string Modifier; + + // In order to avoid starting the next string at the terminating curly + // brace, advance the end position past it if we found an opening curly + // brace. + if (hasCurlyBraces) { + if (VarEnd >= AsmString.size()) + throw "Reached end of string before terminating curly brace in '" + + CGI.TheDef->getName() + "'"; + + // Look for a modifier string. + if (AsmString[VarEnd] == ':') { + ++VarEnd; + if (VarEnd >= AsmString.size()) + throw "Reached end of string before terminating curly brace in '" + + CGI.TheDef->getName() + "'"; + + unsigned ModifierStart = VarEnd; + while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd])) + ++VarEnd; + Modifier = std::string(AsmString.begin()+ModifierStart, + AsmString.begin()+VarEnd); + if (Modifier.empty()) + throw "Bad operand modifier name in '"+ CGI.TheDef->getName() + "'"; + } + + if (AsmString[VarEnd] != '}') + throw "Variable name beginning with '{' did not end with '}' in '" + + CGI.TheDef->getName() + "'"; + ++VarEnd; + } + if (VarName.empty() && Modifier.empty()) + throw "Stray '$' in '" + CGI.TheDef->getName() + + "' asm string, maybe you want $$?"; + + if (VarName.empty()) { + // Just a modifier, pass this into PrintSpecial. + Operands.push_back(AsmWriterOperand("PrintSpecial", + ~0U, + ~0U, + Modifier)); + } else { + // Otherwise, normal operand. + unsigned OpNo = CGI.Operands.getOperandNamed(VarName); + CGIOperandList::OperandInfo OpInfo = CGI.Operands[OpNo]; + + unsigned MIOp = OpInfo.MIOperandNo; + Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName, + OpNo, MIOp, Modifier)); + } + LastEmitted = VarEnd; + } + } + + Operands.push_back(AsmWriterOperand("return;", + AsmWriterOperand::isLiteralStatementOperand)); +} + +/// MatchesAllButOneOp - If this instruction is exactly identical to the +/// specified instruction except for one differing operand, return the differing +/// operand number. If more than one operand mismatches, return ~1, otherwise +/// if the instructions are identical return ~0. +unsigned AsmWriterInst::MatchesAllButOneOp(const AsmWriterInst &Other)const{ + if (Operands.size() != Other.Operands.size()) return ~1; + + unsigned MismatchOperand = ~0U; + for (unsigned i = 0, e = Operands.size(); i != e; ++i) { + if (Operands[i] != Other.Operands[i]) { + if (MismatchOperand != ~0U) // Already have one mismatch? + return ~1U; + else + MismatchOperand = i; + } + } + return MismatchOperand; +} diff --git a/contrib/llvm/utils/TableGen/AsmWriterInst.h b/contrib/llvm/utils/TableGen/AsmWriterInst.h new file mode 100644 index 0000000..ec7d8eb --- /dev/null +++ b/contrib/llvm/utils/TableGen/AsmWriterInst.h @@ -0,0 +1,113 @@ +//===- AsmWriterInst.h - Classes encapsulating a printable inst -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// These classes implement a parser for assembly strings. The parser splits +// the string into operands, which can be literal strings (the constant bits of +// the string), actual operands (i.e., operands from the MachineInstr), and +// dynamically-generated text, specified by raw C++ code. +// +//===----------------------------------------------------------------------===// + +#ifndef ASMWRITER_INST_H +#define ASMWRITER_INST_H + +#include <string> +#include <vector> + +namespace llvm { + class CodeGenInstruction; + class Record; + + struct AsmWriterOperand { + enum OpType { + // Output this text surrounded by quotes to the asm. + isLiteralTextOperand, + // This is the name of a routine to call to print the operand. + isMachineInstrOperand, + // Output this text verbatim to the asm writer. It is code that + // will output some text to the asm. + isLiteralStatementOperand + } OperandType; + + /// Str - For isLiteralTextOperand, this IS the literal text. For + /// isMachineInstrOperand, this is the PrinterMethodName for the operand.. + /// For isLiteralStatementOperand, this is the code to insert verbatim + /// into the asm writer. + std::string Str; + + /// CGIOpNo - For isMachineInstrOperand, this is the index of the operand in + /// the CodeGenInstruction. + unsigned CGIOpNo; + + /// MiOpNo - For isMachineInstrOperand, this is the operand number of the + /// machine instruction. + unsigned MIOpNo; + + /// MiModifier - For isMachineInstrOperand, this is the modifier string for + /// an operand, specified with syntax like ${opname:modifier}. + std::string MiModifier; + + // To make VS STL happy + AsmWriterOperand(OpType op = isLiteralTextOperand):OperandType(op) {} + + AsmWriterOperand(const std::string &LitStr, + OpType op = isLiteralTextOperand) + : OperandType(op), Str(LitStr) {} + + AsmWriterOperand(const std::string &Printer, + unsigned _CGIOpNo, + unsigned _MIOpNo, + const std::string &Modifier, + OpType op = isMachineInstrOperand) + : OperandType(op), Str(Printer), CGIOpNo(_CGIOpNo), MIOpNo(_MIOpNo), + MiModifier(Modifier) {} + + bool operator!=(const AsmWriterOperand &Other) const { + if (OperandType != Other.OperandType || Str != Other.Str) return true; + if (OperandType == isMachineInstrOperand) + return MIOpNo != Other.MIOpNo || MiModifier != Other.MiModifier; + return false; + } + bool operator==(const AsmWriterOperand &Other) const { + return !operator!=(Other); + } + + /// getCode - Return the code that prints this operand. + std::string getCode() const; + }; + + class AsmWriterInst { + public: + std::vector<AsmWriterOperand> Operands; + const CodeGenInstruction *CGI; + + AsmWriterInst(const CodeGenInstruction &CGI, + unsigned Variant, + int FirstOperandColumn, + int OperandSpacing); + + /// MatchesAllButOneOp - If this instruction is exactly identical to the + /// specified instruction except for one differing operand, return the + /// differing operand number. Otherwise return ~0. + unsigned MatchesAllButOneOp(const AsmWriterInst &Other) const; + + private: + void AddLiteralString(const std::string &Str) { + // If the last operand was already a literal text string, append this to + // it, otherwise add a new operand. + if (!Operands.empty() && + Operands.back().OperandType == AsmWriterOperand::isLiteralTextOperand) + Operands.back().Str.append(Str); + else + Operands.push_back(AsmWriterOperand(Str)); + } + }; +} + +#endif diff --git a/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp b/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp new file mode 100644 index 0000000..afbb3a8 --- /dev/null +++ b/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp @@ -0,0 +1,212 @@ +//===- CallingConvEmitter.cpp - Generate calling conventions --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend is responsible for emitting descriptions of the calling +// conventions supported by this target. +// +//===----------------------------------------------------------------------===// + +#include "CallingConvEmitter.h" +#include "CodeGenTarget.h" +#include "llvm/TableGen/Record.h" +using namespace llvm; + +void CallingConvEmitter::run(raw_ostream &O) { + EmitSourceFileHeader("Calling Convention Implementation Fragment", O); + + std::vector<Record*> CCs = Records.getAllDerivedDefinitions("CallingConv"); + + // Emit prototypes for all of the CC's so that they can forward ref each + // other. + for (unsigned i = 0, e = CCs.size(); i != e; ++i) { + O << "static bool " << CCs[i]->getName() + << "(unsigned ValNo, MVT ValVT,\n" + << std::string(CCs[i]->getName().size()+13, ' ') + << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n" + << std::string(CCs[i]->getName().size()+13, ' ') + << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n"; + } + + // Emit each calling convention description in full. + for (unsigned i = 0, e = CCs.size(); i != e; ++i) + EmitCallingConv(CCs[i], O); +} + + +void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) { + ListInit *CCActions = CC->getValueAsListInit("Actions"); + Counter = 0; + + O << "\n\nstatic bool " << CC->getName() + << "(unsigned ValNo, MVT ValVT,\n" + << std::string(CC->getName().size()+13, ' ') + << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n" + << std::string(CC->getName().size()+13, ' ') + << "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n"; + // Emit all of the actions, in order. + for (unsigned i = 0, e = CCActions->getSize(); i != e; ++i) { + O << "\n"; + EmitAction(CCActions->getElementAsRecord(i), 2, O); + } + + O << "\n return true; // CC didn't match.\n"; + O << "}\n"; +} + +void CallingConvEmitter::EmitAction(Record *Action, + unsigned Indent, raw_ostream &O) { + std::string IndentStr = std::string(Indent, ' '); + + if (Action->isSubClassOf("CCPredicateAction")) { + O << IndentStr << "if ("; + + if (Action->isSubClassOf("CCIfType")) { + ListInit *VTs = Action->getValueAsListInit("VTs"); + for (unsigned i = 0, e = VTs->getSize(); i != e; ++i) { + Record *VT = VTs->getElementAsRecord(i); + if (i != 0) O << " ||\n " << IndentStr; + O << "LocVT == " << getEnumName(getValueType(VT)); + } + + } else if (Action->isSubClassOf("CCIf")) { + O << Action->getValueAsString("Predicate"); + } else { + Action->dump(); + throw "Unknown CCPredicateAction!"; + } + + O << ") {\n"; + EmitAction(Action->getValueAsDef("SubAction"), Indent+2, O); + O << IndentStr << "}\n"; + } else { + if (Action->isSubClassOf("CCDelegateTo")) { + Record *CC = Action->getValueAsDef("CC"); + O << IndentStr << "if (!" << CC->getName() + << "(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))\n" + << IndentStr << " return false;\n"; + } else if (Action->isSubClassOf("CCAssignToReg")) { + ListInit *RegList = Action->getValueAsListInit("RegList"); + if (RegList->getSize() == 1) { + O << IndentStr << "if (unsigned Reg = State.AllocateReg("; + O << getQualifiedName(RegList->getElementAsRecord(0)) << ")) {\n"; + } else { + O << IndentStr << "static const uint16_t RegList" << ++Counter + << "[] = {\n"; + O << IndentStr << " "; + for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) { + if (i != 0) O << ", "; + O << getQualifiedName(RegList->getElementAsRecord(i)); + } + O << "\n" << IndentStr << "};\n"; + O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList" + << Counter << ", " << RegList->getSize() << ")) {\n"; + } + O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, " + << "Reg, LocVT, LocInfo));\n"; + O << IndentStr << " return false;\n"; + O << IndentStr << "}\n"; + } else if (Action->isSubClassOf("CCAssignToRegWithShadow")) { + ListInit *RegList = Action->getValueAsListInit("RegList"); + ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList"); + if (ShadowRegList->getSize() >0 && + ShadowRegList->getSize() != RegList->getSize()) + throw "Invalid length of list of shadowed registers"; + + if (RegList->getSize() == 1) { + O << IndentStr << "if (unsigned Reg = State.AllocateReg("; + O << getQualifiedName(RegList->getElementAsRecord(0)); + O << ", " << getQualifiedName(ShadowRegList->getElementAsRecord(0)); + O << ")) {\n"; + } else { + unsigned RegListNumber = ++Counter; + unsigned ShadowRegListNumber = ++Counter; + + O << IndentStr << "static const uint16_t RegList" << RegListNumber + << "[] = {\n"; + O << IndentStr << " "; + for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) { + if (i != 0) O << ", "; + O << getQualifiedName(RegList->getElementAsRecord(i)); + } + O << "\n" << IndentStr << "};\n"; + + O << IndentStr << "static const uint16_t RegList" + << ShadowRegListNumber << "[] = {\n"; + O << IndentStr << " "; + for (unsigned i = 0, e = ShadowRegList->getSize(); i != e; ++i) { + if (i != 0) O << ", "; + O << getQualifiedName(ShadowRegList->getElementAsRecord(i)); + } + O << "\n" << IndentStr << "};\n"; + + O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList" + << RegListNumber << ", " << "RegList" << ShadowRegListNumber + << ", " << RegList->getSize() << ")) {\n"; + } + O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, " + << "Reg, LocVT, LocInfo));\n"; + O << IndentStr << " return false;\n"; + O << IndentStr << "}\n"; + } else if (Action->isSubClassOf("CCAssignToStack")) { + int Size = Action->getValueAsInt("Size"); + int Align = Action->getValueAsInt("Align"); + + O << IndentStr << "unsigned Offset" << ++Counter + << " = State.AllocateStack("; + if (Size) + O << Size << ", "; + else + O << "\n" << IndentStr << " State.getTarget().getTargetData()" + "->getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())), "; + if (Align) + O << Align; + else + O << "\n" << IndentStr << " State.getTarget().getTargetData()" + "->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()))"; + if (Action->isSubClassOf("CCAssignToStackWithShadow")) + O << ", " << getQualifiedName(Action->getValueAsDef("ShadowReg")); + O << ");\n" << IndentStr + << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset" + << Counter << ", LocVT, LocInfo));\n"; + O << IndentStr << "return false;\n"; + } else if (Action->isSubClassOf("CCPromoteToType")) { + Record *DestTy = Action->getValueAsDef("DestTy"); + O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n"; + O << IndentStr << "if (ArgFlags.isSExt())\n" + << IndentStr << IndentStr << "LocInfo = CCValAssign::SExt;\n" + << IndentStr << "else if (ArgFlags.isZExt())\n" + << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExt;\n" + << IndentStr << "else\n" + << IndentStr << IndentStr << "LocInfo = CCValAssign::AExt;\n"; + } else if (Action->isSubClassOf("CCBitConvertToType")) { + Record *DestTy = Action->getValueAsDef("DestTy"); + O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n"; + O << IndentStr << "LocInfo = CCValAssign::BCvt;\n"; + } else if (Action->isSubClassOf("CCPassIndirect")) { + Record *DestTy = Action->getValueAsDef("DestTy"); + O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n"; + O << IndentStr << "LocInfo = CCValAssign::Indirect;\n"; + } else if (Action->isSubClassOf("CCPassByVal")) { + int Size = Action->getValueAsInt("Size"); + int Align = Action->getValueAsInt("Align"); + O << IndentStr + << "State.HandleByVal(ValNo, ValVT, LocVT, LocInfo, " + << Size << ", " << Align << ", ArgFlags);\n"; + O << IndentStr << "return false;\n"; + } else if (Action->isSubClassOf("CCCustom")) { + O << IndentStr + << "if (" << Action->getValueAsString("FuncName") << "(ValNo, ValVT, " + << "LocVT, LocInfo, ArgFlags, State))\n"; + O << IndentStr << IndentStr << "return false;\n"; + } else { + Action->dump(); + throw "Unknown CCAction!"; + } + } +} diff --git a/contrib/llvm/utils/TableGen/CallingConvEmitter.h b/contrib/llvm/utils/TableGen/CallingConvEmitter.h new file mode 100644 index 0000000..7bddd6c --- /dev/null +++ b/contrib/llvm/utils/TableGen/CallingConvEmitter.h @@ -0,0 +1,36 @@ +//===- CallingConvEmitter.h - Generate calling conventions ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend is responsible for emitting descriptions of the calling +// conventions supported by this target. +// +//===----------------------------------------------------------------------===// + +#ifndef CALLINGCONV_EMITTER_H +#define CALLINGCONV_EMITTER_H + +#include "llvm/TableGen/TableGenBackend.h" +#include <cassert> + +namespace llvm { + class CallingConvEmitter : public TableGenBackend { + RecordKeeper &Records; + public: + explicit CallingConvEmitter(RecordKeeper &R) : Records(R) {} + + // run - Output the asmwriter, returning true on failure. + void run(raw_ostream &o); + + private: + void EmitCallingConv(Record *CC, raw_ostream &O); + void EmitAction(Record *Action, unsigned Indent, raw_ostream &O); + unsigned Counter; + }; +} +#endif diff --git a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp new file mode 100644 index 0000000..3943e8a --- /dev/null +++ b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp @@ -0,0 +1,306 @@ +//===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// CodeEmitterGen uses the descriptions of instructions and their fields to +// construct an automated code emitter: a function that, given a MachineInstr, +// returns the (currently, 32-bit unsigned) value of the instruction. +// +//===----------------------------------------------------------------------===// + +#include "CodeEmitterGen.h" +#include "CodeGenTarget.h" +#include "llvm/TableGen/Record.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include <map> +using namespace llvm; + +// FIXME: Somewhat hackish to use a command line option for this. There should +// be a CodeEmitter class in the Target.td that controls this sort of thing +// instead. +static cl::opt<bool> +MCEmitter("mc-emitter", + cl::desc("Generate CodeEmitter for use with the MC library."), + cl::init(false)); + +void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) { + for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end(); + I != E; ++I) { + Record *R = *I; + if (R->getValueAsString("Namespace") == "TargetOpcode" || + R->getValueAsBit("isPseudo")) + continue; + + BitsInit *BI = R->getValueAsBitsInit("Inst"); + + unsigned numBits = BI->getNumBits(); + + SmallVector<Init *, 16> NewBits(numBits); + + for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) { + unsigned bitSwapIdx = numBits - bit - 1; + Init *OrigBit = BI->getBit(bit); + Init *BitSwap = BI->getBit(bitSwapIdx); + NewBits[bit] = BitSwap; + NewBits[bitSwapIdx] = OrigBit; + } + if (numBits % 2) { + unsigned middle = (numBits + 1) / 2; + NewBits[middle] = BI->getBit(middle); + } + + BitsInit *NewBI = BitsInit::get(NewBits); + + // Update the bits in reversed order so that emitInstrOpBits will get the + // correct endianness. + R->getValue("Inst")->setValue(NewBI); + } +} + +// If the VarBitInit at position 'bit' matches the specified variable then +// return the variable bit position. Otherwise return -1. +int CodeEmitterGen::getVariableBit(const std::string &VarName, + BitsInit *BI, int bit) { + if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(BI->getBit(bit))) { + if (VarInit *VI = dynamic_cast<VarInit*>(VBI->getVariable())) + if (VI->getName() == VarName) + return VBI->getBitNum(); + } else if (VarInit *VI = dynamic_cast<VarInit*>(BI->getBit(bit))) { + if (VI->getName() == VarName) + return 0; + } + + return -1; +} + +void CodeEmitterGen:: +AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, + unsigned &NumberedOp, + std::string &Case, CodeGenTarget &Target) { + CodeGenInstruction &CGI = Target.getInstruction(R); + + // Determine if VarName actually contributes to the Inst encoding. + int bit = BI->getNumBits()-1; + + // Scan for a bit that this contributed to. + for (; bit >= 0; ) { + if (getVariableBit(VarName, BI, bit) != -1) + break; + + --bit; + } + + // If we found no bits, ignore this value, otherwise emit the call to get the + // operand encoding. + if (bit < 0) return; + + // If the operand matches by name, reference according to that + // operand number. Non-matching operands are assumed to be in + // order. + unsigned OpIdx; + if (CGI.Operands.hasOperandNamed(VarName, OpIdx)) { + // Get the machine operand number for the indicated operand. + OpIdx = CGI.Operands[OpIdx].MIOperandNo; + assert(!CGI.Operands.isFlatOperandNotEmitted(OpIdx) && + "Explicitly used operand also marked as not emitted!"); + } else { + /// If this operand is not supposed to be emitted by the + /// generated emitter, skip it. + while (CGI.Operands.isFlatOperandNotEmitted(NumberedOp)) + ++NumberedOp; + OpIdx = NumberedOp++; + } + + std::pair<unsigned, unsigned> SO = CGI.Operands.getSubOperandNumber(OpIdx); + std::string &EncoderMethodName = CGI.Operands[SO.first].EncoderMethodName; + + // If the source operand has a custom encoder, use it. This will + // get the encoding for all of the suboperands. + if (!EncoderMethodName.empty()) { + // A custom encoder has all of the information for the + // sub-operands, if there are more than one, so only + // query the encoder once per source operand. + if (SO.second == 0) { + Case += " // op: " + VarName + "\n" + + " op = " + EncoderMethodName + "(MI, " + utostr(OpIdx); + if (MCEmitter) + Case += ", Fixups"; + Case += ");\n"; + } + } else { + Case += " // op: " + VarName + "\n" + + " op = getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")"; + if (MCEmitter) + Case += ", Fixups"; + Case += ");\n"; + } + + for (; bit >= 0; ) { + int varBit = getVariableBit(VarName, BI, bit); + + // If this bit isn't from a variable, skip it. + if (varBit == -1) { + --bit; + continue; + } + + // Figure out the consecutive range of bits covered by this operand, in + // order to generate better encoding code. + int beginInstBit = bit; + int beginVarBit = varBit; + int N = 1; + for (--bit; bit >= 0;) { + varBit = getVariableBit(VarName, BI, bit); + if (varBit == -1 || varBit != (beginVarBit - N)) break; + ++N; + --bit; + } + + uint64_t opMask = ~(uint64_t)0 >> (64-N); + int opShift = beginVarBit - N + 1; + opMask <<= opShift; + opShift = beginInstBit - beginVarBit; + + if (opShift > 0) { + Case += " Value |= (op & UINT64_C(" + utostr(opMask) + ")) << " + + itostr(opShift) + ";\n"; + } else if (opShift < 0) { + Case += " Value |= (op & UINT64_C(" + utostr(opMask) + ")) >> " + + itostr(-opShift) + ";\n"; + } else { + Case += " Value |= op & UINT64_C(" + utostr(opMask) + ");\n"; + } + } +} + + +std::string CodeEmitterGen::getInstructionCase(Record *R, + CodeGenTarget &Target) { + std::string Case; + + BitsInit *BI = R->getValueAsBitsInit("Inst"); + const std::vector<RecordVal> &Vals = R->getValues(); + unsigned NumberedOp = 0; + + // Loop over all of the fields in the instruction, determining which are the + // operands to the instruction. + for (unsigned i = 0, e = Vals.size(); i != e; ++i) { + // Ignore fixed fields in the record, we're looking for values like: + // bits<5> RST = { ?, ?, ?, ?, ? }; + if (Vals[i].getPrefix() || Vals[i].getValue()->isComplete()) + continue; + + AddCodeToMergeInOperand(R, BI, Vals[i].getName(), NumberedOp, Case, Target); + } + + std::string PostEmitter = R->getValueAsString("PostEncoderMethod"); + if (!PostEmitter.empty()) + Case += " Value = " + PostEmitter + "(MI, Value);\n"; + + return Case; +} + +void CodeEmitterGen::run(raw_ostream &o) { + CodeGenTarget Target(Records); + std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); + + // For little-endian instruction bit encodings, reverse the bit order + if (Target.isLittleEndianEncoding()) reverseBits(Insts); + + EmitSourceFileHeader("Machine Code Emitter", o); + + const std::vector<const CodeGenInstruction*> &NumberedInstructions = + Target.getInstructionsByEnumValue(); + + // Emit function declaration + o << "uint64_t " << Target.getName(); + if (MCEmitter) + o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n" + << " SmallVectorImpl<MCFixup> &Fixups) const {\n"; + else + o << "CodeEmitter::getBinaryCodeForInstr(const MachineInstr &MI) const {\n"; + + // Emit instruction base values + o << " static const uint64_t InstBits[] = {\n"; + for (std::vector<const CodeGenInstruction*>::const_iterator + IN = NumberedInstructions.begin(), + EN = NumberedInstructions.end(); + IN != EN; ++IN) { + const CodeGenInstruction *CGI = *IN; + Record *R = CGI->TheDef; + + if (R->getValueAsString("Namespace") == "TargetOpcode" || + R->getValueAsBit("isPseudo")) { + o << " UINT64_C(0),\n"; + continue; + } + + BitsInit *BI = R->getValueAsBitsInit("Inst"); + + // Start by filling in fixed values. + uint64_t Value = 0; + for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) { + if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) + Value |= (uint64_t)B->getValue() << (e-i-1); + } + o << " UINT64_C(" << Value << ")," << '\t' << "// " << R->getName() << "\n"; + } + o << " UINT64_C(0)\n };\n"; + + // Map to accumulate all the cases. + std::map<std::string, std::vector<std::string> > CaseMap; + + // Construct all cases statement for each opcode + for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end(); + IC != EC; ++IC) { + Record *R = *IC; + if (R->getValueAsString("Namespace") == "TargetOpcode" || + R->getValueAsBit("isPseudo")) + continue; + const std::string &InstName = R->getValueAsString("Namespace") + "::" + + R->getName(); + std::string Case = getInstructionCase(R, Target); + + CaseMap[Case].push_back(InstName); + } + + // Emit initial function code + o << " const unsigned opcode = MI.getOpcode();\n" + << " uint64_t Value = InstBits[opcode];\n" + << " uint64_t op = 0;\n" + << " (void)op; // suppress warning\n" + << " switch (opcode) {\n"; + + // Emit each case statement + std::map<std::string, std::vector<std::string> >::iterator IE, EE; + for (IE = CaseMap.begin(), EE = CaseMap.end(); IE != EE; ++IE) { + const std::string &Case = IE->first; + std::vector<std::string> &InstList = IE->second; + + for (int i = 0, N = InstList.size(); i < N; i++) { + if (i) o << "\n"; + o << " case " << InstList[i] << ":"; + } + o << " {\n"; + o << Case; + o << " break;\n" + << " }\n"; + } + + // Default case: unhandled opcode + o << " default:\n" + << " std::string msg;\n" + << " raw_string_ostream Msg(msg);\n" + << " Msg << \"Not supported instr: \" << MI;\n" + << " report_fatal_error(Msg.str());\n" + << " }\n" + << " return Value;\n" + << "}\n\n"; +} diff --git a/contrib/llvm/utils/TableGen/CodeEmitterGen.h b/contrib/llvm/utils/TableGen/CodeEmitterGen.h new file mode 100644 index 0000000..7f6ee2a --- /dev/null +++ b/contrib/llvm/utils/TableGen/CodeEmitterGen.h @@ -0,0 +1,49 @@ +//===- CodeEmitterGen.h - Code Emitter Generator ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// FIXME: document +// +//===----------------------------------------------------------------------===// + +#ifndef CODEMITTERGEN_H +#define CODEMITTERGEN_H + +#include "llvm/TableGen/TableGenBackend.h" +#include <vector> +#include <string> + +namespace llvm { + +class RecordVal; +class BitsInit; +class CodeGenTarget; + +class CodeEmitterGen : public TableGenBackend { + RecordKeeper &Records; +public: + CodeEmitterGen(RecordKeeper &R) : Records(R) {} + + // run - Output the code emitter + void run(raw_ostream &o); +private: + void emitMachineOpEmitter(raw_ostream &o, const std::string &Namespace); + void emitGetValueBit(raw_ostream &o, const std::string &Namespace); + void reverseBits(std::vector<Record*> &Insts); + int getVariableBit(const std::string &VarName, BitsInit *BI, int bit); + std::string getInstructionCase(Record *R, CodeGenTarget &Target); + void + AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, + unsigned &NumberedOp, + std::string &Case, CodeGenTarget &Target); + +}; + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp new file mode 100644 index 0000000..d4b02fb --- /dev/null +++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -0,0 +1,3294 @@ +//===- CodeGenDAGPatterns.cpp - Read DAG patterns from .td file -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the CodeGenDAGPatterns class, which is used to read and +// represent the patterns present in a .td file for instructions. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenDAGPatterns.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include <algorithm> +#include <cstdio> +#include <set> +using namespace llvm; + +//===----------------------------------------------------------------------===// +// EEVT::TypeSet Implementation +//===----------------------------------------------------------------------===// + +static inline bool isInteger(MVT::SimpleValueType VT) { + return EVT(VT).isInteger(); +} +static inline bool isFloatingPoint(MVT::SimpleValueType VT) { + return EVT(VT).isFloatingPoint(); +} +static inline bool isVector(MVT::SimpleValueType VT) { + return EVT(VT).isVector(); +} +static inline bool isScalar(MVT::SimpleValueType VT) { + return !EVT(VT).isVector(); +} + +EEVT::TypeSet::TypeSet(MVT::SimpleValueType VT, TreePattern &TP) { + if (VT == MVT::iAny) + EnforceInteger(TP); + else if (VT == MVT::fAny) + EnforceFloatingPoint(TP); + else if (VT == MVT::vAny) + EnforceVector(TP); + else { + assert((VT < MVT::LAST_VALUETYPE || VT == MVT::iPTR || + VT == MVT::iPTRAny) && "Not a concrete type!"); + TypeVec.push_back(VT); + } +} + + +EEVT::TypeSet::TypeSet(const std::vector<MVT::SimpleValueType> &VTList) { + assert(!VTList.empty() && "empty list?"); + TypeVec.append(VTList.begin(), VTList.end()); + + if (!VTList.empty()) + assert(VTList[0] != MVT::iAny && VTList[0] != MVT::vAny && + VTList[0] != MVT::fAny); + + // Verify no duplicates. + array_pod_sort(TypeVec.begin(), TypeVec.end()); + assert(std::unique(TypeVec.begin(), TypeVec.end()) == TypeVec.end()); +} + +/// FillWithPossibleTypes - Set to all legal types and return true, only valid +/// on completely unknown type sets. +bool EEVT::TypeSet::FillWithPossibleTypes(TreePattern &TP, + bool (*Pred)(MVT::SimpleValueType), + const char *PredicateName) { + assert(isCompletelyUnknown()); + const std::vector<MVT::SimpleValueType> &LegalTypes = + TP.getDAGPatterns().getTargetInfo().getLegalValueTypes(); + + for (unsigned i = 0, e = LegalTypes.size(); i != e; ++i) + if (Pred == 0 || Pred(LegalTypes[i])) + TypeVec.push_back(LegalTypes[i]); + + // If we have nothing that matches the predicate, bail out. + if (TypeVec.empty()) + TP.error("Type inference contradiction found, no " + + std::string(PredicateName) + " types found"); + // No need to sort with one element. + if (TypeVec.size() == 1) return true; + + // Remove duplicates. + array_pod_sort(TypeVec.begin(), TypeVec.end()); + TypeVec.erase(std::unique(TypeVec.begin(), TypeVec.end()), TypeVec.end()); + + return true; +} + +/// hasIntegerTypes - Return true if this TypeSet contains iAny or an +/// integer value type. +bool EEVT::TypeSet::hasIntegerTypes() const { + for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) + if (isInteger(TypeVec[i])) + return true; + return false; +} + +/// hasFloatingPointTypes - Return true if this TypeSet contains an fAny or +/// a floating point value type. +bool EEVT::TypeSet::hasFloatingPointTypes() const { + for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) + if (isFloatingPoint(TypeVec[i])) + return true; + return false; +} + +/// hasVectorTypes - Return true if this TypeSet contains a vAny or a vector +/// value type. +bool EEVT::TypeSet::hasVectorTypes() const { + for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) + if (isVector(TypeVec[i])) + return true; + return false; +} + + +std::string EEVT::TypeSet::getName() const { + if (TypeVec.empty()) return "<empty>"; + + std::string Result; + + for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) { + std::string VTName = llvm::getEnumName(TypeVec[i]); + // Strip off MVT:: prefix if present. + if (VTName.substr(0,5) == "MVT::") + VTName = VTName.substr(5); + if (i) Result += ':'; + Result += VTName; + } + + if (TypeVec.size() == 1) + return Result; + return "{" + Result + "}"; +} + +/// MergeInTypeInfo - This merges in type information from the specified +/// argument. If 'this' changes, it returns true. If the two types are +/// contradictory (e.g. merge f32 into i32) then this throws an exception. +bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){ + if (InVT.isCompletelyUnknown() || *this == InVT) + return false; + + if (isCompletelyUnknown()) { + *this = InVT; + return true; + } + + assert(TypeVec.size() >= 1 && InVT.TypeVec.size() >= 1 && "No unknowns"); + + // Handle the abstract cases, seeing if we can resolve them better. + switch (TypeVec[0]) { + default: break; + case MVT::iPTR: + case MVT::iPTRAny: + if (InVT.hasIntegerTypes()) { + EEVT::TypeSet InCopy(InVT); + InCopy.EnforceInteger(TP); + InCopy.EnforceScalar(TP); + + if (InCopy.isConcrete()) { + // If the RHS has one integer type, upgrade iPTR to i32. + TypeVec[0] = InVT.TypeVec[0]; + return true; + } + + // If the input has multiple scalar integers, this doesn't add any info. + if (!InCopy.isCompletelyUnknown()) + return false; + } + break; + } + + // If the input constraint is iAny/iPTR and this is an integer type list, + // remove non-integer types from the list. + if ((InVT.TypeVec[0] == MVT::iPTR || InVT.TypeVec[0] == MVT::iPTRAny) && + hasIntegerTypes()) { + bool MadeChange = EnforceInteger(TP); + + // If we're merging in iPTR/iPTRAny and the node currently has a list of + // multiple different integer types, replace them with a single iPTR. + if ((InVT.TypeVec[0] == MVT::iPTR || InVT.TypeVec[0] == MVT::iPTRAny) && + TypeVec.size() != 1) { + TypeVec.resize(1); + TypeVec[0] = InVT.TypeVec[0]; + MadeChange = true; + } + + return MadeChange; + } + + // If this is a type list and the RHS is a typelist as well, eliminate entries + // from this list that aren't in the other one. + bool MadeChange = false; + TypeSet InputSet(*this); + + for (unsigned i = 0; i != TypeVec.size(); ++i) { + bool InInVT = false; + for (unsigned j = 0, e = InVT.TypeVec.size(); j != e; ++j) + if (TypeVec[i] == InVT.TypeVec[j]) { + InInVT = true; + break; + } + + if (InInVT) continue; + TypeVec.erase(TypeVec.begin()+i--); + MadeChange = true; + } + + // If we removed all of our types, we have a type contradiction. + if (!TypeVec.empty()) + return MadeChange; + + // FIXME: Really want an SMLoc here! + TP.error("Type inference contradiction found, merging '" + + InVT.getName() + "' into '" + InputSet.getName() + "'"); + return true; // unreachable +} + +/// EnforceInteger - Remove all non-integer types from this set. +bool EEVT::TypeSet::EnforceInteger(TreePattern &TP) { + // If we know nothing, then get the full set. + if (TypeVec.empty()) + return FillWithPossibleTypes(TP, isInteger, "integer"); + if (!hasFloatingPointTypes()) + return false; + + TypeSet InputSet(*this); + + // Filter out all the fp types. + for (unsigned i = 0; i != TypeVec.size(); ++i) + if (!isInteger(TypeVec[i])) + TypeVec.erase(TypeVec.begin()+i--); + + if (TypeVec.empty()) + TP.error("Type inference contradiction found, '" + + InputSet.getName() + "' needs to be integer"); + return true; +} + +/// EnforceFloatingPoint - Remove all integer types from this set. +bool EEVT::TypeSet::EnforceFloatingPoint(TreePattern &TP) { + // If we know nothing, then get the full set. + if (TypeVec.empty()) + return FillWithPossibleTypes(TP, isFloatingPoint, "floating point"); + + if (!hasIntegerTypes()) + return false; + + TypeSet InputSet(*this); + + // Filter out all the fp types. + for (unsigned i = 0; i != TypeVec.size(); ++i) + if (!isFloatingPoint(TypeVec[i])) + TypeVec.erase(TypeVec.begin()+i--); + + if (TypeVec.empty()) + TP.error("Type inference contradiction found, '" + + InputSet.getName() + "' needs to be floating point"); + return true; +} + +/// EnforceScalar - Remove all vector types from this. +bool EEVT::TypeSet::EnforceScalar(TreePattern &TP) { + // If we know nothing, then get the full set. + if (TypeVec.empty()) + return FillWithPossibleTypes(TP, isScalar, "scalar"); + + if (!hasVectorTypes()) + return false; + + TypeSet InputSet(*this); + + // Filter out all the vector types. + for (unsigned i = 0; i != TypeVec.size(); ++i) + if (!isScalar(TypeVec[i])) + TypeVec.erase(TypeVec.begin()+i--); + + if (TypeVec.empty()) + TP.error("Type inference contradiction found, '" + + InputSet.getName() + "' needs to be scalar"); + return true; +} + +/// EnforceVector - Remove all vector types from this. +bool EEVT::TypeSet::EnforceVector(TreePattern &TP) { + // If we know nothing, then get the full set. + if (TypeVec.empty()) + return FillWithPossibleTypes(TP, isVector, "vector"); + + TypeSet InputSet(*this); + bool MadeChange = false; + + // Filter out all the scalar types. + for (unsigned i = 0; i != TypeVec.size(); ++i) + if (!isVector(TypeVec[i])) { + TypeVec.erase(TypeVec.begin()+i--); + MadeChange = true; + } + + if (TypeVec.empty()) + TP.error("Type inference contradiction found, '" + + InputSet.getName() + "' needs to be a vector"); + return MadeChange; +} + + + +/// EnforceSmallerThan - 'this' must be a smaller VT than Other. Update +/// this an other based on this information. +bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { + // Both operands must be integer or FP, but we don't care which. + bool MadeChange = false; + + if (isCompletelyUnknown()) + MadeChange = FillWithPossibleTypes(TP); + + if (Other.isCompletelyUnknown()) + MadeChange = Other.FillWithPossibleTypes(TP); + + // If one side is known to be integer or known to be FP but the other side has + // no information, get at least the type integrality info in there. + if (!hasFloatingPointTypes()) + MadeChange |= Other.EnforceInteger(TP); + else if (!hasIntegerTypes()) + MadeChange |= Other.EnforceFloatingPoint(TP); + if (!Other.hasFloatingPointTypes()) + MadeChange |= EnforceInteger(TP); + else if (!Other.hasIntegerTypes()) + MadeChange |= EnforceFloatingPoint(TP); + + assert(!isCompletelyUnknown() && !Other.isCompletelyUnknown() && + "Should have a type list now"); + + // If one contains vectors but the other doesn't pull vectors out. + if (!hasVectorTypes()) + MadeChange |= Other.EnforceScalar(TP); + if (!hasVectorTypes()) + MadeChange |= EnforceScalar(TP); + + if (TypeVec.size() == 1 && Other.TypeVec.size() == 1) { + // If we are down to concrete types, this code does not currently + // handle nodes which have multiple types, where some types are + // integer, and some are fp. Assert that this is not the case. + assert(!(hasIntegerTypes() && hasFloatingPointTypes()) && + !(Other.hasIntegerTypes() && Other.hasFloatingPointTypes()) && + "SDTCisOpSmallerThanOp does not handle mixed int/fp types!"); + + // Otherwise, if these are both vector types, either this vector + // must have a larger bitsize than the other, or this element type + // must be larger than the other. + EVT Type(TypeVec[0]); + EVT OtherType(Other.TypeVec[0]); + + if (hasVectorTypes() && Other.hasVectorTypes()) { + if (Type.getSizeInBits() >= OtherType.getSizeInBits()) + if (Type.getVectorElementType().getSizeInBits() + >= OtherType.getVectorElementType().getSizeInBits()) + TP.error("Type inference contradiction found, '" + + getName() + "' element type not smaller than '" + + Other.getName() +"'!"); + } + else + // For scalar types, the bitsize of this type must be larger + // than that of the other. + if (Type.getSizeInBits() >= OtherType.getSizeInBits()) + TP.error("Type inference contradiction found, '" + + getName() + "' is not smaller than '" + + Other.getName() +"'!"); + + } + + + // Handle int and fp as disjoint sets. This won't work for patterns + // that have mixed fp/int types but those are likely rare and would + // not have been accepted by this code previously. + + // Okay, find the smallest type from the current set and remove it from the + // largest set. + MVT::SimpleValueType SmallestInt = MVT::LAST_VALUETYPE; + for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) + if (isInteger(TypeVec[i])) { + SmallestInt = TypeVec[i]; + break; + } + for (unsigned i = 1, e = TypeVec.size(); i != e; ++i) + if (isInteger(TypeVec[i]) && TypeVec[i] < SmallestInt) + SmallestInt = TypeVec[i]; + + MVT::SimpleValueType SmallestFP = MVT::LAST_VALUETYPE; + for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) + if (isFloatingPoint(TypeVec[i])) { + SmallestFP = TypeVec[i]; + break; + } + for (unsigned i = 1, e = TypeVec.size(); i != e; ++i) + if (isFloatingPoint(TypeVec[i]) && TypeVec[i] < SmallestFP) + SmallestFP = TypeVec[i]; + + int OtherIntSize = 0; + int OtherFPSize = 0; + for (SmallVector<MVT::SimpleValueType, 2>::iterator TVI = + Other.TypeVec.begin(); + TVI != Other.TypeVec.end(); + /* NULL */) { + if (isInteger(*TVI)) { + ++OtherIntSize; + if (*TVI == SmallestInt) { + TVI = Other.TypeVec.erase(TVI); + --OtherIntSize; + MadeChange = true; + continue; + } + } + else if (isFloatingPoint(*TVI)) { + ++OtherFPSize; + if (*TVI == SmallestFP) { + TVI = Other.TypeVec.erase(TVI); + --OtherFPSize; + MadeChange = true; + continue; + } + } + ++TVI; + } + + // If this is the only type in the large set, the constraint can never be + // satisfied. + if ((Other.hasIntegerTypes() && OtherIntSize == 0) + || (Other.hasFloatingPointTypes() && OtherFPSize == 0)) + TP.error("Type inference contradiction found, '" + + Other.getName() + "' has nothing larger than '" + getName() +"'!"); + + // Okay, find the largest type in the Other set and remove it from the + // current set. + MVT::SimpleValueType LargestInt = MVT::Other; + for (unsigned i = 0, e = Other.TypeVec.size(); i != e; ++i) + if (isInteger(Other.TypeVec[i])) { + LargestInt = Other.TypeVec[i]; + break; + } + for (unsigned i = 1, e = Other.TypeVec.size(); i != e; ++i) + if (isInteger(Other.TypeVec[i]) && Other.TypeVec[i] > LargestInt) + LargestInt = Other.TypeVec[i]; + + MVT::SimpleValueType LargestFP = MVT::Other; + for (unsigned i = 0, e = Other.TypeVec.size(); i != e; ++i) + if (isFloatingPoint(Other.TypeVec[i])) { + LargestFP = Other.TypeVec[i]; + break; + } + for (unsigned i = 1, e = Other.TypeVec.size(); i != e; ++i) + if (isFloatingPoint(Other.TypeVec[i]) && Other.TypeVec[i] > LargestFP) + LargestFP = Other.TypeVec[i]; + + int IntSize = 0; + int FPSize = 0; + for (SmallVector<MVT::SimpleValueType, 2>::iterator TVI = + TypeVec.begin(); + TVI != TypeVec.end(); + /* NULL */) { + if (isInteger(*TVI)) { + ++IntSize; + if (*TVI == LargestInt) { + TVI = TypeVec.erase(TVI); + --IntSize; + MadeChange = true; + continue; + } + } + else if (isFloatingPoint(*TVI)) { + ++FPSize; + if (*TVI == LargestFP) { + TVI = TypeVec.erase(TVI); + --FPSize; + MadeChange = true; + continue; + } + } + ++TVI; + } + + // If this is the only type in the small set, the constraint can never be + // satisfied. + if ((hasIntegerTypes() && IntSize == 0) + || (hasFloatingPointTypes() && FPSize == 0)) + TP.error("Type inference contradiction found, '" + + getName() + "' has nothing smaller than '" + Other.getName()+"'!"); + + return MadeChange; +} + +/// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type +/// whose element is specified by VTOperand. +bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand, + TreePattern &TP) { + // "This" must be a vector and "VTOperand" must be a scalar. + bool MadeChange = false; + MadeChange |= EnforceVector(TP); + MadeChange |= VTOperand.EnforceScalar(TP); + + // If we know the vector type, it forces the scalar to agree. + if (isConcrete()) { + EVT IVT = getConcrete(); + IVT = IVT.getVectorElementType(); + return MadeChange | + VTOperand.MergeInTypeInfo(IVT.getSimpleVT().SimpleTy, TP); + } + + // If the scalar type is known, filter out vector types whose element types + // disagree. + if (!VTOperand.isConcrete()) + return MadeChange; + + MVT::SimpleValueType VT = VTOperand.getConcrete(); + + TypeSet InputSet(*this); + + // Filter out all the types which don't have the right element type. + for (unsigned i = 0; i != TypeVec.size(); ++i) { + assert(isVector(TypeVec[i]) && "EnforceVector didn't work"); + if (EVT(TypeVec[i]).getVectorElementType().getSimpleVT().SimpleTy != VT) { + TypeVec.erase(TypeVec.begin()+i--); + MadeChange = true; + } + } + + if (TypeVec.empty()) // FIXME: Really want an SMLoc here! + TP.error("Type inference contradiction found, forcing '" + + InputSet.getName() + "' to have a vector element"); + return MadeChange; +} + +/// EnforceVectorSubVectorTypeIs - 'this' is now constrainted to be a +/// vector type specified by VTOperand. +bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand, + TreePattern &TP) { + // "This" must be a vector and "VTOperand" must be a vector. + bool MadeChange = false; + MadeChange |= EnforceVector(TP); + MadeChange |= VTOperand.EnforceVector(TP); + + // "This" must be larger than "VTOperand." + MadeChange |= VTOperand.EnforceSmallerThan(*this, TP); + + // If we know the vector type, it forces the scalar types to agree. + if (isConcrete()) { + EVT IVT = getConcrete(); + IVT = IVT.getVectorElementType(); + + EEVT::TypeSet EltTypeSet(IVT.getSimpleVT().SimpleTy, TP); + MadeChange |= VTOperand.EnforceVectorEltTypeIs(EltTypeSet, TP); + } else if (VTOperand.isConcrete()) { + EVT IVT = VTOperand.getConcrete(); + IVT = IVT.getVectorElementType(); + + EEVT::TypeSet EltTypeSet(IVT.getSimpleVT().SimpleTy, TP); + MadeChange |= EnforceVectorEltTypeIs(EltTypeSet, TP); + } + + return MadeChange; +} + +//===----------------------------------------------------------------------===// +// Helpers for working with extended types. + +bool RecordPtrCmp::operator()(const Record *LHS, const Record *RHS) const { + return LHS->getID() < RHS->getID(); +} + +/// Dependent variable map for CodeGenDAGPattern variant generation +typedef std::map<std::string, int> DepVarMap; + +/// Const iterator shorthand for DepVarMap +typedef DepVarMap::const_iterator DepVarMap_citer; + +static void FindDepVarsOf(TreePatternNode *N, DepVarMap &DepMap) { + if (N->isLeaf()) { + if (dynamic_cast<DefInit*>(N->getLeafValue()) != NULL) + DepMap[N->getName()]++; + } else { + for (size_t i = 0, e = N->getNumChildren(); i != e; ++i) + FindDepVarsOf(N->getChild(i), DepMap); + } +} + +/// Find dependent variables within child patterns +static void FindDepVars(TreePatternNode *N, MultipleUseVarSet &DepVars) { + DepVarMap depcounts; + FindDepVarsOf(N, depcounts); + for (DepVarMap_citer i = depcounts.begin(); i != depcounts.end(); ++i) { + if (i->second > 1) // std::pair<std::string, int> + DepVars.insert(i->first); + } +} + +#ifndef NDEBUG +/// Dump the dependent variable set: +static void DumpDepVars(MultipleUseVarSet &DepVars) { + if (DepVars.empty()) { + DEBUG(errs() << "<empty set>"); + } else { + DEBUG(errs() << "[ "); + for (MultipleUseVarSet::const_iterator i = DepVars.begin(), + e = DepVars.end(); i != e; ++i) { + DEBUG(errs() << (*i) << " "); + } + DEBUG(errs() << "]"); + } +} +#endif + + +//===----------------------------------------------------------------------===// +// TreePredicateFn Implementation +//===----------------------------------------------------------------------===// + +/// TreePredicateFn constructor. Here 'N' is a subclass of PatFrag. +TreePredicateFn::TreePredicateFn(TreePattern *N) : PatFragRec(N) { + assert((getPredCode().empty() || getImmCode().empty()) && + ".td file corrupt: can't have a node predicate *and* an imm predicate"); +} + +std::string TreePredicateFn::getPredCode() const { + return PatFragRec->getRecord()->getValueAsString("PredicateCode"); +} + +std::string TreePredicateFn::getImmCode() const { + return PatFragRec->getRecord()->getValueAsString("ImmediateCode"); +} + + +/// isAlwaysTrue - Return true if this is a noop predicate. +bool TreePredicateFn::isAlwaysTrue() const { + return getPredCode().empty() && getImmCode().empty(); +} + +/// Return the name to use in the generated code to reference this, this is +/// "Predicate_foo" if from a pattern fragment "foo". +std::string TreePredicateFn::getFnName() const { + return "Predicate_" + PatFragRec->getRecord()->getName(); +} + +/// getCodeToRunOnSDNode - Return the code for the function body that +/// evaluates this predicate. The argument is expected to be in "Node", +/// not N. This handles casting and conversion to a concrete node type as +/// appropriate. +std::string TreePredicateFn::getCodeToRunOnSDNode() const { + // Handle immediate predicates first. + std::string ImmCode = getImmCode(); + if (!ImmCode.empty()) { + std::string Result = + " int64_t Imm = cast<ConstantSDNode>(Node)->getSExtValue();\n"; + return Result + ImmCode; + } + + // Handle arbitrary node predicates. + assert(!getPredCode().empty() && "Don't have any predicate code!"); + std::string ClassName; + if (PatFragRec->getOnlyTree()->isLeaf()) + ClassName = "SDNode"; + else { + Record *Op = PatFragRec->getOnlyTree()->getOperator(); + ClassName = PatFragRec->getDAGPatterns().getSDNodeInfo(Op).getSDClassName(); + } + std::string Result; + if (ClassName == "SDNode") + Result = " SDNode *N = Node;\n"; + else + Result = " " + ClassName + "*N = cast<" + ClassName + ">(Node);\n"; + + return Result + getPredCode(); +} + +//===----------------------------------------------------------------------===// +// PatternToMatch implementation +// + + +/// getPatternSize - Return the 'size' of this pattern. We want to match large +/// patterns before small ones. This is used to determine the size of a +/// pattern. +static unsigned getPatternSize(const TreePatternNode *P, + const CodeGenDAGPatterns &CGP) { + unsigned Size = 3; // The node itself. + // If the root node is a ConstantSDNode, increases its size. + // e.g. (set R32:$dst, 0). + if (P->isLeaf() && dynamic_cast<IntInit*>(P->getLeafValue())) + Size += 2; + + // FIXME: This is a hack to statically increase the priority of patterns + // which maps a sub-dag to a complex pattern. e.g. favors LEA over ADD. + // Later we can allow complexity / cost for each pattern to be (optionally) + // specified. To get best possible pattern match we'll need to dynamically + // calculate the complexity of all patterns a dag can potentially map to. + const ComplexPattern *AM = P->getComplexPatternInfo(CGP); + if (AM) + Size += AM->getNumOperands() * 3; + + // If this node has some predicate function that must match, it adds to the + // complexity of this node. + if (!P->getPredicateFns().empty()) + ++Size; + + // Count children in the count if they are also nodes. + for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i) { + TreePatternNode *Child = P->getChild(i); + if (!Child->isLeaf() && Child->getNumTypes() && + Child->getType(0) != MVT::Other) + Size += getPatternSize(Child, CGP); + else if (Child->isLeaf()) { + if (dynamic_cast<IntInit*>(Child->getLeafValue())) + Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2). + else if (Child->getComplexPatternInfo(CGP)) + Size += getPatternSize(Child, CGP); + else if (!Child->getPredicateFns().empty()) + ++Size; + } + } + + return Size; +} + +/// Compute the complexity metric for the input pattern. This roughly +/// corresponds to the number of nodes that are covered. +unsigned PatternToMatch:: +getPatternComplexity(const CodeGenDAGPatterns &CGP) const { + return getPatternSize(getSrcPattern(), CGP) + getAddedComplexity(); +} + + +/// getPredicateCheck - Return a single string containing all of this +/// pattern's predicates concatenated with "&&" operators. +/// +std::string PatternToMatch::getPredicateCheck() const { + std::string PredicateCheck; + for (unsigned i = 0, e = Predicates->getSize(); i != e; ++i) { + if (DefInit *Pred = dynamic_cast<DefInit*>(Predicates->getElement(i))) { + Record *Def = Pred->getDef(); + if (!Def->isSubClassOf("Predicate")) { +#ifndef NDEBUG + Def->dump(); +#endif + llvm_unreachable("Unknown predicate type!"); + } + if (!PredicateCheck.empty()) + PredicateCheck += " && "; + PredicateCheck += "(" + Def->getValueAsString("CondString") + ")"; + } + } + + return PredicateCheck; +} + +//===----------------------------------------------------------------------===// +// SDTypeConstraint implementation +// + +SDTypeConstraint::SDTypeConstraint(Record *R) { + OperandNo = R->getValueAsInt("OperandNum"); + + if (R->isSubClassOf("SDTCisVT")) { + ConstraintType = SDTCisVT; + x.SDTCisVT_Info.VT = getValueType(R->getValueAsDef("VT")); + if (x.SDTCisVT_Info.VT == MVT::isVoid) + throw TGError(R->getLoc(), "Cannot use 'Void' as type to SDTCisVT"); + + } else if (R->isSubClassOf("SDTCisPtrTy")) { + ConstraintType = SDTCisPtrTy; + } else if (R->isSubClassOf("SDTCisInt")) { + ConstraintType = SDTCisInt; + } else if (R->isSubClassOf("SDTCisFP")) { + ConstraintType = SDTCisFP; + } else if (R->isSubClassOf("SDTCisVec")) { + ConstraintType = SDTCisVec; + } else if (R->isSubClassOf("SDTCisSameAs")) { + ConstraintType = SDTCisSameAs; + x.SDTCisSameAs_Info.OtherOperandNum = R->getValueAsInt("OtherOperandNum"); + } else if (R->isSubClassOf("SDTCisVTSmallerThanOp")) { + ConstraintType = SDTCisVTSmallerThanOp; + x.SDTCisVTSmallerThanOp_Info.OtherOperandNum = + R->getValueAsInt("OtherOperandNum"); + } else if (R->isSubClassOf("SDTCisOpSmallerThanOp")) { + ConstraintType = SDTCisOpSmallerThanOp; + x.SDTCisOpSmallerThanOp_Info.BigOperandNum = + R->getValueAsInt("BigOperandNum"); + } else if (R->isSubClassOf("SDTCisEltOfVec")) { + ConstraintType = SDTCisEltOfVec; + x.SDTCisEltOfVec_Info.OtherOperandNum = R->getValueAsInt("OtherOpNum"); + } else if (R->isSubClassOf("SDTCisSubVecOfVec")) { + ConstraintType = SDTCisSubVecOfVec; + x.SDTCisSubVecOfVec_Info.OtherOperandNum = + R->getValueAsInt("OtherOpNum"); + } else { + errs() << "Unrecognized SDTypeConstraint '" << R->getName() << "'!\n"; + exit(1); + } +} + +/// getOperandNum - Return the node corresponding to operand #OpNo in tree +/// N, and the result number in ResNo. +static TreePatternNode *getOperandNum(unsigned OpNo, TreePatternNode *N, + const SDNodeInfo &NodeInfo, + unsigned &ResNo) { + unsigned NumResults = NodeInfo.getNumResults(); + if (OpNo < NumResults) { + ResNo = OpNo; + return N; + } + + OpNo -= NumResults; + + if (OpNo >= N->getNumChildren()) { + errs() << "Invalid operand number in type constraint " + << (OpNo+NumResults) << " "; + N->dump(); + errs() << '\n'; + exit(1); + } + + return N->getChild(OpNo); +} + +/// ApplyTypeConstraint - Given a node in a pattern, apply this type +/// constraint to the nodes operands. This returns true if it makes a +/// change, false otherwise. If a type contradiction is found, throw an +/// exception. +bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, + const SDNodeInfo &NodeInfo, + TreePattern &TP) const { + unsigned ResNo = 0; // The result number being referenced. + TreePatternNode *NodeToApply = getOperandNum(OperandNo, N, NodeInfo, ResNo); + + switch (ConstraintType) { + case SDTCisVT: + // Operand must be a particular type. + return NodeToApply->UpdateNodeType(ResNo, x.SDTCisVT_Info.VT, TP); + case SDTCisPtrTy: + // Operand must be same as target pointer type. + return NodeToApply->UpdateNodeType(ResNo, MVT::iPTR, TP); + case SDTCisInt: + // Require it to be one of the legal integer VTs. + return NodeToApply->getExtType(ResNo).EnforceInteger(TP); + case SDTCisFP: + // Require it to be one of the legal fp VTs. + return NodeToApply->getExtType(ResNo).EnforceFloatingPoint(TP); + case SDTCisVec: + // Require it to be one of the legal vector VTs. + return NodeToApply->getExtType(ResNo).EnforceVector(TP); + case SDTCisSameAs: { + unsigned OResNo = 0; + TreePatternNode *OtherNode = + getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NodeInfo, OResNo); + return NodeToApply->UpdateNodeType(OResNo, OtherNode->getExtType(ResNo),TP)| + OtherNode->UpdateNodeType(ResNo,NodeToApply->getExtType(OResNo),TP); + } + case SDTCisVTSmallerThanOp: { + // The NodeToApply must be a leaf node that is a VT. OtherOperandNum must + // have an integer type that is smaller than the VT. + if (!NodeToApply->isLeaf() || + !dynamic_cast<DefInit*>(NodeToApply->getLeafValue()) || + !static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef() + ->isSubClassOf("ValueType")) + TP.error(N->getOperator()->getName() + " expects a VT operand!"); + MVT::SimpleValueType VT = + getValueType(static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef()); + + EEVT::TypeSet TypeListTmp(VT, TP); + + unsigned OResNo = 0; + TreePatternNode *OtherNode = + getOperandNum(x.SDTCisVTSmallerThanOp_Info.OtherOperandNum, N, NodeInfo, + OResNo); + + return TypeListTmp.EnforceSmallerThan(OtherNode->getExtType(OResNo), TP); + } + case SDTCisOpSmallerThanOp: { + unsigned BResNo = 0; + TreePatternNode *BigOperand = + getOperandNum(x.SDTCisOpSmallerThanOp_Info.BigOperandNum, N, NodeInfo, + BResNo); + return NodeToApply->getExtType(ResNo). + EnforceSmallerThan(BigOperand->getExtType(BResNo), TP); + } + case SDTCisEltOfVec: { + unsigned VResNo = 0; + TreePatternNode *VecOperand = + getOperandNum(x.SDTCisEltOfVec_Info.OtherOperandNum, N, NodeInfo, + VResNo); + + // Filter vector types out of VecOperand that don't have the right element + // type. + return VecOperand->getExtType(VResNo). + EnforceVectorEltTypeIs(NodeToApply->getExtType(ResNo), TP); + } + case SDTCisSubVecOfVec: { + unsigned VResNo = 0; + TreePatternNode *BigVecOperand = + getOperandNum(x.SDTCisSubVecOfVec_Info.OtherOperandNum, N, NodeInfo, + VResNo); + + // Filter vector types out of BigVecOperand that don't have the + // right subvector type. + return BigVecOperand->getExtType(VResNo). + EnforceVectorSubVectorTypeIs(NodeToApply->getExtType(ResNo), TP); + } + } + llvm_unreachable("Invalid ConstraintType!"); +} + +//===----------------------------------------------------------------------===// +// SDNodeInfo implementation +// +SDNodeInfo::SDNodeInfo(Record *R) : Def(R) { + EnumName = R->getValueAsString("Opcode"); + SDClassName = R->getValueAsString("SDClass"); + Record *TypeProfile = R->getValueAsDef("TypeProfile"); + NumResults = TypeProfile->getValueAsInt("NumResults"); + NumOperands = TypeProfile->getValueAsInt("NumOperands"); + + // Parse the properties. + Properties = 0; + std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties"); + for (unsigned i = 0, e = PropList.size(); i != e; ++i) { + if (PropList[i]->getName() == "SDNPCommutative") { + Properties |= 1 << SDNPCommutative; + } else if (PropList[i]->getName() == "SDNPAssociative") { + Properties |= 1 << SDNPAssociative; + } else if (PropList[i]->getName() == "SDNPHasChain") { + Properties |= 1 << SDNPHasChain; + } else if (PropList[i]->getName() == "SDNPOutGlue") { + Properties |= 1 << SDNPOutGlue; + } else if (PropList[i]->getName() == "SDNPInGlue") { + Properties |= 1 << SDNPInGlue; + } else if (PropList[i]->getName() == "SDNPOptInGlue") { + Properties |= 1 << SDNPOptInGlue; + } else if (PropList[i]->getName() == "SDNPMayStore") { + Properties |= 1 << SDNPMayStore; + } else if (PropList[i]->getName() == "SDNPMayLoad") { + Properties |= 1 << SDNPMayLoad; + } else if (PropList[i]->getName() == "SDNPSideEffect") { + Properties |= 1 << SDNPSideEffect; + } else if (PropList[i]->getName() == "SDNPMemOperand") { + Properties |= 1 << SDNPMemOperand; + } else if (PropList[i]->getName() == "SDNPVariadic") { + Properties |= 1 << SDNPVariadic; + } else { + errs() << "Unknown SD Node property '" << PropList[i]->getName() + << "' on node '" << R->getName() << "'!\n"; + exit(1); + } + } + + + // Parse the type constraints. + std::vector<Record*> ConstraintList = + TypeProfile->getValueAsListOfDefs("Constraints"); + TypeConstraints.assign(ConstraintList.begin(), ConstraintList.end()); +} + +/// getKnownType - If the type constraints on this node imply a fixed type +/// (e.g. all stores return void, etc), then return it as an +/// MVT::SimpleValueType. Otherwise, return EEVT::Other. +MVT::SimpleValueType SDNodeInfo::getKnownType(unsigned ResNo) const { + unsigned NumResults = getNumResults(); + assert(NumResults <= 1 && + "We only work with nodes with zero or one result so far!"); + assert(ResNo == 0 && "Only handles single result nodes so far"); + + for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i) { + // Make sure that this applies to the correct node result. + if (TypeConstraints[i].OperandNo >= NumResults) // FIXME: need value # + continue; + + switch (TypeConstraints[i].ConstraintType) { + default: break; + case SDTypeConstraint::SDTCisVT: + return TypeConstraints[i].x.SDTCisVT_Info.VT; + case SDTypeConstraint::SDTCisPtrTy: + return MVT::iPTR; + } + } + return MVT::Other; +} + +//===----------------------------------------------------------------------===// +// TreePatternNode implementation +// + +TreePatternNode::~TreePatternNode() { +#if 0 // FIXME: implement refcounted tree nodes! + for (unsigned i = 0, e = getNumChildren(); i != e; ++i) + delete getChild(i); +#endif +} + +static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { + if (Operator->getName() == "set" || + Operator->getName() == "implicit") + return 0; // All return nothing. + + if (Operator->isSubClassOf("Intrinsic")) + return CDP.getIntrinsic(Operator).IS.RetVTs.size(); + + if (Operator->isSubClassOf("SDNode")) + return CDP.getSDNodeInfo(Operator).getNumResults(); + + if (Operator->isSubClassOf("PatFrag")) { + // If we've already parsed this pattern fragment, get it. Otherwise, handle + // the forward reference case where one pattern fragment references another + // before it is processed. + if (TreePattern *PFRec = CDP.getPatternFragmentIfRead(Operator)) + return PFRec->getOnlyTree()->getNumTypes(); + + // Get the result tree. + DagInit *Tree = Operator->getValueAsDag("Fragment"); + Record *Op = 0; + if (Tree && dynamic_cast<DefInit*>(Tree->getOperator())) + Op = dynamic_cast<DefInit*>(Tree->getOperator())->getDef(); + assert(Op && "Invalid Fragment"); + return GetNumNodeResults(Op, CDP); + } + + if (Operator->isSubClassOf("Instruction")) { + CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(Operator); + + // FIXME: Should allow access to all the results here. + unsigned NumDefsToAdd = InstInfo.Operands.NumDefs ? 1 : 0; + + // Add on one implicit def if it has a resolvable type. + if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other) + ++NumDefsToAdd; + return NumDefsToAdd; + } + + if (Operator->isSubClassOf("SDNodeXForm")) + return 1; // FIXME: Generalize SDNodeXForm + + Operator->dump(); + errs() << "Unhandled node in GetNumNodeResults\n"; + exit(1); +} + +void TreePatternNode::print(raw_ostream &OS) const { + if (isLeaf()) + OS << *getLeafValue(); + else + OS << '(' << getOperator()->getName(); + + for (unsigned i = 0, e = Types.size(); i != e; ++i) + OS << ':' << getExtType(i).getName(); + + if (!isLeaf()) { + if (getNumChildren() != 0) { + OS << " "; + getChild(0)->print(OS); + for (unsigned i = 1, e = getNumChildren(); i != e; ++i) { + OS << ", "; + getChild(i)->print(OS); + } + } + OS << ")"; + } + + for (unsigned i = 0, e = PredicateFns.size(); i != e; ++i) + OS << "<<P:" << PredicateFns[i].getFnName() << ">>"; + if (TransformFn) + OS << "<<X:" << TransformFn->getName() << ">>"; + if (!getName().empty()) + OS << ":$" << getName(); + +} +void TreePatternNode::dump() const { + print(errs()); +} + +/// isIsomorphicTo - Return true if this node is recursively +/// isomorphic to the specified node. For this comparison, the node's +/// entire state is considered. The assigned name is ignored, since +/// nodes with differing names are considered isomorphic. However, if +/// the assigned name is present in the dependent variable set, then +/// the assigned name is considered significant and the node is +/// isomorphic if the names match. +bool TreePatternNode::isIsomorphicTo(const TreePatternNode *N, + const MultipleUseVarSet &DepVars) const { + if (N == this) return true; + if (N->isLeaf() != isLeaf() || getExtTypes() != N->getExtTypes() || + getPredicateFns() != N->getPredicateFns() || + getTransformFn() != N->getTransformFn()) + return false; + + if (isLeaf()) { + if (DefInit *DI = dynamic_cast<DefInit*>(getLeafValue())) { + if (DefInit *NDI = dynamic_cast<DefInit*>(N->getLeafValue())) { + return ((DI->getDef() == NDI->getDef()) + && (DepVars.find(getName()) == DepVars.end() + || getName() == N->getName())); + } + } + return getLeafValue() == N->getLeafValue(); + } + + if (N->getOperator() != getOperator() || + N->getNumChildren() != getNumChildren()) return false; + for (unsigned i = 0, e = getNumChildren(); i != e; ++i) + if (!getChild(i)->isIsomorphicTo(N->getChild(i), DepVars)) + return false; + return true; +} + +/// clone - Make a copy of this tree and all of its children. +/// +TreePatternNode *TreePatternNode::clone() const { + TreePatternNode *New; + if (isLeaf()) { + New = new TreePatternNode(getLeafValue(), getNumTypes()); + } else { + std::vector<TreePatternNode*> CChildren; + CChildren.reserve(Children.size()); + for (unsigned i = 0, e = getNumChildren(); i != e; ++i) + CChildren.push_back(getChild(i)->clone()); + New = new TreePatternNode(getOperator(), CChildren, getNumTypes()); + } + New->setName(getName()); + New->Types = Types; + New->setPredicateFns(getPredicateFns()); + New->setTransformFn(getTransformFn()); + return New; +} + +/// RemoveAllTypes - Recursively strip all the types of this tree. +void TreePatternNode::RemoveAllTypes() { + for (unsigned i = 0, e = Types.size(); i != e; ++i) + Types[i] = EEVT::TypeSet(); // Reset to unknown type. + if (isLeaf()) return; + for (unsigned i = 0, e = getNumChildren(); i != e; ++i) + getChild(i)->RemoveAllTypes(); +} + + +/// SubstituteFormalArguments - Replace the formal arguments in this tree +/// with actual values specified by ArgMap. +void TreePatternNode:: +SubstituteFormalArguments(std::map<std::string, TreePatternNode*> &ArgMap) { + if (isLeaf()) return; + + for (unsigned i = 0, e = getNumChildren(); i != e; ++i) { + TreePatternNode *Child = getChild(i); + if (Child->isLeaf()) { + Init *Val = Child->getLeafValue(); + if (dynamic_cast<DefInit*>(Val) && + static_cast<DefInit*>(Val)->getDef()->getName() == "node") { + // We found a use of a formal argument, replace it with its value. + TreePatternNode *NewChild = ArgMap[Child->getName()]; + assert(NewChild && "Couldn't find formal argument!"); + assert((Child->getPredicateFns().empty() || + NewChild->getPredicateFns() == Child->getPredicateFns()) && + "Non-empty child predicate clobbered!"); + setChild(i, NewChild); + } + } else { + getChild(i)->SubstituteFormalArguments(ArgMap); + } + } +} + + +/// InlinePatternFragments - If this pattern refers to any pattern +/// fragments, inline them into place, giving us a pattern without any +/// PatFrag references. +TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { + if (isLeaf()) return this; // nothing to do. + Record *Op = getOperator(); + + if (!Op->isSubClassOf("PatFrag")) { + // Just recursively inline children nodes. + for (unsigned i = 0, e = getNumChildren(); i != e; ++i) { + TreePatternNode *Child = getChild(i); + TreePatternNode *NewChild = Child->InlinePatternFragments(TP); + + assert((Child->getPredicateFns().empty() || + NewChild->getPredicateFns() == Child->getPredicateFns()) && + "Non-empty child predicate clobbered!"); + + setChild(i, NewChild); + } + return this; + } + + // Otherwise, we found a reference to a fragment. First, look up its + // TreePattern record. + TreePattern *Frag = TP.getDAGPatterns().getPatternFragment(Op); + + // Verify that we are passing the right number of operands. + if (Frag->getNumArgs() != Children.size()) + TP.error("'" + Op->getName() + "' fragment requires " + + utostr(Frag->getNumArgs()) + " operands!"); + + TreePatternNode *FragTree = Frag->getOnlyTree()->clone(); + + TreePredicateFn PredFn(Frag); + if (!PredFn.isAlwaysTrue()) + FragTree->addPredicateFn(PredFn); + + // Resolve formal arguments to their actual value. + if (Frag->getNumArgs()) { + // Compute the map of formal to actual arguments. + std::map<std::string, TreePatternNode*> ArgMap; + for (unsigned i = 0, e = Frag->getNumArgs(); i != e; ++i) + ArgMap[Frag->getArgName(i)] = getChild(i)->InlinePatternFragments(TP); + + FragTree->SubstituteFormalArguments(ArgMap); + } + + FragTree->setName(getName()); + for (unsigned i = 0, e = Types.size(); i != e; ++i) + FragTree->UpdateNodeType(i, getExtType(i), TP); + + // Transfer in the old predicates. + for (unsigned i = 0, e = getPredicateFns().size(); i != e; ++i) + FragTree->addPredicateFn(getPredicateFns()[i]); + + // Get a new copy of this fragment to stitch into here. + //delete this; // FIXME: implement refcounting! + + // The fragment we inlined could have recursive inlining that is needed. See + // if there are any pattern fragments in it and inline them as needed. + return FragTree->InlinePatternFragments(TP); +} + +/// getImplicitType - Check to see if the specified record has an implicit +/// type which should be applied to it. This will infer the type of register +/// references from the register file information, for example. +/// +static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo, + bool NotRegisters, TreePattern &TP) { + // Check to see if this is a register operand. + if (R->isSubClassOf("RegisterOperand")) { + assert(ResNo == 0 && "Regoperand ref only has one result!"); + if (NotRegisters) + return EEVT::TypeSet(); // Unknown. + Record *RegClass = R->getValueAsDef("RegClass"); + const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); + return EEVT::TypeSet(T.getRegisterClass(RegClass).getValueTypes()); + } + + // Check to see if this is a register or a register class. + if (R->isSubClassOf("RegisterClass")) { + assert(ResNo == 0 && "Regclass ref only has one result!"); + if (NotRegisters) + return EEVT::TypeSet(); // Unknown. + const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); + return EEVT::TypeSet(T.getRegisterClass(R).getValueTypes()); + } + + if (R->isSubClassOf("PatFrag")) { + assert(ResNo == 0 && "FIXME: PatFrag with multiple results?"); + // Pattern fragment types will be resolved when they are inlined. + return EEVT::TypeSet(); // Unknown. + } + + if (R->isSubClassOf("Register")) { + assert(ResNo == 0 && "Registers only produce one result!"); + if (NotRegisters) + return EEVT::TypeSet(); // Unknown. + const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); + return EEVT::TypeSet(T.getRegisterVTs(R)); + } + + if (R->isSubClassOf("SubRegIndex")) { + assert(ResNo == 0 && "SubRegisterIndices only produce one result!"); + return EEVT::TypeSet(); + } + + if (R->isSubClassOf("ValueType") || R->isSubClassOf("CondCode")) { + assert(ResNo == 0 && "This node only has one result!"); + // Using a VTSDNode or CondCodeSDNode. + return EEVT::TypeSet(MVT::Other, TP); + } + + if (R->isSubClassOf("ComplexPattern")) { + assert(ResNo == 0 && "FIXME: ComplexPattern with multiple results?"); + if (NotRegisters) + return EEVT::TypeSet(); // Unknown. + return EEVT::TypeSet(TP.getDAGPatterns().getComplexPattern(R).getValueType(), + TP); + } + if (R->isSubClassOf("PointerLikeRegClass")) { + assert(ResNo == 0 && "Regclass can only have one result!"); + return EEVT::TypeSet(MVT::iPTR, TP); + } + + if (R->getName() == "node" || R->getName() == "srcvalue" || + R->getName() == "zero_reg") { + // Placeholder. + return EEVT::TypeSet(); // Unknown. + } + + TP.error("Unknown node flavor used in pattern: " + R->getName()); + return EEVT::TypeSet(MVT::Other, TP); +} + + +/// getIntrinsicInfo - If this node corresponds to an intrinsic, return the +/// CodeGenIntrinsic information for it, otherwise return a null pointer. +const CodeGenIntrinsic *TreePatternNode:: +getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const { + if (getOperator() != CDP.get_intrinsic_void_sdnode() && + getOperator() != CDP.get_intrinsic_w_chain_sdnode() && + getOperator() != CDP.get_intrinsic_wo_chain_sdnode()) + return 0; + + unsigned IID = + dynamic_cast<IntInit*>(getChild(0)->getLeafValue())->getValue(); + return &CDP.getIntrinsicInfo(IID); +} + +/// getComplexPatternInfo - If this node corresponds to a ComplexPattern, +/// return the ComplexPattern information, otherwise return null. +const ComplexPattern * +TreePatternNode::getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const { + if (!isLeaf()) return 0; + + DefInit *DI = dynamic_cast<DefInit*>(getLeafValue()); + if (DI && DI->getDef()->isSubClassOf("ComplexPattern")) + return &CGP.getComplexPattern(DI->getDef()); + return 0; +} + +/// NodeHasProperty - Return true if this node has the specified property. +bool TreePatternNode::NodeHasProperty(SDNP Property, + const CodeGenDAGPatterns &CGP) const { + if (isLeaf()) { + if (const ComplexPattern *CP = getComplexPatternInfo(CGP)) + return CP->hasProperty(Property); + return false; + } + + Record *Operator = getOperator(); + if (!Operator->isSubClassOf("SDNode")) return false; + + return CGP.getSDNodeInfo(Operator).hasProperty(Property); +} + + + + +/// TreeHasProperty - Return true if any node in this tree has the specified +/// property. +bool TreePatternNode::TreeHasProperty(SDNP Property, + const CodeGenDAGPatterns &CGP) const { + if (NodeHasProperty(Property, CGP)) + return true; + for (unsigned i = 0, e = getNumChildren(); i != e; ++i) + if (getChild(i)->TreeHasProperty(Property, CGP)) + return true; + return false; +} + +/// isCommutativeIntrinsic - Return true if the node corresponds to a +/// commutative intrinsic. +bool +TreePatternNode::isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const { + if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) + return Int->isCommutative; + return false; +} + + +/// ApplyTypeConstraints - Apply all of the type constraints relevant to +/// this node and its children in the tree. This returns true if it makes a +/// change, false otherwise. If a type contradiction is found, throw an +/// exception. +bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { + CodeGenDAGPatterns &CDP = TP.getDAGPatterns(); + if (isLeaf()) { + if (DefInit *DI = dynamic_cast<DefInit*>(getLeafValue())) { + // If it's a regclass or something else known, include the type. + bool MadeChange = false; + for (unsigned i = 0, e = Types.size(); i != e; ++i) + MadeChange |= UpdateNodeType(i, getImplicitType(DI->getDef(), i, + NotRegisters, TP), TP); + return MadeChange; + } + + if (IntInit *II = dynamic_cast<IntInit*>(getLeafValue())) { + assert(Types.size() == 1 && "Invalid IntInit"); + + // Int inits are always integers. :) + bool MadeChange = Types[0].EnforceInteger(TP); + + if (!Types[0].isConcrete()) + return MadeChange; + + MVT::SimpleValueType VT = getType(0); + if (VT == MVT::iPTR || VT == MVT::iPTRAny) + return MadeChange; + + unsigned Size = EVT(VT).getSizeInBits(); + // Make sure that the value is representable for this type. + if (Size >= 32) return MadeChange; + + int Val = (II->getValue() << (32-Size)) >> (32-Size); + if (Val == II->getValue()) return MadeChange; + + // If sign-extended doesn't fit, does it fit as unsigned? + unsigned ValueMask; + unsigned UnsignedVal; + ValueMask = unsigned(~uint32_t(0UL) >> (32-Size)); + UnsignedVal = unsigned(II->getValue()); + + if ((ValueMask & UnsignedVal) == UnsignedVal) + return MadeChange; + + TP.error("Integer value '" + itostr(II->getValue())+ + "' is out of range for type '" + getEnumName(getType(0)) + "'!"); + return MadeChange; + } + return false; + } + + // special handling for set, which isn't really an SDNode. + if (getOperator()->getName() == "set") { + assert(getNumTypes() == 0 && "Set doesn't produce a value"); + assert(getNumChildren() >= 2 && "Missing RHS of a set?"); + unsigned NC = getNumChildren(); + + TreePatternNode *SetVal = getChild(NC-1); + bool MadeChange = SetVal->ApplyTypeConstraints(TP, NotRegisters); + + for (unsigned i = 0; i < NC-1; ++i) { + TreePatternNode *Child = getChild(i); + MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters); + + // Types of operands must match. + MadeChange |= Child->UpdateNodeType(0, SetVal->getExtType(i), TP); + MadeChange |= SetVal->UpdateNodeType(i, Child->getExtType(0), TP); + } + return MadeChange; + } + + if (getOperator()->getName() == "implicit") { + assert(getNumTypes() == 0 && "Node doesn't produce a value"); + + bool MadeChange = false; + for (unsigned i = 0; i < getNumChildren(); ++i) + MadeChange = getChild(i)->ApplyTypeConstraints(TP, NotRegisters); + return MadeChange; + } + + if (getOperator()->getName() == "COPY_TO_REGCLASS") { + bool MadeChange = false; + MadeChange |= getChild(0)->ApplyTypeConstraints(TP, NotRegisters); + MadeChange |= getChild(1)->ApplyTypeConstraints(TP, NotRegisters); + + assert(getChild(0)->getNumTypes() == 1 && + getChild(1)->getNumTypes() == 1 && "Unhandled case"); + + // child #1 of COPY_TO_REGCLASS should be a register class. We don't care + // what type it gets, so if it didn't get a concrete type just give it the + // first viable type from the reg class. + if (!getChild(1)->hasTypeSet(0) && + !getChild(1)->getExtType(0).isCompletelyUnknown()) { + MVT::SimpleValueType RCVT = getChild(1)->getExtType(0).getTypeList()[0]; + MadeChange |= getChild(1)->UpdateNodeType(0, RCVT, TP); + } + return MadeChange; + } + + if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) { + bool MadeChange = false; + + // Apply the result type to the node. + unsigned NumRetVTs = Int->IS.RetVTs.size(); + unsigned NumParamVTs = Int->IS.ParamVTs.size(); + + for (unsigned i = 0, e = NumRetVTs; i != e; ++i) + MadeChange |= UpdateNodeType(i, Int->IS.RetVTs[i], TP); + + if (getNumChildren() != NumParamVTs + 1) + TP.error("Intrinsic '" + Int->Name + "' expects " + + utostr(NumParamVTs) + " operands, not " + + utostr(getNumChildren() - 1) + " operands!"); + + // Apply type info to the intrinsic ID. + MadeChange |= getChild(0)->UpdateNodeType(0, MVT::iPTR, TP); + + for (unsigned i = 0, e = getNumChildren()-1; i != e; ++i) { + MadeChange |= getChild(i+1)->ApplyTypeConstraints(TP, NotRegisters); + + MVT::SimpleValueType OpVT = Int->IS.ParamVTs[i]; + assert(getChild(i+1)->getNumTypes() == 1 && "Unhandled case"); + MadeChange |= getChild(i+1)->UpdateNodeType(0, OpVT, TP); + } + return MadeChange; + } + + if (getOperator()->isSubClassOf("SDNode")) { + const SDNodeInfo &NI = CDP.getSDNodeInfo(getOperator()); + + // Check that the number of operands is sane. Negative operands -> varargs. + if (NI.getNumOperands() >= 0 && + getNumChildren() != (unsigned)NI.getNumOperands()) + TP.error(getOperator()->getName() + " node requires exactly " + + itostr(NI.getNumOperands()) + " operands!"); + + bool MadeChange = NI.ApplyTypeConstraints(this, TP); + for (unsigned i = 0, e = getNumChildren(); i != e; ++i) + MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters); + return MadeChange; + } + + if (getOperator()->isSubClassOf("Instruction")) { + const DAGInstruction &Inst = CDP.getInstruction(getOperator()); + CodeGenInstruction &InstInfo = + CDP.getTargetInfo().getInstruction(getOperator()); + + bool MadeChange = false; + + // Apply the result types to the node, these come from the things in the + // (outs) list of the instruction. + // FIXME: Cap at one result so far. + unsigned NumResultsToAdd = InstInfo.Operands.NumDefs ? 1 : 0; + for (unsigned ResNo = 0; ResNo != NumResultsToAdd; ++ResNo) { + Record *ResultNode = Inst.getResult(ResNo); + + if (ResultNode->isSubClassOf("PointerLikeRegClass")) { + MadeChange |= UpdateNodeType(ResNo, MVT::iPTR, TP); + } else if (ResultNode->isSubClassOf("RegisterOperand")) { + Record *RegClass = ResultNode->getValueAsDef("RegClass"); + const CodeGenRegisterClass &RC = + CDP.getTargetInfo().getRegisterClass(RegClass); + MadeChange |= UpdateNodeType(ResNo, RC.getValueTypes(), TP); + } else if (ResultNode->getName() == "unknown") { + // Nothing to do. + } else { + assert(ResultNode->isSubClassOf("RegisterClass") && + "Operands should be register classes!"); + const CodeGenRegisterClass &RC = + CDP.getTargetInfo().getRegisterClass(ResultNode); + MadeChange |= UpdateNodeType(ResNo, RC.getValueTypes(), TP); + } + } + + // If the instruction has implicit defs, we apply the first one as a result. + // FIXME: This sucks, it should apply all implicit defs. + if (!InstInfo.ImplicitDefs.empty()) { + unsigned ResNo = NumResultsToAdd; + + // FIXME: Generalize to multiple possible types and multiple possible + // ImplicitDefs. + MVT::SimpleValueType VT = + InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()); + + if (VT != MVT::Other) + MadeChange |= UpdateNodeType(ResNo, VT, TP); + } + + // If this is an INSERT_SUBREG, constrain the source and destination VTs to + // be the same. + if (getOperator()->getName() == "INSERT_SUBREG") { + assert(getChild(0)->getNumTypes() == 1 && "FIXME: Unhandled"); + MadeChange |= UpdateNodeType(0, getChild(0)->getExtType(0), TP); + MadeChange |= getChild(0)->UpdateNodeType(0, getExtType(0), TP); + } + + unsigned ChildNo = 0; + for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) { + Record *OperandNode = Inst.getOperand(i); + + // If the instruction expects a predicate or optional def operand, we + // codegen this by setting the operand to it's default value if it has a + // non-empty DefaultOps field. + if ((OperandNode->isSubClassOf("PredicateOperand") || + OperandNode->isSubClassOf("OptionalDefOperand")) && + !CDP.getDefaultOperand(OperandNode).DefaultOps.empty()) + continue; + + // Verify that we didn't run out of provided operands. + if (ChildNo >= getNumChildren()) + TP.error("Instruction '" + getOperator()->getName() + + "' expects more operands than were provided."); + + MVT::SimpleValueType VT; + TreePatternNode *Child = getChild(ChildNo++); + unsigned ChildResNo = 0; // Instructions always use res #0 of their op. + + if (OperandNode->isSubClassOf("RegisterClass")) { + const CodeGenRegisterClass &RC = + CDP.getTargetInfo().getRegisterClass(OperandNode); + MadeChange |= Child->UpdateNodeType(ChildResNo, RC.getValueTypes(), TP); + } else if (OperandNode->isSubClassOf("RegisterOperand")) { + Record *RegClass = OperandNode->getValueAsDef("RegClass"); + const CodeGenRegisterClass &RC = + CDP.getTargetInfo().getRegisterClass(RegClass); + MadeChange |= Child->UpdateNodeType(ChildResNo, RC.getValueTypes(), TP); + } else if (OperandNode->isSubClassOf("Operand")) { + VT = getValueType(OperandNode->getValueAsDef("Type")); + MadeChange |= Child->UpdateNodeType(ChildResNo, VT, TP); + } else if (OperandNode->isSubClassOf("PointerLikeRegClass")) { + MadeChange |= Child->UpdateNodeType(ChildResNo, MVT::iPTR, TP); + } else if (OperandNode->getName() == "unknown") { + // Nothing to do. + } else + llvm_unreachable("Unknown operand type!"); + + MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters); + } + + if (ChildNo != getNumChildren()) + TP.error("Instruction '" + getOperator()->getName() + + "' was provided too many operands!"); + + return MadeChange; + } + + assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!"); + + // Node transforms always take one operand. + if (getNumChildren() != 1) + TP.error("Node transform '" + getOperator()->getName() + + "' requires one operand!"); + + bool MadeChange = getChild(0)->ApplyTypeConstraints(TP, NotRegisters); + + + // If either the output or input of the xform does not have exact + // type info. We assume they must be the same. Otherwise, it is perfectly + // legal to transform from one type to a completely different type. +#if 0 + if (!hasTypeSet() || !getChild(0)->hasTypeSet()) { + bool MadeChange = UpdateNodeType(getChild(0)->getExtType(), TP); + MadeChange |= getChild(0)->UpdateNodeType(getExtType(), TP); + return MadeChange; + } +#endif + return MadeChange; +} + +/// OnlyOnRHSOfCommutative - Return true if this value is only allowed on the +/// RHS of a commutative operation, not the on LHS. +static bool OnlyOnRHSOfCommutative(TreePatternNode *N) { + if (!N->isLeaf() && N->getOperator()->getName() == "imm") + return true; + if (N->isLeaf() && dynamic_cast<IntInit*>(N->getLeafValue())) + return true; + return false; +} + + +/// canPatternMatch - If it is impossible for this pattern to match on this +/// target, fill in Reason and return false. Otherwise, return true. This is +/// used as a sanity check for .td files (to prevent people from writing stuff +/// that can never possibly work), and to prevent the pattern permuter from +/// generating stuff that is useless. +bool TreePatternNode::canPatternMatch(std::string &Reason, + const CodeGenDAGPatterns &CDP) { + if (isLeaf()) return true; + + for (unsigned i = 0, e = getNumChildren(); i != e; ++i) + if (!getChild(i)->canPatternMatch(Reason, CDP)) + return false; + + // If this is an intrinsic, handle cases that would make it not match. For + // example, if an operand is required to be an immediate. + if (getOperator()->isSubClassOf("Intrinsic")) { + // TODO: + return true; + } + + // If this node is a commutative operator, check that the LHS isn't an + // immediate. + const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(getOperator()); + bool isCommIntrinsic = isCommutativeIntrinsic(CDP); + if (NodeInfo.hasProperty(SDNPCommutative) || isCommIntrinsic) { + // Scan all of the operands of the node and make sure that only the last one + // is a constant node, unless the RHS also is. + if (!OnlyOnRHSOfCommutative(getChild(getNumChildren()-1))) { + bool Skip = isCommIntrinsic ? 1 : 0; // First operand is intrinsic id. + for (unsigned i = Skip, e = getNumChildren()-1; i != e; ++i) + if (OnlyOnRHSOfCommutative(getChild(i))) { + Reason="Immediate value must be on the RHS of commutative operators!"; + return false; + } + } + } + + return true; +} + +//===----------------------------------------------------------------------===// +// TreePattern implementation +// + +TreePattern::TreePattern(Record *TheRec, ListInit *RawPat, bool isInput, + CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp){ + isInputPattern = isInput; + for (unsigned i = 0, e = RawPat->getSize(); i != e; ++i) + Trees.push_back(ParseTreePattern(RawPat->getElement(i), "")); +} + +TreePattern::TreePattern(Record *TheRec, DagInit *Pat, bool isInput, + CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp){ + isInputPattern = isInput; + Trees.push_back(ParseTreePattern(Pat, "")); +} + +TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput, + CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp){ + isInputPattern = isInput; + Trees.push_back(Pat); +} + +void TreePattern::error(const std::string &Msg) const { + dump(); + throw TGError(TheRecord->getLoc(), "In " + TheRecord->getName() + ": " + Msg); +} + +void TreePattern::ComputeNamedNodes() { + for (unsigned i = 0, e = Trees.size(); i != e; ++i) + ComputeNamedNodes(Trees[i]); +} + +void TreePattern::ComputeNamedNodes(TreePatternNode *N) { + if (!N->getName().empty()) + NamedNodes[N->getName()].push_back(N); + + for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) + ComputeNamedNodes(N->getChild(i)); +} + + +TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ + if (DefInit *DI = dynamic_cast<DefInit*>(TheInit)) { + Record *R = DI->getDef(); + + // Direct reference to a leaf DagNode or PatFrag? Turn it into a + // TreePatternNode of its own. For example: + /// (foo GPR, imm) -> (foo GPR, (imm)) + if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag")) + return ParseTreePattern( + DagInit::get(DI, "", + std::vector<std::pair<Init*, std::string> >()), + OpName); + + // Input argument? + TreePatternNode *Res = new TreePatternNode(DI, 1); + if (R->getName() == "node" && !OpName.empty()) { + if (OpName.empty()) + error("'node' argument requires a name to match with operand list"); + Args.push_back(OpName); + } + + Res->setName(OpName); + return Res; + } + + if (IntInit *II = dynamic_cast<IntInit*>(TheInit)) { + if (!OpName.empty()) + error("Constant int argument should not have a name!"); + return new TreePatternNode(II, 1); + } + + if (BitsInit *BI = dynamic_cast<BitsInit*>(TheInit)) { + // Turn this into an IntInit. + Init *II = BI->convertInitializerTo(IntRecTy::get()); + if (II == 0 || !dynamic_cast<IntInit*>(II)) + error("Bits value must be constants!"); + return ParseTreePattern(II, OpName); + } + + DagInit *Dag = dynamic_cast<DagInit*>(TheInit); + if (!Dag) { + TheInit->dump(); + error("Pattern has unexpected init kind!"); + } + DefInit *OpDef = dynamic_cast<DefInit*>(Dag->getOperator()); + if (!OpDef) error("Pattern has unexpected operator type!"); + Record *Operator = OpDef->getDef(); + + if (Operator->isSubClassOf("ValueType")) { + // If the operator is a ValueType, then this must be "type cast" of a leaf + // node. + if (Dag->getNumArgs() != 1) + error("Type cast only takes one operand!"); + + TreePatternNode *New = ParseTreePattern(Dag->getArg(0), Dag->getArgName(0)); + + // Apply the type cast. + assert(New->getNumTypes() == 1 && "FIXME: Unhandled"); + New->UpdateNodeType(0, getValueType(Operator), *this); + + if (!OpName.empty()) + error("ValueType cast should not have a name!"); + return New; + } + + // Verify that this is something that makes sense for an operator. + if (!Operator->isSubClassOf("PatFrag") && + !Operator->isSubClassOf("SDNode") && + !Operator->isSubClassOf("Instruction") && + !Operator->isSubClassOf("SDNodeXForm") && + !Operator->isSubClassOf("Intrinsic") && + Operator->getName() != "set" && + Operator->getName() != "implicit") + error("Unrecognized node '" + Operator->getName() + "'!"); + + // Check to see if this is something that is illegal in an input pattern. + if (isInputPattern) { + if (Operator->isSubClassOf("Instruction") || + Operator->isSubClassOf("SDNodeXForm")) + error("Cannot use '" + Operator->getName() + "' in an input pattern!"); + } else { + if (Operator->isSubClassOf("Intrinsic")) + error("Cannot use '" + Operator->getName() + "' in an output pattern!"); + + if (Operator->isSubClassOf("SDNode") && + Operator->getName() != "imm" && + Operator->getName() != "fpimm" && + Operator->getName() != "tglobaltlsaddr" && + Operator->getName() != "tconstpool" && + Operator->getName() != "tjumptable" && + Operator->getName() != "tframeindex" && + Operator->getName() != "texternalsym" && + Operator->getName() != "tblockaddress" && + Operator->getName() != "tglobaladdr" && + Operator->getName() != "bb" && + Operator->getName() != "vt") + error("Cannot use '" + Operator->getName() + "' in an output pattern!"); + } + + std::vector<TreePatternNode*> Children; + + // Parse all the operands. + for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) + Children.push_back(ParseTreePattern(Dag->getArg(i), Dag->getArgName(i))); + + // If the operator is an intrinsic, then this is just syntactic sugar for for + // (intrinsic_* <number>, ..children..). Pick the right intrinsic node, and + // convert the intrinsic name to a number. + if (Operator->isSubClassOf("Intrinsic")) { + const CodeGenIntrinsic &Int = getDAGPatterns().getIntrinsic(Operator); + unsigned IID = getDAGPatterns().getIntrinsicID(Operator)+1; + + // If this intrinsic returns void, it must have side-effects and thus a + // chain. + if (Int.IS.RetVTs.empty()) + Operator = getDAGPatterns().get_intrinsic_void_sdnode(); + else if (Int.ModRef != CodeGenIntrinsic::NoMem) + // Has side-effects, requires chain. + Operator = getDAGPatterns().get_intrinsic_w_chain_sdnode(); + else // Otherwise, no chain. + Operator = getDAGPatterns().get_intrinsic_wo_chain_sdnode(); + + TreePatternNode *IIDNode = new TreePatternNode(IntInit::get(IID), 1); + Children.insert(Children.begin(), IIDNode); + } + + unsigned NumResults = GetNumNodeResults(Operator, CDP); + TreePatternNode *Result = new TreePatternNode(Operator, Children, NumResults); + Result->setName(OpName); + + if (!Dag->getName().empty()) { + assert(Result->getName().empty()); + Result->setName(Dag->getName()); + } + return Result; +} + +/// SimplifyTree - See if we can simplify this tree to eliminate something that +/// will never match in favor of something obvious that will. This is here +/// strictly as a convenience to target authors because it allows them to write +/// more type generic things and have useless type casts fold away. +/// +/// This returns true if any change is made. +static bool SimplifyTree(TreePatternNode *&N) { + if (N->isLeaf()) + return false; + + // If we have a bitconvert with a resolved type and if the source and + // destination types are the same, then the bitconvert is useless, remove it. + if (N->getOperator()->getName() == "bitconvert" && + N->getExtType(0).isConcrete() && + N->getExtType(0) == N->getChild(0)->getExtType(0) && + N->getName().empty()) { + N = N->getChild(0); + SimplifyTree(N); + return true; + } + + // Walk all children. + bool MadeChange = false; + for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) { + TreePatternNode *Child = N->getChild(i); + MadeChange |= SimplifyTree(Child); + N->setChild(i, Child); + } + return MadeChange; +} + + + +/// InferAllTypes - Infer/propagate as many types throughout the expression +/// patterns as possible. Return true if all types are inferred, false +/// otherwise. Throw an exception if a type contradiction is found. +bool TreePattern:: +InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) { + if (NamedNodes.empty()) + ComputeNamedNodes(); + + bool MadeChange = true; + while (MadeChange) { + MadeChange = false; + for (unsigned i = 0, e = Trees.size(); i != e; ++i) { + MadeChange |= Trees[i]->ApplyTypeConstraints(*this, false); + MadeChange |= SimplifyTree(Trees[i]); + } + + // If there are constraints on our named nodes, apply them. + for (StringMap<SmallVector<TreePatternNode*,1> >::iterator + I = NamedNodes.begin(), E = NamedNodes.end(); I != E; ++I) { + SmallVectorImpl<TreePatternNode*> &Nodes = I->second; + + // If we have input named node types, propagate their types to the named + // values here. + if (InNamedTypes) { + // FIXME: Should be error? + assert(InNamedTypes->count(I->getKey()) && + "Named node in output pattern but not input pattern?"); + + const SmallVectorImpl<TreePatternNode*> &InNodes = + InNamedTypes->find(I->getKey())->second; + + // The input types should be fully resolved by now. + for (unsigned i = 0, e = Nodes.size(); i != e; ++i) { + // If this node is a register class, and it is the root of the pattern + // then we're mapping something onto an input register. We allow + // changing the type of the input register in this case. This allows + // us to match things like: + // def : Pat<(v1i64 (bitconvert(v2i32 DPR:$src))), (v1i64 DPR:$src)>; + if (Nodes[i] == Trees[0] && Nodes[i]->isLeaf()) { + DefInit *DI = dynamic_cast<DefInit*>(Nodes[i]->getLeafValue()); + if (DI && (DI->getDef()->isSubClassOf("RegisterClass") || + DI->getDef()->isSubClassOf("RegisterOperand"))) + continue; + } + + assert(Nodes[i]->getNumTypes() == 1 && + InNodes[0]->getNumTypes() == 1 && + "FIXME: cannot name multiple result nodes yet"); + MadeChange |= Nodes[i]->UpdateNodeType(0, InNodes[0]->getExtType(0), + *this); + } + } + + // If there are multiple nodes with the same name, they must all have the + // same type. + if (I->second.size() > 1) { + for (unsigned i = 0, e = Nodes.size()-1; i != e; ++i) { + TreePatternNode *N1 = Nodes[i], *N2 = Nodes[i+1]; + assert(N1->getNumTypes() == 1 && N2->getNumTypes() == 1 && + "FIXME: cannot name multiple result nodes yet"); + + MadeChange |= N1->UpdateNodeType(0, N2->getExtType(0), *this); + MadeChange |= N2->UpdateNodeType(0, N1->getExtType(0), *this); + } + } + } + } + + bool HasUnresolvedTypes = false; + for (unsigned i = 0, e = Trees.size(); i != e; ++i) + HasUnresolvedTypes |= Trees[i]->ContainsUnresolvedType(); + return !HasUnresolvedTypes; +} + +void TreePattern::print(raw_ostream &OS) const { + OS << getRecord()->getName(); + if (!Args.empty()) { + OS << "(" << Args[0]; + for (unsigned i = 1, e = Args.size(); i != e; ++i) + OS << ", " << Args[i]; + OS << ")"; + } + OS << ": "; + + if (Trees.size() > 1) + OS << "[\n"; + for (unsigned i = 0, e = Trees.size(); i != e; ++i) { + OS << "\t"; + Trees[i]->print(OS); + OS << "\n"; + } + + if (Trees.size() > 1) + OS << "]\n"; +} + +void TreePattern::dump() const { print(errs()); } + +//===----------------------------------------------------------------------===// +// CodeGenDAGPatterns implementation +// + +CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : + Records(R), Target(R) { + + Intrinsics = LoadIntrinsics(Records, false); + TgtIntrinsics = LoadIntrinsics(Records, true); + ParseNodeInfo(); + ParseNodeTransforms(); + ParseComplexPatterns(); + ParsePatternFragments(); + ParseDefaultOperands(); + ParseInstructions(); + ParsePatterns(); + + // Generate variants. For example, commutative patterns can match + // multiple ways. Add them to PatternsToMatch as well. + GenerateVariants(); + + // Infer instruction flags. For example, we can detect loads, + // stores, and side effects in many cases by examining an + // instruction's pattern. + InferInstructionFlags(); +} + +CodeGenDAGPatterns::~CodeGenDAGPatterns() { + for (pf_iterator I = PatternFragments.begin(), + E = PatternFragments.end(); I != E; ++I) + delete I->second; +} + + +Record *CodeGenDAGPatterns::getSDNodeNamed(const std::string &Name) const { + Record *N = Records.getDef(Name); + if (!N || !N->isSubClassOf("SDNode")) { + errs() << "Error getting SDNode '" << Name << "'!\n"; + exit(1); + } + return N; +} + +// Parse all of the SDNode definitions for the target, populating SDNodes. +void CodeGenDAGPatterns::ParseNodeInfo() { + std::vector<Record*> Nodes = Records.getAllDerivedDefinitions("SDNode"); + while (!Nodes.empty()) { + SDNodes.insert(std::make_pair(Nodes.back(), Nodes.back())); + Nodes.pop_back(); + } + + // Get the builtin intrinsic nodes. + intrinsic_void_sdnode = getSDNodeNamed("intrinsic_void"); + intrinsic_w_chain_sdnode = getSDNodeNamed("intrinsic_w_chain"); + intrinsic_wo_chain_sdnode = getSDNodeNamed("intrinsic_wo_chain"); +} + +/// ParseNodeTransforms - Parse all SDNodeXForm instances into the SDNodeXForms +/// map, and emit them to the file as functions. +void CodeGenDAGPatterns::ParseNodeTransforms() { + std::vector<Record*> Xforms = Records.getAllDerivedDefinitions("SDNodeXForm"); + while (!Xforms.empty()) { + Record *XFormNode = Xforms.back(); + Record *SDNode = XFormNode->getValueAsDef("Opcode"); + std::string Code = XFormNode->getValueAsString("XFormFunction"); + SDNodeXForms.insert(std::make_pair(XFormNode, NodeXForm(SDNode, Code))); + + Xforms.pop_back(); + } +} + +void CodeGenDAGPatterns::ParseComplexPatterns() { + std::vector<Record*> AMs = Records.getAllDerivedDefinitions("ComplexPattern"); + while (!AMs.empty()) { + ComplexPatterns.insert(std::make_pair(AMs.back(), AMs.back())); + AMs.pop_back(); + } +} + + +/// ParsePatternFragments - Parse all of the PatFrag definitions in the .td +/// file, building up the PatternFragments map. After we've collected them all, +/// inline fragments together as necessary, so that there are no references left +/// inside a pattern fragment to a pattern fragment. +/// +void CodeGenDAGPatterns::ParsePatternFragments() { + std::vector<Record*> Fragments = Records.getAllDerivedDefinitions("PatFrag"); + + // First step, parse all of the fragments. + for (unsigned i = 0, e = Fragments.size(); i != e; ++i) { + DagInit *Tree = Fragments[i]->getValueAsDag("Fragment"); + TreePattern *P = new TreePattern(Fragments[i], Tree, true, *this); + PatternFragments[Fragments[i]] = P; + + // Validate the argument list, converting it to set, to discard duplicates. + std::vector<std::string> &Args = P->getArgList(); + std::set<std::string> OperandsSet(Args.begin(), Args.end()); + + if (OperandsSet.count("")) + P->error("Cannot have unnamed 'node' values in pattern fragment!"); + + // Parse the operands list. + DagInit *OpsList = Fragments[i]->getValueAsDag("Operands"); + DefInit *OpsOp = dynamic_cast<DefInit*>(OpsList->getOperator()); + // Special cases: ops == outs == ins. Different names are used to + // improve readability. + if (!OpsOp || + (OpsOp->getDef()->getName() != "ops" && + OpsOp->getDef()->getName() != "outs" && + OpsOp->getDef()->getName() != "ins")) + P->error("Operands list should start with '(ops ... '!"); + + // Copy over the arguments. + Args.clear(); + for (unsigned j = 0, e = OpsList->getNumArgs(); j != e; ++j) { + if (!dynamic_cast<DefInit*>(OpsList->getArg(j)) || + static_cast<DefInit*>(OpsList->getArg(j))-> + getDef()->getName() != "node") + P->error("Operands list should all be 'node' values."); + if (OpsList->getArgName(j).empty()) + P->error("Operands list should have names for each operand!"); + if (!OperandsSet.count(OpsList->getArgName(j))) + P->error("'" + OpsList->getArgName(j) + + "' does not occur in pattern or was multiply specified!"); + OperandsSet.erase(OpsList->getArgName(j)); + Args.push_back(OpsList->getArgName(j)); + } + + if (!OperandsSet.empty()) + P->error("Operands list does not contain an entry for operand '" + + *OperandsSet.begin() + "'!"); + + // If there is a code init for this fragment, keep track of the fact that + // this fragment uses it. + TreePredicateFn PredFn(P); + if (!PredFn.isAlwaysTrue()) + P->getOnlyTree()->addPredicateFn(PredFn); + + // If there is a node transformation corresponding to this, keep track of + // it. + Record *Transform = Fragments[i]->getValueAsDef("OperandTransform"); + if (!getSDNodeTransform(Transform).second.empty()) // not noop xform? + P->getOnlyTree()->setTransformFn(Transform); + } + + // Now that we've parsed all of the tree fragments, do a closure on them so + // that there are not references to PatFrags left inside of them. + for (unsigned i = 0, e = Fragments.size(); i != e; ++i) { + TreePattern *ThePat = PatternFragments[Fragments[i]]; + ThePat->InlinePatternFragments(); + + // Infer as many types as possible. Don't worry about it if we don't infer + // all of them, some may depend on the inputs of the pattern. + try { + ThePat->InferAllTypes(); + } catch (...) { + // If this pattern fragment is not supported by this target (no types can + // satisfy its constraints), just ignore it. If the bogus pattern is + // actually used by instructions, the type consistency error will be + // reported there. + } + + // If debugging, print out the pattern fragment result. + DEBUG(ThePat->dump()); + } +} + +void CodeGenDAGPatterns::ParseDefaultOperands() { + std::vector<Record*> DefaultOps[2]; + DefaultOps[0] = Records.getAllDerivedDefinitions("PredicateOperand"); + DefaultOps[1] = Records.getAllDerivedDefinitions("OptionalDefOperand"); + + // Find some SDNode. + assert(!SDNodes.empty() && "No SDNodes parsed?"); + Init *SomeSDNode = DefInit::get(SDNodes.begin()->first); + + for (unsigned iter = 0; iter != 2; ++iter) { + for (unsigned i = 0, e = DefaultOps[iter].size(); i != e; ++i) { + DagInit *DefaultInfo = DefaultOps[iter][i]->getValueAsDag("DefaultOps"); + + // Clone the DefaultInfo dag node, changing the operator from 'ops' to + // SomeSDnode so that we can parse this. + std::vector<std::pair<Init*, std::string> > Ops; + for (unsigned op = 0, e = DefaultInfo->getNumArgs(); op != e; ++op) + Ops.push_back(std::make_pair(DefaultInfo->getArg(op), + DefaultInfo->getArgName(op))); + DagInit *DI = DagInit::get(SomeSDNode, "", Ops); + + // Create a TreePattern to parse this. + TreePattern P(DefaultOps[iter][i], DI, false, *this); + assert(P.getNumTrees() == 1 && "This ctor can only produce one tree!"); + + // Copy the operands over into a DAGDefaultOperand. + DAGDefaultOperand DefaultOpInfo; + + TreePatternNode *T = P.getTree(0); + for (unsigned op = 0, e = T->getNumChildren(); op != e; ++op) { + TreePatternNode *TPN = T->getChild(op); + while (TPN->ApplyTypeConstraints(P, false)) + /* Resolve all types */; + + if (TPN->ContainsUnresolvedType()) { + if (iter == 0) + throw "Value #" + utostr(i) + " of PredicateOperand '" + + DefaultOps[iter][i]->getName() +"' doesn't have a concrete type!"; + else + throw "Value #" + utostr(i) + " of OptionalDefOperand '" + + DefaultOps[iter][i]->getName() +"' doesn't have a concrete type!"; + } + DefaultOpInfo.DefaultOps.push_back(TPN); + } + + // Insert it into the DefaultOperands map so we can find it later. + DefaultOperands[DefaultOps[iter][i]] = DefaultOpInfo; + } + } +} + +/// HandleUse - Given "Pat" a leaf in the pattern, check to see if it is an +/// instruction input. Return true if this is a real use. +static bool HandleUse(TreePattern *I, TreePatternNode *Pat, + std::map<std::string, TreePatternNode*> &InstInputs) { + // No name -> not interesting. + if (Pat->getName().empty()) { + if (Pat->isLeaf()) { + DefInit *DI = dynamic_cast<DefInit*>(Pat->getLeafValue()); + if (DI && (DI->getDef()->isSubClassOf("RegisterClass") || + DI->getDef()->isSubClassOf("RegisterOperand"))) + I->error("Input " + DI->getDef()->getName() + " must be named!"); + } + return false; + } + + Record *Rec; + if (Pat->isLeaf()) { + DefInit *DI = dynamic_cast<DefInit*>(Pat->getLeafValue()); + if (!DI) I->error("Input $" + Pat->getName() + " must be an identifier!"); + Rec = DI->getDef(); + } else { + Rec = Pat->getOperator(); + } + + // SRCVALUE nodes are ignored. + if (Rec->getName() == "srcvalue") + return false; + + TreePatternNode *&Slot = InstInputs[Pat->getName()]; + if (!Slot) { + Slot = Pat; + return true; + } + Record *SlotRec; + if (Slot->isLeaf()) { + SlotRec = dynamic_cast<DefInit*>(Slot->getLeafValue())->getDef(); + } else { + assert(Slot->getNumChildren() == 0 && "can't be a use with children!"); + SlotRec = Slot->getOperator(); + } + + // Ensure that the inputs agree if we've already seen this input. + if (Rec != SlotRec) + I->error("All $" + Pat->getName() + " inputs must agree with each other"); + if (Slot->getExtTypes() != Pat->getExtTypes()) + I->error("All $" + Pat->getName() + " inputs must agree with each other"); + return true; +} + +/// FindPatternInputsAndOutputs - Scan the specified TreePatternNode (which is +/// part of "I", the instruction), computing the set of inputs and outputs of +/// the pattern. Report errors if we see anything naughty. +void CodeGenDAGPatterns:: +FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, + std::map<std::string, TreePatternNode*> &InstInputs, + std::map<std::string, TreePatternNode*>&InstResults, + std::vector<Record*> &InstImpResults) { + if (Pat->isLeaf()) { + bool isUse = HandleUse(I, Pat, InstInputs); + if (!isUse && Pat->getTransformFn()) + I->error("Cannot specify a transform function for a non-input value!"); + return; + } + + if (Pat->getOperator()->getName() == "implicit") { + for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) { + TreePatternNode *Dest = Pat->getChild(i); + if (!Dest->isLeaf()) + I->error("implicitly defined value should be a register!"); + + DefInit *Val = dynamic_cast<DefInit*>(Dest->getLeafValue()); + if (!Val || !Val->getDef()->isSubClassOf("Register")) + I->error("implicitly defined value should be a register!"); + InstImpResults.push_back(Val->getDef()); + } + return; + } + + if (Pat->getOperator()->getName() != "set") { + // If this is not a set, verify that the children nodes are not void typed, + // and recurse. + for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) { + if (Pat->getChild(i)->getNumTypes() == 0) + I->error("Cannot have void nodes inside of patterns!"); + FindPatternInputsAndOutputs(I, Pat->getChild(i), InstInputs, InstResults, + InstImpResults); + } + + // If this is a non-leaf node with no children, treat it basically as if + // it were a leaf. This handles nodes like (imm). + bool isUse = HandleUse(I, Pat, InstInputs); + + if (!isUse && Pat->getTransformFn()) + I->error("Cannot specify a transform function for a non-input value!"); + return; + } + + // Otherwise, this is a set, validate and collect instruction results. + if (Pat->getNumChildren() == 0) + I->error("set requires operands!"); + + if (Pat->getTransformFn()) + I->error("Cannot specify a transform function on a set node!"); + + // Check the set destinations. + unsigned NumDests = Pat->getNumChildren()-1; + for (unsigned i = 0; i != NumDests; ++i) { + TreePatternNode *Dest = Pat->getChild(i); + if (!Dest->isLeaf()) + I->error("set destination should be a register!"); + + DefInit *Val = dynamic_cast<DefInit*>(Dest->getLeafValue()); + if (!Val) + I->error("set destination should be a register!"); + + if (Val->getDef()->isSubClassOf("RegisterClass") || + Val->getDef()->isSubClassOf("RegisterOperand") || + Val->getDef()->isSubClassOf("PointerLikeRegClass")) { + if (Dest->getName().empty()) + I->error("set destination must have a name!"); + if (InstResults.count(Dest->getName())) + I->error("cannot set '" + Dest->getName() +"' multiple times"); + InstResults[Dest->getName()] = Dest; + } else if (Val->getDef()->isSubClassOf("Register")) { + InstImpResults.push_back(Val->getDef()); + } else { + I->error("set destination should be a register!"); + } + } + + // Verify and collect info from the computation. + FindPatternInputsAndOutputs(I, Pat->getChild(NumDests), + InstInputs, InstResults, InstImpResults); +} + +//===----------------------------------------------------------------------===// +// Instruction Analysis +//===----------------------------------------------------------------------===// + +class InstAnalyzer { + const CodeGenDAGPatterns &CDP; + bool &mayStore; + bool &mayLoad; + bool &IsBitcast; + bool &HasSideEffects; + bool &IsVariadic; +public: + InstAnalyzer(const CodeGenDAGPatterns &cdp, + bool &maystore, bool &mayload, bool &isbc, bool &hse, bool &isv) + : CDP(cdp), mayStore(maystore), mayLoad(mayload), IsBitcast(isbc), + HasSideEffects(hse), IsVariadic(isv) { + } + + /// Analyze - Analyze the specified instruction, returning true if the + /// instruction had a pattern. + bool Analyze(Record *InstRecord) { + const TreePattern *Pattern = CDP.getInstruction(InstRecord).getPattern(); + if (Pattern == 0) { + HasSideEffects = 1; + return false; // No pattern. + } + + // FIXME: Assume only the first tree is the pattern. The others are clobber + // nodes. + AnalyzeNode(Pattern->getTree(0)); + return true; + } + +private: + bool IsNodeBitcast(const TreePatternNode *N) const { + if (HasSideEffects || mayLoad || mayStore || IsVariadic) + return false; + + if (N->getNumChildren() != 2) + return false; + + const TreePatternNode *N0 = N->getChild(0); + if (!N0->isLeaf() || !dynamic_cast<DefInit*>(N0->getLeafValue())) + return false; + + const TreePatternNode *N1 = N->getChild(1); + if (N1->isLeaf()) + return false; + if (N1->getNumChildren() != 1 || !N1->getChild(0)->isLeaf()) + return false; + + const SDNodeInfo &OpInfo = CDP.getSDNodeInfo(N1->getOperator()); + if (OpInfo.getNumResults() != 1 || OpInfo.getNumOperands() != 1) + return false; + return OpInfo.getEnumName() == "ISD::BITCAST"; + } + + void AnalyzeNode(const TreePatternNode *N) { + if (N->isLeaf()) { + if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) { + Record *LeafRec = DI->getDef(); + // Handle ComplexPattern leaves. + if (LeafRec->isSubClassOf("ComplexPattern")) { + const ComplexPattern &CP = CDP.getComplexPattern(LeafRec); + if (CP.hasProperty(SDNPMayStore)) mayStore = true; + if (CP.hasProperty(SDNPMayLoad)) mayLoad = true; + if (CP.hasProperty(SDNPSideEffect)) HasSideEffects = true; + } + } + return; + } + + // Analyze children. + for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) + AnalyzeNode(N->getChild(i)); + + // Ignore set nodes, which are not SDNodes. + if (N->getOperator()->getName() == "set") { + IsBitcast = IsNodeBitcast(N); + return; + } + + // Get information about the SDNode for the operator. + const SDNodeInfo &OpInfo = CDP.getSDNodeInfo(N->getOperator()); + + // Notice properties of the node. + if (OpInfo.hasProperty(SDNPMayStore)) mayStore = true; + if (OpInfo.hasProperty(SDNPMayLoad)) mayLoad = true; + if (OpInfo.hasProperty(SDNPSideEffect)) HasSideEffects = true; + if (OpInfo.hasProperty(SDNPVariadic)) IsVariadic = true; + + if (const CodeGenIntrinsic *IntInfo = N->getIntrinsicInfo(CDP)) { + // If this is an intrinsic, analyze it. + if (IntInfo->ModRef >= CodeGenIntrinsic::ReadArgMem) + mayLoad = true;// These may load memory. + + if (IntInfo->ModRef >= CodeGenIntrinsic::ReadWriteArgMem) + mayStore = true;// Intrinsics that can write to memory are 'mayStore'. + + if (IntInfo->ModRef >= CodeGenIntrinsic::ReadWriteMem) + // WriteMem intrinsics can have other strange effects. + HasSideEffects = true; + } + } + +}; + +static void InferFromPattern(const CodeGenInstruction &Inst, + bool &MayStore, bool &MayLoad, + bool &IsBitcast, + bool &HasSideEffects, bool &IsVariadic, + const CodeGenDAGPatterns &CDP) { + MayStore = MayLoad = IsBitcast = HasSideEffects = IsVariadic = false; + + bool HadPattern = + InstAnalyzer(CDP, MayStore, MayLoad, IsBitcast, HasSideEffects, IsVariadic) + .Analyze(Inst.TheDef); + + // InstAnalyzer only correctly analyzes mayStore/mayLoad so far. + if (Inst.mayStore) { // If the .td file explicitly sets mayStore, use it. + // If we decided that this is a store from the pattern, then the .td file + // entry is redundant. + if (MayStore) + PrintWarning(Inst.TheDef->getLoc(), + "mayStore flag explicitly set on " + "instruction, but flag already inferred from pattern."); + MayStore = true; + } + + if (Inst.mayLoad) { // If the .td file explicitly sets mayLoad, use it. + // If we decided that this is a load from the pattern, then the .td file + // entry is redundant. + if (MayLoad) + PrintWarning(Inst.TheDef->getLoc(), + "mayLoad flag explicitly set on " + "instruction, but flag already inferred from pattern."); + MayLoad = true; + } + + if (Inst.neverHasSideEffects) { + if (HadPattern) + PrintWarning(Inst.TheDef->getLoc(), + "neverHasSideEffects flag explicitly set on " + "instruction, but flag already inferred from pattern."); + HasSideEffects = false; + } + + if (Inst.hasSideEffects) { + if (HasSideEffects) + PrintWarning(Inst.TheDef->getLoc(), + "hasSideEffects flag explicitly set on " + "instruction, but flag already inferred from pattern."); + HasSideEffects = true; + } + + if (Inst.Operands.isVariadic) + IsVariadic = true; // Can warn if we want. +} + +/// ParseInstructions - Parse all of the instructions, inlining and resolving +/// any fragments involved. This populates the Instructions list with fully +/// resolved instructions. +void CodeGenDAGPatterns::ParseInstructions() { + std::vector<Record*> Instrs = Records.getAllDerivedDefinitions("Instruction"); + + for (unsigned i = 0, e = Instrs.size(); i != e; ++i) { + ListInit *LI = 0; + + if (dynamic_cast<ListInit*>(Instrs[i]->getValueInit("Pattern"))) + LI = Instrs[i]->getValueAsListInit("Pattern"); + + // If there is no pattern, only collect minimal information about the + // instruction for its operand list. We have to assume that there is one + // result, as we have no detailed info. + if (!LI || LI->getSize() == 0) { + std::vector<Record*> Results; + std::vector<Record*> Operands; + + CodeGenInstruction &InstInfo = Target.getInstruction(Instrs[i]); + + if (InstInfo.Operands.size() != 0) { + if (InstInfo.Operands.NumDefs == 0) { + // These produce no results + for (unsigned j = 0, e = InstInfo.Operands.size(); j < e; ++j) + Operands.push_back(InstInfo.Operands[j].Rec); + } else { + // Assume the first operand is the result. + Results.push_back(InstInfo.Operands[0].Rec); + + // The rest are inputs. + for (unsigned j = 1, e = InstInfo.Operands.size(); j < e; ++j) + Operands.push_back(InstInfo.Operands[j].Rec); + } + } + + // Create and insert the instruction. + std::vector<Record*> ImpResults; + Instructions.insert(std::make_pair(Instrs[i], + DAGInstruction(0, Results, Operands, ImpResults))); + continue; // no pattern. + } + + // Parse the instruction. + TreePattern *I = new TreePattern(Instrs[i], LI, true, *this); + // Inline pattern fragments into it. + I->InlinePatternFragments(); + + // Infer as many types as possible. If we cannot infer all of them, we can + // never do anything with this instruction pattern: report it to the user. + if (!I->InferAllTypes()) + I->error("Could not infer all types in pattern!"); + + // InstInputs - Keep track of all of the inputs of the instruction, along + // with the record they are declared as. + std::map<std::string, TreePatternNode*> InstInputs; + + // InstResults - Keep track of all the virtual registers that are 'set' + // in the instruction, including what reg class they are. + std::map<std::string, TreePatternNode*> InstResults; + + std::vector<Record*> InstImpResults; + + // Verify that the top-level forms in the instruction are of void type, and + // fill in the InstResults map. + for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) { + TreePatternNode *Pat = I->getTree(j); + if (Pat->getNumTypes() != 0) + I->error("Top-level forms in instruction pattern should have" + " void types"); + + // Find inputs and outputs, and verify the structure of the uses/defs. + FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults, + InstImpResults); + } + + // Now that we have inputs and outputs of the pattern, inspect the operands + // list for the instruction. This determines the order that operands are + // added to the machine instruction the node corresponds to. + unsigned NumResults = InstResults.size(); + + // Parse the operands list from the (ops) list, validating it. + assert(I->getArgList().empty() && "Args list should still be empty here!"); + CodeGenInstruction &CGI = Target.getInstruction(Instrs[i]); + + // Check that all of the results occur first in the list. + std::vector<Record*> Results; + TreePatternNode *Res0Node = 0; + for (unsigned i = 0; i != NumResults; ++i) { + if (i == CGI.Operands.size()) + I->error("'" + InstResults.begin()->first + + "' set but does not appear in operand list!"); + const std::string &OpName = CGI.Operands[i].Name; + + // Check that it exists in InstResults. + TreePatternNode *RNode = InstResults[OpName]; + if (RNode == 0) + I->error("Operand $" + OpName + " does not exist in operand list!"); + + if (i == 0) + Res0Node = RNode; + Record *R = dynamic_cast<DefInit*>(RNode->getLeafValue())->getDef(); + if (R == 0) + I->error("Operand $" + OpName + " should be a set destination: all " + "outputs must occur before inputs in operand list!"); + + if (CGI.Operands[i].Rec != R) + I->error("Operand $" + OpName + " class mismatch!"); + + // Remember the return type. + Results.push_back(CGI.Operands[i].Rec); + + // Okay, this one checks out. + InstResults.erase(OpName); + } + + // Loop over the inputs next. Make a copy of InstInputs so we can destroy + // the copy while we're checking the inputs. + std::map<std::string, TreePatternNode*> InstInputsCheck(InstInputs); + + std::vector<TreePatternNode*> ResultNodeOperands; + std::vector<Record*> Operands; + for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) { + CGIOperandList::OperandInfo &Op = CGI.Operands[i]; + const std::string &OpName = Op.Name; + if (OpName.empty()) + I->error("Operand #" + utostr(i) + " in operands list has no name!"); + + if (!InstInputsCheck.count(OpName)) { + // If this is an predicate operand or optional def operand with an + // DefaultOps set filled in, we can ignore this. When we codegen it, + // we will do so as always executed. + if (Op.Rec->isSubClassOf("PredicateOperand") || + Op.Rec->isSubClassOf("OptionalDefOperand")) { + // Does it have a non-empty DefaultOps field? If so, ignore this + // operand. + if (!getDefaultOperand(Op.Rec).DefaultOps.empty()) + continue; + } + I->error("Operand $" + OpName + + " does not appear in the instruction pattern"); + } + TreePatternNode *InVal = InstInputsCheck[OpName]; + InstInputsCheck.erase(OpName); // It occurred, remove from map. + + if (InVal->isLeaf() && + dynamic_cast<DefInit*>(InVal->getLeafValue())) { + Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef(); + if (Op.Rec != InRec && !InRec->isSubClassOf("ComplexPattern")) + I->error("Operand $" + OpName + "'s register class disagrees" + " between the operand and pattern"); + } + Operands.push_back(Op.Rec); + + // Construct the result for the dest-pattern operand list. + TreePatternNode *OpNode = InVal->clone(); + + // No predicate is useful on the result. + OpNode->clearPredicateFns(); + + // Promote the xform function to be an explicit node if set. + if (Record *Xform = OpNode->getTransformFn()) { + OpNode->setTransformFn(0); + std::vector<TreePatternNode*> Children; + Children.push_back(OpNode); + OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes()); + } + + ResultNodeOperands.push_back(OpNode); + } + + if (!InstInputsCheck.empty()) + I->error("Input operand $" + InstInputsCheck.begin()->first + + " occurs in pattern but not in operands list!"); + + TreePatternNode *ResultPattern = + new TreePatternNode(I->getRecord(), ResultNodeOperands, + GetNumNodeResults(I->getRecord(), *this)); + // Copy fully inferred output node type to instruction result pattern. + for (unsigned i = 0; i != NumResults; ++i) + ResultPattern->setType(i, Res0Node->getExtType(i)); + + // Create and insert the instruction. + // FIXME: InstImpResults should not be part of DAGInstruction. + DAGInstruction TheInst(I, Results, Operands, InstImpResults); + Instructions.insert(std::make_pair(I->getRecord(), TheInst)); + + // Use a temporary tree pattern to infer all types and make sure that the + // constructed result is correct. This depends on the instruction already + // being inserted into the Instructions map. + TreePattern Temp(I->getRecord(), ResultPattern, false, *this); + Temp.InferAllTypes(&I->getNamedNodesMap()); + + DAGInstruction &TheInsertedInst = Instructions.find(I->getRecord())->second; + TheInsertedInst.setResultPattern(Temp.getOnlyTree()); + + DEBUG(I->dump()); + } + + // If we can, convert the instructions to be patterns that are matched! + for (std::map<Record*, DAGInstruction, RecordPtrCmp>::iterator II = + Instructions.begin(), + E = Instructions.end(); II != E; ++II) { + DAGInstruction &TheInst = II->second; + const TreePattern *I = TheInst.getPattern(); + if (I == 0) continue; // No pattern. + + // FIXME: Assume only the first tree is the pattern. The others are clobber + // nodes. + TreePatternNode *Pattern = I->getTree(0); + TreePatternNode *SrcPattern; + if (Pattern->getOperator()->getName() == "set") { + SrcPattern = Pattern->getChild(Pattern->getNumChildren()-1)->clone(); + } else{ + // Not a set (store or something?) + SrcPattern = Pattern; + } + + Record *Instr = II->first; + AddPatternToMatch(I, + PatternToMatch(Instr, + Instr->getValueAsListInit("Predicates"), + SrcPattern, + TheInst.getResultPattern(), + TheInst.getImpResults(), + Instr->getValueAsInt("AddedComplexity"), + Instr->getID())); + } +} + + +typedef std::pair<const TreePatternNode*, unsigned> NameRecord; + +static void FindNames(const TreePatternNode *P, + std::map<std::string, NameRecord> &Names, + const TreePattern *PatternTop) { + if (!P->getName().empty()) { + NameRecord &Rec = Names[P->getName()]; + // If this is the first instance of the name, remember the node. + if (Rec.second++ == 0) + Rec.first = P; + else if (Rec.first->getExtTypes() != P->getExtTypes()) + PatternTop->error("repetition of value: $" + P->getName() + + " where different uses have different types!"); + } + + if (!P->isLeaf()) { + for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i) + FindNames(P->getChild(i), Names, PatternTop); + } +} + +void CodeGenDAGPatterns::AddPatternToMatch(const TreePattern *Pattern, + const PatternToMatch &PTM) { + // Do some sanity checking on the pattern we're about to match. + std::string Reason; + if (!PTM.getSrcPattern()->canPatternMatch(Reason, *this)) + Pattern->error("Pattern can never match: " + Reason); + + // If the source pattern's root is a complex pattern, that complex pattern + // must specify the nodes it can potentially match. + if (const ComplexPattern *CP = + PTM.getSrcPattern()->getComplexPatternInfo(*this)) + if (CP->getRootNodes().empty()) + Pattern->error("ComplexPattern at root must specify list of opcodes it" + " could match"); + + + // Find all of the named values in the input and output, ensure they have the + // same type. + std::map<std::string, NameRecord> SrcNames, DstNames; + FindNames(PTM.getSrcPattern(), SrcNames, Pattern); + FindNames(PTM.getDstPattern(), DstNames, Pattern); + + // Scan all of the named values in the destination pattern, rejecting them if + // they don't exist in the input pattern. + for (std::map<std::string, NameRecord>::iterator + I = DstNames.begin(), E = DstNames.end(); I != E; ++I) { + if (SrcNames[I->first].first == 0) + Pattern->error("Pattern has input without matching name in output: $" + + I->first); + } + + // Scan all of the named values in the source pattern, rejecting them if the + // name isn't used in the dest, and isn't used to tie two values together. + for (std::map<std::string, NameRecord>::iterator + I = SrcNames.begin(), E = SrcNames.end(); I != E; ++I) + if (DstNames[I->first].first == 0 && SrcNames[I->first].second == 1) + Pattern->error("Pattern has dead named input: $" + I->first); + + PatternsToMatch.push_back(PTM); +} + + + +void CodeGenDAGPatterns::InferInstructionFlags() { + const std::vector<const CodeGenInstruction*> &Instructions = + Target.getInstructionsByEnumValue(); + for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { + CodeGenInstruction &InstInfo = + const_cast<CodeGenInstruction &>(*Instructions[i]); + // Determine properties of the instruction from its pattern. + bool MayStore, MayLoad, IsBitcast, HasSideEffects, IsVariadic; + InferFromPattern(InstInfo, MayStore, MayLoad, IsBitcast, + HasSideEffects, IsVariadic, *this); + InstInfo.mayStore = MayStore; + InstInfo.mayLoad = MayLoad; + InstInfo.isBitcast = IsBitcast; + InstInfo.hasSideEffects = HasSideEffects; + InstInfo.Operands.isVariadic = IsVariadic; + + // Sanity checks. + if (InstInfo.isReMaterializable && InstInfo.hasSideEffects) + throw TGError(InstInfo.TheDef->getLoc(), "The instruction " + + InstInfo.TheDef->getName() + + " is rematerializable AND has unmodeled side effects?"); + } +} + +/// Given a pattern result with an unresolved type, see if we can find one +/// instruction with an unresolved result type. Force this result type to an +/// arbitrary element if it's possible types to converge results. +static bool ForceArbitraryInstResultType(TreePatternNode *N, TreePattern &TP) { + if (N->isLeaf()) + return false; + + // Analyze children. + for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) + if (ForceArbitraryInstResultType(N->getChild(i), TP)) + return true; + + if (!N->getOperator()->isSubClassOf("Instruction")) + return false; + + // If this type is already concrete or completely unknown we can't do + // anything. + for (unsigned i = 0, e = N->getNumTypes(); i != e; ++i) { + if (N->getExtType(i).isCompletelyUnknown() || N->getExtType(i).isConcrete()) + continue; + + // Otherwise, force its type to the first possibility (an arbitrary choice). + if (N->getExtType(i).MergeInTypeInfo(N->getExtType(i).getTypeList()[0], TP)) + return true; + } + + return false; +} + +void CodeGenDAGPatterns::ParsePatterns() { + std::vector<Record*> Patterns = Records.getAllDerivedDefinitions("Pattern"); + + for (unsigned i = 0, e = Patterns.size(); i != e; ++i) { + Record *CurPattern = Patterns[i]; + DagInit *Tree = CurPattern->getValueAsDag("PatternToMatch"); + TreePattern *Pattern = new TreePattern(CurPattern, Tree, true, *this); + + // Inline pattern fragments into it. + Pattern->InlinePatternFragments(); + + ListInit *LI = CurPattern->getValueAsListInit("ResultInstrs"); + if (LI->getSize() == 0) continue; // no pattern. + + // Parse the instruction. + TreePattern *Result = new TreePattern(CurPattern, LI, false, *this); + + // Inline pattern fragments into it. + Result->InlinePatternFragments(); + + if (Result->getNumTrees() != 1) + Result->error("Cannot handle instructions producing instructions " + "with temporaries yet!"); + + bool IterateInference; + bool InferredAllPatternTypes, InferredAllResultTypes; + do { + // Infer as many types as possible. If we cannot infer all of them, we + // can never do anything with this pattern: report it to the user. + InferredAllPatternTypes = + Pattern->InferAllTypes(&Pattern->getNamedNodesMap()); + + // Infer as many types as possible. If we cannot infer all of them, we + // can never do anything with this pattern: report it to the user. + InferredAllResultTypes = + Result->InferAllTypes(&Pattern->getNamedNodesMap()); + + IterateInference = false; + + // Apply the type of the result to the source pattern. This helps us + // resolve cases where the input type is known to be a pointer type (which + // is considered resolved), but the result knows it needs to be 32- or + // 64-bits. Infer the other way for good measure. + for (unsigned i = 0, e = std::min(Result->getTree(0)->getNumTypes(), + Pattern->getTree(0)->getNumTypes()); + i != e; ++i) { + IterateInference = Pattern->getTree(0)-> + UpdateNodeType(i, Result->getTree(0)->getExtType(i), *Result); + IterateInference |= Result->getTree(0)-> + UpdateNodeType(i, Pattern->getTree(0)->getExtType(i), *Result); + } + + // If our iteration has converged and the input pattern's types are fully + // resolved but the result pattern is not fully resolved, we may have a + // situation where we have two instructions in the result pattern and + // the instructions require a common register class, but don't care about + // what actual MVT is used. This is actually a bug in our modelling: + // output patterns should have register classes, not MVTs. + // + // In any case, to handle this, we just go through and disambiguate some + // arbitrary types to the result pattern's nodes. + if (!IterateInference && InferredAllPatternTypes && + !InferredAllResultTypes) + IterateInference = ForceArbitraryInstResultType(Result->getTree(0), + *Result); + } while (IterateInference); + + // Verify that we inferred enough types that we can do something with the + // pattern and result. If these fire the user has to add type casts. + if (!InferredAllPatternTypes) + Pattern->error("Could not infer all types in pattern!"); + if (!InferredAllResultTypes) { + Pattern->dump(); + Result->error("Could not infer all types in pattern result!"); + } + + // Validate that the input pattern is correct. + std::map<std::string, TreePatternNode*> InstInputs; + std::map<std::string, TreePatternNode*> InstResults; + std::vector<Record*> InstImpResults; + for (unsigned j = 0, ee = Pattern->getNumTrees(); j != ee; ++j) + FindPatternInputsAndOutputs(Pattern, Pattern->getTree(j), + InstInputs, InstResults, + InstImpResults); + + // Promote the xform function to be an explicit node if set. + TreePatternNode *DstPattern = Result->getOnlyTree(); + std::vector<TreePatternNode*> ResultNodeOperands; + for (unsigned ii = 0, ee = DstPattern->getNumChildren(); ii != ee; ++ii) { + TreePatternNode *OpNode = DstPattern->getChild(ii); + if (Record *Xform = OpNode->getTransformFn()) { + OpNode->setTransformFn(0); + std::vector<TreePatternNode*> Children; + Children.push_back(OpNode); + OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes()); + } + ResultNodeOperands.push_back(OpNode); + } + DstPattern = Result->getOnlyTree(); + if (!DstPattern->isLeaf()) + DstPattern = new TreePatternNode(DstPattern->getOperator(), + ResultNodeOperands, + DstPattern->getNumTypes()); + + for (unsigned i = 0, e = Result->getOnlyTree()->getNumTypes(); i != e; ++i) + DstPattern->setType(i, Result->getOnlyTree()->getExtType(i)); + + TreePattern Temp(Result->getRecord(), DstPattern, false, *this); + Temp.InferAllTypes(); + + + AddPatternToMatch(Pattern, + PatternToMatch(CurPattern, + CurPattern->getValueAsListInit("Predicates"), + Pattern->getTree(0), + Temp.getOnlyTree(), InstImpResults, + CurPattern->getValueAsInt("AddedComplexity"), + CurPattern->getID())); + } +} + +/// CombineChildVariants - Given a bunch of permutations of each child of the +/// 'operator' node, put them together in all possible ways. +static void CombineChildVariants(TreePatternNode *Orig, + const std::vector<std::vector<TreePatternNode*> > &ChildVariants, + std::vector<TreePatternNode*> &OutVariants, + CodeGenDAGPatterns &CDP, + const MultipleUseVarSet &DepVars) { + // Make sure that each operand has at least one variant to choose from. + for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i) + if (ChildVariants[i].empty()) + return; + + // The end result is an all-pairs construction of the resultant pattern. + std::vector<unsigned> Idxs; + Idxs.resize(ChildVariants.size()); + bool NotDone; + do { +#ifndef NDEBUG + DEBUG(if (!Idxs.empty()) { + errs() << Orig->getOperator()->getName() << ": Idxs = [ "; + for (unsigned i = 0; i < Idxs.size(); ++i) { + errs() << Idxs[i] << " "; + } + errs() << "]\n"; + }); +#endif + // Create the variant and add it to the output list. + std::vector<TreePatternNode*> NewChildren; + for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i) + NewChildren.push_back(ChildVariants[i][Idxs[i]]); + TreePatternNode *R = new TreePatternNode(Orig->getOperator(), NewChildren, + Orig->getNumTypes()); + + // Copy over properties. + R->setName(Orig->getName()); + R->setPredicateFns(Orig->getPredicateFns()); + R->setTransformFn(Orig->getTransformFn()); + for (unsigned i = 0, e = Orig->getNumTypes(); i != e; ++i) + R->setType(i, Orig->getExtType(i)); + + // If this pattern cannot match, do not include it as a variant. + std::string ErrString; + if (!R->canPatternMatch(ErrString, CDP)) { + delete R; + } else { + bool AlreadyExists = false; + + // Scan to see if this pattern has already been emitted. We can get + // duplication due to things like commuting: + // (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a) + // which are the same pattern. Ignore the dups. + for (unsigned i = 0, e = OutVariants.size(); i != e; ++i) + if (R->isIsomorphicTo(OutVariants[i], DepVars)) { + AlreadyExists = true; + break; + } + + if (AlreadyExists) + delete R; + else + OutVariants.push_back(R); + } + + // Increment indices to the next permutation by incrementing the + // indicies from last index backward, e.g., generate the sequence + // [0, 0], [0, 1], [1, 0], [1, 1]. + int IdxsIdx; + for (IdxsIdx = Idxs.size() - 1; IdxsIdx >= 0; --IdxsIdx) { + if (++Idxs[IdxsIdx] == ChildVariants[IdxsIdx].size()) + Idxs[IdxsIdx] = 0; + else + break; + } + NotDone = (IdxsIdx >= 0); + } while (NotDone); +} + +/// CombineChildVariants - A helper function for binary operators. +/// +static void CombineChildVariants(TreePatternNode *Orig, + const std::vector<TreePatternNode*> &LHS, + const std::vector<TreePatternNode*> &RHS, + std::vector<TreePatternNode*> &OutVariants, + CodeGenDAGPatterns &CDP, + const MultipleUseVarSet &DepVars) { + std::vector<std::vector<TreePatternNode*> > ChildVariants; + ChildVariants.push_back(LHS); + ChildVariants.push_back(RHS); + CombineChildVariants(Orig, ChildVariants, OutVariants, CDP, DepVars); +} + + +static void GatherChildrenOfAssociativeOpcode(TreePatternNode *N, + std::vector<TreePatternNode *> &Children) { + assert(N->getNumChildren()==2 &&"Associative but doesn't have 2 children!"); + Record *Operator = N->getOperator(); + + // Only permit raw nodes. + if (!N->getName().empty() || !N->getPredicateFns().empty() || + N->getTransformFn()) { + Children.push_back(N); + return; + } + + if (N->getChild(0)->isLeaf() || N->getChild(0)->getOperator() != Operator) + Children.push_back(N->getChild(0)); + else + GatherChildrenOfAssociativeOpcode(N->getChild(0), Children); + + if (N->getChild(1)->isLeaf() || N->getChild(1)->getOperator() != Operator) + Children.push_back(N->getChild(1)); + else + GatherChildrenOfAssociativeOpcode(N->getChild(1), Children); +} + +/// GenerateVariantsOf - Given a pattern N, generate all permutations we can of +/// the (potentially recursive) pattern by using algebraic laws. +/// +static void GenerateVariantsOf(TreePatternNode *N, + std::vector<TreePatternNode*> &OutVariants, + CodeGenDAGPatterns &CDP, + const MultipleUseVarSet &DepVars) { + // We cannot permute leaves. + if (N->isLeaf()) { + OutVariants.push_back(N); + return; + } + + // Look up interesting info about the node. + const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(N->getOperator()); + + // If this node is associative, re-associate. + if (NodeInfo.hasProperty(SDNPAssociative)) { + // Re-associate by pulling together all of the linked operators + std::vector<TreePatternNode*> MaximalChildren; + GatherChildrenOfAssociativeOpcode(N, MaximalChildren); + + // Only handle child sizes of 3. Otherwise we'll end up trying too many + // permutations. + if (MaximalChildren.size() == 3) { + // Find the variants of all of our maximal children. + std::vector<TreePatternNode*> AVariants, BVariants, CVariants; + GenerateVariantsOf(MaximalChildren[0], AVariants, CDP, DepVars); + GenerateVariantsOf(MaximalChildren[1], BVariants, CDP, DepVars); + GenerateVariantsOf(MaximalChildren[2], CVariants, CDP, DepVars); + + // There are only two ways we can permute the tree: + // (A op B) op C and A op (B op C) + // Within these forms, we can also permute A/B/C. + + // Generate legal pair permutations of A/B/C. + std::vector<TreePatternNode*> ABVariants; + std::vector<TreePatternNode*> BAVariants; + std::vector<TreePatternNode*> ACVariants; + std::vector<TreePatternNode*> CAVariants; + std::vector<TreePatternNode*> BCVariants; + std::vector<TreePatternNode*> CBVariants; + CombineChildVariants(N, AVariants, BVariants, ABVariants, CDP, DepVars); + CombineChildVariants(N, BVariants, AVariants, BAVariants, CDP, DepVars); + CombineChildVariants(N, AVariants, CVariants, ACVariants, CDP, DepVars); + CombineChildVariants(N, CVariants, AVariants, CAVariants, CDP, DepVars); + CombineChildVariants(N, BVariants, CVariants, BCVariants, CDP, DepVars); + CombineChildVariants(N, CVariants, BVariants, CBVariants, CDP, DepVars); + + // Combine those into the result: (x op x) op x + CombineChildVariants(N, ABVariants, CVariants, OutVariants, CDP, DepVars); + CombineChildVariants(N, BAVariants, CVariants, OutVariants, CDP, DepVars); + CombineChildVariants(N, ACVariants, BVariants, OutVariants, CDP, DepVars); + CombineChildVariants(N, CAVariants, BVariants, OutVariants, CDP, DepVars); + CombineChildVariants(N, BCVariants, AVariants, OutVariants, CDP, DepVars); + CombineChildVariants(N, CBVariants, AVariants, OutVariants, CDP, DepVars); + + // Combine those into the result: x op (x op x) + CombineChildVariants(N, CVariants, ABVariants, OutVariants, CDP, DepVars); + CombineChildVariants(N, CVariants, BAVariants, OutVariants, CDP, DepVars); + CombineChildVariants(N, BVariants, ACVariants, OutVariants, CDP, DepVars); + CombineChildVariants(N, BVariants, CAVariants, OutVariants, CDP, DepVars); + CombineChildVariants(N, AVariants, BCVariants, OutVariants, CDP, DepVars); + CombineChildVariants(N, AVariants, CBVariants, OutVariants, CDP, DepVars); + return; + } + } + + // Compute permutations of all children. + std::vector<std::vector<TreePatternNode*> > ChildVariants; + ChildVariants.resize(N->getNumChildren()); + for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) + GenerateVariantsOf(N->getChild(i), ChildVariants[i], CDP, DepVars); + + // Build all permutations based on how the children were formed. + CombineChildVariants(N, ChildVariants, OutVariants, CDP, DepVars); + + // If this node is commutative, consider the commuted order. + bool isCommIntrinsic = N->isCommutativeIntrinsic(CDP); + if (NodeInfo.hasProperty(SDNPCommutative) || isCommIntrinsic) { + assert((N->getNumChildren()==2 || isCommIntrinsic) && + "Commutative but doesn't have 2 children!"); + // Don't count children which are actually register references. + unsigned NC = 0; + for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) { + TreePatternNode *Child = N->getChild(i); + if (Child->isLeaf()) + if (DefInit *DI = dynamic_cast<DefInit*>(Child->getLeafValue())) { + Record *RR = DI->getDef(); + if (RR->isSubClassOf("Register")) + continue; + } + NC++; + } + // Consider the commuted order. + if (isCommIntrinsic) { + // Commutative intrinsic. First operand is the intrinsic id, 2nd and 3rd + // operands are the commutative operands, and there might be more operands + // after those. + assert(NC >= 3 && + "Commutative intrinsic should have at least 3 childrean!"); + std::vector<std::vector<TreePatternNode*> > Variants; + Variants.push_back(ChildVariants[0]); // Intrinsic id. + Variants.push_back(ChildVariants[2]); + Variants.push_back(ChildVariants[1]); + for (unsigned i = 3; i != NC; ++i) + Variants.push_back(ChildVariants[i]); + CombineChildVariants(N, Variants, OutVariants, CDP, DepVars); + } else if (NC == 2) + CombineChildVariants(N, ChildVariants[1], ChildVariants[0], + OutVariants, CDP, DepVars); + } +} + + +// GenerateVariants - Generate variants. For example, commutative patterns can +// match multiple ways. Add them to PatternsToMatch as well. +void CodeGenDAGPatterns::GenerateVariants() { + DEBUG(errs() << "Generating instruction variants.\n"); + + // Loop over all of the patterns we've collected, checking to see if we can + // generate variants of the instruction, through the exploitation of + // identities. This permits the target to provide aggressive matching without + // the .td file having to contain tons of variants of instructions. + // + // Note that this loop adds new patterns to the PatternsToMatch list, but we + // intentionally do not reconsider these. Any variants of added patterns have + // already been added. + // + for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) { + MultipleUseVarSet DepVars; + std::vector<TreePatternNode*> Variants; + FindDepVars(PatternsToMatch[i].getSrcPattern(), DepVars); + DEBUG(errs() << "Dependent/multiply used variables: "); + DEBUG(DumpDepVars(DepVars)); + DEBUG(errs() << "\n"); + GenerateVariantsOf(PatternsToMatch[i].getSrcPattern(), Variants, *this, + DepVars); + + assert(!Variants.empty() && "Must create at least original variant!"); + Variants.erase(Variants.begin()); // Remove the original pattern. + + if (Variants.empty()) // No variants for this pattern. + continue; + + DEBUG(errs() << "FOUND VARIANTS OF: "; + PatternsToMatch[i].getSrcPattern()->dump(); + errs() << "\n"); + + for (unsigned v = 0, e = Variants.size(); v != e; ++v) { + TreePatternNode *Variant = Variants[v]; + + DEBUG(errs() << " VAR#" << v << ": "; + Variant->dump(); + errs() << "\n"); + + // Scan to see if an instruction or explicit pattern already matches this. + bool AlreadyExists = false; + for (unsigned p = 0, e = PatternsToMatch.size(); p != e; ++p) { + // Skip if the top level predicates do not match. + if (PatternsToMatch[i].getPredicates() != + PatternsToMatch[p].getPredicates()) + continue; + // Check to see if this variant already exists. + if (Variant->isIsomorphicTo(PatternsToMatch[p].getSrcPattern(), + DepVars)) { + DEBUG(errs() << " *** ALREADY EXISTS, ignoring variant.\n"); + AlreadyExists = true; + break; + } + } + // If we already have it, ignore the variant. + if (AlreadyExists) continue; + + // Otherwise, add it to the list of patterns we have. + PatternsToMatch. + push_back(PatternToMatch(PatternsToMatch[i].getSrcRecord(), + PatternsToMatch[i].getPredicates(), + Variant, PatternsToMatch[i].getDstPattern(), + PatternsToMatch[i].getDstRegs(), + PatternsToMatch[i].getAddedComplexity(), + Record::getNewUID())); + } + + DEBUG(errs() << "\n"); + } +} + diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h new file mode 100644 index 0000000..5a2d40a --- /dev/null +++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h @@ -0,0 +1,811 @@ +//===- CodeGenDAGPatterns.h - Read DAG patterns from .td file ---*- 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 CodeGenDAGPatterns class, which is used to read and +// represent the patterns present in a .td file for instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_DAGPATTERNS_H +#define CODEGEN_DAGPATTERNS_H + +#include "CodeGenTarget.h" +#include "CodeGenIntrinsics.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/ErrorHandling.h" +#include <set> +#include <algorithm> +#include <vector> +#include <map> + +namespace llvm { + class Record; + class Init; + class ListInit; + class DagInit; + class SDNodeInfo; + class TreePattern; + class TreePatternNode; + class CodeGenDAGPatterns; + class ComplexPattern; + +/// EEVT::DAGISelGenValueType - These are some extended forms of +/// MVT::SimpleValueType that we use as lattice values during type inference. +/// The existing MVT iAny, fAny and vAny types suffice to represent +/// arbitrary integer, floating-point, and vector types, so only an unknown +/// value is needed. +namespace EEVT { + /// TypeSet - This is either empty if it's completely unknown, or holds a set + /// of types. It is used during type inference because register classes can + /// have multiple possible types and we don't know which one they get until + /// type inference is complete. + /// + /// TypeSet can have three states: + /// Vector is empty: The type is completely unknown, it can be any valid + /// target type. + /// Vector has multiple constrained types: (e.g. v4i32 + v4f32) it is one + /// of those types only. + /// Vector has one concrete type: The type is completely known. + /// + class TypeSet { + SmallVector<MVT::SimpleValueType, 4> TypeVec; + public: + TypeSet() {} + TypeSet(MVT::SimpleValueType VT, TreePattern &TP); + TypeSet(const std::vector<MVT::SimpleValueType> &VTList); + + bool isCompletelyUnknown() const { return TypeVec.empty(); } + + bool isConcrete() const { + if (TypeVec.size() != 1) return false; + unsigned char T = TypeVec[0]; (void)T; + assert(T < MVT::LAST_VALUETYPE || T == MVT::iPTR || T == MVT::iPTRAny); + return true; + } + + MVT::SimpleValueType getConcrete() const { + assert(isConcrete() && "Type isn't concrete yet"); + return (MVT::SimpleValueType)TypeVec[0]; + } + + bool isDynamicallyResolved() const { + return getConcrete() == MVT::iPTR || getConcrete() == MVT::iPTRAny; + } + + const SmallVectorImpl<MVT::SimpleValueType> &getTypeList() const { + assert(!TypeVec.empty() && "Not a type list!"); + return TypeVec; + } + + bool isVoid() const { + return TypeVec.size() == 1 && TypeVec[0] == MVT::isVoid; + } + + /// hasIntegerTypes - Return true if this TypeSet contains any integer value + /// types. + bool hasIntegerTypes() const; + + /// hasFloatingPointTypes - Return true if this TypeSet contains an fAny or + /// a floating point value type. + bool hasFloatingPointTypes() const; + + /// hasVectorTypes - Return true if this TypeSet contains a vector value + /// type. + bool hasVectorTypes() const; + + /// getName() - Return this TypeSet as a string. + std::string getName() const; + + /// MergeInTypeInfo - This merges in type information from the specified + /// argument. If 'this' changes, it returns true. If the two types are + /// contradictory (e.g. merge f32 into i32) then this throws an exception. + bool MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP); + + bool MergeInTypeInfo(MVT::SimpleValueType InVT, TreePattern &TP) { + return MergeInTypeInfo(EEVT::TypeSet(InVT, TP), TP); + } + + /// Force this type list to only contain integer types. + bool EnforceInteger(TreePattern &TP); + + /// Force this type list to only contain floating point types. + bool EnforceFloatingPoint(TreePattern &TP); + + /// EnforceScalar - Remove all vector types from this type list. + bool EnforceScalar(TreePattern &TP); + + /// EnforceVector - Remove all non-vector types from this type list. + bool EnforceVector(TreePattern &TP); + + /// EnforceSmallerThan - 'this' must be a smaller VT than Other. Update + /// this an other based on this information. + bool EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP); + + /// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type + /// whose element is VT. + bool EnforceVectorEltTypeIs(EEVT::TypeSet &VT, TreePattern &TP); + + /// EnforceVectorSubVectorTypeIs - 'this' is now constrainted to + /// be a vector type VT. + bool EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VT, TreePattern &TP); + + bool operator!=(const TypeSet &RHS) const { return TypeVec != RHS.TypeVec; } + bool operator==(const TypeSet &RHS) const { return TypeVec == RHS.TypeVec; } + + private: + /// FillWithPossibleTypes - Set to all legal types and return true, only + /// valid on completely unknown type sets. If Pred is non-null, only MVTs + /// that pass the predicate are added. + bool FillWithPossibleTypes(TreePattern &TP, + bool (*Pred)(MVT::SimpleValueType) = 0, + const char *PredicateName = 0); + }; +} + +/// Set type used to track multiply used variables in patterns +typedef std::set<std::string> MultipleUseVarSet; + +/// SDTypeConstraint - This is a discriminated union of constraints, +/// corresponding to the SDTypeConstraint tablegen class in Target.td. +struct SDTypeConstraint { + SDTypeConstraint(Record *R); + + unsigned OperandNo; // The operand # this constraint applies to. + enum { + SDTCisVT, SDTCisPtrTy, SDTCisInt, SDTCisFP, SDTCisVec, SDTCisSameAs, + SDTCisVTSmallerThanOp, SDTCisOpSmallerThanOp, SDTCisEltOfVec, + SDTCisSubVecOfVec + } ConstraintType; + + union { // The discriminated union. + struct { + MVT::SimpleValueType VT; + } SDTCisVT_Info; + struct { + unsigned OtherOperandNum; + } SDTCisSameAs_Info; + struct { + unsigned OtherOperandNum; + } SDTCisVTSmallerThanOp_Info; + struct { + unsigned BigOperandNum; + } SDTCisOpSmallerThanOp_Info; + struct { + unsigned OtherOperandNum; + } SDTCisEltOfVec_Info; + struct { + unsigned OtherOperandNum; + } SDTCisSubVecOfVec_Info; + } x; + + /// ApplyTypeConstraint - Given a node in a pattern, apply this type + /// constraint to the nodes operands. This returns true if it makes a + /// change, false otherwise. If a type contradiction is found, throw an + /// exception. + bool ApplyTypeConstraint(TreePatternNode *N, const SDNodeInfo &NodeInfo, + TreePattern &TP) const; +}; + +/// SDNodeInfo - One of these records is created for each SDNode instance in +/// the target .td file. This represents the various dag nodes we will be +/// processing. +class SDNodeInfo { + Record *Def; + std::string EnumName; + std::string SDClassName; + unsigned Properties; + unsigned NumResults; + int NumOperands; + std::vector<SDTypeConstraint> TypeConstraints; +public: + SDNodeInfo(Record *R); // Parse the specified record. + + unsigned getNumResults() const { return NumResults; } + + /// getNumOperands - This is the number of operands required or -1 if + /// variadic. + int getNumOperands() const { return NumOperands; } + Record *getRecord() const { return Def; } + const std::string &getEnumName() const { return EnumName; } + const std::string &getSDClassName() const { return SDClassName; } + + const std::vector<SDTypeConstraint> &getTypeConstraints() const { + return TypeConstraints; + } + + /// getKnownType - If the type constraints on this node imply a fixed type + /// (e.g. all stores return void, etc), then return it as an + /// MVT::SimpleValueType. Otherwise, return MVT::Other. + MVT::SimpleValueType getKnownType(unsigned ResNo) const; + + /// hasProperty - Return true if this node has the specified property. + /// + bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); } + + /// ApplyTypeConstraints - Given a node in a pattern, apply the type + /// constraints for this node to the operands of the node. This returns + /// true if it makes a change, false otherwise. If a type contradiction is + /// found, throw an exception. + bool ApplyTypeConstraints(TreePatternNode *N, TreePattern &TP) const { + bool MadeChange = false; + for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i) + MadeChange |= TypeConstraints[i].ApplyTypeConstraint(N, *this, TP); + return MadeChange; + } +}; + +/// TreePredicateFn - This is an abstraction that represents the predicates on +/// a PatFrag node. This is a simple one-word wrapper around a pointer to +/// provide nice accessors. +class TreePredicateFn { + /// PatFragRec - This is the TreePattern for the PatFrag that we + /// originally came from. + TreePattern *PatFragRec; +public: + /// TreePredicateFn constructor. Here 'N' is a subclass of PatFrag. + TreePredicateFn(TreePattern *N); + + + TreePattern *getOrigPatFragRecord() const { return PatFragRec; } + + /// isAlwaysTrue - Return true if this is a noop predicate. + bool isAlwaysTrue() const; + + bool isImmediatePattern() const { return !getImmCode().empty(); } + + /// getImmediatePredicateCode - Return the code that evaluates this pattern if + /// this is an immediate predicate. It is an error to call this on a + /// non-immediate pattern. + std::string getImmediatePredicateCode() const { + std::string Result = getImmCode(); + assert(!Result.empty() && "Isn't an immediate pattern!"); + return Result; + } + + + bool operator==(const TreePredicateFn &RHS) const { + return PatFragRec == RHS.PatFragRec; + } + + bool operator!=(const TreePredicateFn &RHS) const { return !(*this == RHS); } + + /// Return the name to use in the generated code to reference this, this is + /// "Predicate_foo" if from a pattern fragment "foo". + std::string getFnName() const; + + /// getCodeToRunOnSDNode - Return the code for the function body that + /// evaluates this predicate. The argument is expected to be in "Node", + /// not N. This handles casting and conversion to a concrete node type as + /// appropriate. + std::string getCodeToRunOnSDNode() const; + +private: + std::string getPredCode() const; + std::string getImmCode() const; +}; + + +/// FIXME: TreePatternNode's can be shared in some cases (due to dag-shaped +/// patterns), and as such should be ref counted. We currently just leak all +/// TreePatternNode objects! +class TreePatternNode { + /// The type of each node result. Before and during type inference, each + /// result may be a set of possible types. After (successful) type inference, + /// each is a single concrete type. + SmallVector<EEVT::TypeSet, 1> Types; + + /// Operator - The Record for the operator if this is an interior node (not + /// a leaf). + Record *Operator; + + /// Val - The init value (e.g. the "GPRC" record, or "7") for a leaf. + /// + Init *Val; + + /// Name - The name given to this node with the :$foo notation. + /// + std::string Name; + + /// PredicateFns - The predicate functions to execute on this node to check + /// for a match. If this list is empty, no predicate is involved. + std::vector<TreePredicateFn> PredicateFns; + + /// TransformFn - The transformation function to execute on this node before + /// it can be substituted into the resulting instruction on a pattern match. + Record *TransformFn; + + std::vector<TreePatternNode*> Children; +public: + TreePatternNode(Record *Op, const std::vector<TreePatternNode*> &Ch, + unsigned NumResults) + : Operator(Op), Val(0), TransformFn(0), Children(Ch) { + Types.resize(NumResults); + } + TreePatternNode(Init *val, unsigned NumResults) // leaf ctor + : Operator(0), Val(val), TransformFn(0) { + Types.resize(NumResults); + } + ~TreePatternNode(); + + const std::string &getName() const { return Name; } + void setName(StringRef N) { Name.assign(N.begin(), N.end()); } + + bool isLeaf() const { return Val != 0; } + + // Type accessors. + unsigned getNumTypes() const { return Types.size(); } + MVT::SimpleValueType getType(unsigned ResNo) const { + return Types[ResNo].getConcrete(); + } + const SmallVectorImpl<EEVT::TypeSet> &getExtTypes() const { return Types; } + const EEVT::TypeSet &getExtType(unsigned ResNo) const { return Types[ResNo]; } + EEVT::TypeSet &getExtType(unsigned ResNo) { return Types[ResNo]; } + void setType(unsigned ResNo, const EEVT::TypeSet &T) { Types[ResNo] = T; } + + bool hasTypeSet(unsigned ResNo) const { + return Types[ResNo].isConcrete(); + } + bool isTypeCompletelyUnknown(unsigned ResNo) const { + return Types[ResNo].isCompletelyUnknown(); + } + bool isTypeDynamicallyResolved(unsigned ResNo) const { + return Types[ResNo].isDynamicallyResolved(); + } + + Init *getLeafValue() const { assert(isLeaf()); return Val; } + Record *getOperator() const { assert(!isLeaf()); return Operator; } + + unsigned getNumChildren() const { return Children.size(); } + TreePatternNode *getChild(unsigned N) const { return Children[N]; } + void setChild(unsigned i, TreePatternNode *N) { + Children[i] = N; + } + + /// hasChild - Return true if N is any of our children. + bool hasChild(const TreePatternNode *N) const { + for (unsigned i = 0, e = Children.size(); i != e; ++i) + if (Children[i] == N) return true; + return false; + } + + bool hasAnyPredicate() const { return !PredicateFns.empty(); } + + const std::vector<TreePredicateFn> &getPredicateFns() const { + return PredicateFns; + } + void clearPredicateFns() { PredicateFns.clear(); } + void setPredicateFns(const std::vector<TreePredicateFn> &Fns) { + assert(PredicateFns.empty() && "Overwriting non-empty predicate list!"); + PredicateFns = Fns; + } + void addPredicateFn(const TreePredicateFn &Fn) { + assert(!Fn.isAlwaysTrue() && "Empty predicate string!"); + if (std::find(PredicateFns.begin(), PredicateFns.end(), Fn) == + PredicateFns.end()) + PredicateFns.push_back(Fn); + } + + Record *getTransformFn() const { return TransformFn; } + void setTransformFn(Record *Fn) { TransformFn = Fn; } + + /// getIntrinsicInfo - If this node corresponds to an intrinsic, return the + /// CodeGenIntrinsic information for it, otherwise return a null pointer. + const CodeGenIntrinsic *getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const; + + /// getComplexPatternInfo - If this node corresponds to a ComplexPattern, + /// return the ComplexPattern information, otherwise return null. + const ComplexPattern * + getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const; + + /// NodeHasProperty - Return true if this node has the specified property. + bool NodeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const; + + /// TreeHasProperty - Return true if any node in this tree has the specified + /// property. + bool TreeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const; + + /// isCommutativeIntrinsic - Return true if the node is an intrinsic which is + /// marked isCommutative. + bool isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const; + + void print(raw_ostream &OS) const; + void dump() const; + +public: // Higher level manipulation routines. + + /// clone - Return a new copy of this tree. + /// + TreePatternNode *clone() const; + + /// RemoveAllTypes - Recursively strip all the types of this tree. + void RemoveAllTypes(); + + /// isIsomorphicTo - Return true if this node is recursively isomorphic to + /// the specified node. For this comparison, all of the state of the node + /// is considered, except for the assigned name. Nodes with differing names + /// that are otherwise identical are considered isomorphic. + bool isIsomorphicTo(const TreePatternNode *N, + const MultipleUseVarSet &DepVars) const; + + /// SubstituteFormalArguments - Replace the formal arguments in this tree + /// with actual values specified by ArgMap. + void SubstituteFormalArguments(std::map<std::string, + TreePatternNode*> &ArgMap); + + /// InlinePatternFragments - If this pattern refers to any pattern + /// fragments, inline them into place, giving us a pattern without any + /// PatFrag references. + TreePatternNode *InlinePatternFragments(TreePattern &TP); + + /// ApplyTypeConstraints - Apply all of the type constraints relevant to + /// this node and its children in the tree. This returns true if it makes a + /// change, false otherwise. If a type contradiction is found, throw an + /// exception. + bool ApplyTypeConstraints(TreePattern &TP, bool NotRegisters); + + /// UpdateNodeType - Set the node type of N to VT if VT contains + /// information. If N already contains a conflicting type, then throw an + /// exception. This returns true if any information was updated. + /// + bool UpdateNodeType(unsigned ResNo, const EEVT::TypeSet &InTy, + TreePattern &TP) { + return Types[ResNo].MergeInTypeInfo(InTy, TP); + } + + bool UpdateNodeType(unsigned ResNo, MVT::SimpleValueType InTy, + TreePattern &TP) { + return Types[ResNo].MergeInTypeInfo(EEVT::TypeSet(InTy, TP), TP); + } + + /// ContainsUnresolvedType - Return true if this tree contains any + /// unresolved types. + bool ContainsUnresolvedType() const { + for (unsigned i = 0, e = Types.size(); i != e; ++i) + if (!Types[i].isConcrete()) return true; + + for (unsigned i = 0, e = getNumChildren(); i != e; ++i) + if (getChild(i)->ContainsUnresolvedType()) return true; + return false; + } + + /// canPatternMatch - If it is impossible for this pattern to match on this + /// target, fill in Reason and return false. Otherwise, return true. + bool canPatternMatch(std::string &Reason, const CodeGenDAGPatterns &CDP); +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const TreePatternNode &TPN) { + TPN.print(OS); + return OS; +} + + +/// TreePattern - Represent a pattern, used for instructions, pattern +/// fragments, etc. +/// +class TreePattern { + /// Trees - The list of pattern trees which corresponds to this pattern. + /// Note that PatFrag's only have a single tree. + /// + std::vector<TreePatternNode*> Trees; + + /// NamedNodes - This is all of the nodes that have names in the trees in this + /// pattern. + StringMap<SmallVector<TreePatternNode*,1> > NamedNodes; + + /// TheRecord - The actual TableGen record corresponding to this pattern. + /// + Record *TheRecord; + + /// Args - This is a list of all of the arguments to this pattern (for + /// PatFrag patterns), which are the 'node' markers in this pattern. + std::vector<std::string> Args; + + /// CDP - the top-level object coordinating this madness. + /// + CodeGenDAGPatterns &CDP; + + /// isInputPattern - True if this is an input pattern, something to match. + /// False if this is an output pattern, something to emit. + bool isInputPattern; +public: + + /// TreePattern constructor - Parse the specified DagInits into the + /// current record. + TreePattern(Record *TheRec, ListInit *RawPat, bool isInput, + CodeGenDAGPatterns &ise); + TreePattern(Record *TheRec, DagInit *Pat, bool isInput, + CodeGenDAGPatterns &ise); + TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput, + CodeGenDAGPatterns &ise); + + /// getTrees - Return the tree patterns which corresponds to this pattern. + /// + const std::vector<TreePatternNode*> &getTrees() const { return Trees; } + unsigned getNumTrees() const { return Trees.size(); } + TreePatternNode *getTree(unsigned i) const { return Trees[i]; } + TreePatternNode *getOnlyTree() const { + assert(Trees.size() == 1 && "Doesn't have exactly one pattern!"); + return Trees[0]; + } + + const StringMap<SmallVector<TreePatternNode*,1> > &getNamedNodesMap() { + if (NamedNodes.empty()) + ComputeNamedNodes(); + return NamedNodes; + } + + /// getRecord - Return the actual TableGen record corresponding to this + /// pattern. + /// + Record *getRecord() const { return TheRecord; } + + unsigned getNumArgs() const { return Args.size(); } + const std::string &getArgName(unsigned i) const { + assert(i < Args.size() && "Argument reference out of range!"); + return Args[i]; + } + std::vector<std::string> &getArgList() { return Args; } + + CodeGenDAGPatterns &getDAGPatterns() const { return CDP; } + + /// InlinePatternFragments - If this pattern refers to any pattern + /// fragments, inline them into place, giving us a pattern without any + /// PatFrag references. + void InlinePatternFragments() { + for (unsigned i = 0, e = Trees.size(); i != e; ++i) + Trees[i] = Trees[i]->InlinePatternFragments(*this); + } + + /// InferAllTypes - Infer/propagate as many types throughout the expression + /// patterns as possible. Return true if all types are inferred, false + /// otherwise. Throw an exception if a type contradiction is found. + bool InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > + *NamedTypes=0); + + /// error - Throw an exception, prefixing it with information about this + /// pattern. + void error(const std::string &Msg) const; + + void print(raw_ostream &OS) const; + void dump() const; + +private: + TreePatternNode *ParseTreePattern(Init *DI, StringRef OpName); + void ComputeNamedNodes(); + void ComputeNamedNodes(TreePatternNode *N); +}; + +/// DAGDefaultOperand - One of these is created for each PredicateOperand +/// or OptionalDefOperand that has a set ExecuteAlways / DefaultOps field. +struct DAGDefaultOperand { + std::vector<TreePatternNode*> DefaultOps; +}; + +class DAGInstruction { + TreePattern *Pattern; + std::vector<Record*> Results; + std::vector<Record*> Operands; + std::vector<Record*> ImpResults; + TreePatternNode *ResultPattern; +public: + DAGInstruction(TreePattern *TP, + const std::vector<Record*> &results, + const std::vector<Record*> &operands, + const std::vector<Record*> &impresults) + : Pattern(TP), Results(results), Operands(operands), + ImpResults(impresults), ResultPattern(0) {} + + const TreePattern *getPattern() const { return Pattern; } + unsigned getNumResults() const { return Results.size(); } + unsigned getNumOperands() const { return Operands.size(); } + unsigned getNumImpResults() const { return ImpResults.size(); } + const std::vector<Record*>& getImpResults() const { return ImpResults; } + + void setResultPattern(TreePatternNode *R) { ResultPattern = R; } + + Record *getResult(unsigned RN) const { + assert(RN < Results.size()); + return Results[RN]; + } + + Record *getOperand(unsigned ON) const { + assert(ON < Operands.size()); + return Operands[ON]; + } + + Record *getImpResult(unsigned RN) const { + assert(RN < ImpResults.size()); + return ImpResults[RN]; + } + + TreePatternNode *getResultPattern() const { return ResultPattern; } +}; + +/// PatternToMatch - Used by CodeGenDAGPatterns to keep tab of patterns +/// processed to produce isel. +class PatternToMatch { +public: + PatternToMatch(Record *srcrecord, ListInit *preds, + TreePatternNode *src, TreePatternNode *dst, + const std::vector<Record*> &dstregs, + unsigned complexity, unsigned uid) + : SrcRecord(srcrecord), Predicates(preds), SrcPattern(src), DstPattern(dst), + Dstregs(dstregs), AddedComplexity(complexity), ID(uid) {} + + Record *SrcRecord; // Originating Record for the pattern. + ListInit *Predicates; // Top level predicate conditions to match. + TreePatternNode *SrcPattern; // Source pattern to match. + TreePatternNode *DstPattern; // Resulting pattern. + std::vector<Record*> Dstregs; // Physical register defs being matched. + unsigned AddedComplexity; // Add to matching pattern complexity. + unsigned ID; // Unique ID for the record. + + Record *getSrcRecord() const { return SrcRecord; } + ListInit *getPredicates() const { return Predicates; } + TreePatternNode *getSrcPattern() const { return SrcPattern; } + TreePatternNode *getDstPattern() const { return DstPattern; } + const std::vector<Record*> &getDstRegs() const { return Dstregs; } + unsigned getAddedComplexity() const { return AddedComplexity; } + + std::string getPredicateCheck() const; + + /// Compute the complexity metric for the input pattern. This roughly + /// corresponds to the number of nodes that are covered. + unsigned getPatternComplexity(const CodeGenDAGPatterns &CGP) const; +}; + +// Deterministic comparison of Record*. +struct RecordPtrCmp { + bool operator()(const Record *LHS, const Record *RHS) const; +}; + +class CodeGenDAGPatterns { + RecordKeeper &Records; + CodeGenTarget Target; + std::vector<CodeGenIntrinsic> Intrinsics; + std::vector<CodeGenIntrinsic> TgtIntrinsics; + + std::map<Record*, SDNodeInfo, RecordPtrCmp> SDNodes; + std::map<Record*, std::pair<Record*, std::string>, RecordPtrCmp> SDNodeXForms; + std::map<Record*, ComplexPattern, RecordPtrCmp> ComplexPatterns; + std::map<Record*, TreePattern*, RecordPtrCmp> PatternFragments; + std::map<Record*, DAGDefaultOperand, RecordPtrCmp> DefaultOperands; + std::map<Record*, DAGInstruction, RecordPtrCmp> Instructions; + + // Specific SDNode definitions: + Record *intrinsic_void_sdnode; + Record *intrinsic_w_chain_sdnode, *intrinsic_wo_chain_sdnode; + + /// PatternsToMatch - All of the things we are matching on the DAG. The first + /// value is the pattern to match, the second pattern is the result to + /// emit. + std::vector<PatternToMatch> PatternsToMatch; +public: + CodeGenDAGPatterns(RecordKeeper &R); + ~CodeGenDAGPatterns(); + + CodeGenTarget &getTargetInfo() { return Target; } + const CodeGenTarget &getTargetInfo() const { return Target; } + + Record *getSDNodeNamed(const std::string &Name) const; + + const SDNodeInfo &getSDNodeInfo(Record *R) const { + assert(SDNodes.count(R) && "Unknown node!"); + return SDNodes.find(R)->second; + } + + // Node transformation lookups. + typedef std::pair<Record*, std::string> NodeXForm; + const NodeXForm &getSDNodeTransform(Record *R) const { + assert(SDNodeXForms.count(R) && "Invalid transform!"); + return SDNodeXForms.find(R)->second; + } + + typedef std::map<Record*, NodeXForm, RecordPtrCmp>::const_iterator + nx_iterator; + nx_iterator nx_begin() const { return SDNodeXForms.begin(); } + nx_iterator nx_end() const { return SDNodeXForms.end(); } + + + const ComplexPattern &getComplexPattern(Record *R) const { + assert(ComplexPatterns.count(R) && "Unknown addressing mode!"); + return ComplexPatterns.find(R)->second; + } + + const CodeGenIntrinsic &getIntrinsic(Record *R) const { + for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i) + if (Intrinsics[i].TheDef == R) return Intrinsics[i]; + for (unsigned i = 0, e = TgtIntrinsics.size(); i != e; ++i) + if (TgtIntrinsics[i].TheDef == R) return TgtIntrinsics[i]; + llvm_unreachable("Unknown intrinsic!"); + } + + const CodeGenIntrinsic &getIntrinsicInfo(unsigned IID) const { + if (IID-1 < Intrinsics.size()) + return Intrinsics[IID-1]; + if (IID-Intrinsics.size()-1 < TgtIntrinsics.size()) + return TgtIntrinsics[IID-Intrinsics.size()-1]; + llvm_unreachable("Bad intrinsic ID!"); + } + + unsigned getIntrinsicID(Record *R) const { + for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i) + if (Intrinsics[i].TheDef == R) return i; + for (unsigned i = 0, e = TgtIntrinsics.size(); i != e; ++i) + if (TgtIntrinsics[i].TheDef == R) return i + Intrinsics.size(); + llvm_unreachable("Unknown intrinsic!"); + } + + const DAGDefaultOperand &getDefaultOperand(Record *R) const { + assert(DefaultOperands.count(R) &&"Isn't an analyzed default operand!"); + return DefaultOperands.find(R)->second; + } + + // Pattern Fragment information. + TreePattern *getPatternFragment(Record *R) const { + assert(PatternFragments.count(R) && "Invalid pattern fragment request!"); + return PatternFragments.find(R)->second; + } + TreePattern *getPatternFragmentIfRead(Record *R) const { + if (!PatternFragments.count(R)) return 0; + return PatternFragments.find(R)->second; + } + + typedef std::map<Record*, TreePattern*, RecordPtrCmp>::const_iterator + pf_iterator; + pf_iterator pf_begin() const { return PatternFragments.begin(); } + pf_iterator pf_end() const { return PatternFragments.end(); } + + // Patterns to match information. + typedef std::vector<PatternToMatch>::const_iterator ptm_iterator; + ptm_iterator ptm_begin() const { return PatternsToMatch.begin(); } + ptm_iterator ptm_end() const { return PatternsToMatch.end(); } + + + + const DAGInstruction &getInstruction(Record *R) const { + assert(Instructions.count(R) && "Unknown instruction!"); + return Instructions.find(R)->second; + } + + Record *get_intrinsic_void_sdnode() const { + return intrinsic_void_sdnode; + } + Record *get_intrinsic_w_chain_sdnode() const { + return intrinsic_w_chain_sdnode; + } + Record *get_intrinsic_wo_chain_sdnode() const { + return intrinsic_wo_chain_sdnode; + } + + bool hasTargetIntrinsics() { return !TgtIntrinsics.empty(); } + +private: + void ParseNodeInfo(); + void ParseNodeTransforms(); + void ParseComplexPatterns(); + void ParsePatternFragments(); + void ParseDefaultOperands(); + void ParseInstructions(); + void ParsePatterns(); + void InferInstructionFlags(); + void GenerateVariants(); + + void AddPatternToMatch(const TreePattern *Pattern, const PatternToMatch &PTM); + void FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, + std::map<std::string, + TreePatternNode*> &InstInputs, + std::map<std::string, + TreePatternNode*> &InstResults, + std::vector<Record*> &InstImpResults); +}; +} // end namespace llvm + +#endif diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp new file mode 100644 index 0000000..fb9ad93 --- /dev/null +++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp @@ -0,0 +1,593 @@ +//===- CodeGenInstruction.cpp - CodeGen Instruction Class Wrapper ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the CodeGenInstruction class. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenInstruction.h" +#include "CodeGenTarget.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" +#include <set> +using namespace llvm; + +//===----------------------------------------------------------------------===// +// CGIOperandList Implementation +//===----------------------------------------------------------------------===// + +CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { + isPredicable = false; + hasOptionalDef = false; + isVariadic = false; + + DagInit *OutDI = R->getValueAsDag("OutOperandList"); + + if (DefInit *Init = dynamic_cast<DefInit*>(OutDI->getOperator())) { + if (Init->getDef()->getName() != "outs") + throw R->getName() + ": invalid def name for output list: use 'outs'"; + } else + throw R->getName() + ": invalid output list: use 'outs'"; + + NumDefs = OutDI->getNumArgs(); + + DagInit *InDI = R->getValueAsDag("InOperandList"); + if (DefInit *Init = dynamic_cast<DefInit*>(InDI->getOperator())) { + if (Init->getDef()->getName() != "ins") + throw R->getName() + ": invalid def name for input list: use 'ins'"; + } else + throw R->getName() + ": invalid input list: use 'ins'"; + + unsigned MIOperandNo = 0; + std::set<std::string> OperandNames; + for (unsigned i = 0, e = InDI->getNumArgs()+OutDI->getNumArgs(); i != e; ++i){ + Init *ArgInit; + std::string ArgName; + if (i < NumDefs) { + ArgInit = OutDI->getArg(i); + ArgName = OutDI->getArgName(i); + } else { + ArgInit = InDI->getArg(i-NumDefs); + ArgName = InDI->getArgName(i-NumDefs); + } + + DefInit *Arg = dynamic_cast<DefInit*>(ArgInit); + if (!Arg) + throw "Illegal operand for the '" + R->getName() + "' instruction!"; + + Record *Rec = Arg->getDef(); + std::string PrintMethod = "printOperand"; + std::string EncoderMethod; + std::string OperandType = "OPERAND_UNKNOWN"; + unsigned NumOps = 1; + DagInit *MIOpInfo = 0; + if (Rec->isSubClassOf("RegisterOperand")) { + PrintMethod = Rec->getValueAsString("PrintMethod"); + } else if (Rec->isSubClassOf("Operand")) { + PrintMethod = Rec->getValueAsString("PrintMethod"); + OperandType = Rec->getValueAsString("OperandType"); + // If there is an explicit encoder method, use it. + EncoderMethod = Rec->getValueAsString("EncoderMethod"); + MIOpInfo = Rec->getValueAsDag("MIOperandInfo"); + + // Verify that MIOpInfo has an 'ops' root value. + if (!dynamic_cast<DefInit*>(MIOpInfo->getOperator()) || + dynamic_cast<DefInit*>(MIOpInfo->getOperator()) + ->getDef()->getName() != "ops") + throw "Bad value for MIOperandInfo in operand '" + Rec->getName() + + "'\n"; + + // If we have MIOpInfo, then we have #operands equal to number of entries + // in MIOperandInfo. + if (unsigned NumArgs = MIOpInfo->getNumArgs()) + NumOps = NumArgs; + + if (Rec->isSubClassOf("PredicateOperand")) + isPredicable = true; + else if (Rec->isSubClassOf("OptionalDefOperand")) + hasOptionalDef = true; + } else if (Rec->getName() == "variable_ops") { + isVariadic = true; + continue; + } else if (Rec->isSubClassOf("RegisterClass")) { + OperandType = "OPERAND_REGISTER"; + } else if (!Rec->isSubClassOf("PointerLikeRegClass") && + Rec->getName() != "unknown") + throw "Unknown operand class '" + Rec->getName() + + "' in '" + R->getName() + "' instruction!"; + + // Check that the operand has a name and that it's unique. + if (ArgName.empty()) + throw "In instruction '" + R->getName() + "', operand #" + utostr(i) + + " has no name!"; + if (!OperandNames.insert(ArgName).second) + throw "In instruction '" + R->getName() + "', operand #" + utostr(i) + + " has the same name as a previous operand!"; + + OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod, EncoderMethod, + OperandType, MIOperandNo, NumOps, + MIOpInfo)); + MIOperandNo += NumOps; + } + + + // Make sure the constraints list for each operand is large enough to hold + // constraint info, even if none is present. + for (unsigned i = 0, e = OperandList.size(); i != e; ++i) + OperandList[i].Constraints.resize(OperandList[i].MINumOperands); +} + + +/// getOperandNamed - Return the index of the operand with the specified +/// non-empty name. If the instruction does not have an operand with the +/// specified name, throw an exception. +/// +unsigned CGIOperandList::getOperandNamed(StringRef Name) const { + unsigned OpIdx; + if (hasOperandNamed(Name, OpIdx)) return OpIdx; + throw "'" + TheDef->getName() + "' does not have an operand named '$" + + Name.str() + "'!"; +} + +/// hasOperandNamed - Query whether the instruction has an operand of the +/// given name. If so, return true and set OpIdx to the index of the +/// operand. Otherwise, return false. +bool CGIOperandList::hasOperandNamed(StringRef Name, unsigned &OpIdx) const { + assert(!Name.empty() && "Cannot search for operand with no name!"); + for (unsigned i = 0, e = OperandList.size(); i != e; ++i) + if (OperandList[i].Name == Name) { + OpIdx = i; + return true; + } + return false; +} + +std::pair<unsigned,unsigned> +CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) { + if (Op.empty() || Op[0] != '$') + throw TheDef->getName() + ": Illegal operand name: '" + Op + "'"; + + std::string OpName = Op.substr(1); + std::string SubOpName; + + // Check to see if this is $foo.bar. + std::string::size_type DotIdx = OpName.find_first_of("."); + if (DotIdx != std::string::npos) { + SubOpName = OpName.substr(DotIdx+1); + if (SubOpName.empty()) + throw TheDef->getName() + ": illegal empty suboperand name in '" +Op +"'"; + OpName = OpName.substr(0, DotIdx); + } + + unsigned OpIdx = getOperandNamed(OpName); + + if (SubOpName.empty()) { // If no suboperand name was specified: + // If one was needed, throw. + if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp && + SubOpName.empty()) + throw TheDef->getName() + ": Illegal to refer to" + " whole operand part of complex operand '" + Op + "'"; + + // Otherwise, return the operand. + return std::make_pair(OpIdx, 0U); + } + + // Find the suboperand number involved. + DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo; + if (MIOpInfo == 0) + throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'"; + + // Find the operand with the right name. + for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i) + if (MIOpInfo->getArgName(i) == SubOpName) + return std::make_pair(OpIdx, i); + + // Otherwise, didn't find it! + throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'"; +} + +static void ParseConstraint(const std::string &CStr, CGIOperandList &Ops) { + // EARLY_CLOBBER: @early $reg + std::string::size_type wpos = CStr.find_first_of(" \t"); + std::string::size_type start = CStr.find_first_not_of(" \t"); + std::string Tok = CStr.substr(start, wpos - start); + if (Tok == "@earlyclobber") { + std::string Name = CStr.substr(wpos+1); + wpos = Name.find_first_not_of(" \t"); + if (wpos == std::string::npos) + throw "Illegal format for @earlyclobber constraint: '" + CStr + "'"; + Name = Name.substr(wpos); + std::pair<unsigned,unsigned> Op = Ops.ParseOperandName(Name, false); + + // Build the string for the operand + if (!Ops[Op.first].Constraints[Op.second].isNone()) + throw "Operand '" + Name + "' cannot have multiple constraints!"; + Ops[Op.first].Constraints[Op.second] = + CGIOperandList::ConstraintInfo::getEarlyClobber(); + return; + } + + // Only other constraint is "TIED_TO" for now. + std::string::size_type pos = CStr.find_first_of('='); + assert(pos != std::string::npos && "Unrecognized constraint"); + start = CStr.find_first_not_of(" \t"); + std::string Name = CStr.substr(start, pos - start); + + // TIED_TO: $src1 = $dst + wpos = Name.find_first_of(" \t"); + if (wpos == std::string::npos) + throw "Illegal format for tied-to constraint: '" + CStr + "'"; + std::string DestOpName = Name.substr(0, wpos); + std::pair<unsigned,unsigned> DestOp = Ops.ParseOperandName(DestOpName, false); + + Name = CStr.substr(pos+1); + wpos = Name.find_first_not_of(" \t"); + if (wpos == std::string::npos) + throw "Illegal format for tied-to constraint: '" + CStr + "'"; + + std::pair<unsigned,unsigned> SrcOp = + Ops.ParseOperandName(Name.substr(wpos), false); + if (SrcOp > DestOp) + throw "Illegal tied-to operand constraint '" + CStr + "'"; + + + unsigned FlatOpNo = Ops.getFlattenedOperandNumber(SrcOp); + + if (!Ops[DestOp.first].Constraints[DestOp.second].isNone()) + throw "Operand '" + DestOpName + "' cannot have multiple constraints!"; + Ops[DestOp.first].Constraints[DestOp.second] = + CGIOperandList::ConstraintInfo::getTied(FlatOpNo); +} + +static void ParseConstraints(const std::string &CStr, CGIOperandList &Ops) { + if (CStr.empty()) return; + + const std::string delims(","); + std::string::size_type bidx, eidx; + + bidx = CStr.find_first_not_of(delims); + while (bidx != std::string::npos) { + eidx = CStr.find_first_of(delims, bidx); + if (eidx == std::string::npos) + eidx = CStr.length(); + + ParseConstraint(CStr.substr(bidx, eidx - bidx), Ops); + bidx = CStr.find_first_not_of(delims, eidx); + } +} + +void CGIOperandList::ProcessDisableEncoding(std::string DisableEncoding) { + while (1) { + std::pair<StringRef, StringRef> P = getToken(DisableEncoding, " ,\t"); + std::string OpName = P.first; + DisableEncoding = P.second; + if (OpName.empty()) break; + + // Figure out which operand this is. + std::pair<unsigned,unsigned> Op = ParseOperandName(OpName, false); + + // Mark the operand as not-to-be encoded. + if (Op.second >= OperandList[Op.first].DoNotEncode.size()) + OperandList[Op.first].DoNotEncode.resize(Op.second+1); + OperandList[Op.first].DoNotEncode[Op.second] = true; + } + +} + +//===----------------------------------------------------------------------===// +// CodeGenInstruction Implementation +//===----------------------------------------------------------------------===// + +CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R), Operands(R) { + Namespace = R->getValueAsString("Namespace"); + AsmString = R->getValueAsString("AsmString"); + + isReturn = R->getValueAsBit("isReturn"); + isBranch = R->getValueAsBit("isBranch"); + isIndirectBranch = R->getValueAsBit("isIndirectBranch"); + isCompare = R->getValueAsBit("isCompare"); + isMoveImm = R->getValueAsBit("isMoveImm"); + isBitcast = R->getValueAsBit("isBitcast"); + isBarrier = R->getValueAsBit("isBarrier"); + isCall = R->getValueAsBit("isCall"); + canFoldAsLoad = R->getValueAsBit("canFoldAsLoad"); + mayLoad = R->getValueAsBit("mayLoad"); + mayStore = R->getValueAsBit("mayStore"); + isPredicable = Operands.isPredicable || R->getValueAsBit("isPredicable"); + isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress"); + isCommutable = R->getValueAsBit("isCommutable"); + isTerminator = R->getValueAsBit("isTerminator"); + isReMaterializable = R->getValueAsBit("isReMaterializable"); + hasDelaySlot = R->getValueAsBit("hasDelaySlot"); + usesCustomInserter = R->getValueAsBit("usesCustomInserter"); + hasPostISelHook = R->getValueAsBit("hasPostISelHook"); + hasCtrlDep = R->getValueAsBit("hasCtrlDep"); + isNotDuplicable = R->getValueAsBit("isNotDuplicable"); + hasSideEffects = R->getValueAsBit("hasSideEffects"); + neverHasSideEffects = R->getValueAsBit("neverHasSideEffects"); + isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove"); + hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq"); + hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq"); + isCodeGenOnly = R->getValueAsBit("isCodeGenOnly"); + isPseudo = R->getValueAsBit("isPseudo"); + ImplicitDefs = R->getValueAsListOfDefs("Defs"); + ImplicitUses = R->getValueAsListOfDefs("Uses"); + + if (neverHasSideEffects + hasSideEffects > 1) + throw R->getName() + ": multiple conflicting side-effect flags set!"; + + // Parse Constraints. + ParseConstraints(R->getValueAsString("Constraints"), Operands); + + // Parse the DisableEncoding field. + Operands.ProcessDisableEncoding(R->getValueAsString("DisableEncoding")); +} + +/// HasOneImplicitDefWithKnownVT - If the instruction has at least one +/// implicit def and it has a known VT, return the VT, otherwise return +/// MVT::Other. +MVT::SimpleValueType CodeGenInstruction:: +HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const { + if (ImplicitDefs.empty()) return MVT::Other; + + // Check to see if the first implicit def has a resolvable type. + Record *FirstImplicitDef = ImplicitDefs[0]; + assert(FirstImplicitDef->isSubClassOf("Register")); + const std::vector<MVT::SimpleValueType> &RegVTs = + TargetInfo.getRegisterVTs(FirstImplicitDef); + if (RegVTs.size() == 1) + return RegVTs[0]; + return MVT::Other; +} + + +/// FlattenAsmStringVariants - Flatten the specified AsmString to only +/// include text from the specified variant, returning the new string. +std::string CodeGenInstruction:: +FlattenAsmStringVariants(StringRef Cur, unsigned Variant) { + std::string Res = ""; + + for (;;) { + // Find the start of the next variant string. + size_t VariantsStart = 0; + for (size_t e = Cur.size(); VariantsStart != e; ++VariantsStart) + if (Cur[VariantsStart] == '{' && + (VariantsStart == 0 || (Cur[VariantsStart-1] != '$' && + Cur[VariantsStart-1] != '\\'))) + break; + + // Add the prefix to the result. + Res += Cur.slice(0, VariantsStart); + if (VariantsStart == Cur.size()) + break; + + ++VariantsStart; // Skip the '{'. + + // Scan to the end of the variants string. + size_t VariantsEnd = VariantsStart; + unsigned NestedBraces = 1; + for (size_t e = Cur.size(); VariantsEnd != e; ++VariantsEnd) { + if (Cur[VariantsEnd] == '}' && Cur[VariantsEnd-1] != '\\') { + if (--NestedBraces == 0) + break; + } else if (Cur[VariantsEnd] == '{') + ++NestedBraces; + } + + // Select the Nth variant (or empty). + StringRef Selection = Cur.slice(VariantsStart, VariantsEnd); + for (unsigned i = 0; i != Variant; ++i) + Selection = Selection.split('|').second; + Res += Selection.split('|').first; + + assert(VariantsEnd != Cur.size() && + "Unterminated variants in assembly string!"); + Cur = Cur.substr(VariantsEnd + 1); + } + + return Res; +} + + +//===----------------------------------------------------------------------===// +/// CodeGenInstAlias Implementation +//===----------------------------------------------------------------------===// + +/// tryAliasOpMatch - This is a helper function for the CodeGenInstAlias +/// constructor. It checks if an argument in an InstAlias pattern matches +/// the corresponding operand of the instruction. It returns true on a +/// successful match, with ResOp set to the result operand to be used. +bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, + Record *InstOpRec, bool hasSubOps, + SMLoc Loc, CodeGenTarget &T, + ResultOperand &ResOp) { + Init *Arg = Result->getArg(AliasOpNo); + DefInit *ADI = dynamic_cast<DefInit*>(Arg); + + if (ADI && ADI->getDef() == InstOpRec) { + // If the operand is a record, it must have a name, and the record type + // must match up with the instruction's argument type. + if (Result->getArgName(AliasOpNo).empty()) + throw TGError(Loc, "result argument #" + utostr(AliasOpNo) + + " must have a name!"); + ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef()); + return true; + } + + // For register operands, the source register class can be a subclass + // of the instruction register class, not just an exact match. + if (ADI && ADI->getDef()->isSubClassOf("RegisterClass")) { + if (!InstOpRec->isSubClassOf("RegisterClass")) + return false; + if (!T.getRegisterClass(InstOpRec) + .hasSubClass(&T.getRegisterClass(ADI->getDef()))) + return false; + ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef()); + return true; + } + + // Handle explicit registers. + if (ADI && ADI->getDef()->isSubClassOf("Register")) { + if (InstOpRec->isSubClassOf("OptionalDefOperand")) { + DagInit *DI = InstOpRec->getValueAsDag("MIOperandInfo"); + // The operand info should only have a single (register) entry. We + // want the register class of it. + InstOpRec = dynamic_cast<DefInit*>(DI->getArg(0))->getDef(); + } + + if (InstOpRec->isSubClassOf("RegisterOperand")) + InstOpRec = InstOpRec->getValueAsDef("RegClass"); + + if (!InstOpRec->isSubClassOf("RegisterClass")) + return false; + + if (!T.getRegisterClass(InstOpRec) + .contains(T.getRegBank().getReg(ADI->getDef()))) + throw TGError(Loc, "fixed register " + ADI->getDef()->getName() + + " is not a member of the " + InstOpRec->getName() + + " register class!"); + + if (!Result->getArgName(AliasOpNo).empty()) + throw TGError(Loc, "result fixed register argument must " + "not have a name!"); + + ResOp = ResultOperand(ADI->getDef()); + return true; + } + + // Handle "zero_reg" for optional def operands. + if (ADI && ADI->getDef()->getName() == "zero_reg") { + + // Check if this is an optional def. + // Tied operands where the source is a sub-operand of a complex operand + // need to represent both operands in the alias destination instruction. + // Allow zero_reg for the tied portion. This can and should go away once + // the MC representation of things doesn't use tied operands at all. + //if (!InstOpRec->isSubClassOf("OptionalDefOperand")) + // throw TGError(Loc, "reg0 used for result that is not an " + // "OptionalDefOperand!"); + + ResOp = ResultOperand(static_cast<Record*>(0)); + return true; + } + + // Literal integers. + if (IntInit *II = dynamic_cast<IntInit*>(Arg)) { + if (hasSubOps || !InstOpRec->isSubClassOf("Operand")) + return false; + // Integer arguments can't have names. + if (!Result->getArgName(AliasOpNo).empty()) + throw TGError(Loc, "result argument #" + utostr(AliasOpNo) + + " must not have a name!"); + ResOp = ResultOperand(II->getValue()); + return true; + } + + // If both are Operands with the same MVT, allow the conversion. It's + // up to the user to make sure the values are appropriate, just like + // for isel Pat's. + if (InstOpRec->isSubClassOf("Operand") && + ADI->getDef()->isSubClassOf("Operand")) { + // FIXME: What other attributes should we check here? Identical + // MIOperandInfo perhaps? + if (InstOpRec->getValueInit("Type") != ADI->getDef()->getValueInit("Type")) + return false; + ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef()); + return true; + } + + return false; +} + +CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) { + AsmString = R->getValueAsString("AsmString"); + Result = R->getValueAsDag("ResultInst"); + + // Verify that the root of the result is an instruction. + DefInit *DI = dynamic_cast<DefInit*>(Result->getOperator()); + if (DI == 0 || !DI->getDef()->isSubClassOf("Instruction")) + throw TGError(R->getLoc(), "result of inst alias should be an instruction"); + + ResultInst = &T.getInstruction(DI->getDef()); + + // NameClass - If argument names are repeated, we need to verify they have + // the same class. + StringMap<Record*> NameClass; + for (unsigned i = 0, e = Result->getNumArgs(); i != e; ++i) { + DefInit *ADI = dynamic_cast<DefInit*>(Result->getArg(i)); + if (!ADI || Result->getArgName(i).empty()) + continue; + // Verify we don't have something like: (someinst GR16:$foo, GR32:$foo) + // $foo can exist multiple times in the result list, but it must have the + // same type. + Record *&Entry = NameClass[Result->getArgName(i)]; + if (Entry && Entry != ADI->getDef()) + throw TGError(R->getLoc(), "result value $" + Result->getArgName(i) + + " is both " + Entry->getName() + " and " + + ADI->getDef()->getName() + "!"); + Entry = ADI->getDef(); + } + + // Decode and validate the arguments of the result. + unsigned AliasOpNo = 0; + for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) { + + // Tied registers don't have an entry in the result dag unless they're part + // of a complex operand, in which case we include them anyways, as we + // don't have any other way to specify the whole operand. + if (ResultInst->Operands[i].MINumOperands == 1 && + ResultInst->Operands[i].getTiedRegister() != -1) + continue; + + if (AliasOpNo >= Result->getNumArgs()) + throw TGError(R->getLoc(), "not enough arguments for instruction!"); + + Record *InstOpRec = ResultInst->Operands[i].Rec; + unsigned NumSubOps = ResultInst->Operands[i].MINumOperands; + ResultOperand ResOp(static_cast<int64_t>(0)); + if (tryAliasOpMatch(Result, AliasOpNo, InstOpRec, (NumSubOps > 1), + R->getLoc(), T, ResOp)) { + ResultOperands.push_back(ResOp); + ResultInstOperandIndex.push_back(std::make_pair(i, -1)); + ++AliasOpNo; + continue; + } + + // If the argument did not match the instruction operand, and the operand + // is composed of multiple suboperands, try matching the suboperands. + if (NumSubOps > 1) { + DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo; + for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) { + if (AliasOpNo >= Result->getNumArgs()) + throw TGError(R->getLoc(), "not enough arguments for instruction!"); + Record *SubRec = dynamic_cast<DefInit*>(MIOI->getArg(SubOp))->getDef(); + if (tryAliasOpMatch(Result, AliasOpNo, SubRec, false, + R->getLoc(), T, ResOp)) { + ResultOperands.push_back(ResOp); + ResultInstOperandIndex.push_back(std::make_pair(i, SubOp)); + ++AliasOpNo; + } else { + throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + + " does not match instruction operand class " + + (SubOp == 0 ? InstOpRec->getName() :SubRec->getName())); + } + } + continue; + } + throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + + " does not match instruction operand class " + + InstOpRec->getName()); + } + + if (AliasOpNo != Result->getNumArgs()) + throw TGError(R->getLoc(), "too many operands for instruction!"); +} diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.h b/contrib/llvm/utils/TableGen/CodeGenInstruction.h new file mode 100644 index 0000000..468277a --- /dev/null +++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.h @@ -0,0 +1,326 @@ +//===- CodeGenInstruction.h - Instruction Class Wrapper ---------*- 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 a wrapper class for the 'Instruction' TableGen class. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_INSTRUCTION_H +#define CODEGEN_INSTRUCTION_H + +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/SourceMgr.h" +#include <string> +#include <vector> +#include <utility> + +namespace llvm { + class Record; + class DagInit; + class CodeGenTarget; + class StringRef; + + class CGIOperandList { + public: + class ConstraintInfo { + enum { None, EarlyClobber, Tied } Kind; + unsigned OtherTiedOperand; + public: + ConstraintInfo() : Kind(None) {} + + static ConstraintInfo getEarlyClobber() { + ConstraintInfo I; + I.Kind = EarlyClobber; + I.OtherTiedOperand = 0; + return I; + } + + static ConstraintInfo getTied(unsigned Op) { + ConstraintInfo I; + I.Kind = Tied; + I.OtherTiedOperand = Op; + return I; + } + + bool isNone() const { return Kind == None; } + bool isEarlyClobber() const { return Kind == EarlyClobber; } + bool isTied() const { return Kind == Tied; } + + unsigned getTiedOperand() const { + assert(isTied()); + return OtherTiedOperand; + } + }; + + /// OperandInfo - The information we keep track of for each operand in the + /// operand list for a tablegen instruction. + struct OperandInfo { + /// Rec - The definition this operand is declared as. + /// + Record *Rec; + + /// Name - If this operand was assigned a symbolic name, this is it, + /// otherwise, it's empty. + std::string Name; + + /// PrinterMethodName - The method used to print operands of this type in + /// the asmprinter. + std::string PrinterMethodName; + + /// EncoderMethodName - The method used to get the machine operand value + /// for binary encoding. "getMachineOpValue" by default. + std::string EncoderMethodName; + + /// OperandType - A value from MCOI::OperandType representing the type of + /// the operand. + std::string OperandType; + + /// MIOperandNo - Currently (this is meant to be phased out), some logical + /// operands correspond to multiple MachineInstr operands. In the X86 + /// target for example, one address operand is represented as 4 + /// MachineOperands. Because of this, the operand number in the + /// OperandList may not match the MachineInstr operand num. Until it + /// does, this contains the MI operand index of this operand. + unsigned MIOperandNo; + unsigned MINumOperands; // The number of operands. + + /// DoNotEncode - Bools are set to true in this vector for each operand in + /// the DisableEncoding list. These should not be emitted by the code + /// emitter. + std::vector<bool> DoNotEncode; + + /// MIOperandInfo - Default MI operand type. Note an operand may be made + /// up of multiple MI operands. + DagInit *MIOperandInfo; + + /// Constraint info for this operand. This operand can have pieces, so we + /// track constraint info for each. + std::vector<ConstraintInfo> Constraints; + + OperandInfo(Record *R, const std::string &N, const std::string &PMN, + const std::string &EMN, const std::string &OT, unsigned MION, + unsigned MINO, DagInit *MIOI) + : Rec(R), Name(N), PrinterMethodName(PMN), EncoderMethodName(EMN), + OperandType(OT), MIOperandNo(MION), MINumOperands(MINO), + MIOperandInfo(MIOI) {} + + + /// getTiedOperand - If this operand is tied to another one, return the + /// other operand number. Otherwise, return -1. + int getTiedRegister() const { + for (unsigned j = 0, e = Constraints.size(); j != e; ++j) { + const CGIOperandList::ConstraintInfo &CI = Constraints[j]; + if (CI.isTied()) return CI.getTiedOperand(); + } + return -1; + } + }; + + CGIOperandList(Record *D); + + Record *TheDef; // The actual record containing this OperandList. + + /// NumDefs - Number of def operands declared, this is the number of + /// elements in the instruction's (outs) list. + /// + unsigned NumDefs; + + /// OperandList - The list of declared operands, along with their declared + /// type (which is a record). + std::vector<OperandInfo> OperandList; + + // Information gleaned from the operand list. + bool isPredicable; + bool hasOptionalDef; + bool isVariadic; + + // Provide transparent accessors to the operand list. + bool empty() const { return OperandList.empty(); } + unsigned size() const { return OperandList.size(); } + const OperandInfo &operator[](unsigned i) const { return OperandList[i]; } + OperandInfo &operator[](unsigned i) { return OperandList[i]; } + OperandInfo &back() { return OperandList.back(); } + const OperandInfo &back() const { return OperandList.back(); } + + + /// getOperandNamed - Return the index of the operand with the specified + /// non-empty name. If the instruction does not have an operand with the + /// specified name, throw an exception. + unsigned getOperandNamed(StringRef Name) const; + + /// hasOperandNamed - Query whether the instruction has an operand of the + /// given name. If so, return true and set OpIdx to the index of the + /// operand. Otherwise, return false. + bool hasOperandNamed(StringRef Name, unsigned &OpIdx) const; + + /// ParseOperandName - Parse an operand name like "$foo" or "$foo.bar", + /// where $foo is a whole operand and $foo.bar refers to a suboperand. + /// This throws an exception if the name is invalid. If AllowWholeOp is + /// true, references to operands with suboperands are allowed, otherwise + /// not. + std::pair<unsigned,unsigned> ParseOperandName(const std::string &Op, + bool AllowWholeOp = true); + + /// getFlattenedOperandNumber - Flatten a operand/suboperand pair into a + /// flat machineinstr operand #. + unsigned getFlattenedOperandNumber(std::pair<unsigned,unsigned> Op) const { + return OperandList[Op.first].MIOperandNo + Op.second; + } + + /// getSubOperandNumber - Unflatten a operand number into an + /// operand/suboperand pair. + std::pair<unsigned,unsigned> getSubOperandNumber(unsigned Op) const { + for (unsigned i = 0; ; ++i) { + assert(i < OperandList.size() && "Invalid flat operand #"); + if (OperandList[i].MIOperandNo+OperandList[i].MINumOperands > Op) + return std::make_pair(i, Op-OperandList[i].MIOperandNo); + } + } + + + /// isFlatOperandNotEmitted - Return true if the specified flat operand # + /// should not be emitted with the code emitter. + bool isFlatOperandNotEmitted(unsigned FlatOpNo) const { + std::pair<unsigned,unsigned> Op = getSubOperandNumber(FlatOpNo); + if (OperandList[Op.first].DoNotEncode.size() > Op.second) + return OperandList[Op.first].DoNotEncode[Op.second]; + return false; + } + + void ProcessDisableEncoding(std::string Value); + }; + + + class CodeGenInstruction { + public: + Record *TheDef; // The actual record defining this instruction. + std::string Namespace; // The namespace the instruction is in. + + /// AsmString - The format string used to emit a .s file for the + /// instruction. + std::string AsmString; + + /// Operands - This is information about the (ins) and (outs) list specified + /// to the instruction. + CGIOperandList Operands; + + /// ImplicitDefs/ImplicitUses - These are lists of registers that are + /// implicitly defined and used by the instruction. + std::vector<Record*> ImplicitDefs, ImplicitUses; + + // Various boolean values we track for the instruction. + bool isReturn; + bool isBranch; + bool isIndirectBranch; + bool isCompare; + bool isMoveImm; + bool isBitcast; + bool isBarrier; + bool isCall; + bool canFoldAsLoad; + bool mayLoad, mayStore; + bool isPredicable; + bool isConvertibleToThreeAddress; + bool isCommutable; + bool isTerminator; + bool isReMaterializable; + bool hasDelaySlot; + bool usesCustomInserter; + bool hasPostISelHook; + bool hasCtrlDep; + bool isNotDuplicable; + bool hasSideEffects; + bool neverHasSideEffects; + bool isAsCheapAsAMove; + bool hasExtraSrcRegAllocReq; + bool hasExtraDefRegAllocReq; + bool isCodeGenOnly; + bool isPseudo; + + + CodeGenInstruction(Record *R); + + /// HasOneImplicitDefWithKnownVT - If the instruction has at least one + /// implicit def and it has a known VT, return the VT, otherwise return + /// MVT::Other. + MVT::SimpleValueType + HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const; + + + /// FlattenAsmStringVariants - Flatten the specified AsmString to only + /// include text from the specified variant, returning the new string. + static std::string FlattenAsmStringVariants(StringRef AsmString, + unsigned Variant); + }; + + + /// CodeGenInstAlias - This represents an InstAlias definition. + class CodeGenInstAlias { + public: + Record *TheDef; // The actual record defining this InstAlias. + + /// AsmString - The format string used to emit a .s file for the + /// instruction. + std::string AsmString; + + /// Result - The result instruction. + DagInit *Result; + + /// ResultInst - The instruction generated by the alias (decoded from + /// Result). + CodeGenInstruction *ResultInst; + + + struct ResultOperand { + private: + StringRef Name; + Record *R; + + int64_t Imm; + public: + enum { + K_Record, + K_Imm, + K_Reg + } Kind; + + ResultOperand(StringRef N, Record *r) : Name(N), R(r), Kind(K_Record) {} + ResultOperand(int64_t I) : Imm(I), Kind(K_Imm) {} + ResultOperand(Record *r) : R(r), Kind(K_Reg) {} + + bool isRecord() const { return Kind == K_Record; } + bool isImm() const { return Kind == K_Imm; } + bool isReg() const { return Kind == K_Reg; } + + StringRef getName() const { assert(isRecord()); return Name; } + Record *getRecord() const { assert(isRecord()); return R; } + int64_t getImm() const { assert(isImm()); return Imm; } + Record *getRegister() const { assert(isReg()); return R; } + }; + + /// ResultOperands - The decoded operands for the result instruction. + std::vector<ResultOperand> ResultOperands; + + /// ResultInstOperandIndex - For each operand, this vector holds a pair of + /// indices to identify the corresponding operand in the result + /// instruction. The first index specifies the operand and the second + /// index specifies the suboperand. If there are no suboperands or if all + /// of them are matched by the operand, the second value should be -1. + std::vector<std::pair<unsigned, int> > ResultInstOperandIndex; + + CodeGenInstAlias(Record *R, CodeGenTarget &T); + + bool tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, + Record *InstOpRec, bool hasSubOps, SMLoc Loc, + CodeGenTarget &T, ResultOperand &ResOp); + }; +} + +#endif diff --git a/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h b/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h new file mode 100644 index 0000000..3f6ba61 --- /dev/null +++ b/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h @@ -0,0 +1,90 @@ +//===- CodeGenIntrinsic.h - Intrinsic Class Wrapper ------------*- 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 a wrapper class for the 'Intrinsic' TableGen class. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_INTRINSIC_H +#define CODEGEN_INTRINSIC_H + +#include <string> +#include <vector> +#include "llvm/CodeGen/ValueTypes.h" + +namespace llvm { + class Record; + class RecordKeeper; + class CodeGenTarget; + + struct CodeGenIntrinsic { + Record *TheDef; // The actual record defining this intrinsic. + std::string Name; // The name of the LLVM function "llvm.bswap.i32" + std::string EnumName; // The name of the enum "bswap_i32" + std::string GCCBuiltinName;// Name of the corresponding GCC builtin, or "". + std::string TargetPrefix; // Target prefix, e.g. "ppc" for t-s intrinsics. + + /// IntrinsicSignature - This structure holds the return values and + /// parameter values of an intrinsic. If the number of return values is > 1, + /// then the intrinsic implicitly returns a first-class aggregate. The + /// numbering of the types starts at 0 with the first return value and + /// continues from there through the parameter list. This is useful for + /// "matching" types. + struct IntrinsicSignature { + /// RetVTs - The MVT::SimpleValueType for each return type. Note that this + /// list is only populated when in the context of a target .td file. When + /// building Intrinsics.td, this isn't available, because we don't know + /// the target pointer size. + std::vector<MVT::SimpleValueType> RetVTs; + + /// RetTypeDefs - The records for each return type. + std::vector<Record*> RetTypeDefs; + + /// ParamVTs - The MVT::SimpleValueType for each parameter type. Note that + /// this list is only populated when in the context of a target .td file. + /// When building Intrinsics.td, this isn't available, because we don't + /// know the target pointer size. + std::vector<MVT::SimpleValueType> ParamVTs; + + /// ParamTypeDefs - The records for each parameter type. + std::vector<Record*> ParamTypeDefs; + }; + + IntrinsicSignature IS; + + // Memory mod/ref behavior of this intrinsic. + enum { + NoMem, ReadArgMem, ReadMem, ReadWriteArgMem, ReadWriteMem + } ModRef; + + /// This is set to true if the intrinsic is overloaded by its argument + /// types. + bool isOverloaded; + + /// isCommutative - True if the intrinsic is commutative. + bool isCommutative; + + /// canThrow - True if the intrinsic can throw. + bool canThrow; + + enum ArgAttribute { + NoCapture + }; + std::vector<std::pair<unsigned, ArgAttribute> > ArgumentAttributes; + + CodeGenIntrinsic(Record *R); + }; + + /// LoadIntrinsics - Read all of the intrinsics defined in the specified + /// .td file. + std::vector<CodeGenIntrinsic> LoadIntrinsics(const RecordKeeper &RC, + bool TargetOnly); +} + +#endif diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp new file mode 100644 index 0000000..45c5bb8 --- /dev/null +++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp @@ -0,0 +1,1645 @@ +//===- CodeGenRegisters.cpp - Register and RegisterClass Info -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines structures to encapsulate information gleaned from the +// target register and register class definitions. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenRegisters.h" +#include "CodeGenTarget.h" +#include "llvm/TableGen/Error.h" +#include "llvm/ADT/IntEqClasses.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// CodeGenSubRegIndex +//===----------------------------------------------------------------------===// + +CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum) + : TheDef(R), + EnumValue(Enum) +{} + +std::string CodeGenSubRegIndex::getNamespace() const { + if (TheDef->getValue("Namespace")) + return TheDef->getValueAsString("Namespace"); + else + return ""; +} + +const std::string &CodeGenSubRegIndex::getName() const { + return TheDef->getName(); +} + +std::string CodeGenSubRegIndex::getQualifiedName() const { + std::string N = getNamespace(); + if (!N.empty()) + N += "::"; + N += getName(); + return N; +} + +void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) { + std::vector<Record*> Comps = TheDef->getValueAsListOfDefs("ComposedOf"); + if (Comps.empty()) + return; + if (Comps.size() != 2) + throw TGError(TheDef->getLoc(), "ComposedOf must have exactly two entries"); + CodeGenSubRegIndex *A = RegBank.getSubRegIdx(Comps[0]); + CodeGenSubRegIndex *B = RegBank.getSubRegIdx(Comps[1]); + CodeGenSubRegIndex *X = A->addComposite(B, this); + if (X) + throw TGError(TheDef->getLoc(), "Ambiguous ComposedOf entries"); +} + +void CodeGenSubRegIndex::cleanComposites() { + // Clean out redundant mappings of the form this+X -> X. + for (CompMap::iterator i = Composed.begin(), e = Composed.end(); i != e;) { + CompMap::iterator j = i; + ++i; + if (j->first == j->second) + Composed.erase(j); + } +} + +//===----------------------------------------------------------------------===// +// CodeGenRegister +//===----------------------------------------------------------------------===// + +CodeGenRegister::CodeGenRegister(Record *R, unsigned Enum) + : TheDef(R), + EnumValue(Enum), + CostPerUse(R->getValueAsInt("CostPerUse")), + CoveredBySubRegs(R->getValueAsBit("CoveredBySubRegs")), + SubRegsComplete(false) +{} + +const std::string &CodeGenRegister::getName() const { + return TheDef->getName(); +} + +namespace { +// Iterate over all register units in a set of registers. +class RegUnitIterator { + CodeGenRegister::Set::const_iterator RegI, RegE; + CodeGenRegister::RegUnitList::const_iterator UnitI, UnitE; + +public: + RegUnitIterator(const CodeGenRegister::Set &Regs): + RegI(Regs.begin()), RegE(Regs.end()), UnitI(), UnitE() { + + if (RegI != RegE) { + UnitI = (*RegI)->getRegUnits().begin(); + UnitE = (*RegI)->getRegUnits().end(); + advance(); + } + } + + bool isValid() const { return UnitI != UnitE; } + + unsigned operator* () const { assert(isValid()); return *UnitI; }; + + const CodeGenRegister *getReg() const { assert(isValid()); return *RegI; } + + /// Preincrement. Move to the next unit. + void operator++() { + assert(isValid() && "Cannot advance beyond the last operand"); + ++UnitI; + advance(); + } + +protected: + void advance() { + while (UnitI == UnitE) { + if (++RegI == RegE) + break; + UnitI = (*RegI)->getRegUnits().begin(); + UnitE = (*RegI)->getRegUnits().end(); + } + } +}; +} // namespace + +// Merge two RegUnitLists maintaining the order and removing duplicates. +// Overwrites MergedRU in the process. +static void mergeRegUnits(CodeGenRegister::RegUnitList &MergedRU, + const CodeGenRegister::RegUnitList &RRU) { + CodeGenRegister::RegUnitList LRU = MergedRU; + MergedRU.clear(); + std::set_union(LRU.begin(), LRU.end(), RRU.begin(), RRU.end(), + std::back_inserter(MergedRU)); +} + +// Return true of this unit appears in RegUnits. +static bool hasRegUnit(CodeGenRegister::RegUnitList &RegUnits, unsigned Unit) { + return std::count(RegUnits.begin(), RegUnits.end(), Unit); +} + +// Inherit register units from subregisters. +// Return true if the RegUnits changed. +bool CodeGenRegister::inheritRegUnits(CodeGenRegBank &RegBank) { + unsigned OldNumUnits = RegUnits.size(); + for (SubRegMap::const_iterator I = SubRegs.begin(), E = SubRegs.end(); + I != E; ++I) { + // Strangely a register may have itself as a subreg (self-cycle) e.g. XMM. + // Only create a unit if no other subregs have units. + CodeGenRegister *SR = I->second; + if (SR == this) { + // RegUnits are only empty during getSubRegs, prior to computing weight. + if (RegUnits.empty()) + RegUnits.push_back(RegBank.newRegUnit(0)); + continue; + } + // Merge the subregister's units into this register's RegUnits. + mergeRegUnits(RegUnits, SR->RegUnits); + } + return OldNumUnits != RegUnits.size(); +} + +const CodeGenRegister::SubRegMap & +CodeGenRegister::getSubRegs(CodeGenRegBank &RegBank) { + // Only compute this map once. + if (SubRegsComplete) + return SubRegs; + SubRegsComplete = true; + + std::vector<Record*> SubList = TheDef->getValueAsListOfDefs("SubRegs"); + std::vector<Record*> IdxList = TheDef->getValueAsListOfDefs("SubRegIndices"); + if (SubList.size() != IdxList.size()) + throw TGError(TheDef->getLoc(), "Register " + getName() + + " SubRegIndices doesn't match SubRegs"); + + // First insert the direct subregs and make sure they are fully indexed. + SmallVector<CodeGenSubRegIndex*, 8> Indices; + for (unsigned i = 0, e = SubList.size(); i != e; ++i) { + CodeGenRegister *SR = RegBank.getReg(SubList[i]); + CodeGenSubRegIndex *Idx = RegBank.getSubRegIdx(IdxList[i]); + Indices.push_back(Idx); + if (!SubRegs.insert(std::make_pair(Idx, SR)).second) + throw TGError(TheDef->getLoc(), "SubRegIndex " + Idx->getName() + + " appears twice in Register " + getName()); + } + + // Keep track of inherited subregs and how they can be reached. + SmallPtrSet<CodeGenRegister*, 8> Orphans; + + // Clone inherited subregs and place duplicate entries in Orphans. + // Here the order is important - earlier subregs take precedence. + for (unsigned i = 0, e = SubList.size(); i != e; ++i) { + CodeGenRegister *SR = RegBank.getReg(SubList[i]); + const SubRegMap &Map = SR->getSubRegs(RegBank); + + // Add this as a super-register of SR now all sub-registers are in the list. + // This creates a topological ordering, the exact order depends on the + // order getSubRegs is called on all registers. + SR->SuperRegs.push_back(this); + + for (SubRegMap::const_iterator SI = Map.begin(), SE = Map.end(); SI != SE; + ++SI) { + if (!SubRegs.insert(*SI).second) + Orphans.insert(SI->second); + + // Noop sub-register indexes are possible, so avoid duplicates. + if (SI->second != SR) + SI->second->SuperRegs.push_back(this); + } + } + + // Expand any composed subreg indices. + // If dsub_2 has ComposedOf = [qsub_1, dsub_0], and this register has a + // qsub_1 subreg, add a dsub_2 subreg. Keep growing Indices and process + // expanded subreg indices recursively. + for (unsigned i = 0; i != Indices.size(); ++i) { + CodeGenSubRegIndex *Idx = Indices[i]; + const CodeGenSubRegIndex::CompMap &Comps = Idx->getComposites(); + CodeGenRegister *SR = SubRegs[Idx]; + const SubRegMap &Map = SR->getSubRegs(RegBank); + + // Look at the possible compositions of Idx. + // They may not all be supported by SR. + for (CodeGenSubRegIndex::CompMap::const_iterator I = Comps.begin(), + E = Comps.end(); I != E; ++I) { + SubRegMap::const_iterator SRI = Map.find(I->first); + if (SRI == Map.end()) + continue; // Idx + I->first doesn't exist in SR. + // Add I->second as a name for the subreg SRI->second, assuming it is + // orphaned, and the name isn't already used for something else. + if (SubRegs.count(I->second) || !Orphans.erase(SRI->second)) + continue; + // We found a new name for the orphaned sub-register. + SubRegs.insert(std::make_pair(I->second, SRI->second)); + Indices.push_back(I->second); + } + } + + // Process the composites. + ListInit *Comps = TheDef->getValueAsListInit("CompositeIndices"); + for (unsigned i = 0, e = Comps->size(); i != e; ++i) { + DagInit *Pat = dynamic_cast<DagInit*>(Comps->getElement(i)); + if (!Pat) + throw TGError(TheDef->getLoc(), "Invalid dag '" + + Comps->getElement(i)->getAsString() + + "' in CompositeIndices"); + DefInit *BaseIdxInit = dynamic_cast<DefInit*>(Pat->getOperator()); + if (!BaseIdxInit || !BaseIdxInit->getDef()->isSubClassOf("SubRegIndex")) + throw TGError(TheDef->getLoc(), "Invalid SubClassIndex in " + + Pat->getAsString()); + CodeGenSubRegIndex *BaseIdx = RegBank.getSubRegIdx(BaseIdxInit->getDef()); + + // Resolve list of subreg indices into R2. + CodeGenRegister *R2 = this; + for (DagInit::const_arg_iterator di = Pat->arg_begin(), + de = Pat->arg_end(); di != de; ++di) { + DefInit *IdxInit = dynamic_cast<DefInit*>(*di); + if (!IdxInit || !IdxInit->getDef()->isSubClassOf("SubRegIndex")) + throw TGError(TheDef->getLoc(), "Invalid SubClassIndex in " + + Pat->getAsString()); + CodeGenSubRegIndex *Idx = RegBank.getSubRegIdx(IdxInit->getDef()); + const SubRegMap &R2Subs = R2->getSubRegs(RegBank); + SubRegMap::const_iterator ni = R2Subs.find(Idx); + if (ni == R2Subs.end()) + throw TGError(TheDef->getLoc(), "Composite " + Pat->getAsString() + + " refers to bad index in " + R2->getName()); + R2 = ni->second; + } + + // Insert composite index. Allow overriding inherited indices etc. + SubRegs[BaseIdx] = R2; + + // R2 is no longer an orphan. + Orphans.erase(R2); + } + + // Now Orphans contains the inherited subregisters without a direct index. + // Create inferred indexes for all missing entries. + // Work backwards in the Indices vector in order to compose subregs bottom-up. + // Consider this subreg sequence: + // + // qsub_1 -> dsub_0 -> ssub_0 + // + // The qsub_1 -> dsub_0 composition becomes dsub_2, so the ssub_0 register + // can be reached in two different ways: + // + // qsub_1 -> ssub_0 + // dsub_2 -> ssub_0 + // + // We pick the latter composition because another register may have [dsub_0, + // dsub_1, dsub_2] subregs without neccessarily having a qsub_1 subreg. The + // dsub_2 -> ssub_0 composition can be shared. + while (!Indices.empty() && !Orphans.empty()) { + CodeGenSubRegIndex *Idx = Indices.pop_back_val(); + CodeGenRegister *SR = SubRegs[Idx]; + const SubRegMap &Map = SR->getSubRegs(RegBank); + for (SubRegMap::const_iterator SI = Map.begin(), SE = Map.end(); SI != SE; + ++SI) + if (Orphans.erase(SI->second)) + SubRegs[RegBank.getCompositeSubRegIndex(Idx, SI->first)] = SI->second; + } + + // Initialize RegUnitList. A register with no subregisters creates its own + // unit. Otherwise, it inherits all its subregister's units. Because + // getSubRegs is called recursively, this processes the register hierarchy in + // postorder. + // + // TODO: We currently assume all register units correspond to a named "leaf" + // register. We should also unify register units for ad-hoc register + // aliases. This can be done by iteratively merging units for aliasing + // registers using a worklist. + assert(RegUnits.empty() && "Should only initialize RegUnits once"); + if (SubRegs.empty()) + RegUnits.push_back(RegBank.newRegUnit(0)); + else + inheritRegUnits(RegBank); + return SubRegs; +} + +void +CodeGenRegister::addSubRegsPreOrder(SetVector<const CodeGenRegister*> &OSet, + CodeGenRegBank &RegBank) const { + assert(SubRegsComplete && "Must precompute sub-registers"); + std::vector<Record*> Indices = TheDef->getValueAsListOfDefs("SubRegIndices"); + for (unsigned i = 0, e = Indices.size(); i != e; ++i) { + CodeGenSubRegIndex *Idx = RegBank.getSubRegIdx(Indices[i]); + CodeGenRegister *SR = SubRegs.find(Idx)->second; + if (OSet.insert(SR)) + SR->addSubRegsPreOrder(OSet, RegBank); + } +} + +// Get the sum of this register's unit weights. +unsigned CodeGenRegister::getWeight(const CodeGenRegBank &RegBank) const { + unsigned Weight = 0; + for (RegUnitList::const_iterator I = RegUnits.begin(), E = RegUnits.end(); + I != E; ++I) { + Weight += RegBank.getRegUnitWeight(*I); + } + return Weight; +} + +//===----------------------------------------------------------------------===// +// RegisterTuples +//===----------------------------------------------------------------------===// + +// A RegisterTuples def is used to generate pseudo-registers from lists of +// sub-registers. We provide a SetTheory expander class that returns the new +// registers. +namespace { +struct TupleExpander : SetTheory::Expander { + void expand(SetTheory &ST, Record *Def, SetTheory::RecSet &Elts) { + std::vector<Record*> Indices = Def->getValueAsListOfDefs("SubRegIndices"); + unsigned Dim = Indices.size(); + ListInit *SubRegs = Def->getValueAsListInit("SubRegs"); + if (Dim != SubRegs->getSize()) + throw TGError(Def->getLoc(), "SubRegIndices and SubRegs size mismatch"); + if (Dim < 2) + throw TGError(Def->getLoc(), "Tuples must have at least 2 sub-registers"); + + // Evaluate the sub-register lists to be zipped. + unsigned Length = ~0u; + SmallVector<SetTheory::RecSet, 4> Lists(Dim); + for (unsigned i = 0; i != Dim; ++i) { + ST.evaluate(SubRegs->getElement(i), Lists[i]); + Length = std::min(Length, unsigned(Lists[i].size())); + } + + if (Length == 0) + return; + + // Precompute some types. + Record *RegisterCl = Def->getRecords().getClass("Register"); + RecTy *RegisterRecTy = RecordRecTy::get(RegisterCl); + StringInit *BlankName = StringInit::get(""); + + // Zip them up. + for (unsigned n = 0; n != Length; ++n) { + std::string Name; + Record *Proto = Lists[0][n]; + std::vector<Init*> Tuple; + unsigned CostPerUse = 0; + for (unsigned i = 0; i != Dim; ++i) { + Record *Reg = Lists[i][n]; + if (i) Name += '_'; + Name += Reg->getName(); + Tuple.push_back(DefInit::get(Reg)); + CostPerUse = std::max(CostPerUse, + unsigned(Reg->getValueAsInt("CostPerUse"))); + } + + // Create a new Record representing the synthesized register. This record + // is only for consumption by CodeGenRegister, it is not added to the + // RecordKeeper. + Record *NewReg = new Record(Name, Def->getLoc(), Def->getRecords()); + Elts.insert(NewReg); + + // Copy Proto super-classes. + for (unsigned i = 0, e = Proto->getSuperClasses().size(); i != e; ++i) + NewReg->addSuperClass(Proto->getSuperClasses()[i]); + + // Copy Proto fields. + for (unsigned i = 0, e = Proto->getValues().size(); i != e; ++i) { + RecordVal RV = Proto->getValues()[i]; + + // Skip existing fields, like NAME. + if (NewReg->getValue(RV.getNameInit())) + continue; + + StringRef Field = RV.getName(); + + // Replace the sub-register list with Tuple. + if (Field == "SubRegs") + RV.setValue(ListInit::get(Tuple, RegisterRecTy)); + + // Provide a blank AsmName. MC hacks are required anyway. + if (Field == "AsmName") + RV.setValue(BlankName); + + // CostPerUse is aggregated from all Tuple members. + if (Field == "CostPerUse") + RV.setValue(IntInit::get(CostPerUse)); + + // Composite registers are always covered by sub-registers. + if (Field == "CoveredBySubRegs") + RV.setValue(BitInit::get(true)); + + // Copy fields from the RegisterTuples def. + if (Field == "SubRegIndices" || + Field == "CompositeIndices") { + NewReg->addValue(*Def->getValue(Field)); + continue; + } + + // Some fields get their default uninitialized value. + if (Field == "DwarfNumbers" || + Field == "DwarfAlias" || + Field == "Aliases") { + if (const RecordVal *DefRV = RegisterCl->getValue(Field)) + NewReg->addValue(*DefRV); + continue; + } + + // Everything else is copied from Proto. + NewReg->addValue(RV); + } + } + } +}; +} + +//===----------------------------------------------------------------------===// +// CodeGenRegisterClass +//===----------------------------------------------------------------------===// + +CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) + : TheDef(R), Name(R->getName()), EnumValue(-1) { + // Rename anonymous register classes. + if (R->getName().size() > 9 && R->getName()[9] == '.') { + static unsigned AnonCounter = 0; + R->setName("AnonRegClass_"+utostr(AnonCounter++)); + } + + std::vector<Record*> TypeList = R->getValueAsListOfDefs("RegTypes"); + for (unsigned i = 0, e = TypeList.size(); i != e; ++i) { + Record *Type = TypeList[i]; + if (!Type->isSubClassOf("ValueType")) + throw "RegTypes list member '" + Type->getName() + + "' does not derive from the ValueType class!"; + VTs.push_back(getValueType(Type)); + } + assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!"); + + // Allocation order 0 is the full set. AltOrders provides others. + const SetTheory::RecVec *Elements = RegBank.getSets().expand(R); + ListInit *AltOrders = R->getValueAsListInit("AltOrders"); + Orders.resize(1 + AltOrders->size()); + + // Default allocation order always contains all registers. + for (unsigned i = 0, e = Elements->size(); i != e; ++i) { + Orders[0].push_back((*Elements)[i]); + Members.insert(RegBank.getReg((*Elements)[i])); + } + + // Alternative allocation orders may be subsets. + SetTheory::RecSet Order; + for (unsigned i = 0, e = AltOrders->size(); i != e; ++i) { + RegBank.getSets().evaluate(AltOrders->getElement(i), Order); + Orders[1 + i].append(Order.begin(), Order.end()); + // Verify that all altorder members are regclass members. + while (!Order.empty()) { + CodeGenRegister *Reg = RegBank.getReg(Order.back()); + Order.pop_back(); + if (!contains(Reg)) + throw TGError(R->getLoc(), " AltOrder register " + Reg->getName() + + " is not a class member"); + } + } + + // SubRegClasses is a list<dag> containing (RC, subregindex, ...) dags. + ListInit *SRC = R->getValueAsListInit("SubRegClasses"); + for (ListInit::const_iterator i = SRC->begin(), e = SRC->end(); i != e; ++i) { + DagInit *DAG = dynamic_cast<DagInit*>(*i); + if (!DAG) throw "SubRegClasses must contain DAGs"; + DefInit *DAGOp = dynamic_cast<DefInit*>(DAG->getOperator()); + Record *RCRec; + if (!DAGOp || !(RCRec = DAGOp->getDef())->isSubClassOf("RegisterClass")) + throw "Operator '" + DAG->getOperator()->getAsString() + + "' in SubRegClasses is not a RegisterClass"; + // Iterate over args, all SubRegIndex instances. + for (DagInit::const_arg_iterator ai = DAG->arg_begin(), ae = DAG->arg_end(); + ai != ae; ++ai) { + DefInit *Idx = dynamic_cast<DefInit*>(*ai); + Record *IdxRec; + if (!Idx || !(IdxRec = Idx->getDef())->isSubClassOf("SubRegIndex")) + throw "Argument '" + (*ai)->getAsString() + + "' in SubRegClasses is not a SubRegIndex"; + if (!SubRegClasses.insert(std::make_pair(IdxRec, RCRec)).second) + throw "SubRegIndex '" + IdxRec->getName() + "' mentioned twice"; + } + } + + // Allow targets to override the size in bits of the RegisterClass. + unsigned Size = R->getValueAsInt("Size"); + + Namespace = R->getValueAsString("Namespace"); + SpillSize = Size ? Size : EVT(VTs[0]).getSizeInBits(); + SpillAlignment = R->getValueAsInt("Alignment"); + CopyCost = R->getValueAsInt("CopyCost"); + Allocatable = R->getValueAsBit("isAllocatable"); + AltOrderSelect = R->getValueAsString("AltOrderSelect"); +} + +// Create an inferred register class that was missing from the .td files. +// Most properties will be inherited from the closest super-class after the +// class structure has been computed. +CodeGenRegisterClass::CodeGenRegisterClass(StringRef Name, Key Props) + : Members(*Props.Members), + TheDef(0), + Name(Name), + EnumValue(-1), + SpillSize(Props.SpillSize), + SpillAlignment(Props.SpillAlignment), + CopyCost(0), + Allocatable(true) { +} + +// Compute inherited propertied for a synthesized register class. +void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) { + assert(!getDef() && "Only synthesized classes can inherit properties"); + assert(!SuperClasses.empty() && "Synthesized class without super class"); + + // The last super-class is the smallest one. + CodeGenRegisterClass &Super = *SuperClasses.back(); + + // Most properties are copied directly. + // Exceptions are members, size, and alignment + Namespace = Super.Namespace; + VTs = Super.VTs; + CopyCost = Super.CopyCost; + Allocatable = Super.Allocatable; + AltOrderSelect = Super.AltOrderSelect; + + // Copy all allocation orders, filter out foreign registers from the larger + // super-class. + Orders.resize(Super.Orders.size()); + for (unsigned i = 0, ie = Super.Orders.size(); i != ie; ++i) + for (unsigned j = 0, je = Super.Orders[i].size(); j != je; ++j) + if (contains(RegBank.getReg(Super.Orders[i][j]))) + Orders[i].push_back(Super.Orders[i][j]); +} + +bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const { + return Members.count(Reg); +} + +namespace llvm { + raw_ostream &operator<<(raw_ostream &OS, const CodeGenRegisterClass::Key &K) { + OS << "{ S=" << K.SpillSize << ", A=" << K.SpillAlignment; + for (CodeGenRegister::Set::const_iterator I = K.Members->begin(), + E = K.Members->end(); I != E; ++I) + OS << ", " << (*I)->getName(); + return OS << " }"; + } +} + +// This is a simple lexicographical order that can be used to search for sets. +// It is not the same as the topological order provided by TopoOrderRC. +bool CodeGenRegisterClass::Key:: +operator<(const CodeGenRegisterClass::Key &B) const { + assert(Members && B.Members); + if (*Members != *B.Members) + return *Members < *B.Members; + if (SpillSize != B.SpillSize) + return SpillSize < B.SpillSize; + return SpillAlignment < B.SpillAlignment; +} + +// Returns true if RC is a strict subclass. +// RC is a sub-class of this class if it is a valid replacement for any +// instruction operand where a register of this classis required. It must +// satisfy these conditions: +// +// 1. All RC registers are also in this. +// 2. The RC spill size must not be smaller than our spill size. +// 3. RC spill alignment must be compatible with ours. +// +static bool testSubClass(const CodeGenRegisterClass *A, + const CodeGenRegisterClass *B) { + return A->SpillAlignment && B->SpillAlignment % A->SpillAlignment == 0 && + A->SpillSize <= B->SpillSize && + std::includes(A->getMembers().begin(), A->getMembers().end(), + B->getMembers().begin(), B->getMembers().end(), + CodeGenRegister::Less()); +} + +/// Sorting predicate for register classes. This provides a topological +/// ordering that arranges all register classes before their sub-classes. +/// +/// Register classes with the same registers, spill size, and alignment form a +/// clique. They will be ordered alphabetically. +/// +static int TopoOrderRC(const void *PA, const void *PB) { + const CodeGenRegisterClass *A = *(const CodeGenRegisterClass* const*)PA; + const CodeGenRegisterClass *B = *(const CodeGenRegisterClass* const*)PB; + if (A == B) + return 0; + + // Order by descending set size. Note that the classes' allocation order may + // not have been computed yet. The Members set is always vaild. + if (A->getMembers().size() > B->getMembers().size()) + return -1; + if (A->getMembers().size() < B->getMembers().size()) + return 1; + + // Order by ascending spill size. + if (A->SpillSize < B->SpillSize) + return -1; + if (A->SpillSize > B->SpillSize) + return 1; + + // Order by ascending spill alignment. + if (A->SpillAlignment < B->SpillAlignment) + return -1; + if (A->SpillAlignment > B->SpillAlignment) + return 1; + + // Finally order by name as a tie breaker. + return StringRef(A->getName()).compare(B->getName()); +} + +std::string CodeGenRegisterClass::getQualifiedName() const { + if (Namespace.empty()) + return getName(); + else + return Namespace + "::" + getName(); +} + +// Compute sub-classes of all register classes. +// Assume the classes are ordered topologically. +void CodeGenRegisterClass::computeSubClasses(CodeGenRegBank &RegBank) { + ArrayRef<CodeGenRegisterClass*> RegClasses = RegBank.getRegClasses(); + + // Visit backwards so sub-classes are seen first. + for (unsigned rci = RegClasses.size(); rci; --rci) { + CodeGenRegisterClass &RC = *RegClasses[rci - 1]; + RC.SubClasses.resize(RegClasses.size()); + RC.SubClasses.set(RC.EnumValue); + + // Normally, all subclasses have IDs >= rci, unless RC is part of a clique. + for (unsigned s = rci; s != RegClasses.size(); ++s) { + if (RC.SubClasses.test(s)) + continue; + CodeGenRegisterClass *SubRC = RegClasses[s]; + if (!testSubClass(&RC, SubRC)) + continue; + // SubRC is a sub-class. Grap all its sub-classes so we won't have to + // check them again. + RC.SubClasses |= SubRC->SubClasses; + } + + // Sweep up missed clique members. They will be immediately preceeding RC. + for (unsigned s = rci - 1; s && testSubClass(&RC, RegClasses[s - 1]); --s) + RC.SubClasses.set(s - 1); + } + + // Compute the SuperClasses lists from the SubClasses vectors. + for (unsigned rci = 0; rci != RegClasses.size(); ++rci) { + const BitVector &SC = RegClasses[rci]->getSubClasses(); + for (int s = SC.find_first(); s >= 0; s = SC.find_next(s)) { + if (unsigned(s) == rci) + continue; + RegClasses[s]->SuperClasses.push_back(RegClasses[rci]); + } + } + + // With the class hierarchy in place, let synthesized register classes inherit + // properties from their closest super-class. The iteration order here can + // propagate properties down multiple levels. + for (unsigned rci = 0; rci != RegClasses.size(); ++rci) + if (!RegClasses[rci]->getDef()) + RegClasses[rci]->inheritProperties(RegBank); +} + +void +CodeGenRegisterClass::getSuperRegClasses(CodeGenSubRegIndex *SubIdx, + BitVector &Out) const { + DenseMap<CodeGenSubRegIndex*, + SmallPtrSet<CodeGenRegisterClass*, 8> >::const_iterator + FindI = SuperRegClasses.find(SubIdx); + if (FindI == SuperRegClasses.end()) + return; + for (SmallPtrSet<CodeGenRegisterClass*, 8>::const_iterator I = + FindI->second.begin(), E = FindI->second.end(); I != E; ++I) + Out.set((*I)->EnumValue); +} + +// Populate a unique sorted list of units from a register set. +void CodeGenRegisterClass::buildRegUnitSet( + std::vector<unsigned> &RegUnits) const { + std::vector<unsigned> TmpUnits; + for (RegUnitIterator UnitI(Members); UnitI.isValid(); ++UnitI) + TmpUnits.push_back(*UnitI); + std::sort(TmpUnits.begin(), TmpUnits.end()); + std::unique_copy(TmpUnits.begin(), TmpUnits.end(), + std::back_inserter(RegUnits)); +} + +//===----------------------------------------------------------------------===// +// CodeGenRegBank +//===----------------------------------------------------------------------===// + +CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) : Records(Records) { + // Configure register Sets to understand register classes and tuples. + Sets.addFieldExpander("RegisterClass", "MemberList"); + Sets.addFieldExpander("CalleeSavedRegs", "SaveList"); + Sets.addExpander("RegisterTuples", new TupleExpander()); + + // Read in the user-defined (named) sub-register indices. + // More indices will be synthesized later. + std::vector<Record*> SRIs = Records.getAllDerivedDefinitions("SubRegIndex"); + std::sort(SRIs.begin(), SRIs.end(), LessRecord()); + NumNamedIndices = SRIs.size(); + for (unsigned i = 0, e = SRIs.size(); i != e; ++i) + getSubRegIdx(SRIs[i]); + // Build composite maps from ComposedOf fields. + for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) + SubRegIndices[i]->updateComponents(*this); + + // Read in the register definitions. + std::vector<Record*> Regs = Records.getAllDerivedDefinitions("Register"); + std::sort(Regs.begin(), Regs.end(), LessRecord()); + Registers.reserve(Regs.size()); + // Assign the enumeration values. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) + getReg(Regs[i]); + + // Expand tuples and number the new registers. + std::vector<Record*> Tups = + Records.getAllDerivedDefinitions("RegisterTuples"); + for (unsigned i = 0, e = Tups.size(); i != e; ++i) { + const std::vector<Record*> *TupRegs = Sets.expand(Tups[i]); + for (unsigned j = 0, je = TupRegs->size(); j != je; ++j) + getReg((*TupRegs)[j]); + } + + // Precompute all sub-register maps now all the registers are known. + // This will create Composite entries for all inferred sub-register indices. + NumRegUnits = 0; + for (unsigned i = 0, e = Registers.size(); i != e; ++i) + Registers[i]->getSubRegs(*this); + + // Native register units are associated with a leaf register. They've all been + // discovered now. + NumNativeRegUnits = NumRegUnits; + + // Read in register class definitions. + std::vector<Record*> RCs = Records.getAllDerivedDefinitions("RegisterClass"); + if (RCs.empty()) + throw std::string("No 'RegisterClass' subclasses defined!"); + + // Allocate user-defined register classes. + RegClasses.reserve(RCs.size()); + for (unsigned i = 0, e = RCs.size(); i != e; ++i) + addToMaps(new CodeGenRegisterClass(*this, RCs[i])); + + // Infer missing classes to create a full algebra. + computeInferredRegisterClasses(); + + // Order register classes topologically and assign enum values. + array_pod_sort(RegClasses.begin(), RegClasses.end(), TopoOrderRC); + for (unsigned i = 0, e = RegClasses.size(); i != e; ++i) + RegClasses[i]->EnumValue = i; + CodeGenRegisterClass::computeSubClasses(*this); +} + +CodeGenSubRegIndex *CodeGenRegBank::getSubRegIdx(Record *Def) { + CodeGenSubRegIndex *&Idx = Def2SubRegIdx[Def]; + if (Idx) + return Idx; + Idx = new CodeGenSubRegIndex(Def, SubRegIndices.size() + 1); + SubRegIndices.push_back(Idx); + return Idx; +} + +CodeGenRegister *CodeGenRegBank::getReg(Record *Def) { + CodeGenRegister *&Reg = Def2Reg[Def]; + if (Reg) + return Reg; + Reg = new CodeGenRegister(Def, Registers.size() + 1); + Registers.push_back(Reg); + return Reg; +} + +void CodeGenRegBank::addToMaps(CodeGenRegisterClass *RC) { + RegClasses.push_back(RC); + + if (Record *Def = RC->getDef()) + Def2RC.insert(std::make_pair(Def, RC)); + + // Duplicate classes are rejected by insert(). + // That's OK, we only care about the properties handled by CGRC::Key. + CodeGenRegisterClass::Key K(*RC); + Key2RC.insert(std::make_pair(K, RC)); +} + +// Create a synthetic sub-class if it is missing. +CodeGenRegisterClass* +CodeGenRegBank::getOrCreateSubClass(const CodeGenRegisterClass *RC, + const CodeGenRegister::Set *Members, + StringRef Name) { + // Synthetic sub-class has the same size and alignment as RC. + CodeGenRegisterClass::Key K(Members, RC->SpillSize, RC->SpillAlignment); + RCKeyMap::const_iterator FoundI = Key2RC.find(K); + if (FoundI != Key2RC.end()) + return FoundI->second; + + // Sub-class doesn't exist, create a new one. + CodeGenRegisterClass *NewRC = new CodeGenRegisterClass(Name, K); + addToMaps(NewRC); + return NewRC; +} + +CodeGenRegisterClass *CodeGenRegBank::getRegClass(Record *Def) { + if (CodeGenRegisterClass *RC = Def2RC[Def]) + return RC; + + throw TGError(Def->getLoc(), "Not a known RegisterClass!"); +} + +CodeGenSubRegIndex* +CodeGenRegBank::getCompositeSubRegIndex(CodeGenSubRegIndex *A, + CodeGenSubRegIndex *B) { + // Look for an existing entry. + CodeGenSubRegIndex *Comp = A->compose(B); + if (Comp) + return Comp; + + // None exists, synthesize one. + std::string Name = A->getName() + "_then_" + B->getName(); + Comp = getSubRegIdx(new Record(Name, SMLoc(), Records)); + A->addComposite(B, Comp); + return Comp; +} + +void CodeGenRegBank::computeComposites() { + for (unsigned i = 0, e = Registers.size(); i != e; ++i) { + CodeGenRegister *Reg1 = Registers[i]; + const CodeGenRegister::SubRegMap &SRM1 = Reg1->getSubRegs(); + for (CodeGenRegister::SubRegMap::const_iterator i1 = SRM1.begin(), + e1 = SRM1.end(); i1 != e1; ++i1) { + CodeGenSubRegIndex *Idx1 = i1->first; + CodeGenRegister *Reg2 = i1->second; + // Ignore identity compositions. + if (Reg1 == Reg2) + continue; + const CodeGenRegister::SubRegMap &SRM2 = Reg2->getSubRegs(); + // Try composing Idx1 with another SubRegIndex. + for (CodeGenRegister::SubRegMap::const_iterator i2 = SRM2.begin(), + e2 = SRM2.end(); i2 != e2; ++i2) { + CodeGenSubRegIndex *Idx2 = i2->first; + CodeGenRegister *Reg3 = i2->second; + // Ignore identity compositions. + if (Reg2 == Reg3) + continue; + // OK Reg1:IdxPair == Reg3. Find the index with Reg:Idx == Reg3. + for (CodeGenRegister::SubRegMap::const_iterator i1d = SRM1.begin(), + e1d = SRM1.end(); i1d != e1d; ++i1d) { + if (i1d->second == Reg3) { + // Conflicting composition? Emit a warning but allow it. + if (CodeGenSubRegIndex *Prev = Idx1->addComposite(Idx2, i1d->first)) + PrintWarning(Twine("SubRegIndex") + Idx1->getQualifiedName() + + " and " + Idx2->getQualifiedName() + + " compose ambiguously as " + Prev->getQualifiedName() + + " or " + i1d->first->getQualifiedName()); + } + } + } + } + } + + // We don't care about the difference between (Idx1, Idx2) -> Idx2 and invalid + // compositions, so remove any mappings of that form. + for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) + SubRegIndices[i]->cleanComposites(); +} + +namespace { +// UberRegSet is a helper class for computeRegUnitWeights. Each UberRegSet is +// the transitive closure of the union of overlapping register +// classes. Together, the UberRegSets form a partition of the registers. If we +// consider overlapping register classes to be connected, then each UberRegSet +// is a set of connected components. +// +// An UberRegSet will likely be a horizontal slice of register names of +// the same width. Nontrivial subregisters should then be in a separate +// UberRegSet. But this property isn't required for valid computation of +// register unit weights. +// +// A Weight field caches the max per-register unit weight in each UberRegSet. +// +// A set of SingularDeterminants flags single units of some register in this set +// for which the unit weight equals the set weight. These units should not have +// their weight increased. +struct UberRegSet { + CodeGenRegister::Set Regs; + unsigned Weight; + CodeGenRegister::RegUnitList SingularDeterminants; + + UberRegSet(): Weight(0) {} +}; +} // namespace + +// Partition registers into UberRegSets, where each set is the transitive +// closure of the union of overlapping register classes. +// +// UberRegSets[0] is a special non-allocatable set. +static void computeUberSets(std::vector<UberRegSet> &UberSets, + std::vector<UberRegSet*> &RegSets, + CodeGenRegBank &RegBank) { + + const std::vector<CodeGenRegister*> &Registers = RegBank.getRegisters(); + + // The Register EnumValue is one greater than its index into Registers. + assert(Registers.size() == Registers[Registers.size()-1]->EnumValue && + "register enum value mismatch"); + + // For simplicitly make the SetID the same as EnumValue. + IntEqClasses UberSetIDs(Registers.size()+1); + std::set<unsigned> AllocatableRegs; + for (unsigned i = 0, e = RegBank.getRegClasses().size(); i != e; ++i) { + + CodeGenRegisterClass *RegClass = RegBank.getRegClasses()[i]; + if (!RegClass->Allocatable) + continue; + + const CodeGenRegister::Set &Regs = RegClass->getMembers(); + if (Regs.empty()) + continue; + + unsigned USetID = UberSetIDs.findLeader((*Regs.begin())->EnumValue); + assert(USetID && "register number 0 is invalid"); + + AllocatableRegs.insert((*Regs.begin())->EnumValue); + for (CodeGenRegister::Set::const_iterator I = llvm::next(Regs.begin()), + E = Regs.end(); I != E; ++I) { + AllocatableRegs.insert((*I)->EnumValue); + UberSetIDs.join(USetID, (*I)->EnumValue); + } + } + // Combine non-allocatable regs. + for (unsigned i = 0, e = Registers.size(); i != e; ++i) { + unsigned RegNum = Registers[i]->EnumValue; + if (AllocatableRegs.count(RegNum)) + continue; + + UberSetIDs.join(0, RegNum); + } + UberSetIDs.compress(); + + // Make the first UberSet a special unallocatable set. + unsigned ZeroID = UberSetIDs[0]; + + // Insert Registers into the UberSets formed by union-find. + // Do not resize after this. + UberSets.resize(UberSetIDs.getNumClasses()); + for (unsigned i = 0, e = Registers.size(); i != e; ++i) { + const CodeGenRegister *Reg = Registers[i]; + unsigned USetID = UberSetIDs[Reg->EnumValue]; + if (!USetID) + USetID = ZeroID; + else if (USetID == ZeroID) + USetID = 0; + + UberRegSet *USet = &UberSets[USetID]; + USet->Regs.insert(Reg); + RegSets[i] = USet; + } +} + +// Recompute each UberSet weight after changing unit weights. +static void computeUberWeights(std::vector<UberRegSet> &UberSets, + CodeGenRegBank &RegBank) { + // Skip the first unallocatable set. + for (std::vector<UberRegSet>::iterator I = llvm::next(UberSets.begin()), + E = UberSets.end(); I != E; ++I) { + + // Initialize all unit weights in this set, and remember the max units/reg. + const CodeGenRegister *Reg = 0; + unsigned MaxWeight = 0, Weight = 0; + for (RegUnitIterator UnitI(I->Regs); UnitI.isValid(); ++UnitI) { + if (Reg != UnitI.getReg()) { + if (Weight > MaxWeight) + MaxWeight = Weight; + Reg = UnitI.getReg(); + Weight = 0; + } + unsigned UWeight = RegBank.getRegUnitWeight(*UnitI); + if (!UWeight) { + UWeight = 1; + RegBank.increaseRegUnitWeight(*UnitI, UWeight); + } + Weight += UWeight; + } + if (Weight > MaxWeight) + MaxWeight = Weight; + + // Update the set weight. + I->Weight = MaxWeight; + + // Find singular determinants. + for (CodeGenRegister::Set::iterator RegI = I->Regs.begin(), + RegE = I->Regs.end(); RegI != RegE; ++RegI) { + if ((*RegI)->getRegUnits().size() == 1 + && (*RegI)->getWeight(RegBank) == I->Weight) + mergeRegUnits(I->SingularDeterminants, (*RegI)->getRegUnits()); + } + } +} + +// normalizeWeight is a computeRegUnitWeights helper that adjusts the weight of +// a register and its subregisters so that they have the same weight as their +// UberSet. Self-recursion processes the subregister tree in postorder so +// subregisters are normalized first. +// +// Side effects: +// - creates new adopted register units +// - causes superregisters to inherit adopted units +// - increases the weight of "singular" units +// - induces recomputation of UberWeights. +static bool normalizeWeight(CodeGenRegister *Reg, + std::vector<UberRegSet> &UberSets, + std::vector<UberRegSet*> &RegSets, + CodeGenRegister::RegUnitList &NormalUnits, + CodeGenRegBank &RegBank) { + bool Changed = false; + const CodeGenRegister::SubRegMap &SRM = Reg->getSubRegs(); + for (CodeGenRegister::SubRegMap::const_iterator SRI = SRM.begin(), + SRE = SRM.end(); SRI != SRE; ++SRI) { + if (SRI->second == Reg) + continue; // self-cycles happen + + Changed |= + normalizeWeight(SRI->second, UberSets, RegSets, NormalUnits, RegBank); + } + // Postorder register normalization. + + // Inherit register units newly adopted by subregisters. + if (Reg->inheritRegUnits(RegBank)) + computeUberWeights(UberSets, RegBank); + + // Check if this register is too skinny for its UberRegSet. + UberRegSet *UberSet = RegSets[RegBank.getRegIndex(Reg)]; + + unsigned RegWeight = Reg->getWeight(RegBank); + if (UberSet->Weight > RegWeight) { + // A register unit's weight can be adjusted only if it is the singular unit + // for this register, has not been used to normalize a subregister's set, + // and has not already been used to singularly determine this UberRegSet. + unsigned AdjustUnit = Reg->getRegUnits().front(); + if (Reg->getRegUnits().size() != 1 + || hasRegUnit(NormalUnits, AdjustUnit) + || hasRegUnit(UberSet->SingularDeterminants, AdjustUnit)) { + // We don't have an adjustable unit, so adopt a new one. + AdjustUnit = RegBank.newRegUnit(UberSet->Weight - RegWeight); + Reg->adoptRegUnit(AdjustUnit); + // Adopting a unit does not immediately require recomputing set weights. + } + else { + // Adjust the existing single unit. + RegBank.increaseRegUnitWeight(AdjustUnit, UberSet->Weight - RegWeight); + // The unit may be shared among sets and registers within this set. + computeUberWeights(UberSets, RegBank); + } + Changed = true; + } + + // Mark these units normalized so superregisters can't change their weights. + mergeRegUnits(NormalUnits, Reg->getRegUnits()); + + return Changed; +} + +// Compute a weight for each register unit created during getSubRegs. +// +// The goal is that two registers in the same class will have the same weight, +// where each register's weight is defined as sum of its units' weights. +void CodeGenRegBank::computeRegUnitWeights() { + assert(RegUnitWeights.empty() && "Only initialize RegUnitWeights once"); + + // Only allocatable units will be initialized to nonzero weight. + RegUnitWeights.resize(NumRegUnits); + + std::vector<UberRegSet> UberSets; + std::vector<UberRegSet*> RegSets(Registers.size()); + computeUberSets(UberSets, RegSets, *this); + // UberSets and RegSets are now immutable. + + computeUberWeights(UberSets, *this); + + // Iterate over each Register, normalizing the unit weights until reaching + // a fix point. + unsigned NumIters = 0; + for (bool Changed = true; Changed; ++NumIters) { + assert(NumIters <= NumNativeRegUnits && "Runaway register unit weights"); + Changed = false; + for (unsigned i = 0, e = Registers.size(); i != e; ++i) { + CodeGenRegister::RegUnitList NormalUnits; + Changed |= + normalizeWeight(Registers[i], UberSets, RegSets, NormalUnits, *this); + } + } +} + +// Find a set in UniqueSets with the same elements as Set. +// Return an iterator into UniqueSets. +static std::vector<RegUnitSet>::const_iterator +findRegUnitSet(const std::vector<RegUnitSet> &UniqueSets, + const RegUnitSet &Set) { + std::vector<RegUnitSet>::const_iterator + I = UniqueSets.begin(), E = UniqueSets.end(); + for(;I != E; ++I) { + if (I->Units == Set.Units) + break; + } + return I; +} + +// Return true if the RUSubSet is a subset of RUSuperSet. +static bool isRegUnitSubSet(const std::vector<unsigned> &RUSubSet, + const std::vector<unsigned> &RUSuperSet) { + return std::includes(RUSuperSet.begin(), RUSuperSet.end(), + RUSubSet.begin(), RUSubSet.end()); +} + +// Iteratively prune unit sets. +void CodeGenRegBank::pruneUnitSets() { + assert(RegClassUnitSets.empty() && "this invalidates RegClassUnitSets"); + + // Form an equivalence class of UnitSets with no significant difference. + std::vector<unsigned> SuperSetIDs; + for (unsigned SubIdx = 0, EndIdx = RegUnitSets.size(); + SubIdx != EndIdx; ++SubIdx) { + const RegUnitSet &SubSet = RegUnitSets[SubIdx]; + unsigned SuperIdx = 0; + for (; SuperIdx != EndIdx; ++SuperIdx) { + if (SuperIdx == SubIdx) + continue; + + const RegUnitSet &SuperSet = RegUnitSets[SuperIdx]; + if (isRegUnitSubSet(SubSet.Units, SuperSet.Units) + && (SubSet.Units.size() + 3 > SuperSet.Units.size())) { + break; + } + } + if (SuperIdx == EndIdx) + SuperSetIDs.push_back(SubIdx); + } + // Populate PrunedUnitSets with each equivalence class's superset. + std::vector<RegUnitSet> PrunedUnitSets(SuperSetIDs.size()); + for (unsigned i = 0, e = SuperSetIDs.size(); i != e; ++i) { + unsigned SuperIdx = SuperSetIDs[i]; + PrunedUnitSets[i].Name = RegUnitSets[SuperIdx].Name; + PrunedUnitSets[i].Units.swap(RegUnitSets[SuperIdx].Units); + } + RegUnitSets.swap(PrunedUnitSets); +} + +// Create a RegUnitSet for each RegClass that contains all units in the class +// including adopted units that are necessary to model register pressure. Then +// iteratively compute RegUnitSets such that the union of any two overlapping +// RegUnitSets is repreresented. +// +// RegisterInfoEmitter will map each RegClass to its RegUnitClass and any +// RegUnitSet that is a superset of that RegUnitClass. +void CodeGenRegBank::computeRegUnitSets() { + + // Compute a unique RegUnitSet for each RegClass. + const ArrayRef<CodeGenRegisterClass*> &RegClasses = getRegClasses(); + unsigned NumRegClasses = RegClasses.size(); + for (unsigned RCIdx = 0, RCEnd = NumRegClasses; RCIdx != RCEnd; ++RCIdx) { + if (!RegClasses[RCIdx]->Allocatable) + continue; + + // Speculatively grow the RegUnitSets to hold the new set. + RegUnitSets.resize(RegUnitSets.size() + 1); + RegUnitSets.back().Name = RegClasses[RCIdx]->getName(); + + // Compute a sorted list of units in this class. + RegClasses[RCIdx]->buildRegUnitSet(RegUnitSets.back().Units); + + // Find an existing RegUnitSet. + std::vector<RegUnitSet>::const_iterator SetI = + findRegUnitSet(RegUnitSets, RegUnitSets.back()); + if (SetI != llvm::prior(RegUnitSets.end())) + RegUnitSets.pop_back(); + } + + // Iteratively prune unit sets. + pruneUnitSets(); + + // Iterate over all unit sets, including new ones added by this loop. + unsigned NumRegUnitSubSets = RegUnitSets.size(); + for (unsigned Idx = 0, EndIdx = RegUnitSets.size(); Idx != EndIdx; ++Idx) { + // In theory, this is combinatorial. In practice, it needs to be bounded + // by a small number of sets for regpressure to be efficient. + // If the assert is hit, we need to implement pruning. + assert(Idx < (2*NumRegUnitSubSets) && "runaway unit set inference"); + + // Compare new sets with all original classes. + for (unsigned SearchIdx = (Idx >= NumRegUnitSubSets) ? 0 : Idx+1; + SearchIdx != EndIdx; ++SearchIdx) { + std::set<unsigned> Intersection; + std::set_intersection(RegUnitSets[Idx].Units.begin(), + RegUnitSets[Idx].Units.end(), + RegUnitSets[SearchIdx].Units.begin(), + RegUnitSets[SearchIdx].Units.end(), + std::inserter(Intersection, Intersection.begin())); + if (Intersection.empty()) + continue; + + // Speculatively grow the RegUnitSets to hold the new set. + RegUnitSets.resize(RegUnitSets.size() + 1); + RegUnitSets.back().Name = + RegUnitSets[Idx].Name + "+" + RegUnitSets[SearchIdx].Name; + + std::set_union(RegUnitSets[Idx].Units.begin(), + RegUnitSets[Idx].Units.end(), + RegUnitSets[SearchIdx].Units.begin(), + RegUnitSets[SearchIdx].Units.end(), + std::inserter(RegUnitSets.back().Units, + RegUnitSets.back().Units.begin())); + + // Find an existing RegUnitSet, or add the union to the unique sets. + std::vector<RegUnitSet>::const_iterator SetI = + findRegUnitSet(RegUnitSets, RegUnitSets.back()); + if (SetI != llvm::prior(RegUnitSets.end())) + RegUnitSets.pop_back(); + } + } + + // Iteratively prune unit sets after inferring supersets. + pruneUnitSets(); + + // For each register class, list the UnitSets that are supersets. + RegClassUnitSets.resize(NumRegClasses); + for (unsigned RCIdx = 0, RCEnd = NumRegClasses; RCIdx != RCEnd; ++RCIdx) { + if (!RegClasses[RCIdx]->Allocatable) + continue; + + // Recompute the sorted list of units in this class. + std::vector<unsigned> RegUnits; + RegClasses[RCIdx]->buildRegUnitSet(RegUnits); + + // Don't increase pressure for unallocatable regclasses. + if (RegUnits.empty()) + continue; + + // Find all supersets. + for (unsigned USIdx = 0, USEnd = RegUnitSets.size(); + USIdx != USEnd; ++USIdx) { + if (isRegUnitSubSet(RegUnits, RegUnitSets[USIdx].Units)) + RegClassUnitSets[RCIdx].push_back(USIdx); + } + assert(!RegClassUnitSets[RCIdx].empty() && "missing unit set for regclass"); + } +} + +// Compute sets of overlapping registers. +// +// The standard set is all super-registers and all sub-registers, but the +// target description can add arbitrary overlapping registers via the 'Aliases' +// field. This complicates things, but we can compute overlapping sets using +// the following rules: +// +// 1. The relation overlap(A, B) is reflexive and symmetric but not transitive. +// +// 2. overlap(A, B) implies overlap(A, S) for all S in supers(B). +// +// Alternatively: +// +// overlap(A, B) iff there exists: +// A' in { A, subregs(A) } and B' in { B, subregs(B) } such that: +// A' = B' or A' in aliases(B') or B' in aliases(A'). +// +// Here subregs(A) is the full flattened sub-register set returned by +// A.getSubRegs() while aliases(A) is simply the special 'Aliases' field in the +// description of register A. +// +// This also implies that registers with a common sub-register are considered +// overlapping. This can happen when forming register pairs: +// +// P0 = (R0, R1) +// P1 = (R1, R2) +// P2 = (R2, R3) +// +// In this case, we will infer an overlap between P0 and P1 because of the +// shared sub-register R1. There is no overlap between P0 and P2. +// +void CodeGenRegBank:: +computeOverlaps(std::map<const CodeGenRegister*, CodeGenRegister::Set> &Map) { + assert(Map.empty()); + + // Collect overlaps that don't follow from rule 2. + for (unsigned i = 0, e = Registers.size(); i != e; ++i) { + CodeGenRegister *Reg = Registers[i]; + CodeGenRegister::Set &Overlaps = Map[Reg]; + + // Reg overlaps itself. + Overlaps.insert(Reg); + + // All super-registers overlap. + const CodeGenRegister::SuperRegList &Supers = Reg->getSuperRegs(); + Overlaps.insert(Supers.begin(), Supers.end()); + + // Form symmetrical relations from the special Aliases[] lists. + std::vector<Record*> RegList = Reg->TheDef->getValueAsListOfDefs("Aliases"); + for (unsigned i2 = 0, e2 = RegList.size(); i2 != e2; ++i2) { + CodeGenRegister *Reg2 = getReg(RegList[i2]); + CodeGenRegister::Set &Overlaps2 = Map[Reg2]; + const CodeGenRegister::SuperRegList &Supers2 = Reg2->getSuperRegs(); + // Reg overlaps Reg2 which implies it overlaps supers(Reg2). + Overlaps.insert(Reg2); + Overlaps.insert(Supers2.begin(), Supers2.end()); + Overlaps2.insert(Reg); + Overlaps2.insert(Supers.begin(), Supers.end()); + } + } + + // Apply rule 2. and inherit all sub-register overlaps. + for (unsigned i = 0, e = Registers.size(); i != e; ++i) { + CodeGenRegister *Reg = Registers[i]; + CodeGenRegister::Set &Overlaps = Map[Reg]; + const CodeGenRegister::SubRegMap &SRM = Reg->getSubRegs(); + for (CodeGenRegister::SubRegMap::const_iterator i2 = SRM.begin(), + e2 = SRM.end(); i2 != e2; ++i2) { + CodeGenRegister::Set &Overlaps2 = Map[i2->second]; + Overlaps.insert(Overlaps2.begin(), Overlaps2.end()); + } + } +} + +void CodeGenRegBank::computeDerivedInfo() { + computeComposites(); + + // Compute a weight for each register unit created during getSubRegs. + // This may create adopted register units (with unit # >= NumNativeRegUnits). + computeRegUnitWeights(); + + // Compute a unique set of RegUnitSets. One for each RegClass and inferred + // supersets for the union of overlapping sets. + computeRegUnitSets(); +} + +// +// Synthesize missing register class intersections. +// +// Make sure that sub-classes of RC exists such that getCommonSubClass(RC, X) +// returns a maximal register class for all X. +// +void CodeGenRegBank::inferCommonSubClass(CodeGenRegisterClass *RC) { + for (unsigned rci = 0, rce = RegClasses.size(); rci != rce; ++rci) { + CodeGenRegisterClass *RC1 = RC; + CodeGenRegisterClass *RC2 = RegClasses[rci]; + if (RC1 == RC2) + continue; + + // Compute the set intersection of RC1 and RC2. + const CodeGenRegister::Set &Memb1 = RC1->getMembers(); + const CodeGenRegister::Set &Memb2 = RC2->getMembers(); + CodeGenRegister::Set Intersection; + std::set_intersection(Memb1.begin(), Memb1.end(), + Memb2.begin(), Memb2.end(), + std::inserter(Intersection, Intersection.begin()), + CodeGenRegister::Less()); + + // Skip disjoint class pairs. + if (Intersection.empty()) + continue; + + // If RC1 and RC2 have different spill sizes or alignments, use the + // larger size for sub-classing. If they are equal, prefer RC1. + if (RC2->SpillSize > RC1->SpillSize || + (RC2->SpillSize == RC1->SpillSize && + RC2->SpillAlignment > RC1->SpillAlignment)) + std::swap(RC1, RC2); + + getOrCreateSubClass(RC1, &Intersection, + RC1->getName() + "_and_" + RC2->getName()); + } +} + +// +// Synthesize missing sub-classes for getSubClassWithSubReg(). +// +// Make sure that the set of registers in RC with a given SubIdx sub-register +// form a register class. Update RC->SubClassWithSubReg. +// +void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) { + // Map SubRegIndex to set of registers in RC supporting that SubRegIndex. + typedef std::map<CodeGenSubRegIndex*, CodeGenRegister::Set, + CodeGenSubRegIndex::Less> SubReg2SetMap; + + // Compute the set of registers supporting each SubRegIndex. + SubReg2SetMap SRSets; + for (CodeGenRegister::Set::const_iterator RI = RC->getMembers().begin(), + RE = RC->getMembers().end(); RI != RE; ++RI) { + const CodeGenRegister::SubRegMap &SRM = (*RI)->getSubRegs(); + for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(), + E = SRM.end(); I != E; ++I) + SRSets[I->first].insert(*RI); + } + + // Find matching classes for all SRSets entries. Iterate in SubRegIndex + // numerical order to visit synthetic indices last. + for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { + CodeGenSubRegIndex *SubIdx = SubRegIndices[sri]; + SubReg2SetMap::const_iterator I = SRSets.find(SubIdx); + // Unsupported SubRegIndex. Skip it. + if (I == SRSets.end()) + continue; + // In most cases, all RC registers support the SubRegIndex. + if (I->second.size() == RC->getMembers().size()) { + RC->setSubClassWithSubReg(SubIdx, RC); + continue; + } + // This is a real subset. See if we have a matching class. + CodeGenRegisterClass *SubRC = + getOrCreateSubClass(RC, &I->second, + RC->getName() + "_with_" + I->first->getName()); + RC->setSubClassWithSubReg(SubIdx, SubRC); + } +} + +// +// Synthesize missing sub-classes of RC for getMatchingSuperRegClass(). +// +// Create sub-classes of RC such that getMatchingSuperRegClass(RC, SubIdx, X) +// has a maximal result for any SubIdx and any X >= FirstSubRegRC. +// + +void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC, + unsigned FirstSubRegRC) { + SmallVector<std::pair<const CodeGenRegister*, + const CodeGenRegister*>, 16> SSPairs; + + // Iterate in SubRegIndex numerical order to visit synthetic indices last. + for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { + CodeGenSubRegIndex *SubIdx = SubRegIndices[sri]; + // Skip indexes that aren't fully supported by RC's registers. This was + // computed by inferSubClassWithSubReg() above which should have been + // called first. + if (RC->getSubClassWithSubReg(SubIdx) != RC) + continue; + + // Build list of (Super, Sub) pairs for this SubIdx. + SSPairs.clear(); + for (CodeGenRegister::Set::const_iterator RI = RC->getMembers().begin(), + RE = RC->getMembers().end(); RI != RE; ++RI) { + const CodeGenRegister *Super = *RI; + const CodeGenRegister *Sub = Super->getSubRegs().find(SubIdx)->second; + assert(Sub && "Missing sub-register"); + SSPairs.push_back(std::make_pair(Super, Sub)); + } + + // Iterate over sub-register class candidates. Ignore classes created by + // this loop. They will never be useful. + for (unsigned rci = FirstSubRegRC, rce = RegClasses.size(); rci != rce; + ++rci) { + CodeGenRegisterClass *SubRC = RegClasses[rci]; + // Compute the subset of RC that maps into SubRC. + CodeGenRegister::Set SubSet; + for (unsigned i = 0, e = SSPairs.size(); i != e; ++i) + if (SubRC->contains(SSPairs[i].second)) + SubSet.insert(SSPairs[i].first); + if (SubSet.empty()) + continue; + // RC injects completely into SubRC. + if (SubSet.size() == SSPairs.size()) { + SubRC->addSuperRegClass(SubIdx, RC); + continue; + } + // Only a subset of RC maps into SubRC. Make sure it is represented by a + // class. + getOrCreateSubClass(RC, &SubSet, RC->getName() + + "_with_" + SubIdx->getName() + + "_in_" + SubRC->getName()); + } + } +} + + +// +// Infer missing register classes. +// +void CodeGenRegBank::computeInferredRegisterClasses() { + // When this function is called, the register classes have not been sorted + // and assigned EnumValues yet. That means getSubClasses(), + // getSuperClasses(), and hasSubClass() functions are defunct. + unsigned FirstNewRC = RegClasses.size(); + + // Visit all register classes, including the ones being added by the loop. + for (unsigned rci = 0; rci != RegClasses.size(); ++rci) { + CodeGenRegisterClass *RC = RegClasses[rci]; + + // Synthesize answers for getSubClassWithSubReg(). + inferSubClassWithSubReg(RC); + + // Synthesize answers for getCommonSubClass(). + inferCommonSubClass(RC); + + // Synthesize answers for getMatchingSuperRegClass(). + inferMatchingSuperRegClass(RC); + + // New register classes are created while this loop is running, and we need + // to visit all of them. I particular, inferMatchingSuperRegClass needs + // to match old super-register classes with sub-register classes created + // after inferMatchingSuperRegClass was called. At this point, + // inferMatchingSuperRegClass has checked SuperRC = [0..rci] with SubRC = + // [0..FirstNewRC). We need to cover SubRC = [FirstNewRC..rci]. + if (rci + 1 == FirstNewRC) { + unsigned NextNewRC = RegClasses.size(); + for (unsigned rci2 = 0; rci2 != FirstNewRC; ++rci2) + inferMatchingSuperRegClass(RegClasses[rci2], FirstNewRC); + FirstNewRC = NextNewRC; + } + } +} + +/// getRegisterClassForRegister - Find the register class that contains the +/// specified physical register. If the register is not in a register class, +/// return null. If the register is in multiple classes, and the classes have a +/// superset-subset relationship and the same set of types, return the +/// superclass. Otherwise return null. +const CodeGenRegisterClass* +CodeGenRegBank::getRegClassForRegister(Record *R) { + const CodeGenRegister *Reg = getReg(R); + ArrayRef<CodeGenRegisterClass*> RCs = getRegClasses(); + const CodeGenRegisterClass *FoundRC = 0; + for (unsigned i = 0, e = RCs.size(); i != e; ++i) { + const CodeGenRegisterClass &RC = *RCs[i]; + if (!RC.contains(Reg)) + continue; + + // If this is the first class that contains the register, + // make a note of it and go on to the next class. + if (!FoundRC) { + FoundRC = &RC; + continue; + } + + // If a register's classes have different types, return null. + if (RC.getValueTypes() != FoundRC->getValueTypes()) + return 0; + + // Check to see if the previously found class that contains + // the register is a subclass of the current class. If so, + // prefer the superclass. + if (RC.hasSubClass(FoundRC)) { + FoundRC = &RC; + continue; + } + + // Check to see if the previously found class that contains + // the register is a superclass of the current class. If so, + // prefer the superclass. + if (FoundRC->hasSubClass(&RC)) + continue; + + // Multiple classes, and neither is a superclass of the other. + // Return null. + return 0; + } + return FoundRC; +} + +BitVector CodeGenRegBank::computeCoveredRegisters(ArrayRef<Record*> Regs) { + SetVector<const CodeGenRegister*> Set; + + // First add Regs with all sub-registers. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + CodeGenRegister *Reg = getReg(Regs[i]); + if (Set.insert(Reg)) + // Reg is new, add all sub-registers. + // The pre-ordering is not important here. + Reg->addSubRegsPreOrder(Set, *this); + } + + // Second, find all super-registers that are completely covered by the set. + for (unsigned i = 0; i != Set.size(); ++i) { + const CodeGenRegister::SuperRegList &SR = Set[i]->getSuperRegs(); + for (unsigned j = 0, e = SR.size(); j != e; ++j) { + const CodeGenRegister *Super = SR[j]; + if (!Super->CoveredBySubRegs || Set.count(Super)) + continue; + // This new super-register is covered by its sub-registers. + bool AllSubsInSet = true; + const CodeGenRegister::SubRegMap &SRM = Super->getSubRegs(); + for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(), + E = SRM.end(); I != E; ++I) + if (!Set.count(I->second)) { + AllSubsInSet = false; + break; + } + // All sub-registers in Set, add Super as well. + // We will visit Super later to recheck its super-registers. + if (AllSubsInSet) + Set.insert(Super); + } + } + + // Convert to BitVector. + BitVector BV(Registers.size() + 1); + for (unsigned i = 0, e = Set.size(); i != e; ++i) + BV.set(Set[i]->EnumValue); + return BV; +} diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.h b/contrib/llvm/utils/TableGen/CodeGenRegisters.h new file mode 100644 index 0000000..232a6e7 --- /dev/null +++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.h @@ -0,0 +1,508 @@ +//===- CodeGenRegisters.h - Register and RegisterClass Info -----*- 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 structures to encapsulate information gleaned from the +// target register and register class definitions. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_REGISTERS_H +#define CODEGEN_REGISTERS_H + +#include "SetTheory.h" +#include "llvm/TableGen/Record.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/Support/ErrorHandling.h" +#include <cstdlib> +#include <map> +#include <string> +#include <set> +#include <vector> + +namespace llvm { + class CodeGenRegBank; + + /// CodeGenSubRegIndex - Represents a sub-register index. + class CodeGenSubRegIndex { + Record *const TheDef; + const unsigned EnumValue; + + public: + CodeGenSubRegIndex(Record *R, unsigned Enum); + + const std::string &getName() const; + std::string getNamespace() const; + std::string getQualifiedName() const; + + // Order CodeGenSubRegIndex pointers by EnumValue. + struct Less { + bool operator()(const CodeGenSubRegIndex *A, + const CodeGenSubRegIndex *B) const { + assert(A && B); + return A->EnumValue < B->EnumValue; + } + }; + + // Map of composite subreg indices. + typedef std::map<CodeGenSubRegIndex*, CodeGenSubRegIndex*, Less> CompMap; + + // Returns the subreg index that results from composing this with Idx. + // Returns NULL if this and Idx don't compose. + CodeGenSubRegIndex *compose(CodeGenSubRegIndex *Idx) const { + CompMap::const_iterator I = Composed.find(Idx); + return I == Composed.end() ? 0 : I->second; + } + + // Add a composite subreg index: this+A = B. + // Return a conflicting composite, or NULL + CodeGenSubRegIndex *addComposite(CodeGenSubRegIndex *A, + CodeGenSubRegIndex *B) { + std::pair<CompMap::iterator, bool> Ins = + Composed.insert(std::make_pair(A, B)); + return (Ins.second || Ins.first->second == B) ? 0 : Ins.first->second; + } + + // Update the composite maps of components specified in 'ComposedOf'. + void updateComponents(CodeGenRegBank&); + + // Clean out redundant composite mappings. + void cleanComposites(); + + // Return the map of composites. + const CompMap &getComposites() const { return Composed; } + + private: + CompMap Composed; + }; + + /// CodeGenRegister - Represents a register definition. + struct CodeGenRegister { + Record *TheDef; + unsigned EnumValue; + unsigned CostPerUse; + bool CoveredBySubRegs; + + // Map SubRegIndex -> Register. + typedef std::map<CodeGenSubRegIndex*, CodeGenRegister*, + CodeGenSubRegIndex::Less> SubRegMap; + + CodeGenRegister(Record *R, unsigned Enum); + + const std::string &getName() const; + + // Get a map of sub-registers computed lazily. + // This includes unique entries for all sub-sub-registers. + const SubRegMap &getSubRegs(CodeGenRegBank&); + + const SubRegMap &getSubRegs() const { + assert(SubRegsComplete && "Must precompute sub-registers"); + return SubRegs; + } + + // Add sub-registers to OSet following a pre-order defined by the .td file. + void addSubRegsPreOrder(SetVector<const CodeGenRegister*> &OSet, + CodeGenRegBank&) const; + + // List of super-registers in topological order, small to large. + typedef std::vector<const CodeGenRegister*> SuperRegList; + + // Get the list of super-registers. This is valid after getSubReg + // visits all registers during RegBank construction. + const SuperRegList &getSuperRegs() const { + assert(SubRegsComplete && "Must precompute sub-registers"); + return SuperRegs; + } + + // List of register units in ascending order. + typedef SmallVector<unsigned, 16> RegUnitList; + + // Get the list of register units. + // This is only valid after getSubRegs() completes. + const RegUnitList &getRegUnits() const { return RegUnits; } + + // Inherit register units from subregisters. + // Return true if the RegUnits changed. + bool inheritRegUnits(CodeGenRegBank &RegBank); + + // Adopt a register unit for pressure tracking. + // A unit is adopted iff its unit number is >= NumNativeRegUnits. + void adoptRegUnit(unsigned RUID) { RegUnits.push_back(RUID); } + + // Get the sum of this register's register unit weights. + unsigned getWeight(const CodeGenRegBank &RegBank) const; + + // Order CodeGenRegister pointers by EnumValue. + struct Less { + bool operator()(const CodeGenRegister *A, + const CodeGenRegister *B) const { + assert(A && B); + return A->EnumValue < B->EnumValue; + } + }; + + // Canonically ordered set. + typedef std::set<const CodeGenRegister*, Less> Set; + + private: + bool SubRegsComplete; + SubRegMap SubRegs; + SuperRegList SuperRegs; + RegUnitList RegUnits; + }; + + + class CodeGenRegisterClass { + CodeGenRegister::Set Members; + // Allocation orders. Order[0] always contains all registers in Members. + std::vector<SmallVector<Record*, 16> > Orders; + // Bit mask of sub-classes including this, indexed by their EnumValue. + BitVector SubClasses; + // List of super-classes, topologocally ordered to have the larger classes + // first. This is the same as sorting by EnumValue. + SmallVector<CodeGenRegisterClass*, 4> SuperClasses; + Record *TheDef; + std::string Name; + + // For a synthesized class, inherit missing properties from the nearest + // super-class. + void inheritProperties(CodeGenRegBank&); + + // Map SubRegIndex -> sub-class. This is the largest sub-class where all + // registers have a SubRegIndex sub-register. + DenseMap<CodeGenSubRegIndex*, CodeGenRegisterClass*> SubClassWithSubReg; + + // Map SubRegIndex -> set of super-reg classes. This is all register + // classes SuperRC such that: + // + // R:SubRegIndex in this RC for all R in SuperRC. + // + DenseMap<CodeGenSubRegIndex*, + SmallPtrSet<CodeGenRegisterClass*, 8> > SuperRegClasses; + + public: + unsigned EnumValue; + std::string Namespace; + std::vector<MVT::SimpleValueType> VTs; + unsigned SpillSize; + unsigned SpillAlignment; + int CopyCost; + bool Allocatable; + // Map SubRegIndex -> RegisterClass + DenseMap<Record*,Record*> SubRegClasses; + std::string AltOrderSelect; + + // Return the Record that defined this class, or NULL if the class was + // created by TableGen. + Record *getDef() const { return TheDef; } + + const std::string &getName() const { return Name; } + std::string getQualifiedName() const; + const std::vector<MVT::SimpleValueType> &getValueTypes() const {return VTs;} + unsigned getNumValueTypes() const { return VTs.size(); } + + MVT::SimpleValueType getValueTypeNum(unsigned VTNum) const { + if (VTNum < VTs.size()) + return VTs[VTNum]; + llvm_unreachable("VTNum greater than number of ValueTypes in RegClass!"); + } + + // Return true if this this class contains the register. + bool contains(const CodeGenRegister*) const; + + // Returns true if RC is a subclass. + // RC is a sub-class of this class if it is a valid replacement for any + // instruction operand where a register of this classis required. It must + // satisfy these conditions: + // + // 1. All RC registers are also in this. + // 2. The RC spill size must not be smaller than our spill size. + // 3. RC spill alignment must be compatible with ours. + // + bool hasSubClass(const CodeGenRegisterClass *RC) const { + return SubClasses.test(RC->EnumValue); + } + + // getSubClassWithSubReg - Returns the largest sub-class where all + // registers have a SubIdx sub-register. + CodeGenRegisterClass* + getSubClassWithSubReg(CodeGenSubRegIndex *SubIdx) const { + return SubClassWithSubReg.lookup(SubIdx); + } + + void setSubClassWithSubReg(CodeGenSubRegIndex *SubIdx, + CodeGenRegisterClass *SubRC) { + SubClassWithSubReg[SubIdx] = SubRC; + } + + // getSuperRegClasses - Returns a bit vector of all register classes + // containing only SubIdx super-registers of this class. + void getSuperRegClasses(CodeGenSubRegIndex *SubIdx, BitVector &Out) const; + + // addSuperRegClass - Add a class containing only SudIdx super-registers. + void addSuperRegClass(CodeGenSubRegIndex *SubIdx, + CodeGenRegisterClass *SuperRC) { + SuperRegClasses[SubIdx].insert(SuperRC); + } + + // getSubClasses - Returns a constant BitVector of subclasses indexed by + // EnumValue. + // The SubClasses vector includs an entry for this class. + const BitVector &getSubClasses() const { return SubClasses; } + + // getSuperClasses - Returns a list of super classes ordered by EnumValue. + // The array does not include an entry for this class. + ArrayRef<CodeGenRegisterClass*> getSuperClasses() const { + return SuperClasses; + } + + // Returns an ordered list of class members. + // The order of registers is the same as in the .td file. + // No = 0 is the default allocation order, No = 1 is the first alternative. + ArrayRef<Record*> getOrder(unsigned No = 0) const { + return Orders[No]; + } + + // Return the total number of allocation orders available. + unsigned getNumOrders() const { return Orders.size(); } + + // Get the set of registers. This set contains the same registers as + // getOrder(0). + const CodeGenRegister::Set &getMembers() const { return Members; } + + // Populate a unique sorted list of units from a register set. + void buildRegUnitSet(std::vector<unsigned> &RegUnits) const; + + CodeGenRegisterClass(CodeGenRegBank&, Record *R); + + // A key representing the parts of a register class used for forming + // sub-classes. Note the ordering provided by this key is not the same as + // the topological order used for the EnumValues. + struct Key { + const CodeGenRegister::Set *Members; + unsigned SpillSize; + unsigned SpillAlignment; + + Key(const Key &O) + : Members(O.Members), + SpillSize(O.SpillSize), + SpillAlignment(O.SpillAlignment) {} + + Key(const CodeGenRegister::Set *M, unsigned S = 0, unsigned A = 0) + : Members(M), SpillSize(S), SpillAlignment(A) {} + + Key(const CodeGenRegisterClass &RC) + : Members(&RC.getMembers()), + SpillSize(RC.SpillSize), + SpillAlignment(RC.SpillAlignment) {} + + // Lexicographical order of (Members, SpillSize, SpillAlignment). + bool operator<(const Key&) const; + }; + + // Create a non-user defined register class. + CodeGenRegisterClass(StringRef Name, Key Props); + + // Called by CodeGenRegBank::CodeGenRegBank(). + static void computeSubClasses(CodeGenRegBank&); + }; + + // Each RegUnitSet is a sorted vector with a name. + struct RegUnitSet { + typedef std::vector<unsigned>::const_iterator iterator; + + std::string Name; + std::vector<unsigned> Units; + }; + + // CodeGenRegBank - Represent a target's registers and the relations between + // them. + class CodeGenRegBank { + RecordKeeper &Records; + SetTheory Sets; + + // SubRegIndices. + std::vector<CodeGenSubRegIndex*> SubRegIndices; + DenseMap<Record*, CodeGenSubRegIndex*> Def2SubRegIdx; + unsigned NumNamedIndices; + + // Registers. + std::vector<CodeGenRegister*> Registers; + DenseMap<Record*, CodeGenRegister*> Def2Reg; + unsigned NumNativeRegUnits; + unsigned NumRegUnits; // # native + adopted register units. + + // Map each register unit to a weight (for register pressure). + // Includes native and adopted register units. + std::vector<unsigned> RegUnitWeights; + + // Register classes. + std::vector<CodeGenRegisterClass*> RegClasses; + DenseMap<Record*, CodeGenRegisterClass*> Def2RC; + typedef std::map<CodeGenRegisterClass::Key, CodeGenRegisterClass*> RCKeyMap; + RCKeyMap Key2RC; + + // Remember each unique set of register units. Initially, this contains a + // unique set for each register class. Simliar sets are coalesced with + // pruneUnitSets and new supersets are inferred during computeRegUnitSets. + std::vector<RegUnitSet> RegUnitSets; + + // Map RegisterClass index to the index of the RegUnitSet that contains the + // class's units and any inferred RegUnit supersets. + std::vector<std::vector<unsigned> > RegClassUnitSets; + + // Add RC to *2RC maps. + void addToMaps(CodeGenRegisterClass*); + + // Create a synthetic sub-class if it is missing. + CodeGenRegisterClass *getOrCreateSubClass(const CodeGenRegisterClass *RC, + const CodeGenRegister::Set *Membs, + StringRef Name); + + // Infer missing register classes. + void computeInferredRegisterClasses(); + void inferCommonSubClass(CodeGenRegisterClass *RC); + void inferSubClassWithSubReg(CodeGenRegisterClass *RC); + void inferMatchingSuperRegClass(CodeGenRegisterClass *RC, + unsigned FirstSubRegRC = 0); + + // Iteratively prune unit sets. + void pruneUnitSets(); + + // Compute a weight for each register unit created during getSubRegs. + void computeRegUnitWeights(); + + // Create a RegUnitSet for each RegClass and infer superclasses. + void computeRegUnitSets(); + + // Populate the Composite map from sub-register relationships. + void computeComposites(); + + public: + CodeGenRegBank(RecordKeeper&); + + SetTheory &getSets() { return Sets; } + + // Sub-register indices. The first NumNamedIndices are defined by the user + // in the .td files. The rest are synthesized such that all sub-registers + // have a unique name. + ArrayRef<CodeGenSubRegIndex*> getSubRegIndices() { return SubRegIndices; } + unsigned getNumNamedIndices() { return NumNamedIndices; } + + // Find a SubRegIndex form its Record def. + CodeGenSubRegIndex *getSubRegIdx(Record*); + + // Find or create a sub-register index representing the A+B composition. + CodeGenSubRegIndex *getCompositeSubRegIndex(CodeGenSubRegIndex *A, + CodeGenSubRegIndex *B); + + const std::vector<CodeGenRegister*> &getRegisters() { return Registers; } + + // Find a register from its Record def. + CodeGenRegister *getReg(Record*); + + // Get a Register's index into the Registers array. + unsigned getRegIndex(const CodeGenRegister *Reg) const { + return Reg->EnumValue - 1; + } + + // Create a new non-native register unit that can be adopted by a register + // to increase its pressure. Note that NumNativeRegUnits is not increased. + unsigned newRegUnit(unsigned Weight) { + if (!RegUnitWeights.empty()) { + assert(Weight && "should only add allocatable units"); + RegUnitWeights.resize(NumRegUnits+1); + RegUnitWeights[NumRegUnits] = Weight; + } + return NumRegUnits++; + } + + // Native units are the singular unit of a leaf register. Register aliasing + // is completely characterized by native units. Adopted units exist to give + // register additional weight but don't affect aliasing. + bool isNativeUnit(unsigned RUID) { + return RUID < NumNativeRegUnits; + } + + ArrayRef<CodeGenRegisterClass*> getRegClasses() const { + return RegClasses; + } + + // Find a register class from its def. + CodeGenRegisterClass *getRegClass(Record*); + + /// getRegisterClassForRegister - Find the register class that contains the + /// specified physical register. If the register is not in a register + /// class, return null. If the register is in multiple classes, and the + /// classes have a superset-subset relationship and the same set of types, + /// return the superclass. Otherwise return null. + const CodeGenRegisterClass* getRegClassForRegister(Record *R); + + // Get a register unit's weight. Zero for unallocatable registers. + unsigned getRegUnitWeight(unsigned RUID) const { + return RegUnitWeights[RUID]; + } + + // Get the sum of unit weights. + unsigned getRegUnitSetWeight(const std::vector<unsigned> &Units) const { + unsigned Weight = 0; + for (std::vector<unsigned>::const_iterator + I = Units.begin(), E = Units.end(); I != E; ++I) + Weight += getRegUnitWeight(*I); + return Weight; + } + + // Increase a RegUnitWeight. + void increaseRegUnitWeight(unsigned RUID, unsigned Inc) { + RegUnitWeights[RUID] += Inc; + } + + // Get the number of register pressure dimensions. + unsigned getNumRegPressureSets() const { return RegUnitSets.size(); } + + // Get a set of register unit IDs for a given dimension of pressure. + RegUnitSet getRegPressureSet(unsigned Idx) const { + return RegUnitSets[Idx]; + } + + // Get a list of pressure set IDs for a register class. Liveness of a + // register in this class impacts each pressure set in this list by the + // weight of the register. An exact solution requires all registers in a + // class to have the same class, but it is not strictly guaranteed. + ArrayRef<unsigned> getRCPressureSetIDs(unsigned RCIdx) const { + return RegClassUnitSets[RCIdx]; + } + + // Computed derived records such as missing sub-register indices. + void computeDerivedInfo(); + + // Compute full overlap sets for every register. These sets include the + // rarely used aliases that are neither sub nor super-registers. + // + // Map[R1].count(R2) is reflexive and symmetric, but not transitive. + // + // If R1 is a sub-register of R2, Map[R1] is a subset of Map[R2]. + void computeOverlaps(std::map<const CodeGenRegister*, + CodeGenRegister::Set> &Map); + + // Compute the set of registers completely covered by the registers in Regs. + // The returned BitVector will have a bit set for each register in Regs, + // all sub-registers, and all super-registers that are covered by the + // registers in Regs. + // + // This is used to compute the mask of call-preserved registers from a list + // of callee-saves. + BitVector computeCoveredRegisters(ArrayRef<Record*> Regs); + }; +} + +#endif diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp new file mode 100644 index 0000000..cf67935 --- /dev/null +++ b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp @@ -0,0 +1,523 @@ +//===- CodeGenTarget.cpp - CodeGen Target Class Wrapper -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class wraps target description classes used by the various code +// generation TableGen backends. This makes it easier to access the data and +// provides a single place that needs to check it for validity. All of these +// classes throw exceptions on error conditions. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenTarget.h" +#include "CodeGenIntrinsics.h" +#include "llvm/TableGen/Record.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/CommandLine.h" +#include <algorithm> +using namespace llvm; + +static cl::opt<unsigned> +AsmParserNum("asmparsernum", cl::init(0), + cl::desc("Make -gen-asm-parser emit assembly parser #N")); + +static cl::opt<unsigned> +AsmWriterNum("asmwriternum", cl::init(0), + cl::desc("Make -gen-asm-writer emit assembly writer #N")); + +/// getValueType - Return the MVT::SimpleValueType that the specified TableGen +/// record corresponds to. +MVT::SimpleValueType llvm::getValueType(Record *Rec) { + return (MVT::SimpleValueType)Rec->getValueAsInt("Value"); +} + +std::string llvm::getName(MVT::SimpleValueType T) { + switch (T) { + case MVT::Other: return "UNKNOWN"; + case MVT::iPTR: return "TLI.getPointerTy()"; + case MVT::iPTRAny: return "TLI.getPointerTy()"; + default: return getEnumName(T); + } +} + +std::string llvm::getEnumName(MVT::SimpleValueType T) { + switch (T) { + case MVT::Other: return "MVT::Other"; + case MVT::i1: return "MVT::i1"; + case MVT::i8: return "MVT::i8"; + case MVT::i16: return "MVT::i16"; + case MVT::i32: return "MVT::i32"; + case MVT::i64: return "MVT::i64"; + case MVT::i128: return "MVT::i128"; + case MVT::iAny: return "MVT::iAny"; + case MVT::fAny: return "MVT::fAny"; + case MVT::vAny: return "MVT::vAny"; + case MVT::f16: return "MVT::f16"; + case MVT::f32: return "MVT::f32"; + case MVT::f64: return "MVT::f64"; + case MVT::f80: return "MVT::f80"; + case MVT::f128: return "MVT::f128"; + case MVT::ppcf128: return "MVT::ppcf128"; + case MVT::x86mmx: return "MVT::x86mmx"; + case MVT::Glue: return "MVT::Glue"; + case MVT::isVoid: return "MVT::isVoid"; + case MVT::v2i8: return "MVT::v2i8"; + case MVT::v4i8: return "MVT::v4i8"; + case MVT::v8i8: return "MVT::v8i8"; + case MVT::v16i8: return "MVT::v16i8"; + case MVT::v32i8: return "MVT::v32i8"; + case MVT::v2i16: return "MVT::v2i16"; + case MVT::v4i16: return "MVT::v4i16"; + case MVT::v8i16: return "MVT::v8i16"; + case MVT::v16i16: return "MVT::v16i16"; + case MVT::v2i32: return "MVT::v2i32"; + case MVT::v4i32: return "MVT::v4i32"; + case MVT::v8i32: return "MVT::v8i32"; + case MVT::v1i64: return "MVT::v1i64"; + case MVT::v2i64: return "MVT::v2i64"; + case MVT::v4i64: return "MVT::v4i64"; + case MVT::v8i64: return "MVT::v8i64"; + case MVT::v2f16: return "MVT::v2f16"; + case MVT::v2f32: return "MVT::v2f32"; + case MVT::v4f32: return "MVT::v4f32"; + case MVT::v8f32: return "MVT::v8f32"; + case MVT::v2f64: return "MVT::v2f64"; + case MVT::v4f64: return "MVT::v4f64"; + case MVT::Metadata: return "MVT::Metadata"; + case MVT::iPTR: return "MVT::iPTR"; + case MVT::iPTRAny: return "MVT::iPTRAny"; + case MVT::Untyped: return "MVT::Untyped"; + default: llvm_unreachable("ILLEGAL VALUE TYPE!"); + } +} + +/// getQualifiedName - Return the name of the specified record, with a +/// namespace qualifier if the record contains one. +/// +std::string llvm::getQualifiedName(const Record *R) { + std::string Namespace; + if (R->getValue("Namespace")) + Namespace = R->getValueAsString("Namespace"); + if (Namespace.empty()) return R->getName(); + return Namespace + "::" + R->getName(); +} + + +/// getTarget - Return the current instance of the Target class. +/// +CodeGenTarget::CodeGenTarget(RecordKeeper &records) + : Records(records), RegBank(0) { + std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target"); + if (Targets.size() == 0) + throw std::string("ERROR: No 'Target' subclasses defined!"); + if (Targets.size() != 1) + throw std::string("ERROR: Multiple subclasses of Target defined!"); + TargetRec = Targets[0]; +} + + +const std::string &CodeGenTarget::getName() const { + return TargetRec->getName(); +} + +std::string CodeGenTarget::getInstNamespace() const { + for (inst_iterator i = inst_begin(), e = inst_end(); i != e; ++i) { + // Make sure not to pick up "TargetOpcode" by accidentally getting + // the namespace off the PHI instruction or something. + if ((*i)->Namespace != "TargetOpcode") + return (*i)->Namespace; + } + + return ""; +} + +Record *CodeGenTarget::getInstructionSet() const { + return TargetRec->getValueAsDef("InstructionSet"); +} + + +/// getAsmParser - Return the AssemblyParser definition for this target. +/// +Record *CodeGenTarget::getAsmParser() const { + std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers"); + if (AsmParserNum >= LI.size()) + throw "Target does not have an AsmParser #" + utostr(AsmParserNum) + "!"; + return LI[AsmParserNum]; +} + +/// getAsmParserVariant - Return the AssmblyParserVariant definition for +/// this target. +/// +Record *CodeGenTarget::getAsmParserVariant(unsigned i) const { + std::vector<Record*> LI = + TargetRec->getValueAsListOfDefs("AssemblyParserVariants"); + if (i >= LI.size()) + throw "Target does not have an AsmParserVariant #" + utostr(i) + "!"; + return LI[i]; +} + +/// getAsmParserVariantCount - Return the AssmblyParserVariant definition +/// available for this target. +/// +unsigned CodeGenTarget::getAsmParserVariantCount() const { + std::vector<Record*> LI = + TargetRec->getValueAsListOfDefs("AssemblyParserVariants"); + return LI.size(); +} + +/// getAsmWriter - Return the AssemblyWriter definition for this target. +/// +Record *CodeGenTarget::getAsmWriter() const { + std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters"); + if (AsmWriterNum >= LI.size()) + throw "Target does not have an AsmWriter #" + utostr(AsmWriterNum) + "!"; + return LI[AsmWriterNum]; +} + +CodeGenRegBank &CodeGenTarget::getRegBank() const { + if (!RegBank) + RegBank = new CodeGenRegBank(Records); + return *RegBank; +} + +void CodeGenTarget::ReadRegAltNameIndices() const { + RegAltNameIndices = Records.getAllDerivedDefinitions("RegAltNameIndex"); + std::sort(RegAltNameIndices.begin(), RegAltNameIndices.end(), LessRecord()); +} + +/// getRegisterByName - If there is a register with the specific AsmName, +/// return it. +const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const { + const std::vector<CodeGenRegister*> &Regs = getRegBank().getRegisters(); + for (unsigned i = 0, e = Regs.size(); i != e; ++i) + if (Regs[i]->TheDef->getValueAsString("AsmName") == Name) + return Regs[i]; + + return 0; +} + +std::vector<MVT::SimpleValueType> CodeGenTarget:: +getRegisterVTs(Record *R) const { + const CodeGenRegister *Reg = getRegBank().getReg(R); + std::vector<MVT::SimpleValueType> Result; + ArrayRef<CodeGenRegisterClass*> RCs = getRegBank().getRegClasses(); + for (unsigned i = 0, e = RCs.size(); i != e; ++i) { + const CodeGenRegisterClass &RC = *RCs[i]; + if (RC.contains(Reg)) { + const std::vector<MVT::SimpleValueType> &InVTs = RC.getValueTypes(); + Result.insert(Result.end(), InVTs.begin(), InVTs.end()); + } + } + + // Remove duplicates. + array_pod_sort(Result.begin(), Result.end()); + Result.erase(std::unique(Result.begin(), Result.end()), Result.end()); + return Result; +} + + +void CodeGenTarget::ReadLegalValueTypes() const { + ArrayRef<CodeGenRegisterClass*> RCs = getRegBank().getRegClasses(); + for (unsigned i = 0, e = RCs.size(); i != e; ++i) + for (unsigned ri = 0, re = RCs[i]->VTs.size(); ri != re; ++ri) + LegalValueTypes.push_back(RCs[i]->VTs[ri]); + + // Remove duplicates. + std::sort(LegalValueTypes.begin(), LegalValueTypes.end()); + LegalValueTypes.erase(std::unique(LegalValueTypes.begin(), + LegalValueTypes.end()), + LegalValueTypes.end()); +} + + +void CodeGenTarget::ReadInstructions() const { + std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); + if (Insts.size() <= 2) + throw std::string("No 'Instruction' subclasses defined!"); + + // Parse the instructions defined in the .td file. + for (unsigned i = 0, e = Insts.size(); i != e; ++i) + Instructions[Insts[i]] = new CodeGenInstruction(Insts[i]); +} + +static const CodeGenInstruction * +GetInstByName(const char *Name, + const DenseMap<const Record*, CodeGenInstruction*> &Insts, + RecordKeeper &Records) { + const Record *Rec = Records.getDef(Name); + + DenseMap<const Record*, CodeGenInstruction*>::const_iterator + I = Insts.find(Rec); + if (Rec == 0 || I == Insts.end()) + throw std::string("Could not find '") + Name + "' instruction!"; + return I->second; +} + +namespace { +/// SortInstByName - Sorting predicate to sort instructions by name. +/// +struct SortInstByName { + bool operator()(const CodeGenInstruction *Rec1, + const CodeGenInstruction *Rec2) const { + return Rec1->TheDef->getName() < Rec2->TheDef->getName(); + } +}; +} + +/// getInstructionsByEnumValue - Return all of the instructions defined by the +/// target, ordered by their enum value. +void CodeGenTarget::ComputeInstrsByEnum() const { + // The ordering here must match the ordering in TargetOpcodes.h. + const char *const FixedInstrs[] = { + "PHI", + "INLINEASM", + "PROLOG_LABEL", + "EH_LABEL", + "GC_LABEL", + "KILL", + "EXTRACT_SUBREG", + "INSERT_SUBREG", + "IMPLICIT_DEF", + "SUBREG_TO_REG", + "COPY_TO_REGCLASS", + "DBG_VALUE", + "REG_SEQUENCE", + "COPY", + "BUNDLE", + 0 + }; + const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions(); + for (const char *const *p = FixedInstrs; *p; ++p) { + const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records); + assert(Instr && "Missing target independent instruction"); + assert(Instr->Namespace == "TargetOpcode" && "Bad namespace"); + InstrsByEnum.push_back(Instr); + } + unsigned EndOfPredefines = InstrsByEnum.size(); + + for (DenseMap<const Record*, CodeGenInstruction*>::const_iterator + I = Insts.begin(), E = Insts.end(); I != E; ++I) { + const CodeGenInstruction *CGI = I->second; + if (CGI->Namespace != "TargetOpcode") + InstrsByEnum.push_back(CGI); + } + + assert(InstrsByEnum.size() == Insts.size() && "Missing predefined instr"); + + // All of the instructions are now in random order based on the map iteration. + // Sort them by name. + std::sort(InstrsByEnum.begin()+EndOfPredefines, InstrsByEnum.end(), + SortInstByName()); +} + + +/// isLittleEndianEncoding - Return whether this target encodes its instruction +/// in little-endian format, i.e. bits laid out in the order [0..n] +/// +bool CodeGenTarget::isLittleEndianEncoding() const { + return getInstructionSet()->getValueAsBit("isLittleEndianEncoding"); +} + +//===----------------------------------------------------------------------===// +// ComplexPattern implementation +// +ComplexPattern::ComplexPattern(Record *R) { + Ty = ::getValueType(R->getValueAsDef("Ty")); + NumOperands = R->getValueAsInt("NumOperands"); + SelectFunc = R->getValueAsString("SelectFunc"); + RootNodes = R->getValueAsListOfDefs("RootNodes"); + + // Parse the properties. + Properties = 0; + std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties"); + for (unsigned i = 0, e = PropList.size(); i != e; ++i) + if (PropList[i]->getName() == "SDNPHasChain") { + Properties |= 1 << SDNPHasChain; + } else if (PropList[i]->getName() == "SDNPOptInGlue") { + Properties |= 1 << SDNPOptInGlue; + } else if (PropList[i]->getName() == "SDNPMayStore") { + Properties |= 1 << SDNPMayStore; + } else if (PropList[i]->getName() == "SDNPMayLoad") { + Properties |= 1 << SDNPMayLoad; + } else if (PropList[i]->getName() == "SDNPSideEffect") { + Properties |= 1 << SDNPSideEffect; + } else if (PropList[i]->getName() == "SDNPMemOperand") { + Properties |= 1 << SDNPMemOperand; + } else if (PropList[i]->getName() == "SDNPVariadic") { + Properties |= 1 << SDNPVariadic; + } else if (PropList[i]->getName() == "SDNPWantRoot") { + Properties |= 1 << SDNPWantRoot; + } else if (PropList[i]->getName() == "SDNPWantParent") { + Properties |= 1 << SDNPWantParent; + } else { + errs() << "Unsupported SD Node property '" << PropList[i]->getName() + << "' on ComplexPattern '" << R->getName() << "'!\n"; + exit(1); + } +} + +//===----------------------------------------------------------------------===// +// CodeGenIntrinsic Implementation +//===----------------------------------------------------------------------===// + +std::vector<CodeGenIntrinsic> llvm::LoadIntrinsics(const RecordKeeper &RC, + bool TargetOnly) { + std::vector<Record*> I = RC.getAllDerivedDefinitions("Intrinsic"); + + std::vector<CodeGenIntrinsic> Result; + + for (unsigned i = 0, e = I.size(); i != e; ++i) { + bool isTarget = I[i]->getValueAsBit("isTarget"); + if (isTarget == TargetOnly) + Result.push_back(CodeGenIntrinsic(I[i])); + } + return Result; +} + +CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { + TheDef = R; + std::string DefName = R->getName(); + ModRef = ReadWriteMem; + isOverloaded = false; + isCommutative = false; + canThrow = false; + + if (DefName.size() <= 4 || + std::string(DefName.begin(), DefName.begin() + 4) != "int_") + throw "Intrinsic '" + DefName + "' does not start with 'int_'!"; + + EnumName = std::string(DefName.begin()+4, DefName.end()); + + if (R->getValue("GCCBuiltinName")) // Ignore a missing GCCBuiltinName field. + GCCBuiltinName = R->getValueAsString("GCCBuiltinName"); + + TargetPrefix = R->getValueAsString("TargetPrefix"); + Name = R->getValueAsString("LLVMName"); + + if (Name == "") { + // If an explicit name isn't specified, derive one from the DefName. + Name = "llvm."; + + for (unsigned i = 0, e = EnumName.size(); i != e; ++i) + Name += (EnumName[i] == '_') ? '.' : EnumName[i]; + } else { + // Verify it starts with "llvm.". + if (Name.size() <= 5 || + std::string(Name.begin(), Name.begin() + 5) != "llvm.") + throw "Intrinsic '" + DefName + "'s name does not start with 'llvm.'!"; + } + + // If TargetPrefix is specified, make sure that Name starts with + // "llvm.<targetprefix>.". + if (!TargetPrefix.empty()) { + if (Name.size() < 6+TargetPrefix.size() || + std::string(Name.begin() + 5, Name.begin() + 6 + TargetPrefix.size()) + != (TargetPrefix + ".")) + throw "Intrinsic '" + DefName + "' does not start with 'llvm." + + TargetPrefix + ".'!"; + } + + // Parse the list of return types. + std::vector<MVT::SimpleValueType> OverloadedVTs; + ListInit *TypeList = R->getValueAsListInit("RetTypes"); + for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) { + Record *TyEl = TypeList->getElementAsRecord(i); + assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!"); + MVT::SimpleValueType VT; + if (TyEl->isSubClassOf("LLVMMatchType")) { + unsigned MatchTy = TyEl->getValueAsInt("Number"); + assert(MatchTy < OverloadedVTs.size() && + "Invalid matching number!"); + VT = OverloadedVTs[MatchTy]; + // It only makes sense to use the extended and truncated vector element + // variants with iAny types; otherwise, if the intrinsic is not + // overloaded, all the types can be specified directly. + assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") && + !TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) || + VT == MVT::iAny || VT == MVT::vAny) && + "Expected iAny or vAny type"); + } else { + VT = getValueType(TyEl->getValueAsDef("VT")); + } + if (EVT(VT).isOverloaded()) { + OverloadedVTs.push_back(VT); + isOverloaded = true; + } + + // Reject invalid types. + if (VT == MVT::isVoid) + throw "Intrinsic '" + DefName + " has void in result type list!"; + + IS.RetVTs.push_back(VT); + IS.RetTypeDefs.push_back(TyEl); + } + + // Parse the list of parameter types. + TypeList = R->getValueAsListInit("ParamTypes"); + for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) { + Record *TyEl = TypeList->getElementAsRecord(i); + assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!"); + MVT::SimpleValueType VT; + if (TyEl->isSubClassOf("LLVMMatchType")) { + unsigned MatchTy = TyEl->getValueAsInt("Number"); + assert(MatchTy < OverloadedVTs.size() && + "Invalid matching number!"); + VT = OverloadedVTs[MatchTy]; + // It only makes sense to use the extended and truncated vector element + // variants with iAny types; otherwise, if the intrinsic is not + // overloaded, all the types can be specified directly. + assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") && + !TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) || + VT == MVT::iAny || VT == MVT::vAny) && + "Expected iAny or vAny type"); + } else + VT = getValueType(TyEl->getValueAsDef("VT")); + + if (EVT(VT).isOverloaded()) { + OverloadedVTs.push_back(VT); + isOverloaded = true; + } + + // Reject invalid types. + if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/) + throw "Intrinsic '" + DefName + " has void in result type list!"; + + IS.ParamVTs.push_back(VT); + IS.ParamTypeDefs.push_back(TyEl); + } + + // Parse the intrinsic properties. + ListInit *PropList = R->getValueAsListInit("Properties"); + for (unsigned i = 0, e = PropList->getSize(); i != e; ++i) { + Record *Property = PropList->getElementAsRecord(i); + assert(Property->isSubClassOf("IntrinsicProperty") && + "Expected a property!"); + + if (Property->getName() == "IntrNoMem") + ModRef = NoMem; + else if (Property->getName() == "IntrReadArgMem") + ModRef = ReadArgMem; + else if (Property->getName() == "IntrReadMem") + ModRef = ReadMem; + else if (Property->getName() == "IntrReadWriteArgMem") + ModRef = ReadWriteArgMem; + else if (Property->getName() == "Commutative") + isCommutative = true; + else if (Property->getName() == "Throws") + canThrow = true; + else if (Property->isSubClassOf("NoCapture")) { + unsigned ArgNo = Property->getValueAsInt("ArgNo"); + ArgumentAttributes.push_back(std::make_pair(ArgNo, NoCapture)); + } else + llvm_unreachable("Unknown property!"); + } + + // Sort the argument attributes for later benefit. + std::sort(ArgumentAttributes.begin(), ArgumentAttributes.end()); +} diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.h b/contrib/llvm/utils/TableGen/CodeGenTarget.h new file mode 100644 index 0000000..85463da --- /dev/null +++ b/contrib/llvm/utils/TableGen/CodeGenTarget.h @@ -0,0 +1,201 @@ +//===- CodeGenTarget.h - Target Class Wrapper -------------------*- 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 wrappers for the Target class and related global +// functionality. This makes it easier to access the data and provides a single +// place that needs to check it for validity. All of these classes throw +// exceptions on error conditions. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_TARGET_H +#define CODEGEN_TARGET_H + +#include "CodeGenRegisters.h" +#include "CodeGenInstruction.h" +#include "llvm/TableGen/Record.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> + +namespace llvm { + +struct CodeGenRegister; +class CodeGenTarget; + +// SelectionDAG node properties. +// SDNPMemOperand: indicates that a node touches memory and therefore must +// have an associated memory operand that describes the access. +enum SDNP { + SDNPCommutative, + SDNPAssociative, + SDNPHasChain, + SDNPOutGlue, + SDNPInGlue, + SDNPOptInGlue, + SDNPMayLoad, + SDNPMayStore, + SDNPSideEffect, + SDNPMemOperand, + SDNPVariadic, + SDNPWantRoot, + SDNPWantParent +}; + +/// getValueType - Return the MVT::SimpleValueType that the specified TableGen +/// record corresponds to. +MVT::SimpleValueType getValueType(Record *Rec); + +std::string getName(MVT::SimpleValueType T); +std::string getEnumName(MVT::SimpleValueType T); + +/// getQualifiedName - Return the name of the specified record, with a +/// namespace qualifier if the record contains one. +std::string getQualifiedName(const Record *R); + +/// CodeGenTarget - This class corresponds to the Target class in the .td files. +/// +class CodeGenTarget { + RecordKeeper &Records; + Record *TargetRec; + + mutable DenseMap<const Record*, CodeGenInstruction*> Instructions; + mutable CodeGenRegBank *RegBank; + mutable std::vector<Record*> RegAltNameIndices; + mutable std::vector<MVT::SimpleValueType> LegalValueTypes; + void ReadRegAltNameIndices() const; + void ReadInstructions() const; + void ReadLegalValueTypes() const; + + mutable std::vector<const CodeGenInstruction*> InstrsByEnum; +public: + CodeGenTarget(RecordKeeper &Records); + + Record *getTargetRecord() const { return TargetRec; } + const std::string &getName() const; + + /// getInstNamespace - Return the target-specific instruction namespace. + /// + std::string getInstNamespace() const; + + /// getInstructionSet - Return the InstructionSet object. + /// + Record *getInstructionSet() const; + + /// getAsmParser - Return the AssemblyParser definition for this target. + /// + Record *getAsmParser() const; + + /// getAsmParserVariant - Return the AssmblyParserVariant definition for + /// this target. + /// + Record *getAsmParserVariant(unsigned i) const; + + /// getAsmParserVariantCount - Return the AssmblyParserVariant definition + /// available for this target. + /// + unsigned getAsmParserVariantCount() const; + + /// getAsmWriter - Return the AssemblyWriter definition for this target. + /// + Record *getAsmWriter() const; + + /// getRegBank - Return the register bank description. + CodeGenRegBank &getRegBank() const; + + /// getRegisterByName - If there is a register with the specific AsmName, + /// return it. + const CodeGenRegister *getRegisterByName(StringRef Name) const; + + const std::vector<Record*> &getRegAltNameIndices() const { + if (RegAltNameIndices.empty()) ReadRegAltNameIndices(); + return RegAltNameIndices; + } + + const CodeGenRegisterClass &getRegisterClass(Record *R) const { + return *getRegBank().getRegClass(R); + } + + /// getRegisterVTs - Find the union of all possible SimpleValueTypes for the + /// specified physical register. + std::vector<MVT::SimpleValueType> getRegisterVTs(Record *R) const; + + const std::vector<MVT::SimpleValueType> &getLegalValueTypes() const { + if (LegalValueTypes.empty()) ReadLegalValueTypes(); + return LegalValueTypes; + } + + /// isLegalValueType - Return true if the specified value type is natively + /// supported by the target (i.e. there are registers that directly hold it). + bool isLegalValueType(MVT::SimpleValueType VT) const { + const std::vector<MVT::SimpleValueType> &LegalVTs = getLegalValueTypes(); + for (unsigned i = 0, e = LegalVTs.size(); i != e; ++i) + if (LegalVTs[i] == VT) return true; + return false; + } + +private: + DenseMap<const Record*, CodeGenInstruction*> &getInstructions() const { + if (Instructions.empty()) ReadInstructions(); + return Instructions; + } +public: + + CodeGenInstruction &getInstruction(const Record *InstRec) const { + if (Instructions.empty()) ReadInstructions(); + DenseMap<const Record*, CodeGenInstruction*>::iterator I = + Instructions.find(InstRec); + assert(I != Instructions.end() && "Not an instruction"); + return *I->second; + } + + /// getInstructionsByEnumValue - Return all of the instructions defined by the + /// target, ordered by their enum value. + const std::vector<const CodeGenInstruction*> & + getInstructionsByEnumValue() const { + if (InstrsByEnum.empty()) ComputeInstrsByEnum(); + return InstrsByEnum; + } + + typedef std::vector<const CodeGenInstruction*>::const_iterator inst_iterator; + inst_iterator inst_begin() const{return getInstructionsByEnumValue().begin();} + inst_iterator inst_end() const { return getInstructionsByEnumValue().end(); } + + + /// isLittleEndianEncoding - are instruction bit patterns defined as [0..n]? + /// + bool isLittleEndianEncoding() const; + +private: + void ComputeInstrsByEnum() const; +}; + +/// ComplexPattern - ComplexPattern info, corresponding to the ComplexPattern +/// tablegen class in TargetSelectionDAG.td +class ComplexPattern { + MVT::SimpleValueType Ty; + unsigned NumOperands; + std::string SelectFunc; + std::vector<Record*> RootNodes; + unsigned Properties; // Node properties +public: + ComplexPattern() : NumOperands(0) {} + ComplexPattern(Record *R); + + MVT::SimpleValueType getValueType() const { return Ty; } + unsigned getNumOperands() const { return NumOperands; } + const std::string &getSelectFunc() const { return SelectFunc; } + const std::vector<Record*> &getRootNodes() const { + return RootNodes; + } + bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); } +}; + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp b/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp new file mode 100644 index 0000000..7db9003 --- /dev/null +++ b/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp @@ -0,0 +1,155 @@ +//===- DAGISelEmitter.cpp - Generate an instruction selector --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend emits a DAG instruction selector. +// +//===----------------------------------------------------------------------===// + +#include "DAGISelEmitter.h" +#include "DAGISelMatcher.h" +#include "llvm/TableGen/Record.h" +#include "llvm/Support/Debug.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// DAGISelEmitter Helper methods +// + +/// getResultPatternCost - Compute the number of instructions for this pattern. +/// This is a temporary hack. We should really include the instruction +/// latencies in this calculation. +static unsigned getResultPatternCost(TreePatternNode *P, + CodeGenDAGPatterns &CGP) { + if (P->isLeaf()) return 0; + + unsigned Cost = 0; + Record *Op = P->getOperator(); + if (Op->isSubClassOf("Instruction")) { + Cost++; + CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op); + if (II.usesCustomInserter) + Cost += 10; + } + for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i) + Cost += getResultPatternCost(P->getChild(i), CGP); + return Cost; +} + +/// getResultPatternCodeSize - Compute the code size of instructions for this +/// pattern. +static unsigned getResultPatternSize(TreePatternNode *P, + CodeGenDAGPatterns &CGP) { + if (P->isLeaf()) return 0; + + unsigned Cost = 0; + Record *Op = P->getOperator(); + if (Op->isSubClassOf("Instruction")) { + Cost += Op->getValueAsInt("CodeSize"); + } + for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i) + Cost += getResultPatternSize(P->getChild(i), CGP); + return Cost; +} + +namespace { +// PatternSortingPredicate - return true if we prefer to match LHS before RHS. +// In particular, we want to match maximal patterns first and lowest cost within +// a particular complexity first. +struct PatternSortingPredicate { + PatternSortingPredicate(CodeGenDAGPatterns &cgp) : CGP(cgp) {} + CodeGenDAGPatterns &CGP; + + bool operator()(const PatternToMatch *LHS, const PatternToMatch *RHS) { + const TreePatternNode *LHSSrc = LHS->getSrcPattern(); + const TreePatternNode *RHSSrc = RHS->getSrcPattern(); + + if (LHSSrc->getNumTypes() != 0 && RHSSrc->getNumTypes() != 0 && + LHSSrc->getType(0) != RHSSrc->getType(0)) { + MVT::SimpleValueType V1 = LHSSrc->getType(0), V2 = RHSSrc->getType(0); + if (MVT(V1).isVector() != MVT(V2).isVector()) + return MVT(V2).isVector(); + + if (MVT(V1).isFloatingPoint() != MVT(V2).isFloatingPoint()) + return MVT(V2).isFloatingPoint(); + } + + // Otherwise, if the patterns might both match, sort based on complexity, + // which means that we prefer to match patterns that cover more nodes in the + // input over nodes that cover fewer. + unsigned LHSSize = LHS->getPatternComplexity(CGP); + unsigned RHSSize = RHS->getPatternComplexity(CGP); + if (LHSSize > RHSSize) return true; // LHS -> bigger -> less cost + if (LHSSize < RHSSize) return false; + + // If the patterns have equal complexity, compare generated instruction cost + unsigned LHSCost = getResultPatternCost(LHS->getDstPattern(), CGP); + unsigned RHSCost = getResultPatternCost(RHS->getDstPattern(), CGP); + if (LHSCost < RHSCost) return true; + if (LHSCost > RHSCost) return false; + + unsigned LHSPatSize = getResultPatternSize(LHS->getDstPattern(), CGP); + unsigned RHSPatSize = getResultPatternSize(RHS->getDstPattern(), CGP); + if (LHSPatSize < RHSPatSize) return true; + if (LHSPatSize > RHSPatSize) return false; + + // Sort based on the UID of the pattern, giving us a deterministic ordering + // if all other sorting conditions fail. + assert(LHS == RHS || LHS->ID != RHS->ID); + return LHS->ID < RHS->ID; + } +}; +} + + +void DAGISelEmitter::run(raw_ostream &OS) { + EmitSourceFileHeader("DAG Instruction Selector for the " + + CGP.getTargetInfo().getName() + " target", OS); + + OS << "// *** NOTE: This file is #included into the middle of the target\n" + << "// *** instruction selector class. These functions are really " + << "methods.\n\n"; + + DEBUG(errs() << "\n\nALL PATTERNS TO MATCH:\n\n"; + for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(), + E = CGP.ptm_end(); I != E; ++I) { + errs() << "PATTERN: "; I->getSrcPattern()->dump(); + errs() << "\nRESULT: "; I->getDstPattern()->dump(); + errs() << "\n"; + }); + + // Add all the patterns to a temporary list so we can sort them. + std::vector<const PatternToMatch*> Patterns; + for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(), E = CGP.ptm_end(); + I != E; ++I) + Patterns.push_back(&*I); + + // We want to process the matches in order of minimal cost. Sort the patterns + // so the least cost one is at the start. + std::sort(Patterns.begin(), Patterns.end(), PatternSortingPredicate(CGP)); + + + // Convert each variant of each pattern into a Matcher. + std::vector<Matcher*> PatternMatchers; + for (unsigned i = 0, e = Patterns.size(); i != e; ++i) { + for (unsigned Variant = 0; ; ++Variant) { + if (Matcher *M = ConvertPatternToMatcher(*Patterns[i], Variant, CGP)) + PatternMatchers.push_back(M); + else + break; + } + } + + Matcher *TheMatcher = new ScopeMatcher(&PatternMatchers[0], + PatternMatchers.size()); + + TheMatcher = OptimizeMatcher(TheMatcher, CGP); + //Matcher->dump(); + EmitMatcherTable(TheMatcher, CGP, OS); + delete TheMatcher; +} diff --git a/contrib/llvm/utils/TableGen/DAGISelEmitter.h b/contrib/llvm/utils/TableGen/DAGISelEmitter.h new file mode 100644 index 0000000..9c9fe42 --- /dev/null +++ b/contrib/llvm/utils/TableGen/DAGISelEmitter.h @@ -0,0 +1,37 @@ +//===- DAGISelEmitter.h - Generate an instruction selector ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend emits a DAG instruction selector. +// +//===----------------------------------------------------------------------===// + +#ifndef DAGISEL_EMITTER_H +#define DAGISEL_EMITTER_H + +#include "llvm/TableGen/TableGenBackend.h" +#include "CodeGenDAGPatterns.h" + +namespace llvm { + +/// DAGISelEmitter - The top-level class which coordinates construction +/// and emission of the instruction selector. +/// +class DAGISelEmitter : public TableGenBackend { + RecordKeeper &Records; + CodeGenDAGPatterns CGP; +public: + explicit DAGISelEmitter(RecordKeeper &R) : Records(R), CGP(R) {} + + // run - Output the isel, returning true on failure. + void run(raw_ostream &OS); +}; + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp new file mode 100644 index 0000000..bd77907 --- /dev/null +++ b/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp @@ -0,0 +1,415 @@ +//===- DAGISelMatcher.cpp - Representation of DAG pattern matcher ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DAGISelMatcher.h" +#include "CodeGenDAGPatterns.h" +#include "CodeGenTarget.h" +#include "llvm/TableGen/Record.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/StringExtras.h" +using namespace llvm; + +void Matcher::anchor() { } + +void Matcher::dump() const { + print(errs(), 0); +} + +void Matcher::print(raw_ostream &OS, unsigned indent) const { + printImpl(OS, indent); + if (Next) + return Next->print(OS, indent); +} + +void Matcher::printOne(raw_ostream &OS) const { + printImpl(OS, 0); +} + +/// unlinkNode - Unlink the specified node from this chain. If Other == this, +/// we unlink the next pointer and return it. Otherwise we unlink Other from +/// the list and return this. +Matcher *Matcher::unlinkNode(Matcher *Other) { + if (this == Other) + return takeNext(); + + // Scan until we find the predecessor of Other. + Matcher *Cur = this; + for (; Cur && Cur->getNext() != Other; Cur = Cur->getNext()) + /*empty*/; + + if (Cur == 0) return 0; + Cur->takeNext(); + Cur->setNext(Other->takeNext()); + return this; +} + +/// canMoveBefore - Return true if this matcher is the same as Other, or if +/// we can move this matcher past all of the nodes in-between Other and this +/// node. Other must be equal to or before this. +bool Matcher::canMoveBefore(const Matcher *Other) const { + for (;; Other = Other->getNext()) { + assert(Other && "Other didn't come before 'this'?"); + if (this == Other) return true; + + // We have to be able to move this node across the Other node. + if (!canMoveBeforeNode(Other)) + return false; + } +} + +/// canMoveBefore - Return true if it is safe to move the current matcher +/// across the specified one. +bool Matcher::canMoveBeforeNode(const Matcher *Other) const { + // We can move simple predicates before record nodes. + if (isSimplePredicateNode()) + return Other->isSimplePredicateOrRecordNode(); + + // We can move record nodes across simple predicates. + if (isSimplePredicateOrRecordNode()) + return isSimplePredicateNode(); + + // We can't move record nodes across each other etc. + return false; +} + + +ScopeMatcher::~ScopeMatcher() { + for (unsigned i = 0, e = Children.size(); i != e; ++i) + delete Children[i]; +} + + +CheckPredicateMatcher::CheckPredicateMatcher(const TreePredicateFn &pred) + : Matcher(CheckPredicate), Pred(pred.getOrigPatFragRecord()) {} + +TreePredicateFn CheckPredicateMatcher::getPredicate() const { + return TreePredicateFn(Pred); +} + + + +// printImpl methods. + +void ScopeMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "Scope\n"; + for (unsigned i = 0, e = getNumChildren(); i != e; ++i) { + if (getChild(i) == 0) + OS.indent(indent+1) << "NULL POINTER\n"; + else + getChild(i)->print(OS, indent+2); + } +} + +void RecordMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "Record\n"; +} + +void RecordChildMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "RecordChild: " << ChildNo << '\n'; +} + +void RecordMemRefMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "RecordMemRef\n"; +} + +void CaptureGlueInputMatcher::printImpl(raw_ostream &OS, unsigned indent) const{ + OS.indent(indent) << "CaptureGlueInput\n"; +} + +void MoveChildMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "MoveChild " << ChildNo << '\n'; +} + +void MoveParentMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "MoveParent\n"; +} + +void CheckSameMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "CheckSame " << MatchNumber << '\n'; +} + +void CheckPatternPredicateMatcher:: +printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "CheckPatternPredicate " << Predicate << '\n'; +} + +void CheckPredicateMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "CheckPredicate " << getPredicate().getFnName() << '\n'; +} + +void CheckOpcodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "CheckOpcode " << Opcode.getEnumName() << '\n'; +} + +void SwitchOpcodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "SwitchOpcode: {\n"; + for (unsigned i = 0, e = Cases.size(); i != e; ++i) { + OS.indent(indent) << "case " << Cases[i].first->getEnumName() << ":\n"; + Cases[i].second->print(OS, indent+2); + } + OS.indent(indent) << "}\n"; +} + + +void CheckTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "CheckType " << getEnumName(Type) << ", ResNo=" + << ResNo << '\n'; +} + +void SwitchTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "SwitchType: {\n"; + for (unsigned i = 0, e = Cases.size(); i != e; ++i) { + OS.indent(indent) << "case " << getEnumName(Cases[i].first) << ":\n"; + Cases[i].second->print(OS, indent+2); + } + OS.indent(indent) << "}\n"; +} + +void CheckChildTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "CheckChildType " << ChildNo << " " + << getEnumName(Type) << '\n'; +} + + +void CheckIntegerMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "CheckInteger " << Value << '\n'; +} + +void CheckCondCodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "CheckCondCode ISD::" << CondCodeName << '\n'; +} + +void CheckValueTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "CheckValueType MVT::" << TypeName << '\n'; +} + +void CheckComplexPatMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "CheckComplexPat " << Pattern.getSelectFunc() << '\n'; +} + +void CheckAndImmMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "CheckAndImm " << Value << '\n'; +} + +void CheckOrImmMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "CheckOrImm " << Value << '\n'; +} + +void CheckFoldableChainNodeMatcher::printImpl(raw_ostream &OS, + unsigned indent) const { + OS.indent(indent) << "CheckFoldableChainNode\n"; +} + +void EmitIntegerMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "EmitInteger " << Val << " VT=" << VT << '\n'; +} + +void EmitStringIntegerMatcher:: +printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "EmitStringInteger " << Val << " VT=" << VT << '\n'; +} + +void EmitRegisterMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "EmitRegister "; + if (Reg) + OS << Reg->getName(); + else + OS << "zero_reg"; + OS << " VT=" << VT << '\n'; +} + +void EmitConvertToTargetMatcher:: +printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "EmitConvertToTarget " << Slot << '\n'; +} + +void EmitMergeInputChainsMatcher:: +printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "EmitMergeInputChains <todo: args>\n"; +} + +void EmitCopyToRegMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "EmitCopyToReg <todo: args>\n"; +} + +void EmitNodeXFormMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "EmitNodeXForm " << NodeXForm->getName() + << " Slot=" << Slot << '\n'; +} + + +void EmitNodeMatcherCommon::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent); + OS << (isa<MorphNodeToMatcher>(this) ? "MorphNodeTo: " : "EmitNode: ") + << OpcodeName << ": <todo flags> "; + + for (unsigned i = 0, e = VTs.size(); i != e; ++i) + OS << ' ' << getEnumName(VTs[i]); + OS << '('; + for (unsigned i = 0, e = Operands.size(); i != e; ++i) + OS << Operands[i] << ' '; + OS << ")\n"; +} + +void MarkGlueResultsMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "MarkGlueResults <todo: args>\n"; +} + +void CompleteMatchMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "CompleteMatch <todo args>\n"; + OS.indent(indent) << "Src = " << *Pattern.getSrcPattern() << "\n"; + OS.indent(indent) << "Dst = " << *Pattern.getDstPattern() << "\n"; +} + +// getHashImpl Implementation. + +unsigned CheckPatternPredicateMatcher::getHashImpl() const { + return HashString(Predicate); +} + +unsigned CheckPredicateMatcher::getHashImpl() const { + return HashString(getPredicate().getFnName()); +} + +unsigned CheckOpcodeMatcher::getHashImpl() const { + return HashString(Opcode.getEnumName()); +} + +unsigned CheckCondCodeMatcher::getHashImpl() const { + return HashString(CondCodeName); +} + +unsigned CheckValueTypeMatcher::getHashImpl() const { + return HashString(TypeName); +} + +unsigned EmitStringIntegerMatcher::getHashImpl() const { + return HashString(Val) ^ VT; +} + +template<typename It> +static unsigned HashUnsigneds(It I, It E) { + unsigned Result = 0; + for (; I != E; ++I) + Result = (Result<<3) ^ *I; + return Result; +} + +unsigned EmitMergeInputChainsMatcher::getHashImpl() const { + return HashUnsigneds(ChainNodes.begin(), ChainNodes.end()); +} + +bool CheckOpcodeMatcher::isEqualImpl(const Matcher *M) const { + // Note: pointer equality isn't enough here, we have to check the enum names + // to ensure that the nodes are for the same opcode. + return cast<CheckOpcodeMatcher>(M)->Opcode.getEnumName() == + Opcode.getEnumName(); +} + +bool EmitNodeMatcherCommon::isEqualImpl(const Matcher *m) const { + const EmitNodeMatcherCommon *M = cast<EmitNodeMatcherCommon>(m); + return M->OpcodeName == OpcodeName && M->VTs == VTs && + M->Operands == Operands && M->HasChain == HasChain && + M->HasInGlue == HasInGlue && M->HasOutGlue == HasOutGlue && + M->HasMemRefs == HasMemRefs && + M->NumFixedArityOperands == NumFixedArityOperands; +} + +unsigned EmitNodeMatcherCommon::getHashImpl() const { + return (HashString(OpcodeName) << 4) | Operands.size(); +} + + +void EmitNodeMatcher::anchor() { } + +void MorphNodeToMatcher::anchor() { } + +unsigned MarkGlueResultsMatcher::getHashImpl() const { + return HashUnsigneds(GlueResultNodes.begin(), GlueResultNodes.end()); +} + +unsigned CompleteMatchMatcher::getHashImpl() const { + return HashUnsigneds(Results.begin(), Results.end()) ^ + ((unsigned)(intptr_t)&Pattern << 8); +} + +// isContradictoryImpl Implementations. + +static bool TypesAreContradictory(MVT::SimpleValueType T1, + MVT::SimpleValueType T2) { + // If the two types are the same, then they are the same, so they don't + // contradict. + if (T1 == T2) return false; + + // If either type is about iPtr, then they don't conflict unless the other + // one is not a scalar integer type. + if (T1 == MVT::iPTR) + return !MVT(T2).isInteger() || MVT(T2).isVector(); + + if (T2 == MVT::iPTR) + return !MVT(T1).isInteger() || MVT(T1).isVector(); + + // Otherwise, they are two different non-iPTR types, they conflict. + return true; +} + +bool CheckOpcodeMatcher::isContradictoryImpl(const Matcher *M) const { + if (const CheckOpcodeMatcher *COM = dyn_cast<CheckOpcodeMatcher>(M)) { + // One node can't have two different opcodes! + // Note: pointer equality isn't enough here, we have to check the enum names + // to ensure that the nodes are for the same opcode. + return COM->getOpcode().getEnumName() != getOpcode().getEnumName(); + } + + // If the node has a known type, and if the type we're checking for is + // different, then we know they contradict. For example, a check for + // ISD::STORE will never be true at the same time a check for Type i32 is. + if (const CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(M)) { + // If checking for a result the opcode doesn't have, it can't match. + if (CT->getResNo() >= getOpcode().getNumResults()) + return true; + + MVT::SimpleValueType NodeType = getOpcode().getKnownType(CT->getResNo()); + if (NodeType != MVT::Other) + return TypesAreContradictory(NodeType, CT->getType()); + } + + return false; +} + +bool CheckTypeMatcher::isContradictoryImpl(const Matcher *M) const { + if (const CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(M)) + return TypesAreContradictory(getType(), CT->getType()); + return false; +} + +bool CheckChildTypeMatcher::isContradictoryImpl(const Matcher *M) const { + if (const CheckChildTypeMatcher *CC = dyn_cast<CheckChildTypeMatcher>(M)) { + // If the two checks are about different nodes, we don't know if they + // conflict! + if (CC->getChildNo() != getChildNo()) + return false; + + return TypesAreContradictory(getType(), CC->getType()); + } + return false; +} + +bool CheckIntegerMatcher::isContradictoryImpl(const Matcher *M) const { + if (const CheckIntegerMatcher *CIM = dyn_cast<CheckIntegerMatcher>(M)) + return CIM->getValue() != getValue(); + return false; +} + +bool CheckValueTypeMatcher::isContradictoryImpl(const Matcher *M) const { + if (const CheckValueTypeMatcher *CVT = dyn_cast<CheckValueTypeMatcher>(M)) + return CVT->getTypeName() != getTypeName(); + return false; +} + diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcher.h b/contrib/llvm/utils/TableGen/DAGISelMatcher.h new file mode 100644 index 0000000..99ebf98 --- /dev/null +++ b/contrib/llvm/utils/TableGen/DAGISelMatcher.h @@ -0,0 +1,1119 @@ +//===- DAGISelMatcher.h - Representation of DAG pattern matcher -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef TBLGEN_DAGISELMATCHER_H +#define TBLGEN_DAGISELMATCHER_H + +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Casting.h" + +namespace llvm { + struct CodeGenRegister; + class CodeGenDAGPatterns; + class Matcher; + class PatternToMatch; + class raw_ostream; + class ComplexPattern; + class Record; + class SDNodeInfo; + class TreePredicateFn; + class TreePattern; + +Matcher *ConvertPatternToMatcher(const PatternToMatch &Pattern,unsigned Variant, + const CodeGenDAGPatterns &CGP); +Matcher *OptimizeMatcher(Matcher *Matcher, const CodeGenDAGPatterns &CGP); +void EmitMatcherTable(const Matcher *Matcher, const CodeGenDAGPatterns &CGP, + raw_ostream &OS); + + +/// Matcher - Base class for all the the DAG ISel Matcher representation +/// nodes. +class Matcher { + // The next matcher node that is executed after this one. Null if this is the + // last stage of a match. + OwningPtr<Matcher> Next; + virtual void anchor(); +public: + enum KindTy { + // Matcher state manipulation. + Scope, // Push a checking scope. + RecordNode, // Record the current node. + RecordChild, // Record a child of the current node. + RecordMemRef, // Record the memref in the current node. + CaptureGlueInput, // If the current node has an input glue, save it. + MoveChild, // Move current node to specified child. + MoveParent, // Move current node to parent. + + // Predicate checking. + CheckSame, // Fail if not same as prev match. + CheckPatternPredicate, + CheckPredicate, // Fail if node predicate fails. + CheckOpcode, // Fail if not opcode. + SwitchOpcode, // Dispatch based on opcode. + CheckType, // Fail if not correct type. + SwitchType, // Dispatch based on type. + CheckChildType, // Fail if child has wrong type. + CheckInteger, // Fail if wrong val. + CheckCondCode, // Fail if not condcode. + CheckValueType, + CheckComplexPat, + CheckAndImm, + CheckOrImm, + CheckFoldableChainNode, + + // Node creation/emisssion. + EmitInteger, // Create a TargetConstant + EmitStringInteger, // Create a TargetConstant from a string. + EmitRegister, // Create a register. + EmitConvertToTarget, // Convert a imm/fpimm to target imm/fpimm + EmitMergeInputChains, // Merge together a chains for an input. + EmitCopyToReg, // Emit a copytoreg into a physreg. + EmitNode, // Create a DAG node + EmitNodeXForm, // Run a SDNodeXForm + MarkGlueResults, // Indicate which interior nodes have glue results. + CompleteMatch, // Finish a match and update the results. + MorphNodeTo // Build a node, finish a match and update results. + }; + const KindTy Kind; + +protected: + Matcher(KindTy K) : Kind(K) {} +public: + virtual ~Matcher() {} + + KindTy getKind() const { return Kind; } + + Matcher *getNext() { return Next.get(); } + const Matcher *getNext() const { return Next.get(); } + void setNext(Matcher *C) { Next.reset(C); } + Matcher *takeNext() { return Next.take(); } + + OwningPtr<Matcher> &getNextPtr() { return Next; } + + static inline bool classof(const Matcher *) { return true; } + + bool isEqual(const Matcher *M) const { + if (getKind() != M->getKind()) return false; + return isEqualImpl(M); + } + + unsigned getHash() const { + // Clear the high bit so we don't conflict with tombstones etc. + return ((getHashImpl() << 4) ^ getKind()) & (~0U>>1); + } + + /// isSafeToReorderWithPatternPredicate - Return true if it is safe to sink a + /// PatternPredicate node past this one. + virtual bool isSafeToReorderWithPatternPredicate() const { + return false; + } + + /// isSimplePredicateNode - Return true if this is a simple predicate that + /// operates on the node or its children without potential side effects or a + /// change of the current node. + bool isSimplePredicateNode() const { + switch (getKind()) { + default: return false; + case CheckSame: + case CheckPatternPredicate: + case CheckPredicate: + case CheckOpcode: + case CheckType: + case CheckChildType: + case CheckInteger: + case CheckCondCode: + case CheckValueType: + case CheckAndImm: + case CheckOrImm: + case CheckFoldableChainNode: + return true; + } + } + + /// isSimplePredicateOrRecordNode - Return true if this is a record node or + /// a simple predicate. + bool isSimplePredicateOrRecordNode() const { + return isSimplePredicateNode() || + getKind() == RecordNode || getKind() == RecordChild; + } + + /// unlinkNode - Unlink the specified node from this chain. If Other == this, + /// we unlink the next pointer and return it. Otherwise we unlink Other from + /// the list and return this. + Matcher *unlinkNode(Matcher *Other); + + /// canMoveBefore - Return true if this matcher is the same as Other, or if + /// we can move this matcher past all of the nodes in-between Other and this + /// node. Other must be equal to or before this. + bool canMoveBefore(const Matcher *Other) const; + + /// canMoveBefore - Return true if it is safe to move the current matcher + /// across the specified one. + bool canMoveBeforeNode(const Matcher *Other) const; + + /// isContradictory - Return true of these two matchers could never match on + /// the same node. + bool isContradictory(const Matcher *Other) const { + // Since this predicate is reflexive, we canonicalize the ordering so that + // we always match a node against nodes with kinds that are greater or equal + // to them. For example, we'll pass in a CheckType node as an argument to + // the CheckOpcode method, not the other way around. + if (getKind() < Other->getKind()) + return isContradictoryImpl(Other); + return Other->isContradictoryImpl(this); + } + + void print(raw_ostream &OS, unsigned indent = 0) const; + void printOne(raw_ostream &OS) const; + void dump() const; +protected: + virtual void printImpl(raw_ostream &OS, unsigned indent) const = 0; + virtual bool isEqualImpl(const Matcher *M) const = 0; + virtual unsigned getHashImpl() const = 0; + virtual bool isContradictoryImpl(const Matcher *M) const { return false; } +}; + +/// ScopeMatcher - This attempts to match each of its children to find the first +/// one that successfully matches. If one child fails, it tries the next child. +/// If none of the children match then this check fails. It never has a 'next'. +class ScopeMatcher : public Matcher { + SmallVector<Matcher*, 4> Children; +public: + ScopeMatcher(Matcher *const *children, unsigned numchildren) + : Matcher(Scope), Children(children, children+numchildren) { + } + virtual ~ScopeMatcher(); + + unsigned getNumChildren() const { return Children.size(); } + + Matcher *getChild(unsigned i) { return Children[i]; } + const Matcher *getChild(unsigned i) const { return Children[i]; } + + void resetChild(unsigned i, Matcher *N) { + delete Children[i]; + Children[i] = N; + } + + Matcher *takeChild(unsigned i) { + Matcher *Res = Children[i]; + Children[i] = 0; + return Res; + } + + void setNumChildren(unsigned NC) { + if (NC < Children.size()) { + // delete any children we're about to lose pointers to. + for (unsigned i = NC, e = Children.size(); i != e; ++i) + delete Children[i]; + } + Children.resize(NC); + } + + static inline bool classof(const Matcher *N) { + return N->getKind() == Scope; + } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { return false; } + virtual unsigned getHashImpl() const { return 12312; } +}; + +/// RecordMatcher - Save the current node in the operand list. +class RecordMatcher : public Matcher { + /// WhatFor - This is a string indicating why we're recording this. This + /// should only be used for comment generation not anything semantic. + std::string WhatFor; + + /// ResultNo - The slot number in the RecordedNodes vector that this will be, + /// just printed as a comment. + unsigned ResultNo; +public: + RecordMatcher(const std::string &whatfor, unsigned resultNo) + : Matcher(RecordNode), WhatFor(whatfor), ResultNo(resultNo) {} + + const std::string &getWhatFor() const { return WhatFor; } + unsigned getResultNo() const { return ResultNo; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == RecordNode; + } + + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { return true; } + virtual unsigned getHashImpl() const { return 0; } +}; + +/// RecordChildMatcher - Save a numbered child of the current node, or fail +/// the match if it doesn't exist. This is logically equivalent to: +/// MoveChild N + RecordNode + MoveParent. +class RecordChildMatcher : public Matcher { + unsigned ChildNo; + + /// WhatFor - This is a string indicating why we're recording this. This + /// should only be used for comment generation not anything semantic. + std::string WhatFor; + + /// ResultNo - The slot number in the RecordedNodes vector that this will be, + /// just printed as a comment. + unsigned ResultNo; +public: + RecordChildMatcher(unsigned childno, const std::string &whatfor, + unsigned resultNo) + : Matcher(RecordChild), ChildNo(childno), WhatFor(whatfor), + ResultNo(resultNo) {} + + unsigned getChildNo() const { return ChildNo; } + const std::string &getWhatFor() const { return WhatFor; } + unsigned getResultNo() const { return ResultNo; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == RecordChild; + } + + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return cast<RecordChildMatcher>(M)->getChildNo() == getChildNo(); + } + virtual unsigned getHashImpl() const { return getChildNo(); } +}; + +/// RecordMemRefMatcher - Save the current node's memref. +class RecordMemRefMatcher : public Matcher { +public: + RecordMemRefMatcher() : Matcher(RecordMemRef) {} + + static inline bool classof(const Matcher *N) { + return N->getKind() == RecordMemRef; + } + + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { return true; } + virtual unsigned getHashImpl() const { return 0; } +}; + + +/// CaptureGlueInputMatcher - If the current record has a glue input, record +/// it so that it is used as an input to the generated code. +class CaptureGlueInputMatcher : public Matcher { +public: + CaptureGlueInputMatcher() : Matcher(CaptureGlueInput) {} + + static inline bool classof(const Matcher *N) { + return N->getKind() == CaptureGlueInput; + } + + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { return true; } + virtual unsigned getHashImpl() const { return 0; } +}; + +/// MoveChildMatcher - This tells the interpreter to move into the +/// specified child node. +class MoveChildMatcher : public Matcher { + unsigned ChildNo; +public: + MoveChildMatcher(unsigned childNo) : Matcher(MoveChild), ChildNo(childNo) {} + + unsigned getChildNo() const { return ChildNo; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == MoveChild; + } + + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return cast<MoveChildMatcher>(M)->getChildNo() == getChildNo(); + } + virtual unsigned getHashImpl() const { return getChildNo(); } +}; + +/// MoveParentMatcher - This tells the interpreter to move to the parent +/// of the current node. +class MoveParentMatcher : public Matcher { +public: + MoveParentMatcher() : Matcher(MoveParent) {} + + static inline bool classof(const Matcher *N) { + return N->getKind() == MoveParent; + } + + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { return true; } + virtual unsigned getHashImpl() const { return 0; } +}; + +/// CheckSameMatcher - This checks to see if this node is exactly the same +/// node as the specified match that was recorded with 'Record'. This is used +/// when patterns have the same name in them, like '(mul GPR:$in, GPR:$in)'. +class CheckSameMatcher : public Matcher { + unsigned MatchNumber; +public: + CheckSameMatcher(unsigned matchnumber) + : Matcher(CheckSame), MatchNumber(matchnumber) {} + + unsigned getMatchNumber() const { return MatchNumber; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == CheckSame; + } + + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return cast<CheckSameMatcher>(M)->getMatchNumber() == getMatchNumber(); + } + virtual unsigned getHashImpl() const { return getMatchNumber(); } +}; + +/// CheckPatternPredicateMatcher - This checks the target-specific predicate +/// to see if the entire pattern is capable of matching. This predicate does +/// not take a node as input. This is used for subtarget feature checks etc. +class CheckPatternPredicateMatcher : public Matcher { + std::string Predicate; +public: + CheckPatternPredicateMatcher(StringRef predicate) + : Matcher(CheckPatternPredicate), Predicate(predicate) {} + + StringRef getPredicate() const { return Predicate; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == CheckPatternPredicate; + } + + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return cast<CheckPatternPredicateMatcher>(M)->getPredicate() == Predicate; + } + virtual unsigned getHashImpl() const; +}; + +/// CheckPredicateMatcher - This checks the target-specific predicate to +/// see if the node is acceptable. +class CheckPredicateMatcher : public Matcher { + TreePattern *Pred; +public: + CheckPredicateMatcher(const TreePredicateFn &pred); + + TreePredicateFn getPredicate() const; + + static inline bool classof(const Matcher *N) { + return N->getKind() == CheckPredicate; + } + + // TODO: Ok? + //virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return cast<CheckPredicateMatcher>(M)->Pred == Pred; + } + virtual unsigned getHashImpl() const; +}; + + +/// CheckOpcodeMatcher - This checks to see if the current node has the +/// specified opcode, if not it fails to match. +class CheckOpcodeMatcher : public Matcher { + const SDNodeInfo &Opcode; +public: + CheckOpcodeMatcher(const SDNodeInfo &opcode) + : Matcher(CheckOpcode), Opcode(opcode) {} + + const SDNodeInfo &getOpcode() const { return Opcode; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == CheckOpcode; + } + + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const; + virtual unsigned getHashImpl() const; + virtual bool isContradictoryImpl(const Matcher *M) const; +}; + +/// SwitchOpcodeMatcher - Switch based on the current node's opcode, dispatching +/// to one matcher per opcode. If the opcode doesn't match any of the cases, +/// then the match fails. This is semantically equivalent to a Scope node where +/// every child does a CheckOpcode, but is much faster. +class SwitchOpcodeMatcher : public Matcher { + SmallVector<std::pair<const SDNodeInfo*, Matcher*>, 8> Cases; +public: + SwitchOpcodeMatcher(const std::pair<const SDNodeInfo*, Matcher*> *cases, + unsigned numcases) + : Matcher(SwitchOpcode), Cases(cases, cases+numcases) {} + + static inline bool classof(const Matcher *N) { + return N->getKind() == SwitchOpcode; + } + + unsigned getNumCases() const { return Cases.size(); } + + const SDNodeInfo &getCaseOpcode(unsigned i) const { return *Cases[i].first; } + Matcher *getCaseMatcher(unsigned i) { return Cases[i].second; } + const Matcher *getCaseMatcher(unsigned i) const { return Cases[i].second; } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { return false; } + virtual unsigned getHashImpl() const { return 4123; } +}; + +/// CheckTypeMatcher - This checks to see if the current node has the +/// specified type at the specified result, if not it fails to match. +class CheckTypeMatcher : public Matcher { + MVT::SimpleValueType Type; + unsigned ResNo; +public: + CheckTypeMatcher(MVT::SimpleValueType type, unsigned resno) + : Matcher(CheckType), Type(type), ResNo(resno) {} + + MVT::SimpleValueType getType() const { return Type; } + unsigned getResNo() const { return ResNo; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == CheckType; + } + + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return cast<CheckTypeMatcher>(M)->Type == Type; + } + virtual unsigned getHashImpl() const { return Type; } + virtual bool isContradictoryImpl(const Matcher *M) const; +}; + +/// SwitchTypeMatcher - Switch based on the current node's type, dispatching +/// to one matcher per case. If the type doesn't match any of the cases, +/// then the match fails. This is semantically equivalent to a Scope node where +/// every child does a CheckType, but is much faster. +class SwitchTypeMatcher : public Matcher { + SmallVector<std::pair<MVT::SimpleValueType, Matcher*>, 8> Cases; +public: + SwitchTypeMatcher(const std::pair<MVT::SimpleValueType, Matcher*> *cases, + unsigned numcases) + : Matcher(SwitchType), Cases(cases, cases+numcases) {} + + static inline bool classof(const Matcher *N) { + return N->getKind() == SwitchType; + } + + unsigned getNumCases() const { return Cases.size(); } + + MVT::SimpleValueType getCaseType(unsigned i) const { return Cases[i].first; } + Matcher *getCaseMatcher(unsigned i) { return Cases[i].second; } + const Matcher *getCaseMatcher(unsigned i) const { return Cases[i].second; } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { return false; } + virtual unsigned getHashImpl() const { return 4123; } +}; + + +/// CheckChildTypeMatcher - This checks to see if a child node has the +/// specified type, if not it fails to match. +class CheckChildTypeMatcher : public Matcher { + unsigned ChildNo; + MVT::SimpleValueType Type; +public: + CheckChildTypeMatcher(unsigned childno, MVT::SimpleValueType type) + : Matcher(CheckChildType), ChildNo(childno), Type(type) {} + + unsigned getChildNo() const { return ChildNo; } + MVT::SimpleValueType getType() const { return Type; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == CheckChildType; + } + + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return cast<CheckChildTypeMatcher>(M)->ChildNo == ChildNo && + cast<CheckChildTypeMatcher>(M)->Type == Type; + } + virtual unsigned getHashImpl() const { return (Type << 3) | ChildNo; } + virtual bool isContradictoryImpl(const Matcher *M) const; +}; + + +/// CheckIntegerMatcher - This checks to see if the current node is a +/// ConstantSDNode with the specified integer value, if not it fails to match. +class CheckIntegerMatcher : public Matcher { + int64_t Value; +public: + CheckIntegerMatcher(int64_t value) + : Matcher(CheckInteger), Value(value) {} + + int64_t getValue() const { return Value; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == CheckInteger; + } + + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return cast<CheckIntegerMatcher>(M)->Value == Value; + } + virtual unsigned getHashImpl() const { return Value; } + virtual bool isContradictoryImpl(const Matcher *M) const; +}; + +/// CheckCondCodeMatcher - This checks to see if the current node is a +/// CondCodeSDNode with the specified condition, if not it fails to match. +class CheckCondCodeMatcher : public Matcher { + StringRef CondCodeName; +public: + CheckCondCodeMatcher(StringRef condcodename) + : Matcher(CheckCondCode), CondCodeName(condcodename) {} + + StringRef getCondCodeName() const { return CondCodeName; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == CheckCondCode; + } + + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return cast<CheckCondCodeMatcher>(M)->CondCodeName == CondCodeName; + } + virtual unsigned getHashImpl() const; +}; + +/// CheckValueTypeMatcher - This checks to see if the current node is a +/// VTSDNode with the specified type, if not it fails to match. +class CheckValueTypeMatcher : public Matcher { + StringRef TypeName; +public: + CheckValueTypeMatcher(StringRef type_name) + : Matcher(CheckValueType), TypeName(type_name) {} + + StringRef getTypeName() const { return TypeName; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == CheckValueType; + } + + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return cast<CheckValueTypeMatcher>(M)->TypeName == TypeName; + } + virtual unsigned getHashImpl() const; + bool isContradictoryImpl(const Matcher *M) const; +}; + + + +/// CheckComplexPatMatcher - This node runs the specified ComplexPattern on +/// the current node. +class CheckComplexPatMatcher : public Matcher { + const ComplexPattern &Pattern; + + /// MatchNumber - This is the recorded nodes slot that contains the node we + /// want to match against. + unsigned MatchNumber; + + /// Name - The name of the node we're matching, for comment emission. + std::string Name; + + /// FirstResult - This is the first slot in the RecordedNodes list that the + /// result of the match populates. + unsigned FirstResult; +public: + CheckComplexPatMatcher(const ComplexPattern &pattern, unsigned matchnumber, + const std::string &name, unsigned firstresult) + : Matcher(CheckComplexPat), Pattern(pattern), MatchNumber(matchnumber), + Name(name), FirstResult(firstresult) {} + + const ComplexPattern &getPattern() const { return Pattern; } + unsigned getMatchNumber() const { return MatchNumber; } + + const std::string getName() const { return Name; } + unsigned getFirstResult() const { return FirstResult; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == CheckComplexPat; + } + + // Not safe to move a pattern predicate past a complex pattern. + virtual bool isSafeToReorderWithPatternPredicate() const { return false; } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return &cast<CheckComplexPatMatcher>(M)->Pattern == &Pattern && + cast<CheckComplexPatMatcher>(M)->MatchNumber == MatchNumber; + } + virtual unsigned getHashImpl() const { + return (unsigned)(intptr_t)&Pattern ^ MatchNumber; + } +}; + +/// CheckAndImmMatcher - This checks to see if the current node is an 'and' +/// with something equivalent to the specified immediate. +class CheckAndImmMatcher : public Matcher { + int64_t Value; +public: + CheckAndImmMatcher(int64_t value) + : Matcher(CheckAndImm), Value(value) {} + + int64_t getValue() const { return Value; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == CheckAndImm; + } + + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return cast<CheckAndImmMatcher>(M)->Value == Value; + } + virtual unsigned getHashImpl() const { return Value; } +}; + +/// CheckOrImmMatcher - This checks to see if the current node is an 'and' +/// with something equivalent to the specified immediate. +class CheckOrImmMatcher : public Matcher { + int64_t Value; +public: + CheckOrImmMatcher(int64_t value) + : Matcher(CheckOrImm), Value(value) {} + + int64_t getValue() const { return Value; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == CheckOrImm; + } + + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return cast<CheckOrImmMatcher>(M)->Value == Value; + } + virtual unsigned getHashImpl() const { return Value; } +}; + +/// CheckFoldableChainNodeMatcher - This checks to see if the current node +/// (which defines a chain operand) is safe to fold into a larger pattern. +class CheckFoldableChainNodeMatcher : public Matcher { +public: + CheckFoldableChainNodeMatcher() + : Matcher(CheckFoldableChainNode) {} + + static inline bool classof(const Matcher *N) { + return N->getKind() == CheckFoldableChainNode; + } + + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { return true; } + virtual unsigned getHashImpl() const { return 0; } +}; + +/// EmitIntegerMatcher - This creates a new TargetConstant. +class EmitIntegerMatcher : public Matcher { + int64_t Val; + MVT::SimpleValueType VT; +public: + EmitIntegerMatcher(int64_t val, MVT::SimpleValueType vt) + : Matcher(EmitInteger), Val(val), VT(vt) {} + + int64_t getValue() const { return Val; } + MVT::SimpleValueType getVT() const { return VT; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == EmitInteger; + } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return cast<EmitIntegerMatcher>(M)->Val == Val && + cast<EmitIntegerMatcher>(M)->VT == VT; + } + virtual unsigned getHashImpl() const { return (Val << 4) | VT; } +}; + +/// EmitStringIntegerMatcher - A target constant whose value is represented +/// by a string. +class EmitStringIntegerMatcher : public Matcher { + std::string Val; + MVT::SimpleValueType VT; +public: + EmitStringIntegerMatcher(const std::string &val, MVT::SimpleValueType vt) + : Matcher(EmitStringInteger), Val(val), VT(vt) {} + + const std::string &getValue() const { return Val; } + MVT::SimpleValueType getVT() const { return VT; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == EmitStringInteger; + } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return cast<EmitStringIntegerMatcher>(M)->Val == Val && + cast<EmitStringIntegerMatcher>(M)->VT == VT; + } + virtual unsigned getHashImpl() const; +}; + +/// EmitRegisterMatcher - This creates a new TargetConstant. +class EmitRegisterMatcher : public Matcher { + /// Reg - The def for the register that we're emitting. If this is null, then + /// this is a reference to zero_reg. + const CodeGenRegister *Reg; + MVT::SimpleValueType VT; +public: + EmitRegisterMatcher(const CodeGenRegister *reg, MVT::SimpleValueType vt) + : Matcher(EmitRegister), Reg(reg), VT(vt) {} + + const CodeGenRegister *getReg() const { return Reg; } + MVT::SimpleValueType getVT() const { return VT; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == EmitRegister; + } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return cast<EmitRegisterMatcher>(M)->Reg == Reg && + cast<EmitRegisterMatcher>(M)->VT == VT; + } + virtual unsigned getHashImpl() const { + return ((unsigned)(intptr_t)Reg) << 4 | VT; + } +}; + +/// EmitConvertToTargetMatcher - Emit an operation that reads a specified +/// recorded node and converts it from being a ISD::Constant to +/// ISD::TargetConstant, likewise for ConstantFP. +class EmitConvertToTargetMatcher : public Matcher { + unsigned Slot; +public: + EmitConvertToTargetMatcher(unsigned slot) + : Matcher(EmitConvertToTarget), Slot(slot) {} + + unsigned getSlot() const { return Slot; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == EmitConvertToTarget; + } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return cast<EmitConvertToTargetMatcher>(M)->Slot == Slot; + } + virtual unsigned getHashImpl() const { return Slot; } +}; + +/// EmitMergeInputChainsMatcher - Emit a node that merges a list of input +/// chains together with a token factor. The list of nodes are the nodes in the +/// matched pattern that have chain input/outputs. This node adds all input +/// chains of these nodes if they are not themselves a node in the pattern. +class EmitMergeInputChainsMatcher : public Matcher { + SmallVector<unsigned, 3> ChainNodes; +public: + EmitMergeInputChainsMatcher(const unsigned *nodes, unsigned NumNodes) + : Matcher(EmitMergeInputChains), ChainNodes(nodes, nodes+NumNodes) {} + + unsigned getNumNodes() const { return ChainNodes.size(); } + + unsigned getNode(unsigned i) const { + assert(i < ChainNodes.size()); + return ChainNodes[i]; + } + + static inline bool classof(const Matcher *N) { + return N->getKind() == EmitMergeInputChains; + } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return cast<EmitMergeInputChainsMatcher>(M)->ChainNodes == ChainNodes; + } + virtual unsigned getHashImpl() const; +}; + +/// EmitCopyToRegMatcher - Emit a CopyToReg node from a value to a physreg, +/// pushing the chain and glue results. +/// +class EmitCopyToRegMatcher : public Matcher { + unsigned SrcSlot; // Value to copy into the physreg. + Record *DestPhysReg; +public: + EmitCopyToRegMatcher(unsigned srcSlot, Record *destPhysReg) + : Matcher(EmitCopyToReg), SrcSlot(srcSlot), DestPhysReg(destPhysReg) {} + + unsigned getSrcSlot() const { return SrcSlot; } + Record *getDestPhysReg() const { return DestPhysReg; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == EmitCopyToReg; + } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return cast<EmitCopyToRegMatcher>(M)->SrcSlot == SrcSlot && + cast<EmitCopyToRegMatcher>(M)->DestPhysReg == DestPhysReg; + } + virtual unsigned getHashImpl() const { + return SrcSlot ^ ((unsigned)(intptr_t)DestPhysReg << 4); + } +}; + + + +/// EmitNodeXFormMatcher - Emit an operation that runs an SDNodeXForm on a +/// recorded node and records the result. +class EmitNodeXFormMatcher : public Matcher { + unsigned Slot; + Record *NodeXForm; +public: + EmitNodeXFormMatcher(unsigned slot, Record *nodeXForm) + : Matcher(EmitNodeXForm), Slot(slot), NodeXForm(nodeXForm) {} + + unsigned getSlot() const { return Slot; } + Record *getNodeXForm() const { return NodeXForm; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == EmitNodeXForm; + } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return cast<EmitNodeXFormMatcher>(M)->Slot == Slot && + cast<EmitNodeXFormMatcher>(M)->NodeXForm == NodeXForm; + } + virtual unsigned getHashImpl() const { + return Slot ^ ((unsigned)(intptr_t)NodeXForm << 4); + } +}; + +/// EmitNodeMatcherCommon - Common class shared between EmitNode and +/// MorphNodeTo. +class EmitNodeMatcherCommon : public Matcher { + std::string OpcodeName; + const SmallVector<MVT::SimpleValueType, 3> VTs; + const SmallVector<unsigned, 6> Operands; + bool HasChain, HasInGlue, HasOutGlue, HasMemRefs; + + /// NumFixedArityOperands - If this is a fixed arity node, this is set to -1. + /// If this is a varidic node, this is set to the number of fixed arity + /// operands in the root of the pattern. The rest are appended to this node. + int NumFixedArityOperands; +public: + EmitNodeMatcherCommon(const std::string &opcodeName, + const MVT::SimpleValueType *vts, unsigned numvts, + const unsigned *operands, unsigned numops, + bool hasChain, bool hasInGlue, bool hasOutGlue, + bool hasmemrefs, + int numfixedarityoperands, bool isMorphNodeTo) + : Matcher(isMorphNodeTo ? MorphNodeTo : EmitNode), OpcodeName(opcodeName), + VTs(vts, vts+numvts), Operands(operands, operands+numops), + HasChain(hasChain), HasInGlue(hasInGlue), HasOutGlue(hasOutGlue), + HasMemRefs(hasmemrefs), NumFixedArityOperands(numfixedarityoperands) {} + + const std::string &getOpcodeName() const { return OpcodeName; } + + unsigned getNumVTs() const { return VTs.size(); } + MVT::SimpleValueType getVT(unsigned i) const { + assert(i < VTs.size()); + return VTs[i]; + } + + unsigned getNumOperands() const { return Operands.size(); } + unsigned getOperand(unsigned i) const { + assert(i < Operands.size()); + return Operands[i]; + } + + const SmallVectorImpl<MVT::SimpleValueType> &getVTList() const { return VTs; } + const SmallVectorImpl<unsigned> &getOperandList() const { return Operands; } + + + bool hasChain() const { return HasChain; } + bool hasInFlag() const { return HasInGlue; } + bool hasOutFlag() const { return HasOutGlue; } + bool hasMemRefs() const { return HasMemRefs; } + int getNumFixedArityOperands() const { return NumFixedArityOperands; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == EmitNode || N->getKind() == MorphNodeTo; + } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const; + virtual unsigned getHashImpl() const; +}; + +/// EmitNodeMatcher - This signals a successful match and generates a node. +class EmitNodeMatcher : public EmitNodeMatcherCommon { + virtual void anchor(); + unsigned FirstResultSlot; +public: + EmitNodeMatcher(const std::string &opcodeName, + const MVT::SimpleValueType *vts, unsigned numvts, + const unsigned *operands, unsigned numops, + bool hasChain, bool hasInFlag, bool hasOutFlag, + bool hasmemrefs, + int numfixedarityoperands, unsigned firstresultslot) + : EmitNodeMatcherCommon(opcodeName, vts, numvts, operands, numops, hasChain, + hasInFlag, hasOutFlag, hasmemrefs, + numfixedarityoperands, false), + FirstResultSlot(firstresultslot) {} + + unsigned getFirstResultSlot() const { return FirstResultSlot; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == EmitNode; + } + +}; + +class MorphNodeToMatcher : public EmitNodeMatcherCommon { + virtual void anchor(); + const PatternToMatch &Pattern; +public: + MorphNodeToMatcher(const std::string &opcodeName, + const MVT::SimpleValueType *vts, unsigned numvts, + const unsigned *operands, unsigned numops, + bool hasChain, bool hasInFlag, bool hasOutFlag, + bool hasmemrefs, + int numfixedarityoperands, const PatternToMatch &pattern) + : EmitNodeMatcherCommon(opcodeName, vts, numvts, operands, numops, hasChain, + hasInFlag, hasOutFlag, hasmemrefs, + numfixedarityoperands, true), + Pattern(pattern) { + } + + const PatternToMatch &getPattern() const { return Pattern; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == MorphNodeTo; + } +}; + +/// MarkGlueResultsMatcher - This node indicates which non-root nodes in the +/// pattern produce glue. This allows CompleteMatchMatcher to update them +/// with the output glue of the resultant code. +class MarkGlueResultsMatcher : public Matcher { + SmallVector<unsigned, 3> GlueResultNodes; +public: + MarkGlueResultsMatcher(const unsigned *nodes, unsigned NumNodes) + : Matcher(MarkGlueResults), GlueResultNodes(nodes, nodes+NumNodes) {} + + unsigned getNumNodes() const { return GlueResultNodes.size(); } + + unsigned getNode(unsigned i) const { + assert(i < GlueResultNodes.size()); + return GlueResultNodes[i]; + } + + static inline bool classof(const Matcher *N) { + return N->getKind() == MarkGlueResults; + } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return cast<MarkGlueResultsMatcher>(M)->GlueResultNodes == GlueResultNodes; + } + virtual unsigned getHashImpl() const; +}; + +/// CompleteMatchMatcher - Complete a match by replacing the results of the +/// pattern with the newly generated nodes. This also prints a comment +/// indicating the source and dest patterns. +class CompleteMatchMatcher : public Matcher { + SmallVector<unsigned, 2> Results; + const PatternToMatch &Pattern; +public: + CompleteMatchMatcher(const unsigned *results, unsigned numresults, + const PatternToMatch &pattern) + : Matcher(CompleteMatch), Results(results, results+numresults), + Pattern(pattern) {} + + unsigned getNumResults() const { return Results.size(); } + unsigned getResult(unsigned R) const { return Results[R]; } + const PatternToMatch &getPattern() const { return Pattern; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == CompleteMatch; + } + +private: + virtual void printImpl(raw_ostream &OS, unsigned indent) const; + virtual bool isEqualImpl(const Matcher *M) const { + return cast<CompleteMatchMatcher>(M)->Results == Results && + &cast<CompleteMatchMatcher>(M)->Pattern == &Pattern; + } + virtual unsigned getHashImpl() const; +}; + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp new file mode 100644 index 0000000..bd425a9 --- /dev/null +++ b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -0,0 +1,811 @@ +//===- DAGISelMatcherEmitter.cpp - Matcher Emitter ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains code to generate C++ code for a matcher. +// +//===----------------------------------------------------------------------===// + +#include "DAGISelMatcher.h" +#include "CodeGenDAGPatterns.h" +#include "llvm/TableGen/Record.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FormattedStream.h" +using namespace llvm; + +enum { + CommentIndent = 30 +}; + +// To reduce generated source code size. +static cl::opt<bool> +OmitComments("omit-comments", cl::desc("Do not generate comments"), + cl::init(false)); + +namespace { +class MatcherTableEmitter { + const CodeGenDAGPatterns &CGP; + + DenseMap<TreePattern *, unsigned> NodePredicateMap; + std::vector<TreePredicateFn> NodePredicates; + + StringMap<unsigned> PatternPredicateMap; + std::vector<std::string> PatternPredicates; + + DenseMap<const ComplexPattern*, unsigned> ComplexPatternMap; + std::vector<const ComplexPattern*> ComplexPatterns; + + + DenseMap<Record*, unsigned> NodeXFormMap; + std::vector<Record*> NodeXForms; + +public: + MatcherTableEmitter(const CodeGenDAGPatterns &cgp) + : CGP(cgp) {} + + unsigned EmitMatcherList(const Matcher *N, unsigned Indent, + unsigned StartIdx, formatted_raw_ostream &OS); + + void EmitPredicateFunctions(formatted_raw_ostream &OS); + + void EmitHistogram(const Matcher *N, formatted_raw_ostream &OS); +private: + unsigned EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, + formatted_raw_ostream &OS); + + unsigned getNodePredicate(TreePredicateFn Pred) { + unsigned &Entry = NodePredicateMap[Pred.getOrigPatFragRecord()]; + if (Entry == 0) { + NodePredicates.push_back(Pred); + Entry = NodePredicates.size(); + } + return Entry-1; + } + + unsigned getPatternPredicate(StringRef PredName) { + unsigned &Entry = PatternPredicateMap[PredName]; + if (Entry == 0) { + PatternPredicates.push_back(PredName.str()); + Entry = PatternPredicates.size(); + } + return Entry-1; + } + unsigned getComplexPat(const ComplexPattern &P) { + unsigned &Entry = ComplexPatternMap[&P]; + if (Entry == 0) { + ComplexPatterns.push_back(&P); + Entry = ComplexPatterns.size(); + } + return Entry-1; + } + + unsigned getNodeXFormID(Record *Rec) { + unsigned &Entry = NodeXFormMap[Rec]; + if (Entry == 0) { + NodeXForms.push_back(Rec); + Entry = NodeXForms.size(); + } + return Entry-1; + } + +}; +} // end anonymous namespace. + +static unsigned GetVBRSize(unsigned Val) { + if (Val <= 127) return 1; + + unsigned NumBytes = 0; + while (Val >= 128) { + Val >>= 7; + ++NumBytes; + } + return NumBytes+1; +} + +/// EmitVBRValue - Emit the specified value as a VBR, returning the number of +/// bytes emitted. +static uint64_t EmitVBRValue(uint64_t Val, raw_ostream &OS) { + if (Val <= 127) { + OS << Val << ", "; + return 1; + } + + uint64_t InVal = Val; + unsigned NumBytes = 0; + while (Val >= 128) { + OS << (Val&127) << "|128,"; + Val >>= 7; + ++NumBytes; + } + OS << Val; + if (!OmitComments) + OS << "/*" << InVal << "*/"; + OS << ", "; + return NumBytes+1; +} + +/// EmitMatcherOpcodes - Emit bytes for the specified matcher and return +/// the number of bytes emitted. +unsigned MatcherTableEmitter:: +EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, + formatted_raw_ostream &OS) { + OS.PadToColumn(Indent*2); + + switch (N->getKind()) { + case Matcher::Scope: { + const ScopeMatcher *SM = cast<ScopeMatcher>(N); + assert(SM->getNext() == 0 && "Shouldn't have next after scope"); + + unsigned StartIdx = CurrentIdx; + + // Emit all of the children. + for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i) { + if (i == 0) { + OS << "OPC_Scope, "; + ++CurrentIdx; + } else { + if (!OmitComments) { + OS << "/*" << CurrentIdx << "*/"; + OS.PadToColumn(Indent*2) << "/*Scope*/ "; + } else + OS.PadToColumn(Indent*2); + } + + // We need to encode the child and the offset of the failure code before + // emitting either of them. Handle this by buffering the output into a + // string while we get the size. Unfortunately, the offset of the + // children depends on the VBR size of the child, so for large children we + // have to iterate a bit. + SmallString<128> TmpBuf; + unsigned ChildSize = 0; + unsigned VBRSize = 0; + do { + VBRSize = GetVBRSize(ChildSize); + + TmpBuf.clear(); + raw_svector_ostream OS(TmpBuf); + formatted_raw_ostream FOS(OS); + ChildSize = EmitMatcherList(SM->getChild(i), Indent+1, + CurrentIdx+VBRSize, FOS); + } while (GetVBRSize(ChildSize) != VBRSize); + + assert(ChildSize != 0 && "Should not have a zero-sized child!"); + + CurrentIdx += EmitVBRValue(ChildSize, OS); + if (!OmitComments) { + OS << "/*->" << CurrentIdx+ChildSize << "*/"; + + if (i == 0) + OS.PadToColumn(CommentIndent) << "// " << SM->getNumChildren() + << " children in Scope"; + } + + OS << '\n' << TmpBuf.str(); + CurrentIdx += ChildSize; + } + + // Emit a zero as a sentinel indicating end of 'Scope'. + if (!OmitComments) + OS << "/*" << CurrentIdx << "*/"; + OS.PadToColumn(Indent*2) << "0, "; + if (!OmitComments) + OS << "/*End of Scope*/"; + OS << '\n'; + return CurrentIdx - StartIdx + 1; + } + + case Matcher::RecordNode: + OS << "OPC_RecordNode,"; + if (!OmitComments) + OS.PadToColumn(CommentIndent) << "// #" + << cast<RecordMatcher>(N)->getResultNo() << " = " + << cast<RecordMatcher>(N)->getWhatFor(); + OS << '\n'; + return 1; + + case Matcher::RecordChild: + OS << "OPC_RecordChild" << cast<RecordChildMatcher>(N)->getChildNo() + << ','; + if (!OmitComments) + OS.PadToColumn(CommentIndent) << "// #" + << cast<RecordChildMatcher>(N)->getResultNo() << " = " + << cast<RecordChildMatcher>(N)->getWhatFor(); + OS << '\n'; + return 1; + + case Matcher::RecordMemRef: + OS << "OPC_RecordMemRef,\n"; + return 1; + + case Matcher::CaptureGlueInput: + OS << "OPC_CaptureGlueInput,\n"; + return 1; + + case Matcher::MoveChild: + OS << "OPC_MoveChild, " << cast<MoveChildMatcher>(N)->getChildNo() << ",\n"; + return 2; + + case Matcher::MoveParent: + OS << "OPC_MoveParent,\n"; + return 1; + + case Matcher::CheckSame: + OS << "OPC_CheckSame, " + << cast<CheckSameMatcher>(N)->getMatchNumber() << ",\n"; + return 2; + + case Matcher::CheckPatternPredicate: { + StringRef Pred =cast<CheckPatternPredicateMatcher>(N)->getPredicate(); + OS << "OPC_CheckPatternPredicate, " << getPatternPredicate(Pred) << ','; + if (!OmitComments) + OS.PadToColumn(CommentIndent) << "// " << Pred; + OS << '\n'; + return 2; + } + case Matcher::CheckPredicate: { + TreePredicateFn Pred = cast<CheckPredicateMatcher>(N)->getPredicate(); + OS << "OPC_CheckPredicate, " << getNodePredicate(Pred) << ','; + if (!OmitComments) + OS.PadToColumn(CommentIndent) << "// " << Pred.getFnName(); + OS << '\n'; + return 2; + } + + case Matcher::CheckOpcode: + OS << "OPC_CheckOpcode, TARGET_VAL(" + << cast<CheckOpcodeMatcher>(N)->getOpcode().getEnumName() << "),\n"; + return 3; + + case Matcher::SwitchOpcode: + case Matcher::SwitchType: { + unsigned StartIdx = CurrentIdx; + + unsigned NumCases; + if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) { + OS << "OPC_SwitchOpcode "; + NumCases = SOM->getNumCases(); + } else { + OS << "OPC_SwitchType "; + NumCases = cast<SwitchTypeMatcher>(N)->getNumCases(); + } + + if (!OmitComments) + OS << "/*" << NumCases << " cases */"; + OS << ", "; + ++CurrentIdx; + + // For each case we emit the size, then the opcode, then the matcher. + for (unsigned i = 0, e = NumCases; i != e; ++i) { + const Matcher *Child; + unsigned IdxSize; + if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) { + Child = SOM->getCaseMatcher(i); + IdxSize = 2; // size of opcode in table is 2 bytes. + } else { + Child = cast<SwitchTypeMatcher>(N)->getCaseMatcher(i); + IdxSize = 1; // size of type in table is 1 byte. + } + + // We need to encode the opcode and the offset of the case code before + // emitting the case code. Handle this by buffering the output into a + // string while we get the size. Unfortunately, the offset of the + // children depends on the VBR size of the child, so for large children we + // have to iterate a bit. + SmallString<128> TmpBuf; + unsigned ChildSize = 0; + unsigned VBRSize = 0; + do { + VBRSize = GetVBRSize(ChildSize); + + TmpBuf.clear(); + raw_svector_ostream OS(TmpBuf); + formatted_raw_ostream FOS(OS); + ChildSize = EmitMatcherList(Child, Indent+1, CurrentIdx+VBRSize+IdxSize, + FOS); + } while (GetVBRSize(ChildSize) != VBRSize); + + assert(ChildSize != 0 && "Should not have a zero-sized child!"); + + if (i != 0) { + OS.PadToColumn(Indent*2); + if (!OmitComments) + OS << (isa<SwitchOpcodeMatcher>(N) ? + "/*SwitchOpcode*/ " : "/*SwitchType*/ "); + } + + // Emit the VBR. + CurrentIdx += EmitVBRValue(ChildSize, OS); + + OS << ' '; + if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) + OS << "TARGET_VAL(" << SOM->getCaseOpcode(i).getEnumName() << "),"; + else + OS << getEnumName(cast<SwitchTypeMatcher>(N)->getCaseType(i)) << ','; + + CurrentIdx += IdxSize; + + if (!OmitComments) + OS << "// ->" << CurrentIdx+ChildSize; + OS << '\n'; + OS << TmpBuf.str(); + CurrentIdx += ChildSize; + } + + // Emit the final zero to terminate the switch. + OS.PadToColumn(Indent*2) << "0, "; + if (!OmitComments) + OS << (isa<SwitchOpcodeMatcher>(N) ? + "// EndSwitchOpcode" : "// EndSwitchType"); + + OS << '\n'; + ++CurrentIdx; + return CurrentIdx-StartIdx; + } + + case Matcher::CheckType: + assert(cast<CheckTypeMatcher>(N)->getResNo() == 0 && + "FIXME: Add support for CheckType of resno != 0"); + OS << "OPC_CheckType, " + << getEnumName(cast<CheckTypeMatcher>(N)->getType()) << ",\n"; + return 2; + + case Matcher::CheckChildType: + OS << "OPC_CheckChild" + << cast<CheckChildTypeMatcher>(N)->getChildNo() << "Type, " + << getEnumName(cast<CheckChildTypeMatcher>(N)->getType()) << ",\n"; + return 2; + + case Matcher::CheckInteger: { + OS << "OPC_CheckInteger, "; + unsigned Bytes=1+EmitVBRValue(cast<CheckIntegerMatcher>(N)->getValue(), OS); + OS << '\n'; + return Bytes; + } + case Matcher::CheckCondCode: + OS << "OPC_CheckCondCode, ISD::" + << cast<CheckCondCodeMatcher>(N)->getCondCodeName() << ",\n"; + return 2; + + case Matcher::CheckValueType: + OS << "OPC_CheckValueType, MVT::" + << cast<CheckValueTypeMatcher>(N)->getTypeName() << ",\n"; + return 2; + + case Matcher::CheckComplexPat: { + const CheckComplexPatMatcher *CCPM = cast<CheckComplexPatMatcher>(N); + const ComplexPattern &Pattern = CCPM->getPattern(); + OS << "OPC_CheckComplexPat, /*CP*/" << getComplexPat(Pattern) << ", /*#*/" + << CCPM->getMatchNumber() << ','; + + if (!OmitComments) { + OS.PadToColumn(CommentIndent) << "// " << Pattern.getSelectFunc(); + OS << ":$" << CCPM->getName(); + for (unsigned i = 0, e = Pattern.getNumOperands(); i != e; ++i) + OS << " #" << CCPM->getFirstResult()+i; + + if (Pattern.hasProperty(SDNPHasChain)) + OS << " + chain result"; + } + OS << '\n'; + return 3; + } + + case Matcher::CheckAndImm: { + OS << "OPC_CheckAndImm, "; + unsigned Bytes=1+EmitVBRValue(cast<CheckAndImmMatcher>(N)->getValue(), OS); + OS << '\n'; + return Bytes; + } + + case Matcher::CheckOrImm: { + OS << "OPC_CheckOrImm, "; + unsigned Bytes = 1+EmitVBRValue(cast<CheckOrImmMatcher>(N)->getValue(), OS); + OS << '\n'; + return Bytes; + } + + case Matcher::CheckFoldableChainNode: + OS << "OPC_CheckFoldableChainNode,\n"; + return 1; + + case Matcher::EmitInteger: { + int64_t Val = cast<EmitIntegerMatcher>(N)->getValue(); + OS << "OPC_EmitInteger, " + << getEnumName(cast<EmitIntegerMatcher>(N)->getVT()) << ", "; + unsigned Bytes = 2+EmitVBRValue(Val, OS); + OS << '\n'; + return Bytes; + } + case Matcher::EmitStringInteger: { + const std::string &Val = cast<EmitStringIntegerMatcher>(N)->getValue(); + // These should always fit into one byte. + OS << "OPC_EmitInteger, " + << getEnumName(cast<EmitStringIntegerMatcher>(N)->getVT()) << ", " + << Val << ",\n"; + return 3; + } + + case Matcher::EmitRegister: { + const EmitRegisterMatcher *Matcher = cast<EmitRegisterMatcher>(N); + const CodeGenRegister *Reg = Matcher->getReg(); + // If the enum value of the register is larger than one byte can handle, + // use EmitRegister2. + if (Reg && Reg->EnumValue > 255) { + OS << "OPC_EmitRegister2, " << getEnumName(Matcher->getVT()) << ", "; + OS << "TARGET_VAL(" << getQualifiedName(Reg->TheDef) << "),\n"; + return 4; + } else { + OS << "OPC_EmitRegister, " << getEnumName(Matcher->getVT()) << ", "; + if (Reg) { + OS << getQualifiedName(Reg->TheDef) << ",\n"; + } else { + OS << "0 "; + if (!OmitComments) + OS << "/*zero_reg*/"; + OS << ",\n"; + } + return 3; + } + } + + case Matcher::EmitConvertToTarget: + OS << "OPC_EmitConvertToTarget, " + << cast<EmitConvertToTargetMatcher>(N)->getSlot() << ",\n"; + return 2; + + case Matcher::EmitMergeInputChains: { + const EmitMergeInputChainsMatcher *MN = + cast<EmitMergeInputChainsMatcher>(N); + + // Handle the specialized forms OPC_EmitMergeInputChains1_0 and 1_1. + if (MN->getNumNodes() == 1 && MN->getNode(0) < 2) { + OS << "OPC_EmitMergeInputChains1_" << MN->getNode(0) << ",\n"; + return 1; + } + + OS << "OPC_EmitMergeInputChains, " << MN->getNumNodes() << ", "; + for (unsigned i = 0, e = MN->getNumNodes(); i != e; ++i) + OS << MN->getNode(i) << ", "; + OS << '\n'; + return 2+MN->getNumNodes(); + } + case Matcher::EmitCopyToReg: + OS << "OPC_EmitCopyToReg, " + << cast<EmitCopyToRegMatcher>(N)->getSrcSlot() << ", " + << getQualifiedName(cast<EmitCopyToRegMatcher>(N)->getDestPhysReg()) + << ",\n"; + return 3; + case Matcher::EmitNodeXForm: { + const EmitNodeXFormMatcher *XF = cast<EmitNodeXFormMatcher>(N); + OS << "OPC_EmitNodeXForm, " << getNodeXFormID(XF->getNodeXForm()) << ", " + << XF->getSlot() << ','; + if (!OmitComments) + OS.PadToColumn(CommentIndent) << "// "<<XF->getNodeXForm()->getName(); + OS <<'\n'; + return 3; + } + + case Matcher::EmitNode: + case Matcher::MorphNodeTo: { + const EmitNodeMatcherCommon *EN = cast<EmitNodeMatcherCommon>(N); + OS << (isa<EmitNodeMatcher>(EN) ? "OPC_EmitNode" : "OPC_MorphNodeTo"); + OS << ", TARGET_VAL(" << EN->getOpcodeName() << "), 0"; + + if (EN->hasChain()) OS << "|OPFL_Chain"; + if (EN->hasInFlag()) OS << "|OPFL_GlueInput"; + if (EN->hasOutFlag()) OS << "|OPFL_GlueOutput"; + if (EN->hasMemRefs()) OS << "|OPFL_MemRefs"; + if (EN->getNumFixedArityOperands() != -1) + OS << "|OPFL_Variadic" << EN->getNumFixedArityOperands(); + OS << ",\n"; + + OS.PadToColumn(Indent*2+4) << EN->getNumVTs(); + if (!OmitComments) + OS << "/*#VTs*/"; + OS << ", "; + for (unsigned i = 0, e = EN->getNumVTs(); i != e; ++i) + OS << getEnumName(EN->getVT(i)) << ", "; + + OS << EN->getNumOperands(); + if (!OmitComments) + OS << "/*#Ops*/"; + OS << ", "; + unsigned NumOperandBytes = 0; + for (unsigned i = 0, e = EN->getNumOperands(); i != e; ++i) + NumOperandBytes += EmitVBRValue(EN->getOperand(i), OS); + + if (!OmitComments) { + // Print the result #'s for EmitNode. + if (const EmitNodeMatcher *E = dyn_cast<EmitNodeMatcher>(EN)) { + if (unsigned NumResults = EN->getNumVTs()) { + OS.PadToColumn(CommentIndent) << "// Results = "; + unsigned First = E->getFirstResultSlot(); + for (unsigned i = 0; i != NumResults; ++i) + OS << "#" << First+i << " "; + } + } + OS << '\n'; + + if (const MorphNodeToMatcher *SNT = dyn_cast<MorphNodeToMatcher>(N)) { + OS.PadToColumn(Indent*2) << "// Src: " + << *SNT->getPattern().getSrcPattern() << " - Complexity = " + << SNT->getPattern().getPatternComplexity(CGP) << '\n'; + OS.PadToColumn(Indent*2) << "// Dst: " + << *SNT->getPattern().getDstPattern() << '\n'; + } + } else + OS << '\n'; + + return 6+EN->getNumVTs()+NumOperandBytes; + } + case Matcher::MarkGlueResults: { + const MarkGlueResultsMatcher *CFR = cast<MarkGlueResultsMatcher>(N); + OS << "OPC_MarkGlueResults, " << CFR->getNumNodes() << ", "; + unsigned NumOperandBytes = 0; + for (unsigned i = 0, e = CFR->getNumNodes(); i != e; ++i) + NumOperandBytes += EmitVBRValue(CFR->getNode(i), OS); + OS << '\n'; + return 2+NumOperandBytes; + } + case Matcher::CompleteMatch: { + const CompleteMatchMatcher *CM = cast<CompleteMatchMatcher>(N); + OS << "OPC_CompleteMatch, " << CM->getNumResults() << ", "; + unsigned NumResultBytes = 0; + for (unsigned i = 0, e = CM->getNumResults(); i != e; ++i) + NumResultBytes += EmitVBRValue(CM->getResult(i), OS); + OS << '\n'; + if (!OmitComments) { + OS.PadToColumn(Indent*2) << "// Src: " + << *CM->getPattern().getSrcPattern() << " - Complexity = " + << CM->getPattern().getPatternComplexity(CGP) << '\n'; + OS.PadToColumn(Indent*2) << "// Dst: " + << *CM->getPattern().getDstPattern(); + } + OS << '\n'; + return 2 + NumResultBytes; + } + } + llvm_unreachable("Unreachable"); +} + +/// EmitMatcherList - Emit the bytes for the specified matcher subtree. +unsigned MatcherTableEmitter:: +EmitMatcherList(const Matcher *N, unsigned Indent, unsigned CurrentIdx, + formatted_raw_ostream &OS) { + unsigned Size = 0; + while (N) { + if (!OmitComments) + OS << "/*" << CurrentIdx << "*/"; + unsigned MatcherSize = EmitMatcher(N, Indent, CurrentIdx, OS); + Size += MatcherSize; + CurrentIdx += MatcherSize; + + // If there are other nodes in this list, iterate to them, otherwise we're + // done. + N = N->getNext(); + } + return Size; +} + +void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { + // Emit pattern predicates. + if (!PatternPredicates.empty()) { + OS << "bool CheckPatternPredicate(unsigned PredNo) const {\n"; + OS << " switch (PredNo) {\n"; + OS << " default: llvm_unreachable(\"Invalid predicate in table?\");\n"; + for (unsigned i = 0, e = PatternPredicates.size(); i != e; ++i) + OS << " case " << i << ": return " << PatternPredicates[i] << ";\n"; + OS << " }\n"; + OS << "}\n\n"; + } + + // Emit Node predicates. + // FIXME: Annoyingly, these are stored by name, which we never even emit. Yay? + StringMap<TreePattern*> PFsByName; + + for (CodeGenDAGPatterns::pf_iterator I = CGP.pf_begin(), E = CGP.pf_end(); + I != E; ++I) + PFsByName[I->first->getName()] = I->second; + + if (!NodePredicates.empty()) { + OS << "bool CheckNodePredicate(SDNode *Node, unsigned PredNo) const {\n"; + OS << " switch (PredNo) {\n"; + OS << " default: llvm_unreachable(\"Invalid predicate in table?\");\n"; + for (unsigned i = 0, e = NodePredicates.size(); i != e; ++i) { + // Emit the predicate code corresponding to this pattern. + TreePredicateFn PredFn = NodePredicates[i]; + + assert(!PredFn.isAlwaysTrue() && "No code in this predicate"); + OS << " case " << i << ": { // " << NodePredicates[i].getFnName() <<'\n'; + + OS << PredFn.getCodeToRunOnSDNode() << "\n }\n"; + } + OS << " }\n"; + OS << "}\n\n"; + } + + // Emit CompletePattern matchers. + // FIXME: This should be const. + if (!ComplexPatterns.empty()) { + OS << "bool CheckComplexPattern(SDNode *Root, SDNode *Parent, SDValue N,\n"; + OS << " unsigned PatternNo,\n"; + OS << " SmallVectorImpl<std::pair<SDValue, SDNode*> > &Result) {\n"; + OS << " unsigned NextRes = Result.size();\n"; + OS << " switch (PatternNo) {\n"; + OS << " default: llvm_unreachable(\"Invalid pattern # in table?\");\n"; + for (unsigned i = 0, e = ComplexPatterns.size(); i != e; ++i) { + const ComplexPattern &P = *ComplexPatterns[i]; + unsigned NumOps = P.getNumOperands(); + + if (P.hasProperty(SDNPHasChain)) + ++NumOps; // Get the chained node too. + + OS << " case " << i << ":\n"; + OS << " Result.resize(NextRes+" << NumOps << ");\n"; + OS << " return " << P.getSelectFunc(); + + OS << "("; + // If the complex pattern wants the root of the match, pass it in as the + // first argument. + if (P.hasProperty(SDNPWantRoot)) + OS << "Root, "; + + // If the complex pattern wants the parent of the operand being matched, + // pass it in as the next argument. + if (P.hasProperty(SDNPWantParent)) + OS << "Parent, "; + + OS << "N"; + for (unsigned i = 0; i != NumOps; ++i) + OS << ", Result[NextRes+" << i << "].first"; + OS << ");\n"; + } + OS << " }\n"; + OS << "}\n\n"; + } + + + // Emit SDNodeXForm handlers. + // FIXME: This should be const. + if (!NodeXForms.empty()) { + OS << "SDValue RunSDNodeXForm(SDValue V, unsigned XFormNo) {\n"; + OS << " switch (XFormNo) {\n"; + OS << " default: llvm_unreachable(\"Invalid xform # in table?\");\n"; + + // FIXME: The node xform could take SDValue's instead of SDNode*'s. + for (unsigned i = 0, e = NodeXForms.size(); i != e; ++i) { + const CodeGenDAGPatterns::NodeXForm &Entry = + CGP.getSDNodeTransform(NodeXForms[i]); + + Record *SDNode = Entry.first; + const std::string &Code = Entry.second; + + OS << " case " << i << ": { "; + if (!OmitComments) + OS << "// " << NodeXForms[i]->getName(); + OS << '\n'; + + std::string ClassName = CGP.getSDNodeInfo(SDNode).getSDClassName(); + if (ClassName == "SDNode") + OS << " SDNode *N = V.getNode();\n"; + else + OS << " " << ClassName << " *N = cast<" << ClassName + << ">(V.getNode());\n"; + OS << Code << "\n }\n"; + } + OS << " }\n"; + OS << "}\n\n"; + } +} + +static void BuildHistogram(const Matcher *M, std::vector<unsigned> &OpcodeFreq){ + for (; M != 0; M = M->getNext()) { + // Count this node. + if (unsigned(M->getKind()) >= OpcodeFreq.size()) + OpcodeFreq.resize(M->getKind()+1); + OpcodeFreq[M->getKind()]++; + + // Handle recursive nodes. + if (const ScopeMatcher *SM = dyn_cast<ScopeMatcher>(M)) { + for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i) + BuildHistogram(SM->getChild(i), OpcodeFreq); + } else if (const SwitchOpcodeMatcher *SOM = + dyn_cast<SwitchOpcodeMatcher>(M)) { + for (unsigned i = 0, e = SOM->getNumCases(); i != e; ++i) + BuildHistogram(SOM->getCaseMatcher(i), OpcodeFreq); + } else if (const SwitchTypeMatcher *STM = dyn_cast<SwitchTypeMatcher>(M)) { + for (unsigned i = 0, e = STM->getNumCases(); i != e; ++i) + BuildHistogram(STM->getCaseMatcher(i), OpcodeFreq); + } + } +} + +void MatcherTableEmitter::EmitHistogram(const Matcher *M, + formatted_raw_ostream &OS) { + if (OmitComments) + return; + + std::vector<unsigned> OpcodeFreq; + BuildHistogram(M, OpcodeFreq); + + OS << " // Opcode Histogram:\n"; + for (unsigned i = 0, e = OpcodeFreq.size(); i != e; ++i) { + OS << " // #"; + switch ((Matcher::KindTy)i) { + case Matcher::Scope: OS << "OPC_Scope"; break; + case Matcher::RecordNode: OS << "OPC_RecordNode"; break; + case Matcher::RecordChild: OS << "OPC_RecordChild"; break; + case Matcher::RecordMemRef: OS << "OPC_RecordMemRef"; break; + case Matcher::CaptureGlueInput: OS << "OPC_CaptureGlueInput"; break; + case Matcher::MoveChild: OS << "OPC_MoveChild"; break; + case Matcher::MoveParent: OS << "OPC_MoveParent"; break; + case Matcher::CheckSame: OS << "OPC_CheckSame"; break; + case Matcher::CheckPatternPredicate: + OS << "OPC_CheckPatternPredicate"; break; + case Matcher::CheckPredicate: OS << "OPC_CheckPredicate"; break; + case Matcher::CheckOpcode: OS << "OPC_CheckOpcode"; break; + case Matcher::SwitchOpcode: OS << "OPC_SwitchOpcode"; break; + case Matcher::CheckType: OS << "OPC_CheckType"; break; + case Matcher::SwitchType: OS << "OPC_SwitchType"; break; + case Matcher::CheckChildType: OS << "OPC_CheckChildType"; break; + case Matcher::CheckInteger: OS << "OPC_CheckInteger"; break; + case Matcher::CheckCondCode: OS << "OPC_CheckCondCode"; break; + case Matcher::CheckValueType: OS << "OPC_CheckValueType"; break; + case Matcher::CheckComplexPat: OS << "OPC_CheckComplexPat"; break; + case Matcher::CheckAndImm: OS << "OPC_CheckAndImm"; break; + case Matcher::CheckOrImm: OS << "OPC_CheckOrImm"; break; + case Matcher::CheckFoldableChainNode: + OS << "OPC_CheckFoldableChainNode"; break; + case Matcher::EmitInteger: OS << "OPC_EmitInteger"; break; + case Matcher::EmitStringInteger: OS << "OPC_EmitStringInteger"; break; + case Matcher::EmitRegister: OS << "OPC_EmitRegister"; break; + case Matcher::EmitConvertToTarget: OS << "OPC_EmitConvertToTarget"; break; + case Matcher::EmitMergeInputChains: OS << "OPC_EmitMergeInputChains"; break; + case Matcher::EmitCopyToReg: OS << "OPC_EmitCopyToReg"; break; + case Matcher::EmitNode: OS << "OPC_EmitNode"; break; + case Matcher::MorphNodeTo: OS << "OPC_MorphNodeTo"; break; + case Matcher::EmitNodeXForm: OS << "OPC_EmitNodeXForm"; break; + case Matcher::MarkGlueResults: OS << "OPC_MarkGlueResults"; break; + case Matcher::CompleteMatch: OS << "OPC_CompleteMatch"; break; + } + + OS.PadToColumn(40) << " = " << OpcodeFreq[i] << '\n'; + } + OS << '\n'; +} + + +void llvm::EmitMatcherTable(const Matcher *TheMatcher, + const CodeGenDAGPatterns &CGP, + raw_ostream &O) { + formatted_raw_ostream OS(O); + + OS << "// The main instruction selector code.\n"; + OS << "SDNode *SelectCode(SDNode *N) {\n"; + + MatcherTableEmitter MatcherEmitter(CGP); + + OS << " // Some target values are emitted as 2 bytes, TARGET_VAL handles\n"; + OS << " // this.\n"; + OS << " #define TARGET_VAL(X) X & 255, unsigned(X) >> 8\n"; + OS << " static const unsigned char MatcherTable[] = {\n"; + unsigned TotalSize = MatcherEmitter.EmitMatcherList(TheMatcher, 5, 0, OS); + OS << " 0\n }; // Total Array size is " << (TotalSize+1) << " bytes\n\n"; + + MatcherEmitter.EmitHistogram(TheMatcher, OS); + + OS << " #undef TARGET_VAL\n"; + OS << " return SelectCodeCommon(N, MatcherTable,sizeof(MatcherTable));\n}\n"; + OS << '\n'; + + // Next up, emit the function for node and pattern predicates: + MatcherEmitter.EmitPredicateFunctions(OS); +} diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp new file mode 100644 index 0000000..2ac7b87 --- /dev/null +++ b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp @@ -0,0 +1,951 @@ +//===- DAGISelMatcherGen.cpp - Matcher generator --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DAGISelMatcher.h" +#include "CodeGenDAGPatterns.h" +#include "CodeGenRegisters.h" +#include "llvm/TableGen/Record.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include <utility> +using namespace llvm; + + +/// getRegisterValueType - Look up and return the ValueType of the specified +/// register. If the register is a member of multiple register classes which +/// have different associated types, return MVT::Other. +static MVT::SimpleValueType getRegisterValueType(Record *R, + const CodeGenTarget &T) { + bool FoundRC = false; + MVT::SimpleValueType VT = MVT::Other; + const CodeGenRegister *Reg = T.getRegBank().getReg(R); + ArrayRef<CodeGenRegisterClass*> RCs = T.getRegBank().getRegClasses(); + + for (unsigned rc = 0, e = RCs.size(); rc != e; ++rc) { + const CodeGenRegisterClass &RC = *RCs[rc]; + if (!RC.contains(Reg)) + continue; + + if (!FoundRC) { + FoundRC = true; + VT = RC.getValueTypeNum(0); + continue; + } + + // If this occurs in multiple register classes, they all have to agree. + assert(VT == RC.getValueTypeNum(0)); + } + return VT; +} + + +namespace { + class MatcherGen { + const PatternToMatch &Pattern; + const CodeGenDAGPatterns &CGP; + + /// PatWithNoTypes - This is a clone of Pattern.getSrcPattern() that starts + /// out with all of the types removed. This allows us to insert type checks + /// as we scan the tree. + TreePatternNode *PatWithNoTypes; + + /// VariableMap - A map from variable names ('$dst') to the recorded operand + /// number that they were captured as. These are biased by 1 to make + /// insertion easier. + StringMap<unsigned> VariableMap; + + /// NextRecordedOperandNo - As we emit opcodes to record matched values in + /// the RecordedNodes array, this keeps track of which slot will be next to + /// record into. + unsigned NextRecordedOperandNo; + + /// MatchedChainNodes - This maintains the position in the recorded nodes + /// array of all of the recorded input nodes that have chains. + SmallVector<unsigned, 2> MatchedChainNodes; + + /// MatchedGlueResultNodes - This maintains the position in the recorded + /// nodes array of all of the recorded input nodes that have glue results. + SmallVector<unsigned, 2> MatchedGlueResultNodes; + + /// MatchedComplexPatterns - This maintains a list of all of the + /// ComplexPatterns that we need to check. The patterns are known to have + /// names which were recorded. The second element of each pair is the first + /// slot number that the OPC_CheckComplexPat opcode drops the matched + /// results into. + SmallVector<std::pair<const TreePatternNode*, + unsigned>, 2> MatchedComplexPatterns; + + /// PhysRegInputs - List list has an entry for each explicitly specified + /// physreg input to the pattern. The first elt is the Register node, the + /// second is the recorded slot number the input pattern match saved it in. + SmallVector<std::pair<Record*, unsigned>, 2> PhysRegInputs; + + /// Matcher - This is the top level of the generated matcher, the result. + Matcher *TheMatcher; + + /// CurPredicate - As we emit matcher nodes, this points to the latest check + /// which should have future checks stuck into its Next position. + Matcher *CurPredicate; + public: + MatcherGen(const PatternToMatch &pattern, const CodeGenDAGPatterns &cgp); + + ~MatcherGen() { + delete PatWithNoTypes; + } + + bool EmitMatcherCode(unsigned Variant); + void EmitResultCode(); + + Matcher *GetMatcher() const { return TheMatcher; } + private: + void AddMatcher(Matcher *NewNode); + void InferPossibleTypes(); + + // Matcher Generation. + void EmitMatchCode(const TreePatternNode *N, TreePatternNode *NodeNoTypes); + void EmitLeafMatchCode(const TreePatternNode *N); + void EmitOperatorMatchCode(const TreePatternNode *N, + TreePatternNode *NodeNoTypes); + + // Result Code Generation. + unsigned getNamedArgumentSlot(StringRef Name) { + unsigned VarMapEntry = VariableMap[Name]; + assert(VarMapEntry != 0 && + "Variable referenced but not defined and not caught earlier!"); + return VarMapEntry-1; + } + + /// GetInstPatternNode - Get the pattern for an instruction. + const TreePatternNode *GetInstPatternNode(const DAGInstruction &Ins, + const TreePatternNode *N); + + void EmitResultOperand(const TreePatternNode *N, + SmallVectorImpl<unsigned> &ResultOps); + void EmitResultOfNamedOperand(const TreePatternNode *N, + SmallVectorImpl<unsigned> &ResultOps); + void EmitResultLeafAsOperand(const TreePatternNode *N, + SmallVectorImpl<unsigned> &ResultOps); + void EmitResultInstructionAsOperand(const TreePatternNode *N, + SmallVectorImpl<unsigned> &ResultOps); + void EmitResultSDNodeXFormAsOperand(const TreePatternNode *N, + SmallVectorImpl<unsigned> &ResultOps); + }; + +} // end anon namespace. + +MatcherGen::MatcherGen(const PatternToMatch &pattern, + const CodeGenDAGPatterns &cgp) +: Pattern(pattern), CGP(cgp), NextRecordedOperandNo(0), + TheMatcher(0), CurPredicate(0) { + // We need to produce the matcher tree for the patterns source pattern. To do + // this we need to match the structure as well as the types. To do the type + // matching, we want to figure out the fewest number of type checks we need to + // emit. For example, if there is only one integer type supported by a + // target, there should be no type comparisons at all for integer patterns! + // + // To figure out the fewest number of type checks needed, clone the pattern, + // remove the types, then perform type inference on the pattern as a whole. + // If there are unresolved types, emit an explicit check for those types, + // apply the type to the tree, then rerun type inference. Iterate until all + // types are resolved. + // + PatWithNoTypes = Pattern.getSrcPattern()->clone(); + PatWithNoTypes->RemoveAllTypes(); + + // If there are types that are manifestly known, infer them. + InferPossibleTypes(); +} + +/// InferPossibleTypes - As we emit the pattern, we end up generating type +/// checks and applying them to the 'PatWithNoTypes' tree. As we do this, we +/// want to propagate implied types as far throughout the tree as possible so +/// that we avoid doing redundant type checks. This does the type propagation. +void MatcherGen::InferPossibleTypes() { + // TP - Get *SOME* tree pattern, we don't care which. It is only used for + // diagnostics, which we know are impossible at this point. + TreePattern &TP = *CGP.pf_begin()->second; + + try { + bool MadeChange = true; + while (MadeChange) + MadeChange = PatWithNoTypes->ApplyTypeConstraints(TP, + true/*Ignore reg constraints*/); + } catch (...) { + errs() << "Type constraint application shouldn't fail!"; + abort(); + } +} + + +/// AddMatcher - Add a matcher node to the current graph we're building. +void MatcherGen::AddMatcher(Matcher *NewNode) { + if (CurPredicate != 0) + CurPredicate->setNext(NewNode); + else + TheMatcher = NewNode; + CurPredicate = NewNode; +} + + +//===----------------------------------------------------------------------===// +// Pattern Match Generation +//===----------------------------------------------------------------------===// + +/// EmitLeafMatchCode - Generate matching code for leaf nodes. +void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { + assert(N->isLeaf() && "Not a leaf?"); + + // Direct match against an integer constant. + if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) { + // If this is the root of the dag we're matching, we emit a redundant opcode + // check to ensure that this gets folded into the normal top-level + // OpcodeSwitch. + if (N == Pattern.getSrcPattern()) { + const SDNodeInfo &NI = CGP.getSDNodeInfo(CGP.getSDNodeNamed("imm")); + AddMatcher(new CheckOpcodeMatcher(NI)); + } + + return AddMatcher(new CheckIntegerMatcher(II->getValue())); + } + + DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue()); + if (DI == 0) { + errs() << "Unknown leaf kind: " << *N << "\n"; + abort(); + } + + Record *LeafRec = DI->getDef(); + if (// Handle register references. Nothing to do here, they always match. + LeafRec->isSubClassOf("RegisterClass") || + LeafRec->isSubClassOf("RegisterOperand") || + LeafRec->isSubClassOf("PointerLikeRegClass") || + LeafRec->isSubClassOf("SubRegIndex") || + // Place holder for SRCVALUE nodes. Nothing to do here. + LeafRec->getName() == "srcvalue") + return; + + // If we have a physreg reference like (mul gpr:$src, EAX) then we need to + // record the register + if (LeafRec->isSubClassOf("Register")) { + AddMatcher(new RecordMatcher("physreg input "+LeafRec->getName(), + NextRecordedOperandNo)); + PhysRegInputs.push_back(std::make_pair(LeafRec, NextRecordedOperandNo++)); + return; + } + + if (LeafRec->isSubClassOf("ValueType")) + return AddMatcher(new CheckValueTypeMatcher(LeafRec->getName())); + + if (LeafRec->isSubClassOf("CondCode")) + return AddMatcher(new CheckCondCodeMatcher(LeafRec->getName())); + + if (LeafRec->isSubClassOf("ComplexPattern")) { + // We can't model ComplexPattern uses that don't have their name taken yet. + // The OPC_CheckComplexPattern operation implicitly records the results. + if (N->getName().empty()) { + errs() << "We expect complex pattern uses to have names: " << *N << "\n"; + exit(1); + } + + // Remember this ComplexPattern so that we can emit it after all the other + // structural matches are done. + MatchedComplexPatterns.push_back(std::make_pair(N, 0)); + return; + } + + errs() << "Unknown leaf kind: " << *N << "\n"; + abort(); +} + +void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N, + TreePatternNode *NodeNoTypes) { + assert(!N->isLeaf() && "Not an operator?"); + const SDNodeInfo &CInfo = CGP.getSDNodeInfo(N->getOperator()); + + // If this is an 'and R, 1234' where the operation is AND/OR and the RHS is + // a constant without a predicate fn that has more that one bit set, handle + // this as a special case. This is usually for targets that have special + // handling of certain large constants (e.g. alpha with it's 8/16/32-bit + // handling stuff). Using these instructions is often far more efficient + // than materializing the constant. Unfortunately, both the instcombiner + // and the dag combiner can often infer that bits are dead, and thus drop + // them from the mask in the dag. For example, it might turn 'AND X, 255' + // into 'AND X, 254' if it knows the low bit is set. Emit code that checks + // to handle this. + if ((N->getOperator()->getName() == "and" || + N->getOperator()->getName() == "or") && + N->getChild(1)->isLeaf() && N->getChild(1)->getPredicateFns().empty() && + N->getPredicateFns().empty()) { + if (IntInit *II = dynamic_cast<IntInit*>(N->getChild(1)->getLeafValue())) { + if (!isPowerOf2_32(II->getValue())) { // Don't bother with single bits. + // If this is at the root of the pattern, we emit a redundant + // CheckOpcode so that the following checks get factored properly under + // a single opcode check. + if (N == Pattern.getSrcPattern()) + AddMatcher(new CheckOpcodeMatcher(CInfo)); + + // Emit the CheckAndImm/CheckOrImm node. + if (N->getOperator()->getName() == "and") + AddMatcher(new CheckAndImmMatcher(II->getValue())); + else + AddMatcher(new CheckOrImmMatcher(II->getValue())); + + // Match the LHS of the AND as appropriate. + AddMatcher(new MoveChildMatcher(0)); + EmitMatchCode(N->getChild(0), NodeNoTypes->getChild(0)); + AddMatcher(new MoveParentMatcher()); + return; + } + } + } + + // Check that the current opcode lines up. + AddMatcher(new CheckOpcodeMatcher(CInfo)); + + // If this node has memory references (i.e. is a load or store), tell the + // interpreter to capture them in the memref array. + if (N->NodeHasProperty(SDNPMemOperand, CGP)) + AddMatcher(new RecordMemRefMatcher()); + + // If this node has a chain, then the chain is operand #0 is the SDNode, and + // the child numbers of the node are all offset by one. + unsigned OpNo = 0; + if (N->NodeHasProperty(SDNPHasChain, CGP)) { + // Record the node and remember it in our chained nodes list. + AddMatcher(new RecordMatcher("'" + N->getOperator()->getName() + + "' chained node", + NextRecordedOperandNo)); + // Remember all of the input chains our pattern will match. + MatchedChainNodes.push_back(NextRecordedOperandNo++); + + // Don't look at the input chain when matching the tree pattern to the + // SDNode. + OpNo = 1; + + // If this node is not the root and the subtree underneath it produces a + // chain, then the result of matching the node is also produce a chain. + // Beyond that, this means that we're also folding (at least) the root node + // into the node that produce the chain (for example, matching + // "(add reg, (load ptr))" as a add_with_memory on X86). This is + // problematic, if the 'reg' node also uses the load (say, its chain). + // Graphically: + // + // [LD] + // ^ ^ + // | \ DAG's like cheese. + // / | + // / [YY] + // | ^ + // [XX]--/ + // + // It would be invalid to fold XX and LD. In this case, folding the two + // nodes together would induce a cycle in the DAG, making it a 'cyclic DAG' + // To prevent this, we emit a dynamic check for legality before allowing + // this to be folded. + // + const TreePatternNode *Root = Pattern.getSrcPattern(); + if (N != Root) { // Not the root of the pattern. + // If there is a node between the root and this node, then we definitely + // need to emit the check. + bool NeedCheck = !Root->hasChild(N); + + // If it *is* an immediate child of the root, we can still need a check if + // the root SDNode has multiple inputs. For us, this means that it is an + // intrinsic, has multiple operands, or has other inputs like chain or + // glue). + if (!NeedCheck) { + const SDNodeInfo &PInfo = CGP.getSDNodeInfo(Root->getOperator()); + NeedCheck = + Root->getOperator() == CGP.get_intrinsic_void_sdnode() || + Root->getOperator() == CGP.get_intrinsic_w_chain_sdnode() || + Root->getOperator() == CGP.get_intrinsic_wo_chain_sdnode() || + PInfo.getNumOperands() > 1 || + PInfo.hasProperty(SDNPHasChain) || + PInfo.hasProperty(SDNPInGlue) || + PInfo.hasProperty(SDNPOptInGlue); + } + + if (NeedCheck) + AddMatcher(new CheckFoldableChainNodeMatcher()); + } + } + + // If this node has an output glue and isn't the root, remember it. + if (N->NodeHasProperty(SDNPOutGlue, CGP) && + N != Pattern.getSrcPattern()) { + // TODO: This redundantly records nodes with both glues and chains. + + // Record the node and remember it in our chained nodes list. + AddMatcher(new RecordMatcher("'" + N->getOperator()->getName() + + "' glue output node", + NextRecordedOperandNo)); + // Remember all of the nodes with output glue our pattern will match. + MatchedGlueResultNodes.push_back(NextRecordedOperandNo++); + } + + // If this node is known to have an input glue or if it *might* have an input + // glue, capture it as the glue input of the pattern. + if (N->NodeHasProperty(SDNPOptInGlue, CGP) || + N->NodeHasProperty(SDNPInGlue, CGP)) + AddMatcher(new CaptureGlueInputMatcher()); + + for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) { + // Get the code suitable for matching this child. Move to the child, check + // it then move back to the parent. + AddMatcher(new MoveChildMatcher(OpNo)); + EmitMatchCode(N->getChild(i), NodeNoTypes->getChild(i)); + AddMatcher(new MoveParentMatcher()); + } +} + + +void MatcherGen::EmitMatchCode(const TreePatternNode *N, + TreePatternNode *NodeNoTypes) { + // If N and NodeNoTypes don't agree on a type, then this is a case where we + // need to do a type check. Emit the check, apply the tyep to NodeNoTypes and + // reinfer any correlated types. + SmallVector<unsigned, 2> ResultsToTypeCheck; + + for (unsigned i = 0, e = NodeNoTypes->getNumTypes(); i != e; ++i) { + if (NodeNoTypes->getExtType(i) == N->getExtType(i)) continue; + NodeNoTypes->setType(i, N->getExtType(i)); + InferPossibleTypes(); + ResultsToTypeCheck.push_back(i); + } + + // If this node has a name associated with it, capture it in VariableMap. If + // we already saw this in the pattern, emit code to verify dagness. + if (!N->getName().empty()) { + unsigned &VarMapEntry = VariableMap[N->getName()]; + if (VarMapEntry == 0) { + // If it is a named node, we must emit a 'Record' opcode. + AddMatcher(new RecordMatcher("$" + N->getName(), NextRecordedOperandNo)); + VarMapEntry = ++NextRecordedOperandNo; + } else { + // If we get here, this is a second reference to a specific name. Since + // we already have checked that the first reference is valid, we don't + // have to recursively match it, just check that it's the same as the + // previously named thing. + AddMatcher(new CheckSameMatcher(VarMapEntry-1)); + return; + } + } + + if (N->isLeaf()) + EmitLeafMatchCode(N); + else + EmitOperatorMatchCode(N, NodeNoTypes); + + // If there are node predicates for this node, generate their checks. + for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i) + AddMatcher(new CheckPredicateMatcher(N->getPredicateFns()[i])); + + for (unsigned i = 0, e = ResultsToTypeCheck.size(); i != e; ++i) + AddMatcher(new CheckTypeMatcher(N->getType(ResultsToTypeCheck[i]), + ResultsToTypeCheck[i])); +} + +/// EmitMatcherCode - Generate the code that matches the predicate of this +/// pattern for the specified Variant. If the variant is invalid this returns +/// true and does not generate code, if it is valid, it returns false. +bool MatcherGen::EmitMatcherCode(unsigned Variant) { + // If the root of the pattern is a ComplexPattern and if it is specified to + // match some number of root opcodes, these are considered to be our variants. + // Depending on which variant we're generating code for, emit the root opcode + // check. + if (const ComplexPattern *CP = + Pattern.getSrcPattern()->getComplexPatternInfo(CGP)) { + const std::vector<Record*> &OpNodes = CP->getRootNodes(); + assert(!OpNodes.empty() &&"Complex Pattern must specify what it can match"); + if (Variant >= OpNodes.size()) return true; + + AddMatcher(new CheckOpcodeMatcher(CGP.getSDNodeInfo(OpNodes[Variant]))); + } else { + if (Variant != 0) return true; + } + + // Emit the matcher for the pattern structure and types. + EmitMatchCode(Pattern.getSrcPattern(), PatWithNoTypes); + + // If the pattern has a predicate on it (e.g. only enabled when a subtarget + // feature is around, do the check). + if (!Pattern.getPredicateCheck().empty()) + AddMatcher(new CheckPatternPredicateMatcher(Pattern.getPredicateCheck())); + + // Now that we've completed the structural type match, emit any ComplexPattern + // checks (e.g. addrmode matches). We emit this after the structural match + // because they are generally more expensive to evaluate and more difficult to + // factor. + for (unsigned i = 0, e = MatchedComplexPatterns.size(); i != e; ++i) { + const TreePatternNode *N = MatchedComplexPatterns[i].first; + + // Remember where the results of this match get stuck. + MatchedComplexPatterns[i].second = NextRecordedOperandNo; + + // Get the slot we recorded the value in from the name on the node. + unsigned RecNodeEntry = VariableMap[N->getName()]; + assert(!N->getName().empty() && RecNodeEntry && + "Complex pattern should have a name and slot"); + --RecNodeEntry; // Entries in VariableMap are biased. + + const ComplexPattern &CP = + CGP.getComplexPattern(((DefInit*)N->getLeafValue())->getDef()); + + // Emit a CheckComplexPat operation, which does the match (aborting if it + // fails) and pushes the matched operands onto the recorded nodes list. + AddMatcher(new CheckComplexPatMatcher(CP, RecNodeEntry, + N->getName(), NextRecordedOperandNo)); + + // Record the right number of operands. + NextRecordedOperandNo += CP.getNumOperands(); + if (CP.hasProperty(SDNPHasChain)) { + // If the complex pattern has a chain, then we need to keep track of the + // fact that we just recorded a chain input. The chain input will be + // matched as the last operand of the predicate if it was successful. + ++NextRecordedOperandNo; // Chained node operand. + + // It is the last operand recorded. + assert(NextRecordedOperandNo > 1 && + "Should have recorded input/result chains at least!"); + MatchedChainNodes.push_back(NextRecordedOperandNo-1); + } + + // TODO: Complex patterns can't have output glues, if they did, we'd want + // to record them. + } + + return false; +} + + +//===----------------------------------------------------------------------===// +// Node Result Generation +//===----------------------------------------------------------------------===// + +void MatcherGen::EmitResultOfNamedOperand(const TreePatternNode *N, + SmallVectorImpl<unsigned> &ResultOps){ + assert(!N->getName().empty() && "Operand not named!"); + + // A reference to a complex pattern gets all of the results of the complex + // pattern's match. + if (const ComplexPattern *CP = N->getComplexPatternInfo(CGP)) { + unsigned SlotNo = 0; + for (unsigned i = 0, e = MatchedComplexPatterns.size(); i != e; ++i) + if (MatchedComplexPatterns[i].first->getName() == N->getName()) { + SlotNo = MatchedComplexPatterns[i].second; + break; + } + assert(SlotNo != 0 && "Didn't get a slot number assigned?"); + + // The first slot entry is the node itself, the subsequent entries are the + // matched values. + for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) + ResultOps.push_back(SlotNo+i); + return; + } + + unsigned SlotNo = getNamedArgumentSlot(N->getName()); + + // If this is an 'imm' or 'fpimm' node, make sure to convert it to the target + // version of the immediate so that it doesn't get selected due to some other + // node use. + if (!N->isLeaf()) { + StringRef OperatorName = N->getOperator()->getName(); + if (OperatorName == "imm" || OperatorName == "fpimm") { + AddMatcher(new EmitConvertToTargetMatcher(SlotNo)); + ResultOps.push_back(NextRecordedOperandNo++); + return; + } + } + + ResultOps.push_back(SlotNo); +} + +void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N, + SmallVectorImpl<unsigned> &ResultOps) { + assert(N->isLeaf() && "Must be a leaf"); + + if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) { + AddMatcher(new EmitIntegerMatcher(II->getValue(), N->getType(0))); + ResultOps.push_back(NextRecordedOperandNo++); + return; + } + + // If this is an explicit register reference, handle it. + if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) { + Record *Def = DI->getDef(); + if (Def->isSubClassOf("Register")) { + const CodeGenRegister *Reg = + CGP.getTargetInfo().getRegBank().getReg(Def); + AddMatcher(new EmitRegisterMatcher(Reg, N->getType(0))); + ResultOps.push_back(NextRecordedOperandNo++); + return; + } + + if (Def->getName() == "zero_reg") { + AddMatcher(new EmitRegisterMatcher(0, N->getType(0))); + ResultOps.push_back(NextRecordedOperandNo++); + return; + } + + // Handle a reference to a register class. This is used + // in COPY_TO_SUBREG instructions. + if (Def->isSubClassOf("RegisterOperand")) + Def = Def->getValueAsDef("RegClass"); + if (Def->isSubClassOf("RegisterClass")) { + std::string Value = getQualifiedName(Def) + "RegClassID"; + AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32)); + ResultOps.push_back(NextRecordedOperandNo++); + return; + } + + // Handle a subregister index. This is used for INSERT_SUBREG etc. + if (Def->isSubClassOf("SubRegIndex")) { + std::string Value = getQualifiedName(Def); + AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32)); + ResultOps.push_back(NextRecordedOperandNo++); + return; + } + } + + errs() << "unhandled leaf node: \n"; + N->dump(); +} + +/// GetInstPatternNode - Get the pattern for an instruction. +/// +const TreePatternNode *MatcherGen:: +GetInstPatternNode(const DAGInstruction &Inst, const TreePatternNode *N) { + const TreePattern *InstPat = Inst.getPattern(); + + // FIXME2?: Assume actual pattern comes before "implicit". + TreePatternNode *InstPatNode; + if (InstPat) + InstPatNode = InstPat->getTree(0); + else if (/*isRoot*/ N == Pattern.getDstPattern()) + InstPatNode = Pattern.getSrcPattern(); + else + return 0; + + if (InstPatNode && !InstPatNode->isLeaf() && + InstPatNode->getOperator()->getName() == "set") + InstPatNode = InstPatNode->getChild(InstPatNode->getNumChildren()-1); + + return InstPatNode; +} + +static bool +mayInstNodeLoadOrStore(const TreePatternNode *N, + const CodeGenDAGPatterns &CGP) { + Record *Op = N->getOperator(); + const CodeGenTarget &CGT = CGP.getTargetInfo(); + CodeGenInstruction &II = CGT.getInstruction(Op); + return II.mayLoad || II.mayStore; +} + +static unsigned +numNodesThatMayLoadOrStore(const TreePatternNode *N, + const CodeGenDAGPatterns &CGP) { + if (N->isLeaf()) + return 0; + + Record *OpRec = N->getOperator(); + if (!OpRec->isSubClassOf("Instruction")) + return 0; + + unsigned Count = 0; + if (mayInstNodeLoadOrStore(N, CGP)) + ++Count; + + for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) + Count += numNodesThatMayLoadOrStore(N->getChild(i), CGP); + + return Count; +} + +void MatcherGen:: +EmitResultInstructionAsOperand(const TreePatternNode *N, + SmallVectorImpl<unsigned> &OutputOps) { + Record *Op = N->getOperator(); + const CodeGenTarget &CGT = CGP.getTargetInfo(); + CodeGenInstruction &II = CGT.getInstruction(Op); + const DAGInstruction &Inst = CGP.getInstruction(Op); + + // If we can, get the pattern for the instruction we're generating. We derive + // a variety of information from this pattern, such as whether it has a chain. + // + // FIXME2: This is extremely dubious for several reasons, not the least of + // which it gives special status to instructions with patterns that Pat<> + // nodes can't duplicate. + const TreePatternNode *InstPatNode = GetInstPatternNode(Inst, N); + + // NodeHasChain - Whether the instruction node we're creating takes chains. + bool NodeHasChain = InstPatNode && + InstPatNode->TreeHasProperty(SDNPHasChain, CGP); + + bool isRoot = N == Pattern.getDstPattern(); + + // TreeHasOutGlue - True if this tree has glue. + bool TreeHasInGlue = false, TreeHasOutGlue = false; + if (isRoot) { + const TreePatternNode *SrcPat = Pattern.getSrcPattern(); + TreeHasInGlue = SrcPat->TreeHasProperty(SDNPOptInGlue, CGP) || + SrcPat->TreeHasProperty(SDNPInGlue, CGP); + + // FIXME2: this is checking the entire pattern, not just the node in + // question, doing this just for the root seems like a total hack. + TreeHasOutGlue = SrcPat->TreeHasProperty(SDNPOutGlue, CGP); + } + + // NumResults - This is the number of results produced by the instruction in + // the "outs" list. + unsigned NumResults = Inst.getNumResults(); + + // Loop over all of the operands of the instruction pattern, emitting code + // to fill them all in. The node 'N' usually has number children equal to + // the number of input operands of the instruction. However, in cases + // where there are predicate operands for an instruction, we need to fill + // in the 'execute always' values. Match up the node operands to the + // instruction operands to do this. + SmallVector<unsigned, 8> InstOps; + for (unsigned ChildNo = 0, InstOpNo = NumResults, e = II.Operands.size(); + InstOpNo != e; ++InstOpNo) { + + // Determine what to emit for this operand. + Record *OperandNode = II.Operands[InstOpNo].Rec; + if ((OperandNode->isSubClassOf("PredicateOperand") || + OperandNode->isSubClassOf("OptionalDefOperand")) && + !CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) { + // This is a predicate or optional def operand; emit the + // 'default ops' operands. + const DAGDefaultOperand &DefaultOp + = CGP.getDefaultOperand(OperandNode); + for (unsigned i = 0, e = DefaultOp.DefaultOps.size(); i != e; ++i) + EmitResultOperand(DefaultOp.DefaultOps[i], InstOps); + continue; + } + + const TreePatternNode *Child = N->getChild(ChildNo); + + // Otherwise this is a normal operand or a predicate operand without + // 'execute always'; emit it. + unsigned BeforeAddingNumOps = InstOps.size(); + EmitResultOperand(Child, InstOps); + assert(InstOps.size() > BeforeAddingNumOps && "Didn't add any operands"); + + // If the operand is an instruction and it produced multiple results, just + // take the first one. + if (!Child->isLeaf() && Child->getOperator()->isSubClassOf("Instruction")) + InstOps.resize(BeforeAddingNumOps+1); + + ++ChildNo; + } + + // If this node has input glue or explicitly specified input physregs, we + // need to add chained and glued copyfromreg nodes and materialize the glue + // input. + if (isRoot && !PhysRegInputs.empty()) { + // Emit all of the CopyToReg nodes for the input physical registers. These + // occur in patterns like (mul:i8 AL:i8, GR8:i8:$src). + for (unsigned i = 0, e = PhysRegInputs.size(); i != e; ++i) + AddMatcher(new EmitCopyToRegMatcher(PhysRegInputs[i].second, + PhysRegInputs[i].first)); + // Even if the node has no other glue inputs, the resultant node must be + // glued to the CopyFromReg nodes we just generated. + TreeHasInGlue = true; + } + + // Result order: node results, chain, glue + + // Determine the result types. + SmallVector<MVT::SimpleValueType, 4> ResultVTs; + for (unsigned i = 0, e = N->getNumTypes(); i != e; ++i) + ResultVTs.push_back(N->getType(i)); + + // If this is the root instruction of a pattern that has physical registers in + // its result pattern, add output VTs for them. For example, X86 has: + // (set AL, (mul ...)) + // This also handles implicit results like: + // (implicit EFLAGS) + if (isRoot && !Pattern.getDstRegs().empty()) { + // If the root came from an implicit def in the instruction handling stuff, + // don't re-add it. + Record *HandledReg = 0; + if (II.HasOneImplicitDefWithKnownVT(CGT) != MVT::Other) + HandledReg = II.ImplicitDefs[0]; + + for (unsigned i = 0; i != Pattern.getDstRegs().size(); ++i) { + Record *Reg = Pattern.getDstRegs()[i]; + if (!Reg->isSubClassOf("Register") || Reg == HandledReg) continue; + ResultVTs.push_back(getRegisterValueType(Reg, CGT)); + } + } + + // If this is the root of the pattern and the pattern we're matching includes + // a node that is variadic, mark the generated node as variadic so that it + // gets the excess operands from the input DAG. + int NumFixedArityOperands = -1; + if (isRoot && + (Pattern.getSrcPattern()->NodeHasProperty(SDNPVariadic, CGP))) + NumFixedArityOperands = Pattern.getSrcPattern()->getNumChildren(); + + // If this is the root node and multiple matched nodes in the input pattern + // have MemRefs in them, have the interpreter collect them and plop them onto + // this node. If there is just one node with MemRefs, leave them on that node + // even if it is not the root. + // + // FIXME3: This is actively incorrect for result patterns with multiple + // memory-referencing instructions. + bool PatternHasMemOperands = + Pattern.getSrcPattern()->TreeHasProperty(SDNPMemOperand, CGP); + + bool NodeHasMemRefs = false; + if (PatternHasMemOperands) { + unsigned NumNodesThatLoadOrStore = + numNodesThatMayLoadOrStore(Pattern.getDstPattern(), CGP); + bool NodeIsUniqueLoadOrStore = mayInstNodeLoadOrStore(N, CGP) && + NumNodesThatLoadOrStore == 1; + NodeHasMemRefs = + NodeIsUniqueLoadOrStore || (isRoot && (mayInstNodeLoadOrStore(N, CGP) || + NumNodesThatLoadOrStore != 1)); + } + + assert((!ResultVTs.empty() || TreeHasOutGlue || NodeHasChain) && + "Node has no result"); + + AddMatcher(new EmitNodeMatcher(II.Namespace+"::"+II.TheDef->getName(), + ResultVTs.data(), ResultVTs.size(), + InstOps.data(), InstOps.size(), + NodeHasChain, TreeHasInGlue, TreeHasOutGlue, + NodeHasMemRefs, NumFixedArityOperands, + NextRecordedOperandNo)); + + // The non-chain and non-glue results of the newly emitted node get recorded. + for (unsigned i = 0, e = ResultVTs.size(); i != e; ++i) { + if (ResultVTs[i] == MVT::Other || ResultVTs[i] == MVT::Glue) break; + OutputOps.push_back(NextRecordedOperandNo++); + } +} + +void MatcherGen:: +EmitResultSDNodeXFormAsOperand(const TreePatternNode *N, + SmallVectorImpl<unsigned> &ResultOps) { + assert(N->getOperator()->isSubClassOf("SDNodeXForm") && "Not SDNodeXForm?"); + + // Emit the operand. + SmallVector<unsigned, 8> InputOps; + + // FIXME2: Could easily generalize this to support multiple inputs and outputs + // to the SDNodeXForm. For now we just support one input and one output like + // the old instruction selector. + assert(N->getNumChildren() == 1); + EmitResultOperand(N->getChild(0), InputOps); + + // The input currently must have produced exactly one result. + assert(InputOps.size() == 1 && "Unexpected input to SDNodeXForm"); + + AddMatcher(new EmitNodeXFormMatcher(InputOps[0], N->getOperator())); + ResultOps.push_back(NextRecordedOperandNo++); +} + +void MatcherGen::EmitResultOperand(const TreePatternNode *N, + SmallVectorImpl<unsigned> &ResultOps) { + // This is something selected from the pattern we matched. + if (!N->getName().empty()) + return EmitResultOfNamedOperand(N, ResultOps); + + if (N->isLeaf()) + return EmitResultLeafAsOperand(N, ResultOps); + + Record *OpRec = N->getOperator(); + if (OpRec->isSubClassOf("Instruction")) + return EmitResultInstructionAsOperand(N, ResultOps); + if (OpRec->isSubClassOf("SDNodeXForm")) + return EmitResultSDNodeXFormAsOperand(N, ResultOps); + errs() << "Unknown result node to emit code for: " << *N << '\n'; + throw std::string("Unknown node in result pattern!"); +} + +void MatcherGen::EmitResultCode() { + // Patterns that match nodes with (potentially multiple) chain inputs have to + // merge them together into a token factor. This informs the generated code + // what all the chained nodes are. + if (!MatchedChainNodes.empty()) + AddMatcher(new EmitMergeInputChainsMatcher + (MatchedChainNodes.data(), MatchedChainNodes.size())); + + // Codegen the root of the result pattern, capturing the resulting values. + SmallVector<unsigned, 8> Ops; + EmitResultOperand(Pattern.getDstPattern(), Ops); + + // At this point, we have however many values the result pattern produces. + // However, the input pattern might not need all of these. If there are + // excess values at the end (such as implicit defs of condition codes etc) + // just lop them off. This doesn't need to worry about glue or chains, just + // explicit results. + // + unsigned NumSrcResults = Pattern.getSrcPattern()->getNumTypes(); + + // If the pattern also has (implicit) results, count them as well. + if (!Pattern.getDstRegs().empty()) { + // If the root came from an implicit def in the instruction handling stuff, + // don't re-add it. + Record *HandledReg = 0; + const TreePatternNode *DstPat = Pattern.getDstPattern(); + if (!DstPat->isLeaf() &&DstPat->getOperator()->isSubClassOf("Instruction")){ + const CodeGenTarget &CGT = CGP.getTargetInfo(); + CodeGenInstruction &II = CGT.getInstruction(DstPat->getOperator()); + + if (II.HasOneImplicitDefWithKnownVT(CGT) != MVT::Other) + HandledReg = II.ImplicitDefs[0]; + } + + for (unsigned i = 0; i != Pattern.getDstRegs().size(); ++i) { + Record *Reg = Pattern.getDstRegs()[i]; + if (!Reg->isSubClassOf("Register") || Reg == HandledReg) continue; + ++NumSrcResults; + } + } + + assert(Ops.size() >= NumSrcResults && "Didn't provide enough results"); + Ops.resize(NumSrcResults); + + // If the matched pattern covers nodes which define a glue result, emit a node + // that tells the matcher about them so that it can update their results. + if (!MatchedGlueResultNodes.empty()) + AddMatcher(new MarkGlueResultsMatcher(MatchedGlueResultNodes.data(), + MatchedGlueResultNodes.size())); + + AddMatcher(new CompleteMatchMatcher(Ops.data(), Ops.size(), Pattern)); +} + + +/// ConvertPatternToMatcher - Create the matcher for the specified pattern with +/// the specified variant. If the variant number is invalid, this returns null. +Matcher *llvm::ConvertPatternToMatcher(const PatternToMatch &Pattern, + unsigned Variant, + const CodeGenDAGPatterns &CGP) { + MatcherGen Gen(Pattern, CGP); + + // Generate the code for the matcher. + if (Gen.EmitMatcherCode(Variant)) + return 0; + + // FIXME2: Kill extra MoveParent commands at the end of the matcher sequence. + // FIXME2: Split result code out to another table, and make the matcher end + // with an "Emit <index>" command. This allows result generation stuff to be + // shared and factored? + + // If the match succeeds, then we generate Pattern. + Gen.EmitResultCode(); + + // Unconditional match. + return Gen.GetMatcher(); +} diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp new file mode 100644 index 0000000..f996422 --- /dev/null +++ b/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp @@ -0,0 +1,513 @@ +//===- DAGISelMatcherOpt.cpp - Optimize a DAG Matcher ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the DAG Matcher optimizer. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "isel-opt" +#include "DAGISelMatcher.h" +#include "CodeGenDAGPatterns.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/StringSet.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +/// ContractNodes - Turn multiple matcher node patterns like 'MoveChild+Record' +/// into single compound nodes like RecordChild. +static void ContractNodes(OwningPtr<Matcher> &MatcherPtr, + const CodeGenDAGPatterns &CGP) { + // If we reached the end of the chain, we're done. + Matcher *N = MatcherPtr.get(); + if (N == 0) return; + + // If we have a scope node, walk down all of the children. + if (ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N)) { + for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) { + OwningPtr<Matcher> Child(Scope->takeChild(i)); + ContractNodes(Child, CGP); + Scope->resetChild(i, Child.take()); + } + return; + } + + // If we found a movechild node with a node that comes in a 'foochild' form, + // transform it. + if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N)) { + Matcher *New = 0; + if (RecordMatcher *RM = dyn_cast<RecordMatcher>(MC->getNext())) + if (MC->getChildNo() < 8) // Only have RecordChild0...7 + New = new RecordChildMatcher(MC->getChildNo(), RM->getWhatFor(), + RM->getResultNo()); + + if (CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(MC->getNext())) + if (MC->getChildNo() < 8 && // Only have CheckChildType0...7 + CT->getResNo() == 0) // CheckChildType checks res #0 + New = new CheckChildTypeMatcher(MC->getChildNo(), CT->getType()); + + if (New) { + // Insert the new node. + New->setNext(MatcherPtr.take()); + MatcherPtr.reset(New); + // Remove the old one. + MC->setNext(MC->getNext()->takeNext()); + return ContractNodes(MatcherPtr, CGP); + } + } + + // Zap movechild -> moveparent. + if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N)) + if (MoveParentMatcher *MP = + dyn_cast<MoveParentMatcher>(MC->getNext())) { + MatcherPtr.reset(MP->takeNext()); + return ContractNodes(MatcherPtr, CGP); + } + + // Turn EmitNode->MarkFlagResults->CompleteMatch into + // MarkFlagResults->EmitNode->CompleteMatch when we can to encourage + // MorphNodeTo formation. This is safe because MarkFlagResults never refers + // to the root of the pattern. + if (isa<EmitNodeMatcher>(N) && isa<MarkGlueResultsMatcher>(N->getNext()) && + isa<CompleteMatchMatcher>(N->getNext()->getNext())) { + // Unlink the two nodes from the list. + Matcher *EmitNode = MatcherPtr.take(); + Matcher *MFR = EmitNode->takeNext(); + Matcher *Tail = MFR->takeNext(); + + // Relink them. + MatcherPtr.reset(MFR); + MFR->setNext(EmitNode); + EmitNode->setNext(Tail); + return ContractNodes(MatcherPtr, CGP); + } + + // Turn EmitNode->CompleteMatch into MorphNodeTo if we can. + if (EmitNodeMatcher *EN = dyn_cast<EmitNodeMatcher>(N)) + if (CompleteMatchMatcher *CM = + dyn_cast<CompleteMatchMatcher>(EN->getNext())) { + // We can only use MorphNodeTo if the result values match up. + unsigned RootResultFirst = EN->getFirstResultSlot(); + bool ResultsMatch = true; + for (unsigned i = 0, e = CM->getNumResults(); i != e; ++i) + if (CM->getResult(i) != RootResultFirst+i) + ResultsMatch = false; + + // If the selected node defines a subset of the glue/chain results, we + // can't use MorphNodeTo. For example, we can't use MorphNodeTo if the + // matched pattern has a chain but the root node doesn't. + const PatternToMatch &Pattern = CM->getPattern(); + + if (!EN->hasChain() && + Pattern.getSrcPattern()->NodeHasProperty(SDNPHasChain, CGP)) + ResultsMatch = false; + + // If the matched node has glue and the output root doesn't, we can't + // use MorphNodeTo. + // + // NOTE: Strictly speaking, we don't have to check for glue here + // because the code in the pattern generator doesn't handle it right. We + // do it anyway for thoroughness. + if (!EN->hasOutFlag() && + Pattern.getSrcPattern()->NodeHasProperty(SDNPOutGlue, CGP)) + ResultsMatch = false; + + + // If the root result node defines more results than the source root node + // *and* has a chain or glue input, then we can't match it because it + // would end up replacing the extra result with the chain/glue. +#if 0 + if ((EN->hasGlue() || EN->hasChain()) && + EN->getNumNonChainGlueVTs() > ... need to get no results reliably ...) + ResultMatch = false; +#endif + + if (ResultsMatch) { + const SmallVectorImpl<MVT::SimpleValueType> &VTs = EN->getVTList(); + const SmallVectorImpl<unsigned> &Operands = EN->getOperandList(); + MatcherPtr.reset(new MorphNodeToMatcher(EN->getOpcodeName(), + VTs.data(), VTs.size(), + Operands.data(),Operands.size(), + EN->hasChain(), EN->hasInFlag(), + EN->hasOutFlag(), + EN->hasMemRefs(), + EN->getNumFixedArityOperands(), + Pattern)); + return; + } + + // FIXME2: Kill off all the SelectionDAG::SelectNodeTo and getMachineNode + // variants. + } + + ContractNodes(N->getNextPtr(), CGP); + + + // If we have a CheckType/CheckChildType/Record node followed by a + // CheckOpcode, invert the two nodes. We prefer to do structural checks + // before type checks, as this opens opportunities for factoring on targets + // like X86 where many operations are valid on multiple types. + if ((isa<CheckTypeMatcher>(N) || isa<CheckChildTypeMatcher>(N) || + isa<RecordMatcher>(N)) && + isa<CheckOpcodeMatcher>(N->getNext())) { + // Unlink the two nodes from the list. + Matcher *CheckType = MatcherPtr.take(); + Matcher *CheckOpcode = CheckType->takeNext(); + Matcher *Tail = CheckOpcode->takeNext(); + + // Relink them. + MatcherPtr.reset(CheckOpcode); + CheckOpcode->setNext(CheckType); + CheckType->setNext(Tail); + return ContractNodes(MatcherPtr, CGP); + } +} + +/// SinkPatternPredicates - Pattern predicates can be checked at any level of +/// the matching tree. The generator dumps them at the top level of the pattern +/// though, which prevents factoring from being able to see past them. This +/// optimization sinks them as far down into the pattern as possible. +/// +/// Conceptually, we'd like to sink these predicates all the way to the last +/// matcher predicate in the series. However, it turns out that some +/// ComplexPatterns have side effects on the graph, so we really don't want to +/// run a the complex pattern if the pattern predicate will fail. For this +/// reason, we refuse to sink the pattern predicate past a ComplexPattern. +/// +static void SinkPatternPredicates(OwningPtr<Matcher> &MatcherPtr) { + // Recursively scan for a PatternPredicate. + // If we reached the end of the chain, we're done. + Matcher *N = MatcherPtr.get(); + if (N == 0) return; + + // Walk down all members of a scope node. + if (ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N)) { + for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) { + OwningPtr<Matcher> Child(Scope->takeChild(i)); + SinkPatternPredicates(Child); + Scope->resetChild(i, Child.take()); + } + return; + } + + // If this node isn't a CheckPatternPredicateMatcher we keep scanning until + // we find one. + CheckPatternPredicateMatcher *CPPM =dyn_cast<CheckPatternPredicateMatcher>(N); + if (CPPM == 0) + return SinkPatternPredicates(N->getNextPtr()); + + // Ok, we found one, lets try to sink it. Check if we can sink it past the + // next node in the chain. If not, we won't be able to change anything and + // might as well bail. + if (!CPPM->getNext()->isSafeToReorderWithPatternPredicate()) + return; + + // Okay, we know we can sink it past at least one node. Unlink it from the + // chain and scan for the new insertion point. + MatcherPtr.take(); // Don't delete CPPM. + MatcherPtr.reset(CPPM->takeNext()); + + N = MatcherPtr.get(); + while (N->getNext()->isSafeToReorderWithPatternPredicate()) + N = N->getNext(); + + // At this point, we want to insert CPPM after N. + CPPM->setNext(N->takeNext()); + N->setNext(CPPM); +} + +/// FindNodeWithKind - Scan a series of matchers looking for a matcher with a +/// specified kind. Return null if we didn't find one otherwise return the +/// matcher. +static Matcher *FindNodeWithKind(Matcher *M, Matcher::KindTy Kind) { + for (; M; M = M->getNext()) + if (M->getKind() == Kind) + return M; + return 0; +} + + +/// FactorNodes - Turn matches like this: +/// Scope +/// OPC_CheckType i32 +/// ABC +/// OPC_CheckType i32 +/// XYZ +/// into: +/// OPC_CheckType i32 +/// Scope +/// ABC +/// XYZ +/// +static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) { + // If we reached the end of the chain, we're done. + Matcher *N = MatcherPtr.get(); + if (N == 0) return; + + // If this is not a push node, just scan for one. + ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N); + if (Scope == 0) + return FactorNodes(N->getNextPtr()); + + // Okay, pull together the children of the scope node into a vector so we can + // inspect it more easily. While we're at it, bucket them up by the hash + // code of their first predicate. + SmallVector<Matcher*, 32> OptionsToMatch; + + for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) { + // Factor the subexpression. + OwningPtr<Matcher> Child(Scope->takeChild(i)); + FactorNodes(Child); + + if (Matcher *N = Child.take()) + OptionsToMatch.push_back(N); + } + + SmallVector<Matcher*, 32> NewOptionsToMatch; + + // Loop over options to match, merging neighboring patterns with identical + // starting nodes into a shared matcher. + for (unsigned OptionIdx = 0, e = OptionsToMatch.size(); OptionIdx != e;) { + // Find the set of matchers that start with this node. + Matcher *Optn = OptionsToMatch[OptionIdx++]; + + if (OptionIdx == e) { + NewOptionsToMatch.push_back(Optn); + continue; + } + + // See if the next option starts with the same matcher. If the two + // neighbors *do* start with the same matcher, we can factor the matcher out + // of at least these two patterns. See what the maximal set we can merge + // together is. + SmallVector<Matcher*, 8> EqualMatchers; + EqualMatchers.push_back(Optn); + + // Factor all of the known-equal matchers after this one into the same + // group. + while (OptionIdx != e && OptionsToMatch[OptionIdx]->isEqual(Optn)) + EqualMatchers.push_back(OptionsToMatch[OptionIdx++]); + + // If we found a non-equal matcher, see if it is contradictory with the + // current node. If so, we know that the ordering relation between the + // current sets of nodes and this node don't matter. Look past it to see if + // we can merge anything else into this matching group. + unsigned Scan = OptionIdx; + while (1) { + // If we ran out of stuff to scan, we're done. + if (Scan == e) break; + + Matcher *ScanMatcher = OptionsToMatch[Scan]; + + // If we found an entry that matches out matcher, merge it into the set to + // handle. + if (Optn->isEqual(ScanMatcher)) { + // If is equal after all, add the option to EqualMatchers and remove it + // from OptionsToMatch. + EqualMatchers.push_back(ScanMatcher); + OptionsToMatch.erase(OptionsToMatch.begin()+Scan); + --e; + continue; + } + + // If the option we're checking for contradicts the start of the list, + // skip over it. + if (Optn->isContradictory(ScanMatcher)) { + ++Scan; + continue; + } + + // If we're scanning for a simple node, see if it occurs later in the + // sequence. If so, and if we can move it up, it might be contradictory + // or the same as what we're looking for. If so, reorder it. + if (Optn->isSimplePredicateOrRecordNode()) { + Matcher *M2 = FindNodeWithKind(ScanMatcher, Optn->getKind()); + if (M2 != 0 && M2 != ScanMatcher && + M2->canMoveBefore(ScanMatcher) && + (M2->isEqual(Optn) || M2->isContradictory(Optn))) { + Matcher *MatcherWithoutM2 = ScanMatcher->unlinkNode(M2); + M2->setNext(MatcherWithoutM2); + OptionsToMatch[Scan] = M2; + continue; + } + } + + // Otherwise, we don't know how to handle this entry, we have to bail. + break; + } + + if (Scan != e && + // Don't print it's obvious nothing extra could be merged anyway. + Scan+1 != e) { + DEBUG(errs() << "Couldn't merge this:\n"; + Optn->print(errs(), 4); + errs() << "into this:\n"; + OptionsToMatch[Scan]->print(errs(), 4); + if (Scan+1 != e) + OptionsToMatch[Scan+1]->printOne(errs()); + if (Scan+2 < e) + OptionsToMatch[Scan+2]->printOne(errs()); + errs() << "\n"); + } + + // If we only found one option starting with this matcher, no factoring is + // possible. + if (EqualMatchers.size() == 1) { + NewOptionsToMatch.push_back(EqualMatchers[0]); + continue; + } + + // Factor these checks by pulling the first node off each entry and + // discarding it. Take the first one off the first entry to reuse. + Matcher *Shared = Optn; + Optn = Optn->takeNext(); + EqualMatchers[0] = Optn; + + // Remove and delete the first node from the other matchers we're factoring. + for (unsigned i = 1, e = EqualMatchers.size(); i != e; ++i) { + Matcher *Tmp = EqualMatchers[i]->takeNext(); + delete EqualMatchers[i]; + EqualMatchers[i] = Tmp; + } + + Shared->setNext(new ScopeMatcher(&EqualMatchers[0], EqualMatchers.size())); + + // Recursively factor the newly created node. + FactorNodes(Shared->getNextPtr()); + + NewOptionsToMatch.push_back(Shared); + } + + // If we're down to a single pattern to match, then we don't need this scope + // anymore. + if (NewOptionsToMatch.size() == 1) { + MatcherPtr.reset(NewOptionsToMatch[0]); + return; + } + + if (NewOptionsToMatch.empty()) { + MatcherPtr.reset(0); + return; + } + + // If our factoring failed (didn't achieve anything) see if we can simplify in + // other ways. + + // Check to see if all of the leading entries are now opcode checks. If so, + // we can convert this Scope to be a OpcodeSwitch instead. + bool AllOpcodeChecks = true, AllTypeChecks = true; + for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) { + // Check to see if this breaks a series of CheckOpcodeMatchers. + if (AllOpcodeChecks && + !isa<CheckOpcodeMatcher>(NewOptionsToMatch[i])) { +#if 0 + if (i > 3) { + errs() << "FAILING OPC #" << i << "\n"; + NewOptionsToMatch[i]->dump(); + } +#endif + AllOpcodeChecks = false; + } + + // Check to see if this breaks a series of CheckTypeMatcher's. + if (AllTypeChecks) { + CheckTypeMatcher *CTM = + cast_or_null<CheckTypeMatcher>(FindNodeWithKind(NewOptionsToMatch[i], + Matcher::CheckType)); + if (CTM == 0 || + // iPTR checks could alias any other case without us knowing, don't + // bother with them. + CTM->getType() == MVT::iPTR || + // SwitchType only works for result #0. + CTM->getResNo() != 0 || + // If the CheckType isn't at the start of the list, see if we can move + // it there. + !CTM->canMoveBefore(NewOptionsToMatch[i])) { +#if 0 + if (i > 3 && AllTypeChecks) { + errs() << "FAILING TYPE #" << i << "\n"; + NewOptionsToMatch[i]->dump(); + } +#endif + AllTypeChecks = false; + } + } + } + + // If all the options are CheckOpcode's, we can form the SwitchOpcode, woot. + if (AllOpcodeChecks) { + StringSet<> Opcodes; + SmallVector<std::pair<const SDNodeInfo*, Matcher*>, 8> Cases; + for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) { + CheckOpcodeMatcher *COM = cast<CheckOpcodeMatcher>(NewOptionsToMatch[i]); + assert(Opcodes.insert(COM->getOpcode().getEnumName()) && + "Duplicate opcodes not factored?"); + Cases.push_back(std::make_pair(&COM->getOpcode(), COM->getNext())); + } + + MatcherPtr.reset(new SwitchOpcodeMatcher(&Cases[0], Cases.size())); + return; + } + + // If all the options are CheckType's, we can form the SwitchType, woot. + if (AllTypeChecks) { + DenseMap<unsigned, unsigned> TypeEntry; + SmallVector<std::pair<MVT::SimpleValueType, Matcher*>, 8> Cases; + for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) { + CheckTypeMatcher *CTM = + cast_or_null<CheckTypeMatcher>(FindNodeWithKind(NewOptionsToMatch[i], + Matcher::CheckType)); + Matcher *MatcherWithoutCTM = NewOptionsToMatch[i]->unlinkNode(CTM); + MVT::SimpleValueType CTMTy = CTM->getType(); + delete CTM; + + unsigned &Entry = TypeEntry[CTMTy]; + if (Entry != 0) { + // If we have unfactored duplicate types, then we should factor them. + Matcher *PrevMatcher = Cases[Entry-1].second; + if (ScopeMatcher *SM = dyn_cast<ScopeMatcher>(PrevMatcher)) { + SM->setNumChildren(SM->getNumChildren()+1); + SM->resetChild(SM->getNumChildren()-1, MatcherWithoutCTM); + continue; + } + + Matcher *Entries[2] = { PrevMatcher, MatcherWithoutCTM }; + Cases[Entry-1].second = new ScopeMatcher(Entries, 2); + continue; + } + + Entry = Cases.size()+1; + Cases.push_back(std::make_pair(CTMTy, MatcherWithoutCTM)); + } + + if (Cases.size() != 1) { + MatcherPtr.reset(new SwitchTypeMatcher(&Cases[0], Cases.size())); + } else { + // If we factored and ended up with one case, create it now. + MatcherPtr.reset(new CheckTypeMatcher(Cases[0].first, 0)); + MatcherPtr->setNext(Cases[0].second); + } + return; + } + + + // Reassemble the Scope node with the adjusted children. + Scope->setNumChildren(NewOptionsToMatch.size()); + for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) + Scope->resetChild(i, NewOptionsToMatch[i]); +} + +Matcher *llvm::OptimizeMatcher(Matcher *TheMatcher, + const CodeGenDAGPatterns &CGP) { + OwningPtr<Matcher> MatcherPtr(TheMatcher); + ContractNodes(MatcherPtr, CGP); + SinkPatternPredicates(MatcherPtr); + FactorNodes(MatcherPtr); + return MatcherPtr.take(); +} diff --git a/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp new file mode 100644 index 0000000..4abf54e --- /dev/null +++ b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp @@ -0,0 +1,512 @@ +//===- DFAPacketizerEmitter.cpp - Packetization DFA for a VLIW machine-----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class parses the Schedule.td file and produces an API that can be used +// to reason about whether an instruction can be added to a packet on a VLIW +// architecture. The class internally generates a deterministic finite +// automaton (DFA) that models all possible mappings of machine instructions +// to functional units as instructions are added to a packet. +// +//===----------------------------------------------------------------------===// + +#include "llvm/TableGen/Record.h" +#include "CodeGenTarget.h" +#include "DFAPacketizerEmitter.h" +#include <list> + +using namespace llvm; + +// +// +// State represents the usage of machine resources if the packet contains +// a set of instruction classes. +// +// Specifically, currentState is a set of bit-masks. +// The nth bit in a bit-mask indicates whether the nth resource is being used +// by this state. The set of bit-masks in a state represent the different +// possible outcomes of transitioning to this state. +// For example: consider a two resource architecture: resource L and resource M +// with three instruction classes: L, M, and L_or_M. +// From the initial state (currentState = 0x00), if we add instruction class +// L_or_M we will transition to a state with currentState = [0x01, 0x10]. This +// represents the possible resource states that can result from adding a L_or_M +// instruction +// +// Another way of thinking about this transition is we are mapping a NDFA with +// two states [0x01] and [0x10] into a DFA with a single state [0x01, 0x10]. +// +// +namespace { +class State { + public: + static int currentStateNum; + int stateNum; + bool isInitial; + std::set<unsigned> stateInfo; + + State(); + State(const State &S); + + // + // canAddInsnClass - Returns true if an instruction of type InsnClass is a + // valid transition from this state, i.e., can an instruction of type InsnClass + // be added to the packet represented by this state. + // + // PossibleStates is the set of valid resource states that ensue from valid + // transitions. + // + bool canAddInsnClass(unsigned InsnClass, std::set<unsigned> &PossibleStates); +}; +} // End anonymous namespace. + + +namespace { +struct Transition { + public: + static int currentTransitionNum; + int transitionNum; + State *from; + unsigned input; + State *to; + + Transition(State *from_, unsigned input_, State *to_); +}; +} // End anonymous namespace. + + +// +// Comparators to keep set of states sorted. +// +namespace { +struct ltState { + bool operator()(const State *s1, const State *s2) const; +}; +} // End anonymous namespace. + + +// +// class DFA: deterministic finite automaton for processor resource tracking. +// +namespace { +class DFA { +public: + DFA(); + + // Set of states. Need to keep this sorted to emit the transition table. + std::set<State*, ltState> states; + + // Map from a state to the list of transitions with that state as source. + std::map<State*, SmallVector<Transition*, 16>, ltState> stateTransitions; + State *currentState; + + // Highest valued Input seen. + unsigned LargestInput; + + // + // Modify the DFA. + // + void initialize(); + void addState(State *); + void addTransition(Transition *); + + // + // getTransition - Return the state when a transition is made from + // State From with Input I. If a transition is not found, return NULL. + // + State *getTransition(State *, unsigned); + + // + // isValidTransition: Predicate that checks if there is a valid transition + // from state From on input InsnClass. + // + bool isValidTransition(State *From, unsigned InsnClass); + + // + // writeTable: Print out a table representing the DFA. + // + void writeTableAndAPI(raw_ostream &OS, const std::string &ClassName); +}; +} // End anonymous namespace. + + +// +// Constructors for State, Transition, and DFA +// +State::State() : + stateNum(currentStateNum++), isInitial(false) {} + + +State::State(const State &S) : + stateNum(currentStateNum++), isInitial(S.isInitial), + stateInfo(S.stateInfo) {} + + +Transition::Transition(State *from_, unsigned input_, State *to_) : + transitionNum(currentTransitionNum++), from(from_), input(input_), + to(to_) {} + + +DFA::DFA() : + LargestInput(0) {} + + +bool ltState::operator()(const State *s1, const State *s2) const { + return (s1->stateNum < s2->stateNum); +} + + +// +// canAddInsnClass - Returns true if an instruction of type InsnClass is a +// valid transition from this state i.e., can an instruction of type InsnClass +// be added to the packet represented by this state. +// +// PossibleStates is the set of valid resource states that ensue from valid +// transitions. +// +bool State::canAddInsnClass(unsigned InsnClass, + std::set<unsigned> &PossibleStates) { + // + // Iterate over all resource states in currentState. + // + bool AddedState = false; + + for (std::set<unsigned>::iterator SI = stateInfo.begin(); + SI != stateInfo.end(); ++SI) { + unsigned thisState = *SI; + + // + // Iterate over all possible resources used in InsnClass. + // For ex: for InsnClass = 0x11, all resources = {0x01, 0x10}. + // + + DenseSet<unsigned> VisitedResourceStates; + for (unsigned int j = 0; j < sizeof(InsnClass) * 8; ++j) { + if ((0x1 << j) & InsnClass) { + // + // For each possible resource used in InsnClass, generate the + // resource state if that resource was used. + // + unsigned ResultingResourceState = thisState | (0x1 << j); + // + // Check if the resulting resource state can be accommodated in this + // packet. + // We compute ResultingResourceState OR thisState. + // If the result of the OR is different than thisState, it implies + // that there is at least one resource that can be used to schedule + // InsnClass in the current packet. + // Insert ResultingResourceState into PossibleStates only if we haven't + // processed ResultingResourceState before. + // + if ((ResultingResourceState != thisState) && + (VisitedResourceStates.count(ResultingResourceState) == 0)) { + VisitedResourceStates.insert(ResultingResourceState); + PossibleStates.insert(ResultingResourceState); + AddedState = true; + } + } + } + } + + return AddedState; +} + + +void DFA::initialize() { + currentState->isInitial = true; +} + + +void DFA::addState(State *S) { + assert(!states.count(S) && "State already exists"); + states.insert(S); +} + + +void DFA::addTransition(Transition *T) { + // Update LargestInput. + if (T->input > LargestInput) + LargestInput = T->input; + + // Add the new transition. + stateTransitions[T->from].push_back(T); +} + + +// +// getTransition - Return the state when a transition is made from +// State From with Input I. If a transition is not found, return NULL. +// +State *DFA::getTransition(State *From, unsigned I) { + // Do we have a transition from state From? + if (!stateTransitions.count(From)) + return NULL; + + // Do we have a transition from state From with Input I? + for (SmallVector<Transition*, 16>::iterator VI = + stateTransitions[From].begin(); + VI != stateTransitions[From].end(); ++VI) + if ((*VI)->input == I) + return (*VI)->to; + + return NULL; +} + + +bool DFA::isValidTransition(State *From, unsigned InsnClass) { + return (getTransition(From, InsnClass) != NULL); +} + + +int State::currentStateNum = 0; +int Transition::currentTransitionNum = 0; + +DFAGen::DFAGen(RecordKeeper &R): + TargetName(CodeGenTarget(R).getName()), + allInsnClasses(), Records(R) {} + + +// +// writeTableAndAPI - Print out a table representing the DFA and the +// associated API to create a DFA packetizer. +// +// Format: +// DFAStateInputTable[][2] = pairs of <Input, Transition> for all valid +// transitions. +// DFAStateEntryTable[i] = Index of the first entry in DFAStateInputTable for +// the ith state. +// +// +void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName) { + std::set<State*, ltState>::iterator SI = states.begin(); + // This table provides a map to the beginning of the transitions for State s + // in DFAStateInputTable. + std::vector<int> StateEntry(states.size()); + + OS << "namespace llvm {\n\n"; + OS << "const int " << TargetName << "DFAStateInputTable[][2] = {\n"; + + // Tracks the total valid transitions encountered so far. It is used + // to construct the StateEntry table. + int ValidTransitions = 0; + for (unsigned i = 0; i < states.size(); ++i, ++SI) { + StateEntry[i] = ValidTransitions; + for (unsigned j = 0; j <= LargestInput; ++j) { + assert (((*SI)->stateNum == (int) i) && "Mismatch in state numbers"); + if (!isValidTransition(*SI, j)) + continue; + + OS << "{" << j << ", " + << getTransition(*SI, j)->stateNum + << "}, "; + ++ValidTransitions; + } + + // If there are no valid transitions from this stage, we need a sentinel + // transition. + if (ValidTransitions == StateEntry[i]) { + OS << "{-1, -1},"; + ++ValidTransitions; + } + + OS << "\n"; + } + OS << "};\n\n"; + OS << "const unsigned int " << TargetName << "DFAStateEntryTable[] = {\n"; + + // Multiply i by 2 since each entry in DFAStateInputTable is a set of + // two numbers. + for (unsigned i = 0; i < states.size(); ++i) + OS << StateEntry[i] << ", "; + + OS << "\n};\n"; + OS << "} // namespace\n"; + + + // + // Emit DFA Packetizer tables if the target is a VLIW machine. + // + std::string SubTargetClassName = TargetName + "GenSubtargetInfo"; + OS << "\n" << "#include \"llvm/CodeGen/DFAPacketizer.h\"\n"; + OS << "namespace llvm {\n"; + OS << "DFAPacketizer *" << SubTargetClassName << "::" + << "createDFAPacketizer(const InstrItineraryData *IID) const {\n" + << " return new DFAPacketizer(IID, " << TargetName + << "DFAStateInputTable, " << TargetName << "DFAStateEntryTable);\n}\n\n"; + OS << "} // End llvm namespace \n"; +} + + +// +// collectAllInsnClasses - Populate allInsnClasses which is a set of units +// used in each stage. +// +void DFAGen::collectAllInsnClasses(const std::string &Name, + Record *ItinData, + unsigned &NStages, + raw_ostream &OS) { + // Collect processor itineraries. + std::vector<Record*> ProcItinList = + Records.getAllDerivedDefinitions("ProcessorItineraries"); + + // If just no itinerary then don't bother. + if (ProcItinList.size() < 2) + return; + std::map<std::string, unsigned> NameToBitsMap; + + // Parse functional units for all the itineraries. + for (unsigned i = 0, N = ProcItinList.size(); i < N; ++i) { + Record *Proc = ProcItinList[i]; + std::vector<Record*> FUs = Proc->getValueAsListOfDefs("FU"); + + // Convert macros to bits for each stage. + for (unsigned i = 0, N = FUs.size(); i < N; ++i) + NameToBitsMap[FUs[i]->getName()] = (unsigned) (1U << i); + } + + const std::vector<Record*> &StageList = + ItinData->getValueAsListOfDefs("Stages"); + + // The number of stages. + NStages = StageList.size(); + + // For each unit. + unsigned UnitBitValue = 0; + + // Compute the bitwise or of each unit used in this stage. + for (unsigned i = 0; i < NStages; ++i) { + const Record *Stage = StageList[i]; + + // Get unit list. + const std::vector<Record*> &UnitList = + Stage->getValueAsListOfDefs("Units"); + + for (unsigned j = 0, M = UnitList.size(); j < M; ++j) { + // Conduct bitwise or. + std::string UnitName = UnitList[j]->getName(); + assert(NameToBitsMap.count(UnitName)); + UnitBitValue |= NameToBitsMap[UnitName]; + } + + if (UnitBitValue != 0) + allInsnClasses.insert(UnitBitValue); + } +} + + +// +// Run the worklist algorithm to generate the DFA. +// +void DFAGen::run(raw_ostream &OS) { + EmitSourceFileHeader("Target DFA Packetizer Tables", OS); + + // Collect processor iteraries. + std::vector<Record*> ProcItinList = + Records.getAllDerivedDefinitions("ProcessorItineraries"); + + // + // Collect the instruction classes. + // + for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) { + Record *Proc = ProcItinList[i]; + + // Get processor itinerary name. + const std::string &Name = Proc->getName(); + + // Skip default. + if (Name == "NoItineraries") + continue; + + // Sanity check for at least one instruction itinerary class. + unsigned NItinClasses = + Records.getAllDerivedDefinitions("InstrItinClass").size(); + if (NItinClasses == 0) + return; + + // Get itinerary data list. + std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID"); + + // Collect instruction classes for all itinerary data. + for (unsigned j = 0, M = ItinDataList.size(); j < M; j++) { + Record *ItinData = ItinDataList[j]; + unsigned NStages; + collectAllInsnClasses(Name, ItinData, NStages, OS); + } + } + + + // + // Run a worklist algorithm to generate the DFA. + // + DFA D; + State *Initial = new State; + Initial->isInitial = true; + Initial->stateInfo.insert(0x0); + D.addState(Initial); + SmallVector<State*, 32> WorkList; + std::map<std::set<unsigned>, State*> Visited; + + WorkList.push_back(Initial); + + // + // Worklist algorithm to create a DFA for processor resource tracking. + // C = {set of InsnClasses} + // Begin with initial node in worklist. Initial node does not have + // any consumed resources, + // ResourceState = 0x0 + // Visited = {} + // While worklist != empty + // S = first element of worklist + // For every instruction class C + // if we can accommodate C in S: + // S' = state with resource states = {S Union C} + // Add a new transition: S x C -> S' + // If S' is not in Visited: + // Add S' to worklist + // Add S' to Visited + // + while (!WorkList.empty()) { + State *current = WorkList.pop_back_val(); + for (DenseSet<unsigned>::iterator CI = allInsnClasses.begin(), + CE = allInsnClasses.end(); CI != CE; ++CI) { + unsigned InsnClass = *CI; + + std::set<unsigned> NewStateResources; + // + // If we haven't already created a transition for this input + // and the state can accommodate this InsnClass, create a transition. + // + if (!D.getTransition(current, InsnClass) && + current->canAddInsnClass(InsnClass, NewStateResources)) { + State *NewState = NULL; + + // + // If we have seen this state before, then do not create a new state. + // + // + std::map<std::set<unsigned>, State*>::iterator VI; + if ((VI = Visited.find(NewStateResources)) != Visited.end()) + NewState = VI->second; + else { + NewState = new State; + NewState->stateInfo = NewStateResources; + D.addState(NewState); + Visited[NewStateResources] = NewState; + WorkList.push_back(NewState); + } + + Transition *NewTransition = new Transition(current, InsnClass, + NewState); + D.addTransition(NewTransition); + } + } + } + + // Print out the table. + D.writeTableAndAPI(OS, TargetName); +} diff --git a/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.h b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.h new file mode 100644 index 0000000..1727150 --- /dev/null +++ b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.h @@ -0,0 +1,52 @@ +//===- DFAPacketizerEmitter.h - Packetization DFA for a VLIW machine-------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class parses the Schedule.td file and produces an API that can be used +// to reason about whether an instruction can be added to a packet on a VLIW +// architecture. The class internally generates a deterministic finite +// automaton (DFA) that models all possible mappings of machine instructions +// to functional units as instructions are added to a packet. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/DenseSet.h" +#include "llvm/TableGen/TableGenBackend.h" +#include <map> +#include <string> + +namespace llvm { +// +// class DFAGen: class that generates and prints out the DFA for resource +// tracking. +// +class DFAGen : public TableGenBackend { +private: + std::string TargetName; + // + // allInsnClasses is the set of all possible resources consumed by an + // InstrStage. + // + DenseSet<unsigned> allInsnClasses; + RecordKeeper &Records; + +public: + DFAGen(RecordKeeper &R); + + // + // collectAllInsnClasses: Populate allInsnClasses which is a set of units + // used in each stage. + // + void collectAllInsnClasses(const std::string &Name, + Record *ItinData, + unsigned &NStages, + raw_ostream &OS); + + void run(raw_ostream &OS); +}; +} diff --git a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp new file mode 100644 index 0000000..4650197 --- /dev/null +++ b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp @@ -0,0 +1,142 @@ +//===- DisassemblerEmitter.cpp - Generate a disassembler ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DisassemblerEmitter.h" +#include "CodeGenTarget.h" +#include "X86DisassemblerTables.h" +#include "X86RecognizableInstr.h" +#include "FixedLenDecoderEmitter.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" + +using namespace llvm; +using namespace llvm::X86Disassembler; + +/// DisassemblerEmitter - Contains disassembler table emitters for various +/// architectures. + +/// X86 Disassembler Emitter +/// +/// *** IF YOU'RE HERE TO RESOLVE A "Primary decode conflict", LOOK DOWN NEAR +/// THE END OF THIS COMMENT! +/// +/// The X86 disassembler emitter is part of the X86 Disassembler, which is +/// documented in lib/Target/X86/X86Disassembler.h. +/// +/// The emitter produces the tables that the disassembler uses to translate +/// instructions. The emitter generates the following tables: +/// +/// - One table (CONTEXTS_SYM) that contains a mapping of attribute masks to +/// instruction contexts. Although for each attribute there are cases where +/// that attribute determines decoding, in the majority of cases decoding is +/// the same whether or not an attribute is present. For example, a 64-bit +/// instruction with an OPSIZE prefix and an XS prefix decodes the same way in +/// all cases as a 64-bit instruction with only OPSIZE set. (The XS prefix +/// may have effects on its execution, but does not change the instruction +/// returned.) This allows considerable space savings in other tables. +/// - Six tables (ONEBYTE_SYM, TWOBYTE_SYM, THREEBYTE38_SYM, THREEBYTE3A_SYM, +/// THREEBYTEA6_SYM, and THREEBYTEA7_SYM contain the hierarchy that the +/// decoder traverses while decoding an instruction. At the lowest level of +/// this hierarchy are instruction UIDs, 16-bit integers that can be used to +/// uniquely identify the instruction and correspond exactly to its position +/// in the list of CodeGenInstructions for the target. +/// - One table (INSTRUCTIONS_SYM) contains information about the operands of +/// each instruction and how to decode them. +/// +/// During table generation, there may be conflicts between instructions that +/// occupy the same space in the decode tables. These conflicts are resolved as +/// follows in setTableFields() (X86DisassemblerTables.cpp) +/// +/// - If the current context is the native context for one of the instructions +/// (that is, the attributes specified for it in the LLVM tables specify +/// precisely the current context), then it has priority. +/// - If the current context isn't native for either of the instructions, then +/// the higher-priority context wins (that is, the one that is more specific). +/// That hierarchy is determined by outranks() (X86DisassemblerTables.cpp) +/// - If the current context is native for both instructions, then the table +/// emitter reports a conflict and dies. +/// +/// *** RESOLUTION FOR "Primary decode conflict"S +/// +/// If two instructions collide, typically the solution is (in order of +/// likelihood): +/// +/// (1) to filter out one of the instructions by editing filter() +/// (X86RecognizableInstr.cpp). This is the most common resolution, but +/// check the Intel manuals first to make sure that (2) and (3) are not the +/// problem. +/// (2) to fix the tables (X86.td and its subsidiaries) so the opcodes are +/// accurate. Sometimes they are not. +/// (3) to fix the tables to reflect the actual context (for example, required +/// prefixes), and possibly to add a new context by editing +/// lib/Target/X86/X86DisassemblerDecoderCommon.h. This is unlikely to be +/// the cause. +/// +/// DisassemblerEmitter.cpp contains the implementation for the emitter, +/// which simply pulls out instructions from the CodeGenTarget and pushes them +/// into X86DisassemblerTables. +/// X86DisassemblerTables.h contains the interface for the instruction tables, +/// which manage and emit the structures discussed above. +/// X86DisassemblerTables.cpp contains the implementation for the instruction +/// tables. +/// X86ModRMFilters.h contains filters that can be used to determine which +/// ModR/M values are valid for a particular instruction. These are used to +/// populate ModRMDecisions. +/// X86RecognizableInstr.h contains the interface for a single instruction, +/// which knows how to translate itself from a CodeGenInstruction and provide +/// the information necessary for integration into the tables. +/// X86RecognizableInstr.cpp contains the implementation for a single +/// instruction. + +void DisassemblerEmitter::run(raw_ostream &OS) { + CodeGenTarget Target(Records); + + OS << "/*===- TableGen'erated file " + << "---------------------------------------*- C -*-===*\n" + << " *\n" + << " * " << Target.getName() << " Disassembler\n" + << " *\n" + << " * Automatically generated file, do not edit!\n" + << " *\n" + << " *===---------------------------------------------------------------" + << "-------===*/\n"; + + // X86 uses a custom disassembler. + if (Target.getName() == "X86") { + DisassemblerTables Tables; + + const std::vector<const CodeGenInstruction*> &numberedInstructions = + Target.getInstructionsByEnumValue(); + + for (unsigned i = 0, e = numberedInstructions.size(); i != e; ++i) + RecognizableInstr::processInstr(Tables, *numberedInstructions[i], i); + + // FIXME: As long as we are using exceptions, might as well drop this to the + // actual conflict site. + if (Tables.hasConflicts()) + throw TGError(Target.getTargetRecord()->getLoc(), + "Primary decode conflict"); + + Tables.emit(OS); + return; + } + + // ARM and Thumb have a CHECK() macro to deal with DecodeStatuses. + if (Target.getName() == "ARM" || + Target.getName() == "Thumb") { + FixedLenDecoderEmitter(Records, + "ARM", + "if (!Check(S, ", ")) return MCDisassembler::Fail;", + "S", "MCDisassembler::Fail", + " MCDisassembler::DecodeStatus S = MCDisassembler::Success;\n(void)S;").run(OS); + return; + } + + FixedLenDecoderEmitter(Records, Target.getName()).run(OS); +} diff --git a/contrib/llvm/utils/TableGen/DisassemblerEmitter.h b/contrib/llvm/utils/TableGen/DisassemblerEmitter.h new file mode 100644 index 0000000..63ee552 --- /dev/null +++ b/contrib/llvm/utils/TableGen/DisassemblerEmitter.h @@ -0,0 +1,28 @@ +//===- DisassemblerEmitter.h - Disassembler Generator -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef DISASSEMBLEREMITTER_H +#define DISASSEMBLEREMITTER_H + +#include "llvm/TableGen/TableGenBackend.h" + +namespace llvm { + + class DisassemblerEmitter : public TableGenBackend { + RecordKeeper &Records; + public: + DisassemblerEmitter(RecordKeeper &R) : Records(R) {} + + /// run - Output the disassembler. + void run(raw_ostream &o); + }; + +} // end llvm namespace + +#endif diff --git a/contrib/llvm/utils/TableGen/EDEmitter.cpp b/contrib/llvm/utils/TableGen/EDEmitter.cpp new file mode 100644 index 0000000..fe484ca --- /dev/null +++ b/contrib/llvm/utils/TableGen/EDEmitter.cpp @@ -0,0 +1,991 @@ +//===- EDEmitter.cpp - Generate instruction descriptions for ED -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend is responsible for emitting a description of each +// instruction in a format that the enhanced disassembler can use to tokenize +// and parse instructions. +// +//===----------------------------------------------------------------------===// + +#include "EDEmitter.h" + +#include "AsmWriterInst.h" +#include "CodeGenTarget.h" + +#include "llvm/TableGen/Record.h" +#include "llvm/MC/EDInstInfo.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" + +#include <string> +#include <vector> + +using namespace llvm; + +/////////////////////////////////////////////////////////// +// Support classes for emitting nested C data structures // +/////////////////////////////////////////////////////////// + +namespace { + + class EnumEmitter { + private: + std::string Name; + std::vector<std::string> Entries; + public: + EnumEmitter(const char *N) : Name(N) { + } + int addEntry(const char *e) { + Entries.push_back(std::string(e)); + return Entries.size() - 1; + } + void emit(raw_ostream &o, unsigned int &i) { + o.indent(i) << "enum " << Name.c_str() << " {" << "\n"; + i += 2; + + unsigned int index = 0; + unsigned int numEntries = Entries.size(); + for (index = 0; index < numEntries; ++index) { + o.indent(i) << Entries[index]; + if (index < (numEntries - 1)) + o << ","; + o << "\n"; + } + + i -= 2; + o.indent(i) << "};" << "\n"; + } + + void emitAsFlags(raw_ostream &o, unsigned int &i) { + o.indent(i) << "enum " << Name.c_str() << " {" << "\n"; + i += 2; + + unsigned int index = 0; + unsigned int numEntries = Entries.size(); + unsigned int flag = 1; + for (index = 0; index < numEntries; ++index) { + o.indent(i) << Entries[index] << " = " << format("0x%x", flag); + if (index < (numEntries - 1)) + o << ","; + o << "\n"; + flag <<= 1; + } + + i -= 2; + o.indent(i) << "};" << "\n"; + } + }; + + class ConstantEmitter { + public: + virtual ~ConstantEmitter() { } + virtual void emit(raw_ostream &o, unsigned int &i) = 0; + }; + + class LiteralConstantEmitter : public ConstantEmitter { + private: + bool IsNumber; + union { + int Number; + const char* String; + }; + public: + LiteralConstantEmitter(int number = 0) : + IsNumber(true), + Number(number) { + } + void set(const char *string) { + IsNumber = false; + Number = 0; + String = string; + } + bool is(const char *string) { + return !strcmp(String, string); + } + void emit(raw_ostream &o, unsigned int &i) { + if (IsNumber) + o << Number; + else + o << String; + } + }; + + class CompoundConstantEmitter : public ConstantEmitter { + private: + unsigned int Padding; + std::vector<ConstantEmitter *> Entries; + public: + CompoundConstantEmitter(unsigned int padding = 0) : Padding(padding) { + } + CompoundConstantEmitter &addEntry(ConstantEmitter *e) { + Entries.push_back(e); + + return *this; + } + ~CompoundConstantEmitter() { + while (Entries.size()) { + ConstantEmitter *entry = Entries.back(); + Entries.pop_back(); + delete entry; + } + } + void emit(raw_ostream &o, unsigned int &i) { + o << "{" << "\n"; + i += 2; + + unsigned int index; + unsigned int numEntries = Entries.size(); + + unsigned int numToPrint; + + if (Padding) { + if (numEntries > Padding) { + fprintf(stderr, "%u entries but %u padding\n", numEntries, Padding); + llvm_unreachable("More entries than padding"); + } + numToPrint = Padding; + } else { + numToPrint = numEntries; + } + + for (index = 0; index < numToPrint; ++index) { + o.indent(i); + if (index < numEntries) + Entries[index]->emit(o, i); + else + o << "-1"; + + if (index < (numToPrint - 1)) + o << ","; + o << "\n"; + } + + i -= 2; + o.indent(i) << "}"; + } + }; + + class FlagsConstantEmitter : public ConstantEmitter { + private: + std::vector<std::string> Flags; + public: + FlagsConstantEmitter() { + } + FlagsConstantEmitter &addEntry(const char *f) { + Flags.push_back(std::string(f)); + return *this; + } + void emit(raw_ostream &o, unsigned int &i) { + unsigned int index; + unsigned int numFlags = Flags.size(); + if (numFlags == 0) + o << "0"; + + for (index = 0; index < numFlags; ++index) { + o << Flags[index].c_str(); + if (index < (numFlags - 1)) + o << " | "; + } + } + }; +} + +EDEmitter::EDEmitter(RecordKeeper &R) : Records(R) { +} + +/// populateOperandOrder - Accepts a CodeGenInstruction and generates its +/// AsmWriterInst for the desired assembly syntax, giving an ordered list of +/// operands in the order they appear in the printed instruction. Then, for +/// each entry in that list, determines the index of the same operand in the +/// CodeGenInstruction, and emits the resulting mapping into an array, filling +/// in unused slots with -1. +/// +/// @arg operandOrder - The array that will be populated with the operand +/// mapping. Each entry will contain -1 (invalid index +/// into the operands present in the AsmString) or a number +/// representing an index in the operand descriptor array. +/// @arg inst - The instruction to use when looking up the operands +/// @arg syntax - The syntax to use, according to LLVM's enumeration +void populateOperandOrder(CompoundConstantEmitter *operandOrder, + const CodeGenInstruction &inst, + unsigned syntax) { + unsigned int numArgs = 0; + + AsmWriterInst awInst(inst, syntax, -1, -1); + + std::vector<AsmWriterOperand>::iterator operandIterator; + + for (operandIterator = awInst.Operands.begin(); + operandIterator != awInst.Operands.end(); + ++operandIterator) { + if (operandIterator->OperandType == + AsmWriterOperand::isMachineInstrOperand) { + operandOrder->addEntry( + new LiteralConstantEmitter(operandIterator->CGIOpNo)); + numArgs++; + } + } +} + +///////////////////////////////////////////////////// +// Support functions for handling X86 instructions // +///////////////////////////////////////////////////// + +#define SET(flag) { type->set(flag); return 0; } + +#define REG(str) if (name == str) SET("kOperandTypeRegister"); +#define MEM(str) if (name == str) SET("kOperandTypeX86Memory"); +#define LEA(str) if (name == str) SET("kOperandTypeX86EffectiveAddress"); +#define IMM(str) if (name == str) SET("kOperandTypeImmediate"); +#define PCR(str) if (name == str) SET("kOperandTypeX86PCRelative"); + +/// X86TypeFromOpName - Processes the name of a single X86 operand (which is +/// actually its type) and translates it into an operand type +/// +/// @arg flags - The type object to set +/// @arg name - The name of the operand +static int X86TypeFromOpName(LiteralConstantEmitter *type, + const std::string &name) { + REG("GR8"); + REG("GR8_NOREX"); + REG("GR16"); + REG("GR16_NOAX"); + REG("GR32"); + REG("GR32_NOAX"); + REG("GR32_NOREX"); + REG("GR32_TC"); + REG("FR32"); + REG("RFP32"); + REG("GR64"); + REG("GR64_NOAX"); + REG("GR64_TC"); + REG("FR64"); + REG("VR64"); + REG("RFP64"); + REG("RFP80"); + REG("VR128"); + REG("VR256"); + REG("RST"); + REG("SEGMENT_REG"); + REG("DEBUG_REG"); + REG("CONTROL_REG"); + + IMM("i8imm"); + IMM("i16imm"); + IMM("i16i8imm"); + IMM("i32imm"); + IMM("i32i8imm"); + IMM("u32u8imm"); + IMM("i64imm"); + IMM("i64i8imm"); + IMM("i64i32imm"); + IMM("SSECC"); + IMM("AVXCC"); + + // all R, I, R, I, R + MEM("i8mem"); + MEM("i8mem_NOREX"); + MEM("i16mem"); + MEM("i32mem"); + MEM("i32mem_TC"); + MEM("f32mem"); + MEM("ssmem"); + MEM("opaque32mem"); + MEM("opaque48mem"); + MEM("i64mem"); + MEM("i64mem_TC"); + MEM("f64mem"); + MEM("sdmem"); + MEM("f80mem"); + MEM("opaque80mem"); + MEM("i128mem"); + MEM("i256mem"); + MEM("f128mem"); + MEM("f256mem"); + MEM("opaque512mem"); + + // all R, I, R, I + LEA("lea32mem"); + LEA("lea64_32mem"); + LEA("lea64mem"); + + // all I + PCR("i16imm_pcrel"); + PCR("i32imm_pcrel"); + PCR("i64i32imm_pcrel"); + PCR("brtarget8"); + PCR("offset8"); + PCR("offset16"); + PCR("offset32"); + PCR("offset64"); + PCR("brtarget"); + PCR("uncondbrtarget"); + PCR("bltarget"); + + // all I, ARM mode only, conditional/unconditional + PCR("br_target"); + PCR("bl_target"); + return 1; +} + +#undef REG +#undef MEM +#undef LEA +#undef IMM +#undef PCR + +#undef SET + +/// X86PopulateOperands - Handles all the operands in an X86 instruction, adding +/// the appropriate flags to their descriptors +/// +/// @operandFlags - A reference the array of operand flag objects +/// @inst - The instruction to use as a source of information +static void X86PopulateOperands( + LiteralConstantEmitter *(&operandTypes)[EDIS_MAX_OPERANDS], + const CodeGenInstruction &inst) { + if (!inst.TheDef->isSubClassOf("X86Inst")) + return; + + unsigned int index; + unsigned int numOperands = inst.Operands.size(); + + for (index = 0; index < numOperands; ++index) { + const CGIOperandList::OperandInfo &operandInfo = inst.Operands[index]; + Record &rec = *operandInfo.Rec; + + if (X86TypeFromOpName(operandTypes[index], rec.getName()) && + !rec.isSubClassOf("PointerLikeRegClass")) { + errs() << "Operand type: " << rec.getName().c_str() << "\n"; + errs() << "Operand name: " << operandInfo.Name.c_str() << "\n"; + errs() << "Instruction name: " << inst.TheDef->getName().c_str() << "\n"; + llvm_unreachable("Unhandled type"); + } + } +} + +/// decorate1 - Decorates a named operand with a new flag +/// +/// @operandFlags - The array of operand flag objects, which don't have names +/// @inst - The CodeGenInstruction, which provides a way to translate +/// between names and operand indices +/// @opName - The name of the operand +/// @flag - The name of the flag to add +static inline void decorate1( + FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS], + const CodeGenInstruction &inst, + const char *opName, + const char *opFlag) { + unsigned opIndex; + + opIndex = inst.Operands.getOperandNamed(std::string(opName)); + + operandFlags[opIndex]->addEntry(opFlag); +} + +#define DECORATE1(opName, opFlag) decorate1(operandFlags, inst, opName, opFlag) + +#define MOV(source, target) { \ + instType.set("kInstructionTypeMove"); \ + DECORATE1(source, "kOperandFlagSource"); \ + DECORATE1(target, "kOperandFlagTarget"); \ +} + +#define BRANCH(target) { \ + instType.set("kInstructionTypeBranch"); \ + DECORATE1(target, "kOperandFlagTarget"); \ +} + +#define PUSH(source) { \ + instType.set("kInstructionTypePush"); \ + DECORATE1(source, "kOperandFlagSource"); \ +} + +#define POP(target) { \ + instType.set("kInstructionTypePop"); \ + DECORATE1(target, "kOperandFlagTarget"); \ +} + +#define CALL(target) { \ + instType.set("kInstructionTypeCall"); \ + DECORATE1(target, "kOperandFlagTarget"); \ +} + +#define RETURN() { \ + instType.set("kInstructionTypeReturn"); \ +} + +/// X86ExtractSemantics - Performs various checks on the name of an X86 +/// instruction to determine what sort of an instruction it is and then adds +/// the appropriate flags to the instruction and its operands +/// +/// @arg instType - A reference to the type for the instruction as a whole +/// @arg operandFlags - A reference to the array of operand flag object pointers +/// @arg inst - A reference to the original instruction +static void X86ExtractSemantics( + LiteralConstantEmitter &instType, + FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS], + const CodeGenInstruction &inst) { + const std::string &name = inst.TheDef->getName(); + + if (name.find("MOV") != name.npos) { + if (name.find("MOV_V") != name.npos) { + // ignore (this is a pseudoinstruction) + } else if (name.find("MASK") != name.npos) { + // ignore (this is a masking move) + } else if (name.find("r0") != name.npos) { + // ignore (this is a pseudoinstruction) + } else if (name.find("PS") != name.npos || + name.find("PD") != name.npos) { + // ignore (this is a shuffling move) + } else if (name.find("MOVS") != name.npos) { + // ignore (this is a string move) + } else if (name.find("_F") != name.npos) { + // TODO handle _F moves to ST(0) + } else if (name.find("a") != name.npos) { + // TODO handle moves to/from %ax + } else if (name.find("CMOV") != name.npos) { + MOV("src2", "dst"); + } else if (name.find("PC") != name.npos) { + MOV("label", "reg") + } else { + MOV("src", "dst"); + } + } + + if (name.find("JMP") != name.npos || + name.find("J") == 0) { + if (name.find("FAR") != name.npos && name.find("i") != name.npos) { + BRANCH("off"); + } else { + BRANCH("dst"); + } + } + + if (name.find("PUSH") != name.npos) { + if (name.find("CS") != name.npos || + name.find("DS") != name.npos || + name.find("ES") != name.npos || + name.find("FS") != name.npos || + name.find("GS") != name.npos || + name.find("SS") != name.npos) { + instType.set("kInstructionTypePush"); + // TODO add support for fixed operands + } else if (name.find("F") != name.npos) { + // ignore (this pushes onto the FP stack) + } else if (name.find("A") != name.npos) { + // ignore (pushes all GP registoers onto the stack) + } else if (name[name.length() - 1] == 'm') { + PUSH("src"); + } else if (name.find("i") != name.npos) { + PUSH("imm"); + } else { + PUSH("reg"); + } + } + + if (name.find("POP") != name.npos) { + if (name.find("POPCNT") != name.npos) { + // ignore (not a real pop) + } else if (name.find("CS") != name.npos || + name.find("DS") != name.npos || + name.find("ES") != name.npos || + name.find("FS") != name.npos || + name.find("GS") != name.npos || + name.find("SS") != name.npos) { + instType.set("kInstructionTypePop"); + // TODO add support for fixed operands + } else if (name.find("F") != name.npos) { + // ignore (this pops from the FP stack) + } else if (name.find("A") != name.npos) { + // ignore (pushes all GP registoers onto the stack) + } else if (name[name.length() - 1] == 'm') { + POP("dst"); + } else { + POP("reg"); + } + } + + if (name.find("CALL") != name.npos) { + if (name.find("ADJ") != name.npos) { + // ignore (not a call) + } else if (name.find("SYSCALL") != name.npos) { + // ignore (doesn't go anywhere we know about) + } else if (name.find("VMCALL") != name.npos) { + // ignore (rather different semantics than a regular call) + } else if (name.find("VMMCALL") != name.npos) { + // ignore (rather different semantics than a regular call) + } else if (name.find("FAR") != name.npos && name.find("i") != name.npos) { + CALL("off"); + } else { + CALL("dst"); + } + } + + if (name.find("RET") != name.npos) { + RETURN(); + } +} + +#undef MOV +#undef BRANCH +#undef PUSH +#undef POP +#undef CALL +#undef RETURN + +///////////////////////////////////////////////////// +// Support functions for handling ARM instructions // +///////////////////////////////////////////////////// + +#define SET(flag) { type->set(flag); return 0; } + +#define REG(str) if (name == str) SET("kOperandTypeRegister"); +#define IMM(str) if (name == str) SET("kOperandTypeImmediate"); + +#define MISC(str, type) if (name == str) SET(type); + +/// ARMFlagFromOpName - Processes the name of a single ARM operand (which is +/// actually its type) and translates it into an operand type +/// +/// @arg type - The type object to set +/// @arg name - The name of the operand +static int ARMFlagFromOpName(LiteralConstantEmitter *type, + const std::string &name) { + REG("GPR"); + REG("rGPR"); + REG("GPRnopc"); + REG("GPRsp"); + REG("tcGPR"); + REG("cc_out"); + REG("s_cc_out"); + REG("tGPR"); + REG("DPR"); + REG("DPR_VFP2"); + REG("DPR_8"); + REG("DPair"); + REG("SPR"); + REG("QPR"); + REG("QQPR"); + REG("QQQQPR"); + REG("VecListOneD"); + REG("VecListDPair"); + REG("VecListDPairSpaced"); + REG("VecListThreeD"); + REG("VecListFourD"); + REG("VecListOneDAllLanes"); + REG("VecListDPairAllLanes"); + REG("VecListDPairSpacedAllLanes"); + + IMM("i32imm"); + IMM("fbits16"); + IMM("fbits32"); + IMM("i32imm_hilo16"); + IMM("bf_inv_mask_imm"); + IMM("lsb_pos_imm"); + IMM("width_imm"); + IMM("jtblock_operand"); + IMM("nohash_imm"); + IMM("p_imm"); + IMM("pf_imm"); + IMM("c_imm"); + IMM("coproc_option_imm"); + IMM("imod_op"); + IMM("iflags_op"); + IMM("cpinst_operand"); + IMM("setend_op"); + IMM("cps_opt"); + IMM("vfp_f64imm"); + IMM("vfp_f32imm"); + IMM("memb_opt"); + IMM("msr_mask"); + IMM("neg_zero"); + IMM("imm0_31"); + IMM("imm0_31_m1"); + IMM("imm1_16"); + IMM("imm1_32"); + IMM("nModImm"); + IMM("nImmSplatI8"); + IMM("nImmSplatI16"); + IMM("nImmSplatI32"); + IMM("nImmSplatI64"); + IMM("nImmVMOVI32"); + IMM("nImmVMOVF32"); + IMM("imm8"); + IMM("imm16"); + IMM("imm32"); + IMM("imm1_7"); + IMM("imm1_15"); + IMM("imm1_31"); + IMM("imm0_1"); + IMM("imm0_3"); + IMM("imm0_7"); + IMM("imm0_15"); + IMM("imm0_255"); + IMM("imm0_4095"); + IMM("imm0_65535"); + IMM("imm0_65535_expr"); + IMM("imm24b"); + IMM("pkh_lsl_amt"); + IMM("pkh_asr_amt"); + IMM("jt2block_operand"); + IMM("t_imm0_1020s4"); + IMM("t_imm0_508s4"); + IMM("pclabel"); + IMM("adrlabel"); + IMM("t_adrlabel"); + IMM("t2adrlabel"); + IMM("shift_imm"); + IMM("t2_shift_imm"); + IMM("neon_vcvt_imm32"); + IMM("shr_imm8"); + IMM("shr_imm16"); + IMM("shr_imm32"); + IMM("shr_imm64"); + IMM("t2ldrlabel"); + IMM("postidx_imm8"); + IMM("postidx_imm8s4"); + IMM("imm_sr"); + IMM("imm1_31"); + IMM("VectorIndex8"); + IMM("VectorIndex16"); + IMM("VectorIndex32"); + + MISC("brtarget", "kOperandTypeARMBranchTarget"); // ? + MISC("uncondbrtarget", "kOperandTypeARMBranchTarget"); // ? + MISC("t_brtarget", "kOperandTypeARMBranchTarget"); // ? + MISC("t_bcctarget", "kOperandTypeARMBranchTarget"); // ? + MISC("t_cbtarget", "kOperandTypeARMBranchTarget"); // ? + MISC("bltarget", "kOperandTypeARMBranchTarget"); // ? + + MISC("br_target", "kOperandTypeARMBranchTarget"); // ? + MISC("bl_target", "kOperandTypeARMBranchTarget"); // ? + MISC("blx_target", "kOperandTypeARMBranchTarget"); // ? + + MISC("t_bltarget", "kOperandTypeARMBranchTarget"); // ? + MISC("t_blxtarget", "kOperandTypeARMBranchTarget"); // ? + MISC("so_reg_imm", "kOperandTypeARMSoRegReg"); // R, R, I + MISC("so_reg_reg", "kOperandTypeARMSoRegImm"); // R, R, I + MISC("shift_so_reg_reg", "kOperandTypeARMSoRegReg"); // R, R, I + MISC("shift_so_reg_imm", "kOperandTypeARMSoRegImm"); // R, R, I + MISC("t2_so_reg", "kOperandTypeThumb2SoReg"); // R, I + MISC("so_imm", "kOperandTypeARMSoImm"); // I + MISC("rot_imm", "kOperandTypeARMRotImm"); // I + MISC("t2_so_imm", "kOperandTypeThumb2SoImm"); // I + MISC("so_imm2part", "kOperandTypeARMSoImm2Part"); // I + MISC("pred", "kOperandTypeARMPredicate"); // I, R + MISC("it_pred", "kOperandTypeARMPredicate"); // I + MISC("addrmode_imm12", "kOperandTypeAddrModeImm12"); // R, I + MISC("ldst_so_reg", "kOperandTypeLdStSOReg"); // R, R, I + MISC("postidx_reg", "kOperandTypeARMAddrMode3Offset"); // R, I + MISC("addrmode2", "kOperandTypeARMAddrMode2"); // R, R, I + MISC("am2offset_reg", "kOperandTypeARMAddrMode2Offset"); // R, I + MISC("am2offset_imm", "kOperandTypeARMAddrMode2Offset"); // R, I + MISC("addrmode3", "kOperandTypeARMAddrMode3"); // R, R, I + MISC("am3offset", "kOperandTypeARMAddrMode3Offset"); // R, I + MISC("ldstm_mode", "kOperandTypeARMLdStmMode"); // I + MISC("addrmode5", "kOperandTypeARMAddrMode5"); // R, I + MISC("addrmode6", "kOperandTypeARMAddrMode6"); // R, R, I, I + MISC("am6offset", "kOperandTypeARMAddrMode6Offset"); // R, I, I + MISC("addrmode6dup", "kOperandTypeARMAddrMode6"); // R, R, I, I + MISC("addrmode6oneL32", "kOperandTypeARMAddrMode6"); // R, R, I, I + MISC("addrmodepc", "kOperandTypeARMAddrModePC"); // R, I + MISC("addr_offset_none", "kOperandTypeARMAddrMode7"); // R + MISC("reglist", "kOperandTypeARMRegisterList"); // I, R, ... + MISC("dpr_reglist", "kOperandTypeARMDPRRegisterList"); // I, R, ... + MISC("spr_reglist", "kOperandTypeARMSPRRegisterList"); // I, R, ... + MISC("it_mask", "kOperandTypeThumbITMask"); // I + MISC("t2addrmode_reg", "kOperandTypeThumb2AddrModeReg"); // R + MISC("t2addrmode_posimm8", "kOperandTypeThumb2AddrModeImm8"); // R, I + MISC("t2addrmode_negimm8", "kOperandTypeThumb2AddrModeImm8"); // R, I + MISC("t2addrmode_imm8", "kOperandTypeThumb2AddrModeImm8"); // R, I + MISC("t2am_imm8_offset", "kOperandTypeThumb2AddrModeImm8Offset");//I + MISC("t2addrmode_imm12", "kOperandTypeThumb2AddrModeImm12"); // R, I + MISC("t2addrmode_so_reg", "kOperandTypeThumb2AddrModeSoReg"); // R, R, I + MISC("t2addrmode_imm8s4", "kOperandTypeThumb2AddrModeImm8s4"); // R, I + MISC("t2addrmode_imm0_1020s4", "kOperandTypeThumb2AddrModeImm8s4"); // R, I + MISC("t2am_imm8s4_offset", "kOperandTypeThumb2AddrModeImm8s4Offset"); + // R, I + MISC("tb_addrmode", "kOperandTypeARMTBAddrMode"); // I + MISC("t_addrmode_rrs1", "kOperandTypeThumbAddrModeRegS1"); // R, R + MISC("t_addrmode_rrs2", "kOperandTypeThumbAddrModeRegS2"); // R, R + MISC("t_addrmode_rrs4", "kOperandTypeThumbAddrModeRegS4"); // R, R + MISC("t_addrmode_is1", "kOperandTypeThumbAddrModeImmS1"); // R, I + MISC("t_addrmode_is2", "kOperandTypeThumbAddrModeImmS2"); // R, I + MISC("t_addrmode_is4", "kOperandTypeThumbAddrModeImmS4"); // R, I + MISC("t_addrmode_rr", "kOperandTypeThumbAddrModeRR"); // R, R + MISC("t_addrmode_sp", "kOperandTypeThumbAddrModeSP"); // R, I + MISC("t_addrmode_pc", "kOperandTypeThumbAddrModePC"); // R, I + MISC("addrmode_tbb", "kOperandTypeThumbAddrModeRR"); // R, R + MISC("addrmode_tbh", "kOperandTypeThumbAddrModeRR"); // R, R + + return 1; +} + +#undef REG +#undef MEM +#undef MISC + +#undef SET + +/// ARMPopulateOperands - Handles all the operands in an ARM instruction, adding +/// the appropriate flags to their descriptors +/// +/// @operandFlags - A reference the array of operand flag objects +/// @inst - The instruction to use as a source of information +static void ARMPopulateOperands( + LiteralConstantEmitter *(&operandTypes)[EDIS_MAX_OPERANDS], + const CodeGenInstruction &inst) { + if (!inst.TheDef->isSubClassOf("InstARM") && + !inst.TheDef->isSubClassOf("InstThumb")) + return; + + unsigned int index; + unsigned int numOperands = inst.Operands.size(); + + if (numOperands > EDIS_MAX_OPERANDS) { + errs() << "numOperands == " << numOperands << " > " << + EDIS_MAX_OPERANDS << '\n'; + llvm_unreachable("Too many operands"); + } + + for (index = 0; index < numOperands; ++index) { + const CGIOperandList::OperandInfo &operandInfo = inst.Operands[index]; + Record &rec = *operandInfo.Rec; + + if (ARMFlagFromOpName(operandTypes[index], rec.getName())) { + errs() << "Operand type: " << rec.getName() << '\n'; + errs() << "Operand name: " << operandInfo.Name << '\n'; + errs() << "Instruction name: " << inst.TheDef->getName() << '\n'; + throw("Unhandled type in EDEmitter"); + } + } +} + +#define BRANCH(target) { \ + instType.set("kInstructionTypeBranch"); \ + DECORATE1(target, "kOperandFlagTarget"); \ +} + +/// ARMExtractSemantics - Performs various checks on the name of an ARM +/// instruction to determine what sort of an instruction it is and then adds +/// the appropriate flags to the instruction and its operands +/// +/// @arg instType - A reference to the type for the instruction as a whole +/// @arg operandTypes - A reference to the array of operand type object pointers +/// @arg operandFlags - A reference to the array of operand flag object pointers +/// @arg inst - A reference to the original instruction +static void ARMExtractSemantics( + LiteralConstantEmitter &instType, + LiteralConstantEmitter *(&operandTypes)[EDIS_MAX_OPERANDS], + FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS], + const CodeGenInstruction &inst) { + const std::string &name = inst.TheDef->getName(); + + if (name == "tBcc" || + name == "tB" || + name == "t2Bcc" || + name == "Bcc" || + name == "tCBZ" || + name == "tCBNZ") { + BRANCH("target"); + } + + if (name == "tBLr9" || + name == "BLr9_pred" || + name == "tBLXi_r9" || + name == "tBLXr_r9" || + name == "BLXr9" || + name == "t2BXJ" || + name == "BXJ") { + BRANCH("func"); + + unsigned opIndex; + opIndex = inst.Operands.getOperandNamed("func"); + if (operandTypes[opIndex]->is("kOperandTypeImmediate")) + operandTypes[opIndex]->set("kOperandTypeARMBranchTarget"); + } +} + +#undef BRANCH + +/// populateInstInfo - Fills an array of InstInfos with information about each +/// instruction in a target +/// +/// @arg infoArray - The array of InstInfo objects to populate +/// @arg target - The CodeGenTarget to use as a source of instructions +static void populateInstInfo(CompoundConstantEmitter &infoArray, + CodeGenTarget &target) { + const std::vector<const CodeGenInstruction*> &numberedInstructions = + target.getInstructionsByEnumValue(); + + unsigned int index; + unsigned int numInstructions = numberedInstructions.size(); + + for (index = 0; index < numInstructions; ++index) { + const CodeGenInstruction& inst = *numberedInstructions[index]; + + CompoundConstantEmitter *infoStruct = new CompoundConstantEmitter; + infoArray.addEntry(infoStruct); + + LiteralConstantEmitter *instType = new LiteralConstantEmitter; + infoStruct->addEntry(instType); + + LiteralConstantEmitter *numOperandsEmitter = + new LiteralConstantEmitter(inst.Operands.size()); + infoStruct->addEntry(numOperandsEmitter); + + CompoundConstantEmitter *operandTypeArray = new CompoundConstantEmitter; + infoStruct->addEntry(operandTypeArray); + + LiteralConstantEmitter *operandTypes[EDIS_MAX_OPERANDS]; + + CompoundConstantEmitter *operandFlagArray = new CompoundConstantEmitter; + infoStruct->addEntry(operandFlagArray); + + FlagsConstantEmitter *operandFlags[EDIS_MAX_OPERANDS]; + + for (unsigned operandIndex = 0; + operandIndex < EDIS_MAX_OPERANDS; + ++operandIndex) { + operandTypes[operandIndex] = new LiteralConstantEmitter; + operandTypeArray->addEntry(operandTypes[operandIndex]); + + operandFlags[operandIndex] = new FlagsConstantEmitter; + operandFlagArray->addEntry(operandFlags[operandIndex]); + } + + unsigned numSyntaxes = 0; + + // We don't need to do anything for pseudo-instructions, as we'll never + // see them here. We'll only see real instructions. + // We still need to emit null initializers for everything. + if (!inst.isPseudo) { + if (target.getName() == "X86") { + X86PopulateOperands(operandTypes, inst); + X86ExtractSemantics(*instType, operandFlags, inst); + numSyntaxes = 2; + } + else if (target.getName() == "ARM") { + ARMPopulateOperands(operandTypes, inst); + ARMExtractSemantics(*instType, operandTypes, operandFlags, inst); + numSyntaxes = 1; + } + } + + CompoundConstantEmitter *operandOrderArray = new CompoundConstantEmitter; + + infoStruct->addEntry(operandOrderArray); + + for (unsigned syntaxIndex = 0; + syntaxIndex < EDIS_MAX_SYNTAXES; + ++syntaxIndex) { + CompoundConstantEmitter *operandOrder = + new CompoundConstantEmitter(EDIS_MAX_OPERANDS); + + operandOrderArray->addEntry(operandOrder); + + if (syntaxIndex < numSyntaxes) { + populateOperandOrder(operandOrder, inst, syntaxIndex); + } + } + + infoStruct = NULL; + } +} + +static void emitCommonEnums(raw_ostream &o, unsigned int &i) { + EnumEmitter operandTypes("OperandTypes"); + operandTypes.addEntry("kOperandTypeNone"); + operandTypes.addEntry("kOperandTypeImmediate"); + operandTypes.addEntry("kOperandTypeRegister"); + operandTypes.addEntry("kOperandTypeX86Memory"); + operandTypes.addEntry("kOperandTypeX86EffectiveAddress"); + operandTypes.addEntry("kOperandTypeX86PCRelative"); + operandTypes.addEntry("kOperandTypeARMBranchTarget"); + operandTypes.addEntry("kOperandTypeARMSoRegReg"); + operandTypes.addEntry("kOperandTypeARMSoRegImm"); + operandTypes.addEntry("kOperandTypeARMSoImm"); + operandTypes.addEntry("kOperandTypeARMRotImm"); + operandTypes.addEntry("kOperandTypeARMSoImm2Part"); + operandTypes.addEntry("kOperandTypeARMPredicate"); + operandTypes.addEntry("kOperandTypeAddrModeImm12"); + operandTypes.addEntry("kOperandTypeLdStSOReg"); + operandTypes.addEntry("kOperandTypeARMAddrMode2"); + operandTypes.addEntry("kOperandTypeARMAddrMode2Offset"); + operandTypes.addEntry("kOperandTypeARMAddrMode3"); + operandTypes.addEntry("kOperandTypeARMAddrMode3Offset"); + operandTypes.addEntry("kOperandTypeARMLdStmMode"); + operandTypes.addEntry("kOperandTypeARMAddrMode5"); + operandTypes.addEntry("kOperandTypeARMAddrMode6"); + operandTypes.addEntry("kOperandTypeARMAddrMode6Offset"); + operandTypes.addEntry("kOperandTypeARMAddrMode7"); + operandTypes.addEntry("kOperandTypeARMAddrModePC"); + operandTypes.addEntry("kOperandTypeARMRegisterList"); + operandTypes.addEntry("kOperandTypeARMDPRRegisterList"); + operandTypes.addEntry("kOperandTypeARMSPRRegisterList"); + operandTypes.addEntry("kOperandTypeARMTBAddrMode"); + operandTypes.addEntry("kOperandTypeThumbITMask"); + operandTypes.addEntry("kOperandTypeThumbAddrModeImmS1"); + operandTypes.addEntry("kOperandTypeThumbAddrModeImmS2"); + operandTypes.addEntry("kOperandTypeThumbAddrModeImmS4"); + operandTypes.addEntry("kOperandTypeThumbAddrModeRegS1"); + operandTypes.addEntry("kOperandTypeThumbAddrModeRegS2"); + operandTypes.addEntry("kOperandTypeThumbAddrModeRegS4"); + operandTypes.addEntry("kOperandTypeThumbAddrModeRR"); + operandTypes.addEntry("kOperandTypeThumbAddrModeSP"); + operandTypes.addEntry("kOperandTypeThumbAddrModePC"); + operandTypes.addEntry("kOperandTypeThumb2AddrModeReg"); + operandTypes.addEntry("kOperandTypeThumb2SoReg"); + operandTypes.addEntry("kOperandTypeThumb2SoImm"); + operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8"); + operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8Offset"); + operandTypes.addEntry("kOperandTypeThumb2AddrModeImm12"); + operandTypes.addEntry("kOperandTypeThumb2AddrModeSoReg"); + operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8s4"); + operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8s4Offset"); + operandTypes.emit(o, i); + + o << "\n"; + + EnumEmitter operandFlags("OperandFlags"); + operandFlags.addEntry("kOperandFlagSource"); + operandFlags.addEntry("kOperandFlagTarget"); + operandFlags.emitAsFlags(o, i); + + o << "\n"; + + EnumEmitter instructionTypes("InstructionTypes"); + instructionTypes.addEntry("kInstructionTypeNone"); + instructionTypes.addEntry("kInstructionTypeMove"); + instructionTypes.addEntry("kInstructionTypeBranch"); + instructionTypes.addEntry("kInstructionTypePush"); + instructionTypes.addEntry("kInstructionTypePop"); + instructionTypes.addEntry("kInstructionTypeCall"); + instructionTypes.addEntry("kInstructionTypeReturn"); + instructionTypes.emit(o, i); + + o << "\n"; +} + +void EDEmitter::run(raw_ostream &o) { + unsigned int i = 0; + + CompoundConstantEmitter infoArray; + CodeGenTarget target(Records); + + populateInstInfo(infoArray, target); + + emitCommonEnums(o, i); + + o << "static const llvm::EDInstInfo instInfo" << target.getName() << "[] = "; + infoArray.emit(o, i); + o << ";" << "\n"; +} diff --git a/contrib/llvm/utils/TableGen/EDEmitter.h b/contrib/llvm/utils/TableGen/EDEmitter.h new file mode 100644 index 0000000..f268375 --- /dev/null +++ b/contrib/llvm/utils/TableGen/EDEmitter.h @@ -0,0 +1,34 @@ +//===- EDEmitter.h - Generate instruction descriptions for ED ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend is responsible for emitting a description of each +// instruction in a format that the semantic disassembler can use to tokenize +// and parse instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef SEMANTIC_INFO_EMITTER_H +#define SEMANTIC_INFO_EMITTER_H + +#include "llvm/TableGen/TableGenBackend.h" + +namespace llvm { + + class EDEmitter : public TableGenBackend { + RecordKeeper &Records; + public: + EDEmitter(RecordKeeper &R); + + // run - Output the instruction table. + void run(raw_ostream &o); + }; + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/utils/TableGen/FastISelEmitter.cpp b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp new file mode 100644 index 0000000..e8dad77 --- /dev/null +++ b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp @@ -0,0 +1,872 @@ +//===- FastISelEmitter.cpp - Generate an instruction selector -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend emits code for use by the "fast" instruction +// selection algorithm. See the comments at the top of +// lib/CodeGen/SelectionDAG/FastISel.cpp for background. +// +// This file scans through the target's tablegen instruction-info files +// and extracts instructions with obvious-looking patterns, and it emits +// code to look up these instructions by type and operator. +// +//===----------------------------------------------------------------------===// + +#include "FastISelEmitter.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +using namespace llvm; + +namespace { + +/// InstructionMemo - This class holds additional information about an +/// instruction needed to emit code for it. +/// +struct InstructionMemo { + std::string Name; + const CodeGenRegisterClass *RC; + std::string SubRegNo; + std::vector<std::string>* PhysRegs; +}; + +/// ImmPredicateSet - This uniques predicates (represented as a string) and +/// gives them unique (small) integer ID's that start at 0. +class ImmPredicateSet { + DenseMap<TreePattern *, unsigned> ImmIDs; + std::vector<TreePredicateFn> PredsByName; +public: + + unsigned getIDFor(TreePredicateFn Pred) { + unsigned &Entry = ImmIDs[Pred.getOrigPatFragRecord()]; + if (Entry == 0) { + PredsByName.push_back(Pred); + Entry = PredsByName.size(); + } + return Entry-1; + } + + const TreePredicateFn &getPredicate(unsigned i) { + assert(i < PredsByName.size()); + return PredsByName[i]; + } + + typedef std::vector<TreePredicateFn>::const_iterator iterator; + iterator begin() const { return PredsByName.begin(); } + iterator end() const { return PredsByName.end(); } + +}; + +/// OperandsSignature - This class holds a description of a list of operand +/// types. It has utility methods for emitting text based on the operands. +/// +struct OperandsSignature { + class OpKind { + enum { OK_Reg, OK_FP, OK_Imm, OK_Invalid = -1 }; + char Repr; + public: + + OpKind() : Repr(OK_Invalid) {} + + bool operator<(OpKind RHS) const { return Repr < RHS.Repr; } + bool operator==(OpKind RHS) const { return Repr == RHS.Repr; } + + static OpKind getReg() { OpKind K; K.Repr = OK_Reg; return K; } + static OpKind getFP() { OpKind K; K.Repr = OK_FP; return K; } + static OpKind getImm(unsigned V) { + assert((unsigned)OK_Imm+V < 128 && + "Too many integer predicates for the 'Repr' char"); + OpKind K; K.Repr = OK_Imm+V; return K; + } + + bool isReg() const { return Repr == OK_Reg; } + bool isFP() const { return Repr == OK_FP; } + bool isImm() const { return Repr >= OK_Imm; } + + unsigned getImmCode() const { assert(isImm()); return Repr-OK_Imm; } + + void printManglingSuffix(raw_ostream &OS, ImmPredicateSet &ImmPredicates, + bool StripImmCodes) const { + if (isReg()) + OS << 'r'; + else if (isFP()) + OS << 'f'; + else { + OS << 'i'; + if (!StripImmCodes) + if (unsigned Code = getImmCode()) + OS << "_" << ImmPredicates.getPredicate(Code-1).getFnName(); + } + } + }; + + + SmallVector<OpKind, 3> Operands; + + bool operator<(const OperandsSignature &O) const { + return Operands < O.Operands; + } + bool operator==(const OperandsSignature &O) const { + return Operands == O.Operands; + } + + bool empty() const { return Operands.empty(); } + + bool hasAnyImmediateCodes() const { + for (unsigned i = 0, e = Operands.size(); i != e; ++i) + if (Operands[i].isImm() && Operands[i].getImmCode() != 0) + return true; + return false; + } + + /// getWithoutImmCodes - Return a copy of this with any immediate codes forced + /// to zero. + OperandsSignature getWithoutImmCodes() const { + OperandsSignature Result; + for (unsigned i = 0, e = Operands.size(); i != e; ++i) + if (!Operands[i].isImm()) + Result.Operands.push_back(Operands[i]); + else + Result.Operands.push_back(OpKind::getImm(0)); + return Result; + } + + void emitImmediatePredicate(raw_ostream &OS, ImmPredicateSet &ImmPredicates) { + bool EmittedAnything = false; + for (unsigned i = 0, e = Operands.size(); i != e; ++i) { + if (!Operands[i].isImm()) continue; + + unsigned Code = Operands[i].getImmCode(); + if (Code == 0) continue; + + if (EmittedAnything) + OS << " &&\n "; + + TreePredicateFn PredFn = ImmPredicates.getPredicate(Code-1); + + // Emit the type check. + OS << "VT == " + << getEnumName(PredFn.getOrigPatFragRecord()->getTree(0)->getType(0)) + << " && "; + + + OS << PredFn.getFnName() << "(imm" << i <<')'; + EmittedAnything = true; + } + } + + /// initialize - Examine the given pattern and initialize the contents + /// of the Operands array accordingly. Return true if all the operands + /// are supported, false otherwise. + /// + bool initialize(TreePatternNode *InstPatNode, const CodeGenTarget &Target, + MVT::SimpleValueType VT, + ImmPredicateSet &ImmediatePredicates) { + if (InstPatNode->isLeaf()) + return false; + + if (InstPatNode->getOperator()->getName() == "imm") { + Operands.push_back(OpKind::getImm(0)); + return true; + } + + if (InstPatNode->getOperator()->getName() == "fpimm") { + Operands.push_back(OpKind::getFP()); + return true; + } + + const CodeGenRegisterClass *DstRC = 0; + + for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e; ++i) { + TreePatternNode *Op = InstPatNode->getChild(i); + + // Handle imm operands specially. + if (!Op->isLeaf() && Op->getOperator()->getName() == "imm") { + unsigned PredNo = 0; + if (!Op->getPredicateFns().empty()) { + TreePredicateFn PredFn = Op->getPredicateFns()[0]; + // If there is more than one predicate weighing in on this operand + // then we don't handle it. This doesn't typically happen for + // immediates anyway. + if (Op->getPredicateFns().size() > 1 || + !PredFn.isImmediatePattern()) + return false; + // Ignore any instruction with 'FastIselShouldIgnore', these are + // not needed and just bloat the fast instruction selector. For + // example, X86 doesn't need to generate code to match ADD16ri8 since + // ADD16ri will do just fine. + Record *Rec = PredFn.getOrigPatFragRecord()->getRecord(); + if (Rec->getValueAsBit("FastIselShouldIgnore")) + return false; + + PredNo = ImmediatePredicates.getIDFor(PredFn)+1; + } + + // Handle unmatched immediate sizes here. + //if (Op->getType(0) != VT) + // return false; + + Operands.push_back(OpKind::getImm(PredNo)); + continue; + } + + + // For now, filter out any operand with a predicate. + // For now, filter out any operand with multiple values. + if (!Op->getPredicateFns().empty() || Op->getNumTypes() != 1) + return false; + + if (!Op->isLeaf()) { + if (Op->getOperator()->getName() == "fpimm") { + Operands.push_back(OpKind::getFP()); + continue; + } + // For now, ignore other non-leaf nodes. + return false; + } + + assert(Op->hasTypeSet(0) && "Type infererence not done?"); + + // For now, all the operands must have the same type (if they aren't + // immediates). Note that this causes us to reject variable sized shifts + // on X86. + if (Op->getType(0) != VT) + return false; + + DefInit *OpDI = dynamic_cast<DefInit*>(Op->getLeafValue()); + if (!OpDI) + return false; + Record *OpLeafRec = OpDI->getDef(); + + // For now, the only other thing we accept is register operands. + const CodeGenRegisterClass *RC = 0; + if (OpLeafRec->isSubClassOf("RegisterOperand")) + OpLeafRec = OpLeafRec->getValueAsDef("RegClass"); + if (OpLeafRec->isSubClassOf("RegisterClass")) + RC = &Target.getRegisterClass(OpLeafRec); + else if (OpLeafRec->isSubClassOf("Register")) + RC = Target.getRegBank().getRegClassForRegister(OpLeafRec); + else + return false; + + // For now, this needs to be a register class of some sort. + if (!RC) + return false; + + // For now, all the operands must have the same register class or be + // a strict subclass of the destination. + if (DstRC) { + if (DstRC != RC && !DstRC->hasSubClass(RC)) + return false; + } else + DstRC = RC; + Operands.push_back(OpKind::getReg()); + } + return true; + } + + void PrintParameters(raw_ostream &OS) const { + for (unsigned i = 0, e = Operands.size(); i != e; ++i) { + if (Operands[i].isReg()) { + OS << "unsigned Op" << i << ", bool Op" << i << "IsKill"; + } else if (Operands[i].isImm()) { + OS << "uint64_t imm" << i; + } else if (Operands[i].isFP()) { + OS << "const ConstantFP *f" << i; + } else { + llvm_unreachable("Unknown operand kind!"); + } + if (i + 1 != e) + OS << ", "; + } + } + + void PrintArguments(raw_ostream &OS, + const std::vector<std::string> &PR) const { + assert(PR.size() == Operands.size()); + bool PrintedArg = false; + for (unsigned i = 0, e = Operands.size(); i != e; ++i) { + if (PR[i] != "") + // Implicit physical register operand. + continue; + + if (PrintedArg) + OS << ", "; + if (Operands[i].isReg()) { + OS << "Op" << i << ", Op" << i << "IsKill"; + PrintedArg = true; + } else if (Operands[i].isImm()) { + OS << "imm" << i; + PrintedArg = true; + } else if (Operands[i].isFP()) { + OS << "f" << i; + PrintedArg = true; + } else { + llvm_unreachable("Unknown operand kind!"); + } + } + } + + void PrintArguments(raw_ostream &OS) const { + for (unsigned i = 0, e = Operands.size(); i != e; ++i) { + if (Operands[i].isReg()) { + OS << "Op" << i << ", Op" << i << "IsKill"; + } else if (Operands[i].isImm()) { + OS << "imm" << i; + } else if (Operands[i].isFP()) { + OS << "f" << i; + } else { + llvm_unreachable("Unknown operand kind!"); + } + if (i + 1 != e) + OS << ", "; + } + } + + + void PrintManglingSuffix(raw_ostream &OS, const std::vector<std::string> &PR, + ImmPredicateSet &ImmPredicates, + bool StripImmCodes = false) const { + for (unsigned i = 0, e = Operands.size(); i != e; ++i) { + if (PR[i] != "") + // Implicit physical register operand. e.g. Instruction::Mul expect to + // select to a binary op. On x86, mul may take a single operand with + // the other operand being implicit. We must emit something that looks + // like a binary instruction except for the very inner FastEmitInst_* + // call. + continue; + Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes); + } + } + + void PrintManglingSuffix(raw_ostream &OS, ImmPredicateSet &ImmPredicates, + bool StripImmCodes = false) const { + for (unsigned i = 0, e = Operands.size(); i != e; ++i) + Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes); + } +}; + +class FastISelMap { + typedef std::map<std::string, InstructionMemo> PredMap; + typedef std::map<MVT::SimpleValueType, PredMap> RetPredMap; + typedef std::map<MVT::SimpleValueType, RetPredMap> TypeRetPredMap; + typedef std::map<std::string, TypeRetPredMap> OpcodeTypeRetPredMap; + typedef std::map<OperandsSignature, OpcodeTypeRetPredMap> + OperandsOpcodeTypeRetPredMap; + + OperandsOpcodeTypeRetPredMap SimplePatterns; + + std::map<OperandsSignature, std::vector<OperandsSignature> > + SignaturesWithConstantForms; + + std::string InstNS; + ImmPredicateSet ImmediatePredicates; +public: + explicit FastISelMap(std::string InstNS); + + void collectPatterns(CodeGenDAGPatterns &CGP); + void printImmediatePredicates(raw_ostream &OS); + void printFunctionDefinitions(raw_ostream &OS); +}; + +} + +static std::string getOpcodeName(Record *Op, CodeGenDAGPatterns &CGP) { + return CGP.getSDNodeInfo(Op).getEnumName(); +} + +static std::string getLegalCName(std::string OpName) { + std::string::size_type pos = OpName.find("::"); + if (pos != std::string::npos) + OpName.replace(pos, 2, "_"); + return OpName; +} + +FastISelMap::FastISelMap(std::string instns) + : InstNS(instns) { +} + +static std::string PhyRegForNode(TreePatternNode *Op, + const CodeGenTarget &Target) { + std::string PhysReg; + + if (!Op->isLeaf()) + return PhysReg; + + DefInit *OpDI = dynamic_cast<DefInit*>(Op->getLeafValue()); + Record *OpLeafRec = OpDI->getDef(); + if (!OpLeafRec->isSubClassOf("Register")) + return PhysReg; + + PhysReg += static_cast<StringInit*>(OpLeafRec->getValue( \ + "Namespace")->getValue())->getValue(); + PhysReg += "::"; + PhysReg += Target.getRegBank().getReg(OpLeafRec)->getName(); + return PhysReg; +} + +void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) { + const CodeGenTarget &Target = CGP.getTargetInfo(); + + // Determine the target's namespace name. + InstNS = Target.getInstNamespace() + "::"; + assert(InstNS.size() > 2 && "Can't determine target-specific namespace!"); + + // Scan through all the patterns and record the simple ones. + for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(), + E = CGP.ptm_end(); I != E; ++I) { + const PatternToMatch &Pattern = *I; + + // For now, just look at Instructions, so that we don't have to worry + // about emitting multiple instructions for a pattern. + TreePatternNode *Dst = Pattern.getDstPattern(); + if (Dst->isLeaf()) continue; + Record *Op = Dst->getOperator(); + if (!Op->isSubClassOf("Instruction")) + continue; + CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op); + if (II.Operands.empty()) + continue; + + // For now, ignore multi-instruction patterns. + bool MultiInsts = false; + for (unsigned i = 0, e = Dst->getNumChildren(); i != e; ++i) { + TreePatternNode *ChildOp = Dst->getChild(i); + if (ChildOp->isLeaf()) + continue; + if (ChildOp->getOperator()->isSubClassOf("Instruction")) { + MultiInsts = true; + break; + } + } + if (MultiInsts) + continue; + + // For now, ignore instructions where the first operand is not an + // output register. + const CodeGenRegisterClass *DstRC = 0; + std::string SubRegNo; + if (Op->getName() != "EXTRACT_SUBREG") { + Record *Op0Rec = II.Operands[0].Rec; + if (Op0Rec->isSubClassOf("RegisterOperand")) + Op0Rec = Op0Rec->getValueAsDef("RegClass"); + if (!Op0Rec->isSubClassOf("RegisterClass")) + continue; + DstRC = &Target.getRegisterClass(Op0Rec); + if (!DstRC) + continue; + } else { + // If this isn't a leaf, then continue since the register classes are + // a bit too complicated for now. + if (!Dst->getChild(1)->isLeaf()) continue; + + DefInit *SR = dynamic_cast<DefInit*>(Dst->getChild(1)->getLeafValue()); + if (SR) + SubRegNo = getQualifiedName(SR->getDef()); + else + SubRegNo = Dst->getChild(1)->getLeafValue()->getAsString(); + } + + // Inspect the pattern. + TreePatternNode *InstPatNode = Pattern.getSrcPattern(); + if (!InstPatNode) continue; + if (InstPatNode->isLeaf()) continue; + + // Ignore multiple result nodes for now. + if (InstPatNode->getNumTypes() > 1) continue; + + Record *InstPatOp = InstPatNode->getOperator(); + std::string OpcodeName = getOpcodeName(InstPatOp, CGP); + MVT::SimpleValueType RetVT = MVT::isVoid; + if (InstPatNode->getNumTypes()) RetVT = InstPatNode->getType(0); + MVT::SimpleValueType VT = RetVT; + if (InstPatNode->getNumChildren()) { + assert(InstPatNode->getChild(0)->getNumTypes() == 1); + VT = InstPatNode->getChild(0)->getType(0); + } + + // For now, filter out any instructions with predicates. + if (!InstPatNode->getPredicateFns().empty()) + continue; + + // Check all the operands. + OperandsSignature Operands; + if (!Operands.initialize(InstPatNode, Target, VT, ImmediatePredicates)) + continue; + + std::vector<std::string>* PhysRegInputs = new std::vector<std::string>(); + if (InstPatNode->getOperator()->getName() == "imm" || + InstPatNode->getOperator()->getName() == "fpimm") + PhysRegInputs->push_back(""); + else { + // Compute the PhysRegs used by the given pattern, and check that + // the mapping from the src to dst patterns is simple. + bool FoundNonSimplePattern = false; + unsigned DstIndex = 0; + for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e; ++i) { + std::string PhysReg = PhyRegForNode(InstPatNode->getChild(i), Target); + if (PhysReg.empty()) { + if (DstIndex >= Dst->getNumChildren() || + Dst->getChild(DstIndex)->getName() != + InstPatNode->getChild(i)->getName()) { + FoundNonSimplePattern = true; + break; + } + ++DstIndex; + } + + PhysRegInputs->push_back(PhysReg); + } + + if (Op->getName() != "EXTRACT_SUBREG" && DstIndex < Dst->getNumChildren()) + FoundNonSimplePattern = true; + + if (FoundNonSimplePattern) + continue; + } + + // Get the predicate that guards this pattern. + std::string PredicateCheck = Pattern.getPredicateCheck(); + + // Ok, we found a pattern that we can handle. Remember it. + InstructionMemo Memo = { + Pattern.getDstPattern()->getOperator()->getName(), + DstRC, + SubRegNo, + PhysRegInputs + }; + + if (SimplePatterns[Operands][OpcodeName][VT][RetVT].count(PredicateCheck)) + throw TGError(Pattern.getSrcRecord()->getLoc(), + "Duplicate record in FastISel table!"); + + SimplePatterns[Operands][OpcodeName][VT][RetVT][PredicateCheck] = Memo; + + // If any of the operands were immediates with predicates on them, strip + // them down to a signature that doesn't have predicates so that we can + // associate them with the stripped predicate version. + if (Operands.hasAnyImmediateCodes()) { + SignaturesWithConstantForms[Operands.getWithoutImmCodes()] + .push_back(Operands); + } + } +} + +void FastISelMap::printImmediatePredicates(raw_ostream &OS) { + if (ImmediatePredicates.begin() == ImmediatePredicates.end()) + return; + + OS << "\n// FastEmit Immediate Predicate functions.\n"; + for (ImmPredicateSet::iterator I = ImmediatePredicates.begin(), + E = ImmediatePredicates.end(); I != E; ++I) { + OS << "static bool " << I->getFnName() << "(int64_t Imm) {\n"; + OS << I->getImmediatePredicateCode() << "\n}\n"; + } + + OS << "\n\n"; +} + + +void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { + // Now emit code for all the patterns that we collected. + for (OperandsOpcodeTypeRetPredMap::const_iterator OI = SimplePatterns.begin(), + OE = SimplePatterns.end(); OI != OE; ++OI) { + const OperandsSignature &Operands = OI->first; + const OpcodeTypeRetPredMap &OTM = OI->second; + + for (OpcodeTypeRetPredMap::const_iterator I = OTM.begin(), E = OTM.end(); + I != E; ++I) { + const std::string &Opcode = I->first; + const TypeRetPredMap &TM = I->second; + + OS << "// FastEmit functions for " << Opcode << ".\n"; + OS << "\n"; + + // Emit one function for each opcode,type pair. + for (TypeRetPredMap::const_iterator TI = TM.begin(), TE = TM.end(); + TI != TE; ++TI) { + MVT::SimpleValueType VT = TI->first; + const RetPredMap &RM = TI->second; + if (RM.size() != 1) { + for (RetPredMap::const_iterator RI = RM.begin(), RE = RM.end(); + RI != RE; ++RI) { + MVT::SimpleValueType RetVT = RI->first; + const PredMap &PM = RI->second; + bool HasPred = false; + + OS << "unsigned FastEmit_" + << getLegalCName(Opcode) + << "_" << getLegalCName(getName(VT)) + << "_" << getLegalCName(getName(RetVT)) << "_"; + Operands.PrintManglingSuffix(OS, ImmediatePredicates); + OS << "("; + Operands.PrintParameters(OS); + OS << ") {\n"; + + // Emit code for each possible instruction. There may be + // multiple if there are subtarget concerns. + for (PredMap::const_iterator PI = PM.begin(), PE = PM.end(); + PI != PE; ++PI) { + std::string PredicateCheck = PI->first; + const InstructionMemo &Memo = PI->second; + + if (PredicateCheck.empty()) { + assert(!HasPred && + "Multiple instructions match, at least one has " + "a predicate and at least one doesn't!"); + } else { + OS << " if (" + PredicateCheck + ") {\n"; + OS << " "; + HasPred = true; + } + + for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) { + if ((*Memo.PhysRegs)[i] != "") + OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, " + << "TII.get(TargetOpcode::COPY), " + << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n"; + } + + OS << " return FastEmitInst_"; + if (Memo.SubRegNo.empty()) { + Operands.PrintManglingSuffix(OS, *Memo.PhysRegs, + ImmediatePredicates, true); + OS << "(" << InstNS << Memo.Name << ", "; + OS << InstNS << Memo.RC->getName() << "RegisterClass"; + if (!Operands.empty()) + OS << ", "; + Operands.PrintArguments(OS, *Memo.PhysRegs); + OS << ");\n"; + } else { + OS << "extractsubreg(" << getName(RetVT); + OS << ", Op0, Op0IsKill, " << Memo.SubRegNo << ");\n"; + } + + if (HasPred) + OS << " }\n"; + + } + // Return 0 if none of the predicates were satisfied. + if (HasPred) + OS << " return 0;\n"; + OS << "}\n"; + OS << "\n"; + } + + // Emit one function for the type that demultiplexes on return type. + OS << "unsigned FastEmit_" + << getLegalCName(Opcode) << "_" + << getLegalCName(getName(VT)) << "_"; + Operands.PrintManglingSuffix(OS, ImmediatePredicates); + OS << "(MVT RetVT"; + if (!Operands.empty()) + OS << ", "; + Operands.PrintParameters(OS); + OS << ") {\nswitch (RetVT.SimpleTy) {\n"; + for (RetPredMap::const_iterator RI = RM.begin(), RE = RM.end(); + RI != RE; ++RI) { + MVT::SimpleValueType RetVT = RI->first; + OS << " case " << getName(RetVT) << ": return FastEmit_" + << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) + << "_" << getLegalCName(getName(RetVT)) << "_"; + Operands.PrintManglingSuffix(OS, ImmediatePredicates); + OS << "("; + Operands.PrintArguments(OS); + OS << ");\n"; + } + OS << " default: return 0;\n}\n}\n\n"; + + } else { + // Non-variadic return type. + OS << "unsigned FastEmit_" + << getLegalCName(Opcode) << "_" + << getLegalCName(getName(VT)) << "_"; + Operands.PrintManglingSuffix(OS, ImmediatePredicates); + OS << "(MVT RetVT"; + if (!Operands.empty()) + OS << ", "; + Operands.PrintParameters(OS); + OS << ") {\n"; + + OS << " if (RetVT.SimpleTy != " << getName(RM.begin()->first) + << ")\n return 0;\n"; + + const PredMap &PM = RM.begin()->second; + bool HasPred = false; + + // Emit code for each possible instruction. There may be + // multiple if there are subtarget concerns. + for (PredMap::const_iterator PI = PM.begin(), PE = PM.end(); PI != PE; + ++PI) { + std::string PredicateCheck = PI->first; + const InstructionMemo &Memo = PI->second; + + if (PredicateCheck.empty()) { + assert(!HasPred && + "Multiple instructions match, at least one has " + "a predicate and at least one doesn't!"); + } else { + OS << " if (" + PredicateCheck + ") {\n"; + OS << " "; + HasPred = true; + } + + for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) { + if ((*Memo.PhysRegs)[i] != "") + OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, " + << "TII.get(TargetOpcode::COPY), " + << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n"; + } + + OS << " return FastEmitInst_"; + + if (Memo.SubRegNo.empty()) { + Operands.PrintManglingSuffix(OS, *Memo.PhysRegs, + ImmediatePredicates, true); + OS << "(" << InstNS << Memo.Name << ", "; + OS << InstNS << Memo.RC->getName() << "RegisterClass"; + if (!Operands.empty()) + OS << ", "; + Operands.PrintArguments(OS, *Memo.PhysRegs); + OS << ");\n"; + } else { + OS << "extractsubreg(RetVT, Op0, Op0IsKill, "; + OS << Memo.SubRegNo; + OS << ");\n"; + } + + if (HasPred) + OS << " }\n"; + } + + // Return 0 if none of the predicates were satisfied. + if (HasPred) + OS << " return 0;\n"; + OS << "}\n"; + OS << "\n"; + } + } + + // Emit one function for the opcode that demultiplexes based on the type. + OS << "unsigned FastEmit_" + << getLegalCName(Opcode) << "_"; + Operands.PrintManglingSuffix(OS, ImmediatePredicates); + OS << "(MVT VT, MVT RetVT"; + if (!Operands.empty()) + OS << ", "; + Operands.PrintParameters(OS); + OS << ") {\n"; + OS << " switch (VT.SimpleTy) {\n"; + for (TypeRetPredMap::const_iterator TI = TM.begin(), TE = TM.end(); + TI != TE; ++TI) { + MVT::SimpleValueType VT = TI->first; + std::string TypeName = getName(VT); + OS << " case " << TypeName << ": return FastEmit_" + << getLegalCName(Opcode) << "_" << getLegalCName(TypeName) << "_"; + Operands.PrintManglingSuffix(OS, ImmediatePredicates); + OS << "(RetVT"; + if (!Operands.empty()) + OS << ", "; + Operands.PrintArguments(OS); + OS << ");\n"; + } + OS << " default: return 0;\n"; + OS << " }\n"; + OS << "}\n"; + OS << "\n"; + } + + OS << "// Top-level FastEmit function.\n"; + OS << "\n"; + + // Emit one function for the operand signature that demultiplexes based + // on opcode and type. + OS << "unsigned FastEmit_"; + Operands.PrintManglingSuffix(OS, ImmediatePredicates); + OS << "(MVT VT, MVT RetVT, unsigned Opcode"; + if (!Operands.empty()) + OS << ", "; + Operands.PrintParameters(OS); + OS << ") {\n"; + + // If there are any forms of this signature available that operand on + // constrained forms of the immediate (e.g. 32-bit sext immediate in a + // 64-bit operand), check them first. + + std::map<OperandsSignature, std::vector<OperandsSignature> >::iterator MI + = SignaturesWithConstantForms.find(Operands); + if (MI != SignaturesWithConstantForms.end()) { + // Unique any duplicates out of the list. + std::sort(MI->second.begin(), MI->second.end()); + MI->second.erase(std::unique(MI->second.begin(), MI->second.end()), + MI->second.end()); + + // Check each in order it was seen. It would be nice to have a good + // relative ordering between them, but we're not going for optimality + // here. + for (unsigned i = 0, e = MI->second.size(); i != e; ++i) { + OS << " if ("; + MI->second[i].emitImmediatePredicate(OS, ImmediatePredicates); + OS << ")\n if (unsigned Reg = FastEmit_"; + MI->second[i].PrintManglingSuffix(OS, ImmediatePredicates); + OS << "(VT, RetVT, Opcode"; + if (!MI->second[i].empty()) + OS << ", "; + MI->second[i].PrintArguments(OS); + OS << "))\n return Reg;\n\n"; + } + + // Done with this, remove it. + SignaturesWithConstantForms.erase(MI); + } + + OS << " switch (Opcode) {\n"; + for (OpcodeTypeRetPredMap::const_iterator I = OTM.begin(), E = OTM.end(); + I != E; ++I) { + const std::string &Opcode = I->first; + + OS << " case " << Opcode << ": return FastEmit_" + << getLegalCName(Opcode) << "_"; + Operands.PrintManglingSuffix(OS, ImmediatePredicates); + OS << "(VT, RetVT"; + if (!Operands.empty()) + OS << ", "; + Operands.PrintArguments(OS); + OS << ");\n"; + } + OS << " default: return 0;\n"; + OS << " }\n"; + OS << "}\n"; + OS << "\n"; + } + + // TODO: SignaturesWithConstantForms should be empty here. +} + +void FastISelEmitter::run(raw_ostream &OS) { + const CodeGenTarget &Target = CGP.getTargetInfo(); + + // Determine the target's namespace name. + std::string InstNS = Target.getInstNamespace() + "::"; + assert(InstNS.size() > 2 && "Can't determine target-specific namespace!"); + + EmitSourceFileHeader("\"Fast\" Instruction Selector for the " + + Target.getName() + " target", OS); + + FastISelMap F(InstNS); + F.collectPatterns(CGP); + F.printImmediatePredicates(OS); + F.printFunctionDefinitions(OS); +} + +FastISelEmitter::FastISelEmitter(RecordKeeper &R) + : Records(R), CGP(R) { +} + diff --git a/contrib/llvm/utils/TableGen/FastISelEmitter.h b/contrib/llvm/utils/TableGen/FastISelEmitter.h new file mode 100644 index 0000000..4f75ac1 --- /dev/null +++ b/contrib/llvm/utils/TableGen/FastISelEmitter.h @@ -0,0 +1,39 @@ +//===- FastISelEmitter.h - Generate an instruction selector -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend emits a "fast" instruction selector. +// +//===----------------------------------------------------------------------===// + +#ifndef FASTISEL_EMITTER_H +#define FASTISEL_EMITTER_H + +#include "CodeGenDAGPatterns.h" +#include "llvm/TableGen/TableGenBackend.h" + +namespace llvm { + +class CodeGenTarget; + +/// FastISelEmitter - The top-level class which coordinates construction +/// and emission of the instruction selector. +/// +class FastISelEmitter : public TableGenBackend { + RecordKeeper &Records; + CodeGenDAGPatterns CGP; +public: + explicit FastISelEmitter(RecordKeeper &R); + + // run - Output the isel, returning true on failure. + void run(raw_ostream &OS); +}; + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp new file mode 100644 index 0000000..9b676f2 --- /dev/null +++ b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -0,0 +1,1575 @@ +//===------------ FixedLenDecoderEmitter.cpp - Decoder Generator ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// It contains the tablegen backend that emits the decoder functions for +// targets with fixed length instruction set. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "decoder-emitter" + +#include "FixedLenDecoderEmitter.h" +#include "CodeGenTarget.h" +#include "llvm/TableGen/Record.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +#include <vector> +#include <map> +#include <string> + +using namespace llvm; + +// The set (BIT_TRUE, BIT_FALSE, BIT_UNSET) represents a ternary logic system +// for a bit value. +// +// BIT_UNFILTERED is used as the init value for a filter position. It is used +// only for filter processings. +typedef enum { + BIT_TRUE, // '1' + BIT_FALSE, // '0' + BIT_UNSET, // '?' + BIT_UNFILTERED // unfiltered +} bit_value_t; + +static bool ValueSet(bit_value_t V) { + return (V == BIT_TRUE || V == BIT_FALSE); +} +static bool ValueNotSet(bit_value_t V) { + return (V == BIT_UNSET); +} +static int Value(bit_value_t V) { + return ValueNotSet(V) ? -1 : (V == BIT_FALSE ? 0 : 1); +} +static bit_value_t bitFromBits(const BitsInit &bits, unsigned index) { + if (BitInit *bit = dynamic_cast<BitInit*>(bits.getBit(index))) + return bit->getValue() ? BIT_TRUE : BIT_FALSE; + + // The bit is uninitialized. + return BIT_UNSET; +} +// Prints the bit value for each position. +static void dumpBits(raw_ostream &o, const BitsInit &bits) { + unsigned index; + + for (index = bits.getNumBits(); index > 0; index--) { + switch (bitFromBits(bits, index - 1)) { + case BIT_TRUE: + o << "1"; + break; + case BIT_FALSE: + o << "0"; + break; + case BIT_UNSET: + o << "_"; + break; + default: + llvm_unreachable("unexpected return value from bitFromBits"); + } + } +} + +static BitsInit &getBitsField(const Record &def, const char *str) { + BitsInit *bits = def.getValueAsBitsInit(str); + return *bits; +} + +// Forward declaration. +class FilterChooser; + +// Representation of the instruction to work on. +typedef std::vector<bit_value_t> insn_t; + +/// Filter - Filter works with FilterChooser to produce the decoding tree for +/// the ISA. +/// +/// It is useful to think of a Filter as governing the switch stmts of the +/// decoding tree in a certain level. Each case stmt delegates to an inferior +/// FilterChooser to decide what further decoding logic to employ, or in another +/// words, what other remaining bits to look at. The FilterChooser eventually +/// chooses a best Filter to do its job. +/// +/// This recursive scheme ends when the number of Opcodes assigned to the +/// FilterChooser becomes 1 or if there is a conflict. A conflict happens when +/// the Filter/FilterChooser combo does not know how to distinguish among the +/// Opcodes assigned. +/// +/// An example of a conflict is +/// +/// Conflict: +/// 111101000.00........00010000.... +/// 111101000.00........0001........ +/// 1111010...00........0001........ +/// 1111010...00.................... +/// 1111010......................... +/// 1111............................ +/// ................................ +/// VST4q8a 111101000_00________00010000____ +/// VST4q8b 111101000_00________00010000____ +/// +/// The Debug output shows the path that the decoding tree follows to reach the +/// the conclusion that there is a conflict. VST4q8a is a vst4 to double-spaced +/// even registers, while VST4q8b is a vst4 to double-spaced odd regsisters. +/// +/// The encoding info in the .td files does not specify this meta information, +/// which could have been used by the decoder to resolve the conflict. The +/// decoder could try to decode the even/odd register numbering and assign to +/// VST4q8a or VST4q8b, but for the time being, the decoder chooses the "a" +/// version and return the Opcode since the two have the same Asm format string. +class Filter { +protected: + const FilterChooser *Owner;// points to the FilterChooser who owns this filter + unsigned StartBit; // the starting bit position + unsigned NumBits; // number of bits to filter + bool Mixed; // a mixed region contains both set and unset bits + + // Map of well-known segment value to the set of uid's with that value. + std::map<uint64_t, std::vector<unsigned> > FilteredInstructions; + + // Set of uid's with non-constant segment values. + std::vector<unsigned> VariableInstructions; + + // Map of well-known segment value to its delegate. + std::map<unsigned, const FilterChooser*> FilterChooserMap; + + // Number of instructions which fall under FilteredInstructions category. + unsigned NumFiltered; + + // Keeps track of the last opcode in the filtered bucket. + unsigned LastOpcFiltered; + +public: + unsigned getNumFiltered() const { return NumFiltered; } + unsigned getSingletonOpc() const { + assert(NumFiltered == 1); + return LastOpcFiltered; + } + // Return the filter chooser for the group of instructions without constant + // segment values. + const FilterChooser &getVariableFC() const { + assert(NumFiltered == 1); + assert(FilterChooserMap.size() == 1); + return *(FilterChooserMap.find((unsigned)-1)->second); + } + + Filter(const Filter &f); + Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, bool mixed); + + ~Filter(); + + // Divides the decoding task into sub tasks and delegates them to the + // inferior FilterChooser's. + // + // A special case arises when there's only one entry in the filtered + // instructions. In order to unambiguously decode the singleton, we need to + // match the remaining undecoded encoding bits against the singleton. + void recurse(); + + // Emit code to decode instructions given a segment or segments of bits. + void emit(raw_ostream &o, unsigned &Indentation) const; + + // Returns the number of fanout produced by the filter. More fanout implies + // the filter distinguishes more categories of instructions. + unsigned usefulness() const; +}; // End of class Filter + +// These are states of our finite state machines used in FilterChooser's +// filterProcessor() which produces the filter candidates to use. +typedef enum { + ATTR_NONE, + ATTR_FILTERED, + ATTR_ALL_SET, + ATTR_ALL_UNSET, + ATTR_MIXED +} bitAttr_t; + +/// FilterChooser - FilterChooser chooses the best filter among a set of Filters +/// in order to perform the decoding of instructions at the current level. +/// +/// Decoding proceeds from the top down. Based on the well-known encoding bits +/// of instructions available, FilterChooser builds up the possible Filters that +/// can further the task of decoding by distinguishing among the remaining +/// candidate instructions. +/// +/// Once a filter has been chosen, it is called upon to divide the decoding task +/// into sub-tasks and delegates them to its inferior FilterChoosers for further +/// processings. +/// +/// It is useful to think of a Filter as governing the switch stmts of the +/// decoding tree. And each case is delegated to an inferior FilterChooser to +/// decide what further remaining bits to look at. +class FilterChooser { +protected: + friend class Filter; + + // Vector of codegen instructions to choose our filter. + const std::vector<const CodeGenInstruction*> &AllInstructions; + + // Vector of uid's for this filter chooser to work on. + const std::vector<unsigned> &Opcodes; + + // Lookup table for the operand decoding of instructions. + const std::map<unsigned, std::vector<OperandInfo> > &Operands; + + // Vector of candidate filters. + std::vector<Filter> Filters; + + // Array of bit values passed down from our parent. + // Set to all BIT_UNFILTERED's for Parent == NULL. + std::vector<bit_value_t> FilterBitValues; + + // Links to the FilterChooser above us in the decoding tree. + const FilterChooser *Parent; + + // Index of the best filter from Filters. + int BestIndex; + + // Width of instructions + unsigned BitWidth; + + // Parent emitter + const FixedLenDecoderEmitter *Emitter; + +public: + FilterChooser(const FilterChooser &FC) + : AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes), + Operands(FC.Operands), Filters(FC.Filters), + FilterBitValues(FC.FilterBitValues), Parent(FC.Parent), + BestIndex(FC.BestIndex), BitWidth(FC.BitWidth), + Emitter(FC.Emitter) { } + + FilterChooser(const std::vector<const CodeGenInstruction*> &Insts, + const std::vector<unsigned> &IDs, + const std::map<unsigned, std::vector<OperandInfo> > &Ops, + unsigned BW, + const FixedLenDecoderEmitter *E) + : AllInstructions(Insts), Opcodes(IDs), Operands(Ops), Filters(), + Parent(NULL), BestIndex(-1), BitWidth(BW), Emitter(E) { + for (unsigned i = 0; i < BitWidth; ++i) + FilterBitValues.push_back(BIT_UNFILTERED); + + doFilter(); + } + + FilterChooser(const std::vector<const CodeGenInstruction*> &Insts, + const std::vector<unsigned> &IDs, + const std::map<unsigned, std::vector<OperandInfo> > &Ops, + const std::vector<bit_value_t> &ParentFilterBitValues, + const FilterChooser &parent) + : AllInstructions(Insts), Opcodes(IDs), Operands(Ops), + Filters(), FilterBitValues(ParentFilterBitValues), + Parent(&parent), BestIndex(-1), BitWidth(parent.BitWidth), + Emitter(parent.Emitter) { + doFilter(); + } + + // The top level filter chooser has NULL as its parent. + bool isTopLevel() const { return Parent == NULL; } + + // Emit the top level typedef and decodeInstruction() function. + void emitTop(raw_ostream &o, unsigned Indentation, + const std::string &Namespace) const; + +protected: + // Populates the insn given the uid. + void insnWithID(insn_t &Insn, unsigned Opcode) const { + BitsInit &Bits = getBitsField(*AllInstructions[Opcode]->TheDef, "Inst"); + + // We may have a SoftFail bitmask, which specifies a mask where an encoding + // may differ from the value in "Inst" and yet still be valid, but the + // disassembler should return SoftFail instead of Success. + // + // This is used for marking UNPREDICTABLE instructions in the ARM world. + BitsInit *SFBits = + AllInstructions[Opcode]->TheDef->getValueAsBitsInit("SoftFail"); + + for (unsigned i = 0; i < BitWidth; ++i) { + if (SFBits && bitFromBits(*SFBits, i) == BIT_TRUE) + Insn.push_back(BIT_UNSET); + else + Insn.push_back(bitFromBits(Bits, i)); + } + } + + // Returns the record name. + const std::string &nameWithID(unsigned Opcode) const { + return AllInstructions[Opcode]->TheDef->getName(); + } + + // Populates the field of the insn given the start position and the number of + // consecutive bits to scan for. + // + // Returns false if there exists any uninitialized bit value in the range. + // Returns true, otherwise. + bool fieldFromInsn(uint64_t &Field, insn_t &Insn, unsigned StartBit, + unsigned NumBits) const; + + /// dumpFilterArray - dumpFilterArray prints out debugging info for the given + /// filter array as a series of chars. + void dumpFilterArray(raw_ostream &o, + const std::vector<bit_value_t> & filter) const; + + /// dumpStack - dumpStack traverses the filter chooser chain and calls + /// dumpFilterArray on each filter chooser up to the top level one. + void dumpStack(raw_ostream &o, const char *prefix) const; + + Filter &bestFilter() { + assert(BestIndex != -1 && "BestIndex not set"); + return Filters[BestIndex]; + } + + // Called from Filter::recurse() when singleton exists. For debug purpose. + void SingletonExists(unsigned Opc) const; + + bool PositionFiltered(unsigned i) const { + return ValueSet(FilterBitValues[i]); + } + + // Calculates the island(s) needed to decode the instruction. + // This returns a lit of undecoded bits of an instructions, for example, + // Inst{20} = 1 && Inst{3-0} == 0b1111 represents two islands of yet-to-be + // decoded bits in order to verify that the instruction matches the Opcode. + unsigned getIslands(std::vector<unsigned> &StartBits, + std::vector<unsigned> &EndBits, + std::vector<uint64_t> &FieldVals, + const insn_t &Insn) const; + + // Emits code to check the Predicates member of an instruction are true. + // Returns true if predicate matches were emitted, false otherwise. + bool emitPredicateMatch(raw_ostream &o, unsigned &Indentation, + unsigned Opc) const; + + void emitSoftFailCheck(raw_ostream &o, unsigned Indentation, + unsigned Opc) const; + + // Emits code to decode the singleton. Return true if we have matched all the + // well-known bits. + bool emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, + unsigned Opc) const; + + // Emits code to decode the singleton, and then to decode the rest. + void emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, + const Filter &Best) const; + + void emitBinaryParser(raw_ostream &o , unsigned &Indentation, + const OperandInfo &OpInfo) const; + + // Assign a single filter and run with it. + void runSingleFilter(unsigned startBit, unsigned numBit, bool mixed); + + // reportRegion is a helper function for filterProcessor to mark a region as + // eligible for use as a filter region. + void reportRegion(bitAttr_t RA, unsigned StartBit, unsigned BitIndex, + bool AllowMixed); + + // FilterProcessor scans the well-known encoding bits of the instructions and + // builds up a list of candidate filters. It chooses the best filter and + // recursively descends down the decoding tree. + bool filterProcessor(bool AllowMixed, bool Greedy = true); + + // Decides on the best configuration of filter(s) to use in order to decode + // the instructions. A conflict of instructions may occur, in which case we + // dump the conflict set to the standard error. + void doFilter(); + + // Emits code to decode our share of instructions. Returns true if the + // emitted code causes a return, which occurs if we know how to decode + // the instruction at this level or the instruction is not decodeable. + bool emit(raw_ostream &o, unsigned &Indentation) const; +}; + +/////////////////////////// +// // +// Filter Implementation // +// // +/////////////////////////// + +Filter::Filter(const Filter &f) + : Owner(f.Owner), StartBit(f.StartBit), NumBits(f.NumBits), Mixed(f.Mixed), + FilteredInstructions(f.FilteredInstructions), + VariableInstructions(f.VariableInstructions), + FilterChooserMap(f.FilterChooserMap), NumFiltered(f.NumFiltered), + LastOpcFiltered(f.LastOpcFiltered) { +} + +Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, + bool mixed) + : Owner(&owner), StartBit(startBit), NumBits(numBits), Mixed(mixed) { + assert(StartBit + NumBits - 1 < Owner->BitWidth); + + NumFiltered = 0; + LastOpcFiltered = 0; + + for (unsigned i = 0, e = Owner->Opcodes.size(); i != e; ++i) { + insn_t Insn; + + // Populates the insn given the uid. + Owner->insnWithID(Insn, Owner->Opcodes[i]); + + uint64_t Field; + // Scans the segment for possibly well-specified encoding bits. + bool ok = Owner->fieldFromInsn(Field, Insn, StartBit, NumBits); + + if (ok) { + // The encoding bits are well-known. Lets add the uid of the + // instruction into the bucket keyed off the constant field value. + LastOpcFiltered = Owner->Opcodes[i]; + FilteredInstructions[Field].push_back(LastOpcFiltered); + ++NumFiltered; + } else { + // Some of the encoding bit(s) are unspecified. This contributes to + // one additional member of "Variable" instructions. + VariableInstructions.push_back(Owner->Opcodes[i]); + } + } + + assert((FilteredInstructions.size() + VariableInstructions.size() > 0) + && "Filter returns no instruction categories"); +} + +Filter::~Filter() { + std::map<unsigned, const FilterChooser*>::iterator filterIterator; + for (filterIterator = FilterChooserMap.begin(); + filterIterator != FilterChooserMap.end(); + filterIterator++) { + delete filterIterator->second; + } +} + +// Divides the decoding task into sub tasks and delegates them to the +// inferior FilterChooser's. +// +// A special case arises when there's only one entry in the filtered +// instructions. In order to unambiguously decode the singleton, we need to +// match the remaining undecoded encoding bits against the singleton. +void Filter::recurse() { + std::map<uint64_t, std::vector<unsigned> >::const_iterator mapIterator; + + // Starts by inheriting our parent filter chooser's filter bit values. + std::vector<bit_value_t> BitValueArray(Owner->FilterBitValues); + + unsigned bitIndex; + + if (VariableInstructions.size()) { + // Conservatively marks each segment position as BIT_UNSET. + for (bitIndex = 0; bitIndex < NumBits; bitIndex++) + BitValueArray[StartBit + bitIndex] = BIT_UNSET; + + // Delegates to an inferior filter chooser for further processing on this + // group of instructions whose segment values are variable. + FilterChooserMap.insert(std::pair<unsigned, const FilterChooser*>( + (unsigned)-1, + new FilterChooser(Owner->AllInstructions, + VariableInstructions, + Owner->Operands, + BitValueArray, + *Owner) + )); + } + + // No need to recurse for a singleton filtered instruction. + // See also Filter::emit(). + if (getNumFiltered() == 1) { + //Owner->SingletonExists(LastOpcFiltered); + assert(FilterChooserMap.size() == 1); + return; + } + + // Otherwise, create sub choosers. + for (mapIterator = FilteredInstructions.begin(); + mapIterator != FilteredInstructions.end(); + mapIterator++) { + + // Marks all the segment positions with either BIT_TRUE or BIT_FALSE. + for (bitIndex = 0; bitIndex < NumBits; bitIndex++) { + if (mapIterator->first & (1ULL << bitIndex)) + BitValueArray[StartBit + bitIndex] = BIT_TRUE; + else + BitValueArray[StartBit + bitIndex] = BIT_FALSE; + } + + // Delegates to an inferior filter chooser for further processing on this + // category of instructions. + FilterChooserMap.insert(std::pair<unsigned, const FilterChooser*>( + mapIterator->first, + new FilterChooser(Owner->AllInstructions, + mapIterator->second, + Owner->Operands, + BitValueArray, + *Owner) + )); + } +} + +// Emit code to decode instructions given a segment or segments of bits. +void Filter::emit(raw_ostream &o, unsigned &Indentation) const { + o.indent(Indentation) << "// Check Inst{"; + + if (NumBits > 1) + o << (StartBit + NumBits - 1) << '-'; + + o << StartBit << "} ...\n"; + + o.indent(Indentation) << "switch (fieldFromInstruction" << Owner->BitWidth + << "(insn, " << StartBit << ", " + << NumBits << ")) {\n"; + + std::map<unsigned, const FilterChooser*>::const_iterator filterIterator; + + bool DefaultCase = false; + for (filterIterator = FilterChooserMap.begin(); + filterIterator != FilterChooserMap.end(); + filterIterator++) { + + // Field value -1 implies a non-empty set of variable instructions. + // See also recurse(). + if (filterIterator->first == (unsigned)-1) { + DefaultCase = true; + + o.indent(Indentation) << "default:\n"; + o.indent(Indentation) << " break; // fallthrough\n"; + + // Closing curly brace for the switch statement. + // This is unconventional because we want the default processing to be + // performed for the fallthrough cases as well, i.e., when the "cases" + // did not prove a decoded instruction. + o.indent(Indentation) << "}\n"; + + } else + o.indent(Indentation) << "case " << filterIterator->first << ":\n"; + + // We arrive at a category of instructions with the same segment value. + // Now delegate to the sub filter chooser for further decodings. + // The case may fallthrough, which happens if the remaining well-known + // encoding bits do not match exactly. + if (!DefaultCase) { ++Indentation; ++Indentation; } + + filterIterator->second->emit(o, Indentation); + // For top level default case, there's no need for a break statement. + if (Owner->isTopLevel() && DefaultCase) + break; + + o.indent(Indentation) << "break;\n"; + + if (!DefaultCase) { --Indentation; --Indentation; } + } + + // If there is no default case, we still need to supply a closing brace. + if (!DefaultCase) { + // Closing curly brace for the switch statement. + o.indent(Indentation) << "}\n"; + } +} + +// Returns the number of fanout produced by the filter. More fanout implies +// the filter distinguishes more categories of instructions. +unsigned Filter::usefulness() const { + if (VariableInstructions.size()) + return FilteredInstructions.size(); + else + return FilteredInstructions.size() + 1; +} + +////////////////////////////////// +// // +// Filterchooser Implementation // +// // +////////////////////////////////// + +// Emit the top level typedef and decodeInstruction() function. +void FilterChooser::emitTop(raw_ostream &o, unsigned Indentation, + const std::string &Namespace) const { + o.indent(Indentation) << + "static MCDisassembler::DecodeStatus decode" << Namespace << "Instruction" + << BitWidth << "(MCInst &MI, uint" << BitWidth + << "_t insn, uint64_t Address, " + << "const void *Decoder, const MCSubtargetInfo &STI) {\n"; + o.indent(Indentation) << " unsigned tmp = 0;\n"; + o.indent(Indentation) << " (void)tmp;\n"; + o.indent(Indentation) << Emitter->Locals << "\n"; + o.indent(Indentation) << " uint64_t Bits = STI.getFeatureBits();\n"; + o.indent(Indentation) << " (void)Bits;\n"; + + ++Indentation; ++Indentation; + // Emits code to decode the instructions. + emit(o, Indentation); + + o << '\n'; + o.indent(Indentation) << "return " << Emitter->ReturnFail << ";\n"; + --Indentation; --Indentation; + + o.indent(Indentation) << "}\n"; + + o << '\n'; +} + +// Populates the field of the insn given the start position and the number of +// consecutive bits to scan for. +// +// Returns false if and on the first uninitialized bit value encountered. +// Returns true, otherwise. +bool FilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn, + unsigned StartBit, unsigned NumBits) const { + Field = 0; + + for (unsigned i = 0; i < NumBits; ++i) { + if (Insn[StartBit + i] == BIT_UNSET) + return false; + + if (Insn[StartBit + i] == BIT_TRUE) + Field = Field | (1ULL << i); + } + + return true; +} + +/// dumpFilterArray - dumpFilterArray prints out debugging info for the given +/// filter array as a series of chars. +void FilterChooser::dumpFilterArray(raw_ostream &o, + const std::vector<bit_value_t> &filter) const { + unsigned bitIndex; + + for (bitIndex = BitWidth; bitIndex > 0; bitIndex--) { + switch (filter[bitIndex - 1]) { + case BIT_UNFILTERED: + o << "."; + break; + case BIT_UNSET: + o << "_"; + break; + case BIT_TRUE: + o << "1"; + break; + case BIT_FALSE: + o << "0"; + break; + } + } +} + +/// dumpStack - dumpStack traverses the filter chooser chain and calls +/// dumpFilterArray on each filter chooser up to the top level one. +void FilterChooser::dumpStack(raw_ostream &o, const char *prefix) const { + const FilterChooser *current = this; + + while (current) { + o << prefix; + dumpFilterArray(o, current->FilterBitValues); + o << '\n'; + current = current->Parent; + } +} + +// Called from Filter::recurse() when singleton exists. For debug purpose. +void FilterChooser::SingletonExists(unsigned Opc) const { + insn_t Insn0; + insnWithID(Insn0, Opc); + + errs() << "Singleton exists: " << nameWithID(Opc) + << " with its decoding dominating "; + for (unsigned i = 0; i < Opcodes.size(); ++i) { + if (Opcodes[i] == Opc) continue; + errs() << nameWithID(Opcodes[i]) << ' '; + } + errs() << '\n'; + + dumpStack(errs(), "\t\t"); + for (unsigned i = 0; i < Opcodes.size(); ++i) { + const std::string &Name = nameWithID(Opcodes[i]); + + errs() << '\t' << Name << " "; + dumpBits(errs(), + getBitsField(*AllInstructions[Opcodes[i]]->TheDef, "Inst")); + errs() << '\n'; + } +} + +// Calculates the island(s) needed to decode the instruction. +// This returns a list of undecoded bits of an instructions, for example, +// Inst{20} = 1 && Inst{3-0} == 0b1111 represents two islands of yet-to-be +// decoded bits in order to verify that the instruction matches the Opcode. +unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits, + std::vector<unsigned> &EndBits, + std::vector<uint64_t> &FieldVals, + const insn_t &Insn) const { + unsigned Num, BitNo; + Num = BitNo = 0; + + uint64_t FieldVal = 0; + + // 0: Init + // 1: Water (the bit value does not affect decoding) + // 2: Island (well-known bit value needed for decoding) + int State = 0; + int Val = -1; + + for (unsigned i = 0; i < BitWidth; ++i) { + Val = Value(Insn[i]); + bool Filtered = PositionFiltered(i); + switch (State) { + default: llvm_unreachable("Unreachable code!"); + case 0: + case 1: + if (Filtered || Val == -1) + State = 1; // Still in Water + else { + State = 2; // Into the Island + BitNo = 0; + StartBits.push_back(i); + FieldVal = Val; + } + break; + case 2: + if (Filtered || Val == -1) { + State = 1; // Into the Water + EndBits.push_back(i - 1); + FieldVals.push_back(FieldVal); + ++Num; + } else { + State = 2; // Still in Island + ++BitNo; + FieldVal = FieldVal | Val << BitNo; + } + break; + } + } + // If we are still in Island after the loop, do some housekeeping. + if (State == 2) { + EndBits.push_back(BitWidth - 1); + FieldVals.push_back(FieldVal); + ++Num; + } + + assert(StartBits.size() == Num && EndBits.size() == Num && + FieldVals.size() == Num); + return Num; +} + +void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation, + const OperandInfo &OpInfo) const { + const std::string &Decoder = OpInfo.Decoder; + + if (OpInfo.numFields() == 1) { + OperandInfo::const_iterator OI = OpInfo.begin(); + o.indent(Indentation) << " tmp = fieldFromInstruction" << BitWidth + << "(insn, " << OI->Base << ", " << OI->Width + << ");\n"; + } else { + o.indent(Indentation) << " tmp = 0;\n"; + for (OperandInfo::const_iterator OI = OpInfo.begin(), OE = OpInfo.end(); + OI != OE; ++OI) { + o.indent(Indentation) << " tmp |= (fieldFromInstruction" << BitWidth + << "(insn, " << OI->Base << ", " << OI->Width + << ") << " << OI->Offset << ");\n"; + } + } + + if (Decoder != "") + o.indent(Indentation) << " " << Emitter->GuardPrefix << Decoder + << "(MI, tmp, Address, Decoder)" + << Emitter->GuardPostfix << "\n"; + else + o.indent(Indentation) << " MI.addOperand(MCOperand::CreateImm(tmp));\n"; + +} + +static void emitSinglePredicateMatch(raw_ostream &o, StringRef str, + const std::string &PredicateNamespace) { + if (str[0] == '!') + o << "!(Bits & " << PredicateNamespace << "::" + << str.slice(1,str.size()) << ")"; + else + o << "(Bits & " << PredicateNamespace << "::" << str << ")"; +} + +bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation, + unsigned Opc) const { + ListInit *Predicates = + AllInstructions[Opc]->TheDef->getValueAsListInit("Predicates"); + for (unsigned i = 0; i < Predicates->getSize(); ++i) { + Record *Pred = Predicates->getElementAsRecord(i); + if (!Pred->getValue("AssemblerMatcherPredicate")) + continue; + + std::string P = Pred->getValueAsString("AssemblerCondString"); + + if (!P.length()) + continue; + + if (i != 0) + o << " && "; + + StringRef SR(P); + std::pair<StringRef, StringRef> pairs = SR.split(','); + while (pairs.second.size()) { + emitSinglePredicateMatch(o, pairs.first, Emitter->PredicateNamespace); + o << " && "; + pairs = pairs.second.split(','); + } + emitSinglePredicateMatch(o, pairs.first, Emitter->PredicateNamespace); + } + return Predicates->getSize() > 0; +} + +void FilterChooser::emitSoftFailCheck(raw_ostream &o, unsigned Indentation, + unsigned Opc) const { + BitsInit *SFBits = + AllInstructions[Opc]->TheDef->getValueAsBitsInit("SoftFail"); + if (!SFBits) return; + BitsInit *InstBits = AllInstructions[Opc]->TheDef->getValueAsBitsInit("Inst"); + + APInt PositiveMask(BitWidth, 0ULL); + APInt NegativeMask(BitWidth, 0ULL); + for (unsigned i = 0; i < BitWidth; ++i) { + bit_value_t B = bitFromBits(*SFBits, i); + bit_value_t IB = bitFromBits(*InstBits, i); + + if (B != BIT_TRUE) continue; + + switch (IB) { + case BIT_FALSE: + // The bit is meant to be false, so emit a check to see if it is true. + PositiveMask.setBit(i); + break; + case BIT_TRUE: + // The bit is meant to be true, so emit a check to see if it is false. + NegativeMask.setBit(i); + break; + default: + // The bit is not set; this must be an error! + StringRef Name = AllInstructions[Opc]->TheDef->getName(); + errs() << "SoftFail Conflict: bit SoftFail{" << i << "} in " + << Name + << " is set but Inst{" << i <<"} is unset!\n" + << " - You can only mark a bit as SoftFail if it is fully defined" + << " (1/0 - not '?') in Inst\n"; + o << "#error SoftFail Conflict, " << Name << "::SoftFail{" << i + << "} set but Inst{" << i << "} undefined!\n"; + } + } + + bool NeedPositiveMask = PositiveMask.getBoolValue(); + bool NeedNegativeMask = NegativeMask.getBoolValue(); + + if (!NeedPositiveMask && !NeedNegativeMask) + return; + + std::string PositiveMaskStr = PositiveMask.toString(16, /*signed=*/false); + std::string NegativeMaskStr = NegativeMask.toString(16, /*signed=*/false); + StringRef BitExt = ""; + if (BitWidth > 32) + BitExt = "ULL"; + + o.indent(Indentation) << "if ("; + if (NeedPositiveMask) + o << "insn & 0x" << PositiveMaskStr << BitExt; + if (NeedPositiveMask && NeedNegativeMask) + o << " || "; + if (NeedNegativeMask) + o << "~insn & 0x" << NegativeMaskStr << BitExt; + o << ")\n"; + o.indent(Indentation+2) << "S = MCDisassembler::SoftFail;\n"; +} + +// Emits code to decode the singleton. Return true if we have matched all the +// well-known bits. +bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, + unsigned Opc) const { + std::vector<unsigned> StartBits; + std::vector<unsigned> EndBits; + std::vector<uint64_t> FieldVals; + insn_t Insn; + insnWithID(Insn, Opc); + + // Look for islands of undecoded bits of the singleton. + getIslands(StartBits, EndBits, FieldVals, Insn); + + unsigned Size = StartBits.size(); + unsigned I, NumBits; + + // If we have matched all the well-known bits, just issue a return. + if (Size == 0) { + o.indent(Indentation) << "if ("; + if (!emitPredicateMatch(o, Indentation, Opc)) + o << "1"; + o << ") {\n"; + emitSoftFailCheck(o, Indentation+2, Opc); + o.indent(Indentation) << " MI.setOpcode(" << Opc << ");\n"; + std::map<unsigned, std::vector<OperandInfo> >::const_iterator OpIter = + Operands.find(Opc); + const std::vector<OperandInfo>& InsnOperands = OpIter->second; + for (std::vector<OperandInfo>::const_iterator + I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) { + // If a custom instruction decoder was specified, use that. + if (I->numFields() == 0 && I->Decoder.size()) { + o.indent(Indentation) << " " << Emitter->GuardPrefix << I->Decoder + << "(MI, insn, Address, Decoder)" + << Emitter->GuardPostfix << "\n"; + break; + } + + emitBinaryParser(o, Indentation, *I); + } + + o.indent(Indentation) << " return " << Emitter->ReturnOK << "; // " + << nameWithID(Opc) << '\n'; + o.indent(Indentation) << "}\n"; // Closing predicate block. + return true; + } + + // Otherwise, there are more decodings to be done! + + // Emit code to match the island(s) for the singleton. + o.indent(Indentation) << "// Check "; + + for (I = Size; I != 0; --I) { + o << "Inst{" << EndBits[I-1] << '-' << StartBits[I-1] << "} "; + if (I > 1) + o << " && "; + else + o << "for singleton decoding...\n"; + } + + o.indent(Indentation) << "if ("; + if (emitPredicateMatch(o, Indentation, Opc)) { + o << " &&\n"; + o.indent(Indentation+4); + } + + for (I = Size; I != 0; --I) { + NumBits = EndBits[I-1] - StartBits[I-1] + 1; + o << "fieldFromInstruction" << BitWidth << "(insn, " + << StartBits[I-1] << ", " << NumBits + << ") == " << FieldVals[I-1]; + if (I > 1) + o << " && "; + else + o << ") {\n"; + } + emitSoftFailCheck(o, Indentation+2, Opc); + o.indent(Indentation) << " MI.setOpcode(" << Opc << ");\n"; + std::map<unsigned, std::vector<OperandInfo> >::const_iterator OpIter = + Operands.find(Opc); + const std::vector<OperandInfo>& InsnOperands = OpIter->second; + for (std::vector<OperandInfo>::const_iterator + I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) { + // If a custom instruction decoder was specified, use that. + if (I->numFields() == 0 && I->Decoder.size()) { + o.indent(Indentation) << " " << Emitter->GuardPrefix << I->Decoder + << "(MI, insn, Address, Decoder)" + << Emitter->GuardPostfix << "\n"; + break; + } + + emitBinaryParser(o, Indentation, *I); + } + o.indent(Indentation) << " return " << Emitter->ReturnOK << "; // " + << nameWithID(Opc) << '\n'; + o.indent(Indentation) << "}\n"; + + return false; +} + +// Emits code to decode the singleton, and then to decode the rest. +void FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, + const Filter &Best) const { + + unsigned Opc = Best.getSingletonOpc(); + + emitSingletonDecoder(o, Indentation, Opc); + + // Emit code for the rest. + o.indent(Indentation) << "else\n"; + + Indentation += 2; + Best.getVariableFC().emit(o, Indentation); + Indentation -= 2; +} + +// Assign a single filter and run with it. Top level API client can initialize +// with a single filter to start the filtering process. +void FilterChooser::runSingleFilter(unsigned startBit, unsigned numBit, + bool mixed) { + Filters.clear(); + Filter F(*this, startBit, numBit, true); + Filters.push_back(F); + BestIndex = 0; // Sole Filter instance to choose from. + bestFilter().recurse(); +} + +// reportRegion is a helper function for filterProcessor to mark a region as +// eligible for use as a filter region. +void FilterChooser::reportRegion(bitAttr_t RA, unsigned StartBit, + unsigned BitIndex, bool AllowMixed) { + if (RA == ATTR_MIXED && AllowMixed) + Filters.push_back(Filter(*this, StartBit, BitIndex - StartBit, true)); + else if (RA == ATTR_ALL_SET && !AllowMixed) + Filters.push_back(Filter(*this, StartBit, BitIndex - StartBit, false)); +} + +// FilterProcessor scans the well-known encoding bits of the instructions and +// builds up a list of candidate filters. It chooses the best filter and +// recursively descends down the decoding tree. +bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { + Filters.clear(); + BestIndex = -1; + unsigned numInstructions = Opcodes.size(); + + assert(numInstructions && "Filter created with no instructions"); + + // No further filtering is necessary. + if (numInstructions == 1) + return true; + + // Heuristics. See also doFilter()'s "Heuristics" comment when num of + // instructions is 3. + if (AllowMixed && !Greedy) { + assert(numInstructions == 3); + + for (unsigned i = 0; i < Opcodes.size(); ++i) { + std::vector<unsigned> StartBits; + std::vector<unsigned> EndBits; + std::vector<uint64_t> FieldVals; + insn_t Insn; + + insnWithID(Insn, Opcodes[i]); + + // Look for islands of undecoded bits of any instruction. + if (getIslands(StartBits, EndBits, FieldVals, Insn) > 0) { + // Found an instruction with island(s). Now just assign a filter. + runSingleFilter(StartBits[0], EndBits[0] - StartBits[0] + 1, true); + return true; + } + } + } + + unsigned BitIndex, InsnIndex; + + // We maintain BIT_WIDTH copies of the bitAttrs automaton. + // The automaton consumes the corresponding bit from each + // instruction. + // + // Input symbols: 0, 1, and _ (unset). + // States: NONE, FILTERED, ALL_SET, ALL_UNSET, and MIXED. + // Initial state: NONE. + // + // (NONE) ------- [01] -> (ALL_SET) + // (NONE) ------- _ ----> (ALL_UNSET) + // (ALL_SET) ---- [01] -> (ALL_SET) + // (ALL_SET) ---- _ ----> (MIXED) + // (ALL_UNSET) -- [01] -> (MIXED) + // (ALL_UNSET) -- _ ----> (ALL_UNSET) + // (MIXED) ------ . ----> (MIXED) + // (FILTERED)---- . ----> (FILTERED) + + std::vector<bitAttr_t> bitAttrs; + + // FILTERED bit positions provide no entropy and are not worthy of pursuing. + // Filter::recurse() set either BIT_TRUE or BIT_FALSE for each position. + for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex) + if (FilterBitValues[BitIndex] == BIT_TRUE || + FilterBitValues[BitIndex] == BIT_FALSE) + bitAttrs.push_back(ATTR_FILTERED); + else + bitAttrs.push_back(ATTR_NONE); + + for (InsnIndex = 0; InsnIndex < numInstructions; ++InsnIndex) { + insn_t insn; + + insnWithID(insn, Opcodes[InsnIndex]); + + for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex) { + switch (bitAttrs[BitIndex]) { + case ATTR_NONE: + if (insn[BitIndex] == BIT_UNSET) + bitAttrs[BitIndex] = ATTR_ALL_UNSET; + else + bitAttrs[BitIndex] = ATTR_ALL_SET; + break; + case ATTR_ALL_SET: + if (insn[BitIndex] == BIT_UNSET) + bitAttrs[BitIndex] = ATTR_MIXED; + break; + case ATTR_ALL_UNSET: + if (insn[BitIndex] != BIT_UNSET) + bitAttrs[BitIndex] = ATTR_MIXED; + break; + case ATTR_MIXED: + case ATTR_FILTERED: + break; + } + } + } + + // The regionAttr automaton consumes the bitAttrs automatons' state, + // lowest-to-highest. + // + // Input symbols: F(iltered), (all_)S(et), (all_)U(nset), M(ixed) + // States: NONE, ALL_SET, MIXED + // Initial state: NONE + // + // (NONE) ----- F --> (NONE) + // (NONE) ----- S --> (ALL_SET) ; and set region start + // (NONE) ----- U --> (NONE) + // (NONE) ----- M --> (MIXED) ; and set region start + // (ALL_SET) -- F --> (NONE) ; and report an ALL_SET region + // (ALL_SET) -- S --> (ALL_SET) + // (ALL_SET) -- U --> (NONE) ; and report an ALL_SET region + // (ALL_SET) -- M --> (MIXED) ; and report an ALL_SET region + // (MIXED) ---- F --> (NONE) ; and report a MIXED region + // (MIXED) ---- S --> (ALL_SET) ; and report a MIXED region + // (MIXED) ---- U --> (NONE) ; and report a MIXED region + // (MIXED) ---- M --> (MIXED) + + bitAttr_t RA = ATTR_NONE; + unsigned StartBit = 0; + + for (BitIndex = 0; BitIndex < BitWidth; BitIndex++) { + bitAttr_t bitAttr = bitAttrs[BitIndex]; + + assert(bitAttr != ATTR_NONE && "Bit without attributes"); + + switch (RA) { + case ATTR_NONE: + switch (bitAttr) { + case ATTR_FILTERED: + break; + case ATTR_ALL_SET: + StartBit = BitIndex; + RA = ATTR_ALL_SET; + break; + case ATTR_ALL_UNSET: + break; + case ATTR_MIXED: + StartBit = BitIndex; + RA = ATTR_MIXED; + break; + default: + llvm_unreachable("Unexpected bitAttr!"); + } + break; + case ATTR_ALL_SET: + switch (bitAttr) { + case ATTR_FILTERED: + reportRegion(RA, StartBit, BitIndex, AllowMixed); + RA = ATTR_NONE; + break; + case ATTR_ALL_SET: + break; + case ATTR_ALL_UNSET: + reportRegion(RA, StartBit, BitIndex, AllowMixed); + RA = ATTR_NONE; + break; + case ATTR_MIXED: + reportRegion(RA, StartBit, BitIndex, AllowMixed); + StartBit = BitIndex; + RA = ATTR_MIXED; + break; + default: + llvm_unreachable("Unexpected bitAttr!"); + } + break; + case ATTR_MIXED: + switch (bitAttr) { + case ATTR_FILTERED: + reportRegion(RA, StartBit, BitIndex, AllowMixed); + StartBit = BitIndex; + RA = ATTR_NONE; + break; + case ATTR_ALL_SET: + reportRegion(RA, StartBit, BitIndex, AllowMixed); + StartBit = BitIndex; + RA = ATTR_ALL_SET; + break; + case ATTR_ALL_UNSET: + reportRegion(RA, StartBit, BitIndex, AllowMixed); + RA = ATTR_NONE; + break; + case ATTR_MIXED: + break; + default: + llvm_unreachable("Unexpected bitAttr!"); + } + break; + case ATTR_ALL_UNSET: + llvm_unreachable("regionAttr state machine has no ATTR_UNSET state"); + case ATTR_FILTERED: + llvm_unreachable("regionAttr state machine has no ATTR_FILTERED state"); + } + } + + // At the end, if we're still in ALL_SET or MIXED states, report a region + switch (RA) { + case ATTR_NONE: + break; + case ATTR_FILTERED: + break; + case ATTR_ALL_SET: + reportRegion(RA, StartBit, BitIndex, AllowMixed); + break; + case ATTR_ALL_UNSET: + break; + case ATTR_MIXED: + reportRegion(RA, StartBit, BitIndex, AllowMixed); + break; + } + + // We have finished with the filter processings. Now it's time to choose + // the best performing filter. + BestIndex = 0; + bool AllUseless = true; + unsigned BestScore = 0; + + for (unsigned i = 0, e = Filters.size(); i != e; ++i) { + unsigned Usefulness = Filters[i].usefulness(); + + if (Usefulness) + AllUseless = false; + + if (Usefulness > BestScore) { + BestIndex = i; + BestScore = Usefulness; + } + } + + if (!AllUseless) + bestFilter().recurse(); + + return !AllUseless; +} // end of FilterChooser::filterProcessor(bool) + +// Decides on the best configuration of filter(s) to use in order to decode +// the instructions. A conflict of instructions may occur, in which case we +// dump the conflict set to the standard error. +void FilterChooser::doFilter() { + unsigned Num = Opcodes.size(); + assert(Num && "FilterChooser created with no instructions"); + + // Try regions of consecutive known bit values first. + if (filterProcessor(false)) + return; + + // Then regions of mixed bits (both known and unitialized bit values allowed). + if (filterProcessor(true)) + return; + + // Heuristics to cope with conflict set {t2CMPrs, t2SUBSrr, t2SUBSrs} where + // no single instruction for the maximum ATTR_MIXED region Inst{14-4} has a + // well-known encoding pattern. In such case, we backtrack and scan for the + // the very first consecutive ATTR_ALL_SET region and assign a filter to it. + if (Num == 3 && filterProcessor(true, false)) + return; + + // If we come to here, the instruction decoding has failed. + // Set the BestIndex to -1 to indicate so. + BestIndex = -1; +} + +// Emits code to decode our share of instructions. Returns true if the +// emitted code causes a return, which occurs if we know how to decode +// the instruction at this level or the instruction is not decodeable. +bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) const { + if (Opcodes.size() == 1) + // There is only one instruction in the set, which is great! + // Call emitSingletonDecoder() to see whether there are any remaining + // encodings bits. + return emitSingletonDecoder(o, Indentation, Opcodes[0]); + + // Choose the best filter to do the decodings! + if (BestIndex != -1) { + const Filter &Best = Filters[BestIndex]; + if (Best.getNumFiltered() == 1) + emitSingletonDecoder(o, Indentation, Best); + else + Best.emit(o, Indentation); + return false; + } + + // We don't know how to decode these instructions! Return 0 and dump the + // conflict set! + o.indent(Indentation) << "return 0;" << " // Conflict set: "; + for (int i = 0, N = Opcodes.size(); i < N; ++i) { + o << nameWithID(Opcodes[i]); + if (i < (N - 1)) + o << ", "; + else + o << '\n'; + } + + // Print out useful conflict information for postmortem analysis. + errs() << "Decoding Conflict:\n"; + + dumpStack(errs(), "\t\t"); + + for (unsigned i = 0; i < Opcodes.size(); ++i) { + const std::string &Name = nameWithID(Opcodes[i]); + + errs() << '\t' << Name << " "; + dumpBits(errs(), + getBitsField(*AllInstructions[Opcodes[i]]->TheDef, "Inst")); + errs() << '\n'; + } + + return true; +} + +static bool populateInstruction(const CodeGenInstruction &CGI, unsigned Opc, + std::map<unsigned, std::vector<OperandInfo> > &Operands){ + const Record &Def = *CGI.TheDef; + // If all the bit positions are not specified; do not decode this instruction. + // We are bound to fail! For proper disassembly, the well-known encoding bits + // of the instruction must be fully specified. + // + // This also removes pseudo instructions from considerations of disassembly, + // which is a better design and less fragile than the name matchings. + // Ignore "asm parser only" instructions. + if (Def.getValueAsBit("isAsmParserOnly") || + Def.getValueAsBit("isCodeGenOnly")) + return false; + + BitsInit &Bits = getBitsField(Def, "Inst"); + if (Bits.allInComplete()) return false; + + std::vector<OperandInfo> InsnOperands; + + // If the instruction has specified a custom decoding hook, use that instead + // of trying to auto-generate the decoder. + std::string InstDecoder = Def.getValueAsString("DecoderMethod"); + if (InstDecoder != "") { + InsnOperands.push_back(OperandInfo(InstDecoder)); + Operands[Opc] = InsnOperands; + return true; + } + + // Generate a description of the operand of the instruction that we know + // how to decode automatically. + // FIXME: We'll need to have a way to manually override this as needed. + + // Gather the outputs/inputs of the instruction, so we can find their + // positions in the encoding. This assumes for now that they appear in the + // MCInst in the order that they're listed. + std::vector<std::pair<Init*, std::string> > InOutOperands; + DagInit *Out = Def.getValueAsDag("OutOperandList"); + DagInit *In = Def.getValueAsDag("InOperandList"); + for (unsigned i = 0; i < Out->getNumArgs(); ++i) + InOutOperands.push_back(std::make_pair(Out->getArg(i), Out->getArgName(i))); + for (unsigned i = 0; i < In->getNumArgs(); ++i) + InOutOperands.push_back(std::make_pair(In->getArg(i), In->getArgName(i))); + + // Search for tied operands, so that we can correctly instantiate + // operands that are not explicitly represented in the encoding. + std::map<std::string, std::string> TiedNames; + for (unsigned i = 0; i < CGI.Operands.size(); ++i) { + int tiedTo = CGI.Operands[i].getTiedRegister(); + if (tiedTo != -1) { + TiedNames[InOutOperands[i].second] = InOutOperands[tiedTo].second; + TiedNames[InOutOperands[tiedTo].second] = InOutOperands[i].second; + } + } + + // For each operand, see if we can figure out where it is encoded. + for (std::vector<std::pair<Init*, std::string> >::const_iterator + NI = InOutOperands.begin(), NE = InOutOperands.end(); NI != NE; ++NI) { + std::string Decoder = ""; + + // At this point, we can locate the field, but we need to know how to + // interpret it. As a first step, require the target to provide callbacks + // for decoding register classes. + // FIXME: This need to be extended to handle instructions with custom + // decoder methods, and operands with (simple) MIOperandInfo's. + TypedInit *TI = dynamic_cast<TypedInit*>(NI->first); + RecordRecTy *Type = dynamic_cast<RecordRecTy*>(TI->getType()); + Record *TypeRecord = Type->getRecord(); + bool isReg = false; + if (TypeRecord->isSubClassOf("RegisterOperand")) + TypeRecord = TypeRecord->getValueAsDef("RegClass"); + if (TypeRecord->isSubClassOf("RegisterClass")) { + Decoder = "Decode" + TypeRecord->getName() + "RegisterClass"; + isReg = true; + } + + RecordVal *DecoderString = TypeRecord->getValue("DecoderMethod"); + StringInit *String = DecoderString ? + dynamic_cast<StringInit*>(DecoderString->getValue()) : 0; + if (!isReg && String && String->getValue() != "") + Decoder = String->getValue(); + + OperandInfo OpInfo(Decoder); + unsigned Base = ~0U; + unsigned Width = 0; + unsigned Offset = 0; + + for (unsigned bi = 0; bi < Bits.getNumBits(); ++bi) { + VarInit *Var = 0; + VarBitInit *BI = dynamic_cast<VarBitInit*>(Bits.getBit(bi)); + if (BI) + Var = dynamic_cast<VarInit*>(BI->getVariable()); + else + Var = dynamic_cast<VarInit*>(Bits.getBit(bi)); + + if (!Var) { + if (Base != ~0U) { + OpInfo.addField(Base, Width, Offset); + Base = ~0U; + Width = 0; + Offset = 0; + } + continue; + } + + if (Var->getName() != NI->second && + Var->getName() != TiedNames[NI->second]) { + if (Base != ~0U) { + OpInfo.addField(Base, Width, Offset); + Base = ~0U; + Width = 0; + Offset = 0; + } + continue; + } + + if (Base == ~0U) { + Base = bi; + Width = 1; + Offset = BI ? BI->getBitNum() : 0; + } else if (BI && BI->getBitNum() != Offset + Width) { + OpInfo.addField(Base, Width, Offset); + Base = bi; + Width = 1; + Offset = BI->getBitNum(); + } else { + ++Width; + } + } + + if (Base != ~0U) + OpInfo.addField(Base, Width, Offset); + + if (OpInfo.numFields() > 0) + InsnOperands.push_back(OpInfo); + } + + Operands[Opc] = InsnOperands; + + +#if 0 + DEBUG({ + // Dumps the instruction encoding bits. + dumpBits(errs(), Bits); + + errs() << '\n'; + + // Dumps the list of operand info. + for (unsigned i = 0, e = CGI.Operands.size(); i != e; ++i) { + const CGIOperandList::OperandInfo &Info = CGI.Operands[i]; + const std::string &OperandName = Info.Name; + const Record &OperandDef = *Info.Rec; + + errs() << "\t" << OperandName << " (" << OperandDef.getName() << ")\n"; + } + }); +#endif + + return true; +} + +static void emitHelper(llvm::raw_ostream &o, unsigned BitWidth) { + unsigned Indentation = 0; + std::string WidthStr = "uint" + utostr(BitWidth) + "_t"; + + o << '\n'; + + o.indent(Indentation) << "static " << WidthStr << + " fieldFromInstruction" << BitWidth << + "(" << WidthStr <<" insn, unsigned startBit, unsigned numBits)\n"; + + o.indent(Indentation) << "{\n"; + + ++Indentation; ++Indentation; + o.indent(Indentation) << "assert(startBit + numBits <= " << BitWidth + << " && \"Instruction field out of bounds!\");\n"; + o << '\n'; + o.indent(Indentation) << WidthStr << " fieldMask;\n"; + o << '\n'; + o.indent(Indentation) << "if (numBits == " << BitWidth << ")\n"; + + ++Indentation; ++Indentation; + o.indent(Indentation) << "fieldMask = (" << WidthStr << ")-1;\n"; + --Indentation; --Indentation; + + o.indent(Indentation) << "else\n"; + + ++Indentation; ++Indentation; + o.indent(Indentation) << "fieldMask = ((1 << numBits) - 1) << startBit;\n"; + --Indentation; --Indentation; + + o << '\n'; + o.indent(Indentation) << "return (insn & fieldMask) >> startBit;\n"; + --Indentation; --Indentation; + + o.indent(Indentation) << "}\n"; + + o << '\n'; +} + +// Emits disassembler code for instruction decoding. +void FixedLenDecoderEmitter::run(raw_ostream &o) { + o << "#include \"llvm/MC/MCInst.h\"\n"; + o << "#include \"llvm/Support/DataTypes.h\"\n"; + o << "#include <assert.h>\n"; + o << '\n'; + o << "namespace llvm {\n\n"; + + // Parameterize the decoders based on namespace and instruction width. + const std::vector<const CodeGenInstruction*> &NumberedInstructions = + Target.getInstructionsByEnumValue(); + std::map<std::pair<std::string, unsigned>, + std::vector<unsigned> > OpcMap; + std::map<unsigned, std::vector<OperandInfo> > Operands; + + for (unsigned i = 0; i < NumberedInstructions.size(); ++i) { + const CodeGenInstruction *Inst = NumberedInstructions[i]; + const Record *Def = Inst->TheDef; + unsigned Size = Def->getValueAsInt("Size"); + if (Def->getValueAsString("Namespace") == "TargetOpcode" || + Def->getValueAsBit("isPseudo") || + Def->getValueAsBit("isAsmParserOnly") || + Def->getValueAsBit("isCodeGenOnly")) + continue; + + std::string DecoderNamespace = Def->getValueAsString("DecoderNamespace"); + + if (Size) { + if (populateInstruction(*Inst, i, Operands)) { + OpcMap[std::make_pair(DecoderNamespace, Size)].push_back(i); + } + } + } + + std::set<unsigned> Sizes; + for (std::map<std::pair<std::string, unsigned>, + std::vector<unsigned> >::const_iterator + I = OpcMap.begin(), E = OpcMap.end(); I != E; ++I) { + // If we haven't visited this instruction width before, emit the + // helper method to extract fields. + if (!Sizes.count(I->first.second)) { + emitHelper(o, 8*I->first.second); + Sizes.insert(I->first.second); + } + + // Emit the decoder for this namespace+width combination. + FilterChooser FC(NumberedInstructions, I->second, Operands, + 8*I->first.second, this); + FC.emitTop(o, 0, I->first.first); + } + + o << "\n} // End llvm namespace \n"; +} diff --git a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.h b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.h new file mode 100644 index 0000000..195297c --- /dev/null +++ b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.h @@ -0,0 +1,79 @@ +//===------------ FixedLenDecoderEmitter.h - Decoder Generator --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// It contains the tablegen backend that emits the decoder functions for +// targets with fixed length instruction set. +// +//===----------------------------------------------------------------------===// + +#ifndef FixedLenDECODEREMITTER_H +#define FixedLenDECODEREMITTER_H + +#include "CodeGenTarget.h" + +#include "llvm/TableGen/TableGenBackend.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +struct EncodingField { + unsigned Base, Width, Offset; + EncodingField(unsigned B, unsigned W, unsigned O) + : Base(B), Width(W), Offset(O) { } +}; + +struct OperandInfo { + std::vector<EncodingField> Fields; + std::string Decoder; + + OperandInfo(std::string D) + : Decoder(D) { } + + void addField(unsigned Base, unsigned Width, unsigned Offset) { + Fields.push_back(EncodingField(Base, Width, Offset)); + } + + unsigned numFields() const { return Fields.size(); } + + typedef std::vector<EncodingField>::const_iterator const_iterator; + + const_iterator begin() const { return Fields.begin(); } + const_iterator end() const { return Fields.end(); } +}; + +class FixedLenDecoderEmitter : public TableGenBackend { +public: + FixedLenDecoderEmitter(RecordKeeper &R, + std::string PredicateNamespace, + std::string GPrefix = "if (", + std::string GPostfix = " == MCDisassembler::Fail)" + " return MCDisassembler::Fail;", + std::string ROK = "MCDisassembler::Success", + std::string RFail = "MCDisassembler::Fail", + std::string L = "") : + Target(R), + PredicateNamespace(PredicateNamespace), + GuardPrefix(GPrefix), GuardPostfix(GPostfix), + ReturnOK(ROK), ReturnFail(RFail), Locals(L) {} + + // run - Output the code emitter + void run(raw_ostream &o); + +private: + CodeGenTarget Target; +public: + std::string PredicateNamespace; + std::string GuardPrefix, GuardPostfix; + std::string ReturnOK, ReturnFail; + std::string Locals; +}; + +} // end llvm namespace + +#endif diff --git a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp new file mode 100644 index 0000000..8b3efd3 --- /dev/null +++ b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp @@ -0,0 +1,396 @@ +//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend is responsible for emitting a description of the target +// instruction set for the code generator. +// +//===----------------------------------------------------------------------===// + +#include "InstrInfoEmitter.h" +#include "CodeGenTarget.h" +#include "SequenceToOffsetTable.h" +#include "llvm/TableGen/Record.h" +#include "llvm/ADT/StringExtras.h" +#include <algorithm> +#include <cstdio> +using namespace llvm; + +static void PrintDefList(const std::vector<Record*> &Uses, + unsigned Num, raw_ostream &OS) { + OS << "static const uint16_t ImplicitList" << Num << "[] = { "; + for (unsigned i = 0, e = Uses.size(); i != e; ++i) + OS << getQualifiedName(Uses[i]) << ", "; + OS << "0 };\n"; +} + +//===----------------------------------------------------------------------===// +// Instruction Itinerary Information. +//===----------------------------------------------------------------------===// + +void InstrInfoEmitter::GatherItinClasses() { + std::vector<Record*> DefList = + Records.getAllDerivedDefinitions("InstrItinClass"); + std::sort(DefList.begin(), DefList.end(), LessRecord()); + + for (unsigned i = 0, N = DefList.size(); i < N; i++) + ItinClassMap[DefList[i]->getName()] = i; +} + +unsigned InstrInfoEmitter::getItinClassNumber(const Record *InstRec) { + return ItinClassMap[InstRec->getValueAsDef("Itinerary")->getName()]; +} + +//===----------------------------------------------------------------------===// +// Operand Info Emission. +//===----------------------------------------------------------------------===// + +std::vector<std::string> +InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { + std::vector<std::string> Result; + + for (unsigned i = 0, e = Inst.Operands.size(); i != e; ++i) { + // Handle aggregate operands and normal operands the same way by expanding + // either case into a list of operands for this op. + std::vector<CGIOperandList::OperandInfo> OperandList; + + // This might be a multiple operand thing. Targets like X86 have + // registers in their multi-operand operands. It may also be an anonymous + // operand, which has a single operand, but no declared class for the + // operand. + DagInit *MIOI = Inst.Operands[i].MIOperandInfo; + + if (!MIOI || MIOI->getNumArgs() == 0) { + // Single, anonymous, operand. + OperandList.push_back(Inst.Operands[i]); + } else { + for (unsigned j = 0, e = Inst.Operands[i].MINumOperands; j != e; ++j) { + OperandList.push_back(Inst.Operands[i]); + + Record *OpR = dynamic_cast<DefInit*>(MIOI->getArg(j))->getDef(); + OperandList.back().Rec = OpR; + } + } + + for (unsigned j = 0, e = OperandList.size(); j != e; ++j) { + Record *OpR = OperandList[j].Rec; + std::string Res; + + if (OpR->isSubClassOf("RegisterOperand")) + OpR = OpR->getValueAsDef("RegClass"); + if (OpR->isSubClassOf("RegisterClass")) + Res += getQualifiedName(OpR) + "RegClassID, "; + else if (OpR->isSubClassOf("PointerLikeRegClass")) + Res += utostr(OpR->getValueAsInt("RegClassKind")) + ", "; + else + // -1 means the operand does not have a fixed register class. + Res += "-1, "; + + // Fill in applicable flags. + Res += "0"; + + // Ptr value whose register class is resolved via callback. + if (OpR->isSubClassOf("PointerLikeRegClass")) + Res += "|(1<<MCOI::LookupPtrRegClass)"; + + // Predicate operands. Check to see if the original unexpanded operand + // was of type PredicateOperand. + if (Inst.Operands[i].Rec->isSubClassOf("PredicateOperand")) + Res += "|(1<<MCOI::Predicate)"; + + // Optional def operands. Check to see if the original unexpanded operand + // was of type OptionalDefOperand. + if (Inst.Operands[i].Rec->isSubClassOf("OptionalDefOperand")) + Res += "|(1<<MCOI::OptionalDef)"; + + // Fill in operand type. + Res += ", MCOI::"; + assert(!Inst.Operands[i].OperandType.empty() && "Invalid operand type."); + Res += Inst.Operands[i].OperandType; + + // Fill in constraint info. + Res += ", "; + + const CGIOperandList::ConstraintInfo &Constraint = + Inst.Operands[i].Constraints[j]; + if (Constraint.isNone()) + Res += "0"; + else if (Constraint.isEarlyClobber()) + Res += "(1 << MCOI::EARLY_CLOBBER)"; + else { + assert(Constraint.isTied()); + Res += "((" + utostr(Constraint.getTiedOperand()) + + " << 16) | (1 << MCOI::TIED_TO))"; + } + + Result.push_back(Res); + } + } + + return Result; +} + +void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS, + OperandInfoMapTy &OperandInfoIDs) { + // ID #0 is for no operand info. + unsigned OperandListNum = 0; + OperandInfoIDs[std::vector<std::string>()] = ++OperandListNum; + + OS << "\n"; + const CodeGenTarget &Target = CDP.getTargetInfo(); + for (CodeGenTarget::inst_iterator II = Target.inst_begin(), + E = Target.inst_end(); II != E; ++II) { + std::vector<std::string> OperandInfo = GetOperandInfo(**II); + unsigned &N = OperandInfoIDs[OperandInfo]; + if (N != 0) continue; + + N = ++OperandListNum; + OS << "static const MCOperandInfo OperandInfo" << N << "[] = { "; + for (unsigned i = 0, e = OperandInfo.size(); i != e; ++i) + OS << "{ " << OperandInfo[i] << " }, "; + OS << "};\n"; + } +} + +//===----------------------------------------------------------------------===// +// Main Output. +//===----------------------------------------------------------------------===// + +// run - Emit the main instruction description records for the target... +void InstrInfoEmitter::run(raw_ostream &OS) { + emitEnums(OS); + + GatherItinClasses(); + + EmitSourceFileHeader("Target Instruction Descriptors", OS); + + OS << "\n#ifdef GET_INSTRINFO_MC_DESC\n"; + OS << "#undef GET_INSTRINFO_MC_DESC\n"; + + OS << "namespace llvm {\n\n"; + + CodeGenTarget &Target = CDP.getTargetInfo(); + const std::string &TargetName = Target.getName(); + Record *InstrInfo = Target.getInstructionSet(); + + // Keep track of all of the def lists we have emitted already. + std::map<std::vector<Record*>, unsigned> EmittedLists; + unsigned ListNumber = 0; + + // Emit all of the instruction's implicit uses and defs. + for (CodeGenTarget::inst_iterator II = Target.inst_begin(), + E = Target.inst_end(); II != E; ++II) { + Record *Inst = (*II)->TheDef; + std::vector<Record*> Uses = Inst->getValueAsListOfDefs("Uses"); + if (!Uses.empty()) { + unsigned &IL = EmittedLists[Uses]; + if (!IL) PrintDefList(Uses, IL = ++ListNumber, OS); + } + std::vector<Record*> Defs = Inst->getValueAsListOfDefs("Defs"); + if (!Defs.empty()) { + unsigned &IL = EmittedLists[Defs]; + if (!IL) PrintDefList(Defs, IL = ++ListNumber, OS); + } + } + + OperandInfoMapTy OperandInfoIDs; + + // Emit all of the operand info records. + EmitOperandInfo(OS, OperandInfoIDs); + + // Emit all of the MCInstrDesc records in their ENUM ordering. + // + OS << "\nextern const MCInstrDesc " << TargetName << "Insts[] = {\n"; + const std::vector<const CodeGenInstruction*> &NumberedInstructions = + Target.getInstructionsByEnumValue(); + + for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) + emitRecord(*NumberedInstructions[i], i, InstrInfo, EmittedLists, + OperandInfoIDs, OS); + OS << "};\n\n"; + + // Build an array of instruction names + SequenceToOffsetTable<std::string> InstrNames; + for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { + const CodeGenInstruction *Instr = NumberedInstructions[i]; + InstrNames.add(Instr->TheDef->getName()); + } + + InstrNames.layout(); + OS << "extern const char " << TargetName << "InstrNameData[] = {\n"; + InstrNames.emit(OS, printChar); + OS << "};\n\n"; + + OS << "extern const unsigned " << TargetName <<"InstrNameIndices[] = {"; + for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { + if (i % 8 == 0) + OS << "\n "; + const CodeGenInstruction *Instr = NumberedInstructions[i]; + OS << InstrNames.get(Instr->TheDef->getName()) << "U, "; + } + + OS << "\n};\n\n"; + + // MCInstrInfo initialization routine. + OS << "static inline void Init" << TargetName + << "MCInstrInfo(MCInstrInfo *II) {\n"; + OS << " II->InitMCInstrInfo(" << TargetName << "Insts, " + << TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, " + << NumberedInstructions.size() << ");\n}\n\n"; + + OS << "} // End llvm namespace \n"; + + OS << "#endif // GET_INSTRINFO_MC_DESC\n\n"; + + // Create a TargetInstrInfo subclass to hide the MC layer initialization. + OS << "\n#ifdef GET_INSTRINFO_HEADER\n"; + OS << "#undef GET_INSTRINFO_HEADER\n"; + + std::string ClassName = TargetName + "GenInstrInfo"; + OS << "namespace llvm {\n"; + OS << "struct " << ClassName << " : public TargetInstrInfoImpl {\n" + << " explicit " << ClassName << "(int SO = -1, int DO = -1);\n" + << "};\n"; + OS << "} // End llvm namespace \n"; + + OS << "#endif // GET_INSTRINFO_HEADER\n\n"; + + OS << "\n#ifdef GET_INSTRINFO_CTOR\n"; + OS << "#undef GET_INSTRINFO_CTOR\n"; + + OS << "namespace llvm {\n"; + OS << "extern const MCInstrDesc " << TargetName << "Insts[];\n"; + OS << "extern const unsigned " << TargetName << "InstrNameIndices[];\n"; + OS << "extern const char " << TargetName << "InstrNameData[];\n"; + OS << ClassName << "::" << ClassName << "(int SO, int DO)\n" + << " : TargetInstrInfoImpl(SO, DO) {\n" + << " InitMCInstrInfo(" << TargetName << "Insts, " + << TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, " + << NumberedInstructions.size() << ");\n}\n"; + OS << "} // End llvm namespace \n"; + + OS << "#endif // GET_INSTRINFO_CTOR\n\n"; +} + +void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, + Record *InstrInfo, + std::map<std::vector<Record*>, unsigned> &EmittedLists, + const OperandInfoMapTy &OpInfo, + raw_ostream &OS) { + int MinOperands = 0; + if (!Inst.Operands.size() == 0) + // Each logical operand can be multiple MI operands. + MinOperands = Inst.Operands.back().MIOperandNo + + Inst.Operands.back().MINumOperands; + + OS << " { "; + OS << Num << ",\t" << MinOperands << ",\t" + << Inst.Operands.NumDefs << ",\t" + << getItinClassNumber(Inst.TheDef) << ",\t" + << Inst.TheDef->getValueAsInt("Size") << ",\t0"; + + // Emit all of the target indepedent flags... + if (Inst.isPseudo) OS << "|(1<<MCID::Pseudo)"; + if (Inst.isReturn) OS << "|(1<<MCID::Return)"; + if (Inst.isBranch) OS << "|(1<<MCID::Branch)"; + if (Inst.isIndirectBranch) OS << "|(1<<MCID::IndirectBranch)"; + if (Inst.isCompare) OS << "|(1<<MCID::Compare)"; + if (Inst.isMoveImm) OS << "|(1<<MCID::MoveImm)"; + if (Inst.isBitcast) OS << "|(1<<MCID::Bitcast)"; + if (Inst.isBarrier) OS << "|(1<<MCID::Barrier)"; + if (Inst.hasDelaySlot) OS << "|(1<<MCID::DelaySlot)"; + if (Inst.isCall) OS << "|(1<<MCID::Call)"; + if (Inst.canFoldAsLoad) OS << "|(1<<MCID::FoldableAsLoad)"; + if (Inst.mayLoad) OS << "|(1<<MCID::MayLoad)"; + if (Inst.mayStore) OS << "|(1<<MCID::MayStore)"; + if (Inst.isPredicable) OS << "|(1<<MCID::Predicable)"; + if (Inst.isConvertibleToThreeAddress) OS << "|(1<<MCID::ConvertibleTo3Addr)"; + if (Inst.isCommutable) OS << "|(1<<MCID::Commutable)"; + if (Inst.isTerminator) OS << "|(1<<MCID::Terminator)"; + if (Inst.isReMaterializable) OS << "|(1<<MCID::Rematerializable)"; + if (Inst.isNotDuplicable) OS << "|(1<<MCID::NotDuplicable)"; + if (Inst.Operands.hasOptionalDef) OS << "|(1<<MCID::HasOptionalDef)"; + if (Inst.usesCustomInserter) OS << "|(1<<MCID::UsesCustomInserter)"; + if (Inst.hasPostISelHook) OS << "|(1<<MCID::HasPostISelHook)"; + if (Inst.Operands.isVariadic)OS << "|(1<<MCID::Variadic)"; + if (Inst.hasSideEffects) OS << "|(1<<MCID::UnmodeledSideEffects)"; + if (Inst.isAsCheapAsAMove) OS << "|(1<<MCID::CheapAsAMove)"; + if (Inst.hasExtraSrcRegAllocReq) OS << "|(1<<MCID::ExtraSrcRegAllocReq)"; + if (Inst.hasExtraDefRegAllocReq) OS << "|(1<<MCID::ExtraDefRegAllocReq)"; + + // Emit all of the target-specific flags... + BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags"); + if (!TSF) throw "no TSFlags?"; + uint64_t Value = 0; + for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) { + if (BitInit *Bit = dynamic_cast<BitInit*>(TSF->getBit(i))) + Value |= uint64_t(Bit->getValue()) << i; + else + throw "Invalid TSFlags bit in " + Inst.TheDef->getName(); + } + OS << ", 0x"; + OS.write_hex(Value); + OS << "ULL, "; + + // Emit the implicit uses and defs lists... + std::vector<Record*> UseList = Inst.TheDef->getValueAsListOfDefs("Uses"); + if (UseList.empty()) + OS << "NULL, "; + else + OS << "ImplicitList" << EmittedLists[UseList] << ", "; + + std::vector<Record*> DefList = Inst.TheDef->getValueAsListOfDefs("Defs"); + if (DefList.empty()) + OS << "NULL, "; + else + OS << "ImplicitList" << EmittedLists[DefList] << ", "; + + // Emit the operand info. + std::vector<std::string> OperandInfo = GetOperandInfo(Inst); + if (OperandInfo.empty()) + OS << "0"; + else + OS << "OperandInfo" << OpInfo.find(OperandInfo)->second; + + OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n"; +} + +// emitEnums - Print out enum values for all of the instructions. +void InstrInfoEmitter::emitEnums(raw_ostream &OS) { + EmitSourceFileHeader("Target Instruction Enum Values", OS); + + OS << "\n#ifdef GET_INSTRINFO_ENUM\n"; + OS << "#undef GET_INSTRINFO_ENUM\n"; + + OS << "namespace llvm {\n\n"; + + CodeGenTarget Target(Records); + + // We must emit the PHI opcode first... + std::string Namespace = Target.getInstNamespace(); + + if (Namespace.empty()) { + fprintf(stderr, "No instructions defined!\n"); + exit(1); + } + + const std::vector<const CodeGenInstruction*> &NumberedInstructions = + Target.getInstructionsByEnumValue(); + + OS << "namespace " << Namespace << " {\n"; + OS << " enum {\n"; + for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { + OS << " " << NumberedInstructions[i]->TheDef->getName() + << "\t= " << i << ",\n"; + } + OS << " INSTRUCTION_LIST_END = " << NumberedInstructions.size() << "\n"; + OS << " };\n}\n"; + OS << "} // End llvm namespace \n"; + + OS << "#endif // GET_INSTRINFO_ENUM\n\n"; +} diff --git a/contrib/llvm/utils/TableGen/InstrInfoEmitter.h b/contrib/llvm/utils/TableGen/InstrInfoEmitter.h new file mode 100644 index 0000000..f8d3ea5 --- /dev/null +++ b/contrib/llvm/utils/TableGen/InstrInfoEmitter.h @@ -0,0 +1,62 @@ +//===- InstrInfoEmitter.h - Generate a Instruction Set Desc. ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend is responsible for emitting a description of the target +// instruction set for the code generator. +// +//===----------------------------------------------------------------------===// + +#ifndef INSTRINFO_EMITTER_H +#define INSTRINFO_EMITTER_H + +#include "CodeGenDAGPatterns.h" +#include "llvm/TableGen/TableGenBackend.h" +#include <vector> +#include <map> + +namespace llvm { + +class StringInit; +class IntInit; +class ListInit; +class CodeGenInstruction; + +class InstrInfoEmitter : public TableGenBackend { + RecordKeeper &Records; + CodeGenDAGPatterns CDP; + std::map<std::string, unsigned> ItinClassMap; + +public: + InstrInfoEmitter(RecordKeeper &R) : Records(R), CDP(R) { } + + // run - Output the instruction set description. + void run(raw_ostream &OS); + +private: + void emitEnums(raw_ostream &OS); + + typedef std::map<std::vector<std::string>, unsigned> OperandInfoMapTy; + void emitRecord(const CodeGenInstruction &Inst, unsigned Num, + Record *InstrInfo, + std::map<std::vector<Record*>, unsigned> &EL, + const OperandInfoMapTy &OpInfo, + raw_ostream &OS); + + // Itinerary information. + void GatherItinClasses(); + unsigned getItinClassNumber(const Record *InstRec); + + // Operand information. + void EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs); + std::vector<std::string> GetOperandInfo(const CodeGenInstruction &Inst); +}; + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp new file mode 100644 index 0000000..8e1bae8 --- /dev/null +++ b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp @@ -0,0 +1,732 @@ +//===- IntrinsicEmitter.cpp - Generate intrinsic information --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend emits information about intrinsic functions. +// +//===----------------------------------------------------------------------===// + +#include "CodeGenTarget.h" +#include "IntrinsicEmitter.h" +#include "StringMatcher.h" +#include "llvm/TableGen/Record.h" +#include "llvm/ADT/StringExtras.h" +#include <algorithm> +using namespace llvm; + +//===----------------------------------------------------------------------===// +// IntrinsicEmitter Implementation +//===----------------------------------------------------------------------===// + +void IntrinsicEmitter::run(raw_ostream &OS) { + EmitSourceFileHeader("Intrinsic Function Source Fragment", OS); + + std::vector<CodeGenIntrinsic> Ints = LoadIntrinsics(Records, TargetOnly); + + if (TargetOnly && !Ints.empty()) + TargetPrefix = Ints[0].TargetPrefix; + + EmitPrefix(OS); + + // Emit the enum information. + EmitEnumInfo(Ints, OS); + + // Emit the intrinsic ID -> name table. + EmitIntrinsicToNameTable(Ints, OS); + + // Emit the intrinsic ID -> overload table. + EmitIntrinsicToOverloadTable(Ints, OS); + + // Emit the function name recognizer. + EmitFnNameRecognizer(Ints, OS); + + // Emit the intrinsic verifier. + EmitVerifier(Ints, OS); + + // Emit the intrinsic declaration generator. + EmitGenerator(Ints, OS); + + // Emit the intrinsic parameter attributes. + EmitAttributes(Ints, OS); + + // Emit intrinsic alias analysis mod/ref behavior. + EmitModRefBehavior(Ints, OS); + + // Emit code to translate GCC builtins into LLVM intrinsics. + EmitIntrinsicToGCCBuiltinMap(Ints, OS); + + EmitSuffix(OS); +} + +void IntrinsicEmitter::EmitPrefix(raw_ostream &OS) { + OS << "// VisualStudio defines setjmp as _setjmp\n" + "#if defined(_MSC_VER) && defined(setjmp) && \\\n" + " !defined(setjmp_undefined_for_msvc)\n" + "# pragma push_macro(\"setjmp\")\n" + "# undef setjmp\n" + "# define setjmp_undefined_for_msvc\n" + "#endif\n\n"; +} + +void IntrinsicEmitter::EmitSuffix(raw_ostream &OS) { + OS << "#if defined(_MSC_VER) && defined(setjmp_undefined_for_msvc)\n" + "// let's return it to _setjmp state\n" + "# pragma pop_macro(\"setjmp\")\n" + "# undef setjmp_undefined_for_msvc\n" + "#endif\n\n"; +} + +void IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints, + raw_ostream &OS) { + OS << "// Enum values for Intrinsics.h\n"; + OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n"; + for (unsigned i = 0, e = Ints.size(); i != e; ++i) { + OS << " " << Ints[i].EnumName; + OS << ((i != e-1) ? ", " : " "); + OS << std::string(40-Ints[i].EnumName.size(), ' ') + << "// " << Ints[i].Name << "\n"; + } + OS << "#endif\n\n"; +} + +void IntrinsicEmitter:: +EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints, + raw_ostream &OS) { + // Build a 'first character of function name' -> intrinsic # mapping. + std::map<char, std::vector<unsigned> > IntMapping; + for (unsigned i = 0, e = Ints.size(); i != e; ++i) + IntMapping[Ints[i].Name[5]].push_back(i); + + OS << "// Function name -> enum value recognizer code.\n"; + OS << "#ifdef GET_FUNCTION_RECOGNIZER\n"; + OS << " StringRef NameR(Name+6, Len-6); // Skip over 'llvm.'\n"; + OS << " switch (Name[5]) { // Dispatch on first letter.\n"; + OS << " default: break;\n"; + // Emit the intrinsic matching stuff by first letter. + for (std::map<char, std::vector<unsigned> >::iterator I = IntMapping.begin(), + E = IntMapping.end(); I != E; ++I) { + OS << " case '" << I->first << "':\n"; + std::vector<unsigned> &IntList = I->second; + + // Emit all the overloaded intrinsics first, build a table of the + // non-overloaded ones. + std::vector<StringMatcher::StringPair> MatchTable; + + for (unsigned i = 0, e = IntList.size(); i != e; ++i) { + unsigned IntNo = IntList[i]; + std::string Result = "return " + TargetPrefix + "Intrinsic::" + + Ints[IntNo].EnumName + ";"; + + if (!Ints[IntNo].isOverloaded) { + MatchTable.push_back(std::make_pair(Ints[IntNo].Name.substr(6),Result)); + continue; + } + + // For overloaded intrinsics, only the prefix needs to match + std::string TheStr = Ints[IntNo].Name.substr(6); + TheStr += '.'; // Require "bswap." instead of bswap. + OS << " if (NameR.startswith(\"" << TheStr << "\")) " + << Result << '\n'; + } + + // Emit the matcher logic for the fixed length strings. + StringMatcher("NameR", MatchTable, OS).Emit(1); + OS << " break; // end of '" << I->first << "' case.\n"; + } + + OS << " }\n"; + OS << "#endif\n\n"; +} + +void IntrinsicEmitter:: +EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints, + raw_ostream &OS) { + OS << "// Intrinsic ID to name table\n"; + OS << "#ifdef GET_INTRINSIC_NAME_TABLE\n"; + OS << " // Note that entry #0 is the invalid intrinsic!\n"; + for (unsigned i = 0, e = Ints.size(); i != e; ++i) + OS << " \"" << Ints[i].Name << "\",\n"; + OS << "#endif\n\n"; +} + +void IntrinsicEmitter:: +EmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints, + raw_ostream &OS) { + OS << "// Intrinsic ID to overload bitset\n"; + OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n"; + OS << "static const uint8_t OTable[] = {\n"; + OS << " 0"; + for (unsigned i = 0, e = Ints.size(); i != e; ++i) { + // Add one to the index so we emit a null bit for the invalid #0 intrinsic. + if ((i+1)%8 == 0) + OS << ",\n 0"; + if (Ints[i].isOverloaded) + OS << " | (1<<" << (i+1)%8 << ')'; + } + OS << "\n};\n\n"; + // OTable contains a true bit at the position if the intrinsic is overloaded. + OS << "return (OTable[id/8] & (1 << (id%8))) != 0;\n"; + OS << "#endif\n\n"; +} + +static void EmitTypeForValueType(raw_ostream &OS, MVT::SimpleValueType VT) { + if (EVT(VT).isInteger()) { + unsigned BitWidth = EVT(VT).getSizeInBits(); + OS << "IntegerType::get(Context, " << BitWidth << ")"; + } else if (VT == MVT::Other) { + // MVT::OtherVT is used to mean the empty struct type here. + OS << "StructType::get(Context)"; + } else if (VT == MVT::f16) { + OS << "Type::getHalfTy(Context)"; + } else if (VT == MVT::f32) { + OS << "Type::getFloatTy(Context)"; + } else if (VT == MVT::f64) { + OS << "Type::getDoubleTy(Context)"; + } else if (VT == MVT::f80) { + OS << "Type::getX86_FP80Ty(Context)"; + } else if (VT == MVT::f128) { + OS << "Type::getFP128Ty(Context)"; + } else if (VT == MVT::ppcf128) { + OS << "Type::getPPC_FP128Ty(Context)"; + } else if (VT == MVT::isVoid) { + OS << "Type::getVoidTy(Context)"; + } else if (VT == MVT::Metadata) { + OS << "Type::getMetadataTy(Context)"; + } else if (VT == MVT::x86mmx) { + OS << "Type::getX86_MMXTy(Context)"; + } else { + assert(false && "Unsupported ValueType!"); + } +} + +static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType, + unsigned &ArgNo); + +static void EmitTypeGenerate(raw_ostream &OS, + const std::vector<Record*> &ArgTypes, + unsigned &ArgNo) { + if (ArgTypes.empty()) + return EmitTypeForValueType(OS, MVT::isVoid); + + if (ArgTypes.size() == 1) + return EmitTypeGenerate(OS, ArgTypes.front(), ArgNo); + + OS << "StructType::get("; + + for (std::vector<Record*>::const_iterator + I = ArgTypes.begin(), E = ArgTypes.end(); I != E; ++I) { + EmitTypeGenerate(OS, *I, ArgNo); + OS << ", "; + } + + OS << " NULL)"; +} + +static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType, + unsigned &ArgNo) { + MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT")); + + if (ArgType->isSubClassOf("LLVMMatchType")) { + unsigned Number = ArgType->getValueAsInt("Number"); + assert(Number < ArgNo && "Invalid matching number!"); + if (ArgType->isSubClassOf("LLVMExtendedElementVectorType")) + OS << "VectorType::getExtendedElementVectorType" + << "(dyn_cast<VectorType>(Tys[" << Number << "]))"; + else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType")) + OS << "VectorType::getTruncatedElementVectorType" + << "(dyn_cast<VectorType>(Tys[" << Number << "]))"; + else + OS << "Tys[" << Number << "]"; + } else if (VT == MVT::iAny || VT == MVT::fAny || VT == MVT::vAny) { + // NOTE: The ArgNo variable here is not the absolute argument number, it is + // the index of the "arbitrary" type in the Tys array passed to the + // Intrinsic::getDeclaration function. Consequently, we only want to + // increment it when we actually hit an overloaded type. Getting this wrong + // leads to very subtle bugs! + OS << "Tys[" << ArgNo++ << "]"; + } else if (EVT(VT).isVector()) { + EVT VVT = VT; + OS << "VectorType::get("; + EmitTypeForValueType(OS, VVT.getVectorElementType().getSimpleVT().SimpleTy); + OS << ", " << VVT.getVectorNumElements() << ")"; + } else if (VT == MVT::iPTR) { + OS << "PointerType::getUnqual("; + EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo); + OS << ")"; + } else if (VT == MVT::iPTRAny) { + // Make sure the user has passed us an argument type to overload. If not, + // treat it as an ordinary (not overloaded) intrinsic. + OS << "(" << ArgNo << " < Tys.size()) ? Tys[" << ArgNo + << "] : PointerType::getUnqual("; + EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo); + OS << ")"; + ++ArgNo; + } else if (VT == MVT::isVoid) { + if (ArgNo == 0) + OS << "Type::getVoidTy(Context)"; + else + // MVT::isVoid is used to mean varargs here. + OS << "..."; + } else { + EmitTypeForValueType(OS, VT); + } +} + +/// RecordListComparator - Provide a deterministic comparator for lists of +/// records. +namespace { + typedef std::pair<std::vector<Record*>, std::vector<Record*> > RecPair; + struct RecordListComparator { + bool operator()(const RecPair &LHS, + const RecPair &RHS) const { + unsigned i = 0; + const std::vector<Record*> *LHSVec = &LHS.first; + const std::vector<Record*> *RHSVec = &RHS.first; + unsigned RHSSize = RHSVec->size(); + unsigned LHSSize = LHSVec->size(); + + for (; i != LHSSize; ++i) { + if (i == RHSSize) return false; // RHS is shorter than LHS. + if ((*LHSVec)[i] != (*RHSVec)[i]) + return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName(); + } + + if (i != RHSSize) return true; + + i = 0; + LHSVec = &LHS.second; + RHSVec = &RHS.second; + RHSSize = RHSVec->size(); + LHSSize = LHSVec->size(); + + for (i = 0; i != LHSSize; ++i) { + if (i == RHSSize) return false; // RHS is shorter than LHS. + if ((*LHSVec)[i] != (*RHSVec)[i]) + return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName(); + } + + return i != RHSSize; + } + }; +} + +void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints, + raw_ostream &OS) { + OS << "// Verifier::visitIntrinsicFunctionCall code.\n"; + OS << "#ifdef GET_INTRINSIC_VERIFIER\n"; + OS << " switch (ID) {\n"; + OS << " default: llvm_unreachable(\"Invalid intrinsic!\");\n"; + + // This checking can emit a lot of very common code. To reduce the amount of + // code that we emit, batch up cases that have identical types. This avoids + // problems where GCC can run out of memory compiling Verifier.cpp. + typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy; + MapTy UniqueArgInfos; + + // Compute the unique argument type info. + for (unsigned i = 0, e = Ints.size(); i != e; ++i) + UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs, + Ints[i].IS.ParamTypeDefs)].push_back(i); + + // Loop through the array, emitting one comparison for each batch. + for (MapTy::iterator I = UniqueArgInfos.begin(), + E = UniqueArgInfos.end(); I != E; ++I) { + for (unsigned i = 0, e = I->second.size(); i != e; ++i) + OS << " case Intrinsic::" << Ints[I->second[i]].EnumName << ":\t\t// " + << Ints[I->second[i]].Name << "\n"; + + const RecPair &ArgTypes = I->first; + const std::vector<Record*> &RetTys = ArgTypes.first; + const std::vector<Record*> &ParamTys = ArgTypes.second; + std::vector<unsigned> OverloadedTypeIndices; + + OS << " VerifyIntrinsicPrototype(ID, IF, " << RetTys.size() << ", " + << ParamTys.size(); + + // Emit return types. + for (unsigned j = 0, je = RetTys.size(); j != je; ++j) { + Record *ArgType = RetTys[j]; + OS << ", "; + + if (ArgType->isSubClassOf("LLVMMatchType")) { + unsigned Number = ArgType->getValueAsInt("Number"); + assert(Number < OverloadedTypeIndices.size() && + "Invalid matching number!"); + Number = OverloadedTypeIndices[Number]; + if (ArgType->isSubClassOf("LLVMExtendedElementVectorType")) + OS << "~(ExtendedElementVectorType | " << Number << ")"; + else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType")) + OS << "~(TruncatedElementVectorType | " << Number << ")"; + else + OS << "~" << Number; + } else { + MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT")); + OS << getEnumName(VT); + + if (EVT(VT).isOverloaded()) + OverloadedTypeIndices.push_back(j); + + if (VT == MVT::isVoid && j != 0 && j != je - 1) + throw "Var arg type not last argument"; + } + } + + // Emit the parameter types. + for (unsigned j = 0, je = ParamTys.size(); j != je; ++j) { + Record *ArgType = ParamTys[j]; + OS << ", "; + + if (ArgType->isSubClassOf("LLVMMatchType")) { + unsigned Number = ArgType->getValueAsInt("Number"); + assert(Number < OverloadedTypeIndices.size() && + "Invalid matching number!"); + Number = OverloadedTypeIndices[Number]; + if (ArgType->isSubClassOf("LLVMExtendedElementVectorType")) + OS << "~(ExtendedElementVectorType | " << Number << ")"; + else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType")) + OS << "~(TruncatedElementVectorType | " << Number << ")"; + else + OS << "~" << Number; + } else { + MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT")); + OS << getEnumName(VT); + + if (EVT(VT).isOverloaded()) + OverloadedTypeIndices.push_back(j + RetTys.size()); + + if (VT == MVT::isVoid && j != 0 && j != je - 1) + throw "Var arg type not last argument"; + } + } + + OS << ");\n"; + OS << " break;\n"; + } + OS << " }\n"; + OS << "#endif\n\n"; +} + +void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints, + raw_ostream &OS) { + OS << "// Code for generating Intrinsic function declarations.\n"; + OS << "#ifdef GET_INTRINSIC_GENERATOR\n"; + OS << " switch (id) {\n"; + OS << " default: llvm_unreachable(\"Invalid intrinsic!\");\n"; + + // Similar to GET_INTRINSIC_VERIFIER, batch up cases that have identical + // types. + typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy; + MapTy UniqueArgInfos; + + // Compute the unique argument type info. + for (unsigned i = 0, e = Ints.size(); i != e; ++i) + UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs, + Ints[i].IS.ParamTypeDefs)].push_back(i); + + // Loop through the array, emitting one generator for each batch. + std::string IntrinsicStr = TargetPrefix + "Intrinsic::"; + + for (MapTy::iterator I = UniqueArgInfos.begin(), + E = UniqueArgInfos.end(); I != E; ++I) { + for (unsigned i = 0, e = I->second.size(); i != e; ++i) + OS << " case " << IntrinsicStr << Ints[I->second[i]].EnumName + << ":\t\t// " << Ints[I->second[i]].Name << "\n"; + + const RecPair &ArgTypes = I->first; + const std::vector<Record*> &RetTys = ArgTypes.first; + const std::vector<Record*> &ParamTys = ArgTypes.second; + + unsigned N = ParamTys.size(); + + if (N > 1 && + getValueType(ParamTys[N - 1]->getValueAsDef("VT")) == MVT::isVoid) { + OS << " IsVarArg = true;\n"; + --N; + } + + unsigned ArgNo = 0; + OS << " ResultTy = "; + EmitTypeGenerate(OS, RetTys, ArgNo); + OS << ";\n"; + + for (unsigned j = 0; j != N; ++j) { + OS << " ArgTys.push_back("; + EmitTypeGenerate(OS, ParamTys[j], ArgNo); + OS << ");\n"; + } + + OS << " break;\n"; + } + + OS << " }\n"; + OS << "#endif\n\n"; +} + +namespace { + enum ModRefKind { + MRK_none, + MRK_readonly, + MRK_readnone + }; + + ModRefKind getModRefKind(const CodeGenIntrinsic &intrinsic) { + switch (intrinsic.ModRef) { + case CodeGenIntrinsic::NoMem: + return MRK_readnone; + case CodeGenIntrinsic::ReadArgMem: + case CodeGenIntrinsic::ReadMem: + return MRK_readonly; + case CodeGenIntrinsic::ReadWriteArgMem: + case CodeGenIntrinsic::ReadWriteMem: + return MRK_none; + } + llvm_unreachable("bad mod-ref kind"); + } + + struct AttributeComparator { + bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const { + // Sort throwing intrinsics after non-throwing intrinsics. + if (L->canThrow != R->canThrow) + return R->canThrow; + + // Try to order by readonly/readnone attribute. + ModRefKind LK = getModRefKind(*L); + ModRefKind RK = getModRefKind(*R); + if (LK != RK) return (LK > RK); + + // Order by argument attributes. + // This is reliable because each side is already sorted internally. + return (L->ArgumentAttributes < R->ArgumentAttributes); + } + }; +} + +/// EmitAttributes - This emits the Intrinsic::getAttributes method. +void IntrinsicEmitter:: +EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { + OS << "// Add parameter attributes that are not common to all intrinsics.\n"; + OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n"; + if (TargetOnly) + OS << "static AttrListPtr getAttributes(" << TargetPrefix + << "Intrinsic::ID id) {\n"; + else + OS << "AttrListPtr Intrinsic::getAttributes(ID id) {\n"; + + // Compute the maximum number of attribute arguments and the map + typedef std::map<const CodeGenIntrinsic*, unsigned, + AttributeComparator> UniqAttrMapTy; + UniqAttrMapTy UniqAttributes; + unsigned maxArgAttrs = 0; + unsigned AttrNum = 0; + for (unsigned i = 0, e = Ints.size(); i != e; ++i) { + const CodeGenIntrinsic &intrinsic = Ints[i]; + maxArgAttrs = + std::max(maxArgAttrs, unsigned(intrinsic.ArgumentAttributes.size())); + unsigned &N = UniqAttributes[&intrinsic]; + if (N) continue; + assert(AttrNum < 256 && "Too many unique attributes for table!"); + N = ++AttrNum; + } + + // Emit an array of AttributeWithIndex. Most intrinsics will have + // at least one entry, for the function itself (index ~1), which is + // usually nounwind. + OS << " static const uint8_t IntrinsicsToAttributesMap[] = {\n"; + + for (unsigned i = 0, e = Ints.size(); i != e; ++i) { + const CodeGenIntrinsic &intrinsic = Ints[i]; + + OS << " " << UniqAttributes[&intrinsic] << ", // " + << intrinsic.Name << "\n"; + } + OS << " };\n\n"; + + OS << " AttributeWithIndex AWI[" << maxArgAttrs+1 << "];\n"; + OS << " unsigned NumAttrs = 0;\n"; + OS << " if (id != 0) {\n"; + OS << " switch(IntrinsicsToAttributesMap[id - "; + if (TargetOnly) + OS << "Intrinsic::num_intrinsics"; + else + OS << "1"; + OS << "]) {\n"; + OS << " default: llvm_unreachable(\"Invalid attribute number\");\n"; + for (UniqAttrMapTy::const_iterator I = UniqAttributes.begin(), + E = UniqAttributes.end(); I != E; ++I) { + OS << " case " << I->second << ":\n"; + + const CodeGenIntrinsic &intrinsic = *(I->first); + + // Keep track of the number of attributes we're writing out. + unsigned numAttrs = 0; + + // The argument attributes are alreadys sorted by argument index. + for (unsigned ai = 0, ae = intrinsic.ArgumentAttributes.size(); ai != ae;) { + unsigned argNo = intrinsic.ArgumentAttributes[ai].first; + + OS << " AWI[" << numAttrs++ << "] = AttributeWithIndex::get(" + << argNo+1 << ", "; + + bool moreThanOne = false; + + do { + if (moreThanOne) OS << '|'; + + switch (intrinsic.ArgumentAttributes[ai].second) { + case CodeGenIntrinsic::NoCapture: + OS << "Attribute::NoCapture"; + break; + } + + ++ai; + moreThanOne = true; + } while (ai != ae && intrinsic.ArgumentAttributes[ai].first == argNo); + + OS << ");\n"; + } + + ModRefKind modRef = getModRefKind(intrinsic); + + if (!intrinsic.canThrow || modRef) { + OS << " AWI[" << numAttrs++ << "] = AttributeWithIndex::get(~0, "; + if (!intrinsic.canThrow) { + OS << "Attribute::NoUnwind"; + if (modRef) OS << '|'; + } + switch (modRef) { + case MRK_none: break; + case MRK_readonly: OS << "Attribute::ReadOnly"; break; + case MRK_readnone: OS << "Attribute::ReadNone"; break; + } + OS << ");\n"; + } + + if (numAttrs) { + OS << " NumAttrs = " << numAttrs << ";\n"; + OS << " break;\n"; + } else { + OS << " return AttrListPtr();\n"; + } + } + + OS << " }\n"; + OS << " }\n"; + OS << " return AttrListPtr::get(AWI, NumAttrs);\n"; + OS << "}\n"; + OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n"; +} + +/// EmitModRefBehavior - Determine intrinsic alias analysis mod/ref behavior. +void IntrinsicEmitter:: +EmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){ + OS << "// Determine intrinsic alias analysis mod/ref behavior.\n" + << "#ifdef GET_INTRINSIC_MODREF_BEHAVIOR\n" + << "assert(iid <= Intrinsic::" << Ints.back().EnumName << " && " + << "\"Unknown intrinsic.\");\n\n"; + + OS << "static const uint8_t IntrinsicModRefBehavior[] = {\n" + << " /* invalid */ UnknownModRefBehavior,\n"; + for (unsigned i = 0, e = Ints.size(); i != e; ++i) { + OS << " /* " << TargetPrefix << Ints[i].EnumName << " */ "; + switch (Ints[i].ModRef) { + case CodeGenIntrinsic::NoMem: + OS << "DoesNotAccessMemory,\n"; + break; + case CodeGenIntrinsic::ReadArgMem: + OS << "OnlyReadsArgumentPointees,\n"; + break; + case CodeGenIntrinsic::ReadMem: + OS << "OnlyReadsMemory,\n"; + break; + case CodeGenIntrinsic::ReadWriteArgMem: + OS << "OnlyAccessesArgumentPointees,\n"; + break; + case CodeGenIntrinsic::ReadWriteMem: + OS << "UnknownModRefBehavior,\n"; + break; + } + } + OS << "};\n\n" + << "return static_cast<ModRefBehavior>(IntrinsicModRefBehavior[iid]);\n" + << "#endif // GET_INTRINSIC_MODREF_BEHAVIOR\n\n"; +} + +/// EmitTargetBuiltins - All of the builtins in the specified map are for the +/// same target, and we already checked it. +static void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM, + const std::string &TargetPrefix, + raw_ostream &OS) { + + std::vector<StringMatcher::StringPair> Results; + + for (std::map<std::string, std::string>::const_iterator I = BIM.begin(), + E = BIM.end(); I != E; ++I) { + std::string ResultCode = + "return " + TargetPrefix + "Intrinsic::" + I->second + ";"; + Results.push_back(StringMatcher::StringPair(I->first, ResultCode)); + } + + StringMatcher("BuiltinName", Results, OS).Emit(); +} + + +void IntrinsicEmitter:: +EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, + raw_ostream &OS) { + typedef std::map<std::string, std::map<std::string, std::string> > BIMTy; + BIMTy BuiltinMap; + for (unsigned i = 0, e = Ints.size(); i != e; ++i) { + if (!Ints[i].GCCBuiltinName.empty()) { + // Get the map for this target prefix. + std::map<std::string, std::string> &BIM =BuiltinMap[Ints[i].TargetPrefix]; + + if (!BIM.insert(std::make_pair(Ints[i].GCCBuiltinName, + Ints[i].EnumName)).second) + throw "Intrinsic '" + Ints[i].TheDef->getName() + + "': duplicate GCC builtin name!"; + } + } + + OS << "// Get the LLVM intrinsic that corresponds to a GCC builtin.\n"; + OS << "// This is used by the C front-end. The GCC builtin name is passed\n"; + OS << "// in as BuiltinName, and a target prefix (e.g. 'ppc') is passed\n"; + OS << "// in as TargetPrefix. The result is assigned to 'IntrinsicID'.\n"; + OS << "#ifdef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN\n"; + + if (TargetOnly) { + OS << "static " << TargetPrefix << "Intrinsic::ID " + << "getIntrinsicForGCCBuiltin(const char " + << "*TargetPrefixStr, const char *BuiltinNameStr) {\n"; + } else { + OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char " + << "*TargetPrefixStr, const char *BuiltinNameStr) {\n"; + } + + OS << " StringRef BuiltinName(BuiltinNameStr);\n"; + OS << " StringRef TargetPrefix(TargetPrefixStr);\n\n"; + + // Note: this could emit significantly better code if we cared. + for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){ + OS << " "; + if (!I->first.empty()) + OS << "if (TargetPrefix == \"" << I->first << "\") "; + else + OS << "/* Target Independent Builtins */ "; + OS << "{\n"; + + // Emit the comparisons for this target prefix. + EmitTargetBuiltins(I->second, TargetPrefix, OS); + OS << " }\n"; + } + OS << " return "; + if (!TargetPrefix.empty()) + OS << "(" << TargetPrefix << "Intrinsic::ID)"; + OS << "Intrinsic::not_intrinsic;\n"; + OS << "}\n"; + OS << "#endif\n\n"; +} diff --git a/contrib/llvm/utils/TableGen/IntrinsicEmitter.h b/contrib/llvm/utils/TableGen/IntrinsicEmitter.h new file mode 100644 index 0000000..f9bcd59 --- /dev/null +++ b/contrib/llvm/utils/TableGen/IntrinsicEmitter.h @@ -0,0 +1,61 @@ +//===- IntrinsicEmitter.h - Generate intrinsic information ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend emits information about intrinsic functions. +// +//===----------------------------------------------------------------------===// + +#ifndef INTRINSIC_EMITTER_H +#define INTRINSIC_EMITTER_H + +#include "CodeGenIntrinsics.h" +#include "llvm/TableGen/TableGenBackend.h" + +namespace llvm { + class IntrinsicEmitter : public TableGenBackend { + RecordKeeper &Records; + bool TargetOnly; + std::string TargetPrefix; + + public: + IntrinsicEmitter(RecordKeeper &R, bool T = false) + : Records(R), TargetOnly(T) {} + + void run(raw_ostream &OS); + + void EmitPrefix(raw_ostream &OS); + + void EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints, + raw_ostream &OS); + + void EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints, + raw_ostream &OS); + void EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints, + raw_ostream &OS); + void EmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints, + raw_ostream &OS); + void EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints, + raw_ostream &OS); + void EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints, + raw_ostream &OS); + void EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, + raw_ostream &OS); + void EmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, + raw_ostream &OS); + void EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, + raw_ostream &OS); + void EmitSuffix(raw_ostream &OS); + }; + +} // End llvm namespace + +#endif + + + diff --git a/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp new file mode 100644 index 0000000..802d112 --- /dev/null +++ b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp @@ -0,0 +1,244 @@ +//===- PseudoLoweringEmitter.cpp - PseudoLowering Generator -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pseudo-lowering" +#include "CodeGenInstruction.h" +#include "PseudoLoweringEmitter.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" +#include "llvm/Support/Debug.h" +#include <vector> +using namespace llvm; + +// FIXME: This pass currently can only expand a pseudo to a single instruction. +// The pseudo expansion really should take a list of dags, not just +// a single dag, so we can do fancier things. + +unsigned PseudoLoweringEmitter:: +addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Insn, + IndexedMap<OpData> &OperandMap, unsigned BaseIdx) { + unsigned OpsAdded = 0; + for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) { + if (DefInit *DI = dynamic_cast<DefInit*>(Dag->getArg(i))) { + // Physical register reference. Explicit check for the special case + // "zero_reg" definition. + if (DI->getDef()->isSubClassOf("Register") || + DI->getDef()->getName() == "zero_reg") { + OperandMap[BaseIdx + i].Kind = OpData::Reg; + OperandMap[BaseIdx + i].Data.Reg = DI->getDef(); + ++OpsAdded; + continue; + } + + // Normal operands should always have the same type, or we have a + // problem. + // FIXME: We probably shouldn't ever get a non-zero BaseIdx here. + assert(BaseIdx == 0 && "Named subargument in pseudo expansion?!"); + if (DI->getDef() != Insn.Operands[BaseIdx + i].Rec) + throw TGError(Rec->getLoc(), + "Pseudo operand type '" + DI->getDef()->getName() + + "' does not match expansion operand type '" + + Insn.Operands[BaseIdx + i].Rec->getName() + "'"); + // Source operand maps to destination operand. The Data element + // will be filled in later, just set the Kind for now. Do it + // for each corresponding MachineInstr operand, not just the first. + for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I) + OperandMap[BaseIdx + i + I].Kind = OpData::Operand; + OpsAdded += Insn.Operands[i].MINumOperands; + } else if (IntInit *II = dynamic_cast<IntInit*>(Dag->getArg(i))) { + OperandMap[BaseIdx + i].Kind = OpData::Imm; + OperandMap[BaseIdx + i].Data.Imm = II->getValue(); + ++OpsAdded; + } else if (DagInit *SubDag = dynamic_cast<DagInit*>(Dag->getArg(i))) { + // Just add the operands recursively. This is almost certainly + // a constant value for a complex operand (> 1 MI operand). + unsigned NewOps = + addDagOperandMapping(Rec, SubDag, Insn, OperandMap, BaseIdx + i); + OpsAdded += NewOps; + // Since we added more than one, we also need to adjust the base. + BaseIdx += NewOps - 1; + } else + llvm_unreachable("Unhandled pseudo-expansion argument type!"); + } + return OpsAdded; +} + +void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) { + DEBUG(dbgs() << "Pseudo definition: " << Rec->getName() << "\n"); + + // Validate that the result pattern has the corrent number and types + // of arguments for the instruction it references. + DagInit *Dag = Rec->getValueAsDag("ResultInst"); + assert(Dag && "Missing result instruction in pseudo expansion!"); + DEBUG(dbgs() << " Result: " << *Dag << "\n"); + + DefInit *OpDef = dynamic_cast<DefInit*>(Dag->getOperator()); + if (!OpDef) + throw TGError(Rec->getLoc(), Rec->getName() + + " has unexpected operator type!"); + Record *Operator = OpDef->getDef(); + if (!Operator->isSubClassOf("Instruction")) + throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + + "' is not an instruction!"); + + CodeGenInstruction Insn(Operator); + + if (Insn.isCodeGenOnly || Insn.isPseudo) + throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + + "' cannot be another pseudo instruction!"); + + if (Insn.Operands.size() != Dag->getNumArgs()) + throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + + "' operand count mismatch"); + + unsigned NumMIOperands = 0; + for (unsigned i = 0, e = Insn.Operands.size(); i != e; ++i) + NumMIOperands += Insn.Operands[i].MINumOperands; + IndexedMap<OpData> OperandMap; + OperandMap.grow(NumMIOperands); + + addDagOperandMapping(Rec, Dag, Insn, OperandMap, 0); + + // If there are more operands that weren't in the DAG, they have to + // be operands that have default values, or we have an error. Currently, + // PredicateOperand and OptionalDefOperand both have default values. + + + // Validate that each result pattern argument has a matching (by name) + // argument in the source instruction, in either the (outs) or (ins) list. + // Also check that the type of the arguments match. + // + // Record the mapping of the source to result arguments for use by + // the lowering emitter. + CodeGenInstruction SourceInsn(Rec); + StringMap<unsigned> SourceOperands; + for (unsigned i = 0, e = SourceInsn.Operands.size(); i != e; ++i) + SourceOperands[SourceInsn.Operands[i].Name] = i; + + DEBUG(dbgs() << " Operand mapping:\n"); + for (unsigned i = 0, e = Insn.Operands.size(); i != e; ++i) { + // We've already handled constant values. Just map instruction operands + // here. + if (OperandMap[Insn.Operands[i].MIOperandNo].Kind != OpData::Operand) + continue; + StringMap<unsigned>::iterator SourceOp = + SourceOperands.find(Dag->getArgName(i)); + if (SourceOp == SourceOperands.end()) + throw TGError(Rec->getLoc(), + "Pseudo output operand '" + Dag->getArgName(i) + + "' has no matching source operand."); + // Map the source operand to the destination operand index for each + // MachineInstr operand. + for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I) + OperandMap[Insn.Operands[i].MIOperandNo + I].Data.Operand = + SourceOp->getValue(); + + DEBUG(dbgs() << " " << SourceOp->getValue() << " ==> " << i << "\n"); + } + + Expansions.push_back(PseudoExpansion(SourceInsn, Insn, OperandMap)); +} + +void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) { + // Emit file header. + EmitSourceFileHeader("Pseudo-instruction MC lowering Source Fragment", o); + + o << "bool " << Target.getName() + "AsmPrinter" << "::\n" + << "emitPseudoExpansionLowering(MCStreamer &OutStreamer,\n" + << " const MachineInstr *MI) {\n" + << " switch (MI->getOpcode()) {\n" + << " default: return false;\n"; + for (unsigned i = 0, e = Expansions.size(); i != e; ++i) { + PseudoExpansion &Expansion = Expansions[i]; + CodeGenInstruction &Source = Expansion.Source; + CodeGenInstruction &Dest = Expansion.Dest; + o << " case " << Source.Namespace << "::" + << Source.TheDef->getName() << ": {\n" + << " MCInst TmpInst;\n" + << " MCOperand MCOp;\n" + << " TmpInst.setOpcode(" << Dest.Namespace << "::" + << Dest.TheDef->getName() << ");\n"; + + // Copy the operands from the source instruction. + // FIXME: Instruction operands with defaults values (predicates and cc_out + // in ARM, for example shouldn't need explicit values in the + // expansion DAG. + unsigned MIOpNo = 0; + for (unsigned OpNo = 0, E = Dest.Operands.size(); OpNo != E; + ++OpNo) { + o << " // Operand: " << Dest.Operands[OpNo].Name << "\n"; + for (unsigned i = 0, e = Dest.Operands[OpNo].MINumOperands; + i != e; ++i) { + switch (Expansion.OperandMap[MIOpNo + i].Kind) { + case OpData::Operand: + o << " lowerOperand(MI->getOperand(" + << Source.Operands[Expansion.OperandMap[MIOpNo].Data + .Operand].MIOperandNo + i + << "), MCOp);\n" + << " TmpInst.addOperand(MCOp);\n"; + break; + case OpData::Imm: + o << " TmpInst.addOperand(MCOperand::CreateImm(" + << Expansion.OperandMap[MIOpNo + i].Data.Imm << "));\n"; + break; + case OpData::Reg: { + Record *Reg = Expansion.OperandMap[MIOpNo + i].Data.Reg; + o << " TmpInst.addOperand(MCOperand::CreateReg("; + // "zero_reg" is special. + if (Reg->getName() == "zero_reg") + o << "0"; + else + o << Reg->getValueAsString("Namespace") << "::" << Reg->getName(); + o << "));\n"; + break; + } + } + } + MIOpNo += Dest.Operands[OpNo].MINumOperands; + } + if (Dest.Operands.isVariadic) { + o << " // variable_ops\n"; + o << " for (unsigned i = " << MIOpNo + << ", e = MI->getNumOperands(); i != e; ++i)\n" + << " if (lowerOperand(MI->getOperand(i), MCOp))\n" + << " TmpInst.addOperand(MCOp);\n"; + } + o << " OutStreamer.EmitInstruction(TmpInst);\n" + << " break;\n" + << " }\n"; + } + o << " }\n return true;\n}\n\n"; +} + +void PseudoLoweringEmitter::run(raw_ostream &o) { + Record *ExpansionClass = Records.getClass("PseudoInstExpansion"); + Record *InstructionClass = Records.getClass("PseudoInstExpansion"); + assert(ExpansionClass && "PseudoInstExpansion class definition missing!"); + assert(InstructionClass && "Instruction class definition missing!"); + + std::vector<Record*> Insts; + for (std::map<std::string, Record*>::const_iterator I = + Records.getDefs().begin(), E = Records.getDefs().end(); I != E; ++I) { + if (I->second->isSubClassOf(ExpansionClass) && + I->second->isSubClassOf(InstructionClass)) + Insts.push_back(I->second); + } + + // Process the pseudo expansion definitions, validating them as we do so. + for (unsigned i = 0, e = Insts.size(); i != e; ++i) + evaluateExpansion(Insts[i]); + + // Generate expansion code to lower the pseudo to an MCInst of the real + // instruction. + emitLoweringEmitter(o); +} + diff --git a/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.h b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.h new file mode 100644 index 0000000..325bc8b --- /dev/null +++ b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.h @@ -0,0 +1,65 @@ +//===- PseudoLoweringEmitter.h - PseudoLowering Generator -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef PSEUDOLOWERINGEMITTER_H +#define PSEUDOLOWERINGEMITTER_H + +#include "CodeGenInstruction.h" +#include "CodeGenTarget.h" +#include "llvm/TableGen/TableGenBackend.h" +#include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +class PseudoLoweringEmitter : public TableGenBackend { + struct OpData { + enum MapKind { Operand, Imm, Reg }; + MapKind Kind; + union { + unsigned Operand; // Operand number mapped to. + uint64_t Imm; // Integer immedate value. + Record *Reg; // Physical register. + } Data; + }; + struct PseudoExpansion { + CodeGenInstruction Source; // The source pseudo instruction definition. + CodeGenInstruction Dest; // The destination instruction to lower to. + IndexedMap<OpData> OperandMap; + + PseudoExpansion(CodeGenInstruction &s, CodeGenInstruction &d, + IndexedMap<OpData> &m) : + Source(s), Dest(d), OperandMap(m) {} + }; + + RecordKeeper &Records; + + // It's overkill to have an instance of the full CodeGenTarget object, + // but it loads everything on demand, not in the constructor, so it's + // lightweight in performance, so it works out OK. + CodeGenTarget Target; + + SmallVector<PseudoExpansion, 64> Expansions; + + unsigned addDagOperandMapping(Record *Rec, DagInit *Dag, + CodeGenInstruction &Insn, + IndexedMap<OpData> &OperandMap, + unsigned BaseIdx); + void evaluateExpansion(Record *Pseudo); + void emitLoweringEmitter(raw_ostream &o); +public: + PseudoLoweringEmitter(RecordKeeper &R) : Records(R), Target(R) {} + + /// run - Output the pseudo-lowerings. + void run(raw_ostream &o); +}; + +} // end llvm namespace + +#endif diff --git a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp new file mode 100644 index 0000000..97fcca3 --- /dev/null +++ b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp @@ -0,0 +1,1113 @@ +//===- RegisterInfoEmitter.cpp - Generate a Register File Desc. -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend is responsible for emitting a description of a target +// register file for a code generator. It uses instances of the Register, +// RegisterAliases, and RegisterClass classes to gather this information. +// +//===----------------------------------------------------------------------===// + +#include "RegisterInfoEmitter.h" +#include "CodeGenTarget.h" +#include "CodeGenRegisters.h" +#include "SequenceToOffsetTable.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Format.h" +#include <algorithm> +#include <set> +using namespace llvm; + +// runEnums - Print out enum values for all of the registers. +void RegisterInfoEmitter::runEnums(raw_ostream &OS, + CodeGenTarget &Target, CodeGenRegBank &Bank) { + const std::vector<CodeGenRegister*> &Registers = Bank.getRegisters(); + + // Register enums are stored as uint16_t in the tables. Make sure we'll fit. + assert(Registers.size() <= 0xffff && "Too many regs to fit in tables"); + + std::string Namespace = Registers[0]->TheDef->getValueAsString("Namespace"); + + EmitSourceFileHeader("Target Register Enum Values", OS); + + OS << "\n#ifdef GET_REGINFO_ENUM\n"; + OS << "#undef GET_REGINFO_ENUM\n"; + + OS << "namespace llvm {\n\n"; + + OS << "class MCRegisterClass;\n" + << "extern const MCRegisterClass " << Namespace + << "MCRegisterClasses[];\n\n"; + + if (!Namespace.empty()) + OS << "namespace " << Namespace << " {\n"; + OS << "enum {\n NoRegister,\n"; + + for (unsigned i = 0, e = Registers.size(); i != e; ++i) + OS << " " << Registers[i]->getName() << " = " << + Registers[i]->EnumValue << ",\n"; + assert(Registers.size() == Registers[Registers.size()-1]->EnumValue && + "Register enum value mismatch!"); + OS << " NUM_TARGET_REGS \t// " << Registers.size()+1 << "\n"; + OS << "};\n"; + if (!Namespace.empty()) + OS << "}\n"; + + ArrayRef<CodeGenRegisterClass*> RegisterClasses = Bank.getRegClasses(); + if (!RegisterClasses.empty()) { + + // RegisterClass enums are stored as uint16_t in the tables. + assert(RegisterClasses.size() <= 0xffff && + "Too many register classes to fit in tables"); + + OS << "\n// Register classes\n"; + if (!Namespace.empty()) + OS << "namespace " << Namespace << " {\n"; + OS << "enum {\n"; + for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { + if (i) OS << ",\n"; + OS << " " << RegisterClasses[i]->getName() << "RegClassID"; + OS << " = " << i; + } + OS << "\n };\n"; + if (!Namespace.empty()) + OS << "}\n"; + } + + const std::vector<Record*> RegAltNameIndices = Target.getRegAltNameIndices(); + // If the only definition is the default NoRegAltName, we don't need to + // emit anything. + if (RegAltNameIndices.size() > 1) { + OS << "\n// Register alternate name indices\n"; + if (!Namespace.empty()) + OS << "namespace " << Namespace << " {\n"; + OS << "enum {\n"; + for (unsigned i = 0, e = RegAltNameIndices.size(); i != e; ++i) + OS << " " << RegAltNameIndices[i]->getName() << ",\t// " << i << "\n"; + OS << " NUM_TARGET_REG_ALT_NAMES = " << RegAltNameIndices.size() << "\n"; + OS << "};\n"; + if (!Namespace.empty()) + OS << "}\n"; + } + + ArrayRef<CodeGenSubRegIndex*> SubRegIndices = Bank.getSubRegIndices(); + if (!SubRegIndices.empty()) { + OS << "\n// Subregister indices\n"; + std::string Namespace = + SubRegIndices[0]->getNamespace(); + if (!Namespace.empty()) + OS << "namespace " << Namespace << " {\n"; + OS << "enum {\n NoSubRegister,\n"; + for (unsigned i = 0, e = Bank.getNumNamedIndices(); i != e; ++i) + OS << " " << SubRegIndices[i]->getName() << ",\t// " << i+1 << "\n"; + OS << " NUM_TARGET_NAMED_SUBREGS\n};\n"; + if (!Namespace.empty()) + OS << "}\n"; + } + + OS << "} // End llvm namespace \n"; + OS << "#endif // GET_REGINFO_ENUM\n\n"; +} + +void RegisterInfoEmitter:: +EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, + const std::string &ClassName) { + unsigned NumRCs = RegBank.getRegClasses().size(); + unsigned NumSets = RegBank.getNumRegPressureSets(); + + OS << "/// Get the weight in units of pressure for this register class.\n" + << "const RegClassWeight &" << ClassName << "::\n" + << "getRegClassWeight(const TargetRegisterClass *RC) const {\n" + << " static const RegClassWeight RCWeightTable[] = {\n"; + for (unsigned i = 0, e = NumRCs; i != e; ++i) { + const CodeGenRegisterClass &RC = *RegBank.getRegClasses()[i]; + const CodeGenRegister::Set &Regs = RC.getMembers(); + if (Regs.empty()) + OS << " {0, 0"; + else { + std::vector<unsigned> RegUnits; + RC.buildRegUnitSet(RegUnits); + OS << " {" << (*Regs.begin())->getWeight(RegBank) + << ", " << RegBank.getRegUnitSetWeight(RegUnits); + } + OS << "}, \t// " << RC.getName() << "\n"; + } + OS << " {0, 0} };\n" + << " return RCWeightTable[RC->getID()];\n" + << "}\n\n"; + + OS << "\n" + << "// Get the number of dimensions of register pressure.\n" + << "unsigned " << ClassName << "::getNumRegPressureSets() const {\n" + << " return " << NumSets << ";\n}\n\n"; + + OS << "// Get the register unit pressure limit for this dimension.\n" + << "// This limit must be adjusted dynamically for reserved registers.\n" + << "unsigned " << ClassName << "::\n" + << "getRegPressureSetLimit(unsigned Idx) const {\n" + << " static const unsigned PressureLimitTable[] = {\n"; + for (unsigned i = 0; i < NumSets; ++i ) { + const RegUnitSet &RegUnits = RegBank.getRegPressureSet(i); + OS << " " << RegBank.getRegUnitSetWeight(RegUnits.Units) + << ", \t// " << i << ": " << RegBank.getRegPressureSet(i).Name << "\n"; + } + OS << " 0 };\n" + << " return PressureLimitTable[Idx];\n" + << "}\n\n"; + + OS << "/// Get the dimensions of register pressure " + << "impacted by this register class.\n" + << "/// Returns a -1 terminated array of pressure set IDs\n" + << "const int* " << ClassName << "::\n" + << "getRegClassPressureSets(const TargetRegisterClass *RC) const {\n" + << " static const int RCSetsTable[] = {\n "; + std::vector<unsigned> RCSetStarts(NumRCs); + for (unsigned i = 0, StartIdx = 0, e = NumRCs; i != e; ++i) { + RCSetStarts[i] = StartIdx; + ArrayRef<unsigned> PSetIDs = RegBank.getRCPressureSetIDs(i); + for (ArrayRef<unsigned>::iterator PSetI = PSetIDs.begin(), + PSetE = PSetIDs.end(); PSetI != PSetE; ++PSetI) { + OS << *PSetI << ", "; + ++StartIdx; + } + OS << "-1, \t// " << RegBank.getRegClasses()[i]->getName() << "\n "; + ++StartIdx; + } + OS << "-1 };\n"; + OS << " static const unsigned RCSetStartTable[] = {\n "; + for (unsigned i = 0, e = NumRCs; i != e; ++i) { + OS << RCSetStarts[i] << ","; + } + OS << "0 };\n" + << " unsigned SetListStart = RCSetStartTable[RC->getID()];\n" + << " return &RCSetsTable[SetListStart];\n" + << "}\n\n"; +} + +void +RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, + const std::vector<CodeGenRegister*> &Regs, + bool isCtor) { + // Collect all information about dwarf register numbers + typedef std::map<Record*, std::vector<int64_t>, LessRecord> DwarfRegNumsMapTy; + DwarfRegNumsMapTy DwarfRegNums; + + // First, just pull all provided information to the map + unsigned maxLength = 0; + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + Record *Reg = Regs[i]->TheDef; + std::vector<int64_t> RegNums = Reg->getValueAsListOfInts("DwarfNumbers"); + maxLength = std::max((size_t)maxLength, RegNums.size()); + if (DwarfRegNums.count(Reg)) + PrintWarning(Reg->getLoc(), Twine("DWARF numbers for register ") + + getQualifiedName(Reg) + "specified multiple times"); + DwarfRegNums[Reg] = RegNums; + } + + if (!maxLength) + return; + + // Now we know maximal length of number list. Append -1's, where needed + for (DwarfRegNumsMapTy::iterator + I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) + for (unsigned i = I->second.size(), e = maxLength; i != e; ++i) + I->second.push_back(-1); + + std::string Namespace = Regs[0]->TheDef->getValueAsString("Namespace"); + + OS << "// " << Namespace << " Dwarf<->LLVM register mappings.\n"; + + // Emit reverse information about the dwarf register numbers. + for (unsigned j = 0; j < 2; ++j) { + for (unsigned i = 0, e = maxLength; i != e; ++i) { + OS << "extern const MCRegisterInfo::DwarfLLVMRegPair " << Namespace; + OS << (j == 0 ? "DwarfFlavour" : "EHFlavour"); + OS << i << "Dwarf2L[]"; + + if (!isCtor) { + OS << " = {\n"; + + // Store the mapping sorted by the LLVM reg num so lookup can be done + // with a binary search. + std::map<uint64_t, Record*> Dwarf2LMap; + for (DwarfRegNumsMapTy::iterator + I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) { + int DwarfRegNo = I->second[i]; + if (DwarfRegNo < 0) + continue; + Dwarf2LMap[DwarfRegNo] = I->first; + } + + for (std::map<uint64_t, Record*>::iterator + I = Dwarf2LMap.begin(), E = Dwarf2LMap.end(); I != E; ++I) + OS << " { " << I->first << "U, " << getQualifiedName(I->second) + << " },\n"; + + OS << "};\n"; + } else { + OS << ";\n"; + } + + // We have to store the size in a const global, it's used in multiple + // places. + OS << "extern const unsigned " << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "Dwarf2LSize"; + if (!isCtor) + OS << " = sizeof(" << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i + << "Dwarf2L)/sizeof(MCRegisterInfo::DwarfLLVMRegPair);\n\n"; + else + OS << ";\n\n"; + } + } + + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + Record *Reg = Regs[i]->TheDef; + const RecordVal *V = Reg->getValue("DwarfAlias"); + if (!V || !V->getValue()) + continue; + + DefInit *DI = dynamic_cast<DefInit*>(V->getValue()); + Record *Alias = DI->getDef(); + DwarfRegNums[Reg] = DwarfRegNums[Alias]; + } + + // Emit information about the dwarf register numbers. + for (unsigned j = 0; j < 2; ++j) { + for (unsigned i = 0, e = maxLength; i != e; ++i) { + OS << "extern const MCRegisterInfo::DwarfLLVMRegPair " << Namespace; + OS << (j == 0 ? "DwarfFlavour" : "EHFlavour"); + OS << i << "L2Dwarf[]"; + if (!isCtor) { + OS << " = {\n"; + // Store the mapping sorted by the Dwarf reg num so lookup can be done + // with a binary search. + for (DwarfRegNumsMapTy::iterator + I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) { + int RegNo = I->second[i]; + if (RegNo == -1) // -1 is the default value, don't emit a mapping. + continue; + + OS << " { " << getQualifiedName(I->first) << ", " << RegNo + << "U },\n"; + } + OS << "};\n"; + } else { + OS << ";\n"; + } + + // We have to store the size in a const global, it's used in multiple + // places. + OS << "extern const unsigned " << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2DwarfSize"; + if (!isCtor) + OS << " = sizeof(" << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i + << "L2Dwarf)/sizeof(MCRegisterInfo::DwarfLLVMRegPair);\n\n"; + else + OS << ";\n\n"; + } + } +} + +void +RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS, + const std::vector<CodeGenRegister*> &Regs, + bool isCtor) { + // Emit the initializer so the tables from EmitRegMappingTables get wired up + // to the MCRegisterInfo object. + unsigned maxLength = 0; + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + Record *Reg = Regs[i]->TheDef; + maxLength = std::max((size_t)maxLength, + Reg->getValueAsListOfInts("DwarfNumbers").size()); + } + + if (!maxLength) + return; + + std::string Namespace = Regs[0]->TheDef->getValueAsString("Namespace"); + + // Emit reverse information about the dwarf register numbers. + for (unsigned j = 0; j < 2; ++j) { + OS << " switch ("; + if (j == 0) + OS << "DwarfFlavour"; + else + OS << "EHFlavour"; + OS << ") {\n" + << " default:\n" + << " llvm_unreachable(\"Unknown DWARF flavour\");\n"; + + for (unsigned i = 0, e = maxLength; i != e; ++i) { + OS << " case " << i << ":\n"; + OS << " "; + if (!isCtor) + OS << "RI->"; + std::string Tmp; + raw_string_ostream(Tmp) << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i + << "Dwarf2L"; + OS << "mapDwarfRegsToLLVMRegs(" << Tmp << ", " << Tmp << "Size, "; + if (j == 0) + OS << "false"; + else + OS << "true"; + OS << ");\n"; + OS << " break;\n"; + } + OS << " }\n"; + } + + // Emit information about the dwarf register numbers. + for (unsigned j = 0; j < 2; ++j) { + OS << " switch ("; + if (j == 0) + OS << "DwarfFlavour"; + else + OS << "EHFlavour"; + OS << ") {\n" + << " default:\n" + << " llvm_unreachable(\"Unknown DWARF flavour\");\n"; + + for (unsigned i = 0, e = maxLength; i != e; ++i) { + OS << " case " << i << ":\n"; + OS << " "; + if (!isCtor) + OS << "RI->"; + std::string Tmp; + raw_string_ostream(Tmp) << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i + << "L2Dwarf"; + OS << "mapLLVMRegsToDwarfRegs(" << Tmp << ", " << Tmp << "Size, "; + if (j == 0) + OS << "false"; + else + OS << "true"; + OS << ");\n"; + OS << " break;\n"; + } + OS << " }\n"; + } +} + +// Print a BitVector as a sequence of hex numbers using a little-endian mapping. +// Width is the number of bits per hex number. +static void printBitVectorAsHex(raw_ostream &OS, + const BitVector &Bits, + unsigned Width) { + assert(Width <= 32 && "Width too large"); + unsigned Digits = (Width + 3) / 4; + for (unsigned i = 0, e = Bits.size(); i < e; i += Width) { + unsigned Value = 0; + for (unsigned j = 0; j != Width && i + j != e; ++j) + Value |= Bits.test(i + j) << j; + OS << format("0x%0*x, ", Digits, Value); + } +} + +// Helper to emit a set of bits into a constant byte array. +class BitVectorEmitter { + BitVector Values; +public: + void add(unsigned v) { + if (v >= Values.size()) + Values.resize(((v/8)+1)*8); // Round up to the next byte. + Values[v] = true; + } + + void print(raw_ostream &OS) { + printBitVectorAsHex(OS, Values, 8); + } +}; + +static void printRegister(raw_ostream &OS, const CodeGenRegister *Reg) { + OS << getQualifiedName(Reg->TheDef); +} + +static void printSimpleValueType(raw_ostream &OS, MVT::SimpleValueType VT) { + OS << getEnumName(VT); +} + +// +// runMCDesc - Print out MC register descriptions. +// +void +RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, + CodeGenRegBank &RegBank) { + EmitSourceFileHeader("MC Register Information", OS); + + OS << "\n#ifdef GET_REGINFO_MC_DESC\n"; + OS << "#undef GET_REGINFO_MC_DESC\n"; + + const std::vector<CodeGenRegister*> &Regs = RegBank.getRegisters(); + std::map<const CodeGenRegister*, CodeGenRegister::Set> Overlaps; + RegBank.computeOverlaps(Overlaps); + + // The lists of sub-registers, super-registers, and overlaps all go in the + // same array. That allows us to share suffixes. + typedef std::vector<const CodeGenRegister*> RegVec; + SmallVector<RegVec, 4> SubRegLists(Regs.size()); + SmallVector<RegVec, 4> OverlapLists(Regs.size()); + SequenceToOffsetTable<RegVec, CodeGenRegister::Less> RegSeqs; + + // Precompute register lists for the SequenceToOffsetTable. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister *Reg = Regs[i]; + + // Compute the ordered sub-register list. + SetVector<const CodeGenRegister*> SR; + Reg->addSubRegsPreOrder(SR, RegBank); + RegVec &SubRegList = SubRegLists[i]; + SubRegList.assign(SR.begin(), SR.end()); + RegSeqs.add(SubRegList); + + // Super-registers are already computed. + const RegVec &SuperRegList = Reg->getSuperRegs(); + RegSeqs.add(SuperRegList); + + // The list of overlaps doesn't need to have any particular order, except + // Reg itself must be the first element. Pick an ordering that has one of + // the other lists as a suffix. + RegVec &OverlapList = OverlapLists[i]; + const RegVec &Suffix = SubRegList.size() > SuperRegList.size() ? + SubRegList : SuperRegList; + CodeGenRegister::Set Omit(Suffix.begin(), Suffix.end()); + + // First element is Reg itself. + OverlapList.push_back(Reg); + Omit.insert(Reg); + + // Any elements not in Suffix. + const CodeGenRegister::Set &OSet = Overlaps[Reg]; + std::set_difference(OSet.begin(), OSet.end(), + Omit.begin(), Omit.end(), + std::back_inserter(OverlapList), + CodeGenRegister::Less()); + + // Finally, Suffix itself. + OverlapList.insert(OverlapList.end(), Suffix.begin(), Suffix.end()); + RegSeqs.add(OverlapList); + } + + // Compute the final layout of the sequence table. + RegSeqs.layout(); + + OS << "namespace llvm {\n\n"; + + const std::string &TargetName = Target.getName(); + + // Emit the shared table of register lists. + OS << "extern const uint16_t " << TargetName << "RegLists[] = {\n"; + RegSeqs.emit(OS, printRegister); + OS << "};\n\n"; + + OS << "extern const MCRegisterDesc " << TargetName + << "RegDesc[] = { // Descriptors\n"; + OS << " { \"NOREG\", 0, 0, 0 },\n"; + + // Emit the register descriptors now. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister *Reg = Regs[i]; + OS << " { \"" << Reg->getName() << "\", " + << RegSeqs.get(OverlapLists[i]) << ", " + << RegSeqs.get(SubRegLists[i]) << ", " + << RegSeqs.get(Reg->getSuperRegs()) << " },\n"; + } + OS << "};\n\n"; // End of register descriptors... + + ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses(); + + // Loop over all of the register classes... emitting each one. + OS << "namespace { // Register classes...\n"; + + // Emit the register enum value arrays for each RegisterClass + for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { + const CodeGenRegisterClass &RC = *RegisterClasses[rc]; + ArrayRef<Record*> Order = RC.getOrder(); + + // Give the register class a legal C name if it's anonymous. + std::string Name = RC.getName(); + + // Emit the register list now. + OS << " // " << Name << " Register Class...\n" + << " const uint16_t " << Name + << "[] = {\n "; + for (unsigned i = 0, e = Order.size(); i != e; ++i) { + Record *Reg = Order[i]; + OS << getQualifiedName(Reg) << ", "; + } + OS << "\n };\n\n"; + + OS << " // " << Name << " Bit set.\n" + << " const uint8_t " << Name + << "Bits[] = {\n "; + BitVectorEmitter BVE; + for (unsigned i = 0, e = Order.size(); i != e; ++i) { + Record *Reg = Order[i]; + BVE.add(Target.getRegBank().getReg(Reg)->EnumValue); + } + BVE.print(OS); + OS << "\n };\n\n"; + + } + OS << "}\n\n"; + + OS << "extern const MCRegisterClass " << TargetName + << "MCRegisterClasses[] = {\n"; + + for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { + const CodeGenRegisterClass &RC = *RegisterClasses[rc]; + + // Asserts to make sure values will fit in table assuming types from + // MCRegisterInfo.h + assert((RC.SpillSize/8) <= 0xffff && "SpillSize too large."); + assert((RC.SpillAlignment/8) <= 0xffff && "SpillAlignment too large."); + assert(RC.CopyCost >= -128 && RC.CopyCost <= 127 && "Copy cost too large."); + + OS << " { " << '\"' << RC.getName() << "\", " + << RC.getName() << ", " << RC.getName() << "Bits, " + << RC.getOrder().size() << ", sizeof(" << RC.getName() << "Bits), " + << RC.getQualifiedName() + "RegClassID" << ", " + << RC.SpillSize/8 << ", " + << RC.SpillAlignment/8 << ", " + << RC.CopyCost << ", " + << RC.Allocatable << " },\n"; + } + + OS << "};\n\n"; + + // Emit the data table for getSubReg(). + ArrayRef<CodeGenSubRegIndex*> SubRegIndices = RegBank.getSubRegIndices(); + if (SubRegIndices.size()) { + OS << "const uint16_t " << TargetName << "SubRegTable[][" + << SubRegIndices.size() << "] = {\n"; + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister::SubRegMap &SRM = Regs[i]->getSubRegs(); + OS << " /* " << Regs[i]->TheDef->getName() << " */\n"; + if (SRM.empty()) { + OS << " {0},\n"; + continue; + } + OS << " {"; + for (unsigned j = 0, je = SubRegIndices.size(); j != je; ++j) { + // FIXME: We really should keep this to 80 columns... + CodeGenRegister::SubRegMap::const_iterator SubReg = + SRM.find(SubRegIndices[j]); + if (SubReg != SRM.end()) + OS << getQualifiedName(SubReg->second->TheDef); + else + OS << "0"; + if (j != je - 1) + OS << ", "; + } + OS << "}" << (i != e ? "," : "") << "\n"; + } + OS << "};\n\n"; + OS << "const uint16_t *get" << TargetName + << "SubRegTable() {\n return (const uint16_t *)" << TargetName + << "SubRegTable;\n}\n\n"; + } + + EmitRegMappingTables(OS, Regs, false); + + // MCRegisterInfo initialization routine. + OS << "static inline void Init" << TargetName + << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, " + << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0) {\n"; + OS << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, " + << Regs.size()+1 << ", RA, " << TargetName << "MCRegisterClasses, " + << RegisterClasses.size() << ", " << TargetName << "RegLists, "; + if (SubRegIndices.size() != 0) + OS << "(uint16_t*)" << TargetName << "SubRegTable, " + << SubRegIndices.size() << ");\n\n"; + else + OS << "NULL, 0);\n\n"; + + EmitRegMapping(OS, Regs, false); + + OS << "}\n\n"; + + OS << "} // End llvm namespace \n"; + OS << "#endif // GET_REGINFO_MC_DESC\n\n"; +} + +void +RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, + CodeGenRegBank &RegBank) { + EmitSourceFileHeader("Register Information Header Fragment", OS); + + OS << "\n#ifdef GET_REGINFO_HEADER\n"; + OS << "#undef GET_REGINFO_HEADER\n"; + + const std::string &TargetName = Target.getName(); + std::string ClassName = TargetName + "GenRegisterInfo"; + + OS << "#include \"llvm/Target/TargetRegisterInfo.h\"\n\n"; + + OS << "namespace llvm {\n\n"; + + OS << "struct " << ClassName << " : public TargetRegisterInfo {\n" + << " explicit " << ClassName + << "(unsigned RA, unsigned D = 0, unsigned E = 0);\n" + << " virtual bool needsStackRealignment(const MachineFunction &) const\n" + << " { return false; }\n" + << " unsigned composeSubRegIndices(unsigned, unsigned) const;\n" + << " const TargetRegisterClass *" + "getSubClassWithSubReg(const TargetRegisterClass*, unsigned) const;\n" + << " const TargetRegisterClass *getMatchingSuperRegClass(" + "const TargetRegisterClass*, const TargetRegisterClass*, " + "unsigned) const;\n" + << " const RegClassWeight &getRegClassWeight(" + << "const TargetRegisterClass *RC) const;\n" + << " unsigned getNumRegPressureSets() const;\n" + << " unsigned getRegPressureSetLimit(unsigned Idx) const;\n" + << " const int *getRegClassPressureSets(" + << "const TargetRegisterClass *RC) const;\n" + << "};\n\n"; + + ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses(); + + if (!RegisterClasses.empty()) { + OS << "namespace " << RegisterClasses[0]->Namespace + << " { // Register classes\n"; + + for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { + const CodeGenRegisterClass &RC = *RegisterClasses[i]; + const std::string &Name = RC.getName(); + + // Output the extern for the instance. + OS << " extern const TargetRegisterClass " << Name << "RegClass;\n"; + // Output the extern for the pointer to the instance (should remove). + OS << " static const TargetRegisterClass * const " << Name + << "RegisterClass = &" << Name << "RegClass;\n"; + } + OS << "} // end of namespace " << TargetName << "\n\n"; + } + OS << "} // End llvm namespace \n"; + OS << "#endif // GET_REGINFO_HEADER\n\n"; +} + +// +// runTargetDesc - Output the target register and register file descriptions. +// +void +RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, + CodeGenRegBank &RegBank){ + EmitSourceFileHeader("Target Register and Register Classes Information", OS); + + OS << "\n#ifdef GET_REGINFO_TARGET_DESC\n"; + OS << "#undef GET_REGINFO_TARGET_DESC\n"; + + OS << "namespace llvm {\n\n"; + + // Get access to MCRegisterClass data. + OS << "extern const MCRegisterClass " << Target.getName() + << "MCRegisterClasses[];\n"; + + // Start out by emitting each of the register classes. + ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses(); + + // Collect all registers belonging to any allocatable class. + std::set<Record*> AllocatableRegs; + + // Collect allocatable registers. + for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { + const CodeGenRegisterClass &RC = *RegisterClasses[rc]; + ArrayRef<Record*> Order = RC.getOrder(); + + if (RC.Allocatable) + AllocatableRegs.insert(Order.begin(), Order.end()); + } + + // Build a shared array of value types. + SequenceToOffsetTable<std::vector<MVT::SimpleValueType> > VTSeqs; + for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) + VTSeqs.add(RegisterClasses[rc]->VTs); + VTSeqs.layout(); + OS << "\nstatic const MVT::SimpleValueType VTLists[] = {\n"; + VTSeqs.emit(OS, printSimpleValueType, "MVT::Other"); + OS << "};\n"; + + // Now that all of the structs have been emitted, emit the instances. + if (!RegisterClasses.empty()) { + std::map<unsigned, std::set<unsigned> > SuperRegClassMap; + + OS << "\nstatic const TargetRegisterClass *const " + << "NullRegClasses[] = { NULL };\n\n"; + + unsigned NumSubRegIndices = RegBank.getSubRegIndices().size(); + + if (NumSubRegIndices) { + // Compute the super-register classes for each RegisterClass + for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { + const CodeGenRegisterClass &RC = *RegisterClasses[rc]; + for (DenseMap<Record*,Record*>::const_iterator + i = RC.SubRegClasses.begin(), + e = RC.SubRegClasses.end(); i != e; ++i) { + // Find the register class number of i->second for SuperRegClassMap. + const CodeGenRegisterClass *RC2 = RegBank.getRegClass(i->second); + assert(RC2 && "Invalid register class in SubRegClasses"); + SuperRegClassMap[RC2->EnumValue].insert(rc); + } + } + + // Emit the super-register classes for each RegisterClass + for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { + const CodeGenRegisterClass &RC = *RegisterClasses[rc]; + + // Give the register class a legal C name if it's anonymous. + std::string Name = RC.getName(); + + OS << "// " << Name + << " Super-register Classes...\n" + << "static const TargetRegisterClass *const " + << Name << "SuperRegClasses[] = {\n "; + + bool Empty = true; + std::map<unsigned, std::set<unsigned> >::iterator I = + SuperRegClassMap.find(rc); + if (I != SuperRegClassMap.end()) { + for (std::set<unsigned>::iterator II = I->second.begin(), + EE = I->second.end(); II != EE; ++II) { + const CodeGenRegisterClass &RC2 = *RegisterClasses[*II]; + if (!Empty) + OS << ", "; + OS << "&" << RC2.getQualifiedName() << "RegClass"; + Empty = false; + } + } + + OS << (!Empty ? ", " : "") << "NULL"; + OS << "\n};\n\n"; + } + } + + // Emit the sub-classes array for each RegisterClass + for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { + const CodeGenRegisterClass &RC = *RegisterClasses[rc]; + + // Give the register class a legal C name if it's anonymous. + std::string Name = RC.getName(); + + OS << "static const uint32_t " << Name << "SubclassMask[] = {\n "; + printBitVectorAsHex(OS, RC.getSubClasses(), 32); + OS << "\n};\n\n"; + } + + // Emit NULL terminated super-class lists. + for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { + const CodeGenRegisterClass &RC = *RegisterClasses[rc]; + ArrayRef<CodeGenRegisterClass*> Supers = RC.getSuperClasses(); + + // Skip classes without supers. We can reuse NullRegClasses. + if (Supers.empty()) + continue; + + OS << "static const TargetRegisterClass *const " + << RC.getName() << "Superclasses[] = {\n"; + for (unsigned i = 0; i != Supers.size(); ++i) + OS << " &" << Supers[i]->getQualifiedName() << "RegClass,\n"; + OS << " NULL\n};\n\n"; + } + + // Emit methods. + for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { + const CodeGenRegisterClass &RC = *RegisterClasses[i]; + if (!RC.AltOrderSelect.empty()) { + OS << "\nstatic inline unsigned " << RC.getName() + << "AltOrderSelect(const MachineFunction &MF) {" + << RC.AltOrderSelect << "}\n\n" + << "static ArrayRef<uint16_t> " << RC.getName() + << "GetRawAllocationOrder(const MachineFunction &MF) {\n"; + for (unsigned oi = 1 , oe = RC.getNumOrders(); oi != oe; ++oi) { + ArrayRef<Record*> Elems = RC.getOrder(oi); + if (!Elems.empty()) { + OS << " static const uint16_t AltOrder" << oi << "[] = {"; + for (unsigned elem = 0; elem != Elems.size(); ++elem) + OS << (elem ? ", " : " ") << getQualifiedName(Elems[elem]); + OS << " };\n"; + } + } + OS << " const MCRegisterClass &MCR = " << Target.getName() + << "MCRegisterClasses[" << RC.getQualifiedName() + "RegClassID];\n" + << " const ArrayRef<uint16_t> Order[] = {\n" + << " makeArrayRef(MCR.begin(), MCR.getNumRegs()"; + for (unsigned oi = 1, oe = RC.getNumOrders(); oi != oe; ++oi) + if (RC.getOrder(oi).empty()) + OS << "),\n ArrayRef<uint16_t>("; + else + OS << "),\n makeArrayRef(AltOrder" << oi; + OS << ")\n };\n const unsigned Select = " << RC.getName() + << "AltOrderSelect(MF);\n assert(Select < " << RC.getNumOrders() + << ");\n return Order[Select];\n}\n"; + } + } + + // Now emit the actual value-initialized register class instances. + OS << "namespace " << RegisterClasses[0]->Namespace + << " { // Register class instances\n"; + + for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { + const CodeGenRegisterClass &RC = *RegisterClasses[i]; + OS << " extern const TargetRegisterClass " + << RegisterClasses[i]->getName() << "RegClass = {\n " + << '&' << Target.getName() << "MCRegisterClasses[" << RC.getName() + << "RegClassID],\n " + << "VTLists + " << VTSeqs.get(RC.VTs) << ",\n " + << RC.getName() << "SubclassMask,\n "; + if (RC.getSuperClasses().empty()) + OS << "NullRegClasses,\n "; + else + OS << RC.getName() << "Superclasses,\n "; + OS << (NumSubRegIndices ? RC.getName() + "Super" : std::string("Null")) + << "RegClasses,\n "; + if (RC.AltOrderSelect.empty()) + OS << "0\n"; + else + OS << RC.getName() << "GetRawAllocationOrder\n"; + OS << " };\n\n"; + } + + OS << "}\n"; + } + + OS << "\nnamespace {\n"; + OS << " const TargetRegisterClass* const RegisterClasses[] = {\n"; + for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) + OS << " &" << RegisterClasses[i]->getQualifiedName() + << "RegClass,\n"; + OS << " };\n"; + OS << "}\n"; // End of anonymous namespace... + + // Emit extra information about registers. + const std::string &TargetName = Target.getName(); + OS << "\nstatic const TargetRegisterInfoDesc " + << TargetName << "RegInfoDesc[] = { // Extra Descriptors\n"; + OS << " { 0, 0 },\n"; + + const std::vector<CodeGenRegister*> &Regs = RegBank.getRegisters(); + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister &Reg = *Regs[i]; + OS << " { "; + OS << Reg.CostPerUse << ", " + << int(AllocatableRegs.count(Reg.TheDef)) << " },\n"; + } + OS << "};\n"; // End of register descriptors... + + + // Calculate the mapping of subregister+index pairs to physical registers. + // This will also create further anonymous indices. + unsigned NamedIndices = RegBank.getNumNamedIndices(); + + // Emit SubRegIndex names, skipping 0 + ArrayRef<CodeGenSubRegIndex*> SubRegIndices = RegBank.getSubRegIndices(); + OS << "\nstatic const char *const " << TargetName + << "SubRegIndexTable[] = { \""; + for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { + OS << SubRegIndices[i]->getName(); + if (i+1 != e) + OS << "\", \""; + } + OS << "\" };\n\n"; + + // Emit names of the anonymous subreg indices. + if (SubRegIndices.size() > NamedIndices) { + OS << " enum {"; + for (unsigned i = NamedIndices, e = SubRegIndices.size(); i != e; ++i) { + OS << "\n " << SubRegIndices[i]->getName() << " = " << i+1; + if (i+1 != e) + OS << ','; + } + OS << "\n };\n\n"; + } + OS << "\n"; + + std::string ClassName = Target.getName() + "GenRegisterInfo"; + + // Emit composeSubRegIndices + OS << "unsigned " << ClassName + << "::composeSubRegIndices(unsigned IdxA, unsigned IdxB) const {\n" + << " switch (IdxA) {\n" + << " default:\n return IdxB;\n"; + for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { + bool Open = false; + for (unsigned j = 0; j != e; ++j) { + if (CodeGenSubRegIndex *Comp = + SubRegIndices[i]->compose(SubRegIndices[j])) { + if (!Open) { + OS << " case " << SubRegIndices[i]->getQualifiedName() + << ": switch(IdxB) {\n default: return IdxB;\n"; + Open = true; + } + OS << " case " << SubRegIndices[j]->getQualifiedName() + << ": return " << Comp->getQualifiedName() << ";\n"; + } + } + if (Open) + OS << " }\n"; + } + OS << " }\n}\n\n"; + + // Emit getSubClassWithSubReg. + OS << "const TargetRegisterClass *" << ClassName + << "::getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx)" + " const {\n"; + if (SubRegIndices.empty()) { + OS << " assert(Idx == 0 && \"Target has no sub-registers\");\n" + << " return RC;\n"; + } else { + // Use the smallest type that can hold a regclass ID with room for a + // sentinel. + if (RegisterClasses.size() < UINT8_MAX) + OS << " static const uint8_t Table["; + else if (RegisterClasses.size() < UINT16_MAX) + OS << " static const uint16_t Table["; + else + throw "Too many register classes."; + OS << RegisterClasses.size() << "][" << SubRegIndices.size() << "] = {\n"; + for (unsigned rci = 0, rce = RegisterClasses.size(); rci != rce; ++rci) { + const CodeGenRegisterClass &RC = *RegisterClasses[rci]; + OS << " {\t// " << RC.getName() << "\n"; + for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { + CodeGenSubRegIndex *Idx = SubRegIndices[sri]; + if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(Idx)) + OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx->getName() + << " -> " << SRC->getName() << "\n"; + else + OS << " 0,\t// " << Idx->getName() << "\n"; + } + OS << " },\n"; + } + OS << " };\n assert(RC && \"Missing regclass\");\n" + << " if (!Idx) return RC;\n --Idx;\n" + << " assert(Idx < " << SubRegIndices.size() << " && \"Bad subreg\");\n" + << " unsigned TV = Table[RC->getID()][Idx];\n" + << " return TV ? getRegClass(TV - 1) : 0;\n"; + } + OS << "}\n\n"; + + // Emit getMatchingSuperRegClass. + OS << "const TargetRegisterClass *" << ClassName + << "::getMatchingSuperRegClass(const TargetRegisterClass *A," + " const TargetRegisterClass *B, unsigned Idx) const {\n"; + if (SubRegIndices.empty()) { + OS << " llvm_unreachable(\"Target has no sub-registers\");\n"; + } else { + // We need to find the largest sub-class of A such that every register has + // an Idx sub-register in B. Map (B, Idx) to a bit-vector of + // super-register classes that map into B. Then compute the largest common + // sub-class with A by taking advantage of the register class ordering, + // like getCommonSubClass(). + + // Bitvector table is NumRCs x NumSubIndexes x BVWords, where BVWords is + // the number of 32-bit words required to represent all register classes. + const unsigned BVWords = (RegisterClasses.size()+31)/32; + BitVector BV(RegisterClasses.size()); + + OS << " static const uint32_t Table[" << RegisterClasses.size() + << "][" << SubRegIndices.size() << "][" << BVWords << "] = {\n"; + for (unsigned rci = 0, rce = RegisterClasses.size(); rci != rce; ++rci) { + const CodeGenRegisterClass &RC = *RegisterClasses[rci]; + OS << " {\t// " << RC.getName() << "\n"; + for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { + CodeGenSubRegIndex *Idx = SubRegIndices[sri]; + BV.reset(); + RC.getSuperRegClasses(Idx, BV); + OS << " { "; + printBitVectorAsHex(OS, BV, 32); + OS << "},\t// " << Idx->getName() << '\n'; + } + OS << " },\n"; + } + OS << " };\n assert(A && B && \"Missing regclass\");\n" + << " --Idx;\n" + << " assert(Idx < " << SubRegIndices.size() << " && \"Bad subreg\");\n" + << " const uint32_t *TV = Table[B->getID()][Idx];\n" + << " const uint32_t *SC = A->getSubClassMask();\n" + << " for (unsigned i = 0; i != " << BVWords << "; ++i)\n" + << " if (unsigned Common = TV[i] & SC[i])\n" + << " return getRegClass(32*i + CountTrailingZeros_32(Common));\n" + << " return 0;\n"; + } + OS << "}\n\n"; + + EmitRegUnitPressure(OS, RegBank, ClassName); + + // Emit the constructor of the class... + OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n"; + OS << "extern const uint16_t " << TargetName << "RegLists[];\n"; + if (SubRegIndices.size() != 0) + OS << "extern const uint16_t *get" << TargetName + << "SubRegTable();\n"; + + EmitRegMappingTables(OS, Regs, true); + + OS << ClassName << "::\n" << ClassName + << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour)\n" + << " : TargetRegisterInfo(" << TargetName << "RegInfoDesc" + << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n" + << " " << TargetName << "SubRegIndexTable) {\n" + << " InitMCRegisterInfo(" << TargetName << "RegDesc, " + << Regs.size()+1 << ", RA,\n " << TargetName + << "MCRegisterClasses, " << RegisterClasses.size() << ",\n" + << " " << TargetName << "RegLists,\n" + << " "; + if (SubRegIndices.size() != 0) + OS << "get" << TargetName << "SubRegTable(), " + << SubRegIndices.size() << ");\n\n"; + else + OS << "NULL, 0);\n\n"; + + EmitRegMapping(OS, Regs, true); + + OS << "}\n\n"; + + + // Emit CalleeSavedRegs information. + std::vector<Record*> CSRSets = + Records.getAllDerivedDefinitions("CalleeSavedRegs"); + for (unsigned i = 0, e = CSRSets.size(); i != e; ++i) { + Record *CSRSet = CSRSets[i]; + const SetTheory::RecVec *Regs = RegBank.getSets().expand(CSRSet); + assert(Regs && "Cannot expand CalleeSavedRegs instance"); + + // Emit the *_SaveList list of callee-saved registers. + OS << "static const uint16_t " << CSRSet->getName() + << "_SaveList[] = { "; + for (unsigned r = 0, re = Regs->size(); r != re; ++r) + OS << getQualifiedName((*Regs)[r]) << ", "; + OS << "0 };\n"; + + // Emit the *_RegMask bit mask of call-preserved registers. + OS << "static const uint32_t " << CSRSet->getName() + << "_RegMask[] = { "; + printBitVectorAsHex(OS, RegBank.computeCoveredRegisters(*Regs), 32); + OS << "};\n"; + } + OS << "\n\n"; + + OS << "} // End llvm namespace \n"; + OS << "#endif // GET_REGINFO_TARGET_DESC\n\n"; +} + +void RegisterInfoEmitter::run(raw_ostream &OS) { + CodeGenTarget Target(Records); + CodeGenRegBank &RegBank = Target.getRegBank(); + RegBank.computeDerivedInfo(); + + runEnums(OS, Target, RegBank); + runMCDesc(OS, Target, RegBank); + runTargetHeader(OS, Target, RegBank); + runTargetDesc(OS, Target, RegBank); +} diff --git a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.h b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.h new file mode 100644 index 0000000..ee9903c --- /dev/null +++ b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.h @@ -0,0 +1,64 @@ +//===- RegisterInfoEmitter.h - Generate a Register File Desc. ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend is responsible for emitting a description of a target +// register file for a code generator. It uses instances of the Register, +// RegisterAliases, and RegisterClass classes to gather this information. +// +//===----------------------------------------------------------------------===// + +#ifndef REGISTER_INFO_EMITTER_H +#define REGISTER_INFO_EMITTER_H + +#include "llvm/TableGen/TableGenBackend.h" +#include <vector> + +namespace llvm { + +class CodeGenRegBank; +struct CodeGenRegister; +class CodeGenTarget; + +class RegisterInfoEmitter : public TableGenBackend { + RecordKeeper &Records; +public: + RegisterInfoEmitter(RecordKeeper &R) : Records(R) {} + + // runEnums - Print out enum values for all of the registers. + void runEnums(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank); + + // runMCDesc - Print out MC register descriptions. + void runMCDesc(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank); + + // runTargetHeader - Emit a header fragment for the register info emitter. + void runTargetHeader(raw_ostream &o, CodeGenTarget &Target, + CodeGenRegBank &Bank); + + // runTargetDesc - Output the target register and register file descriptions. + void runTargetDesc(raw_ostream &o, CodeGenTarget &Target, + CodeGenRegBank &Bank); + + // run - Output the register file description. + void run(raw_ostream &o); + +private: + void EmitRegMapping(raw_ostream &o, + const std::vector<CodeGenRegister*> &Regs, bool isCtor); + void EmitRegMappingTables(raw_ostream &o, + const std::vector<CodeGenRegister*> &Regs, + bool isCtor); + void EmitRegClasses(raw_ostream &OS, CodeGenTarget &Target); + + void EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, + const std::string &ClassName); +}; + +} // End llvm namespace + +#endif diff --git a/contrib/llvm/utils/TableGen/SequenceToOffsetTable.h b/contrib/llvm/utils/TableGen/SequenceToOffsetTable.h new file mode 100644 index 0000000..97c764e --- /dev/null +++ b/contrib/llvm/utils/TableGen/SequenceToOffsetTable.h @@ -0,0 +1,139 @@ +//===-- SequenceToOffsetTable.h - Compress similar sequences ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// SequenceToOffsetTable can be used to emit a number of null-terminated +// sequences as one big array. Use the same memory when a sequence is a suffix +// of another. +// +//===----------------------------------------------------------------------===// + +#ifndef TBLGEN_SEQUENCE_TO_OFFSET_TABLE_H +#define TBLGEN_SEQUENCE_TO_OFFSET_TABLE_H + +#include "llvm/Support/raw_ostream.h" +#include <functional> +#include <algorithm> +#include <vector> +#include <cassert> +#include <cctype> + +namespace llvm { + +/// SequenceToOffsetTable - Collect a number of terminated sequences of T. +/// Compute the layout of a table that contains all the sequences, possibly by +/// reusing entries. +/// +/// @param SeqT The sequence container. (vector or string). +/// @param Less A stable comparator for SeqT elements. +template<typename SeqT, typename Less = std::less<typename SeqT::value_type> > +class SequenceToOffsetTable { + typedef typename SeqT::value_type ElemT; + + // Define a comparator for SeqT that sorts a suffix immediately before a + // sequence with that suffix. + struct SeqLess : public std::binary_function<SeqT, SeqT, bool> { + Less L; + bool operator()(const SeqT &A, const SeqT &B) const { + return std::lexicographical_compare(A.rbegin(), A.rend(), + B.rbegin(), B.rend(), L); + } + }; + + // Keep sequences ordered according to SeqLess so suffixes are easy to find. + // Map each sequence to its offset in the table. + typedef std::map<SeqT, unsigned, SeqLess> SeqMap; + + // Sequences added so far, with suffixes removed. + SeqMap Seqs; + + // Entries in the final table, or 0 before layout was called. + unsigned Entries; + + // isSuffix - Returns true if A is a suffix of B. + static bool isSuffix(const SeqT &A, const SeqT &B) { + return A.size() <= B.size() && std::equal(A.rbegin(), A.rend(), B.rbegin()); + } + +public: + SequenceToOffsetTable() : Entries(0) {} + + /// add - Add a sequence to the table. + /// This must be called before layout(). + void add(const SeqT &Seq) { + assert(Entries == 0 && "Cannot call add() after layout()"); + typename SeqMap::iterator I = Seqs.lower_bound(Seq); + + // If SeqMap contains a sequence that has Seq as a suffix, I will be + // pointing to it. + if (I != Seqs.end() && isSuffix(Seq, I->first)) + return; + + I = Seqs.insert(I, std::make_pair(Seq, 0u)); + + // The entry before I may be a suffix of Seq that can now be erased. + if (I != Seqs.begin() && isSuffix((--I)->first, Seq)) + Seqs.erase(I); + } + + /// layout - Computes the final table layout. + void layout() { + assert(Entries == 0 && "Can only call layout() once"); + // Lay out the table in Seqs iteration order. + for (typename SeqMap::iterator I = Seqs.begin(), E = Seqs.end(); I != E; + ++I) { + I->second = Entries; + // Include space for a terminator. + Entries += I->first.size() + 1; + } + } + + /// get - Returns the offset of Seq in the final table. + unsigned get(const SeqT &Seq) const { + assert(Entries && "Call layout() before get()"); + typename SeqMap::const_iterator I = Seqs.lower_bound(Seq); + assert(I != Seqs.end() && isSuffix(Seq, I->first) && + "get() called with sequence that wasn't added first"); + return I->second + (I->first.size() - Seq.size()); + } + + /// emit - Print out the table as the body of an array initializer. + /// Use the Print function to print elements. + void emit(raw_ostream &OS, + void (*Print)(raw_ostream&, ElemT), + const char *Term = "0") const { + assert(Entries && "Call layout() before emit()"); + for (typename SeqMap::const_iterator I = Seqs.begin(), E = Seqs.end(); + I != E; ++I) { + OS << " /* " << I->second << " */ "; + for (typename SeqT::const_iterator SI = I->first.begin(), + SE = I->first.end(); SI != SE; ++SI) { + Print(OS, *SI); + OS << ", "; + } + OS << Term << ",\n"; + } + } +}; + +// Helper function for SequenceToOffsetTable<string>. +static inline void printChar(raw_ostream &OS, char C) { + unsigned char UC(C); + if (isalnum(UC) || ispunct(UC)) { + OS << '\''; + if (C == '\\' || C == '\'') + OS << '\\'; + OS << C << '\''; + } else { + OS << unsigned(UC); + } +} + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/utils/TableGen/SetTheory.cpp b/contrib/llvm/utils/TableGen/SetTheory.cpp new file mode 100644 index 0000000..0649fd1 --- /dev/null +++ b/contrib/llvm/utils/TableGen/SetTheory.cpp @@ -0,0 +1,299 @@ +//===- SetTheory.cpp - Generate ordered sets from DAG expressions ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SetTheory class that computes ordered sets of +// Records from DAG expressions. +// +//===----------------------------------------------------------------------===// + +#include "SetTheory.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" +#include "llvm/Support/Format.h" + +using namespace llvm; + +// Define the standard operators. +namespace { + +typedef SetTheory::RecSet RecSet; +typedef SetTheory::RecVec RecVec; + +// (add a, b, ...) Evaluate and union all arguments. +struct AddOp : public SetTheory::Operator { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) { + ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts); + } +}; + +// (sub Add, Sub, ...) Set difference. +struct SubOp : public SetTheory::Operator { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) { + if (Expr->arg_size() < 2) + throw "Set difference needs at least two arguments: " + + Expr->getAsString(); + RecSet Add, Sub; + ST.evaluate(*Expr->arg_begin(), Add); + ST.evaluate(Expr->arg_begin() + 1, Expr->arg_end(), Sub); + for (RecSet::iterator I = Add.begin(), E = Add.end(); I != E; ++I) + if (!Sub.count(*I)) + Elts.insert(*I); + } +}; + +// (and S1, S2) Set intersection. +struct AndOp : public SetTheory::Operator { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) { + if (Expr->arg_size() != 2) + throw "Set intersection requires two arguments: " + Expr->getAsString(); + RecSet S1, S2; + ST.evaluate(Expr->arg_begin()[0], S1); + ST.evaluate(Expr->arg_begin()[1], S2); + for (RecSet::iterator I = S1.begin(), E = S1.end(); I != E; ++I) + if (S2.count(*I)) + Elts.insert(*I); + } +}; + +// SetIntBinOp - Abstract base class for (Op S, N) operators. +struct SetIntBinOp : public SetTheory::Operator { + virtual void apply2(SetTheory &ST, DagInit *Expr, + RecSet &Set, int64_t N, + RecSet &Elts) =0; + + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) { + if (Expr->arg_size() != 2) + throw "Operator requires (Op Set, Int) arguments: " + Expr->getAsString(); + RecSet Set; + ST.evaluate(Expr->arg_begin()[0], Set); + IntInit *II = dynamic_cast<IntInit*>(Expr->arg_begin()[1]); + if (!II) + throw "Second argument must be an integer: " + Expr->getAsString(); + apply2(ST, Expr, Set, II->getValue(), Elts); + } +}; + +// (shl S, N) Shift left, remove the first N elements. +struct ShlOp : public SetIntBinOp { + void apply2(SetTheory &ST, DagInit *Expr, + RecSet &Set, int64_t N, + RecSet &Elts) { + if (N < 0) + throw "Positive shift required: " + Expr->getAsString(); + if (unsigned(N) < Set.size()) + Elts.insert(Set.begin() + N, Set.end()); + } +}; + +// (trunc S, N) Truncate after the first N elements. +struct TruncOp : public SetIntBinOp { + void apply2(SetTheory &ST, DagInit *Expr, + RecSet &Set, int64_t N, + RecSet &Elts) { + if (N < 0) + throw "Positive length required: " + Expr->getAsString(); + if (unsigned(N) > Set.size()) + N = Set.size(); + Elts.insert(Set.begin(), Set.begin() + N); + } +}; + +// Left/right rotation. +struct RotOp : public SetIntBinOp { + const bool Reverse; + + RotOp(bool Rev) : Reverse(Rev) {} + + void apply2(SetTheory &ST, DagInit *Expr, + RecSet &Set, int64_t N, + RecSet &Elts) { + if (Reverse) + N = -N; + // N > 0 -> rotate left, N < 0 -> rotate right. + if (Set.empty()) + return; + if (N < 0) + N = Set.size() - (-N % Set.size()); + else + N %= Set.size(); + Elts.insert(Set.begin() + N, Set.end()); + Elts.insert(Set.begin(), Set.begin() + N); + } +}; + +// (decimate S, N) Pick every N'th element of S. +struct DecimateOp : public SetIntBinOp { + void apply2(SetTheory &ST, DagInit *Expr, + RecSet &Set, int64_t N, + RecSet &Elts) { + if (N <= 0) + throw "Positive stride required: " + Expr->getAsString(); + for (unsigned I = 0; I < Set.size(); I += N) + Elts.insert(Set[I]); + } +}; + +// (interleave S1, S2, ...) Interleave elements of the arguments. +struct InterleaveOp : public SetTheory::Operator { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) { + // Evaluate the arguments individually. + SmallVector<RecSet, 4> Args(Expr->getNumArgs()); + unsigned MaxSize = 0; + for (unsigned i = 0, e = Expr->getNumArgs(); i != e; ++i) { + ST.evaluate(Expr->getArg(i), Args[i]); + MaxSize = std::max(MaxSize, unsigned(Args[i].size())); + } + // Interleave arguments into Elts. + for (unsigned n = 0; n != MaxSize; ++n) + for (unsigned i = 0, e = Expr->getNumArgs(); i != e; ++i) + if (n < Args[i].size()) + Elts.insert(Args[i][n]); + } +}; + +// (sequence "Format", From, To) Generate a sequence of records by name. +struct SequenceOp : public SetTheory::Operator { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) { + if (Expr->arg_size() != 3) + throw "Bad args to (sequence \"Format\", From, To): " + + Expr->getAsString(); + std::string Format; + if (StringInit *SI = dynamic_cast<StringInit*>(Expr->arg_begin()[0])) + Format = SI->getValue(); + else + throw "Format must be a string: " + Expr->getAsString(); + + int64_t From, To; + if (IntInit *II = dynamic_cast<IntInit*>(Expr->arg_begin()[1])) + From = II->getValue(); + else + throw "From must be an integer: " + Expr->getAsString(); + if (From < 0 || From >= (1 << 30)) + throw "From out of range"; + + if (IntInit *II = dynamic_cast<IntInit*>(Expr->arg_begin()[2])) + To = II->getValue(); + else + throw "From must be an integer: " + Expr->getAsString(); + if (To < 0 || To >= (1 << 30)) + throw "To out of range"; + + RecordKeeper &Records = + dynamic_cast<DefInit&>(*Expr->getOperator()).getDef()->getRecords(); + + int Step = From <= To ? 1 : -1; + for (To += Step; From != To; From += Step) { + std::string Name; + raw_string_ostream OS(Name); + OS << format(Format.c_str(), unsigned(From)); + Record *Rec = Records.getDef(OS.str()); + if (!Rec) + throw "No def named '" + Name + "': " + Expr->getAsString(); + // Try to reevaluate Rec in case it is a set. + if (const RecVec *Result = ST.expand(Rec)) + Elts.insert(Result->begin(), Result->end()); + else + Elts.insert(Rec); + } + } +}; + +// Expand a Def into a set by evaluating one of its fields. +struct FieldExpander : public SetTheory::Expander { + StringRef FieldName; + + FieldExpander(StringRef fn) : FieldName(fn) {} + + void expand(SetTheory &ST, Record *Def, RecSet &Elts) { + ST.evaluate(Def->getValueInit(FieldName), Elts); + } +}; +} // end anonymous namespace + +void SetTheory::Operator::anchor() { } + +void SetTheory::Expander::anchor() { } + +SetTheory::SetTheory() { + addOperator("add", new AddOp); + addOperator("sub", new SubOp); + addOperator("and", new AndOp); + addOperator("shl", new ShlOp); + addOperator("trunc", new TruncOp); + addOperator("rotl", new RotOp(false)); + addOperator("rotr", new RotOp(true)); + addOperator("decimate", new DecimateOp); + addOperator("interleave", new InterleaveOp); + addOperator("sequence", new SequenceOp); +} + +void SetTheory::addOperator(StringRef Name, Operator *Op) { + Operators[Name] = Op; +} + +void SetTheory::addExpander(StringRef ClassName, Expander *E) { + Expanders[ClassName] = E; +} + +void SetTheory::addFieldExpander(StringRef ClassName, StringRef FieldName) { + addExpander(ClassName, new FieldExpander(FieldName)); +} + +void SetTheory::evaluate(Init *Expr, RecSet &Elts) { + // A def in a list can be a just an element, or it may expand. + if (DefInit *Def = dynamic_cast<DefInit*>(Expr)) { + if (const RecVec *Result = expand(Def->getDef())) + return Elts.insert(Result->begin(), Result->end()); + Elts.insert(Def->getDef()); + return; + } + + // Lists simply expand. + if (ListInit *LI = dynamic_cast<ListInit*>(Expr)) + return evaluate(LI->begin(), LI->end(), Elts); + + // Anything else must be a DAG. + DagInit *DagExpr = dynamic_cast<DagInit*>(Expr); + if (!DagExpr) + throw "Invalid set element: " + Expr->getAsString(); + DefInit *OpInit = dynamic_cast<DefInit*>(DagExpr->getOperator()); + if (!OpInit) + throw "Bad set expression: " + Expr->getAsString(); + Operator *Op = Operators.lookup(OpInit->getDef()->getName()); + if (!Op) + throw "Unknown set operator: " + Expr->getAsString(); + Op->apply(*this, DagExpr, Elts); +} + +const RecVec *SetTheory::expand(Record *Set) { + // Check existing entries for Set and return early. + ExpandMap::iterator I = Expansions.find(Set); + if (I != Expansions.end()) + return &I->second; + + // This is the first time we see Set. Find a suitable expander. + try { + const std::vector<Record*> &SC = Set->getSuperClasses(); + for (unsigned i = 0, e = SC.size(); i != e; ++i) + if (Expander *Exp = Expanders.lookup(SC[i]->getName())) { + // This breaks recursive definitions. + RecVec &EltVec = Expansions[Set]; + RecSet Elts; + Exp->expand(*this, Set, Elts); + EltVec.assign(Elts.begin(), Elts.end()); + return &EltVec; + } + } catch (const std::string &Error) { + throw TGError(Set->getLoc(), Error); + } + + // Set is not expandable. + return 0; +} + diff --git a/contrib/llvm/utils/TableGen/SetTheory.h b/contrib/llvm/utils/TableGen/SetTheory.h new file mode 100644 index 0000000..b394058 --- /dev/null +++ b/contrib/llvm/utils/TableGen/SetTheory.h @@ -0,0 +1,140 @@ +//===- SetTheory.h - Generate ordered sets from DAG expressions -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SetTheory class that computes ordered sets of +// Records from DAG expressions. Operators for standard set operations are +// predefined, and it is possible to add special purpose set operators as well. +// +// The user may define named sets as Records of predefined classes. Set +// expanders can be added to a SetTheory instance to teach it how to find the +// elements of such a named set. +// +// These are the predefined operators. The argument lists can be individual +// elements (defs), other sets (defs of expandable classes), lists, or DAG +// expressions that are evaluated recursively. +// +// - (add S1, S2 ...) Union sets. This is also how sets are created from element +// lists. +// +// - (sub S1, S2, ...) Set difference. Every element in S1 except for the +// elements in S2, ... +// +// - (and S1, S2) Set intersection. Every element in S1 that is also in S2. +// +// - (shl S, N) Shift left. Remove the first N elements from S. +// +// - (trunc S, N) Truncate. The first N elements of S. +// +// - (rotl S, N) Rotate left. Same as (add (shl S, N), (trunc S, N)). +// +// - (rotr S, N) Rotate right. +// +// - (decimate S, N) Decimate S by picking every N'th element, starting with +// the first one. For instance, (decimate S, 2) returns the even elements of +// S. +// +// - (sequence "Format", From, To) Generate a sequence of defs with printf. +// For instance, (sequence "R%u", 0, 3) -> [ R0, R1, R2, R3 ] +// +//===----------------------------------------------------------------------===// + +#ifndef SETTHEORY_H +#define SETTHEORY_H + +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/SetVector.h" +#include <map> +#include <vector> + +namespace llvm { + +class DagInit; +class Init; +class Record; +class RecordKeeper; + +class SetTheory { +public: + typedef std::vector<Record*> RecVec; + typedef SmallSetVector<Record*, 16> RecSet; + + /// Operator - A callback representing a DAG operator. + class Operator { + virtual void anchor(); + public: + virtual ~Operator() {} + + /// apply - Apply this operator to Expr's arguments and insert the result + /// in Elts. + virtual void apply(SetTheory&, DagInit *Expr, RecSet &Elts) =0; + }; + + /// Expander - A callback function that can transform a Record representing a + /// set into a fully expanded list of elements. Expanders provide a way for + /// users to define named sets that can be used in DAG expressions. + class Expander { + virtual void anchor(); + public: + virtual ~Expander() {} + + virtual void expand(SetTheory&, Record*, RecSet &Elts) =0; + }; + +private: + // Map set defs to their fully expanded contents. This serves as a memoization + // cache and it makes it possible to return const references on queries. + typedef std::map<Record*, RecVec> ExpandMap; + ExpandMap Expansions; + + // Known DAG operators by name. + StringMap<Operator*> Operators; + + // Typed expanders by class name. + StringMap<Expander*> Expanders; + +public: + /// Create a SetTheory instance with only the standard operators. + SetTheory(); + + /// addExpander - Add an expander for Records with the named super class. + void addExpander(StringRef ClassName, Expander*); + + /// addFieldExpander - Add an expander for ClassName that simply evaluates + /// FieldName in the Record to get the set elements. That is all that is + /// needed for a class like: + /// + /// class Set<dag d> { + /// dag Elts = d; + /// } + /// + void addFieldExpander(StringRef ClassName, StringRef FieldName); + + /// addOperator - Add a DAG operator. + void addOperator(StringRef Name, Operator*); + + /// evaluate - Evaluate Expr and append the resulting set to Elts. + void evaluate(Init *Expr, RecSet &Elts); + + /// evaluate - Evaluate a sequence of Inits and append to Elts. + template<typename Iter> + void evaluate(Iter begin, Iter end, RecSet &Elts) { + while (begin != end) + evaluate(*begin++, Elts); + } + + /// expand - Expand a record into a set of elements if possible. Return a + /// pointer to the expanded elements, or NULL if Set cannot be expanded + /// further. + const RecVec *expand(Record *Set); +}; + +} // end namespace llvm + +#endif + diff --git a/contrib/llvm/utils/TableGen/StringMatcher.cpp b/contrib/llvm/utils/TableGen/StringMatcher.cpp new file mode 100644 index 0000000..6aedcbf --- /dev/null +++ b/contrib/llvm/utils/TableGen/StringMatcher.cpp @@ -0,0 +1,149 @@ +//===- StringMatcher.cpp - Generate a matcher for input strings -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the StringMatcher class. +// +//===----------------------------------------------------------------------===// + +#include "StringMatcher.h" +#include "llvm/Support/raw_ostream.h" +#include <map> +using namespace llvm; + +/// FindFirstNonCommonLetter - Find the first character in the keys of the +/// string pairs that is not shared across the whole set of strings. All +/// strings are assumed to have the same length. +static unsigned +FindFirstNonCommonLetter(const std::vector<const + StringMatcher::StringPair*> &Matches) { + assert(!Matches.empty()); + for (unsigned i = 0, e = Matches[0]->first.size(); i != e; ++i) { + // Check to see if letter i is the same across the set. + char Letter = Matches[0]->first[i]; + + for (unsigned str = 0, e = Matches.size(); str != e; ++str) + if (Matches[str]->first[i] != Letter) + return i; + } + + return Matches[0]->first.size(); +} + +/// EmitStringMatcherForChar - Given a set of strings that are known to be the +/// same length and whose characters leading up to CharNo are the same, emit +/// code to verify that CharNo and later are the same. +/// +/// \return - True if control can leave the emitted code fragment. +bool StringMatcher:: +EmitStringMatcherForChar(const std::vector<const StringPair*> &Matches, + unsigned CharNo, unsigned IndentCount) const { + assert(!Matches.empty() && "Must have at least one string to match!"); + std::string Indent(IndentCount*2+4, ' '); + + // If we have verified that the entire string matches, we're done: output the + // matching code. + if (CharNo == Matches[0]->first.size()) { + assert(Matches.size() == 1 && "Had duplicate keys to match on"); + + // If the to-execute code has \n's in it, indent each subsequent line. + StringRef Code = Matches[0]->second; + + std::pair<StringRef, StringRef> Split = Code.split('\n'); + OS << Indent << Split.first << "\t // \"" << Matches[0]->first << "\"\n"; + + Code = Split.second; + while (!Code.empty()) { + Split = Code.split('\n'); + OS << Indent << Split.first << "\n"; + Code = Split.second; + } + return false; + } + + // Bucket the matches by the character we are comparing. + std::map<char, std::vector<const StringPair*> > MatchesByLetter; + + for (unsigned i = 0, e = Matches.size(); i != e; ++i) + MatchesByLetter[Matches[i]->first[CharNo]].push_back(Matches[i]); + + + // If we have exactly one bucket to match, see how many characters are common + // across the whole set and match all of them at once. + if (MatchesByLetter.size() == 1) { + unsigned FirstNonCommonLetter = FindFirstNonCommonLetter(Matches); + unsigned NumChars = FirstNonCommonLetter-CharNo; + + // Emit code to break out if the prefix doesn't match. + if (NumChars == 1) { + // Do the comparison with if (Str[1] != 'f') + // FIXME: Need to escape general characters. + OS << Indent << "if (" << StrVariableName << "[" << CharNo << "] != '" + << Matches[0]->first[CharNo] << "')\n"; + OS << Indent << " break;\n"; + } else { + // Do the comparison with if (Str.substr(1, 3) != "foo"). + // FIXME: Need to escape general strings. + OS << Indent << "if (" << StrVariableName << ".substr(" << CharNo << ", " + << NumChars << ") != \""; + OS << Matches[0]->first.substr(CharNo, NumChars) << "\")\n"; + OS << Indent << " break;\n"; + } + + return EmitStringMatcherForChar(Matches, FirstNonCommonLetter, IndentCount); + } + + // Otherwise, we have multiple possible things, emit a switch on the + // character. + OS << Indent << "switch (" << StrVariableName << "[" << CharNo << "]) {\n"; + OS << Indent << "default: break;\n"; + + for (std::map<char, std::vector<const StringPair*> >::iterator LI = + MatchesByLetter.begin(), E = MatchesByLetter.end(); LI != E; ++LI) { + // TODO: escape hard stuff (like \n) if we ever care about it. + OS << Indent << "case '" << LI->first << "':\t // " + << LI->second.size() << " string"; + if (LI->second.size() != 1) OS << 's'; + OS << " to match.\n"; + if (EmitStringMatcherForChar(LI->second, CharNo+1, IndentCount+1)) + OS << Indent << " break;\n"; + } + + OS << Indent << "}\n"; + return true; +} + + +/// Emit - Top level entry point. +/// +void StringMatcher::Emit(unsigned Indent) const { + // If nothing to match, just fall through. + if (Matches.empty()) return; + + // First level categorization: group strings by length. + std::map<unsigned, std::vector<const StringPair*> > MatchesByLength; + + for (unsigned i = 0, e = Matches.size(); i != e; ++i) + MatchesByLength[Matches[i].first.size()].push_back(&Matches[i]); + + // Output a switch statement on length and categorize the elements within each + // bin. + OS.indent(Indent*2+2) << "switch (" << StrVariableName << ".size()) {\n"; + OS.indent(Indent*2+2) << "default: break;\n"; + + for (std::map<unsigned, std::vector<const StringPair*> >::iterator LI = + MatchesByLength.begin(), E = MatchesByLength.end(); LI != E; ++LI) { + OS.indent(Indent*2+2) << "case " << LI->first << ":\t // " + << LI->second.size() + << " string" << (LI->second.size() == 1 ? "" : "s") << " to match.\n"; + if (EmitStringMatcherForChar(LI->second, 0, Indent)) + OS.indent(Indent*2+4) << "break;\n"; + } + + OS.indent(Indent*2+2) << "}\n"; +} diff --git a/contrib/llvm/utils/TableGen/StringMatcher.h b/contrib/llvm/utils/TableGen/StringMatcher.h new file mode 100644 index 0000000..1dadc76 --- /dev/null +++ b/contrib/llvm/utils/TableGen/StringMatcher.h @@ -0,0 +1,54 @@ +//===- StringMatcher.h - Generate a matcher for input strings ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the StringMatcher class. +// +//===----------------------------------------------------------------------===// + +#ifndef STRINGMATCHER_H +#define STRINGMATCHER_H + +#include <vector> +#include <string> +#include <utility> +#include "llvm/ADT/StringRef.h" + +namespace llvm { + class raw_ostream; + +/// StringMatcher - Given a list of strings and code to execute when they match, +/// output a simple switch tree to classify the input string. +/// +/// If a match is found, the code in Vals[i].second is executed; control must +/// not exit this code fragment. If nothing matches, execution falls through. +/// +class StringMatcher { +public: + typedef std::pair<std::string, std::string> StringPair; +private: + StringRef StrVariableName; + const std::vector<StringPair> &Matches; + raw_ostream &OS; + +public: + StringMatcher(StringRef strVariableName, + const std::vector<StringPair> &matches, raw_ostream &os) + : StrVariableName(strVariableName), Matches(matches), OS(os) {} + + void Emit(unsigned Indent = 0) const; + + +private: + bool EmitStringMatcherForChar(const std::vector<const StringPair*> &Matches, + unsigned CharNo, unsigned IndentCount) const; +}; + +} // end llvm namespace. + +#endif diff --git a/contrib/llvm/utils/TableGen/StringToOffsetTable.h b/contrib/llvm/utils/TableGen/StringToOffsetTable.h new file mode 100644 index 0000000..803f5bd --- /dev/null +++ b/contrib/llvm/utils/TableGen/StringToOffsetTable.h @@ -0,0 +1,82 @@ +//===- StringToOffsetTable.h - Emit a big concatenated string ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef TBLGEN_STRING_TO_OFFSET_TABLE_H +#define TBLGEN_STRING_TO_OFFSET_TABLE_H + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +/// StringToOffsetTable - This class uniques a bunch of nul-terminated strings +/// and keeps track of their offset in a massive contiguous string allocation. +/// It can then output this string blob and use indexes into the string to +/// reference each piece. +class StringToOffsetTable { + StringMap<unsigned> StringOffset; + std::string AggregateString; +public: + + unsigned GetOrAddStringOffset(StringRef Str, bool appendZero = true) { + StringMapEntry<unsigned> &Entry = StringOffset.GetOrCreateValue(Str, -1U); + if (Entry.getValue() == -1U) { + // Add the string to the aggregate if this is the first time found. + Entry.setValue(AggregateString.size()); + AggregateString.append(Str.begin(), Str.end()); + if (appendZero) + AggregateString += '\0'; + } + + return Entry.getValue(); + } + + void EmitString(raw_ostream &O) { + // Escape the string. + SmallString<256> Str; + raw_svector_ostream(Str).write_escaped(AggregateString); + AggregateString = Str.str(); + + O << " \""; + unsigned CharsPrinted = 0; + for (unsigned i = 0, e = AggregateString.size(); i != e; ++i) { + if (CharsPrinted > 70) { + O << "\"\n \""; + CharsPrinted = 0; + } + O << AggregateString[i]; + ++CharsPrinted; + + // Print escape sequences all together. + if (AggregateString[i] != '\\') + continue; + + assert(i+1 < AggregateString.size() && "Incomplete escape sequence!"); + if (isdigit(AggregateString[i+1])) { + assert(isdigit(AggregateString[i+2]) && + isdigit(AggregateString[i+3]) && + "Expected 3 digit octal escape!"); + O << AggregateString[++i]; + O << AggregateString[++i]; + O << AggregateString[++i]; + CharsPrinted += 3; + } else { + O << AggregateString[++i]; + ++CharsPrinted; + } + } + O << "\""; + } +}; + +} // end namespace llvm + +#endif diff --git a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp new file mode 100644 index 0000000..986c50f --- /dev/null +++ b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp @@ -0,0 +1,775 @@ +//===- SubtargetEmitter.cpp - Generate subtarget enumerations -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend emits subtarget enumerations. +// +//===----------------------------------------------------------------------===// + +#include "SubtargetEmitter.h" +#include "CodeGenTarget.h" +#include "llvm/TableGen/Record.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Debug.h" +#include <algorithm> +using namespace llvm; + +// +// Enumeration - Emit the specified class as an enumeration. +// +void SubtargetEmitter::Enumeration(raw_ostream &OS, + const char *ClassName, + bool isBits) { + // Get all records of class and sort + std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName); + std::sort(DefList.begin(), DefList.end(), LessRecord()); + + unsigned N = DefList.size(); + if (N == 0) + return; + if (N > 64) { + errs() << "Too many (> 64) subtarget features!\n"; + exit(1); + } + + OS << "namespace " << Target << " {\n"; + + // For bit flag enumerations with more than 32 items, emit constants. + // Emit an enum for everything else. + if (isBits && N > 32) { + // For each record + for (unsigned i = 0; i < N; i++) { + // Next record + Record *Def = DefList[i]; + + // Get and emit name and expression (1 << i) + OS << " const uint64_t " << Def->getName() << " = 1ULL << " << i << ";\n"; + } + } else { + // Open enumeration + OS << "enum {\n"; + + // For each record + for (unsigned i = 0; i < N;) { + // Next record + Record *Def = DefList[i]; + + // Get and emit name + OS << " " << Def->getName(); + + // If bit flags then emit expression (1 << i) + if (isBits) OS << " = " << " 1ULL << " << i; + + // Depending on 'if more in the list' emit comma + if (++i < N) OS << ","; + + OS << "\n"; + } + + // Close enumeration + OS << "};\n"; + } + + OS << "}\n"; +} + +// +// FeatureKeyValues - Emit data of all the subtarget features. Used by the +// command line. +// +unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) { + // Gather and sort all the features + std::vector<Record*> FeatureList = + Records.getAllDerivedDefinitions("SubtargetFeature"); + + if (FeatureList.empty()) + return 0; + + std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName()); + + // Begin feature table + OS << "// Sorted (by key) array of values for CPU features.\n" + << "extern const llvm::SubtargetFeatureKV " << Target + << "FeatureKV[] = {\n"; + + // For each feature + unsigned NumFeatures = 0; + for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) { + // Next feature + Record *Feature = FeatureList[i]; + + const std::string &Name = Feature->getName(); + const std::string &CommandLineName = Feature->getValueAsString("Name"); + const std::string &Desc = Feature->getValueAsString("Desc"); + + if (CommandLineName.empty()) continue; + + // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in } + OS << " { " + << "\"" << CommandLineName << "\", " + << "\"" << Desc << "\", " + << Target << "::" << Name << ", "; + + const std::vector<Record*> &ImpliesList = + Feature->getValueAsListOfDefs("Implies"); + + if (ImpliesList.empty()) { + OS << "0ULL"; + } else { + for (unsigned j = 0, M = ImpliesList.size(); j < M;) { + OS << Target << "::" << ImpliesList[j]->getName(); + if (++j < M) OS << " | "; + } + } + + OS << " }"; + ++NumFeatures; + + // Depending on 'if more in the list' emit comma + if ((i + 1) < N) OS << ","; + + OS << "\n"; + } + + // End feature table + OS << "};\n"; + + return NumFeatures; +} + +// +// CPUKeyValues - Emit data of all the subtarget processors. Used by command +// line. +// +unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) { + // Gather and sort processor information + std::vector<Record*> ProcessorList = + Records.getAllDerivedDefinitions("Processor"); + std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName()); + + // Begin processor table + OS << "// Sorted (by key) array of values for CPU subtype.\n" + << "extern const llvm::SubtargetFeatureKV " << Target + << "SubTypeKV[] = {\n"; + + // For each processor + for (unsigned i = 0, N = ProcessorList.size(); i < N;) { + // Next processor + Record *Processor = ProcessorList[i]; + + const std::string &Name = Processor->getValueAsString("Name"); + const std::vector<Record*> &FeatureList = + Processor->getValueAsListOfDefs("Features"); + + // Emit as { "cpu", "description", f1 | f2 | ... fn }, + OS << " { " + << "\"" << Name << "\", " + << "\"Select the " << Name << " processor\", "; + + if (FeatureList.empty()) { + OS << "0ULL"; + } else { + for (unsigned j = 0, M = FeatureList.size(); j < M;) { + OS << Target << "::" << FeatureList[j]->getName(); + if (++j < M) OS << " | "; + } + } + + // The "0" is for the "implies" section of this data structure. + OS << ", 0ULL }"; + + // Depending on 'if more in the list' emit comma + if (++i < N) OS << ","; + + OS << "\n"; + } + + // End processor table + OS << "};\n"; + + return ProcessorList.size(); +} + +// +// CollectAllItinClasses - Gathers and enumerates all the itinerary classes. +// Returns itinerary class count. +// +unsigned SubtargetEmitter:: +CollectAllItinClasses(raw_ostream &OS, + std::map<std::string, unsigned> &ItinClassesMap, + std::vector<Record*> &ItinClassList) { + // For each itinerary class + unsigned N = ItinClassList.size(); + for (unsigned i = 0; i < N; i++) { + // Next itinerary class + const Record *ItinClass = ItinClassList[i]; + // Get name of itinerary class + // Assign itinerary class a unique number + ItinClassesMap[ItinClass->getName()] = i; + } + + // Return itinerary class count + return N; +} + +// +// FormItineraryStageString - Compose a string containing the stage +// data initialization for the specified itinerary. N is the number +// of stages. +// +void SubtargetEmitter::FormItineraryStageString(const std::string &Name, + Record *ItinData, + std::string &ItinString, + unsigned &NStages) { + // Get states list + const std::vector<Record*> &StageList = + ItinData->getValueAsListOfDefs("Stages"); + + // For each stage + unsigned N = NStages = StageList.size(); + for (unsigned i = 0; i < N;) { + // Next stage + const Record *Stage = StageList[i]; + + // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind } + int Cycles = Stage->getValueAsInt("Cycles"); + ItinString += " { " + itostr(Cycles) + ", "; + + // Get unit list + const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units"); + + // For each unit + for (unsigned j = 0, M = UnitList.size(); j < M;) { + // Add name and bitwise or + ItinString += Name + "FU::" + UnitList[j]->getName(); + if (++j < M) ItinString += " | "; + } + + int TimeInc = Stage->getValueAsInt("TimeInc"); + ItinString += ", " + itostr(TimeInc); + + int Kind = Stage->getValueAsInt("Kind"); + ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind); + + // Close off stage + ItinString += " }"; + if (++i < N) ItinString += ", "; + } +} + +// +// FormItineraryOperandCycleString - Compose a string containing the +// operand cycle initialization for the specified itinerary. N is the +// number of operands that has cycles specified. +// +void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData, + std::string &ItinString, unsigned &NOperandCycles) { + // Get operand cycle list + const std::vector<int64_t> &OperandCycleList = + ItinData->getValueAsListOfInts("OperandCycles"); + + // For each operand cycle + unsigned N = NOperandCycles = OperandCycleList.size(); + for (unsigned i = 0; i < N;) { + // Next operand cycle + const int OCycle = OperandCycleList[i]; + + ItinString += " " + itostr(OCycle); + if (++i < N) ItinString += ", "; + } +} + +void SubtargetEmitter::FormItineraryBypassString(const std::string &Name, + Record *ItinData, + std::string &ItinString, + unsigned NOperandCycles) { + const std::vector<Record*> &BypassList = + ItinData->getValueAsListOfDefs("Bypasses"); + unsigned N = BypassList.size(); + unsigned i = 0; + for (; i < N;) { + ItinString += Name + "Bypass::" + BypassList[i]->getName(); + if (++i < NOperandCycles) ItinString += ", "; + } + for (; i < NOperandCycles;) { + ItinString += " 0"; + if (++i < NOperandCycles) ItinString += ", "; + } +} + +// +// EmitStageAndOperandCycleData - Generate unique itinerary stages and +// operand cycle tables. Record itineraries for processors. +// +void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, + unsigned NItinClasses, + std::map<std::string, unsigned> &ItinClassesMap, + std::vector<Record*> &ItinClassList, + std::vector<std::vector<InstrItinerary> > &ProcList) { + // Gather processor iteraries + std::vector<Record*> ProcItinList = + Records.getAllDerivedDefinitions("ProcessorItineraries"); + + // If just no itinerary then don't bother + if (ProcItinList.size() < 2) return; + + // Emit functional units for all the itineraries. + for (unsigned i = 0, N = ProcItinList.size(); i < N; ++i) { + // Next record + Record *Proc = ProcItinList[i]; + + std::vector<Record*> FUs = Proc->getValueAsListOfDefs("FU"); + if (FUs.empty()) + continue; + + const std::string &Name = Proc->getName(); + OS << "\n// Functional units for itineraries \"" << Name << "\"\n" + << "namespace " << Name << "FU {\n"; + + for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j) + OS << " const unsigned " << FUs[j]->getName() + << " = 1 << " << j << ";\n"; + + OS << "}\n"; + + std::vector<Record*> BPs = Proc->getValueAsListOfDefs("BP"); + if (BPs.size()) { + OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name + << "\"\n" << "namespace " << Name << "Bypass {\n"; + + OS << " const unsigned NoBypass = 0;\n"; + for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j) + OS << " const unsigned " << BPs[j]->getName() + << " = 1 << " << j << ";\n"; + + OS << "}\n"; + } + } + + // Begin stages table + std::string StageTable = "\nextern const llvm::InstrStage " + Target + + "Stages[] = {\n"; + StageTable += " { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n"; + + // Begin operand cycle table + std::string OperandCycleTable = "extern const unsigned " + Target + + "OperandCycles[] = {\n"; + OperandCycleTable += " 0, // No itinerary\n"; + + // Begin pipeline bypass table + std::string BypassTable = "extern const unsigned " + Target + + "ForwardingPathes[] = {\n"; + BypassTable += " 0, // No itinerary\n"; + + unsigned StageCount = 1, OperandCycleCount = 1; + std::map<std::string, unsigned> ItinStageMap, ItinOperandMap; + for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) { + // Next record + Record *Proc = ProcItinList[i]; + + // Get processor itinerary name + const std::string &Name = Proc->getName(); + + // Skip default + if (Name == "NoItineraries") continue; + + // Create and expand processor itinerary to cover all itinerary classes + std::vector<InstrItinerary> ItinList; + ItinList.resize(NItinClasses); + + // Get itinerary data list + std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID"); + + // For each itinerary data + for (unsigned j = 0, M = ItinDataList.size(); j < M; j++) { + // Next itinerary data + Record *ItinData = ItinDataList[j]; + + // Get string and stage count + std::string ItinStageString; + unsigned NStages; + FormItineraryStageString(Name, ItinData, ItinStageString, NStages); + + // Get string and operand cycle count + std::string ItinOperandCycleString; + unsigned NOperandCycles; + FormItineraryOperandCycleString(ItinData, ItinOperandCycleString, + NOperandCycles); + + std::string ItinBypassString; + FormItineraryBypassString(Name, ItinData, ItinBypassString, + NOperandCycles); + + // Check to see if stage already exists and create if it doesn't + unsigned FindStage = 0; + if (NStages > 0) { + FindStage = ItinStageMap[ItinStageString]; + if (FindStage == 0) { + // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices + StageTable += ItinStageString + ", // " + itostr(StageCount); + if (NStages > 1) + StageTable += "-" + itostr(StageCount + NStages - 1); + StageTable += "\n"; + // Record Itin class number. + ItinStageMap[ItinStageString] = FindStage = StageCount; + StageCount += NStages; + } + } + + // Check to see if operand cycle already exists and create if it doesn't + unsigned FindOperandCycle = 0; + if (NOperandCycles > 0) { + std::string ItinOperandString = ItinOperandCycleString+ItinBypassString; + FindOperandCycle = ItinOperandMap[ItinOperandString]; + if (FindOperandCycle == 0) { + // Emit as cycle, // index + OperandCycleTable += ItinOperandCycleString + ", // "; + std::string OperandIdxComment = itostr(OperandCycleCount); + if (NOperandCycles > 1) + OperandIdxComment += "-" + + itostr(OperandCycleCount + NOperandCycles - 1); + OperandCycleTable += OperandIdxComment + "\n"; + // Record Itin class number. + ItinOperandMap[ItinOperandCycleString] = + FindOperandCycle = OperandCycleCount; + // Emit as bypass, // index + BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n"; + OperandCycleCount += NOperandCycles; + } + } + + // Locate where to inject into processor itinerary table + const std::string &Name = ItinData->getValueAsDef("TheClass")->getName(); + unsigned Find = ItinClassesMap[Name]; + + // Set up itinerary as location and location + stage count + unsigned NumUOps = ItinClassList[Find]->getValueAsInt("NumMicroOps"); + InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages, + FindOperandCycle, + FindOperandCycle + NOperandCycles}; + + // Inject - empty slots will be 0, 0 + ItinList[Find] = Intinerary; + } + + // Add process itinerary to list + ProcList.push_back(ItinList); + } + + // Closing stage + StageTable += " { 0, 0, 0, llvm::InstrStage::Required } // End itinerary\n"; + StageTable += "};\n"; + + // Closing operand cycles + OperandCycleTable += " 0 // End itinerary\n"; + OperandCycleTable += "};\n"; + + BypassTable += " 0 // End itinerary\n"; + BypassTable += "};\n"; + + // Emit tables. + OS << StageTable; + OS << OperandCycleTable; + OS << BypassTable; +} + +// +// EmitProcessorData - Generate data for processor itineraries. +// +void SubtargetEmitter:: +EmitProcessorData(raw_ostream &OS, + std::vector<Record*> &ItinClassList, + std::vector<std::vector<InstrItinerary> > &ProcList) { + // Get an iterator for processor itinerary stages + std::vector<std::vector<InstrItinerary> >::iterator + ProcListIter = ProcList.begin(); + + // For each processor itinerary + std::vector<Record*> Itins = + Records.getAllDerivedDefinitions("ProcessorItineraries"); + for (unsigned i = 0, N = Itins.size(); i < N; i++) { + // Next record + Record *Itin = Itins[i]; + + // Get processor itinerary name + const std::string &Name = Itin->getName(); + + // Skip default + if (Name == "NoItineraries") continue; + + // Begin processor itinerary table + OS << "\n"; + OS << "static const llvm::InstrItinerary " << Name << "[] = {\n"; + + // For each itinerary class + std::vector<InstrItinerary> &ItinList = *ProcListIter++; + assert(ItinList.size() == ItinClassList.size() && "bad itinerary"); + for (unsigned j = 0, M = ItinList.size(); j < M; ++j) { + InstrItinerary &Intinerary = ItinList[j]; + + // Emit in the form of + // { firstStage, lastStage, firstCycle, lastCycle } // index + if (Intinerary.FirstStage == 0) { + OS << " { 1, 0, 0, 0, 0 }"; + } else { + OS << " { " << + Intinerary.NumMicroOps << ", " << + Intinerary.FirstStage << ", " << + Intinerary.LastStage << ", " << + Intinerary.FirstOperandCycle << ", " << + Intinerary.LastOperandCycle << " }"; + } + + OS << ", // " << j << " " << ItinClassList[j]->getName() << "\n"; + } + + // End processor itinerary table + OS << " { 1, ~0U, ~0U, ~0U, ~0U } // end marker\n"; + OS << "};\n"; + } +} + +// +// EmitProcessorLookup - generate cpu name to itinerary lookup table. +// +void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) { + // Gather and sort processor information + std::vector<Record*> ProcessorList = + Records.getAllDerivedDefinitions("Processor"); + std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName()); + + // Begin processor table + OS << "\n"; + OS << "// Sorted (by key) array of itineraries for CPU subtype.\n" + << "extern const llvm::SubtargetInfoKV " + << Target << "ProcItinKV[] = {\n"; + + // For each processor + for (unsigned i = 0, N = ProcessorList.size(); i < N;) { + // Next processor + Record *Processor = ProcessorList[i]; + + const std::string &Name = Processor->getValueAsString("Name"); + const std::string &ProcItin = + Processor->getValueAsDef("ProcItin")->getName(); + + // Emit as { "cpu", procinit }, + OS << " { " + << "\"" << Name << "\", " + << "(void *)&" << ProcItin; + + OS << " }"; + + // Depending on ''if more in the list'' emit comma + if (++i < N) OS << ","; + + OS << "\n"; + } + + // End processor table + OS << "};\n"; +} + +// +// EmitData - Emits all stages and itineries, folding common patterns. +// +void SubtargetEmitter::EmitData(raw_ostream &OS) { + std::map<std::string, unsigned> ItinClassesMap; + // Gather and sort all itinerary classes + std::vector<Record*> ItinClassList = + Records.getAllDerivedDefinitions("InstrItinClass"); + std::sort(ItinClassList.begin(), ItinClassList.end(), LessRecord()); + + // Enumerate all the itinerary classes + unsigned NItinClasses = CollectAllItinClasses(OS, ItinClassesMap, + ItinClassList); + // Make sure the rest is worth the effort + HasItineraries = NItinClasses != 1; // Ignore NoItinerary. + + if (HasItineraries) { + std::vector<std::vector<InstrItinerary> > ProcList; + // Emit the stage data + EmitStageAndOperandCycleData(OS, NItinClasses, ItinClassesMap, + ItinClassList, ProcList); + // Emit the processor itinerary data + EmitProcessorData(OS, ItinClassList, ProcList); + // Emit the processor lookup data + EmitProcessorLookup(OS); + } +} + +// +// ParseFeaturesFunction - Produces a subtarget specific function for parsing +// the subtarget features string. +// +void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS, + unsigned NumFeatures, + unsigned NumProcs) { + std::vector<Record*> Features = + Records.getAllDerivedDefinitions("SubtargetFeature"); + std::sort(Features.begin(), Features.end(), LessRecord()); + + OS << "// ParseSubtargetFeatures - Parses features string setting specified\n" + << "// subtarget options.\n" + << "void llvm::"; + OS << Target; + OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n" + << " DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n" + << " DEBUG(dbgs() << \"\\nCPU:\" << CPU);\n"; + + if (Features.empty()) { + OS << "}\n"; + return; + } + + OS << " uint64_t Bits = ReInitMCSubtargetInfo(CPU, FS);\n"; + + for (unsigned i = 0; i < Features.size(); i++) { + // Next record + Record *R = Features[i]; + const std::string &Instance = R->getName(); + const std::string &Value = R->getValueAsString("Value"); + const std::string &Attribute = R->getValueAsString("Attribute"); + + if (Value=="true" || Value=="false") + OS << " if ((Bits & " << Target << "::" + << Instance << ") != 0) " + << Attribute << " = " << Value << ";\n"; + else + OS << " if ((Bits & " << Target << "::" + << Instance << ") != 0 && " + << Attribute << " < " << Value << ") " + << Attribute << " = " << Value << ";\n"; + } + + OS << "}\n"; +} + +// +// SubtargetEmitter::run - Main subtarget enumeration emitter. +// +void SubtargetEmitter::run(raw_ostream &OS) { + Target = CodeGenTarget(Records).getName(); + + EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS); + + OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n"; + OS << "#undef GET_SUBTARGETINFO_ENUM\n"; + + OS << "namespace llvm {\n"; + Enumeration(OS, "SubtargetFeature", true); + OS << "} // End llvm namespace \n"; + OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n"; + + OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n"; + OS << "#undef GET_SUBTARGETINFO_MC_DESC\n"; + + OS << "namespace llvm {\n"; +#if 0 + OS << "namespace {\n"; +#endif + unsigned NumFeatures = FeatureKeyValues(OS); + OS << "\n"; + unsigned NumProcs = CPUKeyValues(OS); + OS << "\n"; + EmitData(OS); + OS << "\n"; +#if 0 + OS << "}\n"; +#endif + + // MCInstrInfo initialization routine. + OS << "static inline void Init" << Target + << "MCSubtargetInfo(MCSubtargetInfo *II, " + << "StringRef TT, StringRef CPU, StringRef FS) {\n"; + OS << " II->InitMCSubtargetInfo(TT, CPU, FS, "; + if (NumFeatures) + OS << Target << "FeatureKV, "; + else + OS << "0, "; + if (NumProcs) + OS << Target << "SubTypeKV, "; + else + OS << "0, "; + if (HasItineraries) { + OS << Target << "ProcItinKV, " + << Target << "Stages, " + << Target << "OperandCycles, " + << Target << "ForwardingPathes, "; + } else + OS << "0, 0, 0, 0, "; + OS << NumFeatures << ", " << NumProcs << ");\n}\n\n"; + + OS << "} // End llvm namespace \n"; + + OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n"; + + OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n"; + OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n"; + + OS << "#include \"llvm/Support/Debug.h\"\n"; + OS << "#include \"llvm/Support/raw_ostream.h\"\n"; + ParseFeaturesFunction(OS, NumFeatures, NumProcs); + + OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n"; + + // Create a TargetSubtargetInfo subclass to hide the MC layer initialization. + OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n"; + OS << "#undef GET_SUBTARGETINFO_HEADER\n"; + + std::string ClassName = Target + "GenSubtargetInfo"; + OS << "namespace llvm {\n"; + OS << "class DFAPacketizer;\n"; + OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n" + << " explicit " << ClassName << "(StringRef TT, StringRef CPU, " + << "StringRef FS);\n" + << "public:\n" + << " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)" + << " const;\n" + << "};\n"; + OS << "} // End llvm namespace \n"; + + OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n"; + + OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n"; + OS << "#undef GET_SUBTARGETINFO_CTOR\n"; + + OS << "namespace llvm {\n"; + OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n"; + OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n"; + if (HasItineraries) { + OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcItinKV[];\n"; + OS << "extern const llvm::InstrStage " << Target << "Stages[];\n"; + OS << "extern const unsigned " << Target << "OperandCycles[];\n"; + OS << "extern const unsigned " << Target << "ForwardingPathes[];\n"; + } + + OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, " + << "StringRef FS)\n" + << " : TargetSubtargetInfo() {\n" + << " InitMCSubtargetInfo(TT, CPU, FS, "; + if (NumFeatures) + OS << Target << "FeatureKV, "; + else + OS << "0, "; + if (NumProcs) + OS << Target << "SubTypeKV, "; + else + OS << "0, "; + if (HasItineraries) { + OS << Target << "ProcItinKV, " + << Target << "Stages, " + << Target << "OperandCycles, " + << Target << "ForwardingPathes, "; + } else + OS << "0, 0, 0, 0, "; + OS << NumFeatures << ", " << NumProcs << ");\n}\n\n"; + OS << "} // End llvm namespace \n"; + + OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n"; +} diff --git a/contrib/llvm/utils/TableGen/SubtargetEmitter.h b/contrib/llvm/utils/TableGen/SubtargetEmitter.h new file mode 100644 index 0000000..ff01274 --- /dev/null +++ b/contrib/llvm/utils/TableGen/SubtargetEmitter.h @@ -0,0 +1,72 @@ +//===- SubtargetEmitter.h - Generate subtarget enumerations -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend emits subtarget enumerations. +// +//===----------------------------------------------------------------------===// + +#ifndef SUBTARGET_EMITTER_H +#define SUBTARGET_EMITTER_H + +#include "llvm/TableGen/TableGenBackend.h" +#include "llvm/MC/MCInstrItineraries.h" +#include <vector> +#include <map> +#include <string> + + +namespace llvm { + +class SubtargetEmitter : public TableGenBackend { + + RecordKeeper &Records; + std::string Target; + bool HasItineraries; + + void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits); + unsigned FeatureKeyValues(raw_ostream &OS); + unsigned CPUKeyValues(raw_ostream &OS); + unsigned CollectAllItinClasses(raw_ostream &OS, + std::map<std::string,unsigned> &ItinClassesMap, + std::vector<Record*> &ItinClassList); + void FormItineraryStageString(const std::string &Names, + Record *ItinData, std::string &ItinString, + unsigned &NStages); + void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString, + unsigned &NOperandCycles); + void FormItineraryBypassString(const std::string &Names, + Record *ItinData, + std::string &ItinString, unsigned NOperandCycles); + void EmitStageAndOperandCycleData(raw_ostream &OS, unsigned NItinClasses, + std::map<std::string, unsigned> &ItinClassesMap, + std::vector<Record*> &ItinClassList, + std::vector<std::vector<InstrItinerary> > &ProcList); + void EmitProcessorData(raw_ostream &OS, + std::vector<Record*> &ItinClassList, + std::vector<std::vector<InstrItinerary> > &ProcList); + void EmitProcessorLookup(raw_ostream &OS); + void EmitData(raw_ostream &OS); + void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures, + unsigned NumProcs); + +public: + SubtargetEmitter(RecordKeeper &R) : Records(R), HasItineraries(false) {} + + // run - Output the subtarget enumerations, returning true on failure. + void run(raw_ostream &o); + +}; + + +} // End llvm namespace + +#endif + + + diff --git a/contrib/llvm/utils/TableGen/TGValueTypes.cpp b/contrib/llvm/utils/TableGen/TGValueTypes.cpp new file mode 100644 index 0000000..af0d9f4 --- /dev/null +++ b/contrib/llvm/utils/TableGen/TGValueTypes.cpp @@ -0,0 +1,105 @@ +//===- ValueTypes.cpp - Tablegen extended ValueType implementation --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The EVT type is used by tablegen as well as in LLVM. In order to handle +// extended types, the EVT type uses support functions that call into +// LLVM's type system code. These aren't accessible in tablegen, so this +// file provides simple replacements. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/ValueTypes.h" +#include <map> +using namespace llvm; + +namespace llvm { + +class Type { +public: + virtual unsigned getSizeInBits() const = 0; + virtual ~Type() {} +}; + +} + +class ExtendedIntegerType : public Type { + unsigned BitWidth; +public: + explicit ExtendedIntegerType(unsigned bits) + : BitWidth(bits) {} + unsigned getSizeInBits() const { + return getBitWidth(); + } + unsigned getBitWidth() const { + return BitWidth; + } +}; + +class ExtendedVectorType : public Type { + EVT ElementType; + unsigned NumElements; +public: + ExtendedVectorType(EVT elty, unsigned num) + : ElementType(elty), NumElements(num) {} + unsigned getSizeInBits() const { + return getNumElements() * getElementType().getSizeInBits(); + } + EVT getElementType() const { + return ElementType; + } + unsigned getNumElements() const { + return NumElements; + } +}; + +static std::map<unsigned, const Type *> + ExtendedIntegerTypeMap; +static std::map<std::pair<uintptr_t, uintptr_t>, const Type *> + ExtendedVectorTypeMap; + +bool EVT::isExtendedFloatingPoint() const { + assert(isExtended() && "Type is not extended!"); + // Extended floating-point types are not supported yet. + return false; +} + +bool EVT::isExtendedInteger() const { + assert(isExtended() && "Type is not extended!"); + return dynamic_cast<const ExtendedIntegerType *>(LLVMTy) != 0; +} + +bool EVT::isExtendedVector() const { + assert(isExtended() && "Type is not extended!"); + return dynamic_cast<const ExtendedVectorType *>(LLVMTy) != 0; +} + +bool EVT::isExtended64BitVector() const { + assert(isExtended() && "Type is not extended!"); + return isExtendedVector() && getSizeInBits() == 64; +} + +bool EVT::isExtended128BitVector() const { + assert(isExtended() && "Type is not extended!"); + return isExtendedVector() && getSizeInBits() == 128; +} + +EVT EVT::getExtendedVectorElementType() const { + assert(isExtendedVector() && "Type is not an extended vector!"); + return static_cast<const ExtendedVectorType *>(LLVMTy)->getElementType(); +} + +unsigned EVT::getExtendedVectorNumElements() const { + assert(isExtendedVector() && "Type is not an extended vector!"); + return static_cast<const ExtendedVectorType *>(LLVMTy)->getNumElements(); +} + +unsigned EVT::getExtendedSizeInBits() const { + assert(isExtended() && "Type is not extended!"); + return LLVMTy->getSizeInBits(); +} diff --git a/contrib/llvm/utils/TableGen/TableGen.cpp b/contrib/llvm/utils/TableGen/TableGen.cpp new file mode 100644 index 0000000..8c41358 --- /dev/null +++ b/contrib/llvm/utils/TableGen/TableGen.cpp @@ -0,0 +1,195 @@ +//===- TableGen.cpp - Top-Level TableGen implementation for LLVM ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the main function for LLVM's TableGen. +// +//===----------------------------------------------------------------------===// + +#include "AsmMatcherEmitter.h" +#include "AsmWriterEmitter.h" +#include "CallingConvEmitter.h" +#include "CodeEmitterGen.h" +#include "DAGISelEmitter.h" +#include "DFAPacketizerEmitter.h" +#include "DisassemblerEmitter.h" +#include "EDEmitter.h" +#include "FastISelEmitter.h" +#include "InstrInfoEmitter.h" +#include "IntrinsicEmitter.h" +#include "PseudoLoweringEmitter.h" +#include "RegisterInfoEmitter.h" +#include "SubtargetEmitter.h" +#include "SetTheory.h" + +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Signals.h" +#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 { + PrintRecords, + GenEmitter, + GenRegisterInfo, + GenInstrInfo, + GenAsmWriter, + GenAsmMatcher, + GenDisassembler, + GenPseudoLowering, + GenCallingConv, + GenDAGISel, + GenDFAPacketizer, + GenFastISel, + GenSubtarget, + GenIntrinsic, + GenTgtIntrinsic, + GenEDInfo, + PrintEnums, + PrintSets +}; + +namespace { + cl::opt<ActionType> + Action(cl::desc("Action to perform:"), + cl::values(clEnumValN(PrintRecords, "print-records", + "Print all records to stdout (default)"), + clEnumValN(GenEmitter, "gen-emitter", + "Generate machine code emitter"), + clEnumValN(GenRegisterInfo, "gen-register-info", + "Generate registers and register classes info"), + clEnumValN(GenInstrInfo, "gen-instr-info", + "Generate instruction descriptions"), + clEnumValN(GenCallingConv, "gen-callingconv", + "Generate calling convention descriptions"), + clEnumValN(GenAsmWriter, "gen-asm-writer", + "Generate assembly writer"), + clEnumValN(GenDisassembler, "gen-disassembler", + "Generate disassembler"), + clEnumValN(GenPseudoLowering, "gen-pseudo-lowering", + "Generate pseudo instruction lowering"), + clEnumValN(GenAsmMatcher, "gen-asm-matcher", + "Generate assembly instruction matcher"), + clEnumValN(GenDAGISel, "gen-dag-isel", + "Generate a DAG instruction selector"), + clEnumValN(GenDFAPacketizer, "gen-dfa-packetizer", + "Generate DFA Packetizer for VLIW targets"), + clEnumValN(GenFastISel, "gen-fast-isel", + "Generate a \"fast\" instruction selector"), + clEnumValN(GenSubtarget, "gen-subtarget", + "Generate subtarget enumerations"), + clEnumValN(GenIntrinsic, "gen-intrinsic", + "Generate intrinsic information"), + clEnumValN(GenTgtIntrinsic, "gen-tgt-intrinsic", + "Generate target intrinsic information"), + clEnumValN(GenEDInfo, "gen-enhanced-disassembly-info", + "Generate enhanced disassembly info"), + clEnumValN(PrintEnums, "print-enums", + "Print enum values for a class"), + clEnumValN(PrintSets, "print-sets", + "Print expanded sets for testing DAG exprs"), + clEnumValEnd)); + + cl::opt<std::string> + Class("class", cl::desc("Print Enum list for this class"), + cl::value_desc("class name")); + + class LLVMTableGenAction : public TableGenAction { + public: + bool operator()(raw_ostream &OS, RecordKeeper &Records) { + switch (Action) { + case PrintRecords: + OS << Records; // No argument, dump all contents + break; + case GenEmitter: + CodeEmitterGen(Records).run(OS); + break; + case GenRegisterInfo: + RegisterInfoEmitter(Records).run(OS); + break; + case GenInstrInfo: + InstrInfoEmitter(Records).run(OS); + break; + case GenCallingConv: + CallingConvEmitter(Records).run(OS); + break; + case GenAsmWriter: + AsmWriterEmitter(Records).run(OS); + break; + case GenAsmMatcher: + AsmMatcherEmitter(Records).run(OS); + break; + case GenDisassembler: + DisassemblerEmitter(Records).run(OS); + break; + case GenPseudoLowering: + PseudoLoweringEmitter(Records).run(OS); + break; + case GenDAGISel: + DAGISelEmitter(Records).run(OS); + break; + case GenDFAPacketizer: + DFAGen(Records).run(OS); + break; + case GenFastISel: + FastISelEmitter(Records).run(OS); + break; + case GenSubtarget: + SubtargetEmitter(Records).run(OS); + break; + case GenIntrinsic: + IntrinsicEmitter(Records).run(OS); + break; + case GenTgtIntrinsic: + IntrinsicEmitter(Records, true).run(OS); + break; + case GenEDInfo: + EDEmitter(Records).run(OS); + break; + case PrintEnums: + { + std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class); + for (unsigned i = 0, e = Recs.size(); i != e; ++i) + OS << Recs[i]->getName() << ", "; + OS << "\n"; + break; + } + case PrintSets: + { + SetTheory Sets; + Sets.addFieldExpander("Set", "Elements"); + std::vector<Record*> Recs = Records.getAllDerivedDefinitions("Set"); + for (unsigned i = 0, e = Recs.size(); i != e; ++i) { + OS << Recs[i]->getName() << " = ["; + const std::vector<Record*> *Elts = Sets.expand(Recs[i]); + assert(Elts && "Couldn't expand Set instance"); + for (unsigned ei = 0, ee = Elts->size(); ei != ee; ++ei) + OS << ' ' << (*Elts)[ei]->getName(); + OS << " ]\n"; + } + break; + } + } + + return false; + } + }; +} + +int main(int argc, char **argv) { + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + cl::ParseCommandLineOptions(argc, argv); + + LLVMTableGenAction Action; + return TableGenMain(argv[0], Action); +} diff --git a/contrib/llvm/utils/TableGen/X86DisassemblerShared.h b/contrib/llvm/utils/TableGen/X86DisassemblerShared.h new file mode 100644 index 0000000..0417e9d --- /dev/null +++ b/contrib/llvm/utils/TableGen/X86DisassemblerShared.h @@ -0,0 +1,38 @@ +//===- X86DisassemblerShared.h - Emitter shared header ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef X86DISASSEMBLERSHARED_H +#define X86DISASSEMBLERSHARED_H + +#include <string> +#include <string.h> + +#define INSTRUCTION_SPECIFIER_FIELDS \ + bool filtered; \ + InstructionContext insnContext; \ + std::string name; \ + \ + InstructionSpecifier() { \ + filtered = false; \ + insnContext = IC; \ + name = ""; \ + modifierType = MODIFIER_NONE; \ + modifierBase = 0; \ + memset(operands, 0, sizeof(operands)); \ + } + +#define INSTRUCTION_IDS \ + InstrUID instructionIDs[256]; + +#include "../../lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h" + +#undef INSTRUCTION_SPECIFIER_FIELDS +#undef INSTRUCTION_IDS + +#endif diff --git a/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp b/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp new file mode 100644 index 0000000..2875168 --- /dev/null +++ b/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp @@ -0,0 +1,708 @@ +//===- X86DisassemblerTables.cpp - Disassembler tables ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is part of the X86 Disassembler Emitter. +// It contains the implementation of the disassembler tables. +// Documentation for the disassembler emitter in general can be found in +// X86DisasemblerEmitter.h. +// +//===----------------------------------------------------------------------===// + +#include "X86DisassemblerShared.h" +#include "X86DisassemblerTables.h" + +#include "llvm/TableGen/TableGenBackend.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" + +using namespace llvm; +using namespace X86Disassembler; + +/// inheritsFrom - Indicates whether all instructions in one class also belong +/// to another class. +/// +/// @param child - The class that may be the subset +/// @param parent - The class that may be the superset +/// @return - True if child is a subset of parent, false otherwise. +static inline bool inheritsFrom(InstructionContext child, + InstructionContext parent, + bool VEX_LIG = false) { + if (child == parent) + return true; + + switch (parent) { + case IC: + return(inheritsFrom(child, IC_64BIT) || + inheritsFrom(child, IC_OPSIZE) || + inheritsFrom(child, IC_ADSIZE) || + inheritsFrom(child, IC_XD) || + inheritsFrom(child, IC_XS)); + case IC_64BIT: + return(inheritsFrom(child, IC_64BIT_REXW) || + inheritsFrom(child, IC_64BIT_OPSIZE) || + inheritsFrom(child, IC_64BIT_ADSIZE) || + inheritsFrom(child, IC_64BIT_XD) || + inheritsFrom(child, IC_64BIT_XS)); + case IC_OPSIZE: + return inheritsFrom(child, IC_64BIT_OPSIZE); + case IC_ADSIZE: + case IC_64BIT_ADSIZE: + return false; + case IC_XD: + return inheritsFrom(child, IC_64BIT_XD); + case IC_XS: + return inheritsFrom(child, IC_64BIT_XS); + case IC_XD_OPSIZE: + return inheritsFrom(child, IC_64BIT_XD_OPSIZE); + case IC_XS_OPSIZE: + return inheritsFrom(child, IC_64BIT_XS_OPSIZE); + case IC_64BIT_REXW: + return(inheritsFrom(child, IC_64BIT_REXW_XS) || + inheritsFrom(child, IC_64BIT_REXW_XD) || + inheritsFrom(child, IC_64BIT_REXW_OPSIZE)); + case IC_64BIT_OPSIZE: + return(inheritsFrom(child, IC_64BIT_REXW_OPSIZE)); + case IC_64BIT_XD: + return(inheritsFrom(child, IC_64BIT_REXW_XD)); + case IC_64BIT_XS: + return(inheritsFrom(child, IC_64BIT_REXW_XS)); + case IC_64BIT_XD_OPSIZE: + case IC_64BIT_XS_OPSIZE: + return false; + case IC_64BIT_REXW_XD: + case IC_64BIT_REXW_XS: + case IC_64BIT_REXW_OPSIZE: + return false; + case IC_VEX: + return inheritsFrom(child, IC_VEX_W) || + (VEX_LIG && inheritsFrom(child, IC_VEX_L)); + case IC_VEX_XS: + return inheritsFrom(child, IC_VEX_W_XS) || + (VEX_LIG && inheritsFrom(child, IC_VEX_L_XS)); + case IC_VEX_XD: + return inheritsFrom(child, IC_VEX_W_XD) || + (VEX_LIG && inheritsFrom(child, IC_VEX_L_XD)); + case IC_VEX_OPSIZE: + return inheritsFrom(child, IC_VEX_W_OPSIZE) || + (VEX_LIG && inheritsFrom(child, IC_VEX_L_OPSIZE)); + case IC_VEX_W: + case IC_VEX_W_XS: + case IC_VEX_W_XD: + case IC_VEX_W_OPSIZE: + return false; + case IC_VEX_L: + case IC_VEX_L_XS: + case IC_VEX_L_XD: + return false; + case IC_VEX_L_OPSIZE: + return inheritsFrom(child, IC_VEX_L_W_OPSIZE); + case IC_VEX_L_W_OPSIZE: + return false; + default: + llvm_unreachable("Unknown instruction class"); + } +} + +/// outranks - Indicates whether, if an instruction has two different applicable +/// classes, which class should be preferred when performing decode. This +/// imposes a total ordering (ties are resolved toward "lower") +/// +/// @param upper - The class that may be preferable +/// @param lower - The class that may be less preferable +/// @return - True if upper is to be preferred, false otherwise. +static inline bool outranks(InstructionContext upper, + InstructionContext lower) { + assert(upper < IC_max); + assert(lower < IC_max); + +#define ENUM_ENTRY(n, r, d) r, + static int ranks[IC_max] = { + INSTRUCTION_CONTEXTS + }; +#undef ENUM_ENTRY + + return (ranks[upper] > ranks[lower]); +} + +/// stringForContext - Returns a string containing the name of a particular +/// InstructionContext, usually for diagnostic purposes. +/// +/// @param insnContext - The instruction class to transform to a string. +/// @return - A statically-allocated string constant that contains the +/// name of the instruction class. +static inline const char* stringForContext(InstructionContext insnContext) { + switch (insnContext) { + default: + llvm_unreachable("Unhandled instruction class"); +#define ENUM_ENTRY(n, r, d) case n: return #n; break; + INSTRUCTION_CONTEXTS +#undef ENUM_ENTRY + } +} + +/// stringForOperandType - Like stringForContext, but for OperandTypes. +static inline const char* stringForOperandType(OperandType type) { + switch (type) { + default: + llvm_unreachable("Unhandled type"); +#define ENUM_ENTRY(i, d) case i: return #i; + TYPES +#undef ENUM_ENTRY + } +} + +/// stringForOperandEncoding - like stringForContext, but for +/// OperandEncodings. +static inline const char* stringForOperandEncoding(OperandEncoding encoding) { + switch (encoding) { + default: + llvm_unreachable("Unhandled encoding"); +#define ENUM_ENTRY(i, d) case i: return #i; + ENCODINGS +#undef ENUM_ENTRY + } +} + +void DisassemblerTables::emitOneID(raw_ostream &o, + uint32_t &i, + InstrUID id, + bool addComma) const { + if (id) + o.indent(i * 2) << format("0x%hx", id); + else + o.indent(i * 2) << 0; + + if (addComma) + o << ", "; + else + o << " "; + + o << "/* "; + o << InstructionSpecifiers[id].name; + o << "*/"; + + o << "\n"; +} + +/// emitEmptyTable - Emits the modRMEmptyTable, which is used as a ID table by +/// all ModR/M decisions for instructions that are invalid for all possible +/// ModR/M byte values. +/// +/// @param o - The output stream on which to emit the table. +/// @param i - The indentation level for that output stream. +static void emitEmptyTable(raw_ostream &o, uint32_t &i) +{ + o.indent(i * 2) << "0x0, /* EmptyTable */\n"; +} + +/// getDecisionType - Determines whether a ModRM decision with 255 entries can +/// be compacted by eliminating redundant information. +/// +/// @param decision - The decision to be compacted. +/// @return - The compactest available representation for the decision. +static ModRMDecisionType getDecisionType(ModRMDecision &decision) +{ + bool satisfiesOneEntry = true; + bool satisfiesSplitRM = true; + bool satisfiesSplitReg = true; + + uint16_t index; + + for (index = 0; index < 256; ++index) { + if (decision.instructionIDs[index] != decision.instructionIDs[0]) + satisfiesOneEntry = false; + + if (((index & 0xc0) == 0xc0) && + (decision.instructionIDs[index] != decision.instructionIDs[0xc0])) + satisfiesSplitRM = false; + + if (((index & 0xc0) != 0xc0) && + (decision.instructionIDs[index] != decision.instructionIDs[0x00])) + satisfiesSplitRM = false; + + if (((index & 0xc0) == 0xc0) && + (decision.instructionIDs[index] != decision.instructionIDs[index&0xf8])) + satisfiesSplitReg = false; + + if (((index & 0xc0) != 0xc0) && + (decision.instructionIDs[index] != decision.instructionIDs[index&0x38])) + satisfiesSplitReg = false; + } + + if (satisfiesOneEntry) + return MODRM_ONEENTRY; + + if (satisfiesSplitRM) + return MODRM_SPLITRM; + + if (satisfiesSplitReg) + return MODRM_SPLITREG; + + return MODRM_FULL; +} + +/// stringForDecisionType - Returns a statically-allocated string corresponding +/// to a particular decision type. +/// +/// @param dt - The decision type. +/// @return - A pointer to the statically-allocated string (e.g., +/// "MODRM_ONEENTRY" for MODRM_ONEENTRY). +static const char* stringForDecisionType(ModRMDecisionType dt) +{ +#define ENUM_ENTRY(n) case n: return #n; + switch (dt) { + default: + llvm_unreachable("Unknown decision type"); + MODRMTYPES + }; +#undef ENUM_ENTRY +} + +/// stringForModifierType - Returns a statically-allocated string corresponding +/// to an opcode modifier type. +/// +/// @param mt - The modifier type. +/// @return - A pointer to the statically-allocated string (e.g., +/// "MODIFIER_NONE" for MODIFIER_NONE). +static const char* stringForModifierType(ModifierType mt) +{ +#define ENUM_ENTRY(n) case n: return #n; + switch(mt) { + default: + llvm_unreachable("Unknown modifier type"); + MODIFIER_TYPES + }; +#undef ENUM_ENTRY +} + +DisassemblerTables::DisassemblerTables() { + unsigned i; + + for (i = 0; i < array_lengthof(Tables); i++) { + Tables[i] = new ContextDecision; + memset(Tables[i], 0, sizeof(ContextDecision)); + } + + HasConflicts = false; +} + +DisassemblerTables::~DisassemblerTables() { + unsigned i; + + for (i = 0; i < array_lengthof(Tables); i++) + delete Tables[i]; +} + +void DisassemblerTables::emitModRMDecision(raw_ostream &o1, + raw_ostream &o2, + uint32_t &i1, + uint32_t &i2, + ModRMDecision &decision) + const { + static uint64_t sTableNumber = 0; + static uint64_t sEntryNumber = 1; + ModRMDecisionType dt = getDecisionType(decision); + uint16_t index; + + if (dt == MODRM_ONEENTRY && decision.instructionIDs[0] == 0) + { + o2.indent(i2) << "{ /* ModRMDecision */" << "\n"; + i2++; + + o2.indent(i2) << stringForDecisionType(dt) << "," << "\n"; + o2.indent(i2) << 0 << " /* EmptyTable */\n"; + + i2--; + o2.indent(i2) << "}"; + return; + } + + o1 << "/* Table" << sTableNumber << " */\n"; + i1++; + + switch (dt) { + default: + llvm_unreachable("Unknown decision type"); + case MODRM_ONEENTRY: + emitOneID(o1, i1, decision.instructionIDs[0], true); + break; + case MODRM_SPLITRM: + emitOneID(o1, i1, decision.instructionIDs[0x00], true); // mod = 0b00 + emitOneID(o1, i1, decision.instructionIDs[0xc0], true); // mod = 0b11 + break; + case MODRM_SPLITREG: + for (index = 0; index < 64; index += 8) + emitOneID(o1, i1, decision.instructionIDs[index], true); + for (index = 0xc0; index < 256; index += 8) + emitOneID(o1, i1, decision.instructionIDs[index], true); + break; + case MODRM_FULL: + for (index = 0; index < 256; ++index) + emitOneID(o1, i1, decision.instructionIDs[index], true); + break; + } + + i1--; + + o2.indent(i2) << "{ /* struct ModRMDecision */" << "\n"; + i2++; + + o2.indent(i2) << stringForDecisionType(dt) << "," << "\n"; + o2.indent(i2) << sEntryNumber << " /* Table" << sTableNumber << " */\n"; + + i2--; + o2.indent(i2) << "}"; + + switch (dt) { + default: + llvm_unreachable("Unknown decision type"); + case MODRM_ONEENTRY: + sEntryNumber += 1; + break; + case MODRM_SPLITRM: + sEntryNumber += 2; + break; + case MODRM_SPLITREG: + sEntryNumber += 16; + break; + case MODRM_FULL: + sEntryNumber += 256; + break; + } + + ++sTableNumber; +} + +void DisassemblerTables::emitOpcodeDecision( + raw_ostream &o1, + raw_ostream &o2, + uint32_t &i1, + uint32_t &i2, + OpcodeDecision &decision) const { + uint16_t index; + + o2.indent(i2) << "{ /* struct OpcodeDecision */" << "\n"; + i2++; + o2.indent(i2) << "{" << "\n"; + i2++; + + for (index = 0; index < 256; ++index) { + o2.indent(i2); + + o2 << "/* 0x" << format("%02hhx", index) << " */" << "\n"; + + emitModRMDecision(o1, o2, i1, i2, decision.modRMDecisions[index]); + + if (index < 255) + o2 << ","; + + o2 << "\n"; + } + + i2--; + o2.indent(i2) << "}" << "\n"; + i2--; + o2.indent(i2) << "}" << "\n"; +} + +void DisassemblerTables::emitContextDecision( + raw_ostream &o1, + raw_ostream &o2, + uint32_t &i1, + uint32_t &i2, + ContextDecision &decision, + const char* name) const { + o2.indent(i2) << "static const struct ContextDecision " << name << " = {\n"; + i2++; + o2.indent(i2) << "{ /* opcodeDecisions */" << "\n"; + i2++; + + unsigned index; + + for (index = 0; index < IC_max; ++index) { + o2.indent(i2) << "/* "; + o2 << stringForContext((InstructionContext)index); + o2 << " */"; + o2 << "\n"; + + emitOpcodeDecision(o1, o2, i1, i2, decision.opcodeDecisions[index]); + + if (index + 1 < IC_max) + o2 << ", "; + } + + i2--; + o2.indent(i2) << "}" << "\n"; + i2--; + o2.indent(i2) << "};" << "\n"; +} + +void DisassemblerTables::emitInstructionInfo(raw_ostream &o, uint32_t &i) + const { + o.indent(i * 2) << "static const struct InstructionSpecifier "; + o << INSTRUCTIONS_STR "[" << InstructionSpecifiers.size() << "] = {\n"; + + i++; + + uint16_t numInstructions = InstructionSpecifiers.size(); + uint16_t index, operandIndex; + + for (index = 0; index < numInstructions; ++index) { + o.indent(i * 2) << "{ /* " << index << " */" << "\n"; + i++; + + o.indent(i * 2) << stringForModifierType( + (ModifierType)InstructionSpecifiers[index].modifierType); + o << "," << "\n"; + + o.indent(i * 2) << "0x"; + o << format("%02hhx", (uint16_t)InstructionSpecifiers[index].modifierBase); + o << "," << "\n"; + + o.indent(i * 2) << "{" << "\n"; + i++; + + for (operandIndex = 0; operandIndex < X86_MAX_OPERANDS; ++operandIndex) { + o.indent(i * 2) << "{ "; + o <<stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[index] + .operands[operandIndex] + .encoding); + o << ", "; + o << stringForOperandType((OperandType)InstructionSpecifiers[index] + .operands[operandIndex] + .type); + o << " }"; + + if (operandIndex < X86_MAX_OPERANDS - 1) + o << ","; + + o << "\n"; + } + + i--; + o.indent(i * 2) << "}," << "\n"; + + o.indent(i * 2) << "/* " << InstructionSpecifiers[index].name << " */"; + o << "\n"; + + i--; + o.indent(i * 2) << "}"; + + if (index + 1 < numInstructions) + o << ","; + + o << "\n"; + } + + i--; + o.indent(i * 2) << "};" << "\n"; +} + +void DisassemblerTables::emitContextTable(raw_ostream &o, uint32_t &i) const { + uint16_t index; + + o.indent(i * 2) << "static const InstructionContext " CONTEXTS_STR + "[256] = {\n"; + i++; + + for (index = 0; index < 256; ++index) { + o.indent(i * 2); + + if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_OPSIZE)) + o << "IC_VEX_L_W_OPSIZE"; + else if ((index & ATTR_VEXL) && (index & ATTR_OPSIZE)) + o << "IC_VEX_L_OPSIZE"; + else if ((index & ATTR_VEXL) && (index & ATTR_XD)) + o << "IC_VEX_L_XD"; + else if ((index & ATTR_VEXL) && (index & ATTR_XS)) + o << "IC_VEX_L_XS"; + else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_OPSIZE)) + o << "IC_VEX_W_OPSIZE"; + else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XD)) + o << "IC_VEX_W_XD"; + else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XS)) + o << "IC_VEX_W_XS"; + else if (index & ATTR_VEXL) + o << "IC_VEX_L"; + else if ((index & ATTR_VEX) && (index & ATTR_REXW)) + o << "IC_VEX_W"; + else if ((index & ATTR_VEX) && (index & ATTR_OPSIZE)) + o << "IC_VEX_OPSIZE"; + else if ((index & ATTR_VEX) && (index & ATTR_XD)) + o << "IC_VEX_XD"; + else if ((index & ATTR_VEX) && (index & ATTR_XS)) + o << "IC_VEX_XS"; + else if (index & ATTR_VEX) + o << "IC_VEX"; + else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XS)) + o << "IC_64BIT_REXW_XS"; + else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XD)) + o << "IC_64BIT_REXW_XD"; + else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && + (index & ATTR_OPSIZE)) + o << "IC_64BIT_REXW_OPSIZE"; + else if ((index & ATTR_64BIT) && (index & ATTR_XD) && (index & ATTR_OPSIZE)) + o << "IC_64BIT_XD_OPSIZE"; + else if ((index & ATTR_64BIT) && (index & ATTR_XS) && (index & ATTR_OPSIZE)) + o << "IC_64BIT_XS_OPSIZE"; + else if ((index & ATTR_64BIT) && (index & ATTR_XS)) + o << "IC_64BIT_XS"; + else if ((index & ATTR_64BIT) && (index & ATTR_XD)) + o << "IC_64BIT_XD"; + else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE)) + o << "IC_64BIT_OPSIZE"; + else if ((index & ATTR_64BIT) && (index & ATTR_ADSIZE)) + o << "IC_64BIT_ADSIZE"; + else if ((index & ATTR_64BIT) && (index & ATTR_REXW)) + o << "IC_64BIT_REXW"; + else if ((index & ATTR_64BIT)) + o << "IC_64BIT"; + else if ((index & ATTR_XS) && (index & ATTR_OPSIZE)) + o << "IC_XS_OPSIZE"; + else if ((index & ATTR_XD) && (index & ATTR_OPSIZE)) + o << "IC_XD_OPSIZE"; + else if (index & ATTR_XS) + o << "IC_XS"; + else if (index & ATTR_XD) + o << "IC_XD"; + else if (index & ATTR_OPSIZE) + o << "IC_OPSIZE"; + else if (index & ATTR_ADSIZE) + o << "IC_ADSIZE"; + else + o << "IC"; + + if (index < 255) + o << ","; + else + o << " "; + + o << " /* " << index << " */"; + + o << "\n"; + } + + i--; + o.indent(i * 2) << "};" << "\n"; +} + +void DisassemblerTables::emitContextDecisions(raw_ostream &o1, + raw_ostream &o2, + uint32_t &i1, + uint32_t &i2) + const { + emitContextDecision(o1, o2, i1, i2, *Tables[0], ONEBYTE_STR); + emitContextDecision(o1, o2, i1, i2, *Tables[1], TWOBYTE_STR); + emitContextDecision(o1, o2, i1, i2, *Tables[2], THREEBYTE38_STR); + emitContextDecision(o1, o2, i1, i2, *Tables[3], THREEBYTE3A_STR); + emitContextDecision(o1, o2, i1, i2, *Tables[4], THREEBYTEA6_STR); + emitContextDecision(o1, o2, i1, i2, *Tables[5], THREEBYTEA7_STR); +} + +void DisassemblerTables::emit(raw_ostream &o) const { + uint32_t i1 = 0; + uint32_t i2 = 0; + + std::string s1; + std::string s2; + + raw_string_ostream o1(s1); + raw_string_ostream o2(s2); + + emitInstructionInfo(o, i2); + o << "\n"; + + emitContextTable(o, i2); + o << "\n"; + + o << "static const InstrUID modRMTable[] = {\n"; + i1++; + emitEmptyTable(o1, i1); + i1--; + emitContextDecisions(o1, o2, i1, i2); + + o << o1.str(); + o << " 0x0\n"; + o << "};\n"; + o << "\n"; + o << o2.str(); + o << "\n"; + o << "\n"; +} + +void DisassemblerTables::setTableFields(ModRMDecision &decision, + const ModRMFilter &filter, + InstrUID uid, + uint8_t opcode) { + unsigned index; + + for (index = 0; index < 256; ++index) { + if (filter.accepts(index)) { + if (decision.instructionIDs[index] == uid) + continue; + + if (decision.instructionIDs[index] != 0) { + InstructionSpecifier &newInfo = + InstructionSpecifiers[uid]; + InstructionSpecifier &previousInfo = + InstructionSpecifiers[decision.instructionIDs[index]]; + + if(newInfo.filtered) + continue; // filtered instructions get lowest priority + + if(previousInfo.name == "NOOP" && (newInfo.name == "XCHG16ar" || + newInfo.name == "XCHG32ar" || + newInfo.name == "XCHG32ar64" || + newInfo.name == "XCHG64ar")) + continue; // special case for XCHG*ar and NOOP + + if (outranks(previousInfo.insnContext, newInfo.insnContext)) + continue; + + if (previousInfo.insnContext == newInfo.insnContext && + !previousInfo.filtered) { + errs() << "Error: Primary decode conflict: "; + errs() << newInfo.name << " would overwrite " << previousInfo.name; + errs() << "\n"; + errs() << "ModRM " << index << "\n"; + errs() << "Opcode " << (uint16_t)opcode << "\n"; + errs() << "Context " << stringForContext(newInfo.insnContext) << "\n"; + HasConflicts = true; + } + } + + decision.instructionIDs[index] = uid; + } + } +} + +void DisassemblerTables::setTableFields(OpcodeType type, + InstructionContext insnContext, + uint8_t opcode, + const ModRMFilter &filter, + InstrUID uid, + bool is32bit, + bool ignoresVEX_L) { + unsigned index; + + ContextDecision &decision = *Tables[type]; + + for (index = 0; index < IC_max; ++index) { + if (is32bit && inheritsFrom((InstructionContext)index, IC_64BIT)) + continue; + + if (inheritsFrom((InstructionContext)index, + InstructionSpecifiers[uid].insnContext, ignoresVEX_L)) + setTableFields(decision.opcodeDecisions[index].modRMDecisions[opcode], + filter, + uid, + opcode); + } +} diff --git a/contrib/llvm/utils/TableGen/X86DisassemblerTables.h b/contrib/llvm/utils/TableGen/X86DisassemblerTables.h new file mode 100644 index 0000000..e148cd2 --- /dev/null +++ b/contrib/llvm/utils/TableGen/X86DisassemblerTables.h @@ -0,0 +1,298 @@ +//===- X86DisassemblerTables.h - Disassembler tables ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is part of the X86 Disassembler Emitter. +// It contains the interface of the disassembler tables. +// Documentation for the disassembler emitter in general can be found in +// X86DisasemblerEmitter.h. +// +//===----------------------------------------------------------------------===// + +#ifndef X86DISASSEMBLERTABLES_H +#define X86DISASSEMBLERTABLES_H + +#include "X86DisassemblerShared.h" +#include "X86ModRMFilters.h" + +#include "llvm/Support/raw_ostream.h" + +#include <vector> + +namespace llvm { + +namespace X86Disassembler { + +/// DisassemblerTables - Encapsulates all the decode tables being generated by +/// the table emitter. Contains functions to populate the tables as well as +/// to emit them as hierarchical C structures suitable for consumption by the +/// runtime. +class DisassemblerTables { +private: + /// The decoder tables. There is one for each opcode type: + /// [0] one-byte opcodes + /// [1] two-byte opcodes of the form 0f __ + /// [2] three-byte opcodes of the form 0f 38 __ + /// [3] three-byte opcodes of the form 0f 3a __ + /// [4] three-byte opcodes of the form 0f a6 __ + /// [5] three-byte opcodes of the form 0f a7 __ + ContextDecision* Tables[6]; + + /// The instruction information table + std::vector<InstructionSpecifier> InstructionSpecifiers; + + /// True if there are primary decode conflicts in the instruction set + bool HasConflicts; + + /// emitOneID - Emits a table entry for a single instruction entry, at the + /// innermost level of the structure hierarchy. The entry is printed out + /// in the format "nnnn, /* MNEMONIC */" where nnnn is the ID in decimal, + /// the comma is printed if addComma is true, and the menonic is the name + /// of the instruction as listed in the LLVM tables. + /// + /// @param o - The output stream to print the entry on. + /// @param i - The indentation level for o. + /// @param id - The unique ID of the instruction to print. + /// @param addComma - Whether or not to print a comma after the ID. True if + /// additional items will follow. + void emitOneID(raw_ostream &o, + uint32_t &i, + InstrUID id, + bool addComma) const; + + /// emitModRMDecision - Emits a table of entries corresponding to a single + /// ModR/M decision. Compacts the ModR/M decision if possible. ModR/M + /// decisions are printed as: + /// + /// { /* struct ModRMDecision */ + /// TYPE, + /// modRMTablennnn + /// } + /// + /// where nnnn is a unique ID for the corresponding table of IDs. + /// TYPE indicates whether the table has one entry that is the same + /// regardless of ModR/M byte, two entries - one for bytes 0x00-0xbf and one + /// for bytes 0xc0-0xff -, or 256 entries, one for each possible byte. + /// nnnn is the number of a table for looking up these values. The tables + /// are written separately so that tables consisting entirely of zeros will + /// not be duplicated. (These all have the name modRMEmptyTable.) A table + /// is printed as: + /// + /// InstrUID modRMTablennnn[k] = { + /// nnnn, /* MNEMONIC */ + /// ... + /// nnnn /* MNEMONIC */ + /// }; + /// + /// @param o1 - The output stream to print the ID table to. + /// @param o2 - The output stream to print the decision structure to. + /// @param i1 - The indentation level to use with stream o1. + /// @param i2 - The indentation level to use with stream o2. + /// @param decision - The ModR/M decision to emit. This decision has 256 + /// entries - emitModRMDecision decides how to compact it. + void emitModRMDecision(raw_ostream &o1, + raw_ostream &o2, + uint32_t &i1, + uint32_t &i2, + ModRMDecision &decision) const; + + /// emitOpcodeDecision - Emits an OpcodeDecision and all its subsidiary ModR/M + /// decisions. An OpcodeDecision is printed as: + /// + /// { /* struct OpcodeDecision */ + /// /* 0x00 */ + /// { /* struct ModRMDecision */ + /// ... + /// } + /// ... + /// } + /// + /// where the ModRMDecision structure is printed as described in the + /// documentation for emitModRMDecision(). emitOpcodeDecision() passes on a + /// stream and indent level for the UID tables generated by + /// emitModRMDecision(), but does not use them itself. + /// + /// @param o1 - The output stream to print the ID tables generated by + /// emitModRMDecision() to. + /// @param o2 - The output stream for the decision structure itself. + /// @param i1 - The indent level to use with stream o1. + /// @param i2 - The indent level to use with stream o2. + /// @param decision - The OpcodeDecision to emit along with its subsidiary + /// structures. + void emitOpcodeDecision(raw_ostream &o1, + raw_ostream &o2, + uint32_t &i1, + uint32_t &i2, + OpcodeDecision &decision) const; + + /// emitContextDecision - Emits a ContextDecision and all its subsidiary + /// Opcode and ModRMDecisions. A ContextDecision is printed as: + /// + /// struct ContextDecision NAME = { + /// { /* OpcodeDecisions */ + /// /* IC */ + /// { /* struct OpcodeDecision */ + /// ... + /// }, + /// ... + /// } + /// } + /// + /// NAME is the name of the ContextDecision (typically one of the four names + /// ONEBYTE_SYM, TWOBYTE_SYM, THREEBYTE38_SYM, THREEBYTE3A_SYM, + /// THREEBYTEA6_SYM, and THREEBYTEA7_SYM from + /// X86DisassemblerDecoderCommon.h). + /// IC is one of the contexts in InstructionContext. There is an opcode + /// decision for each possible context. + /// The OpcodeDecision structures are printed as described in the + /// documentation for emitOpcodeDecision. + /// + /// @param o1 - The output stream to print the ID tables generated by + /// emitModRMDecision() to. + /// @param o2 - The output stream to print the decision structure to. + /// @param i1 - The indent level to use with stream o1. + /// @param i2 - The indent level to use with stream o2. + /// @param decision - The ContextDecision to emit along with its subsidiary + /// structures. + /// @param name - The name for the ContextDecision. + void emitContextDecision(raw_ostream &o1, + raw_ostream &o2, + uint32_t &i1, + uint32_t &i2, + ContextDecision &decision, + const char* name) const; + + /// emitInstructionInfo - Prints the instruction specifier table, which has + /// one entry for each instruction, and contains name and operand + /// information. This table is printed as: + /// + /// struct InstructionSpecifier CONTEXTS_SYM[k] = { + /// { + /// /* nnnn */ + /// "MNEMONIC", + /// 0xnn, + /// { + /// { + /// ENCODING, + /// TYPE + /// }, + /// ... + /// } + /// }, + /// }; + /// + /// k is the total number of instructions. + /// nnnn is the ID of the current instruction (0-based). This table + /// includes entries for non-instructions like PHINODE. + /// 0xnn is the lowest possible opcode for the current instruction, used for + /// AddRegFrm instructions to compute the operand's value. + /// ENCODING and TYPE describe the encoding and type for a single operand. + /// + /// @param o - The output stream to which the instruction table should be + /// written. + /// @param i - The indent level for use with the stream. + void emitInstructionInfo(raw_ostream &o, uint32_t &i) const; + + /// emitContextTable - Prints the table that is used to translate from an + /// instruction attribute mask to an instruction context. This table is + /// printed as: + /// + /// InstructionContext CONTEXTS_STR[256] = { + /// IC, /* 0x00 */ + /// ... + /// }; + /// + /// IC is the context corresponding to the mask 0x00, and there are 256 + /// possible masks. + /// + /// @param o - The output stream to which the context table should be written. + /// @param i - The indent level for use with the stream. + void emitContextTable(raw_ostream &o, uint32_t &i) const; + + /// emitContextDecisions - Prints all four ContextDecision structures using + /// emitContextDecision(). + /// + /// @param o1 - The output stream to print the ID tables generated by + /// emitModRMDecision() to. + /// @param o2 - The output stream to print the decision structures to. + /// @param i1 - The indent level to use with stream o1. + /// @param i2 - The indent level to use with stream o2. + void emitContextDecisions(raw_ostream &o1, + raw_ostream &o2, + uint32_t &i1, + uint32_t &i2) const; + + /// setTableFields - Uses a ModRMFilter to set the appropriate entries in a + /// ModRMDecision to refer to a particular instruction ID. + /// + /// @param decision - The ModRMDecision to populate. + /// @param filter - The filter to use in deciding which entries to populate. + /// @param uid - The unique ID to set matching entries to. + /// @param opcode - The opcode of the instruction, for error reporting. + void setTableFields(ModRMDecision &decision, + const ModRMFilter &filter, + InstrUID uid, + uint8_t opcode); +public: + /// Constructor - Allocates space for the class decisions and clears them. + DisassemblerTables(); + + ~DisassemblerTables(); + + /// emit - Emits the instruction table, context table, and class decisions. + /// + /// @param o - The output stream to print the tables to. + void emit(raw_ostream &o) const; + + /// setTableFields - Uses the opcode type, instruction context, opcode, and a + /// ModRMFilter as criteria to set a particular set of entries in the + /// decode tables to point to a specific uid. + /// + /// @param type - The opcode type (ONEBYTE, TWOBYTE, etc.) + /// @param insnContext - The context to use (IC, IC_64BIT, etc.) + /// @param opcode - The last byte of the opcode (not counting any escape + /// or extended opcodes). + /// @param filter - The ModRMFilter that decides which ModR/M byte values + /// correspond to the desired instruction. + /// @param uid - The unique ID of the instruction. + /// @param is32bit - Instructon is only 32-bit + /// @param ignoresVEX_L - Instruction ignores VEX.L + void setTableFields(OpcodeType type, + InstructionContext insnContext, + uint8_t opcode, + const ModRMFilter &filter, + InstrUID uid, + bool is32bit, + bool ignoresVEX_L); + + /// specForUID - Returns the instruction specifier for a given unique + /// instruction ID. Used when resolving collisions. + /// + /// @param uid - The unique ID of the instruction. + /// @return - A reference to the instruction specifier. + InstructionSpecifier& specForUID(InstrUID uid) { + if (uid >= InstructionSpecifiers.size()) + InstructionSpecifiers.resize(uid + 1); + + return InstructionSpecifiers[uid]; + } + + // hasConflicts - Reports whether there were primary decode conflicts + // from any instructions added to the tables. + // @return - true if there were; false otherwise. + + bool hasConflicts() { + return HasConflicts; + } +}; + +} // namespace X86Disassembler + +} // namespace llvm + +#endif diff --git a/contrib/llvm/utils/TableGen/X86ModRMFilters.cpp b/contrib/llvm/utils/TableGen/X86ModRMFilters.cpp new file mode 100644 index 0000000..7166fe0 --- /dev/null +++ b/contrib/llvm/utils/TableGen/X86ModRMFilters.cpp @@ -0,0 +1,26 @@ +//===- X86ModRMFilters.cpp - Disassembler ModR/M filterss -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "X86ModRMFilters.h" + +using namespace llvm::X86Disassembler; + +void ModRMFilter::anchor() { } + +void DumbFilter::anchor() { } + +void ModFilter::anchor() { } + +void EscapeFilter::anchor() { } + +void AddRegEscapeFilter::anchor() { } + +void ExtendedFilter::anchor() { } + +void ExactFilter::anchor() { } diff --git a/contrib/llvm/utils/TableGen/X86ModRMFilters.h b/contrib/llvm/utils/TableGen/X86ModRMFilters.h new file mode 100644 index 0000000..19fecbc --- /dev/null +++ b/contrib/llvm/utils/TableGen/X86ModRMFilters.h @@ -0,0 +1,198 @@ +//===- X86ModRMFilters.h - Disassembler ModR/M filterss ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is part of the X86 Disassembler Emitter. +// It contains ModR/M filters that determine which values of the ModR/M byte +// are valid for a partiuclar instruction. +// Documentation for the disassembler emitter in general can be found in +// X86DisasemblerEmitter.h. +// +//===----------------------------------------------------------------------===// + +#ifndef X86MODRMFILTERS_H +#define X86MODRMFILTERS_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +namespace X86Disassembler { + +/// ModRMFilter - Abstract base class for clases that recognize patterns in +/// ModR/M bytes. +class ModRMFilter { + virtual void anchor(); +public: + /// Destructor - Override as necessary. + virtual ~ModRMFilter() { } + + /// isDumb - Indicates whether this filter returns the same value for + /// any value of the ModR/M byte. + /// + /// @result - True if the filter returns the same value for any ModR/M + /// byte; false if not. + virtual bool isDumb() const { return false; } + + /// accepts - Indicates whether the filter accepts a particular ModR/M + /// byte value. + /// + /// @result - True if the filter accepts the ModR/M byte; false if not. + virtual bool accepts(uint8_t modRM) const = 0; +}; + +/// DumbFilter - Accepts any ModR/M byte. Used for instructions that do not +/// require a ModR/M byte or instructions where the entire ModR/M byte is used +/// for operands. +class DumbFilter : public ModRMFilter { + virtual void anchor(); +public: + bool isDumb() const { + return true; + } + + bool accepts(uint8_t modRM) const { + return true; + } +}; + +/// ModFilter - Filters based on the mod bits [bits 7-6] of the ModR/M byte. +/// Some instructions are classified based on whether they are 11 or anything +/// else. This filter performs that classification. +class ModFilter : public ModRMFilter { + virtual void anchor(); + bool R; +public: + /// Constructor + /// + /// @r - True if the mod bits of the ModR/M byte must be 11; false + /// otherwise. The name r derives from the fact that the mod + /// bits indicate whether the R/M bits [bits 2-0] signify a + /// register or a memory operand. + ModFilter(bool r) : + ModRMFilter(), + R(r) { + } + + bool accepts(uint8_t modRM) const { + if (R == ((modRM & 0xc0) == 0xc0)) + return true; + else + return false; + } +}; + +/// EscapeFilter - Filters escape opcodes, which are classified in two ways. If +/// the ModR/M byte is between 0xc0 and 0xff, then there is one slot for each +/// possible value. Otherwise, there is one instruction for each value of the +/// nnn field [bits 5-3], known elsewhere as the reg field. +class EscapeFilter : public ModRMFilter { + virtual void anchor(); + bool C0_FF; + uint8_t NNN_or_ModRM; +public: + /// Constructor + /// + /// @c0_ff - True if the ModR/M byte must fall between 0xc0 and 0xff; + /// false otherwise. + /// @nnn_or_modRM - If c0_ff is true, the required value of the entire ModR/M + /// byte. If c0_ff is false, the required value of the nnn + /// field. + EscapeFilter(bool c0_ff, uint8_t nnn_or_modRM) : + ModRMFilter(), + C0_FF(c0_ff), + NNN_or_ModRM(nnn_or_modRM) { + } + + bool accepts(uint8_t modRM) const { + if ((C0_FF && modRM >= 0xc0 && (modRM == NNN_or_ModRM)) || + (!C0_FF && modRM < 0xc0 && ((modRM & 0x38) >> 3) == NNN_or_ModRM)) + return true; + else + return false; + } +}; + +/// AddRegEscapeFilter - Some escape opcodes have one of the register operands +/// added to the ModR/M byte, meaning that a range of eight ModR/M values +/// maps to a single instruction. Such instructions require the ModR/M byte +/// to fall between 0xc0 and 0xff. +class AddRegEscapeFilter : public ModRMFilter { + virtual void anchor(); + uint8_t ModRM; +public: + /// Constructor + /// + /// @modRM - The value of the ModR/M byte when the register operand + /// refers to the first register in the register set. + AddRegEscapeFilter(uint8_t modRM) : ModRM(modRM) { + } + + bool accepts(uint8_t modRM) const { + if (modRM >= ModRM && modRM < ModRM + 8) + return true; + else + return false; + } +}; + +/// ExtendedFilter - Extended opcodes are classified based on the value of the +/// mod field [bits 7-6] and the value of the nnn field [bits 5-3]. +class ExtendedFilter : public ModRMFilter { + virtual void anchor(); + bool R; + uint8_t NNN; +public: + /// Constructor + /// + /// @r - True if the mod field must be set to 11; false otherwise. + /// The name is explained at ModFilter. + /// @nnn - The required value of the nnn field. + ExtendedFilter(bool r, uint8_t nnn) : + ModRMFilter(), + R(r), + NNN(nnn) { + } + + bool accepts(uint8_t modRM) const { + if (((R && ((modRM & 0xc0) == 0xc0)) || + (!R && ((modRM & 0xc0) != 0xc0))) && + (((modRM & 0x38) >> 3) == NNN)) + return true; + else + return false; + } +}; + +/// ExactFilter - The occasional extended opcode (such as VMCALL or MONITOR) +/// requires the ModR/M byte to have a specific value. +class ExactFilter : public ModRMFilter { + virtual void anchor(); + uint8_t ModRM; +public: + /// Constructor + /// + /// @modRM - The required value of the full ModR/M byte. + ExactFilter(uint8_t modRM) : + ModRMFilter(), + ModRM(modRM) { + } + + bool accepts(uint8_t modRM) const { + if (ModRM == modRM) + return true; + else + return false; + } +}; + +} // namespace X86Disassembler + +} // namespace llvm + +#endif diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp new file mode 100644 index 0000000..6a01cce --- /dev/null +++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp @@ -0,0 +1,1293 @@ +//===- X86RecognizableInstr.cpp - Disassembler instruction spec --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is part of the X86 Disassembler Emitter. +// It contains the implementation of a single recognizable instruction. +// Documentation for the disassembler emitter in general can be found in +// X86DisasemblerEmitter.h. +// +//===----------------------------------------------------------------------===// + +#include "X86DisassemblerShared.h" +#include "X86RecognizableInstr.h" +#include "X86ModRMFilters.h" + +#include "llvm/Support/ErrorHandling.h" + +#include <string> + +using namespace llvm; + +#define MRM_MAPPING \ + MAP(C1, 33) \ + MAP(C2, 34) \ + MAP(C3, 35) \ + MAP(C4, 36) \ + MAP(C8, 37) \ + MAP(C9, 38) \ + MAP(E8, 39) \ + MAP(F0, 40) \ + MAP(F8, 41) \ + MAP(F9, 42) \ + MAP(D0, 45) \ + MAP(D1, 46) \ + MAP(D4, 47) \ + MAP(D8, 48) \ + MAP(D9, 49) \ + MAP(DA, 50) \ + MAP(DB, 51) \ + MAP(DC, 52) \ + MAP(DD, 53) \ + MAP(DE, 54) \ + MAP(DF, 55) + +// A clone of X86 since we can't depend on something that is generated. +namespace X86Local { + enum { + Pseudo = 0, + RawFrm = 1, + AddRegFrm = 2, + MRMDestReg = 3, + MRMDestMem = 4, + MRMSrcReg = 5, + MRMSrcMem = 6, + MRM0r = 16, MRM1r = 17, MRM2r = 18, MRM3r = 19, + MRM4r = 20, MRM5r = 21, MRM6r = 22, MRM7r = 23, + MRM0m = 24, MRM1m = 25, MRM2m = 26, MRM3m = 27, + MRM4m = 28, MRM5m = 29, MRM6m = 30, MRM7m = 31, + MRMInitReg = 32, +#define MAP(from, to) MRM_##from = to, + MRM_MAPPING +#undef MAP + RawFrmImm8 = 43, + RawFrmImm16 = 44, + lastMRM + }; + + enum { + TB = 1, + REP = 2, + D8 = 3, D9 = 4, DA = 5, DB = 6, + DC = 7, DD = 8, DE = 9, DF = 10, + XD = 11, XS = 12, + T8 = 13, P_TA = 14, + A6 = 15, A7 = 16, T8XD = 17, T8XS = 18, TAXD = 19 + }; +} + +// If rows are added to the opcode extension tables, then corresponding entries +// must be added here. +// +// If the row corresponds to a single byte (i.e., 8f), then add an entry for +// that byte to ONE_BYTE_EXTENSION_TABLES. +// +// If the row corresponds to two bytes where the first is 0f, add an entry for +// the second byte to TWO_BYTE_EXTENSION_TABLES. +// +// If the row corresponds to some other set of bytes, you will need to modify +// the code in RecognizableInstr::emitDecodePath() as well, and add new prefixes +// to the X86 TD files, except in two cases: if the first two bytes of such a +// new combination are 0f 38 or 0f 3a, you just have to add maps called +// THREE_BYTE_38_EXTENSION_TABLES and THREE_BYTE_3A_EXTENSION_TABLES and add a +// switch(Opcode) just below the case X86Local::T8: or case X86Local::TA: line +// in RecognizableInstr::emitDecodePath(). + +#define ONE_BYTE_EXTENSION_TABLES \ + EXTENSION_TABLE(80) \ + EXTENSION_TABLE(81) \ + EXTENSION_TABLE(82) \ + EXTENSION_TABLE(83) \ + EXTENSION_TABLE(8f) \ + EXTENSION_TABLE(c0) \ + EXTENSION_TABLE(c1) \ + EXTENSION_TABLE(c6) \ + EXTENSION_TABLE(c7) \ + EXTENSION_TABLE(d0) \ + EXTENSION_TABLE(d1) \ + EXTENSION_TABLE(d2) \ + EXTENSION_TABLE(d3) \ + EXTENSION_TABLE(f6) \ + EXTENSION_TABLE(f7) \ + EXTENSION_TABLE(fe) \ + EXTENSION_TABLE(ff) + +#define TWO_BYTE_EXTENSION_TABLES \ + EXTENSION_TABLE(00) \ + EXTENSION_TABLE(01) \ + EXTENSION_TABLE(18) \ + EXTENSION_TABLE(71) \ + EXTENSION_TABLE(72) \ + EXTENSION_TABLE(73) \ + EXTENSION_TABLE(ae) \ + EXTENSION_TABLE(ba) \ + EXTENSION_TABLE(c7) + +#define THREE_BYTE_38_EXTENSION_TABLES \ + EXTENSION_TABLE(F3) + +using namespace X86Disassembler; + +/// needsModRMForDecode - Indicates whether a particular instruction requires a +/// ModR/M byte for the instruction to be properly decoded. For example, a +/// MRMDestReg instruction needs the Mod field in the ModR/M byte to be set to +/// 0b11. +/// +/// @param form - The form of the instruction. +/// @return - true if the form implies that a ModR/M byte is required, false +/// otherwise. +static bool needsModRMForDecode(uint8_t form) { + if (form == X86Local::MRMDestReg || + form == X86Local::MRMDestMem || + form == X86Local::MRMSrcReg || + form == X86Local::MRMSrcMem || + (form >= X86Local::MRM0r && form <= X86Local::MRM7r) || + (form >= X86Local::MRM0m && form <= X86Local::MRM7m)) + return true; + else + return false; +} + +/// isRegFormat - Indicates whether a particular form requires the Mod field of +/// the ModR/M byte to be 0b11. +/// +/// @param form - The form of the instruction. +/// @return - true if the form implies that Mod must be 0b11, false +/// otherwise. +static bool isRegFormat(uint8_t form) { + if (form == X86Local::MRMDestReg || + form == X86Local::MRMSrcReg || + (form >= X86Local::MRM0r && form <= X86Local::MRM7r)) + return true; + else + return false; +} + +/// byteFromBitsInit - Extracts a value at most 8 bits in width from a BitsInit. +/// Useful for switch statements and the like. +/// +/// @param init - A reference to the BitsInit to be decoded. +/// @return - The field, with the first bit in the BitsInit as the lowest +/// order bit. +static uint8_t byteFromBitsInit(BitsInit &init) { + int width = init.getNumBits(); + + assert(width <= 8 && "Field is too large for uint8_t!"); + + int index; + uint8_t mask = 0x01; + + uint8_t ret = 0; + + for (index = 0; index < width; index++) { + if (static_cast<BitInit*>(init.getBit(index))->getValue()) + ret |= mask; + + mask <<= 1; + } + + return ret; +} + +/// byteFromRec - Extract a value at most 8 bits in with from a Record given the +/// name of the field. +/// +/// @param rec - The record from which to extract the value. +/// @param name - The name of the field in the record. +/// @return - The field, as translated by byteFromBitsInit(). +static uint8_t byteFromRec(const Record* rec, const std::string &name) { + BitsInit* bits = rec->getValueAsBitsInit(name); + return byteFromBitsInit(*bits); +} + +RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, + const CodeGenInstruction &insn, + InstrUID uid) { + UID = uid; + + Rec = insn.TheDef; + Name = Rec->getName(); + Spec = &tables.specForUID(UID); + + if (!Rec->isSubClassOf("X86Inst")) { + ShouldBeEmitted = false; + return; + } + + Prefix = byteFromRec(Rec, "Prefix"); + Opcode = byteFromRec(Rec, "Opcode"); + Form = byteFromRec(Rec, "FormBits"); + SegOvr = byteFromRec(Rec, "SegOvrBits"); + + HasOpSizePrefix = Rec->getValueAsBit("hasOpSizePrefix"); + HasAdSizePrefix = Rec->getValueAsBit("hasAdSizePrefix"); + HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix"); + HasVEXPrefix = Rec->getValueAsBit("hasVEXPrefix"); + HasVEX_4VPrefix = Rec->getValueAsBit("hasVEX_4VPrefix"); + HasVEX_4VOp3Prefix = Rec->getValueAsBit("hasVEX_4VOp3Prefix"); + HasVEX_WPrefix = Rec->getValueAsBit("hasVEX_WPrefix"); + HasMemOp4Prefix = Rec->getValueAsBit("hasMemOp4Prefix"); + IgnoresVEX_L = Rec->getValueAsBit("ignoresVEX_L"); + HasLockPrefix = Rec->getValueAsBit("hasLockPrefix"); + IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly"); + + Name = Rec->getName(); + AsmString = Rec->getValueAsString("AsmString"); + + Operands = &insn.Operands.OperandList; + + IsSSE = (HasOpSizePrefix && (Name.find("16") == Name.npos)) || + (Name.find("CRC32") != Name.npos); + HasFROperands = hasFROperands(); + HasVEX_LPrefix = has256BitOperands() || Rec->getValueAsBit("hasVEX_L"); + + // Check for 64-bit inst which does not require REX + Is32Bit = false; + Is64Bit = false; + // FIXME: Is there some better way to check for In64BitMode? + std::vector<Record*> Predicates = Rec->getValueAsListOfDefs("Predicates"); + for (unsigned i = 0, e = Predicates.size(); i != e; ++i) { + if (Predicates[i]->getName().find("32Bit") != Name.npos) { + Is32Bit = true; + break; + } + if (Predicates[i]->getName().find("64Bit") != Name.npos) { + Is64Bit = true; + break; + } + } + // FIXME: These instructions aren't marked as 64-bit in any way + Is64Bit |= Rec->getName() == "JMP64pcrel32" || + Rec->getName() == "MASKMOVDQU64" || + Rec->getName() == "POPFS64" || + Rec->getName() == "POPGS64" || + Rec->getName() == "PUSHFS64" || + Rec->getName() == "PUSHGS64" || + Rec->getName() == "REX64_PREFIX" || + Rec->getName().find("MOV64") != Name.npos || + Rec->getName().find("PUSH64") != Name.npos || + Rec->getName().find("POP64") != Name.npos; + + ShouldBeEmitted = true; +} + +void RecognizableInstr::processInstr(DisassemblerTables &tables, + const CodeGenInstruction &insn, + InstrUID uid) +{ + // Ignore "asm parser only" instructions. + if (insn.TheDef->getValueAsBit("isAsmParserOnly")) + return; + + RecognizableInstr recogInstr(tables, insn, uid); + + recogInstr.emitInstructionSpecifier(tables); + + if (recogInstr.shouldBeEmitted()) + recogInstr.emitDecodePath(tables); +} + +InstructionContext RecognizableInstr::insnContext() const { + InstructionContext insnContext; + + if (HasVEX_4VPrefix || HasVEX_4VOp3Prefix|| HasVEXPrefix) { + if (HasVEX_LPrefix && HasVEX_WPrefix) { + if (HasOpSizePrefix) + insnContext = IC_VEX_L_W_OPSIZE; + else + llvm_unreachable("Don't support VEX.L and VEX.W together"); + } else if (HasOpSizePrefix && HasVEX_LPrefix) + insnContext = IC_VEX_L_OPSIZE; + else if (HasOpSizePrefix && HasVEX_WPrefix) + insnContext = IC_VEX_W_OPSIZE; + else if (HasOpSizePrefix) + insnContext = IC_VEX_OPSIZE; + else if (HasVEX_LPrefix && + (Prefix == X86Local::XS || Prefix == X86Local::T8XS)) + insnContext = IC_VEX_L_XS; + else if (HasVEX_LPrefix && (Prefix == X86Local::XD || + Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD)) + insnContext = IC_VEX_L_XD; + else if (HasVEX_WPrefix && + (Prefix == X86Local::XS || Prefix == X86Local::T8XS)) + insnContext = IC_VEX_W_XS; + else if (HasVEX_WPrefix && (Prefix == X86Local::XD || + Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD)) + insnContext = IC_VEX_W_XD; + else if (HasVEX_WPrefix) + insnContext = IC_VEX_W; + else if (HasVEX_LPrefix) + insnContext = IC_VEX_L; + else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD) + insnContext = IC_VEX_XD; + else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS) + insnContext = IC_VEX_XS; + else + insnContext = IC_VEX; + } else if (Is64Bit || HasREX_WPrefix) { + if (HasREX_WPrefix && HasOpSizePrefix) + insnContext = IC_64BIT_REXW_OPSIZE; + else if (HasOpSizePrefix && (Prefix == X86Local::XD || + Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD)) + insnContext = IC_64BIT_XD_OPSIZE; + else if (HasOpSizePrefix && + (Prefix == X86Local::XS || Prefix == X86Local::T8XS)) + insnContext = IC_64BIT_XS_OPSIZE; + else if (HasOpSizePrefix) + insnContext = IC_64BIT_OPSIZE; + else if (HasAdSizePrefix) + insnContext = IC_64BIT_ADSIZE; + else if (HasREX_WPrefix && + (Prefix == X86Local::XS || Prefix == X86Local::T8XS)) + insnContext = IC_64BIT_REXW_XS; + else if (HasREX_WPrefix && (Prefix == X86Local::XD || + Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD)) + insnContext = IC_64BIT_REXW_XD; + else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD) + insnContext = IC_64BIT_XD; + else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS) + insnContext = IC_64BIT_XS; + else if (HasREX_WPrefix) + insnContext = IC_64BIT_REXW; + else + insnContext = IC_64BIT; + } else { + if (HasOpSizePrefix && (Prefix == X86Local::XD || + Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD)) + insnContext = IC_XD_OPSIZE; + else if (HasOpSizePrefix && + (Prefix == X86Local::XS || Prefix == X86Local::T8XS)) + insnContext = IC_XS_OPSIZE; + else if (HasOpSizePrefix) + insnContext = IC_OPSIZE; + else if (HasAdSizePrefix) + insnContext = IC_ADSIZE; + else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || + Prefix == X86Local::TAXD) + insnContext = IC_XD; + else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS || + Prefix == X86Local::REP) + insnContext = IC_XS; + else + insnContext = IC; + } + + return insnContext; +} + +RecognizableInstr::filter_ret RecognizableInstr::filter() const { + /////////////////// + // FILTER_STRONG + // + + // Filter out intrinsics + + if (!Rec->isSubClassOf("X86Inst")) + return FILTER_STRONG; + + if (Form == X86Local::Pseudo || + (IsCodeGenOnly && Name.find("_REV") == Name.npos)) + return FILTER_STRONG; + + if (Form == X86Local::MRMInitReg) + return FILTER_STRONG; + + + // Filter out artificial instructions but leave in the LOCK_PREFIX so it is + // printed as a separate "instruction". + + if (Name.find("_Int") != Name.npos || + Name.find("Int_") != Name.npos || + Name.find("_NOREX") != Name.npos || + Name.find("2SDL") != Name.npos) + return FILTER_STRONG; + + // Filter out instructions with segment override prefixes. + // They're too messy to handle now and we'll special case them if needed. + + if (SegOvr) + return FILTER_STRONG; + + // Filter out instructions that can't be printed. + + if (AsmString.size() == 0) + return FILTER_STRONG; + + // Filter out instructions with subreg operands. + + if (AsmString.find("subreg") != AsmString.npos) + return FILTER_STRONG; + + ///////////////// + // FILTER_WEAK + // + + + // Filter out instructions with a LOCK prefix; + // prefer forms that do not have the prefix + if (HasLockPrefix) + return FILTER_WEAK; + + // Filter out alternate forms of AVX instructions + if (Name.find("_alt") != Name.npos || + Name.find("XrYr") != Name.npos || + (Name.find("r64r") != Name.npos && Name.find("r64r64") == Name.npos) || + Name.find("_64mr") != Name.npos || + Name.find("Xrr") != Name.npos || + Name.find("rr64") != Name.npos) + return FILTER_WEAK; + + // Special cases. + + if (Name.find("PCMPISTRI") != Name.npos && Name != "PCMPISTRI") + return FILTER_WEAK; + if (Name.find("PCMPESTRI") != Name.npos && Name != "PCMPESTRI") + return FILTER_WEAK; + + if (Name.find("MOV") != Name.npos && Name.find("r0") != Name.npos) + return FILTER_WEAK; + if (Name.find("MOVZ") != Name.npos && Name.find("MOVZX") == Name.npos) + return FILTER_WEAK; + if (Name.find("Fs") != Name.npos) + return FILTER_WEAK; + if (Name == "PUSH64i16" || + Name == "MOVPQI2QImr" || + Name == "VMOVPQI2QImr" || + Name == "MMX_MOVD64rrv164" || + Name == "MOV64ri64i32" || + Name == "VMASKMOVDQU64" || + Name == "VEXTRACTPSrr64" || + Name == "VMOVQd64rr" || + Name == "VMOVQs64rr") + return FILTER_WEAK; + + if (HasFROperands && Name.find("MOV") != Name.npos && + ((Name.find("2") != Name.npos && Name.find("32") == Name.npos) || + (Name.find("to") != Name.npos))) + return FILTER_WEAK; + + return FILTER_NORMAL; +} + +bool RecognizableInstr::hasFROperands() const { + const std::vector<CGIOperandList::OperandInfo> &OperandList = *Operands; + unsigned numOperands = OperandList.size(); + + for (unsigned operandIndex = 0; operandIndex < numOperands; ++operandIndex) { + const std::string &recName = OperandList[operandIndex].Rec->getName(); + + if (recName.find("FR") != recName.npos) + return true; + } + return false; +} + +bool RecognizableInstr::has256BitOperands() const { + const std::vector<CGIOperandList::OperandInfo> &OperandList = *Operands; + unsigned numOperands = OperandList.size(); + + for (unsigned operandIndex = 0; operandIndex < numOperands; ++operandIndex) { + const std::string &recName = OperandList[operandIndex].Rec->getName(); + + if (!recName.compare("VR256") || !recName.compare("f256mem")) { + return true; + } + } + return false; +} + +void RecognizableInstr::handleOperand( + bool optional, + unsigned &operandIndex, + unsigned &physicalOperandIndex, + unsigned &numPhysicalOperands, + unsigned *operandMapping, + OperandEncoding (*encodingFromString)(const std::string&, bool hasOpSizePrefix)) { + if (optional) { + if (physicalOperandIndex >= numPhysicalOperands) + return; + } else { + assert(physicalOperandIndex < numPhysicalOperands); + } + + while (operandMapping[operandIndex] != operandIndex) { + Spec->operands[operandIndex].encoding = ENCODING_DUP; + Spec->operands[operandIndex].type = + (OperandType)(TYPE_DUP0 + operandMapping[operandIndex]); + ++operandIndex; + } + + const std::string &typeName = (*Operands)[operandIndex].Rec->getName(); + + Spec->operands[operandIndex].encoding = encodingFromString(typeName, + HasOpSizePrefix); + Spec->operands[operandIndex].type = typeFromString(typeName, + IsSSE, + HasREX_WPrefix, + HasOpSizePrefix); + + ++operandIndex; + ++physicalOperandIndex; +} + +void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { + Spec->name = Name; + + if (!Rec->isSubClassOf("X86Inst")) + return; + + switch (filter()) { + case FILTER_WEAK: + Spec->filtered = true; + break; + case FILTER_STRONG: + ShouldBeEmitted = false; + return; + case FILTER_NORMAL: + break; + } + + Spec->insnContext = insnContext(); + + const std::vector<CGIOperandList::OperandInfo> &OperandList = *Operands; + + unsigned operandIndex; + unsigned numOperands = OperandList.size(); + unsigned numPhysicalOperands = 0; + + // operandMapping maps from operands in OperandList to their originals. + // If operandMapping[i] != i, then the entry is a duplicate. + unsigned operandMapping[X86_MAX_OPERANDS]; + + bool hasFROperands = false; + + assert(numOperands <= X86_MAX_OPERANDS && "X86_MAX_OPERANDS is not large enough"); + + for (operandIndex = 0; operandIndex < numOperands; ++operandIndex) { + if (OperandList[operandIndex].Constraints.size()) { + const CGIOperandList::ConstraintInfo &Constraint = + OperandList[operandIndex].Constraints[0]; + if (Constraint.isTied()) { + operandMapping[operandIndex] = Constraint.getTiedOperand(); + } else { + ++numPhysicalOperands; + operandMapping[operandIndex] = operandIndex; + } + } else { + ++numPhysicalOperands; + operandMapping[operandIndex] = operandIndex; + } + + const std::string &recName = OperandList[operandIndex].Rec->getName(); + + if (recName.find("FR") != recName.npos) + hasFROperands = true; + } + + if (hasFROperands && Name.find("MOV") != Name.npos && + ((Name.find("2") != Name.npos && Name.find("32") == Name.npos) || + (Name.find("to") != Name.npos))) + ShouldBeEmitted = false; + + if (!ShouldBeEmitted) + return; + +#define HANDLE_OPERAND(class) \ + handleOperand(false, \ + operandIndex, \ + physicalOperandIndex, \ + numPhysicalOperands, \ + operandMapping, \ + class##EncodingFromString); + +#define HANDLE_OPTIONAL(class) \ + handleOperand(true, \ + operandIndex, \ + physicalOperandIndex, \ + numPhysicalOperands, \ + operandMapping, \ + class##EncodingFromString); + + // operandIndex should always be < numOperands + operandIndex = 0; + // physicalOperandIndex should always be < numPhysicalOperands + unsigned physicalOperandIndex = 0; + + switch (Form) { + case X86Local::RawFrm: + // Operand 1 (optional) is an address or immediate. + // Operand 2 (optional) is an immediate. + assert(numPhysicalOperands <= 2 && + "Unexpected number of operands for RawFrm"); + HANDLE_OPTIONAL(relocation) + HANDLE_OPTIONAL(immediate) + break; + case X86Local::AddRegFrm: + // Operand 1 is added to the opcode. + // Operand 2 (optional) is an address. + assert(numPhysicalOperands >= 1 && numPhysicalOperands <= 2 && + "Unexpected number of operands for AddRegFrm"); + HANDLE_OPERAND(opcodeModifier) + HANDLE_OPTIONAL(relocation) + break; + case X86Local::MRMDestReg: + // Operand 1 is a register operand in the R/M field. + // Operand 2 is a register operand in the Reg/Opcode field. + // - In AVX, there is a register operand in the VEX.vvvv field here - + // Operand 3 (optional) is an immediate. + if (HasVEX_4VPrefix) + assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && + "Unexpected number of operands for MRMDestRegFrm with VEX_4V"); + else + assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && + "Unexpected number of operands for MRMDestRegFrm"); + + HANDLE_OPERAND(rmRegister) + + if (HasVEX_4VPrefix) + // FIXME: In AVX, the register below becomes the one encoded + // in ModRMVEX and the one above the one in the VEX.VVVV field + HANDLE_OPERAND(vvvvRegister) + + HANDLE_OPERAND(roRegister) + HANDLE_OPTIONAL(immediate) + break; + case X86Local::MRMDestMem: + // Operand 1 is a memory operand (possibly SIB-extended) + // Operand 2 is a register operand in the Reg/Opcode field. + // - In AVX, there is a register operand in the VEX.vvvv field here - + // Operand 3 (optional) is an immediate. + if (HasVEX_4VPrefix) + assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && + "Unexpected number of operands for MRMDestMemFrm with VEX_4V"); + else + assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && + "Unexpected number of operands for MRMDestMemFrm"); + HANDLE_OPERAND(memory) + + if (HasVEX_4VPrefix) + // FIXME: In AVX, the register below becomes the one encoded + // in ModRMVEX and the one above the one in the VEX.VVVV field + HANDLE_OPERAND(vvvvRegister) + + HANDLE_OPERAND(roRegister) + HANDLE_OPTIONAL(immediate) + break; + case X86Local::MRMSrcReg: + // Operand 1 is a register operand in the Reg/Opcode field. + // Operand 2 is a register operand in the R/M field. + // - In AVX, there is a register operand in the VEX.vvvv field here - + // Operand 3 (optional) is an immediate. + + if (HasVEX_4VPrefix || HasVEX_4VOp3Prefix) + assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 5 && + "Unexpected number of operands for MRMSrcRegFrm with VEX_4V"); + else + assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && + "Unexpected number of operands for MRMSrcRegFrm"); + + HANDLE_OPERAND(roRegister) + + if (HasVEX_4VPrefix) + // FIXME: In AVX, the register below becomes the one encoded + // in ModRMVEX and the one above the one in the VEX.VVVV field + HANDLE_OPERAND(vvvvRegister) + + if (HasMemOp4Prefix) + HANDLE_OPERAND(immediate) + + HANDLE_OPERAND(rmRegister) + + if (HasVEX_4VOp3Prefix) + HANDLE_OPERAND(vvvvRegister) + + if (!HasMemOp4Prefix) + HANDLE_OPTIONAL(immediate) + HANDLE_OPTIONAL(immediate) // above might be a register in 7:4 + break; + case X86Local::MRMSrcMem: + // Operand 1 is a register operand in the Reg/Opcode field. + // Operand 2 is a memory operand (possibly SIB-extended) + // - In AVX, there is a register operand in the VEX.vvvv field here - + // Operand 3 (optional) is an immediate. + + if (HasVEX_4VPrefix || HasVEX_4VOp3Prefix) + assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 5 && + "Unexpected number of operands for MRMSrcMemFrm with VEX_4V"); + else + assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && + "Unexpected number of operands for MRMSrcMemFrm"); + + HANDLE_OPERAND(roRegister) + + if (HasVEX_4VPrefix) + // FIXME: In AVX, the register below becomes the one encoded + // in ModRMVEX and the one above the one in the VEX.VVVV field + HANDLE_OPERAND(vvvvRegister) + + if (HasMemOp4Prefix) + HANDLE_OPERAND(immediate) + + HANDLE_OPERAND(memory) + + if (HasVEX_4VOp3Prefix) + HANDLE_OPERAND(vvvvRegister) + + if (!HasMemOp4Prefix) + HANDLE_OPTIONAL(immediate) + HANDLE_OPTIONAL(immediate) // above might be a register in 7:4 + break; + case X86Local::MRM0r: + case X86Local::MRM1r: + case X86Local::MRM2r: + case X86Local::MRM3r: + case X86Local::MRM4r: + case X86Local::MRM5r: + case X86Local::MRM6r: + case X86Local::MRM7r: + // Operand 1 is a register operand in the R/M field. + // Operand 2 (optional) is an immediate or relocation. + if (HasVEX_4VPrefix) + assert(numPhysicalOperands <= 3 && + "Unexpected number of operands for MRMnRFrm with VEX_4V"); + else + assert(numPhysicalOperands <= 2 && + "Unexpected number of operands for MRMnRFrm"); + if (HasVEX_4VPrefix) + HANDLE_OPERAND(vvvvRegister) + HANDLE_OPTIONAL(rmRegister) + HANDLE_OPTIONAL(relocation) + break; + case X86Local::MRM0m: + case X86Local::MRM1m: + case X86Local::MRM2m: + case X86Local::MRM3m: + case X86Local::MRM4m: + case X86Local::MRM5m: + case X86Local::MRM6m: + case X86Local::MRM7m: + // Operand 1 is a memory operand (possibly SIB-extended) + // Operand 2 (optional) is an immediate or relocation. + if (HasVEX_4VPrefix) + assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && + "Unexpected number of operands for MRMnMFrm"); + else + assert(numPhysicalOperands >= 1 && numPhysicalOperands <= 2 && + "Unexpected number of operands for MRMnMFrm"); + if (HasVEX_4VPrefix) + HANDLE_OPERAND(vvvvRegister) + HANDLE_OPERAND(memory) + HANDLE_OPTIONAL(relocation) + break; + case X86Local::RawFrmImm8: + // operand 1 is a 16-bit immediate + // operand 2 is an 8-bit immediate + assert(numPhysicalOperands == 2 && + "Unexpected number of operands for X86Local::RawFrmImm8"); + HANDLE_OPERAND(immediate) + HANDLE_OPERAND(immediate) + break; + case X86Local::RawFrmImm16: + // operand 1 is a 16-bit immediate + // operand 2 is a 16-bit immediate + HANDLE_OPERAND(immediate) + HANDLE_OPERAND(immediate) + break; + case X86Local::MRMInitReg: + // Ignored. + break; + } + + #undef HANDLE_OPERAND + #undef HANDLE_OPTIONAL +} + +void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { + // Special cases where the LLVM tables are not complete + +#define MAP(from, to) \ + case X86Local::MRM_##from: \ + filter = new ExactFilter(0x##from); \ + break; + + OpcodeType opcodeType = (OpcodeType)-1; + + ModRMFilter* filter = NULL; + uint8_t opcodeToSet = 0; + + switch (Prefix) { + // Extended two-byte opcodes can start with f2 0f, f3 0f, or 0f + case X86Local::XD: + case X86Local::XS: + case X86Local::TB: + opcodeType = TWOBYTE; + + switch (Opcode) { + default: + if (needsModRMForDecode(Form)) + filter = new ModFilter(isRegFormat(Form)); + else + filter = new DumbFilter(); + break; +#define EXTENSION_TABLE(n) case 0x##n: + TWO_BYTE_EXTENSION_TABLES +#undef EXTENSION_TABLE + switch (Form) { + default: + llvm_unreachable("Unhandled two-byte extended opcode"); + case X86Local::MRM0r: + case X86Local::MRM1r: + case X86Local::MRM2r: + case X86Local::MRM3r: + case X86Local::MRM4r: + case X86Local::MRM5r: + case X86Local::MRM6r: + case X86Local::MRM7r: + filter = new ExtendedFilter(true, Form - X86Local::MRM0r); + break; + case X86Local::MRM0m: + case X86Local::MRM1m: + case X86Local::MRM2m: + case X86Local::MRM3m: + case X86Local::MRM4m: + case X86Local::MRM5m: + case X86Local::MRM6m: + case X86Local::MRM7m: + filter = new ExtendedFilter(false, Form - X86Local::MRM0m); + break; + MRM_MAPPING + } // switch (Form) + break; + } // switch (Opcode) + opcodeToSet = Opcode; + break; + case X86Local::T8: + case X86Local::T8XD: + case X86Local::T8XS: + opcodeType = THREEBYTE_38; + switch (Opcode) { + default: + if (needsModRMForDecode(Form)) + filter = new ModFilter(isRegFormat(Form)); + else + filter = new DumbFilter(); + break; +#define EXTENSION_TABLE(n) case 0x##n: + THREE_BYTE_38_EXTENSION_TABLES +#undef EXTENSION_TABLE + switch (Form) { + default: + llvm_unreachable("Unhandled two-byte extended opcode"); + case X86Local::MRM0r: + case X86Local::MRM1r: + case X86Local::MRM2r: + case X86Local::MRM3r: + case X86Local::MRM4r: + case X86Local::MRM5r: + case X86Local::MRM6r: + case X86Local::MRM7r: + filter = new ExtendedFilter(true, Form - X86Local::MRM0r); + break; + case X86Local::MRM0m: + case X86Local::MRM1m: + case X86Local::MRM2m: + case X86Local::MRM3m: + case X86Local::MRM4m: + case X86Local::MRM5m: + case X86Local::MRM6m: + case X86Local::MRM7m: + filter = new ExtendedFilter(false, Form - X86Local::MRM0m); + break; + MRM_MAPPING + } // switch (Form) + break; + } // switch (Opcode) + opcodeToSet = Opcode; + break; + case X86Local::P_TA: + case X86Local::TAXD: + opcodeType = THREEBYTE_3A; + if (needsModRMForDecode(Form)) + filter = new ModFilter(isRegFormat(Form)); + else + filter = new DumbFilter(); + opcodeToSet = Opcode; + break; + case X86Local::A6: + opcodeType = THREEBYTE_A6; + if (needsModRMForDecode(Form)) + filter = new ModFilter(isRegFormat(Form)); + else + filter = new DumbFilter(); + opcodeToSet = Opcode; + break; + case X86Local::A7: + opcodeType = THREEBYTE_A7; + if (needsModRMForDecode(Form)) + filter = new ModFilter(isRegFormat(Form)); + else + filter = new DumbFilter(); + opcodeToSet = Opcode; + break; + case X86Local::D8: + case X86Local::D9: + case X86Local::DA: + case X86Local::DB: + case X86Local::DC: + case X86Local::DD: + case X86Local::DE: + case X86Local::DF: + assert(Opcode >= 0xc0 && "Unexpected opcode for an escape opcode"); + opcodeType = ONEBYTE; + if (Form == X86Local::AddRegFrm) { + Spec->modifierType = MODIFIER_MODRM; + Spec->modifierBase = Opcode; + filter = new AddRegEscapeFilter(Opcode); + } else { + filter = new EscapeFilter(true, Opcode); + } + opcodeToSet = 0xd8 + (Prefix - X86Local::D8); + break; + case X86Local::REP: + default: + opcodeType = ONEBYTE; + switch (Opcode) { +#define EXTENSION_TABLE(n) case 0x##n: + ONE_BYTE_EXTENSION_TABLES +#undef EXTENSION_TABLE + switch (Form) { + default: + llvm_unreachable("Fell through the cracks of a single-byte " + "extended opcode"); + case X86Local::MRM0r: + case X86Local::MRM1r: + case X86Local::MRM2r: + case X86Local::MRM3r: + case X86Local::MRM4r: + case X86Local::MRM5r: + case X86Local::MRM6r: + case X86Local::MRM7r: + filter = new ExtendedFilter(true, Form - X86Local::MRM0r); + break; + case X86Local::MRM0m: + case X86Local::MRM1m: + case X86Local::MRM2m: + case X86Local::MRM3m: + case X86Local::MRM4m: + case X86Local::MRM5m: + case X86Local::MRM6m: + case X86Local::MRM7m: + filter = new ExtendedFilter(false, Form - X86Local::MRM0m); + break; + MRM_MAPPING + } // switch (Form) + break; + case 0xd8: + case 0xd9: + case 0xda: + case 0xdb: + case 0xdc: + case 0xdd: + case 0xde: + case 0xdf: + filter = new EscapeFilter(false, Form - X86Local::MRM0m); + break; + default: + if (needsModRMForDecode(Form)) + filter = new ModFilter(isRegFormat(Form)); + else + filter = new DumbFilter(); + break; + } // switch (Opcode) + opcodeToSet = Opcode; + } // switch (Prefix) + + assert(opcodeType != (OpcodeType)-1 && + "Opcode type not set"); + assert(filter && "Filter not set"); + + if (Form == X86Local::AddRegFrm) { + if(Spec->modifierType != MODIFIER_MODRM) { + assert(opcodeToSet < 0xf9 && + "Not enough room for all ADDREG_FRM operands"); + + uint8_t currentOpcode; + + for (currentOpcode = opcodeToSet; + currentOpcode < opcodeToSet + 8; + ++currentOpcode) + tables.setTableFields(opcodeType, + insnContext(), + currentOpcode, + *filter, + UID, Is32Bit, IgnoresVEX_L); + + Spec->modifierType = MODIFIER_OPCODE; + Spec->modifierBase = opcodeToSet; + } else { + // modifierBase was set where MODIFIER_MODRM was set + tables.setTableFields(opcodeType, + insnContext(), + opcodeToSet, + *filter, + UID, Is32Bit, IgnoresVEX_L); + } + } else { + tables.setTableFields(opcodeType, + insnContext(), + opcodeToSet, + *filter, + UID, Is32Bit, IgnoresVEX_L); + + Spec->modifierType = MODIFIER_NONE; + Spec->modifierBase = opcodeToSet; + } + + delete filter; + +#undef MAP +} + +#define TYPE(str, type) if (s == str) return type; +OperandType RecognizableInstr::typeFromString(const std::string &s, + bool isSSE, + bool hasREX_WPrefix, + bool hasOpSizePrefix) { + if (isSSE) { + // For SSE instructions, we ignore the OpSize prefix and force operand + // sizes. + TYPE("GR16", TYPE_R16) + TYPE("GR32", TYPE_R32) + TYPE("GR64", TYPE_R64) + } + if(hasREX_WPrefix) { + // For instructions with a REX_W prefix, a declared 32-bit register encoding + // is special. + TYPE("GR32", TYPE_R32) + } + if(!hasOpSizePrefix) { + // For instructions without an OpSize prefix, a declared 16-bit register or + // immediate encoding is special. + TYPE("GR16", TYPE_R16) + TYPE("i16imm", TYPE_IMM16) + } + TYPE("i16mem", TYPE_Mv) + TYPE("i16imm", TYPE_IMMv) + TYPE("i16i8imm", TYPE_IMMv) + TYPE("GR16", TYPE_Rv) + TYPE("i32mem", TYPE_Mv) + TYPE("i32imm", TYPE_IMMv) + TYPE("i32i8imm", TYPE_IMM32) + TYPE("u32u8imm", TYPE_IMM32) + TYPE("GR32", TYPE_Rv) + TYPE("i64mem", TYPE_Mv) + TYPE("i64i32imm", TYPE_IMM64) + TYPE("i64i8imm", TYPE_IMM64) + TYPE("GR64", TYPE_R64) + TYPE("i8mem", TYPE_M8) + TYPE("i8imm", TYPE_IMM8) + TYPE("GR8", TYPE_R8) + TYPE("VR128", TYPE_XMM128) + TYPE("f128mem", TYPE_M128) + TYPE("f256mem", TYPE_M256) + TYPE("FR64", TYPE_XMM64) + TYPE("f64mem", TYPE_M64FP) + TYPE("sdmem", TYPE_M64FP) + TYPE("FR32", TYPE_XMM32) + TYPE("f32mem", TYPE_M32FP) + TYPE("ssmem", TYPE_M32FP) + TYPE("RST", TYPE_ST) + TYPE("i128mem", TYPE_M128) + TYPE("i256mem", TYPE_M256) + TYPE("i64i32imm_pcrel", TYPE_REL64) + TYPE("i16imm_pcrel", TYPE_REL16) + TYPE("i32imm_pcrel", TYPE_REL32) + TYPE("SSECC", TYPE_IMM3) + TYPE("AVXCC", TYPE_IMM5) + TYPE("brtarget", TYPE_RELv) + TYPE("uncondbrtarget", TYPE_RELv) + TYPE("brtarget8", TYPE_REL8) + TYPE("f80mem", TYPE_M80FP) + TYPE("lea32mem", TYPE_LEA) + TYPE("lea64_32mem", TYPE_LEA) + TYPE("lea64mem", TYPE_LEA) + TYPE("VR64", TYPE_MM64) + TYPE("i64imm", TYPE_IMMv) + TYPE("opaque32mem", TYPE_M1616) + TYPE("opaque48mem", TYPE_M1632) + TYPE("opaque80mem", TYPE_M1664) + TYPE("opaque512mem", TYPE_M512) + TYPE("SEGMENT_REG", TYPE_SEGMENTREG) + TYPE("DEBUG_REG", TYPE_DEBUGREG) + TYPE("CONTROL_REG", TYPE_CONTROLREG) + TYPE("offset8", TYPE_MOFFS8) + TYPE("offset16", TYPE_MOFFS16) + TYPE("offset32", TYPE_MOFFS32) + TYPE("offset64", TYPE_MOFFS64) + TYPE("VR256", TYPE_XMM256) + TYPE("GR16_NOAX", TYPE_Rv) + TYPE("GR32_NOAX", TYPE_Rv) + TYPE("GR64_NOAX", TYPE_R64) + errs() << "Unhandled type string " << s << "\n"; + llvm_unreachable("Unhandled type string"); +} +#undef TYPE + +#define ENCODING(str, encoding) if (s == str) return encoding; +OperandEncoding RecognizableInstr::immediateEncodingFromString + (const std::string &s, + bool hasOpSizePrefix) { + if(!hasOpSizePrefix) { + // For instructions without an OpSize prefix, a declared 16-bit register or + // immediate encoding is special. + ENCODING("i16imm", ENCODING_IW) + } + ENCODING("i32i8imm", ENCODING_IB) + ENCODING("u32u8imm", ENCODING_IB) + ENCODING("SSECC", ENCODING_IB) + ENCODING("AVXCC", ENCODING_IB) + ENCODING("i16imm", ENCODING_Iv) + ENCODING("i16i8imm", ENCODING_IB) + ENCODING("i32imm", ENCODING_Iv) + ENCODING("i64i32imm", ENCODING_ID) + ENCODING("i64i8imm", ENCODING_IB) + ENCODING("i8imm", ENCODING_IB) + // This is not a typo. Instructions like BLENDVPD put + // register IDs in 8-bit immediates nowadays. + ENCODING("VR256", ENCODING_IB) + ENCODING("VR128", ENCODING_IB) + errs() << "Unhandled immediate encoding " << s << "\n"; + llvm_unreachable("Unhandled immediate encoding"); +} + +OperandEncoding RecognizableInstr::rmRegisterEncodingFromString + (const std::string &s, + bool hasOpSizePrefix) { + ENCODING("GR16", ENCODING_RM) + ENCODING("GR32", ENCODING_RM) + ENCODING("GR64", ENCODING_RM) + ENCODING("GR8", ENCODING_RM) + ENCODING("VR128", ENCODING_RM) + ENCODING("FR64", ENCODING_RM) + ENCODING("FR32", ENCODING_RM) + ENCODING("VR64", ENCODING_RM) + ENCODING("VR256", ENCODING_RM) + errs() << "Unhandled R/M register encoding " << s << "\n"; + llvm_unreachable("Unhandled R/M register encoding"); +} + +OperandEncoding RecognizableInstr::roRegisterEncodingFromString + (const std::string &s, + bool hasOpSizePrefix) { + ENCODING("GR16", ENCODING_REG) + ENCODING("GR32", ENCODING_REG) + ENCODING("GR64", ENCODING_REG) + ENCODING("GR8", ENCODING_REG) + ENCODING("VR128", ENCODING_REG) + ENCODING("FR64", ENCODING_REG) + ENCODING("FR32", ENCODING_REG) + ENCODING("VR64", ENCODING_REG) + ENCODING("SEGMENT_REG", ENCODING_REG) + ENCODING("DEBUG_REG", ENCODING_REG) + ENCODING("CONTROL_REG", ENCODING_REG) + ENCODING("VR256", ENCODING_REG) + errs() << "Unhandled reg/opcode register encoding " << s << "\n"; + llvm_unreachable("Unhandled reg/opcode register encoding"); +} + +OperandEncoding RecognizableInstr::vvvvRegisterEncodingFromString + (const std::string &s, + bool hasOpSizePrefix) { + ENCODING("GR32", ENCODING_VVVV) + ENCODING("GR64", ENCODING_VVVV) + ENCODING("FR32", ENCODING_VVVV) + ENCODING("FR64", ENCODING_VVVV) + ENCODING("VR128", ENCODING_VVVV) + ENCODING("VR256", ENCODING_VVVV) + errs() << "Unhandled VEX.vvvv register encoding " << s << "\n"; + llvm_unreachable("Unhandled VEX.vvvv register encoding"); +} + +OperandEncoding RecognizableInstr::memoryEncodingFromString + (const std::string &s, + bool hasOpSizePrefix) { + ENCODING("i16mem", ENCODING_RM) + ENCODING("i32mem", ENCODING_RM) + ENCODING("i64mem", ENCODING_RM) + ENCODING("i8mem", ENCODING_RM) + ENCODING("ssmem", ENCODING_RM) + ENCODING("sdmem", ENCODING_RM) + ENCODING("f128mem", ENCODING_RM) + ENCODING("f256mem", ENCODING_RM) + ENCODING("f64mem", ENCODING_RM) + ENCODING("f32mem", ENCODING_RM) + ENCODING("i128mem", ENCODING_RM) + ENCODING("i256mem", ENCODING_RM) + ENCODING("f80mem", ENCODING_RM) + ENCODING("lea32mem", ENCODING_RM) + ENCODING("lea64_32mem", ENCODING_RM) + ENCODING("lea64mem", ENCODING_RM) + ENCODING("opaque32mem", ENCODING_RM) + ENCODING("opaque48mem", ENCODING_RM) + ENCODING("opaque80mem", ENCODING_RM) + ENCODING("opaque512mem", ENCODING_RM) + errs() << "Unhandled memory encoding " << s << "\n"; + llvm_unreachable("Unhandled memory encoding"); +} + +OperandEncoding RecognizableInstr::relocationEncodingFromString + (const std::string &s, + bool hasOpSizePrefix) { + if(!hasOpSizePrefix) { + // For instructions without an OpSize prefix, a declared 16-bit register or + // immediate encoding is special. + ENCODING("i16imm", ENCODING_IW) + } + ENCODING("i16imm", ENCODING_Iv) + ENCODING("i16i8imm", ENCODING_IB) + ENCODING("i32imm", ENCODING_Iv) + ENCODING("i32i8imm", ENCODING_IB) + ENCODING("i64i32imm", ENCODING_ID) + ENCODING("i64i8imm", ENCODING_IB) + ENCODING("i8imm", ENCODING_IB) + ENCODING("i64i32imm_pcrel", ENCODING_ID) + ENCODING("i16imm_pcrel", ENCODING_IW) + ENCODING("i32imm_pcrel", ENCODING_ID) + ENCODING("brtarget", ENCODING_Iv) + ENCODING("brtarget8", ENCODING_IB) + ENCODING("i64imm", ENCODING_IO) + ENCODING("offset8", ENCODING_Ia) + ENCODING("offset16", ENCODING_Ia) + ENCODING("offset32", ENCODING_Ia) + ENCODING("offset64", ENCODING_Ia) + errs() << "Unhandled relocation encoding " << s << "\n"; + llvm_unreachable("Unhandled relocation encoding"); +} + +OperandEncoding RecognizableInstr::opcodeModifierEncodingFromString + (const std::string &s, + bool hasOpSizePrefix) { + ENCODING("RST", ENCODING_I) + ENCODING("GR32", ENCODING_Rv) + ENCODING("GR64", ENCODING_RO) + ENCODING("GR16", ENCODING_Rv) + ENCODING("GR8", ENCODING_RB) + ENCODING("GR16_NOAX", ENCODING_Rv) + ENCODING("GR32_NOAX", ENCODING_Rv) + ENCODING("GR64_NOAX", ENCODING_RO) + errs() << "Unhandled opcode modifier encoding " << s << "\n"; + llvm_unreachable("Unhandled opcode modifier encoding"); +} +#undef ENCODING diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.h b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h new file mode 100644 index 0000000..6c0a234 --- /dev/null +++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h @@ -0,0 +1,266 @@ +//===- X86RecognizableInstr.h - Disassembler instruction spec ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is part of the X86 Disassembler Emitter. +// It contains the interface of a single recognizable instruction. +// Documentation for the disassembler emitter in general can be found in +// X86DisasemblerEmitter.h. +// +//===----------------------------------------------------------------------===// + +#ifndef X86RECOGNIZABLEINSTR_H +#define X86RECOGNIZABLEINSTR_H + +#include "X86DisassemblerTables.h" + +#include "CodeGenTarget.h" + +#include "llvm/TableGen/Record.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +namespace X86Disassembler { + +/// RecognizableInstr - Encapsulates all information required to decode a single +/// instruction, as extracted from the LLVM instruction tables. Has methods +/// to interpret the information available in the LLVM tables, and to emit the +/// instruction into DisassemblerTables. +class RecognizableInstr { +private: + /// The opcode of the instruction, as used in an MCInst + InstrUID UID; + /// The record from the .td files corresponding to this instruction + const Record* Rec; + /// The prefix field from the record + uint8_t Prefix; + /// The opcode field from the record; this is the opcode used in the Intel + /// encoding and therefore distinct from the UID + uint8_t Opcode; + /// The form field from the record + uint8_t Form; + /// The segment override field from the record + uint8_t SegOvr; + /// The hasOpSizePrefix field from the record + bool HasOpSizePrefix; + /// The hasAdSizePrefix field from the record + bool HasAdSizePrefix; + /// The hasREX_WPrefix field from the record + bool HasREX_WPrefix; + /// The hasVEXPrefix field from the record + bool HasVEXPrefix; + /// The hasVEX_4VPrefix field from the record + bool HasVEX_4VPrefix; + /// The hasVEX_4VOp3Prefix field from the record + bool HasVEX_4VOp3Prefix; + /// The hasVEX_WPrefix field from the record + bool HasVEX_WPrefix; + /// Inferred from the operands; indicates whether the L bit in the VEX prefix is set + bool HasVEX_LPrefix; + /// The hasMemOp4Prefix field from the record + bool HasMemOp4Prefix; + /// The ignoreVEX_L field from the record + bool IgnoresVEX_L; + /// The hasLockPrefix field from the record + bool HasLockPrefix; + /// The isCodeGenOnly filed from the record + bool IsCodeGenOnly; + // Whether the instruction has the predicate "In64BitMode" + bool Is64Bit; + // Whether the instruction has the predicate "In32BitMode" + bool Is32Bit; + + /// The instruction name as listed in the tables + std::string Name; + /// The AT&T AsmString for the instruction + std::string AsmString; + + /// Indicates whether the instruction is SSE + bool IsSSE; + /// Indicates whether the instruction has FR operands - MOVs with FR operands + /// are typically ignored + bool HasFROperands; + /// Indicates whether the instruction should be emitted into the decode + /// tables; regardless, it will be emitted into the instruction info table + bool ShouldBeEmitted; + + /// The operands of the instruction, as listed in the CodeGenInstruction. + /// They are not one-to-one with operands listed in the MCInst; for example, + /// memory operands expand to 5 operands in the MCInst + const std::vector<CGIOperandList::OperandInfo>* Operands; + + /// The description of the instruction that is emitted into the instruction + /// info table + InstructionSpecifier* Spec; + + /// insnContext - Returns the primary context in which the instruction is + /// valid. + /// + /// @return - The context in which the instruction is valid. + InstructionContext insnContext() const; + + enum filter_ret { + FILTER_STRONG, // instruction has no place in the instruction tables + FILTER_WEAK, // instruction may conflict, and should be eliminated if + // it does + FILTER_NORMAL // instruction should have high priority and generate an + // error if it conflcits with any other FILTER_NORMAL + // instruction + }; + + /// filter - Determines whether the instruction should be decodable. Some + /// instructions are pure intrinsics and use unencodable operands; many + /// synthetic instructions are duplicates of other instructions; other + /// instructions only differ in the logical way in which they are used, and + /// have the same decoding. Because these would cause decode conflicts, + /// they must be filtered out. + /// + /// @return - The degree of filtering to be applied (see filter_ret). + filter_ret filter() const; + + /// hasFROperands - Returns true if any operand is a FR operand. + bool hasFROperands() const; + + /// has256BitOperands - Returns true if any operand is a 256-bit SSE operand. + bool has256BitOperands() const; + + /// typeFromString - Translates an operand type from the string provided in + /// the LLVM tables to an OperandType for use in the operand specifier. + /// + /// @param s - The string, as extracted by calling Rec->getName() + /// on a CodeGenInstruction::OperandInfo. + /// @param isSSE - Indicates whether the instruction is an SSE + /// instruction. For SSE instructions, immediates are + /// fixed-size rather than being affected by the + /// mandatory OpSize prefix. + /// @param hasREX_WPrefix - Indicates whether the instruction has a REX.W + /// prefix. If it does, 32-bit register operands stay + /// 32-bit regardless of the operand size. + /// @param hasOpSizePrefix- Indicates whether the instruction has an OpSize + /// prefix. If it does not, then 16-bit register + /// operands stay 16-bit. + /// @return - The operand's type. + static OperandType typeFromString(const std::string& s, + bool isSSE, + bool hasREX_WPrefix, + bool hasOpSizePrefix); + + /// immediateEncodingFromString - Translates an immediate encoding from the + /// string provided in the LLVM tables to an OperandEncoding for use in + /// the operand specifier. + /// + /// @param s - See typeFromString(). + /// @param hasOpSizePrefix - Indicates whether the instruction has an OpSize + /// prefix. If it does not, then 16-bit immediate + /// operands stay 16-bit. + /// @return - The operand's encoding. + static OperandEncoding immediateEncodingFromString(const std::string &s, + bool hasOpSizePrefix); + + /// rmRegisterEncodingFromString - Like immediateEncodingFromString, but + /// handles operands that are in the REG field of the ModR/M byte. + static OperandEncoding rmRegisterEncodingFromString(const std::string &s, + bool hasOpSizePrefix); + + /// rmRegisterEncodingFromString - Like immediateEncodingFromString, but + /// handles operands that are in the REG field of the ModR/M byte. + static OperandEncoding roRegisterEncodingFromString(const std::string &s, + bool hasOpSizePrefix); + static OperandEncoding memoryEncodingFromString(const std::string &s, + bool hasOpSizePrefix); + static OperandEncoding relocationEncodingFromString(const std::string &s, + bool hasOpSizePrefix); + static OperandEncoding opcodeModifierEncodingFromString(const std::string &s, + bool hasOpSizePrefix); + static OperandEncoding vvvvRegisterEncodingFromString(const std::string &s, + bool HasOpSizePrefix); + + /// handleOperand - Converts a single operand from the LLVM table format to + /// the emitted table format, handling any duplicate operands it encounters + /// and then one non-duplicate. + /// + /// @param optional - Determines whether to assert that the + /// operand exists. + /// @param operandIndex - The index into the generated operand table. + /// Incremented by this function one or more + /// times to reflect possible duplicate + /// operands). + /// @param physicalOperandIndex - The index of the current operand into the + /// set of non-duplicate ('physical') operands. + /// Incremented by this function once. + /// @param numPhysicalOperands - The number of non-duplicate operands in the + /// instructions. + /// @param operandMapping - The operand mapping, which has an entry for + /// each operand that indicates whether it is a + /// duplicate, and of what. + void handleOperand(bool optional, + unsigned &operandIndex, + unsigned &physicalOperandIndex, + unsigned &numPhysicalOperands, + unsigned *operandMapping, + OperandEncoding (*encodingFromString) + (const std::string&, + bool hasOpSizePrefix)); + + /// shouldBeEmitted - Returns the shouldBeEmitted field. Although filter() + /// filters out many instructions, at various points in decoding we + /// determine that the instruction should not actually be decodable. In + /// particular, MMX MOV instructions aren't emitted, but they're only + /// identified during operand parsing. + /// + /// @return - true if at this point we believe the instruction should be + /// emitted; false if not. This will return false if filter() returns false + /// once emitInstructionSpecifier() has been called. + bool shouldBeEmitted() const { + return ShouldBeEmitted; + } + + /// emitInstructionSpecifier - Loads the instruction specifier for the current + /// instruction into a DisassemblerTables. + /// + /// @arg tables - The DisassemblerTables to populate with the specifier for + /// the current instruction. + void emitInstructionSpecifier(DisassemblerTables &tables); + + /// emitDecodePath - Populates the proper fields in the decode tables + /// corresponding to the decode paths for this instruction. + /// + /// @arg tables - The DisassemblerTables to populate with the decode + /// decode information for the current instruction. + void emitDecodePath(DisassemblerTables &tables) const; + + /// Constructor - Initializes a RecognizableInstr with the appropriate fields + /// from a CodeGenInstruction. + /// + /// @arg tables - The DisassemblerTables that the specifier will be added to. + /// @arg insn - The CodeGenInstruction to extract information from. + /// @arg uid - The unique ID of the current instruction. + RecognizableInstr(DisassemblerTables &tables, + const CodeGenInstruction &insn, + InstrUID uid); +public: + /// processInstr - Accepts a CodeGenInstruction and loads decode information + /// for it into a DisassemblerTables if appropriate. + /// + /// @arg tables - The DiassemblerTables to be populated with decode + /// information. + /// @arg insn - The CodeGenInstruction to be used as a source for this + /// information. + /// @uid - The unique ID of the instruction. + static void processInstr(DisassemblerTables &tables, + const CodeGenInstruction &insn, + InstrUID uid); +}; + +} // namespace X86Disassembler + +} // namespace llvm + +#endif |