void CheckOrImmMatcher::printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "CheckOrImm " << Value << '\n'; }
void RecordMemRefMatcher::printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "RecordMemRef\n"; }
void MoveChildMatcher::printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "MoveChild " << ChildNo << '\n'; }
void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2, unsigned &i1, unsigned &i2, unsigned &ModRMTableNum, ModRMDecision &decision) const { static uint32_t sTableNumber = 0; static uint32_t sEntryNumber = 1; ModRMDecisionType dt = getDecisionType(decision); if (dt == MODRM_ONEENTRY && decision.instructionIDs[0] == 0) { o2.indent(i2) << "{ /* ModRMDecision */" << "\n"; i2++; o2.indent(i2) << stringForDecisionType(dt) << "," << "\n"; o2.indent(i2) << 0 << " /* EmptyTable */\n"; i2--; o2.indent(i2) << "}"; return; } std::vector<unsigned> ModRMDecision; switch (dt) { default: llvm_unreachable("Unknown decision type"); case MODRM_ONEENTRY: ModRMDecision.push_back(decision.instructionIDs[0]); break; case MODRM_SPLITRM: ModRMDecision.push_back(decision.instructionIDs[0x00]); ModRMDecision.push_back(decision.instructionIDs[0xc0]); break; case MODRM_SPLITREG: for (unsigned index = 0; index < 64; index += 8) ModRMDecision.push_back(decision.instructionIDs[index]); for (unsigned index = 0xc0; index < 256; index += 8) ModRMDecision.push_back(decision.instructionIDs[index]); break; case MODRM_SPLITMISC: for (unsigned index = 0; index < 64; index += 8) ModRMDecision.push_back(decision.instructionIDs[index]); for (unsigned index = 0xc0; index < 256; ++index) ModRMDecision.push_back(decision.instructionIDs[index]); break; case MODRM_FULL: for (unsigned index = 0; index < 256; ++index) ModRMDecision.push_back(decision.instructionIDs[index]); break; } unsigned &EntryNumber = ModRMTable[ModRMDecision]; if (EntryNumber == 0) { EntryNumber = ModRMTableNum; ModRMTableNum += ModRMDecision.size(); o1 << "/* Table" << EntryNumber << " */\n"; i1++; for (std::vector<unsigned>::const_iterator I = ModRMDecision.begin(), E = ModRMDecision.end(); I != E; ++I) { o1.indent(i1 * 2) << format("0x%hx", *I) << ", /* " << InstructionSpecifiers[*I].name << " */\n"; } i1--; } o2.indent(i2) << "{ /* struct ModRMDecision */" << "\n"; i2++; o2.indent(i2) << stringForDecisionType(dt) << "," << "\n"; o2.indent(i2) << EntryNumber << " /* Table" << EntryNumber << " */\n"; i2--; o2.indent(i2) << "}"; switch (dt) { default: llvm_unreachable("Unknown decision type"); case MODRM_ONEENTRY: sEntryNumber += 1; break; case MODRM_SPLITRM: sEntryNumber += 2; break; case MODRM_SPLITREG: sEntryNumber += 16; break; case MODRM_SPLITMISC: sEntryNumber += 8 + 64; break; case MODRM_FULL: sEntryNumber += 256; break; } // We assume that the index can fit into uint16_t. assert(sEntryNumber < 65536U && "Index into ModRMDecision is too large for uint16_t!"); ++sTableNumber; }
void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const { const unsigned int tableSize = 16384; o.indent(i * 2) << "static const uint8_t " CONTEXTS_STR "[" << tableSize << "] = {\n"; i++; for (unsigned index = 0; index < tableSize; ++index) { o.indent(i * 2); if (index & ATTR_EVEX) { o << "IC_EVEX"; if (index & ATTR_EVEXL2) o << "_L2"; else if (index & ATTR_EVEXL) o << "_L"; if (index & ATTR_REXW) o << "_W"; if (index & ATTR_OPSIZE) o << "_OPSIZE"; else if (index & ATTR_XD) o << "_XD"; else if (index & ATTR_XS) o << "_XS"; if (index & ATTR_EVEXKZ) o << "_KZ"; else if (index & ATTR_EVEXK) o << "_K"; if (index & ATTR_EVEXB) o << "_B"; } else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_OPSIZE)) o << "IC_VEX_L_W_OPSIZE"; else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_XD)) o << "IC_VEX_L_W_XD"; else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_XS)) o << "IC_VEX_L_W_XS"; else if ((index & ATTR_VEXL) && (index & ATTR_REXW)) o << "IC_VEX_L_W"; else if ((index & ATTR_VEXL) && (index & ATTR_OPSIZE)) o << "IC_VEX_L_OPSIZE"; else if ((index & ATTR_VEXL) && (index & ATTR_XD)) o << "IC_VEX_L_XD"; else if ((index & ATTR_VEXL) && (index & ATTR_XS)) o << "IC_VEX_L_XS"; else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_OPSIZE)) o << "IC_VEX_W_OPSIZE"; else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XD)) o << "IC_VEX_W_XD"; else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XS)) o << "IC_VEX_W_XS"; else if (index & ATTR_VEXL) o << "IC_VEX_L"; else if ((index & ATTR_VEX) && (index & ATTR_REXW)) o << "IC_VEX_W"; else if ((index & ATTR_VEX) && (index & ATTR_OPSIZE)) o << "IC_VEX_OPSIZE"; else if ((index & ATTR_VEX) && (index & ATTR_XD)) o << "IC_VEX_XD"; else if ((index & ATTR_VEX) && (index & ATTR_XS)) o << "IC_VEX_XS"; else if (index & ATTR_VEX) o << "IC_VEX"; else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XS)) o << "IC_64BIT_REXW_XS"; else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XD)) o << "IC_64BIT_REXW_XD"; else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_OPSIZE)) o << "IC_64BIT_REXW_OPSIZE"; else if ((index & ATTR_64BIT) && (index & ATTR_XD) && (index & ATTR_OPSIZE)) o << "IC_64BIT_XD_OPSIZE"; else if ((index & ATTR_64BIT) && (index & ATTR_XS) && (index & ATTR_OPSIZE)) o << "IC_64BIT_XS_OPSIZE"; else if ((index & ATTR_64BIT) && (index & ATTR_XS)) o << "IC_64BIT_XS"; else if ((index & ATTR_64BIT) && (index & ATTR_XD)) o << "IC_64BIT_XD"; else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE)) o << "IC_64BIT_OPSIZE"; else if ((index & ATTR_64BIT) && (index & ATTR_ADSIZE)) o << "IC_64BIT_ADSIZE"; else if ((index & ATTR_64BIT) && (index & ATTR_REXW)) o << "IC_64BIT_REXW"; else if ((index & ATTR_64BIT)) o << "IC_64BIT"; else if ((index & ATTR_XS) && (index & ATTR_OPSIZE)) o << "IC_XS_OPSIZE"; else if ((index & ATTR_XD) && (index & ATTR_OPSIZE)) o << "IC_XD_OPSIZE"; else if (index & ATTR_XS) o << "IC_XS"; else if (index & ATTR_XD) o << "IC_XD"; else if (index & ATTR_OPSIZE) o << "IC_OPSIZE"; else if (index & ATTR_ADSIZE) o << "IC_ADSIZE"; else o << "IC"; if (index < tableSize - 1) o << ","; else o << " "; o << " /* " << index << " */"; o << "\n"; } i--; o.indent(i * 2) << "};" << "\n"; }
/// EmitMatcher - Emit bytes for the specified matcher and return /// the number of bytes emitted. unsigned MatcherTableEmitter:: EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, raw_ostream &OS) { OS.indent(Indent*2); switch (N->getKind()) { case Matcher::Scope: { const ScopeMatcher *SM = cast<ScopeMatcher>(N); assert(SM->getNext() == nullptr && "Shouldn't have next after scope"); unsigned StartIdx = CurrentIdx; // Emit all of the children. for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i) { if (i == 0) { OS << "OPC_Scope, "; ++CurrentIdx; } else { if (!OmitComments) { OS << "/*" << format_decimal(CurrentIdx, IndexWidth) << "*/"; OS.indent(Indent*2) << "/*Scope*/ "; } else OS.indent(Indent*2); } // We need to encode the child and the offset of the failure code before // emitting either of them. Handle this by buffering the output into a // string while we get the size. Unfortunately, the offset of the // children depends on the VBR size of the child, so for large children we // have to iterate a bit. SmallString<128> TmpBuf; unsigned ChildSize = 0; unsigned VBRSize = 0; do { VBRSize = GetVBRSize(ChildSize); TmpBuf.clear(); raw_svector_ostream OS(TmpBuf); ChildSize = EmitMatcherList(SM->getChild(i), Indent+1, CurrentIdx+VBRSize, OS); } while (GetVBRSize(ChildSize) != VBRSize); assert(ChildSize != 0 && "Should not have a zero-sized child!"); CurrentIdx += EmitVBRValue(ChildSize, OS); if (!OmitComments) { OS << "/*->" << CurrentIdx+ChildSize << "*/"; if (i == 0) OS << " // " << SM->getNumChildren() << " children in Scope"; } OS << '\n' << TmpBuf; CurrentIdx += ChildSize; } // Emit a zero as a sentinel indicating end of 'Scope'. if (!OmitComments) OS << "/*" << format_decimal(CurrentIdx, IndexWidth) << "*/"; OS.indent(Indent*2) << "0, "; if (!OmitComments) OS << "/*End of Scope*/"; OS << '\n'; return CurrentIdx - StartIdx + 1; } case Matcher::RecordNode: OS << "OPC_RecordNode,"; if (!OmitComments) OS << " // #" << cast<RecordMatcher>(N)->getResultNo() << " = " << cast<RecordMatcher>(N)->getWhatFor(); OS << '\n'; return 1; case Matcher::RecordChild: OS << "OPC_RecordChild" << cast<RecordChildMatcher>(N)->getChildNo() << ','; if (!OmitComments) OS << " // #" << cast<RecordChildMatcher>(N)->getResultNo() << " = " << cast<RecordChildMatcher>(N)->getWhatFor(); OS << '\n'; return 1; case Matcher::RecordMemRef: OS << "OPC_RecordMemRef,\n"; return 1; case Matcher::CaptureGlueInput: OS << "OPC_CaptureGlueInput,\n"; return 1; case Matcher::MoveChild: { const auto *MCM = cast<MoveChildMatcher>(N); OS << "OPC_MoveChild"; // Handle the specialized forms. if (MCM->getChildNo() >= 8) OS << ", "; OS << MCM->getChildNo() << ",\n"; return (MCM->getChildNo() >= 8) ? 2 : 1; } case Matcher::MoveParent: OS << "OPC_MoveParent,\n"; return 1; case Matcher::CheckSame: OS << "OPC_CheckSame, " << cast<CheckSameMatcher>(N)->getMatchNumber() << ",\n"; return 2; case Matcher::CheckChildSame: OS << "OPC_CheckChild" << cast<CheckChildSameMatcher>(N)->getChildNo() << "Same, " << cast<CheckChildSameMatcher>(N)->getMatchNumber() << ",\n"; return 2; case Matcher::CheckPatternPredicate: { StringRef Pred =cast<CheckPatternPredicateMatcher>(N)->getPredicate(); OS << "OPC_CheckPatternPredicate, " << getPatternPredicate(Pred) << ','; if (!OmitComments) OS << " // " << Pred; OS << '\n'; return 2; } case Matcher::CheckPredicate: { TreePredicateFn Pred = cast<CheckPredicateMatcher>(N)->getPredicate(); unsigned OperandBytes = 0; if (Pred.usesOperands()) { unsigned NumOps = cast<CheckPredicateMatcher>(N)->getNumOperands(); OS << "OPC_CheckPredicateWithOperands, " << NumOps << "/*#Ops*/, "; for (unsigned i = 0; i < NumOps; ++i) OS << cast<CheckPredicateMatcher>(N)->getOperandNo(i) << ", "; OperandBytes = 1 + NumOps; } else { OS << "OPC_CheckPredicate, "; } OS << getNodePredicate(Pred) << ','; if (!OmitComments) OS << " // " << Pred.getFnName(); OS << '\n'; return 2 + OperandBytes; } case Matcher::CheckOpcode: OS << "OPC_CheckOpcode, TARGET_VAL(" << cast<CheckOpcodeMatcher>(N)->getOpcode().getEnumName() << "),\n"; return 3; case Matcher::SwitchOpcode: case Matcher::SwitchType: { unsigned StartIdx = CurrentIdx; unsigned NumCases; if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) { OS << "OPC_SwitchOpcode "; NumCases = SOM->getNumCases(); } else { OS << "OPC_SwitchType "; NumCases = cast<SwitchTypeMatcher>(N)->getNumCases(); } if (!OmitComments) OS << "/*" << NumCases << " cases */"; OS << ", "; ++CurrentIdx; // For each case we emit the size, then the opcode, then the matcher. for (unsigned i = 0, e = NumCases; i != e; ++i) { const Matcher *Child; unsigned IdxSize; if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) { Child = SOM->getCaseMatcher(i); IdxSize = 2; // size of opcode in table is 2 bytes. } else { Child = cast<SwitchTypeMatcher>(N)->getCaseMatcher(i); IdxSize = 1; // size of type in table is 1 byte. } // We need to encode the opcode and the offset of the case code before // emitting the case code. Handle this by buffering the output into a // string while we get the size. Unfortunately, the offset of the // children depends on the VBR size of the child, so for large children we // have to iterate a bit. SmallString<128> TmpBuf; unsigned ChildSize = 0; unsigned VBRSize = 0; do { VBRSize = GetVBRSize(ChildSize); TmpBuf.clear(); raw_svector_ostream OS(TmpBuf); ChildSize = EmitMatcherList(Child, Indent+1, CurrentIdx+VBRSize+IdxSize, OS); } while (GetVBRSize(ChildSize) != VBRSize); assert(ChildSize != 0 && "Should not have a zero-sized child!"); if (i != 0) { if (!OmitComments) OS << "/*" << format_decimal(CurrentIdx, IndexWidth) << "*/"; OS.indent(Indent*2); if (!OmitComments) OS << (isa<SwitchOpcodeMatcher>(N) ? "/*SwitchOpcode*/ " : "/*SwitchType*/ "); } // Emit the VBR. CurrentIdx += EmitVBRValue(ChildSize, OS); if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) OS << "TARGET_VAL(" << SOM->getCaseOpcode(i).getEnumName() << "),"; else OS << getEnumName(cast<SwitchTypeMatcher>(N)->getCaseType(i)) << ','; CurrentIdx += IdxSize; if (!OmitComments) OS << "// ->" << CurrentIdx+ChildSize; OS << '\n'; OS << TmpBuf; CurrentIdx += ChildSize; } // Emit the final zero to terminate the switch. if (!OmitComments) OS << "/*" << format_decimal(CurrentIdx, IndexWidth) << "*/"; OS.indent(Indent*2) << "0,"; if (!OmitComments) OS << (isa<SwitchOpcodeMatcher>(N) ? " // EndSwitchOpcode" : " // EndSwitchType"); OS << '\n'; ++CurrentIdx; return CurrentIdx-StartIdx; } case Matcher::CheckType: if (cast<CheckTypeMatcher>(N)->getResNo() == 0) { OS << "OPC_CheckType, " << getEnumName(cast<CheckTypeMatcher>(N)->getType()) << ",\n"; return 2; } OS << "OPC_CheckTypeRes, " << cast<CheckTypeMatcher>(N)->getResNo() << ", " << getEnumName(cast<CheckTypeMatcher>(N)->getType()) << ",\n"; return 3; case Matcher::CheckChildType: OS << "OPC_CheckChild" << cast<CheckChildTypeMatcher>(N)->getChildNo() << "Type, " << getEnumName(cast<CheckChildTypeMatcher>(N)->getType()) << ",\n"; return 2; case Matcher::CheckInteger: { OS << "OPC_CheckInteger, "; unsigned Bytes=1+EmitVBRValue(cast<CheckIntegerMatcher>(N)->getValue(), OS); OS << '\n'; return Bytes; } case Matcher::CheckChildInteger: { OS << "OPC_CheckChild" << cast<CheckChildIntegerMatcher>(N)->getChildNo() << "Integer, "; unsigned Bytes=1+EmitVBRValue(cast<CheckChildIntegerMatcher>(N)->getValue(), OS); OS << '\n'; return Bytes; } case Matcher::CheckCondCode: OS << "OPC_CheckCondCode, ISD::" << cast<CheckCondCodeMatcher>(N)->getCondCodeName() << ",\n"; return 2; case Matcher::CheckChild2CondCode: OS << "OPC_CheckChild2CondCode, ISD::" << cast<CheckChild2CondCodeMatcher>(N)->getCondCodeName() << ",\n"; return 2; case Matcher::CheckValueType: OS << "OPC_CheckValueType, MVT::" << cast<CheckValueTypeMatcher>(N)->getTypeName() << ",\n"; return 2; case Matcher::CheckComplexPat: { const CheckComplexPatMatcher *CCPM = cast<CheckComplexPatMatcher>(N); const ComplexPattern &Pattern = CCPM->getPattern(); OS << "OPC_CheckComplexPat, /*CP*/" << getComplexPat(Pattern) << ", /*#*/" << CCPM->getMatchNumber() << ','; if (!OmitComments) { OS << " // " << Pattern.getSelectFunc(); OS << ":$" << CCPM->getName(); for (unsigned i = 0, e = Pattern.getNumOperands(); i != e; ++i) OS << " #" << CCPM->getFirstResult()+i; if (Pattern.hasProperty(SDNPHasChain)) OS << " + chain result"; } OS << '\n'; return 3; } case Matcher::CheckAndImm: { OS << "OPC_CheckAndImm, "; unsigned Bytes=1+EmitVBRValue(cast<CheckAndImmMatcher>(N)->getValue(), OS); OS << '\n'; return Bytes; } case Matcher::CheckOrImm: { OS << "OPC_CheckOrImm, "; unsigned Bytes = 1+EmitVBRValue(cast<CheckOrImmMatcher>(N)->getValue(), OS); OS << '\n'; return Bytes; } case Matcher::CheckFoldableChainNode: OS << "OPC_CheckFoldableChainNode,\n"; return 1; case Matcher::CheckImmAllOnesV: OS << "OPC_CheckImmAllOnesV,\n"; return 1; case Matcher::CheckImmAllZerosV: OS << "OPC_CheckImmAllZerosV,\n"; return 1; case Matcher::EmitInteger: { int64_t Val = cast<EmitIntegerMatcher>(N)->getValue(); OS << "OPC_EmitInteger, " << getEnumName(cast<EmitIntegerMatcher>(N)->getVT()) << ", "; unsigned Bytes = 2+EmitVBRValue(Val, OS); OS << '\n'; return Bytes; } case Matcher::EmitStringInteger: { const std::string &Val = cast<EmitStringIntegerMatcher>(N)->getValue(); // These should always fit into one byte. OS << "OPC_EmitInteger, " << getEnumName(cast<EmitStringIntegerMatcher>(N)->getVT()) << ", " << Val << ",\n"; return 3; } case Matcher::EmitRegister: { const EmitRegisterMatcher *Matcher = cast<EmitRegisterMatcher>(N); const CodeGenRegister *Reg = Matcher->getReg(); // If the enum value of the register is larger than one byte can handle, // use EmitRegister2. if (Reg && Reg->EnumValue > 255) { OS << "OPC_EmitRegister2, " << getEnumName(Matcher->getVT()) << ", "; OS << "TARGET_VAL(" << getQualifiedName(Reg->TheDef) << "),\n"; return 4; } else { OS << "OPC_EmitRegister, " << getEnumName(Matcher->getVT()) << ", "; if (Reg) { OS << getQualifiedName(Reg->TheDef) << ",\n"; } else { OS << "0 "; if (!OmitComments) OS << "/*zero_reg*/"; OS << ",\n"; } return 3; } } case Matcher::EmitConvertToTarget: OS << "OPC_EmitConvertToTarget, " << cast<EmitConvertToTargetMatcher>(N)->getSlot() << ",\n"; return 2; case Matcher::EmitMergeInputChains: { const EmitMergeInputChainsMatcher *MN = cast<EmitMergeInputChainsMatcher>(N); // Handle the specialized forms OPC_EmitMergeInputChains1_0, 1_1, and 1_2. if (MN->getNumNodes() == 1 && MN->getNode(0) < 3) { OS << "OPC_EmitMergeInputChains1_" << MN->getNode(0) << ",\n"; return 1; } OS << "OPC_EmitMergeInputChains, " << MN->getNumNodes() << ", "; for (unsigned i = 0, e = MN->getNumNodes(); i != e; ++i) OS << MN->getNode(i) << ", "; OS << '\n'; return 2+MN->getNumNodes(); } case Matcher::EmitCopyToReg: OS << "OPC_EmitCopyToReg, " << cast<EmitCopyToRegMatcher>(N)->getSrcSlot() << ", " << getQualifiedName(cast<EmitCopyToRegMatcher>(N)->getDestPhysReg()) << ",\n"; return 3; case Matcher::EmitNodeXForm: { const EmitNodeXFormMatcher *XF = cast<EmitNodeXFormMatcher>(N); OS << "OPC_EmitNodeXForm, " << getNodeXFormID(XF->getNodeXForm()) << ", " << XF->getSlot() << ','; if (!OmitComments) OS << " // "<<XF->getNodeXForm()->getName(); OS <<'\n'; return 3; } case Matcher::EmitNode: case Matcher::MorphNodeTo: { auto NumCoveredBytes = 0; if (InstrumentCoverage) { if (const MorphNodeToMatcher *SNT = dyn_cast<MorphNodeToMatcher>(N)) { NumCoveredBytes = 3; OS << "OPC_Coverage, "; std::string src = GetPatFromTreePatternNode(SNT->getPattern().getSrcPattern()); std::string dst = GetPatFromTreePatternNode(SNT->getPattern().getDstPattern()); Record *PatRecord = SNT->getPattern().getSrcRecord(); std::string include_src = getIncludePath(PatRecord); unsigned Offset = getPatternIdxFromTable(src + " -> " + dst, std::move(include_src)); OS << "TARGET_VAL(" << Offset << "),\n"; OS.indent(FullIndexWidth + Indent * 2); } } const EmitNodeMatcherCommon *EN = cast<EmitNodeMatcherCommon>(N); OS << (isa<EmitNodeMatcher>(EN) ? "OPC_EmitNode" : "OPC_MorphNodeTo"); bool CompressVTs = EN->getNumVTs() < 3; if (CompressVTs) OS << EN->getNumVTs(); OS << ", TARGET_VAL(" << EN->getOpcodeName() << "), 0"; if (EN->hasChain()) OS << "|OPFL_Chain"; 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(); OS << ",\n"; OS.indent(FullIndexWidth + Indent*2+4); if (!CompressVTs) { OS << EN->getNumVTs(); if (!OmitComments) OS << "/*#VTs*/"; OS << ", "; } for (unsigned i = 0, e = EN->getNumVTs(); i != e; ++i) OS << getEnumName(EN->getVT(i)) << ", "; OS << EN->getNumOperands(); if (!OmitComments) OS << "/*#Ops*/"; OS << ", "; unsigned NumOperandBytes = 0; for (unsigned i = 0, e = EN->getNumOperands(); i != e; ++i) NumOperandBytes += EmitVBRValue(EN->getOperand(i), OS); if (!OmitComments) { // Print the result #'s for EmitNode. if (const EmitNodeMatcher *E = dyn_cast<EmitNodeMatcher>(EN)) { if (unsigned NumResults = EN->getNumVTs()) { OS << " // Results ="; unsigned First = E->getFirstResultSlot(); for (unsigned i = 0; i != NumResults; ++i) OS << " #" << First+i; } } OS << '\n'; if (const MorphNodeToMatcher *SNT = dyn_cast<MorphNodeToMatcher>(N)) { OS.indent(FullIndexWidth + Indent*2) << "// Src: " << *SNT->getPattern().getSrcPattern() << " - Complexity = " << SNT->getPattern().getPatternComplexity(CGP) << '\n'; OS.indent(FullIndexWidth + Indent*2) << "// Dst: " << *SNT->getPattern().getDstPattern() << '\n'; } } else OS << '\n'; return 5 + !CompressVTs + EN->getNumVTs() + NumOperandBytes + NumCoveredBytes; } case Matcher::CompleteMatch: { const CompleteMatchMatcher *CM = cast<CompleteMatchMatcher>(N); auto NumCoveredBytes = 0; if (InstrumentCoverage) { NumCoveredBytes = 3; OS << "OPC_Coverage, "; std::string src = GetPatFromTreePatternNode(CM->getPattern().getSrcPattern()); std::string dst = GetPatFromTreePatternNode(CM->getPattern().getDstPattern()); Record *PatRecord = CM->getPattern().getSrcRecord(); std::string include_src = getIncludePath(PatRecord); unsigned Offset = getPatternIdxFromTable(src + " -> " + dst, std::move(include_src)); OS << "TARGET_VAL(" << Offset << "),\n"; OS.indent(FullIndexWidth + Indent * 2); } OS << "OPC_CompleteMatch, " << CM->getNumResults() << ", "; unsigned NumResultBytes = 0; for (unsigned i = 0, e = CM->getNumResults(); i != e; ++i) NumResultBytes += EmitVBRValue(CM->getResult(i), OS); OS << '\n'; if (!OmitComments) { OS.indent(FullIndexWidth + Indent*2) << " // Src: " << *CM->getPattern().getSrcPattern() << " - Complexity = " << CM->getPattern().getPatternComplexity(CGP) << '\n'; OS.indent(FullIndexWidth + Indent*2) << " // Dst: " << *CM->getPattern().getDstPattern(); } OS << '\n'; return 2 + NumResultBytes + NumCoveredBytes; } } llvm_unreachable("Unreachable"); }
void Module::print(raw_ostream &OS, unsigned Indent) const { OS.indent(Indent); if (IsFramework) OS << "framework "; if (IsExplicit) OS << "explicit "; OS << "module " << Name; if (IsSystem) { OS.indent(Indent + 2); OS << " [system]"; } OS << " {\n"; if (!Requires.empty()) { OS.indent(Indent + 2); OS << "requires "; for (unsigned I = 0, N = Requires.size(); I != N; ++I) { if (I) OS << ", "; OS << Requires[I]; } OS << "\n"; } if (const FileEntry *UmbrellaHeader = getUmbrellaHeader()) { OS.indent(Indent + 2); OS << "umbrella header \""; OS.write_escaped(UmbrellaHeader->getName()); OS << "\"\n"; } else if (const DirectoryEntry *UmbrellaDir = getUmbrellaDir()) { OS.indent(Indent + 2); OS << "umbrella \""; OS.write_escaped(UmbrellaDir->getName()); OS << "\"\n"; } if (!ConfigMacros.empty() || ConfigMacrosExhaustive) { OS.indent(Indent + 2); OS << "config_macros "; if (ConfigMacrosExhaustive) OS << "[exhaustive]"; for (unsigned I = 0, N = ConfigMacros.size(); I != N; ++I) { if (I) OS << ", "; OS << ConfigMacros[I]; } OS << "\n"; } for (unsigned I = 0, N = NormalHeaders.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "header \""; OS.write_escaped(NormalHeaders[I]->getName()); OS << "\"\n"; } for (unsigned I = 0, N = ExcludedHeaders.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "exclude header \""; OS.write_escaped(ExcludedHeaders[I]->getName()); OS << "\"\n"; } for (unsigned I = 0, N = PrivateHeaders.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "private header \""; OS.write_escaped(PrivateHeaders[I]->getName()); OS << "\"\n"; } for (submodule_const_iterator MI = submodule_begin(), MIEnd = submodule_end(); MI != MIEnd; ++MI) (*MI)->print(OS, Indent + 2); for (unsigned I = 0, N = Exports.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "export "; if (Module *Restriction = Exports[I].getPointer()) { OS << Restriction->getFullModuleName(); if (Exports[I].getInt()) OS << ".*"; } else { OS << "*"; } OS << "\n"; } for (unsigned I = 0, N = UnresolvedExports.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "export "; printModuleId(OS, UnresolvedExports[I].Id); if (UnresolvedExports[I].Wildcard) { if (UnresolvedExports[I].Id.empty()) OS << "*"; else OS << ".*"; } OS << "\n"; } for (unsigned I = 0, N = LinkLibraries.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "link "; if (LinkLibraries[I].IsFramework) OS << "framework "; OS << "\""; OS.write_escaped(LinkLibraries[I].Library); OS << "\""; } for (unsigned I = 0, N = UnresolvedConflicts.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "conflict "; printModuleId(OS, UnresolvedConflicts[I].Id); OS << ", \""; OS.write_escaped(UnresolvedConflicts[I].Message); OS << "\"\n"; } for (unsigned I = 0, N = Conflicts.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "conflict "; OS << Conflicts[I].Other->getFullModuleName(); OS << ", \""; OS.write_escaped(Conflicts[I].Message); OS << "\"\n"; } if (InferSubmodules) { OS.indent(Indent + 2); if (InferExplicitSubmodules) OS << "explicit "; OS << "module * {\n"; if (InferExportWildcard) { OS.indent(Indent + 4); OS << "export *\n"; } OS.indent(Indent + 2); OS << "}\n"; } OS.indent(Indent); OS << "}\n"; }
void EmitCopyToRegMatcher::printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "EmitCopyToReg <todo: args>\n"; }
void EmitNodeXFormMatcher::printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "EmitNodeXForm " << NodeXForm->getName() << " Slot=" << Slot << '\n'; }
void EmitConvertToTargetMatcher:: printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "EmitConvertToTarget " << Slot << '\n'; }
void EmitMergeInputChainsMatcher:: printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "EmitMergeInputChains <todo: args>\n"; }
void EmitStringIntegerMatcher:: printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "EmitStringInteger " << Val << " VT=" << getEnumName(VT) << '\n'; }
void CheckImmAllZerosVMatcher::printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "CheckAllZerosV\n"; }
void CheckFoldableChainNodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "CheckFoldableChainNode\n"; }
void OtherPlatformAvailabilitySpec::print(raw_ostream &OS, unsigned Indent) const { OS.indent(Indent) << '(' << "other_constraint_availability_spec" << " " << ')'; }
void CompleteMatchMatcher::printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "CompleteMatch <todo args>\n"; OS.indent(indent) << "Src = " << *Pattern.getSrcPattern() << "\n"; OS.indent(indent) << "Dst = " << *Pattern.getDstPattern() << "\n"; }
void Module::print(raw_ostream &OS, unsigned Indent) const { OS.indent(Indent); if (IsFramework) OS << "framework "; if (IsExplicit) OS << "explicit "; OS << "module " << Name; if (IsSystem || IsExternC) { OS.indent(Indent + 2); if (IsSystem) OS << " [system]"; if (IsExternC) OS << " [extern_c]"; } OS << " {\n"; if (!Requirements.empty()) { OS.indent(Indent + 2); OS << "requires "; for (unsigned I = 0, N = Requirements.size(); I != N; ++I) { if (I) OS << ", "; if (!Requirements[I].second) OS << "!"; OS << Requirements[I].first; } OS << "\n"; } if (Header H = getUmbrellaHeader()) { OS.indent(Indent + 2); OS << "umbrella header \""; OS.write_escaped(H.NameAsWritten); OS << "\"\n"; } else if (DirectoryName D = getUmbrellaDir()) { OS.indent(Indent + 2); OS << "umbrella \""; OS.write_escaped(D.NameAsWritten); OS << "\"\n"; } if (!ConfigMacros.empty() || ConfigMacrosExhaustive) { OS.indent(Indent + 2); OS << "config_macros "; if (ConfigMacrosExhaustive) OS << "[exhaustive]"; for (unsigned I = 0, N = ConfigMacros.size(); I != N; ++I) { if (I) OS << ", "; OS << ConfigMacros[I]; } OS << "\n"; } struct { StringRef Prefix; HeaderKind Kind; } Kinds[] = {{"", HK_Normal}, {"textual ", HK_Textual}, {"private ", HK_Private}, {"private textual ", HK_PrivateTextual}, {"exclude ", HK_Excluded}}; for (auto &K : Kinds) { for (auto &H : Headers[K.Kind]) { OS.indent(Indent + 2); OS << K.Prefix << "header \""; OS.write_escaped(H.NameAsWritten); OS << "\"\n"; } } for (submodule_const_iterator MI = submodule_begin(), MIEnd = submodule_end(); MI != MIEnd; ++MI) // Print inferred subframework modules so that we don't need to re-infer // them (requires expensive directory iteration + stat calls) when we build // the module. Regular inferred submodules are OK, as we need to look at all // those header files anyway. if (!(*MI)->IsInferred || (*MI)->IsFramework) (*MI)->print(OS, Indent + 2); for (unsigned I = 0, N = Exports.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "export "; if (Module *Restriction = Exports[I].getPointer()) { OS << Restriction->getFullModuleName(); if (Exports[I].getInt()) OS << ".*"; } else { OS << "*"; } OS << "\n"; } for (unsigned I = 0, N = UnresolvedExports.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "export "; printModuleId(OS, UnresolvedExports[I].Id); if (UnresolvedExports[I].Wildcard) OS << (UnresolvedExports[I].Id.empty() ? "*" : ".*"); OS << "\n"; } for (unsigned I = 0, N = DirectUses.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "use "; OS << DirectUses[I]->getFullModuleName(); OS << "\n"; } for (unsigned I = 0, N = UnresolvedDirectUses.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "use "; printModuleId(OS, UnresolvedDirectUses[I]); OS << "\n"; } for (unsigned I = 0, N = LinkLibraries.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "link "; if (LinkLibraries[I].IsFramework) OS << "framework "; OS << "\""; OS.write_escaped(LinkLibraries[I].Library); OS << "\""; } for (unsigned I = 0, N = UnresolvedConflicts.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "conflict "; printModuleId(OS, UnresolvedConflicts[I].Id); OS << ", \""; OS.write_escaped(UnresolvedConflicts[I].Message); OS << "\"\n"; } for (unsigned I = 0, N = Conflicts.size(); I != N; ++I) { OS.indent(Indent + 2); OS << "conflict "; OS << Conflicts[I].Other->getFullModuleName(); OS << ", \""; OS.write_escaped(Conflicts[I].Message); OS << "\"\n"; } if (InferSubmodules) { OS.indent(Indent + 2); if (InferExplicitSubmodules) OS << "explicit "; OS << "module * {\n"; if (InferExportWildcard) { OS.indent(Indent + 4); OS << "export *\n"; } OS.indent(Indent + 2); OS << "}\n"; } OS.indent(Indent); OS << "}\n"; }
/// emitEmptyTable - Emits the modRMEmptyTable, which is used as a ID table by /// all ModR/M decisions for instructions that are invalid for all possible /// ModR/M byte values. /// /// @param o - The output stream on which to emit the table. /// @param i - The indentation level for that output stream. static void emitEmptyTable(raw_ostream &o, uint32_t &i) { o.indent(i * 2) << "static const InstrUID modRMEmptyTable[1] = { 0 };\n"; o << "\n"; }
void AMDGPUInstPrinter::printLast(const MCInst *MI, unsigned OpNo, raw_ostream &O) { printIfSet(MI, OpNo, O.indent(25 - O.GetNumBytesInBuffer()), "*", " "); }
void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2, uint32_t &i1, uint32_t &i2, ModRMDecision &decision) const { static uint64_t sTableNumber = 0; uint64_t thisTableNumber = sTableNumber; ModRMDecisionType dt = getDecisionType(decision); uint16_t index; if (dt == MODRM_ONEENTRY && decision.instructionIDs[0] == 0) { o2.indent(i2) << "{ /* ModRMDecision */" << "\n"; i2++; o2.indent(i2) << stringForDecisionType(dt) << "," << "\n"; o2.indent(i2) << "modRMEmptyTable"; i2--; o2.indent(i2) << "}"; return; } o1.indent(i1) << "static const InstrUID modRMTable" << thisTableNumber; switch (dt) { default: llvm_unreachable("Unknown decision type"); case MODRM_ONEENTRY: o1 << "[1]"; break; case MODRM_SPLITRM: o1 << "[2]"; break; case MODRM_FULL: o1 << "[256]"; break; } o1 << " = {" << "\n"; i1++; switch (dt) { default: llvm_unreachable("Unknown decision type"); case MODRM_ONEENTRY: emitOneID(o1, i1, decision.instructionIDs[0], false); break; case MODRM_SPLITRM: emitOneID(o1, i1, decision.instructionIDs[0x00], true); // mod = 0b00 emitOneID(o1, i1, decision.instructionIDs[0xc0], false); // mod = 0b11 break; case MODRM_FULL: for (index = 0; index < 256; ++index) emitOneID(o1, i1, decision.instructionIDs[index], index < 255); break; } i1--; o1.indent(i1) << "};" << "\n"; o1 << "\n"; o2.indent(i2) << "{ /* struct ModRMDecision */" << "\n"; i2++; o2.indent(i2) << stringForDecisionType(dt) << "," << "\n"; o2.indent(i2) << "modRMTable" << sTableNumber << "\n"; i2--; o2.indent(i2) << "}"; ++sTableNumber; }
unsigned DeclContext::printContext(raw_ostream &OS, const unsigned indent, const bool onlyAPartialLine) const { unsigned Depth = 0; if (!onlyAPartialLine) if (auto *P = getParent()) Depth = P->printContext(OS, indent); const char *Kind; switch (getContextKind()) { case DeclContextKind::Module: Kind = "Module"; break; case DeclContextKind::FileUnit: Kind = "FileUnit"; break; case DeclContextKind::SerializedLocal: Kind = "Serialized Local"; break; case DeclContextKind::AbstractClosureExpr: Kind = "AbstractClosureExpr"; break; case DeclContextKind::GenericTypeDecl: switch (cast<GenericTypeDecl>(this)->getKind()) { #define DECL(ID, PARENT) \ case DeclKind::ID: Kind = #ID "Decl"; break; #include "swift/AST/DeclNodes.def" } break; case DeclContextKind::ExtensionDecl: Kind = "ExtensionDecl"; break; case DeclContextKind::TopLevelCodeDecl: Kind = "TopLevelCodeDecl"; break; case DeclContextKind::Initializer: Kind = "Initializer"; break; case DeclContextKind::AbstractFunctionDecl: Kind = "AbstractFunctionDecl"; break; case DeclContextKind::SubscriptDecl: Kind = "SubscriptDecl"; break; case DeclContextKind::EnumElementDecl: Kind = "EnumElementDecl"; break; } OS.indent(Depth*2 + indent) << (void*)this << " " << Kind; switch (getContextKind()) { case DeclContextKind::Module: OS << " name=" << cast<ModuleDecl>(this)->getName(); break; case DeclContextKind::FileUnit: switch (cast<FileUnit>(this)->getKind()) { case FileUnitKind::Builtin: OS << " Builtin"; break; case FileUnitKind::Source: OS << " file=\"" << cast<SourceFile>(this)->getFilename() << "\""; break; case FileUnitKind::SerializedAST: case FileUnitKind::ClangModule: case FileUnitKind::DWARFModule: OS << " file=\"" << cast<LoadedFile>(this)->getFilename() << "\""; break; } break; case DeclContextKind::AbstractClosureExpr: OS << " line=" << getLineNumber(cast<AbstractClosureExpr>(this)); OS << " : " << cast<AbstractClosureExpr>(this)->getType(); break; case DeclContextKind::GenericTypeDecl: OS << " name=" << cast<GenericTypeDecl>(this)->getName(); break; case DeclContextKind::ExtensionDecl: OS << " line=" << getLineNumber(cast<ExtensionDecl>(this)); OS << " base=" << cast<ExtensionDecl>(this)->getExtendedType(); break; case DeclContextKind::TopLevelCodeDecl: OS << " line=" << getLineNumber(cast<TopLevelCodeDecl>(this)); break; case DeclContextKind::AbstractFunctionDecl: { auto *AFD = cast<AbstractFunctionDecl>(this); OS << " name=" << AFD->getFullName(); if (AFD->hasInterfaceType()) OS << " : " << AFD->getInterfaceType(); else OS << " : (no type set)"; break; } case DeclContextKind::SubscriptDecl: { auto *SD = cast<SubscriptDecl>(this); OS << " name=" << SD->getBaseName(); if (SD->hasInterfaceType()) OS << " : " << SD->getInterfaceType(); else OS << " : (no type set)"; break; } case DeclContextKind::EnumElementDecl: { auto *EED = cast<EnumElementDecl>(this); OS << " name=" << EED->getBaseName(); if (EED->hasInterfaceType()) OS << " : " << EED->getInterfaceType(); else OS << " : (no type set)"; break; } case DeclContextKind::Initializer: switch (cast<Initializer>(this)->getInitializerKind()) { case InitializerKind::PatternBinding: { auto init = cast<PatternBindingInitializer>(this); OS << " PatternBinding 0x" << (void*) init->getBinding() << " #" << init->getBindingIndex(); break; } case InitializerKind::DefaultArgument: { auto init = cast<DefaultArgumentInitializer>(this); OS << " DefaultArgument index=" << init->getIndex(); break; } } break; case DeclContextKind::SerializedLocal: { auto local = cast<SerializedLocalDeclContext>(this); switch (local->getLocalDeclContextKind()) { case LocalDeclContextKind::AbstractClosure: { auto serializedClosure = cast<SerializedAbstractClosureExpr>(local); OS << " closure : " << serializedClosure->getType(); break; } case LocalDeclContextKind::DefaultArgumentInitializer: { auto init = cast<SerializedDefaultArgumentInitializer>(local); OS << "DefaultArgument index=" << init->getIndex(); break; } case LocalDeclContextKind::PatternBindingInitializer: { auto init = cast<SerializedPatternBindingInitializer>(local); OS << " PatternBinding 0x" << (void*) init->getBinding() << " #" << init->getBindingIndex(); break; } case LocalDeclContextKind::TopLevelCodeDecl: OS << " TopLevelCode"; break; } } } if (!onlyAPartialLine) OS << "\n"; return Depth + 1; }
static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, uint32_t *OffsetPtr, dwarf::Attribute Attr, dwarf::Form Form, unsigned Indent, DIDumpOptions DumpOpts) { if (!Die.isValid()) return; const char BaseIndent[] = " "; OS << BaseIndent; OS.indent(Indent+2); auto attrString = AttributeString(Attr); if (!attrString.empty()) WithColor(OS, syntax::Attribute) << attrString; else WithColor(OS, syntax::Attribute).get() << format("DW_AT_Unknown_%x", Attr); if (DumpOpts.Verbose) { auto formString = FormEncodingString(Form); if (!formString.empty()) OS << " [" << formString << ']'; else OS << format(" [DW_FORM_Unknown_%x]", Form); } DWARFUnit *U = Die.getDwarfUnit(); DWARFFormValue formValue(Form); if (!formValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr, U)) return; OS << "\t("; StringRef Name; std::string File; auto Color = syntax::Enumerator; if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file) { Color = syntax::String; if (const auto *LT = U->getContext().getLineTableForUnit(U)) if (LT->getFileNameByIndex(formValue.getAsUnsignedConstant().getValue(), U->getCompilationDir(), DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) { File = '"' + File + '"'; Name = File; } } else if (Optional<uint64_t> Val = formValue.getAsUnsignedConstant()) Name = AttributeValueString(Attr, *Val); if (!Name.empty()) WithColor(OS, Color) << Name; else if (Attr == DW_AT_decl_line || Attr == DW_AT_call_line) OS << *formValue.getAsUnsignedConstant(); else if (Attr == DW_AT_location || Attr == DW_AT_frame_base || Attr == DW_AT_data_member_location) dumpLocation(OS, formValue, U, sizeof(BaseIndent) + Indent + 4, DumpOpts); else formValue.dump(OS, DumpOpts); // We have dumped the attribute raw value. For some attributes // having both the raw value and the pretty-printed value is // interesting. These attributes are handled below. if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin) { if (const char *Name = Die.getAttributeValueAsReferencedDie(Attr).getName(DINameKind::LinkageName)) OS << " \"" << Name << '\"'; } else if (Attr == DW_AT_APPLE_property_attribute) { if (Optional<uint64_t> OptVal = formValue.getAsUnsignedConstant()) dumpApplePropertyAttribute(OS, *OptVal); } else if (Attr == DW_AT_ranges) { const DWARFObject &Obj = Die.getDwarfUnit()->getContext().getDWARFObj(); dumpRanges(Obj, OS, Die.getAddressRanges(), U->getAddressByteSize(), sizeof(BaseIndent) + Indent + 4, DumpOpts); } OS << ")\n"; }
void DisassemblerTables::emitInstructionInfo(raw_ostream &o, unsigned &i) const { unsigned NumInstructions = InstructionSpecifiers.size(); o << "static const struct OperandSpecifier x86OperandSets[][" << X86_MAX_OPERANDS << "] = {\n"; typedef std::vector<std::pair<const char *, const char *> > OperandListTy; std::map<OperandListTy, unsigned> OperandSets; unsigned OperandSetNum = 0; for (unsigned Index = 0; Index < NumInstructions; ++Index) { OperandListTy OperandList; for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS; ++OperandIndex) { const char *Encoding = stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[Index] .operands[OperandIndex].encoding); const char *Type = stringForOperandType((OperandType)InstructionSpecifiers[Index] .operands[OperandIndex].type); OperandList.push_back(std::make_pair(Encoding, Type)); } unsigned &N = OperandSets[OperandList]; if (N != 0) continue; N = ++OperandSetNum; o << " { /* " << (OperandSetNum - 1) << " */\n"; for (unsigned i = 0, e = OperandList.size(); i != e; ++i) { o << " { " << OperandList[i].first << ", " << OperandList[i].second << " },\n"; } o << " },\n"; } o << "};" << "\n\n"; o.indent(i * 2) << "static const struct InstructionSpecifier "; o << INSTRUCTIONS_STR "[" << InstructionSpecifiers.size() << "] = {\n"; i++; for (unsigned index = 0; index < NumInstructions; ++index) { o.indent(i * 2) << "{ /* " << index << " */" << "\n"; i++; OperandListTy OperandList; for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS; ++OperandIndex) { const char *Encoding = stringForOperandEncoding((OperandEncoding)InstructionSpecifiers[index] .operands[OperandIndex].encoding); const char *Type = stringForOperandType((OperandType)InstructionSpecifiers[index] .operands[OperandIndex].type); OperandList.push_back(std::make_pair(Encoding, Type)); } o.indent(i * 2) << (OperandSets[OperandList] - 1) << ",\n"; o.indent(i * 2) << "/* " << InstructionSpecifiers[index].name << " */"; o << "\n"; i--; o.indent(i * 2) << "}"; if (index + 1 < NumInstructions) o << ","; o << "\n"; } i--; o.indent(i * 2) << "};" << "\n"; }
void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth, unsigned Indent, DIDumpOptions DumpOpts) const { if (!isValid()) return; DWARFDataExtractor debug_info_data = U->getDebugInfoExtractor(); const uint32_t Offset = getOffset(); uint32_t offset = Offset; if (DumpOpts.ShowChildren) RecurseDepth++; if (DumpOpts.ShowParents) { DumpOpts.ShowParents = false; Indent = dumpParentChain(getParent(), OS, Indent, DumpOpts); } if (debug_info_data.isValidOffset(offset)) { uint32_t abbrCode = debug_info_data.getULEB128(&offset); WithColor(OS, syntax::Address).get() << format("\n0x%8.8x: ", Offset); if (abbrCode) { auto AbbrevDecl = getAbbreviationDeclarationPtr(); if (AbbrevDecl) { auto tagString = TagString(getTag()); if (!tagString.empty()) WithColor(OS, syntax::Tag).get().indent(Indent) << tagString; else WithColor(OS, syntax::Tag).get().indent(Indent) << format("DW_TAG_Unknown_%x", getTag()); if (DumpOpts.Verbose) OS << format(" [%u] %c", abbrCode, AbbrevDecl->hasChildren() ? '*' : ' '); OS << '\n'; // Dump all data in the DIE for the attributes. for (const auto &AttrSpec : AbbrevDecl->attributes()) { if (AttrSpec.Form == DW_FORM_implicit_const) { // We are dumping .debug_info section , // implicit_const attribute values are not really stored here, // but in .debug_abbrev section. So we just skip such attrs. continue; } dumpAttribute(OS, *this, &offset, AttrSpec.Attr, AttrSpec.Form, Indent, DumpOpts); } DWARFDie child = getFirstChild(); if (RecurseDepth > 0 && child) { while (child) { child.dump(OS, RecurseDepth-1, Indent+2, DumpOpts); child = child.getSibling(); } } } else { OS << "Abbreviation code not found in 'debug_abbrev' class for code: " << abbrCode << '\n'; } } else { OS.indent(Indent) << "NULL\n"; } } }
void RecordChildMatcher::printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "RecordChild: " << ChildNo << '\n'; }
// 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) << "if ("; if (!emitPredicateMatch(o, Indentation, Opc)) o << "1"; 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->numFields() == 0 && I->Decoder.size()) { o.indent(Indentation) << " " << Emitter->GuardPrefix << I->Decoder << "(MI, insn, Address, Decoder)" << Emitter->GuardPostfix << "\n"; break; } emitBinaryParser(o, Indentation, *I); } o.indent(Indentation) << " return " << Emitter->ReturnOK << "; // " << nameWithID(Opc) << '\n'; o.indent(Indentation) << "}\n"; // Closing predicate block. 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 ("; if (emitPredicateMatch(o, Indentation, Opc)) { o << " &&\n"; o.indent(Indentation+4); } for (I = Size; I != 0; --I) { NumBits = EndBits[I-1] - StartBits[I-1] + 1; o << "fieldFromInstruction" << BitWidth << "(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->numFields() == 0 && I->Decoder.size()) { o.indent(Indentation) << " " << Emitter->GuardPrefix << I->Decoder << "(MI, insn, Address, Decoder)" << Emitter->GuardPostfix << "\n"; break; } emitBinaryParser(o, Indentation, *I); } o.indent(Indentation) << " return " << Emitter->ReturnOK << "; // " << nameWithID(Opc) << '\n'; o.indent(Indentation) << "}\n"; return false; }
void CaptureGlueInputMatcher::printImpl(raw_ostream &OS, unsigned indent) const{ OS.indent(indent) << "CaptureGlueInput\n"; }
void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { CodeGenTarget Target(Records); Record *AsmWriter = Target.getAsmWriter(); if (!AsmWriter->getValueAsBit("isMCAsmWriter")) return; O << "\n#ifdef PRINT_ALIAS_INSTR\n"; O << "#undef PRINT_ALIAS_INSTR\n\n"; EmitRegIsInRegClass(O); // Emit the method that prints the alias instruction. std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); std::vector<Record*> AllInstAliases = Records.getAllDerivedDefinitions("InstAlias"); // Create a map from the qualified name to a list of potential matches. std::map<std::string, std::vector<CodeGenInstAlias*> > AliasMap; for (std::vector<Record*>::iterator I = AllInstAliases.begin(), E = AllInstAliases.end(); I != E; ++I) { CodeGenInstAlias *Alias = new CodeGenInstAlias(*I, Target); const Record *R = *I; if (!R->getValueAsBit("EmitAlias")) continue; // We were told not to emit the alias, but to emit the aliasee. const DagInit *DI = R->getValueAsDag("ResultInst"); const DefInit *Op = dynamic_cast<const DefInit*>(DI->getOperator()); AliasMap[getQualifiedName(Op->getDef())].push_back(Alias); } // A map of which conditions need to be met for each instruction operand // before it can be matched to the mnemonic. std::map<std::string, std::vector<IAPrinter*> > IAPrinterMap; for (std::map<std::string, std::vector<CodeGenInstAlias*> >::iterator I = AliasMap.begin(), E = AliasMap.end(); I != E; ++I) { std::vector<CodeGenInstAlias*> &Aliases = I->second; for (std::vector<CodeGenInstAlias*>::iterator II = Aliases.begin(), IE = Aliases.end(); II != IE; ++II) { const CodeGenInstAlias *CGA = *II; unsigned LastOpNo = CGA->ResultInstOperandIndex.size(); unsigned NumResultOps = CountResultNumOperands(CGA->ResultInst->AsmString); // Don't emit the alias if it has more operands than what it's aliasing. if (NumResultOps < CountNumOperands(CGA->AsmString)) continue; IAPrinter *IAP = new IAPrinter(CGA->Result->getAsString(), CGA->AsmString); std::string Cond; Cond = std::string("MI->getNumOperands() == ") + llvm::utostr(LastOpNo); IAP->addCond(Cond); std::map<StringRef, unsigned> OpMap; bool CantHandle = false; for (unsigned i = 0, e = LastOpNo; i != e; ++i) { const CodeGenInstAlias::ResultOperand &RO = CGA->ResultOperands[i]; switch (RO.Kind) { case CodeGenInstAlias::ResultOperand::K_Record: { const Record *Rec = RO.getRecord(); StringRef ROName = RO.getName(); if (Rec->isSubClassOf("RegisterOperand")) Rec = Rec->getValueAsDef("RegClass"); if (Rec->isSubClassOf("RegisterClass")) { Cond = std::string("MI->getOperand(")+llvm::utostr(i)+").isReg()"; IAP->addCond(Cond); if (!IAP->isOpMapped(ROName)) { IAP->addOperand(ROName, i); Cond = std::string("regIsInRegisterClass(RC_") + CGA->ResultOperands[i].getRecord()->getName() + ", MI->getOperand(" + llvm::utostr(i) + ").getReg())"; IAP->addCond(Cond); } else { Cond = std::string("MI->getOperand(") + llvm::utostr(i) + ").getReg() == MI->getOperand(" + llvm::utostr(IAP->getOpIndex(ROName)) + ").getReg()"; IAP->addCond(Cond); } } else { assert(Rec->isSubClassOf("Operand") && "Unexpected operand!"); // FIXME: We may need to handle these situations. delete IAP; IAP = 0; CantHandle = true; break; } break; } case CodeGenInstAlias::ResultOperand::K_Imm: Cond = std::string("MI->getOperand(") + llvm::utostr(i) + ").getImm() == " + llvm::utostr(CGA->ResultOperands[i].getImm()); IAP->addCond(Cond); break; case CodeGenInstAlias::ResultOperand::K_Reg: // If this is zero_reg, something's playing tricks we're not // equipped to handle. if (!CGA->ResultOperands[i].getRegister()) { CantHandle = true; break; } Cond = std::string("MI->getOperand(") + llvm::utostr(i) + ").getReg() == " + Target.getName() + "::" + CGA->ResultOperands[i].getRegister()->getName(); IAP->addCond(Cond); break; } if (!IAP) break; } if (CantHandle) continue; IAPrinterMap[I->first].push_back(IAP); } } std::string Header; raw_string_ostream HeaderO(Header); HeaderO << "bool " << Target.getName() << ClassName << "::printAliasInstr(const MCInst" << " *MI, raw_ostream &OS) {\n"; std::string Cases; raw_string_ostream CasesO(Cases); for (std::map<std::string, std::vector<IAPrinter*> >::iterator I = IAPrinterMap.begin(), E = IAPrinterMap.end(); I != E; ++I) { std::vector<IAPrinter*> &IAPs = I->second; std::vector<IAPrinter*> UniqueIAPs; for (std::vector<IAPrinter*>::iterator II = IAPs.begin(), IE = IAPs.end(); II != IE; ++II) { IAPrinter *LHS = *II; bool IsDup = false; for (std::vector<IAPrinter*>::iterator III = IAPs.begin(), IIE = IAPs.end(); III != IIE; ++III) { IAPrinter *RHS = *III; if (LHS != RHS && *LHS == *RHS) { IsDup = true; break; } } if (!IsDup) UniqueIAPs.push_back(LHS); } if (UniqueIAPs.empty()) continue; CasesO.indent(2) << "case " << I->first << ":\n"; for (std::vector<IAPrinter*>::iterator II = UniqueIAPs.begin(), IE = UniqueIAPs.end(); II != IE; ++II) { IAPrinter *IAP = *II; CasesO.indent(4); IAP->print(CasesO); CasesO << '\n'; } CasesO.indent(4) << "return false;\n"; } if (CasesO.str().empty()) { O << HeaderO.str(); O << " return false;\n"; O << "}\n\n"; O << "#endif // PRINT_ALIAS_INSTR\n"; return; } EmitGetMapOperandNumber(O); O << HeaderO.str(); O.indent(2) << "StringRef AsmString;\n"; O.indent(2) << "SmallVector<std::pair<StringRef, unsigned>, 4> OpMap;\n"; O.indent(2) << "switch (MI->getOpcode()) {\n"; O.indent(2) << "default: return false;\n"; O << CasesO.str(); O.indent(2) << "}\n\n"; // Code that prints the alias, replacing the operands with the ones from the // MCInst. O << " std::pair<StringRef, StringRef> ASM = AsmString.split(' ');\n"; O << " OS << '\\t' << ASM.first;\n"; O << " if (!ASM.second.empty()) {\n"; O << " OS << '\\t';\n"; O << " for (StringRef::iterator\n"; O << " I = ASM.second.begin(), E = ASM.second.end(); I != E; ) {\n"; O << " if (*I == '$') {\n"; O << " StringRef::iterator Start = ++I;\n"; O << " while (I != E &&\n"; O << " ((*I >= 'a' && *I <= 'z') ||\n"; O << " (*I >= 'A' && *I <= 'Z') ||\n"; O << " (*I >= '0' && *I <= '9') ||\n"; O << " *I == '_'))\n"; O << " ++I;\n"; O << " StringRef Name(Start, I - Start);\n"; O << " printOperand(MI, getMapOperandNumber(OpMap, Name), OS);\n"; O << " } else {\n"; O << " OS << *I++;\n"; O << " }\n"; O << " }\n"; O << " }\n\n"; O << " return true;\n"; O << "}\n\n"; O << "#endif // PRINT_ALIAS_INSTR\n"; }
void MoveParentMatcher::printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "MoveParent\n"; }
void CheckComplexPatMatcher::printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "CheckComplexPat " << Pattern.getSelectFunc() << '\n'; }