1*0b57cec5SDimitry Andric //===- CallingConvEmitter.cpp - Generate calling conventions --------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This tablegen backend is responsible for emitting descriptions of the calling 10*0b57cec5SDimitry Andric // conventions supported by this target. 11*0b57cec5SDimitry Andric // 12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13*0b57cec5SDimitry Andric 14*0b57cec5SDimitry Andric #include "CodeGenTarget.h" 15*0b57cec5SDimitry Andric #include "llvm/TableGen/Error.h" 16*0b57cec5SDimitry Andric #include "llvm/TableGen/Record.h" 17*0b57cec5SDimitry Andric #include "llvm/TableGen/TableGenBackend.h" 18*0b57cec5SDimitry Andric #include <cassert> 19*0b57cec5SDimitry Andric using namespace llvm; 20*0b57cec5SDimitry Andric 21*0b57cec5SDimitry Andric namespace { 22*0b57cec5SDimitry Andric class CallingConvEmitter { 23*0b57cec5SDimitry Andric RecordKeeper &Records; 24*0b57cec5SDimitry Andric public: 25*0b57cec5SDimitry Andric explicit CallingConvEmitter(RecordKeeper &R) : Records(R) {} 26*0b57cec5SDimitry Andric 27*0b57cec5SDimitry Andric void run(raw_ostream &o); 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andric private: 30*0b57cec5SDimitry Andric void EmitCallingConv(Record *CC, raw_ostream &O); 31*0b57cec5SDimitry Andric void EmitAction(Record *Action, unsigned Indent, raw_ostream &O); 32*0b57cec5SDimitry Andric unsigned Counter; 33*0b57cec5SDimitry Andric }; 34*0b57cec5SDimitry Andric } // End anonymous namespace 35*0b57cec5SDimitry Andric 36*0b57cec5SDimitry Andric void CallingConvEmitter::run(raw_ostream &O) { 37*0b57cec5SDimitry Andric std::vector<Record*> CCs = Records.getAllDerivedDefinitions("CallingConv"); 38*0b57cec5SDimitry Andric 39*0b57cec5SDimitry Andric // Emit prototypes for all of the non-custom CC's so that they can forward ref 40*0b57cec5SDimitry Andric // each other. 41*0b57cec5SDimitry Andric for (Record *CC : CCs) { 42*0b57cec5SDimitry Andric if (!CC->getValueAsBit("Custom")) { 43*0b57cec5SDimitry Andric unsigned Pad = CC->getName().size(); 44*0b57cec5SDimitry Andric if (CC->getValueAsBit("Entry")) { 45*0b57cec5SDimitry Andric O << "bool llvm::"; 46*0b57cec5SDimitry Andric Pad += 12; 47*0b57cec5SDimitry Andric } else { 48*0b57cec5SDimitry Andric O << "static bool "; 49*0b57cec5SDimitry Andric Pad += 13; 50*0b57cec5SDimitry Andric } 51*0b57cec5SDimitry Andric O << CC->getName() << "(unsigned ValNo, MVT ValVT,\n" 52*0b57cec5SDimitry Andric << std::string(Pad, ' ') << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n" 53*0b57cec5SDimitry Andric << std::string(Pad, ' ') 54*0b57cec5SDimitry Andric << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n"; 55*0b57cec5SDimitry Andric } 56*0b57cec5SDimitry Andric } 57*0b57cec5SDimitry Andric 58*0b57cec5SDimitry Andric // Emit each non-custom calling convention description in full. 59*0b57cec5SDimitry Andric for (Record *CC : CCs) { 60*0b57cec5SDimitry Andric if (!CC->getValueAsBit("Custom")) 61*0b57cec5SDimitry Andric EmitCallingConv(CC, O); 62*0b57cec5SDimitry Andric } 63*0b57cec5SDimitry Andric } 64*0b57cec5SDimitry Andric 65*0b57cec5SDimitry Andric 66*0b57cec5SDimitry Andric void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) { 67*0b57cec5SDimitry Andric ListInit *CCActions = CC->getValueAsListInit("Actions"); 68*0b57cec5SDimitry Andric Counter = 0; 69*0b57cec5SDimitry Andric 70*0b57cec5SDimitry Andric O << "\n\n"; 71*0b57cec5SDimitry Andric unsigned Pad = CC->getName().size(); 72*0b57cec5SDimitry Andric if (CC->getValueAsBit("Entry")) { 73*0b57cec5SDimitry Andric O << "bool llvm::"; 74*0b57cec5SDimitry Andric Pad += 12; 75*0b57cec5SDimitry Andric } else { 76*0b57cec5SDimitry Andric O << "static bool "; 77*0b57cec5SDimitry Andric Pad += 13; 78*0b57cec5SDimitry Andric } 79*0b57cec5SDimitry Andric O << CC->getName() << "(unsigned ValNo, MVT ValVT,\n" 80*0b57cec5SDimitry Andric << std::string(Pad, ' ') << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n" 81*0b57cec5SDimitry Andric << std::string(Pad, ' ') << "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n"; 82*0b57cec5SDimitry Andric // Emit all of the actions, in order. 83*0b57cec5SDimitry Andric for (unsigned i = 0, e = CCActions->size(); i != e; ++i) { 84*0b57cec5SDimitry Andric O << "\n"; 85*0b57cec5SDimitry Andric EmitAction(CCActions->getElementAsRecord(i), 2, O); 86*0b57cec5SDimitry Andric } 87*0b57cec5SDimitry Andric 88*0b57cec5SDimitry Andric O << "\n return true; // CC didn't match.\n"; 89*0b57cec5SDimitry Andric O << "}\n"; 90*0b57cec5SDimitry Andric } 91*0b57cec5SDimitry Andric 92*0b57cec5SDimitry Andric void CallingConvEmitter::EmitAction(Record *Action, 93*0b57cec5SDimitry Andric unsigned Indent, raw_ostream &O) { 94*0b57cec5SDimitry Andric std::string IndentStr = std::string(Indent, ' '); 95*0b57cec5SDimitry Andric 96*0b57cec5SDimitry Andric if (Action->isSubClassOf("CCPredicateAction")) { 97*0b57cec5SDimitry Andric O << IndentStr << "if ("; 98*0b57cec5SDimitry Andric 99*0b57cec5SDimitry Andric if (Action->isSubClassOf("CCIfType")) { 100*0b57cec5SDimitry Andric ListInit *VTs = Action->getValueAsListInit("VTs"); 101*0b57cec5SDimitry Andric for (unsigned i = 0, e = VTs->size(); i != e; ++i) { 102*0b57cec5SDimitry Andric Record *VT = VTs->getElementAsRecord(i); 103*0b57cec5SDimitry Andric if (i != 0) O << " ||\n " << IndentStr; 104*0b57cec5SDimitry Andric O << "LocVT == " << getEnumName(getValueType(VT)); 105*0b57cec5SDimitry Andric } 106*0b57cec5SDimitry Andric 107*0b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCIf")) { 108*0b57cec5SDimitry Andric O << Action->getValueAsString("Predicate"); 109*0b57cec5SDimitry Andric } else { 110*0b57cec5SDimitry Andric errs() << *Action; 111*0b57cec5SDimitry Andric PrintFatalError(Action->getLoc(), "Unknown CCPredicateAction!"); 112*0b57cec5SDimitry Andric } 113*0b57cec5SDimitry Andric 114*0b57cec5SDimitry Andric O << ") {\n"; 115*0b57cec5SDimitry Andric EmitAction(Action->getValueAsDef("SubAction"), Indent+2, O); 116*0b57cec5SDimitry Andric O << IndentStr << "}\n"; 117*0b57cec5SDimitry Andric } else { 118*0b57cec5SDimitry Andric if (Action->isSubClassOf("CCDelegateTo")) { 119*0b57cec5SDimitry Andric Record *CC = Action->getValueAsDef("CC"); 120*0b57cec5SDimitry Andric O << IndentStr << "if (!" << CC->getName() 121*0b57cec5SDimitry Andric << "(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))\n" 122*0b57cec5SDimitry Andric << IndentStr << " return false;\n"; 123*0b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCAssignToReg")) { 124*0b57cec5SDimitry Andric ListInit *RegList = Action->getValueAsListInit("RegList"); 125*0b57cec5SDimitry Andric if (RegList->size() == 1) { 126*0b57cec5SDimitry Andric O << IndentStr << "if (unsigned Reg = State.AllocateReg("; 127*0b57cec5SDimitry Andric O << getQualifiedName(RegList->getElementAsRecord(0)) << ")) {\n"; 128*0b57cec5SDimitry Andric } else { 129*0b57cec5SDimitry Andric O << IndentStr << "static const MCPhysReg RegList" << ++Counter 130*0b57cec5SDimitry Andric << "[] = {\n"; 131*0b57cec5SDimitry Andric O << IndentStr << " "; 132*0b57cec5SDimitry Andric for (unsigned i = 0, e = RegList->size(); i != e; ++i) { 133*0b57cec5SDimitry Andric if (i != 0) O << ", "; 134*0b57cec5SDimitry Andric O << getQualifiedName(RegList->getElementAsRecord(i)); 135*0b57cec5SDimitry Andric } 136*0b57cec5SDimitry Andric O << "\n" << IndentStr << "};\n"; 137*0b57cec5SDimitry Andric O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList" 138*0b57cec5SDimitry Andric << Counter << ")) {\n"; 139*0b57cec5SDimitry Andric } 140*0b57cec5SDimitry Andric O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, " 141*0b57cec5SDimitry Andric << "Reg, LocVT, LocInfo));\n"; 142*0b57cec5SDimitry Andric O << IndentStr << " return false;\n"; 143*0b57cec5SDimitry Andric O << IndentStr << "}\n"; 144*0b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCAssignToRegWithShadow")) { 145*0b57cec5SDimitry Andric ListInit *RegList = Action->getValueAsListInit("RegList"); 146*0b57cec5SDimitry Andric ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList"); 147*0b57cec5SDimitry Andric if (!ShadowRegList->empty() && ShadowRegList->size() != RegList->size()) 148*0b57cec5SDimitry Andric PrintFatalError(Action->getLoc(), 149*0b57cec5SDimitry Andric "Invalid length of list of shadowed registers"); 150*0b57cec5SDimitry Andric 151*0b57cec5SDimitry Andric if (RegList->size() == 1) { 152*0b57cec5SDimitry Andric O << IndentStr << "if (unsigned Reg = State.AllocateReg("; 153*0b57cec5SDimitry Andric O << getQualifiedName(RegList->getElementAsRecord(0)); 154*0b57cec5SDimitry Andric O << ", " << getQualifiedName(ShadowRegList->getElementAsRecord(0)); 155*0b57cec5SDimitry Andric O << ")) {\n"; 156*0b57cec5SDimitry Andric } else { 157*0b57cec5SDimitry Andric unsigned RegListNumber = ++Counter; 158*0b57cec5SDimitry Andric unsigned ShadowRegListNumber = ++Counter; 159*0b57cec5SDimitry Andric 160*0b57cec5SDimitry Andric O << IndentStr << "static const MCPhysReg RegList" << RegListNumber 161*0b57cec5SDimitry Andric << "[] = {\n"; 162*0b57cec5SDimitry Andric O << IndentStr << " "; 163*0b57cec5SDimitry Andric for (unsigned i = 0, e = RegList->size(); i != e; ++i) { 164*0b57cec5SDimitry Andric if (i != 0) O << ", "; 165*0b57cec5SDimitry Andric O << getQualifiedName(RegList->getElementAsRecord(i)); 166*0b57cec5SDimitry Andric } 167*0b57cec5SDimitry Andric O << "\n" << IndentStr << "};\n"; 168*0b57cec5SDimitry Andric 169*0b57cec5SDimitry Andric O << IndentStr << "static const MCPhysReg RegList" 170*0b57cec5SDimitry Andric << ShadowRegListNumber << "[] = {\n"; 171*0b57cec5SDimitry Andric O << IndentStr << " "; 172*0b57cec5SDimitry Andric for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i) { 173*0b57cec5SDimitry Andric if (i != 0) O << ", "; 174*0b57cec5SDimitry Andric O << getQualifiedName(ShadowRegList->getElementAsRecord(i)); 175*0b57cec5SDimitry Andric } 176*0b57cec5SDimitry Andric O << "\n" << IndentStr << "};\n"; 177*0b57cec5SDimitry Andric 178*0b57cec5SDimitry Andric O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList" 179*0b57cec5SDimitry Andric << RegListNumber << ", " << "RegList" << ShadowRegListNumber 180*0b57cec5SDimitry Andric << ")) {\n"; 181*0b57cec5SDimitry Andric } 182*0b57cec5SDimitry Andric O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, " 183*0b57cec5SDimitry Andric << "Reg, LocVT, LocInfo));\n"; 184*0b57cec5SDimitry Andric O << IndentStr << " return false;\n"; 185*0b57cec5SDimitry Andric O << IndentStr << "}\n"; 186*0b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCAssignToStack")) { 187*0b57cec5SDimitry Andric int Size = Action->getValueAsInt("Size"); 188*0b57cec5SDimitry Andric int Align = Action->getValueAsInt("Align"); 189*0b57cec5SDimitry Andric 190*0b57cec5SDimitry Andric O << IndentStr << "unsigned Offset" << ++Counter 191*0b57cec5SDimitry Andric << " = State.AllocateStack("; 192*0b57cec5SDimitry Andric if (Size) 193*0b57cec5SDimitry Andric O << Size << ", "; 194*0b57cec5SDimitry Andric else 195*0b57cec5SDimitry Andric O << "\n" << IndentStr 196*0b57cec5SDimitry Andric << " State.getMachineFunction().getDataLayout()." 197*0b57cec5SDimitry Andric "getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext()))," 198*0b57cec5SDimitry Andric " "; 199*0b57cec5SDimitry Andric if (Align) 200*0b57cec5SDimitry Andric O << Align; 201*0b57cec5SDimitry Andric else 202*0b57cec5SDimitry Andric O << "\n" << IndentStr 203*0b57cec5SDimitry Andric << " State.getMachineFunction().getDataLayout()." 204*0b57cec5SDimitry Andric "getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()" 205*0b57cec5SDimitry Andric "))"; 206*0b57cec5SDimitry Andric O << ");\n" << IndentStr 207*0b57cec5SDimitry Andric << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset" 208*0b57cec5SDimitry Andric << Counter << ", LocVT, LocInfo));\n"; 209*0b57cec5SDimitry Andric O << IndentStr << "return false;\n"; 210*0b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCAssignToStackWithShadow")) { 211*0b57cec5SDimitry Andric int Size = Action->getValueAsInt("Size"); 212*0b57cec5SDimitry Andric int Align = Action->getValueAsInt("Align"); 213*0b57cec5SDimitry Andric ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList"); 214*0b57cec5SDimitry Andric 215*0b57cec5SDimitry Andric unsigned ShadowRegListNumber = ++Counter; 216*0b57cec5SDimitry Andric 217*0b57cec5SDimitry Andric O << IndentStr << "static const MCPhysReg ShadowRegList" 218*0b57cec5SDimitry Andric << ShadowRegListNumber << "[] = {\n"; 219*0b57cec5SDimitry Andric O << IndentStr << " "; 220*0b57cec5SDimitry Andric for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i) { 221*0b57cec5SDimitry Andric if (i != 0) O << ", "; 222*0b57cec5SDimitry Andric O << getQualifiedName(ShadowRegList->getElementAsRecord(i)); 223*0b57cec5SDimitry Andric } 224*0b57cec5SDimitry Andric O << "\n" << IndentStr << "};\n"; 225*0b57cec5SDimitry Andric 226*0b57cec5SDimitry Andric O << IndentStr << "unsigned Offset" << ++Counter 227*0b57cec5SDimitry Andric << " = State.AllocateStack(" 228*0b57cec5SDimitry Andric << Size << ", " << Align << ", " 229*0b57cec5SDimitry Andric << "ShadowRegList" << ShadowRegListNumber << ");\n"; 230*0b57cec5SDimitry Andric O << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset" 231*0b57cec5SDimitry Andric << Counter << ", LocVT, LocInfo));\n"; 232*0b57cec5SDimitry Andric O << IndentStr << "return false;\n"; 233*0b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCPromoteToType")) { 234*0b57cec5SDimitry Andric Record *DestTy = Action->getValueAsDef("DestTy"); 235*0b57cec5SDimitry Andric MVT::SimpleValueType DestVT = getValueType(DestTy); 236*0b57cec5SDimitry Andric O << IndentStr << "LocVT = " << getEnumName(DestVT) <<";\n"; 237*0b57cec5SDimitry Andric if (MVT(DestVT).isFloatingPoint()) { 238*0b57cec5SDimitry Andric O << IndentStr << "LocInfo = CCValAssign::FPExt;\n"; 239*0b57cec5SDimitry Andric } else { 240*0b57cec5SDimitry Andric O << IndentStr << "if (ArgFlags.isSExt())\n" 241*0b57cec5SDimitry Andric << IndentStr << IndentStr << "LocInfo = CCValAssign::SExt;\n" 242*0b57cec5SDimitry Andric << IndentStr << "else if (ArgFlags.isZExt())\n" 243*0b57cec5SDimitry Andric << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExt;\n" 244*0b57cec5SDimitry Andric << IndentStr << "else\n" 245*0b57cec5SDimitry Andric << IndentStr << IndentStr << "LocInfo = CCValAssign::AExt;\n"; 246*0b57cec5SDimitry Andric } 247*0b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCPromoteToUpperBitsInType")) { 248*0b57cec5SDimitry Andric Record *DestTy = Action->getValueAsDef("DestTy"); 249*0b57cec5SDimitry Andric MVT::SimpleValueType DestVT = getValueType(DestTy); 250*0b57cec5SDimitry Andric O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n"; 251*0b57cec5SDimitry Andric if (MVT(DestVT).isFloatingPoint()) { 252*0b57cec5SDimitry Andric PrintFatalError(Action->getLoc(), 253*0b57cec5SDimitry Andric "CCPromoteToUpperBitsInType does not handle floating " 254*0b57cec5SDimitry Andric "point"); 255*0b57cec5SDimitry Andric } else { 256*0b57cec5SDimitry Andric O << IndentStr << "if (ArgFlags.isSExt())\n" 257*0b57cec5SDimitry Andric << IndentStr << IndentStr << "LocInfo = CCValAssign::SExtUpper;\n" 258*0b57cec5SDimitry Andric << IndentStr << "else if (ArgFlags.isZExt())\n" 259*0b57cec5SDimitry Andric << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExtUpper;\n" 260*0b57cec5SDimitry Andric << IndentStr << "else\n" 261*0b57cec5SDimitry Andric << IndentStr << IndentStr << "LocInfo = CCValAssign::AExtUpper;\n"; 262*0b57cec5SDimitry Andric } 263*0b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCBitConvertToType")) { 264*0b57cec5SDimitry Andric Record *DestTy = Action->getValueAsDef("DestTy"); 265*0b57cec5SDimitry Andric O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n"; 266*0b57cec5SDimitry Andric O << IndentStr << "LocInfo = CCValAssign::BCvt;\n"; 267*0b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCPassIndirect")) { 268*0b57cec5SDimitry Andric Record *DestTy = Action->getValueAsDef("DestTy"); 269*0b57cec5SDimitry Andric O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n"; 270*0b57cec5SDimitry Andric O << IndentStr << "LocInfo = CCValAssign::Indirect;\n"; 271*0b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCPassByVal")) { 272*0b57cec5SDimitry Andric int Size = Action->getValueAsInt("Size"); 273*0b57cec5SDimitry Andric int Align = Action->getValueAsInt("Align"); 274*0b57cec5SDimitry Andric O << IndentStr 275*0b57cec5SDimitry Andric << "State.HandleByVal(ValNo, ValVT, LocVT, LocInfo, " 276*0b57cec5SDimitry Andric << Size << ", " << Align << ", ArgFlags);\n"; 277*0b57cec5SDimitry Andric O << IndentStr << "return false;\n"; 278*0b57cec5SDimitry Andric } else if (Action->isSubClassOf("CCCustom")) { 279*0b57cec5SDimitry Andric O << IndentStr 280*0b57cec5SDimitry Andric << "if (" << Action->getValueAsString("FuncName") << "(ValNo, ValVT, " 281*0b57cec5SDimitry Andric << "LocVT, LocInfo, ArgFlags, State))\n"; 282*0b57cec5SDimitry Andric O << IndentStr << IndentStr << "return false;\n"; 283*0b57cec5SDimitry Andric } else { 284*0b57cec5SDimitry Andric errs() << *Action; 285*0b57cec5SDimitry Andric PrintFatalError(Action->getLoc(), "Unknown CCAction!"); 286*0b57cec5SDimitry Andric } 287*0b57cec5SDimitry Andric } 288*0b57cec5SDimitry Andric } 289*0b57cec5SDimitry Andric 290*0b57cec5SDimitry Andric namespace llvm { 291*0b57cec5SDimitry Andric 292*0b57cec5SDimitry Andric void EmitCallingConv(RecordKeeper &RK, raw_ostream &OS) { 293*0b57cec5SDimitry Andric emitSourceFileHeader("Calling Convention Implementation Fragment", OS); 294*0b57cec5SDimitry Andric CallingConvEmitter(RK).run(OS); 295*0b57cec5SDimitry Andric } 296*0b57cec5SDimitry Andric 297*0b57cec5SDimitry Andric } // End llvm namespace 298