1234285Sdim//===-- llvm/CallingConvLower.cpp - Calling Convention lowering -----------===//
2234285Sdim//
3234285Sdim//                     The LLVM Compiler Infrastructure
4234285Sdim//
5234285Sdim// This file is distributed under the University of Illinois Open Source
6234285Sdim// License. See LICENSE.TXT for details.
7234285Sdim//
8234285Sdim//===----------------------------------------------------------------------===//
9234285Sdim//
10234285Sdim// This file implements the Hexagon_CCState class, used for lowering and
11234285Sdim// implementing calling conventions. Adapted from the machine independent
12234285Sdim// version of the class (CCState) but this handles calls to varargs functions
13234285Sdim//
14234285Sdim//===----------------------------------------------------------------------===//
15234285Sdim
16234285Sdim#include "HexagonCallingConvLower.h"
17234285Sdim#include "Hexagon.h"
18249423Sdim#include "llvm/IR/DataLayout.h"
19234285Sdim#include "llvm/Support/Debug.h"
20234285Sdim#include "llvm/Support/ErrorHandling.h"
21234285Sdim#include "llvm/Support/raw_ostream.h"
22249423Sdim#include "llvm/Target/TargetMachine.h"
23249423Sdim#include "llvm/Target/TargetRegisterInfo.h"
24234285Sdimusing namespace llvm;
25234285Sdim
26234285SdimHexagon_CCState::Hexagon_CCState(CallingConv::ID CC, bool isVarArg,
27234285Sdim                                 const TargetMachine &tm,
28263508Sdim                                 SmallVectorImpl<CCValAssign> &locs,
29234285Sdim                                 LLVMContext &c)
30263508Sdim  : CallingConv(CC), IsVarArg(isVarArg), TM(tm), Locs(locs), Context(c) {
31234285Sdim  // No stack is used.
32234285Sdim  StackOffset = 0;
33234285Sdim
34263508Sdim  UsedRegs.resize((TM.getRegisterInfo()->getNumRegs()+31)/32);
35234285Sdim}
36234285Sdim
37234285Sdim// HandleByVal - Allocate a stack slot large enough to pass an argument by
38234285Sdim// value. The size and alignment information of the argument is encoded in its
39234285Sdim// parameter attribute.
40234285Sdimvoid Hexagon_CCState::HandleByVal(unsigned ValNo, EVT ValVT,
41234285Sdim                                EVT LocVT, CCValAssign::LocInfo LocInfo,
42234285Sdim                                int MinSize, int MinAlign,
43234285Sdim                                ISD::ArgFlagsTy ArgFlags) {
44234285Sdim  unsigned Align = ArgFlags.getByValAlign();
45234285Sdim  unsigned Size  = ArgFlags.getByValSize();
46234285Sdim  if (MinSize > (int)Size)
47234285Sdim    Size = MinSize;
48234285Sdim  if (MinAlign > (int)Align)
49234285Sdim    Align = MinAlign;
50234285Sdim  unsigned Offset = AllocateStack(Size, Align);
51234285Sdim
52234285Sdim  addLoc(CCValAssign::getMem(ValNo, ValVT.getSimpleVT(), Offset,
53234285Sdim                             LocVT.getSimpleVT(), LocInfo));
54234285Sdim}
55234285Sdim
56234285Sdim/// MarkAllocated - Mark a register and all of its aliases as allocated.
57234285Sdimvoid Hexagon_CCState::MarkAllocated(unsigned Reg) {
58263508Sdim  const TargetRegisterInfo &TRI = *TM.getRegisterInfo();
59239462Sdim  for (MCRegAliasIterator AI(Reg, &TRI, true); AI.isValid(); ++AI)
60239462Sdim    UsedRegs[*AI/32] |= 1 << (*AI&31);
61234285Sdim}
62234285Sdim
63234285Sdim/// AnalyzeFormalArguments - Analyze an ISD::FORMAL_ARGUMENTS node,
64234285Sdim/// incorporating info about the formals into this state.
65234285Sdimvoid
66234285SdimHexagon_CCState::AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg>
67234285Sdim                                        &Ins,
68234285Sdim                                        Hexagon_CCAssignFn Fn,
69234285Sdim                                        unsigned SretValueInRegs) {
70234285Sdim  unsigned NumArgs = Ins.size();
71234285Sdim  unsigned i = 0;
72234285Sdim
73234285Sdim  // If the function returns a small struct in registers, skip
74234285Sdim  // over the first (dummy) argument.
75234285Sdim  if (SretValueInRegs != 0) {
76234285Sdim    ++i;
77234285Sdim  }
78234285Sdim
79234285Sdim
80234285Sdim  for (; i != NumArgs; ++i) {
81234285Sdim    EVT ArgVT = Ins[i].VT;
82234285Sdim    ISD::ArgFlagsTy ArgFlags = Ins[i].Flags;
83234285Sdim    if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this, 0, 0, false)) {
84234285Sdim      dbgs() << "Formal argument #" << i << " has unhandled type "
85234285Sdim             << ArgVT.getEVTString() << "\n";
86234285Sdim      abort();
87234285Sdim    }
88234285Sdim  }
89234285Sdim}
90234285Sdim
91234285Sdim/// AnalyzeReturn - Analyze the returned values of an ISD::RET node,
92234285Sdim/// incorporating info about the result values into this state.
93234285Sdimvoid
94234285SdimHexagon_CCState::AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
95234285Sdim                               Hexagon_CCAssignFn Fn,
96234285Sdim                               unsigned SretValueInRegs) {
97234285Sdim
98234285Sdim  // For Hexagon, Return small structures in registers.
99234285Sdim  if (SretValueInRegs != 0) {
100234285Sdim    if (SretValueInRegs <= 32) {
101234285Sdim      unsigned Reg = Hexagon::R0;
102234285Sdim      addLoc(CCValAssign::getReg(0, MVT::i32, Reg, MVT::i32,
103234285Sdim                                 CCValAssign::Full));
104234285Sdim      return;
105234285Sdim    }
106234285Sdim    if (SretValueInRegs <= 64) {
107234285Sdim      unsigned Reg = Hexagon::D0;
108234285Sdim      addLoc(CCValAssign::getReg(0, MVT::i64, Reg, MVT::i64,
109234285Sdim                                 CCValAssign::Full));
110234285Sdim      return;
111234285Sdim    }
112234285Sdim  }
113234285Sdim
114234285Sdim
115234285Sdim  // Determine which register each value should be copied into.
116234285Sdim  for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
117234285Sdim    EVT VT = Outs[i].VT;
118234285Sdim    ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
119234285Sdim    if (Fn(i, VT, VT, CCValAssign::Full, ArgFlags, *this, -1, -1, false)){
120234285Sdim      dbgs() << "Return operand #" << i << " has unhandled type "
121234285Sdim           << VT.getEVTString() << "\n";
122234285Sdim      abort();
123234285Sdim    }
124234285Sdim  }
125234285Sdim}
126234285Sdim
127234285Sdim
128234285Sdim/// AnalyzeCallOperands - Analyze an ISD::CALL node, incorporating info
129234285Sdim/// about the passed values into this state.
130234285Sdimvoid
131234285SdimHexagon_CCState::AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg>
132234285Sdim                                     &Outs,
133234285Sdim                                     Hexagon_CCAssignFn Fn,
134234285Sdim                                     int NonVarArgsParams,
135234285Sdim                                     unsigned SretValueSize) {
136234285Sdim  unsigned NumOps = Outs.size();
137234285Sdim
138234285Sdim  unsigned i = 0;
139234285Sdim  // If the called function returns a small struct in registers, skip
140234285Sdim  // the first actual parameter. We do not want to pass a pointer to
141234285Sdim  // the stack location.
142234285Sdim  if (SretValueSize != 0) {
143234285Sdim    ++i;
144234285Sdim  }
145234285Sdim
146234285Sdim  for (; i != NumOps; ++i) {
147234285Sdim    EVT ArgVT = Outs[i].VT;
148234285Sdim    ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
149234285Sdim    if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this,
150234285Sdim           NonVarArgsParams, i+1, false)) {
151234285Sdim      dbgs() << "Call operand #" << i << " has unhandled type "
152234285Sdim           << ArgVT.getEVTString() << "\n";
153234285Sdim      abort();
154234285Sdim    }
155234285Sdim  }
156234285Sdim}
157234285Sdim
158234285Sdim/// AnalyzeCallOperands - Same as above except it takes vectors of types
159234285Sdim/// and argument flags.
160234285Sdimvoid
161234285SdimHexagon_CCState::AnalyzeCallOperands(SmallVectorImpl<EVT> &ArgVTs,
162234285Sdim                                     SmallVectorImpl<ISD::ArgFlagsTy> &Flags,
163234285Sdim                                     Hexagon_CCAssignFn Fn) {
164234285Sdim  unsigned NumOps = ArgVTs.size();
165234285Sdim  for (unsigned i = 0; i != NumOps; ++i) {
166234285Sdim    EVT ArgVT = ArgVTs[i];
167234285Sdim    ISD::ArgFlagsTy ArgFlags = Flags[i];
168234285Sdim    if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this, -1, -1,
169234285Sdim           false)) {
170234285Sdim      dbgs() << "Call operand #" << i << " has unhandled type "
171234285Sdim           << ArgVT.getEVTString() << "\n";
172234285Sdim      abort();
173234285Sdim    }
174234285Sdim  }
175234285Sdim}
176234285Sdim
177234285Sdim/// AnalyzeCallResult - Analyze the return values of an ISD::CALL node,
178234285Sdim/// incorporating info about the passed values into this state.
179234285Sdimvoid
180234285SdimHexagon_CCState::AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins,
181234285Sdim                                   Hexagon_CCAssignFn Fn,
182234285Sdim                                   unsigned SretValueInRegs) {
183234285Sdim
184234285Sdim  for (unsigned i = 0, e = Ins.size(); i != e; ++i) {
185234285Sdim    EVT VT = Ins[i].VT;
186234285Sdim    ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy();
187234285Sdim      if (Fn(i, VT, VT, CCValAssign::Full, Flags, *this, -1, -1, false)) {
188234285Sdim        dbgs() << "Call result #" << i << " has unhandled type "
189234285Sdim               << VT.getEVTString() << "\n";
190234285Sdim      abort();
191234285Sdim    }
192234285Sdim  }
193234285Sdim}
194234285Sdim
195234285Sdim/// AnalyzeCallResult - Same as above except it's specialized for calls which
196234285Sdim/// produce a single value.
197234285Sdimvoid Hexagon_CCState::AnalyzeCallResult(EVT VT, Hexagon_CCAssignFn Fn) {
198234285Sdim  if (Fn(0, VT, VT, CCValAssign::Full, ISD::ArgFlagsTy(), *this, -1, -1,
199234285Sdim         false)) {
200234285Sdim    dbgs() << "Call result has unhandled type "
201234285Sdim         << VT.getEVTString() << "\n";
202234285Sdim    abort();
203234285Sdim  }
204234285Sdim}
205