| OLD | NEW |
| 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// | 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 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 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 if (Flags.getTargetInstructionSet() != | 154 if (Flags.getTargetInstructionSet() != |
| 155 TargetInstructionSet::BaseInstructionSet) { | 155 TargetInstructionSet::BaseInstructionSet) { |
| 156 InstructionSet = static_cast<ARM32InstructionSet>( | 156 InstructionSet = static_cast<ARM32InstructionSet>( |
| 157 (Flags.getTargetInstructionSet() - | 157 (Flags.getTargetInstructionSet() - |
| 158 TargetInstructionSet::ARM32InstructionSet_Begin) + | 158 TargetInstructionSet::ARM32InstructionSet_Begin) + |
| 159 ARM32InstructionSet::Begin); | 159 ARM32InstructionSet::Begin); |
| 160 } | 160 } |
| 161 } | 161 } |
| 162 | 162 |
| 163 TargetARM32::TargetARM32(Cfg *Func) | 163 TargetARM32::TargetARM32(Cfg *Func) |
| 164 : TargetLowering(Func), NeedSandboxing(Ctx->getFlags().getUseSandboxing()), | 164 : TargetLowering(Func), CPUFeatures(Func->getContext()->getFlags()) {} |
| 165 CPUFeatures(Func->getContext()->getFlags()) {} | |
| 166 | 165 |
| 167 void TargetARM32::staticInit() { | 166 void TargetARM32::staticInit() { |
| 168 // Limit this size (or do all bitsets need to be the same width)??? | 167 // Limit this size (or do all bitsets need to be the same width)??? |
| 169 llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM); | 168 llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM); |
| 170 llvm::SmallBitVector I64PairRegisters(RegARM32::Reg_NUM); | 169 llvm::SmallBitVector I64PairRegisters(RegARM32::Reg_NUM); |
| 171 llvm::SmallBitVector Float32Registers(RegARM32::Reg_NUM); | 170 llvm::SmallBitVector Float32Registers(RegARM32::Reg_NUM); |
| 172 llvm::SmallBitVector Float64Registers(RegARM32::Reg_NUM); | 171 llvm::SmallBitVector Float64Registers(RegARM32::Reg_NUM); |
| 173 llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM); | 172 llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM); |
| 174 llvm::SmallBitVector InvalidRegisters(RegARM32::Reg_NUM); | 173 llvm::SmallBitVector InvalidRegisters(RegARM32::Reg_NUM); |
| 175 ScratchRegs.resize(RegARM32::Reg_NUM); | 174 ScratchRegs.resize(RegARM32::Reg_NUM); |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 538 auto *Call = InstCall::create(Func, MaxArgs, NoDest, TargetHelper, | 537 auto *Call = InstCall::create(Func, MaxArgs, NoDest, TargetHelper, |
| 539 NoTailCall, IsTargetHelperCall); | 538 NoTailCall, IsTargetHelperCall); |
| 540 Call->addArg(IntrinsicCall->getArg(0)); | 539 Call->addArg(IntrinsicCall->getArg(0)); |
| 541 Call->addArg(ValExt); | 540 Call->addArg(ValExt); |
| 542 Call->addArg(IntrinsicCall->getArg(2)); | 541 Call->addArg(IntrinsicCall->getArg(2)); |
| 543 Context.insert(Call); | 542 Context.insert(Call); |
| 544 Instr->setDeleted(); | 543 Instr->setDeleted(); |
| 545 return; | 544 return; |
| 546 } | 545 } |
| 547 case Intrinsics::NaClReadTP: { | 546 case Intrinsics::NaClReadTP: { |
| 548 if (NeedSandboxing) { | 547 if (Ctx->getFlags().getUseSandboxing()) { |
| 548 UnimplementedError(Func->getContext()->getFlags()); |
| 549 return; | 549 return; |
| 550 } | 550 } |
| 551 static constexpr SizeT MaxArgs = 0; | 551 static constexpr SizeT MaxArgs = 0; |
| 552 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_read_tp); | 552 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_read_tp); |
| 553 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper, | 553 auto *Call = InstCall::create(Func, MaxArgs, Dest, TargetHelper, |
| 554 NoTailCall, IsTargetHelperCall); | 554 NoTailCall, IsTargetHelperCall); |
| 555 Context.insert(Call); | 555 Context.insert(Call); |
| 556 Instr->setDeleted(); | 556 Instr->setDeleted(); |
| 557 return; | 557 return; |
| 558 } | 558 } |
| (...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1113 CalleeSaves[RegARM32::Reg_lr] = true; | 1113 CalleeSaves[RegARM32::Reg_lr] = true; |
| 1114 RegsUsed[RegARM32::Reg_lr] = true; | 1114 RegsUsed[RegARM32::Reg_lr] = true; |
| 1115 } | 1115 } |
| 1116 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { | 1116 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { |
| 1117 if (RegARM32::isI64RegisterPair(i)) { | 1117 if (RegARM32::isI64RegisterPair(i)) { |
| 1118 // We don't save register pairs explicitly. Instead, we rely on the code | 1118 // We don't save register pairs explicitly. Instead, we rely on the code |
| 1119 // fake-defing/fake-using each register in the pair. | 1119 // fake-defing/fake-using each register in the pair. |
| 1120 continue; | 1120 continue; |
| 1121 } | 1121 } |
| 1122 if (CalleeSaves[i] && RegsUsed[i]) { | 1122 if (CalleeSaves[i] && RegsUsed[i]) { |
| 1123 if (NeedSandboxing && i == RegARM32::Reg_r9) { | |
| 1124 // r9 is never updated in sandboxed code. | |
| 1125 continue; | |
| 1126 } | |
| 1127 ++NumCallee; | 1123 ++NumCallee; |
| 1128 Variable *PhysicalRegister = getPhysicalRegister(i); | 1124 Variable *PhysicalRegister = getPhysicalRegister(i); |
| 1129 PreservedRegsSizeBytes += | 1125 PreservedRegsSizeBytes += |
| 1130 typeWidthInBytesOnStack(PhysicalRegister->getType()); | 1126 typeWidthInBytesOnStack(PhysicalRegister->getType()); |
| 1131 GPRsToPreserve.push_back(getPhysicalRegister(i)); | 1127 GPRsToPreserve.push_back(getPhysicalRegister(i)); |
| 1132 } | 1128 } |
| 1133 } | 1129 } |
| 1134 Ctx->statsUpdateRegistersSaved(NumCallee); | 1130 Ctx->statsUpdateRegistersSaved(NumCallee); |
| 1135 if (!GPRsToPreserve.empty()) | 1131 if (!GPRsToPreserve.empty()) |
| 1136 _push(GPRsToPreserve); | 1132 _push(GPRsToPreserve); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1170 } | 1166 } |
| 1171 | 1167 |
| 1172 // Combine fixed alloca with SpillAreaSize. | 1168 // Combine fixed alloca with SpillAreaSize. |
| 1173 SpillAreaSizeBytes += FixedAllocaSizeBytes; | 1169 SpillAreaSizeBytes += FixedAllocaSizeBytes; |
| 1174 | 1170 |
| 1175 // Generate "sub sp, SpillAreaSizeBytes" | 1171 // Generate "sub sp, SpillAreaSizeBytes" |
| 1176 if (SpillAreaSizeBytes) { | 1172 if (SpillAreaSizeBytes) { |
| 1177 // Use the scratch register if needed to legalize the immediate. | 1173 // Use the scratch register if needed to legalize the immediate. |
| 1178 Operand *SubAmount = legalize(Ctx->getConstantInt32(SpillAreaSizeBytes), | 1174 Operand *SubAmount = legalize(Ctx->getConstantInt32(SpillAreaSizeBytes), |
| 1179 Legal_Reg | Legal_Flex, getReservedTmpReg()); | 1175 Legal_Reg | Legal_Flex, getReservedTmpReg()); |
| 1180 AutoSandboxer(this).sub_sp(SubAmount); | 1176 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| 1177 _sub(SP, SP, SubAmount); |
| 1181 if (FixedAllocaAlignBytes > ARM32_STACK_ALIGNMENT_BYTES) { | 1178 if (FixedAllocaAlignBytes > ARM32_STACK_ALIGNMENT_BYTES) { |
| 1182 AutoSandboxer(this).align_sp(FixedAllocaAlignBytes); | 1179 alignRegisterPow2(SP, FixedAllocaAlignBytes); |
| 1183 } | 1180 } |
| 1184 } | 1181 } |
| 1185 | 1182 |
| 1186 Ctx->statsUpdateFrameBytes(SpillAreaSizeBytes); | 1183 Ctx->statsUpdateFrameBytes(SpillAreaSizeBytes); |
| 1187 | 1184 |
| 1188 // Fill in stack offsets for stack args, and copy args into registers for | 1185 // Fill in stack offsets for stack args, and copy args into registers for |
| 1189 // those that were register-allocated. Args are pushed right to left, so | 1186 // those that were register-allocated. Args are pushed right to left, so |
| 1190 // Arg[0] is closest to the stack/frame pointer. | 1187 // Arg[0] is closest to the stack/frame pointer. |
| 1191 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); | 1188 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); |
| 1192 size_t BasicFrameOffset = PreservedRegsSizeBytes; | 1189 size_t BasicFrameOffset = PreservedRegsSizeBytes; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1266 Context.init(Node); | 1263 Context.init(Node); |
| 1267 Context.setInsertPoint(InsertPoint); | 1264 Context.setInsertPoint(InsertPoint); |
| 1268 | 1265 |
| 1269 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 1266 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| 1270 if (UsesFramePointer) { | 1267 if (UsesFramePointer) { |
| 1271 Variable *FP = getPhysicalRegister(RegARM32::Reg_fp); | 1268 Variable *FP = getPhysicalRegister(RegARM32::Reg_fp); |
| 1272 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake | 1269 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake |
| 1273 // use of SP before the assignment of SP=FP keeps previous SP adjustments | 1270 // use of SP before the assignment of SP=FP keeps previous SP adjustments |
| 1274 // from being dead-code eliminated. | 1271 // from being dead-code eliminated. |
| 1275 Context.insert(InstFakeUse::create(Func, SP)); | 1272 Context.insert(InstFakeUse::create(Func, SP)); |
| 1276 AutoSandboxer(this).reset_sp(FP); | 1273 _mov(SP, FP); |
| 1277 } else { | 1274 } else { |
| 1278 // add SP, SpillAreaSizeBytes | 1275 // add SP, SpillAreaSizeBytes |
| 1279 if (SpillAreaSizeBytes) { | 1276 if (SpillAreaSizeBytes) { |
| 1280 // Use the scratch register if needed to legalize the immediate. | 1277 // Use the scratch register if needed to legalize the immediate. |
| 1281 Operand *AddAmount = | 1278 Operand *AddAmount = |
| 1282 legalize(Ctx->getConstantInt32(SpillAreaSizeBytes), | 1279 legalize(Ctx->getConstantInt32(SpillAreaSizeBytes), |
| 1283 Legal_Reg | Legal_Flex, getReservedTmpReg()); | 1280 Legal_Reg | Legal_Flex, getReservedTmpReg()); |
| 1284 AutoSandboxer(this).add_sp(AddAmount); | 1281 _add(SP, SP, AddAmount); |
| 1285 } | 1282 } |
| 1286 } | 1283 } |
| 1287 | 1284 |
| 1288 // Add pop instructions for preserved registers. | 1285 // Add pop instructions for preserved registers. |
| 1289 llvm::SmallBitVector CalleeSaves = | 1286 llvm::SmallBitVector CalleeSaves = |
| 1290 getRegisterSet(RegSet_CalleeSave, RegSet_None); | 1287 getRegisterSet(RegSet_CalleeSave, RegSet_None); |
| 1291 VarList GPRsToRestore; | 1288 VarList GPRsToRestore; |
| 1292 GPRsToRestore.reserve(CalleeSaves.size()); | 1289 GPRsToRestore.reserve(CalleeSaves.size()); |
| 1293 // Consider FP and LR as callee-save / used as needed. | 1290 // Consider FP and LR as callee-save / used as needed. |
| 1294 if (UsesFramePointer) { | 1291 if (UsesFramePointer) { |
| 1295 CalleeSaves[RegARM32::Reg_fp] = true; | 1292 CalleeSaves[RegARM32::Reg_fp] = true; |
| 1296 } | 1293 } |
| 1297 if (!MaybeLeafFunc) { | 1294 if (!MaybeLeafFunc) { |
| 1298 CalleeSaves[RegARM32::Reg_lr] = true; | 1295 CalleeSaves[RegARM32::Reg_lr] = true; |
| 1299 } | 1296 } |
| 1300 // Pop registers in ascending order just like push (instead of in reverse | 1297 // Pop registers in ascending order just like push (instead of in reverse |
| 1301 // order). | 1298 // order). |
| 1302 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { | 1299 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { |
| 1303 if (RegARM32::isI64RegisterPair(i)) { | 1300 if (RegARM32::isI64RegisterPair(i)) { |
| 1304 continue; | 1301 continue; |
| 1305 } | 1302 } |
| 1306 | 1303 |
| 1307 if (CalleeSaves[i] && RegsUsed[i]) { | 1304 if (CalleeSaves[i] && RegsUsed[i]) { |
| 1308 if (NeedSandboxing && i == RegARM32::Reg_r9) { | |
| 1309 continue; | |
| 1310 } | |
| 1311 GPRsToRestore.push_back(getPhysicalRegister(i)); | 1305 GPRsToRestore.push_back(getPhysicalRegister(i)); |
| 1312 } | 1306 } |
| 1313 } | 1307 } |
| 1314 if (!GPRsToRestore.empty()) | 1308 if (!GPRsToRestore.empty()) |
| 1315 _pop(GPRsToRestore); | 1309 _pop(GPRsToRestore); |
| 1316 | 1310 |
| 1317 if (!Ctx->getFlags().getUseSandboxing()) | 1311 if (!Ctx->getFlags().getUseSandboxing()) |
| 1318 return; | 1312 return; |
| 1319 | 1313 |
| 1320 // Change the original ret instruction into a sandboxed return sequence. | 1314 // Change the original ret instruction into a sandboxed return sequence. |
| 1321 // bundle_lock | 1315 // bundle_lock |
| 1322 // bic lr, #0xc000000f | 1316 // bic lr, #0xc000000f |
| 1323 // bx lr | 1317 // bx lr |
| 1324 // bundle_unlock | 1318 // bundle_unlock |
| 1325 // This isn't just aligning to the getBundleAlignLog2Bytes(). It needs to | 1319 // This isn't just aligning to the getBundleAlignLog2Bytes(). It needs to |
| 1326 // restrict to the lower 1GB as well. | 1320 // restrict to the lower 1GB as well. |
| 1327 Variable *LR = getPhysicalRegister(RegARM32::Reg_lr); | 1321 Operand *RetMask = |
| 1322 legalize(Ctx->getConstantInt32(0xc000000f), Legal_Reg | Legal_Flex); |
| 1323 Variable *LR = makeReg(IceType_i32, RegARM32::Reg_lr); |
| 1328 Variable *RetValue = nullptr; | 1324 Variable *RetValue = nullptr; |
| 1329 if (RI->getSrcSize()) | 1325 if (RI->getSrcSize()) |
| 1330 RetValue = llvm::cast<Variable>(RI->getSrc(0)); | 1326 RetValue = llvm::cast<Variable>(RI->getSrc(0)); |
| 1331 | 1327 _bundle_lock(); |
| 1332 AutoSandboxer(this).ret(LR, RetValue); | 1328 _bic(LR, LR, RetMask); |
| 1333 | 1329 _ret(LR, RetValue); |
| 1330 _bundle_unlock(); |
| 1334 RI->setDeleted(); | 1331 RI->setDeleted(); |
| 1335 } | 1332 } |
| 1336 | 1333 |
| 1337 bool TargetARM32::isLegalMemOffset(Type Ty, int32_t Offset) const { | 1334 bool TargetARM32::isLegalMemOffset(Type Ty, int32_t Offset) const { |
| 1338 constexpr bool ZeroExt = false; | 1335 constexpr bool ZeroExt = false; |
| 1339 return OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset); | 1336 return OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset); |
| 1340 } | 1337 } |
| 1341 | 1338 |
| 1342 Variable *TargetARM32::PostLoweringLegalizer::newBaseRegister( | 1339 Variable *TargetARM32::PostLoweringLegalizer::newBaseRegister( |
| 1343 Variable *Base, int32_t Offset, int32_t ScratchRegNum) { | 1340 Variable *Base, int32_t Offset, int32_t ScratchRegNum) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1374 TempBaseOffset = 0; | 1371 TempBaseOffset = 0; |
| 1375 } | 1372 } |
| 1376 } | 1373 } |
| 1377 | 1374 |
| 1378 return ScratchReg; | 1375 return ScratchReg; |
| 1379 } | 1376 } |
| 1380 | 1377 |
| 1381 OperandARM32Mem *TargetARM32::PostLoweringLegalizer::createMemOperand( | 1378 OperandARM32Mem *TargetARM32::PostLoweringLegalizer::createMemOperand( |
| 1382 Type Ty, Variable *Base, int32_t Offset, bool AllowOffsets) { | 1379 Type Ty, Variable *Base, int32_t Offset, bool AllowOffsets) { |
| 1383 assert(!Base->isRematerializable()); | 1380 assert(!Base->isRematerializable()); |
| 1384 if (Offset == 0 || (AllowOffsets && Target->isLegalMemOffset(Ty, Offset))) { | 1381 if (AllowOffsets && Target->isLegalMemOffset(Ty, Offset)) { |
| 1385 return OperandARM32Mem::create( | 1382 return OperandARM32Mem::create( |
| 1386 Target->Func, Ty, Base, | 1383 Target->Func, Ty, Base, |
| 1387 llvm::cast<ConstantInteger32>(Target->Ctx->getConstantInt32(Offset)), | 1384 llvm::cast<ConstantInteger32>(Target->Ctx->getConstantInt32(Offset)), |
| 1388 OperandARM32Mem::Offset); | 1385 OperandARM32Mem::Offset); |
| 1389 } | 1386 } |
| 1390 | 1387 |
| 1391 if (!AllowOffsets || TempBaseReg == nullptr) { | 1388 if (!AllowOffsets || TempBaseReg == nullptr) { |
| 1392 newBaseRegister(Base, Offset, Target->getReservedTmpReg()); | 1389 newBaseRegister(Base, Offset, Target->getReservedTmpReg()); |
| 1393 } | 1390 } |
| 1394 | 1391 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1447 if (MovInstr->isMultiDest() || MovInstr->isMultiSource()) | 1444 if (MovInstr->isMultiDest() || MovInstr->isMultiSource()) |
| 1448 return; | 1445 return; |
| 1449 | 1446 |
| 1450 bool Legalized = false; | 1447 bool Legalized = false; |
| 1451 if (!Dest->hasReg()) { | 1448 if (!Dest->hasReg()) { |
| 1452 auto *SrcR = llvm::cast<Variable>(Src); | 1449 auto *SrcR = llvm::cast<Variable>(Src); |
| 1453 assert(SrcR->hasReg()); | 1450 assert(SrcR->hasReg()); |
| 1454 assert(!SrcR->isRematerializable()); | 1451 assert(!SrcR->isRematerializable()); |
| 1455 const int32_t Offset = Dest->getStackOffset(); | 1452 const int32_t Offset = Dest->getStackOffset(); |
| 1456 // This is a _mov(Mem(), Variable), i.e., a store. | 1453 // This is a _mov(Mem(), Variable), i.e., a store. |
| 1457 TargetARM32::AutoSandboxer(Target) | 1454 Target->_str(SrcR, createMemOperand(DestTy, StackOrFrameReg, Offset), |
| 1458 .str(SrcR, createMemOperand(DestTy, StackOrFrameReg, Offset), | 1455 MovInstr->getPredicate()); |
| 1459 MovInstr->getPredicate()); | |
| 1460 // _str() does not have a Dest, so we add a fake-def(Dest). | 1456 // _str() does not have a Dest, so we add a fake-def(Dest). |
| 1461 Target->Context.insert(InstFakeDef::create(Target->Func, Dest)); | 1457 Target->Context.insert(InstFakeDef::create(Target->Func, Dest)); |
| 1462 Legalized = true; | 1458 Legalized = true; |
| 1463 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { | 1459 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { |
| 1464 if (Var->isRematerializable()) { | 1460 if (Var->isRematerializable()) { |
| 1465 // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable). | 1461 // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable). |
| 1466 | 1462 |
| 1467 // ExtraOffset is only needed for frame-pointer based frames as we have | 1463 // ExtraOffset is only needed for frame-pointer based frames as we have |
| 1468 // to account for spill storage. | 1464 // to account for spill storage. |
| 1469 const int32_t ExtraOffset = | 1465 const int32_t ExtraOffset = |
| 1470 (static_cast<SizeT>(Var->getRegNum()) == Target->getFrameReg()) | 1466 (static_cast<SizeT>(Var->getRegNum()) == Target->getFrameReg()) |
| 1471 ? Target->getFrameFixedAllocaOffset() | 1467 ? Target->getFrameFixedAllocaOffset() |
| 1472 : 0; | 1468 : 0; |
| 1473 | 1469 |
| 1474 const int32_t Offset = Var->getStackOffset() + ExtraOffset; | 1470 const int32_t Offset = Var->getStackOffset() + ExtraOffset; |
| 1475 Variable *Base = Target->getPhysicalRegister(Var->getRegNum()); | 1471 Variable *Base = Target->getPhysicalRegister(Var->getRegNum()); |
| 1476 Variable *T = newBaseRegister(Base, Offset, Dest->getRegNum()); | 1472 Variable *T = newBaseRegister(Base, Offset, Dest->getRegNum()); |
| 1477 Target->_mov(Dest, T); | 1473 Target->_mov(Dest, T); |
| 1478 Legalized = true; | 1474 Legalized = true; |
| 1479 } else { | 1475 } else { |
| 1480 if (!Var->hasReg()) { | 1476 if (!Var->hasReg()) { |
| 1481 // This is a _mov(Variable, Mem()), i.e., a load. | 1477 // This is a _mov(Variable, Mem()), i.e., a load. |
| 1482 const int32_t Offset = Var->getStackOffset(); | 1478 const int32_t Offset = Var->getStackOffset(); |
| 1483 TargetARM32::AutoSandboxer(Target) | 1479 Target->_ldr(Dest, createMemOperand(DestTy, StackOrFrameReg, Offset), |
| 1484 .ldr(Dest, createMemOperand(DestTy, StackOrFrameReg, Offset), | 1480 MovInstr->getPredicate()); |
| 1485 MovInstr->getPredicate()); | |
| 1486 Legalized = true; | 1481 Legalized = true; |
| 1487 } | 1482 } |
| 1488 } | 1483 } |
| 1489 } | 1484 } |
| 1490 | 1485 |
| 1491 if (Legalized) { | 1486 if (Legalized) { |
| 1492 if (MovInstr->isDestRedefined()) { | 1487 if (MovInstr->isDestRedefined()) { |
| 1493 Target->_set_dest_redefined(); | 1488 Target->_set_dest_redefined(); |
| 1494 } | 1489 } |
| 1495 MovInstr->setDeleted(); | 1490 MovInstr->setDeleted(); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1540 const int32_t ExtraOffset = | 1535 const int32_t ExtraOffset = |
| 1541 (static_cast<SizeT>(Base->getRegNum()) == Target->getFrameReg()) | 1536 (static_cast<SizeT>(Base->getRegNum()) == Target->getFrameReg()) |
| 1542 ? Target->getFrameFixedAllocaOffset() | 1537 ? Target->getFrameFixedAllocaOffset() |
| 1543 : 0; | 1538 : 0; |
| 1544 Offset += Base->getStackOffset() + ExtraOffset; | 1539 Offset += Base->getStackOffset() + ExtraOffset; |
| 1545 Base = Target->getPhysicalRegister(Base->getRegNum()); | 1540 Base = Target->getPhysicalRegister(Base->getRegNum()); |
| 1546 assert(!Base->isRematerializable()); | 1541 assert(!Base->isRematerializable()); |
| 1547 Legalized = true; | 1542 Legalized = true; |
| 1548 } | 1543 } |
| 1549 | 1544 |
| 1550 if (!Legalized && !Target->NeedSandboxing) { | 1545 if (!Legalized) { |
| 1551 return nullptr; | 1546 return nullptr; |
| 1552 } | 1547 } |
| 1553 | 1548 |
| 1554 if (Target->NeedSandboxing && Base->getRegNum() == RegARM32::Reg_r9) { | |
| 1555 if (Legalized) { | |
| 1556 llvm::report_fatal_error("r9-based mem operand should not need to be " | |
| 1557 "legalized."); | |
| 1558 } | |
| 1559 return nullptr; | |
| 1560 } | |
| 1561 | |
| 1562 if (!Mem->isRegReg()) { | 1549 if (!Mem->isRegReg()) { |
| 1563 return createMemOperand(Mem->getType(), Base, Offset, AllowOffsets); | 1550 return createMemOperand(Mem->getType(), Base, Offset, AllowOffsets); |
| 1564 } | 1551 } |
| 1565 | 1552 |
| 1566 assert(!Target->NeedSandboxing); | |
| 1567 assert(MemTraits[Mem->getType()].CanHaveIndex); | 1553 assert(MemTraits[Mem->getType()].CanHaveIndex); |
| 1568 | 1554 |
| 1569 if (Offset != 0) { | 1555 if (Offset != 0) { |
| 1570 if (TempBaseReg == nullptr) { | 1556 if (TempBaseReg == nullptr) { |
| 1571 Base = newBaseRegister(Base, Offset, Target->getReservedTmpReg()); | 1557 Base = newBaseRegister(Base, Offset, Target->getReservedTmpReg()); |
| 1572 } else { | 1558 } else { |
| 1573 uint32_t Imm8, Rotate; | 1559 uint32_t Imm8, Rotate; |
| 1574 const int32_t OffsetDiff = Offset - TempBaseOffset; | 1560 const int32_t OffsetDiff = Offset - TempBaseOffset; |
| 1575 if (OffsetDiff == 0) { | 1561 if (OffsetDiff == 0) { |
| 1576 Base = TempBaseReg; | 1562 Base = TempBaseReg; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1628 Inst *CurInstr = Context.getCur(); | 1614 Inst *CurInstr = Context.getCur(); |
| 1629 | 1615 |
| 1630 // Check if the previous TempBaseReg is clobbered, and reset if needed. | 1616 // Check if the previous TempBaseReg is clobbered, and reset if needed. |
| 1631 Legalizer.resetTempBaseIfClobberedBy(CurInstr); | 1617 Legalizer.resetTempBaseIfClobberedBy(CurInstr); |
| 1632 | 1618 |
| 1633 if (auto *MovInstr = llvm::dyn_cast<InstARM32Mov>(CurInstr)) { | 1619 if (auto *MovInstr = llvm::dyn_cast<InstARM32Mov>(CurInstr)) { |
| 1634 Legalizer.legalizeMov(MovInstr); | 1620 Legalizer.legalizeMov(MovInstr); |
| 1635 } else if (auto *LdrInstr = llvm::dyn_cast<InstARM32Ldr>(CurInstr)) { | 1621 } else if (auto *LdrInstr = llvm::dyn_cast<InstARM32Ldr>(CurInstr)) { |
| 1636 if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand( | 1622 if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand( |
| 1637 llvm::cast<OperandARM32Mem>(LdrInstr->getSrc(0)))) { | 1623 llvm::cast<OperandARM32Mem>(LdrInstr->getSrc(0)))) { |
| 1638 AutoSandboxer(this) | 1624 _ldr(CurInstr->getDest(), LegalMem, LdrInstr->getPredicate()); |
| 1639 .ldr(CurInstr->getDest(), LegalMem, LdrInstr->getPredicate()); | |
| 1640 CurInstr->setDeleted(); | 1625 CurInstr->setDeleted(); |
| 1641 } | 1626 } |
| 1642 } else if (auto *LdrexInstr = llvm::dyn_cast<InstARM32Ldrex>(CurInstr)) { | 1627 } else if (auto *LdrexInstr = llvm::dyn_cast<InstARM32Ldrex>(CurInstr)) { |
| 1643 constexpr bool DisallowOffsetsBecauseLdrex = false; | 1628 constexpr bool DisallowOffsetsBecauseLdrex = false; |
| 1644 if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand( | 1629 if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand( |
| 1645 llvm::cast<OperandARM32Mem>(LdrexInstr->getSrc(0)), | 1630 llvm::cast<OperandARM32Mem>(LdrexInstr->getSrc(0)), |
| 1646 DisallowOffsetsBecauseLdrex)) { | 1631 DisallowOffsetsBecauseLdrex)) { |
| 1647 AutoSandboxer(this) | 1632 _ldrex(CurInstr->getDest(), LegalMem, LdrexInstr->getPredicate()); |
| 1648 .ldrex(CurInstr->getDest(), LegalMem, LdrexInstr->getPredicate()); | |
| 1649 CurInstr->setDeleted(); | 1633 CurInstr->setDeleted(); |
| 1650 } | 1634 } |
| 1651 } else if (auto *StrInstr = llvm::dyn_cast<InstARM32Str>(CurInstr)) { | 1635 } else if (auto *StrInstr = llvm::dyn_cast<InstARM32Str>(CurInstr)) { |
| 1652 AutoSandboxer Bundle(this); | |
| 1653 if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand( | 1636 if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand( |
| 1654 llvm::cast<OperandARM32Mem>(StrInstr->getSrc(1)))) { | 1637 llvm::cast<OperandARM32Mem>(StrInstr->getSrc(1)))) { |
| 1655 AutoSandboxer(this).str(llvm::cast<Variable>(CurInstr->getSrc(0)), | 1638 _str(llvm::cast<Variable>(CurInstr->getSrc(0)), LegalMem, |
| 1656 LegalMem, StrInstr->getPredicate()); | 1639 StrInstr->getPredicate()); |
| 1657 CurInstr->setDeleted(); | 1640 CurInstr->setDeleted(); |
| 1658 } | 1641 } |
| 1659 } else if (auto *StrexInstr = llvm::dyn_cast<InstARM32Strex>(CurInstr)) { | 1642 } else if (auto *StrexInstr = llvm::dyn_cast<InstARM32Strex>(CurInstr)) { |
| 1660 constexpr bool DisallowOffsetsBecauseStrex = false; | 1643 constexpr bool DisallowOffsetsBecauseStrex = false; |
| 1661 if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand( | 1644 if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand( |
| 1662 llvm::cast<OperandARM32Mem>(StrexInstr->getSrc(1)), | 1645 llvm::cast<OperandARM32Mem>(StrexInstr->getSrc(1)), |
| 1663 DisallowOffsetsBecauseStrex)) { | 1646 DisallowOffsetsBecauseStrex)) { |
| 1664 AutoSandboxer(this).strex(CurInstr->getDest(), | 1647 _strex(CurInstr->getDest(), llvm::cast<Variable>(CurInstr->getSrc(0)), |
| 1665 llvm::cast<Variable>(CurInstr->getSrc(0)), | 1648 LegalMem, StrexInstr->getPredicate()); |
| 1666 LegalMem, StrexInstr->getPredicate()); | |
| 1667 CurInstr->setDeleted(); | 1649 CurInstr->setDeleted(); |
| 1668 } | 1650 } |
| 1669 } | 1651 } |
| 1670 | 1652 |
| 1671 // Sanity-check: the Legalizer will either have no Temp, or it will be | 1653 // Sanity-check: the Legalizer will either have no Temp, or it will be |
| 1672 // bound to IP. | 1654 // bound to IP. |
| 1673 Legalizer.assertNoTempOrAssignedToIP(); | 1655 Legalizer.assertNoTempOrAssignedToIP(); |
| 1674 } | 1656 } |
| 1675 } | 1657 } |
| 1676 } | 1658 } |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1814 const bool OptM1 = Ctx->getFlags().getOptLevel() == Opt_m1; | 1796 const bool OptM1 = Ctx->getFlags().getOptLevel() == Opt_m1; |
| 1815 const bool AllocaWithKnownOffset = Inst->getKnownFrameOffset(); | 1797 const bool AllocaWithKnownOffset = Inst->getKnownFrameOffset(); |
| 1816 const bool UseFramePointer = | 1798 const bool UseFramePointer = |
| 1817 hasFramePointer() || OverAligned || !AllocaWithKnownOffset || OptM1; | 1799 hasFramePointer() || OverAligned || !AllocaWithKnownOffset || OptM1; |
| 1818 | 1800 |
| 1819 if (UseFramePointer) | 1801 if (UseFramePointer) |
| 1820 setHasFramePointer(); | 1802 setHasFramePointer(); |
| 1821 | 1803 |
| 1822 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 1804 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| 1823 if (OverAligned) { | 1805 if (OverAligned) { |
| 1824 AutoSandboxer(this).align_sp(Alignment); | 1806 alignRegisterPow2(SP, Alignment); |
| 1825 } | 1807 } |
| 1826 | 1808 |
| 1827 Variable *Dest = Inst->getDest(); | 1809 Variable *Dest = Inst->getDest(); |
| 1828 Operand *TotalSize = Inst->getSizeInBytes(); | 1810 Operand *TotalSize = Inst->getSizeInBytes(); |
| 1829 | 1811 |
| 1830 if (const auto *ConstantTotalSize = | 1812 if (const auto *ConstantTotalSize = |
| 1831 llvm::dyn_cast<ConstantInteger32>(TotalSize)) { | 1813 llvm::dyn_cast<ConstantInteger32>(TotalSize)) { |
| 1832 const uint32_t Value = | 1814 const uint32_t Value = |
| 1833 Utils::applyAlignment(ConstantTotalSize->getValue(), Alignment); | 1815 Utils::applyAlignment(ConstantTotalSize->getValue(), Alignment); |
| 1834 // Constant size alloca. | 1816 // Constant size alloca. |
| 1835 if (!UseFramePointer) { | 1817 if (!UseFramePointer) { |
| 1836 // If we don't need a Frame Pointer, this alloca has a known offset to the | 1818 // If we don't need a Frame Pointer, this alloca has a known offset to the |
| 1837 // stack pointer. We don't need adjust the stack pointer, nor assign any | 1819 // stack pointer. We don't need adjust the stack pointer, nor assign any |
| 1838 // value to Dest, as Dest is rematerializable. | 1820 // value to Dest, as Dest is rematerializable. |
| 1839 assert(Dest->isRematerializable()); | 1821 assert(Dest->isRematerializable()); |
| 1840 FixedAllocaSizeBytes += Value; | 1822 FixedAllocaSizeBytes += Value; |
| 1841 Context.insert(InstFakeDef::create(Func, Dest)); | 1823 Context.insert(InstFakeDef::create(Func, Dest)); |
| 1842 return; | 1824 return; |
| 1843 } | 1825 } |
| 1844 | 1826 |
| 1845 // If a frame pointer is required, then we need to store the alloca'd result | 1827 // If a frame pointer is required, then we need to store the alloca'd result |
| 1846 // in Dest. | 1828 // in Dest. |
| 1847 Operand *SubAmountRF = | 1829 Operand *SubAmountRF = |
| 1848 legalize(Ctx->getConstantInt32(Value), Legal_Reg | Legal_Flex); | 1830 legalize(Ctx->getConstantInt32(Value), Legal_Reg | Legal_Flex); |
| 1849 AutoSandboxer(this).sub_sp(SubAmountRF); | 1831 _sub(SP, SP, SubAmountRF); |
| 1850 } else { | 1832 } else { |
| 1851 // Non-constant sizes need to be adjusted to the next highest multiple of | 1833 // Non-constant sizes need to be adjusted to the next highest multiple of |
| 1852 // the required alignment at runtime. | 1834 // the required alignment at runtime. |
| 1853 TotalSize = legalize(TotalSize, Legal_Reg | Legal_Flex); | 1835 TotalSize = legalize(TotalSize, Legal_Reg | Legal_Flex); |
| 1854 Variable *T = makeReg(IceType_i32); | 1836 Variable *T = makeReg(IceType_i32); |
| 1855 _mov(T, TotalSize); | 1837 _mov(T, TotalSize); |
| 1856 Operand *AddAmount = legalize(Ctx->getConstantInt32(Alignment - 1)); | 1838 Operand *AddAmount = legalize(Ctx->getConstantInt32(Alignment - 1)); |
| 1857 _add(T, T, AddAmount); | 1839 _add(T, T, AddAmount); |
| 1858 alignRegisterPow2(T, Alignment); | 1840 alignRegisterPow2(T, Alignment); |
| 1859 AutoSandboxer(this).sub_sp(T); | 1841 _sub(SP, SP, T); |
| 1860 } | 1842 } |
| 1861 | 1843 |
| 1862 // Adds back a few bytes to SP to account for the out args area. | 1844 // Adds back a few bytes to SP to account for the out args area. |
| 1863 Variable *T = SP; | 1845 Variable *T = SP; |
| 1864 if (MaxOutArgsSizeBytes != 0) { | 1846 if (MaxOutArgsSizeBytes != 0) { |
| 1865 T = makeReg(getPointerType()); | 1847 T = makeReg(getPointerType()); |
| 1866 Operand *OutArgsSizeRF = legalize( | 1848 Operand *OutArgsSizeRF = legalize( |
| 1867 Ctx->getConstantInt32(MaxOutArgsSizeBytes), Legal_Reg | Legal_Flex); | 1849 Ctx->getConstantInt32(MaxOutArgsSizeBytes), Legal_Reg | Legal_Flex); |
| 1868 _add(T, SP, OutArgsSizeRF); | 1850 _add(T, SP, OutArgsSizeRF); |
| 1869 } | 1851 } |
| (...skipping 1390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3260 case IceType_v8i1: | 3242 case IceType_v8i1: |
| 3261 case IceType_v16i1: | 3243 case IceType_v16i1: |
| 3262 case IceType_v16i8: | 3244 case IceType_v16i8: |
| 3263 case IceType_v8i16: | 3245 case IceType_v8i16: |
| 3264 case IceType_v4i32: | 3246 case IceType_v4i32: |
| 3265 case IceType_v4f32: | 3247 case IceType_v4f32: |
| 3266 ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_q0); | 3248 ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_q0); |
| 3267 break; | 3249 break; |
| 3268 } | 3250 } |
| 3269 } | 3251 } |
| 3252 // TODO(jvoung): Handle sandboxing. const bool NeedSandboxing = |
| 3253 // Ctx->getFlags().getUseSandboxing(); |
| 3270 | 3254 |
| 3271 // Allow ConstantRelocatable to be left alone as a direct call, but force | 3255 // Allow ConstantRelocatable to be left alone as a direct call, but force |
| 3272 // other constants like ConstantInteger32 to be in a register and make it an | 3256 // other constants like ConstantInteger32 to be in a register and make it an |
| 3273 // indirect call. | 3257 // indirect call. |
| 3274 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { | 3258 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { |
| 3275 CallTarget = legalize(CallTarget, Legal_Reg); | 3259 CallTarget = legalize(CallTarget, Legal_Reg); |
| 3276 } | 3260 } |
| 3277 | 3261 |
| 3278 // Copy arguments to be passed in registers to the appropriate registers. | 3262 // Copy arguments to be passed in registers to the appropriate registers. |
| 3279 for (auto &FPArg : FPArgs) { | 3263 for (auto &FPArg : FPArgs) { |
| 3280 Variable *Reg = legalizeToReg(FPArg.first, FPArg.second); | 3264 Variable *Reg = legalizeToReg(FPArg.first, FPArg.second); |
| 3281 Context.insert(InstFakeUse::create(Func, Reg)); | 3265 Context.insert(InstFakeUse::create(Func, Reg)); |
| 3282 } | 3266 } |
| 3283 for (auto &GPRArg : GPRArgs) { | 3267 for (auto &GPRArg : GPRArgs) { |
| 3284 Variable *Reg = legalizeToReg(GPRArg.first, GPRArg.second); | 3268 Variable *Reg = legalizeToReg(GPRArg.first, GPRArg.second); |
| 3285 // Generate a FakeUse of register arguments so that they do not get dead | 3269 // Generate a FakeUse of register arguments so that they do not get dead |
| 3286 // code eliminated as a result of the FakeKill of scratch registers after | 3270 // code eliminated as a result of the FakeKill of scratch registers after |
| 3287 // the call. | 3271 // the call. |
| 3288 Context.insert(InstFakeUse::create(Func, Reg)); | 3272 Context.insert(InstFakeUse::create(Func, Reg)); |
| 3289 } | 3273 } |
| 3290 | 3274 Inst *NewCall = InstARM32Call::create(Func, ReturnReg, CallTarget); |
| 3291 InstARM32Call *NewCall = AutoSandboxer(this, InstBundleLock::Opt_AlignToEnd) | 3275 Context.insert(NewCall); |
| 3292 .bl(ReturnReg, CallTarget); | |
| 3293 | |
| 3294 if (ReturnRegHi) | 3276 if (ReturnRegHi) |
| 3295 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); | 3277 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); |
| 3296 | 3278 |
| 3297 // Insert a register-kill pseudo instruction. | 3279 // Insert a register-kill pseudo instruction. |
| 3298 Context.insert(InstFakeKill::create(Func, NewCall)); | 3280 Context.insert(InstFakeKill::create(Func, NewCall)); |
| 3299 | 3281 |
| 3300 // Generate a FakeUse to keep the call live if necessary. | 3282 // Generate a FakeUse to keep the call live if necessary. |
| 3301 if (Instr->hasSideEffects() && ReturnReg) { | 3283 if (Instr->hasSideEffects() && ReturnReg) { |
| 3302 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); | 3284 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); |
| 3303 Context.insert(FakeUse); | 3285 Context.insert(FakeUse); |
| (...skipping 1319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4623 case Intrinsics::Memcpy: { | 4605 case Intrinsics::Memcpy: { |
| 4624 llvm::report_fatal_error("memcpy should have been prelowered."); | 4606 llvm::report_fatal_error("memcpy should have been prelowered."); |
| 4625 } | 4607 } |
| 4626 case Intrinsics::Memmove: { | 4608 case Intrinsics::Memmove: { |
| 4627 llvm::report_fatal_error("memmove should have been prelowered."); | 4609 llvm::report_fatal_error("memmove should have been prelowered."); |
| 4628 } | 4610 } |
| 4629 case Intrinsics::Memset: { | 4611 case Intrinsics::Memset: { |
| 4630 llvm::report_fatal_error("memmove should have been prelowered."); | 4612 llvm::report_fatal_error("memmove should have been prelowered."); |
| 4631 } | 4613 } |
| 4632 case Intrinsics::NaClReadTP: { | 4614 case Intrinsics::NaClReadTP: { |
| 4633 if (!NeedSandboxing) { | 4615 llvm::report_fatal_error("nacl-read-tp should have been prelowered."); |
| 4634 llvm::report_fatal_error("nacl-read-tp should have been prelowered."); | |
| 4635 } | |
| 4636 Variable *TP = legalizeToReg(OperandARM32Mem::create( | |
| 4637 Func, getPointerType(), getPhysicalRegister(RegARM32::Reg_r9), | |
| 4638 llvm::cast<ConstantInteger32>(Ctx->getConstantZero(IceType_i32)))); | |
| 4639 _mov(Dest, TP); | |
| 4640 return; | |
| 4641 } | 4616 } |
| 4642 case Intrinsics::Setjmp: { | 4617 case Intrinsics::Setjmp: { |
| 4643 llvm::report_fatal_error("setjmp should have been prelowered."); | 4618 llvm::report_fatal_error("setjmp should have been prelowered."); |
| 4644 } | 4619 } |
| 4645 case Intrinsics::Sqrt: { | 4620 case Intrinsics::Sqrt: { |
| 4646 Variable *Src = legalizeToReg(Instr->getArg(0)); | 4621 Variable *Src = legalizeToReg(Instr->getArg(0)); |
| 4647 Variable *T = makeReg(Dest->getType()); | 4622 Variable *T = makeReg(Dest->getType()); |
| 4648 _vsqrt(T, Src); | 4623 _vsqrt(T, Src); |
| 4649 _mov(Dest, T); | 4624 _mov(Dest, T); |
| 4650 return; | 4625 return; |
| 4651 } | 4626 } |
| 4652 case Intrinsics::Stacksave: { | 4627 case Intrinsics::Stacksave: { |
| 4653 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 4628 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| 4654 _mov(Dest, SP); | 4629 _mov(Dest, SP); |
| 4655 return; | 4630 return; |
| 4656 } | 4631 } |
| 4657 case Intrinsics::Stackrestore: { | 4632 case Intrinsics::Stackrestore: { |
| 4658 Variable *Val = legalizeToReg(Instr->getArg(0)); | 4633 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| 4659 AutoSandboxer(this).reset_sp(Val); | 4634 Operand *Val = legalize(Instr->getArg(0), Legal_Reg | Legal_Flex); |
| 4635 _mov_redefined(SP, Val); |
| 4660 return; | 4636 return; |
| 4661 } | 4637 } |
| 4662 case Intrinsics::Trap: | 4638 case Intrinsics::Trap: |
| 4663 _trap(); | 4639 _trap(); |
| 4664 return; | 4640 return; |
| 4665 case Intrinsics::UnknownIntrinsic: | 4641 case Intrinsics::UnknownIntrinsic: |
| 4666 Func->setError("Should not be lowering UnknownIntrinsic"); | 4642 Func->setError("Should not be lowering UnknownIntrinsic"); |
| 4667 return; | 4643 return; |
| 4668 } | 4644 } |
| 4669 return; | 4645 return; |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5004 // "[reg]" addressing mode (the other supported modes are write back.) | 4980 // "[reg]" addressing mode (the other supported modes are write back.) |
| 5005 return nullptr; | 4981 return nullptr; |
| 5006 | 4982 |
| 5007 auto *BaseVar = llvm::dyn_cast<Variable>(Base); | 4983 auto *BaseVar = llvm::dyn_cast<Variable>(Base); |
| 5008 if (BaseVar == nullptr) | 4984 if (BaseVar == nullptr) |
| 5009 return nullptr; | 4985 return nullptr; |
| 5010 | 4986 |
| 5011 (void)MemTraitsSize; | 4987 (void)MemTraitsSize; |
| 5012 assert(Ty < MemTraitsSize); | 4988 assert(Ty < MemTraitsSize); |
| 5013 auto *TypeTraits = &MemTraits[Ty]; | 4989 auto *TypeTraits = &MemTraits[Ty]; |
| 5014 const bool CanHaveIndex = !NeedSandboxing && TypeTraits->CanHaveIndex; | 4990 const bool CanHaveIndex = TypeTraits->CanHaveIndex; |
| 5015 const bool CanHaveShiftedIndex = | 4991 const bool CanHaveShiftedIndex = TypeTraits->CanHaveShiftedIndex; |
| 5016 !NeedSandboxing && TypeTraits->CanHaveShiftedIndex; | |
| 5017 const bool CanHaveImm = TypeTraits->CanHaveImm; | 4992 const bool CanHaveImm = TypeTraits->CanHaveImm; |
| 5018 const int32_t ValidImmMask = TypeTraits->ValidImmMask; | 4993 const int32_t ValidImmMask = TypeTraits->ValidImmMask; |
| 5019 (void)ValidImmMask; | 4994 (void)ValidImmMask; |
| 5020 assert(!CanHaveImm || ValidImmMask >= 0); | 4995 assert(!CanHaveImm || ValidImmMask >= 0); |
| 5021 | 4996 |
| 5022 const VariablesMetadata *VMetadata = Func->getVMetadata(); | 4997 const VariablesMetadata *VMetadata = Func->getVMetadata(); |
| 5023 const Inst *Reason = nullptr; | 4998 const Inst *Reason = nullptr; |
| 5024 | 4999 |
| 5025 do { | 5000 do { |
| 5026 if (Reason != nullptr) { | 5001 if (Reason != nullptr) { |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5178 Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex); | 5153 Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex); |
| 5179 Reg = makeReg(Src0F->getType(), RegARM32::Reg_r0); | 5154 Reg = makeReg(Src0F->getType(), RegARM32::Reg_r0); |
| 5180 _mov(Reg, Src0F, CondARM32::AL); | 5155 _mov(Reg, Src0F, CondARM32::AL); |
| 5181 } | 5156 } |
| 5182 } | 5157 } |
| 5183 // Add a ret instruction even if sandboxing is enabled, because addEpilog | 5158 // Add a ret instruction even if sandboxing is enabled, because addEpilog |
| 5184 // explicitly looks for a ret instruction as a marker for where to insert the | 5159 // explicitly looks for a ret instruction as a marker for where to insert the |
| 5185 // frame removal instructions. addEpilog is responsible for restoring the | 5160 // frame removal instructions. addEpilog is responsible for restoring the |
| 5186 // "lr" register as needed prior to this ret instruction. | 5161 // "lr" register as needed prior to this ret instruction. |
| 5187 _ret(getPhysicalRegister(RegARM32::Reg_lr), Reg); | 5162 _ret(getPhysicalRegister(RegARM32::Reg_lr), Reg); |
| 5188 | |
| 5189 // Add a fake use of sp to make sure sp stays alive for the entire function. | 5163 // Add a fake use of sp to make sure sp stays alive for the entire function. |
| 5190 // Otherwise post-call sp adjustments get dead-code eliminated. | 5164 // Otherwise post-call sp adjustments get dead-code eliminated. |
| 5191 // TODO: Are there more places where the fake use should be inserted? E.g. | 5165 // TODO: Are there more places where the fake use should be inserted? E.g. |
| 5192 // "void f(int n){while(1) g(n);}" may not have a ret instruction. | 5166 // "void f(int n){while(1) g(n);}" may not have a ret instruction. |
| 5193 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 5167 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| 5194 Context.insert(InstFakeUse::create(Func, SP)); | 5168 Context.insert(InstFakeUse::create(Func, SP)); |
| 5195 } | 5169 } |
| 5196 | 5170 |
| 5197 void TargetARM32::lowerSelect(const InstSelect *Inst) { | 5171 void TargetARM32::lowerSelect(const InstSelect *Inst) { |
| 5198 Variable *Dest = Inst->getDest(); | 5172 Variable *Dest = Inst->getDest(); |
| (...skipping 927 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6126 // Technically R9 is used for TLS with Sandboxing, and we reserve it. | 6100 // Technically R9 is used for TLS with Sandboxing, and we reserve it. |
| 6127 // However, for compatibility with current NaCl LLVM, don't claim that. | 6101 // However, for compatibility with current NaCl LLVM, don't claim that. |
| 6128 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 6102 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
| 6129 } | 6103 } |
| 6130 | 6104 |
| 6131 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; | 6105 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; |
| 6132 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; | 6106 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; |
| 6133 llvm::SmallBitVector TargetARM32::ScratchRegs; | 6107 llvm::SmallBitVector TargetARM32::ScratchRegs; |
| 6134 | 6108 |
| 6135 } // end of namespace Ice | 6109 } // end of namespace Ice |
| OLD | NEW |