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