| OLD | NEW |
| 1 //===- subzero/src/IceInstX8632.cpp - X86-32 instruction implementation ---===// | 1 //===- subzero/src/IceInstX8632.cpp - X86-32 instruction implementation ---===// |
| 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 // This file implements the InstX8632 and OperandX8632 classes, | 10 // This file implements the InstX8632 and OperandX8632 classes, |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 if (TargetFalse == OldNode) { | 193 if (TargetFalse == OldNode) { |
| 194 TargetFalse = NewNode; | 194 TargetFalse = NewNode; |
| 195 return true; | 195 return true; |
| 196 } else if (TargetTrue == OldNode) { | 196 } else if (TargetTrue == OldNode) { |
| 197 TargetTrue = NewNode; | 197 TargetTrue = NewNode; |
| 198 return true; | 198 return true; |
| 199 } | 199 } |
| 200 return false; | 200 return false; |
| 201 } | 201 } |
| 202 | 202 |
| 203 InstX8632Jmp::InstX8632Jmp(Cfg *Func, Operand *Target) |
| 204 : InstX8632(Func, InstX8632::Jmp, 1, nullptr) { |
| 205 addSource(Target); |
| 206 } |
| 207 |
| 203 InstX8632Call::InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget) | 208 InstX8632Call::InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget) |
| 204 : InstX8632(Func, InstX8632::Call, 1, Dest) { | 209 : InstX8632(Func, InstX8632::Call, 1, Dest) { |
| 205 HasSideEffects = true; | 210 HasSideEffects = true; |
| 206 addSource(CallTarget); | 211 addSource(CallTarget); |
| 207 } | 212 } |
| 208 | 213 |
| 209 InstX8632Cmov::InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source, | 214 InstX8632Cmov::InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source, |
| 210 CondX86::BrCond Condition) | 215 CondX86::BrCond Condition) |
| 211 : InstX8632(Func, InstX8632::Cmov, 2, Dest), Condition(Condition) { | 216 : InstX8632(Func, InstX8632::Cmov, 2, Dest), Condition(Condition) { |
| 212 // The final result is either the original Dest, or Source, so mark | 217 // The final result is either the original Dest, or Source, so mark |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 if (Label) { | 448 if (Label) { |
| 444 Str << ", label %" << Label->getName(Func); | 449 Str << ", label %" << Label->getName(Func); |
| 445 } else { | 450 } else { |
| 446 Str << ", label %" << getTargetTrue()->getName(); | 451 Str << ", label %" << getTargetTrue()->getName(); |
| 447 if (getTargetFalse()) { | 452 if (getTargetFalse()) { |
| 448 Str << ", label %" << getTargetFalse()->getName(); | 453 Str << ", label %" << getTargetFalse()->getName(); |
| 449 } | 454 } |
| 450 } | 455 } |
| 451 } | 456 } |
| 452 | 457 |
| 458 void InstX8632Jmp::emit(const Cfg *Func) const { |
| 459 if (!ALLOW_DUMP) |
| 460 return; |
| 461 Ostream &Str = Func->getContext()->getStrEmit(); |
| 462 assert(getSrcSize() == 1); |
| 463 Str << "\tjmp\t*"; |
| 464 getJmpTarget()->emit(Func); |
| 465 } |
| 466 |
| 467 void InstX8632Jmp::emitIAS(const Cfg *Func) const { |
| 468 // Note: Adapted (mostly copied) from InstX8632Call::emitIAS(). |
| 469 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 470 Operand *Target = getJmpTarget(); |
| 471 if (const auto Var = llvm::dyn_cast<Variable>(Target)) { |
| 472 if (Var->hasReg()) { |
| 473 Asm->jmp(RegX8632::getEncodedGPR(Var->getRegNum())); |
| 474 } else { |
| 475 // The jmp instruction with a memory operand should be possible |
| 476 // to encode, but it isn't a valid sandboxed instruction, and |
| 477 // there shouldn't be a register allocation issue to jump |
| 478 // through a scratch register, so we don't really need to bother |
| 479 // implementing it. |
| 480 llvm::report_fatal_error("Assembler can't jmp to memory operand"); |
| 481 } |
| 482 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Target)) { |
| 483 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 484 llvm::report_fatal_error("Assembler can't jmp to memory operand"); |
| 485 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) { |
| 486 assert(CR->getOffset() == 0 && "We only support jumping to a function"); |
| 487 Asm->jmp(CR); |
| 488 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) { |
| 489 // NaCl trampoline calls refer to an address within the sandbox directly. |
| 490 // This is usually only needed for non-IRT builds and otherwise not |
| 491 // very portable or stable. For this, we would use the 0xE8 opcode |
| 492 // (relative version of call) and there should be a PC32 reloc too. |
| 493 // The PC32 reloc will have symbol index 0, and the absolute address |
| 494 // would be encoded as an offset relative to the next instruction. |
| 495 // TODO(jvoung): Do we need to support this? |
| 496 (void)Imm; |
| 497 llvm::report_fatal_error("Unexpected jmp to absolute address"); |
| 498 } else { |
| 499 llvm::report_fatal_error("Unexpected operand type"); |
| 500 } |
| 501 } |
| 502 |
| 503 void InstX8632Jmp::dump(const Cfg *Func) const { |
| 504 if (!ALLOW_DUMP) |
| 505 return; |
| 506 Ostream &Str = Func->getContext()->getStrDump(); |
| 507 Str << "jmp "; |
| 508 getJmpTarget()->dump(Func); |
| 509 } |
| 510 |
| 453 void InstX8632Call::emit(const Cfg *Func) const { | 511 void InstX8632Call::emit(const Cfg *Func) const { |
| 454 if (!ALLOW_DUMP) | 512 if (!ALLOW_DUMP) |
| 455 return; | 513 return; |
| 456 Ostream &Str = Func->getContext()->getStrEmit(); | 514 Ostream &Str = Func->getContext()->getStrEmit(); |
| 457 assert(getSrcSize() == 1); | 515 assert(getSrcSize() == 1); |
| 458 Str << "\tcall\t"; | 516 Str << "\tcall\t"; |
| 459 if (const auto CallTarget = | 517 if (const auto CallTarget = |
| 460 llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) { | 518 llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) { |
| 461 // TODO(stichnot): All constant targets should suppress the '$', | 519 // TODO(stichnot): All constant targets should suppress the '$', |
| 462 // not just relocatables. | 520 // not just relocatables. |
| (...skipping 2259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2722 Str << "xchg." << Ty << " "; | 2780 Str << "xchg." << Ty << " "; |
| 2723 dumpSources(Func); | 2781 dumpSources(Func); |
| 2724 } | 2782 } |
| 2725 | 2783 |
| 2726 void OperandX8632Mem::emit(const Cfg *Func) const { | 2784 void OperandX8632Mem::emit(const Cfg *Func) const { |
| 2727 if (!ALLOW_DUMP) | 2785 if (!ALLOW_DUMP) |
| 2728 return; | 2786 return; |
| 2729 Ostream &Str = Func->getContext()->getStrEmit(); | 2787 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2730 if (SegmentReg != DefaultSegment) { | 2788 if (SegmentReg != DefaultSegment) { |
| 2731 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); | 2789 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); |
| 2732 Str << InstX8632SegmentRegNames[SegmentReg] << ":"; | 2790 Str << "%" << InstX8632SegmentRegNames[SegmentReg] << ":"; |
| 2733 } | 2791 } |
| 2734 // Emit as Offset(Base,Index,1<<Shift). | 2792 // Emit as Offset(Base,Index,1<<Shift). |
| 2735 // Offset is emitted without the leading '$'. | 2793 // Offset is emitted without the leading '$'. |
| 2736 // Omit the (Base,Index,1<<Shift) part if Base==nullptr. | 2794 // Omit the (Base,Index,1<<Shift) part if Base==nullptr. |
| 2737 if (!Offset) { | 2795 if (!Offset) { |
| 2738 // No offset, emit nothing. | 2796 // No offset, emit nothing. |
| 2739 } else if (const auto CI = llvm::dyn_cast<ConstantInteger32>(Offset)) { | 2797 } else if (const auto CI = llvm::dyn_cast<ConstantInteger32>(Offset)) { |
| 2740 if (CI->getValue()) | 2798 if (Base == nullptr || CI->getValue()) |
| 2741 // Emit a non-zero offset without a leading '$'. | 2799 // Emit a non-zero offset without a leading '$'. |
| 2742 Str << CI->getValue(); | 2800 Str << CI->getValue(); |
| 2743 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) { | 2801 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) { |
| 2744 CR->emitWithoutDollar(Func->getContext()); | 2802 CR->emitWithoutDollar(Func->getContext()); |
| 2745 } else { | 2803 } else { |
| 2746 llvm_unreachable("Invalid offset type for x86 mem operand"); | 2804 llvm_unreachable("Invalid offset type for x86 mem operand"); |
| 2747 } | 2805 } |
| 2748 | 2806 |
| 2749 if (Base) { | 2807 if (Base) { |
| 2750 Str << "("; | 2808 Str << "("; |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2887 } | 2945 } |
| 2888 Str << "("; | 2946 Str << "("; |
| 2889 if (Func) | 2947 if (Func) |
| 2890 Var->dump(Func); | 2948 Var->dump(Func); |
| 2891 else | 2949 else |
| 2892 Var->dump(Str); | 2950 Var->dump(Str); |
| 2893 Str << ")"; | 2951 Str << ")"; |
| 2894 } | 2952 } |
| 2895 | 2953 |
| 2896 } // end of namespace Ice | 2954 } // end of namespace Ice |
| OLD | NEW |