aboutsummaryrefslogtreecommitdiff
path: root/llvm/utils/TableGen/CallingConvEmitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/utils/TableGen/CallingConvEmitter.cpp')
-rw-r--r--llvm/utils/TableGen/CallingConvEmitter.cpp139
1 files changed, 127 insertions, 12 deletions
diff --git a/llvm/utils/TableGen/CallingConvEmitter.cpp b/llvm/utils/TableGen/CallingConvEmitter.cpp
index 127ae6247bd9..8f080cd250ab 100644
--- a/llvm/utils/TableGen/CallingConvEmitter.cpp
+++ b/llvm/utils/TableGen/CallingConvEmitter.cpp
@@ -15,12 +15,19 @@
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
-#include <cassert>
using namespace llvm;
namespace {
class CallingConvEmitter {
RecordKeeper &Records;
+ unsigned Counter;
+ std::string CurrentAction;
+ bool SwiftAction;
+
+ std::map<std::string, std::set<std::string>> AssignedRegsMap;
+ std::map<std::string, std::set<std::string>> AssignedSwiftRegsMap;
+ std::map<std::string, std::set<std::string>> DelegateToMap;
+
public:
explicit CallingConvEmitter(RecordKeeper &R) : Records(R) {}
@@ -29,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
@@ -39,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();
@@ -59,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;
@@ -78,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<Record *, SMRange> &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";
@@ -94,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 (";
@@ -122,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";
@@ -288,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<std::string, std::set<std::string>>;
+ bool Redo;
+ do {
+ Redo = false;
+ std::deque<EntryTy> Worklist(DelegateToMap.begin(), DelegateToMap.end());
+
+ while (!Worklist.empty()) {
+ EntryTy Entry = Worklist.front();
+ Worklist.pop_front();
+
+ const std::string &CCName = Entry.first;
+ std::set<std::string> &Registers = Entry.second;
+ if (!Registers.empty())
+ continue;
+
+ for (auto &InnerEntry : Worklist) {
+ const std::string &InnerCCName = InnerEntry.first;
+ std::set<std::string> &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<std::string> &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<std::string> &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) {