OLD | NEW |
---|---|
1 //===- subzero/src/IceTargetLoweringMIPS32.cpp - MIPS32 lowering ----------===// | 1 //===- subzero/src/IceTargetLoweringMIPS32.cpp - MIPS32 lowering ----------===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 /// | 9 /// |
10 /// \file | 10 /// \file |
11 /// This file implements the TargetLoweringMIPS32 class, which consists almost | 11 /// This file implements the TargetLoweringMIPS32 class, which consists almost |
12 /// entirely of the lowering sequence for each high-level instruction. | 12 /// entirely of the lowering sequence for each high-level instruction. |
13 /// | 13 /// |
14 //===----------------------------------------------------------------------===// | 14 //===----------------------------------------------------------------------===// |
15 | 15 |
16 #include "IceTargetLoweringMIPS32.h" | 16 #include "IceTargetLoweringMIPS32.h" |
17 | 17 |
18 #include "IceCfg.h" | 18 #include "IceCfg.h" |
19 #include "IceCfgNode.h" | 19 #include "IceCfgNode.h" |
20 #include "IceClFlags.h" | 20 #include "IceClFlags.h" |
21 #include "IceDefs.h" | 21 #include "IceDefs.h" |
22 #include "IceELFObjectWriter.h" | 22 #include "IceELFObjectWriter.h" |
23 #include "IceGlobalInits.h" | 23 #include "IceGlobalInits.h" |
24 #include "IceInstMIPS32.h" | 24 #include "IceInstMIPS32.h" |
25 #include "IceLiveness.h" | 25 #include "IceLiveness.h" |
26 #include "IceOperand.h" | 26 #include "IceOperand.h" |
27 #include "IcePhiLoweringImpl.h" | |
27 #include "IceRegistersMIPS32.h" | 28 #include "IceRegistersMIPS32.h" |
28 #include "IceTargetLoweringMIPS32.def" | 29 #include "IceTargetLoweringMIPS32.def" |
29 #include "IceUtils.h" | 30 #include "IceUtils.h" |
30 #include "llvm/Support/MathExtras.h" | 31 #include "llvm/Support/MathExtras.h" |
31 | 32 |
32 namespace Ice { | 33 namespace Ice { |
33 | 34 |
35 using llvm::isInt; | |
36 | |
34 namespace { | 37 namespace { |
35 void UnimplementedError(const ClFlags &Flags) { | 38 void UnimplementedError(const ClFlags &Flags) { |
36 if (!Flags.getSkipUnimplemented()) { | 39 if (!Flags.getSkipUnimplemented()) { |
37 // Use llvm_unreachable instead of report_fatal_error, which gives better | 40 // Use llvm_unreachable instead of report_fatal_error, which gives better |
38 // stack traces. | 41 // stack traces. |
39 llvm_unreachable("Not yet implemented"); | 42 llvm_unreachable("Not yet implemented"); |
40 abort(); | 43 abort(); |
41 } | 44 } |
42 } | 45 } |
46 | |
47 // The maximum number of arguments to pass in GPR registers. | |
48 const uint32_t MIPS32_MAX_GPR_ARG = 4; | |
Jim Stichnoth
2015/10/18 11:48:40
Use constexpr if possible.
rkotlerimgtec
2015/10/19 00:12:00
Done.
| |
49 | |
43 } // end of anonymous namespace | 50 } // end of anonymous namespace |
44 | 51 |
45 TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) { | 52 TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) { |
46 // TODO: Don't initialize IntegerRegisters and friends every time. Instead, | 53 // TODO: Don't initialize IntegerRegisters and friends every time. Instead, |
47 // initialize in some sort of static initializer for the class. | 54 // initialize in some sort of static initializer for the class. |
55 | |
48 llvm::SmallBitVector IntegerRegisters(RegMIPS32::Reg_NUM); | 56 llvm::SmallBitVector IntegerRegisters(RegMIPS32::Reg_NUM); |
49 llvm::SmallBitVector FloatRegisters(RegMIPS32::Reg_NUM); | 57 llvm::SmallBitVector I64PairRegisters(RegMIPS32::Reg_NUM); |
58 llvm::SmallBitVector Float32Registers(RegMIPS32::Reg_NUM); | |
59 llvm::SmallBitVector Float64Registers(RegMIPS32::Reg_NUM); | |
50 llvm::SmallBitVector VectorRegisters(RegMIPS32::Reg_NUM); | 60 llvm::SmallBitVector VectorRegisters(RegMIPS32::Reg_NUM); |
51 llvm::SmallBitVector InvalidRegisters(RegMIPS32::Reg_NUM); | 61 llvm::SmallBitVector InvalidRegisters(RegMIPS32::Reg_NUM); |
52 ScratchRegs.resize(RegMIPS32::Reg_NUM); | 62 ScratchRegs.resize(RegMIPS32::Reg_NUM); |
53 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ | 63 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ |
54 isFP) \ | 64 isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
55 IntegerRegisters[RegMIPS32::val] = isInt; \ | 65 IntegerRegisters[RegMIPS32::val] = isInt; \ |
56 FloatRegisters[RegMIPS32::val] = isFP; \ | 66 I64PairRegisters[RegMIPS32::val] = isI64Pair; \ |
57 VectorRegisters[RegMIPS32::val] = isFP; \ | 67 Float32Registers[RegMIPS32::val] = isFP32; \ |
68 Float64Registers[RegMIPS32::val] = isFP64; \ | |
69 VectorRegisters[RegMIPS32::val] = isVec128; \ | |
58 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ | 70 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ |
59 RegisterAliases[RegMIPS32::val].set(RegMIPS32::val); \ | 71 for (SizeT RegAlias : alias_init) { \ |
72 assert(!RegisterAliases[RegMIPS32::val][RegAlias] && \ | |
73 "Duplicate alias for " #val); \ | |
74 RegisterAliases[RegMIPS32::val].set(RegAlias); \ | |
75 } \ | |
76 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ | |
77 assert(RegisterAliases[RegMIPS32::val][RegMIPS32::val]); \ | |
60 ScratchRegs[RegMIPS32::val] = scratch; | 78 ScratchRegs[RegMIPS32::val] = scratch; |
61 REGMIPS32_TABLE; | 79 REGMIPS32_TABLE; |
62 #undef X | 80 #undef X |
63 TypeToRegisterSet[IceType_void] = InvalidRegisters; | 81 TypeToRegisterSet[IceType_void] = InvalidRegisters; |
64 TypeToRegisterSet[IceType_i1] = IntegerRegisters; | 82 TypeToRegisterSet[IceType_i1] = IntegerRegisters; |
65 TypeToRegisterSet[IceType_i8] = IntegerRegisters; | 83 TypeToRegisterSet[IceType_i8] = IntegerRegisters; |
66 TypeToRegisterSet[IceType_i16] = IntegerRegisters; | 84 TypeToRegisterSet[IceType_i16] = IntegerRegisters; |
67 TypeToRegisterSet[IceType_i32] = IntegerRegisters; | 85 TypeToRegisterSet[IceType_i32] = IntegerRegisters; |
68 TypeToRegisterSet[IceType_i64] = IntegerRegisters; | 86 TypeToRegisterSet[IceType_i64] = IntegerRegisters; |
69 TypeToRegisterSet[IceType_f32] = FloatRegisters; | 87 TypeToRegisterSet[IceType_f32] = Float32Registers; |
70 TypeToRegisterSet[IceType_f64] = FloatRegisters; | 88 TypeToRegisterSet[IceType_f64] = Float64Registers; |
71 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; | 89 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; |
72 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; | 90 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; |
73 TypeToRegisterSet[IceType_v16i1] = VectorRegisters; | 91 TypeToRegisterSet[IceType_v16i1] = VectorRegisters; |
74 TypeToRegisterSet[IceType_v16i8] = VectorRegisters; | 92 TypeToRegisterSet[IceType_v16i8] = VectorRegisters; |
75 TypeToRegisterSet[IceType_v8i16] = VectorRegisters; | 93 TypeToRegisterSet[IceType_v8i16] = VectorRegisters; |
76 TypeToRegisterSet[IceType_v4i32] = VectorRegisters; | 94 TypeToRegisterSet[IceType_v4i32] = VectorRegisters; |
77 TypeToRegisterSet[IceType_v4f32] = VectorRegisters; | 95 TypeToRegisterSet[IceType_v4f32] = VectorRegisters; |
78 } | 96 } |
79 | 97 |
80 void TargetMIPS32::translateO2() { | 98 void TargetMIPS32::translateO2() { |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
217 (void)NextNode; | 235 (void)NextNode; |
218 UnimplementedError(Func->getContext()->getFlags()); | 236 UnimplementedError(Func->getContext()->getFlags()); |
219 return false; | 237 return false; |
220 } | 238 } |
221 | 239 |
222 IceString TargetMIPS32::getRegName(SizeT RegNum, Type Ty) const { | 240 IceString TargetMIPS32::getRegName(SizeT RegNum, Type Ty) const { |
223 assert(RegNum < RegMIPS32::Reg_NUM); | 241 assert(RegNum < RegMIPS32::Reg_NUM); |
224 (void)Ty; | 242 (void)Ty; |
225 static const char *RegNames[] = { | 243 static const char *RegNames[] = { |
226 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ | 244 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ |
227 isFP) \ | 245 isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
228 name, | 246 name, |
229 REGMIPS32_TABLE | 247 REGMIPS32_TABLE |
230 #undef X | 248 #undef X |
231 }; | 249 }; |
232 return RegNames[RegNum]; | 250 return RegNames[RegNum]; |
233 } | 251 } |
234 | 252 |
235 Variable *TargetMIPS32::getPhysicalRegister(SizeT RegNum, Type Ty) { | 253 Variable *TargetMIPS32::getPhysicalRegister(SizeT RegNum, Type Ty) { |
236 if (Ty == IceType_void) | 254 if (Ty == IceType_void) |
237 Ty = IceType_i32; | 255 Ty = IceType_i32; |
(...skipping 14 matching lines...) Expand all Loading... | |
252 } | 270 } |
253 return Reg; | 271 return Reg; |
254 } | 272 } |
255 | 273 |
256 void TargetMIPS32::emitJumpTable(const Cfg *Func, | 274 void TargetMIPS32::emitJumpTable(const Cfg *Func, |
257 const InstJumpTable *JumpTable) const { | 275 const InstJumpTable *JumpTable) const { |
258 (void)JumpTable; | 276 (void)JumpTable; |
259 UnimplementedError(Func->getContext()->getFlags()); | 277 UnimplementedError(Func->getContext()->getFlags()); |
260 } | 278 } |
261 | 279 |
280 /// Provide a trivial wrapper to legalize() for this common usage. | |
281 Variable *TargetMIPS32::legalizeToReg(Operand *From, int32_t RegNum) { | |
282 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); | |
283 } | |
284 | |
285 /// Legalize undef values to concrete values. | |
286 Operand *TargetMIPS32::legalizeUndef(Operand *From, int32_t RegNum) { | |
287 (void)RegNum; | |
288 Type Ty = From->getType(); | |
289 if (llvm::isa<ConstantUndef>(From)) { | |
290 // Lower undefs to zero. Another option is to lower undefs to an | |
291 // uninitialized register; however, using an uninitialized register | |
292 // results in less predictable code. | |
293 // | |
294 // If in the future the implementation is changed to lower undef | |
295 // values to uninitialized registers, a FakeDef will be needed: | |
296 // Context.insert(InstFakeDef::create(Func, Reg)); | |
297 // This is in order to ensure that the live range of Reg is not | |
298 // overestimated. If the constant being lowered is a 64 bit value, | |
299 // then the result should be split and the lo and hi components will | |
300 // need to go in uninitialized registers. | |
301 if (isVectorType(Ty)) | |
302 UnimplementedError(Func->getContext()->getFlags()); | |
303 return Ctx->getConstantZero(Ty); | |
304 } | |
305 return From; | |
306 } | |
307 | |
308 Variable *TargetMIPS32::makeReg(Type Type, int32_t RegNum) { | |
309 // There aren't any 64-bit integer registers for Mips32. | |
310 assert(Type != IceType_i64); | |
311 Variable *Reg = Func->makeVariable(Type); | |
312 if (RegNum == Variable::NoRegister) | |
313 Reg->setMustHaveReg(); | |
314 else | |
315 Reg->setRegNum(RegNum); | |
316 return Reg; | |
317 } | |
318 | |
262 void TargetMIPS32::emitVariable(const Variable *Var) const { | 319 void TargetMIPS32::emitVariable(const Variable *Var) const { |
263 if (!BuildDefs::dump()) | 320 if (!BuildDefs::dump()) |
264 return; | 321 return; |
265 Ostream &Str = Ctx->getStrEmit(); | 322 Ostream &Str = Ctx->getStrEmit(); |
266 (void)Var; | 323 const Type FrameSPTy = IceType_i32; |
267 (void)Str; | 324 if (Var->hasReg()) { |
325 Str << '$' << getRegName(Var->getRegNum(), Var->getType()); | |
326 return; | |
327 } else { | |
328 int32_t Offset = Var->getStackOffset(); | |
329 Str << Offset; | |
330 Str << "(" << getRegName(getFrameOrStackReg(), FrameSPTy); | |
331 Str << ")"; | |
332 } | |
268 UnimplementedError(Func->getContext()->getFlags()); | 333 UnimplementedError(Func->getContext()->getFlags()); |
Jim Stichnoth
2015/10/18 11:48:39
Is the stack reference part actually unimplemented
rkotlerimgtec
2015/10/19 00:12:00
It's incomplete. I was starting to add it but real
| |
269 } | 334 } |
270 | 335 |
271 void TargetMIPS32::lowerArguments() { | 336 void TargetMIPS32::lowerArguments() { |
272 VarList &Args = Func->getArgs(); | 337 VarList &Args = Func->getArgs(); |
273 if (Args.size() > 0) | 338 // We are only handling integer registers for now. The Mips o32 ABI is |
274 UnimplementedError(Func->getContext()->getFlags()); | 339 // somewhat complex but will be implemented in it's totality through follow |
Jim Stichnoth
2015/10/18 11:48:39
its
rkotlerimgtec
2015/10/19 00:12:00
Done.
| |
340 // on patches. | |
341 // | |
342 unsigned NumGPRRegsUsed = 0; | |
343 (void)NumGPRRegsUsed; | |
Jim Stichnoth
2015/10/18 11:48:39
remove this
rkotlerimgtec
2015/10/19 00:12:00
Done.
| |
344 // For each register argument, replace Arg in the argument list with the | |
345 // home register. Then generate an instruction in the prolog to copy the | |
346 // home register to the assigned location of Arg. | |
347 Context.init(Func->getEntryNode()); | |
348 Context.setInsertPoint(Context.getCur()); | |
349 for (SizeT I = 0, E = Args.size(); I < E; ++I) { | |
Jim Stichnoth
2015/10/18 11:48:40
I can't tell for sure whether I or E are really us
rkotlerimgtec
2015/10/19 00:12:00
I is used.
| |
350 Variable *Arg = Args[I]; | |
351 Type Ty = Arg->getType(); | |
352 // TODO(rkotler): handle float/vector types. | |
353 if (isVectorType(Ty)) { | |
354 UnimplementedError(Func->getContext()->getFlags()); | |
355 continue; | |
Jim Stichnoth
2015/10/18 11:48:39
Don't use "else if" following a "continue". I.e.,
rkotlerimgtec
2015/10/19 00:12:00
Done.
| |
356 } else if (isFloatingType(Ty)) { | |
357 UnimplementedError(Func->getContext()->getFlags()); | |
358 continue; | |
359 } else if (Ty == IceType_i64) { | |
360 if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG) | |
361 continue; | |
362 int32_t RegLo = RegMIPS32::Reg_A0 + NumGPRRegsUsed; | |
363 int32_t RegHi = RegLo + 1; | |
364 ++NumGPRRegsUsed; | |
365 // Always start i64 registers at an even register, so this may end | |
366 // up padding away a register. | |
367 if (RegLo % 2 != 0) { | |
368 ++RegLo; | |
369 ++NumGPRRegsUsed; | |
370 } | |
371 // If this leaves us without room to consume another register, | |
372 // leave any previously speculatively consumed registers as consumed. | |
373 if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG) | |
374 continue; | |
375 // RegHi = RegMIPS32::Reg_A0 + NumGPRRegsUsed; | |
376 ++NumGPRRegsUsed; | |
377 Variable *RegisterArg = Func->makeVariable(Ty); | |
378 auto *RegisterArg64On32 = llvm::cast<Variable64On32>(RegisterArg); | |
379 if (BuildDefs::dump()) | |
380 RegisterArg64On32->setName(Func, "home_reg:" + Arg->getName(Func)); | |
381 RegisterArg64On32->initHiLo(Func); | |
382 RegisterArg64On32->setIsArg(); | |
383 RegisterArg64On32->getLo()->setRegNum(RegLo); | |
384 RegisterArg64On32->getHi()->setRegNum(RegHi); | |
385 Arg->setIsArg(false); | |
386 Args[I] = RegisterArg64On32; | |
387 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); | |
388 continue; | |
389 } else { | |
390 assert(Ty == IceType_i32); | |
391 if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG) | |
392 continue; | |
393 int32_t RegNum = RegMIPS32::Reg_A0 + NumGPRRegsUsed; | |
394 ++NumGPRRegsUsed; | |
395 Variable *RegisterArg = Func->makeVariable(Ty); | |
396 if (BuildDefs::dump()) { | |
397 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); | |
398 } | |
399 RegisterArg->setRegNum(RegNum); | |
400 RegisterArg->setIsArg(); | |
401 Arg->setIsArg(false); | |
402 Args[I] = RegisterArg; | |
403 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); | |
404 } | |
405 } | |
275 } | 406 } |
276 | 407 |
277 Type TargetMIPS32::stackSlotType() { return IceType_i32; } | 408 Type TargetMIPS32::stackSlotType() { return IceType_i32; } |
278 | 409 |
279 void TargetMIPS32::addProlog(CfgNode *Node) { | 410 void TargetMIPS32::addProlog(CfgNode *Node) { |
280 (void)Node; | 411 (void)Node; |
412 return; | |
281 UnimplementedError(Func->getContext()->getFlags()); | 413 UnimplementedError(Func->getContext()->getFlags()); |
282 } | 414 } |
283 | 415 |
284 void TargetMIPS32::addEpilog(CfgNode *Node) { | 416 void TargetMIPS32::addEpilog(CfgNode *Node) { |
285 (void)Node; | 417 (void)Node; |
286 UnimplementedError(Func->getContext()->getFlags()); | 418 return; |
419 UnimplementedError(Func->getContext()->getFlags()); | |
420 } | |
421 | |
Jim Stichnoth
2015/10/18 11:48:39
just one blank line here
rkotlerimgtec
2015/10/19 00:12:00
Done.
| |
422 | |
423 Operand *TargetMIPS32::loOperand(Operand *Operand) { | |
424 assert(Operand->getType() == IceType_i64); | |
425 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) | |
426 return Var64On32->getLo(); | |
427 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { | |
Jim Stichnoth
2015/10/18 11:48:39
auto *Const
rkotlerimgtec
2015/10/19 00:12:00
Done.
rkotlerimgtec
2015/10/19 00:12:01
Done.
| |
428 return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue())); | |
429 } | |
430 if (OperandMIPS32Mem *Mem = llvm::dyn_cast<OperandMIPS32Mem>(Operand)) { | |
Jim Stichnoth
2015/10/18 11:48:39
auto *Mem
rkotlerimgtec
2015/10/19 00:12:00
Done.
| |
431 // Conservatively disallow memory operands with side-effects (pre/post | |
432 // increment) in case of duplication. | |
433 assert(Mem->getAddrMode() == OperandMIPS32Mem::Offset); | |
434 return OperandMIPS32Mem::create(Func, IceType_i32, Mem->getBase(), | |
435 Mem->getOffset(), Mem->getAddrMode()); | |
436 } | |
437 llvm_unreachable("Unsupported operand type"); | |
438 return nullptr; | |
439 } | |
440 | |
441 Operand *TargetMIPS32::hiOperand(Operand *Operand) { | |
442 assert(Operand->getType() == IceType_i64); | |
443 if (Operand->getType() != IceType_i64) | |
444 return Operand; | |
445 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) | |
446 return Var64On32->getHi(); | |
447 if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { | |
Jim Stichnoth
2015/10/18 11:48:40
auto *Const
rkotlerimgtec
2015/10/19 00:12:00
Done.
| |
448 return Ctx->getConstantInt32( | |
449 static_cast<uint32_t>(Const->getValue() >> 32)); | |
450 } | |
451 if (OperandMIPS32Mem *Mem = llvm::dyn_cast<OperandMIPS32Mem>(Operand)) { | |
Jim Stichnoth
2015/10/18 11:48:39
auto *Mem
rkotlerimgtec
2015/10/19 00:12:00
Done.
| |
452 // Conservatively disallow memory operands with side-effects | |
453 // in case of duplication. | |
454 assert(Mem->getAddrMode() == OperandMIPS32Mem::Offset); | |
455 const Type SplitType = IceType_i32; | |
456 Variable *Base = Mem->getBase(); | |
457 ConstantInteger32 *Offset = Mem->getOffset(); | |
458 assert(!Utils::WouldOverflowAdd(Offset->getValue(), 4)); | |
459 int32_t NextOffsetVal = Offset->getValue() + 4; | |
460 const bool SignExt = false; | |
Jim Stichnoth
2015/10/18 11:48:39
constexpr
rkotlerimgtec
2015/10/19 00:12:00
Done.
| |
461 if (!OperandMIPS32Mem::canHoldOffset(SplitType, SignExt, NextOffsetVal)) { | |
462 // We have to make a temp variable and add 4 to either Base or Offset. | |
463 // If we add 4 to Offset, this will convert a non-RegReg addressing | |
464 // mode into a RegReg addressing mode. Since NaCl sandboxing disallows | |
465 // RegReg addressing modes, prefer adding to base and replacing instead. | |
466 // Thus we leave the old offset alone. | |
467 Constant *Four = Ctx->getConstantInt32(4); | |
468 Variable *NewBase = Func->makeVariable(Base->getType()); | |
469 lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add, NewBase, | |
470 Base, Four)); | |
471 Base = NewBase; | |
472 } else { | |
473 Offset = | |
474 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(NextOffsetVal)); | |
475 } | |
476 return OperandMIPS32Mem::create(Func, SplitType, Base, Offset, | |
477 Mem->getAddrMode()); | |
478 } | |
479 llvm_unreachable("Unsupported operand type"); | |
480 return nullptr; | |
287 } | 481 } |
288 | 482 |
289 llvm::SmallBitVector TargetMIPS32::getRegisterSet(RegSetMask Include, | 483 llvm::SmallBitVector TargetMIPS32::getRegisterSet(RegSetMask Include, |
290 RegSetMask Exclude) const { | 484 RegSetMask Exclude) const { |
291 llvm::SmallBitVector Registers(RegMIPS32::Reg_NUM); | 485 llvm::SmallBitVector Registers(RegMIPS32::Reg_NUM); |
292 | 486 |
293 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ | 487 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ |
294 isFP) \ | 488 isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
295 if (scratch && (Include & RegSet_CallerSave)) \ | 489 if (scratch && (Include & RegSet_CallerSave)) \ |
296 Registers[RegMIPS32::val] = true; \ | 490 Registers[RegMIPS32::val] = true; \ |
297 if (preserved && (Include & RegSet_CalleeSave)) \ | 491 if (preserved && (Include & RegSet_CalleeSave)) \ |
298 Registers[RegMIPS32::val] = true; \ | 492 Registers[RegMIPS32::val] = true; \ |
299 if (stackptr && (Include & RegSet_StackPointer)) \ | 493 if (stackptr && (Include & RegSet_StackPointer)) \ |
300 Registers[RegMIPS32::val] = true; \ | 494 Registers[RegMIPS32::val] = true; \ |
301 if (frameptr && (Include & RegSet_FramePointer)) \ | 495 if (frameptr && (Include & RegSet_FramePointer)) \ |
302 Registers[RegMIPS32::val] = true; \ | 496 Registers[RegMIPS32::val] = true; \ |
303 if (scratch && (Exclude & RegSet_CallerSave)) \ | 497 if (scratch && (Exclude & RegSet_CallerSave)) \ |
304 Registers[RegMIPS32::val] = false; \ | 498 Registers[RegMIPS32::val] = false; \ |
(...skipping 17 matching lines...) Expand all Loading... | |
322 // operations implemented below assume that the stack is aligned before the | 516 // operations implemented below assume that the stack is aligned before the |
323 // alloca. All the alloca code ensures that the stack alignment is preserved | 517 // alloca. All the alloca code ensures that the stack alignment is preserved |
324 // after the alloca. The stack alignment restriction can be relaxed in some | 518 // after the alloca. The stack alignment restriction can be relaxed in some |
325 // cases. | 519 // cases. |
326 NeedsStackAlignment = true; | 520 NeedsStackAlignment = true; |
327 (void)Inst; | 521 (void)Inst; |
328 UnimplementedError(Func->getContext()->getFlags()); | 522 UnimplementedError(Func->getContext()->getFlags()); |
329 } | 523 } |
330 | 524 |
331 void TargetMIPS32::lowerArithmetic(const InstArithmetic *Inst) { | 525 void TargetMIPS32::lowerArithmetic(const InstArithmetic *Inst) { |
332 switch (Inst->getOp()) { | 526 Variable *Dest = Inst->getDest(); |
333 case InstArithmetic::_num: | 527 Operand *Src0 = legalizeUndef(Inst->getSrc(0)); |
528 Operand *Src1 = legalizeUndef(Inst->getSrc(1)); | |
529 (void)Src0; | |
530 (void)Src1; | |
531 if (Dest->getType() == IceType_i64) { | |
334 UnimplementedError(Func->getContext()->getFlags()); | 532 UnimplementedError(Func->getContext()->getFlags()); |
335 break; | 533 } else if (isVectorType(Dest->getType())) { |
336 case InstArithmetic::Add: | |
337 UnimplementedError(Func->getContext()->getFlags()); | 534 UnimplementedError(Func->getContext()->getFlags()); |
338 break; | 535 } else { // Dest->getType() is non-i64 scalar |
339 case InstArithmetic::And: | 536 switch (Inst->getOp()) { |
340 UnimplementedError(Func->getContext()->getFlags()); | 537 case InstArithmetic::_num: |
341 break; | 538 UnimplementedError(Func->getContext()->getFlags()); |
342 case InstArithmetic::Or: | 539 break; |
343 UnimplementedError(Func->getContext()->getFlags()); | 540 case InstArithmetic::Add: |
344 break; | 541 UnimplementedError(Func->getContext()->getFlags()); |
345 case InstArithmetic::Xor: | 542 // Variable *T = makeReg(Dest->getType()); |
346 UnimplementedError(Func->getContext()->getFlags()); | 543 // _add(T, Src0, Src1); |
347 break; | 544 // _mov(Dest, T); |
348 case InstArithmetic::Sub: | 545 return; |
349 UnimplementedError(Func->getContext()->getFlags()); | 546 case InstArithmetic::And: |
350 break; | 547 UnimplementedError(Func->getContext()->getFlags()); |
351 case InstArithmetic::Mul: | 548 break; |
352 UnimplementedError(Func->getContext()->getFlags()); | 549 case InstArithmetic::Or: |
353 break; | 550 UnimplementedError(Func->getContext()->getFlags()); |
354 case InstArithmetic::Shl: | 551 break; |
355 UnimplementedError(Func->getContext()->getFlags()); | 552 case InstArithmetic::Xor: |
356 break; | 553 UnimplementedError(Func->getContext()->getFlags()); |
357 case InstArithmetic::Lshr: | 554 break; |
358 UnimplementedError(Func->getContext()->getFlags()); | 555 case InstArithmetic::Sub: |
359 break; | 556 UnimplementedError(Func->getContext()->getFlags()); |
360 case InstArithmetic::Ashr: | 557 break; |
361 UnimplementedError(Func->getContext()->getFlags()); | 558 case InstArithmetic::Mul: |
362 break; | 559 UnimplementedError(Func->getContext()->getFlags()); |
363 case InstArithmetic::Udiv: | 560 break; |
364 UnimplementedError(Func->getContext()->getFlags()); | 561 case InstArithmetic::Shl: |
365 break; | 562 UnimplementedError(Func->getContext()->getFlags()); |
366 case InstArithmetic::Sdiv: | 563 break; |
367 UnimplementedError(Func->getContext()->getFlags()); | 564 case InstArithmetic::Lshr: |
368 break; | 565 UnimplementedError(Func->getContext()->getFlags()); |
369 case InstArithmetic::Urem: | 566 break; |
370 UnimplementedError(Func->getContext()->getFlags()); | 567 case InstArithmetic::Ashr: |
371 break; | 568 UnimplementedError(Func->getContext()->getFlags()); |
372 case InstArithmetic::Srem: | 569 break; |
373 UnimplementedError(Func->getContext()->getFlags()); | 570 case InstArithmetic::Udiv: |
374 break; | 571 UnimplementedError(Func->getContext()->getFlags()); |
375 case InstArithmetic::Fadd: | 572 break; |
376 UnimplementedError(Func->getContext()->getFlags()); | 573 case InstArithmetic::Sdiv: |
377 break; | 574 UnimplementedError(Func->getContext()->getFlags()); |
378 case InstArithmetic::Fsub: | 575 break; |
379 UnimplementedError(Func->getContext()->getFlags()); | 576 case InstArithmetic::Urem: |
380 break; | 577 UnimplementedError(Func->getContext()->getFlags()); |
381 case InstArithmetic::Fmul: | 578 break; |
382 UnimplementedError(Func->getContext()->getFlags()); | 579 case InstArithmetic::Srem: |
383 break; | 580 UnimplementedError(Func->getContext()->getFlags()); |
384 case InstArithmetic::Fdiv: | 581 break; |
385 UnimplementedError(Func->getContext()->getFlags()); | 582 case InstArithmetic::Fadd: |
386 break; | 583 UnimplementedError(Func->getContext()->getFlags()); |
387 case InstArithmetic::Frem: | 584 break; |
388 UnimplementedError(Func->getContext()->getFlags()); | 585 case InstArithmetic::Fsub: |
389 break; | 586 UnimplementedError(Func->getContext()->getFlags()); |
587 break; | |
588 case InstArithmetic::Fmul: | |
589 UnimplementedError(Func->getContext()->getFlags()); | |
590 break; | |
591 case InstArithmetic::Fdiv: | |
592 UnimplementedError(Func->getContext()->getFlags()); | |
593 break; | |
594 case InstArithmetic::Frem: | |
595 UnimplementedError(Func->getContext()->getFlags()); | |
596 break; | |
597 } | |
390 } | 598 } |
391 } | 599 } |
392 | 600 |
393 void TargetMIPS32::lowerAssign(const InstAssign *Inst) { | 601 void TargetMIPS32::lowerAssign(const InstAssign *Inst) { |
394 (void)Inst; | 602 Variable *Dest = Inst->getDest(); |
395 UnimplementedError(Func->getContext()->getFlags()); | 603 Operand *Src0 = Inst->getSrc(0); |
604 assert(Dest->getType() == Src0->getType()); | |
605 if (Dest->getType() == IceType_i64) { | |
606 Src0 = legalizeUndef(Src0); | |
607 Operand *Src0Lo = legalize(loOperand(Src0), Legal_Reg); | |
608 Operand *Src0Hi = legalize(hiOperand(Src0), Legal_Reg); | |
609 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | |
610 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | |
611 // Variable *T_Lo = nullptr, *T_Hi = nullptr; | |
612 Variable *T_Lo = makeReg(IceType_i32); | |
613 Variable *T_Hi = makeReg(IceType_i32); | |
614 _mov(T_Lo, Src0Lo); | |
615 _mov(DestLo, T_Lo); | |
616 _mov(T_Hi, Src0Hi); | |
617 _mov(DestHi, T_Hi); | |
618 } else { | |
619 Operand *SrcR; | |
620 if (Dest->hasReg()) { | |
621 // If Dest already has a physical register, then legalize the Src operand | |
622 // into a Variable with the same register assignment. This especially | |
623 // helps allow the use of Flex operands. | |
624 SrcR = legalize(Src0, Legal_Reg, Dest->getRegNum()); | |
625 } else { | |
626 // Dest could be a stack operand. Since we could potentially need | |
627 // to do a Store (and store can only have Register operands), | |
628 // legalize this to a register. | |
629 SrcR = legalize(Src0, Legal_Reg); | |
630 } | |
631 if (isVectorType(Dest->getType())) { | |
632 UnimplementedError(Func->getContext()->getFlags()); | |
633 } else { | |
634 _mov(Dest, SrcR); | |
635 } | |
636 } | |
396 } | 637 } |
397 | 638 |
398 void TargetMIPS32::lowerBr(const InstBr *Inst) { | 639 void TargetMIPS32::lowerBr(const InstBr *Inst) { |
399 (void)Inst; | 640 (void)Inst; |
400 UnimplementedError(Func->getContext()->getFlags()); | 641 UnimplementedError(Func->getContext()->getFlags()); |
401 } | 642 } |
402 | 643 |
403 void TargetMIPS32::lowerCall(const InstCall *Inst) { | 644 void TargetMIPS32::lowerCall(const InstCall *Inst) { |
404 (void)Inst; | 645 (void)Inst; |
405 UnimplementedError(Func->getContext()->getFlags()); | 646 UnimplementedError(Func->getContext()->getFlags()); |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
612 UnimplementedError(Func->getContext()->getFlags()); | 853 UnimplementedError(Func->getContext()->getFlags()); |
613 } | 854 } |
614 } | 855 } |
615 | 856 |
616 void TargetMIPS32::lowerPhi(const InstPhi * /*Inst*/) { | 857 void TargetMIPS32::lowerPhi(const InstPhi * /*Inst*/) { |
617 Func->setError("Phi found in regular instruction list"); | 858 Func->setError("Phi found in regular instruction list"); |
618 } | 859 } |
619 | 860 |
620 void TargetMIPS32::lowerRet(const InstRet *Inst) { | 861 void TargetMIPS32::lowerRet(const InstRet *Inst) { |
621 Variable *Reg = nullptr; | 862 Variable *Reg = nullptr; |
622 if (Inst->hasRetValue()) | 863 if (Inst->hasRetValue()) { |
623 UnimplementedError(Func->getContext()->getFlags()); | 864 Operand *Src0 = Inst->getRetValue(); |
865 switch (Src0->getType()) { | |
866 case IceType_i1: | |
867 case IceType_i8: | |
868 case IceType_i16: | |
869 case IceType_i32: { | |
870 // Reg = legalizeToReg(Src0, RegMIPS32::Reg_V0); | |
871 Operand *Src0F = legalize(Src0, Legal_Reg); | |
872 Reg = makeReg(Src0F->getType(), RegMIPS32::Reg_V0); | |
873 _mov(Reg, Src0F); | |
874 break; | |
875 } | |
876 case IceType_i64: { | |
877 Src0 = legalizeUndef(Src0); | |
878 Variable *R0 = legalizeToReg(loOperand(Src0), RegMIPS32::Reg_V0); | |
879 Variable *R1 = legalizeToReg(hiOperand(Src0), RegMIPS32::Reg_V1); | |
880 Reg = R0; | |
881 Context.insert(InstFakeUse::create(Func, R1)); | |
882 break; | |
883 } | |
884 | |
885 default: | |
886 UnimplementedError(Func->getContext()->getFlags()); | |
887 } | |
888 } | |
624 _ret(getPhysicalRegister(RegMIPS32::Reg_RA), Reg); | 889 _ret(getPhysicalRegister(RegMIPS32::Reg_RA), Reg); |
625 } | 890 } |
626 | 891 |
627 void TargetMIPS32::lowerSelect(const InstSelect *Inst) { | 892 void TargetMIPS32::lowerSelect(const InstSelect *Inst) { |
628 (void)Inst; | 893 (void)Inst; |
629 UnimplementedError(Func->getContext()->getFlags()); | 894 UnimplementedError(Func->getContext()->getFlags()); |
630 } | 895 } |
631 | 896 |
632 void TargetMIPS32::lowerStore(const InstStore *Inst) { | 897 void TargetMIPS32::lowerStore(const InstStore *Inst) { |
633 (void)Inst; | 898 (void)Inst; |
(...skipping 10 matching lines...) Expand all Loading... | |
644 } | 909 } |
645 | 910 |
646 void TargetMIPS32::lowerUnreachable(const InstUnreachable * /*Inst*/) { | 911 void TargetMIPS32::lowerUnreachable(const InstUnreachable * /*Inst*/) { |
647 UnimplementedError(Func->getContext()->getFlags()); | 912 UnimplementedError(Func->getContext()->getFlags()); |
648 } | 913 } |
649 | 914 |
650 // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to preserve | 915 // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to preserve |
651 // integrity of liveness analysis. Undef values are also turned into zeroes, | 916 // integrity of liveness analysis. Undef values are also turned into zeroes, |
652 // since loOperand() and hiOperand() don't expect Undef input. | 917 // since loOperand() and hiOperand() don't expect Undef input. |
653 void TargetMIPS32::prelowerPhis() { | 918 void TargetMIPS32::prelowerPhis() { |
654 UnimplementedError(Func->getContext()->getFlags()); | 919 PhiLowering::prelowerPhis32Bit<TargetMIPS32>(this, Context.getNode(), Func); |
655 } | 920 } |
656 | 921 |
657 void TargetMIPS32::postLower() { | 922 void TargetMIPS32::postLower() { |
658 if (Ctx->getFlags().getOptLevel() == Opt_m1) | 923 if (Ctx->getFlags().getOptLevel() == Opt_m1) |
659 return; | 924 return; |
660 // Find two-address non-SSA instructions where Dest==Src0, and set the | 925 // Find two-address non-SSA instructions where Dest==Src0, and set the |
661 // IsDestRedefined flag to keep liveness analysis consistent. | 926 // IsDestRedefined flag to keep liveness analysis consistent. |
662 UnimplementedError(Func->getContext()->getFlags()); | 927 UnimplementedError(Func->getContext()->getFlags()); |
663 } | 928 } |
664 | 929 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
709 return; | 974 return; |
710 UnimplementedError(Ctx->getFlags()); | 975 UnimplementedError(Ctx->getFlags()); |
711 } | 976 } |
712 | 977 |
713 void TargetDataMIPS32::lowerJumpTables() { | 978 void TargetDataMIPS32::lowerJumpTables() { |
714 if (Ctx->getFlags().getDisableTranslation()) | 979 if (Ctx->getFlags().getDisableTranslation()) |
715 return; | 980 return; |
716 UnimplementedError(Ctx->getFlags()); | 981 UnimplementedError(Ctx->getFlags()); |
717 } | 982 } |
718 | 983 |
984 // Helper for legalize() to emit the right code to lower an operand to a | |
985 // register of the appropriate type. | |
986 Variable *TargetMIPS32::copyToReg(Operand *Src, int32_t RegNum) { | |
987 Type Ty = Src->getType(); | |
988 Variable *Reg = makeReg(Ty, RegNum); | |
989 if (isVectorType(Ty) || isFloatingType(Ty)) { | |
990 UnimplementedError(Ctx->getFlags()); | |
991 } else { | |
992 // Mov's Src operand can really only be the flexible second operand type | |
993 // or a register. Users should guarantee that. | |
994 _mov(Reg, Src); | |
995 } | |
996 return Reg; | |
997 } | |
998 | |
999 Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed, | |
1000 int32_t RegNum) { | |
1001 Type Ty = From->getType(); | |
1002 // Assert that a physical register is allowed. To date, all calls | |
1003 // to legalize() allow a physical register. Legal_Flex converts | |
1004 // registers to the right type OperandMIPS32FlexReg as needed. | |
1005 assert(Allowed & Legal_Reg); | |
1006 // Go through the various types of operands: | |
1007 // OperandMIPS32Mem, OperandMIPS32Flex, Constant, and Variable. | |
1008 // Given the above assertion, if type of operand is not legal | |
1009 // (e.g., OperandMIPS32Mem and !Legal_Mem), we can always copy | |
1010 // to a register. | |
1011 if (auto C = llvm::dyn_cast<ConstantRelocatable>(From)) { | |
1012 (void)C; | |
1013 return From; | |
1014 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(From)) { | |
1015 uint32_t Value = static_cast<uint32_t>(C32->getValue()); | |
1016 // Check if the immediate will fit in a Flexible second operand, | |
1017 // if a Flexible second operand is allowed. We need to know the exact | |
1018 // value, so that rules out relocatable constants. | |
1019 // Also try the inverse and use MVN if possible. | |
1020 // Do a movw/movt to a register. | |
1021 Variable *Reg; | |
1022 if (RegNum == Variable::NoRegister) | |
1023 Reg = makeReg(Ty, RegNum); | |
1024 else | |
1025 Reg = getPhysicalRegister(RegNum); | |
1026 if (isInt<16>(int32_t(Value))) { | |
1027 _addiu(Reg, getPhysicalRegister(RegMIPS32::Reg_ZERO, Ty), Value); | |
1028 } else { | |
1029 uint32_t UpperBits = (Value >> 16) & 0xFFFF; | |
1030 (void)UpperBits; | |
1031 uint32_t LowerBits = Value & 0xFFFF; | |
1032 Variable *TReg = makeReg(Ty, RegNum); | |
1033 _lui(TReg, UpperBits); | |
1034 _ori(Reg, TReg, LowerBits); | |
1035 } | |
1036 return Reg; | |
1037 } | |
1038 if (auto Var = llvm::dyn_cast<Variable>(From)) { | |
1039 // Check if the variable is guaranteed a physical register. This | |
1040 // can happen either when the variable is pre-colored or when it is | |
1041 // assigned infinite weight. | |
1042 bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg()); | |
1043 // We need a new physical register for the operand if: | |
1044 // Mem is not allowed and Var isn't guaranteed a physical | |
1045 // register, or | |
1046 // RegNum is required and Var->getRegNum() doesn't match. | |
1047 if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || | |
1048 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) { | |
1049 From = copyToReg(From, RegNum); | |
1050 } | |
1051 return From; | |
1052 } | |
1053 return From; | |
1054 } | |
1055 | |
1056 /// Provide a trivial wrapper to legalize() for this common usage. | |
1057 // Variable *TargetMIPS32::legalizeToVar(Operand *From, int32_t RegNum) { | |
1058 // return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); | |
1059 //} | |
1060 | |
719 TargetHeaderMIPS32::TargetHeaderMIPS32(GlobalContext *Ctx) | 1061 TargetHeaderMIPS32::TargetHeaderMIPS32(GlobalContext *Ctx) |
720 : TargetHeaderLowering(Ctx) {} | 1062 : TargetHeaderLowering(Ctx) {} |
721 | 1063 |
1064 void TargetHeaderMIPS32::lower() { | |
1065 OstreamLocker L(Ctx); | |
1066 Ostream &Str = Ctx->getStrEmit(); | |
1067 Str << "\t.set\tnomicromips\n"; | |
1068 Str << "\t.set\tnomips16\n"; | |
1069 } | |
1070 | |
722 } // end of namespace Ice | 1071 } // end of namespace Ice |
OLD | NEW |