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 #include <cassert> 190b57cec5SDimitry Andric using namespace llvm; 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric namespace { 220b57cec5SDimitry Andric class CallingConvEmitter { 230b57cec5SDimitry Andric RecordKeeper &Records; 240b57cec5SDimitry Andric public: 250b57cec5SDimitry Andric explicit CallingConvEmitter(RecordKeeper &R) : Records(R) {} 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric void run(raw_ostream &o); 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric private: 300b57cec5SDimitry Andric void EmitCallingConv(Record *CC, raw_ostream &O); 310b57cec5SDimitry Andric void EmitAction(Record *Action, unsigned Indent, raw_ostream &O); 320b57cec5SDimitry Andric unsigned Counter; 330b57cec5SDimitry Andric }; 340b57cec5SDimitry Andric } // End anonymous namespace 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric void CallingConvEmitter::run(raw_ostream &O) { 370b57cec5SDimitry Andric std::vector<Record*> CCs = Records.getAllDerivedDefinitions("CallingConv"); 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric // Emit prototypes for all of the non-custom CC's so that they can forward ref 400b57cec5SDimitry Andric // each other. 41*e8d8bef9SDimitry Andric Records.startTimer("Emit prototypes"); 420b57cec5SDimitry Andric for (Record *CC : CCs) { 430b57cec5SDimitry Andric if (!CC->getValueAsBit("Custom")) { 440b57cec5SDimitry Andric unsigned Pad = CC->getName().size(); 450b57cec5SDimitry Andric if (CC->getValueAsBit("Entry")) { 460b57cec5SDimitry Andric O << "bool llvm::"; 470b57cec5SDimitry Andric Pad += 12; 480b57cec5SDimitry Andric } else { 490b57cec5SDimitry Andric O << "static bool "; 500b57cec5SDimitry Andric Pad += 13; 510b57cec5SDimitry Andric } 520b57cec5SDimitry Andric O << CC->getName() << "(unsigned ValNo, MVT ValVT,\n" 530b57cec5SDimitry Andric << std::string(Pad, ' ') << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n" 540b57cec5SDimitry Andric << std::string(Pad, ' ') 550b57cec5SDimitry Andric << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n"; 560b57cec5SDimitry Andric } 570b57cec5SDimitry Andric } 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric // Emit each non-custom calling convention description in full. 60*e8d8bef9SDimitry Andric Records.startTimer("Emit full descriptions"); 610b57cec5SDimitry Andric for (Record *CC : CCs) { 620b57cec5SDimitry Andric if (!CC->getValueAsBit("Custom")) 630b57cec5SDimitry Andric EmitCallingConv(CC, O); 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric } 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) { 690b57cec5SDimitry Andric ListInit *CCActions = CC->getValueAsListInit("Actions"); 700b57cec5SDimitry Andric Counter = 0; 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric O << "\n\n"; 730b57cec5SDimitry Andric unsigned Pad = CC->getName().size(); 740b57cec5SDimitry Andric if (CC->getValueAsBit("Entry")) { 750b57cec5SDimitry Andric O << "bool llvm::"; 760b57cec5SDimitry Andric Pad += 12; 770b57cec5SDimitry Andric } else { 780b57cec5SDimitry Andric O << "static bool "; 790b57cec5SDimitry Andric Pad += 13; 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric O << CC->getName() << "(unsigned ValNo, MVT ValVT,\n" 820b57cec5SDimitry Andric << std::string(Pad, ' ') << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n" 830b57cec5SDimitry Andric << std::string(Pad, ' ') << "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n"; 840b57cec5SDimitry Andric // Emit all of the actions, in order. 850b57cec5SDimitry Andric for (unsigned i = 0, e = CCActions->size(); i != e; ++i) { 860b57cec5SDimitry Andric O << "\n"; 870b57cec5SDimitry Andric EmitAction(CCActions->getElementAsRecord(i), 2, O); 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric O << "\n return true; // CC didn't match.\n"; 910b57cec5SDimitry Andric O << "}\n"; 920b57cec5SDimitry Andric } 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric void CallingConvEmitter::EmitAction(Record *Action, 950b57cec5SDimitry Andric unsigned Indent, raw_ostream &O) { 960b57cec5SDimitry Andric std::string IndentStr = std::string(Indent, ' '); 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric if (Action->isSubClassOf("CCPredicateAction")) { 990b57cec5SDimitry Andric O << IndentStr << "if ("; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric if (Action->isSubClassOf("CCIfType")) { 1020b57cec5SDimitry Andric ListInit *VTs = Action->getValueAsListInit("VTs"); 1030b57cec5SDimitry Andric for (unsigned i = 0, e = VTs->size(); i != e; ++i) { 1040b57cec5SDimitry Andric Record *VT = VTs->getElementAsRecord(i); 1050b57cec5SDimitry Andric if (i != 0) O << " ||\n " << IndentStr; 1060b57cec5SDimitry Andric O << "LocVT == " << getEnumName(getValueType(VT)); 1070b57cec5SDimitry Andric } 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCIf")) { 1100b57cec5SDimitry Andric O << Action->getValueAsString("Predicate"); 1110b57cec5SDimitry Andric } else { 1120b57cec5SDimitry Andric errs() << *Action; 1130b57cec5SDimitry Andric PrintFatalError(Action->getLoc(), "Unknown CCPredicateAction!"); 1140b57cec5SDimitry Andric } 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric O << ") {\n"; 1170b57cec5SDimitry Andric EmitAction(Action->getValueAsDef("SubAction"), Indent+2, O); 1180b57cec5SDimitry Andric O << IndentStr << "}\n"; 1190b57cec5SDimitry Andric } else { 1200b57cec5SDimitry Andric if (Action->isSubClassOf("CCDelegateTo")) { 1210b57cec5SDimitry Andric Record *CC = Action->getValueAsDef("CC"); 1220b57cec5SDimitry Andric O << IndentStr << "if (!" << CC->getName() 1230b57cec5SDimitry Andric << "(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))\n" 1240b57cec5SDimitry Andric << IndentStr << " return false;\n"; 1250b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCAssignToReg")) { 1260b57cec5SDimitry Andric ListInit *RegList = Action->getValueAsListInit("RegList"); 1270b57cec5SDimitry Andric if (RegList->size() == 1) { 1280b57cec5SDimitry Andric O << IndentStr << "if (unsigned Reg = State.AllocateReg("; 1290b57cec5SDimitry Andric O << getQualifiedName(RegList->getElementAsRecord(0)) << ")) {\n"; 1300b57cec5SDimitry Andric } else { 1310b57cec5SDimitry Andric O << IndentStr << "static const MCPhysReg RegList" << ++Counter 1320b57cec5SDimitry Andric << "[] = {\n"; 1330b57cec5SDimitry Andric O << IndentStr << " "; 1340b57cec5SDimitry Andric for (unsigned i = 0, e = RegList->size(); i != e; ++i) { 1350b57cec5SDimitry Andric if (i != 0) O << ", "; 1360b57cec5SDimitry Andric O << getQualifiedName(RegList->getElementAsRecord(i)); 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric O << "\n" << IndentStr << "};\n"; 1390b57cec5SDimitry Andric O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList" 1400b57cec5SDimitry Andric << Counter << ")) {\n"; 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, " 1430b57cec5SDimitry Andric << "Reg, LocVT, LocInfo));\n"; 1440b57cec5SDimitry Andric O << IndentStr << " return false;\n"; 1450b57cec5SDimitry Andric O << IndentStr << "}\n"; 1460b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCAssignToRegWithShadow")) { 1470b57cec5SDimitry Andric ListInit *RegList = Action->getValueAsListInit("RegList"); 1480b57cec5SDimitry Andric ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList"); 1490b57cec5SDimitry Andric if (!ShadowRegList->empty() && ShadowRegList->size() != RegList->size()) 1500b57cec5SDimitry Andric PrintFatalError(Action->getLoc(), 1510b57cec5SDimitry Andric "Invalid length of list of shadowed registers"); 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric if (RegList->size() == 1) { 1540b57cec5SDimitry Andric O << IndentStr << "if (unsigned Reg = State.AllocateReg("; 1550b57cec5SDimitry Andric O << getQualifiedName(RegList->getElementAsRecord(0)); 1560b57cec5SDimitry Andric O << ", " << getQualifiedName(ShadowRegList->getElementAsRecord(0)); 1570b57cec5SDimitry Andric O << ")) {\n"; 1580b57cec5SDimitry Andric } else { 1590b57cec5SDimitry Andric unsigned RegListNumber = ++Counter; 1600b57cec5SDimitry Andric unsigned ShadowRegListNumber = ++Counter; 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric O << IndentStr << "static const MCPhysReg RegList" << RegListNumber 1630b57cec5SDimitry Andric << "[] = {\n"; 1640b57cec5SDimitry Andric O << IndentStr << " "; 1650b57cec5SDimitry Andric for (unsigned i = 0, e = RegList->size(); i != e; ++i) { 1660b57cec5SDimitry Andric if (i != 0) O << ", "; 1670b57cec5SDimitry Andric O << getQualifiedName(RegList->getElementAsRecord(i)); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric O << "\n" << IndentStr << "};\n"; 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric O << IndentStr << "static const MCPhysReg RegList" 1720b57cec5SDimitry Andric << ShadowRegListNumber << "[] = {\n"; 1730b57cec5SDimitry Andric O << IndentStr << " "; 1740b57cec5SDimitry Andric for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i) { 1750b57cec5SDimitry Andric if (i != 0) O << ", "; 1760b57cec5SDimitry Andric O << getQualifiedName(ShadowRegList->getElementAsRecord(i)); 1770b57cec5SDimitry Andric } 1780b57cec5SDimitry Andric O << "\n" << IndentStr << "};\n"; 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList" 1810b57cec5SDimitry Andric << RegListNumber << ", " << "RegList" << ShadowRegListNumber 1820b57cec5SDimitry Andric << ")) {\n"; 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, " 1850b57cec5SDimitry Andric << "Reg, LocVT, LocInfo));\n"; 1860b57cec5SDimitry Andric O << IndentStr << " return false;\n"; 1870b57cec5SDimitry Andric O << IndentStr << "}\n"; 1880b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCAssignToStack")) { 1890b57cec5SDimitry Andric int Size = Action->getValueAsInt("Size"); 1900b57cec5SDimitry Andric int Align = Action->getValueAsInt("Align"); 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric O << IndentStr << "unsigned Offset" << ++Counter 1930b57cec5SDimitry Andric << " = State.AllocateStack("; 1940b57cec5SDimitry Andric if (Size) 1950b57cec5SDimitry Andric O << Size << ", "; 1960b57cec5SDimitry Andric else 1970b57cec5SDimitry Andric O << "\n" << IndentStr 1980b57cec5SDimitry Andric << " State.getMachineFunction().getDataLayout()." 1990b57cec5SDimitry Andric "getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext()))," 2000b57cec5SDimitry Andric " "; 2010b57cec5SDimitry Andric if (Align) 2025ffd83dbSDimitry Andric O << "Align(" << Align << ")"; 2030b57cec5SDimitry Andric else 2045ffd83dbSDimitry Andric O << "\n" 2055ffd83dbSDimitry Andric << IndentStr 2060b57cec5SDimitry Andric << " State.getMachineFunction().getDataLayout()." 2075ffd83dbSDimitry Andric "getABITypeAlign(EVT(LocVT).getTypeForEVT(State.getContext()" 2080b57cec5SDimitry Andric "))"; 2090b57cec5SDimitry Andric O << ");\n" << IndentStr 2100b57cec5SDimitry Andric << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset" 2110b57cec5SDimitry Andric << Counter << ", LocVT, LocInfo));\n"; 2120b57cec5SDimitry Andric O << IndentStr << "return false;\n"; 2130b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCAssignToStackWithShadow")) { 2140b57cec5SDimitry Andric int Size = Action->getValueAsInt("Size"); 2150b57cec5SDimitry Andric int Align = Action->getValueAsInt("Align"); 2160b57cec5SDimitry Andric ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList"); 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric unsigned ShadowRegListNumber = ++Counter; 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric O << IndentStr << "static const MCPhysReg ShadowRegList" 2210b57cec5SDimitry Andric << ShadowRegListNumber << "[] = {\n"; 2220b57cec5SDimitry Andric O << IndentStr << " "; 2230b57cec5SDimitry Andric for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i) { 2240b57cec5SDimitry Andric if (i != 0) O << ", "; 2250b57cec5SDimitry Andric O << getQualifiedName(ShadowRegList->getElementAsRecord(i)); 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric O << "\n" << IndentStr << "};\n"; 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric O << IndentStr << "unsigned Offset" << ++Counter 2305ffd83dbSDimitry Andric << " = State.AllocateStack(" << Size << ", Align(" << Align << "), " 2310b57cec5SDimitry Andric << "ShadowRegList" << ShadowRegListNumber << ");\n"; 2320b57cec5SDimitry Andric O << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset" 2330b57cec5SDimitry Andric << Counter << ", LocVT, LocInfo));\n"; 2340b57cec5SDimitry Andric O << IndentStr << "return false;\n"; 2350b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCPromoteToType")) { 2360b57cec5SDimitry Andric Record *DestTy = Action->getValueAsDef("DestTy"); 2370b57cec5SDimitry Andric MVT::SimpleValueType DestVT = getValueType(DestTy); 2380b57cec5SDimitry Andric O << IndentStr << "LocVT = " << getEnumName(DestVT) <<";\n"; 2390b57cec5SDimitry Andric if (MVT(DestVT).isFloatingPoint()) { 2400b57cec5SDimitry Andric O << IndentStr << "LocInfo = CCValAssign::FPExt;\n"; 2410b57cec5SDimitry Andric } else { 2420b57cec5SDimitry Andric O << IndentStr << "if (ArgFlags.isSExt())\n" 243*e8d8bef9SDimitry Andric << IndentStr << " LocInfo = CCValAssign::SExt;\n" 2440b57cec5SDimitry Andric << IndentStr << "else if (ArgFlags.isZExt())\n" 245*e8d8bef9SDimitry Andric << IndentStr << " LocInfo = CCValAssign::ZExt;\n" 2460b57cec5SDimitry Andric << IndentStr << "else\n" 247*e8d8bef9SDimitry Andric << IndentStr << " LocInfo = CCValAssign::AExt;\n"; 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCPromoteToUpperBitsInType")) { 2500b57cec5SDimitry Andric Record *DestTy = Action->getValueAsDef("DestTy"); 2510b57cec5SDimitry Andric MVT::SimpleValueType DestVT = getValueType(DestTy); 2520b57cec5SDimitry Andric O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n"; 2530b57cec5SDimitry Andric if (MVT(DestVT).isFloatingPoint()) { 2540b57cec5SDimitry Andric PrintFatalError(Action->getLoc(), 2550b57cec5SDimitry Andric "CCPromoteToUpperBitsInType does not handle floating " 2560b57cec5SDimitry Andric "point"); 2570b57cec5SDimitry Andric } else { 2580b57cec5SDimitry Andric O << IndentStr << "if (ArgFlags.isSExt())\n" 259*e8d8bef9SDimitry Andric << IndentStr << " LocInfo = CCValAssign::SExtUpper;\n" 2600b57cec5SDimitry Andric << IndentStr << "else if (ArgFlags.isZExt())\n" 261*e8d8bef9SDimitry Andric << IndentStr << " LocInfo = CCValAssign::ZExtUpper;\n" 2620b57cec5SDimitry Andric << IndentStr << "else\n" 263*e8d8bef9SDimitry Andric << IndentStr << " LocInfo = CCValAssign::AExtUpper;\n"; 2640b57cec5SDimitry Andric } 2650b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCBitConvertToType")) { 2660b57cec5SDimitry Andric Record *DestTy = Action->getValueAsDef("DestTy"); 2670b57cec5SDimitry Andric O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n"; 2680b57cec5SDimitry Andric O << IndentStr << "LocInfo = CCValAssign::BCvt;\n"; 2698bcb0991SDimitry Andric } else if (Action->isSubClassOf("CCTruncToType")) { 2708bcb0991SDimitry Andric Record *DestTy = Action->getValueAsDef("DestTy"); 2718bcb0991SDimitry Andric O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n"; 2728bcb0991SDimitry Andric O << IndentStr << "LocInfo = CCValAssign::Trunc;\n"; 2730b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCPassIndirect")) { 2740b57cec5SDimitry Andric Record *DestTy = Action->getValueAsDef("DestTy"); 2750b57cec5SDimitry Andric O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n"; 2760b57cec5SDimitry Andric O << IndentStr << "LocInfo = CCValAssign::Indirect;\n"; 2770b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCPassByVal")) { 2780b57cec5SDimitry Andric int Size = Action->getValueAsInt("Size"); 2790b57cec5SDimitry Andric int Align = Action->getValueAsInt("Align"); 2805ffd83dbSDimitry Andric O << IndentStr << "State.HandleByVal(ValNo, ValVT, LocVT, LocInfo, " 2815ffd83dbSDimitry Andric << Size << ", Align(" << Align << "), ArgFlags);\n"; 2820b57cec5SDimitry Andric O << IndentStr << "return false;\n"; 2830b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCCustom")) { 2840b57cec5SDimitry Andric O << IndentStr 2850b57cec5SDimitry Andric << "if (" << Action->getValueAsString("FuncName") << "(ValNo, ValVT, " 2860b57cec5SDimitry Andric << "LocVT, LocInfo, ArgFlags, State))\n"; 287*e8d8bef9SDimitry Andric O << IndentStr << " return false;\n"; 2880b57cec5SDimitry Andric } else { 2890b57cec5SDimitry Andric errs() << *Action; 2900b57cec5SDimitry Andric PrintFatalError(Action->getLoc(), "Unknown CCAction!"); 2910b57cec5SDimitry Andric } 2920b57cec5SDimitry Andric } 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric namespace llvm { 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric void EmitCallingConv(RecordKeeper &RK, raw_ostream &OS) { 2980b57cec5SDimitry Andric emitSourceFileHeader("Calling Convention Implementation Fragment", OS); 2990b57cec5SDimitry Andric CallingConvEmitter(RK).run(OS); 3000b57cec5SDimitry Andric } 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric } // End llvm namespace 303