diff options
Diffstat (limited to 'utils/TableGen')
57 files changed, 7203 insertions, 3614 deletions
diff --git a/utils/TableGen/ARMDecoderEmitter.cpp b/utils/TableGen/ARMDecoderEmitter.cpp index 03b01f6..a8de745 100644 --- a/utils/TableGen/ARMDecoderEmitter.cpp +++ b/utils/TableGen/ARMDecoderEmitter.cpp @@ -221,7 +221,7 @@ typedef enum { #define BIT_WIDTH 32 // Forward declaration. -class FilterChooser; +class ARMFilterChooser; // Representation of the instruction to work on. typedef bit_value_t insn_t[BIT_WIDTH]; @@ -240,7 +240,7 @@ typedef bit_value_t insn_t[BIT_WIDTH]; /// the Filter/FilterChooser combo does not know how to distinguish among the /// Opcodes assigned. /// -/// An example of a conflcit is +/// An example of a conflict is /// /// Conflict: /// 111101000.00........00010000.... @@ -262,9 +262,9 @@ typedef bit_value_t insn_t[BIT_WIDTH]; /// decoder could try to decode the even/odd register numbering and assign to /// VST4q8a or VST4q8b, but for the time being, the decoder chooses the "a" /// version and return the Opcode since the two have the same Asm format string. -class Filter { +class ARMFilter { protected: - FilterChooser *Owner; // points to the FilterChooser who owns this filter + ARMFilterChooser *Owner; // points to the FilterChooser who owns this filter unsigned StartBit; // the starting bit position unsigned NumBits; // number of bits to filter bool Mixed; // a mixed region contains both set and unset bits @@ -276,7 +276,7 @@ protected: std::vector<unsigned> VariableInstructions; // Map of well-known segment value to its delegate. - std::map<unsigned, FilterChooser*> FilterChooserMap; + std::map<unsigned, ARMFilterChooser*> FilterChooserMap; // Number of instructions which fall under FilteredInstructions category. unsigned NumFiltered; @@ -296,16 +296,17 @@ public: } // Return the filter chooser for the group of instructions without constant // segment values. - FilterChooser &getVariableFC() { + ARMFilterChooser &getVariableFC() { assert(NumFiltered == 1); assert(FilterChooserMap.size() == 1); return *(FilterChooserMap.find((unsigned)-1)->second); } - Filter(const Filter &f); - Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, bool mixed); + ARMFilter(const ARMFilter &f); + ARMFilter(ARMFilterChooser &owner, unsigned startBit, unsigned numBits, + bool mixed); - ~Filter(); + ~ARMFilter(); // Divides the decoding task into sub tasks and delegates them to the // inferior FilterChooser's. @@ -333,7 +334,7 @@ typedef enum { ATTR_MIXED } bitAttr_t; -/// FilterChooser - FilterChooser chooses the best filter among a set of Filters +/// ARMFilterChooser - FilterChooser chooses the best filter among a set of Filters /// in order to perform the decoding of instructions at the current level. /// /// Decoding proceeds from the top down. Based on the well-known encoding bits @@ -348,11 +349,11 @@ typedef enum { /// It is useful to think of a Filter as governing the switch stmts of the /// decoding tree. And each case is delegated to an inferior FilterChooser to /// decide what further remaining bits to look at. -class FilterChooser { +class ARMFilterChooser { static TARGET_NAME_t TargetName; protected: - friend class Filter; + friend class ARMFilter; // Vector of codegen instructions to choose our filter. const std::vector<const CodeGenInstruction*> &AllInstructions; @@ -361,14 +362,14 @@ protected: const std::vector<unsigned> Opcodes; // Vector of candidate filters. - std::vector<Filter> Filters; + std::vector<ARMFilter> Filters; // Array of bit values passed down from our parent. // Set to all BIT_UNFILTERED's for Parent == NULL. bit_value_t FilterBitValues[BIT_WIDTH]; // Links to the FilterChooser above us in the decoding tree. - FilterChooser *Parent; + ARMFilterChooser *Parent; // Index of the best filter from Filters. int BestIndex; @@ -376,13 +377,13 @@ protected: public: static void setTargetName(TARGET_NAME_t tn) { TargetName = tn; } - FilterChooser(const FilterChooser &FC) : + ARMFilterChooser(const ARMFilterChooser &FC) : AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes), Filters(FC.Filters), Parent(FC.Parent), BestIndex(FC.BestIndex) { memcpy(FilterBitValues, FC.FilterBitValues, sizeof(FilterBitValues)); } - FilterChooser(const std::vector<const CodeGenInstruction*> &Insts, + ARMFilterChooser(const std::vector<const CodeGenInstruction*> &Insts, const std::vector<unsigned> &IDs) : AllInstructions(Insts), Opcodes(IDs), Filters(), Parent(NULL), BestIndex(-1) { @@ -392,10 +393,10 @@ public: doFilter(); } - FilterChooser(const std::vector<const CodeGenInstruction*> &Insts, - const std::vector<unsigned> &IDs, - bit_value_t (&ParentFilterBitValues)[BIT_WIDTH], - FilterChooser &parent) : + ARMFilterChooser(const std::vector<const CodeGenInstruction*> &Insts, + const std::vector<unsigned> &IDs, + bit_value_t (&ParentFilterBitValues)[BIT_WIDTH], + ARMFilterChooser &parent) : AllInstructions(Insts), Opcodes(IDs), Filters(), Parent(&parent), BestIndex(-1) { for (unsigned i = 0; i < BIT_WIDTH; ++i) @@ -426,8 +427,9 @@ protected: Insn[i] = bitFromBits(Bits, i); // Set Inst{21} to 1 (wback) when IndexModeBits == IndexModeUpd. - if (getByteField(*AllInstructions[Opcode]->TheDef, "IndexModeBits") - == IndexModeUpd) + Record *R = AllInstructions[Opcode]->TheDef; + if (R->getValue("IndexModeBits") && + getByteField(*R, "IndexModeBits") == IndexModeUpd) Insn[21] = BIT_TRUE; } @@ -452,7 +454,7 @@ protected: /// dumpFilterArray on each filter chooser up to the top level one. void dumpStack(raw_ostream &o, const char *prefix); - Filter &bestFilter() { + ARMFilter &bestFilter() { assert(BestIndex != -1 && "BestIndex not set"); return Filters[BestIndex]; } @@ -497,11 +499,12 @@ protected: bool emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,unsigned Opc); // Emits code to decode the singleton, and then to decode the rest. - void emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,Filter &Best); + void emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, + ARMFilter &Best); // Assign a single filter and run with it. - void runSingleFilter(FilterChooser &owner, unsigned startBit, unsigned numBit, - bool mixed); + void runSingleFilter(ARMFilterChooser &owner, unsigned startBit, + unsigned numBit, bool mixed); // reportRegion is a helper function for filterProcessor to mark a region as // eligible for use as a filter region. @@ -530,7 +533,7 @@ protected: // // /////////////////////////// -Filter::Filter(const Filter &f) : +ARMFilter::ARMFilter(const ARMFilter &f) : Owner(f.Owner), StartBit(f.StartBit), NumBits(f.NumBits), Mixed(f.Mixed), FilteredInstructions(f.FilteredInstructions), VariableInstructions(f.VariableInstructions), @@ -538,7 +541,7 @@ Filter::Filter(const Filter &f) : LastOpcFiltered(f.LastOpcFiltered), NumVariable(f.NumVariable) { } -Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, +ARMFilter::ARMFilter(ARMFilterChooser &owner, unsigned startBit, unsigned numBits, bool mixed) : Owner(&owner), StartBit(startBit), NumBits(numBits), Mixed(mixed) { assert(StartBit + NumBits - 1 < BIT_WIDTH); @@ -575,8 +578,8 @@ Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, && "Filter returns no instruction categories"); } -Filter::~Filter() { - std::map<unsigned, FilterChooser*>::iterator filterIterator; +ARMFilter::~ARMFilter() { + std::map<unsigned, ARMFilterChooser*>::iterator filterIterator; for (filterIterator = FilterChooserMap.begin(); filterIterator != FilterChooserMap.end(); filterIterator++) { @@ -590,7 +593,7 @@ Filter::~Filter() { // A special case arises when there's only one entry in the filtered // instructions. In order to unambiguously decode the singleton, we need to // match the remaining undecoded encoding bits against the singleton. -void Filter::recurse() { +void ARMFilter::recurse() { std::map<uint64_t, std::vector<unsigned> >::const_iterator mapIterator; bit_value_t BitValueArray[BIT_WIDTH]; @@ -606,12 +609,12 @@ void Filter::recurse() { // Delegates to an inferior filter chooser for futher processing on this // group of instructions whose segment values are variable. - FilterChooserMap.insert(std::pair<unsigned, FilterChooser*>( + FilterChooserMap.insert(std::pair<unsigned, ARMFilterChooser*>( (unsigned)-1, - new FilterChooser(Owner->AllInstructions, - VariableInstructions, - BitValueArray, - *Owner) + new ARMFilterChooser(Owner->AllInstructions, + VariableInstructions, + BitValueArray, + *Owner) )); } @@ -638,18 +641,18 @@ void Filter::recurse() { // Delegates to an inferior filter chooser for futher processing on this // category of instructions. - FilterChooserMap.insert(std::pair<unsigned, FilterChooser*>( + FilterChooserMap.insert(std::pair<unsigned, ARMFilterChooser*>( mapIterator->first, - new FilterChooser(Owner->AllInstructions, - mapIterator->second, - BitValueArray, - *Owner) + new ARMFilterChooser(Owner->AllInstructions, + mapIterator->second, + BitValueArray, + *Owner) )); } } // Emit code to decode instructions given a segment or segments of bits. -void Filter::emit(raw_ostream &o, unsigned &Indentation) { +void ARMFilter::emit(raw_ostream &o, unsigned &Indentation) { o.indent(Indentation) << "// Check Inst{"; if (NumBits > 1) @@ -660,7 +663,7 @@ void Filter::emit(raw_ostream &o, unsigned &Indentation) { o.indent(Indentation) << "switch (fieldFromInstruction(insn, " << StartBit << ", " << NumBits << ")) {\n"; - std::map<unsigned, FilterChooser*>::iterator filterIterator; + std::map<unsigned, ARMFilterChooser*>::iterator filterIterator; bool DefaultCase = false; for (filterIterator = FilterChooserMap.begin(); @@ -709,7 +712,7 @@ void Filter::emit(raw_ostream &o, unsigned &Indentation) { // Returns the number of fanout produced by the filter. More fanout implies // the filter distinguishes more categories of instructions. -unsigned Filter::usefulness() const { +unsigned ARMFilter::usefulness() const { if (VariableInstructions.size()) return FilteredInstructions.size(); else @@ -723,10 +726,10 @@ unsigned Filter::usefulness() const { ////////////////////////////////// // Define the symbol here. -TARGET_NAME_t FilterChooser::TargetName; +TARGET_NAME_t ARMFilterChooser::TargetName; // This provides an opportunity for target specific code emission. -void FilterChooser::emitTopHook(raw_ostream &o) { +void ARMFilterChooser::emitTopHook(raw_ostream &o) { if (TargetName == TARGET_ARM) { // Emit code that references the ARMFormat data type. o << "static const ARMFormat ARMFormats[] = {\n"; @@ -747,7 +750,7 @@ void FilterChooser::emitTopHook(raw_ostream &o) { } // Emit the top level typedef and decodeInstruction() function. -void FilterChooser::emitTop(raw_ostream &o, unsigned &Indentation) { +void ARMFilterChooser::emitTop(raw_ostream &o, unsigned &Indentation) { // Run the target specific emit hook. emitTopHook(o); @@ -801,7 +804,7 @@ void FilterChooser::emitTop(raw_ostream &o, unsigned &Indentation) { o << '\n'; - o.indent(Indentation) << "static uint16_t decodeInstruction(field_t insn) {\n"; + o.indent(Indentation) <<"static uint16_t decodeInstruction(field_t insn) {\n"; ++Indentation; ++Indentation; // Emits code to decode the instructions. @@ -818,7 +821,7 @@ void FilterChooser::emitTop(raw_ostream &o, unsigned &Indentation) { // This provides an opportunity for target specific code emission after // emitTop(). -void FilterChooser::emitBot(raw_ostream &o, unsigned &Indentation) { +void ARMFilterChooser::emitBot(raw_ostream &o, unsigned &Indentation) { if (TargetName != TARGET_THUMB) return; // Emit code that decodes the Thumb ISA. @@ -843,7 +846,7 @@ void FilterChooser::emitBot(raw_ostream &o, unsigned &Indentation) { // // Returns false if and on the first uninitialized bit value encountered. // Returns true, otherwise. -bool FilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn, +bool ARMFilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn, unsigned StartBit, unsigned NumBits) const { Field = 0; @@ -860,7 +863,7 @@ bool FilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn, /// dumpFilterArray - dumpFilterArray prints out debugging info for the given /// filter array as a series of chars. -void FilterChooser::dumpFilterArray(raw_ostream &o, +void ARMFilterChooser::dumpFilterArray(raw_ostream &o, bit_value_t (&filter)[BIT_WIDTH]) { unsigned bitIndex; @@ -884,8 +887,8 @@ void FilterChooser::dumpFilterArray(raw_ostream &o, /// dumpStack - dumpStack traverses the filter chooser chain and calls /// dumpFilterArray on each filter chooser up to the top level one. -void FilterChooser::dumpStack(raw_ostream &o, const char *prefix) { - FilterChooser *current = this; +void ARMFilterChooser::dumpStack(raw_ostream &o, const char *prefix) { + ARMFilterChooser *current = this; while (current) { o << prefix; @@ -896,7 +899,7 @@ void FilterChooser::dumpStack(raw_ostream &o, const char *prefix) { } // Called from Filter::recurse() when singleton exists. For debug purpose. -void FilterChooser::SingletonExists(unsigned Opc) { +void ARMFilterChooser::SingletonExists(unsigned Opc) { insn_t Insn0; insnWithID(Insn0, Opc); @@ -923,7 +926,7 @@ void FilterChooser::SingletonExists(unsigned Opc) { // This returns a list of undecoded bits of an instructions, for example, // Inst{20} = 1 && Inst{3-0} == 0b1111 represents two islands of yet-to-be // decoded bits in order to verify that the instruction matches the Opcode. -unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits, +unsigned ARMFilterChooser::getIslands(std::vector<unsigned> &StartBits, std::vector<unsigned> &EndBits, std::vector<uint64_t> &FieldVals, insn_t &Insn) { unsigned Num, BitNo; @@ -983,7 +986,7 @@ unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits, // Emits code to decode the singleton. Return true if we have matched all the // well-known bits. -bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, +bool ARMFilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, unsigned Opc) { std::vector<unsigned> StartBits; std::vector<unsigned> EndBits; @@ -1046,8 +1049,9 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, } // Emits code to decode the singleton, and then to decode the rest. -void FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, - Filter &Best) { +void ARMFilterChooser::emitSingletonDecoder(raw_ostream &o, + unsigned &Indentation, + ARMFilter &Best) { unsigned Opc = Best.getSingletonOpc(); @@ -1063,10 +1067,11 @@ void FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, // Assign a single filter and run with it. Top level API client can initialize // with a single filter to start the filtering process. -void FilterChooser::runSingleFilter(FilterChooser &owner, unsigned startBit, - unsigned numBit, bool mixed) { +void ARMFilterChooser::runSingleFilter(ARMFilterChooser &owner, + unsigned startBit, + unsigned numBit, bool mixed) { Filters.clear(); - Filter F(*this, startBit, numBit, true); + ARMFilter F(*this, startBit, numBit, true); Filters.push_back(F); BestIndex = 0; // Sole Filter instance to choose from. bestFilter().recurse(); @@ -1074,18 +1079,18 @@ void FilterChooser::runSingleFilter(FilterChooser &owner, unsigned startBit, // reportRegion is a helper function for filterProcessor to mark a region as // eligible for use as a filter region. -void FilterChooser::reportRegion(bitAttr_t RA, unsigned StartBit, - unsigned BitIndex, bool AllowMixed) { +void ARMFilterChooser::reportRegion(bitAttr_t RA, unsigned StartBit, + unsigned BitIndex, bool AllowMixed) { if (RA == ATTR_MIXED && AllowMixed) - Filters.push_back(Filter(*this, StartBit, BitIndex - StartBit, true)); + Filters.push_back(ARMFilter(*this, StartBit, BitIndex - StartBit, true)); else if (RA == ATTR_ALL_SET && !AllowMixed) - Filters.push_back(Filter(*this, StartBit, BitIndex - StartBit, false)); + Filters.push_back(ARMFilter(*this, StartBit, BitIndex - StartBit, false)); } // FilterProcessor scans the well-known encoding bits of the instructions and // builds up a list of candidate filters. It chooses the best filter and // recursively descends down the decoding tree. -bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { +bool ARMFilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { Filters.clear(); BestIndex = -1; unsigned numInstructions = Opcodes.size(); @@ -1317,7 +1322,7 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { // Decides on the best configuration of filter(s) to use in order to decode // the instructions. A conflict of instructions may occur, in which case we // dump the conflict set to the standard error. -void FilterChooser::doFilter() { +void ARMFilterChooser::doFilter() { unsigned Num = Opcodes.size(); assert(Num && "FilterChooser created with no instructions"); @@ -1350,7 +1355,7 @@ void FilterChooser::doFilter() { // Emits code to decode our share of instructions. Returns true if the // emitted code causes a return, which occurs if we know how to decode // the instruction at this level or the instruction is not decodeable. -bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) { +bool ARMFilterChooser::emit(raw_ostream &o, unsigned &Indentation) { if (Opcodes.size() == 1) // There is only one instruction in the set, which is great! // Call emitSingletonDecoder() to see whether there are any remaining @@ -1359,7 +1364,7 @@ bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) { // Choose the best filter to do the decodings! if (BestIndex != -1) { - Filter &Best = bestFilter(); + ARMFilter &Best = bestFilter(); if (Best.getNumFiltered() == 1) emitSingletonDecoder(o, Indentation, Best); else @@ -1488,11 +1493,11 @@ bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) { class ARMDecoderEmitter::ARMDEBackend { public: - ARMDEBackend(ARMDecoderEmitter &frontend) : + ARMDEBackend(ARMDecoderEmitter &frontend, RecordKeeper &Records) : NumberedInstructions(), Opcodes(), Frontend(frontend), - Target(), + Target(Records), FC(NULL) { if (Target.getName() == "ARM") @@ -1538,13 +1543,14 @@ protected: std::vector<unsigned> Opcodes2; ARMDecoderEmitter &Frontend; CodeGenTarget Target; - FilterChooser *FC; + ARMFilterChooser *FC; TARGET_NAME_t TargetName; }; -bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( - const CodeGenInstruction &CGI, TARGET_NAME_t TN) { +bool ARMDecoderEmitter:: +ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI, + TARGET_NAME_t TN) { const Record &Def = *CGI.TheDef; const StringRef Name = Def.getName(); uint8_t Form = getByteField(Def, "Form"); @@ -1559,6 +1565,10 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( // which is a better design and less fragile than the name matchings. if (Bits.allInComplete()) return false; + // Ignore "asm parser only" instructions. + if (Def.getValueAsBit("isAsmParserOnly")) + return false; + if (TN == TARGET_ARM) { // FIXME: what about Int_MemBarrierV6 and Int_SyncBarrierV6? if ((Name != "Int_MemBarrierV7" && Name != "Int_SyncBarrierV7") && @@ -1566,13 +1576,6 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( return false; if (thumbInstruction(Form)) return false; - if (Name.find("CMPz") != std::string::npos /* || - Name.find("CMNz") != std::string::npos */) - return false; - - // Ignore pseudo instructions. - if (Name == "BXr9" || Name == "BMOVPCRX" || Name == "BMOVPCRXr9") - return false; // Tail calls are other patterns that generate existing instructions. if (Name == "TCRETURNdi" || Name == "TCRETURNdiND" || @@ -1583,11 +1586,6 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( Name == "MOVr_TC") return false; - // VLDMQ/VSTMQ can be handled with the more generic VLDMD/VSTMD. - if (Name == "VLDMQ" || Name == "VLDMQ_UPD" || - Name == "VSTMQ" || Name == "VSTMQ_UPD") - return false; - // // The following special cases are for conflict resolutions. // @@ -1610,13 +1608,13 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( // better off using the generic RSCri and RSCrs instructions. if (Name == "RSCSri" || Name == "RSCSrs") return false; - // MOVCCr, MOVCCs, MOVCCi, FCYPScc, FCYPDcc, FNEGScc, and FNEGDcc are used - // in the compiler to implement conditional moves. We can ignore them in - // favor of their more generic versions of instructions. - // See also SDNode *ARMDAGToDAGISel::Select(SDValue Op). - if (Name == "MOVCCr" || Name == "MOVCCs" || Name == "MOVCCi" || - Name == "FCPYScc" || Name == "FCPYDcc" || - Name == "FNEGScc" || Name == "FNEGDcc") + // MOVCCr, MOVCCs, MOVCCi, MOVCCi16, FCYPScc, FCYPDcc, FNEGScc, and + // FNEGDcc are used in the compiler to implement conditional moves. + // We can ignore them in favor of their more generic versions of + // instructions. See also SDNode *ARMDAGToDAGISel::Select(SDValue Op). + if (Name == "MOVCCr" || Name == "MOVCCs" || Name == "MOVCCi" || + Name == "MOVCCi16" || Name == "FCPYScc" || Name == "FCPYDcc" || + Name == "FNEGScc" || Name == "FNEGDcc") return false; // Ditto for VMOVDcc, VMOVScc, VNEGDcc, and VNEGScc. @@ -1624,15 +1622,10 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( Name == "VNEGScc") return false; - // Ignore the *_sfp instructions when decoding. They are used by the - // compiler to implement scalar floating point operations using vector - // operations in order to work around some performance issues. - if (Name.find("_sfp") != std::string::npos) return false; - - // LDM_RET is a special case of LDM (Load Multiple) where the registers + // LDMIA_RET is a special case of LDM (Load Multiple) where the registers // loaded include the PC, causing a branch to a loaded address. Ignore - // the LDM_RET instruction when decoding. - if (Name == "LDM_RET") return false; + // the LDMIA_RET instruction when decoding. + if (Name == "LDMIA_RET") return false; // Bcc is in a more generic form than B. Ignore B when decoding. if (Name == "B") return false; @@ -1671,18 +1664,17 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( // VREV64qf is equivalent to VREV64q32. if (Name == "VREV64df" || Name == "VREV64qf") return false; - // VDUPLNfd is equivalent to VDUPLN32d; VDUPfdf is specialized VDUPLN32d. - // VDUPLNfq is equivalent to VDUPLN32q; VDUPfqf is specialized VDUPLN32q. + // VDUPLNfd is equivalent to VDUPLN32d. + // VDUPLNfq is equivalent to VDUPLN32q. // VLD1df is equivalent to VLD1d32. // VLD1qf is equivalent to VLD1q32. // VLD2d64 is equivalent to VLD1q64. // VST1df is equivalent to VST1d32. // VST1qf is equivalent to VST1q32. // VST2d64 is equivalent to VST1q64. - if (Name == "VDUPLNfd" || Name == "VDUPfdf" || - Name == "VDUPLNfq" || Name == "VDUPfqf" || - Name == "VLD1df" || Name == "VLD1qf" || Name == "VLD2d64" || - Name == "VST1df" || Name == "VST1qf" || Name == "VST2d64") + if (Name == "VDUPLNfd" || Name == "VDUPLNfq" || + Name == "VLD1df" || Name == "VLD1qf" || Name == "VLD2d64" || + Name == "VST1df" || Name == "VST1qf" || Name == "VST2d64") return false; } else if (TN == TARGET_THUMB) { if (!thumbInstruction(Form)) @@ -1696,12 +1688,8 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( if (Name == "tTPsoft" || Name == "t2TPsoft") return false; - // Ignore tLEApcrel and tLEApcrelJT, prefer tADDrPCi. - if (Name == "tLEApcrel" || Name == "tLEApcrelJT") - return false; - - // Ignore t2LEApcrel, prefer the generic t2ADD* for disassembly printing. - if (Name == "t2LEApcrel") + // Ignore tADR, prefer tADDrPCi. + if (Name == "tADR") return false; // Ignore tADDrSP, tADDspr, and tPICADD, prefer the generic tADDhirr. @@ -1719,42 +1707,33 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( if (Name == "t2LDRDpci") return false; - // Ignore t2TBB, t2TBH and prefer the generic t2TBBgen, t2TBHgen. - if (Name == "t2TBB" || Name == "t2TBH") - return false; - // Resolve conflicts: // // tBfar conflicts with tBLr9 - // tCMNz conflicts with tCMN (with assembly format strings being equal) - // tPOP_RET/t2LDM_RET conflict with tPOP/t2LDM (ditto) + // tPOP_RET/t2LDMIA_RET conflict with tPOP/t2LDM (ditto) // tMOVCCi conflicts with tMOVi8 // tMOVCCr conflicts with tMOVgpr2gpr - // tBR_JTr conflicts with tBRIND // tSpill conflicts with tSTRspi // tLDRcp conflicts with tLDRspi // tRestore conflicts with tLDRspi - // t2LEApcrelJT conflicts with t2LEApcrel + // t2MOVCCi16 conflicts with tMOVi16 if (Name == "tBfar" || - /* Name == "tCMNz" || */ Name == "tCMPzi8" || Name == "tCMPzr" || - Name == "tCMPzhir" || /* Name == "t2CMNzrr" || Name == "t2CMNzrs" || - Name == "t2CMNzri" || */ Name == "t2CMPzrr" || Name == "t2CMPzrs" || - Name == "t2CMPzri" || Name == "tPOP_RET" || Name == "t2LDM_RET" || - Name == "tMOVCCi" || Name == "tMOVCCr" || Name == "tBR_JTr" || + Name == "tPOP_RET" || Name == "t2LDMIA_RET" || + Name == "tMOVCCi" || Name == "tMOVCCr" || Name == "tSpill" || Name == "tLDRcp" || Name == "tRestore" || - Name == "t2LEApcrelJT") + Name == "t2MOVCCi16") return false; } - // Dumps the instruction encoding format. - switch (TargetName) { - case TARGET_ARM: - case TARGET_THUMB: - DEBUG(errs() << Name << " " << stringForARMFormat((ARMFormat)Form)); - break; - } - DEBUG({ + // Dumps the instruction encoding format. + switch (TargetName) { + case TARGET_ARM: + case TARGET_THUMB: + errs() << Name << " " << stringForARMFormat((ARMFormat)Form); + break; + } + errs() << " "; // Dumps the instruction encoding bits. @@ -1763,8 +1742,8 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( errs() << '\n'; // Dumps the list of operand info. - for (unsigned i = 0, e = CGI.OperandList.size(); i != e; ++i) { - CodeGenInstruction::OperandInfo Info = CGI.OperandList[i]; + for (unsigned i = 0, e = CGI.Operands.size(); i != e; ++i) { + const CGIOperandList::OperandInfo &Info = CGI.Operands[i]; const std::string &OperandName = Info.Name; const Record &OperandDef = *Info.Rec; @@ -1778,32 +1757,20 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( void ARMDecoderEmitter::ARMDEBackend::populateInstructions() { getInstructionsByEnumValue(NumberedInstructions); - uint16_t numUIDs = NumberedInstructions.size(); - uint16_t uid; - - const char *instClass = NULL; - - switch (TargetName) { - case TARGET_ARM: - instClass = "InstARM"; - break; - default: - assert(0 && "Unreachable code!"); - } - - for (uid = 0; uid < numUIDs; uid++) { - // filter out intrinsics - if (!NumberedInstructions[uid]->TheDef->isSubClassOf(instClass)) - continue; + unsigned numUIDs = NumberedInstructions.size(); + if (TargetName == TARGET_ARM) { + for (unsigned uid = 0; uid < numUIDs; uid++) { + // filter out intrinsics + if (!NumberedInstructions[uid]->TheDef->isSubClassOf("InstARM")) + continue; - if (populateInstruction(*NumberedInstructions[uid], TargetName)) - Opcodes.push_back(uid); - } + if (populateInstruction(*NumberedInstructions[uid], TargetName)) + Opcodes.push_back(uid); + } - // Special handling for the ARM chip, which supports two modes of execution. - // This branch handles the Thumb opcodes. - if (TargetName == TARGET_ARM) { - for (uid = 0; uid < numUIDs; uid++) { + // Special handling for the ARM chip, which supports two modes of execution. + // This branch handles the Thumb opcodes. + for (unsigned uid = 0; uid < numUIDs; uid++) { // filter out intrinsics if (!NumberedInstructions[uid]->TheDef->isSubClassOf("InstARM") && !NumberedInstructions[uid]->TheDef->isSubClassOf("InstThumb")) @@ -1812,6 +1779,18 @@ void ARMDecoderEmitter::ARMDEBackend::populateInstructions() { if (populateInstruction(*NumberedInstructions[uid], TARGET_THUMB)) Opcodes2.push_back(uid); } + + return; + } + + // For other targets. + for (unsigned uid = 0; uid < numUIDs; uid++) { + Record *R = NumberedInstructions[uid]->TheDef; + if (R->getValueAsString("Namespace") == "TargetOpcode") + continue; + + if (populateInstruction(*NumberedInstructions[uid], TargetName)) + Opcodes.push_back(uid); } } @@ -1826,25 +1805,25 @@ void ARMDecoderEmitter::ARMDEBackend::emit(raw_ostream &o) { assert(0 && "Unreachable code!"); } - o << "#include \"llvm/System/DataTypes.h\"\n"; + o << "#include \"llvm/Support/DataTypes.h\"\n"; o << "#include <assert.h>\n"; o << '\n'; o << "namespace llvm {\n\n"; - FilterChooser::setTargetName(TargetName); + ARMFilterChooser::setTargetName(TargetName); switch (TargetName) { case TARGET_ARM: { // Emit common utility and ARM ISA decoder. - FC = new FilterChooser(NumberedInstructions, Opcodes); + FC = new ARMFilterChooser(NumberedInstructions, Opcodes); // Reset indentation level. unsigned Indentation = 0; FC->emitTop(o, Indentation); delete FC; // Emit Thumb ISA decoder as well. - FilterChooser::setTargetName(TARGET_THUMB); - FC = new FilterChooser(NumberedInstructions, Opcodes2); + ARMFilterChooser::setTargetName(TARGET_THUMB); + FC = new ARMFilterChooser(NumberedInstructions, Opcodes2); // Reset indentation level. Indentation = 0; FC->emitBot(o, Indentation); @@ -1863,7 +1842,7 @@ void ARMDecoderEmitter::ARMDEBackend::emit(raw_ostream &o) { void ARMDecoderEmitter::initBackend() { - Backend = new ARMDEBackend(*this); + Backend = new ARMDEBackend(*this, Records); } void ARMDecoderEmitter::run(raw_ostream &o) diff --git a/utils/TableGen/ARMDecoderEmitter.h b/utils/TableGen/ARMDecoderEmitter.h index 571a947..1faeb91 100644 --- a/utils/TableGen/ARMDecoderEmitter.h +++ b/utils/TableGen/ARMDecoderEmitter.h @@ -17,7 +17,7 @@ #include "TableGenBackend.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 5583986..e3def41 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -8,7 +8,11 @@ //===----------------------------------------------------------------------===// // // This tablegen backend emits a target specifier matcher for converting parsed -// assembly operands in the MCInst structures. +// assembly operands in the MCInst structures. It also emits a matcher for +// custom operand parsing. +// +// Converting assembly operands into MCInst structures +// --------------------------------------------------- // // The input to the target specific matcher is a list of literal tokens and // operands. The target specific parser should generally eliminate any syntax @@ -20,7 +24,7 @@ // Some example inputs, for X86: // 'addl' (immediate ...) (register ...) // 'add' (immediate ...) (memory ...) -// 'call' '*' %epc +// 'call' '*' %epc // // The assembly matcher is responsible for converting this input into a precise // machine instruction (i.e., an instruction with a well defined encoding). This @@ -63,26 +67,47 @@ // In addition, the subset relation amongst classes induces a partial order // on such tuples, which we use to resolve ambiguities. // -// FIXME: What do we do if a crazy case shows up where this is the wrong -// resolution? -// // 2. The input can now be treated as a tuple of classes (static tokens are // simple singleton sets). Each such tuple should generally map to a single // instruction (we currently ignore cases where this isn't true, whee!!!), // which we can emit a simple matcher for. // +// Custom Operand Parsing +// ---------------------- +// +// Some targets need a custom way to parse operands, some specific instructions +// can contain arguments that can represent processor flags and other kinds of +// identifiers that need to be mapped to specific valeus in the final encoded +// instructions. The target specific custom operand parsing works in the +// following way: +// +// 1. A operand match table is built, each entry contains a mnemonic, an +// operand class, a mask for all operand positions for that same +// class/mnemonic and target features to be checked while trying to match. +// +// 2. The operand matcher will try every possible entry with the same +// mnemonic and will check if the target feature for this mnemonic also +// matches. After that, if the operand to be matched has its index +// present in the mask, a successfull match occurs. Otherwise, fallback +// to the regular operand parsing. +// +// 3. For a match success, each operand class that has a 'ParserMethod' +// becomes part of a switch from where the custom method is called. +// //===----------------------------------------------------------------------===// #include "AsmMatcherEmitter.h" #include "CodeGenTarget.h" #include "Record.h" +#include "StringMatcher.h" #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" -#include <list> #include <map> #include <set> using namespace llvm; @@ -91,197 +116,8 @@ static cl::opt<std::string> MatchPrefix("match-prefix", cl::init(""), cl::desc("Only match instructions with the given prefix")); -/// FlattenVariants - Flatten an .td file assembly string by selecting the -/// variant at index \arg N. -static std::string FlattenVariants(const std::string &AsmString, - unsigned N) { - StringRef Cur = AsmString; - std::string Res = ""; - - for (;;) { - // Find the start of the next variant string. - size_t VariantsStart = 0; - for (size_t e = Cur.size(); VariantsStart != e; ++VariantsStart) - if (Cur[VariantsStart] == '{' && - (VariantsStart == 0 || (Cur[VariantsStart-1] != '$' && - Cur[VariantsStart-1] != '\\'))) - break; - - // Add the prefix to the result. - Res += Cur.slice(0, VariantsStart); - if (VariantsStart == Cur.size()) - break; - - ++VariantsStart; // Skip the '{'. - - // Scan to the end of the variants string. - size_t VariantsEnd = VariantsStart; - unsigned NestedBraces = 1; - for (size_t e = Cur.size(); VariantsEnd != e; ++VariantsEnd) { - if (Cur[VariantsEnd] == '}' && Cur[VariantsEnd-1] != '\\') { - if (--NestedBraces == 0) - break; - } else if (Cur[VariantsEnd] == '{') - ++NestedBraces; - } - - // Select the Nth variant (or empty). - StringRef Selection = Cur.slice(VariantsStart, VariantsEnd); - for (unsigned i = 0; i != N; ++i) - Selection = Selection.split('|').second; - Res += Selection.split('|').first; - - assert(VariantsEnd != Cur.size() && - "Unterminated variants in assembly string!"); - Cur = Cur.substr(VariantsEnd + 1); - } - - return Res; -} - -/// TokenizeAsmString - Tokenize a simplified assembly string. -static void TokenizeAsmString(StringRef AsmString, - SmallVectorImpl<StringRef> &Tokens) { - unsigned Prev = 0; - bool InTok = true; - for (unsigned i = 0, e = AsmString.size(); i != e; ++i) { - switch (AsmString[i]) { - case '[': - case ']': - case '*': - case '!': - case ' ': - case '\t': - case ',': - if (InTok) { - Tokens.push_back(AsmString.slice(Prev, i)); - InTok = false; - } - if (!isspace(AsmString[i]) && AsmString[i] != ',') - Tokens.push_back(AsmString.substr(i, 1)); - Prev = i + 1; - break; - - case '\\': - if (InTok) { - Tokens.push_back(AsmString.slice(Prev, i)); - InTok = false; - } - ++i; - assert(i != AsmString.size() && "Invalid quoted character"); - Tokens.push_back(AsmString.substr(i, 1)); - Prev = i + 1; - break; - - case '$': { - // If this isn't "${", treat like a normal token. - if (i + 1 == AsmString.size() || AsmString[i + 1] != '{') { - if (InTok) { - Tokens.push_back(AsmString.slice(Prev, i)); - InTok = false; - } - Prev = i; - break; - } - - if (InTok) { - Tokens.push_back(AsmString.slice(Prev, i)); - InTok = false; - } - - StringRef::iterator End = - std::find(AsmString.begin() + i, AsmString.end(), '}'); - assert(End != AsmString.end() && "Missing brace in operand reference!"); - size_t EndPos = End - AsmString.begin(); - Tokens.push_back(AsmString.slice(i, EndPos+1)); - Prev = EndPos + 1; - i = EndPos; - break; - } - - case '.': - if (InTok) { - Tokens.push_back(AsmString.slice(Prev, i)); - } - Prev = i; - InTok = true; - break; - - default: - InTok = true; - } - } - if (InTok && Prev != AsmString.size()) - Tokens.push_back(AsmString.substr(Prev)); -} - -static bool IsAssemblerInstruction(StringRef Name, - const CodeGenInstruction &CGI, - const SmallVectorImpl<StringRef> &Tokens) { - // Ignore "codegen only" instructions. - if (CGI.TheDef->getValueAsBit("isCodeGenOnly")) - return false; - - // Ignore pseudo ops. - // - // FIXME: This is a hack; can we convert these instructions to set the - // "codegen only" bit instead? - if (const RecordVal *Form = CGI.TheDef->getValue("Form")) - if (Form->getValue()->getAsString() == "Pseudo") - return false; - - // Ignore "Int_*" and "*_Int" instructions, which are internal aliases. - // - // FIXME: This is a total hack. - if (StringRef(Name).startswith("Int_") || StringRef(Name).endswith("_Int")) - return false; - - // Ignore instructions with no .s string. - // - // FIXME: What are these? - if (CGI.AsmString.empty()) - return false; - - // FIXME: Hack; ignore any instructions with a newline in them. - if (std::find(CGI.AsmString.begin(), - CGI.AsmString.end(), '\n') != CGI.AsmString.end()) - return false; - - // Ignore instructions with attributes, these are always fake instructions for - // simplifying codegen. - // - // FIXME: Is this true? - // - // Also, check for instructions which reference the operand multiple times; - // this implies a constraint we would not honor. - std::set<std::string> OperandNames; - for (unsigned i = 1, e = Tokens.size(); i < e; ++i) { - if (Tokens[i][0] == '$' && - std::find(Tokens[i].begin(), - Tokens[i].end(), ':') != Tokens[i].end()) { - DEBUG({ - errs() << "warning: '" << Name << "': " - << "ignoring instruction; operand with attribute '" - << Tokens[i] << "'\n"; - }); - return false; - } - - if (Tokens[i][0] == '$' && !OperandNames.insert(Tokens[i]).second) { - DEBUG({ - errs() << "warning: '" << Name << "': " - << "ignoring instruction with tied operand '" - << Tokens[i].str() << "'\n"; - }); - return false; - } - } - - return true; -} - namespace { - +class AsmMatcherInfo; struct SubtargetFeatureInfo; /// ClassInfo - Helper class for storing the information about a particular @@ -331,6 +167,10 @@ struct ClassInfo { /// MCInst; this is not valid for Token or register kinds. std::string RenderMethod; + /// ParserMethod - The name of the operand method to do a target specific + /// parsing on the operand. + std::string ParserMethod; + /// For register classes, the records for all the registers in this class. std::set<Record*> Registers; @@ -360,7 +200,7 @@ public: std::set<Record*> Tmp; std::insert_iterator< std::set<Record*> > II(Tmp, Tmp.begin()); - std::set_intersection(Registers.begin(), Registers.end(), + std::set_intersection(Registers.begin(), Registers.end(), RHS.Registers.begin(), RHS.Registers.end(), II); @@ -380,11 +220,11 @@ public: const ClassInfo *RHSRoot = &RHS; while (!RHSRoot->SuperClasses.empty()) RHSRoot = RHSRoot->SuperClasses.front(); - + return Root == RHSRoot; } - /// isSubsetOf - Test whether this class is a subset of \arg RHS; + /// isSubsetOf - Test whether this class is a subset of \arg RHS; bool isSubsetOf(const ClassInfo &RHS) const { // This is a subset of RHS if it is the same class... if (this == &RHS) @@ -430,32 +270,131 @@ public: } }; -/// InstructionInfo - Helper class for storing the necessary information for an -/// instruction which is capable of being matched. -struct InstructionInfo { - struct Operand { +/// MatchableInfo - Helper class for storing the necessary information for an +/// instruction or alias which is capable of being matched. +struct MatchableInfo { + struct AsmOperand { + /// Token - This is the token that the operand came from. + StringRef Token; + /// The unique class instance this operand should match. ClassInfo *Class; - /// The original operand this corresponds to, if any. - const CodeGenInstruction::OperandInfo *OperandInfo; + /// The operand name this is, if anything. + StringRef SrcOpName; + + /// The suboperand index within SrcOpName, or -1 for the entire operand. + int SubOpIdx; + + explicit AsmOperand(StringRef T) : Token(T), Class(0), SubOpIdx(-1) {} }; - /// InstrName - The target name for this instruction. - std::string InstrName; + /// ResOperand - This represents a single operand in the result instruction + /// generated by the match. In cases (like addressing modes) where a single + /// assembler operand expands to multiple MCOperands, this represents the + /// single assembler operand, not the MCOperand. + struct ResOperand { + enum { + /// RenderAsmOperand - This represents an operand result that is + /// generated by calling the render method on the assembly operand. The + /// corresponding AsmOperand is specified by AsmOperandNum. + RenderAsmOperand, + + /// TiedOperand - This represents a result operand that is a duplicate of + /// a previous result operand. + TiedOperand, + + /// ImmOperand - This represents an immediate value that is dumped into + /// the operand. + ImmOperand, + + /// RegOperand - This represents a fixed register that is dumped in. + RegOperand + } Kind; + + union { + /// This is the operand # in the AsmOperands list that this should be + /// copied from. + unsigned AsmOperandNum; + + /// TiedOperandNum - This is the (earlier) result operand that should be + /// copied from. + unsigned TiedOperandNum; + + /// ImmVal - This is the immediate value added to the instruction. + int64_t ImmVal; + + /// Register - This is the register record. + Record *Register; + }; + + /// MINumOperands - The number of MCInst operands populated by this + /// operand. + unsigned MINumOperands; + + static ResOperand getRenderedOp(unsigned AsmOpNum, unsigned NumOperands) { + ResOperand X; + X.Kind = RenderAsmOperand; + X.AsmOperandNum = AsmOpNum; + X.MINumOperands = NumOperands; + return X; + } + + static ResOperand getTiedOp(unsigned TiedOperandNum) { + ResOperand X; + X.Kind = TiedOperand; + X.TiedOperandNum = TiedOperandNum; + X.MINumOperands = 1; + return X; + } - /// Instr - The instruction this matches. - const CodeGenInstruction *Instr; + static ResOperand getImmOp(int64_t Val) { + ResOperand X; + X.Kind = ImmOperand; + X.ImmVal = Val; + X.MINumOperands = 1; + return X; + } + + static ResOperand getRegOp(Record *Reg) { + ResOperand X; + X.Kind = RegOperand; + X.Register = Reg; + X.MINumOperands = 1; + return X; + } + }; + + /// TheDef - This is the definition of the instruction or InstAlias that this + /// matchable came from. + Record *const TheDef; + + /// DefRec - This is the definition that it came from. + PointerUnion<const CodeGenInstruction*, const CodeGenInstAlias*> DefRec; + + const CodeGenInstruction *getResultInst() const { + if (DefRec.is<const CodeGenInstruction*>()) + return DefRec.get<const CodeGenInstruction*>(); + return DefRec.get<const CodeGenInstAlias*>()->ResultInst; + } + + /// ResOperands - This is the operand list that should be built for the result + /// MCInst. + std::vector<ResOperand> ResOperands; /// AsmString - The assembly string for this instruction (with variants - /// removed). + /// removed), e.g. "movsx $src, $dst". std::string AsmString; - /// Tokens - The tokenized assembly pattern that this instruction matches. - SmallVector<StringRef, 4> Tokens; + /// Mnemonic - This is the first token of the matched instruction, its + /// mnemonic. + StringRef Mnemonic; - /// Operands - The operands that this instruction matches. - SmallVector<Operand, 4> Operands; + /// AsmOperands - The textual operands that this instruction matches, + /// annotated with a class and where in the OperandList they were defined. + /// This directly corresponds to the tokenized AsmString after the mnemonic is + /// removed. + SmallVector<AsmOperand, 4> AsmOperands; /// Predicates - The required subtarget features to match this instruction. SmallVector<SubtargetFeatureInfo*, 4> RequiredFeatures; @@ -465,29 +404,79 @@ struct InstructionInfo { /// function. std::string ConversionFnKind; - /// operator< - Compare two instructions. - bool operator<(const InstructionInfo &RHS) const { - if (Operands.size() != RHS.Operands.size()) - return Operands.size() < RHS.Operands.size(); + MatchableInfo(const CodeGenInstruction &CGI) + : TheDef(CGI.TheDef), DefRec(&CGI), AsmString(CGI.AsmString) { + } + + MatchableInfo(const CodeGenInstAlias *Alias) + : TheDef(Alias->TheDef), DefRec(Alias), AsmString(Alias->AsmString) { + } + + void Initialize(const AsmMatcherInfo &Info, + SmallPtrSet<Record*, 16> &SingletonRegisters); + + /// Validate - Return true if this matchable is a valid thing to match against + /// and perform a bunch of validity checking. + bool Validate(StringRef CommentDelimiter, bool Hack) const; + + /// getSingletonRegisterForAsmOperand - If the specified token is a singleton + /// register, return the Record for it, otherwise return null. + Record *getSingletonRegisterForAsmOperand(unsigned i, + const AsmMatcherInfo &Info) const; + + /// FindAsmOperand - Find the AsmOperand with the specified name and + /// suboperand index. + int FindAsmOperand(StringRef N, int SubOpIdx) const { + for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) + if (N == AsmOperands[i].SrcOpName && + SubOpIdx == AsmOperands[i].SubOpIdx) + return i; + return -1; + } + + /// FindAsmOperandNamed - Find the first AsmOperand with the specified name. + /// This does not check the suboperand index. + int FindAsmOperandNamed(StringRef N) const { + for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) + if (N == AsmOperands[i].SrcOpName) + return i; + return -1; + } + + void BuildInstructionResultOperands(); + void BuildAliasResultOperands(); + + /// operator< - Compare two matchables. + bool operator<(const MatchableInfo &RHS) const { + // The primary comparator is the instruction mnemonic. + if (Mnemonic != RHS.Mnemonic) + return Mnemonic < RHS.Mnemonic; + + if (AsmOperands.size() != RHS.AsmOperands.size()) + return AsmOperands.size() < RHS.AsmOperands.size(); // Compare lexicographically by operand. The matcher validates that other - // orderings wouldn't be ambiguous using \see CouldMatchAmiguouslyWith(). - for (unsigned i = 0, e = Operands.size(); i != e; ++i) { - if (*Operands[i].Class < *RHS.Operands[i].Class) + // orderings wouldn't be ambiguous using \see CouldMatchAmbiguouslyWith(). + for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { + if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class) return true; - if (*RHS.Operands[i].Class < *Operands[i].Class) + if (*RHS.AsmOperands[i].Class < *AsmOperands[i].Class) return false; } return false; } - /// CouldMatchAmiguouslyWith - Check whether this instruction could + /// CouldMatchAmbiguouslyWith - Check whether this matchable could /// ambiguously match the same set of operands as \arg RHS (without being a /// strictly superior match). - bool CouldMatchAmiguouslyWith(const InstructionInfo &RHS) { + bool CouldMatchAmbiguouslyWith(const MatchableInfo &RHS) { + // The primary comparator is the instruction mnemonic. + if (Mnemonic != RHS.Mnemonic) + return false; + // The number of operands is unambiguous. - if (Operands.size() != RHS.Operands.size()) + if (AsmOperands.size() != RHS.AsmOperands.size()) return false; // Otherwise, make sure the ordering of the two instructions is unambiguous @@ -496,29 +485,31 @@ struct InstructionInfo { // Tokens and operand kinds are unambiguous (assuming a correct target // specific parser). - for (unsigned i = 0, e = Operands.size(); i != e; ++i) - if (Operands[i].Class->Kind != RHS.Operands[i].Class->Kind || - Operands[i].Class->Kind == ClassInfo::Token) - if (*Operands[i].Class < *RHS.Operands[i].Class || - *RHS.Operands[i].Class < *Operands[i].Class) + for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) + if (AsmOperands[i].Class->Kind != RHS.AsmOperands[i].Class->Kind || + AsmOperands[i].Class->Kind == ClassInfo::Token) + if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class || + *RHS.AsmOperands[i].Class < *AsmOperands[i].Class) return false; - + // Otherwise, this operand could commute if all operands are equivalent, or // there is a pair of operands that compare less than and a pair that // compare greater than. bool HasLT = false, HasGT = false; - for (unsigned i = 0, e = Operands.size(); i != e; ++i) { - if (*Operands[i].Class < *RHS.Operands[i].Class) + for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { + if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class) HasLT = true; - if (*RHS.Operands[i].Class < *Operands[i].Class) + if (*RHS.AsmOperands[i].Class < *AsmOperands[i].Class) HasGT = true; } return !(HasLT ^ HasGT); } -public: void dump(); + +private: + void TokenizeAsmString(const AsmMatcherInfo &Info); }; /// SubtargetFeatureInfo - Helper class for storing information on a subtarget @@ -530,26 +521,52 @@ struct SubtargetFeatureInfo { /// \brief An unique index assigned to represent this feature. unsigned Index; + SubtargetFeatureInfo(Record *D, unsigned Idx) : TheDef(D), Index(Idx) {} + /// \brief The name of the enumerated constant identifying this feature. - std::string EnumName; + std::string getEnumName() const { + return "Feature_" + TheDef->getName(); + } }; +struct OperandMatchEntry { + unsigned OperandMask; + MatchableInfo* MI; + ClassInfo *CI; + + static OperandMatchEntry Create(MatchableInfo* mi, ClassInfo *ci, + unsigned opMask) { + OperandMatchEntry X; + X.OperandMask = opMask; + X.CI = ci; + X.MI = mi; + return X; + } +}; + + class AsmMatcherInfo { public: + /// Tracked Records + RecordKeeper &Records; + /// The tablegen AsmParser record. Record *AsmParser; - /// The AsmParser "CommentDelimiter" value. - std::string CommentDelimiter; + /// Target - The target information. + CodeGenTarget &Target; /// The AsmParser "RegisterPrefix" value. std::string RegisterPrefix; /// The classes which are needed for matching. std::vector<ClassInfo*> Classes; - - /// The information on the instruction to match. - std::vector<InstructionInfo*> Instructions; + + /// The information on the matchables to match. + std::vector<MatchableInfo*> Matchables; + + /// Info for custom matching operands by user defined methods. + std::vector<OperandMatchEntry> OperandMatchInfo; /// Map of Register records to their class information. std::map<Record*, ClassInfo*> RegisterClasses; @@ -572,108 +589,265 @@ private: ClassInfo *getTokenClass(StringRef Token); /// getOperandClass - Lookup or create the class for the given operand. - ClassInfo *getOperandClass(StringRef Token, - const CodeGenInstruction::OperandInfo &OI); - - /// getSubtargetFeature - Lookup or create the subtarget feature info for the - /// given operand. - SubtargetFeatureInfo *getSubtargetFeature(Record *Def) { - assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!"); - - SubtargetFeatureInfo *&Entry = SubtargetFeatures[Def]; - if (!Entry) { - Entry = new SubtargetFeatureInfo; - Entry->TheDef = Def; - Entry->Index = SubtargetFeatures.size() - 1; - Entry->EnumName = "Feature_" + Def->getName(); - assert(Entry->Index < 32 && "Too many subtarget features!"); - } - - return Entry; - } + ClassInfo *getOperandClass(const CGIOperandList::OperandInfo &OI, + int SubOpIdx = -1); /// BuildRegisterClasses - Build the ClassInfo* instances for register /// classes. - void BuildRegisterClasses(CodeGenTarget &Target, - std::set<std::string> &SingletonRegisterNames); + void BuildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters); /// BuildOperandClasses - Build the ClassInfo* instances for user defined /// operand classes. - void BuildOperandClasses(CodeGenTarget &Target); + void BuildOperandClasses(); + + void BuildInstructionOperandReference(MatchableInfo *II, StringRef OpName, + unsigned AsmOpIdx); + void BuildAliasOperandReference(MatchableInfo *II, StringRef OpName, + MatchableInfo::AsmOperand &Op); public: - AsmMatcherInfo(Record *_AsmParser); + AsmMatcherInfo(Record *AsmParser, + CodeGenTarget &Target, + RecordKeeper &Records); /// BuildInfo - Construct the various tables used during matching. - void BuildInfo(CodeGenTarget &Target); + void BuildInfo(); + + /// BuildOperandMatchInfo - Build the necessary information to handle user + /// defined operand parsing methods. + void BuildOperandMatchInfo(); + + /// getSubtargetFeature - Lookup or create the subtarget feature info for the + /// given operand. + SubtargetFeatureInfo *getSubtargetFeature(Record *Def) const { + assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!"); + std::map<Record*, SubtargetFeatureInfo*>::const_iterator I = + SubtargetFeatures.find(Def); + return I == SubtargetFeatures.end() ? 0 : I->second; + } + + RecordKeeper &getRecords() const { + return Records; + } }; } -void InstructionInfo::dump() { - errs() << InstrName << " -- " << "flattened:\"" << AsmString << '\"' - << ", tokens:["; - for (unsigned i = 0, e = Tokens.size(); i != e; ++i) { - errs() << Tokens[i]; - if (i + 1 != e) - errs() << ", "; - } - errs() << "]\n"; +void MatchableInfo::dump() { + errs() << TheDef->getName() << " -- " << "flattened:\"" << AsmString <<"\"\n"; - for (unsigned i = 0, e = Operands.size(); i != e; ++i) { - Operand &Op = Operands[i]; + for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { + AsmOperand &Op = AsmOperands[i]; errs() << " op[" << i << "] = " << Op.Class->ClassName << " - "; - if (Op.Class->Kind == ClassInfo::Token) { - errs() << '\"' << Tokens[i] << "\"\n"; - continue; + errs() << '\"' << Op.Token << "\"\n"; + } +} + +void MatchableInfo::Initialize(const AsmMatcherInfo &Info, + SmallPtrSet<Record*, 16> &SingletonRegisters) { + // TODO: Eventually support asmparser for Variant != 0. + AsmString = CodeGenInstruction::FlattenAsmStringVariants(AsmString, 0); + + TokenizeAsmString(Info); + + // Compute the require features. + std::vector<Record*> Predicates =TheDef->getValueAsListOfDefs("Predicates"); + for (unsigned i = 0, e = Predicates.size(); i != e; ++i) + if (SubtargetFeatureInfo *Feature = + Info.getSubtargetFeature(Predicates[i])) + RequiredFeatures.push_back(Feature); + + // Collect singleton registers, if used. + for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { + if (Record *Reg = getSingletonRegisterForAsmOperand(i, Info)) + SingletonRegisters.insert(Reg); + } +} + +/// TokenizeAsmString - Tokenize a simplified assembly string. +void MatchableInfo::TokenizeAsmString(const AsmMatcherInfo &Info) { + StringRef String = AsmString; + unsigned Prev = 0; + bool InTok = true; + for (unsigned i = 0, e = String.size(); i != e; ++i) { + switch (String[i]) { + case '[': + case ']': + case '*': + case '!': + case ' ': + case '\t': + case ',': + if (InTok) { + AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); + InTok = false; + } + if (!isspace(String[i]) && String[i] != ',') + AsmOperands.push_back(AsmOperand(String.substr(i, 1))); + Prev = i + 1; + break; + + case '\\': + if (InTok) { + AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); + InTok = false; + } + ++i; + assert(i != String.size() && "Invalid quoted character"); + AsmOperands.push_back(AsmOperand(String.substr(i, 1))); + Prev = i + 1; + break; + + case '$': { + if (InTok) { + AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); + InTok = false; + } + + // If this isn't "${", treat like a normal token. + if (i + 1 == String.size() || String[i + 1] != '{') { + Prev = i; + break; + } + + StringRef::iterator End = std::find(String.begin() + i, String.end(),'}'); + assert(End != String.end() && "Missing brace in operand reference!"); + size_t EndPos = End - String.begin(); + AsmOperands.push_back(AsmOperand(String.slice(i, EndPos+1))); + Prev = EndPos + 1; + i = EndPos; + break; } - if (!Op.OperandInfo) { - errs() << "(singleton register)\n"; - continue; + case '.': + if (InTok) + AsmOperands.push_back(AsmOperand(String.slice(Prev, i))); + Prev = i; + InTok = true; + break; + + default: + InTok = true; } + } + if (InTok && Prev != String.size()) + AsmOperands.push_back(AsmOperand(String.substr(Prev))); + + // The first token of the instruction is the mnemonic, which must be a + // simple string, not a $foo variable or a singleton register. + assert(!AsmOperands.empty() && "Instruction has no tokens?"); + Mnemonic = AsmOperands[0].Token; + if (Mnemonic[0] == '$' || getSingletonRegisterForAsmOperand(0, Info)) + throw TGError(TheDef->getLoc(), + "Invalid instruction mnemonic '" + Mnemonic.str() + "'!"); + + // Remove the first operand, it is tracked in the mnemonic field. + AsmOperands.erase(AsmOperands.begin()); +} - const CodeGenInstruction::OperandInfo &OI = *Op.OperandInfo; - errs() << OI.Name << " " << OI.Rec->getName() - << " (" << OI.MIOperandNo << ", " << OI.MINumOperands << ")\n"; +bool MatchableInfo::Validate(StringRef CommentDelimiter, bool Hack) const { + // Reject matchables with no .s string. + if (AsmString.empty()) + throw TGError(TheDef->getLoc(), "instruction with empty asm string"); + + // Reject any matchables with a newline in them, they should be marked + // isCodeGenOnly if they are pseudo instructions. + if (AsmString.find('\n') != std::string::npos) + throw TGError(TheDef->getLoc(), + "multiline instruction is not valid for the asmparser, " + "mark it isCodeGenOnly"); + + // Remove comments from the asm string. We know that the asmstring only + // has one line. + if (!CommentDelimiter.empty() && + StringRef(AsmString).find(CommentDelimiter) != StringRef::npos) + throw TGError(TheDef->getLoc(), + "asmstring for instruction has comment character in it, " + "mark it isCodeGenOnly"); + + // Reject matchables with operand modifiers, these aren't something we can + // handle, the target should be refactored to use operands instead of + // modifiers. + // + // Also, check for instructions which reference the operand multiple times; + // this implies a constraint we would not honor. + std::set<std::string> OperandNames; + for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { + StringRef Tok = AsmOperands[i].Token; + if (Tok[0] == '$' && Tok.find(':') != StringRef::npos) + throw TGError(TheDef->getLoc(), + "matchable with operand modifier '" + Tok.str() + + "' not supported by asm matcher. Mark isCodeGenOnly!"); + + // Verify that any operand is only mentioned once. + // We reject aliases and ignore instructions for now. + if (Tok[0] == '$' && !OperandNames.insert(Tok).second) { + if (!Hack) + throw TGError(TheDef->getLoc(), + "ERROR: matchable with tied operand '" + Tok.str() + + "' can never be matched!"); + // FIXME: Should reject these. The ARM backend hits this with $lane in a + // bunch of instructions. It is unclear what the right answer is. + DEBUG({ + errs() << "warning: '" << TheDef->getName() << "': " + << "ignoring instruction with tied operand '" + << Tok.str() << "'\n"; + }); + return false; + } } + + return true; +} + +/// getSingletonRegisterForAsmOperand - If the specified token is a singleton +/// register, return the register name, otherwise return a null StringRef. +Record *MatchableInfo:: +getSingletonRegisterForAsmOperand(unsigned i, const AsmMatcherInfo &Info) const{ + StringRef Tok = AsmOperands[i].Token; + if (!Tok.startswith(Info.RegisterPrefix)) + return 0; + + StringRef RegName = Tok.substr(Info.RegisterPrefix.size()); + if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(RegName)) + return Reg->TheDef; + + // If there is no register prefix (i.e. "%" in "%eax"), then this may + // be some random non-register token, just ignore it. + if (Info.RegisterPrefix.empty()) + return 0; + + // Otherwise, we have something invalid prefixed with the register prefix, + // such as %foo. + std::string Err = "unable to find register for '" + RegName.str() + + "' (which matches register prefix)"; + throw TGError(TheDef->getLoc(), Err); } static std::string getEnumNameForToken(StringRef Str) { std::string Res; - + for (StringRef::iterator it = Str.begin(), ie = Str.end(); it != ie; ++it) { switch (*it) { case '*': Res += "_STAR_"; break; case '%': Res += "_PCT_"; break; case ':': Res += "_COLON_"; break; - + case '!': Res += "_EXCLAIM_"; break; + case '.': Res += "_DOT_"; break; default: - if (isalnum(*it)) { + if (isalnum(*it)) Res += *it; - } else { + else Res += "_" + utostr((unsigned) *it) + "_"; - } } } return Res; } -/// getRegisterRecord - Get the register record for \arg name, or 0. -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")) - return Reg.TheDef; - } - - return 0; -} - ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) { ClassInfo *&Entry = TokenClasses[Token]; - + if (!Entry) { Entry = new ClassInfo(); Entry->Kind = ClassInfo::Token; @@ -682,6 +856,7 @@ ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) { Entry->ValueName = Token; Entry->PredicateMethod = "<invalid>"; Entry->RenderMethod = "<invalid>"; + Entry->ParserMethod = ""; Classes.push_back(Entry); } @@ -689,65 +864,58 @@ ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) { } ClassInfo * -AsmMatcherInfo::getOperandClass(StringRef Token, - const CodeGenInstruction::OperandInfo &OI) { - if (OI.Rec->isSubClassOf("RegisterClass")) { - ClassInfo *CI = RegisterClassClasses[OI.Rec]; - - if (!CI) { - PrintError(OI.Rec->getLoc(), "register class has no class info!"); - throw std::string("ERROR: Missing register class!"); - } - - return CI; +AsmMatcherInfo::getOperandClass(const CGIOperandList::OperandInfo &OI, + int SubOpIdx) { + Record *Rec = OI.Rec; + if (SubOpIdx != -1) + Rec = dynamic_cast<DefInit*>(OI.MIOperandInfo->getArg(SubOpIdx))->getDef(); + + if (Rec->isSubClassOf("RegisterClass")) { + if (ClassInfo *CI = RegisterClassClasses[Rec]) + return CI; + throw TGError(Rec->getLoc(), "register class has no class info!"); } - assert(OI.Rec->isSubClassOf("Operand") && "Unexpected operand!"); - Record *MatchClass = OI.Rec->getValueAsDef("ParserMatchClass"); - ClassInfo *CI = AsmOperandClasses[MatchClass]; - - if (!CI) { - PrintError(OI.Rec->getLoc(), "operand has no match class!"); - throw std::string("ERROR: Missing match class!"); - } + assert(Rec->isSubClassOf("Operand") && "Unexpected operand!"); + Record *MatchClass = Rec->getValueAsDef("ParserMatchClass"); + if (ClassInfo *CI = AsmOperandClasses[MatchClass]) + return CI; - return CI; + throw TGError(Rec->getLoc(), "operand has no match class!"); } -void AsmMatcherInfo::BuildRegisterClasses(CodeGenTarget &Target, - std::set<std::string> - &SingletonRegisterNames) { - std::vector<CodeGenRegisterClass> RegisterClasses; - std::vector<CodeGenRegister> Registers; - - RegisterClasses = Target.getRegisterClasses(); - Registers = Target.getRegisters(); +void AsmMatcherInfo:: +BuildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) { + const std::vector<CodeGenRegister> &Registers = Target.getRegisters(); + const std::vector<CodeGenRegisterClass> &RegClassList = + Target.getRegisterClasses(); // The register sets used for matching. std::set< std::set<Record*> > RegisterSets; - // Gather the defined sets. - for (std::vector<CodeGenRegisterClass>::iterator it = RegisterClasses.begin(), - ie = RegisterClasses.end(); it != ie; ++it) + // Gather the defined sets. + for (std::vector<CodeGenRegisterClass>::const_iterator it = + RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) RegisterSets.insert(std::set<Record*>(it->Elements.begin(), it->Elements.end())); // Add any required singleton sets. - for (std::set<std::string>::iterator it = SingletonRegisterNames.begin(), - ie = SingletonRegisterNames.end(); it != ie; ++it) - if (Record *Rec = getRegisterRecord(Target, *it)) - RegisterSets.insert(std::set<Record*>(&Rec, &Rec + 1)); - + for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(), + ie = SingletonRegisters.end(); it != ie; ++it) { + Record *Rec = *it; + RegisterSets.insert(std::set<Record*>(&Rec, &Rec + 1)); + } + // Introduce derived sets where necessary (when a register does not determine // a unique register set class), and build the mapping of registers to the set // they should classify to. std::map<Record*, std::set<Record*> > RegisterMap; - for (std::vector<CodeGenRegister>::iterator it = Registers.begin(), + for (std::vector<CodeGenRegister>::const_iterator it = Registers.begin(), ie = Registers.end(); it != ie; ++it) { - CodeGenRegister &CGR = *it; + const CodeGenRegister &CGR = *it; // Compute the intersection of all sets containing this register. std::set<Record*> ContainingSet; - + for (std::set< std::set<Record*> >::iterator it = RegisterSets.begin(), ie = RegisterSets.end(); it != ie; ++it) { if (!it->count(CGR.TheDef)) @@ -755,14 +923,14 @@ void AsmMatcherInfo::BuildRegisterClasses(CodeGenTarget &Target, if (ContainingSet.empty()) { ContainingSet = *it; - } else { - std::set<Record*> Tmp; - std::swap(Tmp, ContainingSet); - std::insert_iterator< std::set<Record*> > II(ContainingSet, - ContainingSet.begin()); - std::set_intersection(Tmp.begin(), Tmp.end(), it->begin(), it->end(), - II); + continue; } + + std::set<Record*> Tmp; + std::swap(Tmp, ContainingSet); + std::insert_iterator< std::set<Record*> > II(ContainingSet, + ContainingSet.begin()); + std::set_intersection(Tmp.begin(), Tmp.end(), it->begin(), it->end(), II); } if (!ContainingSet.empty()) { @@ -795,14 +963,14 @@ void AsmMatcherInfo::BuildRegisterClasses(CodeGenTarget &Target, ClassInfo *CI = RegisterSetClasses[*it]; for (std::set< std::set<Record*> >::iterator it2 = RegisterSets.begin(), ie2 = RegisterSets.end(); it2 != ie2; ++it2) - if (*it != *it2 && + if (*it != *it2 && std::includes(it2->begin(), it2->end(), it->begin(), it->end())) CI->SuperClasses.push_back(RegisterSetClasses[*it2]); } // Name the register classes which correspond to a user defined RegisterClass. - for (std::vector<CodeGenRegisterClass>::iterator it = RegisterClasses.begin(), - ie = RegisterClasses.end(); it != ie; ++it) { + for (std::vector<CodeGenRegisterClass>::const_iterator + it = RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) { ClassInfo *CI = RegisterSetClasses[std::set<Record*>(it->Elements.begin(), it->Elements.end())]; if (CI->ValueName.empty()) { @@ -818,36 +986,35 @@ void AsmMatcherInfo::BuildRegisterClasses(CodeGenTarget &Target, // Populate the map for individual registers. for (std::map<Record*, std::set<Record*> >::iterator it = RegisterMap.begin(), ie = RegisterMap.end(); it != ie; ++it) - this->RegisterClasses[it->first] = RegisterSetClasses[it->second]; + RegisterClasses[it->first] = RegisterSetClasses[it->second]; // Name the register classes which correspond to singleton registers. - for (std::set<std::string>::iterator it = SingletonRegisterNames.begin(), - ie = SingletonRegisterNames.end(); it != ie; ++it) { - if (Record *Rec = getRegisterRecord(Target, *it)) { - ClassInfo *CI = this->RegisterClasses[Rec]; - assert(CI && "Missing singleton register class info!"); - - if (CI->ValueName.empty()) { - CI->ClassName = Rec->getName(); - CI->Name = "MCK_" + Rec->getName(); - CI->ValueName = Rec->getName(); - } else - CI->ValueName = CI->ValueName + "," + Rec->getName(); - } + for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(), + ie = SingletonRegisters.end(); it != ie; ++it) { + Record *Rec = *it; + ClassInfo *CI = RegisterClasses[Rec]; + assert(CI && "Missing singleton register class info!"); + + if (CI->ValueName.empty()) { + CI->ClassName = Rec->getName(); + CI->Name = "MCK_" + Rec->getName(); + CI->ValueName = Rec->getName(); + } else + CI->ValueName = CI->ValueName + "," + Rec->getName(); } } -void AsmMatcherInfo::BuildOperandClasses(CodeGenTarget &Target) { - std::vector<Record*> AsmOperands; - AsmOperands = Records.getAllDerivedDefinitions("AsmOperandClass"); +void AsmMatcherInfo::BuildOperandClasses() { + std::vector<Record*> AsmOperands = + Records.getAllDerivedDefinitions("AsmOperandClass"); // Pre-populate AsmOperandClasses map. - for (std::vector<Record*>::iterator it = AsmOperands.begin(), + 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(), + for (std::vector<Record*>::iterator it = AsmOperands.begin(), ie = AsmOperands.end(); it != ie; ++it, ++Index) { ClassInfo *CI = AsmOperandClasses[*it]; CI->Kind = ClassInfo::UserClass0 + Index; @@ -875,7 +1042,7 @@ void AsmMatcherInfo::BuildOperandClasses(CodeGenTarget &Target) { if (StringInit *SI = dynamic_cast<StringInit*>(PMName)) { CI->PredicateMethod = SI->getValue(); } else { - assert(dynamic_cast<UnsetInit*>(PMName) && + assert(dynamic_cast<UnsetInit*>(PMName) && "Unexpected PredicateMethod field!"); CI->PredicateMethod = "is" + CI->ClassName; } @@ -890,128 +1057,192 @@ void AsmMatcherInfo::BuildOperandClasses(CodeGenTarget &Target) { CI->RenderMethod = "add" + CI->ClassName + "Operands"; } + // Get the parse method name or leave it as empty. + Init *PRMName = (*it)->getValueInit("ParserMethod"); + if (StringInit *SI = dynamic_cast<StringInit*>(PRMName)) + CI->ParserMethod = SI->getValue(); + AsmOperandClasses[*it] = CI; Classes.push_back(CI); } } -AsmMatcherInfo::AsmMatcherInfo(Record *_AsmParser) - : AsmParser(_AsmParser), - CommentDelimiter(AsmParser->getValueAsString("CommentDelimiter")), - RegisterPrefix(AsmParser->getValueAsString("RegisterPrefix")) -{ +AsmMatcherInfo::AsmMatcherInfo(Record *asmParser, + CodeGenTarget &target, + RecordKeeper &records) + : Records(records), AsmParser(asmParser), Target(target), + RegisterPrefix(AsmParser->getValueAsString("RegisterPrefix")) { +} + +/// BuildOperandMatchInfo - Build the necessary information to handle user +/// defined operand parsing methods. +void AsmMatcherInfo::BuildOperandMatchInfo() { + + /// Map containing a mask with all operands indicies that can be found for + /// that class inside a instruction. + std::map<ClassInfo*, unsigned> OpClassMask; + + for (std::vector<MatchableInfo*>::const_iterator it = + Matchables.begin(), ie = Matchables.end(); + it != ie; ++it) { + MatchableInfo &II = **it; + OpClassMask.clear(); + + // Keep track of all operands of this instructions which belong to the + // same class. + for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) { + MatchableInfo::AsmOperand &Op = II.AsmOperands[i]; + if (Op.Class->ParserMethod.empty()) + continue; + unsigned &OperandMask = OpClassMask[Op.Class]; + OperandMask |= (1 << i); + } + + // Generate operand match info for each mnemonic/operand class pair. + for (std::map<ClassInfo*, unsigned>::iterator iit = OpClassMask.begin(), + iie = OpClassMask.end(); iit != iie; ++iit) { + unsigned OpMask = iit->second; + ClassInfo *CI = iit->first; + OperandMatchInfo.push_back(OperandMatchEntry::Create(&II, CI, OpMask)); + } + } } -void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) { +void AsmMatcherInfo::BuildInfo() { + // Build information about all of the AssemblerPredicates. + std::vector<Record*> AllPredicates = + Records.getAllDerivedDefinitions("Predicate"); + for (unsigned i = 0, e = AllPredicates.size(); i != e; ++i) { + Record *Pred = AllPredicates[i]; + // Ignore predicates that are not intended for the assembler. + if (!Pred->getValueAsBit("AssemblerMatcherPredicate")) + continue; + + if (Pred->getName().empty()) + throw TGError(Pred->getLoc(), "Predicate has no name!"); + + unsigned FeatureNo = SubtargetFeatures.size(); + SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo); + assert(FeatureNo < 32 && "Too many subtarget features!"); + } + + StringRef CommentDelimiter = AsmParser->getValueAsString("CommentDelimiter"); + // Parse the instructions; we need to do this first so that we can gather the // singleton register classes. - std::set<std::string> SingletonRegisterNames; - - const std::vector<const CodeGenInstruction*> &InstrList = - Target.getInstructionsByEnumValue(); - - for (unsigned i = 0, e = InstrList.size(); i != e; ++i) { - const CodeGenInstruction &CGI = *InstrList[i]; + SmallPtrSet<Record*, 16> SingletonRegisters; + for (CodeGenTarget::inst_iterator I = Target.inst_begin(), + E = Target.inst_end(); I != E; ++I) { + const CodeGenInstruction &CGI = **I; + // If the tblgen -match-prefix option is specified (for tblgen hackers), + // filter the set of instructions we consider. if (!StringRef(CGI.TheDef->getName()).startswith(MatchPrefix)) continue; - OwningPtr<InstructionInfo> II(new InstructionInfo()); - - II->InstrName = CGI.TheDef->getName(); - II->Instr = &CGI; - II->AsmString = FlattenVariants(CGI.AsmString, 0); - - // Remove comments from the asm string. - if (!CommentDelimiter.empty()) { - size_t Idx = StringRef(II->AsmString).find(CommentDelimiter); - if (Idx != StringRef::npos) - II->AsmString = II->AsmString.substr(0, Idx); - } - - TokenizeAsmString(II->AsmString, II->Tokens); - - // Ignore instructions which shouldn't be matched. - if (!IsAssemblerInstruction(CGI.TheDef->getName(), CGI, II->Tokens)) + // Ignore "codegen only" instructions. + if (CGI.TheDef->getValueAsBit("isCodeGenOnly")) continue; - // Collect singleton registers, if used. - if (!RegisterPrefix.empty()) { - for (unsigned i = 0, e = II->Tokens.size(); i != e; ++i) { - if (II->Tokens[i].startswith(RegisterPrefix)) { - StringRef RegName = II->Tokens[i].substr(RegisterPrefix.size()); - Record *Rec = getRegisterRecord(Target, RegName); - - if (!Rec) { - std::string Err = "unable to find register for '" + RegName.str() + - "' (which matches register prefix)"; - throw TGError(CGI.TheDef->getLoc(), Err); - } - - SingletonRegisterNames.insert(RegName); + // Validate the operand list to ensure we can handle this instruction. + for (unsigned i = 0, e = CGI.Operands.size(); i != e; ++i) { + const CGIOperandList::OperandInfo &OI = CGI.Operands[i]; + + // Validate tied operands. + if (OI.getTiedRegister() != -1) { + // If we have a tied operand that consists of multiple MCOperands, + // reject it. We reject aliases and ignore instructions for now. + if (OI.MINumOperands != 1) { + // FIXME: Should reject these. The ARM backend hits this with $lane + // in a bunch of instructions. It is unclear what the right answer is. + DEBUG({ + errs() << "warning: '" << CGI.TheDef->getName() << "': " + << "ignoring instruction with multi-operand tied operand '" + << OI.Name << "'\n"; + }); + continue; } } } - // Compute the require features. - ListInit *Predicates = CGI.TheDef->getValueAsListInit("Predicates"); - for (unsigned i = 0, e = Predicates->getSize(); i != e; ++i) { - if (DefInit *Pred = dynamic_cast<DefInit*>(Predicates->getElement(i))) { - // Ignore OptForSize and OptForSpeed, they aren't really requirements, - // rather they are hints to isel. - // - // FIXME: Find better way to model this. - if (Pred->getDef()->getName() == "OptForSize" || - Pred->getDef()->getName() == "OptForSpeed") - continue; + OwningPtr<MatchableInfo> II(new MatchableInfo(CGI)); - // FIXME: Total hack; for now, we just limit ourselves to In32BitMode - // and In64BitMode, because we aren't going to have the right feature - // masks for SSE and friends. We need to decide what we are going to do - // about CPU subtypes to implement this the right way. - if (Pred->getDef()->getName() != "In32BitMode" && - Pred->getDef()->getName() != "In64BitMode") - continue; + II->Initialize(*this, SingletonRegisters); - II->RequiredFeatures.push_back(getSubtargetFeature(Pred->getDef())); - } - } + // Ignore instructions which shouldn't be matched and diagnose invalid + // instruction definitions with an error. + if (!II->Validate(CommentDelimiter, true)) + continue; - Instructions.push_back(II.take()); + // Ignore "Int_*" and "*_Int" instructions, which are internal aliases. + // + // FIXME: This is a total hack. + if (StringRef(II->TheDef->getName()).startswith("Int_") || + StringRef(II->TheDef->getName()).endswith("_Int")) + continue; + + Matchables.push_back(II.take()); + } + + // Parse all of the InstAlias definitions and stick them in the list of + // matchables. + std::vector<Record*> AllInstAliases = + Records.getAllDerivedDefinitions("InstAlias"); + for (unsigned i = 0, e = AllInstAliases.size(); i != e; ++i) { + CodeGenInstAlias *Alias = new CodeGenInstAlias(AllInstAliases[i], Target); + + // If the tblgen -match-prefix option is specified (for tblgen hackers), + // filter the set of instruction aliases we consider, based on the target + // instruction. + if (!StringRef(Alias->ResultInst->TheDef->getName()).startswith( + MatchPrefix)) + continue; + + OwningPtr<MatchableInfo> II(new MatchableInfo(Alias)); + + II->Initialize(*this, SingletonRegisters); + + // Validate the alias definitions. + II->Validate(CommentDelimiter, false); + + Matchables.push_back(II.take()); } // Build info for the register classes. - BuildRegisterClasses(Target, SingletonRegisterNames); + BuildRegisterClasses(SingletonRegisters); // Build info for the user defined assembly operand classes. - BuildOperandClasses(Target); + BuildOperandClasses(); - // Build the instruction information. - for (std::vector<InstructionInfo*>::iterator it = Instructions.begin(), - ie = Instructions.end(); it != ie; ++it) { - InstructionInfo *II = *it; + // Build the information about matchables, now that we have fully formed + // classes. + for (std::vector<MatchableInfo*>::iterator it = Matchables.begin(), + ie = Matchables.end(); it != ie; ++it) { + MatchableInfo *II = *it; - for (unsigned i = 0, e = II->Tokens.size(); i != e; ++i) { - StringRef Token = II->Tokens[i]; + // Parse the tokens after the mnemonic. + // Note: BuildInstructionOperandReference may insert new AsmOperands, so + // don't precompute the loop bound. + for (unsigned i = 0; i != II->AsmOperands.size(); ++i) { + MatchableInfo::AsmOperand &Op = II->AsmOperands[i]; + StringRef Token = Op.Token; // Check for singleton registers. - if (!RegisterPrefix.empty() && Token.startswith(RegisterPrefix)) { - StringRef RegName = II->Tokens[i].substr(RegisterPrefix.size()); - InstructionInfo::Operand Op; - Op.Class = RegisterClasses[getRegisterRecord(Target, RegName)]; - Op.OperandInfo = 0; + if (Record *RegRecord = II->getSingletonRegisterForAsmOperand(i, *this)) { + Op.Class = RegisterClasses[RegRecord]; assert(Op.Class && Op.Class->Registers.size() == 1 && "Unexpected class for singleton register"); - II->Operands.push_back(Op); continue; } // Check for simple tokens. if (Token[0] != '$') { - InstructionInfo::Operand Op; Op.Class = getTokenClass(Token); - Op.OperandInfo = 0; - II->Operands.push_back(Op); + continue; + } + + if (Token.size() > 1 && isdigit(Token[1])) { + Op.Class = getTokenClass(Token); continue; } @@ -1022,58 +1253,204 @@ void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) { else OperandName = Token.substr(1); - // Map this token to an operand. FIXME: Move elsewhere. - unsigned Idx; - try { - Idx = II->Instr->getOperandNamed(OperandName); - } catch(...) { - throw std::string("error: unable to find operand: '" + - OperandName.str() + "'"); - } + if (II->DefRec.is<const CodeGenInstruction*>()) + BuildInstructionOperandReference(II, OperandName, i); + else + BuildAliasOperandReference(II, OperandName, Op); + } - // 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; - } - } + if (II->DefRec.is<const CodeGenInstruction*>()) + II->BuildInstructionResultOperands(); + else + II->BuildAliasResultOperands(); + } - assert(OI && "Unable to find tied operand target!"); - } + // Reorder classes so that classes preceed super classes. + std::sort(Classes.begin(), Classes.end(), less_ptr<ClassInfo>()); +} - InstructionInfo::Operand Op; - Op.Class = getOperandClass(Token, *OI); - Op.OperandInfo = OI; - II->Operands.push_back(Op); +/// BuildInstructionOperandReference - The specified operand is a reference to a +/// named operand such as $src. Resolve the Class and OperandInfo pointers. +void AsmMatcherInfo:: +BuildInstructionOperandReference(MatchableInfo *II, + StringRef OperandName, + unsigned AsmOpIdx) { + const CodeGenInstruction &CGI = *II->DefRec.get<const CodeGenInstruction*>(); + const CGIOperandList &Operands = CGI.Operands; + MatchableInfo::AsmOperand *Op = &II->AsmOperands[AsmOpIdx]; + + // Map this token to an operand. + unsigned Idx; + if (!Operands.hasOperandNamed(OperandName, Idx)) + throw TGError(II->TheDef->getLoc(), "error: unable to find operand: '" + + OperandName.str() + "'"); + + // If the instruction operand has multiple suboperands, but the parser + // match class for the asm operand is still the default "ImmAsmOperand", + // then handle each suboperand separately. + if (Op->SubOpIdx == -1 && Operands[Idx].MINumOperands > 1) { + Record *Rec = Operands[Idx].Rec; + assert(Rec->isSubClassOf("Operand") && "Unexpected operand!"); + Record *MatchClass = Rec->getValueAsDef("ParserMatchClass"); + if (MatchClass && MatchClass->getValueAsString("Name") == "Imm") { + // Insert remaining suboperands after AsmOpIdx in II->AsmOperands. + StringRef Token = Op->Token; // save this in case Op gets moved + for (unsigned SI = 1, SE = Operands[Idx].MINumOperands; SI != SE; ++SI) { + MatchableInfo::AsmOperand NewAsmOp(Token); + NewAsmOp.SubOpIdx = SI; + II->AsmOperands.insert(II->AsmOperands.begin()+AsmOpIdx+SI, NewAsmOp); + } + // Replace Op with first suboperand. + Op = &II->AsmOperands[AsmOpIdx]; // update the pointer in case it moved + Op->SubOpIdx = 0; } } - // Reorder classes so that classes preceed super classes. - std::sort(Classes.begin(), Classes.end(), less_ptr<ClassInfo>()); + // Set up the operand class. + Op->Class = getOperandClass(Operands[Idx], Op->SubOpIdx); + + // If the named operand is tied, canonicalize it to the untied operand. + // For example, something like: + // (outs GPR:$dst), (ins GPR:$src) + // with an asmstring of + // "inc $src" + // we want to canonicalize to: + // "inc $dst" + // so that we know how to provide the $dst operand when filling in the result. + int OITied = Operands[Idx].getTiedRegister(); + if (OITied != -1) { + // The tied operand index is an MIOperand index, find the operand that + // contains it. + std::pair<unsigned, unsigned> Idx = Operands.getSubOperandNumber(OITied); + OperandName = Operands[Idx.first].Name; + Op->SubOpIdx = Idx.second; + } + + Op->SrcOpName = OperandName; } -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]; +/// BuildAliasOperandReference - When parsing an operand reference out of the +/// matching string (e.g. "movsx $src, $dst"), determine what the class of the +/// operand reference is by looking it up in the result pattern definition. +void AsmMatcherInfo::BuildAliasOperandReference(MatchableInfo *II, + StringRef OperandName, + MatchableInfo::AsmOperand &Op) { + const CodeGenInstAlias &CGA = *II->DefRec.get<const CodeGenInstAlias*>(); + + // Set up the operand class. + for (unsigned i = 0, e = CGA.ResultOperands.size(); i != e; ++i) + if (CGA.ResultOperands[i].isRecord() && + CGA.ResultOperands[i].getName() == OperandName) { + // It's safe to go with the first one we find, because CodeGenInstAlias + // validates that all operands with the same name have the same record. + unsigned ResultIdx = CGA.ResultInstOperandIndex[i].first; + Op.SubOpIdx = CGA.ResultInstOperandIndex[i].second; + Op.Class = getOperandClass(CGA.ResultInst->Operands[ResultIdx], + Op.SubOpIdx); + Op.SrcOpName = OperandName; + return; + } + + throw TGError(II->TheDef->getLoc(), "error: unable to find operand: '" + + OperandName.str() + "'"); +} + +void MatchableInfo::BuildInstructionResultOperands() { + const CodeGenInstruction *ResultInst = getResultInst(); + + // Loop over all operands of the result instruction, determining how to + // populate them. + for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) { + const CGIOperandList::OperandInfo &OpInfo = ResultInst->Operands[i]; + + // If this is a tied operand, just copy from the previously handled operand. + int TiedOp = OpInfo.getTiedRegister(); + if (TiedOp != -1) { + ResOperands.push_back(ResOperand::getTiedOp(TiedOp)); + continue; + } + + // Find out what operand from the asmparser this MCInst operand comes from. + int SrcOperand = FindAsmOperandNamed(OpInfo.Name); + if (OpInfo.Name.empty() || SrcOperand == -1) + throw TGError(TheDef->getLoc(), "Instruction '" + + TheDef->getName() + "' has operand '" + OpInfo.Name + + "' that doesn't appear in asm string!"); + + // Check if the one AsmOperand populates the entire operand. + unsigned NumOperands = OpInfo.MINumOperands; + if (AsmOperands[SrcOperand].SubOpIdx == -1) { + ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, NumOperands)); + continue; + } - return 0; + // Add a separate ResOperand for each suboperand. + for (unsigned AI = 0; AI < NumOperands; ++AI) { + assert(AsmOperands[SrcOperand+AI].SubOpIdx == (int)AI && + AsmOperands[SrcOperand+AI].SrcOpName == OpInfo.Name && + "unexpected AsmOperands for suboperands"); + ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand + AI, 1)); + } + } } -static void EmitConvertToMCInst(CodeGenTarget &Target, - std::vector<InstructionInfo*> &Infos, +void MatchableInfo::BuildAliasResultOperands() { + const CodeGenInstAlias &CGA = *DefRec.get<const CodeGenInstAlias*>(); + const CodeGenInstruction *ResultInst = getResultInst(); + + // Loop over all operands of the result instruction, determining how to + // populate them. + unsigned AliasOpNo = 0; + unsigned LastOpNo = CGA.ResultInstOperandIndex.size(); + for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) { + const CGIOperandList::OperandInfo *OpInfo = &ResultInst->Operands[i]; + + // If this is a tied operand, just copy from the previously handled operand. + int TiedOp = OpInfo->getTiedRegister(); + if (TiedOp != -1) { + ResOperands.push_back(ResOperand::getTiedOp(TiedOp)); + continue; + } + + // Handle all the suboperands for this operand. + const std::string &OpName = OpInfo->Name; + for ( ; AliasOpNo < LastOpNo && + CGA.ResultInstOperandIndex[AliasOpNo].first == i; ++AliasOpNo) { + int SubIdx = CGA.ResultInstOperandIndex[AliasOpNo].second; + + // Find out what operand from the asmparser that this MCInst operand + // comes from. + switch (CGA.ResultOperands[AliasOpNo].Kind) { + default: assert(0 && "unexpected InstAlias operand kind"); + case CodeGenInstAlias::ResultOperand::K_Record: { + StringRef Name = CGA.ResultOperands[AliasOpNo].getName(); + int SrcOperand = FindAsmOperand(Name, SubIdx); + if (SrcOperand == -1) + throw TGError(TheDef->getLoc(), "Instruction '" + + TheDef->getName() + "' has operand '" + OpName + + "' that doesn't appear in asm string!"); + unsigned NumOperands = (SubIdx == -1 ? OpInfo->MINumOperands : 1); + ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, + NumOperands)); + break; + } + case CodeGenInstAlias::ResultOperand::K_Imm: { + int64_t ImmVal = CGA.ResultOperands[AliasOpNo].getImm(); + ResOperands.push_back(ResOperand::getImmOp(ImmVal)); + break; + } + case CodeGenInstAlias::ResultOperand::K_Reg: { + Record *Reg = CGA.ResultOperands[AliasOpNo].getRegister(); + ResOperands.push_back(ResOperand::getRegOp(Reg)); + break; + } + } + } + } +} + +static void EmitConvertToMCInst(CodeGenTarget &Target, StringRef ClassName, + std::vector<MatchableInfo*> &Infos, raw_ostream &OS) { // Write the convert function to a separate stream, so we can drop it after // the enum. @@ -1084,8 +1461,8 @@ static void EmitConvertToMCInst(CodeGenTarget &Target, std::set<std::string> GeneratedFns; // Start the unified conversion function. - - CvtOS << "static void ConvertToMCInst(ConversionKind Kind, MCInst &Inst, " + CvtOS << "bool " << Target.getName() << ClassName << "::\n"; + CvtOS << "ConvertToMCInst(unsigned Kind, MCInst &Inst, " << "unsigned Opcode,\n" << " const SmallVectorImpl<MCParsedAsmOperand*" << "> &Operands) {\n"; @@ -1095,92 +1472,94 @@ static void EmitConvertToMCInst(CodeGenTarget &Target, // Start the enum, which we will generate inline. - OS << "// Unified function for converting operants to MCInst instances.\n\n"; + OS << "// Unified function for converting operands to MCInst instances.\n\n"; OS << "enum ConversionKind {\n"; - + // TargetOperandClass - This is the target's operand class, like X86Operand. std::string TargetOperandClass = Target.getName() + "Operand"; - - for (std::vector<InstructionInfo*>::const_iterator it = Infos.begin(), + + for (std::vector<MatchableInfo*>::const_iterator it = Infos.begin(), ie = Infos.end(); it != ie; ++it) { - InstructionInfo &II = **it; - - // Order the (class) operands by the order to convert them into an MCInst. - SmallVector<std::pair<unsigned, unsigned>, 4> MIOperandList; - for (unsigned i = 0, e = II.Operands.size(); i != e; ++i) { - InstructionInfo::Operand &Op = II.Operands[i]; - if (Op.OperandInfo) - MIOperandList.push_back(std::make_pair(Op.OperandInfo->MIOperandNo, i)); - } + MatchableInfo &II = **it; - // 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())); - } - } + // Check if we have a custom match function. + StringRef AsmMatchConverter = II.getResultInst()->TheDef->getValueAsString( + "AsmMatchConverter"); + if (!AsmMatchConverter.empty()) { + std::string Signature = "ConvertCustom_" + AsmMatchConverter.str(); + II.ConversionFnKind = Signature; - std::sort(MIOperandList.begin(), MIOperandList.end()); + // Check if we have already generated this signature. + if (!GeneratedFns.insert(Signature).second) + continue; - // Compute the total number of operands. - unsigned NumMIOperands = 0; - for (unsigned i = 0, e = II.Instr->OperandList.size(); i != e; ++i) { - const CodeGenInstruction::OperandInfo &OI = II.Instr->OperandList[i]; - NumMIOperands = std::max(NumMIOperands, - OI.MIOperandNo + OI.MINumOperands); + // If not, emit it now. Add to the enum list. + OS << " " << Signature << ",\n"; + + CvtOS << " case " << Signature << ":\n"; + CvtOS << " return " << AsmMatchConverter + << "(Inst, Opcode, Operands);\n"; + continue; } // Build the conversion function signature. std::string Signature = "Convert"; - unsigned CurIndex = 0; - for (unsigned i = 0, e = MIOperandList.size(); i != e; ++i) { - InstructionInfo::Operand &Op = II.Operands[MIOperandList[i].second]; - assert(CurIndex <= Op.OperandInfo->MIOperandNo && - "Duplicate match for instruction operand!"); - - // 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) { - std::pair<unsigned, unsigned> *Tie = GetTiedOperandAtIndex(TiedOperands, - CurIndex); - if (!Tie) - Signature += "__Imp"; + std::string CaseBody; + raw_string_ostream CaseOS(CaseBody); + + // Compute the convert enum and the case body. + for (unsigned i = 0, e = II.ResOperands.size(); i != e; ++i) { + const MatchableInfo::ResOperand &OpInfo = II.ResOperands[i]; + + // Generate code to populate each result operand. + switch (OpInfo.Kind) { + case MatchableInfo::ResOperand::RenderAsmOperand: { + // This comes from something we parsed. + MatchableInfo::AsmOperand &Op = II.AsmOperands[OpInfo.AsmOperandNum]; + + // Registers are always converted the same, don't duplicate the + // conversion function based on them. + Signature += "__"; + if (Op.Class->isRegisterClass()) + Signature += "Reg"; else - Signature += "__Tie" + utostr(Tie->second); - } - - Signature += "__"; - - // Registers are always converted the same, don't duplicate the conversion - // function based on them. - // - // FIXME: We could generalize this based on the render method, if it - // mattered. - if (Op.Class->isRegisterClass()) - Signature += "Reg"; - else - Signature += Op.Class->ClassName; - Signature += utostr(Op.OperandInfo->MINumOperands); - Signature += "_" + utostr(MIOperandList[i].second); + Signature += Op.Class->ClassName; + Signature += utostr(OpInfo.MINumOperands); + Signature += "_" + itostr(OpInfo.AsmOperandNum); - CurIndex += Op.OperandInfo->MINumOperands; - } + CaseOS << " ((" << TargetOperandClass << "*)Operands[" + << (OpInfo.AsmOperandNum+1) << "])->" << Op.Class->RenderMethod + << "(Inst, " << OpInfo.MINumOperands << ");\n"; + break; + } - // Add any trailing implicit operands. - for (; CurIndex != NumMIOperands; ++CurIndex) { - std::pair<unsigned, unsigned> *Tie = GetTiedOperandAtIndex(TiedOperands, - CurIndex); - if (!Tie) - Signature += "__Imp"; - else - Signature += "__Tie" + utostr(Tie->second); + case MatchableInfo::ResOperand::TiedOperand: { + // If this operand is tied to a previous one, just copy the MCInst + // operand from the earlier one.We can only tie single MCOperand values. + //assert(OpInfo.MINumOperands == 1 && "Not a singular MCOperand"); + unsigned TiedOp = OpInfo.TiedOperandNum; + assert(i > TiedOp && "Tied operand preceeds its target!"); + CaseOS << " Inst.addOperand(Inst.getOperand(" << TiedOp << "));\n"; + Signature += "__Tie" + utostr(TiedOp); + break; + } + case MatchableInfo::ResOperand::ImmOperand: { + int64_t Val = OpInfo.ImmVal; + CaseOS << " Inst.addOperand(MCOperand::CreateImm(" << Val << "));\n"; + Signature += "__imm" + itostr(Val); + break; + } + case MatchableInfo::ResOperand::RegOperand: { + if (OpInfo.Register == 0) { + CaseOS << " Inst.addOperand(MCOperand::CreateReg(0));\n"; + Signature += "__reg0"; + } else { + std::string N = getQualifiedName(OpInfo.Register); + CaseOS << " Inst.addOperand(MCOperand::CreateReg(" << N << "));\n"; + Signature += "__reg" + OpInfo.Register->getName(); + } + } + } } II.ConversionFnKind = Signature; @@ -1189,72 +1568,25 @@ static void EmitConvertToMCInst(CodeGenTarget &Target, if (!GeneratedFns.insert(Signature).second) continue; - // If not, emit it now. - - // Add to the enum list. + // If not, emit it now. Add to the enum list. OS << " " << Signature << ",\n"; - // And to the convert function. CvtOS << " case " << Signature << ":\n"; - CurIndex = 0; - for (unsigned i = 0, e = MIOperandList.size(); i != e; ++i) { - InstructionInfo::Operand &Op = II.Operands[MIOperandList[i].second]; - - // Add the implicit operands. - for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex) { - // 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 - << "])->" << Op.Class->RenderMethod - << "(Inst, " << Op.OperandInfo->MINumOperands << ");\n"; - CurIndex += Op.OperandInfo->MINumOperands; - } - - // And add trailing implicit operands. - 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 << " return;\n"; + CvtOS << CaseOS.str(); + CvtOS << " return true;\n"; } // Finish the convert function. CvtOS << " }\n"; + CvtOS << " return false;\n"; CvtOS << "}\n\n"; // Finish the enum, and drop the convert function after it. OS << " NumConversionVariants\n"; OS << "};\n\n"; - + OS << CvtOS.str(); } @@ -1268,7 +1600,7 @@ static void EmitMatchClassEnumeration(CodeGenTarget &Target, << "/// instruction matching.\n"; OS << "enum MatchClassKind {\n"; OS << " InvalidMatchClass = 0,\n"; - for (std::vector<ClassInfo*>::iterator it = Infos.begin(), + for (std::vector<ClassInfo*>::iterator it = Infos.begin(), ie = Infos.end(); it != ie; ++it) { ClassInfo &CI = **it; OS << " " << CI.Name << ", // "; @@ -1289,64 +1621,50 @@ static void EmitMatchClassEnumeration(CodeGenTarget &Target, OS << "}\n\n"; } -/// EmitClassifyOperand - Emit the function to classify an operand. -static void EmitClassifyOperand(CodeGenTarget &Target, - AsmMatcherInfo &Info, - raw_ostream &OS) { - OS << "static MatchClassKind ClassifyOperand(MCParsedAsmOperand *GOp) {\n" - << " " << Target.getName() << "Operand &Operand = *(" - << Target.getName() << "Operand*)GOp;\n"; +/// EmitValidateOperandClass - Emit the function to validate an operand class. +static void EmitValidateOperandClass(AsmMatcherInfo &Info, + raw_ostream &OS) { + OS << "static bool ValidateOperandClass(MCParsedAsmOperand *GOp, " + << "MatchClassKind Kind) {\n"; + OS << " " << Info.Target.getName() << "Operand &Operand = *(" + << Info.Target.getName() << "Operand*)GOp;\n"; - // Classify tokens. + // Check for Token operands first. OS << " if (Operand.isToken())\n"; - OS << " return MatchTokenString(Operand.getToken());\n\n"; + OS << " return MatchTokenString(Operand.getToken()) == Kind;\n\n"; - // Classify registers. - // - // FIXME: Don't hardcode isReg, getReg. + // Check for register operands, including sub-classes. OS << " if (Operand.isReg()) {\n"; + OS << " MatchClassKind OpKind;\n"; OS << " switch (Operand.getReg()) {\n"; - OS << " default: return InvalidMatchClass;\n"; - for (std::map<Record*, ClassInfo*>::iterator + OS << " default: OpKind = InvalidMatchClass; break;\n"; + for (std::map<Record*, ClassInfo*>::iterator it = Info.RegisterClasses.begin(), ie = Info.RegisterClasses.end(); it != ie; ++it) - OS << " case " << Target.getName() << "::" - << it->first->getName() << ": return " << it->second->Name << ";\n"; + OS << " case " << Info.Target.getName() << "::" + << it->first->getName() << ": OpKind = " << it->second->Name + << "; break;\n"; OS << " }\n"; + OS << " return IsSubclass(OpKind, Kind);\n"; OS << " }\n\n"; - // Classify user defined operands. - for (std::vector<ClassInfo*>::iterator it = Info.Classes.begin(), + // Check the user classes. We don't care what order since we're only + // actually matching against one of them. + for (std::vector<ClassInfo*>::iterator it = Info.Classes.begin(), ie = Info.Classes.end(); it != ie; ++it) { ClassInfo &CI = **it; if (!CI.isUserClass()) continue; - OS << " // '" << CI.ClassName << "' class"; - if (!CI.SuperClasses.empty()) { - OS << ", subclass of "; - for (unsigned i = 0, e = CI.SuperClasses.size(); i != e; ++i) { - if (i) OS << ", "; - OS << "'" << CI.SuperClasses[i]->ClassName << "'"; - assert(CI < *CI.SuperClasses[i] && "Invalid class relation!"); - } - } - OS << "\n"; - - OS << " if (Operand." << CI.PredicateMethod << "()) {\n"; - - // Validate subclass relationships. - if (!CI.SuperClasses.empty()) { - for (unsigned i = 0, e = CI.SuperClasses.size(); i != e; ++i) - OS << " assert(Operand." << CI.SuperClasses[i]->PredicateMethod - << "() && \"Invalid class relationship!\");\n"; - } - - OS << " return " << CI.Name << ";\n"; + OS << " // '" << CI.ClassName << "' class\n"; + OS << " if (Kind == " << CI.Name + << " && Operand." << CI.PredicateMethod << "()) {\n"; + OS << " return true;\n"; OS << " }\n\n"; } - OS << " return InvalidMatchClass;\n"; + + OS << " return false;\n"; OS << "}\n\n"; } @@ -1362,13 +1680,13 @@ static void EmitIsSubclass(CodeGenTarget &Target, OS << " switch (A) {\n"; OS << " default:\n"; OS << " return false;\n"; - for (std::vector<ClassInfo*>::iterator it = Infos.begin(), + for (std::vector<ClassInfo*>::iterator it = Infos.begin(), ie = Infos.end(); it != ie; ++it) { ClassInfo &A = **it; if (A.Kind != ClassInfo::Token) { std::vector<StringRef> SuperClasses; - for (std::vector<ClassInfo*>::iterator it = Infos.begin(), + for (std::vector<ClassInfo*>::iterator it = Infos.begin(), ie = Infos.end(); it != ie; ++it) { ClassInfo &B = **it; @@ -1397,153 +1715,25 @@ static void EmitIsSubclass(CodeGenTarget &Target, OS << "}\n\n"; } -typedef std::pair<std::string, std::string> StringPair; - -/// FindFirstNonCommonLetter - Find the first character in the keys of the -/// string pairs that is not shared across the whole set of strings. All -/// strings are assumed to have the same length. -static unsigned -FindFirstNonCommonLetter(const std::vector<const StringPair*> &Matches) { - assert(!Matches.empty()); - for (unsigned i = 0, e = Matches[0]->first.size(); i != e; ++i) { - // Check to see if letter i is the same across the set. - char Letter = Matches[0]->first[i]; - - for (unsigned str = 0, e = Matches.size(); str != e; ++str) - if (Matches[str]->first[i] != Letter) - return i; - } - - return Matches[0]->first.size(); -} - -/// EmitStringMatcherForChar - Given a set of strings that are known to be the -/// same length and whose characters leading up to CharNo are the same, emit -/// code to verify that CharNo and later are the same. -/// -/// \return - True if control can leave the emitted code fragment. -static bool EmitStringMatcherForChar(const std::string &StrVariableName, - const std::vector<const StringPair*> &Matches, - unsigned CharNo, unsigned IndentCount, - raw_ostream &OS) { - assert(!Matches.empty() && "Must have at least one string to match!"); - std::string Indent(IndentCount*2+4, ' '); - - // If we have verified that the entire string matches, we're done: output the - // matching code. - if (CharNo == Matches[0]->first.size()) { - assert(Matches.size() == 1 && "Had duplicate keys to match on"); - - // FIXME: If Matches[0].first has embeded \n, this will be bad. - OS << Indent << Matches[0]->second << "\t // \"" << Matches[0]->first - << "\"\n"; - return false; - } - - // Bucket the matches by the character we are comparing. - std::map<char, std::vector<const StringPair*> > MatchesByLetter; - - for (unsigned i = 0, e = Matches.size(); i != e; ++i) - MatchesByLetter[Matches[i]->first[CharNo]].push_back(Matches[i]); - - - // If we have exactly one bucket to match, see how many characters are common - // across the whole set and match all of them at once. - if (MatchesByLetter.size() == 1) { - unsigned FirstNonCommonLetter = FindFirstNonCommonLetter(Matches); - unsigned NumChars = FirstNonCommonLetter-CharNo; - - // Emit code to break out if the prefix doesn't match. - if (NumChars == 1) { - // Do the comparison with if (Str[1] != 'f') - // FIXME: Need to escape general characters. - OS << Indent << "if (" << StrVariableName << "[" << CharNo << "] != '" - << Matches[0]->first[CharNo] << "')\n"; - OS << Indent << " break;\n"; - } else { - // Do the comparison with if (Str.substr(1,3) != "foo"). - // FIXME: Need to escape general strings. - OS << Indent << "if (" << StrVariableName << ".substr(" << CharNo << "," - << NumChars << ") != \""; - OS << Matches[0]->first.substr(CharNo, NumChars) << "\")\n"; - OS << Indent << " break;\n"; - } - - return EmitStringMatcherForChar(StrVariableName, Matches, - FirstNonCommonLetter, IndentCount, OS); - } - - // Otherwise, we have multiple possible things, emit a switch on the - // character. - OS << Indent << "switch (" << StrVariableName << "[" << CharNo << "]) {\n"; - OS << Indent << "default: break;\n"; - - for (std::map<char, std::vector<const StringPair*> >::iterator LI = - MatchesByLetter.begin(), E = MatchesByLetter.end(); LI != E; ++LI) { - // TODO: escape hard stuff (like \n) if we ever care about it. - OS << Indent << "case '" << LI->first << "':\t // " - << LI->second.size() << " strings to match.\n"; - if (EmitStringMatcherForChar(StrVariableName, LI->second, CharNo+1, - IndentCount+1, OS)) - OS << Indent << " break;\n"; - } - - OS << Indent << "}\n"; - return true; -} - - -/// EmitStringMatcher - Given a list of strings and code to execute when they -/// match, output a simple switch tree to classify the input string. -/// -/// If a match is found, the code in Vals[i].second is executed; control must -/// not exit this code fragment. If nothing matches, execution falls through. -/// -/// \param StrVariableName - The name of the variable to test. -static void EmitStringMatcher(const std::string &StrVariableName, - const std::vector<StringPair> &Matches, - raw_ostream &OS) { - // First level categorization: group strings by length. - std::map<unsigned, std::vector<const StringPair*> > MatchesByLength; - - for (unsigned i = 0, e = Matches.size(); i != e; ++i) - MatchesByLength[Matches[i].first.size()].push_back(&Matches[i]); - - // Output a switch statement on length and categorize the elements within each - // bin. - OS << " switch (" << StrVariableName << ".size()) {\n"; - OS << " default: break;\n"; - - for (std::map<unsigned, std::vector<const StringPair*> >::iterator LI = - MatchesByLength.begin(), E = MatchesByLength.end(); LI != E; ++LI) { - OS << " case " << LI->first << ":\t // " << LI->second.size() - << " strings to match.\n"; - if (EmitStringMatcherForChar(StrVariableName, LI->second, 0, 0, OS)) - OS << " break;\n"; - } - - OS << " }\n"; -} - - /// EmitMatchTokenString - Emit the function to match a token string to the /// appropriate match class value. static void EmitMatchTokenString(CodeGenTarget &Target, std::vector<ClassInfo*> &Infos, raw_ostream &OS) { // Construct the match list. - std::vector<StringPair> Matches; - for (std::vector<ClassInfo*>::iterator it = Infos.begin(), + std::vector<StringMatcher::StringPair> Matches; + for (std::vector<ClassInfo*>::iterator it = Infos.begin(), ie = Infos.end(); it != ie; ++it) { ClassInfo &CI = **it; if (CI.Kind == ClassInfo::Token) - Matches.push_back(StringPair(CI.ValueName, "return " + CI.Name + ";")); + Matches.push_back(StringMatcher::StringPair(CI.ValueName, + "return " + CI.Name + ";")); } OS << "static MatchClassKind MatchTokenString(StringRef Name) {\n"; - EmitStringMatcher("Name", Matches, OS); + StringMatcher("Name", Matches, OS).Emit(); OS << " return InvalidMatchClass;\n"; OS << "}\n\n"; @@ -1554,28 +1744,28 @@ static void EmitMatchTokenString(CodeGenTarget &Target, static void EmitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser, raw_ostream &OS) { // Construct the match list. - std::vector<StringPair> Matches; + std::vector<StringMatcher::StringPair> Matches; for (unsigned i = 0, e = Target.getRegisters().size(); i != e; ++i) { const CodeGenRegister &Reg = Target.getRegisters()[i]; if (Reg.TheDef->getValueAsString("AsmName").empty()) continue; - Matches.push_back(StringPair(Reg.TheDef->getValueAsString("AsmName"), - "return " + utostr(i + 1) + ";")); + Matches.push_back(StringMatcher::StringPair( + Reg.TheDef->getValueAsString("AsmName"), + "return " + utostr(i + 1) + ";")); } - + OS << "static unsigned MatchRegisterName(StringRef Name) {\n"; - EmitStringMatcher("Name", Matches, OS); - + StringMatcher("Name", Matches, OS).Emit(); + OS << " return 0;\n"; OS << "}\n\n"; } /// EmitSubtargetFeatureFlagEnumeration - Emit the subtarget feature flag /// definitions. -static void EmitSubtargetFeatureFlagEnumeration(CodeGenTarget &Target, - AsmMatcherInfo &Info, +static void EmitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info, raw_ostream &OS) { OS << "// Flags for subtarget features that participate in " << "instruction matching.\n"; @@ -1584,7 +1774,7 @@ static void EmitSubtargetFeatureFlagEnumeration(CodeGenTarget &Target, it = Info.SubtargetFeatures.begin(), ie = Info.SubtargetFeatures.end(); it != ie; ++it) { SubtargetFeatureInfo &SFI = *it->second; - OS << " " << SFI.EnumName << " = (1 << " << SFI.Index << "),\n"; + OS << " " << SFI.getEnumName() << " = (1 << " << SFI.Index << "),\n"; } OS << " Feature_None = 0\n"; OS << "};\n\n"; @@ -1592,14 +1782,13 @@ static void EmitSubtargetFeatureFlagEnumeration(CodeGenTarget &Target, /// EmitComputeAvailableFeatures - Emit the function to compute the list of /// available features given a subtarget. -static void EmitComputeAvailableFeatures(CodeGenTarget &Target, - AsmMatcherInfo &Info, +static void EmitComputeAvailableFeatures(AsmMatcherInfo &Info, raw_ostream &OS) { std::string ClassName = Info.AsmParser->getValueAsString("AsmParserClassName"); - OS << "unsigned " << Target.getName() << ClassName << "::\n" - << "ComputeAvailableFeatures(const " << Target.getName() + OS << "unsigned " << Info.Target.getName() << ClassName << "::\n" + << "ComputeAvailableFeatures(const " << Info.Target.getName() << "Subtarget *Subtarget) const {\n"; OS << " unsigned Features = 0;\n"; for (std::map<Record*, SubtargetFeatureInfo*>::const_iterator @@ -1608,73 +1797,375 @@ static void EmitComputeAvailableFeatures(CodeGenTarget &Target, SubtargetFeatureInfo &SFI = *it->second; OS << " if (" << SFI.TheDef->getValueAsString("CondString") << ")\n"; - OS << " Features |= " << SFI.EnumName << ";\n"; + OS << " Features |= " << SFI.getEnumName() << ";\n"; } OS << " return Features;\n"; OS << "}\n\n"; } +static std::string GetAliasRequiredFeatures(Record *R, + const AsmMatcherInfo &Info) { + std::vector<Record*> ReqFeatures = R->getValueAsListOfDefs("Predicates"); + std::string Result; + unsigned NumFeatures = 0; + for (unsigned i = 0, e = ReqFeatures.size(); i != e; ++i) { + SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]); + + if (F == 0) + throw TGError(R->getLoc(), "Predicate '" + ReqFeatures[i]->getName() + + "' is not marked as an AssemblerPredicate!"); + + if (NumFeatures) + Result += '|'; + + Result += F->getEnumName(); + ++NumFeatures; + } + + if (NumFeatures > 1) + Result = '(' + Result + ')'; + return Result; +} + +/// EmitMnemonicAliases - If the target has any MnemonicAlias<> definitions, +/// emit a function for them and return true, otherwise return false. +static bool EmitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info) { + // Ignore aliases when match-prefix is set. + if (!MatchPrefix.empty()) + return false; + + std::vector<Record*> Aliases = + Info.getRecords().getAllDerivedDefinitions("MnemonicAlias"); + if (Aliases.empty()) return false; + + OS << "static void ApplyMnemonicAliases(StringRef &Mnemonic, " + "unsigned Features) {\n"; + + // Keep track of all the aliases from a mnemonic. Use an std::map so that the + // iteration order of the map is stable. + std::map<std::string, std::vector<Record*> > AliasesFromMnemonic; + + for (unsigned i = 0, e = Aliases.size(); i != e; ++i) { + Record *R = Aliases[i]; + AliasesFromMnemonic[R->getValueAsString("FromMnemonic")].push_back(R); + } + + // Process each alias a "from" mnemonic at a time, building the code executed + // by the string remapper. + std::vector<StringMatcher::StringPair> Cases; + for (std::map<std::string, std::vector<Record*> >::iterator + I = AliasesFromMnemonic.begin(), E = AliasesFromMnemonic.end(); + I != E; ++I) { + const std::vector<Record*> &ToVec = I->second; + + // Loop through each alias and emit code that handles each case. If there + // are two instructions without predicates, emit an error. If there is one, + // emit it last. + std::string MatchCode; + int AliasWithNoPredicate = -1; + + for (unsigned i = 0, e = ToVec.size(); i != e; ++i) { + Record *R = ToVec[i]; + std::string FeatureMask = GetAliasRequiredFeatures(R, Info); + + // If this unconditionally matches, remember it for later and diagnose + // duplicates. + if (FeatureMask.empty()) { + if (AliasWithNoPredicate != -1) { + // We can't have two aliases from the same mnemonic with no predicate. + PrintError(ToVec[AliasWithNoPredicate]->getLoc(), + "two MnemonicAliases with the same 'from' mnemonic!"); + throw TGError(R->getLoc(), "this is the other MnemonicAlias."); + } + + AliasWithNoPredicate = i; + continue; + } + if (R->getValueAsString("ToMnemonic") == I->first) + throw TGError(R->getLoc(), "MnemonicAlias to the same string"); + + if (!MatchCode.empty()) + MatchCode += "else "; + MatchCode += "if ((Features & " + FeatureMask + ") == "+FeatureMask+")\n"; + MatchCode += " Mnemonic = \"" +R->getValueAsString("ToMnemonic")+"\";\n"; + } + + if (AliasWithNoPredicate != -1) { + Record *R = ToVec[AliasWithNoPredicate]; + if (!MatchCode.empty()) + MatchCode += "else\n "; + MatchCode += "Mnemonic = \"" + R->getValueAsString("ToMnemonic")+"\";\n"; + } + + MatchCode += "return;"; + + Cases.push_back(std::make_pair(I->first, MatchCode)); + } + + StringMatcher("Mnemonic", Cases, OS).Emit(); + OS << "}\n\n"; + + return true; +} + +static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, + const AsmMatcherInfo &Info, StringRef ClassName) { + // Emit the static custom operand parsing table; + OS << "namespace {\n"; + OS << " struct OperandMatchEntry {\n"; + OS << " const char *Mnemonic;\n"; + OS << " unsigned OperandMask;\n"; + OS << " MatchClassKind Class;\n"; + OS << " unsigned RequiredFeatures;\n"; + OS << " };\n\n"; + + OS << " // Predicate for searching for an opcode.\n"; + OS << " struct LessOpcodeOperand {\n"; + OS << " bool operator()(const OperandMatchEntry &LHS, StringRef RHS) {\n"; + OS << " return StringRef(LHS.Mnemonic) < RHS;\n"; + OS << " }\n"; + OS << " bool operator()(StringRef LHS, const OperandMatchEntry &RHS) {\n"; + OS << " return LHS < StringRef(RHS.Mnemonic);\n"; + OS << " }\n"; + OS << " bool operator()(const OperandMatchEntry &LHS,"; + OS << " const OperandMatchEntry &RHS) {\n"; + OS << " return StringRef(LHS.Mnemonic) < StringRef(RHS.Mnemonic);\n"; + OS << " }\n"; + OS << " };\n"; + + OS << "} // end anonymous namespace.\n\n"; + + OS << "static const OperandMatchEntry OperandMatchTable[" + << Info.OperandMatchInfo.size() << "] = {\n"; + + OS << " /* Mnemonic, Operand List Mask, Operand Class, Features */\n"; + for (std::vector<OperandMatchEntry>::const_iterator it = + Info.OperandMatchInfo.begin(), ie = Info.OperandMatchInfo.end(); + it != ie; ++it) { + const OperandMatchEntry &OMI = *it; + const MatchableInfo &II = *OMI.MI; + + OS << " { \"" << II.Mnemonic << "\"" + << ", " << OMI.OperandMask; + + OS << " /* "; + bool printComma = false; + for (int i = 0, e = 31; i !=e; ++i) + if (OMI.OperandMask & (1 << i)) { + if (printComma) + OS << ", "; + OS << i; + printComma = true; + } + OS << " */"; + + OS << ", " << OMI.CI->Name + << ", "; + + // Write the required features mask. + if (!II.RequiredFeatures.empty()) { + for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) { + if (i) OS << "|"; + OS << II.RequiredFeatures[i]->getEnumName(); + } + } else + OS << "0"; + OS << " },\n"; + } + OS << "};\n\n"; + + // Emit the operand class switch to call the correct custom parser for + // the found operand class. + OS << Target.getName() << ClassName << "::OperandMatchResultTy " + << Target.getName() << ClassName << "::\n" + << "TryCustomParseOperand(SmallVectorImpl<MCParsedAsmOperand*>" + << " &Operands,\n unsigned MCK) {\n\n" + << " switch(MCK) {\n"; + + for (std::vector<ClassInfo*>::const_iterator it = Info.Classes.begin(), + ie = Info.Classes.end(); it != ie; ++it) { + ClassInfo *CI = *it; + if (CI->ParserMethod.empty()) + continue; + OS << " case " << CI->Name << ":\n" + << " return " << CI->ParserMethod << "(Operands);\n"; + } + + OS << " default:\n"; + OS << " return MatchOperand_NoMatch;\n"; + OS << " }\n"; + OS << " return MatchOperand_NoMatch;\n"; + OS << "}\n\n"; + + // Emit the static custom operand parser. This code is very similar with + // the other matcher. Also use MatchResultTy here just in case we go for + // a better error handling. + OS << Target.getName() << ClassName << "::OperandMatchResultTy " + << Target.getName() << ClassName << "::\n" + << "MatchOperandParserImpl(SmallVectorImpl<MCParsedAsmOperand*>" + << " &Operands,\n StringRef Mnemonic) {\n"; + + // Emit code to get the available features. + OS << " // Get the current feature set.\n"; + OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n"; + + OS << " // Get the next operand index.\n"; + OS << " unsigned NextOpNum = Operands.size()-1;\n"; + + // Emit code to search the table. + OS << " // Search the table.\n"; + OS << " std::pair<const OperandMatchEntry*, const OperandMatchEntry*>"; + OS << " MnemonicRange =\n"; + OS << " std::equal_range(OperandMatchTable, OperandMatchTable+" + << Info.OperandMatchInfo.size() << ", Mnemonic,\n" + << " LessOpcodeOperand());\n\n"; + + OS << " if (MnemonicRange.first == MnemonicRange.second)\n"; + OS << " return MatchOperand_NoMatch;\n\n"; + + OS << " for (const OperandMatchEntry *it = MnemonicRange.first,\n" + << " *ie = MnemonicRange.second; it != ie; ++it) {\n"; + + OS << " // equal_range guarantees that instruction mnemonic matches.\n"; + OS << " assert(Mnemonic == it->Mnemonic);\n\n"; + + // Emit check that the required features are available. + OS << " // check if the available features match\n"; + OS << " if ((AvailableFeatures & it->RequiredFeatures) " + << "!= it->RequiredFeatures) {\n"; + OS << " continue;\n"; + OS << " }\n\n"; + + // Emit check to ensure the operand number matches. + OS << " // check if the operand in question has a custom parser.\n"; + OS << " if (!(it->OperandMask & (1 << NextOpNum)))\n"; + OS << " continue;\n\n"; + + // Emit call to the custom parser method + OS << " // call custom parse method to handle the operand\n"; + OS << " OperandMatchResultTy Result = "; + OS << "TryCustomParseOperand(Operands, it->Class);\n"; + OS << " if (Result != MatchOperand_NoMatch)\n"; + OS << " return Result;\n"; + OS << " }\n\n"; + + OS << " // Okay, we had no match.\n"; + OS << " return MatchOperand_NoMatch;\n"; + OS << "}\n\n"; +} + void AsmMatcherEmitter::run(raw_ostream &OS) { - CodeGenTarget Target; + CodeGenTarget Target(Records); Record *AsmParser = Target.getAsmParser(); std::string ClassName = AsmParser->getValueAsString("AsmParserClassName"); // Compute the information on the instructions to match. - AsmMatcherInfo Info(AsmParser); - Info.BuildInfo(Target); + AsmMatcherInfo Info(AsmParser, Target, Records); + Info.BuildInfo(); // Sort the instruction table using the partial order on classes. We use // stable_sort to ensure that ambiguous instructions are still // deterministically ordered. - std::stable_sort(Info.Instructions.begin(), Info.Instructions.end(), - less_ptr<InstructionInfo>()); - + std::stable_sort(Info.Matchables.begin(), Info.Matchables.end(), + less_ptr<MatchableInfo>()); + DEBUG_WITH_TYPE("instruction_info", { - for (std::vector<InstructionInfo*>::iterator - it = Info.Instructions.begin(), ie = Info.Instructions.end(); + for (std::vector<MatchableInfo*>::iterator + it = Info.Matchables.begin(), ie = Info.Matchables.end(); it != ie; ++it) (*it)->dump(); }); - // Check for ambiguous instructions. - unsigned NumAmbiguous = 0; - for (unsigned i = 0, e = Info.Instructions.size(); i != e; ++i) { - for (unsigned j = i + 1; j != e; ++j) { - InstructionInfo &A = *Info.Instructions[i]; - InstructionInfo &B = *Info.Instructions[j]; - - if (A.CouldMatchAmiguouslyWith(B)) { - DEBUG_WITH_TYPE("ambiguous_instrs", { - errs() << "warning: ambiguous instruction match:\n"; - A.dump(); - errs() << "\nis incomparable with:\n"; - B.dump(); - errs() << "\n\n"; - }); - ++NumAmbiguous; + // Check for ambiguous matchables. + DEBUG_WITH_TYPE("ambiguous_instrs", { + unsigned NumAmbiguous = 0; + for (unsigned i = 0, e = Info.Matchables.size(); i != e; ++i) { + for (unsigned j = i + 1; j != e; ++j) { + MatchableInfo &A = *Info.Matchables[i]; + MatchableInfo &B = *Info.Matchables[j]; + + if (A.CouldMatchAmbiguouslyWith(B)) { + errs() << "warning: ambiguous matchables:\n"; + A.dump(); + errs() << "\nis incomparable with:\n"; + B.dump(); + errs() << "\n\n"; + ++NumAmbiguous; + } } } - } - if (NumAmbiguous) - DEBUG_WITH_TYPE("ambiguous_instrs", { - errs() << "warning: " << NumAmbiguous - << " ambiguous instructions!\n"; - }); + if (NumAmbiguous) + errs() << "warning: " << NumAmbiguous + << " ambiguous matchables!\n"; + }); + + // Compute the information on the custom operand parsing. + Info.BuildOperandMatchInfo(); // Write the output. EmitSourceFileHeader("Assembly Matcher Source Fragment", OS); + // Information for the class declaration. + OS << "\n#ifdef GET_ASSEMBLER_HEADER\n"; + OS << "#undef GET_ASSEMBLER_HEADER\n"; + OS << " // This should be included into the middle of the declaration of\n"; + OS << " // your subclasses implementation of TargetAsmParser.\n"; + OS << " unsigned ComputeAvailableFeatures(const " << + Target.getName() << "Subtarget *Subtarget) const;\n"; + OS << " enum MatchResultTy {\n"; + OS << " Match_ConversionFail,\n"; + OS << " Match_InvalidOperand,\n"; + OS << " Match_MissingFeature,\n"; + OS << " Match_MnemonicFail,\n"; + OS << " Match_Success\n"; + OS << " };\n"; + OS << " bool ConvertToMCInst(unsigned Kind, MCInst &Inst, " + << "unsigned Opcode,\n" + << " const SmallVectorImpl<MCParsedAsmOperand*> " + << "&Operands);\n"; + OS << " bool MnemonicIsValid(StringRef Mnemonic);\n"; + OS << " MatchResultTy MatchInstructionImpl(\n"; + OS << " const SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n"; + OS << " MCInst &Inst, unsigned &ErrorInfo);\n"; + + if (Info.OperandMatchInfo.size()) { + OS << "\n enum OperandMatchResultTy {\n"; + OS << " MatchOperand_Success, // operand matched successfully\n"; + OS << " MatchOperand_NoMatch, // operand did not match\n"; + OS << " MatchOperand_ParseFail // operand matched but had errors\n"; + OS << " };\n"; + OS << " OperandMatchResultTy MatchOperandParserImpl(\n"; + OS << " SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n"; + OS << " StringRef Mnemonic);\n"; + + OS << " OperandMatchResultTy TryCustomParseOperand(\n"; + OS << " SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n"; + OS << " unsigned MCK);\n\n"; + } + + OS << "#endif // GET_ASSEMBLER_HEADER_INFO\n\n"; + + OS << "\n#ifdef GET_REGISTER_MATCHER\n"; + OS << "#undef GET_REGISTER_MATCHER\n\n"; + // Emit the subtarget feature enumeration. - EmitSubtargetFeatureFlagEnumeration(Target, Info, OS); + EmitSubtargetFeatureFlagEnumeration(Info, OS); // Emit the function to match a register name to number. EmitMatchRegisterName(Target, AsmParser, OS); - - OS << "#ifndef REGISTERS_ONLY\n\n"; + + OS << "#endif // GET_REGISTER_MATCHER\n\n"; + + + OS << "\n#ifdef GET_MATCHER_IMPLEMENTATION\n"; + OS << "#undef GET_MATCHER_IMPLEMENTATION\n\n"; + + // Generate the function that remaps for mnemonic aliases. + bool HasMnemonicAliases = EmitMnemonicAliases(OS, Info); // Generate the unified function to convert operands into an MCInst. - EmitConvertToMCInst(Target, Info.Instructions, OS); + EmitConvertToMCInst(Target, ClassName, Info.Matchables, OS); // Emit the enumeration for classes which participate in matching. EmitMatchClassEnumeration(Target, Info.Classes, OS); @@ -1682,27 +2173,21 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // Emit the routine to match token strings to their match class. EmitMatchTokenString(Target, Info.Classes, OS); - // Emit the routine to classify an operand. - EmitClassifyOperand(Target, Info, OS); - // Emit the subclass predicate routine. EmitIsSubclass(Target, Info.Classes, OS); + // Emit the routine to validate an operand against a match class. + EmitValidateOperandClass(Info, OS); + // Emit the available features compute function. - EmitComputeAvailableFeatures(Target, Info, OS); + EmitComputeAvailableFeatures(Info, OS); - // Finally, build the match function. size_t MaxNumOperands = 0; - for (std::vector<InstructionInfo*>::const_iterator it = - Info.Instructions.begin(), ie = Info.Instructions.end(); + for (std::vector<MatchableInfo*>::const_iterator it = + Info.Matchables.begin(), ie = Info.Matchables.end(); it != ie; ++it) - MaxNumOperands = std::max(MaxNumOperands, (*it)->Operands.size()); - - OS << "bool " << Target.getName() << ClassName << "::\n" - << "MatchInstructionImpl(const SmallVectorImpl<MCParsedAsmOperand*>" - << " &Operands,\n"; - OS << " MCInst &Inst) {\n"; + MaxNumOperands = std::max(MaxNumOperands, (*it)->AsmOperands.size()); // Emit the static match table; unused classes get initalized to 0 which is // guaranteed to be InvalidMatchClass. @@ -1714,23 +2199,44 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // order the match kinds appropriately (putting mnemonics last), then we // should only end up using a few bits for each class, especially the ones // following the mnemonic. - OS << " static const struct MatchEntry {\n"; + OS << "namespace {\n"; + OS << " struct MatchEntry {\n"; OS << " unsigned Opcode;\n"; + OS << " const char *Mnemonic;\n"; OS << " ConversionKind ConvertFn;\n"; OS << " MatchClassKind Classes[" << MaxNumOperands << "];\n"; OS << " unsigned RequiredFeatures;\n"; - OS << " } MatchTable[" << Info.Instructions.size() << "] = {\n"; + OS << " };\n\n"; + + OS << " // Predicate for searching for an opcode.\n"; + OS << " struct LessOpcode {\n"; + OS << " bool operator()(const MatchEntry &LHS, StringRef RHS) {\n"; + OS << " return StringRef(LHS.Mnemonic) < RHS;\n"; + OS << " }\n"; + OS << " bool operator()(StringRef LHS, const MatchEntry &RHS) {\n"; + OS << " return LHS < StringRef(RHS.Mnemonic);\n"; + OS << " }\n"; + OS << " bool operator()(const MatchEntry &LHS, const MatchEntry &RHS) {\n"; + OS << " return StringRef(LHS.Mnemonic) < StringRef(RHS.Mnemonic);\n"; + OS << " }\n"; + OS << " };\n"; - for (std::vector<InstructionInfo*>::const_iterator it = - Info.Instructions.begin(), ie = Info.Instructions.end(); + OS << "} // end anonymous namespace.\n\n"; + + OS << "static const MatchEntry MatchTable[" + << Info.Matchables.size() << "] = {\n"; + + for (std::vector<MatchableInfo*>::const_iterator it = + Info.Matchables.begin(), ie = Info.Matchables.end(); it != ie; ++it) { - InstructionInfo &II = **it; + MatchableInfo &II = **it; - OS << " { " << Target.getName() << "::" << II.InstrName + OS << " { " << Target.getName() << "::" + << II.getResultInst()->TheDef->getName() << ", \"" << II.Mnemonic << "\"" << ", " << II.ConversionFnKind << ", { "; - for (unsigned i = 0, e = II.Operands.size(); i != e; ++i) { - InstructionInfo::Operand &Op = II.Operands[i]; - + for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) { + MatchableInfo::AsmOperand &Op = II.AsmOperands[i]; + if (i) OS << ", "; OS << Op.Class->Name; } @@ -1740,7 +2246,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { if (!II.RequiredFeatures.empty()) { for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) { if (i) OS << "|"; - OS << II.RequiredFeatures[i]->EnumName; + OS << II.RequiredFeatures[i]->getEnumName(); } } else OS << "0"; @@ -1748,52 +2254,101 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "},\n"; } - OS << " };\n\n"; + OS << "};\n\n"; + + // A method to determine if a mnemonic is in the list. + OS << "bool " << Target.getName() << ClassName << "::\n" + << "MnemonicIsValid(StringRef Mnemonic) {\n"; + OS << " // Search the table.\n"; + OS << " std::pair<const MatchEntry*, const MatchEntry*> MnemonicRange =\n"; + OS << " std::equal_range(MatchTable, MatchTable+" + << Info.Matchables.size() << ", Mnemonic, LessOpcode());\n"; + OS << " return MnemonicRange.first != MnemonicRange.second;\n"; + OS << "}\n\n"; + // Finally, build the match function. + OS << Target.getName() << ClassName << "::MatchResultTy " + << Target.getName() << ClassName << "::\n" + << "MatchInstructionImpl(const SmallVectorImpl<MCParsedAsmOperand*>" + << " &Operands,\n"; + OS << " MCInst &Inst, unsigned &ErrorInfo) {\n"; // Emit code to get the available features. OS << " // Get the current feature set.\n"; OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n"; - // Emit code to compute the class list for this operand vector. - OS << " // Eliminate obvious mismatches.\n"; - OS << " if (Operands.size() > " << MaxNumOperands << ")\n"; - OS << " return true;\n\n"; + OS << " // Get the instruction mnemonic, which is the first token.\n"; + OS << " StringRef Mnemonic = ((" << Target.getName() + << "Operand*)Operands[0])->getToken();\n\n"; - OS << " // Compute the class list for this operand vector.\n"; - OS << " MatchClassKind Classes[" << MaxNumOperands << "];\n"; - OS << " for (unsigned i = 0, e = Operands.size(); i != e; ++i) {\n"; - OS << " Classes[i] = ClassifyOperand(Operands[i]);\n\n"; + if (HasMnemonicAliases) { + OS << " // Process all MnemonicAliases to remap the mnemonic.\n"; + OS << " ApplyMnemonicAliases(Mnemonic, AvailableFeatures);\n\n"; + } - OS << " // Check for invalid operands before matching.\n"; - OS << " if (Classes[i] == InvalidMatchClass)\n"; - OS << " return true;\n"; + // Emit code to compute the class list for this operand vector. + OS << " // Eliminate obvious mismatches.\n"; + OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n"; + OS << " ErrorInfo = " << (MaxNumOperands+1) << ";\n"; + OS << " return Match_InvalidOperand;\n"; OS << " }\n\n"; - OS << " // Mark unused classes.\n"; - OS << " for (unsigned i = Operands.size(), e = " << MaxNumOperands << "; " - << "i != e; ++i)\n"; - OS << " Classes[i] = InvalidMatchClass;\n\n"; + OS << " // Some state to try to produce better error messages.\n"; + OS << " bool HadMatchOtherThanFeatures = false;\n\n"; + OS << " // Set ErrorInfo to the operand that mismatches if it is\n"; + OS << " // wrong for all instances of the instruction.\n"; + OS << " ErrorInfo = ~0U;\n"; // Emit code to search the table. OS << " // Search the table.\n"; - OS << " for (const MatchEntry *it = MatchTable, " - << "*ie = MatchTable + " << Info.Instructions.size() - << "; it != ie; ++it) {\n"; + OS << " std::pair<const MatchEntry*, const MatchEntry*> MnemonicRange =\n"; + OS << " std::equal_range(MatchTable, MatchTable+" + << Info.Matchables.size() << ", Mnemonic, LessOpcode());\n\n"; - // Emit check that the required features are available. - OS << " if ((AvailableFeatures & it->RequiredFeatures) " - << "!= it->RequiredFeatures)\n"; - OS << " continue;\n"; + OS << " // Return a more specific error code if no mnemonics match.\n"; + OS << " if (MnemonicRange.first == MnemonicRange.second)\n"; + OS << " return Match_MnemonicFail;\n\n"; + + OS << " for (const MatchEntry *it = MnemonicRange.first, " + << "*ie = MnemonicRange.second;\n"; + OS << " it != ie; ++it) {\n"; + + OS << " // equal_range guarantees that instruction mnemonic matches.\n"; + OS << " assert(Mnemonic == it->Mnemonic);\n"; // Emit check that the subclasses match. - for (unsigned i = 0; i != MaxNumOperands; ++i) { - OS << " if (!IsSubclass(Classes[" - << i << "], it->Classes[" << i << "]))\n"; - OS << " continue;\n"; - } + OS << " bool OperandsValid = true;\n"; + OS << " for (unsigned i = 0; i != " << MaxNumOperands << "; ++i) {\n"; + OS << " if (i + 1 >= Operands.size()) {\n"; + OS << " OperandsValid = (it->Classes[i] == " <<"InvalidMatchClass);\n"; + OS << " break;"; + OS << " }\n"; + OS << " if (ValidateOperandClass(Operands[i+1], it->Classes[i]))\n"; + OS << " continue;\n"; + OS << " // If this operand is broken for all of the instances of this\n"; + OS << " // mnemonic, keep track of it so we can report loc info.\n"; + OS << " if (it == MnemonicRange.first || ErrorInfo <= i+1)\n"; + OS << " ErrorInfo = i+1;\n"; + OS << " // Otherwise, just reject this instance of the mnemonic.\n"; + OS << " OperandsValid = false;\n"; + OS << " break;\n"; + OS << " }\n\n"; + + OS << " if (!OperandsValid) continue;\n"; + + // Emit check that the required features are available. + OS << " if ((AvailableFeatures & it->RequiredFeatures) " + << "!= it->RequiredFeatures) {\n"; + OS << " HadMatchOtherThanFeatures = true;\n"; + OS << " continue;\n"; + OS << " }\n"; + OS << "\n"; + OS << " // We have selected a definite instruction, convert the parsed\n" + << " // operands into the appropriate MCInst.\n"; + OS << " if (!ConvertToMCInst(it->ConvertFn, Inst,\n" + << " it->Opcode, Operands))\n"; + OS << " return Match_ConversionFail;\n"; OS << "\n"; - OS << " ConvertToMCInst(it->ConvertFn, Inst, it->Opcode, Operands);\n"; // Call the post-processing function, if used. std::string InsnCleanupFn = @@ -1801,11 +2356,16 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { if (!InsnCleanupFn.empty()) OS << " " << InsnCleanupFn << "(Inst);\n"; - OS << " return false;\n"; + OS << " return Match_Success;\n"; OS << " }\n\n"; - OS << " return true;\n"; + OS << " // Okay, we had no match. Try to return a useful error code.\n"; + OS << " if (HadMatchOtherThanFeatures) return Match_MissingFeature;\n"; + OS << " return Match_InvalidOperand;\n"; OS << "}\n\n"; - - OS << "#endif // REGISTERS_ONLY\n"; + + if (Info.OperandMatchInfo.size()) + EmitCustomOperandParsing(OS, Target, Info, ClassName); + + OS << "#endif // GET_MATCHER_IMPLEMENTATION\n\n"; } diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index 23f13c2..448ebad 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -101,22 +101,22 @@ static void EmitInstructions(std::vector<AsmWriterInst> &Insts, } void AsmWriterEmitter:: -FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands, +FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands, std::vector<unsigned> &InstIdxs, std::vector<unsigned> &InstOpsUsed) const { InstIdxs.assign(NumberedInstructions.size(), ~0U); - + // This vector parallels UniqueOperandCommands, keeping track of which // instructions each case are used for. It is a comma separated string of // enums. std::vector<std::string> InstrsForCase; InstrsForCase.resize(UniqueOperandCommands.size()); InstOpsUsed.assign(UniqueOperandCommands.size(), 0); - + for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { const AsmWriterInst *Inst = getAsmWriterInstByID(i); if (Inst == 0) continue; // PHI, INLINEASM, PROLOG_LABEL, etc. - + std::string Command; if (Inst->Operands.empty()) continue; // Instruction already done. @@ -143,13 +143,13 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands, InstOpsUsed.push_back(1); } } - + // For each entry of UniqueOperandCommands, there is a set of instructions // that uses it. If the next command of all instructions in the set are // identical, fold it into the command. for (unsigned CommandIdx = 0, e = UniqueOperandCommands.size(); CommandIdx != e; ++CommandIdx) { - + for (unsigned Op = 1; ; ++Op) { // Scan for the first instruction in the set. std::vector<unsigned>::iterator NIT = @@ -158,7 +158,7 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands, // If this instruction has no more operands, we isn't anything to merge // into this command. - const AsmWriterInst *FirstInst = + const AsmWriterInst *FirstInst = getAsmWriterInstByID(NIT-InstIdxs.begin()); if (!FirstInst || FirstInst->Operands.size() == Op) break; @@ -175,7 +175,7 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands, NIT = std::find(NIT+1, InstIdxs.end(), CommandIdx)) { // Okay, found another instruction in this command set. If the operand // matches, we're ok, otherwise bail out. - const AsmWriterInst *OtherInst = + const AsmWriterInst *OtherInst = getAsmWriterInstByID(NIT-InstIdxs.begin()); if (OtherInst && @@ -189,16 +189,16 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands, } } if (!AllSame) break; - + // Okay, everything in this command set has the same next operand. Add it // to UniqueOperandCommands and remember that it was consumed. std::string Command = " " + FirstInst->Operands[Op].getCode() + "\n"; - + UniqueOperandCommands[CommandIdx] += Command; InstOpsUsed[CommandIdx]++; } } - + // Prepend some of the instructions each case is used for onto the case val. for (unsigned i = 0, e = InstrsForCase.size(); i != e; ++i) { std::string Instrs = InstrsForCase[i]; @@ -206,9 +206,9 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands, Instrs.erase(Instrs.begin()+70, Instrs.end()); Instrs += "..."; } - + if (!Instrs.empty()) - UniqueOperandCommands[i] = " // " + Instrs + "\n" + + UniqueOperandCommands[i] = " // " + Instrs + "\n" + UniqueOperandCommands[i]; } } @@ -240,15 +240,18 @@ static void UnescapeString(std::string &Str) { /// EmitPrintInstruction - Generate the code for the "printInstruction" method /// implementation. void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { - CodeGenTarget Target; + CodeGenTarget Target(Records); Record *AsmWriter = Target.getAsmWriter(); std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); - + bool isMC = AsmWriter->getValueAsBit("isMCAsmWriter"); + const char *MachineInstrClassName = isMC ? "MCInst" : "MachineInstr"; + O << "/// printInstruction - This method is automatically generated by tablegen\n" "/// from the instruction set description.\n" "void " << Target.getName() << ClassName - << "::printInstruction(const MachineInstr *MI, raw_ostream &O) {\n"; + << "::printInstruction(const " << MachineInstrClassName + << " *MI, raw_ostream &O) {\n"; std::vector<AsmWriterInst> Instructions; @@ -257,14 +260,14 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { if (!(*I)->AsmString.empty() && (*I)->TheDef->getName() != "PHI") Instructions.push_back( - AsmWriterInst(**I, + AsmWriterInst(**I, AsmWriter->getValueAsInt("Variant"), AsmWriter->getValueAsInt("FirstOperandColumn"), AsmWriter->getValueAsInt("OperandSpacing"))); // Get the instruction numbering. NumberedInstructions = Target.getInstructionsByEnumValue(); - + // Compute the CodeGenInstruction -> AsmWriterInst mapping. Note that not // all machine instructions are necessarily being printed, so there may be // target instructions not in this map. @@ -273,11 +276,11 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { // Build an aggregate string, and build a table of offsets into it. StringToOffsetTable StringTable; - + /// OpcodeInfo - This encodes the index of the string to use for the first /// chunk of the output as well as indices used for operand printing. std::vector<unsigned> OpcodeInfo; - + unsigned MaxStringIdx = 0; for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]]; @@ -285,7 +288,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { if (AWI == 0) { // Something not handled by the asmwriter printer. Idx = ~0U; - } else if (AWI->Operands[0].OperandType != + } else if (AWI->Operands[0].OperandType != AsmWriterOperand::isLiteralTextOperand || AWI->Operands[0].Str.empty()) { // Something handled by the asmwriter printer, but with no leading string. @@ -295,51 +298,51 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { UnescapeString(Str); Idx = StringTable.GetOrAddStringOffset(Str); MaxStringIdx = std::max(MaxStringIdx, Idx); - + // Nuke the string from the operand list. It is now handled! AWI->Operands.erase(AWI->Operands.begin()); } - + // Bias offset by one since we want 0 as a sentinel. OpcodeInfo.push_back(Idx+1); } - + // Figure out how many bits we used for the string index. unsigned AsmStrBits = Log2_32_Ceil(MaxStringIdx+2); - + // To reduce code size, we compactify common instructions into a few bits // in the opcode-indexed table. unsigned BitsLeft = 32-AsmStrBits; std::vector<std::vector<std::string> > TableDrivenOperandPrinters; - + while (1) { std::vector<std::string> UniqueOperandCommands; std::vector<unsigned> InstIdxs; std::vector<unsigned> NumInstOpsHandled; FindUniqueOperandCommands(UniqueOperandCommands, InstIdxs, NumInstOpsHandled); - + // If we ran out of operands to print, we're done. if (UniqueOperandCommands.empty()) break; - + // Compute the number of bits we need to represent these cases, this is // ceil(log2(numentries)). unsigned NumBits = Log2_32_Ceil(UniqueOperandCommands.size()); - + // If we don't have enough bits for this operand, don't include it. if (NumBits > BitsLeft) { DEBUG(errs() << "Not enough bits to densely encode " << NumBits << " more bits\n"); break; } - + // Otherwise, we can include this in the initial lookup table. Add it in. BitsLeft -= NumBits; for (unsigned i = 0, e = InstIdxs.size(); i != e; ++i) if (InstIdxs[i] != ~0U) OpcodeInfo[i] |= InstIdxs[i] << (BitsLeft+AsmStrBits); - + // Remove the info about this operand. for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { if (AsmWriterInst *Inst = getAsmWriterInstByID(i)) @@ -351,13 +354,13 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { Inst->Operands.begin()+NumOps); } } - + // Remember the handlers for this set of operands. TableDrivenOperandPrinters.push_back(UniqueOperandCommands); } - - - + + + O<<" static const unsigned OpInfo[] = {\n"; for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { O << " " << OpcodeInfo[i] << "U,\t// " @@ -366,7 +369,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { // Add a dummy entry so the array init doesn't end with a comma. O << " 0U\n"; O << " };\n\n"; - + // Emit the string itself. O << " const char *AsmStrs = \n"; StringTable.EmitString(O); @@ -388,13 +391,13 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { // ceil(log2(numentries)). unsigned NumBits = Log2_32_Ceil(Commands.size()); assert(NumBits <= BitsLeft && "consistency error"); - + // Emit code to extract this field from Bits. BitsLeft -= NumBits; - + O << "\n // Fragment " << i << " encoded into " << NumBits << " bits for " << Commands.size() << " unique commands.\n"; - + if (Commands.size() == 2) { // Emit two possibilitys with if/else. O << " if ((Bits >> " << (BitsLeft+AsmStrBits) << ") & " @@ -403,11 +406,14 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { << " } else {\n" << Commands[0] << " }\n\n"; + } else if (Commands.size() == 1) { + // Emit a single possibility. + O << Commands[0] << "\n\n"; } else { O << " switch ((Bits >> " << (BitsLeft+AsmStrBits) << ") & " << ((1 << NumBits)-1) << ") {\n" << " default: // unreachable.\n"; - + // Print out all the cases. for (unsigned i = 0, e = Commands.size(); i != e; ++i) { O << " case " << i << ":\n"; @@ -417,7 +423,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { O << " }\n\n"; } } - + // Okay, delete instructions with no operand info left. for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { // Entire instruction has been emitted? @@ -428,12 +434,12 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { } } - + // Because this is a vector, we want to emit from the end. Reverse all of the // elements in the vector. std::reverse(Instructions.begin(), Instructions.end()); - - + + // Now that we've emitted all of the operand info that fit into 32 bits, emit // information for those instructions that are left. This is a less dense // encoding, but we expect the main 32-bit table to handle the majority of @@ -453,11 +459,11 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) { - CodeGenTarget Target; + CodeGenTarget Target(Records); Record *AsmWriter = Target.getAsmWriter(); std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); const std::vector<CodeGenRegister> &Registers = Target.getRegisters(); - + StringToOffsetTable StringTable; O << "\n\n/// getRegisterName - This method is automatically generated by tblgen\n" @@ -475,33 +481,33 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) { std::string AsmName = Reg.TheDef->getValueAsString("AsmName"); if (AsmName.empty()) AsmName = Reg.getName(); - - + + if ((i % 14) == 0) O << "\n "; - + O << StringTable.GetOrAddStringOffset(AsmName) << ", "; } O << "0\n" << " };\n" << "\n"; - + O << " const char *AsmStrs =\n"; StringTable.EmitString(O); O << ";\n"; - + O << " return AsmStrs+RegAsmOffset[RegNo-1];\n" << "}\n"; } void AsmWriterEmitter::EmitGetInstructionName(raw_ostream &O) { - CodeGenTarget Target; + CodeGenTarget Target(Records); Record *AsmWriter = Target.getAsmWriter(); std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); const std::vector<const CodeGenInstruction*> &NumberedInstructions = Target.getInstructionsByEnumValue(); - + StringToOffsetTable StringTable; O << "\n\n#ifdef GET_INSTRUCTION_NAME\n" @@ -517,21 +523,21 @@ void AsmWriterEmitter::EmitGetInstructionName(raw_ostream &O) { << " 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"; } @@ -540,7 +546,7 @@ void AsmWriterEmitter::EmitGetInstructionName(raw_ostream &O) { void AsmWriterEmitter::run(raw_ostream &O) { EmitSourceFileHeader("Assembly Writer Source Fragment", O); - + EmitPrintInstruction(O); EmitGetRegisterName(O); EmitGetInstructionName(O); diff --git a/utils/TableGen/AsmWriterInst.cpp b/utils/TableGen/AsmWriterInst.cpp index b2228b0..fdf447f 100644 --- a/utils/TableGen/AsmWriterInst.cpp +++ b/utils/TableGen/AsmWriterInst.cpp @@ -53,8 +53,6 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, 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; @@ -62,54 +60,48 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, // 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 AsmString = CGI.FlattenAsmStringVariants(CGI.AsmString, Variant); std::string::size_type LastEmitted = 0; while (LastEmitted != AsmString.size()) { std::string::size_type DollarPos = - AsmString.find_first_of("${|}\\", LastEmitted); + 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; - } + for (; LastEmitted != DollarPos; ++LastEmitted) + switch (AsmString[LastEmitted]) { + case '\n': + AddLiteralString("\\n"); + break; + case '\t': + // If the asm writer is not using a columnar layout, \t is not + // magic. + if (FirstOperandColumn == -1 || OperandSpacing == -1) { + AddLiteralString("\\t"); + } else { + // We recognize a tab as an operand delimeter. + unsigned DestColumn = FirstOperandColumn + + CurColumn++ * OperandSpacing; + Operands.push_back( + AsmWriterOperand( + "O.PadToColumn(" + + utostr(DestColumn) + ");\n", + AsmWriterOperand::isLiteralStatementOperand)); + } + break; + case '"': + AddLiteralString("\\\""); + break; + case '\\': + AddLiteralString("\\\\"); + break; + default: + AddLiteralString(std::string(1, AsmString[LastEmitted])); + break; + } } else if (AsmString[DollarPos] == '\\') { - if (DollarPos+1 != AsmString.size() && - (CurVariant == Variant || CurVariant == ~0U)) { + if (DollarPos+1 != AsmString.size()) { if (AsmString[DollarPos+1] == 'n') { AddLiteralString("\\n"); } else if (AsmString[DollarPos+1] == 't') { @@ -137,29 +129,9 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, 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("$"); // "$$" -> $ - } + AddLiteralString("$"); // "$$" -> $ LastEmitted = DollarPos+2; } else { // Get the name of the variable. @@ -226,16 +198,12 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, Modifier)); } else { // Otherwise, normal operand. - unsigned OpNo = CGI.getOperandNamed(VarName); - CodeGenInstruction::OperandInfo OpInfo = CGI.OperandList[OpNo]; + unsigned OpNo = CGI.Operands.getOperandNamed(VarName); + CGIOperandList::OperandInfo OpInfo = CGI.Operands[OpNo]; - if (CurVariant == Variant || CurVariant == ~0U) { - unsigned MIOp = OpInfo.MIOperandNo; - Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName, - OpNo, - MIOp, - Modifier)); - } + unsigned MIOp = OpInfo.MIOperandNo; + Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName, + OpNo, MIOp, Modifier)); } LastEmitted = VarEnd; } diff --git a/utils/TableGen/AsmWriterInst.h b/utils/TableGen/AsmWriterInst.h index 20b8588..ec7d8eb 100644 --- a/utils/TableGen/AsmWriterInst.h +++ b/utils/TableGen/AsmWriterInst.h @@ -23,51 +23,51 @@ namespace llvm { class CodeGenInstruction; class Record; - + struct AsmWriterOperand { enum OpType { // Output this text surrounded by quotes to the asm. - isLiteralTextOperand, + 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 + /// 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) + 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) @@ -77,26 +77,26 @@ namespace llvm { 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, + + 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 diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt index 972989b..e24314c 100644 --- a/utils/TableGen/CMakeLists.txt +++ b/utils/TableGen/CMakeLists.txt @@ -1,3 +1,8 @@ +set(LLVM_REQUIRES_EH 1) +set(LLVM_REQUIRES_RTTI 1) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LLVM_TOOLS_BINARY_DIR}) + add_executable(tblgen ARMDecoderEmitter.cpp AsmMatcherEmitter.cpp @@ -7,6 +12,7 @@ add_executable(tblgen ClangASTNodesEmitter.cpp ClangAttrEmitter.cpp ClangDiagnosticsEmitter.cpp + ClangSACheckersEmitter.cpp CodeEmitterGen.cpp CodeGenDAGPatterns.cpp CodeGenInstruction.cpp @@ -19,6 +25,7 @@ add_executable(tblgen DisassemblerEmitter.cpp EDEmitter.cpp FastISelEmitter.cpp + FixedLenDecoderEmitter.cpp InstrEnumEmitter.cpp InstrInfoEmitter.cpp IntrinsicEmitter.cpp @@ -27,6 +34,7 @@ add_executable(tblgen OptParserEmitter.cpp Record.cpp RegisterInfoEmitter.cpp + StringMatcher.cpp SubtargetEmitter.cpp TGLexer.cpp TGParser.cpp @@ -37,10 +45,12 @@ add_executable(tblgen X86RecognizableInstr.cpp ) -target_link_libraries(tblgen LLVMSupport LLVMSystem) +target_link_libraries(tblgen LLVMSupport) if( MINGW ) target_link_libraries(tblgen imagehlp psapi) endif( MINGW ) if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD AND NOT BEOS ) target_link_libraries(tblgen pthread) endif() + +install(TARGETS tblgen RUNTIME DESTINATION bin) diff --git a/utils/TableGen/CallingConvEmitter.cpp b/utils/TableGen/CallingConvEmitter.cpp index 7643609..c51afd8 100644 --- a/utils/TableGen/CallingConvEmitter.cpp +++ b/utils/TableGen/CallingConvEmitter.cpp @@ -26,9 +26,9 @@ void CallingConvEmitter::run(raw_ostream &O) { // other. for (unsigned i = 0, e = CCs.size(); i != e; ++i) { O << "static bool " << CCs[i]->getName() - << "(unsigned ValNo, EVT ValVT,\n" + << "(unsigned ValNo, MVT ValVT,\n" << std::string(CCs[i]->getName().size()+13, ' ') - << "EVT LocVT, CCValAssign::LocInfo LocInfo,\n" + << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n" << std::string(CCs[i]->getName().size()+13, ' ') << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n"; } @@ -44,9 +44,9 @@ void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) { Counter = 0; O << "\n\nstatic bool " << CC->getName() - << "(unsigned ValNo, EVT ValVT,\n" + << "(unsigned ValNo, MVT ValVT,\n" << std::string(CC->getName().size()+13, ' ') - << "EVT LocVT, CCValAssign::LocInfo LocInfo,\n" + << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n" << std::string(CC->getName().size()+13, ' ') << "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n"; // Emit all of the actions, in order. @@ -163,12 +163,12 @@ void CallingConvEmitter::EmitAction(Record *Action, O << Size << ", "; else O << "\n" << IndentStr << " State.getTarget().getTargetData()" - "->getTypeAllocSize(LocVT.getTypeForEVT(State.getContext())), "; + "->getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())), "; if (Align) O << Align; else O << "\n" << IndentStr << " State.getTarget().getTargetData()" - "->getABITypeAlignment(LocVT.getTypeForEVT(State.getContext()))"; + "->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()))"; if (Action->isSubClassOf("CCAssignToStackWithShadow")) O << ", " << getQualifiedName(Action->getValueAsDef("ShadowReg")); O << ");\n" << IndentStr diff --git a/utils/TableGen/ClangASTNodesEmitter.h b/utils/TableGen/ClangASTNodesEmitter.h index abf9c9a..712333b 100644 --- a/utils/TableGen/ClangASTNodesEmitter.h +++ b/utils/TableGen/ClangASTNodesEmitter.h @@ -57,7 +57,7 @@ class ClangASTNodesEmitter : public TableGenBackend { public: explicit ClangASTNodesEmitter(RecordKeeper &R, const std::string &N, const std::string &S) - : Records(R), Root(N, SMLoc()), BaseSuffix(S) + : Records(R), Root(N, SMLoc(), R), BaseSuffix(S) {} // run - Output the .inc file contents diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp index 8d3399a..27e1e02 100644 --- a/utils/TableGen/ClangAttrEmitter.cpp +++ b/utils/TableGen/ClangAttrEmitter.cpp @@ -19,8 +19,8 @@ using namespace llvm; -static const std::vector<StringRef> getValueAsListOfStrings(Record &R, - StringRef FieldName) { +static const std::vector<StringRef> +getValueAsListOfStrings(Record &R, StringRef FieldName) { ListInit *List = R.getValueAsListInit(FieldName); assert (List && "Got a null ListInit"); @@ -44,7 +44,8 @@ std::string ReadPCHRecord(StringRef type) { return StringSwitch<std::string>(type) .EndsWith("Decl *", "cast_or_null<" + std::string(type, 0, type.size()-1) + ">(GetDecl(Record[Idx++]))") - .Case("QualType", "ReadTypeRecord(Idx++)") + .Case("QualType", "GetType(Record[Idx++])") + .Case("Expr *", "ReadSubExpr()") .Default("Record[Idx++]"); } @@ -54,6 +55,7 @@ std::string WritePCHRecord(StringRef type, StringRef name) { .EndsWith("Decl *", "AddDeclRef(" + std::string(name) + ", Record);\n") .Case("QualType", "AddTypeRef(" + std::string(name) + ", Record);\n") + .Case("Expr *", "AddStmt(" + std::string(name) + ");\n") .Default("Record.push_back(" + std::string(name) + ");\n"); } @@ -171,7 +173,8 @@ namespace { OS << "char *" << getLowerName() << ";"; } void writePCHReadDecls(raw_ostream &OS) const { - OS << " std::string " << getLowerName() << "= ReadString(Record, Idx);\n"; + OS << " std::string " << getLowerName() + << "= ReadString(Record, Idx);\n"; } void writePCHReadArgs(raw_ostream &OS) const { OS << getLowerName(); @@ -269,10 +272,10 @@ namespace { OS << " bool is" << getLowerName() << "Expr = Record[Idx++];\n"; OS << " void *" << getLowerName() << "Ptr;\n"; OS << " if (is" << getLowerName() << "Expr)\n"; - OS << " " << getLowerName() << "Ptr = ReadExpr(DeclsCursor);\n"; + OS << " " << getLowerName() << "Ptr = ReadExpr(F);\n"; OS << " else\n"; OS << " " << getLowerName() - << "Ptr = GetTypeSourceInfo(DeclsCursor, Record, Idx);\n"; + << "Ptr = GetTypeSourceInfo(F, Record, Idx);\n"; } void writePCHWrite(raw_ostream &OS) const { OS << " Record.push_back(SA->is" << getUpperName() << "Expr());\n"; @@ -461,8 +464,9 @@ void ClangAttrClassEmitter::run(raw_ostream &OS) { for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(); i != e; ++i) { Record &R = **i; + const std::string &SuperName = R.getSuperClasses().back()->getName(); - OS << "class " << R.getName() << "Attr : public Attr {\n"; + OS << "class " << R.getName() << "Attr : public " << SuperName << " {\n"; std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args"); std::vector<Argument*> Args; @@ -493,7 +497,7 @@ void ClangAttrClassEmitter::run(raw_ostream &OS) { } OS << " )\n"; - OS << " : Attr(attr::" << R.getName() << ", L)\n"; + OS << " : " << SuperName << "(attr::" << R.getName() << ", L)\n"; for (ai = Args.begin(); ai != ae; ++ai) { OS << " , "; @@ -557,31 +561,58 @@ void ClangAttrImplEmitter::run(raw_ostream &OS) { } } +static void EmitAttrList(raw_ostream &OS, StringRef Class, + const std::vector<Record*> &AttrList) { + std::vector<Record*>::const_iterator i = AttrList.begin(), e = AttrList.end(); + + if (i != e) { + // Move the end iterator back to emit the last attribute. + for(--e; i != e; ++i) + OS << Class << "(" << (*i)->getName() << ")\n"; + + OS << "LAST_" << Class << "(" << (*i)->getName() << ")\n\n"; + } +} + void ClangAttrListEmitter::run(raw_ostream &OS) { OS << "// This file is generated by TableGen. Do not edit.\n\n"; OS << "#ifndef LAST_ATTR\n"; OS << "#define LAST_ATTR(NAME) ATTR(NAME)\n"; OS << "#endif\n\n"; - - std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); - std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(); - if (i != e) { - // Move the end iterator back to emit the last attribute. - for(--e; i != e; ++i) - OS << "ATTR(" << (*i)->getName() << ")\n"; - - OS << "LAST_ATTR(" << (*i)->getName() << ")\n\n"; + OS << "#ifndef INHERITABLE_ATTR\n"; + OS << "#define INHERITABLE_ATTR(NAME) ATTR(NAME)\n"; + OS << "#endif\n\n"; + + OS << "#ifndef LAST_INHERITABLE_ATTR\n"; + OS << "#define LAST_INHERITABLE_ATTR(NAME) INHERITABLE_ATTR(NAME)\n"; + OS << "#endif\n\n"; + + Record *InhClass = Records.getClass("InheritableAttr"); + std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), + NonInhAttrs, InhAttrs; + for (std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(); + i != e; ++i) { + if ((*i)->isSubClassOf(InhClass)) + InhAttrs.push_back(*i); + else + NonInhAttrs.push_back(*i); } + EmitAttrList(OS, "INHERITABLE_ATTR", InhAttrs); + EmitAttrList(OS, "ATTR", NonInhAttrs); + OS << "#undef LAST_ATTR\n"; + OS << "#undef INHERITABLE_ATTR\n"; + OS << "#undef LAST_INHERITABLE_ATTR\n"; OS << "#undef ATTR\n"; } void ClangAttrPCHReadEmitter::run(raw_ostream &OS) { - OS << "// This file is generated by TableGen. Do not edi.\n\n"; + OS << "// This file is generated by TableGen. Do not edit.\n\n"; + Record *InhClass = Records.getClass("InheritableAttr"); std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), ArgRecords; std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae; @@ -595,6 +626,8 @@ void ClangAttrPCHReadEmitter::run(raw_ostream &OS) { for (; i != e; ++i) { Record &R = **i; OS << " case attr::" << R.getName() << ": {\n"; + if (R.isSubClassOf(InhClass)) + OS << " bool isInherited = Record[Idx++];\n"; ArgRecords = R.getValueAsListOfDefs("Args"); Args.clear(); for (ai = ArgRecords.begin(), ae = ArgRecords.end(); ai != ae; ++ai) { @@ -608,6 +641,8 @@ void ClangAttrPCHReadEmitter::run(raw_ostream &OS) { (*ri)->writePCHReadArgs(OS); } OS << ");\n"; + if (R.isSubClassOf(InhClass)) + OS << " cast<InheritableAttr>(New)->setInherited(isInherited);\n"; OS << " break;\n"; OS << " }\n"; } @@ -615,6 +650,7 @@ void ClangAttrPCHReadEmitter::run(raw_ostream &OS) { } void ClangAttrPCHWriteEmitter::run(raw_ostream &OS) { + Record *InhClass = Records.getClass("InheritableAttr"); std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"), Args; std::vector<Record*>::iterator i = Attrs.begin(), e = Attrs.end(), ai, ae; @@ -626,9 +662,11 @@ void ClangAttrPCHWriteEmitter::run(raw_ostream &OS) { Record &R = **i; OS << " case attr::" << R.getName() << ": {\n"; Args = R.getValueAsListOfDefs("Args"); - if (!Args.empty()) + if (R.isSubClassOf(InhClass) || !Args.empty()) OS << " const " << R.getName() << "Attr *SA = cast<" << R.getName() << "Attr>(A);\n"; + if (R.isSubClassOf(InhClass)) + OS << " Record.push_back(SA->isInherited());\n"; for (ai = Args.begin(), ae = Args.end(); ai != ae; ++ai) createArgument(**ai, R.getName())->writePCHWrite(OS); OS << " break;\n"; @@ -636,3 +674,21 @@ void ClangAttrPCHWriteEmitter::run(raw_ostream &OS) { } OS << " }\n"; } + +void ClangAttrSpellingListEmitter::run(raw_ostream &OS) { + OS << "// This file is generated by TableGen. Do not edit.\n\n"; + + std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr"); + + for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) { + Record &Attr = **I; + + std::vector<StringRef> Spellings = getValueAsListOfStrings(Attr, "Spellings"); + + for (std::vector<StringRef>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) { + StringRef Spelling = *I; + OS << ".Case(\"" << Spelling << "\", true)\n"; + } + } + +} diff --git a/utils/TableGen/ClangAttrEmitter.h b/utils/TableGen/ClangAttrEmitter.h index 8314982..af87009 100644 --- a/utils/TableGen/ClangAttrEmitter.h +++ b/utils/TableGen/ClangAttrEmitter.h @@ -83,6 +83,19 @@ public: void run(raw_ostream &OS); }; +/// ClangAttrSpellingListEmitter - class emits the list of spellings for attributes for +/// clang. +class ClangAttrSpellingListEmitter : public TableGenBackend { + RecordKeeper &Records; + + public: + explicit ClangAttrSpellingListEmitter(RecordKeeper &R) + : Records(R) + {} + + void run(raw_ostream &OS); +}; + } #endif diff --git a/utils/TableGen/ClangDiagnosticsEmitter.cpp b/utils/TableGen/ClangDiagnosticsEmitter.cpp index 75b6252..60e67c4 100644 --- a/utils/TableGen/ClangDiagnosticsEmitter.cpp +++ b/utils/TableGen/ClangDiagnosticsEmitter.cpp @@ -29,9 +29,10 @@ using namespace llvm; namespace { class DiagGroupParentMap { + RecordKeeper &Records; std::map<const Record*, std::vector<Record*> > Mapping; public: - DiagGroupParentMap() { + DiagGroupParentMap(RecordKeeper &records) : Records(records) { std::vector<Record*> DiagGroups = Records.getAllDerivedDefinitions("DiagGroup"); for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) { @@ -84,11 +85,12 @@ static std::string getDiagnosticCategory(const Record *R, namespace { class DiagCategoryIDMap { + RecordKeeper &Records; StringMap<unsigned> CategoryIDs; std::vector<std::string> CategoryStrings; public: - DiagCategoryIDMap() { - DiagGroupParentMap ParentInfo; + DiagCategoryIDMap(RecordKeeper &records) : Records(records) { + DiagGroupParentMap ParentInfo(Records); // The zero'th category is "". CategoryStrings.push_back(""); @@ -138,8 +140,8 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) { const std::vector<Record*> &Diags = Records.getAllDerivedDefinitions("Diagnostic"); - DiagCategoryIDMap CategoryIDs; - DiagGroupParentMap DGParentMap; + DiagCategoryIDMap CategoryIDs(Records); + DiagGroupParentMap DGParentMap(Records); for (unsigned i = 0, e = Diags.size(); i != e; ++i) { const Record &R = *Diags[i]; @@ -168,7 +170,13 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) { OS << ", true"; else OS << ", false"; - + + // Access control bit + if (R.getValueAsBit("AccessControl")) + OS << ", true"; + else + OS << ", false"; + // Category number. OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap)); OS << ")\n"; @@ -179,15 +187,17 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) { // Warning Group Tables generation //===----------------------------------------------------------------------===// +namespace { struct GroupInfo { std::vector<const Record*> DiagsInGroup; std::vector<std::string> SubGroups; unsigned IDNo; }; +} // end anonymous namespace. void ClangDiagGroupsEmitter::run(raw_ostream &OS) { // Compute a mapping from a DiagGroup to all of its parents. - DiagGroupParentMap DGParentMap; + DiagGroupParentMap DGParentMap(Records); // Invert the 1-[0/1] mapping of diags to group into a one to many mapping of // groups to diags in the group. @@ -277,7 +287,7 @@ void ClangDiagGroupsEmitter::run(raw_ostream &OS) { OS << "#endif // GET_DIAG_TABLE\n\n"; // Emit the category table next. - DiagCategoryIDMap CategoriesByID; + DiagCategoryIDMap CategoriesByID(Records); OS << "\n#ifdef GET_CATEGORY_TABLE\n"; for (DiagCategoryIDMap::iterator I = CategoriesByID.begin(), E = CategoriesByID.end(); I != E; ++I) diff --git a/utils/TableGen/ClangSACheckersEmitter.cpp b/utils/TableGen/ClangSACheckersEmitter.cpp new file mode 100644 index 0000000..3e49ab1 --- /dev/null +++ b/utils/TableGen/ClangSACheckersEmitter.cpp @@ -0,0 +1,229 @@ +//=- ClangSACheckersEmitter.cpp - Generate Clang SA checkers tables -*- C++ -*- +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend emits Clang Static Analyzer checkers tables. +// +//===----------------------------------------------------------------------===// + +#include "ClangSACheckersEmitter.h" +#include "Record.h" +#include "llvm/ADT/DenseSet.h" +#include <map> +#include <string> +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Static Analyzer Checkers Tables generation +//===----------------------------------------------------------------------===// + +/// \brief True if it is specified hidden or a parent package is specified +/// as hidden, otherwise false. +static bool isHidden(const Record &R) { + if (R.getValueAsBit("Hidden")) + return true; + // Not declared as hidden, check the parent package if it is hidden. + if (DefInit *DI = dynamic_cast<DefInit*>(R.getValueInit("ParentPackage"))) + return isHidden(*DI->getDef()); + + return false; +} + +static bool isCheckerNamed(const Record *R) { + return !R->getValueAsString("CheckerName").empty(); +} + +static std::string getPackageFullName(const Record *R); + +static std::string getParentPackageFullName(const Record *R) { + std::string name; + if (DefInit *DI = dynamic_cast<DefInit*>(R->getValueInit("ParentPackage"))) + name = getPackageFullName(DI->getDef()); + return name; +} + +static std::string getPackageFullName(const Record *R) { + std::string name = getParentPackageFullName(R); + if (!name.empty()) name += "."; + return name + R->getValueAsString("PackageName"); +} + +static std::string getCheckerFullName(const Record *R) { + std::string name = getParentPackageFullName(R); + if (isCheckerNamed(R)) { + if (!name.empty()) name += "."; + name += R->getValueAsString("CheckerName"); + } + return name; +} + +static std::string getStringValue(const Record &R, StringRef field) { + if (StringInit * + SI = dynamic_cast<StringInit*>(R.getValueInit(field))) + return SI->getValue(); + return std::string(); +} + +namespace { +struct GroupInfo { + std::vector<const Record*> Checkers; + llvm::DenseSet<const Record *> SubGroups; + bool Hidden; + unsigned Index; + + GroupInfo() : Hidden(false) { } +}; +} + +void ClangSACheckersEmitter::run(raw_ostream &OS) { + std::vector<Record*> checkers = Records.getAllDerivedDefinitions("Checker"); + llvm::DenseMap<const Record *, unsigned> checkerRecIndexMap; + for (unsigned i = 0, e = checkers.size(); i != e; ++i) + checkerRecIndexMap[checkers[i]] = i; + + OS << "\n#ifdef GET_CHECKERS\n"; + for (unsigned i = 0, e = checkers.size(); i != e; ++i) { + const Record &R = *checkers[i]; + + OS << "CHECKER(" << "\""; + std::string name; + if (isCheckerNamed(&R)) + name = getCheckerFullName(&R); + OS.write_escaped(name) << "\", "; + OS << R.getName() << ", "; + OS << getStringValue(R, "DescFile") << ", "; + OS << "\""; + OS.write_escaped(getStringValue(R, "HelpText")) << "\", "; + // Hidden bit + if (isHidden(R)) + OS << "true"; + else + OS << "false"; + OS << ")\n"; + } + OS << "#endif // GET_CHECKERS\n\n"; + + // Invert the mapping of checkers to package/group into a one to many + // mapping of packages/groups to checkers. + std::map<std::string, GroupInfo> groupInfoByName; + llvm::DenseMap<const Record *, GroupInfo *> recordGroupMap; + + std::vector<Record*> packages = Records.getAllDerivedDefinitions("Package"); + for (unsigned i = 0, e = packages.size(); i != e; ++i) { + Record *R = packages[i]; + std::string fullName = getPackageFullName(R); + if (!fullName.empty()) { + GroupInfo &info = groupInfoByName[fullName]; + info.Hidden = isHidden(*R); + recordGroupMap[R] = &info; + } + } + + std::vector<Record*> + checkerGroups = Records.getAllDerivedDefinitions("CheckerGroup"); + for (unsigned i = 0, e = checkerGroups.size(); i != e; ++i) { + Record *R = checkerGroups[i]; + std::string name = R->getValueAsString("GroupName"); + if (!name.empty()) { + GroupInfo &info = groupInfoByName[name]; + recordGroupMap[R] = &info; + } + } + + for (unsigned i = 0, e = checkers.size(); i != e; ++i) { + Record *R = checkers[i]; + Record *package = 0; + if (DefInit * + DI = dynamic_cast<DefInit*>(R->getValueInit("ParentPackage"))) + package = DI->getDef(); + if (!isCheckerNamed(R) && !package) + throw "Checker '" + R->getName() + "' is neither named, nor in a package!"; + + if (isCheckerNamed(R)) { + // Create a pseudo-group to hold this checker. + std::string fullName = getCheckerFullName(R); + GroupInfo &info = groupInfoByName[fullName]; + recordGroupMap[R] = &info; + info.Checkers.push_back(R); + } else { + recordGroupMap[package]->Checkers.push_back(R); + } + + Record *currR = isCheckerNamed(R) ? R : package; + // Insert the checker and its parent packages into the subgroups set of + // the corresponding parent package. + while (DefInit *DI + = dynamic_cast<DefInit*>(currR->getValueInit("ParentPackage"))) { + Record *parentPackage = DI->getDef(); + recordGroupMap[parentPackage]->SubGroups.insert(currR); + currR = parentPackage; + } + // Insert the checker into the set of its group. + if (DefInit *DI = dynamic_cast<DefInit*>(R->getValueInit("Group"))) + recordGroupMap[DI->getDef()]->Checkers.push_back(R); + } + + unsigned index = 0; + for (std::map<std::string, GroupInfo>::iterator + I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I) + I->second.Index = index++; + + // Walk through the packages/groups/checkers emitting an array for each + // set of checkers and an array for each set of subpackages. + + OS << "\n#ifdef GET_MEMBER_ARRAYS\n"; + unsigned maxLen = 0; + for (std::map<std::string, GroupInfo>::iterator + I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I) { + maxLen = std::max(maxLen, (unsigned)I->first.size()); + + std::vector<const Record*> &V = I->second.Checkers; + if (!V.empty()) { + OS << "static const short CheckerArray" << I->second.Index << "[] = { "; + for (unsigned i = 0, e = V.size(); i != e; ++i) + OS << checkerRecIndexMap[V[i]] << ", "; + OS << "-1 };\n"; + } + + llvm::DenseSet<const Record *> &subGroups = I->second.SubGroups; + if (!subGroups.empty()) { + OS << "static const short SubPackageArray" << I->second.Index << "[] = { "; + for (llvm::DenseSet<const Record *>::iterator + I = subGroups.begin(), E = subGroups.end(); I != E; ++I) { + OS << recordGroupMap[*I]->Index << ", "; + } + OS << "-1 };\n"; + } + } + OS << "#endif // GET_MEMBER_ARRAYS\n\n"; + + OS << "\n#ifdef GET_CHECKNAME_TABLE\n"; + for (std::map<std::string, GroupInfo>::iterator + I = groupInfoByName.begin(), E = groupInfoByName.end(); I != E; ++I) { + // Group option string. + OS << " { \""; + OS.write_escaped(I->first) << "\"," + << std::string(maxLen-I->first.size()+1, ' '); + + if (I->second.Checkers.empty()) + OS << "0, "; + else + OS << "CheckerArray" << I->second.Index << ", "; + + // Subgroups. + if (I->second.SubGroups.empty()) + OS << "0, "; + else + OS << "SubPackageArray" << I->second.Index << ", "; + + OS << (I->second.Hidden ? "true" : "false"); + + OS << " },\n"; + } + OS << "#endif // GET_CHECKNAME_TABLE\n\n"; +} diff --git a/utils/TableGen/ClangSACheckersEmitter.h b/utils/TableGen/ClangSACheckersEmitter.h new file mode 100644 index 0000000..6bd1635 --- /dev/null +++ b/utils/TableGen/ClangSACheckersEmitter.h @@ -0,0 +1,31 @@ +//===- ClangSACheckersEmitter.h - Generate Clang SA checkers tables -*- C++ -*- +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend emits Clang Static Analyzer checkers tables. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANGSACHECKERS_EMITTER_H +#define CLANGSACHECKERS_EMITTER_H + +#include "TableGenBackend.h" + +namespace llvm { + +class ClangSACheckersEmitter : public TableGenBackend { + RecordKeeper &Records; +public: + explicit ClangSACheckersEmitter(RecordKeeper &R) : Records(R) {} + + void run(raw_ostream &OS); +}; + +} // End llvm namespace + +#endif diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index ec702c2a5..957dd19 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/utils/TableGen/CodeEmitterGen.cpp @@ -17,9 +17,19 @@ #include "CodeGenTarget.h" #include "Record.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include <map> using namespace llvm; +// FIXME: Somewhat hackish to use a command line option for this. There should +// be a CodeEmitter class in the Target.td that controls this sort of thing +// instead. +static cl::opt<bool> +MCEmitter("mc-emitter", + cl::desc("Generate CodeEmitter for use with the MC library."), + cl::init(false)); + void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) { for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end(); I != E; ++I) { @@ -42,46 +52,171 @@ void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) { unsigned middle = (numBits + 1) / 2; NewBI->setBit(middle, BI->getBit(middle)); } - + // Update the bits in reversed order so that emitInstrOpBits will get the // correct endianness. R->getValue("Inst")->setValue(NewBI); } } - // If the VarBitInit at position 'bit' matches the specified variable then // return the variable bit position. Otherwise return -1. int CodeEmitterGen::getVariableBit(const std::string &VarName, - BitsInit *BI, int bit) { - if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(BI->getBit(bit))) { - TypedInit *TI = VBI->getVariable(); + BitsInit *BI, int bit) { + if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(BI->getBit(bit))) + if (VarInit *VI = dynamic_cast<VarInit*>(VBI->getVariable())) + if (VI->getName() == VarName) + return VBI->getBitNum(); + + return -1; +} + +void CodeEmitterGen:: +AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, + unsigned &NumberedOp, + std::string &Case, CodeGenTarget &Target) { + CodeGenInstruction &CGI = Target.getInstruction(R); + + // Determine if VarName actually contributes to the Inst encoding. + int bit = BI->getNumBits()-1; + + // Scan for a bit that this contributed to. + for (; bit >= 0; ) { + if (getVariableBit(VarName, BI, bit) != -1) + break; - if (VarInit *VI = dynamic_cast<VarInit*>(TI)) { - if (VI->getName() == VarName) return VBI->getBitNum(); + --bit; + } + + // If we found no bits, ignore this value, otherwise emit the call to get the + // operand encoding. + if (bit < 0) return; + + // If the operand matches by name, reference according to that + // operand number. Non-matching operands are assumed to be in + // order. + unsigned OpIdx; + if (CGI.Operands.hasOperandNamed(VarName, OpIdx)) { + // Get the machine operand number for the indicated operand. + OpIdx = CGI.Operands[OpIdx].MIOperandNo; + assert(!CGI.Operands.isFlatOperandNotEmitted(OpIdx) && + "Explicitly used operand also marked as not emitted!"); + } else { + /// If this operand is not supposed to be emitted by the + /// generated emitter, skip it. + while (CGI.Operands.isFlatOperandNotEmitted(NumberedOp)) + ++NumberedOp; + OpIdx = NumberedOp++; + } + + std::pair<unsigned, unsigned> SO = CGI.Operands.getSubOperandNumber(OpIdx); + std::string &EncoderMethodName = CGI.Operands[SO.first].EncoderMethodName; + + // If the source operand has a custom encoder, use it. This will + // get the encoding for all of the suboperands. + if (!EncoderMethodName.empty()) { + // A custom encoder has all of the information for the + // sub-operands, if there are more than one, so only + // query the encoder once per source operand. + if (SO.second == 0) { + Case += " // op: " + VarName + "\n" + + " op = " + EncoderMethodName + "(MI, " + utostr(OpIdx); + if (MCEmitter) + Case += ", Fixups"; + Case += ");\n"; } + } else { + Case += " // op: " + VarName + "\n" + + " op = getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")"; + if (MCEmitter) + Case += ", Fixups"; + Case += ");\n"; } - return -1; -} + for (; bit >= 0; ) { + int varBit = getVariableBit(VarName, BI, bit); + + // If this bit isn't from a variable, skip it. + if (varBit == -1) { + --bit; + continue; + } + + // Figure out the consecutive range of bits covered by this operand, in + // order to generate better encoding code. + int beginInstBit = bit; + int beginVarBit = varBit; + int N = 1; + for (--bit; bit >= 0;) { + varBit = getVariableBit(VarName, BI, bit); + if (varBit == -1 || varBit != (beginVarBit - N)) break; + ++N; + --bit; + } + + unsigned opMask = ~0U >> (32-N); + int opShift = beginVarBit - N + 1; + opMask <<= opShift; + opShift = beginInstBit - beginVarBit; + + if (opShift > 0) { + Case += " Value |= (op & " + utostr(opMask) + "U) << " + + itostr(opShift) + ";\n"; + } else if (opShift < 0) { + Case += " Value |= (op & " + utostr(opMask) + "U) >> " + + itostr(-opShift) + ";\n"; + } else { + Case += " Value |= op & " + utostr(opMask) + "U;\n"; + } + } +} +std::string CodeEmitterGen::getInstructionCase(Record *R, + CodeGenTarget &Target) { + std::string Case; + + BitsInit *BI = R->getValueAsBitsInit("Inst"); + const std::vector<RecordVal> &Vals = R->getValues(); + unsigned NumberedOp = 0; + + // Loop over all of the fields in the instruction, determining which are the + // operands to the instruction. + for (unsigned i = 0, e = Vals.size(); i != e; ++i) { + // Ignore fixed fields in the record, we're looking for values like: + // bits<5> RST = { ?, ?, ?, ?, ? }; + if (Vals[i].getPrefix() || Vals[i].getValue()->isComplete()) + continue; + + AddCodeToMergeInOperand(R, BI, Vals[i].getName(), NumberedOp, Case, Target); + } + + std::string PostEmitter = R->getValueAsString("PostEncoderMethod"); + if (!PostEmitter.empty()) + Case += " Value = " + PostEmitter + "(MI, Value);\n"; + + return Case; +} + void CodeEmitterGen::run(raw_ostream &o) { - CodeGenTarget Target; + CodeGenTarget Target(Records); std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); - + // For little-endian instruction bit encodings, reverse the bit order if (Target.isLittleEndianEncoding()) reverseBits(Insts); EmitSourceFileHeader("Machine Code Emitter", o); - std::string Namespace = Insts[0]->getValueAsString("Namespace") + "::"; - + const std::vector<const CodeGenInstruction*> &NumberedInstructions = Target.getInstructionsByEnumValue(); // Emit function declaration - o << "unsigned " << Target.getName() << "CodeEmitter::" - << "getBinaryCodeForInstr(const MachineInstr &MI) {\n"; + o << "unsigned " << Target.getName(); + if (MCEmitter) + o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n" + << " SmallVectorImpl<MCFixup> &Fixups) const {\n"; + else + o << "CodeEmitter::getBinaryCodeForInstr(const MachineInstr &MI) const {\n"; // Emit instruction base values o << " static const unsigned InstBits[] = {\n"; @@ -91,109 +226,45 @@ void CodeEmitterGen::run(raw_ostream &o) { IN != EN; ++IN) { const CodeGenInstruction *CGI = *IN; Record *R = CGI->TheDef; - + if (R->getValueAsString("Namespace") == "TargetOpcode") { o << " 0U,\n"; continue; } - + BitsInit *BI = R->getValueAsBitsInit("Inst"); - // Start by filling in fixed values... + // Start by filling in fixed values. unsigned Value = 0; for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) { - if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) { + if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) Value |= B->getValue() << (e-i-1); - } } o << " " << Value << "U," << '\t' << "// " << R->getName() << "\n"; } o << " 0U\n };\n"; - + // Map to accumulate all the cases. std::map<std::string, std::vector<std::string> > CaseMap; - + // Construct all cases statement for each opcode for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end(); IC != EC; ++IC) { Record *R = *IC; if (R->getValueAsString("Namespace") == "TargetOpcode") continue; - const std::string &InstName = R->getName(); - std::string Case(""); - - BitsInit *BI = R->getValueAsBitsInit("Inst"); - const std::vector<RecordVal> &Vals = R->getValues(); - CodeGenInstruction &CGI = Target.getInstruction(R); - - // Loop over all of the fields in the instruction, determining which are the - // operands to the instruction. - unsigned op = 0; - for (unsigned i = 0, e = Vals.size(); i != e; ++i) { - if (!Vals[i].getPrefix() && !Vals[i].getValue()->isComplete()) { - // Is the operand continuous? If so, we can just mask and OR it in - // instead of doing it bit-by-bit, saving a lot in runtime cost. - const std::string &VarName = Vals[i].getName(); - bool gotOp = false; - - for (int bit = BI->getNumBits()-1; bit >= 0; ) { - int varBit = getVariableBit(VarName, BI, bit); - - if (varBit == -1) { - --bit; - } else { - int beginInstBit = bit; - int beginVarBit = varBit; - int N = 1; - - for (--bit; bit >= 0;) { - varBit = getVariableBit(VarName, BI, bit); - if (varBit == -1 || varBit != (beginVarBit - N)) break; - ++N; - --bit; - } - - if (!gotOp) { - /// If this operand is not supposed to be emitted by the generated - /// emitter, skip it. - while (CGI.isFlatOperandNotEmitted(op)) - ++op; - - Case += " // op: " + VarName + "\n" - + " op = getMachineOpValue(MI, MI.getOperand(" - + utostr(op++) + "));\n"; - gotOp = true; - } - - unsigned opMask = ~0U >> (32-N); - int opShift = beginVarBit - N + 1; - opMask <<= opShift; - opShift = beginInstBit - beginVarBit; - - if (opShift > 0) { - Case += " Value |= (op & " + utostr(opMask) + "U) << " - + itostr(opShift) + ";\n"; - } else if (opShift < 0) { - Case += " Value |= (op & " + utostr(opMask) + "U) >> " - + itostr(-opShift) + ";\n"; - } else { - Case += " Value |= op & " + utostr(opMask) + "U;\n"; - } - } - } - } - } + const std::string &InstName = R->getValueAsString("Namespace") + "::" + + R->getName(); + std::string Case = getInstructionCase(R, Target); - std::vector<std::string> &InstList = CaseMap[Case]; - InstList.push_back(InstName); + CaseMap[Case].push_back(InstName); } - // Emit initial function code o << " const unsigned opcode = MI.getOpcode();\n" << " unsigned Value = InstBits[opcode];\n" << " unsigned op = 0;\n" - << " op = op; // suppress warning\n" + << " (void)op; // suppress warning\n" << " switch (opcode) {\n"; // Emit each case statement @@ -204,7 +275,7 @@ void CodeEmitterGen::run(raw_ostream &o) { for (int i = 0, N = InstList.size(); i < N; i++) { if (i) o << "\n"; - o << " case " << Namespace << InstList[i] << ":"; + o << " case " << InstList[i] << ":"; } o << " {\n"; o << Case; diff --git a/utils/TableGen/CodeEmitterGen.h b/utils/TableGen/CodeEmitterGen.h index f0b3229..a874d97 100644 --- a/utils/TableGen/CodeEmitterGen.h +++ b/utils/TableGen/CodeEmitterGen.h @@ -15,7 +15,6 @@ #define CODEMITTERGEN_H #include "TableGenBackend.h" -#include <map> #include <vector> #include <string> @@ -23,6 +22,7 @@ namespace llvm { class RecordVal; class BitsInit; +class CodeGenTarget; class CodeEmitterGen : public TableGenBackend { RecordKeeper &Records; @@ -36,6 +36,12 @@ private: void emitGetValueBit(raw_ostream &o, const std::string &Namespace); void reverseBits(std::vector<Record*> &Insts); int getVariableBit(const std::string &VarName, BitsInit *BI, int bit); + std::string getInstructionCase(Record *R, CodeGenTarget &Target); + void + AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, + unsigned &NumberedOp, + std::string &Case, CodeGenTarget &Target); + }; } // End llvm namespace diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 303aa6c..aa60f87 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -56,11 +56,11 @@ EEVT::TypeSet::TypeSet(MVT::SimpleValueType VT, TreePattern &TP) { EEVT::TypeSet::TypeSet(const std::vector<MVT::SimpleValueType> &VTList) { assert(!VTList.empty() && "empty list?"); TypeVec.append(VTList.begin(), VTList.end()); - + if (!VTList.empty()) assert(VTList[0] != MVT::iAny && VTList[0] != MVT::vAny && VTList[0] != MVT::fAny); - + // Verify no duplicates. array_pod_sort(TypeVec.begin(), TypeVec.end()); assert(std::unique(TypeVec.begin(), TypeVec.end()) == TypeVec.end()); @@ -72,9 +72,9 @@ bool EEVT::TypeSet::FillWithPossibleTypes(TreePattern &TP, bool (*Pred)(MVT::SimpleValueType), const char *PredicateName) { assert(isCompletelyUnknown()); - const std::vector<MVT::SimpleValueType> &LegalTypes = + const std::vector<MVT::SimpleValueType> &LegalTypes = TP.getDAGPatterns().getTargetInfo().getLegalValueTypes(); - + for (unsigned i = 0, e = LegalTypes.size(); i != e; ++i) if (Pred == 0 || Pred(LegalTypes[i])) TypeVec.push_back(LegalTypes[i]); @@ -82,14 +82,14 @@ bool EEVT::TypeSet::FillWithPossibleTypes(TreePattern &TP, // If we have nothing that matches the predicate, bail out. if (TypeVec.empty()) TP.error("Type inference contradiction found, no " + - std::string(PredicateName) + " types found"); + std::string(PredicateName) + " types found"); // No need to sort with one element. if (TypeVec.size() == 1) return true; // Remove duplicates. array_pod_sort(TypeVec.begin(), TypeVec.end()); TypeVec.erase(std::unique(TypeVec.begin(), TypeVec.end()), TypeVec.end()); - + return true; } @@ -100,7 +100,7 @@ bool EEVT::TypeSet::hasIntegerTypes() const { if (isInteger(TypeVec[i])) return true; return false; -} +} /// hasFloatingPointTypes - Return true if this TypeSet contains an fAny or /// a floating point value type. @@ -109,7 +109,7 @@ bool EEVT::TypeSet::hasFloatingPointTypes() const { if (isFloatingPoint(TypeVec[i])) return true; return false; -} +} /// hasVectorTypes - Return true if this TypeSet contains a vAny or a vector /// value type. @@ -123,9 +123,9 @@ bool EEVT::TypeSet::hasVectorTypes() const { std::string EEVT::TypeSet::getName() const { if (TypeVec.empty()) return "<empty>"; - + std::string Result; - + for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) { std::string VTName = llvm::getEnumName(TypeVec[i]); // Strip off MVT:: prefix if present. @@ -134,7 +134,7 @@ std::string EEVT::TypeSet::getName() const { if (i) Result += ':'; Result += VTName; } - + if (TypeVec.size() == 1) return Result; return "{" + Result + "}"; @@ -146,14 +146,14 @@ std::string EEVT::TypeSet::getName() const { bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){ if (InVT.isCompletelyUnknown() || *this == InVT) return false; - + if (isCompletelyUnknown()) { *this = InVT; return true; } - + assert(TypeVec.size() >= 1 && InVT.TypeVec.size() >= 1 && "No unknowns"); - + // Handle the abstract cases, seeing if we can resolve them better. switch (TypeVec[0]) { default: break; @@ -163,26 +163,26 @@ bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){ EEVT::TypeSet InCopy(InVT); InCopy.EnforceInteger(TP); InCopy.EnforceScalar(TP); - + if (InCopy.isConcrete()) { // If the RHS has one integer type, upgrade iPTR to i32. TypeVec[0] = InVT.TypeVec[0]; return true; } - + // If the input has multiple scalar integers, this doesn't add any info. if (!InCopy.isCompletelyUnknown()) return false; } break; } - + // If the input constraint is iAny/iPTR and this is an integer type list, // remove non-integer types from the list. if ((InVT.TypeVec[0] == MVT::iPTR || InVT.TypeVec[0] == MVT::iPTRAny) && hasIntegerTypes()) { bool MadeChange = EnforceInteger(TP); - + // If we're merging in iPTR/iPTRAny and the node currently has a list of // multiple different integer types, replace them with a single iPTR. if ((InVT.TypeVec[0] == MVT::iPTR || InVT.TypeVec[0] == MVT::iPTRAny) && @@ -191,10 +191,10 @@ bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){ TypeVec[0] = InVT.TypeVec[0]; MadeChange = true; } - + return MadeChange; } - + // If this is a type list and the RHS is a typelist as well, eliminate entries // from this list that aren't in the other one. bool MadeChange = false; @@ -207,16 +207,16 @@ bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){ InInVT = true; break; } - + if (InInVT) continue; TypeVec.erase(TypeVec.begin()+i--); MadeChange = true; } - + // If we removed all of our types, we have a type contradiction. if (!TypeVec.empty()) return MadeChange; - + // FIXME: Really want an SMLoc here! TP.error("Type inference contradiction found, merging '" + InVT.getName() + "' into '" + InputSet.getName() + "'"); @@ -232,12 +232,12 @@ bool EEVT::TypeSet::EnforceInteger(TreePattern &TP) { return false; TypeSet InputSet(*this); - + // Filter out all the fp types. for (unsigned i = 0; i != TypeVec.size(); ++i) if (!isInteger(TypeVec[i])) TypeVec.erase(TypeVec.begin()+i--); - + if (TypeVec.empty()) TP.error("Type inference contradiction found, '" + InputSet.getName() + "' needs to be integer"); @@ -254,12 +254,12 @@ bool EEVT::TypeSet::EnforceFloatingPoint(TreePattern &TP) { return false; TypeSet InputSet(*this); - + // Filter out all the fp types. for (unsigned i = 0; i != TypeVec.size(); ++i) if (!isFloatingPoint(TypeVec[i])) TypeVec.erase(TypeVec.begin()+i--); - + if (TypeVec.empty()) TP.error("Type inference contradiction found, '" + InputSet.getName() + "' needs to be floating point"); @@ -276,12 +276,12 @@ bool EEVT::TypeSet::EnforceScalar(TreePattern &TP) { return false; TypeSet InputSet(*this); - + // Filter out all the vector types. for (unsigned i = 0; i != TypeVec.size(); ++i) if (!isScalar(TypeVec[i])) TypeVec.erase(TypeVec.begin()+i--); - + if (TypeVec.empty()) TP.error("Type inference contradiction found, '" + InputSet.getName() + "' needs to be scalar"); @@ -296,14 +296,14 @@ bool EEVT::TypeSet::EnforceVector(TreePattern &TP) { TypeSet InputSet(*this); bool MadeChange = false; - + // Filter out all the scalar types. for (unsigned i = 0; i != TypeVec.size(); ++i) if (!isVector(TypeVec[i])) { TypeVec.erase(TypeVec.begin()+i--); MadeChange = true; } - + if (TypeVec.empty()) TP.error("Type inference contradiction found, '" + InputSet.getName() + "' needs to be a vector"); @@ -317,13 +317,13 @@ bool EEVT::TypeSet::EnforceVector(TreePattern &TP) { bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { // Both operands must be integer or FP, but we don't care which. bool MadeChange = false; - + if (isCompletelyUnknown()) MadeChange = FillWithPossibleTypes(TP); if (Other.isCompletelyUnknown()) MadeChange = Other.FillWithPossibleTypes(TP); - + // If one side is known to be integer or known to be FP but the other side has // no information, get at least the type integrality info in there. if (!hasFloatingPointTypes()) @@ -334,62 +334,165 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { MadeChange |= EnforceInteger(TP); else if (!Other.hasIntegerTypes()) MadeChange |= EnforceFloatingPoint(TP); - + assert(!isCompletelyUnknown() && !Other.isCompletelyUnknown() && "Should have a type list now"); - + // If one contains vectors but the other doesn't pull vectors out. if (!hasVectorTypes()) MadeChange |= Other.EnforceScalar(TP); if (!hasVectorTypes()) MadeChange |= EnforceScalar(TP); + + if (TypeVec.size() == 1 && Other.TypeVec.size() == 1) { + // If we are down to concrete types, this code does not currently + // handle nodes which have multiple types, where some types are + // integer, and some are fp. Assert that this is not the case. + assert(!(hasIntegerTypes() && hasFloatingPointTypes()) && + !(Other.hasIntegerTypes() && Other.hasFloatingPointTypes()) && + "SDTCisOpSmallerThanOp does not handle mixed int/fp types!"); + + // Otherwise, if these are both vector types, either this vector + // must have a larger bitsize than the other, or this element type + // must be larger than the other. + EVT Type(TypeVec[0]); + EVT OtherType(Other.TypeVec[0]); + + if (hasVectorTypes() && Other.hasVectorTypes()) { + if (Type.getSizeInBits() >= OtherType.getSizeInBits()) + if (Type.getVectorElementType().getSizeInBits() + >= OtherType.getVectorElementType().getSizeInBits()) + TP.error("Type inference contradiction found, '" + + getName() + "' element type not smaller than '" + + Other.getName() +"'!"); + } + else + // For scalar types, the bitsize of this type must be larger + // than that of the other. + if (Type.getSizeInBits() >= OtherType.getSizeInBits()) + TP.error("Type inference contradiction found, '" + + getName() + "' is not smaller than '" + + Other.getName() +"'!"); + + } - // This code does not currently handle nodes which have multiple types, - // where some types are integer, and some are fp. Assert that this is not - // the case. - assert(!(hasIntegerTypes() && hasFloatingPointTypes()) && - !(Other.hasIntegerTypes() && Other.hasFloatingPointTypes()) && - "SDTCisOpSmallerThanOp does not handle mixed int/fp types!"); - + + // Handle int and fp as disjoint sets. This won't work for patterns + // that have mixed fp/int types but those are likely rare and would + // not have been accepted by this code previously. + // Okay, find the smallest type from the current set and remove it from the // largest set. - MVT::SimpleValueType Smallest = TypeVec[0]; + MVT::SimpleValueType SmallestInt = MVT::LAST_VALUETYPE; + for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) + if (isInteger(TypeVec[i])) { + SmallestInt = TypeVec[i]; + break; + } for (unsigned i = 1, e = TypeVec.size(); i != e; ++i) - if (TypeVec[i] < Smallest) - Smallest = TypeVec[i]; - + if (isInteger(TypeVec[i]) && TypeVec[i] < SmallestInt) + SmallestInt = TypeVec[i]; + + MVT::SimpleValueType SmallestFP = MVT::LAST_VALUETYPE; + for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) + if (isFloatingPoint(TypeVec[i])) { + SmallestFP = TypeVec[i]; + break; + } + for (unsigned i = 1, e = TypeVec.size(); i != e; ++i) + if (isFloatingPoint(TypeVec[i]) && TypeVec[i] < SmallestFP) + SmallestFP = TypeVec[i]; + + int OtherIntSize = 0; + int OtherFPSize = 0; + for (SmallVector<MVT::SimpleValueType, 2>::iterator TVI = + Other.TypeVec.begin(); + TVI != Other.TypeVec.end(); + /* NULL */) { + if (isInteger(*TVI)) { + ++OtherIntSize; + if (*TVI == SmallestInt) { + TVI = Other.TypeVec.erase(TVI); + --OtherIntSize; + MadeChange = true; + continue; + } + } + else if (isFloatingPoint(*TVI)) { + ++OtherFPSize; + if (*TVI == SmallestFP) { + TVI = Other.TypeVec.erase(TVI); + --OtherFPSize; + MadeChange = true; + continue; + } + } + ++TVI; + } + // If this is the only type in the large set, the constraint can never be // satisfied. - if (Other.TypeVec.size() == 1 && Other.TypeVec[0] == Smallest) + if ((Other.hasIntegerTypes() && OtherIntSize == 0) + || (Other.hasFloatingPointTypes() && OtherFPSize == 0)) TP.error("Type inference contradiction found, '" + Other.getName() + "' has nothing larger than '" + getName() +"'!"); - - SmallVector<MVT::SimpleValueType, 2>::iterator TVI = - std::find(Other.TypeVec.begin(), Other.TypeVec.end(), Smallest); - if (TVI != Other.TypeVec.end()) { - Other.TypeVec.erase(TVI); - MadeChange = true; - } - + // Okay, find the largest type in the Other set and remove it from the // current set. - MVT::SimpleValueType Largest = Other.TypeVec[0]; + MVT::SimpleValueType LargestInt = MVT::Other; + for (unsigned i = 0, e = Other.TypeVec.size(); i != e; ++i) + if (isInteger(Other.TypeVec[i])) { + LargestInt = Other.TypeVec[i]; + break; + } for (unsigned i = 1, e = Other.TypeVec.size(); i != e; ++i) - if (Other.TypeVec[i] > Largest) - Largest = Other.TypeVec[i]; - + if (isInteger(Other.TypeVec[i]) && Other.TypeVec[i] > LargestInt) + LargestInt = Other.TypeVec[i]; + + MVT::SimpleValueType LargestFP = MVT::Other; + for (unsigned i = 0, e = Other.TypeVec.size(); i != e; ++i) + if (isFloatingPoint(Other.TypeVec[i])) { + LargestFP = Other.TypeVec[i]; + break; + } + for (unsigned i = 1, e = Other.TypeVec.size(); i != e; ++i) + if (isFloatingPoint(Other.TypeVec[i]) && Other.TypeVec[i] > LargestFP) + LargestFP = Other.TypeVec[i]; + + int IntSize = 0; + int FPSize = 0; + for (SmallVector<MVT::SimpleValueType, 2>::iterator TVI = + TypeVec.begin(); + TVI != TypeVec.end(); + /* NULL */) { + if (isInteger(*TVI)) { + ++IntSize; + if (*TVI == LargestInt) { + TVI = TypeVec.erase(TVI); + --IntSize; + MadeChange = true; + continue; + } + } + else if (isFloatingPoint(*TVI)) { + ++FPSize; + if (*TVI == LargestFP) { + TVI = TypeVec.erase(TVI); + --FPSize; + MadeChange = true; + continue; + } + } + ++TVI; + } + // If this is the only type in the small set, the constraint can never be // satisfied. - if (TypeVec.size() == 1 && TypeVec[0] == Largest) + if ((hasIntegerTypes() && IntSize == 0) + || (hasFloatingPointTypes() && FPSize == 0)) TP.error("Type inference contradiction found, '" + getName() + "' has nothing smaller than '" + Other.getName()+"'!"); - - TVI = std::find(TypeVec.begin(), TypeVec.end(), Largest); - if (TVI != TypeVec.end()) { - TypeVec.erase(TVI); - MadeChange = true; - } - + return MadeChange; } @@ -406,7 +509,7 @@ bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand, if (isConcrete()) { EVT IVT = getConcrete(); IVT = IVT.getVectorElementType(); - return MadeChange | + return MadeChange | VTOperand.MergeInTypeInfo(IVT.getSimpleVT().SimpleTy, TP); } @@ -414,11 +517,11 @@ bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand, // disagree. if (!VTOperand.isConcrete()) return MadeChange; - + MVT::SimpleValueType VT = VTOperand.getConcrete(); - + TypeSet InputSet(*this); - + // Filter out all the types which don't have the right element type. for (unsigned i = 0; i != TypeVec.size(); ++i) { assert(isVector(TypeVec[i]) && "EnforceVector didn't work"); @@ -427,13 +530,43 @@ bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand, MadeChange = true; } } - + if (TypeVec.empty()) // FIXME: Really want an SMLoc here! TP.error("Type inference contradiction found, forcing '" + InputSet.getName() + "' to have a vector element"); return MadeChange; } +/// EnforceVectorSubVectorTypeIs - 'this' is now constrainted to be a +/// vector type specified by VTOperand. +bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand, + TreePattern &TP) { + // "This" must be a vector and "VTOperand" must be a vector. + bool MadeChange = false; + MadeChange |= EnforceVector(TP); + MadeChange |= VTOperand.EnforceVector(TP); + + // "This" must be larger than "VTOperand." + MadeChange |= VTOperand.EnforceSmallerThan(*this, TP); + + // If we know the vector type, it forces the scalar types to agree. + if (isConcrete()) { + EVT IVT = getConcrete(); + IVT = IVT.getVectorElementType(); + + EEVT::TypeSet EltTypeSet(IVT.getSimpleVT().SimpleTy, TP); + MadeChange |= VTOperand.EnforceVectorEltTypeIs(EltTypeSet, TP); + } else if (VTOperand.isConcrete()) { + EVT IVT = VTOperand.getConcrete(); + IVT = IVT.getVectorElementType(); + + EEVT::TypeSet EltTypeSet(IVT.getSimpleVT().SimpleTy, TP); + MadeChange |= EnforceVectorEltTypeIs(EltTypeSet, TP); + } + + return MadeChange; +} + //===----------------------------------------------------------------------===// // Helpers for working with extended types. @@ -473,18 +606,21 @@ void FindDepVars(TreePatternNode *N, MultipleUseVarSet &DepVars) { } //! Dump the dependent variable set: +#ifndef NDEBUG void DumpDepVars(MultipleUseVarSet &DepVars) { if (DepVars.empty()) { DEBUG(errs() << "<empty set>"); } else { DEBUG(errs() << "[ "); - for (MultipleUseVarSet::const_iterator i = DepVars.begin(), e = DepVars.end(); - i != e; ++i) { + for (MultipleUseVarSet::const_iterator i = DepVars.begin(), + e = DepVars.end(); i != e; ++i) { DEBUG(errs() << (*i) << " "); } DEBUG(errs() << "]"); } } +#endif + } //===----------------------------------------------------------------------===// @@ -502,7 +638,7 @@ static unsigned getPatternSize(const TreePatternNode *P, // e.g. (set R32:$dst, 0). if (P->isLeaf() && dynamic_cast<IntInit*>(P->getLeafValue())) Size += 2; - + // FIXME: This is a hack to statically increase the priority of patterns // which maps a sub-dag to a complex pattern. e.g. favors LEA over ADD. // Later we can allow complexity / cost for each pattern to be (optionally) @@ -511,12 +647,12 @@ static unsigned getPatternSize(const TreePatternNode *P, const ComplexPattern *AM = P->getComplexPatternInfo(CGP); if (AM) Size += AM->getNumOperands() * 3; - + // If this node has some predicate function that must match, it adds to the // complexity of this node. if (!P->getPredicateFns().empty()) ++Size; - + // Count children in the count if they are also nodes. for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i) { TreePatternNode *Child = P->getChild(i); @@ -524,7 +660,7 @@ static unsigned getPatternSize(const TreePatternNode *P, Child->getType(0) != MVT::Other) Size += getPatternSize(Child, CGP); else if (Child->isLeaf()) { - if (dynamic_cast<IntInit*>(Child->getLeafValue())) + if (dynamic_cast<IntInit*>(Child->getLeafValue())) Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2). else if (Child->getComplexPatternInfo(CGP)) Size += getPatternSize(Child, CGP); @@ -532,7 +668,7 @@ static unsigned getPatternSize(const TreePatternNode *P, ++Size; } } - + return Size; } @@ -573,13 +709,13 @@ std::string PatternToMatch::getPredicateCheck() const { SDTypeConstraint::SDTypeConstraint(Record *R) { OperandNo = R->getValueAsInt("OperandNum"); - + if (R->isSubClassOf("SDTCisVT")) { ConstraintType = SDTCisVT; x.SDTCisVT_Info.VT = getValueType(R->getValueAsDef("VT")); if (x.SDTCisVT_Info.VT == MVT::isVoid) throw TGError(R->getLoc(), "Cannot use 'Void' as type to SDTCisVT"); - + } else if (R->isSubClassOf("SDTCisPtrTy")) { ConstraintType = SDTCisPtrTy; } else if (R->isSubClassOf("SDTCisInt")) { @@ -593,15 +729,19 @@ SDTypeConstraint::SDTypeConstraint(Record *R) { x.SDTCisSameAs_Info.OtherOperandNum = R->getValueAsInt("OtherOperandNum"); } else if (R->isSubClassOf("SDTCisVTSmallerThanOp")) { ConstraintType = SDTCisVTSmallerThanOp; - x.SDTCisVTSmallerThanOp_Info.OtherOperandNum = + x.SDTCisVTSmallerThanOp_Info.OtherOperandNum = R->getValueAsInt("OtherOperandNum"); } else if (R->isSubClassOf("SDTCisOpSmallerThanOp")) { ConstraintType = SDTCisOpSmallerThanOp; - x.SDTCisOpSmallerThanOp_Info.BigOperandNum = + x.SDTCisOpSmallerThanOp_Info.BigOperandNum = R->getValueAsInt("BigOperandNum"); } else if (R->isSubClassOf("SDTCisEltOfVec")) { ConstraintType = SDTCisEltOfVec; x.SDTCisEltOfVec_Info.OtherOperandNum = R->getValueAsInt("OtherOpNum"); + } else if (R->isSubClassOf("SDTCisSubVecOfVec")) { + ConstraintType = SDTCisSubVecOfVec; + x.SDTCisSubVecOfVec_Info.OtherOperandNum = + R->getValueAsInt("OtherOpNum"); } else { errs() << "Unrecognized SDTypeConstraint '" << R->getName() << "'!\n"; exit(1); @@ -618,11 +758,11 @@ static TreePatternNode *getOperandNum(unsigned OpNo, TreePatternNode *N, ResNo = OpNo; return N; } - + OpNo -= NumResults; - + if (OpNo >= N->getNumChildren()) { - errs() << "Invalid operand number in type constraint " + errs() << "Invalid operand number in type constraint " << (OpNo+NumResults) << " "; N->dump(); errs() << '\n'; @@ -641,7 +781,7 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, TreePattern &TP) const { unsigned ResNo = 0; // The result number being referenced. TreePatternNode *NodeToApply = getOperandNum(OperandNo, N, NodeInfo, ResNo); - + switch (ConstraintType) { default: assert(0 && "Unknown constraint type!"); case SDTCisVT: @@ -676,9 +816,9 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, TP.error(N->getOperator()->getName() + " expects a VT operand!"); MVT::SimpleValueType VT = getValueType(static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef()); - + EEVT::TypeSet TypeListTmp(VT, TP); - + unsigned OResNo = 0; TreePatternNode *OtherNode = getOperandNum(x.SDTCisVTSmallerThanOp_Info.OtherOperandNum, N, NodeInfo, @@ -699,13 +839,24 @@ bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N, TreePatternNode *VecOperand = getOperandNum(x.SDTCisEltOfVec_Info.OtherOperandNum, N, NodeInfo, VResNo); - + // Filter vector types out of VecOperand that don't have the right element // type. return VecOperand->getExtType(VResNo). EnforceVectorEltTypeIs(NodeToApply->getExtType(ResNo), TP); } - } + case SDTCisSubVecOfVec: { + unsigned VResNo = 0; + TreePatternNode *BigVecOperand = + getOperandNum(x.SDTCisSubVecOfVec_Info.OtherOperandNum, N, NodeInfo, + VResNo); + + // Filter vector types out of BigVecOperand that don't have the + // right subvector type. + return BigVecOperand->getExtType(VResNo). + EnforceVectorSubVectorTypeIs(NodeToApply->getExtType(ResNo), TP); + } + } return false; } @@ -718,7 +869,7 @@ SDNodeInfo::SDNodeInfo(Record *R) : Def(R) { Record *TypeProfile = R->getValueAsDef("TypeProfile"); NumResults = TypeProfile->getValueAsInt("NumResults"); NumOperands = TypeProfile->getValueAsInt("NumOperands"); - + // Parse the properties. Properties = 0; std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties"); @@ -729,12 +880,12 @@ SDNodeInfo::SDNodeInfo(Record *R) : Def(R) { Properties |= 1 << SDNPAssociative; } else if (PropList[i]->getName() == "SDNPHasChain") { Properties |= 1 << SDNPHasChain; - } else if (PropList[i]->getName() == "SDNPOutFlag") { - Properties |= 1 << SDNPOutFlag; - } else if (PropList[i]->getName() == "SDNPInFlag") { - Properties |= 1 << SDNPInFlag; - } else if (PropList[i]->getName() == "SDNPOptInFlag") { - Properties |= 1 << SDNPOptInFlag; + } else if (PropList[i]->getName() == "SDNPOutGlue") { + Properties |= 1 << SDNPOutGlue; + } else if (PropList[i]->getName() == "SDNPInGlue") { + Properties |= 1 << SDNPInGlue; + } else if (PropList[i]->getName() == "SDNPOptInGlue") { + Properties |= 1 << SDNPOptInGlue; } else if (PropList[i]->getName() == "SDNPMayStore") { Properties |= 1 << SDNPMayStore; } else if (PropList[i]->getName() == "SDNPMayLoad") { @@ -751,8 +902,8 @@ SDNodeInfo::SDNodeInfo(Record *R) : Def(R) { exit(1); } } - - + + // Parse the type constraints. std::vector<Record*> ConstraintList = TypeProfile->getValueAsListOfDefs("Constraints"); @@ -767,12 +918,12 @@ MVT::SimpleValueType SDNodeInfo::getKnownType(unsigned ResNo) const { assert(NumResults <= 1 && "We only work with nodes with zero or one result so far!"); assert(ResNo == 0 && "Only handles single result nodes so far"); - + for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i) { // Make sure that this applies to the correct node result. if (TypeConstraints[i].OperandNo >= NumResults) // FIXME: need value # continue; - + switch (TypeConstraints[i].ConstraintType) { default: break; case SDTypeConstraint::SDTCisVT: @@ -799,20 +950,20 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { if (Operator->getName() == "set" || Operator->getName() == "implicit") return 0; // All return nothing. - + if (Operator->isSubClassOf("Intrinsic")) return CDP.getIntrinsic(Operator).IS.RetVTs.size(); - + if (Operator->isSubClassOf("SDNode")) return CDP.getSDNodeInfo(Operator).getNumResults(); - + if (Operator->isSubClassOf("PatFrag")) { // If we've already parsed this pattern fragment, get it. Otherwise, handle // the forward reference case where one pattern fragment references another // before it is processed. if (TreePattern *PFRec = CDP.getPatternFragmentIfRead(Operator)) return PFRec->getOnlyTree()->getNumTypes(); - + // Get the result tree. DagInit *Tree = Operator->getValueAsDag("Fragment"); Record *Op = 0; @@ -821,22 +972,22 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { assert(Op && "Invalid Fragment"); return GetNumNodeResults(Op, CDP); } - + if (Operator->isSubClassOf("Instruction")) { CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(Operator); // FIXME: Should allow access to all the results here. - unsigned NumDefsToAdd = InstInfo.NumDefs ? 1 : 0; - + unsigned NumDefsToAdd = InstInfo.Operands.NumDefs ? 1 : 0; + // Add on one implicit def if it has a resolvable type. if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other) ++NumDefsToAdd; return NumDefsToAdd; } - + if (Operator->isSubClassOf("SDNodeXForm")) return 1; // FIXME: Generalize SDNodeXForm - + Operator->dump(); errs() << "Unhandled node in GetNumNodeResults\n"; exit(1); @@ -862,7 +1013,7 @@ void TreePatternNode::print(raw_ostream &OS) const { } OS << ")"; } - + for (unsigned i = 0, e = PredicateFns.size(); i != e; ++i) OS << "<<P:" << PredicateFns[i] << ">>"; if (TransformFn) @@ -900,7 +1051,7 @@ bool TreePatternNode::isIsomorphicTo(const TreePatternNode *N, } return getLeafValue() == N->getLeafValue(); } - + if (N->getOperator() != getOperator() || N->getNumChildren() != getNumChildren()) return false; for (unsigned i = 0, e = getNumChildren(); i != e; ++i) @@ -944,7 +1095,7 @@ void TreePatternNode::RemoveAllTypes() { void TreePatternNode:: SubstituteFormalArguments(std::map<std::string, TreePatternNode*> &ArgMap) { if (isLeaf()) return; - + for (unsigned i = 0, e = getNumChildren(); i != e; ++i) { TreePatternNode *Child = getChild(i); if (Child->isLeaf()) { @@ -972,7 +1123,7 @@ SubstituteFormalArguments(std::map<std::string, TreePatternNode*> &ArgMap) { TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { if (isLeaf()) return this; // nothing to do. Record *Op = getOperator(); - + if (!Op->isSubClassOf("PatFrag")) { // Just recursively inline children nodes. for (unsigned i = 0, e = getNumChildren(); i != e; ++i) { @@ -991,7 +1142,7 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { // Otherwise, we found a reference to a fragment. First, look up its // TreePattern record. TreePattern *Frag = TP.getDAGPatterns().getPatternFragment(Op); - + // Verify that we are passing the right number of operands. if (Frag->getNumArgs() != Children.size()) TP.error("'" + Op->getName() + "' fragment requires " + @@ -1009,10 +1160,10 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { std::map<std::string, TreePatternNode*> ArgMap; for (unsigned i = 0, e = Frag->getNumArgs(); i != e; ++i) ArgMap[Frag->getArgName(i)] = getChild(i)->InlinePatternFragments(TP); - + FragTree->SubstituteFormalArguments(ArgMap); } - + FragTree->setName(getName()); for (unsigned i = 0, e = Types.size(); i != e; ++i) FragTree->UpdateNodeType(i, getExtType(i), TP); @@ -1023,7 +1174,7 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { // Get a new copy of this fragment to stitch into here. //delete this; // FIXME: implement refcounting! - + // The fragment we inlined could have recursive inlining that is needed. See // if there are any pattern fragments in it and inline them as needed. return FragTree->InlinePatternFragments(TP); @@ -1038,21 +1189,21 @@ static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo, // Check to see if this is a register or a register class. if (R->isSubClassOf("RegisterClass")) { assert(ResNo == 0 && "Regclass ref only has one result!"); - if (NotRegisters) + if (NotRegisters) return EEVT::TypeSet(); // Unknown. const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); return EEVT::TypeSet(T.getRegisterClass(R).getValueTypes()); } - + if (R->isSubClassOf("PatFrag")) { assert(ResNo == 0 && "FIXME: PatFrag with multiple results?"); // Pattern fragment types will be resolved when they are inlined. return EEVT::TypeSet(); // Unknown. } - + if (R->isSubClassOf("Register")) { assert(ResNo == 0 && "Registers only produce one result!"); - if (NotRegisters) + if (NotRegisters) return EEVT::TypeSet(); // Unknown. const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo(); return EEVT::TypeSet(T.getRegisterVTs(R)); @@ -1062,16 +1213,16 @@ static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo, assert(ResNo == 0 && "SubRegisterIndices only produce one result!"); return EEVT::TypeSet(); } - + if (R->isSubClassOf("ValueType") || R->isSubClassOf("CondCode")) { assert(ResNo == 0 && "This node only has one result!"); // Using a VTSDNode or CondCodeSDNode. return EEVT::TypeSet(MVT::Other, TP); } - + if (R->isSubClassOf("ComplexPattern")) { assert(ResNo == 0 && "FIXME: ComplexPattern with multiple results?"); - if (NotRegisters) + if (NotRegisters) return EEVT::TypeSet(); // Unknown. return EEVT::TypeSet(TP.getDAGPatterns().getComplexPattern(R).getValueType(), TP); @@ -1080,13 +1231,13 @@ static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo, assert(ResNo == 0 && "Regclass can only have one result!"); return EEVT::TypeSet(MVT::iPTR, TP); } - + if (R->getName() == "node" || R->getName() == "srcvalue" || R->getName() == "zero_reg") { // Placeholder. return EEVT::TypeSet(); // Unknown. } - + TP.error("Unknown node flavor used in pattern: " + R->getName()); return EEVT::TypeSet(MVT::Other, TP); } @@ -1100,8 +1251,8 @@ getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const { getOperator() != CDP.get_intrinsic_w_chain_sdnode() && getOperator() != CDP.get_intrinsic_wo_chain_sdnode()) return 0; - - unsigned IID = + + unsigned IID = dynamic_cast<IntInit*>(getChild(0)->getLeafValue())->getValue(); return &CDP.getIntrinsicInfo(IID); } @@ -1111,7 +1262,7 @@ getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const { 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()); @@ -1126,10 +1277,10 @@ bool TreePatternNode::NodeHasProperty(SDNP Property, return CP->hasProperty(Property); return false; } - + Record *Operator = getOperator(); if (!Operator->isSubClassOf("SDNode")) return false; - + return CGP.getSDNodeInfo(Operator).hasProperty(Property); } @@ -1146,7 +1297,7 @@ bool TreePatternNode::TreeHasProperty(SDNP Property, if (getChild(i)->TreeHasProperty(Property, CGP)) return true; return false; -} +} /// isCommutativeIntrinsic - Return true if the node corresponds to a /// commutative intrinsic. @@ -1173,27 +1324,27 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { NotRegisters, TP), TP); return MadeChange; } - + if (IntInit *II = dynamic_cast<IntInit*>(getLeafValue())) { assert(Types.size() == 1 && "Invalid IntInit"); - + // Int inits are always integers. :) bool MadeChange = Types[0].EnforceInteger(TP); - + if (!Types[0].isConcrete()) return MadeChange; - + MVT::SimpleValueType VT = getType(0); if (VT == MVT::iPTR || VT == MVT::iPTRAny) return MadeChange; - + unsigned Size = EVT(VT).getSizeInBits(); // Make sure that the value is representable for this type. if (Size >= 32) return MadeChange; - + int Val = (II->getValue() << (32-Size)) >> (32-Size); if (Val == II->getValue()) return MadeChange; - + // If sign-extended doesn't fit, does it fit as unsigned? unsigned ValueMask; unsigned UnsignedVal; @@ -1202,34 +1353,34 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { if ((ValueMask & UnsignedVal) == UnsignedVal) return MadeChange; - + TP.error("Integer value '" + itostr(II->getValue())+ "' is out of range for type '" + getEnumName(getType(0)) + "'!"); return MadeChange; } return false; } - + // special handling for set, which isn't really an SDNode. if (getOperator()->getName() == "set") { assert(getNumTypes() == 0 && "Set doesn't produce a value"); assert(getNumChildren() >= 2 && "Missing RHS of a set?"); unsigned NC = getNumChildren(); - + TreePatternNode *SetVal = getChild(NC-1); bool MadeChange = SetVal->ApplyTypeConstraints(TP, NotRegisters); for (unsigned i = 0; i < NC-1; ++i) { TreePatternNode *Child = getChild(i); MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters); - + // Types of operands must match. MadeChange |= Child->UpdateNodeType(0, SetVal->getExtType(i), TP); MadeChange |= SetVal->UpdateNodeType(i, Child->getExtType(0), TP); } return MadeChange; } - + if (getOperator()->getName() == "implicit") { assert(getNumTypes() == 0 && "Node doesn't produce a value"); @@ -1238,15 +1389,15 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { MadeChange = getChild(i)->ApplyTypeConstraints(TP, NotRegisters); return MadeChange; } - + if (getOperator()->getName() == "COPY_TO_REGCLASS") { bool MadeChange = false; MadeChange |= getChild(0)->ApplyTypeConstraints(TP, NotRegisters); MadeChange |= getChild(1)->ApplyTypeConstraints(TP, NotRegisters); - + assert(getChild(0)->getNumTypes() == 1 && getChild(1)->getNumTypes() == 1 && "Unhandled case"); - + // child #1 of COPY_TO_REGCLASS should be a register class. We don't care // what type it gets, so if it didn't get a concrete type just give it the // first viable type from the reg class. @@ -1257,14 +1408,14 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { } return MadeChange; } - + if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) { bool MadeChange = false; // Apply the result type to the node. unsigned NumRetVTs = Int->IS.RetVTs.size(); unsigned NumParamVTs = Int->IS.ParamVTs.size(); - + for (unsigned i = 0, e = NumRetVTs; i != e; ++i) MadeChange |= UpdateNodeType(i, Int->IS.RetVTs[i], TP); @@ -1275,46 +1426,46 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { // Apply type info to the intrinsic ID. MadeChange |= getChild(0)->UpdateNodeType(0, MVT::iPTR, TP); - + for (unsigned i = 0, e = getNumChildren()-1; i != e; ++i) { MadeChange |= getChild(i+1)->ApplyTypeConstraints(TP, NotRegisters); - + MVT::SimpleValueType OpVT = Int->IS.ParamVTs[i]; assert(getChild(i+1)->getNumTypes() == 1 && "Unhandled case"); MadeChange |= getChild(i+1)->UpdateNodeType(0, OpVT, TP); } return MadeChange; } - + if (getOperator()->isSubClassOf("SDNode")) { const SDNodeInfo &NI = CDP.getSDNodeInfo(getOperator()); - + // Check that the number of operands is sane. Negative operands -> varargs. if (NI.getNumOperands() >= 0 && getNumChildren() != (unsigned)NI.getNumOperands()) TP.error(getOperator()->getName() + " node requires exactly " + itostr(NI.getNumOperands()) + " operands!"); - + bool MadeChange = NI.ApplyTypeConstraints(this, TP); for (unsigned i = 0, e = getNumChildren(); i != e; ++i) MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters); return MadeChange; } - + if (getOperator()->isSubClassOf("Instruction")) { const DAGInstruction &Inst = CDP.getInstruction(getOperator()); CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(getOperator()); - + bool MadeChange = false; // Apply the result types to the node, these come from the things in the // (outs) list of the instruction. // FIXME: Cap at one result so far. - unsigned NumResultsToAdd = InstInfo.NumDefs ? 1 : 0; + unsigned NumResultsToAdd = InstInfo.Operands.NumDefs ? 1 : 0; for (unsigned ResNo = 0; ResNo != NumResultsToAdd; ++ResNo) { Record *ResultNode = Inst.getResult(ResNo); - + if (ResultNode->isSubClassOf("PointerLikeRegClass")) { MadeChange |= UpdateNodeType(ResNo, MVT::iPTR, TP); } else if (ResultNode->getName() == "unknown") { @@ -1322,26 +1473,26 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { } else { assert(ResultNode->isSubClassOf("RegisterClass") && "Operands should be register classes!"); - const CodeGenRegisterClass &RC = + const CodeGenRegisterClass &RC = CDP.getTargetInfo().getRegisterClass(ResultNode); MadeChange |= UpdateNodeType(ResNo, RC.getValueTypes(), TP); } } - + // If the instruction has implicit defs, we apply the first one as a result. // FIXME: This sucks, it should apply all implicit defs. if (!InstInfo.ImplicitDefs.empty()) { unsigned ResNo = NumResultsToAdd; - + // FIXME: Generalize to multiple possible types and multiple possible // ImplicitDefs. MVT::SimpleValueType VT = InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()); - + if (VT != MVT::Other) MadeChange |= UpdateNodeType(ResNo, VT, TP); } - + // If this is an INSERT_SUBREG, constrain the source and destination VTs to // be the same. if (getOperator()->getName() == "INSERT_SUBREG") { @@ -1353,7 +1504,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { unsigned ChildNo = 0; for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) { Record *OperandNode = Inst.getOperand(i); - + // If the instruction expects a predicate or optional def operand, we // codegen this by setting the operand to it's default value if it has a // non-empty DefaultOps field. @@ -1361,18 +1512,18 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { OperandNode->isSubClassOf("OptionalDefOperand")) && !CDP.getDefaultOperand(OperandNode).DefaultOps.empty()) continue; - + // Verify that we didn't run out of provided operands. if (ChildNo >= getNumChildren()) TP.error("Instruction '" + getOperator()->getName() + "' expects more operands than were provided."); - + MVT::SimpleValueType VT; TreePatternNode *Child = getChild(ChildNo++); unsigned ChildResNo = 0; // Instructions always use res #0 of their op. - + if (OperandNode->isSubClassOf("RegisterClass")) { - const CodeGenRegisterClass &RC = + const CodeGenRegisterClass &RC = CDP.getTargetInfo().getRegisterClass(OperandNode); MadeChange |= Child->UpdateNodeType(ChildResNo, RC.getValueTypes(), TP); } else if (OperandNode->isSubClassOf("Operand")) { @@ -1392,12 +1543,12 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { if (ChildNo != getNumChildren()) TP.error("Instruction '" + getOperator()->getName() + "' was provided too many operands!"); - + return MadeChange; } - + assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!"); - + // Node transforms always take one operand. if (getNumChildren() != 1) TP.error("Node transform '" + getOperator()->getName() + @@ -1405,7 +1556,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { bool MadeChange = getChild(0)->ApplyTypeConstraints(TP, NotRegisters); - + // If either the output or input of the xform does not have exact // type info. We assume they must be the same. Otherwise, it is perfectly // legal to transform from one type to a completely different type. @@ -1435,7 +1586,7 @@ static bool OnlyOnRHSOfCommutative(TreePatternNode *N) { /// used as a sanity check for .td files (to prevent people from writing stuff /// that can never possibly work), and to prevent the pattern permuter from /// generating stuff that is useless. -bool TreePatternNode::canPatternMatch(std::string &Reason, +bool TreePatternNode::canPatternMatch(std::string &Reason, const CodeGenDAGPatterns &CDP) { if (isLeaf()) return true; @@ -1449,7 +1600,7 @@ bool TreePatternNode::canPatternMatch(std::string &Reason, // TODO: return true; } - + // If this node is a commutative operator, check that the LHS isn't an // immediate. const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(getOperator()); @@ -1466,7 +1617,7 @@ bool TreePatternNode::canPatternMatch(std::string &Reason, } } } - + return true; } @@ -1506,7 +1657,7 @@ void TreePattern::ComputeNamedNodes() { void TreePattern::ComputeNamedNodes(TreePatternNode *N) { if (!N->getName().empty()) NamedNodes[N->getName()].push_back(N); - + for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) ComputeNamedNodes(N->getChild(i)); } @@ -1515,7 +1666,7 @@ void TreePattern::ComputeNamedNodes(TreePatternNode *N) { TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ if (DefInit *DI = dynamic_cast<DefInit*>(TheInit)) { Record *R = DI->getDef(); - + // Direct reference to a leaf DagNode or PatFrag? Turn it into a // TreePatternNode if its own. For example: /// (foo GPR, imm) -> (foo GPR, (imm)) @@ -1523,7 +1674,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ return ParseTreePattern(new DagInit(DI, "", std::vector<std::pair<Init*, std::string> >()), OpName); - + // Input argument? TreePatternNode *Res = new TreePatternNode(DI, 1); if (R->getName() == "node" && !OpName.empty()) { @@ -1535,13 +1686,13 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ Res->setName(OpName); return Res; } - + if (IntInit *II = dynamic_cast<IntInit*>(TheInit)) { if (!OpName.empty()) error("Constant int argument should not have a name!"); return new TreePatternNode(II, 1); } - + if (BitsInit *BI = dynamic_cast<BitsInit*>(TheInit)) { // Turn this into an IntInit. Init *II = BI->convertInitializerTo(new IntRecTy()); @@ -1558,34 +1709,34 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ DefInit *OpDef = dynamic_cast<DefInit*>(Dag->getOperator()); if (!OpDef) error("Pattern has unexpected operator type!"); Record *Operator = OpDef->getDef(); - + if (Operator->isSubClassOf("ValueType")) { // If the operator is a ValueType, then this must be "type cast" of a leaf // node. if (Dag->getNumArgs() != 1) error("Type cast only takes one operand!"); - + TreePatternNode *New = ParseTreePattern(Dag->getArg(0), Dag->getArgName(0)); - + // Apply the type cast. assert(New->getNumTypes() == 1 && "FIXME: Unhandled"); New->UpdateNodeType(0, getValueType(Operator), *this); - + if (!OpName.empty()) error("ValueType cast should not have a name!"); return New; } - + // Verify that this is something that makes sense for an operator. - if (!Operator->isSubClassOf("PatFrag") && + if (!Operator->isSubClassOf("PatFrag") && !Operator->isSubClassOf("SDNode") && - !Operator->isSubClassOf("Instruction") && + !Operator->isSubClassOf("Instruction") && !Operator->isSubClassOf("SDNodeXForm") && !Operator->isSubClassOf("Intrinsic") && Operator->getName() != "set" && Operator->getName() != "implicit") error("Unrecognized node '" + Operator->getName() + "'!"); - + // Check to see if this is something that is illegal in an input pattern. if (isInputPattern) { if (Operator->isSubClassOf("Instruction") || @@ -1594,7 +1745,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ } else { if (Operator->isSubClassOf("Intrinsic")) error("Cannot use '" + Operator->getName() + "' in an output pattern!"); - + if (Operator->isSubClassOf("SDNode") && Operator->getName() != "imm" && Operator->getName() != "fpimm" && @@ -1609,15 +1760,15 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ Operator->getName() != "vt") error("Cannot use '" + Operator->getName() + "' in an output pattern!"); } - + std::vector<TreePatternNode*> Children; // Parse all the operands. for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) Children.push_back(ParseTreePattern(Dag->getArg(i), Dag->getArgName(i))); - + // If the operator is an intrinsic, then this is just syntactic sugar for for - // (intrinsic_* <number>, ..children..). Pick the right intrinsic node, and + // (intrinsic_* <number>, ..children..). Pick the right intrinsic node, and // convert the intrinsic name to a number. if (Operator->isSubClassOf("Intrinsic")) { const CodeGenIntrinsic &Int = getDAGPatterns().getIntrinsic(Operator); @@ -1632,15 +1783,15 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ Operator = getDAGPatterns().get_intrinsic_w_chain_sdnode(); else // Otherwise, no chain. Operator = getDAGPatterns().get_intrinsic_wo_chain_sdnode(); - + TreePatternNode *IIDNode = new TreePatternNode(new IntInit(IID), 1); Children.insert(Children.begin(), IIDNode); } - + unsigned NumResults = GetNumNodeResults(Operator, CDP); TreePatternNode *Result = new TreePatternNode(Operator, Children, NumResults); Result->setName(OpName); - + if (!Dag->getName().empty()) { assert(Result->getName().empty()); Result->setName(Dag->getName()); @@ -1698,10 +1849,10 @@ InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) { } // If there are constraints on our named nodes, apply them. - for (StringMap<SmallVector<TreePatternNode*,1> >::iterator + for (StringMap<SmallVector<TreePatternNode*,1> >::iterator I = NamedNodes.begin(), E = NamedNodes.end(); I != E; ++I) { SmallVectorImpl<TreePatternNode*> &Nodes = I->second; - + // If we have input named node types, propagate their types to the named // values here. if (InNamedTypes) { @@ -1724,7 +1875,7 @@ InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) { if (DI && DI->getDef()->isSubClassOf("RegisterClass")) continue; } - + assert(Nodes[i]->getNumTypes() == 1 && InNodes[0]->getNumTypes() == 1 && "FIXME: cannot name multiple result nodes yet"); @@ -1732,7 +1883,7 @@ InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) { *this); } } - + // If there are multiple nodes with the same name, they must all have the // same type. if (I->second.size() > 1) { @@ -1740,14 +1891,14 @@ InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) { TreePatternNode *N1 = Nodes[i], *N2 = Nodes[i+1]; assert(N1->getNumTypes() == 1 && N2->getNumTypes() == 1 && "FIXME: cannot name multiple result nodes yet"); - + MadeChange |= N1->UpdateNodeType(0, N2->getExtType(0), *this); MadeChange |= N2->UpdateNodeType(0, N1->getExtType(0), *this); } } } } - + bool HasUnresolvedTypes = false; for (unsigned i = 0, e = Trees.size(); i != e; ++i) HasUnresolvedTypes |= Trees[i]->ContainsUnresolvedType(); @@ -1763,7 +1914,7 @@ void TreePattern::print(raw_ostream &OS) const { OS << ")"; } OS << ": "; - + if (Trees.size() > 1) OS << "[\n"; for (unsigned i = 0, e = Trees.size(); i != e; ++i) { @@ -1782,7 +1933,9 @@ void TreePattern::dump() const { print(errs()); } // CodeGenDAGPatterns implementation // -CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : Records(R) { +CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : + Records(R), Target(R) { + Intrinsics = LoadIntrinsics(Records, false); TgtIntrinsics = LoadIntrinsics(Records, true); ParseNodeInfo(); @@ -1792,7 +1945,7 @@ CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : Records(R) { ParseDefaultOperands(); ParseInstructions(); ParsePatterns(); - + // Generate variants. For example, commutative patterns can match // multiple ways. Add them to PatternsToMatch as well. GenerateVariants(); @@ -1863,20 +2016,20 @@ void CodeGenDAGPatterns::ParseComplexPatterns() { /// void CodeGenDAGPatterns::ParsePatternFragments() { std::vector<Record*> Fragments = Records.getAllDerivedDefinitions("PatFrag"); - + // First step, parse all of the fragments. for (unsigned i = 0, e = Fragments.size(); i != e; ++i) { DagInit *Tree = Fragments[i]->getValueAsDag("Fragment"); TreePattern *P = new TreePattern(Fragments[i], Tree, true, *this); PatternFragments[Fragments[i]] = P; - + // Validate the argument list, converting it to set, to discard duplicates. std::vector<std::string> &Args = P->getArgList(); std::set<std::string> OperandsSet(Args.begin(), Args.end()); - + if (OperandsSet.count("")) P->error("Cannot have unnamed 'node' values in pattern fragment!"); - + // Parse the operands list. DagInit *OpsList = Fragments[i]->getValueAsDag("Operands"); DefInit *OpsOp = dynamic_cast<DefInit*>(OpsList->getOperator()); @@ -1887,8 +2040,8 @@ void CodeGenDAGPatterns::ParsePatternFragments() { OpsOp->getDef()->getName() != "outs" && OpsOp->getDef()->getName() != "ins")) P->error("Operands list should start with '(ops ... '!"); - - // Copy over the arguments. + + // Copy over the arguments. Args.clear(); for (unsigned j = 0, e = OpsList->getNumArgs(); j != e; ++j) { if (!dynamic_cast<DefInit*>(OpsList->getArg(j)) || @@ -1903,7 +2056,7 @@ void CodeGenDAGPatterns::ParsePatternFragments() { OperandsSet.erase(OpsList->getArgName(j)); Args.push_back(OpsList->getArgName(j)); } - + if (!OperandsSet.empty()) P->error("Operands list does not contain an entry for operand '" + *OperandsSet.begin() + "'!"); @@ -1913,20 +2066,20 @@ void CodeGenDAGPatterns::ParsePatternFragments() { std::string Code = Fragments[i]->getValueAsCode("Predicate"); if (!Code.empty()) P->getOnlyTree()->addPredicateFn("Predicate_"+Fragments[i]->getName()); - + // If there is a node transformation corresponding to this, keep track of // it. Record *Transform = Fragments[i]->getValueAsDef("OperandTransform"); if (!getSDNodeTransform(Transform).second.empty()) // not noop xform? P->getOnlyTree()->setTransformFn(Transform); } - + // Now that we've parsed all of the tree fragments, do a closure on them so // that there are not references to PatFrags left inside of them. for (unsigned i = 0, e = Fragments.size(); i != e; ++i) { TreePattern *ThePat = PatternFragments[Fragments[i]]; ThePat->InlinePatternFragments(); - + // Infer as many types as possible. Don't worry about it if we don't infer // all of them, some may depend on the inputs of the pattern. try { @@ -1937,7 +2090,7 @@ void CodeGenDAGPatterns::ParsePatternFragments() { // actually used by instructions, the type consistency error will be // reported there. } - + // If debugging, print out the pattern fragment result. DEBUG(ThePat->dump()); } @@ -1951,11 +2104,11 @@ void CodeGenDAGPatterns::ParseDefaultOperands() { // Find some SDNode. assert(!SDNodes.empty() && "No SDNodes parsed?"); Init *SomeSDNode = new DefInit(SDNodes.begin()->first); - + for (unsigned iter = 0; iter != 2; ++iter) { for (unsigned i = 0, e = DefaultOps[iter].size(); i != e; ++i) { DagInit *DefaultInfo = DefaultOps[iter][i]->getValueAsDag("DefaultOps"); - + // Clone the DefaultInfo dag node, changing the operator from 'ops' to // SomeSDnode so that we can parse this. std::vector<std::pair<Init*, std::string> > Ops; @@ -1963,20 +2116,20 @@ void CodeGenDAGPatterns::ParseDefaultOperands() { Ops.push_back(std::make_pair(DefaultInfo->getArg(op), DefaultInfo->getArgName(op))); DagInit *DI = new DagInit(SomeSDNode, "", Ops); - + // Create a TreePattern to parse this. TreePattern P(DefaultOps[iter][i], DI, false, *this); assert(P.getNumTrees() == 1 && "This ctor can only produce one tree!"); // Copy the operands over into a DAGDefaultOperand. DAGDefaultOperand DefaultOpInfo; - + TreePatternNode *T = P.getTree(0); for (unsigned op = 0, e = T->getNumChildren(); op != e; ++op) { TreePatternNode *TPN = T->getChild(op); while (TPN->ApplyTypeConstraints(P, false)) /* Resolve all types */; - + if (TPN->ContainsUnresolvedType()) { if (iter == 0) throw "Value #" + utostr(i) + " of PredicateOperand '" + @@ -2033,7 +2186,7 @@ static bool HandleUse(TreePattern *I, TreePatternNode *Pat, assert(Slot->getNumChildren() == 0 && "can't be a use with children!"); SlotRec = Slot->getOperator(); } - + // Ensure that the inputs agree if we've already seen this input. if (Rec != SlotRec) I->error("All $" + Pat->getName() + " inputs must agree with each other"); @@ -2056,13 +2209,13 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, I->error("Cannot specify a transform function for a non-input value!"); return; } - + if (Pat->getOperator()->getName() == "implicit") { for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) { TreePatternNode *Dest = Pat->getChild(i); if (!Dest->isLeaf()) I->error("implicitly defined value should be a register!"); - + DefInit *Val = dynamic_cast<DefInit*>(Dest->getLeafValue()); if (!Val || !Val->getDef()->isSubClassOf("Register")) I->error("implicitly defined value should be a register!"); @@ -2070,7 +2223,7 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, } return; } - + if (Pat->getOperator()->getName() != "set") { // If this is not a set, verify that the children nodes are not void typed, // and recurse. @@ -2080,30 +2233,30 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, FindPatternInputsAndOutputs(I, Pat->getChild(i), InstInputs, InstResults, InstImpResults); } - + // If this is a non-leaf node with no children, treat it basically as if // it were a leaf. This handles nodes like (imm). bool isUse = HandleUse(I, Pat, InstInputs); - + if (!isUse && Pat->getTransformFn()) I->error("Cannot specify a transform function for a non-input value!"); return; } - + // Otherwise, this is a set, validate and collect instruction results. if (Pat->getNumChildren() == 0) I->error("set requires operands!"); - + if (Pat->getTransformFn()) I->error("Cannot specify a transform function on a set node!"); - + // Check the set destinations. unsigned NumDests = Pat->getNumChildren()-1; for (unsigned i = 0; i != NumDests; ++i) { TreePatternNode *Dest = Pat->getChild(i); if (!Dest->isLeaf()) I->error("set destination should be a register!"); - + DefInit *Val = dynamic_cast<DefInit*>(Dest->getLeafValue()); if (!Val) I->error("set destination should be a register!"); @@ -2121,7 +2274,7 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, I->error("set destination should be a register!"); } } - + // Verify and collect info from the computation. FindPatternInputsAndOutputs(I, Pat->getChild(NumDests), InstInputs, InstResults, InstImpResults); @@ -2254,8 +2407,8 @@ static void InferFromPattern(const CodeGenInstruction &Inst, "which already inferred this.\n", Inst.TheDef->getName().c_str()); HasSideEffects = true; } - - if (Inst.isVariadic) + + if (Inst.Operands.isVariadic) IsVariadic = true; // Can warn if we want. } @@ -2264,64 +2417,64 @@ static void InferFromPattern(const CodeGenInstruction &Inst, /// resolved instructions. void CodeGenDAGPatterns::ParseInstructions() { std::vector<Record*> Instrs = Records.getAllDerivedDefinitions("Instruction"); - + for (unsigned i = 0, e = Instrs.size(); i != e; ++i) { ListInit *LI = 0; - + if (dynamic_cast<ListInit*>(Instrs[i]->getValueInit("Pattern"))) LI = Instrs[i]->getValueAsListInit("Pattern"); - + // If there is no pattern, only collect minimal information about the // instruction for its operand list. We have to assume that there is one // result, as we have no detailed info. if (!LI || LI->getSize() == 0) { std::vector<Record*> Results; std::vector<Record*> Operands; - + CodeGenInstruction &InstInfo = Target.getInstruction(Instrs[i]); - if (InstInfo.OperandList.size() != 0) { - if (InstInfo.NumDefs == 0) { + if (InstInfo.Operands.size() != 0) { + if (InstInfo.Operands.NumDefs == 0) { // These produce no results - for (unsigned j = 0, e = InstInfo.OperandList.size(); j < e; ++j) - Operands.push_back(InstInfo.OperandList[j].Rec); + for (unsigned j = 0, e = InstInfo.Operands.size(); j < e; ++j) + Operands.push_back(InstInfo.Operands[j].Rec); } else { // Assume the first operand is the result. - Results.push_back(InstInfo.OperandList[0].Rec); - + Results.push_back(InstInfo.Operands[0].Rec); + // The rest are inputs. - for (unsigned j = 1, e = InstInfo.OperandList.size(); j < e; ++j) - Operands.push_back(InstInfo.OperandList[j].Rec); + for (unsigned j = 1, e = InstInfo.Operands.size(); j < e; ++j) + Operands.push_back(InstInfo.Operands[j].Rec); } } - + // Create and insert the instruction. std::vector<Record*> ImpResults; - Instructions.insert(std::make_pair(Instrs[i], + Instructions.insert(std::make_pair(Instrs[i], DAGInstruction(0, Results, Operands, ImpResults))); continue; // no pattern. } - + // Parse the instruction. TreePattern *I = new TreePattern(Instrs[i], LI, true, *this); // Inline pattern fragments into it. I->InlinePatternFragments(); - + // Infer as many types as possible. If we cannot infer all of them, we can // never do anything with this instruction pattern: report it to the user. if (!I->InferAllTypes()) I->error("Could not infer all types in pattern!"); - - // InstInputs - Keep track of all of the inputs of the instruction, along + + // InstInputs - Keep track of all of the inputs of the instruction, along // with the record they are declared as. std::map<std::string, TreePatternNode*> InstInputs; - + // InstResults - Keep track of all the virtual registers that are 'set' // in the instruction, including what reg class they are. std::map<std::string, TreePatternNode*> InstResults; std::vector<Record*> InstImpResults; - + // Verify that the top-level forms in the instruction are of void type, and // fill in the InstResults map. for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) { @@ -2348,29 +2501,29 @@ void CodeGenDAGPatterns::ParseInstructions() { std::vector<Record*> Results; TreePatternNode *Res0Node = 0; for (unsigned i = 0; i != NumResults; ++i) { - if (i == CGI.OperandList.size()) + if (i == CGI.Operands.size()) I->error("'" + InstResults.begin()->first + "' set but does not appear in operand list!"); - const std::string &OpName = CGI.OperandList[i].Name; - + const std::string &OpName = CGI.Operands[i].Name; + // Check that it exists in InstResults. TreePatternNode *RNode = InstResults[OpName]; if (RNode == 0) I->error("Operand $" + OpName + " does not exist in operand list!"); - + if (i == 0) Res0Node = RNode; Record *R = dynamic_cast<DefInit*>(RNode->getLeafValue())->getDef(); if (R == 0) I->error("Operand $" + OpName + " should be a set destination: all " "outputs must occur before inputs in operand list!"); - - if (CGI.OperandList[i].Rec != R) + + if (CGI.Operands[i].Rec != R) I->error("Operand $" + OpName + " class mismatch!"); - + // Remember the return type. - Results.push_back(CGI.OperandList[i].Rec); - + Results.push_back(CGI.Operands[i].Rec); + // Okay, this one checks out. InstResults.erase(OpName); } @@ -2381,8 +2534,8 @@ void CodeGenDAGPatterns::ParseInstructions() { std::vector<TreePatternNode*> ResultNodeOperands; std::vector<Record*> Operands; - for (unsigned i = NumResults, e = CGI.OperandList.size(); i != e; ++i) { - CodeGenInstruction::OperandInfo &Op = CGI.OperandList[i]; + for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) { + CGIOperandList::OperandInfo &Op = CGI.Operands[i]; const std::string &OpName = Op.Name; if (OpName.empty()) I->error("Operand #" + utostr(i) + " in operands list has no name!"); @@ -2403,7 +2556,7 @@ void CodeGenDAGPatterns::ParseInstructions() { } TreePatternNode *InVal = InstInputsCheck[OpName]; InstInputsCheck.erase(OpName); // It occurred, remove from map. - + if (InVal->isLeaf() && dynamic_cast<DefInit*>(InVal->getLeafValue())) { Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef(); @@ -2412,13 +2565,13 @@ void CodeGenDAGPatterns::ParseInstructions() { " between the operand and pattern"); } Operands.push_back(Op.Rec); - + // Construct the result for the dest-pattern operand list. TreePatternNode *OpNode = InVal->clone(); - + // No predicate is useful on the result. OpNode->clearPredicateFns(); - + // Promote the xform function to be an explicit node if set. if (Record *Xform = OpNode->getTransformFn()) { OpNode->setTransformFn(0); @@ -2426,10 +2579,10 @@ void CodeGenDAGPatterns::ParseInstructions() { Children.push_back(OpNode); OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes()); } - + ResultNodeOperands.push_back(OpNode); } - + if (!InstInputsCheck.empty()) I->error("Input operand $" + InstInputsCheck.begin()->first + " occurs in pattern but not in operands list!"); @@ -2454,10 +2607,10 @@ void CodeGenDAGPatterns::ParseInstructions() { DAGInstruction &TheInsertedInst = Instructions.find(I->getRecord())->second; TheInsertedInst.setResultPattern(Temp.getOnlyTree()); - + DEBUG(I->dump()); } - + // If we can, convert the instructions to be patterns that are matched! for (std::map<Record*, DAGInstruction, RecordPtrCmp>::iterator II = Instructions.begin(), @@ -2476,10 +2629,11 @@ void CodeGenDAGPatterns::ParseInstructions() { // Not a set (store or something?) SrcPattern = Pattern; } - + Record *Instr = II->first; AddPatternToMatch(I, - PatternToMatch(Instr->getValueAsListInit("Predicates"), + PatternToMatch(Instr, + Instr->getValueAsListInit("Predicates"), SrcPattern, TheInst.getResultPattern(), TheInst.getImpResults(), @@ -2491,7 +2645,7 @@ void CodeGenDAGPatterns::ParseInstructions() { typedef std::pair<const TreePatternNode*, unsigned> NameRecord; -static void FindNames(const TreePatternNode *P, +static void FindNames(const TreePatternNode *P, std::map<std::string, NameRecord> &Names, const TreePattern *PatternTop) { if (!P->getName().empty()) { @@ -2503,7 +2657,7 @@ static void FindNames(const TreePatternNode *P, PatternTop->error("repetition of value: $" + P->getName() + " where different uses have different types!"); } - + if (!P->isLeaf()) { for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i) FindNames(P->getChild(i), Names, PatternTop); @@ -2516,7 +2670,7 @@ void CodeGenDAGPatterns::AddPatternToMatch(const TreePattern *Pattern, std::string Reason; if (!PTM.getSrcPattern()->canPatternMatch(Reason, *this)) Pattern->error("Pattern can never match: " + Reason); - + // If the source pattern's root is a complex pattern, that complex pattern // must specify the nodes it can potentially match. if (const ComplexPattern *CP = @@ -2524,8 +2678,8 @@ void CodeGenDAGPatterns::AddPatternToMatch(const TreePattern *Pattern, if (CP->getRootNodes().empty()) Pattern->error("ComplexPattern at root must specify list of opcodes it" " could match"); - - + + // Find all of the named values in the input and output, ensure they have the // same type. std::map<std::string, NameRecord> SrcNames, DstNames; @@ -2540,14 +2694,14 @@ void CodeGenDAGPatterns::AddPatternToMatch(const TreePattern *Pattern, Pattern->error("Pattern has input without matching name in output: $" + I->first); } - + // Scan all of the named values in the source pattern, rejecting them if the // name isn't used in the dest, and isn't used to tie two values together. for (std::map<std::string, NameRecord>::iterator I = SrcNames.begin(), E = SrcNames.end(); I != E; ++I) if (DstNames[I->first].first == 0 && SrcNames[I->first].second == 1) Pattern->error("Pattern has dead named input: $" + I->first); - + PatternsToMatch.push_back(PTM); } @@ -2566,7 +2720,7 @@ void CodeGenDAGPatterns::InferInstructionFlags() { InstInfo.mayStore = MayStore; InstInfo.mayLoad = MayLoad; InstInfo.hasSideEffects = HasSideEffects; - InstInfo.isVariadic = IsVariadic; + InstInfo.Operands.isVariadic = IsVariadic; } } @@ -2576,7 +2730,7 @@ void CodeGenDAGPatterns::InferInstructionFlags() { static bool ForceArbitraryInstResultType(TreePatternNode *N, TreePattern &TP) { if (N->isLeaf()) return false; - + // Analyze children. for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) if (ForceArbitraryInstResultType(N->getChild(i), TP)) @@ -2590,12 +2744,12 @@ static bool ForceArbitraryInstResultType(TreePatternNode *N, TreePattern &TP) { for (unsigned i = 0, e = N->getNumTypes(); i != e; ++i) { if (N->getExtType(i).isCompletelyUnknown() || N->getExtType(i).isConcrete()) continue; - + // Otherwise, force its type to the first possibility (an arbitrary choice). if (N->getExtType(i).MergeInTypeInfo(N->getExtType(i).getTypeList()[0], TP)) return true; } - + return false; } @@ -2609,20 +2763,20 @@ void CodeGenDAGPatterns::ParsePatterns() { // Inline pattern fragments into it. Pattern->InlinePatternFragments(); - + ListInit *LI = CurPattern->getValueAsListInit("ResultInstrs"); if (LI->getSize() == 0) continue; // no pattern. - + // Parse the instruction. TreePattern *Result = new TreePattern(CurPattern, LI, false, *this); - + // Inline pattern fragments into it. Result->InlinePatternFragments(); if (Result->getNumTrees() != 1) Result->error("Cannot handle instructions producing instructions " "with temporaries yet!"); - + bool IterateInference; bool InferredAllPatternTypes, InferredAllResultTypes; do { @@ -2630,14 +2784,14 @@ void CodeGenDAGPatterns::ParsePatterns() { // can never do anything with this pattern: report it to the user. InferredAllPatternTypes = Pattern->InferAllTypes(&Pattern->getNamedNodesMap()); - + // Infer as many types as possible. If we cannot infer all of them, we // can never do anything with this pattern: report it to the user. InferredAllResultTypes = Result->InferAllTypes(&Pattern->getNamedNodesMap()); IterateInference = false; - + // Apply the type of the result to the source pattern. This helps us // resolve cases where the input type is known to be a pointer type (which // is considered resolved), but the result knows it needs to be 32- or @@ -2650,7 +2804,7 @@ void CodeGenDAGPatterns::ParsePatterns() { IterateInference |= Result->getTree(0)-> UpdateNodeType(i, Pattern->getTree(0)->getExtType(i), *Result); } - + // If our iteration has converged and the input pattern's types are fully // resolved but the result pattern is not fully resolved, we may have a // situation where we have two instructions in the result pattern and @@ -2665,7 +2819,7 @@ void CodeGenDAGPatterns::ParsePatterns() { IterateInference = ForceArbitraryInstResultType(Result->getTree(0), *Result); } while (IterateInference); - + // Verify that we inferred enough types that we can do something with the // pattern and result. If these fire the user has to add type casts. if (!InferredAllPatternTypes) @@ -2674,7 +2828,7 @@ void CodeGenDAGPatterns::ParsePatterns() { Pattern->dump(); Result->error("Could not infer all types in pattern result!"); } - + // Validate that the input pattern is correct. std::map<std::string, TreePatternNode*> InstInputs; std::map<std::string, TreePatternNode*> InstResults; @@ -2702,16 +2856,17 @@ void CodeGenDAGPatterns::ParsePatterns() { DstPattern = new TreePatternNode(DstPattern->getOperator(), ResultNodeOperands, DstPattern->getNumTypes()); - + for (unsigned i = 0, e = Result->getOnlyTree()->getNumTypes(); i != e; ++i) DstPattern->setType(i, Result->getOnlyTree()->getExtType(i)); - + TreePattern Temp(Result->getRecord(), DstPattern, false, *this); Temp.InferAllTypes(); - + AddPatternToMatch(Pattern, - PatternToMatch(CurPattern->getValueAsListInit("Predicates"), + PatternToMatch(CurPattern, + CurPattern->getValueAsListInit("Predicates"), Pattern->getTree(0), Temp.getOnlyTree(), InstImpResults, CurPattern->getValueAsInt("AddedComplexity"), @@ -2721,7 +2876,7 @@ void CodeGenDAGPatterns::ParsePatterns() { /// CombineChildVariants - Given a bunch of permutations of each child of the /// 'operator' node, put them together in all possible ways. -static void CombineChildVariants(TreePatternNode *Orig, +static void CombineChildVariants(TreePatternNode *Orig, const std::vector<std::vector<TreePatternNode*> > &ChildVariants, std::vector<TreePatternNode*> &OutVariants, CodeGenDAGPatterns &CDP, @@ -2730,7 +2885,7 @@ static void CombineChildVariants(TreePatternNode *Orig, for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i) if (ChildVariants[i].empty()) return; - + // The end result is an all-pairs construction of the resultant pattern. std::vector<unsigned> Idxs; Idxs.resize(ChildVariants.size()); @@ -2751,21 +2906,21 @@ static void CombineChildVariants(TreePatternNode *Orig, NewChildren.push_back(ChildVariants[i][Idxs[i]]); TreePatternNode *R = new TreePatternNode(Orig->getOperator(), NewChildren, Orig->getNumTypes()); - + // Copy over properties. R->setName(Orig->getName()); R->setPredicateFns(Orig->getPredicateFns()); R->setTransformFn(Orig->getTransformFn()); for (unsigned i = 0, e = Orig->getNumTypes(); i != e; ++i) R->setType(i, Orig->getExtType(i)); - + // If this pattern cannot match, do not include it as a variant. std::string ErrString; if (!R->canPatternMatch(ErrString, CDP)) { delete R; } else { bool AlreadyExists = false; - + // Scan to see if this pattern has already been emitted. We can get // duplication due to things like commuting: // (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a) @@ -2775,13 +2930,13 @@ static void CombineChildVariants(TreePatternNode *Orig, AlreadyExists = true; break; } - + if (AlreadyExists) delete R; else OutVariants.push_back(R); } - + // Increment indices to the next permutation by incrementing the // indicies from last index backward, e.g., generate the sequence // [0, 0], [0, 1], [1, 0], [1, 1]. @@ -2798,7 +2953,7 @@ static void CombineChildVariants(TreePatternNode *Orig, /// CombineChildVariants - A helper function for binary operators. /// -static void CombineChildVariants(TreePatternNode *Orig, +static void CombineChildVariants(TreePatternNode *Orig, const std::vector<TreePatternNode*> &LHS, const std::vector<TreePatternNode*> &RHS, std::vector<TreePatternNode*> &OutVariants, @@ -2808,14 +2963,14 @@ static void CombineChildVariants(TreePatternNode *Orig, ChildVariants.push_back(LHS); ChildVariants.push_back(RHS); CombineChildVariants(Orig, ChildVariants, OutVariants, CDP, DepVars); -} +} static void GatherChildrenOfAssociativeOpcode(TreePatternNode *N, std::vector<TreePatternNode *> &Children) { assert(N->getNumChildren()==2 &&"Associative but doesn't have 2 children!"); Record *Operator = N->getOperator(); - + // Only permit raw nodes. if (!N->getName().empty() || !N->getPredicateFns().empty() || N->getTransformFn()) { @@ -2852,7 +3007,7 @@ static void GenerateVariantsOf(TreePatternNode *N, // If this node is associative, re-associate. if (NodeInfo.hasProperty(SDNPAssociative)) { - // Re-associate by pulling together all of the linked operators + // Re-associate by pulling together all of the linked operators std::vector<TreePatternNode*> MaximalChildren; GatherChildrenOfAssociativeOpcode(N, MaximalChildren); @@ -2864,11 +3019,11 @@ static void GenerateVariantsOf(TreePatternNode *N, GenerateVariantsOf(MaximalChildren[0], AVariants, CDP, DepVars); GenerateVariantsOf(MaximalChildren[1], BVariants, CDP, DepVars); GenerateVariantsOf(MaximalChildren[2], CVariants, CDP, DepVars); - + // There are only two ways we can permute the tree: // (A op B) op C and A op (B op C) // Within these forms, we can also permute A/B/C. - + // Generate legal pair permutations of A/B/C. std::vector<TreePatternNode*> ABVariants; std::vector<TreePatternNode*> BAVariants; @@ -2901,7 +3056,7 @@ static void GenerateVariantsOf(TreePatternNode *N, return; } } - + // Compute permutations of all children. std::vector<std::vector<TreePatternNode*> > ChildVariants; ChildVariants.resize(N->getNumChildren()); @@ -2953,7 +3108,7 @@ static void GenerateVariantsOf(TreePatternNode *N, // match multiple ways. Add them to PatternsToMatch as well. void CodeGenDAGPatterns::GenerateVariants() { DEBUG(errs() << "Generating instruction variants.\n"); - + // Loop over all of the patterns we've collected, checking to see if we can // generate variants of the instruction, through the exploitation of // identities. This permits the target to provide aggressive matching without @@ -2970,7 +3125,8 @@ void CodeGenDAGPatterns::GenerateVariants() { DEBUG(errs() << "Dependent/multiply used variables: "); DEBUG(DumpDepVars(DepVars)); DEBUG(errs() << "\n"); - GenerateVariantsOf(PatternsToMatch[i].getSrcPattern(), Variants, *this, DepVars); + GenerateVariantsOf(PatternsToMatch[i].getSrcPattern(), Variants, *this, + DepVars); assert(!Variants.empty() && "Must create at least original variant!"); Variants.erase(Variants.begin()); // Remove the original pattern. @@ -2988,7 +3144,7 @@ void CodeGenDAGPatterns::GenerateVariants() { DEBUG(errs() << " VAR#" << v << ": "; Variant->dump(); errs() << "\n"); - + // Scan to see if an instruction or explicit pattern already matches this. bool AlreadyExists = false; for (unsigned p = 0, e = PatternsToMatch.size(); p != e; ++p) { @@ -2997,7 +3153,8 @@ void CodeGenDAGPatterns::GenerateVariants() { PatternsToMatch[p].getPredicates()) continue; // Check to see if this variant already exists. - if (Variant->isIsomorphicTo(PatternsToMatch[p].getSrcPattern(), DepVars)) { + if (Variant->isIsomorphicTo(PatternsToMatch[p].getSrcPattern(), + DepVars)) { DEBUG(errs() << " *** ALREADY EXISTS, ignoring variant.\n"); AlreadyExists = true; break; @@ -3008,7 +3165,8 @@ void CodeGenDAGPatterns::GenerateVariants() { // Otherwise, add it to the list of patterns we have. PatternsToMatch. - push_back(PatternToMatch(PatternsToMatch[i].getPredicates(), + push_back(PatternToMatch(PatternsToMatch[i].getSrcRecord(), + PatternsToMatch[i].getPredicates(), Variant, PatternsToMatch[i].getDstPattern(), PatternsToMatch[i].getDstRegs(), PatternsToMatch[i].getAddedComplexity(), diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h index 0a1362a..946dcee 100644 --- a/utils/TableGen/CodeGenDAGPatterns.h +++ b/utils/TableGen/CodeGenDAGPatterns.h @@ -58,50 +58,50 @@ namespace EEVT { public: TypeSet() {} TypeSet(MVT::SimpleValueType VT, TreePattern &TP); - TypeSet(const std::vector<MVT::SimpleValueType> &VTList); - + TypeSet(const std::vector<MVT::SimpleValueType> &VTList); + bool isCompletelyUnknown() const { return TypeVec.empty(); } - + bool isConcrete() const { if (TypeVec.size() != 1) return false; unsigned char T = TypeVec[0]; (void)T; assert(T < MVT::LAST_VALUETYPE || T == MVT::iPTR || T == MVT::iPTRAny); return true; } - + MVT::SimpleValueType getConcrete() const { assert(isConcrete() && "Type isn't concrete yet"); return (MVT::SimpleValueType)TypeVec[0]; } - + bool isDynamicallyResolved() const { return getConcrete() == MVT::iPTR || getConcrete() == MVT::iPTRAny; } - + const SmallVectorImpl<MVT::SimpleValueType> &getTypeList() const { assert(!TypeVec.empty() && "Not a type list!"); return TypeVec; } - + bool isVoid() const { return TypeVec.size() == 1 && TypeVec[0] == MVT::isVoid; } - + /// hasIntegerTypes - Return true if this TypeSet contains any integer value /// types. bool hasIntegerTypes() const; - + /// hasFloatingPointTypes - Return true if this TypeSet contains an fAny or /// a floating point value type. bool hasFloatingPointTypes() const; - + /// hasVectorTypes - Return true if this TypeSet contains a vector value /// type. bool hasVectorTypes() const; - + /// getName() - Return this TypeSet as a string. std::string getName() const; - + /// MergeInTypeInfo - This merges in type information from the specified /// argument. If 'this' changes, it returns true. If the two types are /// contradictory (e.g. merge f32 into i32) then this throws an exception. @@ -126,14 +126,18 @@ namespace EEVT { /// EnforceSmallerThan - 'this' must be a smaller VT than Other. Update /// this an other based on this information. bool EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP); - + /// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type /// whose element is VT. bool EnforceVectorEltTypeIs(EEVT::TypeSet &VT, TreePattern &TP); - + + /// EnforceVectorSubVectorTypeIs - 'this' is now constrainted to + /// be a vector type VT. + bool EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VT, TreePattern &TP); + bool operator!=(const TypeSet &RHS) const { return TypeVec != RHS.TypeVec; } bool operator==(const TypeSet &RHS) const { return TypeVec == RHS.TypeVec; } - + private: /// FillWithPossibleTypes - Set to all legal types and return true, only /// valid on completely unknown type sets. If Pred is non-null, only MVTs @@ -151,13 +155,14 @@ typedef std::set<std::string> MultipleUseVarSet; /// corresponding to the SDTypeConstraint tablegen class in Target.td. struct SDTypeConstraint { SDTypeConstraint(Record *R); - + unsigned OperandNo; // The operand # this constraint applies to. - enum { - SDTCisVT, SDTCisPtrTy, SDTCisInt, SDTCisFP, SDTCisVec, SDTCisSameAs, - SDTCisVTSmallerThanOp, SDTCisOpSmallerThanOp, SDTCisEltOfVec + enum { + SDTCisVT, SDTCisPtrTy, SDTCisInt, SDTCisFP, SDTCisVec, SDTCisSameAs, + SDTCisVTSmallerThanOp, SDTCisOpSmallerThanOp, SDTCisEltOfVec, + SDTCisSubVecOfVec } ConstraintType; - + union { // The discriminated union. struct { MVT::SimpleValueType VT; @@ -174,6 +179,9 @@ struct SDTypeConstraint { struct { unsigned OtherOperandNum; } SDTCisEltOfVec_Info; + struct { + unsigned OtherOperandNum; + } SDTCisSubVecOfVec_Info; } x; /// ApplyTypeConstraint - Given a node in a pattern, apply this type @@ -197,25 +205,25 @@ class SDNodeInfo { std::vector<SDTypeConstraint> TypeConstraints; public: SDNodeInfo(Record *R); // Parse the specified record. - + unsigned getNumResults() const { return NumResults; } - + /// getNumOperands - This is the number of operands required or -1 if /// variadic. int getNumOperands() const { return NumOperands; } Record *getRecord() const { return Def; } const std::string &getEnumName() const { return EnumName; } const std::string &getSDClassName() const { return SDClassName; } - + const std::vector<SDTypeConstraint> &getTypeConstraints() const { return TypeConstraints; } - + /// getKnownType - If the type constraints on this node imply a fixed type /// (e.g. all stores return void, etc), then return it as an /// MVT::SimpleValueType. Otherwise, return MVT::Other. MVT::SimpleValueType getKnownType(unsigned ResNo) const; - + /// hasProperty - Return true if this node has the specified property. /// bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); } @@ -240,31 +248,31 @@ class TreePatternNode { /// result may be a set of possible types. After (successful) type inference, /// each is a single concrete type. SmallVector<EEVT::TypeSet, 1> Types; - + /// Operator - The Record for the operator if this is an interior node (not /// a leaf). Record *Operator; - + /// Val - The init value (e.g. the "GPRC" record, or "7") for a leaf. /// Init *Val; - + /// Name - The name given to this node with the :$foo notation. /// std::string Name; - + /// PredicateFns - The predicate functions to execute on this node to check /// for a match. If this list is empty, no predicate is involved. std::vector<std::string> PredicateFns; - + /// TransformFn - The transformation function to execute on this node before /// it can be substituted into the resulting instruction on a pattern match. Record *TransformFn; - + std::vector<TreePatternNode*> Children; public: TreePatternNode(Record *Op, const std::vector<TreePatternNode*> &Ch, - unsigned NumResults) + unsigned NumResults) : Operator(Op), Val(0), TransformFn(0), Children(Ch) { Types.resize(NumResults); } @@ -273,12 +281,12 @@ public: Types.resize(NumResults); } ~TreePatternNode(); - + const std::string &getName() const { return Name; } void setName(StringRef N) { Name.assign(N.begin(), N.end()); } - + bool isLeaf() const { return Val != 0; } - + // Type accessors. unsigned getNumTypes() const { return Types.size(); } MVT::SimpleValueType getType(unsigned ResNo) const { @@ -288,7 +296,7 @@ public: const EEVT::TypeSet &getExtType(unsigned ResNo) const { return Types[ResNo]; } EEVT::TypeSet &getExtType(unsigned ResNo) { return Types[ResNo]; } void setType(unsigned ResNo, const EEVT::TypeSet &T) { Types[ResNo] = T; } - + bool hasTypeSet(unsigned ResNo) const { return Types[ResNo].isConcrete(); } @@ -298,16 +306,16 @@ public: bool isTypeDynamicallyResolved(unsigned ResNo) const { return Types[ResNo].isDynamicallyResolved(); } - + Init *getLeafValue() const { assert(isLeaf()); return Val; } Record *getOperator() const { assert(!isLeaf()); return Operator; } - + unsigned getNumChildren() const { return Children.size(); } TreePatternNode *getChild(unsigned N) const { return Children[N]; } void setChild(unsigned i, TreePatternNode *N) { Children[i] = N; } - + /// hasChild - Return true if N is any of our children. bool hasChild(const TreePatternNode *N) const { for (unsigned i = 0, e = Children.size(); i != e; ++i) @@ -321,7 +329,7 @@ public: assert(PredicateFns.empty() && "Overwriting non-empty predicate list!"); PredicateFns = Fns; } - void addPredicateFn(const std::string &Fn) { + void addPredicateFn(const std::string &Fn) { assert(!Fn.empty() && "Empty predicate string!"); if (std::find(PredicateFns.begin(), PredicateFns.end(), Fn) == PredicateFns.end()) @@ -330,7 +338,7 @@ public: Record *getTransformFn() const { return TransformFn; } void setTransformFn(Record *Fn) { TransformFn = Fn; } - + /// getIntrinsicInfo - If this node corresponds to an intrinsic, return the /// CodeGenIntrinsic information for it, otherwise return a null pointer. const CodeGenIntrinsic *getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const; @@ -342,18 +350,18 @@ public: /// NodeHasProperty - Return true if this node has the specified property. bool NodeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const; - + /// TreeHasProperty - Return true if any node in this tree has the specified /// property. bool TreeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const; - + /// isCommutativeIntrinsic - Return true if the node is an intrinsic which is /// marked isCommutative. bool isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const; - + void print(raw_ostream &OS) const; void dump() const; - + public: // Higher level manipulation routines. /// clone - Return a new copy of this tree. @@ -362,14 +370,14 @@ public: // Higher level manipulation routines. /// RemoveAllTypes - Recursively strip all the types of this tree. void RemoveAllTypes(); - + /// isIsomorphicTo - Return true if this node is recursively isomorphic to /// the specified node. For this comparison, all of the state of the node /// is considered, except for the assigned name. Nodes with differing names /// that are otherwise identical are considered isomorphic. bool isIsomorphicTo(const TreePatternNode *N, const MultipleUseVarSet &DepVars) const; - + /// SubstituteFormalArguments - Replace the formal arguments in this tree /// with actual values specified by ArgMap. void SubstituteFormalArguments(std::map<std::string, @@ -379,13 +387,13 @@ public: // Higher level manipulation routines. /// fragments, inline them into place, giving us a pattern without any /// PatFrag references. TreePatternNode *InlinePatternFragments(TreePattern &TP); - + /// ApplyTypeConstraints - Apply all of the type constraints relevant to /// this node and its children in the tree. This returns true if it makes a /// change, false otherwise. If a type contradiction is found, throw an /// exception. bool ApplyTypeConstraints(TreePattern &TP, bool NotRegisters); - + /// UpdateNodeType - Set the node type of N to VT if VT contains /// information. If N already contains a conflicting type, then throw an /// exception. This returns true if any information was updated. @@ -399,18 +407,18 @@ public: // Higher level manipulation routines. TreePattern &TP) { return Types[ResNo].MergeInTypeInfo(EEVT::TypeSet(InTy, TP), TP); } - + /// ContainsUnresolvedType - Return true if this tree contains any /// unresolved types. bool ContainsUnresolvedType() const { for (unsigned i = 0, e = Types.size(); i != e; ++i) if (!Types[i].isConcrete()) return true; - + for (unsigned i = 0, e = getNumChildren(); i != e; ++i) if (getChild(i)->ContainsUnresolvedType()) return true; return false; } - + /// canPatternMatch - If it is impossible for this pattern to match on this /// target, fill in Reason and return false. Otherwise, return true. bool canPatternMatch(std::string &Reason, const CodeGenDAGPatterns &CDP); @@ -420,7 +428,7 @@ 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. @@ -430,19 +438,19 @@ class TreePattern { /// Note that PatFrag's only have a single tree. /// std::vector<TreePatternNode*> Trees; - + /// NamedNodes - This is all of the nodes that have names in the trees in this /// pattern. StringMap<SmallVector<TreePatternNode*,1> > NamedNodes; - + /// TheRecord - The actual TableGen record corresponding to this pattern. /// Record *TheRecord; - + /// Args - This is a list of all of the arguments to this pattern (for /// PatFrag patterns), which are the 'node' markers in this pattern. std::vector<std::string> Args; - + /// CDP - the top-level object coordinating this madness. /// CodeGenDAGPatterns &CDP; @@ -451,7 +459,7 @@ class TreePattern { /// False if this is an output pattern, something to emit. bool isInputPattern; public: - + /// TreePattern constructor - Parse the specified DagInits into the /// current record. TreePattern(Record *TheRec, ListInit *RawPat, bool isInput, @@ -460,7 +468,7 @@ public: CodeGenDAGPatterns &ise); TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput, CodeGenDAGPatterns &ise); - + /// getTrees - Return the tree patterns which corresponds to this pattern. /// const std::vector<TreePatternNode*> &getTrees() const { return Trees; } @@ -470,25 +478,25 @@ public: assert(Trees.size() == 1 && "Doesn't have exactly one pattern!"); return Trees[0]; } - + const StringMap<SmallVector<TreePatternNode*,1> > &getNamedNodesMap() { if (NamedNodes.empty()) ComputeNamedNodes(); return NamedNodes; } - + /// getRecord - Return the actual TableGen record corresponding to this /// pattern. /// Record *getRecord() const { return TheRecord; } - + unsigned getNumArgs() const { return Args.size(); } const std::string &getArgName(unsigned i) const { assert(i < Args.size() && "Argument reference out of range!"); return Args[i]; } std::vector<std::string> &getArgList() { return Args; } - + CodeGenDAGPatterns &getDAGPatterns() const { return CDP; } /// InlinePatternFragments - If this pattern refers to any pattern @@ -498,20 +506,20 @@ public: for (unsigned i = 0, e = Trees.size(); i != e; ++i) Trees[i] = Trees[i]->InlinePatternFragments(*this); } - + /// InferAllTypes - Infer/propagate as many types throughout the expression /// patterns as possible. Return true if all types are inferred, false /// otherwise. Throw an exception if a type contradiction is found. bool InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *NamedTypes=0); - + /// error - Throw an exception, prefixing it with information about this /// pattern. void error(const std::string &Msg) const; - + void print(raw_ostream &OS) const; void dump() const; - + private: TreePatternNode *ParseTreePattern(Init *DI, StringRef OpName); void ComputeNamedNodes(); @@ -535,7 +543,7 @@ public: const std::vector<Record*> &results, const std::vector<Record*> &operands, const std::vector<Record*> &impresults) - : Pattern(TP), Results(results), Operands(operands), + : Pattern(TP), Results(results), Operands(operands), ImpResults(impresults), ResultPattern(0) {} const TreePattern *getPattern() const { return Pattern; } @@ -543,14 +551,14 @@ public: unsigned getNumOperands() const { return Operands.size(); } unsigned getNumImpResults() const { return ImpResults.size(); } const std::vector<Record*>& getImpResults() const { return ImpResults; } - + void setResultPattern(TreePatternNode *R) { ResultPattern = R; } - + Record *getResult(unsigned RN) const { assert(RN < Results.size()); return Results[RN]; } - + Record *getOperand(unsigned ON) const { assert(ON < Operands.size()); return Operands[ON]; @@ -560,21 +568,22 @@ public: assert(RN < ImpResults.size()); return ImpResults[RN]; } - + TreePatternNode *getResultPattern() const { return ResultPattern; } }; - + /// PatternToMatch - Used by CodeGenDAGPatterns to keep tab of patterns /// processed to produce isel. class PatternToMatch { public: - PatternToMatch(ListInit *preds, + PatternToMatch(Record *srcrecord, ListInit *preds, TreePatternNode *src, TreePatternNode *dst, const std::vector<Record*> &dstregs, unsigned complexity, unsigned uid) - : Predicates(preds), SrcPattern(src), DstPattern(dst), + : SrcRecord(srcrecord), Predicates(preds), SrcPattern(src), DstPattern(dst), Dstregs(dstregs), AddedComplexity(complexity), ID(uid) {} + Record *SrcRecord; // Originating Record for the pattern. ListInit *Predicates; // Top level predicate conditions to match. TreePatternNode *SrcPattern; // Source pattern to match. TreePatternNode *DstPattern; // Resulting pattern. @@ -582,6 +591,7 @@ public: unsigned AddedComplexity; // Add to matching pattern complexity. unsigned ID; // Unique ID for the record. + Record *getSrcRecord() const { return SrcRecord; } ListInit *getPredicates() const { return Predicates; } TreePatternNode *getSrcPattern() const { return SrcPattern; } TreePatternNode *getDstPattern() const { return DstPattern; } @@ -589,7 +599,7 @@ public: unsigned getAddedComplexity() const { return AddedComplexity; } std::string getPredicateCheck() const; - + /// Compute the complexity metric for the input pattern. This roughly /// corresponds to the number of nodes that are covered. unsigned getPatternComplexity(const CodeGenDAGPatterns &CGP) const; @@ -599,60 +609,60 @@ public: struct RecordPtrCmp { bool operator()(const Record *LHS, const Record *RHS) const; }; - + class CodeGenDAGPatterns { RecordKeeper &Records; CodeGenTarget Target; std::vector<CodeGenIntrinsic> Intrinsics; std::vector<CodeGenIntrinsic> TgtIntrinsics; - + std::map<Record*, SDNodeInfo, RecordPtrCmp> SDNodes; std::map<Record*, std::pair<Record*, std::string>, RecordPtrCmp> SDNodeXForms; std::map<Record*, ComplexPattern, RecordPtrCmp> ComplexPatterns; std::map<Record*, TreePattern*, RecordPtrCmp> PatternFragments; std::map<Record*, DAGDefaultOperand, RecordPtrCmp> DefaultOperands; std::map<Record*, DAGInstruction, RecordPtrCmp> Instructions; - + // Specific SDNode definitions: Record *intrinsic_void_sdnode; Record *intrinsic_w_chain_sdnode, *intrinsic_wo_chain_sdnode; - + /// PatternsToMatch - All of the things we are matching on the DAG. The first /// value is the pattern to match, the second pattern is the result to /// emit. std::vector<PatternToMatch> PatternsToMatch; public: - CodeGenDAGPatterns(RecordKeeper &R); + CodeGenDAGPatterns(RecordKeeper &R); ~CodeGenDAGPatterns(); - + CodeGenTarget &getTargetInfo() { return Target; } const CodeGenTarget &getTargetInfo() const { return Target; } - + Record *getSDNodeNamed(const std::string &Name) const; - + const SDNodeInfo &getSDNodeInfo(Record *R) const { assert(SDNodes.count(R) && "Unknown node!"); return SDNodes.find(R)->second; } - + // Node transformation lookups. typedef std::pair<Record*, std::string> NodeXForm; const NodeXForm &getSDNodeTransform(Record *R) const { assert(SDNodeXForms.count(R) && "Invalid transform!"); return SDNodeXForms.find(R)->second; } - + typedef std::map<Record*, NodeXForm, RecordPtrCmp>::const_iterator nx_iterator; nx_iterator nx_begin() const { return SDNodeXForms.begin(); } nx_iterator nx_end() const { return SDNodeXForms.end(); } - + const ComplexPattern &getComplexPattern(Record *R) const { assert(ComplexPatterns.count(R) && "Unknown addressing mode!"); return ComplexPatterns.find(R)->second; } - + const CodeGenIntrinsic &getIntrinsic(Record *R) const { for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i) if (Intrinsics[i].TheDef == R) return Intrinsics[i]; @@ -661,7 +671,7 @@ public: assert(0 && "Unknown intrinsic!"); abort(); } - + const CodeGenIntrinsic &getIntrinsicInfo(unsigned IID) const { if (IID-1 < Intrinsics.size()) return Intrinsics[IID-1]; @@ -670,7 +680,7 @@ public: assert(0 && "Bad intrinsic ID!"); abort(); } - + unsigned getIntrinsicID(Record *R) const { for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i) if (Intrinsics[i].TheDef == R) return i; @@ -679,12 +689,12 @@ public: assert(0 && "Unknown intrinsic!"); abort(); } - + const DAGDefaultOperand &getDefaultOperand(Record *R) const { assert(DefaultOperands.count(R) &&"Isn't an analyzed default operand!"); return DefaultOperands.find(R)->second; } - + // Pattern Fragment information. TreePattern *getPatternFragment(Record *R) const { assert(PatternFragments.count(R) && "Invalid pattern fragment request!"); @@ -694,7 +704,7 @@ public: if (!PatternFragments.count(R)) return 0; return PatternFragments.find(R)->second; } - + typedef std::map<Record*, TreePattern*, RecordPtrCmp>::const_iterator pf_iterator; pf_iterator pf_begin() const { return PatternFragments.begin(); } @@ -704,14 +714,14 @@ public: typedef std::vector<PatternToMatch>::const_iterator ptm_iterator; ptm_iterator ptm_begin() const { return PatternsToMatch.begin(); } ptm_iterator ptm_end() const { return PatternsToMatch.end(); } - - - + + + const DAGInstruction &getInstruction(Record *R) const { assert(Instructions.count(R) && "Unknown instruction!"); return Instructions.find(R)->second; } - + Record *get_intrinsic_void_sdnode() const { return intrinsic_void_sdnode; } @@ -721,7 +731,7 @@ public: Record *get_intrinsic_wo_chain_sdnode() const { return intrinsic_wo_chain_sdnode; } - + bool hasTargetIntrinsics() { return !TgtIntrinsics.empty(); } private: @@ -734,7 +744,7 @@ private: void ParsePatterns(); void InferInstructionFlags(); void GenerateVariants(); - + void AddPatternToMatch(const TreePattern *Pattern, const PatternToMatch &PTM); void FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, std::map<std::string, diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 01a1fe1..f37d3ea 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -15,120 +15,19 @@ #include "CodeGenTarget.h" #include "Record.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/STLExtras.h" #include <set> using namespace llvm; -static void ParseConstraint(const std::string &CStr, CodeGenInstruction *I) { - // EARLY_CLOBBER: @early $reg - std::string::size_type wpos = CStr.find_first_of(" \t"); - std::string::size_type start = CStr.find_first_not_of(" \t"); - std::string Tok = CStr.substr(start, wpos - start); - if (Tok == "@earlyclobber") { - std::string Name = CStr.substr(wpos+1); - wpos = Name.find_first_not_of(" \t"); - if (wpos == std::string::npos) - throw "Illegal format for @earlyclobber constraint: '" + CStr + "'"; - Name = Name.substr(wpos); - std::pair<unsigned,unsigned> Op = - I->ParseOperandName(Name, false); - - // Build the string for the operand - if (!I->OperandList[Op.first].Constraints[Op.second].isNone()) - throw "Operand '" + Name + "' cannot have multiple constraints!"; - I->OperandList[Op.first].Constraints[Op.second] = - CodeGenInstruction::ConstraintInfo::getEarlyClobber(); - return; - } - - // Only other constraint is "TIED_TO" for now. - std::string::size_type pos = CStr.find_first_of('='); - assert(pos != std::string::npos && "Unrecognized constraint"); - start = CStr.find_first_not_of(" \t"); - std::string Name = CStr.substr(start, pos - start); - - // TIED_TO: $src1 = $dst - wpos = Name.find_first_of(" \t"); - if (wpos == std::string::npos) - throw "Illegal format for tied-to constraint: '" + CStr + "'"; - std::string DestOpName = Name.substr(0, wpos); - std::pair<unsigned,unsigned> DestOp = I->ParseOperandName(DestOpName, false); - - Name = CStr.substr(pos+1); - wpos = Name.find_first_not_of(" \t"); - if (wpos == std::string::npos) - throw "Illegal format for tied-to constraint: '" + CStr + "'"; - - std::pair<unsigned,unsigned> SrcOp = - I->ParseOperandName(Name.substr(wpos), false); - if (SrcOp > DestOp) - throw "Illegal tied-to operand constraint '" + CStr + "'"; - - - unsigned FlatOpNo = I->getFlattenedOperandNumber(SrcOp); - - if (!I->OperandList[DestOp.first].Constraints[DestOp.second].isNone()) - throw "Operand '" + DestOpName + "' cannot have multiple constraints!"; - I->OperandList[DestOp.first].Constraints[DestOp.second] = - CodeGenInstruction::ConstraintInfo::getTied(FlatOpNo); -} - -static void ParseConstraints(const std::string &CStr, CodeGenInstruction *I) { - // Make sure the constraints list for each operand is large enough to hold - // constraint info, even if none is present. - for (unsigned i = 0, e = I->OperandList.size(); i != e; ++i) - I->OperandList[i].Constraints.resize(I->OperandList[i].MINumOperands); - - if (CStr.empty()) return; - - const std::string delims(","); - std::string::size_type bidx, eidx; - - bidx = CStr.find_first_not_of(delims); - while (bidx != std::string::npos) { - eidx = CStr.find_first_of(delims, bidx); - if (eidx == std::string::npos) - eidx = CStr.length(); - - ParseConstraint(CStr.substr(bidx, eidx - bidx), I); - bidx = CStr.find_first_not_of(delims, eidx); - } -} - -CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr) - : TheDef(R), AsmString(AsmStr) { - Namespace = R->getValueAsString("Namespace"); +//===----------------------------------------------------------------------===// +// CGIOperandList Implementation +//===----------------------------------------------------------------------===// - isReturn = R->getValueAsBit("isReturn"); - isBranch = R->getValueAsBit("isBranch"); - isIndirectBranch = R->getValueAsBit("isIndirectBranch"); - isCompare = R->getValueAsBit("isCompare"); - isBarrier = R->getValueAsBit("isBarrier"); - isCall = R->getValueAsBit("isCall"); - canFoldAsLoad = R->getValueAsBit("canFoldAsLoad"); - mayLoad = R->getValueAsBit("mayLoad"); - mayStore = R->getValueAsBit("mayStore"); - isPredicable = R->getValueAsBit("isPredicable"); - isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress"); - isCommutable = R->getValueAsBit("isCommutable"); - isTerminator = R->getValueAsBit("isTerminator"); - isReMaterializable = R->getValueAsBit("isReMaterializable"); - hasDelaySlot = R->getValueAsBit("hasDelaySlot"); - usesCustomInserter = R->getValueAsBit("usesCustomInserter"); - hasCtrlDep = R->getValueAsBit("hasCtrlDep"); - isNotDuplicable = R->getValueAsBit("isNotDuplicable"); - hasSideEffects = R->getValueAsBit("hasSideEffects"); - neverHasSideEffects = R->getValueAsBit("neverHasSideEffects"); - isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove"); - hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq"); - hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq"); +CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { + isPredicable = false; hasOptionalDef = false; isVariadic = false; - ImplicitDefs = R->getValueAsListOfDefs("Defs"); - ImplicitUses = R->getValueAsListOfDefs("Uses"); - - if (neverHasSideEffects + hasSideEffects > 1) - throw R->getName() + ": multiple conflicting side-effect flags set!"; DagInit *OutDI = R->getValueAsDag("OutOperandList"); @@ -137,16 +36,16 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr) throw R->getName() + ": invalid def name for output list: use 'outs'"; } else throw R->getName() + ": invalid output list: use 'outs'"; - + NumDefs = OutDI->getNumArgs(); - + DagInit *InDI = R->getValueAsDag("InOperandList"); if (DefInit *Init = dynamic_cast<DefInit*>(InDI->getOperator())) { if (Init->getDef()->getName() != "ins") throw R->getName() + ": invalid def name for input list: use 'ins'"; } else throw R->getName() + ": invalid input list: use 'ins'"; - + unsigned MIOperandNo = 0; std::set<std::string> OperandNames; for (unsigned i = 0, e = InDI->getNumArgs()+OutDI->getNumArgs(); i != e; ++i){ @@ -159,25 +58,28 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr) ArgInit = InDI->getArg(i-NumDefs); ArgName = InDI->getArgName(i-NumDefs); } - + DefInit *Arg = dynamic_cast<DefInit*>(ArgInit); if (!Arg) throw "Illegal operand for the '" + R->getName() + "' instruction!"; Record *Rec = Arg->getDef(); std::string PrintMethod = "printOperand"; + std::string EncoderMethod; unsigned NumOps = 1; DagInit *MIOpInfo = 0; if (Rec->isSubClassOf("Operand")) { PrintMethod = Rec->getValueAsString("PrintMethod"); + // If there is an explicit encoder method, use it. + EncoderMethod = Rec->getValueAsString("EncoderMethod"); MIOpInfo = Rec->getValueAsDag("MIOperandInfo"); // Verify that MIOpInfo has an 'ops' root value. if (!dynamic_cast<DefInit*>(MIOpInfo->getOperator()) || dynamic_cast<DefInit*>(MIOpInfo->getOperator()) - ->getDef()->getName() != "ops") + ->getDef()->getName() != "ops") throw "Bad value for MIOperandInfo in operand '" + Rec->getName() + - "'\n"; + "'\n"; // If we have MIOpInfo, then we have #operands equal to number of entries // in MIOperandInfo. @@ -192,58 +94,58 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr) isVariadic = true; continue; } else if (!Rec->isSubClassOf("RegisterClass") && - Rec->getName() != "ptr_rc" && Rec->getName() != "unknown") + !Rec->isSubClassOf("PointerLikeRegClass") && + Rec->getName() != "unknown") throw "Unknown operand class '" + Rec->getName() + - "' in '" + R->getName() + "' instruction!"; + "' in '" + R->getName() + "' instruction!"; // Check that the operand has a name and that it's unique. if (ArgName.empty()) throw "In instruction '" + R->getName() + "', operand #" + utostr(i) + - " has no name!"; + " has no name!"; if (!OperandNames.insert(ArgName).second) throw "In instruction '" + R->getName() + "', operand #" + utostr(i) + - " has the same name as a previous operand!"; + " has the same name as a previous operand!"; - OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod, + OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod, EncoderMethod, MIOperandNo, NumOps, MIOpInfo)); MIOperandNo += NumOps; } - // Parse Constraints. - ParseConstraints(R->getValueAsString("Constraints"), this); - - // Parse the DisableEncoding field. - std::string DisableEncoding = R->getValueAsString("DisableEncoding"); - while (1) { - std::string OpName; - tie(OpName, DisableEncoding) = getToken(DisableEncoding, " ,\t"); - if (OpName.empty()) break; - - // Figure out which operand this is. - std::pair<unsigned,unsigned> Op = ParseOperandName(OpName, false); - // Mark the operand as not-to-be encoded. - if (Op.second >= OperandList[Op.first].DoNotEncode.size()) - OperandList[Op.first].DoNotEncode.resize(Op.second+1); - OperandList[Op.first].DoNotEncode[Op.second] = true; - } + // Make sure the constraints list for each operand is large enough to hold + // constraint info, even if none is present. + for (unsigned i = 0, e = OperandList.size(); i != e; ++i) + OperandList[i].Constraints.resize(OperandList[i].MINumOperands); } + /// getOperandNamed - Return the index of the operand with the specified /// non-empty name. If the instruction does not have an operand with the /// specified name, throw an exception. /// -unsigned CodeGenInstruction::getOperandNamed(const std::string &Name) const { +unsigned CGIOperandList::getOperandNamed(StringRef Name) const { + unsigned OpIdx; + if (hasOperandNamed(Name, OpIdx)) return OpIdx; + throw "'" + TheDef->getName() + "' does not have an operand named '$" + + Name.str() + "'!"; +} + +/// hasOperandNamed - Query whether the instruction has an operand of the +/// given name. If so, return true and set OpIdx to the index of the +/// operand. Otherwise, return false. +bool CGIOperandList::hasOperandNamed(StringRef Name, unsigned &OpIdx) const { assert(!Name.empty() && "Cannot search for operand with no name!"); for (unsigned i = 0, e = OperandList.size(); i != e; ++i) - if (OperandList[i].Name == Name) return i; - throw "Instruction '" + TheDef->getName() + - "' does not have an operand named '$" + Name + "'!"; + if (OperandList[i].Name == Name) { + OpIdx = i; + return true; + } + return false; } std::pair<unsigned,unsigned> -CodeGenInstruction::ParseOperandName(const std::string &Op, - bool AllowWholeOp) { +CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) { if (Op.empty() || Op[0] != '$') throw TheDef->getName() + ": Illegal operand name: '" + Op + "'"; @@ -266,7 +168,7 @@ CodeGenInstruction::ParseOperandName(const std::string &Op, if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp && SubOpName.empty()) throw TheDef->getName() + ": Illegal to refer to" - " whole operand part of complex operand '" + Op + "'"; + " whole operand part of complex operand '" + Op + "'"; // Otherwise, return the operand. return std::make_pair(OpIdx, 0U); @@ -286,6 +188,137 @@ CodeGenInstruction::ParseOperandName(const std::string &Op, throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'"; } +static void ParseConstraint(const std::string &CStr, CGIOperandList &Ops) { + // EARLY_CLOBBER: @early $reg + std::string::size_type wpos = CStr.find_first_of(" \t"); + std::string::size_type start = CStr.find_first_not_of(" \t"); + std::string Tok = CStr.substr(start, wpos - start); + if (Tok == "@earlyclobber") { + std::string Name = CStr.substr(wpos+1); + wpos = Name.find_first_not_of(" \t"); + if (wpos == std::string::npos) + throw "Illegal format for @earlyclobber constraint: '" + CStr + "'"; + Name = Name.substr(wpos); + std::pair<unsigned,unsigned> Op = Ops.ParseOperandName(Name, false); + + // Build the string for the operand + if (!Ops[Op.first].Constraints[Op.second].isNone()) + throw "Operand '" + Name + "' cannot have multiple constraints!"; + Ops[Op.first].Constraints[Op.second] = + CGIOperandList::ConstraintInfo::getEarlyClobber(); + return; + } + + // Only other constraint is "TIED_TO" for now. + std::string::size_type pos = CStr.find_first_of('='); + assert(pos != std::string::npos && "Unrecognized constraint"); + start = CStr.find_first_not_of(" \t"); + std::string Name = CStr.substr(start, pos - start); + + // TIED_TO: $src1 = $dst + wpos = Name.find_first_of(" \t"); + if (wpos == std::string::npos) + throw "Illegal format for tied-to constraint: '" + CStr + "'"; + std::string DestOpName = Name.substr(0, wpos); + std::pair<unsigned,unsigned> DestOp = Ops.ParseOperandName(DestOpName, false); + + Name = CStr.substr(pos+1); + wpos = Name.find_first_not_of(" \t"); + if (wpos == std::string::npos) + throw "Illegal format for tied-to constraint: '" + CStr + "'"; + + std::pair<unsigned,unsigned> SrcOp = + Ops.ParseOperandName(Name.substr(wpos), false); + if (SrcOp > DestOp) + throw "Illegal tied-to operand constraint '" + CStr + "'"; + + + unsigned FlatOpNo = Ops.getFlattenedOperandNumber(SrcOp); + + if (!Ops[DestOp.first].Constraints[DestOp.second].isNone()) + throw "Operand '" + DestOpName + "' cannot have multiple constraints!"; + Ops[DestOp.first].Constraints[DestOp.second] = + CGIOperandList::ConstraintInfo::getTied(FlatOpNo); +} + +static void ParseConstraints(const std::string &CStr, CGIOperandList &Ops) { + if (CStr.empty()) return; + + const std::string delims(","); + std::string::size_type bidx, eidx; + + bidx = CStr.find_first_not_of(delims); + while (bidx != std::string::npos) { + eidx = CStr.find_first_of(delims, bidx); + if (eidx == std::string::npos) + eidx = CStr.length(); + + ParseConstraint(CStr.substr(bidx, eidx - bidx), Ops); + bidx = CStr.find_first_not_of(delims, eidx); + } +} + +void CGIOperandList::ProcessDisableEncoding(std::string DisableEncoding) { + while (1) { + std::string OpName; + tie(OpName, DisableEncoding) = getToken(DisableEncoding, " ,\t"); + if (OpName.empty()) break; + + // Figure out which operand this is. + std::pair<unsigned,unsigned> Op = ParseOperandName(OpName, false); + + // Mark the operand as not-to-be encoded. + if (Op.second >= OperandList[Op.first].DoNotEncode.size()) + OperandList[Op.first].DoNotEncode.resize(Op.second+1); + OperandList[Op.first].DoNotEncode[Op.second] = true; + } + +} + +//===----------------------------------------------------------------------===// +// CodeGenInstruction Implementation +//===----------------------------------------------------------------------===// + +CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R), Operands(R) { + Namespace = R->getValueAsString("Namespace"); + AsmString = R->getValueAsString("AsmString"); + + isReturn = R->getValueAsBit("isReturn"); + isBranch = R->getValueAsBit("isBranch"); + isIndirectBranch = R->getValueAsBit("isIndirectBranch"); + isCompare = R->getValueAsBit("isCompare"); + isMoveImm = R->getValueAsBit("isMoveImm"); + isBarrier = R->getValueAsBit("isBarrier"); + isCall = R->getValueAsBit("isCall"); + canFoldAsLoad = R->getValueAsBit("canFoldAsLoad"); + mayLoad = R->getValueAsBit("mayLoad"); + mayStore = R->getValueAsBit("mayStore"); + isPredicable = Operands.isPredicable || R->getValueAsBit("isPredicable"); + isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress"); + isCommutable = R->getValueAsBit("isCommutable"); + isTerminator = R->getValueAsBit("isTerminator"); + isReMaterializable = R->getValueAsBit("isReMaterializable"); + hasDelaySlot = R->getValueAsBit("hasDelaySlot"); + usesCustomInserter = R->getValueAsBit("usesCustomInserter"); + hasCtrlDep = R->getValueAsBit("hasCtrlDep"); + isNotDuplicable = R->getValueAsBit("isNotDuplicable"); + hasSideEffects = R->getValueAsBit("hasSideEffects"); + neverHasSideEffects = R->getValueAsBit("neverHasSideEffects"); + isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove"); + hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq"); + hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq"); + ImplicitDefs = R->getValueAsListOfDefs("Defs"); + ImplicitUses = R->getValueAsListOfDefs("Uses"); + + if (neverHasSideEffects + hasSideEffects > 1) + throw R->getName() + ": multiple conflicting side-effect flags set!"; + + // Parse Constraints. + ParseConstraints(R->getValueAsString("Constraints"), Operands); + + // Parse the DisableEncoding field. + Operands.ProcessDisableEncoding(R->getValueAsString("DisableEncoding")); +} /// HasOneImplicitDefWithKnownVT - If the instruction has at least one /// implicit def and it has a known VT, return the VT, otherwise return @@ -293,14 +326,212 @@ CodeGenInstruction::ParseOperandName(const std::string &Op, MVT::SimpleValueType CodeGenInstruction:: HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const { if (ImplicitDefs.empty()) return MVT::Other; - + // Check to see if the first implicit def has a resolvable type. Record *FirstImplicitDef = ImplicitDefs[0]; assert(FirstImplicitDef->isSubClassOf("Register")); - const std::vector<MVT::SimpleValueType> &RegVTs = + const std::vector<MVT::SimpleValueType> &RegVTs = TargetInfo.getRegisterVTs(FirstImplicitDef); if (RegVTs.size() == 1) return RegVTs[0]; return MVT::Other; } + +/// FlattenAsmStringVariants - Flatten the specified AsmString to only +/// include text from the specified variant, returning the new string. +std::string CodeGenInstruction:: +FlattenAsmStringVariants(StringRef Cur, unsigned Variant) { + std::string Res = ""; + + for (;;) { + // Find the start of the next variant string. + size_t VariantsStart = 0; + for (size_t e = Cur.size(); VariantsStart != e; ++VariantsStart) + if (Cur[VariantsStart] == '{' && + (VariantsStart == 0 || (Cur[VariantsStart-1] != '$' && + Cur[VariantsStart-1] != '\\'))) + break; + + // Add the prefix to the result. + Res += Cur.slice(0, VariantsStart); + if (VariantsStart == Cur.size()) + break; + + ++VariantsStart; // Skip the '{'. + + // Scan to the end of the variants string. + size_t VariantsEnd = VariantsStart; + unsigned NestedBraces = 1; + for (size_t e = Cur.size(); VariantsEnd != e; ++VariantsEnd) { + if (Cur[VariantsEnd] == '}' && Cur[VariantsEnd-1] != '\\') { + if (--NestedBraces == 0) + break; + } else if (Cur[VariantsEnd] == '{') + ++NestedBraces; + } + + // Select the Nth variant (or empty). + StringRef Selection = Cur.slice(VariantsStart, VariantsEnd); + for (unsigned i = 0; i != Variant; ++i) + Selection = Selection.split('|').second; + Res += Selection.split('|').first; + + assert(VariantsEnd != Cur.size() && + "Unterminated variants in assembly string!"); + Cur = Cur.substr(VariantsEnd + 1); + } + + return Res; +} + + +//===----------------------------------------------------------------------===// +/// CodeGenInstAlias Implementation +//===----------------------------------------------------------------------===// + +/// tryAliasOpMatch - This is a helper function for the CodeGenInstAlias +/// constructor. It checks if an argument in an InstAlias pattern matches +/// the corresponding operand of the instruction. It returns true on a +/// successful match, with ResOp set to the result operand to be used. +bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, + Record *InstOpRec, bool hasSubOps, + SMLoc Loc, CodeGenTarget &T, + ResultOperand &ResOp) { + Init *Arg = Result->getArg(AliasOpNo); + DefInit *ADI = dynamic_cast<DefInit*>(Arg); + + if (ADI && ADI->getDef() == InstOpRec) { + // If the operand is a record, it must have a name, and the record type + // must match up with the instruction's argument type. + if (Result->getArgName(AliasOpNo).empty()) + throw TGError(Loc, "result argument #" + utostr(AliasOpNo) + + " must have a name!"); + ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef()); + return true; + } + + // Handle explicit registers. + if (ADI && ADI->getDef()->isSubClassOf("Register")) { + if (!InstOpRec->isSubClassOf("RegisterClass")) + return false; + + if (!T.getRegisterClass(InstOpRec).containsRegister(ADI->getDef())) + throw TGError(Loc, "fixed register " +ADI->getDef()->getName() + + " is not a member of the " + InstOpRec->getName() + + " register class!"); + + if (!Result->getArgName(AliasOpNo).empty()) + throw TGError(Loc, "result fixed register argument must " + "not have a name!"); + + ResOp = ResultOperand(ADI->getDef()); + return true; + } + + // Handle "zero_reg" for optional def operands. + if (ADI && ADI->getDef()->getName() == "zero_reg") { + + // Check if this is an optional def. + if (!InstOpRec->isSubClassOf("OptionalDefOperand")) + throw TGError(Loc, "reg0 used for result that is not an " + "OptionalDefOperand!"); + + ResOp = ResultOperand(static_cast<Record*>(0)); + return true; + } + + if (IntInit *II = dynamic_cast<IntInit*>(Arg)) { + if (hasSubOps || !InstOpRec->isSubClassOf("Operand")) + return false; + // Integer arguments can't have names. + if (!Result->getArgName(AliasOpNo).empty()) + throw TGError(Loc, "result argument #" + utostr(AliasOpNo) + + " must not have a name!"); + ResOp = ResultOperand(II->getValue()); + return true; + } + + return false; +} + +CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) { + AsmString = R->getValueAsString("AsmString"); + Result = R->getValueAsDag("ResultInst"); + + // Verify that the root of the result is an instruction. + DefInit *DI = dynamic_cast<DefInit*>(Result->getOperator()); + if (DI == 0 || !DI->getDef()->isSubClassOf("Instruction")) + throw TGError(R->getLoc(), "result of inst alias should be an instruction"); + + ResultInst = &T.getInstruction(DI->getDef()); + + // NameClass - If argument names are repeated, we need to verify they have + // the same class. + StringMap<Record*> NameClass; + for (unsigned i = 0, e = Result->getNumArgs(); i != e; ++i) { + DefInit *ADI = dynamic_cast<DefInit*>(Result->getArg(i)); + if (!ADI || Result->getArgName(i).empty()) + continue; + // Verify we don't have something like: (someinst GR16:$foo, GR32:$foo) + // $foo can exist multiple times in the result list, but it must have the + // same type. + Record *&Entry = NameClass[Result->getArgName(i)]; + if (Entry && Entry != ADI->getDef()) + throw TGError(R->getLoc(), "result value $" + Result->getArgName(i) + + " is both " + Entry->getName() + " and " + + ADI->getDef()->getName() + "!"); + Entry = ADI->getDef(); + } + + // Decode and validate the arguments of the result. + unsigned AliasOpNo = 0; + for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) { + + // Tied registers don't have an entry in the result dag. + if (ResultInst->Operands[i].getTiedRegister() != -1) + continue; + + if (AliasOpNo >= Result->getNumArgs()) + throw TGError(R->getLoc(), "not enough arguments for instruction!"); + + Record *InstOpRec = ResultInst->Operands[i].Rec; + unsigned NumSubOps = ResultInst->Operands[i].MINumOperands; + ResultOperand ResOp(static_cast<int64_t>(0)); + if (tryAliasOpMatch(Result, AliasOpNo, InstOpRec, (NumSubOps > 1), + R->getLoc(), T, ResOp)) { + ResultOperands.push_back(ResOp); + ResultInstOperandIndex.push_back(std::make_pair(i, -1)); + ++AliasOpNo; + continue; + } + + // If the argument did not match the instruction operand, and the operand + // is composed of multiple suboperands, try matching the suboperands. + if (NumSubOps > 1) { + DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo; + for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) { + if (AliasOpNo >= Result->getNumArgs()) + throw TGError(R->getLoc(), "not enough arguments for instruction!"); + Record *SubRec = dynamic_cast<DefInit*>(MIOI->getArg(SubOp))->getDef(); + if (tryAliasOpMatch(Result, AliasOpNo, SubRec, false, + R->getLoc(), T, ResOp)) { + ResultOperands.push_back(ResOp); + ResultInstOperandIndex.push_back(std::make_pair(i, SubOp)); + ++AliasOpNo; + } else { + throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + + " does not match instruction operand class " + + (SubOp == 0 ? InstOpRec->getName() :SubRec->getName())); + } + } + continue; + } + throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + + " does not match instruction operand class " + + InstOpRec->getName()); + } + + if (AliasOpNo != Result->getNumArgs()) + throw TGError(R->getLoc(), "too many operands for instruction!"); +} diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index b02d0d3..58913b9 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -15,6 +15,8 @@ #define CODEGEN_INSTRUCTION_H #include "llvm/CodeGen/ValueTypes.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/SourceMgr.h" #include <string> #include <vector> #include <utility> @@ -23,22 +25,16 @@ namespace llvm { class Record; class DagInit; class CodeGenTarget; - - class CodeGenInstruction { + class StringRef; + + class CGIOperandList { public: - Record *TheDef; // The actual record defining this instruction. - std::string Namespace; // The namespace the instruction is in. - - /// AsmString - The format string used to emit a .s file for the - /// instruction. - std::string AsmString; - class ConstraintInfo { enum { None, EarlyClobber, Tied } Kind; unsigned OtherTiedOperand; public: ConstraintInfo() : Kind(None) {} - + static ConstraintInfo getEarlyClobber() { ConstraintInfo I; I.Kind = EarlyClobber; @@ -62,22 +58,26 @@ namespace llvm { return OtherTiedOperand; } }; - + /// OperandInfo - The information we keep track of for each operand in the /// operand list for a tablegen instruction. struct OperandInfo { /// Rec - The definition this operand is declared as. /// Record *Rec; - + /// Name - If this operand was assigned a symbolic name, this is it, /// otherwise, it's empty. std::string Name; - + /// PrinterMethodName - The method used to print operands of this type in /// the asmprinter. std::string PrinterMethodName; - + + /// EncoderMethodName - The method used to get the machine operand value + /// for binary encoding. "getMachineOpValue" by default. + std::string EncoderMethodName; + /// MIOperandNo - Currently (this is meant to be phased out), some logical /// operands correspond to multiple MachineInstr operands. In the X86 /// target for example, one address operand is represented as 4 @@ -86,7 +86,7 @@ namespace llvm { /// does, this contains the MI operand index of this operand. unsigned MIOperandNo; unsigned MINumOperands; // The number of operands. - + /// DoNotEncode - Bools are set to true in this vector for each operand in /// the DisableEncoding list. These should not be emitted by the code /// emitter. @@ -99,52 +99,61 @@ namespace llvm { /// Constraint info for this operand. This operand can have pieces, so we /// track constraint info for each. std::vector<ConstraintInfo> Constraints; - - OperandInfo(Record *R, const std::string &N, const std::string &PMN, - unsigned MION, unsigned MINO, DagInit *MIOI) - : Rec(R), Name(N), PrinterMethodName(PMN), MIOperandNo(MION), - MINumOperands(MINO), MIOperandInfo(MIOI) {} + + OperandInfo(Record *R, const std::string &N, const std::string &PMN, + const std::string &EMN, unsigned MION, unsigned MINO, + DagInit *MIOI) + : Rec(R), Name(N), PrinterMethodName(PMN), EncoderMethodName(EMN), + MIOperandNo(MION), MINumOperands(MINO), MIOperandInfo(MIOI) {} + + + /// getTiedOperand - If this operand is tied to another one, return the + /// other operand number. Otherwise, return -1. + int getTiedRegister() const { + for (unsigned j = 0, e = Constraints.size(); j != e; ++j) { + const CGIOperandList::ConstraintInfo &CI = Constraints[j]; + if (CI.isTied()) return CI.getTiedOperand(); + } + return -1; + } }; + + CGIOperandList(Record *D); + + Record *TheDef; // The actual record containing this OperandList. /// NumDefs - Number of def operands declared, this is the number of /// elements in the instruction's (outs) list. /// unsigned NumDefs; - + /// OperandList - The list of declared operands, along with their declared /// type (which is a record). std::vector<OperandInfo> OperandList; - - /// ImplicitDefs/ImplicitUses - These are lists of registers that are - /// implicitly defined and used by the instruction. - std::vector<Record*> ImplicitDefs, ImplicitUses; - - // Various boolean values we track for the instruction. - bool isReturn; - bool isBranch; - bool isIndirectBranch; - bool isCompare; - bool isBarrier; - bool isCall; - bool canFoldAsLoad; - bool mayLoad, mayStore; + + // Information gleaned from the operand list. bool isPredicable; - bool isConvertibleToThreeAddress; - bool isCommutable; - bool isTerminator; - bool isReMaterializable; - bool hasDelaySlot; - bool usesCustomInserter; - bool isVariadic; - bool hasCtrlDep; - bool isNotDuplicable; bool hasOptionalDef; - bool hasSideEffects; - bool neverHasSideEffects; - bool isAsCheapAsAMove; - bool hasExtraSrcRegAllocReq; - bool hasExtraDefRegAllocReq; + bool isVariadic; + + // Provide transparent accessors to the operand list. + unsigned size() const { return OperandList.size(); } + const OperandInfo &operator[](unsigned i) const { return OperandList[i]; } + OperandInfo &operator[](unsigned i) { return OperandList[i]; } + OperandInfo &back() { return OperandList.back(); } + const OperandInfo &back() const { return OperandList.back(); } + + + /// getOperandNamed - Return the index of the operand with the specified + /// non-empty name. If the instruction does not have an operand with the + /// specified name, throw an exception. + unsigned getOperandNamed(StringRef Name) const; + /// hasOperandNamed - Query whether the instruction has an operand of the + /// given name. If so, return true and set OpIdx to the index of the + /// operand. Otherwise, return false. + bool hasOperandNamed(StringRef Name, unsigned &OpIdx) const; + /// ParseOperandName - Parse an operand name like "$foo" or "$foo.bar", /// where $foo is a whole operand and $foo.bar refers to a suboperand. /// This throws an exception if the name is invalid. If AllowWholeOp is @@ -178,20 +187,130 @@ namespace llvm { return OperandList[Op.first].DoNotEncode[Op.second]; return false; } + + void ProcessDisableEncoding(std::string Value); + }; + - CodeGenInstruction(Record *R, const std::string &AsmStr); + class CodeGenInstruction { + public: + Record *TheDef; // The actual record defining this instruction. + std::string Namespace; // The namespace the instruction is in. + + /// AsmString - The format string used to emit a .s file for the + /// instruction. + std::string AsmString; + + /// Operands - This is information about the (ins) and (outs) list specified + /// to the instruction. + CGIOperandList Operands; + + /// ImplicitDefs/ImplicitUses - These are lists of registers that are + /// implicitly defined and used by the instruction. + std::vector<Record*> ImplicitDefs, ImplicitUses; + + // Various boolean values we track for the instruction. + bool isReturn; + bool isBranch; + bool isIndirectBranch; + bool isCompare; + bool isMoveImm; + bool isBarrier; + bool isCall; + bool canFoldAsLoad; + bool mayLoad, mayStore; + bool isPredicable; + bool isConvertibleToThreeAddress; + bool isCommutable; + bool isTerminator; + bool isReMaterializable; + bool hasDelaySlot; + bool usesCustomInserter; + bool hasCtrlDep; + bool isNotDuplicable; + bool hasSideEffects; + bool neverHasSideEffects; + bool isAsCheapAsAMove; + bool hasExtraSrcRegAllocReq; + bool hasExtraDefRegAllocReq; + + + CodeGenInstruction(Record *R); - /// getOperandNamed - Return the index of the operand with the specified - /// non-empty name. If the instruction does not have an operand with the - /// specified name, throw an exception. - unsigned getOperandNamed(const std::string &Name) const; - /// HasOneImplicitDefWithKnownVT - If the instruction has at least one /// implicit def and it has a known VT, return the VT, otherwise return /// MVT::Other. - MVT::SimpleValueType + MVT::SimpleValueType HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const; + + + /// FlattenAsmStringVariants - Flatten the specified AsmString to only + /// include text from the specified variant, returning the new string. + static std::string FlattenAsmStringVariants(StringRef AsmString, + unsigned Variant); }; + + + /// CodeGenInstAlias - This represents an InstAlias definition. + class CodeGenInstAlias { + public: + Record *TheDef; // The actual record defining this InstAlias. + + /// AsmString - The format string used to emit a .s file for the + /// instruction. + std::string AsmString; + + /// Result - The result instruction. + DagInit *Result; + + /// ResultInst - The instruction generated by the alias (decoded from + /// Result). + CodeGenInstruction *ResultInst; + + + struct ResultOperand { + private: + StringRef Name; + Record *R; + + int64_t Imm; + public: + enum { + K_Record, + K_Imm, + K_Reg + } Kind; + + ResultOperand(StringRef N, Record *r) : Name(N), R(r), Kind(K_Record) {} + ResultOperand(int64_t I) : Imm(I), Kind(K_Imm) {} + ResultOperand(Record *r) : R(r), Kind(K_Reg) {} + + bool isRecord() const { return Kind == K_Record; } + bool isImm() const { return Kind == K_Imm; } + bool isReg() const { return Kind == K_Reg; } + + StringRef getName() const { assert(isRecord()); return Name; } + Record *getRecord() const { assert(isRecord()); return R; } + int64_t getImm() const { assert(isImm()); return Imm; } + Record *getRegister() const { assert(isReg()); return R; } + }; + + /// ResultOperands - The decoded operands for the result instruction. + std::vector<ResultOperand> ResultOperands; + + /// ResultInstOperandIndex - For each operand, this vector holds a pair of + /// indices to identify the corresponding operand in the result + /// instruction. The first index specifies the operand and the second + /// index specifies the suboperand. If there are no suboperands or if all + /// of them are matched by the operand, the second value should be -1. + std::vector<std::pair<unsigned, int> > ResultInstOperandIndex; + + CodeGenInstAlias(Record *R, CodeGenTarget &T); + + bool tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, + Record *InstOpRec, bool hasSubOps, SMLoc Loc, + CodeGenTarget &T, ResultOperand &ResOp); + }; } #endif diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h index ccd3d22..bbd0cef 100644 --- a/utils/TableGen/CodeGenRegisters.h +++ b/utils/TableGen/CodeGenRegisters.h @@ -57,6 +57,12 @@ namespace llvm { abort(); } + bool containsRegister(Record *R) const { + for (unsigned i = 0, e = Elements.size(); i != e; ++i) + if (Elements[i] == R) return true; + return false; + } + // Returns true if RC is a strict subclass. // RC is a sub-class of this class if it is a valid replacement for any // instruction operand where a register of this classis required. It must diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index cbfe2ad..d0f7d8b 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -48,46 +48,47 @@ std::string llvm::getName(MVT::SimpleValueType T) { std::string llvm::getEnumName(MVT::SimpleValueType T) { switch (T) { - case MVT::Other: return "MVT::Other"; - case MVT::i1: return "MVT::i1"; - case MVT::i8: return "MVT::i8"; - case MVT::i16: return "MVT::i16"; - case MVT::i32: return "MVT::i32"; - case MVT::i64: return "MVT::i64"; - case MVT::i128: return "MVT::i128"; - case MVT::iAny: return "MVT::iAny"; - case MVT::fAny: return "MVT::fAny"; - case MVT::vAny: return "MVT::vAny"; - case MVT::f32: return "MVT::f32"; - case MVT::f64: return "MVT::f64"; - case MVT::f80: return "MVT::f80"; - case MVT::f128: return "MVT::f128"; + case MVT::Other: return "MVT::Other"; + case MVT::i1: return "MVT::i1"; + case MVT::i8: return "MVT::i8"; + case MVT::i16: return "MVT::i16"; + case MVT::i32: return "MVT::i32"; + case MVT::i64: return "MVT::i64"; + case MVT::i128: return "MVT::i128"; + case MVT::iAny: return "MVT::iAny"; + case MVT::fAny: return "MVT::fAny"; + case MVT::vAny: return "MVT::vAny"; + case MVT::f32: return "MVT::f32"; + case MVT::f64: return "MVT::f64"; + case MVT::f80: return "MVT::f80"; + case MVT::f128: return "MVT::f128"; case MVT::ppcf128: return "MVT::ppcf128"; - case MVT::Flag: return "MVT::Flag"; - case MVT::isVoid:return "MVT::isVoid"; - case MVT::v2i8: return "MVT::v2i8"; - case MVT::v4i8: return "MVT::v4i8"; - case MVT::v8i8: return "MVT::v8i8"; - case MVT::v16i8: return "MVT::v16i8"; - case MVT::v32i8: return "MVT::v32i8"; - case MVT::v2i16: return "MVT::v2i16"; - case MVT::v4i16: return "MVT::v4i16"; - case MVT::v8i16: return "MVT::v8i16"; - case MVT::v16i16: return "MVT::v16i16"; - case MVT::v2i32: return "MVT::v2i32"; - case MVT::v4i32: return "MVT::v4i32"; - case MVT::v8i32: return "MVT::v8i32"; - case MVT::v1i64: return "MVT::v1i64"; - case MVT::v2i64: return "MVT::v2i64"; - case MVT::v4i64: return "MVT::v4i64"; - case MVT::v8i64: return "MVT::v8i64"; - case MVT::v2f32: return "MVT::v2f32"; - case MVT::v4f32: return "MVT::v4f32"; - case MVT::v8f32: return "MVT::v8f32"; - case MVT::v2f64: return "MVT::v2f64"; - case MVT::v4f64: return "MVT::v4f64"; + case MVT::x86mmx: return "MVT::x86mmx"; + case MVT::Glue: return "MVT::Glue"; + case MVT::isVoid: return "MVT::isVoid"; + case MVT::v2i8: return "MVT::v2i8"; + case MVT::v4i8: return "MVT::v4i8"; + case MVT::v8i8: return "MVT::v8i8"; + case MVT::v16i8: return "MVT::v16i8"; + case MVT::v32i8: return "MVT::v32i8"; + case MVT::v2i16: return "MVT::v2i16"; + case MVT::v4i16: return "MVT::v4i16"; + case MVT::v8i16: return "MVT::v8i16"; + case MVT::v16i16: return "MVT::v16i16"; + case MVT::v2i32: return "MVT::v2i32"; + case MVT::v4i32: return "MVT::v4i32"; + case MVT::v8i32: return "MVT::v8i32"; + case MVT::v1i64: return "MVT::v1i64"; + case MVT::v2i64: return "MVT::v2i64"; + case MVT::v4i64: return "MVT::v4i64"; + case MVT::v8i64: return "MVT::v8i64"; + case MVT::v2f32: return "MVT::v2f32"; + case MVT::v4f32: return "MVT::v4f32"; + case MVT::v8f32: return "MVT::v8f32"; + case MVT::v2f64: return "MVT::v2f64"; + case MVT::v4f64: return "MVT::v4f64"; case MVT::Metadata: return "MVT::Metadata"; - case MVT::iPTR: return "MVT::iPTR"; + case MVT::iPTR: return "MVT::iPTR"; case MVT::iPTRAny: return "MVT::iPTRAny"; default: assert(0 && "ILLEGAL VALUE TYPE!"); return ""; } @@ -107,7 +108,7 @@ std::string llvm::getQualifiedName(const Record *R) { /// getTarget - Return the current instance of the Target class. /// -CodeGenTarget::CodeGenTarget() { +CodeGenTarget::CodeGenTarget(RecordKeeper &records) : Records(records) { std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target"); if (Targets.size() == 0) throw std::string("ERROR: No 'Target' subclasses defined!"); @@ -189,6 +190,19 @@ void CodeGenTarget::ReadRegisterClasses() const { RegisterClasses.assign(RegClasses.begin(), RegClasses.end()); } +/// getRegisterByName - If there is a register with the specific AsmName, +/// return it. +const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const { + const std::vector<CodeGenRegister> &Regs = getRegisters(); + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister &Reg = Regs[i]; + if (Reg.TheDef->getValueAsString("AsmName") == Name) + return &Reg; + } + + return 0; +} + std::vector<MVT::SimpleValueType> CodeGenTarget:: getRegisterVTs(Record *R) const { std::vector<MVT::SimpleValueType> Result; @@ -294,18 +308,14 @@ void CodeGenTarget::ReadInstructions() const { throw std::string("No 'Instruction' subclasses defined!"); // Parse the instructions defined in the .td file. - std::string InstFormatName = - getAsmWriter()->getValueAsString("InstFormatName"); - - for (unsigned i = 0, e = Insts.size(); i != e; ++i) { - std::string AsmStr = Insts[i]->getValueAsString(InstFormatName); - Instructions[Insts[i]] = new CodeGenInstruction(Insts[i], AsmStr); - } + for (unsigned i = 0, e = Insts.size(); i != e; ++i) + Instructions[Insts[i]] = new CodeGenInstruction(Insts[i]); } static const CodeGenInstruction * GetInstByName(const char *Name, - const DenseMap<const Record*, CodeGenInstruction*> &Insts) { + const DenseMap<const Record*, CodeGenInstruction*> &Insts, + RecordKeeper &Records) { const Record *Rec = Records.getDef(Name); DenseMap<const Record*, CodeGenInstruction*>::const_iterator @@ -349,7 +359,7 @@ void CodeGenTarget::ComputeInstrsByEnum() const { }; const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions(); for (const char *const *p = FixedInstrs; *p; ++p) { - const CodeGenInstruction *Instr = GetInstByName(*p, Insts); + const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records); assert(Instr && "Missing target independent instruction"); assert(Instr->Namespace == "TargetOpcode" && "Bad namespace"); InstrsByEnum.push_back(Instr); @@ -394,8 +404,8 @@ ComplexPattern::ComplexPattern(Record *R) { for (unsigned i = 0, e = PropList.size(); i != e; ++i) if (PropList[i]->getName() == "SDNPHasChain") { Properties |= 1 << SDNPHasChain; - } else if (PropList[i]->getName() == "SDNPOptInFlag") { - Properties |= 1 << SDNPOptInFlag; + } else if (PropList[i]->getName() == "SDNPOptInGlue") { + Properties |= 1 << SDNPOptInGlue; } else if (PropList[i]->getName() == "SDNPMayStore") { Properties |= 1 << SDNPMayStore; } else if (PropList[i]->getName() == "SDNPMayLoad") { @@ -406,6 +416,10 @@ ComplexPattern::ComplexPattern(Record *R) { Properties |= 1 << SDNPMemOperand; } else if (PropList[i]->getName() == "SDNPVariadic") { Properties |= 1 << SDNPVariadic; + } else if (PropList[i]->getName() == "SDNPWantRoot") { + Properties |= 1 << SDNPWantRoot; + } else if (PropList[i]->getName() == "SDNPWantParent") { + Properties |= 1 << SDNPWantParent; } else { errs() << "Unsupported SD Node property '" << PropList[i]->getName() << "' on ComplexPattern '" << R->getName() << "'!\n"; diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h index 6b06b66..f1058eb 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -35,14 +35,16 @@ enum SDNP { SDNPCommutative, SDNPAssociative, SDNPHasChain, - SDNPOutFlag, - SDNPInFlag, - SDNPOptInFlag, + SDNPOutGlue, + SDNPInGlue, + SDNPOptInGlue, SDNPMayLoad, SDNPMayStore, SDNPSideEffect, SDNPMemOperand, - SDNPVariadic + SDNPVariadic, + SDNPWantRoot, + SDNPWantParent }; /// getValueType - Return the MVT::SimpleValueType that the specified TableGen @@ -59,6 +61,7 @@ std::string getQualifiedName(const Record *R); /// CodeGenTarget - This class corresponds to the Target class in the .td files. /// class CodeGenTarget { + RecordKeeper &Records; Record *TargetRec; mutable DenseMap<const Record*, CodeGenInstruction*> Instructions; @@ -74,7 +77,7 @@ class CodeGenTarget { mutable std::vector<const CodeGenInstruction*> InstrsByEnum; public: - CodeGenTarget(); + CodeGenTarget(RecordKeeper &Records); Record *getTargetRecord() const { return TargetRec; } const std::string &getName() const; @@ -99,6 +102,10 @@ public: if (Registers.empty()) ReadRegisters(); return Registers; } + + /// getRegisterByName - If there is a register with the specific AsmName, + /// return it. + const CodeGenRegister *getRegisterByName(StringRef Name) const; const std::vector<Record*> &getSubRegIndices() const { if (SubRegIndices.empty()) ReadSubRegIndices(); diff --git a/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp index 9f12a68..2afa2b9 100644 --- a/utils/TableGen/DAGISelMatcher.cpp +++ b/utils/TableGen/DAGISelMatcher.cpp @@ -35,7 +35,7 @@ void Matcher::printOne(raw_ostream &OS) const { Matcher *Matcher::unlinkNode(Matcher *Other) { if (this == Other) return takeNext(); - + // Scan until we find the predecessor of Other. Matcher *Cur = this; for (; Cur && Cur->getNext() != Other; Cur = Cur->getNext()) @@ -67,11 +67,11 @@ bool Matcher::canMoveBeforeNode(const Matcher *Other) const { // We can move simple predicates before record nodes. if (isSimplePredicateNode()) return Other->isSimplePredicateOrRecordNode(); - + // We can move record nodes across simple predicates. if (isSimplePredicateOrRecordNode()) return isSimplePredicateNode(); - + // We can't move record nodes across each other etc. return false; } @@ -107,8 +107,8 @@ void RecordMemRefMatcher::printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "RecordMemRef\n"; } -void CaptureFlagInputMatcher::printImpl(raw_ostream &OS, unsigned indent) const{ - OS.indent(indent) << "CaptureFlagInput\n"; +void CaptureGlueInputMatcher::printImpl(raw_ostream &OS, unsigned indent) const{ + OS.indent(indent) << "CaptureGlueInput\n"; } void MoveChildMatcher::printImpl(raw_ostream &OS, unsigned indent) const { @@ -246,8 +246,8 @@ void EmitNodeMatcherCommon::printImpl(raw_ostream &OS, unsigned indent) const { OS << ")\n"; } -void MarkFlagResultsMatcher::printImpl(raw_ostream &OS, unsigned indent) const { - OS.indent(indent) << "MarkFlagResults <todo: args>\n"; +void MarkGlueResultsMatcher::printImpl(raw_ostream &OS, unsigned indent) const { + OS.indent(indent) << "MarkGlueResults <todo: args>\n"; } void CompleteMatchMatcher::printImpl(raw_ostream &OS, unsigned indent) const { @@ -296,7 +296,7 @@ unsigned EmitMergeInputChainsMatcher::getHashImpl() const { bool CheckOpcodeMatcher::isEqualImpl(const Matcher *M) const { // Note: pointer equality isn't enough here, we have to check the enum names - // to ensure that the nodes are for the same opcode. + // to ensure that the nodes are for the same opcode. return cast<CheckOpcodeMatcher>(M)->Opcode.getEnumName() == Opcode.getEnumName(); } @@ -306,7 +306,7 @@ bool EmitNodeMatcherCommon::isEqualImpl(const Matcher *m) const { const EmitNodeMatcherCommon *M = cast<EmitNodeMatcherCommon>(m); return M->OpcodeName == OpcodeName && M->VTs == VTs && M->Operands == Operands && M->HasChain == HasChain && - M->HasInFlag == HasInFlag && M->HasOutFlag == HasOutFlag && + M->HasInGlue == HasInGlue && M->HasOutGlue == HasOutGlue && M->HasMemRefs == HasMemRefs && M->NumFixedArityOperands == NumFixedArityOperands; } @@ -316,12 +316,12 @@ unsigned EmitNodeMatcherCommon::getHashImpl() const { } -unsigned MarkFlagResultsMatcher::getHashImpl() const { - return HashUnsigneds(FlagResultNodes.begin(), FlagResultNodes.end()); +unsigned MarkGlueResultsMatcher::getHashImpl() const { + return HashUnsigneds(GlueResultNodes.begin(), GlueResultNodes.end()); } unsigned CompleteMatchMatcher::getHashImpl() const { - return HashUnsigneds(Results.begin(), Results.end()) ^ + return HashUnsigneds(Results.begin(), Results.end()) ^ ((unsigned)(intptr_t)&Pattern << 8); } @@ -332,15 +332,15 @@ static bool TypesAreContradictory(MVT::SimpleValueType T1, // If the two types are the same, then they are the same, so they don't // contradict. if (T1 == T2) return false; - + // If either type is about iPtr, then they don't conflict unless the other // one is not a scalar integer type. if (T1 == MVT::iPTR) return !MVT(T2).isInteger() || MVT(T2).isVector(); - + if (T2 == MVT::iPTR) return !MVT(T1).isInteger() || MVT(T1).isVector(); - + // Otherwise, they are two different non-iPTR types, they conflict. return true; } @@ -349,10 +349,10 @@ bool CheckOpcodeMatcher::isContradictoryImpl(const Matcher *M) const { if (const CheckOpcodeMatcher *COM = dyn_cast<CheckOpcodeMatcher>(M)) { // One node can't have two different opcodes! // Note: pointer equality isn't enough here, we have to check the enum names - // to ensure that the nodes are for the same opcode. + // to ensure that the nodes are for the same opcode. return COM->getOpcode().getEnumName() != getOpcode().getEnumName(); } - + // If the node has a known type, and if the type we're checking for is // different, then we know they contradict. For example, a check for // ISD::STORE will never be true at the same time a check for Type i32 is. @@ -360,12 +360,12 @@ bool CheckOpcodeMatcher::isContradictoryImpl(const Matcher *M) const { // If checking for a result the opcode doesn't have, it can't match. if (CT->getResNo() >= getOpcode().getNumResults()) return true; - + MVT::SimpleValueType NodeType = getOpcode().getKnownType(CT->getResNo()); if (NodeType != MVT::Other) return TypesAreContradictory(NodeType, CT->getType()); } - + return false; } @@ -381,12 +381,12 @@ bool CheckChildTypeMatcher::isContradictoryImpl(const Matcher *M) const { // conflict! if (CC->getChildNo() != getChildNo()) return false; - + return TypesAreContradictory(getType(), CC->getType()); } return false; } - + bool CheckIntegerMatcher::isContradictoryImpl(const Matcher *M) const { if (const CheckIntegerMatcher *CIM = dyn_cast<CheckIntegerMatcher>(M)) return CIM->getValue() != getValue(); diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h index d9b25d5..8e6e446 100644 --- a/utils/TableGen/DAGISelMatcher.h +++ b/utils/TableGen/DAGISelMatcher.h @@ -31,7 +31,7 @@ Matcher *OptimizeMatcher(Matcher *Matcher, const CodeGenDAGPatterns &CGP); void EmitMatcherTable(const Matcher *Matcher, const CodeGenDAGPatterns &CGP, raw_ostream &OS); - + /// Matcher - Base class for all the the DAG ISel Matcher representation /// nodes. class Matcher { @@ -45,10 +45,10 @@ public: RecordNode, // Record the current node. RecordChild, // Record a child of the current node. RecordMemRef, // Record the memref in the current node. - CaptureFlagInput, // If the current node has an input flag, save it. + CaptureGlueInput, // If the current node has an input glue, save it. MoveChild, // Move current node to specified child. MoveParent, // Move current node to parent. - + // Predicate checking. CheckSame, // Fail if not same as prev match. CheckPatternPredicate, @@ -65,7 +65,7 @@ public: CheckAndImm, CheckOrImm, CheckFoldableChainNode, - + // Node creation/emisssion. EmitInteger, // Create a TargetConstant EmitStringInteger, // Create a TargetConstant from a string. @@ -75,7 +75,7 @@ public: EmitCopyToReg, // Emit a copytoreg into a physreg. EmitNode, // Create a DAG node EmitNodeXForm, // Run a SDNodeXForm - MarkFlagResults, // Indicate which interior nodes have flag results. + MarkGlueResults, // Indicate which interior nodes have glue results. CompleteMatch, // Finish a match and update the results. MorphNodeTo // Build a node, finish a match and update results. }; @@ -85,7 +85,7 @@ protected: Matcher(KindTy K) : Kind(K) {} public: virtual ~Matcher() {} - + KindTy getKind() const { return Kind; } Matcher *getNext() { return Next.get(); } @@ -94,25 +94,25 @@ public: Matcher *takeNext() { return Next.take(); } OwningPtr<Matcher> &getNextPtr() { return Next; } - + static inline bool classof(const Matcher *) { return true; } - + bool isEqual(const Matcher *M) const { if (getKind() != M->getKind()) return false; return isEqualImpl(M); } - + unsigned getHash() const { // Clear the high bit so we don't conflict with tombstones etc. return ((getHashImpl() << 4) ^ getKind()) & (~0U>>1); } - + /// isSafeToReorderWithPatternPredicate - Return true if it is safe to sink a /// PatternPredicate node past this one. virtual bool isSafeToReorderWithPatternPredicate() const { return false; } - + /// isSimplePredicateNode - Return true if this is a simple predicate that /// operates on the node or its children without potential side effects or a /// change of the current node. @@ -134,28 +134,28 @@ public: return true; } } - + /// isSimplePredicateOrRecordNode - Return true if this is a record node or /// a simple predicate. bool isSimplePredicateOrRecordNode() const { return isSimplePredicateNode() || getKind() == RecordNode || getKind() == RecordChild; } - + /// unlinkNode - Unlink the specified node from this chain. If Other == this, /// we unlink the next pointer and return it. Otherwise we unlink Other from /// the list and return this. Matcher *unlinkNode(Matcher *Other); - + /// canMoveBefore - Return true if this matcher is the same as Other, or if /// we can move this matcher past all of the nodes in-between Other and this /// node. Other must be equal to or before this. bool canMoveBefore(const Matcher *Other) const; - + /// canMoveBefore - Return true if it is safe to move the current matcher /// across the specified one. bool canMoveBeforeNode(const Matcher *Other) const; - + /// isContradictory - Return true of these two matchers could never match on /// the same node. bool isContradictory(const Matcher *Other) const { @@ -167,7 +167,7 @@ public: return isContradictoryImpl(Other); return Other->isContradictoryImpl(this); } - + void print(raw_ostream &OS, unsigned indent = 0) const; void printOne(raw_ostream &OS) const; void dump() const; @@ -177,7 +177,7 @@ protected: virtual unsigned getHashImpl() const = 0; virtual bool isContradictoryImpl(const Matcher *M) const { return false; } }; - + /// ScopeMatcher - This attempts to match each of its children to find the first /// one that successfully matches. If one child fails, it tries the next child. /// If none of the children match then this check fails. It never has a 'next'. @@ -188,12 +188,12 @@ public: : Matcher(Scope), Children(children, children+numchildren) { } virtual ~ScopeMatcher(); - + unsigned getNumChildren() const { return Children.size(); } - + Matcher *getChild(unsigned i) { return Children[i]; } const Matcher *getChild(unsigned i) const { return Children[i]; } - + void resetChild(unsigned i, Matcher *N) { delete Children[i]; Children[i] = N; @@ -204,7 +204,7 @@ public: Children[i] = 0; return Res; } - + void setNumChildren(unsigned NC) { if (NC < Children.size()) { // delete any children we're about to lose pointers to. @@ -217,7 +217,7 @@ public: static inline bool classof(const Matcher *N) { return N->getKind() == Scope; } - + private: virtual void printImpl(raw_ostream &OS, unsigned indent) const; virtual bool isEqualImpl(const Matcher *M) const { return false; } @@ -229,38 +229,38 @@ class RecordMatcher : public Matcher { /// WhatFor - This is a string indicating why we're recording this. This /// should only be used for comment generation not anything semantic. std::string WhatFor; - + /// ResultNo - The slot number in the RecordedNodes vector that this will be, /// just printed as a comment. unsigned ResultNo; public: RecordMatcher(const std::string &whatfor, unsigned resultNo) : Matcher(RecordNode), WhatFor(whatfor), ResultNo(resultNo) {} - + const std::string &getWhatFor() const { return WhatFor; } unsigned getResultNo() const { return ResultNo; } - + static inline bool classof(const Matcher *N) { return N->getKind() == RecordNode; } - + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } private: virtual void printImpl(raw_ostream &OS, unsigned indent) const; virtual bool isEqualImpl(const Matcher *M) const { return true; } virtual unsigned getHashImpl() const { return 0; } }; - + /// RecordChildMatcher - Save a numbered child of the current node, or fail /// the match if it doesn't exist. This is logically equivalent to: /// MoveChild N + RecordNode + MoveParent. class RecordChildMatcher : public Matcher { unsigned ChildNo; - + /// WhatFor - This is a string indicating why we're recording this. This /// should only be used for comment generation not anything semantic. std::string WhatFor; - + /// ResultNo - The slot number in the RecordedNodes vector that this will be, /// just printed as a comment. unsigned ResultNo; @@ -269,7 +269,7 @@ public: unsigned resultNo) : Matcher(RecordChild), ChildNo(childno), WhatFor(whatfor), ResultNo(resultNo) {} - + unsigned getChildNo() const { return ChildNo; } const std::string &getWhatFor() const { return WhatFor; } unsigned getResultNo() const { return ResultNo; } @@ -277,7 +277,7 @@ public: static inline bool classof(const Matcher *N) { return N->getKind() == RecordChild; } - + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } private: @@ -287,16 +287,16 @@ private: } virtual unsigned getHashImpl() const { return getChildNo(); } }; - + /// RecordMemRefMatcher - Save the current node's memref. class RecordMemRefMatcher : public Matcher { public: RecordMemRefMatcher() : Matcher(RecordMemRef) {} - + static inline bool classof(const Matcher *N) { return N->getKind() == RecordMemRef; } - + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } private: @@ -305,17 +305,17 @@ private: virtual unsigned getHashImpl() const { return 0; } }; - -/// CaptureFlagInputMatcher - If the current record has a flag input, record + +/// CaptureGlueInputMatcher - If the current record has a glue input, record /// it so that it is used as an input to the generated code. -class CaptureFlagInputMatcher : public Matcher { +class CaptureGlueInputMatcher : public Matcher { public: - CaptureFlagInputMatcher() : Matcher(CaptureFlagInput) {} - + CaptureGlueInputMatcher() : Matcher(CaptureGlueInput) {} + static inline bool classof(const Matcher *N) { - return N->getKind() == CaptureFlagInput; + return N->getKind() == CaptureGlueInput; } - + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } private: @@ -323,20 +323,20 @@ private: virtual bool isEqualImpl(const Matcher *M) const { return true; } virtual unsigned getHashImpl() const { return 0; } }; - + /// MoveChildMatcher - This tells the interpreter to move into the /// specified child node. class MoveChildMatcher : public Matcher { unsigned ChildNo; public: MoveChildMatcher(unsigned childNo) : Matcher(MoveChild), ChildNo(childNo) {} - + unsigned getChildNo() const { return ChildNo; } - + static inline bool classof(const Matcher *N) { return N->getKind() == MoveChild; } - + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } private: @@ -346,17 +346,17 @@ private: } virtual unsigned getHashImpl() const { return getChildNo(); } }; - + /// MoveParentMatcher - This tells the interpreter to move to the parent /// of the current node. class MoveParentMatcher : public Matcher { public: MoveParentMatcher() : Matcher(MoveParent) {} - + static inline bool classof(const Matcher *N) { return N->getKind() == MoveParent; } - + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } private: @@ -373,13 +373,13 @@ class CheckSameMatcher : public Matcher { public: CheckSameMatcher(unsigned matchnumber) : Matcher(CheckSame), MatchNumber(matchnumber) {} - + unsigned getMatchNumber() const { return MatchNumber; } - + static inline bool classof(const Matcher *N) { return N->getKind() == CheckSame; } - + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } private: @@ -389,7 +389,7 @@ private: } virtual unsigned getHashImpl() const { return getMatchNumber(); } }; - + /// CheckPatternPredicateMatcher - This checks the target-specific predicate /// to see if the entire pattern is capable of matching. This predicate does /// not take a node as input. This is used for subtarget feature checks etc. @@ -398,13 +398,13 @@ class CheckPatternPredicateMatcher : public Matcher { public: CheckPatternPredicateMatcher(StringRef predicate) : Matcher(CheckPatternPredicate), Predicate(predicate) {} - + StringRef getPredicate() const { return Predicate; } - + static inline bool classof(const Matcher *N) { return N->getKind() == CheckPatternPredicate; } - + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } private: @@ -414,7 +414,7 @@ private: } virtual unsigned getHashImpl() const; }; - + /// CheckPredicateMatcher - This checks the target-specific predicate to /// see if the node is acceptable. class CheckPredicateMatcher : public Matcher { @@ -422,13 +422,13 @@ class CheckPredicateMatcher : public Matcher { public: CheckPredicateMatcher(StringRef predname) : Matcher(CheckPredicate), PredName(predname) {} - + StringRef getPredicateName() const { return PredName; } static inline bool classof(const Matcher *N) { return N->getKind() == CheckPredicate; } - + // TODO: Ok? //virtual bool isSafeToReorderWithPatternPredicate() const { return true; } @@ -439,8 +439,8 @@ private: } virtual unsigned getHashImpl() const; }; - - + + /// CheckOpcodeMatcher - This checks to see if the current node has the /// specified opcode, if not it fails to match. class CheckOpcodeMatcher : public Matcher { @@ -448,13 +448,13 @@ class CheckOpcodeMatcher : public Matcher { public: CheckOpcodeMatcher(const SDNodeInfo &opcode) : Matcher(CheckOpcode), Opcode(opcode) {} - + const SDNodeInfo &getOpcode() const { return Opcode; } - + static inline bool classof(const Matcher *N) { return N->getKind() == CheckOpcode; } - + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } private: @@ -478,19 +478,19 @@ public: static inline bool classof(const Matcher *N) { return N->getKind() == SwitchOpcode; } - + unsigned getNumCases() const { return Cases.size(); } - + const SDNodeInfo &getCaseOpcode(unsigned i) const { return *Cases[i].first; } Matcher *getCaseMatcher(unsigned i) { return Cases[i].second; } const Matcher *getCaseMatcher(unsigned i) const { return Cases[i].second; } - + private: virtual void printImpl(raw_ostream &OS, unsigned indent) const; virtual bool isEqualImpl(const Matcher *M) const { return false; } virtual unsigned getHashImpl() const { return 4123; } }; - + /// CheckTypeMatcher - This checks to see if the current node has the /// specified type at the specified result, if not it fails to match. class CheckTypeMatcher : public Matcher { @@ -499,14 +499,14 @@ class CheckTypeMatcher : public Matcher { public: CheckTypeMatcher(MVT::SimpleValueType type, unsigned resno) : Matcher(CheckType), Type(type), ResNo(resno) {} - + MVT::SimpleValueType getType() const { return Type; } unsigned getResNo() const { return ResNo; } - + static inline bool classof(const Matcher *N) { return N->getKind() == CheckType; } - + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } private: @@ -517,7 +517,7 @@ private: virtual unsigned getHashImpl() const { return Type; } virtual bool isContradictoryImpl(const Matcher *M) const; }; - + /// SwitchTypeMatcher - Switch based on the current node's type, dispatching /// to one matcher per case. If the type doesn't match any of the cases, /// then the match fails. This is semantically equivalent to a Scope node where @@ -528,24 +528,24 @@ public: SwitchTypeMatcher(const std::pair<MVT::SimpleValueType, Matcher*> *cases, unsigned numcases) : Matcher(SwitchType), Cases(cases, cases+numcases) {} - + static inline bool classof(const Matcher *N) { return N->getKind() == SwitchType; } - + unsigned getNumCases() const { return Cases.size(); } - + MVT::SimpleValueType getCaseType(unsigned i) const { return Cases[i].first; } Matcher *getCaseMatcher(unsigned i) { return Cases[i].second; } const Matcher *getCaseMatcher(unsigned i) const { return Cases[i].second; } - + private: virtual void printImpl(raw_ostream &OS, unsigned indent) const; virtual bool isEqualImpl(const Matcher *M) const { return false; } virtual unsigned getHashImpl() const { return 4123; } }; - - + + /// CheckChildTypeMatcher - This checks to see if a child node has the /// specified type, if not it fails to match. class CheckChildTypeMatcher : public Matcher { @@ -554,14 +554,14 @@ class CheckChildTypeMatcher : public Matcher { public: CheckChildTypeMatcher(unsigned childno, MVT::SimpleValueType type) : Matcher(CheckChildType), ChildNo(childno), Type(type) {} - + unsigned getChildNo() const { return ChildNo; } MVT::SimpleValueType getType() const { return Type; } - + static inline bool classof(const Matcher *N) { return N->getKind() == CheckChildType; } - + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } private: @@ -573,7 +573,7 @@ private: virtual unsigned getHashImpl() const { return (Type << 3) | ChildNo; } virtual bool isContradictoryImpl(const Matcher *M) const; }; - + /// CheckIntegerMatcher - This checks to see if the current node is a /// ConstantSDNode with the specified integer value, if not it fails to match. @@ -582,13 +582,13 @@ class CheckIntegerMatcher : public Matcher { public: CheckIntegerMatcher(int64_t value) : Matcher(CheckInteger), Value(value) {} - + int64_t getValue() const { return Value; } - + static inline bool classof(const Matcher *N) { return N->getKind() == CheckInteger; } - + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } private: @@ -599,7 +599,7 @@ private: virtual unsigned getHashImpl() const { return Value; } virtual bool isContradictoryImpl(const Matcher *M) const; }; - + /// CheckCondCodeMatcher - This checks to see if the current node is a /// CondCodeSDNode with the specified condition, if not it fails to match. class CheckCondCodeMatcher : public Matcher { @@ -607,13 +607,13 @@ class CheckCondCodeMatcher : public Matcher { public: CheckCondCodeMatcher(StringRef condcodename) : Matcher(CheckCondCode), CondCodeName(condcodename) {} - + StringRef getCondCodeName() const { return CondCodeName; } - + static inline bool classof(const Matcher *N) { return N->getKind() == CheckCondCode; } - + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } private: @@ -623,7 +623,7 @@ private: } virtual unsigned getHashImpl() const; }; - + /// CheckValueTypeMatcher - This checks to see if the current node is a /// VTSDNode with the specified type, if not it fails to match. class CheckValueTypeMatcher : public Matcher { @@ -631,13 +631,13 @@ class CheckValueTypeMatcher : public Matcher { public: CheckValueTypeMatcher(StringRef type_name) : Matcher(CheckValueType), TypeName(type_name) {} - + StringRef getTypeName() const { return TypeName; } static inline bool classof(const Matcher *N) { return N->getKind() == CheckValueType; } - + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } private: @@ -648,21 +648,21 @@ private: virtual unsigned getHashImpl() const; bool isContradictoryImpl(const Matcher *M) const; }; - - - + + + /// CheckComplexPatMatcher - This node runs the specified ComplexPattern on /// the current node. class CheckComplexPatMatcher : public Matcher { const ComplexPattern &Pattern; - - /// MatchNumber - This is the recorded nodes slot that contains the node we want to - /// match against. + + /// MatchNumber - This is the recorded nodes slot that contains the node we + /// want to match against. unsigned MatchNumber; - + /// Name - The name of the node we're matching, for comment emission. std::string Name; - + /// FirstResult - This is the first slot in the RecordedNodes list that the /// result of the match populates. unsigned FirstResult; @@ -671,17 +671,17 @@ public: const std::string &name, unsigned firstresult) : Matcher(CheckComplexPat), Pattern(pattern), MatchNumber(matchnumber), Name(name), FirstResult(firstresult) {} - + const ComplexPattern &getPattern() const { return Pattern; } unsigned getMatchNumber() const { return MatchNumber; } - + const std::string getName() const { return Name; } unsigned getFirstResult() const { return FirstResult; } - + static inline bool classof(const Matcher *N) { return N->getKind() == CheckComplexPat; } - + // Not safe to move a pattern predicate past a complex pattern. virtual bool isSafeToReorderWithPatternPredicate() const { return false; } @@ -695,7 +695,7 @@ private: return (unsigned)(intptr_t)&Pattern ^ MatchNumber; } }; - + /// CheckAndImmMatcher - This checks to see if the current node is an 'and' /// with something equivalent to the specified immediate. class CheckAndImmMatcher : public Matcher { @@ -703,13 +703,13 @@ class CheckAndImmMatcher : public Matcher { public: CheckAndImmMatcher(int64_t value) : Matcher(CheckAndImm), Value(value) {} - + int64_t getValue() const { return Value; } - + static inline bool classof(const Matcher *N) { return N->getKind() == CheckAndImm; } - + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } private: @@ -727,13 +727,13 @@ class CheckOrImmMatcher : public Matcher { public: CheckOrImmMatcher(int64_t value) : Matcher(CheckOrImm), Value(value) {} - + int64_t getValue() const { return Value; } static inline bool classof(const Matcher *N) { return N->getKind() == CheckOrImm; } - + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } private: @@ -750,11 +750,11 @@ class CheckFoldableChainNodeMatcher : public Matcher { public: CheckFoldableChainNodeMatcher() : Matcher(CheckFoldableChainNode) {} - + static inline bool classof(const Matcher *N) { return N->getKind() == CheckFoldableChainNode; } - + virtual bool isSafeToReorderWithPatternPredicate() const { return true; } private: @@ -770,14 +770,14 @@ class EmitIntegerMatcher : public Matcher { public: EmitIntegerMatcher(int64_t val, MVT::SimpleValueType vt) : Matcher(EmitInteger), Val(val), VT(vt) {} - + int64_t getValue() const { return Val; } MVT::SimpleValueType getVT() const { return VT; } - + static inline bool classof(const Matcher *N) { return N->getKind() == EmitInteger; } - + private: virtual void printImpl(raw_ostream &OS, unsigned indent) const; virtual bool isEqualImpl(const Matcher *M) const { @@ -795,14 +795,14 @@ class EmitStringIntegerMatcher : public Matcher { public: EmitStringIntegerMatcher(const std::string &val, MVT::SimpleValueType vt) : Matcher(EmitStringInteger), Val(val), VT(vt) {} - + const std::string &getValue() const { return Val; } MVT::SimpleValueType getVT() const { return VT; } - + static inline bool classof(const Matcher *N) { return N->getKind() == EmitStringInteger; } - + private: virtual void printImpl(raw_ostream &OS, unsigned indent) const; virtual bool isEqualImpl(const Matcher *M) const { @@ -811,7 +811,7 @@ private: } virtual unsigned getHashImpl() const; }; - + /// EmitRegisterMatcher - This creates a new TargetConstant. class EmitRegisterMatcher : public Matcher { /// Reg - The def for the register that we're emitting. If this is null, then @@ -821,14 +821,14 @@ class EmitRegisterMatcher : public Matcher { public: EmitRegisterMatcher(Record *reg, MVT::SimpleValueType vt) : Matcher(EmitRegister), Reg(reg), VT(vt) {} - + Record *getReg() const { return Reg; } MVT::SimpleValueType getVT() const { return VT; } - + static inline bool classof(const Matcher *N) { return N->getKind() == EmitRegister; } - + private: virtual void printImpl(raw_ostream &OS, unsigned indent) const; virtual bool isEqualImpl(const Matcher *M) const { @@ -848,13 +848,13 @@ class EmitConvertToTargetMatcher : public Matcher { public: EmitConvertToTargetMatcher(unsigned slot) : Matcher(EmitConvertToTarget), Slot(slot) {} - + unsigned getSlot() const { return Slot; } - + static inline bool classof(const Matcher *N) { return N->getKind() == EmitConvertToTarget; } - + private: virtual void printImpl(raw_ostream &OS, unsigned indent) const; virtual bool isEqualImpl(const Matcher *M) const { @@ -862,7 +862,7 @@ private: } virtual unsigned getHashImpl() const { return Slot; } }; - + /// EmitMergeInputChainsMatcher - Emit a node that merges a list of input /// chains together with a token factor. The list of nodes are the nodes in the /// matched pattern that have chain input/outputs. This node adds all input @@ -872,18 +872,18 @@ class EmitMergeInputChainsMatcher : public Matcher { public: EmitMergeInputChainsMatcher(const unsigned *nodes, unsigned NumNodes) : Matcher(EmitMergeInputChains), ChainNodes(nodes, nodes+NumNodes) {} - + unsigned getNumNodes() const { return ChainNodes.size(); } - + unsigned getNode(unsigned i) const { assert(i < ChainNodes.size()); return ChainNodes[i]; - } - + } + static inline bool classof(const Matcher *N) { return N->getKind() == EmitMergeInputChains; } - + private: virtual void printImpl(raw_ostream &OS, unsigned indent) const; virtual bool isEqualImpl(const Matcher *M) const { @@ -891,9 +891,9 @@ private: } virtual unsigned getHashImpl() const; }; - + /// EmitCopyToRegMatcher - Emit a CopyToReg node from a value to a physreg, -/// pushing the chain and flag results. +/// pushing the chain and glue results. /// class EmitCopyToRegMatcher : public Matcher { unsigned SrcSlot; // Value to copy into the physreg. @@ -901,27 +901,27 @@ class EmitCopyToRegMatcher : public Matcher { public: EmitCopyToRegMatcher(unsigned srcSlot, Record *destPhysReg) : Matcher(EmitCopyToReg), SrcSlot(srcSlot), DestPhysReg(destPhysReg) {} - + unsigned getSrcSlot() const { return SrcSlot; } Record *getDestPhysReg() const { return DestPhysReg; } - + static inline bool classof(const Matcher *N) { return N->getKind() == EmitCopyToReg; } - + private: virtual void printImpl(raw_ostream &OS, unsigned indent) const; virtual bool isEqualImpl(const Matcher *M) const { return cast<EmitCopyToRegMatcher>(M)->SrcSlot == SrcSlot && - cast<EmitCopyToRegMatcher>(M)->DestPhysReg == DestPhysReg; + cast<EmitCopyToRegMatcher>(M)->DestPhysReg == DestPhysReg; } virtual unsigned getHashImpl() const { return SrcSlot ^ ((unsigned)(intptr_t)DestPhysReg << 4); } }; - - - + + + /// EmitNodeXFormMatcher - Emit an operation that runs an SDNodeXForm on a /// recorded node and records the result. class EmitNodeXFormMatcher : public Matcher { @@ -930,33 +930,33 @@ class EmitNodeXFormMatcher : public Matcher { public: EmitNodeXFormMatcher(unsigned slot, Record *nodeXForm) : Matcher(EmitNodeXForm), Slot(slot), NodeXForm(nodeXForm) {} - + unsigned getSlot() const { return Slot; } Record *getNodeXForm() const { return NodeXForm; } - + static inline bool classof(const Matcher *N) { return N->getKind() == EmitNodeXForm; } - + private: virtual void printImpl(raw_ostream &OS, unsigned indent) const; virtual bool isEqualImpl(const Matcher *M) const { return cast<EmitNodeXFormMatcher>(M)->Slot == Slot && - cast<EmitNodeXFormMatcher>(M)->NodeXForm == NodeXForm; + cast<EmitNodeXFormMatcher>(M)->NodeXForm == NodeXForm; } virtual unsigned getHashImpl() const { return Slot ^ ((unsigned)(intptr_t)NodeXForm << 4); } }; - + /// EmitNodeMatcherCommon - Common class shared between EmitNode and /// MorphNodeTo. class EmitNodeMatcherCommon : public Matcher { std::string OpcodeName; const SmallVector<MVT::SimpleValueType, 3> VTs; const SmallVector<unsigned, 6> Operands; - bool HasChain, HasInFlag, HasOutFlag, HasMemRefs; - + bool HasChain, HasInGlue, HasOutGlue, HasMemRefs; + /// NumFixedArityOperands - If this is a fixed arity node, this is set to -1. /// If this is a varidic node, this is set to the number of fixed arity /// operands in the root of the pattern. The rest are appended to this node. @@ -965,16 +965,16 @@ public: EmitNodeMatcherCommon(const std::string &opcodeName, const MVT::SimpleValueType *vts, unsigned numvts, const unsigned *operands, unsigned numops, - bool hasChain, bool hasInFlag, bool hasOutFlag, + bool hasChain, bool hasInGlue, bool hasOutGlue, bool hasmemrefs, int numfixedarityoperands, bool isMorphNodeTo) : Matcher(isMorphNodeTo ? MorphNodeTo : EmitNode), OpcodeName(opcodeName), VTs(vts, vts+numvts), Operands(operands, operands+numops), - HasChain(hasChain), HasInFlag(hasInFlag), HasOutFlag(hasOutFlag), + HasChain(hasChain), HasInGlue(hasInGlue), HasOutGlue(hasOutGlue), HasMemRefs(hasmemrefs), NumFixedArityOperands(numfixedarityoperands) {} - + const std::string &getOpcodeName() const { return OpcodeName; } - + unsigned getNumVTs() const { return VTs.size(); } MVT::SimpleValueType getVT(unsigned i) const { assert(i < VTs.size()); @@ -986,27 +986,27 @@ public: assert(i < Operands.size()); return Operands[i]; } - + const SmallVectorImpl<MVT::SimpleValueType> &getVTList() const { return VTs; } const SmallVectorImpl<unsigned> &getOperandList() const { return Operands; } - + bool hasChain() const { return HasChain; } - bool hasInFlag() const { return HasInFlag; } - bool hasOutFlag() const { return HasOutFlag; } + bool hasInFlag() const { return HasInGlue; } + bool hasOutFlag() const { return HasOutGlue; } bool hasMemRefs() const { return HasMemRefs; } int getNumFixedArityOperands() const { return NumFixedArityOperands; } - + static inline bool classof(const Matcher *N) { return N->getKind() == EmitNode || N->getKind() == MorphNodeTo; } - + private: virtual void printImpl(raw_ostream &OS, unsigned indent) const; virtual bool isEqualImpl(const Matcher *M) const; virtual unsigned getHashImpl() const; }; - + /// EmitNodeMatcher - This signals a successful match and generates a node. class EmitNodeMatcher : public EmitNodeMatcherCommon { unsigned FirstResultSlot; @@ -1021,15 +1021,15 @@ public: hasInFlag, hasOutFlag, hasmemrefs, numfixedarityoperands, false), FirstResultSlot(firstresultslot) {} - + unsigned getFirstResultSlot() const { return FirstResultSlot; } - + static inline bool classof(const Matcher *N) { return N->getKind() == EmitNode; } - + }; - + class MorphNodeToMatcher : public EmitNodeMatcherCommon { const PatternToMatch &Pattern; public: @@ -1044,38 +1044,38 @@ public: numfixedarityoperands, true), Pattern(pattern) { } - + const PatternToMatch &getPattern() const { return Pattern; } static inline bool classof(const Matcher *N) { return N->getKind() == MorphNodeTo; } }; - -/// MarkFlagResultsMatcher - This node indicates which non-root nodes in the -/// pattern produce flags. This allows CompleteMatchMatcher to update them -/// with the output flag of the resultant code. -class MarkFlagResultsMatcher : public Matcher { - SmallVector<unsigned, 3> FlagResultNodes; + +/// MarkGlueResultsMatcher - This node indicates which non-root nodes in the +/// pattern produce glue. This allows CompleteMatchMatcher to update them +/// with the output glue of the resultant code. +class MarkGlueResultsMatcher : public Matcher { + SmallVector<unsigned, 3> GlueResultNodes; public: - MarkFlagResultsMatcher(const unsigned *nodes, unsigned NumNodes) - : Matcher(MarkFlagResults), FlagResultNodes(nodes, nodes+NumNodes) {} - - unsigned getNumNodes() const { return FlagResultNodes.size(); } - + MarkGlueResultsMatcher(const unsigned *nodes, unsigned NumNodes) + : Matcher(MarkGlueResults), GlueResultNodes(nodes, nodes+NumNodes) {} + + unsigned getNumNodes() const { return GlueResultNodes.size(); } + unsigned getNode(unsigned i) const { - assert(i < FlagResultNodes.size()); - return FlagResultNodes[i]; - } - + assert(i < GlueResultNodes.size()); + return GlueResultNodes[i]; + } + static inline bool classof(const Matcher *N) { - return N->getKind() == MarkFlagResults; + return N->getKind() == MarkGlueResults; } - + private: virtual void printImpl(raw_ostream &OS, unsigned indent) const; virtual bool isEqualImpl(const Matcher *M) const { - return cast<MarkFlagResultsMatcher>(M)->FlagResultNodes == FlagResultNodes; + return cast<MarkGlueResultsMatcher>(M)->GlueResultNodes == GlueResultNodes; } virtual unsigned getHashImpl() const; }; @@ -1095,11 +1095,11 @@ public: unsigned getNumResults() const { return Results.size(); } unsigned getResult(unsigned R) const { return Results[R]; } const PatternToMatch &getPattern() const { return Pattern; } - + static inline bool classof(const Matcher *N) { return N->getKind() == CompleteMatch; } - + private: virtual void printImpl(raw_ostream &OS, unsigned indent) const; virtual bool isEqualImpl(const Matcher *M) const { @@ -1108,7 +1108,7 @@ private: } virtual unsigned getHashImpl() const; }; - + } // end namespace llvm #endif diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp index dfbfe80..0b7fbf7 100644 --- a/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -220,8 +220,8 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, OS << "OPC_RecordMemRef,\n"; return 1; - case Matcher::CaptureFlagInput: - OS << "OPC_CaptureFlagInput,\n"; + case Matcher::CaptureGlueInput: + OS << "OPC_CaptureGlueInput,\n"; return 1; case Matcher::MoveChild: @@ -485,8 +485,8 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, OS << ", TARGET_OPCODE(" << EN->getOpcodeName() << "), 0"; if (EN->hasChain()) OS << "|OPFL_Chain"; - if (EN->hasInFlag()) OS << "|OPFL_FlagInput"; - if (EN->hasOutFlag()) OS << "|OPFL_FlagOutput"; + if (EN->hasInFlag()) OS << "|OPFL_GlueInput"; + if (EN->hasOutFlag()) OS << "|OPFL_GlueOutput"; if (EN->hasMemRefs()) OS << "|OPFL_MemRefs"; if (EN->getNumFixedArityOperands() != -1) OS << "|OPFL_Variadic" << EN->getNumFixedArityOperands(); @@ -531,9 +531,9 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, return 6+EN->getNumVTs()+NumOperandBytes; } - case Matcher::MarkFlagResults: { - const MarkFlagResultsMatcher *CFR = cast<MarkFlagResultsMatcher>(N); - OS << "OPC_MarkFlagResults, " << CFR->getNumNodes() << ", "; + case Matcher::MarkGlueResults: { + const MarkGlueResultsMatcher *CFR = cast<MarkGlueResultsMatcher>(N); + OS << "OPC_MarkGlueResults, " << CFR->getNumNodes() << ", "; unsigned NumOperandBytes = 0; for (unsigned i = 0, e = CFR->getNumNodes(); i != e; ++i) NumOperandBytes += EmitVBRValue(CFR->getNode(i), OS); @@ -633,8 +633,9 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { // Emit CompletePattern matchers. // FIXME: This should be const. if (!ComplexPatterns.empty()) { - OS << "bool CheckComplexPattern(SDNode *Root, SDValue N,\n"; - OS << " unsigned PatternNo, SmallVectorImpl<SDValue> &Result) {\n"; + OS << "bool CheckComplexPattern(SDNode *Root, SDNode *Parent, SDValue N,\n"; + OS << " unsigned PatternNo,\n"; + OS << " SmallVectorImpl<std::pair<SDValue, SDNode*> > &Result) {\n"; OS << " unsigned NextRes = Result.size();\n"; OS << " switch (PatternNo) {\n"; OS << " default: assert(0 && \"Invalid pattern # in table?\");\n"; @@ -649,9 +650,20 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { OS << " Result.resize(NextRes+" << NumOps << ");\n"; OS << " return " << P.getSelectFunc(); - OS << "(Root, N"; + OS << "("; + // If the complex pattern wants the root of the match, pass it in as the + // first argument. + if (P.hasProperty(SDNPWantRoot)) + OS << "Root, "; + + // If the complex pattern wants the parent of the operand being matched, + // pass it in as the next argument. + if (P.hasProperty(SDNPWantParent)) + OS << "Parent, "; + + OS << "N"; for (unsigned i = 0; i != NumOps; ++i) - OS << ", Result[NextRes+" << i << ']'; + OS << ", Result[NextRes+" << i << "].first"; OS << ");\n"; } OS << " }\n"; @@ -730,7 +742,7 @@ void MatcherTableEmitter::EmitHistogram(const Matcher *M, case Matcher::RecordNode: OS << "OPC_RecordNode"; break; case Matcher::RecordChild: OS << "OPC_RecordChild"; break; case Matcher::RecordMemRef: OS << "OPC_RecordMemRef"; break; - case Matcher::CaptureFlagInput: OS << "OPC_CaptureFlagInput"; break; + case Matcher::CaptureGlueInput: OS << "OPC_CaptureGlueInput"; break; case Matcher::MoveChild: OS << "OPC_MoveChild"; break; case Matcher::MoveParent: OS << "OPC_MoveParent"; break; case Matcher::CheckSame: OS << "OPC_CheckSame"; break; @@ -759,7 +771,7 @@ void MatcherTableEmitter::EmitHistogram(const Matcher *M, case Matcher::EmitNode: OS << "OPC_EmitNode"; break; case Matcher::MorphNodeTo: OS << "OPC_MorphNodeTo"; break; case Matcher::EmitNodeXForm: OS << "OPC_EmitNodeXForm"; break; - case Matcher::MarkFlagResults: OS << "OPC_MarkFlagResults"; break; + case Matcher::MarkGlueResults: OS << "OPC_MarkGlueResults"; break; case Matcher::CompleteMatch: OS << "OPC_CompleteMatch"; break; } diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index aba6636..7c0bade 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -25,12 +25,12 @@ static MVT::SimpleValueType getRegisterValueType(Record *R, MVT::SimpleValueType VT = MVT::Other; const std::vector<CodeGenRegisterClass> &RCs = T.getRegisterClasses(); std::vector<Record*>::const_iterator Element; - + for (unsigned rc = 0, e = RCs.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = RCs[rc]; if (!std::count(RC.Elements.begin(), RC.Elements.end(), R)) continue; - + if (!FoundRC) { FoundRC = true; VT = RC.getValueTypeNum(0); @@ -48,30 +48,30 @@ namespace { class MatcherGen { const PatternToMatch &Pattern; const CodeGenDAGPatterns &CGP; - + /// PatWithNoTypes - This is a clone of Pattern.getSrcPattern() that starts /// out with all of the types removed. This allows us to insert type checks /// as we scan the tree. TreePatternNode *PatWithNoTypes; - + /// VariableMap - A map from variable names ('$dst') to the recorded operand /// number that they were captured as. These are biased by 1 to make /// insertion easier. StringMap<unsigned> VariableMap; - + /// NextRecordedOperandNo - As we emit opcodes to record matched values in /// the RecordedNodes array, this keeps track of which slot will be next to /// record into. unsigned NextRecordedOperandNo; - + /// MatchedChainNodes - This maintains the position in the recorded nodes /// array of all of the recorded input nodes that have chains. SmallVector<unsigned, 2> MatchedChainNodes; - /// MatchedFlagResultNodes - This maintains the position in the recorded - /// nodes array of all of the recorded input nodes that have flag results. - SmallVector<unsigned, 2> MatchedFlagResultNodes; - + /// MatchedGlueResultNodes - This maintains the position in the recorded + /// nodes array of all of the recorded input nodes that have glue results. + SmallVector<unsigned, 2> MatchedGlueResultNodes; + /// MatchedComplexPatterns - This maintains a list of all of the /// ComplexPatterns that we need to check. The patterns are known to have /// names which were recorded. The second element of each pair is the first @@ -79,40 +79,39 @@ namespace { /// results into. SmallVector<std::pair<const TreePatternNode*, unsigned>, 2> MatchedComplexPatterns; - + /// PhysRegInputs - List list has an entry for each explicitly specified /// physreg input to the pattern. The first elt is the Register node, the /// second is the recorded slot number the input pattern match saved it in. SmallVector<std::pair<Record*, unsigned>, 2> PhysRegInputs; - + /// Matcher - This is the top level of the generated matcher, the result. Matcher *TheMatcher; - + /// CurPredicate - As we emit matcher nodes, this points to the latest check /// which should have future checks stuck into its Next position. Matcher *CurPredicate; public: MatcherGen(const PatternToMatch &pattern, const CodeGenDAGPatterns &cgp); - + ~MatcherGen() { delete PatWithNoTypes; } - + bool EmitMatcherCode(unsigned Variant); void EmitResultCode(); - + Matcher *GetMatcher() const { return TheMatcher; } - Matcher *GetCurPredicate() const { return CurPredicate; } private: void AddMatcher(Matcher *NewNode); void InferPossibleTypes(); - + // Matcher Generation. void EmitMatchCode(const TreePatternNode *N, TreePatternNode *NodeNoTypes); void EmitLeafMatchCode(const TreePatternNode *N); void EmitOperatorMatchCode(const TreePatternNode *N, TreePatternNode *NodeNoTypes); - + // Result Code Generation. unsigned getNamedArgumentSlot(StringRef Name) { unsigned VarMapEntry = VariableMap[Name]; @@ -124,7 +123,7 @@ namespace { /// GetInstPatternNode - Get the pattern for an instruction. const TreePatternNode *GetInstPatternNode(const DAGInstruction &Ins, const TreePatternNode *N); - + void EmitResultOperand(const TreePatternNode *N, SmallVectorImpl<unsigned> &ResultOps); void EmitResultOfNamedOperand(const TreePatternNode *N, @@ -136,7 +135,7 @@ namespace { void EmitResultSDNodeXFormAsOperand(const TreePatternNode *N, SmallVectorImpl<unsigned> &ResultOps); }; - + } // end anon namespace. MatcherGen::MatcherGen(const PatternToMatch &pattern, @@ -157,7 +156,7 @@ MatcherGen::MatcherGen(const PatternToMatch &pattern, // PatWithNoTypes = Pattern.getSrcPattern()->clone(); PatWithNoTypes->RemoveAllTypes(); - + // If there are types that are manifestly known, infer them. InferPossibleTypes(); } @@ -170,7 +169,7 @@ 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) @@ -183,7 +182,7 @@ void MatcherGen::InferPossibleTypes() { } -/// AddMatcher - Add a matcher node to the current graph we're building. +/// AddMatcher - Add a matcher node to the current graph we're building. void MatcherGen::AddMatcher(Matcher *NewNode) { if (CurPredicate != 0) CurPredicate->setNext(NewNode); @@ -200,7 +199,7 @@ void MatcherGen::AddMatcher(Matcher *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())) { // If this is the root of the dag we're matching, we emit a redundant opcode @@ -213,16 +212,16 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { return AddMatcher(new CheckIntegerMatcher(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("RegisterClass") || LeafRec->isSubClassOf("PointerLikeRegClass") || LeafRec->isSubClassOf("SubRegIndex") || // Place holder for SRCVALUE nodes. Nothing to do here. @@ -230,20 +229,20 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { return; // If we have a physreg reference like (mul gpr:$src, EAX) then we need to - // record the register + // record the register if (LeafRec->isSubClassOf("Register")) { AddMatcher(new RecordMatcher("physreg input "+LeafRec->getName(), NextRecordedOperandNo)); PhysRegInputs.push_back(std::make_pair(LeafRec, NextRecordedOperandNo++)); return; } - + if (LeafRec->isSubClassOf("ValueType")) return AddMatcher(new CheckValueTypeMatcher(LeafRec->getName())); - + if (LeafRec->isSubClassOf("CondCode")) return AddMatcher(new CheckCondCodeMatcher(LeafRec->getName())); - + if (LeafRec->isSubClassOf("ComplexPattern")) { // We can't model ComplexPattern uses that don't have their name taken yet. // The OPC_CheckComplexPattern operation implicitly records the results. @@ -257,7 +256,7 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { MatchedComplexPatterns.push_back(std::make_pair(N, 0)); return; } - + errs() << "Unknown leaf kind: " << *N << "\n"; abort(); } @@ -266,7 +265,7 @@ 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 @@ -277,7 +276,7 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N, // 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" || + if ((N->getOperator()->getName() == "and" || N->getOperator()->getName() == "or") && N->getChild(1)->isLeaf() && N->getChild(1)->getPredicateFns().empty() && N->getPredicateFns().empty()) { @@ -303,15 +302,15 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N, } } } - + // Check that the current opcode lines up. AddMatcher(new CheckOpcodeMatcher(CInfo)); - + // If this node has memory references (i.e. is a load or store), tell the // interpreter to capture them in the memref array. if (N->NodeHasProperty(SDNPMemOperand, CGP)) AddMatcher(new RecordMemRefMatcher()); - + // If this node has a chain, then the chain is operand #0 is the SDNode, and // the child numbers of the node are all offset by one. unsigned OpNo = 0; @@ -322,7 +321,7 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N, NextRecordedOperandNo)); // Remember all of the input chains our pattern will match. MatchedChainNodes.push_back(NextRecordedOperandNo++); - + // Don't look at the input chain when matching the tree pattern to the // SDNode. OpNo = 1; @@ -353,11 +352,11 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N, // 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). + // glue). if (!NeedCheck) { const SDNodeInfo &PInfo = CGP.getSDNodeInfo(Root->getOperator()); NeedCheck = @@ -366,34 +365,34 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N, Root->getOperator() == CGP.get_intrinsic_wo_chain_sdnode() || PInfo.getNumOperands() > 1 || PInfo.hasProperty(SDNPHasChain) || - PInfo.hasProperty(SDNPInFlag) || - PInfo.hasProperty(SDNPOptInFlag); + PInfo.hasProperty(SDNPInGlue) || + PInfo.hasProperty(SDNPOptInGlue); } - + if (NeedCheck) AddMatcher(new CheckFoldableChainNodeMatcher()); } } - // If this node has an output flag and isn't the root, remember it. - if (N->NodeHasProperty(SDNPOutFlag, CGP) && + // If this node has an output glue and isn't the root, remember it. + if (N->NodeHasProperty(SDNPOutGlue, CGP) && N != Pattern.getSrcPattern()) { - // TODO: This redundantly records nodes with both flags and chains. - + // TODO: This redundantly records nodes with both glues and chains. + // Record the node and remember it in our chained nodes list. AddMatcher(new RecordMatcher("'" + N->getOperator()->getName() + - "' flag output node", + "' glue output node", NextRecordedOperandNo)); - // Remember all of the nodes with output flags our pattern will match. - MatchedFlagResultNodes.push_back(NextRecordedOperandNo++); + // Remember all of the nodes with output glue our pattern will match. + MatchedGlueResultNodes.push_back(NextRecordedOperandNo++); } - - // If this node is known to have an input flag or if it *might* have an input - // flag, capture it as the flag input of the pattern. - if (N->NodeHasProperty(SDNPOptInFlag, CGP) || - N->NodeHasProperty(SDNPInFlag, CGP)) - AddMatcher(new CaptureFlagInputMatcher()); - + + // If this node is known to have an input glue or if it *might* have an input + // glue, capture it as the glue input of the pattern. + if (N->NodeHasProperty(SDNPOptInGlue, CGP) || + N->NodeHasProperty(SDNPInGlue, CGP)) + AddMatcher(new CaptureGlueInputMatcher()); + for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) { // Get the code suitable for matching this child. Move to the child, check // it then move back to the parent. @@ -410,14 +409,14 @@ void MatcherGen::EmitMatchCode(const TreePatternNode *N, // need to do a type check. Emit the check, apply the tyep to NodeNoTypes and // reinfer any correlated types. SmallVector<unsigned, 2> ResultsToTypeCheck; - + for (unsigned i = 0, e = NodeNoTypes->getNumTypes(); i != e; ++i) { if (NodeNoTypes->getExtType(i) == N->getExtType(i)) continue; NodeNoTypes->setType(i, N->getExtType(i)); InferPossibleTypes(); ResultsToTypeCheck.push_back(i); } - + // If this node has a name associated with it, capture it in VariableMap. If // we already saw this in the pattern, emit code to verify dagness. if (!N->getName().empty()) { @@ -435,16 +434,16 @@ void MatcherGen::EmitMatchCode(const TreePatternNode *N, return; } } - + if (N->isLeaf()) EmitLeafMatchCode(N); else EmitOperatorMatchCode(N, NodeNoTypes); - + // If there are node predicates for this node, generate their checks. for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i) AddMatcher(new CheckPredicateMatcher(N->getPredicateFns()[i])); - + for (unsigned i = 0, e = ResultsToTypeCheck.size(); i != e; ++i) AddMatcher(new CheckTypeMatcher(N->getType(ResultsToTypeCheck[i]), ResultsToTypeCheck[i])); @@ -463,27 +462,27 @@ bool MatcherGen::EmitMatcherCode(unsigned Variant) { const std::vector<Record*> &OpNodes = CP->getRootNodes(); assert(!OpNodes.empty() &&"Complex Pattern must specify what it can match"); if (Variant >= OpNodes.size()) return true; - + AddMatcher(new CheckOpcodeMatcher(CGP.getSDNodeInfo(OpNodes[Variant]))); } else { if (Variant != 0) return true; } - + // Emit the matcher for the pattern structure and types. EmitMatchCode(Pattern.getSrcPattern(), PatWithNoTypes); - + // If the pattern has a predicate on it (e.g. only enabled when a subtarget // feature is around, do the check). if (!Pattern.getPredicateCheck().empty()) AddMatcher(new CheckPatternPredicateMatcher(Pattern.getPredicateCheck())); - + // Now that we've completed the structural type match, emit any ComplexPattern // checks (e.g. addrmode matches). We emit this after the structural match // because they are generally more expensive to evaluate and more difficult to // factor. for (unsigned i = 0, e = MatchedComplexPatterns.size(); i != e; ++i) { const TreePatternNode *N = MatchedComplexPatterns[i].first; - + // Remember where the results of this match get stuck. MatchedComplexPatterns[i].second = NextRecordedOperandNo; @@ -492,15 +491,15 @@ bool MatcherGen::EmitMatcherCode(unsigned Variant) { assert(!N->getName().empty() && RecNodeEntry && "Complex pattern should have a name and slot"); --RecNodeEntry; // Entries in VariableMap are biased. - + const ComplexPattern &CP = CGP.getComplexPattern(((DefInit*)N->getLeafValue())->getDef()); - + // Emit a CheckComplexPat operation, which does the match (aborting if it // fails) and pushes the matched operands onto the recorded nodes list. AddMatcher(new CheckComplexPatMatcher(CP, RecNodeEntry, N->getName(), NextRecordedOperandNo)); - + // Record the right number of operands. NextRecordedOperandNo += CP.getNumOperands(); if (CP.hasProperty(SDNPHasChain)) { @@ -508,17 +507,17 @@ bool MatcherGen::EmitMatcherCode(unsigned Variant) { // fact that we just recorded a chain input. The chain input will be // matched as the last operand of the predicate if it was successful. ++NextRecordedOperandNo; // Chained node operand. - + // It is the last operand recorded. assert(NextRecordedOperandNo > 1 && "Should have recorded input/result chains at least!"); MatchedChainNodes.push_back(NextRecordedOperandNo-1); } - - // TODO: Complex patterns can't have output flags, if they did, we'd want + + // TODO: Complex patterns can't have output glues, if they did, we'd want // to record them. } - + return false; } @@ -530,7 +529,7 @@ bool MatcherGen::EmitMatcherCode(unsigned Variant) { void MatcherGen::EmitResultOfNamedOperand(const TreePatternNode *N, SmallVectorImpl<unsigned> &ResultOps){ assert(!N->getName().empty() && "Operand not named!"); - + // A reference to a complex pattern gets all of the results of the complex // pattern's match. if (const ComplexPattern *CP = N->getComplexPatternInfo(CGP)) { @@ -541,7 +540,7 @@ void MatcherGen::EmitResultOfNamedOperand(const TreePatternNode *N, break; } assert(SlotNo != 0 && "Didn't get a slot number assigned?"); - + // The first slot entry is the node itself, the subsequent entries are the // matched values. for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) @@ -562,20 +561,20 @@ void MatcherGen::EmitResultOfNamedOperand(const TreePatternNode *N, return; } } - + ResultOps.push_back(SlotNo); } void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N, SmallVectorImpl<unsigned> &ResultOps) { assert(N->isLeaf() && "Must be a leaf"); - + if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) { AddMatcher(new EmitIntegerMatcher(II->getValue(), N->getType(0))); ResultOps.push_back(NextRecordedOperandNo++); return; } - + // If this is an explicit register reference, handle it. if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) { if (DI->getDef()->isSubClassOf("Register")) { @@ -583,13 +582,13 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N, ResultOps.push_back(NextRecordedOperandNo++); return; } - + if (DI->getDef()->getName() == "zero_reg") { AddMatcher(new EmitRegisterMatcher(0, N->getType(0))); ResultOps.push_back(NextRecordedOperandNo++); return; } - + // Handle a reference to a register class. This is used // in COPY_TO_SUBREG instructions. if (DI->getDef()->isSubClassOf("RegisterClass")) { @@ -607,17 +606,17 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N, return; } } - + errs() << "unhandled leaf node: \n"; N->dump(); } /// GetInstPatternNode - Get the pattern for an instruction. -/// +/// const TreePatternNode *MatcherGen:: GetInstPatternNode(const DAGInstruction &Inst, const TreePatternNode *N) { const TreePattern *InstPat = Inst.getPattern(); - + // FIXME2?: Assume actual pattern comes before "implicit". TreePatternNode *InstPatNode; if (InstPat) @@ -626,11 +625,11 @@ GetInstPatternNode(const DAGInstruction &Inst, const TreePatternNode *N) { InstPatNode = Pattern.getSrcPattern(); else return 0; - + if (InstPatNode && !InstPatNode->isLeaf() && InstPatNode->getOperator()->getName() == "set") InstPatNode = InstPatNode->getChild(InstPatNode->getNumChildren()-1); - + return InstPatNode; } @@ -641,7 +640,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, const CodeGenTarget &CGT = CGP.getTargetInfo(); CodeGenInstruction &II = CGT.getInstruction(Op); const DAGInstruction &Inst = CGP.getInstruction(Op); - + // If we can, get the pattern for the instruction we're generating. We derive // a variety of information from this pattern, such as whether it has a chain. // @@ -650,27 +649,27 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, // nodes can't duplicate. const TreePatternNode *InstPatNode = GetInstPatternNode(Inst, N); - // NodeHasChain - Whether the instruction node we're creating takes chains. + // NodeHasChain - Whether the instruction node we're creating takes chains. bool NodeHasChain = InstPatNode && InstPatNode->TreeHasProperty(SDNPHasChain, CGP); - + bool isRoot = N == Pattern.getDstPattern(); - // TreeHasOutFlag - True if this tree has a flag. - bool TreeHasInFlag = false, TreeHasOutFlag = false; + // TreeHasOutGlue - True if this tree has glue. + bool TreeHasInGlue = false, TreeHasOutGlue = false; if (isRoot) { const TreePatternNode *SrcPat = Pattern.getSrcPattern(); - TreeHasInFlag = SrcPat->TreeHasProperty(SDNPOptInFlag, CGP) || - SrcPat->TreeHasProperty(SDNPInFlag, CGP); - + TreeHasInGlue = SrcPat->TreeHasProperty(SDNPOptInGlue, CGP) || + SrcPat->TreeHasProperty(SDNPInGlue, CGP); + // FIXME2: this is checking the entire pattern, not just the node in // question, doing this just for the root seems like a total hack. - TreeHasOutFlag = SrcPat->TreeHasProperty(SDNPOutFlag, CGP); + TreeHasOutGlue = SrcPat->TreeHasProperty(SDNPOutGlue, CGP); } // NumResults - This is the number of results produced by the instruction in // the "outs" list. - unsigned NumResults = Inst.getNumResults(); + unsigned NumResults = Inst.getNumResults(); // Loop over all of the operands of the instruction pattern, emitting code // to fill them all in. The node 'N' usually has number children equal to @@ -679,41 +678,41 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, // in the 'execute always' values. Match up the node operands to the // instruction operands to do this. SmallVector<unsigned, 8> InstOps; - for (unsigned ChildNo = 0, InstOpNo = NumResults, e = II.OperandList.size(); + for (unsigned ChildNo = 0, InstOpNo = NumResults, e = II.Operands.size(); InstOpNo != e; ++InstOpNo) { - + // Determine what to emit for this operand. - Record *OperandNode = II.OperandList[InstOpNo].Rec; + Record *OperandNode = II.Operands[InstOpNo].Rec; if ((OperandNode->isSubClassOf("PredicateOperand") || OperandNode->isSubClassOf("OptionalDefOperand")) && !CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) { // This is a predicate or optional def operand; emit the // 'default ops' operands. const DAGDefaultOperand &DefaultOp - = CGP.getDefaultOperand(OperandNode); + = CGP.getDefaultOperand(OperandNode); for (unsigned i = 0, e = DefaultOp.DefaultOps.size(); i != e; ++i) EmitResultOperand(DefaultOp.DefaultOps[i], InstOps); continue; } - + const TreePatternNode *Child = N->getChild(ChildNo); - + // Otherwise this is a normal operand or a predicate operand without // 'execute always'; emit it. unsigned BeforeAddingNumOps = InstOps.size(); EmitResultOperand(Child, InstOps); assert(InstOps.size() > BeforeAddingNumOps && "Didn't add any operands"); - + // If the operand is an instruction and it produced multiple results, just // take the first one. if (!Child->isLeaf() && Child->getOperator()->isSubClassOf("Instruction")) InstOps.resize(BeforeAddingNumOps+1); - + ++ChildNo; } - - // If this node has an input flag or explicitly specified input physregs, we - // need to add chained and flagged copyfromreg nodes and materialize the flag + + // If this node has input glue or explicitly specified input physregs, we + // need to add chained and glued copyfromreg nodes and materialize the glue // input. if (isRoot && !PhysRegInputs.empty()) { // Emit all of the CopyToReg nodes for the input physical registers. These @@ -721,18 +720,18 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, for (unsigned i = 0, e = PhysRegInputs.size(); i != e; ++i) AddMatcher(new EmitCopyToRegMatcher(PhysRegInputs[i].second, PhysRegInputs[i].first)); - // Even if the node has no other flag inputs, the resultant node must be - // flagged to the CopyFromReg nodes we just generated. - TreeHasInFlag = true; + // Even if the node has no other glue inputs, the resultant node must be + // glued to the CopyFromReg nodes we just generated. + TreeHasInGlue = true; } - - // Result order: node results, chain, flags - + + // Result order: node results, chain, glue + // Determine the result types. SmallVector<MVT::SimpleValueType, 4> ResultVTs; for (unsigned i = 0, e = N->getNumTypes(); i != e; ++i) ResultVTs.push_back(N->getType(i)); - + // If this is the root instruction of a pattern that has physical registers in // its result pattern, add output VTs for them. For example, X86 has: // (set AL, (mul ...)) @@ -744,7 +743,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, Record *HandledReg = 0; if (II.HasOneImplicitDefWithKnownVT(CGT) != MVT::Other) HandledReg = II.ImplicitDefs[0]; - + for (unsigned i = 0; i != Pattern.getDstRegs().size(); ++i) { Record *Reg = Pattern.getDstRegs()[i]; if (!Reg->isSubClassOf("Register") || Reg == HandledReg) continue; @@ -759,7 +758,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, if (isRoot && (Pattern.getSrcPattern()->NodeHasProperty(SDNPVariadic, CGP))) NumFixedArityOperands = Pattern.getSrcPattern()->getNumChildren(); - + // If this is the root node and any of the nodes matched nodes in the input // pattern have MemRefs in them, have the interpreter collect them and plop // them onto this node. @@ -776,19 +775,19 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, bool NodeHasMemRefs = isRoot && Pattern.getSrcPattern()->TreeHasProperty(SDNPMemOperand, CGP); - assert((!ResultVTs.empty() || TreeHasOutFlag || NodeHasChain) && + assert((!ResultVTs.empty() || TreeHasOutGlue || NodeHasChain) && "Node has no result"); - + AddMatcher(new EmitNodeMatcher(II.Namespace+"::"+II.TheDef->getName(), ResultVTs.data(), ResultVTs.size(), InstOps.data(), InstOps.size(), - NodeHasChain, TreeHasInFlag, TreeHasOutFlag, + NodeHasChain, TreeHasInGlue, TreeHasOutGlue, NodeHasMemRefs, NumFixedArityOperands, NextRecordedOperandNo)); - - // The non-chain and non-flag results of the newly emitted node get recorded. + + // The non-chain and non-glue results of the newly emitted node get recorded. for (unsigned i = 0, e = ResultVTs.size(); i != e; ++i) { - if (ResultVTs[i] == MVT::Other || ResultVTs[i] == MVT::Flag) break; + if (ResultVTs[i] == MVT::Other || ResultVTs[i] == MVT::Glue) break; OutputOps.push_back(NextRecordedOperandNo++); } } @@ -800,7 +799,7 @@ EmitResultSDNodeXFormAsOperand(const TreePatternNode *N, // Emit the operand. SmallVector<unsigned, 8> InputOps; - + // FIXME2: Could easily generalize this to support multiple inputs and outputs // to the SDNodeXForm. For now we just support one input and one output like // the old instruction selector. @@ -839,7 +838,7 @@ void MatcherGen::EmitResultCode() { if (!MatchedChainNodes.empty()) AddMatcher(new EmitMergeInputChainsMatcher (MatchedChainNodes.data(), MatchedChainNodes.size())); - + // Codegen the root of the result pattern, capturing the resulting values. SmallVector<unsigned, 8> Ops; EmitResultOperand(Pattern.getDstPattern(), Ops); @@ -847,11 +846,11 @@ void MatcherGen::EmitResultCode() { // At this point, we have however many values the result pattern produces. // However, the input pattern might not need all of these. If there are // excess values at the end (such as implicit defs of condition codes etc) - // just lop them off. This doesn't need to worry about flags or chains, just + // just lop them off. This doesn't need to worry about glue or chains, just // explicit results. // unsigned NumSrcResults = Pattern.getSrcPattern()->getNumTypes(); - + // If the pattern also has (implicit) results, count them as well. if (!Pattern.getDstRegs().empty()) { // If the root came from an implicit def in the instruction handling stuff, @@ -865,23 +864,23 @@ void MatcherGen::EmitResultCode() { if (II.HasOneImplicitDefWithKnownVT(CGT) != MVT::Other) HandledReg = II.ImplicitDefs[0]; } - + for (unsigned i = 0; i != Pattern.getDstRegs().size(); ++i) { Record *Reg = Pattern.getDstRegs()[i]; if (!Reg->isSubClassOf("Register") || Reg == HandledReg) continue; ++NumSrcResults; } - } - + } + assert(Ops.size() >= NumSrcResults && "Didn't provide enough results"); Ops.resize(NumSrcResults); - // If the matched pattern covers nodes which define a flag result, emit a node + // If the matched pattern covers nodes which define a glue result, emit a node // that tells the matcher about them so that it can update their results. - if (!MatchedFlagResultNodes.empty()) - AddMatcher(new MarkFlagResultsMatcher(MatchedFlagResultNodes.data(), - MatchedFlagResultNodes.size())); - + if (!MatchedGlueResultNodes.empty()) + AddMatcher(new MarkGlueResultsMatcher(MatchedGlueResultNodes.data(), + MatchedGlueResultNodes.size())); + AddMatcher(new CompleteMatchMatcher(Ops.data(), Ops.size(), Pattern)); } @@ -896,12 +895,12 @@ Matcher *llvm::ConvertPatternToMatcher(const PatternToMatch &Pattern, // Generate the code for the matcher. if (Gen.EmitMatcherCode(Variant)) return 0; - + // FIXME2: Kill extra MoveParent commands at the end of the matcher sequence. // FIXME2: Split result code out to another table, and make the matcher end // with an "Emit <index>" command. This allows result generation stuff to be // shared and factored? - + // If the match succeeds, then we generate Pattern. Gen.EmitResultCode(); diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp index c73bdb9..3169ea1 100644 --- a/utils/TableGen/DAGISelMatcherOpt.cpp +++ b/utils/TableGen/DAGISelMatcherOpt.cpp @@ -75,7 +75,7 @@ static void ContractNodes(OwningPtr<Matcher> &MatcherPtr, // MarkFlagResults->EmitNode->CompleteMatch when we can to encourage // MorphNodeTo formation. This is safe because MarkFlagResults never refers // to the root of the pattern. - if (isa<EmitNodeMatcher>(N) && isa<MarkFlagResultsMatcher>(N->getNext()) && + if (isa<EmitNodeMatcher>(N) && isa<MarkGlueResultsMatcher>(N->getNext()) && isa<CompleteMatchMatcher>(N->getNext()->getNext())) { // Unlink the two nodes from the list. Matcher *EmitNode = MatcherPtr.take(); @@ -100,7 +100,7 @@ static void ContractNodes(OwningPtr<Matcher> &MatcherPtr, if (CM->getResult(i) != RootResultFirst+i) ResultsMatch = false; - // If the selected node defines a subset of the flag/chain results, we + // If the selected node defines a subset of the glue/chain results, we // can't use MorphNodeTo. For example, we can't use MorphNodeTo if the // matched pattern has a chain but the root node doesn't. const PatternToMatch &Pattern = CM->getPattern(); @@ -109,23 +109,23 @@ static void ContractNodes(OwningPtr<Matcher> &MatcherPtr, Pattern.getSrcPattern()->NodeHasProperty(SDNPHasChain, CGP)) ResultsMatch = false; - // If the matched node has a flag and the output root doesn't, we can't + // If the matched node has glue and the output root doesn't, we can't // use MorphNodeTo. // - // NOTE: Strictly speaking, we don't have to check for the flag here + // NOTE: Strictly speaking, we don't have to check for glue here // because the code in the pattern generator doesn't handle it right. We // do it anyway for thoroughness. if (!EN->hasOutFlag() && - Pattern.getSrcPattern()->NodeHasProperty(SDNPOutFlag, CGP)) + Pattern.getSrcPattern()->NodeHasProperty(SDNPOutGlue, CGP)) ResultsMatch = false; // If the root result node defines more results than the source root node - // *and* has a chain or flag input, then we can't match it because it - // would end up replacing the extra result with the chain/flag. + // *and* has a chain or glue input, then we can't match it because it + // would end up replacing the extra result with the chain/glue. #if 0 - if ((EN->hasFlag() || EN->hasChain()) && - EN->getNumNonChainFlagVTs() > ... need to get no results reliably ...) + if ((EN->hasGlue() || EN->hasChain()) && + EN->getNumNonChainGlueVTs() > ... need to get no results reliably ...) ResultMatch = false; #endif diff --git a/utils/TableGen/DisassemblerEmitter.cpp b/utils/TableGen/DisassemblerEmitter.cpp index 3284366..90a2af2 100644 --- a/utils/TableGen/DisassemblerEmitter.cpp +++ b/utils/TableGen/DisassemblerEmitter.cpp @@ -13,6 +13,7 @@ #include "X86DisassemblerTables.h" #include "X86RecognizableInstr.h" #include "ARMDecoderEmitter.h" +#include "FixedLenDecoderEmitter.h" using namespace llvm; using namespace llvm::X86Disassembler; @@ -94,7 +95,7 @@ using namespace llvm::X86Disassembler; /// instruction. void DisassemblerEmitter::run(raw_ostream &OS) { - CodeGenTarget Target; + CodeGenTarget Target(Records); OS << "/*===- TableGen'erated file " << "---------------------------------------*- C -*-===*\n" @@ -127,11 +128,11 @@ void DisassemblerEmitter::run(raw_ostream &OS) { } // Fixed-instruction-length targets use a common disassembler. + // ARM use its own implementation for now. if (Target.getName() == "ARM") { ARMDecoderEmitter(Records).run(OS); return; } - throw TGError(Target.getTargetRecord()->getLoc(), - "Unable to generate disassembler for this target"); + FixedLenDecoderEmitter(Records).run(OS); } diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index 525fffb..020a4a3 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -35,22 +35,22 @@ using namespace llvm; /////////////////////////////////////////////////////////// namespace { - + class EnumEmitter { private: std::string Name; std::vector<std::string> Entries; public: - EnumEmitter(const char *N) : Name(N) { + EnumEmitter(const char *N) : Name(N) { } - int addEntry(const char *e) { + int addEntry(const char *e) { Entries.push_back(std::string(e)); - return Entries.size() - 1; + 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) { @@ -59,15 +59,15 @@ namespace { 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; @@ -78,7 +78,7 @@ namespace { o << "\n"; flag <<= 1; } - + i -= 2; o.indent(i) << "};" << "\n"; } @@ -89,7 +89,7 @@ namespace { virtual ~ConstantEmitter() { } virtual void emit(raw_ostream &o, unsigned int &i) = 0; }; - + class LiteralConstantEmitter : public ConstantEmitter { private: bool IsNumber; @@ -98,7 +98,7 @@ namespace { const char* String; }; public: - LiteralConstantEmitter(int number = 0) : + LiteralConstantEmitter(int number = 0) : IsNumber(true), Number(number) { } @@ -117,7 +117,7 @@ namespace { o << String; } }; - + class CompoundConstantEmitter : public ConstantEmitter { private: unsigned int Padding; @@ -127,7 +127,7 @@ namespace { } CompoundConstantEmitter &addEntry(ConstantEmitter *e) { Entries.push_back(e); - + return *this; } ~CompoundConstantEmitter() { @@ -140,12 +140,12 @@ namespace { void emit(raw_ostream &o, unsigned int &i) { o << "{" << "\n"; i += 2; - + unsigned int index; unsigned int numEntries = Entries.size(); - + unsigned int numToPrint; - + if (Padding) { if (numEntries > Padding) { fprintf(stderr, "%u entries but %u padding\n", numEntries, Padding); @@ -155,24 +155,24 @@ namespace { } else { numToPrint = numEntries; } - + for (index = 0; index < numToPrint; ++index) { o.indent(i); if (index < numEntries) Entries[index]->emit(o, i); else o << "-1"; - + if (index < (numToPrint - 1)) o << ","; o << "\n"; } - + i -= 2; o.indent(i) << "}"; } }; - + class FlagsConstantEmitter : public ConstantEmitter { private: std::vector<std::string> Flags; @@ -188,7 +188,7 @@ namespace { 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)) @@ -218,15 +218,15 @@ 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 == + if (operandIterator->OperandType == AsmWriterOperand::isMachineInstrOperand) { operandOrder->addEntry( new LiteralConstantEmitter(operandIterator->CGIOpNo)); @@ -274,7 +274,7 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type, REG("SEGMENT_REG"); REG("DEBUG_REG"); REG("CONTROL_REG"); - + IMM("i8imm"); IMM("i16imm"); IMM("i16i8imm"); @@ -284,7 +284,7 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type, IMM("i64i8imm"); IMM("i64i32imm"); IMM("SSECC"); - + // all R, I, R, I, R MEM("i8mem"); MEM("i8mem_NOREX"); @@ -306,12 +306,12 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type, MEM("f128mem"); MEM("f256mem"); MEM("opaque512mem"); - + // all R, I, R, I LEA("lea32mem"); LEA("lea64_32mem"); LEA("lea64mem"); - + // all I PCR("i16imm_pcrel"); PCR("i32imm_pcrel"); @@ -322,7 +322,12 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type, PCR("offset32"); PCR("offset64"); PCR("brtarget"); - + PCR("uncondbrtarget"); + PCR("bltarget"); + + // all I, ARM mode only, conditional/unconditional + PCR("br_target"); + PCR("bl_target"); return 1; } @@ -344,19 +349,19 @@ static void X86PopulateOperands( const CodeGenInstruction &inst) { if (!inst.TheDef->isSubClassOf("X86Inst")) return; - + unsigned int index; - unsigned int numOperands = inst.OperandList.size(); - + unsigned int numOperands = inst.Operands.size(); + for (index = 0; index < numOperands; ++index) { - const CodeGenInstruction::OperandInfo &operandInfo = - inst.OperandList[index]; + const CGIOperandList::OperandInfo &operandInfo = inst.Operands[index]; Record &rec = *operandInfo.Rec; - - if (X86TypeFromOpName(operandTypes[index], rec.getName())) { + + if (X86TypeFromOpName(operandTypes[index], rec.getName()) && + !rec.isSubClassOf("PointerLikeRegClass")) { errs() << "Operand type: " << rec.getName().c_str() << "\n"; errs() << "Operand name: " << operandInfo.Name.c_str() << "\n"; - errs() << "Instruction mame: " << inst.TheDef->getName().c_str() << "\n"; + errs() << "Instruction name: " << inst.TheDef->getName().c_str() << "\n"; llvm_unreachable("Unhandled type"); } } @@ -375,9 +380,9 @@ static inline void decorate1( const char *opName, const char *opFlag) { unsigned opIndex; - - opIndex = inst.getOperandNamed(std::string(opName)); - + + opIndex = inst.Operands.getOperandNamed(std::string(opName)); + operandFlags[opIndex]->addEntry(opFlag); } @@ -414,7 +419,7 @@ static inline void decorate1( } /// X86ExtractSemantics - Performs various checks on the name of an X86 -/// instruction to determine what sort of an instruction it is and then adds +/// instruction to determine what sort of an instruction it is and then adds /// the appropriate flags to the instruction and its operands /// /// @arg instType - A reference to the type for the instruction as a whole @@ -425,7 +430,7 @@ static void X86ExtractSemantics( FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS], const CodeGenInstruction &inst) { const std::string &name = inst.TheDef->getName(); - + if (name.find("MOV") != name.npos) { if (name.find("MOV_V") != name.npos) { // ignore (this is a pseudoinstruction) @@ -450,7 +455,7 @@ static void X86ExtractSemantics( MOV("src", "dst"); } } - + if (name.find("JMP") != name.npos || name.find("J") == 0) { if (name.find("FAR") != name.npos && name.find("i") != name.npos) { @@ -459,10 +464,14 @@ static void X86ExtractSemantics( BRANCH("dst"); } } - + if (name.find("PUSH") != name.npos) { - if (name.find("FS") != name.npos || - name.find("GS") != name.npos) { + if (name.find("CS") != name.npos || + name.find("DS") != name.npos || + name.find("ES") != name.npos || + name.find("FS") != name.npos || + name.find("GS") != name.npos || + name.find("SS") != name.npos) { instType.set("kInstructionTypePush"); // TODO add support for fixed operands } else if (name.find("F") != name.npos) { @@ -477,12 +486,16 @@ static void X86ExtractSemantics( 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) { + } else if (name.find("CS") != name.npos || + name.find("DS") != name.npos || + name.find("ES") != name.npos || + name.find("FS") != name.npos || + name.find("GS") != name.npos || + name.find("SS") != name.npos) { instType.set("kInstructionTypePop"); // TODO add support for fixed operands } else if (name.find("F") != name.npos) { @@ -495,7 +508,7 @@ static void X86ExtractSemantics( POP("reg"); } } - + if (name.find("CALL") != name.npos) { if (name.find("ADJ") != name.npos) { // ignore (not a call) @@ -509,7 +522,7 @@ static void X86ExtractSemantics( CALL("dst"); } } - + if (name.find("RET") != name.npos) { RETURN(); } @@ -553,12 +566,20 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, REG("QPR"); REG("QQPR"); REG("QQQQPR"); - + IMM("i32imm"); + IMM("i32imm_hilo16"); IMM("bf_inv_mask_imm"); + IMM("lsb_pos_imm"); + IMM("width_imm"); IMM("jtblock_operand"); IMM("nohash_imm"); + IMM("p_imm"); + IMM("c_imm"); + IMM("imod_op"); + IMM("iflags_op"); IMM("cpinst_operand"); + IMM("setend_op"); IMM("cps_opt"); IMM("vfp_f64imm"); IMM("vfp_f32imm"); @@ -566,46 +587,73 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, IMM("msr_mask"); IMM("neg_zero"); IMM("imm0_31"); + IMM("imm0_31_m1"); IMM("nModImm"); IMM("imm0_4095"); IMM("jt2block_operand"); IMM("t_imm_s4"); IMM("pclabel"); + IMM("adrlabel"); + IMM("t_adrlabel"); + IMM("t2adrlabel"); IMM("shift_imm"); - + IMM("neon_vcvt_imm32"); + MISC("brtarget", "kOperandTypeARMBranchTarget"); // ? + MISC("uncondbrtarget", "kOperandTypeARMBranchTarget"); // ? + MISC("t_brtarget", "kOperandTypeARMBranchTarget"); // ? + MISC("t_bcctarget", "kOperandTypeARMBranchTarget"); // ? + MISC("t_cbtarget", "kOperandTypeARMBranchTarget"); // ? + MISC("bltarget", "kOperandTypeARMBranchTarget"); // ? + + MISC("br_target", "kOperandTypeARMBranchTarget"); // ? + MISC("bl_target", "kOperandTypeARMBranchTarget"); // ? + + MISC("t_bltarget", "kOperandTypeARMBranchTarget"); // ? + MISC("t_blxtarget", "kOperandTypeARMBranchTarget"); // ? MISC("so_reg", "kOperandTypeARMSoReg"); // R, R, I + MISC("shift_so_reg", "kOperandTypeARMSoReg"); // R, R, I MISC("t2_so_reg", "kOperandTypeThumb2SoReg"); // R, I MISC("so_imm", "kOperandTypeARMSoImm"); // I + MISC("rot_imm", "kOperandTypeARMRotImm"); // I MISC("t2_so_imm", "kOperandTypeThumb2SoImm"); // I MISC("so_imm2part", "kOperandTypeARMSoImm2Part"); // I MISC("pred", "kOperandTypeARMPredicate"); // I, R MISC("it_pred", "kOperandTypeARMPredicate"); // I + MISC("addrmode_imm12", "kOperandTypeAddrModeImm12"); // R, I + MISC("ldst_so_reg", "kOperandTypeLdStSOReg"); // R, R, I MISC("addrmode2", "kOperandTypeARMAddrMode2"); // R, R, I MISC("am2offset", "kOperandTypeARMAddrMode2Offset"); // R, I MISC("addrmode3", "kOperandTypeARMAddrMode3"); // R, R, I MISC("am3offset", "kOperandTypeARMAddrMode3Offset"); // R, I - MISC("addrmode4", "kOperandTypeARMAddrMode4"); // R, I + MISC("ldstm_mode", "kOperandTypeARMLdStmMode"); // I MISC("addrmode5", "kOperandTypeARMAddrMode5"); // R, I MISC("addrmode6", "kOperandTypeARMAddrMode6"); // R, R, I, I MISC("am6offset", "kOperandTypeARMAddrMode6Offset"); // R, I, I + MISC("addrmode6dup", "kOperandTypeARMAddrMode6"); // R, R, I, I MISC("addrmodepc", "kOperandTypeARMAddrModePC"); // R, I MISC("reglist", "kOperandTypeARMRegisterList"); // I, R, ... + MISC("dpr_reglist", "kOperandTypeARMDPRRegisterList"); // I, R, ... + MISC("spr_reglist", "kOperandTypeARMSPRRegisterList"); // I, R, ... MISC("it_mask", "kOperandTypeThumbITMask"); // I MISC("t2addrmode_imm8", "kOperandTypeThumb2AddrModeImm8"); // R, I MISC("t2am_imm8_offset", "kOperandTypeThumb2AddrModeImm8Offset");//I MISC("t2addrmode_imm12", "kOperandTypeThumb2AddrModeImm12"); // R, I MISC("t2addrmode_so_reg", "kOperandTypeThumb2AddrModeSoReg"); // R, R, I MISC("t2addrmode_imm8s4", "kOperandTypeThumb2AddrModeImm8s4"); // R, I - MISC("t2am_imm8s4_offset", "kOperandTypeThumb2AddrModeImm8s4Offset"); + MISC("t2am_imm8s4_offset", "kOperandTypeThumb2AddrModeImm8s4Offset"); // R, I MISC("tb_addrmode", "kOperandTypeARMTBAddrMode"); // I - MISC("t_addrmode_s1", "kOperandTypeThumbAddrModeS1"); // R, I, R - MISC("t_addrmode_s2", "kOperandTypeThumbAddrModeS2"); // R, I, R - MISC("t_addrmode_s4", "kOperandTypeThumbAddrModeS4"); // R, I, R + MISC("t_addrmode_rrs1", "kOperandTypeThumbAddrModeRegS"); // R, R + MISC("t_addrmode_rrs2", "kOperandTypeThumbAddrModeRegS"); // R, R + MISC("t_addrmode_rrs4", "kOperandTypeThumbAddrModeRegS"); // R, R + MISC("t_addrmode_is1", "kOperandTypeThumbAddrModeImmS"); // R, I + MISC("t_addrmode_is2", "kOperandTypeThumbAddrModeImmS"); // R, I + MISC("t_addrmode_is4", "kOperandTypeThumbAddrModeImmS"); // R, I MISC("t_addrmode_rr", "kOperandTypeThumbAddrModeRR"); // R, R MISC("t_addrmode_sp", "kOperandTypeThumbAddrModeSP"); // R, I - + MISC("t_addrmode_pc", "kOperandTypeThumbAddrModePC"); // R, I + return 1; } @@ -631,25 +679,24 @@ static void ARMPopulateOperands( if (!inst.TheDef->isSubClassOf("InstARM") && !inst.TheDef->isSubClassOf("InstThumb")) return; - + unsigned int index; - unsigned int numOperands = inst.OperandList.size(); - + unsigned int numOperands = inst.Operands.size(); + if (numOperands > EDIS_MAX_OPERANDS) { - errs() << "numOperands == " << numOperands << " > " << + errs() << "numOperands == " << numOperands << " > " << EDIS_MAX_OPERANDS << '\n'; llvm_unreachable("Too many operands"); } - + for (index = 0; index < numOperands; ++index) { - const CodeGenInstruction::OperandInfo &operandInfo = - inst.OperandList[index]; + const CGIOperandList::OperandInfo &operandInfo = inst.Operands[index]; Record &rec = *operandInfo.Rec; - + if (ARMFlagFromOpName(operandTypes[index], rec.getName())) { errs() << "Operand type: " << rec.getName() << '\n'; errs() << "Operand name: " << operandInfo.Name << '\n'; - errs() << "Instruction mame: " << inst.TheDef->getName() << '\n'; + errs() << "Instruction name: " << inst.TheDef->getName() << '\n'; llvm_unreachable("Unhandled type"); } } @@ -661,7 +708,7 @@ static void ARMPopulateOperands( } /// ARMExtractSemantics - Performs various checks on the name of an ARM -/// instruction to determine what sort of an instruction it is and then adds +/// instruction to determine what sort of an instruction it is and then adds /// the appropriate flags to the instruction and its operands /// /// @arg instType - A reference to the type for the instruction as a whole @@ -674,7 +721,7 @@ static void ARMExtractSemantics( FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS], const CodeGenInstruction &inst) { const std::string &name = inst.TheDef->getName(); - + if (name == "tBcc" || name == "tB" || name == "t2Bcc" || @@ -683,7 +730,7 @@ static void ARMExtractSemantics( name == "tCBNZ") { BRANCH("target"); } - + if (name == "tBLr9" || name == "BLr9_pred" || name == "tBLXi_r9" || @@ -692,9 +739,9 @@ static void ARMExtractSemantics( name == "t2BXJ" || name == "BXJ") { BRANCH("func"); - + unsigned opIndex; - opIndex = inst.getOperandNamed("func"); + opIndex = inst.Operands.getOperandNamed("func"); if (operandTypes[opIndex]->is("kOperandTypeImmediate")) operandTypes[opIndex]->set("kOperandTypeARMBranchTarget"); } @@ -702,7 +749,7 @@ static void ARMExtractSemantics( #undef BRANCH -/// populateInstInfo - Fills an array of InstInfos with information about each +/// populateInstInfo - Fills an array of InstInfos with information about each /// instruction in a target /// /// @arg infoArray - The array of InstInfo objects to populate @@ -711,45 +758,45 @@ static void populateInstInfo(CompoundConstantEmitter &infoArray, CodeGenTarget &target) { const std::vector<const CodeGenInstruction*> &numberedInstructions = target.getInstructionsByEnumValue(); - + unsigned int index; unsigned int numInstructions = numberedInstructions.size(); - + for (index = 0; index < numInstructions; ++index) { const CodeGenInstruction& inst = *numberedInstructions[index]; - + CompoundConstantEmitter *infoStruct = new CompoundConstantEmitter; infoArray.addEntry(infoStruct); - + LiteralConstantEmitter *instType = new LiteralConstantEmitter; infoStruct->addEntry(instType); - - LiteralConstantEmitter *numOperandsEmitter = - new LiteralConstantEmitter(inst.OperandList.size()); + + LiteralConstantEmitter *numOperandsEmitter = + new LiteralConstantEmitter(inst.Operands.size()); infoStruct->addEntry(numOperandsEmitter); - + CompoundConstantEmitter *operandTypeArray = new CompoundConstantEmitter; infoStruct->addEntry(operandTypeArray); - + LiteralConstantEmitter *operandTypes[EDIS_MAX_OPERANDS]; - + CompoundConstantEmitter *operandFlagArray = new CompoundConstantEmitter; infoStruct->addEntry(operandFlagArray); - + FlagsConstantEmitter *operandFlags[EDIS_MAX_OPERANDS]; - - for (unsigned operandIndex = 0; - operandIndex < EDIS_MAX_OPERANDS; + + for (unsigned operandIndex = 0; + operandIndex < EDIS_MAX_OPERANDS; ++operandIndex) { operandTypes[operandIndex] = new LiteralConstantEmitter; operandTypeArray->addEntry(operandTypes[operandIndex]); - + operandFlags[operandIndex] = new FlagsConstantEmitter; operandFlagArray->addEntry(operandFlags[operandIndex]); } - + unsigned numSyntaxes = 0; - + if (target.getName() == "X86") { X86PopulateOperands(operandTypes, inst); X86ExtractSemantics(*instType, operandFlags, inst); @@ -760,24 +807,24 @@ static void populateInstInfo(CompoundConstantEmitter &infoArray, ARMExtractSemantics(*instType, operandTypes, operandFlags, inst); numSyntaxes = 1; } - - CompoundConstantEmitter *operandOrderArray = new CompoundConstantEmitter; - + + CompoundConstantEmitter *operandOrderArray = new CompoundConstantEmitter; + infoStruct->addEntry(operandOrderArray); - - for (unsigned syntaxIndex = 0; - syntaxIndex < EDIS_MAX_SYNTAXES; + + for (unsigned syntaxIndex = 0; + syntaxIndex < EDIS_MAX_SYNTAXES; ++syntaxIndex) { - CompoundConstantEmitter *operandOrder = + CompoundConstantEmitter *operandOrder = new CompoundConstantEmitter(EDIS_MAX_OPERANDS); - + operandOrderArray->addEntry(operandOrder); - + if (syntaxIndex < numSyntaxes) { populateOperandOrder(operandOrder, inst, syntaxIndex); } } - + infoStruct = NULL; } } @@ -793,25 +840,30 @@ static void emitCommonEnums(raw_ostream &o, unsigned int &i) { operandTypes.addEntry("kOperandTypeARMBranchTarget"); operandTypes.addEntry("kOperandTypeARMSoReg"); operandTypes.addEntry("kOperandTypeARMSoImm"); + operandTypes.addEntry("kOperandTypeARMRotImm"); operandTypes.addEntry("kOperandTypeARMSoImm2Part"); operandTypes.addEntry("kOperandTypeARMPredicate"); + operandTypes.addEntry("kOperandTypeAddrModeImm12"); + operandTypes.addEntry("kOperandTypeLdStSOReg"); operandTypes.addEntry("kOperandTypeARMAddrMode2"); operandTypes.addEntry("kOperandTypeARMAddrMode2Offset"); operandTypes.addEntry("kOperandTypeARMAddrMode3"); operandTypes.addEntry("kOperandTypeARMAddrMode3Offset"); - operandTypes.addEntry("kOperandTypeARMAddrMode4"); + operandTypes.addEntry("kOperandTypeARMLdStmMode"); operandTypes.addEntry("kOperandTypeARMAddrMode5"); operandTypes.addEntry("kOperandTypeARMAddrMode6"); operandTypes.addEntry("kOperandTypeARMAddrMode6Offset"); operandTypes.addEntry("kOperandTypeARMAddrModePC"); operandTypes.addEntry("kOperandTypeARMRegisterList"); + operandTypes.addEntry("kOperandTypeARMDPRRegisterList"); + operandTypes.addEntry("kOperandTypeARMSPRRegisterList"); operandTypes.addEntry("kOperandTypeARMTBAddrMode"); operandTypes.addEntry("kOperandTypeThumbITMask"); - operandTypes.addEntry("kOperandTypeThumbAddrModeS1"); - operandTypes.addEntry("kOperandTypeThumbAddrModeS2"); - operandTypes.addEntry("kOperandTypeThumbAddrModeS4"); + operandTypes.addEntry("kOperandTypeThumbAddrModeRegS"); + operandTypes.addEntry("kOperandTypeThumbAddrModeImmS"); operandTypes.addEntry("kOperandTypeThumbAddrModeRR"); operandTypes.addEntry("kOperandTypeThumbAddrModeSP"); + operandTypes.addEntry("kOperandTypeThumbAddrModePC"); operandTypes.addEntry("kOperandTypeThumb2SoReg"); operandTypes.addEntry("kOperandTypeThumb2SoImm"); operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8"); @@ -821,16 +873,16 @@ static void emitCommonEnums(raw_ostream &o, unsigned int &i) { operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8s4"); operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8s4Offset"); operandTypes.emit(o, i); - + o << "\n"; - + EnumEmitter operandFlags("OperandFlags"); operandFlags.addEntry("kOperandFlagSource"); operandFlags.addEntry("kOperandFlagTarget"); operandFlags.emitAsFlags(o, i); - + o << "\n"; - + EnumEmitter instructionTypes("InstructionTypes"); instructionTypes.addEntry("kInstructionTypeNone"); instructionTypes.addEntry("kInstructionTypeMove"); @@ -840,25 +892,25 @@ static void emitCommonEnums(raw_ostream &o, unsigned int &i) { instructionTypes.addEntry("kInstructionTypeCall"); instructionTypes.addEntry("kInstructionTypeReturn"); instructionTypes.emit(o, i); - + o << "\n"; } void EDEmitter::run(raw_ostream &o) { unsigned int i = 0; - + CompoundConstantEmitter infoArray; - CodeGenTarget target; - + CodeGenTarget target(Records); + populateInstInfo(infoArray, target); - + emitCommonEnums(o, i); - + o << "namespace {\n"; - + o << "llvm::EDInstInfo instInfo" << target.getName().c_str() << "[] = "; infoArray.emit(o, i); o << ";" << "\n"; - + o << "}\n"; } diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp index 6c16fcf..f01de1d 100644 --- a/utils/TableGen/FastISelEmitter.cpp +++ b/utils/TableGen/FastISelEmitter.cpp @@ -20,6 +20,7 @@ #include "FastISelEmitter.h" #include "Record.h" #include "llvm/Support/Debug.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/VectorExtras.h" using namespace llvm; @@ -65,23 +66,23 @@ struct OperandsSignature { return true; } } - + const CodeGenRegisterClass *DstRC = 0; - + for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e; ++i) { TreePatternNode *Op = InstPatNode->getChild(i); - + // For now, filter out any operand with a predicate. // For now, filter out any operand with multiple values. if (!Op->getPredicateFns().empty() || Op->getNumTypes() != 1) return false; - + assert(Op->hasTypeSet(0) && "Type infererence not done?"); // For now, all the operands must have the same type. if (Op->getType(0) != VT) return false; - + if (!Op->isLeaf()) { if (Op->getOperator()->getName() == "imm") { Operands.push_back("i"); @@ -107,7 +108,7 @@ struct OperandsSignature { RC = Target.getRegisterClassForRegister(OpLeafRec); else return false; - + // For now, this needs to be a register class of some sort. if (!RC) return false; @@ -212,7 +213,7 @@ class FastISelMap { typedef std::map<MVT::SimpleValueType, PredMap> RetPredMap; typedef std::map<MVT::SimpleValueType, RetPredMap> TypeRetPredMap; typedef std::map<std::string, TypeRetPredMap> OpcodeTypeRetPredMap; - typedef std::map<OperandsSignature, OpcodeTypeRetPredMap> + typedef std::map<OperandsSignature, OpcodeTypeRetPredMap> OperandsOpcodeTypeRetPredMap; OperandsOpcodeTypeRetPredMap SimplePatterns; @@ -263,9 +264,9 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { if (!Op->isSubClassOf("Instruction")) continue; CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op); - if (II.OperandList.empty()) + if (II.Operands.size() == 0) continue; - + // For now, ignore multi-instruction patterns. bool MultiInsts = false; for (unsigned i = 0, e = Dst->getNumChildren(); i != e; ++i) { @@ -285,7 +286,7 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { const CodeGenRegisterClass *DstRC = 0; std::string SubRegNo; if (Op->getName() != "EXTRACT_SUBREG") { - Record *Op0Rec = II.OperandList[0].Rec; + Record *Op0Rec = II.Operands[0].Rec; if (!Op0Rec->isSubClassOf("RegisterClass")) continue; DstRC = &Target.getRegisterClass(Op0Rec); @@ -295,7 +296,7 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { // If this isn't a leaf, then continue since the register classes are // a bit too complicated for now. if (!Dst->getChild(1)->isLeaf()) continue; - + DefInit *SR = dynamic_cast<DefInit*>(Dst->getChild(1)->getLeafValue()); if (SR) SubRegNo = getQualifiedName(SR->getDef()); @@ -310,7 +311,7 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { // Ignore multiple result nodes for now. if (InstPatNode->getNumTypes() > 1) continue; - + Record *InstPatOp = InstPatNode->getOperator(); std::string OpcodeName = getOpcodeName(InstPatOp, CGP); MVT::SimpleValueType RetVT = MVT::isVoid; @@ -334,7 +335,7 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { OperandsSignature Operands; if (!Operands.initialize(InstPatNode, Target, VT)) continue; - + std::vector<std::string>* PhysRegInputs = new std::vector<std::string>(); if (!InstPatNode->isLeaf() && (InstPatNode->getOperator()->getName() == "imm" || @@ -347,7 +348,7 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { PhysRegInputs->push_back(""); continue; } - + DefInit *OpDI = dynamic_cast<DefInit*>(Op->getLeafValue()); Record *OpLeafRec = OpDI->getDef(); std::string PhysReg; @@ -355,7 +356,7 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { PhysReg += static_cast<StringInit*>(OpLeafRec->getValue( \ "Namespace")->getValue())->getValue(); PhysReg += "::"; - + std::vector<CodeGenRegister> Regs = Target.getRegisters(); for (unsigned i = 0; i < Regs.size(); ++i) { if (Regs[i].TheDef == OpLeafRec) { @@ -364,7 +365,7 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { } } } - + PhysRegInputs->push_back(PhysReg); } } else @@ -380,9 +381,10 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) { SubRegNo, PhysRegInputs }; - assert(!SimplePatterns[Operands][OpcodeName][VT][RetVT] - .count(PredicateCheck) && - "Duplicate pattern!"); + if (SimplePatterns[Operands][OpcodeName][VT][RetVT] + .count(PredicateCheck)) + throw TGError(Pattern.getSrcRecord()->getLoc(), "Duplicate record!"); + SimplePatterns[Operands][OpcodeName][VT][RetVT][PredicateCheck] = Memo; } } @@ -429,7 +431,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { PI != PE; ++PI) { std::string PredicateCheck = PI->first; const InstructionMemo &Memo = PI->second; - + if (PredicateCheck.empty()) { assert(!HasPred && "Multiple instructions match, at least one has " @@ -439,14 +441,14 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << " "; HasPred = true; } - + for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) { if ((*Memo.PhysRegs)[i] != "") OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, " << "TII.get(TargetOpcode::COPY), " << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n"; } - + OS << " return FastEmitInst_"; if (Memo.SubRegNo.empty()) { Operands.PrintManglingSuffix(OS, *Memo.PhysRegs); @@ -462,10 +464,10 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << Memo.SubRegNo; OS << ");\n"; } - + if (HasPred) OS << " }\n"; - + } // Return 0 if none of the predicates were satisfied. if (HasPred) @@ -473,7 +475,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << "}\n"; OS << "\n"; } - + // Emit one function for the type that demultiplexes on return type. OS << "unsigned FastEmit_" << getLegalCName(Opcode) << "_" @@ -496,7 +498,7 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << ");\n"; } OS << " default: return 0;\n}\n}\n\n"; - + } else { // Non-variadic return type. OS << "unsigned FastEmit_" @@ -508,13 +510,13 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << ", "; Operands.PrintParameters(OS); OS << ") {\n"; - + OS << " if (RetVT.SimpleTy != " << getName(RM.begin()->first) << ")\n return 0;\n"; - + const PredMap &PM = RM.begin()->second; bool HasPred = false; - + // Emit code for each possible instruction. There may be // multiple if there are subtarget concerns. for (PredMap::const_iterator PI = PM.begin(), PE = PM.end(); PI != PE; @@ -531,16 +533,16 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << " "; HasPred = true; } - + for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) { if ((*Memo.PhysRegs)[i] != "") OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, " << "TII.get(TargetOpcode::COPY), " << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n"; } - + OS << " return FastEmitInst_"; - + if (Memo.SubRegNo.empty()) { Operands.PrintManglingSuffix(OS, *Memo.PhysRegs); OS << "(" << InstNS << Memo.Name << ", "; @@ -554,11 +556,11 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) { OS << Memo.SubRegNo; OS << ");\n"; } - + if (HasPred) OS << " }\n"; } - + // Return 0 if none of the predicates were satisfied. if (HasPred) OS << " return 0;\n"; diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp new file mode 100644 index 0000000..2c222b3 --- /dev/null +++ b/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -0,0 +1,1372 @@ +//===------------ FixedLenDecoderEmitter.cpp - Decoder Generator ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// It contains the tablegen backend that emits the decoder functions for +// targets with fixed length instruction set. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "decoder-emitter" + +#include "FixedLenDecoderEmitter.h" +#include "CodeGenTarget.h" +#include "Record.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +#include <vector> +#include <map> +#include <string> + +using namespace llvm; + +// The set (BIT_TRUE, BIT_FALSE, BIT_UNSET) represents a ternary logic system +// for a bit value. +// +// BIT_UNFILTERED is used as the init value for a filter position. It is used +// only for filter processings. +typedef enum { + BIT_TRUE, // '1' + BIT_FALSE, // '0' + BIT_UNSET, // '?' + BIT_UNFILTERED // unfiltered +} bit_value_t; + +static bool ValueSet(bit_value_t V) { + return (V == BIT_TRUE || V == BIT_FALSE); +} +static bool ValueNotSet(bit_value_t V) { + return (V == BIT_UNSET); +} +static int Value(bit_value_t V) { + return ValueNotSet(V) ? -1 : (V == BIT_FALSE ? 0 : 1); +} +static bit_value_t bitFromBits(BitsInit &bits, unsigned index) { + if (BitInit *bit = dynamic_cast<BitInit*>(bits.getBit(index))) + return bit->getValue() ? BIT_TRUE : BIT_FALSE; + + // The bit is uninitialized. + return BIT_UNSET; +} +// Prints the bit value for each position. +static void dumpBits(raw_ostream &o, BitsInit &bits) { + unsigned index; + + for (index = bits.getNumBits(); index > 0; index--) { + switch (bitFromBits(bits, index - 1)) { + case BIT_TRUE: + o << "1"; + break; + case BIT_FALSE: + o << "0"; + break; + case BIT_UNSET: + o << "_"; + break; + default: + assert(0 && "unexpected return value from bitFromBits"); + } + } +} + +static BitsInit &getBitsField(const Record &def, const char *str) { + BitsInit *bits = def.getValueAsBitsInit(str); + return *bits; +} + +// Forward declaration. +class FilterChooser; + +// FIXME: Possibly auto-detected? +#define BIT_WIDTH 32 + +// Representation of the instruction to work on. +typedef bit_value_t insn_t[BIT_WIDTH]; + +/// Filter - Filter works with FilterChooser to produce the decoding tree for +/// the ISA. +/// +/// It is useful to think of a Filter as governing the switch stmts of the +/// decoding tree in a certain level. Each case stmt delegates to an inferior +/// FilterChooser to decide what further decoding logic to employ, or in another +/// words, what other remaining bits to look at. The FilterChooser eventually +/// chooses a best Filter to do its job. +/// +/// This recursive scheme ends when the number of Opcodes assigned to the +/// FilterChooser becomes 1 or if there is a conflict. A conflict happens when +/// the Filter/FilterChooser combo does not know how to distinguish among the +/// Opcodes assigned. +/// +/// An example of a conflict is +/// +/// Conflict: +/// 111101000.00........00010000.... +/// 111101000.00........0001........ +/// 1111010...00........0001........ +/// 1111010...00.................... +/// 1111010......................... +/// 1111............................ +/// ................................ +/// VST4q8a 111101000_00________00010000____ +/// VST4q8b 111101000_00________00010000____ +/// +/// The Debug output shows the path that the decoding tree follows to reach the +/// the conclusion that there is a conflict. VST4q8a is a vst4 to double-spaced +/// even registers, while VST4q8b is a vst4 to double-spaced odd regsisters. +/// +/// The encoding info in the .td files does not specify this meta information, +/// which could have been used by the decoder to resolve the conflict. The +/// decoder could try to decode the even/odd register numbering and assign to +/// VST4q8a or VST4q8b, but for the time being, the decoder chooses the "a" +/// version and return the Opcode since the two have the same Asm format string. +class Filter { +protected: + FilterChooser *Owner; // points to the FilterChooser who owns this filter + unsigned StartBit; // the starting bit position + unsigned NumBits; // number of bits to filter + bool Mixed; // a mixed region contains both set and unset bits + + // Map of well-known segment value to the set of uid's with that value. + std::map<uint64_t, std::vector<unsigned> > FilteredInstructions; + + // Set of uid's with non-constant segment values. + std::vector<unsigned> VariableInstructions; + + // Map of well-known segment value to its delegate. + std::map<unsigned, FilterChooser*> FilterChooserMap; + + // Number of instructions which fall under FilteredInstructions category. + unsigned NumFiltered; + + // Keeps track of the last opcode in the filtered bucket. + unsigned LastOpcFiltered; + + // Number of instructions which fall under VariableInstructions category. + unsigned NumVariable; + +public: + unsigned getNumFiltered() { return NumFiltered; } + unsigned getNumVariable() { return NumVariable; } + unsigned getSingletonOpc() { + assert(NumFiltered == 1); + return LastOpcFiltered; + } + // Return the filter chooser for the group of instructions without constant + // segment values. + FilterChooser &getVariableFC() { + assert(NumFiltered == 1); + assert(FilterChooserMap.size() == 1); + return *(FilterChooserMap.find((unsigned)-1)->second); + } + + Filter(const Filter &f); + Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, bool mixed); + + ~Filter(); + + // Divides the decoding task into sub tasks and delegates them to the + // inferior FilterChooser's. + // + // A special case arises when there's only one entry in the filtered + // instructions. In order to unambiguously decode the singleton, we need to + // match the remaining undecoded encoding bits against the singleton. + void recurse(); + + // Emit code to decode instructions given a segment or segments of bits. + void emit(raw_ostream &o, unsigned &Indentation); + + // Returns the number of fanout produced by the filter. More fanout implies + // the filter distinguishes more categories of instructions. + unsigned usefulness() const; +}; // End of class Filter + +// These are states of our finite state machines used in FilterChooser's +// filterProcessor() which produces the filter candidates to use. +typedef enum { + ATTR_NONE, + ATTR_FILTERED, + ATTR_ALL_SET, + ATTR_ALL_UNSET, + ATTR_MIXED +} bitAttr_t; + +/// FilterChooser - FilterChooser chooses the best filter among a set of Filters +/// in order to perform the decoding of instructions at the current level. +/// +/// Decoding proceeds from the top down. Based on the well-known encoding bits +/// of instructions available, FilterChooser builds up the possible Filters that +/// can further the task of decoding by distinguishing among the remaining +/// candidate instructions. +/// +/// Once a filter has been chosen, it is called upon to divide the decoding task +/// into sub-tasks and delegates them to its inferior FilterChoosers for further +/// processings. +/// +/// It is useful to think of a Filter as governing the switch stmts of the +/// decoding tree. And each case is delegated to an inferior FilterChooser to +/// decide what further remaining bits to look at. +class FilterChooser { +protected: + friend class Filter; + + // Vector of codegen instructions to choose our filter. + const std::vector<const CodeGenInstruction*> &AllInstructions; + + // Vector of uid's for this filter chooser to work on. + const std::vector<unsigned> Opcodes; + + // Lookup table for the operand decoding of instructions. + std::map<unsigned, std::vector<OperandInfo> > &Operands; + + // Vector of candidate filters. + std::vector<Filter> Filters; + + // Array of bit values passed down from our parent. + // Set to all BIT_UNFILTERED's for Parent == NULL. + bit_value_t FilterBitValues[BIT_WIDTH]; + + // Links to the FilterChooser above us in the decoding tree. + FilterChooser *Parent; + + // Index of the best filter from Filters. + int BestIndex; + +public: + FilterChooser(const FilterChooser &FC) : + AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes), + Operands(FC.Operands), Filters(FC.Filters), Parent(FC.Parent), + BestIndex(FC.BestIndex) { + memcpy(FilterBitValues, FC.FilterBitValues, sizeof(FilterBitValues)); + } + + FilterChooser(const std::vector<const CodeGenInstruction*> &Insts, + const std::vector<unsigned> &IDs, + std::map<unsigned, std::vector<OperandInfo> > &Ops) : + AllInstructions(Insts), Opcodes(IDs), Operands(Ops), Filters(), + Parent(NULL), BestIndex(-1) { + for (unsigned i = 0; i < BIT_WIDTH; ++i) + FilterBitValues[i] = BIT_UNFILTERED; + + doFilter(); + } + + FilterChooser(const std::vector<const CodeGenInstruction*> &Insts, + const std::vector<unsigned> &IDs, + std::map<unsigned, std::vector<OperandInfo> > &Ops, + bit_value_t (&ParentFilterBitValues)[BIT_WIDTH], + FilterChooser &parent) : + AllInstructions(Insts), Opcodes(IDs), Operands(Ops), + Filters(), Parent(&parent), BestIndex(-1) { + for (unsigned i = 0; i < BIT_WIDTH; ++i) + FilterBitValues[i] = ParentFilterBitValues[i]; + + doFilter(); + } + + // The top level filter chooser has NULL as its parent. + bool isTopLevel() { return Parent == NULL; } + + // Emit the top level typedef and decodeInstruction() function. + void emitTop(raw_ostream &o, unsigned Indentation); + +protected: + // Populates the insn given the uid. + void insnWithID(insn_t &Insn, unsigned Opcode) const { + BitsInit &Bits = getBitsField(*AllInstructions[Opcode]->TheDef, "Inst"); + + for (unsigned i = 0; i < BIT_WIDTH; ++i) + Insn[i] = bitFromBits(Bits, i); + } + + // Returns the record name. + const std::string &nameWithID(unsigned Opcode) const { + return AllInstructions[Opcode]->TheDef->getName(); + } + + // Populates the field of the insn given the start position and the number of + // consecutive bits to scan for. + // + // Returns false if there exists any uninitialized bit value in the range. + // Returns true, otherwise. + bool fieldFromInsn(uint64_t &Field, insn_t &Insn, unsigned StartBit, + unsigned NumBits) const; + + /// dumpFilterArray - dumpFilterArray prints out debugging info for the given + /// filter array as a series of chars. + void dumpFilterArray(raw_ostream &o, bit_value_t (&filter)[BIT_WIDTH]); + + /// dumpStack - dumpStack traverses the filter chooser chain and calls + /// dumpFilterArray on each filter chooser up to the top level one. + void dumpStack(raw_ostream &o, const char *prefix); + + Filter &bestFilter() { + assert(BestIndex != -1 && "BestIndex not set"); + return Filters[BestIndex]; + } + + // Called from Filter::recurse() when singleton exists. For debug purpose. + void SingletonExists(unsigned Opc); + + bool PositionFiltered(unsigned i) { + return ValueSet(FilterBitValues[i]); + } + + // Calculates the island(s) needed to decode the instruction. + // This returns a lit of undecoded bits of an instructions, for example, + // Inst{20} = 1 && Inst{3-0} == 0b1111 represents two islands of yet-to-be + // decoded bits in order to verify that the instruction matches the Opcode. + unsigned getIslands(std::vector<unsigned> &StartBits, + std::vector<unsigned> &EndBits, std::vector<uint64_t> &FieldVals, + insn_t &Insn); + + // Emits code to decode the singleton. Return true if we have matched all the + // well-known bits. + bool emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,unsigned Opc); + + // Emits code to decode the singleton, and then to decode the rest. + void emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,Filter &Best); + + // Assign a single filter and run with it. + void runSingleFilter(FilterChooser &owner, unsigned startBit, unsigned numBit, + bool mixed); + + // reportRegion is a helper function for filterProcessor to mark a region as + // eligible for use as a filter region. + void reportRegion(bitAttr_t RA, unsigned StartBit, unsigned BitIndex, + bool AllowMixed); + + // FilterProcessor scans the well-known encoding bits of the instructions and + // builds up a list of candidate filters. It chooses the best filter and + // recursively descends down the decoding tree. + bool filterProcessor(bool AllowMixed, bool Greedy = true); + + // Decides on the best configuration of filter(s) to use in order to decode + // the instructions. A conflict of instructions may occur, in which case we + // dump the conflict set to the standard error. + void doFilter(); + + // Emits code to decode our share of instructions. Returns true if the + // emitted code causes a return, which occurs if we know how to decode + // the instruction at this level or the instruction is not decodeable. + bool emit(raw_ostream &o, unsigned &Indentation); +}; + +/////////////////////////// +// // +// Filter Implmenetation // +// // +/////////////////////////// + +Filter::Filter(const Filter &f) : + Owner(f.Owner), StartBit(f.StartBit), NumBits(f.NumBits), Mixed(f.Mixed), + FilteredInstructions(f.FilteredInstructions), + VariableInstructions(f.VariableInstructions), + FilterChooserMap(f.FilterChooserMap), NumFiltered(f.NumFiltered), + LastOpcFiltered(f.LastOpcFiltered), NumVariable(f.NumVariable) { +} + +Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, + bool mixed) : Owner(&owner), StartBit(startBit), NumBits(numBits), + Mixed(mixed) { + assert(StartBit + NumBits - 1 < BIT_WIDTH); + + NumFiltered = 0; + LastOpcFiltered = 0; + NumVariable = 0; + + for (unsigned i = 0, e = Owner->Opcodes.size(); i != e; ++i) { + insn_t Insn; + + // Populates the insn given the uid. + Owner->insnWithID(Insn, Owner->Opcodes[i]); + + uint64_t Field; + // Scans the segment for possibly well-specified encoding bits. + bool ok = Owner->fieldFromInsn(Field, Insn, StartBit, NumBits); + + if (ok) { + // The encoding bits are well-known. Lets add the uid of the + // instruction into the bucket keyed off the constant field value. + LastOpcFiltered = Owner->Opcodes[i]; + FilteredInstructions[Field].push_back(LastOpcFiltered); + ++NumFiltered; + } else { + // Some of the encoding bit(s) are unspecfied. This contributes to + // one additional member of "Variable" instructions. + VariableInstructions.push_back(Owner->Opcodes[i]); + ++NumVariable; + } + } + + assert((FilteredInstructions.size() + VariableInstructions.size() > 0) + && "Filter returns no instruction categories"); +} + +Filter::~Filter() { + std::map<unsigned, FilterChooser*>::iterator filterIterator; + for (filterIterator = FilterChooserMap.begin(); + filterIterator != FilterChooserMap.end(); + filterIterator++) { + delete filterIterator->second; + } +} + +// Divides the decoding task into sub tasks and delegates them to the +// inferior FilterChooser's. +// +// A special case arises when there's only one entry in the filtered +// instructions. In order to unambiguously decode the singleton, we need to +// match the remaining undecoded encoding bits against the singleton. +void Filter::recurse() { + std::map<uint64_t, std::vector<unsigned> >::const_iterator mapIterator; + + bit_value_t BitValueArray[BIT_WIDTH]; + // Starts by inheriting our parent filter chooser's filter bit values. + memcpy(BitValueArray, Owner->FilterBitValues, sizeof(BitValueArray)); + + unsigned bitIndex; + + if (VariableInstructions.size()) { + // Conservatively marks each segment position as BIT_UNSET. + for (bitIndex = 0; bitIndex < NumBits; bitIndex++) + BitValueArray[StartBit + bitIndex] = BIT_UNSET; + + // Delegates to an inferior filter chooser for futher processing on this + // group of instructions whose segment values are variable. + FilterChooserMap.insert(std::pair<unsigned, FilterChooser*>( + (unsigned)-1, + new FilterChooser(Owner->AllInstructions, + VariableInstructions, + Owner->Operands, + BitValueArray, + *Owner) + )); + } + + // No need to recurse for a singleton filtered instruction. + // See also Filter::emit(). + if (getNumFiltered() == 1) { + //Owner->SingletonExists(LastOpcFiltered); + assert(FilterChooserMap.size() == 1); + return; + } + + // Otherwise, create sub choosers. + for (mapIterator = FilteredInstructions.begin(); + mapIterator != FilteredInstructions.end(); + mapIterator++) { + + // Marks all the segment positions with either BIT_TRUE or BIT_FALSE. + for (bitIndex = 0; bitIndex < NumBits; bitIndex++) { + if (mapIterator->first & (1ULL << bitIndex)) + BitValueArray[StartBit + bitIndex] = BIT_TRUE; + else + BitValueArray[StartBit + bitIndex] = BIT_FALSE; + } + + // Delegates to an inferior filter chooser for futher processing on this + // category of instructions. + FilterChooserMap.insert(std::pair<unsigned, FilterChooser*>( + mapIterator->first, + new FilterChooser(Owner->AllInstructions, + mapIterator->second, + Owner->Operands, + BitValueArray, + *Owner) + )); + } +} + +// Emit code to decode instructions given a segment or segments of bits. +void Filter::emit(raw_ostream &o, unsigned &Indentation) { + o.indent(Indentation) << "// Check Inst{"; + + if (NumBits > 1) + o << (StartBit + NumBits - 1) << '-'; + + o << StartBit << "} ...\n"; + + o.indent(Indentation) << "switch (fieldFromInstruction(insn, " + << StartBit << ", " << NumBits << ")) {\n"; + + std::map<unsigned, FilterChooser*>::iterator filterIterator; + + bool DefaultCase = false; + for (filterIterator = FilterChooserMap.begin(); + filterIterator != FilterChooserMap.end(); + filterIterator++) { + + // Field value -1 implies a non-empty set of variable instructions. + // See also recurse(). + if (filterIterator->first == (unsigned)-1) { + DefaultCase = true; + + o.indent(Indentation) << "default:\n"; + o.indent(Indentation) << " break; // fallthrough\n"; + + // Closing curly brace for the switch statement. + // This is unconventional because we want the default processing to be + // performed for the fallthrough cases as well, i.e., when the "cases" + // did not prove a decoded instruction. + o.indent(Indentation) << "}\n"; + + } else + o.indent(Indentation) << "case " << filterIterator->first << ":\n"; + + // We arrive at a category of instructions with the same segment value. + // Now delegate to the sub filter chooser for further decodings. + // The case may fallthrough, which happens if the remaining well-known + // encoding bits do not match exactly. + if (!DefaultCase) { ++Indentation; ++Indentation; } + + bool finished = filterIterator->second->emit(o, Indentation); + // For top level default case, there's no need for a break statement. + if (Owner->isTopLevel() && DefaultCase) + break; + if (!finished) + o.indent(Indentation) << "break;\n"; + + if (!DefaultCase) { --Indentation; --Indentation; } + } + + // If there is no default case, we still need to supply a closing brace. + if (!DefaultCase) { + // Closing curly brace for the switch statement. + o.indent(Indentation) << "}\n"; + } +} + +// Returns the number of fanout produced by the filter. More fanout implies +// the filter distinguishes more categories of instructions. +unsigned Filter::usefulness() const { + if (VariableInstructions.size()) + return FilteredInstructions.size(); + else + return FilteredInstructions.size() + 1; +} + +////////////////////////////////// +// // +// Filterchooser Implementation // +// // +////////////////////////////////// + +// Emit the top level typedef and decodeInstruction() function. +void FilterChooser::emitTop(raw_ostream &o, unsigned Indentation) { + switch (BIT_WIDTH) { + case 8: + o.indent(Indentation) << "typedef uint8_t field_t;\n"; + break; + case 16: + o.indent(Indentation) << "typedef uint16_t field_t;\n"; + break; + case 32: + o.indent(Indentation) << "typedef uint32_t field_t;\n"; + break; + case 64: + o.indent(Indentation) << "typedef uint64_t field_t;\n"; + break; + default: + assert(0 && "Unexpected instruction size!"); + } + + o << '\n'; + + o.indent(Indentation) << "static field_t " << + "fieldFromInstruction(field_t insn, unsigned startBit, unsigned numBits)\n"; + + o.indent(Indentation) << "{\n"; + + ++Indentation; ++Indentation; + o.indent(Indentation) << "assert(startBit + numBits <= " << BIT_WIDTH + << " && \"Instruction field out of bounds!\");\n"; + o << '\n'; + o.indent(Indentation) << "field_t fieldMask;\n"; + o << '\n'; + o.indent(Indentation) << "if (numBits == " << BIT_WIDTH << ")\n"; + + ++Indentation; ++Indentation; + o.indent(Indentation) << "fieldMask = (field_t)-1;\n"; + --Indentation; --Indentation; + + o.indent(Indentation) << "else\n"; + + ++Indentation; ++Indentation; + o.indent(Indentation) << "fieldMask = ((1 << numBits) - 1) << startBit;\n"; + --Indentation; --Indentation; + + o << '\n'; + o.indent(Indentation) << "return (insn & fieldMask) >> startBit;\n"; + --Indentation; --Indentation; + + o.indent(Indentation) << "}\n"; + + o << '\n'; + + o.indent(Indentation) << + "static bool decodeInstruction(MCInst &MI, field_t insn) {\n"; + o.indent(Indentation) << " unsigned tmp = 0;\n"; + + ++Indentation; ++Indentation; + // Emits code to decode the instructions. + emit(o, Indentation); + + o << '\n'; + o.indent(Indentation) << "return false;\n"; + --Indentation; --Indentation; + + o.indent(Indentation) << "}\n"; + + o << '\n'; +} + +// Populates the field of the insn given the start position and the number of +// consecutive bits to scan for. +// +// Returns false if and on the first uninitialized bit value encountered. +// Returns true, otherwise. +bool FilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn, + unsigned StartBit, unsigned NumBits) const { + Field = 0; + + for (unsigned i = 0; i < NumBits; ++i) { + if (Insn[StartBit + i] == BIT_UNSET) + return false; + + if (Insn[StartBit + i] == BIT_TRUE) + Field = Field | (1ULL << i); + } + + return true; +} + +/// dumpFilterArray - dumpFilterArray prints out debugging info for the given +/// filter array as a series of chars. +void FilterChooser::dumpFilterArray(raw_ostream &o, + bit_value_t (&filter)[BIT_WIDTH]) { + unsigned bitIndex; + + for (bitIndex = BIT_WIDTH; bitIndex > 0; bitIndex--) { + switch (filter[bitIndex - 1]) { + case BIT_UNFILTERED: + o << "."; + break; + case BIT_UNSET: + o << "_"; + break; + case BIT_TRUE: + o << "1"; + break; + case BIT_FALSE: + o << "0"; + break; + } + } +} + +/// dumpStack - dumpStack traverses the filter chooser chain and calls +/// dumpFilterArray on each filter chooser up to the top level one. +void FilterChooser::dumpStack(raw_ostream &o, const char *prefix) { + FilterChooser *current = this; + + while (current) { + o << prefix; + dumpFilterArray(o, current->FilterBitValues); + o << '\n'; + current = current->Parent; + } +} + +// Called from Filter::recurse() when singleton exists. For debug purpose. +void FilterChooser::SingletonExists(unsigned Opc) { + insn_t Insn0; + insnWithID(Insn0, Opc); + + errs() << "Singleton exists: " << nameWithID(Opc) + << " with its decoding dominating "; + for (unsigned i = 0; i < Opcodes.size(); ++i) { + if (Opcodes[i] == Opc) continue; + errs() << nameWithID(Opcodes[i]) << ' '; + } + errs() << '\n'; + + dumpStack(errs(), "\t\t"); + for (unsigned i = 0; i < Opcodes.size(); i++) { + const std::string &Name = nameWithID(Opcodes[i]); + + errs() << '\t' << Name << " "; + dumpBits(errs(), + getBitsField(*AllInstructions[Opcodes[i]]->TheDef, "Inst")); + errs() << '\n'; + } +} + +// Calculates the island(s) needed to decode the instruction. +// This returns a list of undecoded bits of an instructions, for example, +// Inst{20} = 1 && Inst{3-0} == 0b1111 represents two islands of yet-to-be +// decoded bits in order to verify that the instruction matches the Opcode. +unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits, + std::vector<unsigned> &EndBits, std::vector<uint64_t> &FieldVals, + insn_t &Insn) { + unsigned Num, BitNo; + Num = BitNo = 0; + + uint64_t FieldVal = 0; + + // 0: Init + // 1: Water (the bit value does not affect decoding) + // 2: Island (well-known bit value needed for decoding) + int State = 0; + int Val = -1; + + for (unsigned i = 0; i < BIT_WIDTH; ++i) { + Val = Value(Insn[i]); + bool Filtered = PositionFiltered(i); + switch (State) { + default: + assert(0 && "Unreachable code!"); + break; + case 0: + case 1: + if (Filtered || Val == -1) + State = 1; // Still in Water + else { + State = 2; // Into the Island + BitNo = 0; + StartBits.push_back(i); + FieldVal = Val; + } + break; + case 2: + if (Filtered || Val == -1) { + State = 1; // Into the Water + EndBits.push_back(i - 1); + FieldVals.push_back(FieldVal); + ++Num; + } else { + State = 2; // Still in Island + ++BitNo; + FieldVal = FieldVal | Val << BitNo; + } + break; + } + } + // If we are still in Island after the loop, do some housekeeping. + if (State == 2) { + EndBits.push_back(BIT_WIDTH - 1); + FieldVals.push_back(FieldVal); + ++Num; + } + + assert(StartBits.size() == Num && EndBits.size() == Num && + FieldVals.size() == Num); + return Num; +} + +// Emits code to decode the singleton. Return true if we have matched all the +// well-known bits. +bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, + unsigned Opc) { + std::vector<unsigned> StartBits; + std::vector<unsigned> EndBits; + std::vector<uint64_t> FieldVals; + insn_t Insn; + insnWithID(Insn, Opc); + + // Look for islands of undecoded bits of the singleton. + getIslands(StartBits, EndBits, FieldVals, Insn); + + unsigned Size = StartBits.size(); + unsigned I, NumBits; + + // If we have matched all the well-known bits, just issue a return. + if (Size == 0) { + o.indent(Indentation) << "{\n"; + o.indent(Indentation) << " MI.setOpcode(" << Opc << ");\n"; + std::vector<OperandInfo>& InsnOperands = Operands[Opc]; + for (std::vector<OperandInfo>::iterator + I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) { + // If a custom instruction decoder was specified, use that. + if (I->FieldBase == ~0U && I->FieldLength == ~0U) { + o.indent(Indentation) << " " << I->Decoder << "(MI, insn);\n"; + break; + } + + o.indent(Indentation) + << " tmp = fieldFromInstruction(insn, " << I->FieldBase + << ", " << I->FieldLength << ");\n"; + if (I->Decoder != "") { + o.indent(Indentation) << " " << I->Decoder << "(MI, tmp);\n"; + } else { + o.indent(Indentation) + << " MI.addOperand(MCOperand::CreateImm(tmp));\n"; + } + } + + o.indent(Indentation) << " return true; // " << nameWithID(Opc) + << '\n'; + o.indent(Indentation) << "}\n"; + return true; + } + + // Otherwise, there are more decodings to be done! + + // Emit code to match the island(s) for the singleton. + o.indent(Indentation) << "// Check "; + + for (I = Size; I != 0; --I) { + o << "Inst{" << EndBits[I-1] << '-' << StartBits[I-1] << "} "; + if (I > 1) + o << "&& "; + else + o << "for singleton decoding...\n"; + } + + o.indent(Indentation) << "if ("; + + for (I = Size; I != 0; --I) { + NumBits = EndBits[I-1] - StartBits[I-1] + 1; + o << "fieldFromInstruction(insn, " << StartBits[I-1] << ", " << NumBits + << ") == " << FieldVals[I-1]; + if (I > 1) + o << " && "; + else + o << ") {\n"; + } + o.indent(Indentation) << " MI.setOpcode(" << Opc << ");\n"; + std::vector<OperandInfo>& InsnOperands = Operands[Opc]; + for (std::vector<OperandInfo>::iterator + I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) { + // If a custom instruction decoder was specified, use that. + if (I->FieldBase == ~0U && I->FieldLength == ~0U) { + o.indent(Indentation) << " " << I->Decoder << "(MI, insn);\n"; + break; + } + + o.indent(Indentation) + << " tmp = fieldFromInstruction(insn, " << I->FieldBase + << ", " << I->FieldLength << ");\n"; + if (I->Decoder != "") { + o.indent(Indentation) << " " << I->Decoder << "(MI, tmp);\n"; + } else { + o.indent(Indentation) + << " MI.addOperand(MCOperand::CreateImm(tmp));\n"; + } + } + o.indent(Indentation) << " return true; // " << nameWithID(Opc) + << '\n'; + o.indent(Indentation) << "}\n"; + + return false; +} + +// Emits code to decode the singleton, and then to decode the rest. +void FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, + Filter &Best) { + + unsigned Opc = Best.getSingletonOpc(); + + emitSingletonDecoder(o, Indentation, Opc); + + // Emit code for the rest. + o.indent(Indentation) << "else\n"; + + Indentation += 2; + Best.getVariableFC().emit(o, Indentation); + Indentation -= 2; +} + +// Assign a single filter and run with it. Top level API client can initialize +// with a single filter to start the filtering process. +void FilterChooser::runSingleFilter(FilterChooser &owner, unsigned startBit, + unsigned numBit, bool mixed) { + Filters.clear(); + Filter F(*this, startBit, numBit, true); + Filters.push_back(F); + BestIndex = 0; // Sole Filter instance to choose from. + bestFilter().recurse(); +} + +// reportRegion is a helper function for filterProcessor to mark a region as +// eligible for use as a filter region. +void FilterChooser::reportRegion(bitAttr_t RA, unsigned StartBit, + unsigned BitIndex, bool AllowMixed) { + if (RA == ATTR_MIXED && AllowMixed) + Filters.push_back(Filter(*this, StartBit, BitIndex - StartBit, true)); + else if (RA == ATTR_ALL_SET && !AllowMixed) + Filters.push_back(Filter(*this, StartBit, BitIndex - StartBit, false)); +} + +// FilterProcessor scans the well-known encoding bits of the instructions and +// builds up a list of candidate filters. It chooses the best filter and +// recursively descends down the decoding tree. +bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { + Filters.clear(); + BestIndex = -1; + unsigned numInstructions = Opcodes.size(); + + assert(numInstructions && "Filter created with no instructions"); + + // No further filtering is necessary. + if (numInstructions == 1) + return true; + + // Heuristics. See also doFilter()'s "Heuristics" comment when num of + // instructions is 3. + if (AllowMixed && !Greedy) { + assert(numInstructions == 3); + + for (unsigned i = 0; i < Opcodes.size(); ++i) { + std::vector<unsigned> StartBits; + std::vector<unsigned> EndBits; + std::vector<uint64_t> FieldVals; + insn_t Insn; + + insnWithID(Insn, Opcodes[i]); + + // Look for islands of undecoded bits of any instruction. + if (getIslands(StartBits, EndBits, FieldVals, Insn) > 0) { + // Found an instruction with island(s). Now just assign a filter. + runSingleFilter(*this, StartBits[0], EndBits[0] - StartBits[0] + 1, + true); + return true; + } + } + } + + unsigned BitIndex, InsnIndex; + + // We maintain BIT_WIDTH copies of the bitAttrs automaton. + // The automaton consumes the corresponding bit from each + // instruction. + // + // Input symbols: 0, 1, and _ (unset). + // States: NONE, FILTERED, ALL_SET, ALL_UNSET, and MIXED. + // Initial state: NONE. + // + // (NONE) ------- [01] -> (ALL_SET) + // (NONE) ------- _ ----> (ALL_UNSET) + // (ALL_SET) ---- [01] -> (ALL_SET) + // (ALL_SET) ---- _ ----> (MIXED) + // (ALL_UNSET) -- [01] -> (MIXED) + // (ALL_UNSET) -- _ ----> (ALL_UNSET) + // (MIXED) ------ . ----> (MIXED) + // (FILTERED)---- . ----> (FILTERED) + + bitAttr_t bitAttrs[BIT_WIDTH]; + + // FILTERED bit positions provide no entropy and are not worthy of pursuing. + // Filter::recurse() set either BIT_TRUE or BIT_FALSE for each position. + for (BitIndex = 0; BitIndex < BIT_WIDTH; ++BitIndex) + if (FilterBitValues[BitIndex] == BIT_TRUE || + FilterBitValues[BitIndex] == BIT_FALSE) + bitAttrs[BitIndex] = ATTR_FILTERED; + else + bitAttrs[BitIndex] = ATTR_NONE; + + for (InsnIndex = 0; InsnIndex < numInstructions; ++InsnIndex) { + insn_t insn; + + insnWithID(insn, Opcodes[InsnIndex]); + + for (BitIndex = 0; BitIndex < BIT_WIDTH; ++BitIndex) { + switch (bitAttrs[BitIndex]) { + case ATTR_NONE: + if (insn[BitIndex] == BIT_UNSET) + bitAttrs[BitIndex] = ATTR_ALL_UNSET; + else + bitAttrs[BitIndex] = ATTR_ALL_SET; + break; + case ATTR_ALL_SET: + if (insn[BitIndex] == BIT_UNSET) + bitAttrs[BitIndex] = ATTR_MIXED; + break; + case ATTR_ALL_UNSET: + if (insn[BitIndex] != BIT_UNSET) + bitAttrs[BitIndex] = ATTR_MIXED; + break; + case ATTR_MIXED: + case ATTR_FILTERED: + break; + } + } + } + + // The regionAttr automaton consumes the bitAttrs automatons' state, + // lowest-to-highest. + // + // Input symbols: F(iltered), (all_)S(et), (all_)U(nset), M(ixed) + // States: NONE, ALL_SET, MIXED + // Initial state: NONE + // + // (NONE) ----- F --> (NONE) + // (NONE) ----- S --> (ALL_SET) ; and set region start + // (NONE) ----- U --> (NONE) + // (NONE) ----- M --> (MIXED) ; and set region start + // (ALL_SET) -- F --> (NONE) ; and report an ALL_SET region + // (ALL_SET) -- S --> (ALL_SET) + // (ALL_SET) -- U --> (NONE) ; and report an ALL_SET region + // (ALL_SET) -- M --> (MIXED) ; and report an ALL_SET region + // (MIXED) ---- F --> (NONE) ; and report a MIXED region + // (MIXED) ---- S --> (ALL_SET) ; and report a MIXED region + // (MIXED) ---- U --> (NONE) ; and report a MIXED region + // (MIXED) ---- M --> (MIXED) + + bitAttr_t RA = ATTR_NONE; + unsigned StartBit = 0; + + for (BitIndex = 0; BitIndex < BIT_WIDTH; BitIndex++) { + bitAttr_t bitAttr = bitAttrs[BitIndex]; + + assert(bitAttr != ATTR_NONE && "Bit without attributes"); + + switch (RA) { + case ATTR_NONE: + switch (bitAttr) { + case ATTR_FILTERED: + break; + case ATTR_ALL_SET: + StartBit = BitIndex; + RA = ATTR_ALL_SET; + break; + case ATTR_ALL_UNSET: + break; + case ATTR_MIXED: + StartBit = BitIndex; + RA = ATTR_MIXED; + break; + default: + assert(0 && "Unexpected bitAttr!"); + } + break; + case ATTR_ALL_SET: + switch (bitAttr) { + case ATTR_FILTERED: + reportRegion(RA, StartBit, BitIndex, AllowMixed); + RA = ATTR_NONE; + break; + case ATTR_ALL_SET: + break; + case ATTR_ALL_UNSET: + reportRegion(RA, StartBit, BitIndex, AllowMixed); + RA = ATTR_NONE; + break; + case ATTR_MIXED: + reportRegion(RA, StartBit, BitIndex, AllowMixed); + StartBit = BitIndex; + RA = ATTR_MIXED; + break; + default: + assert(0 && "Unexpected bitAttr!"); + } + break; + case ATTR_MIXED: + switch (bitAttr) { + case ATTR_FILTERED: + reportRegion(RA, StartBit, BitIndex, AllowMixed); + StartBit = BitIndex; + RA = ATTR_NONE; + break; + case ATTR_ALL_SET: + reportRegion(RA, StartBit, BitIndex, AllowMixed); + StartBit = BitIndex; + RA = ATTR_ALL_SET; + break; + case ATTR_ALL_UNSET: + reportRegion(RA, StartBit, BitIndex, AllowMixed); + RA = ATTR_NONE; + break; + case ATTR_MIXED: + break; + default: + assert(0 && "Unexpected bitAttr!"); + } + break; + case ATTR_ALL_UNSET: + assert(0 && "regionAttr state machine has no ATTR_UNSET state"); + case ATTR_FILTERED: + assert(0 && "regionAttr state machine has no ATTR_FILTERED state"); + } + } + + // At the end, if we're still in ALL_SET or MIXED states, report a region + switch (RA) { + case ATTR_NONE: + break; + case ATTR_FILTERED: + break; + case ATTR_ALL_SET: + reportRegion(RA, StartBit, BitIndex, AllowMixed); + break; + case ATTR_ALL_UNSET: + break; + case ATTR_MIXED: + reportRegion(RA, StartBit, BitIndex, AllowMixed); + break; + } + + // We have finished with the filter processings. Now it's time to choose + // the best performing filter. + BestIndex = 0; + bool AllUseless = true; + unsigned BestScore = 0; + + for (unsigned i = 0, e = Filters.size(); i != e; ++i) { + unsigned Usefulness = Filters[i].usefulness(); + + if (Usefulness) + AllUseless = false; + + if (Usefulness > BestScore) { + BestIndex = i; + BestScore = Usefulness; + } + } + + if (!AllUseless) + bestFilter().recurse(); + + return !AllUseless; +} // end of FilterChooser::filterProcessor(bool) + +// Decides on the best configuration of filter(s) to use in order to decode +// the instructions. A conflict of instructions may occur, in which case we +// dump the conflict set to the standard error. +void FilterChooser::doFilter() { + unsigned Num = Opcodes.size(); + assert(Num && "FilterChooser created with no instructions"); + + // Try regions of consecutive known bit values first. + if (filterProcessor(false)) + return; + + // Then regions of mixed bits (both known and unitialized bit values allowed). + if (filterProcessor(true)) + return; + + // Heuristics to cope with conflict set {t2CMPrs, t2SUBSrr, t2SUBSrs} where + // no single instruction for the maximum ATTR_MIXED region Inst{14-4} has a + // well-known encoding pattern. In such case, we backtrack and scan for the + // the very first consecutive ATTR_ALL_SET region and assign a filter to it. + if (Num == 3 && filterProcessor(true, false)) + return; + + // If we come to here, the instruction decoding has failed. + // Set the BestIndex to -1 to indicate so. + BestIndex = -1; +} + +// Emits code to decode our share of instructions. Returns true if the +// emitted code causes a return, which occurs if we know how to decode +// the instruction at this level or the instruction is not decodeable. +bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) { + if (Opcodes.size() == 1) + // There is only one instruction in the set, which is great! + // Call emitSingletonDecoder() to see whether there are any remaining + // encodings bits. + return emitSingletonDecoder(o, Indentation, Opcodes[0]); + + // Choose the best filter to do the decodings! + if (BestIndex != -1) { + Filter &Best = bestFilter(); + if (Best.getNumFiltered() == 1) + emitSingletonDecoder(o, Indentation, Best); + else + bestFilter().emit(o, Indentation); + return false; + } + + // We don't know how to decode these instructions! Return 0 and dump the + // conflict set! + o.indent(Indentation) << "return 0;" << " // Conflict set: "; + for (int i = 0, N = Opcodes.size(); i < N; ++i) { + o << nameWithID(Opcodes[i]); + if (i < (N - 1)) + o << ", "; + else + o << '\n'; + } + + // Print out useful conflict information for postmortem analysis. + errs() << "Decoding Conflict:\n"; + + dumpStack(errs(), "\t\t"); + + for (unsigned i = 0; i < Opcodes.size(); i++) { + const std::string &Name = nameWithID(Opcodes[i]); + + errs() << '\t' << Name << " "; + dumpBits(errs(), + getBitsField(*AllInstructions[Opcodes[i]]->TheDef, "Inst")); + errs() << '\n'; + } + + return true; +} + +bool FixedLenDecoderEmitter::populateInstruction(const CodeGenInstruction &CGI, + unsigned Opc){ + const Record &Def = *CGI.TheDef; + // If all the bit positions are not specified; do not decode this instruction. + // We are bound to fail! For proper disassembly, the well-known encoding bits + // of the instruction must be fully specified. + // + // This also removes pseudo instructions from considerations of disassembly, + // which is a better design and less fragile than the name matchings. + BitsInit &Bits = getBitsField(Def, "Inst"); + if (Bits.allInComplete()) return false; + + // Ignore "asm parser only" instructions. + if (Def.getValueAsBit("isAsmParserOnly")) + return false; + + std::vector<OperandInfo> InsnOperands; + + // If the instruction has specified a custom decoding hook, use that instead + // of trying to auto-generate the decoder. + std::string InstDecoder = Def.getValueAsString("DecoderMethod"); + if (InstDecoder != "") { + InsnOperands.push_back(OperandInfo(~0U, ~0U, InstDecoder)); + Operands[Opc] = InsnOperands; + return true; + } + + // Generate a description of the operand of the instruction that we know + // how to decode automatically. + // FIXME: We'll need to have a way to manually override this as needed. + + // Gather the outputs/inputs of the instruction, so we can find their + // positions in the encoding. This assumes for now that they appear in the + // MCInst in the order that they're listed. + std::vector<std::pair<Init*, std::string> > InOutOperands; + DagInit *Out = Def.getValueAsDag("OutOperandList"); + DagInit *In = Def.getValueAsDag("InOperandList"); + for (unsigned i = 0; i < Out->getNumArgs(); ++i) + InOutOperands.push_back(std::make_pair(Out->getArg(i), Out->getArgName(i))); + for (unsigned i = 0; i < In->getNumArgs(); ++i) + InOutOperands.push_back(std::make_pair(In->getArg(i), In->getArgName(i))); + + // For each operand, see if we can figure out where it is encoded. + for (std::vector<std::pair<Init*, std::string> >::iterator + NI = InOutOperands.begin(), NE = InOutOperands.end(); NI != NE; ++NI) { + unsigned PrevBit = ~0; + unsigned Base = ~0; + unsigned PrevPos = ~0; + std::string Decoder = ""; + + for (unsigned bi = 0; bi < Bits.getNumBits(); ++bi) { + VarBitInit *BI = dynamic_cast<VarBitInit*>(Bits.getBit(bi)); + if (!BI) continue; + + VarInit *Var = dynamic_cast<VarInit*>(BI->getVariable()); + assert(Var); + unsigned CurrBit = BI->getBitNum(); + if (Var->getName() != NI->second) continue; + + // Figure out the lowest bit of the value, and the width of the field. + // Deliberately don't try to handle cases where the field is scattered, + // or where not all bits of the the field are explicit. + if (Base == ~0U && PrevBit == ~0U && PrevPos == ~0U) { + if (CurrBit == 0) + Base = bi; + else + continue; + } + + if ((PrevPos != ~0U && bi-1 != PrevPos) || + (CurrBit != ~0U && CurrBit-1 != PrevBit)) { + PrevBit = ~0; + Base = ~0; + PrevPos = ~0; + } + + PrevPos = bi; + PrevBit = CurrBit; + + // At this point, we can locate the field, but we need to know how to + // interpret it. As a first step, require the target to provide callbacks + // for decoding register classes. + // FIXME: This need to be extended to handle instructions with custom + // decoder methods, and operands with (simple) MIOperandInfo's. + TypedInit *TI = dynamic_cast<TypedInit*>(NI->first); + RecordRecTy *Type = dynamic_cast<RecordRecTy*>(TI->getType()); + Record *TypeRecord = Type->getRecord(); + bool isReg = false; + if (TypeRecord->isSubClassOf("RegisterClass")) { + Decoder = "Decode" + Type->getRecord()->getName() + "RegisterClass"; + isReg = true; + } + + RecordVal *DecoderString = TypeRecord->getValue("DecoderMethod"); + StringInit *String = DecoderString ? + dynamic_cast<StringInit*>(DecoderString->getValue()) : + 0; + if (!isReg && String && String->getValue() != "") + Decoder = String->getValue(); + } + + if (Base != ~0U) { + InsnOperands.push_back(OperandInfo(Base, PrevBit+1, Decoder)); + DEBUG(errs() << "ENCODED OPERAND: $" << NI->second << " @ (" + << utostr(Base+PrevBit) << ", " << utostr(Base) << ")\n"); + } + } + + Operands[Opc] = InsnOperands; + + +#if 0 + DEBUG({ + // Dumps the instruction encoding bits. + dumpBits(errs(), Bits); + + errs() << '\n'; + + // Dumps the list of operand info. + for (unsigned i = 0, e = CGI.Operands.size(); i != e; ++i) { + const CGIOperandList::OperandInfo &Info = CGI.Operands[i]; + const std::string &OperandName = Info.Name; + const Record &OperandDef = *Info.Rec; + + errs() << "\t" << OperandName << " (" << OperandDef.getName() << ")\n"; + } + }); +#endif + + return true; +} + +void FixedLenDecoderEmitter::populateInstructions() { + for (unsigned i = 0, e = NumberedInstructions.size(); i < e; ++i) { + Record *R = NumberedInstructions[i]->TheDef; + if (R->getValueAsString("Namespace") == "TargetOpcode") + continue; + + if (populateInstruction(*NumberedInstructions[i], i)) + Opcodes.push_back(i); + } +} + +// Emits disassembler code for instruction decoding. +void FixedLenDecoderEmitter::run(raw_ostream &o) +{ + o << "#include \"llvm/MC/MCInst.h\"\n"; + o << "#include \"llvm/Support/DataTypes.h\"\n"; + o << "#include <assert.h>\n"; + o << '\n'; + o << "namespace llvm {\n\n"; + + NumberedInstructions = Target.getInstructionsByEnumValue(); + populateInstructions(); + FilterChooser FC(NumberedInstructions, Opcodes, Operands); + FC.emitTop(o, 0); + + o << "\n} // End llvm namespace \n"; +} diff --git a/utils/TableGen/FixedLenDecoderEmitter.h b/utils/TableGen/FixedLenDecoderEmitter.h new file mode 100644 index 0000000..d46a495 --- /dev/null +++ b/utils/TableGen/FixedLenDecoderEmitter.h @@ -0,0 +1,56 @@ +//===------------ FixedLenDecoderEmitter.h - Decoder Generator --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// It contains the tablegen backend that emits the decoder functions for +// targets with fixed length instruction set. +// +//===----------------------------------------------------------------------===// + +#ifndef FixedLenDECODEREMITTER_H +#define FixedLenDECODEREMITTER_H + +#include "CodeGenTarget.h" +#include "TableGenBackend.h" + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +struct OperandInfo { + unsigned FieldBase; + unsigned FieldLength; + std::string Decoder; + + OperandInfo(unsigned FB, unsigned FL, std::string D) + : FieldBase(FB), FieldLength(FL), Decoder(D) { } +}; + +class FixedLenDecoderEmitter : public TableGenBackend { +public: + FixedLenDecoderEmitter(RecordKeeper &R) : + Records(R), Target(R), + NumberedInstructions(Target.getInstructionsByEnumValue()) {} + + // run - Output the code emitter + void run(raw_ostream &o); + +private: + RecordKeeper &Records; + CodeGenTarget Target; + std::vector<const CodeGenInstruction*> NumberedInstructions; + std::vector<unsigned> Opcodes; + std::map<unsigned, std::vector<OperandInfo> > Operands; + + bool populateInstruction(const CodeGenInstruction &CGI, unsigned Opc); + void populateInstructions(); +}; + +} // end llvm namespace + +#endif diff --git a/utils/TableGen/InstrEnumEmitter.cpp b/utils/TableGen/InstrEnumEmitter.cpp index 47a8474..aa59689 100644 --- a/utils/TableGen/InstrEnumEmitter.cpp +++ b/utils/TableGen/InstrEnumEmitter.cpp @@ -23,7 +23,7 @@ void InstrEnumEmitter::run(raw_ostream &OS) { EmitSourceFileHeader("Target Instruction Enum Values", OS); OS << "namespace llvm {\n\n"; - CodeGenTarget Target; + CodeGenTarget Target(Records); // We must emit the PHI opcode first... std::string Namespace = Target.getInstNamespace(); diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 4d3aa5e..2b684be 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -60,23 +60,23 @@ std::vector<std::string> InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { std::vector<std::string> Result; - for (unsigned i = 0, e = Inst.OperandList.size(); i != e; ++i) { + for (unsigned i = 0, e = Inst.Operands.size(); i != e; ++i) { // Handle aggregate operands and normal operands the same way by expanding // either case into a list of operands for this op. - std::vector<CodeGenInstruction::OperandInfo> OperandList; + std::vector<CGIOperandList::OperandInfo> OperandList; // This might be a multiple operand thing. Targets like X86 have // registers in their multi-operand operands. It may also be an anonymous // operand, which has a single operand, but no declared class for the // operand. - DagInit *MIOI = Inst.OperandList[i].MIOperandInfo; + DagInit *MIOI = Inst.Operands[i].MIOperandInfo; if (!MIOI || MIOI->getNumArgs() == 0) { // Single, anonymous, operand. - OperandList.push_back(Inst.OperandList[i]); + OperandList.push_back(Inst.Operands[i]); } else { - for (unsigned j = 0, e = Inst.OperandList[i].MINumOperands; j != e; ++j) { - OperandList.push_back(Inst.OperandList[i]); + for (unsigned j = 0, e = Inst.Operands[i].MINumOperands; j != e; ++j) { + OperandList.push_back(Inst.Operands[i]); Record *OpR = dynamic_cast<DefInit*>(MIOI->getArg(j))->getDef(); OperandList.back().Rec = OpR; @@ -104,19 +104,19 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { // Predicate operands. Check to see if the original unexpanded operand // was of type PredicateOperand. - if (Inst.OperandList[i].Rec->isSubClassOf("PredicateOperand")) + if (Inst.Operands[i].Rec->isSubClassOf("PredicateOperand")) Res += "|(1<<TOI::Predicate)"; // Optional def operands. Check to see if the original unexpanded operand // was of type OptionalDefOperand. - if (Inst.OperandList[i].Rec->isSubClassOf("OptionalDefOperand")) + if (Inst.Operands[i].Rec->isSubClassOf("OptionalDefOperand")) Res += "|(1<<TOI::OptionalDef)"; // Fill in constraint info. Res += ", "; - const CodeGenInstruction::ConstraintInfo &Constraint = - Inst.OperandList[i].Constraints[j]; + const CGIOperandList::ConstraintInfo &Constraint = + Inst.Operands[i].Constraints[j]; if (Constraint.isNone()) Res += "0"; else if (Constraint.isEarlyClobber()) @@ -256,14 +256,14 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, const OperandInfoMapTy &OpInfo, raw_ostream &OS) { int MinOperands = 0; - if (!Inst.OperandList.empty()) + if (!Inst.Operands.size() == 0) // Each logical operand can be multiple MI operands. - MinOperands = Inst.OperandList.back().MIOperandNo + - Inst.OperandList.back().MINumOperands; + MinOperands = Inst.Operands.back().MIOperandNo + + Inst.Operands.back().MINumOperands; OS << " { "; OS << Num << ",\t" << MinOperands << ",\t" - << Inst.NumDefs << ",\t" << getItinClassNumber(Inst.TheDef) + << Inst.Operands.NumDefs << ",\t" << getItinClassNumber(Inst.TheDef) << ",\t\"" << Inst.TheDef->getName() << "\", 0"; // Emit all of the target indepedent flags... @@ -271,6 +271,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, if (Inst.isBranch) OS << "|(1<<TID::Branch)"; if (Inst.isIndirectBranch) OS << "|(1<<TID::IndirectBranch)"; if (Inst.isCompare) OS << "|(1<<TID::Compare)"; + if (Inst.isMoveImm) OS << "|(1<<TID::MoveImm)"; if (Inst.isBarrier) OS << "|(1<<TID::Barrier)"; if (Inst.hasDelaySlot) OS << "|(1<<TID::DelaySlot)"; if (Inst.isCall) OS << "|(1<<TID::Call)"; @@ -283,9 +284,9 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, if (Inst.isTerminator) OS << "|(1<<TID::Terminator)"; if (Inst.isReMaterializable) OS << "|(1<<TID::Rematerializable)"; if (Inst.isNotDuplicable) OS << "|(1<<TID::NotDuplicable)"; - if (Inst.hasOptionalDef) OS << "|(1<<TID::HasOptionalDef)"; + if (Inst.Operands.hasOptionalDef) OS << "|(1<<TID::HasOptionalDef)"; if (Inst.usesCustomInserter) OS << "|(1<<TID::UsesCustomInserter)"; - if (Inst.isVariadic) OS << "|(1<<TID::Variadic)"; + if (Inst.Operands.isVariadic)OS << "|(1<<TID::Variadic)"; if (Inst.hasSideEffects) OS << "|(1<<TID::UnmodeledSideEffects)"; if (Inst.isAsCheapAsAMove) OS << "|(1<<TID::CheapAsAMove)"; if (Inst.hasExtraSrcRegAllocReq) OS << "|(1<<TID::ExtraSrcRegAllocReq)"; diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index ba30d97..08f6728 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -14,6 +14,7 @@ #include "CodeGenTarget.h" #include "IntrinsicEmitter.h" #include "Record.h" +#include "StringMatcher.h" #include "llvm/ADT/StringExtras.h" #include <algorithm> using namespace llvm; @@ -67,16 +68,19 @@ void IntrinsicEmitter::run(raw_ostream &OS) { void IntrinsicEmitter::EmitPrefix(raw_ostream &OS) { OS << "// VisualStudio defines setjmp as _setjmp\n" - "#if defined(_MSC_VER) && defined(setjmp)\n" - "#define setjmp_undefined_for_visual_studio\n" - "#undef setjmp\n" + "#if defined(_MSC_VER) && defined(setjmp) && \\\n" + " !defined(setjmp_undefined_for_msvc)\n" + "# pragma push_macro(\"setjmp\")\n" + "# undef setjmp\n" + "# define setjmp_undefined_for_msvc\n" "#endif\n\n"; } void IntrinsicEmitter::EmitSuffix(raw_ostream &OS) { - OS << "#if defined(_MSC_VER) && defined(setjmp_undefined_for_visual_studio)\n" + OS << "#if defined(_MSC_VER) && defined(setjmp_undefined_for_msvc)\n" "// let's return it to _setjmp state\n" - "#define setjmp _setjmp\n" + "# pragma pop_macro(\"setjmp\")\n" + "# undef setjmp_undefined_for_msvc\n" "#endif\n\n"; } @@ -96,37 +100,48 @@ void IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints, void IntrinsicEmitter:: EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { - // Build a function name -> intrinsic name mapping. - std::map<std::string, unsigned> IntMapping; + // Build a 'first character of function name' -> intrinsic # mapping. + std::map<char, std::vector<unsigned> > IntMapping; for (unsigned i = 0, e = Ints.size(); i != e; ++i) - IntMapping[Ints[i].Name] = i; - + IntMapping[Ints[i].Name[5]].push_back(i); + OS << "// Function name -> enum value recognizer code.\n"; OS << "#ifdef GET_FUNCTION_RECOGNIZER\n"; - OS << " switch (Name[5]) {\n"; - OS << " default:\n"; - // Emit the intrinsics in sorted order. - char LastChar = 0; - for (std::map<std::string, unsigned>::iterator I = IntMapping.begin(), + OS << " StringRef NameR(Name+6, Len-6); // Skip over 'llvm.'\n"; + OS << " switch (Name[5]) { // Dispatch on first letter.\n"; + OS << " default: break;\n"; + // Emit the intrinsic matching stuff by first letter. + for (std::map<char, std::vector<unsigned> >::iterator I = IntMapping.begin(), E = IntMapping.end(); I != E; ++I) { - if (I->first[5] != LastChar) { - LastChar = I->first[5]; - OS << " break;\n"; - OS << " case '" << LastChar << "':\n"; + OS << " case '" << I->first << "':\n"; + std::vector<unsigned> &IntList = I->second; + + // Emit all the overloaded intrinsics first, build a table of the + // non-overloaded ones. + std::vector<StringMatcher::StringPair> MatchTable; + + for (unsigned i = 0, e = IntList.size(); i != e; ++i) { + unsigned IntNo = IntList[i]; + std::string Result = "return " + TargetPrefix + "Intrinsic::" + + Ints[IntNo].EnumName + ";"; + + if (!Ints[IntNo].isOverloaded) { + MatchTable.push_back(std::make_pair(Ints[IntNo].Name.substr(6),Result)); + continue; + } + + // For overloaded intrinsics, only the prefix needs to match + std::string TheStr = Ints[IntNo].Name.substr(6); + TheStr += '.'; // Require "bswap." instead of bswap. + OS << " if (NameR.startswith(\"" << TheStr << "\")) " + << Result << '\n'; } - // For overloaded intrinsics, only the prefix needs to match - if (Ints[I->second].isOverloaded) - OS << " if (Len > " << I->first.size() - << " && !memcmp(Name, \"" << I->first << ".\", " - << (I->first.size() + 1) << ")) return " << TargetPrefix << "Intrinsic::" - << Ints[I->second].EnumName << ";\n"; - else - OS << " if (Len == " << I->first.size() - << " && !memcmp(Name, \"" << I->first << "\", " - << I->first.size() << ")) return " << TargetPrefix << "Intrinsic::" - << Ints[I->second].EnumName << ";\n"; + // Emit the matcher logic for the fixed length strings. + StringMatcher("NameR", MatchTable, OS).Emit(1); + OS << " break; // end of '" << I->first << "' case.\n"; } + OS << " }\n"; OS << "#endif\n\n"; } @@ -180,6 +195,8 @@ static void EmitTypeForValueType(raw_ostream &OS, MVT::SimpleValueType VT) { OS << "Type::getVoidTy(Context)"; } else if (VT == MVT::Metadata) { OS << "Type::getMetadataTy(Context)"; + } else if (VT == MVT::x86mmx) { + OS << "Type::getX86_MMXTy(Context)"; } else { assert(false && "Unsupported ValueType!"); } @@ -556,11 +573,13 @@ EmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){ OS << " return DoesNotAccessMemory;\n"; break; case CodeGenIntrinsic::ReadArgMem: + OS << " return OnlyReadsArgumentPointees;\n"; + break; case CodeGenIntrinsic::ReadMem: OS << " return OnlyReadsMemory;\n"; break; case CodeGenIntrinsic::ReadWriteArgMem: - OS << " return AccessesArguments;\n"; + OS << " return OnlyAccessesArgumentPointees;\n"; break; } } @@ -584,112 +603,22 @@ EmitGCCBuiltinList(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){ OS << "#endif\n\n"; } -/// EmitBuiltinComparisons - Emit comparisons to determine whether the specified -/// sorted range of builtin names is equal to the current builtin. This breaks -/// it down into a simple tree. -/// -/// At this point, we know that all the builtins in the range have the same name -/// for the first 'CharStart' characters. Only the end of the name needs to be -/// discriminated. -typedef std::map<std::string, std::string>::const_iterator StrMapIterator; -static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End, - unsigned CharStart, unsigned Indent, - std::string TargetPrefix, raw_ostream &OS) { - if (Start == End) return; // empty range. - - // Determine what, if anything, is the same about all these strings. - std::string CommonString = Start->first; - unsigned NumInRange = 0; - for (StrMapIterator I = Start; I != End; ++I, ++NumInRange) { - // Find the first character that doesn't match. - const std::string &ThisStr = I->first; - unsigned NonMatchChar = CharStart; - while (NonMatchChar < CommonString.size() && - NonMatchChar < ThisStr.size() && - CommonString[NonMatchChar] == ThisStr[NonMatchChar]) - ++NonMatchChar; - // Truncate off pieces that don't match. - CommonString.resize(NonMatchChar); - } - - // Just compare the rest of the string. - if (NumInRange == 1) { - if (CharStart != CommonString.size()) { - OS << std::string(Indent*2, ' ') << "if (!memcmp(BuiltinName"; - if (CharStart) OS << "+" << CharStart; - OS << ", \"" << (CommonString.c_str()+CharStart) << "\", "; - OS << CommonString.size() - CharStart << "))\n"; - ++Indent; - } - OS << std::string(Indent*2, ' ') << "IntrinsicID = " << TargetPrefix - << "Intrinsic::"; - OS << Start->second << ";\n"; - return; - } - - // At this point, we potentially have a common prefix for these builtins, emit - // a check for this common prefix. - if (CommonString.size() != CharStart) { - OS << std::string(Indent*2, ' ') << "if (!memcmp(BuiltinName"; - if (CharStart) OS << "+" << CharStart; - OS << ", \"" << (CommonString.c_str()+CharStart) << "\", "; - OS << CommonString.size()-CharStart << ")) {\n"; - - EmitBuiltinComparisons(Start, End, CommonString.size(), Indent+1, - TargetPrefix, OS); - OS << std::string(Indent*2, ' ') << "}\n"; - return; - } - - // Output a switch on the character that differs across the set. - OS << std::string(Indent*2, ' ') << "switch (BuiltinName[" << CharStart - << "]) {"; - if (CharStart) - OS << " // \"" << std::string(Start->first.begin(), - Start->first.begin()+CharStart) << "\""; - OS << "\n"; - - for (StrMapIterator I = Start; I != End; ) { - char ThisChar = I->first[CharStart]; - OS << std::string(Indent*2, ' ') << "case '" << ThisChar << "':\n"; - // Figure out the range that has this common character. - StrMapIterator NextChar = I; - for (++NextChar; NextChar != End && NextChar->first[CharStart] == ThisChar; - ++NextChar) - /*empty*/; - EmitBuiltinComparisons(I, NextChar, CharStart+1, Indent+1, TargetPrefix,OS); - OS << std::string(Indent*2, ' ') << " break;\n"; - I = NextChar; - } - OS << std::string(Indent*2, ' ') << "}\n"; -} - /// EmitTargetBuiltins - All of the builtins in the specified map are for the /// same target, and we already checked it. static void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM, const std::string &TargetPrefix, raw_ostream &OS) { - // Rearrange the builtins by length. - std::vector<std::map<std::string, std::string> > BuiltinsByLen; - BuiltinsByLen.reserve(100); - for (StrMapIterator I = BIM.begin(), E = BIM.end(); I != E; ++I) { - if (I->first.size() >= BuiltinsByLen.size()) - BuiltinsByLen.resize(I->first.size()+1); - BuiltinsByLen[I->first.size()].insert(*I); - } + std::vector<StringMatcher::StringPair> Results; - // Now that we have all the builtins by their length, emit a switch stmt. - OS << " switch (strlen(BuiltinName)) {\n"; - OS << " default: break;\n"; - for (unsigned i = 0, e = BuiltinsByLen.size(); i != e; ++i) { - if (BuiltinsByLen[i].empty()) continue; - OS << " case " << i << ":\n"; - EmitBuiltinComparisons(BuiltinsByLen[i].begin(), BuiltinsByLen[i].end(), - 0, 3, TargetPrefix, OS); - OS << " break;\n"; + for (std::map<std::string, std::string>::const_iterator I = BIM.begin(), + E = BIM.end(); I != E; ++I) { + std::string ResultCode = + "return " + TargetPrefix + "Intrinsic::" + I->second + ";"; + Results.push_back(StringMatcher::StringPair(I->first, ResultCode)); } - OS << " }\n"; + + StringMatcher("BuiltinName", Results, OS).Emit(); } @@ -719,24 +648,20 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, if (TargetOnly) { OS << "static " << TargetPrefix << "Intrinsic::ID " << "getIntrinsicForGCCBuiltin(const char " - << "*TargetPrefix, const char *BuiltinName) {\n"; - OS << " " << TargetPrefix << "Intrinsic::ID IntrinsicID = "; + << "*TargetPrefixStr, const char *BuiltinNameStr) {\n"; } else { OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char " - << "*TargetPrefix, const char *BuiltinName) {\n"; - OS << " Intrinsic::ID IntrinsicID = "; + << "*TargetPrefixStr, const char *BuiltinNameStr) {\n"; } - if (TargetOnly) - OS << "(" << TargetPrefix<< "Intrinsic::ID)"; - - OS << "Intrinsic::not_intrinsic;\n"; + OS << " StringRef BuiltinName(BuiltinNameStr);\n"; + OS << " StringRef TargetPrefix(TargetPrefixStr);\n\n"; // Note: this could emit significantly better code if we cared. for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){ OS << " "; if (!I->first.empty()) - OS << "if (!strcmp(TargetPrefix, \"" << I->first << "\")) "; + OS << "if (TargetPrefix == \"" << I->first << "\") "; else OS << "/* Target Independent Builtins */ "; OS << "{\n"; @@ -745,7 +670,10 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, EmitTargetBuiltins(I->second, TargetPrefix, OS); OS << " }\n"; } - OS << " return IntrinsicID;\n"; + OS << " return "; + if (!TargetPrefix.empty()) + OS << "(" << TargetPrefix << "Intrinsic::ID)"; + OS << "Intrinsic::not_intrinsic;\n"; OS << "}\n"; OS << "#endif\n\n"; } diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp index 8b81e14..c40a39d 100644 --- a/utils/TableGen/LLVMCConfigurationEmitter.cpp +++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp @@ -25,6 +25,7 @@ #include <string> #include <typeinfo> + using namespace llvm; namespace { @@ -164,18 +165,6 @@ void CheckedIncrement(I& P, I E, S ErrorString) { throw ErrorString; } -// apply is needed because C++'s syntax doesn't let us construct a function -// object and call it in the same statement. -template<typename F, typename T0> -void apply(F Fun, T0& Arg0) { - return Fun(Arg0); -} - -template<typename F, typename T0, typename T1> -void apply(F Fun, T0& Arg0, T1& Arg1) { - return Fun(Arg0, Arg1); -} - //===----------------------------------------------------------------------===// /// Back-end specific code @@ -779,14 +768,21 @@ public: CheckNumberOfArguments(d, 2); + // Alias option store the aliased option name in the 'Help' field and do not + // have any properties. if (OD.isAlias()) { - // Aliases store the aliased option name in the 'Help' field. OD.Help = InitPtrToString(d.getArg(1)); } else { processOptionProperties(d, OD); } + // Switch options are ZeroOrMore by default. + if (OD.isSwitch()) { + if (!(OD.isOptional() || OD.isOneOrMore() || OD.isRequired())) + OD.setZeroOrMore(); + } + OptDescs_.InsertDescription(OD); } @@ -809,13 +805,12 @@ void CollectOptionDescriptions (const RecordVector& V, OptionDescriptions& OptDescs) { // For every OptionList: - for (RecordVector::const_iterator B = V.begin(), - E = V.end(); B!=E; ++B) { + for (RecordVector::const_iterator B = V.begin(), E = V.end(); B!=E; ++B) + { // Throws an exception if the value does not exist. ListInit* PropList = (*B)->getValueAsListInit("options"); - // For every option description in this list: - // collect the information and + // For every option description in this list: invoke AddOption. std::for_each(PropList->begin(), PropList->end(), AddOption(OptDescs)); } } @@ -833,7 +828,7 @@ struct ToolDescription : public RefCountedBase<ToolDescription> { StrVector InLanguage; std::string InFileOption; std::string OutFileOption; - std::string OutLanguage; + StrVector OutLanguage; std::string OutputSuffix; unsigned Flags; const Init* OnEmpty; @@ -919,31 +914,24 @@ private: toolDesc_.CmdLine = d.getArg(0); } - void onInLanguage (const DagInit& d) { + /// onInOutLanguage - Common implementation of on{In,Out}Language(). + void onInOutLanguage (const DagInit& d, StrVector& OutVec) { CheckNumberOfArguments(d, 1); - Init* arg = d.getArg(0); - // Find out the argument's type. - if (typeid(*arg) == typeid(StringInit)) { - // It's a string. - toolDesc_.InLanguage.push_back(InitPtrToString(arg)); + // Copy strings to the output vector. + for (unsigned i = 0, NumArgs = d.getNumArgs(); i < NumArgs; ++i) { + OutVec.push_back(InitPtrToString(d.getArg(i))); } - else { - // It's a list. - const ListInit& lst = InitPtrToList(arg); - StrVector& out = toolDesc_.InLanguage; - // Copy strings to the output vector. - for (ListInit::const_iterator B = lst.begin(), E = lst.end(); - B != E; ++B) { - out.push_back(InitPtrToString(*B)); - } + // Remove duplicates. + std::sort(OutVec.begin(), OutVec.end()); + StrVector::iterator newE = std::unique(OutVec.begin(), OutVec.end()); + OutVec.erase(newE, OutVec.end()); + } - // Remove duplicates. - std::sort(out.begin(), out.end()); - StrVector::iterator newE = std::unique(out.begin(), out.end()); - out.erase(newE, out.end()); - } + + void onInLanguage (const DagInit& d) { + this->onInOutLanguage(d, toolDesc_.InLanguage); } void onJoin (const DagInit& d) { @@ -952,8 +940,7 @@ private: } void onOutLanguage (const DagInit& d) { - CheckNumberOfArguments(d, 1); - toolDesc_.OutLanguage = InitPtrToString(d.getArg(0)); + this->onInOutLanguage(d, toolDesc_.OutLanguage); } void onOutFileOption (const DagInit& d) { @@ -1062,47 +1049,62 @@ void FilterNotInGraph (const DagVector& EdgeVector, } /// FillInToolToLang - Fills in two tables that map tool names to -/// (input, output) languages. Helper function used by TypecheckGraph(). +/// input & output language names. Helper function used by TypecheckGraph(). void FillInToolToLang (const ToolDescriptions& ToolDescs, StringMap<StringSet<> >& ToolToInLang, - StringMap<std::string>& ToolToOutLang) { + StringMap<StringSet<> >& ToolToOutLang) { for (ToolDescriptions::const_iterator B = ToolDescs.begin(), E = ToolDescs.end(); B != E; ++B) { const ToolDescription& D = *(*B); for (StrVector::const_iterator B = D.InLanguage.begin(), E = D.InLanguage.end(); B != E; ++B) ToolToInLang[D.Name].insert(*B); - ToolToOutLang[D.Name] = D.OutLanguage; + for (StrVector::const_iterator B = D.OutLanguage.begin(), + E = D.OutLanguage.end(); B != E; ++B) + ToolToOutLang[D.Name].insert(*B); } } +/// Intersect - Is set intersection non-empty? +bool Intersect (const StringSet<>& S1, const StringSet<>& S2) { + for (StringSet<>::const_iterator B = S1.begin(), E = S1.end(); B != E; ++B) { + if (S2.count(B->first()) != 0) + return true; + } + return false; +} + /// TypecheckGraph - Check that names for output and input languages /// on all edges do match. void TypecheckGraph (const DagVector& EdgeVector, const ToolDescriptions& ToolDescs) { StringMap<StringSet<> > ToolToInLang; - StringMap<std::string> ToolToOutLang; + StringMap<StringSet<> > ToolToOutLang; FillInToolToLang(ToolDescs, ToolToInLang, ToolToOutLang); - StringMap<std::string>::iterator IAE = ToolToOutLang.end(); - StringMap<StringSet<> >::iterator IBE = ToolToInLang.end(); for (DagVector::const_iterator B = EdgeVector.begin(), E = EdgeVector.end(); B != E; ++B) { const DagInit* Edge = *B; const std::string& NodeA = InitPtrToString(Edge->getArg(0)); const std::string& NodeB = InitPtrToString(Edge->getArg(1)); - StringMap<std::string>::iterator IA = ToolToOutLang.find(NodeA); + StringMap<StringSet<> >::iterator IA = ToolToOutLang.find(NodeA); StringMap<StringSet<> >::iterator IB = ToolToInLang.find(NodeB); + if (NodeB == "root") + throw "Edges back to the root are not allowed!"; + if (NodeA != "root") { - if (IA != IAE && IB != IBE && IB->second.count(IA->second) == 0) + if (IA == ToolToOutLang.end()) + throw NodeA + ": no output language defined!"; + if (IB == ToolToInLang.end()) + throw NodeB + ": no input language defined!"; + + if (!Intersect(IA->second, IB->second)) { throw "Edge " + NodeA + "->" + NodeB + ": output->input language mismatch"; + } } - - if (NodeB == "root") - throw "Edges back to the root are not allowed!"; } } @@ -1178,25 +1180,20 @@ class ExtractOptionNames { if (ActionName == "forward" || ActionName == "forward_as" || ActionName == "forward_value" || ActionName == "forward_transformed_value" || - ActionName == "switch_on" || ActionName == "any_switch_on" || - ActionName == "parameter_equals" || - ActionName == "element_in_list" || ActionName == "not_empty" || - ActionName == "empty") { + ActionName == "parameter_equals" || ActionName == "element_in_list") { CheckNumberOfArguments(Stmt, 1); Init* Arg = Stmt.getArg(0); - if (typeid(*Arg) == typeid(StringInit)) { - const std::string& Name = InitPtrToString(Arg); - OptionNames_.insert(Name); - } - else { - // It's a list. - const ListInit& List = InitPtrToList(Arg); - for (ListInit::const_iterator B = List.begin(), E = List.end(); - B != E; ++B) { - const std::string& Name = InitPtrToString(*B); - OptionNames_.insert(Name); - } + if (typeid(*Arg) == typeid(StringInit)) + OptionNames_.insert(InitPtrToString(Arg)); + } + else if (ActionName == "any_switch_on" || ActionName == "switch_on" || + ActionName == "any_not_empty" || ActionName == "any_empty" || + ActionName == "not_empty" || ActionName == "empty") { + for (unsigned i = 0, NumArgs = Stmt.getNumArgs(); i < NumArgs; ++i) { + Init* Arg = Stmt.getArg(i); + if (typeid(*Arg) == typeid(StringInit)) + OptionNames_.insert(InitPtrToString(Arg)); } } else if (ActionName == "and" || ActionName == "or" || ActionName == "not") { @@ -1211,6 +1208,7 @@ public: {} void operator()(const Init* Statement) { + // Statement is either a dag, or a list of dags. if (typeid(*Statement) == typeid(ListInit)) { const ListInit& DagList = *static_cast<const ListInit*>(Statement); for (ListInit::const_iterator B = DagList.begin(), E = DagList.end(); @@ -1291,24 +1289,20 @@ bool EmitCaseTest0Args(const std::string& TestName, raw_ostream& O) { return false; } -/// EmitListTest - Helper function used by EmitCaseTest1ArgList(). +/// EmitMultipleArgumentTest - Helper function used by +/// EmitCaseTestMultipleArgs() template <typename F> -void EmitListTest(const ListInit& L, const char* LogicOp, - F Callback, raw_ostream& O) +void EmitMultipleArgumentTest(const DagInit& D, const char* LogicOp, + F Callback, raw_ostream& O) { - // This is a lot like EmitLogicalOperationTest, but works on ListInits instead - // of Dags... - bool isFirst = true; - for (ListInit::const_iterator B = L.begin(), E = L.end(); B != E; ++B) { - if (isFirst) - isFirst = false; - else - O << ' ' << LogicOp << ' '; - Callback(InitPtrToString(*B), O); + for (unsigned i = 0, NumArgs = D.getNumArgs(); i < NumArgs; ++i) { + if (i != 0) + O << ' ' << LogicOp << ' '; + Callback(InitPtrToString(D.getArg(i)), O); } } -// Callbacks for use with EmitListTest. +// Callbacks for use with EmitMultipleArgumentTest class EmitSwitchOn { const OptionDescriptions& OptDescs_; @@ -1346,54 +1340,48 @@ public: }; -/// EmitCaseTest1ArgList - Helper function used by EmitCaseTest1Arg(); -bool EmitCaseTest1ArgList(const std::string& TestName, - const DagInit& d, - const OptionDescriptions& OptDescs, - raw_ostream& O) { - const ListInit& L = InitPtrToList(d.getArg(0)); - +/// EmitCaseTestMultipleArgs - Helper function used by EmitCaseTest1Arg() +bool EmitCaseTestMultipleArgs (const std::string& TestName, + const DagInit& d, + const OptionDescriptions& OptDescs, + raw_ostream& O) { if (TestName == "any_switch_on") { - EmitListTest(L, "||", EmitSwitchOn(OptDescs), O); + EmitMultipleArgumentTest(d, "||", EmitSwitchOn(OptDescs), O); return true; } else if (TestName == "switch_on") { - EmitListTest(L, "&&", EmitSwitchOn(OptDescs), O); + EmitMultipleArgumentTest(d, "&&", EmitSwitchOn(OptDescs), O); return true; } else if (TestName == "any_not_empty") { - EmitListTest(L, "||", EmitEmptyTest(true, OptDescs), O); + EmitMultipleArgumentTest(d, "||", EmitEmptyTest(true, OptDescs), O); return true; } else if (TestName == "any_empty") { - EmitListTest(L, "||", EmitEmptyTest(false, OptDescs), O); + EmitMultipleArgumentTest(d, "||", EmitEmptyTest(false, OptDescs), O); return true; } else if (TestName == "not_empty") { - EmitListTest(L, "&&", EmitEmptyTest(true, OptDescs), O); + EmitMultipleArgumentTest(d, "&&", EmitEmptyTest(true, OptDescs), O); return true; } else if (TestName == "empty") { - EmitListTest(L, "&&", EmitEmptyTest(false, OptDescs), O); + EmitMultipleArgumentTest(d, "&&", EmitEmptyTest(false, OptDescs), O); return true; } return false; } -/// EmitCaseTest1ArgStr - Helper function used by EmitCaseTest1Arg(); -bool EmitCaseTest1ArgStr(const std::string& TestName, - const DagInit& d, - const OptionDescriptions& OptDescs, - raw_ostream& O) { - const std::string& OptName = InitPtrToString(d.getArg(0)); +/// EmitCaseTest1Arg - Helper function used by EmitCaseTest1OrMoreArgs() +bool EmitCaseTest1Arg (const std::string& TestName, + const DagInit& d, + const OptionDescriptions& OptDescs, + raw_ostream& O) { + const std::string& Arg = InitPtrToString(d.getArg(0)); - if (TestName == "switch_on") { - apply(EmitSwitchOn(OptDescs), OptName, O); - return true; - } - else if (TestName == "input_languages_contain") { - O << "InLangs.count(\"" << OptName << "\") != 0"; + if (TestName == "input_languages_contain") { + O << "InLangs.count(\"" << Arg << "\") != 0"; return true; } else if (TestName == "in_language") { @@ -1401,28 +1389,22 @@ bool EmitCaseTest1ArgStr(const std::string& TestName, // tools can process several files in different languages simultaneously. // TODO: make this work with Edge::Weight (if possible). - O << "LangMap.GetLanguage(inFile) == \"" << OptName << '\"'; - return true; - } - else if (TestName == "not_empty" || TestName == "empty") { - bool EmitNegate = (TestName == "not_empty"); - apply(EmitEmptyTest(EmitNegate, OptDescs), OptName, O); + O << "LangMap.GetLanguage(inFile) == \"" << Arg << '\"'; return true; } return false; } -/// EmitCaseTest1Arg - Helper function used by EmitCaseConstructHandler(); -bool EmitCaseTest1Arg(const std::string& TestName, - const DagInit& d, - const OptionDescriptions& OptDescs, - raw_ostream& O) { +/// EmitCaseTest1OrMoreArgs - Helper function used by +/// EmitCaseConstructHandler() +bool EmitCaseTest1OrMoreArgs(const std::string& TestName, + const DagInit& d, + const OptionDescriptions& OptDescs, + raw_ostream& O) { CheckNumberOfArguments(d, 1); - if (typeid(*d.getArg(0)) == typeid(ListInit)) - return EmitCaseTest1ArgList(TestName, d, OptDescs, O); - else - return EmitCaseTest1ArgStr(TestName, d, OptDescs, O); + return EmitCaseTest1Arg(TestName, d, OptDescs, O) || + EmitCaseTestMultipleArgs(TestName, d, OptDescs, O); } /// EmitCaseTest2Args - Helper function used by EmitCaseConstructHandler(). @@ -1466,10 +1448,10 @@ void EmitLogicalOperationTest(const DagInit& d, const char* LogicOp, const OptionDescriptions& OptDescs, raw_ostream& O) { O << '('; - for (unsigned j = 0, NumArgs = d.getNumArgs(); j < NumArgs; ++j) { - const DagInit& InnerTest = InitPtrToDag(d.getArg(j)); + for (unsigned i = 0, NumArgs = d.getNumArgs(); i < NumArgs; ++i) { + const DagInit& InnerTest = InitPtrToDag(d.getArg(i)); EmitCaseTest(InnerTest, IndentLevel, OptDescs, O); - if (j != NumArgs - 1) { + if (i != NumArgs - 1) { O << ")\n"; O.indent(IndentLevel + Indent1) << ' ' << LogicOp << " ("; } @@ -1503,7 +1485,7 @@ void EmitCaseTest(const DagInit& d, unsigned IndentLevel, EmitLogicalNot(d, IndentLevel, OptDescs, O); else if (EmitCaseTest0Args(TestName, O)) return; - else if (EmitCaseTest1Arg(TestName, d, OptDescs, O)) + else if (EmitCaseTest1OrMoreArgs(TestName, d, OptDescs, O)) return; else if (EmitCaseTest2Args(TestName, d, IndentLevel, OptDescs, O)) return; @@ -1550,10 +1532,12 @@ public: {} void operator() (const Init* Statement, unsigned IndentLevel) { + // Is this a nested 'case'? + bool IsCase = dynamic_cast<const DagInit*>(Statement) && + GetOperatorName(static_cast<const DagInit&>(*Statement)) == "case"; - // Ignore nested 'case' DAG. - if (!(dynamic_cast<const DagInit*>(Statement) && - GetOperatorName(static_cast<const DagInit&>(*Statement)) == "case")) { + // If so, ignore it, it is handled by our caller, WalkCase. + if (!IsCase) { if (typeid(*Statement) == typeid(ListInit)) { const ListInit& DagList = *static_cast<const ListInit*>(Statement); for (ListInit::const_iterator B = DagList.begin(), E = DagList.end(); @@ -2250,11 +2234,8 @@ void EmitInOutLanguageMethods (const ToolDescription& D, raw_ostream& O) { O.indent(Indent2) << "return InputLanguages_;\n"; O.indent(Indent1) << "}\n\n"; - if (D.OutLanguage.empty()) - throw "Tool " + D.Name + " has no 'out_language' property!"; - - O.indent(Indent1) << "const char* OutputLanguage() const {\n"; - O.indent(Indent2) << "return \"" << D.OutLanguage << "\";\n"; + O.indent(Indent1) << "const char** OutputLanguages() const {\n"; + O.indent(Indent2) << "return OutputLanguages_;\n"; O.indent(Indent1) << "}\n\n"; } @@ -2299,17 +2280,28 @@ void EmitWorksOnEmptyMethod (const ToolDescription& D, O.indent(Indent1) << "}\n\n"; } +/// EmitStrArray - Emit definition of a 'const char**' static member +/// variable. Helper used by EmitStaticMemberDefinitions(); +void EmitStrArray(const std::string& Name, const std::string& VarName, + const StrVector& StrVec, raw_ostream& O) { + O << "const char* " << Name << "::" << VarName << "[] = {"; + for (StrVector::const_iterator B = StrVec.begin(), E = StrVec.end(); + B != E; ++B) + O << '\"' << *B << "\", "; + O << "0};\n"; +} + /// EmitStaticMemberDefinitions - Emit static member definitions for a /// given Tool class. void EmitStaticMemberDefinitions(const ToolDescription& D, raw_ostream& O) { if (D.InLanguage.empty()) throw "Tool " + D.Name + " has no 'in_language' property!"; + if (D.OutLanguage.empty()) + throw "Tool " + D.Name + " has no 'out_language' property!"; - O << "const char* " << D.Name << "::InputLanguages_[] = {"; - for (StrVector::const_iterator B = D.InLanguage.begin(), - E = D.InLanguage.end(); B != E; ++B) - O << '\"' << *B << "\", "; - O << "0};\n\n"; + EmitStrArray(D.Name, "InputLanguages_", D.InLanguage, O); + EmitStrArray(D.Name, "OutputLanguages_", D.OutLanguage, O); + O << '\n'; } /// EmitToolClassDefinition - Emit a Tool class definition. @@ -2327,7 +2319,8 @@ void EmitToolClassDefinition (const ToolDescription& D, O << "Tool"; O << " {\nprivate:\n"; - O.indent(Indent1) << "static const char* InputLanguages_[];\n\n"; + O.indent(Indent1) << "static const char* InputLanguages_[];\n"; + O.indent(Indent1) << "static const char* OutputLanguages_[];\n\n"; O << "public:\n"; EmitNameMethod(D, O); @@ -2448,21 +2441,13 @@ class EmitPreprocessOptionsCallback : const OptionDescriptions& OptDescs_; - void onListOrDag(const DagInit& d, HandlerImpl h, - unsigned IndentLevel, raw_ostream& O) const + void onEachArgument(const DagInit& d, HandlerImpl h, + unsigned IndentLevel, raw_ostream& O) const { CheckNumberOfArguments(d, 1); - const Init* I = d.getArg(0); - // If I is a list, apply h to each element. - if (typeid(*I) == typeid(ListInit)) { - const ListInit& L = *static_cast<const ListInit*>(I); - for (ListInit::const_iterator B = L.begin(), E = L.end(); B != E; ++B) - ((this)->*(h))(*B, IndentLevel, O); - } - // Otherwise, apply h to I. - else { - ((this)->*(h))(I, IndentLevel, O); + for (unsigned i = 0, NumArgs = d.getNumArgs(); i < NumArgs; ++i) { + ((this)->*(h))(d.getArg(i), IndentLevel, O); } } @@ -2489,16 +2474,17 @@ class EmitPreprocessOptionsCallback : void onUnsetOption(const DagInit& d, unsigned IndentLevel, raw_ostream& O) const { - this->onListOrDag(d, &EmitPreprocessOptionsCallback::onUnsetOptionImpl, - IndentLevel, O); + this->onEachArgument(d, &EmitPreprocessOptionsCallback::onUnsetOptionImpl, + IndentLevel, O); } - void onSetOptionImpl(const DagInit& d, + void onSetOptionImpl(const DagInit& D, unsigned IndentLevel, raw_ostream& O) const { - CheckNumberOfArguments(d, 2); - const std::string& OptName = InitPtrToString(d.getArg(0)); - const Init* Value = d.getArg(1); + CheckNumberOfArguments(D, 2); + + const std::string& OptName = InitPtrToString(D.getArg(0)); const OptionDescription& OptDesc = OptDescs_.FindOption(OptName); + const Init* Value = D.getArg(1); if (OptDesc.isList()) { const ListInit& List = InitPtrToList(Value); @@ -2528,7 +2514,7 @@ class EmitPreprocessOptionsCallback : << " = \"" << Str << "\";\n"; } else { - throw "Can't apply 'set_option' to alias option -" + OptName + " !"; + throw "Can't apply 'set_option' to alias option '" + OptName + "'!"; } } @@ -2548,15 +2534,22 @@ class EmitPreprocessOptionsCallback : { CheckNumberOfArguments(d, 1); - // Two arguments: (set_option "parameter", VALUE), where VALUE can be a - // boolean, a string or a string list. - if (d.getNumArgs() > 1) - this->onSetOptionImpl(d, IndentLevel, O); - // One argument: (set_option "switch") - // or (set_option ["switch1", "switch2", ...]) - else - this->onListOrDag(d, &EmitPreprocessOptionsCallback::onSetSwitch, - IndentLevel, O); + // 2-argument form: (set_option "A", true), (set_option "B", "C"), + // (set_option "D", ["E", "F"]) + if (d.getNumArgs() == 2) { + const OptionDescription& OptDesc = + OptDescs_.FindOption(InitPtrToString(d.getArg(0))); + const Init* Opt2 = d.getArg(1); + + if (!OptDesc.isSwitch() || typeid(*Opt2) != typeid(StringInit)) { + this->onSetOptionImpl(d, IndentLevel, O); + return; + } + } + + // Multiple argument form: (set_option "A"), (set_option "B", "C", "D") + this->onEachArgument(d, &EmitPreprocessOptionsCallback::onSetSwitch, + IndentLevel, O); } public: @@ -2661,10 +2654,11 @@ void EmitPopulateLanguageMap (const RecordKeeper& Records, raw_ostream& O) { O << "int PopulateLanguageMap (LanguageMap& langMap) {\n"; - // For each LangMap: + // For each LanguageMap: const RecordVector& LangMaps = Records.getAllDerivedDefinitions("LanguageMap"); + // Call DoEmitPopulateLanguageMap. for (RecordVector::const_iterator B = LangMaps.begin(), E = LangMaps.end(); B!=E; ++B) { ListInit* LangMap = (*B)->getValueAsListInit("map"); @@ -2899,7 +2893,7 @@ public: return; } - // We're invoked on a command line. + // We're invoked on a command line string. this->onCmdLine(InitPtrToString(Arg)); } @@ -3041,7 +3035,8 @@ void CheckDriverData(DriverData& Data) { CheckForSuperfluousOptions(Data.Edges, Data.ToolDescs, Data.OptDescs); } -void EmitDriverCode(const DriverData& Data, raw_ostream& O) { +void EmitDriverCode(const DriverData& Data, + raw_ostream& O, RecordKeeper &Records) { // Emit file header. EmitIncludes(O); @@ -3102,7 +3097,7 @@ void LLVMCConfigurationEmitter::run (raw_ostream &O) { CheckDriverData(Data); this->EmitSourceFileHeader("llvmc-based driver: auto-generated code", O); - EmitDriverCode(Data, O); + EmitDriverCode(Data, O, Records); } catch (std::exception& Error) { throw Error.what() + std::string(" - usually this means a syntax error."); diff --git a/utils/TableGen/LLVMCConfigurationEmitter.h b/utils/TableGen/LLVMCConfigurationEmitter.h index b37b83f..0f2ff37 100644 --- a/utils/TableGen/LLVMCConfigurationEmitter.h +++ b/utils/TableGen/LLVMCConfigurationEmitter.h @@ -21,8 +21,10 @@ namespace llvm { /// LLVMCConfigurationEmitter - TableGen backend that generates /// configuration code for LLVMC. class LLVMCConfigurationEmitter : public TableGenBackend { + RecordKeeper &Records; public: - explicit LLVMCConfigurationEmitter(RecordKeeper&) {} + explicit LLVMCConfigurationEmitter(RecordKeeper &records) : + Records(records) {} // run - Output the asmwriter, returning true on failure. void run(raw_ostream &o); diff --git a/utils/TableGen/Makefile b/utils/TableGen/Makefile index f27cd99..c01b660 100644 --- a/utils/TableGen/Makefile +++ b/utils/TableGen/Makefile @@ -9,7 +9,7 @@ LEVEL = ../.. TOOLNAME = tblgen -USEDLIBS = LLVMSupport.a LLVMSystem.a +USEDLIBS = LLVMSupport.a REQUIRES_EH := 1 REQUIRES_RTTI := 1 diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp index 0a12f37..64224d9 100644 --- a/utils/TableGen/NeonEmitter.cpp +++ b/utils/TableGen/NeonEmitter.cpp @@ -8,17 +8,18 @@ //===----------------------------------------------------------------------===// // // This tablegen backend is responsible for emitting arm_neon.h, which includes -// a declaration and definition of each function specified by the ARM NEON +// a declaration and definition of each function specified by the ARM NEON // compiler interface. See ARM document DUI0348B. // // Each NEON instruction is implemented in terms of 1 or more functions which -// are suffixed with the element type of the input vectors. Functions may be +// are suffixed with the element type of the input vectors. Functions may be // implemented in terms of generic vector operations such as +, *, -, etc. or // by calling a __builtin_-prefixed function which will be handled by clang's // CodeGen library. // // Additional validation code can be generated by this file when runHeader() is -// called, rather than the normal run() entry point. +// called, rather than the normal run() entry point. A complete set of tests +// for Neon intrinsics can be generated by calling the runTests() entry point. // //===----------------------------------------------------------------------===// @@ -38,11 +39,11 @@ static void ParseTypes(Record *r, std::string &s, SmallVectorImpl<StringRef> &TV) { const char *data = s.data(); int len = 0; - + for (unsigned i = 0, e = s.size(); i != e; ++i, ++len) { if (data[len] == 'P' || data[len] == 'Q' || data[len] == 'U') continue; - + switch (data[len]) { case 'c': case 's': @@ -72,6 +73,8 @@ static char Widen(const char t) { return 'i'; case 'i': return 'l'; + case 'h': + return 'f'; default: throw "unhandled type in widen!"; } return '\0'; @@ -89,7 +92,7 @@ static char Narrow(const char t) { return 'i'; case 'f': return 'h'; - default: throw "unhandled type in widen!"; + default: throw "unhandled type in narrow!"; } return '\0'; } @@ -98,25 +101,25 @@ static char Narrow(const char t) { /// the quad-vector, polynomial, or unsigned modifiers set. static char ClassifyType(StringRef ty, bool &quad, bool &poly, bool &usgn) { unsigned off = 0; - + // remember quad. if (ty[off] == 'Q') { quad = true; ++off; } - + // remember poly. if (ty[off] == 'P') { poly = true; ++off; } - + // remember unsigned. if (ty[off] == 'U') { usgn = true; ++off; } - + // base type to get the type string for. return ty[off]; } @@ -134,7 +137,12 @@ static char ModType(const char mod, char type, bool &quad, bool &poly, break; case 'u': usgn = true; + poly = false; + if (type == 'f') + type = 'i'; + break; case 'x': + usgn = false; poly = false; if (type == 'f') type = 'i'; @@ -155,6 +163,10 @@ static char ModType(const char mod, char type, bool &quad, bool &poly, case 'n': type = Widen(type); break; + case 'i': + type = 'i'; + scal = true; + break; case 'l': type = 'l'; scal = true; @@ -189,36 +201,31 @@ static char ModType(const char mod, char type, bool &quad, bool &poly, } /// TypeString - for a modifier and type, generate the name of the typedef for -/// that type. If generic is true, emit the generic vector type rather than -/// the public NEON type. QUc -> uint8x8_t / __neon_uint8x8_t. -static std::string TypeString(const char mod, StringRef typestr, - bool generic = false) { +/// that type. QUc -> uint8x8_t. +static std::string TypeString(const char mod, StringRef typestr) { bool quad = false; bool poly = false; bool usgn = false; bool scal = false; bool cnst = false; bool pntr = false; - + if (mod == 'v') return "void"; if (mod == 'i') return "int"; - + // base type to get the type string for. char type = ClassifyType(typestr, quad, poly, usgn); - + // Based on the modifying character, change the type and width if necessary. type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr); - + SmallString<128> s; - - if (generic) - s += "__neon_"; - + if (usgn) s.push_back('u'); - + switch (type) { case 'c': s += poly ? "poly8" : "int8"; @@ -267,16 +274,16 @@ static std::string TypeString(const char mod, StringRef typestr, s += "x3"; if (mod == '4') s += "x4"; - + // Append _t, finishing the type string typedef type. s += "_t"; - + if (cnst) s += " const"; - + if (pntr) s += " *"; - + return s.str(); } @@ -291,23 +298,25 @@ static std::string BuiltinTypeString(const char mod, StringRef typestr, bool scal = false; bool cnst = false; bool pntr = false; - + if (mod == 'v') - return "v"; + return "v"; // void if (mod == 'i') - return "i"; - + return "i"; // int + // base type to get the type string for. char type = ClassifyType(typestr, quad, poly, usgn); - + // Based on the modifying character, change the type and width if necessary. type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr); + // All pointers are void* pointers. Change type to 'v' now. if (pntr) { usgn = false; poly = false; type = 'v'; } + // Treat half-float ('h') types as unsigned short ('s') types. if (type == 'h') { type = 's'; usgn = true; @@ -319,12 +328,14 @@ static std::string BuiltinTypeString(const char mod, StringRef typestr, if (usgn) s.push_back('U'); - - if (type == 'l') + else if (type == 'c') + s.push_back('S'); // make chars explicitly signed + + if (type == 'l') // 64-bit long s += "LLi"; else s.push_back(type); - + if (cnst) s.push_back('C'); if (pntr) @@ -337,8 +348,8 @@ static std::string BuiltinTypeString(const char mod, StringRef typestr, // returning structs of 2, 3, or 4 vectors which are returned in a sret-like // fashion, storing them to a pointer arg. if (ret) { - if (mod == '2' || mod == '3' || mod == '4') - return "vv*"; + if (mod >= '2' && mod <= '4') + return "vv*"; // void result with void* first argument if (mod == 'f' || (ck != ClassB && type == 'f')) return quad ? "V4f" : "V2f"; if (ck != ClassB && type == 's') @@ -347,17 +358,17 @@ static std::string BuiltinTypeString(const char mod, StringRef typestr, return quad ? "V4i" : "V2i"; if (ck != ClassB && type == 'l') return quad ? "V2LLi" : "V1LLi"; - - return quad ? "V16c" : "V8c"; - } + + return quad ? "V16Sc" : "V8Sc"; + } // Non-return array types are passed as individual vectors. if (mod == '2') - return quad ? "V16cV16c" : "V8cV8c"; + return quad ? "V16ScV16Sc" : "V8ScV8Sc"; if (mod == '3') - return quad ? "V16cV16cV16c" : "V8cV8cV8c"; + return quad ? "V16ScV16ScV16Sc" : "V8ScV8ScV8Sc"; if (mod == '4') - return quad ? "V16cV16cV16cV16c" : "V8cV8cV8cV8c"; + return quad ? "V16ScV16ScV16ScV16Sc" : "V8ScV8ScV8ScV8Sc"; if (mod == 'f' || (ck != ClassB && type == 'f')) return quad ? "V4f" : "V2f"; @@ -367,71 +378,25 @@ static std::string BuiltinTypeString(const char mod, StringRef typestr, return quad ? "V4i" : "V2i"; if (ck != ClassB && type == 'l') return quad ? "V2LLi" : "V1LLi"; - - return quad ? "V16c" : "V8c"; -} -/// StructTag - generate the name of the struct tag for a type. -/// These names are mandated by ARM's ABI. -static std::string StructTag(StringRef typestr) { - bool quad = false; - bool poly = false; - bool usgn = false; - - // base type to get the type string for. - char type = ClassifyType(typestr, quad, poly, usgn); - - SmallString<128> s; - s += "__simd"; - s += quad ? "128_" : "64_"; - if (usgn) - s.push_back('u'); - - switch (type) { - case 'c': - s += poly ? "poly8" : "int8"; - break; - case 's': - s += poly ? "poly16" : "int16"; - break; - case 'i': - s += "int32"; - break; - case 'l': - s += "int64"; - break; - case 'h': - s += "float16"; - break; - case 'f': - s += "float32"; - break; - default: - throw "unhandled type!"; - break; - } - - // Append _t, finishing the struct tag name. - s += "_t"; - - return s.str(); + return quad ? "V16Sc" : "V8Sc"; } -/// MangleName - Append a type or width suffix to a base neon function name, +/// MangleName - Append a type or width suffix to a base neon function name, /// and insert a 'q' in the appropriate location if the operation works on /// 128b rather than 64b. E.g. turn "vst2_lane" into "vst2q_lane_f32", etc. static std::string MangleName(const std::string &name, StringRef typestr, ClassKind ck) { if (name == "vcvt_f32_f16") return name; - + bool quad = false; bool poly = false; bool usgn = false; char type = ClassifyType(typestr, quad, poly, usgn); std::string s = name; - + switch (type) { case 'c': switch (ck) { @@ -487,8 +452,8 @@ static std::string MangleName(const std::string &name, StringRef typestr, } if (ck == ClassB) s += "_v"; - - // Insert a 'q' before the first '_' character so that it ends up before + + // Insert a 'q' before the first '_' character so that it ends up before // _lane or _n on vector-scalar operations. if (quad) { size_t pos = s.find('_'); @@ -501,177 +466,344 @@ static std::string MangleName(const std::string &name, StringRef typestr, static std::string GenArgs(const std::string &proto, StringRef typestr) { bool define = proto.find('i') != std::string::npos; char arg = 'a'; - + std::string s; s += "("; - + for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) { - if (!define) { - s += TypeString(proto[i], typestr); - s.push_back(' '); + if (define) { + // Immediate macro arguments are used directly instead of being assigned + // to local temporaries; prepend an underscore prefix to make their + // names consistent with the local temporaries. + if (proto[i] == 'i') + s += "__"; + } else { + s += TypeString(proto[i], typestr) + " __"; } s.push_back(arg); if ((i + 1) < e) s += ", "; } - + s += ")"; return s; } -static std::string Duplicate(unsigned nElts, StringRef typestr, +// Macro arguments are not type-checked like inline function arguments, so +// assign them to local temporaries to get the right type checking. +static std::string GenMacroLocals(const std::string &proto, StringRef typestr) { + char arg = 'a'; + std::string s; + + for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) { + // Do not create a temporary for an immediate argument. + // That would defeat the whole point of using a macro! + if (proto[i] == 'i') continue; + + s += TypeString(proto[i], typestr) + " __"; + s.push_back(arg); + s += " = ("; + s.push_back(arg); + s += "); "; + } + + s += "\\\n "; + return s; +} + +// Use the vmovl builtin to sign-extend or zero-extend a vector. +static std::string Extend(StringRef typestr, const std::string &a) { + std::string s; + s = MangleName("vmovl", typestr, ClassS); + s += "(" + a + ")"; + return s; +} + +static std::string Duplicate(unsigned nElts, StringRef typestr, const std::string &a) { std::string s; - - s = "(__neon_" + TypeString('d', typestr) + "){ "; + + s = "(" + TypeString('d', typestr) + "){ "; for (unsigned i = 0; i != nElts; ++i) { s += a; if ((i + 1) < nElts) s += ", "; } s += " }"; - + return s; } -// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd. -// If structTypes is true, the NEON types are structs of vector types rather -// than vector types, and the call becomes "a.val + b.val" -static std::string GenOpString(OpKind op, const std::string &proto, - StringRef typestr, bool structTypes = true) { - bool dummy, quad = false; +static std::string SplatLane(unsigned nElts, const std::string &vec, + const std::string &lane) { + std::string s = "__builtin_shufflevector(" + vec + ", " + vec; + for (unsigned i = 0; i < nElts; ++i) + s += ", " + lane; + s += ")"; + return s; +} + +static unsigned GetNumElements(StringRef typestr, bool &quad) { + quad = false; + bool dummy = false; char type = ClassifyType(typestr, quad, dummy, dummy); unsigned nElts = 0; switch (type) { - case 'c': nElts = 8; break; - case 's': nElts = 4; break; - case 'i': nElts = 2; break; - case 'l': nElts = 1; break; - case 'h': nElts = 4; break; - case 'f': nElts = 2; break; + case 'c': nElts = 8; break; + case 's': nElts = 4; break; + case 'i': nElts = 2; break; + case 'l': nElts = 1; break; + case 'h': nElts = 4; break; + case 'f': nElts = 2; break; + default: + throw "unhandled type!"; + break; } - + if (quad) nElts <<= 1; + return nElts; +} + +// Generate the definition for this intrinsic, e.g. "a + b" for OpAdd. +static std::string GenOpString(OpKind op, const std::string &proto, + StringRef typestr) { + bool quad; + unsigned nElts = GetNumElements(typestr, quad); + + // If this builtin takes an immediate argument, we need to #define it rather + // than use a standard declaration, so that SemaChecking can range check + // the immediate passed by the user. + bool define = proto.find('i') != std::string::npos; + std::string ts = TypeString(proto[0], typestr); - std::string s = ts + " r; r"; - - if (structTypes) - s += ".val"; - - s += " = "; - - std::string a, b, c; - if (proto.size() > 1) - a = (structTypes && proto[1] != 'l' && proto[1] != 's') ? "a.val" : "a"; - b = structTypes ? "b.val" : "b"; - c = structTypes ? "c.val" : "c"; - + std::string s; + if (!define) { + s = "return "; + } + switch(op) { case OpAdd: - s += a + " + " + b; + s += "__a + __b;"; + break; + case OpAddl: + s += Extend(typestr, "__a") + " + " + Extend(typestr, "__b") + ";"; + break; + case OpAddw: + s += "__a + " + Extend(typestr, "__b") + ";"; break; case OpSub: - s += a + " - " + b; + s += "__a - __b;"; + break; + case OpSubl: + s += Extend(typestr, "__a") + " - " + Extend(typestr, "__b") + ";"; + break; + case OpSubw: + s += "__a - " + Extend(typestr, "__b") + ";"; break; case OpMulN: - b = Duplicate(nElts << (int)quad, typestr, "b"); + s += "__a * " + Duplicate(nElts, typestr, "__b") + ";"; + break; + case OpMulLane: + s += "__a * " + SplatLane(nElts, "__b", "__c") + ";"; + break; case OpMul: - s += a + " * " + b; + s += "__a * __b;"; + break; + case OpMullN: + s += Extend(typestr, "__a") + " * " + + Extend(typestr, Duplicate(nElts << (int)quad, typestr, "__b")) + ";"; + break; + case OpMullLane: + s += Extend(typestr, "__a") + " * " + + Extend(typestr, SplatLane(nElts, "__b", "__c")) + ";"; + break; + case OpMull: + s += Extend(typestr, "__a") + " * " + Extend(typestr, "__b") + ";"; break; case OpMlaN: - c = Duplicate(nElts << (int)quad, typestr, "c"); + s += "__a + (__b * " + Duplicate(nElts, typestr, "__c") + ");"; + break; + case OpMlaLane: + s += "__a + (__b * " + SplatLane(nElts, "__c", "__d") + ");"; + break; case OpMla: - s += a + " + ( " + b + " * " + c + " )"; + s += "__a + (__b * __c);"; + break; + case OpMlalN: + s += "__a + (" + Extend(typestr, "__b") + " * " + + Extend(typestr, Duplicate(nElts, typestr, "__c")) + ");"; + break; + case OpMlalLane: + s += "__a + (" + Extend(typestr, "__b") + " * " + + Extend(typestr, SplatLane(nElts, "__c", "__d")) + ");"; + break; + case OpMlal: + s += "__a + (" + Extend(typestr, "__b") + " * " + + Extend(typestr, "__c") + ");"; break; case OpMlsN: - c = Duplicate(nElts << (int)quad, typestr, "c"); + s += "__a - (__b * " + Duplicate(nElts, typestr, "__c") + ");"; + break; + case OpMlsLane: + s += "__a - (__b * " + SplatLane(nElts, "__c", "__d") + ");"; + break; case OpMls: - s += a + " - ( " + b + " * " + c + " )"; + s += "__a - (__b * __c);"; + break; + case OpMlslN: + s += "__a - (" + Extend(typestr, "__b") + " * " + + Extend(typestr, Duplicate(nElts, typestr, "__c")) + ");"; + break; + case OpMlslLane: + s += "__a - (" + Extend(typestr, "__b") + " * " + + Extend(typestr, SplatLane(nElts, "__c", "__d")) + ");"; + break; + case OpMlsl: + s += "__a - (" + Extend(typestr, "__b") + " * " + + Extend(typestr, "__c") + ");"; + break; + case OpQDMullLane: + s += MangleName("vqdmull", typestr, ClassS) + "(__a, " + + SplatLane(nElts, "__b", "__c") + ");"; + break; + case OpQDMlalLane: + s += MangleName("vqdmlal", typestr, ClassS) + "(__a, __b, " + + SplatLane(nElts, "__c", "__d") + ");"; + break; + case OpQDMlslLane: + s += MangleName("vqdmlsl", typestr, ClassS) + "(__a, __b, " + + SplatLane(nElts, "__c", "__d") + ");"; + break; + case OpQDMulhLane: + s += MangleName("vqdmulh", typestr, ClassS) + "(__a, " + + SplatLane(nElts, "__b", "__c") + ");"; + break; + case OpQRDMulhLane: + s += MangleName("vqrdmulh", typestr, ClassS) + "(__a, " + + SplatLane(nElts, "__b", "__c") + ");"; break; case OpEq: - s += "(__neon_" + ts + ")(" + a + " == " + b + ")"; + s += "(" + ts + ")(__a == __b);"; break; case OpGe: - s += "(__neon_" + ts + ")(" + a + " >= " + b + ")"; + s += "(" + ts + ")(__a >= __b);"; break; case OpLe: - s += "(__neon_" + ts + ")(" + a + " <= " + b + ")"; + s += "(" + ts + ")(__a <= __b);"; break; case OpGt: - s += "(__neon_" + ts + ")(" + a + " > " + b + ")"; + s += "(" + ts + ")(__a > __b);"; break; case OpLt: - s += "(__neon_" + ts + ")(" + a + " < " + b + ")"; + s += "(" + ts + ")(__a < __b);"; break; case OpNeg: - s += " -" + a; + s += " -__a;"; break; case OpNot: - s += " ~" + a; + s += " ~__a;"; break; case OpAnd: - s += a + " & " + b; + s += "__a & __b;"; break; case OpOr: - s += a + " | " + b; + s += "__a | __b;"; break; case OpXor: - s += a + " ^ " + b; + s += "__a ^ __b;"; break; case OpAndNot: - s += a + " & ~" + b; + s += "__a & ~__b;"; break; case OpOrNot: - s += a + " | ~" + b; + s += "__a | ~__b;"; break; case OpCast: - s += "(__neon_" + ts + ")" + a; + s += "(" + ts + ")__a;"; break; case OpConcat: - s += "__builtin_shufflevector((__neon_int64x1_t)" + a; - s += ", (__neon_int64x1_t)" + b + ", 0, 1)"; + s += "(" + ts + ")__builtin_shufflevector((int64x1_t)__a"; + s += ", (int64x1_t)__b, 0, 1);"; break; case OpHi: - s += "(__neon_int64x1_t)(((__neon_int64x2_t)" + a + ")[1])"; + s += "(" + ts + + ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 1);"; break; case OpLo: - s += "(__neon_int64x1_t)(((__neon_int64x2_t)" + a + ")[0])"; + s += "(" + ts + + ")__builtin_shufflevector((int64x2_t)__a, (int64x2_t)__a, 0);"; break; case OpDup: - s += Duplicate(nElts << (int)quad, typestr, a); + s += Duplicate(nElts, typestr, "__a") + ";"; + break; + case OpDupLane: + s += SplatLane(nElts, "__a", "__b") + ";"; break; case OpSelect: // ((0 & 1) | (~0 & 2)) + s += "(" + ts + ")"; ts = TypeString(proto[1], typestr); - s += "( " + a + " & (__neon_" + ts + ")" + b + ") | "; - s += "(~" + a + " & (__neon_" + ts + ")" + c + ")"; + s += "((__a & (" + ts + ")__b) | "; + s += "(~__a & (" + ts + ")__c));"; break; case OpRev16: - s += "__builtin_shufflevector(" + a + ", " + a; - for (unsigned i = 2; i <= nElts << (int)quad; i += 2) + s += "__builtin_shufflevector(__a, __a"; + for (unsigned i = 2; i <= nElts; i += 2) for (unsigned j = 0; j != 2; ++j) s += ", " + utostr(i - j - 1); - s += ")"; + s += ");"; break; - case OpRev32: - nElts >>= 1; - s += "__builtin_shufflevector(" + a + ", " + a; - for (unsigned i = nElts; i <= nElts << (1 + (int)quad); i += nElts) - for (unsigned j = 0; j != nElts; ++j) + case OpRev32: { + unsigned WordElts = nElts >> (1 + (int)quad); + s += "__builtin_shufflevector(__a, __a"; + for (unsigned i = WordElts; i <= nElts; i += WordElts) + for (unsigned j = 0; j != WordElts; ++j) s += ", " + utostr(i - j - 1); - s += ")"; + s += ");"; break; - case OpRev64: - s += "__builtin_shufflevector(" + a + ", " + a; - for (unsigned i = nElts; i <= nElts << (int)quad; i += nElts) - for (unsigned j = 0; j != nElts; ++j) + } + case OpRev64: { + unsigned DblWordElts = nElts >> (int)quad; + s += "__builtin_shufflevector(__a, __a"; + for (unsigned i = DblWordElts; i <= nElts; i += DblWordElts) + for (unsigned j = 0; j != DblWordElts; ++j) s += ", " + utostr(i - j - 1); - s += ")"; + s += ");"; + break; + } + case OpAbdl: { + std::string abd = MangleName("vabd", typestr, ClassS) + "(__a, __b)"; + if (typestr[0] != 'U') { + // vabd results are always unsigned and must be zero-extended. + std::string utype = "U" + typestr.str(); + s += "(" + TypeString(proto[0], typestr) + ")"; + abd = "(" + TypeString('d', utype) + ")" + abd; + s += Extend(utype, abd) + ";"; + } else { + s += Extend(typestr, abd) + ";"; + } + break; + } + case OpAba: + s += "__a + " + MangleName("vabd", typestr, ClassS) + "(__b, __c);"; break; + case OpAbal: { + s += "__a + "; + std::string abd = MangleName("vabd", typestr, ClassS) + "(__b, __c)"; + if (typestr[0] != 'U') { + // vabd results are always unsigned and must be zero-extended. + std::string utype = "U" + typestr.str(); + s += "(" + TypeString(proto[0], typestr) + ")"; + abd = "(" + TypeString('d', utype) + ")" + abd; + s += Extend(utype, abd) + ";"; + } else { + s += Extend(typestr, abd) + ";"; + } + break; + } default: throw "unknown OpKind!"; break; } - s += "; return r;"; return s; } @@ -688,10 +820,10 @@ static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) { bool scal = false; bool cnst = false; bool pntr = false; - + // Base type to get the type string for. char type = ClassifyType(typestr, quad, poly, usgn); - + // Based on the modifying character, change the type and width if necessary. type = ModType(mod, type, quad, poly, usgn, scal, cnst, pntr); @@ -699,9 +831,9 @@ static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) { ret |= 0x08; if (quad && proto[1] != 'g') ret |= 0x10; - + switch (type) { - case 'c': + case 'c': ret |= poly ? 5 : 0; break; case 's': @@ -727,65 +859,45 @@ static unsigned GetNeonEnum(const std::string &proto, StringRef typestr) { } // Generate the definition for this intrinsic, e.g. __builtin_neon_cls(a) -// If structTypes is true, the NEON types are structs of vector types rather -// than vector types, and the call becomes __builtin_neon_cls(a.val) static std::string GenBuiltin(const std::string &name, const std::string &proto, - StringRef typestr, ClassKind ck, - bool structTypes = true) { - bool dummy, quad = false; - char type = ClassifyType(typestr, quad, dummy, dummy); - unsigned nElts = 0; - switch (type) { - case 'c': nElts = 8; break; - case 's': nElts = 4; break; - case 'i': nElts = 2; break; - case 'l': nElts = 1; break; - case 'h': nElts = 4; break; - case 'f': nElts = 2; break; - } - if (quad) nElts <<= 1; - - char arg = 'a'; + StringRef typestr, ClassKind ck) { std::string s; // If this builtin returns a struct 2, 3, or 4 vectors, pass it as an implicit // sret-like argument. - bool sret = (proto[0] == '2' || proto[0] == '3' || proto[0] == '4'); + bool sret = (proto[0] >= '2' && proto[0] <= '4'); // If this builtin takes an immediate argument, we need to #define it rather // than use a standard declaration, so that SemaChecking can range check // the immediate passed by the user. bool define = proto.find('i') != std::string::npos; - // If all types are the same size, bitcasting the args will take care - // of arg checking. The actual signedness etc. will be taken care of with - // special enums. + // Check if the prototype has a scalar operand with the type of the vector + // elements. If not, bitcasting the args will take care of arg checking. + // The actual signedness etc. will be taken care of with special enums. if (proto.find('s') == std::string::npos) ck = ClassB; if (proto[0] != 'v') { std::string ts = TypeString(proto[0], typestr); - + if (define) { if (sret) - s += "({ " + ts + " r; "; - else if (proto[0] != 's') - s += "(" + ts + "){(__neon_" + ts + ")"; + s += ts + " r; "; + else + s += "(" + ts + ")"; } else if (sret) { s += ts + " r; "; } else { - s += ts + " r; r"; - if (structTypes && proto[0] != 's' && proto[0] != 'i' && proto[0] != 'l') - s += ".val"; - - s += " = "; + s += "return (" + ts + ")"; } } - + bool splat = proto.find('a') != std::string::npos; - + s += "__builtin_neon_"; if (splat) { + // Call the non-splat builtin: chop off the "_n" suffix from the name. std::string vname(name, 0, name.size()-2); s += MangleName(vname, typestr, ck); } else { @@ -797,17 +909,32 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto, // builtins. if (sret) s += "&r, "; - + + char arg = 'a'; for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) { std::string args = std::string(&arg, 1); - if (define) - args = "(" + args + ")"; - + + // Use the local temporaries instead of the macro arguments. + args = "__" + args; + + bool argQuad = false; + bool argPoly = false; + bool argUsgn = false; + bool argScalar = false; + bool dummy = false; + char argType = ClassifyType(typestr, argQuad, argPoly, argUsgn); + argType = ModType(proto[i], argType, argQuad, argPoly, argUsgn, argScalar, + dummy, dummy); + // Handle multiple-vector values specially, emitting each subvector as an // argument to the __builtin. - if (structTypes && (proto[i] == '2' || proto[i] == '3' || proto[i] == '4')){ + if (proto[i] >= '2' && proto[i] <= '4') { + // Check if an explicit cast is needed. + if (argType != 'c' || argPoly || argUsgn) + args = (argQuad ? "(int8x16_t)" : "(int8x8_t)") + args; + for (unsigned vi = 0, ve = proto[i] - '0'; vi != ve; ++vi) { - s += args + ".val[" + utostr(vi) + "].val"; + s += args + ".val[" + utostr(vi) + "]"; if ((vi + 1) < ve) s += ", "; } @@ -816,77 +943,158 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto, continue; } - - if (splat && (i + 1) == e) - s += Duplicate(nElts, typestr, args); - else - s += args; - - if (structTypes && proto[i] != 's' && proto[i] != 'i' && proto[i] != 'l' && - proto[i] != 'p' && proto[i] != 'c' && proto[i] != 'a') { - s += ".val"; + + if (splat && (i + 1) == e) + args = Duplicate(GetNumElements(typestr, argQuad), typestr, args); + + // Check if an explicit cast is needed. + if ((splat || !argScalar) && + ((ck == ClassB && argType != 'c') || argPoly || argUsgn)) { + std::string argTypeStr = "c"; + if (ck != ClassB) + argTypeStr = argType; + if (argQuad) + argTypeStr = "Q" + argTypeStr; + args = "(" + TypeString('d', argTypeStr) + ")" + args; } + + s += args; if ((i + 1) < e) s += ", "; } - + // Extra constant integer to hold type class enum for this function, e.g. s8 if (ck == ClassB) s += ", " + utostr(GetNeonEnum(proto, typestr)); - - if (define) - s += ")"; - else - s += ");"; - if (proto[0] != 'v') { - if (define) { - if (sret) - s += "; r; })"; - else if (proto[0] != 's') - s += "}"; - } else { + s += ");"; + + if (proto[0] != 'v' && sret) { + if (define) + s += " r;"; + else s += " return r;"; - } } return s; } -static std::string GenBuiltinDef(const std::string &name, +static std::string GenBuiltinDef(const std::string &name, const std::string &proto, StringRef typestr, ClassKind ck) { std::string s("BUILTIN(__builtin_neon_"); - // If all types are the same size, bitcasting the args will take care + // If all types are the same size, bitcasting the args will take care // of arg checking. The actual signedness etc. will be taken care of with // special enums. if (proto.find('s') == std::string::npos) ck = ClassB; - + s += MangleName(name, typestr, ck); s += ", \""; - + for (unsigned i = 0, e = proto.size(); i != e; ++i) s += BuiltinTypeString(proto[i], typestr, ck, i == 0); // Extra constant integer to hold type class enum for this function, e.g. s8 if (ck == ClassB) s += "i"; - + s += "\", \"n\")"; return s; } +static std::string GenIntrinsic(const std::string &name, + const std::string &proto, + StringRef outTypeStr, StringRef inTypeStr, + OpKind kind, ClassKind classKind) { + assert(!proto.empty() && ""); + bool define = proto.find('i') != std::string::npos; + std::string s; + + // static always inline + return type + if (define) + s += "#define "; + else + s += "__ai " + TypeString(proto[0], outTypeStr) + " "; + + // Function name with type suffix + std::string mangledName = MangleName(name, outTypeStr, ClassS); + if (outTypeStr != inTypeStr) { + // If the input type is different (e.g., for vreinterpret), append a suffix + // for the input type. String off a "Q" (quad) prefix so that MangleName + // does not insert another "q" in the name. + unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0); + StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff); + mangledName = MangleName(mangledName, inTypeNoQuad, ClassS); + } + s += mangledName; + + // Function arguments + s += GenArgs(proto, inTypeStr); + + // Definition. + if (define) { + s += " __extension__ ({ \\\n "; + s += GenMacroLocals(proto, inTypeStr); + } else { + s += " { \\\n "; + } + + if (kind != OpNone) + s += GenOpString(kind, proto, outTypeStr); + else + s += GenBuiltin(name, proto, outTypeStr, classKind); + if (define) + s += " })"; + else + s += " }"; + s += "\n"; + return s; +} + /// run - Read the records in arm_neon.td and output arm_neon.h. arm_neon.h /// is comprised of type definitions and function declarations. void NeonEmitter::run(raw_ostream &OS) { - EmitSourceFileHeader("ARM NEON Header", OS); - - // FIXME: emit license into file? - + OS << + "/*===---- arm_neon.h - ARM Neon intrinsics ------------------------------" + "---===\n" + " *\n" + " * Permission is hereby granted, free of charge, to any person obtaining " + "a copy\n" + " * of this software and associated documentation files (the \"Software\")," + " to deal\n" + " * in the Software without restriction, including without limitation the " + "rights\n" + " * to use, copy, modify, merge, publish, distribute, sublicense, " + "and/or sell\n" + " * copies of the Software, and to permit persons to whom the Software is\n" + " * furnished to do so, subject to the following conditions:\n" + " *\n" + " * The above copyright notice and this permission notice shall be " + "included in\n" + " * all copies or substantial portions of the Software.\n" + " *\n" + " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, " + "EXPRESS OR\n" + " * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF " + "MERCHANTABILITY,\n" + " * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT " + "SHALL THE\n" + " * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR " + "OTHER\n" + " * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, " + "ARISING FROM,\n" + " * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER " + "DEALINGS IN\n" + " * THE SOFTWARE.\n" + " *\n" + " *===--------------------------------------------------------------------" + "---===\n" + " */\n\n"; + OS << "#ifndef __ARM_NEON_H\n"; OS << "#define __ARM_NEON_H\n\n"; - + OS << "#ifndef __ARM_NEON__\n"; OS << "#error \"NEON support not enabled\"\n"; OS << "#endif\n\n"; @@ -895,8 +1103,8 @@ void NeonEmitter::run(raw_ostream &OS) { // Emit NEON-specific scalar typedefs. OS << "typedef float float32_t;\n"; - OS << "typedef uint8_t poly8_t;\n"; - OS << "typedef uint16_t poly16_t;\n"; + OS << "typedef int8_t poly8_t;\n"; + OS << "typedef int16_t poly16_t;\n"; OS << "typedef uint16_t float16_t;\n"; // Emit Neon vector typedefs. @@ -905,105 +1113,105 @@ void NeonEmitter::run(raw_ostream &OS) { ParseTypes(0, TypedefTypes, TDTypeVec); // Emit vector typedefs. - for (unsigned v = 1; v != 5; ++v) { - for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) { - bool dummy, quad = false; - (void) ClassifyType(TDTypeVec[i], quad, dummy, dummy); - OS << "typedef __attribute__(( __vector_size__("; - - OS << utostr(8*v*(quad ? 2 : 1)) << ") )) "; - if (!quad) - OS << " "; - - OS << TypeString('s', TDTypeVec[i]); - OS << " __neon_"; - - char t = (v == 1) ? 'd' : '0' + v; - OS << TypeString(t, TDTypeVec[i]) << ";\n"; - } + for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) { + bool dummy, quad = false, poly = false; + (void) ClassifyType(TDTypeVec[i], quad, poly, dummy); + if (poly) + OS << "typedef __attribute__((neon_polyvector_type("; + else + OS << "typedef __attribute__((neon_vector_type("; + + unsigned nElts = GetNumElements(TDTypeVec[i], quad); + OS << utostr(nElts) << "))) "; + if (nElts < 10) + OS << " "; + + OS << TypeString('s', TDTypeVec[i]); + OS << " " << TypeString('d', TDTypeVec[i]) << ";\n"; } OS << "\n"; // Emit struct typedefs. - for (unsigned vi = 1; vi != 5; ++vi) { + for (unsigned vi = 2; vi != 5; ++vi) { for (unsigned i = 0, e = TDTypeVec.size(); i != e; ++i) { - std::string ts = TypeString('d', TDTypeVec[i], vi == 1); - std::string vs = TypeString((vi > 1) ? '0' + vi : 'd', TDTypeVec[i]); - std::string tag = (vi > 1) ? vs : StructTag(TDTypeVec[i]); - OS << "typedef struct " << tag << " {\n"; + std::string ts = TypeString('d', TDTypeVec[i]); + std::string vs = TypeString('0' + vi, TDTypeVec[i]); + OS << "typedef struct " << vs << " {\n"; OS << " " << ts << " val"; - if (vi > 1) - OS << "[" << utostr(vi) << "]"; - OS << ";\n} " << vs << ";\n\n"; + OS << "[" << utostr(vi) << "]"; + OS << ";\n} "; + OS << vs << ";\n\n"; } } - + OS << "#define __ai static __attribute__((__always_inline__))\n\n"; std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst"); - - // Unique the return+pattern types, and assign them. + + // Emit vmovl and vabd intrinsics first so they can be used by other + // intrinsics. (Some of the saturating multiply instructions are also + // used to implement the corresponding "_lane" variants, but tablegen + // sorts the records into alphabetical order so that the "_lane" variants + // come after the intrinsics they use.) + emitIntrinsic(OS, Records.getDef("VMOVL")); + emitIntrinsic(OS, Records.getDef("VABD")); + for (unsigned i = 0, e = RV.size(); i != e; ++i) { Record *R = RV[i]; - std::string name = LowercaseString(R->getName()); - std::string Proto = R->getValueAsString("Prototype"); - std::string Types = R->getValueAsString("Types"); - - SmallVector<StringRef, 16> TypeVec; - ParseTypes(R, Types, TypeVec); - - OpKind k = OpMap[R->getValueAsDef("Operand")->getName()]; - - bool define = Proto.find('i') != std::string::npos; - - for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) { - assert(!Proto.empty() && ""); - - // static always inline + return type - if (define) - OS << "#define"; - else - OS << "__ai " << TypeString(Proto[0], TypeVec[ti]); - - // Function name with type suffix - OS << " " << MangleName(name, TypeVec[ti], ClassS); - - // Function arguments - OS << GenArgs(Proto, TypeVec[ti]); - - // Definition. - if (define) - OS << " "; - else - OS << " { "; - - if (k != OpNone) { - OS << GenOpString(k, Proto, TypeVec[ti]); - } else { - if (R->getSuperClasses().size() < 2) - throw TGError(R->getLoc(), "Builtin has no class kind"); - - ClassKind ck = ClassMap[R->getSuperClasses()[1]]; - - if (ck == ClassNone) - throw TGError(R->getLoc(), "Builtin has no class kind"); - OS << GenBuiltin(name, Proto, TypeVec[ti], ck); - } - if (!define) - OS << " }"; - OS << "\n"; - } - OS << "\n"; + if (R->getName() != "VMOVL" && R->getName() != "VABD") + emitIntrinsic(OS, R); } + OS << "#undef __ai\n\n"; OS << "#endif /* __ARM_NEON_H */\n"; } -static unsigned RangeFromType(StringRef typestr) { +/// emitIntrinsic - Write out the arm_neon.h header file definitions for the +/// intrinsics specified by record R. +void NeonEmitter::emitIntrinsic(raw_ostream &OS, Record *R) { + std::string name = R->getValueAsString("Name"); + std::string Proto = R->getValueAsString("Prototype"); + std::string Types = R->getValueAsString("Types"); + + SmallVector<StringRef, 16> TypeVec; + ParseTypes(R, Types, TypeVec); + + OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()]; + + ClassKind classKind = ClassNone; + if (R->getSuperClasses().size() >= 2) + classKind = ClassMap[R->getSuperClasses()[1]]; + if (classKind == ClassNone && kind == OpNone) + throw TGError(R->getLoc(), "Builtin has no class kind"); + + for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) { + if (kind == OpReinterpret) { + bool outQuad = false; + bool dummy = false; + (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy); + for (unsigned srcti = 0, srcte = TypeVec.size(); + srcti != srcte; ++srcti) { + bool inQuad = false; + (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy); + if (srcti == ti || inQuad != outQuad) + continue; + OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[srcti], + OpCast, ClassS); + } + } else { + OS << GenIntrinsic(name, Proto, TypeVec[ti], TypeVec[ti], + kind, classKind); + } + } + OS << "\n"; +} + +static unsigned RangeFromType(const char mod, StringRef typestr) { // base type to get the type string for. bool quad = false, dummy = false; char type = ClassifyType(typestr, quad, dummy, dummy); - + type = ModType(mod, type, quad, dummy, dummy, dummy, dummy, dummy); + switch (type) { case 'c': return (8 << (int)quad) - 1; @@ -1031,7 +1239,7 @@ void NeonEmitter::runHeader(raw_ostream &OS) { std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst"); StringMap<OpKind> EmittedMap; - + // Generate BuiltinsARM.def for NEON OS << "#ifdef GET_NEON_BUILTINS\n"; for (unsigned i = 0, e = RV.size(); i != e; ++i) { @@ -1041,22 +1249,22 @@ void NeonEmitter::runHeader(raw_ostream &OS) { continue; std::string Proto = R->getValueAsString("Prototype"); - + // Functions with 'a' (the splat code) in the type prototype should not get // their own builtin as they use the non-splat variant. if (Proto.find('a') != std::string::npos) continue; - + std::string Types = R->getValueAsString("Types"); SmallVector<StringRef, 16> TypeVec; ParseTypes(R, Types, TypeVec); - + if (R->getSuperClasses().size() < 2) throw TGError(R->getLoc(), "Builtin has no class kind"); - - std::string name = LowercaseString(R->getName()); + + std::string name = R->getValueAsString("Name"); ClassKind ck = ClassMap[R->getSuperClasses()[1]]; - + for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) { // Generate the BuiltinsARM.def declaration for this builtin, ensuring // that each unique BUILTIN() macro appears only once in the output @@ -1064,13 +1272,13 @@ void NeonEmitter::runHeader(raw_ostream &OS) { std::string bd = GenBuiltinDef(name, Proto, TypeVec[ti], ck); if (EmittedMap.count(bd)) continue; - + EmittedMap[bd] = OpNone; OS << bd << "\n"; } } OS << "#endif\n\n"; - + // Generate the overloaded type checking code for SemaChecking.cpp OS << "#ifdef GET_NEON_OVERLOAD_CHECK\n"; for (unsigned i = 0, e = RV.size(); i != e; ++i) { @@ -1078,34 +1286,34 @@ void NeonEmitter::runHeader(raw_ostream &OS) { OpKind k = OpMap[R->getValueAsDef("Operand")->getName()]; if (k != OpNone) continue; - + std::string Proto = R->getValueAsString("Prototype"); std::string Types = R->getValueAsString("Types"); - std::string name = LowercaseString(R->getName()); - + std::string name = R->getValueAsString("Name"); + // Functions with 'a' (the splat code) in the type prototype should not get // their own builtin as they use the non-splat variant. if (Proto.find('a') != std::string::npos) continue; - + // Functions which have a scalar argument cannot be overloaded, no need to // check them if we are emitting the type checking code. if (Proto.find('s') != std::string::npos) continue; - + SmallVector<StringRef, 16> TypeVec; ParseTypes(R, Types, TypeVec); - + if (R->getSuperClasses().size() < 2) throw TGError(R->getLoc(), "Builtin has no class kind"); - + int si = -1, qi = -1; unsigned mask = 0, qmask = 0; for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) { // Generate the switch case(s) for this builtin for the type validation. bool quad = false, poly = false, usgn = false; (void) ClassifyType(TypeVec[ti], quad, poly, usgn); - + if (quad) { qi = ti; qmask |= 1 << GetNeonEnum(Proto, TypeVec[ti]); @@ -1115,64 +1323,67 @@ void NeonEmitter::runHeader(raw_ostream &OS) { } } if (mask) - OS << "case ARM::BI__builtin_neon_" - << MangleName(name, TypeVec[si], ClassB) - << ": mask = " << "0x" << utohexstr(mask) << "; break;\n"; + OS << "case ARM::BI__builtin_neon_" + << MangleName(name, TypeVec[si], ClassB) + << ": mask = " << "0x" << utohexstr(mask) << "; break;\n"; if (qmask) - OS << "case ARM::BI__builtin_neon_" - << MangleName(name, TypeVec[qi], ClassB) - << ": mask = " << "0x" << utohexstr(qmask) << "; break;\n"; + OS << "case ARM::BI__builtin_neon_" + << MangleName(name, TypeVec[qi], ClassB) + << ": mask = " << "0x" << utohexstr(qmask) << "; break;\n"; } OS << "#endif\n\n"; - + // Generate the intrinsic range checking code for shift/lane immediates. OS << "#ifdef GET_NEON_IMMEDIATE_CHECK\n"; for (unsigned i = 0, e = RV.size(); i != e; ++i) { Record *R = RV[i]; - + OpKind k = OpMap[R->getValueAsDef("Operand")->getName()]; if (k != OpNone) continue; - - std::string name = LowercaseString(R->getName()); + + std::string name = R->getValueAsString("Name"); std::string Proto = R->getValueAsString("Prototype"); std::string Types = R->getValueAsString("Types"); - + // Functions with 'a' (the splat code) in the type prototype should not get // their own builtin as they use the non-splat variant. if (Proto.find('a') != std::string::npos) continue; - + // Functions which do not have an immediate do not need to have range // checking code emitted. - if (Proto.find('i') == std::string::npos) + size_t immPos = Proto.find('i'); + if (immPos == std::string::npos) continue; - + SmallVector<StringRef, 16> TypeVec; ParseTypes(R, Types, TypeVec); - + if (R->getSuperClasses().size() < 2) throw TGError(R->getLoc(), "Builtin has no class kind"); - + ClassKind ck = ClassMap[R->getSuperClasses()[1]]; - + for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) { std::string namestr, shiftstr, rangestr; - + // Builtins which are overloaded by type will need to have their upper // bound computed at Sema time based on the type constant. if (Proto.find('s') == std::string::npos) { ck = ClassB; if (R->getValueAsBit("isShift")) { shiftstr = ", true"; - + // Right shifts have an 'r' in the name, left shifts do not. if (name.find('r') != std::string::npos) rangestr = "l = 1; "; } rangestr += "u = RFT(TV" + shiftstr + ")"; } else { - rangestr = "u = " + utostr(RangeFromType(TypeVec[ti])); + // The immediate generally refers to a lane in the preceding argument. + assert(immPos > 0 && "unexpected immediate operand"); + rangestr = "u = " + utostr(RangeFromType(Proto[immPos-1], TypeVec[ti])); } // Make sure cases appear only once by uniquing them in a string map. namestr = MangleName(name, TypeVec[ti], ck); @@ -1182,13 +1393,13 @@ void NeonEmitter::runHeader(raw_ostream &OS) { // Calculate the index of the immediate that should be range checked. unsigned immidx = 0; - + // Builtins that return a struct of multiple vectors have an extra // leading arg for the struct return. - if (Proto[0] == '2' || Proto[0] == '3' || Proto[0] == '4') + if (Proto[0] >= '2' && Proto[0] <= '4') ++immidx; - - // Add one to the index for each argument until we reach the immediate + + // Add one to the index for each argument until we reach the immediate // to be checked. Structs of vectors are passed as multiple arguments. for (unsigned ii = 1, ie = Proto.size(); ii != ie; ++ii) { switch (Proto[ii]) { @@ -1199,9 +1410,113 @@ void NeonEmitter::runHeader(raw_ostream &OS) { case 'i': ie = ii + 1; break; } } - OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[ti], ck) + OS << "case ARM::BI__builtin_neon_" << MangleName(name, TypeVec[ti], ck) << ": i = " << immidx << "; " << rangestr << "; break;\n"; } } OS << "#endif\n\n"; } + +/// GenTest - Write out a test for the intrinsic specified by the name and +/// type strings, including the embedded patterns for FileCheck to match. +static std::string GenTest(const std::string &name, + const std::string &proto, + StringRef outTypeStr, StringRef inTypeStr, + bool isShift) { + assert(!proto.empty() && ""); + std::string s; + + // Function name with type suffix + std::string mangledName = MangleName(name, outTypeStr, ClassS); + if (outTypeStr != inTypeStr) { + // If the input type is different (e.g., for vreinterpret), append a suffix + // for the input type. String off a "Q" (quad) prefix so that MangleName + // does not insert another "q" in the name. + unsigned typeStrOff = (inTypeStr[0] == 'Q' ? 1 : 0); + StringRef inTypeNoQuad = inTypeStr.substr(typeStrOff); + mangledName = MangleName(mangledName, inTypeNoQuad, ClassS); + } + + // Emit the FileCheck patterns. + s += "// CHECK: test_" + mangledName + "\n"; + // s += "// CHECK: \n"; // FIXME: + expected instruction opcode. + + // Emit the start of the test function. + s += TypeString(proto[0], outTypeStr) + " test_" + mangledName + "("; + char arg = 'a'; + std::string comma; + for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) { + // Do not create arguments for values that must be immediate constants. + if (proto[i] == 'i') + continue; + s += comma + TypeString(proto[i], inTypeStr) + " "; + s.push_back(arg); + comma = ", "; + } + s += ") { \\\n "; + + if (proto[0] != 'v') + s += "return "; + s += mangledName + "("; + arg = 'a'; + for (unsigned i = 1, e = proto.size(); i != e; ++i, ++arg) { + if (proto[i] == 'i') { + // For immediate operands, test the maximum value. + if (isShift) + s += "1"; // FIXME + else + // The immediate generally refers to a lane in the preceding argument. + s += utostr(RangeFromType(proto[i-1], inTypeStr)); + } else { + s.push_back(arg); + } + if ((i + 1) < e) + s += ", "; + } + s += ");\n}\n\n"; + return s; +} + +/// runTests - Write out a complete set of tests for all of the Neon +/// intrinsics. +void NeonEmitter::runTests(raw_ostream &OS) { + OS << + "// RUN: %clang_cc1 -triple thumbv7-apple-darwin \\\n" + "// RUN: -target-cpu cortex-a9 -ffreestanding -S -o - %s | FileCheck %s\n" + "\n" + "#include <arm_neon.h>\n" + "\n"; + + std::vector<Record*> RV = Records.getAllDerivedDefinitions("Inst"); + for (unsigned i = 0, e = RV.size(); i != e; ++i) { + Record *R = RV[i]; + std::string name = R->getValueAsString("Name"); + std::string Proto = R->getValueAsString("Prototype"); + std::string Types = R->getValueAsString("Types"); + bool isShift = R->getValueAsBit("isShift"); + + SmallVector<StringRef, 16> TypeVec; + ParseTypes(R, Types, TypeVec); + + OpKind kind = OpMap[R->getValueAsDef("Operand")->getName()]; + for (unsigned ti = 0, te = TypeVec.size(); ti != te; ++ti) { + if (kind == OpReinterpret) { + bool outQuad = false; + bool dummy = false; + (void)ClassifyType(TypeVec[ti], outQuad, dummy, dummy); + for (unsigned srcti = 0, srcte = TypeVec.size(); + srcti != srcte; ++srcti) { + bool inQuad = false; + (void)ClassifyType(TypeVec[srcti], inQuad, dummy, dummy); + if (srcti == ti || inQuad != outQuad) + continue; + OS << GenTest(name, Proto, TypeVec[ti], TypeVec[srcti], isShift); + } + } else { + OS << GenTest(name, Proto, TypeVec[ti], TypeVec[ti], isShift); + } + } + OS << "\n"; + } +} + diff --git a/utils/TableGen/NeonEmitter.h b/utils/TableGen/NeonEmitter.h index 6c6760d..1e6fcbf 100644 --- a/utils/TableGen/NeonEmitter.h +++ b/utils/TableGen/NeonEmitter.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // This tablegen backend is responsible for emitting arm_neon.h, which includes -// a declaration and definition of each function specified by the ARM NEON +// a declaration and definition of each function specified by the ARM NEON // compiler interface. See ARM document DUI0348B. // //===----------------------------------------------------------------------===// @@ -24,13 +24,34 @@ enum OpKind { OpNone, OpAdd, + OpAddl, + OpAddw, OpSub, + OpSubl, + OpSubw, OpMul, + OpMull, OpMla, + OpMlal, OpMls, + OpMlsl, OpMulN, + OpMullN, OpMlaN, OpMlsN, + OpMlalN, + OpMlslN, + OpMulLane, + OpMullLane, + OpMlaLane, + OpMlsLane, + OpMlalLane, + OpMlslLane, + OpQDMullLane, + OpQDMlalLane, + OpQDMlslLane, + OpQDMulhLane, + OpQRDMulhLane, OpEq, OpGe, OpLe, @@ -46,40 +67,66 @@ enum OpKind { OpCast, OpConcat, OpDup, + OpDupLane, OpHi, OpLo, OpSelect, OpRev16, OpRev32, - OpRev64 + OpRev64, + OpReinterpret, + OpAbdl, + OpAba, + OpAbal }; enum ClassKind { ClassNone, - ClassI, - ClassS, - ClassW, - ClassB + ClassI, // generic integer instruction, e.g., "i8" suffix + ClassS, // signed/unsigned/poly, e.g., "s8", "u8" or "p8" suffix + ClassW, // width-specific instruction, e.g., "8" suffix + ClassB // bitcast arguments with enum argument to specify type }; namespace llvm { - + class NeonEmitter : public TableGenBackend { RecordKeeper &Records; StringMap<OpKind> OpMap; DenseMap<Record*, ClassKind> ClassMap; - + public: NeonEmitter(RecordKeeper &R) : Records(R) { OpMap["OP_NONE"] = OpNone; OpMap["OP_ADD"] = OpAdd; + OpMap["OP_ADDL"] = OpAddl; + OpMap["OP_ADDW"] = OpAddw; OpMap["OP_SUB"] = OpSub; + OpMap["OP_SUBL"] = OpSubl; + OpMap["OP_SUBW"] = OpSubw; OpMap["OP_MUL"] = OpMul; + OpMap["OP_MULL"] = OpMull; OpMap["OP_MLA"] = OpMla; + OpMap["OP_MLAL"] = OpMlal; OpMap["OP_MLS"] = OpMls; + OpMap["OP_MLSL"] = OpMlsl; OpMap["OP_MUL_N"] = OpMulN; + OpMap["OP_MULL_N"]= OpMullN; OpMap["OP_MLA_N"] = OpMlaN; OpMap["OP_MLS_N"] = OpMlsN; + OpMap["OP_MLAL_N"] = OpMlalN; + OpMap["OP_MLSL_N"] = OpMlslN; + OpMap["OP_MUL_LN"]= OpMulLane; + OpMap["OP_MULL_LN"] = OpMullLane; + OpMap["OP_MLA_LN"]= OpMlaLane; + OpMap["OP_MLS_LN"]= OpMlsLane; + OpMap["OP_MLAL_LN"] = OpMlalLane; + OpMap["OP_MLSL_LN"] = OpMlslLane; + OpMap["OP_QDMULL_LN"] = OpQDMullLane; + OpMap["OP_QDMLAL_LN"] = OpQDMlalLane; + OpMap["OP_QDMLSL_LN"] = OpQDMlslLane; + OpMap["OP_QDMULH_LN"] = OpQDMulhLane; + OpMap["OP_QRDMULH_LN"] = OpQRDMulhLane; OpMap["OP_EQ"] = OpEq; OpMap["OP_GE"] = OpGe; OpMap["OP_LE"] = OpLe; @@ -97,10 +144,15 @@ namespace llvm { OpMap["OP_HI"] = OpHi; OpMap["OP_LO"] = OpLo; OpMap["OP_DUP"] = OpDup; + OpMap["OP_DUP_LN"] = OpDupLane; OpMap["OP_SEL"] = OpSelect; OpMap["OP_REV16"] = OpRev16; OpMap["OP_REV32"] = OpRev32; OpMap["OP_REV64"] = OpRev64; + OpMap["OP_REINT"] = OpReinterpret; + OpMap["OP_ABDL"] = OpAbdl; + OpMap["OP_ABA"] = OpAba; + OpMap["OP_ABAL"] = OpAbal; Record *SI = R.getClass("SInst"); Record *II = R.getClass("IInst"); @@ -109,14 +161,20 @@ namespace llvm { ClassMap[II] = ClassI; ClassMap[WI] = ClassW; } - + // run - Emit arm_neon.h.inc void run(raw_ostream &o); // runHeader - Emit all the __builtin prototypes used in arm_neon.h void runHeader(raw_ostream &o); + + // runTests - Emit tests for all the Neon intrinsics. + void runTests(raw_ostream &o); + + private: + void emitIntrinsic(raw_ostream &OS, Record *R); }; - + } // End llvm namespace #endif diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp index dc79358..abbbafe 100644 --- a/utils/TableGen/Record.cpp +++ b/utils/TableGen/Record.cpp @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #include "Record.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/Format.h" #include "llvm/ADT/StringExtras.h" @@ -59,26 +59,34 @@ Init *BitsRecTy::convertValue(UnsetInit *UI) { } Init *BitsRecTy::convertValue(BitInit *UI) { - if (Size != 1) return 0; // Can only convert single bit... + if (Size != 1) return 0; // Can only convert single bit. BitsInit *Ret = new BitsInit(1); Ret->setBit(0, UI); return Ret; } -// convertValue from Int initializer to bits type: Split the integer up into the -// appropriate bits... -// -Init *BitsRecTy::convertValue(IntInit *II) { - int64_t Value = II->getValue(); - // Make sure this bitfield is large enough to hold the integer value... +/// canFitInBitfield - Return true if the number of bits is large enough to hold +/// the integer value. +static bool canFitInBitfield(int64_t Value, unsigned NumBits) { if (Value >= 0) { - if (Value & ~((1LL << Size)-1)) - return 0; - } else { - if ((Value >> Size) != -1 || ((Value & (1LL << (Size-1))) == 0)) - return 0; + if (Value & ~((1LL << NumBits) - 1)) + return false; + } else if ((Value >> NumBits) != -1 || (Value & (1LL << (NumBits-1))) == 0) { + return false; } + return true; +} + +/// convertValue from Int initializer to bits type: Split the integer up into the +/// appropriate bits. +/// +Init *BitsRecTy::convertValue(IntInit *II) { + int64_t Value = II->getValue(); + // Make sure this bitfield is large enough to hold the integer value. + if (!canFitInBitfield(Value, Size)) + return 0; + BitsInit *Ret = new BitsInit(Size); for (unsigned i = 0; i != Size; ++i) Ret->setBit(i, new BitInit(Value & (1LL << i))); @@ -88,7 +96,7 @@ Init *BitsRecTy::convertValue(IntInit *II) { Init *BitsRecTy::convertValue(BitsInit *BI) { // If the number of bits is right, return it. Otherwise we need to expand or - // truncate... + // truncate. if (BI->getNumBits() == Size) return BI; return 0; } @@ -101,12 +109,56 @@ Init *BitsRecTy::convertValue(TypedInit *VI) { Ret->setBit(i, new VarBitInit(VI, i)); return Ret; } + if (Size == 1 && dynamic_cast<BitRecTy*>(VI->getType())) { BitsInit *Ret = new BitsInit(1); Ret->setBit(0, VI); return Ret; } + if (TernOpInit *Tern = dynamic_cast<TernOpInit*>(VI)) { + if (Tern->getOpcode() == TernOpInit::IF) { + Init *LHS = Tern->getLHS(); + Init *MHS = Tern->getMHS(); + Init *RHS = Tern->getRHS(); + + IntInit *MHSi = dynamic_cast<IntInit*>(MHS); + IntInit *RHSi = dynamic_cast<IntInit*>(RHS); + + if (MHSi && RHSi) { + int64_t MHSVal = MHSi->getValue(); + int64_t RHSVal = RHSi->getValue(); + + if (canFitInBitfield(MHSVal, Size) && canFitInBitfield(RHSVal, Size)) { + BitsInit *Ret = new BitsInit(Size); + + for (unsigned i = 0; i != Size; ++i) + Ret->setBit(i, new TernOpInit(TernOpInit::IF, LHS, + new IntInit((MHSVal & (1LL << i)) ? 1 : 0), + new IntInit((RHSVal & (1LL << i)) ? 1 : 0), + VI->getType())); + + return Ret; + } + } else { + BitsInit *MHSbs = dynamic_cast<BitsInit*>(MHS); + BitsInit *RHSbs = dynamic_cast<BitsInit*>(RHS); + + if (MHSbs && RHSbs) { + BitsInit *Ret = new BitsInit(Size); + + for (unsigned i = 0; i != Size; ++i) + Ret->setBit(i, new TernOpInit(TernOpInit::IF, LHS, + MHSbs->getBit(i), + RHSbs->getBit(i), + VI->getType())); + + return Ret; + } + } + } + } + return 0; } @@ -152,16 +204,6 @@ Init *StringRecTy::convertValue(BinOpInit *BO) { return new BinOpInit(BinOpInit::STRCONCAT, L, R, new StringRecTy); return BO; } - if (BO->getOpcode() == BinOpInit::NAMECONCAT) { - if (BO->getType()->getAsString() == getAsString()) { - Init *L = BO->getLHS()->convertInitializerTo(this); - Init *R = BO->getRHS()->convertInitializerTo(this); - if (L == 0 || R == 0) return 0; - if (L != BO->getLHS() || R != BO->getRHS()) - return new BinOpInit(BinOpInit::NAMECONCAT, L, R, new StringRecTy); - return BO; - } - } return convertValue((TypedInit*)BO); } @@ -236,16 +278,6 @@ Init *DagRecTy::convertValue(BinOpInit *BO) { return new BinOpInit(BinOpInit::CONCAT, L, R, new DagRecTy); return BO; } - if (BO->getOpcode() == BinOpInit::NAMECONCAT) { - if (BO->getType()->getAsString() == getAsString()) { - Init *L = BO->getLHS()->convertInitializerTo(this); - Init *R = BO->getRHS()->convertInitializerTo(this); - if (L == 0 || R == 0) return 0; - if (L != BO->getLHS() || R != BO->getRHS()) - return new BinOpInit(BinOpInit::CONCAT, L, R, new DagRecTy); - return BO; - } - } return 0; } @@ -518,9 +550,8 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { // From TGParser::ParseIDValue if (CurRec) { if (const RecordVal *RV = CurRec->getValue(Name)) { - if (RV->getType() != getType()) { - throw "type mismatch in nameconcat"; - } + if (RV->getType() != getType()) + throw "type mismatch in cast"; return new VarInit(Name, RV->getType()); } @@ -529,9 +560,8 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { const RecordVal *RV = CurRec->getValue(TemplateArgName); assert(RV && "Template arg doesn't exist??"); - if (RV->getType() != getType()) { - throw "type mismatch in nameconcat"; - } + if (RV->getType() != getType()) + throw "type mismatch in cast"; return new VarInit(TemplateArgName, RV->getType()); } @@ -543,15 +573,14 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { const RecordVal *RV = CurMultiClass->Rec.getValue(MCName); assert(RV && "Template arg doesn't exist??"); - if (RV->getType() != getType()) { - throw "type mismatch in nameconcat"; - } + if (RV->getType() != getType()) + throw "type mismatch in cast"; return new VarInit(MCName, RV->getType()); } } - if (Record *D = Records.getDef(Name)) + if (Record *D = (CurRec->getRecords()).getDef(Name)) return new DefInit(D); errs() << "Variable not defined: '" + Name + "'\n"; @@ -561,7 +590,7 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { } break; } - case CAR: { + case HEAD: { ListInit *LHSl = dynamic_cast<ListInit*>(LHS); if (LHSl) { if (LHSl->getSize() == 0) { @@ -572,7 +601,7 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { } break; } - case CDR: { + case TAIL: { ListInit *LHSl = dynamic_cast<ListInit*>(LHS); if (LHSl) { if (LHSl->getSize() == 0) { @@ -585,7 +614,7 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { } break; } - case LNULL: { + case EMPTY: { ListInit *LHSl = dynamic_cast<ListInit*>(LHS); if (LHSl) { if (LHSl->getSize() == 0) { @@ -621,9 +650,9 @@ std::string UnOpInit::getAsString() const { std::string Result; switch (Opc) { case CAST: Result = "!cast<" + getType()->getAsString() + ">"; break; - case CAR: Result = "!car"; break; - case CDR: Result = "!cdr"; break; - case LNULL: Result = "!null"; break; + case HEAD: Result = "!head"; break; + case TAIL: Result = "!tail"; break; + case EMPTY: Result = "!empty"; break; } return Result + "(" + LHS->getAsString() + ")"; } @@ -660,57 +689,6 @@ Init *BinOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) { return new StringInit(LHSs->getValue() + RHSs->getValue()); break; } - case NAMECONCAT: { - StringInit *LHSs = dynamic_cast<StringInit*>(LHS); - StringInit *RHSs = dynamic_cast<StringInit*>(RHS); - if (LHSs && RHSs) { - std::string Name(LHSs->getValue() + RHSs->getValue()); - - // From TGParser::ParseIDValue - if (CurRec) { - if (const RecordVal *RV = CurRec->getValue(Name)) { - if (RV->getType() != getType()) { - throw "type mismatch in nameconcat"; - } - return new VarInit(Name, RV->getType()); - } - - std::string TemplateArgName = CurRec->getName()+":"+Name; - if (CurRec->isTemplateArg(TemplateArgName)) { - const RecordVal *RV = CurRec->getValue(TemplateArgName); - assert(RV && "Template arg doesn't exist??"); - - if (RV->getType() != getType()) { - throw "type mismatch in nameconcat"; - } - - return new VarInit(TemplateArgName, RV->getType()); - } - } - - if (CurMultiClass) { - std::string MCName = CurMultiClass->Rec.getName()+"::"+Name; - if (CurMultiClass->Rec.isTemplateArg(MCName)) { - const RecordVal *RV = CurMultiClass->Rec.getValue(MCName); - assert(RV && "Template arg doesn't exist??"); - - if (RV->getType() != getType()) { - throw "type mismatch in nameconcat"; - } - - return new VarInit(MCName, RV->getType()); - } - } - - if (Record *D = Records.getDef(Name)) - return new DefInit(D); - - errs() << "Variable not defined in !nameconcat: '" + Name + "'\n"; - assert(0 && "Variable not found in !nameconcat"); - return 0; - } - break; - } case EQ: { // try to fold eq comparison for 'bit' and 'int', otherwise fallback // to string objects. @@ -771,8 +749,6 @@ std::string BinOpInit::getAsString() const { case SRL: Result = "!srl"; break; case EQ: Result = "!eq"; break; case STRCONCAT: Result = "!strconcat"; break; - case NAMECONCAT: - Result = "!nameconcat<" + getType()->getAsString() + ">"; break; } return Result + "(" + LHS->getAsString() + ", " + RHS->getAsString() + ")"; } @@ -1042,7 +1018,7 @@ RecTy *TypedInit::getFieldType(const std::string &FieldName) const { Init *TypedInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) { BitsRecTy *T = dynamic_cast<BitsRecTy*>(getType()); - if (T == 0) return 0; // Cannot subscript a non-bits variable... + if (T == 0) return 0; // Cannot subscript a non-bits variable. unsigned NumBits = T->getNumBits(); BitsInit *BI = new BitsInit(Bits.size()); @@ -1058,7 +1034,7 @@ Init *TypedInit::convertInitializerBitRange(const std::vector<unsigned> &Bits) { Init *TypedInit::convertInitListSlice(const std::vector<unsigned> &Elements) { ListRecTy *T = dynamic_cast<ListRecTy*>(getType()); - if (T == 0) return 0; // Cannot subscript a non-list variable... + if (T == 0) return 0; // Cannot subscript a non-list variable. if (Elements.size() == 1) return new VarListElementInit(this, Elements[0]); @@ -1211,7 +1187,7 @@ Init *FieldInit::resolveBitReference(Record &R, const RecordVal *RV, assert(Bit < BI->getNumBits() && "Bit reference out of range!"); Init *B = BI->getBit(Bit); - if (dynamic_cast<BitInit*>(B)) // If the bit is set... + if (dynamic_cast<BitInit*>(B)) // If the bit is set. return B; // Replace the VarBitInit with it. } return 0; @@ -1303,14 +1279,14 @@ void RecordVal::print(raw_ostream &OS, bool PrintSem) const { unsigned Record::LastID = 0; void Record::setName(const std::string &Name) { - if (Records.getDef(getName()) == this) { - Records.removeDef(getName()); + if (TrackedRecords.getDef(getName()) == this) { + TrackedRecords.removeDef(getName()); this->Name = Name; - Records.addDef(this); + TrackedRecords.addDef(this); } else { - Records.removeClass(getName()); + TrackedRecords.removeClass(getName()); this->Name = Name; - Records.addClass(this); + TrackedRecords.addClass(this); } } @@ -1573,7 +1549,7 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const RecordKeeper &RK) { /// name does not exist, an error is printed and true is returned. std::vector<Record*> RecordKeeper::getAllDerivedDefinitions(const std::string &ClassName) const { - Record *Class = Records.getClass(ClassName); + Record *Class = getClass(ClassName); if (!Class) throw "ERROR: Couldn't find the `" + ClassName + "' class!\n"; diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h index d6f37ee..f3a5df2 100644 --- a/utils/TableGen/Record.h +++ b/utils/TableGen/Record.h @@ -16,7 +16,7 @@ #define RECORD_H #include "llvm/Support/SourceMgr.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/Support/raw_ostream.h" #include <map> @@ -57,6 +57,7 @@ class VarListElementInit; class Record; class RecordVal; struct MultiClass; +class RecordKeeper; //===----------------------------------------------------------------------===// // Type Classes @@ -810,7 +811,7 @@ public: /// class UnOpInit : public OpInit { public: - enum UnaryOp { CAST, CAR, CDR, LNULL }; + enum UnaryOp { CAST, HEAD, TAIL, EMPTY }; private: UnaryOp Opc; Init *LHS; @@ -848,7 +849,7 @@ public: /// class BinOpInit : public OpInit { public: - enum BinaryOp { SHL, SRA, SRL, STRCONCAT, CONCAT, NAMECONCAT, EQ }; + enum BinaryOp { SHL, SRA, SRL, STRCONCAT, CONCAT, EQ }; private: BinaryOp Opc; Init *LHS, *RHS; @@ -930,6 +931,8 @@ public: // possible to fold. Init *Fold(Record *CurRec, MultiClass *CurMultiClass); + virtual bool isComplete() const { return false; } + virtual Init *resolveReferences(Record &R, const RecordVal *RV); virtual std::string getAsString() const; @@ -1227,16 +1230,21 @@ class Record { std::vector<std::string> TemplateArgs; std::vector<RecordVal> Values; std::vector<Record*> SuperClasses; + + // Tracks Record instances. Not owned by Record. + RecordKeeper &TrackedRecords; + public: - explicit Record(const std::string &N, SMLoc loc) : - ID(LastID++), Name(N), Loc(loc) {} + // Constructs a record. + explicit Record(const std::string &N, SMLoc loc, RecordKeeper &records) : + ID(LastID++), Name(N), Loc(loc), TrackedRecords(records) {} ~Record() {} - + static unsigned getNewUID() { return LastID++; } - - + + unsigned getID() const { return ID; } const std::string &getName() const { return Name; } @@ -1315,6 +1323,10 @@ public: /// possible references. void resolveReferencesTo(const RecordVal *RV); + RecordKeeper &getRecords() const { + return TrackedRecords; + } + void dump() const; //===--------------------------------------------------------------------===// @@ -1350,9 +1362,9 @@ public: /// std::vector<Record*> getValueAsListOfDefs(StringRef FieldName) const; - /// getValueAsListOfInts - This method looks up the specified field and returns - /// its value as a vector of integers, throwing an exception if the field does - /// not exist or if the value is not the right type. + /// getValueAsListOfInts - This method looks up the specified field and + /// returns its value as a vector of integers, throwing an exception if the + /// field does not exist or if the value is not the right type. /// std::vector<int64_t> getValueAsListOfInts(StringRef FieldName) const; @@ -1396,7 +1408,8 @@ struct MultiClass { void dump() const; - MultiClass(const std::string &Name, SMLoc Loc) : Rec(Name, Loc) {} + MultiClass(const std::string &Name, SMLoc Loc, RecordKeeper &Records) : + Rec(Name, Loc, Records) {} }; class RecordKeeper { @@ -1453,7 +1466,6 @@ public: std::vector<Record*> getAllDerivedDefinitions(const std::string &ClassName) const; - void dump() const; }; @@ -1488,9 +1500,7 @@ public: raw_ostream &operator<<(raw_ostream &OS, const RecordKeeper &RK); -extern RecordKeeper Records; - -void PrintError(SMLoc ErrorLoc, const std::string &Msg); +void PrintError(SMLoc ErrorLoc, const Twine &Msg); } // End llvm namespace diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 6f06705..96399a4 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -25,7 +25,7 @@ using namespace llvm; // runEnums - Print out enum values for all of the registers. void RegisterInfoEmitter::runEnums(raw_ostream &OS) { - CodeGenTarget Target; + CodeGenTarget Target(Records); const std::vector<CodeGenRegister> &Registers = Target.getRegisters(); std::string Namespace = Registers[0].TheDef->getValueAsString("Namespace"); @@ -63,7 +63,7 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS) { void RegisterInfoEmitter::runHeader(raw_ostream &OS) { EmitSourceFileHeader("Register Information Header Fragment", OS); - CodeGenTarget Target; + CodeGenTarget Target(Records); const std::string &TargetName = Target.getName(); std::string ClassName = TargetName + "GenRegisterInfo"; @@ -333,7 +333,7 @@ public: // RegisterInfoEmitter::run - Main register file description emitter. // void RegisterInfoEmitter::run(raw_ostream &OS) { - CodeGenTarget Target; + CodeGenTarget Target(Records); EmitSourceFileHeader("Register Information Source Fragment", OS); OS << "namespace llvm {\n\n"; @@ -777,17 +777,13 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { delete [] AliasesHashTable; if (!RegisterAliases.empty()) - OS << "\n\n // Register Alias Sets...\n"; + OS << "\n\n // Register Overlap Lists...\n"; - // Emit the empty alias list - OS << " const unsigned Empty_AliasSet[] = { 0 };\n"; - // Loop over all of the registers which have aliases, emitting the alias list - // to memory. + // Emit an overlap list for all registers. for (std::map<Record*, std::set<Record*>, LessRecord >::iterator I = RegisterAliases.begin(), E = RegisterAliases.end(); I != E; ++I) { - if (I->second.empty()) - continue; - OS << " const unsigned " << I->first->getName() << "_AliasSet[] = { "; + OS << " const unsigned " << I->first->getName() << "_Overlaps[] = { " + << getQualifiedName(I->first) << ", "; for (std::set<Record*>::iterator ASI = I->second.begin(), E = I->second.end(); ASI != E; ++ASI) OS << getQualifiedName(*ASI) << ", "; @@ -849,11 +845,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { for (unsigned i = 0, e = Regs.size(); i != e; ++i) { const CodeGenRegister &Reg = Regs[i]; OS << " { \""; - OS << Reg.getName() << "\",\t"; - if (!RegisterAliases[Reg.TheDef].empty()) - OS << Reg.getName() << "_AliasSet,\t"; - else - OS << "Empty_AliasSet,\t"; + OS << Reg.getName() << "\",\t" << Reg.getName() << "_Overlaps,\t"; if (!RegisterSubRegs[Reg.TheDef].empty()) OS << Reg.getName() << "_SubRegsSet,\t"; else diff --git a/utils/TableGen/StringMatcher.cpp b/utils/TableGen/StringMatcher.cpp new file mode 100644 index 0000000..6aedcbf --- /dev/null +++ b/utils/TableGen/StringMatcher.cpp @@ -0,0 +1,149 @@ +//===- StringMatcher.cpp - Generate a matcher for input strings -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the StringMatcher class. +// +//===----------------------------------------------------------------------===// + +#include "StringMatcher.h" +#include "llvm/Support/raw_ostream.h" +#include <map> +using namespace llvm; + +/// FindFirstNonCommonLetter - Find the first character in the keys of the +/// string pairs that is not shared across the whole set of strings. All +/// strings are assumed to have the same length. +static unsigned +FindFirstNonCommonLetter(const std::vector<const + StringMatcher::StringPair*> &Matches) { + assert(!Matches.empty()); + for (unsigned i = 0, e = Matches[0]->first.size(); i != e; ++i) { + // Check to see if letter i is the same across the set. + char Letter = Matches[0]->first[i]; + + for (unsigned str = 0, e = Matches.size(); str != e; ++str) + if (Matches[str]->first[i] != Letter) + return i; + } + + return Matches[0]->first.size(); +} + +/// EmitStringMatcherForChar - Given a set of strings that are known to be the +/// same length and whose characters leading up to CharNo are the same, emit +/// code to verify that CharNo and later are the same. +/// +/// \return - True if control can leave the emitted code fragment. +bool StringMatcher:: +EmitStringMatcherForChar(const std::vector<const StringPair*> &Matches, + unsigned CharNo, unsigned IndentCount) const { + assert(!Matches.empty() && "Must have at least one string to match!"); + std::string Indent(IndentCount*2+4, ' '); + + // If we have verified that the entire string matches, we're done: output the + // matching code. + if (CharNo == Matches[0]->first.size()) { + assert(Matches.size() == 1 && "Had duplicate keys to match on"); + + // If the to-execute code has \n's in it, indent each subsequent line. + StringRef Code = Matches[0]->second; + + std::pair<StringRef, StringRef> Split = Code.split('\n'); + OS << Indent << Split.first << "\t // \"" << Matches[0]->first << "\"\n"; + + Code = Split.second; + while (!Code.empty()) { + Split = Code.split('\n'); + OS << Indent << Split.first << "\n"; + Code = Split.second; + } + return false; + } + + // Bucket the matches by the character we are comparing. + std::map<char, std::vector<const StringPair*> > MatchesByLetter; + + for (unsigned i = 0, e = Matches.size(); i != e; ++i) + MatchesByLetter[Matches[i]->first[CharNo]].push_back(Matches[i]); + + + // If we have exactly one bucket to match, see how many characters are common + // across the whole set and match all of them at once. + if (MatchesByLetter.size() == 1) { + unsigned FirstNonCommonLetter = FindFirstNonCommonLetter(Matches); + unsigned NumChars = FirstNonCommonLetter-CharNo; + + // Emit code to break out if the prefix doesn't match. + if (NumChars == 1) { + // Do the comparison with if (Str[1] != 'f') + // FIXME: Need to escape general characters. + OS << Indent << "if (" << StrVariableName << "[" << CharNo << "] != '" + << Matches[0]->first[CharNo] << "')\n"; + OS << Indent << " break;\n"; + } else { + // Do the comparison with if (Str.substr(1, 3) != "foo"). + // FIXME: Need to escape general strings. + OS << Indent << "if (" << StrVariableName << ".substr(" << CharNo << ", " + << NumChars << ") != \""; + OS << Matches[0]->first.substr(CharNo, NumChars) << "\")\n"; + OS << Indent << " break;\n"; + } + + return EmitStringMatcherForChar(Matches, FirstNonCommonLetter, IndentCount); + } + + // Otherwise, we have multiple possible things, emit a switch on the + // character. + OS << Indent << "switch (" << StrVariableName << "[" << CharNo << "]) {\n"; + OS << Indent << "default: break;\n"; + + for (std::map<char, std::vector<const StringPair*> >::iterator LI = + MatchesByLetter.begin(), E = MatchesByLetter.end(); LI != E; ++LI) { + // TODO: escape hard stuff (like \n) if we ever care about it. + OS << Indent << "case '" << LI->first << "':\t // " + << LI->second.size() << " string"; + if (LI->second.size() != 1) OS << 's'; + OS << " to match.\n"; + if (EmitStringMatcherForChar(LI->second, CharNo+1, IndentCount+1)) + OS << Indent << " break;\n"; + } + + OS << Indent << "}\n"; + return true; +} + + +/// Emit - Top level entry point. +/// +void StringMatcher::Emit(unsigned Indent) const { + // If nothing to match, just fall through. + if (Matches.empty()) return; + + // First level categorization: group strings by length. + std::map<unsigned, std::vector<const StringPair*> > MatchesByLength; + + for (unsigned i = 0, e = Matches.size(); i != e; ++i) + MatchesByLength[Matches[i].first.size()].push_back(&Matches[i]); + + // Output a switch statement on length and categorize the elements within each + // bin. + OS.indent(Indent*2+2) << "switch (" << StrVariableName << ".size()) {\n"; + OS.indent(Indent*2+2) << "default: break;\n"; + + for (std::map<unsigned, std::vector<const StringPair*> >::iterator LI = + MatchesByLength.begin(), E = MatchesByLength.end(); LI != E; ++LI) { + OS.indent(Indent*2+2) << "case " << LI->first << ":\t // " + << LI->second.size() + << " string" << (LI->second.size() == 1 ? "" : "s") << " to match.\n"; + if (EmitStringMatcherForChar(LI->second, 0, Indent)) + OS.indent(Indent*2+4) << "break;\n"; + } + + OS.indent(Indent*2+2) << "}\n"; +} diff --git a/utils/TableGen/StringMatcher.h b/utils/TableGen/StringMatcher.h new file mode 100644 index 0000000..1dadc76 --- /dev/null +++ b/utils/TableGen/StringMatcher.h @@ -0,0 +1,54 @@ +//===- StringMatcher.h - Generate a matcher for input strings ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the StringMatcher class. +// +//===----------------------------------------------------------------------===// + +#ifndef STRINGMATCHER_H +#define STRINGMATCHER_H + +#include <vector> +#include <string> +#include <utility> +#include "llvm/ADT/StringRef.h" + +namespace llvm { + class raw_ostream; + +/// StringMatcher - Given a list of strings and code to execute when they match, +/// output a simple switch tree to classify the input string. +/// +/// If a match is found, the code in Vals[i].second is executed; control must +/// not exit this code fragment. If nothing matches, execution falls through. +/// +class StringMatcher { +public: + typedef std::pair<std::string, std::string> StringPair; +private: + StringRef StrVariableName; + const std::vector<StringPair> &Matches; + raw_ostream &OS; + +public: + StringMatcher(StringRef strVariableName, + const std::vector<StringPair> &matches, raw_ostream &os) + : StrVariableName(strVariableName), Matches(matches), OS(os) {} + + void Emit(unsigned Indent = 0) const; + + +private: + bool EmitStringMatcherForChar(const std::vector<const StringPair*> &Matches, + unsigned CharNo, unsigned IndentCount) const; +}; + +} // end llvm namespace. + +#endif diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index b04eaf8..e35bdca 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -172,13 +172,10 @@ void SubtargetEmitter::CPUKeyValues(raw_ostream &OS) { // CollectAllItinClasses - Gathers and enumerates all the itinerary classes. // Returns itinerary class count. // -unsigned SubtargetEmitter::CollectAllItinClasses(raw_ostream &OS, - std::map<std::string, unsigned> &ItinClassesMap) { - // Gather and sort all itinerary classes - std::vector<Record*> ItinClassList = - Records.getAllDerivedDefinitions("InstrItinClass"); - std::sort(ItinClassList.begin(), ItinClassList.end(), LessRecord()); - +unsigned SubtargetEmitter:: +CollectAllItinClasses(raw_ostream &OS, + std::map<std::string, unsigned> &ItinClassesMap, + std::vector<Record*> &ItinClassList) { // For each itinerary class unsigned N = ItinClassList.size(); for (unsigned i = 0; i < N; i++) { @@ -265,13 +262,32 @@ void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData, } } +void SubtargetEmitter::FormItineraryBypassString(const std::string &Name, + Record *ItinData, + std::string &ItinString, + unsigned NOperandCycles) { + const std::vector<Record*> &BypassList = + ItinData->getValueAsListOfDefs("Bypasses"); + unsigned N = BypassList.size(); + unsigned i = 0; + for (; i < N;) { + ItinString += Name + "Bypass::" + BypassList[i]->getName(); + if (++i < NOperandCycles) ItinString += ", "; + } + for (; i < NOperandCycles;) { + ItinString += " 0"; + if (++i < NOperandCycles) ItinString += ", "; + } +} + // // EmitStageAndOperandCycleData - Generate unique itinerary stages and // operand cycle tables. Record itineraries for processors. // void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, unsigned NItinClasses, - std::map<std::string, unsigned> &ItinClassesMap, + std::map<std::string, unsigned> &ItinClassesMap, + std::vector<Record*> &ItinClassList, std::vector<std::vector<InstrItinerary> > &ProcList) { // Gather processor iteraries std::vector<Record*> ProcItinList = @@ -298,6 +314,19 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, << " = 1 << " << j << ";\n"; OS << "}\n"; + + std::vector<Record*> BPs = Proc->getValueAsListOfDefs("BP"); + if (BPs.size()) { + OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name + << "\"\n" << "namespace " << Name << "Bypass {\n"; + + OS << " const unsigned NoBypass = 0;\n"; + for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j) + OS << " const unsigned " << BPs[j]->getName() + << " = 1 << " << j << ";\n"; + + OS << "}\n"; + } } // Begin stages table @@ -307,10 +336,14 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, // Begin operand cycle table std::string OperandCycleTable = "static const unsigned OperandCycles[] = {\n"; OperandCycleTable += " 0, // No itinerary\n"; + + // Begin pipeline bypass table + std::string BypassTable = "static const unsigned ForwardingPathes[] = {\n"; + BypassTable += " 0, // No itinerary\n"; unsigned StageCount = 1, OperandCycleCount = 1; unsigned ItinStageEnum = 1, ItinOperandCycleEnum = 1; - std::map<std::string, unsigned> ItinStageMap, ItinOperandCycleMap; + std::map<std::string, unsigned> ItinStageMap, ItinOperandMap; for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) { // Next record Record *Proc = ProcItinList[i]; @@ -344,6 +377,10 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, FormItineraryOperandCycleString(ItinData, ItinOperandCycleString, NOperandCycles); + std::string ItinBypassString; + FormItineraryBypassString(Name, ItinData, ItinBypassString, + NOperandCycles); + // Check to see if stage already exists and create if it doesn't unsigned FindStage = 0; if (NStages > 0) { @@ -361,27 +398,35 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, // Check to see if operand cycle already exists and create if it doesn't unsigned FindOperandCycle = 0; if (NOperandCycles > 0) { - FindOperandCycle = ItinOperandCycleMap[ItinOperandCycleString]; + std::string ItinOperandString = ItinOperandCycleString+ItinBypassString; + FindOperandCycle = ItinOperandMap[ItinOperandString]; if (FindOperandCycle == 0) { // Emit as cycle, // index OperandCycleTable += ItinOperandCycleString + ", // " + itostr(ItinOperandCycleEnum) + "\n"; // Record Itin class number. - ItinOperandCycleMap[ItinOperandCycleString] = + ItinOperandMap[ItinOperandCycleString] = FindOperandCycle = OperandCycleCount; + + // Emit as bypass, // index + BypassTable += ItinBypassString + ", // " + + itostr(ItinOperandCycleEnum) + "\n"; + OperandCycleCount += NOperandCycles; ItinOperandCycleEnum++; } } - // Set up itinerary as location and location + stage count - InstrItinerary Intinerary = { FindStage, FindStage + NStages, - FindOperandCycle, FindOperandCycle + NOperandCycles}; - // Locate where to inject into processor itinerary table const std::string &Name = ItinData->getValueAsDef("TheClass")->getName(); unsigned Find = ItinClassesMap[Name]; + // Set up itinerary as location and location + stage count + unsigned NumUOps = ItinClassList[Find]->getValueAsInt("NumMicroOps"); + InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages, + FindOperandCycle, + FindOperandCycle + NOperandCycles}; + // Inject - empty slots will be 0, 0 ItinList[Find] = Intinerary; } @@ -389,7 +434,7 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, // Add process itinerary to list ProcList.push_back(ItinList); } - + // Closing stage StageTable += " { 0, 0, 0, llvm::InstrStage::Required } // End itinerary\n"; StageTable += "};\n"; @@ -398,9 +443,13 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, OperandCycleTable += " 0 // End itinerary\n"; OperandCycleTable += "};\n"; + BypassTable += " 0 // End itinerary\n"; + BypassTable += "};\n"; + // Emit tables. OS << StageTable; OS << OperandCycleTable; + OS << BypassTable; // Emit size of tables OS<<"\nenum {\n"; @@ -443,9 +492,11 @@ void SubtargetEmitter::EmitProcessorData(raw_ostream &OS, // Emit in the form of // { firstStage, lastStage, firstCycle, lastCycle } // index if (Intinerary.FirstStage == 0) { - OS << " { 0, 0, 0, 0 }"; + OS << " { 1, 0, 0, 0, 0 }"; } else { - OS << " { " << Intinerary.FirstStage << ", " << + OS << " { " << + Intinerary.NumMicroOps << ", " << + Intinerary.FirstStage << ", " << Intinerary.LastStage << ", " << Intinerary.FirstOperandCycle << ", " << Intinerary.LastOperandCycle << " }"; @@ -455,7 +506,7 @@ void SubtargetEmitter::EmitProcessorData(raw_ostream &OS, } // End processor itinerary table - OS << " { ~0U, ~0U, ~0U, ~0U } // end marker\n"; + OS << " { 1, ~0U, ~0U, ~0U, ~0U } // end marker\n"; OS << "};\n"; } } @@ -511,16 +562,22 @@ void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) { // void SubtargetEmitter::EmitData(raw_ostream &OS) { std::map<std::string, unsigned> ItinClassesMap; - std::vector<std::vector<InstrItinerary> > ProcList; + // Gather and sort all itinerary classes + std::vector<Record*> ItinClassList = + Records.getAllDerivedDefinitions("InstrItinClass"); + std::sort(ItinClassList.begin(), ItinClassList.end(), LessRecord()); // Enumerate all the itinerary classes - unsigned NItinClasses = CollectAllItinClasses(OS, ItinClassesMap); + unsigned NItinClasses = CollectAllItinClasses(OS, ItinClassesMap, + ItinClassList); // Make sure the rest is worth the effort HasItineraries = NItinClasses != 1; // Ignore NoItinerary. if (HasItineraries) { + std::vector<std::vector<InstrItinerary> > ProcList; // Emit the stage data - EmitStageAndOperandCycleData(OS, NItinClasses, ItinClassesMap, ProcList); + EmitStageAndOperandCycleData(OS, NItinClasses, ItinClassesMap, + ItinClassList, ProcList); // Emit the processor itinerary data EmitProcessorData(OS, ProcList); // Emit the processor lookup data @@ -569,7 +626,8 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) { OS << "\n" << " InstrItinerary *Itinerary = (InstrItinerary *)" << "Features.getInfo(ProcItinKV, ProcItinKVSize);\n" - << " InstrItins = InstrItineraryData(Stages, OperandCycles, Itinerary);\n"; + << " InstrItins = InstrItineraryData(Stages, OperandCycles, " + << "ForwardingPathes, Itinerary);\n"; } OS << " return Features.getCPU();\n" @@ -580,7 +638,7 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) { // SubtargetEmitter::run - Main subtarget enumeration emitter. // void SubtargetEmitter::run(raw_ostream &OS) { - Target = CodeGenTarget().getName(); + Target = CodeGenTarget(Records).getName(); EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS); diff --git a/utils/TableGen/SubtargetEmitter.h b/utils/TableGen/SubtargetEmitter.h index f43a443..3abec3b 100644 --- a/utils/TableGen/SubtargetEmitter.h +++ b/utils/TableGen/SubtargetEmitter.h @@ -33,14 +33,19 @@ class SubtargetEmitter : public TableGenBackend { void FeatureKeyValues(raw_ostream &OS); void CPUKeyValues(raw_ostream &OS); unsigned CollectAllItinClasses(raw_ostream &OS, - std::map<std::string, unsigned> &ItinClassesMap); + std::map<std::string,unsigned> &ItinClassesMap, + std::vector<Record*> &ItinClassList); void FormItineraryStageString(const std::string &Names, Record *ItinData, std::string &ItinString, unsigned &NStages); void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString, unsigned &NOperandCycles); + void FormItineraryBypassString(const std::string &Names, + Record *ItinData, + std::string &ItinString, unsigned NOperandCycles); void EmitStageAndOperandCycleData(raw_ostream &OS, unsigned NItinClasses, std::map<std::string, unsigned> &ItinClassesMap, + std::vector<Record*> &ItinClassList, std::vector<std::vector<InstrItinerary> > &ProcList); void EmitProcessorData(raw_ostream &OS, std::vector<std::vector<InstrItinerary> > &ProcList); diff --git a/utils/TableGen/TGLexer.cpp b/utils/TableGen/TGLexer.cpp index 2c7becc..82d2b64 100644 --- a/utils/TableGen/TGLexer.cpp +++ b/utils/TableGen/TGLexer.cpp @@ -15,6 +15,8 @@ #include "llvm/Support/SourceMgr.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Config/config.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" #include <cctype> #include <cstdio> #include <cstdlib> @@ -36,17 +38,17 @@ SMLoc TGLexer::getLoc() const { /// ReturnError - Set the error to the specified string at the specified /// location. This is defined to always return tgtok::Error. -tgtok::TokKind TGLexer::ReturnError(const char *Loc, const std::string &Msg) { +tgtok::TokKind TGLexer::ReturnError(const char *Loc, const Twine &Msg) { PrintError(Loc, Msg); return tgtok::Error; } -void TGLexer::PrintError(const char *Loc, const std::string &Msg) const { +void TGLexer::PrintError(const char *Loc, const Twine &Msg) const { SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), Msg, "error"); } -void TGLexer::PrintError(SMLoc Loc, const std::string &Msg) const { +void TGLexer::PrintError(SMLoc Loc, const Twine &Msg) const { SrcMgr.PrintMessage(Loc, Msg, "error"); } @@ -95,7 +97,7 @@ tgtok::TokKind TGLexer::LexToken() { switch (CurChar) { default: - // Handle letters: [a-zA-Z_] + // Handle letters: [a-zA-Z_#] if (isalpha(CurChar) || CurChar == '_' || CurChar == '#') return LexIdentifier(); @@ -214,23 +216,13 @@ tgtok::TokKind TGLexer::LexVarName() { tgtok::TokKind TGLexer::LexIdentifier() { - // The first letter is [a-zA-Z_]. + // The first letter is [a-zA-Z_#]. const char *IdentStart = TokStart; - // Match the rest of the identifier regex: [0-9a-zA-Z_]* - while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_' - || *CurPtr == '#') { - // If this contains a '#', make sure it's value - if (*CurPtr == '#') { - if (strncmp(CurPtr, "#NAME#", 6) != 0) { - return tgtok::Error; - } - CurPtr += 6; - } - else { - ++CurPtr; - } - } + // Match the rest of the identifier regex: [0-9a-zA-Z_#]* + while (isalpha(*CurPtr) || isdigit(*CurPtr) || *CurPtr == '_' || + *CurPtr == '#') + ++CurPtr; // Check to see if this identifier is a keyword. @@ -421,30 +413,30 @@ tgtok::TokKind TGLexer::LexBracket() { /// LexExclaim - Lex '!' and '![a-zA-Z]+'. tgtok::TokKind TGLexer::LexExclaim() { if (!isalpha(*CurPtr)) - return ReturnError(CurPtr-1, "Invalid \"!operator\""); + return ReturnError(CurPtr - 1, "Invalid \"!operator\""); const char *Start = CurPtr++; while (isalpha(*CurPtr)) ++CurPtr; // Check to see which operator this is. - unsigned Len = CurPtr-Start; - - if (Len == 3 && !memcmp(Start, "con", 3)) return tgtok::XConcat; - if (Len == 3 && !memcmp(Start, "sra", 3)) return tgtok::XSRA; - if (Len == 3 && !memcmp(Start, "srl", 3)) return tgtok::XSRL; - if (Len == 3 && !memcmp(Start, "shl", 3)) return tgtok::XSHL; - if (Len == 2 && !memcmp(Start, "eq", 2)) return tgtok::XEq; - if (Len == 9 && !memcmp(Start, "strconcat", 9)) return tgtok::XStrConcat; - if (Len == 10 && !memcmp(Start, "nameconcat", 10)) return tgtok::XNameConcat; - if (Len == 5 && !memcmp(Start, "subst", 5)) return tgtok::XSubst; - if (Len == 7 && !memcmp(Start, "foreach", 7)) return tgtok::XForEach; - if (Len == 4 && !memcmp(Start, "cast", 4)) return tgtok::XCast; - if (Len == 3 && !memcmp(Start, "car", 3)) return tgtok::XCar; - if (Len == 3 && !memcmp(Start, "cdr", 3)) return tgtok::XCdr; - if (Len == 4 && !memcmp(Start, "null", 4)) return tgtok::XNull; - if (Len == 2 && !memcmp(Start, "if", 2)) return tgtok::XIf; - - return ReturnError(Start-1, "Unknown operator"); + tgtok::TokKind Kind = + StringSwitch<tgtok::TokKind>(StringRef(Start, CurPtr - Start)) + .Case("eq", tgtok::XEq) + .Case("if", tgtok::XIf) + .Case("head", tgtok::XHead) + .Case("tail", tgtok::XTail) + .Case("con", tgtok::XConcat) + .Case("shl", tgtok::XSHL) + .Case("sra", tgtok::XSRA) + .Case("srl", tgtok::XSRL) + .Case("cast", tgtok::XCast) + .Case("empty", tgtok::XEmpty) + .Case("subst", tgtok::XSubst) + .Case("foreach", tgtok::XForEach) + .Case("strconcat", tgtok::XStrConcat) + .Default(tgtok::Error); + + return Kind != tgtok::Error ? Kind : ReturnError(Start-1, "Unknown operator"); } diff --git a/utils/TableGen/TGLexer.h b/utils/TableGen/TGLexer.h index 835f351..55a6c5d 100644 --- a/utils/TableGen/TGLexer.h +++ b/utils/TableGen/TGLexer.h @@ -14,7 +14,7 @@ #ifndef TGLEXER_H #define TGLEXER_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include <vector> #include <string> #include <cassert> @@ -23,7 +23,8 @@ namespace llvm { class MemoryBuffer; class SourceMgr; class SMLoc; - +class Twine; + namespace tgtok { enum TokKind { // Markers @@ -44,8 +45,8 @@ namespace tgtok { MultiClass, String, // !keywords. - XConcat, XSRA, XSRL, XSHL, XStrConcat, XNameConcat, XCast, XSubst, - XForEach, XCar, XCdr, XNull, XIf, XEq, + XConcat, XSRA, XSRL, XSHL, XStrConcat, XCast, XSubst, + XForEach, XHead, XTail, XEmpty, XIf, XEq, // Integer value. IntVal, @@ -95,14 +96,14 @@ public: SMLoc getLoc() const; - void PrintError(const char *Loc, const std::string &Msg) const; - void PrintError(SMLoc Loc, const std::string &Msg) const; + void PrintError(const char *Loc, const Twine &Msg) const; + void PrintError(SMLoc Loc, const Twine &Msg) const; private: /// LexToken - Read the next token and return its code. tgtok::TokKind LexToken(); - tgtok::TokKind ReturnError(const char *Loc, const std::string &Msg); + tgtok::TokKind ReturnError(const char *Loc, const Twine &Msg); int getNextChar(); void SkipBCPLComment(); diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp index f81aabe..f6041be 100644 --- a/utils/TableGen/TGParser.cpp +++ b/utils/TableGen/TGParser.cpp @@ -16,6 +16,8 @@ #include "llvm/ADT/StringExtras.h" #include <algorithm> #include <sstream> +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/CommandLine.h" using namespace llvm; //===----------------------------------------------------------------------===// @@ -294,20 +296,23 @@ static bool isObjectStart(tgtok::TokKind K) { K == tgtok::Defm || K == tgtok::Let || K == tgtok::MultiClass; } +static std::string GetNewAnonymousName() { + static unsigned AnonCounter = 0; + return "anonymous."+utostr(AnonCounter++); +} + /// ParseObjectName - If an object name is specified, return it. Otherwise, /// return an anonymous name. /// ObjectName ::= ID /// ObjectName ::= /*empty*/ /// std::string TGParser::ParseObjectName() { - if (Lex.getCode() == tgtok::Id) { - std::string Ret = Lex.getCurStrVal(); - Lex.Lex(); - return Ret; - } + if (Lex.getCode() != tgtok::Id) + return GetNewAnonymousName(); - static unsigned AnonCounter = 0; - return "anonymous."+utostr(AnonCounter++); + std::string Ret = Lex.getCurStrVal(); + Lex.Lex(); + return Ret; } @@ -678,9 +683,9 @@ Init *TGParser::ParseOperation(Record *CurRec) { TokError("unknown operation"); return 0; break; - case tgtok::XCar: - case tgtok::XCdr: - case tgtok::XNull: + case tgtok::XHead: + case tgtok::XTail: + case tgtok::XEmpty: case tgtok::XCast: { // Value ::= !unop '(' Value ')' UnOpInit::UnaryOp Code; RecTy *Type = 0; @@ -699,17 +704,17 @@ Init *TGParser::ParseOperation(Record *CurRec) { } break; - case tgtok::XCar: + case tgtok::XHead: Lex.Lex(); // eat the operation - Code = UnOpInit::CAR; + Code = UnOpInit::HEAD; break; - case tgtok::XCdr: + case tgtok::XTail: Lex.Lex(); // eat the operation - Code = UnOpInit::CDR; + Code = UnOpInit::TAIL; break; - case tgtok::XNull: + case tgtok::XEmpty: Lex.Lex(); // eat the operation - Code = UnOpInit::LNULL; + Code = UnOpInit::EMPTY; Type = new IntRecTy; break; } @@ -722,9 +727,9 @@ Init *TGParser::ParseOperation(Record *CurRec) { Init *LHS = ParseValue(CurRec); if (LHS == 0) return 0; - if (Code == UnOpInit::CAR - || Code == UnOpInit::CDR - || Code == UnOpInit::LNULL) { + if (Code == UnOpInit::HEAD + || Code == UnOpInit::TAIL + || Code == UnOpInit::EMPTY) { ListInit *LHSl = dynamic_cast<ListInit*>(LHS); StringInit *LHSs = dynamic_cast<StringInit*>(LHS); TypedInit *LHSt = dynamic_cast<TypedInit*>(LHS); @@ -741,8 +746,8 @@ Init *TGParser::ParseOperation(Record *CurRec) { } } - if (Code == UnOpInit::CAR - || Code == UnOpInit::CDR) { + if (Code == UnOpInit::HEAD + || Code == UnOpInit::TAIL) { if (LHSl == 0 && LHSt == 0) { TokError("expected list type argumnet in unary operator"); return 0; @@ -759,7 +764,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { TokError("untyped list element in unary operator"); return 0; } - if (Code == UnOpInit::CAR) { + if (Code == UnOpInit::HEAD) { Type = Itemt->getType(); } else { Type = new ListRecTy(Itemt->getType()); @@ -771,7 +776,7 @@ Init *TGParser::ParseOperation(Record *CurRec) { TokError("expected list type argumnet in unary operator"); return 0; } - if (Code == UnOpInit::CAR) { + if (Code == UnOpInit::HEAD) { Type = LType->getElementType(); } else { Type = LType; @@ -793,81 +798,68 @@ Init *TGParser::ParseOperation(Record *CurRec) { case tgtok::XSRL: case tgtok::XSHL: case tgtok::XEq: - case tgtok::XStrConcat: - case tgtok::XNameConcat: { // Value ::= !binop '(' Value ',' Value ')' + case tgtok::XStrConcat: { // Value ::= !binop '(' Value ',' Value ')' + tgtok::TokKind OpTok = Lex.getCode(); + SMLoc OpLoc = Lex.getLoc(); + Lex.Lex(); // eat the operation + BinOpInit::BinaryOp Code; RecTy *Type = 0; - - switch (Lex.getCode()) { + switch (OpTok) { default: assert(0 && "Unhandled code!"); - case tgtok::XConcat: - Lex.Lex(); // eat the operation - Code = BinOpInit::CONCAT; - Type = new DagRecTy(); - break; - case tgtok::XSRA: - Lex.Lex(); // eat the operation - Code = BinOpInit::SRA; - Type = new IntRecTy(); - break; - case tgtok::XSRL: - Lex.Lex(); // eat the operation - Code = BinOpInit::SRL; - Type = new IntRecTy(); - break; - case tgtok::XSHL: - Lex.Lex(); // eat the operation - Code = BinOpInit::SHL; - Type = new IntRecTy(); - break; - case tgtok::XEq: - Lex.Lex(); // eat the operation - Code = BinOpInit::EQ; - Type = new IntRecTy(); - break; + case tgtok::XConcat: Code = BinOpInit::CONCAT; Type = new DagRecTy(); break; + case tgtok::XSRA: Code = BinOpInit::SRA; Type = new IntRecTy(); break; + case tgtok::XSRL: Code = BinOpInit::SRL; Type = new IntRecTy(); break; + case tgtok::XSHL: Code = BinOpInit::SHL; Type = new IntRecTy(); break; + case tgtok::XEq: Code = BinOpInit::EQ; Type = new BitRecTy(); break; case tgtok::XStrConcat: - Lex.Lex(); // eat the operation Code = BinOpInit::STRCONCAT; Type = new StringRecTy(); break; - case tgtok::XNameConcat: - Lex.Lex(); // eat the operation - Code = BinOpInit::NAMECONCAT; - - Type = ParseOperatorType(); - - if (Type == 0) { - TokError("did not get type for binary operator"); - return 0; - } - - break; } + if (Lex.getCode() != tgtok::l_paren) { TokError("expected '(' after binary operator"); return 0; } Lex.Lex(); // eat the '(' - Init *LHS = ParseValue(CurRec); - if (LHS == 0) return 0; + SmallVector<Init*, 2> InitList; - if (Lex.getCode() != tgtok::comma) { - TokError("expected ',' in binary operator"); - return 0; - } - Lex.Lex(); // eat the ',' + InitList.push_back(ParseValue(CurRec)); + if (InitList.back() == 0) return 0; - Init *RHS = ParseValue(CurRec); - if (RHS == 0) return 0; + while (Lex.getCode() == tgtok::comma) { + Lex.Lex(); // eat the ',' + + InitList.push_back(ParseValue(CurRec)); + if (InitList.back() == 0) return 0; + } if (Lex.getCode() != tgtok::r_paren) { - TokError("expected ')' in binary operator"); + TokError("expected ')' in operator"); return 0; } Lex.Lex(); // eat the ')' - return (new BinOpInit(Code, LHS, RHS, Type))->Fold(CurRec, CurMultiClass); + + // We allow multiple operands to associative operators like !strconcat as + // shorthand for nesting them. + if (Code == BinOpInit::STRCONCAT) { + while (InitList.size() > 2) { + Init *RHS = InitList.pop_back_val(); + RHS = (new BinOpInit(Code, InitList.back(), RHS, Type)) + ->Fold(CurRec, CurMultiClass); + InitList.back() = RHS; + } + } + + if (InitList.size() == 2) + return (new BinOpInit(Code, InitList[0], InitList[1], Type)) + ->Fold(CurRec, CurMultiClass); + + Error(OpLoc, "expected two operands to operator"); + return 0; } case tgtok::XIf: @@ -876,7 +868,6 @@ Init *TGParser::ParseOperation(Record *CurRec) { TernOpInit::TernaryOp Code; RecTy *Type = 0; - tgtok::TokKind LexCode = Lex.getCode(); Lex.Lex(); // eat the operation switch (LexCode) { @@ -927,16 +918,45 @@ Init *TGParser::ParseOperation(Record *CurRec) { switch (LexCode) { default: assert(0 && "Unhandled code!"); case tgtok::XIf: { - TypedInit *MHSt = dynamic_cast<TypedInit *>(MHS); - TypedInit *RHSt = dynamic_cast<TypedInit *>(RHS); - if (MHSt == 0 || RHSt == 0) { + // FIXME: The `!if' operator doesn't handle non-TypedInit well at + // all. This can be made much more robust. + TypedInit *MHSt = dynamic_cast<TypedInit*>(MHS); + TypedInit *RHSt = dynamic_cast<TypedInit*>(RHS); + + RecTy *MHSTy = 0; + RecTy *RHSTy = 0; + + if (MHSt == 0 && RHSt == 0) { + BitsInit *MHSbits = dynamic_cast<BitsInit*>(MHS); + BitsInit *RHSbits = dynamic_cast<BitsInit*>(RHS); + + if (MHSbits && RHSbits && + MHSbits->getNumBits() == RHSbits->getNumBits()) { + Type = new BitRecTy(); + break; + } else { + BitInit *MHSbit = dynamic_cast<BitInit*>(MHS); + BitInit *RHSbit = dynamic_cast<BitInit*>(RHS); + + if (MHSbit && RHSbit) { + Type = new BitRecTy(); + break; + } + } + } else if (MHSt != 0 && RHSt != 0) { + MHSTy = MHSt->getType(); + RHSTy = RHSt->getType(); + } + + if (!MHSTy || !RHSTy) { TokError("could not get type for !if"); return 0; } - if (MHSt->getType()->typeIsConvertibleTo(RHSt->getType())) { - Type = RHSt->getType(); - } else if (RHSt->getType()->typeIsConvertibleTo(MHSt->getType())) { - Type = MHSt->getType(); + + if (MHSTy->typeIsConvertibleTo(RHSTy)) { + Type = RHSTy; + } else if (RHSTy->typeIsConvertibleTo(MHSTy)) { + Type = MHSTy; } else { TokError("inconsistent types for !if"); return 0; @@ -1037,8 +1057,13 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { break; } case tgtok::CodeFragment: - R = new CodeInit(Lex.getCurStrVal()); Lex.Lex(); break; - case tgtok::question: R = new UnsetInit(); Lex.Lex(); break; + R = new CodeInit(Lex.getCurStrVal()); + Lex.Lex(); + break; + case tgtok::question: + R = new UnsetInit(); + Lex.Lex(); + break; case tgtok::Id: { SMLoc NameLoc = Lex.getLoc(); std::string Name = Lex.getCurStrVal(); @@ -1071,7 +1096,9 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { // Create the new record, set it as CurRec temporarily. static unsigned AnonCounter = 0; - Record *NewRec = new Record("anonymous.val."+utostr(AnonCounter++),NameLoc); + Record *NewRec = new Record("anonymous.val."+utostr(AnonCounter++), + NameLoc, + Records); SubClassReference SCRef; SCRef.RefLoc = NameLoc; SCRef.Rec = Class; @@ -1212,21 +1239,13 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { } case tgtok::l_paren: { // Value ::= '(' IDValue DagArgList ')' Lex.Lex(); // eat the '(' - if (Lex.getCode() != tgtok::Id - && Lex.getCode() != tgtok::XCast - && Lex.getCode() != tgtok::XNameConcat) { + if (Lex.getCode() != tgtok::Id && Lex.getCode() != tgtok::XCast) { TokError("expected identifier in dag init"); return 0; } - Init *Operator = 0; - if (Lex.getCode() == tgtok::Id) { - Operator = ParseIDValue(CurRec); - if (Operator == 0) return 0; - } else { - Operator = ParseOperation(CurRec); - if (Operator == 0) return 0; - } + Init *Operator = ParseValue(CurRec); + if (Operator == 0) return 0; // If the operator name is present, parse it. std::string OperatorName; @@ -1252,25 +1271,22 @@ Init *TGParser::ParseSimpleValue(Record *CurRec, RecTy *ItemType) { Lex.Lex(); // eat the ')' return new DagInit(Operator, OperatorName, DagArgs); - break; } - case tgtok::XCar: - case tgtok::XCdr: - case tgtok::XNull: + case tgtok::XHead: + case tgtok::XTail: + case tgtok::XEmpty: case tgtok::XCast: // Value ::= !unop '(' Value ')' case tgtok::XConcat: case tgtok::XSRA: case tgtok::XSRL: case tgtok::XSHL: case tgtok::XEq: - case tgtok::XStrConcat: - case tgtok::XNameConcat: // Value ::= !binop '(' Value ',' Value ')' + case tgtok::XStrConcat: // Value ::= !binop '(' Value ',' Value ')' case tgtok::XIf: case tgtok::XForEach: case tgtok::XSubst: { // Value ::= !ternop '(' Value ',' Value ',' Value ')' return ParseOperation(CurRec); - break; } } @@ -1646,7 +1662,7 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) { Lex.Lex(); // Eat the 'def' token. // Parse ObjectName and make a record for it. - Record *CurRec = new Record(ParseObjectName(), DefLoc); + Record *CurRec = new Record(ParseObjectName(), DefLoc, Records); if (!CurMultiClass) { // Top-level def definition. @@ -1713,7 +1729,7 @@ bool TGParser::ParseClass() { return TokError("Class '" + CurRec->getName() + "' already defined"); } else { // If this is the first reference to this class, create and add it. - CurRec = new Record(Lex.getCurStrVal(), Lex.getLoc()); + CurRec = new Record(Lex.getCurStrVal(), Lex.getLoc(), Records); Records.addClass(CurRec); } Lex.Lex(); // eat the name. @@ -1830,7 +1846,8 @@ bool TGParser::ParseMultiClass() { if (MultiClasses.count(Name)) return TokError("multiclass '" + Name + "' already defined"); - CurMultiClass = MultiClasses[Name] = new MultiClass(Name, Lex.getLoc()); + CurMultiClass = MultiClasses[Name] = new MultiClass(Name, + Lex.getLoc(), Records); Lex.Lex(); // Eat the identifier. // If there are template args, parse them. @@ -1899,12 +1916,15 @@ bool TGParser::ParseMultiClass() { /// bool TGParser::ParseDefm(MultiClass *CurMultiClass) { assert(Lex.getCode() == tgtok::Defm && "Unexpected token!"); - if (Lex.Lex() != tgtok::Id) // eat the defm. - return TokError("expected identifier after defm"); + + std::string DefmPrefix; + if (Lex.Lex() == tgtok::Id) { // eat the defm. + DefmPrefix = Lex.getCurStrVal(); + Lex.Lex(); // Eat the defm prefix. + } SMLoc DefmPrefixLoc = Lex.getLoc(); - std::string DefmPrefix = Lex.getCurStrVal(); - if (Lex.Lex() != tgtok::colon) + if (Lex.getCode() != tgtok::colon) return TokError("expected ':' after defm identifier"); // Keep track of the new generated record definitions. @@ -1939,17 +1959,24 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) { for (unsigned i = 0, e = MC->DefPrototypes.size(); i != e; ++i) { Record *DefProto = MC->DefPrototypes[i]; - // Add in the defm name + // Add in the defm name. If the defm prefix is empty, give each + // instantiated def a unique name. Otherwise, if "#NAME#" exists in the + // name, substitute the prefix for #NAME#. Otherwise, use the defm name + // as a prefix. std::string DefName = DefProto->getName(); - std::string::size_type idx = DefName.find("#NAME#"); - if (idx != std::string::npos) { - DefName.replace(idx, 6, DefmPrefix); + if (DefmPrefix.empty()) { + DefName = GetNewAnonymousName(); } else { - // Add the suffix to the defm name to get the new name. - DefName = DefmPrefix + DefName; + std::string::size_type idx = DefName.find("#NAME#"); + if (idx != std::string::npos) { + DefName.replace(idx, 6, DefmPrefix); + } else { + // Add the suffix to the defm name to get the new name. + DefName = DefmPrefix + DefName; + } } - Record *CurRec = new Record(DefName, DefmPrefixLoc); + Record *CurRec = new Record(DefName, DefmPrefixLoc, Records); SubClassReference Ref; Ref.RefLoc = DefmPrefixLoc; @@ -2091,7 +2118,8 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) { /// Object ::= LETCommand Object bool TGParser::ParseObject(MultiClass *MC) { switch (Lex.getCode()) { - default: assert(0 && "This is not an object"); + default: + return TokError("Expected class, def, defm, multiclass or let definition"); case tgtok::Let: return ParseTopLevelLet(MC); case tgtok::Def: return ParseDef(MC); case tgtok::Defm: return ParseDefm(MC); diff --git a/utils/TableGen/TGParser.h b/utils/TableGen/TGParser.h index 0aee931..9cdf68f 100644 --- a/utils/TableGen/TGParser.h +++ b/utils/TableGen/TGParser.h @@ -15,12 +15,14 @@ #define TGPARSER_H #include "TGLexer.h" +#include "llvm/ADT/Twine.h" #include "llvm/Support/SourceMgr.h" #include <map> namespace llvm { class Record; class RecordVal; + class RecordKeeper; struct RecTy; struct Init; struct MultiClass; @@ -46,18 +48,22 @@ class TGParser { /// CurMultiClass - If we are parsing a 'multiclass' definition, this is the /// current value. MultiClass *CurMultiClass; + + // Record tracker + RecordKeeper &Records; public: - TGParser(SourceMgr &SrcMgr) : Lex(SrcMgr), CurMultiClass(0) {} + TGParser(SourceMgr &SrcMgr, RecordKeeper &records) : + Lex(SrcMgr), CurMultiClass(0), Records(records) {} /// ParseFile - Main entrypoint for parsing a tblgen file. These parser /// routines return true on error, or false on success. bool ParseFile(); - bool Error(SMLoc L, const std::string &Msg) const { + bool Error(SMLoc L, const Twine &Msg) const { Lex.PrintError(L, Msg); return true; } - bool TokError(const std::string &Msg) const { + bool TokError(const Twine &Msg) const { return Error(Lex.getLoc(), Msg); } private: // Semantic analysis methods. diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index 5e3e282..3b7dc01 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -21,6 +21,7 @@ #include "ClangASTNodesEmitter.h" #include "ClangAttrEmitter.h" #include "ClangDiagnosticsEmitter.h" +#include "ClangSACheckersEmitter.h" #include "CodeEmitterGen.h" #include "DAGISelEmitter.h" #include "DisassemblerEmitter.h" @@ -37,11 +38,13 @@ #include "ARMDecoderEmitter.h" #include "SubtargetEmitter.h" #include "TGParser.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/System/Signals.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/system_error.h" #include <algorithm> #include <cstdio> using namespace llvm; @@ -59,10 +62,12 @@ enum ActionType { GenClangAttrList, GenClangAttrPCHRead, GenClangAttrPCHWrite, + GenClangAttrSpellingList, GenClangDiagsDefs, GenClangDiagGroups, GenClangDeclNodes, GenClangStmtNodes, + GenClangSACheckers, GenDAGISel, GenFastISel, GenOptParserDefs, GenOptParserImpl, @@ -73,6 +78,7 @@ enum ActionType { GenEDInfo, GenArmNeon, GenArmNeonSema, + GenArmNeonTest, PrintEnums }; @@ -127,14 +133,18 @@ namespace { "Generate clang PCH attribute reader"), clEnumValN(GenClangAttrPCHWrite, "gen-clang-attr-pch-write", "Generate clang PCH attribute writer"), + clEnumValN(GenClangAttrSpellingList, "gen-clang-attr-spelling-list", + "Generate a clang attribute spelling list"), clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs", "Generate Clang diagnostics definitions"), clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups", "Generate Clang diagnostic groups"), clEnumValN(GenClangDeclNodes, "gen-clang-decl-nodes", - "Generate Clang AST statement nodes"), + "Generate Clang AST declaration nodes"), clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes", "Generate Clang AST statement nodes"), + clEnumValN(GenClangSACheckers, "gen-clang-sa-checkers", + "Generate Clang Static Analyzer checkers"), clEnumValN(GenLLVMCConf, "gen-llvmc", "Generate LLVMC configuration library"), clEnumValN(GenEDInfo, "gen-enhanced-disassembly-info", @@ -143,6 +153,8 @@ namespace { "Generate arm_neon.h for clang"), clEnumValN(GenArmNeonSema, "gen-arm-neon-sema", "Generate ARM NEON sema support for clang"), + clEnumValN(GenArmNeonTest, "gen-arm-neon-test", + "Generate ARM NEON tests for clang"), clEnumValN(PrintEnums, "print-enums", "Print enum values for a class"), clEnumValEnd)); @@ -169,12 +181,9 @@ namespace { } -// FIXME: Eliminate globals from tblgen. -RecordKeeper llvm::Records; - static SourceMgr SrcMgr; -void llvm::PrintError(SMLoc ErrorLoc, const std::string &Msg) { +void llvm::PrintError(SMLoc ErrorLoc, const Twine &Msg) { SrcMgr.PrintMessage(ErrorLoc, Msg, "error"); } @@ -184,14 +193,15 @@ void llvm::PrintError(SMLoc ErrorLoc, const std::string &Msg) { /// file. static bool ParseFile(const std::string &Filename, const std::vector<std::string> &IncludeDirs, - SourceMgr &SrcMgr) { - std::string ErrorStr; - MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrorStr); - if (F == 0) { + SourceMgr &SrcMgr, + RecordKeeper &Records) { + OwningPtr<MemoryBuffer> File; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), File)) { errs() << "Could not open input file '" << Filename << "': " - << ErrorStr <<"\n"; + << ec.message() <<"\n"; return true; } + MemoryBuffer *F = File.take(); // Tell SrcMgr about this buffer, which is what TGParser will pick up. SrcMgr.AddNewSourceBuffer(F, SMLoc()); @@ -200,19 +210,21 @@ static bool ParseFile(const std::string &Filename, // it later. SrcMgr.setIncludeDirs(IncludeDirs); - TGParser Parser(SrcMgr); + TGParser Parser(SrcMgr, Records); return Parser.ParseFile(); } int main(int argc, char **argv) { + RecordKeeper Records; + sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); cl::ParseCommandLineOptions(argc, argv); // Parse the input file. - if (ParseFile(InputFilename, IncludeDirs, SrcMgr)) + if (ParseFile(InputFilename, IncludeDirs, SrcMgr, Records)) return 1; std::string Error; @@ -274,6 +286,9 @@ int main(int argc, char **argv) { case GenClangAttrPCHWrite: ClangAttrPCHWriteEmitter(Records).run(Out.os()); break; + case GenClangAttrSpellingList: + ClangAttrSpellingListEmitter(Records).run(Out.os()); + break; case GenClangDiagsDefs: ClangDiagsDefsEmitter(Records, ClangComponent).run(Out.os()); break; @@ -287,6 +302,9 @@ int main(int argc, char **argv) { case GenClangStmtNodes: ClangASTNodesEmitter(Records, "Stmt", "").run(Out.os()); break; + case GenClangSACheckers: + ClangSACheckersEmitter(Records).run(Out.os()); + break; case GenDisassembler: DisassemblerEmitter(Records).run(Out.os()); break; @@ -323,6 +341,9 @@ int main(int argc, char **argv) { case GenArmNeonSema: NeonEmitter(Records).runHeader(Out.os()); break; + case GenArmNeonTest: + NeonEmitter(Records).runTests(Out.os()); + break; case PrintEnums: { std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class); diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp index 2176224..94797f5 100644 --- a/utils/TableGen/X86DisassemblerTables.cpp +++ b/utils/TableGen/X86DisassemblerTables.cpp @@ -161,7 +161,7 @@ void DisassemblerTables::emitOneID(raw_ostream &o, /// @param i - The indentation level for that output stream. static void emitEmptyTable(raw_ostream &o, uint32_t &i) { - o.indent(i * 2) << "static InstrUID modRMEmptyTable[1] = { 0 };" << "\n"; + o.indent(i * 2) << "static const InstrUID modRMEmptyTable[1] = { 0 };\n"; o << "\n"; } @@ -275,7 +275,7 @@ void DisassemblerTables::emitModRMDecision(raw_ostream &o1, return; } - o1.indent(i1) << "static InstrUID modRMTable" << thisTableNumber; + o1.indent(i1) << "static const InstrUID modRMTable" << thisTableNumber; switch (dt) { default: @@ -365,7 +365,7 @@ void DisassemblerTables::emitContextDecision( uint32_t &i2, ContextDecision &decision, const char* name) const { - o2.indent(i2) << "struct ContextDecision " << name << " = {" << "\n"; + o2.indent(i2) << "static const struct ContextDecision " << name << " = {\n"; i2++; o2.indent(i2) << "{ /* opcodeDecisions */" << "\n"; i2++; @@ -392,10 +392,8 @@ void DisassemblerTables::emitContextDecision( void DisassemblerTables::emitInstructionInfo(raw_ostream &o, uint32_t &i) const { - o.indent(i * 2) << "struct InstructionSpecifier "; - o << INSTRUCTIONS_STR << "["; - o << InstructionSpecifiers.size(); - o << "] = {" << "\n"; + o.indent(i * 2) << "static const struct InstructionSpecifier "; + o << INSTRUCTIONS_STR "[" << InstructionSpecifiers.size() << "] = {\n"; i++; @@ -456,8 +454,8 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o, uint32_t &i) void DisassemblerTables::emitContextTable(raw_ostream &o, uint32_t &i) const { uint16_t index; - o.indent(i * 2) << "InstructionContext "; - o << CONTEXTS_STR << "[256] = {" << "\n"; + o.indent(i * 2) << "static const InstructionContext " CONTEXTS_STR + "[256] = {\n"; i++; for (index = 0; index < 256; ++index) { diff --git a/utils/TableGen/X86ModRMFilters.h b/utils/TableGen/X86ModRMFilters.h index 45cb07a..199040b 100644 --- a/utils/TableGen/X86ModRMFilters.h +++ b/utils/TableGen/X86ModRMFilters.h @@ -18,7 +18,7 @@ #ifndef X86MODRMFILTERS_H #define X86MODRMFILTERS_H -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" namespace llvm { diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index 4dba85b..ccd3efd 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -51,10 +51,11 @@ namespace X86Local { MRM0m = 24, MRM1m = 25, MRM2m = 26, MRM3m = 27, MRM4m = 28, MRM5m = 29, MRM6m = 30, MRM7m = 31, MRMInitReg = 32, - #define MAP(from, to) MRM_##from = to, MRM_MAPPING #undef MAP + RawFrmImm8 = 43, + RawFrmImm16 = 44, lastMRM }; @@ -113,7 +114,6 @@ namespace X86Local { EXTENSION_TABLE(72) \ EXTENSION_TABLE(73) \ EXTENSION_TABLE(ae) \ - EXTENSION_TABLE(b9) \ EXTENSION_TABLE(ba) \ EXTENSION_TABLE(c7) @@ -219,7 +219,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, Name = Rec->getName(); AsmString = Rec->getValueAsString("AsmString"); - Operands = &insn.OperandList; + Operands = &insn.Operands.OperandList; IsSSE = HasOpSizePrefix && (Name.find("16") == Name.npos); HasFROperands = false; @@ -311,7 +311,7 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const { return FILTER_STRONG; // Special cases. - + if (Name.find("PCMPISTRI") != Name.npos && Name != "PCMPISTRI") return FILTER_WEAK; if (Name.find("PCMPESTRI") != Name.npos && Name != "PCMPESTRI") @@ -424,7 +424,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { Spec->insnContext = insnContext(); - const std::vector<CodeGenInstruction::OperandInfo> &OperandList = *Operands; + const std::vector<CGIOperandList::OperandInfo> &OperandList = *Operands; unsigned operandIndex; unsigned numOperands = OperandList.size(); @@ -440,7 +440,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { for (operandIndex = 0; operandIndex < numOperands; ++operandIndex) { if (OperandList[operandIndex].Constraints.size()) { - const CodeGenInstruction::ConstraintInfo &Constraint = + const CGIOperandList::ConstraintInfo &Constraint = OperandList[operandIndex].Constraints[0]; if (Constraint.isTied()) { operandMapping[operandIndex] = Constraint.getTiedOperand(); @@ -587,6 +587,20 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { HANDLE_OPERAND(memory) HANDLE_OPTIONAL(relocation) break; + case X86Local::RawFrmImm8: + // operand 1 is a 16-bit immediate + // operand 2 is an 8-bit immediate + assert(numPhysicalOperands == 2 && + "Unexpected number of operands for X86Local::RawFrmImm8"); + HANDLE_OPERAND(immediate) + HANDLE_OPERAND(immediate) + break; + case X86Local::RawFrmImm16: + // operand 1 is a 16-bit immediate + // operand 2 is a 16-bit immediate + HANDLE_OPERAND(immediate) + HANDLE_OPERAND(immediate) + break; case X86Local::MRMInitReg: // Ignored. break; @@ -829,10 +843,13 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("GR8", TYPE_R8) TYPE("VR128", TYPE_XMM128) TYPE("f128mem", TYPE_M128) + TYPE("f256mem", TYPE_M256) TYPE("FR64", TYPE_XMM64) TYPE("f64mem", TYPE_M64FP) + TYPE("sdmem", TYPE_M64FP) TYPE("FR32", TYPE_XMM32) TYPE("f32mem", TYPE_M32FP) + TYPE("ssmem", TYPE_M32FP) TYPE("RST", TYPE_ST) TYPE("i128mem", TYPE_M128) TYPE("i64i32imm_pcrel", TYPE_REL64) @@ -840,6 +857,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("i32imm_pcrel", TYPE_REL32) TYPE("SSECC", TYPE_IMM3) TYPE("brtarget", TYPE_RELv) + TYPE("uncondbrtarget", TYPE_RELv) TYPE("brtarget8", TYPE_REL8) TYPE("f80mem", TYPE_M80FP) TYPE("lea32mem", TYPE_LEA) @@ -924,7 +942,10 @@ OperandEncoding RecognizableInstr::memoryEncodingFromString ENCODING("i32mem", ENCODING_RM) ENCODING("i64mem", ENCODING_RM) ENCODING("i8mem", ENCODING_RM) + ENCODING("ssmem", ENCODING_RM) + ENCODING("sdmem", ENCODING_RM) ENCODING("f128mem", ENCODING_RM) + ENCODING("f256mem", ENCODING_RM) ENCODING("f64mem", ENCODING_RM) ENCODING("f32mem", ENCODING_RM) ENCODING("i128mem", ENCODING_RM) diff --git a/utils/TableGen/X86RecognizableInstr.h b/utils/TableGen/X86RecognizableInstr.h index db4d96d..c043b90 100644 --- a/utils/TableGen/X86RecognizableInstr.h +++ b/utils/TableGen/X86RecognizableInstr.h @@ -22,7 +22,7 @@ #include "CodeGenTarget.h" #include "Record.h" -#include "llvm/System/DataTypes.h" +#include "llvm/Support/DataTypes.h" #include "llvm/ADT/SmallVector.h" namespace llvm { @@ -76,7 +76,8 @@ private: /// The operands of the instruction, as listed in the CodeGenInstruction. /// They are not one-to-one with operands listed in the MCInst; for example, /// memory operands expand to 5 operands in the MCInst - const std::vector<CodeGenInstruction::OperandInfo>* Operands; + const std::vector<CGIOperandList::OperandInfo>* Operands; + /// The description of the instruction that is emitted into the instruction /// info table InstructionSpecifier* Spec; |