10b57cec5SDimitry Andric //===- CallingConvEmitter.cpp - Generate calling conventions --------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This tablegen backend is responsible for emitting descriptions of the calling 100b57cec5SDimitry Andric // conventions supported by this target. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "CodeGenTarget.h" 150b57cec5SDimitry Andric #include "llvm/TableGen/Error.h" 160b57cec5SDimitry Andric #include "llvm/TableGen/Record.h" 170b57cec5SDimitry Andric #include "llvm/TableGen/TableGenBackend.h" 180b57cec5SDimitry Andric using namespace llvm; 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric namespace { 210b57cec5SDimitry Andric class CallingConvEmitter { 220b57cec5SDimitry Andric RecordKeeper &Records; 2381ad6265SDimitry Andric unsigned Counter; 2481ad6265SDimitry Andric std::string CurrentAction; 2581ad6265SDimitry Andric bool SwiftAction; 2681ad6265SDimitry Andric 2781ad6265SDimitry Andric std::map<std::string, std::set<std::string>> AssignedRegsMap; 2881ad6265SDimitry Andric std::map<std::string, std::set<std::string>> AssignedSwiftRegsMap; 2981ad6265SDimitry Andric std::map<std::string, std::set<std::string>> DelegateToMap; 3081ad6265SDimitry Andric 310b57cec5SDimitry Andric public: 320b57cec5SDimitry Andric explicit CallingConvEmitter(RecordKeeper &R) : Records(R) {} 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric void run(raw_ostream &o); 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric private: 370b57cec5SDimitry Andric void EmitCallingConv(Record *CC, raw_ostream &O); 380b57cec5SDimitry Andric void EmitAction(Record *Action, unsigned Indent, raw_ostream &O); 3981ad6265SDimitry Andric void EmitArgRegisterLists(raw_ostream &O); 400b57cec5SDimitry Andric }; 410b57cec5SDimitry Andric } // End anonymous namespace 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric void CallingConvEmitter::run(raw_ostream &O) { 440b57cec5SDimitry Andric std::vector<Record*> CCs = Records.getAllDerivedDefinitions("CallingConv"); 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric // Emit prototypes for all of the non-custom CC's so that they can forward ref 470b57cec5SDimitry Andric // each other. 48e8d8bef9SDimitry Andric Records.startTimer("Emit prototypes"); 4981ad6265SDimitry Andric O << "#ifndef GET_CC_REGISTER_LISTS\n\n"; 500b57cec5SDimitry Andric for (Record *CC : CCs) { 510b57cec5SDimitry Andric if (!CC->getValueAsBit("Custom")) { 520b57cec5SDimitry Andric unsigned Pad = CC->getName().size(); 530b57cec5SDimitry Andric if (CC->getValueAsBit("Entry")) { 540b57cec5SDimitry Andric O << "bool llvm::"; 550b57cec5SDimitry Andric Pad += 12; 560b57cec5SDimitry Andric } else { 570b57cec5SDimitry Andric O << "static bool "; 580b57cec5SDimitry Andric Pad += 13; 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric O << CC->getName() << "(unsigned ValNo, MVT ValVT,\n" 610b57cec5SDimitry Andric << std::string(Pad, ' ') << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n" 620b57cec5SDimitry Andric << std::string(Pad, ' ') 630b57cec5SDimitry Andric << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n"; 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric } 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric // Emit each non-custom calling convention description in full. 68e8d8bef9SDimitry Andric Records.startTimer("Emit full descriptions"); 690b57cec5SDimitry Andric for (Record *CC : CCs) { 7081ad6265SDimitry Andric if (!CC->getValueAsBit("Custom")) { 710b57cec5SDimitry Andric EmitCallingConv(CC, O); 720b57cec5SDimitry Andric } 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric 7581ad6265SDimitry Andric EmitArgRegisterLists(O); 7681ad6265SDimitry Andric 7781ad6265SDimitry Andric O << "\n#endif // CC_REGISTER_LIST\n"; 7881ad6265SDimitry Andric } 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) { 810b57cec5SDimitry Andric ListInit *CCActions = CC->getValueAsListInit("Actions"); 820b57cec5SDimitry Andric Counter = 0; 830b57cec5SDimitry Andric 8481ad6265SDimitry Andric CurrentAction = CC->getName().str(); 8581ad6265SDimitry Andric // Call upon the creation of a map entry from the void! 8681ad6265SDimitry Andric // We want an entry in AssignedRegsMap for every action, even if that 8781ad6265SDimitry Andric // entry is empty. 8881ad6265SDimitry Andric AssignedRegsMap[CurrentAction] = {}; 8981ad6265SDimitry Andric 900b57cec5SDimitry Andric O << "\n\n"; 9181ad6265SDimitry Andric unsigned Pad = CurrentAction.size(); 920b57cec5SDimitry Andric if (CC->getValueAsBit("Entry")) { 930b57cec5SDimitry Andric O << "bool llvm::"; 940b57cec5SDimitry Andric Pad += 12; 950b57cec5SDimitry Andric } else { 960b57cec5SDimitry Andric O << "static bool "; 970b57cec5SDimitry Andric Pad += 13; 980b57cec5SDimitry Andric } 9981ad6265SDimitry Andric O << CurrentAction << "(unsigned ValNo, MVT ValVT,\n" 1000b57cec5SDimitry Andric << std::string(Pad, ' ') << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n" 1010b57cec5SDimitry Andric << std::string(Pad, ' ') << "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n"; 1020b57cec5SDimitry Andric // Emit all of the actions, in order. 1030b57cec5SDimitry Andric for (unsigned i = 0, e = CCActions->size(); i != e; ++i) { 10481ad6265SDimitry Andric Record *Action = CCActions->getElementAsRecord(i); 10581ad6265SDimitry Andric SwiftAction = llvm::any_of(Action->getSuperClasses(), 10681ad6265SDimitry Andric [](const std::pair<Record *, SMRange> &Class) { 10781ad6265SDimitry Andric std::string Name = 10881ad6265SDimitry Andric Class.first->getNameInitAsString(); 10981ad6265SDimitry Andric return StringRef(Name).startswith("CCIfSwift"); 11081ad6265SDimitry Andric }); 11181ad6265SDimitry Andric 1120b57cec5SDimitry Andric O << "\n"; 11381ad6265SDimitry Andric EmitAction(Action, 2, O); 1140b57cec5SDimitry Andric } 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric O << "\n return true; // CC didn't match.\n"; 1170b57cec5SDimitry Andric O << "}\n"; 1180b57cec5SDimitry Andric } 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric void CallingConvEmitter::EmitAction(Record *Action, 1210b57cec5SDimitry Andric unsigned Indent, raw_ostream &O) { 1220b57cec5SDimitry Andric std::string IndentStr = std::string(Indent, ' '); 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric if (Action->isSubClassOf("CCPredicateAction")) { 1250b57cec5SDimitry Andric O << IndentStr << "if ("; 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric if (Action->isSubClassOf("CCIfType")) { 1280b57cec5SDimitry Andric ListInit *VTs = Action->getValueAsListInit("VTs"); 1290b57cec5SDimitry Andric for (unsigned i = 0, e = VTs->size(); i != e; ++i) { 1300b57cec5SDimitry Andric Record *VT = VTs->getElementAsRecord(i); 1310b57cec5SDimitry Andric if (i != 0) O << " ||\n " << IndentStr; 1320b57cec5SDimitry Andric O << "LocVT == " << getEnumName(getValueType(VT)); 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCIf")) { 1360b57cec5SDimitry Andric O << Action->getValueAsString("Predicate"); 1370b57cec5SDimitry Andric } else { 1380b57cec5SDimitry Andric errs() << *Action; 1390b57cec5SDimitry Andric PrintFatalError(Action->getLoc(), "Unknown CCPredicateAction!"); 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric O << ") {\n"; 1430b57cec5SDimitry Andric EmitAction(Action->getValueAsDef("SubAction"), Indent+2, O); 1440b57cec5SDimitry Andric O << IndentStr << "}\n"; 1450b57cec5SDimitry Andric } else { 1460b57cec5SDimitry Andric if (Action->isSubClassOf("CCDelegateTo")) { 1470b57cec5SDimitry Andric Record *CC = Action->getValueAsDef("CC"); 1480b57cec5SDimitry Andric O << IndentStr << "if (!" << CC->getName() 1490b57cec5SDimitry Andric << "(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))\n" 1500b57cec5SDimitry Andric << IndentStr << " return false;\n"; 15181ad6265SDimitry Andric DelegateToMap[CurrentAction].insert(CC->getName().str()); 152*fcaf7f86SDimitry Andric } else if (Action->isSubClassOf("CCAssignToReg") || 153*fcaf7f86SDimitry Andric Action->isSubClassOf("CCAssignToRegAndStack")) { 1540b57cec5SDimitry Andric ListInit *RegList = Action->getValueAsListInit("RegList"); 1550b57cec5SDimitry Andric if (RegList->size() == 1) { 15681ad6265SDimitry Andric std::string Name = getQualifiedName(RegList->getElementAsRecord(0)); 15781ad6265SDimitry Andric O << IndentStr << "if (unsigned Reg = State.AllocateReg(" << Name 15881ad6265SDimitry Andric << ")) {\n"; 15981ad6265SDimitry Andric if (SwiftAction) 16081ad6265SDimitry Andric AssignedSwiftRegsMap[CurrentAction].insert(Name); 16181ad6265SDimitry Andric else 16281ad6265SDimitry Andric AssignedRegsMap[CurrentAction].insert(Name); 1630b57cec5SDimitry Andric } else { 1640b57cec5SDimitry Andric O << IndentStr << "static const MCPhysReg RegList" << ++Counter 1650b57cec5SDimitry Andric << "[] = {\n"; 1660b57cec5SDimitry Andric O << IndentStr << " "; 167fe6060f1SDimitry Andric ListSeparator LS; 16881ad6265SDimitry Andric for (unsigned i = 0, e = RegList->size(); i != e; ++i) { 16981ad6265SDimitry Andric std::string Name = getQualifiedName(RegList->getElementAsRecord(i)); 17081ad6265SDimitry Andric if (SwiftAction) 17181ad6265SDimitry Andric AssignedSwiftRegsMap[CurrentAction].insert(Name); 17281ad6265SDimitry Andric else 17381ad6265SDimitry Andric AssignedRegsMap[CurrentAction].insert(Name); 17481ad6265SDimitry Andric O << LS << Name; 17581ad6265SDimitry Andric } 1760b57cec5SDimitry Andric O << "\n" << IndentStr << "};\n"; 1770b57cec5SDimitry Andric O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList" 1780b57cec5SDimitry Andric << Counter << ")) {\n"; 1790b57cec5SDimitry Andric } 1800b57cec5SDimitry Andric O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, " 1810b57cec5SDimitry Andric << "Reg, LocVT, LocInfo));\n"; 182*fcaf7f86SDimitry Andric if (Action->isSubClassOf("CCAssignToRegAndStack")) { 183*fcaf7f86SDimitry Andric int Size = Action->getValueAsInt("Size"); 184*fcaf7f86SDimitry Andric int Align = Action->getValueAsInt("Align"); 185*fcaf7f86SDimitry Andric O << IndentStr << " (void)State.AllocateStack("; 186*fcaf7f86SDimitry Andric if (Size) 187*fcaf7f86SDimitry Andric O << Size << ", "; 188*fcaf7f86SDimitry Andric else 189*fcaf7f86SDimitry Andric O << "\n" 190*fcaf7f86SDimitry Andric << IndentStr 191*fcaf7f86SDimitry Andric << " State.getMachineFunction().getDataLayout()." 192*fcaf7f86SDimitry Andric "getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext()))," 193*fcaf7f86SDimitry Andric " "; 194*fcaf7f86SDimitry Andric if (Align) 195*fcaf7f86SDimitry Andric O << "Align(" << Align << ")"; 196*fcaf7f86SDimitry Andric else 197*fcaf7f86SDimitry Andric O << "\n" 198*fcaf7f86SDimitry Andric << IndentStr 199*fcaf7f86SDimitry Andric << " State.getMachineFunction().getDataLayout()." 200*fcaf7f86SDimitry Andric "getABITypeAlign(EVT(LocVT).getTypeForEVT(State.getContext()" 201*fcaf7f86SDimitry Andric "))"; 202*fcaf7f86SDimitry Andric O << ");\n"; 203*fcaf7f86SDimitry Andric } 2040b57cec5SDimitry Andric O << IndentStr << " return false;\n"; 2050b57cec5SDimitry Andric O << IndentStr << "}\n"; 2060b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCAssignToRegWithShadow")) { 2070b57cec5SDimitry Andric ListInit *RegList = Action->getValueAsListInit("RegList"); 2080b57cec5SDimitry Andric ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList"); 2090b57cec5SDimitry Andric if (!ShadowRegList->empty() && ShadowRegList->size() != RegList->size()) 2100b57cec5SDimitry Andric PrintFatalError(Action->getLoc(), 2110b57cec5SDimitry Andric "Invalid length of list of shadowed registers"); 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric if (RegList->size() == 1) { 2140b57cec5SDimitry Andric O << IndentStr << "if (unsigned Reg = State.AllocateReg("; 2150b57cec5SDimitry Andric O << getQualifiedName(RegList->getElementAsRecord(0)); 2160b57cec5SDimitry Andric O << ", " << getQualifiedName(ShadowRegList->getElementAsRecord(0)); 2170b57cec5SDimitry Andric O << ")) {\n"; 2180b57cec5SDimitry Andric } else { 2190b57cec5SDimitry Andric unsigned RegListNumber = ++Counter; 2200b57cec5SDimitry Andric unsigned ShadowRegListNumber = ++Counter; 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric O << IndentStr << "static const MCPhysReg RegList" << RegListNumber 2230b57cec5SDimitry Andric << "[] = {\n"; 2240b57cec5SDimitry Andric O << IndentStr << " "; 225fe6060f1SDimitry Andric ListSeparator LS; 226fe6060f1SDimitry Andric for (unsigned i = 0, e = RegList->size(); i != e; ++i) 227fe6060f1SDimitry Andric O << LS << getQualifiedName(RegList->getElementAsRecord(i)); 2280b57cec5SDimitry Andric O << "\n" << IndentStr << "};\n"; 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric O << IndentStr << "static const MCPhysReg RegList" 2310b57cec5SDimitry Andric << ShadowRegListNumber << "[] = {\n"; 2320b57cec5SDimitry Andric O << IndentStr << " "; 233fe6060f1SDimitry Andric ListSeparator LSS; 234fe6060f1SDimitry Andric for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i) 235fe6060f1SDimitry Andric O << LSS << getQualifiedName(ShadowRegList->getElementAsRecord(i)); 2360b57cec5SDimitry Andric O << "\n" << IndentStr << "};\n"; 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList" 2390b57cec5SDimitry Andric << RegListNumber << ", " << "RegList" << ShadowRegListNumber 2400b57cec5SDimitry Andric << ")) {\n"; 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, " 2430b57cec5SDimitry Andric << "Reg, LocVT, LocInfo));\n"; 2440b57cec5SDimitry Andric O << IndentStr << " return false;\n"; 2450b57cec5SDimitry Andric O << IndentStr << "}\n"; 2460b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCAssignToStack")) { 2470b57cec5SDimitry Andric int Size = Action->getValueAsInt("Size"); 2480b57cec5SDimitry Andric int Align = Action->getValueAsInt("Align"); 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric O << IndentStr << "unsigned Offset" << ++Counter 2510b57cec5SDimitry Andric << " = State.AllocateStack("; 2520b57cec5SDimitry Andric if (Size) 2530b57cec5SDimitry Andric O << Size << ", "; 2540b57cec5SDimitry Andric else 2550b57cec5SDimitry Andric O << "\n" << IndentStr 2560b57cec5SDimitry Andric << " State.getMachineFunction().getDataLayout()." 2570b57cec5SDimitry Andric "getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext()))," 2580b57cec5SDimitry Andric " "; 2590b57cec5SDimitry Andric if (Align) 2605ffd83dbSDimitry Andric O << "Align(" << Align << ")"; 2610b57cec5SDimitry Andric else 2625ffd83dbSDimitry Andric O << "\n" 2635ffd83dbSDimitry Andric << IndentStr 2640b57cec5SDimitry Andric << " State.getMachineFunction().getDataLayout()." 2655ffd83dbSDimitry Andric "getABITypeAlign(EVT(LocVT).getTypeForEVT(State.getContext()" 2660b57cec5SDimitry Andric "))"; 2670b57cec5SDimitry Andric O << ");\n" << IndentStr 2680b57cec5SDimitry Andric << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset" 2690b57cec5SDimitry Andric << Counter << ", LocVT, LocInfo));\n"; 2700b57cec5SDimitry Andric O << IndentStr << "return false;\n"; 2710b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCAssignToStackWithShadow")) { 2720b57cec5SDimitry Andric int Size = Action->getValueAsInt("Size"); 2730b57cec5SDimitry Andric int Align = Action->getValueAsInt("Align"); 2740b57cec5SDimitry Andric ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList"); 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric unsigned ShadowRegListNumber = ++Counter; 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric O << IndentStr << "static const MCPhysReg ShadowRegList" 2790b57cec5SDimitry Andric << ShadowRegListNumber << "[] = {\n"; 2800b57cec5SDimitry Andric O << IndentStr << " "; 281fe6060f1SDimitry Andric ListSeparator LS; 282fe6060f1SDimitry Andric for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i) 283fe6060f1SDimitry Andric O << LS << getQualifiedName(ShadowRegList->getElementAsRecord(i)); 2840b57cec5SDimitry Andric O << "\n" << IndentStr << "};\n"; 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric O << IndentStr << "unsigned Offset" << ++Counter 2875ffd83dbSDimitry Andric << " = State.AllocateStack(" << Size << ", Align(" << Align << "), " 2880b57cec5SDimitry Andric << "ShadowRegList" << ShadowRegListNumber << ");\n"; 2890b57cec5SDimitry Andric O << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset" 2900b57cec5SDimitry Andric << Counter << ", LocVT, LocInfo));\n"; 2910b57cec5SDimitry Andric O << IndentStr << "return false;\n"; 2920b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCPromoteToType")) { 2930b57cec5SDimitry Andric Record *DestTy = Action->getValueAsDef("DestTy"); 2940b57cec5SDimitry Andric MVT::SimpleValueType DestVT = getValueType(DestTy); 2950b57cec5SDimitry Andric O << IndentStr << "LocVT = " << getEnumName(DestVT) <<";\n"; 2960b57cec5SDimitry Andric if (MVT(DestVT).isFloatingPoint()) { 2970b57cec5SDimitry Andric O << IndentStr << "LocInfo = CCValAssign::FPExt;\n"; 2980b57cec5SDimitry Andric } else { 2990b57cec5SDimitry Andric O << IndentStr << "if (ArgFlags.isSExt())\n" 300e8d8bef9SDimitry Andric << IndentStr << " LocInfo = CCValAssign::SExt;\n" 3010b57cec5SDimitry Andric << IndentStr << "else if (ArgFlags.isZExt())\n" 302e8d8bef9SDimitry Andric << IndentStr << " LocInfo = CCValAssign::ZExt;\n" 3030b57cec5SDimitry Andric << IndentStr << "else\n" 304e8d8bef9SDimitry Andric << IndentStr << " LocInfo = CCValAssign::AExt;\n"; 3050b57cec5SDimitry Andric } 3060b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCPromoteToUpperBitsInType")) { 3070b57cec5SDimitry Andric Record *DestTy = Action->getValueAsDef("DestTy"); 3080b57cec5SDimitry Andric MVT::SimpleValueType DestVT = getValueType(DestTy); 3090b57cec5SDimitry Andric O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n"; 3100b57cec5SDimitry Andric if (MVT(DestVT).isFloatingPoint()) { 3110b57cec5SDimitry Andric PrintFatalError(Action->getLoc(), 3120b57cec5SDimitry Andric "CCPromoteToUpperBitsInType does not handle floating " 3130b57cec5SDimitry Andric "point"); 3140b57cec5SDimitry Andric } else { 3150b57cec5SDimitry Andric O << IndentStr << "if (ArgFlags.isSExt())\n" 316e8d8bef9SDimitry Andric << IndentStr << " LocInfo = CCValAssign::SExtUpper;\n" 3170b57cec5SDimitry Andric << IndentStr << "else if (ArgFlags.isZExt())\n" 318e8d8bef9SDimitry Andric << IndentStr << " LocInfo = CCValAssign::ZExtUpper;\n" 3190b57cec5SDimitry Andric << IndentStr << "else\n" 320e8d8bef9SDimitry Andric << IndentStr << " LocInfo = CCValAssign::AExtUpper;\n"; 3210b57cec5SDimitry Andric } 3220b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCBitConvertToType")) { 3230b57cec5SDimitry Andric Record *DestTy = Action->getValueAsDef("DestTy"); 3240b57cec5SDimitry Andric O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n"; 3250b57cec5SDimitry Andric O << IndentStr << "LocInfo = CCValAssign::BCvt;\n"; 3268bcb0991SDimitry Andric } else if (Action->isSubClassOf("CCTruncToType")) { 3278bcb0991SDimitry Andric Record *DestTy = Action->getValueAsDef("DestTy"); 3288bcb0991SDimitry Andric O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n"; 3298bcb0991SDimitry Andric O << IndentStr << "LocInfo = CCValAssign::Trunc;\n"; 3300b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCPassIndirect")) { 3310b57cec5SDimitry Andric Record *DestTy = Action->getValueAsDef("DestTy"); 3320b57cec5SDimitry Andric O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n"; 3330b57cec5SDimitry Andric O << IndentStr << "LocInfo = CCValAssign::Indirect;\n"; 3340b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCPassByVal")) { 3350b57cec5SDimitry Andric int Size = Action->getValueAsInt("Size"); 3360b57cec5SDimitry Andric int Align = Action->getValueAsInt("Align"); 3375ffd83dbSDimitry Andric O << IndentStr << "State.HandleByVal(ValNo, ValVT, LocVT, LocInfo, " 3385ffd83dbSDimitry Andric << Size << ", Align(" << Align << "), ArgFlags);\n"; 3390b57cec5SDimitry Andric O << IndentStr << "return false;\n"; 3400b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCCustom")) { 3410b57cec5SDimitry Andric O << IndentStr 3420b57cec5SDimitry Andric << "if (" << Action->getValueAsString("FuncName") << "(ValNo, ValVT, " 3430b57cec5SDimitry Andric << "LocVT, LocInfo, ArgFlags, State))\n"; 344e8d8bef9SDimitry Andric O << IndentStr << " return false;\n"; 3450b57cec5SDimitry Andric } else { 3460b57cec5SDimitry Andric errs() << *Action; 3470b57cec5SDimitry Andric PrintFatalError(Action->getLoc(), "Unknown CCAction!"); 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric } 3500b57cec5SDimitry Andric } 3510b57cec5SDimitry Andric 35281ad6265SDimitry Andric void CallingConvEmitter::EmitArgRegisterLists(raw_ostream &O) { 35381ad6265SDimitry Andric // Transitively merge all delegated CCs into AssignedRegsMap. 35481ad6265SDimitry Andric using EntryTy = std::pair<std::string, std::set<std::string>>; 35581ad6265SDimitry Andric bool Redo; 35681ad6265SDimitry Andric do { 35781ad6265SDimitry Andric Redo = false; 35881ad6265SDimitry Andric std::deque<EntryTy> Worklist(DelegateToMap.begin(), DelegateToMap.end()); 35981ad6265SDimitry Andric 36081ad6265SDimitry Andric while (!Worklist.empty()) { 36181ad6265SDimitry Andric EntryTy Entry = Worklist.front(); 36281ad6265SDimitry Andric Worklist.pop_front(); 36381ad6265SDimitry Andric 36481ad6265SDimitry Andric const std::string &CCName = Entry.first; 36581ad6265SDimitry Andric std::set<std::string> &Registers = Entry.second; 36681ad6265SDimitry Andric if (!Registers.empty()) 36781ad6265SDimitry Andric continue; 36881ad6265SDimitry Andric 36981ad6265SDimitry Andric for (auto &InnerEntry : Worklist) { 37081ad6265SDimitry Andric const std::string &InnerCCName = InnerEntry.first; 37181ad6265SDimitry Andric std::set<std::string> &InnerRegisters = InnerEntry.second; 37281ad6265SDimitry Andric 37381ad6265SDimitry Andric if (InnerRegisters.find(CCName) != InnerRegisters.end()) { 37481ad6265SDimitry Andric AssignedRegsMap[InnerCCName].insert( 37581ad6265SDimitry Andric AssignedRegsMap[CCName].begin(), 37681ad6265SDimitry Andric AssignedRegsMap[CCName].end()); 37781ad6265SDimitry Andric InnerRegisters.erase(CCName); 37881ad6265SDimitry Andric } 37981ad6265SDimitry Andric } 38081ad6265SDimitry Andric 38181ad6265SDimitry Andric DelegateToMap.erase(CCName); 38281ad6265SDimitry Andric Redo = true; 38381ad6265SDimitry Andric } 38481ad6265SDimitry Andric } while (Redo); 38581ad6265SDimitry Andric 38681ad6265SDimitry Andric if (AssignedRegsMap.empty()) 38781ad6265SDimitry Andric return; 38881ad6265SDimitry Andric 38981ad6265SDimitry Andric O << "\n#else\n\n"; 39081ad6265SDimitry Andric 39181ad6265SDimitry Andric for (auto &Entry : AssignedRegsMap) { 39281ad6265SDimitry Andric const std::string &RegName = Entry.first; 39381ad6265SDimitry Andric std::set<std::string> &Registers = Entry.second; 39481ad6265SDimitry Andric 39581ad6265SDimitry Andric if (RegName.empty()) 39681ad6265SDimitry Andric continue; 39781ad6265SDimitry Andric 39881ad6265SDimitry Andric O << "const MCRegister " << Entry.first << "_ArgRegs[] = { "; 39981ad6265SDimitry Andric 40081ad6265SDimitry Andric if (Registers.empty()) { 40181ad6265SDimitry Andric O << "0"; 40281ad6265SDimitry Andric } else { 40381ad6265SDimitry Andric ListSeparator LS; 40481ad6265SDimitry Andric for (const std::string &Reg : Registers) 40581ad6265SDimitry Andric O << LS << Reg; 40681ad6265SDimitry Andric } 40781ad6265SDimitry Andric 40881ad6265SDimitry Andric O << " };\n"; 40981ad6265SDimitry Andric } 41081ad6265SDimitry Andric 41181ad6265SDimitry Andric if (AssignedSwiftRegsMap.empty()) 41281ad6265SDimitry Andric return; 41381ad6265SDimitry Andric 41481ad6265SDimitry Andric O << "\n// Registers used by Swift.\n"; 41581ad6265SDimitry Andric for (auto &Entry : AssignedSwiftRegsMap) { 41681ad6265SDimitry Andric const std::string &RegName = Entry.first; 41781ad6265SDimitry Andric std::set<std::string> &Registers = Entry.second; 41881ad6265SDimitry Andric 41981ad6265SDimitry Andric O << "const MCRegister " << RegName << "_Swift_ArgRegs[] = { "; 42081ad6265SDimitry Andric 42181ad6265SDimitry Andric ListSeparator LS; 42281ad6265SDimitry Andric for (const std::string &Reg : Registers) 42381ad6265SDimitry Andric O << LS << Reg; 42481ad6265SDimitry Andric 42581ad6265SDimitry Andric O << " };\n"; 42681ad6265SDimitry Andric } 42781ad6265SDimitry Andric } 42881ad6265SDimitry Andric 4290b57cec5SDimitry Andric namespace llvm { 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric void EmitCallingConv(RecordKeeper &RK, raw_ostream &OS) { 4320b57cec5SDimitry Andric emitSourceFileHeader("Calling Convention Implementation Fragment", OS); 4330b57cec5SDimitry Andric CallingConvEmitter(RK).run(OS); 4340b57cec5SDimitry Andric } 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric } // End llvm namespace 437