<commit_before>//===-- X86FixupLEAs.cpp - use or replace LEA instructions -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the pass which will find  instructions  which
// can be re-written as LEA instructions in order to reduce pipeline
// delays for some models of the Intel Atom family.
//
//===----------------------------------------------------------------------===//

#include "X86.h"
#include "X86InstrInfo.h"
#include "X86Subtarget.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetInstrInfo.h"
using namespace llvm;

#define DEBUG_TYPE "x86-fixup-LEAs"

STATISTIC(NumLEAs, "Number of LEA instructions created");

namespace {
  class FixupLEAPass : public MachineFunctionPass {
    enum RegUsageState { RU_NotUsed, RU_Write, RU_Read };
    static char ID;
    /// \brief Loop over all of the instructions in the basic block
    /// replacing applicable instructions with LEA instructions,
    /// where appropriate.
    bool processBasicBlock(MachineFunction &MF, MachineFunction::iterator MFI);

    const char *getPassName() const override { return "X86 Atom LEA Fixup";}

    /// \brief Given a machine register, look for the instruction
    /// which writes it in the current basic block. If found,
    /// try to replace it with an equivalent LEA instruction.
    /// If replacement succeeds, then also process the the newly created
    /// instruction.
    void  seekLEAFixup(MachineOperand& p, MachineBasicBlock::iterator& I,
                      MachineFunction::iterator MFI);

    /// \brief Given a memory access or LEA instruction
    /// whose address mode uses a base and/or index register, look for
    /// an opportunity to replace the instruction which sets the base or index
    /// register with an equivalent LEA instruction.
    void processInstruction(MachineBasicBlock::iterator& I,
                            MachineFunction::iterator MFI);

    /// \brief Given a LEA instruction which is unprofitable
    /// on Silvermont try to replace it with an equivalent ADD instruction
    void processInstructionForSLM(MachineBasicBlock::iterator& I,
                                  MachineFunction::iterator MFI);

    /// \brief Determine if an instruction references a machine register
    /// and, if so, whether it reads or writes the register.
    RegUsageState usesRegister(MachineOperand& p,
                               MachineBasicBlock::iterator I);

    /// \brief Step backwards through a basic block, looking
    /// for an instruction which writes a register within
    /// a maximum of INSTR_DISTANCE_THRESHOLD instruction latency cycles.
    MachineBasicBlock::iterator searchBackwards(MachineOperand& p,
                                                MachineBasicBlock::iterator& I,
                                                MachineFunction::iterator MFI);

    /// \brief if an instruction can be converted to an
    /// equivalent LEA, insert the new instruction into the basic block
    /// and return a pointer to it. Otherwise, return zero.
    MachineInstr* postRAConvertToLEA(MachineFunction::iterator &MFI,
                                     MachineBasicBlock::iterator &MBBI) const;

  public:
    FixupLEAPass() : MachineFunctionPass(ID) {}

    /// \brief Loop over all of the basic blocks,
    /// replacing instructions by equivalent LEA instructions
    /// if needed and when possible.
    bool runOnMachineFunction(MachineFunction &MF) override;

  private:
    MachineFunction *MF;
    const TargetMachine *TM;
    const X86InstrInfo *TII; // Machine instruction info.

  };
  char FixupLEAPass::ID = 0;
}

MachineInstr *
FixupLEAPass::postRAConvertToLEA(MachineFunction::iterator &MFI,
                                 MachineBasicBlock::iterator &MBBI) const {
  MachineInstr* MI = MBBI;
  MachineInstr* NewMI;
  switch (MI->getOpcode()) {
  case X86::MOV32rr:
  case X86::MOV64rr: {
    const MachineOperand& Src = MI->getOperand(1);
    const MachineOperand& Dest = MI->getOperand(0);
    NewMI = BuildMI(*MF, MI->getDebugLoc(),
      TII->get( MI->getOpcode() == X86::MOV32rr ? X86::LEA32r : X86::LEA64r))
      .addOperand(Dest)
      .addOperand(Src).addImm(1).addReg(0).addImm(0).addReg(0);
    MFI->insert(MBBI, NewMI);   // Insert the new inst
    return NewMI;
  }
  case X86::ADD64ri32:
  case X86::ADD64ri8:
  case X86::ADD64ri32_DB:
  case X86::ADD64ri8_DB:
  case X86::ADD32ri:
  case X86::ADD32ri8:
  case X86::ADD32ri_DB:
  case X86::ADD32ri8_DB:
  case X86::ADD16ri:
  case X86::ADD16ri8:
  case X86::ADD16ri_DB:
  case X86::ADD16ri8_DB:
    if (!MI->getOperand(2).isImm()) {
      // convertToThreeAddress will call getImm()
      // which requires isImm() to be true
      return nullptr;
    }
    break;
  case X86::ADD16rr:
  case X86::ADD16rr_DB:
    if (MI->getOperand(1).getReg() != MI->getOperand(2).getReg()) {
      // if src1 != src2, then convertToThreeAddress will
      // need to create a Virtual register, which we cannot do
      // after register allocation.
      return nullptr;
    }
  }
  return TII->convertToThreeAddress(MFI, MBBI, nullptr);
}

FunctionPass *llvm::createX86FixupLEAs() {
  return new FixupLEAPass();
}

bool FixupLEAPass::runOnMachineFunction(MachineFunction &Func) {
  TM = &Func.getTarget();
  const X86Subtarget &ST = TM->getSubtarget<X86Subtarget>();
  if (!ST.LEAusesAG() && !ST.slowLEA())
    return false;

  TII = static_cast<const X86InstrInfo*>(TM->getInstrInfo());

  DEBUG(dbgs() << "Start X86FixupLEAs\n";);
  // Process all basic blocks.
  for (MachineFunction::iterator I = Func.begin(), E = Func.end(); I != E; ++I)
    processBasicBlock(Func, I);
  DEBUG(dbgs() << "End X86FixupLEAs\n";);

  return true;
}

FixupLEAPass::RegUsageState FixupLEAPass::usesRegister(MachineOperand& p,
                                MachineBasicBlock::iterator I) {
  RegUsageState RegUsage = RU_NotUsed;
  MachineInstr* MI = I;

  for (unsigned int i = 0; i < MI->getNumOperands(); ++i) {
    MachineOperand& opnd = MI->getOperand(i);
    if (opnd.isReg() && opnd.getReg() == p.getReg()){
      if (opnd.isDef())
        return RU_Write;
      RegUsage = RU_Read;
    }
  }
  return RegUsage;
}

/// getPreviousInstr - Given a reference to an instruction in a basic
/// block, return a reference to the previous instruction in the block,
/// wrapping around to the last instruction of the block if the block
/// branches to itself.
static inline bool getPreviousInstr(MachineBasicBlock::iterator& I,
                                    MachineFunction::iterator MFI) {
  if (I == MFI->begin()) {
    if (MFI->isPredecessor(MFI)) {
      I = --MFI->end();
      return true;
    }
    else
      return false;
  }
  --I;
  return true;
}

MachineBasicBlock::iterator FixupLEAPass::searchBackwards(MachineOperand& p,
                                   MachineBasicBlock::iterator& I,
                                   MachineFunction::iterator MFI) {
  int InstrDistance = 1;
  MachineBasicBlock::iterator CurInst;
  static const int INSTR_DISTANCE_THRESHOLD = 5;

  CurInst = I;
  bool Found;
  Found = getPreviousInstr(CurInst, MFI);
  while( Found && I != CurInst) {
    if (CurInst->isCall() || CurInst->isInlineAsm())
      break;
    if (InstrDistance > INSTR_DISTANCE_THRESHOLD)
      break; // too far back to make a difference
    if (usesRegister(p, CurInst) == RU_Write){
      return CurInst;
    }
    InstrDistance += TII->getInstrLatency(TM->getInstrItineraryData(), CurInst);
    Found = getPreviousInstr(CurInst, MFI);
  }
  return nullptr;
}

void FixupLEAPass::processInstruction(MachineBasicBlock::iterator& I,
                                      MachineFunction::iterator MFI) {
  // Process a load, store, or LEA instruction.
  MachineInstr *MI = I;
  int opcode = MI->getOpcode();
  const MCInstrDesc& Desc = MI->getDesc();
  int AddrOffset = X86II::getMemoryOperandNo(Desc.TSFlags, opcode);
  if (AddrOffset >= 0) {
    AddrOffset += X86II::getOperandBias(Desc);
    MachineOperand& p = MI->getOperand(AddrOffset + X86::AddrBaseReg);
    if (p.isReg() && p.getReg() != X86::ESP) {
      seekLEAFixup(p, I, MFI);
    }
    MachineOperand& q = MI->getOperand(AddrOffset + X86::AddrIndexReg);
    if (q.isReg() && q.getReg() != X86::ESP) {
      seekLEAFixup(q, I, MFI);
    }
  }
}

void FixupLEAPass::seekLEAFixup(MachineOperand& p,
                                MachineBasicBlock::iterator& I,
                                MachineFunction::iterator MFI) {
  MachineBasicBlock::iterator MBI = searchBackwards(p, I, MFI);
  if (MBI) {
    MachineInstr* NewMI = postRAConvertToLEA(MFI, MBI);
    if (NewMI) {
      ++NumLEAs;
      DEBUG(dbgs() << "FixLEA: Candidate to replace:"; MBI->dump(););
      // now to replace with an equivalent LEA...
      DEBUG(dbgs() << "FixLEA: Replaced by: "; NewMI->dump(););
      MFI->erase(MBI);
      MachineBasicBlock::iterator J =
                             static_cast<MachineBasicBlock::iterator> (NewMI);
      processInstruction(J, MFI);
    }
  }
}

void FixupLEAPass::processInstructionForSLM(MachineBasicBlock::iterator &I,
                                            MachineFunction::iterator MFI) {
  MachineInstr *MI = I;
  const int opcode = MI->getOpcode();
  if (opcode != X86::LEA16r && opcode != X86::LEA32r && opcode != X86::LEA64r &&
      opcode != X86::LEA64_32r)
    return;
  if (MI->getOperand(5).getReg() != 0 || !MI->getOperand(4).isImm() ||
      !TII->isSafeToClobberEFLAGS(*MFI, I))
    return;
  const unsigned DstR = MI->getOperand(0).getReg();
  const unsigned SrcR1 = MI->getOperand(1).getReg();
  const unsigned SrcR2 = MI->getOperand(3).getReg();
  if ((SrcR1 == 0 || SrcR1 != DstR) && (SrcR2 == 0 || SrcR2 != DstR))
    return;
  if (MI->getOperand(2).getImm() > 1)
    return;
  int addrr_opcode, addri_opcode;
  switch (opcode) {
  case X86::LEA16r:
    addrr_opcode = X86::ADD16rr;
    addri_opcode = X86::ADD16ri;
    break;
  case X86::LEA32r:
    addrr_opcode = X86::ADD32rr;
    addri_opcode = X86::ADD32ri;
    break;
  case X86::LEA64_32r:
  case X86::LEA64r:
    addrr_opcode = X86::ADD64rr;
    addri_opcode = X86::ADD64ri32;
    break;
  default:
    assert(false && "Unexpected LEA instruction");
  }
  DEBUG(dbgs() << "FixLEA: Candidate to replace:"; I->dump(););
  DEBUG(dbgs() << "FixLEA: Replaced by: ";);
  MachineInstr *NewMI = 0;
  const MachineOperand &Dst = MI->getOperand(0);
  // Make ADD instruction for two registers writing to LEA's destination
  if (SrcR1 != 0 && SrcR2 != 0) {
    const MachineOperand &Src1 = MI->getOperand(SrcR1 == DstR ? 1 : 3);
    const MachineOperand &Src2 = MI->getOperand(SrcR1 == DstR ? 3 : 1);
    NewMI = BuildMI(*MF, MI->getDebugLoc(), TII->get(addrr_opcode))
                .addOperand(Dst)
                .addOperand(Src1)
                .addOperand(Src2);
    MFI->insert(I, NewMI);
    DEBUG(NewMI->dump(););
  }
  // Make ADD instruction for immediate
  if (MI->getOperand(4).getImm() != 0) {
    const MachineOperand &SrcR = MI->getOperand(SrcR1 == DstR ? 1 : 3);
    NewMI = BuildMI(*MF, MI->getDebugLoc(), TII->get(addri_opcode))
                .addOperand(Dst)
                .addOperand(SrcR)
                .addImm(MI->getOperand(4).getImm());
    MFI->insert(I, NewMI);
    DEBUG(NewMI->dump(););
  }
  if (NewMI) {
    MFI->erase(I);
    I = static_cast<MachineBasicBlock::iterator>(NewMI);
  }
}

bool FixupLEAPass::processBasicBlock(MachineFunction &MF,
                                     MachineFunction::iterator MFI) {

  for (MachineBasicBlock::iterator I = MFI->begin(); I != MFI->end(); ++I) {
    if (TM->getSubtarget<X86Subtarget>().isSLM())
      processInstructionForSLM(I, MFI);
    else
      processInstruction(I, MFI);
  }
  return false;
}
<commit_msg>Fixup formatting in the pass.<commit_after>//===-- X86FixupLEAs.cpp - use or replace LEA instructions -----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the pass which will find  instructions  which
// can be re-written as LEA instructions in order to reduce pipeline
// delays for some models of the Intel Atom family.
//
//===----------------------------------------------------------------------===//

#include "X86.h"
#include "X86InstrInfo.h"
#include "X86Subtarget.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetInstrInfo.h"
using namespace llvm;

#define DEBUG_TYPE "x86-fixup-LEAs"

STATISTIC(NumLEAs, "Number of LEA instructions created");

namespace {
class FixupLEAPass : public MachineFunctionPass {
  enum RegUsageState { RU_NotUsed, RU_Write, RU_Read };
  static char ID;
  /// \brief Loop over all of the instructions in the basic block
  /// replacing applicable instructions with LEA instructions,
  /// where appropriate.
  bool processBasicBlock(MachineFunction &MF, MachineFunction::iterator MFI);

  const char *getPassName() const override { return "X86 Atom LEA Fixup"; }

  /// \brief Given a machine register, look for the instruction
  /// which writes it in the current basic block. If found,
  /// try to replace it with an equivalent LEA instruction.
  /// If replacement succeeds, then also process the the newly created
  /// instruction.
  void seekLEAFixup(MachineOperand &p, MachineBasicBlock::iterator &I,
                    MachineFunction::iterator MFI);

  /// \brief Given a memory access or LEA instruction
  /// whose address mode uses a base and/or index register, look for
  /// an opportunity to replace the instruction which sets the base or index
  /// register with an equivalent LEA instruction.
  void processInstruction(MachineBasicBlock::iterator &I,
                          MachineFunction::iterator MFI);

  /// \brief Given a LEA instruction which is unprofitable
  /// on Silvermont try to replace it with an equivalent ADD instruction
  void processInstructionForSLM(MachineBasicBlock::iterator &I,
                                MachineFunction::iterator MFI);

  /// \brief Determine if an instruction references a machine register
  /// and, if so, whether it reads or writes the register.
  RegUsageState usesRegister(MachineOperand &p, MachineBasicBlock::iterator I);

  /// \brief Step backwards through a basic block, looking
  /// for an instruction which writes a register within
  /// a maximum of INSTR_DISTANCE_THRESHOLD instruction latency cycles.
  MachineBasicBlock::iterator searchBackwards(MachineOperand &p,
                                              MachineBasicBlock::iterator &I,
                                              MachineFunction::iterator MFI);

  /// \brief if an instruction can be converted to an
  /// equivalent LEA, insert the new instruction into the basic block
  /// and return a pointer to it. Otherwise, return zero.
  MachineInstr *postRAConvertToLEA(MachineFunction::iterator &MFI,
                                   MachineBasicBlock::iterator &MBBI) const;

public:
  FixupLEAPass() : MachineFunctionPass(ID) {}

  /// \brief Loop over all of the basic blocks,
  /// replacing instructions by equivalent LEA instructions
  /// if needed and when possible.
  bool runOnMachineFunction(MachineFunction &MF) override;

private:
  MachineFunction *MF;
  const TargetMachine *TM;
  const X86InstrInfo *TII; // Machine instruction info.
};
char FixupLEAPass::ID = 0;
}

MachineInstr *
FixupLEAPass::postRAConvertToLEA(MachineFunction::iterator &MFI,
                                 MachineBasicBlock::iterator &MBBI) const {
  MachineInstr *MI = MBBI;
  MachineInstr *NewMI;
  switch (MI->getOpcode()) {
  case X86::MOV32rr:
  case X86::MOV64rr: {
    const MachineOperand &Src = MI->getOperand(1);
    const MachineOperand &Dest = MI->getOperand(0);
    NewMI = BuildMI(*MF, MI->getDebugLoc(),
                    TII->get(MI->getOpcode() == X86::MOV32rr ? X86::LEA32r
                                                             : X86::LEA64r))
                .addOperand(Dest)
                .addOperand(Src)
                .addImm(1)
                .addReg(0)
                .addImm(0)
                .addReg(0);
    MFI->insert(MBBI, NewMI); // Insert the new inst
    return NewMI;
  }
  case X86::ADD64ri32:
  case X86::ADD64ri8:
  case X86::ADD64ri32_DB:
  case X86::ADD64ri8_DB:
  case X86::ADD32ri:
  case X86::ADD32ri8:
  case X86::ADD32ri_DB:
  case X86::ADD32ri8_DB:
  case X86::ADD16ri:
  case X86::ADD16ri8:
  case X86::ADD16ri_DB:
  case X86::ADD16ri8_DB:
    if (!MI->getOperand(2).isImm()) {
      // convertToThreeAddress will call getImm()
      // which requires isImm() to be true
      return nullptr;
    }
    break;
  case X86::ADD16rr:
  case X86::ADD16rr_DB:
    if (MI->getOperand(1).getReg() != MI->getOperand(2).getReg()) {
      // if src1 != src2, then convertToThreeAddress will
      // need to create a Virtual register, which we cannot do
      // after register allocation.
      return nullptr;
    }
  }
  return TII->convertToThreeAddress(MFI, MBBI, nullptr);
}

FunctionPass *llvm::createX86FixupLEAs() { return new FixupLEAPass(); }

bool FixupLEAPass::runOnMachineFunction(MachineFunction &Func) {
  TM = &Func.getTarget();
  const X86Subtarget &ST = TM->getSubtarget<X86Subtarget>();
  if (!ST.LEAusesAG() && !ST.slowLEA())
    return false;

  TII = static_cast<const X86InstrInfo *>(TM->getInstrInfo());

  DEBUG(dbgs() << "Start X86FixupLEAs\n";);
  // Process all basic blocks.
  for (MachineFunction::iterator I = Func.begin(), E = Func.end(); I != E; ++I)
    processBasicBlock(Func, I);
  DEBUG(dbgs() << "End X86FixupLEAs\n";);

  return true;
}

FixupLEAPass::RegUsageState
FixupLEAPass::usesRegister(MachineOperand &p, MachineBasicBlock::iterator I) {
  RegUsageState RegUsage = RU_NotUsed;
  MachineInstr *MI = I;

  for (unsigned int i = 0; i < MI->getNumOperands(); ++i) {
    MachineOperand &opnd = MI->getOperand(i);
    if (opnd.isReg() && opnd.getReg() == p.getReg()) {
      if (opnd.isDef())
        return RU_Write;
      RegUsage = RU_Read;
    }
  }
  return RegUsage;
}

/// getPreviousInstr - Given a reference to an instruction in a basic
/// block, return a reference to the previous instruction in the block,
/// wrapping around to the last instruction of the block if the block
/// branches to itself.
static inline bool getPreviousInstr(MachineBasicBlock::iterator &I,
                                    MachineFunction::iterator MFI) {
  if (I == MFI->begin()) {
    if (MFI->isPredecessor(MFI)) {
      I = --MFI->end();
      return true;
    } else
      return false;
  }
  --I;
  return true;
}

MachineBasicBlock::iterator
FixupLEAPass::searchBackwards(MachineOperand &p, MachineBasicBlock::iterator &I,
                              MachineFunction::iterator MFI) {
  int InstrDistance = 1;
  MachineBasicBlock::iterator CurInst;
  static const int INSTR_DISTANCE_THRESHOLD = 5;

  CurInst = I;
  bool Found;
  Found = getPreviousInstr(CurInst, MFI);
  while (Found && I != CurInst) {
    if (CurInst->isCall() || CurInst->isInlineAsm())
      break;
    if (InstrDistance > INSTR_DISTANCE_THRESHOLD)
      break; // too far back to make a difference
    if (usesRegister(p, CurInst) == RU_Write) {
      return CurInst;
    }
    InstrDistance += TII->getInstrLatency(TM->getInstrItineraryData(), CurInst);
    Found = getPreviousInstr(CurInst, MFI);
  }
  return nullptr;
}

void FixupLEAPass::processInstruction(MachineBasicBlock::iterator &I,
                                      MachineFunction::iterator MFI) {
  // Process a load, store, or LEA instruction.
  MachineInstr *MI = I;
  int opcode = MI->getOpcode();
  const MCInstrDesc &Desc = MI->getDesc();
  int AddrOffset = X86II::getMemoryOperandNo(Desc.TSFlags, opcode);
  if (AddrOffset >= 0) {
    AddrOffset += X86II::getOperandBias(Desc);
    MachineOperand &p = MI->getOperand(AddrOffset + X86::AddrBaseReg);
    if (p.isReg() && p.getReg() != X86::ESP) {
      seekLEAFixup(p, I, MFI);
    }
    MachineOperand &q = MI->getOperand(AddrOffset + X86::AddrIndexReg);
    if (q.isReg() && q.getReg() != X86::ESP) {
      seekLEAFixup(q, I, MFI);
    }
  }
}

void FixupLEAPass::seekLEAFixup(MachineOperand &p,
                                MachineBasicBlock::iterator &I,
                                MachineFunction::iterator MFI) {
  MachineBasicBlock::iterator MBI = searchBackwards(p, I, MFI);
  if (MBI) {
    MachineInstr *NewMI = postRAConvertToLEA(MFI, MBI);
    if (NewMI) {
      ++NumLEAs;
      DEBUG(dbgs() << "FixLEA: Candidate to replace:"; MBI->dump(););
      // now to replace with an equivalent LEA...
      DEBUG(dbgs() << "FixLEA: Replaced by: "; NewMI->dump(););
      MFI->erase(MBI);
      MachineBasicBlock::iterator J =
          static_cast<MachineBasicBlock::iterator>(NewMI);
      processInstruction(J, MFI);
    }
  }
}

void FixupLEAPass::processInstructionForSLM(MachineBasicBlock::iterator &I,
                                            MachineFunction::iterator MFI) {
  MachineInstr *MI = I;
  const int opcode = MI->getOpcode();
  if (opcode != X86::LEA16r && opcode != X86::LEA32r && opcode != X86::LEA64r &&
      opcode != X86::LEA64_32r)
    return;
  if (MI->getOperand(5).getReg() != 0 || !MI->getOperand(4).isImm() ||
      !TII->isSafeToClobberEFLAGS(*MFI, I))
    return;
  const unsigned DstR = MI->getOperand(0).getReg();
  const unsigned SrcR1 = MI->getOperand(1).getReg();
  const unsigned SrcR2 = MI->getOperand(3).getReg();
  if ((SrcR1 == 0 || SrcR1 != DstR) && (SrcR2 == 0 || SrcR2 != DstR))
    return;
  if (MI->getOperand(2).getImm() > 1)
    return;
  int addrr_opcode, addri_opcode;
  switch (opcode) {
  case X86::LEA16r:
    addrr_opcode = X86::ADD16rr;
    addri_opcode = X86::ADD16ri;
    break;
  case X86::LEA32r:
    addrr_opcode = X86::ADD32rr;
    addri_opcode = X86::ADD32ri;
    break;
  case X86::LEA64_32r:
  case X86::LEA64r:
    addrr_opcode = X86::ADD64rr;
    addri_opcode = X86::ADD64ri32;
    break;
  default:
    assert(false && "Unexpected LEA instruction");
  }
  DEBUG(dbgs() << "FixLEA: Candidate to replace:"; I->dump(););
  DEBUG(dbgs() << "FixLEA: Replaced by: ";);
  MachineInstr *NewMI = 0;
  const MachineOperand &Dst = MI->getOperand(0);
  // Make ADD instruction for two registers writing to LEA's destination
  if (SrcR1 != 0 && SrcR2 != 0) {
    const MachineOperand &Src1 = MI->getOperand(SrcR1 == DstR ? 1 : 3);
    const MachineOperand &Src2 = MI->getOperand(SrcR1 == DstR ? 3 : 1);
    NewMI = BuildMI(*MF, MI->getDebugLoc(), TII->get(addrr_opcode))
                .addOperand(Dst)
                .addOperand(Src1)
                .addOperand(Src2);
    MFI->insert(I, NewMI);
    DEBUG(NewMI->dump(););
  }
  // Make ADD instruction for immediate
  if (MI->getOperand(4).getImm() != 0) {
    const MachineOperand &SrcR = MI->getOperand(SrcR1 == DstR ? 1 : 3);
    NewMI = BuildMI(*MF, MI->getDebugLoc(), TII->get(addri_opcode))
                .addOperand(Dst)
                .addOperand(SrcR)
                .addImm(MI->getOperand(4).getImm());
    MFI->insert(I, NewMI);
    DEBUG(NewMI->dump(););
  }
  if (NewMI) {
    MFI->erase(I);
    I = static_cast<MachineBasicBlock::iterator>(NewMI);
  }
}

bool FixupLEAPass::processBasicBlock(MachineFunction &MF,
                                     MachineFunction::iterator MFI) {

  for (MachineBasicBlock::iterator I = MFI->begin(); I != MFI->end(); ++I) {
    if (TM->getSubtarget<X86Subtarget>().isSLM())
      processInstructionForSLM(I, MFI);
    else
      processInstruction(I, MFI);
  }
  return false;
}
<|endoftext|>


<commit_before>//===-- X86MCAsmInfo.cpp - X86 asm properties -----------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the X86MCAsmInfo properties.
//
//===----------------------------------------------------------------------===//

#include "X86MCAsmInfo.h"
#include "X86TargetMachine.h"
#include "llvm/ADT/Triple.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;

enum AsmWriterFlavorTy {
  // Note: This numbering has to match the GCC assembler dialects for inline
  // asm alternatives to work right.
  ATT = 0, Intel = 1
};

static cl::opt<AsmWriterFlavorTy>
AsmWriterFlavor("x86-asm-syntax", cl::init(ATT),
  cl::desc("Choose style of code to emit from X86 backend:"),
  cl::values(clEnumValN(ATT,   "att",   "Emit AT&T-style assembly"),
             clEnumValN(Intel, "intel", "Emit Intel-style assembly"),
             clEnumValEnd));

static const char *const x86_asm_table[] = {
  "{si}", "S",
  "{di}", "D",
  "{ax}", "a",
  "{cx}", "c",
  "{memory}", "memory",
  "{flags}", "",
  "{dirflag}", "",
  "{fpsr}", "",
  "{cc}", "cc",
  0,0};

X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &Triple) {
  AsmTransCBE = x86_asm_table;
  AssemblerDialect = AsmWriterFlavor;

  bool is64Bit = Triple.getArch() == Triple::x86_64;

  TextAlignFillValue = 0x90;

  if (!is64Bit)
    Data64bitsDirective = 0;       // we can't emit a 64-bit unit

  // Use ## as a comment string so that .s files generated by llvm can go
  // through the GCC preprocessor without causing an error.  This is needed
  // because "clang foo.s" runs the C preprocessor, which is usually reserved
  // for .S files on other systems.  Perhaps this is because the file system
  // wasn't always case preserving or something.
  CommentString = "##";
  PCSymbol = ".";

  SupportsDebugInformation = true;
  DwarfUsesInlineInfoSection = true;

  // Exceptions handling
  ExceptionsType = ExceptionHandling::Dwarf;
}

X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &T) {
  AsmTransCBE = x86_asm_table;
  AssemblerDialect = AsmWriterFlavor;

  TextAlignFillValue = 0x90;

  PrivateGlobalPrefix = ".L";
  WeakRefDirective = "\t.weak\t";
  PCSymbol = ".";

  // Set up DWARF directives
  HasLEB128 = true;  // Target asm supports leb128 directives (little-endian)

  // Debug Information
  SupportsDebugInformation = true;

  // Exceptions handling
  ExceptionsType = ExceptionHandling::Dwarf;

  // OpenBSD has buggy support for .quad in 32-bit mode, just split into two
  // .words.
  if (T.getOS() == Triple::OpenBSD && T.getArch() == Triple::x86)
    Data64bitsDirective = 0;
}

const MCSection *X86ELFMCAsmInfo::
getNonexecutableStackSection(MCContext &Ctx) const {
  return Ctx.getELFSection(".note.GNU-stack", MCSectionELF::SHT_PROGBITS,
                           0, SectionKind::getMetadata());
}

X86MCAsmInfoCOFF::X86MCAsmInfoCOFF(const Triple &Triple) {
  if (Triple.getArch() == Triple::x86_64)
    GlobalPrefix = "";

  AsmTransCBE = x86_asm_table;
  AssemblerDialect = AsmWriterFlavor;

  TextAlignFillValue = 0x90;
}
<commit_msg>lib/Target/X86/X86MCAsmInfo.cpp: [PR8741] On Win64, specify explicit PrivateGlobalPrefix as ".L".<commit_after>//===-- X86MCAsmInfo.cpp - X86 asm properties -----------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the X86MCAsmInfo properties.
//
//===----------------------------------------------------------------------===//

#include "X86MCAsmInfo.h"
#include "X86TargetMachine.h"
#include "llvm/ADT/Triple.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;

enum AsmWriterFlavorTy {
  // Note: This numbering has to match the GCC assembler dialects for inline
  // asm alternatives to work right.
  ATT = 0, Intel = 1
};

static cl::opt<AsmWriterFlavorTy>
AsmWriterFlavor("x86-asm-syntax", cl::init(ATT),
  cl::desc("Choose style of code to emit from X86 backend:"),
  cl::values(clEnumValN(ATT,   "att",   "Emit AT&T-style assembly"),
             clEnumValN(Intel, "intel", "Emit Intel-style assembly"),
             clEnumValEnd));

static const char *const x86_asm_table[] = {
  "{si}", "S",
  "{di}", "D",
  "{ax}", "a",
  "{cx}", "c",
  "{memory}", "memory",
  "{flags}", "",
  "{dirflag}", "",
  "{fpsr}", "",
  "{cc}", "cc",
  0,0};

X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &Triple) {
  AsmTransCBE = x86_asm_table;
  AssemblerDialect = AsmWriterFlavor;

  bool is64Bit = Triple.getArch() == Triple::x86_64;

  TextAlignFillValue = 0x90;

  if (!is64Bit)
    Data64bitsDirective = 0;       // we can't emit a 64-bit unit

  // Use ## as a comment string so that .s files generated by llvm can go
  // through the GCC preprocessor without causing an error.  This is needed
  // because "clang foo.s" runs the C preprocessor, which is usually reserved
  // for .S files on other systems.  Perhaps this is because the file system
  // wasn't always case preserving or something.
  CommentString = "##";
  PCSymbol = ".";

  SupportsDebugInformation = true;
  DwarfUsesInlineInfoSection = true;

  // Exceptions handling
  ExceptionsType = ExceptionHandling::Dwarf;
}

X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &T) {
  AsmTransCBE = x86_asm_table;
  AssemblerDialect = AsmWriterFlavor;

  TextAlignFillValue = 0x90;

  PrivateGlobalPrefix = ".L";
  WeakRefDirective = "\t.weak\t";
  PCSymbol = ".";

  // Set up DWARF directives
  HasLEB128 = true;  // Target asm supports leb128 directives (little-endian)

  // Debug Information
  SupportsDebugInformation = true;

  // Exceptions handling
  ExceptionsType = ExceptionHandling::Dwarf;

  // OpenBSD has buggy support for .quad in 32-bit mode, just split into two
  // .words.
  if (T.getOS() == Triple::OpenBSD && T.getArch() == Triple::x86)
    Data64bitsDirective = 0;
}

const MCSection *X86ELFMCAsmInfo::
getNonexecutableStackSection(MCContext &Ctx) const {
  return Ctx.getELFSection(".note.GNU-stack", MCSectionELF::SHT_PROGBITS,
                           0, SectionKind::getMetadata());
}

X86MCAsmInfoCOFF::X86MCAsmInfoCOFF(const Triple &Triple) {
  if (Triple.getArch() == Triple::x86_64) {
    GlobalPrefix = "";
    PrivateGlobalPrefix = ".L";
  }

  AsmTransCBE = x86_asm_table;
  AssemblerDialect = AsmWriterFlavor;

  TextAlignFillValue = 0x90;
}
<|endoftext|>


<commit_before>//===-- X86Subtarget.cpp - X86 Subtarget Information ------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the X86 specific subclass of TargetSubtarget.
//
//===----------------------------------------------------------------------===//

#include "X86Subtarget.h"
#include "X86GenSubtarget.inc"
#include "llvm/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;

cl::opt<X86Subtarget::AsmWriterFlavorTy>
AsmWriterFlavor("x86-asm-syntax", cl::init(X86Subtarget::Unset),
  cl::desc("Choose style of code to emit from X86 backend:"),
  cl::values(
    clEnumValN(X86Subtarget::ATT,   "att",   "  Emit AT&T-style assembly"),
    clEnumValN(X86Subtarget::Intel, "intel", "  Emit Intel-style assembly"),
    clEnumValEnd));

/// True if accessing the GV requires an extra load. For Windows, dllimported
/// symbols are indirect, loading the value at address GV rather then the
/// value of GV itself. This means that the GlobalAddress must be in the base
/// or index register of the address, not the GV offset field.
bool X86Subtarget::GVRequiresExtraLoad(const GlobalValue* GV,
                                       const TargetMachine& TM,
                                       bool isDirectCall) const
{
  // FIXME: PIC
  if (TM.getRelocationModel() != Reloc::Static) {
    if (isTargetDarwin()) {
      return (!isDirectCall &&
              (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
               (GV->isDeclaration() && !GV->hasNotBeenReadFromBitcode())));
    } else if (isTargetELF()) {
      // Extra load is needed for all non-statics.
      return (!isDirectCall &&
              (GV->isDeclaration() || !GV->hasInternalLinkage()));
    } else if (isTargetCygMing() || isTargetWindows()) {
      return (GV->hasDLLImportLinkage());
    }
  }

  return false;
}

/// This function returns the name of a function which has an interface
/// like the non-standard bzero function, if such a function exists on
/// the current subtarget and it is considered prefereable over
/// memset with zero passed as the second argument. Otherwise it
/// returns null.
const char *X86Subtarget::getBZeroEntry() const {

  // Darwin 10 has a __bzero entry point for this purpose.
  if (getDarwinVers() >= 10)
    return "__bzero";

  return 0;
}

/// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in the
/// specified arguments.  If we can't run cpuid on the host, return true.
bool X86::GetCpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
                          unsigned *rECX, unsigned *rEDX) {
#if defined(__x86_64__)
  // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually.
  asm ("movq\t%%rbx, %%rsi\n\t"
       "cpuid\n\t"
       "xchgq\t%%rbx, %%rsi\n\t"
       : "=a" (*rEAX),
         "=S" (*rEBX),
         "=c" (*rECX),
         "=d" (*rEDX)
       :  "a" (value));
  return false;
#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
#if defined(__GNUC__)
  asm ("movl\t%%ebx, %%esi\n\t"
       "cpuid\n\t"
       "xchgl\t%%ebx, %%esi\n\t"
       : "=a" (*rEAX),
         "=S" (*rEBX),
         "=c" (*rECX),
         "=d" (*rEDX)
       :  "a" (value));
  return false;
#elif defined(_MSC_VER)
  __asm {
    mov   eax,value
    cpuid
    mov   esi,rEAX
    mov   dword ptr [esi],eax
    mov   esi,rEBX
    mov   dword ptr [esi],ebx
    mov   esi,rECX
    mov   dword ptr [esi],ecx
    mov   esi,rEDX
    mov   dword ptr [esi],edx
  }
  return false;
#endif
#endif
  return true;
}

void X86Subtarget::AutoDetectSubtargetFeatures() {
  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
  union {
    unsigned u[3];
    char     c[12];
  } text;

  if (X86::GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1))
    return;

  X86::GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX);

  if ((EDX >> 23) & 0x1) X86SSELevel = MMX;
  if ((EDX >> 25) & 0x1) X86SSELevel = SSE1;
  if ((EDX >> 26) & 0x1) X86SSELevel = SSE2;
  if (ECX & 0x1)         X86SSELevel = SSE3;
  if ((ECX >> 9)  & 0x1) X86SSELevel = SSSE3;
  if ((ECX >> 19) & 0x1) X86SSELevel = SSE41;
  if ((ECX >> 20) & 0x1) X86SSELevel = SSE42;

  if (memcmp(text.c, "GenuineIntel", 12) == 0 ||
      memcmp(text.c, "AuthenticAMD", 12) == 0) {
    X86::GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
    HasX86_64 = (EDX >> 29) & 0x1;
  }
}

static const char *GetCurrentX86CPU() {
  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
  if (X86::GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX))
    return "generic";
  unsigned Family  = (EAX >> 8) & 0xf; // Bits 8 - 11
  unsigned Model   = (EAX >> 4) & 0xf; // Bits 4 - 7
  X86::GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
  bool Em64T = (EDX >> 29) & 0x1;

  union {
    unsigned u[3];
    char     c[12];
  } text;

  X86::GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1);
  if (memcmp(text.c, "GenuineIntel", 12) == 0) {
    switch (Family) {
      case 3:
        return "i386";
      case 4:
        return "i486";
      case 5:
        switch (Model) {
        case 4:  return "pentium-mmx";
        default: return "pentium";
        }
      case 6:
        switch (Model) {
        case 1:  return "pentiumpro";
        case 3:
        case 5:
        case 6:  return "pentium2";
        case 7:
        case 8:
        case 10:
        case 11: return "pentium3";
        case 9:
        case 13: return "pentium-m";
        case 14: return "yonah";
        case 15: return "core2";
        default: return "i686";
        }
      case 15: {
        switch (Model) {
        case 3:
        case 4:
          return (Em64T) ? "nocona" : "prescott";
        default:
          return (Em64T) ? "x86-64" : "pentium4";
        }
      }

    default:
      return "generic";
    }
  } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) {
    // FIXME: this poorly matches the generated SubtargetFeatureKV table.  There
    // appears to be no way to generate the wide variety of AMD-specific targets
    // from the information returned from CPUID.
    switch (Family) {
      case 4:
        return "i486";
      case 5:
        switch (Model) {
        case 6:
        case 7:  return "k6";
        case 8:  return "k6-2";
        case 9:
        case 13: return "k6-3";
        default: return "pentium";
        }
      case 6:
        switch (Model) {
        case 4:  return "athlon-tbird";
        case 6:
        case 7:
        case 8:  return "athlon-mp";
        case 10: return "athlon-xp";
        default: return "athlon";
        }
      case 15:
        switch (Model) {
        case 1:  return "opteron";
        case 5:  return "athlon-fx"; // also opteron
        default: return "athlon64";
        }
    default:
      return "generic";
    }
  } else {
    return "generic";
  }
}

X86Subtarget::X86Subtarget(const Module &M, const std::string &FS, bool is64Bit)
  : AsmFlavor(AsmWriterFlavor)
  , PICStyle(PICStyle::None)
  , X86SSELevel(NoMMXSSE)
  , X863DNowLevel(NoThreeDNow)
  , HasX86_64(false)
  , DarwinVers(0)
  , stackAlignment(8)
  // FIXME: this is a known good value for Yonah. How about others?
  , MaxInlineSizeThreshold(128)
  , Is64Bit(is64Bit)
  , TargetType(isELF) { // Default to ELF unless otherwise specified.

  // Determine default and user specified characteristics
  if (!FS.empty()) {
    // If feature string is not empty, parse features string.
    std::string CPU = GetCurrentX86CPU();
    ParseSubtargetFeatures(FS, CPU);
  } else {
    // Otherwise, use CPUID to auto-detect feature set.
    AutoDetectSubtargetFeatures();
  }

  // If requesting codegen for X86-64, make sure that 64-bit and SSE2 features
  // are enabled.  These are available on all x86-64 CPUs.
  if (Is64Bit) {
    HasX86_64 = true;
    if (X86SSELevel < SSE2)
      X86SSELevel = SSE2;
  }

  // Set the boolean corresponding to the current target triple, or the default
  // if one cannot be determined, to true.
  const std::string& TT = M.getTargetTriple();
  if (TT.length() > 5) {
    size_t Pos;
    if ((Pos = TT.find("-darwin")) != std::string::npos) {
      TargetType = isDarwin;

      // Compute the darwin version number.
      if (isdigit(TT[Pos+7]))
        DarwinVers = atoi(&TT[Pos+7]);
      else
        DarwinVers = 8;  // Minimum supported darwin is Tiger.
    } else if (TT.find("linux") != std::string::npos) {
      // Linux doesn't imply ELF, but we don't currently support anything else.
      TargetType = isELF;
      IsLinux = true;
    } else if (TT.find("cygwin") != std::string::npos) {
      TargetType = isCygwin;
    } else if (TT.find("mingw") != std::string::npos) {
      TargetType = isMingw;
    } else if (TT.find("win32") != std::string::npos) {
      TargetType = isWindows;
    } else if (TT.find("windows") != std::string::npos) {
      TargetType = isWindows;
    }
  } else if (TT.empty()) {
#if defined(__CYGWIN__)
    TargetType = isCygwin;
#elif defined(__MINGW32__) || defined(__MINGW64__)
    TargetType = isMingw;
#elif defined(__APPLE__)
    TargetType = isDarwin;
#if __APPLE_CC__ > 5400
    DarwinVers = 9;  // GCC 5400+ is Leopard.
#else
    DarwinVers = 8;  // Minimum supported darwin is Tiger.
#endif

#elif defined(_WIN32) || defined(_WIN64)
    TargetType = isWindows;
#elif defined(__linux__)
    // Linux doesn't imply ELF, but we don't currently support anything else.
    TargetType = isELF;
    IsLinux = true;
#endif
  }

  // If the asm syntax hasn't been overridden on the command line, use whatever
  // the target wants.
  if (AsmFlavor == X86Subtarget::Unset) {
    AsmFlavor = (TargetType == isWindows)
      ? X86Subtarget::Intel : X86Subtarget::ATT;
  }

  // Stack alignment is 16 bytes on Darwin (both 32 and 64 bit) and for all 64
  // bit targets.
  if (TargetType == isDarwin || Is64Bit)
    stackAlignment = 16;

  if (StackAlignment)
    stackAlignment = StackAlignment;
}
<commit_msg>Fix IsLinux being uninitialized on non-Linux targets.<commit_after>//===-- X86Subtarget.cpp - X86 Subtarget Information ------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the X86 specific subclass of TargetSubtarget.
//
//===----------------------------------------------------------------------===//

#include "X86Subtarget.h"
#include "X86GenSubtarget.inc"
#include "llvm/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;

cl::opt<X86Subtarget::AsmWriterFlavorTy>
AsmWriterFlavor("x86-asm-syntax", cl::init(X86Subtarget::Unset),
  cl::desc("Choose style of code to emit from X86 backend:"),
  cl::values(
    clEnumValN(X86Subtarget::ATT,   "att",   "  Emit AT&T-style assembly"),
    clEnumValN(X86Subtarget::Intel, "intel", "  Emit Intel-style assembly"),
    clEnumValEnd));

/// True if accessing the GV requires an extra load. For Windows, dllimported
/// symbols are indirect, loading the value at address GV rather then the
/// value of GV itself. This means that the GlobalAddress must be in the base
/// or index register of the address, not the GV offset field.
bool X86Subtarget::GVRequiresExtraLoad(const GlobalValue* GV,
                                       const TargetMachine& TM,
                                       bool isDirectCall) const
{
  // FIXME: PIC
  if (TM.getRelocationModel() != Reloc::Static) {
    if (isTargetDarwin()) {
      return (!isDirectCall &&
              (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
               (GV->isDeclaration() && !GV->hasNotBeenReadFromBitcode())));
    } else if (isTargetELF()) {
      // Extra load is needed for all non-statics.
      return (!isDirectCall &&
              (GV->isDeclaration() || !GV->hasInternalLinkage()));
    } else if (isTargetCygMing() || isTargetWindows()) {
      return (GV->hasDLLImportLinkage());
    }
  }

  return false;
}

/// This function returns the name of a function which has an interface
/// like the non-standard bzero function, if such a function exists on
/// the current subtarget and it is considered prefereable over
/// memset with zero passed as the second argument. Otherwise it
/// returns null.
const char *X86Subtarget::getBZeroEntry() const {

  // Darwin 10 has a __bzero entry point for this purpose.
  if (getDarwinVers() >= 10)
    return "__bzero";

  return 0;
}

/// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in the
/// specified arguments.  If we can't run cpuid on the host, return true.
bool X86::GetCpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
                          unsigned *rECX, unsigned *rEDX) {
#if defined(__x86_64__)
  // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually.
  asm ("movq\t%%rbx, %%rsi\n\t"
       "cpuid\n\t"
       "xchgq\t%%rbx, %%rsi\n\t"
       : "=a" (*rEAX),
         "=S" (*rEBX),
         "=c" (*rECX),
         "=d" (*rEDX)
       :  "a" (value));
  return false;
#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
#if defined(__GNUC__)
  asm ("movl\t%%ebx, %%esi\n\t"
       "cpuid\n\t"
       "xchgl\t%%ebx, %%esi\n\t"
       : "=a" (*rEAX),
         "=S" (*rEBX),
         "=c" (*rECX),
         "=d" (*rEDX)
       :  "a" (value));
  return false;
#elif defined(_MSC_VER)
  __asm {
    mov   eax,value
    cpuid
    mov   esi,rEAX
    mov   dword ptr [esi],eax
    mov   esi,rEBX
    mov   dword ptr [esi],ebx
    mov   esi,rECX
    mov   dword ptr [esi],ecx
    mov   esi,rEDX
    mov   dword ptr [esi],edx
  }
  return false;
#endif
#endif
  return true;
}

void X86Subtarget::AutoDetectSubtargetFeatures() {
  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
  union {
    unsigned u[3];
    char     c[12];
  } text;

  if (X86::GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1))
    return;

  X86::GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX);

  if ((EDX >> 23) & 0x1) X86SSELevel = MMX;
  if ((EDX >> 25) & 0x1) X86SSELevel = SSE1;
  if ((EDX >> 26) & 0x1) X86SSELevel = SSE2;
  if (ECX & 0x1)         X86SSELevel = SSE3;
  if ((ECX >> 9)  & 0x1) X86SSELevel = SSSE3;
  if ((ECX >> 19) & 0x1) X86SSELevel = SSE41;
  if ((ECX >> 20) & 0x1) X86SSELevel = SSE42;

  if (memcmp(text.c, "GenuineIntel", 12) == 0 ||
      memcmp(text.c, "AuthenticAMD", 12) == 0) {
    X86::GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
    HasX86_64 = (EDX >> 29) & 0x1;
  }
}

static const char *GetCurrentX86CPU() {
  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
  if (X86::GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX))
    return "generic";
  unsigned Family  = (EAX >> 8) & 0xf; // Bits 8 - 11
  unsigned Model   = (EAX >> 4) & 0xf; // Bits 4 - 7
  X86::GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
  bool Em64T = (EDX >> 29) & 0x1;

  union {
    unsigned u[3];
    char     c[12];
  } text;

  X86::GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1);
  if (memcmp(text.c, "GenuineIntel", 12) == 0) {
    switch (Family) {
      case 3:
        return "i386";
      case 4:
        return "i486";
      case 5:
        switch (Model) {
        case 4:  return "pentium-mmx";
        default: return "pentium";
        }
      case 6:
        switch (Model) {
        case 1:  return "pentiumpro";
        case 3:
        case 5:
        case 6:  return "pentium2";
        case 7:
        case 8:
        case 10:
        case 11: return "pentium3";
        case 9:
        case 13: return "pentium-m";
        case 14: return "yonah";
        case 15: return "core2";
        default: return "i686";
        }
      case 15: {
        switch (Model) {
        case 3:
        case 4:
          return (Em64T) ? "nocona" : "prescott";
        default:
          return (Em64T) ? "x86-64" : "pentium4";
        }
      }

    default:
      return "generic";
    }
  } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) {
    // FIXME: this poorly matches the generated SubtargetFeatureKV table.  There
    // appears to be no way to generate the wide variety of AMD-specific targets
    // from the information returned from CPUID.
    switch (Family) {
      case 4:
        return "i486";
      case 5:
        switch (Model) {
        case 6:
        case 7:  return "k6";
        case 8:  return "k6-2";
        case 9:
        case 13: return "k6-3";
        default: return "pentium";
        }
      case 6:
        switch (Model) {
        case 4:  return "athlon-tbird";
        case 6:
        case 7:
        case 8:  return "athlon-mp";
        case 10: return "athlon-xp";
        default: return "athlon";
        }
      case 15:
        switch (Model) {
        case 1:  return "opteron";
        case 5:  return "athlon-fx"; // also opteron
        default: return "athlon64";
        }
    default:
      return "generic";
    }
  } else {
    return "generic";
  }
}

X86Subtarget::X86Subtarget(const Module &M, const std::string &FS, bool is64Bit)
  : AsmFlavor(AsmWriterFlavor)
  , PICStyle(PICStyle::None)
  , X86SSELevel(NoMMXSSE)
  , X863DNowLevel(NoThreeDNow)
  , HasX86_64(false)
  , DarwinVers(0)
  , IsLinux(false)
  , stackAlignment(8)
  // FIXME: this is a known good value for Yonah. How about others?
  , MaxInlineSizeThreshold(128)
  , Is64Bit(is64Bit)
  , TargetType(isELF) { // Default to ELF unless otherwise specified.

  // Determine default and user specified characteristics
  if (!FS.empty()) {
    // If feature string is not empty, parse features string.
    std::string CPU = GetCurrentX86CPU();
    ParseSubtargetFeatures(FS, CPU);
  } else {
    // Otherwise, use CPUID to auto-detect feature set.
    AutoDetectSubtargetFeatures();
  }

  // If requesting codegen for X86-64, make sure that 64-bit and SSE2 features
  // are enabled.  These are available on all x86-64 CPUs.
  if (Is64Bit) {
    HasX86_64 = true;
    if (X86SSELevel < SSE2)
      X86SSELevel = SSE2;
  }

  // Set the boolean corresponding to the current target triple, or the default
  // if one cannot be determined, to true.
  const std::string& TT = M.getTargetTriple();
  if (TT.length() > 5) {
    size_t Pos;
    if ((Pos = TT.find("-darwin")) != std::string::npos) {
      TargetType = isDarwin;

      // Compute the darwin version number.
      if (isdigit(TT[Pos+7]))
        DarwinVers = atoi(&TT[Pos+7]);
      else
        DarwinVers = 8;  // Minimum supported darwin is Tiger.
    } else if (TT.find("linux") != std::string::npos) {
      // Linux doesn't imply ELF, but we don't currently support anything else.
      TargetType = isELF;
      IsLinux = true;
    } else if (TT.find("cygwin") != std::string::npos) {
      TargetType = isCygwin;
    } else if (TT.find("mingw") != std::string::npos) {
      TargetType = isMingw;
    } else if (TT.find("win32") != std::string::npos) {
      TargetType = isWindows;
    } else if (TT.find("windows") != std::string::npos) {
      TargetType = isWindows;
    }
  } else if (TT.empty()) {
#if defined(__CYGWIN__)
    TargetType = isCygwin;
#elif defined(__MINGW32__) || defined(__MINGW64__)
    TargetType = isMingw;
#elif defined(__APPLE__)
    TargetType = isDarwin;
#if __APPLE_CC__ > 5400
    DarwinVers = 9;  // GCC 5400+ is Leopard.
#else
    DarwinVers = 8;  // Minimum supported darwin is Tiger.
#endif

#elif defined(_WIN32) || defined(_WIN64)
    TargetType = isWindows;
#elif defined(__linux__)
    // Linux doesn't imply ELF, but we don't currently support anything else.
    TargetType = isELF;
    IsLinux = true;
#endif
  }

  // If the asm syntax hasn't been overridden on the command line, use whatever
  // the target wants.
  if (AsmFlavor == X86Subtarget::Unset) {
    AsmFlavor = (TargetType == isWindows)
      ? X86Subtarget::Intel : X86Subtarget::ATT;
  }

  // Stack alignment is 16 bytes on Darwin (both 32 and 64 bit) and for all 64
  // bit targets.
  if (TargetType == isDarwin || Is64Bit)
    stackAlignment = 16;

  if (StackAlignment)
    stackAlignment = StackAlignment;
}
<|endoftext|>


<commit_before>/**
Copyright (c) 2016 Ryan Porter - arrayNodes
You may use, distribute, or modify this code under the terms of the MIT license.
*/

//-----------------------------------------------------------------------------
//  angleUnaryOp node
//
//  Performs a reducing operation with the input values
//      No Operation    - Returns zero.
//      Sum             - Returns the sum of the input values.
//      Difference      - Returns the difference of the input values.
//      Product         - Returns the product of the input values.
//      Minimum         - Returns the smallest input value.
//      Maximum         - Returns the largest input value.
//-----------------------------------------------------------------------------

#include "n_angleMultiOp.h"
#include "node.h"

#include <vector>
#include <algorithm>
#include <numeric>

#include <maya/MAngle.h>
#include <maya/MDataHandle.h>
#include <maya/MFnEnumAttribute.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnUnitAttribute.h>
#include <maya/MPlug.h>
#include <maya/MPxNode.h>

MObject AngleMultiOpNode::aInput;
MObject AngleMultiOpNode::aOperation;
MObject AngleMultiOpNode::aOutput;

const short NO_OP = 0;
const short SUM = 1;
const short DIFF = 2;
const short PRODUCT = 3;
const short MIN_ = 4;
const short MAX_ = 5;

void* AngleMultiOpNode::creator()
{
    return new AngleMultiOpNode();
}

MStatus AngleMultiOpNode::initialize()
{
    MStatus status;

    MFnUnitAttribute u;
    MFnEnumAttribute e;

    aInput = u.create("input", "i", MFnUnitAttribute::kAngle, 0.0, &status);
    __CHECK_STATUS(status);
    MAKE_INPUT_ATTR(u);
    u.setArray(true);

    aOperation = e.create("operation", "op", SUM, &status);
    __CHECK_STATUS(status);
    MAKE_INPUT_ATTR(e);

    e.addField("No Operation", NO_OP);
    e.addField("Sum", SUM);
    e.addField("Difference", DIFF);
    e.addField("Product", PRODUCT);
    e.addField("Minimum", MIN_);
    e.addField("Maximum", MAX_);

    aOutput = u.create("output", "o", MFnUnitAttribute::kAngle, 0.0, &status);
    __CHECK_STATUS(status);
    MAKE_OUTPUT_ATTR(u)

    addAttribute(aInput);
    addAttribute(aOperation);
    addAttribute(aOutput);

    attributeAffects(aInput, aOutput);
    attributeAffects(aOperation, aOutput);

    return MS::kSuccess;
}

MStatus AngleMultiOpNode::compute(const MPlug& plug, MDataBlock& data)
{
    if (plug != aOutput)
    {
        return MS::kUnknownParameter;
    }

    MArrayDataHandle inputArrayHandle = data.inputValue(aInput);

    uint numInputs = inputArrayHandle.elementCount();
    std::vector<double> inputs(numInputs);

    for (uint i = 0; i < numInputs; i++)
    {
        inputs[i] = inputArrayHandle.inputValue().asAngle().asDegrees();
        if (!inputArrayHandle.next()) continue;
    }

    short operation = data.inputValue(aOperation).asShort();

    double result = 0;

    switch (operation)
    {
        case SUM:
            result = std::accumulate(inputs.begin(), inputs.end(), 0.0, std::plus<double>());
            break;

        case DIFF:
            result = std::accumulate(inputs.begin(), inputs.end(), 0.0, std::minus<double>());
            break;

        case PRODUCT:
            result = std::accumulate(inputs.begin(), inputs.end(), 1.0, std::multiplies<double>());
            break;

        case MIN_:
            result = *std::min_element(inputs.begin(), inputs.end());
            break;

        case MAX_:
            result = *std::max_element(inputs.begin(), inputs.end());
            break;
    }

    MDataHandle output = data.outputValue(aOutput);
    output.setMAngle(MAngle(result, MAngle::kDegrees));
    output.setClean();

    return MS::kSuccess;
}<commit_msg>Fix #3 - change uint to unsigned.<commit_after>/**
Copyright (c) 2016 Ryan Porter - arrayNodes
You may use, distribute, or modify this code under the terms of the MIT license.
*/

//-----------------------------------------------------------------------------
//  angleUnaryOp node
//
//  Performs a reducing operation with the input values
//      No Operation    - Returns zero.
//      Sum             - Returns the sum of the input values.
//      Difference      - Returns the difference of the input values.
//      Product         - Returns the product of the input values.
//      Minimum         - Returns the smallest input value.
//      Maximum         - Returns the largest input value.
//-----------------------------------------------------------------------------

#include "n_angleMultiOp.h"
#include "node.h"

#include <vector>
#include <algorithm>
#include <numeric>

#include <maya/MAngle.h>
#include <maya/MDataHandle.h>
#include <maya/MFnEnumAttribute.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnUnitAttribute.h>
#include <maya/MPlug.h>
#include <maya/MPxNode.h>

MObject AngleMultiOpNode::aInput;
MObject AngleMultiOpNode::aOperation;
MObject AngleMultiOpNode::aOutput;

const short NO_OP = 0;
const short SUM = 1;
const short DIFF = 2;
const short PRODUCT = 3;
const short MIN_ = 4;
const short MAX_ = 5;

void* AngleMultiOpNode::creator()
{
    return new AngleMultiOpNode();
}

MStatus AngleMultiOpNode::initialize()
{
    MStatus status;

    MFnUnitAttribute u;
    MFnEnumAttribute e;

    aInput = u.create("input", "i", MFnUnitAttribute::kAngle, 0.0, &status);
    __CHECK_STATUS(status);
    MAKE_INPUT_ATTR(u);
    u.setArray(true);

    aOperation = e.create("operation", "op", SUM, &status);
    __CHECK_STATUS(status);
    MAKE_INPUT_ATTR(e);

    e.addField("No Operation", NO_OP);
    e.addField("Sum", SUM);
    e.addField("Difference", DIFF);
    e.addField("Product", PRODUCT);
    e.addField("Minimum", MIN_);
    e.addField("Maximum", MAX_);

    aOutput = u.create("output", "o", MFnUnitAttribute::kAngle, 0.0, &status);
    __CHECK_STATUS(status);
    MAKE_OUTPUT_ATTR(u)

    addAttribute(aInput);
    addAttribute(aOperation);
    addAttribute(aOutput);

    attributeAffects(aInput, aOutput);
    attributeAffects(aOperation, aOutput);

    return MS::kSuccess;
}

MStatus AngleMultiOpNode::compute(const MPlug& plug, MDataBlock& data)
{
    if (plug != aOutput)
    {
        return MS::kUnknownParameter;
    }

    MArrayDataHandle inputArrayHandle = data.inputValue(aInput);

    unsigned numInputs = inputArrayHandle.elementCount();
    std::vector<double> inputs(numInputs);

    for (unsigned i = 0; i < numInputs; i++)
    {
        inputs[i] = inputArrayHandle.inputValue().asAngle().asDegrees();
        if (!inputArrayHandle.next()) continue;
    }

    short operation = data.inputValue(aOperation).asShort();

    double result = 0;

    switch (operation)
    {
        case SUM:
            result = std::accumulate(inputs.begin(), inputs.end(), 0.0, std::plus<double>());
            break;

        case DIFF:
            result = std::accumulate(inputs.begin(), inputs.end(), 0.0, std::minus<double>());
            break;

        case PRODUCT:
            result = std::accumulate(inputs.begin(), inputs.end(), 1.0, std::multiplies<double>());
            break;

        case MIN_:
            result = *std::min_element(inputs.begin(), inputs.end());
            break;

        case MAX_:
            result = *std::max_element(inputs.begin(), inputs.end());
            break;
    }

    MDataHandle output = data.outputValue(aOutput);
    output.setMAngle(MAngle(result, MAngle::kDegrees));
    output.setClean();

    return MS::kSuccess;
}<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */
#include "vbaheadersfooters.hxx"
#include "vbaheaderfooter.hxx"
#include <ooo/vba/word/WdHeaderFooterIndex.hpp>

using namespace ::ooo::vba;
using namespace ::com::sun::star;

// I assume there is only one headersfooters in Writer
typedef ::cppu::WeakImplHelper1<container::XIndexAccess > HeadersFootersIndexAccess_Base;
class HeadersFootersIndexAccess : public HeadersFootersIndexAccess_Base
{
private:
    uno::Reference< XHelperInterface > mxParent;
    uno::Reference< uno::XComponentContext > mxContext;
    uno::Reference< frame::XModel > mxModel;
    uno::Reference< beans::XPropertySet > mxPageStyleProps;
    bool mbHeader;

public:
    HeadersFootersIndexAccess( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< frame::XModel >& xModel, const uno::Reference< beans::XPropertySet >& xPageStyleProps, bool bHeader ) : mxParent( xParent ), mxContext( xContext ), mxModel( xModel ), mxPageStyleProps( xPageStyleProps ), mbHeader( bHeader ) {}
    virtual ~HeadersFootersIndexAccess(){}

    // XIndexAccess
    virtual sal_Int32 SAL_CALL getCount(  ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
    {
        // first page, evenpages and primary page
        return 3;
    }
    virtual uno::Any SAL_CALL getByIndex( sal_Int32 Index ) throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
    {
        if( Index < 1 || Index > 3 )
            throw container::NoSuchElementException();
        return uno::makeAny( uno::Reference< word::XHeaderFooter >( new SwVbaHeaderFooter( mxParent,  mxContext, mxModel, mxPageStyleProps, mbHeader, Index ) ) );
    }
    virtual uno::Type SAL_CALL getElementType(  ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
    {
        return cppu::UnoType<word::XHeaderFooter>::get();
    }
    virtual sal_Bool SAL_CALL hasElements(  ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
    {
        return sal_True;
    }
};

class HeadersFootersEnumWrapper : public EnumerationHelper_BASE
{
    SwVbaHeadersFooters* pHeadersFooters;
    sal_Int32 nIndex;
public:
    HeadersFootersEnumWrapper( SwVbaHeadersFooters* _pHeadersFooters ) : pHeadersFooters( _pHeadersFooters ), nIndex( 0 ) {}
    virtual sal_Bool SAL_CALL hasMoreElements(  ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
    {
        return ( nIndex < pHeadersFooters->getCount() );
    }

    virtual uno::Any SAL_CALL nextElement(  ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
    {
        if ( nIndex < pHeadersFooters->getCount() )
            return pHeadersFooters->Item( uno::makeAny( ++nIndex ), uno::Any() );
        throw container::NoSuchElementException();
    }
};

SwVbaHeadersFooters::SwVbaHeadersFooters( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext > & xContext, const uno::Reference< frame::XModel >& xModel, const uno::Reference< beans::XPropertySet >& xPageStyleProps, bool isHeader ): SwVbaHeadersFooters_BASE( xParent, xContext, new HeadersFootersIndexAccess( xParent, xContext, xModel, xPageStyleProps, isHeader ) ),  mxModel( xModel ), mxPageStyleProps( xPageStyleProps ), mbHeader( isHeader )
{
}

::sal_Int32 SAL_CALL SwVbaHeadersFooters::getCount() throw (uno::RuntimeException)
{
    // wdHeaderFooterFirstPage, wdHeaderFooterPrimary and wdHeaderFooterEvenPages
    return 3;
}

uno::Any SAL_CALL SwVbaHeadersFooters::Item( const uno::Any& Index1, const uno::Any& ) throw (uno::RuntimeException)
{
    sal_Int32 nIndex = 0;
    Index1 >>= nIndex;
    if( ( nIndex < 1 ) || ( nIndex > 3 ) )
    {
        throw container::NoSuchElementException();
    }
    return uno::makeAny( uno::Reference< word::XHeaderFooter >( new SwVbaHeaderFooter( this,  mxContext, mxModel, mxPageStyleProps, mbHeader, nIndex ) ) );
}

// XEnumerationAccess
uno::Type
SwVbaHeadersFooters::getElementType() throw (uno::RuntimeException)
{
    return cppu::UnoType<word::XHeaderFooter>::get();
}
uno::Reference< container::XEnumeration >

SwVbaHeadersFooters::createEnumeration() throw (uno::RuntimeException)
{
    return new HeadersFootersEnumWrapper( this );
}

uno::Any
SwVbaHeadersFooters::createCollectionObject( const uno::Any& aSource )
{
    return aSource;
}

OUString
SwVbaHeadersFooters::getServiceImplName()
{
    return OUString("SwVbaHeadersFooters");
}

uno::Sequence<OUString>
SwVbaHeadersFooters::getServiceNames()
{
    static uno::Sequence< OUString > sNames;
    if ( sNames.getLength() == 0 )
    {
        sNames.realloc( 1 );
        sNames[0] = "ooo.vba.word.HeadersFooters";
    }
    return sNames;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>coverity#738454 Uncaught exception<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */
#include "vbaheadersfooters.hxx"
#include "vbaheaderfooter.hxx"
#include <ooo/vba/word/WdHeaderFooterIndex.hpp>

using namespace ::ooo::vba;
using namespace ::com::sun::star;

// I assume there is only one headersfooters in Writer
typedef ::cppu::WeakImplHelper1<container::XIndexAccess > HeadersFootersIndexAccess_Base;
class HeadersFootersIndexAccess : public HeadersFootersIndexAccess_Base
{
private:
    uno::Reference< XHelperInterface > mxParent;
    uno::Reference< uno::XComponentContext > mxContext;
    uno::Reference< frame::XModel > mxModel;
    uno::Reference< beans::XPropertySet > mxPageStyleProps;
    bool mbHeader;

public:
    HeadersFootersIndexAccess( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< frame::XModel >& xModel, const uno::Reference< beans::XPropertySet >& xPageStyleProps, bool bHeader ) : mxParent( xParent ), mxContext( xContext ), mxModel( xModel ), mxPageStyleProps( xPageStyleProps ), mbHeader( bHeader ) {}
    virtual ~HeadersFootersIndexAccess(){}

    // XIndexAccess
    virtual sal_Int32 SAL_CALL getCount(  ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
    {
        // first page, evenpages and primary page
        return 3;
    }
    virtual uno::Any SAL_CALL getByIndex( sal_Int32 Index ) throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
    {
        if( Index < 1 || Index > 3 )
            throw lang::IndexOutOfBoundsException();
        return uno::makeAny( uno::Reference< word::XHeaderFooter >( new SwVbaHeaderFooter( mxParent,  mxContext, mxModel, mxPageStyleProps, mbHeader, Index ) ) );
    }
    virtual uno::Type SAL_CALL getElementType(  ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
    {
        return cppu::UnoType<word::XHeaderFooter>::get();
    }
    virtual sal_Bool SAL_CALL hasElements(  ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
    {
        return sal_True;
    }
};

class HeadersFootersEnumWrapper : public EnumerationHelper_BASE
{
    SwVbaHeadersFooters* pHeadersFooters;
    sal_Int32 nIndex;
public:
    HeadersFootersEnumWrapper( SwVbaHeadersFooters* _pHeadersFooters ) : pHeadersFooters( _pHeadersFooters ), nIndex( 0 ) {}
    virtual sal_Bool SAL_CALL hasMoreElements(  ) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
    {
        return ( nIndex < pHeadersFooters->getCount() );
    }

    virtual uno::Any SAL_CALL nextElement(  ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
    {
        if ( nIndex < pHeadersFooters->getCount() )
            return pHeadersFooters->Item( uno::makeAny( ++nIndex ), uno::Any() );
        throw container::NoSuchElementException();
    }
};

SwVbaHeadersFooters::SwVbaHeadersFooters( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext > & xContext, const uno::Reference< frame::XModel >& xModel, const uno::Reference< beans::XPropertySet >& xPageStyleProps, bool isHeader ): SwVbaHeadersFooters_BASE( xParent, xContext, new HeadersFootersIndexAccess( xParent, xContext, xModel, xPageStyleProps, isHeader ) ),  mxModel( xModel ), mxPageStyleProps( xPageStyleProps ), mbHeader( isHeader )
{
}

::sal_Int32 SAL_CALL SwVbaHeadersFooters::getCount() throw (uno::RuntimeException)
{
    // wdHeaderFooterFirstPage, wdHeaderFooterPrimary and wdHeaderFooterEvenPages
    return 3;
}

uno::Any SAL_CALL SwVbaHeadersFooters::Item( const uno::Any& Index1, const uno::Any& ) throw (uno::RuntimeException)
{
    sal_Int32 nIndex = 0;
    Index1 >>= nIndex;
    if( ( nIndex < 1 ) || ( nIndex > 3 ) )
    {
        throw container::NoSuchElementException();
    }
    return uno::makeAny( uno::Reference< word::XHeaderFooter >( new SwVbaHeaderFooter( this,  mxContext, mxModel, mxPageStyleProps, mbHeader, nIndex ) ) );
}

// XEnumerationAccess
uno::Type
SwVbaHeadersFooters::getElementType() throw (uno::RuntimeException)
{
    return cppu::UnoType<word::XHeaderFooter>::get();
}
uno::Reference< container::XEnumeration >

SwVbaHeadersFooters::createEnumeration() throw (uno::RuntimeException)
{
    return new HeadersFootersEnumWrapper( this );
}

uno::Any
SwVbaHeadersFooters::createCollectionObject( const uno::Any& aSource )
{
    return aSource;
}

OUString
SwVbaHeadersFooters::getServiceImplName()
{
    return OUString("SwVbaHeadersFooters");
}

uno::Sequence<OUString>
SwVbaHeadersFooters::getServiceNames()
{
    static uno::Sequence< OUString > sNames;
    if ( sNames.getLength() == 0 )
    {
        sNames.realloc( 1 );
        sNames[0] = "ooo.vba.word.HeadersFooters";
    }
    return sNames;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/system_wrappers/source/thread_posix.h"

#include <algorithm>

#include <errno.h>
#include <unistd.h>
#ifdef WEBRTC_LINUX
#include <linux/unistd.h>
#include <sched.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <sys/types.h>
#endif

#include "webrtc/base/checks.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/sleep.h"
#include "webrtc/system_wrappers/interface/trace.h"

namespace webrtc {
namespace {
struct ThreadAttributes {
  ThreadAttributes() { pthread_attr_init(&attr); }
  ~ThreadAttributes() { pthread_attr_destroy(&attr); }
  pthread_attr_t* operator&() { return &attr; }
  pthread_attr_t attr;
};
}  // namespace

int ConvertToSystemPriority(ThreadPriority priority, int min_prio,
                            int max_prio) {
  DCHECK(max_prio - min_prio > 2);
  const int top_prio = max_prio - 1;
  const int low_prio = min_prio + 1;

  switch (priority) {
    case kLowPriority:
      return low_prio;
    case kNormalPriority:
      // The -1 ensures that the kHighPriority is always greater or equal to
      // kNormalPriority.
      return (low_prio + top_prio - 1) / 2;
    case kHighPriority:
      return std::max(top_prio - 2, low_prio);
    case kHighestPriority:
      return std::max(top_prio - 1, low_prio);
    case kRealtimePriority:
      return top_prio;
  }
  DCHECK(false);
  return low_prio;
}

// static
void* ThreadPosix::StartThread(void* param) {
  static_cast<ThreadPosix*>(param)->Run();
  return 0;
}

ThreadPosix::ThreadPosix(ThreadRunFunction func, void* obj,
                         const char* thread_name)
    : run_function_(func),
      obj_(obj),
      stop_event_(false, false),
      name_(thread_name ? thread_name : "webrtc"),
      thread_(0) {
  DCHECK(name_.length() < 64);
}

uint32_t ThreadWrapper::GetThreadId() {
  return rtc::CurrentThreadId();
}

ThreadPosix::~ThreadPosix() {
  DCHECK(thread_checker_.CalledOnValidThread());
}

// TODO(pbos): Make Start void, calling code really doesn't support failures
// here.
bool ThreadPosix::Start() {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!thread_) << "Thread already started?";

  ThreadAttributes attr;
  // Set the stack stack size to 1M.
  pthread_attr_setstacksize(&attr, 1024 * 1024);
  CHECK_EQ(0, pthread_create(&thread_, &attr, &StartThread, this));
  return true;
}

bool ThreadPosix::Stop() {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!thread_)
    return true;

  stop_event_.Set();
  CHECK_EQ(0, pthread_join(thread_, nullptr));
  thread_ = 0;

  return true;
}

bool ThreadPosix::SetPriority(ThreadPriority priority) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!thread_)
    return false;

#ifdef WEBRTC_THREAD_RR
  const int policy = SCHED_RR;
#else
  const int policy = SCHED_FIFO;
#endif
  const int min_prio = sched_get_priority_min(policy);
  const int max_prio = sched_get_priority_max(policy);
  if (min_prio == -1 || max_prio == -1) {
    WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
                 "unable to retreive min or max priority for threads");
    return false;
  }

  if (max_prio - min_prio <= 2)
    return false;

  sched_param param;
  param.sched_priority = ConvertToSystemPriority(priority, min_prio, max_prio);
  if (pthread_setschedparam(thread_, policy, &param) != 0) {
    WEBRTC_TRACE(
        kTraceError, kTraceUtility, -1, "unable to set thread priority");
    return false;
  }

  return true;
}

void ThreadPosix::Run() {
  if (!name_.empty()) {
    // Setting the thread name may fail (harmlessly) if running inside a
    // sandbox. Ignore failures if they happen.
#if defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
    prctl(PR_SET_NAME, reinterpret_cast<unsigned long>(name_.c_str()));
#elif defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
    pthread_setname_np(name_.substr(0, 63).c_str());
#endif
  }

  // It's a requirement that for successful thread creation that the run
  // function be called at least once (see RunFunctionIsCalled unit test),
  // so to fullfill that requirement, we use a |do| loop and not |while|.
  do {
    if (!run_function_(obj_))
      break;
  } while (!stop_event_.Wait(0));
}

}  // namespace webrtc
<commit_msg>Temporarily disable SetPriority when building with Chromium. This is due to errors we were hitting with Chromium's sandbox policy for pthread_setschedparam.<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/system_wrappers/source/thread_posix.h"

#include <algorithm>

#include <errno.h>
#include <unistd.h>
#ifdef WEBRTC_LINUX
#include <linux/unistd.h>
#include <sched.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <sys/types.h>
#endif

#include "webrtc/base/checks.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/sleep.h"
#include "webrtc/system_wrappers/interface/trace.h"

namespace webrtc {
namespace {
struct ThreadAttributes {
  ThreadAttributes() { pthread_attr_init(&attr); }
  ~ThreadAttributes() { pthread_attr_destroy(&attr); }
  pthread_attr_t* operator&() { return &attr; }
  pthread_attr_t attr;
};
}  // namespace

int ConvertToSystemPriority(ThreadPriority priority, int min_prio,
                            int max_prio) {
  DCHECK(max_prio - min_prio > 2);
  const int top_prio = max_prio - 1;
  const int low_prio = min_prio + 1;

  switch (priority) {
    case kLowPriority:
      return low_prio;
    case kNormalPriority:
      // The -1 ensures that the kHighPriority is always greater or equal to
      // kNormalPriority.
      return (low_prio + top_prio - 1) / 2;
    case kHighPriority:
      return std::max(top_prio - 2, low_prio);
    case kHighestPriority:
      return std::max(top_prio - 1, low_prio);
    case kRealtimePriority:
      return top_prio;
  }
  DCHECK(false);
  return low_prio;
}

// static
void* ThreadPosix::StartThread(void* param) {
  static_cast<ThreadPosix*>(param)->Run();
  return 0;
}

ThreadPosix::ThreadPosix(ThreadRunFunction func, void* obj,
                         const char* thread_name)
    : run_function_(func),
      obj_(obj),
      stop_event_(false, false),
      name_(thread_name ? thread_name : "webrtc"),
      thread_(0) {
  DCHECK(name_.length() < 64);
}

uint32_t ThreadWrapper::GetThreadId() {
  return rtc::CurrentThreadId();
}

ThreadPosix::~ThreadPosix() {
  DCHECK(thread_checker_.CalledOnValidThread());
}

// TODO(pbos): Make Start void, calling code really doesn't support failures
// here.
bool ThreadPosix::Start() {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!thread_) << "Thread already started?";

  ThreadAttributes attr;
  // Set the stack stack size to 1M.
  pthread_attr_setstacksize(&attr, 1024 * 1024);
  CHECK_EQ(0, pthread_create(&thread_, &attr, &StartThread, this));
  return true;
}

bool ThreadPosix::Stop() {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!thread_)
    return true;

  stop_event_.Set();
  CHECK_EQ(0, pthread_join(thread_, nullptr));
  thread_ = 0;

  return true;
}

bool ThreadPosix::SetPriority(ThreadPriority priority) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!thread_)
    return false;
#if defined(WEBRTC_CHROMIUM_BUILD)
  // TODO(tommi): Switch to the same mechanism as Chromium uses for
  // changing thread priorities.
  return true;
#else
#ifdef WEBRTC_THREAD_RR
  const int policy = SCHED_RR;
#else
  const int policy = SCHED_FIFO;
#endif
  const int min_prio = sched_get_priority_min(policy);
  const int max_prio = sched_get_priority_max(policy);
  if (min_prio == -1 || max_prio == -1) {
    WEBRTC_TRACE(kTraceError, kTraceUtility, -1,
                 "unable to retreive min or max priority for threads");
    return false;
  }

  if (max_prio - min_prio <= 2)
    return false;

  sched_param param;
  param.sched_priority = ConvertToSystemPriority(priority, min_prio, max_prio);
  if (pthread_setschedparam(thread_, policy, &param) != 0) {
    WEBRTC_TRACE(
        kTraceError, kTraceUtility, -1, "unable to set thread priority");
    return false;
  }

  return true;
#endif  // defined(WEBRTC_CHROMIUM_BUILD)
}

void ThreadPosix::Run() {
  if (!name_.empty()) {
    // Setting the thread name may fail (harmlessly) if running inside a
    // sandbox. Ignore failures if they happen.
#if defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
    prctl(PR_SET_NAME, reinterpret_cast<unsigned long>(name_.c_str()));
#elif defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
    pthread_setname_np(name_.substr(0, 63).c_str());
#endif
  }

  // It's a requirement that for successful thread creation that the run
  // function be called at least once (see RunFunctionIsCalled unit test),
  // so to fullfill that requirement, we use a |do| loop and not |while|.
  do {
    if (!run_function_(obj_))
      break;
  } while (!stop_event_.Wait(0));
}

}  // namespace webrtc
<|endoftext|>


<commit_before>//*
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include "RPNCalc.h"
#include "RPNTestHelper.h"

using namespace P4_RPNCALC;

TEST_CASE("Operation Methods")
{
	RPNTestHelper test;

	SECTION("Sanity Tests") {
		for (int n = 0; n < 100; n++) {
			REQUIRE(test.expectedOutput(n, n));
		}
	}

	SECTION("Method: clearAll()")
	{
		REQUIRE(test.expectedOutput("50", "50"));
		REQUIRE(test.expectedOutput("c", ""));
		REQUIRE(test.expectedOutput("50 100 +", "150"));
		REQUIRE(test.expectedOutput("c", ""));
		REQUIRE(test.expectedOutput("50 100 + 200", "200"));
		REQUIRE(test.expectedOutput("c", ""));
		REQUIRE(test.expectedOutput("50", "50"));
		REQUIRE(test.expectedOutput("C", ""));
		REQUIRE(test.expectedOutput("50 100 +", "150"));
		REQUIRE(test.expectedOutput("C", ""));
		REQUIRE(test.expectedOutput("50 100 + 200", "200"));
		REQUIRE(test.getOutput("C") == "");
	}

	/*
	SECTION("Method: clearEntry()")
	{
		REQUIRE(test.expectedInputOutput("50", "50"));
		REQUIRE(test.expectedInputOutput("ce", ""));
		REQUIRE(test.expectedInputOutput("50 100 +", "150"));
		REQUIRE(test.expectedInputOutput("ce", ""));
		REQUIRE(test.expectedInputOutput("50 100 + 200", "200"));
		REQUIRE(test.expectedInputOutput("ce", "150"));
		REQUIRE(test.expectedInputOutput("ce", ""));
		REQUIRE(test.expectedInputOutput("50", "50"));
		REQUIRE(test.expectedInputOutput("CE", ""));
		REQUIRE(test.expectedInputOutput("50 100 +", "150"));
		REQUIRE(test.expectedInputOutput("CE", ""));
		REQUIRE(test.expectedInputOutput("50 100 + 200", "200"));
		REQUIRE(test.expectedInputOutput("CE", "150"));
		REQUIRE(test.expectedInputOutput("CE", ""));
	}

	SECTION("Method: add()")
	{
		REQUIRE(test.expectedInputOutput("3 5 +", "8"));
		REQUIRE(test.expectedInputOutput("2 4 3 +", "7"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("3 4 + 6", "6"));
		REQUIRE(test.expectedInputOutput("4 +", "10"));
		REQUIRE(test.expectedInputOutput("-12 +", "-2"));
		REQUIRE(test.expectedInputOutput("5 +", "3"));
		REQUIRE(test.expectedInputOutput("3 +", "6"));
		REQUIRE(test.expectedInputOutput("10 100 +", "110"));
		REQUIRE(test.expectedInputOutput("10 100+", "110"));
		REQUIRE(test.expectedInputOutput("+", "<<error>>"));
	}

	SECTION("Method: combinations of add() & subtract()")
	{
		REQUIRE(test.expectedInputOutput("4.4 5.5 + 60 -", "-50.1"));
		REQUIRE(test.expectedInputOutput("4.4 5.5 - 60 +", "58.9"));
		REQUIRE(test.expectedInputOutput("40 50 + 60 -", "30"));
		REQUIRE(test.expectedInputOutput("40 50 - 60 +", "50"));
		REQUIRE(test.expectedInputOutput("40 50 60 + -", "-70"));
		REQUIRE(test.expectedInputOutput("40 50 60 - +", "30"));
		REQUIRE(test.expectedInputOutput("-40 -50 + 60 -", "-150"));
		REQUIRE(test.expectedInputOutput("-40 -50 + -60 -", "-30"));
		REQUIRE(test.expectedInputOutput("-40 -50 - 60 +", "70"));
		REQUIRE(test.expectedInputOutput("-40 -50 - -60 +", "-50"));
	}

	SECTION("Method: subtract()")
	{
		REQUIRE(test.expectedInputOutput("5 6 -", "-1"));
		REQUIRE(test.expectedInputOutput("3 9 4 -", "5"));
		REQUIRE(test.expectedInputOutput("-", "-2"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("-1 5 -", "-6"));
		REQUIRE(test.expectedInputOutput("10 100 -", "-90"));
		REQUIRE(test.expectedInputOutput("10 100-", "-90"));
		REQUIRE(test.expectedInputOutput("-", "<<error>>"));
	}

	SECTION("Method: multiply()")
	{
		REQUIRE(test.expectedInputOutput("3 9 7 2 4 *", "8"));
		REQUIRE(test.expectedInputOutput("*", "56"));
		REQUIRE(test.expectedInputOutput("*", "504"));
		REQUIRE(test.expectedInputOutput("*", "1512"));
		REQUIRE(test.expectedInputOutput("*", "<<error>>"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("-4 -6 *", "24"));
		REQUIRE(test.expectedInputOutput("-2 *", "-48"));
		REQUIRE(test.expectedInputOutput("10 100 *", "1000"));
		REQUIRE(test.expectedInputOutput("10 100*", "1000"));
		REQUIRE(test.expectedInputOutput("5.5 2.2*", "12.1"));
	}

	SECTION("Method: divide()")
	{
		REQUIRE(test.expectedInputOutput("16 4 2 /", "2"));
		REQUIRE(test.expectedInputOutput("/", "8"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("2 5 /", "0.4"));
		REQUIRE(test.expectedInputOutput("9 3 7 /", "0.428571"));
		REQUIRE(test.expectedInputOutput("-1 /", "-0.428571"));
		REQUIRE(test.expectedInputOutput("-1 / ", "0.428571"));
		REQUIRE(test.expectedInputOutput("100 10 /", "10"));
		REQUIRE(test.expectedInputOutput("100 10/", "10"));
		REQUIRE(test.expectedInputOutput("/", "<<error>>"));
	}

	SECTION("Method: mod()")
	{
		REQUIRE(test.expectedInputOutput("16 8 6 %", "2"));
		REQUIRE(test.expectedInputOutput("%", "0"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("%", "<<error>>"));
		REQUIRE(test.expectedInputOutput("10 1 %", "0"));
		REQUIRE(test.expectedInputOutput("10 2 %", "0"));
		REQUIRE(test.expectedInputOutput("10 3 %", "1"));
		REQUIRE(test.expectedInputOutput("10 4 %", "2"));
		REQUIRE(test.expectedInputOutput("10 5 %", "0"));
		REQUIRE(test.expectedInputOutput("10 6 %", "4"));
		REQUIRE(test.expectedInputOutput("10 7 %", "3"));
		REQUIRE(test.expectedInputOutput("10 8 %", "2"));
		REQUIRE(test.expectedInputOutput("10 9 %", "1"));
		REQUIRE(test.expectedInputOutput("10 10 %", "0"));
		REQUIRE(test.expectedInputOutput("100 70 %", "30"));
		REQUIRE(test.expectedInputOutput("100 70%", "30"));
	}

	SECTION("Method: exp()")
	{
		REQUIRE(test.expectedInputOutput("10 2 ^", "100"));
		REQUIRE(test.expectedInputOutput("10 2 2 ^", "4"));
		REQUIRE(test.expectedInputOutput("^", "10000"));
		REQUIRE(test.expectedInputOutput("-10 2 ^", "100"));
		REQUIRE(test.expectedInputOutput("-10 3 ^", "-1000"));
		REQUIRE(test.expectedInputOutput("-10 3^", "-1000"));
		REQUIRE(test.expectedInputOutput("0^", "1"));
		REQUIRE(test.expectedInputOutput("^", "<<error>>"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("100 100^", "1e+200"));
	}

	SECTION("Method: neg()")
	{
		REQUIRE(test.expectedInputOutput("-1000", "-1000"));
		REQUIRE(test.expectedInputOutput("M", "1000"));
		REQUIRE(test.expectedInputOutput("-1000 -1*", "1000"));
		REQUIRE(test.expectedInputOutput("M", "-1000"));
		REQUIRE(test.expectedInputOutput("-4/", "-250"));
		REQUIRE(test.expectedInputOutput("m", "250"));
		REQUIRE(test.expectedInputOutput("-2*", "-500"));
		REQUIRE(test.expectedInputOutput("m", "500"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("m", "<<error>>"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("M", "<<error>>"));
	}

	SECTION("Method: rotateDown()")
	{
		REQUIRE(test.expectedInputOutput("100 200", "200"));
		REQUIRE(test.expectedInputOutput("D", "100"));
		REQUIRE(test.expectedInputOutput("D", "200"));
		REQUIRE(test.expectedInputOutput("d", "100"));
		REQUIRE(test.expectedInputOutput("d", "200"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("D", "<<error>>"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("d", "<<error>>"));
	}

	SECTION("Method: rotateUp()")
	{
		REQUIRE(test.expectedInputOutput("300 500", "500"));
		REQUIRE(test.expectedInputOutput("U", "300"));
		REQUIRE(test.expectedInputOutput("U", "500"));
		REQUIRE(test.expectedInputOutput("u", "300"));
		REQUIRE(test.expectedInputOutput("u", "500"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("U", "<<error>>"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("u", "<<error>>"));
	}

	SECTION("Methods: saveToFile(), loadProgram(), recordProgram(), runProgram()")
	{
		REQUIRE(test.expectedInputOutput("R", "<<error>>"));
		REQUIRE(test.expectedInputOutput("F", "<<error>>"));
		REQUIRE(test.expectedInputOutput("p", "0>"));
		REQUIRE(test.expectedInputOutput("5 10 +", "1>"));
		REQUIRE(test.expectedInputOutput("20 30 -", "2>"));
		//REQUIRE(test.expectedInputOutput("P", ""));
		//REQUIRE(test.expectedInputOutput("f", "Enter a filename:"));
		REQUIRE(test.expectedInputOutput("test1", ""));
		//REQUIRE(test.expectedInputOutput("l", "Enter a filename:"));
		REQUIRE(test.expectedInputOutput("test", "error"));
		//REQUIRE(test.expectedInputOutput("L", "Enter a filename:"));
		REQUIRE(test.expectedInputOutput("test1", ""));
		REQUIRE(test.expectedInputOutput("r", "-10"));
		REQUIRE(test.expectedInputOutput("c", ""));
	}

	SECTION("Methods: getReg(), setReg()")
	{
		REQUIRE(test.expectedInputOutput("s0", "<<error>>"));
		REQUIRE(test.expectedInputOutput("S1", "<<error>>"));
		REQUIRE(test.expectedInputOutput("s5", "<<error>>"));
		REQUIRE(test.expectedInputOutput("G0", "0"));
		REQUIRE(test.expectedInputOutput("g1", "0"));
		REQUIRE(test.expectedInputOutput("G5", "0"));
		REQUIRE(test.expectedInputOutput("1000", "1000"));
		REQUIRE(test.expectedInputOutput("s5", "1000"));
		REQUIRE(test.expectedInputOutput("2.5", "2.5"));
		REQUIRE(test.expectedInputOutput("S0", "2.5"));
		REQUIRE(test.expectedInputOutput("G5", "1000"));
		REQUIRE(test.expectedInputOutput("g0", "2.5"));
	}
	//*/
}
//*/<commit_msg>rework tests with new methods<commit_after>//*
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include "RPNCalc.h"
#include "RPNTestHelper.h"

using namespace P4_RPNCALC;

TEST_CASE("Operation Methods")
{
	RPNTestHelper test;

	SECTION("Sanity Tests") {
		for (int n = 0; n < 100; n++) {
			REQUIRE(test.expectedStackOutput(to_string(n), to_string(n)));
		}
	}

	SECTION("Method: clearAll()")
	{
		REQUIRE(test.expectedStackOutput("50", "50"));
		REQUIRE(test.expectedOutput("c", ""));
		REQUIRE(test.expectedStackOutput("50 100 +", "150"));
		REQUIRE(test.expectedOutput("c", ""));
		REQUIRE(test.expectedStackOutput("50 100 + 200", "200"));
		REQUIRE(test.expectedOutput("c", ""));
		REQUIRE(test.expectedStackOutput("50", "50"));
		REQUIRE(test.expectedOutput("C", ""));
		REQUIRE(test.expectedStackOutput("50 100 +", "150"));
		REQUIRE(test.expectedOutput("C", ""));
		REQUIRE(test.expectedStackOutput("50 100 + 200", "200"));
		REQUIRE(test.expectedOutput("C", ""));
	}

	/*
	SECTION("Method: clearEntry()")
	{
		REQUIRE(test.expectedInputOutput("50", "50"));
		REQUIRE(test.expectedInputOutput("ce", ""));
		REQUIRE(test.expectedInputOutput("50 100 +", "150"));
		REQUIRE(test.expectedInputOutput("ce", ""));
		REQUIRE(test.expectedInputOutput("50 100 + 200", "200"));
		REQUIRE(test.expectedInputOutput("ce", "150"));
		REQUIRE(test.expectedInputOutput("ce", ""));
		REQUIRE(test.expectedInputOutput("50", "50"));
		REQUIRE(test.expectedInputOutput("CE", ""));
		REQUIRE(test.expectedInputOutput("50 100 +", "150"));
		REQUIRE(test.expectedInputOutput("CE", ""));
		REQUIRE(test.expectedInputOutput("50 100 + 200", "200"));
		REQUIRE(test.expectedInputOutput("CE", "150"));
		REQUIRE(test.expectedInputOutput("CE", ""));
	}

	SECTION("Method: add()")
	{
		REQUIRE(test.expectedInputOutput("3 5 +", "8"));
		REQUIRE(test.expectedInputOutput("2 4 3 +", "7"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("3 4 + 6", "6"));
		REQUIRE(test.expectedInputOutput("4 +", "10"));
		REQUIRE(test.expectedInputOutput("-12 +", "-2"));
		REQUIRE(test.expectedInputOutput("5 +", "3"));
		REQUIRE(test.expectedInputOutput("3 +", "6"));
		REQUIRE(test.expectedInputOutput("10 100 +", "110"));
		REQUIRE(test.expectedInputOutput("10 100+", "110"));
		REQUIRE(test.expectedInputOutput("+", "<<error>>"));
	}

	SECTION("Method: combinations of add() & subtract()")
	{
		REQUIRE(test.expectedInputOutput("4.4 5.5 + 60 -", "-50.1"));
		REQUIRE(test.expectedInputOutput("4.4 5.5 - 60 +", "58.9"));
		REQUIRE(test.expectedInputOutput("40 50 + 60 -", "30"));
		REQUIRE(test.expectedInputOutput("40 50 - 60 +", "50"));
		REQUIRE(test.expectedInputOutput("40 50 60 + -", "-70"));
		REQUIRE(test.expectedInputOutput("40 50 60 - +", "30"));
		REQUIRE(test.expectedInputOutput("-40 -50 + 60 -", "-150"));
		REQUIRE(test.expectedInputOutput("-40 -50 + -60 -", "-30"));
		REQUIRE(test.expectedInputOutput("-40 -50 - 60 +", "70"));
		REQUIRE(test.expectedInputOutput("-40 -50 - -60 +", "-50"));
	}

	SECTION("Method: subtract()")
	{
		REQUIRE(test.expectedInputOutput("5 6 -", "-1"));
		REQUIRE(test.expectedInputOutput("3 9 4 -", "5"));
		REQUIRE(test.expectedInputOutput("-", "-2"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("-1 5 -", "-6"));
		REQUIRE(test.expectedInputOutput("10 100 -", "-90"));
		REQUIRE(test.expectedInputOutput("10 100-", "-90"));
		REQUIRE(test.expectedInputOutput("-", "<<error>>"));
	}

	SECTION("Method: multiply()")
	{
		REQUIRE(test.expectedInputOutput("3 9 7 2 4 *", "8"));
		REQUIRE(test.expectedInputOutput("*", "56"));
		REQUIRE(test.expectedInputOutput("*", "504"));
		REQUIRE(test.expectedInputOutput("*", "1512"));
		REQUIRE(test.expectedInputOutput("*", "<<error>>"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("-4 -6 *", "24"));
		REQUIRE(test.expectedInputOutput("-2 *", "-48"));
		REQUIRE(test.expectedInputOutput("10 100 *", "1000"));
		REQUIRE(test.expectedInputOutput("10 100*", "1000"));
		REQUIRE(test.expectedInputOutput("5.5 2.2*", "12.1"));
	}

	SECTION("Method: divide()")
	{
		REQUIRE(test.expectedInputOutput("16 4 2 /", "2"));
		REQUIRE(test.expectedInputOutput("/", "8"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("2 5 /", "0.4"));
		REQUIRE(test.expectedInputOutput("9 3 7 /", "0.428571"));
		REQUIRE(test.expectedInputOutput("-1 /", "-0.428571"));
		REQUIRE(test.expectedInputOutput("-1 / ", "0.428571"));
		REQUIRE(test.expectedInputOutput("100 10 /", "10"));
		REQUIRE(test.expectedInputOutput("100 10/", "10"));
		REQUIRE(test.expectedInputOutput("/", "<<error>>"));
	}

	SECTION("Method: mod()")
	{
		REQUIRE(test.expectedInputOutput("16 8 6 %", "2"));
		REQUIRE(test.expectedInputOutput("%", "0"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("%", "<<error>>"));
		REQUIRE(test.expectedInputOutput("10 1 %", "0"));
		REQUIRE(test.expectedInputOutput("10 2 %", "0"));
		REQUIRE(test.expectedInputOutput("10 3 %", "1"));
		REQUIRE(test.expectedInputOutput("10 4 %", "2"));
		REQUIRE(test.expectedInputOutput("10 5 %", "0"));
		REQUIRE(test.expectedInputOutput("10 6 %", "4"));
		REQUIRE(test.expectedInputOutput("10 7 %", "3"));
		REQUIRE(test.expectedInputOutput("10 8 %", "2"));
		REQUIRE(test.expectedInputOutput("10 9 %", "1"));
		REQUIRE(test.expectedInputOutput("10 10 %", "0"));
		REQUIRE(test.expectedInputOutput("100 70 %", "30"));
		REQUIRE(test.expectedInputOutput("100 70%", "30"));
	}

	SECTION("Method: exp()")
	{
		REQUIRE(test.expectedInputOutput("10 2 ^", "100"));
		REQUIRE(test.expectedInputOutput("10 2 2 ^", "4"));
		REQUIRE(test.expectedInputOutput("^", "10000"));
		REQUIRE(test.expectedInputOutput("-10 2 ^", "100"));
		REQUIRE(test.expectedInputOutput("-10 3 ^", "-1000"));
		REQUIRE(test.expectedInputOutput("-10 3^", "-1000"));
		REQUIRE(test.expectedInputOutput("0^", "1"));
		REQUIRE(test.expectedInputOutput("^", "<<error>>"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("100 100^", "1e+200"));
	}

	SECTION("Method: neg()")
	{
		REQUIRE(test.expectedInputOutput("-1000", "-1000"));
		REQUIRE(test.expectedInputOutput("M", "1000"));
		REQUIRE(test.expectedInputOutput("-1000 -1*", "1000"));
		REQUIRE(test.expectedInputOutput("M", "-1000"));
		REQUIRE(test.expectedInputOutput("-4/", "-250"));
		REQUIRE(test.expectedInputOutput("m", "250"));
		REQUIRE(test.expectedInputOutput("-2*", "-500"));
		REQUIRE(test.expectedInputOutput("m", "500"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("m", "<<error>>"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("M", "<<error>>"));
	}

	SECTION("Method: rotateDown()")
	{
		REQUIRE(test.expectedInputOutput("100 200", "200"));
		REQUIRE(test.expectedInputOutput("D", "100"));
		REQUIRE(test.expectedInputOutput("D", "200"));
		REQUIRE(test.expectedInputOutput("d", "100"));
		REQUIRE(test.expectedInputOutput("d", "200"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("D", "<<error>>"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("d", "<<error>>"));
	}

	SECTION("Method: rotateUp()")
	{
		REQUIRE(test.expectedInputOutput("300 500", "500"));
		REQUIRE(test.expectedInputOutput("U", "300"));
		REQUIRE(test.expectedInputOutput("U", "500"));
		REQUIRE(test.expectedInputOutput("u", "300"));
		REQUIRE(test.expectedInputOutput("u", "500"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("U", "<<error>>"));
		REQUIRE(test.expectedInputOutput("c", ""));
		REQUIRE(test.expectedInputOutput("u", "<<error>>"));
	}

	SECTION("Methods: saveToFile(), loadProgram(), recordProgram(), runProgram()")
	{
		REQUIRE(test.expectedInputOutput("R", "<<error>>"));
		REQUIRE(test.expectedInputOutput("F", "<<error>>"));
		REQUIRE(test.expectedInputOutput("p", "0>"));
		REQUIRE(test.expectedInputOutput("5 10 +", "1>"));
		REQUIRE(test.expectedInputOutput("20 30 -", "2>"));
		//REQUIRE(test.expectedInputOutput("P", ""));
		//REQUIRE(test.expectedInputOutput("f", "Enter a filename:"));
		REQUIRE(test.expectedInputOutput("test1", ""));
		//REQUIRE(test.expectedInputOutput("l", "Enter a filename:"));
		REQUIRE(test.expectedInputOutput("test", "error"));
		//REQUIRE(test.expectedInputOutput("L", "Enter a filename:"));
		REQUIRE(test.expectedInputOutput("test1", ""));
		REQUIRE(test.expectedInputOutput("r", "-10"));
		REQUIRE(test.expectedInputOutput("c", ""));
	}

	SECTION("Methods: getReg(), setReg()")
	{
		REQUIRE(test.expectedInputOutput("s0", "<<error>>"));
		REQUIRE(test.expectedInputOutput("S1", "<<error>>"));
		REQUIRE(test.expectedInputOutput("s5", "<<error>>"));
		REQUIRE(test.expectedInputOutput("G0", "0"));
		REQUIRE(test.expectedInputOutput("g1", "0"));
		REQUIRE(test.expectedInputOutput("G5", "0"));
		REQUIRE(test.expectedInputOutput("1000", "1000"));
		REQUIRE(test.expectedInputOutput("s5", "1000"));
		REQUIRE(test.expectedInputOutput("2.5", "2.5"));
		REQUIRE(test.expectedInputOutput("S0", "2.5"));
		REQUIRE(test.expectedInputOutput("G5", "1000"));
		REQUIRE(test.expectedInputOutput("g0", "2.5"));
	}
	//*/
}
//*/<|endoftext|>