#include "X86CallingConv.h"
#include "X86Subtarget.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/IR/CallingConv.h"
using namespace llvm;
static bool CC_X86_32_RegCall_Assign2Regs(unsigned &ValNo, MVT &ValVT,
MVT &LocVT,
CCValAssign::LocInfo &LocInfo,
ISD::ArgFlagsTy &ArgFlags,
CCState &State) {
static const MCPhysReg RegList[] = {X86::EAX, X86::ECX, X86::EDX, X86::EDI,
X86::ESI};
SmallVector<unsigned, 5> AvailableRegs;
for (auto Reg : RegList) {
if (!State.isAllocated(Reg))
AvailableRegs.push_back(Reg);
}
const size_t RequiredGprsUponSplit = 2;
if (AvailableRegs.size() < RequiredGprsUponSplit)
return false;
for (unsigned I = 0; I < RequiredGprsUponSplit; I++) {
unsigned Reg = State.AllocateReg(AvailableRegs[I]);
assert(Reg && "Expecting a register will be available");
State.addLoc(CCValAssign::getCustomReg(ValNo, ValVT, Reg, LocVT, LocInfo));
}
return true;
}
static ArrayRef<MCPhysReg> CC_X86_VectorCallGetSSEs(const MVT &ValVT) {
if (ValVT.is512BitVector()) {
static const MCPhysReg RegListZMM[] = {X86::ZMM0, X86::ZMM1, X86::ZMM2,
X86::ZMM3, X86::ZMM4, X86::ZMM5};
return makeArrayRef(std::begin(RegListZMM), std::end(RegListZMM));
}
if (ValVT.is256BitVector()) {
static const MCPhysReg RegListYMM[] = {X86::YMM0, X86::YMM1, X86::YMM2,
X86::YMM3, X86::YMM4, X86::YMM5};
return makeArrayRef(std::begin(RegListYMM), std::end(RegListYMM));
}
static const MCPhysReg RegListXMM[] = {X86::XMM0, X86::XMM1, X86::XMM2,
X86::XMM3, X86::XMM4, X86::XMM5};
return makeArrayRef(std::begin(RegListXMM), std::end(RegListXMM));
}
static ArrayRef<MCPhysReg> CC_X86_64_VectorCallGetGPRs() {
static const MCPhysReg RegListGPR[] = {X86::RCX, X86::RDX, X86::R8, X86::R9};
return makeArrayRef(std::begin(RegListGPR), std::end(RegListGPR));
}
static bool CC_X86_VectorCallAssignRegister(unsigned &ValNo, MVT &ValVT,
MVT &LocVT,
CCValAssign::LocInfo &LocInfo,
ISD::ArgFlagsTy &ArgFlags,
CCState &State) {
ArrayRef<MCPhysReg> RegList = CC_X86_VectorCallGetSSEs(ValVT);
bool Is64bit = static_cast<const X86Subtarget &>(
State.getMachineFunction().getSubtarget())
.is64Bit();
for (auto Reg : RegList) {
if (!State.isAllocated(Reg)) {
unsigned AssigedReg = State.AllocateReg(Reg);
assert(AssigedReg == Reg && "Expecting a valid register allocation");
State.addLoc(
CCValAssign::getReg(ValNo, ValVT, AssigedReg, LocVT, LocInfo));
return true;
}
if (Is64bit && State.IsShadowAllocatedReg(Reg)) {
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
return true;
}
}
llvm_unreachable("Clang should ensure that hva marked vectors will have "
"an available register.");
return false;
}
static bool CC_X86_64_VectorCall(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
CCValAssign::LocInfo &LocInfo,
ISD::ArgFlagsTy &ArgFlags, CCState &State) {
if (ArgFlags.isSecArgPass()) {
if (ArgFlags.isHva())
return CC_X86_VectorCallAssignRegister(ValNo, ValVT, LocVT, LocInfo,
ArgFlags, State);
return true;
}
if (!(ValVT.isFloatingPoint() ||
(ValVT.isVector() && ValVT.getSizeInBits() >= 128))) {
if (State.isAllocated(X86::R9)) {
(void)State.AllocateReg(CC_X86_VectorCallGetSSEs(ValVT));
}
return false;
}
if (!ArgFlags.isHva() || ArgFlags.isHvaStart()) {
(void)State.AllocateReg(CC_X86_64_VectorCallGetGPRs());
if (unsigned Reg = State.AllocateReg(CC_X86_VectorCallGetSSEs(ValVT))) {
const TargetRegisterInfo *TRI =
State.getMachineFunction().getSubtarget().getRegisterInfo();
if (TRI->regsOverlap(Reg, X86::XMM4) ||
TRI->regsOverlap(Reg, X86::XMM5))
State.AllocateStack(8, Align(8));
if (!ArgFlags.isHva()) {
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
return true; }
}
}
return ArgFlags.isHva();
}
static bool CC_X86_32_VectorCall(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
CCValAssign::LocInfo &LocInfo,
ISD::ArgFlagsTy &ArgFlags, CCState &State) {
if (ArgFlags.isSecArgPass()) {
if (ArgFlags.isHva())
return CC_X86_VectorCallAssignRegister(ValNo, ValVT, LocVT, LocInfo,
ArgFlags, State);
return true;
}
if (!(ValVT.isFloatingPoint() ||
(ValVT.isVector() && ValVT.getSizeInBits() >= 128))) {
return false;
}
if (ArgFlags.isHva())
return true;
if (unsigned Reg = State.AllocateReg(CC_X86_VectorCallGetSSEs(ValVT))) {
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
return true;
}
if (!ValVT.isFloatingPoint()) {
LocVT = MVT::i32;
LocInfo = CCValAssign::Indirect;
ArgFlags.setInReg();
}
return false; }
static bool CC_X86_AnyReg_Error(unsigned &, MVT &, MVT &,
CCValAssign::LocInfo &, ISD::ArgFlagsTy &,
CCState &) {
llvm_unreachable("The AnyReg calling convention is only supported by the "
"stackmap and patchpoint intrinsics.");
return false;
}
static bool CC_X86_32_MCUInReg(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
CCValAssign::LocInfo &LocInfo,
ISD::ArgFlagsTy &ArgFlags, CCState &State) {
static const MCPhysReg RegList[] = {X86::EAX, X86::EDX, X86::ECX};
static const unsigned NumRegs = sizeof(RegList) / sizeof(RegList[0]);
SmallVectorImpl<CCValAssign> &PendingMembers = State.getPendingLocs();
if (ArgFlags.isSplit() || !PendingMembers.empty()) {
PendingMembers.push_back(
CCValAssign::getPending(ValNo, ValVT, LocVT, LocInfo));
if (!ArgFlags.isSplitEnd())
return true;
}
if (PendingMembers.empty()) {
if (unsigned Reg = State.AllocateReg(RegList)) {
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
return true;
}
return false;
}
assert(ArgFlags.isSplitEnd());
unsigned FirstFree = State.getFirstUnallocated(RegList);
bool UseRegs = PendingMembers.size() <= std::min(2U, NumRegs - FirstFree);
for (auto &It : PendingMembers) {
if (UseRegs)
It.convertToReg(State.AllocateReg(RegList[FirstFree++]));
else
It.convertToMem(State.AllocateStack(4, Align(4)));
State.addLoc(It);
}
PendingMembers.clear();
return true;
}
static bool CC_X86_Intr(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
CCValAssign::LocInfo &LocInfo,
ISD::ArgFlagsTy &ArgFlags, CCState &State) {
const MachineFunction &MF = State.getMachineFunction();
size_t ArgCount = State.getMachineFunction().getFunction().arg_size();
bool Is64Bit = MF.getSubtarget<X86Subtarget>().is64Bit();
unsigned SlotSize = Is64Bit ? 8 : 4;
unsigned Offset;
if (ArgCount == 1 && ValNo == 0) {
Offset = State.AllocateStack(5 * SlotSize, Align(4));
} else if (ArgCount == 2 && ValNo == 0) {
Offset = SlotSize;
} else if (ArgCount == 2 && ValNo == 1) {
Offset = 0;
(void)State.AllocateStack(6 * SlotSize, Align(4));
} else {
report_fatal_error("unsupported x86 interrupt prototype");
}
if (Is64Bit && ArgCount == 2)
Offset += SlotSize;
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
return true;
}
static bool CC_X86_64_Pointer(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
CCValAssign::LocInfo &LocInfo,
ISD::ArgFlagsTy &ArgFlags, CCState &State) {
if (LocVT != MVT::i64) {
LocVT = MVT::i64;
LocInfo = CCValAssign::ZExt;
}
return false;
}
#include "X86GenCallingConv.inc"