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