| Index: src/IceInstX8632.cpp
|
| diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp
|
| index 30edb9ee9b1b252853583b162f253b4456349a2d..330683711102aefb5c1b77adf5c56b51574d9d67 100644
|
| --- a/src/IceInstX8632.cpp
|
| +++ b/src/IceInstX8632.cpp
|
| @@ -200,6 +200,11 @@ bool InstX8632Br::repointEdge(CfgNode *OldNode, CfgNode *NewNode) {
|
| return false;
|
| }
|
|
|
| +InstX8632Jmp::InstX8632Jmp(Cfg *Func, Operand *Target)
|
| + : InstX8632(Func, InstX8632::Jmp, 1, nullptr) {
|
| + addSource(Target);
|
| +}
|
| +
|
| InstX8632Call::InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
|
| : InstX8632(Func, InstX8632::Call, 1, Dest) {
|
| HasSideEffects = true;
|
| @@ -450,6 +455,59 @@ void InstX8632Br::dump(const Cfg *Func) const {
|
| }
|
| }
|
|
|
| +void InstX8632Jmp::emit(const Cfg *Func) const {
|
| + if (!ALLOW_DUMP)
|
| + return;
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + assert(getSrcSize() == 1);
|
| + Str << "\tjmp\t*";
|
| + getSrc(0)->emit(Func);
|
| +}
|
| +
|
| +void InstX8632Jmp::emitIAS(const Cfg *Func) const {
|
| + // Note: Adapted (mostly copied) from InstX8632Call::emitIAS().
|
| + x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
|
| + Operand *Target = getSrc(0);
|
| + if (const auto Var = llvm::dyn_cast<Variable>(Target)) {
|
| + if (Var->hasReg()) {
|
| + Asm->jmp(RegX8632::getEncodedGPR(Var->getRegNum()));
|
| + } else {
|
| + // The jmp instruction with a memory operand should be possible
|
| + // to encode, but it isn't a valid sandboxed instruction, and
|
| + // there shouldn't be a register allocation issue to jump
|
| + // through a scratch register, so we don't really need to bother
|
| + // implementing it.
|
| + llvm::report_fatal_error("Assembler can't jmp to memory operand");
|
| + }
|
| + } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Target)) {
|
| + assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
|
| + llvm::report_fatal_error("Assembler can't jmp to memory operand");
|
| + } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) {
|
| + assert(CR->getOffset() == 0 && "We only support jumping to a function");
|
| + Asm->jmp(CR);
|
| + } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) {
|
| + // NaCl trampoline calls refer to an address within the sandbox directly.
|
| + // This is usually only needed for non-IRT builds and otherwise not
|
| + // very portable or stable. For this, we would use the 0xE8 opcode
|
| + // (relative version of call) and there should be a PC32 reloc too.
|
| + // The PC32 reloc will have symbol index 0, and the absolute address
|
| + // would be encoded as an offset relative to the next instruction.
|
| + // TODO(jvoung): Do we need to support this?
|
| + (void)Imm;
|
| + llvm::report_fatal_error("Unexpected jmp to absolute address");
|
| + } else {
|
| + llvm::report_fatal_error("Unexpected operand type");
|
| + }
|
| +}
|
| +
|
| +void InstX8632Jmp::dump(const Cfg *Func) const {
|
| + if (!ALLOW_DUMP)
|
| + return;
|
| + Ostream &Str = Func->getContext()->getStrDump();
|
| + Str << "jmp ";
|
| + getSrc(0)->dump(Func);
|
| +}
|
| +
|
| void InstX8632Call::emit(const Cfg *Func) const {
|
| if (!ALLOW_DUMP)
|
| return;
|
|
|