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, |