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