CallingConvLower.h revision 234353
1249997Swkoszek//===-- llvm/CallingConvLower.h - Calling Conventions -----------*- C++ -*-===//
2273645Sian//
3249997Swkoszek//                     The LLVM Compiler Infrastructure
4249997Swkoszek//
5249997Swkoszek// This file is distributed under the University of Illinois Open Source
6249997Swkoszek// License. See LICENSE.TXT for details.
7249997Swkoszek//
8249997Swkoszek//===----------------------------------------------------------------------===//
9249997Swkoszek//
10249997Swkoszek// This file declares the CCState and CCValAssign classes, used for lowering
11249997Swkoszek// and implementing calling conventions.
12249997Swkoszek//
13249997Swkoszek//===----------------------------------------------------------------------===//
14249997Swkoszek
15249997Swkoszek#ifndef LLVM_CODEGEN_CALLINGCONVLOWER_H
16249997Swkoszek#define LLVM_CODEGEN_CALLINGCONVLOWER_H
17249997Swkoszek
18249997Swkoszek#include "llvm/ADT/SmallVector.h"
19249997Swkoszek#include "llvm/CodeGen/MachineFunction.h"
20249997Swkoszek#include "llvm/CodeGen/ValueTypes.h"
21249997Swkoszek#include "llvm/Target/TargetCallingConv.h"
22249997Swkoszek#include "llvm/CallingConv.h"
23249997Swkoszek
24249997Swkoszeknamespace llvm {
25249997Swkoszek  class TargetRegisterInfo;
26249997Swkoszek  class TargetMachine;
27250015Swkoszek  class CCState;
28250015Swkoszek
29249997Swkoszek/// CCValAssign - Represent assignment of one arg/retval to a location.
30249997Swkoszekclass CCValAssign {
31249997Swkoszekpublic:
32249997Swkoszek  enum LocInfo {
33249997Swkoszek    Full,   // The value fills the full location.
34249997Swkoszek    SExt,   // The value is sign extended in the location.
35249997Swkoszek    ZExt,   // The value is zero extended in the location.
36249997Swkoszek    AExt,   // The value is extended with undefined upper bits.
37249997Swkoszek    BCvt,   // The value is bit-converted in the location.
38249997Swkoszek    VExt,   // The value is vector-widened in the location.
39249997Swkoszek            // FIXME: Not implemented yet. Code that uses AExt to mean
40249997Swkoszek            // vector-widen should be fixed to use VExt instead.
41249997Swkoszek    Indirect // The location contains pointer to the value.
42249997Swkoszek    // TODO: a subset of the value is in the location.
43249997Swkoszek  };
44249997Swkoszekprivate:
45249997Swkoszek  /// ValNo - This is the value number begin assigned (e.g. an argument number).
46249997Swkoszek  unsigned ValNo;
47249997Swkoszek
48249997Swkoszek  /// Loc is either a stack offset or a register number.
49249997Swkoszek  unsigned Loc;
50249997Swkoszek
51249997Swkoszek  /// isMem - True if this is a memory loc, false if it is a register loc.
52249997Swkoszek  bool isMem : 1;
53249997Swkoszek
54249997Swkoszek  /// isCustom - True if this arg/retval requires special handling.
55249997Swkoszek  bool isCustom : 1;
56249997Swkoszek
57249997Swkoszek  /// Information about how the value is assigned.
58249997Swkoszek  LocInfo HTP : 6;
59249997Swkoszek
60249997Swkoszek  /// ValVT - The type of the value being assigned.
61249997Swkoszek  MVT ValVT;
62249997Swkoszek
63249997Swkoszek  /// LocVT - The type of the location being assigned to.
64249997Swkoszek  MVT LocVT;
65249997Swkoszekpublic:
66249997Swkoszek
67249997Swkoszek  static CCValAssign getReg(unsigned ValNo, MVT ValVT,
68249997Swkoszek                            unsigned RegNo, MVT LocVT,
69249997Swkoszek                            LocInfo HTP) {
70249997Swkoszek    CCValAssign Ret;
71249997Swkoszek    Ret.ValNo = ValNo;
72249997Swkoszek    Ret.Loc = RegNo;
73249997Swkoszek    Ret.isMem = false;
74249997Swkoszek    Ret.isCustom = false;
75249997Swkoszek    Ret.HTP = HTP;
76249997Swkoszek    Ret.ValVT = ValVT;
77249997Swkoszek    Ret.LocVT = LocVT;
78249997Swkoszek    return Ret;
79249997Swkoszek  }
80249997Swkoszek
81249997Swkoszek  static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT,
82249997Swkoszek                                  unsigned RegNo, MVT LocVT,
83249997Swkoszek                                  LocInfo HTP) {
84273645Sian    CCValAssign Ret;
85273645Sian    Ret = getReg(ValNo, ValVT, RegNo, LocVT, HTP);
86249997Swkoszek    Ret.isCustom = true;
87249997Swkoszek    return Ret;
88249997Swkoszek  }
89249997Swkoszek
90249997Swkoszek  static CCValAssign getMem(unsigned ValNo, MVT ValVT,
91249997Swkoszek                            unsigned Offset, MVT LocVT,
92273645Sian                            LocInfo HTP) {
93249997Swkoszek    CCValAssign Ret;
94273645Sian    Ret.ValNo = ValNo;
95249997Swkoszek    Ret.Loc = Offset;
96249997Swkoszek    Ret.isMem = true;
97249997Swkoszek    Ret.isCustom = false;
98249997Swkoszek    Ret.HTP = HTP;
99249997Swkoszek    Ret.ValVT = ValVT;
100249997Swkoszek    Ret.LocVT = LocVT;
101249997Swkoszek    return Ret;
102249997Swkoszek  }
103249997Swkoszek
104273645Sian  static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT,
105249997Swkoszek                                  unsigned Offset, MVT LocVT,
106249997Swkoszek                                  LocInfo HTP) {
107249997Swkoszek    CCValAssign Ret;
108249997Swkoszek    Ret = getMem(ValNo, ValVT, Offset, LocVT, HTP);
109249997Swkoszek    Ret.isCustom = true;
110249997Swkoszek    return Ret;
111273645Sian  }
112249997Swkoszek
113249997Swkoszek  unsigned getValNo() const { return ValNo; }
114249997Swkoszek  MVT getValVT() const { return ValVT; }
115249997Swkoszek
116249997Swkoszek  bool isRegLoc() const { return !isMem; }
117249997Swkoszek  bool isMemLoc() const { return isMem; }
118249997Swkoszek
119249997Swkoszek  bool needsCustom() const { return isCustom; }
120249997Swkoszek
121249997Swkoszek  unsigned getLocReg() const { assert(isRegLoc()); return Loc; }
122249997Swkoszek  unsigned getLocMemOffset() const { assert(isMemLoc()); return Loc; }
123249997Swkoszek  MVT getLocVT() const { return LocVT; }
124249997Swkoszek
125249997Swkoszek  LocInfo getLocInfo() const { return HTP; }
126249997Swkoszek  bool isExtInLoc() const {
127273645Sian    return (HTP == AExt || HTP == SExt || HTP == ZExt);
128273645Sian  }
129273645Sian
130273645Sian};
131273645Sian
132249997Swkoszek/// CCAssignFn - This function assigns a location for Val, updating State to
133249997Swkoszek/// reflect the change.  It returns 'true' if it failed to handle Val.
134249997Swkoszektypedef bool CCAssignFn(unsigned ValNo, MVT ValVT,
135249997Swkoszek                        MVT LocVT, CCValAssign::LocInfo LocInfo,
136249997Swkoszek                        ISD::ArgFlagsTy ArgFlags, CCState &State);
137249997Swkoszek
138249997Swkoszek/// CCCustomFn - This function assigns a location for Val, possibly updating
139249997Swkoszek/// all args to reflect changes and indicates if it handled it. It must set
140249997Swkoszek/// isCustom if it handles the arg and returns true.
141249997Swkoszektypedef bool CCCustomFn(unsigned &ValNo, MVT &ValVT,
142273645Sian                        MVT &LocVT, CCValAssign::LocInfo &LocInfo,
143273645Sian                        ISD::ArgFlagsTy &ArgFlags, CCState &State);
144273645Sian
145273645Sian/// ParmContext - This enum tracks whether calling convention lowering is in
146273645Sian/// the context of prologue or call generation. Not all backends make use of
147273645Sian/// this information.
148273645Siantypedef enum { Unknown, Prologue, Call } ParmContext;
149273645Sian
150273645Sian/// CCState - This class holds information needed while lowering arguments and
151273645Sian/// return values.  It captures which registers are already assigned and which
152273645Sian/// stack slots are used.  It provides accessors to allocate these values.
153273645Sianclass CCState {
154273645Sianprivate:
155273645Sian  CallingConv::ID CallingConv;
156273645Sian  bool IsVarArg;
157273645Sian  MachineFunction &MF;
158273645Sian  const TargetMachine &TM;
159273645Sian  const TargetRegisterInfo &TRI;
160273645Sian  SmallVector<CCValAssign, 16> &Locs;
161273645Sian  LLVMContext &Context;
162273645Sian
163273645Sian  unsigned StackOffset;
164273645Sian  SmallVector<uint32_t, 16> UsedRegs;
165273645Sian  unsigned FirstByValReg;
166273645Sian  bool FirstByValRegValid;
167273645Sian
168273645Sianprotected:
169273645Sian  ParmContext CallOrPrologue;
170273645Sian
171273645Sianpublic:
172273645Sian  CCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF,
173273645Sian          const TargetMachine &TM, SmallVector<CCValAssign, 16> &locs,
174273645Sian          LLVMContext &C);
175273645Sian
176273645Sian  void addLoc(const CCValAssign &V) {
177273645Sian    Locs.push_back(V);
178273645Sian  }
179273645Sian
180273645Sian  LLVMContext &getContext() const { return Context; }
181273645Sian  const TargetMachine &getTarget() const { return TM; }
182273645Sian  MachineFunction &getMachineFunction() const { return MF; }
183273645Sian  CallingConv::ID getCallingConv() const { return CallingConv; }
184273645Sian  bool isVarArg() const { return IsVarArg; }
185273645Sian
186273645Sian  unsigned getNextStackOffset() const { return StackOffset; }
187273645Sian
188273645Sian  /// isAllocated - Return true if the specified register (or an alias) is
189273645Sian  /// allocated.
190273645Sian  bool isAllocated(unsigned Reg) const {
191273645Sian    return UsedRegs[Reg/32] & (1 << (Reg&31));
192249997Swkoszek  }
193249997Swkoszek
194249997Swkoszek  /// AnalyzeFormalArguments - Analyze an array of argument values,
195249997Swkoszek  /// incorporating info about the formals into this state.
196249997Swkoszek  void AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
197249997Swkoszek                              CCAssignFn Fn);
198249997Swkoszek
199249997Swkoszek  /// AnalyzeReturn - Analyze the returned values of a return,
200249997Swkoszek  /// incorporating info about the result values into this state.
201249997Swkoszek  void AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
202249997Swkoszek                     CCAssignFn Fn);
203249997Swkoszek
204249997Swkoszek  /// CheckReturn - Analyze the return values of a function, returning
205249997Swkoszek  /// true if the return can be performed without sret-demotion, and
206249997Swkoszek  /// false otherwise.
207273645Sian  bool CheckReturn(const SmallVectorImpl<ISD::OutputArg> &ArgsFlags,
208273645Sian                   CCAssignFn Fn);
209273645Sian
210249997Swkoszek  /// AnalyzeCallOperands - Analyze the outgoing arguments to a call,
211249997Swkoszek  /// incorporating info about the passed values into this state.
212249997Swkoszek  void AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs,
213249997Swkoszek                           CCAssignFn Fn);
214249997Swkoszek
215249997Swkoszek  /// AnalyzeCallOperands - Same as above except it takes vectors of types
216249997Swkoszek  /// and argument flags.
217249997Swkoszek  void AnalyzeCallOperands(SmallVectorImpl<MVT> &ArgVTs,
218273645Sian                           SmallVectorImpl<ISD::ArgFlagsTy> &Flags,
219273645Sian                           CCAssignFn Fn);
220249997Swkoszek
221249997Swkoszek  /// AnalyzeCallResult - Analyze the return values of a call,
222249997Swkoszek  /// incorporating info about the passed values into this state.
223249997Swkoszek  void AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins,
224249997Swkoszek                         CCAssignFn Fn);
225249997Swkoszek
226249997Swkoszek  /// AnalyzeCallResult - Same as above except it's specialized for calls which
227249997Swkoszek  /// produce a single value.
228249997Swkoszek  void AnalyzeCallResult(MVT VT, CCAssignFn Fn);
229249997Swkoszek
230249997Swkoszek  /// getFirstUnallocated - Return the first unallocated register in the set, or
231249997Swkoszek  /// NumRegs if they are all allocated.
232249997Swkoszek  unsigned getFirstUnallocated(const uint16_t *Regs, unsigned NumRegs) const {
233249997Swkoszek    for (unsigned i = 0; i != NumRegs; ++i)
234249997Swkoszek      if (!isAllocated(Regs[i]))
235249997Swkoszek        return i;
236249997Swkoszek    return NumRegs;
237249997Swkoszek  }
238249997Swkoszek
239249997Swkoszek  /// AllocateReg - Attempt to allocate one register.  If it is not available,
240249997Swkoszek  /// return zero.  Otherwise, return the register, marking it and any aliases
241249997Swkoszek  /// as allocated.
242249997Swkoszek  unsigned AllocateReg(unsigned Reg) {
243249997Swkoszek    if (isAllocated(Reg)) return 0;
244249997Swkoszek    MarkAllocated(Reg);
245249997Swkoszek    return Reg;
246249997Swkoszek  }
247249997Swkoszek
248249997Swkoszek  /// Version of AllocateReg with extra register to be shadowed.
249249997Swkoszek  unsigned AllocateReg(unsigned Reg, unsigned ShadowReg) {
250249997Swkoszek    if (isAllocated(Reg)) return 0;
251249997Swkoszek    MarkAllocated(Reg);
252249997Swkoszek    MarkAllocated(ShadowReg);
253249997Swkoszek    return Reg;
254249997Swkoszek  }
255249997Swkoszek
256273645Sian  /// AllocateReg - Attempt to allocate one of the specified registers.  If none
257249997Swkoszek  /// are available, return zero.  Otherwise, return the first one available,
258273645Sian  /// marking it and any aliases as allocated.
259273645Sian  unsigned AllocateReg(const uint16_t *Regs, unsigned NumRegs) {
260273645Sian    unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs);
261273645Sian    if (FirstUnalloc == NumRegs)
262273645Sian      return 0;    // Didn't find the reg.
263273645Sian
264273645Sian    // Mark the register and any aliases as allocated.
265273645Sian    unsigned Reg = Regs[FirstUnalloc];
266249997Swkoszek    MarkAllocated(Reg);
267249997Swkoszek    return Reg;
268249997Swkoszek  }
269249997Swkoszek
270249997Swkoszek  /// Version of AllocateReg with list of registers to be shadowed.
271249997Swkoszek  unsigned AllocateReg(const uint16_t *Regs, const uint16_t *ShadowRegs,
272249997Swkoszek                       unsigned NumRegs) {
273249997Swkoszek    unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs);
274249997Swkoszek    if (FirstUnalloc == NumRegs)
275249997Swkoszek      return 0;    // Didn't find the reg.
276249997Swkoszek
277249997Swkoszek    // Mark the register and any aliases as allocated.
278249997Swkoszek    unsigned Reg = Regs[FirstUnalloc], ShadowReg = ShadowRegs[FirstUnalloc];
279249997Swkoszek    MarkAllocated(Reg);
280249997Swkoszek    MarkAllocated(ShadowReg);
281249997Swkoszek    return Reg;
282249997Swkoszek  }
283249997Swkoszek
284249997Swkoszek  /// AllocateStack - Allocate a chunk of stack space with the specified size
285249997Swkoszek  /// and alignment.
286249997Swkoszek  unsigned AllocateStack(unsigned Size, unsigned Align) {
287249997Swkoszek    assert(Align && ((Align-1) & Align) == 0); // Align is power of 2.
288249997Swkoszek    StackOffset = ((StackOffset + Align-1) & ~(Align-1));
289249997Swkoszek    unsigned Result = StackOffset;
290249997Swkoszek    StackOffset += Size;
291249997Swkoszek    return Result;
292249997Swkoszek  }
293249997Swkoszek
294249997Swkoszek  /// Version of AllocateStack with extra register to be shadowed.
295249997Swkoszek  unsigned AllocateStack(unsigned Size, unsigned Align, unsigned ShadowReg) {
296249997Swkoszek    MarkAllocated(ShadowReg);
297249997Swkoszek    return AllocateStack(Size, Align);
298249997Swkoszek  }
299249997Swkoszek
300249997Swkoszek  // HandleByVal - Allocate a stack slot large enough to pass an argument by
301249997Swkoszek  // value. The size and alignment information of the argument is encoded in its
302249997Swkoszek  // parameter attribute.
303249997Swkoszek  void HandleByVal(unsigned ValNo, MVT ValVT,
304249997Swkoszek                   MVT LocVT, CCValAssign::LocInfo LocInfo,
305249997Swkoszek                   int MinSize, int MinAlign, ISD::ArgFlagsTy ArgFlags);
306249997Swkoszek
307249997Swkoszek  // First GPR that carries part of a byval aggregate that's split
308249997Swkoszek  // between registers and memory.
309249997Swkoszek  unsigned getFirstByValReg() const { return FirstByValRegValid ? FirstByValReg : 0; }
310249997Swkoszek  void setFirstByValReg(unsigned r) { FirstByValReg = r; FirstByValRegValid = true; }
311249997Swkoszek  void clearFirstByValReg() { FirstByValReg = 0; FirstByValRegValid = false; }
312249997Swkoszek  bool isFirstByValRegValid() const { return FirstByValRegValid; }
313249997Swkoszek
314249997Swkoszek  ParmContext getCallOrPrologue() const { return CallOrPrologue; }
315249997Swkoszek
316249997Swkoszekprivate:
317249997Swkoszek  /// MarkAllocated - Mark a register and all of its aliases as allocated.
318249997Swkoszek  void MarkAllocated(unsigned Reg);
319249997Swkoszek};
320249997Swkoszek
321249997Swkoszek
322249997Swkoszek
323249997Swkoszek} // end namespace llvm
324249997Swkoszek
325249997Swkoszek#endif
326249997Swkoszek