summaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/FileCheck/FileCheck.cpp22
-rwxr-xr-xutils/GenLibDeps.pl143
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp144
-rw-r--r--utils/TableGen/AsmWriterEmitter.cpp394
-rw-r--r--utils/TableGen/AsmWriterEmitter.h1
-rw-r--r--utils/TableGen/AsmWriterInst.cpp264
-rw-r--r--utils/TableGen/AsmWriterInst.h113
-rw-r--r--utils/TableGen/CMakeLists.txt5
-rw-r--r--utils/TableGen/CodeEmitterGen.cpp6
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp57
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.h29
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp25
-rw-r--r--utils/TableGen/CodeGenInstruction.h32
-rw-r--r--utils/TableGen/CodeGenTarget.cpp10
-rw-r--r--utils/TableGen/DAGISelEmitter.cpp1847
-rw-r--r--utils/TableGen/DAGISelMatcher.cpp118
-rw-r--r--utils/TableGen/DAGISelMatcher.h391
-rw-r--r--utils/TableGen/DAGISelMatcherEmitter.cpp278
-rw-r--r--utils/TableGen/DAGISelMatcherGen.cpp328
-rw-r--r--utils/TableGen/EDEmitter.cpp665
-rw-r--r--utils/TableGen/EDEmitter.h37
-rw-r--r--utils/TableGen/InstrInfoEmitter.cpp17
-rw-r--r--utils/TableGen/LLVMCConfigurationEmitter.cpp19
-rw-r--r--utils/TableGen/TableGen.cpp12
-rw-r--r--utils/TableGen/X86RecognizableInstr.cpp111
-rwxr-xr-xutils/UpdateCMakeLists.pl3
-rw-r--r--utils/lit/lit/ShUtil.py2
-rw-r--r--utils/lit/lit/TestFormats.py27
-rw-r--r--utils/lit/lit/Util.py5
-rw-r--r--utils/llvm.grm1
-rw-r--r--utils/unittest/UnitTestMain/Makefile1
-rw-r--r--utils/unittest/googletest/Makefile1
-rw-r--r--utils/vim/llvm.vim2
33 files changed, 3687 insertions, 1423 deletions
diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp
index 078028a..3c4742c 100644
--- a/utils/FileCheck/FileCheck.cpp
+++ b/utils/FileCheck/FileCheck.cpp
@@ -340,12 +340,10 @@ unsigned Pattern::ComputeMatchDistance(StringRef Buffer,
if (ExampleString.empty())
ExampleString = RegExStr;
- unsigned Distance = 0;
- for (unsigned i = 0, e = ExampleString.size(); i != e; ++i)
- if (Buffer.substr(i, 1) != ExampleString.substr(i, 1))
- ++Distance;
-
- return Distance;
+ // Only compare up to the first line in the buffer, or the string size.
+ StringRef BufferPrefix = Buffer.substr(0, ExampleString.size());
+ BufferPrefix = BufferPrefix.split('\n').first;
+ return BufferPrefix.edit_distance(ExampleString);
}
void Pattern::PrintFailureInfo(const SourceMgr &SM, StringRef Buffer,
@@ -383,10 +381,15 @@ void Pattern::PrintFailureInfo(const SourceMgr &SM, StringRef Buffer,
double BestQuality = 0;
// Use an arbitrary 4k limit on how far we will search.
- for (size_t i = 0, e = std::min(4096, int(Buffer.size())); i != e; ++i) {
+ for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) {
if (Buffer[i] == '\n')
++NumLinesForward;
+ // Patterns have leading whitespace stripped, so skip whitespace when
+ // looking for something which looks like a pattern.
+ if (Buffer[i] == ' ' || Buffer[i] == '\t')
+ continue;
+
// Compute the "quality" of this match as an arbitrary combination of the
// match distance and the number of lines skipped to get to this match.
unsigned Distance = ComputeMatchDistance(Buffer.substr(i), VariableTable);
@@ -529,6 +532,9 @@ static bool ReadCheckFile(SourceMgr &SM,
// Scan ahead to the end of line.
size_t EOL = Buffer.find_first_of("\n\r");
+ // Remember the location of the start of the pattern, for diagnostics.
+ SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());
+
// Parse the pattern.
Pattern P;
if (P.ParsePattern(Buffer.substr(0, EOL), SM))
@@ -555,7 +561,7 @@ static bool ReadCheckFile(SourceMgr &SM,
// Okay, add the string we captured to the output vector and move on.
CheckStrings.push_back(CheckString(P,
- SMLoc::getFromPointer(Buffer.data()),
+ PatternLoc,
IsCheckNext));
std::swap(NotMatches, CheckStrings.back().NotStrings);
}
diff --git a/utils/GenLibDeps.pl b/utils/GenLibDeps.pl
index 6d0b13e..b320a91 100755
--- a/utils/GenLibDeps.pl
+++ b/utils/GenLibDeps.pl
@@ -9,10 +9,12 @@
# Syntax: GenLibDeps.pl [-flat] <directory_with_libraries_in_it> [path_to_nm_binary]
#
use strict;
-
+use warnings;
# Parse arguments...
my $FLAT = 0;
my $WHY = 0;
+my $PEROBJ = 0;
+my $PEROBJINCL = 0;
while (scalar(@ARGV) and ($_ = $ARGV[0], /^[-+]/)) {
shift;
last if /^--$/; # Stop processing arguments on --
@@ -20,6 +22,8 @@ while (scalar(@ARGV) and ($_ = $ARGV[0], /^[-+]/)) {
# List command line options here...
if (/^-flat$/) { $FLAT = 1; next; }
if (/^-why/) { $WHY = 1; $FLAT = 1; next; }
+ if (/^-perobj$/) { $PEROBJ = 1; next; }
+ if (/^-perobjincl/) { $PEROBJINCL = 1; next;}
print "Unknown option: $_ : ignoring!\n";
}
@@ -47,6 +51,19 @@ if (!defined($nmPath) || $nmPath eq "") {
die "Can't find 'nm'" if (! -x "$nmPath");
}
+my $ranlibPath;
+if ($PEROBJ) {
+ $ranlibPath = $ARGV[2];
+ if (defined($ENV{RANLIB})) {
+ chomp($ranlibPath=$ENV{RANLIB});
+ }
+
+ if (!defined($ranlibPath) || $ranlibPath eq "") {
+ chomp($ranlibPath=`which ranlib`);
+ die "Can't find 'ranlib'" if (! -x "$ranlibPath");
+ }
+}
+
# Open the directory and read its contents, sorting by name and differentiating
# by whether its a library (.a) or an object file (.o)
opendir DIR,$Directory;
@@ -60,6 +77,93 @@ my @objs = grep(/LLVM.*\.o$/,sort(@files));
my %libdefs;
my %objdefs;
+my %libobjs;
+my %objdeps=();
+# Gather library definitions at object file granularity (optional)
+if ($PEROBJ) {
+ foreach my $lib (@libs ) {
+ `$ranlibPath $Directory/$lib`;
+ my $libpath = $lib;
+ $libpath =~ s/^libLLVM(.*)\.a/$1/;
+ $libpath =~ s/(.+)CodeGen$/Target\/$1/;
+ $libpath =~ s/(.+)AsmPrinter$/Target\/$1\/AsmPrinter/;
+ $libpath =~ s/(.+)AsmParser$/Target\/$1\/AsmParser/;
+ $libpath =~ s/(.+)Info$/Target\/$1\/TargetInfo/;
+ $libpath =~ s/(.+)Disassembler$/Target\/$1\/Disassembler/;
+ $libpath =~ s/SelectionDAG/CodeGen\/SelectionDAG/;
+ $libpath =~ s/^AsmPrinter/CodeGen\/AsmPrinter/;
+ $libpath =~ s/^BitReader/Bitcode\/Reader/;
+ $libpath =~ s/^BitWriter/Bitcode\/Writer/;
+ $libpath =~ s/^CBackend/Target\/CBackend/;
+ $libpath =~ s/^CppBackend/Target\/CppBackend/;
+ $libpath =~ s/^MSIL/Target\/MSIL/;
+ $libpath =~ s/^Core/VMCore/;
+ $libpath =~ s/^Instrumentation/Transforms\/Instrumentation/;
+ $libpath =~ s/^Interpreter/ExecutionEngine\/Interpreter/;
+ $libpath =~ s/^JIT/ExecutionEngine\/JIT/;
+ $libpath =~ s/^ScalarOpts/Transforms\/Scalar/;
+ $libpath =~ s/^TransformUtils/Transforms\/Utils/;
+ $libpath =~ s/^ipa/Analysis\/IPA/;
+ $libpath =~ s/^ipo/Transforms\/IPO/;
+ $libpath =~ s/^pic16passes/Target\/PIC16\/PIC16Passes/;
+ $libpath = "lib/".$libpath."/";
+ open DEFS, "$nmPath -sg $Directory/$lib|";
+ while (<DEFS>) {
+ chomp;
+ if (/^([^ ]*) in ([^ ]*)/) {
+ my $objfile = $libpath.$2;
+ $objdefs{$1} = $objfile;
+ $objdeps{$objfile} = {};
+ $libobjs{$lib}{$objfile}=1;
+# my $p = "../llvm/".$objfile;
+# $p =~ s/Support\/reg(.*).o/Support\/reg$1.c/;
+# $p =~ s/.o$/.cpp/;
+# unless (-e $p) {
+# die "$p\n"
+# }
+ }
+ }
+ close DEFS or die "nm failed";
+ }
+ foreach my $lib (@libs ) {
+ my $libpath = $lib;
+ $libpath =~ s/^libLLVM(.*)\.a/$1/;
+ $libpath =~ s/(.+)CodeGen$/Target\/$1/;
+ $libpath =~ s/(.+)AsmPrinter$/Target\/$1\/AsmPrinter/;
+ $libpath =~ s/(.+)AsmParser$/Target\/$1\/AsmParser/;
+ $libpath =~ s/(.+)Info$/Target\/$1\/TargetInfo/;
+ $libpath =~ s/(.+)Disassembler$/Target\/$1\/Disassembler/;
+ $libpath =~ s/SelectionDAG/CodeGen\/SelectionDAG/;
+ $libpath =~ s/^AsmPrinter/CodeGen\/AsmPrinter/;
+ $libpath =~ s/^BitReader/Bitcode\/Reader/;
+ $libpath =~ s/^BitWriter/Bitcode\/Writer/;
+ $libpath =~ s/^CBackend/Target\/CBackend/;
+ $libpath =~ s/^CppBackend/Target\/CppBackend/;
+ $libpath =~ s/^MSIL/Target\/MSIL/;
+ $libpath =~ s/^Core/VMCore/;
+ $libpath =~ s/^Instrumentation/Transforms\/Instrumentation/;
+ $libpath =~ s/^Interpreter/ExecutionEngine\/Interpreter/;
+ $libpath =~ s/^JIT/ExecutionEngine\/JIT/;
+ $libpath =~ s/^ScalarOpts/Transforms\/Scalar/;
+ $libpath =~ s/^TransformUtils/Transforms\/Utils/;
+ $libpath =~ s/^ipa/Analysis\/IPA/;
+ $libpath =~ s/^ipo/Transforms\/IPO/;
+ $libpath =~ s/^pic16passes/Target\/PIC16\/PIC16Passes/;
+ $libpath = "lib/".$libpath."/";
+ open UDEFS, "$nmPath -Aup $Directory/$lib|";
+ while (<UDEFS>) {
+ chomp;
+ if (/:([^:]+):/) {
+ my $obj = $libpath.$1;
+ s/[^ ]+: *U //;
+ if (defined($objdefs{$_})) {
+ $objdeps{$obj}{$objdefs{$_}}=1;
+ }
+ }
+ }
+ close UDEFS or die "nm failed"
+ }
+} else {
# Gather definitions from the libraries
foreach my $lib (@libs ) {
open DEFS, "$nmPath -g $Directory/$lib|";
@@ -72,6 +176,7 @@ foreach my $lib (@libs ) {
}
close DEFS or die "nm failed";
}
+}
# Gather definitions from the object files.
foreach my $obj (@objs ) {
@@ -109,6 +214,11 @@ sub gen_one_entry {
$DepLibs{$libdefs{$_}} = [] unless exists $DepLibs{$libdefs{$_}};
push(@{$DepLibs{$libdefs{$_}}}, $_);
} elsif (defined($objdefs{$_}) && $objdefs{$_} ne $lib) {
+ if ($PEROBJ && !$PEROBJINCL) {
+ # -perobjincl makes .a files depend on .o files they contain themselves
+ # default is don't depend on these.
+ next if defined $libobjs{$lib}{$objdefs{$_}};
+ }
my $libroot = $lib;
$libroot =~ s/lib(.*).a/$1/;
if ($objdefs{$_} ne "$libroot.o") {
@@ -144,6 +254,25 @@ sub gen_one_entry {
}
close UNDEFS or die "nm failed";
}
+ if ($PEROBJINCL) {
+ # include the .a's objects
+ for my $obj (keys %{$libobjs{$lib}}) {
+ $DepLibs{$obj} = ["<.a object>"] unless exists $DepLibs{$obj};
+ }
+ my $madechange = 1;
+ while($madechange) {
+ $madechange = 0;
+ my %temp = %DepLibs;
+ foreach my $obj (keys %DepLibs) {
+ foreach my $objdeps (keys %{$objdeps{$obj}}) {
+ next if defined $temp{$objdeps};
+ push(@{$temp{$objdeps}}, $obj);
+ $madechange = 1;
+ }
+ }
+ %DepLibs = %temp;
+ }
+ }
for my $key (sort keys %DepLibs) {
if ($FLAT) {
@@ -209,6 +338,18 @@ foreach my $lib (@libs) {
gen_one_entry($lib);
}
+if ($PEROBJ) {
+ foreach my $obj (keys %objdeps) {
+ print "$obj:";
+ if (!$PEROBJINCL) {
+ foreach my $dep (keys %{$objdeps{$obj}}) {
+ print " $dep";
+ }
+ }
+ print "\n";
+ }
+}
+
if (!$FLAT) {
print DOT "}\n";
close DOT;
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index ce1521d..b823e57 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -140,7 +140,7 @@ static std::string FlattenVariants(const std::string &AsmString,
}
/// TokenizeAsmString - Tokenize a simplified assembly string.
-static void TokenizeAsmString(const StringRef &AsmString,
+static void TokenizeAsmString(StringRef AsmString,
SmallVectorImpl<StringRef> &Tokens) {
unsigned Prev = 0;
bool InTok = true;
@@ -207,7 +207,7 @@ static void TokenizeAsmString(const StringRef &AsmString,
Tokens.push_back(AsmString.substr(Prev));
}
-static bool IsAssemblerInstruction(const StringRef &Name,
+static bool IsAssemblerInstruction(StringRef Name,
const CodeGenInstruction &CGI,
const SmallVectorImpl<StringRef> &Tokens) {
// Ignore "codegen only" instructions.
@@ -528,10 +528,10 @@ private:
private:
/// getTokenClass - Lookup or create the class for the given token.
- ClassInfo *getTokenClass(const StringRef &Token);
+ ClassInfo *getTokenClass(StringRef Token);
/// getOperandClass - Lookup or create the class for the given operand.
- ClassInfo *getOperandClass(const StringRef &Token,
+ ClassInfo *getOperandClass(StringRef Token,
const CodeGenInstruction::OperandInfo &OI);
/// BuildRegisterClasses - Build the ClassInfo* instances for register
@@ -581,7 +581,7 @@ void InstructionInfo::dump() {
}
}
-static std::string getEnumNameForToken(const StringRef &Str) {
+static std::string getEnumNameForToken(StringRef Str) {
std::string Res;
for (StringRef::iterator it = Str.begin(), ie = Str.end(); it != ie; ++it) {
@@ -603,7 +603,7 @@ static std::string getEnumNameForToken(const StringRef &Str) {
}
/// getRegisterRecord - Get the register record for \arg name, or 0.
-static Record *getRegisterRecord(CodeGenTarget &Target, const StringRef &Name) {
+static Record *getRegisterRecord(CodeGenTarget &Target, StringRef Name) {
for (unsigned i = 0, e = Target.getRegisters().size(); i != e; ++i) {
const CodeGenRegister &Reg = Target.getRegisters()[i];
if (Name == Reg.TheDef->getValueAsString("AsmName"))
@@ -613,7 +613,7 @@ static Record *getRegisterRecord(CodeGenTarget &Target, const StringRef &Name) {
return 0;
}
-ClassInfo *AsmMatcherInfo::getTokenClass(const StringRef &Token) {
+ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) {
ClassInfo *&Entry = TokenClasses[Token];
if (!Entry) {
@@ -631,7 +631,7 @@ ClassInfo *AsmMatcherInfo::getTokenClass(const StringRef &Token) {
}
ClassInfo *
-AsmMatcherInfo::getOperandClass(const StringRef &Token,
+AsmMatcherInfo::getOperandClass(StringRef Token,
const CodeGenInstruction::OperandInfo &OI) {
if (OI.Rec->isSubClassOf("RegisterClass")) {
ClassInfo *CI = RegisterClassClasses[OI.Rec];
@@ -782,10 +782,16 @@ void AsmMatcherInfo::BuildRegisterClasses(CodeGenTarget &Target,
void AsmMatcherInfo::BuildOperandClasses(CodeGenTarget &Target) {
std::vector<Record*> AsmOperands;
AsmOperands = Records.getAllDerivedDefinitions("AsmOperandClass");
+
+ // Pre-populate AsmOperandClasses map.
+ for (std::vector<Record*>::iterator it = AsmOperands.begin(),
+ ie = AsmOperands.end(); it != ie; ++it)
+ AsmOperandClasses[*it] = new ClassInfo();
+
unsigned Index = 0;
for (std::vector<Record*>::iterator it = AsmOperands.begin(),
ie = AsmOperands.end(); it != ie; ++it, ++Index) {
- ClassInfo *CI = new ClassInfo();
+ ClassInfo *CI = AsmOperandClasses[*it];
CI->Kind = ClassInfo::UserClass0 + Index;
Init *Super = (*it)->getValueInit("SuperClass");
@@ -938,10 +944,29 @@ void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) {
OperandName.str() + "'");
}
- const CodeGenInstruction::OperandInfo &OI = II->Instr->OperandList[Idx];
+ // FIXME: This is annoying, the named operand may be tied (e.g.,
+ // XCHG8rm). What we want is the untied operand, which we now have to
+ // grovel for. Only worry about this for single entry operands, we have to
+ // clean this up anyway.
+ const CodeGenInstruction::OperandInfo *OI = &II->Instr->OperandList[Idx];
+ if (OI->Constraints[0].isTied()) {
+ unsigned TiedOp = OI->Constraints[0].getTiedOperand();
+
+ // The tied operand index is an MIOperand index, find the operand that
+ // contains it.
+ for (unsigned i = 0, e = II->Instr->OperandList.size(); i != e; ++i) {
+ if (II->Instr->OperandList[i].MIOperandNo == TiedOp) {
+ OI = &II->Instr->OperandList[i];
+ break;
+ }
+ }
+
+ assert(OI && "Unable to find tied operand target!");
+ }
+
InstructionInfo::Operand Op;
- Op.Class = getOperandClass(Token, OI);
- Op.OperandInfo = &OI;
+ Op.Class = getOperandClass(Token, *OI);
+ Op.OperandInfo = OI;
II->Operands.push_back(Op);
}
}
@@ -950,6 +975,16 @@ void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) {
std::sort(Classes.begin(), Classes.end(), less_ptr<ClassInfo>());
}
+static std::pair<unsigned, unsigned> *
+GetTiedOperandAtIndex(SmallVectorImpl<std::pair<unsigned, unsigned> > &List,
+ unsigned Index) {
+ for (unsigned i = 0, e = List.size(); i != e; ++i)
+ if (Index == List[i].first)
+ return &List[i];
+
+ return 0;
+}
+
static void EmitConvertToMCInst(CodeGenTarget &Target,
std::vector<InstructionInfo*> &Infos,
raw_ostream &OS) {
@@ -990,6 +1025,19 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
if (Op.OperandInfo)
MIOperandList.push_back(std::make_pair(Op.OperandInfo->MIOperandNo, i));
}
+
+ // Find any tied operands.
+ SmallVector<std::pair<unsigned, unsigned>, 4> TiedOperands;
+ for (unsigned i = 0, e = II.Instr->OperandList.size(); i != e; ++i) {
+ const CodeGenInstruction::OperandInfo &OpInfo = II.Instr->OperandList[i];
+ for (unsigned j = 0, e = OpInfo.Constraints.size(); j != e; ++j) {
+ const CodeGenInstruction::ConstraintInfo &CI = OpInfo.Constraints[j];
+ if (CI.isTied())
+ TiedOperands.push_back(std::make_pair(OpInfo.MIOperandNo + j,
+ CI.getTiedOperand()));
+ }
+ }
+
std::sort(MIOperandList.begin(), MIOperandList.end());
// Compute the total number of operands.
@@ -1008,14 +1056,20 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
assert(CurIndex <= Op.OperandInfo->MIOperandNo &&
"Duplicate match for instruction operand!");
- Signature += "_";
-
// Skip operands which weren't matched by anything, this occurs when the
// .td file encodes "implicit" operands as explicit ones.
//
// FIXME: This should be removed from the MCInst structure.
- for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex)
- Signature += "Imp";
+ for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex) {
+ std::pair<unsigned, unsigned> *Tie = GetTiedOperandAtIndex(TiedOperands,
+ CurIndex);
+ if (!Tie)
+ Signature += "__Imp";
+ else
+ Signature += "__Tie" + utostr(Tie->second);
+ }
+
+ Signature += "__";
// Registers are always converted the same, don't duplicate the conversion
// function based on them.
@@ -1033,8 +1087,14 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
}
// Add any trailing implicit operands.
- for (; CurIndex != NumMIOperands; ++CurIndex)
- Signature += "Imp";
+ for (; CurIndex != NumMIOperands; ++CurIndex) {
+ std::pair<unsigned, unsigned> *Tie = GetTiedOperandAtIndex(TiedOperands,
+ CurIndex);
+ if (!Tie)
+ Signature += "__Imp";
+ else
+ Signature += "__Tie" + utostr(Tie->second);
+ }
II.ConversionFnKind = Signature;
@@ -1054,8 +1114,22 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
InstructionInfo::Operand &Op = II.Operands[MIOperandList[i].second];
// Add the implicit operands.
- for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex)
- CvtOS << " Inst.addOperand(MCOperand::CreateReg(0));\n";
+ for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex) {
+ // See if this is a tied operand.
+ std::pair<unsigned, unsigned> *Tie = GetTiedOperandAtIndex(TiedOperands,
+ CurIndex);
+
+ if (!Tie) {
+ // If not, this is some implicit operand. Just assume it is a register
+ // for now.
+ CvtOS << " Inst.addOperand(MCOperand::CreateReg(0));\n";
+ } else {
+ // Copy the tied operand.
+ assert(Tie->first>Tie->second && "Tied operand preceeds its target!");
+ CvtOS << " Inst.addOperand(Inst.getOperand("
+ << Tie->second << "));\n";
+ }
+ }
CvtOS << " ((" << TargetOperandClass << "*)Operands["
<< MIOperandList[i].second
@@ -1065,8 +1139,22 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
}
// And add trailing implicit operands.
- for (; CurIndex != NumMIOperands; ++CurIndex)
- CvtOS << " Inst.addOperand(MCOperand::CreateReg(0));\n";
+ for (; CurIndex != NumMIOperands; ++CurIndex) {
+ std::pair<unsigned, unsigned> *Tie = GetTiedOperandAtIndex(TiedOperands,
+ CurIndex);
+
+ if (!Tie) {
+ // If not, this is some implicit operand. Just assume it is a register
+ // for now.
+ CvtOS << " Inst.addOperand(MCOperand::CreateReg(0));\n";
+ } else {
+ // Copy the tied operand.
+ assert(Tie->first>Tie->second && "Tied operand preceeds its target!");
+ CvtOS << " Inst.addOperand(Inst.getOperand("
+ << Tie->second << "));\n";
+ }
+ }
+
CvtOS << " break;\n";
}
@@ -1367,7 +1455,7 @@ static void EmitMatchTokenString(CodeGenTarget &Target,
Matches.push_back(StringPair(CI.ValueName, "return " + CI.Name + ";"));
}
- OS << "static MatchClassKind MatchTokenString(const StringRef &Name) {\n";
+ OS << "static MatchClassKind MatchTokenString(StringRef Name) {\n";
EmitStringMatcher("Name", Matches, OS);
@@ -1390,7 +1478,7 @@ static void EmitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser,
"return " + utostr(i + 1) + ";"));
}
- OS << "static unsigned MatchRegisterName(const StringRef &Name) {\n";
+ OS << "static unsigned MatchRegisterName(StringRef Name) {\n";
EmitStringMatcher("Name", Matches, OS);
@@ -1407,9 +1495,11 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
AsmMatcherInfo Info(AsmParser);
Info.BuildInfo(Target);
- // Sort the instruction table using the partial order on classes.
- std::sort(Info.Instructions.begin(), Info.Instructions.end(),
- less_ptr<InstructionInfo>());
+ // Sort the instruction table using the partial order on classes. We use
+ // stable_sort to ensure that ambiguous instructions are still
+ // deterministically ordered.
+ std::stable_sort(Info.Instructions.begin(), Info.Instructions.end(),
+ less_ptr<InstructionInfo>());
DEBUG_WITH_TYPE("instruction_info", {
for (std::vector<InstructionInfo*>::iterator
diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp
index ff83c76..3a38dd4 100644
--- a/utils/TableGen/AsmWriterEmitter.cpp
+++ b/utils/TableGen/AsmWriterEmitter.cpp
@@ -13,339 +13,15 @@
//===----------------------------------------------------------------------===//
#include "AsmWriterEmitter.h"
+#include "AsmWriterInst.h"
#include "CodeGenTarget.h"
#include "Record.h"
#include "StringToOffsetTable.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
#include <algorithm>
using namespace llvm;
-
-static bool isIdentChar(char C) {
- return (C >= 'a' && C <= 'z') ||
- (C >= 'A' && C <= 'Z') ||
- (C >= '0' && C <= '9') ||
- C == '_';
-}
-
-// This should be an anon namespace, this works around a GCC warning.
-namespace llvm {
- struct AsmWriterOperand {
- enum OpType {
- // Output this text surrounded by quotes to the asm.
- isLiteralTextOperand,
- // This is the name of a routine to call to print the operand.
- isMachineInstrOperand,
- // Output this text verbatim to the asm writer. It is code that
- // will output some text to the asm.
- isLiteralStatementOperand
- } OperandType;
-
- /// Str - For isLiteralTextOperand, this IS the literal text. For
- /// isMachineInstrOperand, this is the PrinterMethodName for the operand..
- /// For isLiteralStatementOperand, this is the code to insert verbatim
- /// into the asm writer.
- std::string Str;
-
- /// MiOpNo - For isMachineInstrOperand, this is the operand number of the
- /// machine instruction.
- unsigned MIOpNo;
-
- /// MiModifier - For isMachineInstrOperand, this is the modifier string for
- /// an operand, specified with syntax like ${opname:modifier}.
- std::string MiModifier;
-
- // To make VS STL happy
- AsmWriterOperand(OpType op = isLiteralTextOperand):OperandType(op) {}
-
- AsmWriterOperand(const std::string &LitStr,
- OpType op = isLiteralTextOperand)
- : OperandType(op), Str(LitStr) {}
-
- AsmWriterOperand(const std::string &Printer, unsigned OpNo,
- const std::string &Modifier,
- OpType op = isMachineInstrOperand)
- : OperandType(op), Str(Printer), MIOpNo(OpNo),
- MiModifier(Modifier) {}
-
- bool operator!=(const AsmWriterOperand &Other) const {
- if (OperandType != Other.OperandType || Str != Other.Str) return true;
- if (OperandType == isMachineInstrOperand)
- return MIOpNo != Other.MIOpNo || MiModifier != Other.MiModifier;
- return false;
- }
- bool operator==(const AsmWriterOperand &Other) const {
- return !operator!=(Other);
- }
-
- /// getCode - Return the code that prints this operand.
- std::string getCode() const;
- };
-}
-
-namespace llvm {
- class AsmWriterInst {
- public:
- std::vector<AsmWriterOperand> Operands;
- const CodeGenInstruction *CGI;
-
- AsmWriterInst(const CodeGenInstruction &CGI, Record *AsmWriter);
-
- /// MatchesAllButOneOp - If this instruction is exactly identical to the
- /// specified instruction except for one differing operand, return the
- /// differing operand number. Otherwise return ~0.
- unsigned MatchesAllButOneOp(const AsmWriterInst &Other) const;
-
- private:
- void AddLiteralString(const std::string &Str) {
- // If the last operand was already a literal text string, append this to
- // it, otherwise add a new operand.
- if (!Operands.empty() &&
- Operands.back().OperandType == AsmWriterOperand::isLiteralTextOperand)
- Operands.back().Str.append(Str);
- else
- Operands.push_back(AsmWriterOperand(Str));
- }
- };
-}
-
-
-std::string AsmWriterOperand::getCode() const {
- if (OperandType == isLiteralTextOperand) {
- if (Str.size() == 1)
- return "O << '" + Str + "'; ";
- return "O << \"" + Str + "\"; ";
- }
-
- if (OperandType == isLiteralStatementOperand)
- return Str;
-
- std::string Result = Str + "(MI";
- if (MIOpNo != ~0U)
- Result += ", " + utostr(MIOpNo);
- if (!MiModifier.empty())
- Result += ", \"" + MiModifier + '"';
- return Result + "); ";
-}
-
-
-/// ParseAsmString - Parse the specified Instruction's AsmString into this
-/// AsmWriterInst.
-///
-AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, Record *AsmWriter) {
- this->CGI = &CGI;
-
- unsigned Variant = AsmWriter->getValueAsInt("Variant");
- int FirstOperandColumn = AsmWriter->getValueAsInt("FirstOperandColumn");
- int OperandSpacing = AsmWriter->getValueAsInt("OperandSpacing");
-
- unsigned CurVariant = ~0U; // ~0 if we are outside a {.|.|.} region, other #.
-
- // This is the number of tabs we've seen if we're doing columnar layout.
- unsigned CurColumn = 0;
-
-
- // NOTE: Any extensions to this code need to be mirrored in the
- // AsmPrinter::printInlineAsm code that executes as compile time (assuming
- // that inline asm strings should also get the new feature)!
- const std::string &AsmString = CGI.AsmString;
- std::string::size_type LastEmitted = 0;
- while (LastEmitted != AsmString.size()) {
- std::string::size_type DollarPos =
- AsmString.find_first_of("${|}\\", LastEmitted);
- if (DollarPos == std::string::npos) DollarPos = AsmString.size();
-
- // Emit a constant string fragment.
-
- if (DollarPos != LastEmitted) {
- if (CurVariant == Variant || CurVariant == ~0U) {
- for (; LastEmitted != DollarPos; ++LastEmitted)
- switch (AsmString[LastEmitted]) {
- case '\n':
- AddLiteralString("\\n");
- break;
- case '\t':
- // If the asm writer is not using a columnar layout, \t is not
- // magic.
- if (FirstOperandColumn == -1 || OperandSpacing == -1) {
- AddLiteralString("\\t");
- } else {
- // We recognize a tab as an operand delimeter.
- unsigned DestColumn = FirstOperandColumn +
- CurColumn++ * OperandSpacing;
- Operands.push_back(
- AsmWriterOperand("O.PadToColumn(" +
- utostr(DestColumn) + ");\n",
- AsmWriterOperand::isLiteralStatementOperand));
- }
- break;
- case '"':
- AddLiteralString("\\\"");
- break;
- case '\\':
- AddLiteralString("\\\\");
- break;
- default:
- AddLiteralString(std::string(1, AsmString[LastEmitted]));
- break;
- }
- } else {
- LastEmitted = DollarPos;
- }
- } else if (AsmString[DollarPos] == '\\') {
- if (DollarPos+1 != AsmString.size() &&
- (CurVariant == Variant || CurVariant == ~0U)) {
- if (AsmString[DollarPos+1] == 'n') {
- AddLiteralString("\\n");
- } else if (AsmString[DollarPos+1] == 't') {
- // If the asm writer is not using a columnar layout, \t is not
- // magic.
- if (FirstOperandColumn == -1 || OperandSpacing == -1) {
- AddLiteralString("\\t");
- break;
- }
-
- // We recognize a tab as an operand delimeter.
- unsigned DestColumn = FirstOperandColumn +
- CurColumn++ * OperandSpacing;
- Operands.push_back(
- AsmWriterOperand("O.PadToColumn(" + utostr(DestColumn) + ");\n",
- AsmWriterOperand::isLiteralStatementOperand));
- break;
- } else if (std::string("${|}\\").find(AsmString[DollarPos+1])
- != std::string::npos) {
- AddLiteralString(std::string(1, AsmString[DollarPos+1]));
- } else {
- throw "Non-supported escaped character found in instruction '" +
- CGI.TheDef->getName() + "'!";
- }
- LastEmitted = DollarPos+2;
- continue;
- }
- } else if (AsmString[DollarPos] == '{') {
- if (CurVariant != ~0U)
- throw "Nested variants found for instruction '" +
- CGI.TheDef->getName() + "'!";
- LastEmitted = DollarPos+1;
- CurVariant = 0; // We are now inside of the variant!
- } else if (AsmString[DollarPos] == '|') {
- if (CurVariant == ~0U)
- throw "'|' character found outside of a variant in instruction '"
- + CGI.TheDef->getName() + "'!";
- ++CurVariant;
- ++LastEmitted;
- } else if (AsmString[DollarPos] == '}') {
- if (CurVariant == ~0U)
- throw "'}' character found outside of a variant in instruction '"
- + CGI.TheDef->getName() + "'!";
- ++LastEmitted;
- CurVariant = ~0U;
- } else if (DollarPos+1 != AsmString.size() &&
- AsmString[DollarPos+1] == '$') {
- if (CurVariant == Variant || CurVariant == ~0U) {
- AddLiteralString("$"); // "$$" -> $
- }
- LastEmitted = DollarPos+2;
- } else {
- // Get the name of the variable.
- std::string::size_type VarEnd = DollarPos+1;
-
- // handle ${foo}bar as $foo by detecting whether the character following
- // the dollar sign is a curly brace. If so, advance VarEnd and DollarPos
- // so the variable name does not contain the leading curly brace.
- bool hasCurlyBraces = false;
- if (VarEnd < AsmString.size() && '{' == AsmString[VarEnd]) {
- hasCurlyBraces = true;
- ++DollarPos;
- ++VarEnd;
- }
-
- while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
- ++VarEnd;
- std::string VarName(AsmString.begin()+DollarPos+1,
- AsmString.begin()+VarEnd);
-
- // Modifier - Support ${foo:modifier} syntax, where "modifier" is passed
- // into printOperand. Also support ${:feature}, which is passed into
- // PrintSpecial.
- std::string Modifier;
-
- // In order to avoid starting the next string at the terminating curly
- // brace, advance the end position past it if we found an opening curly
- // brace.
- if (hasCurlyBraces) {
- if (VarEnd >= AsmString.size())
- throw "Reached end of string before terminating curly brace in '"
- + CGI.TheDef->getName() + "'";
-
- // Look for a modifier string.
- if (AsmString[VarEnd] == ':') {
- ++VarEnd;
- if (VarEnd >= AsmString.size())
- throw "Reached end of string before terminating curly brace in '"
- + CGI.TheDef->getName() + "'";
-
- unsigned ModifierStart = VarEnd;
- while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
- ++VarEnd;
- Modifier = std::string(AsmString.begin()+ModifierStart,
- AsmString.begin()+VarEnd);
- if (Modifier.empty())
- throw "Bad operand modifier name in '"+ CGI.TheDef->getName() + "'";
- }
-
- if (AsmString[VarEnd] != '}')
- throw "Variable name beginning with '{' did not end with '}' in '"
- + CGI.TheDef->getName() + "'";
- ++VarEnd;
- }
- if (VarName.empty() && Modifier.empty())
- throw "Stray '$' in '" + CGI.TheDef->getName() +
- "' asm string, maybe you want $$?";
-
- if (VarName.empty()) {
- // Just a modifier, pass this into PrintSpecial.
- Operands.push_back(AsmWriterOperand("PrintSpecial", ~0U, Modifier));
- } else {
- // Otherwise, normal operand.
- unsigned OpNo = CGI.getOperandNamed(VarName);
- CodeGenInstruction::OperandInfo OpInfo = CGI.OperandList[OpNo];
-
- if (CurVariant == Variant || CurVariant == ~0U) {
- unsigned MIOp = OpInfo.MIOperandNo;
- Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName, MIOp,
- Modifier));
- }
- }
- LastEmitted = VarEnd;
- }
- }
-
- Operands.push_back(AsmWriterOperand("return;",
- AsmWriterOperand::isLiteralStatementOperand));
-}
-
-/// MatchesAllButOneOp - If this instruction is exactly identical to the
-/// specified instruction except for one differing operand, return the differing
-/// operand number. If more than one operand mismatches, return ~1, otherwise
-/// if the instructions are identical return ~0.
-unsigned AsmWriterInst::MatchesAllButOneOp(const AsmWriterInst &Other)const{
- if (Operands.size() != Other.Operands.size()) return ~1;
-
- unsigned MismatchOperand = ~0U;
- for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
- if (Operands[i] != Other.Operands[i]) {
- if (MismatchOperand != ~0U) // Already have one mismatch?
- return ~1U;
- else
- MismatchOperand = i;
- }
- }
- return MismatchOperand;
-}
-
static void PrintCases(std::vector<std::pair<std::string,
AsmWriterOperand> > &OpsToPrint, raw_ostream &O) {
O << " case " << OpsToPrint.back().first << ": ";
@@ -580,7 +256,11 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
E = Target.inst_end(); I != E; ++I)
if (!I->second.AsmString.empty() &&
I->second.TheDef->getName() != "PHI")
- Instructions.push_back(AsmWriterInst(I->second, AsmWriter));
+ Instructions.push_back(
+ AsmWriterInst(I->second,
+ AsmWriter->getValueAsInt("Variant"),
+ AsmWriter->getValueAsInt("FirstOperandColumn"),
+ AsmWriter->getValueAsInt("OperandSpacing")));
// Get the instruction numbering.
Target.getInstructionsByEnumValue(NumberedInstructions);
@@ -692,24 +372,6 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
StringTable.EmitString(O);
O << ";\n\n";
- O << "\n#ifndef NO_ASM_WRITER_BOILERPLATE\n";
-
- O << " if (MI->getOpcode() == TargetInstrInfo::INLINEASM) {\n"
- << " printInlineAsm(MI);\n"
- << " return;\n"
- << " } else if (MI->isLabel()) {\n"
- << " printLabel(MI);\n"
- << " return;\n"
- << " } else if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) {\n"
- << " printImplicitDef(MI);\n"
- << " return;\n"
- << " } else if (MI->getOpcode() == TargetInstrInfo::KILL) {\n"
- << " printKill(MI);\n"
- << " return;\n"
- << " }\n\n";
-
- O << "\n#endif\n";
-
O << " O << \"\\t\";\n\n";
O << " // Emit the opcode for the instruction.\n"
@@ -832,11 +494,55 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
<< "}\n";
}
+void AsmWriterEmitter::EmitGetInstructionName(raw_ostream &O) {
+ CodeGenTarget Target;
+ Record *AsmWriter = Target.getAsmWriter();
+ std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
+
+ std::vector<const CodeGenInstruction*> NumberedInstructions;
+ Target.getInstructionsByEnumValue(NumberedInstructions);
+
+ StringToOffsetTable StringTable;
+ O <<
+"\n\n#ifdef GET_INSTRUCTION_NAME\n"
+"#undef GET_INSTRUCTION_NAME\n\n"
+"/// getInstructionName: This method is automatically generated by tblgen\n"
+"/// from the instruction set description. This returns the enum name of the\n"
+"/// specified instruction.\n"
+ "const char *" << Target.getName() << ClassName
+ << "::getInstructionName(unsigned Opcode) {\n"
+ << " assert(Opcode < " << NumberedInstructions.size()
+ << " && \"Invalid instruction number!\");\n"
+ << "\n"
+ << " static const unsigned InstAsmOffset[] = {";
+ for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
+ const CodeGenInstruction &Inst = *NumberedInstructions[i];
+
+ std::string AsmName = Inst.TheDef->getName();
+ if ((i % 14) == 0)
+ O << "\n ";
+
+ O << StringTable.GetOrAddStringOffset(AsmName) << ", ";
+ }
+ O << "0\n"
+ << " };\n"
+ << "\n";
+
+ O << " const char *Strs =\n";
+ StringTable.EmitString(O);
+ O << ";\n";
+
+ O << " return Strs+InstAsmOffset[Opcode];\n"
+ << "}\n\n#endif\n";
+}
+
+
void AsmWriterEmitter::run(raw_ostream &O) {
EmitSourceFileHeader("Assembly Writer Source Fragment", O);
EmitPrintInstruction(O);
EmitGetRegisterName(O);
+ EmitGetInstructionName(O);
}
diff --git a/utils/TableGen/AsmWriterEmitter.h b/utils/TableGen/AsmWriterEmitter.h
index 7862caa..9f7d776 100644
--- a/utils/TableGen/AsmWriterEmitter.h
+++ b/utils/TableGen/AsmWriterEmitter.h
@@ -37,6 +37,7 @@ namespace llvm {
private:
void EmitPrintInstruction(raw_ostream &o);
void EmitGetRegisterName(raw_ostream &o);
+ void EmitGetInstructionName(raw_ostream &o);
AsmWriterInst *getAsmWriterInstByID(unsigned ID) const {
assert(ID < NumberedInstructions.size());
diff --git a/utils/TableGen/AsmWriterInst.cpp b/utils/TableGen/AsmWriterInst.cpp
new file mode 100644
index 0000000..508e453
--- /dev/null
+++ b/utils/TableGen/AsmWriterInst.cpp
@@ -0,0 +1,264 @@
+//===- AsmWriterInst.h - Classes encapsulating a printable inst -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These classes implement a parser for assembly strings.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AsmWriterInst.h"
+#include "CodeGenTarget.h"
+#include "Record.h"
+#include "llvm/ADT/StringExtras.h"
+
+using namespace llvm;
+
+static bool isIdentChar(char C) {
+ return (C >= 'a' && C <= 'z') ||
+ (C >= 'A' && C <= 'Z') ||
+ (C >= '0' && C <= '9') ||
+ C == '_';
+}
+
+std::string AsmWriterOperand::getCode() const {
+ if (OperandType == isLiteralTextOperand) {
+ if (Str.size() == 1)
+ return "O << '" + Str + "'; ";
+ return "O << \"" + Str + "\"; ";
+ }
+
+ if (OperandType == isLiteralStatementOperand)
+ return Str;
+
+ std::string Result = Str + "(MI";
+ if (MIOpNo != ~0U)
+ Result += ", " + utostr(MIOpNo);
+ if (!MiModifier.empty())
+ Result += ", \"" + MiModifier + '"';
+ return Result + "); ";
+}
+
+/// ParseAsmString - Parse the specified Instruction's AsmString into this
+/// AsmWriterInst.
+///
+AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI,
+ unsigned Variant,
+ int FirstOperandColumn,
+ int OperandSpacing) {
+ this->CGI = &CGI;
+
+ unsigned CurVariant = ~0U; // ~0 if we are outside a {.|.|.} region, other #.
+
+ // This is the number of tabs we've seen if we're doing columnar layout.
+ unsigned CurColumn = 0;
+
+
+ // NOTE: Any extensions to this code need to be mirrored in the
+ // AsmPrinter::printInlineAsm code that executes as compile time (assuming
+ // that inline asm strings should also get the new feature)!
+ const std::string &AsmString = CGI.AsmString;
+ std::string::size_type LastEmitted = 0;
+ while (LastEmitted != AsmString.size()) {
+ std::string::size_type DollarPos =
+ AsmString.find_first_of("${|}\\", LastEmitted);
+ if (DollarPos == std::string::npos) DollarPos = AsmString.size();
+
+ // Emit a constant string fragment.
+
+ if (DollarPos != LastEmitted) {
+ if (CurVariant == Variant || CurVariant == ~0U) {
+ for (; LastEmitted != DollarPos; ++LastEmitted)
+ switch (AsmString[LastEmitted]) {
+ case '\n':
+ AddLiteralString("\\n");
+ break;
+ case '\t':
+ // If the asm writer is not using a columnar layout, \t is not
+ // magic.
+ if (FirstOperandColumn == -1 || OperandSpacing == -1) {
+ AddLiteralString("\\t");
+ } else {
+ // We recognize a tab as an operand delimeter.
+ unsigned DestColumn = FirstOperandColumn +
+ CurColumn++ * OperandSpacing;
+ Operands.push_back(
+ AsmWriterOperand(
+ "O.PadToColumn(" +
+ utostr(DestColumn) + ");\n",
+ AsmWriterOperand::isLiteralStatementOperand));
+ }
+ break;
+ case '"':
+ AddLiteralString("\\\"");
+ break;
+ case '\\':
+ AddLiteralString("\\\\");
+ break;
+ default:
+ AddLiteralString(std::string(1, AsmString[LastEmitted]));
+ break;
+ }
+ } else {
+ LastEmitted = DollarPos;
+ }
+ } else if (AsmString[DollarPos] == '\\') {
+ if (DollarPos+1 != AsmString.size() &&
+ (CurVariant == Variant || CurVariant == ~0U)) {
+ if (AsmString[DollarPos+1] == 'n') {
+ AddLiteralString("\\n");
+ } else if (AsmString[DollarPos+1] == 't') {
+ // If the asm writer is not using a columnar layout, \t is not
+ // magic.
+ if (FirstOperandColumn == -1 || OperandSpacing == -1) {
+ AddLiteralString("\\t");
+ break;
+ }
+
+ // We recognize a tab as an operand delimeter.
+ unsigned DestColumn = FirstOperandColumn +
+ CurColumn++ * OperandSpacing;
+ Operands.push_back(
+ AsmWriterOperand("O.PadToColumn(" + utostr(DestColumn) + ");\n",
+ AsmWriterOperand::isLiteralStatementOperand));
+ break;
+ } else if (std::string("${|}\\").find(AsmString[DollarPos+1])
+ != std::string::npos) {
+ AddLiteralString(std::string(1, AsmString[DollarPos+1]));
+ } else {
+ throw "Non-supported escaped character found in instruction '" +
+ CGI.TheDef->getName() + "'!";
+ }
+ LastEmitted = DollarPos+2;
+ continue;
+ }
+ } else if (AsmString[DollarPos] == '{') {
+ if (CurVariant != ~0U)
+ throw "Nested variants found for instruction '" +
+ CGI.TheDef->getName() + "'!";
+ LastEmitted = DollarPos+1;
+ CurVariant = 0; // We are now inside of the variant!
+ } else if (AsmString[DollarPos] == '|') {
+ if (CurVariant == ~0U)
+ throw "'|' character found outside of a variant in instruction '"
+ + CGI.TheDef->getName() + "'!";
+ ++CurVariant;
+ ++LastEmitted;
+ } else if (AsmString[DollarPos] == '}') {
+ if (CurVariant == ~0U)
+ throw "'}' character found outside of a variant in instruction '"
+ + CGI.TheDef->getName() + "'!";
+ ++LastEmitted;
+ CurVariant = ~0U;
+ } else if (DollarPos+1 != AsmString.size() &&
+ AsmString[DollarPos+1] == '$') {
+ if (CurVariant == Variant || CurVariant == ~0U) {
+ AddLiteralString("$"); // "$$" -> $
+ }
+ LastEmitted = DollarPos+2;
+ } else {
+ // Get the name of the variable.
+ std::string::size_type VarEnd = DollarPos+1;
+
+ // handle ${foo}bar as $foo by detecting whether the character following
+ // the dollar sign is a curly brace. If so, advance VarEnd and DollarPos
+ // so the variable name does not contain the leading curly brace.
+ bool hasCurlyBraces = false;
+ if (VarEnd < AsmString.size() && '{' == AsmString[VarEnd]) {
+ hasCurlyBraces = true;
+ ++DollarPos;
+ ++VarEnd;
+ }
+
+ while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
+ ++VarEnd;
+ std::string VarName(AsmString.begin()+DollarPos+1,
+ AsmString.begin()+VarEnd);
+
+ // Modifier - Support ${foo:modifier} syntax, where "modifier" is passed
+ // into printOperand. Also support ${:feature}, which is passed into
+ // PrintSpecial.
+ std::string Modifier;
+
+ // In order to avoid starting the next string at the terminating curly
+ // brace, advance the end position past it if we found an opening curly
+ // brace.
+ if (hasCurlyBraces) {
+ if (VarEnd >= AsmString.size())
+ throw "Reached end of string before terminating curly brace in '"
+ + CGI.TheDef->getName() + "'";
+
+ // Look for a modifier string.
+ if (AsmString[VarEnd] == ':') {
+ ++VarEnd;
+ if (VarEnd >= AsmString.size())
+ throw "Reached end of string before terminating curly brace in '"
+ + CGI.TheDef->getName() + "'";
+
+ unsigned ModifierStart = VarEnd;
+ while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
+ ++VarEnd;
+ Modifier = std::string(AsmString.begin()+ModifierStart,
+ AsmString.begin()+VarEnd);
+ if (Modifier.empty())
+ throw "Bad operand modifier name in '"+ CGI.TheDef->getName() + "'";
+ }
+
+ if (AsmString[VarEnd] != '}')
+ throw "Variable name beginning with '{' did not end with '}' in '"
+ + CGI.TheDef->getName() + "'";
+ ++VarEnd;
+ }
+ if (VarName.empty() && Modifier.empty())
+ throw "Stray '$' in '" + CGI.TheDef->getName() +
+ "' asm string, maybe you want $$?";
+
+ if (VarName.empty()) {
+ // Just a modifier, pass this into PrintSpecial.
+ Operands.push_back(AsmWriterOperand("PrintSpecial",
+ ~0U,
+ ~0U,
+ Modifier));
+ } else {
+ // Otherwise, normal operand.
+ unsigned OpNo = CGI.getOperandNamed(VarName);
+ CodeGenInstruction::OperandInfo OpInfo = CGI.OperandList[OpNo];
+
+ if (CurVariant == Variant || CurVariant == ~0U) {
+ unsigned MIOp = OpInfo.MIOperandNo;
+ Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName,
+ OpNo,
+ MIOp,
+ Modifier));
+ }
+ }
+ LastEmitted = VarEnd;
+ }
+ }
+
+ Operands.push_back(AsmWriterOperand("return;",
+ AsmWriterOperand::isLiteralStatementOperand));
+}
+
+/// MatchesAllButOneOp - If this instruction is exactly identical to the
+/// specified instruction except for one differing operand, return the differing
+/// operand number. If more than one operand mismatches, return ~1, otherwise
+/// if the instructions are identical return ~0.
+unsigned AsmWriterInst::MatchesAllButOneOp(const AsmWriterInst &Other)const{
+ if (Operands.size() != Other.Operands.size()) return ~1;
+
+ unsigned MismatchOperand = ~0U;
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ if (Operands[i] != Other.Operands[i]) {
+ if (MismatchOperand != ~0U) // Already have one mismatch?
+ return ~1U;
+ else
+ MismatchOperand = i;
+ }
+ }
+ return MismatchOperand;
+}
diff --git a/utils/TableGen/AsmWriterInst.h b/utils/TableGen/AsmWriterInst.h
new file mode 100644
index 0000000..20b8588
--- /dev/null
+++ b/utils/TableGen/AsmWriterInst.h
@@ -0,0 +1,113 @@
+//===- AsmWriterInst.h - Classes encapsulating a printable inst -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These classes implement a parser for assembly strings. The parser splits
+// the string into operands, which can be literal strings (the constant bits of
+// the string), actual operands (i.e., operands from the MachineInstr), and
+// dynamically-generated text, specified by raw C++ code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ASMWRITER_INST_H
+#define ASMWRITER_INST_H
+
+#include <string>
+#include <vector>
+
+namespace llvm {
+ class CodeGenInstruction;
+ class Record;
+
+ struct AsmWriterOperand {
+ enum OpType {
+ // Output this text surrounded by quotes to the asm.
+ isLiteralTextOperand,
+ // This is the name of a routine to call to print the operand.
+ isMachineInstrOperand,
+ // Output this text verbatim to the asm writer. It is code that
+ // will output some text to the asm.
+ isLiteralStatementOperand
+ } OperandType;
+
+ /// Str - For isLiteralTextOperand, this IS the literal text. For
+ /// isMachineInstrOperand, this is the PrinterMethodName for the operand..
+ /// For isLiteralStatementOperand, this is the code to insert verbatim
+ /// into the asm writer.
+ std::string Str;
+
+ /// CGIOpNo - For isMachineInstrOperand, this is the index of the operand in
+ /// the CodeGenInstruction.
+ unsigned CGIOpNo;
+
+ /// MiOpNo - For isMachineInstrOperand, this is the operand number of the
+ /// machine instruction.
+ unsigned MIOpNo;
+
+ /// MiModifier - For isMachineInstrOperand, this is the modifier string for
+ /// an operand, specified with syntax like ${opname:modifier}.
+ std::string MiModifier;
+
+ // To make VS STL happy
+ AsmWriterOperand(OpType op = isLiteralTextOperand):OperandType(op) {}
+
+ AsmWriterOperand(const std::string &LitStr,
+ OpType op = isLiteralTextOperand)
+ : OperandType(op), Str(LitStr) {}
+
+ AsmWriterOperand(const std::string &Printer,
+ unsigned _CGIOpNo,
+ unsigned _MIOpNo,
+ const std::string &Modifier,
+ OpType op = isMachineInstrOperand)
+ : OperandType(op), Str(Printer), CGIOpNo(_CGIOpNo), MIOpNo(_MIOpNo),
+ MiModifier(Modifier) {}
+
+ bool operator!=(const AsmWriterOperand &Other) const {
+ if (OperandType != Other.OperandType || Str != Other.Str) return true;
+ if (OperandType == isMachineInstrOperand)
+ return MIOpNo != Other.MIOpNo || MiModifier != Other.MiModifier;
+ return false;
+ }
+ bool operator==(const AsmWriterOperand &Other) const {
+ return !operator!=(Other);
+ }
+
+ /// getCode - Return the code that prints this operand.
+ std::string getCode() const;
+ };
+
+ class AsmWriterInst {
+ public:
+ std::vector<AsmWriterOperand> Operands;
+ const CodeGenInstruction *CGI;
+
+ AsmWriterInst(const CodeGenInstruction &CGI,
+ unsigned Variant,
+ int FirstOperandColumn,
+ int OperandSpacing);
+
+ /// MatchesAllButOneOp - If this instruction is exactly identical to the
+ /// specified instruction except for one differing operand, return the
+ /// differing operand number. Otherwise return ~0.
+ unsigned MatchesAllButOneOp(const AsmWriterInst &Other) const;
+
+ private:
+ void AddLiteralString(const std::string &Str) {
+ // If the last operand was already a literal text string, append this to
+ // it, otherwise add a new operand.
+ if (!Operands.empty() &&
+ Operands.back().OperandType == AsmWriterOperand::isLiteralTextOperand)
+ Operands.back().Str.append(Str);
+ else
+ Operands.push_back(AsmWriterOperand(Str));
+ }
+ };
+}
+
+#endif
diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt
index ce9b66f..a2678a2 100644
--- a/utils/TableGen/CMakeLists.txt
+++ b/utils/TableGen/CMakeLists.txt
@@ -1,6 +1,7 @@
add_executable(tblgen
AsmMatcherEmitter.cpp
AsmWriterEmitter.cpp
+ AsmWriterInst.cpp
CallingConvEmitter.cpp
ClangDiagnosticsEmitter.cpp
CodeEmitterGen.cpp
@@ -8,7 +9,11 @@ add_executable(tblgen
CodeGenInstruction.cpp
CodeGenTarget.cpp
DAGISelEmitter.cpp
+ DAGISelMatcherEmitter.cpp
+ DAGISelMatcherGen.cpp
+ DAGISelMatcher.cpp
DisassemblerEmitter.cpp
+ EDEmitter.cpp
FastISelEmitter.cpp
InstrEnumEmitter.cpp
InstrInfoEmitter.cpp
diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp
index 714a39c..f1857f5 100644
--- a/utils/TableGen/CodeEmitterGen.cpp
+++ b/utils/TableGen/CodeEmitterGen.cpp
@@ -35,7 +35,7 @@ void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) {
R->getName() == "IMPLICIT_DEF" ||
R->getName() == "SUBREG_TO_REG" ||
R->getName() == "COPY_TO_REGCLASS" ||
- R->getName() == "DEBUG_VALUE") continue;
+ R->getName() == "DBG_VALUE") continue;
BitsInit *BI = R->getValueAsBitsInit("Inst");
@@ -113,7 +113,7 @@ void CodeEmitterGen::run(raw_ostream &o) {
R->getName() == "IMPLICIT_DEF" ||
R->getName() == "SUBREG_TO_REG" ||
R->getName() == "COPY_TO_REGCLASS" ||
- R->getName() == "DEBUG_VALUE") {
+ R->getName() == "DBG_VALUE") {
o << " 0U,\n";
continue;
}
@@ -152,7 +152,7 @@ void CodeEmitterGen::run(raw_ostream &o) {
InstName == "IMPLICIT_DEF" ||
InstName == "SUBREG_TO_REG" ||
InstName == "COPY_TO_REGCLASS" ||
- InstName == "DEBUG_VALUE") continue;
+ InstName == "DBG_VALUE") continue;
BitsInit *BI = R->getValueAsBitsInit("Inst");
const std::vector<RecordVal> &Vals = R->getValues();
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index cf79365..94d3534 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -674,6 +674,15 @@ TreePatternNode *TreePatternNode::clone() const {
return New;
}
+/// RemoveAllTypes - Recursively strip all the types of this tree.
+void TreePatternNode::RemoveAllTypes() {
+ removeTypes();
+ if (isLeaf()) return;
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ getChild(i)->RemoveAllTypes();
+}
+
+
/// SubstituteFormalArguments - Replace the formal arguments in this tree
/// with actual values specified by ArgMap.
void TreePatternNode::
@@ -768,7 +777,7 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
/// references from the register file information, for example.
///
static std::vector<unsigned char> getImplicitType(Record *R, bool NotRegisters,
- TreePattern &TP) {
+ TreePattern &TP) {
// Some common return values
std::vector<unsigned char> Unknown(1, EEVT::isUnknown);
std::vector<unsigned char> Other(1, MVT::Other);
@@ -825,6 +834,48 @@ getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const {
return &CDP.getIntrinsicInfo(IID);
}
+/// getComplexPatternInfo - If this node corresponds to a ComplexPattern,
+/// return the ComplexPattern information, otherwise return null.
+const ComplexPattern *
+TreePatternNode::getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const {
+ if (!isLeaf()) return 0;
+
+ DefInit *DI = dynamic_cast<DefInit*>(getLeafValue());
+ if (DI && DI->getDef()->isSubClassOf("ComplexPattern"))
+ return &CGP.getComplexPattern(DI->getDef());
+ return 0;
+}
+
+/// NodeHasProperty - Return true if this node has the specified property.
+bool TreePatternNode::NodeHasProperty(SDNP Property,
+ const CodeGenDAGPatterns &CGP) const {
+ if (isLeaf()) {
+ if (const ComplexPattern *CP = getComplexPatternInfo(CGP))
+ return CP->hasProperty(Property);
+ return false;
+ }
+
+ Record *Operator = getOperator();
+ if (!Operator->isSubClassOf("SDNode")) return false;
+
+ return CGP.getSDNodeInfo(Operator).hasProperty(Property);
+}
+
+
+
+
+/// TreeHasProperty - Return true if any node in this tree has the specified
+/// property.
+bool TreePatternNode::TreeHasProperty(SDNP Property,
+ const CodeGenDAGPatterns &CGP) const {
+ if (NodeHasProperty(Property, CGP))
+ return true;
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ if (getChild(i)->TreeHasProperty(Property, CGP))
+ return true;
+ return false;
+}
+
/// isCommutativeIntrinsic - Return true if the node corresponds to a
/// commutative intrinsic.
bool
@@ -845,7 +896,9 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
if (DefInit *DI = dynamic_cast<DefInit*>(getLeafValue())) {
// If it's a regclass or something else known, include the type.
return UpdateNodeType(getImplicitType(DI->getDef(), NotRegisters, TP),TP);
- } else if (IntInit *II = dynamic_cast<IntInit*>(getLeafValue())) {
+ }
+
+ if (IntInit *II = dynamic_cast<IntInit*>(getLeafValue())) {
// Int inits are always integers. :)
bool MadeChange = UpdateNodeType(MVT::iAny, TP);
diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h
index c51232a..f1f7bca 100644
--- a/utils/TableGen/CodeGenDAGPatterns.h
+++ b/utils/TableGen/CodeGenDAGPatterns.h
@@ -216,8 +216,15 @@ public:
void setChild(unsigned i, TreePatternNode *N) {
Children[i] = N;
}
+
+ /// hasChild - Return true if N is any of our children.
+ bool hasChild(const TreePatternNode *N) const {
+ for (unsigned i = 0, e = Children.size(); i != e; ++i)
+ if (Children[i] == N) return true;
+ return false;
+ }
- const std::vector<std::string> &getPredicateFns() const { return PredicateFns; }
+ const std::vector<std::string> &getPredicateFns() const {return PredicateFns;}
void clearPredicateFns() { PredicateFns.clear(); }
void setPredicateFns(const std::vector<std::string> &Fns) {
assert(PredicateFns.empty() && "Overwriting non-empty predicate list!");
@@ -237,6 +244,18 @@ public:
/// CodeGenIntrinsic information for it, otherwise return a null pointer.
const CodeGenIntrinsic *getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const;
+ /// getComplexPatternInfo - If this node corresponds to a ComplexPattern,
+ /// return the ComplexPattern information, otherwise return null.
+ const ComplexPattern *
+ getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const;
+
+ /// NodeHasProperty - Return true if this node has the specified property.
+ bool NodeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const;
+
+ /// TreeHasProperty - Return true if any node in this tree has the specified
+ /// property.
+ bool TreeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const;
+
/// isCommutativeIntrinsic - Return true if the node is an intrinsic which is
/// marked isCommutative.
bool isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const;
@@ -249,6 +268,9 @@ public: // Higher level manipulation routines.
/// clone - Return a new copy of this tree.
///
TreePatternNode *clone() const;
+
+ /// RemoveAllTypes - Recursively strip all the types of this tree.
+ void RemoveAllTypes();
/// isIsomorphicTo - Return true if this node is recursively isomorphic to
/// the specified node. For this comparison, all of the state of the node
@@ -298,6 +320,11 @@ public: // Higher level manipulation routines.
bool canPatternMatch(std::string &Reason, const CodeGenDAGPatterns &CDP);
};
+inline raw_ostream &operator<<(raw_ostream &OS, const TreePatternNode &TPN) {
+ TPN.print(OS);
+ return OS;
+}
+
/// TreePattern - Represent a pattern, used for instructions, pattern
/// fragments, etc.
diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp
index 684431a..d31502b 100644
--- a/utils/TableGen/CodeGenInstruction.cpp
+++ b/utils/TableGen/CodeGenInstruction.cpp
@@ -33,10 +33,10 @@ static void ParseConstraint(const std::string &CStr, CodeGenInstruction *I) {
I->ParseOperandName(Name, false);
// Build the string for the operand
- std::string OpConstraint = "(1 << TOI::EARLY_CLOBBER)";
- if (!I->OperandList[Op.first].Constraints[Op.second].empty())
+ if (!I->OperandList[Op.first].Constraints[Op.second].isNone())
throw "Operand '" + Name + "' cannot have multiple constraints!";
- I->OperandList[Op.first].Constraints[Op.second] = OpConstraint;
+ I->OperandList[Op.first].Constraints[Op.second] =
+ CodeGenInstruction::ConstraintInfo::getEarlyClobber();
return;
}
@@ -65,13 +65,11 @@ static void ParseConstraint(const std::string &CStr, CodeGenInstruction *I) {
unsigned FlatOpNo = I->getFlattenedOperandNumber(SrcOp);
- // Build the string for the operand.
- std::string OpConstraint =
- "((" + utostr(FlatOpNo) + " << 16) | (1 << TOI::TIED_TO))";
- if (!I->OperandList[DestOp.first].Constraints[DestOp.second].empty())
+ if (!I->OperandList[DestOp.first].Constraints[DestOp.second].isNone())
throw "Operand '" + DestOpName + "' cannot have multiple constraints!";
- I->OperandList[DestOp.first].Constraints[DestOp.second] = OpConstraint;
+ I->OperandList[DestOp.first].Constraints[DestOp.second] =
+ CodeGenInstruction::ConstraintInfo::getTied(FlatOpNo);
}
static void ParseConstraints(const std::string &CStr, CodeGenInstruction *I) {
@@ -210,18 +208,13 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
// For backward compatibility: isTwoAddress means operand 1 is tied to
// operand 0.
if (isTwoAddress) {
- if (!OperandList[1].Constraints[0].empty())
+ if (!OperandList[1].Constraints[0].isNone())
throw R->getName() + ": cannot use isTwoAddress property: instruction "
"already has constraint set!";
- OperandList[1].Constraints[0] = "((0 << 16) | (1 << TOI::TIED_TO))";
+ OperandList[1].Constraints[0] =
+ CodeGenInstruction::ConstraintInfo::getTied(0);
}
- // Any operands with unset constraints get 0 as their constraint.
- for (unsigned op = 0, e = OperandList.size(); op != e; ++op)
- for (unsigned j = 0, e = OperandList[op].MINumOperands; j != e; ++j)
- if (OperandList[op].Constraints[j].empty())
- OperandList[op].Constraints[j] = "0";
-
// Parse the DisableEncoding field.
std::string DisableEncoding = R->getValueAsString("DisableEncoding");
while (1) {
diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h
index d22ac3e..285da14 100644
--- a/utils/TableGen/CodeGenInstruction.h
+++ b/utils/TableGen/CodeGenInstruction.h
@@ -32,6 +32,36 @@ namespace llvm {
/// instruction.
std::string AsmString;
+ class ConstraintInfo {
+ enum { None, EarlyClobber, Tied } Kind;
+ unsigned OtherTiedOperand;
+ public:
+ ConstraintInfo() : Kind(None) {}
+
+ static ConstraintInfo getEarlyClobber() {
+ ConstraintInfo I;
+ I.Kind = EarlyClobber;
+ I.OtherTiedOperand = 0;
+ return I;
+ }
+
+ static ConstraintInfo getTied(unsigned Op) {
+ ConstraintInfo I;
+ I.Kind = Tied;
+ I.OtherTiedOperand = Op;
+ return I;
+ }
+
+ bool isNone() const { return Kind == None; }
+ bool isEarlyClobber() const { return Kind == EarlyClobber; }
+ bool isTied() const { return Kind == Tied; }
+
+ unsigned getTiedOperand() const {
+ assert(isTied());
+ return OtherTiedOperand;
+ }
+ };
+
/// OperandInfo - The information we keep track of for each operand in the
/// operand list for a tablegen instruction.
struct OperandInfo {
@@ -67,7 +97,7 @@ namespace llvm {
/// Constraint info for this operand. This operand can have pieces, so we
/// track constraint info for each.
- std::vector<std::string> Constraints;
+ std::vector<ConstraintInfo> Constraints;
OperandInfo(Record *R, const std::string &N, const std::string &PMN,
unsigned MION, unsigned MINO, DagInit *MIOI)
diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp
index c9af5f7..2688091 100644
--- a/utils/TableGen/CodeGenTarget.cpp
+++ b/utils/TableGen/CodeGenTarget.cpp
@@ -337,10 +337,10 @@ getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
throw "Could not find 'COPY_TO_REGCLASS' instruction!";
const CodeGenInstruction *COPY_TO_REGCLASS = &I->second;
- I = getInstructions().find("DEBUG_VALUE");
+ I = getInstructions().find("DBG_VALUE");
if (I == Instructions.end())
- throw "Could not find 'DEBUG_VALUE' instruction!";
- const CodeGenInstruction *DEBUG_VALUE = &I->second;
+ throw "Could not find 'DBG_VALUE' instruction!";
+ const CodeGenInstruction *DBG_VALUE = &I->second;
// Print out the rest of the instructions now.
NumberedInstructions.push_back(PHI);
@@ -354,7 +354,7 @@ getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
NumberedInstructions.push_back(IMPLICIT_DEF);
NumberedInstructions.push_back(SUBREG_TO_REG);
NumberedInstructions.push_back(COPY_TO_REGCLASS);
- NumberedInstructions.push_back(DEBUG_VALUE);
+ NumberedInstructions.push_back(DBG_VALUE);
for (inst_iterator II = inst_begin(), E = inst_end(); II != E; ++II)
if (&II->second != PHI &&
&II->second != INLINEASM &&
@@ -367,7 +367,7 @@ getInstructionsByEnumValue(std::vector<const CodeGenInstruction*>
&II->second != IMPLICIT_DEF &&
&II->second != SUBREG_TO_REG &&
&II->second != COPY_TO_REGCLASS &&
- &II->second != DEBUG_VALUE)
+ &II->second != DBG_VALUE)
NumberedInstructions.push_back(&II->second);
}
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp
index c97582b..f0cebed 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "DAGISelEmitter.h"
+#include "DAGISelMatcher.h"
#include "Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
@@ -55,19 +56,6 @@ static bool NodeIsComplexPattern(TreePatternNode *N) {
isSubClassOf("ComplexPattern"));
}
-/// NodeGetComplexPattern - return the pointer to the ComplexPattern if N
-/// is a leaf node and a subclass of ComplexPattern, else it returns NULL.
-static const ComplexPattern *NodeGetComplexPattern(TreePatternNode *N,
- CodeGenDAGPatterns &CGP) {
- if (N->isLeaf() &&
- dynamic_cast<DefInit*>(N->getLeafValue()) &&
- static_cast<DefInit*>(N->getLeafValue())->getDef()->
- isSubClassOf("ComplexPattern")) {
- return &CGP.getComplexPattern(static_cast<DefInit*>(N->getLeafValue())
- ->getDef());
- }
- return NULL;
-}
/// getPatternSize - Return the 'size' of this pattern. We want to match large
/// patterns before small ones. This is used to determine the size of a
@@ -91,7 +79,7 @@ static unsigned getPatternSize(TreePatternNode *P, CodeGenDAGPatterns &CGP) {
// Later we can allow complexity / cost for each pattern to be (optionally)
// specified. To get best possible pattern match we'll need to dynamically
// calculate the complexity of all patterns a dag can potentially map to.
- const ComplexPattern *AM = NodeGetComplexPattern(P, CGP);
+ const ComplexPattern *AM = P->getComplexPatternInfo(CGP);
if (AM)
Size += AM->getNumOperands() * 3;
@@ -217,68 +205,10 @@ static MVT::SimpleValueType getRegisterValueType(Record *R, const CodeGenTarget
return VT;
}
-
-/// RemoveAllTypes - A quick recursive walk over a pattern which removes all
-/// type information from it.
-static void RemoveAllTypes(TreePatternNode *N) {
- N->removeTypes();
- if (!N->isLeaf())
- for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
- RemoveAllTypes(N->getChild(i));
-}
-
-/// NodeHasProperty - return true if TreePatternNode has the specified
-/// property.
-static bool NodeHasProperty(TreePatternNode *N, SDNP Property,
- CodeGenDAGPatterns &CGP) {
- if (N->isLeaf()) {
- const ComplexPattern *CP = NodeGetComplexPattern(N, CGP);
- if (CP)
- return CP->hasProperty(Property);
- return false;
- }
- Record *Operator = N->getOperator();
- if (!Operator->isSubClassOf("SDNode")) return false;
-
- return CGP.getSDNodeInfo(Operator).hasProperty(Property);
-}
-
-static bool PatternHasProperty(TreePatternNode *N, SDNP Property,
- CodeGenDAGPatterns &CGP) {
- if (NodeHasProperty(N, Property, CGP))
- return true;
-
- for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
- TreePatternNode *Child = N->getChild(i);
- if (PatternHasProperty(Child, Property, CGP))
- return true;
- }
-
- return false;
-}
-
static std::string getOpcodeName(Record *Op, CodeGenDAGPatterns &CGP) {
return CGP.getSDNodeInfo(Op).getEnumName();
}
-static
-bool DisablePatternForFastISel(TreePatternNode *N, CodeGenDAGPatterns &CGP) {
- bool isStore = !N->isLeaf() &&
- getOpcodeName(N->getOperator(), CGP) == "ISD::STORE";
- if (!isStore && NodeHasProperty(N, SDNPHasChain, CGP))
- return false;
-
- bool HasChain = false;
- for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
- TreePatternNode *Child = N->getChild(i);
- if (PatternHasProperty(Child, SDNPHasChain, CGP)) {
- HasChain = true;
- break;
- }
- }
- return HasChain;
-}
-
//===----------------------------------------------------------------------===//
// Node Transformation emitter implementation.
//
@@ -340,14 +270,14 @@ void DAGISelEmitter::EmitPredicateFunctions(raw_ostream &OS) {
if (P->getOnlyTree()->isLeaf())
OS << "inline bool Predicate_" << PatFragRecord->getName()
- << "(SDNode *N) {\n";
+ << "(SDNode *N) const {\n";
else {
std::string ClassName =
CGP.getSDNodeInfo(P->getOnlyTree()->getOperator()).getSDClassName();
const char *C2 = ClassName == "SDNode" ? "N" : "inN";
OS << "inline bool Predicate_" << PatFragRecord->getName()
- << "(SDNode *" << C2 << ") {\n";
+ << "(SDNode *" << C2 << ") const {\n";
if (ClassName != "SDNode")
OS << " " << ClassName << " *N = cast<" << ClassName << ">(inN);\n";
}
@@ -463,760 +393,860 @@ public:
/// matches, and the SDNode for the result has the RootName specified name.
void EmitMatchCode(TreePatternNode *N, TreePatternNode *P,
const std::string &RootName, const std::string &ChainSuffix,
- bool &FoundChain) {
-
- // Save loads/stores matched by a pattern.
- if (!N->isLeaf() && N->getName().empty()) {
- if (NodeHasProperty(N, SDNPMemOperand, CGP))
- LSI.push_back(getNodeName(RootName));
- }
-
- bool isRoot = (P == NULL);
- // Emit instruction predicates. Each predicate is just a string for now.
- if (isRoot) {
- // Record input varargs info.
- NumInputRootOps = N->getNumChildren();
+ bool &FoundChain);
- if (DisablePatternForFastISel(N, CGP))
- emitCheck("OptLevel != CodeGenOpt::None");
+ void EmitChildMatchCode(TreePatternNode *Child, TreePatternNode *Parent,
+ const std::string &RootName,
+ const std::string &ChainSuffix, bool &FoundChain);
- emitCheck(PredicateCheck);
- }
+ /// EmitResultCode - Emit the action for a pattern. Now that it has matched
+ /// we actually have to build a DAG!
+ std::vector<std::string>
+ EmitResultCode(TreePatternNode *N, std::vector<Record*> DstRegs,
+ bool InFlagDecled, bool ResNodeDecled,
+ bool LikeLeaf = false, bool isRoot = false);
- if (N->isLeaf()) {
- if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
- emitCheck("cast<ConstantSDNode>(" + getNodeName(RootName) +
- ")->getSExtValue() == INT64_C(" +
- itostr(II->getValue()) + ")");
- return;
- } else if (!NodeIsComplexPattern(N)) {
- assert(0 && "Cannot match this as a leaf value!");
- abort();
- }
+ /// InsertOneTypeCheck - Insert a type-check for an unresolved type in 'Pat'
+ /// and add it to the tree. 'Pat' and 'Other' are isomorphic trees except that
+ /// 'Pat' may be missing types. If we find an unresolved type to add a check
+ /// for, this returns true otherwise false if Pat has all types.
+ bool InsertOneTypeCheck(TreePatternNode *Pat, TreePatternNode *Other,
+ const std::string &Prefix, bool isRoot = false) {
+ // Did we find one?
+ if (Pat->getExtTypes() != Other->getExtTypes()) {
+ // Move a type over from 'other' to 'pat'.
+ Pat->setTypes(Other->getExtTypes());
+ // The top level node type is checked outside of the select function.
+ if (!isRoot)
+ emitCheck(Prefix + ".getValueType() == " +
+ getName(Pat->getTypeNum(0)));
+ return true;
}
- // If this node has a name associated with it, capture it in VariableMap. If
- // we already saw this in the pattern, emit code to verify dagness.
- if (!N->getName().empty()) {
- std::string &VarMapEntry = VariableMap[N->getName()];
- if (VarMapEntry.empty()) {
- VarMapEntry = RootName;
- } else {
- // If we get here, this is a second reference to a specific name. Since
- // we already have checked that the first reference is valid, we don't
- // have to recursively match it, just check that it's the same as the
- // previously named thing.
- emitCheck(VarMapEntry + " == " + RootName);
- return;
- }
-
- if (!N->isLeaf())
- OperatorMap[N->getName()] = N->getOperator();
- }
-
+ unsigned OpNo = (unsigned)Pat->NodeHasProperty(SDNPHasChain, CGP);
+ for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i, ++OpNo)
+ if (InsertOneTypeCheck(Pat->getChild(i), Other->getChild(i),
+ Prefix + utostr(OpNo)))
+ return true;
+ return false;
+ }
- // Emit code to load the child nodes and match their contents recursively.
- unsigned OpNo = 0;
- bool NodeHasChain = NodeHasProperty (N, SDNPHasChain, CGP);
- bool HasChain = PatternHasProperty(N, SDNPHasChain, CGP);
- bool EmittedUseCheck = false;
- if (HasChain) {
- if (NodeHasChain)
- OpNo = 1;
- if (!isRoot) {
- // Multiple uses of actual result?
- emitCheck(getValueName(RootName) + ".hasOneUse()");
- EmittedUseCheck = true;
- if (NodeHasChain) {
- // If the immediate use can somehow reach this node through another
- // path, then can't fold it either or it will create a cycle.
- // e.g. In the following diagram, XX can reach ld through YY. If
- // ld is folded into XX, then YY is both a predecessor and a successor
- // of XX.
- //
- // [ld]
- // ^ ^
- // | |
- // / \---
- // / [YY]
- // | ^
- // [XX]-------|
- bool NeedCheck = P != Pattern;
- if (!NeedCheck) {
- const SDNodeInfo &PInfo = CGP.getSDNodeInfo(P->getOperator());
- NeedCheck =
- P->getOperator() == CGP.get_intrinsic_void_sdnode() ||
- P->getOperator() == CGP.get_intrinsic_w_chain_sdnode() ||
- P->getOperator() == CGP.get_intrinsic_wo_chain_sdnode() ||
- PInfo.getNumOperands() > 1 ||
- PInfo.hasProperty(SDNPHasChain) ||
- PInfo.hasProperty(SDNPInFlag) ||
- PInfo.hasProperty(SDNPOptInFlag);
+private:
+ /// EmitInFlagSelectCode - Emit the flag operands for the DAG that is
+ /// being built.
+ void EmitInFlagSelectCode(TreePatternNode *N, const std::string &RootName,
+ bool &ChainEmitted, bool &InFlagDecled,
+ bool &ResNodeDecled, bool isRoot = false) {
+ const CodeGenTarget &T = CGP.getTargetInfo();
+ unsigned OpNo = (unsigned)N->NodeHasProperty(SDNPHasChain, CGP);
+ bool HasInFlag = N->NodeHasProperty(SDNPInFlag, CGP);
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {
+ TreePatternNode *Child = N->getChild(i);
+ if (!Child->isLeaf()) {
+ EmitInFlagSelectCode(Child, RootName + utostr(OpNo), ChainEmitted,
+ InFlagDecled, ResNodeDecled);
+ } else {
+ if (DefInit *DI = dynamic_cast<DefInit*>(Child->getLeafValue())) {
+ if (!Child->getName().empty()) {
+ std::string Name = RootName + utostr(OpNo);
+ if (Duplicates.find(Name) != Duplicates.end())
+ // A duplicate! Do not emit a copy for this node.
+ continue;
}
- if (NeedCheck) {
- std::string ParentName(RootName.begin(), RootName.end()-1);
- emitCheck("IsLegalAndProfitableToFold(" + getNodeName(RootName) +
- ", " + getNodeName(ParentName) + ", N)");
+ Record *RR = DI->getDef();
+ if (RR->isSubClassOf("Register")) {
+ MVT::SimpleValueType RVT = getRegisterValueType(RR, T);
+ if (RVT == MVT::Flag) {
+ if (!InFlagDecled) {
+ emitCode("SDValue InFlag = " +
+ getValueName(RootName + utostr(OpNo)) + ";");
+ InFlagDecled = true;
+ } else
+ emitCode("InFlag = " +
+ getValueName(RootName + utostr(OpNo)) + ";");
+ } else {
+ if (!ChainEmitted) {
+ emitCode("SDValue Chain = CurDAG->getEntryNode();");
+ ChainName = "Chain";
+ ChainEmitted = true;
+ }
+ if (!InFlagDecled) {
+ emitCode("SDValue InFlag(0, 0);");
+ InFlagDecled = true;
+ }
+ std::string Decl = (!ResNodeDecled) ? "SDNode *" : "";
+ emitCode(Decl + "ResNode = CurDAG->getCopyToReg(" + ChainName +
+ ", " + getNodeName(RootName) + "->getDebugLoc()" +
+ ", " + getQualifiedName(RR) +
+ ", " + getValueName(RootName + utostr(OpNo)) +
+ ", InFlag).getNode();");
+ ResNodeDecled = true;
+ emitCode(ChainName + " = SDValue(ResNode, 0);");
+ emitCode("InFlag = SDValue(ResNode, 1);");
+ }
}
}
}
-
- if (NodeHasChain) {
- if (FoundChain) {
- emitCheck("(" + ChainName + ".getNode() == " +
- getNodeName(RootName) + " || "
- "IsChainCompatible(" + ChainName + ".getNode(), " +
- getNodeName(RootName) + "))");
- OrigChains.push_back(std::make_pair(ChainName,
- getValueName(RootName)));
- } else
- FoundChain = true;
- ChainName = "Chain" + ChainSuffix;
- emitInit("SDValue " + ChainName + " = " + getNodeName(RootName) +
- "->getOperand(0);");
- }
}
- // Don't fold any node which reads or writes a flag and has multiple uses.
- // FIXME: We really need to separate the concepts of flag and "glue". Those
- // real flag results, e.g. X86CMP output, can have multiple uses.
- // FIXME: If the optional incoming flag does not exist. Then it is ok to
- // fold it.
- if (!isRoot &&
- (PatternHasProperty(N, SDNPInFlag, CGP) ||
- PatternHasProperty(N, SDNPOptInFlag, CGP) ||
- PatternHasProperty(N, SDNPOutFlag, CGP))) {
- if (!EmittedUseCheck) {
- // Multiple uses of actual result?
- emitCheck(getValueName(RootName) + ".hasOneUse()");
- }
+ if (HasInFlag) {
+ if (!InFlagDecled) {
+ emitCode("SDValue InFlag = " + getNodeName(RootName) +
+ "->getOperand(" + utostr(OpNo) + ");");
+ InFlagDecled = true;
+ } else
+ emitCode("InFlag = " + getNodeName(RootName) +
+ "->getOperand(" + utostr(OpNo) + ");");
}
+ }
+};
+
- // If there are node predicates for this, emit the calls.
- for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i)
- emitCheck(N->getPredicateFns()[i] + "(" + getNodeName(RootName) + ")");
-
- // If this is an 'and R, 1234' where the operation is AND/OR and the RHS is
- // a constant without a predicate fn that has more that one bit set, handle
- // this as a special case. This is usually for targets that have special
- // handling of certain large constants (e.g. alpha with it's 8/16/32-bit
- // handling stuff). Using these instructions is often far more efficient
- // than materializing the constant. Unfortunately, both the instcombiner
- // and the dag combiner can often infer that bits are dead, and thus drop
- // them from the mask in the dag. For example, it might turn 'AND X, 255'
- // into 'AND X, 254' if it knows the low bit is set. Emit code that checks
- // to handle this.
- if (!N->isLeaf() &&
- (N->getOperator()->getName() == "and" ||
- N->getOperator()->getName() == "or") &&
- N->getChild(1)->isLeaf() &&
- N->getChild(1)->getPredicateFns().empty()) {
- if (IntInit *II = dynamic_cast<IntInit*>(N->getChild(1)->getLeafValue())) {
- if (!isPowerOf2_32(II->getValue())) { // Don't bother with single bits.
- emitInit("SDValue " + RootName + "0" + " = " +
- getNodeName(RootName) + "->getOperand(" + utostr(0) + ");");
- emitInit("SDValue " + RootName + "1" + " = " +
- getNodeName(RootName) + "->getOperand(" + utostr(1) + ");");
-
- unsigned NTmp = TmpNo++;
- emitCode("ConstantSDNode *Tmp" + utostr(NTmp) +
- " = dyn_cast<ConstantSDNode>(" +
- getNodeName(RootName + "1") + ");");
- emitCheck("Tmp" + utostr(NTmp));
- const char *MaskPredicate = N->getOperator()->getName() == "or"
- ? "CheckOrMask(" : "CheckAndMask(";
- emitCheck(MaskPredicate + getValueName(RootName + "0") +
- ", Tmp" + utostr(NTmp) +
- ", INT64_C(" + itostr(II->getValue()) + "))");
-
- EmitChildMatchCode(N->getChild(0), N, RootName + utostr(0),
- ChainSuffix + utostr(0), FoundChain);
- return;
+/// EmitMatchCode - Emit a matcher for N, going to the label for PatternNo
+/// if the match fails. At this point, we already know that the opcode for N
+/// matches, and the SDNode for the result has the RootName specified name.
+void PatternCodeEmitter::EmitMatchCode(TreePatternNode *N, TreePatternNode *P,
+ const std::string &RootName,
+ const std::string &ChainSuffix,
+ bool &FoundChain) {
+
+ // Save loads/stores matched by a pattern.
+ if (!N->isLeaf() && N->getName().empty()) {
+ if (N->NodeHasProperty(SDNPMemOperand, CGP))
+ LSI.push_back(getNodeName(RootName));
+ }
+
+ bool isRoot = (P == NULL);
+ // Emit instruction predicates. Each predicate is just a string for now.
+ if (isRoot) {
+ // Record input varargs info.
+ NumInputRootOps = N->getNumChildren();
+ emitCheck(PredicateCheck);
+ }
+
+ if (N->isLeaf()) {
+ if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
+ emitCheck("cast<ConstantSDNode>(" + getNodeName(RootName) +
+ ")->getSExtValue() == INT64_C(" +
+ itostr(II->getValue()) + ")");
+ return;
+ } else if (!NodeIsComplexPattern(N)) {
+ assert(0 && "Cannot match this as a leaf value!");
+ abort();
+ }
+ }
+
+ // If this node has a name associated with it, capture it in VariableMap. If
+ // we already saw this in the pattern, emit code to verify dagness.
+ if (!N->getName().empty()) {
+ std::string &VarMapEntry = VariableMap[N->getName()];
+ if (VarMapEntry.empty()) {
+ VarMapEntry = RootName;
+ } else {
+ // If we get here, this is a second reference to a specific name. Since
+ // we already have checked that the first reference is valid, we don't
+ // have to recursively match it, just check that it's the same as the
+ // previously named thing.
+ emitCheck(VarMapEntry + " == " + RootName);
+ return;
+ }
+
+ if (!N->isLeaf())
+ OperatorMap[N->getName()] = N->getOperator();
+ }
+
+
+ // Emit code to load the child nodes and match their contents recursively.
+ unsigned OpNo = 0;
+ bool NodeHasChain = N->NodeHasProperty(SDNPHasChain, CGP);
+ bool HasChain = N->TreeHasProperty(SDNPHasChain, CGP);
+ if (HasChain) {
+ if (NodeHasChain)
+ OpNo = 1;
+ if (!isRoot) {
+ // Check if it's profitable to fold the node. e.g. Check for multiple uses
+ // of actual result?
+ std::string ParentName(RootName.begin(), RootName.end()-1);
+ emitCheck("IsProfitableToFold(" + getValueName(RootName) +
+ ", " + getNodeName(ParentName) + ", N)");
+ if (NodeHasChain) {
+ // If the immediate use can somehow reach this node through another
+ // path, then can't fold it either or it will create a cycle.
+ // e.g. In the following diagram, XX can reach ld through YY. If
+ // ld is folded into XX, then YY is both a predecessor and a successor
+ // of XX.
+ //
+ // [ld]
+ // ^ ^
+ // | |
+ // / \---
+ // / [YY]
+ // | ^
+ // [XX]-------|
+
+ // We know we need the check if N's parent is not the root.
+ bool NeedCheck = P != Pattern;
+ if (!NeedCheck) {
+ const SDNodeInfo &PInfo = CGP.getSDNodeInfo(P->getOperator());
+ NeedCheck =
+ P->getOperator() == CGP.get_intrinsic_void_sdnode() ||
+ P->getOperator() == CGP.get_intrinsic_w_chain_sdnode() ||
+ P->getOperator() == CGP.get_intrinsic_wo_chain_sdnode() ||
+ PInfo.getNumOperands() > 1 ||
+ PInfo.hasProperty(SDNPHasChain) ||
+ PInfo.hasProperty(SDNPInFlag) ||
+ PInfo.hasProperty(SDNPOptInFlag);
+ }
+
+ if (NeedCheck) {
+ emitCheck("IsLegalToFold(" + getValueName(RootName) +
+ ", " + getNodeName(ParentName) + ", N)");
}
}
}
- for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {
- emitInit("SDValue " + getValueName(RootName + utostr(OpNo)) + " = " +
- getNodeName(RootName) + "->getOperand(" + utostr(OpNo) + ");");
-
- EmitChildMatchCode(N->getChild(i), N, RootName + utostr(OpNo),
- ChainSuffix + utostr(OpNo), FoundChain);
+ if (NodeHasChain) {
+ if (FoundChain) {
+ emitCheck("(" + ChainName + ".getNode() == " +
+ getNodeName(RootName) + " || "
+ "IsChainCompatible(" + ChainName + ".getNode(), " +
+ getNodeName(RootName) + "))");
+ OrigChains.push_back(std::make_pair(ChainName,
+ getValueName(RootName)));
+ } else
+ FoundChain = true;
+ ChainName = "Chain" + ChainSuffix;
+ emitInit("SDValue " + ChainName + " = " + getNodeName(RootName) +
+ "->getOperand(0);");
}
-
- // Handle cases when root is a complex pattern.
- const ComplexPattern *CP;
- if (isRoot && N->isLeaf() && (CP = NodeGetComplexPattern(N, CGP))) {
- std::string Fn = CP->getSelectFunc();
- unsigned NumOps = CP->getNumOperands();
- for (unsigned i = 0; i < NumOps; ++i) {
- emitDecl("CPTmp" + RootName + "_" + utostr(i));
- emitCode("SDValue CPTmp" + RootName + "_" + utostr(i) + ";");
- }
- if (CP->hasProperty(SDNPHasChain)) {
- emitDecl("CPInChain");
- emitDecl("Chain" + ChainSuffix);
- emitCode("SDValue CPInChain;");
- emitCode("SDValue Chain" + ChainSuffix + ";");
- }
-
- std::string Code = Fn + "(" +
- getNodeName(RootName) + ", " +
- getValueName(RootName);
- for (unsigned i = 0; i < NumOps; i++)
- Code += ", CPTmp" + RootName + "_" + utostr(i);
- if (CP->hasProperty(SDNPHasChain)) {
- ChainName = "Chain" + ChainSuffix;
- Code += ", CPInChain, Chain" + ChainSuffix;
+ }
+
+ // If there are node predicates for this, emit the calls.
+ for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i)
+ emitCheck(N->getPredicateFns()[i] + "(" + getNodeName(RootName) + ")");
+
+ // If this is an 'and R, 1234' where the operation is AND/OR and the RHS is
+ // a constant without a predicate fn that has more that one bit set, handle
+ // this as a special case. This is usually for targets that have special
+ // handling of certain large constants (e.g. alpha with it's 8/16/32-bit
+ // handling stuff). Using these instructions is often far more efficient
+ // than materializing the constant. Unfortunately, both the instcombiner
+ // and the dag combiner can often infer that bits are dead, and thus drop
+ // them from the mask in the dag. For example, it might turn 'AND X, 255'
+ // into 'AND X, 254' if it knows the low bit is set. Emit code that checks
+ // to handle this.
+ if (!N->isLeaf() &&
+ (N->getOperator()->getName() == "and" ||
+ N->getOperator()->getName() == "or") &&
+ N->getChild(1)->isLeaf() &&
+ N->getChild(1)->getPredicateFns().empty()) {
+ if (IntInit *II = dynamic_cast<IntInit*>(N->getChild(1)->getLeafValue())) {
+ if (!isPowerOf2_32(II->getValue())) { // Don't bother with single bits.
+ emitInit("SDValue " + RootName + "0" + " = " +
+ getNodeName(RootName) + "->getOperand(" + utostr(0) + ");");
+ emitInit("SDValue " + RootName + "1" + " = " +
+ getNodeName(RootName) + "->getOperand(" + utostr(1) + ");");
+
+ unsigned NTmp = TmpNo++;
+ emitCode("ConstantSDNode *Tmp" + utostr(NTmp) +
+ " = dyn_cast<ConstantSDNode>(" +
+ getNodeName(RootName + "1") + ");");
+ emitCheck("Tmp" + utostr(NTmp));
+ const char *MaskPredicate = N->getOperator()->getName() == "or"
+ ? "CheckOrMask(" : "CheckAndMask(";
+ emitCheck(MaskPredicate + getValueName(RootName + "0") +
+ ", Tmp" + utostr(NTmp) +
+ ", INT64_C(" + itostr(II->getValue()) + "))");
+
+ EmitChildMatchCode(N->getChild(0), N, RootName + utostr(0),
+ ChainSuffix + utostr(0), FoundChain);
+ return;
}
- emitCheck(Code + ")");
}
}
+
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {
+ emitInit("SDValue " + getValueName(RootName + utostr(OpNo)) + " = " +
+ getNodeName(RootName) + "->getOperand(" + utostr(OpNo) + ");");
+
+ EmitChildMatchCode(N->getChild(i), N, RootName + utostr(OpNo),
+ ChainSuffix + utostr(OpNo), FoundChain);
+ }
+
+ // Handle cases when root is a complex pattern.
+ const ComplexPattern *CP;
+ if (isRoot && N->isLeaf() && (CP = N->getComplexPatternInfo(CGP))) {
+ std::string Fn = CP->getSelectFunc();
+ unsigned NumOps = CP->getNumOperands();
+ for (unsigned i = 0; i < NumOps; ++i) {
+ emitDecl("CPTmp" + RootName + "_" + utostr(i));
+ emitCode("SDValue CPTmp" + RootName + "_" + utostr(i) + ";");
+ }
+ if (CP->hasProperty(SDNPHasChain)) {
+ emitDecl("CPInChain");
+ emitDecl("Chain" + ChainSuffix);
+ emitCode("SDValue CPInChain;");
+ emitCode("SDValue Chain" + ChainSuffix + ";");
+ }
+
+ std::string Code = Fn + "(" +
+ getNodeName(RootName) + ", " +
+ getValueName(RootName);
+ for (unsigned i = 0; i < NumOps; i++)
+ Code += ", CPTmp" + RootName + "_" + utostr(i);
+ if (CP->hasProperty(SDNPHasChain)) {
+ ChainName = "Chain" + ChainSuffix;
+ Code += ", CPInChain, Chain" + ChainSuffix;
+ }
+ emitCheck(Code + ")");
+ }
+}
- void EmitChildMatchCode(TreePatternNode *Child, TreePatternNode *Parent,
- const std::string &RootName,
- const std::string &ChainSuffix, bool &FoundChain) {
- if (!Child->isLeaf()) {
- // If it's not a leaf, recursively match.
- const SDNodeInfo &CInfo = CGP.getSDNodeInfo(Child->getOperator());
- emitCheck(getNodeName(RootName) + "->getOpcode() == " +
- CInfo.getEnumName());
- EmitMatchCode(Child, Parent, RootName, ChainSuffix, FoundChain);
- bool HasChain = false;
- if (NodeHasProperty(Child, SDNPHasChain, CGP)) {
- HasChain = true;
- FoldedChains.push_back(std::make_pair(getValueName(RootName),
- CInfo.getNumResults()));
- }
- if (NodeHasProperty(Child, SDNPOutFlag, CGP)) {
- assert(FoldedFlag.first == "" && FoldedFlag.second == 0 &&
- "Pattern folded multiple nodes which produce flags?");
- FoldedFlag = std::make_pair(getValueName(RootName),
- CInfo.getNumResults() + (unsigned)HasChain);
+void PatternCodeEmitter::EmitChildMatchCode(TreePatternNode *Child,
+ TreePatternNode *Parent,
+ const std::string &RootName,
+ const std::string &ChainSuffix,
+ bool &FoundChain) {
+ if (!Child->isLeaf()) {
+ // If it's not a leaf, recursively match.
+ const SDNodeInfo &CInfo = CGP.getSDNodeInfo(Child->getOperator());
+ emitCheck(getNodeName(RootName) + "->getOpcode() == " +
+ CInfo.getEnumName());
+ EmitMatchCode(Child, Parent, RootName, ChainSuffix, FoundChain);
+ bool HasChain = false;
+ if (Child->NodeHasProperty(SDNPHasChain, CGP)) {
+ HasChain = true;
+ FoldedChains.push_back(std::make_pair(getValueName(RootName),
+ CInfo.getNumResults()));
+ }
+ if (Child->NodeHasProperty(SDNPOutFlag, CGP)) {
+ assert(FoldedFlag.first == "" && FoldedFlag.second == 0 &&
+ "Pattern folded multiple nodes which produce flags?");
+ FoldedFlag = std::make_pair(getValueName(RootName),
+ CInfo.getNumResults() + (unsigned)HasChain);
+ }
+ } else {
+ // If this child has a name associated with it, capture it in VarMap. If
+ // we already saw this in the pattern, emit code to verify dagness.
+ if (!Child->getName().empty()) {
+ std::string &VarMapEntry = VariableMap[Child->getName()];
+ if (VarMapEntry.empty()) {
+ VarMapEntry = getValueName(RootName);
+ } else {
+ // If we get here, this is a second reference to a specific name.
+ // Since we already have checked that the first reference is valid,
+ // we don't have to recursively match it, just check that it's the
+ // same as the previously named thing.
+ emitCheck(VarMapEntry + " == " + getValueName(RootName));
+ Duplicates.insert(getValueName(RootName));
+ return;
}
- } else {
- // If this child has a name associated with it, capture it in VarMap. If
- // we already saw this in the pattern, emit code to verify dagness.
- if (!Child->getName().empty()) {
- std::string &VarMapEntry = VariableMap[Child->getName()];
- if (VarMapEntry.empty()) {
- VarMapEntry = getValueName(RootName);
- } else {
- // If we get here, this is a second reference to a specific name.
- // Since we already have checked that the first reference is valid,
- // we don't have to recursively match it, just check that it's the
- // same as the previously named thing.
- emitCheck(VarMapEntry + " == " + getValueName(RootName));
- Duplicates.insert(getValueName(RootName));
- return;
+ }
+
+ // Handle leaves of various types.
+ if (DefInit *DI = dynamic_cast<DefInit*>(Child->getLeafValue())) {
+ Record *LeafRec = DI->getDef();
+ if (LeafRec->isSubClassOf("RegisterClass") ||
+ LeafRec->isSubClassOf("PointerLikeRegClass")) {
+ // Handle register references. Nothing to do here.
+ } else if (LeafRec->isSubClassOf("Register")) {
+ // Handle register references.
+ } else if (LeafRec->isSubClassOf("ComplexPattern")) {
+ // Handle complex pattern.
+ const ComplexPattern *CP = Child->getComplexPatternInfo(CGP);
+ std::string Fn = CP->getSelectFunc();
+ unsigned NumOps = CP->getNumOperands();
+ for (unsigned i = 0; i < NumOps; ++i) {
+ emitDecl("CPTmp" + RootName + "_" + utostr(i));
+ emitCode("SDValue CPTmp" + RootName + "_" + utostr(i) + ";");
}
- }
-
- // Handle leaves of various types.
- if (DefInit *DI = dynamic_cast<DefInit*>(Child->getLeafValue())) {
- Record *LeafRec = DI->getDef();
- if (LeafRec->isSubClassOf("RegisterClass") ||
- LeafRec->isSubClassOf("PointerLikeRegClass")) {
- // Handle register references. Nothing to do here.
- } else if (LeafRec->isSubClassOf("Register")) {
- // Handle register references.
- } else if (LeafRec->isSubClassOf("ComplexPattern")) {
- // Handle complex pattern.
- const ComplexPattern *CP = NodeGetComplexPattern(Child, CGP);
- std::string Fn = CP->getSelectFunc();
- unsigned NumOps = CP->getNumOperands();
- for (unsigned i = 0; i < NumOps; ++i) {
- emitDecl("CPTmp" + RootName + "_" + utostr(i));
- emitCode("SDValue CPTmp" + RootName + "_" + utostr(i) + ";");
- }
- if (CP->hasProperty(SDNPHasChain)) {
- const SDNodeInfo &PInfo = CGP.getSDNodeInfo(Parent->getOperator());
- FoldedChains.push_back(std::make_pair("CPInChain",
- PInfo.getNumResults()));
- ChainName = "Chain" + ChainSuffix;
- emitDecl("CPInChain");
- emitDecl(ChainName);
- emitCode("SDValue CPInChain;");
- emitCode("SDValue " + ChainName + ";");
- }
-
- std::string Code = Fn + "(N, ";
- if (CP->hasProperty(SDNPHasChain)) {
- std::string ParentName(RootName.begin(), RootName.end()-1);
- Code += getValueName(ParentName) + ", ";
- }
- Code += getValueName(RootName);
- for (unsigned i = 0; i < NumOps; i++)
- Code += ", CPTmp" + RootName + "_" + utostr(i);
- if (CP->hasProperty(SDNPHasChain))
- Code += ", CPInChain, Chain" + ChainSuffix;
- emitCheck(Code + ")");
- } else if (LeafRec->getName() == "srcvalue") {
- // Place holder for SRCVALUE nodes. Nothing to do here.
- } else if (LeafRec->isSubClassOf("ValueType")) {
- // Make sure this is the specified value type.
- emitCheck("cast<VTSDNode>(" + getNodeName(RootName) +
- ")->getVT() == MVT::" + LeafRec->getName());
- } else if (LeafRec->isSubClassOf("CondCode")) {
- // Make sure this is the specified cond code.
- emitCheck("cast<CondCodeSDNode>(" + getNodeName(RootName) +
- ")->get() == ISD::" + LeafRec->getName());
- } else {
-#ifndef NDEBUG
- Child->dump();
- errs() << " ";
-#endif
- assert(0 && "Unknown leaf type!");
+ if (CP->hasProperty(SDNPHasChain)) {
+ const SDNodeInfo &PInfo = CGP.getSDNodeInfo(Parent->getOperator());
+ FoldedChains.push_back(std::make_pair("CPInChain",
+ PInfo.getNumResults()));
+ ChainName = "Chain" + ChainSuffix;
+ emitDecl("CPInChain");
+ emitDecl(ChainName);
+ emitCode("SDValue CPInChain;");
+ emitCode("SDValue " + ChainName + ";");
}
- // If there are node predicates for this, emit the calls.
- for (unsigned i = 0, e = Child->getPredicateFns().size(); i != e; ++i)
- emitCheck(Child->getPredicateFns()[i] + "(" + getNodeName(RootName) +
- ")");
- } else if (IntInit *II =
- dynamic_cast<IntInit*>(Child->getLeafValue())) {
- unsigned NTmp = TmpNo++;
- emitCode("ConstantSDNode *Tmp"+ utostr(NTmp) +
- " = dyn_cast<ConstantSDNode>("+
- getNodeName(RootName) + ");");
- emitCheck("Tmp" + utostr(NTmp));
- unsigned CTmp = TmpNo++;
- emitCode("int64_t CN"+ utostr(CTmp) +
- " = Tmp" + utostr(NTmp) + "->getSExtValue();");
- emitCheck("CN" + utostr(CTmp) + " == "
- "INT64_C(" +itostr(II->getValue()) + ")");
+ std::string Code = Fn + "(N, ";
+ if (CP->hasProperty(SDNPHasChain)) {
+ std::string ParentName(RootName.begin(), RootName.end()-1);
+ Code += getValueName(ParentName) + ", ";
+ }
+ Code += getValueName(RootName);
+ for (unsigned i = 0; i < NumOps; i++)
+ Code += ", CPTmp" + RootName + "_" + utostr(i);
+ if (CP->hasProperty(SDNPHasChain))
+ Code += ", CPInChain, Chain" + ChainSuffix;
+ emitCheck(Code + ")");
+ } else if (LeafRec->getName() == "srcvalue") {
+ // Place holder for SRCVALUE nodes. Nothing to do here.
+ } else if (LeafRec->isSubClassOf("ValueType")) {
+ // Make sure this is the specified value type.
+ emitCheck("cast<VTSDNode>(" + getNodeName(RootName) +
+ ")->getVT() == MVT::" + LeafRec->getName());
+ } else if (LeafRec->isSubClassOf("CondCode")) {
+ // Make sure this is the specified cond code.
+ emitCheck("cast<CondCodeSDNode>(" + getNodeName(RootName) +
+ ")->get() == ISD::" + LeafRec->getName());
} else {
#ifndef NDEBUG
Child->dump();
+ errs() << " ";
#endif
assert(0 && "Unknown leaf type!");
}
+
+ // If there are node predicates for this, emit the calls.
+ for (unsigned i = 0, e = Child->getPredicateFns().size(); i != e; ++i)
+ emitCheck(Child->getPredicateFns()[i] + "(" + getNodeName(RootName) +
+ ")");
+ } else if (IntInit *II =
+ dynamic_cast<IntInit*>(Child->getLeafValue())) {
+ unsigned NTmp = TmpNo++;
+ emitCode("ConstantSDNode *Tmp"+ utostr(NTmp) +
+ " = dyn_cast<ConstantSDNode>("+
+ getNodeName(RootName) + ");");
+ emitCheck("Tmp" + utostr(NTmp));
+ unsigned CTmp = TmpNo++;
+ emitCode("int64_t CN"+ utostr(CTmp) +
+ " = Tmp" + utostr(NTmp) + "->getSExtValue();");
+ emitCheck("CN" + utostr(CTmp) + " == "
+ "INT64_C(" +itostr(II->getValue()) + ")");
+ } else {
+#ifndef NDEBUG
+ Child->dump();
+#endif
+ assert(0 && "Unknown leaf type!");
}
}
+}
- /// EmitResultCode - Emit the action for a pattern. Now that it has matched
- /// we actually have to build a DAG!
- std::vector<std::string>
- EmitResultCode(TreePatternNode *N, std::vector<Record*> DstRegs,
- bool InFlagDecled, bool ResNodeDecled,
- bool LikeLeaf = false, bool isRoot = false) {
- // List of arguments of getMachineNode() or SelectNodeTo().
- std::vector<std::string> NodeOps;
- // This is something selected from the pattern we matched.
- if (!N->getName().empty()) {
- const std::string &VarName = N->getName();
- std::string Val = VariableMap[VarName];
- bool ModifiedVal = false;
- if (Val.empty()) {
- errs() << "Variable '" << VarName << " referenced but not defined "
- << "and not caught earlier!\n";
- abort();
- }
- if (Val[0] == 'T' && Val[1] == 'm' && Val[2] == 'p') {
- // Already selected this operand, just return the tmpval.
- NodeOps.push_back(getValueName(Val));
- return NodeOps;
- }
-
- const ComplexPattern *CP;
- unsigned ResNo = TmpNo++;
- if (!N->isLeaf() && N->getOperator()->getName() == "imm") {
- assert(N->getExtTypes().size() == 1 && "Multiple types not handled!");
- std::string CastType;
- std::string TmpVar = "Tmp" + utostr(ResNo);
- switch (N->getTypeNum(0)) {
+/// EmitResultCode - Emit the action for a pattern. Now that it has matched
+/// we actually have to build a DAG!
+std::vector<std::string>
+PatternCodeEmitter::EmitResultCode(TreePatternNode *N,
+ std::vector<Record*> DstRegs,
+ bool InFlagDecled, bool ResNodeDecled,
+ bool LikeLeaf, bool isRoot) {
+ // List of arguments of getMachineNode() or SelectNodeTo().
+ std::vector<std::string> NodeOps;
+ // This is something selected from the pattern we matched.
+ if (!N->getName().empty()) {
+ const std::string &VarName = N->getName();
+ std::string Val = VariableMap[VarName];
+ bool ModifiedVal = false;
+ if (Val.empty()) {
+ errs() << "Variable '" << VarName << " referenced but not defined "
+ << "and not caught earlier!\n";
+ abort();
+ }
+ if (Val[0] == 'T' && Val[1] == 'm' && Val[2] == 'p') {
+ // Already selected this operand, just return the tmpval.
+ NodeOps.push_back(getValueName(Val));
+ return NodeOps;
+ }
+
+ const ComplexPattern *CP;
+ unsigned ResNo = TmpNo++;
+ if (!N->isLeaf() && N->getOperator()->getName() == "imm") {
+ assert(N->getExtTypes().size() == 1 && "Multiple types not handled!");
+ std::string CastType;
+ std::string TmpVar = "Tmp" + utostr(ResNo);
+ switch (N->getTypeNum(0)) {
default:
errs() << "Cannot handle " << getEnumName(N->getTypeNum(0))
- << " type as an immediate constant. Aborting\n";
+ << " type as an immediate constant. Aborting\n";
abort();
case MVT::i1: CastType = "bool"; break;
case MVT::i8: CastType = "unsigned char"; break;
case MVT::i16: CastType = "unsigned short"; break;
case MVT::i32: CastType = "unsigned"; break;
case MVT::i64: CastType = "uint64_t"; break;
- }
- emitCode("SDValue " + TmpVar +
- " = CurDAG->getTargetConstant(((" + CastType +
- ") cast<ConstantSDNode>(" + Val + ")->getZExtValue()), " +
+ }
+ emitCode("SDValue " + TmpVar +
+ " = CurDAG->getTargetConstant(((" + CastType +
+ ") cast<ConstantSDNode>(" + Val + ")->getZExtValue()), " +
+ getEnumName(N->getTypeNum(0)) + ");");
+ // Add Tmp<ResNo> to VariableMap, so that we don't multiply select this
+ // value if used multiple times by this pattern result.
+ Val = TmpVar;
+ ModifiedVal = true;
+ NodeOps.push_back(getValueName(Val));
+ } else if (!N->isLeaf() && N->getOperator()->getName() == "fpimm") {
+ assert(N->getExtTypes().size() == 1 && "Multiple types not handled!");
+ std::string TmpVar = "Tmp" + utostr(ResNo);
+ emitCode("SDValue " + TmpVar +
+ " = CurDAG->getTargetConstantFP(*cast<ConstantFPSDNode>(" +
+ Val + ")->getConstantFPValue(), cast<ConstantFPSDNode>(" +
+ Val + ")->getValueType(0));");
+ // Add Tmp<ResNo> to VariableMap, so that we don't multiply select this
+ // value if used multiple times by this pattern result.
+ Val = TmpVar;
+ ModifiedVal = true;
+ NodeOps.push_back(getValueName(Val));
+ } else if (!N->isLeaf() && N->getOperator()->getName() == "texternalsym"){
+ Record *Op = OperatorMap[N->getName()];
+ // Transform ExternalSymbol to TargetExternalSymbol
+ if (Op && Op->getName() == "externalsym") {
+ std::string TmpVar = "Tmp"+utostr(ResNo);
+ emitCode("SDValue " + TmpVar + " = CurDAG->getTarget"
+ "ExternalSymbol(cast<ExternalSymbolSDNode>(" +
+ Val + ")->getSymbol(), " +
getEnumName(N->getTypeNum(0)) + ");");
- // Add Tmp<ResNo> to VariableMap, so that we don't multiply select this
- // value if used multiple times by this pattern result.
+ // Add Tmp<ResNo> to VariableMap, so that we don't multiply select
+ // this value if used multiple times by this pattern result.
Val = TmpVar;
ModifiedVal = true;
- NodeOps.push_back(getValueName(Val));
- } else if (!N->isLeaf() && N->getOperator()->getName() == "fpimm") {
- assert(N->getExtTypes().size() == 1 && "Multiple types not handled!");
- std::string TmpVar = "Tmp" + utostr(ResNo);
- emitCode("SDValue " + TmpVar +
- " = CurDAG->getTargetConstantFP(*cast<ConstantFPSDNode>(" +
- Val + ")->getConstantFPValue(), cast<ConstantFPSDNode>(" +
- Val + ")->getValueType(0));");
- // Add Tmp<ResNo> to VariableMap, so that we don't multiply select this
- // value if used multiple times by this pattern result.
+ }
+ NodeOps.push_back(getValueName(Val));
+ } else if (!N->isLeaf() && (N->getOperator()->getName() == "tglobaladdr"
+ || N->getOperator()->getName() == "tglobaltlsaddr")) {
+ Record *Op = OperatorMap[N->getName()];
+ // Transform GlobalAddress to TargetGlobalAddress
+ if (Op && (Op->getName() == "globaladdr" ||
+ Op->getName() == "globaltlsaddr")) {
+ std::string TmpVar = "Tmp" + utostr(ResNo);
+ emitCode("SDValue " + TmpVar + " = CurDAG->getTarget"
+ "GlobalAddress(cast<GlobalAddressSDNode>(" + Val +
+ ")->getGlobal(), " + getEnumName(N->getTypeNum(0)) +
+ ");");
+ // Add Tmp<ResNo> to VariableMap, so that we don't multiply select
+ // this value if used multiple times by this pattern result.
Val = TmpVar;
ModifiedVal = true;
- NodeOps.push_back(getValueName(Val));
- } else if (!N->isLeaf() && N->getOperator()->getName() == "texternalsym"){
- Record *Op = OperatorMap[N->getName()];
- // Transform ExternalSymbol to TargetExternalSymbol
- if (Op && Op->getName() == "externalsym") {
- std::string TmpVar = "Tmp"+utostr(ResNo);
- emitCode("SDValue " + TmpVar + " = CurDAG->getTarget"
- "ExternalSymbol(cast<ExternalSymbolSDNode>(" +
- Val + ")->getSymbol(), " +
- getEnumName(N->getTypeNum(0)) + ");");
- // Add Tmp<ResNo> to VariableMap, so that we don't multiply select
- // this value if used multiple times by this pattern result.
- Val = TmpVar;
- ModifiedVal = true;
- }
- NodeOps.push_back(getValueName(Val));
- } else if (!N->isLeaf() && (N->getOperator()->getName() == "tglobaladdr"
- || N->getOperator()->getName() == "tglobaltlsaddr")) {
- Record *Op = OperatorMap[N->getName()];
- // Transform GlobalAddress to TargetGlobalAddress
- if (Op && (Op->getName() == "globaladdr" ||
- Op->getName() == "globaltlsaddr")) {
- std::string TmpVar = "Tmp" + utostr(ResNo);
- emitCode("SDValue " + TmpVar + " = CurDAG->getTarget"
- "GlobalAddress(cast<GlobalAddressSDNode>(" + Val +
- ")->getGlobal(), " + getEnumName(N->getTypeNum(0)) +
- ");");
- // Add Tmp<ResNo> to VariableMap, so that we don't multiply select
- // this value if used multiple times by this pattern result.
- Val = TmpVar;
- ModifiedVal = true;
- }
- NodeOps.push_back(getValueName(Val));
- } else if (!N->isLeaf()
- && (N->getOperator()->getName() == "texternalsym"
- || N->getOperator()->getName() == "tconstpool")) {
- // Do not rewrite the variable name, since we don't generate a new
- // temporary.
- NodeOps.push_back(getValueName(Val));
- } else if (N->isLeaf() && (CP = NodeGetComplexPattern(N, CGP))) {
- for (unsigned i = 0; i < CP->getNumOperands(); ++i) {
- NodeOps.push_back(getValueName("CPTmp" + Val + "_" + utostr(i)));
- }
- } else {
- // This node, probably wrapped in a SDNodeXForm, behaves like a leaf
- // node even if it isn't one. Don't select it.
- if (!LikeLeaf) {
- if (isRoot && N->isLeaf()) {
- emitCode("ReplaceUses(SDValue(N, 0), " + Val + ");");
- emitCode("return NULL;");
- }
- }
- NodeOps.push_back(getValueName(Val));
}
-
- if (ModifiedVal) {
- VariableMap[VarName] = Val;
+ NodeOps.push_back(getValueName(Val));
+ } else if (!N->isLeaf()
+ && (N->getOperator()->getName() == "texternalsym" ||
+ N->getOperator()->getName() == "tconstpool")) {
+ // Do not rewrite the variable name, since we don't generate a new
+ // temporary.
+ NodeOps.push_back(getValueName(Val));
+ } else if (N->isLeaf() && (CP = N->getComplexPatternInfo(CGP))) {
+ for (unsigned i = 0; i < CP->getNumOperands(); ++i) {
+ NodeOps.push_back(getValueName("CPTmp" + Val + "_" + utostr(i)));
}
- return NodeOps;
- }
- if (N->isLeaf()) {
- // If this is an explicit register reference, handle it.
- if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) {
- unsigned ResNo = TmpNo++;
- if (DI->getDef()->isSubClassOf("Register")) {
- emitCode("SDValue Tmp" + utostr(ResNo) + " = CurDAG->getRegister(" +
- getQualifiedName(DI->getDef()) + ", " +
- getEnumName(N->getTypeNum(0)) + ");");
- NodeOps.push_back(getValueName("Tmp" + utostr(ResNo)));
- return NodeOps;
- } else if (DI->getDef()->getName() == "zero_reg") {
- emitCode("SDValue Tmp" + utostr(ResNo) +
- " = CurDAG->getRegister(0, " +
- getEnumName(N->getTypeNum(0)) + ");");
- NodeOps.push_back(getValueName("Tmp" + utostr(ResNo)));
- return NodeOps;
- } else if (DI->getDef()->isSubClassOf("RegisterClass")) {
- // Handle a reference to a register class. This is used
- // in COPY_TO_SUBREG instructions.
- emitCode("SDValue Tmp" + utostr(ResNo) +
- " = CurDAG->getTargetConstant(" +
- getQualifiedName(DI->getDef()) + "RegClassID, " +
- "MVT::i32);");
- NodeOps.push_back(getValueName("Tmp" + utostr(ResNo)));
- return NodeOps;
+ } else {
+ // This node, probably wrapped in a SDNodeXForm, behaves like a leaf
+ // node even if it isn't one. Don't select it.
+ if (!LikeLeaf) {
+ if (isRoot && N->isLeaf()) {
+ emitCode("ReplaceUses(SDValue(N, 0), " + Val + ");");
+ emitCode("return NULL;");
}
- } else if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
- unsigned ResNo = TmpNo++;
- assert(N->getExtTypes().size() == 1 && "Multiple types not handled!");
- emitCode("SDValue Tmp" + utostr(ResNo) +
- " = CurDAG->getTargetConstant(0x" +
- utohexstr((uint64_t) II->getValue()) +
- "ULL, " + getEnumName(N->getTypeNum(0)) + ");");
+ }
+ NodeOps.push_back(getValueName(Val));
+ }
+
+ if (ModifiedVal)
+ VariableMap[VarName] = Val;
+ return NodeOps;
+ }
+ if (N->isLeaf()) {
+ // If this is an explicit register reference, handle it.
+ if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) {
+ unsigned ResNo = TmpNo++;
+ if (DI->getDef()->isSubClassOf("Register")) {
+ emitCode("SDValue Tmp" + utostr(ResNo) + " = CurDAG->getRegister(" +
+ getQualifiedName(DI->getDef()) + ", " +
+ getEnumName(N->getTypeNum(0)) + ");");
+ NodeOps.push_back(getValueName("Tmp" + utostr(ResNo)));
+ return NodeOps;
+ } else if (DI->getDef()->getName() == "zero_reg") {
+ emitCode("SDValue Tmp" + utostr(ResNo) +
+ " = CurDAG->getRegister(0, " +
+ getEnumName(N->getTypeNum(0)) + ");");
+ NodeOps.push_back(getValueName("Tmp" + utostr(ResNo)));
+ return NodeOps;
+ } else if (DI->getDef()->isSubClassOf("RegisterClass")) {
+ // Handle a reference to a register class. This is used
+ // in COPY_TO_SUBREG instructions.
+ emitCode("SDValue Tmp" + utostr(ResNo) +
+ " = CurDAG->getTargetConstant(" +
+ getQualifiedName(DI->getDef()) + "RegClassID, " +
+ "MVT::i32);");
NodeOps.push_back(getValueName("Tmp" + utostr(ResNo)));
return NodeOps;
}
+ } else if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
+ unsigned ResNo = TmpNo++;
+ assert(N->getExtTypes().size() == 1 && "Multiple types not handled!");
+ emitCode("SDValue Tmp" + utostr(ResNo) +
+ " = CurDAG->getTargetConstant(0x" +
+ utohexstr((uint64_t) II->getValue()) +
+ "ULL, " + getEnumName(N->getTypeNum(0)) + ");");
+ NodeOps.push_back(getValueName("Tmp" + utostr(ResNo)));
+ return NodeOps;
+ }
#ifndef NDEBUG
- N->dump();
+ N->dump();
#endif
- assert(0 && "Unknown leaf type!");
- return NodeOps;
+ assert(0 && "Unknown leaf type!");
+ return NodeOps;
+ }
+
+ Record *Op = N->getOperator();
+ if (Op->isSubClassOf("Instruction")) {
+ const CodeGenTarget &CGT = CGP.getTargetInfo();
+ CodeGenInstruction &II = CGT.getInstruction(Op->getName());
+ const DAGInstruction &Inst = CGP.getInstruction(Op);
+ const TreePattern *InstPat = Inst.getPattern();
+ // FIXME: Assume actual pattern comes before "implicit".
+ TreePatternNode *InstPatNode =
+ isRoot ? (InstPat ? InstPat->getTree(0) : Pattern)
+ : (InstPat ? InstPat->getTree(0) : NULL);
+ if (InstPatNode && !InstPatNode->isLeaf() &&
+ InstPatNode->getOperator()->getName() == "set") {
+ InstPatNode = InstPatNode->getChild(InstPatNode->getNumChildren()-1);
}
-
- Record *Op = N->getOperator();
- if (Op->isSubClassOf("Instruction")) {
- const CodeGenTarget &CGT = CGP.getTargetInfo();
- CodeGenInstruction &II = CGT.getInstruction(Op->getName());
- const DAGInstruction &Inst = CGP.getInstruction(Op);
- const TreePattern *InstPat = Inst.getPattern();
- // FIXME: Assume actual pattern comes before "implicit".
- TreePatternNode *InstPatNode =
- isRoot ? (InstPat ? InstPat->getTree(0) : Pattern)
- : (InstPat ? InstPat->getTree(0) : NULL);
- if (InstPatNode && !InstPatNode->isLeaf() &&
- InstPatNode->getOperator()->getName() == "set") {
- InstPatNode = InstPatNode->getChild(InstPatNode->getNumChildren()-1);
- }
- bool IsVariadic = isRoot && II.isVariadic;
- // FIXME: fix how we deal with physical register operands.
- bool HasImpInputs = isRoot && Inst.getNumImpOperands() > 0;
- bool HasImpResults = isRoot && DstRegs.size() > 0;
- bool NodeHasOptInFlag = isRoot &&
- PatternHasProperty(Pattern, SDNPOptInFlag, CGP);
- bool NodeHasInFlag = isRoot &&
- PatternHasProperty(Pattern, SDNPInFlag, CGP);
- bool NodeHasOutFlag = isRoot &&
- PatternHasProperty(Pattern, SDNPOutFlag, CGP);
- bool NodeHasChain = InstPatNode &&
- PatternHasProperty(InstPatNode, SDNPHasChain, CGP);
- bool InputHasChain = isRoot &&
- NodeHasProperty(Pattern, SDNPHasChain, CGP);
- unsigned NumResults = Inst.getNumResults();
- unsigned NumDstRegs = HasImpResults ? DstRegs.size() : 0;
-
- // Record output varargs info.
- OutputIsVariadic = IsVariadic;
-
- if (NodeHasOptInFlag) {
- emitCode("bool HasInFlag = "
- "(N->getOperand(N->getNumOperands()-1).getValueType() == "
- "MVT::Flag);");
- }
- if (IsVariadic)
- emitCode("SmallVector<SDValue, 8> Ops" + utostr(OpcNo) + ";");
-
- // How many results is this pattern expected to produce?
- unsigned NumPatResults = 0;
- for (unsigned i = 0, e = Pattern->getExtTypes().size(); i != e; i++) {
- MVT::SimpleValueType VT = Pattern->getTypeNum(i);
- if (VT != MVT::isVoid && VT != MVT::Flag)
- NumPatResults++;
+ bool IsVariadic = isRoot && II.isVariadic;
+ // FIXME: fix how we deal with physical register operands.
+ bool HasImpInputs = isRoot && Inst.getNumImpOperands() > 0;
+ bool HasImpResults = isRoot && DstRegs.size() > 0;
+ bool NodeHasOptInFlag = isRoot &&
+ Pattern->TreeHasProperty(SDNPOptInFlag, CGP);
+ bool NodeHasInFlag = isRoot &&
+ Pattern->TreeHasProperty(SDNPInFlag, CGP);
+ bool NodeHasOutFlag = isRoot &&
+ Pattern->TreeHasProperty(SDNPOutFlag, CGP);
+ bool NodeHasChain = InstPatNode &&
+ InstPatNode->TreeHasProperty(SDNPHasChain, CGP);
+ bool InputHasChain = isRoot && Pattern->NodeHasProperty(SDNPHasChain, CGP);
+ unsigned NumResults = Inst.getNumResults();
+ unsigned NumDstRegs = HasImpResults ? DstRegs.size() : 0;
+
+ // Record output varargs info.
+ OutputIsVariadic = IsVariadic;
+
+ if (NodeHasOptInFlag) {
+ emitCode("bool HasInFlag = "
+ "(N->getOperand(N->getNumOperands()-1).getValueType() == "
+ "MVT::Flag);");
+ }
+ if (IsVariadic)
+ emitCode("SmallVector<SDValue, 8> Ops" + utostr(OpcNo) + ";");
+
+ // How many results is this pattern expected to produce?
+ unsigned NumPatResults = 0;
+ for (unsigned i = 0, e = Pattern->getExtTypes().size(); i != e; i++) {
+ MVT::SimpleValueType VT = Pattern->getTypeNum(i);
+ if (VT != MVT::isVoid && VT != MVT::Flag)
+ NumPatResults++;
+ }
+
+ if (OrigChains.size() > 0) {
+ // The original input chain is being ignored. If it is not just
+ // pointing to the op that's being folded, we should create a
+ // TokenFactor with it and the chain of the folded op as the new chain.
+ // We could potentially be doing multiple levels of folding, in that
+ // case, the TokenFactor can have more operands.
+ emitCode("SmallVector<SDValue, 8> InChains;");
+ for (unsigned i = 0, e = OrigChains.size(); i < e; ++i) {
+ emitCode("if (" + OrigChains[i].first + ".getNode() != " +
+ OrigChains[i].second + ".getNode()) {");
+ emitCode(" InChains.push_back(" + OrigChains[i].first + ");");
+ emitCode("}");
}
-
- if (OrigChains.size() > 0) {
- // The original input chain is being ignored. If it is not just
- // pointing to the op that's being folded, we should create a
- // TokenFactor with it and the chain of the folded op as the new chain.
- // We could potentially be doing multiple levels of folding, in that
- // case, the TokenFactor can have more operands.
- emitCode("SmallVector<SDValue, 8> InChains;");
- for (unsigned i = 0, e = OrigChains.size(); i < e; ++i) {
- emitCode("if (" + OrigChains[i].first + ".getNode() != " +
- OrigChains[i].second + ".getNode()) {");
- emitCode(" InChains.push_back(" + OrigChains[i].first + ");");
- emitCode("}");
- }
- emitCode("InChains.push_back(" + ChainName + ");");
- emitCode(ChainName + " = CurDAG->getNode(ISD::TokenFactor, "
- "N->getDebugLoc(), MVT::Other, "
- "&InChains[0], InChains.size());");
- if (GenDebug) {
- emitCode("CurDAG->setSubgraphColor(" + ChainName +".getNode(), \"yellow\");");
- emitCode("CurDAG->setSubgraphColor(" + ChainName +".getNode(), \"black\");");
- }
+ emitCode("InChains.push_back(" + ChainName + ");");
+ emitCode(ChainName + " = CurDAG->getNode(ISD::TokenFactor, "
+ "N->getDebugLoc(), MVT::Other, "
+ "&InChains[0], InChains.size());");
+ if (GenDebug) {
+ emitCode("CurDAG->setSubgraphColor(" + ChainName +".getNode(), \"yellow\");");
+ emitCode("CurDAG->setSubgraphColor(" + ChainName +".getNode(), \"black\");");
}
-
- // Loop over all of the operands of the instruction pattern, emitting code
- // to fill them all in. The node 'N' usually has number children equal to
- // the number of input operands of the instruction. However, in cases
- // where there are predicate operands for an instruction, we need to fill
- // in the 'execute always' values. Match up the node operands to the
- // instruction operands to do this.
- std::vector<std::string> AllOps;
- for (unsigned ChildNo = 0, InstOpNo = NumResults;
- InstOpNo != II.OperandList.size(); ++InstOpNo) {
- std::vector<std::string> Ops;
-
- // Determine what to emit for this operand.
- Record *OperandNode = II.OperandList[InstOpNo].Rec;
- if ((OperandNode->isSubClassOf("PredicateOperand") ||
- OperandNode->isSubClassOf("OptionalDefOperand")) &&
- !CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) {
- // This is a predicate or optional def operand; emit the
- // 'default ops' operands.
- const DAGDefaultOperand &DefaultOp =
- CGP.getDefaultOperand(II.OperandList[InstOpNo].Rec);
- for (unsigned i = 0, e = DefaultOp.DefaultOps.size(); i != e; ++i) {
- Ops = EmitResultCode(DefaultOp.DefaultOps[i], DstRegs,
- InFlagDecled, ResNodeDecled);
- AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
- }
- } else {
- // Otherwise this is a normal operand or a predicate operand without
- // 'execute always'; emit it.
- Ops = EmitResultCode(N->getChild(ChildNo), DstRegs,
+ }
+
+ // Loop over all of the operands of the instruction pattern, emitting code
+ // to fill them all in. The node 'N' usually has number children equal to
+ // the number of input operands of the instruction. However, in cases
+ // where there are predicate operands for an instruction, we need to fill
+ // in the 'execute always' values. Match up the node operands to the
+ // instruction operands to do this.
+ std::vector<std::string> AllOps;
+ for (unsigned ChildNo = 0, InstOpNo = NumResults;
+ InstOpNo != II.OperandList.size(); ++InstOpNo) {
+ std::vector<std::string> Ops;
+
+ // Determine what to emit for this operand.
+ Record *OperandNode = II.OperandList[InstOpNo].Rec;
+ if ((OperandNode->isSubClassOf("PredicateOperand") ||
+ OperandNode->isSubClassOf("OptionalDefOperand")) &&
+ !CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) {
+ // This is a predicate or optional def operand; emit the
+ // 'default ops' operands.
+ const DAGDefaultOperand &DefaultOp =
+ CGP.getDefaultOperand(II.OperandList[InstOpNo].Rec);
+ for (unsigned i = 0, e = DefaultOp.DefaultOps.size(); i != e; ++i) {
+ Ops = EmitResultCode(DefaultOp.DefaultOps[i], DstRegs,
InFlagDecled, ResNodeDecled);
AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
- ++ChildNo;
}
- }
-
- // Emit all the chain and CopyToReg stuff.
- bool ChainEmitted = NodeHasChain;
- if (NodeHasInFlag || HasImpInputs)
- EmitInFlagSelectCode(Pattern, "N", ChainEmitted,
- InFlagDecled, ResNodeDecled, true);
- if (NodeHasOptInFlag || NodeHasInFlag || HasImpInputs) {
- if (!InFlagDecled) {
- emitCode("SDValue InFlag(0, 0);");
- InFlagDecled = true;
- }
- if (NodeHasOptInFlag) {
- emitCode("if (HasInFlag) {");
- emitCode(" InFlag = N->getOperand(N->getNumOperands()-1);");
- emitCode("}");
- }
- }
-
- unsigned ResNo = TmpNo++;
-
- unsigned OpsNo = OpcNo;
- std::string CodePrefix;
- bool ChainAssignmentNeeded = NodeHasChain && !isRoot;
- std::deque<std::string> After;
- std::string NodeName;
- if (!isRoot) {
- NodeName = "Tmp" + utostr(ResNo);
- CodePrefix = "SDValue " + NodeName + "(";
} else {
- NodeName = "ResNode";
- if (!ResNodeDecled) {
- CodePrefix = "SDNode *" + NodeName + " = ";
- ResNodeDecled = true;
- } else
- CodePrefix = NodeName + " = ";
- }
-
- std::string Code = "Opc" + utostr(OpcNo);
-
- if (!isRoot || (InputHasChain && !NodeHasChain))
- // For call to "getMachineNode()".
- Code += ", N->getDebugLoc()";
-
- emitOpcode(II.Namespace + "::" + II.TheDef->getName());
-
- // Output order: results, chain, flags
- // Result types.
- if (NumResults > 0 && N->getTypeNum(0) != MVT::isVoid) {
- Code += ", VT" + utostr(VTNo);
- emitVT(getEnumName(N->getTypeNum(0)));
+ // Otherwise this is a normal operand or a predicate operand without
+ // 'execute always'; emit it.
+ Ops = EmitResultCode(N->getChild(ChildNo), DstRegs,
+ InFlagDecled, ResNodeDecled);
+ AllOps.insert(AllOps.end(), Ops.begin(), Ops.end());
+ ++ChildNo;
}
- // Add types for implicit results in physical registers, scheduler will
- // care of adding copyfromreg nodes.
- for (unsigned i = 0; i < NumDstRegs; i++) {
- Record *RR = DstRegs[i];
- if (RR->isSubClassOf("Register")) {
- MVT::SimpleValueType RVT = getRegisterValueType(RR, CGT);
- Code += ", " + getEnumName(RVT);
- }
+ }
+
+ // Emit all the chain and CopyToReg stuff.
+ bool ChainEmitted = NodeHasChain;
+ if (NodeHasInFlag || HasImpInputs)
+ EmitInFlagSelectCode(Pattern, "N", ChainEmitted,
+ InFlagDecled, ResNodeDecled, true);
+ if (NodeHasOptInFlag || NodeHasInFlag || HasImpInputs) {
+ if (!InFlagDecled) {
+ emitCode("SDValue InFlag(0, 0);");
+ InFlagDecled = true;
}
- if (NodeHasChain)
- Code += ", MVT::Other";
- if (NodeHasOutFlag)
- Code += ", MVT::Flag";
-
- // Inputs.
- if (IsVariadic) {
- for (unsigned i = 0, e = AllOps.size(); i != e; ++i)
- emitCode("Ops" + utostr(OpsNo) + ".push_back(" + AllOps[i] + ");");
- AllOps.clear();
-
- // Figure out whether any operands at the end of the op list are not
- // part of the variable section.
- std::string EndAdjust;
- if (NodeHasInFlag || HasImpInputs)
- EndAdjust = "-1"; // Always has one flag.
- else if (NodeHasOptInFlag)
- EndAdjust = "-(HasInFlag?1:0)"; // May have a flag.
-
- emitCode("for (unsigned i = NumInputRootOps + " + utostr(NodeHasChain) +
- ", e = N->getNumOperands()" + EndAdjust + "; i != e; ++i) {");
-
- emitCode(" Ops" + utostr(OpsNo) + ".push_back(N->getOperand(i));");
+ if (NodeHasOptInFlag) {
+ emitCode("if (HasInFlag) {");
+ emitCode(" InFlag = N->getOperand(N->getNumOperands()-1);");
emitCode("}");
}
-
- // Populate MemRefs with entries for each memory accesses covered by
- // this pattern.
- if (isRoot && !LSI.empty()) {
- std::string MemRefs = "MemRefs" + utostr(OpsNo);
- emitCode("MachineSDNode::mmo_iterator " + MemRefs + " = "
- "MF->allocateMemRefsArray(" + utostr(LSI.size()) + ");");
- for (unsigned i = 0, e = LSI.size(); i != e; ++i)
- emitCode(MemRefs + "[" + utostr(i) + "] = "
- "cast<MemSDNode>(" + LSI[i] + ")->getMemOperand();");
- After.push_back("cast<MachineSDNode>(ResNode)->setMemRefs(" +
- MemRefs + ", " + MemRefs + " + " + utostr(LSI.size()) +
- ");");
+ }
+
+ unsigned ResNo = TmpNo++;
+
+ unsigned OpsNo = OpcNo;
+ std::string CodePrefix;
+ bool ChainAssignmentNeeded = NodeHasChain && !isRoot;
+ std::deque<std::string> After;
+ std::string NodeName;
+ if (!isRoot) {
+ NodeName = "Tmp" + utostr(ResNo);
+ CodePrefix = "SDValue " + NodeName + "(";
+ } else {
+ NodeName = "ResNode";
+ if (!ResNodeDecled) {
+ CodePrefix = "SDNode *" + NodeName + " = ";
+ ResNodeDecled = true;
+ } else
+ CodePrefix = NodeName + " = ";
+ }
+
+ std::string Code = "Opc" + utostr(OpcNo);
+
+ if (!isRoot || (InputHasChain && !NodeHasChain))
+ // For call to "getMachineNode()".
+ Code += ", N->getDebugLoc()";
+
+ emitOpcode(II.Namespace + "::" + II.TheDef->getName());
+
+ // Output order: results, chain, flags
+ // Result types.
+ if (NumResults > 0 && N->getTypeNum(0) != MVT::isVoid) {
+ Code += ", VT" + utostr(VTNo);
+ emitVT(getEnumName(N->getTypeNum(0)));
+ }
+ // Add types for implicit results in physical registers, scheduler will
+ // care of adding copyfromreg nodes.
+ for (unsigned i = 0; i < NumDstRegs; i++) {
+ Record *RR = DstRegs[i];
+ if (RR->isSubClassOf("Register")) {
+ MVT::SimpleValueType RVT = getRegisterValueType(RR, CGT);
+ Code += ", " + getEnumName(RVT);
}
-
- if (NodeHasChain) {
- if (IsVariadic)
- emitCode("Ops" + utostr(OpsNo) + ".push_back(" + ChainName + ");");
- else
- AllOps.push_back(ChainName);
+ }
+ if (NodeHasChain)
+ Code += ", MVT::Other";
+ if (NodeHasOutFlag)
+ Code += ", MVT::Flag";
+
+ // Inputs.
+ if (IsVariadic) {
+ for (unsigned i = 0, e = AllOps.size(); i != e; ++i)
+ emitCode("Ops" + utostr(OpsNo) + ".push_back(" + AllOps[i] + ");");
+ AllOps.clear();
+
+ // Figure out whether any operands at the end of the op list are not
+ // part of the variable section.
+ std::string EndAdjust;
+ if (NodeHasInFlag || HasImpInputs)
+ EndAdjust = "-1"; // Always has one flag.
+ else if (NodeHasOptInFlag)
+ EndAdjust = "-(HasInFlag?1:0)"; // May have a flag.
+
+ emitCode("for (unsigned i = NumInputRootOps + " + utostr(NodeHasChain) +
+ ", e = N->getNumOperands()" + EndAdjust + "; i != e; ++i) {");
+
+ emitCode(" Ops" + utostr(OpsNo) + ".push_back(N->getOperand(i));");
+ emitCode("}");
+ }
+
+ // Populate MemRefs with entries for each memory accesses covered by
+ // this pattern.
+ if (isRoot && !LSI.empty()) {
+ std::string MemRefs = "MemRefs" + utostr(OpsNo);
+ emitCode("MachineSDNode::mmo_iterator " + MemRefs + " = "
+ "MF->allocateMemRefsArray(" + utostr(LSI.size()) + ");");
+ for (unsigned i = 0, e = LSI.size(); i != e; ++i)
+ emitCode(MemRefs + "[" + utostr(i) + "] = "
+ "cast<MemSDNode>(" + LSI[i] + ")->getMemOperand();");
+ After.push_back("cast<MachineSDNode>(ResNode)->setMemRefs(" +
+ MemRefs + ", " + MemRefs + " + " + utostr(LSI.size()) +
+ ");");
+ }
+
+ if (NodeHasChain) {
+ if (IsVariadic)
+ emitCode("Ops" + utostr(OpsNo) + ".push_back(" + ChainName + ");");
+ else
+ AllOps.push_back(ChainName);
+ }
+
+ if (IsVariadic) {
+ if (NodeHasInFlag || HasImpInputs)
+ emitCode("Ops" + utostr(OpsNo) + ".push_back(InFlag);");
+ else if (NodeHasOptInFlag) {
+ emitCode("if (HasInFlag)");
+ emitCode(" Ops" + utostr(OpsNo) + ".push_back(InFlag);");
}
-
- if (IsVariadic) {
- if (NodeHasInFlag || HasImpInputs)
- emitCode("Ops" + utostr(OpsNo) + ".push_back(InFlag);");
- else if (NodeHasOptInFlag) {
- emitCode("if (HasInFlag)");
- emitCode(" Ops" + utostr(OpsNo) + ".push_back(InFlag);");
- }
- Code += ", &Ops" + utostr(OpsNo) + "[0], Ops" + utostr(OpsNo) +
- ".size()";
- } else if (NodeHasInFlag || NodeHasOptInFlag || HasImpInputs)
- AllOps.push_back("InFlag");
-
- unsigned NumOps = AllOps.size();
- if (NumOps) {
- if (!NodeHasOptInFlag && NumOps < 4) {
- for (unsigned i = 0; i != NumOps; ++i)
- Code += ", " + AllOps[i];
- } else {
- std::string OpsCode = "SDValue Ops" + utostr(OpsNo) + "[] = { ";
- for (unsigned i = 0; i != NumOps; ++i) {
- OpsCode += AllOps[i];
- if (i != NumOps-1)
- OpsCode += ", ";
- }
- emitCode(OpsCode + " };");
- Code += ", Ops" + utostr(OpsNo) + ", ";
- if (NodeHasOptInFlag) {
- Code += "HasInFlag ? ";
- Code += utostr(NumOps) + " : " + utostr(NumOps-1);
- } else
- Code += utostr(NumOps);
+ Code += ", &Ops" + utostr(OpsNo) + "[0], Ops" + utostr(OpsNo) +
+ ".size()";
+ } else if (NodeHasInFlag || NodeHasOptInFlag || HasImpInputs)
+ AllOps.push_back("InFlag");
+
+ unsigned NumOps = AllOps.size();
+ if (NumOps) {
+ if (!NodeHasOptInFlag && NumOps < 4) {
+ for (unsigned i = 0; i != NumOps; ++i)
+ Code += ", " + AllOps[i];
+ } else {
+ std::string OpsCode = "SDValue Ops" + utostr(OpsNo) + "[] = { ";
+ for (unsigned i = 0; i != NumOps; ++i) {
+ OpsCode += AllOps[i];
+ if (i != NumOps-1)
+ OpsCode += ", ";
}
+ emitCode(OpsCode + " };");
+ Code += ", Ops" + utostr(OpsNo) + ", ";
+ if (NodeHasOptInFlag) {
+ Code += "HasInFlag ? ";
+ Code += utostr(NumOps) + " : " + utostr(NumOps-1);
+ } else
+ Code += utostr(NumOps);
}
-
- if (!isRoot)
- Code += "), 0";
-
- std::vector<std::string> ReplaceFroms;
- std::vector<std::string> ReplaceTos;
- if (!isRoot) {
- NodeOps.push_back("Tmp" + utostr(ResNo));
- } else {
-
+ }
+
+ if (!isRoot)
+ Code += "), 0";
+
+ std::vector<std::string> ReplaceFroms;
+ std::vector<std::string> ReplaceTos;
+ if (!isRoot) {
+ NodeOps.push_back("Tmp" + utostr(ResNo));
+ } else {
+
if (NodeHasOutFlag) {
if (!InFlagDecled) {
After.push_back("SDValue InFlag(ResNode, " +
@@ -1228,7 +1258,7 @@ public:
utostr(NumResults+NumDstRegs+(unsigned)NodeHasChain) +
");");
}
-
+
for (unsigned j = 0, e = FoldedChains.size(); j < e; j++) {
ReplaceFroms.push_back("SDValue(" +
FoldedChains[j].first + ".getNode(), " +
@@ -1237,21 +1267,21 @@ public:
ReplaceTos.push_back("SDValue(ResNode, " +
utostr(NumResults+NumDstRegs) + ")");
}
-
+
if (NodeHasOutFlag) {
if (FoldedFlag.first != "") {
ReplaceFroms.push_back("SDValue(" + FoldedFlag.first + ".getNode(), " +
utostr(FoldedFlag.second) + ")");
ReplaceTos.push_back("InFlag");
} else {
- assert(NodeHasProperty(Pattern, SDNPOutFlag, CGP));
+ assert(Pattern->NodeHasProperty(SDNPOutFlag, CGP));
ReplaceFroms.push_back("SDValue(N, " +
utostr(NumPatResults + (unsigned)InputHasChain)
+ ")");
ReplaceTos.push_back("InFlag");
}
}
-
+
if (!ReplaceFroms.empty() && InputHasChain) {
ReplaceFroms.push_back("SDValue(N, " +
utostr(NumPatResults) + ")");
@@ -1259,7 +1289,7 @@ public:
ChainName + ".getResNo()" + ")");
ChainAssignmentNeeded |= NodeHasChain;
}
-
+
// User does not expect the instruction would produce a chain!
if ((!InputHasChain && NodeHasChain) && NodeHasOutFlag) {
;
@@ -1270,193 +1300,97 @@ public:
utostr(NumPatResults) + ")");
ReplaceTos.push_back(ChainName);
}
- }
-
- if (ChainAssignmentNeeded) {
- // Remember which op produces the chain.
- std::string ChainAssign;
- if (!isRoot)
- ChainAssign = ChainName + " = SDValue(" + NodeName +
- ".getNode(), " + utostr(NumResults+NumDstRegs) + ");";
- else
- ChainAssign = ChainName + " = SDValue(" + NodeName +
- ", " + utostr(NumResults+NumDstRegs) + ");";
-
- After.push_front(ChainAssign);
- }
-
- if (ReplaceFroms.size() == 1) {
- After.push_back("ReplaceUses(" + ReplaceFroms[0] + ", " +
- ReplaceTos[0] + ");");
- } else if (!ReplaceFroms.empty()) {
- After.push_back("const SDValue Froms[] = {");
- for (unsigned i = 0, e = ReplaceFroms.size(); i != e; ++i)
- After.push_back(" " + ReplaceFroms[i] + (i + 1 != e ? "," : ""));
- After.push_back("};");
- After.push_back("const SDValue Tos[] = {");
- for (unsigned i = 0, e = ReplaceFroms.size(); i != e; ++i)
- After.push_back(" " + ReplaceTos[i] + (i + 1 != e ? "," : ""));
- After.push_back("};");
- After.push_back("ReplaceUses(Froms, Tos, " +
- itostr(ReplaceFroms.size()) + ");");
- }
-
- // We prefer to use SelectNodeTo since it avoids allocation when
- // possible and it avoids CSE map recalculation for the node's
- // users, however it's tricky to use in a non-root context.
- //
- // We also don't use SelectNodeTo if the pattern replacement is being
- // used to jettison a chain result, since morphing the node in place
- // would leave users of the chain dangling.
- //
- if (!isRoot || (InputHasChain && !NodeHasChain)) {
- Code = "CurDAG->getMachineNode(" + Code;
- } else {
- Code = "CurDAG->SelectNodeTo(N, " + Code;
- }
- if (isRoot) {
- if (After.empty())
- CodePrefix = "return ";
- else
- After.push_back("return ResNode;");
- }
-
- emitCode(CodePrefix + Code + ");");
-
- if (GenDebug) {
- if (!isRoot) {
- emitCode("CurDAG->setSubgraphColor(" + NodeName +".getNode(), \"yellow\");");
- emitCode("CurDAG->setSubgraphColor(" + NodeName +".getNode(), \"black\");");
- }
- else {
- emitCode("CurDAG->setSubgraphColor(" + NodeName +", \"yellow\");");
- emitCode("CurDAG->setSubgraphColor(" + NodeName +", \"black\");");
- }
- }
-
- for (unsigned i = 0, e = After.size(); i != e; ++i)
- emitCode(After[i]);
-
- return NodeOps;
}
- if (Op->isSubClassOf("SDNodeXForm")) {
- assert(N->getNumChildren() == 1 && "node xform should have one child!");
- // PatLeaf node - the operand may or may not be a leaf node. But it should
- // behave like one.
- std::vector<std::string> Ops =
- EmitResultCode(N->getChild(0), DstRegs, InFlagDecled,
- ResNodeDecled, true);
- unsigned ResNo = TmpNo++;
- emitCode("SDValue Tmp" + utostr(ResNo) + " = Transform_" + Op->getName()
- + "(" + Ops.back() + ".getNode());");
- NodeOps.push_back("Tmp" + utostr(ResNo));
- if (isRoot)
- emitCode("return Tmp" + utostr(ResNo) + ".getNode();");
- return NodeOps;
- }
-
- N->dump();
- errs() << "\n";
- throw std::string("Unknown node in result pattern!");
- }
-
- /// InsertOneTypeCheck - Insert a type-check for an unresolved type in 'Pat'
- /// and add it to the tree. 'Pat' and 'Other' are isomorphic trees except that
- /// 'Pat' may be missing types. If we find an unresolved type to add a check
- /// for, this returns true otherwise false if Pat has all types.
- bool InsertOneTypeCheck(TreePatternNode *Pat, TreePatternNode *Other,
- const std::string &Prefix, bool isRoot = false) {
- // Did we find one?
- if (Pat->getExtTypes() != Other->getExtTypes()) {
- // Move a type over from 'other' to 'pat'.
- Pat->setTypes(Other->getExtTypes());
- // The top level node type is checked outside of the select function.
+
+ if (ChainAssignmentNeeded) {
+ // Remember which op produces the chain.
+ std::string ChainAssign;
if (!isRoot)
- emitCheck(Prefix + ".getValueType() == " +
- getName(Pat->getTypeNum(0)));
- return true;
+ ChainAssign = ChainName + " = SDValue(" + NodeName +
+ ".getNode(), " + utostr(NumResults+NumDstRegs) + ");";
+ else
+ ChainAssign = ChainName + " = SDValue(" + NodeName +
+ ", " + utostr(NumResults+NumDstRegs) + ");";
+
+ After.push_front(ChainAssign);
}
-
- unsigned OpNo =
- (unsigned) NodeHasProperty(Pat, SDNPHasChain, CGP);
- for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i, ++OpNo)
- if (InsertOneTypeCheck(Pat->getChild(i), Other->getChild(i),
- Prefix + utostr(OpNo)))
- return true;
- return false;
- }
-
-private:
- /// EmitInFlagSelectCode - Emit the flag operands for the DAG that is
- /// being built.
- void EmitInFlagSelectCode(TreePatternNode *N, const std::string &RootName,
- bool &ChainEmitted, bool &InFlagDecled,
- bool &ResNodeDecled, bool isRoot = false) {
- const CodeGenTarget &T = CGP.getTargetInfo();
- unsigned OpNo =
- (unsigned) NodeHasProperty(N, SDNPHasChain, CGP);
- bool HasInFlag = NodeHasProperty(N, SDNPInFlag, CGP);
- for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {
- TreePatternNode *Child = N->getChild(i);
- if (!Child->isLeaf()) {
- EmitInFlagSelectCode(Child, RootName + utostr(OpNo), ChainEmitted,
- InFlagDecled, ResNodeDecled);
+
+ if (ReplaceFroms.size() == 1) {
+ After.push_back("ReplaceUses(" + ReplaceFroms[0] + ", " +
+ ReplaceTos[0] + ");");
+ } else if (!ReplaceFroms.empty()) {
+ After.push_back("const SDValue Froms[] = {");
+ for (unsigned i = 0, e = ReplaceFroms.size(); i != e; ++i)
+ After.push_back(" " + ReplaceFroms[i] + (i + 1 != e ? "," : ""));
+ After.push_back("};");
+ After.push_back("const SDValue Tos[] = {");
+ for (unsigned i = 0, e = ReplaceFroms.size(); i != e; ++i)
+ After.push_back(" " + ReplaceTos[i] + (i + 1 != e ? "," : ""));
+ After.push_back("};");
+ After.push_back("ReplaceUses(Froms, Tos, " +
+ itostr(ReplaceFroms.size()) + ");");
+ }
+
+ // We prefer to use SelectNodeTo since it avoids allocation when
+ // possible and it avoids CSE map recalculation for the node's
+ // users, however it's tricky to use in a non-root context.
+ //
+ // We also don't use SelectNodeTo if the pattern replacement is being
+ // used to jettison a chain result, since morphing the node in place
+ // would leave users of the chain dangling.
+ //
+ if (!isRoot || (InputHasChain && !NodeHasChain)) {
+ Code = "CurDAG->getMachineNode(" + Code;
+ } else {
+ Code = "CurDAG->SelectNodeTo(N, " + Code;
+ }
+ if (isRoot) {
+ if (After.empty())
+ CodePrefix = "return ";
+ else
+ After.push_back("return ResNode;");
+ }
+
+ emitCode(CodePrefix + Code + ");");
+
+ if (GenDebug) {
+ if (!isRoot) {
+ emitCode("CurDAG->setSubgraphColor(" +
+ NodeName +".getNode(), \"yellow\");");
+ emitCode("CurDAG->setSubgraphColor(" +
+ NodeName +".getNode(), \"black\");");
} else {
- if (DefInit *DI = dynamic_cast<DefInit*>(Child->getLeafValue())) {
- if (!Child->getName().empty()) {
- std::string Name = RootName + utostr(OpNo);
- if (Duplicates.find(Name) != Duplicates.end())
- // A duplicate! Do not emit a copy for this node.
- continue;
- }
-
- Record *RR = DI->getDef();
- if (RR->isSubClassOf("Register")) {
- MVT::SimpleValueType RVT = getRegisterValueType(RR, T);
- if (RVT == MVT::Flag) {
- if (!InFlagDecled) {
- emitCode("SDValue InFlag = " +
- getValueName(RootName + utostr(OpNo)) + ";");
- InFlagDecled = true;
- } else
- emitCode("InFlag = " +
- getValueName(RootName + utostr(OpNo)) + ";");
- } else {
- if (!ChainEmitted) {
- emitCode("SDValue Chain = CurDAG->getEntryNode();");
- ChainName = "Chain";
- ChainEmitted = true;
- }
- if (!InFlagDecled) {
- emitCode("SDValue InFlag(0, 0);");
- InFlagDecled = true;
- }
- std::string Decl = (!ResNodeDecled) ? "SDNode *" : "";
- emitCode(Decl + "ResNode = CurDAG->getCopyToReg(" + ChainName +
- ", " + getNodeName(RootName) + "->getDebugLoc()" +
- ", " + getQualifiedName(RR) +
- ", " + getValueName(RootName + utostr(OpNo)) +
- ", InFlag).getNode();");
- ResNodeDecled = true;
- emitCode(ChainName + " = SDValue(ResNode, 0);");
- emitCode("InFlag = SDValue(ResNode, 1);");
- }
- }
- }
+ emitCode("CurDAG->setSubgraphColor(" + NodeName +", \"yellow\");");
+ emitCode("CurDAG->setSubgraphColor(" + NodeName +", \"black\");");
}
}
-
- if (HasInFlag) {
- if (!InFlagDecled) {
- emitCode("SDValue InFlag = " + getNodeName(RootName) +
- "->getOperand(" + utostr(OpNo) + ");");
- InFlagDecled = true;
- } else
- emitCode("InFlag = " + getNodeName(RootName) +
- "->getOperand(" + utostr(OpNo) + ");");
- }
+
+ for (unsigned i = 0, e = After.size(); i != e; ++i)
+ emitCode(After[i]);
+
+ return NodeOps;
}
-};
+ if (Op->isSubClassOf("SDNodeXForm")) {
+ assert(N->getNumChildren() == 1 && "node xform should have one child!");
+ // PatLeaf node - the operand may or may not be a leaf node. But it should
+ // behave like one.
+ std::vector<std::string> Ops =
+ EmitResultCode(N->getChild(0), DstRegs, InFlagDecled,
+ ResNodeDecled, true);
+ unsigned ResNo = TmpNo++;
+ emitCode("SDValue Tmp" + utostr(ResNo) + " = Transform_" + Op->getName()
+ + "(" + Ops.back() + ".getNode());");
+ NodeOps.push_back("Tmp" + utostr(ResNo));
+ if (isRoot)
+ emitCode("return Tmp" + utostr(ResNo) + ".getNode();");
+ return NodeOps;
+ }
+
+ N->dump();
+ errs() << "\n";
+ throw std::string("Unknown node in result pattern!");
+}
+
/// EmitCodeForPattern - Given a pattern to match, emit code to the specified
/// stream to match the pattern, and generate the code for the match if it
@@ -1481,7 +1415,8 @@ void DAGISelEmitter::GenerateCodeForPattern(const PatternToMatch &Pattern,
bool FoundChain = false;
Emitter.EmitMatchCode(Pattern.getSrcPattern(), NULL, "N", "", FoundChain);
- // TP - Get *SOME* tree pattern, we don't care which.
+ // TP - Get *SOME* tree pattern, we don't care which. It is only used for
+ // diagnostics, which we know are impossible at this point.
TreePattern &TP = *CGP.pf_begin()->second;
// At this point, we know that we structurally match the pattern, but the
@@ -1497,7 +1432,7 @@ void DAGISelEmitter::GenerateCodeForPattern(const PatternToMatch &Pattern,
// types are resolved.
//
TreePatternNode *Pat = Pattern.getSrcPattern()->clone();
- RemoveAllTypes(Pat);
+ Pat->RemoveAllTypes();
do {
// Resolve/propagate as many types as possible.
@@ -1662,7 +1597,7 @@ static std::string getLegalCName(std::string OpName) {
void DAGISelEmitter::EmitInstructionSelector(raw_ostream &OS) {
const CodeGenTarget &Target = CGP.getTargetInfo();
-
+
// Get the namespace to insert instructions into.
std::string InstNS = Target.getInstNamespace();
if (!InstNS.empty()) InstNS += "::";
@@ -1674,7 +1609,6 @@ void DAGISelEmitter::EmitInstructionSelector(raw_ostream &OS) {
for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(),
E = CGP.ptm_end(); I != E; ++I) {
const PatternToMatch &Pattern = *I;
-
TreePatternNode *Node = Pattern.getSrcPattern();
if (!Node->isLeaf()) {
PatternsByOpcode[getOpcodeName(Node->getOperator(), CGP)].
@@ -1684,7 +1618,7 @@ void DAGISelEmitter::EmitInstructionSelector(raw_ostream &OS) {
if (dynamic_cast<IntInit*>(Node->getLeafValue())) {
PatternsByOpcode[getOpcodeName(CGP.getSDNodeNamed("imm"), CGP)].
push_back(&Pattern);
- } else if ((CP = NodeGetComplexPattern(Node, CGP))) {
+ } else if ((CP = Node->getComplexPatternInfo(CGP))) {
std::vector<Record*> OpNodes = CP->getRootNodes();
for (unsigned j = 0, e = OpNodes.size(); j != e; j++) {
PatternsByOpcode[getOpcodeName(OpNodes[j], CGP)]
@@ -1831,9 +1765,8 @@ void DAGISelEmitter::EmitInstructionSelector(raw_ostream &OS) {
// Replace the emission code within selection routines with calls to the
// emission functions.
- if (GenDebug) {
+ if (GenDebug)
GeneratedCode.push_back(std::make_pair(0, "CurDAG->setSubgraphColor(N, \"red\");"));
- }
CallerCode = "SDNode *Result = Emit_" + utostr(EmitFuncNum) + CallerCode;
GeneratedCode.push_back(std::make_pair(3, CallerCode));
if (GenDebug) {
@@ -2065,4 +1998,26 @@ void DAGISelEmitter::run(raw_ostream &OS) {
// definitions. Emit the resultant instruction selector.
EmitInstructionSelector(OS);
+#if 0
+ MatcherNode *Matcher = 0;
+ // Walk the patterns backwards, building a matcher for each and adding it to
+ // the matcher for the whole target.
+ for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(),
+ E = CGP.ptm_end(); I != E;) {
+ const PatternToMatch &Pattern = *--E;
+ MatcherNode *N = ConvertPatternToMatcher(Pattern, CGP);
+
+ if (Matcher == 0)
+ Matcher = N;
+ else
+ Matcher = new PushMatcherNode(N, Matcher);
+ }
+
+
+ EmitMatcherTable(Matcher, OS);
+
+
+ //Matcher->dump();
+ delete Matcher;
+#endif
}
diff --git a/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp
new file mode 100644
index 0000000..3f75558
--- /dev/null
+++ b/utils/TableGen/DAGISelMatcher.cpp
@@ -0,0 +1,118 @@
+//===- DAGISelMatcher.cpp - Representation of DAG pattern matcher ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DAGISelMatcher.h"
+#include "CodeGenDAGPatterns.h"
+#include "CodeGenTarget.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+void MatcherNode::dump() const {
+ print(errs());
+}
+
+void EmitNodeMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitNode: Src = " << *Pattern.getSrcPattern() << "\n";
+ OS.indent(indent) << "EmitNode: Dst = " << *Pattern.getDstPattern() << "\n";
+}
+
+void MatcherNodeWithChild::printChild(raw_ostream &OS, unsigned indent) const {
+ if (Child)
+ return Child->print(OS, indent);
+ OS.indent(indent) << "<null child>\n";
+}
+
+
+void PushMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "Push\n";
+ printChild(OS, indent+2);
+ Failure->print(OS, indent);
+}
+
+void RecordMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "Record\n";
+ printChild(OS, indent);
+}
+
+void MoveChildMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "MoveChild " << ChildNo << '\n';
+ printChild(OS, indent);
+}
+
+void MoveParentMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "MoveParent\n";
+ printChild(OS, indent);
+}
+
+void CheckSameMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckSame " << MatchNumber << '\n';
+ printChild(OS, indent);
+}
+
+void CheckPatternPredicateMatcherNode::
+print(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckPatternPredicate " << Predicate << '\n';
+ printChild(OS, indent);
+}
+
+void CheckPredicateMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckPredicate " << PredName << '\n';
+ printChild(OS, indent);
+}
+
+void CheckOpcodeMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckOpcode " << OpcodeName << '\n';
+ printChild(OS, indent);
+}
+
+void CheckTypeMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckType " << getEnumName(Type) << '\n';
+ printChild(OS, indent);
+}
+
+void CheckIntegerMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckInteger " << Value << '\n';
+ printChild(OS, indent);
+}
+
+void CheckCondCodeMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckCondCode ISD::" << CondCodeName << '\n';
+ printChild(OS, indent);
+}
+
+void CheckValueTypeMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckValueType MVT::" << TypeName << '\n';
+ printChild(OS, indent);
+}
+
+void CheckComplexPatMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckComplexPat " << Pattern.getSelectFunc() << '\n';
+ printChild(OS, indent);
+}
+
+void CheckAndImmMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckAndImm " << Value << '\n';
+ printChild(OS, indent);
+}
+
+void CheckOrImmMatcherNode::print(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckOrImm " << Value << '\n';
+ printChild(OS, indent);
+}
+
+void CheckProfitableToFoldMatcherNode::print(raw_ostream &OS,
+ unsigned indent) const {
+ OS.indent(indent) << "CheckProfitableToFold\n";
+ printChild(OS, indent);
+}
+
+void CheckLegalToFoldMatcherNode::print(raw_ostream &OS, unsigned indent) const{
+ OS.indent(indent) << "CheckLegalToFold\n";
+ printChild(OS, indent);
+}
diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h
new file mode 100644
index 0000000..b40fbf9
--- /dev/null
+++ b/utils/TableGen/DAGISelMatcher.h
@@ -0,0 +1,391 @@
+//===- DAGISelMatcher.h - Representation of DAG pattern matcher -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TBLGEN_DAGISELMATCHER_H
+#define TBLGEN_DAGISELMATCHER_H
+
+#include "llvm/CodeGen/ValueTypes.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
+
+namespace llvm {
+ class CodeGenDAGPatterns;
+ class MatcherNode;
+ class PatternToMatch;
+ class raw_ostream;
+ class ComplexPattern;
+
+MatcherNode *ConvertPatternToMatcher(const PatternToMatch &Pattern,
+ const CodeGenDAGPatterns &CGP);
+
+void EmitMatcherTable(const MatcherNode *Matcher, raw_ostream &OS);
+
+
+/// MatcherNode - Base class for all the the DAG ISel Matcher representation
+/// nodes.
+class MatcherNode {
+public:
+ enum KindTy {
+ EmitNode,
+ Push, // [Push, Dest0, Dest1, Dest2, Dest3]
+ Record, // [Record]
+ MoveChild, // [MoveChild, Child#]
+ MoveParent, // [MoveParent]
+
+ CheckSame, // [CheckSame, N] Fail if not same as prev match.
+ CheckPatternPredicate,
+ CheckPredicate, // [CheckPredicate, P] Fail if predicate fails.
+ CheckOpcode, // [CheckOpcode, Opcode] Fail if not opcode.
+ CheckType, // [CheckType, MVT] Fail if not correct type.
+ CheckInteger, // [CheckInteger, int0,int1,int2,...int7] Fail if wrong val.
+ CheckCondCode, // [CheckCondCode, CondCode] Fail if not condcode.
+ CheckValueType,
+ CheckComplexPat,
+ CheckAndImm,
+ CheckOrImm,
+ CheckProfitableToFold,
+ CheckLegalToFold
+ };
+ const KindTy Kind;
+
+protected:
+ MatcherNode(KindTy K) : Kind(K) {}
+public:
+ virtual ~MatcherNode() {}
+
+ KindTy getKind() const { return Kind; }
+
+
+ static inline bool classof(const MatcherNode *) { return true; }
+
+ virtual void print(raw_ostream &OS, unsigned indent = 0) const = 0;
+ void dump() const;
+};
+
+/// EmitNodeMatcherNode - This signals a successful match and generates a node.
+class EmitNodeMatcherNode : public MatcherNode {
+ const PatternToMatch &Pattern;
+public:
+ EmitNodeMatcherNode(const PatternToMatch &pattern)
+ : MatcherNode(EmitNode), Pattern(pattern) {}
+
+ const PatternToMatch &getPattern() const { return Pattern; }
+
+ static inline bool classof(const MatcherNode *N) {
+ return N->getKind() == EmitNode;
+ }
+
+ virtual void print(raw_ostream &OS, unsigned indent = 0) const;
+};
+
+/// MatcherNodeWithChild - Every node accept the final accept state has a child
+/// that is executed after the node runs. This class captures this commonality.
+class MatcherNodeWithChild : public MatcherNode {
+ OwningPtr<MatcherNode> Child;
+public:
+ MatcherNodeWithChild(KindTy K) : MatcherNode(K) {}
+
+ MatcherNode *getChild() { return Child.get(); }
+ const MatcherNode *getChild() const { return Child.get(); }
+ void setChild(MatcherNode *C) { Child.reset(C); }
+
+ static inline bool classof(const MatcherNode *N) {
+ return N->getKind() != EmitNode;
+ }
+
+protected:
+ void printChild(raw_ostream &OS, unsigned indent) const;
+};
+
+/// PushMatcherNode - This pushes a failure scope on the stack and evaluates
+/// 'child'. If 'child' fails to match, it pops its scope and attempts to
+/// match 'Failure'.
+class PushMatcherNode : public MatcherNodeWithChild {
+ OwningPtr<MatcherNode> Failure;
+public:
+ PushMatcherNode(MatcherNode *child = 0, MatcherNode *failure = 0)
+ : MatcherNodeWithChild(Push), Failure(failure) {
+ setChild(child);
+ }
+
+ MatcherNode *getFailure() { return Failure.get(); }
+ const MatcherNode *getFailure() const { return Failure.get(); }
+ void setFailure(MatcherNode *N) { Failure.reset(N); }
+
+ static inline bool classof(const MatcherNode *N) {
+ return N->getKind() == Push;
+ }
+
+ virtual void print(raw_ostream &OS, unsigned indent = 0) const;
+};
+
+/// RecordMatcherNode - Save the current node in the operand list.
+class RecordMatcherNode : public MatcherNodeWithChild {
+public:
+ RecordMatcherNode() : MatcherNodeWithChild(Record) {}
+
+ static inline bool classof(const MatcherNode *N) {
+ return N->getKind() == Record;
+ }
+
+ virtual void print(raw_ostream &OS, unsigned indent = 0) const;
+};
+
+/// MoveChildMatcherNode - This tells the interpreter to move into the
+/// specified child node.
+class MoveChildMatcherNode : public MatcherNodeWithChild {
+ unsigned ChildNo;
+public:
+ MoveChildMatcherNode(unsigned childNo)
+ : MatcherNodeWithChild(MoveChild), ChildNo(childNo) {}
+
+ unsigned getChildNo() const { return ChildNo; }
+
+ static inline bool classof(const MatcherNode *N) {
+ return N->getKind() == MoveChild;
+ }
+
+ virtual void print(raw_ostream &OS, unsigned indent = 0) const;
+};
+
+/// MoveParentMatcherNode - This tells the interpreter to move to the parent
+/// of the current node.
+class MoveParentMatcherNode : public MatcherNodeWithChild {
+public:
+ MoveParentMatcherNode()
+ : MatcherNodeWithChild(MoveParent) {}
+
+ static inline bool classof(const MatcherNode *N) {
+ return N->getKind() == MoveParent;
+ }
+
+ virtual void print(raw_ostream &OS, unsigned indent = 0) const;
+};
+
+/// CheckSameMatcherNode - This checks to see if this node is exactly the same
+/// node as the specified match that was recorded with 'Record'. This is used
+/// when patterns have the same name in them, like '(mul GPR:$in, GPR:$in)'.
+class CheckSameMatcherNode : public MatcherNodeWithChild {
+ unsigned MatchNumber;
+public:
+ CheckSameMatcherNode(unsigned matchnumber)
+ : MatcherNodeWithChild(CheckSame), MatchNumber(matchnumber) {}
+
+ unsigned getMatchNumber() const { return MatchNumber; }
+
+ static inline bool classof(const MatcherNode *N) {
+ return N->getKind() == CheckSame;
+ }
+
+ virtual void print(raw_ostream &OS, unsigned indent = 0) const;
+};
+
+/// CheckPatternPredicateMatcherNode - This checks the target-specific predicate
+/// to see if the entire pattern is capable of matching. This predicate does
+/// not take a node as input. This is used for subtarget feature checks etc.
+class CheckPatternPredicateMatcherNode : public MatcherNodeWithChild {
+ std::string Predicate;
+public:
+ CheckPatternPredicateMatcherNode(StringRef predicate)
+ : MatcherNodeWithChild(CheckPatternPredicate), Predicate(predicate) {}
+
+ StringRef getPredicate() const { return Predicate; }
+
+ static inline bool classof(const MatcherNode *N) {
+ return N->getKind() == CheckPatternPredicate;
+ }
+
+ virtual void print(raw_ostream &OS, unsigned indent = 0) const;
+};
+
+/// CheckPredicateMatcherNode - This checks the target-specific predicate to
+/// see if the node is acceptable.
+class CheckPredicateMatcherNode : public MatcherNodeWithChild {
+ StringRef PredName;
+public:
+ CheckPredicateMatcherNode(StringRef predname)
+ : MatcherNodeWithChild(CheckPredicate), PredName(predname) {}
+
+ StringRef getPredicateName() const { return PredName; }
+
+ static inline bool classof(const MatcherNode *N) {
+ return N->getKind() == CheckPredicate;
+ }
+
+ virtual void print(raw_ostream &OS, unsigned indent = 0) const;
+};
+
+
+/// CheckOpcodeMatcherNode - This checks to see if the current node has the
+/// specified opcode, if not it fails to match.
+class CheckOpcodeMatcherNode : public MatcherNodeWithChild {
+ StringRef OpcodeName;
+public:
+ CheckOpcodeMatcherNode(StringRef opcodename)
+ : MatcherNodeWithChild(CheckOpcode), OpcodeName(opcodename) {}
+
+ StringRef getOpcodeName() const { return OpcodeName; }
+
+ static inline bool classof(const MatcherNode *N) {
+ return N->getKind() == CheckOpcode;
+ }
+
+ virtual void print(raw_ostream &OS, unsigned indent = 0) const;
+};
+
+/// CheckTypeMatcherNode - This checks to see if the current node has the
+/// specified type, if not it fails to match.
+class CheckTypeMatcherNode : public MatcherNodeWithChild {
+ MVT::SimpleValueType Type;
+public:
+ CheckTypeMatcherNode(MVT::SimpleValueType type)
+ : MatcherNodeWithChild(CheckType), Type(type) {}
+
+ MVT::SimpleValueType getType() const { return Type; }
+
+ static inline bool classof(const MatcherNode *N) {
+ return N->getKind() == CheckType;
+ }
+
+ virtual void print(raw_ostream &OS, unsigned indent = 0) const;
+};
+
+/// CheckIntegerMatcherNode - This checks to see if the current node is a
+/// ConstantSDNode with the specified integer value, if not it fails to match.
+class CheckIntegerMatcherNode : public MatcherNodeWithChild {
+ int64_t Value;
+public:
+ CheckIntegerMatcherNode(int64_t value)
+ : MatcherNodeWithChild(CheckInteger), Value(value) {}
+
+ int64_t getValue() const { return Value; }
+
+ static inline bool classof(const MatcherNode *N) {
+ return N->getKind() == CheckInteger;
+ }
+
+ virtual void print(raw_ostream &OS, unsigned indent = 0) const;
+};
+
+/// CheckCondCodeMatcherNode - This checks to see if the current node is a
+/// CondCodeSDNode with the specified condition, if not it fails to match.
+class CheckCondCodeMatcherNode : public MatcherNodeWithChild {
+ StringRef CondCodeName;
+public:
+ CheckCondCodeMatcherNode(StringRef condcodename)
+ : MatcherNodeWithChild(CheckCondCode), CondCodeName(condcodename) {}
+
+ StringRef getCondCodeName() const { return CondCodeName; }
+
+ static inline bool classof(const MatcherNode *N) {
+ return N->getKind() == CheckCondCode;
+ }
+
+ virtual void print(raw_ostream &OS, unsigned indent = 0) const;
+};
+
+/// CheckValueTypeMatcherNode - This checks to see if the current node is a
+/// VTSDNode with the specified type, if not it fails to match.
+class CheckValueTypeMatcherNode : public MatcherNodeWithChild {
+ StringRef TypeName;
+public:
+ CheckValueTypeMatcherNode(StringRef type_name)
+ : MatcherNodeWithChild(CheckValueType), TypeName(type_name) {}
+
+ StringRef getTypeName() const { return TypeName; }
+
+ static inline bool classof(const MatcherNode *N) {
+ return N->getKind() == CheckValueType;
+ }
+
+ virtual void print(raw_ostream &OS, unsigned indent = 0) const;
+};
+
+
+
+/// CheckComplexPatMatcherNode - This node runs the specified ComplexPattern on
+/// the current node.
+class CheckComplexPatMatcherNode : public MatcherNodeWithChild {
+ const ComplexPattern &Pattern;
+public:
+ CheckComplexPatMatcherNode(const ComplexPattern &pattern)
+ : MatcherNodeWithChild(CheckComplexPat), Pattern(pattern) {}
+
+ static inline bool classof(const MatcherNode *N) {
+ return N->getKind() == CheckComplexPat;
+ }
+
+ virtual void print(raw_ostream &OS, unsigned indent = 0) const;
+};
+
+/// CheckAndImmMatcherNode - This checks to see if the current node is an 'and'
+/// with something equivalent to the specified immediate.
+class CheckAndImmMatcherNode : public MatcherNodeWithChild {
+ int64_t Value;
+public:
+ CheckAndImmMatcherNode(int64_t value)
+ : MatcherNodeWithChild(CheckAndImm), Value(value) {}
+
+ int64_t getValue() const { return Value; }
+
+ static inline bool classof(const MatcherNode *N) {
+ return N->getKind() == CheckAndImm;
+ }
+
+ virtual void print(raw_ostream &OS, unsigned indent = 0) const;
+};
+
+/// CheckOrImmMatcherNode - This checks to see if the current node is an 'and'
+/// with something equivalent to the specified immediate.
+class CheckOrImmMatcherNode : public MatcherNodeWithChild {
+ int64_t Value;
+public:
+ CheckOrImmMatcherNode(int64_t value)
+ : MatcherNodeWithChild(CheckOrImm), Value(value) {}
+
+ int64_t getValue() const { return Value; }
+
+ static inline bool classof(const MatcherNode *N) {
+ return N->getKind() == CheckOrImm;
+ }
+
+ virtual void print(raw_ostream &OS, unsigned indent = 0) const;
+};
+
+/// CheckProfitableToFoldMatcherNode - This checks to see if the current node is
+/// worthwhile to try to fold into a large pattern.
+class CheckProfitableToFoldMatcherNode : public MatcherNodeWithChild {
+public:
+ CheckProfitableToFoldMatcherNode()
+ : MatcherNodeWithChild(CheckProfitableToFold) {}
+
+ static inline bool classof(const MatcherNode *N) {
+ return N->getKind() == CheckProfitableToFold;
+ }
+
+ virtual void print(raw_ostream &OS, unsigned indent = 0) const;
+};
+
+/// CheckLegalToFoldMatcherNode - This checks to see if the current node is
+/// legal to try to fold into a large pattern.
+class CheckLegalToFoldMatcherNode : public MatcherNodeWithChild {
+public:
+ CheckLegalToFoldMatcherNode()
+ : MatcherNodeWithChild(CheckLegalToFold) {}
+
+ static inline bool classof(const MatcherNode *N) {
+ return N->getKind() == CheckLegalToFold;
+ }
+
+ virtual void print(raw_ostream &OS, unsigned indent = 0) const;
+};
+} // end namespace llvm
+
+#endif
diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp
new file mode 100644
index 0000000..c0ad169
--- /dev/null
+++ b/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -0,0 +1,278 @@
+//===- DAGISelMatcherEmitter.cpp - Matcher Emitter ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains code to generate C++ code a matcher.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DAGISelMatcher.h"
+#include "CodeGenDAGPatterns.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/FormattedStream.h"
+using namespace llvm;
+
+namespace {
+enum {
+ CommentIndent = 25
+};
+}
+
+/// ClassifyInt - Classify an integer by size, return '1','2','4','8' if this
+/// fits in 1, 2, 4, or 8 sign extended bytes.
+static char ClassifyInt(int64_t Val) {
+ if (Val == int8_t(Val)) return '1';
+ if (Val == int16_t(Val)) return '2';
+ if (Val == int32_t(Val)) return '4';
+ return '8';
+}
+
+/// EmitInt - Emit the specified integer, returning the number of bytes emitted.
+static unsigned EmitInt(int64_t Val, formatted_raw_ostream &OS) {
+ unsigned BytesEmitted = 1;
+ OS << (int)(unsigned char)Val << ", ";
+ if (Val == int8_t(Val)) {
+ OS << "\n";
+ return BytesEmitted;
+ }
+
+ OS << (int)(unsigned char)(Val >> 8) << ", ";
+ ++BytesEmitted;
+
+ if (Val != int16_t(Val)) {
+ OS << (int)(unsigned char)(Val >> 16) << ','
+ << (int)(unsigned char)(Val >> 24) << ',';
+ BytesEmitted += 2;
+
+ if (Val != int32_t(Val)) {
+ OS << (int)(unsigned char)(Val >> 32) << ','
+ << (int)(unsigned char)(Val >> 40) << ','
+ << (int)(unsigned char)(Val >> 48) << ','
+ << (int)(unsigned char)(Val >> 56) << ',';
+ BytesEmitted += 4;
+ }
+ }
+
+ OS.PadToColumn(CommentIndent) << "// " << Val << '\n';
+ return BytesEmitted;
+}
+
+namespace {
+class MatcherTableEmitter {
+ formatted_raw_ostream &OS;
+
+ StringMap<unsigned> NodePredicateMap, PatternPredicateMap;
+ std::vector<std::string> NodePredicates, PatternPredicates;
+
+public:
+ MatcherTableEmitter(formatted_raw_ostream &os) : OS(os) {}
+
+ unsigned EmitMatcherAndChildren(const MatcherNode *N, unsigned Indent);
+
+ void EmitPredicateFunctions();
+private:
+ unsigned EmitMatcher(const MatcherNode *N, unsigned Indent);
+
+ unsigned getNodePredicate(StringRef PredName) {
+ unsigned &Entry = NodePredicateMap[PredName];
+ if (Entry == 0) {
+ NodePredicates.push_back(PredName.str());
+ Entry = NodePredicates.size();
+ }
+ return Entry-1;
+ }
+ unsigned getPatternPredicate(StringRef PredName) {
+ unsigned &Entry = PatternPredicateMap[PredName];
+ if (Entry == 0) {
+ PatternPredicates.push_back(PredName.str());
+ Entry = PatternPredicates.size();
+ }
+ return Entry-1;
+ }
+};
+} // end anonymous namespace.
+
+/// EmitMatcherOpcodes - Emit bytes for the specified matcher and return
+/// the number of bytes emitted.
+unsigned MatcherTableEmitter::
+EmitMatcher(const MatcherNode *N, unsigned Indent) {
+ OS.PadToColumn(Indent*2);
+
+ switch (N->getKind()) {
+ case MatcherNode::Push: assert(0 && "Should be handled by caller");
+ case MatcherNode::EmitNode:
+ OS << "OPC_Emit, /*XXX*/";
+ OS.PadToColumn(CommentIndent) << "// Src: "
+ << *cast<EmitNodeMatcherNode>(N)->getPattern().getSrcPattern() << '\n';
+ OS.PadToColumn(CommentIndent) << "// Dst: "
+ << *cast<EmitNodeMatcherNode>(N)->getPattern().getDstPattern() << '\n';
+ return 1;
+ case MatcherNode::Record:
+ OS << "OPC_Record,\n";
+ return 1;
+ case MatcherNode::MoveChild:
+ OS << "OPC_MoveChild, "
+ << cast<MoveChildMatcherNode>(N)->getChildNo() << ",\n";
+ return 2;
+
+ case MatcherNode::MoveParent:
+ OS << "OPC_MoveParent,\n";
+ return 1;
+
+ case MatcherNode::CheckSame:
+ OS << "OPC_CheckSame, "
+ << cast<CheckSameMatcherNode>(N)->getMatchNumber() << ",\n";
+ return 2;
+
+ case MatcherNode::CheckPatternPredicate: {
+ StringRef Pred = cast<CheckPatternPredicateMatcherNode>(N)->getPredicate();
+ OS << "OPC_CheckPatternPredicate, " << getPatternPredicate(Pred) << ',';
+ OS.PadToColumn(CommentIndent) << "// " << Pred << '\n';
+ return 2;
+ }
+ case MatcherNode::CheckPredicate: {
+ StringRef Pred = cast<CheckPredicateMatcherNode>(N)->getPredicateName();
+ OS << "OPC_CheckPredicate, " << getNodePredicate(Pred) << ',';
+ OS.PadToColumn(CommentIndent) << "// " << Pred << '\n';
+ return 2;
+ }
+
+ case MatcherNode::CheckOpcode:
+ OS << "OPC_CheckOpcode, "
+ << cast<CheckOpcodeMatcherNode>(N)->getOpcodeName() << ",\n";
+ return 2;
+
+ case MatcherNode::CheckType:
+ OS << "OPC_CheckType, "
+ << getEnumName(cast<CheckTypeMatcherNode>(N)->getType()) << ",\n";
+ return 2;
+
+ case MatcherNode::CheckInteger: {
+ int64_t Val = cast<CheckIntegerMatcherNode>(N)->getValue();
+ OS << "OPC_CheckInteger" << ClassifyInt(Val) << ", ";
+ return EmitInt(Val, OS)+1;
+ }
+ case MatcherNode::CheckCondCode:
+ OS << "OPC_CheckCondCode, ISD::"
+ << cast<CheckCondCodeMatcherNode>(N)->getCondCodeName() << ",\n";
+ return 2;
+
+ case MatcherNode::CheckValueType:
+ OS << "OPC_CheckValueType, MVT::"
+ << cast<CheckValueTypeMatcherNode>(N)->getTypeName() << ",\n";
+ return 2;
+
+ case MatcherNode::CheckComplexPat:
+ OS << "OPC_CheckComplexPat, 0/*XXX*/,\n";
+ return 2;
+
+ case MatcherNode::CheckAndImm: {
+ int64_t Val = cast<CheckAndImmMatcherNode>(N)->getValue();
+ OS << "OPC_CheckAndImm" << ClassifyInt(Val) << ", ";
+ return EmitInt(Val, OS)+1;
+ }
+
+ case MatcherNode::CheckOrImm: {
+ int64_t Val = cast<CheckOrImmMatcherNode>(N)->getValue();
+ OS << "OPC_CheckOrImm" << ClassifyInt(Val) << ", ";
+ return EmitInt(Val, OS)+1;
+ }
+ case MatcherNode::CheckProfitableToFold:
+ OS << "OPC_IsProfitableToFold,\n";
+ return 1;
+ case MatcherNode::CheckLegalToFold:
+ OS << "OPC_IsLegalToFold,\n";
+ return 1;
+ }
+ assert(0 && "Unreachable");
+ return 0;
+}
+
+/// EmitMatcherAndChildren - Emit the bytes for the specified matcher subtree.
+unsigned MatcherTableEmitter::
+EmitMatcherAndChildren(const MatcherNode *N, unsigned Indent) {
+ unsigned Size = 0;
+ while (1) {
+ // Push is a special case since it is binary.
+ if (const PushMatcherNode *PMN = dyn_cast<PushMatcherNode>(N)) {
+ // We need to encode the child and the offset of the failure code before
+ // emitting either of them. Handle this by buffering the output into a
+ // string while we get the size.
+ SmallString<128> TmpBuf;
+ unsigned ChildSize;
+ {
+ raw_svector_ostream OS(TmpBuf);
+ formatted_raw_ostream FOS(OS);
+ ChildSize =
+ EmitMatcherAndChildren(cast<PushMatcherNode>(N)->getChild(),Indent+1);
+ }
+
+ if (ChildSize > 255) {
+ errs() <<
+ "Tblgen internal error: can't handle predicate this complex yet\n";
+ exit(1);
+ }
+
+ OS.PadToColumn(Indent*2);
+ OS << "OPC_Push, " << ChildSize << ",\n";
+ OS << TmpBuf.str();
+
+ Size += 2 + ChildSize;
+
+ N = PMN->getFailure();
+ continue;
+ }
+
+ Size += EmitMatcher(N, Indent);
+
+ // If there are children of this node, iterate to them, otherwise we're
+ // done.
+ if (const MatcherNodeWithChild *MNWC = dyn_cast<MatcherNodeWithChild>(N))
+ N = MNWC->getChild();
+ else
+ return Size;
+ }
+}
+
+void MatcherTableEmitter::EmitPredicateFunctions() {
+ OS << "bool CheckPatternPredicate(unsigned PredNo) const {\n";
+ OS << " switch (PredNo) {\n";
+ OS << " default: assert(0 && \"Invalid predicate in table?\");\n";
+ for (unsigned i = 0, e = PatternPredicates.size(); i != e; ++i)
+ OS << " case " << i << ": return " << PatternPredicates[i] << ";\n";
+ OS << " }\n";
+ OS << "}\n\n";
+
+ OS << "bool CheckNodePredicate(SDNode *N, unsigned PredNo) const {\n";
+ OS << " switch (PredNo) {\n";
+ OS << " default: assert(0 && \"Invalid predicate in table?\");\n";
+ for (unsigned i = 0, e = NodePredicates.size(); i != e; ++i)
+ OS << " case " << i << ": return " << NodePredicates[i] << "(N);\n";
+ OS << " }\n";
+ OS << "}\n\n";
+}
+
+
+void llvm::EmitMatcherTable(const MatcherNode *Matcher, raw_ostream &O) {
+ formatted_raw_ostream OS(O);
+
+ OS << "// The main instruction selector code.\n";
+ OS << "SDNode *SelectCode2(SDNode *N) {\n";
+
+ MatcherTableEmitter MatcherEmitter(OS);
+
+ OS << " static const unsigned char MatcherTable[] = {\n";
+ unsigned TotalSize = MatcherEmitter.EmitMatcherAndChildren(Matcher, 2);
+ OS << " 0\n }; // Total Array size is " << (TotalSize+1) << " bytes\n\n";
+ OS << " return SelectCodeCommon(N, MatcherTable,sizeof(MatcherTable));\n}\n";
+ OS << "\n";
+
+ // Next up, emit the function for node and pattern predicates:
+ MatcherEmitter.EmitPredicateFunctions();
+}
diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp
new file mode 100644
index 0000000..07ab472
--- /dev/null
+++ b/utils/TableGen/DAGISelMatcherGen.cpp
@@ -0,0 +1,328 @@
+//===- DAGISelMatcherGen.cpp - Matcher generator --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DAGISelMatcher.h"
+#include "CodeGenDAGPatterns.h"
+#include "Record.h"
+#include "llvm/ADT/StringMap.h"
+using namespace llvm;
+
+namespace {
+ class MatcherGen {
+ const PatternToMatch &Pattern;
+ const CodeGenDAGPatterns &CGP;
+
+ /// PatWithNoTypes - This is a clone of Pattern.getSrcPattern() that starts
+ /// out with all of the types removed. This allows us to insert type checks
+ /// as we scan the tree.
+ TreePatternNode *PatWithNoTypes;
+
+ /// VariableMap - A map from variable names ('$dst') to the recorded operand
+ /// number that they were captured as. These are biased by 1 to make
+ /// insertion easier.
+ StringMap<unsigned> VariableMap;
+ unsigned NextRecordedOperandNo;
+
+ MatcherNodeWithChild *Matcher;
+ MatcherNodeWithChild *CurPredicate;
+ public:
+ MatcherGen(const PatternToMatch &pattern, const CodeGenDAGPatterns &cgp);
+
+ ~MatcherGen() {
+ delete PatWithNoTypes;
+ }
+
+ void EmitMatcherCode();
+
+ MatcherNodeWithChild *GetMatcher() const { return Matcher; }
+ MatcherNodeWithChild *GetCurPredicate() const { return CurPredicate; }
+ private:
+ void AddMatcherNode(MatcherNodeWithChild *NewNode);
+ void InferPossibleTypes();
+ void EmitMatchCode(const TreePatternNode *N, TreePatternNode *NodeNoTypes);
+ void EmitLeafMatchCode(const TreePatternNode *N);
+ void EmitOperatorMatchCode(const TreePatternNode *N,
+ TreePatternNode *NodeNoTypes);
+ };
+
+} // end anon namespace.
+
+MatcherGen::MatcherGen(const PatternToMatch &pattern,
+ const CodeGenDAGPatterns &cgp)
+: Pattern(pattern), CGP(cgp), NextRecordedOperandNo(0),
+ Matcher(0), CurPredicate(0) {
+ // We need to produce the matcher tree for the patterns source pattern. To do
+ // this we need to match the structure as well as the types. To do the type
+ // matching, we want to figure out the fewest number of type checks we need to
+ // emit. For example, if there is only one integer type supported by a
+ // target, there should be no type comparisons at all for integer patterns!
+ //
+ // To figure out the fewest number of type checks needed, clone the pattern,
+ // remove the types, then perform type inference on the pattern as a whole.
+ // If there are unresolved types, emit an explicit check for those types,
+ // apply the type to the tree, then rerun type inference. Iterate until all
+ // types are resolved.
+ //
+ PatWithNoTypes = Pattern.getSrcPattern()->clone();
+ PatWithNoTypes->RemoveAllTypes();
+
+ // If there are types that are manifestly known, infer them.
+ InferPossibleTypes();
+}
+
+/// InferPossibleTypes - As we emit the pattern, we end up generating type
+/// checks and applying them to the 'PatWithNoTypes' tree. As we do this, we
+/// want to propagate implied types as far throughout the tree as possible so
+/// that we avoid doing redundant type checks. This does the type propagation.
+void MatcherGen::InferPossibleTypes() {
+ // TP - Get *SOME* tree pattern, we don't care which. It is only used for
+ // diagnostics, which we know are impossible at this point.
+ TreePattern &TP = *CGP.pf_begin()->second;
+
+ try {
+ bool MadeChange = true;
+ while (MadeChange)
+ MadeChange = PatWithNoTypes->ApplyTypeConstraints(TP,
+ true/*Ignore reg constraints*/);
+ } catch (...) {
+ errs() << "Type constraint application shouldn't fail!";
+ abort();
+ }
+}
+
+
+/// AddMatcherNode - Add a matcher node to the current graph we're building.
+void MatcherGen::AddMatcherNode(MatcherNodeWithChild *NewNode) {
+ if (CurPredicate != 0)
+ CurPredicate->setChild(NewNode);
+ else
+ Matcher = NewNode;
+ CurPredicate = NewNode;
+}
+
+
+
+/// EmitLeafMatchCode - Generate matching code for leaf nodes.
+void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) {
+ assert(N->isLeaf() && "Not a leaf?");
+ // Direct match against an integer constant.
+ if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue()))
+ return AddMatcherNode(new CheckIntegerMatcherNode(II->getValue()));
+
+ DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue());
+ if (DI == 0) {
+ errs() << "Unknown leaf kind: " << *DI << "\n";
+ abort();
+ }
+
+ Record *LeafRec = DI->getDef();
+ if (// Handle register references. Nothing to do here, they always match.
+ LeafRec->isSubClassOf("RegisterClass") ||
+ LeafRec->isSubClassOf("PointerLikeRegClass") ||
+ LeafRec->isSubClassOf("Register") ||
+ // Place holder for SRCVALUE nodes. Nothing to do here.
+ LeafRec->getName() == "srcvalue")
+ return;
+
+ if (LeafRec->isSubClassOf("ValueType"))
+ return AddMatcherNode(new CheckValueTypeMatcherNode(LeafRec->getName()));
+
+ if (LeafRec->isSubClassOf("CondCode"))
+ return AddMatcherNode(new CheckCondCodeMatcherNode(LeafRec->getName()));
+
+ if (LeafRec->isSubClassOf("ComplexPattern")) {
+ // Handle complex pattern.
+ const ComplexPattern &CP = CGP.getComplexPattern(LeafRec);
+ return AddMatcherNode(new CheckComplexPatMatcherNode(CP));
+ }
+
+ errs() << "Unknown leaf kind: " << *N << "\n";
+ abort();
+}
+
+void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N,
+ TreePatternNode *NodeNoTypes) {
+ assert(!N->isLeaf() && "Not an operator?");
+ const SDNodeInfo &CInfo = CGP.getSDNodeInfo(N->getOperator());
+
+ // If this is an 'and R, 1234' where the operation is AND/OR and the RHS is
+ // a constant without a predicate fn that has more that one bit set, handle
+ // this as a special case. This is usually for targets that have special
+ // handling of certain large constants (e.g. alpha with it's 8/16/32-bit
+ // handling stuff). Using these instructions is often far more efficient
+ // than materializing the constant. Unfortunately, both the instcombiner
+ // and the dag combiner can often infer that bits are dead, and thus drop
+ // them from the mask in the dag. For example, it might turn 'AND X, 255'
+ // into 'AND X, 254' if it knows the low bit is set. Emit code that checks
+ // to handle this.
+ if ((N->getOperator()->getName() == "and" ||
+ N->getOperator()->getName() == "or") &&
+ N->getChild(1)->isLeaf() && N->getChild(1)->getPredicateFns().empty()) {
+ if (IntInit *II = dynamic_cast<IntInit*>(N->getChild(1)->getLeafValue())) {
+ if (!isPowerOf2_32(II->getValue())) { // Don't bother with single bits.
+ if (N->getOperator()->getName() == "and")
+ AddMatcherNode(new CheckAndImmMatcherNode(II->getValue()));
+ else
+ AddMatcherNode(new CheckOrImmMatcherNode(II->getValue()));
+
+ // Match the LHS of the AND as appropriate.
+ AddMatcherNode(new MoveChildMatcherNode(0));
+ EmitMatchCode(N->getChild(0), NodeNoTypes->getChild(0));
+ AddMatcherNode(new MoveParentMatcherNode());
+ return;
+ }
+ }
+ }
+
+ // Check that the current opcode lines up.
+ AddMatcherNode(new CheckOpcodeMatcherNode(CInfo.getEnumName()));
+
+ // If this node has a chain, then the chain is operand #0 is the SDNode, and
+ // the child numbers of the node are all offset by one.
+ unsigned OpNo = 0;
+ if (N->NodeHasProperty(SDNPHasChain, CGP))
+ OpNo = 1;
+
+ // If this node is not the root and the subtree underneath it produces a
+ // chain, then the result of matching the node is also produce a chain.
+ // Beyond that, this means that we're also folding (at least) the root node
+ // into the node that produce the chain (for example, matching
+ // "(add reg, (load ptr))" as a add_with_memory on X86). This is problematic,
+ // if the 'reg' node also uses the load (say, its chain). Graphically:
+ //
+ // [LD]
+ // ^ ^
+ // | \ DAG's like cheese.
+ // / |
+ // / [YY]
+ // | ^
+ // [XX]--/
+ //
+ // It would be invalid to fold XX and LD. In this case, folding the two
+ // nodes together would induce a cycle in the DAG, making it a cyclic DAG (!).
+ // To prevent this, we emit a dynamic check for legality before allowing this
+ // to be folded.
+ //
+ const TreePatternNode *Root = Pattern.getSrcPattern();
+ if (N != Root && // Not the root of the pattern.
+ N->TreeHasProperty(SDNPHasChain, CGP)) { // Has a chain somewhere in tree.
+
+ AddMatcherNode(new CheckProfitableToFoldMatcherNode());
+
+ // If this non-root node produces a chain, we may need to emit a validity
+ // check.
+ if (OpNo != 0) {
+ // If there is a node between the root and this node, then we definitely
+ // need to emit the check.
+ bool NeedCheck = !Root->hasChild(N);
+
+ // If it *is* an immediate child of the root, we can still need a check if
+ // the root SDNode has multiple inputs. For us, this means that it is an
+ // intrinsic, has multiple operands, or has other inputs like chain or
+ // flag).
+ if (!NeedCheck) {
+ const SDNodeInfo &PInfo = CGP.getSDNodeInfo(Root->getOperator());
+ NeedCheck =
+ Root->getOperator() == CGP.get_intrinsic_void_sdnode() ||
+ Root->getOperator() == CGP.get_intrinsic_w_chain_sdnode() ||
+ Root->getOperator() == CGP.get_intrinsic_wo_chain_sdnode() ||
+ PInfo.getNumOperands() > 1 ||
+ PInfo.hasProperty(SDNPHasChain) ||
+ PInfo.hasProperty(SDNPInFlag) ||
+ PInfo.hasProperty(SDNPOptInFlag);
+ }
+
+ if (NeedCheck)
+ AddMatcherNode(new CheckLegalToFoldMatcherNode());
+ }
+ }
+
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {
+ // Get the code suitable for matching this child. Move to the child, check
+ // it then move back to the parent.
+ AddMatcherNode(new MoveChildMatcherNode(i));
+ EmitMatchCode(N->getChild(i), NodeNoTypes->getChild(i));
+ AddMatcherNode(new MoveParentMatcherNode());
+ }
+}
+
+
+void MatcherGen::EmitMatchCode(const TreePatternNode *N,
+ TreePatternNode *NodeNoTypes) {
+ // If N and NodeNoTypes don't agree on a type, then this is a case where we
+ // need to do a type check. Emit the check, apply the tyep to NodeNoTypes and
+ // reinfer any correlated types.
+ if (NodeNoTypes->getExtTypes() != N->getExtTypes()) {
+ AddMatcherNode(new CheckTypeMatcherNode(N->getTypeNum(0)));
+ NodeNoTypes->setTypes(N->getExtTypes());
+ InferPossibleTypes();
+ }
+
+
+ // If this node has a name associated with it, capture it in VariableMap. If
+ // we already saw this in the pattern, emit code to verify dagness.
+ if (!N->getName().empty()) {
+ unsigned &VarMapEntry = VariableMap[N->getName()];
+ if (VarMapEntry == 0) {
+ VarMapEntry = ++NextRecordedOperandNo;
+ AddMatcherNode(new RecordMatcherNode());
+ } else {
+ // If we get here, this is a second reference to a specific name. Since
+ // we already have checked that the first reference is valid, we don't
+ // have to recursively match it, just check that it's the same as the
+ // previously named thing.
+ AddMatcherNode(new CheckSameMatcherNode(VarMapEntry-1));
+ return;
+ }
+ }
+
+ // If there are node predicates for this node, generate their checks.
+ for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i)
+ AddMatcherNode(new CheckPredicateMatcherNode(N->getPredicateFns()[i]));
+
+ if (N->isLeaf())
+ EmitLeafMatchCode(N);
+ else
+ EmitOperatorMatchCode(N, NodeNoTypes);
+}
+
+void MatcherGen::EmitMatcherCode() {
+ // If the pattern has a predicate on it (e.g. only enabled when a subtarget
+ // feature is around, do the check).
+ if (!Pattern.getPredicateCheck().empty())
+ AddMatcherNode(new
+ CheckPatternPredicateMatcherNode(Pattern.getPredicateCheck()));
+
+ // Emit the matcher for the pattern structure and types.
+ EmitMatchCode(Pattern.getSrcPattern(), PatWithNoTypes);
+}
+
+
+MatcherNode *llvm::ConvertPatternToMatcher(const PatternToMatch &Pattern,
+ const CodeGenDAGPatterns &CGP) {
+ MatcherGen Gen(Pattern, CGP);
+
+ // Generate the code for the matcher.
+ Gen.EmitMatcherCode();
+
+ // If the match succeeds, then we generate Pattern.
+ EmitNodeMatcherNode *Result = new EmitNodeMatcherNode(Pattern);
+
+ // Link it into the pattern.
+ if (MatcherNodeWithChild *Pred = Gen.GetCurPredicate()) {
+ Pred->setChild(Result);
+ return Gen.GetMatcher();
+ }
+
+ // Unconditional match.
+ return Result;
+}
+
+
+
diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp
new file mode 100644
index 0000000..9aad2f6
--- /dev/null
+++ b/utils/TableGen/EDEmitter.cpp
@@ -0,0 +1,665 @@
+//===- EDEmitter.cpp - Generate instruction descriptions for ED -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting a description of each
+// instruction in a format that the enhanced disassembler can use to tokenize
+// and parse instructions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "EDEmitter.h"
+
+#include "AsmWriterInst.h"
+#include "CodeGenTarget.h"
+#include "Record.h"
+
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <vector>
+#include <string>
+
+#define MAX_OPERANDS 5
+#define MAX_SYNTAXES 2
+
+using namespace llvm;
+
+///////////////////////////////////////////////////////////
+// Support classes for emitting nested C data structures //
+///////////////////////////////////////////////////////////
+
+namespace {
+
+ class EnumEmitter {
+ private:
+ std::string Name;
+ std::vector<std::string> Entries;
+ public:
+ EnumEmitter(const char *N) : Name(N) {
+ }
+ int addEntry(const char *e) {
+ Entries.push_back(std::string(e));
+ return Entries.size() - 1;
+ }
+ void emit(raw_ostream &o, unsigned int &i) {
+ o.indent(i) << "enum " << Name.c_str() << " {" << "\n";
+ i += 2;
+
+ unsigned int index = 0;
+ unsigned int numEntries = Entries.size();
+ for(index = 0; index < numEntries; ++index) {
+ o.indent(i) << Entries[index];
+ if(index < (numEntries - 1))
+ o << ",";
+ o << "\n";
+ }
+
+ i -= 2;
+ o.indent(i) << "};" << "\n";
+ }
+
+ void emitAsFlags(raw_ostream &o, unsigned int &i) {
+ o.indent(i) << "enum " << Name.c_str() << " {" << "\n";
+ i += 2;
+
+ unsigned int index = 0;
+ unsigned int numEntries = Entries.size();
+ unsigned int flag = 1;
+ for (index = 0; index < numEntries; ++index) {
+ o.indent(i) << Entries[index] << " = " << format("0x%x", flag);
+ if (index < (numEntries - 1))
+ o << ",";
+ o << "\n";
+ flag <<= 1;
+ }
+
+ i -= 2;
+ o.indent(i) << "};" << "\n";
+ }
+ };
+
+ class StructEmitter {
+ private:
+ std::string Name;
+ std::vector<std::string> MemberTypes;
+ std::vector<std::string> MemberNames;
+ public:
+ StructEmitter(const char *N) : Name(N) {
+ }
+ void addMember(const char *t, const char *n) {
+ MemberTypes.push_back(std::string(t));
+ MemberNames.push_back(std::string(n));
+ }
+ void emit(raw_ostream &o, unsigned int &i) {
+ o.indent(i) << "struct " << Name.c_str() << " {" << "\n";
+ i += 2;
+
+ unsigned int index = 0;
+ unsigned int numMembers = MemberTypes.size();
+ for (index = 0; index < numMembers; ++index) {
+ o.indent(i) << MemberTypes[index] << " " << MemberNames[index] << ";";
+ o << "\n";
+ }
+
+ i -= 2;
+ o.indent(i) << "};" << "\n";
+ }
+ };
+
+ class ConstantEmitter {
+ public:
+ virtual ~ConstantEmitter() { }
+ virtual void emit(raw_ostream &o, unsigned int &i) = 0;
+ };
+
+ class LiteralConstantEmitter : public ConstantEmitter {
+ private:
+ std::string Literal;
+ public:
+ LiteralConstantEmitter(const char *literal) : Literal(literal) {
+ }
+ LiteralConstantEmitter(int literal) {
+ char buf[256];
+ snprintf(buf, 256, "%d", literal);
+ Literal = buf;
+ }
+ void emit(raw_ostream &o, unsigned int &i) {
+ o << Literal;
+ }
+ };
+
+ class CompoundConstantEmitter : public ConstantEmitter {
+ private:
+ std::vector<ConstantEmitter*> Entries;
+ public:
+ CompoundConstantEmitter() {
+ }
+ ~CompoundConstantEmitter() {
+ unsigned int index;
+ unsigned int numEntries = Entries.size();
+ for (index = 0; index < numEntries; ++index) {
+ delete Entries[index];
+ }
+ }
+ CompoundConstantEmitter &addEntry(ConstantEmitter *e) {
+ Entries.push_back(e);
+ return *this;
+ }
+ void emit(raw_ostream &o, unsigned int &i) {
+ o << "{" << "\n";
+ i += 2;
+
+ unsigned int index;
+ unsigned int numEntries = Entries.size();
+ for (index = 0; index < numEntries; ++index) {
+ o.indent(i);
+ Entries[index]->emit(o, i);
+ if (index < (numEntries - 1))
+ o << ",";
+ o << "\n";
+ }
+
+ i -= 2;
+ o.indent(i) << "}";
+ }
+ };
+
+ class FlagsConstantEmitter : public ConstantEmitter {
+ private:
+ std::vector<std::string> Flags;
+ public:
+ FlagsConstantEmitter() {
+ }
+ FlagsConstantEmitter &addEntry(const char *f) {
+ Flags.push_back(std::string(f));
+ return *this;
+ }
+ void emit(raw_ostream &o, unsigned int &i) {
+ unsigned int index;
+ unsigned int numFlags = Flags.size();
+ if (numFlags == 0)
+ o << "0";
+
+ for (index = 0; index < numFlags; ++index) {
+ o << Flags[index].c_str();
+ if (index < (numFlags - 1))
+ o << " | ";
+ }
+ }
+ };
+}
+
+EDEmitter::EDEmitter(RecordKeeper &R) : Records(R) {
+}
+
+/// populateOperandOrder - Accepts a CodeGenInstruction and generates its
+/// AsmWriterInst for the desired assembly syntax, giving an ordered list of
+/// operands in the order they appear in the printed instruction. Then, for
+/// each entry in that list, determines the index of the same operand in the
+/// CodeGenInstruction, and emits the resulting mapping into an array, filling
+/// in unused slots with -1.
+///
+/// @arg operandOrder - The array that will be populated with the operand
+/// mapping. Each entry will contain -1 (invalid index
+/// into the operands present in the AsmString) or a number
+/// representing an index in the operand descriptor array.
+/// @arg inst - The instruction to use when looking up the operands
+/// @arg syntax - The syntax to use, according to LLVM's enumeration
+void populateOperandOrder(CompoundConstantEmitter *operandOrder,
+ const CodeGenInstruction &inst,
+ unsigned syntax) {
+ unsigned int numArgs = 0;
+
+ AsmWriterInst awInst(inst, syntax, -1, -1);
+
+ std::vector<AsmWriterOperand>::iterator operandIterator;
+
+ for (operandIterator = awInst.Operands.begin();
+ operandIterator != awInst.Operands.end();
+ ++operandIterator) {
+ if (operandIterator->OperandType ==
+ AsmWriterOperand::isMachineInstrOperand) {
+ char buf[2];
+ snprintf(buf, sizeof(buf), "%u", operandIterator->CGIOpNo);
+ operandOrder->addEntry(new LiteralConstantEmitter(buf));
+ numArgs++;
+ }
+ }
+
+ for(; numArgs < MAX_OPERANDS; numArgs++) {
+ operandOrder->addEntry(new LiteralConstantEmitter("-1"));
+ }
+}
+
+/////////////////////////////////////////////////////
+// Support functions for handling X86 instructions //
+/////////////////////////////////////////////////////
+
+#define ADDFLAG(flag) flags->addEntry(flag)
+
+#define REG(str) if (name == str) { ADDFLAG("kOperandFlagRegister"); return 0; }
+#define MEM(str) if (name == str) { ADDFLAG("kOperandFlagMemory"); return 0; }
+#define LEA(str) if (name == str) { ADDFLAG("kOperandFlagEffectiveAddress"); \
+ return 0; }
+#define IMM(str) if (name == str) { ADDFLAG("kOperandFlagImmediate"); \
+ return 0; }
+#define PCR(str) if (name == str) { ADDFLAG("kOperandFlagMemory"); \
+ ADDFLAG("kOperandFlagPCRelative"); \
+ return 0; }
+
+/// X86FlagFromOpName - Processes the name of a single X86 operand (which is
+/// actually its type) and translates it into an operand flag
+///
+/// @arg flags - The flags object to add the flag to
+/// @arg name - The name of the operand
+static int X86FlagFromOpName(FlagsConstantEmitter *flags,
+ const std::string &name) {
+ REG("GR8");
+ REG("GR8_NOREX");
+ REG("GR16");
+ REG("GR32");
+ REG("GR32_NOREX");
+ REG("FR32");
+ REG("RFP32");
+ REG("GR64");
+ REG("FR64");
+ REG("VR64");
+ REG("RFP64");
+ REG("RFP80");
+ REG("VR128");
+ REG("RST");
+ REG("SEGMENT_REG");
+ REG("DEBUG_REG");
+ REG("CONTROL_REG_32");
+ REG("CONTROL_REG_64");
+
+ MEM("i8mem");
+ MEM("i8mem_NOREX");
+ MEM("i16mem");
+ MEM("i32mem");
+ MEM("f32mem");
+ MEM("ssmem");
+ MEM("opaque32mem");
+ MEM("opaque48mem");
+ MEM("i64mem");
+ MEM("f64mem");
+ MEM("sdmem");
+ MEM("f80mem");
+ MEM("opaque80mem");
+ MEM("i128mem");
+ MEM("f128mem");
+ MEM("opaque512mem");
+
+ LEA("lea32mem");
+ LEA("lea64_32mem");
+ LEA("lea64mem");
+
+ IMM("i8imm");
+ IMM("i16imm");
+ IMM("i16i8imm");
+ IMM("i32imm");
+ IMM("i32imm_pcrel");
+ IMM("i32i8imm");
+ IMM("i64imm");
+ IMM("i64i8imm");
+ IMM("i64i32imm");
+ IMM("i64i32imm_pcrel");
+ IMM("SSECC");
+
+ PCR("brtarget8");
+ PCR("offset8");
+ PCR("offset16");
+ PCR("offset32");
+ PCR("offset64");
+ PCR("brtarget");
+
+ return 1;
+}
+
+#undef REG
+#undef MEM
+#undef LEA
+#undef IMM
+#undef PCR
+#undef ADDFLAG
+
+/// X86PopulateOperands - Handles all the operands in an X86 instruction, adding
+/// the appropriate flags to their descriptors
+///
+/// @operandFlags - A reference the array of operand flag objects
+/// @inst - The instruction to use as a source of information
+static void X86PopulateOperands(
+ FlagsConstantEmitter *(&operandFlags)[MAX_OPERANDS],
+ const CodeGenInstruction &inst) {
+ if (!inst.TheDef->isSubClassOf("X86Inst"))
+ return;
+
+ unsigned int index;
+ unsigned int numOperands = inst.OperandList.size();
+
+ for (index = 0; index < numOperands; ++index) {
+ const CodeGenInstruction::OperandInfo &operandInfo =
+ inst.OperandList[index];
+ Record &rec = *operandInfo.Rec;
+
+ if (X86FlagFromOpName(operandFlags[index], rec.getName())) {
+ errs() << "Operand type: " << rec.getName().c_str() << "\n";
+ errs() << "Operand name: " << operandInfo.Name.c_str() << "\n";
+ errs() << "Instruction mame: " << inst.TheDef->getName().c_str() << "\n";
+ llvm_unreachable("Unhandled type");
+ }
+ }
+}
+
+/// decorate1 - Decorates a named operand with a new flag
+///
+/// @operandFlags - The array of operand flag objects, which don't have names
+/// @inst - The CodeGenInstruction, which provides a way to translate
+/// between names and operand indices
+/// @opName - The name of the operand
+/// @flag - The name of the flag to add
+static inline void decorate1(FlagsConstantEmitter *(&operandFlags)[MAX_OPERANDS],
+ const CodeGenInstruction &inst,
+ const char *opName,
+ const char *opFlag) {
+ unsigned opIndex;
+
+ opIndex = inst.getOperandNamed(std::string(opName));
+
+ operandFlags[opIndex]->addEntry(opFlag);
+}
+
+#define DECORATE1(opName, opFlag) decorate1(operandFlags, inst, opName, opFlag)
+
+#define MOV(source, target) { \
+ instFlags.addEntry("kInstructionFlagMove"); \
+ DECORATE1(source, "kOperandFlagSource"); \
+ DECORATE1(target, "kOperandFlagTarget"); \
+}
+
+#define BRANCH(target) { \
+ instFlags.addEntry("kInstructionFlagBranch"); \
+ DECORATE1(target, "kOperandFlagTarget"); \
+}
+
+#define PUSH(source) { \
+ instFlags.addEntry("kInstructionFlagPush"); \
+ DECORATE1(source, "kOperandFlagSource"); \
+}
+
+#define POP(target) { \
+ instFlags.addEntry("kInstructionFlagPop"); \
+ DECORATE1(target, "kOperandFlagTarget"); \
+}
+
+#define CALL(target) { \
+ instFlags.addEntry("kInstructionFlagCall"); \
+ DECORATE1(target, "kOperandFlagTarget"); \
+}
+
+#define RETURN() { \
+ instFlags.addEntry("kInstructionFlagReturn"); \
+}
+
+/// X86ExtractSemantics - Performs various checks on the name of an X86
+/// instruction to determine what sort of an instruction it is and then adds
+/// the appropriate flags to the instruction and its operands
+///
+/// @arg instFlags - A reference to the flags for the instruction as a whole
+/// @arg operandFlags - A reference to the array of operand flag object pointers
+/// @arg inst - A reference to the original instruction
+static void X86ExtractSemantics(FlagsConstantEmitter &instFlags,
+ FlagsConstantEmitter *(&operandFlags)[MAX_OPERANDS],
+ const CodeGenInstruction &inst) {
+ const std::string &name = inst.TheDef->getName();
+
+ if (name.find("MOV") != name.npos) {
+ if (name.find("MOV_V") != name.npos) {
+ // ignore (this is a pseudoinstruction)
+ }
+ else if (name.find("MASK") != name.npos) {
+ // ignore (this is a masking move)
+ }
+ else if (name.find("r0") != name.npos) {
+ // ignore (this is a pseudoinstruction)
+ }
+ else if (name.find("PS") != name.npos ||
+ name.find("PD") != name.npos) {
+ // ignore (this is a shuffling move)
+ }
+ else if (name.find("MOVS") != name.npos) {
+ // ignore (this is a string move)
+ }
+ else if (name.find("_F") != name.npos) {
+ // TODO handle _F moves to ST(0)
+ }
+ else if (name.find("a") != name.npos) {
+ // TODO handle moves to/from %ax
+ }
+ else if (name.find("CMOV") != name.npos) {
+ MOV("src2", "dst");
+ }
+ else if (name.find("PC") != name.npos) {
+ MOV("label", "reg")
+ }
+ else {
+ MOV("src", "dst");
+ }
+ }
+
+ if (name.find("JMP") != name.npos ||
+ name.find("J") == 0) {
+ if (name.find("FAR") != name.npos && name.find("i") != name.npos) {
+ BRANCH("off");
+ }
+ else {
+ BRANCH("dst");
+ }
+ }
+
+ if (name.find("PUSH") != name.npos) {
+ if (name.find("FS") != name.npos ||
+ name.find("GS") != name.npos) {
+ instFlags.addEntry("kInstructionFlagPush");
+ // TODO add support for fixed operands
+ }
+ else if (name.find("F") != name.npos) {
+ // ignore (this pushes onto the FP stack)
+ }
+ else if (name[name.length() - 1] == 'm') {
+ PUSH("src");
+ }
+ else if (name.find("i") != name.npos) {
+ PUSH("imm");
+ }
+ else {
+ PUSH("reg");
+ }
+ }
+
+ if (name.find("POP") != name.npos) {
+ if (name.find("POPCNT") != name.npos) {
+ // ignore (not a real pop)
+ }
+ else if (name.find("FS") != name.npos ||
+ name.find("GS") != name.npos) {
+ instFlags.addEntry("kInstructionFlagPop");
+ // TODO add support for fixed operands
+ }
+ else if (name.find("F") != name.npos) {
+ // ignore (this pops from the FP stack)
+ }
+ else if (name[name.length() - 1] == 'm') {
+ POP("dst");
+ }
+ else {
+ POP("reg");
+ }
+ }
+
+ if (name.find("CALL") != name.npos) {
+ if (name.find("ADJ") != name.npos) {
+ // ignore (not a call)
+ }
+ else if (name.find("SYSCALL") != name.npos) {
+ // ignore (doesn't go anywhere we know about)
+ }
+ else if (name.find("VMCALL") != name.npos) {
+ // ignore (rather different semantics than a regular call)
+ }
+ else if (name.find("FAR") != name.npos && name.find("i") != name.npos) {
+ CALL("off");
+ }
+ else {
+ CALL("dst");
+ }
+ }
+
+ if (name.find("RET") != name.npos) {
+ RETURN();
+ }
+}
+
+#undef MOV
+#undef BRANCH
+#undef PUSH
+#undef POP
+#undef CALL
+#undef RETURN
+
+#undef COND_DECORATE_2
+#undef COND_DECORATE_1
+#undef DECORATE1
+
+/// populateInstInfo - Fills an array of InstInfos with information about each
+/// instruction in a target
+///
+/// @arg infoArray - The array of InstInfo objects to populate
+/// @arg target - The CodeGenTarget to use as a source of instructions
+static void populateInstInfo(CompoundConstantEmitter &infoArray,
+ CodeGenTarget &target) {
+ std::vector<const CodeGenInstruction*> numberedInstructions;
+ target.getInstructionsByEnumValue(numberedInstructions);
+
+ unsigned int index;
+ unsigned int numInstructions = numberedInstructions.size();
+
+ for (index = 0; index < numInstructions; ++index) {
+ const CodeGenInstruction& inst = *numberedInstructions[index];
+
+ CompoundConstantEmitter *infoStruct = new CompoundConstantEmitter;
+ infoArray.addEntry(infoStruct);
+
+ FlagsConstantEmitter *instFlags = new FlagsConstantEmitter;
+ infoStruct->addEntry(instFlags);
+
+ LiteralConstantEmitter *numOperandsEmitter =
+ new LiteralConstantEmitter(inst.OperandList.size());
+ infoStruct->addEntry(numOperandsEmitter);
+
+ CompoundConstantEmitter *operandFlagArray = new CompoundConstantEmitter;
+ infoStruct->addEntry(operandFlagArray);
+
+ FlagsConstantEmitter *operandFlags[MAX_OPERANDS];
+
+ for (unsigned operandIndex = 0; operandIndex < MAX_OPERANDS; ++operandIndex) {
+ operandFlags[operandIndex] = new FlagsConstantEmitter;
+ operandFlagArray->addEntry(operandFlags[operandIndex]);
+ }
+
+ unsigned numSyntaxes = 0;
+
+ if (target.getName() == "X86") {
+ X86PopulateOperands(operandFlags, inst);
+ X86ExtractSemantics(*instFlags, operandFlags, inst);
+ numSyntaxes = 2;
+ }
+
+ CompoundConstantEmitter *operandOrderArray = new CompoundConstantEmitter;
+ infoStruct->addEntry(operandOrderArray);
+
+ for (unsigned syntaxIndex = 0; syntaxIndex < MAX_SYNTAXES; ++syntaxIndex) {
+ CompoundConstantEmitter *operandOrder = new CompoundConstantEmitter;
+ operandOrderArray->addEntry(operandOrder);
+
+ if (syntaxIndex < numSyntaxes) {
+ populateOperandOrder(operandOrder, inst, syntaxIndex);
+ }
+ else {
+ for (unsigned operandIndex = 0;
+ operandIndex < MAX_OPERANDS;
+ ++operandIndex) {
+ operandOrder->addEntry(new LiteralConstantEmitter("-1"));
+ }
+ }
+ }
+ }
+}
+
+void EDEmitter::run(raw_ostream &o) {
+ unsigned int i = 0;
+
+ CompoundConstantEmitter infoArray;
+ CodeGenTarget target;
+
+ populateInstInfo(infoArray, target);
+
+ o << "InstInfo instInfo" << target.getName().c_str() << "[] = ";
+ infoArray.emit(o, i);
+ o << ";" << "\n";
+}
+
+void EDEmitter::runHeader(raw_ostream &o) {
+ EmitSourceFileHeader("Enhanced Disassembly Info Header", o);
+
+ o << "#ifndef EDInfo_" << "\n";
+ o << "#define EDInfo_" << "\n";
+ o << "\n";
+ o << "#include <inttypes.h>" << "\n";
+ o << "\n";
+ o << "#define MAX_OPERANDS " << format("%d", MAX_OPERANDS) << "\n";
+ o << "#define MAX_SYNTAXES " << format("%d", MAX_SYNTAXES) << "\n";
+ o << "\n";
+
+ unsigned int i = 0;
+
+ EnumEmitter operandFlags("OperandFlags");
+ operandFlags.addEntry("kOperandFlagImmediate");
+ operandFlags.addEntry("kOperandFlagRegister");
+ operandFlags.addEntry("kOperandFlagMemory");
+ operandFlags.addEntry("kOperandFlagEffectiveAddress");
+ operandFlags.addEntry("kOperandFlagPCRelative");
+ operandFlags.addEntry("kOperandFlagSource");
+ operandFlags.addEntry("kOperandFlagTarget");
+ operandFlags.emitAsFlags(o, i);
+
+ o << "\n";
+
+ EnumEmitter instructionFlags("InstructionFlags");
+ instructionFlags.addEntry("kInstructionFlagMove");
+ instructionFlags.addEntry("kInstructionFlagBranch");
+ instructionFlags.addEntry("kInstructionFlagPush");
+ instructionFlags.addEntry("kInstructionFlagPop");
+ instructionFlags.addEntry("kInstructionFlagCall");
+ instructionFlags.addEntry("kInstructionFlagReturn");
+ instructionFlags.emitAsFlags(o, i);
+
+ o << "\n";
+
+ StructEmitter instInfo("InstInfo");
+ instInfo.addMember("uint32_t", "instructionFlags");
+ instInfo.addMember("uint8_t", "numOperands");
+ instInfo.addMember("uint8_t", "operandFlags[MAX_OPERANDS]");
+ instInfo.addMember("const char", "operandOrders[MAX_SYNTAXES][MAX_OPERANDS]");
+ instInfo.emit(o, i);
+
+ o << "\n";
+ o << "#endif" << "\n";
+}
diff --git a/utils/TableGen/EDEmitter.h b/utils/TableGen/EDEmitter.h
new file mode 100644
index 0000000..9e40a8b
--- /dev/null
+++ b/utils/TableGen/EDEmitter.h
@@ -0,0 +1,37 @@
+//===- EDEmitter.h - Generate instruction descriptions for ED ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting a description of each
+// instruction in a format that the semantic disassembler can use to tokenize
+// and parse instructions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SEMANTIC_INFO_EMITTER_H
+#define SEMANTIC_INFO_EMITTER_H
+
+#include "TableGenBackend.h"
+
+namespace llvm {
+
+ class EDEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+ public:
+ EDEmitter(RecordKeeper &R);
+
+ // run - Output the instruction table.
+ void run(raw_ostream &o);
+
+ // runHeader - Emit a header file that allows use of the instruction table.
+ void runHeader(raw_ostream &o);
+ };
+
+} // End llvm namespace
+
+#endif
diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
index cf40c78..898c92a 100644
--- a/utils/TableGen/InstrInfoEmitter.cpp
+++ b/utils/TableGen/InstrInfoEmitter.cpp
@@ -118,7 +118,20 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
Res += "|(1<<TOI::OptionalDef)";
// Fill in constraint info.
- Res += ", " + Inst.OperandList[i].Constraints[j];
+ Res += ", ";
+
+ const CodeGenInstruction::ConstraintInfo &Constraint =
+ Inst.OperandList[i].Constraints[j];
+ if (Constraint.isNone())
+ Res += "0";
+ else if (Constraint.isEarlyClobber())
+ Res += "(1 << TOI::EARLY_CLOBBER)";
+ else {
+ assert(Constraint.isTied());
+ Res += "((" + utostr(Constraint.getTiedOperand()) +
+ " << 16) | (1 << TOI::TIED_TO))";
+ }
+
Result.push_back(Res);
}
}
@@ -346,7 +359,7 @@ void InstrInfoEmitter::emitShiftedValue(Record *R, StringInit *Val,
R->getName() != "IMPLICIT_DEF" &&
R->getName() != "SUBREG_TO_REG" &&
R->getName() != "COPY_TO_REGCLASS" &&
- R->getName() != "DEBUG_VALUE")
+ R->getName() != "DBG_VALUE")
throw R->getName() + " doesn't have a field named '" +
Val->getValue() + "'!";
return;
diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp
index 88fb6c3..2abc94b 100644
--- a/utils/TableGen/LLVMCConfigurationEmitter.cpp
+++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp
@@ -116,7 +116,7 @@ bool IsDagEmpty (const DagInit& d) {
// EscapeVariableName - Escape commas and other symbols not allowed
// in the C++ variable names. Makes it possible to use options named
// like "Wa," (useful for prefix options).
-std::string EscapeVariableName(const std::string& Var) {
+std::string EscapeVariableName (const std::string& Var) {
std::string ret;
for (unsigned i = 0; i != Var.size(); ++i) {
char cur_char = Var[i];
@@ -136,6 +136,21 @@ std::string EscapeVariableName(const std::string& Var) {
return ret;
}
+/// EscapeQuotes - Replace '"' with '\"'.
+std::string EscapeQuotes (const std::string& Var) {
+ std::string ret;
+ for (unsigned i = 0; i != Var.size(); ++i) {
+ char cur_char = Var[i];
+ if (cur_char == '"') {
+ ret += "\\\"";
+ }
+ else {
+ ret.push_back(cur_char);
+ }
+ }
+ return ret;
+}
+
/// OneOf - Does the input string contain this character?
bool OneOf(const char* lst, char c) {
while (*lst) {
@@ -594,7 +609,7 @@ private:
void onHelp (const DagInit& d) {
CheckNumberOfArguments(d, 1);
- optDesc_.Help = InitPtrToString(d.getArg(0));
+ optDesc_.Help = EscapeQuotes(InitPtrToString(d.getArg(0)));
}
void onHidden (const DagInit& d) {
diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index 7c8d288..f20ec00 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/utils/TableGen/TableGen.cpp
@@ -22,6 +22,7 @@
#include "CodeEmitterGen.h"
#include "DAGISelEmitter.h"
#include "DisassemblerEmitter.h"
+#include "EDEmitter.h"
#include "FastISelEmitter.h"
#include "InstrEnumEmitter.h"
#include "InstrInfoEmitter.h"
@@ -58,6 +59,7 @@ enum ActionType {
GenIntrinsic,
GenTgtIntrinsic,
GenLLVMCConf,
+ GenEDHeader, GenEDInfo,
PrintEnums
};
@@ -106,6 +108,10 @@ namespace {
"Generate Clang diagnostic groups"),
clEnumValN(GenLLVMCConf, "gen-llvmc",
"Generate LLVMC configuration library"),
+ clEnumValN(GenEDHeader, "gen-enhanced-disassembly-header",
+ "Generate enhanced disassembly info header"),
+ clEnumValN(GenEDInfo, "gen-enhanced-disassembly-info",
+ "Generate enhanced disassembly info"),
clEnumValN(PrintEnums, "print-enums",
"Print enum values for a class"),
clEnumValEnd));
@@ -259,6 +265,12 @@ int main(int argc, char **argv) {
case GenLLVMCConf:
LLVMCConfigurationEmitter(Records).run(*Out);
break;
+ case GenEDHeader:
+ EDEmitter(Records).runHeader(*Out);
+ break;
+ case GenEDInfo:
+ EDEmitter(Records).run(*Out);
+ break;
case PrintEnums:
{
std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp
index 2b6e30d..3843e56 100644
--- a/utils/TableGen/X86RecognizableInstr.cpp
+++ b/utils/TableGen/X86RecognizableInstr.cpp
@@ -24,6 +24,18 @@
using namespace llvm;
+#define MRM_MAPPING \
+ MAP(C1, 33) \
+ MAP(C2, 34) \
+ MAP(C3, 35) \
+ MAP(C4, 36) \
+ MAP(C8, 37) \
+ MAP(C9, 38) \
+ MAP(E8, 39) \
+ MAP(F0, 40) \
+ MAP(F8, 41) \
+ MAP(F9, 42)
+
// A clone of X86 since we can't depend on something that is generated.
namespace X86Local {
enum {
@@ -38,7 +50,12 @@ namespace X86Local {
MRM4r = 20, MRM5r = 21, MRM6r = 22, MRM7r = 23,
MRM0m = 24, MRM1m = 25, MRM2m = 26, MRM3m = 27,
MRM4m = 28, MRM5m = 29, MRM6m = 30, MRM7m = 31,
- MRMInitReg = 32
+ MRMInitReg = 32,
+
+#define MAP(from, to) MRM_##from = to,
+ MRM_MAPPING
+#undef MAP
+ lastMRM
};
enum {
@@ -47,10 +64,28 @@ namespace X86Local {
D8 = 3, D9 = 4, DA = 5, DB = 6,
DC = 7, DD = 8, DE = 9, DF = 10,
XD = 11, XS = 12,
- T8 = 13, TA = 14
+ T8 = 13, P_TA = 14,
+ P_0F_AE = 16, P_0F_01 = 17
};
}
-
+
+// If rows are added to the opcode extension tables, then corresponding entries
+// must be added here.
+//
+// If the row corresponds to a single byte (i.e., 8f), then add an entry for
+// that byte to ONE_BYTE_EXTENSION_TABLES.
+//
+// If the row corresponds to two bytes where the first is 0f, add an entry for
+// the second byte to TWO_BYTE_EXTENSION_TABLES.
+//
+// If the row corresponds to some other set of bytes, you will need to modify
+// the code in RecognizableInstr::emitDecodePath() as well, and add new prefixes
+// to the X86 TD files, except in two cases: if the first two bytes of such a
+// new combination are 0f 38 or 0f 3a, you just have to add maps called
+// THREE_BYTE_38_EXTENSION_TABLES and THREE_BYTE_3A_EXTENSION_TABLES and add a
+// switch(Opcode) just below the case X86Local::T8: or case X86Local::TA: line
+// in RecognizableInstr::emitDecodePath().
+
#define ONE_BYTE_EXTENSION_TABLES \
EXTENSION_TABLE(80) \
EXTENSION_TABLE(81) \
@@ -81,10 +116,6 @@ namespace X86Local {
EXTENSION_TABLE(b9) \
EXTENSION_TABLE(ba) \
EXTENSION_TABLE(c7)
-
-#define TWO_BYTE_FULL_EXTENSION_TABLES \
- EXTENSION_TABLE(01)
-
using namespace X86Disassembler;
@@ -402,13 +433,10 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
for (operandIndex = 0; operandIndex < numOperands; ++operandIndex) {
if (OperandList[operandIndex].Constraints.size()) {
- const std::string &constraint = OperandList[operandIndex].Constraints[0];
- std::string::size_type tiedToPos;
-
- if ((tiedToPos = constraint.find(" << 16) | (1 << TOI::TIED_TO))")) !=
- constraint.npos) {
- tiedToPos--;
- operandMapping[operandIndex] = constraint[tiedToPos] - '0';
+ const CodeGenInstruction::ConstraintInfo &Constraint =
+ OperandList[operandIndex].Constraints[0];
+ if (Constraint.isTied()) {
+ operandMapping[operandIndex] = Constraint.getTiedOperand();
} else {
++numPhysicalOperands;
operandMapping[operandIndex] = operandIndex;
@@ -552,36 +580,10 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
// Special cases where the LLVM tables are not complete
-#define EXACTCASE(class, name, lastbyte) \
- if (Name == name) { \
- tables.setTableFields(class, \
- insnContext(), \
- Opcode, \
- ExactFilter(lastbyte), \
- UID); \
- Spec->modifierBase = Opcode; \
- return; \
- }
-
- EXACTCASE(TWOBYTE, "MONITOR", 0xc8)
- EXACTCASE(TWOBYTE, "MWAIT", 0xc9)
- EXACTCASE(TWOBYTE, "SWPGS", 0xf8)
- EXACTCASE(TWOBYTE, "INVEPT", 0x80)
- EXACTCASE(TWOBYTE, "INVVPID", 0x81)
- EXACTCASE(TWOBYTE, "VMCALL", 0xc1)
- EXACTCASE(TWOBYTE, "VMLAUNCH", 0xc2)
- EXACTCASE(TWOBYTE, "VMRESUME", 0xc3)
- EXACTCASE(TWOBYTE, "VMXOFF", 0xc4)
-
- if (Name == "INVLPG") {
- tables.setTableFields(TWOBYTE,
- insnContext(),
- Opcode,
- ExtendedFilter(false, 7),
- UID);
- Spec->modifierBase = Opcode;
- return;
- }
+#define MAP(from, to) \
+ case X86Local::MRM_##from: \
+ filter = new ExactFilter(0x##from); \
+ break;
OpcodeType opcodeType = (OpcodeType)-1;
@@ -596,6 +598,12 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
opcodeType = TWOBYTE;
switch (Opcode) {
+ default:
+ if (needsModRMForDecode(Form))
+ filter = new ModFilter(isRegFormat(Form));
+ else
+ filter = new DumbFilter();
+ break;
#define EXTENSION_TABLE(n) case 0x##n:
TWO_BYTE_EXTENSION_TABLES
#undef EXTENSION_TABLE
@@ -622,16 +630,10 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
case X86Local::MRM7m:
filter = new ExtendedFilter(false, Form - X86Local::MRM0m);
break;
+ MRM_MAPPING
} // switch (Form)
break;
- default:
- if (needsModRMForDecode(Form))
- filter = new ModFilter(isRegFormat(Form));
- else
- filter = new DumbFilter();
-
- break;
- } // switch (opcode)
+ } // switch (Opcode)
opcodeToSet = Opcode;
break;
case X86Local::T8:
@@ -642,7 +644,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
filter = new DumbFilter();
opcodeToSet = Opcode;
break;
- case X86Local::TA:
+ case X86Local::P_TA:
opcodeType = THREEBYTE_3A;
if (needsModRMForDecode(Form))
filter = new ModFilter(isRegFormat(Form));
@@ -699,6 +701,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
case X86Local::MRM7m:
filter = new ExtendedFilter(false, Form - X86Local::MRM0m);
break;
+ MRM_MAPPING
} // switch (Form)
break;
case 0xd8:
@@ -763,6 +766,8 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
}
delete filter;
+
+#undef MAP
}
#define TYPE(str, type) if (s == str) return type;
diff --git a/utils/UpdateCMakeLists.pl b/utils/UpdateCMakeLists.pl
index 6d24d90..8f535145 100755
--- a/utils/UpdateCMakeLists.pl
+++ b/utils/UpdateCMakeLists.pl
@@ -68,7 +68,8 @@ sub UpdateCMake {
while(<IN>) {
if (!$foundLibrary) {
print OUT $_;
- if (/^add_clang_library\(/ || /^add_llvm_library\(/ || /^add_llvm_target\(/) {
+ if (/^add_clang_library\(/ || /^add_llvm_library\(/ || /^add_llvm_target\(/
+ || /^add_executable\(/) {
$foundLibrary = 1;
EmitCMakeList($dir);
}
diff --git a/utils/lit/lit/ShUtil.py b/utils/lit/lit/ShUtil.py
index c4bbb3d..c8f9332 100644
--- a/utils/lit/lit/ShUtil.py
+++ b/utils/lit/lit/ShUtil.py
@@ -66,7 +66,7 @@ class ShLexer:
return (tok[0], num)
elif c == '"':
self.eat()
- str += self.lex_arg_quoted('"')
+ str += self.lex_arg_quoted('"')
elif not self.win32Escapes and c == '\\':
# Outside of a string, '\\' escapes everything.
self.eat()
diff --git a/utils/lit/lit/TestFormats.py b/utils/lit/lit/TestFormats.py
index 5dfd54a..d87a467 100644
--- a/utils/lit/lit/TestFormats.py
+++ b/utils/lit/lit/TestFormats.py
@@ -9,13 +9,19 @@ class GoogleTest(object):
self.test_sub_dir = str(test_sub_dir)
self.test_suffix = str(test_suffix)
- def getGTestTests(self, path, litConfig):
+ def getGTestTests(self, path, litConfig, localConfig):
"""getGTestTests(path) - [name]
-
- Return the tests available in gtest executable."""
+
+ Return the tests available in gtest executable.
+
+ Args:
+ path: String path to a gtest executable
+ litConfig: LitConfig instance
+ localConfig: TestingConfig instance"""
try:
- lines = Util.capture([path, '--gtest_list_tests']).split('\n')
+ lines = Util.capture([path, '--gtest_list_tests'],
+ env=localConfig.environment).split('\n')
except:
litConfig.error("unable to discover google-tests in %r" % path)
raise StopIteration
@@ -52,7 +58,8 @@ class GoogleTest(object):
execpath = os.path.join(filepath, subfilename)
# Discover the tests in this executable.
- for name in self.getGTestTests(execpath, litConfig):
+ for name in self.getGTestTests(execpath, litConfig,
+ localConfig):
testPath = path_in_suite + (filename, subfilename, name)
yield Test.Test(testSuite, testPath, localConfig)
@@ -65,7 +72,8 @@ class GoogleTest(object):
testName = os.path.join(namePrefix, testName)
cmd = [testPath, '--gtest_filter=' + testName]
- out, err, exitCode = TestRunner.executeCommand(cmd)
+ out, err, exitCode = TestRunner.executeCommand(
+ cmd, env=test.config.environment)
if not exitCode:
return Test.PASS,''
@@ -79,6 +87,10 @@ class FileBasedTest(object):
litConfig, localConfig):
source_path = testSuite.getSourcePath(path_in_suite)
for filename in os.listdir(source_path):
+ # Ignore dot files.
+ if filename.startswith('.'):
+ continue
+
filepath = os.path.join(source_path, filename)
if not os.path.isdir(filepath):
base,ext = os.path.splitext(filename)
@@ -129,7 +141,8 @@ class OneCommandPerFileTest:
d not in localConfig.excludes)]
for filename in filenames:
- if (not self.pattern.match(filename) or
+ if (filename.startswith('.') or
+ not self.pattern.match(filename) or
filename in localConfig.excludes):
continue
diff --git a/utils/lit/lit/Util.py b/utils/lit/lit/Util.py
index 66c5e46..414b714 100644
--- a/utils/lit/lit/Util.py
+++ b/utils/lit/lit/Util.py
@@ -39,11 +39,12 @@ def mkdir_p(path):
if e.errno != errno.EEXIST:
raise
-def capture(args):
+def capture(args, env=None):
import subprocess
"""capture(command) - Run the given command (or argv list) in a shell and
return the standard output."""
- p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+ env=env)
out,_ = p.communicate()
return out
diff --git a/utils/llvm.grm b/utils/llvm.grm
index 4499d4b..86a707a 100644
--- a/utils/llvm.grm
+++ b/utils/llvm.grm
@@ -161,6 +161,7 @@ FuncAttr ::= noreturn
| signext
| readnone
| readonly
+ | inlinehint
| noinline
| alwaysinline
| optsize
diff --git a/utils/unittest/UnitTestMain/Makefile b/utils/unittest/UnitTestMain/Makefile
index 7b49191..328d5e2 100644
--- a/utils/unittest/UnitTestMain/Makefile
+++ b/utils/unittest/UnitTestMain/Makefile
@@ -13,6 +13,7 @@ include $(LEVEL)/Makefile.config
LIBRARYNAME = UnitTestMain
BUILD_ARCHIVE = 1
+REQUIRES_RTTI = 1
CPP.Flags += -I$(LLVM_SRC_ROOT)/utils/unittest/googletest/include
CPP.Flags += $(NO_MISSING_FIELD_INITIALIZERS) $(NO_VARIADIC_MACROS)
diff --git a/utils/unittest/googletest/Makefile b/utils/unittest/googletest/Makefile
index 2d2c282..15bbf4e 100644
--- a/utils/unittest/googletest/Makefile
+++ b/utils/unittest/googletest/Makefile
@@ -13,6 +13,7 @@ include $(LEVEL)/Makefile.config
LIBRARYNAME = GoogleTest
BUILD_ARCHIVE = 1
+REQUIRES_RTTI = 1
CPP.Flags += -I$(LLVM_SRC_ROOT)/utils/unittest/googletest/include
CPP.Flags += $(NO_MISSING_FIELD_INITIALIZERS) $(NO_VARIADIC_MACROS)
diff --git a/utils/vim/llvm.vim b/utils/vim/llvm.vim
index 48a4c68..6e4a207 100644
--- a/utils/vim/llvm.vim
+++ b/utils/vim/llvm.vim
@@ -51,7 +51,7 @@ syn keyword llvmKeyword volatile fastcc coldcc cc ccc
syn keyword llvmKeyword x86_stdcallcc x86_fastcallcc
syn keyword llvmKeyword signext zeroext inreg sret nounwind noreturn
syn keyword llvmKeyword nocapture byval nest readnone readonly noalias
-syn keyword llvmKeyword noinline alwaysinline optsize ssp sspreq
+syn keyword llvmKeyword inlinehint noinline alwaysinline optsize ssp sspreq
syn keyword llvmKeyword noredzone noimplicitfloat naked
syn keyword llvmKeyword module asm align tail to
syn keyword llvmKeyword addrspace section alias sideeffect c gc
OpenPOWER on IntegriCloud