Path: blob/main/contrib/llvm-project/llvm/lib/CodeGen/CallingConvLower.cpp
35233 views
//===-- CallingConvLower.cpp - 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 file implements the CCState class, used for lowering and implementing9// calling conventions.10//11//===----------------------------------------------------------------------===//1213#include "llvm/CodeGen/CallingConvLower.h"14#include "llvm/CodeGen/MachineFrameInfo.h"15#include "llvm/CodeGen/MachineFunction.h"16#include "llvm/CodeGen/TargetLowering.h"17#include "llvm/CodeGen/TargetRegisterInfo.h"18#include "llvm/CodeGen/TargetSubtargetInfo.h"19#include "llvm/MC/MCRegisterInfo.h"20#include "llvm/Support/Debug.h"21#include "llvm/Support/ErrorHandling.h"22#include "llvm/Support/SaveAndRestore.h"23#include "llvm/Support/raw_ostream.h"2425using namespace llvm;2627CCState::CCState(CallingConv::ID CC, bool IsVarArg, MachineFunction &MF,28SmallVectorImpl<CCValAssign> &Locs, LLVMContext &Context,29bool NegativeOffsets)30: CallingConv(CC), IsVarArg(IsVarArg), MF(MF),31TRI(*MF.getSubtarget().getRegisterInfo()), Locs(Locs), Context(Context),32NegativeOffsets(NegativeOffsets) {3334// No stack is used.35StackSize = 0;3637clearByValRegsInfo();38UsedRegs.resize((TRI.getNumRegs()+31)/32);39}4041/// Allocate space on the stack large enough to pass an argument by value.42/// The size and alignment information of the argument is encoded in43/// its parameter attribute.44void CCState::HandleByVal(unsigned ValNo, MVT ValVT, MVT LocVT,45CCValAssign::LocInfo LocInfo, int MinSize,46Align MinAlign, ISD::ArgFlagsTy ArgFlags) {47Align Alignment = ArgFlags.getNonZeroByValAlign();48unsigned Size = ArgFlags.getByValSize();49if (MinSize > (int)Size)50Size = MinSize;51if (MinAlign > Alignment)52Alignment = MinAlign;53ensureMaxAlignment(Alignment);54MF.getSubtarget().getTargetLowering()->HandleByVal(this, Size, Alignment);55Size = unsigned(alignTo(Size, MinAlign));56uint64_t Offset = AllocateStack(Size, Alignment);57addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));58}5960/// Mark a register and all of its aliases as allocated.61void CCState::MarkAllocated(MCPhysReg Reg) {62for (MCRegAliasIterator AI(Reg, &TRI, true); AI.isValid(); ++AI)63UsedRegs[*AI / 32] |= 1 << (*AI & 31);64}6566void CCState::MarkUnallocated(MCPhysReg Reg) {67for (MCRegAliasIterator AI(Reg, &TRI, true); AI.isValid(); ++AI)68UsedRegs[*AI / 32] &= ~(1 << (*AI & 31));69}7071bool CCState::IsShadowAllocatedReg(MCRegister Reg) const {72if (!isAllocated(Reg))73return false;7475for (auto const &ValAssign : Locs)76if (ValAssign.isRegLoc() && TRI.regsOverlap(ValAssign.getLocReg(), Reg))77return false;78return true;79}8081/// Analyze an array of argument values,82/// incorporating info about the formals into this state.83void84CCState::AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,85CCAssignFn Fn) {86unsigned NumArgs = Ins.size();8788for (unsigned i = 0; i != NumArgs; ++i) {89MVT ArgVT = Ins[i].VT;90ISD::ArgFlagsTy ArgFlags = Ins[i].Flags;91if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this))92report_fatal_error("unable to allocate function argument #" + Twine(i));93}94}9596/// Analyze the return values of a function, returning true if the return can97/// be performed without sret-demotion and false otherwise.98bool CCState::CheckReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,99CCAssignFn Fn) {100// Determine which register each value should be copied into.101for (unsigned i = 0, e = Outs.size(); i != e; ++i) {102MVT VT = Outs[i].VT;103ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;104if (Fn(i, VT, VT, CCValAssign::Full, ArgFlags, *this))105return false;106}107return true;108}109110/// Analyze the returned values of a return,111/// incorporating info about the result values into this state.112void CCState::AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,113CCAssignFn Fn) {114// Determine which register each value should be copied into.115for (unsigned i = 0, e = Outs.size(); i != e; ++i) {116MVT VT = Outs[i].VT;117ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;118if (Fn(i, VT, VT, CCValAssign::Full, ArgFlags, *this))119report_fatal_error("unable to allocate function return #" + Twine(i));120}121}122123/// Analyze the outgoing arguments to a call,124/// incorporating info about the passed values into this state.125void CCState::AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs,126CCAssignFn Fn) {127unsigned NumOps = Outs.size();128for (unsigned i = 0; i != NumOps; ++i) {129MVT ArgVT = Outs[i].VT;130ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;131if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this)) {132#ifndef NDEBUG133dbgs() << "Call operand #" << i << " has unhandled type "134<< ArgVT << '\n';135#endif136llvm_unreachable(nullptr);137}138}139}140141/// Same as above except it takes vectors of types and argument flags.142void CCState::AnalyzeCallOperands(SmallVectorImpl<MVT> &ArgVTs,143SmallVectorImpl<ISD::ArgFlagsTy> &Flags,144CCAssignFn Fn) {145unsigned NumOps = ArgVTs.size();146for (unsigned i = 0; i != NumOps; ++i) {147MVT ArgVT = ArgVTs[i];148ISD::ArgFlagsTy ArgFlags = Flags[i];149if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this)) {150#ifndef NDEBUG151dbgs() << "Call operand #" << i << " has unhandled type "152<< ArgVT << '\n';153#endif154llvm_unreachable(nullptr);155}156}157}158159/// Analyze the return values of a call, incorporating info about the passed160/// values into this state.161void CCState::AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins,162CCAssignFn Fn) {163for (unsigned i = 0, e = Ins.size(); i != e; ++i) {164MVT VT = Ins[i].VT;165ISD::ArgFlagsTy Flags = Ins[i].Flags;166if (Fn(i, VT, VT, CCValAssign::Full, Flags, *this)) {167#ifndef NDEBUG168dbgs() << "Call result #" << i << " has unhandled type "169<< VT << '\n';170#endif171llvm_unreachable(nullptr);172}173}174}175176/// Same as above except it's specialized for calls that produce a single value.177void CCState::AnalyzeCallResult(MVT VT, CCAssignFn Fn) {178if (Fn(0, VT, VT, CCValAssign::Full, ISD::ArgFlagsTy(), *this)) {179#ifndef NDEBUG180dbgs() << "Call result has unhandled type "181<< VT << '\n';182#endif183llvm_unreachable(nullptr);184}185}186187void CCState::ensureMaxAlignment(Align Alignment) {188if (!AnalyzingMustTailForwardedRegs)189MF.getFrameInfo().ensureMaxAlignment(Alignment);190}191192static bool isValueTypeInRegForCC(CallingConv::ID CC, MVT VT) {193if (VT.isVector())194return true; // Assume -msse-regparm might be in effect.195if (!VT.isInteger())196return false;197return (CC == CallingConv::X86_VectorCall || CC == CallingConv::X86_FastCall);198}199200void CCState::getRemainingRegParmsForType(SmallVectorImpl<MCPhysReg> &Regs,201MVT VT, CCAssignFn Fn) {202uint64_t SavedStackSize = StackSize;203Align SavedMaxStackArgAlign = MaxStackArgAlign;204unsigned NumLocs = Locs.size();205206// Set the 'inreg' flag if it is used for this calling convention.207ISD::ArgFlagsTy Flags;208if (isValueTypeInRegForCC(CallingConv, VT))209Flags.setInReg();210211// Allocate something of this value type repeatedly until we get assigned a212// location in memory.213bool HaveRegParm;214do {215if (Fn(0, VT, VT, CCValAssign::Full, Flags, *this)) {216#ifndef NDEBUG217dbgs() << "Call has unhandled type " << VT218<< " while computing remaining regparms\n";219#endif220llvm_unreachable(nullptr);221}222HaveRegParm = Locs.back().isRegLoc();223} while (HaveRegParm);224225// Copy all the registers from the value locations we added.226assert(NumLocs < Locs.size() && "CC assignment failed to add location");227for (unsigned I = NumLocs, E = Locs.size(); I != E; ++I)228if (Locs[I].isRegLoc())229Regs.push_back(MCPhysReg(Locs[I].getLocReg()));230231// Clear the assigned values and stack memory. We leave the registers marked232// as allocated so that future queries don't return the same registers, i.e.233// when i64 and f64 are both passed in GPRs.234StackSize = SavedStackSize;235MaxStackArgAlign = SavedMaxStackArgAlign;236Locs.truncate(NumLocs);237}238239void CCState::analyzeMustTailForwardedRegisters(240SmallVectorImpl<ForwardedRegister> &Forwards, ArrayRef<MVT> RegParmTypes,241CCAssignFn Fn) {242// Oftentimes calling conventions will not user register parameters for243// variadic functions, so we need to assume we're not variadic so that we get244// all the registers that might be used in a non-variadic call.245SaveAndRestore SavedVarArg(IsVarArg, false);246SaveAndRestore SavedMustTail(AnalyzingMustTailForwardedRegs, true);247248for (MVT RegVT : RegParmTypes) {249SmallVector<MCPhysReg, 8> RemainingRegs;250getRemainingRegParmsForType(RemainingRegs, RegVT, Fn);251const TargetLowering *TL = MF.getSubtarget().getTargetLowering();252const TargetRegisterClass *RC = TL->getRegClassFor(RegVT);253for (MCPhysReg PReg : RemainingRegs) {254Register VReg = MF.addLiveIn(PReg, RC);255Forwards.push_back(ForwardedRegister(VReg, PReg, RegVT));256}257}258}259260bool CCState::resultsCompatible(CallingConv::ID CalleeCC,261CallingConv::ID CallerCC, MachineFunction &MF,262LLVMContext &C,263const SmallVectorImpl<ISD::InputArg> &Ins,264CCAssignFn CalleeFn, CCAssignFn CallerFn) {265if (CalleeCC == CallerCC)266return true;267SmallVector<CCValAssign, 4> RVLocs1;268CCState CCInfo1(CalleeCC, false, MF, RVLocs1, C);269CCInfo1.AnalyzeCallResult(Ins, CalleeFn);270271SmallVector<CCValAssign, 4> RVLocs2;272CCState CCInfo2(CallerCC, false, MF, RVLocs2, C);273CCInfo2.AnalyzeCallResult(Ins, CallerFn);274275auto AreCompatible = [](const CCValAssign &Loc1, const CCValAssign &Loc2) {276assert(!Loc1.isPendingLoc() && !Loc2.isPendingLoc() &&277"The location must have been decided by now");278// Must fill the same part of their locations.279if (Loc1.getLocInfo() != Loc2.getLocInfo())280return false;281// Must both be in the same registers, or both in memory at the same offset.282if (Loc1.isRegLoc() && Loc2.isRegLoc())283return Loc1.getLocReg() == Loc2.getLocReg();284if (Loc1.isMemLoc() && Loc2.isMemLoc())285return Loc1.getLocMemOffset() == Loc2.getLocMemOffset();286llvm_unreachable("Unknown location kind");287};288289return std::equal(RVLocs1.begin(), RVLocs1.end(), RVLocs2.begin(),290RVLocs2.end(), AreCompatible);291}292293294