Chromium Code Reviews| 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), CPUFeatures(Func->getContext()->getFlags()) {} | 164 : TargetLowering(Func), NeedSandboxing(Ctx->getFlags().getUseSandboxing()), |
| 165 CPUFeatures(Func->getContext()->getFlags()) {} | |
| 165 | 166 |
| 166 void TargetARM32::staticInit() { | 167 void TargetARM32::staticInit() { |
| 167 // Limit this size (or do all bitsets need to be the same width)??? | 168 // Limit this size (or do all bitsets need to be the same width)??? |
| 168 llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM); | 169 llvm::SmallBitVector IntegerRegisters(RegARM32::Reg_NUM); |
| 169 llvm::SmallBitVector I64PairRegisters(RegARM32::Reg_NUM); | 170 llvm::SmallBitVector I64PairRegisters(RegARM32::Reg_NUM); |
| 170 llvm::SmallBitVector Float32Registers(RegARM32::Reg_NUM); | 171 llvm::SmallBitVector Float32Registers(RegARM32::Reg_NUM); |
| 171 llvm::SmallBitVector Float64Registers(RegARM32::Reg_NUM); | 172 llvm::SmallBitVector Float64Registers(RegARM32::Reg_NUM); |
| 172 llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM); | 173 llvm::SmallBitVector VectorRegisters(RegARM32::Reg_NUM); |
| 173 llvm::SmallBitVector InvalidRegisters(RegARM32::Reg_NUM); | 174 llvm::SmallBitVector InvalidRegisters(RegARM32::Reg_NUM); |
| 174 ScratchRegs.resize(RegARM32::Reg_NUM); | 175 ScratchRegs.resize(RegARM32::Reg_NUM); |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 537 auto *Call = InstCall::create(Func, MaxArgs, NoDest, TargetHelper, | 538 auto *Call = InstCall::create(Func, MaxArgs, NoDest, TargetHelper, |
| 538 NoTailCall, IsTargetHelperCall); | 539 NoTailCall, IsTargetHelperCall); |
| 539 Call->addArg(IntrinsicCall->getArg(0)); | 540 Call->addArg(IntrinsicCall->getArg(0)); |
| 540 Call->addArg(ValExt); | 541 Call->addArg(ValExt); |
| 541 Call->addArg(IntrinsicCall->getArg(2)); | 542 Call->addArg(IntrinsicCall->getArg(2)); |
| 542 Context.insert(Call); | 543 Context.insert(Call); |
| 543 Instr->setDeleted(); | 544 Instr->setDeleted(); |
| 544 return; | 545 return; |
| 545 } | 546 } |
| 546 case Intrinsics::NaClReadTP: { | 547 case Intrinsics::NaClReadTP: { |
| 547 if (Ctx->getFlags().getUseSandboxing()) { | 548 if (NeedSandboxing) { |
| 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 } | |
| 1123 ++NumCallee; | 1127 ++NumCallee; |
| 1124 Variable *PhysicalRegister = getPhysicalRegister(i); | 1128 Variable *PhysicalRegister = getPhysicalRegister(i); |
| 1125 PreservedRegsSizeBytes += | 1129 PreservedRegsSizeBytes += |
| 1126 typeWidthInBytesOnStack(PhysicalRegister->getType()); | 1130 typeWidthInBytesOnStack(PhysicalRegister->getType()); |
| 1127 GPRsToPreserve.push_back(getPhysicalRegister(i)); | 1131 GPRsToPreserve.push_back(getPhysicalRegister(i)); |
| 1128 } | 1132 } |
| 1129 } | 1133 } |
| 1130 Ctx->statsUpdateRegistersSaved(NumCallee); | 1134 Ctx->statsUpdateRegistersSaved(NumCallee); |
| 1131 if (!GPRsToPreserve.empty()) | 1135 if (!GPRsToPreserve.empty()) |
| 1132 _push(GPRsToPreserve); | 1136 _push(GPRsToPreserve); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1166 } | 1170 } |
| 1167 | 1171 |
| 1168 // Combine fixed alloca with SpillAreaSize. | 1172 // Combine fixed alloca with SpillAreaSize. |
| 1169 SpillAreaSizeBytes += FixedAllocaSizeBytes; | 1173 SpillAreaSizeBytes += FixedAllocaSizeBytes; |
| 1170 | 1174 |
| 1171 // Generate "sub sp, SpillAreaSizeBytes" | 1175 // Generate "sub sp, SpillAreaSizeBytes" |
| 1172 if (SpillAreaSizeBytes) { | 1176 if (SpillAreaSizeBytes) { |
| 1173 // Use the scratch register if needed to legalize the immediate. | 1177 // Use the scratch register if needed to legalize the immediate. |
| 1174 Operand *SubAmount = legalize(Ctx->getConstantInt32(SpillAreaSizeBytes), | 1178 Operand *SubAmount = legalize(Ctx->getConstantInt32(SpillAreaSizeBytes), |
| 1175 Legal_Reg | Legal_Flex, getReservedTmpReg()); | 1179 Legal_Reg | Legal_Flex, getReservedTmpReg()); |
| 1176 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 1180 AutoSandboxer(this).sub_sp(SubAmount); |
| 1177 _sub(SP, SP, SubAmount); | |
| 1178 if (FixedAllocaAlignBytes > ARM32_STACK_ALIGNMENT_BYTES) { | 1181 if (FixedAllocaAlignBytes > ARM32_STACK_ALIGNMENT_BYTES) { |
| 1179 alignRegisterPow2(SP, FixedAllocaAlignBytes); | 1182 AutoSandboxer(this).align_sp(FixedAllocaAlignBytes); |
| 1180 } | 1183 } |
| 1181 } | 1184 } |
| 1182 | 1185 |
| 1183 Ctx->statsUpdateFrameBytes(SpillAreaSizeBytes); | 1186 Ctx->statsUpdateFrameBytes(SpillAreaSizeBytes); |
| 1184 | 1187 |
| 1185 // Fill in stack offsets for stack args, and copy args into registers for | 1188 // Fill in stack offsets for stack args, and copy args into registers for |
| 1186 // those that were register-allocated. Args are pushed right to left, so | 1189 // those that were register-allocated. Args are pushed right to left, so |
| 1187 // Arg[0] is closest to the stack/frame pointer. | 1190 // Arg[0] is closest to the stack/frame pointer. |
| 1188 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); | 1191 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); |
| 1189 size_t BasicFrameOffset = PreservedRegsSizeBytes; | 1192 size_t BasicFrameOffset = PreservedRegsSizeBytes; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1263 Context.init(Node); | 1266 Context.init(Node); |
| 1264 Context.setInsertPoint(InsertPoint); | 1267 Context.setInsertPoint(InsertPoint); |
| 1265 | 1268 |
| 1266 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 1269 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| 1267 if (UsesFramePointer) { | 1270 if (UsesFramePointer) { |
| 1268 Variable *FP = getPhysicalRegister(RegARM32::Reg_fp); | 1271 Variable *FP = getPhysicalRegister(RegARM32::Reg_fp); |
| 1269 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake | 1272 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake |
| 1270 // use of SP before the assignment of SP=FP keeps previous SP adjustments | 1273 // use of SP before the assignment of SP=FP keeps previous SP adjustments |
| 1271 // from being dead-code eliminated. | 1274 // from being dead-code eliminated. |
| 1272 Context.insert(InstFakeUse::create(Func, SP)); | 1275 Context.insert(InstFakeUse::create(Func, SP)); |
| 1273 _mov(SP, FP); | 1276 AutoSandboxer(this).reset_sp(FP); |
| 1274 } else { | 1277 } else { |
| 1275 // add SP, SpillAreaSizeBytes | 1278 // add SP, SpillAreaSizeBytes |
| 1276 if (SpillAreaSizeBytes) { | 1279 if (SpillAreaSizeBytes) { |
| 1277 // Use the scratch register if needed to legalize the immediate. | 1280 // Use the scratch register if needed to legalize the immediate. |
| 1278 Operand *AddAmount = | 1281 Operand *AddAmount = |
| 1279 legalize(Ctx->getConstantInt32(SpillAreaSizeBytes), | 1282 legalize(Ctx->getConstantInt32(SpillAreaSizeBytes), |
| 1280 Legal_Reg | Legal_Flex, getReservedTmpReg()); | 1283 Legal_Reg | Legal_Flex, getReservedTmpReg()); |
| 1281 _add(SP, SP, AddAmount); | 1284 AutoSandboxer(this).add_sp(AddAmount); |
| 1282 } | 1285 } |
| 1283 } | 1286 } |
| 1284 | 1287 |
| 1285 // Add pop instructions for preserved registers. | 1288 // Add pop instructions for preserved registers. |
| 1286 llvm::SmallBitVector CalleeSaves = | 1289 llvm::SmallBitVector CalleeSaves = |
| 1287 getRegisterSet(RegSet_CalleeSave, RegSet_None); | 1290 getRegisterSet(RegSet_CalleeSave, RegSet_None); |
| 1288 VarList GPRsToRestore; | 1291 VarList GPRsToRestore; |
| 1289 GPRsToRestore.reserve(CalleeSaves.size()); | 1292 GPRsToRestore.reserve(CalleeSaves.size()); |
| 1290 // Consider FP and LR as callee-save / used as needed. | 1293 // Consider FP and LR as callee-save / used as needed. |
| 1291 if (UsesFramePointer) { | 1294 if (UsesFramePointer) { |
| 1292 CalleeSaves[RegARM32::Reg_fp] = true; | 1295 CalleeSaves[RegARM32::Reg_fp] = true; |
| 1293 } | 1296 } |
| 1294 if (!MaybeLeafFunc) { | 1297 if (!MaybeLeafFunc) { |
| 1295 CalleeSaves[RegARM32::Reg_lr] = true; | 1298 CalleeSaves[RegARM32::Reg_lr] = true; |
| 1296 } | 1299 } |
| 1297 // Pop registers in ascending order just like push (instead of in reverse | 1300 // Pop registers in ascending order just like push (instead of in reverse |
| 1298 // order). | 1301 // order). |
| 1299 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { | 1302 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { |
| 1300 if (RegARM32::isI64RegisterPair(i)) { | 1303 if (RegARM32::isI64RegisterPair(i)) { |
| 1301 continue; | 1304 continue; |
| 1302 } | 1305 } |
| 1303 | 1306 |
| 1304 if (CalleeSaves[i] && RegsUsed[i]) { | 1307 if (CalleeSaves[i] && RegsUsed[i]) { |
| 1308 if (NeedSandboxing && i == RegARM32::Reg_r9) { | |
| 1309 continue; | |
| 1310 } | |
| 1305 GPRsToRestore.push_back(getPhysicalRegister(i)); | 1311 GPRsToRestore.push_back(getPhysicalRegister(i)); |
| 1306 } | 1312 } |
| 1307 } | 1313 } |
| 1308 if (!GPRsToRestore.empty()) | 1314 if (!GPRsToRestore.empty()) |
| 1309 _pop(GPRsToRestore); | 1315 _pop(GPRsToRestore); |
| 1310 | 1316 |
| 1311 if (!Ctx->getFlags().getUseSandboxing()) | 1317 if (!Ctx->getFlags().getUseSandboxing()) |
| 1312 return; | 1318 return; |
| 1313 | 1319 |
| 1314 // Change the original ret instruction into a sandboxed return sequence. | 1320 // Change the original ret instruction into a sandboxed return sequence. |
| 1315 // bundle_lock | 1321 // bundle_lock |
| 1316 // bic lr, #0xc000000f | 1322 // bic lr, #0xc000000f |
| 1317 // bx lr | 1323 // bx lr |
| 1318 // bundle_unlock | 1324 // bundle_unlock |
| 1319 // This isn't just aligning to the getBundleAlignLog2Bytes(). It needs to | 1325 // This isn't just aligning to the getBundleAlignLog2Bytes(). It needs to |
| 1320 // restrict to the lower 1GB as well. | 1326 // restrict to the lower 1GB as well. |
| 1321 Operand *RetMask = | 1327 Variable *LR = getPhysicalRegister(RegARM32::Reg_lr); |
| 1322 legalize(Ctx->getConstantInt32(0xc000000f), Legal_Reg | Legal_Flex); | |
| 1323 Variable *LR = makeReg(IceType_i32, RegARM32::Reg_lr); | |
| 1324 Variable *RetValue = nullptr; | 1328 Variable *RetValue = nullptr; |
| 1325 if (RI->getSrcSize()) | 1329 if (RI->getSrcSize()) |
| 1326 RetValue = llvm::cast<Variable>(RI->getSrc(0)); | 1330 RetValue = llvm::cast<Variable>(RI->getSrc(0)); |
| 1327 _bundle_lock(); | 1331 |
| 1328 _bic(LR, LR, RetMask); | 1332 AutoSandboxer(this).ret(LR, RetValue); |
| 1329 _ret(LR, RetValue); | 1333 |
| 1330 _bundle_unlock(); | |
| 1331 RI->setDeleted(); | 1334 RI->setDeleted(); |
| 1332 } | 1335 } |
| 1333 | 1336 |
| 1334 bool TargetARM32::isLegalMemOffset(Type Ty, int32_t Offset) const { | 1337 bool TargetARM32::isLegalMemOffset(Type Ty, int32_t Offset) const { |
| 1335 constexpr bool ZeroExt = false; | 1338 constexpr bool ZeroExt = false; |
| 1336 return OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset); | 1339 return OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset); |
| 1337 } | 1340 } |
| 1338 | 1341 |
| 1339 Variable *TargetARM32::PostLoweringLegalizer::newBaseRegister( | 1342 Variable *TargetARM32::PostLoweringLegalizer::newBaseRegister( |
| 1340 Variable *Base, int32_t Offset, int32_t ScratchRegNum) { | 1343 Variable *Base, int32_t Offset, int32_t ScratchRegNum) { |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 1371 TempBaseOffset = 0; | 1374 TempBaseOffset = 0; |
| 1372 } | 1375 } |
| 1373 } | 1376 } |
| 1374 | 1377 |
| 1375 return ScratchReg; | 1378 return ScratchReg; |
| 1376 } | 1379 } |
| 1377 | 1380 |
| 1378 OperandARM32Mem *TargetARM32::PostLoweringLegalizer::createMemOperand( | 1381 OperandARM32Mem *TargetARM32::PostLoweringLegalizer::createMemOperand( |
| 1379 Type Ty, Variable *Base, int32_t Offset, bool AllowOffsets) { | 1382 Type Ty, Variable *Base, int32_t Offset, bool AllowOffsets) { |
| 1380 assert(!Base->isRematerializable()); | 1383 assert(!Base->isRematerializable()); |
| 1381 if (AllowOffsets && Target->isLegalMemOffset(Ty, Offset)) { | 1384 if (Offset == 0 || (AllowOffsets && Target->isLegalMemOffset(Ty, Offset))) { |
| 1382 return OperandARM32Mem::create( | 1385 return OperandARM32Mem::create( |
| 1383 Target->Func, Ty, Base, | 1386 Target->Func, Ty, Base, |
| 1384 llvm::cast<ConstantInteger32>(Target->Ctx->getConstantInt32(Offset)), | 1387 llvm::cast<ConstantInteger32>(Target->Ctx->getConstantInt32(Offset)), |
| 1385 OperandARM32Mem::Offset); | 1388 OperandARM32Mem::Offset); |
| 1386 } | 1389 } |
| 1387 | 1390 |
| 1388 if (!AllowOffsets || TempBaseReg == nullptr) { | 1391 if (!AllowOffsets || TempBaseReg == nullptr) { |
| 1389 newBaseRegister(Base, Offset, Target->getReservedTmpReg()); | 1392 newBaseRegister(Base, Offset, Target->getReservedTmpReg()); |
| 1390 } | 1393 } |
| 1391 | 1394 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1444 if (MovInstr->isMultiDest() || MovInstr->isMultiSource()) | 1447 if (MovInstr->isMultiDest() || MovInstr->isMultiSource()) |
| 1445 return; | 1448 return; |
| 1446 | 1449 |
| 1447 bool Legalized = false; | 1450 bool Legalized = false; |
| 1448 if (!Dest->hasReg()) { | 1451 if (!Dest->hasReg()) { |
| 1449 auto *SrcR = llvm::cast<Variable>(Src); | 1452 auto *SrcR = llvm::cast<Variable>(Src); |
| 1450 assert(SrcR->hasReg()); | 1453 assert(SrcR->hasReg()); |
| 1451 assert(!SrcR->isRematerializable()); | 1454 assert(!SrcR->isRematerializable()); |
| 1452 const int32_t Offset = Dest->getStackOffset(); | 1455 const int32_t Offset = Dest->getStackOffset(); |
| 1453 // This is a _mov(Mem(), Variable), i.e., a store. | 1456 // This is a _mov(Mem(), Variable), i.e., a store. |
| 1454 Target->_str(SrcR, createMemOperand(DestTy, StackOrFrameReg, Offset), | 1457 TargetARM32::AutoSandboxer(Target) |
| 1455 MovInstr->getPredicate()); | 1458 .str(SrcR, createMemOperand(DestTy, StackOrFrameReg, Offset), |
| 1459 MovInstr->getPredicate()); | |
| 1456 // _str() does not have a Dest, so we add a fake-def(Dest). | 1460 // _str() does not have a Dest, so we add a fake-def(Dest). |
| 1457 Target->Context.insert(InstFakeDef::create(Target->Func, Dest)); | 1461 Target->Context.insert(InstFakeDef::create(Target->Func, Dest)); |
| 1458 Legalized = true; | 1462 Legalized = true; |
| 1459 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { | 1463 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { |
| 1460 if (Var->isRematerializable()) { | 1464 if (Var->isRematerializable()) { |
| 1461 // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable). | 1465 // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable). |
| 1462 | 1466 |
| 1463 // ExtraOffset is only needed for frame-pointer based frames as we have | 1467 // ExtraOffset is only needed for frame-pointer based frames as we have |
| 1464 // to account for spill storage. | 1468 // to account for spill storage. |
| 1465 const int32_t ExtraOffset = | 1469 const int32_t ExtraOffset = |
| 1466 (static_cast<SizeT>(Var->getRegNum()) == Target->getFrameReg()) | 1470 (static_cast<SizeT>(Var->getRegNum()) == Target->getFrameReg()) |
| 1467 ? Target->getFrameFixedAllocaOffset() | 1471 ? Target->getFrameFixedAllocaOffset() |
| 1468 : 0; | 1472 : 0; |
| 1469 | 1473 |
| 1470 const int32_t Offset = Var->getStackOffset() + ExtraOffset; | 1474 const int32_t Offset = Var->getStackOffset() + ExtraOffset; |
| 1471 Variable *Base = Target->getPhysicalRegister(Var->getRegNum()); | 1475 Variable *Base = Target->getPhysicalRegister(Var->getRegNum()); |
| 1472 Variable *T = newBaseRegister(Base, Offset, Dest->getRegNum()); | 1476 Variable *T = newBaseRegister(Base, Offset, Dest->getRegNum()); |
| 1473 Target->_mov(Dest, T); | 1477 Target->_mov(Dest, T); |
| 1474 Legalized = true; | 1478 Legalized = true; |
| 1475 } else { | 1479 } else { |
| 1476 if (!Var->hasReg()) { | 1480 if (!Var->hasReg()) { |
| 1477 // This is a _mov(Variable, Mem()), i.e., a load. | 1481 // This is a _mov(Variable, Mem()), i.e., a load. |
| 1478 const int32_t Offset = Var->getStackOffset(); | 1482 const int32_t Offset = Var->getStackOffset(); |
| 1479 Target->_ldr(Dest, createMemOperand(DestTy, StackOrFrameReg, Offset), | 1483 TargetARM32::AutoSandboxer(Target) |
| 1480 MovInstr->getPredicate()); | 1484 .ldr(Dest, createMemOperand(DestTy, StackOrFrameReg, Offset), |
| 1485 MovInstr->getPredicate()); | |
| 1481 Legalized = true; | 1486 Legalized = true; |
| 1482 } | 1487 } |
| 1483 } | 1488 } |
| 1484 } | 1489 } |
| 1485 | 1490 |
| 1486 if (Legalized) { | 1491 if (Legalized) { |
| 1487 if (MovInstr->isDestRedefined()) { | 1492 if (MovInstr->isDestRedefined()) { |
| 1488 Target->_set_dest_redefined(); | 1493 Target->_set_dest_redefined(); |
| 1489 } | 1494 } |
| 1490 MovInstr->setDeleted(); | 1495 MovInstr->setDeleted(); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1535 const int32_t ExtraOffset = | 1540 const int32_t ExtraOffset = |
| 1536 (static_cast<SizeT>(Base->getRegNum()) == Target->getFrameReg()) | 1541 (static_cast<SizeT>(Base->getRegNum()) == Target->getFrameReg()) |
| 1537 ? Target->getFrameFixedAllocaOffset() | 1542 ? Target->getFrameFixedAllocaOffset() |
| 1538 : 0; | 1543 : 0; |
| 1539 Offset += Base->getStackOffset() + ExtraOffset; | 1544 Offset += Base->getStackOffset() + ExtraOffset; |
| 1540 Base = Target->getPhysicalRegister(Base->getRegNum()); | 1545 Base = Target->getPhysicalRegister(Base->getRegNum()); |
| 1541 assert(!Base->isRematerializable()); | 1546 assert(!Base->isRematerializable()); |
| 1542 Legalized = true; | 1547 Legalized = true; |
| 1543 } | 1548 } |
| 1544 | 1549 |
| 1545 if (!Legalized) { | 1550 if (!Legalized && !Target->NeedSandboxing) { |
| 1546 return nullptr; | 1551 return nullptr; |
| 1547 } | 1552 } |
| 1548 | 1553 |
| 1549 if (!Mem->isRegReg()) { | 1554 if (!Mem->isRegReg()) { |
| 1550 return createMemOperand(Mem->getType(), Base, Offset, AllowOffsets); | 1555 return createMemOperand(Mem->getType(), Base, Offset, AllowOffsets); |
| 1551 } | 1556 } |
| 1552 | 1557 |
| 1558 if (Target->NeedSandboxing) { | |
| 1559 llvm::report_fatal_error("Reg-Reg address mode is not allowed."); | |
| 1560 } | |
| 1561 | |
| 1553 assert(MemTraits[Mem->getType()].CanHaveIndex); | 1562 assert(MemTraits[Mem->getType()].CanHaveIndex); |
| 1554 | 1563 |
| 1555 if (Offset != 0) { | 1564 if (Offset != 0) { |
| 1556 if (TempBaseReg == nullptr) { | 1565 if (TempBaseReg == nullptr) { |
| 1557 Base = newBaseRegister(Base, Offset, Target->getReservedTmpReg()); | 1566 Base = newBaseRegister(Base, Offset, Target->getReservedTmpReg()); |
| 1558 } else { | 1567 } else { |
| 1559 uint32_t Imm8, Rotate; | 1568 uint32_t Imm8, Rotate; |
| 1560 const int32_t OffsetDiff = Offset - TempBaseOffset; | 1569 const int32_t OffsetDiff = Offset - TempBaseOffset; |
| 1561 if (OffsetDiff == 0) { | 1570 if (OffsetDiff == 0) { |
| 1562 Base = TempBaseReg; | 1571 Base = TempBaseReg; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1614 Inst *CurInstr = Context.getCur(); | 1623 Inst *CurInstr = Context.getCur(); |
| 1615 | 1624 |
| 1616 // Check if the previous TempBaseReg is clobbered, and reset if needed. | 1625 // Check if the previous TempBaseReg is clobbered, and reset if needed. |
| 1617 Legalizer.resetTempBaseIfClobberedBy(CurInstr); | 1626 Legalizer.resetTempBaseIfClobberedBy(CurInstr); |
| 1618 | 1627 |
| 1619 if (auto *MovInstr = llvm::dyn_cast<InstARM32Mov>(CurInstr)) { | 1628 if (auto *MovInstr = llvm::dyn_cast<InstARM32Mov>(CurInstr)) { |
| 1620 Legalizer.legalizeMov(MovInstr); | 1629 Legalizer.legalizeMov(MovInstr); |
| 1621 } else if (auto *LdrInstr = llvm::dyn_cast<InstARM32Ldr>(CurInstr)) { | 1630 } else if (auto *LdrInstr = llvm::dyn_cast<InstARM32Ldr>(CurInstr)) { |
| 1622 if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand( | 1631 if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand( |
| 1623 llvm::cast<OperandARM32Mem>(LdrInstr->getSrc(0)))) { | 1632 llvm::cast<OperandARM32Mem>(LdrInstr->getSrc(0)))) { |
| 1624 _ldr(CurInstr->getDest(), LegalMem, LdrInstr->getPredicate()); | 1633 AutoSandboxer(this) |
| 1634 .ldr(CurInstr->getDest(), LegalMem, LdrInstr->getPredicate()); | |
| 1625 CurInstr->setDeleted(); | 1635 CurInstr->setDeleted(); |
| 1626 } | 1636 } |
| 1627 } else if (auto *LdrexInstr = llvm::dyn_cast<InstARM32Ldrex>(CurInstr)) { | 1637 } else if (auto *LdrexInstr = llvm::dyn_cast<InstARM32Ldrex>(CurInstr)) { |
| 1628 constexpr bool DisallowOffsetsBecauseLdrex = false; | 1638 constexpr bool DisallowOffsetsBecauseLdrex = false; |
| 1629 if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand( | 1639 if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand( |
| 1630 llvm::cast<OperandARM32Mem>(LdrexInstr->getSrc(0)), | 1640 llvm::cast<OperandARM32Mem>(LdrexInstr->getSrc(0)), |
| 1631 DisallowOffsetsBecauseLdrex)) { | 1641 DisallowOffsetsBecauseLdrex)) { |
| 1632 _ldrex(CurInstr->getDest(), LegalMem, LdrexInstr->getPredicate()); | 1642 AutoSandboxer(this) |
| 1643 .ldrex(CurInstr->getDest(), LegalMem, LdrexInstr->getPredicate()); | |
| 1633 CurInstr->setDeleted(); | 1644 CurInstr->setDeleted(); |
| 1634 } | 1645 } |
| 1635 } else if (auto *StrInstr = llvm::dyn_cast<InstARM32Str>(CurInstr)) { | 1646 } else if (auto *StrInstr = llvm::dyn_cast<InstARM32Str>(CurInstr)) { |
| 1647 AutoSandboxer Bundle(this); | |
| 1636 if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand( | 1648 if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand( |
| 1637 llvm::cast<OperandARM32Mem>(StrInstr->getSrc(1)))) { | 1649 llvm::cast<OperandARM32Mem>(StrInstr->getSrc(1)))) { |
| 1638 _str(llvm::cast<Variable>(CurInstr->getSrc(0)), LegalMem, | 1650 AutoSandboxer(this).str(llvm::cast<Variable>(CurInstr->getSrc(0)), |
| 1639 StrInstr->getPredicate()); | 1651 LegalMem, StrInstr->getPredicate()); |
| 1640 CurInstr->setDeleted(); | 1652 CurInstr->setDeleted(); |
| 1641 } | 1653 } |
| 1642 } else if (auto *StrexInstr = llvm::dyn_cast<InstARM32Strex>(CurInstr)) { | 1654 } else if (auto *StrexInstr = llvm::dyn_cast<InstARM32Strex>(CurInstr)) { |
| 1643 constexpr bool DisallowOffsetsBecauseStrex = false; | 1655 constexpr bool DisallowOffsetsBecauseStrex = false; |
| 1644 if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand( | 1656 if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand( |
| 1645 llvm::cast<OperandARM32Mem>(StrexInstr->getSrc(1)), | 1657 llvm::cast<OperandARM32Mem>(StrexInstr->getSrc(1)), |
| 1646 DisallowOffsetsBecauseStrex)) { | 1658 DisallowOffsetsBecauseStrex)) { |
| 1647 _strex(CurInstr->getDest(), llvm::cast<Variable>(CurInstr->getSrc(0)), | 1659 AutoSandboxer(this).strex(CurInstr->getDest(), |
| 1648 LegalMem, StrexInstr->getPredicate()); | 1660 llvm::cast<Variable>(CurInstr->getSrc(0)), |
| 1661 LegalMem, StrexInstr->getPredicate()); | |
| 1649 CurInstr->setDeleted(); | 1662 CurInstr->setDeleted(); |
| 1650 } | 1663 } |
| 1651 } | 1664 } |
| 1652 | 1665 |
| 1653 // Sanity-check: the Legalizer will either have no Temp, or it will be | 1666 // Sanity-check: the Legalizer will either have no Temp, or it will be |
| 1654 // bound to IP. | 1667 // bound to IP. |
| 1655 Legalizer.assertNoTempOrAssignedToIP(); | 1668 Legalizer.assertNoTempOrAssignedToIP(); |
| 1656 } | 1669 } |
| 1657 } | 1670 } |
| 1658 } | 1671 } |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1796 const bool OptM1 = Ctx->getFlags().getOptLevel() == Opt_m1; | 1809 const bool OptM1 = Ctx->getFlags().getOptLevel() == Opt_m1; |
| 1797 const bool AllocaWithKnownOffset = Inst->getKnownFrameOffset(); | 1810 const bool AllocaWithKnownOffset = Inst->getKnownFrameOffset(); |
| 1798 const bool UseFramePointer = | 1811 const bool UseFramePointer = |
| 1799 hasFramePointer() || OverAligned || !AllocaWithKnownOffset || OptM1; | 1812 hasFramePointer() || OverAligned || !AllocaWithKnownOffset || OptM1; |
| 1800 | 1813 |
| 1801 if (UseFramePointer) | 1814 if (UseFramePointer) |
| 1802 setHasFramePointer(); | 1815 setHasFramePointer(); |
| 1803 | 1816 |
| 1804 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 1817 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| 1805 if (OverAligned) { | 1818 if (OverAligned) { |
| 1806 alignRegisterPow2(SP, Alignment); | 1819 AutoSandboxer(this).align_sp(Alignment); |
| 1807 } | 1820 } |
| 1808 | 1821 |
| 1809 Variable *Dest = Inst->getDest(); | 1822 Variable *Dest = Inst->getDest(); |
| 1810 Operand *TotalSize = Inst->getSizeInBytes(); | 1823 Operand *TotalSize = Inst->getSizeInBytes(); |
| 1811 | 1824 |
| 1812 if (const auto *ConstantTotalSize = | 1825 if (const auto *ConstantTotalSize = |
| 1813 llvm::dyn_cast<ConstantInteger32>(TotalSize)) { | 1826 llvm::dyn_cast<ConstantInteger32>(TotalSize)) { |
| 1814 const uint32_t Value = | 1827 const uint32_t Value = |
| 1815 Utils::applyAlignment(ConstantTotalSize->getValue(), Alignment); | 1828 Utils::applyAlignment(ConstantTotalSize->getValue(), Alignment); |
| 1816 // Constant size alloca. | 1829 // Constant size alloca. |
| 1817 if (!UseFramePointer) { | 1830 if (!UseFramePointer) { |
| 1818 // If we don't need a Frame Pointer, this alloca has a known offset to the | 1831 // If we don't need a Frame Pointer, this alloca has a known offset to the |
| 1819 // stack pointer. We don't need adjust the stack pointer, nor assign any | 1832 // stack pointer. We don't need adjust the stack pointer, nor assign any |
| 1820 // value to Dest, as Dest is rematerializable. | 1833 // value to Dest, as Dest is rematerializable. |
| 1821 assert(Dest->isRematerializable()); | 1834 assert(Dest->isRematerializable()); |
| 1822 FixedAllocaSizeBytes += Value; | 1835 FixedAllocaSizeBytes += Value; |
| 1823 Context.insert(InstFakeDef::create(Func, Dest)); | 1836 Context.insert(InstFakeDef::create(Func, Dest)); |
| 1824 return; | 1837 return; |
| 1825 } | 1838 } |
| 1826 | 1839 |
| 1827 // If a frame pointer is required, then we need to store the alloca'd result | 1840 // If a frame pointer is required, then we need to store the alloca'd result |
| 1828 // in Dest. | 1841 // in Dest. |
| 1829 Operand *SubAmountRF = | 1842 Operand *SubAmountRF = |
| 1830 legalize(Ctx->getConstantInt32(Value), Legal_Reg | Legal_Flex); | 1843 legalize(Ctx->getConstantInt32(Value), Legal_Reg | Legal_Flex); |
| 1831 _sub(SP, SP, SubAmountRF); | 1844 AutoSandboxer(this).sub_sp(SubAmountRF); |
| 1832 } else { | 1845 } else { |
| 1833 // Non-constant sizes need to be adjusted to the next highest multiple of | 1846 // Non-constant sizes need to be adjusted to the next highest multiple of |
| 1834 // the required alignment at runtime. | 1847 // the required alignment at runtime. |
| 1835 TotalSize = legalize(TotalSize, Legal_Reg | Legal_Flex); | 1848 TotalSize = legalize(TotalSize, Legal_Reg | Legal_Flex); |
| 1836 Variable *T = makeReg(IceType_i32); | 1849 Variable *T = makeReg(IceType_i32); |
| 1837 _mov(T, TotalSize); | 1850 _mov(T, TotalSize); |
| 1838 Operand *AddAmount = legalize(Ctx->getConstantInt32(Alignment - 1)); | 1851 Operand *AddAmount = legalize(Ctx->getConstantInt32(Alignment - 1)); |
| 1839 _add(T, T, AddAmount); | 1852 _add(T, T, AddAmount); |
| 1840 alignRegisterPow2(T, Alignment); | 1853 alignRegisterPow2(T, Alignment); |
| 1841 _sub(SP, SP, T); | 1854 AutoSandboxer(this).sub_sp(T); |
| 1842 } | 1855 } |
| 1843 | 1856 |
| 1844 // Adds back a few bytes to SP to account for the out args area. | 1857 // Adds back a few bytes to SP to account for the out args area. |
| 1845 Variable *T = SP; | 1858 Variable *T = SP; |
| 1846 if (MaxOutArgsSizeBytes != 0) { | 1859 if (MaxOutArgsSizeBytes != 0) { |
| 1847 T = makeReg(getPointerType()); | 1860 T = makeReg(getPointerType()); |
| 1848 Operand *OutArgsSizeRF = legalize( | 1861 Operand *OutArgsSizeRF = legalize( |
| 1849 Ctx->getConstantInt32(MaxOutArgsSizeBytes), Legal_Reg | Legal_Flex); | 1862 Ctx->getConstantInt32(MaxOutArgsSizeBytes), Legal_Reg | Legal_Flex); |
| 1850 _add(T, SP, OutArgsSizeRF); | 1863 _add(T, SP, OutArgsSizeRF); |
| 1851 } | 1864 } |
| (...skipping 1390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3242 case IceType_v8i1: | 3255 case IceType_v8i1: |
| 3243 case IceType_v16i1: | 3256 case IceType_v16i1: |
| 3244 case IceType_v16i8: | 3257 case IceType_v16i8: |
| 3245 case IceType_v8i16: | 3258 case IceType_v8i16: |
| 3246 case IceType_v4i32: | 3259 case IceType_v4i32: |
| 3247 case IceType_v4f32: | 3260 case IceType_v4f32: |
| 3248 ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_q0); | 3261 ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_q0); |
| 3249 break; | 3262 break; |
| 3250 } | 3263 } |
| 3251 } | 3264 } |
| 3252 // TODO(jvoung): Handle sandboxing. const bool NeedSandboxing = | |
| 3253 // Ctx->getFlags().getUseSandboxing(); | |
| 3254 | 3265 |
| 3255 // Allow ConstantRelocatable to be left alone as a direct call, but force | 3266 // Allow ConstantRelocatable to be left alone as a direct call, but force |
| 3256 // other constants like ConstantInteger32 to be in a register and make it an | 3267 // other constants like ConstantInteger32 to be in a register and make it an |
| 3257 // indirect call. | 3268 // indirect call. |
| 3258 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { | 3269 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { |
| 3259 CallTarget = legalize(CallTarget, Legal_Reg); | 3270 CallTarget = legalize(CallTarget, Legal_Reg); |
| 3260 } | 3271 } |
| 3261 | 3272 |
| 3262 // Copy arguments to be passed in registers to the appropriate registers. | 3273 // Copy arguments to be passed in registers to the appropriate registers. |
| 3263 for (auto &FPArg : FPArgs) { | 3274 for (auto &FPArg : FPArgs) { |
| 3264 Variable *Reg = legalizeToReg(FPArg.first, FPArg.second); | 3275 Variable *Reg = legalizeToReg(FPArg.first, FPArg.second); |
| 3265 Context.insert(InstFakeUse::create(Func, Reg)); | 3276 Context.insert(InstFakeUse::create(Func, Reg)); |
| 3266 } | 3277 } |
| 3267 for (auto &GPRArg : GPRArgs) { | 3278 for (auto &GPRArg : GPRArgs) { |
| 3268 Variable *Reg = legalizeToReg(GPRArg.first, GPRArg.second); | 3279 Variable *Reg = legalizeToReg(GPRArg.first, GPRArg.second); |
| 3269 // Generate a FakeUse of register arguments so that they do not get dead | 3280 // Generate a FakeUse of register arguments so that they do not get dead |
| 3270 // code eliminated as a result of the FakeKill of scratch registers after | 3281 // code eliminated as a result of the FakeKill of scratch registers after |
| 3271 // the call. | 3282 // the call. |
| 3272 Context.insert(InstFakeUse::create(Func, Reg)); | 3283 Context.insert(InstFakeUse::create(Func, Reg)); |
| 3273 } | 3284 } |
| 3274 Inst *NewCall = InstARM32Call::create(Func, ReturnReg, CallTarget); | 3285 |
| 3275 Context.insert(NewCall); | 3286 InstARM32Call *NewCall = AutoSandboxer(this, InstBundleLock::Opt_AlignToEnd) |
| 3287 .bl(ReturnReg, CallTarget); | |
| 3288 | |
| 3276 if (ReturnRegHi) | 3289 if (ReturnRegHi) |
| 3277 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); | 3290 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); |
| 3278 | 3291 |
| 3279 // Insert a register-kill pseudo instruction. | 3292 // Insert a register-kill pseudo instruction. |
| 3280 Context.insert(InstFakeKill::create(Func, NewCall)); | 3293 Context.insert(InstFakeKill::create(Func, NewCall)); |
| 3281 | 3294 |
| 3282 // Generate a FakeUse to keep the call live if necessary. | 3295 // Generate a FakeUse to keep the call live if necessary. |
| 3283 if (Instr->hasSideEffects() && ReturnReg) { | 3296 if (Instr->hasSideEffects() && ReturnReg) { |
| 3284 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); | 3297 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); |
| 3285 Context.insert(FakeUse); | 3298 Context.insert(FakeUse); |
| (...skipping 1319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4605 case Intrinsics::Memcpy: { | 4618 case Intrinsics::Memcpy: { |
| 4606 llvm::report_fatal_error("memcpy should have been prelowered."); | 4619 llvm::report_fatal_error("memcpy should have been prelowered."); |
| 4607 } | 4620 } |
| 4608 case Intrinsics::Memmove: { | 4621 case Intrinsics::Memmove: { |
| 4609 llvm::report_fatal_error("memmove should have been prelowered."); | 4622 llvm::report_fatal_error("memmove should have been prelowered."); |
| 4610 } | 4623 } |
| 4611 case Intrinsics::Memset: { | 4624 case Intrinsics::Memset: { |
| 4612 llvm::report_fatal_error("memmove should have been prelowered."); | 4625 llvm::report_fatal_error("memmove should have been prelowered."); |
| 4613 } | 4626 } |
| 4614 case Intrinsics::NaClReadTP: { | 4627 case Intrinsics::NaClReadTP: { |
| 4615 llvm::report_fatal_error("nacl-read-tp should have been prelowered."); | 4628 if (!NeedSandboxing) { |
| 4629 llvm::report_fatal_error("nacl-read-tp should have been prelowered."); | |
| 4630 } | |
| 4631 Variable *TP = legalizeToReg(OperandARM32Mem::create( | |
| 4632 Func, getPointerType(), getPhysicalRegister(RegARM32::Reg_r9), | |
| 4633 llvm::cast<ConstantInteger32>(Ctx->getConstantZero(IceType_i32)))); | |
| 4634 _mov(Dest, TP); | |
| 4635 return; | |
| 4616 } | 4636 } |
| 4617 case Intrinsics::Setjmp: { | 4637 case Intrinsics::Setjmp: { |
| 4618 llvm::report_fatal_error("setjmp should have been prelowered."); | 4638 llvm::report_fatal_error("setjmp should have been prelowered."); |
| 4619 } | 4639 } |
| 4620 case Intrinsics::Sqrt: { | 4640 case Intrinsics::Sqrt: { |
| 4621 Variable *Src = legalizeToReg(Instr->getArg(0)); | 4641 Variable *Src = legalizeToReg(Instr->getArg(0)); |
| 4622 Variable *T = makeReg(Dest->getType()); | 4642 Variable *T = makeReg(Dest->getType()); |
| 4623 _vsqrt(T, Src); | 4643 _vsqrt(T, Src); |
| 4624 _mov(Dest, T); | 4644 _mov(Dest, T); |
| 4625 return; | 4645 return; |
| 4626 } | 4646 } |
| 4627 case Intrinsics::Stacksave: { | 4647 case Intrinsics::Stacksave: { |
| 4628 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 4648 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| 4629 _mov(Dest, SP); | 4649 _mov(Dest, SP); |
| 4630 return; | 4650 return; |
| 4631 } | 4651 } |
| 4632 case Intrinsics::Stackrestore: { | 4652 case Intrinsics::Stackrestore: { |
| 4633 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 4653 Variable *Val = legalizeToReg(Instr->getArg(0)); |
| 4634 Operand *Val = legalize(Instr->getArg(0), Legal_Reg | Legal_Flex); | 4654 AutoSandboxer(this).reset_sp(Val); |
| 4635 _mov_redefined(SP, Val); | |
| 4636 return; | 4655 return; |
| 4637 } | 4656 } |
| 4638 case Intrinsics::Trap: | 4657 case Intrinsics::Trap: |
| 4639 _trap(); | 4658 _trap(); |
| 4640 return; | 4659 return; |
| 4641 case Intrinsics::UnknownIntrinsic: | 4660 case Intrinsics::UnknownIntrinsic: |
| 4642 Func->setError("Should not be lowering UnknownIntrinsic"); | 4661 Func->setError("Should not be lowering UnknownIntrinsic"); |
| 4643 return; | 4662 return; |
| 4644 } | 4663 } |
| 4645 return; | 4664 return; |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4980 // "[reg]" addressing mode (the other supported modes are write back.) | 4999 // "[reg]" addressing mode (the other supported modes are write back.) |
| 4981 return nullptr; | 5000 return nullptr; |
| 4982 | 5001 |
| 4983 auto *BaseVar = llvm::dyn_cast<Variable>(Base); | 5002 auto *BaseVar = llvm::dyn_cast<Variable>(Base); |
| 4984 if (BaseVar == nullptr) | 5003 if (BaseVar == nullptr) |
| 4985 return nullptr; | 5004 return nullptr; |
| 4986 | 5005 |
| 4987 (void)MemTraitsSize; | 5006 (void)MemTraitsSize; |
| 4988 assert(Ty < MemTraitsSize); | 5007 assert(Ty < MemTraitsSize); |
| 4989 auto *TypeTraits = &MemTraits[Ty]; | 5008 auto *TypeTraits = &MemTraits[Ty]; |
| 4990 const bool CanHaveIndex = TypeTraits->CanHaveIndex; | 5009 const bool CanHaveIndex = !NeedSandboxing && TypeTraits->CanHaveIndex; |
| 4991 const bool CanHaveShiftedIndex = TypeTraits->CanHaveShiftedIndex; | 5010 const bool CanHaveShiftedIndex = |
| 5011 !NeedSandboxing && TypeTraits->CanHaveShiftedIndex; | |
| 4992 const bool CanHaveImm = TypeTraits->CanHaveImm; | 5012 const bool CanHaveImm = TypeTraits->CanHaveImm; |
| 4993 const int32_t ValidImmMask = TypeTraits->ValidImmMask; | 5013 const int32_t ValidImmMask = TypeTraits->ValidImmMask; |
| 4994 (void)ValidImmMask; | 5014 (void)ValidImmMask; |
| 4995 assert(!CanHaveImm || ValidImmMask >= 0); | 5015 assert(!CanHaveImm || ValidImmMask >= 0); |
| 4996 | 5016 |
| 4997 const VariablesMetadata *VMetadata = Func->getVMetadata(); | 5017 const VariablesMetadata *VMetadata = Func->getVMetadata(); |
| 4998 const Inst *Reason = nullptr; | 5018 const Inst *Reason = nullptr; |
| 4999 | 5019 |
| 5000 do { | 5020 do { |
| 5001 if (Reason != nullptr) { | 5021 if (Reason != nullptr) { |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5152 } else { | 5172 } else { |
| 5153 Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex); | 5173 Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex); |
| 5154 Reg = makeReg(Src0F->getType(), RegARM32::Reg_r0); | 5174 Reg = makeReg(Src0F->getType(), RegARM32::Reg_r0); |
| 5155 _mov(Reg, Src0F, CondARM32::AL); | 5175 _mov(Reg, Src0F, CondARM32::AL); |
| 5156 } | 5176 } |
| 5157 } | 5177 } |
| 5158 // Add a ret instruction even if sandboxing is enabled, because addEpilog | 5178 // Add a ret instruction even if sandboxing is enabled, because addEpilog |
| 5159 // explicitly looks for a ret instruction as a marker for where to insert the | 5179 // explicitly looks for a ret instruction as a marker for where to insert the |
| 5160 // frame removal instructions. addEpilog is responsible for restoring the | 5180 // frame removal instructions. addEpilog is responsible for restoring the |
| 5161 // "lr" register as needed prior to this ret instruction. | 5181 // "lr" register as needed prior to this ret instruction. |
| 5162 _ret(getPhysicalRegister(RegARM32::Reg_lr), Reg); | 5182 _ret(getPhysicalRegister(RegARM32::Reg_lr), Reg); |
|
Karl
2015/12/04 20:41:17
Indentation wrong?
John
2015/12/05 16:20:11
where, the _ret? seems fine to me (there's an unde
| |
| 5183 | |
| 5163 // Add a fake use of sp to make sure sp stays alive for the entire function. | 5184 // Add a fake use of sp to make sure sp stays alive for the entire function. |
| 5164 // Otherwise post-call sp adjustments get dead-code eliminated. | 5185 // Otherwise post-call sp adjustments get dead-code eliminated. |
| 5165 // TODO: Are there more places where the fake use should be inserted? E.g. | 5186 // TODO: Are there more places where the fake use should be inserted? E.g. |
| 5166 // "void f(int n){while(1) g(n);}" may not have a ret instruction. | 5187 // "void f(int n){while(1) g(n);}" may not have a ret instruction. |
| 5167 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 5188 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| 5168 Context.insert(InstFakeUse::create(Func, SP)); | 5189 Context.insert(InstFakeUse::create(Func, SP)); |
| 5169 } | 5190 } |
| 5170 | 5191 |
| 5171 void TargetARM32::lowerSelect(const InstSelect *Inst) { | 5192 void TargetARM32::lowerSelect(const InstSelect *Inst) { |
| 5172 Variable *Dest = Inst->getDest(); | 5193 Variable *Dest = Inst->getDest(); |
| (...skipping 732 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5905 | 5926 |
| 5906 // Mark as "dead" rather than outright deleting. This is so that other | 5927 // Mark as "dead" rather than outright deleting. This is so that other |
| 5907 // peephole style optimizations during or before lowering have access to | 5928 // peephole style optimizations during or before lowering have access to |
| 5908 // this instruction in undeleted form. See for example | 5929 // this instruction in undeleted form. See for example |
| 5909 // tryOptimizedCmpxchgCmpBr(). | 5930 // tryOptimizedCmpxchgCmpBr(). |
| 5910 Iter->second.Instr->setDead(); | 5931 Iter->second.Instr->setDead(); |
| 5911 ++Iter; | 5932 ++Iter; |
| 5912 } | 5933 } |
| 5913 } | 5934 } |
| 5914 | 5935 |
| 5936 TargetARM32::AutoSandboxer::AutoSandboxer(TargetARM32 *Target, | |
| 5937 InstBundleLock::Option BundleOption) | |
| 5938 : Target(Target) { | |
| 5939 if (Target->NeedSandboxing) { | |
| 5940 Target->_bundle_lock(BundleOption); | |
| 5941 } | |
| 5942 } | |
| 5943 | |
| 5944 TargetARM32::AutoSandboxer::~AutoSandboxer() { | |
| 5945 if (Target->NeedSandboxing) { | |
| 5946 Target->_bundle_unlock(); | |
| 5947 } | |
| 5948 } | |
| 5949 | |
| 5950 namespace { | |
| 5951 OperandARM32FlexImm *indirectBranchBicMask(Cfg *Func) { | |
| 5952 constexpr uint32_t Imm8 = 0xFC; // 0xC000000F | |
| 5953 constexpr uint32_t RotateAmt = 2; | |
| 5954 return OperandARM32FlexImm::create(Func, IceType_i32, Imm8, RotateAmt); | |
| 5955 } | |
| 5956 | |
| 5957 OperandARM32FlexImm *memOpBicMask(Cfg *Func) { | |
| 5958 constexpr uint32_t Imm8 = 0x0C; // 0xC0000000 | |
| 5959 constexpr uint32_t RotateAmt = 2; | |
| 5960 return OperandARM32FlexImm::create(Func, IceType_i32, Imm8, RotateAmt); | |
| 5961 } | |
|
Karl
2015/12/04 20:41:17
Add blank line?
John
2015/12/05 16:20:11
Done.
| |
| 5962 static bool baseNeedsBic(Variable *Base) { | |
| 5963 return Base->getRegNum() != RegARM32::Reg_r9 && | |
| 5964 Base->getRegNum() != RegARM32::Reg_sp; | |
| 5965 } | |
| 5966 } // end of anonymous namespace | |
| 5967 | |
| 5968 void TargetARM32::AutoSandboxer::add_sp(Operand *AddAmount) { | |
| 5969 Variable *SP = Target->getPhysicalRegister(RegARM32::Reg_sp); | |
| 5970 Target->_add(SP, SP, AddAmount); | |
| 5971 if (Target->NeedSandboxing) { | |
| 5972 Target->_bic(SP, SP, memOpBicMask(Target->Func)); | |
| 5973 } | |
| 5974 } | |
| 5975 | |
| 5976 void TargetARM32::AutoSandboxer::align_sp(size_t Alignment) { | |
| 5977 Variable *SP = Target->getPhysicalRegister(RegARM32::Reg_sp); | |
| 5978 Target->alignRegisterPow2(SP, Alignment); | |
| 5979 if (Target->NeedSandboxing) { | |
| 5980 Target->_bic(SP, SP, memOpBicMask(Target->Func)); | |
| 5981 } | |
| 5982 } | |
| 5983 | |
| 5984 InstARM32Call *TargetARM32::AutoSandboxer::bl(Variable *ReturnReg, | |
| 5985 Operand *CallTarget) { | |
| 5986 if (Target->NeedSandboxing) { | |
| 5987 if (auto *CallTargetR = llvm::dyn_cast<Variable>(CallTarget)) { | |
| 5988 Target->_bic(CallTargetR, CallTargetR, | |
| 5989 indirectBranchBicMask(Target->Func)); | |
| 5990 } | |
| 5991 } | |
| 5992 auto *Call = InstARM32Call::create(Target->Func, ReturnReg, CallTarget); | |
| 5993 Target->Context.insert(Call); | |
| 5994 return Call; | |
| 5995 } | |
| 5996 | |
| 5997 void TargetARM32::AutoSandboxer::ldr(Variable *Dest, OperandARM32Mem *Mem, | |
| 5998 CondARM32::Cond Pred) { | |
| 5999 Variable *MemBase = Mem->getBase(); | |
| 6000 if (Target->NeedSandboxing && baseNeedsBic(MemBase)) { | |
| 6001 assert(!Mem->isRegReg()); | |
| 6002 Target->_bic(MemBase, MemBase, memOpBicMask(Target->Func), Pred); | |
| 6003 } | |
| 6004 Target->_ldr(Dest, Mem, Pred); | |
| 6005 } | |
| 6006 | |
| 6007 void TargetARM32::AutoSandboxer::ldrex(Variable *Dest, OperandARM32Mem *Mem, | |
| 6008 CondARM32::Cond Pred) { | |
| 6009 Variable *MemBase = Mem->getBase(); | |
| 6010 if (Target->NeedSandboxing && baseNeedsBic(MemBase)) { | |
| 6011 assert(!Mem->isRegReg()); | |
| 6012 Target->_bic(MemBase, MemBase, memOpBicMask(Target->Func), Pred); | |
| 6013 } | |
| 6014 Target->_ldrex(Dest, Mem, Pred); | |
| 6015 } | |
| 6016 | |
| 6017 void TargetARM32::AutoSandboxer::reset_sp(Variable *Src) { | |
| 6018 Variable *SP = Target->getPhysicalRegister(RegARM32::Reg_sp); | |
| 6019 Target->_mov_redefined(SP, Src); | |
| 6020 if (Target->NeedSandboxing) { | |
| 6021 Target->_bic(SP, SP, memOpBicMask(Target->Func)); | |
| 6022 } | |
| 6023 } | |
| 6024 | |
| 6025 void TargetARM32::AutoSandboxer::ret(Variable *RetAddr, Variable *RetValue) { | |
| 6026 if (Target->NeedSandboxing) { | |
| 6027 Target->_bic(RetAddr, RetAddr, indirectBranchBicMask(Target->Func)); | |
| 6028 } | |
| 6029 Target->_ret(RetAddr, RetValue); | |
| 6030 } | |
| 6031 | |
| 6032 void TargetARM32::AutoSandboxer::str(Variable *Src, OperandARM32Mem *Mem, | |
| 6033 CondARM32::Cond Pred) { | |
| 6034 Variable *MemBase = Mem->getBase(); | |
| 6035 if (Target->NeedSandboxing && baseNeedsBic(MemBase)) { | |
| 6036 assert(!Mem->isRegReg()); | |
| 6037 Target->_bic(MemBase, MemBase, memOpBicMask(Target->Func), Pred); | |
| 6038 } | |
| 6039 Target->_str(Src, Mem, Pred); | |
| 6040 } | |
| 6041 | |
| 6042 void TargetARM32::AutoSandboxer::strex(Variable *Dest, Variable *Src, | |
| 6043 OperandARM32Mem *Mem, | |
| 6044 CondARM32::Cond Pred) { | |
| 6045 Variable *MemBase = Mem->getBase(); | |
| 6046 if (Target->NeedSandboxing && baseNeedsBic(MemBase)) { | |
| 6047 assert(!Mem->isRegReg()); | |
| 6048 Target->_bic(MemBase, MemBase, memOpBicMask(Target->Func), Pred); | |
| 6049 } | |
| 6050 Target->_strex(Dest, Src, Mem, Pred); | |
| 6051 } | |
| 6052 | |
| 6053 void TargetARM32::AutoSandboxer::sub_sp(Operand *SubAmount) { | |
| 6054 Variable *SP = Target->getPhysicalRegister(RegARM32::Reg_sp); | |
| 6055 Target->_sub(SP, SP, SubAmount); | |
| 6056 if (Target->NeedSandboxing) { | |
| 6057 Target->_bic(SP, SP, memOpBicMask(Target->Func)); | |
| 6058 } | |
| 6059 } | |
| 6060 | |
| 5915 TargetDataARM32::TargetDataARM32(GlobalContext *Ctx) | 6061 TargetDataARM32::TargetDataARM32(GlobalContext *Ctx) |
| 5916 : TargetDataLowering(Ctx) {} | 6062 : TargetDataLowering(Ctx) {} |
| 5917 | 6063 |
| 5918 void TargetDataARM32::lowerGlobals(const VariableDeclarationList &Vars, | 6064 void TargetDataARM32::lowerGlobals(const VariableDeclarationList &Vars, |
| 5919 const IceString &SectionSuffix) { | 6065 const IceString &SectionSuffix) { |
| 5920 switch (Ctx->getFlags().getOutFileType()) { | 6066 switch (Ctx->getFlags().getOutFileType()) { |
| 5921 case FT_Elf: { | 6067 case FT_Elf: { |
| 5922 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | 6068 ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
| 5923 Writer->writeDataSection(Vars, llvm::ELF::R_ARM_ABS32, SectionSuffix); | 6069 Writer->writeDataSection(Vars, llvm::ELF::R_ARM_ABS32, SectionSuffix); |
| 5924 } break; | 6070 } break; |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6100 // Technically R9 is used for TLS with Sandboxing, and we reserve it. | 6246 // Technically R9 is used for TLS with Sandboxing, and we reserve it. |
| 6101 // However, for compatibility with current NaCl LLVM, don't claim that. | 6247 // However, for compatibility with current NaCl LLVM, don't claim that. |
| 6102 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 6248 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
| 6103 } | 6249 } |
| 6104 | 6250 |
| 6105 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; | 6251 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; |
| 6106 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; | 6252 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; |
| 6107 llvm::SmallBitVector TargetARM32::ScratchRegs; | 6253 llvm::SmallBitVector TargetARM32::ScratchRegs; |
| 6108 | 6254 |
| 6109 } // end of namespace Ice | 6255 } // end of namespace Ice |
| OLD | NEW |