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 |