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 |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 | 134 |
135 // TODO(stichnot): share passes with X86? | 135 // TODO(stichnot): share passes with X86? |
136 // https://code.google.com/p/nativeclient/issues/detail?id=4094 | 136 // https://code.google.com/p/nativeclient/issues/detail?id=4094 |
137 genTargetHelperCalls(); | 137 genTargetHelperCalls(); |
138 | 138 |
139 // Merge Alloca instructions, and lay out the stack. | 139 // Merge Alloca instructions, and lay out the stack. |
140 static constexpr bool SortAndCombineAllocas = false; | 140 static constexpr bool SortAndCombineAllocas = false; |
141 Func->processAllocas(SortAndCombineAllocas); | 141 Func->processAllocas(SortAndCombineAllocas); |
142 Func->dump("After Alloca processing"); | 142 Func->dump("After Alloca processing"); |
143 | 143 |
144 if (!Ctx->getFlags().getEnablePhiEdgeSplit()) { | 144 if (!getFlags().getEnablePhiEdgeSplit()) { |
145 // Lower Phi instructions. | 145 // Lower Phi instructions. |
146 Func->placePhiLoads(); | 146 Func->placePhiLoads(); |
147 if (Func->hasError()) | 147 if (Func->hasError()) |
148 return; | 148 return; |
149 Func->placePhiStores(); | 149 Func->placePhiStores(); |
150 if (Func->hasError()) | 150 if (Func->hasError()) |
151 return; | 151 return; |
152 Func->deletePhis(); | 152 Func->deletePhis(); |
153 if (Func->hasError()) | 153 if (Func->hasError()) |
154 return; | 154 return; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 assert(Func->validateLiveness()); | 197 assert(Func->validateLiveness()); |
198 // The post-codegen dump is done here, after liveness analysis and associated | 198 // The post-codegen dump is done here, after liveness analysis and associated |
199 // cleanup, to make the dump cleaner and more useful. | 199 // cleanup, to make the dump cleaner and more useful. |
200 Func->dump("After initial MIPS32 codegen"); | 200 Func->dump("After initial MIPS32 codegen"); |
201 Func->getVMetadata()->init(VMK_All); | 201 Func->getVMetadata()->init(VMK_All); |
202 regAlloc(RAK_Global); | 202 regAlloc(RAK_Global); |
203 if (Func->hasError()) | 203 if (Func->hasError()) |
204 return; | 204 return; |
205 Func->dump("After linear scan regalloc"); | 205 Func->dump("After linear scan regalloc"); |
206 | 206 |
207 if (Ctx->getFlags().getEnablePhiEdgeSplit()) { | 207 if (getFlags().getEnablePhiEdgeSplit()) { |
208 Func->advancedPhiLowering(); | 208 Func->advancedPhiLowering(); |
209 Func->dump("After advanced Phi lowering"); | 209 Func->dump("After advanced Phi lowering"); |
210 } | 210 } |
211 | 211 |
212 // Stack frame mapping. | 212 // Stack frame mapping. |
213 Func->genFrame(); | 213 Func->genFrame(); |
214 if (Func->hasError()) | 214 if (Func->hasError()) |
215 return; | 215 return; |
216 Func->dump("After stack frame mapping"); | 216 Func->dump("After stack frame mapping"); |
217 | 217 |
218 Func->contractEmptyNodes(); | 218 Func->contractEmptyNodes(); |
219 Func->reorderNodes(); | 219 Func->reorderNodes(); |
220 | 220 |
221 // Branch optimization. This needs to be done just before code emission. In | 221 // Branch optimization. This needs to be done just before code emission. In |
222 // particular, no transformations that insert or reorder CfgNodes should be | 222 // particular, no transformations that insert or reorder CfgNodes should be |
223 // done after branch optimization. We go ahead and do it before nop insertion | 223 // done after branch optimization. We go ahead and do it before nop insertion |
224 // to reduce the amount of work needed for searching for opportunities. | 224 // to reduce the amount of work needed for searching for opportunities. |
225 Func->doBranchOpt(); | 225 Func->doBranchOpt(); |
226 Func->dump("After branch optimization"); | 226 Func->dump("After branch optimization"); |
227 | 227 |
228 // Nop insertion | 228 // Nop insertion |
229 if (Ctx->getFlags().getShouldDoNopInsertion()) { | 229 if (getFlags().getShouldDoNopInsertion()) { |
230 Func->doNopInsertion(); | 230 Func->doNopInsertion(); |
231 } | 231 } |
232 } | 232 } |
233 | 233 |
234 void TargetMIPS32::translateOm1() { | 234 void TargetMIPS32::translateOm1() { |
235 TimerMarker T(TimerStack::TT_Om1, Func); | 235 TimerMarker T(TimerStack::TT_Om1, Func); |
236 | 236 |
237 // TODO: share passes with X86? | 237 // TODO: share passes with X86? |
238 genTargetHelperCalls(); | 238 genTargetHelperCalls(); |
239 | 239 |
(...skipping 24 matching lines...) Expand all Loading... |
264 if (Func->hasError()) | 264 if (Func->hasError()) |
265 return; | 265 return; |
266 Func->dump("After regalloc of infinite-weight variables"); | 266 Func->dump("After regalloc of infinite-weight variables"); |
267 | 267 |
268 Func->genFrame(); | 268 Func->genFrame(); |
269 if (Func->hasError()) | 269 if (Func->hasError()) |
270 return; | 270 return; |
271 Func->dump("After stack frame mapping"); | 271 Func->dump("After stack frame mapping"); |
272 | 272 |
273 // Nop insertion | 273 // Nop insertion |
274 if (Ctx->getFlags().getShouldDoNopInsertion()) { | 274 if (getFlags().getShouldDoNopInsertion()) { |
275 Func->doNopInsertion(); | 275 Func->doNopInsertion(); |
276 } | 276 } |
277 } | 277 } |
278 | 278 |
279 bool TargetMIPS32::doBranchOpt(Inst *Instr, const CfgNode *NextNode) { | 279 bool TargetMIPS32::doBranchOpt(Inst *Instr, const CfgNode *NextNode) { |
280 (void)Instr; | 280 (void)Instr; |
281 (void)NextNode; | 281 (void)NextNode; |
282 UnimplementedError(Func->getContext()->getFlags()); | 282 UnimplementedError(getFlags()); |
283 return false; | 283 return false; |
284 } | 284 } |
285 | 285 |
286 namespace { | 286 namespace { |
287 | 287 |
288 const char *RegNames[RegMIPS32::Reg_NUM] = { | 288 const char *RegNames[RegMIPS32::Reg_NUM] = { |
289 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ | 289 #define X(val, encode, name, scratch, preserved, stackptr, frameptr, isInt, \ |
290 isI64Pair, isFP32, isFP64, isVec128, alias_init) \ | 290 isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
291 name, | 291 name, |
292 REGMIPS32_TABLE | 292 REGMIPS32_TABLE |
(...skipping 28 matching lines...) Expand all Loading... |
321 // liveness validation errors for saving callee-save registers. | 321 // liveness validation errors for saving callee-save registers. |
322 Func->addImplicitArg(Reg); | 322 Func->addImplicitArg(Reg); |
323 // Don't bother tracking the live range of a named physical register. | 323 // Don't bother tracking the live range of a named physical register. |
324 Reg->setIgnoreLiveness(); | 324 Reg->setIgnoreLiveness(); |
325 } | 325 } |
326 return Reg; | 326 return Reg; |
327 } | 327 } |
328 | 328 |
329 void TargetMIPS32::emitJumpTable(const Cfg *Func, | 329 void TargetMIPS32::emitJumpTable(const Cfg *Func, |
330 const InstJumpTable *JumpTable) const { | 330 const InstJumpTable *JumpTable) const { |
| 331 (void)Func; |
331 (void)JumpTable; | 332 (void)JumpTable; |
332 UnimplementedError(Func->getContext()->getFlags()); | 333 UnimplementedError(getFlags()); |
333 } | 334 } |
334 | 335 |
335 /// Provide a trivial wrapper to legalize() for this common usage. | 336 /// Provide a trivial wrapper to legalize() for this common usage. |
336 Variable *TargetMIPS32::legalizeToReg(Operand *From, RegNumT RegNum) { | 337 Variable *TargetMIPS32::legalizeToReg(Operand *From, RegNumT RegNum) { |
337 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); | 338 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); |
338 } | 339 } |
339 | 340 |
340 /// Legalize undef values to concrete values. | 341 /// Legalize undef values to concrete values. |
341 Operand *TargetMIPS32::legalizeUndef(Operand *From, RegNumT RegNum) { | 342 Operand *TargetMIPS32::legalizeUndef(Operand *From, RegNumT RegNum) { |
342 (void)RegNum; | 343 (void)RegNum; |
343 Type Ty = From->getType(); | 344 Type Ty = From->getType(); |
344 if (llvm::isa<ConstantUndef>(From)) { | 345 if (llvm::isa<ConstantUndef>(From)) { |
345 // Lower undefs to zero. Another option is to lower undefs to an | 346 // Lower undefs to zero. Another option is to lower undefs to an |
346 // uninitialized register; however, using an uninitialized register | 347 // uninitialized register; however, using an uninitialized register |
347 // results in less predictable code. | 348 // results in less predictable code. |
348 // | 349 // |
349 // If in the future the implementation is changed to lower undef | 350 // If in the future the implementation is changed to lower undef |
350 // values to uninitialized registers, a FakeDef will be needed: | 351 // values to uninitialized registers, a FakeDef will be needed: |
351 // Context.insert(InstFakeDef::create(Func, Reg)); | 352 // Context.insert(InstFakeDef::create(Func, Reg)); |
352 // This is in order to ensure that the live range of Reg is not | 353 // This is in order to ensure that the live range of Reg is not |
353 // overestimated. If the constant being lowered is a 64 bit value, | 354 // overestimated. If the constant being lowered is a 64 bit value, |
354 // then the result should be split and the lo and hi components will | 355 // then the result should be split and the lo and hi components will |
355 // need to go in uninitialized registers. | 356 // need to go in uninitialized registers. |
356 if (isVectorType(Ty)) | 357 if (isVectorType(Ty)) |
357 UnimplementedError(Func->getContext()->getFlags()); | 358 UnimplementedError(getFlags()); |
358 return Ctx->getConstantZero(Ty); | 359 return Ctx->getConstantZero(Ty); |
359 } | 360 } |
360 return From; | 361 return From; |
361 } | 362 } |
362 | 363 |
363 Variable *TargetMIPS32::makeReg(Type Type, RegNumT RegNum) { | 364 Variable *TargetMIPS32::makeReg(Type Type, RegNumT RegNum) { |
364 // There aren't any 64-bit integer registers for Mips32. | 365 // There aren't any 64-bit integer registers for Mips32. |
365 assert(Type != IceType_i64); | 366 assert(Type != IceType_i64); |
366 Variable *Reg = Func->makeVariable(Type); | 367 Variable *Reg = Func->makeVariable(Type); |
367 if (RegNum.hasValue()) | 368 if (RegNum.hasValue()) |
(...skipping 10 matching lines...) Expand all Loading... |
378 const Type FrameSPTy = IceType_i32; | 379 const Type FrameSPTy = IceType_i32; |
379 if (Var->hasReg()) { | 380 if (Var->hasReg()) { |
380 Str << '$' << getRegName(Var->getRegNum(), Var->getType()); | 381 Str << '$' << getRegName(Var->getRegNum(), Var->getType()); |
381 return; | 382 return; |
382 } else { | 383 } else { |
383 int32_t Offset = Var->getStackOffset(); | 384 int32_t Offset = Var->getStackOffset(); |
384 Str << Offset; | 385 Str << Offset; |
385 Str << "($" << getRegName(getFrameOrStackReg(), FrameSPTy); | 386 Str << "($" << getRegName(getFrameOrStackReg(), FrameSPTy); |
386 Str << ")"; | 387 Str << ")"; |
387 } | 388 } |
388 UnimplementedError(Func->getContext()->getFlags()); | 389 UnimplementedError(getFlags()); |
389 } | 390 } |
390 | 391 |
391 void TargetMIPS32::lowerArguments() { | 392 void TargetMIPS32::lowerArguments() { |
392 VarList &Args = Func->getArgs(); | 393 VarList &Args = Func->getArgs(); |
393 // We are only handling integer registers for now. The Mips o32 ABI is | 394 // We are only handling integer registers for now. The Mips o32 ABI is |
394 // somewhat complex but will be implemented in its totality through follow | 395 // somewhat complex but will be implemented in its totality through follow |
395 // on patches. | 396 // on patches. |
396 // | 397 // |
397 unsigned NumGPRRegsUsed = 0; | 398 unsigned NumGPRRegsUsed = 0; |
398 // For each register argument, replace Arg in the argument list with the | 399 // For each register argument, replace Arg in the argument list with the |
399 // home register. Then generate an instruction in the prolog to copy the | 400 // home register. Then generate an instruction in the prolog to copy the |
400 // home register to the assigned location of Arg. | 401 // home register to the assigned location of Arg. |
401 Context.init(Func->getEntryNode()); | 402 Context.init(Func->getEntryNode()); |
402 Context.setInsertPoint(Context.getCur()); | 403 Context.setInsertPoint(Context.getCur()); |
403 for (SizeT I = 0, E = Args.size(); I < E; ++I) { | 404 for (SizeT I = 0, E = Args.size(); I < E; ++I) { |
404 Variable *Arg = Args[I]; | 405 Variable *Arg = Args[I]; |
405 Type Ty = Arg->getType(); | 406 Type Ty = Arg->getType(); |
406 // TODO(rkotler): handle float/vector types. | 407 // TODO(rkotler): handle float/vector types. |
407 if (isVectorType(Ty)) { | 408 if (isVectorType(Ty)) { |
408 UnimplementedError(Func->getContext()->getFlags()); | 409 UnimplementedError(getFlags()); |
409 continue; | 410 continue; |
410 } | 411 } |
411 if (isFloatingType(Ty)) { | 412 if (isFloatingType(Ty)) { |
412 UnimplementedError(Func->getContext()->getFlags()); | 413 UnimplementedError(getFlags()); |
413 continue; | 414 continue; |
414 } | 415 } |
415 if (Ty == IceType_i64) { | 416 if (Ty == IceType_i64) { |
416 if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG) | 417 if (NumGPRRegsUsed >= MIPS32_MAX_GPR_ARG) |
417 continue; | 418 continue; |
418 auto RegLo = RegNumT::fixme(RegMIPS32::Reg_A0 + NumGPRRegsUsed); | 419 auto RegLo = RegNumT::fixme(RegMIPS32::Reg_A0 + NumGPRRegsUsed); |
419 auto RegHi = RegNumT::fixme(RegLo + 1); | 420 auto RegHi = RegNumT::fixme(RegLo + 1); |
420 ++NumGPRRegsUsed; | 421 ++NumGPRRegsUsed; |
421 // Always start i64 registers at an even register, so this may end | 422 // Always start i64 registers at an even register, so this may end |
422 // up padding away a register. | 423 // up padding away a register. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 Context.insert<InstAssign>(Arg, RegisterArg); | 460 Context.insert<InstAssign>(Arg, RegisterArg); |
460 } | 461 } |
461 } | 462 } |
462 } | 463 } |
463 | 464 |
464 Type TargetMIPS32::stackSlotType() { return IceType_i32; } | 465 Type TargetMIPS32::stackSlotType() { return IceType_i32; } |
465 | 466 |
466 void TargetMIPS32::addProlog(CfgNode *Node) { | 467 void TargetMIPS32::addProlog(CfgNode *Node) { |
467 (void)Node; | 468 (void)Node; |
468 return; | 469 return; |
469 UnimplementedError(Func->getContext()->getFlags()); | 470 UnimplementedError(getFlags()); |
470 } | 471 } |
471 | 472 |
472 void TargetMIPS32::addEpilog(CfgNode *Node) { | 473 void TargetMIPS32::addEpilog(CfgNode *Node) { |
473 (void)Node; | 474 (void)Node; |
474 return; | 475 return; |
475 UnimplementedError(Func->getContext()->getFlags()); | 476 UnimplementedError(getFlags()); |
476 } | 477 } |
477 | 478 |
478 Operand *TargetMIPS32::loOperand(Operand *Operand) { | 479 Operand *TargetMIPS32::loOperand(Operand *Operand) { |
479 assert(Operand->getType() == IceType_i64); | 480 assert(Operand->getType() == IceType_i64); |
480 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) | 481 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) |
481 return Var64On32->getLo(); | 482 return Var64On32->getLo(); |
482 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { | 483 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
483 return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue())); | 484 return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue())); |
484 } | 485 } |
485 if (auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(Operand)) { | 486 if (auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(Operand)) { |
(...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1046 Variable *ValExt = Func->makeVariable(stackSlotType()); | 1047 Variable *ValExt = Func->makeVariable(stackSlotType()); |
1047 lowerCast(InstCast::create(Func, InstCast::Zext, ValExt, ValOp)); | 1048 lowerCast(InstCast::create(Func, InstCast::Zext, ValExt, ValOp)); |
1048 InstCall *Call = makeHelperCall(RuntimeHelper::H_call_memset, nullptr, 3); | 1049 InstCall *Call = makeHelperCall(RuntimeHelper::H_call_memset, nullptr, 3); |
1049 Call->addArg(Instr->getArg(0)); | 1050 Call->addArg(Instr->getArg(0)); |
1050 Call->addArg(ValExt); | 1051 Call->addArg(ValExt); |
1051 Call->addArg(Instr->getArg(2)); | 1052 Call->addArg(Instr->getArg(2)); |
1052 lowerCall(Call); | 1053 lowerCall(Call); |
1053 return; | 1054 return; |
1054 } | 1055 } |
1055 case Intrinsics::NaClReadTP: { | 1056 case Intrinsics::NaClReadTP: { |
1056 if (Ctx->getFlags().getUseSandboxing()) { | 1057 if (getFlags().getUseSandboxing()) { |
1057 UnimplementedLoweringError(this, Instr); | 1058 UnimplementedLoweringError(this, Instr); |
1058 } else { | 1059 } else { |
1059 InstCall *Call = | 1060 InstCall *Call = |
1060 makeHelperCall(RuntimeHelper::H_call_read_tp, Instr->getDest(), 0); | 1061 makeHelperCall(RuntimeHelper::H_call_read_tp, Instr->getDest(), 0); |
1061 lowerCall(Call); | 1062 lowerCall(Call); |
1062 } | 1063 } |
1063 return; | 1064 return; |
1064 } | 1065 } |
1065 case Intrinsics::Setjmp: { | 1066 case Intrinsics::Setjmp: { |
1066 InstCall *Call = | 1067 InstCall *Call = |
(...skipping 21 matching lines...) Expand all Loading... |
1088 Func->setError("Should not be lowering UnknownIntrinsic"); | 1089 Func->setError("Should not be lowering UnknownIntrinsic"); |
1089 return; | 1090 return; |
1090 } | 1091 } |
1091 return; | 1092 return; |
1092 } | 1093 } |
1093 | 1094 |
1094 void TargetMIPS32::lowerLoad(const InstLoad *Instr) { | 1095 void TargetMIPS32::lowerLoad(const InstLoad *Instr) { |
1095 UnimplementedLoweringError(this, Instr); | 1096 UnimplementedLoweringError(this, Instr); |
1096 } | 1097 } |
1097 | 1098 |
1098 void TargetMIPS32::doAddressOptLoad() { | 1099 void TargetMIPS32::doAddressOptLoad() { UnimplementedError(getFlags()); } |
1099 UnimplementedError(Func->getContext()->getFlags()); | |
1100 } | |
1101 | 1100 |
1102 void TargetMIPS32::randomlyInsertNop(float Probability, | 1101 void TargetMIPS32::randomlyInsertNop(float Probability, |
1103 RandomNumberGenerator &RNG) { | 1102 RandomNumberGenerator &RNG) { |
1104 RandomNumberGeneratorWrapper RNGW(RNG); | 1103 RandomNumberGeneratorWrapper RNGW(RNG); |
1105 if (RNGW.getTrueWithProbability(Probability)) { | 1104 if (RNGW.getTrueWithProbability(Probability)) { |
1106 UnimplementedError(Func->getContext()->getFlags()); | 1105 UnimplementedError(getFlags()); |
1107 } | 1106 } |
1108 } | 1107 } |
1109 | 1108 |
1110 void TargetMIPS32::lowerPhi(const InstPhi * /*Instr*/) { | 1109 void TargetMIPS32::lowerPhi(const InstPhi * /*Instr*/) { |
1111 Func->setError("Phi found in regular instruction list"); | 1110 Func->setError("Phi found in regular instruction list"); |
1112 } | 1111 } |
1113 | 1112 |
1114 void TargetMIPS32::lowerRet(const InstRet *Instr) { | 1113 void TargetMIPS32::lowerRet(const InstRet *Instr) { |
1115 Variable *Reg = nullptr; | 1114 Variable *Reg = nullptr; |
1116 if (Instr->hasRetValue()) { | 1115 if (Instr->hasRetValue()) { |
(...skipping 26 matching lines...) Expand all Loading... |
1143 } | 1142 } |
1144 | 1143 |
1145 void TargetMIPS32::lowerSelect(const InstSelect *Instr) { | 1144 void TargetMIPS32::lowerSelect(const InstSelect *Instr) { |
1146 UnimplementedLoweringError(this, Instr); | 1145 UnimplementedLoweringError(this, Instr); |
1147 } | 1146 } |
1148 | 1147 |
1149 void TargetMIPS32::lowerStore(const InstStore *Instr) { | 1148 void TargetMIPS32::lowerStore(const InstStore *Instr) { |
1150 UnimplementedLoweringError(this, Instr); | 1149 UnimplementedLoweringError(this, Instr); |
1151 } | 1150 } |
1152 | 1151 |
1153 void TargetMIPS32::doAddressOptStore() { | 1152 void TargetMIPS32::doAddressOptStore() { UnimplementedError(getFlags()); } |
1154 UnimplementedError(Func->getContext()->getFlags()); | |
1155 } | |
1156 | 1153 |
1157 void TargetMIPS32::lowerSwitch(const InstSwitch *Instr) { | 1154 void TargetMIPS32::lowerSwitch(const InstSwitch *Instr) { |
1158 UnimplementedLoweringError(this, Instr); | 1155 UnimplementedLoweringError(this, Instr); |
1159 } | 1156 } |
1160 | 1157 |
1161 void TargetMIPS32::lowerUnreachable(const InstUnreachable *Instr) { | 1158 void TargetMIPS32::lowerUnreachable(const InstUnreachable *Instr) { |
1162 UnimplementedLoweringError(this, Instr); | 1159 UnimplementedLoweringError(this, Instr); |
1163 } | 1160 } |
1164 | 1161 |
1165 // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to preserve | 1162 // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to preserve |
1166 // integrity of liveness analysis. Undef values are also turned into zeroes, | 1163 // integrity of liveness analysis. Undef values are also turned into zeroes, |
1167 // since loOperand() and hiOperand() don't expect Undef input. | 1164 // since loOperand() and hiOperand() don't expect Undef input. |
1168 void TargetMIPS32::prelowerPhis() { | 1165 void TargetMIPS32::prelowerPhis() { |
1169 PhiLowering::prelowerPhis32Bit<TargetMIPS32>(this, Context.getNode(), Func); | 1166 PhiLowering::prelowerPhis32Bit<TargetMIPS32>(this, Context.getNode(), Func); |
1170 } | 1167 } |
1171 | 1168 |
1172 void TargetMIPS32::postLower() { | 1169 void TargetMIPS32::postLower() { |
1173 if (Ctx->getFlags().getOptLevel() == Opt_m1) | 1170 if (getFlags().getOptLevel() == Opt_m1) |
1174 return; | 1171 return; |
1175 // TODO(rkotler): Find two-address non-SSA instructions where Dest==Src0, | 1172 // TODO(rkotler): Find two-address non-SSA instructions where Dest==Src0, |
1176 // and set the IsDestRedefined flag to keep liveness analysis consistent. | 1173 // and set the IsDestRedefined flag to keep liveness analysis consistent. |
1177 UnimplementedError(Func->getContext()->getFlags()); | 1174 UnimplementedError(getFlags()); |
1178 } | 1175 } |
1179 | 1176 |
1180 void TargetMIPS32::makeRandomRegisterPermutation( | 1177 void TargetMIPS32::makeRandomRegisterPermutation( |
1181 llvm::SmallVectorImpl<RegNumT> &Permutation, | 1178 llvm::SmallVectorImpl<RegNumT> &Permutation, |
1182 const SmallBitVector &ExcludeRegisters, uint64_t Salt) const { | 1179 const SmallBitVector &ExcludeRegisters, uint64_t Salt) const { |
1183 (void)Permutation; | 1180 (void)Permutation; |
1184 (void)ExcludeRegisters; | 1181 (void)ExcludeRegisters; |
1185 (void)Salt; | 1182 (void)Salt; |
1186 UnimplementedError(Func->getContext()->getFlags()); | 1183 UnimplementedError(getFlags()); |
1187 } | 1184 } |
1188 | 1185 |
1189 /* TODO(jvoung): avoid duplicate symbols with multiple targets. | 1186 /* TODO(jvoung): avoid duplicate symbols with multiple targets. |
1190 void ConstantUndef::emitWithoutDollar(GlobalContext *) const { | 1187 void ConstantUndef::emitWithoutDollar(GlobalContext *) const { |
1191 llvm_unreachable("Not expecting to emitWithoutDollar undef"); | 1188 llvm_unreachable("Not expecting to emitWithoutDollar undef"); |
1192 } | 1189 } |
1193 | 1190 |
1194 void ConstantUndef::emit(GlobalContext *) const { | 1191 void ConstantUndef::emit(GlobalContext *) const { |
1195 llvm_unreachable("undef value encountered by emitter."); | 1192 llvm_unreachable("undef value encountered by emitter."); |
1196 } | 1193 } |
1197 */ | 1194 */ |
1198 | 1195 |
1199 TargetDataMIPS32::TargetDataMIPS32(GlobalContext *Ctx) | 1196 TargetDataMIPS32::TargetDataMIPS32(GlobalContext *Ctx) |
1200 : TargetDataLowering(Ctx) {} | 1197 : TargetDataLowering(Ctx) {} |
1201 | 1198 |
1202 void TargetDataMIPS32::lowerGlobals(const VariableDeclarationList &Vars, | 1199 void TargetDataMIPS32::lowerGlobals(const VariableDeclarationList &Vars, |
1203 const std::string &SectionSuffix) { | 1200 const std::string &SectionSuffix) { |
1204 const bool IsPIC = Ctx->getFlags().getUseNonsfi(); | 1201 const bool IsPIC = getFlags().getUseNonsfi(); |
1205 switch (Ctx->getFlags().getOutFileType()) { | 1202 switch (getFlags().getOutFileType()) { |
1206 case FT_Elf: { | 1203 case FT_Elf: { |
1207 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | 1204 ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
1208 Writer->writeDataSection(Vars, llvm::ELF::R_MIPS_GLOB_DAT, SectionSuffix, | 1205 Writer->writeDataSection(Vars, llvm::ELF::R_MIPS_GLOB_DAT, SectionSuffix, |
1209 IsPIC); | 1206 IsPIC); |
1210 } break; | 1207 } break; |
1211 case FT_Asm: | 1208 case FT_Asm: |
1212 case FT_Iasm: { | 1209 case FT_Iasm: { |
1213 const std::string TranslateOnly = Ctx->getFlags().getTranslateOnly(); | 1210 const std::string TranslateOnly = getFlags().getTranslateOnly(); |
1214 OstreamLocker L(Ctx); | 1211 OstreamLocker L(Ctx); |
1215 for (const VariableDeclaration *Var : Vars) { | 1212 for (const VariableDeclaration *Var : Vars) { |
1216 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) { | 1213 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) { |
1217 emitGlobal(*Var, SectionSuffix); | 1214 emitGlobal(*Var, SectionSuffix); |
1218 } | 1215 } |
1219 } | 1216 } |
1220 } break; | 1217 } break; |
1221 } | 1218 } |
1222 } | 1219 } |
1223 | 1220 |
1224 void TargetDataMIPS32::lowerConstants() { | 1221 void TargetDataMIPS32::lowerConstants() { |
1225 if (Ctx->getFlags().getDisableTranslation()) | 1222 if (getFlags().getDisableTranslation()) |
1226 return; | 1223 return; |
1227 UnimplementedError(Ctx->getFlags()); | 1224 UnimplementedError(getFlags()); |
1228 } | 1225 } |
1229 | 1226 |
1230 void TargetDataMIPS32::lowerJumpTables() { | 1227 void TargetDataMIPS32::lowerJumpTables() { |
1231 if (Ctx->getFlags().getDisableTranslation()) | 1228 if (getFlags().getDisableTranslation()) |
1232 return; | 1229 return; |
1233 UnimplementedError(Ctx->getFlags()); | 1230 UnimplementedError(getFlags()); |
1234 } | 1231 } |
1235 | 1232 |
1236 // Helper for legalize() to emit the right code to lower an operand to a | 1233 // Helper for legalize() to emit the right code to lower an operand to a |
1237 // register of the appropriate type. | 1234 // register of the appropriate type. |
1238 Variable *TargetMIPS32::copyToReg(Operand *Src, RegNumT RegNum) { | 1235 Variable *TargetMIPS32::copyToReg(Operand *Src, RegNumT RegNum) { |
1239 Type Ty = Src->getType(); | 1236 Type Ty = Src->getType(); |
1240 Variable *Reg = makeReg(Ty, RegNum); | 1237 Variable *Reg = makeReg(Ty, RegNum); |
1241 if (isVectorType(Ty) || isFloatingType(Ty)) { | 1238 if (isVectorType(Ty) || isFloatingType(Ty)) { |
1242 UnimplementedError(Ctx->getFlags()); | 1239 UnimplementedError(getFlags()); |
1243 } else { | 1240 } else { |
1244 // Mov's Src operand can really only be the flexible second operand type | 1241 // Mov's Src operand can really only be the flexible second operand type |
1245 // or a register. Users should guarantee that. | 1242 // or a register. Users should guarantee that. |
1246 _mov(Reg, Src); | 1243 _mov(Reg, Src); |
1247 } | 1244 } |
1248 return Reg; | 1245 return Reg; |
1249 } | 1246 } |
1250 | 1247 |
1251 Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed, | 1248 Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed, |
1252 RegNumT RegNum) { | 1249 RegNumT RegNum) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1321 Str << "\t.set\t" | 1318 Str << "\t.set\t" |
1322 << "nomips16\n"; | 1319 << "nomips16\n"; |
1323 } | 1320 } |
1324 | 1321 |
1325 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; | 1322 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; |
1326 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; | 1323 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; |
1327 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; | 1324 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; |
1328 | 1325 |
1329 } // end of namespace MIPS32 | 1326 } // end of namespace MIPS32 |
1330 } // end of namespace Ice | 1327 } // end of namespace Ice |
OLD | NEW |