Path: blob/main/contrib/llvm-project/llvm/utils/TableGen/CallingConvEmitter.cpp
35258 views
//===- CallingConvEmitter.cpp - Generate calling conventions --------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This tablegen backend is responsible for emitting descriptions of the calling9// conventions supported by this target.10//11//===----------------------------------------------------------------------===//1213#include "Common/CodeGenTarget.h"14#include "llvm/TableGen/Error.h"15#include "llvm/TableGen/Record.h"16#include "llvm/TableGen/TableGenBackend.h"17#include <deque>18#include <set>1920using namespace llvm;2122namespace {23class CallingConvEmitter {24RecordKeeper &Records;25unsigned Counter = 0u;26std::string CurrentAction;27bool SwiftAction = false;2829std::map<std::string, std::set<std::string>> AssignedRegsMap;30std::map<std::string, std::set<std::string>> AssignedSwiftRegsMap;31std::map<std::string, std::set<std::string>> DelegateToMap;3233public:34explicit CallingConvEmitter(RecordKeeper &R) : Records(R) {}3536void run(raw_ostream &o);3738private:39void EmitCallingConv(Record *CC, raw_ostream &O);40void EmitAction(Record *Action, unsigned Indent, raw_ostream &O);41void EmitArgRegisterLists(raw_ostream &O);42};43} // End anonymous namespace4445void CallingConvEmitter::run(raw_ostream &O) {46emitSourceFileHeader("Calling Convention Implementation Fragment", O);4748std::vector<Record *> CCs = Records.getAllDerivedDefinitions("CallingConv");4950// Emit prototypes for all of the non-custom CC's so that they can forward ref51// each other.52Records.startTimer("Emit prototypes");53O << "#ifndef GET_CC_REGISTER_LISTS\n\n";54for (Record *CC : CCs) {55if (!CC->getValueAsBit("Custom")) {56unsigned Pad = CC->getName().size();57if (CC->getValueAsBit("Entry")) {58O << "bool llvm::";59Pad += 12;60} else {61O << "static bool ";62Pad += 13;63}64O << 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}7071// Emit each non-custom calling convention description in full.72Records.startTimer("Emit full descriptions");73for (Record *CC : CCs) {74if (!CC->getValueAsBit("Custom")) {75EmitCallingConv(CC, O);76}77}7879EmitArgRegisterLists(O);8081O << "\n#endif // CC_REGISTER_LIST\n";82}8384void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) {85ListInit *CCActions = CC->getValueAsListInit("Actions");86Counter = 0;8788CurrentAction = 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 that91// entry is empty.92AssignedRegsMap[CurrentAction] = {};9394O << "\n\n";95unsigned Pad = CurrentAction.size();96if (CC->getValueAsBit("Entry")) {97O << "bool llvm::";98Pad += 12;99} else {100O << "static bool ";101Pad += 13;102}103O << 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.107for (unsigned i = 0, e = CCActions->size(); i != e; ++i) {108Record *Action = CCActions->getElementAsRecord(i);109SwiftAction =110llvm::any_of(Action->getSuperClasses(),111[](const std::pair<Record *, SMRange> &Class) {112std::string Name = Class.first->getNameInitAsString();113return StringRef(Name).starts_with("CCIfSwift");114});115116O << "\n";117EmitAction(Action, 2, O);118}119120O << "\n return true; // CC didn't match.\n";121O << "}\n";122}123124void CallingConvEmitter::EmitAction(Record *Action, unsigned Indent,125raw_ostream &O) {126std::string IndentStr = std::string(Indent, ' ');127128if (Action->isSubClassOf("CCPredicateAction")) {129O << IndentStr << "if (";130131if (Action->isSubClassOf("CCIfType")) {132ListInit *VTs = Action->getValueAsListInit("VTs");133for (unsigned i = 0, e = VTs->size(); i != e; ++i) {134Record *VT = VTs->getElementAsRecord(i);135if (i != 0)136O << " ||\n " << IndentStr;137O << "LocVT == " << getEnumName(getValueType(VT));138}139140} else if (Action->isSubClassOf("CCIf")) {141O << Action->getValueAsString("Predicate");142} else {143errs() << *Action;144PrintFatalError(Action->getLoc(), "Unknown CCPredicateAction!");145}146147O << ") {\n";148EmitAction(Action->getValueAsDef("SubAction"), Indent + 2, O);149O << IndentStr << "}\n";150} else {151if (Action->isSubClassOf("CCDelegateTo")) {152Record *CC = Action->getValueAsDef("CC");153O << IndentStr << "if (!" << CC->getName()154<< "(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))\n"155<< IndentStr << " return false;\n";156DelegateToMap[CurrentAction].insert(CC->getName().str());157} else if (Action->isSubClassOf("CCAssignToReg") ||158Action->isSubClassOf("CCAssignToRegAndStack")) {159ListInit *RegList = Action->getValueAsListInit("RegList");160if (RegList->size() == 1) {161std::string Name = getQualifiedName(RegList->getElementAsRecord(0));162O << IndentStr << "if (unsigned Reg = State.AllocateReg(" << Name163<< ")) {\n";164if (SwiftAction)165AssignedSwiftRegsMap[CurrentAction].insert(Name);166else167AssignedRegsMap[CurrentAction].insert(Name);168} else {169O << IndentStr << "static const MCPhysReg RegList" << ++Counter170<< "[] = {\n";171O << IndentStr << " ";172ListSeparator LS;173for (unsigned i = 0, e = RegList->size(); i != e; ++i) {174std::string Name = getQualifiedName(RegList->getElementAsRecord(i));175if (SwiftAction)176AssignedSwiftRegsMap[CurrentAction].insert(Name);177else178AssignedRegsMap[CurrentAction].insert(Name);179O << LS << Name;180}181O << "\n" << IndentStr << "};\n";182O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"183<< Counter << ")) {\n";184}185O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, "186<< "Reg, LocVT, LocInfo));\n";187if (Action->isSubClassOf("CCAssignToRegAndStack")) {188int Size = Action->getValueAsInt("Size");189int Align = Action->getValueAsInt("Align");190O << IndentStr << " (void)State.AllocateStack(";191if (Size)192O << Size << ", ";193else194O << "\n"195<< IndentStr196<< " State.getMachineFunction().getDataLayout()."197"getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())),"198" ";199if (Align)200O << "Align(" << Align << ")";201else202O << "\n"203<< IndentStr204<< " State.getMachineFunction().getDataLayout()."205"getABITypeAlign(EVT(LocVT).getTypeForEVT(State.getContext()"206"))";207O << ");\n";208}209O << IndentStr << " return false;\n";210O << IndentStr << "}\n";211} else if (Action->isSubClassOf("CCAssignToRegWithShadow")) {212ListInit *RegList = Action->getValueAsListInit("RegList");213ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");214if (!ShadowRegList->empty() && ShadowRegList->size() != RegList->size())215PrintFatalError(Action->getLoc(),216"Invalid length of list of shadowed registers");217218if (RegList->size() == 1) {219O << IndentStr << "if (unsigned Reg = State.AllocateReg(";220O << getQualifiedName(RegList->getElementAsRecord(0));221O << ", " << getQualifiedName(ShadowRegList->getElementAsRecord(0));222O << ")) {\n";223} else {224unsigned RegListNumber = ++Counter;225unsigned ShadowRegListNumber = ++Counter;226227O << IndentStr << "static const MCPhysReg RegList" << RegListNumber228<< "[] = {\n";229O << IndentStr << " ";230ListSeparator LS;231for (unsigned i = 0, e = RegList->size(); i != e; ++i)232O << LS << getQualifiedName(RegList->getElementAsRecord(i));233O << "\n" << IndentStr << "};\n";234235O << IndentStr << "static const MCPhysReg RegList"236<< ShadowRegListNumber << "[] = {\n";237O << IndentStr << " ";238ListSeparator LSS;239for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i)240O << LSS << getQualifiedName(ShadowRegList->getElementAsRecord(i));241O << "\n" << IndentStr << "};\n";242243O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"244<< RegListNumber << ", "245<< "RegList" << ShadowRegListNumber << ")) {\n";246}247O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, "248<< "Reg, LocVT, LocInfo));\n";249O << IndentStr << " return false;\n";250O << IndentStr << "}\n";251} else if (Action->isSubClassOf("CCAssignToStack")) {252int Size = Action->getValueAsInt("Size");253int Align = Action->getValueAsInt("Align");254255O << IndentStr << "int64_t Offset" << ++Counter256<< " = State.AllocateStack(";257if (Size)258O << Size << ", ";259else260O << "\n"261<< IndentStr262<< " State.getMachineFunction().getDataLayout()."263"getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())),"264" ";265if (Align)266O << "Align(" << Align << ")";267else268O << "\n"269<< IndentStr270<< " State.getMachineFunction().getDataLayout()."271"getABITypeAlign(EVT(LocVT).getTypeForEVT(State.getContext()"272"))";273O << ");\n"274<< IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"275<< Counter << ", LocVT, LocInfo));\n";276O << IndentStr << "return false;\n";277} else if (Action->isSubClassOf("CCAssignToStackWithShadow")) {278int Size = Action->getValueAsInt("Size");279int Align = Action->getValueAsInt("Align");280ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");281282unsigned ShadowRegListNumber = ++Counter;283284O << IndentStr << "static const MCPhysReg ShadowRegList"285<< ShadowRegListNumber << "[] = {\n";286O << IndentStr << " ";287ListSeparator LS;288for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i)289O << LS << getQualifiedName(ShadowRegList->getElementAsRecord(i));290O << "\n" << IndentStr << "};\n";291292O << IndentStr << "int64_t Offset" << ++Counter293<< " = State.AllocateStack(" << Size << ", Align(" << Align << "), "294<< "ShadowRegList" << ShadowRegListNumber << ");\n";295O << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"296<< Counter << ", LocVT, LocInfo));\n";297O << IndentStr << "return false;\n";298} else if (Action->isSubClassOf("CCPromoteToType")) {299Record *DestTy = Action->getValueAsDef("DestTy");300MVT::SimpleValueType DestVT = getValueType(DestTy);301O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n";302if (MVT(DestVT).isFloatingPoint()) {303O << IndentStr << "LocInfo = CCValAssign::FPExt;\n";304} else {305O << IndentStr << "if (ArgFlags.isSExt())\n"306<< IndentStr << " LocInfo = CCValAssign::SExt;\n"307<< IndentStr << "else if (ArgFlags.isZExt())\n"308<< IndentStr << " LocInfo = CCValAssign::ZExt;\n"309<< IndentStr << "else\n"310<< IndentStr << " LocInfo = CCValAssign::AExt;\n";311}312} else if (Action->isSubClassOf("CCPromoteToUpperBitsInType")) {313Record *DestTy = Action->getValueAsDef("DestTy");314MVT::SimpleValueType DestVT = getValueType(DestTy);315O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n";316if (MVT(DestVT).isFloatingPoint()) {317PrintFatalError(Action->getLoc(),318"CCPromoteToUpperBitsInType does not handle floating "319"point");320} else {321O << IndentStr << "if (ArgFlags.isSExt())\n"322<< IndentStr << " LocInfo = CCValAssign::SExtUpper;\n"323<< IndentStr << "else if (ArgFlags.isZExt())\n"324<< IndentStr << " LocInfo = CCValAssign::ZExtUpper;\n"325<< IndentStr << "else\n"326<< IndentStr << " LocInfo = CCValAssign::AExtUpper;\n";327}328} else if (Action->isSubClassOf("CCBitConvertToType")) {329Record *DestTy = Action->getValueAsDef("DestTy");330O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy))331<< ";\n";332O << IndentStr << "LocInfo = CCValAssign::BCvt;\n";333} else if (Action->isSubClassOf("CCTruncToType")) {334Record *DestTy = Action->getValueAsDef("DestTy");335O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy))336<< ";\n";337O << IndentStr << "LocInfo = CCValAssign::Trunc;\n";338} else if (Action->isSubClassOf("CCPassIndirect")) {339Record *DestTy = Action->getValueAsDef("DestTy");340O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy))341<< ";\n";342O << IndentStr << "LocInfo = CCValAssign::Indirect;\n";343} else if (Action->isSubClassOf("CCPassByVal")) {344int Size = Action->getValueAsInt("Size");345int Align = Action->getValueAsInt("Align");346O << IndentStr << "State.HandleByVal(ValNo, ValVT, LocVT, LocInfo, "347<< Size << ", Align(" << Align << "), ArgFlags);\n";348O << IndentStr << "return false;\n";349} else if (Action->isSubClassOf("CCCustom")) {350O << IndentStr << "if (" << Action->getValueAsString("FuncName")351<< "(ValNo, ValVT, "352<< "LocVT, LocInfo, ArgFlags, State))\n";353O << IndentStr << " return false;\n";354} else {355errs() << *Action;356PrintFatalError(Action->getLoc(), "Unknown CCAction!");357}358}359}360361void CallingConvEmitter::EmitArgRegisterLists(raw_ostream &O) {362// Transitively merge all delegated CCs into AssignedRegsMap.363using EntryTy = std::pair<std::string, std::set<std::string>>;364bool Redo;365do {366Redo = false;367std::deque<EntryTy> Worklist(DelegateToMap.begin(), DelegateToMap.end());368369while (!Worklist.empty()) {370EntryTy Entry = Worklist.front();371Worklist.pop_front();372373const std::string &CCName = Entry.first;374std::set<std::string> &Registers = Entry.second;375if (!Registers.empty())376continue;377378for (auto &InnerEntry : Worklist) {379const std::string &InnerCCName = InnerEntry.first;380std::set<std::string> &InnerRegisters = InnerEntry.second;381382if (InnerRegisters.find(CCName) != InnerRegisters.end()) {383AssignedRegsMap[InnerCCName].insert(AssignedRegsMap[CCName].begin(),384AssignedRegsMap[CCName].end());385InnerRegisters.erase(CCName);386}387}388389DelegateToMap.erase(CCName);390Redo = true;391}392} while (Redo);393394if (AssignedRegsMap.empty())395return;396397O << "\n#else\n\n";398399for (auto &Entry : AssignedRegsMap) {400const std::string &RegName = Entry.first;401std::set<std::string> &Registers = Entry.second;402403if (RegName.empty())404continue;405406O << "const MCRegister " << Entry.first << "_ArgRegs[] = { ";407408if (Registers.empty()) {409O << "0";410} else {411ListSeparator LS;412for (const std::string &Reg : Registers)413O << LS << Reg;414}415416O << " };\n";417}418419if (AssignedSwiftRegsMap.empty())420return;421422O << "\n// Registers used by Swift.\n";423for (auto &Entry : AssignedSwiftRegsMap) {424const std::string &RegName = Entry.first;425std::set<std::string> &Registers = Entry.second;426427O << "const MCRegister " << RegName << "_Swift_ArgRegs[] = { ";428429ListSeparator LS;430for (const std::string &Reg : Registers)431O << LS << Reg;432433O << " };\n";434}435}436437static TableGen::Emitter::OptClass<CallingConvEmitter>438X("gen-callingconv", "Generate calling convention descriptions");439440441