Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: src/IceTargetLoweringX8664.cpp

Issue 1616103002: Subzero. X8664. Enables RIP-based addressing mode. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Addresses comments. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceInstX8664.cpp ('k') | src/IceTargetLoweringX8664Traits.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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()) {
308 return false;
309 }
310
311 const int32_t RegNum = Var->getRegNum();
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 bool AbsoluteAddress = false;
342 if (Base == nullptr && Index == nullptr) {
343 if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) {
344 if (CR->getName() != "") {
345 // Mem is RIP-relative. There's no need to rebase it.
346 return Mem;
347 }
348 }
349 // Offset is an absolute address, so we need to emit
350 // Offset(%r15)
351 AbsoluteAddress = true;
352 }
353
318 if (Mem->getIsRebased()) { 354 if (Mem->getIsRebased()) {
319 // If Mem.IsRebased, then we don't need to update Mem to contain a reference 355 // 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 356 // updated to contain a reference to one of %rsp, %rbp, or %r15.
321 // truncate Mem.Index (if any) to 32-bit. 357 // We don't return early because we still need to zero extend Index.
322 assert(ZeroReg == Base || Base->isRematerializable()); 358 assert(ZeroReg == Base || AbsoluteAddress || isAssignedToRspOrRbp(Base));
323 T = makeReg(IceType_i32); 359 if (!AbsoluteAddress) {
324 _mov(T, Index); 360 // If Mem is an absolute address, no need to update ZeroReg (which is
325 Shift = Mem->getShift(); 361 // already set to %r15.)
362 ZeroReg = Base;
363 }
364 if (Index != nullptr) {
365 T = makeReg(IceType_i32);
366 _mov(T, Index);
367 Shift = Mem->getShift();
368 }
326 } else { 369 } else {
327 if (Base != nullptr) { 370 if (Base != nullptr) {
328 if (Base->isRematerializable()) { 371 // If Base is a valid base pointer we don't need to use the RebasePtr. By
372 // doing this we might save us the need to zero extend the memory operand.
373 if (isAssignedToRspOrRbp(Base)) {
329 ZeroReg = Base; 374 ZeroReg = Base;
330 } else { 375 } else {
331 T = Base; 376 T = Base;
332 } 377 }
333 } 378 }
334 379
335 if (Index != nullptr) { 380 if (Index != nullptr) {
336 assert(!Index->isRematerializable()); 381 assert(!Index->isRematerializable());
382 // If Index is not nullptr, it is mandatory that T is a nullptr.
383 // Otherwise, the lowering generated a memory operand with two registers.
384 // Note that Base might still be non-nullptr, but it must be a valid
385 // base register.
337 if (T != nullptr) { 386 if (T != nullptr) {
338 llvm::report_fatal_error("memory reference contains base and index."); 387 llvm::report_fatal_error("memory reference contains base and index.");
339 } 388 }
340 T = Index; 389 // If the Index is not shifted, and it is a Valid Base, and the ZeroReg is
341 Shift = Mem->getShift(); 390 // still RebasePtr, then we do ZeroReg = Index, and hopefully prevent the
391 // need to zero-extend the memory operand (which may still happen -- see
392 // NeedLea below.)
393 if (Shift == 0 && isAssignedToRspOrRbp(Index) && ZeroReg == RebasePtr) {
394 ZeroReg = Index;
395 } else {
396 T = Index;
397 Shift = Mem->getShift();
398 }
342 } 399 }
343 } 400 }
344 401
345 // NeedsLea is a flags indicating whether Mem needs to be materialized to a 402 // 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 403 // 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 404 // 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 405 // needed to ensure the sandboxed memory operand will only use the lower
349 // 32-bits of T+Offset. 406 // 32-bits of T+Offset.
350 bool NeedsLea = false; 407 bool NeedsLea = false;
351 if (const auto *Offset = Mem->getOffset()) { 408 if (Offset != nullptr) {
352 if (llvm::isa<ConstantRelocatable>(Offset)) { 409 if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) {
353 NeedsLea = true; 410 NeedsLea = CR->getName() != "" || CR->getOffset() < 0;
354 } else if (const auto *Imm = llvm::cast<ConstantInteger32>(Offset)) { 411 } else if (const auto *Imm = llvm::cast<ConstantInteger32>(Offset)) {
355 NeedsLea = Imm->getValue() < 0; 412 NeedsLea = Imm->getValue() < 0;
413 } else {
414 llvm::report_fatal_error("Unexpected Offset type.");
356 } 415 }
357 } 416 }
358 417
359 int32_t RegNum = Variable::NoRegister; 418 int32_t RegNum = Variable::NoRegister;
360 int32_t RegNum32 = Variable::NoRegister; 419 int32_t RegNum32 = Variable::NoRegister;
361 if (T != nullptr) { 420 if (T != nullptr) {
362 if (T->hasReg()) { 421 if (T->hasReg()) {
363 RegNum = Traits::getGprForType(IceType_i64, T->getRegNum()); 422 RegNum = Traits::getGprForType(IceType_i64, T->getRegNum());
364 RegNum32 = Traits::getGprForType(IceType_i32, RegNum); 423 RegNum32 = Traits::getGprForType(IceType_i32, RegNum);
365 switch (RegNum) { 424 // At this point, if T was assigned to rsp/rbp, then we would have already
366 case Traits::RegisterSet::Reg_rsp: 425 // made this the ZeroReg.
367 case Traits::RegisterSet::Reg_rbp: 426 assert(RegNum != Traits::RegisterSet::Reg_rsp);
368 // Memory operands referencing rsp/rbp do not need to be sandboxed. 427 assert(RegNum != Traits::RegisterSet::Reg_rbp);
369 return Mem;
370 }
371 } 428 }
372 429
373 switch (T->getType()) { 430 switch (T->getType()) {
374 default: 431 default:
432 llvm::report_fatal_error("Mem pointer should be a 32-bit GPR.");
375 case IceType_i64: 433 case IceType_i64:
376 // Even though "default:" would also catch T.Type == IceType_i64, an 434 // Even though "default:" would also catch T.Type == IceType_i64, an
377 // explicit 'case IceType_i64' shows that memory operands are always 435 // explicit 'case IceType_i64' shows that memory operands are always
378 // supposed to be 32-bits. 436 // supposed to be 32-bits.
379 llvm::report_fatal_error("Mem pointer should be 32-bit."); 437 llvm::report_fatal_error("Mem pointer should not be a 64-bit GPR.");
380 case IceType_i32: { 438 case IceType_i32: {
381 Variable *T64 = makeReg(IceType_i64, RegNum); 439 Variable *T64 = makeReg(IceType_i64, RegNum);
382 auto *Movzx = _movzx(T64, T); 440 auto *Movzx = _movzx(T64, T);
383 if (!NeedsLea) { 441 if (!NeedsLea) {
384 // This movzx is only needed when Mem does not need to be lea'd into a 442 // 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 443 // 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 -- 444 // is safe because the emitted lea will write a 32-bit result --
387 // implicitly zero-extended to 64-bit. 445 // implicitly zero-extended to 64-bit.
388 Movzx->setMustKeep(); 446 Movzx->setMustKeep();
389 } 447 }
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
716 #define X(tag, sizeLog2, align, elts, elty, str, rcstr) \ 774 #define X(tag, sizeLog2, align, elts, elty, str, rcstr) \
717 static_assert(_table1_##tag == _table2_##tag, \ 775 static_assert(_table1_##tag == _table2_##tag, \
718 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); 776 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE");
719 ICETYPE_TABLE 777 ICETYPE_TABLE
720 #undef X 778 #undef X
721 } // end of namespace dummy3 779 } // end of namespace dummy3
722 } // end of anonymous namespace 780 } // end of anonymous namespace
723 781
724 } // end of namespace X8664 782 } // end of namespace X8664
725 } // end of namespace Ice 783 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceInstX8664.cpp ('k') | src/IceTargetLoweringX8664Traits.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698