summaryrefslogtreecommitdiffstats
path: root/utils/TableGen
diff options
context:
space:
mode:
Diffstat (limited to 'utils/TableGen')
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp1545
-rw-r--r--utils/TableGen/AsmMatcherEmitter.h33
-rw-r--r--utils/TableGen/AsmWriterEmitter.cpp298
-rw-r--r--utils/TableGen/AsmWriterEmitter.h3
-rw-r--r--utils/TableGen/CMakeLists.txt1
-rw-r--r--utils/TableGen/CallingConvEmitter.cpp16
-rw-r--r--utils/TableGen/CodeEmitterGen.cpp12
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp198
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.h57
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp6
-rw-r--r--utils/TableGen/CodeGenInstruction.h2
-rw-r--r--utils/TableGen/CodeGenTarget.cpp84
-rw-r--r--utils/TableGen/CodeGenTarget.h4
-rw-r--r--utils/TableGen/DAGISelEmitter.cpp100
-rw-r--r--utils/TableGen/FastISelEmitter.cpp15
-rw-r--r--utils/TableGen/InstrInfoEmitter.cpp10
-rw-r--r--utils/TableGen/IntrinsicEmitter.cpp47
-rw-r--r--utils/TableGen/LLVMCConfigurationEmitter.cpp502
-rw-r--r--utils/TableGen/Record.cpp62
-rw-r--r--utils/TableGen/Record.h51
-rw-r--r--utils/TableGen/RegisterInfoEmitter.cpp17
-rw-r--r--utils/TableGen/StringToOffsetTable.h76
-rw-r--r--utils/TableGen/SubtargetEmitter.cpp154
-rw-r--r--utils/TableGen/SubtargetEmitter.h8
-rw-r--r--utils/TableGen/TGParser.cpp2
-rw-r--r--utils/TableGen/TGValueTypes.cpp45
-rw-r--r--utils/TableGen/TableGen.cpp24
27 files changed, 2668 insertions, 704 deletions
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
new file mode 100644
index 0000000..3eac9d2
--- /dev/null
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -0,0 +1,1545 @@
+//===- 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.
+//
+// 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.
+//
+// FIXME: What do we do if a crazy case shows up where this is the wrong
+// resolution?
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AsmMatcherEmitter.h"
+#include "CodeGenTarget.h"
+#include "Record.h"
+#include "llvm/ADT/OwningPtr.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 <list>
+#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"));
+
+/// FlattenVariants - Flatten an .td file assembly string by selecting the
+/// variant at index \arg N.
+static std::string FlattenVariants(const std::string &AsmString,
+ unsigned N) {
+ StringRef Cur = AsmString;
+ 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 != N; ++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;
+}
+
+/// TokenizeAsmString - Tokenize a simplified assembly string.
+static void TokenizeAsmString(const StringRef &AsmString,
+ SmallVectorImpl<StringRef> &Tokens) {
+ unsigned Prev = 0;
+ bool InTok = true;
+ for (unsigned i = 0, e = AsmString.size(); i != e; ++i) {
+ switch (AsmString[i]) {
+ case '[':
+ case ']':
+ case '*':
+ case '!':
+ case ' ':
+ case '\t':
+ case ',':
+ if (InTok) {
+ Tokens.push_back(AsmString.slice(Prev, i));
+ InTok = false;
+ }
+ if (!isspace(AsmString[i]) && AsmString[i] != ',')
+ Tokens.push_back(AsmString.substr(i, 1));
+ Prev = i + 1;
+ break;
+
+ case '\\':
+ if (InTok) {
+ Tokens.push_back(AsmString.slice(Prev, i));
+ InTok = false;
+ }
+ ++i;
+ assert(i != AsmString.size() && "Invalid quoted character");
+ Tokens.push_back(AsmString.substr(i, 1));
+ Prev = i + 1;
+ break;
+
+ case '$': {
+ // If this isn't "${", treat like a normal token.
+ if (i + 1 == AsmString.size() || AsmString[i + 1] != '{') {
+ if (InTok) {
+ Tokens.push_back(AsmString.slice(Prev, i));
+ InTok = false;
+ }
+ Prev = i;
+ break;
+ }
+
+ if (InTok) {
+ Tokens.push_back(AsmString.slice(Prev, i));
+ InTok = false;
+ }
+
+ StringRef::iterator End =
+ std::find(AsmString.begin() + i, AsmString.end(), '}');
+ assert(End != AsmString.end() && "Missing brace in operand reference!");
+ size_t EndPos = End - AsmString.begin();
+ Tokens.push_back(AsmString.slice(i, EndPos+1));
+ Prev = EndPos + 1;
+ i = EndPos;
+ break;
+ }
+
+ default:
+ InTok = true;
+ }
+ }
+ if (InTok && Prev != AsmString.size())
+ Tokens.push_back(AsmString.substr(Prev));
+}
+
+static bool IsAssemblerInstruction(const StringRef &Name,
+ const CodeGenInstruction &CGI,
+ const SmallVectorImpl<StringRef> &Tokens) {
+ // Ignore "codegen only" instructions.
+ if (CGI.TheDef->getValueAsBit("isCodeGenOnly"))
+ return false;
+
+ // Ignore pseudo ops.
+ //
+ // FIXME: This is a hack; can we convert these instructions to set the
+ // "codegen only" bit instead?
+ if (const RecordVal *Form = CGI.TheDef->getValue("Form"))
+ if (Form->getValue()->getAsString() == "Pseudo")
+ return false;
+
+ // Ignore "Int_*" and "*_Int" instructions, which are internal aliases.
+ //
+ // FIXME: This is a total hack.
+ if (StringRef(Name).startswith("Int_") || StringRef(Name).endswith("_Int"))
+ return false;
+
+ // Ignore instructions with no .s string.
+ //
+ // FIXME: What are these?
+ if (CGI.AsmString.empty())
+ return false;
+
+ // FIXME: Hack; ignore any instructions with a newline in them.
+ if (std::find(CGI.AsmString.begin(),
+ CGI.AsmString.end(), '\n') != CGI.AsmString.end())
+ return false;
+
+ // Ignore instructions with attributes, these are always fake instructions for
+ // simplifying codegen.
+ //
+ // FIXME: Is this true?
+ //
+ // 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 = 1, e = Tokens.size(); i < e; ++i) {
+ if (Tokens[i][0] == '$' &&
+ std::find(Tokens[i].begin(),
+ Tokens[i].end(), ':') != Tokens[i].end()) {
+ DEBUG({
+ errs() << "warning: '" << Name << "': "
+ << "ignoring instruction; operand with attribute '"
+ << Tokens[i] << "'\n";
+ });
+ return false;
+ }
+
+ if (Tokens[i][0] == '$' && !OperandNames.insert(Tokens[i]).second) {
+ std::string Err = "'" + Name.str() + "': " +
+ "invalid assembler instruction; tied operand '" + Tokens[i].str() + "'";
+ throw TGError(CGI.TheDef->getLoc(), Err);
+ }
+ }
+
+ return true;
+}
+
+namespace {
+
+/// 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;
+
+ /// 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 {
+ // Unrelated classes can be ordered by kind.
+ if (!isRelatedTo(RHS))
+ return Kind < RHS.Kind;
+
+ switch (Kind) {
+ case Invalid:
+ assert(0 && "Invalid kind!");
+ case Token:
+ // Tokens are comparable by value.
+ //
+ // FIXME: Compare by enum value.
+ return ValueName < RHS.ValueName;
+
+ default:
+ // This class preceeds the RHS if it is a proper subset of the RHS.
+ return this != &RHS && isSubsetOf(RHS);
+ }
+ }
+};
+
+/// InstructionInfo - Helper class for storing the necessary information for an
+/// instruction which is capable of being matched.
+struct InstructionInfo {
+ struct Operand {
+ /// The unique class instance this operand should match.
+ ClassInfo *Class;
+
+ /// The original operand this corresponds to, if any.
+ const CodeGenInstruction::OperandInfo *OperandInfo;
+ };
+
+ /// InstrName - The target name for this instruction.
+ std::string InstrName;
+
+ /// Instr - The instruction this matches.
+ const CodeGenInstruction *Instr;
+
+ /// AsmString - The assembly string for this instruction (with variants
+ /// removed).
+ std::string AsmString;
+
+ /// Tokens - The tokenized assembly pattern that this instruction matches.
+ SmallVector<StringRef, 4> Tokens;
+
+ /// Operands - The operands that this instruction matches.
+ SmallVector<Operand, 4> Operands;
+
+ /// ConversionFnKind - The enum value which is passed to the generated
+ /// ConvertToMCInst to convert parsed operands into an MCInst for this
+ /// function.
+ std::string ConversionFnKind;
+
+ /// operator< - Compare two instructions.
+ bool operator<(const InstructionInfo &RHS) const {
+ if (Operands.size() != RHS.Operands.size())
+ return Operands.size() < RHS.Operands.size();
+
+ // Compare lexicographically by operand. The matcher validates that other
+ // orderings wouldn't be ambiguous using \see CouldMatchAmiguouslyWith().
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ if (*Operands[i].Class < *RHS.Operands[i].Class)
+ return true;
+ if (*RHS.Operands[i].Class < *Operands[i].Class)
+ return false;
+ }
+
+ return false;
+ }
+
+ /// CouldMatchAmiguouslyWith - Check whether this instruction could
+ /// ambiguously match the same set of operands as \arg RHS (without being a
+ /// strictly superior match).
+ bool CouldMatchAmiguouslyWith(const InstructionInfo &RHS) {
+ // The number of operands is unambiguous.
+ if (Operands.size() != RHS.Operands.size())
+ return false;
+
+ // Tokens and operand kinds are unambiguous (assuming a correct target
+ // specific parser).
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i)
+ if (Operands[i].Class->Kind != RHS.Operands[i].Class->Kind ||
+ Operands[i].Class->Kind == ClassInfo::Token)
+ if (*Operands[i].Class < *RHS.Operands[i].Class ||
+ *RHS.Operands[i].Class < *Operands[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 = Operands.size(); i != e; ++i) {
+ if (*Operands[i].Class < *RHS.Operands[i].Class)
+ HasLT = true;
+ if (*RHS.Operands[i].Class < *Operands[i].Class)
+ HasGT = true;
+ }
+
+ return !(HasLT ^ HasGT);
+ }
+
+public:
+ void dump();
+};
+
+class AsmMatcherInfo {
+public:
+ /// The tablegen AsmParser record.
+ Record *AsmParser;
+
+ /// The AsmParser "CommentDelimiter" value.
+ std::string CommentDelimiter;
+
+ /// The AsmParser "RegisterPrefix" value.
+ std::string RegisterPrefix;
+
+ /// The classes which are needed for matching.
+ std::vector<ClassInfo*> Classes;
+
+ /// The information on the instruction to match.
+ std::vector<InstructionInfo*> Instructions;
+
+ /// Map of Register records to their class information.
+ std::map<Record*, ClassInfo*> RegisterClasses;
+
+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(const StringRef &Token);
+
+ /// getOperandClass - Lookup or create the class for the given operand.
+ ClassInfo *getOperandClass(const StringRef &Token,
+ const CodeGenInstruction::OperandInfo &OI);
+
+ /// BuildRegisterClasses - Build the ClassInfo* instances for register
+ /// classes.
+ void BuildRegisterClasses(CodeGenTarget &Target,
+ std::set<std::string> &SingletonRegisterNames);
+
+ /// BuildOperandClasses - Build the ClassInfo* instances for user defined
+ /// operand classes.
+ void BuildOperandClasses(CodeGenTarget &Target);
+
+public:
+ AsmMatcherInfo(Record *_AsmParser);
+
+ /// BuildInfo - Construct the various tables used during matching.
+ void BuildInfo(CodeGenTarget &Target);
+};
+
+}
+
+void InstructionInfo::dump() {
+ errs() << InstrName << " -- " << "flattened:\"" << AsmString << '\"'
+ << ", tokens:[";
+ for (unsigned i = 0, e = Tokens.size(); i != e; ++i) {
+ errs() << Tokens[i];
+ if (i + 1 != e)
+ errs() << ", ";
+ }
+ errs() << "]\n";
+
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ Operand &Op = Operands[i];
+ errs() << " op[" << i << "] = " << Op.Class->ClassName << " - ";
+ if (Op.Class->Kind == ClassInfo::Token) {
+ errs() << '\"' << Tokens[i] << "\"\n";
+ continue;
+ }
+
+ if (!Op.OperandInfo) {
+ errs() << "(singleton register)\n";
+ continue;
+ }
+
+ const CodeGenInstruction::OperandInfo &OI = *Op.OperandInfo;
+ errs() << OI.Name << " " << OI.Rec->getName()
+ << " (" << OI.MIOperandNo << ", " << OI.MINumOperands << ")\n";
+ }
+}
+
+static std::string getEnumNameForToken(const 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;
+
+ default:
+ if (isalnum(*it)) {
+ Res += *it;
+ } else {
+ Res += "_" + utostr((unsigned) *it) + "_";
+ }
+ }
+ }
+
+ return Res;
+}
+
+/// getRegisterRecord - Get the register record for \arg name, or 0.
+static Record *getRegisterRecord(CodeGenTarget &Target, const StringRef &Name) {
+ for (unsigned i = 0, e = Target.getRegisters().size(); i != e; ++i) {
+ const CodeGenRegister &Reg = Target.getRegisters()[i];
+ if (Name == Reg.TheDef->getValueAsString("AsmName"))
+ return Reg.TheDef;
+ }
+
+ return 0;
+}
+
+ClassInfo *AsmMatcherInfo::getTokenClass(const 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>";
+ Classes.push_back(Entry);
+ }
+
+ return Entry;
+}
+
+ClassInfo *
+AsmMatcherInfo::getOperandClass(const StringRef &Token,
+ const CodeGenInstruction::OperandInfo &OI) {
+ if (OI.Rec->isSubClassOf("RegisterClass")) {
+ ClassInfo *CI = RegisterClassClasses[OI.Rec];
+
+ if (!CI) {
+ PrintError(OI.Rec->getLoc(), "register class has no class info!");
+ throw std::string("ERROR: Missing register class!");
+ }
+
+ return CI;
+ }
+
+ assert(OI.Rec->isSubClassOf("Operand") && "Unexpected operand!");
+ Record *MatchClass = OI.Rec->getValueAsDef("ParserMatchClass");
+ ClassInfo *CI = AsmOperandClasses[MatchClass];
+
+ if (!CI) {
+ PrintError(OI.Rec->getLoc(), "operand has no match class!");
+ throw std::string("ERROR: Missing match class!");
+ }
+
+ return CI;
+}
+
+void AsmMatcherInfo::BuildRegisterClasses(CodeGenTarget &Target,
+ std::set<std::string>
+ &SingletonRegisterNames) {
+ std::vector<CodeGenRegisterClass> RegisterClasses;
+ std::vector<CodeGenRegister> Registers;
+
+ RegisterClasses = Target.getRegisterClasses();
+ Registers = Target.getRegisters();
+
+ // The register sets used for matching.
+ std::set< std::set<Record*> > RegisterSets;
+
+ // Gather the defined sets.
+ for (std::vector<CodeGenRegisterClass>::iterator it = RegisterClasses.begin(),
+ ie = RegisterClasses.end(); it != ie; ++it)
+ RegisterSets.insert(std::set<Record*>(it->Elements.begin(),
+ it->Elements.end()));
+
+ // Add any required singleton sets.
+ for (std::set<std::string>::iterator it = SingletonRegisterNames.begin(),
+ ie = SingletonRegisterNames.end(); it != ie; ++it)
+ if (Record *Rec = getRegisterRecord(Target, *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>::iterator it = Registers.begin(),
+ ie = Registers.end(); it != ie; ++it) {
+ 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;
+ } else {
+ 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 (std::vector<CodeGenRegisterClass>::iterator it = RegisterClasses.begin(),
+ ie = RegisterClasses.end(); it != ie; ++it) {
+ ClassInfo *CI = RegisterSetClasses[std::set<Record*>(it->Elements.begin(),
+ it->Elements.end())];
+ if (CI->ValueName.empty()) {
+ CI->ClassName = it->getName();
+ CI->Name = "MCK_" + it->getName();
+ CI->ValueName = it->getName();
+ } else
+ CI->ValueName = CI->ValueName + "," + it->getName();
+
+ RegisterClassClasses.insert(std::make_pair(it->TheDef, CI));
+ }
+
+ // Populate the map for individual registers.
+ for (std::map<Record*, std::set<Record*> >::iterator it = RegisterMap.begin(),
+ ie = RegisterMap.end(); it != ie; ++it)
+ this->RegisterClasses[it->first] = RegisterSetClasses[it->second];
+
+ // Name the register classes which correspond to singleton registers.
+ for (std::set<std::string>::iterator it = SingletonRegisterNames.begin(),
+ ie = SingletonRegisterNames.end(); it != ie; ++it) {
+ if (Record *Rec = getRegisterRecord(Target, *it)) {
+ ClassInfo *CI = this->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(CodeGenTarget &Target) {
+ std::vector<Record*> AsmOperands;
+ AsmOperands = Records.getAllDerivedDefinitions("AsmOperandClass");
+ unsigned Index = 0;
+ for (std::vector<Record*>::iterator it = AsmOperands.begin(),
+ ie = AsmOperands.end(); it != ie; ++it, ++Index) {
+ ClassInfo *CI = new ClassInfo();
+ CI->Kind = ClassInfo::UserClass0 + Index;
+
+ Init *Super = (*it)->getValueInit("SuperClass");
+ if (DefInit *DI = dynamic_cast<DefInit*>(Super)) {
+ ClassInfo *SC = AsmOperandClasses[DI->getDef()];
+ if (!SC)
+ PrintError((*it)->getLoc(), "Invalid super class reference!");
+ else
+ CI->SuperClasses.push_back(SC);
+ } else {
+ assert(dynamic_cast<UnsetInit*>(Super) && "Unexpected SuperClass field!");
+ }
+ 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";
+ }
+
+ AsmOperandClasses[*it] = CI;
+ Classes.push_back(CI);
+ }
+}
+
+AsmMatcherInfo::AsmMatcherInfo(Record *_AsmParser)
+ : AsmParser(_AsmParser),
+ CommentDelimiter(AsmParser->getValueAsString("CommentDelimiter")),
+ RegisterPrefix(AsmParser->getValueAsString("RegisterPrefix"))
+{
+}
+
+void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) {
+ // Parse the instructions; we need to do this first so that we can gather the
+ // singleton register classes.
+ std::set<std::string> SingletonRegisterNames;
+ for (std::map<std::string, CodeGenInstruction>::const_iterator
+ it = Target.getInstructions().begin(),
+ ie = Target.getInstructions().end();
+ it != ie; ++it) {
+ const CodeGenInstruction &CGI = it->second;
+
+ if (!StringRef(it->first).startswith(MatchPrefix))
+ continue;
+
+ OwningPtr<InstructionInfo> II(new InstructionInfo);
+
+ II->InstrName = it->first;
+ II->Instr = &it->second;
+ II->AsmString = FlattenVariants(CGI.AsmString, 0);
+
+ // Remove comments from the asm string.
+ if (!CommentDelimiter.empty()) {
+ size_t Idx = StringRef(II->AsmString).find(CommentDelimiter);
+ if (Idx != StringRef::npos)
+ II->AsmString = II->AsmString.substr(0, Idx);
+ }
+
+ TokenizeAsmString(II->AsmString, II->Tokens);
+
+ // Ignore instructions which shouldn't be matched.
+ if (!IsAssemblerInstruction(it->first, CGI, II->Tokens))
+ continue;
+
+ // Collect singleton registers, if used.
+ if (!RegisterPrefix.empty()) {
+ for (unsigned i = 0, e = II->Tokens.size(); i != e; ++i) {
+ if (II->Tokens[i].startswith(RegisterPrefix)) {
+ StringRef RegName = II->Tokens[i].substr(RegisterPrefix.size());
+ Record *Rec = getRegisterRecord(Target, RegName);
+
+ if (!Rec) {
+ std::string Err = "unable to find register for '" + RegName.str() +
+ "' (which matches register prefix)";
+ throw TGError(CGI.TheDef->getLoc(), Err);
+ }
+
+ SingletonRegisterNames.insert(RegName);
+ }
+ }
+ }
+
+ Instructions.push_back(II.take());
+ }
+
+ // Build info for the register classes.
+ BuildRegisterClasses(Target, SingletonRegisterNames);
+
+ // Build info for the user defined assembly operand classes.
+ BuildOperandClasses(Target);
+
+ // Build the instruction information.
+ for (std::vector<InstructionInfo*>::iterator it = Instructions.begin(),
+ ie = Instructions.end(); it != ie; ++it) {
+ InstructionInfo *II = *it;
+
+ for (unsigned i = 0, e = II->Tokens.size(); i != e; ++i) {
+ StringRef Token = II->Tokens[i];
+
+ // Check for singleton registers.
+ if (!RegisterPrefix.empty() && Token.startswith(RegisterPrefix)) {
+ StringRef RegName = II->Tokens[i].substr(RegisterPrefix.size());
+ InstructionInfo::Operand Op;
+ Op.Class = RegisterClasses[getRegisterRecord(Target, RegName)];
+ Op.OperandInfo = 0;
+ assert(Op.Class && Op.Class->Registers.size() == 1 &&
+ "Unexpected class for singleton register");
+ II->Operands.push_back(Op);
+ continue;
+ }
+
+ // Check for simple tokens.
+ if (Token[0] != '$') {
+ InstructionInfo::Operand Op;
+ Op.Class = getTokenClass(Token);
+ Op.OperandInfo = 0;
+ II->Operands.push_back(Op);
+ continue;
+ }
+
+ // Otherwise this is an operand reference.
+ StringRef OperandName;
+ if (Token[1] == '{')
+ OperandName = Token.substr(2, Token.size() - 3);
+ else
+ OperandName = Token.substr(1);
+
+ // Map this token to an operand. FIXME: Move elsewhere.
+ unsigned Idx;
+ try {
+ Idx = II->Instr->getOperandNamed(OperandName);
+ } catch(...) {
+ throw std::string("error: unable to find operand: '" +
+ OperandName.str() + "'");
+ }
+
+ const CodeGenInstruction::OperandInfo &OI = II->Instr->OperandList[Idx];
+ InstructionInfo::Operand Op;
+ Op.Class = getOperandClass(Token, OI);
+ Op.OperandInfo = &OI;
+ II->Operands.push_back(Op);
+ }
+ }
+
+ // Reorder classes so that classes preceed super classes.
+ std::sort(Classes.begin(), Classes.end(), less_ptr<ClassInfo>());
+}
+
+static void EmitConvertToMCInst(CodeGenTarget &Target,
+ std::vector<InstructionInfo*> &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 << "static bool ConvertToMCInst(ConversionKind Kind, MCInst &Inst, "
+ << "unsigned Opcode,\n"
+ << " SmallVectorImpl<"
+ << Target.getName() << "Operand> &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 operants to MCInst instances.\n\n";
+ OS << "enum ConversionKind {\n";
+
+ for (std::vector<InstructionInfo*>::const_iterator it = Infos.begin(),
+ ie = Infos.end(); it != ie; ++it) {
+ InstructionInfo &II = **it;
+
+ // Order the (class) operands by the order to convert them into an MCInst.
+ SmallVector<std::pair<unsigned, unsigned>, 4> MIOperandList;
+ for (unsigned i = 0, e = II.Operands.size(); i != e; ++i) {
+ InstructionInfo::Operand &Op = II.Operands[i];
+ if (Op.OperandInfo)
+ MIOperandList.push_back(std::make_pair(Op.OperandInfo->MIOperandNo, i));
+ }
+ std::sort(MIOperandList.begin(), MIOperandList.end());
+
+ // Compute the total number of operands.
+ unsigned NumMIOperands = 0;
+ for (unsigned i = 0, e = II.Instr->OperandList.size(); i != e; ++i) {
+ const CodeGenInstruction::OperandInfo &OI = II.Instr->OperandList[i];
+ NumMIOperands = std::max(NumMIOperands,
+ OI.MIOperandNo + OI.MINumOperands);
+ }
+
+ // Build the conversion function signature.
+ std::string Signature = "Convert";
+ unsigned CurIndex = 0;
+ for (unsigned i = 0, e = MIOperandList.size(); i != e; ++i) {
+ InstructionInfo::Operand &Op = II.Operands[MIOperandList[i].second];
+ assert(CurIndex <= Op.OperandInfo->MIOperandNo &&
+ "Duplicate match for instruction operand!");
+
+ Signature += "_";
+
+ // Skip operands which weren't matched by anything, this occurs when the
+ // .td file encodes "implicit" operands as explicit ones.
+ //
+ // FIXME: This should be removed from the MCInst structure.
+ for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex)
+ Signature += "Imp";
+
+ // Registers are always converted the same, don't duplicate the conversion
+ // function based on them.
+ //
+ // FIXME: We could generalize this based on the render method, if it
+ // mattered.
+ if (Op.Class->isRegisterClass())
+ Signature += "Reg";
+ else
+ Signature += Op.Class->ClassName;
+ Signature += utostr(Op.OperandInfo->MINumOperands);
+ Signature += "_" + utostr(MIOperandList[i].second);
+
+ CurIndex += Op.OperandInfo->MINumOperands;
+ }
+
+ // Add any trailing implicit operands.
+ for (; CurIndex != NumMIOperands; ++CurIndex)
+ Signature += "Imp";
+
+ 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";
+
+ // And to the convert function.
+ CvtOS << " case " << Signature << ":\n";
+ CurIndex = 0;
+ for (unsigned i = 0, e = MIOperandList.size(); i != e; ++i) {
+ InstructionInfo::Operand &Op = II.Operands[MIOperandList[i].second];
+
+ // Add the implicit operands.
+ for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex)
+ CvtOS << " Inst.addOperand(MCOperand::CreateReg(0));\n";
+
+ CvtOS << " Operands[" << MIOperandList[i].second
+ << "]." << Op.Class->RenderMethod
+ << "(Inst, " << Op.OperandInfo->MINumOperands << ");\n";
+ CurIndex += Op.OperandInfo->MINumOperands;
+ }
+
+ // And add trailing implicit operands.
+ for (; CurIndex != NumMIOperands; ++CurIndex)
+ CvtOS << " Inst.addOperand(MCOperand::CreateReg(0));\n";
+ CvtOS << " break;\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";
+}
+
+/// EmitClassifyOperand - Emit the function to classify an operand.
+static void EmitClassifyOperand(CodeGenTarget &Target,
+ AsmMatcherInfo &Info,
+ raw_ostream &OS) {
+ OS << "static MatchClassKind ClassifyOperand("
+ << Target.getName() << "Operand &Operand) {\n";
+
+ // Classify tokens.
+ OS << " if (Operand.isToken())\n";
+ OS << " return MatchTokenString(Operand.getToken());\n\n";
+
+ // Classify registers.
+ //
+ // FIXME: Don't hardcode isReg, getReg.
+ OS << " if (Operand.isReg()) {\n";
+ OS << " switch (Operand.getReg()) {\n";
+ OS << " default: return InvalidMatchClass;\n";
+ for (std::map<Record*, ClassInfo*>::iterator
+ it = Info.RegisterClasses.begin(), ie = Info.RegisterClasses.end();
+ it != ie; ++it)
+ OS << " case " << Target.getName() << "::"
+ << it->first->getName() << ": return " << it->second->Name << ";\n";
+ OS << " }\n";
+ OS << " }\n\n";
+
+ // Classify user defined operands.
+ 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";
+ if (!CI.SuperClasses.empty()) {
+ OS << ", subclass of ";
+ for (unsigned i = 0, e = CI.SuperClasses.size(); i != e; ++i) {
+ if (i) OS << ", ";
+ OS << "'" << CI.SuperClasses[i]->ClassName << "'";
+ assert(CI < *CI.SuperClasses[i] && "Invalid class relation!");
+ }
+ }
+ OS << "\n";
+
+ OS << " if (Operand." << CI.PredicateMethod << "()) {\n";
+
+ // Validate subclass relationships.
+ if (!CI.SuperClasses.empty()) {
+ for (unsigned i = 0, e = CI.SuperClasses.size(); i != e; ++i)
+ OS << " assert(Operand." << CI.SuperClasses[i]->PredicateMethod
+ << "() && \"Invalid class relationship!\");\n";
+ }
+
+ OS << " return " << CI.Name << ";\n";
+ OS << " }\n\n";
+ }
+ OS << " return InvalidMatchClass;\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;
+
+ if (A.Kind != ClassInfo::Token) {
+ 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";
+}
+
+typedef std::pair<std::string, std::string> StringPair;
+
+/// 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 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.
+static bool EmitStringMatcherForChar(const std::string &StrVariableName,
+ const std::vector<const StringPair*> &Matches,
+ unsigned CharNo, unsigned IndentCount,
+ raw_ostream &OS) {
+ 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");
+
+ // FIXME: If Matches[0].first has embeded \n, this will be bad.
+ OS << Indent << Matches[0]->second << "\t // \"" << Matches[0]->first
+ << "\"\n";
+ 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(StrVariableName, Matches,
+ FirstNonCommonLetter, IndentCount, OS);
+ }
+
+ // 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() << " strings to match.\n";
+ if (EmitStringMatcherForChar(StrVariableName, LI->second, CharNo+1,
+ IndentCount+1, OS))
+ OS << Indent << " break;\n";
+ }
+
+ OS << Indent << "}\n";
+ return true;
+}
+
+
+/// EmitStringMatcher - 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.
+///
+/// \param StrVariableName - The name of the variable to test.
+static void EmitStringMatcher(const std::string &StrVariableName,
+ const std::vector<StringPair> &Matches,
+ raw_ostream &OS) {
+ // 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 << " switch (" << StrVariableName << ".size()) {\n";
+ OS << " default: break;\n";
+
+ for (std::map<unsigned, std::vector<const StringPair*> >::iterator LI =
+ MatchesByLength.begin(), E = MatchesByLength.end(); LI != E; ++LI) {
+ OS << " case " << LI->first << ":\t // " << LI->second.size()
+ << " strings to match.\n";
+ if (EmitStringMatcherForChar(StrVariableName, LI->second, 0, 0, OS))
+ OS << " break;\n";
+ }
+
+ OS << " }\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<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(StringPair(CI.ValueName, "return " + CI.Name + ";"));
+ }
+
+ OS << "static MatchClassKind MatchTokenString(const StringRef &Name) {\n";
+
+ EmitStringMatcher("Name", Matches, OS);
+
+ 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<StringPair> Matches;
+ for (unsigned i = 0, e = Target.getRegisters().size(); i != e; ++i) {
+ const CodeGenRegister &Reg = Target.getRegisters()[i];
+ if (Reg.TheDef->getValueAsString("AsmName").empty())
+ continue;
+
+ Matches.push_back(StringPair(Reg.TheDef->getValueAsString("AsmName"),
+ "return " + utostr(i + 1) + ";"));
+ }
+
+ OS << "unsigned " << Target.getName()
+ << AsmParser->getValueAsString("AsmParserClassName")
+ << "::MatchRegisterName(const StringRef &Name) {\n";
+
+ EmitStringMatcher("Name", Matches, OS);
+
+ OS << " return 0;\n";
+ OS << "}\n\n";
+}
+
+void AsmMatcherEmitter::run(raw_ostream &OS) {
+ CodeGenTarget Target;
+ Record *AsmParser = Target.getAsmParser();
+ std::string ClassName = AsmParser->getValueAsString("AsmParserClassName");
+
+ // Compute the information on the instructions to match.
+ AsmMatcherInfo Info(AsmParser);
+ Info.BuildInfo(Target);
+
+ // Sort the instruction table using the partial order on classes.
+ std::sort(Info.Instructions.begin(), Info.Instructions.end(),
+ less_ptr<InstructionInfo>());
+
+ DEBUG_WITH_TYPE("instruction_info", {
+ for (std::vector<InstructionInfo*>::iterator
+ it = Info.Instructions.begin(), ie = Info.Instructions.end();
+ it != ie; ++it)
+ (*it)->dump();
+ });
+
+ // Check for ambiguous instructions.
+ unsigned NumAmbiguous = 0;
+ for (unsigned i = 0, e = Info.Instructions.size(); i != e; ++i) {
+ for (unsigned j = i + 1; j != e; ++j) {
+ InstructionInfo &A = *Info.Instructions[i];
+ InstructionInfo &B = *Info.Instructions[j];
+
+ if (A.CouldMatchAmiguouslyWith(B)) {
+ DEBUG_WITH_TYPE("ambiguous_instrs", {
+ errs() << "warning: ambiguous instruction match:\n";
+ A.dump();
+ errs() << "\nis incomparable with:\n";
+ B.dump();
+ errs() << "\n\n";
+ });
+ ++NumAmbiguous;
+ }
+ }
+ }
+ if (NumAmbiguous)
+ DEBUG_WITH_TYPE("ambiguous_instrs", {
+ errs() << "warning: " << NumAmbiguous
+ << " ambiguous instructions!\n";
+ });
+
+ // Write the output.
+
+ EmitSourceFileHeader("Assembly Matcher Source Fragment", OS);
+
+ // Emit the function to match a register name to number.
+ EmitMatchRegisterName(Target, AsmParser, OS);
+
+ // Generate the unified function to convert operands into an MCInst.
+ EmitConvertToMCInst(Target, Info.Instructions, 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 routine to classify an operand.
+ EmitClassifyOperand(Target, Info, OS);
+
+ // Emit the subclass predicate routine.
+ EmitIsSubclass(Target, Info.Classes, OS);
+
+ // Finally, build the match function.
+
+ size_t MaxNumOperands = 0;
+ for (std::vector<InstructionInfo*>::const_iterator it =
+ Info.Instructions.begin(), ie = Info.Instructions.end();
+ it != ie; ++it)
+ MaxNumOperands = std::max(MaxNumOperands, (*it)->Operands.size());
+
+ OS << "bool " << Target.getName() << ClassName
+ << "::MatchInstruction("
+ << "SmallVectorImpl<" << Target.getName() << "Operand> &Operands, "
+ << "MCInst &Inst) {\n";
+
+ // 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 << " static const struct MatchEntry {\n";
+ OS << " unsigned Opcode;\n";
+ OS << " ConversionKind ConvertFn;\n";
+ OS << " MatchClassKind Classes[" << MaxNumOperands << "];\n";
+ OS << " } MatchTable[" << Info.Instructions.size() << "] = {\n";
+
+ for (std::vector<InstructionInfo*>::const_iterator it =
+ Info.Instructions.begin(), ie = Info.Instructions.end();
+ it != ie; ++it) {
+ InstructionInfo &II = **it;
+
+ OS << " { " << Target.getName() << "::" << II.InstrName
+ << ", " << II.ConversionFnKind << ", { ";
+ for (unsigned i = 0, e = II.Operands.size(); i != e; ++i) {
+ InstructionInfo::Operand &Op = II.Operands[i];
+
+ if (i) OS << ", ";
+ OS << Op.Class->Name;
+ }
+ OS << " } },\n";
+ }
+
+ OS << " };\n\n";
+
+ // Emit code to compute the class list for this operand vector.
+ OS << " // Eliminate obvious mismatches.\n";
+ OS << " if (Operands.size() > " << MaxNumOperands << ")\n";
+ OS << " return true;\n\n";
+
+ OS << " // Compute the class list for this operand vector.\n";
+ OS << " MatchClassKind Classes[" << MaxNumOperands << "];\n";
+ OS << " for (unsigned i = 0, e = Operands.size(); i != e; ++i) {\n";
+ OS << " Classes[i] = ClassifyOperand(Operands[i]);\n\n";
+
+ OS << " // Check for invalid operands before matching.\n";
+ OS << " if (Classes[i] == InvalidMatchClass)\n";
+ OS << " return true;\n";
+ OS << " }\n\n";
+
+ OS << " // Mark unused classes.\n";
+ OS << " for (unsigned i = Operands.size(), e = " << MaxNumOperands << "; "
+ << "i != e; ++i)\n";
+ OS << " Classes[i] = InvalidMatchClass;\n\n";
+
+ // Emit code to search the table.
+ OS << " // Search the table.\n";
+ OS << " for (const MatchEntry *it = MatchTable, "
+ << "*ie = MatchTable + " << Info.Instructions.size()
+ << "; it != ie; ++it) {\n";
+ for (unsigned i = 0; i != MaxNumOperands; ++i) {
+ OS << " if (!IsSubclass(Classes["
+ << i << "], it->Classes[" << i << "]))\n";
+ OS << " continue;\n";
+ }
+ OS << "\n";
+ OS << " return ConvertToMCInst(it->ConvertFn, Inst, "
+ << "it->Opcode, Operands);\n";
+ OS << " }\n\n";
+
+ OS << " return true;\n";
+ OS << "}\n\n";
+}
diff --git a/utils/TableGen/AsmMatcherEmitter.h b/utils/TableGen/AsmMatcherEmitter.h
new file mode 100644
index 0000000..729c938
--- /dev/null
+++ b/utils/TableGen/AsmMatcherEmitter.h
@@ -0,0 +1,33 @@
+//===- 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 "TableGenBackend.h"
+#include <map>
+#include <vector>
+#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/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp
index f34feef..84a647b 100644
--- a/utils/TableGen/AsmWriterEmitter.cpp
+++ b/utils/TableGen/AsmWriterEmitter.cpp
@@ -15,13 +15,14 @@
#include "AsmWriterEmitter.h"
#include "CodeGenTarget.h"
#include "Record.h"
+#include "StringToOffsetTable.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
#include <algorithm>
-#include <iostream>
using namespace llvm;
+
static bool isIdentChar(char C) {
return (C >= 'a' && C <= 'z') ||
(C >= 'A' && C <= 'Z') ||
@@ -32,10 +33,20 @@ static bool isIdentChar(char C) {
// This should be an anon namespace, this works around a GCC warning.
namespace llvm {
struct AsmWriterOperand {
- enum { isLiteralTextOperand, isMachineInstrOperand } OperandType;
+ 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.
+ /// isMachineInstrOperand, this is the PrinterMethodName for the operand..
+ /// For isLiteralStatementOperand, this is the code to insert verbatim
+ /// into the asm writer.
std::string Str;
/// MiOpNo - For isMachineInstrOperand, this is the operand number of the
@@ -47,14 +58,16 @@ namespace llvm {
std::string MiModifier;
// To make VS STL happy
- AsmWriterOperand():OperandType(isLiteralTextOperand) {}
+ AsmWriterOperand(OpType op = isLiteralTextOperand):OperandType(op) {}
- explicit AsmWriterOperand(const std::string &LitStr)
- : OperandType(isLiteralTextOperand), Str(LitStr) {}
+ AsmWriterOperand(const std::string &LitStr,
+ OpType op = isLiteralTextOperand)
+ : OperandType(op), Str(LitStr) {}
AsmWriterOperand(const std::string &Printer, unsigned OpNo,
- const std::string &Modifier)
- : OperandType(isMachineInstrOperand), Str(Printer), MIOpNo(OpNo),
+ const std::string &Modifier,
+ OpType op = isMachineInstrOperand)
+ : OperandType(op), Str(Printer), MIOpNo(OpNo),
MiModifier(Modifier) {}
bool operator!=(const AsmWriterOperand &Other) const {
@@ -78,7 +91,7 @@ namespace llvm {
std::vector<AsmWriterOperand> Operands;
const CodeGenInstruction *CGI;
- AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant);
+ AsmWriterInst(const CodeGenInstruction &CGI, Record *AsmWriter);
/// MatchesAllButOneOp - If this instruction is exactly identical to the
/// specified instruction except for one differing operand, return the
@@ -100,8 +113,14 @@ namespace llvm {
std::string AsmWriterOperand::getCode() const {
- if (OperandType == isLiteralTextOperand)
+ 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)
@@ -115,10 +134,19 @@ std::string AsmWriterOperand::getCode() const {
/// ParseAsmString - Parse the specified Instruction's AsmString into this
/// AsmWriterInst.
///
-AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) {
+AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, Record *AsmWriter) {
this->CGI = &CGI;
+
+ unsigned Variant = AsmWriter->getValueAsInt("Variant");
+ int FirstOperandColumn = AsmWriter->getValueAsInt("FirstOperandColumn");
+ int OperandSpacing = AsmWriter->getValueAsInt("OperandSpacing");
+
unsigned CurVariant = ~0U; // ~0 if we are outside a {.|.|.} region, other #.
+ // 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)!
@@ -130,14 +158,35 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) {
if (DollarPos == std::string::npos) DollarPos = AsmString.size();
// Emit a constant string fragment.
+
if (DollarPos != LastEmitted) {
if (CurVariant == Variant || CurVariant == ~0U) {
for (; LastEmitted != DollarPos; ++LastEmitted)
switch (AsmString[LastEmitted]) {
- case '\n': AddLiteralString("\\n"); break;
- case '\t': AddLiteralString("\\t"); break;
- case '"': AddLiteralString("\\\""); break;
- case '\\': AddLiteralString("\\\\"); break;
+ 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;
@@ -151,7 +200,20 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) {
if (AsmString[DollarPos+1] == 'n') {
AddLiteralString("\\n");
} else if (AsmString[DollarPos+1] == 't') {
- AddLiteralString("\\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]));
@@ -182,13 +244,14 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) {
CurVariant = ~0U;
} else if (DollarPos+1 != AsmString.size() &&
AsmString[DollarPos+1] == '$') {
- if (CurVariant == Variant || CurVariant == ~0U)
+ if (CurVariant == Variant || CurVariant == ~0U) {
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.
@@ -259,8 +322,9 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) {
LastEmitted = VarEnd;
}
}
-
- AddLiteralString("\\n");
+
+ Operands.push_back(AsmWriterOperand("return;",
+ AsmWriterOperand::isLiteralStatementOperand));
}
/// MatchesAllButOneOp - If this instruction is exactly identical to the
@@ -357,7 +421,6 @@ static void EmitInstructions(std::vector<AsmWriterInst> &Insts,
}
O << "\n";
}
-
O << " break;\n";
}
@@ -384,10 +447,6 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
Command = " " + Inst->Operands[0].getCode() + "\n";
- // If this is the last operand, emit a return.
- if (Inst->Operands.size() == 1)
- Command += " return true;\n";
-
// Check to see if we already have 'Command' in UniqueOperandCommands.
// If not, add it.
bool FoundIt = false;
@@ -431,7 +490,10 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
// 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)) {
@@ -439,6 +501,11 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
// 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;
@@ -451,10 +518,6 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
// to UniqueOperandCommands and remember that it was consumed.
std::string Command = " " + FirstInst->Operands[Op].getCode() + "\n";
- // If this is the last operand, emit a return after the code.
- if (FirstInst->Operands.size() == Op+1)
- Command += " return true;\n";
-
UniqueOperandCommands[CommandIdx] += Command;
InstOpsUsed[CommandIdx]++;
}
@@ -475,29 +538,26 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
}
-
-void AsmWriterEmitter::run(raw_ostream &O) {
- EmitSourceFileHeader("Assembly Writer Source Fragment", O);
-
+/// EmitPrintInstruction - Generate the code for the "printInstruction" method
+/// implementation.
+void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
CodeGenTarget Target;
Record *AsmWriter = Target.getAsmWriter();
std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
- unsigned Variant = AsmWriter->getValueAsInt("Variant");
-
+
O <<
"/// printInstruction - This method is automatically generated by tablegen\n"
- "/// from the instruction set description. This method returns true if the\n"
- "/// machine instruction was sufficiently described to print it, otherwise\n"
- "/// it returns false.\n"
- "bool " << Target.getName() << ClassName
+ "/// from the instruction set description.\n"
+ "void " << Target.getName() << ClassName
<< "::printInstruction(const MachineInstr *MI) {\n";
std::vector<AsmWriterInst> Instructions;
for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
E = Target.inst_end(); I != E; ++I)
- if (!I->second.AsmString.empty())
- Instructions.push_back(AsmWriterInst(I->second, Variant));
+ if (!I->second.AsmString.empty() &&
+ I->second.TheDef->getName() != "PHI")
+ Instructions.push_back(AsmWriterInst(I->second, AsmWriter));
// Get the instruction numbering.
Target.getInstructionsByEnumValue(NumberedInstructions);
@@ -509,10 +569,7 @@ void AsmWriterEmitter::run(raw_ostream &O) {
CGIAWIMap.insert(std::make_pair(Instructions[i].CGI, &Instructions[i]));
// Build an aggregate string, and build a table of offsets into it.
- std::map<std::string, unsigned> StringOffset;
- std::string AggregateString;
- AggregateString.push_back(0); // "\0"
- AggregateString.push_back(0); // "\0"
+ StringToOffsetTable 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.
@@ -524,32 +581,28 @@ void AsmWriterEmitter::run(raw_ostream &O) {
unsigned Idx;
if (AWI == 0) {
// Something not handled by the asmwriter printer.
- Idx = 0;
+ 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 = 1;
+ Idx = StringTable.GetOrAddStringOffset("");
} else {
- unsigned &Entry = StringOffset[AWI->Operands[0].Str];
- if (Entry == 0) {
- // Add the string to the aggregate if this is the first time found.
- MaxStringIdx = Entry = AggregateString.size();
- std::string Str = AWI->Operands[0].Str;
- UnescapeString(Str);
- AggregateString += Str;
- AggregateString += '\0';
- }
- Idx = Entry;
-
+ std::string Str = AWI->Operands[0].Str;
+ UnescapeString(Str);
+ Idx = StringTable.GetOrAddStringOffset(Str);
+ MaxStringIdx = std::max(MaxStringIdx, Idx);
+
// Nuke the string from the operand list. It is now handled!
AWI->Operands.erase(AWI->Operands.begin());
}
- OpcodeInfo.push_back(Idx);
+
+ // 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+1);
+ unsigned AsmStrBits = Log2_32_Ceil(MaxStringIdx+2);
// To reduce code size, we compactify common instructions into a few bits
// in the opcode-indexed table.
@@ -557,17 +610,8 @@ void AsmWriterEmitter::run(raw_ostream &O) {
std::vector<std::vector<std::string> > TableDrivenOperandPrinters;
- bool isFirst = true;
while (1) {
std::vector<std::string> UniqueOperandCommands;
-
- // For the first operand check, add a default value for instructions with
- // just opcode strings to use.
- if (isFirst) {
- UniqueOperandCommands.push_back(" return true;\n");
- isFirst = false;
- }
-
std::vector<unsigned> InstIdxs;
std::vector<unsigned> NumInstOpsHandled;
FindUniqueOperandCommands(UniqueOperandCommands, InstIdxs,
@@ -582,8 +626,8 @@ void AsmWriterEmitter::run(raw_ostream &O) {
// If we don't have enough bits for this operand, don't include it.
if (NumBits > BitsLeft) {
- DOUT << "Not enough bits to densely encode " << NumBits
- << " more bits\n";
+ DEBUG(errs() << "Not enough bits to densely encode " << NumBits
+ << " more bits\n");
break;
}
@@ -621,52 +665,24 @@ void AsmWriterEmitter::run(raw_ostream &O) {
O << " };\n\n";
// Emit the string itself.
- O << " const char *AsmStrs = \n \"";
- unsigned CharsPrinted = 0;
- EscapeString(AggregateString);
- 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] == '\\') {
- 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 << "\";\n\n";
-
- O << " processDebugLoc(MI->getDebugLoc());\n\n";
+ O << " const char *AsmStrs = \n";
+ StringTable.EmitString(O);
+ O << ";\n\n";
O << "\n#ifndef NO_ASM_WRITER_BOILERPLATE\n";
O << " if (MI->getOpcode() == TargetInstrInfo::INLINEASM) {\n"
<< " O << \"\\t\";\n"
<< " printInlineAsm(MI);\n"
- << " return true;\n"
+ << " return;\n"
<< " } else if (MI->isLabel()) {\n"
<< " printLabel(MI);\n"
- << " return true;\n"
- << " } else if (MI->getOpcode() == TargetInstrInfo::DECLARE) {\n"
- << " printDeclare(MI);\n"
- << " return true;\n"
+ << " return;\n"
<< " } else if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) {\n"
<< " printImplicitDef(MI);\n"
- << " return true;\n"
+ << " return;\n"
+ << " } else if (MI->getOpcode() == TargetInstrInfo::KILL) {\n"
+ << " return;\n"
<< " }\n\n";
O << "\n#endif\n";
@@ -675,8 +691,8 @@ void AsmWriterEmitter::run(raw_ostream &O) {
O << " // Emit the opcode for the instruction.\n"
<< " unsigned Bits = OpInfo[MI->getOpcode()];\n"
- << " if (Bits == 0) return false;\n"
- << " O << AsmStrs+(Bits & " << (1 << AsmStrBits)-1 << ");\n\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;
@@ -732,6 +748,11 @@ void AsmWriterEmitter::run(raw_ostream &O) {
// 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";
@@ -739,8 +760,61 @@ void AsmWriterEmitter::run(raw_ostream &O) {
EmitInstructions(Instructions, O);
O << " }\n";
- O << " return true;\n";
+ O << " return;\n";
}
-
+
+ O << " return;\n";
O << "}\n";
}
+
+
+void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
+ CodeGenTarget Target;
+ Record *AsmWriter = Target.getAsmWriter();
+ std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
+ const std::vector<CodeGenRegister> &Registers = Target.getRegisters();
+
+ StringToOffsetTable StringTable;
+ 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
+ << "::getRegisterName(unsigned RegNo) {\n"
+ << " assert(RegNo && RegNo < " << (Registers.size()+1)
+ << " && \"Invalid register number!\");\n"
+ << "\n"
+ << " static const unsigned RegAsmOffset[] = {";
+ for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
+ const CodeGenRegister &Reg = Registers[i];
+
+ std::string AsmName = Reg.TheDef->getValueAsString("AsmName");
+ if (AsmName.empty())
+ AsmName = Reg.getName();
+
+
+ if ((i % 14) == 0)
+ O << "\n ";
+
+ O << StringTable.GetOrAddStringOffset(AsmName) << ", ";
+ }
+ O << "0\n"
+ << " };\n"
+ << "\n";
+
+ O << " const char *AsmStrs =\n";
+ StringTable.EmitString(O);
+ O << ";\n";
+
+ O << " return AsmStrs+RegAsmOffset[RegNo-1];\n"
+ << "}\n";
+}
+
+
+void AsmWriterEmitter::run(raw_ostream &O) {
+ EmitSourceFileHeader("Assembly Writer Source Fragment", O);
+
+ EmitPrintInstruction(O);
+ EmitGetRegisterName(O);
+}
+
diff --git a/utils/TableGen/AsmWriterEmitter.h b/utils/TableGen/AsmWriterEmitter.h
index 75e6996..7862caa 100644
--- a/utils/TableGen/AsmWriterEmitter.h
+++ b/utils/TableGen/AsmWriterEmitter.h
@@ -35,6 +35,9 @@ namespace llvm {
void run(raw_ostream &o);
private:
+ void EmitPrintInstruction(raw_ostream &o);
+ void EmitGetRegisterName(raw_ostream &o);
+
AsmWriterInst *getAsmWriterInstByID(unsigned ID) const {
assert(ID < NumberedInstructions.size());
std::map<const CodeGenInstruction*, AsmWriterInst*>::const_iterator I =
diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt
index 6ec1d99..e568c62 100644
--- a/utils/TableGen/CMakeLists.txt
+++ b/utils/TableGen/CMakeLists.txt
@@ -1,4 +1,5 @@
add_executable(tblgen
+ AsmMatcherEmitter.cpp
AsmWriterEmitter.cpp
CallingConvEmitter.cpp
ClangDiagnosticsEmitter.cpp
diff --git a/utils/TableGen/CallingConvEmitter.cpp b/utils/TableGen/CallingConvEmitter.cpp
index a14be0b..28ba2ed 100644
--- a/utils/TableGen/CallingConvEmitter.cpp
+++ b/utils/TableGen/CallingConvEmitter.cpp
@@ -26,9 +26,9 @@ void CallingConvEmitter::run(raw_ostream &O) {
// other.
for (unsigned i = 0, e = CCs.size(); i != e; ++i) {
O << "static bool " << CCs[i]->getName()
- << "(unsigned ValNo, MVT ValVT,\n"
+ << "(unsigned ValNo, EVT ValVT,\n"
<< std::string(CCs[i]->getName().size()+13, ' ')
- << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
+ << "EVT LocVT, CCValAssign::LocInfo LocInfo,\n"
<< std::string(CCs[i]->getName().size()+13, ' ')
<< "ISD::ArgFlagsTy ArgFlags, CCState &State);\n";
}
@@ -44,9 +44,9 @@ void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) {
Counter = 0;
O << "\n\nstatic bool " << CC->getName()
- << "(unsigned ValNo, MVT ValVT,\n"
+ << "(unsigned ValNo, EVT ValVT,\n"
<< std::string(CC->getName().size()+13, ' ')
- << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
+ << "EVT LocVT, CCValAssign::LocInfo LocInfo,\n"
<< std::string(CC->getName().size()+13, ' ')
<< "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n";
// Emit all of the actions, in order.
@@ -163,12 +163,12 @@ void CallingConvEmitter::EmitAction(Record *Action,
O << Size << ", ";
else
O << "\n" << IndentStr << " State.getTarget().getTargetData()"
- "->getTypeAllocSize(LocVT.getTypeForMVT()), ";
+ "->getTypeAllocSize(LocVT.getTypeForEVT(State.getContext())), ";
if (Align)
O << Align;
else
O << "\n" << IndentStr << " State.getTarget().getTargetData()"
- "->getABITypeAlignment(LocVT.getTypeForMVT())";
+ "->getABITypeAlignment(LocVT.getTypeForEVT(State.getContext()))";
O << ");\n" << IndentStr
<< "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
<< Counter << ", LocVT, LocInfo));\n";
@@ -186,6 +186,10 @@ void CallingConvEmitter::EmitAction(Record *Action,
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");
diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp
index 6466025..7e6c769 100644
--- a/utils/TableGen/CodeEmitterGen.cpp
+++ b/utils/TableGen/CodeEmitterGen.cpp
@@ -29,7 +29,7 @@ void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) {
R->getName() == "DBG_LABEL" ||
R->getName() == "EH_LABEL" ||
R->getName() == "GC_LABEL" ||
- R->getName() == "DECLARE" ||
+ R->getName() == "KILL" ||
R->getName() == "EXTRACT_SUBREG" ||
R->getName() == "INSERT_SUBREG" ||
R->getName() == "IMPLICIT_DEF" ||
@@ -106,7 +106,7 @@ void CodeEmitterGen::run(raw_ostream &o) {
R->getName() == "DBG_LABEL" ||
R->getName() == "EH_LABEL" ||
R->getName() == "GC_LABEL" ||
- R->getName() == "DECLARE" ||
+ R->getName() == "KILL" ||
R->getName() == "EXTRACT_SUBREG" ||
R->getName() == "INSERT_SUBREG" ||
R->getName() == "IMPLICIT_DEF" ||
@@ -144,7 +144,7 @@ void CodeEmitterGen::run(raw_ostream &o) {
InstName == "DBG_LABEL"||
InstName == "EH_LABEL"||
InstName == "GC_LABEL"||
- InstName == "DECLARE"||
+ InstName == "KILL"||
InstName == "EXTRACT_SUBREG" ||
InstName == "INSERT_SUBREG" ||
InstName == "IMPLICIT_DEF" ||
@@ -243,8 +243,10 @@ void CodeEmitterGen::run(raw_ostream &o) {
// Default case: unhandled opcode
o << " default:\n"
- << " cerr << \"Not supported instr: \" << MI << \"\\n\";\n"
- << " abort();\n"
+ << " std::string msg;\n"
+ << " raw_string_ostream Msg(msg);\n"
+ << " Msg << \"Not supported instr: \" << MI;\n"
+ << " llvm_report_error(Msg.str());\n"
<< " }\n"
<< " return Value;\n"
<< "}\n\n";
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index 2289ae7..6b8ceae 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -55,15 +55,15 @@ ConvertVTs(const std::vector<MVT::SimpleValueType> &InVTs) {
}
static inline bool isInteger(MVT::SimpleValueType VT) {
- return MVT(VT).isInteger();
+ return EVT(VT).isInteger();
}
static inline bool isFloatingPoint(MVT::SimpleValueType VT) {
- return MVT(VT).isFloatingPoint();
+ return EVT(VT).isFloatingPoint();
}
static inline bool isVector(MVT::SimpleValueType VT) {
- return MVT(VT).isVector();
+ return EVT(VT).isVector();
}
static bool LHSIsSubsetOfRHS(const std::vector<unsigned char> &LHS,
@@ -76,23 +76,33 @@ static bool LHSIsSubsetOfRHS(const std::vector<unsigned char> &LHS,
}
namespace llvm {
-namespace EMVT {
+namespace EEVT {
/// isExtIntegerInVTs - Return true if the specified extended value type vector
-/// contains isInt or an integer value type.
+/// contains iAny or an integer value type.
bool isExtIntegerInVTs(const std::vector<unsigned char> &EVTs) {
assert(!EVTs.empty() && "Cannot check for integer in empty ExtVT list!");
- return EVTs[0] == isInt || !(FilterEVTs(EVTs, isInteger).empty());
+ return EVTs[0] == MVT::iAny || !(FilterEVTs(EVTs, isInteger).empty());
}
/// isExtFloatingPointInVTs - Return true if the specified extended value type
-/// vector contains isFP or a FP value type.
+/// vector contains fAny or a FP value type.
bool isExtFloatingPointInVTs(const std::vector<unsigned char> &EVTs) {
- assert(!EVTs.empty() && "Cannot check for integer in empty ExtVT list!");
- return EVTs[0] == isFP || !(FilterEVTs(EVTs, isFloatingPoint).empty());
+ assert(!EVTs.empty() && "Cannot check for FP in empty ExtVT list!");
+ return EVTs[0] == MVT::fAny || !(FilterEVTs(EVTs, isFloatingPoint).empty());
+}
+
+/// isExtVectorInVTs - Return true if the specified extended value type
+/// vector contains vAny or a vector value type.
+bool isExtVectorInVTs(const std::vector<unsigned char> &EVTs) {
+ assert(!EVTs.empty() && "Cannot check for vector in empty ExtVT list!");
+ return EVTs[0] == MVT::vAny || !(FilterEVTs(EVTs, isVector).empty());
}
-} // end namespace EMVT.
+} // end namespace EEVT.
} // end namespace llvm.
+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;
@@ -128,14 +138,14 @@ void FindDepVars(TreePatternNode *N, MultipleUseVarSet &DepVars) {
//! Dump the dependent variable set:
void DumpDepVars(MultipleUseVarSet &DepVars) {
if (DepVars.empty()) {
- DOUT << "<empty set>";
+ DEBUG(errs() << "<empty set>");
} else {
- DOUT << "[ ";
+ DEBUG(errs() << "[ ");
for (MultipleUseVarSet::const_iterator i = DepVars.begin(), e = DepVars.end();
i != e; ++i) {
- DOUT << (*i) << " ";
+ DEBUG(errs() << (*i) << " ");
}
- DOUT << "]";
+ DEBUG(errs() << "]");
}
}
}
@@ -183,6 +193,8 @@ SDTypeConstraint::SDTypeConstraint(Record *R) {
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");
@@ -264,7 +276,7 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
// If we found exactly one supported integer type, apply it.
if (IntVTs.size() == 1)
return NodeToApply->UpdateNodeType(IntVTs[0], TP);
- return NodeToApply->UpdateNodeType(EMVT::isInt, TP);
+ return NodeToApply->UpdateNodeType(MVT::iAny, TP);
}
case SDTCisFP: {
// If there is only one FP type supported, this must be it.
@@ -274,7 +286,17 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
// If we found exactly one supported FP type, apply it.
if (FPVTs.size() == 1)
return NodeToApply->UpdateNodeType(FPVTs[0], TP);
- return NodeToApply->UpdateNodeType(EMVT::isFP, TP);
+ return NodeToApply->UpdateNodeType(MVT::fAny, TP);
+ }
+ case SDTCisVec: {
+ // If there is only one vector type supported, this must be it.
+ std::vector<MVT::SimpleValueType> VecVTs =
+ FilterVTs(CGT.getLegalValueTypes(), isVector);
+
+ // If we found exactly one supported vector type, apply it.
+ if (VecVTs.size() == 1)
+ return NodeToApply->UpdateNodeType(VecVTs[0], TP);
+ return NodeToApply->UpdateNodeType(MVT::vAny, TP);
}
case SDTCisSameAs: {
TreePatternNode *OtherNode =
@@ -300,7 +322,7 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
// It must be integer.
bool MadeChange = false;
- MadeChange |= OtherNode->UpdateNodeType(EMVT::isInt, TP);
+ MadeChange |= OtherNode->UpdateNodeType(MVT::iAny, TP);
// This code only handles nodes that have one type set. Assert here so
// that we can change this if we ever need to deal with multiple value
@@ -320,25 +342,25 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
// 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(!(EMVT::isExtIntegerInVTs(NodeToApply->getExtTypes()) &&
- EMVT::isExtFloatingPointInVTs(NodeToApply->getExtTypes())) &&
- !(EMVT::isExtIntegerInVTs(BigOperand->getExtTypes()) &&
- EMVT::isExtFloatingPointInVTs(BigOperand->getExtTypes())) &&
+ assert(!(EEVT::isExtIntegerInVTs(NodeToApply->getExtTypes()) &&
+ EEVT::isExtFloatingPointInVTs(NodeToApply->getExtTypes())) &&
+ !(EEVT::isExtIntegerInVTs(BigOperand->getExtTypes()) &&
+ EEVT::isExtFloatingPointInVTs(BigOperand->getExtTypes())) &&
"SDTCisOpSmallerThanOp does not handle mixed int/fp types!");
- if (EMVT::isExtIntegerInVTs(NodeToApply->getExtTypes()))
- MadeChange |= BigOperand->UpdateNodeType(EMVT::isInt, TP);
- else if (EMVT::isExtFloatingPointInVTs(NodeToApply->getExtTypes()))
- MadeChange |= BigOperand->UpdateNodeType(EMVT::isFP, TP);
- if (EMVT::isExtIntegerInVTs(BigOperand->getExtTypes()))
- MadeChange |= NodeToApply->UpdateNodeType(EMVT::isInt, TP);
- else if (EMVT::isExtFloatingPointInVTs(BigOperand->getExtTypes()))
- MadeChange |= NodeToApply->UpdateNodeType(EMVT::isFP, TP);
+ if (EEVT::isExtIntegerInVTs(NodeToApply->getExtTypes()))
+ MadeChange |= BigOperand->UpdateNodeType(MVT::iAny, TP);
+ else if (EEVT::isExtFloatingPointInVTs(NodeToApply->getExtTypes()))
+ MadeChange |= BigOperand->UpdateNodeType(MVT::fAny, TP);
+ if (EEVT::isExtIntegerInVTs(BigOperand->getExtTypes()))
+ MadeChange |= NodeToApply->UpdateNodeType(MVT::iAny, TP);
+ else if (EEVT::isExtFloatingPointInVTs(BigOperand->getExtTypes()))
+ MadeChange |= NodeToApply->UpdateNodeType(MVT::fAny, TP);
std::vector<MVT::SimpleValueType> VTs = CGT.getLegalValueTypes();
- if (EMVT::isExtIntegerInVTs(NodeToApply->getExtTypes())) {
+ if (EEVT::isExtIntegerInVTs(NodeToApply->getExtTypes())) {
VTs = FilterVTs(VTs, isInteger);
- } else if (EMVT::isExtFloatingPointInVTs(NodeToApply->getExtTypes())) {
+ } else if (EEVT::isExtFloatingPointInVTs(NodeToApply->getExtTypes())) {
VTs = FilterVTs(VTs, isFloatingPoint);
} else {
VTs.clear();
@@ -368,9 +390,9 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
if (OtherOperand->hasTypeSet()) {
if (!isVector(OtherOperand->getTypeNum(0)))
TP.error(N->getOperator()->getName() + " VT operand must be a vector!");
- MVT IVT = OtherOperand->getTypeNum(0);
+ EVT IVT = OtherOperand->getTypeNum(0);
IVT = IVT.getVectorElementType();
- return NodeToApply->UpdateNodeType(IVT.getSimpleVT(), TP);
+ return NodeToApply->UpdateNodeType(IVT.getSimpleVT().SimpleTy, TP);
}
return false;
}
@@ -445,7 +467,7 @@ bool TreePatternNode::UpdateNodeType(const std::vector<unsigned char> &ExtVTs,
TreePattern &TP) {
assert(!ExtVTs.empty() && "Cannot update node type with empty type vector!");
- if (ExtVTs[0] == EMVT::isUnknown || LHSIsSubsetOfRHS(getExtTypes(), ExtVTs))
+ if (ExtVTs[0] == EEVT::isUnknown || LHSIsSubsetOfRHS(getExtTypes(), ExtVTs))
return false;
if (isTypeCompletelyUnknown() || LHSIsSubsetOfRHS(ExtVTs, getExtTypes())) {
setTypes(ExtVTs);
@@ -454,9 +476,9 @@ bool TreePatternNode::UpdateNodeType(const std::vector<unsigned char> &ExtVTs,
if (getExtTypeNum(0) == MVT::iPTR || getExtTypeNum(0) == MVT::iPTRAny) {
if (ExtVTs[0] == MVT::iPTR || ExtVTs[0] == MVT::iPTRAny ||
- ExtVTs[0] == EMVT::isInt)
+ ExtVTs[0] == MVT::iAny)
return false;
- if (EMVT::isExtIntegerInVTs(ExtVTs)) {
+ if (EEVT::isExtIntegerInVTs(ExtVTs)) {
std::vector<unsigned char> FVTs = FilterEVTs(ExtVTs, isInteger);
if (FVTs.size()) {
setTypes(ExtVTs);
@@ -465,8 +487,19 @@ bool TreePatternNode::UpdateNodeType(const std::vector<unsigned char> &ExtVTs,
}
}
- if ((ExtVTs[0] == EMVT::isInt || ExtVTs[0] == MVT::iAny) &&
- EMVT::isExtIntegerInVTs(getExtTypes())) {
+ // Merge vAny with iAny/fAny. The latter include vector types so keep them
+ // as the more specific information.
+ if (ExtVTs[0] == MVT::vAny &&
+ (getExtTypeNum(0) == MVT::iAny || getExtTypeNum(0) == MVT::fAny))
+ return false;
+ if (getExtTypeNum(0) == MVT::vAny &&
+ (ExtVTs[0] == MVT::iAny || ExtVTs[0] == MVT::fAny)) {
+ setTypes(ExtVTs);
+ return true;
+ }
+
+ if (ExtVTs[0] == MVT::iAny &&
+ EEVT::isExtIntegerInVTs(getExtTypes())) {
assert(hasTypeSet() && "should be handled above!");
std::vector<unsigned char> FVTs = FilterEVTs(getExtTypes(), isInteger);
if (getExtTypes() == FVTs)
@@ -475,7 +508,7 @@ bool TreePatternNode::UpdateNodeType(const std::vector<unsigned char> &ExtVTs,
return true;
}
if ((ExtVTs[0] == MVT::iPTR || ExtVTs[0] == MVT::iPTRAny) &&
- EMVT::isExtIntegerInVTs(getExtTypes())) {
+ EEVT::isExtIntegerInVTs(getExtTypes())) {
//assert(hasTypeSet() && "should be handled above!");
std::vector<unsigned char> FVTs = FilterEVTs(getExtTypes(), isInteger);
if (getExtTypes() == FVTs)
@@ -485,8 +518,8 @@ bool TreePatternNode::UpdateNodeType(const std::vector<unsigned char> &ExtVTs,
return true;
}
}
- if ((ExtVTs[0] == EMVT::isFP || ExtVTs[0] == MVT::fAny) &&
- EMVT::isExtFloatingPointInVTs(getExtTypes())) {
+ if (ExtVTs[0] == MVT::fAny &&
+ EEVT::isExtFloatingPointInVTs(getExtTypes())) {
assert(hasTypeSet() && "should be handled above!");
std::vector<unsigned char> FVTs =
FilterEVTs(getExtTypes(), isFloatingPoint);
@@ -495,20 +528,31 @@ bool TreePatternNode::UpdateNodeType(const std::vector<unsigned char> &ExtVTs,
setTypes(FVTs);
return true;
}
-
- // If we know this is an int or fp type, and we are told it is a specific one,
- // take the advice.
+ if (ExtVTs[0] == MVT::vAny &&
+ EEVT::isExtVectorInVTs(getExtTypes())) {
+ assert(hasTypeSet() && "should be handled above!");
+ std::vector<unsigned char> FVTs = FilterEVTs(getExtTypes(), isVector);
+ if (getExtTypes() == FVTs)
+ return false;
+ setTypes(FVTs);
+ return true;
+ }
+
+ // If we know this is an int, FP, or vector type, and we are told it is a
+ // specific one, take the advice.
//
// Similarly, we should probably set the type here to the intersection of
- // {isInt|isFP} and ExtVTs
- if (((getExtTypeNum(0) == EMVT::isInt || getExtTypeNum(0) == MVT::iAny) &&
- EMVT::isExtIntegerInVTs(ExtVTs)) ||
- ((getExtTypeNum(0) == EMVT::isFP || getExtTypeNum(0) == MVT::fAny) &&
- EMVT::isExtFloatingPointInVTs(ExtVTs))) {
+ // {iAny|fAny|vAny} and ExtVTs
+ if ((getExtTypeNum(0) == MVT::iAny &&
+ EEVT::isExtIntegerInVTs(ExtVTs)) ||
+ (getExtTypeNum(0) == MVT::fAny &&
+ EEVT::isExtFloatingPointInVTs(ExtVTs)) ||
+ (getExtTypeNum(0) == MVT::vAny &&
+ EEVT::isExtVectorInVTs(ExtVTs))) {
setTypes(ExtVTs);
return true;
}
- if (getExtTypeNum(0) == EMVT::isInt &&
+ if (getExtTypeNum(0) == MVT::iAny &&
(ExtVTs[0] == MVT::iPTR || ExtVTs[0] == MVT::iPTRAny)) {
setTypes(ExtVTs);
return true;
@@ -537,14 +581,15 @@ void TreePatternNode::print(raw_ostream &OS) const {
// nodes that are multiply typed.
switch (getExtTypeNum(0)) {
case MVT::Other: OS << ":Other"; break;
- case EMVT::isInt: OS << ":isInt"; break;
- case EMVT::isFP : OS << ":isFP"; break;
- case EMVT::isUnknown: ; /*OS << ":?";*/ break;
+ case MVT::iAny: OS << ":iAny"; break;
+ case MVT::fAny : OS << ":fAny"; break;
+ case MVT::vAny: OS << ":vAny"; break;
+ case EEVT::isUnknown: ; /*OS << ":?";*/ break;
case MVT::iPTR: OS << ":iPTR"; break;
case MVT::iPTRAny: OS << ":iPTRAny"; break;
default: {
std::string VTName = llvm::getName(getTypeNum(0));
- // Strip off MVT:: prefix if present.
+ // Strip off EVT:: prefix if present.
if (VTName.substr(0,5) == "MVT::")
VTName = VTName.substr(5);
OS << ":" << VTName;
@@ -726,7 +771,7 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
static std::vector<unsigned char> getImplicitType(Record *R, bool NotRegisters,
TreePattern &TP) {
// Some common return values
- std::vector<unsigned char> Unknown(1, EMVT::isUnknown);
+ std::vector<unsigned char> Unknown(1, EEVT::isUnknown);
std::vector<unsigned char> Other(1, MVT::Other);
// Check to see if this is a register or a register class...
@@ -753,7 +798,7 @@ static std::vector<unsigned char> getImplicitType(Record *R, bool NotRegisters,
std::vector<unsigned char>
ComplexPat(1, TP.getDAGPatterns().getComplexPattern(R).getValueType());
return ComplexPat;
- } else if (R->getName() == "ptr_rc") {
+ } else if (R->isSubClassOf("PointerLikeRegClass")) {
Other[0] = MVT::iPTR;
return Other;
} else if (R->getName() == "node" || R->getName() == "srcvalue" ||
@@ -803,7 +848,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
return UpdateNodeType(getImplicitType(DI->getDef(), NotRegisters, TP),TP);
} else if (IntInit *II = dynamic_cast<IntInit*>(getLeafValue())) {
// Int inits are always integers. :)
- bool MadeChange = UpdateNodeType(EMVT::isInt, TP);
+ bool MadeChange = UpdateNodeType(MVT::iAny, TP);
if (hasTypeSet()) {
// At some point, it may make sense for this tree pattern to have
@@ -816,7 +861,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
VT = getTypeNum(0);
if (VT != MVT::iPTR && VT != MVT::iPTRAny) {
- unsigned Size = MVT(VT).getSizeInBits();
+ unsigned Size = EVT(VT).getSizeInBits();
// Make sure that the value is representable for this type.
if (Size < 32) {
int Val = (II->getValue() << (32-Size)) >> (32-Size);
@@ -924,13 +969,13 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
} else {
Record *ResultNode = Inst.getResult(0);
- if (ResultNode->getName() == "ptr_rc") {
+ if (ResultNode->isSubClassOf("PointerLikeRegClass")) {
std::vector<unsigned char> VT;
VT.push_back(MVT::iPTR);
MadeChange = UpdateNodeType(VT, TP);
} else if (ResultNode->getName() == "unknown") {
std::vector<unsigned char> VT;
- VT.push_back(EMVT::isUnknown);
+ VT.push_back(EEVT::isUnknown);
MadeChange = UpdateNodeType(VT, TP);
} else {
assert(ResultNode->isSubClassOf("RegisterClass") &&
@@ -968,10 +1013,10 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
} else if (OperandNode->isSubClassOf("Operand")) {
VT = getValueType(OperandNode->getValueAsDef("Type"));
MadeChange |= Child->UpdateNodeType(VT, TP);
- } else if (OperandNode->getName() == "ptr_rc") {
+ } else if (OperandNode->isSubClassOf("PointerLikeRegClass")) {
MadeChange |= Child->UpdateNodeType(MVT::iPTR, TP);
} else if (OperandNode->getName() == "unknown") {
- MadeChange |= Child->UpdateNodeType(EMVT::isUnknown, TP);
+ MadeChange |= Child->UpdateNodeType(EEVT::isUnknown, TP);
} else {
assert(0 && "Unknown operand type!");
abort();
@@ -1297,7 +1342,7 @@ CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : Records(R) {
}
CodeGenDAGPatterns::~CodeGenDAGPatterns() {
- for (std::map<Record*, TreePattern*>::iterator I = PatternFragments.begin(),
+ for (pf_iterator I = PatternFragments.begin(),
E = PatternFragments.end(); I != E; ++I)
delete I->second;
}
@@ -1602,7 +1647,7 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
I->error("set destination should be a register!");
if (Val->getDef()->isSubClassOf("RegisterClass") ||
- Val->getDef()->getName() == "ptr_rc") {
+ Val->getDef()->isSubClassOf("PointerLikeRegClass")) {
if (Dest->getName().empty())
I->error("set destination must have a name!");
if (InstResults.count(Dest->getName()))
@@ -1949,7 +1994,8 @@ void CodeGenDAGPatterns::ParseInstructions() {
}
// If we can, convert the instructions to be patterns that are matched!
- for (std::map<Record*, DAGInstruction>::iterator II = Instructions.begin(),
+ 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();
@@ -2350,7 +2396,7 @@ static void GenerateVariantsOf(TreePatternNode *N,
// GenerateVariants - Generate variants. For example, commutative patterns can
// match multiple ways. Add them to PatternsToMatch as well.
void CodeGenDAGPatterns::GenerateVariants() {
- DOUT << "Generating instruction variants.\n";
+ 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
@@ -2365,9 +2411,9 @@ void CodeGenDAGPatterns::GenerateVariants() {
MultipleUseVarSet DepVars;
std::vector<TreePatternNode*> Variants;
FindDepVars(PatternsToMatch[i].getSrcPattern(), DepVars);
- DOUT << "Dependent/multiply used variables: ";
+ DEBUG(errs() << "Dependent/multiply used variables: ");
DEBUG(DumpDepVars(DepVars));
- DOUT << "\n";
+ DEBUG(errs() << "\n");
GenerateVariantsOf(PatternsToMatch[i].getSrcPattern(), Variants, *this, DepVars);
assert(!Variants.empty() && "Must create at least original variant!");
@@ -2376,16 +2422,16 @@ void CodeGenDAGPatterns::GenerateVariants() {
if (Variants.empty()) // No variants for this pattern.
continue;
- DOUT << "FOUND VARIANTS OF: ";
- DEBUG(PatternsToMatch[i].getSrcPattern()->dump());
- DOUT << "\n";
+ 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];
- DOUT << " VAR#" << v << ": ";
- DEBUG(Variant->dump());
- DOUT << "\n";
+ DEBUG(errs() << " VAR#" << v << ": ";
+ Variant->dump();
+ errs() << "\n");
// Scan to see if an instruction or explicit pattern already matches this.
bool AlreadyExists = false;
@@ -2396,7 +2442,7 @@ void CodeGenDAGPatterns::GenerateVariants() {
continue;
// Check to see if this variant already exists.
if (Variant->isIsomorphicTo(PatternsToMatch[p].getSrcPattern(), DepVars)) {
- DOUT << " *** ALREADY EXISTS, ignoring variant.\n";
+ DEBUG(errs() << " *** ALREADY EXISTS, ignoring variant.\n");
AlreadyExists = true;
break;
}
@@ -2412,7 +2458,7 @@ void CodeGenDAGPatterns::GenerateVariants() {
PatternsToMatch[i].getAddedComplexity()));
}
- DOUT << "\n";
+ DEBUG(errs() << "\n");
}
}
diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h
index d398006..9b53ecc5 100644
--- a/utils/TableGen/CodeGenDAGPatterns.h
+++ b/utils/TableGen/CodeGenDAGPatterns.h
@@ -33,22 +33,27 @@ namespace llvm {
class CodeGenDAGPatterns;
class ComplexPattern;
-/// EMVT::DAGISelGenValueType - These are some extended forms of
+/// EEVT::DAGISelGenValueType - These are some extended forms of
/// MVT::SimpleValueType that we use as lattice values during type inference.
-namespace EMVT {
+/// 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 {
enum DAGISelGenValueType {
- isFP = MVT::LAST_VALUETYPE,
- isInt,
- isUnknown
+ isUnknown = MVT::LAST_VALUETYPE
};
- /// isExtIntegerVT - Return true if the specified extended value type vector
- /// contains isInt or an integer value type.
+ /// isExtIntegerInVTs - Return true if the specified extended value type
+ /// vector contains iAny or an integer value type.
bool isExtIntegerInVTs(const std::vector<unsigned char> &EVTs);
- /// isExtFloatingPointVT - Return true if the specified extended value type
- /// vector contains isFP or a FP value type.
+ /// isExtFloatingPointInVTs - Return true if the specified extended value
+ /// type vector contains fAny or a FP value type.
bool isExtFloatingPointInVTs(const std::vector<unsigned char> &EVTs);
+
+ /// isExtVectorinVTs - Return true if the specified extended value type
+ /// vector contains vAny or a vector value type.
+ bool isExtVectorInVTs(const std::vector<unsigned char> &EVTs);
}
/// Set type used to track multiply used variables in patterns
@@ -61,7 +66,7 @@ struct SDTypeConstraint {
unsigned OperandNo; // The operand # this constraint applies to.
enum {
- SDTCisVT, SDTCisPtrTy, SDTCisInt, SDTCisFP, SDTCisSameAs,
+ SDTCisVT, SDTCisPtrTy, SDTCisInt, SDTCisFP, SDTCisVec, SDTCisSameAs,
SDTCisVTSmallerThanOp, SDTCisOpSmallerThanOp, SDTCisEltOfVec
} ConstraintType;
@@ -140,7 +145,7 @@ public:
/// patterns), and as such should be ref counted. We currently just leak all
/// TreePatternNode objects!
class TreePatternNode {
- /// The inferred type for this node, or EMVT::isUnknown if it hasn't
+ /// The inferred type for this node, or EEVT::isUnknown if it hasn't
/// been determined yet. This is a std::vector because during inference
/// there may be multiple possible types.
std::vector<unsigned char> Types;
@@ -169,10 +174,10 @@ class TreePatternNode {
public:
TreePatternNode(Record *Op, const std::vector<TreePatternNode*> &Ch)
: Types(), Operator(Op), Val(0), TransformFn(0),
- Children(Ch) { Types.push_back(EMVT::isUnknown); }
+ Children(Ch) { Types.push_back(EEVT::isUnknown); }
TreePatternNode(Init *val) // leaf ctor
: Types(), Operator(0), Val(val), TransformFn(0) {
- Types.push_back(EMVT::isUnknown);
+ Types.push_back(EEVT::isUnknown);
}
~TreePatternNode();
@@ -185,7 +190,7 @@ public:
(Types[0] == MVT::iPTRAny);
}
bool isTypeCompletelyUnknown() const {
- return Types[0] == EMVT::isUnknown;
+ return Types[0] == EEVT::isUnknown;
}
bool isTypeDynamicallyResolved() const {
return (Types[0] == MVT::iPTR) || (Types[0] == MVT::iPTRAny);
@@ -201,7 +206,7 @@ public:
}
const std::vector<unsigned char> &getExtTypes() const { return Types; }
void setTypes(const std::vector<unsigned char> &T) { Types = T; }
- void removeTypes() { Types = std::vector<unsigned char>(1, EMVT::isUnknown); }
+ void removeTypes() { Types = std::vector<unsigned char>(1, EEVT::isUnknown); }
Init *getLeafValue() const { assert(isLeaf()); return Val; }
Record *getOperator() const { assert(!isLeaf()); return Operator; }
@@ -457,6 +462,10 @@ struct PatternToMatch {
std::string getPredicateCheck() const;
};
+// Deterministic comparison of Record*.
+struct RecordPtrCmp {
+ bool operator()(const Record *LHS, const Record *RHS) const;
+};
class CodeGenDAGPatterns {
RecordKeeper &Records;
@@ -464,12 +473,12 @@ class CodeGenDAGPatterns {
std::vector<CodeGenIntrinsic> Intrinsics;
std::vector<CodeGenIntrinsic> TgtIntrinsics;
- std::map<Record*, SDNodeInfo> SDNodes;
- std::map<Record*, std::pair<Record*, std::string> > SDNodeXForms;
- std::map<Record*, ComplexPattern> ComplexPatterns;
- std::map<Record*, TreePattern*> PatternFragments;
- std::map<Record*, DAGDefaultOperand> DefaultOperands;
- std::map<Record*, DAGInstruction> Instructions;
+ 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;
@@ -500,7 +509,8 @@ public:
return SDNodeXForms.find(R)->second;
}
- typedef std::map<Record*, NodeXForm>::const_iterator nx_iterator;
+ 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(); }
@@ -547,7 +557,8 @@ public:
assert(PatternFragments.count(R) && "Invalid pattern fragment request!");
return PatternFragments.find(R)->second;
}
- typedef std::map<Record*, TreePattern*>::const_iterator pf_iterator;
+ 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(); }
diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp
index 4650b88..d421fd0 100644
--- a/utils/TableGen/CodeGenInstruction.cpp
+++ b/utils/TableGen/CodeGenInstruction.cpp
@@ -22,7 +22,7 @@ static void ParseConstraint(const std::string &CStr, CodeGenInstruction *I) {
std::string::size_type pos = CStr.find_first_of('=');
assert(pos != std::string::npos && "Unrecognized constraint");
std::string::size_type start = CStr.find_first_not_of(" \t");
- std::string Name = CStr.substr(start, pos);
+ std::string Name = CStr.substr(start, pos - start);
// TIED_TO: $src1 = $dst
std::string::size_type wpos = Name.find_first_of(" \t");
@@ -70,7 +70,7 @@ static void ParseConstraints(const std::string &CStr, CodeGenInstruction *I) {
if (eidx == std::string::npos)
eidx = CStr.length();
- ParseConstraint(CStr.substr(bidx, eidx), I);
+ ParseConstraint(CStr.substr(bidx, eidx - bidx), I);
bidx = CStr.find_first_not_of(delims, eidx);
}
}
@@ -101,6 +101,8 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
mayHaveSideEffects = R->getValueAsBit("mayHaveSideEffects");
neverHasSideEffects = R->getValueAsBit("neverHasSideEffects");
isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove");
+ hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq");
+ hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq");
hasOptionalDef = false;
isVariadic = false;
diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h
index f4afd5e..04506e9 100644
--- a/utils/TableGen/CodeGenInstruction.h
+++ b/utils/TableGen/CodeGenInstruction.h
@@ -106,6 +106,8 @@ namespace llvm {
bool mayHaveSideEffects;
bool neverHasSideEffects;
bool isAsCheapAsAMove;
+ bool hasExtraSrcRegAllocReq;
+ bool hasExtraDefRegAllocReq;
/// ParseOperandName - Parse an operand name like "$foo" or "$foo.bar",
/// where $foo is a whole operand and $foo.bar refers to a suboperand.
diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp
index c17cd0e..0edca73 100644
--- a/utils/TableGen/CodeGenTarget.cpp
+++ b/utils/TableGen/CodeGenTarget.cpp
@@ -23,6 +23,10 @@
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"));
@@ -34,47 +38,10 @@ MVT::SimpleValueType llvm::getValueType(Record *Rec) {
std::string llvm::getName(MVT::SimpleValueType T) {
switch (T) {
- case MVT::Other: return "UNKNOWN";
- 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::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::Flag: return "MVT::Flag";
- 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::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::v3i32: return "MVT::v3i32";
- case MVT::v3f32: return "MVT::v3f32";
- case MVT::iPTR: return "TLI.getPointerTy()";
- case MVT::iPTRAny: return "TLI.getPointerTy()";
- default: assert(0 && "ILLEGAL VALUE TYPE!"); return "";
+ case MVT::Other: return "UNKNOWN";
+ case MVT::iPTR: return "TLI.getPointerTy()";
+ case MVT::iPTRAny: return "TLI.getPointerTy()";
+ default: return getEnumName(T);
}
}
@@ -89,6 +56,7 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) {
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::f32: return "MVT::f32";
case MVT::f64: return "MVT::f64";
case MVT::f80: return "MVT::f80";
@@ -116,8 +84,7 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::v8f32: return "MVT::v8f32";
case MVT::v2f64: return "MVT::v2f64";
case MVT::v4f64: return "MVT::v4f64";
- case MVT::v3i32: return "MVT::v3i32";
- case MVT::v3f32: return "MVT::v3f32";
+ case MVT::Metadata: return "MVT::Metadata";
case MVT::iPTR: return "MVT::iPTR";
case MVT::iPTRAny: return "MVT::iPTRAny";
default: assert(0 && "ILLEGAL VALUE TYPE!"); return "";
@@ -171,6 +138,15 @@ 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];
+}
+
/// getAsmWriter - Return the AssemblyWriter definition for this target.
///
Record *CodeGenTarget::getAsmWriter() const {
@@ -265,7 +241,7 @@ CodeGenRegisterClass::CodeGenRegisterClass(Record *R) : TheDef(R) {
unsigned Size = R->getValueAsInt("Size");
Namespace = R->getValueAsString("Namespace");
- SpillSize = Size ? Size : MVT(VTs[0]).getSizeInBits();
+ SpillSize = Size ? Size : EVT(VTs[0]).getSizeInBits();
SpillAlignment = R->getValueAsInt("Alignment");
CopyCost = R->getValueAsInt("CopyCost");
MethodBodies = R->getValueAsCode("MethodBodies");
@@ -332,9 +308,9 @@ getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
if (I == Instructions.end()) throw "Could not find 'GC_LABEL' instruction!";
const CodeGenInstruction *GC_LABEL = &I->second;
- I = getInstructions().find("DECLARE");
- if (I == Instructions.end()) throw "Could not find 'DECLARE' instruction!";
- const CodeGenInstruction *DECLARE = &I->second;
+ I = getInstructions().find("KILL");
+ if (I == Instructions.end()) throw "Could not find 'KILL' instruction!";
+ const CodeGenInstruction *KILL = &I->second;
I = getInstructions().find("EXTRACT_SUBREG");
if (I == Instructions.end())
@@ -367,7 +343,7 @@ getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
NumberedInstructions.push_back(DBG_LABEL);
NumberedInstructions.push_back(EH_LABEL);
NumberedInstructions.push_back(GC_LABEL);
- NumberedInstructions.push_back(DECLARE);
+ NumberedInstructions.push_back(KILL);
NumberedInstructions.push_back(EXTRACT_SUBREG);
NumberedInstructions.push_back(INSERT_SUBREG);
NumberedInstructions.push_back(IMPLICIT_DEF);
@@ -379,7 +355,7 @@ getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
&II->second != DBG_LABEL &&
&II->second != EH_LABEL &&
&II->second != GC_LABEL &&
- &II->second != DECLARE &&
+ &II->second != KILL &&
&II->second != EXTRACT_SUBREG &&
&II->second != INSERT_SUBREG &&
&II->second != IMPLICIT_DEF &&
@@ -517,11 +493,12 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
// overloaded, all the types can be specified directly.
assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") &&
!TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) ||
- VT == MVT::iAny) && "Expected iAny type");
+ VT == MVT::iAny || VT == MVT::vAny) &&
+ "Expected iAny or vAny type");
} else {
VT = getValueType(TyEl->getValueAsDef("VT"));
}
- if (VT == MVT::iAny || VT == MVT::fAny || VT == MVT::iPTRAny) {
+ if (EVT(VT).isOverloaded()) {
OverloadedVTs.push_back(VT);
isOverloaded |= true;
}
@@ -548,10 +525,11 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
// overloaded, all the types can be specified directly.
assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") &&
!TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) ||
- VT == MVT::iAny) && "Expected iAny type");
+ VT == MVT::iAny || VT == MVT::vAny) &&
+ "Expected iAny or vAny type");
} else
VT = getValueType(TyEl->getValueAsDef("VT"));
- if (VT == MVT::iAny || VT == MVT::fAny || VT == MVT::iPTRAny) {
+ if (EVT(VT).isOverloaded()) {
OverloadedVTs.push_back(VT);
isOverloaded |= true;
}
diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h
index 0ec9955..e763795 100644
--- a/utils/TableGen/CodeGenTarget.h
+++ b/utils/TableGen/CodeGenTarget.h
@@ -87,6 +87,10 @@ public:
///
Record *getInstructionSet() const;
+ /// getAsmParser - Return the AssemblyParser definition for this target.
+ ///
+ Record *getAsmParser() const;
+
/// getAsmWriter - Return the AssemblyWriter definition for this target.
///
Record *getAsmWriter() const;
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp
index bb26a1d..dcf64e4 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -23,11 +23,8 @@
#include <iostream>
using namespace llvm;
-namespace {
- cl::opt<bool>
- GenDebug("gen-debug", cl::desc("Generate debug code"),
- cl::init(false));
-}
+static cl::opt<bool>
+GenDebug("gen-debug", cl::desc("Generate debug code"), cl::init(false));
//===----------------------------------------------------------------------===//
// DAGISelEmitter Helper methods
@@ -60,8 +57,8 @@ static const ComplexPattern *NodeGetComplexPattern(TreePatternNode *N,
/// patterns before small ones. This is used to determine the size of a
/// pattern.
static unsigned getPatternSize(TreePatternNode *P, CodeGenDAGPatterns &CGP) {
- assert((EMVT::isExtIntegerInVTs(P->getExtTypes()) ||
- EMVT::isExtFloatingPointInVTs(P->getExtTypes()) ||
+ assert((EEVT::isExtIntegerInVTs(P->getExtTypes()) ||
+ EEVT::isExtFloatingPointInVTs(P->getExtTypes()) ||
P->getExtTypeNum(0) == MVT::isVoid ||
P->getExtTypeNum(0) == MVT::Flag ||
P->getExtTypeNum(0) == MVT::iPTR ||
@@ -698,7 +695,7 @@ public:
if (DefInit *DI = dynamic_cast<DefInit*>(Child->getLeafValue())) {
Record *LeafRec = DI->getDef();
if (LeafRec->isSubClassOf("RegisterClass") ||
- LeafRec->getName() == "ptr_rc") {
+ LeafRec->isSubClassOf("PointerLikeRegClass")) {
// Handle register references. Nothing to do here.
} else if (LeafRec->isSubClassOf("Register")) {
// Handle register references.
@@ -787,7 +784,7 @@ public:
EmitResultCode(TreePatternNode *N, std::vector<Record*> DstRegs,
bool InFlagDecled, bool ResNodeDecled,
bool LikeLeaf = false, bool isRoot = false) {
- // List of arguments of getTargetNode() or SelectNodeTo().
+ // List of arguments of getMachineNode() or SelectNodeTo().
std::vector<std::string> NodeOps;
// This is something selected from the pattern we matched.
if (!N->getName().empty()) {
@@ -932,7 +929,8 @@ public:
unsigned ResNo = TmpNo++;
assert(N->getExtTypes().size() == 1 && "Multiple types not handled!");
emitCode("SDValue Tmp" + utostr(ResNo) +
- " = CurDAG->getTargetConstant(0x" + itohexstr(II->getValue()) +
+ " = CurDAG->getTargetConstant(0x" +
+ utohexstr((uint64_t) II->getValue()) +
"ULL, " + getEnumName(N->getTypeNum(0)) + ");");
NodeOps.push_back("Tmp" + utostr(ResNo));
return NodeOps;
@@ -1091,7 +1089,7 @@ public:
std::string Code = "Opc" + utostr(OpcNo);
if (!isRoot || (InputHasChain && !NodeHasChain))
- // For call to "getTargetNode()".
+ // For call to "getMachineNode()".
Code += ", N.getDebugLoc()";
emitOpcode(II.Namespace + "::" + II.TheDef->getName());
@@ -1137,24 +1135,18 @@ public:
emitCode("}");
}
- // Generate MemOperandSDNodes nodes for each memory accesses covered by
+ // Populate MemRefs with entries for each memory accesses covered by
// this pattern.
- if (II.mayLoad | II.mayStore) {
- std::vector<std::string>::const_iterator mi, mie;
- for (mi = LSI.begin(), mie = LSI.end(); mi != mie; ++mi) {
- std::string LSIName = "LSI_" + *mi;
- emitCode("SDValue " + LSIName + " = "
- "CurDAG->getMemOperand(cast<MemSDNode>(" +
- *mi + ")->getMemOperand());");
- if (GenDebug) {
- emitCode("CurDAG->setSubgraphColor(" + LSIName +".getNode(), \"yellow\");");
- emitCode("CurDAG->setSubgraphColor(" + LSIName +".getNode(), \"black\");");
- }
- if (IsVariadic)
- emitCode("Ops" + utostr(OpsNo) + ".push_back(" + LSIName + ");");
- else
- AllOps.push_back(LSIName);
- }
+ if (isRoot && !LSI.empty()) {
+ std::string MemRefs = "MemRefs" + utostr(OpsNo);
+ emitCode("MachineSDNode::mmo_iterator " + MemRefs + " = "
+ "MF->allocateMemRefsArray(" + utostr(LSI.size()) + ");");
+ for (unsigned i = 0, e = LSI.size(); i != e; ++i)
+ emitCode(MemRefs + "[" + utostr(i) + "] = "
+ "cast<MemSDNode>(" + LSI[i] + ")->getMemOperand();");
+ After.push_back("cast<MachineSDNode>(ResNode)->setMemRefs(" +
+ MemRefs + ", " + MemRefs + " + " + utostr(LSI.size()) +
+ ");");
}
if (NodeHasChain) {
@@ -1305,7 +1297,7 @@ public:
// would leave users of the chain dangling.
//
if (!isRoot || (InputHasChain && !NodeHasChain)) {
- Code = "CurDAG->getTargetNode(" + Code;
+ Code = "CurDAG->getMachineNode(" + Code;
} else {
Code = "CurDAG->SelectNodeTo(N.getNode(), " + Code;
}
@@ -1778,7 +1770,7 @@ void DAGISelEmitter::EmitInstructionSelector(raw_ostream &OS) {
CallerCode += ", " + TargetOpcodes[j];
}
for (unsigned j = 0, e = TargetVTs.size(); j != e; ++j) {
- CalleeCode += ", MVT VT" + utostr(j);
+ CalleeCode += ", MVT::SimpleValueType VT" + utostr(j);
CallerCode += ", " + TargetVTs[j];
}
for (std::set<std::string>::iterator
@@ -1930,7 +1922,7 @@ void DAGISelEmitter::EmitInstructionSelector(raw_ostream &OS) {
<< " std::vector<SDValue> Ops(N.getNode()->op_begin(), N.getNode()->op_end());\n"
<< " SelectInlineAsmMemoryOperands(Ops);\n\n"
- << " std::vector<MVT> VTs;\n"
+ << " std::vector<EVT> VTs;\n"
<< " VTs.push_back(MVT::Other);\n"
<< " VTs.push_back(MVT::Flag);\n"
<< " SDValue New = CurDAG->getNode(ISD::INLINEASM, N.getDebugLoc(), "
@@ -1959,32 +1951,14 @@ void DAGISelEmitter::EmitInstructionSelector(raw_ostream &OS) {
<< " MVT::Other, Tmp, Chain);\n"
<< "}\n\n";
- OS << "SDNode *Select_DECLARE(const SDValue &N) {\n"
- << " SDValue Chain = N.getOperand(0);\n"
- << " SDValue N1 = N.getOperand(1);\n"
- << " SDValue N2 = N.getOperand(2);\n"
- << " if (!isa<FrameIndexSDNode>(N1) || !isa<GlobalAddressSDNode>(N2)) {\n"
- << " CannotYetSelect(N);\n"
- << " }\n"
- << " int FI = cast<FrameIndexSDNode>(N1)->getIndex();\n"
- << " GlobalValue *GV = cast<GlobalAddressSDNode>(N2)->getGlobal();\n"
- << " SDValue Tmp1 = "
- << "CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());\n"
- << " SDValue Tmp2 = "
- << "CurDAG->getTargetGlobalAddress(GV, TLI.getPointerTy());\n"
- << " return CurDAG->SelectNodeTo(N.getNode(), TargetInstrInfo::DECLARE,\n"
- << " MVT::Other, Tmp1, Tmp2, Chain);\n"
- << "}\n\n";
-
OS << "// The main instruction selector code.\n"
<< "SDNode *SelectCode(SDValue N) {\n"
- << " MVT::SimpleValueType NVT = N.getNode()->getValueType(0).getSimpleVT();\n"
+ << " MVT::SimpleValueType NVT = N.getNode()->getValueType(0).getSimpleVT().SimpleTy;\n"
<< " switch (N.getOpcode()) {\n"
<< " default:\n"
<< " assert(!N.isMachineOpcode() && \"Node already selected!\");\n"
<< " break;\n"
<< " case ISD::EntryToken: // These nodes remain the same.\n"
- << " case ISD::MEMOPERAND:\n"
<< " case ISD::BasicBlock:\n"
<< " case ISD::Register:\n"
<< " case ISD::HANDLENODE:\n"
@@ -2009,7 +1983,6 @@ void DAGISelEmitter::EmitInstructionSelector(raw_ostream &OS) {
<< " case ISD::INLINEASM: return Select_INLINEASM(N);\n"
<< " case ISD::DBG_LABEL: return Select_DBG_LABEL(N);\n"
<< " case ISD::EH_LABEL: return Select_EH_LABEL(N);\n"
- << " case ISD::DECLARE: return Select_DECLARE(N);\n"
<< " case ISD::UNDEF: return Select_UNDEF(N);\n";
// Loop over all of the case statements, emiting a call to each method we
@@ -2083,20 +2056,19 @@ void DAGISelEmitter::EmitInstructionSelector(raw_ostream &OS) {
<< "}\n\n";
OS << "void CannotYetSelect(SDValue N) DISABLE_INLINE {\n"
- << " cerr << \"Cannot yet select: \";\n"
- << " N.getNode()->dump(CurDAG);\n"
- << " cerr << '\\n';\n"
- << " abort();\n"
+ << " std::string msg;\n"
+ << " raw_string_ostream Msg(msg);\n"
+ << " Msg << \"Cannot yet select: \";\n"
+ << " N.getNode()->print(Msg, CurDAG);\n"
+ << " llvm_report_error(Msg.str());\n"
<< "}\n\n";
OS << "void CannotYetSelectIntrinsic(SDValue N) DISABLE_INLINE {\n"
- << " cerr << \"Cannot yet select: \";\n"
+ << " errs() << \"Cannot yet select: \";\n"
<< " unsigned iid = cast<ConstantSDNode>(N.getOperand("
<< "N.getOperand(0).getValueType() == MVT::Other))->getZExtValue();\n"
- << " cerr << \"intrinsic %\"<< "
- << "Intrinsic::getName((Intrinsic::ID)iid);\n"
- << " cerr << '\\n';\n"
- << " abort();\n"
+ << " llvm_report_error(\"Cannot yet select: intrinsic %\" +\n"
+ << "Intrinsic::getName((Intrinsic::ID)iid));\n"
<< "}\n\n";
}
@@ -2115,12 +2087,12 @@ void DAGISelEmitter::run(raw_ostream &OS) {
EmitNodeTransforms(OS);
EmitPredicateFunctions(OS);
- DOUT << "\n\nALL PATTERNS TO MATCH:\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) {
- DOUT << "PATTERN: "; DEBUG(I->getSrcPattern()->dump());
- DOUT << "\nRESULT: "; DEBUG(I->getDstPattern()->dump());
- DOUT << "\n";
+ DEBUG(errs() << "PATTERN: "; I->getSrcPattern()->dump());
+ DEBUG(errs() << "\nRESULT: "; I->getDstPattern()->dump());
+ DEBUG(errs() << "\n");
}
// At this point, we have full information about the 'Patterns' we need to
diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp
index 0a43f02..277640d 100644
--- a/utils/TableGen/FastISelEmitter.cpp
+++ b/utils/TableGen/FastISelEmitter.cpp
@@ -216,7 +216,6 @@ public:
explicit FastISelMap(std::string InstNS);
void CollectPatterns(CodeGenDAGPatterns &CGP);
- void PrintClass(raw_ostream &OS);
void PrintFunctionDefinitions(raw_ostream &OS);
};
@@ -461,11 +460,11 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) {
<< getLegalCName(Opcode) << "_"
<< getLegalCName(getName(VT)) << "_";
Operands.PrintManglingSuffix(OS);
- OS << "(MVT::SimpleValueType RetVT";
+ OS << "(MVT RetVT";
if (!Operands.empty())
OS << ", ";
Operands.PrintParameters(OS);
- OS << ") {\nswitch (RetVT) {\n";
+ OS << ") {\nswitch (RetVT.SimpleTy) {\n";
for (RetPredMap::const_iterator RI = RM.begin(), RE = RM.end();
RI != RE; ++RI) {
MVT::SimpleValueType RetVT = RI->first;
@@ -485,13 +484,13 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) {
<< getLegalCName(Opcode) << "_"
<< getLegalCName(getName(VT)) << "_";
Operands.PrintManglingSuffix(OS);
- OS << "(MVT::SimpleValueType RetVT";
+ OS << "(MVT RetVT";
if (!Operands.empty())
OS << ", ";
Operands.PrintParameters(OS);
OS << ") {\n";
- OS << " if (RetVT != " << getName(RM.begin()->first)
+ OS << " if (RetVT.SimpleTy != " << getName(RM.begin()->first)
<< ")\n return 0;\n";
const PredMap &PM = RM.begin()->second;
@@ -555,12 +554,12 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) {
OS << "unsigned FastEmit_"
<< getLegalCName(Opcode) << "_";
Operands.PrintManglingSuffix(OS);
- OS << "(MVT::SimpleValueType VT, MVT::SimpleValueType RetVT";
+ OS << "(MVT VT, MVT RetVT";
if (!Operands.empty())
OS << ", ";
Operands.PrintParameters(OS);
OS << ") {\n";
- OS << " switch (VT) {\n";
+ OS << " switch (VT.SimpleTy) {\n";
for (TypeRetPredMap::const_iterator TI = TM.begin(), TE = TM.end();
TI != TE; ++TI) {
MVT::SimpleValueType VT = TI->first;
@@ -587,7 +586,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) {
// on opcode and type.
OS << "unsigned FastEmit_";
Operands.PrintManglingSuffix(OS);
- OS << "(MVT::SimpleValueType VT, MVT::SimpleValueType RetVT, ISD::NodeType Opcode";
+ OS << "(MVT VT, MVT RetVT, ISD::NodeType Opcode";
if (!Operands.empty())
OS << ", ";
Operands.PrintParameters(OS);
diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
index 4502da1..3a104ea 100644
--- a/utils/TableGen/InstrInfoEmitter.cpp
+++ b/utils/TableGen/InstrInfoEmitter.cpp
@@ -15,6 +15,7 @@
#include "InstrInfoEmitter.h"
#include "CodeGenTarget.h"
#include "Record.h"
+#include "llvm/ADT/StringExtras.h"
#include <algorithm>
using namespace llvm;
@@ -94,13 +95,16 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
if (OpR->isSubClassOf("RegisterClass"))
Res += getQualifiedName(OpR) + "RegClassID, ";
+ else if (OpR->isSubClassOf("PointerLikeRegClass"))
+ Res += utostr(OpR->getValueAsInt("RegClassKind")) + ", ";
else
Res += "0, ";
+
// Fill in applicable flags.
Res += "0";
// Ptr value whose register class is resolved via callback.
- if (OpR->getName() == "ptr_rc")
+ if (OpR->isSubClassOf("PointerLikeRegClass"))
Res += "|(1<<TOI::LookupPtrRegClass)";
// Predicate operands. Check to see if the original unexpanded operand
@@ -276,6 +280,8 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
if (Inst.isVariadic) OS << "|(1<<TID::Variadic)";
if (Inst.hasSideEffects) OS << "|(1<<TID::UnmodeledSideEffects)";
if (Inst.isAsCheapAsAMove) OS << "|(1<<TID::CheapAsAMove)";
+ if (Inst.hasExtraSrcRegAllocReq) OS << "|(1<<TID::ExtraSrcRegAllocReq)";
+ if (Inst.hasExtraDefRegAllocReq) OS << "|(1<<TID::ExtraDefRegAllocReq)";
OS << ", 0";
// Emit all of the target-specific flags...
@@ -335,7 +341,7 @@ void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val,
R->getName() != "DBG_LABEL" &&
R->getName() != "EH_LABEL" &&
R->getName() != "GC_LABEL" &&
- R->getName() != "DECLARE" &&
+ R->getName() != "KILL" &&
R->getName() != "EXTRACT_SUBREG" &&
R->getName() != "INSERT_SUBREG" &&
R->getName() != "IMPLICIT_DEF" &&
diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp
index 3676831..23919d9 100644
--- a/utils/TableGen/IntrinsicEmitter.cpp
+++ b/utils/TableGen/IntrinsicEmitter.cpp
@@ -141,24 +141,26 @@ EmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints,
}
static void EmitTypeForValueType(raw_ostream &OS, MVT::SimpleValueType VT) {
- if (MVT(VT).isInteger()) {
- unsigned BitWidth = MVT(VT).getSizeInBits();
- OS << "IntegerType::get(" << BitWidth << ")";
+ 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()";
+ OS << "StructType::get(Context)";
} else if (VT == MVT::f32) {
- OS << "Type::FloatTy";
+ OS << "Type::getFloatTy(Context)";
} else if (VT == MVT::f64) {
- OS << "Type::DoubleTy";
+ OS << "Type::getDoubleTy(Context)";
} else if (VT == MVT::f80) {
- OS << "Type::X86_FP80Ty";
+ OS << "Type::getX86_FP80Ty(Context)";
} else if (VT == MVT::f128) {
- OS << "Type::FP128Ty";
+ OS << "Type::getFP128Ty(Context)";
} else if (VT == MVT::ppcf128) {
- OS << "Type::PPC_FP128Ty";
+ OS << "Type::getPPC_FP128Ty(Context)";
} else if (VT == MVT::isVoid) {
- OS << "Type::VoidTy";
+ OS << "Type::getVoidTy(Context)";
+ } else if (VT == MVT::Metadata) {
+ OS << "Type::getMetadataTy(Context)";
} else {
assert(false && "Unsupported ValueType!");
}
@@ -175,7 +177,7 @@ static void EmitTypeGenerate(raw_ostream &OS,
return;
}
- OS << "StructType::get(";
+ OS << "StructType::get(Context, ";
for (std::vector<Record*>::const_iterator
I = ArgTypes.begin(), E = ArgTypes.end(); I != E; ++I) {
@@ -201,17 +203,17 @@ static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
<< "(dyn_cast<VectorType>(Tys[" << Number << "]))";
else
OS << "Tys[" << Number << "]";
- } else if (VT == MVT::iAny || VT == MVT::fAny) {
+ } 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 (MVT(VT).isVector()) {
- MVT VVT = VT;
+ } else if (EVT(VT).isVector()) {
+ EVT VVT = VT;
OS << "VectorType::get(";
- EmitTypeForValueType(OS, VVT.getVectorElementType().getSimpleVT());
+ EmitTypeForValueType(OS, VVT.getVectorElementType().getSimpleVT().SimpleTy);
OS << ", " << VVT.getVectorNumElements() << ")";
} else if (VT == MVT::iPTR) {
OS << "PointerType::getUnqual(";
@@ -227,7 +229,7 @@ static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
++ArgNo;
} else if (VT == MVT::isVoid) {
if (ArgNo == 0)
- OS << "Type::VoidTy";
+ OS << "Type::getVoidTy(Context)";
else
// MVT::isVoid is used to mean varargs here.
OS << "...";
@@ -302,6 +304,7 @@ void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
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();
@@ -313,6 +316,9 @@ void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
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"))
@@ -323,6 +329,9 @@ void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
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";
}
@@ -335,6 +344,9 @@ void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
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"))
@@ -345,6 +357,9 @@ void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
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";
}
diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp
index fc182ce..06afaf7 100644
--- a/utils/TableGen/LLVMCConfigurationEmitter.cpp
+++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp
@@ -39,10 +39,11 @@ typedef std::vector<std::string> StrVector;
//===----------------------------------------------------------------------===//
/// Constants
-// Indentation strings.
-const char * Indent1 = " ";
-const char * Indent2 = " ";
-const char * Indent3 = " ";
+// Indentation.
+unsigned TabWidth = 4;
+unsigned Indent1 = TabWidth*1;
+unsigned Indent2 = TabWidth*2;
+unsigned Indent3 = TabWidth*3;
// Default help string.
const char * DefaultHelpString = "NO HELP MESSAGE PROVIDED";
@@ -81,16 +82,15 @@ const DagInit& InitPtrToDag(const Init* ptr) {
}
// checkNumberOfArguments - Ensure that the number of args in d is
-// less than or equal to min_arguments, otherwise throw an exception.
+// greater than or equal to min_arguments, otherwise throw an exception.
void checkNumberOfArguments (const DagInit* d, unsigned min_arguments) {
if (!d || d->getNumArgs() < min_arguments)
- throw d->getOperator()->getAsString()
- + ": too few arguments!";
+ throw d->getOperator()->getAsString() + ": too few arguments!";
}
// isDagEmpty - is this DAG marked with an empty marker?
bool isDagEmpty (const DagInit* d) {
- return d->getOperator()->getAsString() == "empty";
+ return d->getOperator()->getAsString() == "empty_dag_marker";
}
// EscapeVariableName - Escape commas and other symbols not allowed
@@ -139,20 +139,21 @@ void checkedIncrement(I& P, I E, S ErrorString) {
/// OptionType - One of six different option types. See the
/// documentation for detailed description of differences.
namespace OptionType {
+
enum OptionType { Alias, Switch, Parameter, ParameterList,
Prefix, PrefixList};
-bool IsList (OptionType t) {
- return (t == ParameterList || t == PrefixList);
-}
+ bool IsList (OptionType t) {
+ return (t == ParameterList || t == PrefixList);
+ }
-bool IsSwitch (OptionType t) {
- return (t == Switch);
-}
+ bool IsSwitch (OptionType t) {
+ return (t == Switch);
+ }
-bool IsParameter (OptionType t) {
- return (t == Parameter || t == Prefix);
-}
+ bool IsParameter (OptionType t) {
+ return (t == Parameter || t == Prefix);
+ }
}
@@ -187,11 +188,12 @@ struct OptionDescription {
unsigned Flags;
std::string Help;
unsigned MultiVal;
+ Init* InitVal;
OptionDescription(OptionType::OptionType t = OptionType::Switch,
const std::string& n = "",
const std::string& h = DefaultHelpString)
- : Type(t), Name(n), Flags(0x0), Help(h), MultiVal(1)
+ : Type(t), Name(n), Flags(0x0), Help(h), MultiVal(1), InitVal(0)
{}
/// GenTypeDeclaration - Returns the C++ variable type of this
@@ -229,6 +231,15 @@ struct OptionDescription {
bool isReallyHidden() const;
void setReallyHidden();
+ bool isParameter() const
+ { return OptionType::IsParameter(this->Type); }
+
+ bool isSwitch() const
+ { return OptionType::IsSwitch(this->Type); }
+
+ bool isList() const
+ { return OptionType::IsList(this->Type); }
+
};
void OptionDescription::Merge (const OptionDescription& other)
@@ -438,6 +449,7 @@ public:
AddHandler("extern", &CollectOptionProperties::onExtern);
AddHandler("help", &CollectOptionProperties::onHelp);
AddHandler("hidden", &CollectOptionProperties::onHidden);
+ AddHandler("init", &CollectOptionProperties::onInit);
AddHandler("multi_val", &CollectOptionProperties::onMultiVal);
AddHandler("one_or_more", &CollectOptionProperties::onOneOrMore);
AddHandler("really_hidden", &CollectOptionProperties::onReallyHidden);
@@ -481,6 +493,20 @@ private:
optDesc_.setRequired();
}
+ void onInit (const DagInit* d) {
+ checkNumberOfArguments(d, 1);
+ Init* i = d->getArg(0);
+ const std::string& str = i->getAsString();
+
+ bool correct = optDesc_.isParameter() && dynamic_cast<StringInit*>(i);
+ correct |= (optDesc_.isSwitch() && (str == "true" || str == "false"));
+
+ if (!correct)
+ throw std::string("Incorrect usage of the 'init' option property!");
+
+ optDesc_.InitVal = i;
+ }
+
void onOneOrMore (const DagInit* d) {
checkNumberOfArguments(d, 0);
if (optDesc_.isRequired() || optDesc_.isZeroOrOne())
@@ -950,8 +976,22 @@ void CheckForSuperfluousOptions (const RecordVector& Edges,
}
}
-/// EmitCaseTest1Arg - Helper function used by
-/// EmitCaseConstructHandler.
+/// EmitCaseTest0Args - Helper function used by EmitCaseConstructHandler().
+bool EmitCaseTest0Args(const std::string& TestName, raw_ostream& O) {
+ if (TestName == "single_input_file") {
+ O << "InputFilenames.size() == 1";
+ return true;
+ }
+ else if (TestName == "multiple_input_files") {
+ O << "InputFilenames.size() > 1";
+ return true;
+ }
+
+ return false;
+}
+
+
+/// EmitCaseTest1Arg - Helper function used by EmitCaseConstructHandler().
bool EmitCaseTest1Arg(const std::string& TestName,
const DagInit& d,
const OptionDescriptions& OptDescs,
@@ -961,7 +1001,7 @@ bool EmitCaseTest1Arg(const std::string& TestName,
if (TestName == "switch_on") {
const OptionDescription& OptDesc = OptDescs.FindOption(OptName);
- if (!OptionType::IsSwitch(OptDesc.Type))
+ if (!OptDesc.isSwitch())
throw OptName + ": incorrect option type - should be a switch!";
O << OptDesc.GenVariableName();
return true;
@@ -984,7 +1024,7 @@ bool EmitCaseTest1Arg(const std::string& TestName,
}
else {
const OptionDescription& OptDesc = OptDescs.FindOption(OptName);
- if (OptionType::IsSwitch(OptDesc.Type))
+ if (OptDesc.isSwitch())
throw OptName
+ ": incorrect option type - should be a list or parameter!";
O << Test << OptDesc.GenVariableName() << ".empty()";
@@ -995,11 +1035,10 @@ bool EmitCaseTest1Arg(const std::string& TestName,
return false;
}
-/// EmitCaseTest2Args - Helper function used by
-/// EmitCaseConstructHandler.
+/// EmitCaseTest2Args - Helper function used by EmitCaseConstructHandler().
bool EmitCaseTest2Args(const std::string& TestName,
const DagInit& d,
- const char* IndentLevel,
+ unsigned IndentLevel,
const OptionDescriptions& OptDescs,
raw_ostream& O) {
checkNumberOfArguments(&d, 2);
@@ -1008,17 +1047,18 @@ bool EmitCaseTest2Args(const std::string& TestName,
const OptionDescription& OptDesc = OptDescs.FindOption(OptName);
if (TestName == "parameter_equals") {
- if (!OptionType::IsParameter(OptDesc.Type))
+ if (!OptDesc.isParameter())
throw OptName + ": incorrect option type - should be a parameter!";
O << OptDesc.GenVariableName() << " == \"" << OptArg << "\"";
return true;
}
else if (TestName == "element_in_list") {
- if (!OptionType::IsList(OptDesc.Type))
+ if (!OptDesc.isList())
throw OptName + ": incorrect option type - should be a list!";
const std::string& VarName = OptDesc.GenVariableName();
- O << "std::find(" << VarName << ".begin(),\n"
- << IndentLevel << Indent1 << VarName << ".end(), \""
+ O << "std::find(" << VarName << ".begin(),\n";
+ O.indent(IndentLevel + Indent1)
+ << VarName << ".end(), \""
<< OptArg << "\") != " << VarName << ".end()";
return true;
}
@@ -1028,29 +1068,42 @@ bool EmitCaseTest2Args(const std::string& TestName,
// Forward declaration.
// EmitLogicalOperationTest and EmitCaseTest are mutually recursive.
-void EmitCaseTest(const DagInit& d, const char* IndentLevel,
+void EmitCaseTest(const DagInit& d, unsigned IndentLevel,
const OptionDescriptions& OptDescs,
raw_ostream& O);
/// EmitLogicalOperationTest - Helper function used by
/// EmitCaseConstructHandler.
void EmitLogicalOperationTest(const DagInit& d, const char* LogicOp,
- const char* IndentLevel,
+ unsigned IndentLevel,
const OptionDescriptions& OptDescs,
raw_ostream& O) {
O << '(';
for (unsigned j = 0, NumArgs = d.getNumArgs(); j < NumArgs; ++j) {
const DagInit& InnerTest = InitPtrToDag(d.getArg(j));
EmitCaseTest(InnerTest, IndentLevel, OptDescs, O);
- if (j != NumArgs - 1)
- O << ")\n" << IndentLevel << Indent1 << ' ' << LogicOp << " (";
- else
+ if (j != NumArgs - 1) {
+ O << ")\n";
+ O.indent(IndentLevel + Indent1) << ' ' << LogicOp << " (";
+ }
+ else {
O << ')';
+ }
}
}
+void EmitLogicalNot(const DagInit& d, unsigned IndentLevel,
+ const OptionDescriptions& OptDescs, raw_ostream& O)
+{
+ checkNumberOfArguments(&d, 1);
+ const DagInit& InnerTest = InitPtrToDag(d.getArg(0));
+ O << "! (";
+ EmitCaseTest(InnerTest, IndentLevel, OptDescs, O);
+ O << ")";
+}
+
/// EmitCaseTest - Helper function used by EmitCaseConstructHandler.
-void EmitCaseTest(const DagInit& d, const char* IndentLevel,
+void EmitCaseTest(const DagInit& d, unsigned IndentLevel,
const OptionDescriptions& OptDescs,
raw_ostream& O) {
const std::string& TestName = d.getOperator()->getAsString();
@@ -1059,6 +1112,10 @@ void EmitCaseTest(const DagInit& d, const char* IndentLevel,
EmitLogicalOperationTest(d, "&&", IndentLevel, OptDescs, O);
else if (TestName == "or")
EmitLogicalOperationTest(d, "||", IndentLevel, OptDescs, O);
+ else if (TestName == "not")
+ EmitLogicalNot(d, IndentLevel, OptDescs, O);
+ else if (EmitCaseTest0Args(TestName, O))
+ return;
else if (EmitCaseTest1Arg(TestName, d, OptDescs, O))
return;
else if (EmitCaseTest2Args(TestName, d, IndentLevel, OptDescs, O))
@@ -1070,9 +1127,9 @@ void EmitCaseTest(const DagInit& d, const char* IndentLevel,
// Emit code that handles the 'case' construct.
// Takes a function object that should emit code for every case clause.
// Callback's type is
-// void F(Init* Statement, const char* IndentLevel, raw_ostream& O).
+// void F(Init* Statement, unsigned IndentLevel, raw_ostream& O).
template <typename F>
-void EmitCaseConstructHandler(const Init* Dag, const char* IndentLevel,
+void EmitCaseConstructHandler(const Init* Dag, unsigned IndentLevel,
F Callback, bool EmitElseIf,
const OptionDescriptions& OptDescs,
raw_ostream& O) {
@@ -1094,10 +1151,10 @@ void EmitCaseConstructHandler(const Init* Dag, const char* IndentLevel,
if (i+2 != numArgs)
throw std::string("The 'default' clause should be the last in the"
"'case' construct!");
- O << IndentLevel << "else {\n";
+ O.indent(IndentLevel) << "else {\n";
}
else {
- O << IndentLevel << ((i != 0 && EmitElseIf) ? "else if (" : "if (");
+ O.indent(IndentLevel) << ((i != 0 && EmitElseIf) ? "else if (" : "if (");
EmitCaseTest(Test, IndentLevel, OptDescs, O);
O << ") {\n";
}
@@ -1112,13 +1169,13 @@ void EmitCaseConstructHandler(const Init* Dag, const char* IndentLevel,
const DagInit* nd = dynamic_cast<DagInit*>(arg);
if (nd && (nd->getOperator()->getAsString() == "case")) {
// Handle the nested 'case'.
- EmitCaseConstructHandler(nd, (std::string(IndentLevel) + Indent1).c_str(),
+ EmitCaseConstructHandler(nd, (IndentLevel + Indent1),
Callback, EmitElseIf, OptDescs, O);
}
else {
- Callback(arg, (std::string(IndentLevel) + Indent1).c_str(), O);
+ Callback(arg, (IndentLevel + Indent1), O);
}
- O << IndentLevel << "}\n";
+ O.indent(IndentLevel) << "}\n";
}
}
@@ -1272,7 +1329,7 @@ StrVector::const_iterator SubstituteSpecialCommands
/// EmitCmdLineVecFill - Emit code that fills in the command line
/// vector. Helper function used by EmitGenerateActionMethod().
void EmitCmdLineVecFill(const Init* CmdLine, const std::string& ToolName,
- bool IsJoin, const char* IndentLevel,
+ bool IsJoin, unsigned IndentLevel,
raw_ostream& O) {
StrVector StrVec;
TokenizeCmdline(InitPtrToString(CmdLine), StrVec);
@@ -1295,22 +1352,28 @@ void EmitCmdLineVecFill(const Init* CmdLine, const std::string& ToolName,
++I;
}
+ bool hasINFILE = false;
+
for (; I != E; ++I) {
const std::string& cmd = *I;
assert(!cmd.empty());
- O << IndentLevel;
+ O.indent(IndentLevel);
if (cmd.at(0) == '$') {
if (cmd == "$INFILE") {
- if (IsJoin)
+ hasINFILE = true;
+ if (IsJoin) {
O << "for (PathVector::const_iterator B = inFiles.begin()"
- << ", E = inFiles.end();\n"
- << IndentLevel << "B != E; ++B)\n"
- << IndentLevel << Indent1 << "vec.push_back(B->toString());\n";
- else
- O << "vec.push_back(inFile.toString());\n";
+ << ", E = inFiles.end();\n";
+ O.indent(IndentLevel) << "B != E; ++B)\n";
+ O.indent(IndentLevel + Indent1) << "vec.push_back(B->str());\n";
+ }
+ else {
+ O << "vec.push_back(inFile.str());\n";
+ }
}
else if (cmd == "$OUTFILE") {
- O << "vec.push_back(out_file);\n";
+ O << "vec.push_back(\"\");\n";
+ O.indent(IndentLevel) << "out_file_index = vec.size()-1;\n";
}
else {
O << "vec.push_back(";
@@ -1322,8 +1385,10 @@ void EmitCmdLineVecFill(const Init* CmdLine, const std::string& ToolName,
O << "vec.push_back(\"" << cmd << "\");\n";
}
}
- O << IndentLevel << "cmd = ";
+ if (!hasINFILE)
+ throw "Tool '" + ToolName + "' doesn't take any input!";
+ O.indent(IndentLevel) << "cmd = ";
if (StrVec[0][0] == '$')
SubstituteSpecialCommands(StrVec.begin(), StrVec.end(), O);
else
@@ -1341,11 +1406,10 @@ class EmitCmdLineVecFillCallback {
EmitCmdLineVecFillCallback(bool J, const std::string& TN)
: IsJoin(J), ToolName(TN) {}
- void operator()(const Init* Statement, const char* IndentLevel,
+ void operator()(const Init* Statement, unsigned IndentLevel,
raw_ostream& O) const
{
- EmitCmdLineVecFill(Statement, ToolName, IsJoin,
- IndentLevel, O);
+ EmitCmdLineVecFill(Statement, ToolName, IsJoin, IndentLevel, O);
}
};
@@ -1353,53 +1417,56 @@ class EmitCmdLineVecFillCallback {
/// implement EmitActionHandler. Emits code for
/// handling the (forward) and (forward_as) option properties.
void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,
- const char* Indent,
+ unsigned IndentLevel,
const std::string& NewName,
raw_ostream& O) {
const std::string& Name = NewName.empty()
? ("-" + D.Name)
: NewName;
+ unsigned IndentLevel1 = IndentLevel + Indent1;
switch (D.Type) {
case OptionType::Switch:
- O << Indent << "vec.push_back(\"" << Name << "\");\n";
+ O.indent(IndentLevel) << "vec.push_back(\"" << Name << "\");\n";
break;
case OptionType::Parameter:
- O << Indent << "vec.push_back(\"" << Name << "\");\n";
- O << Indent << "vec.push_back(" << D.GenVariableName() << ");\n";
+ O.indent(IndentLevel) << "vec.push_back(\"" << Name << "\");\n";
+ O.indent(IndentLevel) << "vec.push_back(" << D.GenVariableName() << ");\n";
break;
case OptionType::Prefix:
- O << Indent << "vec.push_back(\"" << Name << "\" + "
- << D.GenVariableName() << ");\n";
+ O.indent(IndentLevel) << "vec.push_back(\"" << Name << "\" + "
+ << D.GenVariableName() << ");\n";
break;
case OptionType::PrefixList:
- O << Indent << "for (" << D.GenTypeDeclaration()
- << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
- << Indent << "E = " << D.GenVariableName() << ".end(); B != E;) {\n"
- << Indent << Indent1 << "vec.push_back(\"" << Name << "\" + "
- << "*B);\n"
- << Indent << Indent1 << "++B;\n";
+ O.indent(IndentLevel)
+ << "for (" << D.GenTypeDeclaration()
+ << "::iterator B = " << D.GenVariableName() << ".begin(),\n";
+ O.indent(IndentLevel)
+ << "E = " << D.GenVariableName() << ".end(); B != E;) {\n";
+ O.indent(IndentLevel1) << "vec.push_back(\"" << Name << "\" + " << "*B);\n";
+ O.indent(IndentLevel1) << "++B;\n";
for (int i = 1, j = D.MultiVal; i < j; ++i) {
- O << Indent << Indent1 << "vec.push_back(*B);\n"
- << Indent << Indent1 << "++B;\n";
+ O.indent(IndentLevel1) << "vec.push_back(*B);\n";
+ O.indent(IndentLevel1) << "++B;\n";
}
- O << Indent << "}\n";
+ O.indent(IndentLevel) << "}\n";
break;
case OptionType::ParameterList:
- O << Indent << "for (" << D.GenTypeDeclaration()
- << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
- << Indent << "E = " << D.GenVariableName()
- << ".end() ; B != E;) {\n"
- << Indent << Indent1 << "vec.push_back(\"" << Name << "\");\n";
+ O.indent(IndentLevel)
+ << "for (" << D.GenTypeDeclaration() << "::iterator B = "
+ << D.GenVariableName() << ".begin(),\n";
+ O.indent(IndentLevel) << "E = " << D.GenVariableName()
+ << ".end() ; B != E;) {\n";
+ O.indent(IndentLevel1) << "vec.push_back(\"" << Name << "\");\n";
for (int i = 0, j = D.MultiVal; i < j; ++i) {
- O << Indent << Indent1 << "vec.push_back(*B);\n"
- << Indent << Indent1 << "++B;\n";
+ O.indent(IndentLevel1) << "vec.push_back(*B);\n";
+ O.indent(IndentLevel1) << "++B;\n";
}
- O << Indent << "}\n";
+ O.indent(IndentLevel) << "}\n";
break;
case OptionType::Alias:
default:
@@ -1413,7 +1480,7 @@ void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,
class EmitActionHandler {
const OptionDescriptions& OptDescs;
- void processActionDag(const Init* Statement, const char* IndentLevel,
+ void processActionDag(const Init* Statement, unsigned IndentLevel,
raw_ostream& O) const
{
const DagInit& Dag = InitPtrToDag(Statement);
@@ -1427,10 +1494,10 @@ class EmitActionHandler {
for (StrVector::const_iterator B = Out.begin(), E = Out.end();
B != E; ++B)
- O << IndentLevel << "vec.push_back(\"" << *B << "\");\n";
+ O.indent(IndentLevel) << "vec.push_back(\"" << *B << "\");\n";
}
else if (ActionName == "error") {
- O << IndentLevel << "throw std::runtime_error(\"" <<
+ O.indent(IndentLevel) << "throw std::runtime_error(\"" <<
(Dag.getNumArgs() >= 1 ? InitPtrToString(Dag.getArg(0))
: "Unknown error!")
<< "\");\n";
@@ -1451,10 +1518,10 @@ class EmitActionHandler {
else if (ActionName == "output_suffix") {
checkNumberOfArguments(&Dag, 1);
const std::string& OutSuf = InitPtrToString(Dag.getArg(0));
- O << IndentLevel << "output_suffix = \"" << OutSuf << "\";\n";
+ O.indent(IndentLevel) << "output_suffix = \"" << OutSuf << "\";\n";
}
else if (ActionName == "stop_compilation") {
- O << IndentLevel << "stop_compilation = true;\n";
+ O.indent(IndentLevel) << "stop_compilation = true;\n";
}
else if (ActionName == "unpack_values") {
checkNumberOfArguments(&Dag, 1);
@@ -1464,16 +1531,18 @@ class EmitActionHandler {
if (D.isMultiVal())
throw std::string("Can't use unpack_values with multi-valued options!");
- if (OptionType::IsList(D.Type)) {
- O << IndentLevel << "for (" << D.GenTypeDeclaration()
- << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
- << IndentLevel << "E = " << D.GenVariableName()
- << ".end(); B != E; ++B)\n"
- << IndentLevel << Indent1 << "llvm::SplitString(*B, vec, \",\");\n";
+ if (D.isList()) {
+ O.indent(IndentLevel)
+ << "for (" << D.GenTypeDeclaration()
+ << "::iterator B = " << D.GenVariableName() << ".begin(),\n";
+ O.indent(IndentLevel)
+ << "E = " << D.GenVariableName() << ".end(); B != E; ++B)\n";
+ O.indent(IndentLevel + Indent1)
+ << "llvm::SplitString(*B, vec, \",\");\n";
}
- else if (OptionType::IsParameter(D.Type)){
- O << Indent3 << "llvm::SplitString("
- << D.GenVariableName() << ", vec, \",\");\n";
+ else if (D.isParameter()){
+ O.indent(IndentLevel) << "llvm::SplitString("
+ << D.GenVariableName() << ", vec, \",\");\n";
}
else {
throw "Option '" + D.Name +
@@ -1488,7 +1557,7 @@ class EmitActionHandler {
EmitActionHandler(const OptionDescriptions& OD)
: OptDescs(OD) {}
- void operator()(const Init* Statement, const char* IndentLevel,
+ void operator()(const Init* Statement, unsigned IndentLevel,
raw_ostream& O) const
{
if (typeid(*Statement) == typeid(ListInit)) {
@@ -1503,56 +1572,111 @@ class EmitActionHandler {
}
};
-// EmitGenerateActionMethod - Emit one of two versions of the
+bool IsOutFileIndexCheckRequiredStr (const Init* CmdLine) {
+ StrVector StrVec;
+ TokenizeCmdline(InitPtrToString(CmdLine), StrVec);
+
+ for (StrVector::const_iterator I = StrVec.begin(), E = StrVec.end();
+ I != E; ++I) {
+ if (*I == "$OUTFILE")
+ return false;
+ }
+
+ return true;
+}
+
+class IsOutFileIndexCheckRequiredStrCallback {
+ bool* ret_;
+
+public:
+ IsOutFileIndexCheckRequiredStrCallback(bool* ret) : ret_(ret)
+ {}
+
+ void operator()(const Init* CmdLine) {
+ if (IsOutFileIndexCheckRequiredStr(CmdLine))
+ *ret_ = true;
+ }
+};
+
+bool IsOutFileIndexCheckRequiredCase (Init* CmdLine) {
+ bool ret = false;
+ WalkCase(CmdLine, Id(), IsOutFileIndexCheckRequiredStrCallback(&ret));
+ return ret;
+}
+
+/// IsOutFileIndexCheckRequired - Should we emit an "out_file_index != -1" check
+/// in EmitGenerateActionMethod() ?
+bool IsOutFileIndexCheckRequired (Init* CmdLine) {
+ if (typeid(*CmdLine) == typeid(StringInit))
+ return IsOutFileIndexCheckRequiredStr(CmdLine);
+ else
+ return IsOutFileIndexCheckRequiredCase(CmdLine);
+}
+
+// EmitGenerateActionMethod - Emit either a normal or a "join" version of the
// Tool::GenerateAction() method.
void EmitGenerateActionMethod (const ToolDescription& D,
const OptionDescriptions& OptDescs,
bool IsJoin, raw_ostream& O) {
if (IsJoin)
- O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n";
+ O.indent(Indent1) << "Action GenerateAction(const PathVector& inFiles,\n";
else
- O << Indent1 << "Action GenerateAction(const sys::Path& inFile,\n";
-
- O << Indent2 << "bool HasChildren,\n"
- << Indent2 << "const llvm::sys::Path& TempDir,\n"
- << Indent2 << "const InputLanguagesSet& InLangs,\n"
- << Indent2 << "const LanguageMap& LangMap) const\n"
- << Indent1 << "{\n"
- << Indent2 << "std::string cmd;\n"
- << Indent2 << "std::vector<std::string> vec;\n"
- << Indent2 << "bool stop_compilation = !HasChildren;\n"
- << Indent2 << "const char* output_suffix = \"" << D.OutputSuffix << "\";\n"
- << Indent2 << "std::string out_file;\n\n";
-
- // For every understood option, emit handling code.
- if (D.Actions)
- EmitCaseConstructHandler(D.Actions, Indent2, EmitActionHandler(OptDescs),
- false, OptDescs, O);
-
- O << '\n' << Indent2
- << "out_file = OutFilename(" << (IsJoin ? "sys::Path(),\n" : "inFile,\n")
- << Indent3 << "TempDir, stop_compilation, output_suffix).toString();\n\n";
+ O.indent(Indent1) << "Action GenerateAction(const sys::Path& inFile,\n";
+
+ O.indent(Indent2) << "bool HasChildren,\n";
+ O.indent(Indent2) << "const llvm::sys::Path& TempDir,\n";
+ O.indent(Indent2) << "const InputLanguagesSet& InLangs,\n";
+ O.indent(Indent2) << "const LanguageMap& LangMap) const\n";
+ O.indent(Indent1) << "{\n";
+ O.indent(Indent2) << "std::string cmd;\n";
+ O.indent(Indent2) << "std::vector<std::string> vec;\n";
+ O.indent(Indent2) << "bool stop_compilation = !HasChildren;\n";
+ O.indent(Indent2) << "const char* output_suffix = \""
+ << D.OutputSuffix << "\";\n";
- // cmd_line is either a string or a 'case' construct.
if (!D.CmdLine)
throw "Tool " + D.Name + " has no cmd_line property!";
- else if (typeid(*D.CmdLine) == typeid(StringInit))
+
+ bool IndexCheckRequired = IsOutFileIndexCheckRequired(D.CmdLine);
+ O.indent(Indent2) << "int out_file_index"
+ << (IndexCheckRequired ? " = -1" : "")
+ << ";\n\n";
+
+ // Process the cmd_line property.
+ if (typeid(*D.CmdLine) == typeid(StringInit))
EmitCmdLineVecFill(D.CmdLine, D.Name, IsJoin, Indent2, O);
else
EmitCaseConstructHandler(D.CmdLine, Indent2,
EmitCmdLineVecFillCallback(IsJoin, D.Name),
true, OptDescs, O);
+ // For every understood option, emit handling code.
+ if (D.Actions)
+ EmitCaseConstructHandler(D.Actions, Indent2, EmitActionHandler(OptDescs),
+ false, OptDescs, O);
+
+ O << '\n';
+ O.indent(Indent2)
+ << "std::string out_file = OutFilename("
+ << (IsJoin ? "sys::Path(),\n" : "inFile,\n");
+ O.indent(Indent3) << "TempDir, stop_compilation, output_suffix).str();\n\n";
+
+ if (IndexCheckRequired)
+ O.indent(Indent2) << "if (out_file_index != -1)\n";
+ O.indent(IndexCheckRequired ? Indent3 : Indent2)
+ << "vec[out_file_index] = out_file;\n";
+
// Handle the Sink property.
if (D.isSink()) {
- O << Indent2 << "if (!" << SinkOptionName << ".empty()) {\n"
- << Indent3 << "vec.insert(vec.end(), "
- << SinkOptionName << ".begin(), " << SinkOptionName << ".end());\n"
- << Indent2 << "}\n";
+ O.indent(Indent2) << "if (!" << SinkOptionName << ".empty()) {\n";
+ O.indent(Indent3) << "vec.insert(vec.end(), "
+ << SinkOptionName << ".begin(), " << SinkOptionName
+ << ".end());\n";
+ O.indent(Indent2) << "}\n";
}
- O << Indent2 << "return Action(cmd, vec, stop_compilation, out_file);\n"
- << Indent1 << "}\n\n";
+ O.indent(Indent2) << "return Action(cmd, vec, stop_compilation, out_file);\n";
+ O.indent(Indent1) << "}\n\n";
}
/// EmitGenerateActionMethods - Emit two GenerateAction() methods for
@@ -1560,18 +1684,20 @@ void EmitGenerateActionMethod (const ToolDescription& D,
void EmitGenerateActionMethods (const ToolDescription& ToolDesc,
const OptionDescriptions& OptDescs,
raw_ostream& O) {
- if (!ToolDesc.isJoin())
- O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n"
- << Indent2 << "bool HasChildren,\n"
- << Indent2 << "const llvm::sys::Path& TempDir,\n"
- << Indent2 << "const InputLanguagesSet& InLangs,\n"
- << Indent2 << "const LanguageMap& LangMap) const\n"
- << Indent1 << "{\n"
- << Indent2 << "throw std::runtime_error(\"" << ToolDesc.Name
- << " is not a Join tool!\");\n"
- << Indent1 << "}\n\n";
- else
+ if (!ToolDesc.isJoin()) {
+ O.indent(Indent1) << "Action GenerateAction(const PathVector& inFiles,\n";
+ O.indent(Indent2) << "bool HasChildren,\n";
+ O.indent(Indent2) << "const llvm::sys::Path& TempDir,\n";
+ O.indent(Indent2) << "const InputLanguagesSet& InLangs,\n";
+ O.indent(Indent2) << "const LanguageMap& LangMap) const\n";
+ O.indent(Indent1) << "{\n";
+ O.indent(Indent2) << "throw std::runtime_error(\"" << ToolDesc.Name
+ << " is not a Join tool!\");\n";
+ O.indent(Indent1) << "}\n\n";
+ }
+ else {
EmitGenerateActionMethod(ToolDesc, OptDescs, true, O);
+ }
EmitGenerateActionMethod(ToolDesc, OptDescs, false, O);
}
@@ -1579,34 +1705,34 @@ void EmitGenerateActionMethods (const ToolDescription& ToolDesc,
/// EmitInOutLanguageMethods - Emit the [Input,Output]Language()
/// methods for a given Tool class.
void EmitInOutLanguageMethods (const ToolDescription& D, raw_ostream& O) {
- O << Indent1 << "const char** InputLanguages() const {\n"
- << Indent2 << "return InputLanguages_;\n"
- << Indent1 << "}\n\n";
+ O.indent(Indent1) << "const char** InputLanguages() const {\n";
+ O.indent(Indent2) << "return InputLanguages_;\n";
+ O.indent(Indent1) << "}\n\n";
if (D.OutLanguage.empty())
throw "Tool " + D.Name + " has no 'out_language' property!";
- O << Indent1 << "const char* OutputLanguage() const {\n"
- << Indent2 << "return \"" << D.OutLanguage << "\";\n"
- << Indent1 << "}\n\n";
+ O.indent(Indent1) << "const char* OutputLanguage() const {\n";
+ O.indent(Indent2) << "return \"" << D.OutLanguage << "\";\n";
+ O.indent(Indent1) << "}\n\n";
}
/// EmitNameMethod - Emit the Name() method for a given Tool class.
void EmitNameMethod (const ToolDescription& D, raw_ostream& O) {
- O << Indent1 << "const char* Name() const {\n"
- << Indent2 << "return \"" << D.Name << "\";\n"
- << Indent1 << "}\n\n";
+ O.indent(Indent1) << "const char* Name() const {\n";
+ O.indent(Indent2) << "return \"" << D.Name << "\";\n";
+ O.indent(Indent1) << "}\n\n";
}
/// EmitIsJoinMethod - Emit the IsJoin() method for a given Tool
/// class.
void EmitIsJoinMethod (const ToolDescription& D, raw_ostream& O) {
- O << Indent1 << "bool IsJoin() const {\n";
+ O.indent(Indent1) << "bool IsJoin() const {\n";
if (D.isJoin())
- O << Indent2 << "return true;\n";
+ O.indent(Indent2) << "return true;\n";
else
- O << Indent2 << "return false;\n";
- O << Indent1 << "}\n\n";
+ O.indent(Indent2) << "return false;\n";
+ O.indent(Indent1) << "}\n\n";
}
/// EmitStaticMemberDefinitions - Emit static member definitions for a
@@ -1636,8 +1762,8 @@ void EmitToolClassDefinition (const ToolDescription& D,
else
O << "Tool";
- O << "{\nprivate:\n"
- << Indent1 << "static const char* InputLanguages_[];\n\n";
+ O << "{\nprivate:\n";
+ O.indent(Indent1) << "static const char* InputLanguages_[];\n\n";
O << "public:\n";
EmitNameMethod(D, O);
@@ -1687,15 +1813,15 @@ void EmitOptionDefinitions (const OptionDescriptions& descs,
O << ", cl::Prefix";
if (val.isRequired()) {
- if (OptionType::IsList(val.Type) && !val.isMultiVal())
+ if (val.isList() && !val.isMultiVal())
O << ", cl::OneOrMore";
else
O << ", cl::Required";
}
- else if (val.isOneOrMore() && OptionType::IsList(val.Type)) {
+ else if (val.isOneOrMore() && val.isList()) {
O << ", cl::OneOrMore";
}
- else if (val.isZeroOrOne() && OptionType::IsList(val.Type)) {
+ else if (val.isZeroOrOne() && val.isList()) {
O << ", cl::ZeroOrOne";
}
@@ -1707,7 +1833,12 @@ void EmitOptionDefinitions (const OptionDescriptions& descs,
}
if (val.MultiVal > 1)
- O << ", cl::multi_val(" << val.MultiVal << ")";
+ O << ", cl::multi_val(" << val.MultiVal << ')';
+
+ if (val.InitVal) {
+ const std::string& str = val.InitVal->getAsString();
+ O << ", cl::init(" << str << ')';
+ }
if (!val.Help.empty())
O << ", cl::desc(\"" << val.Help << "\")";
@@ -1762,9 +1893,9 @@ void EmitPopulateLanguageMap (const RecordKeeper& Records, raw_ostream& O)
const ListInit* Suffixes = LangToSuffixes->getValueAsListInit("suffixes");
for (unsigned i = 0; i < Suffixes->size(); ++i)
- O << Indent1 << "langMap[\""
- << InitPtrToString(Suffixes->getElement(i))
- << "\"] = \"" << Lang << "\";\n";
+ O.indent(Indent1) << "langMap[\""
+ << InitPtrToString(Suffixes->getElement(i))
+ << "\"] = \"" << Lang << "\";\n";
}
}
@@ -1773,21 +1904,22 @@ void EmitPopulateLanguageMap (const RecordKeeper& Records, raw_ostream& O)
/// IncDecWeight - Helper function passed to EmitCaseConstructHandler()
/// by EmitEdgeClass().
-void IncDecWeight (const Init* i, const char* IndentLevel,
+void IncDecWeight (const Init* i, unsigned IndentLevel,
raw_ostream& O) {
const DagInit& d = InitPtrToDag(i);
const std::string& OpName = d.getOperator()->getAsString();
if (OpName == "inc_weight") {
- O << IndentLevel << "ret += ";
+ O.indent(IndentLevel) << "ret += ";
}
else if (OpName == "dec_weight") {
- O << IndentLevel << "ret -= ";
+ O.indent(IndentLevel) << "ret -= ";
}
else if (OpName == "error") {
- O << IndentLevel << "throw std::runtime_error(\"" <<
- (d.getNumArgs() >= 1 ? InitPtrToString(d.getArg(0))
- : "Unknown error!")
+ O.indent(IndentLevel)
+ << "throw std::runtime_error(\"" <<
+ (d.getNumArgs() >= 1 ? InitPtrToString(d.getArg(0))
+ : "Unknown error!")
<< "\");\n";
return;
}
@@ -1810,19 +1942,20 @@ void EmitEdgeClass (unsigned N, const std::string& Target,
// Class constructor.
O << "class Edge" << N << ": public Edge {\n"
- << "public:\n"
- << Indent1 << "Edge" << N << "() : Edge(\"" << Target
- << "\") {}\n\n"
+ << "public:\n";
+ O.indent(Indent1) << "Edge" << N << "() : Edge(\"" << Target
+ << "\") {}\n\n";
// Function Weight().
- << Indent1 << "unsigned Weight(const InputLanguagesSet& InLangs) const {\n"
- << Indent2 << "unsigned ret = 0;\n";
+ O.indent(Indent1)
+ << "unsigned Weight(const InputLanguagesSet& InLangs) const {\n";
+ O.indent(Indent2) << "unsigned ret = 0;\n";
// Handle the 'case' construct.
EmitCaseConstructHandler(Case, Indent2, IncDecWeight, false, OptDescs, O);
- O << Indent2 << "return ret;\n"
- << Indent1 << "};\n\n};\n\n";
+ O.indent(Indent2) << "return ret;\n";
+ O.indent(Indent1) << "};\n\n};\n\n";
}
/// EmitEdgeClasses - Emit Edge* classes that represent graph edges.
@@ -1852,7 +1985,7 @@ void EmitPopulateCompilationGraph (const RecordVector& EdgeVector,
for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
E = ToolDescs.end(); B != E; ++B)
- O << Indent1 << "G.insertNode(new " << (*B)->Name << "());\n";
+ O.indent(Indent1) << "G.insertNode(new " << (*B)->Name << "());\n";
O << '\n';
@@ -1866,7 +1999,7 @@ void EmitPopulateCompilationGraph (const RecordVector& EdgeVector,
const std::string& NodeB = Edge->getValueAsString("b");
DagInit* Weight = Edge->getValueAsDag("weight");
- O << Indent1 << "G.insertEdge(\"" << NodeA << "\", ";
+ O.indent(Indent1) << "G.insertEdge(\"" << NodeA << "\", ";
if (isDagEmpty(Weight))
O << "new SimpleEdge(\"" << NodeB << "\")";
@@ -1955,7 +2088,7 @@ void EmitHookDeclarations(const ToolDescriptions& ToolDescs, raw_ostream& O) {
O << "namespace hooks {\n";
for (StringMap<unsigned>::const_iterator B = HookNames.begin(),
E = HookNames.end(); B != E; ++B) {
- O << Indent1 << "std::string " << B->first() << "(";
+ O.indent(Indent1) << "std::string " << B->first() << "(";
for (unsigned i = 0, j = B->second; i < j; ++i) {
O << "const char* Arg" << i << (i+1 == j ? "" : ", ");
@@ -1968,22 +2101,23 @@ void EmitHookDeclarations(const ToolDescriptions& ToolDescs, raw_ostream& O) {
/// EmitRegisterPlugin - Emit code to register this plugin.
void EmitRegisterPlugin(int Priority, raw_ostream& O) {
- O << "struct Plugin : public llvmc::BasePlugin {\n\n"
- << Indent1 << "int Priority() const { return " << Priority << "; }\n\n"
- << Indent1 << "void PopulateLanguageMap(LanguageMap& langMap) const\n"
- << Indent1 << "{ PopulateLanguageMapLocal(langMap); }\n\n"
- << Indent1
- << "void PopulateCompilationGraph(CompilationGraph& graph) const\n"
- << Indent1 << "{ PopulateCompilationGraphLocal(graph); }\n"
- << "};\n\n"
-
- << "static llvmc::RegisterPlugin<Plugin> RP;\n\n";
+ O << "struct Plugin : public llvmc::BasePlugin {\n\n";
+ O.indent(Indent1) << "int Priority() const { return "
+ << Priority << "; }\n\n";
+ O.indent(Indent1) << "void PopulateLanguageMap(LanguageMap& langMap) const\n";
+ O.indent(Indent1) << "{ PopulateLanguageMapLocal(langMap); }\n\n";
+ O.indent(Indent1)
+ << "void PopulateCompilationGraph(CompilationGraph& graph) const\n";
+ O.indent(Indent1) << "{ PopulateCompilationGraphLocal(graph); }\n"
+ << "};\n\n"
+ << "static llvmc::RegisterPlugin<Plugin> RP;\n\n";
}
/// EmitIncludes - Emit necessary #include directives and some
/// additional declarations.
void EmitIncludes(raw_ostream& O) {
- O << "#include \"llvm/CompilerDriver/CompilationGraph.h\"\n"
+ O << "#include \"llvm/CompilerDriver/BuiltinOptions.h\"\n"
+ << "#include \"llvm/CompilerDriver/CompilationGraph.h\"\n"
<< "#include \"llvm/CompilerDriver/ForceLinkageMacros.h\"\n"
<< "#include \"llvm/CompilerDriver/Plugin.h\"\n"
<< "#include \"llvm/CompilerDriver/Tool.h\"\n\n"
diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp
index 8f31624..a551166 100644
--- a/utils/TableGen/Record.cpp
+++ b/utils/TableGen/Record.cpp
@@ -1319,6 +1319,8 @@ void RecordVal::print(raw_ostream &OS, bool PrintSem) const {
if (PrintSem) OS << ";\n";
}
+unsigned Record::LastID = 0;
+
void Record::setName(const std::string &Name) {
if (Records.getDef(getName()) == this) {
Records.removeDef(getName());
@@ -1382,11 +1384,11 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const Record &R) {
/// getValueInit - Return the initializer for a value with the specified name,
/// or throw an exception if the field does not exist.
///
-Init *Record::getValueInit(const std::string &FieldName) const {
+Init *Record::getValueInit(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName);
if (R == 0 || R->getValue() == 0)
throw "Record `" + getName() + "' does not have a field named `" +
- FieldName + "'!\n";
+ FieldName.str() + "'!\n";
return R->getValue();
}
@@ -1395,15 +1397,15 @@ Init *Record::getValueInit(const std::string &FieldName) const {
/// value as a string, throwing an exception if the field does not exist or if
/// the value is not a string.
///
-std::string Record::getValueAsString(const std::string &FieldName) const {
+std::string Record::getValueAsString(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName);
if (R == 0 || R->getValue() == 0)
throw "Record `" + getName() + "' does not have a field named `" +
- FieldName + "'!\n";
+ FieldName.str() + "'!\n";
if (const StringInit *SI = dynamic_cast<const StringInit*>(R->getValue()))
return SI->getValue();
- throw "Record `" + getName() + "', field `" + FieldName +
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
"' does not have a string initializer!";
}
@@ -1411,15 +1413,15 @@ std::string Record::getValueAsString(const std::string &FieldName) const {
/// its value as a BitsInit, throwing an exception if the field does not exist
/// or if the value is not the right type.
///
-BitsInit *Record::getValueAsBitsInit(const std::string &FieldName) const {
+BitsInit *Record::getValueAsBitsInit(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName);
if (R == 0 || R->getValue() == 0)
throw "Record `" + getName() + "' does not have a field named `" +
- FieldName + "'!\n";
+ FieldName.str() + "'!\n";
if (BitsInit *BI = dynamic_cast<BitsInit*>(R->getValue()))
return BI;
- throw "Record `" + getName() + "', field `" + FieldName +
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
"' does not have a BitsInit initializer!";
}
@@ -1427,15 +1429,15 @@ BitsInit *Record::getValueAsBitsInit(const std::string &FieldName) const {
/// its value as a ListInit, throwing an exception if the field does not exist
/// or if the value is not the right type.
///
-ListInit *Record::getValueAsListInit(const std::string &FieldName) const {
+ListInit *Record::getValueAsListInit(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName);
if (R == 0 || R->getValue() == 0)
throw "Record `" + getName() + "' does not have a field named `" +
- FieldName + "'!\n";
+ FieldName.str() + "'!\n";
if (ListInit *LI = dynamic_cast<ListInit*>(R->getValue()))
return LI;
- throw "Record `" + getName() + "', field `" + FieldName +
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
"' does not have a list initializer!";
}
@@ -1444,14 +1446,14 @@ ListInit *Record::getValueAsListInit(const std::string &FieldName) const {
/// not exist or if the value is not the right type.
///
std::vector<Record*>
-Record::getValueAsListOfDefs(const std::string &FieldName) const {
+Record::getValueAsListOfDefs(StringRef FieldName) const {
ListInit *List = getValueAsListInit(FieldName);
std::vector<Record*> Defs;
for (unsigned i = 0; i < List->getSize(); i++) {
if (DefInit *DI = dynamic_cast<DefInit*>(List->getElement(i))) {
Defs.push_back(DI->getDef());
} else {
- throw "Record `" + getName() + "', field `" + FieldName +
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
"' list is not entirely DefInit!";
}
}
@@ -1462,15 +1464,15 @@ Record::getValueAsListOfDefs(const std::string &FieldName) const {
/// value as an int64_t, throwing an exception if the field does not exist or if
/// the value is not the right type.
///
-int64_t Record::getValueAsInt(const std::string &FieldName) const {
+int64_t Record::getValueAsInt(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName);
if (R == 0 || R->getValue() == 0)
throw "Record `" + getName() + "' does not have a field named `" +
- FieldName + "'!\n";
+ FieldName.str() + "'!\n";
if (IntInit *II = dynamic_cast<IntInit*>(R->getValue()))
return II->getValue();
- throw "Record `" + getName() + "', field `" + FieldName +
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
"' does not have an int initializer!";
}
@@ -1479,14 +1481,14 @@ int64_t Record::getValueAsInt(const std::string &FieldName) const {
/// not exist or if the value is not the right type.
///
std::vector<int64_t>
-Record::getValueAsListOfInts(const std::string &FieldName) const {
+Record::getValueAsListOfInts(StringRef FieldName) const {
ListInit *List = getValueAsListInit(FieldName);
std::vector<int64_t> Ints;
for (unsigned i = 0; i < List->getSize(); i++) {
if (IntInit *II = dynamic_cast<IntInit*>(List->getElement(i))) {
Ints.push_back(II->getValue());
} else {
- throw "Record `" + getName() + "', field `" + FieldName +
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
"' does not have a list of ints initializer!";
}
}
@@ -1497,15 +1499,15 @@ Record::getValueAsListOfInts(const std::string &FieldName) const {
/// value as a Record, throwing an exception if the field does not exist or if
/// the value is not the right type.
///
-Record *Record::getValueAsDef(const std::string &FieldName) const {
+Record *Record::getValueAsDef(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName);
if (R == 0 || R->getValue() == 0)
throw "Record `" + getName() + "' does not have a field named `" +
- FieldName + "'!\n";
+ FieldName.str() + "'!\n";
if (DefInit *DI = dynamic_cast<DefInit*>(R->getValue()))
return DI->getDef();
- throw "Record `" + getName() + "', field `" + FieldName +
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
"' does not have a def initializer!";
}
@@ -1513,15 +1515,15 @@ Record *Record::getValueAsDef(const std::string &FieldName) const {
/// value as a bit, throwing an exception if the field does not exist or if
/// the value is not the right type.
///
-bool Record::getValueAsBit(const std::string &FieldName) const {
+bool Record::getValueAsBit(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName);
if (R == 0 || R->getValue() == 0)
throw "Record `" + getName() + "' does not have a field named `" +
- FieldName + "'!\n";
+ FieldName.str() + "'!\n";
if (BitInit *BI = dynamic_cast<BitInit*>(R->getValue()))
return BI->getValue();
- throw "Record `" + getName() + "', field `" + FieldName +
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
"' does not have a bit initializer!";
}
@@ -1529,27 +1531,27 @@ bool Record::getValueAsBit(const std::string &FieldName) const {
/// value as an Dag, throwing an exception if the field does not exist or if
/// the value is not the right type.
///
-DagInit *Record::getValueAsDag(const std::string &FieldName) const {
+DagInit *Record::getValueAsDag(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName);
if (R == 0 || R->getValue() == 0)
throw "Record `" + getName() + "' does not have a field named `" +
- FieldName + "'!\n";
+ FieldName.str() + "'!\n";
if (DagInit *DI = dynamic_cast<DagInit*>(R->getValue()))
return DI;
- throw "Record `" + getName() + "', field `" + FieldName +
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
"' does not have a dag initializer!";
}
-std::string Record::getValueAsCode(const std::string &FieldName) const {
+std::string Record::getValueAsCode(StringRef FieldName) const {
const RecordVal *R = getValue(FieldName);
if (R == 0 || R->getValue() == 0)
throw "Record `" + getName() + "' does not have a field named `" +
- FieldName + "'!\n";
+ FieldName.str() + "'!\n";
if (const CodeInit *CI = dynamic_cast<const CodeInit*>(R->getValue()))
return CI->getValue();
- throw "Record `" + getName() + "', field `" + FieldName +
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
"' does not have a code initializer!";
}
diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h
index 11db910..1b33743 100644
--- a/utils/TableGen/Record.h
+++ b/utils/TableGen/Record.h
@@ -782,7 +782,7 @@ public:
// Clone - Clone this operator, replacing arguments with the new list
virtual OpInit *clone(std::vector<Init *> &Operands) = 0;
- virtual int getNumOperands(void) const = 0;
+ virtual int getNumOperands() const = 0;
virtual Init *getOperand(int i) = 0;
// Fold - If possible, fold this to a simpler init. Return this if not
@@ -820,7 +820,7 @@ public:
return new UnOpInit(getOpcode(), *Operands.begin(), getType());
}
- int getNumOperands(void) const { return 1; }
+ int getNumOperands() const { return 1; }
Init *getOperand(int i) {
assert(i == 0 && "Invalid operand id for unary operator");
return getOperand();
@@ -864,7 +864,7 @@ public:
return new BinOpInit(getOpcode(), Operands[0], Operands[1], getType());
}
- int getNumOperands(void) const { return 2; }
+ int getNumOperands() const { return 2; }
Init *getOperand(int i) {
assert((i == 0 || i == 1) && "Invalid operand id for binary operator");
if (i == 0) {
@@ -909,7 +909,7 @@ public:
getType());
}
- int getNumOperands(void) const { return 3; }
+ int getNumOperands() const { return 3; }
Init *getOperand(int i) {
assert((i == 0 || i == 1 || i == 2) &&
"Invalid operand id for ternary operator");
@@ -1220,6 +1220,10 @@ inline raw_ostream &operator<<(raw_ostream &OS, const RecordVal &RV) {
}
class Record {
+ static unsigned LastID;
+
+ // Unique record ID.
+ unsigned ID;
std::string Name;
SMLoc Loc;
std::vector<std::string> TemplateArgs;
@@ -1227,9 +1231,12 @@ class Record {
std::vector<Record*> SuperClasses;
public:
- explicit Record(const std::string &N, SMLoc loc) : Name(N), Loc(loc) {}
+ explicit Record(const std::string &N, SMLoc loc) :
+ ID(LastID++), Name(N), Loc(loc) {}
~Record() {}
+ unsigned getID() const { return ID; }
+
const std::string &getName() const { return Name; }
void setName(const std::string &Name); // Also updates RecordKeeper.
@@ -1241,24 +1248,24 @@ public:
const std::vector<RecordVal> &getValues() const { return Values; }
const std::vector<Record*> &getSuperClasses() const { return SuperClasses; }
- bool isTemplateArg(const std::string &Name) const {
+ bool isTemplateArg(StringRef Name) const {
for (unsigned i = 0, e = TemplateArgs.size(); i != e; ++i)
if (TemplateArgs[i] == Name) return true;
return false;
}
- const RecordVal *getValue(const std::string &Name) const {
+ const RecordVal *getValue(StringRef Name) const {
for (unsigned i = 0, e = Values.size(); i != e; ++i)
if (Values[i].getName() == Name) return &Values[i];
return 0;
}
- RecordVal *getValue(const std::string &Name) {
+ RecordVal *getValue(StringRef Name) {
for (unsigned i = 0, e = Values.size(); i != e; ++i)
if (Values[i].getName() == Name) return &Values[i];
return 0;
}
- void addTemplateArg(const std::string &Name) {
+ void addTemplateArg(StringRef Name) {
assert(!isTemplateArg(Name) && "Template arg already defined!");
TemplateArgs.push_back(Name);
}
@@ -1268,7 +1275,7 @@ public:
Values.push_back(RV);
}
- void removeValue(const std::string &Name) {
+ void removeValue(StringRef Name) {
assert(getValue(Name) && "Cannot remove an entry that does not exist!");
for (unsigned i = 0, e = Values.size(); i != e; ++i)
if (Values[i].getName() == Name) {
@@ -1285,7 +1292,7 @@ public:
return false;
}
- bool isSubClassOf(const std::string &Name) const {
+ bool isSubClassOf(StringRef Name) const {
for (unsigned i = 0, e = SuperClasses.size(); i != e; ++i)
if (SuperClasses[i]->getName() == Name)
return true;
@@ -1316,67 +1323,67 @@ public:
/// getValueInit - Return the initializer for a value with the specified name,
/// or throw an exception if the field does not exist.
///
- Init *getValueInit(const std::string &FieldName) const;
+ Init *getValueInit(StringRef FieldName) const;
/// getValueAsString - This method looks up the specified field and returns
/// its value as a string, throwing an exception if the field does not exist
/// or if the value is not a string.
///
- std::string getValueAsString(const std::string &FieldName) const;
+ std::string getValueAsString(StringRef FieldName) const;
/// getValueAsBitsInit - This method looks up the specified field and returns
/// its value as a BitsInit, throwing an exception if the field does not exist
/// or if the value is not the right type.
///
- BitsInit *getValueAsBitsInit(const std::string &FieldName) const;
+ BitsInit *getValueAsBitsInit(StringRef FieldName) const;
/// getValueAsListInit - This method looks up the specified field and returns
/// its value as a ListInit, throwing an exception if the field does not exist
/// or if the value is not the right type.
///
- ListInit *getValueAsListInit(const std::string &FieldName) const;
+ ListInit *getValueAsListInit(StringRef FieldName) const;
/// getValueAsListOfDefs - This method looks up the specified field and
/// returns its value as a vector of records, throwing an exception if the
/// field does not exist or if the value is not the right type.
///
- std::vector<Record*> getValueAsListOfDefs(const std::string &FieldName) const;
+ std::vector<Record*> getValueAsListOfDefs(StringRef FieldName) const;
/// getValueAsListOfInts - This method looks up the specified field and returns
/// its value as a vector of integers, throwing an exception if the field does
/// not exist or if the value is not the right type.
///
- std::vector<int64_t> getValueAsListOfInts(const std::string &FieldName) const;
+ std::vector<int64_t> getValueAsListOfInts(StringRef FieldName) const;
/// getValueAsDef - This method looks up the specified field and returns its
/// value as a Record, throwing an exception if the field does not exist or if
/// the value is not the right type.
///
- Record *getValueAsDef(const std::string &FieldName) const;
+ Record *getValueAsDef(StringRef FieldName) const;
/// getValueAsBit - This method looks up the specified field and returns its
/// value as a bit, throwing an exception if the field does not exist or if
/// the value is not the right type.
///
- bool getValueAsBit(const std::string &FieldName) const;
+ bool getValueAsBit(StringRef FieldName) const;
/// getValueAsInt - This method looks up the specified field and returns its
/// value as an int64_t, throwing an exception if the field does not exist or
/// if the value is not the right type.
///
- int64_t getValueAsInt(const std::string &FieldName) const;
+ int64_t getValueAsInt(StringRef FieldName) const;
/// getValueAsDag - This method looks up the specified field and returns its
/// value as an Dag, throwing an exception if the field does not exist or if
/// the value is not the right type.
///
- DagInit *getValueAsDag(const std::string &FieldName) const;
+ DagInit *getValueAsDag(StringRef FieldName) const;
/// getValueAsCode - This method looks up the specified field and returns
/// its value as the string data in a CodeInit, throwing an exception if the
/// field does not exist or if the value is not a code object.
///
- std::string getValueAsCode(const std::string &FieldName) const;
+ std::string getValueAsCode(StringRef FieldName) const;
};
raw_ostream &operator<<(raw_ostream &OS, const Record &R);
diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp
index 3297e93..3c7b44a 100644
--- a/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/utils/TableGen/RegisterInfoEmitter.cpp
@@ -222,7 +222,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
// Emit the register list now.
OS << " // " << Name
<< " Register Class Value Types...\n"
- << " static const MVT " << Name
+ << " static const EVT " << Name
<< "[] = {\n ";
for (unsigned i = 0, e = RC.VTs.size(); i != e; ++i)
OS << getEnumName(RC.VTs[i]) << ", ";
@@ -252,7 +252,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
OS << " // " << Name
<< " Sub-register Classes...\n"
<< " static const TargetRegisterClass* const "
- << Name << "SubRegClasses [] = {\n ";
+ << Name << "SubRegClasses[] = {\n ";
bool Empty = true;
@@ -298,7 +298,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
OS << " // " << Name
<< " Super-register Classes...\n"
<< " static const TargetRegisterClass* const "
- << Name << "SuperRegClasses [] = {\n ";
+ << Name << "SuperRegClasses[] = {\n ";
bool Empty = true;
std::map<unsigned, std::set<unsigned> >::iterator I =
@@ -334,7 +334,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
OS << " // " << Name
<< " Register Class sub-classes...\n"
<< " static const TargetRegisterClass* const "
- << Name << "Subclasses [] = {\n ";
+ << Name << "Subclasses[] = {\n ";
bool Empty = true;
for (unsigned rc2 = 0, e2 = RegisterClasses.size(); rc2 != e2; ++rc2) {
@@ -382,7 +382,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
OS << " // " << Name
<< " Register Class super-classes...\n"
<< " static const TargetRegisterClass* const "
- << Name << "Superclasses [] = {\n ";
+ << Name << "Superclasses[] = {\n ";
bool Empty = true;
std::map<unsigned, std::set<unsigned> >::iterator I =
@@ -767,7 +767,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
}
OS<<"\n const TargetRegisterDesc RegisterDescriptors[] = { // Descriptors\n";
- OS << " { \"NOREG\",\t\"NOREG\",\t0,\t0,\t0 },\n";
+ OS << " { \"NOREG\",\t0,\t0,\t0 },\n";
// Now that register alias and sub-registers sets have been emitted, emit the
// register descriptors now.
@@ -775,11 +775,6 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
const CodeGenRegister &Reg = Registers[i];
OS << " { \"";
- if (!Reg.TheDef->getValueAsString("AsmName").empty())
- OS << Reg.TheDef->getValueAsString("AsmName");
- else
- OS << Reg.getName();
- OS << "\",\t\"";
OS << Reg.getName() << "\",\t";
if (RegisterAliases.count(Reg.TheDef))
OS << Reg.getName() << "_AliasSet,\t";
diff --git a/utils/TableGen/StringToOffsetTable.h b/utils/TableGen/StringToOffsetTable.h
new file mode 100644
index 0000000..d9d7cf4
--- /dev/null
+++ b/utils/TableGen/StringToOffsetTable.h
@@ -0,0 +1,76 @@
+//===- 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/StringMap.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/StringExtras.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) {
+ unsigned &Entry = StringOffset[Str];
+ if (Entry == 0) {
+ // Add the string to the aggregate if this is the first time found.
+ Entry = AggregateString.size();
+ AggregateString.append(Str.begin(), Str.end());
+ AggregateString += '\0';
+ }
+
+ return Entry;
+ }
+
+ void EmitString(raw_ostream &O) {
+ O << " \"";
+ unsigned CharsPrinted = 0;
+ EscapeString(AggregateString);
+ 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/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp
index 919ac66..c8cf234 100644
--- a/utils/TableGen/SubtargetEmitter.cpp
+++ b/utils/TableGen/SubtargetEmitter.cpp
@@ -199,12 +199,13 @@ unsigned SubtargetEmitter::CollectAllItinClasses(raw_ostream &OS,
}
//
-// FormItineraryString - Compose a string containing the data initialization
-// for the specified itinerary. N is the number of stages.
+// FormItineraryStageString - Compose a string containing the stage
+// data initialization for the specified itinerary. N is the number
+// of stages.
//
-void SubtargetEmitter::FormItineraryString(Record *ItinData,
- std::string &ItinString,
- unsigned &NStages) {
+void SubtargetEmitter::FormItineraryStageString(Record *ItinData,
+ std::string &ItinString,
+ unsigned &NStages) {
// Get states list
const std::vector<Record*> &StageList =
ItinData->getValueAsListOfDefs("Stages");
@@ -215,7 +216,7 @@ void SubtargetEmitter::FormItineraryString(Record *ItinData,
// Next stage
const Record *Stage = StageList[i];
- // Form string as ,{ cycles, u1 | u2 | ... | un }
+ // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc }
int Cycles = Stage->getValueAsInt("Cycles");
ItinString += " { " + itostr(Cycles) + ", ";
@@ -229,6 +230,9 @@ void SubtargetEmitter::FormItineraryString(Record *ItinData,
if (++j < M) ItinString += " | ";
}
+ int TimeInc = Stage->getValueAsInt("TimeInc");
+ ItinString += ", " + itostr(TimeInc);
+
// Close off stage
ItinString += " }";
if (++i < N) ItinString += ", ";
@@ -236,10 +240,32 @@ void SubtargetEmitter::FormItineraryString(Record *ItinData,
}
//
-// EmitStageData - Generate unique itinerary stages. Record itineraries for
-// processors.
+// 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 += ", ";
+ }
+}
+
+//
+// EmitStageAndOperandCycleData - Generate unique itinerary stages and
+// operand cycle tables. Record itineraries for processors.
//
-void SubtargetEmitter::EmitStageData(raw_ostream &OS,
+void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS,
unsigned NItinClasses,
std::map<std::string, unsigned> &ItinClassesMap,
std::vector<std::vector<InstrItinerary> > &ProcList) {
@@ -251,12 +277,16 @@ void SubtargetEmitter::EmitStageData(raw_ostream &OS,
if (ProcItinList.size() < 2) return;
// Begin stages table
- OS << "static const llvm::InstrStage Stages[] = {\n"
- " { 0, 0 }, // No itinerary\n";
+ std::string StageTable = "static const llvm::InstrStage Stages[] = {\n";
+ StageTable += " { 0, 0, 0 }, // No itinerary\n";
- unsigned StageCount = 1;
- unsigned ItinEnum = 1;
- std::map<std::string, unsigned> ItinMap;
+ // Begin operand cycle table
+ std::string OperandCycleTable = "static const unsigned OperandCycles[] = {\n";
+ OperandCycleTable += " 0, // No itinerary\n";
+
+ unsigned StageCount = 1, OperandCycleCount = 1;
+ unsigned ItinStageEnum = 1, ItinOperandCycleEnum = 1;
+ std::map<std::string, unsigned> ItinStageMap, ItinOperandCycleMap;
for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) {
// Next record
Record *Proc = ProcItinList[i];
@@ -280,29 +310,53 @@ void SubtargetEmitter::EmitStageData(raw_ostream &OS,
Record *ItinData = ItinDataList[j];
// Get string and stage count
- std::string ItinString;
+ std::string ItinStageString;
unsigned NStages;
- FormItineraryString(ItinData, ItinString, NStages);
-
- // Check to see if it already exists
- unsigned Find = ItinMap[ItinString];
+ FormItineraryStageString(ItinData, ItinStageString, NStages);
+
+ // Get string and operand cycle count
+ std::string ItinOperandCycleString;
+ unsigned NOperandCycles;
+ FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
+ 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 }, // index
+ StageTable += ItinStageString + ", // " + itostr(ItinStageEnum) + "\n";
+ // Record Itin class number.
+ ItinStageMap[ItinStageString] = FindStage = StageCount;
+ StageCount += NStages;
+ ItinStageEnum++;
+ }
+ }
- // If new itinerary
- if (Find == 0) {
- // Emit as { cycles, u1 | u2 | ... | un }, // index
- OS << ItinString << ", // " << ItinEnum << "\n";
- // Record Itin class number.
- ItinMap[ItinString] = Find = StageCount;
- StageCount += NStages;
- ItinEnum++;
+ // Check to see if operand cycle already exists and create if it doesn't
+ unsigned FindOperandCycle = 0;
+ if (NOperandCycles > 0) {
+ FindOperandCycle = ItinOperandCycleMap[ItinOperandCycleString];
+ if (FindOperandCycle == 0) {
+ // Emit as cycle, // index
+ OperandCycleTable += ItinOperandCycleString + ", // " +
+ itostr(ItinOperandCycleEnum) + "\n";
+ // Record Itin class number.
+ ItinOperandCycleMap[ItinOperandCycleString] =
+ FindOperandCycle = OperandCycleCount;
+ OperandCycleCount += NOperandCycles;
+ ItinOperandCycleEnum++;
+ }
}
// Set up itinerary as location and location + stage count
- InstrItinerary Intinerary = { Find, Find + NStages };
+ InstrItinerary Intinerary = { FindStage, FindStage + NStages,
+ FindOperandCycle, FindOperandCycle + NOperandCycles};
// Locate where to inject into processor itinerary table
const std::string &Name = ItinData->getValueAsDef("TheClass")->getName();
- Find = ItinClassesMap[Name];
+ unsigned Find = ItinClassesMap[Name];
// Inject - empty slots will be 0, 0
ItinList[Find] = Intinerary;
@@ -313,13 +367,21 @@ void SubtargetEmitter::EmitStageData(raw_ostream &OS,
}
// Closing stage
- OS << " { 0, 0 } // End itinerary\n";
- // End stages table
- OS << "};\n";
+ StageTable += " { 0, 0, 0 } // End itinerary\n";
+ StageTable += "};\n";
+
+ // Closing operand cycles
+ OperandCycleTable += " 0 // End itinerary\n";
+ OperandCycleTable += "};\n";
+
+ // Emit tables.
+ OS << StageTable;
+ OS << OperandCycleTable;
- // Emit size of table
+ // Emit size of tables
OS<<"\nenum {\n";
- OS<<" StagesSize = sizeof(Stages)/sizeof(llvm::InstrStage)\n";
+ OS<<" StagesSize = sizeof(Stages)/sizeof(llvm::InstrStage),\n";
+ OS<<" OperandCyclesSize = sizeof(OperandCycles)/sizeof(unsigned)\n";
OS<<"};\n";
}
@@ -351,23 +413,25 @@ void SubtargetEmitter::EmitProcessorData(raw_ostream &OS,
// For each itinerary class
std::vector<InstrItinerary> &ItinList = *ProcListIter++;
- for (unsigned j = 0, M = ItinList.size(); j < M;) {
+ for (unsigned j = 0, M = ItinList.size(); j < M; ++j) {
InstrItinerary &Intinerary = ItinList[j];
- // Emit in the form of { first, last } // index
- if (Intinerary.First == 0) {
- OS << " { 0, 0 }";
+ // Emit in the form of
+ // { firstStage, lastStage, firstCycle, lastCycle } // index
+ if (Intinerary.FirstStage == 0) {
+ OS << " { 0, 0, 0, 0 }";
} else {
- OS << " { " << Intinerary.First << ", " << Intinerary.Last << " }";
+ OS << " { " << Intinerary.FirstStage << ", " <<
+ Intinerary.LastStage << ", " <<
+ Intinerary.FirstOperandCycle << ", " <<
+ Intinerary.LastOperandCycle << " }";
}
- // If more in list add comma
- if (++j < M) OS << ",";
-
- OS << " // " << (j - 1) << "\n";
+ OS << ", // " << j << "\n";
}
// End processor itinerary table
+ OS << " { ~0U, ~0U, ~0U, ~0U } // end marker\n";
OS << "};\n";
}
}
@@ -432,7 +496,7 @@ void SubtargetEmitter::EmitData(raw_ostream &OS) {
if (HasItineraries) {
// Emit the stage data
- EmitStageData(OS, NItinClasses, ItinClassesMap, ProcList);
+ EmitStageAndOperandCycleData(OS, NItinClasses, ItinClassesMap, ProcList);
// Emit the processor itinerary data
EmitProcessorData(OS, ProcList);
// Emit the processor lookup data
@@ -479,7 +543,7 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) {
OS << "\n"
<< " InstrItinerary *Itinerary = (InstrItinerary *)"
<< "Features.getInfo(ProcItinKV, ProcItinKVSize);\n"
- << " InstrItins = InstrItineraryData(Stages, Itinerary);\n";
+ << " InstrItins = InstrItineraryData(Stages, OperandCycles, Itinerary);\n";
}
OS << " return Features.getCPU();\n"
diff --git a/utils/TableGen/SubtargetEmitter.h b/utils/TableGen/SubtargetEmitter.h
index f44278c..1d7088f 100644
--- a/utils/TableGen/SubtargetEmitter.h
+++ b/utils/TableGen/SubtargetEmitter.h
@@ -34,9 +34,11 @@ class SubtargetEmitter : public TableGenBackend {
void CPUKeyValues(raw_ostream &OS);
unsigned CollectAllItinClasses(raw_ostream &OS,
std::map<std::string, unsigned> &ItinClassesMap);
- void FormItineraryString(Record *ItinData, std::string &ItinString,
- unsigned &NStages);
- void EmitStageData(raw_ostream &OS, unsigned NItinClasses,
+ void FormItineraryStageString(Record *ItinData, std::string &ItinString,
+ unsigned &NStages);
+ void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString,
+ unsigned &NOperandCycles);
+ void EmitStageAndOperandCycleData(raw_ostream &OS, unsigned NItinClasses,
std::map<std::string, unsigned> &ItinClassesMap,
std::vector<std::vector<InstrItinerary> > &ProcList);
void EmitProcessorData(raw_ostream &OS,
diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp
index ba480e6..7122265 100644
--- a/utils/TableGen/TGParser.cpp
+++ b/utils/TableGen/TGParser.cpp
@@ -974,7 +974,7 @@ Init *TGParser::ParseOperation(Record *CurRec) {
///
/// OperatorType ::= '<' Type '>'
///
-RecTy *TGParser::ParseOperatorType(void) {
+RecTy *TGParser::ParseOperatorType() {
RecTy *Type = 0;
if (Lex.getCode() != tgtok::less) {
diff --git a/utils/TableGen/TGValueTypes.cpp b/utils/TableGen/TGValueTypes.cpp
index e4edca6..122d085 100644
--- a/utils/TableGen/TGValueTypes.cpp
+++ b/utils/TableGen/TGValueTypes.cpp
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
//
-// The MVT type is used by tablegen as well as in LLVM. In order to handle
-// extended types, the MVT type uses support functions that call into
+// 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.
//
@@ -43,15 +43,15 @@ public:
};
class ExtendedVectorType : public Type {
- MVT ElementType;
+ EVT ElementType;
unsigned NumElements;
public:
- ExtendedVectorType(MVT elty, unsigned num)
+ ExtendedVectorType(EVT elty, unsigned num)
: ElementType(elty), NumElements(num) {}
unsigned getSizeInBits() const {
return getNumElements() * getElementType().getSizeInBits();
}
- MVT getElementType() const {
+ EVT getElementType() const {
return ElementType;
}
unsigned getNumElements() const {
@@ -64,62 +64,43 @@ static std::map<unsigned, const Type *>
static std::map<std::pair<uintptr_t, uintptr_t>, const Type *>
ExtendedVectorTypeMap;
-MVT MVT::getExtendedIntegerVT(unsigned BitWidth) {
- const Type *&ET = ExtendedIntegerTypeMap[BitWidth];
- if (!ET) ET = new ExtendedIntegerType(BitWidth);
- MVT VT;
- VT.LLVMTy = ET;
- assert(VT.isExtended() && "Type is not extended!");
- return VT;
-}
-
-MVT MVT::getExtendedVectorVT(MVT VT, unsigned NumElements) {
- const Type *&ET = ExtendedVectorTypeMap[std::make_pair(VT.getRawBits(),
- NumElements)];
- if (!ET) ET = new ExtendedVectorType(VT, NumElements);
- MVT ResultVT;
- ResultVT.LLVMTy = ET;
- assert(ResultVT.isExtended() && "Type is not extended!");
- return ResultVT;
-}
-
-bool MVT::isExtendedFloatingPoint() const {
+bool EVT::isExtendedFloatingPoint() const {
assert(isExtended() && "Type is not extended!");
// Extended floating-point types are not supported yet.
return false;
}
-bool MVT::isExtendedInteger() const {
+bool EVT::isExtendedInteger() const {
assert(isExtended() && "Type is not extended!");
return dynamic_cast<const ExtendedIntegerType *>(LLVMTy) != 0;
}
-bool MVT::isExtendedVector() const {
+bool EVT::isExtendedVector() const {
assert(isExtended() && "Type is not extended!");
return dynamic_cast<const ExtendedVectorType *>(LLVMTy) != 0;
}
-bool MVT::isExtended64BitVector() const {
+bool EVT::isExtended64BitVector() const {
assert(isExtended() && "Type is not extended!");
return isExtendedVector() && getSizeInBits() == 64;
}
-bool MVT::isExtended128BitVector() const {
+bool EVT::isExtended128BitVector() const {
assert(isExtended() && "Type is not extended!");
return isExtendedVector() && getSizeInBits() == 128;
}
-MVT MVT::getExtendedVectorElementType() const {
+EVT EVT::getExtendedVectorElementType() const {
assert(isExtendedVector() && "Type is not an extended vector!");
return static_cast<const ExtendedVectorType *>(LLVMTy)->getElementType();
}
-unsigned MVT::getExtendedVectorNumElements() const {
+unsigned EVT::getExtendedVectorNumElements() const {
assert(isExtendedVector() && "Type is not an extended vector!");
return static_cast<const ExtendedVectorType *>(LLVMTy)->getNumElements();
}
-unsigned MVT::getExtendedSizeInBits() const {
+unsigned EVT::getExtendedSizeInBits() const {
assert(isExtended() && "Type is not extended!");
return LLVMTy->getSizeInBits();
}
diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index 6015814..c6d7502 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/utils/TableGen/TableGen.cpp
@@ -17,24 +17,25 @@
#include "Record.h"
#include "TGParser.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/System/Signals.h"
-#include "llvm/Support/FileUtilities.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/raw_ostream.h"
#include "CallingConvEmitter.h"
#include "CodeEmitterGen.h"
#include "RegisterInfoEmitter.h"
#include "InstrInfoEmitter.h"
#include "InstrEnumEmitter.h"
#include "AsmWriterEmitter.h"
+#include "AsmMatcherEmitter.h"
#include "DAGISelEmitter.h"
#include "FastISelEmitter.h"
#include "SubtargetEmitter.h"
#include "IntrinsicEmitter.h"
#include "LLVMCConfigurationEmitter.h"
#include "ClangDiagnosticsEmitter.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Signals.h"
#include <algorithm>
#include <cstdio>
using namespace llvm;
@@ -43,7 +44,7 @@ enum ActionType {
PrintRecords,
GenEmitter,
GenRegisterEnums, GenRegister, GenRegisterHeader,
- GenInstrEnums, GenInstrs, GenAsmWriter,
+ GenInstrEnums, GenInstrs, GenAsmWriter, GenAsmMatcher,
GenCallingConv,
GenClangDiagsDefs,
GenClangDiagGroups,
@@ -77,6 +78,8 @@ namespace {
"Generate calling convention descriptions"),
clEnumValN(GenAsmWriter, "gen-asm-writer",
"Generate assembly writer"),
+ clEnumValN(GenAsmMatcher, "gen-asm-matcher",
+ "Generate assembly instruction matcher"),
clEnumValN(GenDAGISel, "gen-dag-isel",
"Generate a DAG instruction selector"),
clEnumValN(GenFastISel, "gen-fast-isel",
@@ -138,7 +141,7 @@ static bool ParseFile(const std::string &Filename,
std::string ErrorStr;
MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrorStr);
if (F == 0) {
- errs() << "Could not open input file '" + Filename + "': "
+ errs() << "Could not open input file '" << Filename << "': "
<< ErrorStr <<"\n";
return true;
}
@@ -168,7 +171,7 @@ int main(int argc, char **argv) {
raw_ostream *Out = &outs();
if (OutputFilename != "-") {
std::string Error;
- Out = new raw_fd_ostream(OutputFilename.c_str(), false, Error);
+ Out = new raw_fd_ostream(OutputFilename.c_str(), Error);
if (!Error.empty()) {
errs() << argv[0] << ": error opening " << OutputFilename
@@ -210,6 +213,9 @@ int main(int argc, char **argv) {
case GenAsmWriter:
AsmWriterEmitter(Records).run(*Out);
break;
+ case GenAsmMatcher:
+ AsmMatcherEmitter(Records).run(*Out);
+ break;
case GenClangDiagsDefs:
ClangDiagsDefsEmitter(Records, ClangComponent).run(*Out);
break;
OpenPOWER on IntegriCloud