Chromium Code Reviews| Index: src/IceInstX8632.cpp |
| diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp |
| index e41fe8227684ca626a5d87d74f596864e81c18d1..dbacd58a87bdcb65a911de3849a96ea7c20692c6 100644 |
| --- a/src/IceInstX8632.cpp |
| +++ b/src/IceInstX8632.cpp |
| @@ -447,6 +447,52 @@ void InstX8632Call::emit(const Cfg *Func) const { |
| Func->getTarget()->resetStackAdjustment(); |
| } |
| +void InstX8632Call::emitIAS(const Cfg *Func) const { |
| + x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| + intptr_t StartPosition = Asm->GetPosition(); |
| + Operand *Target = getCallTarget(); |
| + bool NeedsFallback = false; |
| + if (const auto Var = llvm::dyn_cast<Variable>(Target)) { |
| + if (Var->hasReg()) { |
| + Asm->call(RegX8632::getEncodedGPR(Var->getRegNum())); |
| + } else { |
| + Asm->call(static_cast<TargetX8632 *>(Func->getTarget()) |
| + ->stackVarToAsmOperand(Var)); |
| + } |
| + } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Target)) { |
| + assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| + Asm->call(Mem->toAsmAddress(Asm)); |
| + } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) { |
| + assert(CR->getOffset() == 0 && "We only support calling a function"); |
|
Jim Stichnoth
2014/10/16 02:48:16
llvm_unreachable here too?
jvoung (off chromium)
2014/10/16 15:22:11
Oh, this one is actually reachable. I let it go th
|
| + Asm->call(CR); |
| + NeedsFallback = true; |
| + } 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_unreachable("Unexpected call to absolute address"); |
| + } else { |
| + llvm_unreachable("Unexpected operand type"); |
| + } |
| + if (NeedsFallback) { |
| + // TODO(jvoung): The ".long sym" hack doesn't work, since we need |
| + // a pc-rel relocation and not an absolute relocation. |
| + // |
| + // Still, we have at least filled the assembler buffer so that the |
| + // instruction sizes/positions are correct for jumps. |
| + // For now, fall back to the regular .s emission, after filling the buffer. |
| + emit(Func); |
| + } else { |
| + emitIASBytes(Func, Asm, StartPosition); |
| + } |
| + Func->getTarget()->resetStackAdjustment(); |
| +} |
| + |
| void InstX8632Call::dump(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrDump(); |
| if (getDest()) { |
| @@ -539,8 +585,7 @@ void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Var, |
| x86::DisplacementRelocation::create(Asm, FK_Abs_4, Reloc); |
| (Asm->*(Emitter.GPRImm))(Ty, VarReg, x86::Immediate(Fixup)); |
| } else if (const auto Split = llvm::dyn_cast<VariableSplit>(Src)) { |
| - x86::Address SrcAddr = Split->toAsmAddress(Func); |
| - (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcAddr); |
| + (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func)); |
| } else { |
| llvm_unreachable("Unexpected operand type"); |
| } |
| @@ -570,6 +615,25 @@ void emitIASAddrOpTyGPR(const Cfg *Func, Type Ty, const x86::Address &Addr, |
| emitIASBytes(Func, Asm, StartPosition); |
| } |
| +void emitIASAsAddrOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op0, |
| + const Operand *Op1, |
| + const x86::AssemblerX86::GPREmitterAddrOp &Emitter) { |
| + if (const auto Op0Var = llvm::dyn_cast<Variable>(Op0)) { |
| + assert(!Op0Var->hasReg()); |
| + x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) |
| + ->stackVarToAsmOperand(Op0Var)); |
| + emitIASAddrOpTyGPR(Func, Ty, StackAddr, Op1, Emitter); |
| + } else if (const auto Op0Mem = llvm::dyn_cast<OperandX8632Mem>(Op0)) { |
| + x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| + Op0Mem->emitSegmentOverride(Asm); |
| + emitIASAddrOpTyGPR(Func, Ty, Op0Mem->toAsmAddress(Asm), Op1, Emitter); |
| + } else if (const auto Split = llvm::dyn_cast<VariableSplit>(Op0)) { |
| + emitIASAddrOpTyGPR(Func, Ty, Split->toAsmAddress(Func), Op1, Emitter); |
| + } else { |
| + llvm_unreachable("Unexpected operand type"); |
| + } |
| +} |
| + |
| void emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var, |
| const Operand *Src, |
| const x86::AssemblerX86::GPREmitterShiftOp &Emitter) { |
| @@ -1662,20 +1726,13 @@ void InstX8632Icmp::emitIAS(const Cfg *Func) const { |
| static const x86::AssemblerX86::GPREmitterAddrOp AddrEmitter = { |
| &x86::AssemblerX86::cmp, &x86::AssemblerX86::cmp |
| }; |
| - if (const Variable *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) { |
| + if (const auto SrcVar0 = llvm::dyn_cast<Variable>(Src0)) { |
| if (SrcVar0->hasReg()) { |
| emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter); |
| - } else { |
| - x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) |
| - ->stackVarToAsmOperand(SrcVar0)); |
| - emitIASAddrOpTyGPR(Func, Ty, StackAddr, Src1, AddrEmitter); |
| + return; |
| } |
| - } else if (const OperandX8632Mem *SrcMem0 = |
| - llvm::dyn_cast<OperandX8632Mem>(Src0)) { |
| - x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| - SrcMem0->emitSegmentOverride(Asm); |
| - emitIASAddrOpTyGPR(Func, Ty, SrcMem0->toAsmAddress(Asm), Src1, AddrEmitter); |
| } |
| + emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter); |
| } |
| void InstX8632Icmp::dump(const Cfg *Func) const { |
| @@ -1754,22 +1811,14 @@ void InstX8632Test::emitIAS(const Cfg *Func) const { |
| static const x86::AssemblerX86::GPREmitterAddrOp AddrEmitter = { |
| &x86::AssemblerX86::test, &x86::AssemblerX86::test |
| }; |
| - if (const Variable *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) { |
| + if (const auto SrcVar0 = llvm::dyn_cast<Variable>(Src0)) { |
| if (SrcVar0->hasReg()) { |
| emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter); |
| - } else { |
| - llvm_unreachable("Nothing actually generates this so it's untested"); |
| - x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) |
| - ->stackVarToAsmOperand(SrcVar0)); |
| - emitIASAddrOpTyGPR(Func, Ty, StackAddr, Src1, AddrEmitter); |
| + return; |
| } |
| - } else if (const OperandX8632Mem *SrcMem0 = |
| - llvm::dyn_cast<OperandX8632Mem>(Src0)) { |
| - llvm_unreachable("Nothing actually generates this so it's untested"); |
| - x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| - SrcMem0->emitSegmentOverride(Asm); |
| - emitIASAddrOpTyGPR(Func, Ty, SrcMem0->toAsmAddress(Asm), Src1, AddrEmitter); |
| } |
| + llvm_unreachable("Nothing actually generates this so it's untested"); |
| + emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter); |
| } |
| void InstX8632Test::dump(const Cfg *Func) const { |
| @@ -1807,6 +1856,38 @@ void InstX8632Store::emit(const Cfg *Func) const { |
| Str << "\n"; |
| } |
| +void InstX8632Store::emitIAS(const Cfg *Func) const { |
| + assert(getSrcSize() == 2); |
| + const Operand *Dest = getSrc(1); |
| + const Operand *Src = getSrc(0); |
| + Type DestTy = Dest->getType(); |
| + if (isScalarFloatingType(DestTy)) { |
| + // Src must be a register, since Dest is a Mem operand of some kind. |
| + const Variable *SrcVar = llvm::cast<Variable>(Src); |
| + assert(SrcVar->hasReg()); |
| + RegX8632::XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum()); |
| + x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| + intptr_t StartPosition = Asm->GetPosition(); |
| + if (const auto DestVar = llvm::dyn_cast<Variable>(Dest)) { |
| + assert(!DestVar->hasReg()); |
| + x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) |
| + ->stackVarToAsmOperand(DestVar)); |
| + Asm->movss(DestTy, StackAddr, SrcReg); |
| + } else { |
| + const auto DestMem = llvm::cast<OperandX8632Mem>(Dest); |
| + assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| + Asm->movss(DestTy, DestMem->toAsmAddress(Asm), SrcReg); |
| + } |
| + emitIASBytes(Func, Asm, StartPosition); |
| + return; |
| + } else { |
| + assert(isScalarIntegerType(DestTy)); |
| + static const x86::AssemblerX86::GPREmitterAddrOp GPRAddrEmitter = { |
| + &x86::AssemblerX86::mov, &x86::AssemblerX86::mov}; |
| + emitIASAsAddrOpTyGPR(Func, DestTy, Dest, Src, GPRAddrEmitter); |
| + } |
| +} |
| + |
| void InstX8632Store::dump(const Cfg *Func) const { |
| Ostream &Str = Func->getContext()->getStrDump(); |
| Str << "mov." << getSrc(0)->getType() << " "; |