]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===-- HexagonCallingConvLower.h - Calling Conventions ---------*- 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 declares the Hexagon_CCState class, used for lowering | |
11 | // and implementing calling conventions. Adapted from the target independent | |
12 | // version but this handles calls to varargs functions | |
13 | // | |
14 | //===----------------------------------------------------------------------===// | |
15 | ||
16 | #ifndef LLVM_Hexagon_CODEGEN_CALLINGCONVLOWER_H | |
17 | #define LLVM_Hexagon_CODEGEN_CALLINGCONVLOWER_H | |
18 | ||
19 | #include "llvm/ADT/SmallVector.h" | |
223e47cc | 20 | #include "llvm/CodeGen/CallingConvLower.h" |
970d7e83 LB |
21 | #include "llvm/CodeGen/SelectionDAGNodes.h" |
22 | #include "llvm/CodeGen/ValueTypes.h" | |
223e47cc LB |
23 | |
24 | // | |
25 | // Need to handle varargs. | |
26 | // | |
27 | namespace llvm { | |
28 | class TargetRegisterInfo; | |
29 | class TargetMachine; | |
30 | class Hexagon_CCState; | |
31 | class SDNode; | |
32 | ||
33 | ||
34 | /// Hexagon_CCAssignFn - This function assigns a location for Val, updating | |
35 | /// State to reflect the change. | |
36 | typedef bool Hexagon_CCAssignFn(unsigned ValNo, EVT ValVT, | |
37 | EVT LocVT, CCValAssign::LocInfo LocInfo, | |
38 | ISD::ArgFlagsTy ArgFlags, Hexagon_CCState &State, | |
39 | int NonVarArgsParams, | |
40 | int CurrentParam, | |
41 | bool ForceMem); | |
42 | ||
43 | ||
44 | /// CCState - This class holds information needed while lowering arguments and | |
45 | /// return values. It captures which registers are already assigned and which | |
46 | /// stack slots are used. It provides accessors to allocate these values. | |
47 | class Hexagon_CCState { | |
48 | CallingConv::ID CallingConv; | |
49 | bool IsVarArg; | |
50 | const TargetMachine &TM; | |
51 | const TargetRegisterInfo &TRI; | |
52 | SmallVector<CCValAssign, 16> &Locs; | |
53 | LLVMContext &Context; | |
54 | ||
55 | unsigned StackOffset; | |
56 | SmallVector<uint32_t, 16> UsedRegs; | |
57 | public: | |
58 | Hexagon_CCState(CallingConv::ID CC, bool isVarArg, const TargetMachine &TM, | |
59 | SmallVector<CCValAssign, 16> &locs, LLVMContext &c); | |
60 | ||
61 | void addLoc(const CCValAssign &V) { | |
62 | Locs.push_back(V); | |
63 | } | |
64 | ||
65 | LLVMContext &getContext() const { return Context; } | |
66 | const TargetMachine &getTarget() const { return TM; } | |
67 | unsigned getCallingConv() const { return CallingConv; } | |
68 | bool isVarArg() const { return IsVarArg; } | |
69 | ||
70 | unsigned getNextStackOffset() const { return StackOffset; } | |
71 | ||
72 | /// isAllocated - Return true if the specified register (or an alias) is | |
73 | /// allocated. | |
74 | bool isAllocated(unsigned Reg) const { | |
75 | return UsedRegs[Reg/32] & (1 << (Reg&31)); | |
76 | } | |
77 | ||
78 | /// AnalyzeFormalArguments - Analyze an ISD::FORMAL_ARGUMENTS node, | |
79 | /// incorporating info about the formals into this state. | |
80 | void AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins, | |
81 | Hexagon_CCAssignFn Fn, unsigned SretValueInRegs); | |
82 | ||
83 | /// AnalyzeReturn - Analyze the returned values of an ISD::RET node, | |
84 | /// incorporating info about the result values into this state. | |
85 | void AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs, | |
86 | Hexagon_CCAssignFn Fn, unsigned SretValueInRegs); | |
87 | ||
88 | /// AnalyzeCallOperands - Analyze an ISD::CALL node, incorporating info | |
89 | /// about the passed values into this state. | |
90 | void AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs, | |
91 | Hexagon_CCAssignFn Fn, int NonVarArgsParams, | |
92 | unsigned SretValueSize); | |
93 | ||
94 | /// AnalyzeCallOperands - Same as above except it takes vectors of types | |
95 | /// and argument flags. | |
96 | void AnalyzeCallOperands(SmallVectorImpl<EVT> &ArgVTs, | |
97 | SmallVectorImpl<ISD::ArgFlagsTy> &Flags, | |
98 | Hexagon_CCAssignFn Fn); | |
99 | ||
100 | /// AnalyzeCallResult - Analyze the return values of an ISD::CALL node, | |
101 | /// incorporating info about the passed values into this state. | |
102 | void AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins, | |
103 | Hexagon_CCAssignFn Fn, unsigned SretValueInRegs); | |
104 | ||
105 | /// AnalyzeCallResult - Same as above except it's specialized for calls which | |
106 | /// produce a single value. | |
107 | void AnalyzeCallResult(EVT VT, Hexagon_CCAssignFn Fn); | |
108 | ||
109 | /// getFirstUnallocated - Return the first unallocated register in the set, or | |
110 | /// NumRegs if they are all allocated. | |
111 | unsigned getFirstUnallocated(const unsigned *Regs, unsigned NumRegs) const { | |
112 | for (unsigned i = 0; i != NumRegs; ++i) | |
113 | if (!isAllocated(Regs[i])) | |
114 | return i; | |
115 | return NumRegs; | |
116 | } | |
117 | ||
118 | /// AllocateReg - Attempt to allocate one register. If it is not available, | |
119 | /// return zero. Otherwise, return the register, marking it and any aliases | |
120 | /// as allocated. | |
121 | unsigned AllocateReg(unsigned Reg) { | |
122 | if (isAllocated(Reg)) return 0; | |
123 | MarkAllocated(Reg); | |
124 | return Reg; | |
125 | } | |
126 | ||
127 | /// Version of AllocateReg with extra register to be shadowed. | |
128 | unsigned AllocateReg(unsigned Reg, unsigned ShadowReg) { | |
129 | if (isAllocated(Reg)) return 0; | |
130 | MarkAllocated(Reg); | |
131 | MarkAllocated(ShadowReg); | |
132 | return Reg; | |
133 | } | |
134 | ||
135 | /// AllocateReg - Attempt to allocate one of the specified registers. If none | |
136 | /// are available, return zero. Otherwise, return the first one available, | |
137 | /// marking it and any aliases as allocated. | |
138 | unsigned AllocateReg(const unsigned *Regs, unsigned NumRegs) { | |
139 | unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs); | |
140 | if (FirstUnalloc == NumRegs) | |
141 | return 0; // Didn't find the reg. | |
142 | ||
143 | // Mark the register and any aliases as allocated. | |
144 | unsigned Reg = Regs[FirstUnalloc]; | |
145 | MarkAllocated(Reg); | |
146 | return Reg; | |
147 | } | |
148 | ||
149 | /// Version of AllocateReg with list of registers to be shadowed. | |
150 | unsigned AllocateReg(const unsigned *Regs, const unsigned *ShadowRegs, | |
151 | unsigned NumRegs) { | |
152 | unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs); | |
153 | if (FirstUnalloc == NumRegs) | |
154 | return 0; // Didn't find the reg. | |
155 | ||
156 | // Mark the register and any aliases as allocated. | |
157 | unsigned Reg = Regs[FirstUnalloc], ShadowReg = ShadowRegs[FirstUnalloc]; | |
158 | MarkAllocated(Reg); | |
159 | MarkAllocated(ShadowReg); | |
160 | return Reg; | |
161 | } | |
162 | ||
163 | /// AllocateStack - Allocate a chunk of stack space with the specified size | |
164 | /// and alignment. | |
165 | unsigned AllocateStack(unsigned Size, unsigned Align) { | |
166 | assert(Align && ((Align-1) & Align) == 0); // Align is power of 2. | |
167 | StackOffset = ((StackOffset + Align-1) & ~(Align-1)); | |
168 | unsigned Result = StackOffset; | |
169 | StackOffset += Size; | |
170 | return Result; | |
171 | } | |
172 | ||
173 | // HandleByVal - Allocate a stack slot large enough to pass an argument by | |
174 | // value. The size and alignment information of the argument is encoded in its | |
175 | // parameter attribute. | |
176 | void HandleByVal(unsigned ValNo, EVT ValVT, | |
177 | EVT LocVT, CCValAssign::LocInfo LocInfo, | |
178 | int MinSize, int MinAlign, ISD::ArgFlagsTy ArgFlags); | |
179 | ||
180 | private: | |
181 | /// MarkAllocated - Mark a register and all of its aliases as allocated. | |
182 | void MarkAllocated(unsigned Reg); | |
183 | }; | |
184 | ||
185 | ||
186 | ||
187 | } // end namespace llvm | |
188 | ||
189 | #endif |