| 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 |