blob: d3789f8215b10119e498686d0eb4282b3f22e6ac [file] [log] [blame]
Jim Stichnoth6da4cef2015-06-11 13:26:33 -07001//===- 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//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Declares the TargetLoweringMIPS32 class, which implements the
Andrew Scull9612d322015-07-06 14:53:25 -070012/// TargetLowering interface for the MIPS 32-bit architecture.
13///
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070014//===----------------------------------------------------------------------===//
15
16#ifndef SUBZERO_SRC_ICETARGETLOWERINGMIPS32_H
17#define SUBZERO_SRC_ICETARGETLOWERINGMIPS32_H
18
John Porto53611e22015-12-30 07:30:10 -080019#include "IceAssemblerMIPS32.h"
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070020#include "IceDefs.h"
21#include "IceInstMIPS32.h"
22#include "IceRegistersMIPS32.h"
23#include "IceTargetLowering.h"
24
25namespace Ice {
John Porto4a566862016-01-04 09:33:41 -080026namespace MIPS32 {
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070027
28class TargetMIPS32 : public TargetLowering {
29 TargetMIPS32() = delete;
30 TargetMIPS32(const TargetMIPS32 &) = delete;
31 TargetMIPS32 &operator=(const TargetMIPS32 &) = delete;
32
33public:
John Porto53611e22015-12-30 07:30:10 -080034 ~TargetMIPS32() override = default;
35
Jim Stichnoth8ff4b282016-01-04 15:39:06 -080036 static void staticInit(const ClFlags &Flags);
John Porto53611e22015-12-30 07:30:10 -080037 static std::unique_ptr<::Ice::TargetLowering> create(Cfg *Func) {
38 return makeUnique<TargetMIPS32>(Func);
39 }
40
41 std::unique_ptr<::Ice::Assembler> createAssembler() const override {
42 return makeUnique<MIPS32::AssemblerMIPS32>();
43 }
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070044
45 void translateOm1() override;
46 void translateO2() override;
47 bool doBranchOpt(Inst *I, const CfgNode *NextNode) override;
48
49 SizeT getNumRegisters() const override { return RegMIPS32::Reg_NUM; }
50 Variable *getPhysicalRegister(SizeT RegNum, Type Ty = IceType_void) override;
51 IceString getRegName(SizeT RegNum, Type Ty) const override;
52 llvm::SmallBitVector getRegisterSet(RegSetMask Include,
53 RegSetMask Exclude) const override;
Jim Stichnothc59288b2015-11-09 11:38:40 -080054 const llvm::SmallBitVector &
55 getRegistersForVariable(const Variable *Var) const override {
56 RegClass RC = Var->getRegClass();
57 assert(RC < RC_Target);
58 return TypeToRegisterSet[RC];
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070059 }
John Portobb0a5fe2015-09-04 11:23:41 -070060 const llvm::SmallBitVector &getAliasesForRegister(SizeT Reg) const override {
61 return RegisterAliases[Reg];
62 }
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070063 bool hasFramePointer() const override { return UsesFramePointer; }
David Sehre39d0ca2015-11-06 11:25:41 -080064 void setHasFramePointer() override { UsesFramePointer = true; }
Jim Stichnothe7418712015-10-09 06:54:02 -070065 SizeT getStackReg() const override { return RegMIPS32::Reg_SP; }
David Sehr2f3b8ec2015-11-16 16:51:39 -080066 SizeT getFrameReg() const override { return RegMIPS32::Reg_FP; }
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070067 SizeT getFrameOrStackReg() const override {
David Sehr2f3b8ec2015-11-16 16:51:39 -080068 return UsesFramePointer ? getFrameReg() : getStackReg();
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070069 }
70 size_t typeWidthInBytesOnStack(Type Ty) const override {
Andrew Scull57e12682015-09-16 11:30:19 -070071 // Round up to the next multiple of 4 bytes. In particular, i1, i8, and i16
72 // are rounded up to 4 bytes.
Jim Stichnoth6da4cef2015-06-11 13:26:33 -070073 return (typeWidthInBytes(Ty) + 3) & ~3;
74 }
David Sehre39d0ca2015-11-06 11:25:41 -080075 uint32_t getStackAlignment() const override {
76 // TODO(sehr): what is the stack alignment?
77 return 1;
78 }
David Sehr2f3b8ec2015-11-16 16:51:39 -080079 void reserveFixedAllocaArea(size_t Size, size_t Align) override {
80 // TODO(sehr): Implement fixed stack layout.
81 (void)Size;
82 (void)Align;
83 llvm::report_fatal_error("Not yet implemented");
84 }
85 int32_t getFrameFixedAllocaOffset() const override {
86 // TODO(sehr): Implement fixed stack layout.
87 llvm::report_fatal_error("Not yet implemented");
88 return 0;
89 }
Andrew Scull87f80c12015-07-20 10:19:16 -070090
Andrew Scull6d47bcd2015-09-17 17:10:05 -070091 bool shouldSplitToVariable64On32(Type Ty) const override {
92 return Ty == IceType_i64;
93 }
94
Andrew Scull87f80c12015-07-20 10:19:16 -070095 // TODO(ascull): what is the best size of MIPS?
96 SizeT getMinJumpTableSize() const override { return 3; }
Andrew Scull86df4e92015-07-30 13:54:44 -070097 void emitJumpTable(const Cfg *Func,
98 const InstJumpTable *JumpTable) const override;
Andrew Scull87f80c12015-07-20 10:19:16 -070099
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700100 void emitVariable(const Variable *Var) const override;
101
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700102 void emit(const ConstantInteger32 *C) const final {
Jan Voungfb792842015-06-11 15:27:50 -0700103 (void)C;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700104 llvm::report_fatal_error("Not yet implemented");
105 }
106 void emit(const ConstantInteger64 *C) const final {
Jan Voungfb792842015-06-11 15:27:50 -0700107 (void)C;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700108 llvm::report_fatal_error("Not yet implemented");
109 }
110 void emit(const ConstantFloat *C) const final {
Jan Voungfb792842015-06-11 15:27:50 -0700111 (void)C;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700112 llvm::report_fatal_error("Not yet implemented");
113 }
114 void emit(const ConstantDouble *C) const final {
Jan Voungfb792842015-06-11 15:27:50 -0700115 (void)C;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700116 llvm::report_fatal_error("Not yet implemented");
117 }
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800118 void emit(const ConstantUndef *C) const final {
119 (void)C;
120 llvm::report_fatal_error("Not yet implemented");
121 }
122 void emit(const ConstantRelocatable *C) const final {
123 (void)C;
124 llvm::report_fatal_error("Not yet implemented");
125 }
Reed Kotler37af5b02015-11-05 17:07:19 -0800126
127 // The following are helpers that insert lowered MIPS32 instructions with
128 // minimal syntactic overhead, so that the lowering code can look as close to
129 // assembly as practical.
130 void _add(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800131 Context.insert<InstMIPS32Add>(Dest, Src0, Src1);
Reed Kotler37af5b02015-11-05 17:07:19 -0800132 }
133
134 void _and(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800135 Context.insert<InstMIPS32And>(Dest, Src0, Src1);
Reed Kotler37af5b02015-11-05 17:07:19 -0800136 }
137
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700138 void _ret(Variable *RA, Variable *Src0 = nullptr) {
John Porto1d937a82015-12-17 06:19:34 -0800139 Context.insert<InstMIPS32Ret>(RA, Src0);
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700140 }
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700141
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700142 void _addiu(Variable *Dest, Variable *Src, uint32_t Imm) {
John Porto1d937a82015-12-17 06:19:34 -0800143 Context.insert<InstMIPS32Addiu>(Dest, Src, Imm);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700144 }
145
146 void _lui(Variable *Dest, uint32_t Imm) {
John Porto1d937a82015-12-17 06:19:34 -0800147 Context.insert<InstMIPS32Lui>(Dest, Imm);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700148 }
149
150 void _mov(Variable *Dest, Operand *Src0) {
151 assert(Dest != nullptr);
152 // Variable* Src0_ = llvm::dyn_cast<Variable>(Src0);
153 if (llvm::isa<ConstantRelocatable>(Src0)) {
John Porto1d937a82015-12-17 06:19:34 -0800154 Context.insert<InstMIPS32La>(Dest, Src0);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700155 } else {
John Porto1d937a82015-12-17 06:19:34 -0800156 auto *Instr = Context.insert<InstMIPS32Mov>(Dest, Src0);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700157 if (Instr->isMultiDest()) {
158 // If Instr is multi-dest, then Dest must be a Variable64On32. We add a
159 // fake-def for Instr.DestHi here.
160 assert(llvm::isa<Variable64On32>(Dest));
John Porto1d937a82015-12-17 06:19:34 -0800161 Context.insert<InstFakeDef>(Instr->getDestHi());
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700162 }
163 }
164 }
165
Reed Kotler37af5b02015-11-05 17:07:19 -0800166 void _mul(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800167 Context.insert<InstMIPS32Mul>(Dest, Src0, Src1);
Reed Kotler37af5b02015-11-05 17:07:19 -0800168 }
169
170 void _or(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800171 Context.insert<InstMIPS32Or>(Dest, Src0, Src1);
Reed Kotler37af5b02015-11-05 17:07:19 -0800172 }
173
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700174 void _ori(Variable *Dest, Variable *Src, uint32_t Imm) {
John Porto1d937a82015-12-17 06:19:34 -0800175 Context.insert<InstMIPS32Ori>(Dest, Src, Imm);
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700176 }
177
Reed Kotler37af5b02015-11-05 17:07:19 -0800178 void _sub(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800179 Context.insert<InstMIPS32Sub>(Dest, Src0, Src1);
Reed Kotler37af5b02015-11-05 17:07:19 -0800180 }
181
182 void _xor(Variable *Dest, Variable *Src0, Variable *Src1) {
John Porto1d937a82015-12-17 06:19:34 -0800183 Context.insert<InstMIPS32Xor>(Dest, Src0, Src1);
Reed Kotler37af5b02015-11-05 17:07:19 -0800184 }
185
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700186 void lowerArguments() override;
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700187
188 /// Operand legalization helpers. To deal with address mode constraints,
189 /// the helpers will create a new Operand and emit instructions that
190 /// guarantee that the Operand kind is one of those indicated by the
191 /// LegalMask (a bitmask of allowed kinds). If the input Operand is known
192 /// to already meet the constraints, it may be simply returned as the result,
193 /// without creating any new instructions or operands.
194 enum OperandLegalization {
195 Legal_None = 0,
196 Legal_Reg = 1 << 0, // physical register, not stack location
197 Legal_Imm = 1 << 1,
198 Legal_Mem = 1 << 2,
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800199 Legal_Default = ~Legal_None
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700200 };
201 typedef uint32_t LegalMask;
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800202 Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default,
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700203 int32_t RegNum = Variable::NoRegister);
204
205 Variable *legalizeToVar(Operand *From, int32_t RegNum = Variable::NoRegister);
206
207 Variable *legalizeToReg(Operand *From, int32_t RegNum = Variable::NoRegister);
208
209 Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister);
210 static Type stackSlotType();
211 Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister);
212
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700213 void addProlog(CfgNode *Node) override;
214 void addEpilog(CfgNode *Node) override;
215
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700216 // Ensure that a 64-bit Variable has been split into 2 32-bit
217 // Variables, creating them if necessary. This is needed for all
218 // I64 operations.
219 void split64(Variable *Var);
220 Operand *loOperand(Operand *Operand);
221 Operand *hiOperand(Operand *Operand);
222
223 Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister);
224
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700225protected:
226 explicit TargetMIPS32(Cfg *Func);
227
228 void postLower() override;
229
230 void lowerAlloca(const InstAlloca *Inst) override;
231 void lowerArithmetic(const InstArithmetic *Inst) override;
232 void lowerAssign(const InstAssign *Inst) override;
233 void lowerBr(const InstBr *Inst) override;
234 void lowerCall(const InstCall *Inst) override;
235 void lowerCast(const InstCast *Inst) override;
236 void lowerExtractElement(const InstExtractElement *Inst) override;
237 void lowerFcmp(const InstFcmp *Inst) override;
238 void lowerIcmp(const InstIcmp *Inst) override;
239 void lowerIntrinsicCall(const InstIntrinsicCall *Inst) override;
240 void lowerInsertElement(const InstInsertElement *Inst) override;
241 void lowerLoad(const InstLoad *Inst) override;
242 void lowerPhi(const InstPhi *Inst) override;
243 void lowerRet(const InstRet *Inst) override;
244 void lowerSelect(const InstSelect *Inst) override;
245 void lowerStore(const InstStore *Inst) override;
246 void lowerSwitch(const InstSwitch *Inst) override;
247 void lowerUnreachable(const InstUnreachable *Inst) override;
248 void prelowerPhis() override;
John Portof4198542015-11-20 14:17:23 -0800249 uint32_t getCallStackArgumentsSizeBytes(const InstCall *Instr) override {
250 (void)Instr;
251 return 0;
252 }
John Porto5e0a8a72015-11-20 13:50:36 -0800253 void genTargetHelperCallFor(Inst *Instr) override { (void)Instr; }
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700254 void doAddressOptLoad() override;
255 void doAddressOptStore() override;
Qining Luaee5fa82015-08-20 14:59:03 -0700256 void randomlyInsertNop(float Probability,
257 RandomNumberGenerator &RNG) override;
258 void
259 makeRandomRegisterPermutation(llvm::SmallVectorImpl<int32_t> &Permutation,
260 const llvm::SmallBitVector &ExcludeRegisters,
261 uint64_t Salt) const override;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700262
Jim Stichnotheafb56c2015-06-22 10:35:22 -0700263 bool UsesFramePointer = false;
264 bool NeedsStackAlignment = false;
Jim Stichnothc59288b2015-11-09 11:38:40 -0800265 static llvm::SmallBitVector TypeToRegisterSet[RCMIPS32_NUM];
Jim Stichnoth94844f12015-11-04 16:06:16 -0800266 static llvm::SmallBitVector RegisterAliases[RegMIPS32::Reg_NUM];
267 static llvm::SmallBitVector ScratchRegs;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700268 llvm::SmallBitVector RegsUsed;
269 VarList PhysicalRegisters[IceType_NUM];
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700270
271private:
John Porto53611e22015-12-30 07:30:10 -0800272 ENABLE_MAKE_UNIQUE;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700273};
274
John Porto0f86d032015-06-15 07:44:27 -0700275class TargetDataMIPS32 final : public TargetDataLowering {
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700276 TargetDataMIPS32() = delete;
277 TargetDataMIPS32(const TargetDataMIPS32 &) = delete;
278 TargetDataMIPS32 &operator=(const TargetDataMIPS32 &) = delete;
279
280public:
Jan Voungfb792842015-06-11 15:27:50 -0700281 static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) {
282 return std::unique_ptr<TargetDataLowering>(new TargetDataMIPS32(Ctx));
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700283 }
284
John Porto8b1a7052015-06-17 13:20:08 -0700285 void lowerGlobals(const VariableDeclarationList &Vars,
286 const IceString &SectionSuffix) override;
John Porto0f86d032015-06-15 07:44:27 -0700287 void lowerConstants() override;
Andrew Scull86df4e92015-07-30 13:54:44 -0700288 void lowerJumpTables() override;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700289
290protected:
291 explicit TargetDataMIPS32(GlobalContext *Ctx);
292
293private:
Jim Stichnothe587d942015-06-22 15:49:04 -0700294 ~TargetDataMIPS32() override = default;
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700295 template <typename T> static void emitConstantPool(GlobalContext *Ctx);
296};
297
Jan Voungfb792842015-06-11 15:27:50 -0700298class TargetHeaderMIPS32 final : public TargetHeaderLowering {
299 TargetHeaderMIPS32() = delete;
300 TargetHeaderMIPS32(const TargetHeaderMIPS32 &) = delete;
301 TargetHeaderMIPS32 &operator=(const TargetHeaderMIPS32 &) = delete;
302
303public:
304 static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) {
305 return std::unique_ptr<TargetHeaderLowering>(new TargetHeaderMIPS32(Ctx));
306 }
307
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700308 void lower() override;
309
Jan Voungfb792842015-06-11 15:27:50 -0700310protected:
311 explicit TargetHeaderMIPS32(GlobalContext *Ctx);
312
313private:
314 ~TargetHeaderMIPS32() = default;
315};
316
John Porto4a566862016-01-04 09:33:41 -0800317} // end of namespace MIPS32
Jim Stichnoth6da4cef2015-06-11 13:26:33 -0700318} // end of namespace Ice
319
320#endif // SUBZERO_SRC_ICETARGETLOWERINGMIPS32_H