| OLD | NEW |
| 1 //===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 lowering -----------===// | 1 //===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 lowering -----------===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 /// | 9 /// |
| 10 /// \file | 10 /// \file |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 void TargetX8632::_mov_sp(Operand *NewValue) { | 134 void TargetX8632::_mov_sp(Operand *NewValue) { |
| 135 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); | 135 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); |
| 136 _redefined(_mov(esp, NewValue)); | 136 _redefined(_mov(esp, NewValue)); |
| 137 } | 137 } |
| 138 | 138 |
| 139 void TargetX8632::_sub_sp(Operand *Adjustment) { | 139 void TargetX8632::_sub_sp(Operand *Adjustment) { |
| 140 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); | 140 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); |
| 141 _sub(esp, Adjustment); | 141 _sub(esp, Adjustment); |
| 142 } | 142 } |
| 143 | 143 |
| 144 void TargetX8632::_link_bp() { |
| 145 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp); |
| 146 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); |
| 147 _push(ebp); |
| 148 _mov(ebp, esp); |
| 149 // Keep ebp live for late-stage liveness analysis (e.g. asm-verbose mode). |
| 150 Context.insert<InstFakeUse>(ebp); |
| 151 } |
| 152 |
| 153 void TargetX8632::_unlink_bp() { |
| 154 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); |
| 155 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp); |
| 156 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake |
| 157 // use of esp before the assignment of esp=ebp keeps previous esp |
| 158 // adjustments from being dead-code eliminated. |
| 159 Context.insert<InstFakeUse>(esp); |
| 160 _mov(esp, ebp); |
| 161 _pop(ebp); |
| 162 } |
| 163 |
| 164 void TargetX8632::_push_reg(Variable *Reg) { _push(Reg); } |
| 165 |
| 166 void TargetX8632::emitGetIP(CfgNode *Node) { |
| 167 // If there is a non-deleted InstX86GetIP instruction, we need to move it to |
| 168 // the point after the stack frame has stabilized but before |
| 169 // register-allocated in-args are copied into their home registers. It would |
| 170 // be slightly faster to search for the GetIP instruction before other prolog |
| 171 // instructions are inserted, but it's more clear to do the whole |
| 172 // transformation in a single place. |
| 173 Traits::Insts::GetIP *GetIPInst = nullptr; |
| 174 if (Ctx->getFlags().getUseNonsfi()) { |
| 175 for (Inst &Instr : Node->getInsts()) { |
| 176 if (auto *GetIP = llvm::dyn_cast<Traits::Insts::GetIP>(&Instr)) { |
| 177 if (!Instr.isDeleted()) |
| 178 GetIPInst = GetIP; |
| 179 break; |
| 180 } |
| 181 } |
| 182 } |
| 183 // Delete any existing InstX86GetIP instruction and reinsert it here. Also, |
| 184 // insert the call to the helper function and the spill to the stack, to |
| 185 // simplify emission. |
| 186 if (GetIPInst) { |
| 187 GetIPInst->setDeleted(); |
| 188 Variable *Dest = GetIPInst->getDest(); |
| 189 Variable *CallDest = |
| 190 Dest->hasReg() ? Dest |
| 191 : getPhysicalRegister(Traits::RegisterSet::Reg_eax); |
| 192 // Call the getIP_<reg> helper. |
| 193 IceString RegName = Traits::getRegName(CallDest->getRegNum()); |
| 194 Constant *CallTarget = Ctx->getConstantExternSym(H_getIP_prefix + RegName); |
| 195 Context.insert<Traits::Insts::Call>(CallDest, CallTarget); |
| 196 // Insert a new version of InstX86GetIP. |
| 197 Context.insert<Traits::Insts::GetIP>(CallDest); |
| 198 // Spill the register to its home stack location if necessary. |
| 199 if (!Dest->hasReg()) { |
| 200 _mov(Dest, CallDest); |
| 201 } |
| 202 } |
| 203 } |
| 204 |
| 144 void TargetX8632::lowerIndirectJump(Variable *JumpTarget) { | 205 void TargetX8632::lowerIndirectJump(Variable *JumpTarget) { |
| 145 AutoBundle _(this); | 206 AutoBundle _(this); |
| 146 | 207 |
| 147 if (NeedSandboxing) { | 208 if (NeedSandboxing) { |
| 148 const SizeT BundleSize = | 209 const SizeT BundleSize = |
| 149 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes(); | 210 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes(); |
| 150 _and(JumpTarget, Ctx->getConstantInt32(~(BundleSize - 1))); | 211 _and(JumpTarget, Ctx->getConstantInt32(~(BundleSize - 1))); |
| 151 } | 212 } |
| 152 | 213 |
| 153 _jmp(JumpTarget); | 214 _jmp(JumpTarget); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 Context.insert<InstFakeUse>(edx); | 249 Context.insert<InstFakeUse>(edx); |
| 189 return eax; | 250 return eax; |
| 190 } else { | 251 } else { |
| 191 Variable *Reg = nullptr; | 252 Variable *Reg = nullptr; |
| 192 _mov(Reg, Value, Traits::RegisterSet::Reg_eax); | 253 _mov(Reg, Value, Traits::RegisterSet::Reg_eax); |
| 193 return Reg; | 254 return Reg; |
| 194 } | 255 } |
| 195 } | 256 } |
| 196 } | 257 } |
| 197 | 258 |
| 198 void TargetX8632::addProlog(CfgNode *Node) { | 259 void TargetX8632::emitSandboxedReturn() { |
| 199 // Stack frame layout: | |
| 200 // | |
| 201 // +------------------------+ | |
| 202 // | 1. return address | | |
| 203 // +------------------------+ | |
| 204 // | 2. preserved registers | | |
| 205 // +------------------------+ | |
| 206 // | 3. padding | | |
| 207 // +------------------------+ | |
| 208 // | 4. global spill area | | |
| 209 // +------------------------+ | |
| 210 // | 5. padding | | |
| 211 // +------------------------+ | |
| 212 // | 6. local spill area | | |
| 213 // +------------------------+ | |
| 214 // | 7. padding | | |
| 215 // +------------------------+ | |
| 216 // | 8. allocas | | |
| 217 // +------------------------+ | |
| 218 // | 9. padding | | |
| 219 // +------------------------+ | |
| 220 // | 10. out args | | |
| 221 // +------------------------+ <--- StackPointer | |
| 222 // | |
| 223 // The following variables record the size in bytes of the given areas: | |
| 224 // * X86_RET_IP_SIZE_BYTES: area 1 | |
| 225 // * PreservedRegsSizeBytes: area 2 | |
| 226 // * SpillAreaPaddingBytes: area 3 | |
| 227 // * GlobalsSize: area 4 | |
| 228 // * GlobalsAndSubsequentPaddingSize: areas 4 - 5 | |
| 229 // * LocalsSpillAreaSize: area 6 | |
| 230 // * SpillAreaSizeBytes: areas 3 - 10 | |
| 231 // * maxOutArgsSizeBytes(): area 10 | |
| 232 | |
| 233 // Determine stack frame offsets for each Variable without a register | |
| 234 // assignment. This can be done as one variable per stack slot. Or, do | |
| 235 // coalescing by running the register allocator again with an infinite set of | |
| 236 // registers (as a side effect, this gives variables a second chance at | |
| 237 // physical register assignment). | |
| 238 // | |
| 239 // A middle ground approach is to leverage sparsity and allocate one block of | |
| 240 // space on the frame for globals (variables with multi-block lifetime), and | |
| 241 // one block to share for locals (single-block lifetime). | |
| 242 | |
| 243 Context.init(Node); | |
| 244 Context.setInsertPoint(Context.getCur()); | |
| 245 | |
| 246 llvm::SmallBitVector CalleeSaves = | |
| 247 getRegisterSet(RegSet_CalleeSave, RegSet_None); | |
| 248 RegsUsed = llvm::SmallBitVector(CalleeSaves.size()); | |
| 249 VarList SortedSpilledVariables, VariablesLinkedToSpillSlots; | |
| 250 size_t GlobalsSize = 0; | |
| 251 // If there is a separate locals area, this represents that area. Otherwise | |
| 252 // it counts any variable not counted by GlobalsSize. | |
| 253 SpillAreaSizeBytes = 0; | |
| 254 // If there is a separate locals area, this specifies the alignment for it. | |
| 255 uint32_t LocalsSlotsAlignmentBytes = 0; | |
| 256 // The entire spill locations area gets aligned to largest natural alignment | |
| 257 // of the variables that have a spill slot. | |
| 258 uint32_t SpillAreaAlignmentBytes = 0; | |
| 259 // A spill slot linked to a variable with a stack slot should reuse that | |
| 260 // stack slot. | |
| 261 std::function<bool(Variable *)> TargetVarHook = | |
| 262 [&VariablesLinkedToSpillSlots](Variable *Var) { | |
| 263 if (auto *SpillVar = | |
| 264 llvm::dyn_cast<typename Traits::SpillVariable>(Var)) { | |
| 265 assert(Var->mustNotHaveReg()); | |
| 266 if (SpillVar->getLinkedTo() && !SpillVar->getLinkedTo()->hasReg()) { | |
| 267 VariablesLinkedToSpillSlots.push_back(Var); | |
| 268 return true; | |
| 269 } | |
| 270 } | |
| 271 return false; | |
| 272 }; | |
| 273 | |
| 274 // Compute the list of spilled variables and bounds for GlobalsSize, etc. | |
| 275 getVarStackSlotParams(SortedSpilledVariables, RegsUsed, &GlobalsSize, | |
| 276 &SpillAreaSizeBytes, &SpillAreaAlignmentBytes, | |
| 277 &LocalsSlotsAlignmentBytes, TargetVarHook); | |
| 278 uint32_t LocalsSpillAreaSize = SpillAreaSizeBytes; | |
| 279 SpillAreaSizeBytes += GlobalsSize; | |
| 280 | |
| 281 // Add push instructions for preserved registers. | |
| 282 uint32_t NumCallee = 0; | |
| 283 size_t PreservedRegsSizeBytes = 0; | |
| 284 llvm::SmallBitVector Pushed(CalleeSaves.size()); | |
| 285 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { | |
| 286 SizeT Canonical = Traits::getBaseReg(i); | |
| 287 if (CalleeSaves[i] && RegsUsed[i]) { | |
| 288 Pushed[Canonical] = true; | |
| 289 } | |
| 290 } | |
| 291 for (SizeT i = 0; i < Pushed.size(); ++i) { | |
| 292 if (Pushed[i]) { | |
| 293 ++NumCallee; | |
| 294 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i32); | |
| 295 _push(getPhysicalRegister(i)); | |
| 296 } | |
| 297 } | |
| 298 Ctx->statsUpdateRegistersSaved(NumCallee); | |
| 299 | |
| 300 // Generate "push ebp; mov ebp, esp" | |
| 301 if (IsEbpBasedFrame) { | |
| 302 assert((RegsUsed & getRegisterSet(RegSet_FramePointer, RegSet_None)) | |
| 303 .count() == 0); | |
| 304 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i32); | |
| 305 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp); | |
| 306 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); | |
| 307 _push(ebp); | |
| 308 _mov(ebp, esp); | |
| 309 // Keep ebp live for late-stage liveness analysis (e.g. asm-verbose mode). | |
| 310 Context.insert<InstFakeUse>(ebp); | |
| 311 } | |
| 312 | |
| 313 // Align the variables area. SpillAreaPaddingBytes is the size of the region | |
| 314 // after the preserved registers and before the spill areas. | |
| 315 // LocalsSlotsPaddingBytes is the amount of padding between the globals and | |
| 316 // locals area if they are separate. | |
| 317 assert(SpillAreaAlignmentBytes <= Traits::X86_STACK_ALIGNMENT_BYTES); | |
| 318 assert(LocalsSlotsAlignmentBytes <= SpillAreaAlignmentBytes); | |
| 319 uint32_t SpillAreaPaddingBytes = 0; | |
| 320 uint32_t LocalsSlotsPaddingBytes = 0; | |
| 321 alignStackSpillAreas(Traits::X86_RET_IP_SIZE_BYTES + PreservedRegsSizeBytes, | |
| 322 SpillAreaAlignmentBytes, GlobalsSize, | |
| 323 LocalsSlotsAlignmentBytes, &SpillAreaPaddingBytes, | |
| 324 &LocalsSlotsPaddingBytes); | |
| 325 SpillAreaSizeBytes += SpillAreaPaddingBytes + LocalsSlotsPaddingBytes; | |
| 326 uint32_t GlobalsAndSubsequentPaddingSize = | |
| 327 GlobalsSize + LocalsSlotsPaddingBytes; | |
| 328 | |
| 329 // Functions returning scalar floating point types may need to convert values | |
| 330 // from an in-register xmm value to the top of the x87 floating point stack. | |
| 331 // This is done by a movp[sd] and an fld[sd]. Ensure there is enough scratch | |
| 332 // space on the stack for this. | |
| 333 const Type ReturnType = Func->getReturnType(); | |
| 334 if (isScalarFloatingType(ReturnType)) { | |
| 335 // Avoid misaligned double-precicion load/store. | |
| 336 NeedsStackAlignment = true; | |
| 337 SpillAreaSizeBytes = | |
| 338 std::max(typeWidthInBytesOnStack(ReturnType), SpillAreaSizeBytes); | |
| 339 } | |
| 340 | |
| 341 // Align esp if necessary. | |
| 342 if (NeedsStackAlignment) { | |
| 343 uint32_t StackOffset = | |
| 344 Traits::X86_RET_IP_SIZE_BYTES + PreservedRegsSizeBytes; | |
| 345 uint32_t StackSize = | |
| 346 Traits::applyStackAlignment(StackOffset + SpillAreaSizeBytes); | |
| 347 StackSize = Traits::applyStackAlignment(StackSize + maxOutArgsSizeBytes()); | |
| 348 SpillAreaSizeBytes = StackSize - StackOffset; | |
| 349 } else { | |
| 350 SpillAreaSizeBytes += maxOutArgsSizeBytes(); | |
| 351 } | |
| 352 | |
| 353 // Combine fixed allocations into SpillAreaSizeBytes if we are emitting the | |
| 354 // fixed allocations in the prolog. | |
| 355 if (PrologEmitsFixedAllocas) | |
| 356 SpillAreaSizeBytes += FixedAllocaSizeBytes; | |
| 357 if (SpillAreaSizeBytes) { | |
| 358 // Generate "sub esp, SpillAreaSizeBytes" | |
| 359 _sub(getPhysicalRegister(Traits::RegisterSet::Reg_esp), | |
| 360 Ctx->getConstantInt32(SpillAreaSizeBytes)); | |
| 361 // If the fixed allocas are aligned more than the stack frame, align the | |
| 362 // stack pointer accordingly. | |
| 363 if (PrologEmitsFixedAllocas && | |
| 364 FixedAllocaAlignBytes > Traits::X86_STACK_ALIGNMENT_BYTES) { | |
| 365 assert(IsEbpBasedFrame); | |
| 366 _and(getPhysicalRegister(Traits::RegisterSet::Reg_esp), | |
| 367 Ctx->getConstantInt32(-FixedAllocaAlignBytes)); | |
| 368 } | |
| 369 } | |
| 370 | |
| 371 // Account for known-frame-offset alloca instructions that were not already | |
| 372 // combined into the prolog. | |
| 373 if (!PrologEmitsFixedAllocas) | |
| 374 SpillAreaSizeBytes += FixedAllocaSizeBytes; | |
| 375 | |
| 376 Ctx->statsUpdateFrameBytes(SpillAreaSizeBytes); | |
| 377 | |
| 378 // Fill in stack offsets for stack args, and copy args into registers for | |
| 379 // those that were register-allocated. Args are pushed right to left, so | |
| 380 // Arg[0] is closest to the stack/frame pointer. | |
| 381 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); | |
| 382 size_t BasicFrameOffset = | |
| 383 PreservedRegsSizeBytes + Traits::X86_RET_IP_SIZE_BYTES; | |
| 384 if (!IsEbpBasedFrame) | |
| 385 BasicFrameOffset += SpillAreaSizeBytes; | |
| 386 | |
| 387 // If there is a non-deleted InstX86GetIP instruction, we need to move it to | |
| 388 // the point after the stack frame has stabilized but before | |
| 389 // register-allocated in-args are copied into their home registers. It would | |
| 390 // be slightly faster to search for the GetIP instruction before other prolog | |
| 391 // instructions are inserted, but it's more clear to do the whole | |
| 392 // transformation in a single place. | |
| 393 Traits::Insts::GetIP *GetIPInst = nullptr; | |
| 394 if (Ctx->getFlags().getUseNonsfi()) { | |
| 395 for (Inst &Instr : Node->getInsts()) { | |
| 396 if (auto *GetIP = llvm::dyn_cast<Traits::Insts::GetIP>(&Instr)) { | |
| 397 if (!Instr.isDeleted()) | |
| 398 GetIPInst = GetIP; | |
| 399 break; | |
| 400 } | |
| 401 } | |
| 402 } | |
| 403 // Delete any existing InstX86GetIP instruction and reinsert it here. Also, | |
| 404 // insert the call to the helper function and the spill to the stack, to | |
| 405 // simplify emission. | |
| 406 if (GetIPInst) { | |
| 407 GetIPInst->setDeleted(); | |
| 408 Variable *Dest = GetIPInst->getDest(); | |
| 409 Variable *CallDest = | |
| 410 Dest->hasReg() ? Dest | |
| 411 : getPhysicalRegister(Traits::RegisterSet::Reg_eax); | |
| 412 // Call the getIP_<reg> helper. | |
| 413 IceString RegName = Traits::getRegName(CallDest->getRegNum()); | |
| 414 Constant *CallTarget = Ctx->getConstantExternSym(H_getIP_prefix + RegName); | |
| 415 Context.insert<Traits::Insts::Call>(CallDest, CallTarget); | |
| 416 // Insert a new version of InstX86GetIP. | |
| 417 Context.insert<Traits::Insts::GetIP>(CallDest); | |
| 418 // Spill the register to its home stack location if necessary. | |
| 419 if (!Dest->hasReg()) { | |
| 420 _mov(Dest, CallDest); | |
| 421 } | |
| 422 } | |
| 423 | |
| 424 const VarList &Args = Func->getArgs(); | |
| 425 size_t InArgsSizeBytes = 0; | |
| 426 unsigned NumXmmArgs = 0; | |
| 427 for (Variable *Arg : Args) { | |
| 428 // Skip arguments passed in registers. | |
| 429 if (isVectorType(Arg->getType()) && NumXmmArgs < Traits::X86_MAX_XMM_ARGS) { | |
| 430 ++NumXmmArgs; | |
| 431 continue; | |
| 432 } | |
| 433 // For esp-based frames where the allocas are done outside the prolog, the | |
| 434 // esp value may not stabilize to its home value until after all the | |
| 435 // fixed-size alloca instructions have executed. In this case, a stack | |
| 436 // adjustment is needed when accessing in-args in order to copy them into | |
| 437 // registers. | |
| 438 size_t StackAdjBytes = 0; | |
| 439 if (!IsEbpBasedFrame && !PrologEmitsFixedAllocas) | |
| 440 StackAdjBytes -= FixedAllocaSizeBytes; | |
| 441 finishArgumentLowering(Arg, FramePtr, BasicFrameOffset, StackAdjBytes, | |
| 442 InArgsSizeBytes); | |
| 443 } | |
| 444 | |
| 445 // Fill in stack offsets for locals. | |
| 446 assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes, | |
| 447 SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize, | |
| 448 IsEbpBasedFrame); | |
| 449 // Assign stack offsets to variables that have been linked to spilled | |
| 450 // variables. | |
| 451 for (Variable *Var : VariablesLinkedToSpillSlots) { | |
| 452 Variable *Linked = | |
| 453 (llvm::cast<typename Traits::SpillVariable>(Var))->getLinkedTo(); | |
| 454 Var->setStackOffset(Linked->getStackOffset()); | |
| 455 } | |
| 456 this->HasComputedFrame = true; | |
| 457 | |
| 458 if (BuildDefs::dump() && Func->isVerbose(IceV_Frame)) { | |
| 459 OstreamLocker L(Func->getContext()); | |
| 460 Ostream &Str = Func->getContext()->getStrDump(); | |
| 461 | |
| 462 Str << "Stack layout:\n"; | |
| 463 uint32_t EspAdjustmentPaddingSize = | |
| 464 SpillAreaSizeBytes - LocalsSpillAreaSize - | |
| 465 GlobalsAndSubsequentPaddingSize - SpillAreaPaddingBytes - | |
| 466 maxOutArgsSizeBytes(); | |
| 467 Str << " in-args = " << InArgsSizeBytes << " bytes\n" | |
| 468 << " return address = " << Traits::X86_RET_IP_SIZE_BYTES << " bytes\n" | |
| 469 << " preserved registers = " << PreservedRegsSizeBytes << " bytes\n" | |
| 470 << " spill area padding = " << SpillAreaPaddingBytes << " bytes\n" | |
| 471 << " globals spill area = " << GlobalsSize << " bytes\n" | |
| 472 << " globals-locals spill areas intermediate padding = " | |
| 473 << GlobalsAndSubsequentPaddingSize - GlobalsSize << " bytes\n" | |
| 474 << " locals spill area = " << LocalsSpillAreaSize << " bytes\n" | |
| 475 << " esp alignment padding = " << EspAdjustmentPaddingSize | |
| 476 << " bytes\n"; | |
| 477 | |
| 478 Str << "Stack details:\n" | |
| 479 << " esp adjustment = " << SpillAreaSizeBytes << " bytes\n" | |
| 480 << " spill area alignment = " << SpillAreaAlignmentBytes << " bytes\n" | |
| 481 << " outgoing args size = " << maxOutArgsSizeBytes() << " bytes\n" | |
| 482 << " locals spill area alignment = " << LocalsSlotsAlignmentBytes | |
| 483 << " bytes\n" | |
| 484 << " is ebp based = " << IsEbpBasedFrame << "\n"; | |
| 485 } | |
| 486 } | |
| 487 | |
| 488 void TargetX8632::addEpilog(CfgNode *Node) { | |
| 489 InstList &Insts = Node->getInsts(); | |
| 490 InstList::reverse_iterator RI, E; | |
| 491 for (RI = Insts.rbegin(), E = Insts.rend(); RI != E; ++RI) { | |
| 492 if (llvm::isa<typename Traits::Insts::Ret>(*RI)) | |
| 493 break; | |
| 494 } | |
| 495 if (RI == E) | |
| 496 return; | |
| 497 | |
| 498 // Convert the reverse_iterator position into its corresponding (forward) | |
| 499 // iterator position. | |
| 500 InstList::iterator InsertPoint = RI.base(); | |
| 501 --InsertPoint; | |
| 502 Context.init(Node); | |
| 503 Context.setInsertPoint(InsertPoint); | |
| 504 | |
| 505 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); | |
| 506 if (IsEbpBasedFrame) { | |
| 507 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp); | |
| 508 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake | |
| 509 // use of esp before the assignment of esp=ebp keeps previous esp | |
| 510 // adjustments from being dead-code eliminated. | |
| 511 Context.insert<InstFakeUse>(esp); | |
| 512 _mov(esp, ebp); | |
| 513 _pop(ebp); | |
| 514 } else { | |
| 515 // add esp, SpillAreaSizeBytes | |
| 516 if (SpillAreaSizeBytes) | |
| 517 _add(esp, Ctx->getConstantInt32(SpillAreaSizeBytes)); | |
| 518 } | |
| 519 | |
| 520 // Add pop instructions for preserved registers. | |
| 521 llvm::SmallBitVector CalleeSaves = | |
| 522 getRegisterSet(RegSet_CalleeSave, RegSet_None); | |
| 523 llvm::SmallBitVector Popped(CalleeSaves.size()); | |
| 524 for (SizeT i = 0; i < CalleeSaves.size(); ++i) { | |
| 525 SizeT Canonical = Traits::getBaseReg(i); | |
| 526 if (CalleeSaves[i] && RegsUsed[i]) { | |
| 527 Popped[Canonical] = true; | |
| 528 } | |
| 529 } | |
| 530 for (SizeT i = 0; i < Popped.size(); ++i) { | |
| 531 SizeT j = Popped.size() - i - 1; | |
| 532 SizeT Canonical = Traits::getBaseReg(j); | |
| 533 if (j == Traits::RegisterSet::Reg_ebp && IsEbpBasedFrame) | |
| 534 continue; | |
| 535 if (Popped[j]) { | |
| 536 _pop(getPhysicalRegister(Canonical)); | |
| 537 } | |
| 538 } | |
| 539 | |
| 540 if (!NeedSandboxing) { | |
| 541 return; | |
| 542 } | |
| 543 | |
| 544 // Change the original ret instruction into a sandboxed return sequence. | 260 // Change the original ret instruction into a sandboxed return sequence. |
| 545 // t:ecx = pop | 261 // t:ecx = pop |
| 546 // bundle_lock | 262 // bundle_lock |
| 547 // and t, ~31 | 263 // and t, ~31 |
| 548 // jmp *t | 264 // jmp *t |
| 549 // bundle_unlock | 265 // bundle_unlock |
| 550 // FakeUse <original_ret_operand> | 266 // FakeUse <original_ret_operand> |
| 551 Variable *T_ecx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx); | 267 Variable *T_ecx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx); |
| 552 _pop(T_ecx); | 268 _pop(T_ecx); |
| 553 lowerIndirectJump(T_ecx); | 269 lowerIndirectJump(T_ecx); |
| 554 if (RI->getSrcSize()) { | |
| 555 auto *RetValue = llvm::cast<Variable>(RI->getSrc(0)); | |
| 556 Context.insert<InstFakeUse>(RetValue); | |
| 557 } | |
| 558 RI->setDeleted(); | |
| 559 } | 270 } |
| 560 | 271 |
| 561 void TargetX8632::emitJumpTable(const Cfg *Func, | 272 void TargetX8632::emitJumpTable(const Cfg *Func, |
| 562 const InstJumpTable *JumpTable) const { | 273 const InstJumpTable *JumpTable) const { |
| 563 if (!BuildDefs::dump()) | 274 if (!BuildDefs::dump()) |
| 564 return; | 275 return; |
| 565 Ostream &Str = Ctx->getStrEmit(); | 276 Ostream &Str = Ctx->getStrEmit(); |
| 566 const bool UseNonsfi = Ctx->getFlags().getUseNonsfi(); | 277 const bool UseNonsfi = Ctx->getFlags().getUseNonsfi(); |
| 567 const IceString MangledName = Ctx->mangleName(Func->getFunctionName()); | 278 const IceString MangledName = Ctx->mangleName(Func->getFunctionName()); |
| 568 const IceString Prefix = UseNonsfi ? ".data.rel.ro." : ".rodata."; | 279 const IceString Prefix = UseNonsfi ? ".data.rel.ro." : ".rodata."; |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 879 #define X(tag, sizeLog2, align, elts, elty, str) \ | 590 #define X(tag, sizeLog2, align, elts, elty, str) \ |
| 880 static_assert(_table1_##tag == _table2_##tag, \ | 591 static_assert(_table1_##tag == _table2_##tag, \ |
| 881 "Inconsistency between ICETYPEX8632_TABLE and ICETYPE_TABLE"); | 592 "Inconsistency between ICETYPEX8632_TABLE and ICETYPE_TABLE"); |
| 882 ICETYPE_TABLE | 593 ICETYPE_TABLE |
| 883 #undef X | 594 #undef X |
| 884 } // end of namespace dummy3 | 595 } // end of namespace dummy3 |
| 885 } // end of anonymous namespace | 596 } // end of anonymous namespace |
| 886 | 597 |
| 887 } // end of namespace X8632 | 598 } // end of namespace X8632 |
| 888 } // end of namespace Ice | 599 } // end of namespace Ice |
| OLD | NEW |