Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceTargetLoweringX8664.cpp - x86-64 lowering -----------===// | 1 //===- subzero/src/IceTargetLoweringX8664.cpp - x86-64 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 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 287 } else { | 287 } else { |
| 288 _push_rbp(); | 288 _push_rbp(); |
| 289 } | 289 } |
| 290 } | 290 } |
| 291 | 291 |
| 292 void TargetX8664::emitGetIP(CfgNode *Node) { | 292 void TargetX8664::emitGetIP(CfgNode *Node) { |
| 293 // No IP base register is needed on X86-64. | 293 // No IP base register is needed on X86-64. |
| 294 (void)Node; | 294 (void)Node; |
| 295 } | 295 } |
| 296 | 296 |
| 297 namespace { | |
| 298 bool isAssignedToRspOrRbp(const Variable *Var) { | |
| 299 if (Var == nullptr) { | |
| 300 return false; | |
| 301 } | |
| 302 | |
| 303 if (Var->isRematerializable()) { | |
| 304 return true; | |
| 305 } | |
| 306 | |
| 307 if (!Var->hasReg()) { | |
|
Jim Stichnoth
2016/01/23 01:57:47
Optional: You could skip this condition if you wan
John
2016/01/26 19:44:25
I did not know that. I will leave this as is -- ex
| |
| 308 return false; | |
| 309 } | |
| 310 | |
| 311 int32_t RegNum = Var->getRegNum(); | |
|
Jim Stichnoth
2016/01/23 01:57:47
const
John
2016/01/26 19:44:25
Done.
| |
| 312 if ((RegNum == Traits::RegisterSet::Reg_rsp) || | |
| 313 (RegNum == Traits::RegisterSet::Reg_rbp)) { | |
| 314 return true; | |
| 315 } | |
| 316 | |
| 317 return false; | |
| 318 } | |
| 319 } // end of anonymous namespace | |
| 320 | |
| 297 Traits::X86OperandMem *TargetX8664::_sandbox_mem_reference(X86OperandMem *Mem) { | 321 Traits::X86OperandMem *TargetX8664::_sandbox_mem_reference(X86OperandMem *Mem) { |
| 298 // In x86_64-nacl, all memory references are relative to %r15 (i.e., %rzp.) | |
| 299 // NaCl sandboxing also requires that any registers that are not %rsp and | |
| 300 // %rbp to be 'truncated' to 32-bit before memory access. | |
| 301 if (SandboxingType == ST_None) { | 322 if (SandboxingType == ST_None) { |
| 302 return Mem; | 323 return Mem; |
| 303 } | 324 } |
| 304 | 325 |
| 305 if (SandboxingType == ST_Nonsfi) { | 326 if (SandboxingType == ST_Nonsfi) { |
| 306 llvm::report_fatal_error( | 327 llvm::report_fatal_error( |
| 307 "_sandbox_mem_reference not implemented for nonsfi"); | 328 "_sandbox_mem_reference not implemented for nonsfi"); |
| 308 } | 329 } |
| 309 | 330 |
| 331 // In x86_64-nacl, all memory references are relative to a base register | |
| 332 // (%r15, %rsp, %rbp, or %rip). | |
| 333 | |
| 310 Variable *Base = Mem->getBase(); | 334 Variable *Base = Mem->getBase(); |
| 311 Variable *Index = Mem->getIndex(); | 335 Variable *Index = Mem->getIndex(); |
| 312 uint16_t Shift = 0; | 336 uint16_t Shift = 0; |
| 313 Variable *ZeroReg = | 337 Variable *ZeroReg = RebasePtr; |
| 314 getPhysicalRegister(Traits::RegisterSet::Reg_r15, IceType_i64); | |
| 315 Constant *Offset = Mem->getOffset(); | 338 Constant *Offset = Mem->getOffset(); |
| 316 Variable *T = nullptr; | 339 Variable *T = nullptr; |
| 317 | 340 |
| 341 if (Base == nullptr && Index == nullptr) { | |
| 342 // Mem is RIP-relative. There's no need to rebase it. | |
| 343 return Mem; | |
| 344 } | |
| 345 | |
| 318 if (Mem->getIsRebased()) { | 346 if (Mem->getIsRebased()) { |
| 319 // If Mem.IsRebased, then we don't need to update Mem to contain a reference | 347 // If Mem.IsRebased, then we don't need to update Mem, as it's already been |
| 320 // to a valid base register (%r15, %rsp, or %rbp), but we still need to | 348 // updated to contain a reference to one of %rsp, %rbp, or %r15. |
| 321 // truncate Mem.Index (if any) to 32-bit. | 349 // We don't return early because we still need to zero extend Index. |
|
Jim Stichnoth
2016/01/23 01:57:47
Is the "don't return early" comment because of my
John
2016/01/26 19:44:25
no, it is not. The previous comment said "but we s
| |
| 322 assert(ZeroReg == Base || Base->isRematerializable()); | 350 assert(ZeroReg == Base || isAssignedToRspOrRbp(Base)); |
| 323 T = makeReg(IceType_i32); | 351 ZeroReg = Base; |
| 324 _mov(T, Index); | 352 if (Index != nullptr) { |
| 325 Shift = Mem->getShift(); | 353 T = makeReg(IceType_i32); |
| 354 _mov(T, Index); | |
| 355 Shift = Mem->getShift(); | |
| 356 } | |
| 326 } else { | 357 } else { |
| 327 if (Base != nullptr) { | 358 if (Base != nullptr) { |
| 328 if (Base->isRematerializable()) { | 359 // If Base is a valid base pointer we don't need to use the RebasePtr. By |
| 360 // doing this we might save us the need to zero extend the memory operand. | |
| 361 if (isAssignedToRspOrRbp(Base)) { | |
| 329 ZeroReg = Base; | 362 ZeroReg = Base; |
| 330 } else { | 363 } else { |
| 331 T = Base; | 364 T = Base; |
| 332 } | 365 } |
| 333 } | 366 } |
| 334 | 367 |
| 335 if (Index != nullptr) { | 368 if (Index != nullptr) { |
| 336 assert(!Index->isRematerializable()); | 369 assert(!Index->isRematerializable()); |
| 370 // If Index is not nullptr, it is mandatory that T is a nullptr. | |
| 371 // Otherwise, the lowering generated an memory operand with two registers. | |
|
Jim Stichnoth
2016/01/23 01:57:47
s/an/a/
John
2016/01/26 19:44:25
Done.
| |
| 372 // Note that Base might still be non-nullptr, but it must be a valid | |
| 373 // base register. | |
| 337 if (T != nullptr) { | 374 if (T != nullptr) { |
| 338 llvm::report_fatal_error("memory reference contains base and index."); | 375 llvm::report_fatal_error("memory reference contains base and index."); |
| 339 } | 376 } |
| 340 T = Index; | 377 // If the Index is not shifted, and it is a Valid Base, and the ZeroReg is |
| 341 Shift = Mem->getShift(); | 378 // still RebasePtr, then we do ZeroReg = Index, and hopefully prevent the |
| 379 // need to zero-extend the memory operand (which may still happen -- see | |
| 380 // NeedLea below.) | |
| 381 if (Shift == 0 && isAssignedToRspOrRbp(Index) && ZeroReg == RebasePtr) { | |
| 382 ZeroReg = Index; | |
| 383 } else { | |
| 384 T = Index; | |
| 385 Shift = Mem->getShift(); | |
| 386 } | |
| 342 } | 387 } |
| 343 } | 388 } |
| 344 | 389 |
| 345 // NeedsLea is a flags indicating whether Mem needs to be materialized to a | 390 // NeedsLea is a flags indicating whether Mem needs to be materialized to a |
| 346 // GPR prior to being used. A LEA is needed if Mem.Offset is a constant | 391 // GPR prior to being used. A LEA is needed if Mem.Offset is a constant |
| 347 // relocatable, or if Mem.Offset is negative. In both these cases, the LEA is | 392 // relocatable, or if Mem.Offset is negative. In both these cases, the LEA is |
| 348 // needed to ensure the sandboxed memory operand will only use the lower | 393 // needed to ensure the sandboxed memory operand will only use the lower |
| 349 // 32-bits of T+Offset. | 394 // 32-bits of T+Offset. |
| 350 bool NeedsLea = false; | 395 bool NeedsLea = false; |
| 351 if (const auto *Offset = Mem->getOffset()) { | 396 if (const auto *Offset = Mem->getOffset()) { |
| 352 if (llvm::isa<ConstantRelocatable>(Offset)) { | 397 if (llvm::isa<ConstantRelocatable>(Offset)) { |
| 353 NeedsLea = true; | 398 NeedsLea = true; |
| 354 } else if (const auto *Imm = llvm::cast<ConstantInteger32>(Offset)) { | 399 } else if (const auto *Imm = llvm::cast<ConstantInteger32>(Offset)) { |
| 355 NeedsLea = Imm->getValue() < 0; | 400 NeedsLea = Imm->getValue() < 0; |
| 356 } | 401 } |
| 357 } | 402 } |
| 358 | 403 |
| 359 int32_t RegNum = Variable::NoRegister; | 404 int32_t RegNum = Variable::NoRegister; |
| 360 int32_t RegNum32 = Variable::NoRegister; | 405 int32_t RegNum32 = Variable::NoRegister; |
| 361 if (T != nullptr) { | 406 if (T != nullptr) { |
| 362 if (T->hasReg()) { | 407 if (T->hasReg()) { |
| 363 RegNum = Traits::getGprForType(IceType_i64, T->getRegNum()); | 408 RegNum = Traits::getGprForType(IceType_i64, T->getRegNum()); |
| 364 RegNum32 = Traits::getGprForType(IceType_i32, RegNum); | 409 RegNum32 = Traits::getGprForType(IceType_i32, RegNum); |
| 365 switch (RegNum) { | 410 // At this point, if T was assigned to rsp/rbp, then we would have already |
| 366 case Traits::RegisterSet::Reg_rsp: | 411 // made this the ZeroReg. |
| 367 case Traits::RegisterSet::Reg_rbp: | 412 assert(RegNum != Traits::RegisterSet::Reg_rsp); |
| 368 // Memory operands referencing rsp/rbp do not need to be sandboxed. | 413 assert(RegNum != Traits::RegisterSet::Reg_rbp); |
| 369 return Mem; | |
| 370 } | |
| 371 } | 414 } |
| 372 | 415 |
| 373 switch (T->getType()) { | 416 switch (T->getType()) { |
| 374 default: | 417 default: |
| 418 llvm::report_fatal_error("Mem pointer should be a 32-bit integer."); | |
|
Jim Stichnoth
2016/01/23 01:57:47
Here and below, would it make more sense to say "G
John
2016/01/26 19:44:25
I tend to think about GPRs/Regs in the assembler.
| |
| 375 case IceType_i64: | 419 case IceType_i64: |
| 376 // Even though "default:" would also catch T.Type == IceType_i64, an | 420 // Even though "default:" would also catch T.Type == IceType_i64, an |
| 377 // explicit 'case IceType_i64' shows that memory operands are always | 421 // explicit 'case IceType_i64' shows that memory operands are always |
| 378 // supposed to be 32-bits. | 422 // supposed to be 32-bits. |
| 379 llvm::report_fatal_error("Mem pointer should be 32-bit."); | 423 llvm::report_fatal_error("Mem pointer should not be a 64-bit integer."); |
| 380 case IceType_i32: { | 424 case IceType_i32: { |
| 381 Variable *T64 = makeReg(IceType_i64, RegNum); | 425 Variable *T64 = makeReg(IceType_i64, RegNum); |
| 382 auto *Movzx = _movzx(T64, T); | 426 auto *Movzx = _movzx(T64, T); |
| 383 if (!NeedsLea) { | 427 if (!NeedsLea) { |
| 384 // This movzx is only needed when Mem does not need to be lea'd into a | 428 // This movzx is only needed when Mem does not need to be lea'd into a |
| 385 // temporary. If an lea is going to be emitted, then eliding this movzx | 429 // temporary. If an lea is going to be emitted, then eliding this movzx |
| 386 // is safe because the emitted lea will write a 32-bit result -- | 430 // is safe because the emitted lea will write a 32-bit result -- |
| 387 // implicitly zero-extended to 64-bit. | 431 // implicitly zero-extended to 64-bit. |
| 388 Movzx->setMustKeep(); | 432 Movzx->setMustKeep(); |
| 389 } | 433 } |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 716 #define X(tag, sizeLog2, align, elts, elty, str) \ | 760 #define X(tag, sizeLog2, align, elts, elty, str) \ |
| 717 static_assert(_table1_##tag == _table2_##tag, \ | 761 static_assert(_table1_##tag == _table2_##tag, \ |
| 718 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); | 762 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); |
| 719 ICETYPE_TABLE | 763 ICETYPE_TABLE |
| 720 #undef X | 764 #undef X |
| 721 } // end of namespace dummy3 | 765 } // end of namespace dummy3 |
| 722 } // end of anonymous namespace | 766 } // end of anonymous namespace |
| 723 | 767 |
| 724 } // end of namespace X8664 | 768 } // end of namespace X8664 |
| 725 } // end of namespace Ice | 769 } // end of namespace Ice |
| OLD | NEW |