Chromium Code Reviews| Index: lib/Target/ARM/MCTargetDesc/ARMMCNaClExpander.cpp | 
| diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCNaClExpander.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCNaClExpander.cpp | 
| index 060609f371f6635cf1456f93a6526124249295cb..c44937fc142f68b23f1b31eea2ca1a7ab550e9cf 100644 | 
| --- a/lib/Target/ARM/MCTargetDesc/ARMMCNaClExpander.cpp | 
| +++ b/lib/Target/ARM/MCTargetDesc/ARMMCNaClExpander.cpp | 
| @@ -12,6 +12,8 @@ | 
| // | 
| //===----------------------------------------------------------------------===// | 
| #include "ARMMCNaClExpander.h" | 
| +#include "ARMAddressingModes.h" | 
| +#include "MCTargetDesc/ARMBaseInfo.h" | 
| #include "llvm/MC/MCInst.h" | 
| #include "llvm/MC/MCInstrDesc.h" | 
| @@ -23,9 +25,98 @@ | 
| using namespace llvm; | 
| +const unsigned kBranchTargetMask = 0xC000000F; | 
| +const unsigned kAlwaysPredicate = 14; | 
| + | 
| +static void emitBicMask(unsigned Mask, unsigned Reg, int64_t Pred, | 
| + MCStreamer &Out, const MCSubtargetInfo &STI) { | 
| + MCInst Bic; | 
| + const int32_t EncodedMask = ARM_AM::getSOImmVal(Mask); | 
| + Bic.setOpcode(ARM::BICri); | 
| + Bic.addOperand(MCOperand::CreateReg(Reg)); | 
| + Bic.addOperand(MCOperand::CreateReg(Reg)); | 
| + Bic.addOperand(MCOperand::CreateImm(EncodedMask)); | 
| + Bic.addOperand(MCOperand::CreateImm(Pred)); | 
| + Bic.addOperand(MCOperand::CreateReg(ARM::CPSR)); | 
| + Bic.addOperand(MCOperand::CreateReg(0)); | 
| + Out.EmitInstruction(Bic, STI); | 
| +} | 
| + | 
| +void ARM::ARMMCNaClExpander::expandIndirectBranch(const MCInst &Inst, | 
| + MCStreamer &Out, | 
| + const MCSubtargetInfo &STI, | 
| + bool isCall) { | 
| + assert(Inst.getOperand(0).isReg()); | 
| + // No need to sandbox branch through pc | 
| + if (Inst.getOperand(0).getReg() == ARM::PC || | 
| + Inst.getOperand(0).getReg() == ARM::SP) | 
| + return Out.EmitInstruction(Inst, STI); | 
| + | 
| + // Otherwise, mask target and branch through | 
| + Out.EmitBundleLock(isCall); | 
| + | 
| + unsigned Reg = Inst.getOperand(0).getReg(); | 
| + int64_t Pred = Inst.getNumOperands() > 1 ? Inst.getOperand(1).getImm() | 
| + : kAlwaysPredicate; | 
| + emitBicMask(kBranchTargetMask, Reg, Pred, Out, STI); | 
| + | 
| + Out.EmitInstruction(Inst, STI); | 
| + | 
| + Out.EmitBundleUnlock(); | 
| +} | 
| + | 
| +void ARM::ARMMCNaClExpander::expandCall(const MCInst &Inst, MCStreamer &Out, | 
| + const MCSubtargetInfo &STI) { | 
| + // Test for indirect call | 
| + if (Inst.getOperand(0).isReg()) { | 
| + expandIndirectBranch(Inst, Out, STI, true); | 
| + } | 
| + | 
| + // Otherwise, we are a direct call, so just emit | 
| + else { | 
| + Out.EmitInstruction(Inst, STI); | 
| + } | 
| +} | 
| + | 
| void ARM::ARMMCNaClExpander::doExpandInst(const MCInst &Inst, MCStreamer &Out, | 
| const MCSubtargetInfo &STI) { | 
| - Out.EmitInstruction(Inst, STI); | 
| + if (SaveCount == 0) { | 
| + switch (Inst.getOpcode()) { | 
| + case ARM::SFI_NOP_IF_AT_BUNDLE_END: | 
| 
 
Derek Schuff
2015/08/05 06:11:44
It looks like this is the logic necessary to keep
 
 | 
| + SaveCount = 3; | 
| + break; | 
| + case ARM::SFI_DATA_MASK: | 
| + llvm_unreachable( | 
| + "SFI_DATA_MASK found without preceding SFI_NOP_IF_AT_BUNDLE_END"); | 
| + break; | 
| + case ARM::SFI_GUARD_CALL: | 
| + case ARM::SFI_GUARD_INDIRECT_CALL: | 
| + case ARM::SFI_GUARD_INDIRECT_JMP: | 
| + case ARM::SFI_GUARD_RETURN: | 
| + case ARM::SFI_GUARD_LOADSTORE: | 
| + case ARM::SFI_GUARD_LOADSTORE_TST: | 
| + SaveCount = 2; | 
| + break; | 
| + case ARM::SFI_GUARD_SP_LOAD: | 
| + SaveCount = 4; | 
| + break; | 
| + default: | 
| + break; | 
| + } | 
| + } | 
| + | 
| + if (SaveCount == 0) { | 
| + if (isIndirectBranch(Inst)) { | 
| + return expandIndirectBranch(Inst, Out, STI, false); | 
| + } else if (isCall(Inst)) { | 
| + return expandCall(Inst, Out, STI); | 
| + } else { | 
| + return Out.EmitInstruction(Inst, STI); | 
| + } | 
| + } else { | 
| + SaveCount--; | 
| + Out.EmitInstruction(Inst, STI); | 
| + } | 
| } | 
| bool ARM::ARMMCNaClExpander::expandInst(const MCInst &Inst, MCStreamer &Out, |