blob: 87faf01567cac99c86b5ec629768adcc7d0854dc [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
Jan Voungb36ad9b2015-04-21 17:01:49 -070081 void emitVariable(const Variable *Var) const override;
Jan Voung76bb0be2015-05-14 09:26:19 -070082
83 const char *getConstantPrefix() const final { return "#"; }
84 void emit(const ConstantUndef *C) const final;
85 void emit(const ConstantInteger32 *C) const final;
86 void emit(const ConstantInteger64 *C) const final;
87 void emit(const ConstantFloat *C) const final;
88 void emit(const ConstantDouble *C) const final;
89
Jan Voungb36ad9b2015-04-21 17:01:49 -070090 void lowerArguments() override;
91 void addProlog(CfgNode *Node) override;
92 void addEpilog(CfgNode *Node) override;
93
Andrew Scull9612d322015-07-06 14:53:25 -070094 /// Ensure that a 64-bit Variable has been split into 2 32-bit
95 /// Variables, creating them if necessary. This is needed for all
96 /// I64 operations.
Jan Voungb3401d22015-05-18 09:38:21 -070097 void split64(Variable *Var);
98 Operand *loOperand(Operand *Operand);
99 Operand *hiOperand(Operand *Operand);
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700100 void finishArgumentLowering(Variable *Arg, Variable *FramePtr,
101 size_t BasicFrameOffset, size_t &InArgsSizeBytes);
Jan Voungb3401d22015-05-18 09:38:21 -0700102
Jan Voung6ec369e2015-06-30 11:03:15 -0700103 bool hasCPUFeature(TargetARM32Features::ARM32InstructionSet I) const {
104 return CPUFeatures.hasFeature(I);
105 }
Jan Voung53483692015-07-16 10:47:46 -0700106 Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister);
Jan Voungd062f732015-06-15 17:17:31 -0700107
Jan Voungb36ad9b2015-04-21 17:01:49 -0700108protected:
109 explicit TargetARM32(Cfg *Func);
110
111 void postLower() override;
112
113 void lowerAlloca(const InstAlloca *Inst) override;
114 void lowerArithmetic(const InstArithmetic *Inst) override;
115 void lowerAssign(const InstAssign *Inst) override;
116 void lowerBr(const InstBr *Inst) override;
117 void lowerCall(const InstCall *Inst) override;
118 void lowerCast(const InstCast *Inst) override;
119 void lowerExtractElement(const InstExtractElement *Inst) override;
120 void lowerFcmp(const InstFcmp *Inst) override;
121 void lowerIcmp(const InstIcmp *Inst) override;
122 void lowerIntrinsicCall(const InstIntrinsicCall *Inst) override;
123 void lowerInsertElement(const InstInsertElement *Inst) override;
124 void lowerLoad(const InstLoad *Inst) override;
125 void lowerPhi(const InstPhi *Inst) override;
126 void lowerRet(const InstRet *Inst) override;
127 void lowerSelect(const InstSelect *Inst) override;
128 void lowerStore(const InstStore *Inst) override;
129 void lowerSwitch(const InstSwitch *Inst) override;
130 void lowerUnreachable(const InstUnreachable *Inst) override;
131 void prelowerPhis() override;
132 void lowerPhiAssignments(CfgNode *Node,
133 const AssignList &Assignments) override;
134 void doAddressOptLoad() override;
135 void doAddressOptStore() override;
136 void randomlyInsertNop(float Probability) override;
Jan Voungb3401d22015-05-18 09:38:21 -0700137
138 enum OperandLegalization {
139 Legal_None = 0,
Andrew Scull9612d322015-07-06 14:53:25 -0700140 Legal_Reg = 1 << 0, /// physical register, not stack location
141 Legal_Flex = 1 << 1, /// A flexible operand2, which can hold rotated
142 /// small immediates, or shifted registers.
143 Legal_Mem = 1 << 2, /// includes [r0, r1 lsl #2] as well as [sp, #12]
Jan Voungb3401d22015-05-18 09:38:21 -0700144 Legal_All = ~Legal_None
145 };
146 typedef uint32_t LegalMask;
147 Operand *legalize(Operand *From, LegalMask Allowed = Legal_All,
148 int32_t RegNum = Variable::NoRegister);
149 Variable *legalizeToVar(Operand *From, int32_t RegNum = Variable::NoRegister);
Jan Voungbefd03a2015-06-02 11:03:03 -0700150 OperandARM32Mem *formMemoryOperand(Operand *Ptr, Type Ty);
Jan Voungb3401d22015-05-18 09:38:21 -0700151
152 Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister);
153 static Type stackSlotType();
154 Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister);
Jan Voung55500db2015-05-26 14:25:40 -0700155 void alignRegisterPow2(Variable *Reg, uint32_t Align);
Jan Voungb3401d22015-05-18 09:38:21 -0700156
Andrew Scull9612d322015-07-06 14:53:25 -0700157 /// Returns a vector in a register with the given constant entries.
Jan Voungb3401d22015-05-18 09:38:21 -0700158 Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister);
159
Jan Voungb36ad9b2015-04-21 17:01:49 -0700160 void makeRandomRegisterPermutation(
161 llvm::SmallVectorImpl<int32_t> &Permutation,
162 const llvm::SmallBitVector &ExcludeRegisters) const override;
163
Jan Voung6ec369e2015-06-30 11:03:15 -0700164 // If a divide-by-zero check is needed, inserts a:
165 // test; branch .LSKIP; trap; .LSKIP: <continuation>.
166 // If no check is needed nothing is inserted.
167 void div0Check(Type Ty, Operand *SrcLo, Operand *SrcHi);
168 typedef void (TargetARM32::*ExtInstr)(Variable *, Variable *,
169 CondARM32::Cond);
170 typedef void (TargetARM32::*DivInstr)(Variable *, Variable *, Variable *,
171 CondARM32::Cond);
172 void lowerIDivRem(Variable *Dest, Variable *T, Variable *Src0R, Operand *Src1,
173 ExtInstr ExtFunc, DivInstr DivFunc,
174 const char *DivHelperName, bool IsRemainder);
175
Jan Voungf645d852015-07-09 10:35:09 -0700176 void lowerCLZ(Variable *Dest, Variable *ValLo, Variable *ValHi);
177
Jan Voungb2d50842015-05-12 09:53:50 -0700178 // The following are helpers that insert lowered ARM32 instructions
179 // with minimal syntactic overhead, so that the lowering code can
180 // look as close to assembly as practical.
181
Jan Voung3bfd99a2015-05-22 16:35:25 -0700182 void _add(Variable *Dest, Variable *Src0, Operand *Src1,
183 CondARM32::Cond Pred = CondARM32::AL) {
184 Context.insert(InstARM32Add::create(Func, Dest, Src0, Src1, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700185 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700186 void _adds(Variable *Dest, Variable *Src0, Operand *Src1,
187 CondARM32::Cond Pred = CondARM32::AL) {
Jan Voung29719972015-05-19 11:24:51 -0700188 const bool SetFlags = true;
Jan Voung3bfd99a2015-05-22 16:35:25 -0700189 Context.insert(
190 InstARM32Add::create(Func, Dest, Src0, Src1, Pred, SetFlags));
Jan Voung29719972015-05-19 11:24:51 -0700191 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700192 void _adc(Variable *Dest, Variable *Src0, Operand *Src1,
193 CondARM32::Cond Pred = CondARM32::AL) {
194 Context.insert(InstARM32Adc::create(Func, Dest, Src0, Src1, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700195 }
Jan Voungb0a8c242015-06-18 15:00:14 -0700196 void _adjust_stack(int32_t Amount, Operand *SrcAmount) {
197 Context.insert(InstARM32AdjustStack::create(
198 Func, getPhysicalRegister(RegARM32::Reg_sp), Amount, SrcAmount));
199 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700200 void _and(Variable *Dest, Variable *Src0, Operand *Src1,
201 CondARM32::Cond Pred = CondARM32::AL) {
202 Context.insert(InstARM32And::create(Func, Dest, Src0, Src1, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700203 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700204 void _asr(Variable *Dest, Variable *Src0, Operand *Src1,
205 CondARM32::Cond Pred = CondARM32::AL) {
206 Context.insert(InstARM32Asr::create(Func, Dest, Src0, Src1, Pred));
207 }
Jan Voung55500db2015-05-26 14:25:40 -0700208 void _bic(Variable *Dest, Variable *Src0, Operand *Src1,
209 CondARM32::Cond Pred = CondARM32::AL) {
210 Context.insert(InstARM32Bic::create(Func, Dest, Src0, Src1, Pred));
211 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700212 void _br(CfgNode *TargetTrue, CfgNode *TargetFalse,
213 CondARM32::Cond Condition) {
Jan Voung3bfd99a2015-05-22 16:35:25 -0700214 Context.insert(
215 InstARM32Br::create(Func, TargetTrue, TargetFalse, Condition));
Jan Voung29719972015-05-19 11:24:51 -0700216 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700217 void _br(CfgNode *Target) {
218 Context.insert(InstARM32Br::create(Func, Target));
Jan Voungb3401d22015-05-18 09:38:21 -0700219 }
Andrew Scullfdc54db2015-06-29 11:21:18 -0700220 void _br(CfgNode *Target, CondARM32::Cond Condition) {
221 Context.insert(InstARM32Br::create(Func, Target, Condition));
222 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700223 void _br(InstARM32Label *Label, CondARM32::Cond Condition) {
224 Context.insert(InstARM32Br::create(Func, Label, Condition));
225 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700226 void _cmp(Variable *Src0, Operand *Src1,
227 CondARM32::Cond Pred = CondARM32::AL) {
228 Context.insert(InstARM32Cmp::create(Func, Src0, Src1, Pred));
229 }
Jan Voungf645d852015-07-09 10:35:09 -0700230 void _clz(Variable *Dest, Variable *Src0,
231 CondARM32::Cond Pred = CondARM32::AL) {
232 Context.insert(InstARM32Clz::create(Func, Dest, Src0, Pred));
233 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700234 void _eor(Variable *Dest, Variable *Src0, Operand *Src1,
235 CondARM32::Cond Pred = CondARM32::AL) {
236 Context.insert(InstARM32Eor::create(Func, Dest, Src0, Src1, Pred));
237 }
238 void _ldr(Variable *Dest, OperandARM32Mem *Addr,
239 CondARM32::Cond Pred = CondARM32::AL) {
240 Context.insert(InstARM32Ldr::create(Func, Dest, Addr, Pred));
241 }
242 void _lsl(Variable *Dest, Variable *Src0, Operand *Src1,
243 CondARM32::Cond Pred = CondARM32::AL) {
244 Context.insert(InstARM32Lsl::create(Func, Dest, Src0, Src1, Pred));
245 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700246 void _lsr(Variable *Dest, Variable *Src0, Operand *Src1,
247 CondARM32::Cond Pred = CondARM32::AL) {
248 Context.insert(InstARM32Lsr::create(Func, Dest, Src0, Src1, Pred));
249 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700250 void _mla(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc,
251 CondARM32::Cond Pred = CondARM32::AL) {
252 Context.insert(InstARM32Mla::create(Func, Dest, Src0, Src1, Acc, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700253 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700254 void _mls(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc,
255 CondARM32::Cond Pred = CondARM32::AL) {
256 Context.insert(InstARM32Mls::create(Func, Dest, Src0, Src1, Acc, Pred));
257 }
Andrew Scull9612d322015-07-06 14:53:25 -0700258 /// If Dest=nullptr is passed in, then a new variable is created,
259 /// marked as infinite register allocation weight, and returned
260 /// through the in/out Dest argument.
Jan Voungb3401d22015-05-18 09:38:21 -0700261 void _mov(Variable *&Dest, Operand *Src0,
Jan Voung3bfd99a2015-05-22 16:35:25 -0700262 CondARM32::Cond Pred = CondARM32::AL,
Jan Voungb3401d22015-05-18 09:38:21 -0700263 int32_t RegNum = Variable::NoRegister) {
264 if (Dest == nullptr)
265 Dest = makeReg(Src0->getType(), RegNum);
Jan Voung3bfd99a2015-05-22 16:35:25 -0700266 Context.insert(InstARM32Mov::create(Func, Dest, Src0, Pred));
267 }
268 void _mov_nonkillable(Variable *Dest, Operand *Src0,
269 CondARM32::Cond Pred = CondARM32::AL) {
270 Inst *NewInst = InstARM32Mov::create(Func, Dest, Src0, Pred);
271 NewInst->setDestNonKillable();
272 Context.insert(NewInst);
Jan Voungb3401d22015-05-18 09:38:21 -0700273 }
Andrew Scull9612d322015-07-06 14:53:25 -0700274 /// The Operand can only be a 16-bit immediate or a ConstantRelocatable
275 /// (with an upper16 relocation).
Jan Voung3bfd99a2015-05-22 16:35:25 -0700276 void _movt(Variable *Dest, Operand *Src0,
277 CondARM32::Cond Pred = CondARM32::AL) {
278 Context.insert(InstARM32Movt::create(Func, Dest, Src0, Pred));
Jan Voungb3401d22015-05-18 09:38:21 -0700279 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700280 void _movw(Variable *Dest, Operand *Src0,
281 CondARM32::Cond Pred = CondARM32::AL) {
282 Context.insert(InstARM32Movw::create(Func, Dest, Src0, Pred));
Jan Voungb3401d22015-05-18 09:38:21 -0700283 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700284 void _mul(Variable *Dest, Variable *Src0, Variable *Src1,
285 CondARM32::Cond Pred = CondARM32::AL) {
286 Context.insert(InstARM32Mul::create(Func, Dest, Src0, Src1, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700287 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700288 void _mvn(Variable *Dest, Operand *Src0,
289 CondARM32::Cond Pred = CondARM32::AL) {
290 Context.insert(InstARM32Mvn::create(Func, Dest, Src0, Pred));
Jan Voungb3401d22015-05-18 09:38:21 -0700291 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700292 void _orr(Variable *Dest, Variable *Src0, Operand *Src1,
293 CondARM32::Cond Pred = CondARM32::AL) {
294 Context.insert(InstARM32Orr::create(Func, Dest, Src0, Src1, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700295 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700296 void _orrs(Variable *Dest, Variable *Src0, Operand *Src1,
297 CondARM32::Cond Pred = CondARM32::AL) {
298 const bool SetFlags = true;
299 Context.insert(
300 InstARM32Orr::create(Func, Dest, Src0, Src1, Pred, SetFlags));
301 }
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700302 void _push(const VarList &Sources) {
303 Context.insert(InstARM32Push::create(Func, Sources));
304 }
305 void _pop(const VarList &Dests) {
306 Context.insert(InstARM32Pop::create(Func, Dests));
307 // Mark dests as modified.
308 for (Variable *Dest : Dests)
309 Context.insert(InstFakeDef::create(Func, Dest));
310 }
Jan Voungf645d852015-07-09 10:35:09 -0700311 void _rbit(Variable *Dest, Variable *Src0,
312 CondARM32::Cond Pred = CondARM32::AL) {
313 Context.insert(InstARM32Rbit::create(Func, Dest, Src0, Pred));
314 }
315 void _rev(Variable *Dest, Variable *Src0,
316 CondARM32::Cond Pred = CondARM32::AL) {
317 Context.insert(InstARM32Rev::create(Func, Dest, Src0, Pred));
318 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700319 void _ret(Variable *LR, Variable *Src0 = nullptr) {
320 Context.insert(InstARM32Ret::create(Func, LR, Src0));
321 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700322 void _rsb(Variable *Dest, Variable *Src0, Operand *Src1,
323 CondARM32::Cond Pred = CondARM32::AL) {
324 Context.insert(InstARM32Rsb::create(Func, Dest, Src0, Src1, Pred));
325 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700326 void _sbc(Variable *Dest, Variable *Src0, Operand *Src1,
327 CondARM32::Cond Pred = CondARM32::AL) {
328 Context.insert(InstARM32Sbc::create(Func, Dest, Src0, Src1, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700329 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700330 void _sbcs(Variable *Dest, Variable *Src0, Operand *Src1,
331 CondARM32::Cond Pred = CondARM32::AL) {
Jan Voung29719972015-05-19 11:24:51 -0700332 const bool SetFlags = true;
Jan Voung3bfd99a2015-05-22 16:35:25 -0700333 Context.insert(
334 InstARM32Sbc::create(Func, Dest, Src0, Src1, Pred, SetFlags));
335 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700336 void _sdiv(Variable *Dest, Variable *Src0, Variable *Src1,
337 CondARM32::Cond Pred = CondARM32::AL) {
338 Context.insert(InstARM32Sdiv::create(Func, Dest, Src0, Src1, Pred));
339 }
Jan Voungbefd03a2015-06-02 11:03:03 -0700340 void _str(Variable *Value, OperandARM32Mem *Addr,
341 CondARM32::Cond Pred = CondARM32::AL) {
342 Context.insert(InstARM32Str::create(Func, Value, Addr, Pred));
343 }
Jan Voung3bfd99a2015-05-22 16:35:25 -0700344 void _sub(Variable *Dest, Variable *Src0, Operand *Src1,
345 CondARM32::Cond Pred = CondARM32::AL) {
346 Context.insert(InstARM32Sub::create(Func, Dest, Src0, Src1, Pred));
347 }
348 void _subs(Variable *Dest, Variable *Src0, Operand *Src1,
349 CondARM32::Cond Pred = CondARM32::AL) {
350 const bool SetFlags = true;
351 Context.insert(
352 InstARM32Sub::create(Func, Dest, Src0, Src1, Pred, SetFlags));
Jan Voung29719972015-05-19 11:24:51 -0700353 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700354 void _sxt(Variable *Dest, Variable *Src0,
355 CondARM32::Cond Pred = CondARM32::AL) {
356 Context.insert(InstARM32Sxt::create(Func, Dest, Src0, Pred));
357 }
Jan Voung6ec369e2015-06-30 11:03:15 -0700358 void _tst(Variable *Src0, Operand *Src1,
359 CondARM32::Cond Pred = CondARM32::AL) {
360 Context.insert(InstARM32Tst::create(Func, Src0, Src1, Pred));
361 }
362 void _trap() { Context.insert(InstARM32Trap::create(Func)); }
363 void _udiv(Variable *Dest, Variable *Src0, Variable *Src1,
364 CondARM32::Cond Pred = CondARM32::AL) {
365 Context.insert(InstARM32Udiv::create(Func, Dest, Src0, Src1, Pred));
Jan Voungb2d50842015-05-12 09:53:50 -0700366 }
Jan Voung29719972015-05-19 11:24:51 -0700367 void _umull(Variable *DestLo, Variable *DestHi, Variable *Src0,
Jan Voung3bfd99a2015-05-22 16:35:25 -0700368 Variable *Src1, CondARM32::Cond Pred = CondARM32::AL) {
369 Context.insert(
370 InstARM32Umull::create(Func, DestLo, DestHi, Src0, Src1, Pred));
Jan Voung29719972015-05-19 11:24:51 -0700371 // Model the modification to the second dest as a fake def.
Jan Voung3bfd99a2015-05-22 16:35:25 -0700372 // Note that the def is not predicated.
Jan Voung29719972015-05-19 11:24:51 -0700373 Context.insert(InstFakeDef::create(Func, DestHi, DestLo));
374 }
Jan Voung66c3d5e2015-06-04 17:02:31 -0700375 void _uxt(Variable *Dest, Variable *Src0,
376 CondARM32::Cond Pred = CondARM32::AL) {
377 Context.insert(InstARM32Uxt::create(Func, Dest, Src0, Pred));
378 }
Jan Voungb2d50842015-05-12 09:53:50 -0700379
Jan Voung6ec369e2015-06-30 11:03:15 -0700380 TargetARM32Features CPUFeatures;
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700381 bool UsesFramePointer = false;
382 bool NeedsStackAlignment = false;
383 bool MaybeLeafFunc = true;
384 size_t SpillAreaSizeBytes = 0;
Jan Voungb36ad9b2015-04-21 17:01:49 -0700385 llvm::SmallBitVector TypeToRegisterSet[IceType_NUM];
386 llvm::SmallBitVector ScratchRegs;
387 llvm::SmallBitVector RegsUsed;
388 VarList PhysicalRegisters[IceType_NUM];
389 static IceString RegNames[];
390
Andrew Scull9612d322015-07-06 14:53:25 -0700391 /// Helper class that understands the Calling Convention and register
392 /// assignments. The first few integer type parameters can use r0-r3,
393 /// regardless of their position relative to the floating-point/vector
394 /// arguments in the argument list. Floating-point and vector arguments
395 /// can use q0-q3 (aka d0-d7, s0-s15). Technically, arguments that can
396 /// start with registers but extend beyond the available registers can be
397 /// split between the registers and the stack. However, this is typically
398 /// for passing GPR structs by value, and PNaCl transforms expand this out.
399 ///
400 /// Also, at the point before the call, the stack must be aligned.
Jan Voungb0a8c242015-06-18 15:00:14 -0700401 class CallingConv {
402 CallingConv(const CallingConv &) = delete;
403 CallingConv &operator=(const CallingConv &) = delete;
404
405 public:
406 CallingConv() : NumGPRRegsUsed(0) {}
407 ~CallingConv() = default;
408
409 bool I64InRegs(std::pair<int32_t, int32_t> *Regs);
410 bool I32InReg(int32_t *Reg);
411
412 static constexpr uint32_t ARM32_MAX_GPR_ARG = 4;
413
414 private:
415 uint32_t NumGPRRegsUsed;
416 };
417
Jan Voungb36ad9b2015-04-21 17:01:49 -0700418private:
Jim Stichnothe587d942015-06-22 15:49:04 -0700419 ~TargetARM32() override = default;
Jan Voungb36ad9b2015-04-21 17:01:49 -0700420};
421
John Porto0f86d032015-06-15 07:44:27 -0700422class TargetDataARM32 final : public TargetDataLowering {
Jan Voungb36ad9b2015-04-21 17:01:49 -0700423 TargetDataARM32() = delete;
424 TargetDataARM32(const TargetDataARM32 &) = delete;
425 TargetDataARM32 &operator=(const TargetDataARM32 &) = delete;
426
427public:
Jan Voungfb792842015-06-11 15:27:50 -0700428 static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) {
429 return std::unique_ptr<TargetDataLowering>(new TargetDataARM32(Ctx));
Jan Voungb36ad9b2015-04-21 17:01:49 -0700430 }
431
John Porto8b1a7052015-06-17 13:20:08 -0700432 void lowerGlobals(const VariableDeclarationList &Vars,
433 const IceString &SectionSuffix) override;
John Porto0f86d032015-06-15 07:44:27 -0700434 void lowerConstants() override;
Jan Voungb36ad9b2015-04-21 17:01:49 -0700435
436protected:
437 explicit TargetDataARM32(GlobalContext *Ctx);
438
439private:
Jim Stichnothe587d942015-06-22 15:49:04 -0700440 ~TargetDataARM32() override = default;
Jan Voungb36ad9b2015-04-21 17:01:49 -0700441 template <typename T> static void emitConstantPool(GlobalContext *Ctx);
442};
443
Jan Voungfb792842015-06-11 15:27:50 -0700444class TargetHeaderARM32 final : public TargetHeaderLowering {
445 TargetHeaderARM32() = delete;
446 TargetHeaderARM32(const TargetHeaderARM32 &) = delete;
447 TargetHeaderARM32 &operator=(const TargetHeaderARM32 &) = delete;
448
449public:
450 static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) {
451 return std::unique_ptr<TargetHeaderLowering>(new TargetHeaderARM32(Ctx));
452 }
453
John Porto0f86d032015-06-15 07:44:27 -0700454 void lower() override;
Jan Voungfb792842015-06-11 15:27:50 -0700455
456protected:
457 explicit TargetHeaderARM32(GlobalContext *Ctx);
458
459private:
460 ~TargetHeaderARM32() = default;
Jan Voung6ec369e2015-06-30 11:03:15 -0700461
462 TargetARM32Features CPUFeatures;
Jan Voungfb792842015-06-11 15:27:50 -0700463};
464
Jan Voungb36ad9b2015-04-21 17:01:49 -0700465} // end of namespace Ice
466
467#endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H