<commit_before>//===-- MipsTargetMachine.cpp - Define TargetMachine for Mips -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Implements the info about Mips target spec.
//
//===----------------------------------------------------------------------===//

#include "MipsTargetMachine.h"
#include "Mips.h"
#include "Mips16FrameLowering.h"
#include "Mips16HardFloat.h"
#include "Mips16ISelDAGToDAG.h"
#include "Mips16ISelLowering.h"
#include "Mips16InstrInfo.h"
#include "MipsFrameLowering.h"
#include "MipsInstrInfo.h"
#include "MipsModuleISelDAGToDAG.h"
#include "MipsOs16.h"
#include "MipsSEFrameLowering.h"
#include "MipsSEISelDAGToDAG.h"
#include "MipsSEISelLowering.h"
#include "MipsSEInstrInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/PassManager.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Scalar.h"
using namespace llvm;

#define DEBUG_TYPE "mips"

extern "C" void LLVMInitializeMipsTarget() {
  // Register the target.
  RegisterTargetMachine<MipsebTargetMachine> X(TheMipsTarget);
  RegisterTargetMachine<MipselTargetMachine> Y(TheMipselTarget);
  RegisterTargetMachine<MipsebTargetMachine> A(TheMips64Target);
  RegisterTargetMachine<MipselTargetMachine> B(TheMips64elTarget);
}

// On function prologue, the stack is created by decrementing
// its pointer. Once decremented, all references are done with positive
// offset from the stack/frame pointer, using StackGrowsUp enables
// an easier handling.
// Using CodeModel::Large enables different CALL behavior.
MipsTargetMachine::MipsTargetMachine(const Target &T, StringRef TT,
                                     StringRef CPU, StringRef FS,
                                     const TargetOptions &Options,
                                     Reloc::Model RM, CodeModel::Model CM,
                                     CodeGenOpt::Level OL, bool isLittle)
    : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
      isLittle(isLittle), Subtarget(nullptr),
      DefaultSubtarget(TT, CPU, FS, isLittle, this),
      NoMips16Subtarget(TT, CPU, FS.empty() ? "-mips16" : FS.str() + ",-mips16",
                        isLittle, this),
      Mips16Subtarget(TT, CPU, FS.empty() ? "+mips16" : FS.str() + ",+mips16",
                      isLittle, this) {
  Subtarget = &DefaultSubtarget;
  initAsmInfo();
}

void MipsebTargetMachine::anchor() { }

MipsebTargetMachine::
MipsebTargetMachine(const Target &T, StringRef TT,
                    StringRef CPU, StringRef FS, const TargetOptions &Options,
                    Reloc::Model RM, CodeModel::Model CM,
                    CodeGenOpt::Level OL)
  : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}

void MipselTargetMachine::anchor() { }

MipselTargetMachine::
MipselTargetMachine(const Target &T, StringRef TT,
                    StringRef CPU, StringRef FS, const TargetOptions &Options,
                    Reloc::Model RM, CodeModel::Model CM,
                    CodeGenOpt::Level OL)
  : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}

const MipsSubtarget *
MipsTargetMachine::getSubtargetImpl(const Function &F) const {
  AttributeSet FnAttrs = F.getAttributes();
  Attribute CPUAttr =
      FnAttrs.getAttribute(AttributeSet::FunctionIndex, "target-cpu");
  Attribute FSAttr =
      FnAttrs.getAttribute(AttributeSet::FunctionIndex, "target-features");

  std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
                        ? CPUAttr.getValueAsString().str()
                        : TargetCPU;
  std::string FS = !FSAttr.hasAttribute(Attribute::None)
                       ? FSAttr.getValueAsString().str()
                       : TargetFS;
  bool hasMips16Attr =
      !FnAttrs.getAttribute(AttributeSet::FunctionIndex, "mips16")
           .hasAttribute(Attribute::None);
  bool hasNoMips16Attr =
      !FnAttrs.getAttribute(AttributeSet::FunctionIndex, "nomips16")
           .hasAttribute(Attribute::None);

  if (hasMips16Attr)
    FS += FS.empty() ? "+mips16" : ",+mips16";
  else if (hasNoMips16Attr)
    FS += FS.empty() ? "-mips16" : ",-mips16";

  auto &I = SubtargetMap[CPU + FS];
  if (!I) {
    // This needs to be done before we create a new subtarget since any
    // creation will depend on the TM and the code generation flags on the
    // function that reside in TargetOptions.
    resetTargetOptions(F);
    I = make_unique<MipsSubtarget>(TargetTriple, CPU, FS, isLittle, this);
  }
  return I.get();
}

void MipsTargetMachine::resetSubtarget(MachineFunction *MF) {
  DEBUG(dbgs() << "resetSubtarget\n");

  Subtarget = const_cast<MipsSubtarget *>(getSubtargetImpl(*MF->getFunction()));
  MF->setSubtarget(Subtarget);
  return;
}

namespace {
/// Mips Code Generator Pass Configuration Options.
class MipsPassConfig : public TargetPassConfig {
public:
  MipsPassConfig(MipsTargetMachine *TM, PassManagerBase &PM)
    : TargetPassConfig(TM, PM) {
    // The current implementation of long branch pass requires a scratch
    // register ($at) to be available before branch instructions. Tail merging
    // can break this requirement, so disable it when long branch pass is
    // enabled.
    EnableTailMerge = !getMipsSubtarget().enableLongBranchPass();
  }

  MipsTargetMachine &getMipsTargetMachine() const {
    return getTM<MipsTargetMachine>();
  }

  const MipsSubtarget &getMipsSubtarget() const {
    return *getMipsTargetMachine().getSubtargetImpl();
  }

  void addIRPasses() override;
  bool addInstSelector() override;
  void addMachineSSAOptimization() override;
  bool addPreEmitPass() override;

  bool addPreRegAlloc() override;

};
} // namespace

TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) {
  return new MipsPassConfig(this, PM);
}

void MipsPassConfig::addIRPasses() {
  TargetPassConfig::addIRPasses();
  if (getMipsSubtarget().os16())
    addPass(createMipsOs16(getMipsTargetMachine()));
  if (getMipsSubtarget().inMips16HardFloat())
    addPass(createMips16HardFloat(getMipsTargetMachine()));
}
// Install an instruction selector pass using
// the ISelDag to gen Mips code.
bool MipsPassConfig::addInstSelector() {
  addPass(createMipsModuleISelDag(getMipsTargetMachine()));
  addPass(createMips16ISelDag(getMipsTargetMachine()));
  addPass(createMipsSEISelDag(getMipsTargetMachine()));
  return false;
}

void MipsPassConfig::addMachineSSAOptimization() {
  addPass(createMipsOptimizePICCallPass(getMipsTargetMachine()));
  TargetPassConfig::addMachineSSAOptimization();
}

bool MipsPassConfig::addPreRegAlloc() {
  if (getOptLevel() == CodeGenOpt::None) {
    addPass(createMipsOptimizePICCallPass(getMipsTargetMachine()));
    return true;
  }
  else
    return false;
}

void MipsTargetMachine::addAnalysisPasses(PassManagerBase &PM) {
  if (Subtarget->allowMixed16_32()) {
    DEBUG(errs() << "No ");
    //FIXME: The Basic Target Transform Info
    // pass needs to become a function pass instead of
    // being an immutable pass and then this method as it exists now
    // would be unnecessary.
    PM.add(createNoTargetTransformInfoPass());
  } else
    LLVMTargetMachine::addAnalysisPasses(PM);
  DEBUG(errs() << "Target Transform Info Pass Added\n");
}

// Implemented by targets that want to run passes immediately before
// machine code is emitted. return true if -print-machineinstrs should
// print out the code after the passes.
bool MipsPassConfig::addPreEmitPass() {
  MipsTargetMachine &TM = getMipsTargetMachine();
  addPass(createMipsDelaySlotFillerPass(TM));
  addPass(createMipsLongBranchPass(TM));
  addPass(createMipsConstantIslandPass(TM));
  return true;
}
<commit_msg>Fix build breakage on MSVC 2013<commit_after>//===-- MipsTargetMachine.cpp - Define TargetMachine for Mips -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Implements the info about Mips target spec.
//
//===----------------------------------------------------------------------===//

#include "MipsTargetMachine.h"
#include "Mips.h"
#include "Mips16FrameLowering.h"
#include "Mips16HardFloat.h"
#include "Mips16ISelDAGToDAG.h"
#include "Mips16ISelLowering.h"
#include "Mips16InstrInfo.h"
#include "MipsFrameLowering.h"
#include "MipsInstrInfo.h"
#include "MipsModuleISelDAGToDAG.h"
#include "MipsOs16.h"
#include "MipsSEFrameLowering.h"
#include "MipsSEISelDAGToDAG.h"
#include "MipsSEISelLowering.h"
#include "MipsSEInstrInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/PassManager.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Scalar.h"
using namespace llvm;

#define DEBUG_TYPE "mips"

extern "C" void LLVMInitializeMipsTarget() {
  // Register the target.
  RegisterTargetMachine<MipsebTargetMachine> X(TheMipsTarget);
  RegisterTargetMachine<MipselTargetMachine> Y(TheMipselTarget);
  RegisterTargetMachine<MipsebTargetMachine> A(TheMips64Target);
  RegisterTargetMachine<MipselTargetMachine> B(TheMips64elTarget);
}

// On function prologue, the stack is created by decrementing
// its pointer. Once decremented, all references are done with positive
// offset from the stack/frame pointer, using StackGrowsUp enables
// an easier handling.
// Using CodeModel::Large enables different CALL behavior.
MipsTargetMachine::MipsTargetMachine(const Target &T, StringRef TT,
                                     StringRef CPU, StringRef FS,
                                     const TargetOptions &Options,
                                     Reloc::Model RM, CodeModel::Model CM,
                                     CodeGenOpt::Level OL, bool isLittle)
    : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
      isLittle(isLittle), Subtarget(nullptr),
      DefaultSubtarget(TT, CPU, FS, isLittle, this),
      NoMips16Subtarget(TT, CPU, FS.empty() ? "-mips16" : FS.str() + ",-mips16",
                        isLittle, this),
      Mips16Subtarget(TT, CPU, FS.empty() ? "+mips16" : FS.str() + ",+mips16",
                      isLittle, this) {
  Subtarget = &DefaultSubtarget;
  initAsmInfo();
}

void MipsebTargetMachine::anchor() { }

MipsebTargetMachine::
MipsebTargetMachine(const Target &T, StringRef TT,
                    StringRef CPU, StringRef FS, const TargetOptions &Options,
                    Reloc::Model RM, CodeModel::Model CM,
                    CodeGenOpt::Level OL)
  : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}

void MipselTargetMachine::anchor() { }

MipselTargetMachine::
MipselTargetMachine(const Target &T, StringRef TT,
                    StringRef CPU, StringRef FS, const TargetOptions &Options,
                    Reloc::Model RM, CodeModel::Model CM,
                    CodeGenOpt::Level OL)
  : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}

const MipsSubtarget *
MipsTargetMachine::getSubtargetImpl(const Function &F) const {
  AttributeSet FnAttrs = F.getAttributes();
  Attribute CPUAttr =
      FnAttrs.getAttribute(AttributeSet::FunctionIndex, "target-cpu");
  Attribute FSAttr =
      FnAttrs.getAttribute(AttributeSet::FunctionIndex, "target-features");

  std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
                        ? CPUAttr.getValueAsString().str()
                        : TargetCPU;
  std::string FS = !FSAttr.hasAttribute(Attribute::None)
                       ? FSAttr.getValueAsString().str()
                       : TargetFS;
  bool hasMips16Attr =
      !FnAttrs.getAttribute(AttributeSet::FunctionIndex, "mips16")
           .hasAttribute(Attribute::None);
  bool hasNoMips16Attr =
      !FnAttrs.getAttribute(AttributeSet::FunctionIndex, "nomips16")
           .hasAttribute(Attribute::None);

  if (hasMips16Attr)
    FS += FS.empty() ? "+mips16" : ",+mips16";
  else if (hasNoMips16Attr)
    FS += FS.empty() ? "-mips16" : ",-mips16";

  auto &I = SubtargetMap[CPU + FS];
  if (!I) {
    // This needs to be done before we create a new subtarget since any
    // creation will depend on the TM and the code generation flags on the
    // function that reside in TargetOptions.
    resetTargetOptions(F);
    I = llvm::make_unique<MipsSubtarget>(TargetTriple, CPU, FS, isLittle, this);
  }
  return I.get();
}

void MipsTargetMachine::resetSubtarget(MachineFunction *MF) {
  DEBUG(dbgs() << "resetSubtarget\n");

  Subtarget = const_cast<MipsSubtarget *>(getSubtargetImpl(*MF->getFunction()));
  MF->setSubtarget(Subtarget);
  return;
}

namespace {
/// Mips Code Generator Pass Configuration Options.
class MipsPassConfig : public TargetPassConfig {
public:
  MipsPassConfig(MipsTargetMachine *TM, PassManagerBase &PM)
    : TargetPassConfig(TM, PM) {
    // The current implementation of long branch pass requires a scratch
    // register ($at) to be available before branch instructions. Tail merging
    // can break this requirement, so disable it when long branch pass is
    // enabled.
    EnableTailMerge = !getMipsSubtarget().enableLongBranchPass();
  }

  MipsTargetMachine &getMipsTargetMachine() const {
    return getTM<MipsTargetMachine>();
  }

  const MipsSubtarget &getMipsSubtarget() const {
    return *getMipsTargetMachine().getSubtargetImpl();
  }

  void addIRPasses() override;
  bool addInstSelector() override;
  void addMachineSSAOptimization() override;
  bool addPreEmitPass() override;

  bool addPreRegAlloc() override;

};
} // namespace

TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) {
  return new MipsPassConfig(this, PM);
}

void MipsPassConfig::addIRPasses() {
  TargetPassConfig::addIRPasses();
  if (getMipsSubtarget().os16())
    addPass(createMipsOs16(getMipsTargetMachine()));
  if (getMipsSubtarget().inMips16HardFloat())
    addPass(createMips16HardFloat(getMipsTargetMachine()));
}
// Install an instruction selector pass using
// the ISelDag to gen Mips code.
bool MipsPassConfig::addInstSelector() {
  addPass(createMipsModuleISelDag(getMipsTargetMachine()));
  addPass(createMips16ISelDag(getMipsTargetMachine()));
  addPass(createMipsSEISelDag(getMipsTargetMachine()));
  return false;
}

void MipsPassConfig::addMachineSSAOptimization() {
  addPass(createMipsOptimizePICCallPass(getMipsTargetMachine()));
  TargetPassConfig::addMachineSSAOptimization();
}

bool MipsPassConfig::addPreRegAlloc() {
  if (getOptLevel() == CodeGenOpt::None) {
    addPass(createMipsOptimizePICCallPass(getMipsTargetMachine()));
    return true;
  }
  else
    return false;
}

void MipsTargetMachine::addAnalysisPasses(PassManagerBase &PM) {
  if (Subtarget->allowMixed16_32()) {
    DEBUG(errs() << "No ");
    //FIXME: The Basic Target Transform Info
    // pass needs to become a function pass instead of
    // being an immutable pass and then this method as it exists now
    // would be unnecessary.
    PM.add(createNoTargetTransformInfoPass());
  } else
    LLVMTargetMachine::addAnalysisPasses(PM);
  DEBUG(errs() << "Target Transform Info Pass Added\n");
}

// Implemented by targets that want to run passes immediately before
// machine code is emitted. return true if -print-machineinstrs should
// print out the code after the passes.
bool MipsPassConfig::addPreEmitPass() {
  MipsTargetMachine &TM = getMipsTargetMachine();
  addPass(createMipsDelaySlotFillerPass(TM));
  addPass(createMipsLongBranchPass(TM));
  addPass(createMipsConstantIslandPass(TM));
  return true;
}
<|endoftext|>


<commit_before>//===-- PPCCodeEmitter.cpp - JIT Code Emitter for PowerPC32 -------*- C++ -*-=//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the PowerPC 32-bit CodeEmitter and associated machinery to
// JIT-compile bytecode to native PowerPC.
//
//===----------------------------------------------------------------------===//

#include "PPCTargetMachine.h"
#include "PPCRelocations.h"
#include "PPC.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/CodeGen/MachineCodeEmitter.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Support/Debug.h"
using namespace llvm;

namespace {
  class PPCCodeEmitter : public MachineFunctionPass {
    TargetMachine &TM;
    MachineCodeEmitter &MCE;

    // Tracks which instruction references which BasicBlock
    std::vector<std::pair<MachineBasicBlock*, unsigned*> > BBRefs;
    // Tracks where each BasicBlock starts
    std::map<MachineBasicBlock*, long> BBLocations;

    /// getMachineOpValue - evaluates the MachineOperand of a given MachineInstr
    ///
    int getMachineOpValue(MachineInstr &MI, MachineOperand &MO);

  public:
    PPCCodeEmitter(TargetMachine &T, MachineCodeEmitter &M)
      : TM(T), MCE(M) {}

    const char *getPassName() const { return "PowerPC Machine Code Emitter"; }

    /// runOnMachineFunction - emits the given MachineFunction to memory
    ///
    bool runOnMachineFunction(MachineFunction &MF);

    /// emitBasicBlock - emits the given MachineBasicBlock to memory
    ///
    void emitBasicBlock(MachineBasicBlock &MBB);

    /// emitWord - write a 32-bit word to memory at the current PC
    ///
    void emitWord(unsigned w) { MCE.emitWord(w); }

    /// getValueBit - return the particular bit of Val
    ///
    unsigned getValueBit(int64_t Val, unsigned bit) { return (Val >> bit) & 1; }

    /// getBinaryCodeForInstr - This function, generated by the
    /// CodeEmitterGenerator using TableGen, produces the binary encoding for
    /// machine instructions.
    ///
    unsigned getBinaryCodeForInstr(MachineInstr &MI);
  };
}

/// addPassesToEmitMachineCode - Add passes to the specified pass manager to get
/// machine code emitted.  This uses a MachineCodeEmitter object to handle
/// actually outputting the machine code and resolving things like the address
/// of functions.  This method should returns true if machine code emission is
/// not supported.
///
bool PPCTargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
                                                  MachineCodeEmitter &MCE) {
  // Machine code emitter pass for PowerPC
  PM.add(new PPCCodeEmitter(*this, MCE));
  // Delete machine code for this function after emitting it
  PM.add(createMachineCodeDeleter());
  return false;
}

bool PPCCodeEmitter::runOnMachineFunction(MachineFunction &MF) {
  MCE.startFunction(MF);
  MCE.emitConstantPool(MF.getConstantPool());
  for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB)
    emitBasicBlock(*BB);
  MCE.finishFunction(MF);

  // Resolve branches to BasicBlocks for the entire function
  for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) {
    intptr_t Location = BBLocations[BBRefs[i].first];
    unsigned *Ref = BBRefs[i].second;
    DEBUG(std::cerr << "Fixup @ " << (void*)Ref << " to " << (void*)Location
                    << "\n");
    unsigned Instr = *Ref;
    intptr_t BranchTargetDisp = (Location - (intptr_t)Ref) >> 2;

    switch (Instr >> 26) {
    default: assert(0 && "Unknown branch user!");
    case 18:  // This is B or BL
      *Ref |= (BranchTargetDisp & ((1 << 24)-1)) << 2;
      break;
    case 16:  // This is BLT,BLE,BEQ,BGE,BGT,BNE, or other bcx instruction
      *Ref |= (BranchTargetDisp & ((1 << 14)-1)) << 2;
      break;
    }
  }
  BBRefs.clear();
  BBLocations.clear();

  return false;
}

void PPCCodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) {
  assert(!PICEnabled && "CodeEmitter does not support PIC!");
  BBLocations[&MBB] = MCE.getCurrentPCValue();
  for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I){
    MachineInstr &MI = *I;
    unsigned Opcode = MI.getOpcode();
    switch (MI.getOpcode()) {
    default:
      emitWord(getBinaryCodeForInstr(*I));
      break;
    case PPC::IMPLICIT_DEF_GPR:
    case PPC::IMPLICIT_DEF_F8:
    case PPC::IMPLICIT_DEF_F4:
      break; // pseudo opcode, no side effects
    case PPC::MovePCtoLR:
      assert(0 && "CodeEmitter does not support MovePCtoLR instruction");
      break;
    }
  }
}

static unsigned enumRegToMachineReg(unsigned enumReg) {
  switch (enumReg) {
  case PPC::R0 :  case PPC::F0 :  case PPC::CR0:  return  0;
  case PPC::R1 :  case PPC::F1 :  case PPC::CR1:  return  1;
  case PPC::R2 :  case PPC::F2 :  case PPC::CR2:  return  2;
  case PPC::R3 :  case PPC::F3 :  case PPC::CR3:  return  3;
  case PPC::R4 :  case PPC::F4 :  case PPC::CR4:  return  4;
  case PPC::R5 :  case PPC::F5 :  case PPC::CR5:  return  5;
  case PPC::R6 :  case PPC::F6 :  case PPC::CR6:  return  6;
  case PPC::R7 :  case PPC::F7 :  case PPC::CR7:  return  7;
  case PPC::R8 :  case PPC::F8 :  return  8;
  case PPC::R9 :  case PPC::F9 :  return  9;
  case PPC::R10:  case PPC::F10:  return 10;
  case PPC::R11:  case PPC::F11:  return 11;
  case PPC::R12:  case PPC::F12:  return 12;
  case PPC::R13:  case PPC::F13:  return 13;
  case PPC::R14:  case PPC::F14:  return 14;
  case PPC::R15:  case PPC::F15:  return 15;
  case PPC::R16:  case PPC::F16:  return 16;
  case PPC::R17:  case PPC::F17:  return 17;
  case PPC::R18:  case PPC::F18:  return 18;
  case PPC::R19:  case PPC::F19:  return 19;
  case PPC::R20:  case PPC::F20:  return 20;
  case PPC::R21:  case PPC::F21:  return 21;
  case PPC::R22:  case PPC::F22:  return 22;
  case PPC::R23:  case PPC::F23:  return 23;
  case PPC::R24:  case PPC::F24:  return 24;
  case PPC::R25:  case PPC::F25:  return 25;
  case PPC::R26:  case PPC::F26:  return 26;
  case PPC::R27:  case PPC::F27:  return 27;
  case PPC::R28:  case PPC::F28:  return 28;
  case PPC::R29:  case PPC::F29:  return 29;
  case PPC::R30:  case PPC::F30:  return 30;
  case PPC::R31:  case PPC::F31:  return 31;
  default:
    std::cerr << "Unhandled reg in enumRegToRealReg!\n";
    abort();
  }
}

int PPCCodeEmitter::getMachineOpValue(MachineInstr &MI, MachineOperand &MO) {

  int rv = 0; // Return value; defaults to 0 for unhandled cases
                  // or things that get fixed up later by the JIT.
  if (MO.isRegister()) {
    rv = enumRegToMachineReg(MO.getReg());

    // Special encoding for MTCRF and MFOCRF, which uses a bit mask for the
    // register, not the register number directly.
    if ((MI.getOpcode() == PPC::MTCRF || MI.getOpcode() == PPC::MFOCRF) &&
        (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7)) {
      rv = 0x80 >> rv;
    }
  } else if (MO.isImmediate()) {
    rv = MO.getImmedValue();
  } else if (MO.isGlobalAddress() || MO.isExternalSymbol()) {
    bool isExternal = MO.isExternalSymbol() ||
                      MO.getGlobal()->hasWeakLinkage() ||
                      MO.getGlobal()->isExternal();
    unsigned Reloc = 0;
    if (MI.getOpcode() == PPC::BL)
      Reloc = PPC::reloc_pcrel_bx;
    else {
      switch (MI.getOpcode()) {
      default: MI.dump(); assert(0 && "Unknown instruction for relocation!");
      case PPC::LIS:
        if (isExternal)
          Reloc = PPC::reloc_absolute_ptr_high;   // Pointer to stub
        else
          Reloc = PPC::reloc_absolute_high;       // Pointer to symbol
        break;
      case PPC::LA:
        assert(!isExternal && "Something in the ISEL changed\n");
        Reloc = PPC::reloc_absolute_low;
        break;
      case PPC::LBZ:
      case PPC::LHA:
      case PPC::LHZ:
      case PPC::LWZ:
      case PPC::LFS:
      case PPC::LFD:
      case PPC::STB:
      case PPC::STH:
      case PPC::STW:
      case PPC::STFS:
      case PPC::STFD:
        if (isExternal)
          Reloc = PPC::reloc_absolute_ptr_low;
        else
          Reloc = PPC::reloc_absolute_low;
        break;
      }
    }
    if (MO.isGlobalAddress())
      MCE.addRelocation(MachineRelocation(MCE.getCurrentPCOffset(),
                                          Reloc, MO.getGlobal(), 0));
    else
      MCE.addRelocation(MachineRelocation(MCE.getCurrentPCOffset(),
                                          Reloc, MO.getSymbolName(), 0));
  } else if (MO.isMachineBasicBlock()) {
    unsigned* CurrPC = (unsigned*)(intptr_t)MCE.getCurrentPCValue();
    BBRefs.push_back(std::make_pair(MO.getMachineBasicBlock(), CurrPC));
  } else if (MO.isConstantPoolIndex()) {
    unsigned index = MO.getConstantPoolIndex();
    unsigned Opcode = MI.getOpcode();
    rv = MCE.getConstantPoolEntryAddress(index);
    if (Opcode == PPC::LIS || Opcode == PPC::ADDIS) {
      // lis wants hi16(addr)
      if ((short)rv < 0) rv += 1 << 16;
      rv >>= 16;
    } else if (Opcode == PPC::LWZ || Opcode == PPC::LA ||
               Opcode == PPC::LI ||
               Opcode == PPC::LFS || Opcode == PPC::LFD) {
      // These load opcodes want lo16(addr)
      rv &= 0xffff;
    } else {
      assert(0 && "Unknown constant pool using instruction!");
    }
  } else {
    std::cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n";
    abort();
  }

  return rv;
}

#include "PPCGenCodeEmitter.inc"

<commit_msg>Fix the PPC JIT failures last night, which were due to mishandling of linkonce globals<commit_after>//===-- PPCCodeEmitter.cpp - JIT Code Emitter for PowerPC32 -------*- C++ -*-=//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the PowerPC 32-bit CodeEmitter and associated machinery to
// JIT-compile bytecode to native PowerPC.
//
//===----------------------------------------------------------------------===//

#include "PPCTargetMachine.h"
#include "PPCRelocations.h"
#include "PPC.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/CodeGen/MachineCodeEmitter.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Support/Debug.h"
using namespace llvm;

namespace {
  class PPCCodeEmitter : public MachineFunctionPass {
    TargetMachine &TM;
    MachineCodeEmitter &MCE;

    // Tracks which instruction references which BasicBlock
    std::vector<std::pair<MachineBasicBlock*, unsigned*> > BBRefs;
    // Tracks where each BasicBlock starts
    std::map<MachineBasicBlock*, long> BBLocations;

    /// getMachineOpValue - evaluates the MachineOperand of a given MachineInstr
    ///
    int getMachineOpValue(MachineInstr &MI, MachineOperand &MO);

  public:
    PPCCodeEmitter(TargetMachine &T, MachineCodeEmitter &M)
      : TM(T), MCE(M) {}

    const char *getPassName() const { return "PowerPC Machine Code Emitter"; }

    /// runOnMachineFunction - emits the given MachineFunction to memory
    ///
    bool runOnMachineFunction(MachineFunction &MF);

    /// emitBasicBlock - emits the given MachineBasicBlock to memory
    ///
    void emitBasicBlock(MachineBasicBlock &MBB);

    /// emitWord - write a 32-bit word to memory at the current PC
    ///
    void emitWord(unsigned w) { MCE.emitWord(w); }

    /// getValueBit - return the particular bit of Val
    ///
    unsigned getValueBit(int64_t Val, unsigned bit) { return (Val >> bit) & 1; }

    /// getBinaryCodeForInstr - This function, generated by the
    /// CodeEmitterGenerator using TableGen, produces the binary encoding for
    /// machine instructions.
    ///
    unsigned getBinaryCodeForInstr(MachineInstr &MI);
  };
}

/// addPassesToEmitMachineCode - Add passes to the specified pass manager to get
/// machine code emitted.  This uses a MachineCodeEmitter object to handle
/// actually outputting the machine code and resolving things like the address
/// of functions.  This method should returns true if machine code emission is
/// not supported.
///
bool PPCTargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
                                                  MachineCodeEmitter &MCE) {
  // Machine code emitter pass for PowerPC
  PM.add(new PPCCodeEmitter(*this, MCE));
  // Delete machine code for this function after emitting it
  PM.add(createMachineCodeDeleter());
  return false;
}

bool PPCCodeEmitter::runOnMachineFunction(MachineFunction &MF) {
  MCE.startFunction(MF);
  MCE.emitConstantPool(MF.getConstantPool());
  for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB)
    emitBasicBlock(*BB);
  MCE.finishFunction(MF);

  // Resolve branches to BasicBlocks for the entire function
  for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) {
    intptr_t Location = BBLocations[BBRefs[i].first];
    unsigned *Ref = BBRefs[i].second;
    DEBUG(std::cerr << "Fixup @ " << (void*)Ref << " to " << (void*)Location
                    << "\n");
    unsigned Instr = *Ref;
    intptr_t BranchTargetDisp = (Location - (intptr_t)Ref) >> 2;

    switch (Instr >> 26) {
    default: assert(0 && "Unknown branch user!");
    case 18:  // This is B or BL
      *Ref |= (BranchTargetDisp & ((1 << 24)-1)) << 2;
      break;
    case 16:  // This is BLT,BLE,BEQ,BGE,BGT,BNE, or other bcx instruction
      *Ref |= (BranchTargetDisp & ((1 << 14)-1)) << 2;
      break;
    }
  }
  BBRefs.clear();
  BBLocations.clear();

  return false;
}

void PPCCodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) {
  assert(!PICEnabled && "CodeEmitter does not support PIC!");
  BBLocations[&MBB] = MCE.getCurrentPCValue();
  for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I){
    MachineInstr &MI = *I;
    unsigned Opcode = MI.getOpcode();
    switch (MI.getOpcode()) {
    default:
      emitWord(getBinaryCodeForInstr(*I));
      break;
    case PPC::IMPLICIT_DEF_GPR:
    case PPC::IMPLICIT_DEF_F8:
    case PPC::IMPLICIT_DEF_F4:
      break; // pseudo opcode, no side effects
    case PPC::MovePCtoLR:
      assert(0 && "CodeEmitter does not support MovePCtoLR instruction");
      break;
    }
  }
}

static unsigned enumRegToMachineReg(unsigned enumReg) {
  switch (enumReg) {
  case PPC::R0 :  case PPC::F0 :  case PPC::CR0:  return  0;
  case PPC::R1 :  case PPC::F1 :  case PPC::CR1:  return  1;
  case PPC::R2 :  case PPC::F2 :  case PPC::CR2:  return  2;
  case PPC::R3 :  case PPC::F3 :  case PPC::CR3:  return  3;
  case PPC::R4 :  case PPC::F4 :  case PPC::CR4:  return  4;
  case PPC::R5 :  case PPC::F5 :  case PPC::CR5:  return  5;
  case PPC::R6 :  case PPC::F6 :  case PPC::CR6:  return  6;
  case PPC::R7 :  case PPC::F7 :  case PPC::CR7:  return  7;
  case PPC::R8 :  case PPC::F8 :  return  8;
  case PPC::R9 :  case PPC::F9 :  return  9;
  case PPC::R10:  case PPC::F10:  return 10;
  case PPC::R11:  case PPC::F11:  return 11;
  case PPC::R12:  case PPC::F12:  return 12;
  case PPC::R13:  case PPC::F13:  return 13;
  case PPC::R14:  case PPC::F14:  return 14;
  case PPC::R15:  case PPC::F15:  return 15;
  case PPC::R16:  case PPC::F16:  return 16;
  case PPC::R17:  case PPC::F17:  return 17;
  case PPC::R18:  case PPC::F18:  return 18;
  case PPC::R19:  case PPC::F19:  return 19;
  case PPC::R20:  case PPC::F20:  return 20;
  case PPC::R21:  case PPC::F21:  return 21;
  case PPC::R22:  case PPC::F22:  return 22;
  case PPC::R23:  case PPC::F23:  return 23;
  case PPC::R24:  case PPC::F24:  return 24;
  case PPC::R25:  case PPC::F25:  return 25;
  case PPC::R26:  case PPC::F26:  return 26;
  case PPC::R27:  case PPC::F27:  return 27;
  case PPC::R28:  case PPC::F28:  return 28;
  case PPC::R29:  case PPC::F29:  return 29;
  case PPC::R30:  case PPC::F30:  return 30;
  case PPC::R31:  case PPC::F31:  return 31;
  default:
    std::cerr << "Unhandled reg in enumRegToRealReg!\n";
    abort();
  }
}

int PPCCodeEmitter::getMachineOpValue(MachineInstr &MI, MachineOperand &MO) {

  int rv = 0; // Return value; defaults to 0 for unhandled cases
                  // or things that get fixed up later by the JIT.
  if (MO.isRegister()) {
    rv = enumRegToMachineReg(MO.getReg());

    // Special encoding for MTCRF and MFOCRF, which uses a bit mask for the
    // register, not the register number directly.
    if ((MI.getOpcode() == PPC::MTCRF || MI.getOpcode() == PPC::MFOCRF) &&
        (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7)) {
      rv = 0x80 >> rv;
    }
  } else if (MO.isImmediate()) {
    rv = MO.getImmedValue();
  } else if (MO.isGlobalAddress() || MO.isExternalSymbol()) {
    bool isExternal = MO.isExternalSymbol() ||
                      MO.getGlobal()->hasWeakLinkage() ||
                      MO.getGlobal()->hasLinkOnceLinkage() ||
                      MO.getGlobal()->isExternal();
    unsigned Reloc = 0;
    if (MI.getOpcode() == PPC::BL)
      Reloc = PPC::reloc_pcrel_bx;
    else {
      switch (MI.getOpcode()) {
      default: MI.dump(); assert(0 && "Unknown instruction for relocation!");
      case PPC::LIS:
        if (isExternal)
          Reloc = PPC::reloc_absolute_ptr_high;   // Pointer to stub
        else
          Reloc = PPC::reloc_absolute_high;       // Pointer to symbol
        break;
      case PPC::LA:
        assert(!isExternal && "Something in the ISEL changed\n");
        Reloc = PPC::reloc_absolute_low;
        break;
      case PPC::LBZ:
      case PPC::LHA:
      case PPC::LHZ:
      case PPC::LWZ:
      case PPC::LFS:
      case PPC::LFD:
      case PPC::STB:
      case PPC::STH:
      case PPC::STW:
      case PPC::STFS:
      case PPC::STFD:
        if (isExternal)
          Reloc = PPC::reloc_absolute_ptr_low;
        else
          Reloc = PPC::reloc_absolute_low;
        break;
      }
    }
    if (MO.isGlobalAddress())
      MCE.addRelocation(MachineRelocation(MCE.getCurrentPCOffset(),
                                          Reloc, MO.getGlobal(), 0));
    else
      MCE.addRelocation(MachineRelocation(MCE.getCurrentPCOffset(),
                                          Reloc, MO.getSymbolName(), 0));
  } else if (MO.isMachineBasicBlock()) {
    unsigned* CurrPC = (unsigned*)(intptr_t)MCE.getCurrentPCValue();
    BBRefs.push_back(std::make_pair(MO.getMachineBasicBlock(), CurrPC));
  } else if (MO.isConstantPoolIndex()) {
    unsigned index = MO.getConstantPoolIndex();
    unsigned Opcode = MI.getOpcode();
    rv = MCE.getConstantPoolEntryAddress(index);
    if (Opcode == PPC::LIS || Opcode == PPC::ADDIS) {
      // lis wants hi16(addr)
      if ((short)rv < 0) rv += 1 << 16;
      rv >>= 16;
    } else if (Opcode == PPC::LWZ || Opcode == PPC::LA ||
               Opcode == PPC::LI ||
               Opcode == PPC::LFS || Opcode == PPC::LFD) {
      // These load opcodes want lo16(addr)
      rv &= 0xffff;
    } else {
      assert(0 && "Unknown constant pool using instruction!");
    }
  } else {
    std::cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n";
    abort();
  }

  return rv;
}

#include "PPCGenCodeEmitter.inc"

<|endoftext|>


<commit_before> /*
 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
 *
 * Licensed 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// CLASS HEADER
#include <dali-toolkit/internal/visuals/npatch-loader.h>

// EXTERNAL HEADER
#include <dali/devel-api/adaptor-framework/image-loading.h>
#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
#include <dali/devel-api/common/hash.h>
#include <dali/integration-api/debug.h>

namespace Dali
{

namespace Toolkit
{

namespace Internal
{

namespace NPatchBuffer
{

void GetRedOffsetAndMask( Dali::Pixel::Format pixelFormat, int& byteOffset, int& bitMask )
{
  switch( pixelFormat )
  {
    case Dali::Pixel::A8:
    case Dali::Pixel::L8:
    case Dali::Pixel::LA88:
    {
      byteOffset = 0;
      bitMask = 0;
      break;
    }
    case Dali::Pixel::RGB888:
    case Dali::Pixel::RGB8888:
    case Dali::Pixel::RGBA8888:
    {
      byteOffset = 0;
      bitMask = 0xFF;
      break;
    }
    case Dali::Pixel::BGR8888:
    case Dali::Pixel::BGRA8888:
    {
      byteOffset = 2;
      bitMask = 0xff;
      break;
    }
    case Dali::Pixel::RGB565:
    {
      byteOffset = 0;
      bitMask = 0xf8;
      break;
    }
    case Dali::Pixel::BGR565:
    {
      byteOffset = 1;
      bitMask = 0x1f;
      break;
    }
    case Dali::Pixel::RGBA4444:
    {
      byteOffset = 0;
      bitMask = 0xf0;
      break;
    }
    case Dali::Pixel::BGRA4444:
    {
      byteOffset = 1;
      bitMask = 0xf0;
      break;
    }
    case Dali::Pixel::RGBA5551:
    {
      byteOffset = 0;
      bitMask = 0xf8;
      break;
    }
    case Dali::Pixel::BGRA5551:
    {
      byteOffset = 1;
      bitMask = 0x1e;
      break;
    }
    case Dali::Pixel::INVALID:
    case Dali::Pixel::COMPRESSED_R11_EAC:
    case Dali::Pixel::COMPRESSED_SIGNED_R11_EAC:
    case Dali::Pixel::COMPRESSED_RG11_EAC:
    case Dali::Pixel::COMPRESSED_SIGNED_RG11_EAC:
    case Dali::Pixel::COMPRESSED_RGB8_ETC2:
    case Dali::Pixel::COMPRESSED_SRGB8_ETC2:
    case Dali::Pixel::COMPRESSED_RGB8_ETC1:
    case Dali::Pixel::COMPRESSED_RGB_PVRTC_4BPPV1:
    case Dali::Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
    case Dali::Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
    case Dali::Pixel::COMPRESSED_RGBA8_ETC2_EAC:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_4x4_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x4_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x5_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x5_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x6_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x5_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x6_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x8_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x5_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x8_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x10_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x10_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x12_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
    {
      DALI_LOG_ERROR("Pixel formats for compressed images are not compatible with simple masking-out of per-pixel alpha.\n");
      byteOffset=0;
      bitMask=0;
      break;
    }
    case Dali::Pixel::RGB16F:
    case Dali::Pixel::RGB32F:
    {
      DALI_LOG_ERROR("Pixel format not compatible.\n");
      byteOffset=0;
      bitMask=0;
      break;
    }
  }
}

Uint16Pair ParseRange( unsigned int& index, unsigned int width, unsigned char* pixel, unsigned int pixelStride, int testByte, int testBits, int testValue )
{
  unsigned int start = 0xFFFF;
  for( ; index < width; ++index, pixel += pixelStride )
  {
    if( ( pixel[ testByte ] & testBits ) == testValue )
    {
        start = index;
        ++index;
        pixel += pixelStride;
        break;
    }
  }

  unsigned int end = width;
  for( ; index < width; ++index, pixel += pixelStride )
  {
    if( ( pixel[ testByte ] & testBits ) != testValue )
    {
        end = index;
        ++index;
        pixel += pixelStride;
        break;
    }
  }

  return Uint16Pair( start, end );
}

void ParseBorders( Devel::PixelBuffer& pixelBuffer, NPatchLoader::Data* data  )
{
  data->stretchPixelsX.Clear();
  data->stretchPixelsY.Clear();

  Pixel::Format pixelFormat = pixelBuffer.GetPixelFormat();

  int alphaByte = 0;
  int alphaBits = 0;
  Pixel::GetAlphaOffsetAndMask( pixelFormat, alphaByte, alphaBits );

  int testByte = alphaByte;
  int testBits = alphaBits;
  int testValue = alphaBits; // Opaque == stretch
  if( !alphaBits )
  {
    GetRedOffsetAndMask( pixelFormat, testByte, testBits );
    testValue = 0;           // Black == stretch
  }

  unsigned int bytesPerPixel = Pixel::GetBytesPerPixel( pixelFormat );
  unsigned int width = pixelBuffer.GetWidth();
  unsigned int height = pixelBuffer.GetHeight();
  unsigned char* srcPixels = pixelBuffer.GetBuffer();
  unsigned int srcStride = width * bytesPerPixel;

  // TOP
  unsigned char* top = srcPixels + bytesPerPixel;
  unsigned int index = 0;

  for( ; index < width - 2; )
  {
    Uint16Pair range = ParseRange( index, width - 2, top, bytesPerPixel, testByte, testBits, testValue );
    if( range.GetX() != 0xFFFF )
    {
      data->stretchPixelsX.PushBack( range );
    }
  }

  // LEFT
  unsigned char* left  = srcPixels + srcStride;
  index = 0;
  for( ; index < height - 2; )
  {
    Uint16Pair range = ParseRange( index, height - 2, left, srcStride, testByte, testBits, testValue );
    if( range.GetX() != 0xFFFF )
    {
      data->stretchPixelsY.PushBack( range );
    }
  }

  // If there are no stretch pixels then make the entire image stretchable
  if( data->stretchPixelsX.Size() == 0 )
  {
    data->stretchPixelsX.PushBack( Uint16Pair( 0, width - 2 ) );
  }
  if( data->stretchPixelsY.Size() == 0 )
  {
    data->stretchPixelsY.PushBack( Uint16Pair( 0, height - 2 ) );
  }
}

} // namespace NPatchBuffer

NPatchLoader::NPatchLoader()
{
}

NPatchLoader::~NPatchLoader()
{
}

std::size_t NPatchLoader::Load( const std::string& url, const Rect< int >& border, bool& preMultiplyOnLoad )
{
  std::size_t hash = CalculateHash( url );
  OwnerContainer< Data* >::SizeType index = UNINITIALIZED_ID;
  const OwnerContainer< Data* >::SizeType count = mCache.Count();
  int cachedIndex = -1;

  for( ; index < count; ++index )
  {
    if( mCache[ index ]->hash == hash )
    {
      // hash match, check url as well in case of hash collision
      if( mCache[ index ]->url == url )
      {
        // Use cached data
        if( mCache[ index ]->border == border )
        {
          return index+1u; // valid indices are from 1 onwards
        }
        else
        {
          cachedIndex = index;
        }
      }
    }
  }

  if( cachedIndex != -1 )
  {
    // Same url but border is different - use the existing texture
    Data* data = new Data();
    data->hash = hash;
    data->url = url;
    data->croppedWidth = mCache[ cachedIndex ]->croppedWidth;
    data->croppedHeight = mCache[ cachedIndex ]->croppedHeight;

    data->textureSet = mCache[ cachedIndex ]->textureSet;

    StretchRanges stretchRangesX;
    stretchRangesX.PushBack( Uint16Pair( border.left, ( (data->croppedWidth >= static_cast< unsigned int >( border.right )) ? data->croppedWidth - border.right : 0 ) ) );

    StretchRanges stretchRangesY;
    stretchRangesY.PushBack( Uint16Pair( border.top, ( (data->croppedHeight >= static_cast< unsigned int >( border.bottom )) ? data->croppedHeight - border.bottom : 0 ) ) );

    data->stretchPixelsX = stretchRangesX;
    data->stretchPixelsY = stretchRangesY;
    data->border = border;

    mCache.PushBack( data );

    return mCache.Count(); // valid ids start from 1u
  }

  // got to the end so no match, decode N patch and append new item to cache
  Devel::PixelBuffer pixelBuffer = Dali::LoadImageFromFile( url, ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, true );
  if( pixelBuffer )
  {
    Data* data = new Data();
    data->hash = hash;
    data->url = url;

    if( border == Rect< int >( 0, 0, 0, 0 ) )
    {
      NPatchBuffer::ParseBorders( pixelBuffer, data );

      data->border = Rect< int >( 0, 0, 0, 0 );

      // Crop the image
      pixelBuffer.Crop( 1, 1, pixelBuffer.GetWidth() - 2, pixelBuffer.GetHeight() - 2 );
    }
    else
    {
      data->stretchPixelsX.PushBack( Uint16Pair( border.left, ( (pixelBuffer.GetWidth() >= static_cast< unsigned int >( border.right )) ? pixelBuffer.GetWidth() - border.right : 0 ) ) );
      data->stretchPixelsY.PushBack( Uint16Pair( border.top, ( (pixelBuffer.GetHeight() >= static_cast< unsigned int >( border.bottom )) ? pixelBuffer.GetHeight() - border.bottom : 0 ) ) );
      data->border = border;
    }

    data->croppedWidth = pixelBuffer.GetWidth();
    data->croppedHeight = pixelBuffer.GetHeight();

    if( preMultiplyOnLoad && Pixel::HasAlpha( pixelBuffer.GetPixelFormat() ) )
    {
      pixelBuffer.MultiplyColorByAlpha();
    }
    else
    {
      preMultiplyOnLoad = false;
    }

    PixelData pixels = Devel::PixelBuffer::Convert( pixelBuffer ); // takes ownership of buffer

    Texture texture = Texture::New( TextureType::TEXTURE_2D, pixels.GetPixelFormat(), pixels.GetWidth(), pixels.GetHeight() );
    texture.Upload( pixels );

    data->textureSet = TextureSet::New();
    data->textureSet.SetTexture( 0u, texture );

    mCache.PushBack( data );

    return mCache.Count(); // valid ids start from 1u
  }

  return 0u;
}

bool NPatchLoader::GetNPatchData( std::size_t id, const Data*& data )
{
  if( ( id > UNINITIALIZED_ID )&&( id <= mCache.Count() ) )
  {
    data = mCache[ id - 1u ]; // id's start from 1u
    return true;
  }
  data = NULL;
  return false;
}

} // namespace Internal

} // namespace Toolkit

} // namespace Dali
<commit_msg>Fix npatch loader issue<commit_after> /*
 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
 *
 * Licensed 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// CLASS HEADER
#include <dali-toolkit/internal/visuals/npatch-loader.h>

// EXTERNAL HEADER
#include <dali/devel-api/adaptor-framework/image-loading.h>
#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
#include <dali/devel-api/common/hash.h>
#include <dali/integration-api/debug.h>

namespace Dali
{

namespace Toolkit
{

namespace Internal
{

namespace NPatchBuffer
{

void GetRedOffsetAndMask( Dali::Pixel::Format pixelFormat, int& byteOffset, int& bitMask )
{
  switch( pixelFormat )
  {
    case Dali::Pixel::A8:
    case Dali::Pixel::L8:
    case Dali::Pixel::LA88:
    {
      byteOffset = 0;
      bitMask = 0;
      break;
    }
    case Dali::Pixel::RGB888:
    case Dali::Pixel::RGB8888:
    case Dali::Pixel::RGBA8888:
    {
      byteOffset = 0;
      bitMask = 0xFF;
      break;
    }
    case Dali::Pixel::BGR8888:
    case Dali::Pixel::BGRA8888:
    {
      byteOffset = 2;
      bitMask = 0xff;
      break;
    }
    case Dali::Pixel::RGB565:
    {
      byteOffset = 0;
      bitMask = 0xf8;
      break;
    }
    case Dali::Pixel::BGR565:
    {
      byteOffset = 1;
      bitMask = 0x1f;
      break;
    }
    case Dali::Pixel::RGBA4444:
    {
      byteOffset = 0;
      bitMask = 0xf0;
      break;
    }
    case Dali::Pixel::BGRA4444:
    {
      byteOffset = 1;
      bitMask = 0xf0;
      break;
    }
    case Dali::Pixel::RGBA5551:
    {
      byteOffset = 0;
      bitMask = 0xf8;
      break;
    }
    case Dali::Pixel::BGRA5551:
    {
      byteOffset = 1;
      bitMask = 0x1e;
      break;
    }
    case Dali::Pixel::INVALID:
    case Dali::Pixel::COMPRESSED_R11_EAC:
    case Dali::Pixel::COMPRESSED_SIGNED_R11_EAC:
    case Dali::Pixel::COMPRESSED_RG11_EAC:
    case Dali::Pixel::COMPRESSED_SIGNED_RG11_EAC:
    case Dali::Pixel::COMPRESSED_RGB8_ETC2:
    case Dali::Pixel::COMPRESSED_SRGB8_ETC2:
    case Dali::Pixel::COMPRESSED_RGB8_ETC1:
    case Dali::Pixel::COMPRESSED_RGB_PVRTC_4BPPV1:
    case Dali::Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
    case Dali::Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
    case Dali::Pixel::COMPRESSED_RGBA8_ETC2_EAC:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_4x4_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x4_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x5_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x5_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x6_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x5_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x6_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x8_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x5_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x8_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x10_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x10_KHR:
    case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x12_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
    {
      DALI_LOG_ERROR("Pixel formats for compressed images are not compatible with simple masking-out of per-pixel alpha.\n");
      byteOffset=0;
      bitMask=0;
      break;
    }
    case Dali::Pixel::RGB16F:
    case Dali::Pixel::RGB32F:
    {
      DALI_LOG_ERROR("Pixel format not compatible.\n");
      byteOffset=0;
      bitMask=0;
      break;
    }
  }
}

Uint16Pair ParseRange( unsigned int& index, unsigned int width, unsigned char*& pixel, unsigned int pixelStride, int testByte, int testBits, int testValue )
{
  unsigned int start = 0xFFFF;
  for( ; index < width; ++index, pixel += pixelStride )
  {
    if( ( pixel[ testByte ] & testBits ) == testValue )
    {
        start = index;
        ++index;
        pixel += pixelStride;
        break;
    }
  }

  unsigned int end = width;
  for( ; index < width; ++index, pixel += pixelStride )
  {
    if( ( pixel[ testByte ] & testBits ) != testValue )
    {
        end = index;
        ++index;
        pixel += pixelStride;
        break;
    }
  }

  return Uint16Pair( start, end );
}

void ParseBorders( Devel::PixelBuffer& pixelBuffer, NPatchLoader::Data* data  )
{
  data->stretchPixelsX.Clear();
  data->stretchPixelsY.Clear();

  Pixel::Format pixelFormat = pixelBuffer.GetPixelFormat();

  int alphaByte = 0;
  int alphaBits = 0;
  Pixel::GetAlphaOffsetAndMask( pixelFormat, alphaByte, alphaBits );

  int testByte = alphaByte;
  int testBits = alphaBits;
  int testValue = alphaBits; // Opaque == stretch
  if( !alphaBits )
  {
    GetRedOffsetAndMask( pixelFormat, testByte, testBits );
    testValue = 0;           // Black == stretch
  }

  unsigned int bytesPerPixel = Pixel::GetBytesPerPixel( pixelFormat );
  unsigned int width = pixelBuffer.GetWidth();
  unsigned int height = pixelBuffer.GetHeight();
  unsigned char* srcPixels = pixelBuffer.GetBuffer();
  unsigned int srcStride = width * bytesPerPixel;

  // TOP
  unsigned char* top = srcPixels + bytesPerPixel;
  unsigned int index = 0;

  for( ; index < width - 2; )
  {
    Uint16Pair range = ParseRange( index, width - 2, top, bytesPerPixel, testByte, testBits, testValue );
    if( range.GetX() != 0xFFFF )
    {
      data->stretchPixelsX.PushBack( range );
    }
  }

  // LEFT
  unsigned char* left  = srcPixels + srcStride;
  index = 0;
  for( ; index < height - 2; )
  {
    Uint16Pair range = ParseRange( index, height - 2, left, srcStride, testByte, testBits, testValue );
    if( range.GetX() != 0xFFFF )
    {
      data->stretchPixelsY.PushBack( range );
    }
  }

  // If there are no stretch pixels then make the entire image stretchable
  if( data->stretchPixelsX.Size() == 0 )
  {
    data->stretchPixelsX.PushBack( Uint16Pair( 0, width - 2 ) );
  }
  if( data->stretchPixelsY.Size() == 0 )
  {
    data->stretchPixelsY.PushBack( Uint16Pair( 0, height - 2 ) );
  }
}

} // namespace NPatchBuffer

NPatchLoader::NPatchLoader()
{
}

NPatchLoader::~NPatchLoader()
{
}

std::size_t NPatchLoader::Load( const std::string& url, const Rect< int >& border, bool& preMultiplyOnLoad )
{
  std::size_t hash = CalculateHash( url );
  OwnerContainer< Data* >::SizeType index = UNINITIALIZED_ID;
  const OwnerContainer< Data* >::SizeType count = mCache.Count();
  int cachedIndex = -1;

  for( ; index < count; ++index )
  {
    if( mCache[ index ]->hash == hash )
    {
      // hash match, check url as well in case of hash collision
      if( mCache[ index ]->url == url )
      {
        // Use cached data
        if( mCache[ index ]->border == border )
        {
          return index+1u; // valid indices are from 1 onwards
        }
        else
        {
          cachedIndex = index;
        }
      }
    }
  }

  if( cachedIndex != -1 )
  {
    // Same url but border is different - use the existing texture
    Data* data = new Data();
    data->hash = hash;
    data->url = url;
    data->croppedWidth = mCache[ cachedIndex ]->croppedWidth;
    data->croppedHeight = mCache[ cachedIndex ]->croppedHeight;

    data->textureSet = mCache[ cachedIndex ]->textureSet;

    StretchRanges stretchRangesX;
    stretchRangesX.PushBack( Uint16Pair( border.left, ( (data->croppedWidth >= static_cast< unsigned int >( border.right )) ? data->croppedWidth - border.right : 0 ) ) );

    StretchRanges stretchRangesY;
    stretchRangesY.PushBack( Uint16Pair( border.top, ( (data->croppedHeight >= static_cast< unsigned int >( border.bottom )) ? data->croppedHeight - border.bottom : 0 ) ) );

    data->stretchPixelsX = stretchRangesX;
    data->stretchPixelsY = stretchRangesY;
    data->border = border;

    mCache.PushBack( data );

    return mCache.Count(); // valid ids start from 1u
  }

  // got to the end so no match, decode N patch and append new item to cache
  Devel::PixelBuffer pixelBuffer = Dali::LoadImageFromFile( url, ImageDimensions(), FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, true );
  if( pixelBuffer )
  {
    Data* data = new Data();
    data->hash = hash;
    data->url = url;

    if( border == Rect< int >( 0, 0, 0, 0 ) )
    {
      NPatchBuffer::ParseBorders( pixelBuffer, data );

      data->border = Rect< int >( 0, 0, 0, 0 );

      // Crop the image
      pixelBuffer.Crop( 1, 1, pixelBuffer.GetWidth() - 2, pixelBuffer.GetHeight() - 2 );
    }
    else
    {
      data->stretchPixelsX.PushBack( Uint16Pair( border.left, ( (pixelBuffer.GetWidth() >= static_cast< unsigned int >( border.right )) ? pixelBuffer.GetWidth() - border.right : 0 ) ) );
      data->stretchPixelsY.PushBack( Uint16Pair( border.top, ( (pixelBuffer.GetHeight() >= static_cast< unsigned int >( border.bottom )) ? pixelBuffer.GetHeight() - border.bottom : 0 ) ) );
      data->border = border;
    }

    data->croppedWidth = pixelBuffer.GetWidth();
    data->croppedHeight = pixelBuffer.GetHeight();

    if( preMultiplyOnLoad && Pixel::HasAlpha( pixelBuffer.GetPixelFormat() ) )
    {
      pixelBuffer.MultiplyColorByAlpha();
    }
    else
    {
      preMultiplyOnLoad = false;
    }

    PixelData pixels = Devel::PixelBuffer::Convert( pixelBuffer ); // takes ownership of buffer

    Texture texture = Texture::New( TextureType::TEXTURE_2D, pixels.GetPixelFormat(), pixels.GetWidth(), pixels.GetHeight() );
    texture.Upload( pixels );

    data->textureSet = TextureSet::New();
    data->textureSet.SetTexture( 0u, texture );

    mCache.PushBack( data );

    return mCache.Count(); // valid ids start from 1u
  }

  return 0u;
}

bool NPatchLoader::GetNPatchData( std::size_t id, const Data*& data )
{
  if( ( id > UNINITIALIZED_ID )&&( id <= mCache.Count() ) )
  {
    data = mCache[ id - 1u ]; // id's start from 1u
    return true;
  }
  data = NULL;
  return false;
}

} // namespace Internal

} // namespace Toolkit

} // namespace Dali
<|endoftext|>


<commit_before>//===- FunctionImport.cpp - ThinLTO Summary-based Function Import ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements Function import based on summaries.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO/FunctionImport.h"

#include "llvm/ADT/StringSet.h"
#include "llvm/IR/AutoUpgrade.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Linker/Linker.h"
#include "llvm/Object/FunctionIndexObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/SourceMgr.h"
using namespace llvm;

#define DEBUG_TYPE "function-import"

/// Limit on instruction count of imported functions.
static cl::opt<unsigned> ImportInstrLimit(
    "import-instr-limit", cl::init(100), cl::Hidden, cl::value_desc("N"),
    cl::desc("Only import functions with less than N instructions"));

// Load lazily a module from \p FileName in \p Context.
static std::unique_ptr<Module> loadFile(const std::string &FileName,
                                        LLVMContext &Context) {
  SMDiagnostic Err;
  DEBUG(dbgs() << "Loading '" << FileName << "'\n");
  std::unique_ptr<Module> Result = getLazyIRFileModule(FileName, Err, Context);
  if (!Result) {
    Err.print("function-import", errs());
    return nullptr;
  }

  Result->materializeMetadata();
  UpgradeDebugInfo(*Result);

  return Result;
}

// Get a Module for \p FileName from the cache, or load it lazily.
Module &ModuleLazyLoaderCache::operator()(StringRef FileName) {
  auto &Module = ModuleMap[FileName];
  if (!Module)
    Module = loadFile(FileName, Context);
  return *Module;
}

/// Walk through the instructions in \p F looking for external
/// calls not already in the \p CalledFunctions set. If any are
/// found they are added to the \p Worklist for importing.
static void findExternalCalls(const Function &F, StringSet<> &CalledFunctions,
                              SmallVector<StringRef, 64> &Worklist) {
  for (auto &BB : F) {
    for (auto &I : BB) {
      if (isa<CallInst>(I)) {
        auto CalledFunction = cast<CallInst>(I).getCalledFunction();
        // Insert any new external calls that have not already been
        // added to set/worklist.
        if (CalledFunction && CalledFunction->hasName() &&
            CalledFunction->isDeclaration() &&
            !CalledFunctions.count(CalledFunction->getName())) {
          CalledFunctions.insert(CalledFunction->getName());
          Worklist.push_back(CalledFunction->getName());
        }
      }
    }
  }
}

// Helper function: given a worklist and an index, will process all the worklist
// and import them based on the summary information
static unsigned ProcessImportWorklist(Module &DestModule, SmallVector<StringRef, 64> &Worklist,
                                      StringSet<> &CalledFunctions,
                            Linker &TheLinker, const FunctionInfoIndex &Index,
                            std::function<Module &(StringRef FileName)> &LazyModuleLoader) {
  unsigned ImportCount = 0;
  while (!Worklist.empty()) {
    auto CalledFunctionName = Worklist.pop_back_val();
    DEBUG(dbgs() << "Process import for " << CalledFunctionName << "\n");

    // Try to get a summary for this function call.
    auto InfoList = Index.findFunctionInfoList(CalledFunctionName);
    if (InfoList == Index.end()) {
      DEBUG(dbgs() << "No summary for " << CalledFunctionName
                   << " Ignoring.\n");
      continue;
    }
    assert(!InfoList->second.empty() && "No summary, error at import?");

    // Comdat can have multiple entries, FIXME: what do we do with them?
    auto &Info = InfoList->second[0];
    assert(Info && "Nullptr in list, error importing summaries?\n");

    auto *Summary = Info->functionSummary();
    if (!Summary) {
      // FIXME: in case we are lazyloading summaries, we can do it now.
      DEBUG(dbgs() << "Missing summary for  " << CalledFunctionName
                   << ", error at import?\n");
      llvm_unreachable("Missing summary");
    }

    if (Summary->instCount() > ImportInstrLimit) {
      DEBUG(dbgs() << "Skip import of " << CalledFunctionName << " with "
                   << Summary->instCount() << " instructions (limit "
                   << ImportInstrLimit << ")\n");
      continue;
    }

    // Get the module path from the summary.
    auto FileName = Summary->modulePath();
    DEBUG(dbgs() << "Importing " << CalledFunctionName << " from " << FileName
                 << "\n");

    // Get the module for the import (potentially from the cache).
    auto &Module = LazyModuleLoader(FileName);
    assert(&Module.getContext() == &DestModule.getContext());

    // The function that we will import!
    GlobalValue *SGV = Module.getNamedValue(CalledFunctionName);
    StringRef ImportFunctionName = CalledFunctionName;
    if (!SGV) {
      // Might be local in source Module, promoted/renamed in DestModule.
      std::pair<StringRef, StringRef> Split =
          CalledFunctionName.split(".llvm.");
      SGV = Module.getNamedValue(Split.first);
#ifndef NDEBUG
      // Assert that Split.second is module id
      uint64_t ModuleId;
      assert(!Split.second.getAsInteger(10, ModuleId));
      assert(ModuleId == Index.getModuleId(FileName));
#endif
    }
    Function *F = dyn_cast<Function>(SGV);
    if (!F && isa<GlobalAlias>(SGV)) {
      auto *SGA = dyn_cast<GlobalAlias>(SGV);
      F = dyn_cast<Function>(SGA->getBaseObject());
      ImportFunctionName = F->getName();
    }
    if (!F) {
      errs() << "Can't load function '" << CalledFunctionName << "' in Module '"
             << FileName << "', error in the summary?\n";
      llvm_unreachable("Can't load function in Module");
    }

    // We cannot import weak_any functions/aliases without possibly affecting
    // the order they are seen and selected by the linker, changing program
    // semantics.
    if (SGV->hasWeakAnyLinkage()) {
      DEBUG(dbgs() << "Ignoring import request for weak-any "
                   << (isa<Function>(SGV) ? "function " : "alias ")
                   << CalledFunctionName << " from " << FileName << "\n");
      continue;
    }

    // Link in the specified function.
    DenseSet<const GlobalValue *> FunctionsToImport;
    FunctionsToImport.insert(F);
    if (TheLinker.linkInModule(Module, Linker::Flags::None, &Index,
                       &FunctionsToImport))
      report_fatal_error("Function Import: link error");

    // Process the newly imported function and add callees to the worklist.
    GlobalValue *NewGV = DestModule.getNamedValue(ImportFunctionName);
    assert(NewGV);
    Function *NewF = dyn_cast<Function>(NewGV);
    assert(NewF);
    findExternalCalls(*NewF, CalledFunctions, Worklist);
    ++ImportCount;
  }
  return ImportCount;
}

// Automatically import functions in Module \p DestModule based on the summaries
// index.
//
// The current implementation imports every called functions that exists in the
// summaries index.
bool FunctionImporter::importFunctions(Module &DestModule) {
  DEBUG(errs() << "Starting import for Module " << DestModule.getModuleIdentifier()
               << "\n");
  unsigned ImportedCount = 0;

  /// First step is collecting the called external functions.
  StringSet<> CalledFunctions;
  SmallVector<StringRef, 64> Worklist;
  for (auto &F : DestModule) {
    if (F.isDeclaration() || F.hasFnAttribute(Attribute::OptimizeNone))
      continue;
    findExternalCalls(F, CalledFunctions, Worklist);
  }
  if (Worklist.empty())
    return false;

  /// Second step: for every call to an external function, try to import it.

  // Linker that will be used for importing function
  Linker TheLinker(DestModule, DiagnosticHandler);

  ImportedCount += ProcessImportWorklist(DestModule, Worklist, CalledFunctions, TheLinker, Index, getLazyModule );

  DEBUG(errs() << "Imported " << ImportedCount << " functions for Module "
               << DestModule.getModuleIdentifier() << "\n");
  return ImportedCount;
}

/// Summary file to use for function importing when using -function-import from
/// the command line.
static cl::opt<std::string>
    SummaryFile("summary-file",
                cl::desc("The summary file to use for function importing."));

static void diagnosticHandler(const DiagnosticInfo &DI) {
  raw_ostream &OS = errs();
  DiagnosticPrinterRawOStream DP(OS);
  DI.print(DP);
  OS << '\n';
}

/// Parse the function index out of an IR file and return the function
/// index object if found, or nullptr if not.
static std::unique_ptr<FunctionInfoIndex>
getFunctionIndexForFile(StringRef Path, std::string &Error,
                        DiagnosticHandlerFunction DiagnosticHandler) {
  std::unique_ptr<MemoryBuffer> Buffer;
  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
      MemoryBuffer::getFile(Path);
  if (std::error_code EC = BufferOrErr.getError()) {
    Error = EC.message();
    return nullptr;
  }
  Buffer = std::move(BufferOrErr.get());
  ErrorOr<std::unique_ptr<object::FunctionIndexObjectFile>> ObjOrErr =
      object::FunctionIndexObjectFile::create(Buffer->getMemBufferRef(),
                                              DiagnosticHandler);
  if (std::error_code EC = ObjOrErr.getError()) {
    Error = EC.message();
    return nullptr;
  }
  return (*ObjOrErr)->takeIndex();
}

/// Pass that performs cross-module function import provided a summary file.
class FunctionImportPass : public ModulePass {

public:
  /// Pass identification, replacement for typeid
  static char ID;

  explicit FunctionImportPass() : ModulePass(ID) {}

  bool runOnModule(Module &M) override {
    if (SummaryFile.empty()) {
      report_fatal_error("error: -function-import requires -summary-file\n");
    }
    std::string Error;
    std::unique_ptr<FunctionInfoIndex> Index =
        getFunctionIndexForFile(SummaryFile, Error, diagnosticHandler);
    if (!Index) {
      errs() << "Error loading file '" << SummaryFile << "': " << Error << "\n";
      return false;
    }

    // Perform the import now.
    ModuleLazyLoaderCache Loader(M.getContext());
    FunctionImporter Importer(*Index, diagnosticHandler,
                              [&](StringRef Name)
                                  -> Module &{ return Loader(Name); });
    return Importer.importFunctions(M);

    return false;
  }
};

char FunctionImportPass::ID = 0;
INITIALIZE_PASS_BEGIN(FunctionImportPass, "function-import",
                      "Summary Based Function Import", false, false)
INITIALIZE_PASS_END(FunctionImportPass, "function-import",
                    "Summary Based Function Import", false, false)

namespace llvm {
Pass *createFunctionImportPass() { return new FunctionImportPass(); }
}
<commit_msg>clang-format FunctionImport after refactoring (NFC)<commit_after>//===- FunctionImport.cpp - ThinLTO Summary-based Function Import ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements Function import based on summaries.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO/FunctionImport.h"

#include "llvm/ADT/StringSet.h"
#include "llvm/IR/AutoUpgrade.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Linker/Linker.h"
#include "llvm/Object/FunctionIndexObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/SourceMgr.h"
using namespace llvm;

#define DEBUG_TYPE "function-import"

/// Limit on instruction count of imported functions.
static cl::opt<unsigned> ImportInstrLimit(
    "import-instr-limit", cl::init(100), cl::Hidden, cl::value_desc("N"),
    cl::desc("Only import functions with less than N instructions"));

// Load lazily a module from \p FileName in \p Context.
static std::unique_ptr<Module> loadFile(const std::string &FileName,
                                        LLVMContext &Context) {
  SMDiagnostic Err;
  DEBUG(dbgs() << "Loading '" << FileName << "'\n");
  std::unique_ptr<Module> Result = getLazyIRFileModule(FileName, Err, Context);
  if (!Result) {
    Err.print("function-import", errs());
    return nullptr;
  }

  Result->materializeMetadata();
  UpgradeDebugInfo(*Result);

  return Result;
}

// Get a Module for \p FileName from the cache, or load it lazily.
Module &ModuleLazyLoaderCache::operator()(StringRef FileName) {
  auto &Module = ModuleMap[FileName];
  if (!Module)
    Module = loadFile(FileName, Context);
  return *Module;
}

/// Walk through the instructions in \p F looking for external
/// calls not already in the \p CalledFunctions set. If any are
/// found they are added to the \p Worklist for importing.
static void findExternalCalls(const Function &F, StringSet<> &CalledFunctions,
                              SmallVector<StringRef, 64> &Worklist) {
  for (auto &BB : F) {
    for (auto &I : BB) {
      if (isa<CallInst>(I)) {
        auto CalledFunction = cast<CallInst>(I).getCalledFunction();
        // Insert any new external calls that have not already been
        // added to set/worklist.
        if (CalledFunction && CalledFunction->hasName() &&
            CalledFunction->isDeclaration() &&
            !CalledFunctions.count(CalledFunction->getName())) {
          CalledFunctions.insert(CalledFunction->getName());
          Worklist.push_back(CalledFunction->getName());
        }
      }
    }
  }
}

// Helper function: given a worklist and an index, will process all the worklist
// and import them based on the summary information
static unsigned ProcessImportWorklist(
    Module &DestModule, SmallVector<StringRef, 64> &Worklist,
    StringSet<> &CalledFunctions, Linker &TheLinker,
    const FunctionInfoIndex &Index,
    std::function<Module &(StringRef FileName)> &LazyModuleLoader) {
  unsigned ImportCount = 0;
  while (!Worklist.empty()) {
    auto CalledFunctionName = Worklist.pop_back_val();
    DEBUG(dbgs() << "Process import for " << CalledFunctionName << "\n");

    // Try to get a summary for this function call.
    auto InfoList = Index.findFunctionInfoList(CalledFunctionName);
    if (InfoList == Index.end()) {
      DEBUG(dbgs() << "No summary for " << CalledFunctionName
                   << " Ignoring.\n");
      continue;
    }
    assert(!InfoList->second.empty() && "No summary, error at import?");

    // Comdat can have multiple entries, FIXME: what do we do with them?
    auto &Info = InfoList->second[0];
    assert(Info && "Nullptr in list, error importing summaries?\n");

    auto *Summary = Info->functionSummary();
    if (!Summary) {
      // FIXME: in case we are lazyloading summaries, we can do it now.
      DEBUG(dbgs() << "Missing summary for  " << CalledFunctionName
                   << ", error at import?\n");
      llvm_unreachable("Missing summary");
    }

    if (Summary->instCount() > ImportInstrLimit) {
      DEBUG(dbgs() << "Skip import of " << CalledFunctionName << " with "
                   << Summary->instCount() << " instructions (limit "
                   << ImportInstrLimit << ")\n");
      continue;
    }

    // Get the module path from the summary.
    auto FileName = Summary->modulePath();
    DEBUG(dbgs() << "Importing " << CalledFunctionName << " from " << FileName
                 << "\n");

    // Get the module for the import (potentially from the cache).
    auto &Module = LazyModuleLoader(FileName);
    assert(&Module.getContext() == &DestModule.getContext());

    // The function that we will import!
    GlobalValue *SGV = Module.getNamedValue(CalledFunctionName);
    StringRef ImportFunctionName = CalledFunctionName;
    if (!SGV) {
      // Might be local in source Module, promoted/renamed in DestModule.
      std::pair<StringRef, StringRef> Split =
          CalledFunctionName.split(".llvm.");
      SGV = Module.getNamedValue(Split.first);
#ifndef NDEBUG
      // Assert that Split.second is module id
      uint64_t ModuleId;
      assert(!Split.second.getAsInteger(10, ModuleId));
      assert(ModuleId == Index.getModuleId(FileName));
#endif
    }
    Function *F = dyn_cast<Function>(SGV);
    if (!F && isa<GlobalAlias>(SGV)) {
      auto *SGA = dyn_cast<GlobalAlias>(SGV);
      F = dyn_cast<Function>(SGA->getBaseObject());
      ImportFunctionName = F->getName();
    }
    if (!F) {
      errs() << "Can't load function '" << CalledFunctionName << "' in Module '"
             << FileName << "', error in the summary?\n";
      llvm_unreachable("Can't load function in Module");
    }

    // We cannot import weak_any functions/aliases without possibly affecting
    // the order they are seen and selected by the linker, changing program
    // semantics.
    if (SGV->hasWeakAnyLinkage()) {
      DEBUG(dbgs() << "Ignoring import request for weak-any "
                   << (isa<Function>(SGV) ? "function " : "alias ")
                   << CalledFunctionName << " from " << FileName << "\n");
      continue;
    }

    // Link in the specified function.
    DenseSet<const GlobalValue *> FunctionsToImport;
    FunctionsToImport.insert(F);
    if (TheLinker.linkInModule(Module, Linker::Flags::None, &Index,
                               &FunctionsToImport))
      report_fatal_error("Function Import: link error");

    // Process the newly imported function and add callees to the worklist.
    GlobalValue *NewGV = DestModule.getNamedValue(ImportFunctionName);
    assert(NewGV);
    Function *NewF = dyn_cast<Function>(NewGV);
    assert(NewF);
    findExternalCalls(*NewF, CalledFunctions, Worklist);
    ++ImportCount;
  }
  return ImportCount;
}

// Automatically import functions in Module \p DestModule based on the summaries
// index.
//
// The current implementation imports every called functions that exists in the
// summaries index.
bool FunctionImporter::importFunctions(Module &DestModule) {
  DEBUG(errs() << "Starting import for Module "
               << DestModule.getModuleIdentifier() << "\n");
  unsigned ImportedCount = 0;

  /// First step is collecting the called external functions.
  StringSet<> CalledFunctions;
  SmallVector<StringRef, 64> Worklist;
  for (auto &F : DestModule) {
    if (F.isDeclaration() || F.hasFnAttribute(Attribute::OptimizeNone))
      continue;
    findExternalCalls(F, CalledFunctions, Worklist);
  }
  if (Worklist.empty())
    return false;

  /// Second step: for every call to an external function, try to import it.

  // Linker that will be used for importing function
  Linker TheLinker(DestModule, DiagnosticHandler);

  ImportedCount += ProcessImportWorklist(DestModule, Worklist, CalledFunctions,
                                         TheLinker, Index, getLazyModule);

  DEBUG(errs() << "Imported " << ImportedCount << " functions for Module "
               << DestModule.getModuleIdentifier() << "\n");
  return ImportedCount;
}

/// Summary file to use for function importing when using -function-import from
/// the command line.
static cl::opt<std::string>
    SummaryFile("summary-file",
                cl::desc("The summary file to use for function importing."));

static void diagnosticHandler(const DiagnosticInfo &DI) {
  raw_ostream &OS = errs();
  DiagnosticPrinterRawOStream DP(OS);
  DI.print(DP);
  OS << '\n';
}

/// Parse the function index out of an IR file and return the function
/// index object if found, or nullptr if not.
static std::unique_ptr<FunctionInfoIndex>
getFunctionIndexForFile(StringRef Path, std::string &Error,
                        DiagnosticHandlerFunction DiagnosticHandler) {
  std::unique_ptr<MemoryBuffer> Buffer;
  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
      MemoryBuffer::getFile(Path);
  if (std::error_code EC = BufferOrErr.getError()) {
    Error = EC.message();
    return nullptr;
  }
  Buffer = std::move(BufferOrErr.get());
  ErrorOr<std::unique_ptr<object::FunctionIndexObjectFile>> ObjOrErr =
      object::FunctionIndexObjectFile::create(Buffer->getMemBufferRef(),
                                              DiagnosticHandler);
  if (std::error_code EC = ObjOrErr.getError()) {
    Error = EC.message();
    return nullptr;
  }
  return (*ObjOrErr)->takeIndex();
}

/// Pass that performs cross-module function import provided a summary file.
class FunctionImportPass : public ModulePass {

public:
  /// Pass identification, replacement for typeid
  static char ID;

  explicit FunctionImportPass() : ModulePass(ID) {}

  bool runOnModule(Module &M) override {
    if (SummaryFile.empty()) {
      report_fatal_error("error: -function-import requires -summary-file\n");
    }
    std::string Error;
    std::unique_ptr<FunctionInfoIndex> Index =
        getFunctionIndexForFile(SummaryFile, Error, diagnosticHandler);
    if (!Index) {
      errs() << "Error loading file '" << SummaryFile << "': " << Error << "\n";
      return false;
    }

    // Perform the import now.
    ModuleLazyLoaderCache Loader(M.getContext());
    FunctionImporter Importer(*Index, diagnosticHandler,
                              [&](StringRef Name)
                                  -> Module &{ return Loader(Name); });
    return Importer.importFunctions(M);

    return false;
  }
};

char FunctionImportPass::ID = 0;
INITIALIZE_PASS_BEGIN(FunctionImportPass, "function-import",
                      "Summary Based Function Import", false, false)
INITIALIZE_PASS_END(FunctionImportPass, "function-import",
                    "Summary Based Function Import", false, false)

namespace llvm {
Pass *createFunctionImportPass() { return new FunctionImportPass(); }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: swthreadjoiner.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: obo $ $Date: 2007-07-18 13:32:03 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#include "precompiled_sw.hxx"

#ifndef _SWTHREADJOINER_HXX
#include <swthreadjoiner.hxx>
#endif

#ifndef _FINALTHREADMANAGER_HXX
#include <finalthreadmanager.hxx>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
#include <comphelper/processfactory.hxx>
#endif

/** Testing

    @author OD
*/
using namespace ::com::sun::star;

uno::Reference< util::XJobManager > SwThreadJoiner::mpThreadJoiner;
osl::Mutex* SwThreadJoiner::mpGetJoinerMutex = new osl::Mutex();

uno::Reference< util::XJobManager >& SwThreadJoiner::GetThreadJoiner()
{
    osl::MutexGuard aGuard(*mpGetJoinerMutex);

    if ( !mpThreadJoiner.is() )
    {
        mpThreadJoiner =
            uno::Reference< util::XJobManager >(
                ::comphelper::getProcessServiceFactory()->createInstance(
                    ::rtl::OUString::createFromAscii("com.sun.star.util.JobManager" ) ),
                uno::UNO_QUERY );
    }

    return mpThreadJoiner;
}

bool SwThreadJoiner::ExistsThreadJoiner()
{
    return (mpThreadJoiner.is());
}

void SwThreadJoiner::ReleaseThreadJoiner()
{
    mpThreadJoiner.clear();
}
<commit_msg>INTEGRATION: CWS sw8u10bf05 (1.2.236); FILE MERGED 2008/01/25 10:38:24 ama 1.2.236.1: Fix #85182#: Remove unused functions<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: swthreadjoiner.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: vg $ $Date: 2008-03-18 15:56:16 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#include "precompiled_sw.hxx"

#ifndef _SWTHREADJOINER_HXX
#include <swthreadjoiner.hxx>
#endif

#ifndef _FINALTHREADMANAGER_HXX
#include <finalthreadmanager.hxx>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
#include <comphelper/processfactory.hxx>
#endif

/** Testing

    @author OD
*/
using namespace ::com::sun::star;

uno::Reference< util::XJobManager > SwThreadJoiner::mpThreadJoiner;
osl::Mutex* SwThreadJoiner::mpGetJoinerMutex = new osl::Mutex();

uno::Reference< util::XJobManager >& SwThreadJoiner::GetThreadJoiner()
{
    osl::MutexGuard aGuard(*mpGetJoinerMutex);

    if ( !mpThreadJoiner.is() )
    {
        mpThreadJoiner =
            uno::Reference< util::XJobManager >(
                ::comphelper::getProcessServiceFactory()->createInstance(
                    ::rtl::OUString::createFromAscii("com.sun.star.util.JobManager" ) ),
                uno::UNO_QUERY );
    }

    return mpThreadJoiner;
}

void SwThreadJoiner::ReleaseThreadJoiner()
{
    mpThreadJoiner.clear();
}
<|endoftext|>


<commit_before>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile: mitkPropertyManager.cpp,v $
Language:  C++
Date:      $Date$
Version:   $Revision: 1.12 $

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "QmitkCalculateGrayValueStatisticsToolGUI.h"

#include "QmitkCopyToClipBoardDialog.h"

QmitkCalculateGrayValueStatisticsToolGUI::QmitkCalculateGrayValueStatisticsToolGUI()
:QmitkToolGUI()
{
  connect( this, SIGNAL(NewToolAssociated(mitk::Tool*)), this, SLOT(OnNewToolAssociated(mitk::Tool*)) );
}

QmitkCalculateGrayValueStatisticsToolGUI::~QmitkCalculateGrayValueStatisticsToolGUI()
{
  if (m_CalculateGrayValueStatisticsTool.IsNotNull())
  {
    m_CalculateGrayValueStatisticsTool->StatisticsCompleted.RemoveListener( this, &QmitkCalculateGrayValueStatisticsToolGUI::OnCalculationsDone );
  }
}

void QmitkCalculateGrayValueStatisticsToolGUI::OnNewToolAssociated(mitk::Tool* tool)
{
  if (m_CalculateGrayValueStatisticsTool.IsNotNull())
  {
    m_CalculateGrayValueStatisticsTool->StatisticsCompleted.RemoveListener( this, &QmitkCalculateGrayValueStatisticsToolGUI::OnCalculationsDone );
  }

  m_CalculateGrayValueStatisticsTool = dynamic_cast<mitk::CalculateGrayValueStatisticsTool*>( tool );

  if (m_CalculateGrayValueStatisticsTool.IsNotNull())
  {
    m_CalculateGrayValueStatisticsTool->StatisticsCompleted.AddListener( this, &QmitkCalculateGrayValueStatisticsToolGUI::OnCalculationsDone );
  }
}

void QmitkCalculateGrayValueStatisticsToolGUI::OnCalculationsDone()
{
  if (m_CalculateGrayValueStatisticsTool.IsNotNull())
  {
    std::string report = m_CalculateGrayValueStatisticsTool->GetReport();

    // one for linux users
    std::cout << report << std::endl;

    // one for window users
    QmitkCopyToClipBoardDialog* dialog = new QmitkCopyToClipBoardDialog( report, NULL);
    dialog->show();
  }
}

<commit_msg>COMP: std::string -> QString conversion for VC 7.1<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile: mitkPropertyManager.cpp,v $
Language:  C++
Date:      $Date$
Version:   $Revision: 1.12 $

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "QmitkCalculateGrayValueStatisticsToolGUI.h"

#include "QmitkCopyToClipBoardDialog.h"

QmitkCalculateGrayValueStatisticsToolGUI::QmitkCalculateGrayValueStatisticsToolGUI()
:QmitkToolGUI()
{
  connect( this, SIGNAL(NewToolAssociated(mitk::Tool*)), this, SLOT(OnNewToolAssociated(mitk::Tool*)) );
}

QmitkCalculateGrayValueStatisticsToolGUI::~QmitkCalculateGrayValueStatisticsToolGUI()
{
  if (m_CalculateGrayValueStatisticsTool.IsNotNull())
  {
    m_CalculateGrayValueStatisticsTool->StatisticsCompleted.RemoveListener( this, &QmitkCalculateGrayValueStatisticsToolGUI::OnCalculationsDone );
  }
}

void QmitkCalculateGrayValueStatisticsToolGUI::OnNewToolAssociated(mitk::Tool* tool)
{
  if (m_CalculateGrayValueStatisticsTool.IsNotNull())
  {
    m_CalculateGrayValueStatisticsTool->StatisticsCompleted.RemoveListener( this, &QmitkCalculateGrayValueStatisticsToolGUI::OnCalculationsDone );
  }

  m_CalculateGrayValueStatisticsTool = dynamic_cast<mitk::CalculateGrayValueStatisticsTool*>( tool );

  if (m_CalculateGrayValueStatisticsTool.IsNotNull())
  {
    m_CalculateGrayValueStatisticsTool->StatisticsCompleted.AddListener( this, &QmitkCalculateGrayValueStatisticsToolGUI::OnCalculationsDone );
  }
}

void QmitkCalculateGrayValueStatisticsToolGUI::OnCalculationsDone()
{
  if (m_CalculateGrayValueStatisticsTool.IsNotNull())
  {
    std::string report = m_CalculateGrayValueStatisticsTool->GetReport();

    // one for linux users
    std::cout << report << std::endl;

    // one for window users
    QmitkCopyToClipBoardDialog* dialog = new QmitkCopyToClipBoardDialog( report.c_str(), NULL);
    dialog->show();
  }
}

<|endoftext|>


<commit_before>#include "pch.h"
#include "axl_io_File.h"
#include "axl_io_Mapping.h"
#include "axl_rtl_String.h"

namespace axl {
namespace io {

//.............................................................................

#if (_AXL_ENV == AXL_ENV_WIN)

bool
File::open (
	const char* fileName,
	uint_t flags
	)
{
	uint_t accessMode = (flags & FileFlag_ReadOnly) ?
		GENERIC_READ :
		GENERIC_READ | GENERIC_WRITE;

	uint_t shareMode = (flags & FileFlag_Exclusive) ?
		0 :
		(flags & FileFlag_ReadOnly) || (flags & FileFlag_ShareWrite) ?
			FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE :
			FILE_SHARE_READ;

	uint_t creationDisposition = (flags & (FileFlag_ReadOnly | FileFlag_OpenExisting)) ?
		OPEN_EXISTING :
		OPEN_ALWAYS;

	uint_t flagsAttributes = (flags & FileFlag_DeleteOnClose) ?
		FILE_FLAG_DELETE_ON_CLOSE :
		0;

	if (flags & FileFlag_Asynchronous)
		flagsAttributes |= FILE_FLAG_OVERLAPPED;

	char buffer [256];
	rtl::String_w fileName_w (ref::BufKind_Stack, buffer, sizeof (buffer));
	fileName_w = fileName;

	return m_file.create (
		fileName_w,
		accessMode,
		shareMode,
		NULL,
		creationDisposition,
		flagsAttributes
		);
}

#elif (_AXL_ENV == AXL_ENV_POSIX)

bool
File::open (
	const char* fileName,
	uint_t flags
	)
{
	uint_t posixFlags = (flags & FileFlag_ReadOnly) ? O_RDONLY : O_RDWR;

	if (!(flags & (FileFlag_ReadOnly | FileFlag_OpenExisting)))
		posixFlags |= O_CREAT;

	if (flags & FileFlag_Asynchronous)
		posixFlags |= O_NONBLOCK;

	// TODO: handle exclusive and share write flags with fcntl locks

	bool result = m_file.open (fileName, posixFlags);
	if (!result)
		return false;

	if (flags & FileFlag_DeleteOnClose)
		unlink (fileName);

	return true;
}

#endif

//.............................................................................

#if (_AXL_ENV == AXL_ENV_POSIX)

void
TemporaryFile::close ()
{
	if (!isOpen ())
		return;

	File::close ();
	deleteFile (m_fileName);
	m_fileName.clear ();
}

bool
TemporaryFile::open (
	const char* fileName,
	uint_t flags
	)
{
	close ();

	bool result = File::open (fileName, flags & ~FileFlag_DeleteOnClose);
	if (!result)
		return false;

	m_fileName = fileName;
	return true;
}

#endif

//.............................................................................

uint64_t
copyFile (
	const char* srcFileName,
	const char* dstFileName,
	uint64_t size
	)
{
	File srcFile;
	File dstFile;

	bool result =
		srcFile.open (srcFileName, FileFlag_ReadOnly) &&
		dstFile.open (dstFileName);

	if (!result)
		return false;

	enum
	{
		BlockSize = 32 * 1024, // 32 K
	};

	if (size == -1)
		size = srcFile.getSize ();

	uint64_t offset = 0;

#if (_AXL_ENV == AXL_ENV_WIN)
	win::Mapping srcMapping;
	win::Mapping dstMapping;
	win::MappedView srcView;
	win::MappedView dstView;

	result =
		srcMapping.create (srcFile.m_file, NULL, PAGE_READONLY, size) &&
		dstMapping.create (dstFile.m_file, NULL, PAGE_READWRITE, size);

	while (size)
	{
		size_t blockSize = (size_t) AXL_MIN (BlockSize, size);

		const void* src = srcView.view (srcMapping, FILE_MAP_READ, offset, blockSize);
		void* dst = dstView.view (dstMapping, FILE_MAP_READ | FILE_MAP_WRITE, offset, blockSize);

		if (!src || !dst)
			return false;

		memcpy (dst, src, blockSize);

		offset += blockSize;
		size -= blockSize;
	}

	srcMapping.close ();
	dstMapping.close ();
	srcView.close ();
	dstView.close ();
#else
	psx::Mapping srcMapping;
	psx::Mapping dstMapping;

	while (size)
	{
		size_t blockSize = AXL_MIN (BlockSize, size);

		const void* src = srcView.view (NULL, blockSize, PROT_READ, MAP_SHARED, srcFile->m_file, offset);
		void* dst = dstView.view (NULL, blockSize, PROT_READ | PROT_WRITE, MAP_SHARED, dstFile->m_file, offset);

		if (!src || !dst)
			return false;

		memcpy (dst, src, blockSize);

		offset += blockSize;
		size -= blockSize;
	}

	srcMapping.close ();
	dstMapping.close ();
#endif

	return offset;
}

//.............................................................................

} // namespace io
} // namespace axl
<commit_msg>[axl] bugfix in PSOXI io::copyFile<commit_after>#include "pch.h"
#include "axl_io_File.h"
#include "axl_io_Mapping.h"
#include "axl_rtl_String.h"

namespace axl {
namespace io {

//.............................................................................

#if (_AXL_ENV == AXL_ENV_WIN)

bool
File::open (
	const char* fileName,
	uint_t flags
	)
{
	uint_t accessMode = (flags & FileFlag_ReadOnly) ?
		GENERIC_READ :
		GENERIC_READ | GENERIC_WRITE;

	uint_t shareMode = (flags & FileFlag_Exclusive) ?
		0 :
		(flags & FileFlag_ReadOnly) || (flags & FileFlag_ShareWrite) ?
			FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE :
			FILE_SHARE_READ;

	uint_t creationDisposition = (flags & (FileFlag_ReadOnly | FileFlag_OpenExisting)) ?
		OPEN_EXISTING :
		OPEN_ALWAYS;

	uint_t flagsAttributes = (flags & FileFlag_DeleteOnClose) ?
		FILE_FLAG_DELETE_ON_CLOSE :
		0;

	if (flags & FileFlag_Asynchronous)
		flagsAttributes |= FILE_FLAG_OVERLAPPED;

	char buffer [256];
	rtl::String_w fileName_w (ref::BufKind_Stack, buffer, sizeof (buffer));
	fileName_w = fileName;

	return m_file.create (
		fileName_w,
		accessMode,
		shareMode,
		NULL,
		creationDisposition,
		flagsAttributes
		);
}

#elif (_AXL_ENV == AXL_ENV_POSIX)

bool
File::open (
	const char* fileName,
	uint_t flags
	)
{
	uint_t posixFlags = (flags & FileFlag_ReadOnly) ? O_RDONLY : O_RDWR;

	if (!(flags & (FileFlag_ReadOnly | FileFlag_OpenExisting)))
		posixFlags |= O_CREAT;

	if (flags & FileFlag_Asynchronous)
		posixFlags |= O_NONBLOCK;

	// TODO: handle exclusive and share write flags with fcntl locks

	bool result = m_file.open (fileName, posixFlags);
	if (!result)
		return false;

	if (flags & FileFlag_DeleteOnClose)
		unlink (fileName);

	return true;
}

#endif

//.............................................................................

#if (_AXL_ENV == AXL_ENV_POSIX)

void
TemporaryFile::close ()
{
	if (!isOpen ())
		return;

	File::close ();
	deleteFile (m_fileName);
	m_fileName.clear ();
}

bool
TemporaryFile::open (
	const char* fileName,
	uint_t flags
	)
{
	close ();

	bool result = File::open (fileName, flags & ~FileFlag_DeleteOnClose);
	if (!result)
		return false;

	m_fileName = fileName;
	return true;
}

#endif

//.............................................................................

uint64_t
copyFile (
	const char* srcFileName,
	const char* dstFileName,
	uint64_t size
	)
{
	File srcFile;
	File dstFile;

	bool result =
		srcFile.open (srcFileName, FileFlag_ReadOnly) &&
		dstFile.open (dstFileName);

	if (!result)
		return -1;

	enum
	{
		BlockSize = 32 * 1024, // 32 K
	};

	if (size == -1)
		size = srcFile.getSize ();

	uint64_t offset = 0;

#if (_AXL_ENV == AXL_ENV_WIN)
	win::Mapping srcMapping;
	win::Mapping dstMapping;
	win::MappedView srcView;
	win::MappedView dstView;

	result =
		srcMapping.create (srcFile.m_file, NULL, PAGE_READONLY, size) &&
		dstMapping.create (dstFile.m_file, NULL, PAGE_READWRITE, size);

	while (size)
	{
		size_t blockSize = (size_t) AXL_MIN (BlockSize, size);

		const void* src = srcView.view (srcMapping, FILE_MAP_READ, offset, blockSize);
		void* dst = dstView.view (dstMapping, FILE_MAP_READ | FILE_MAP_WRITE, offset, blockSize);

		if (!src || !dst)
			return -1;

		memcpy (dst, src, blockSize);

		offset += blockSize;
		size -= blockSize;
	}

	srcMapping.close ();
	dstMapping.close ();
	srcView.close ();
	dstView.close ();
#else
	psx::Mapping srcMapping;
	psx::Mapping dstMapping;

	while (size)
	{
		size_t blockSize = AXL_MIN (BlockSize, size);

		const void* src = srcMapping.map (NULL, blockSize, PROT_READ, MAP_SHARED, srcFile.m_file, offset);
		void* dst = dstMapping.map (NULL, blockSize, PROT_READ | PROT_WRITE, MAP_SHARED, dstFile.m_file, offset);

		if (!src || !dst)
			return -1;

		memcpy (dst, src, blockSize);

		offset += blockSize;
		size -= blockSize;
	}

	srcMapping.close ();
	dstMapping.close ();
#endif

	return offset;
}

//.............................................................................

} // namespace io
} // namespace axl
<|endoftext|>


<commit_before>#include <iostream>
#include <algorithm>
using namespace std;

bool perfectly_cut(double *cut, int n, int size, double w) {
	sort(cut, cut+n);
	if (w/2 < cut[0] || cut[n-1]+w/2 < size)
		return false;

	for (int k = 0 ; k < n-1 ; k++) {
		if (cut[k]+w < cut[k+1])
			return false;
	}
	return true;
}

int main() {
	int length = 100, width = 75;
	int nx, ny;
	double w;
	double cutx[1000];
	double cuty[1000];

	cin >> nx;
	cin >> ny;
	cin >> w;

	while (nx != 0 || ny != 0 || w != 0.0) {
		for (int k = 0 ; k < nx ; k++)
			cin >> cutx[k];
		for (int k = 0 ; k < ny ; k++)
			cin >> cuty[k];

		if (perfectly_cut(cutx, nx, width, w) && perfectly_cut(cuty, ny, length, w))
			cout << "YES" << endl;
		else
			cout << "NO" << endl;

		cin >> nx;
		cin >> ny;
		cin >> w;
	}
	return 0;
}
<commit_msg>Lawn mower<commit_after>#include <iostream>
#include <algorithm>
using namespace std;

bool perfectly_cut(double *cut, int n, int size, double w) {
	sort(cut, cut+n);
	if (w/2 < cut[0] || cut[n-1]+w/2 < size)
		return false;

	for (int k = 0 ; k < n-1 ; k++) {
		if (cut[k]+w < cut[k+1])
			return false;
	}
	return true;
}

int main() {
	int length = 100, width = 75;
	int nx, ny;
	double w;
	double cutx[1000];
	double cuty[1000];

	cin >> nx;
	cin >> ny;
	cin >> w;

	while (nx != 0 || ny != 0 || w != 0.0) {
		for (int k = 0 ; k < nx ; k++)
			cin >> cutx[k];
		for (int k = 0 ; k < ny ; k++)
			cin >> cuty[k];

		if (perfectly_cut(cutx, nx, width, w) && perfectly_cut(cuty, ny, length, w))
			cout << "YES" << endl;
		else
			cout << "NO" << endl;

		cin >> nx;
		cin >> ny;
		cin >> w;
	}
	return 0;
}
<|endoftext|>