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/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, unsigned Indent, 126 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) 137 O << " ||\n " << IndentStr; 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 << IndentStr << "}\n"; 151 } else { 152 if (Action->isSubClassOf("CCDelegateTo")) { 153 Record *CC = Action->getValueAsDef("CC"); 154 O << IndentStr << "if (!" << CC->getName() 155 << "(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))\n" 156 << IndentStr << " return false;\n"; 157 DelegateToMap[CurrentAction].insert(CC->getName().str()); 158 } else if (Action->isSubClassOf("CCAssignToReg") || 159 Action->isSubClassOf("CCAssignToRegAndStack")) { 160 ListInit *RegList = Action->getValueAsListInit("RegList"); 161 if (RegList->size() == 1) { 162 std::string Name = getQualifiedName(RegList->getElementAsRecord(0)); 163 O << IndentStr << "if (unsigned Reg = State.AllocateReg(" << Name 164 << ")) {\n"; 165 if (SwiftAction) 166 AssignedSwiftRegsMap[CurrentAction].insert(Name); 167 else 168 AssignedRegsMap[CurrentAction].insert(Name); 169 } else { 170 O << IndentStr << "static const MCPhysReg RegList" << ++Counter 171 << "[] = {\n"; 172 O << IndentStr << " "; 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" << IndentStr << "};\n"; 183 O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList" 184 << Counter << ")) {\n"; 185 } 186 O << IndentStr << " 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 << IndentStr << " (void)State.AllocateStack("; 192 if (Size) 193 O << Size << ", "; 194 else 195 O << "\n" 196 << IndentStr 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 << IndentStr 205 << " State.getMachineFunction().getDataLayout()." 206 "getABITypeAlign(EVT(LocVT).getTypeForEVT(State.getContext()" 207 "))"; 208 O << ");\n"; 209 } 210 O << IndentStr << " return false;\n"; 211 O << IndentStr << "}\n"; 212 } else if (Action->isSubClassOf("CCAssignToRegWithShadow")) { 213 ListInit *RegList = Action->getValueAsListInit("RegList"); 214 ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList"); 215 if (!ShadowRegList->empty() && ShadowRegList->size() != RegList->size()) 216 PrintFatalError(Action->getLoc(), 217 "Invalid length of list of shadowed registers"); 218 219 if (RegList->size() == 1) { 220 O << IndentStr << "if (unsigned Reg = State.AllocateReg("; 221 O << getQualifiedName(RegList->getElementAsRecord(0)); 222 O << ", " << getQualifiedName(ShadowRegList->getElementAsRecord(0)); 223 O << ")) {\n"; 224 } else { 225 unsigned RegListNumber = ++Counter; 226 unsigned ShadowRegListNumber = ++Counter; 227 228 O << IndentStr << "static const MCPhysReg RegList" << RegListNumber 229 << "[] = {\n"; 230 O << IndentStr << " "; 231 ListSeparator LS; 232 for (unsigned i = 0, e = RegList->size(); i != e; ++i) 233 O << LS << getQualifiedName(RegList->getElementAsRecord(i)); 234 O << "\n" << IndentStr << "};\n"; 235 236 O << IndentStr << "static const MCPhysReg RegList" 237 << ShadowRegListNumber << "[] = {\n"; 238 O << IndentStr << " "; 239 ListSeparator LSS; 240 for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i) 241 O << LSS << getQualifiedName(ShadowRegList->getElementAsRecord(i)); 242 O << "\n" << IndentStr << "};\n"; 243 244 O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList" 245 << RegListNumber << ", " 246 << "RegList" << ShadowRegListNumber << ")) {\n"; 247 } 248 O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, " 249 << "Reg, LocVT, LocInfo));\n"; 250 O << IndentStr << " return false;\n"; 251 O << IndentStr << "}\n"; 252 } else if (Action->isSubClassOf("CCAssignToStack")) { 253 int Size = Action->getValueAsInt("Size"); 254 int Align = Action->getValueAsInt("Align"); 255 256 O << IndentStr << "int64_t Offset" << ++Counter 257 << " = State.AllocateStack("; 258 if (Size) 259 O << Size << ", "; 260 else 261 O << "\n" 262 << IndentStr 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 << IndentStr 271 << " State.getMachineFunction().getDataLayout()." 272 "getABITypeAlign(EVT(LocVT).getTypeForEVT(State.getContext()" 273 "))"; 274 O << ");\n" 275 << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset" 276 << Counter << ", LocVT, LocInfo));\n"; 277 O << IndentStr << "return false;\n"; 278 } else if (Action->isSubClassOf("CCAssignToStackWithShadow")) { 279 int Size = Action->getValueAsInt("Size"); 280 int Align = Action->getValueAsInt("Align"); 281 ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList"); 282 283 unsigned ShadowRegListNumber = ++Counter; 284 285 O << IndentStr << "static const MCPhysReg ShadowRegList" 286 << ShadowRegListNumber << "[] = {\n"; 287 O << IndentStr << " "; 288 ListSeparator LS; 289 for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i) 290 O << LS << getQualifiedName(ShadowRegList->getElementAsRecord(i)); 291 O << "\n" << IndentStr << "};\n"; 292 293 O << IndentStr << "int64_t Offset" << ++Counter 294 << " = State.AllocateStack(" << Size << ", Align(" << Align << "), " 295 << "ShadowRegList" << ShadowRegListNumber << ");\n"; 296 O << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset" 297 << Counter << ", LocVT, LocInfo));\n"; 298 O << IndentStr << "return false;\n"; 299 } else if (Action->isSubClassOf("CCPromoteToType")) { 300 Record *DestTy = Action->getValueAsDef("DestTy"); 301 MVT::SimpleValueType DestVT = getValueType(DestTy); 302 O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n"; 303 if (MVT(DestVT).isFloatingPoint()) { 304 O << IndentStr << "LocInfo = CCValAssign::FPExt;\n"; 305 } else { 306 O << IndentStr << "if (ArgFlags.isSExt())\n" 307 << IndentStr << " LocInfo = CCValAssign::SExt;\n" 308 << IndentStr << "else if (ArgFlags.isZExt())\n" 309 << IndentStr << " LocInfo = CCValAssign::ZExt;\n" 310 << IndentStr << "else\n" 311 << IndentStr << " LocInfo = CCValAssign::AExt;\n"; 312 } 313 } else if (Action->isSubClassOf("CCPromoteToUpperBitsInType")) { 314 Record *DestTy = Action->getValueAsDef("DestTy"); 315 MVT::SimpleValueType DestVT = getValueType(DestTy); 316 O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n"; 317 if (MVT(DestVT).isFloatingPoint()) { 318 PrintFatalError(Action->getLoc(), 319 "CCPromoteToUpperBitsInType does not handle floating " 320 "point"); 321 } else { 322 O << IndentStr << "if (ArgFlags.isSExt())\n" 323 << IndentStr << " LocInfo = CCValAssign::SExtUpper;\n" 324 << IndentStr << "else if (ArgFlags.isZExt())\n" 325 << IndentStr << " LocInfo = CCValAssign::ZExtUpper;\n" 326 << IndentStr << "else\n" 327 << IndentStr << " LocInfo = CCValAssign::AExtUpper;\n"; 328 } 329 } else if (Action->isSubClassOf("CCBitConvertToType")) { 330 Record *DestTy = Action->getValueAsDef("DestTy"); 331 O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) 332 << ";\n"; 333 O << IndentStr << "LocInfo = CCValAssign::BCvt;\n"; 334 } else if (Action->isSubClassOf("CCTruncToType")) { 335 Record *DestTy = Action->getValueAsDef("DestTy"); 336 O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) 337 << ";\n"; 338 O << IndentStr << "LocInfo = CCValAssign::Trunc;\n"; 339 } else if (Action->isSubClassOf("CCPassIndirect")) { 340 Record *DestTy = Action->getValueAsDef("DestTy"); 341 O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) 342 << ";\n"; 343 O << IndentStr << "LocInfo = CCValAssign::Indirect;\n"; 344 } else if (Action->isSubClassOf("CCPassByVal")) { 345 int Size = Action->getValueAsInt("Size"); 346 int Align = Action->getValueAsInt("Align"); 347 O << IndentStr << "State.HandleByVal(ValNo, ValVT, LocVT, LocInfo, " 348 << Size << ", Align(" << Align << "), ArgFlags);\n"; 349 O << IndentStr << "return false;\n"; 350 } else if (Action->isSubClassOf("CCCustom")) { 351 O << IndentStr << "if (" << Action->getValueAsString("FuncName") 352 << "(ValNo, ValVT, " 353 << "LocVT, LocInfo, ArgFlags, State))\n"; 354 O << IndentStr << " return false;\n"; 355 } else { 356 errs() << *Action; 357 PrintFatalError(Action->getLoc(), "Unknown CCAction!"); 358 } 359 } 360 } 361 362 void CallingConvEmitter::EmitArgRegisterLists(raw_ostream &O) { 363 // Transitively merge all delegated CCs into AssignedRegsMap. 364 using EntryTy = std::pair<std::string, std::set<std::string>>; 365 bool Redo; 366 do { 367 Redo = false; 368 std::deque<EntryTy> Worklist(DelegateToMap.begin(), DelegateToMap.end()); 369 370 while (!Worklist.empty()) { 371 EntryTy Entry = Worklist.front(); 372 Worklist.pop_front(); 373 374 const std::string &CCName = Entry.first; 375 std::set<std::string> &Registers = Entry.second; 376 if (!Registers.empty()) 377 continue; 378 379 for (auto &InnerEntry : Worklist) { 380 const std::string &InnerCCName = InnerEntry.first; 381 std::set<std::string> &InnerRegisters = InnerEntry.second; 382 383 if (InnerRegisters.find(CCName) != InnerRegisters.end()) { 384 AssignedRegsMap[InnerCCName].insert(AssignedRegsMap[CCName].begin(), 385 AssignedRegsMap[CCName].end()); 386 InnerRegisters.erase(CCName); 387 } 388 } 389 390 DelegateToMap.erase(CCName); 391 Redo = true; 392 } 393 } while (Redo); 394 395 if (AssignedRegsMap.empty()) 396 return; 397 398 O << "\n#else\n\n"; 399 400 for (auto &Entry : AssignedRegsMap) { 401 const std::string &RegName = Entry.first; 402 std::set<std::string> &Registers = Entry.second; 403 404 if (RegName.empty()) 405 continue; 406 407 O << "const MCRegister " << Entry.first << "_ArgRegs[] = { "; 408 409 if (Registers.empty()) { 410 O << "0"; 411 } else { 412 ListSeparator LS; 413 for (const std::string &Reg : Registers) 414 O << LS << Reg; 415 } 416 417 O << " };\n"; 418 } 419 420 if (AssignedSwiftRegsMap.empty()) 421 return; 422 423 O << "\n// Registers used by Swift.\n"; 424 for (auto &Entry : AssignedSwiftRegsMap) { 425 const std::string &RegName = Entry.first; 426 std::set<std::string> &Registers = Entry.second; 427 428 O << "const MCRegister " << RegName << "_Swift_ArgRegs[] = { "; 429 430 ListSeparator LS; 431 for (const std::string &Reg : Registers) 432 O << LS << Reg; 433 434 O << " };\n"; 435 } 436 } 437 438 static TableGen::Emitter::OptClass<CallingConvEmitter> 439 X("gen-callingconv", "Generate calling convention descriptions"); 440