blob: 95e4691b65f158f451fe7b43895b8485ab33ba32 [file] [log] [blame]
Jan Voungb36ad9b2015-04-21 17:01:49 -07001//===- subzero/src/IceTargetLoweringARM32.h - ARM32 lowering ----*- C++ -*-===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
11/// This file declares the TargetLoweringARM32 class, which implements the
12/// TargetLowering interface for the ARM 32-bit architecture.
13///
Jan Voungb36ad9b2015-04-21 17:01:49 -070014//===----------------------------------------------------------------------===//
15
16#ifndef SUBZERO_SRC_ICETARGETLOWERINGARM32_H
17#define SUBZERO_SRC_ICETARGETLOWERINGARM32_H
18
19#include "IceDefs.h"
Jan Voungb2d50842015-05-12 09:53:50 -070020#include "IceInstARM32.h"
Jan Voungb36ad9b2015-04-21 17:01:49 -070021#include "IceRegistersARM32.h"
22#include "IceTargetLowering.h"
23
24namespace Ice {
25
Jan Voung6ec369e2015-06-30 11:03:15 -070026// Class encapsulating ARM cpu features / instruction set.
27class TargetARM32Features {
28 TargetARM32Features() = delete;
29 TargetARM32Features(const TargetARM32Features &) = delete;
30 TargetARM32Features &operator=(const TargetARM32Features &) = delete;
31
32public:
33 explicit TargetARM32Features(const ClFlags &Flags);
34
35 enum ARM32InstructionSet {
36 Begin,
37 // Neon is the PNaCl baseline instruction set.
38 Neon = Begin,
39 HWDivArm, // HW divide in ARM mode (not just Thumb mode).
40 End
41 };
42
43 bool hasFeature(ARM32InstructionSet I) const { return I <= InstructionSet; }
44
45private:
46 ARM32InstructionSet InstructionSet = ARM32InstructionSet::Begin;
47};
48
49// The target lowering logic for ARM32.
Jan Voungb36ad9b2015-04-21 17:01:49 -070050class TargetARM32 : public TargetLowering {
51 TargetARM32() = delete;
52 TargetARM32(const TargetARM32 &) = delete;
53 TargetARM32 &operator=(const TargetARM32 &) = delete;
54
55public:
56 // TODO(jvoung): return a unique_ptr.
57 static TargetARM32 *create(Cfg *Func) { return new TargetARM32(Func); }
58
59 void translateOm1() override;
60 void translateO2() override;
61 bool doBranchOpt(Inst *I, const CfgNode *NextNode) override;
62
63 SizeT getNumRegisters() const override { return RegARM32::Reg_NUM; }
64 Variable *getPhysicalRegister(SizeT RegNum, Type Ty = IceType_void) override;
65 IceString getRegName(SizeT RegNum, Type Ty) const override;
66 llvm::SmallBitVector getRegisterSet(RegSetMask Include,
67 RegSetMask Exclude) const override;
68 const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const override {
69 return TypeToRegisterSet[Ty];
70 }
71 bool hasFramePointer() const override { return UsesFramePointer; }
72 SizeT getFrameOrStackReg() const override {
73 return UsesFramePointer ? RegARM32::Reg_fp : RegARM32::Reg_sp;
74 }
75 size_t typeWidthInBytesOnStack(Type Ty) const override {
76 // Round up to the next multiple of 4 bytes. In particular, i1,
77 // i8, and i16 are rounded up to 4 bytes.
78 return (typeWidthInBytes(Ty) + 3) & ~3;
79 }
Jan Voung0fa6c5a2015-06-01 11:04:04 -070080
Andrew Scull87f80c12015-07-20 10:19:16 -070081 // TODO(ascull): what size is best for ARM?
82 SizeT getMinJumpTableSize() const override { return 3; }
83
Jan Voungb36ad9b2015-04-21 17:01:49 -070084 void emitVariable(const Variable *Var) const override;
Jan Voung76bb0be2015-05-14 09:26:19 -070085
86 const char *getConstantPrefix() const final { return "#"; }
87 void emit(const ConstantUndef *C) const final;
88 void emit(const ConstantInteger32 *C) const final;
89 void emit(const ConstantInteger64 *C) const final;
90 void emit(const ConstantFloat *C) const final;
91 void emit(const ConstantDouble *C) const final;
92
Jan Voungb36ad9b2015-04-21 17:01:49 -070093 void lowerArguments() override;
94 void addProlog(CfgNode *Node) override;
95 void addEpilog(CfgNode *Node) override;
96
Andrew Scull9612d322015-07-06 14:53:25 -070097 /// Ensure that a 64-bit Variable has been split into 2 32-bit
98 /// Variables, creating them if necessary. This is needed for all
99 /// I64 operations.
Jan Voungb3401d22015-05-18 09:38:21 -0700100 void split64(Variable *Var);
101 Operand *loOperand(Operand *Operand);
102 Operand *hiOperand(Operand *Operand);
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700103 void finishArgumentLowering(Variable *Arg, Variable *FramePtr,
104 size_t BasicFrameOffset, size_t &InArgsSizeBytes);
Jan Voungb3401d22015-05-18 09:38:21 -0700105
Jan Voung6ec369e2015-06-30 11:03:15 -0700106 bool hasCPUFeature(TargetARM32Features::ARM32InstructionSet I) const {
107 return CPUFeatures.hasFeature(I);
108 }
Jan Voung53483692015-07-16 10:47:46 -0700109 Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister);
Jan Voungd062f732015-06-15 17:17:31 -0700110
Jan Voungb36ad9b2015-04-21 17:01:49 -0700111protected:
112 explicit TargetARM32(Cfg *Func);
113
114 void postLower() override;
115
116 void lowerAlloca(const InstAlloca *Inst) override;
117 void lowerArithmetic(const InstArithmetic *Inst) override;
118 void lowerAssign(const InstAssign *Inst) override;
119 void lowerBr(const InstBr *Inst) override;
120 void lowerCall(const InstCall *Inst) override;
121 void lowerCast(const InstCast *Inst) override;
122 void lowerExtractElement(const InstExtractElement *Inst) override;
123 void lowerFcmp(const InstFcmp *Inst) override;
124 void lowerIcmp(const InstIcmp *Inst) override;
125 void lowerIntrinsicCall(const InstIntrinsicCall *Inst) override;
126 void lowerInsertElement(const InstInsertElement *Inst) override;
127 void lowerLoad(const InstLoad *Inst) override;
128 void lowerPhi(const InstPhi *Inst) override;
129 void lowerRet(const InstRet *Inst) override;
130 void lowerSelect(const InstSelect *Inst) override;
131 void lowerStore(const InstStore *Inst) override;
132 void lowerSwitch(const InstSwitch *Inst) override;
133 void lowerUnreachable(const InstUnreachable *Inst) override;
134 void prelowerPhis() override;
135 void lowerPhiAssignments(CfgNode *Node,
136 const AssignList &Assignments) override;
137 void doAddressOptLoad() override;
138 void doAddressOptStore() override;
139 void randomlyInsertNop(float Probability) override;
Jan Voungb3401d22015-05-18 09:38:21 -0700140
141 enum OperandLegalization {
142 Legal_None = 0,
Andrew Scull9612d322015-07-06 14:53:25 -0700143 Legal_Reg = 1 << 0, /// physical register, not stack location
144 Legal_Flex = 1 << 1, /// A flexible operand2, which can hold rotated
145 /// small immediates, or shifted registers.
146 Legal_Mem = 1 << 2, /// includes [r0, r1 lsl #2] as well as [sp, #12]
Jan Voungb3401d22015-05-18 09:38:21 -0700147 Legal_All = ~Legal_None
148 };
149 typedef uint32_t LegalMask;
150 Operand *legalize(Operand *From, LegalMask Allowed = Legal_All,
151 int32_t RegNum = Variable::NoRegister);
152 Variable *legalizeToVar(Operand *From, int32_t RegNum = Variable::NoRegister);
Jan Voungbefd03a2015-06-02 11:03:03 -0700153 OperandARM32Mem *formMemoryOperand(Operand *Ptr, Type Ty);
Jan Voungb3401d22015-05-18 09:38:21 -0700154
155 Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister);
156 static Type stackSlotType();
157 Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister);
Jan Voung55500db2015-05-26 14:25:40 -0700158 void alignRegisterPow2(Variable *Reg, uint32_t Align);
Jan Voungb3401d22015-05-18 09:38:21 -0700159
Andrew Scull9612d322015-07-06 14:53:25 -0700160 /// Returns a vector in a register with the given constant entries.
Jan Voungb3401d22015-05-18 09:38:21 -0700161 Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister);
162
Jan Voungb36ad9b2015-04-21 17:01:49 -0700163 void makeRandomRegisterPermutation(
164 llvm::SmallVectorImpl<int32_t> &Permutation,
165 const llvm::SmallBitVector &ExcludeRegisters) const override;
166
Jan Voung6ec369e2015-06-30 11:03:15 -0700167 // If a divide-by-zero check is needed, inserts a:
168 // test; branch .LSKIP; trap; .LSKIP: <continuation>.
169 // If no check is needed nothing is inserted.
170 void div0Check(Type Ty, Operand *SrcLo, Operand *SrcHi);
171 typedef void (TargetARM32::*ExtInstr)(Variable *, Variable *,
172 CondARM32::Cond);
173 typedef void (TargetARM32::*DivInstr)(Variable *, Variable *, Variable *,
174 CondARM32::Cond);
175 void lowerIDivRem(Variable *Dest, Variable *T, Variable *Src0R, Operand *Src1,
176 ExtInstr ExtFunc, DivInstr DivFunc,
177 const char *DivHelperName, bool IsRemainder);
178
Jan Voungf645d852015-07-09 10:35:09 -0700179 void lowerCLZ(Variable *Dest, Variable *ValLo, Variable *ValHi);
180
Jan Voungb2d50842015-05-12 09:53:50 -0700181 // The following are helpers that insert lowered ARM32 instructions
182 // with minimal syntactic overhead, so that the lowering code can
183 // look as close to assembly as practical.
184
Jan Voung3bfd99a2015-05-22 16:35:25 -0700185 void _add(Variable *Dest, Variable *Src0, Operand *Src1,
186 CondARM32::Cond Pred = CondARM32::AL) {
187 Context.insert(InstARM32Add::create(Func, Dest, Src0, Src1, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700188 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700189 void _adds(Variable *Dest, Variable *Src0, Operand *Src1,
190 CondARM32::Cond Pred = CondARM32::AL) {
Jan Voung29719972015-05-19 11:24:51 -0700191 const bool SetFlags = true;
Jan Voung3bfd99a2015-05-22 16:35:25 -0700192 Context.insert(
193 InstARM32Add::create(Func, Dest, Src0, Src1, Pred, SetFlags));
Jan Voung29719972015-05-19 11:24:51 -0700194 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700195 void _adc(Variable *Dest, Variable *Src0, Operand *Src1,
196 CondARM32::Cond Pred = CondARM32::AL) {
197 Context.insert(InstARM32Adc::create(Func, Dest, Src0, Src1, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700198 }
Jan Voungb0a8c242015-06-18 15:00:14 -0700199 void _adjust_stack(int32_t Amount, Operand *SrcAmount) {
200 Context.insert(InstARM32AdjustStack::create(
201 Func, getPhysicalRegister(RegARM32::Reg_sp), Amount, SrcAmount));
202 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700203 void _and(Variable *Dest, Variable *Src0, Operand *Src1,
204 CondARM32::Cond Pred = CondARM32::AL) {
205 Context.insert(InstARM32And::create(Func, Dest, Src0, Src1, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700206 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700207 void _asr(Variable *Dest, Variable *Src0, Operand *Src1,
208 CondARM32::Cond Pred = CondARM32::AL) {
209 Context.insert(InstARM32Asr::create(Func, Dest, Src0, Src1, Pred));
210 }
Jan Voung55500db2015-05-26 14:25:40 -0700211 void _bic(Variable *Dest, Variable *Src0, Operand *Src1,
212 CondARM32::Cond Pred = CondARM32::AL) {
213 Context.insert(InstARM32Bic::create(Func, Dest, Src0, Src1, Pred));
214 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700215 void _br(CfgNode *TargetTrue, CfgNode *TargetFalse,
216 CondARM32::Cond Condition) {
Jan Voung3bfd99a2015-05-22 16:35:25 -0700217 Context.insert(
218 InstARM32Br::create(Func, TargetTrue, TargetFalse, Condition));
Jan Voung29719972015-05-19 11:24:51 -0700219 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700220 void _br(CfgNode *Target) {
221 Context.insert(InstARM32Br::create(Func, Target));
Jan Voungb3401d22015-05-18 09:38:21 -0700222 }
Andrew Scullfdc54db2015-06-29 11:21:18 -0700223 void _br(CfgNode *Target, CondARM32::Cond Condition) {
224 Context.insert(InstARM32Br::create(Func, Target, Condition));
225 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700226 void _br(InstARM32Label *Label, CondARM32::Cond Condition) {
227 Context.insert(InstARM32Br::create(Func, Label, Condition));
228 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700229 void _cmp(Variable *Src0, Operand *Src1,
230 CondARM32::Cond Pred = CondARM32::AL) {
231 Context.insert(InstARM32Cmp::create(Func, Src0, Src1, Pred));
232 }
Jan Voungf645d852015-07-09 10:35:09 -0700233 void _clz(Variable *Dest, Variable *Src0,
234 CondARM32::Cond Pred = CondARM32::AL) {
235 Context.insert(InstARM32Clz::create(Func, Dest, Src0, Pred));
236 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700237 void _eor(Variable *Dest, Variable *Src0, Operand *Src1,
238 CondARM32::Cond Pred = CondARM32::AL) {
239 Context.insert(InstARM32Eor::create(Func, Dest, Src0, Src1, Pred));
240 }
241 void _ldr(Variable *Dest, OperandARM32Mem *Addr,
242 CondARM32::Cond Pred = CondARM32::AL) {
243 Context.insert(InstARM32Ldr::create(Func, Dest, Addr, Pred));
244 }
245 void _lsl(Variable *Dest, Variable *Src0, Operand *Src1,
246 CondARM32::Cond Pred = CondARM32::AL) {
247 Context.insert(InstARM32Lsl::create(Func, Dest, Src0, Src1, Pred));
248 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700249 void _lsr(Variable *Dest, Variable *Src0, Operand *Src1,
250 CondARM32::Cond Pred = CondARM32::AL) {
251 Context.insert(InstARM32Lsr::create(Func, Dest, Src0, Src1, Pred));
252 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700253 void _mla(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc,
254 CondARM32::Cond Pred = CondARM32::AL) {
255 Context.insert(InstARM32Mla::create(Func, Dest, Src0, Src1, Acc, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700256 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700257 void _mls(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc,
258 CondARM32::Cond Pred = CondARM32::AL) {
259 Context.insert(InstARM32Mls::create(Func, Dest, Src0, Src1, Acc, Pred));
260 }
Andrew Scull9612d322015-07-06 14:53:25 -0700261 /// If Dest=nullptr is passed in, then a new variable is created,
262 /// marked as infinite register allocation weight, and returned
263 /// through the in/out Dest argument.
Jan Voungb3401d22015-05-18 09:38:21 -0700264 void _mov(Variable *&Dest, Operand *Src0,
Jan Voung3bfd99a2015-05-22 16:35:25 -0700265 CondARM32::Cond Pred = CondARM32::AL,
Jan Voungb3401d22015-05-18 09:38:21 -0700266 int32_t RegNum = Variable::NoRegister) {
267 if (Dest == nullptr)
268 Dest = makeReg(Src0->getType(), RegNum);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700269 Context.insert(InstARM32Mov::create(Func, Dest, Src0, Pred));
270 }
271 void _mov_nonkillable(Variable *Dest, Operand *Src0,
272 CondARM32::Cond Pred = CondARM32::AL) {
273 Inst *NewInst = InstARM32Mov::create(Func, Dest, Src0, Pred);
274 NewInst->setDestNonKillable();
275 Context.insert(NewInst);
Jan Voungb3401d22015-05-18 09:38:21 -0700276 }
Andrew Scull9612d322015-07-06 14:53:25 -0700277 /// The Operand can only be a 16-bit immediate or a ConstantRelocatable
278 /// (with an upper16 relocation).
Jan Voung3bfd99a2015-05-22 16:35:25 -0700279 void _movt(Variable *Dest, Operand *Src0,
280 CondARM32::Cond Pred = CondARM32::AL) {
281 Context.insert(InstARM32Movt::create(Func, Dest, Src0, Pred));
Jan Voungb3401d22015-05-18 09:38:21 -0700282 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700283 void _movw(Variable *Dest, Operand *Src0,
284 CondARM32::Cond Pred = CondARM32::AL) {
285 Context.insert(InstARM32Movw::create(Func, Dest, Src0, Pred));
Jan Voungb3401d22015-05-18 09:38:21 -0700286 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700287 void _mul(Variable *Dest, Variable *Src0, Variable *Src1,
288 CondARM32::Cond Pred = CondARM32::AL) {
289 Context.insert(InstARM32Mul::create(Func, Dest, Src0, Src1, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700290 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700291 void _mvn(Variable *Dest, Operand *Src0,
292 CondARM32::Cond Pred = CondARM32::AL) {
293 Context.insert(InstARM32Mvn::create(Func, Dest, Src0, Pred));
Jan Voungb3401d22015-05-18 09:38:21 -0700294 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700295 void _orr(Variable *Dest, Variable *Src0, Operand *Src1,
296 CondARM32::Cond Pred = CondARM32::AL) {
297 Context.insert(InstARM32Orr::create(Func, Dest, Src0, Src1, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700298 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700299 void _orrs(Variable *Dest, Variable *Src0, Operand *Src1,
300 CondARM32::Cond Pred = CondARM32::AL) {
301 const bool SetFlags = true;
302 Context.insert(
303 InstARM32Orr::create(Func, Dest, Src0, Src1, Pred, SetFlags));
304 }
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700305 void _push(const VarList &Sources) {
306 Context.insert(InstARM32Push::create(Func, Sources));
307 }
308 void _pop(const VarList &Dests) {
309 Context.insert(InstARM32Pop::create(Func, Dests));
310 // Mark dests as modified.
311 for (Variable *Dest : Dests)
312 Context.insert(InstFakeDef::create(Func, Dest));
313 }
Jan Voungf645d852015-07-09 10:35:09 -0700314 void _rbit(Variable *Dest, Variable *Src0,
315 CondARM32::Cond Pred = CondARM32::AL) {
316 Context.insert(InstARM32Rbit::create(Func, Dest, Src0, Pred));
317 }
318 void _rev(Variable *Dest, Variable *Src0,
319 CondARM32::Cond Pred = CondARM32::AL) {
320 Context.insert(InstARM32Rev::create(Func, Dest, Src0, Pred));
321 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700322 void _ret(Variable *LR, Variable *Src0 = nullptr) {
323 Context.insert(InstARM32Ret::create(Func, LR, Src0));
324 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700325 void _rsb(Variable *Dest, Variable *Src0, Operand *Src1,
326 CondARM32::Cond Pred = CondARM32::AL) {
327 Context.insert(InstARM32Rsb::create(Func, Dest, Src0, Src1, Pred));
328 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700329 void _sbc(Variable *Dest, Variable *Src0, Operand *Src1,
330 CondARM32::Cond Pred = CondARM32::AL) {
331 Context.insert(InstARM32Sbc::create(Func, Dest, Src0, Src1, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700332 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700333 void _sbcs(Variable *Dest, Variable *Src0, Operand *Src1,
334 CondARM32::Cond Pred = CondARM32::AL) {
Jan Voung29719972015-05-19 11:24:51 -0700335 const bool SetFlags = true;
Jan Voung3bfd99a2015-05-22 16:35:25 -0700336 Context.insert(
337 InstARM32Sbc::create(Func, Dest, Src0, Src1, Pred, SetFlags));
338 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700339 void _sdiv(Variable *Dest, Variable *Src0, Variable *Src1,
340 CondARM32::Cond Pred = CondARM32::AL) {
341 Context.insert(InstARM32Sdiv::create(Func, Dest, Src0, Src1, Pred));
342 }
Jan Voungbefd03a2015-06-02 11:03:03 -0700343 void _str(Variable *Value, OperandARM32Mem *Addr,
344 CondARM32::Cond Pred = CondARM32::AL) {
345 Context.insert(InstARM32Str::create(Func, Value, Addr, Pred));
346 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700347 void _sub(Variable *Dest, Variable *Src0, Operand *Src1,
348 CondARM32::Cond Pred = CondARM32::AL) {
349 Context.insert(InstARM32Sub::create(Func, Dest, Src0, Src1, Pred));
350 }
351 void _subs(Variable *Dest, Variable *Src0, Operand *Src1,
352 CondARM32::Cond Pred = CondARM32::AL) {
353 const bool SetFlags = true;
354 Context.insert(
355 InstARM32Sub::create(Func, Dest, Src0, Src1, Pred, SetFlags));
Jan Voung29719972015-05-19 11:24:51 -0700356 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700357 void _sxt(Variable *Dest, Variable *Src0,
358 CondARM32::Cond Pred = CondARM32::AL) {
359 Context.insert(InstARM32Sxt::create(Func, Dest, Src0, Pred));
360 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700361 void _tst(Variable *Src0, Operand *Src1,
362 CondARM32::Cond Pred = CondARM32::AL) {
363 Context.insert(InstARM32Tst::create(Func, Src0, Src1, Pred));
364 }
365 void _trap() { Context.insert(InstARM32Trap::create(Func)); }
366 void _udiv(Variable *Dest, Variable *Src0, Variable *Src1,
367 CondARM32::Cond Pred = CondARM32::AL) {
368 Context.insert(InstARM32Udiv::create(Func, Dest, Src0, Src1, Pred));
Jan Voungb2d50842015-05-12 09:53:50 -0700369 }
Jan Voung29719972015-05-19 11:24:51 -0700370 void _umull(Variable *DestLo, Variable *DestHi, Variable *Src0,
Jan Voung3bfd99a2015-05-22 16:35:25 -0700371 Variable *Src1, CondARM32::Cond Pred = CondARM32::AL) {
372 Context.insert(
373 InstARM32Umull::create(Func, DestLo, DestHi, Src0, Src1, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700374 // Model the modification to the second dest as a fake def.
Jan Voung3bfd99a2015-05-22 16:35:25 -0700375 // Note that the def is not predicated.
Jan Voung29719972015-05-19 11:24:51 -0700376 Context.insert(InstFakeDef::create(Func, DestHi, DestLo));
377 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700378 void _uxt(Variable *Dest, Variable *Src0,
379 CondARM32::Cond Pred = CondARM32::AL) {
380 Context.insert(InstARM32Uxt::create(Func, Dest, Src0, Pred));
381 }
Jan Voungb2d50842015-05-12 09:53:50 -0700382
Jan Voung6ec369e2015-06-30 11:03:15 -0700383 TargetARM32Features CPUFeatures;
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700384 bool UsesFramePointer = false;
385 bool NeedsStackAlignment = false;
386 bool MaybeLeafFunc = true;
387 size_t SpillAreaSizeBytes = 0;
Jan Voungb36ad9b2015-04-21 17:01:49 -0700388 llvm::SmallBitVector TypeToRegisterSet[IceType_NUM];
389 llvm::SmallBitVector ScratchRegs;
390 llvm::SmallBitVector RegsUsed;
391 VarList PhysicalRegisters[IceType_NUM];
392 static IceString RegNames[];
393
Andrew Scull9612d322015-07-06 14:53:25 -0700394 /// Helper class that understands the Calling Convention and register
395 /// assignments. The first few integer type parameters can use r0-r3,
396 /// regardless of their position relative to the floating-point/vector
397 /// arguments in the argument list. Floating-point and vector arguments
398 /// can use q0-q3 (aka d0-d7, s0-s15). Technically, arguments that can
399 /// start with registers but extend beyond the available registers can be
400 /// split between the registers and the stack. However, this is typically
401 /// for passing GPR structs by value, and PNaCl transforms expand this out.
402 ///
403 /// Also, at the point before the call, the stack must be aligned.
Jan Voungb0a8c242015-06-18 15:00:14 -0700404 class CallingConv {
405 CallingConv(const CallingConv &) = delete;
406 CallingConv &operator=(const CallingConv &) = delete;
407
408 public:
409 CallingConv() : NumGPRRegsUsed(0) {}
410 ~CallingConv() = default;
411
412 bool I64InRegs(std::pair<int32_t, int32_t> *Regs);
413 bool I32InReg(int32_t *Reg);
414
415 static constexpr uint32_t ARM32_MAX_GPR_ARG = 4;
416
417 private:
418 uint32_t NumGPRRegsUsed;
419 };
420
Jan Voungb36ad9b2015-04-21 17:01:49 -0700421private:
Jim Stichnothe587d942015-06-22 15:49:04 -0700422 ~TargetARM32() override = default;
Jan Voungb36ad9b2015-04-21 17:01:49 -0700423};
424
John Porto0f86d032015-06-15 07:44:27 -0700425class TargetDataARM32 final : public TargetDataLowering {
Jan Voungb36ad9b2015-04-21 17:01:49 -0700426 TargetDataARM32() = delete;
427 TargetDataARM32(const TargetDataARM32 &) = delete;
428 TargetDataARM32 &operator=(const TargetDataARM32 &) = delete;
429
430public:
Jan Voungfb792842015-06-11 15:27:50 -0700431 static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) {
432 return std::unique_ptr<TargetDataLowering>(new TargetDataARM32(Ctx));
Jan Voungb36ad9b2015-04-21 17:01:49 -0700433 }
434
John Porto8b1a7052015-06-17 13:20:08 -0700435 void lowerGlobals(const VariableDeclarationList &Vars,
436 const IceString &SectionSuffix) override;
John Porto0f86d032015-06-15 07:44:27 -0700437 void lowerConstants() override;
Jan Voungb36ad9b2015-04-21 17:01:49 -0700438
439protected:
440 explicit TargetDataARM32(GlobalContext *Ctx);
441
442private:
Jim Stichnothe587d942015-06-22 15:49:04 -0700443 ~TargetDataARM32() override = default;
Jan Voungb36ad9b2015-04-21 17:01:49 -0700444 template <typename T> static void emitConstantPool(GlobalContext *Ctx);
445};
446
Jan Voungfb792842015-06-11 15:27:50 -0700447class TargetHeaderARM32 final : public TargetHeaderLowering {
448 TargetHeaderARM32() = delete;
449 TargetHeaderARM32(const TargetHeaderARM32 &) = delete;
450 TargetHeaderARM32 &operator=(const TargetHeaderARM32 &) = delete;
451
452public:
453 static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) {
454 return std::unique_ptr<TargetHeaderLowering>(new TargetHeaderARM32(Ctx));
455 }
456
John Porto0f86d032015-06-15 07:44:27 -0700457 void lower() override;
Jan Voungfb792842015-06-11 15:27:50 -0700458
459protected:
460 explicit TargetHeaderARM32(GlobalContext *Ctx);
461
462private:
463 ~TargetHeaderARM32() = default;
Jan Voung6ec369e2015-06-30 11:03:15 -0700464
465 TargetARM32Features CPUFeatures;
Jan Voungfb792842015-06-11 15:27:50 -0700466};
467
Jan Voungb36ad9b2015-04-21 17:01:49 -0700468} // end of namespace Ice
469
470#endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H