1 //===- CallingConvEmitter.cpp - Generate calling conventions --------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This tablegen backend is responsible for emitting descriptions of the calling 10 // conventions supported by this target. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "CodeGenTarget.h" 15 #include "llvm/TableGen/Error.h" 16 #include "llvm/TableGen/Record.h" 17 #include "llvm/TableGen/TableGenBackend.h" 18 #include <deque> 19 #include <set> 20 21 using namespace llvm; 22 23 namespace { 24 class CallingConvEmitter { 25 RecordKeeper &Records; 26 unsigned Counter = 0u; 27 std::string CurrentAction; 28 bool SwiftAction = false; 29 30 std::map<std::string, std::set<std::string>> AssignedRegsMap; 31 std::map<std::string, std::set<std::string>> AssignedSwiftRegsMap; 32 std::map<std::string, std::set<std::string>> DelegateToMap; 33 34 public: 35 explicit CallingConvEmitter(RecordKeeper &R) : Records(R) {} 36 37 void run(raw_ostream &o); 38 39 private: 40 void EmitCallingConv(Record *CC, raw_ostream &O); 41 void EmitAction(Record *Action, unsigned Indent, raw_ostream &O); 42 void EmitArgRegisterLists(raw_ostream &O); 43 }; 44 } // End anonymous namespace 45 46 void CallingConvEmitter::run(raw_ostream &O) { 47 emitSourceFileHeader("Calling Convention Implementation Fragment", O); 48 49 std::vector<Record *> CCs = Records.getAllDerivedDefinitions("CallingConv"); 50 51 // Emit prototypes for all of the non-custom CC's so that they can forward ref 52 // each other. 53 Records.startTimer("Emit prototypes"); 54 O << "#ifndef GET_CC_REGISTER_LISTS\n\n"; 55 for (Record *CC : CCs) { 56 if (!CC->getValueAsBit("Custom")) { 57 unsigned Pad = CC->getName().size(); 58 if (CC->getValueAsBit("Entry")) { 59 O << "bool llvm::"; 60 Pad += 12; 61 } else { 62 O << "static bool "; 63 Pad += 13; 64 } 65 O << CC->getName() << "(unsigned ValNo, MVT ValVT,\n" 66 << std::string(Pad, ' ') << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n" 67 << std::string(Pad, ' ') 68 << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n"; 69 } 70 } 71 72 // Emit each non-custom calling convention description in full. 73 Records.startTimer("Emit full descriptions"); 74 for (Record *CC : CCs) { 75 if (!CC->getValueAsBit("Custom")) { 76 EmitCallingConv(CC, O); 77 } 78 } 79 80 EmitArgRegisterLists(O); 81 82 O << "\n#endif // CC_REGISTER_LIST\n"; 83 } 84 85 void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) { 86 ListInit *CCActions = CC->getValueAsListInit("Actions"); 87 Counter = 0; 88 89 CurrentAction = CC->getName().str(); 90 // Call upon the creation of a map entry from the void! 91 // We want an entry in AssignedRegsMap for every action, even if that 92 // entry is empty. 93 AssignedRegsMap[CurrentAction] = {}; 94 95 O << "\n\n"; 96 unsigned Pad = CurrentAction.size(); 97 if (CC->getValueAsBit("Entry")) { 98 O << "bool llvm::"; 99 Pad += 12; 100 } else { 101 O << "static bool "; 102 Pad += 13; 103 } 104 O << CurrentAction << "(unsigned ValNo, MVT ValVT,\n" 105 << std::string(Pad, ' ') << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n" 106 << std::string(Pad, ' ') << "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n"; 107 // Emit all of the actions, in order. 108 for (unsigned i = 0, e = CCActions->size(); i != e; ++i) { 109 Record *Action = CCActions->getElementAsRecord(i); 110 SwiftAction = 111 llvm::any_of(Action->getSuperClasses(), 112 [](const std::pair<Record *, SMRange> &Class) { 113 std::string Name = Class.first->getNameInitAsString(); 114 return StringRef(Name).starts_with("CCIfSwift"); 115 }); 116 117 O << "\n"; 118 EmitAction(Action, 2, O); 119 } 120 121 O << "\n return true; // CC didn't match.\n"; 122 O << "}\n"; 123 } 124 125 void CallingConvEmitter::EmitAction(Record *Action, 126 unsigned Indent, raw_ostream &O) { 127 std::string IndentStr = std::string(Indent, ' '); 128 129 if (Action->isSubClassOf("CCPredicateAction")) { 130 O << IndentStr << "if ("; 131 132 if (Action->isSubClassOf("CCIfType")) { 133 ListInit *VTs = Action->getValueAsListInit("VTs"); 134 for (unsigned i = 0, e = VTs->size(); i != e; ++i) { 135 Record *VT = VTs->getElementAsRecord(i); 136 if (i != 0) O << " ||\n " << IndentStr; 137 O << "LocVT == " << getEnumName(getValueType(VT)); 138 } 139 140 } else if (Action->isSubClassOf("CCIf")) { 141 O << Action->getValueAsString("Predicate"); 142 } else { 143 errs() << *Action; 144 PrintFatalError(Action->getLoc(), "Unknown CCPredicateAction!"); 145 } 146 147 O << ") {\n"; 148 EmitAction(Action->getValueAsDef("SubAction"), Indent+2, O); 149 O << IndentStr << "}\n"; 150 } else { 151 if (Action->isSubClassOf("CCDelegateTo")) { 152 Record *CC = Action->getValueAsDef("CC"); 153 O << IndentStr << "if (!" << CC->getName() 154 << "(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))\n" 155 << IndentStr << " return false;\n"; 156 DelegateToMap[CurrentAction].insert(CC->getName().str()); 157 } else if (Action->isSubClassOf("CCAssignToReg") || 158 Action->isSubClassOf("CCAssignToRegAndStack")) { 159 ListInit *RegList = Action->getValueAsListInit("RegList"); 160 if (RegList->size() == 1) { 161 std::string Name = getQualifiedName(RegList->getElementAsRecord(0)); 162 O << IndentStr << "if (unsigned Reg = State.AllocateReg(" << Name 163 << ")) {\n"; 164 if (SwiftAction) 165 AssignedSwiftRegsMap[CurrentAction].insert(Name); 166 else 167 AssignedRegsMap[CurrentAction].insert(Name); 168 } else { 169 O << IndentStr << "static const MCPhysReg RegList" << ++Counter 170 << "[] = {\n"; 171 O << IndentStr << " "; 172 ListSeparator LS; 173 for (unsigned i = 0, e = RegList->size(); i != e; ++i) { 174 std::string Name = getQualifiedName(RegList->getElementAsRecord(i)); 175 if (SwiftAction) 176 AssignedSwiftRegsMap[CurrentAction].insert(Name); 177 else 178 AssignedRegsMap[CurrentAction].insert(Name); 179 O << LS << Name; 180 } 181 O << "\n" << IndentStr << "};\n"; 182 O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList" 183 << Counter << ")) {\n"; 184 } 185 O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, " 186 << "Reg, LocVT, LocInfo));\n"; 187 if (Action->isSubClassOf("CCAssignToRegAndStack")) { 188 int Size = Action->getValueAsInt("Size"); 189 int Align = Action->getValueAsInt("Align"); 190 O << IndentStr << " (void)State.AllocateStack("; 191 if (Size) 192 O << Size << ", "; 193 else 194 O << "\n" 195 << IndentStr 196 << " State.getMachineFunction().getDataLayout()." 197 "getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext()))," 198 " "; 199 if (Align) 200 O << "Align(" << Align << ")"; 201 else 202 O << "\n" 203 << IndentStr 204 << " State.getMachineFunction().getDataLayout()." 205 "getABITypeAlign(EVT(LocVT).getTypeForEVT(State.getContext()" 206 "))"; 207 O << ");\n"; 208 } 209 O << IndentStr << " return false;\n"; 210 O << IndentStr << "}\n"; 211 } else if (Action->isSubClassOf("CCAssignToRegWithShadow")) { 212 ListInit *RegList = Action->getValueAsListInit("RegList"); 213 ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList"); 214 if (!ShadowRegList->empty() && ShadowRegList->size() != RegList->size()) 215 PrintFatalError(Action->getLoc(), 216 "Invalid length of list of shadowed registers"); 217 218 if (RegList->size() == 1) { 219 O << IndentStr << "if (unsigned Reg = State.AllocateReg("; 220 O << getQualifiedName(RegList->getElementAsRecord(0)); 221 O << ", " << getQualifiedName(ShadowRegList->getElementAsRecord(0)); 222 O << ")) {\n"; 223 } else { 224 unsigned RegListNumber = ++Counter; 225 unsigned ShadowRegListNumber = ++Counter; 226 227 O << IndentStr << "static const MCPhysReg RegList" << RegListNumber 228 << "[] = {\n"; 229 O << IndentStr << " "; 230 ListSeparator LS; 231 for (unsigned i = 0, e = RegList->size(); i != e; ++i) 232 O << LS << getQualifiedName(RegList->getElementAsRecord(i)); 233 O << "\n" << IndentStr << "};\n"; 234 235 O << IndentStr << "static const MCPhysReg RegList" 236 << ShadowRegListNumber << "[] = {\n"; 237 O << IndentStr << " "; 238 ListSeparator LSS; 239 for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i) 240 O << LSS << getQualifiedName(ShadowRegList->getElementAsRecord(i)); 241 O << "\n" << IndentStr << "};\n"; 242 243 O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList" 244 << RegListNumber << ", " << "RegList" << ShadowRegListNumber 245 << ")) {\n"; 246 } 247 O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, " 248 << "Reg, LocVT, LocInfo));\n"; 249 O << IndentStr << " return false;\n"; 250 O << IndentStr << "}\n"; 251 } else if (Action->isSubClassOf("CCAssignToStack")) { 252 int Size = Action->getValueAsInt("Size"); 253 int Align = Action->getValueAsInt("Align"); 254 255 O << IndentStr << "int64_t Offset" << ++Counter 256 << " = State.AllocateStack("; 257 if (Size) 258 O << Size << ", "; 259 else 260 O << "\n" << IndentStr 261 << " State.getMachineFunction().getDataLayout()." 262 "getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext()))," 263 " "; 264 if (Align) 265 O << "Align(" << Align << ")"; 266 else 267 O << "\n" 268 << IndentStr 269 << " State.getMachineFunction().getDataLayout()." 270 "getABITypeAlign(EVT(LocVT).getTypeForEVT(State.getContext()" 271 "))"; 272 O << ");\n" << IndentStr 273 << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset" 274 << Counter << ", LocVT, LocInfo));\n"; 275 O << IndentStr << "return false;\n"; 276 } else if (Action->isSubClassOf("CCAssignToStackWithShadow")) { 277 int Size = Action->getValueAsInt("Size"); 278 int Align = Action->getValueAsInt("Align"); 279 ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList"); 280 281 unsigned ShadowRegListNumber = ++Counter; 282 283 O << IndentStr << "static const MCPhysReg ShadowRegList" 284 << ShadowRegListNumber << "[] = {\n"; 285 O << IndentStr << " "; 286 ListSeparator LS; 287 for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i) 288 O << LS << getQualifiedName(ShadowRegList->getElementAsRecord(i)); 289 O << "\n" << IndentStr << "};\n"; 290 291 O << IndentStr << "int64_t Offset" << ++Counter 292 << " = State.AllocateStack(" << Size << ", Align(" << Align << "), " 293 << "ShadowRegList" << ShadowRegListNumber << ");\n"; 294 O << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset" 295 << Counter << ", LocVT, LocInfo));\n"; 296 O << IndentStr << "return false;\n"; 297 } else if (Action->isSubClassOf("CCPromoteToType")) { 298 Record *DestTy = Action->getValueAsDef("DestTy"); 299 MVT::SimpleValueType DestVT = getValueType(DestTy); 300 O << IndentStr << "LocVT = " << getEnumName(DestVT) <<";\n"; 301 if (MVT(DestVT).isFloatingPoint()) { 302 O << IndentStr << "LocInfo = CCValAssign::FPExt;\n"; 303 } else { 304 O << IndentStr << "if (ArgFlags.isSExt())\n" 305 << IndentStr << " LocInfo = CCValAssign::SExt;\n" 306 << IndentStr << "else if (ArgFlags.isZExt())\n" 307 << IndentStr << " LocInfo = CCValAssign::ZExt;\n" 308 << IndentStr << "else\n" 309 << IndentStr << " LocInfo = CCValAssign::AExt;\n"; 310 } 311 } else if (Action->isSubClassOf("CCPromoteToUpperBitsInType")) { 312 Record *DestTy = Action->getValueAsDef("DestTy"); 313 MVT::SimpleValueType DestVT = getValueType(DestTy); 314 O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n"; 315 if (MVT(DestVT).isFloatingPoint()) { 316 PrintFatalError(Action->getLoc(), 317 "CCPromoteToUpperBitsInType does not handle floating " 318 "point"); 319 } else { 320 O << IndentStr << "if (ArgFlags.isSExt())\n" 321 << IndentStr << " LocInfo = CCValAssign::SExtUpper;\n" 322 << IndentStr << "else if (ArgFlags.isZExt())\n" 323 << IndentStr << " LocInfo = CCValAssign::ZExtUpper;\n" 324 << IndentStr << "else\n" 325 << IndentStr << " LocInfo = CCValAssign::AExtUpper;\n"; 326 } 327 } else if (Action->isSubClassOf("CCBitConvertToType")) { 328 Record *DestTy = Action->getValueAsDef("DestTy"); 329 O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n"; 330 O << IndentStr << "LocInfo = CCValAssign::BCvt;\n"; 331 } else if (Action->isSubClassOf("CCTruncToType")) { 332 Record *DestTy = Action->getValueAsDef("DestTy"); 333 O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n"; 334 O << IndentStr << "LocInfo = CCValAssign::Trunc;\n"; 335 } else if (Action->isSubClassOf("CCPassIndirect")) { 336 Record *DestTy = Action->getValueAsDef("DestTy"); 337 O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n"; 338 O << IndentStr << "LocInfo = CCValAssign::Indirect;\n"; 339 } else if (Action->isSubClassOf("CCPassByVal")) { 340 int Size = Action->getValueAsInt("Size"); 341 int Align = Action->getValueAsInt("Align"); 342 O << IndentStr << "State.HandleByVal(ValNo, ValVT, LocVT, LocInfo, " 343 << Size << ", Align(" << Align << "), ArgFlags);\n"; 344 O << IndentStr << "return false;\n"; 345 } else if (Action->isSubClassOf("CCCustom")) { 346 O << IndentStr 347 << "if (" << Action->getValueAsString("FuncName") << "(ValNo, ValVT, " 348 << "LocVT, LocInfo, ArgFlags, State))\n"; 349 O << IndentStr << " return false;\n"; 350 } else { 351 errs() << *Action; 352 PrintFatalError(Action->getLoc(), "Unknown CCAction!"); 353 } 354 } 355 } 356 357 void CallingConvEmitter::EmitArgRegisterLists(raw_ostream &O) { 358 // Transitively merge all delegated CCs into AssignedRegsMap. 359 using EntryTy = std::pair<std::string, std::set<std::string>>; 360 bool Redo; 361 do { 362 Redo = false; 363 std::deque<EntryTy> Worklist(DelegateToMap.begin(), DelegateToMap.end()); 364 365 while (!Worklist.empty()) { 366 EntryTy Entry = Worklist.front(); 367 Worklist.pop_front(); 368 369 const std::string &CCName = Entry.first; 370 std::set<std::string> &Registers = Entry.second; 371 if (!Registers.empty()) 372 continue; 373 374 for (auto &InnerEntry : Worklist) { 375 const std::string &InnerCCName = InnerEntry.first; 376 std::set<std::string> &InnerRegisters = InnerEntry.second; 377 378 if (InnerRegisters.find(CCName) != InnerRegisters.end()) { 379 AssignedRegsMap[InnerCCName].insert( 380 AssignedRegsMap[CCName].begin(), 381 AssignedRegsMap[CCName].end()); 382 InnerRegisters.erase(CCName); 383 } 384 } 385 386 DelegateToMap.erase(CCName); 387 Redo = true; 388 } 389 } while (Redo); 390 391 if (AssignedRegsMap.empty()) 392 return; 393 394 O << "\n#else\n\n"; 395 396 for (auto &Entry : AssignedRegsMap) { 397 const std::string &RegName = Entry.first; 398 std::set<std::string> &Registers = Entry.second; 399 400 if (RegName.empty()) 401 continue; 402 403 O << "const MCRegister " << Entry.first << "_ArgRegs[] = { "; 404 405 if (Registers.empty()) { 406 O << "0"; 407 } else { 408 ListSeparator LS; 409 for (const std::string &Reg : Registers) 410 O << LS << Reg; 411 } 412 413 O << " };\n"; 414 } 415 416 if (AssignedSwiftRegsMap.empty()) 417 return; 418 419 O << "\n// Registers used by Swift.\n"; 420 for (auto &Entry : AssignedSwiftRegsMap) { 421 const std::string &RegName = Entry.first; 422 std::set<std::string> &Registers = Entry.second; 423 424 O << "const MCRegister " << RegName << "_Swift_ArgRegs[] = { "; 425 426 ListSeparator LS; 427 for (const std::string &Reg : Registers) 428 O << LS << Reg; 429 430 O << " };\n"; 431 } 432 } 433 434 static TableGen::Emitter::OptClass<CallingConvEmitter> 435 X("gen-callingconv", "Generate calling convention descriptions"); 436