diff options
Diffstat (limited to 'utils')
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 |