xref: /aosp_15_r20/external/llvm/lib/Target/X86/X86CallingConv.h (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //=== X86CallingConv.h - X86 Custom Calling Convention Routines -*- C++ -*-===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file contains the custom routines for the X86 Calling Convention that
11*9880d681SAndroid Build Coastguard Worker // aren't done by tablegen.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker 
15*9880d681SAndroid Build Coastguard Worker #ifndef LLVM_LIB_TARGET_X86_X86CALLINGCONV_H
16*9880d681SAndroid Build Coastguard Worker #define LLVM_LIB_TARGET_X86_X86CALLINGCONV_H
17*9880d681SAndroid Build Coastguard Worker 
18*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/X86MCTargetDesc.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/CallingConvLower.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/CallingConv.h"
21*9880d681SAndroid Build Coastguard Worker 
22*9880d681SAndroid Build Coastguard Worker namespace llvm {
23*9880d681SAndroid Build Coastguard Worker 
CC_X86_32_VectorCallIndirect(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)24*9880d681SAndroid Build Coastguard Worker inline bool CC_X86_32_VectorCallIndirect(unsigned &ValNo, MVT &ValVT,
25*9880d681SAndroid Build Coastguard Worker                                          MVT &LocVT,
26*9880d681SAndroid Build Coastguard Worker                                          CCValAssign::LocInfo &LocInfo,
27*9880d681SAndroid Build Coastguard Worker                                          ISD::ArgFlagsTy &ArgFlags,
28*9880d681SAndroid Build Coastguard Worker                                          CCState &State) {
29*9880d681SAndroid Build Coastguard Worker   // Similar to CCPassIndirect, with the addition of inreg.
30*9880d681SAndroid Build Coastguard Worker   LocVT = MVT::i32;
31*9880d681SAndroid Build Coastguard Worker   LocInfo = CCValAssign::Indirect;
32*9880d681SAndroid Build Coastguard Worker   ArgFlags.setInReg();
33*9880d681SAndroid Build Coastguard Worker   return false; // Continue the search, but now for i32.
34*9880d681SAndroid Build Coastguard Worker }
35*9880d681SAndroid Build Coastguard Worker 
36*9880d681SAndroid Build Coastguard Worker 
CC_X86_AnyReg_Error(unsigned &,MVT &,MVT &,CCValAssign::LocInfo &,ISD::ArgFlagsTy &,CCState &)37*9880d681SAndroid Build Coastguard Worker inline bool CC_X86_AnyReg_Error(unsigned &, MVT &, MVT &,
38*9880d681SAndroid Build Coastguard Worker                                 CCValAssign::LocInfo &, ISD::ArgFlagsTy &,
39*9880d681SAndroid Build Coastguard Worker                                 CCState &) {
40*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("The AnyReg calling convention is only supported by the " \
41*9880d681SAndroid Build Coastguard Worker                    "stackmap and patchpoint intrinsics.");
42*9880d681SAndroid Build Coastguard Worker   // gracefully fallback to X86 C calling convention on Release builds.
43*9880d681SAndroid Build Coastguard Worker   return false;
44*9880d681SAndroid Build Coastguard Worker }
45*9880d681SAndroid Build Coastguard Worker 
CC_X86_32_MCUInReg(unsigned & ValNo,MVT & ValVT,MVT & LocVT,CCValAssign::LocInfo & LocInfo,ISD::ArgFlagsTy & ArgFlags,CCState & State)46*9880d681SAndroid Build Coastguard Worker inline bool CC_X86_32_MCUInReg(unsigned &ValNo, MVT &ValVT,
47*9880d681SAndroid Build Coastguard Worker                                          MVT &LocVT,
48*9880d681SAndroid Build Coastguard Worker                                          CCValAssign::LocInfo &LocInfo,
49*9880d681SAndroid Build Coastguard Worker                                          ISD::ArgFlagsTy &ArgFlags,
50*9880d681SAndroid Build Coastguard Worker                                          CCState &State) {
51*9880d681SAndroid Build Coastguard Worker   // This is similar to CCAssignToReg<[EAX, EDX, ECX]>, but makes sure
52*9880d681SAndroid Build Coastguard Worker   // not to split i64 and double between a register and stack
53*9880d681SAndroid Build Coastguard Worker   static const MCPhysReg RegList[] = {X86::EAX, X86::EDX, X86::ECX};
54*9880d681SAndroid Build Coastguard Worker   static const unsigned NumRegs = sizeof(RegList)/sizeof(RegList[0]);
55*9880d681SAndroid Build Coastguard Worker 
56*9880d681SAndroid Build Coastguard Worker   SmallVectorImpl<CCValAssign> &PendingMembers = State.getPendingLocs();
57*9880d681SAndroid Build Coastguard Worker 
58*9880d681SAndroid Build Coastguard Worker   // If this is the first part of an double/i64/i128, or if we're already
59*9880d681SAndroid Build Coastguard Worker   // in the middle of a split, add to the pending list. If this is not
60*9880d681SAndroid Build Coastguard Worker   // the end of the split, return, otherwise go on to process the pending
61*9880d681SAndroid Build Coastguard Worker   // list
62*9880d681SAndroid Build Coastguard Worker   if (ArgFlags.isSplit() || !PendingMembers.empty()) {
63*9880d681SAndroid Build Coastguard Worker     PendingMembers.push_back(
64*9880d681SAndroid Build Coastguard Worker         CCValAssign::getPending(ValNo, ValVT, LocVT, LocInfo));
65*9880d681SAndroid Build Coastguard Worker     if (!ArgFlags.isSplitEnd())
66*9880d681SAndroid Build Coastguard Worker       return true;
67*9880d681SAndroid Build Coastguard Worker   }
68*9880d681SAndroid Build Coastguard Worker 
69*9880d681SAndroid Build Coastguard Worker   // If there are no pending members, we are not in the middle of a split,
70*9880d681SAndroid Build Coastguard Worker   // so do the usual inreg stuff.
71*9880d681SAndroid Build Coastguard Worker   if (PendingMembers.empty()) {
72*9880d681SAndroid Build Coastguard Worker     if (unsigned Reg = State.AllocateReg(RegList)) {
73*9880d681SAndroid Build Coastguard Worker       State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
74*9880d681SAndroid Build Coastguard Worker       return true;
75*9880d681SAndroid Build Coastguard Worker     }
76*9880d681SAndroid Build Coastguard Worker     return false;
77*9880d681SAndroid Build Coastguard Worker   }
78*9880d681SAndroid Build Coastguard Worker 
79*9880d681SAndroid Build Coastguard Worker   assert(ArgFlags.isSplitEnd());
80*9880d681SAndroid Build Coastguard Worker 
81*9880d681SAndroid Build Coastguard Worker   // We now have the entire original argument in PendingMembers, so decide
82*9880d681SAndroid Build Coastguard Worker   // whether to use registers or the stack.
83*9880d681SAndroid Build Coastguard Worker   // Per the MCU ABI:
84*9880d681SAndroid Build Coastguard Worker   // a) To use registers, we need to have enough of them free to contain
85*9880d681SAndroid Build Coastguard Worker   // the entire argument.
86*9880d681SAndroid Build Coastguard Worker   // b) We never want to use more than 2 registers for a single argument.
87*9880d681SAndroid Build Coastguard Worker 
88*9880d681SAndroid Build Coastguard Worker   unsigned FirstFree = State.getFirstUnallocated(RegList);
89*9880d681SAndroid Build Coastguard Worker   bool UseRegs = PendingMembers.size() <= std::min(2U, NumRegs - FirstFree);
90*9880d681SAndroid Build Coastguard Worker 
91*9880d681SAndroid Build Coastguard Worker   for (auto &It : PendingMembers) {
92*9880d681SAndroid Build Coastguard Worker     if (UseRegs)
93*9880d681SAndroid Build Coastguard Worker       It.convertToReg(State.AllocateReg(RegList[FirstFree++]));
94*9880d681SAndroid Build Coastguard Worker     else
95*9880d681SAndroid Build Coastguard Worker       It.convertToMem(State.AllocateStack(4, 4));
96*9880d681SAndroid Build Coastguard Worker     State.addLoc(It);
97*9880d681SAndroid Build Coastguard Worker   }
98*9880d681SAndroid Build Coastguard Worker 
99*9880d681SAndroid Build Coastguard Worker   PendingMembers.clear();
100*9880d681SAndroid Build Coastguard Worker 
101*9880d681SAndroid Build Coastguard Worker   return true;
102*9880d681SAndroid Build Coastguard Worker }
103*9880d681SAndroid Build Coastguard Worker 
104*9880d681SAndroid Build Coastguard Worker } // End llvm namespace
105*9880d681SAndroid Build Coastguard Worker 
106*9880d681SAndroid Build Coastguard Worker #endif
107*9880d681SAndroid Build Coastguard Worker 
108