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

Side by Side Diff: src/IceInstX86BaseImpl.h

Issue 1559243002: Suzero. X8664. NaCl Sandboxing. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fixes filetype=asm; 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/IceInstX86Base.h ('k') | src/IceRegistersX8664.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/IceInstX86BaseImpl.h - Generic X86 instructions -*- C++ -*=// 1 //===- subzero/src/IceInstX86BaseImpl.h - Generic X86 instructions -*- C++ -*=//
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 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 : InstX86Base(Func, InstX86Base::Pop, 0, Dest) { 317 : InstX86Base(Func, InstX86Base::Pop, 0, Dest) {
318 // A pop instruction affects the stack pointer and so it should not be 318 // A pop instruction affects the stack pointer and so it should not be
319 // allowed to be automatically dead-code eliminated. (The corresponding push 319 // allowed to be automatically dead-code eliminated. (The corresponding push
320 // instruction doesn't need this treatment because it has no dest variable 320 // instruction doesn't need this treatment because it has no dest variable
321 // and therefore won't be dead-code eliminated.) This is needed for 321 // and therefore won't be dead-code eliminated.) This is needed for
322 // late-stage liveness analysis (e.g. asm-verbose mode). 322 // late-stage liveness analysis (e.g. asm-verbose mode).
323 this->HasSideEffects = true; 323 this->HasSideEffects = true;
324 } 324 }
325 325
326 template <typename TraitsType> 326 template <typename TraitsType>
327 InstImpl<TraitsType>::InstX86Push::InstX86Push(Cfg *Func, Variable *Source) 327 InstImpl<TraitsType>::InstX86Push::InstX86Push(Cfg *Func, Operand *Source)
328 : InstX86Base(Func, InstX86Base::Push, 1, nullptr) { 328 : InstX86Base(Func, InstX86Base::Push, 1, nullptr) {
329 this->addSource(Source); 329 this->addSource(Source);
330 } 330 }
331 331
332 template <typename TraitsType> 332 template <typename TraitsType>
333 InstImpl<TraitsType>::InstX86Push::InstX86Push(Cfg *Func, InstX86Label *L)
334 : InstX86Base(Func, InstX86Base::Push, 0, nullptr), Label(L) {}
335
336 template <typename TraitsType>
333 InstImpl<TraitsType>::InstX86Ret::InstX86Ret(Cfg *Func, Variable *Source) 337 InstImpl<TraitsType>::InstX86Ret::InstX86Ret(Cfg *Func, Variable *Source)
334 : InstX86Base(Func, InstX86Base::Ret, Source ? 1 : 0, nullptr) { 338 : InstX86Base(Func, InstX86Base::Ret, Source ? 1 : 0, nullptr) {
335 if (Source) 339 if (Source)
336 this->addSource(Source); 340 this->addSource(Source);
337 } 341 }
338 342
339 template <typename TraitsType> 343 template <typename TraitsType>
340 InstImpl<TraitsType>::InstX86Setcc::InstX86Setcc(Cfg *Func, Variable *Dest, 344 InstImpl<TraitsType>::InstX86Setcc::InstX86Setcc(Cfg *Func, Variable *Dest,
341 BrCond Cond) 345 BrCond Cond)
342 : InstX86Base(Func, InstX86Base::Setcc, 0, Dest), Condition(Cond) {} 346 : InstX86Base(Func, InstX86Base::Setcc, 0, Dest), Condition(Cond) {}
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
448 void InstImpl<TraitsType>::InstX86Label::emit(const Cfg *Func) const { 452 void InstImpl<TraitsType>::InstX86Label::emit(const Cfg *Func) const {
449 if (!BuildDefs::dump()) 453 if (!BuildDefs::dump())
450 return; 454 return;
451 Ostream &Str = Func->getContext()->getStrEmit(); 455 Ostream &Str = Func->getContext()->getStrEmit();
452 Str << getName(Func) << ":"; 456 Str << getName(Func) << ":";
453 } 457 }
454 458
455 template <typename TraitsType> 459 template <typename TraitsType>
456 void InstImpl<TraitsType>::InstX86Label::emitIAS(const Cfg *Func) const { 460 void InstImpl<TraitsType>::InstX86Label::emitIAS(const Cfg *Func) const {
457 Assembler *Asm = Func->getAssembler<Assembler>(); 461 Assembler *Asm = Func->getAssembler<Assembler>();
462 if (IsReturnLocation) {
463 Asm->addRelocationAtCurrentPosition(getName(Func));
464 }
458 Asm->bindLocalLabel(Number); 465 Asm->bindLocalLabel(Number);
459 } 466 }
460 467
461 template <typename TraitsType> 468 template <typename TraitsType>
462 void InstImpl<TraitsType>::InstX86Label::dump(const Cfg *Func) const { 469 void InstImpl<TraitsType>::InstX86Label::dump(const Cfg *Func) const {
463 if (!BuildDefs::dump()) 470 if (!BuildDefs::dump())
464 return; 471 return;
465 Ostream &Str = Func->getContext()->getStrDump(); 472 Ostream &Str = Func->getContext()->getStrDump();
466 Str << getName(Func) << ":"; 473 Str << getName(Func) << ":";
467 } 474 }
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 552
546 Str << " // (" << (isNear() ? "near" : "far") << " jump)"; 553 Str << " // (" << (isNear() ? "near" : "far") << " jump)";
547 } 554 }
548 555
549 template <typename TraitsType> 556 template <typename TraitsType>
550 void InstImpl<TraitsType>::InstX86Jmp::emit(const Cfg *Func) const { 557 void InstImpl<TraitsType>::InstX86Jmp::emit(const Cfg *Func) const {
551 if (!BuildDefs::dump()) 558 if (!BuildDefs::dump())
552 return; 559 return;
553 Ostream &Str = Func->getContext()->getStrEmit(); 560 Ostream &Str = Func->getContext()->getStrEmit();
554 assert(this->getSrcSize() == 1); 561 assert(this->getSrcSize() == 1);
562 const Operand *Src = this->getSrc(0);
563 if (Traits::Is64Bit) {
564 if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src)) {
565 Str << "\t"
566 "jmp"
567 "\t" << CR->getName();
568 return;
569 }
570 }
555 Str << "\t" 571 Str << "\t"
556 "jmp\t*"; 572 "jmp"
573 "\t*";
557 getJmpTarget()->emit(Func); 574 getJmpTarget()->emit(Func);
558 } 575 }
559 576
560 template <typename TraitsType> 577 template <typename TraitsType>
561 void InstImpl<TraitsType>::InstX86Jmp::emitIAS(const Cfg *Func) const { 578 void InstImpl<TraitsType>::InstX86Jmp::emitIAS(const Cfg *Func) const {
562 // Note: Adapted (mostly copied) from 579 // Note: Adapted (mostly copied) from
563 // InstImpl<TraitsType>::InstX86Call::emitIAS(). 580 // InstImpl<TraitsType>::InstX86Call::emitIAS().
564 Assembler *Asm = Func->getAssembler<Assembler>(); 581 Assembler *Asm = Func->getAssembler<Assembler>();
565 Operand *Target = getJmpTarget(); 582 Operand *Target = getJmpTarget();
566 if (const auto *Var = llvm::dyn_cast<Variable>(Target)) { 583 if (const auto *Var = llvm::dyn_cast<Variable>(Target)) {
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Op)) { 717 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Op)) {
701 Mem->emitSegmentOverride(Asm); 718 Mem->emitSegmentOverride(Asm);
702 (Asm->*(Emitter.Addr))(Ty, Mem->toAsmAddress(Asm, Target)); 719 (Asm->*(Emitter.Addr))(Ty, Mem->toAsmAddress(Asm, Target));
703 } else { 720 } else {
704 llvm_unreachable("Unexpected operand type"); 721 llvm_unreachable("Unexpected operand type");
705 } 722 }
706 } 723 }
707 724
708 template <typename TraitsType> 725 template <typename TraitsType>
709 template <bool VarCanBeByte, bool SrcCanBeByte> 726 template <bool VarCanBeByte, bool SrcCanBeByte>
710 void InstImpl<TraitsType>::emitIASRegOpTyGPR(const Cfg *Func, Type Ty, 727 void InstImpl<TraitsType>::emitIASRegOpTyGPR(const Cfg *Func, bool IsLea,
711 const Variable *Var, 728 Type Ty, const Variable *Var,
712 const Operand *Src, 729 const Operand *Src,
713 const GPREmitterRegOp &Emitter) { 730 const GPREmitterRegOp &Emitter) {
714 auto *Target = InstX86Base::getTarget(Func); 731 auto *Target = InstX86Base::getTarget(Func);
715 Assembler *Asm = Func->getAssembler<Assembler>(); 732 Assembler *Asm = Func->getAssembler<Assembler>();
716 assert(Var->hasReg()); 733 assert(Var->hasReg());
717 // We cheat a little and use GPRRegister even for byte operations. 734 // We cheat a little and use GPRRegister even for byte operations.
718 GPRRegister VarReg = VarCanBeByte ? Traits::getEncodedGPR(Var->getRegNum()) 735 GPRRegister VarReg = VarCanBeByte ? Traits::getEncodedGPR(Var->getRegNum())
719 : Traits::getEncodedGPR(Var->getRegNum()); 736 : Traits::getEncodedGPR(Var->getRegNum());
720 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) { 737 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
721 if (SrcVar->hasReg()) { 738 if (SrcVar->hasReg()) {
722 GPRRegister SrcReg = SrcCanBeByte 739 GPRRegister SrcReg = SrcCanBeByte
723 ? Traits::getEncodedGPR(SrcVar->getRegNum()) 740 ? Traits::getEncodedGPR(SrcVar->getRegNum())
724 : Traits::getEncodedGPR(SrcVar->getRegNum()); 741 : Traits::getEncodedGPR(SrcVar->getRegNum());
725 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg); 742 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
726 } else { 743 } else {
727 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar); 744 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
728 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr); 745 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr);
729 } 746 }
730 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) { 747 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
731 Mem->emitSegmentOverride(Asm); 748 Mem->emitSegmentOverride(Asm);
732 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Mem->toAsmAddress(Asm, Target)); 749 (Asm->*(Emitter.GPRAddr))(Ty, VarReg,
750 Mem->toAsmAddress(Asm, Target, IsLea));
733 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { 751 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
734 (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue())); 752 (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
735 } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { 753 } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
736 AssemblerFixup *Fixup = 754 AssemblerFixup *Fixup =
737 Asm->createFixup(Traits::TargetLowering::getAbsFixup(), Reloc); 755 Asm->createFixup(Traits::TargetLowering::getAbsFixup(), Reloc);
738 (Asm->*(Emitter.GPRImm))(Ty, VarReg, 756 (Asm->*(Emitter.GPRImm))(Ty, VarReg,
739 AssemblerImmediate(Reloc->getOffset(), Fixup)); 757 AssemblerImmediate(Reloc->getOffset(), Fixup));
740 } else if (const auto *Split = llvm::dyn_cast<VariableSplit>(Src)) { 758 } else if (const auto *Split = llvm::dyn_cast<VariableSplit>(Src)) {
741 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func)); 759 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func));
742 } else { 760 } else {
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after
1129 (void)Src0Var; 1147 (void)Src0Var;
1130 assert(Src0Var->getRegNum() == RegisterSet::Reg_al); 1148 assert(Src0Var->getRegNum() == RegisterSet::Reg_al);
1131 static const GPREmitterOneOp Emitter = {&Assembler::imul, &Assembler::imul}; 1149 static const GPREmitterOneOp Emitter = {&Assembler::imul, &Assembler::imul};
1132 emitIASOpTyGPR(Func, Ty, this->getSrc(1), Emitter); 1150 emitIASOpTyGPR(Func, Ty, this->getSrc(1), Emitter);
1133 } else { 1151 } else {
1134 // The two-address version is used when multiplying by a non-constant 1152 // The two-address version is used when multiplying by a non-constant
1135 // or doing an 8-bit multiply. 1153 // or doing an 8-bit multiply.
1136 assert(Var == this->getSrc(0)); 1154 assert(Var == this->getSrc(0));
1137 static const GPREmitterRegOp Emitter = {&Assembler::imul, &Assembler::imul, 1155 static const GPREmitterRegOp Emitter = {&Assembler::imul, &Assembler::imul,
1138 &Assembler::imul}; 1156 &Assembler::imul};
1139 emitIASRegOpTyGPR(Func, Ty, Var, Src, Emitter); 1157 constexpr bool NotLea = false;
1158 emitIASRegOpTyGPR(Func, NotLea, Ty, Var, Src, Emitter);
1140 } 1159 }
1141 } 1160 }
1142 1161
1143 template <typename TraitsType> 1162 template <typename TraitsType>
1144 void InstImpl<TraitsType>::InstX86ImulImm::emit(const Cfg *Func) const { 1163 void InstImpl<TraitsType>::InstX86ImulImm::emit(const Cfg *Func) const {
1145 if (!BuildDefs::dump()) 1164 if (!BuildDefs::dump())
1146 return; 1165 return;
1147 Ostream &Str = Func->getContext()->getStrEmit(); 1166 Ostream &Str = Func->getContext()->getStrEmit();
1148 assert(this->getSrcSize() == 2); 1167 assert(this->getSrcSize() == 2);
1149 Variable *Dest = this->getDest(); 1168 Variable *Dest = this->getDest();
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after
1688 assert(this->getSrcSize() == 2); 1707 assert(this->getSrcSize() == 2);
1689 const Operand *Src0 = this->getSrc(0); 1708 const Operand *Src0 = this->getSrc(0);
1690 const Operand *Src1 = this->getSrc(1); 1709 const Operand *Src1 = this->getSrc(1);
1691 Type Ty = Src0->getType(); 1710 Type Ty = Src0->getType();
1692 static const GPREmitterRegOp RegEmitter = {&Assembler::cmp, &Assembler::cmp, 1711 static const GPREmitterRegOp RegEmitter = {&Assembler::cmp, &Assembler::cmp,
1693 &Assembler::cmp}; 1712 &Assembler::cmp};
1694 static const GPREmitterAddrOp AddrEmitter = {&Assembler::cmp, 1713 static const GPREmitterAddrOp AddrEmitter = {&Assembler::cmp,
1695 &Assembler::cmp}; 1714 &Assembler::cmp};
1696 if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) { 1715 if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
1697 if (SrcVar0->hasReg()) { 1716 if (SrcVar0->hasReg()) {
1698 emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter); 1717 constexpr bool NotLea = false;
1718 emitIASRegOpTyGPR(Func, NotLea, Ty, SrcVar0, Src1, RegEmitter);
1699 return; 1719 return;
1700 } 1720 }
1701 } 1721 }
1702 emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter); 1722 emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter);
1703 } 1723 }
1704 1724
1705 template <typename TraitsType> 1725 template <typename TraitsType>
1706 void InstImpl<TraitsType>::InstX86Icmp::dump(const Cfg *Func) const { 1726 void InstImpl<TraitsType>::InstX86Icmp::dump(const Cfg *Func) const {
1707 if (!BuildDefs::dump()) 1727 if (!BuildDefs::dump())
1708 return; 1728 return;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
1790 const Operand *Src0 = this->getSrc(0); 1810 const Operand *Src0 = this->getSrc(0);
1791 const Operand *Src1 = this->getSrc(1); 1811 const Operand *Src1 = this->getSrc(1);
1792 Type Ty = Src0->getType(); 1812 Type Ty = Src0->getType();
1793 // The Reg/Addr form of test is not encodeable. 1813 // The Reg/Addr form of test is not encodeable.
1794 static const GPREmitterRegOp RegEmitter = {&Assembler::test, nullptr, 1814 static const GPREmitterRegOp RegEmitter = {&Assembler::test, nullptr,
1795 &Assembler::test}; 1815 &Assembler::test};
1796 static const GPREmitterAddrOp AddrEmitter = {&Assembler::test, 1816 static const GPREmitterAddrOp AddrEmitter = {&Assembler::test,
1797 &Assembler::test}; 1817 &Assembler::test};
1798 if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) { 1818 if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
1799 if (SrcVar0->hasReg()) { 1819 if (SrcVar0->hasReg()) {
1800 emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter); 1820 constexpr bool NotLea = false;
1821 emitIASRegOpTyGPR(Func, NotLea, Ty, SrcVar0, Src1, RegEmitter);
1801 return; 1822 return;
1802 } 1823 }
1803 } 1824 }
1804 emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter); 1825 emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter);
1805 } 1826 }
1806 1827
1807 template <typename TraitsType> 1828 template <typename TraitsType>
1808 void InstImpl<TraitsType>::InstX86Test::dump(const Cfg *Func) const { 1829 void InstImpl<TraitsType>::InstX86Test::dump(const Cfg *Func) const {
1809 if (!BuildDefs::dump()) 1830 if (!BuildDefs::dump())
1810 return; 1831 return;
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
1973 } 1994 }
1974 1995
1975 template <typename TraitsType> 1996 template <typename TraitsType>
1976 void InstImpl<TraitsType>::InstX86Lea::emit(const Cfg *Func) const { 1997 void InstImpl<TraitsType>::InstX86Lea::emit(const Cfg *Func) const {
1977 if (!BuildDefs::dump()) 1998 if (!BuildDefs::dump())
1978 return; 1999 return;
1979 Ostream &Str = Func->getContext()->getStrEmit(); 2000 Ostream &Str = Func->getContext()->getStrEmit();
1980 assert(this->getSrcSize() == 1); 2001 assert(this->getSrcSize() == 1);
1981 assert(this->getDest()->hasReg()); 2002 assert(this->getDest()->hasReg());
1982 Str << "\t" 2003 Str << "\t"
1983 "leal\t"; 2004 "lea" << this->getWidthString(this->getDest()->getType()) << "\t";
1984 Operand *Src0 = this->getSrc(0); 2005 Operand *Src0 = this->getSrc(0);
1985 if (const auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) { 2006 if (const auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
1986 Type Ty = Src0Var->getType(); 2007 Type Ty = Src0Var->getType();
1987 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an 2008 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an
1988 // acceptable type. 2009 // acceptable type.
1989 Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty, Variable::NoRegister) 2010 Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty, Variable::NoRegister)
1990 ->emit(Func); 2011 ->emit(Func);
1991 } else { 2012 } else {
1992 Src0->emit(Func); 2013 Src0->emit(Func);
1993 } 2014 }
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
2073 if (Traits::Is64Bit && DestTy == IceType_i64) { 2094 if (Traits::Is64Bit && DestTy == IceType_i64) {
2074 if (const auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src)) { 2095 if (const auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src)) {
2075 Func->getAssembler<Assembler>()->movabs( 2096 Func->getAssembler<Assembler>()->movabs(
2076 Traits::getEncodedGPR(Dest->getRegNum()), C64->getValue()); 2097 Traits::getEncodedGPR(Dest->getRegNum()), C64->getValue());
2077 return; 2098 return;
2078 } 2099 }
2079 } 2100 }
2080 if (isScalarIntegerType(SrcTy)) { 2101 if (isScalarIntegerType(SrcTy)) {
2081 SrcTy = DestTy; 2102 SrcTy = DestTy;
2082 } 2103 }
2083 emitIASRegOpTyGPR(Func, DestTy, Dest, Src, GPRRegEmitter); 2104 constexpr bool NotLea = false;
2105 emitIASRegOpTyGPR(Func, NotLea, DestTy, Dest, Src, GPRRegEmitter);
2084 return; 2106 return;
2085 } 2107 }
2086 } else { 2108 } else {
2087 // Dest must be Stack and Src *could* be a register. Use Src's type to 2109 // Dest must be Stack and Src *could* be a register. Use Src's type to
2088 // decide on the emitters. 2110 // decide on the emitters.
2089 Address StackAddr(Target->stackVarToAsmOperand(Dest)); 2111 Address StackAddr(Target->stackVarToAsmOperand(Dest));
2090 if (isScalarFloatingType(SrcTy)) { 2112 if (isScalarFloatingType(SrcTy)) {
2091 // Src must be a register. 2113 // Src must be a register.
2092 const auto *SrcVar = llvm::cast<Variable>(Src); 2114 const auto *SrcVar = llvm::cast<Variable>(Src);
2093 assert(SrcVar->hasReg()); 2115 assert(SrcVar->hasReg());
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
2250 void InstImpl<TraitsType>::InstX86Movsx::emitIAS(const Cfg *Func) const { 2272 void InstImpl<TraitsType>::InstX86Movsx::emitIAS(const Cfg *Func) const {
2251 assert(this->getSrcSize() == 1); 2273 assert(this->getSrcSize() == 1);
2252 const Variable *Dest = this->getDest(); 2274 const Variable *Dest = this->getDest();
2253 const Operand *Src = this->getSrc(0); 2275 const Operand *Src = this->getSrc(0);
2254 // Dest must be a > 8-bit register, but Src can be 8-bit. In practice we just 2276 // Dest must be a > 8-bit register, but Src can be 8-bit. In practice we just
2255 // use the full register for Dest to avoid having an OperandSizeOverride 2277 // use the full register for Dest to avoid having an OperandSizeOverride
2256 // prefix. It also allows us to only dispatch on SrcTy. 2278 // prefix. It also allows us to only dispatch on SrcTy.
2257 Type SrcTy = Src->getType(); 2279 Type SrcTy = Src->getType();
2258 assert(typeWidthInBytes(Dest->getType()) > 1); 2280 assert(typeWidthInBytes(Dest->getType()) > 1);
2259 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy)); 2281 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
2260 emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, this->Emitter); 2282 constexpr bool NotLea = false;
2283 emitIASRegOpTyGPR<false, true>(Func, NotLea, SrcTy, Dest, Src, this->Emitter);
2261 } 2284 }
2262 2285
2263 template <typename TraitsType> 2286 template <typename TraitsType>
2287 bool InstImpl<TraitsType>::InstX86Movzx::mayBeElided(
2288 const Variable *Dest, const Operand *SrcOpnd) const {
2289 assert(Traits::Is64Bit);
2290 const auto *Src = llvm::dyn_cast<Variable>(SrcOpnd);
2291
2292 // Src is not a Variable, so it does not have a register. Movzx can't be
2293 // elided.
2294 if (Src == nullptr)
2295 return false;
2296
2297 // Movzx to/from memory can't be elided.
2298 if (!Src->hasReg() || !Dest->hasReg())
2299 return false;
2300
2301 // Reg/reg move with different source and dest can't be elided.
2302 if (Traits::getEncodedGPR(Src->getRegNum()) !=
2303 Traits::getEncodedGPR(Dest->getRegNum()))
2304 return false;
2305
2306 // A must-keep movzx 32- to 64-bit is sometimes needed in x86-64 sandboxing.
2307 return !MustKeep;
2308 }
2309
2310 template <typename TraitsType>
2264 void InstImpl<TraitsType>::InstX86Movzx::emit(const Cfg *Func) const { 2311 void InstImpl<TraitsType>::InstX86Movzx::emit(const Cfg *Func) const {
2265 if (!BuildDefs::dump()) 2312 if (!BuildDefs::dump())
2266 return; 2313 return;
2267 if (Traits::Is64Bit) { 2314 if (Traits::Is64Bit) {
2268 // There's no movzx %eXX, %rXX. To zero extend 32- to 64-bits, we emit a 2315 // There's no movzx %eXX, %rXX. To zero extend 32- to 64-bits, we emit a
2269 // mov %eXX, %eXX. The processor will still do a movzx[bw]q. 2316 // mov %eXX, %eXX. The processor will still do a movzx[bw]q.
2270 assert(this->getSrcSize() == 1); 2317 assert(this->getSrcSize() == 1);
2271 const Operand *Src = this->getSrc(0); 2318 const Operand *Src = this->getSrc(0);
2272 const Variable *Dest = this->Dest; 2319 const Variable *Dest = this->Dest;
2273 if (Src->getType() == IceType_i32 && Dest->getType() == IceType_i64) { 2320 if (Src->getType() == IceType_i32 && Dest->getType() == IceType_i64) {
2274 Ostream &Str = Func->getContext()->getStrEmit(); 2321 Ostream &Str = Func->getContext()->getStrEmit();
2275 Str << "\t" 2322 if (mayBeElided(Dest, Src)) {
2276 "mov" 2323 Str << "\t/* elided movzx */";
2277 "\t"; 2324 } else {
2278 Src->emit(Func); 2325 Str << "\t"
2279 Str << ", "; 2326 "mov"
2280 Dest->asType(IceType_i32, 2327 "\t";
2281 Traits::getGprForType(IceType_i32, Dest->getRegNum())) 2328 Src->emit(Func);
2282 ->emit(Func); 2329 Str << ", ";
2283 Str << " /* movzx */"; 2330 Dest->asType(IceType_i32,
2331 Traits::getGprForType(IceType_i32, Dest->getRegNum()))
2332 ->emit(Func);
2333 Str << " /* movzx */";
2334 }
2284 return; 2335 return;
2285 } 2336 }
2286 } 2337 }
2287 InstX86BaseUnaryopGPR<InstX86Base::Movzx>::emit(Func); 2338 InstX86BaseUnaryopGPR<InstX86Base::Movzx>::emit(Func);
2288 } 2339 }
2289 2340
2290 template <typename TraitsType> 2341 template <typename TraitsType>
2291 void InstImpl<TraitsType>::InstX86Movzx::emitIAS(const Cfg *Func) const { 2342 void InstImpl<TraitsType>::InstX86Movzx::emitIAS(const Cfg *Func) const {
2292 assert(this->getSrcSize() == 1); 2343 assert(this->getSrcSize() == 1);
2293 const Variable *Dest = this->getDest(); 2344 const Variable *Dest = this->getDest();
2294 const Operand *Src = this->getSrc(0); 2345 const Operand *Src = this->getSrc(0);
2295 Type SrcTy = Src->getType(); 2346 Type SrcTy = Src->getType();
2296 assert(typeWidthInBytes(Dest->getType()) > 1); 2347 assert(typeWidthInBytes(Dest->getType()) > 1);
2297 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy)); 2348 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
2298 emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, this->Emitter); 2349 if (Traits::Is64Bit) {
2350 if (Src->getType() == IceType_i32 && Dest->getType() == IceType_i64 &&
2351 mayBeElided(Dest, Src)) {
2352 return;
2353 }
2354 }
2355 constexpr bool NotLea = false;
2356 emitIASRegOpTyGPR<false, true>(Func, NotLea, SrcTy, Dest, Src, this->Emitter);
2299 } 2357 }
2300 2358
2301 template <typename TraitsType> 2359 template <typename TraitsType>
2302 void InstImpl<TraitsType>::InstX86Nop::emit(const Cfg *Func) const { 2360 void InstImpl<TraitsType>::InstX86Nop::emit(const Cfg *Func) const {
2303 if (!BuildDefs::dump()) 2361 if (!BuildDefs::dump())
2304 return; 2362 return;
2305 Ostream &Str = Func->getContext()->getStrEmit(); 2363 Ostream &Str = Func->getContext()->getStrEmit();
2306 // TODO: Emit the right code for each variant. 2364 // TODO: Emit the right code for each variant.
2307 Str << "\t" 2365 Str << "\t"
2308 "nop\t/* variant = " << Variant << " */"; 2366 "nop\t/* variant = " << Variant << " */";
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
2610 Ostream &Str = Func->getContext()->getStrDump(); 2668 Ostream &Str = Func->getContext()->getStrDump();
2611 this->dumpDest(Func); 2669 this->dumpDest(Func);
2612 Str << " = pop." << this->getDest()->getType() << " "; 2670 Str << " = pop." << this->getDest()->getType() << " ";
2613 } 2671 }
2614 2672
2615 template <typename TraitsType> 2673 template <typename TraitsType>
2616 void InstImpl<TraitsType>::InstX86Push::emit(const Cfg *Func) const { 2674 void InstImpl<TraitsType>::InstX86Push::emit(const Cfg *Func) const {
2617 if (!BuildDefs::dump()) 2675 if (!BuildDefs::dump())
2618 return; 2676 return;
2619 Ostream &Str = Func->getContext()->getStrEmit(); 2677 Ostream &Str = Func->getContext()->getStrEmit();
2678 Str << "\t"
2679 "push"
2680 "\t";
2620 assert(this->getSrcSize() == 1); 2681 assert(this->getSrcSize() == 1);
2621 // Push is currently only used for saving GPRs. 2682 const Operand *Src = this->getSrc(0);
2622 const auto *Var = llvm::cast<Variable>(this->getSrc(0)); 2683 Src->emit(Func);
2623 assert(Var->hasReg());
2624 Str << "\t"
2625 "push\t";
2626 Var->emit(Func);
2627 } 2684 }
2628 2685
2629 template <typename TraitsType> 2686 template <typename TraitsType>
2630 void InstImpl<TraitsType>::InstX86Push::emitIAS(const Cfg *Func) const { 2687 void InstImpl<TraitsType>::InstX86Push::emitIAS(const Cfg *Func) const {
2688 Assembler *Asm = Func->getAssembler<Assembler>();
2689
2631 assert(this->getSrcSize() == 1); 2690 assert(this->getSrcSize() == 1);
2632 // Push is currently only used for saving GPRs. 2691 const Operand *Src = this->getSrc(0);
2633 const auto *Var = llvm::cast<Variable>(this->getSrc(0)); 2692
2634 assert(Var->hasReg()); 2693 if (const auto *Var = llvm::dyn_cast<Variable>(Src)) {
2635 Assembler *Asm = Func->getAssembler<Assembler>(); 2694 Asm->pushl(Traits::getEncodedGPR(Var->getRegNum()));
2636 Asm->pushl(Traits::getEncodedGPR(Var->getRegNum())); 2695 } else if (const auto *Const32 = llvm::dyn_cast<ConstantInteger32>(Src)) {
2696 Asm->pushl(AssemblerImmediate(Const32->getValue()));
2697 } else if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src)) {
2698 Asm->pushl(CR);
2699 } else {
2700 llvm_unreachable("Unexpected operand type");
2701 }
2637 } 2702 }
2638 2703
2639 template <typename TraitsType> 2704 template <typename TraitsType>
2640 void InstImpl<TraitsType>::InstX86Push::dump(const Cfg *Func) const { 2705 void InstImpl<TraitsType>::InstX86Push::dump(const Cfg *Func) const {
2641 if (!BuildDefs::dump()) 2706 if (!BuildDefs::dump())
2642 return; 2707 return;
2643 Ostream &Str = Func->getContext()->getStrDump(); 2708 Ostream &Str = Func->getContext()->getStrDump();
2644 Str << "push." << this->getSrc(0)->getType() << " "; 2709 Str << "push." << this->getSrc(0)->getType() << " ";
2645 this->dumpSources(Func); 2710 this->dumpSources(Func);
2646 } 2711 }
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
2844 return; 2909 return;
2845 Ostream &Str = Func->getContext()->getStrDump(); 2910 Ostream &Str = Func->getContext()->getStrDump();
2846 Str << "IACA_END"; 2911 Str << "IACA_END";
2847 } 2912 }
2848 2913
2849 } // end of namespace X86NAMESPACE 2914 } // end of namespace X86NAMESPACE
2850 2915
2851 } // end of namespace Ice 2916 } // end of namespace Ice
2852 2917
2853 #endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H 2918 #endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H
OLDNEW
« no previous file with comments | « src/IceInstX86Base.h ('k') | src/IceRegistersX8664.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698