1//===- subzero/src/IceTargetLoweringMIPS32.h - MIPS32 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//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief Declares the TargetLoweringMIPS32 class, which implements the
12/// TargetLowering interface for the MIPS 32-bit architecture.
13///
14//===----------------------------------------------------------------------===//
15
16#ifndef SUBZERO_SRC_ICETARGETLOWERINGMIPS32_H
17#define SUBZERO_SRC_ICETARGETLOWERINGMIPS32_H
18
19#include "IceAssemblerMIPS32.h"
20#include "IceDefs.h"
21#include "IceInstMIPS32.h"
22#include "IceRegistersMIPS32.h"
23#include "IceTargetLowering.h"
24
25namespace Ice {
26namespace MIPS32 {
27
28class TargetMIPS32 : public TargetLowering {
29  TargetMIPS32() = delete;
30  TargetMIPS32(const TargetMIPS32 &) = delete;
31  TargetMIPS32 &operator=(const TargetMIPS32 &) = delete;
32
33public:
34  ~TargetMIPS32() override = default;
35
36  static void staticInit(GlobalContext *Ctx);
37  static bool shouldBePooled(const Constant *C) {
38    if (auto *ConstDouble = llvm::dyn_cast<ConstantDouble>(C)) {
39      return !Utils::isPositiveZero(ConstDouble->getValue());
40    }
41    if (auto *ConstFloat = llvm::dyn_cast<ConstantFloat>(C)) {
42      return !Utils::isPositiveZero(ConstFloat->getValue());
43    }
44    return false;
45  }
46  static ::Ice::Type getPointerType() { return ::Ice::IceType_i32; }
47  static std::unique_ptr<::Ice::TargetLowering> create(Cfg *Func) {
48    return makeUnique<TargetMIPS32>(Func);
49  }
50
51  std::unique_ptr<::Ice::Assembler> createAssembler() const override {
52    return makeUnique<MIPS32::AssemblerMIPS32>();
53  }
54
55  void initNodeForLowering(CfgNode *Node) override {
56    Computations.forgetProducers();
57    Computations.recordProducers(Node);
58    Computations.dump(Func);
59  }
60
61  void translateOm1() override;
62  void translateO2() override;
63  bool doBranchOpt(Inst *Instr, const CfgNode *NextNode) override;
64  void setImplicitRet(Variable *Ret) { ImplicitRet = Ret; }
65  Variable *getImplicitRet() const { return ImplicitRet; }
66  SizeT getNumRegisters() const override { return RegMIPS32::Reg_NUM; }
67  Variable *getPhysicalRegister(RegNumT RegNum,
68                                Type Ty = IceType_void) override;
69  const char *getRegName(RegNumT RegNum, Type Ty) const override;
70  SmallBitVector getRegisterSet(RegSetMask Include,
71                                RegSetMask Exclude) const override;
72  const SmallBitVector &
73  getRegistersForVariable(const Variable *Var) const override {
74    RegClass RC = Var->getRegClass();
75    assert(RC < RC_Target);
76    return TypeToRegisterSet[RC];
77  }
78  const SmallBitVector &
79  getAllRegistersForVariable(const Variable *Var) const override {
80    RegClass RC = Var->getRegClass();
81    assert(RC < RC_Target);
82    return TypeToRegisterSetUnfiltered[RC];
83  }
84  const SmallBitVector &getAliasesForRegister(RegNumT Reg) const override {
85    return RegisterAliases[Reg];
86  }
87  bool hasFramePointer() const override { return UsesFramePointer; }
88  void setHasFramePointer() override { UsesFramePointer = true; }
89  RegNumT getStackReg() const override { return RegMIPS32::Reg_SP; }
90  RegNumT getFrameReg() const override { return RegMIPS32::Reg_FP; }
91  RegNumT getFrameOrStackReg() const override {
92    return UsesFramePointer ? getFrameReg() : getStackReg();
93  }
94  RegNumT getReservedTmpReg() const { return RegMIPS32::Reg_AT; }
95  size_t typeWidthInBytesOnStack(Type Ty) const override {
96    // Round up to the next multiple of 4 bytes. In particular, i1, i8, and i16
97    // are rounded up to 4 bytes.
98    return (typeWidthInBytes(Ty) + 3) & ~3;
99  }
100  uint32_t getStackAlignment() const override;
101  void reserveFixedAllocaArea(size_t Size, size_t Align) override {
102    FixedAllocaSizeBytes = Size;
103    assert(llvm::isPowerOf2_32(Align));
104    FixedAllocaAlignBytes = Align;
105    PrologEmitsFixedAllocas = true;
106  }
107  int32_t getFrameFixedAllocaOffset() const override {
108    int32_t FixedAllocaOffset =
109        Utils::applyAlignment(CurrentAllocaOffset, FixedAllocaAlignBytes);
110    return FixedAllocaOffset - MaxOutArgsSizeBytes;
111  }
112
113  uint32_t maxOutArgsSizeBytes() const override { return MaxOutArgsSizeBytes; }
114
115  uint32_t getFramePointerOffset(uint32_t CurrentOffset,
116                                 uint32_t Size) const override {
117    (void)Size;
118    return CurrentOffset + MaxOutArgsSizeBytes;
119  }
120
121  bool shouldSplitToVariable64On32(Type Ty) const override {
122    return Ty == IceType_i64;
123  }
124
125  bool shouldSplitToVariableVecOn32(Type Ty) const override {
126    return isVectorType(Ty);
127  }
128
129  // TODO(ascull): what is the best size of MIPS?
130  SizeT getMinJumpTableSize() const override { return 3; }
131  void emitJumpTable(const Cfg *Func,
132                     const InstJumpTable *JumpTable) const override;
133
134  void emitVariable(const Variable *Var) const override;
135
136  void emit(const ConstantInteger32 *C) const final {
137    if (!BuildDefs::dump())
138      return;
139    Ostream &Str = Ctx->getStrEmit();
140    Str << C->getValue();
141  }
142  void emit(const ConstantInteger64 *C) const final {
143    (void)C;
144    llvm::report_fatal_error("Not yet implemented");
145  }
146  void emit(const ConstantFloat *C) const final {
147    (void)C;
148    llvm::report_fatal_error("Not yet implemented");
149  }
150  void emit(const ConstantDouble *C) const final {
151    (void)C;
152    llvm::report_fatal_error("Not yet implemented");
153  }
154  void emit(const ConstantUndef *C) const final {
155    (void)C;
156    llvm::report_fatal_error("Not yet implemented");
157  }
158  void emit(const ConstantRelocatable *C) const final {
159    (void)C;
160    llvm::report_fatal_error("Not yet implemented");
161  }
162
163  // The following are helpers that insert lowered MIPS32 instructions with
164  // minimal syntactic overhead, so that the lowering code can look as close to
165  // assembly as practical.
166  void _add(Variable *Dest, Variable *Src0, Variable *Src1) {
167    Context.insert<InstMIPS32Add>(Dest, Src0, Src1);
168  }
169
170  void _addu(Variable *Dest, Variable *Src0, Variable *Src1) {
171    Context.insert<InstMIPS32Addu>(Dest, Src0, Src1);
172  }
173
174  void _and(Variable *Dest, Variable *Src0, Variable *Src1) {
175    Context.insert<InstMIPS32And>(Dest, Src0, Src1);
176  }
177
178  void _andi(Variable *Dest, Variable *Src, uint32_t Imm) {
179    Context.insert<InstMIPS32Andi>(Dest, Src, Imm);
180  }
181
182  void _br(CfgNode *Target) { Context.insert<InstMIPS32Br>(Target); }
183
184  void _br(CfgNode *Target, const InstMIPS32Label *Label) {
185    Context.insert<InstMIPS32Br>(Target, Label);
186  }
187
188  void _br(CfgNode *TargetTrue, CfgNode *TargetFalse, Operand *Src0,
189           Operand *Src1, CondMIPS32::Cond Condition) {
190    Context.insert<InstMIPS32Br>(TargetTrue, TargetFalse, Src0, Src1,
191                                 Condition);
192  }
193
194  void _br(CfgNode *TargetTrue, CfgNode *TargetFalse, Operand *Src0,
195           CondMIPS32::Cond Condition) {
196    Context.insert<InstMIPS32Br>(TargetTrue, TargetFalse, Src0, Condition);
197  }
198
199  void _br(CfgNode *TargetTrue, CfgNode *TargetFalse, Operand *Src0,
200           Operand *Src1, const InstMIPS32Label *Label,
201           CondMIPS32::Cond Condition) {
202    Context.insert<InstMIPS32Br>(TargetTrue, TargetFalse, Src0, Src1, Label,
203                                 Condition);
204  }
205
206  void _ret(Variable *RA, Variable *Src0 = nullptr) {
207    Context.insert<InstMIPS32Ret>(RA, Src0);
208  }
209
210  void _abs_d(Variable *Dest, Variable *Src) {
211    Context.insert<InstMIPS32Abs_d>(Dest, Src);
212  }
213
214  void _abs_s(Variable *Dest, Variable *Src) {
215    Context.insert<InstMIPS32Abs_s>(Dest, Src);
216  }
217
218  void _addi(Variable *Dest, Variable *Src, uint32_t Imm) {
219    Context.insert<InstMIPS32Addi>(Dest, Src, Imm);
220  }
221
222  void _add_d(Variable *Dest, Variable *Src0, Variable *Src1) {
223    Context.insert<InstMIPS32Add_d>(Dest, Src0, Src1);
224  }
225
226  void _add_s(Variable *Dest, Variable *Src0, Variable *Src1) {
227    Context.insert<InstMIPS32Add_s>(Dest, Src0, Src1);
228  }
229
230  void _addiu(Variable *Dest, Variable *Src, uint32_t Imm) {
231    Context.insert<InstMIPS32Addiu>(Dest, Src, Imm);
232  }
233
234  void _addiu(Variable *Dest, Variable *Src0, Operand *Src1, RelocOp Reloc) {
235    Context.insert<InstMIPS32Addiu>(Dest, Src0, Src1, Reloc);
236  }
237
238  void _c_eq_d(Variable *Src0, Variable *Src1) {
239    Context.insert<InstMIPS32C_eq_d>(Src0, Src1);
240  }
241
242  void _c_eq_s(Variable *Src0, Variable *Src1) {
243    Context.insert<InstMIPS32C_eq_s>(Src0, Src1);
244  }
245
246  void _c_ole_d(Variable *Src0, Variable *Src1) {
247    Context.insert<InstMIPS32C_ole_d>(Src0, Src1);
248  }
249
250  void _c_ole_s(Variable *Src0, Variable *Src1) {
251    Context.insert<InstMIPS32C_ole_s>(Src0, Src1);
252  }
253
254  void _c_olt_d(Variable *Src0, Variable *Src1) {
255    Context.insert<InstMIPS32C_olt_d>(Src0, Src1);
256  }
257
258  void _c_olt_s(Variable *Src0, Variable *Src1) {
259    Context.insert<InstMIPS32C_olt_s>(Src0, Src1);
260  }
261
262  void _c_ueq_d(Variable *Src0, Variable *Src1) {
263    Context.insert<InstMIPS32C_ueq_d>(Src0, Src1);
264  }
265
266  void _c_ueq_s(Variable *Src0, Variable *Src1) {
267    Context.insert<InstMIPS32C_ueq_s>(Src0, Src1);
268  }
269
270  void _c_ule_d(Variable *Src0, Variable *Src1) {
271    Context.insert<InstMIPS32C_ule_d>(Src0, Src1);
272  }
273
274  void _c_ule_s(Variable *Src0, Variable *Src1) {
275    Context.insert<InstMIPS32C_ule_s>(Src0, Src1);
276  }
277
278  void _c_ult_d(Variable *Src0, Variable *Src1) {
279    Context.insert<InstMIPS32C_ult_d>(Src0, Src1);
280  }
281
282  void _c_ult_s(Variable *Src0, Variable *Src1) {
283    Context.insert<InstMIPS32C_ult_s>(Src0, Src1);
284  }
285
286  void _c_un_d(Variable *Src0, Variable *Src1) {
287    Context.insert<InstMIPS32C_un_d>(Src0, Src1);
288  }
289
290  void _c_un_s(Variable *Src0, Variable *Src1) {
291    Context.insert<InstMIPS32C_un_s>(Src0, Src1);
292  }
293
294  void _clz(Variable *Dest, Variable *Src) {
295    Context.insert<InstMIPS32Clz>(Dest, Src);
296  }
297
298  void _cvt_d_l(Variable *Dest, Variable *Src) {
299    Context.insert<InstMIPS32Cvt_d_l>(Dest, Src);
300  }
301
302  void _cvt_d_s(Variable *Dest, Variable *Src) {
303    Context.insert<InstMIPS32Cvt_d_s>(Dest, Src);
304  }
305
306  void _cvt_d_w(Variable *Dest, Variable *Src) {
307    Context.insert<InstMIPS32Cvt_d_w>(Dest, Src);
308  }
309
310  void _cvt_s_d(Variable *Dest, Variable *Src) {
311    Context.insert<InstMIPS32Cvt_s_d>(Dest, Src);
312  }
313
314  void _cvt_s_l(Variable *Dest, Variable *Src) {
315    Context.insert<InstMIPS32Cvt_s_l>(Dest, Src);
316  }
317
318  void _cvt_s_w(Variable *Dest, Variable *Src) {
319    Context.insert<InstMIPS32Cvt_s_w>(Dest, Src);
320  }
321
322  void _div(Variable *Dest, Variable *Src0, Variable *Src1) {
323    Context.insert<InstMIPS32Div>(Dest, Src0, Src1);
324  }
325
326  void _div_d(Variable *Dest, Variable *Src0, Variable *Src1) {
327    Context.insert<InstMIPS32Div_d>(Dest, Src0, Src1);
328  }
329
330  void _div_s(Variable *Dest, Variable *Src0, Variable *Src1) {
331    Context.insert<InstMIPS32Div_s>(Dest, Src0, Src1);
332  }
333
334  void _divu(Variable *Dest, Variable *Src0, Variable *Src1) {
335    Context.insert<InstMIPS32Divu>(Dest, Src0, Src1);
336  }
337
338  void _ldc1(Variable *Value, OperandMIPS32Mem *Mem, RelocOp Reloc = RO_No) {
339    Context.insert<InstMIPS32Ldc1>(Value, Mem, Reloc);
340  }
341
342  void _ll(Variable *Value, OperandMIPS32Mem *Mem) {
343    Context.insert<InstMIPS32Ll>(Value, Mem);
344  }
345
346  void _lw(Variable *Value, OperandMIPS32Mem *Mem) {
347    Context.insert<InstMIPS32Lw>(Value, Mem);
348  }
349
350  void _lwc1(Variable *Value, OperandMIPS32Mem *Mem, RelocOp Reloc = RO_No) {
351    Context.insert<InstMIPS32Lwc1>(Value, Mem, Reloc);
352  }
353
354  void _lui(Variable *Dest, Operand *Src, RelocOp Reloc = RO_No) {
355    Context.insert<InstMIPS32Lui>(Dest, Src, Reloc);
356  }
357
358  void _mfc1(Variable *Dest, Variable *Src) {
359    Context.insert<InstMIPS32Mfc1>(Dest, Src);
360  }
361
362  void _mfhi(Variable *Dest, Operand *Src) {
363    Context.insert<InstMIPS32Mfhi>(Dest, Src);
364  }
365
366  void _mflo(Variable *Dest, Operand *Src) {
367    Context.insert<InstMIPS32Mflo>(Dest, Src);
368  }
369
370  void _mov(Variable *Dest, Operand *Src0, Operand *Src1 = nullptr) {
371    assert(Dest != nullptr);
372    // Variable* Src0_ = llvm::dyn_cast<Variable>(Src0);
373    if (llvm::isa<ConstantRelocatable>(Src0)) {
374      Context.insert<InstMIPS32La>(Dest, Src0);
375    } else {
376      auto *Instr = Context.insert<InstMIPS32Mov>(Dest, Src0, Src1);
377      if (Instr->getDestHi() != nullptr) {
378        // If DestHi is available, then Dest must be a Variable64On32. We add a
379        // fake-def for Instr.DestHi here.
380        assert(llvm::isa<Variable64On32>(Dest));
381        Context.insert<InstFakeDef>(Instr->getDestHi());
382      }
383    }
384  }
385
386  void _mov_redefined(Variable *Dest, Operand *Src0, Operand *Src1 = nullptr) {
387    if (llvm::isa<ConstantRelocatable>(Src0)) {
388      Context.insert<InstMIPS32La>(Dest, Src0);
389    } else {
390      auto *Instr = Context.insert<InstMIPS32Mov>(Dest, Src0, Src1);
391      Instr->setDestRedefined();
392      if (Instr->getDestHi() != nullptr) {
393        // If Instr is multi-dest, then Dest must be a Variable64On32. We add a
394        // fake-def for Instr.DestHi here.
395        assert(llvm::isa<Variable64On32>(Dest));
396        Context.insert<InstFakeDef>(Instr->getDestHi());
397      }
398    }
399  }
400
401  void _mov_fp64_to_i64(Variable *Dest, Operand *Src, Int64Part Int64HiLo) {
402    assert(Dest != nullptr);
403    Context.insert<InstMIPS32MovFP64ToI64>(Dest, Src, Int64HiLo);
404  }
405
406  void _mov_d(Variable *Dest, Variable *Src) {
407    Context.insert<InstMIPS32Mov_d>(Dest, Src);
408  }
409
410  void _mov_s(Variable *Dest, Variable *Src) {
411    Context.insert<InstMIPS32Mov_s>(Dest, Src);
412  }
413
414  void _movf(Variable *Dest, Variable *Src0, Operand *FCC) {
415    Context.insert<InstMIPS32Movf>(Dest, Src0, FCC)->setDestRedefined();
416  }
417
418  void _movn(Variable *Dest, Variable *Src0, Variable *Src1) {
419    Context.insert<InstMIPS32Movn>(Dest, Src0, Src1)->setDestRedefined();
420  }
421
422  void _movn_d(Variable *Dest, Variable *Src0, Variable *Src1) {
423    Context.insert<InstMIPS32Movn_d>(Dest, Src0, Src1)->setDestRedefined();
424  }
425
426  void _movn_s(Variable *Dest, Variable *Src0, Variable *Src1) {
427    Context.insert<InstMIPS32Movn_s>(Dest, Src0, Src1)->setDestRedefined();
428  }
429
430  void _movt(Variable *Dest, Variable *Src0, Operand *FCC) {
431    Context.insert<InstMIPS32Movt>(Dest, Src0, FCC)->setDestRedefined();
432  }
433
434  void _movz(Variable *Dest, Variable *Src0, Variable *Src1) {
435    Context.insert<InstMIPS32Movz>(Dest, Src0, Src1)->setDestRedefined();
436  }
437
438  void _movz_d(Variable *Dest, Variable *Src0, Variable *Src1) {
439    Context.insert<InstMIPS32Movz_d>(Dest, Src0, Src1)->setDestRedefined();
440  }
441
442  void _movz_s(Variable *Dest, Variable *Src0, Variable *Src1) {
443    Context.insert<InstMIPS32Movz_s>(Dest, Src0, Src1)->setDestRedefined();
444  }
445
446  void _mtc1(Variable *Dest, Variable *Src) {
447    Context.insert<InstMIPS32Mtc1>(Dest, Src);
448  }
449
450  void _mthi(Variable *Dest, Operand *Src) {
451    Context.insert<InstMIPS32Mthi>(Dest, Src);
452  }
453
454  void _mtlo(Variable *Dest, Operand *Src) {
455    Context.insert<InstMIPS32Mtlo>(Dest, Src);
456  }
457
458  void _mul(Variable *Dest, Variable *Src0, Variable *Src1) {
459    Context.insert<InstMIPS32Mul>(Dest, Src0, Src1);
460  }
461
462  void _mul_d(Variable *Dest, Variable *Src0, Variable *Src1) {
463    Context.insert<InstMIPS32Mul_d>(Dest, Src0, Src1);
464  }
465
466  void _mul_s(Variable *Dest, Variable *Src0, Variable *Src1) {
467    Context.insert<InstMIPS32Mul_s>(Dest, Src0, Src1);
468  }
469
470  void _mult(Variable *Dest, Variable *Src0, Variable *Src1) {
471    Context.insert<InstMIPS32Mult>(Dest, Src0, Src1);
472  }
473
474  void _multu(Variable *Dest, Variable *Src0, Variable *Src1) {
475    Context.insert<InstMIPS32Multu>(Dest, Src0, Src1);
476  }
477
478  void _nop() { Context.insert<InstMIPS32Sll>(getZero(), getZero(), 0); }
479
480  void _nor(Variable *Dest, Variable *Src0, Variable *Src1) {
481    Context.insert<InstMIPS32Nor>(Dest, Src0, Src1);
482  }
483
484  void _not(Variable *Dest, Variable *Src0) {
485    Context.insert<InstMIPS32Nor>(Dest, Src0, getZero());
486  }
487
488  void _or(Variable *Dest, Variable *Src0, Variable *Src1) {
489    Context.insert<InstMIPS32Or>(Dest, Src0, Src1);
490  }
491
492  void _ori(Variable *Dest, Variable *Src, uint32_t Imm) {
493    Context.insert<InstMIPS32Ori>(Dest, Src, Imm);
494  }
495
496  InstMIPS32Sc *_sc(Variable *Value, OperandMIPS32Mem *Mem) {
497    return Context.insert<InstMIPS32Sc>(Value, Mem);
498  }
499
500  void _sdc1(Variable *Value, OperandMIPS32Mem *Mem) {
501    Context.insert<InstMIPS32Sdc1>(Value, Mem);
502  }
503
504  void _sll(Variable *Dest, Variable *Src, uint32_t Imm) {
505    Context.insert<InstMIPS32Sll>(Dest, Src, Imm);
506  }
507
508  void _sllv(Variable *Dest, Variable *Src0, Variable *Src1) {
509    Context.insert<InstMIPS32Sllv>(Dest, Src0, Src1);
510  }
511
512  void _slt(Variable *Dest, Variable *Src0, Variable *Src1) {
513    Context.insert<InstMIPS32Slt>(Dest, Src0, Src1);
514  }
515
516  void _slti(Variable *Dest, Variable *Src, uint32_t Imm) {
517    Context.insert<InstMIPS32Slti>(Dest, Src, Imm);
518  }
519
520  void _sltiu(Variable *Dest, Variable *Src, uint32_t Imm) {
521    Context.insert<InstMIPS32Sltiu>(Dest, Src, Imm);
522  }
523
524  void _sltu(Variable *Dest, Variable *Src0, Variable *Src1) {
525    Context.insert<InstMIPS32Sltu>(Dest, Src0, Src1);
526  }
527
528  void _sqrt_d(Variable *Dest, Variable *Src) {
529    Context.insert<InstMIPS32Sqrt_d>(Dest, Src);
530  }
531
532  void _sqrt_s(Variable *Dest, Variable *Src) {
533    Context.insert<InstMIPS32Sqrt_s>(Dest, Src);
534  }
535
536  void _sra(Variable *Dest, Variable *Src, uint32_t Imm) {
537    Context.insert<InstMIPS32Sra>(Dest, Src, Imm);
538  }
539
540  void _srav(Variable *Dest, Variable *Src0, Variable *Src1) {
541    Context.insert<InstMIPS32Srav>(Dest, Src0, Src1);
542  }
543
544  void _srl(Variable *Dest, Variable *Src, uint32_t Imm) {
545    Context.insert<InstMIPS32Srl>(Dest, Src, Imm);
546  }
547
548  void _srlv(Variable *Dest, Variable *Src0, Variable *Src1) {
549    Context.insert<InstMIPS32Srlv>(Dest, Src0, Src1);
550  }
551
552  void _sub(Variable *Dest, Variable *Src0, Variable *Src1) {
553    Context.insert<InstMIPS32Sub>(Dest, Src0, Src1);
554  }
555
556  void _sub_d(Variable *Dest, Variable *Src0, Variable *Src1) {
557    Context.insert<InstMIPS32Sub_d>(Dest, Src0, Src1);
558  }
559
560  void _sub_s(Variable *Dest, Variable *Src0, Variable *Src1) {
561    Context.insert<InstMIPS32Sub_s>(Dest, Src0, Src1);
562  }
563
564  void _subu(Variable *Dest, Variable *Src0, Variable *Src1) {
565    Context.insert<InstMIPS32Subu>(Dest, Src0, Src1);
566  }
567
568  void _sw(Variable *Value, OperandMIPS32Mem *Mem) {
569    Context.insert<InstMIPS32Sw>(Value, Mem);
570  }
571
572  void _swc1(Variable *Value, OperandMIPS32Mem *Mem) {
573    Context.insert<InstMIPS32Swc1>(Value, Mem);
574  }
575
576  void _sync() { Context.insert<InstMIPS32Sync>(); }
577
578  void _teq(Variable *Src0, Variable *Src1, uint32_t TrapCode) {
579    Context.insert<InstMIPS32Teq>(Src0, Src1, TrapCode);
580  }
581
582  void _trunc_l_d(Variable *Dest, Variable *Src) {
583    Context.insert<InstMIPS32Trunc_l_d>(Dest, Src);
584  }
585
586  void _trunc_l_s(Variable *Dest, Variable *Src) {
587    Context.insert<InstMIPS32Trunc_l_s>(Dest, Src);
588  }
589
590  void _trunc_w_d(Variable *Dest, Variable *Src) {
591    Context.insert<InstMIPS32Trunc_w_d>(Dest, Src);
592  }
593
594  void _trunc_w_s(Variable *Dest, Variable *Src) {
595    Context.insert<InstMIPS32Trunc_w_s>(Dest, Src);
596  }
597
598  void _xor(Variable *Dest, Variable *Src0, Variable *Src1) {
599    Context.insert<InstMIPS32Xor>(Dest, Src0, Src1);
600  }
601
602  void _xori(Variable *Dest, Variable *Src, uint32_t Imm) {
603    Context.insert<InstMIPS32Xori>(Dest, Src, Imm);
604  }
605
606  void lowerArguments() override;
607
608  class Sandboxer {
609    Sandboxer() = delete;
610    Sandboxer(const Sandboxer &) = delete;
611    Sandboxer &operator=(const Sandboxer &) = delete;
612
613  public:
614    explicit Sandboxer(
615        TargetMIPS32 *Target,
616        InstBundleLock::Option BundleOption = InstBundleLock::Opt_None);
617    ~Sandboxer();
618
619    void addiu_sp(uint32_t StackOffset);
620    void lw(Variable *Dest, OperandMIPS32Mem *Mem);
621    void sw(Variable *Dest, OperandMIPS32Mem *Mem);
622    void ll(Variable *Dest, OperandMIPS32Mem *Mem);
623    void sc(Variable *Dest, OperandMIPS32Mem *Mem);
624    void lwc1(Variable *Dest, OperandMIPS32Mem *Mem, RelocOp Reloc = RO_No);
625    void ldc1(Variable *Dest, OperandMIPS32Mem *Mem, RelocOp Reloc = RO_No);
626    void ret(Variable *RetAddr, Variable *RetValue);
627    void reset_sp(Variable *Src);
628    InstMIPS32Call *jal(Variable *ReturnReg, Operand *CallTarget);
629
630  private:
631    TargetMIPS32 *const Target;
632    const InstBundleLock::Option BundleOption;
633    std::unique_ptr<AutoBundle> Bundler;
634
635    void createAutoBundle();
636  };
637
638  const bool NeedSandboxing;
639
640  /// Make a pass through the SortedSpilledVariables and actually assign stack
641  /// slots. SpillAreaPaddingBytes takes into account stack alignment padding.
642  /// The SpillArea starts after that amount of padding. This matches the scheme
643  /// in getVarStackSlotParams, where there may be a separate multi-block global
644  /// var spill area and a local var spill area.
645  void assignVarStackSlots(VarList &SortedSpilledVariables,
646                           size_t SpillAreaPaddingBytes,
647                           size_t SpillAreaSizeBytes,
648                           size_t GlobalsAndSubsequentPaddingSize);
649
650  /// Operand legalization helpers.  To deal with address mode constraints,
651  /// the helpers will create a new Operand and emit instructions that
652  /// guarantee that the Operand kind is one of those indicated by the
653  /// LegalMask (a bitmask of allowed kinds).  If the input Operand is known
654  /// to already meet the constraints, it may be simply returned as the result,
655  /// without creating any new instructions or operands.
656  enum OperandLegalization {
657    Legal_None = 0,
658    Legal_Reg = 1 << 0, // physical register, not stack location
659    Legal_Imm = 1 << 1,
660    Legal_Mem = 1 << 2,
661    Legal_Rematerializable = 1 << 3,
662    Legal_Default = ~Legal_None
663  };
664  typedef uint32_t LegalMask;
665  Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
666                    RegNumT RegNum = RegNumT());
667
668  Variable *legalizeToVar(Operand *From, RegNumT RegNum = RegNumT());
669
670  Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT());
671
672  Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT());
673
674  Variable *getZero() {
675    auto *Zero = makeReg(IceType_i32, RegMIPS32::Reg_ZERO);
676    Context.insert<InstFakeDef>(Zero);
677    return Zero;
678  }
679
680  Variable *I32Reg(RegNumT RegNum = RegNumT()) {
681    return makeReg(IceType_i32, RegNum);
682  }
683
684  Variable *F32Reg(RegNumT RegNum = RegNumT()) {
685    return makeReg(IceType_f32, RegNum);
686  }
687
688  Variable *F64Reg(RegNumT RegNum = RegNumT()) {
689    return makeReg(IceType_f64, RegNum);
690  }
691
692  static Type stackSlotType();
693  Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT());
694
695  void unsetIfNonLeafFunc();
696
697  // Iterates over the CFG and determines the maximum outgoing stack arguments
698  // bytes. This information is later used during addProlog() to pre-allocate
699  // the outargs area
700  void findMaxStackOutArgsSize();
701
702  void postLowerLegalization();
703
704  void addProlog(CfgNode *Node) override;
705  void addEpilog(CfgNode *Node) override;
706
707  // Ensure that a 64-bit Variable has been split into 2 32-bit
708  // Variables, creating them if necessary.  This is needed for all
709  // I64 operations.
710  void split64(Variable *Var);
711  Operand *loOperand(Operand *Operand);
712  Operand *hiOperand(Operand *Operand);
713  Operand *getOperandAtIndex(Operand *Operand, Type BaseType, uint32_t Index);
714
715  void finishArgumentLowering(Variable *Arg, bool PartialOnStack,
716                              Variable *FramePtr, size_t BasicFrameOffset,
717                              size_t *InArgsSizeBytes);
718
719  Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT());
720
721  /// Helper class that understands the Calling Convention and register
722  /// assignments as per MIPS O32 abi.
723  class CallingConv {
724    CallingConv(const CallingConv &) = delete;
725    CallingConv &operator=(const CallingConv &) = delete;
726
727  public:
728    CallingConv();
729    ~CallingConv() = default;
730
731    /// argInReg returns true if there is a Register available for the requested
732    /// type, and false otherwise. If it returns true, Reg is set to the
733    /// appropriate register number. Note that, when Ty == IceType_i64, Reg will
734    /// be an I64 register pair.
735    bool argInReg(Type Ty, uint32_t ArgNo, RegNumT *Reg);
736    void discardReg(RegNumT Reg) { GPRegsUsed |= RegisterAliases[Reg]; }
737
738  private:
739    // argInGPR is used to find if any GPR register is available for argument of
740    // type Ty
741    bool argInGPR(Type Ty, RegNumT *Reg);
742    /// argInVFP is to floating-point/vector types what argInGPR is for integer
743    /// types.
744    bool argInVFP(Type Ty, RegNumT *Reg);
745    inline void discardNextGPRAndItsAliases(CfgVector<RegNumT> *Regs);
746    inline void alignGPR(CfgVector<RegNumT> *Regs);
747    void discardUnavailableGPRsAndTheirAliases(CfgVector<RegNumT> *Regs);
748    SmallBitVector GPRegsUsed;
749    CfgVector<RegNumT> GPRArgs;
750    CfgVector<RegNumT> I64Args;
751
752    void discardUnavailableVFPRegsAndTheirAliases(CfgVector<RegNumT> *Regs);
753    SmallBitVector VFPRegsUsed;
754    CfgVector<RegNumT> FP32Args;
755    CfgVector<RegNumT> FP64Args;
756    // UseFPRegs is a flag indicating if FP registers can be used
757    bool UseFPRegs = false;
758  };
759
760protected:
761  explicit TargetMIPS32(Cfg *Func);
762
763  void postLower() override;
764
765  void lowerAlloca(const InstAlloca *Instr) override;
766  void lowerArithmetic(const InstArithmetic *Instr) override;
767  void lowerInt64Arithmetic(const InstArithmetic *Instr, Variable *Dest,
768                            Operand *Src0, Operand *Src1);
769  void lowerAssign(const InstAssign *Instr) override;
770  void lowerBr(const InstBr *Instr) override;
771  void lowerBreakpoint(const InstBreakpoint *Instr) override;
772  void lowerCall(const InstCall *Instr) override;
773  void lowerCast(const InstCast *Instr) override;
774  void lowerExtractElement(const InstExtractElement *Instr) override;
775  void lowerFcmp(const InstFcmp *Instr) override;
776  void lowerIcmp(const InstIcmp *Instr) override;
777  void lower64Icmp(const InstIcmp *Instr);
778  void createArithInst(Intrinsics::AtomicRMWOperation Operation, Variable *Dest,
779                       Variable *Src0, Variable *Src1);
780  void lowerIntrinsicCall(const InstIntrinsicCall *Instr) override;
781  void lowerInsertElement(const InstInsertElement *Instr) override;
782  void lowerLoad(const InstLoad *Instr) override;
783  void lowerPhi(const InstPhi *Instr) override;
784  void lowerRet(const InstRet *Instr) override;
785  void lowerSelect(const InstSelect *Instr) override;
786  void lowerShuffleVector(const InstShuffleVector *Instr) override;
787  void lowerStore(const InstStore *Instr) override;
788  void lowerSwitch(const InstSwitch *Instr) override;
789  void lowerUnreachable(const InstUnreachable *Instr) override;
790  void lowerOther(const Inst *Instr) override;
791  void prelowerPhis() override;
792  uint32_t getCallStackArgumentsSizeBytes(const InstCall *Instr) override;
793  void genTargetHelperCallFor(Inst *Instr) override;
794  void doAddressOptLoad() override;
795  void doAddressOptStore() override;
796  void randomlyInsertNop(float Probability,
797                         RandomNumberGenerator &RNG) override;
798  void
799  makeRandomRegisterPermutation(llvm::SmallVectorImpl<RegNumT> &Permutation,
800                                const SmallBitVector &ExcludeRegisters,
801                                uint64_t Salt) const override;
802
803  OperandMIPS32Mem *formMemoryOperand(Operand *Ptr, Type Ty);
804
805  class PostLoweringLegalizer {
806    PostLoweringLegalizer() = delete;
807    PostLoweringLegalizer(const PostLoweringLegalizer &) = delete;
808    PostLoweringLegalizer &operator=(const PostLoweringLegalizer &) = delete;
809
810  public:
811    explicit PostLoweringLegalizer(TargetMIPS32 *Target)
812        : Target(Target), StackOrFrameReg(Target->getPhysicalRegister(
813                              Target->getFrameOrStackReg())) {}
814
815    /// Legalizes Mem. if Mem.Base is a rematerializable variable,
816    /// Mem.Offset is fixed up.
817    OperandMIPS32Mem *legalizeMemOperand(OperandMIPS32Mem *Mem);
818
819    /// Legalizes Immediate if larger value overflows range of 16 bits
820    Variable *legalizeImmediate(int32_t Imm);
821
822    /// Legalizes Mov if its Source (or Destination) is a spilled Variable, or
823    /// if its Source is a Rematerializable variable (this form is used in lieu
824    /// of lea, which is not available in MIPS.)
825    ///
826    /// Moves to memory become store instructions, and moves from memory, loads.
827    void legalizeMov(InstMIPS32Mov *Mov);
828    void legalizeMovFp(InstMIPS32MovFP64ToI64 *MovInstr);
829
830  private:
831    /// Creates a new Base register centered around [Base, +/- Offset].
832    Variable *newBaseRegister(Variable *Base, int32_t Offset,
833                              RegNumT ScratchRegNum);
834
835    TargetMIPS32 *const Target;
836    Variable *const StackOrFrameReg;
837  };
838
839  bool UsesFramePointer = false;
840  bool NeedsStackAlignment = false;
841  bool MaybeLeafFunc = true;
842  bool PrologEmitsFixedAllocas = false;
843  bool VariableAllocaUsed = false;
844  uint32_t MaxOutArgsSizeBytes = 0;
845  uint32_t TotalStackSizeBytes = 0;
846  uint32_t CurrentAllocaOffset = 0;
847  uint32_t VariableAllocaAlignBytes = 0;
848  static SmallBitVector TypeToRegisterSet[RCMIPS32_NUM];
849  static SmallBitVector TypeToRegisterSetUnfiltered[RCMIPS32_NUM];
850  static SmallBitVector RegisterAliases[RegMIPS32::Reg_NUM];
851  SmallBitVector RegsUsed;
852  VarList PhysicalRegisters[IceType_NUM];
853  VarList PreservedGPRs;
854  static constexpr uint32_t CHAR_BITS = 8;
855  static constexpr uint32_t INT32_BITS = 32;
856  size_t SpillAreaSizeBytes = 0;
857  size_t FixedAllocaSizeBytes = 0;
858  size_t FixedAllocaAlignBytes = 0;
859  size_t PreservedRegsSizeBytes = 0;
860  Variable *ImplicitRet = nullptr; /// Implicit return
861
862private:
863  ENABLE_MAKE_UNIQUE;
864
865  OperandMIPS32Mem *formAddressingMode(Type Ty, Cfg *Func, const Inst *LdSt,
866                                       Operand *Base);
867
868  class ComputationTracker {
869  public:
870    ComputationTracker() = default;
871    ~ComputationTracker() = default;
872
873    void forgetProducers() { KnownComputations.clear(); }
874    void recordProducers(CfgNode *Node);
875
876    const Inst *getProducerOf(const Operand *Opnd) const {
877      auto *Var = llvm::dyn_cast<Variable>(Opnd);
878      if (Var == nullptr) {
879        return nullptr;
880      }
881
882      auto Iter = KnownComputations.find(Var->getIndex());
883      if (Iter == KnownComputations.end()) {
884        return nullptr;
885      }
886
887      return Iter->second.Instr;
888    }
889
890    void dump(const Cfg *Func) const {
891      if (!BuildDefs::dump() || !Func->isVerbose(IceV_Folding))
892        return;
893      OstreamLocker L(Func->getContext());
894      Ostream &Str = Func->getContext()->getStrDump();
895      Str << "foldable producer:\n";
896      for (const auto &Computation : KnownComputations) {
897        Str << "    ";
898        Computation.second.Instr->dump(Func);
899        Str << "\n";
900      }
901      Str << "\n";
902    }
903
904  private:
905    class ComputationEntry {
906    public:
907      ComputationEntry(Inst *I, Type Ty) : Instr(I), ComputationType(Ty) {}
908      Inst *const Instr;
909      // Boolean folding is disabled for variables whose live range is multi
910      // block. We conservatively initialize IsLiveOut to true, and set it to
911      // false once we find the end of the live range for the variable defined
912      // by this instruction. If liveness analysis is not performed (e.g., in
913      // Om1 mode) IsLiveOut will never be set to false, and folding will be
914      // disabled.
915      bool IsLiveOut = true;
916      int32_t NumUses = 0;
917      Type ComputationType;
918    };
919
920    // ComputationMap maps a Variable number to a payload identifying which
921    // instruction defined it.
922    using ComputationMap = CfgUnorderedMap<SizeT, ComputationEntry>;
923    ComputationMap KnownComputations;
924  };
925
926  ComputationTracker Computations;
927};
928
929class TargetDataMIPS32 final : public TargetDataLowering {
930  TargetDataMIPS32() = delete;
931  TargetDataMIPS32(const TargetDataMIPS32 &) = delete;
932  TargetDataMIPS32 &operator=(const TargetDataMIPS32 &) = delete;
933
934public:
935  static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) {
936    return std::unique_ptr<TargetDataLowering>(new TargetDataMIPS32(Ctx));
937  }
938
939  void lowerGlobals(const VariableDeclarationList &Vars,
940                    const std::string &SectionSuffix) override;
941  void lowerConstants() override;
942  void lowerJumpTables() override;
943  void emitTargetRODataSections() override;
944
945protected:
946  explicit TargetDataMIPS32(GlobalContext *Ctx);
947
948private:
949  ~TargetDataMIPS32() override = default;
950};
951
952class TargetHeaderMIPS32 final : public TargetHeaderLowering {
953  TargetHeaderMIPS32() = delete;
954  TargetHeaderMIPS32(const TargetHeaderMIPS32 &) = delete;
955  TargetHeaderMIPS32 &operator=(const TargetHeaderMIPS32 &) = delete;
956
957public:
958  static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) {
959    return std::unique_ptr<TargetHeaderLowering>(new TargetHeaderMIPS32(Ctx));
960  }
961
962  void lower() override;
963
964protected:
965  explicit TargetHeaderMIPS32(GlobalContext *Ctx);
966
967private:
968  ~TargetHeaderMIPS32() = default;
969};
970
971// This structure (with some minor modifications) is copied from
972// llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h file.
973struct MipsABIFlagsSection {
974
975  // Version of the MIPS.abiflags section
976  enum AFL_VERSION {
977    AFL_VERSION_V0 = 0 // Version 0
978  };
979
980  // The level of the ISA: 1-5, 32, 64.
981  enum AFL_ISA_LEVEL {
982    AFL_ISA_LEVEL_NONE = 0,
983    AFL_ISA_LEVEL_MIPS32 = 32, // MIPS32
984  };
985
986  // The revision of ISA: 0 for MIPS V and below, 1-n otherwise.
987  enum AFL_ISA_REV {
988    AFL_ISA_REV_NONE = 0,
989    AFL_ISA_REV_R1 = 1, // R1
990  };
991
992  // Values for the xxx_size bytes of an ABI flags structure.
993  enum AFL_REG {
994    AFL_REG_NONE = 0x00, // No registers.
995    AFL_REG_32 = 0x01,   // 32-bit registers.
996    AFL_REG_64 = 0x02,   // 64-bit registers.
997    AFL_REG_128 = 0x03   // 128-bit registers.
998  };
999
1000  // Values for the fp_abi word of an ABI flags structure.
1001  enum AFL_FP_ABI {
1002    AFL_FP_ANY = 0,
1003    AFL_FP_DOUBLE = 1,
1004    AFL_FP_XX = 5,
1005    AFL_FP_64 = 6,
1006    AFL_FP_64A = 7
1007  };
1008
1009  // Values for the isa_ext word of an ABI flags structure.
1010  enum AFL_EXT {
1011    AFL_EXT_NONE = 0,
1012    AFL_EXT_XLR = 1,          // RMI Xlr instruction.
1013    AFL_EXT_OCTEON2 = 2,      // Cavium Networks Octeon2.
1014    AFL_EXT_OCTEONP = 3,      // Cavium Networks OcteonP.
1015    AFL_EXT_LOONGSON_3A = 4,  // Loongson 3A.
1016    AFL_EXT_OCTEON = 5,       // Cavium Networks Octeon.
1017    AFL_EXT_5900 = 6,         // MIPS R5900 instruction.
1018    AFL_EXT_4650 = 7,         // MIPS R4650 instruction.
1019    AFL_EXT_4010 = 8,         // LSI R4010 instruction.
1020    AFL_EXT_4100 = 9,         // NEC VR4100 instruction.
1021    AFL_EXT_3900 = 10,        // Toshiba R3900 instruction.
1022    AFL_EXT_10000 = 11,       // MIPS R10000 instruction.
1023    AFL_EXT_SB1 = 12,         // Broadcom SB-1 instruction.
1024    AFL_EXT_4111 = 13,        // NEC VR4111/VR4181 instruction.
1025    AFL_EXT_4120 = 14,        // NEC VR4120 instruction.
1026    AFL_EXT_5400 = 15,        // NEC VR5400 instruction.
1027    AFL_EXT_5500 = 16,        // NEC VR5500 instruction.
1028    AFL_EXT_LOONGSON_2E = 17, // ST Microelectronics Loongson 2E.
1029    AFL_EXT_LOONGSON_2F = 18  // ST Microelectronics Loongson 2F.
1030  };
1031
1032  // Masks for the ases word of an ABI flags structure.
1033  enum AFL_ASE {
1034    AFL_ASE_NONE = 0x00000000,
1035    AFL_ASE_DSP = 0x00000001,       // DSP ASE.
1036    AFL_ASE_DSPR2 = 0x00000002,     // DSP R2 ASE.
1037    AFL_ASE_EVA = 0x00000004,       // Enhanced VA Scheme.
1038    AFL_ASE_MCU = 0x00000008,       // MCU (MicroController) ASE.
1039    AFL_ASE_MDMX = 0x00000010,      // MDMX ASE.
1040    AFL_ASE_MIPS3D = 0x00000020,    // MIPS-3D ASE.
1041    AFL_ASE_MT = 0x00000040,        // MT ASE.
1042    AFL_ASE_SMARTMIPS = 0x00000080, // SmartMIPS ASE.
1043    AFL_ASE_VIRT = 0x00000100,      // VZ ASE.
1044    AFL_ASE_MSA = 0x00000200,       // MSA ASE.
1045    AFL_ASE_MIPS16 = 0x00000400,    // MIPS16 ASE.
1046    AFL_ASE_MICROMIPS = 0x00000800, // MICROMIPS ASE.
1047    AFL_ASE_XPA = 0x00001000        // XPA ASE.
1048  };
1049
1050  enum AFL_FLAGS1 { AFL_FLAGS1_NONE = 0, AFL_FLAGS1_ODDSPREG = 1 };
1051
1052  enum AFL_FLAGS2 { AFL_FLAGS2_NONE = 0 };
1053
1054  uint16_t Version = AFL_VERSION_V0;
1055  uint8_t ISALevel = AFL_ISA_LEVEL_MIPS32;
1056  uint8_t ISARevision = AFL_ISA_REV_R1;
1057  uint8_t GPRSize = AFL_REG_32;
1058  uint8_t CPR1Size = AFL_REG_32;
1059  uint8_t CPR2Size = AFL_REG_NONE;
1060  uint8_t FPABI = AFL_FP_DOUBLE;
1061  uint32_t Extension = AFL_EXT_NONE;
1062  uint32_t ASE = AFL_ASE_NONE;
1063  uint32_t Flags1 = AFL_FLAGS1_ODDSPREG;
1064  uint32_t Flags2 = AFL_FLAGS2_NONE;
1065
1066  MipsABIFlagsSection() = default;
1067};
1068
1069} // end of namespace MIPS32
1070} // end of namespace Ice
1071
1072#endif // SUBZERO_SRC_ICETARGETLOWERINGMIPS32_H
1073