summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/utils/TableGen
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/utils/TableGen')
-rw-r--r--contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp9
-rw-r--r--contrib/llvm/utils/TableGen/ARMDecoderEmitter.h2
-rw-r--r--contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp4
-rw-r--r--contrib/llvm/utils/TableGen/CMakeLists.txt4
-rw-r--r--contrib/llvm/utils/TableGen/ClangASTNodesEmitter.cpp116
-rw-r--r--contrib/llvm/utils/TableGen/ClangASTNodesEmitter.h58
-rw-r--r--contrib/llvm/utils/TableGen/ClangAttrEmitter.cpp84
-rw-r--r--contrib/llvm/utils/TableGen/ClangAttrEmitter.h49
-rw-r--r--contrib/llvm/utils/TableGen/CodeEmitterGen.cpp45
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenInstruction.cpp11
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenTarget.cpp77
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp5
-rw-r--r--contrib/llvm/utils/TableGen/EDEmitter.cpp13
-rw-r--r--contrib/llvm/utils/TableGen/FastISelEmitter.cpp40
-rw-r--r--contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp5
-rw-r--r--contrib/llvm/utils/TableGen/NeonEmitter.cpp1202
-rw-r--r--contrib/llvm/utils/TableGen/NeonEmitter.h122
-rw-r--r--contrib/llvm/utils/TableGen/Record.cpp29
-rw-r--r--contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp134
-rw-r--r--contrib/llvm/utils/TableGen/TGParser.cpp165
-rw-r--r--contrib/llvm/utils/TableGen/TGParser.h11
-rw-r--r--contrib/llvm/utils/TableGen/TableGen.cpp115
-rw-r--r--contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp19
-rw-r--r--contrib/llvm/utils/TableGen/X86RecognizableInstr.h2
24 files changed, 2016 insertions, 305 deletions
diff --git a/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp b/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp
index c879a54..5025691 100644
--- a/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp
@@ -1575,6 +1575,15 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction(
if (Name == "BXr9" || Name == "BMOVPCRX" || Name == "BMOVPCRXr9")
return false;
+ // Tail calls are other patterns that generate existing instructions.
+ if (Name == "TCRETURNdi" || Name == "TCRETURNdiND" ||
+ Name == "TCRETURNri" || Name == "TCRETURNriND" ||
+ Name == "TAILJMPd" || Name == "TAILJMPdt" ||
+ Name == "TAILJMPdND" || Name == "TAILJMPdNDt" ||
+ Name == "TAILJMPr" || Name == "TAILJMPrND" ||
+ Name == "MOVr_TC")
+ return false;
+
// VLDMQ/VSTMQ can be hanlded with the more generic VLDMD/VSTMD.
if (Name == "VLDMQ" || Name == "VLDMQ_UPD" ||
Name == "VSTMQ" || Name == "VSTMQ_UPD")
diff --git a/contrib/llvm/utils/TableGen/ARMDecoderEmitter.h b/contrib/llvm/utils/TableGen/ARMDecoderEmitter.h
index 107e085..571a947 100644
--- a/contrib/llvm/utils/TableGen/ARMDecoderEmitter.h
+++ b/contrib/llvm/utils/TableGen/ARMDecoderEmitter.h
@@ -31,7 +31,7 @@ public:
~ARMDecoderEmitter() {
shutdownBackend();
}
-
+
// run - Output the code emitter
void run(raw_ostream &o);
diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index 4ba3df1..e1aa2bc 100644
--- a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -407,9 +407,9 @@ public:
default:
// This class preceeds the RHS if it is a proper subset of the RHS.
if (isSubsetOf(RHS))
- return true;
+ return true;
if (RHS.isSubsetOf(*this))
- return false;
+ return false;
// Otherwise, order by name to ensure we have a total ordering.
return ValueName < RHS.ValueName;
diff --git a/contrib/llvm/utils/TableGen/CMakeLists.txt b/contrib/llvm/utils/TableGen/CMakeLists.txt
index 731cde9..972989b 100644
--- a/contrib/llvm/utils/TableGen/CMakeLists.txt
+++ b/contrib/llvm/utils/TableGen/CMakeLists.txt
@@ -5,6 +5,7 @@ add_executable(tblgen
AsmWriterInst.cpp
CallingConvEmitter.cpp
ClangASTNodesEmitter.cpp
+ ClangAttrEmitter.cpp
ClangDiagnosticsEmitter.cpp
CodeEmitterGen.cpp
CodeGenDAGPatterns.cpp
@@ -22,6 +23,7 @@ add_executable(tblgen
InstrInfoEmitter.cpp
IntrinsicEmitter.cpp
LLVMCConfigurationEmitter.cpp
+ NeonEmitter.cpp
OptParserEmitter.cpp
Record.cpp
RegisterInfoEmitter.cpp
@@ -39,6 +41,6 @@ target_link_libraries(tblgen LLVMSupport LLVMSystem)
if( MINGW )
target_link_libraries(tblgen imagehlp psapi)
endif( MINGW )
-if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD )
+if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD AND NOT BEOS )
target_link_libraries(tblgen pthread)
endif()
diff --git a/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.cpp b/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.cpp
index 5d6423d..187ab46 100644
--- a/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.cpp
@@ -12,33 +12,19 @@
//===----------------------------------------------------------------------===//
#include "ClangASTNodesEmitter.h"
-#include "Record.h"
-#include <map>
-#include <cctype>
+#include <set>
using namespace llvm;
//===----------------------------------------------------------------------===//
// Statement Node Tables (.inc file) generation.
//===----------------------------------------------------------------------===//
-// Create a macro-ized version of a name
-static std::string macroName(std::string S) {
- for (unsigned i = 0; i < S.size(); ++i)
- S[i] = std::toupper(S[i]);
-
- return S;
-}
-
-// A map from a node to each of its derived nodes.
-typedef std::multimap<Record*, Record*> ChildMap;
-typedef ChildMap::const_iterator ChildIterator;
-
// Returns the first and last non-abstract subrecords
// Called recursively to ensure that nodes remain contiguous
-static std::pair<Record *, Record *> EmitStmtNode(const ChildMap &Tree,
- raw_ostream &OS,
- Record *Base,
- bool Root = true) {
+std::pair<Record *, Record *> ClangASTNodesEmitter::EmitNode(
+ const ChildMap &Tree,
+ raw_ostream &OS,
+ Record *Base) {
std::string BaseName = macroName(Base->getName());
ChildIterator i = Tree.lower_bound(Base), e = Tree.upper_bound(Base);
@@ -60,15 +46,15 @@ static std::pair<Record *, Record *> EmitStmtNode(const ChildMap &Tree,
OS << "#endif\n";
if (Abstract)
- OS << "ABSTRACT_STMT(" << NodeName << "(" << R->getName() << ", "
- << Base->getName() << "))\n";
+ OS << "ABSTRACT_" << macroName(Root.getName()) << "(" << NodeName << "("
+ << R->getName() << ", " << baseName(*Base) << "))\n";
else
OS << NodeName << "(" << R->getName() << ", "
- << Base->getName() << ")\n";
+ << baseName(*Base) << ")\n";
if (Tree.find(R) != Tree.end()) {
const std::pair<Record *, Record *> &Result
- = EmitStmtNode(Tree, OS, R, false);
+ = EmitNode(Tree, OS, R);
if (!First && Result.first)
First = Result.first;
if (Result.second)
@@ -87,11 +73,10 @@ static std::pair<Record *, Record *> EmitStmtNode(const ChildMap &Tree,
if (First) {
assert (Last && "Got a first node but not a last node for a range!");
- if (Root)
- OS << "LAST_STMT_RANGE(";
+ if (Base == &Root)
+ OS << "LAST_" << macroName(Root.getName()) << "_RANGE(";
else
- OS << "STMT_RANGE(";
-
+ OS << macroName(Root.getName()) << "_RANGE(";
OS << Base->getName() << ", " << First->getName() << ", "
<< Last->getName() << ")\n\n";
}
@@ -99,43 +84,82 @@ static std::pair<Record *, Record *> EmitStmtNode(const ChildMap &Tree,
return std::make_pair(First, Last);
}
-void ClangStmtNodesEmitter::run(raw_ostream &OS) {
+void ClangASTNodesEmitter::run(raw_ostream &OS) {
// Write the preamble
- OS << "#ifndef ABSTRACT_STMT\n";
- OS << "# define ABSTRACT_STMT(Stmt) Stmt\n";
+ OS << "#ifndef ABSTRACT_" << macroName(Root.getName()) << "\n";
+ OS << "# define ABSTRACT_" << macroName(Root.getName()) << "(Type) Type\n";
OS << "#endif\n";
- OS << "#ifndef STMT_RANGE\n";
- OS << "# define STMT_RANGE(Base, First, Last)\n";
+ OS << "#ifndef " << macroName(Root.getName()) << "_RANGE\n";
+ OS << "# define "
+ << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n";
OS << "#endif\n\n";
- OS << "#ifndef LAST_STMT_RANGE\n";
- OS << "# define LAST_STMT_RANGE(Base, First, Last) "
- "STMT_RANGE(Base, First, Last)\n";
+ OS << "#ifndef LAST_" << macroName(Root.getName()) << "_RANGE\n";
+ OS << "# define LAST_"
+ << macroName(Root.getName()) << "_RANGE(Base, First, Last) "
+ << macroName(Root.getName()) << "_RANGE(Base, First, Last)\n";
OS << "#endif\n\n";
// Emit statements
- const std::vector<Record*> Stmts = Records.getAllDerivedDefinitions("Stmt");
+ const std::vector<Record*> Stmts
+ = Records.getAllDerivedDefinitions(Root.getName());
ChildMap Tree;
- // Create a pseudo-record to serve as the Stmt node, which isn't actually
- // output.
- Record Stmt ("Stmt", SMLoc());
-
for (unsigned i = 0, e = Stmts.size(); i != e; ++i) {
Record *R = Stmts[i];
if (R->getValue("Base"))
Tree.insert(std::make_pair(R->getValueAsDef("Base"), R));
else
- Tree.insert(std::make_pair(&Stmt, R));
+ Tree.insert(std::make_pair(&Root, R));
}
- EmitStmtNode(Tree, OS, &Stmt);
+ EmitNode(Tree, OS, &Root);
+
+ OS << "#undef " << macroName(Root.getName()) << "\n";
+ OS << "#undef " << macroName(Root.getName()) << "_RANGE\n";
+ OS << "#undef LAST_" << macroName(Root.getName()) << "_RANGE\n";
+ OS << "#undef ABSTRACT_" << macroName(Root.getName()) << "\n";
+}
+
+void ClangDeclContextEmitter::run(raw_ostream &OS) {
+ // FIXME: Find a .td file format to allow for this to be represented better.
+
+ OS << "#ifndef DECL_CONTEXT\n";
+ OS << "# define DECL_CONTEXT(DECL)\n";
+ OS << "#endif\n";
+
+ OS << "#ifndef DECL_CONTEXT_BASE\n";
+ OS << "# define DECL_CONTEXT_BASE(DECL) DECL_CONTEXT(DECL)\n";
+ OS << "#endif\n";
+
+ typedef std::set<Record*> RecordSet;
+ typedef std::vector<Record*> RecordVector;
+
+ RecordVector DeclContextsVector
+ = Records.getAllDerivedDefinitions("DeclContext");
+ RecordVector Decls = Records.getAllDerivedDefinitions("Decl");
+ RecordSet DeclContexts (DeclContextsVector.begin(), DeclContextsVector.end());
+
+ for (RecordVector::iterator i = Decls.begin(), e = Decls.end(); i != e; ++i) {
+ Record *R = *i;
+
+ if (R->getValue("Base")) {
+ Record *B = R->getValueAsDef("Base");
+ if (DeclContexts.find(B) != DeclContexts.end()) {
+ OS << "DECL_CONTEXT_BASE(" << B->getName() << ")\n";
+ DeclContexts.erase(B);
+ }
+ }
+ }
+
+ for (RecordSet::iterator i = DeclContexts.begin(), e = DeclContexts.end();
+ i != e; ++i) {
+ OS << "DECL_CONTEXT(" << (*i)->getName() << ")\n";
+ }
- OS << "#undef STMT\n";
- OS << "#undef STMT_RANGE\n";
- OS << "#undef LAST_STMT_RANGE\n";
- OS << "#undef ABSTRACT_STMT\n";
+ OS << "#undef DECL_CONTEXT\n";
+ OS << "#undef DECL_CONTEXT_BASE\n";
}
diff --git a/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.h b/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.h
index c4ce9fa..abf9c9a 100644
--- a/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.h
+++ b/contrib/llvm/utils/TableGen/ClangASTNodesEmitter.h
@@ -15,19 +15,67 @@
#define CLANGAST_EMITTER_H
#include "TableGenBackend.h"
+#include "Record.h"
+#include <string>
+#include <cctype>
+#include <map>
namespace llvm {
-/// ClangStmtNodesEmitter - The top-level class emits .def files containing
+/// ClangASTNodesEmitter - The top-level class emits .inc files containing
/// declarations of Clang statements.
///
-class ClangStmtNodesEmitter : public TableGenBackend {
+class ClangASTNodesEmitter : public TableGenBackend {
+ // A map from a node to each of its derived nodes.
+ typedef std::multimap<Record*, Record*> ChildMap;
+ typedef ChildMap::const_iterator ChildIterator;
+
RecordKeeper &Records;
+ Record Root;
+ const std::string &BaseSuffix;
+
+ // Create a macro-ized version of a name
+ static std::string macroName(std::string S) {
+ for (unsigned i = 0; i < S.size(); ++i)
+ S[i] = std::toupper(S[i]);
+
+ return S;
+ }
+
+ // Return the name to be printed in the base field. Normally this is
+ // the record's name plus the base suffix, but if it is the root node and
+ // the suffix is non-empty, it's just the suffix.
+ std::string baseName(Record &R) {
+ if (&R == &Root && !BaseSuffix.empty())
+ return BaseSuffix;
+
+ return R.getName() + BaseSuffix;
+ }
+
+ std::pair<Record *, Record *> EmitNode (const ChildMap &Tree, raw_ostream& OS,
+ Record *Base);
+public:
+ explicit ClangASTNodesEmitter(RecordKeeper &R, const std::string &N,
+ const std::string &S)
+ : Records(R), Root(N, SMLoc()), BaseSuffix(S)
+ {}
+
+ // run - Output the .inc file contents
+ void run(raw_ostream &OS);
+};
+
+/// ClangDeclContextEmitter - Emits an addendum to a .inc file to enumerate the
+/// clang declaration contexts.
+///
+class ClangDeclContextEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+
public:
- explicit ClangStmtNodesEmitter(RecordKeeper &R)
- : Records(R) {}
+ explicit ClangDeclContextEmitter(RecordKeeper &R)
+ : Records(R)
+ {}
- // run - Output the .def file contents
+ // run - Output the .inc file contents
void run(raw_ostream &OS);
};
diff --git a/contrib/llvm/utils/TableGen/ClangAttrEmitter.cpp b/contrib/llvm/utils/TableGen/ClangAttrEmitter.cpp
new file mode 100644
index 0000000..fbdd2a7
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/ClangAttrEmitter.cpp
@@ -0,0 +1,84 @@
+//===- ClangAttrEmitter.cpp - Generate Clang attribute handling =-*- C++ -*--=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These tablegen backends emit Clang attribute processing code
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangAttrEmitter.h"
+#include "Record.h"
+#include <algorithm>
+
+using namespace llvm;
+
+void ClangAttrClassEmitter::run(raw_ostream &OS) {
+ OS << "// This file is generated by TableGen. Do not edit.\n\n";
+ OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
+ OS << "#define LLVM_CLANG_ATTR_CLASSES_INC\n\n";
+
+ std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+
+ for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
+ i != e; ++i) {
+ Record &R = **i;
+
+ if (R.getValueAsBit("DoNotEmit"))
+ continue;
+
+ OS << "class " << R.getName() << "Attr : public Attr {\n";
+
+ std::vector<Record*> Args = R.getValueAsListOfDefs("Args");
+
+ // FIXME: Handle arguments
+ assert(Args.empty() && "Can't yet handle arguments");
+
+ OS << "\n public:\n";
+ OS << " " << R.getName() << "Attr(";
+
+ // Arguments go here
+
+ OS << ")\n";
+ OS << " : Attr(attr::" << R.getName() << ")";
+
+ // Arguments go here
+
+ OS << " {}\n\n";
+
+ OS << " virtual Attr *clone (ASTContext &C) const;\n";
+ OS << " static bool classof(const Attr *A) { return A->getKind() == "
+ << "attr::" << R.getName() << "; }\n";
+ OS << " static bool classof(const " << R.getName()
+ << "Attr *) { return true; }\n";
+ OS << "};\n\n";
+ }
+
+ OS << "#endif\n";
+}
+
+void ClangAttrListEmitter::run(raw_ostream &OS) {
+ OS << "// This file is generated by TableGen. Do not edit.\n\n";
+
+ OS << "#ifndef LAST_ATTR\n";
+ OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n";
+ OS << "#endif\n\n";
+
+ std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+ std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end();
+
+ if (i != e) {
+ // Move the end iterator back to emit the last attribute.
+ for(--e; i != e; ++i)
+ OS << "ATTR(" << (*i)->getName() << ")\n";
+
+ OS << "LAST_ATTR(" << (*i)->getName() << ")\n\n";
+ }
+
+ OS << "#undef LAST_ATTR\n";
+ OS << "#undef ATTR\n";
+}
diff --git a/contrib/llvm/utils/TableGen/ClangAttrEmitter.h b/contrib/llvm/utils/TableGen/ClangAttrEmitter.h
new file mode 100644
index 0000000..5ce1c87
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/ClangAttrEmitter.h
@@ -0,0 +1,49 @@
+//===- ClangAttrEmitter.h - Generate Clang attribute handling =-*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These tablegen backends emit Clang attribute processing code
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANGATTR_EMITTER_H
+#define CLANGATTR_EMITTER_H
+
+#include "TableGenBackend.h"
+
+namespace llvm {
+
+/// ClangAttrClassEmitter - class emits the class defintions for attributes for
+/// clang.
+class ClangAttrClassEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+
+ public:
+ explicit ClangAttrClassEmitter(RecordKeeper &R)
+ : Records(R)
+ {}
+
+ void run(raw_ostream &OS);
+};
+
+/// ClangAttrListEmitter - class emits the enumeration list for attributes for
+/// clang.
+class ClangAttrListEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+
+ public:
+ explicit ClangAttrListEmitter(RecordKeeper &R)
+ : Records(R)
+ {}
+
+ void run(raw_ostream &OS);
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp
index 2a2a4ef..ec702c2a5 100644
--- a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp
+++ b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp
@@ -24,19 +24,8 @@ void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) {
for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
I != E; ++I) {
Record *R = *I;
- if (R->getName() == "PHI" ||
- R->getName() == "INLINEASM" ||
- R->getName() == "DBG_LABEL" ||
- R->getName() == "EH_LABEL" ||
- R->getName() == "GC_LABEL" ||
- R->getName() == "KILL" ||
- R->getName() == "EXTRACT_SUBREG" ||
- R->getName() == "INSERT_SUBREG" ||
- R->getName() == "IMPLICIT_DEF" ||
- R->getName() == "SUBREG_TO_REG" ||
- R->getName() == "COPY_TO_REGCLASS" ||
- R->getName() == "DBG_VALUE" ||
- R->getName() == "REG_SEQUENCE") continue;
+ if (R->getValueAsString("Namespace") == "TargetOpcode")
+ continue;
BitsInit *BI = R->getValueAsBitsInit("Inst");
@@ -103,19 +92,7 @@ void CodeEmitterGen::run(raw_ostream &o) {
const CodeGenInstruction *CGI = *IN;
Record *R = CGI->TheDef;
- if (R->getName() == "PHI" ||
- R->getName() == "INLINEASM" ||
- R->getName() == "DBG_LABEL" ||
- R->getName() == "EH_LABEL" ||
- R->getName() == "GC_LABEL" ||
- R->getName() == "KILL" ||
- R->getName() == "EXTRACT_SUBREG" ||
- R->getName() == "INSERT_SUBREG" ||
- R->getName() == "IMPLICIT_DEF" ||
- R->getName() == "SUBREG_TO_REG" ||
- R->getName() == "COPY_TO_REGCLASS" ||
- R->getName() == "DBG_VALUE" ||
- R->getName() == "REG_SEQUENCE") {
+ if (R->getValueAsString("Namespace") == "TargetOpcode") {
o << " 0U,\n";
continue;
}
@@ -140,22 +117,10 @@ void CodeEmitterGen::run(raw_ostream &o) {
for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end();
IC != EC; ++IC) {
Record *R = *IC;
+ if (R->getValueAsString("Namespace") == "TargetOpcode")
+ continue;
const std::string &InstName = R->getName();
std::string Case("");
-
- if (InstName == "PHI" ||
- InstName == "INLINEASM" ||
- InstName == "DBG_LABEL"||
- InstName == "EH_LABEL"||
- InstName == "GC_LABEL"||
- InstName == "KILL"||
- InstName == "EXTRACT_SUBREG" ||
- InstName == "INSERT_SUBREG" ||
- InstName == "IMPLICIT_DEF" ||
- InstName == "SUBREG_TO_REG" ||
- InstName == "COPY_TO_REGCLASS" ||
- InstName == "DBG_VALUE" ||
- InstName == "REG_SEQUENCE") continue;
BitsInit *BI = R->getValueAsBitsInit("Inst");
const std::vector<RecordVal> &Vals = R->getValues();
diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp
index 99d196c..35b54a5 100644
--- a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp
@@ -107,7 +107,6 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
canFoldAsLoad = R->getValueAsBit("canFoldAsLoad");
mayLoad = R->getValueAsBit("mayLoad");
mayStore = R->getValueAsBit("mayStore");
- bool isTwoAddress = R->getValueAsBit("isTwoAddress");
isPredicable = R->getValueAsBit("isPredicable");
isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress");
isCommutable = R->getValueAsBit("isCommutable");
@@ -212,16 +211,6 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
// Parse Constraints.
ParseConstraints(R->getValueAsString("Constraints"), this);
- // For backward compatibility: isTwoAddress means operand 1 is tied to
- // operand 0.
- if (isTwoAddress) {
- if (!OperandList[1].Constraints[0].isNone())
- throw R->getName() + ": cannot use isTwoAddress property: instruction "
- "already has constraint set!";
- OperandList[1].Constraints[0] =
- CodeGenInstruction::ConstraintInfo::getTied(0);
- }
-
// Parse the DisableEncoding field.
std::string DisableEncoding = R->getValueAsString("DisableEncoding");
while (1) {
diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp
index 3797992..d8130fb 100644
--- a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp
@@ -329,61 +329,42 @@ struct SortInstByName {
/// getInstructionsByEnumValue - Return all of the instructions defined by the
/// target, ordered by their enum value.
void CodeGenTarget::ComputeInstrsByEnum() const {
+ // The ordering here must match the ordering in TargetOpcodes.h.
+ const char *const FixedInstrs[] = {
+ "PHI",
+ "INLINEASM",
+ "DBG_LABEL",
+ "EH_LABEL",
+ "GC_LABEL",
+ "KILL",
+ "EXTRACT_SUBREG",
+ "INSERT_SUBREG",
+ "IMPLICIT_DEF",
+ "SUBREG_TO_REG",
+ "COPY_TO_REGCLASS",
+ "DBG_VALUE",
+ "REG_SEQUENCE",
+ "COPY",
+ 0
+ };
const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions();
- const CodeGenInstruction *PHI = GetInstByName("PHI", Insts);
- const CodeGenInstruction *INLINEASM = GetInstByName("INLINEASM", Insts);
- const CodeGenInstruction *DBG_LABEL = GetInstByName("DBG_LABEL", Insts);
- const CodeGenInstruction *EH_LABEL = GetInstByName("EH_LABEL", Insts);
- const CodeGenInstruction *GC_LABEL = GetInstByName("GC_LABEL", Insts);
- const CodeGenInstruction *KILL = GetInstByName("KILL", Insts);
- const CodeGenInstruction *EXTRACT_SUBREG =
- GetInstByName("EXTRACT_SUBREG", Insts);
- const CodeGenInstruction *INSERT_SUBREG =
- GetInstByName("INSERT_SUBREG", Insts);
- const CodeGenInstruction *IMPLICIT_DEF = GetInstByName("IMPLICIT_DEF", Insts);
- const CodeGenInstruction *SUBREG_TO_REG =
- GetInstByName("SUBREG_TO_REG", Insts);
- const CodeGenInstruction *COPY_TO_REGCLASS =
- GetInstByName("COPY_TO_REGCLASS", Insts);
- const CodeGenInstruction *DBG_VALUE = GetInstByName("DBG_VALUE", Insts);
- const CodeGenInstruction *REG_SEQUENCE = GetInstByName("REG_SEQUENCE", Insts);
-
- // Print out the rest of the instructions now.
- InstrsByEnum.push_back(PHI);
- InstrsByEnum.push_back(INLINEASM);
- InstrsByEnum.push_back(DBG_LABEL);
- InstrsByEnum.push_back(EH_LABEL);
- InstrsByEnum.push_back(GC_LABEL);
- InstrsByEnum.push_back(KILL);
- InstrsByEnum.push_back(EXTRACT_SUBREG);
- InstrsByEnum.push_back(INSERT_SUBREG);
- InstrsByEnum.push_back(IMPLICIT_DEF);
- InstrsByEnum.push_back(SUBREG_TO_REG);
- InstrsByEnum.push_back(COPY_TO_REGCLASS);
- InstrsByEnum.push_back(DBG_VALUE);
- InstrsByEnum.push_back(REG_SEQUENCE);
-
+ for (const char *const *p = FixedInstrs; *p; ++p) {
+ const CodeGenInstruction *Instr = GetInstByName(*p, Insts);
+ assert(Instr && "Missing target independent instruction");
+ assert(Instr->Namespace == "TargetOpcode" && "Bad namespace");
+ InstrsByEnum.push_back(Instr);
+ }
unsigned EndOfPredefines = InstrsByEnum.size();
-
+
for (DenseMap<const Record*, CodeGenInstruction*>::const_iterator
I = Insts.begin(), E = Insts.end(); I != E; ++I) {
const CodeGenInstruction *CGI = I->second;
- if (CGI != PHI &&
- CGI != INLINEASM &&
- CGI != DBG_LABEL &&
- CGI != EH_LABEL &&
- CGI != GC_LABEL &&
- CGI != KILL &&
- CGI != EXTRACT_SUBREG &&
- CGI != INSERT_SUBREG &&
- CGI != IMPLICIT_DEF &&
- CGI != SUBREG_TO_REG &&
- CGI != COPY_TO_REGCLASS &&
- CGI != DBG_VALUE &&
- CGI != REG_SEQUENCE)
+ if (CGI->Namespace != "TargetOpcode")
InstrsByEnum.push_back(CGI);
}
-
+
+ assert(InstrsByEnum.size() == Insts.size() && "Missing predefined instr");
+
// All of the instructions are now in random order based on the map iteration.
// Sort them by name.
std::sort(InstrsByEnum.begin()+EndOfPredefines, InstrsByEnum.end(),
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
index 4473f0d..3750bd8 100644
--- a/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -635,6 +635,7 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) {
if (!ComplexPatterns.empty()) {
OS << "bool CheckComplexPattern(SDNode *Root, SDValue N,\n";
OS << " unsigned PatternNo, SmallVectorImpl<SDValue> &Result) {\n";
+ OS << " unsigned NextRes = Result.size();\n";
OS << " switch (PatternNo) {\n";
OS << " default: assert(0 && \"Invalid pattern # in table?\");\n";
for (unsigned i = 0, e = ComplexPatterns.size(); i != e; ++i) {
@@ -645,12 +646,12 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) {
++NumOps; // Get the chained node too.
OS << " case " << i << ":\n";
- OS << " Result.resize(Result.size()+" << NumOps << ");\n";
+ OS << " Result.resize(NextRes+" << NumOps << ");\n";
OS << " return " << P.getSelectFunc();
OS << "(Root, N";
for (unsigned i = 0; i != NumOps; ++i)
- OS << ", Result[Result.size()-" << (NumOps-i) << ']';
+ OS << ", Result[NextRes+" << i << ']';
OS << ");\n";
}
OS << " }\n";
diff --git a/contrib/llvm/utils/TableGen/EDEmitter.cpp b/contrib/llvm/utils/TableGen/EDEmitter.cpp
index 0d5ee40..c5ee828 100644
--- a/contrib/llvm/utils/TableGen/EDEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/EDEmitter.cpp
@@ -306,6 +306,7 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type,
REG("RFP64");
REG("RFP80");
REG("VR128");
+ REG("VR256");
REG("RST");
REG("SEGMENT_REG");
REG("DEBUG_REG");
@@ -339,6 +340,7 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type,
MEM("opaque80mem");
MEM("i128mem");
MEM("f128mem");
+ MEM("f256mem");
MEM("opaque512mem");
// all R, I, R, I
@@ -347,6 +349,7 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type,
LEA("lea64mem");
// all I
+ PCR("i16imm_pcrel");
PCR("i32imm_pcrel");
PCR("i64i32imm_pcrel");
PCR("brtarget8");
@@ -500,6 +503,8 @@ static void X86ExtractSemantics(
// TODO add support for fixed operands
} else if (name.find("F") != name.npos) {
// ignore (this pushes onto the FP stack)
+ } else if (name.find("A") != name.npos) {
+ // ignore (pushes all GP registoers onto the stack)
} else if (name[name.length() - 1] == 'm') {
PUSH("src");
} else if (name.find("i") != name.npos) {
@@ -518,6 +523,8 @@ static void X86ExtractSemantics(
// TODO add support for fixed operands
} else if (name.find("F") != name.npos) {
// ignore (this pops from the FP stack)
+ } else if (name.find("A") != name.npos) {
+ // ignore (pushes all GP registoers onto the stack)
} else if (name[name.length() - 1] == 'm') {
POP("dst");
} else {
@@ -570,6 +577,7 @@ static void X86ExtractSemantics(
static int ARMFlagFromOpName(LiteralConstantEmitter *type,
const std::string &name) {
REG("GPR");
+ REG("tcGPR");
REG("cc_out");
REG("s_cc_out");
REG("tGPR");
@@ -592,10 +600,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
IMM("msr_mask");
IMM("neg_zero");
IMM("imm0_31");
- IMM("h8imm");
- IMM("h16imm");
- IMM("h32imm");
- IMM("h64imm");
+ IMM("nModImm");
IMM("imm0_4095");
IMM("jt2block_operand");
IMM("t_imm_s4");
diff --git a/contrib/llvm/utils/TableGen/FastISelEmitter.cpp b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp
index 9ec9e08..08fc139 100644
--- a/contrib/llvm/utils/TableGen/FastISelEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp
@@ -54,15 +54,15 @@ struct OperandsSignature {
bool initialize(TreePatternNode *InstPatNode,
const CodeGenTarget &Target,
MVT::SimpleValueType VT) {
- if (!InstPatNode->isLeaf() &&
- InstPatNode->getOperator()->getName() == "imm") {
- Operands.push_back("i");
- return true;
- }
- if (!InstPatNode->isLeaf() &&
- InstPatNode->getOperator()->getName() == "fpimm") {
- Operands.push_back("f");
- return true;
+ if (!InstPatNode->isLeaf()) {
+ if (InstPatNode->getOperator()->getName() == "imm") {
+ Operands.push_back("i");
+ return true;
+ }
+ if (InstPatNode->getOperator()->getName() == "fpimm") {
+ Operands.push_back("f");
+ return true;
+ }
}
const CodeGenRegisterClass *DstRC = 0;
@@ -432,11 +432,9 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) {
for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) {
if ((*Memo.PhysRegs)[i] != "")
- OS << " TII.copyRegToReg(*MBB, MBB->end(), "
- << (*Memo.PhysRegs)[i] << ", Op" << i << ", "
- << "TM.getRegisterInfo()->getPhysicalRegisterRegClass("
- << (*Memo.PhysRegs)[i] << "), "
- << "MRI.getRegClass(Op" << i << "), DL);\n";
+ OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, "
+ << "TII.get(TargetOpcode::COPY), "
+ << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n";
}
OS << " return FastEmitInst_";
@@ -524,14 +522,12 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) {
HasPred = true;
}
- for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) {
- if ((*Memo.PhysRegs)[i] != "")
- OS << " TII.copyRegToReg(*MBB, MBB->end(), "
- << (*Memo.PhysRegs)[i] << ", Op" << i << ", "
- << "TM.getRegisterInfo()->getPhysicalRegisterRegClass("
- << (*Memo.PhysRegs)[i] << "), "
- << "MRI.getRegClass(Op" << i << "), DL);\n";
- }
+ for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) {
+ if ((*Memo.PhysRegs)[i] != "")
+ OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, "
+ << "TII.get(TargetOpcode::COPY), "
+ << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n";
+ }
OS << " return FastEmitInst_";
diff --git a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp
index 006a2a1..f28af15 100644
--- a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp
@@ -92,7 +92,8 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
else if (OpR->isSubClassOf("PointerLikeRegClass"))
Res += utostr(OpR->getValueAsInt("RegClassKind")) + ", ";
else
- Res += "0, ";
+ // -1 means the operand does not have a fixed register class.
+ Res += "-1, ";
// Fill in applicable flags.
Res += "0";
@@ -301,7 +302,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
}
OS << ", 0x";
OS.write_hex(Value);
- OS << ", ";
+ OS << "ULL, ";
// Emit the implicit uses and defs lists...
std::vector<Record*> UseList = Inst.TheDef->getValueAsListOfDefs("Uses");
diff --git a/contrib/llvm/utils/TableGen/NeonEmitter.cpp b/contrib/llvm/utils/TableGen/NeonEmitter.cpp
new file mode 100644
index 0000000..3516d31
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/NeonEmitter.cpp
@@ -0,0 +1,1202 @@
+//===- NeonEmitter.cpp - Generate arm_neon.h for use with clang -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting arm_neon.h, which includes
+// a declaration and definition of each function specified by the ARM NEON
+// compiler interface. See ARM document DUI0348B.
+//
+// Each NEON instruction is implemented in terms of 1 or more functions which
+// are suffixed with the element type of the input vectors. Functions may be
+// implemented in terms of generic vector operations such as +, *, -, etc. or
+// by calling a __builtin_-prefixed function which will be handled by clang's
+// CodeGen library.
+//
+// Additional validation code can be generated by this file when runHeader() is
+// called, rather than the normal run() entry point.
+//
+//===----------------------------------------------------------------------===//
+
+#include "NeonEmitter.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include <string>
+
+using namespace llvm;
+
+/// ParseTypes - break down a string such as "fQf" into a vector of StringRefs,
+/// which each StringRef representing a single type declared in the string.
+/// for "fQf" we would end up with 2 StringRefs, "f", and "Qf", representing
+/// 2xfloat and 4xfloat respectively.
+static void ParseTypes(Record *r, std::string &s,
+ SmallVectorImpl<StringRef> &TV) {
+ const char *data = s.data();
+ int len = 0;
+
+ for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) {
+ if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U')
+ continue;
+
+ switch (data[len]) {
+ case 'c':
+ case 's':
+ case 'i':
+ case 'l':
+ case 'h':
+ case 'f':
+ break;
+ default:
+ throw TGError(r->getLoc(),
+ "Unexpected letter: " + std::string(data + len, 1));
+ break;
+ }
+ TV.push_back(StringRef(data, len + 1));
+ data += len + 1;
+ len = -1;
+ }
+}
+
+/// Widen - Convert a type code into the next wider type. char -> short,
+/// short -> int, etc.
+static char Widen(const char t) {
+ switch (t) {
+ case 'c':
+ return 's';
+ case 's':
+ return 'i';
+ case 'i':
+ return 'l';
+ default: throw "unhandled type in widen!";
+ }
+ return '\0';
+}
+
+/// Narrow - Convert a type code into the next smaller type. short -> char,
+/// float -> half float, etc.
+static char Narrow(const char t) {
+ switch (t) {
+ case 's':
+ return 'c';
+ case 'i':
+ return 's';
+ case 'l':
+ return 'i';
+ case 'f':
+ return 'h';
+ default: throw "unhandled type in widen!";
+ }
+ return '\0';
+}
+
+/// For a particular StringRef, return the base type code, and whether it has
+/// the quad-vector, polynomial, or unsigned modifiers set.
+static char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) {
+ unsigned off = 0;
+
+ // remember quad.
+ if (ty[off] == 'Q') {
+ quad = true;
+ ++off;
+ }
+
+ // remember poly.
+ if (ty[off] == 'P') {
+ poly = true;
+ ++off;
+ }
+
+ // remember unsigned.
+ if (ty[off] == 'U') {
+ usgn = true;
+ ++off;
+ }
+
+ // base type to get the type string for.
+ return ty[off];
+}
+
+/// ModType - Transform a type code and its modifiers based on a mod code. The
+/// mod code definitions may be found at the top of arm_neon.td.
+static char ModType(const char mod, char type, bool &quad, bool &poly,
+ bool &usgn, bool &scal, bool &cnst, bool &pntr) {
+ switch (mod) {
+ case 't':
+ if (poly) {
+ poly = false;
+ usgn = true;
+ }
+ break;
+ case 'u':
+ usgn = true;
+ case 'x':
+ poly = false;
+ if (type == 'f')
+ type = 'i';
+ break;
+ case 'f':
+ if (type == 'h')
+ quad = true;
+ type = 'f';
+ usgn = false;
+ break;
+ case 'w':
+ type = Widen(type);
+ quad = true;
+ break;
+ case 'n':
+ type = Widen(type);
+ break;
+ case 'l':
+ type = 'l';
+ scal = true;
+ usgn = true;
+ break;
+ case 's':
+ case 'a':
+ scal = true;
+ break;
+ case 'k':
+ quad = true;
+ break;
+ case 'c':
+ cnst = true;
+ case 'p':
+ pntr = true;
+ scal = true;
+ break;
+ case 'h':
+ type = Narrow(type);
+ if (type == 'h')
+ quad = false;
+ break;
+ case 'e':
+ type = Narrow(type);
+ usgn = true;
+ break;
+ default:
+ break;
+ }
+ return type;
+}
+
+/// TypeString - for a modifier and type, generate the name of the typedef for
+/// that type. If generic is true, emit the generic vector type rather than
+/// the public NEON type. QUc -> uint8x8_t / __neon_uint8x8_t.
+static std::string TypeString(const char mod, StringRef typestr,
+ bool generic = false) {
+ bool quad = false;
+ bool poly = false;
+ bool usgn = false;
+ bool scal = false;
+ bool cnst = false;
+ bool pntr = false;
+
+ if (mod == 'v')
+ return "void";
+ if (mod == 'i')
+ return "int";
+
+ // base type to get the type string for.
+ char type = ClassifyType(typestr, quad, poly, usgn);
+
+ // Based on the modifying character, change the type and width if necessary.
+ type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
+
+ SmallString<128> s;
+
+ if (generic)
+ s += "__neon_";
+
+ if (usgn)
+ s.push_back('u');
+
+ switch (type) {
+ case 'c':
+ s += poly ? "poly8" : "int8";
+ if (scal)
+ break;
+ s += quad ? "x16" : "x8";
+ break;
+ case 's':
+ s += poly ? "poly16" : "int16";
+ if (scal)
+ break;
+ s += quad ? "x8" : "x4";
+ break;
+ case 'i':
+ s += "int32";
+ if (scal)
+ break;
+ s += quad ? "x4" : "x2";
+ break;
+ case 'l':
+ s += "int64";
+ if (scal)
+ break;
+ s += quad ? "x2" : "x1";
+ break;
+ case 'h':
+ s += "float16";
+ if (scal)
+ break;
+ s += quad ? "x8" : "x4";
+ break;
+ case 'f':
+ s += "float32";
+ if (scal)
+ break;
+ s += quad ? "x4" : "x2";
+ break;
+ default:
+ throw "unhandled type!";
+ break;
+ }
+
+ if (mod == '2')
+ s += "x2";
+ if (mod == '3')
+ s += "x3";
+ if (mod == '4')
+ s += "x4";
+
+ // Append _t, finishing the type string typedef type.
+ s += "_t";
+
+ if (cnst)
+ s += " const";
+
+ if (pntr)
+ s += " *";
+
+ return s.str();
+}
+
+/// BuiltinTypeString - for a modifier and type, generate the clang
+/// BuiltinsARM.def prototype code for the function. See the top of clang's
+/// Builtins.def for a description of the type strings.
+static std::string BuiltinTypeString(const char mod, StringRef typestr,
+ ClassKind ck, bool ret) {
+ bool quad = false;
+ bool poly = false;
+ bool usgn = false;
+ bool scal = false;
+ bool cnst = false;
+ bool pntr = false;
+
+ if (mod == 'v')
+ return "v";
+ if (mod == 'i')
+ return "i";
+
+ // base type to get the type string for.
+ char type = ClassifyType(typestr, quad, poly, usgn);
+
+ // Based on the modifying character, change the type and width if necessary.
+ type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
+
+ if (pntr) {
+ usgn = false;
+ poly = false;
+ type = 'v';
+ }
+ if (type == 'h') {
+ type = 's';
+ usgn = true;
+ }
+ usgn = usgn | poly | ((ck == ClassI || ck == ClassW) && scal && type != 'f');
+
+ if (scal) {
+ SmallString<128> s;
+
+ if (usgn)
+ s.push_back('U');
+
+ if (type == 'l')
+ s += "LLi";
+ else
+ s.push_back(type);
+
+ if (cnst)
+ s.push_back('C');
+ if (pntr)
+ s.push_back('*');
+ return s.str();
+ }
+
+ // Since the return value must be one type, return a vector type of the
+ // appropriate width which we will bitcast. An exception is made for
+ // returning structs of 2, 3, or 4 vectors which are returned in a sret-like
+ // fashion, storing them to a pointer arg.
+ if (ret) {
+ if (mod == '2' || mod == '3' || mod == '4')
+ return "vv*";
+ if (mod == 'f' || (ck != ClassB && type == 'f'))
+ return quad ? "V4f" : "V2f";
+ if (ck != ClassB && type == 's')
+ return quad ? "V8s" : "V4s";
+ if (ck != ClassB && type == 'i')
+ return quad ? "V4i" : "V2i";
+ if (ck != ClassB && type == 'l')
+ return quad ? "V2LLi" : "V1LLi";
+
+ return quad ? "V16c" : "V8c";
+ }
+
+ // Non-return array types are passed as individual vectors.
+ if (mod == '2')
+ return quad ? "V16cV16c" : "V8cV8c";
+ if (mod == '3')
+ return quad ? "V16cV16cV16c" : "V8cV8cV8c";
+ if (mod == '4')
+ return quad ? "V16cV16cV16cV16c" : "V8cV8cV8cV8c";
+
+ if (mod == 'f' || (ck != ClassB && type == 'f'))
+ return quad ? "V4f" : "V2f";
+ if (ck != ClassB && type == 's')
+ return quad ? "V8s" : "V4s";
+ if (ck != ClassB && type == 'i')
+ return quad ? "V4i" : "V2i";
+ if (ck != ClassB && type == 'l')
+ return quad ? "V2LLi" : "V1LLi";
+
+ return quad ? "V16c" : "V8c";
+}
+
+/// StructTag - generate the name of the struct tag for a type.
+/// These names are mandated by ARM's ABI.
+static std::string StructTag(StringRef typestr) {
+ bool quad = false;
+ bool poly = false;
+ bool usgn = false;
+
+ // base type to get the type string for.
+ char type = ClassifyType(typestr, quad, poly, usgn);
+
+ SmallString<128> s;
+ s += "__simd";
+ s += quad ? "128_" : "64_";
+ if (usgn)
+ s.push_back('u');
+
+ switch (type) {
+ case 'c':
+ s += poly ? "poly8" : "int8";
+ break;
+ case 's':
+ s += poly ? "poly16" : "int16";
+ break;
+ case 'i':
+ s += "int32";
+ break;
+ case 'l':
+ s += "int64";
+ break;
+ case 'h':
+ s += "float16";
+ break;
+ case 'f':
+ s += "float32";
+ break;
+ default:
+ throw "unhandled type!";
+ break;
+ }
+
+ // Append _t, finishing the struct tag name.
+ s += "_t";
+
+ return s.str();
+}
+
+/// MangleName - Append a type or width suffix to a base neon function name,
+/// and insert a 'q' in the appropriate location if the operation works on
+/// 128b rather than 64b. E.g. turn "vst2_lane" into "vst2q_lane_f32", etc.
+static std::string MangleName(const std::string &name, StringRef typestr,
+ ClassKind ck) {
+ if (name == "vcvt_f32_f16")
+ return name;
+
+ bool quad = false;
+ bool poly = false;
+ bool usgn = false;
+ char type = ClassifyType(typestr, quad, poly, usgn);
+
+ std::string s = name;
+
+ switch (type) {
+ case 'c':
+ switch (ck) {
+ case ClassS: s += poly ? "_p8" : usgn ? "_u8" : "_s8"; break;
+ case ClassI: s += "_i8"; break;
+ case ClassW: s += "_8"; break;
+ default: break;
+ }
+ break;
+ case 's':
+ switch (ck) {
+ case ClassS: s += poly ? "_p16" : usgn ? "_u16" : "_s16"; break;
+ case ClassI: s += "_i16"; break;
+ case ClassW: s += "_16"; break;
+ default: break;
+ }
+ break;
+ case 'i':
+ switch (ck) {
+ case ClassS: s += usgn ? "_u32" : "_s32"; break;
+ case ClassI: s += "_i32"; break;
+ case ClassW: s += "_32"; break;
+ default: break;
+ }
+ break;
+ case 'l':
+ switch (ck) {
+ case ClassS: s += usgn ? "_u64" : "_s64"; break;
+ case ClassI: s += "_i64"; break;
+ case ClassW: s += "_64"; break;
+ default: break;
+ }
+ break;
+ case 'h':
+ switch (ck) {
+ case ClassS:
+ case ClassI: s += "_f16"; break;
+ case ClassW: s += "_16"; break;
+ default: break;
+ }
+ break;
+ case 'f':
+ switch (ck) {
+ case ClassS:
+ case ClassI: s += "_f32"; break;
+ case ClassW: s += "_32"; break;
+ default: break;
+ }
+ break;
+ default:
+ throw "unhandled type!";
+ break;
+ }
+ if (ck == ClassB)
+ s += "_v";
+
+ // Insert a 'q' before the first '_' character so that it ends up before
+ // _lane or _n on vector-scalar operations.
+ if (quad) {
+ size_t pos = s.find('_');
+ s = s.insert(pos, "q");
+ }
+ return s;
+}
+
+// Generate the string "(argtype a, argtype b, ...)"
+static std::string GenArgs(const std::string &proto, StringRef typestr) {
+ bool define = proto.find('i') != std::string::npos;
+ char arg = 'a';
+
+ std::string s;
+ s += "(";
+
+ for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
+ if (!define) {
+ s += TypeString(proto[i], typestr);
+ s.push_back(' ');
+ }
+ s.push_back(arg);
+ if ((i + 1) < e)
+ s += ", ";
+ }
+
+ s += ")";
+ return s;
+}
+
+static std::string Duplicate(unsigned nElts, StringRef typestr,
+ const std::string &a) {
+ std::string s;
+
+ s = "(__neon_" + TypeString('d', typestr) + "){ ";
+ for (unsigned i = 0; i != nElts; ++i) {
+ s += a;
+ if ((i + 1) < nElts)
+ s += ", ";
+ }
+ s += " }";
+
+ return s;
+}
+
+// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd.
+// If structTypes is true, the NEON types are structs of vector types rather
+// than vector types, and the call becomes "a.val + b.val"
+static std::string GenOpString(OpKind op, const std::string &proto,
+ StringRef typestr, bool structTypes = true) {
+ bool dummy, quad = false;
+ char type = ClassifyType(typestr, quad, dummy, dummy);
+ unsigned nElts = 0;
+ switch (type) {
+ case 'c': nElts = 8; break;
+ case 's': nElts = 4; break;
+ case 'i': nElts = 2; break;
+ case 'l': nElts = 1; break;
+ case 'h': nElts = 4; break;
+ case 'f': nElts = 2; break;
+ }
+
+ std::string ts = TypeString(proto[0], typestr);
+ std::string s = ts + " r; r";
+
+ if (structTypes)
+ s += ".val";
+
+ s += " = ";
+
+ std::string a, b, c;
+ if (proto.size() > 1)
+ a = (structTypes && proto[1] != 'l' && proto[1] != 's') ? "a.val" : "a";
+ b = structTypes ? "b.val" : "b";
+ c = structTypes ? "c.val" : "c";
+
+ switch(op) {
+ case OpAdd:
+ s += a + " + " + b;
+ break;
+ case OpSub:
+ s += a + " - " + b;
+ break;
+ case OpMulN:
+ b = Duplicate(nElts << (int)quad, typestr, "b");
+ case OpMul:
+ s += a + " * " + b;
+ break;
+ case OpMlaN:
+ c = Duplicate(nElts << (int)quad, typestr, "c");
+ case OpMla:
+ s += a + " + ( " + b + " * " + c + " )";
+ break;
+ case OpMlsN:
+ c = Duplicate(nElts << (int)quad, typestr, "c");
+ case OpMls:
+ s += a + " - ( " + b + " * " + c + " )";
+ break;
+ case OpEq:
+ s += "(__neon_" + ts + ")(" + a + " == " + b + ")";
+ break;
+ case OpGe:
+ s += "(__neon_" + ts + ")(" + a + " >= " + b + ")";
+ break;
+ case OpLe:
+ s += "(__neon_" + ts + ")(" + a + " <= " + b + ")";
+ break;
+ case OpGt:
+ s += "(__neon_" + ts + ")(" + a + " > " + b + ")";
+ break;
+ case OpLt:
+ s += "(__neon_" + ts + ")(" + a + " < " + b + ")";
+ break;
+ case OpNeg:
+ s += " -" + a;
+ break;
+ case OpNot:
+ s += " ~" + a;
+ break;
+ case OpAnd:
+ s += a + " & " + b;
+ break;
+ case OpOr:
+ s += a + " | " + b;
+ break;
+ case OpXor:
+ s += a + " ^ " + b;
+ break;
+ case OpAndNot:
+ s += a + " & ~" + b;
+ break;
+ case OpOrNot:
+ s += a + " | ~" + b;
+ break;
+ case OpCast:
+ s += "(__neon_" + ts + ")" + a;
+ break;
+ case OpConcat:
+ s += "__builtin_shufflevector((__neon_int64x1_t)" + a;
+ s += ", (__neon_int64x1_t)" + b + ", 0, 1)";
+ break;
+ case OpHi:
+ s += "(__neon_int64x1_t)(((__neon_int64x2_t)" + a + ")[1])";
+ break;
+ case OpLo:
+ s += "(__neon_int64x1_t)(((__neon_int64x2_t)" + a + ")[0])";
+ break;
+ case OpDup:
+ s += Duplicate(nElts << (int)quad, typestr, a);
+ break;
+ case OpSelect:
+ // ((0 & 1) | (~0 & 2))
+ ts = TypeString(proto[1], typestr);
+ s += "( " + a + " & (__neon_" + ts + ")" + b + ") | ";
+ s += "(~" + a + " & (__neon_" + ts + ")" + c + ")";
+ break;
+ case OpRev16:
+ s += "__builtin_shufflevector(" + a + ", " + a;
+ for (unsigned i = 2; i <= nElts << (int)quad; i += 2)
+ for (unsigned j = 0; j != 2; ++j)
+ s += ", " + utostr(i - j - 1);
+ s += ")";
+ break;
+ case OpRev32:
+ nElts >>= 1;
+ s += "__builtin_shufflevector(" + a + ", " + a;
+ for (unsigned i = nElts; i <= nElts << (1 + (int)quad); i += nElts)
+ for (unsigned j = 0; j != nElts; ++j)
+ s += ", " + utostr(i - j - 1);
+ s += ")";
+ break;
+ case OpRev64:
+ s += "__builtin_shufflevector(" + a + ", " + a;
+ for (unsigned i = nElts; i <= nElts << (int)quad; i += nElts)
+ for (unsigned j = 0; j != nElts; ++j)
+ s += ", " + utostr(i - j - 1);
+ s += ")";
+ break;
+ default:
+ throw "unknown OpKind!";
+ break;
+ }
+ s += "; return r;";
+ return s;
+}
+
+static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) {
+ unsigned mod = proto[0];
+ unsigned ret = 0;
+
+ if (mod == 'v' || mod == 'f')
+ mod = proto[1];
+
+ bool quad = false;
+ bool poly = false;
+ bool usgn = false;
+ bool scal = false;
+ bool cnst = false;
+ bool pntr = false;
+
+ // base type to get the type string for.
+ char type = ClassifyType(typestr, quad, poly, usgn);
+
+ // Based on the modifying character, change the type and width if necessary.
+ type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr);
+
+ if (usgn)
+ ret |= 0x08;
+ if (quad)
+ ret |= 0x10;
+
+ switch (type) {
+ case 'c':
+ ret |= poly ? 5 : 0;
+ break;
+ case 's':
+ ret |= poly ? 6 : 1;
+ break;
+ case 'i':
+ ret |= 2;
+ break;
+ case 'l':
+ ret |= 3;
+ break;
+ case 'h':
+ ret |= 7;
+ break;
+ case 'f':
+ ret |= 4;
+ break;
+ default:
+ throw "unhandled type!";
+ break;
+ }
+ return ret;
+}
+
+// Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a)
+// If structTypes is true, the NEON types are structs of vector types rather
+// than vector types, and the call becomes __builtin_neon_cls(a.val)
+static std::string GenBuiltin(const std::string &name, const std::string &proto,
+ StringRef typestr, ClassKind ck,
+ bool structTypes = true) {
+ bool dummy, quad = false;
+ char type = ClassifyType(typestr, quad, dummy, dummy);
+ unsigned nElts = 0;
+ switch (type) {
+ case 'c': nElts = 8; break;
+ case 's': nElts = 4; break;
+ case 'i': nElts = 2; break;
+ case 'l': nElts = 1; break;
+ case 'h': nElts = 4; break;
+ case 'f': nElts = 2; break;
+ }
+ if (quad) nElts <<= 1;
+
+ char arg = 'a';
+ std::string s;
+
+ // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit
+ // sret-like argument.
+ bool sret = (proto[0] == '2' || proto[0] == '3' || proto[0] == '4');
+
+ // If this builtin takes an immediate argument, we need to #define it rather
+ // than use a standard declaration, so that SemaChecking can range check
+ // the immediate passed by the user.
+ bool define = proto.find('i') != std::string::npos;
+
+ // If all types are the same size, bitcasting the args will take care
+ // of arg checking. The actual signedness etc. will be taken care of with
+ // special enums.
+ if (proto.find('s') == std::string::npos)
+ ck = ClassB;
+
+ if (proto[0] != 'v') {
+ std::string ts = TypeString(proto[0], typestr);
+
+ if (define) {
+ if (sret)
+ s += "({ " + ts + " r; ";
+ else if (proto[0] != 's')
+ s += "(" + ts + "){(__neon_" + ts + ")";
+ } else if (sret) {
+ s += ts + " r; ";
+ } else {
+ s += ts + " r; r";
+ if (structTypes && proto[0] != 's' && proto[0] != 'i' && proto[0] != 'l')
+ s += ".val";
+
+ s += " = ";
+ }
+ }
+
+ bool splat = proto.find('a') != std::string::npos;
+
+ s += "__builtin_neon_";
+ if (splat) {
+ std::string vname(name, 0, name.size()-2);
+ s += MangleName(vname, typestr, ck);
+ } else {
+ s += MangleName(name, typestr, ck);
+ }
+ s += "(";
+
+ // Pass the address of the return variable as the first argument to sret-like
+ // builtins.
+ if (sret)
+ s += "&r, ";
+
+ for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) {
+ std::string args = std::string(&arg, 1);
+ if (define)
+ args = "(" + args + ")";
+
+ // Handle multiple-vector values specially, emitting each subvector as an
+ // argument to the __builtin.
+ if (structTypes && (proto[i] == '2' || proto[i] == '3' || proto[i] == '4')){
+ for (unsigned vi = 0, ve = proto[i] - '0'; vi != ve; ++vi) {
+ s += args + ".val[" + utostr(vi) + "].val";
+ if ((vi + 1) < ve)
+ s += ", ";
+ }
+ if ((i + 1) < e)
+ s += ", ";
+
+ continue;
+ }
+
+ if (splat && (i + 1) == e)
+ s += Duplicate(nElts, typestr, args);
+ else
+ s += args;
+
+ if (structTypes && proto[i] != 's' && proto[i] != 'i' && proto[i] != 'l' &&
+ proto[i] != 'p' && proto[i] != 'c' && proto[i] != 'a') {
+ s += ".val";
+ }
+ if ((i + 1) < e)
+ s += ", ";
+ }
+
+ // Extra constant integer to hold type class enum for this function, e.g. s8
+ if (ck == ClassB)
+ s += ", " + utostr(GetNeonEnum(proto, typestr));
+
+ if (define)
+ s += ")";
+ else
+ s += ");";
+
+ if (proto[0] != 'v') {
+ if (define) {
+ if (sret)
+ s += "; r; })";
+ else if (proto[0] != 's')
+ s += "}";
+ } else {
+ s += " return r;";
+ }
+ }
+ return s;
+}
+
+static std::string GenBuiltinDef(const std::string &name,
+ const std::string &proto,
+ StringRef typestr, ClassKind ck) {
+ std::string s("BUILTIN(__builtin_neon_");
+
+ // If all types are the same size, bitcasting the args will take care
+ // of arg checking. The actual signedness etc. will be taken care of with
+ // special enums.
+ if (proto.find('s') == std::string::npos)
+ ck = ClassB;
+
+ s += MangleName(name, typestr, ck);
+ s += ", \"";
+
+ for (unsigned i = 0, e = proto.size(); i != e; ++i)
+ s += BuiltinTypeString(proto[i], typestr, ck, i == 0);
+
+ // Extra constant integer to hold type class enum for this function, e.g. s8
+ if (ck == ClassB)
+ s += "i";
+
+ s += "\", \"n\")";
+ return s;
+}
+
+/// run - Read the records in arm_neon.td and output arm_neon.h. arm_neon.h
+/// is comprised of type definitions and function declarations.
+void NeonEmitter::run(raw_ostream &OS) {
+ EmitSourceFileHeader("ARM NEON Header", OS);
+
+ // FIXME: emit license into file?
+
+ OS << "#ifndef __ARM_NEON_H\n";
+ OS << "#define __ARM_NEON_H\n\n";
+
+ OS << "#ifndef __ARM_NEON__\n";
+ OS << "#error \"NEON support not enabled\"\n";
+ OS << "#endif\n\n";
+
+ OS << "#include <stdint.h>\n\n";
+
+ // Emit NEON-specific scalar typedefs.
+ OS << "typedef float float32_t;\n";
+ OS << "typedef uint8_t poly8_t;\n";
+ OS << "typedef uint16_t poly16_t;\n";
+ OS << "typedef uint16_t float16_t;\n";
+
+ // Emit Neon vector typedefs.
+ std::string TypedefTypes("cQcsQsiQilQlUcQUcUsQUsUiQUiUlQUlhQhfQfPcQPcPsQPs");
+ SmallVector<StringRef, 24> TDTypeVec;
+ ParseTypes(0, TypedefTypes, TDTypeVec);
+
+ // Emit vector typedefs.
+ for (unsigned v = 1; v != 5; ++v) {
+ for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
+ bool dummy, quad = false;
+ (void) ClassifyType(TDTypeVec[i], quad, dummy, dummy);
+ OS << "typedef __attribute__(( __vector_size__(";
+
+ OS << utostr(8*v*(quad ? 2 : 1)) << ") )) ";
+ if (!quad)
+ OS << " ";
+
+ OS << TypeString('s', TDTypeVec[i]);
+ OS << " __neon_";
+
+ char t = (v == 1) ? 'd' : '0' + v;
+ OS << TypeString(t, TDTypeVec[i]) << ";\n";
+ }
+ }
+ OS << "\n";
+
+ // Emit struct typedefs.
+ for (unsigned vi = 1; vi != 5; ++vi) {
+ for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) {
+ std::string ts = TypeString('d', TDTypeVec[i], vi == 1);
+ std::string vs = TypeString((vi > 1) ? '0' + vi : 'd', TDTypeVec[i]);
+ std::string tag = (vi > 1) ? vs : StructTag(TDTypeVec[i]);
+ OS << "typedef struct " << tag << " {\n";
+ OS << " " << ts << " val";
+ if (vi > 1)
+ OS << "[" << utostr(vi) << "]";
+ OS << ";\n} " << vs << ";\n\n";
+ }
+ }
+
+ OS << "#define __ai static __attribute__((__always_inline__))\n\n";
+
+ std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
+
+ // Unique the return+pattern types, and assign them.
+ for (unsigned i = 0, e = RV.size(); i != e; ++i) {
+ Record *R = RV[i];
+ std::string name = LowercaseString(R->getName());
+ std::string Proto = R->getValueAsString("Prototype");
+ std::string Types = R->getValueAsString("Types");
+
+ SmallVector<StringRef, 16> TypeVec;
+ ParseTypes(R, Types, TypeVec);
+
+ OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
+
+ bool define = Proto.find('i') != std::string::npos;
+
+ for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
+ assert(!Proto.empty() && "");
+
+ // static always inline + return type
+ if (define)
+ OS << "#define";
+ else
+ OS << "__ai " << TypeString(Proto[0], TypeVec[ti]);
+
+ // Function name with type suffix
+ OS << " " << MangleName(name, TypeVec[ti], ClassS);
+
+ // Function arguments
+ OS << GenArgs(Proto, TypeVec[ti]);
+
+ // Definition.
+ if (define)
+ OS << " ";
+ else
+ OS << " { ";
+
+ if (k != OpNone) {
+ OS << GenOpString(k, Proto, TypeVec[ti]);
+ } else {
+ if (R->getSuperClasses().size() < 2)
+ throw TGError(R->getLoc(), "Builtin has no class kind");
+
+ ClassKind ck = ClassMap[R->getSuperClasses()[1]];
+
+ if (ck == ClassNone)
+ throw TGError(R->getLoc(), "Builtin has no class kind");
+ OS << GenBuiltin(name, Proto, TypeVec[ti], ck);
+ }
+ if (!define)
+ OS << " }";
+ OS << "\n";
+ }
+ OS << "\n";
+ }
+ OS << "#undef __ai\n\n";
+ OS << "#endif /* __ARM_NEON_H */\n";
+}
+
+static unsigned RangeFromType(StringRef typestr) {
+ // base type to get the type string for.
+ bool quad = false, dummy = false;
+ char type = ClassifyType(typestr, quad, dummy, dummy);
+
+ switch (type) {
+ case 'c':
+ return (8 << (int)quad) - 1;
+ case 'h':
+ case 's':
+ return (4 << (int)quad) - 1;
+ case 'f':
+ case 'i':
+ return (2 << (int)quad) - 1;
+ case 'l':
+ return (1 << (int)quad) - 1;
+ default:
+ throw "unhandled type!";
+ break;
+ }
+}
+
+/// runHeader - Emit a file with sections defining:
+/// 1. the NEON section of BuiltinsARM.def.
+/// 2. the SemaChecking code for the type overload checking.
+/// 3. the SemaChecking code for validation of intrinsic immedate arguments.
+void NeonEmitter::runHeader(raw_ostream &OS) {
+ std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst");
+
+ StringMap<OpKind> EmittedMap;
+
+ // Generate BuiltinsARM.def for NEON
+ OS << "#ifdef GET_NEON_BUILTINS\n";
+ for (unsigned i = 0, e = RV.size(); i != e; ++i) {
+ Record *R = RV[i];
+ OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
+ if (k != OpNone)
+ continue;
+
+ std::string Proto = R->getValueAsString("Prototype");
+
+ // Functions with 'a' (the splat code) in the type prototype should not get
+ // their own builtin as they use the non-splat variant.
+ if (Proto.find('a') != std::string::npos)
+ continue;
+
+ std::string Types = R->getValueAsString("Types");
+ SmallVector<StringRef, 16> TypeVec;
+ ParseTypes(R, Types, TypeVec);
+
+ if (R->getSuperClasses().size() < 2)
+ throw TGError(R->getLoc(), "Builtin has no class kind");
+
+ std::string name = LowercaseString(R->getName());
+ ClassKind ck = ClassMap[R->getSuperClasses()[1]];
+
+ for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
+ // Generate the BuiltinsARM.def declaration for this builtin, ensuring
+ // that each unique BUILTIN() macro appears only once in the output
+ // stream.
+ std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck);
+ if (EmittedMap.count(bd))
+ continue;
+
+ EmittedMap[bd] = OpNone;
+ OS << bd << "\n";
+ }
+ }
+ OS << "#endif\n\n";
+
+ // Generate the overloaded type checking code for SemaChecking.cpp
+ OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n";
+ for (unsigned i = 0, e = RV.size(); i != e; ++i) {
+ Record *R = RV[i];
+ OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
+ if (k != OpNone)
+ continue;
+
+ std::string Proto = R->getValueAsString("Prototype");
+ std::string Types = R->getValueAsString("Types");
+ std::string name = LowercaseString(R->getName());
+
+ // Functions with 'a' (the splat code) in the type prototype should not get
+ // their own builtin as they use the non-splat variant.
+ if (Proto.find('a') != std::string::npos)
+ continue;
+
+ // Functions which have a scalar argument cannot be overloaded, no need to
+ // check them if we are emitting the type checking code.
+ if (Proto.find('s') != std::string::npos)
+ continue;
+
+ SmallVector<StringRef, 16> TypeVec;
+ ParseTypes(R, Types, TypeVec);
+
+ if (R->getSuperClasses().size() < 2)
+ throw TGError(R->getLoc(), "Builtin has no class kind");
+
+ int si = -1, qi = -1;
+ unsigned mask = 0, qmask = 0;
+ for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
+ // Generate the switch case(s) for this builtin for the type validation.
+ bool quad = false, poly = false, usgn = false;
+ (void) ClassifyType(TypeVec[ti], quad, poly, usgn);
+
+ if (quad) {
+ qi = ti;
+ qmask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
+ } else {
+ si = ti;
+ mask |= 1 << GetNeonEnum(Proto, TypeVec[ti]);
+ }
+ }
+ if (mask)
+ OS << "case ARM::BI__builtin_neon_"
+ << MangleName(name, TypeVec[si], ClassB)
+ << ": mask = " << "0x" << utohexstr(mask) << "; break;\n";
+ if (qmask)
+ OS << "case ARM::BI__builtin_neon_"
+ << MangleName(name, TypeVec[qi], ClassB)
+ << ": mask = " << "0x" << utohexstr(qmask) << "; break;\n";
+ }
+ OS << "#endif\n\n";
+
+ // Generate the intrinsic range checking code for shift/lane immediates.
+ OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n";
+ for (unsigned i = 0, e = RV.size(); i != e; ++i) {
+ Record *R = RV[i];
+
+ OpKind k = OpMap[R->getValueAsDef("Operand")->getName()];
+ if (k != OpNone)
+ continue;
+
+ std::string name = LowercaseString(R->getName());
+ std::string Proto = R->getValueAsString("Prototype");
+ std::string Types = R->getValueAsString("Types");
+
+ // Functions with 'a' (the splat code) in the type prototype should not get
+ // their own builtin as they use the non-splat variant.
+ if (Proto.find('a') != std::string::npos)
+ continue;
+
+ // Functions which do not have an immediate do not need to have range
+ // checking code emitted.
+ if (Proto.find('i') == std::string::npos)
+ continue;
+
+ SmallVector<StringRef, 16> TypeVec;
+ ParseTypes(R, Types, TypeVec);
+
+ if (R->getSuperClasses().size() < 2)
+ throw TGError(R->getLoc(), "Builtin has no class kind");
+
+ ClassKind ck = ClassMap[R->getSuperClasses()[1]];
+
+ for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) {
+ std::string namestr, shiftstr, rangestr;
+
+ // Builtins which are overloaded by type will need to have their upper
+ // bound computed at Sema time based on the type constant.
+ if (Proto.find('s') == std::string::npos) {
+ ck = ClassB;
+ if (R->getValueAsBit("isShift")) {
+ shiftstr = ", true";
+
+ // Right shifts have an 'r' in the name, left shifts do not.
+ if (name.find('r') != std::string::npos)
+ rangestr = "l = 1; ";
+ }
+ rangestr += "u = RFT(TV" + shiftstr + ")";
+ } else {
+ rangestr = "u = " + utostr(RangeFromType(TypeVec[ti]));
+ }
+ // Make sure cases appear only once by uniquing them in a string map.
+ namestr = MangleName(name, TypeVec[ti], ck);
+ if (EmittedMap.count(namestr))
+ continue;
+ EmittedMap[namestr] = OpNone;
+
+ // Calculate the index of the immediate that should be range checked.
+ unsigned immidx = 0;
+
+ // Builtins that return a struct of multiple vectors have an extra
+ // leading arg for the struct return.
+ if (Proto[0] == '2' || Proto[0] == '3' || Proto[0] == '4')
+ ++immidx;
+
+ // Add one to the index for each argument until we reach the immediate
+ // to be checked. Structs of vectors are passed as multiple arguments.
+ for (unsigned ii = 1, ie = Proto.size(); ii != ie; ++ii) {
+ switch (Proto[ii]) {
+ default: immidx += 1; break;
+ case '2': immidx += 2; break;
+ case '3': immidx += 3; break;
+ case '4': immidx += 4; break;
+ case 'i': ie = ii + 1; break;
+ }
+ }
+ OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[ti], ck)
+ << ": i = " << immidx << "; " << rangestr << "; break;\n";
+ }
+ }
+ OS << "#endif\n\n";
+}
diff --git a/contrib/llvm/utils/TableGen/NeonEmitter.h b/contrib/llvm/utils/TableGen/NeonEmitter.h
new file mode 100644
index 0000000..6c6760d
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/NeonEmitter.h
@@ -0,0 +1,122 @@
+//===- NeonEmitter.h - Generate arm_neon.h for use with clang ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting arm_neon.h, which includes
+// a declaration and definition of each function specified by the ARM NEON
+// compiler interface. See ARM document DUI0348B.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef NEON_EMITTER_H
+#define NEON_EMITTER_H
+
+#include "Record.h"
+#include "TableGenBackend.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
+
+enum OpKind {
+ OpNone,
+ OpAdd,
+ OpSub,
+ OpMul,
+ OpMla,
+ OpMls,
+ OpMulN,
+ OpMlaN,
+ OpMlsN,
+ OpEq,
+ OpGe,
+ OpLe,
+ OpGt,
+ OpLt,
+ OpNeg,
+ OpNot,
+ OpAnd,
+ OpOr,
+ OpXor,
+ OpAndNot,
+ OpOrNot,
+ OpCast,
+ OpConcat,
+ OpDup,
+ OpHi,
+ OpLo,
+ OpSelect,
+ OpRev16,
+ OpRev32,
+ OpRev64
+};
+
+enum ClassKind {
+ ClassNone,
+ ClassI,
+ ClassS,
+ ClassW,
+ ClassB
+};
+
+namespace llvm {
+
+ class NeonEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+ StringMap<OpKind> OpMap;
+ DenseMap<Record*, ClassKind> ClassMap;
+
+ public:
+ NeonEmitter(RecordKeeper &R) : Records(R) {
+ OpMap["OP_NONE"] = OpNone;
+ OpMap["OP_ADD"] = OpAdd;
+ OpMap["OP_SUB"] = OpSub;
+ OpMap["OP_MUL"] = OpMul;
+ OpMap["OP_MLA"] = OpMla;
+ OpMap["OP_MLS"] = OpMls;
+ OpMap["OP_MUL_N"] = OpMulN;
+ OpMap["OP_MLA_N"] = OpMlaN;
+ OpMap["OP_MLS_N"] = OpMlsN;
+ OpMap["OP_EQ"] = OpEq;
+ OpMap["OP_GE"] = OpGe;
+ OpMap["OP_LE"] = OpLe;
+ OpMap["OP_GT"] = OpGt;
+ OpMap["OP_LT"] = OpLt;
+ OpMap["OP_NEG"] = OpNeg;
+ OpMap["OP_NOT"] = OpNot;
+ OpMap["OP_AND"] = OpAnd;
+ OpMap["OP_OR"] = OpOr;
+ OpMap["OP_XOR"] = OpXor;
+ OpMap["OP_ANDN"] = OpAndNot;
+ OpMap["OP_ORN"] = OpOrNot;
+ OpMap["OP_CAST"] = OpCast;
+ OpMap["OP_CONC"] = OpConcat;
+ OpMap["OP_HI"] = OpHi;
+ OpMap["OP_LO"] = OpLo;
+ OpMap["OP_DUP"] = OpDup;
+ OpMap["OP_SEL"] = OpSelect;
+ OpMap["OP_REV16"] = OpRev16;
+ OpMap["OP_REV32"] = OpRev32;
+ OpMap["OP_REV64"] = OpRev64;
+
+ Record *SI = R.getClass("SInst");
+ Record *II = R.getClass("IInst");
+ Record *WI = R.getClass("WInst");
+ ClassMap[SI] = ClassS;
+ ClassMap[II] = ClassI;
+ ClassMap[WI] = ClassW;
+ }
+
+ // run - Emit arm_neon.h.inc
+ void run(raw_ostream &o);
+
+ // runHeader - Emit all the __builtin prototypes used in arm_neon.h
+ void runHeader(raw_ostream &o);
+ };
+
+} // End llvm namespace
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/Record.cpp b/contrib/llvm/utils/TableGen/Record.cpp
index 4f9f604..d2cf379 100644
--- a/contrib/llvm/utils/TableGen/Record.cpp
+++ b/contrib/llvm/utils/TableGen/Record.cpp
@@ -270,7 +270,15 @@ Init *RecordRecTy::convertValue(TypedInit *TI) {
}
bool RecordRecTy::baseClassOf(const RecordRecTy *RHS) const {
- return Rec == RHS->getRecord() || RHS->getRecord()->isSubClassOf(Rec);
+ if (Rec == RHS->getRecord() || RHS->getRecord()->isSubClassOf(Rec))
+ return true;
+
+ const std::vector<Record*> &SC = Rec->getSuperClasses();
+ for (unsigned i = 0, e = SC.size(); i != e; ++i)
+ if (RHS->getRecord()->isSubClassOf(SC[i]))
+ return true;
+
+ return false;
}
@@ -721,9 +729,20 @@ Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
break;
}
case EQ: {
- // Make sure we've resolved
+ // try to fold eq comparison for 'bit' and 'int', otherwise fallback
+ // to string objects.
+ IntInit* L =
+ dynamic_cast<IntInit*>(LHS->convertInitializerTo(new IntRecTy()));
+ IntInit* R =
+ dynamic_cast<IntInit*>(RHS->convertInitializerTo(new IntRecTy()));
+
+ if (L && R)
+ return new IntInit(L->getValue() == R->getValue());
+
StringInit *LHSs = dynamic_cast<StringInit*>(LHS);
StringInit *RHSs = dynamic_cast<StringInit*>(RHS);
+
+ // Make sure we've resolved
if (LHSs && RHSs)
return new IntInit(LHSs->getValue() == RHSs->getValue());
@@ -971,6 +990,8 @@ Init *TernOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) {
case IF: {
IntInit *LHSi = dynamic_cast<IntInit*>(LHS);
+ if (Init *I = LHS->convertInitializerTo(new IntRecTy()))
+ LHSi = dynamic_cast<IntInit*>(I);
if (LHSi) {
if (LHSi->getValue()) {
return MHS;
@@ -990,6 +1011,8 @@ Init *TernOpInit::resolveReferences(Record &R, const RecordVal *RV) {
if (Opc == IF && lhs != LHS) {
IntInit *Value = dynamic_cast<IntInit*>(lhs);
+ if (Init *I = lhs->convertInitializerTo(new IntRecTy()))
+ Value = dynamic_cast<IntInit*>(I);
if (Value != 0) {
// Short-circuit
if (Value->getValue()) {
@@ -1239,7 +1262,7 @@ Init *DagInit::resolveReferences(Record &R, const RecordVal *RV) {
Init *Op = Val->resolveReferences(R, RV);
if (Args != NewArgs || Op != Val)
- return new DagInit(Op, "", NewArgs, ArgNames);
+ return new DagInit(Op, ValName, NewArgs, ArgNames);
return this;
}
diff --git a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp
index c99bbd9..a3ca0bc 100644
--- a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp
@@ -82,6 +82,7 @@ void RegisterInfoEmitter::runHeader(raw_ostream &OS) {
<< " { return false; }\n"
<< " unsigned getSubReg(unsigned RegNo, unsigned Index) const;\n"
<< " unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const;\n"
+ << " unsigned composeSubRegIndices(unsigned, unsigned) const;\n"
<< "};\n\n";
const std::vector<CodeGenRegisterClass> &RegisterClasses =
@@ -95,7 +96,7 @@ void RegisterInfoEmitter::runHeader(raw_ostream &OS) {
for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
if (i) OS << ",\n";
OS << " " << RegisterClasses[i].getName() << "RegClassID";
- OS << " = " << (i+1);
+ OS << " = " << i;
}
OS << "\n };\n\n";
@@ -171,14 +172,28 @@ static void addSubSuperReg(Record *R, Record *S,
addSubSuperReg(R, *I, SubRegs, SuperRegs, Aliases);
}
-// Map SubRegIndex -> Register
-typedef std::map<Record*, Record*, LessRecord> SubRegMap;
-// Map Register -> SubRegMap
-typedef std::map<Record*, SubRegMap> AllSubRegMap;
+struct RegisterMaps {
+ // Map SubRegIndex -> Register
+ typedef std::map<Record*, Record*, LessRecord> SubRegMap;
+ // Map Register -> SubRegMap
+ typedef std::map<Record*, SubRegMap> SubRegMaps;
+
+ SubRegMaps SubReg;
+ SubRegMap &inferSubRegIndices(Record *Reg);
+
+ // Composite SubRegIndex instances.
+ // Map (SubRegIndex,SubRegIndex) -> SubRegIndex
+ typedef DenseMap<std::pair<Record*,Record*>,Record*> CompositeMap;
+ CompositeMap Composite;
+
+ // Compute SubRegIndex compositions after inferSubRegIndices has run on all
+ // registers.
+ void computeComposites();
+};
// Calculate all subregindices for Reg. Loopy subregs cause infinite recursion.
-static SubRegMap &inferSubRegIndices(Record *Reg, AllSubRegMap &ASRM) {
- SubRegMap &SRM = ASRM[Reg];
+RegisterMaps::SubRegMap &RegisterMaps::inferSubRegIndices(Record *Reg) {
+ SubRegMap &SRM = SubReg[Reg];
if (!SRM.empty())
return SRM;
std::vector<Record*> SubRegs = Reg->getValueAsListOfDefs("SubRegs");
@@ -191,7 +206,7 @@ static SubRegMap &inferSubRegIndices(Record *Reg, AllSubRegMap &ASRM) {
if (!SRM.insert(std::make_pair(Indices[i], SubRegs[i])).second)
throw "SubRegIndex " + Indices[i]->getName()
+ " appears twice in Register " + Reg->getName();
- inferSubRegIndices(SubRegs[i], ASRM);
+ inferSubRegIndices(SubRegs[i]);
}
// Keep track of inherited subregs and how they can be reached.
@@ -202,7 +217,7 @@ static SubRegMap &inferSubRegIndices(Record *Reg, AllSubRegMap &ASRM) {
// Clone inherited subregs. Here the order is important - earlier subregs take
// precedence.
for (unsigned i = 0, e = SubRegs.size(); i != e; ++i) {
- SubRegMap &M = ASRM[SubRegs[i]];
+ SubRegMap &M = SubReg[SubRegs[i]];
for (SubRegMap::iterator si = M.begin(), se = M.end(); si != se; ++si)
if (!SRM.insert(*si).second)
Orphans[si->second] = std::make_pair(Indices[i], si->first);
@@ -226,8 +241,8 @@ static SubRegMap &inferSubRegIndices(Record *Reg, AllSubRegMap &ASRM) {
DefInit *IdxInit = dynamic_cast<DefInit*>(*di);
if (!IdxInit || !IdxInit->getDef()->isSubClassOf("SubRegIndex"))
throw "Invalid SubClassIndex in " + Pat->getAsString();
- SubRegMap::const_iterator ni = ASRM[R2].find(IdxInit->getDef());
- if (ni == ASRM[R2].end())
+ SubRegMap::const_iterator ni = SubReg[R2].find(IdxInit->getDef());
+ if (ni == SubReg[R2].end())
throw "Composite " + Pat->getAsString() + " refers to bad index in "
+ R2->getName();
R2 = ni->second;
@@ -255,6 +270,62 @@ static SubRegMap &inferSubRegIndices(Record *Reg, AllSubRegMap &ASRM) {
return SRM;
}
+void RegisterMaps::computeComposites() {
+ for (SubRegMaps::const_iterator sri = SubReg.begin(), sre = SubReg.end();
+ sri != sre; ++sri) {
+ Record *Reg1 = sri->first;
+ const SubRegMap &SRM1 = sri->second;
+ for (SubRegMap::const_iterator i1 = SRM1.begin(), e1 = SRM1.end();
+ i1 != e1; ++i1) {
+ Record *Idx1 = i1->first;
+ Record *Reg2 = i1->second;
+ // Ignore identity compositions.
+ if (Reg1 == Reg2)
+ continue;
+ // If Reg2 has no subregs, Idx1 doesn't compose.
+ if (!SubReg.count(Reg2))
+ continue;
+ const SubRegMap &SRM2 = SubReg[Reg2];
+ // Try composing Idx1 with another SubRegIndex.
+ for (SubRegMap::const_iterator i2 = SRM2.begin(), e2 = SRM2.end();
+ i2 != e2; ++i2) {
+ std::pair<Record*,Record*> IdxPair(Idx1, i2->first);
+ Record *Reg3 = i2->second;
+ // OK Reg1:IdxPair == Reg3. Find the index with Reg:Idx == Reg3.
+ for (SubRegMap::const_iterator i1d = SRM1.begin(), e1d = SRM1.end();
+ i1d != e1d; ++i1d) {
+ // Ignore identity compositions.
+ if (Reg2 == Reg3)
+ continue;
+ if (i1d->second == Reg3) {
+ std::pair<CompositeMap::iterator,bool> Ins =
+ Composite.insert(std::make_pair(IdxPair, i1d->first));
+ // Conflicting composition?
+ if (!Ins.second && Ins.first->second != i1d->first) {
+ errs() << "Error: SubRegIndex " << getQualifiedName(Idx1)
+ << " and " << getQualifiedName(IdxPair.second)
+ << " compose ambiguously as "
+ << getQualifiedName(Ins.first->second) << " or "
+ << getQualifiedName(i1d->first) << "\n";
+ abort();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // We don't care about the difference between (Idx1, Idx2) -> Idx2 and invalid
+ // compositions, so remove any mappings of that form.
+ for (CompositeMap::iterator i = Composite.begin(), e = Composite.end();
+ i != e;) {
+ CompositeMap::iterator j = i;
+ ++i;
+ if (j->first.second == j->second)
+ Composite.erase(j);
+ }
+}
+
class RegisterSorter {
private:
std::map<Record*, std::set<Record*>, LessRecord> &RegisterSubRegs;
@@ -836,7 +907,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
std::string ClassName = Target.getName() + "GenRegisterInfo";
// Calculate the mapping of subregister+index pairs to physical registers.
- AllSubRegMap AllSRM;
+ RegisterMaps RegMaps;
// Emit the subregister + index mapping function based on the information
// calculated above.
@@ -845,14 +916,14 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
<< " switch (RegNo) {\n"
<< " default:\n return 0;\n";
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- SubRegMap &SRM = inferSubRegIndices(Regs[i].TheDef, AllSRM);
+ RegisterMaps::SubRegMap &SRM = RegMaps.inferSubRegIndices(Regs[i].TheDef);
if (SRM.empty())
continue;
OS << " case " << getQualifiedName(Regs[i].TheDef) << ":\n";
OS << " switch (Index) {\n";
OS << " default: return 0;\n";
- for (SubRegMap::const_iterator ii = SRM.begin(), ie = SRM.end(); ii != ie;
- ++ii)
+ for (RegisterMaps::SubRegMap::const_iterator ii = SRM.begin(),
+ ie = SRM.end(); ii != ie; ++ii)
OS << " case " << getQualifiedName(ii->first)
<< ": return " << getQualifiedName(ii->second) << ";\n";
OS << " };\n" << " break;\n";
@@ -866,12 +937,12 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
<< " switch (RegNo) {\n"
<< " default:\n return 0;\n";
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- SubRegMap &SRM = AllSRM[Regs[i].TheDef];
+ RegisterMaps::SubRegMap &SRM = RegMaps.SubReg[Regs[i].TheDef];
if (SRM.empty())
continue;
OS << " case " << getQualifiedName(Regs[i].TheDef) << ":\n";
- for (SubRegMap::const_iterator ii = SRM.begin(), ie = SRM.end(); ii != ie;
- ++ii)
+ for (RegisterMaps::SubRegMap::const_iterator ii = SRM.begin(),
+ ie = SRM.end(); ii != ie; ++ii)
OS << " if (SubRegNo == " << getQualifiedName(ii->second)
<< ") return " << getQualifiedName(ii->first) << ";\n";
OS << " return 0;\n";
@@ -879,7 +950,32 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
OS << " };\n";
OS << " return 0;\n";
OS << "}\n\n";
-
+
+ // Emit composeSubRegIndices
+ RegMaps.computeComposites();
+ OS << "unsigned " << ClassName
+ << "::composeSubRegIndices(unsigned IdxA, unsigned IdxB) const {\n"
+ << " switch (IdxA) {\n"
+ << " default:\n return IdxB;\n";
+ for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) {
+ bool Open = false;
+ for (unsigned j = 0; j != e; ++j) {
+ if (Record *Comp = RegMaps.Composite.lookup(
+ std::make_pair(SubRegIndices[i], SubRegIndices[j]))) {
+ if (!Open) {
+ OS << " case " << getQualifiedName(SubRegIndices[i])
+ << ": switch(IdxB) {\n default: return IdxB;\n";
+ Open = true;
+ }
+ OS << " case " << getQualifiedName(SubRegIndices[j])
+ << ": return " << getQualifiedName(Comp) << ";\n";
+ }
+ }
+ if (Open)
+ OS << " }\n";
+ }
+ OS << " }\n}\n\n";
+
// Emit the constructor of the class...
OS << ClassName << "::" << ClassName
<< "(int CallFrameSetupOpcode, int CallFrameDestroyOpcode)\n"
diff --git a/contrib/llvm/utils/TableGen/TGParser.cpp b/contrib/llvm/utils/TableGen/TGParser.cpp
index 8c158e0..f81aabe 100644
--- a/contrib/llvm/utils/TableGen/TGParser.cpp
+++ b/contrib/llvm/utils/TableGen/TGParser.cpp
@@ -1635,13 +1635,12 @@ bool TGParser::ParseObjectBody(Record *CurRec) {
return ParseBody(CurRec);
}
-
/// ParseDef - Parse and return a top level or multiclass def, return the record
/// corresponding to it. This returns null on error.
///
/// DefInst ::= DEF ObjectName ObjectBody
///
-llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) {
+bool TGParser::ParseDef(MultiClass *CurMultiClass) {
SMLoc DefLoc = Lex.getLoc();
assert(Lex.getCode() == tgtok::Def && "Unknown tok");
Lex.Lex(); // Eat the 'def' token.
@@ -1655,7 +1654,7 @@ llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) {
// Ensure redefinition doesn't happen.
if (Records.getDef(CurRec->getName())) {
Error(DefLoc, "def '" + CurRec->getName() + "' already defined");
- return 0;
+ return true;
}
Records.addDef(CurRec);
} else {
@@ -1664,20 +1663,33 @@ llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) {
if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) {
Error(DefLoc, "def '" + CurRec->getName() +
"' already defined in this multiclass!");
- return 0;
+ return true;
}
CurMultiClass->DefPrototypes.push_back(CurRec);
}
if (ParseObjectBody(CurRec))
- return 0;
+ return true;
if (CurMultiClass == 0) // Def's in multiclasses aren't really defs.
CurRec->resolveReferences();
// If ObjectBody has template arguments, it's an error.
assert(CurRec->getTemplateArgs().empty() && "How'd this get template args?");
- return CurRec;
+
+ if (CurMultiClass) {
+ // Copy the template arguments for the multiclass into the def.
+ const std::vector<std::string> &TArgs =
+ CurMultiClass->Rec.getTemplateArgs();
+
+ for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
+ const RecordVal *RV = CurMultiClass->Rec.getValue(TArgs[i]);
+ assert(RV && "Template arg doesn't exist?");
+ CurRec->addValue(*RV);
+ }
+ }
+
+ return false;
}
@@ -1758,12 +1770,12 @@ std::vector<LetRecord> TGParser::ParseLetList() {
}
/// ParseTopLevelLet - Parse a 'let' at top level. This can be a couple of
-/// different related productions.
+/// different related productions. This works inside multiclasses too.
///
/// Object ::= LET LetList IN '{' ObjectList '}'
/// Object ::= LET LetList IN Object
///
-bool TGParser::ParseTopLevelLet() {
+bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) {
assert(Lex.getCode() == tgtok::Let && "Unexpected token");
Lex.Lex();
@@ -1779,7 +1791,7 @@ bool TGParser::ParseTopLevelLet() {
// If this is a scalar let, just handle it now
if (Lex.getCode() != tgtok::l_brace) {
// LET LetList IN Object
- if (ParseObject())
+ if (ParseObject(CurMultiClass))
return true;
} else { // Object ::= LETCommand '{' ObjectList '}'
SMLoc BraceLoc = Lex.getLoc();
@@ -1787,7 +1799,7 @@ bool TGParser::ParseTopLevelLet() {
Lex.Lex(); // eat the '{'.
// Parse the object list.
- if (ParseObjectList())
+ if (ParseObjectList(CurMultiClass))
return true;
if (Lex.getCode() != tgtok::r_brace) {
@@ -1802,29 +1814,6 @@ bool TGParser::ParseTopLevelLet() {
return false;
}
-/// ParseMultiClassDef - Parse a def in a multiclass context.
-///
-/// MultiClassDef ::= DefInst
-///
-bool TGParser::ParseMultiClassDef(MultiClass *CurMC) {
- if (Lex.getCode() != tgtok::Def)
- return TokError("expected 'def' in multiclass body");
-
- Record *D = ParseDef(CurMC);
- if (D == 0) return true;
-
- // Copy the template arguments for the multiclass into the def.
- const std::vector<std::string> &TArgs = CurMC->Rec.getTemplateArgs();
-
- for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
- const RecordVal *RV = CurMC->Rec.getValue(TArgs[i]);
- assert(RV && "Template arg doesn't exist?");
- D->addValue(*RV);
- }
-
- return false;
-}
-
/// ParseMultiClass - Parse a multiclass definition.
///
/// MultiClassInst ::= MULTICLASS ID TemplateArgList?
@@ -1885,10 +1874,18 @@ bool TGParser::ParseMultiClass() {
if (Lex.Lex() == tgtok::r_brace) // eat the '{'.
return TokError("multiclass must contain at least one def");
- while (Lex.getCode() != tgtok::r_brace)
- if (ParseMultiClassDef(CurMultiClass))
- return true;
-
+ while (Lex.getCode() != tgtok::r_brace) {
+ switch (Lex.getCode()) {
+ default:
+ return TokError("expected 'let', 'def' or 'defm' in multiclass body");
+ case tgtok::Let:
+ case tgtok::Def:
+ case tgtok::Defm:
+ if (ParseObject(CurMultiClass))
+ return true;
+ break;
+ }
+ }
Lex.Lex(); // eat the '}'.
}
@@ -1900,7 +1897,7 @@ bool TGParser::ParseMultiClass() {
///
/// DefMInst ::= DEFM ID ':' DefmSubClassRef ';'
///
-bool TGParser::ParseDefm() {
+bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
assert(Lex.getCode() == tgtok::Defm && "Unexpected token!");
if (Lex.Lex() != tgtok::Id) // eat the defm.
return TokError("expected identifier after defm");
@@ -1910,6 +1907,12 @@ bool TGParser::ParseDefm() {
if (Lex.Lex() != tgtok::colon)
return TokError("expected ':' after defm identifier");
+ // Keep track of the new generated record definitions.
+ std::vector<Record*> NewRecDefs;
+
+ // This record also inherits from a regular class (non-multiclass)?
+ bool InheritFromClass = false;
+
// eat the colon.
Lex.Lex();
@@ -1991,17 +1994,87 @@ bool TGParser::ParseDefm() {
return Error(DefmPrefixLoc, "def '" + CurRec->getName() +
"' already defined, instantiating defm with subdef '" +
DefProto->getName() + "'");
- Records.addDef(CurRec);
- CurRec->resolveReferences();
+
+ // Don't create a top level definition for defm inside multiclasses,
+ // instead, only update the prototypes and bind the template args
+ // with the new created definition.
+ if (CurMultiClass) {
+ for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size();
+ i != e; ++i) {
+ if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) {
+ Error(DefmPrefixLoc, "defm '" + CurRec->getName() +
+ "' already defined in this multiclass!");
+ return 0;
+ }
+ }
+ CurMultiClass->DefPrototypes.push_back(CurRec);
+
+ // Copy the template arguments for the multiclass into the new def.
+ const std::vector<std::string> &TA =
+ CurMultiClass->Rec.getTemplateArgs();
+
+ for (unsigned i = 0, e = TA.size(); i != e; ++i) {
+ const RecordVal *RV = CurMultiClass->Rec.getValue(TA[i]);
+ assert(RV && "Template arg doesn't exist?");
+ CurRec->addValue(*RV);
+ }
+ } else {
+ Records.addDef(CurRec);
+ }
+
+ NewRecDefs.push_back(CurRec);
}
if (Lex.getCode() != tgtok::comma) break;
Lex.Lex(); // eat ','.
SubClassLoc = Lex.getLoc();
+
+ // A defm can inherit from regular classes (non-multiclass) as
+ // long as they come in the end of the inheritance list.
+ InheritFromClass = (Records.getClass(Lex.getCurStrVal()) != 0);
+
+ if (InheritFromClass)
+ break;
+
Ref = ParseSubClassReference(0, true);
}
+ if (InheritFromClass) {
+ // Process all the classes to inherit as if they were part of a
+ // regular 'def' and inherit all record values.
+ SubClassReference SubClass = ParseSubClassReference(0, false);
+ while (1) {
+ // Check for error.
+ if (SubClass.Rec == 0) return true;
+
+ // Get the expanded definition prototypes and teach them about
+ // the record values the current class to inherit has
+ for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i) {
+ Record *CurRec = NewRecDefs[i];
+
+ // Add it.
+ if (AddSubClass(CurRec, SubClass))
+ return true;
+
+ // Process any variables on the let stack.
+ for (unsigned i = 0, e = LetStack.size(); i != e; ++i)
+ for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j)
+ if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name,
+ LetStack[i][j].Bits, LetStack[i][j].Value))
+ return true;
+ }
+
+ if (Lex.getCode() != tgtok::comma) break;
+ Lex.Lex(); // eat ','.
+ SubClass = ParseSubClassReference(0, false);
+ }
+ }
+
+ if (!CurMultiClass)
+ for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i)
+ NewRecDefs[i]->resolveReferences();
+
if (Lex.getCode() != tgtok::semi)
return TokError("expected ';' at end of defm");
Lex.Lex();
@@ -2016,12 +2089,12 @@ bool TGParser::ParseDefm() {
/// Object ::= DefMInst
/// Object ::= LETCommand '{' ObjectList '}'
/// Object ::= LETCommand Object
-bool TGParser::ParseObject() {
+bool TGParser::ParseObject(MultiClass *MC) {
switch (Lex.getCode()) {
default: assert(0 && "This is not an object");
- case tgtok::Let: return ParseTopLevelLet();
- case tgtok::Def: return ParseDef(0) == 0;
- case tgtok::Defm: return ParseDefm();
+ case tgtok::Let: return ParseTopLevelLet(MC);
+ case tgtok::Def: return ParseDef(MC);
+ case tgtok::Defm: return ParseDefm(MC);
case tgtok::Class: return ParseClass();
case tgtok::MultiClass: return ParseMultiClass();
}
@@ -2029,9 +2102,9 @@ bool TGParser::ParseObject() {
/// ParseObjectList
/// ObjectList :== Object*
-bool TGParser::ParseObjectList() {
+bool TGParser::ParseObjectList(MultiClass *MC) {
while (isObjectStart(Lex.getCode())) {
- if (ParseObject())
+ if (ParseObject(MC))
return true;
}
return false;
diff --git a/contrib/llvm/utils/TableGen/TGParser.h b/contrib/llvm/utils/TableGen/TGParser.h
index 9f4b634..0aee931 100644
--- a/contrib/llvm/utils/TableGen/TGParser.h
+++ b/contrib/llvm/utils/TableGen/TGParser.h
@@ -69,16 +69,15 @@ private: // Semantic analysis methods.
SubMultiClassReference &SubMultiClass);
private: // Parser methods.
- bool ParseObjectList();
- bool ParseObject();
+ bool ParseObjectList(MultiClass *MC = 0);
+ bool ParseObject(MultiClass *MC);
bool ParseClass();
bool ParseMultiClass();
- bool ParseMultiClassDef(MultiClass *CurMC);
- bool ParseDefm();
- bool ParseTopLevelLet();
+ bool ParseDefm(MultiClass *CurMultiClass);
+ bool ParseDef(MultiClass *CurMultiClass);
+ bool ParseTopLevelLet(MultiClass *CurMultiClass);
std::vector<LetRecord> ParseLetList();
- Record *ParseDef(MultiClass *CurMultiClass);
bool ParseObjectBody(Record *CurRec);
bool ParseBody(Record *CurRec);
bool ParseBodyItem(Record *CurRec);
diff --git a/contrib/llvm/utils/TableGen/TableGen.cpp b/contrib/llvm/utils/TableGen/TableGen.cpp
index 17435f6..7a4f74f 100644
--- a/contrib/llvm/utils/TableGen/TableGen.cpp
+++ b/contrib/llvm/utils/TableGen/TableGen.cpp
@@ -19,6 +19,7 @@
#include "AsmWriterEmitter.h"
#include "CallingConvEmitter.h"
#include "ClangASTNodesEmitter.h"
+#include "ClangAttrEmitter.h"
#include "ClangDiagnosticsEmitter.h"
#include "CodeEmitterGen.h"
#include "DAGISelEmitter.h"
@@ -29,6 +30,7 @@
#include "InstrInfoEmitter.h"
#include "IntrinsicEmitter.h"
#include "LLVMCConfigurationEmitter.h"
+#include "NeonEmitter.h"
#include "OptParserEmitter.h"
#include "Record.h"
#include "RegisterInfoEmitter.h"
@@ -52,8 +54,11 @@ enum ActionType {
GenARMDecoder,
GenDisassembler,
GenCallingConv,
+ GenClangAttrClasses,
+ GenClangAttrList,
GenClangDiagsDefs,
GenClangDiagGroups,
+ GenClangDeclNodes,
GenClangStmtNodes,
GenDAGISel,
GenFastISel,
@@ -63,6 +68,8 @@ enum ActionType {
GenTgtIntrinsic,
GenLLVMCConf,
GenEDHeader, GenEDInfo,
+ GenArmNeon,
+ GenArmNeonSema,
PrintEnums
};
@@ -107,10 +114,16 @@ namespace {
"Generate intrinsic information"),
clEnumValN(GenTgtIntrinsic, "gen-tgt-intrinsic",
"Generate target intrinsic information"),
+ clEnumValN(GenClangAttrClasses, "gen-clang-attr-classes",
+ "Generate clang attribute clases"),
+ clEnumValN(GenClangAttrList, "gen-clang-attr-list",
+ "Generate a clang attribute list"),
clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",
"Generate Clang diagnostics definitions"),
clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups",
"Generate Clang diagnostic groups"),
+ clEnumValN(GenClangDeclNodes, "gen-clang-decl-nodes",
+ "Generate Clang AST statement nodes"),
clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes",
"Generate Clang AST statement nodes"),
clEnumValN(GenLLVMCConf, "gen-llvmc",
@@ -119,6 +132,10 @@ namespace {
"Generate enhanced disassembly info header"),
clEnumValN(GenEDInfo, "gen-enhanced-disassembly-info",
"Generate enhanced disassembly info"),
+ clEnumValN(GenArmNeon, "gen-arm-neon",
+ "Generate arm_neon.h for clang"),
+ clEnumValN(GenArmNeonSema, "gen-arm-neon-sema",
+ "Generate ARM NEON sema support for clang"),
clEnumValN(PrintEnums, "print-enums",
"Print enum values for a class"),
clEnumValEnd));
@@ -191,105 +208,117 @@ int main(int argc, char **argv) {
if (ParseFile(InputFilename, IncludeDirs, SrcMgr))
return 1;
- raw_ostream *Out = &outs();
- if (OutputFilename != "-") {
- std::string Error;
- Out = new raw_fd_ostream(OutputFilename.c_str(), Error);
-
- if (!Error.empty()) {
- errs() << argv[0] << ": error opening " << OutputFilename
- << ":" << Error << "\n";
- return 1;
- }
-
- // Make sure the file gets removed if *gasp* tablegen crashes...
- sys::RemoveFileOnSignal(sys::Path(OutputFilename));
+ std::string Error;
+ raw_fd_ostream Out(OutputFilename.c_str(), Error);
+ if (!Error.empty()) {
+ errs() << argv[0] << ": error opening " << OutputFilename
+ << ":" << Error << "\n";
+ return 1;
}
+ // Make sure the file gets removed if *gasp* tablegen crashes...
+ sys::RemoveFileOnSignal(sys::Path(OutputFilename));
+
try {
switch (Action) {
case PrintRecords:
- *Out << Records; // No argument, dump all contents
+ Out << Records; // No argument, dump all contents
break;
case GenEmitter:
- CodeEmitterGen(Records).run(*Out);
+ CodeEmitterGen(Records).run(Out);
break;
case GenRegisterEnums:
- RegisterInfoEmitter(Records).runEnums(*Out);
+ RegisterInfoEmitter(Records).runEnums(Out);
break;
case GenRegister:
- RegisterInfoEmitter(Records).run(*Out);
+ RegisterInfoEmitter(Records).run(Out);
break;
case GenRegisterHeader:
- RegisterInfoEmitter(Records).runHeader(*Out);
+ RegisterInfoEmitter(Records).runHeader(Out);
break;
case GenInstrEnums:
- InstrEnumEmitter(Records).run(*Out);
+ InstrEnumEmitter(Records).run(Out);
break;
case GenInstrs:
- InstrInfoEmitter(Records).run(*Out);
+ InstrInfoEmitter(Records).run(Out);
break;
case GenCallingConv:
- CallingConvEmitter(Records).run(*Out);
+ CallingConvEmitter(Records).run(Out);
break;
case GenAsmWriter:
- AsmWriterEmitter(Records).run(*Out);
+ AsmWriterEmitter(Records).run(Out);
break;
case GenARMDecoder:
- ARMDecoderEmitter(Records).run(*Out);
+ ARMDecoderEmitter(Records).run(Out);
break;
case GenAsmMatcher:
- AsmMatcherEmitter(Records).run(*Out);
+ AsmMatcherEmitter(Records).run(Out);
+ break;
+ case GenClangAttrClasses:
+ ClangAttrClassEmitter(Records).run(Out);
+ break;
+ case GenClangAttrList:
+ ClangAttrListEmitter(Records).run(Out);
break;
case GenClangDiagsDefs:
- ClangDiagsDefsEmitter(Records, ClangComponent).run(*Out);
+ ClangDiagsDefsEmitter(Records, ClangComponent).run(Out);
break;
case GenClangDiagGroups:
- ClangDiagGroupsEmitter(Records).run(*Out);
+ ClangDiagGroupsEmitter(Records).run(Out);
+ break;
+ case GenClangDeclNodes:
+ ClangASTNodesEmitter(Records, "Decl", "Decl").run(Out);
+ ClangDeclContextEmitter(Records).run(Out);
break;
case GenClangStmtNodes:
- ClangStmtNodesEmitter(Records).run(*Out);
+ ClangASTNodesEmitter(Records, "Stmt", "").run(Out);
break;
case GenDisassembler:
- DisassemblerEmitter(Records).run(*Out);
+ DisassemblerEmitter(Records).run(Out);
break;
case GenOptParserDefs:
- OptParserEmitter(Records, true).run(*Out);
+ OptParserEmitter(Records, true).run(Out);
break;
case GenOptParserImpl:
- OptParserEmitter(Records, false).run(*Out);
+ OptParserEmitter(Records, false).run(Out);
break;
case GenDAGISel:
- DAGISelEmitter(Records).run(*Out);
+ DAGISelEmitter(Records).run(Out);
break;
case GenFastISel:
- FastISelEmitter(Records).run(*Out);
+ FastISelEmitter(Records).run(Out);
break;
case GenSubtarget:
- SubtargetEmitter(Records).run(*Out);
+ SubtargetEmitter(Records).run(Out);
break;
case GenIntrinsic:
- IntrinsicEmitter(Records).run(*Out);
+ IntrinsicEmitter(Records).run(Out);
break;
case GenTgtIntrinsic:
- IntrinsicEmitter(Records, true).run(*Out);
+ IntrinsicEmitter(Records, true).run(Out);
break;
case GenLLVMCConf:
- LLVMCConfigurationEmitter(Records).run(*Out);
+ LLVMCConfigurationEmitter(Records).run(Out);
break;
case GenEDHeader:
- EDEmitter(Records).runHeader(*Out);
+ EDEmitter(Records).runHeader(Out);
break;
case GenEDInfo:
- EDEmitter(Records).run(*Out);
+ EDEmitter(Records).run(Out);
+ break;
+ case GenArmNeon:
+ NeonEmitter(Records).run(Out);
+ break;
+ case GenArmNeonSema:
+ NeonEmitter(Records).runHeader(Out);
break;
case PrintEnums:
{
std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
for (unsigned i = 0, e = Recs.size(); i != e; ++i)
- *Out << Recs[i]->getName() << ", ";
- *Out << "\n";
+ Out << Recs[i]->getName() << ", ";
+ Out << "\n";
break;
}
default:
@@ -297,8 +326,6 @@ int main(int argc, char **argv) {
return 1;
}
- if (Out != &outs())
- delete Out; // Close the file
return 0;
} catch (const TGError &Error) {
@@ -313,9 +340,7 @@ int main(int argc, char **argv) {
errs() << argv[0] << ": Unknown unexpected exception occurred.\n";
}
- if (Out != &outs()) {
- delete Out; // Close the file
+ if (OutputFilename != "-")
std::remove(OutputFilename.c_str()); // Remove the file, it's broken
- }
return 1;
}
diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
index b7085ae..4dba85b 100644
--- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
+++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
@@ -33,7 +33,7 @@ using namespace llvm;
MAP(C9, 38) \
MAP(E8, 39) \
MAP(F0, 40) \
- MAP(F8, 41) \
+ MAP(F8, 41) \
MAP(F9, 42)
// A clone of X86 since we can't depend on something that is generated.
@@ -212,6 +212,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
HasOpSizePrefix = Rec->getValueAsBit("hasOpSizePrefix");
HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix");
+ HasVEX_4VPrefix = Rec->getValueAsBit("hasVEX_4VPrefix");
HasLockPrefix = Rec->getValueAsBit("hasLockPrefix");
IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly");
@@ -532,7 +533,13 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
"Unexpected number of operands for MRMSrcRegFrm");
HANDLE_OPERAND(roRegister)
HANDLE_OPERAND(rmRegister)
- HANDLE_OPTIONAL(immediate)
+
+ if (HasVEX_4VPrefix)
+ // FIXME: In AVX, the register below becomes the one encoded
+ // in ModRMVEX and the one above the one in the VEX.VVVV field
+ HANDLE_OPTIONAL(rmRegister)
+ else
+ HANDLE_OPTIONAL(immediate)
break;
case X86Local::MRMSrcMem:
// Operand 1 is a register operand in the Reg/Opcode field.
@@ -541,6 +548,12 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
"Unexpected number of operands for MRMSrcMemFrm");
HANDLE_OPERAND(roRegister)
+
+ if (HasVEX_4VPrefix)
+ // FIXME: In AVX, the register below becomes the one encoded
+ // in ModRMVEX and the one above the one in the VEX.VVVV field
+ HANDLE_OPTIONAL(rmRegister)
+
HANDLE_OPERAND(memory)
HANDLE_OPTIONAL(immediate)
break;
@@ -823,6 +836,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("RST", TYPE_ST)
TYPE("i128mem", TYPE_M128)
TYPE("i64i32imm_pcrel", TYPE_REL64)
+ TYPE("i16imm_pcrel", TYPE_REL16)
TYPE("i32imm_pcrel", TYPE_REL32)
TYPE("SSECC", TYPE_IMM3)
TYPE("brtarget", TYPE_RELv)
@@ -942,6 +956,7 @@ OperandEncoding RecognizableInstr::relocationEncodingFromString
ENCODING("i64i8imm", ENCODING_IB)
ENCODING("i8imm", ENCODING_IB)
ENCODING("i64i32imm_pcrel", ENCODING_ID)
+ ENCODING("i16imm_pcrel", ENCODING_IW)
ENCODING("i32imm_pcrel", ENCODING_ID)
ENCODING("brtarget", ENCODING_Iv)
ENCODING("brtarget8", ENCODING_IB)
diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.h b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h
index 84374b0..db4d96d 100644
--- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.h
+++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h
@@ -52,6 +52,8 @@ private:
bool HasOpSizePrefix;
/// The hasREX_WPrefix field from the record
bool HasREX_WPrefix;
+ /// The hasVEX_4VPrefix field from the record
+ bool HasVEX_4VPrefix;
/// The hasLockPrefix field from the record
bool HasLockPrefix;
/// The isCodeGenOnly filed from the record
OpenPOWER on IntegriCloud