<commit_before>//===-- llvm/Target/TargetLoweringObjectFile.cpp - Object File Info -------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements classes used to handle lowerings specific to common
// object file formats.
//
//===----------------------------------------------------------------------===//

#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/SmallString.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
//                              Generic Code
//===----------------------------------------------------------------------===//

TargetLoweringObjectFile::TargetLoweringObjectFile() : Ctx(0) {
  TextSection = 0;
  DataSection = 0;
  BSSSection = 0;
  ReadOnlySection = 0;
  StaticCtorSection = 0;
  StaticDtorSection = 0;
  LSDASection = 0;
  EHFrameSection = 0;

  DwarfAbbrevSection = 0;
  DwarfInfoSection = 0;
  DwarfLineSection = 0;
  DwarfFrameSection = 0;
  DwarfPubNamesSection = 0;
  DwarfPubTypesSection = 0;
  DwarfDebugInlineSection = 0;
  DwarfStrSection = 0;
  DwarfLocSection = 0;
  DwarfARangesSection = 0;
  DwarfRangesSection = 0;
  DwarfMacroInfoSection = 0;
}

TargetLoweringObjectFile::~TargetLoweringObjectFile() {
}

static bool isSuitableForBSS(const GlobalVariable *GV) {
  Constant *C = GV->getInitializer();

  // Must have zero initializer.
  if (!C->isNullValue())
    return false;

  // Leave constant zeros in readonly constant sections, so they can be shared.
  if (GV->isConstant())
    return false;

  // If the global has an explicit section specified, don't put it in BSS.
  if (!GV->getSection().empty())
    return false;

  // If -nozero-initialized-in-bss is specified, don't ever use BSS.
  if (NoZerosInBSS)
    return false;

  // Otherwise, put it in BSS!
  return true;
}

/// IsNullTerminatedString - Return true if the specified constant (which is
/// known to have a type that is an array of 1/2/4 byte elements) ends with a
/// nul value and contains no other nuls in it.
static bool IsNullTerminatedString(const Constant *C) {
  const ArrayType *ATy = cast<ArrayType>(C->getType());

  // First check: is we have constant array of i8 terminated with zero
  if (const ConstantArray *CVA = dyn_cast<ConstantArray>(C)) {
    if (ATy->getNumElements() == 0) return false;

    ConstantInt *Null =
      dyn_cast<ConstantInt>(CVA->getOperand(ATy->getNumElements()-1));
    if (Null == 0 || Null->getZExtValue() != 0)
      return false; // Not null terminated.

    // Verify that the null doesn't occur anywhere else in the string.
    for (unsigned i = 0, e = ATy->getNumElements()-1; i != e; ++i)
      // Reject constantexpr elements etc.
      if (!isa<ConstantInt>(CVA->getOperand(i)) ||
          CVA->getOperand(i) == Null)
        return false;
    return true;
  }

  // Another possibility: [1 x i8] zeroinitializer
  if (isa<ConstantAggregateZero>(C))
    return ATy->getNumElements() == 1;

  return false;
}

/// getKindForGlobal - This is a top-level target-independent classifier for
/// a global variable.  Given an global variable and information from TM, it
/// classifies the global in a variety of ways that make various target
/// implementations simpler.  The target implementation is free to ignore this
/// extra info of course.
SectionKind TargetLoweringObjectFile::getKindForGlobal(const GlobalValue *GV,
                                                       const TargetMachine &TM){
  assert(!GV->isDeclaration() && !GV->hasAvailableExternallyLinkage() &&
         "Can only be used for global definitions");

  Reloc::Model ReloModel = TM.getRelocationModel();

  // Early exit - functions should be always in text sections.
  const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
  if (GVar == 0)
    return SectionKind::getText();

  // Handle thread-local data first.
  if (GVar->isThreadLocal()) {
    if (isSuitableForBSS(GVar))
      return SectionKind::getThreadBSS();
    return SectionKind::getThreadData();
  }

  // Variables with common linkage always get classified as common.
  if (GVar->hasCommonLinkage())
    return SectionKind::getCommon();

  // Variable can be easily put to BSS section.
  if (isSuitableForBSS(GVar)) {
    if (GVar->hasLocalLinkage())
      return SectionKind::getBSSLocal();
    else if (GVar->hasExternalLinkage())
      return SectionKind::getBSSExtern();
    return SectionKind::getBSS();
  }

  Constant *C = GVar->getInitializer();

  // If the global is marked constant, we can put it into a mergable section,
  // a mergable string section, or general .data if it contains relocations.
  if (GVar->isConstant()) {
    // If the initializer for the global contains something that requires a
    // relocation, then we may have to drop this into a wriable data section
    // even though it is marked const.
    switch (C->getRelocationInfo()) {
    default: assert(0 && "unknown relocation info kind");
    case Constant::NoRelocation:
      // If initializer is a null-terminated string, put it in a "cstring"
      // section of the right width.
      if (const ArrayType *ATy = dyn_cast<ArrayType>(C->getType())) {
        if (const IntegerType *ITy =
              dyn_cast<IntegerType>(ATy->getElementType())) {
          if ((ITy->getBitWidth() == 8 || ITy->getBitWidth() == 16 ||
               ITy->getBitWidth() == 32) &&
              IsNullTerminatedString(C)) {
            if (ITy->getBitWidth() == 8)
              return SectionKind::getMergeable1ByteCString();
            if (ITy->getBitWidth() == 16)
              return SectionKind::getMergeable2ByteCString();

            assert(ITy->getBitWidth() == 32 && "Unknown width");
            return SectionKind::getMergeable4ByteCString();
          }
        }
      }

      // Otherwise, just drop it into a mergable constant section.  If we have
      // a section for this size, use it, otherwise use the arbitrary sized
      // mergable section.
      switch (TM.getTargetData()->getTypeAllocSize(C->getType())) {
      case 4:  return SectionKind::getMergeableConst4();
      case 8:  return SectionKind::getMergeableConst8();
      case 16: return SectionKind::getMergeableConst16();
      default: return SectionKind::getMergeableConst();
      }

    case Constant::LocalRelocation:
      // In static relocation model, the linker will resolve all addresses, so
      // the relocation entries will actually be constants by the time the app
      // starts up.  However, we can't put this into a mergable section, because
      // the linker doesn't take relocations into consideration when it tries to
      // merge entries in the section.
      if (ReloModel == Reloc::Static)
        return SectionKind::getReadOnly();

      // Otherwise, the dynamic linker needs to fix it up, put it in the
      // writable data.rel.local section.
      return SectionKind::getReadOnlyWithRelLocal();

    case Constant::GlobalRelocations:
      // In static relocation model, the linker will resolve all addresses, so
      // the relocation entries will actually be constants by the time the app
      // starts up.  However, we can't put this into a mergable section, because
      // the linker doesn't take relocations into consideration when it tries to
      // merge entries in the section.
      if (ReloModel == Reloc::Static)
        return SectionKind::getReadOnly();

      // Otherwise, the dynamic linker needs to fix it up, put it in the
      // writable data.rel section.
      return SectionKind::getReadOnlyWithRel();
    }
  }

  // Okay, this isn't a constant.  If the initializer for the global is going
  // to require a runtime relocation by the dynamic linker, put it into a more
  // specific section to improve startup time of the app.  This coalesces these
  // globals together onto fewer pages, improving the locality of the dynamic
  // linker.
  if (ReloModel == Reloc::Static)
    return SectionKind::getDataNoRel();

  switch (C->getRelocationInfo()) {
  default: assert(0 && "unknown relocation info kind");
  case Constant::NoRelocation:
    return SectionKind::getDataNoRel();
  case Constant::LocalRelocation:
    return SectionKind::getDataRelLocal();
  case Constant::GlobalRelocations:
    return SectionKind::getDataRel();
  }
}

/// SectionForGlobal - This method computes the appropriate section to emit
/// the specified global variable or function definition.  This should not
/// be passed external (or available externally) globals.
const MCSection *TargetLoweringObjectFile::
SectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang,
                 const TargetMachine &TM) const {
  // Select section name.
  if (GV->hasSection())
    return getExplicitSectionGlobal(GV, Kind, Mang, TM);

  // Use default section depending on the 'type' of global
  return SelectSectionForGlobal(GV, Kind, Mang, TM);
}

// Lame default implementation. Calculate the section name for global.
const MCSection *
TargetLoweringObjectFile::SelectSectionForGlobal(const GlobalValue *GV,
                                                 SectionKind Kind,
                                                 Mangler *Mang,
                                                 const TargetMachine &TM) const{
  assert(!Kind.isThreadLocal() && "Doesn't support TLS");

  if (Kind.isText())
    return getTextSection();

  if (Kind.isBSS() && BSSSection != 0)
    return BSSSection;

  if (Kind.isReadOnly() && ReadOnlySection != 0)
    return ReadOnlySection;

  return getDataSection();
}

/// getSectionForConstant - Given a mergable constant with the
/// specified size and relocation information, return a section that it
/// should be placed in.
const MCSection *
TargetLoweringObjectFile::getSectionForConstant(SectionKind Kind) const {
  if (Kind.isReadOnly() && ReadOnlySection != 0)
    return ReadOnlySection;

  return DataSection;
}

/// getSymbolForDwarfGlobalReference - Return an MCExpr to use for a
/// reference to the specified global variable from exception
/// handling information.
const MCExpr *TargetLoweringObjectFile::
getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang,
                             MachineModuleInfo *MMI, unsigned Encoding) const {
  // FIXME: Use GetGlobalValueSymbol.
  SmallString<128> Name;
  Mang->getNameWithPrefix(Name, GV, false);
  const MCSymbol *Sym = getContext().GetOrCreateSymbol(Name.str());

  return getSymbolForDwarfReference(Sym, MMI, Encoding);
}

const MCExpr *TargetLoweringObjectFile::
getSymbolForDwarfReference(const MCSymbol *Sym, MachineModuleInfo *MMI,
                           unsigned Encoding) const {
  const MCExpr *Res = MCSymbolRefExpr::Create(Sym, getContext());

  switch (Encoding & 0xF0) {
  default:
    llvm_report_error("Do not support this DWARF encoding yet!");
    break;
  case dwarf::DW_EH_PE_absptr:
    // Do nothing special
    break;
  case dwarf::DW_EH_PE_pcrel:
    // FIXME: PCSymbol
    const MCExpr *PC = MCSymbolRefExpr::Create(".", getContext());
    Res = MCBinaryExpr::CreateSub(Res, PC, getContext());
    break;
  }

  return Res;
}

unsigned TargetLoweringObjectFile::getPersonalityEncoding() const {
  return dwarf::DW_EH_PE_absptr;
}

unsigned TargetLoweringObjectFile::getLSDAEncoding() const {
  return dwarf::DW_EH_PE_absptr;
}

unsigned TargetLoweringObjectFile::getFDEEncoding() const {
  return dwarf::DW_EH_PE_absptr;
}

unsigned TargetLoweringObjectFile::getTTypeEncoding() const {
  return dwarf::DW_EH_PE_absptr;
}

<commit_msg>Make error statement more personal.<commit_after>//===-- llvm/Target/TargetLoweringObjectFile.cpp - Object File Info -------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements classes used to handle lowerings specific to common
// object file formats.
//
//===----------------------------------------------------------------------===//

#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/SmallString.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
//                              Generic Code
//===----------------------------------------------------------------------===//

TargetLoweringObjectFile::TargetLoweringObjectFile() : Ctx(0) {
  TextSection = 0;
  DataSection = 0;
  BSSSection = 0;
  ReadOnlySection = 0;
  StaticCtorSection = 0;
  StaticDtorSection = 0;
  LSDASection = 0;
  EHFrameSection = 0;

  DwarfAbbrevSection = 0;
  DwarfInfoSection = 0;
  DwarfLineSection = 0;
  DwarfFrameSection = 0;
  DwarfPubNamesSection = 0;
  DwarfPubTypesSection = 0;
  DwarfDebugInlineSection = 0;
  DwarfStrSection = 0;
  DwarfLocSection = 0;
  DwarfARangesSection = 0;
  DwarfRangesSection = 0;
  DwarfMacroInfoSection = 0;
}

TargetLoweringObjectFile::~TargetLoweringObjectFile() {
}

static bool isSuitableForBSS(const GlobalVariable *GV) {
  Constant *C = GV->getInitializer();

  // Must have zero initializer.
  if (!C->isNullValue())
    return false;

  // Leave constant zeros in readonly constant sections, so they can be shared.
  if (GV->isConstant())
    return false;

  // If the global has an explicit section specified, don't put it in BSS.
  if (!GV->getSection().empty())
    return false;

  // If -nozero-initialized-in-bss is specified, don't ever use BSS.
  if (NoZerosInBSS)
    return false;

  // Otherwise, put it in BSS!
  return true;
}

/// IsNullTerminatedString - Return true if the specified constant (which is
/// known to have a type that is an array of 1/2/4 byte elements) ends with a
/// nul value and contains no other nuls in it.
static bool IsNullTerminatedString(const Constant *C) {
  const ArrayType *ATy = cast<ArrayType>(C->getType());

  // First check: is we have constant array of i8 terminated with zero
  if (const ConstantArray *CVA = dyn_cast<ConstantArray>(C)) {
    if (ATy->getNumElements() == 0) return false;

    ConstantInt *Null =
      dyn_cast<ConstantInt>(CVA->getOperand(ATy->getNumElements()-1));
    if (Null == 0 || Null->getZExtValue() != 0)
      return false; // Not null terminated.

    // Verify that the null doesn't occur anywhere else in the string.
    for (unsigned i = 0, e = ATy->getNumElements()-1; i != e; ++i)
      // Reject constantexpr elements etc.
      if (!isa<ConstantInt>(CVA->getOperand(i)) ||
          CVA->getOperand(i) == Null)
        return false;
    return true;
  }

  // Another possibility: [1 x i8] zeroinitializer
  if (isa<ConstantAggregateZero>(C))
    return ATy->getNumElements() == 1;

  return false;
}

/// getKindForGlobal - This is a top-level target-independent classifier for
/// a global variable.  Given an global variable and information from TM, it
/// classifies the global in a variety of ways that make various target
/// implementations simpler.  The target implementation is free to ignore this
/// extra info of course.
SectionKind TargetLoweringObjectFile::getKindForGlobal(const GlobalValue *GV,
                                                       const TargetMachine &TM){
  assert(!GV->isDeclaration() && !GV->hasAvailableExternallyLinkage() &&
         "Can only be used for global definitions");

  Reloc::Model ReloModel = TM.getRelocationModel();

  // Early exit - functions should be always in text sections.
  const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
  if (GVar == 0)
    return SectionKind::getText();

  // Handle thread-local data first.
  if (GVar->isThreadLocal()) {
    if (isSuitableForBSS(GVar))
      return SectionKind::getThreadBSS();
    return SectionKind::getThreadData();
  }

  // Variables with common linkage always get classified as common.
  if (GVar->hasCommonLinkage())
    return SectionKind::getCommon();

  // Variable can be easily put to BSS section.
  if (isSuitableForBSS(GVar)) {
    if (GVar->hasLocalLinkage())
      return SectionKind::getBSSLocal();
    else if (GVar->hasExternalLinkage())
      return SectionKind::getBSSExtern();
    return SectionKind::getBSS();
  }

  Constant *C = GVar->getInitializer();

  // If the global is marked constant, we can put it into a mergable section,
  // a mergable string section, or general .data if it contains relocations.
  if (GVar->isConstant()) {
    // If the initializer for the global contains something that requires a
    // relocation, then we may have to drop this into a wriable data section
    // even though it is marked const.
    switch (C->getRelocationInfo()) {
    default: assert(0 && "unknown relocation info kind");
    case Constant::NoRelocation:
      // If initializer is a null-terminated string, put it in a "cstring"
      // section of the right width.
      if (const ArrayType *ATy = dyn_cast<ArrayType>(C->getType())) {
        if (const IntegerType *ITy =
              dyn_cast<IntegerType>(ATy->getElementType())) {
          if ((ITy->getBitWidth() == 8 || ITy->getBitWidth() == 16 ||
               ITy->getBitWidth() == 32) &&
              IsNullTerminatedString(C)) {
            if (ITy->getBitWidth() == 8)
              return SectionKind::getMergeable1ByteCString();
            if (ITy->getBitWidth() == 16)
              return SectionKind::getMergeable2ByteCString();

            assert(ITy->getBitWidth() == 32 && "Unknown width");
            return SectionKind::getMergeable4ByteCString();
          }
        }
      }

      // Otherwise, just drop it into a mergable constant section.  If we have
      // a section for this size, use it, otherwise use the arbitrary sized
      // mergable section.
      switch (TM.getTargetData()->getTypeAllocSize(C->getType())) {
      case 4:  return SectionKind::getMergeableConst4();
      case 8:  return SectionKind::getMergeableConst8();
      case 16: return SectionKind::getMergeableConst16();
      default: return SectionKind::getMergeableConst();
      }

    case Constant::LocalRelocation:
      // In static relocation model, the linker will resolve all addresses, so
      // the relocation entries will actually be constants by the time the app
      // starts up.  However, we can't put this into a mergable section, because
      // the linker doesn't take relocations into consideration when it tries to
      // merge entries in the section.
      if (ReloModel == Reloc::Static)
        return SectionKind::getReadOnly();

      // Otherwise, the dynamic linker needs to fix it up, put it in the
      // writable data.rel.local section.
      return SectionKind::getReadOnlyWithRelLocal();

    case Constant::GlobalRelocations:
      // In static relocation model, the linker will resolve all addresses, so
      // the relocation entries will actually be constants by the time the app
      // starts up.  However, we can't put this into a mergable section, because
      // the linker doesn't take relocations into consideration when it tries to
      // merge entries in the section.
      if (ReloModel == Reloc::Static)
        return SectionKind::getReadOnly();

      // Otherwise, the dynamic linker needs to fix it up, put it in the
      // writable data.rel section.
      return SectionKind::getReadOnlyWithRel();
    }
  }

  // Okay, this isn't a constant.  If the initializer for the global is going
  // to require a runtime relocation by the dynamic linker, put it into a more
  // specific section to improve startup time of the app.  This coalesces these
  // globals together onto fewer pages, improving the locality of the dynamic
  // linker.
  if (ReloModel == Reloc::Static)
    return SectionKind::getDataNoRel();

  switch (C->getRelocationInfo()) {
  default: assert(0 && "unknown relocation info kind");
  case Constant::NoRelocation:
    return SectionKind::getDataNoRel();
  case Constant::LocalRelocation:
    return SectionKind::getDataRelLocal();
  case Constant::GlobalRelocations:
    return SectionKind::getDataRel();
  }
}

/// SectionForGlobal - This method computes the appropriate section to emit
/// the specified global variable or function definition.  This should not
/// be passed external (or available externally) globals.
const MCSection *TargetLoweringObjectFile::
SectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang,
                 const TargetMachine &TM) const {
  // Select section name.
  if (GV->hasSection())
    return getExplicitSectionGlobal(GV, Kind, Mang, TM);

  // Use default section depending on the 'type' of global
  return SelectSectionForGlobal(GV, Kind, Mang, TM);
}

// Lame default implementation. Calculate the section name for global.
const MCSection *
TargetLoweringObjectFile::SelectSectionForGlobal(const GlobalValue *GV,
                                                 SectionKind Kind,
                                                 Mangler *Mang,
                                                 const TargetMachine &TM) const{
  assert(!Kind.isThreadLocal() && "Doesn't support TLS");

  if (Kind.isText())
    return getTextSection();

  if (Kind.isBSS() && BSSSection != 0)
    return BSSSection;

  if (Kind.isReadOnly() && ReadOnlySection != 0)
    return ReadOnlySection;

  return getDataSection();
}

/// getSectionForConstant - Given a mergable constant with the
/// specified size and relocation information, return a section that it
/// should be placed in.
const MCSection *
TargetLoweringObjectFile::getSectionForConstant(SectionKind Kind) const {
  if (Kind.isReadOnly() && ReadOnlySection != 0)
    return ReadOnlySection;

  return DataSection;
}

/// getSymbolForDwarfGlobalReference - Return an MCExpr to use for a
/// reference to the specified global variable from exception
/// handling information.
const MCExpr *TargetLoweringObjectFile::
getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang,
                             MachineModuleInfo *MMI, unsigned Encoding) const {
  // FIXME: Use GetGlobalValueSymbol.
  SmallString<128> Name;
  Mang->getNameWithPrefix(Name, GV, false);
  const MCSymbol *Sym = getContext().GetOrCreateSymbol(Name.str());

  return getSymbolForDwarfReference(Sym, MMI, Encoding);
}

const MCExpr *TargetLoweringObjectFile::
getSymbolForDwarfReference(const MCSymbol *Sym, MachineModuleInfo *MMI,
                           unsigned Encoding) const {
  const MCExpr *Res = MCSymbolRefExpr::Create(Sym, getContext());

  switch (Encoding & 0xF0) {
  default:
    llvm_report_error("We do not support this DWARF encoding yet!");
    break;
  case dwarf::DW_EH_PE_absptr:
    // Do nothing special
    break;
  case dwarf::DW_EH_PE_pcrel:
    // FIXME: PCSymbol
    const MCExpr *PC = MCSymbolRefExpr::Create(".", getContext());
    Res = MCBinaryExpr::CreateSub(Res, PC, getContext());
    break;
  }

  return Res;
}

unsigned TargetLoweringObjectFile::getPersonalityEncoding() const {
  return dwarf::DW_EH_PE_absptr;
}

unsigned TargetLoweringObjectFile::getLSDAEncoding() const {
  return dwarf::DW_EH_PE_absptr;
}

unsigned TargetLoweringObjectFile::getFDEEncoding() const {
  return dwarf::DW_EH_PE_absptr;
}

unsigned TargetLoweringObjectFile::getTTypeEncoding() const {
  return dwarf::DW_EH_PE_absptr;
}

<|endoftext|>


<commit_before>//===- InlineFunction.cpp - Code to perform function inlining -------------===//
//
//                     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 implements inlining of a function into a call site, resolving
// parameters and the return value as appropriate.
//
// FIXME: This pass should transform alloca instructions in the called function
// into alloca/dealloca pairs!  Or perhaps it should refuse to inline them!
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Instructions.h"
#include "llvm/Intrinsics.h"
#include "llvm/Support/CallSite.h"
using namespace llvm;

bool llvm::InlineFunction(CallInst *CI) { return InlineFunction(CallSite(CI)); }
bool llvm::InlineFunction(InvokeInst *II) {return InlineFunction(CallSite(II));}

// InlineFunction - This function inlines the called function into the basic
// block of the caller.  This returns false if it is not possible to inline this
// call.  The program is still in a well defined state if this occurs though.
//
// Note that this only does one level of inlining.  For example, if the
// instruction 'call B' is inlined, and 'B' calls 'C', then the call to 'C' now
// exists in the instruction stream.  Similiarly this will inline a recursive
// function by one level.
//
bool llvm::InlineFunction(CallSite CS) {
  Instruction *TheCall = CS.getInstruction();
  assert(TheCall->getParent() && TheCall->getParent()->getParent() &&
         "Instruction not in function!");

  const Function *CalledFunc = CS.getCalledFunction();
  if (CalledFunc == 0 ||          // Can't inline external function or indirect
      CalledFunc->isExternal() || // call, or call to a vararg function!
      CalledFunc->getFunctionType()->isVarArg()) return false;

  BasicBlock *OrigBB = TheCall->getParent();
  Function *Caller = OrigBB->getParent();

  // Get an iterator to the last basic block in the function, which will have
  // the new function inlined after it.
  //
  Function::iterator LastBlock = &Caller->back();

  // Make sure to capture all of the return instructions from the cloned
  // function.
  std::vector<ReturnInst*> Returns;
  { // Scope to destroy ValueMap after cloning.
    // Calculate the vector of arguments to pass into the function cloner...
    std::map<const Value*, Value*> ValueMap;
    assert(std::distance(CalledFunc->abegin(), CalledFunc->aend()) ==
           std::distance(CS.arg_begin(), CS.arg_end()) &&
           "No varargs calls can be inlined!");

    CallSite::arg_iterator AI = CS.arg_begin();
    for (Function::const_aiterator I = CalledFunc->abegin(),
           E = CalledFunc->aend(); I != E; ++I, ++AI)
      ValueMap[I] = *AI;

    // Clone the entire body of the callee into the caller.
    CloneFunctionInto(Caller, CalledFunc, ValueMap, Returns, ".i");
  }

  // Remember the first block that is newly cloned over.
  Function::iterator FirstNewBlock = LastBlock; ++FirstNewBlock;

  // If there are any alloca instructions in the block that used to be the entry
  // block for the callee, move them to the entry block of the caller.  First
  // calculate which instruction they should be inserted before.  We insert the
  // instructions at the end of the current alloca list.
  //
  if (isa<AllocaInst>(FirstNewBlock->begin())) {
    BasicBlock::iterator InsertPoint = Caller->begin()->begin();
    for (BasicBlock::iterator I = FirstNewBlock->begin(),
           E = FirstNewBlock->end(); I != E; )
      if (AllocaInst *AI = dyn_cast<AllocaInst>(I++))
        if (isa<Constant>(AI->getArraySize())) {
          // Scan for the block of allocas that we can move over.
          while (isa<AllocaInst>(I) &&
                 isa<Constant>(cast<AllocaInst>(I)->getArraySize()))
            ++I;

          // Transfer all of the allocas over in a block.  Using splice means
          // that they instructions aren't removed from the symbol table, then
          // reinserted.
          Caller->front().getInstList().splice(InsertPoint,
                                               FirstNewBlock->getInstList(),
                                               AI, I);
        }
  }

  // If we are inlining for an invoke instruction, we must make sure to rewrite
  // any inlined 'unwind' instructions into branches to the invoke exception
  // destination, and call instructions into invoke instructions.
  if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) {
    BasicBlock *InvokeDest = II->getUnwindDest();
    std::vector<Value*> InvokeDestPHIValues;

    // If there are PHI nodes in the exceptional destination block, we need to
    // keep track of which values came into them from this invoke, then remove
    // the entry for this block.
    for (BasicBlock::iterator I = InvokeDest->begin(); isa<PHINode>(I); ++I) {
      PHINode *PN = cast<PHINode>(I);
      // Save the value to use for this edge...
      InvokeDestPHIValues.push_back(PN->getIncomingValueForBlock(OrigBB));
    }

    for (Function::iterator BB = FirstNewBlock, E = Caller->end();
         BB != E; ++BB) {
      for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) {
        // We only need to check for function calls: inlined invoke instructions
        // require no special handling...
        if (CallInst *CI = dyn_cast<CallInst>(I)) {
          // Convert this function call into an invoke instruction... if it's
          // not an intrinsic function call (which are known to not throw).
          if (CI->getCalledFunction() &&
              CI->getCalledFunction()->getIntrinsicID()) {
            ++I;
          } else {
            // First, split the basic block...
            BasicBlock *Split = BB->splitBasicBlock(CI, CI->getName()+".noexc");

            // Next, create the new invoke instruction, inserting it at the end
            // of the old basic block.
            InvokeInst *II =
              new InvokeInst(CI->getCalledValue(), Split, InvokeDest,
                            std::vector<Value*>(CI->op_begin()+1, CI->op_end()),
                             CI->getName(), BB->getTerminator());

            // Make sure that anything using the call now uses the invoke!
            CI->replaceAllUsesWith(II);

            // Delete the unconditional branch inserted by splitBasicBlock
            BB->getInstList().pop_back();
            Split->getInstList().pop_front();  // Delete the original call

            // Update any PHI nodes in the exceptional block to indicate that
            // there is now a new entry in them.
            unsigned i = 0;
            for (BasicBlock::iterator I = InvokeDest->begin();
                 isa<PHINode>(I); ++I, ++i) {
              PHINode *PN = cast<PHINode>(I);
              PN->addIncoming(InvokeDestPHIValues[i], BB);
            }

            // This basic block is now complete, start scanning the next one.
            break;
          }
        } else {
          ++I;
        }
      }

      if (UnwindInst *UI = dyn_cast<UnwindInst>(BB->getTerminator())) {
        // An UnwindInst requires special handling when it gets inlined into an
        // invoke site.  Once this happens, we know that the unwind would cause
        // a control transfer to the invoke exception destination, so we can
        // transform it into a direct branch to the exception destination.
        new BranchInst(InvokeDest, UI);

        // Delete the unwind instruction!
        UI->getParent()->getInstList().pop_back();

        // Update any PHI nodes in the exceptional block to indicate that
        // there is now a new entry in them.
        unsigned i = 0;
        for (BasicBlock::iterator I = InvokeDest->begin();
             isa<PHINode>(I); ++I, ++i) {
          PHINode *PN = cast<PHINode>(I);
          PN->addIncoming(InvokeDestPHIValues[i], BB);
        }
      }
    }

    // Now that everything is happy, we have one final detail.  The PHI nodes in
    // the exception destination block still have entries due to the original
    // invoke instruction.  Eliminate these entries (which might even delete the
    // PHI node) now.
    InvokeDest->removePredecessor(II->getParent());
  }

  // If we cloned in _exactly one_ basic block, and if that block ends in a
  // return instruction, we splice the body of the inlined callee directly into
  // the calling basic block.
  if (Returns.size() == 1 && std::distance(FirstNewBlock, Caller->end()) == 1) {
    // Move all of the instructions right before the call.
    OrigBB->getInstList().splice(TheCall, FirstNewBlock->getInstList(),
                                 FirstNewBlock->begin(), FirstNewBlock->end());
    // Remove the cloned basic block.
    Caller->getBasicBlockList().pop_back();

    // If the call site was an invoke instruction, add a branch to the normal
    // destination.
    if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall))
      new BranchInst(II->getNormalDest(), TheCall);

    // If the return instruction returned a value, replace uses of the call with
    // uses of the returned value.
    if (!TheCall->use_empty())
      TheCall->replaceAllUsesWith(Returns[0]->getReturnValue());

    // Since we are now done with the Call/Invoke, we can delete it.
    TheCall->getParent()->getInstList().erase(TheCall);

    // Since we are now done with the return instruction, delete it also.
    Returns[0]->getParent()->getInstList().erase(Returns[0]);

    // We are now done with the inlining.
    return true;
  }

  // Otherwise, we have the normal case, of more than one block to inline or
  // multiple return sites.

  // We want to clone the entire callee function into the hole between the
  // "starter" and "ender" blocks.  How we accomplish this depends on whether
  // this is an invoke instruction or a call instruction.
  BasicBlock *AfterCallBB;
  if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) {

    // Add an unconditional branch to make this look like the CallInst case...
    BranchInst *NewBr = new BranchInst(II->getNormalDest(), TheCall);

    // Split the basic block.  This guarantees that no PHI nodes will have to be
    // updated due to new incoming edges, and make the invoke case more
    // symmetric to the call case.
    AfterCallBB = OrigBB->splitBasicBlock(NewBr,
                                          CalledFunc->getName()+".entry");

  } else {  // It's a call
    // If this is a call instruction, we need to split the basic block that
    // the call lives in.
    //
    AfterCallBB = OrigBB->splitBasicBlock(TheCall,
                                          CalledFunc->getName()+".entry");
  }

  // Change the branch that used to go to AfterCallBB to branch to the first
  // basic block of the inlined function.
  //
  TerminatorInst *Br = OrigBB->getTerminator();
  assert(Br && Br->getOpcode() == Instruction::Br &&
         "splitBasicBlock broken!");
  Br->setOperand(0, FirstNewBlock);

  // Now that the function is correct, make it a little bit nicer.  In
  // particular, move the basic blocks inserted from the end of the function
  // into the space made by splitting the source basic block.
  //
  Caller->getBasicBlockList().splice(AfterCallBB, Caller->getBasicBlockList(),
                                     FirstNewBlock, Caller->end());

  // Handle all of the return instructions that we just cloned in, and eliminate
  // any users of the original call/invoke instruction.
  if (Returns.size() > 1) {
    // The PHI node should go at the front of the new basic block to merge all
    // possible incoming values.
    //
    PHINode *PHI = 0;
    if (!TheCall->use_empty()) {
      PHI = new PHINode(CalledFunc->getReturnType(),
                        TheCall->getName(), AfterCallBB->begin());

      // Anything that used the result of the function call should now use the
      // PHI node as their operand.
      //
      TheCall->replaceAllUsesWith(PHI);
    }

    // Loop over all of the return instructions, turning them into unconditional
    // branches to the merge point now, and adding entries to the PHI node as
    // appropriate.
    for (unsigned i = 0, e = Returns.size(); i != e; ++i) {
      ReturnInst *RI = Returns[i];

      if (PHI) {
        assert(RI->getReturnValue() && "Ret should have value!");
        assert(RI->getReturnValue()->getType() == PHI->getType() &&
               "Ret value not consistent in function!");
        PHI->addIncoming(RI->getReturnValue(), RI->getParent());
      }

      // Add a branch to the merge point where the PHI node lives if it exists.
      new BranchInst(AfterCallBB, RI);

      // Delete the return instruction now
      RI->getParent()->getInstList().erase(RI);
    }

  } else if (!Returns.empty()) {
    // Otherwise, if there is exactly one return value, just replace anything
    // using the return value of the call with the computed value.
    if (!TheCall->use_empty())
      TheCall->replaceAllUsesWith(Returns[0]->getReturnValue());

    // Splice the code from the return block into the block that it will return
    // to, which contains the code that was after the call.
    BasicBlock *ReturnBB = Returns[0]->getParent();
    AfterCallBB->getInstList().splice(AfterCallBB->begin(),
                                      ReturnBB->getInstList());

    // Update PHI nodes that use the ReturnBB to use the AfterCallBB.
    ReturnBB->replaceAllUsesWith(AfterCallBB);

    // Delete the return instruction now and empty ReturnBB now.
    Returns[0]->eraseFromParent();
    ReturnBB->eraseFromParent();
  } else if (!TheCall->use_empty()) {
    // No returns, but something is using the return value of the call.  Just
    // nuke the result.
    TheCall->replaceAllUsesWith(UndefValue::get(TheCall->getType()));
  }

  // Since we are now done with the Call/Invoke, we can delete it.
  TheCall->eraseFromParent();

  // We should always be able to fold the entry block of the function into the
  // single predecessor of the block...
  assert(cast<BranchInst>(Br)->isUnconditional() && "splitBasicBlock broken!");
  BasicBlock *CalleeEntry = cast<BranchInst>(Br)->getSuccessor(0);

  // Splice the code entry block into calling block, right before the
  // unconditional branch.
  OrigBB->getInstList().splice(Br, CalleeEntry->getInstList());
  CalleeEntry->replaceAllUsesWith(OrigBB);  // Update PHI nodes

  // Remove the unconditional branch.
  OrigBB->getInstList().erase(Br);

  // Now we can remove the CalleeEntry block, which is now empty.
  Caller->getBasicBlockList().erase(CalleeEntry);
  return true;
}
<commit_msg>The split bb is really the exit of the old function<commit_after>//===- InlineFunction.cpp - Code to perform function inlining -------------===//
//
//                     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 implements inlining of a function into a call site, resolving
// parameters and the return value as appropriate.
//
// FIXME: This pass should transform alloca instructions in the called function
// into alloca/dealloca pairs!  Or perhaps it should refuse to inline them!
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Instructions.h"
#include "llvm/Intrinsics.h"
#include "llvm/Support/CallSite.h"
using namespace llvm;

bool llvm::InlineFunction(CallInst *CI) { return InlineFunction(CallSite(CI)); }
bool llvm::InlineFunction(InvokeInst *II) {return InlineFunction(CallSite(II));}

// InlineFunction - This function inlines the called function into the basic
// block of the caller.  This returns false if it is not possible to inline this
// call.  The program is still in a well defined state if this occurs though.
//
// Note that this only does one level of inlining.  For example, if the
// instruction 'call B' is inlined, and 'B' calls 'C', then the call to 'C' now
// exists in the instruction stream.  Similiarly this will inline a recursive
// function by one level.
//
bool llvm::InlineFunction(CallSite CS) {
  Instruction *TheCall = CS.getInstruction();
  assert(TheCall->getParent() && TheCall->getParent()->getParent() &&
         "Instruction not in function!");

  const Function *CalledFunc = CS.getCalledFunction();
  if (CalledFunc == 0 ||          // Can't inline external function or indirect
      CalledFunc->isExternal() || // call, or call to a vararg function!
      CalledFunc->getFunctionType()->isVarArg()) return false;

  BasicBlock *OrigBB = TheCall->getParent();
  Function *Caller = OrigBB->getParent();

  // Get an iterator to the last basic block in the function, which will have
  // the new function inlined after it.
  //
  Function::iterator LastBlock = &Caller->back();

  // Make sure to capture all of the return instructions from the cloned
  // function.
  std::vector<ReturnInst*> Returns;
  { // Scope to destroy ValueMap after cloning.
    // Calculate the vector of arguments to pass into the function cloner...
    std::map<const Value*, Value*> ValueMap;
    assert(std::distance(CalledFunc->abegin(), CalledFunc->aend()) ==
           std::distance(CS.arg_begin(), CS.arg_end()) &&
           "No varargs calls can be inlined!");

    CallSite::arg_iterator AI = CS.arg_begin();
    for (Function::const_aiterator I = CalledFunc->abegin(),
           E = CalledFunc->aend(); I != E; ++I, ++AI)
      ValueMap[I] = *AI;

    // Clone the entire body of the callee into the caller.
    CloneFunctionInto(Caller, CalledFunc, ValueMap, Returns, ".i");
  }

  // Remember the first block that is newly cloned over.
  Function::iterator FirstNewBlock = LastBlock; ++FirstNewBlock;

  // If there are any alloca instructions in the block that used to be the entry
  // block for the callee, move them to the entry block of the caller.  First
  // calculate which instruction they should be inserted before.  We insert the
  // instructions at the end of the current alloca list.
  //
  if (isa<AllocaInst>(FirstNewBlock->begin())) {
    BasicBlock::iterator InsertPoint = Caller->begin()->begin();
    for (BasicBlock::iterator I = FirstNewBlock->begin(),
           E = FirstNewBlock->end(); I != E; )
      if (AllocaInst *AI = dyn_cast<AllocaInst>(I++))
        if (isa<Constant>(AI->getArraySize())) {
          // Scan for the block of allocas that we can move over.
          while (isa<AllocaInst>(I) &&
                 isa<Constant>(cast<AllocaInst>(I)->getArraySize()))
            ++I;

          // Transfer all of the allocas over in a block.  Using splice means
          // that they instructions aren't removed from the symbol table, then
          // reinserted.
          Caller->front().getInstList().splice(InsertPoint,
                                               FirstNewBlock->getInstList(),
                                               AI, I);
        }
  }

  // If we are inlining for an invoke instruction, we must make sure to rewrite
  // any inlined 'unwind' instructions into branches to the invoke exception
  // destination, and call instructions into invoke instructions.
  if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) {
    BasicBlock *InvokeDest = II->getUnwindDest();
    std::vector<Value*> InvokeDestPHIValues;

    // If there are PHI nodes in the exceptional destination block, we need to
    // keep track of which values came into them from this invoke, then remove
    // the entry for this block.
    for (BasicBlock::iterator I = InvokeDest->begin(); isa<PHINode>(I); ++I) {
      PHINode *PN = cast<PHINode>(I);
      // Save the value to use for this edge...
      InvokeDestPHIValues.push_back(PN->getIncomingValueForBlock(OrigBB));
    }

    for (Function::iterator BB = FirstNewBlock, E = Caller->end();
         BB != E; ++BB) {
      for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) {
        // We only need to check for function calls: inlined invoke instructions
        // require no special handling...
        if (CallInst *CI = dyn_cast<CallInst>(I)) {
          // Convert this function call into an invoke instruction... if it's
          // not an intrinsic function call (which are known to not throw).
          if (CI->getCalledFunction() &&
              CI->getCalledFunction()->getIntrinsicID()) {
            ++I;
          } else {
            // First, split the basic block...
            BasicBlock *Split = BB->splitBasicBlock(CI, CI->getName()+".noexc");

            // Next, create the new invoke instruction, inserting it at the end
            // of the old basic block.
            InvokeInst *II =
              new InvokeInst(CI->getCalledValue(), Split, InvokeDest,
                            std::vector<Value*>(CI->op_begin()+1, CI->op_end()),
                             CI->getName(), BB->getTerminator());

            // Make sure that anything using the call now uses the invoke!
            CI->replaceAllUsesWith(II);

            // Delete the unconditional branch inserted by splitBasicBlock
            BB->getInstList().pop_back();
            Split->getInstList().pop_front();  // Delete the original call

            // Update any PHI nodes in the exceptional block to indicate that
            // there is now a new entry in them.
            unsigned i = 0;
            for (BasicBlock::iterator I = InvokeDest->begin();
                 isa<PHINode>(I); ++I, ++i) {
              PHINode *PN = cast<PHINode>(I);
              PN->addIncoming(InvokeDestPHIValues[i], BB);
            }

            // This basic block is now complete, start scanning the next one.
            break;
          }
        } else {
          ++I;
        }
      }

      if (UnwindInst *UI = dyn_cast<UnwindInst>(BB->getTerminator())) {
        // An UnwindInst requires special handling when it gets inlined into an
        // invoke site.  Once this happens, we know that the unwind would cause
        // a control transfer to the invoke exception destination, so we can
        // transform it into a direct branch to the exception destination.
        new BranchInst(InvokeDest, UI);

        // Delete the unwind instruction!
        UI->getParent()->getInstList().pop_back();

        // Update any PHI nodes in the exceptional block to indicate that
        // there is now a new entry in them.
        unsigned i = 0;
        for (BasicBlock::iterator I = InvokeDest->begin();
             isa<PHINode>(I); ++I, ++i) {
          PHINode *PN = cast<PHINode>(I);
          PN->addIncoming(InvokeDestPHIValues[i], BB);
        }
      }
    }

    // Now that everything is happy, we have one final detail.  The PHI nodes in
    // the exception destination block still have entries due to the original
    // invoke instruction.  Eliminate these entries (which might even delete the
    // PHI node) now.
    InvokeDest->removePredecessor(II->getParent());
  }

  // If we cloned in _exactly one_ basic block, and if that block ends in a
  // return instruction, we splice the body of the inlined callee directly into
  // the calling basic block.
  if (Returns.size() == 1 && std::distance(FirstNewBlock, Caller->end()) == 1) {
    // Move all of the instructions right before the call.
    OrigBB->getInstList().splice(TheCall, FirstNewBlock->getInstList(),
                                 FirstNewBlock->begin(), FirstNewBlock->end());
    // Remove the cloned basic block.
    Caller->getBasicBlockList().pop_back();

    // If the call site was an invoke instruction, add a branch to the normal
    // destination.
    if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall))
      new BranchInst(II->getNormalDest(), TheCall);

    // If the return instruction returned a value, replace uses of the call with
    // uses of the returned value.
    if (!TheCall->use_empty())
      TheCall->replaceAllUsesWith(Returns[0]->getReturnValue());

    // Since we are now done with the Call/Invoke, we can delete it.
    TheCall->getParent()->getInstList().erase(TheCall);

    // Since we are now done with the return instruction, delete it also.
    Returns[0]->getParent()->getInstList().erase(Returns[0]);

    // We are now done with the inlining.
    return true;
  }

  // Otherwise, we have the normal case, of more than one block to inline or
  // multiple return sites.

  // We want to clone the entire callee function into the hole between the
  // "starter" and "ender" blocks.  How we accomplish this depends on whether
  // this is an invoke instruction or a call instruction.
  BasicBlock *AfterCallBB;
  if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) {

    // Add an unconditional branch to make this look like the CallInst case...
    BranchInst *NewBr = new BranchInst(II->getNormalDest(), TheCall);

    // Split the basic block.  This guarantees that no PHI nodes will have to be
    // updated due to new incoming edges, and make the invoke case more
    // symmetric to the call case.
    AfterCallBB = OrigBB->splitBasicBlock(NewBr,
                                          CalledFunc->getName()+".exit");

  } else {  // It's a call
    // If this is a call instruction, we need to split the basic block that
    // the call lives in.
    //
    AfterCallBB = OrigBB->splitBasicBlock(TheCall,
                                          CalledFunc->getName()+".exit");
  }

  // Change the branch that used to go to AfterCallBB to branch to the first
  // basic block of the inlined function.
  //
  TerminatorInst *Br = OrigBB->getTerminator();
  assert(Br && Br->getOpcode() == Instruction::Br &&
         "splitBasicBlock broken!");
  Br->setOperand(0, FirstNewBlock);

  // Now that the function is correct, make it a little bit nicer.  In
  // particular, move the basic blocks inserted from the end of the function
  // into the space made by splitting the source basic block.
  //
  Caller->getBasicBlockList().splice(AfterCallBB, Caller->getBasicBlockList(),
                                     FirstNewBlock, Caller->end());

  // Handle all of the return instructions that we just cloned in, and eliminate
  // any users of the original call/invoke instruction.
  if (Returns.size() > 1) {
    // The PHI node should go at the front of the new basic block to merge all
    // possible incoming values.
    //
    PHINode *PHI = 0;
    if (!TheCall->use_empty()) {
      PHI = new PHINode(CalledFunc->getReturnType(),
                        TheCall->getName(), AfterCallBB->begin());

      // Anything that used the result of the function call should now use the
      // PHI node as their operand.
      //
      TheCall->replaceAllUsesWith(PHI);
    }

    // Loop over all of the return instructions, turning them into unconditional
    // branches to the merge point now, and adding entries to the PHI node as
    // appropriate.
    for (unsigned i = 0, e = Returns.size(); i != e; ++i) {
      ReturnInst *RI = Returns[i];

      if (PHI) {
        assert(RI->getReturnValue() && "Ret should have value!");
        assert(RI->getReturnValue()->getType() == PHI->getType() &&
               "Ret value not consistent in function!");
        PHI->addIncoming(RI->getReturnValue(), RI->getParent());
      }

      // Add a branch to the merge point where the PHI node lives if it exists.
      new BranchInst(AfterCallBB, RI);

      // Delete the return instruction now
      RI->getParent()->getInstList().erase(RI);
    }

  } else if (!Returns.empty()) {
    // Otherwise, if there is exactly one return value, just replace anything
    // using the return value of the call with the computed value.
    if (!TheCall->use_empty())
      TheCall->replaceAllUsesWith(Returns[0]->getReturnValue());

    // Splice the code from the return block into the block that it will return
    // to, which contains the code that was after the call.
    BasicBlock *ReturnBB = Returns[0]->getParent();
    AfterCallBB->getInstList().splice(AfterCallBB->begin(),
                                      ReturnBB->getInstList());

    // Update PHI nodes that use the ReturnBB to use the AfterCallBB.
    ReturnBB->replaceAllUsesWith(AfterCallBB);

    // Delete the return instruction now and empty ReturnBB now.
    Returns[0]->eraseFromParent();
    ReturnBB->eraseFromParent();
  } else if (!TheCall->use_empty()) {
    // No returns, but something is using the return value of the call.  Just
    // nuke the result.
    TheCall->replaceAllUsesWith(UndefValue::get(TheCall->getType()));
  }

  // Since we are now done with the Call/Invoke, we can delete it.
  TheCall->eraseFromParent();

  // We should always be able to fold the entry block of the function into the
  // single predecessor of the block...
  assert(cast<BranchInst>(Br)->isUnconditional() && "splitBasicBlock broken!");
  BasicBlock *CalleeEntry = cast<BranchInst>(Br)->getSuccessor(0);

  // Splice the code entry block into calling block, right before the
  // unconditional branch.
  OrigBB->getInstList().splice(Br, CalleeEntry->getInstList());
  CalleeEntry->replaceAllUsesWith(OrigBB);  // Update PHI nodes

  // Remove the unconditional branch.
  OrigBB->getInstList().erase(Br);

  // Now we can remove the CalleeEntry block, which is now empty.
  Caller->getBasicBlockList().erase(CalleeEntry);
  return true;
}
<|endoftext|>


<commit_before>#include <m3conf/tokenizer.h>
#include <test/XTest.h>

XTS_TEST(TokenizerTests, testSingleChars) {
	struct Token* t;
	struct Token* c;
	std::string data = "{}=;";
	XTS_ASSERT_EQUALS(0, tokenize(data.c_str(), data.length(), &t));
	c = t;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_LB, c->type);
	XTS_ASSERT_EQUALS(std::string("{"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_RB, c->type);
	XTS_ASSERT_EQUALS(std::string("}"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_EQ, c->type);
	XTS_ASSERT_EQUALS(std::string("="), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_SEMI, c->type);
	XTS_ASSERT_EQUALS(std::string(";"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_EOF, c->type);
	XTS_ASSERT_EQUALS(std::string(""), c->value);
	XTS_ASSERT_EQUALS(NULL, c->next);

	free_tokens(t);
}

XTS_TEST(TokenizerTests, testValidInt) {
	struct Token* t;
	struct Token* c;
	std::string data = "01234-44";
	XTS_ASSERT_EQUALS(0, tokenize(data.c_str(), data.length(), &t));
	c = t;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_INT, c->type);
	XTS_ASSERT_EQUALS(std::string("0"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_INT, c->type);
	XTS_ASSERT_EQUALS(std::string("1234"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_INT, c->type);
	XTS_ASSERT_EQUALS(std::string("-44"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_EOF, c->type);
	XTS_ASSERT_EQUALS(std::string(""), c->value);
	XTS_ASSERT_EQUALS(NULL, c->next);

	free_tokens(t);
}

XTS_TEST(TokenizerTests, testValidStr) {
	struct Token* t;
	struct Token* c;
	std::string data = "\"aoeu\"\"\\\"quote\"\"\\\\\\\"\"";
	XTS_ASSERT_EQUALS(0, tokenize(data.c_str(), data.length(), &t));
	c = t;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_STR, c->type);
	XTS_ASSERT_EQUALS(std::string("aoeu"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_STR, c->type);
	XTS_ASSERT_EQUALS(std::string("\"quote"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_STR, c->type);
	XTS_ASSERT_EQUALS(std::string("\\\""), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_EOF, c->type);
	XTS_ASSERT_EQUALS(std::string(""), c->value);
	XTS_ASSERT_EQUALS(NULL, c->next);

	free_tokens(t);
}

XTS_TEST(TokenizerTests, testValidId) {
	struct Token* t;
	struct Token* c;
	std::string data = "aoeu AOEU a1 section _ _._";
	XTS_ASSERT_EQUALS(0, tokenize(data.c_str(), data.length(), &t));
	c = t;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_ID, c->type);
	XTS_ASSERT_EQUALS(std::string("aoeu"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_ID, c->type);
	XTS_ASSERT_EQUALS(std::string("AOEU"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_ID, c->type);
	XTS_ASSERT_EQUALS(std::string("a1"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_ID, c->type);
	XTS_ASSERT_EQUALS(std::string("section"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_ID, c->type);
	XTS_ASSERT_EQUALS(std::string("_"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_ID, c->type);
	XTS_ASSERT_EQUALS(std::string("_._"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_EOF, c->type);
	XTS_ASSERT_EQUALS(std::string(""), c->value);
	XTS_ASSERT_EQUALS(NULL, c->next);

	free_tokens(t);
}
<commit_msg>Adding a couple more tokenizer tests.<commit_after>#include <m3conf/tokenizer.h>
#include <test/XTest.h>

XTS_TEST(TokenizerTests, testSingleChars) {
	struct Token* t;
	struct Token* c;
	std::string data = "{}=;";
	XTS_ASSERT_EQUALS(0, tokenize(data.c_str(), data.length(), &t));
	c = t;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_LB, c->type);
	XTS_ASSERT_EQUALS(std::string("{"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_RB, c->type);
	XTS_ASSERT_EQUALS(std::string("}"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_EQ, c->type);
	XTS_ASSERT_EQUALS(std::string("="), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_SEMI, c->type);
	XTS_ASSERT_EQUALS(std::string(";"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_EOF, c->type);
	XTS_ASSERT_EQUALS(std::string(""), c->value);
	XTS_ASSERT_EQUALS(NULL, c->next);

	free_tokens(t);
}

XTS_TEST(TokenizerTests, testValidInt) {
	struct Token* t;
	struct Token* c;
	std::string data = "01234-44";
	XTS_ASSERT_EQUALS(0, tokenize(data.c_str(), data.length(), &t));
	c = t;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_INT, c->type);
	XTS_ASSERT_EQUALS(std::string("0"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_INT, c->type);
	XTS_ASSERT_EQUALS(std::string("1234"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_INT, c->type);
	XTS_ASSERT_EQUALS(std::string("-44"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_EOF, c->type);
	XTS_ASSERT_EQUALS(std::string(""), c->value);
	XTS_ASSERT_EQUALS(NULL, c->next);

	free_tokens(t);
}

XTS_TEST(TokenizerTests, testValidStr) {
	struct Token* t;
	struct Token* c;
	std::string data = "\"aoeu\"\"\\\"quote\"\"\\\\\\\"\"";
	XTS_ASSERT_EQUALS(0, tokenize(data.c_str(), data.length(), &t));
	c = t;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_STR, c->type);
	XTS_ASSERT_EQUALS(std::string("aoeu"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_STR, c->type);
	XTS_ASSERT_EQUALS(std::string("\"quote"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_STR, c->type);
	XTS_ASSERT_EQUALS(std::string("\\\""), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_EOF, c->type);
	XTS_ASSERT_EQUALS(std::string(""), c->value);
	XTS_ASSERT_EQUALS(NULL, c->next);

	free_tokens(t);
}

XTS_TEST(TokenizerTests, testValidId) {
	struct Token* t;
	struct Token* c;
	std::string data = "aoeu AOEU a1 section _ _._";
	XTS_ASSERT_EQUALS(0, tokenize(data.c_str(), data.length(), &t));
	c = t;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_ID, c->type);
	XTS_ASSERT_EQUALS(std::string("aoeu"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_ID, c->type);
	XTS_ASSERT_EQUALS(std::string("AOEU"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_ID, c->type);
	XTS_ASSERT_EQUALS(std::string("a1"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_ID, c->type);
	XTS_ASSERT_EQUALS(std::string("section"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_ID, c->type);
	XTS_ASSERT_EQUALS(std::string("_"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_ID, c->type);
	XTS_ASSERT_EQUALS(std::string("_._"), c->value);
	c = c->next;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_EOF, c->type);
	XTS_ASSERT_EQUALS(std::string(""), c->value);
	XTS_ASSERT_EQUALS(NULL, c->next);

	free_tokens(t);
}

XTS_TEST(TokenizerTests, testValidWhiteSpace) {
	struct Token* t;
	struct Token* c;
	std::string data = " \t\n\r";
	XTS_ASSERT_EQUALS(0, tokenize(data.c_str(), data.length(), &t));
	c = t;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_EOF, c->type);
	XTS_ASSERT_EQUALS(std::string(""), c->value);
	XTS_ASSERT_EQUALS(NULL, c->next);

	free_tokens(t);
}

XTS_TEST(TokenizerTests, testValidComment) {
	struct Token* t;
	struct Token* c;
	std::string data = "#comment \t comment\r\n#comment";
	XTS_ASSERT_EQUALS(0, tokenize(data.c_str(), data.length(), &t));
	c = t;
	XTS_ASSERT_DIFFERS(NULL, c);
	XTS_ASSERT_EQUALS(TOK_EOF, c->type);
	XTS_ASSERT_EQUALS(std::string(""), c->value);
	XTS_ASSERT_EQUALS(NULL, c->next);

	free_tokens(t);
}
<|endoftext|>


<commit_before>#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <boost/lexical_cast.hpp>
#include "packet.h"

#define USAGE "Usage:\r\nc \r\n[tux machine number] \r\n[probability of packet corruption in int form] \r\n[probability of packet loss in int form] \r\n[probability of packet delay] \r\n[length of delay in ms] \r\n"
#define PORT 10038
#define PAKSIZE 512
#define ACK 0
#define NAK 1
#define BUFSIZE 505
#define FILENAME "Testfile"
#define TIMEOUT 100 //in ms
#define WIN_SIZE 16

using namespace std;

bool isvpack(unsigned char * p);
bool init(int argc, char** argv);
bool loadFile();
bool getFile();
bool sendFile();
bool isAck();
void handleAck();
void handleNak(int& x);
bool* gremlin(Packet * pack, int corruptProb, int lossProb, int delayProb);
Packet createPacket(int index);
void loadWindow();
bool sendPacket();
bool getGet();

struct sockaddr_in a;
struct sockaddr_in ca;
socklen_t calen;
int rlen;
int s;
bool ack;
string fstr;
char * file;
int probCorrupt;
int probLoss;
int probDelay;
int delayT;
Packet p;
Packet window[16];
int length;
bool dropPck;
bool delayPck;
int toms;
unsigned char b[BUFSIZE];
int base;

int main(int argc, char** argv) {

  if(!init(argc, argv)) return -1;

  sendFile();

  return 0;
}

bool init(int argc, char** argv){

  if(argc != 6) {
    cout << USAGE << endl;
    return false;
  }

  char * probCorruptStr = argv[2];
  probCorrupt = boost::lexical_cast<int>(probCorruptStr);
  char * probLossStr = argv[3];
  probLoss = boost::lexical_cast<int>(probLossStr);
  char * probDelayStr = argv[4];
  probDelay = boost::lexical_cast<int>(probDelayStr);
  char* delayTStr = argv[5];
  delayT = boost::lexical_cast<int>(delayTStr);

  struct timeval timeout;
  timeout.tv_usec = TIMEOUT * 1000;
  toms = TIMEOUT;

  /* Create our socket. */
  if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    cout << "Socket creation failed. (socket s)" << endl;
    return 0;
  }

  setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));

  /*
   * Bind our socket to an IP (whatever the computer decides)
   * and a specified port.
   *
   */

  if (!loadFile()) {
    cout << "Loading file failed. (filename FILENAME)" << endl;
    return false;
  }

  memset((char *)&a, 0, sizeof(a));
  a.sin_family = AF_INET;
  a.sin_addr.s_addr = htonl(INADDR_ANY);
  a.sin_port = htons(PORT);

  if (bind(s, (struct sockaddr *)&a, sizeof(a)) < 0) {
    cout << "Socket binding failed. (socket s, address a)" << endl;
    return 0;
  }

  fstr = string(file);
  cout << "File: " << endl << fstr << endl;

  base = 0;
  dropPck = false;
  calen = sizeof(ca);

  getGet();

  return true;
}

bool getGet(){
	unsigned char packet[PAKSIZE + 1];
	rlen = recvfrom(s, packet, PAKSIZE, 0, (struct sockaddr *)&ca, &calen);
	return (rlen > 0) ? true : false;
}

bool isvpack(unsigned char * p) {
  cout << endl << "=== IS VALID PACKET TESTING" << endl;

  char * sns = new char[2];
  memcpy(sns, &p[0], 1);
  sns[1] = '\0';

  char * css = new char[7];
  memcpy(css, &p[1], 6);
  css[6] = '\0';

  char * db = new char[121 + 1];
  memcpy(db, &p[2], 121);
  db[121] = '\0';

  cout << "Seq. num: " << sns << endl;
  cout << "Checksum: " << css << endl;
  cout << "Message: " << db << endl;

  int sn = boost::lexical_cast<int>(sns);
  int cs = boost::lexical_cast<int>(css);

  Packet pk (0, db);
  pk.setSequenceNum(sn);

  // change to validate based on checksum and sequence number

  if(sn == 0) return false; //doesn't matter, only for the old version (netwark)
  if(cs != pk.generateCheckSum()) return false;
  return true;
}

bool getFile(){

  /* Loop forever, waiting for messages from a client. */
  cout << "Waiting on port " << PORT << "..." << endl;

  ofstream file("Dumpfile");

  for (;;) {
    unsigned char packet[PAKSIZE + 1];
    unsigned char dataPull[PAKSIZE - 7 + 1];
    rlen = recvfrom(s, packet, PAKSIZE, 0, (struct sockaddr *)&ca, &calen);

    for(int x = 0; x < PAKSIZE - 7; x++) {
      dataPull[x] = packet[x + 7];
    }
    dataPull[PAKSIZE - 7] = '\0';
    packet[PAKSIZE] = '\0';
    if (rlen > 0) {
      char * css = new char[6];
      memcpy(css, &packet[1], 5);
      css[5] = '\0';
      cout << endl << endl << "=== RECEIPT" << endl;
      cout << "Seq. num: " << packet[0] << endl;
      cout << "Checksum: " << css << endl;
      cout << "Received message: " << dataPull << endl;
      cout << "Sent response: ";
      if(isvpack(packet)) {
        ack = ACK;
        //seqNum = (seqNum) ? false : true;
        file << dataPull;
      } else {
        ack = NAK;
      }
      cout << ((ack == ACK) ? "ACK" : "NAK") << endl;
      Packet p (false, reinterpret_cast<const char *>(dataPull));
      p.setCheckSum(boost::lexical_cast<int>(css));
      p.setAckNack(ack);

      if(sendto(s, p.str(), PAKSIZE, 0, (struct sockaddr *)&ca, calen) < 0) {
        cout << "Acknowledgement failed. (socket s, acknowledgement message ack, client address ca, client address length calen)" << endl;
        return 0;
      }
      delete css;
    }
  }
  file.close();
  return true;
}

bool loadFile() {

  ifstream is (FILENAME, ifstream::binary);

  if(is) {
    is.seekg(0, is.end);
    length = is.tellg();
    is.seekg(0, is.beg);

    file = new char[length];

    cout << "Reading " << length << " characters..." << endl;
    is.read(file, length);

    if(!is) { cout << "File reading failed. (filename " << FILENAME << "). Only " << is.gcount() << " could be read."; return false; }
    is.close();
  }
  return true;
}

void loadWindow(){
	for(int i = base; i < base + WIN_SIZE; i++) {
		window[i-base] = createPacket(i);
		/*if(strlen(window[i-base].getDataBuffer()) < BUFSIZE && window[i-base].chksm()) {
			cout << "In loadWindow's secret base, index is: " << i-base << endl;*/
			/*for(++i; i < base + WIN_SIZE; i++){
				window[i-base].loadDataBuffer("\0");
			}*/
			/*return;
		}*/
		/*cout << "window[i-base] seq. num: " << window[i-base].getSequenceNum() << endl;*/
	}

		/*cout << "packet " << base + 1 << ": " << window[1].str() << endl;
		cout << "packet " << base + 2 << ": " << window[2].str() << endl;*/
}

bool sendFile() {
	/*Currently causes the program to only send the first 16 packets of file out
		requires additional code later to sendFile again with updated window*/
	base = 0;
	int finale = -1;
	while(base * BUFSIZE < length) {
		loadWindow();

		if(p.str()[0] == '\0') finale = p.getSequenceNum();
		for(int x = 0; x < WIN_SIZE; x++) {
			p = window[x];
			if(!sendPacket()) continue;
		}
		for(int x = 0; x < WIN_SIZE; x++) {
			if(recvfrom(s, b, BUFSIZE + 7, 0, (struct sockaddr *)&ca, &calen) < 0) {
				cout << "=== ACK TIMEOUT" << endl;
				x--;
				continue;
			}

			if(isAck()) {
				handleAck();
			} else {
				handleAck();
				//handleNak(x);
			}

			if(finale > 0 && base == finale) break;
			memset(b, 0, BUFSIZE);
		}

	}

	if(sendto(s, "\0", BUFSIZE, 0, (struct sockaddr *)&ca, sizeof(ca)) < 0) {
		cout << "Final package sending failed. (socket s, server address sa, message m)" << endl;
		return false;
	}
	return true;
}

Packet createPacket(int index){
    string mstr = fstr.substr(index * BUFSIZE, BUFSIZE);

	if(mstr.length() < BUFSIZE) {
		cout << "Null terminated mstr." << endl;
		mstr[length - (index * BUFSIZE)] = '\0';
    }

	cout << "index: " << index << endl;
    return Packet (index, mstr.c_str());
}

bool sendPacket(){
	cout << endl;
    cout << "=== TRANSMISSION START" << endl;
	cout << "Sequence number before gremlin function: " << p.getSequenceNum() << endl;
    int pc = probCorrupt; int pl = probLoss; int pd = probDelay;
	bool* pckStatus = gremlin(&p, pc, pl, pd);

	dropPck = pckStatus[0];
	delayPck = pckStatus[1];

	if (dropPck == true) return false;
	if (delayPck == true) p.setAckNack(1);

    if(sendto(s, p.str(), BUFSIZE + 8, 0, (struct sockaddr *)&ca, sizeof(ca)) < 0) {
		cout << "Package sending failed. (socket s, server address sa, message m)" << endl;
		return false;
    }
    return true;
}
bool isAck() {
    cout << endl << "=== SERVER RESPONSE TEST" << endl;
    cout << "Data: " << b << endl;
    if(b[6] == '0') return true;
    else return false;
}
void handleAck() {
	int ack = boost::lexical_cast<int>(b);
	if(base < ack) base = ack;
	cout << "Window base: " << base << endl;
}
void handleNak(int& x) {

      char * sns = new char[2];
      memcpy(sns, &b[0], 1);
      sns[1] = '\0';

      char * css = new char[5];
      memcpy(css, &b[1], 5);

      char * db = new char[BUFSIZE + 1];
      memcpy(db, &b[2], BUFSIZE);
      db[BUFSIZE] = '\0';

      cout << "Sequence number: " << sns << endl;
      cout << "Checksum: " << css << endl;

      Packet pk (0, db);
      pk.setSequenceNum(boost::lexical_cast<int>(sns));
      pk.setCheckSum(boost::lexical_cast<int>(css));

      if(!pk.chksm()) x--;
      else x = (x - 2 > 0) ? x - 2 : 0;
}
bool* gremlin(Packet * pack, int corruptProb, int lossProb, int delayProb){

  bool* packStatus = new bool[2];
  int r = rand() % 100;

  cout << "Corruption probability: " << corruptProb << endl;
  cout << "Random number: " << r << endl;

  packStatus[0] = false;
  packStatus[1] = false;

  if(r <= (lossProb)){
	packStatus[0] = true;
    cout << "Dropped!" << endl;
  }
  else if(r <= (delayProb)){
	  packStatus[1] = true;
	  cout << "Delayed!" << endl;
  }
  else if(r <= (corruptProb)){
    cout << "Corrupted!" << endl;
	cout << "Seq. num (pre-gremlin): " << pack->getSequenceNum() << endl;
    pack->loadDataBuffer((char*)"GREMLIN LOL");
  }
  cout << "Seq. num: " << pack->getSequenceNum() << endl;
  cout << "Checksum: " << pack->getCheckSum() << endl;
  //cout << "Message: "  << pack->getDataBuffer() << endl;

  return packStatus;
}<commit_msg>Put this stuff back in<commit_after>#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <boost/lexical_cast.hpp>
#include "packet.h"

#define USAGE "Usage:\r\nc \r\n[tux machine number] \r\n[probability of packet corruption in int form] \r\n[probability of packet loss in int form] \r\n[probability of packet delay] \r\n[length of delay in ms] \r\n"
#define PORT 10038
#define PAKSIZE 512
#define ACK 0
#define NAK 1
#define BUFSIZE 505
#define FILENAME "Testfile"
#define TIMEOUT 100 //in ms
#define WIN_SIZE 16

using namespace std;

bool isvpack(unsigned char * p);
bool init(int argc, char** argv);
bool loadFile();
bool getFile();
bool sendFile();
bool isAck();
void handleAck();
void handleNak(int& x);
bool* gremlin(Packet * pack, int corruptProb, int lossProb, int delayProb);
Packet createPacket(int index);
void loadWindow();
bool sendPacket();
bool getGet();

struct sockaddr_in a;
struct sockaddr_in ca;
socklen_t calen;
int rlen;
int s;
bool ack;
string fstr;
char * file;
int probCorrupt;
int probLoss;
int probDelay;
int delayT;
Packet p;
Packet window[16];
int length;
bool dropPck;
bool delayPck;
int toms;
unsigned char b[BUFSIZE];
int base;

int main(int argc, char** argv) {

  if(!init(argc, argv)) return -1;

  sendFile();

  return 0;
}

bool init(int argc, char** argv){

  if(argc != 6) {
    cout << USAGE << endl;
    return false;
  }

  char * probCorruptStr = argv[2];
  probCorrupt = boost::lexical_cast<int>(probCorruptStr);
  char * probLossStr = argv[3];
  probLoss = boost::lexical_cast<int>(probLossStr);
  char * probDelayStr = argv[4];
  probDelay = boost::lexical_cast<int>(probDelayStr);
  char* delayTStr = argv[5];
  delayT = boost::lexical_cast<int>(delayTStr);

  struct timeval timeout;
  timeout.tv_usec = TIMEOUT * 1000;
  toms = TIMEOUT;

  /* Create our socket. */
  if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    cout << "Socket creation failed. (socket s)" << endl;
    return 0;
  }

  setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));

  /*
   * Bind our socket to an IP (whatever the computer decides)
   * and a specified port.
   *
   */

  if (!loadFile()) {
    cout << "Loading file failed. (filename FILENAME)" << endl;
    return false;
  }

  memset((char *)&a, 0, sizeof(a));
  a.sin_family = AF_INET;
  a.sin_addr.s_addr = htonl(INADDR_ANY);
  a.sin_port = htons(PORT);

  if (bind(s, (struct sockaddr *)&a, sizeof(a)) < 0) {
    cout << "Socket binding failed. (socket s, address a)" << endl;
    return 0;
  }

  fstr = string(file);
  cout << "File: " << endl << fstr << endl;

  base = 0;
  dropPck = false;
  calen = sizeof(ca);

  getGet();

  return true;
}

bool getGet(){
	unsigned char packet[PAKSIZE + 1];
	rlen = recvfrom(s, packet, PAKSIZE, 0, (struct sockaddr *)&ca, &calen);
	return (rlen > 0) ? true : false;
}

bool isvpack(unsigned char * p) {
  cout << endl << "=== IS VALID PACKET TESTING" << endl;

  char * sns = new char[2];
  memcpy(sns, &p[0], 1);
  sns[1] = '\0';

  char * css = new char[7];
  memcpy(css, &p[1], 6);
  css[6] = '\0';

  char * db = new char[121 + 1];
  memcpy(db, &p[2], 121);
  db[121] = '\0';

  cout << "Seq. num: " << sns << endl;
  cout << "Checksum: " << css << endl;
  cout << "Message: " << db << endl;

  int sn = boost::lexical_cast<int>(sns);
  int cs = boost::lexical_cast<int>(css);

  Packet pk (0, db);
  pk.setSequenceNum(sn);

  // change to validate based on checksum and sequence number

  if(sn == 0) return false; //doesn't matter, only for the old version (netwark)
  if(cs != pk.generateCheckSum()) return false;
  return true;
}

bool getFile(){

  /* Loop forever, waiting for messages from a client. */
  cout << "Waiting on port " << PORT << "..." << endl;

  ofstream file("Dumpfile");

  for (;;) {
    unsigned char packet[PAKSIZE + 1];
    unsigned char dataPull[PAKSIZE - 7 + 1];
    rlen = recvfrom(s, packet, PAKSIZE, 0, (struct sockaddr *)&ca, &calen);

    for(int x = 0; x < PAKSIZE - 7; x++) {
      dataPull[x] = packet[x + 7];
    }
    dataPull[PAKSIZE - 7] = '\0';
    packet[PAKSIZE] = '\0';
    if (rlen > 0) {
      char * css = new char[6];
      memcpy(css, &packet[1], 5);
      css[5] = '\0';
      cout << endl << endl << "=== RECEIPT" << endl;
      cout << "Seq. num: " << packet[0] << endl;
      cout << "Checksum: " << css << endl;
      cout << "Received message: " << dataPull << endl;
      cout << "Sent response: ";
      if(isvpack(packet)) {
        ack = ACK;
        //seqNum = (seqNum) ? false : true;
        file << dataPull;
      } else {
        ack = NAK;
      }
      cout << ((ack == ACK) ? "ACK" : "NAK") << endl;
      Packet p (false, reinterpret_cast<const char *>(dataPull));
      p.setCheckSum(boost::lexical_cast<int>(css));
      p.setAckNack(ack);

      if(sendto(s, p.str(), PAKSIZE, 0, (struct sockaddr *)&ca, calen) < 0) {
        cout << "Acknowledgement failed. (socket s, acknowledgement message ack, client address ca, client address length calen)" << endl;
        return 0;
      }
      delete css;
    }
  }
  file.close();
  return true;
}

bool loadFile() {

  ifstream is (FILENAME, ifstream::binary);

  if(is) {
    is.seekg(0, is.end);
    length = is.tellg();
    is.seekg(0, is.beg);

    file = new char[length];

    cout << "Reading " << length << " characters..." << endl;
    is.read(file, length);

    if(!is) { cout << "File reading failed. (filename " << FILENAME << "). Only " << is.gcount() << " could be read."; return false; }
    is.close();
  }
  return true;
}

void loadWindow(){
	for(int i = base; i < base + WIN_SIZE; i++) {
		window[i-base] = createPacket(i);
		if(strlen(window[i-base].getDataBuffer()) < BUFSIZE && window[i-base].chksm()) {
			cout << "In loadWindow's secret base, index is: " << i-base << endl;
			for(++i; i < base + WIN_SIZE; i++){
				window[i-base].loadDataBuffer("\0");
			}
			return;
		}
		/*cout << "window[i-base] seq. num: " << window[i-base].getSequenceNum() << endl;*/
	}

		/*cout << "packet " << base + 1 << ": " << window[1].str() << endl;
		cout << "packet " << base + 2 << ": " << window[2].str() << endl;*/
}

bool sendFile() {
	/*Currently causes the program to only send the first 16 packets of file out
		requires additional code later to sendFile again with updated window*/
	base = 0;
	int finale = -1;
	while(base * BUFSIZE < length) {
		loadWindow();

		if(p.str()[0] == '\0') finale = p.getSequenceNum();
		for(int x = 0; x < WIN_SIZE; x++) {
			p = window[x];
			if(!sendPacket()) continue;
		}
		for(int x = 0; x < WIN_SIZE; x++) {
			if(recvfrom(s, b, BUFSIZE + 7, 0, (struct sockaddr *)&ca, &calen) < 0) {
				cout << "=== ACK TIMEOUT" << endl;
				x--;
				continue;
			}

			if(isAck()) {
				handleAck();
			} else {
				handleAck();
				//handleNak(x);
			}

			if(finale > 0 && base == finale) break;
			memset(b, 0, BUFSIZE);
		}

	}

	if(sendto(s, "\0", BUFSIZE, 0, (struct sockaddr *)&ca, sizeof(ca)) < 0) {
		cout << "Final package sending failed. (socket s, server address sa, message m)" << endl;
		return false;
	}
	return true;
}

Packet createPacket(int index){
    string mstr = fstr.substr(index * BUFSIZE, BUFSIZE);

	if(mstr.length() < BUFSIZE) {
		cout << "Null terminated mstr." << endl;
		mstr[length - (index * BUFSIZE)] = '\0';
    }

	cout << "index: " << index << endl;
    return Packet (index, mstr.c_str());
}

bool sendPacket(){
	cout << endl;
    cout << "=== TRANSMISSION START" << endl;
	cout << "Sequence number before gremlin function: " << p.getSequenceNum() << endl;
    int pc = probCorrupt; int pl = probLoss; int pd = probDelay;
	bool* pckStatus = gremlin(&p, pc, pl, pd);

	dropPck = pckStatus[0];
	delayPck = pckStatus[1];

	if (dropPck == true) return false;
	if (delayPck == true) p.setAckNack(1);

    if(sendto(s, p.str(), BUFSIZE + 8, 0, (struct sockaddr *)&ca, sizeof(ca)) < 0) {
		cout << "Package sending failed. (socket s, server address sa, message m)" << endl;
		return false;
    }
    return true;
}
bool isAck() {
    cout << endl << "=== SERVER RESPONSE TEST" << endl;
    cout << "Data: " << b << endl;
    if(b[6] == '0') return true;
    else return false;
}
void handleAck() {
	int ack = boost::lexical_cast<int>(b);
	if(base < ack) base = ack;
	cout << "Window base: " << base << endl;
}
void handleNak(int& x) {

      char * sns = new char[2];
      memcpy(sns, &b[0], 1);
      sns[1] = '\0';

      char * css = new char[5];
      memcpy(css, &b[1], 5);

      char * db = new char[BUFSIZE + 1];
      memcpy(db, &b[2], BUFSIZE);
      db[BUFSIZE] = '\0';

      cout << "Sequence number: " << sns << endl;
      cout << "Checksum: " << css << endl;

      Packet pk (0, db);
      pk.setSequenceNum(boost::lexical_cast<int>(sns));
      pk.setCheckSum(boost::lexical_cast<int>(css));

      if(!pk.chksm()) x--;
      else x = (x - 2 > 0) ? x - 2 : 0;
}
bool* gremlin(Packet * pack, int corruptProb, int lossProb, int delayProb){

  bool* packStatus = new bool[2];
  int r = rand() % 100;

  cout << "Corruption probability: " << corruptProb << endl;
  cout << "Random number: " << r << endl;

  packStatus[0] = false;
  packStatus[1] = false;

  if(r <= (lossProb)){
	packStatus[0] = true;
    cout << "Dropped!" << endl;
  }
  else if(r <= (delayProb)){
	  packStatus[1] = true;
	  cout << "Delayed!" << endl;
  }
  else if(r <= (corruptProb)){
    cout << "Corrupted!" << endl;
	cout << "Seq. num (pre-gremlin): " << pack->getSequenceNum() << endl;
    pack->loadDataBuffer((char*)"GREMLIN LOL");
  }
  cout << "Seq. num: " << pack->getSequenceNum() << endl;
  cout << "Checksum: " << pack->getCheckSum() << endl;
  //cout << "Message: "  << pack->getDataBuffer() << endl;

  return packStatus;
}<|endoftext|>


<commit_before>//----------------------------------------------------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2007 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------------------------------------------------

#include <iomanip>
#include <fstream>

#include <base/logstream.h>
#include <grid/tria.h>
#include <grid/grid_generator.h>
#include <dofs/dof_handler.h>
#include <dofs/dof_accessor.h>
#include <multigrid/mg_dof_handler.h>
#include <multigrid/mg_dof_accessor.h>
#include <fe/fe_q.h>
#include <fe/fe_dgq.h>
#include <fe/fe_system.h>

using namespace dealii;

// Fill dof handlers for different elements and see how large they get.
template <class DOF>
void check_dofs(DOF& dof, unsigned int repeat)
{
  FE_Q<DOF::dimension> q1(1);

  deallog << "Start" << std::endl;
  for (unsigned int i=1;i<6;++i)
    {
      FE_Q<DOF::dimension> fe(i);
      for (unsigned int i=0;i<repeat;++i)
	dof.distribute_dofs(fe);
      deallog << dof.get_fe().get_name()
	      << " memory " << dof.memory_consumption()/1.e6 << std::endl;
    }

  for (unsigned int i=1;i<6;++i)
    {
      FESystem<DOF::dimension> fe(q1, 1 << i);
      for (unsigned int i=0;i<repeat;++i)
	dof.distribute_dofs(fe);
      deallog << dof.get_fe().get_name()
	      << " memory " << dof.memory_consumption()/1.e6 << std::endl;
    }
  dof.clear();
}

template <int dim>
void check (bool local)
{
  deallog << "Dimension " << dim << std::endl;
  Triangulation<dim> tr(Triangulation<dim>::maximum_smoothing);
  GridGenerator::hyper_cube(tr);

  if (local)
    for (unsigned int i=0;i<1800/dim;++i)
      {
	tr.last_active()->set_refine_flag();
	tr.execute_coarsening_and_refinement();
      }
  else
    tr.refine_global(21/dim);

  deallog << "Levels " << tr.n_levels() << " Cells "<< tr.n_cells()
	  << std::endl
	  << " active " << tr.n_active_cells()
	  << " memory " << tr.memory_consumption()/1.e6
	  << std::endl;

  deallog.push("DoF");
  DoFHandler<dim> dof(tr);
  check_dofs(dof, (local ? 10 : 1));
  deallog.pop();
  deallog.push("MGDoF");
  MGDoFHandler<dim> mgdof(tr);
  check_dofs(mgdof, (local ? 10 : 1));
  deallog.pop();
}

int main()
{
  std::ofstream out("dof_handler_timing_01/output");
  deallog.log_execution_time(true);
  deallog.log_time_differences(true);
  deallog.attach(out);
  deallog.push("local");
  check<2>(true);
  check<3>(true);
  deallog.pop();
  deallog.push("global");
  check<2>(false);
  check<3>(false);
  deallog.pop();
}

<commit_msg>make results more scannable<commit_after>//----------------------------------------------------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2007 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------------------------------------------------

#include <iomanip>
#include <fstream>

#include <base/logstream.h>
#include <grid/tria.h>
#include <grid/grid_generator.h>
#include <dofs/dof_handler.h>
#include <dofs/dof_accessor.h>
#include <multigrid/mg_dof_handler.h>
#include <multigrid/mg_dof_accessor.h>
#include <fe/fe_q.h>
#include <fe/fe_dgq.h>
#include <fe/fe_system.h>

using namespace dealii;

// Fill dof handlers for different elements and see how large they get.
template <class DOF>
void check_dofs(DOF& dof, unsigned int repeat)
{
  FE_Q<DOF::dimension> q1(1);

  deallog << "Start" << std::endl;
  for (unsigned int i=1;i<6;++i)
    {
      FE_Q<DOF::dimension> fe(i);
      for (unsigned int i=0;i<repeat;++i)
	dof.distribute_dofs(fe);
      deallog << dof.get_fe().get_name()
	      << " memory " << dof.memory_consumption()/1.e6 << std::endl;
    }

  for (unsigned int i=1;i<6;++i)
    {
      FESystem<DOF::dimension> fe(q1, 1 << i);
      for (unsigned int i=0;i<repeat;++i)
	dof.distribute_dofs(fe);
      deallog << dof.get_fe().get_name()
	      << " memory " << dof.memory_consumption()/1.e6 << std::endl;
    }
  dof.clear();
}

template <int dim>
void check (bool local)
{
  deallog << "Start mesh"  << std::endl;
  Triangulation<dim> tr(Triangulation<dim>::maximum_smoothing);
  GridGenerator::hyper_cube(tr);

  if (local)
    for (unsigned int i=0;i<1800/dim;++i)
      {
	tr.last_active()->set_refine_flag();
	tr.execute_coarsening_and_refinement();
      }
  else
    tr.refine_global(21/dim);

  deallog << "Levels " << tr.n_levels() << " Cells "<< tr.n_cells()
	  << std::endl
	  << "active " << tr.n_active_cells()
	  << " memory " << tr.memory_consumption()/1.e6
	  << std::endl;

  deallog.push("DoF");
  DoFHandler<dim> dof(tr);
  check_dofs(dof, (local ? 10 : 1));
  deallog.pop();
  deallog.push("MGDoF");
  MGDoFHandler<dim> mgdof(tr);
  check_dofs(mgdof, (local ? 10 : 1));
  deallog.pop();
}

int main()
{
  std::ofstream out("dof_handler_timing_01/output");
  deallog.log_execution_time(true);
  deallog.log_time_differences(true);
  deallog.attach(out);
  deallog.push("local");
  deallog.push("2d");
  check<2>(true);
  deallog.pop();
  deallog.push("3d");
  check<3>(true);
  deallog.pop();
  deallog.pop();
  deallog.push("global");
  deallog.push("2d");
  check<2>(false);
  deallog.pop();
  deallog.push("3d");
  check<3>(false);
  deallog.pop();
  deallog.pop();
}

<|endoftext|>


<commit_before>
#include <gainput/gainput.h>
#include <gainput/gestures/GainputPinchGesture.h>

#ifdef GAINPUT_ENABLE_PINCH_GESTURE

#include <math.h>

namespace gainput
{

PinchGesture::PinchGesture(InputManager& manager, DeviceId device) :
	InputDevice(device),
	manager_(manager),
	pinching_(false)
{
	downButton_.buttonId = InvalidDeviceButtonId;
	xAxis_.buttonId = InvalidDeviceButtonId;
	yAxis_.buttonId = InvalidDeviceButtonId;
	downButton2_.buttonId = InvalidDeviceButtonId;
	xAxis2_.buttonId = InvalidDeviceButtonId;
	yAxis2_.buttonId = InvalidDeviceButtonId;

	state_ = manager_.GetAllocator().New<InputState>(manager.GetAllocator(), 1);
	GAINPUT_ASSERT(state_);
	previousState_ = manager_.GetAllocator().New<InputState>(manager.GetAllocator(), 1);
	GAINPUT_ASSERT(previousState_);
}

PinchGesture::~PinchGesture()
{
	manager_.GetAllocator().Delete(state_);
	manager_.GetAllocator().Delete(previousState_);
}

void
PinchGesture::Initialize(DeviceId downDevice, DeviceButtonId downButton,
			DeviceId xAxisDevice, DeviceButtonId xAxis,
			DeviceId yAxisDevice, DeviceButtonId yAxis,
			DeviceId down2Device, DeviceButtonId downButton2,
			DeviceId xAxis2Device, DeviceButtonId xAxis2,
			DeviceId yAxis2Device, DeviceButtonId yAxis2)
{
	downButton_.deviceId = downDevice;
	downButton_.buttonId = downButton;
	xAxis_.deviceId = xAxisDevice;
	xAxis_.buttonId = xAxis;
	yAxis_.deviceId = yAxisDevice;
	yAxis_.buttonId = yAxis;
	downButton2_.deviceId = down2Device;
	downButton2_.buttonId = downButton2;
	xAxis2_.deviceId = xAxis2Device;
	xAxis2_.buttonId = xAxis2;
	yAxis2_.deviceId = yAxis2Device;
	yAxis2_.buttonId = yAxis2;
}

void
PinchGesture::Update(InputDeltaState* delta)
{
	if (downButton_.buttonId == InvalidDeviceButtonId
	 || xAxis_.buttonId == InvalidDeviceButtonId
	 || yAxis_.buttonId == InvalidDeviceButtonId
	 || downButton2_.buttonId == InvalidDeviceButtonId
	 || xAxis2_.buttonId == InvalidDeviceButtonId
	 || yAxis2_.buttonId == InvalidDeviceButtonId)
	{
		return;
	}

	*previousState_ = *state_;

	const InputDevice* downDevice = manager_.GetDevice(downButton_.deviceId);
	GAINPUT_ASSERT(downDevice);
	const bool isDown = downDevice->GetBool(downButton_.buttonId);

	const InputDevice* downDevice2 = manager_.GetDevice(downButton2_.deviceId);
	GAINPUT_ASSERT(downDevice2);
	const bool isDown2 = true; //downDevice2->GetBool(downButton2_.buttonId);

	if (!isDown || !isDown2)
	{
		state_->Set(PinchTriggered, false);
		pinching_ = false;
		return;
	}

	state_->Set(PinchTriggered, true);

	const InputDevice* xAxisDevice = manager_.GetDevice(xAxis_.deviceId);
	GAINPUT_ASSERT(xAxisDevice);
	const float posX = xAxisDevice->GetFloat(xAxis_.buttonId);
	const InputDevice* yAxisDevice = manager_.GetDevice(yAxis_.deviceId);
	GAINPUT_ASSERT(yAxisDevice);
	const float posY = yAxisDevice->GetFloat(yAxis_.buttonId);

	const InputDevice* xAxis2Device = manager_.GetDevice(xAxis2_.deviceId);
	GAINPUT_ASSERT(xAxis2Device);
	const float posX2 = 0;//xAxis2Device->GetFloat(xAxis2_.buttonId);
	const InputDevice* yAxis2Device = manager_.GetDevice(yAxis2_.deviceId);
	GAINPUT_ASSERT(yAxis2Device);
	const float posY2 = 0;//yAxis2Device->GetFloat(yAxis2_.buttonId);

	const float xd = posX - posX2;
	const float yd = posY - posY2;
	const float dist = sqrtf(xd*xd + yd+yd);

	if (!pinching_)
	{
		pinching_ = true;
		initialDistance_ = dist;
		state_->Set(PinchScale, 1.0f);
		return;
	}

	state_->Set(PinchScale, dist / initialDistance_);
}

}

#endif

<commit_msg>Removed some accidentally left in debug code.<commit_after>
#include <gainput/gainput.h>
#include <gainput/gestures/GainputPinchGesture.h>

#ifdef GAINPUT_ENABLE_PINCH_GESTURE

#include <math.h>

namespace gainput
{

PinchGesture::PinchGesture(InputManager& manager, DeviceId device) :
	InputDevice(device),
	manager_(manager),
	pinching_(false)
{
	downButton_.buttonId = InvalidDeviceButtonId;
	xAxis_.buttonId = InvalidDeviceButtonId;
	yAxis_.buttonId = InvalidDeviceButtonId;
	downButton2_.buttonId = InvalidDeviceButtonId;
	xAxis2_.buttonId = InvalidDeviceButtonId;
	yAxis2_.buttonId = InvalidDeviceButtonId;

	state_ = manager_.GetAllocator().New<InputState>(manager.GetAllocator(), 1);
	GAINPUT_ASSERT(state_);
	previousState_ = manager_.GetAllocator().New<InputState>(manager.GetAllocator(), 1);
	GAINPUT_ASSERT(previousState_);
}

PinchGesture::~PinchGesture()
{
	manager_.GetAllocator().Delete(state_);
	manager_.GetAllocator().Delete(previousState_);
}

void
PinchGesture::Initialize(DeviceId downDevice, DeviceButtonId downButton,
			DeviceId xAxisDevice, DeviceButtonId xAxis,
			DeviceId yAxisDevice, DeviceButtonId yAxis,
			DeviceId down2Device, DeviceButtonId downButton2,
			DeviceId xAxis2Device, DeviceButtonId xAxis2,
			DeviceId yAxis2Device, DeviceButtonId yAxis2)
{
	downButton_.deviceId = downDevice;
	downButton_.buttonId = downButton;
	xAxis_.deviceId = xAxisDevice;
	xAxis_.buttonId = xAxis;
	yAxis_.deviceId = yAxisDevice;
	yAxis_.buttonId = yAxis;
	downButton2_.deviceId = down2Device;
	downButton2_.buttonId = downButton2;
	xAxis2_.deviceId = xAxis2Device;
	xAxis2_.buttonId = xAxis2;
	yAxis2_.deviceId = yAxis2Device;
	yAxis2_.buttonId = yAxis2;
}

void
PinchGesture::Update(InputDeltaState* delta)
{
	if (downButton_.buttonId == InvalidDeviceButtonId
	 || xAxis_.buttonId == InvalidDeviceButtonId
	 || yAxis_.buttonId == InvalidDeviceButtonId
	 || downButton2_.buttonId == InvalidDeviceButtonId
	 || xAxis2_.buttonId == InvalidDeviceButtonId
	 || yAxis2_.buttonId == InvalidDeviceButtonId)
	{
		return;
	}

	*previousState_ = *state_;

	const InputDevice* downDevice = manager_.GetDevice(downButton_.deviceId);
	GAINPUT_ASSERT(downDevice);
	const bool isDown = downDevice->GetBool(downButton_.buttonId);

	const InputDevice* downDevice2 = manager_.GetDevice(downButton2_.deviceId);
	GAINPUT_ASSERT(downDevice2);
	const bool isDown2 = downDevice2->GetBool(downButton2_.buttonId);

	if (!isDown || !isDown2)
	{
		state_->Set(PinchTriggered, false);
		pinching_ = false;
		return;
	}

	state_->Set(PinchTriggered, true);

	const InputDevice* xAxisDevice = manager_.GetDevice(xAxis_.deviceId);
	GAINPUT_ASSERT(xAxisDevice);
	const float posX = xAxisDevice->GetFloat(xAxis_.buttonId);
	const InputDevice* yAxisDevice = manager_.GetDevice(yAxis_.deviceId);
	GAINPUT_ASSERT(yAxisDevice);
	const float posY = yAxisDevice->GetFloat(yAxis_.buttonId);

	const InputDevice* xAxis2Device = manager_.GetDevice(xAxis2_.deviceId);
	GAINPUT_ASSERT(xAxis2Device);
	const float posX2 = xAxis2Device->GetFloat(xAxis2_.buttonId);
	const InputDevice* yAxis2Device = manager_.GetDevice(yAxis2_.deviceId);
	GAINPUT_ASSERT(yAxis2Device);
	const float posY2 = yAxis2Device->GetFloat(yAxis2_.buttonId);

	const float xd = posX - posX2;
	const float yd = posY - posY2;
	const float dist = sqrtf(xd*xd + yd+yd);

	if (!pinching_)
	{
		pinching_ = true;
		initialDistance_ = dist;
		state_->Set(PinchScale, 1.0f);
		return;
	}

	state_->Set(PinchScale, dist / initialDistance_);
}

}

#endif

<|endoftext|>