From 88043c1958cb18f970095fa08b34a80c774cc2a9 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Thu, 19 May 2022 13:45:43 -0700 Subject: [PATCH] [TableGen] Add generation of argument register lists There are cases, like with -fzero-call-used-regs, where we need to know which registers can be used by a certain calling convention. This change generates a list of registers used by each calling convention defined in *CallingConv.td. Calling conventions that use registers conditioned on Swift have those registers placed in a separate list. This allows us to be flexible about whether to use the Swift registers or not. Reviewed By: nickdesaulniers Differential Revision: https://reviews.llvm.org/D125421 --- llvm/utils/TableGen/CallingConvEmitter.cpp | 138 ++++++++++++++++++++++++++--- 1 file changed, 127 insertions(+), 11 deletions(-) diff --git a/llvm/utils/TableGen/CallingConvEmitter.cpp b/llvm/utils/TableGen/CallingConvEmitter.cpp index fe5b13e..8f080cd 100644 --- a/llvm/utils/TableGen/CallingConvEmitter.cpp +++ b/llvm/utils/TableGen/CallingConvEmitter.cpp @@ -20,6 +20,14 @@ using namespace llvm; namespace { class CallingConvEmitter { RecordKeeper &Records; + unsigned Counter; + std::string CurrentAction; + bool SwiftAction; + + std::map> AssignedRegsMap; + std::map> AssignedSwiftRegsMap; + std::map> DelegateToMap; + public: explicit CallingConvEmitter(RecordKeeper &R) : Records(R) {} @@ -28,7 +36,7 @@ public: private: void EmitCallingConv(Record *CC, raw_ostream &O); void EmitAction(Record *Action, unsigned Indent, raw_ostream &O); - unsigned Counter; + void EmitArgRegisterLists(raw_ostream &O); }; } // End anonymous namespace @@ -38,6 +46,7 @@ void CallingConvEmitter::run(raw_ostream &O) { // Emit prototypes for all of the non-custom CC's so that they can forward ref // each other. Records.startTimer("Emit prototypes"); + O << "#ifndef GET_CC_REGISTER_LISTS\n\n"; for (Record *CC : CCs) { if (!CC->getValueAsBit("Custom")) { unsigned Pad = CC->getName().size(); @@ -58,18 +67,28 @@ void CallingConvEmitter::run(raw_ostream &O) { // Emit each non-custom calling convention description in full. Records.startTimer("Emit full descriptions"); for (Record *CC : CCs) { - if (!CC->getValueAsBit("Custom")) + if (!CC->getValueAsBit("Custom")) { EmitCallingConv(CC, O); + } } -} + EmitArgRegisterLists(O); + + O << "\n#endif // CC_REGISTER_LIST\n"; +} void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) { ListInit *CCActions = CC->getValueAsListInit("Actions"); Counter = 0; + CurrentAction = CC->getName().str(); + // Call upon the creation of a map entry from the void! + // We want an entry in AssignedRegsMap for every action, even if that + // entry is empty. + AssignedRegsMap[CurrentAction] = {}; + O << "\n\n"; - unsigned Pad = CC->getName().size(); + unsigned Pad = CurrentAction.size(); if (CC->getValueAsBit("Entry")) { O << "bool llvm::"; Pad += 12; @@ -77,13 +96,21 @@ void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) { O << "static bool "; Pad += 13; } - O << CC->getName() << "(unsigned ValNo, MVT ValVT,\n" + O << CurrentAction << "(unsigned ValNo, MVT ValVT,\n" << std::string(Pad, ' ') << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n" << std::string(Pad, ' ') << "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n"; // Emit all of the actions, in order. for (unsigned i = 0, e = CCActions->size(); i != e; ++i) { + Record *Action = CCActions->getElementAsRecord(i); + SwiftAction = llvm::any_of(Action->getSuperClasses(), + [](const std::pair &Class) { + std::string Name = + Class.first->getNameInitAsString(); + return StringRef(Name).startswith("CCIfSwift"); + }); + O << "\n"; - EmitAction(CCActions->getElementAsRecord(i), 2, O); + EmitAction(Action, 2, O); } O << "\n return true; // CC didn't match.\n"; @@ -93,7 +120,7 @@ void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) { void CallingConvEmitter::EmitAction(Record *Action, unsigned Indent, raw_ostream &O) { std::string IndentStr = std::string(Indent, ' '); - + if (Action->isSubClassOf("CCPredicateAction")) { O << IndentStr << "if ("; @@ -121,18 +148,30 @@ void CallingConvEmitter::EmitAction(Record *Action, O << IndentStr << "if (!" << CC->getName() << "(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))\n" << IndentStr << " return false;\n"; + DelegateToMap[CurrentAction].insert(CC->getName().str()); } else if (Action->isSubClassOf("CCAssignToReg")) { ListInit *RegList = Action->getValueAsListInit("RegList"); if (RegList->size() == 1) { - O << IndentStr << "if (unsigned Reg = State.AllocateReg("; - O << getQualifiedName(RegList->getElementAsRecord(0)) << ")) {\n"; + std::string Name = getQualifiedName(RegList->getElementAsRecord(0)); + O << IndentStr << "if (unsigned Reg = State.AllocateReg(" << Name + << ")) {\n"; + if (SwiftAction) + AssignedSwiftRegsMap[CurrentAction].insert(Name); + else + AssignedRegsMap[CurrentAction].insert(Name); } else { O << IndentStr << "static const MCPhysReg RegList" << ++Counter << "[] = {\n"; O << IndentStr << " "; ListSeparator LS; - for (unsigned i = 0, e = RegList->size(); i != e; ++i) - O << LS << getQualifiedName(RegList->getElementAsRecord(i)); + for (unsigned i = 0, e = RegList->size(); i != e; ++i) { + std::string Name = getQualifiedName(RegList->getElementAsRecord(i)); + if (SwiftAction) + AssignedSwiftRegsMap[CurrentAction].insert(Name); + else + AssignedRegsMap[CurrentAction].insert(Name); + O << LS << Name; + } O << "\n" << IndentStr << "};\n"; O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList" << Counter << ")) {\n"; @@ -287,6 +326,83 @@ void CallingConvEmitter::EmitAction(Record *Action, } } +void CallingConvEmitter::EmitArgRegisterLists(raw_ostream &O) { + // Transitively merge all delegated CCs into AssignedRegsMap. + using EntryTy = std::pair>; + bool Redo; + do { + Redo = false; + std::deque Worklist(DelegateToMap.begin(), DelegateToMap.end()); + + while (!Worklist.empty()) { + EntryTy Entry = Worklist.front(); + Worklist.pop_front(); + + const std::string &CCName = Entry.first; + std::set &Registers = Entry.second; + if (!Registers.empty()) + continue; + + for (auto &InnerEntry : Worklist) { + const std::string &InnerCCName = InnerEntry.first; + std::set &InnerRegisters = InnerEntry.second; + + if (InnerRegisters.find(CCName) != InnerRegisters.end()) { + AssignedRegsMap[InnerCCName].insert( + AssignedRegsMap[CCName].begin(), + AssignedRegsMap[CCName].end()); + InnerRegisters.erase(CCName); + } + } + + DelegateToMap.erase(CCName); + Redo = true; + } + } while (Redo); + + if (AssignedRegsMap.empty()) + return; + + O << "\n#else\n\n"; + + for (auto &Entry : AssignedRegsMap) { + const std::string &RegName = Entry.first; + std::set &Registers = Entry.second; + + if (RegName.empty()) + continue; + + O << "const MCRegister " << Entry.first << "_ArgRegs[] = { "; + + if (Registers.empty()) { + O << "0"; + } else { + ListSeparator LS; + for (const std::string &Reg : Registers) + O << LS << Reg; + } + + O << " };\n"; + } + + if (AssignedSwiftRegsMap.empty()) + return; + + O << "\n// Registers used by Swift.\n"; + for (auto &Entry : AssignedSwiftRegsMap) { + const std::string &RegName = Entry.first; + std::set &Registers = Entry.second; + + O << "const MCRegister " << RegName << "_Swift_ArgRegs[] = { "; + + ListSeparator LS; + for (const std::string &Reg : Registers) + O << LS << Reg; + + O << " };\n"; + } +} + namespace llvm { void EmitCallingConv(RecordKeeper &RK, raw_ostream &OS) { -- 2.7.4