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