<commit_before>//===-- PrologEpilogInserter.cpp - Insert Prolog/Epilog code in function --===//
//
//                     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 pass is responsible for finalizing the functions frame layout, saving
// callee saved registers, and for emitting prolog & epilog code for the
// function.
//
// This pass must be run after register allocation.  After this pass is
// executed, it is illegal to construct MO_FrameIndex operands.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
using namespace llvm;

namespace {
  struct PEI : public MachineFunctionPass {
    const char *getPassName() const {
      return "Prolog/Epilog Insertion & Frame Finalization";
    }

    /// runOnMachineFunction - Insert prolog/epilog code and replace abstract
    /// frame indexes with appropriate references.
    ///
    bool runOnMachineFunction(MachineFunction &Fn) {
      // Scan the function for modified caller saved registers and insert spill
      // code for any caller saved registers that are modified.  Also calculate
      // the MaxCallFrameSize and HasCalls variables for the function's frame
      // information and eliminates call frame pseudo instructions.
      calculateCallerSavedRegisters(Fn);

      // Add the code to save and restore the caller saved registers
      saveCallerSavedRegisters(Fn);

      // Allow the target machine to make final modifications to the function
      // before the frame layout is finalized.
      Fn.getTarget().getRegisterInfo()->processFunctionBeforeFrameFinalized(Fn);

      // Calculate actual frame offsets for all of the abstract stack objects...
      calculateFrameObjectOffsets(Fn);

      // Add prolog and epilog code to the function.  This function is required
      // to align the stack frame as necessary for any stack variables or
      // called functions.  Because of this, calculateCallerSavedRegisters
      // must be called before this function in order to set the HasCalls
      // and MaxCallFrameSize variables.
      insertPrologEpilogCode(Fn);

      // Replace all MO_FrameIndex operands with physical register references
      // and actual offsets.
      //
      replaceFrameIndices(Fn);

      RegsToSave.clear();
      StackSlots.clear();
      return true;
    }

  private:
    std::vector<unsigned> RegsToSave;
    std::vector<int> StackSlots;

    void calculateCallerSavedRegisters(MachineFunction &Fn);
    void saveCallerSavedRegisters(MachineFunction &Fn);
    void calculateFrameObjectOffsets(MachineFunction &Fn);
    void replaceFrameIndices(MachineFunction &Fn);
    void insertPrologEpilogCode(MachineFunction &Fn);
  };
}

/// createPrologEpilogCodeInserter - This function returns a pass that inserts
/// prolog and epilog code, and eliminates abstract frame references.
///
FunctionPass *llvm::createPrologEpilogCodeInserter() { return new PEI(); }

/// calculateCallerSavedRegisters - Scan the function for modified caller saved
/// registers.  Also calculate the MaxCallFrameSize and HasCalls variables for
/// the function's frame information and eliminates call frame pseudo
/// instructions.
///
void PEI::calculateCallerSavedRegisters(MachineFunction &Fn) {
  const MRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo();
  const TargetFrameInfo *TFI = Fn.getTarget().getFrameInfo();
  const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo();

  // Get the callee saved register list...
  const unsigned *CSRegs = RegInfo->getCalleeSaveRegs();

  // Get the function call frame set-up and tear-down instruction opcode
  int FrameSetupOpcode   = RegInfo->getCallFrameSetupOpcode();
  int FrameDestroyOpcode = RegInfo->getCallFrameDestroyOpcode();

  // Early exit for targets which have no callee saved registers and no call
  // frame setup/destroy pseudo instructions.
  if ((CSRegs == 0 || CSRegs[0] == 0) &&
      FrameSetupOpcode == -1 && FrameDestroyOpcode == -1)
    return;

  unsigned MaxCallFrameSize = 0;
  bool HasCalls = false;

  for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB)
    for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); )
      if (I->getOpcode() == FrameSetupOpcode ||
          I->getOpcode() == FrameDestroyOpcode) {
        assert(I->getNumOperands() >= 1 && "Call Frame Setup/Destroy Pseudo"
               " instructions should have a single immediate argument!");
        unsigned Size = I->getOperand(0).getImmedValue();
        if (Size > MaxCallFrameSize) MaxCallFrameSize = Size;
        HasCalls = true;
        RegInfo->eliminateCallFramePseudoInstr(Fn, *BB, I++);
      } else {
        ++I;
      }

  MachineFrameInfo *FFI = Fn.getFrameInfo();
  FFI->setHasCalls(HasCalls);
  FFI->setMaxCallFrameSize(MaxCallFrameSize);

  // Now figure out which *callee saved* registers are modified by the current
  // function, thus needing to be saved and restored in the prolog/epilog.
  //
  const bool *PhysRegsUsed = Fn.getUsedPhysregs();
  for (unsigned i = 0; CSRegs[i]; ++i) {
    unsigned Reg = CSRegs[i];
    if (PhysRegsUsed[Reg]) {
      RegsToSave.push_back(Reg);  // If the reg is modified, save it!
    } else {
      for (const unsigned *AliasSet = RegInfo->getAliasSet(Reg);
           *AliasSet; ++AliasSet) {  // Check alias registers too.
        if (PhysRegsUsed[*AliasSet]) {
          RegsToSave.push_back(Reg);
          break;
        }
      }
    }
  }

  if (RegsToSave.empty())
    return;   // Early exit if no caller saved registers are modified!

  unsigned NumFixedSpillSlots;
  const std::pair<unsigned,int> *FixedSpillSlots =
    TFI->getCalleeSaveSpillSlots(NumFixedSpillSlots);

  // Now that we know which registers need to be saved and restored, allocate
  // stack slots for them.
  for (unsigned i = 0, e = RegsToSave.size(); i != e; ++i) {
    unsigned Reg = RegsToSave[i];

    // Check to see if this physreg must be spilled to a particular stack slot
    // on this target.
    const std::pair<unsigned,int> *FixedSlot = FixedSpillSlots;
    while (FixedSlot != FixedSpillSlots+NumFixedSpillSlots &&
           FixedSlot->first != Reg)
      ++FixedSlot;

    int FrameIdx;
    if (FixedSlot == FixedSpillSlots+NumFixedSpillSlots) {
      // Nope, just spill it anywhere convenient.
      FrameIdx = FFI->CreateStackObject(RegInfo->getSpillSize(Reg)/8,
                                        RegInfo->getSpillAlignment(Reg)/8);
    } else {
      // Spill it to the stack where we must.
      FrameIdx = FFI->CreateFixedObject(RegInfo->getSpillSize(Reg)/8,
                                        FixedSlot->second);
    }
    StackSlots.push_back(FrameIdx);
  }
}

/// saveCallerSavedRegisters -  Insert spill code for any caller saved registers
/// that are modified in the function.
///
void PEI::saveCallerSavedRegisters(MachineFunction &Fn) {
  // Early exit if no caller saved registers are modified!
  if (RegsToSave.empty())
    return;

  const MRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo();

  // Now that we have a stack slot for each register to be saved, insert spill
  // code into the entry block.
  MachineBasicBlock *MBB = Fn.begin();
  MachineBasicBlock::iterator I = MBB->begin();
  for (unsigned i = 0, e = RegsToSave.size(); i != e; ++i) {
    // Insert the spill to the stack frame.
    RegInfo->storeRegToStackSlot(*MBB, I, RegsToSave[i], StackSlots[i],
                                 0 /*FIXME*/);
  }

  // Add code to restore the callee-save registers in each exiting block.
  const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo();
  for (MachineFunction::iterator FI = Fn.begin(), E = Fn.end(); FI != E; ++FI)
    // If last instruction is a return instruction, add an epilogue.
    if (!FI->empty() && TII.isReturn(FI->back().getOpcode())) {
      MBB = FI;
      I = MBB->end(); --I;

      // Skip over all terminator instructions, which are part of the return
      // sequence.
      MachineBasicBlock::iterator I2 = I;
      while (I2 != MBB->begin() && TII.isTerminatorInstr((--I2)->getOpcode()))
        I = I2;

      bool AtStart = I == MBB->begin();
      MachineBasicBlock::iterator BeforeI = I;
      if (!AtStart)
        --BeforeI;

      // Restore all registers immediately before the return and any terminators
      // that preceed it.
      for (unsigned i = 0, e = RegsToSave.size(); i != e; ++i) {
        RegInfo->loadRegFromStackSlot(*MBB, I, RegsToSave[i], StackSlots[i],
                                      0 /*FIXME*/);
        assert(I != MBB->begin() &&
               "loadRegFromStackSlot didn't insert any code!");
        // Insert in reverse order.  loadRegFromStackSlot can insert multiple
        // instructions.
        if (AtStart)
          I = MBB->begin();
        else {
          I = BeforeI;
          ++I;
        }
      }
    }
}

/// calculateFrameObjectOffsets - Calculate actual frame offsets for all of the
/// abstract stack objects.
///
void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) {
  const TargetFrameInfo &TFI = *Fn.getTarget().getFrameInfo();

  bool StackGrowsDown =
    TFI.getStackGrowthDirection() == TargetFrameInfo::StackGrowsDown;

  // Loop over all of the stack objects, assigning sequential addresses...
  MachineFrameInfo *FFI = Fn.getFrameInfo();

  unsigned StackAlignment = TFI.getStackAlignment();

  // Start at the beginning of the local area.
  // The Offset is the distance from the stack top in the direction
  // of stack growth -- so it's always positive.
  int Offset = TFI.getOffsetOfLocalArea();
  if (StackGrowsDown)
    Offset = -Offset;
  assert(Offset >= 0
         && "Local area offset should be in direction of stack growth");

  // If there are fixed sized objects that are preallocated in the local area,
  // non-fixed objects can't be allocated right at the start of local area.
  // We currently don't support filling in holes in between fixed sized objects,
  // so we adjust 'Offset' to point to the end of last fixed sized
  // preallocated object.
  for (int i = FFI->getObjectIndexBegin(); i != 0; ++i) {
    int FixedOff;
    if (StackGrowsDown) {
      // The maximum distance from the stack pointer is at lower address of
      // the object -- which is given by offset. For down growing stack
      // the offset is negative, so we negate the offset to get the distance.
      FixedOff = -FFI->getObjectOffset(i);
    } else {
      // The maximum distance from the start pointer is at the upper
      // address of the object.
      FixedOff = FFI->getObjectOffset(i) + FFI->getObjectSize(i);
    }
    if (FixedOff > Offset) Offset = FixedOff;
  }

  for (unsigned i = 0, e = FFI->getObjectIndexEnd(); i != e; ++i) {
    // If stack grows down, we need to add size of find the lowest
    // address of the object.
    if (StackGrowsDown)
      Offset += FFI->getObjectSize(i);

    unsigned Align = FFI->getObjectAlignment(i);
    assert(Align <= StackAlignment && "Cannot align stack object to higher "
           "alignment boundary than the stack itself!");
    Offset = (Offset+Align-1)/Align*Align;   // Adjust to Alignment boundary...

    if (StackGrowsDown) {
      FFI->setObjectOffset(i, -Offset);        // Set the computed offset
    } else {
      FFI->setObjectOffset(i, Offset);
      Offset += FFI->getObjectSize(i);
    }
  }

  // Align the final stack pointer offset, but only if there are calls in the
  // function.  This ensures that any calls to subroutines have their stack
  // frames suitable aligned.
  if (FFI->hasCalls())
    Offset = (Offset+StackAlignment-1)/StackAlignment*StackAlignment;

  // Set the final value of the stack pointer...
  FFI->setStackSize(Offset+TFI.getOffsetOfLocalArea());
}

/// insertPrologEpilogCode - Scan the function for modified caller saved
/// registers, insert spill code for these caller saved registers, then add
/// prolog and epilog code to the function.
///
void PEI::insertPrologEpilogCode(MachineFunction &Fn) {
  // Add prologue to the function...
  Fn.getTarget().getRegisterInfo()->emitPrologue(Fn);

  // Add epilogue to restore the callee-save registers in each exiting block
  const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo();
  for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) {
    // If last instruction is a return instruction, add an epilogue
    if (!I->empty() && TII.isReturn(I->back().getOpcode()))
      Fn.getTarget().getRegisterInfo()->emitEpilogue(Fn, *I);
  }
}

/// replaceFrameIndices - Replace all MO_FrameIndex operands with physical
/// register references and actual offsets.
///
void PEI::replaceFrameIndices(MachineFunction &Fn) {
  if (!Fn.getFrameInfo()->hasStackObjects()) return; // Nothing to do?

  const TargetMachine &TM = Fn.getTarget();
  assert(TM.getRegisterInfo() && "TM::getRegisterInfo() must be implemented!");
  const MRegisterInfo &MRI = *TM.getRegisterInfo();

  for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB)
    for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ++I)
      for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
        if (I->getOperand(i).isFrameIndex()) {
          // If this instruction has a FrameIndex operand, we need to use that
          // target machine register info object to eliminate it.
          MRI.eliminateFrameIndex(I);
          break;
        }
}
<commit_msg>Now that we have getCalleeSaveRegClasses() info, use it to pass the register class into the spill/reload methods.  Targets can now rely on that argument.<commit_after>//===-- PrologEpilogInserter.cpp - Insert Prolog/Epilog code in function --===//
//
//                     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 pass is responsible for finalizing the functions frame layout, saving
// callee saved registers, and for emitting prolog & epilog code for the
// function.
//
// This pass must be run after register allocation.  After this pass is
// executed, it is illegal to construct MO_FrameIndex operands.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
using namespace llvm;

namespace {
  struct PEI : public MachineFunctionPass {
    const char *getPassName() const {
      return "Prolog/Epilog Insertion & Frame Finalization";
    }

    /// runOnMachineFunction - Insert prolog/epilog code and replace abstract
    /// frame indexes with appropriate references.
    ///
    bool runOnMachineFunction(MachineFunction &Fn) {
      // Scan the function for modified caller saved registers and insert spill
      // code for any caller saved registers that are modified.  Also calculate
      // the MaxCallFrameSize and HasCalls variables for the function's frame
      // information and eliminates call frame pseudo instructions.
      calculateCallerSavedRegisters(Fn);

      // Add the code to save and restore the caller saved registers
      saveCallerSavedRegisters(Fn);

      // Allow the target machine to make final modifications to the function
      // before the frame layout is finalized.
      Fn.getTarget().getRegisterInfo()->processFunctionBeforeFrameFinalized(Fn);

      // Calculate actual frame offsets for all of the abstract stack objects...
      calculateFrameObjectOffsets(Fn);

      // Add prolog and epilog code to the function.  This function is required
      // to align the stack frame as necessary for any stack variables or
      // called functions.  Because of this, calculateCallerSavedRegisters
      // must be called before this function in order to set the HasCalls
      // and MaxCallFrameSize variables.
      insertPrologEpilogCode(Fn);

      // Replace all MO_FrameIndex operands with physical register references
      // and actual offsets.
      //
      replaceFrameIndices(Fn);

      RegsToSave.clear();
      StackSlots.clear();
      return true;
    }

  private:
    std::vector<std::pair<unsigned, const TargetRegisterClass*> > RegsToSave;
    std::vector<int> StackSlots;

    void calculateCallerSavedRegisters(MachineFunction &Fn);
    void saveCallerSavedRegisters(MachineFunction &Fn);
    void calculateFrameObjectOffsets(MachineFunction &Fn);
    void replaceFrameIndices(MachineFunction &Fn);
    void insertPrologEpilogCode(MachineFunction &Fn);
  };
}

/// createPrologEpilogCodeInserter - This function returns a pass that inserts
/// prolog and epilog code, and eliminates abstract frame references.
///
FunctionPass *llvm::createPrologEpilogCodeInserter() { return new PEI(); }

/// calculateCallerSavedRegisters - Scan the function for modified caller saved
/// registers.  Also calculate the MaxCallFrameSize and HasCalls variables for
/// the function's frame information and eliminates call frame pseudo
/// instructions.
///
void PEI::calculateCallerSavedRegisters(MachineFunction &Fn) {
  const MRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo();
  const TargetFrameInfo *TFI = Fn.getTarget().getFrameInfo();
  const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo();

  // Get the callee saved register list...
  const unsigned *CSRegs = RegInfo->getCalleeSaveRegs();

  // Get the function call frame set-up and tear-down instruction opcode
  int FrameSetupOpcode   = RegInfo->getCallFrameSetupOpcode();
  int FrameDestroyOpcode = RegInfo->getCallFrameDestroyOpcode();

  // Early exit for targets which have no callee saved registers and no call
  // frame setup/destroy pseudo instructions.
  if ((CSRegs == 0 || CSRegs[0] == 0) &&
      FrameSetupOpcode == -1 && FrameDestroyOpcode == -1)
    return;

  unsigned MaxCallFrameSize = 0;
  bool HasCalls = false;

  for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB)
    for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); )
      if (I->getOpcode() == FrameSetupOpcode ||
          I->getOpcode() == FrameDestroyOpcode) {
        assert(I->getNumOperands() >= 1 && "Call Frame Setup/Destroy Pseudo"
               " instructions should have a single immediate argument!");
        unsigned Size = I->getOperand(0).getImmedValue();
        if (Size > MaxCallFrameSize) MaxCallFrameSize = Size;
        HasCalls = true;
        RegInfo->eliminateCallFramePseudoInstr(Fn, *BB, I++);
      } else {
        ++I;
      }

  MachineFrameInfo *FFI = Fn.getFrameInfo();
  FFI->setHasCalls(HasCalls);
  FFI->setMaxCallFrameSize(MaxCallFrameSize);

  // Now figure out which *callee saved* registers are modified by the current
  // function, thus needing to be saved and restored in the prolog/epilog.
  //
  const bool *PhysRegsUsed = Fn.getUsedPhysregs();
  const TargetRegisterClass* const *CSRegClasses =
    RegInfo->getCalleeSaveRegClasses();
  for (unsigned i = 0; CSRegs[i]; ++i) {
    unsigned Reg = CSRegs[i];
    if (PhysRegsUsed[Reg]) {
        // If the reg is modified, save it!
      RegsToSave.push_back(std::make_pair(Reg, CSRegClasses[i]));
    } else {
      for (const unsigned *AliasSet = RegInfo->getAliasSet(Reg);
           *AliasSet; ++AliasSet) {  // Check alias registers too.
        if (PhysRegsUsed[*AliasSet]) {
          RegsToSave.push_back(std::make_pair(Reg, CSRegClasses[i]));
          break;
        }
      }
    }
  }

  if (RegsToSave.empty())
    return;   // Early exit if no caller saved registers are modified!

  unsigned NumFixedSpillSlots;
  const std::pair<unsigned,int> *FixedSpillSlots =
    TFI->getCalleeSaveSpillSlots(NumFixedSpillSlots);

  // Now that we know which registers need to be saved and restored, allocate
  // stack slots for them.
  for (unsigned i = 0, e = RegsToSave.size(); i != e; ++i) {
    unsigned Reg = RegsToSave[i].first;

    // Check to see if this physreg must be spilled to a particular stack slot
    // on this target.
    const std::pair<unsigned,int> *FixedSlot = FixedSpillSlots;
    while (FixedSlot != FixedSpillSlots+NumFixedSpillSlots &&
           FixedSlot->first != Reg)
      ++FixedSlot;

    int FrameIdx;
    if (FixedSlot == FixedSpillSlots+NumFixedSpillSlots) {
      // Nope, just spill it anywhere convenient.
      FrameIdx = FFI->CreateStackObject(RegInfo->getSpillSize(Reg)/8,
                                        RegInfo->getSpillAlignment(Reg)/8);
    } else {
      // Spill it to the stack where we must.
      FrameIdx = FFI->CreateFixedObject(RegInfo->getSpillSize(Reg)/8,
                                        FixedSlot->second);
    }
    StackSlots.push_back(FrameIdx);
  }
}

/// saveCallerSavedRegisters -  Insert spill code for any caller saved registers
/// that are modified in the function.
///
void PEI::saveCallerSavedRegisters(MachineFunction &Fn) {
  // Early exit if no caller saved registers are modified!
  if (RegsToSave.empty())
    return;

  const MRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo();

  // Now that we have a stack slot for each register to be saved, insert spill
  // code into the entry block.
  MachineBasicBlock *MBB = Fn.begin();
  MachineBasicBlock::iterator I = MBB->begin();
  for (unsigned i = 0, e = RegsToSave.size(); i != e; ++i) {
    // Insert the spill to the stack frame.
    RegInfo->storeRegToStackSlot(*MBB, I, RegsToSave[i].first, StackSlots[i],
                                 RegsToSave[i].second);
  }

  // Add code to restore the callee-save registers in each exiting block.
  const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo();
  for (MachineFunction::iterator FI = Fn.begin(), E = Fn.end(); FI != E; ++FI)
    // If last instruction is a return instruction, add an epilogue.
    if (!FI->empty() && TII.isReturn(FI->back().getOpcode())) {
      MBB = FI;
      I = MBB->end(); --I;

      // Skip over all terminator instructions, which are part of the return
      // sequence.
      MachineBasicBlock::iterator I2 = I;
      while (I2 != MBB->begin() && TII.isTerminatorInstr((--I2)->getOpcode()))
        I = I2;

      bool AtStart = I == MBB->begin();
      MachineBasicBlock::iterator BeforeI = I;
      if (!AtStart)
        --BeforeI;

      // Restore all registers immediately before the return and any terminators
      // that preceed it.
      for (unsigned i = 0, e = RegsToSave.size(); i != e; ++i) {
        RegInfo->loadRegFromStackSlot(*MBB, I, RegsToSave[i].first,
                                      StackSlots[i], RegsToSave[i].second);
        assert(I != MBB->begin() &&
               "loadRegFromStackSlot didn't insert any code!");
        // Insert in reverse order.  loadRegFromStackSlot can insert multiple
        // instructions.
        if (AtStart)
          I = MBB->begin();
        else {
          I = BeforeI;
          ++I;
        }
      }
    }
}

/// calculateFrameObjectOffsets - Calculate actual frame offsets for all of the
/// abstract stack objects.
///
void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) {
  const TargetFrameInfo &TFI = *Fn.getTarget().getFrameInfo();

  bool StackGrowsDown =
    TFI.getStackGrowthDirection() == TargetFrameInfo::StackGrowsDown;

  // Loop over all of the stack objects, assigning sequential addresses...
  MachineFrameInfo *FFI = Fn.getFrameInfo();

  unsigned StackAlignment = TFI.getStackAlignment();

  // Start at the beginning of the local area.
  // The Offset is the distance from the stack top in the direction
  // of stack growth -- so it's always positive.
  int Offset = TFI.getOffsetOfLocalArea();
  if (StackGrowsDown)
    Offset = -Offset;
  assert(Offset >= 0
         && "Local area offset should be in direction of stack growth");

  // If there are fixed sized objects that are preallocated in the local area,
  // non-fixed objects can't be allocated right at the start of local area.
  // We currently don't support filling in holes in between fixed sized objects,
  // so we adjust 'Offset' to point to the end of last fixed sized
  // preallocated object.
  for (int i = FFI->getObjectIndexBegin(); i != 0; ++i) {
    int FixedOff;
    if (StackGrowsDown) {
      // The maximum distance from the stack pointer is at lower address of
      // the object -- which is given by offset. For down growing stack
      // the offset is negative, so we negate the offset to get the distance.
      FixedOff = -FFI->getObjectOffset(i);
    } else {
      // The maximum distance from the start pointer is at the upper
      // address of the object.
      FixedOff = FFI->getObjectOffset(i) + FFI->getObjectSize(i);
    }
    if (FixedOff > Offset) Offset = FixedOff;
  }

  for (unsigned i = 0, e = FFI->getObjectIndexEnd(); i != e; ++i) {
    // If stack grows down, we need to add size of find the lowest
    // address of the object.
    if (StackGrowsDown)
      Offset += FFI->getObjectSize(i);

    unsigned Align = FFI->getObjectAlignment(i);
    assert(Align <= StackAlignment && "Cannot align stack object to higher "
           "alignment boundary than the stack itself!");
    Offset = (Offset+Align-1)/Align*Align;   // Adjust to Alignment boundary...

    if (StackGrowsDown) {
      FFI->setObjectOffset(i, -Offset);        // Set the computed offset
    } else {
      FFI->setObjectOffset(i, Offset);
      Offset += FFI->getObjectSize(i);
    }
  }

  // Align the final stack pointer offset, but only if there are calls in the
  // function.  This ensures that any calls to subroutines have their stack
  // frames suitable aligned.
  if (FFI->hasCalls())
    Offset = (Offset+StackAlignment-1)/StackAlignment*StackAlignment;

  // Set the final value of the stack pointer...
  FFI->setStackSize(Offset+TFI.getOffsetOfLocalArea());
}

/// insertPrologEpilogCode - Scan the function for modified caller saved
/// registers, insert spill code for these caller saved registers, then add
/// prolog and epilog code to the function.
///
void PEI::insertPrologEpilogCode(MachineFunction &Fn) {
  // Add prologue to the function...
  Fn.getTarget().getRegisterInfo()->emitPrologue(Fn);

  // Add epilogue to restore the callee-save registers in each exiting block
  const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo();
  for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) {
    // If last instruction is a return instruction, add an epilogue
    if (!I->empty() && TII.isReturn(I->back().getOpcode()))
      Fn.getTarget().getRegisterInfo()->emitEpilogue(Fn, *I);
  }
}

/// replaceFrameIndices - Replace all MO_FrameIndex operands with physical
/// register references and actual offsets.
///
void PEI::replaceFrameIndices(MachineFunction &Fn) {
  if (!Fn.getFrameInfo()->hasStackObjects()) return; // Nothing to do?

  const TargetMachine &TM = Fn.getTarget();
  assert(TM.getRegisterInfo() && "TM::getRegisterInfo() must be implemented!");
  const MRegisterInfo &MRI = *TM.getRegisterInfo();

  for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB)
    for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ++I)
      for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
        if (I->getOperand(i).isFrameIndex()) {
          // If this instruction has a FrameIndex operand, we need to use that
          // target machine register info object to eliminate it.
          MRI.eliminateFrameIndex(I);
          break;
        }
}
<|endoftext|>


<commit_before>//===-- SparcAsmPrinter.cpp - Sparc LLVM assembly writer ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a printer that converts from our internal representation
// of machine-dependent LLVM code to GAS-format SPARC assembly language.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "asm-printer"
#include "Sparc.h"
#include "SparcInstrInfo.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/Mangler.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MathExtras.h"
#include <cctype>
#include <cstring>
#include <map>
using namespace llvm;

STATISTIC(EmittedInsts, "Number of machine instrs printed");

namespace {
  struct VISIBILITY_HIDDEN SparcAsmPrinter : public AsmPrinter {
    SparcAsmPrinter(std::ostream &O, TargetMachine &TM, const TargetAsmInfo *T)
      : AsmPrinter(O, TM, T) {
    }

    /// We name each basic block in a Function with a unique number, so
    /// that we can consistently refer to them later. This is cleared
    /// at the beginning of each call to runOnMachineFunction().
    ///
    typedef std::map<const Value *, unsigned> ValueMapTy;
    ValueMapTy NumberForBB;

    virtual const char *getPassName() const {
      return "Sparc Assembly Printer";
    }

    void printModuleLevelGV(const GlobalVariable* GVar);
    void printOperand(const MachineInstr *MI, int opNum);
    void printMemOperand(const MachineInstr *MI, int opNum,
                         const char *Modifier = 0);
    void printCCOperand(const MachineInstr *MI, int opNum);

    bool printInstruction(const MachineInstr *MI);  // autogenerated.
    bool runOnMachineFunction(MachineFunction &F);
    std::string getSectionForFunction(const Function &F) const;
    bool doInitialization(Module &M);
    bool doFinalization(Module &M);
  };
} // end of anonymous namespace

#include "SparcGenAsmWriter.inc"

/// createSparcCodePrinterPass - Returns a pass that prints the SPARC
/// assembly code for a MachineFunction to the given output stream,
/// using the given target machine description.  This should work
/// regardless of whether the function is in SSA form.
///
FunctionPass *llvm::createSparcCodePrinterPass(std::ostream &o,
                                               TargetMachine &tm) {
  return new SparcAsmPrinter(o, tm, tm.getTargetAsmInfo());
}

// Substitute old hook with new one temporary
std::string SparcAsmPrinter::getSectionForFunction(const Function &F) const {
  return TAI->SectionForGlobal(&F);
}

/// runOnMachineFunction - This uses the printInstruction()
/// method to print assembly for each instruction.
///
bool SparcAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
  SetupMachineFunction(MF);

  // Print out constants referenced by the function
  EmitConstantPool(MF.getConstantPool());

  // BBNumber is used here so that a given Printer will never give two
  // BBs the same name. (If you have a better way, please let me know!)
  static unsigned BBNumber = 0;

  O << "\n\n";
  // What's my mangled name?
  CurrentFnName = Mang->getValueName(MF.getFunction());

  // Print out the label for the function.
  const Function *F = MF.getFunction();
  SwitchToTextSection(getSectionForFunction(*F).c_str(), F);
  EmitAlignment(4, F);
  O << "\t.globl\t" << CurrentFnName << "\n";
  O << "\t.type\t" << CurrentFnName << ", #function\n";
  O << CurrentFnName << ":\n";

  // Number each basic block so that we can consistently refer to them
  // in PC-relative references.
  // FIXME: Why not use the MBB numbers?
  NumberForBB.clear();
  for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
       I != E; ++I) {
    NumberForBB[I->getBasicBlock()] = BBNumber++;
  }

  // Print out code for the function.
  for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
       I != E; ++I) {
    // Print a label for the basic block.
    if (I != MF.begin()) {
      printBasicBlockLabel(I, true, true);
      O << '\n';
    }
    for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
         II != E; ++II) {
      // Print the assembly for the instruction.
      printInstruction(II);
      ++EmittedInsts;
    }
  }

  // We didn't modify anything.
  return false;
}

void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
  const MachineOperand &MO = MI->getOperand (opNum);
  const TargetRegisterInfo &RI = *TM.getRegisterInfo();
  bool CloseParen = false;
  if (MI->getOpcode() == SP::SETHIi && !MO.isRegister() && !MO.isImmediate()) {
    O << "%hi(";
    CloseParen = true;
  } else if ((MI->getOpcode() == SP::ORri || MI->getOpcode() == SP::ADDri)
             && !MO.isRegister() && !MO.isImmediate()) {
    O << "%lo(";
    CloseParen = true;
  }
  switch (MO.getType()) {
  case MachineOperand::MO_Register:
    if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
      O << "%" << LowercaseString (RI.get(MO.getReg()).AsmName);
    else
      O << "%reg" << MO.getReg();
    break;

  case MachineOperand::MO_Immediate:
    O << (int)MO.getImm();
    break;
  case MachineOperand::MO_MachineBasicBlock:
    printBasicBlockLabel(MO.getMBB());
    return;
  case MachineOperand::MO_GlobalAddress:
    O << Mang->getValueName(MO.getGlobal());
    break;
  case MachineOperand::MO_ExternalSymbol:
    O << MO.getSymbolName();
    break;
  case MachineOperand::MO_ConstantPoolIndex:
    O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
      << MO.getIndex();
    break;
  default:
    O << "<unknown operand type>"; abort (); break;
  }
  if (CloseParen) O << ")";
}

void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
                                      const char *Modifier) {
  printOperand(MI, opNum);

  // If this is an ADD operand, emit it like normal operands.
  if (Modifier && !strcmp(Modifier, "arith")) {
    O << ", ";
    printOperand(MI, opNum+1);
    return;
  }

  if (MI->getOperand(opNum+1).isRegister() &&
      MI->getOperand(opNum+1).getReg() == SP::G0)
    return;   // don't print "+%g0"
  if (MI->getOperand(opNum+1).isImmediate() &&
      MI->getOperand(opNum+1).getImm() == 0)
    return;   // don't print "+0"

  O << "+";
  if (MI->getOperand(opNum+1).isGlobalAddress() ||
      MI->getOperand(opNum+1).isConstantPoolIndex()) {
    O << "%lo(";
    printOperand(MI, opNum+1);
    O << ")";
  } else {
    printOperand(MI, opNum+1);
  }
}

void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
  int CC = (int)MI->getOperand(opNum).getImm();
  O << SPARCCondCodeToString((SPCC::CondCodes)CC);
}

bool SparcAsmPrinter::doInitialization(Module &M) {
  Mang = new Mangler(M);
  return false; // success
}

bool SparcAsmPrinter::doFinalization(Module &M) {
  // Print out module-level global variables here.
  for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
       I != E; ++I)
    printModuleLevelGV(I);

  O << '\n';

  return AsmPrinter::doFinalization(M);
}

void SparcAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
  const TargetData *TD = TM.getTargetData();

  if (!GVar->hasInitializer())
    return;  // External global require no code

  // Check to see if this is a special global used by LLVM, if so, emit it.
  if (EmitSpecialLLVMGlobal(GVar))
    return;

  O << "\n\n";
  std::string SectionName = TAI->SectionForGlobal(GVar);
  std::string name = Mang->getValueName(GVar);
  Constant *C = GVar->getInitializer();
  unsigned Size = TD->getABITypeSize(C->getType());
  unsigned Align = TD->getPreferredAlignment(GVar);

  // FIXME: ELF supports visibility
  SwitchToDataSection(SectionName.c_str());

  if (C->isNullValue() && !GVar->hasSection()) {
    if (!GVar->isThreadLocal() &&
        (GVar->hasInternalLinkage() || GVar->isWeakForLinker())) {
      if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.

      if (GVar->hasInternalLinkage())
        O << "\t.local " << name << "\n";

      O << TAI->getCOMMDirective() << name << ',' << Size;
      if (TAI->getCOMMDirectiveTakesAlignment())
        O << ',' << (1 << Align);

      O << '\n';
      return;
    }
  }

  switch (GVar->getLinkage()) {
   case GlobalValue::CommonLinkage:
   case GlobalValue::LinkOnceLinkage:
   case GlobalValue::WeakLinkage:   // FIXME: Verify correct for weak.
    // Nonnull linkonce -> weak
    O << "\t.weak " << name << "\n";
    break;
   case GlobalValue::AppendingLinkage:
    // FIXME: appending linkage variables should go into a section of
    // their name or something.  For now, just emit them as external.
   case GlobalValue::ExternalLinkage:
    // If external or appending, declare as a global symbol
    O << TAI->getGlobalDirective() << name << "\n";
    // FALL THROUGH
   case GlobalValue::InternalLinkage:
    break;
   case GlobalValue::GhostLinkage:
    cerr << "Should not have any unmaterialized functions!\n";
    abort();
   case GlobalValue::DLLImportLinkage:
    cerr << "DLLImport linkage is not supported by this target!\n";
    abort();
   case GlobalValue::DLLExportLinkage:
    cerr << "DLLExport linkage is not supported by this target!\n";
    abort();
   default:
    assert(0 && "Unknown linkage type!");
  }

  if (Align)
    O << "\t.align " << Align << "\n";

  if (TAI->hasDotTypeDotSizeDirective()) {
    O << "\t.type " << name << ",#object\n";
    O << "\t.size " << name << "," << Size << "\n";
  }

  O << name << ":\n";
  EmitGlobalConstant(C);
}
<commit_msg>Cleanup<commit_after>//===-- SparcAsmPrinter.cpp - Sparc LLVM assembly writer ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a printer that converts from our internal representation
// of machine-dependent LLVM code to GAS-format SPARC assembly language.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "asm-printer"
#include "Sparc.h"
#include "SparcInstrInfo.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/TargetAsmInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/Mangler.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MathExtras.h"
#include <cctype>
#include <cstring>
#include <map>
using namespace llvm;

STATISTIC(EmittedInsts, "Number of machine instrs printed");

namespace {
  struct VISIBILITY_HIDDEN SparcAsmPrinter : public AsmPrinter {
    SparcAsmPrinter(std::ostream &O, TargetMachine &TM, const TargetAsmInfo *T)
      : AsmPrinter(O, TM, T) {
    }

    /// We name each basic block in a Function with a unique number, so
    /// that we can consistently refer to them later. This is cleared
    /// at the beginning of each call to runOnMachineFunction().
    ///
    typedef std::map<const Value *, unsigned> ValueMapTy;
    ValueMapTy NumberForBB;

    virtual const char *getPassName() const {
      return "Sparc Assembly Printer";
    }

    void printModuleLevelGV(const GlobalVariable* GVar);
    void printOperand(const MachineInstr *MI, int opNum);
    void printMemOperand(const MachineInstr *MI, int opNum,
                         const char *Modifier = 0);
    void printCCOperand(const MachineInstr *MI, int opNum);

    bool printInstruction(const MachineInstr *MI);  // autogenerated.
    bool runOnMachineFunction(MachineFunction &F);
    std::string getSectionForFunction(const Function &F) const;
    bool doInitialization(Module &M);
    bool doFinalization(Module &M);
  };
} // end of anonymous namespace

#include "SparcGenAsmWriter.inc"

/// createSparcCodePrinterPass - Returns a pass that prints the SPARC
/// assembly code for a MachineFunction to the given output stream,
/// using the given target machine description.  This should work
/// regardless of whether the function is in SSA form.
///
FunctionPass *llvm::createSparcCodePrinterPass(std::ostream &o,
                                               TargetMachine &tm) {
  return new SparcAsmPrinter(o, tm, tm.getTargetAsmInfo());
}

// Substitute old hook with new one temporary
std::string SparcAsmPrinter::getSectionForFunction(const Function &F) const {
  return TAI->SectionForGlobal(&F);
}

/// runOnMachineFunction - This uses the printInstruction()
/// method to print assembly for each instruction.
///
bool SparcAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
  SetupMachineFunction(MF);

  // Print out constants referenced by the function
  EmitConstantPool(MF.getConstantPool());

  // BBNumber is used here so that a given Printer will never give two
  // BBs the same name. (If you have a better way, please let me know!)
  static unsigned BBNumber = 0;

  O << "\n\n";
  // What's my mangled name?
  CurrentFnName = Mang->getValueName(MF.getFunction());

  // Print out the label for the function.
  const Function *F = MF.getFunction();
  SwitchToTextSection(getSectionForFunction(*F).c_str(), F);
  EmitAlignment(4, F);
  O << "\t.globl\t" << CurrentFnName << '\n';
  O << "\t.type\t" << CurrentFnName << ", #function\n";
  O << CurrentFnName << ":\n";

  // Number each basic block so that we can consistently refer to them
  // in PC-relative references.
  // FIXME: Why not use the MBB numbers?
  NumberForBB.clear();
  for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
       I != E; ++I) {
    NumberForBB[I->getBasicBlock()] = BBNumber++;
  }

  // Print out code for the function.
  for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
       I != E; ++I) {
    // Print a label for the basic block.
    if (I != MF.begin()) {
      printBasicBlockLabel(I, true, true);
      O << '\n';
    }
    for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
         II != E; ++II) {
      // Print the assembly for the instruction.
      printInstruction(II);
      ++EmittedInsts;
    }
  }

  // We didn't modify anything.
  return false;
}

void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
  const MachineOperand &MO = MI->getOperand (opNum);
  const TargetRegisterInfo &RI = *TM.getRegisterInfo();
  bool CloseParen = false;
  if (MI->getOpcode() == SP::SETHIi && !MO.isRegister() && !MO.isImmediate()) {
    O << "%hi(";
    CloseParen = true;
  } else if ((MI->getOpcode() == SP::ORri || MI->getOpcode() == SP::ADDri)
             && !MO.isRegister() && !MO.isImmediate()) {
    O << "%lo(";
    CloseParen = true;
  }
  switch (MO.getType()) {
  case MachineOperand::MO_Register:
    if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
      O << "%" << LowercaseString (RI.get(MO.getReg()).AsmName);
    else
      O << "%reg" << MO.getReg();
    break;

  case MachineOperand::MO_Immediate:
    O << (int)MO.getImm();
    break;
  case MachineOperand::MO_MachineBasicBlock:
    printBasicBlockLabel(MO.getMBB());
    return;
  case MachineOperand::MO_GlobalAddress:
    O << Mang->getValueName(MO.getGlobal());
    break;
  case MachineOperand::MO_ExternalSymbol:
    O << MO.getSymbolName();
    break;
  case MachineOperand::MO_ConstantPoolIndex:
    O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
      << MO.getIndex();
    break;
  default:
    O << "<unknown operand type>"; abort (); break;
  }
  if (CloseParen) O << ")";
}

void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
                                      const char *Modifier) {
  printOperand(MI, opNum);

  // If this is an ADD operand, emit it like normal operands.
  if (Modifier && !strcmp(Modifier, "arith")) {
    O << ", ";
    printOperand(MI, opNum+1);
    return;
  }

  if (MI->getOperand(opNum+1).isRegister() &&
      MI->getOperand(opNum+1).getReg() == SP::G0)
    return;   // don't print "+%g0"
  if (MI->getOperand(opNum+1).isImmediate() &&
      MI->getOperand(opNum+1).getImm() == 0)
    return;   // don't print "+0"

  O << "+";
  if (MI->getOperand(opNum+1).isGlobalAddress() ||
      MI->getOperand(opNum+1).isConstantPoolIndex()) {
    O << "%lo(";
    printOperand(MI, opNum+1);
    O << ")";
  } else {
    printOperand(MI, opNum+1);
  }
}

void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
  int CC = (int)MI->getOperand(opNum).getImm();
  O << SPARCCondCodeToString((SPCC::CondCodes)CC);
}

bool SparcAsmPrinter::doInitialization(Module &M) {
  Mang = new Mangler(M);
  return false; // success
}

bool SparcAsmPrinter::doFinalization(Module &M) {
  // Print out module-level global variables here.
  for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
       I != E; ++I)
    printModuleLevelGV(I);

  O << '\n';

  return AsmPrinter::doFinalization(M);
}

void SparcAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
  const TargetData *TD = TM.getTargetData();

  if (!GVar->hasInitializer())
    return;  // External global require no code

  // Check to see if this is a special global used by LLVM, if so, emit it.
  if (EmitSpecialLLVMGlobal(GVar))
    return;

  O << "\n\n";
  std::string SectionName = TAI->SectionForGlobal(GVar);
  std::string name = Mang->getValueName(GVar);
  Constant *C = GVar->getInitializer();
  unsigned Size = TD->getABITypeSize(C->getType());
  unsigned Align = TD->getPreferredAlignment(GVar);

  // FIXME: ELF supports visibility
  SwitchToDataSection(SectionName.c_str());

  if (C->isNullValue() && !GVar->hasSection()) {
    if (!GVar->isThreadLocal() &&
        (GVar->hasInternalLinkage() || GVar->isWeakForLinker())) {
      if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.

      if (GVar->hasInternalLinkage())
        O << "\t.local " << name << '\n';

      O << TAI->getCOMMDirective() << name << ',' << Size;
      if (TAI->getCOMMDirectiveTakesAlignment())
        O << ',' << (1 << Align);

      O << '\n';
      return;
    }
  }

  switch (GVar->getLinkage()) {
   case GlobalValue::CommonLinkage:
   case GlobalValue::LinkOnceLinkage:
   case GlobalValue::WeakLinkage:   // FIXME: Verify correct for weak.
    // Nonnull linkonce -> weak
    O << "\t.weak " << name << '\n';
    break;
   case GlobalValue::AppendingLinkage:
    // FIXME: appending linkage variables should go into a section of
    // their name or something.  For now, just emit them as external.
   case GlobalValue::ExternalLinkage:
    // If external or appending, declare as a global symbol
    O << TAI->getGlobalDirective() << name << '\n';
    // FALL THROUGH
   case GlobalValue::InternalLinkage:
    break;
   case GlobalValue::GhostLinkage:
    cerr << "Should not have any unmaterialized functions!\n";
    abort();
   case GlobalValue::DLLImportLinkage:
    cerr << "DLLImport linkage is not supported by this target!\n";
    abort();
   case GlobalValue::DLLExportLinkage:
    cerr << "DLLExport linkage is not supported by this target!\n";
    abort();
   default:
    assert(0 && "Unknown linkage type!");
  }

  if (Align)
    O << "\t.align " << Align << '\n';

  if (TAI->hasDotTypeDotSizeDirective()) {
    O << "\t.type " << name << ",#object\n";
    O << "\t.size " << name << ',' << Size << '\n';
  }

  O << name << ":\n";
  EmitGlobalConstant(C);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <stdio.h>

#include "hmat.hpp"

void Laplacian(Eigen::MatrixXd& A, int nx, int ny);

void BuildNaturalToHierarchicalMap
( std::vector<int>& map, int xSize, int ySize, int numLevels );

template<typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& vec);

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

  int nx = 4, ny = 4;
  Eigen::MatrixXd A;
  Laplacian(A, nx, ny);
  std::cout << A << std::endl;

  int numLevels = 3;
  std::vector<int> map;
  BuildNaturalToHierarchicalMap(map, nx, ny, numLevels);
  //std::cout << map << std::endl;

  int N = nx*ny;
  Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic> perm(N);
  for (int i=0; i<N; i++)
    perm.indices()[i] = map[i];

  Eigen::MatrixXd Aperm = perm.transpose() * A * perm;
  std::cout << std::endl << Aperm << std::endl;

  int maxRank = 10;
  AdmissType admiss = WEAK;
  HMat Ah(Aperm, maxRank, numLevels, admiss, nx, ny);

  // random right hand side
  int nRhs = 2;
  Eigen::MatrixXd rhs = Eigen::MatrixXd::Random( N, nRhs );
  Eigen::MatrixXd rhsPerm1 = rhs * perm;
  Eigen::MatrixXd rhsPerm2 = perm * rhs;

  Eigen::MatrixXd x1 = Ah.solve( rhs );
  printf("Residule: %e\n", (Aperm*x1 - rhs).norm() );

  /*
    TODO: test the accuracy for the original matrix A
  Eigen::MatrixXd x1 = Ah.solve( rhsPerm1 );
  printf("Residule: %e\n", (A*x1 - rhs).norm() );
  Eigen::MatrixXd x2 = Ah.solve( rhsPerm2 );
  printf("Residule: %e\n", (A*x2 - rhs).norm() );
  */

  return 0;
}

void Laplacian(Eigen::MatrixXd& A, int nx, int ny) {
  int N = nx*ny;
  A = Eigen::MatrixXd::Zero( N, N );

  for (int x=0; x<nx; x++) {
    for (int y=0; y<ny; y++) {
      int s = x+y*nx;
      A(s,s) = 4;
      if (x > 0)
	A(s,s-1) = -1;
      if (x < nx-1)
	A(s,s+1) = -1;
      if (y > 0)
	A(s,s-nx) = -1;
      if (y < ny-1)
	A(s,s+nx) = -1;
    }
  }
}

void BuildMapOnQuadrant
( int* map, int& index, int level, int numLevels,
  int xSize, int ySize, int thisXSize, int thisYSize )
{
    if( level == numLevels-1 )
    {
        // Stamp these indices into the buffer
        for( int j=0; j<thisYSize; ++j )
        {
            int* thisRow = &map[j*xSize];
            for( int i=0; i<thisXSize; ++i )
                thisRow[i] = index++;
        }
    }
    else
    {
        const int leftWidth = thisXSize/2;
        const int rightWidth = thisXSize - leftWidth;
        const int bottomHeight = thisYSize/2;
        const int topHeight = thisYSize - bottomHeight;

        // Recurse on the lower-left quadrant
        BuildMapOnQuadrant
        ( &map[0], index, level+1, numLevels,
          xSize, ySize, leftWidth, bottomHeight );
        // Recurse on the lower-right quadrant
        BuildMapOnQuadrant
        ( &map[leftWidth], index, level+1, numLevels,
          xSize, ySize, rightWidth, bottomHeight );
        // Recurse on the upper-left quadrant
        BuildMapOnQuadrant
        ( &map[bottomHeight*xSize], index, level+1, numLevels,
          xSize, ySize, leftWidth, topHeight );
        // Recurse on the upper-right quadrant
        BuildMapOnQuadrant
        ( &map[bottomHeight*xSize+leftWidth], index, level+1, numLevels,
          xSize, ySize, rightWidth, topHeight );
    }
}

void BuildNaturalToHierarchicalMap
( std::vector<int>& map, int xSize, int ySize, int numLevels ){

    map.resize( xSize*ySize );

    // Fill the mapping from the 'natural' x-y-z ordering
    int index = 0;
    BuildMapOnQuadrant
    ( &map[0], index, 0, numLevels, xSize, ySize, xSize, ySize );

    assert(index == xSize*ySize);
}

template<typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& vec)
{
  for (int i=0; i<vec.size(); i++)
    os << vec[i] << " ";
  os << std::endl;
  return os;
}
<commit_msg>correct applying permutation matrix for Aperm<commit_after>#include <iostream>
#include <vector>
#include <stdio.h>

#include "hmat.hpp"

void Laplacian(Eigen::MatrixXd& A, int nx, int ny);

void BuildNaturalToHierarchicalMap
( std::vector<int>& map, int xSize, int ySize, int numLevels );

template<typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& vec);

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

  int nx = 8, ny = 8;
  Eigen::MatrixXd A;
  Laplacian(A, nx, ny);
#ifdef DEBUG
  //std::cout << A << std::endl;
#endif

  int numLevels = 2;
  std::vector<int> map;
  BuildNaturalToHierarchicalMap(map, nx, ny, numLevels);
  //std::cout << map << std::endl;

  int N = nx*ny;
  Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic> perm(N);
  for (int i=0; i<N; i++)
    perm.indices()[i] = map[i];

  // TODO: study applying permutation matrix
  //Eigen::MatrixXd Aperm = perm.transpose() * A * perm;
  Eigen::MatrixXd Aperm = perm * A * perm.transpose();
#ifdef DEBUG
  //std::cout << std::endl << Aperm << std::endl;
#endif

  int maxRank = 10;
  AdmissType admiss = WEAK;
  HMat Ah(Aperm, maxRank, numLevels, admiss, nx, ny);

  // random right hand side
  int nRhs = 2;
  Eigen::MatrixXd rhs = Eigen::MatrixXd::Random( N, nRhs );
  Eigen::MatrixXd rhsPerm1 = rhs * perm;
  Eigen::MatrixXd rhsPerm2 = perm * rhs;

  Eigen::MatrixXd x1 = Ah.solve( rhs );
  printf("Residule: %e\n", (Aperm*x1 - rhs).norm() );

  /*
    TODO: test the accuracy for the original matrix A
  Eigen::MatrixXd x1 = Ah.solve( rhsPerm1 );
  printf("Residule: %e\n", (A*x1 - rhs).norm() );
  Eigen::MatrixXd x2 = Ah.solve( rhsPerm2 );
  printf("Residule: %e\n", (A*x2 - rhs).norm() );
  */

  return 0;
}

void Laplacian(Eigen::MatrixXd& A, int nx, int ny) {
  int N = nx*ny;
  A = Eigen::MatrixXd::Zero( N, N );

  for (int x=0; x<nx; x++) {
    for (int y=0; y<ny; y++) {
      int s = x+y*nx;
      A(s,s) = 4;
      if (x > 0)
	A(s,s-1) = -1;
      if (x < nx-1)
	A(s,s+1) = -1;
      if (y > 0)
	A(s,s-nx) = -1;
      if (y < ny-1)
	A(s,s+nx) = -1;
    }
  }
}

void BuildMapOnQuadrant
( int* map, int& index, int level, int numLevels,
  int xSize, int ySize, int thisXSize, int thisYSize )
{
    if( level == numLevels-1 )
    {
        // Stamp these indices into the buffer
        for( int j=0; j<thisYSize; ++j )
        {
            int* thisRow = &map[j*xSize];
            for( int i=0; i<thisXSize; ++i )
                thisRow[i] = index++;
        }
    }
    else
    {
        const int leftWidth = thisXSize/2;
        const int rightWidth = thisXSize - leftWidth;
        const int bottomHeight = thisYSize/2;
        const int topHeight = thisYSize - bottomHeight;

        // Recurse on the lower-left quadrant
        BuildMapOnQuadrant
        ( &map[0], index, level+1, numLevels,
          xSize, ySize, leftWidth, bottomHeight );
        // Recurse on the lower-right quadrant
        BuildMapOnQuadrant
        ( &map[leftWidth], index, level+1, numLevels,
          xSize, ySize, rightWidth, bottomHeight );
        // Recurse on the upper-left quadrant
        BuildMapOnQuadrant
        ( &map[bottomHeight*xSize], index, level+1, numLevels,
          xSize, ySize, leftWidth, topHeight );
        // Recurse on the upper-right quadrant
        BuildMapOnQuadrant
        ( &map[bottomHeight*xSize+leftWidth], index, level+1, numLevels,
          xSize, ySize, rightWidth, topHeight );
    }
}

void BuildNaturalToHierarchicalMap
( std::vector<int>& map, int xSize, int ySize, int numLevels ){

    map.resize( xSize*ySize );

    // Fill the mapping from the 'natural' x-y-z ordering
    int index = 0;
    BuildMapOnQuadrant
    ( &map[0], index, 0, numLevels, xSize, ySize, xSize, ySize );

    assert(index == xSize*ySize);
}

template<typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& vec)
{
  for (int i=0; i<vec.size(); i++)
    os << vec[i] << " ";
  os << std::endl;
  return os;
}
<|endoftext|>


<commit_before>#include <iostream>
//~ #include <fstream>
//~ #include <cmath>

//~ #include "TH1.h"
//~ #include "TH2.h"
//~ #include "TH3.h"
//~ #include "TCanvas.h"
//~ #include "TRandom3.h"
//~ #include "TVector2.h"
//~ #include "TVector3.h"
//~ #include "TLorentzVector.h"

#include "Math/Minimizer.h"
#include "Math/Factory.h"
#include "Math/Functor.h"

/* Algorithms list
 * minName              algoName
 * ---------------------------------
 * Minuit/Minuit2       Migrad, Simplex, Seek, Combined (default is Migrad)
 * Minuit/Minuit2       Scan (good for scans, not minimizations)
 * Minuit2              Fumili (*** needs different function type ***), Fumili2
 * Fumili               *** needs different function type ***
 * GSLMultiMin          ConjugateFR, ConjugatePR, BFGS, BFGS2, SteepestDescent
 * GSLMultiFit          *** needs different function type ***
 * GSLSimAn
 * Linear               *** needs linear function ***
 * Genetic
 *
 *
 * https://root.cern.ch/fitting
 * https://root.cern.ch/numerical-minimization
 */

const int Ndim = 2;

using namespace ROOT::Math;
using namespace std;

double func1(const double* xx)
{
    double x = xx[0];
    double y = xx[1];
    return (x-3)*(x-3)+(y-2)*(y-2);
}

int minimizer()
{
    // List of valid minimizers
    vector<pair<string,string>> minVector;
    //                                      name      algorithm
    minVector.push_back(pair<string,string>("Minuit", "Migrad"));
    minVector.push_back(pair<string,string>("Minuit", "Simplex"));
    minVector.push_back(pair<string,string>("Minuit", "Combined"));
    minVector.push_back(pair<string,string>("Minuit", "Seek"));
    // minVector.push_back(pair<string,string>("Minuit", "Scan"));

    minVector.push_back(pair<string,string>("Minuit2", "Migrad"));
    minVector.push_back(pair<string,string>("Minuit2", "Simplex"));
    minVector.push_back(pair<string,string>("Minuit2", "Combined"));
    minVector.push_back(pair<string,string>("Minuit2", "Seek"));
    // minVector.push_back(pair<string,string>("Minuit2", "Scan"));
    // minVector.push_back(pair<string,string>("Minuit2", "Fumili"));
    minVector.push_back(pair<string,string>("Minuit2", "Fumili2"));

    // minVector.push_back(pair<string,string>("Fumili",  "Fumili"));

    minVector.push_back(pair<string,string>("GSLMultiMin", "ConjugateFR"));
    minVector.push_back(pair<string,string>("GSLMultiMin", "ConjugatePR"));
    minVector.push_back(pair<string,string>("GSLMultiMin", "BFGS"));
    minVector.push_back(pair<string,string>("GSLMultiMin", "BFGS2"));
    minVector.push_back(pair<string,string>("GSLMultiMin", "SteepestDescent"));

    // minVector.push_back(pair<string,string>("GSLMultiFit", ""));

    minVector.push_back(pair<string,string>("GSLSimAn", ""));

    // minVector.push_back(pair<string,string>("Linear", "");

    minVector.push_back(pair<string,string>("Genetic", ""));

    for (unsigned int i=0; i < minVector.size(); ++i) {

        Minimizer* min = Factory::CreateMinimizer(minVector[i].first, minVector[i].second);
        if (min==nullptr) {
            cout << "Invalid algorithm: " << minVector[i].first << " - " << minVector[i].second << endl;
            continue;
        }
        else cout << "Using algorithm: " << minVector[i].first << " - " << minVector[i].second << endl;

        // The minimizer needs an IMultiGenFunction, which is easily provided
        // by a Functor, which is a generic wrapper class
        Functor fun = Functor(&func1, Ndim);

        // Give the function to the minimizer
        min->SetFunction(fun);

        // Give the function variables
        min->SetVariable(0, "x", 0, 0.1);
        min->SetVariable(1, "y", 0, 0.1);

        // Verbosity
        min->SetPrintLevel(1);

        // Algorithm strategy (higher=slower & more accurate)
        // min->SetStrategy(1);

        // Algorithms parameters
        min->SetMaxFunctionCalls(100000);
        min->SetMaxIterations(10000);
        min->SetTolerance(0.001);

        // Minimize!
        min->Minimize();

        // Get out the values
        const double  minValue = min->MinValue();
        const double* minPoint = min->X();
        const double* minErrors= min->Errors();

        cout << "\nValue: " << minValue << endl;
        for (int i=0; i<Ndim; ++i) {
            cout << "x" << i+1 << ": " << minPoint[i];
            if (minErrors!=nullptr) cout << " ± " << minErrors[i];
            cout << endl;
        }
        cout << endl;
    }

    return 0;
}

int main(int, char**)
{
    return minimizer();
}
<commit_msg>Starting to look at big functions<commit_after>#include <iostream>
//~ #include <fstream>
//~ #include <cmath>

//~ #include "TH1.h"
//~ #include "TH2.h"
//~ #include "TH3.h"
//~ #include "TCanvas.h"
//~ #include "TRandom3.h"
//~ #include "TVector2.h"
//~ #include "TVector3.h"
//~ #include "TLorentzVector.h"
#include "TString.h"

#include "Math/Minimizer.h"
#include "Math/Factory.h"
#include "Math/Functor.h"

/* Algorithms list
 * minName              algoName
 * ---------------------------------
 * Minuit/Minuit2       Migrad, Simplex, Seek, Combined (default is Migrad)
 * Minuit/Minuit2       Scan (good for scans, not minimizations)
 * Minuit2              Fumili (*** needs different function type ***), Fumili2
 * Fumili               *** needs different function type ***
 * GSLMultiMin          ConjugateFR, ConjugatePR, BFGS, BFGS2, SteepestDescent
 * GSLMultiFit          *** needs different function type ***
 * GSLSimAn
 * Linear               *** needs linear function ***
 * Genetic
 *
 *
 * https://root.cern.ch/fitting
 * https://root.cern.ch/numerical-minimization
 */

const int Ndim = 100;

using namespace ROOT::Math;
using namespace std;

double func1(const double* xx)
{
    double x = xx[0];
    double y = xx[1];
    return (x-3)*(x-3)+(y-2)*(y-2);
}

double funcN(const double* xx)
{
    double accumulator=0;
    for (int i=0; i< Ndim; ++i) {
        accumulator += (xx[i]-1)*(xx[i]-1);
    }
    return accumulator;
}

int minimizer()
{
    // List of valid minimizers
    vector<pair<string,string>> minVector;
    //                                      name      algorithm
    minVector.push_back(pair<string,string>("Minuit", "Migrad"));
    minVector.push_back(pair<string,string>("Minuit", "Simplex"));
    minVector.push_back(pair<string,string>("Minuit", "Combined"));
    minVector.push_back(pair<string,string>("Minuit", "Seek"));
    // minVector.push_back(pair<string,string>("Minuit", "Scan"));

    minVector.push_back(pair<string,string>("Minuit2", "Migrad"));
    minVector.push_back(pair<string,string>("Minuit2", "Simplex"));
    minVector.push_back(pair<string,string>("Minuit2", "Combined"));
    minVector.push_back(pair<string,string>("Minuit2", "Seek"));
    // minVector.push_back(pair<string,string>("Minuit2", "Scan"));
    // minVector.push_back(pair<string,string>("Minuit2", "Fumili"));
    minVector.push_back(pair<string,string>("Minuit2", "Fumili2"));

    // minVector.push_back(pair<string,string>("Fumili",  "Fumili"));

    minVector.push_back(pair<string,string>("GSLMultiMin", "ConjugateFR"));
    minVector.push_back(pair<string,string>("GSLMultiMin", "ConjugatePR"));
    minVector.push_back(pair<string,string>("GSLMultiMin", "BFGS"));
    minVector.push_back(pair<string,string>("GSLMultiMin", "BFGS2"));
    minVector.push_back(pair<string,string>("GSLMultiMin", "SteepestDescent"));

    // minVector.push_back(pair<string,string>("GSLMultiFit", ""));

    minVector.push_back(pair<string,string>("GSLSimAn", ""));

    // minVector.push_back(pair<string,string>("Linear", "");

    minVector.push_back(pair<string,string>("Genetic", ""));

    for (unsigned int i=0; i < minVector.size(); ++i) {

        Minimizer* min = Factory::CreateMinimizer(minVector[i].first, minVector[i].second);
        if (min==nullptr) {
            cout << "Invalid algorithm: " << minVector[i].first << " - " << minVector[i].second << endl;
            continue;
        }
        else cout << "Using algorithm: " << minVector[i].first << " - " << minVector[i].second << endl;

        // The minimizer needs an IMultiGenFunction, which is easily provided
        // by a Functor, which is a generic wrapper class
        Functor fun = Functor(&funcN, Ndim);

        // Give the function to the minimizer
        min->SetFunction(fun);

        // Give the function variables
        for (int i=0; i<Ndim; ++i) {
            min->SetVariable(i, Form("x%d", i), 0, 0.1);
        }

        // Verbosity
        min->SetPrintLevel(1);

        // Algorithm strategy (higher=slower & more accurate)
        // min->SetStrategy(1);

        // Algorithms parameters
        min->SetMaxFunctionCalls(100000);
        min->SetMaxIterations(10000);
        min->SetTolerance(0.001);

        // Minimize!
        min->Minimize();

        // Get out the values
        const double  minValue = min->MinValue();
        const double* minPoint = min->X();
        const double* minErrors= min->Errors();

        cout << "\nValue: " << minValue << endl;
        for (int i=0; i<Ndim; ++i) {
            cout << "x" << i+1 << ": " << minPoint[i];
            if (minErrors!=nullptr) cout << " ± " << minErrors[i];
            cout << endl;
        }
        cout << endl;
    }

    return 0;
}

int main(int, char**)
{
    return minimizer();
}
<|endoftext|>


<commit_before>#include <geode/python/module.h>

GEODE_PYTHON_MODULE(hollow_wrap) {
  // petsc
  GEODE_WRAP(petsc_config)
  GEODE_WRAP(init)
  GEODE_WRAP(mpi)
  GEODE_WRAP(vec)
  GEODE_WRAP(mat)
  GEODE_WRAP(ksp)
  GEODE_WRAP(fe)
  GEODE_WRAP(dm)
  GEODE_WRAP(snes)
  GEODE_WRAP(model)
  GEODE_WRAP(analytic)

  // laplace
  GEODE_WRAP(laplace)

  // iga
  GEODE_WRAP(iga)
  GEODE_WRAP(laplace_iga)

  // tao
  GEODE_WRAP(tao_solver)

  // elastic
  GEODE_WRAP(elastic_test)
  GEODE_WRAP(elastic)

  // ode
  GEODE_WRAP(integral)
}
<commit_msg>Instantiate Array<HalfedgeId> python conversion<commit_after>#include <geode/python/module.h>
#include <geode/array/convert.h>
#include <geode/mesh/ids.h>

namespace geode {
ARRAY_CONVERSIONS(1,HalfedgeId)
}

GEODE_PYTHON_MODULE(hollow_wrap) {
  // petsc
  GEODE_WRAP(petsc_config)
  GEODE_WRAP(init)
  GEODE_WRAP(mpi)
  GEODE_WRAP(vec)
  GEODE_WRAP(mat)
  GEODE_WRAP(ksp)
  GEODE_WRAP(fe)
  GEODE_WRAP(dm)
  GEODE_WRAP(snes)
  GEODE_WRAP(model)
  GEODE_WRAP(analytic)

  // laplace
  GEODE_WRAP(laplace)

  // iga
  GEODE_WRAP(iga)
  GEODE_WRAP(laplace_iga)

  // tao
  GEODE_WRAP(tao_solver)

  // elastic
  GEODE_WRAP(elastic_test)
  GEODE_WRAP(elastic)

  // ode
  GEODE_WRAP(integral)
}
<|endoftext|>


<commit_before>/// @file
/// @author  Boris Mikic
/// @version 3.14
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://www.opensource.org/licenses/bsd-license.php

#ifdef _OPENKODE
#include <KD/kd.h>

#include <gtypes/Vector2.h>
#include <hltypes/hlog.h>
#include <hltypes/hltypesUtil.h>
#include <hltypes/hmap.h>
#include <hltypes/hplatform.h>
#include <hltypes/hstring.h>

#include "april.h"

#ifdef _EGL
#include "egl.h"
#endif
#include "Platform.h"
#include "RenderSystem.h"
#include "Window.h"

#ifdef __APPLE__
	#include <TargetConditionals.h>
	#if TARGET_OS_IPHONE
		void getStaticiOSInfo(chstr name, april::SystemInfo& info);
	#elif TARGET_OS_MAC
		#include <sys/sysctl.h>
	#endif
#endif

#if defined(_ANDROID)
#include <jni.h>
#define __NATIVE_INTERFACE_CLASS "net/sourceforge/april/android/NativeInterface"
#include "androidUtilJNI.h"
#endif

namespace april
{
	static SystemInfo info;
	SystemInfo getSystemInfo()
	{
		if (info.locale == "")
		{
			// number of CPU cores
			info.cpuCores = 1;
			// display resolution
			int width = 0;
			int height = 0;
			kdQueryAttribi(KD_ATTRIB_WIDTH, (KDint*)&width);
			kdQueryAttribi(KD_ATTRIB_HEIGHT, (KDint*)&height);
			info.displayResolution.set((float)hmax(width, height), (float)hmin(width, height));
			// display DPI
			kdQueryAttribi(KD_ATTRIB_DPI, (KDint*)&info.displayDpi);
#if TARGET_OS_IPHONE // On iOS, april prefers to use hardcoded device info than OpenKODE's info, it's more accurate
			hstr model = kdQueryAttribcv(KD_ATTRIB_PLATFORM);
			if (model.contains("(") && model.contains(")"))
			{
				hstr a, b;
				model.split("(",a, b);
				b.split(")", model, a);
				getStaticiOSInfo(model, info);
			}
#elif defined(__APPLE__) && defined(_PC_INPUT) // mac
			info.cpuCores = sysconf(_SC_NPROCESSORS_ONLN);
#elif defined(_WINRT)
			SYSTEM_INFO w32info;
			GetNativeSystemInfo(&w32info);
			info.cpuCores = w32info.dwNumberOfProcessors;
#elif defined(_ANDROID)
			APRIL_GET_NATIVE_INTERFACE_CLASS(classNativeInterface);
			// CPU cores
			jmethodID methodGetCpuCores = env->GetStaticMethodID(classNativeInterface, "getCpuCores", _JARGS(_JINT, ));
			info.cpuCores = (int)env->CallStaticIntMethod(classNativeInterface, methodGetCpuCores);

			// OS version
			jmethodID methodGetOsVersion = env->GetStaticMethodID(classNativeInterface, "getOsVersion", _JARGS(_JSTR, ));
			harray<hstr> osVersions = _JSTR_TO_HSTR((jstring)env->CallStaticObjectMethod(classNativeInterface, methodGetOsVersion)).split('.');
			hstr majorVersion = osVersions.remove_first();
			hstr minorVersion = osVersions.join("");
			osVersions.clear();
			osVersions += majorVersion;
			osVersions += minorVersion;
			info.osVersion = (float)osVersions.join('.');

#endif
			// RAM size
#if TARGET_IPHONE_SIMULATOR
			info.ram = 1024;
#elif defined(__APPLE__) && defined(_PC_INPUT) // mac
			int mib [] = {CTL_HW, HW_MEMSIZE};
			int64_t value = 0;
			size_t length = sizeof(value);
			if (sysctl(mib, 2, &value, &length, NULL, 0) != -1)
			{
				info.ram = value / (1024 * 1024);
			}
			else
			{
				info.ram = 2048;
			}
#else
			int pageSize;
			int pageCount;
			kdQueryAttribi(KD_ATTRIB_PAGESIZE, (KDint*)&pageSize);
			kdQueryAttribi(KD_ATTRIB_NUMPAGES, (KDint*)&pageCount);
#ifdef _WINRT
			info.ram = (int)((int64)pageSize * pageCount / (1024 * 1024)); // in MB
#else
			info.ram = (int)((int64_t)pageSize * pageCount / (1024 * 1024)); // in MB
#endif
#endif
			// other
			info.locale = hstr(kdGetLocale());
			if (info.locale == "")
			{
				info.locale = "en"; // default is "en"
			}
			else if (info.locale == "pt_PT")
			{
				info.locale = "pt-PT";
			}
			else if (info.locale.utf8_size() > 2 && info.locale != "pt-PT")
			{
				info.locale = info.locale.utf8_substr(0, 2);
			}
		}
		if (info.maxTextureSize == 0 && april::rendersys != NULL)
		{
			info.maxTextureSize = april::rendersys->getMaxTextureSize();
		}
		return info;
	}

	DeviceType getDeviceType()
	{
		return DEVICE_OPENKODE;
	}

	hstr getPackageName()
	{
#ifndef _WINRT
		return hstr(kdGetenv("KD_APP_ID"));
#else
		return _HL_PSTR_TO_HSTR(Windows::ApplicationModel::Package::Current->Id->FamilyName);
#endif
	}

	hstr getUserDataPath()
	{
		return "data";
	}

	void messageBox_platform(chstr title, chstr text, MessageBoxButton buttonMask, MessageBoxStyle style,
		hmap<MessageBoxButton, hstr> customButtonTitles, void(*callback)(MessageBoxButton))
	{
		hstr ok;
		hstr yes;
		hstr no;
		hstr cancel;
		_makeButtonLabels(&ok, &yes, &no, &cancel, buttonMask, customButtonTitles);
		const char* buttons[4] = {"", NULL, NULL, NULL};
		MessageBoxButton resultButtons[4] = {AMSGBTN_NULL, AMSGBTN_NULL, AMSGBTN_NULL, AMSGBTN_NULL};
		int indexCancel = -1;
		if ((buttonMask & AMSGBTN_OK) && (buttonMask & AMSGBTN_CANCEL))
		{
			// order is reversed because libKD prefers the colored button to be at place [1], at least on iOS
			// if this is going to be changed for a new platform, ifdef the button order for iOS
			buttons[1] = ok.c_str();
			buttons[0] = cancel.c_str();
			resultButtons[1] = AMSGBTN_OK;
			resultButtons[0] = AMSGBTN_CANCEL;
			indexCancel = 0;
		}
		else if ((buttonMask & AMSGBTN_YES) && (buttonMask & AMSGBTN_NO) && (buttonMask & AMSGBTN_CANCEL))
		{
			buttons[1] = yes.c_str();
			buttons[0] = no.c_str();
			buttons[2] = cancel.c_str();
			resultButtons[1] = AMSGBTN_YES;
			resultButtons[0] = AMSGBTN_NO;
			resultButtons[2] = AMSGBTN_CANCEL;
			indexCancel = 2;
		}
		else if (buttonMask & AMSGBTN_OK)
		{
			buttons[0] = ok.c_str();
			resultButtons[0] = AMSGBTN_OK;
			indexCancel = 0;
		}
		else if ((buttonMask & AMSGBTN_YES) && (buttonMask & AMSGBTN_NO))
		{
			buttons[1] = yes.c_str();
			buttons[0] = no.c_str();
			resultButtons[1] = AMSGBTN_YES;
			resultButtons[0] = AMSGBTN_NO;
			indexCancel = 1;
		}
		int index = kdShowMessage(title.c_str(), text.c_str(), buttons);
		if (index == -1)
		{
			index = indexCancel;
		}
		if (callback != NULL && index >= 0)
		{
			(*callback)(resultButtons[index]);
		}
	}

}
#endif
<commit_msg>- small update<commit_after>/// @file
/// @author  Boris Mikic
/// @version 3.14
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://www.opensource.org/licenses/bsd-license.php

#ifdef _OPENKODE
#include <KD/kd.h>

#include <gtypes/Vector2.h>
#include <hltypes/hlog.h>
#include <hltypes/hltypesUtil.h>
#include <hltypes/hmap.h>
#include <hltypes/hplatform.h>
#include <hltypes/hstring.h>

#include "april.h"

#ifdef _EGL
#include "egl.h"
#endif
#include "Platform.h"
#include "RenderSystem.h"
#include "Window.h"

#ifdef __APPLE__
	#include <TargetConditionals.h>
	#if TARGET_OS_IPHONE
		void getStaticiOSInfo(chstr name, april::SystemInfo& info);
	#elif TARGET_OS_MAC
		#include <sys/sysctl.h>
	#endif
#endif

#if defined(_ANDROID)
#include <jni.h>
#define __NATIVE_INTERFACE_CLASS "net/sourceforge/april/android/NativeInterface"
#include "androidUtilJNI.h"
#endif

namespace april
{
	static SystemInfo info;
	SystemInfo getSystemInfo()
	{
		if (info.locale == "")
		{
			// number of CPU cores
			info.cpuCores = 1;
			// display resolution
			int width = 0;
			int height = 0;
			kdQueryAttribi(KD_ATTRIB_WIDTH, (KDint*)&width);
			kdQueryAttribi(KD_ATTRIB_HEIGHT, (KDint*)&height);
			info.displayResolution.set((float)hmax(width, height), (float)hmin(width, height));
			// display DPI
			kdQueryAttribi(KD_ATTRIB_DPI, (KDint*)&info.displayDpi);
#if TARGET_OS_IPHONE // On iOS, april prefers to use hardcoded device info than OpenKODE's info, it's more accurate
			hstr model = kdQueryAttribcv(KD_ATTRIB_PLATFORM);
			if (model.contains("(") && model.contains(")"))
			{
				hstr a, b;
				model.split("(",a, b);
				b.split(")", model, a);
				getStaticiOSInfo(model, info);
			}
#elif defined(__APPLE__) && defined(_PC_INPUT) // mac
			info.cpuCores = sysconf(_SC_NPROCESSORS_ONLN);
#elif defined(_WINRT)
			SYSTEM_INFO w32info;
			GetNativeSystemInfo(&w32info);
			info.cpuCores = w32info.dwNumberOfProcessors;
#elif defined(_ANDROID)
			APRIL_GET_NATIVE_INTERFACE_CLASS(classNativeInterface);
			// CPU cores
			jmethodID methodGetCpuCores = env->GetStaticMethodID(classNativeInterface, "getCpuCores", _JARGS(_JINT, ));
			info.cpuCores = (int)env->CallStaticIntMethod(classNativeInterface, methodGetCpuCores);
			// OS version
			jmethodID methodGetOsVersion = env->GetStaticMethodID(classNativeInterface, "getOsVersion", _JARGS(_JSTR, ));
			harray<hstr> osVersions = _JSTR_TO_HSTR((jstring)env->CallStaticObjectMethod(classNativeInterface, methodGetOsVersion)).split('.');
			hstr majorVersion = osVersions.remove_first();
			hstr minorVersion = osVersions.join("");
			osVersions.clear();
			osVersions += majorVersion;
			osVersions += minorVersion;
			info.osVersion = (float)osVersions.join('.');
#endif
			// RAM size
#if TARGET_IPHONE_SIMULATOR
			info.ram = 1024;
#elif defined(__APPLE__) && defined(_PC_INPUT) // mac
			int mib [] = {CTL_HW, HW_MEMSIZE};
			int64_t value = 0;
			size_t length = sizeof(value);
			if (sysctl(mib, 2, &value, &length, NULL, 0) != -1)
			{
				info.ram = value / (1024 * 1024);
			}
			else
			{
				info.ram = 2048;
			}
#else
			int pageSize;
			int pageCount;
			kdQueryAttribi(KD_ATTRIB_PAGESIZE, (KDint*)&pageSize);
			kdQueryAttribi(KD_ATTRIB_NUMPAGES, (KDint*)&pageCount);
#ifdef _WINRT
			info.ram = (int)((int64)pageSize * pageCount / (1024 * 1024)); // in MB
#else
			info.ram = (int)((int64_t)pageSize * pageCount / (1024 * 1024)); // in MB
#endif
#endif
			// other
			info.locale = hstr(kdGetLocale());
			if (info.locale == "")
			{
				info.locale = "en"; // default is "en"
			}
			else if (info.locale == "pt_PT")
			{
				info.locale = "pt-PT";
			}
			else if (info.locale.utf8_size() > 2 && info.locale != "pt-PT")
			{
				info.locale = info.locale.utf8_substr(0, 2);
			}
		}
		if (info.maxTextureSize == 0 && april::rendersys != NULL)
		{
			info.maxTextureSize = april::rendersys->getMaxTextureSize();
		}
		return info;
	}

	DeviceType getDeviceType()
	{
		return DEVICE_OPENKODE;
	}

	hstr getPackageName()
	{
#ifndef _WINRT
		return hstr(kdGetenv("KD_APP_ID"));
#else
		return _HL_PSTR_TO_HSTR(Windows::ApplicationModel::Package::Current->Id->FamilyName);
#endif
	}

	hstr getUserDataPath()
	{
		return "data";
	}

	void messageBox_platform(chstr title, chstr text, MessageBoxButton buttonMask, MessageBoxStyle style,
		hmap<MessageBoxButton, hstr> customButtonTitles, void(*callback)(MessageBoxButton))
	{
		hstr ok;
		hstr yes;
		hstr no;
		hstr cancel;
		_makeButtonLabels(&ok, &yes, &no, &cancel, buttonMask, customButtonTitles);
		const char* buttons[4] = {"", NULL, NULL, NULL};
		MessageBoxButton resultButtons[4] = {AMSGBTN_NULL, AMSGBTN_NULL, AMSGBTN_NULL, AMSGBTN_NULL};
		int indexCancel = -1;
		if ((buttonMask & AMSGBTN_OK) && (buttonMask & AMSGBTN_CANCEL))
		{
			// order is reversed because libKD prefers the colored button to be at place [1], at least on iOS
			// if this is going to be changed for a new platform, ifdef the button order for iOS
			buttons[1] = ok.c_str();
			buttons[0] = cancel.c_str();
			resultButtons[1] = AMSGBTN_OK;
			resultButtons[0] = AMSGBTN_CANCEL;
			indexCancel = 0;
		}
		else if ((buttonMask & AMSGBTN_YES) && (buttonMask & AMSGBTN_NO) && (buttonMask & AMSGBTN_CANCEL))
		{
			buttons[1] = yes.c_str();
			buttons[0] = no.c_str();
			buttons[2] = cancel.c_str();
			resultButtons[1] = AMSGBTN_YES;
			resultButtons[0] = AMSGBTN_NO;
			resultButtons[2] = AMSGBTN_CANCEL;
			indexCancel = 2;
		}
		else if (buttonMask & AMSGBTN_OK)
		{
			buttons[0] = ok.c_str();
			resultButtons[0] = AMSGBTN_OK;
			indexCancel = 0;
		}
		else if ((buttonMask & AMSGBTN_YES) && (buttonMask & AMSGBTN_NO))
		{
			buttons[1] = yes.c_str();
			buttons[0] = no.c_str();
			resultButtons[1] = AMSGBTN_YES;
			resultButtons[0] = AMSGBTN_NO;
			indexCancel = 1;
		}
		int index = kdShowMessage(title.c_str(), text.c_str(), buttons);
		if (index == -1)
		{
			index = indexCancel;
		}
		if (callback != NULL && index >= 0)
		{
			(*callback)(resultButtons[index]);
		}
	}

}
#endif
<|endoftext|>


<commit_before>/// @file
/// @author  Boris Mikic
/// @version 3.1
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://www.opensource.org/licenses/bsd-license.php

#ifdef _OPENKODE
#include <KD/kd.h>

#include <gtypes/Vector2.h>
#include <hltypes/hlog.h>
#include <hltypes/hltypesUtil.h>
#include <hltypes/hmap.h>
#include <hltypes/hplatform.h>
#include <hltypes/hstring.h>

#include "april.h"

#ifdef _EGL
#include "egl.h"
#endif
#include "Platform.h"
#include "RenderSystem.h"
#include "Window.h"

#ifdef __APPLE__
	#include <TargetConditionals.h>
	#if TARGET_OS_IPHONE
		void getStaticiOSInfo(chstr name, april::SystemInfo& info);
	#elif TARGET_OS_MAC
		#include <sys/sysctl.h>
	#endif
#endif

namespace april
{
	static SystemInfo info;
	SystemInfo getSystemInfo()
	{
		if (info.locale == "")
		{
			// RAM size
#if TARGET_IPHONE_SIMULATOR
			info.ram = 1024;
#elif defined(__APPLE__) && defined(_PC_INPUT) // mac
			int mib [] = { CTL_HW, HW_MEMSIZE };
			int64_t value = 0;
			size_t length = sizeof(value);

			if (sysctl(mib, 2, &value, &length, NULL, 0) == -1)
			{
				info.ram = 2048;
			}
			else
			{
				info.ram = value / (1024 * 1024);
			}
#else
			int ram;
			kdQueryAttribi(KD_ATTRIB_RAM, (KDint*)&ram);
			info.ram = ram / 1048576; // in MB
#endif

			// display resolution
			int width = 0;
			int height = 0;
			kdQueryAttribi(KD_ATTRIB_WIDTH, (KDint*)&width);
			kdQueryAttribi(KD_ATTRIB_HEIGHT, (KDint*)&height);
			info.displayResolution.set((float)width, (float)height);
			// display DPI
			kdQueryAttribi(KD_ATTRIB_DPI, (KDint*)&info.displayDpi);
			// other

			// number of CPU cores
			info.cpuCores = 1;
#if TARGET_OS_IPHONE // On iOS, april prefers to use hardcoded device info then OpenKODE's info, it's more accurate
			hstr model = kdQueryAttribcv(KD_ATTRIB_PLATFORM);
			if (model.contains("(") && model.contains(")"))
			{
				hstr a, b;
				model.split("(",a, b);
				b.split(")", model, a);
				getStaticiOSInfo(model, info);
			}
#elif defined(__APPLE__) && defined(_PC_INPUT) // mac
			info.cpuCores = sysconf(_SC_NPROCESSORS_ONLN);
#endif

			info.locale = hstr(kdGetLocale());
			if (info.locale == "")
			{
				info.locale = "en"; // default is "en"
			}
			else if (info.locale == "pt_PT")
			{
				info.locale = "pt-PT";
			}
			else if (info.locale.utf8_size() > 2 && info.locale != "pt-PT")
			{
				info.locale = info.locale.utf8_substr(0, 2);
			}
		}
		if (info.maxTextureSize == 0 && april::rendersys != NULL)
		{
			info.maxTextureSize = april::rendersys->getMaxTextureSize();
		}
		return info;
	}

	DeviceType getDeviceType()
	{
		return DEVICE_OPENKODE;
	}

	hstr getPackageName()
	{
#ifndef _WINRT
		return hstr(kdGetenv("KD_APP_ID"));
#else
		return _HL_PSTR_TO_HSTR(Windows::ApplicationModel::Package::Current->Id->Name);
#endif

	}

	hstr getUserDataPath()
	{
		return "data";
	}

	void messageBox_platform(chstr title, chstr text, MessageBoxButton buttonMask, MessageBoxStyle style,
		hmap<MessageBoxButton, hstr> customButtonTitles, void(*callback)(MessageBoxButton))
	{
		hstr ok;
		hstr yes;
		hstr no;
		hstr cancel;
		_makeButtonLabels(&ok, &yes, &no, &cancel, buttonMask, customButtonTitles);
		const char* buttons[4] = {"", NULL, NULL, NULL};
		MessageBoxButton resultButtons[4] = {AMSGBTN_NULL, AMSGBTN_NULL, AMSGBTN_NULL, AMSGBTN_NULL};
		int indexCancel = -1;
		if ((buttonMask & AMSGBTN_OK) && (buttonMask & AMSGBTN_CANCEL))
		{
			// order is reversed because libKD prefers the colored button to be at place [1], at least on iOS
			// if this is going to be changed for a new platform, ifdef the button order for iOS
			buttons[1] = ok.c_str();
			buttons[0] = cancel.c_str();
			resultButtons[1] = AMSGBTN_OK;
			resultButtons[0] = AMSGBTN_CANCEL;
			indexCancel = 0;
		}
		else if ((buttonMask & AMSGBTN_YES) && (buttonMask & AMSGBTN_NO) && (buttonMask & AMSGBTN_CANCEL))
		{
			buttons[1] = yes.c_str();
			buttons[0] = no.c_str();
			buttons[2] = cancel.c_str();
			resultButtons[1] = AMSGBTN_YES;
			resultButtons[0] = AMSGBTN_NO;
			resultButtons[2] = AMSGBTN_CANCEL;
			indexCancel = 2;
		}
		else if (buttonMask & AMSGBTN_OK)
		{
			buttons[0] = ok.c_str();
			resultButtons[0] = AMSGBTN_OK;
			indexCancel = 0;
		}
		else if ((buttonMask & AMSGBTN_YES) && (buttonMask & AMSGBTN_NO))
		{
			buttons[1] = yes.c_str();
			buttons[0] = no.c_str();
			resultButtons[1] = AMSGBTN_YES;
			resultButtons[0] = AMSGBTN_NO;
			indexCancel = 1;
		}
		int index = kdShowMessage(title.c_str(), text.c_str(), buttons);
		if (index == -1)
		{
			index = indexCancel;
		}
		if (callback != NULL && index >= 0)
		{
			(*callback)(resultButtons[index]);
		}
	}

}
#endif
<commit_msg>- WinRT KD update<commit_after>/// @file
/// @author  Boris Mikic
/// @version 3.1
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://www.opensource.org/licenses/bsd-license.php

#ifdef _OPENKODE
#include <KD/kd.h>

#include <gtypes/Vector2.h>
#include <hltypes/hlog.h>
#include <hltypes/hltypesUtil.h>
#include <hltypes/hmap.h>
#include <hltypes/hplatform.h>
#include <hltypes/hstring.h>

#include "april.h"

#ifdef _EGL
#include "egl.h"
#endif
#include "Platform.h"
#include "RenderSystem.h"
#include "Window.h"

#ifdef __APPLE__
	#include <TargetConditionals.h>
	#if TARGET_OS_IPHONE
		void getStaticiOSInfo(chstr name, april::SystemInfo& info);
	#elif TARGET_OS_MAC
		#include <sys/sysctl.h>
	#endif
#endif

namespace april
{
	static SystemInfo info;
	SystemInfo getSystemInfo()
	{
		if (info.locale == "")
		{
			// number of CPU cores
			info.cpuCores = 1;
#if TARGET_OS_IPHONE // On iOS, april prefers to use hardcoded device info then OpenKODE's info, it's more accurate
			hstr model = kdQueryAttribcv(KD_ATTRIB_PLATFORM);
			if (model.contains("(") && model.contains(")"))
			{
				hstr a, b;
				model.split("(",a, b);
				b.split(")", model, a);
				getStaticiOSInfo(model, info);
			}
#elif defined(__APPLE__) && defined(_PC_INPUT) // mac
			info.cpuCores = sysconf(_SC_NPROCESSORS_ONLN);
#elif defined(_WINRT)
			SYSTEM_INFO w32info;
			GetNativeSystemInfo(&w32info);
			info.cpuCores = w32info.dwNumberOfProcessors;
#endif
			// RAM size
#if TARGET_IPHONE_SIMULATOR
			info.ram = 1024;
#elif defined(__APPLE__) && defined(_PC_INPUT) // mac
			int mib [] = { CTL_HW, HW_MEMSIZE };
			int64_t value = 0;
			size_t length = sizeof(value);

			if (sysctl(mib, 2, &value, &length, NULL, 0) == -1)
			{
				info.ram = 2048;
			}
			else
			{
				info.ram = value / (1024 * 1024);
			}
#else
			int ram;
			kdQueryAttribi(KD_ATTRIB_RAM, (KDint*)&ram);
			info.ram = ram / 1048576; // in MB
#endif
			// display resolution
			int width = 0;
			int height = 0;
			kdQueryAttribi(KD_ATTRIB_WIDTH, (KDint*)&width);
			kdQueryAttribi(KD_ATTRIB_HEIGHT, (KDint*)&height);
			info.displayResolution.set((float)width, (float)height);
			// display DPI
			kdQueryAttribi(KD_ATTRIB_DPI, (KDint*)&info.displayDpi);
			// other
			info.locale = hstr(kdGetLocale());
			if (info.locale == "")
			{
				info.locale = "en"; // default is "en"
			}
			else if (info.locale == "pt_PT")
			{
				info.locale = "pt-PT";
			}
			else if (info.locale.utf8_size() > 2 && info.locale != "pt-PT")
			{
				info.locale = info.locale.utf8_substr(0, 2);
			}
		}
		if (info.maxTextureSize == 0 && april::rendersys != NULL)
		{
			info.maxTextureSize = april::rendersys->getMaxTextureSize();
		}
		return info;
	}

	DeviceType getDeviceType()
	{
		return DEVICE_OPENKODE;
	}

	hstr getPackageName()
	{
#ifndef _WINRT
		return hstr(kdGetenv("KD_APP_ID"));
#else
		return _HL_PSTR_TO_HSTR(Windows::ApplicationModel::Package::Current->Id->FamilyName);
#endif
	}

	hstr getUserDataPath()
	{
		return "data";
	}

	void messageBox_platform(chstr title, chstr text, MessageBoxButton buttonMask, MessageBoxStyle style,
		hmap<MessageBoxButton, hstr> customButtonTitles, void(*callback)(MessageBoxButton))
	{
		hstr ok;
		hstr yes;
		hstr no;
		hstr cancel;
		_makeButtonLabels(&ok, &yes, &no, &cancel, buttonMask, customButtonTitles);
		const char* buttons[4] = {"", NULL, NULL, NULL};
		MessageBoxButton resultButtons[4] = {AMSGBTN_NULL, AMSGBTN_NULL, AMSGBTN_NULL, AMSGBTN_NULL};
		int indexCancel = -1;
		if ((buttonMask & AMSGBTN_OK) && (buttonMask & AMSGBTN_CANCEL))
		{
			// order is reversed because libKD prefers the colored button to be at place [1], at least on iOS
			// if this is going to be changed for a new platform, ifdef the button order for iOS
			buttons[1] = ok.c_str();
			buttons[0] = cancel.c_str();
			resultButtons[1] = AMSGBTN_OK;
			resultButtons[0] = AMSGBTN_CANCEL;
			indexCancel = 0;
		}
		else if ((buttonMask & AMSGBTN_YES) && (buttonMask & AMSGBTN_NO) && (buttonMask & AMSGBTN_CANCEL))
		{
			buttons[1] = yes.c_str();
			buttons[0] = no.c_str();
			buttons[2] = cancel.c_str();
			resultButtons[1] = AMSGBTN_YES;
			resultButtons[0] = AMSGBTN_NO;
			resultButtons[2] = AMSGBTN_CANCEL;
			indexCancel = 2;
		}
		else if (buttonMask & AMSGBTN_OK)
		{
			buttons[0] = ok.c_str();
			resultButtons[0] = AMSGBTN_OK;
			indexCancel = 0;
		}
		else if ((buttonMask & AMSGBTN_YES) && (buttonMask & AMSGBTN_NO))
		{
			buttons[1] = yes.c_str();
			buttons[0] = no.c_str();
			resultButtons[1] = AMSGBTN_YES;
			resultButtons[0] = AMSGBTN_NO;
			indexCancel = 1;
		}
		int index = kdShowMessage(title.c_str(), text.c_str(), buttons);
		if (index == -1)
		{
			index = indexCancel;
		}
		if (callback != NULL && index >= 0)
		{
			(*callback)(resultButtons[index]);
		}
	}

}
#endif
<|endoftext|>


<commit_before>#include <common.h>
#include "spritesheets/assets.c"
#include "entity.h"
#include "player.h"
#include "world.h"
#include "levels.h"
// The following assumes a 128x128px spritesheet with 16x16px sprites.
#define render_sprite(spritesheet, sprite_index, x, y) ST_RenderSpritePosition((spritesheet), ((sprite_index) % 8) * 16, ((sprite_index) / 8) * 16, 16, 16, (x), (y))

//extern const st_image player_spritesheet;
level_t level1 =\
{
  {1, 13},
  {13, 1},
  120,
  { {W, W, W, W, W, W, W, W, W, W, W, W, W, W, W},
    {W, P, P, W, D, B, B, B, B, B, M, B, W, R, W},
    {W, P, P, S, B, B, S, B, B, B, B, M, W, B, W},
    {W, B, B, B, S, B, B, S, S, S, B, B, M, B, W},
    {W, B, B, B, B, S, B, B, S, B, S, B, B, D, W},
    {W, B, B, B, B, B, S, B, B, S, B, S, B, D, W},
    {W, B, B, B, W, B, W, S, B, S, B, B, S, B, W},
    {W, B, B, S, B, S, B, D, B, S, B, B, B, S, W},
    {W, W, W, W, B, B, B, S, W, B, B, B, B, B, W},
    {W, B, B, W, B, W, M, M, B, W, B, B, B, B, W},
    {W, D, B, B, B, S, S, S, B, W, B, B, B, B, W},
    {W, B, P, P, W, M, M, M, M, W, B, B, B, B, W},
    {W, B, P, P, B, B, B, W, W, W, B, B, B, B, W},
    {W, B, B, S, P, B, B, B, B, B, B, B, B, B, W},
    {W, W, W, W, W, W, W, W, W, W, W, W, W, W, W} }
};

level_t level2 =\
{
  {1, 1 },
  {13, 10},
  20, //Is this even possible? I have no idea.
  //                               1  1  1  1  1
  // 0  1  2  3  4  5  6  7  8  9  0  1  2  3  4
  { {W, W, W, W, W, W, W, W, W, W, W, W, W, W, W}, //0
    {W, B, W, B, B, B, B, B, W, B, B, B, S, B, W}, //1
    {W, B, S, B, S, B, S, B, B, S, B, B, W, B, W}, //2
    {W, B, S, B, S, B, S, B, B, S, B, B, S, B, W}, //3
    {W, B, B, B, W, B, W, B, B, B, B, B, S, B, W}, //4
    {W, S, S, S, S, S, S, S, S, S, B, B, B, B, W}, //5
    {W, B, B, B, S, B, B, B, B, S, S, S, S, B, W}, //6
    {W, B, S, B, S, B, S, S, B, B, S, B, B, B, W}, //7
    {W, B, S, B, S, B, B, S, S, B, S, B, S, B, W}, //8
    {W, B, S, B, S, S, B, S, B, B, S, B, S, S, W}, //9
    {W, B, D, B, B, B, B, S, B, S, S, B, S, R, W}, //10
    {W, B, S, S, S, S, S, S, B, B, B, B, S, B, W}, //11
    {W, B, S, S, S, S, S, S, S, S, S, S, S, B, W}, //12
    {W, B, B, B, B, B, B, B, B, B, B, B, B, B, W}, //13
    {W, W, W, W, W, W, W, W, W, W, W, W, W, W, W} }//14
};

#define current_level (level_switch ? level1 : level2)

void draw_water(st_spritesheet *sheet, int framecount)
{
	std::vector<unsigned char> water_tiles = {WATER_1, WATER_2, WATER_3, WATER_4};
	for (int k = 0; k < 321; k += 320)
		for (int i = 0; i < 5; i++)
			for (int j = 0; j < 15; j++)
			ST_RenderSpritePosition(sheet, (water_tiles[(int)(framecount % (80)) / 20] % 8) * 16, (water_tiles[(int)(framecount % (80)) / 20] / 8 * 16), 16, 16, 16 * i + k, 16 * j);
}

int main(int argc, char **argv) {
	ST_Init();
	consoleInit(GFX_BOTTOM, NULL);
	int framecount = 0;
	u64 game_clock;
	st_spritesheet *player_ss = ST_SpritesheetCreateSpritesheet(
		main_spritesheet_data.pixel_data,
		main_spritesheet_data.width,
		main_spritesheet_data.height);
	ST_RenderSetBackground(0x82, 0xE1, 0x11);
	World world = World(player_ss);
	bool level_switch = true;
	world.load_level(player_ss, current_level);
	bool player_mode = true;
	while(aptMainLoop())
	{
		ST_RenderStartFrame(GFX_TOP);
		ST_InputScan();
			if (ST_InputButtonPressed(KEY_DUP))
			{
				if (world.player_can_move_rel(0, -1))
					world.player.move_rel(0, -1);
				world.player.direction = UP;
			}

			if (ST_InputButtonPressed(KEY_DDOWN))
			{
				if (world.player_can_move_rel(0, 1))
					world.player.move_rel(0, 1);
				world.player.direction = DOWN;
			}
			if (ST_InputButtonPressed(KEY_DLEFT))
			{
				if (world.player_can_move_rel(-1, 0))
					world.player.move_rel(-1, 0);
				world.player.direction = LEFT;
			}
			if (ST_InputButtonPressed(KEY_DRIGHT))
			{
				if (world.player_can_move_rel(1, 0))
					world.player.move_rel(1, 0);
				world.player.direction = RIGHT;
			}
			if (ST_InputButtonPressed(KEY_SELECT))
			{
				player_mode = !player_mode;
			}
			if (ST_InputButtonPressed(KEY_START))
			{
				level_switch = !level_switch;
				world.load_level(player_ss, current_level);
			}
			world.render_all(player_mode, framecount);
			draw_water(player_ss, framecount);
			game_clock = ST_TimeRunning() - world.start_time;
			if (game_clock > 1000 * current_level.seconds && !world.player_won())
				world.load_level(player_ss, current_level);
			else
				printf("\x1b[0;0H%03d",current_level.seconds - (int)game_clock/1000);
		ST_RenderEndRender();
		if (world.player_won())
			printf("YOU WON!!");
			//world.load_level(player_ss, level1);
		if (world.player_is_on_mine())
			world.load_level(player_ss, current_level);
		framecount++;
	}

	ST_SpritesheetFreeSpritesheet(player_ss);
	ST_Fini();
	return 0;
}
<commit_msg>Changed level 1 timer<commit_after>#include <common.h>
#include "spritesheets/assets.c"
#include "entity.h"
#include "player.h"
#include "world.h"
#include "levels.h"
// The following assumes a 128x128px spritesheet with 16x16px sprites.
#define render_sprite(spritesheet, sprite_index, x, y) ST_RenderSpritePosition((spritesheet), ((sprite_index) % 8) * 16, ((sprite_index) / 8) * 16, 16, 16, (x), (y))

//extern const st_image player_spritesheet;
level_t level1 =\
{
  {1, 13},
  {13, 1},
  25,
  { {W, W, W, W, W, W, W, W, W, W, W, W, W, W, W},
    {W, P, P, W, D, B, B, B, B, B, M, B, W, R, W},
    {W, P, P, S, B, B, S, B, B, B, B, M, W, B, W},
    {W, B, B, B, S, B, B, S, S, S, B, B, M, B, W},
    {W, B, B, B, B, S, B, B, S, B, S, B, B, D, W},
    {W, B, B, B, B, B, S, B, B, S, B, S, B, D, W},
    {W, B, B, B, W, B, W, S, B, S, B, B, S, B, W},
    {W, B, B, S, B, S, B, D, B, S, B, B, B, S, W},
    {W, W, W, W, B, B, B, S, W, B, B, B, B, B, W},
    {W, B, B, W, B, W, M, M, B, W, B, B, B, B, W},
    {W, D, B, B, B, S, S, S, B, W, B, B, B, B, W},
    {W, B, P, P, W, M, M, M, M, W, B, B, B, B, W},
    {W, B, P, P, B, B, B, W, W, W, B, B, B, B, W},
    {W, B, B, S, P, B, B, B, B, B, B, B, B, B, W},
    {W, W, W, W, W, W, W, W, W, W, W, W, W, W, W} }
};

level_t level2 =\
{
  {1, 1 },
  {13, 10},
  20, //Is this even possible? I have no idea.
  //                               1  1  1  1  1
  // 0  1  2  3  4  5  6  7  8  9  0  1  2  3  4
  { {W, W, W, W, W, W, W, W, W, W, W, W, W, W, W}, //0
    {W, B, W, B, B, B, B, B, W, B, B, B, S, B, W}, //1
    {W, B, S, B, S, B, S, B, B, S, B, B, W, B, W}, //2
    {W, B, S, B, S, B, S, B, B, S, B, B, S, B, W}, //3
    {W, B, B, B, W, B, W, B, B, B, B, B, S, B, W}, //4
    {W, S, S, S, S, S, S, S, S, S, B, B, B, B, W}, //5
    {W, B, B, B, S, B, B, B, B, S, S, S, S, B, W}, //6
    {W, B, S, B, S, B, S, S, B, B, S, B, B, B, W}, //7
    {W, B, S, B, S, B, B, S, S, B, S, B, S, B, W}, //8
    {W, B, S, B, S, S, B, S, B, B, S, B, S, S, W}, //9
    {W, B, D, B, B, B, B, S, B, S, S, B, S, R, W}, //10
    {W, B, S, S, S, S, S, S, B, B, B, B, S, B, W}, //11
    {W, B, S, S, S, S, S, S, S, S, S, S, S, B, W}, //12
    {W, B, B, B, B, B, B, B, B, B, B, B, B, B, W}, //13
    {W, W, W, W, W, W, W, W, W, W, W, W, W, W, W} }//14
};

#define current_level (level_switch ? level1 : level2)

void draw_water(st_spritesheet *sheet, int framecount)
{
	std::vector<unsigned char> water_tiles = {WATER_1, WATER_2, WATER_3, WATER_4};
	for (int k = 0; k < 321; k += 320)
		for (int i = 0; i < 5; i++)
			for (int j = 0; j < 15; j++)
			ST_RenderSpritePosition(sheet, (water_tiles[(int)(framecount % (80)) / 20] % 8) * 16, (water_tiles[(int)(framecount % (80)) / 20] / 8 * 16), 16, 16, 16 * i + k, 16 * j);
}

int main(int argc, char **argv) {
	ST_Init();
	consoleInit(GFX_BOTTOM, NULL);
	int framecount = 0;
	u64 game_clock;
	st_spritesheet *player_ss = ST_SpritesheetCreateSpritesheet(
		main_spritesheet_data.pixel_data,
		main_spritesheet_data.width,
		main_spritesheet_data.height);
	ST_RenderSetBackground(0x82, 0xE1, 0x11);
	World world = World(player_ss);
	bool level_switch = true;
	world.load_level(player_ss, current_level);
	bool player_mode = true;
	while(aptMainLoop())
	{
		ST_RenderStartFrame(GFX_TOP);
		ST_InputScan();
			if (ST_InputButtonPressed(KEY_DUP))
			{
				if (world.player_can_move_rel(0, -1))
					world.player.move_rel(0, -1);
				world.player.direction = UP;
			}

			if (ST_InputButtonPressed(KEY_DDOWN))
			{
				if (world.player_can_move_rel(0, 1))
					world.player.move_rel(0, 1);
				world.player.direction = DOWN;
			}
			if (ST_InputButtonPressed(KEY_DLEFT))
			{
				if (world.player_can_move_rel(-1, 0))
					world.player.move_rel(-1, 0);
				world.player.direction = LEFT;
			}
			if (ST_InputButtonPressed(KEY_DRIGHT))
			{
				if (world.player_can_move_rel(1, 0))
					world.player.move_rel(1, 0);
				world.player.direction = RIGHT;
			}
			if (ST_InputButtonPressed(KEY_SELECT))
			{
				player_mode = !player_mode;
			}
			if (ST_InputButtonPressed(KEY_START))
			{
				level_switch = !level_switch;
				world.load_level(player_ss, current_level);
			}
			world.render_all(player_mode, framecount);
			draw_water(player_ss, framecount);
			game_clock = ST_TimeRunning() - world.start_time;
			if (game_clock > 1000 * current_level.seconds && !world.player_won())
				world.load_level(player_ss, current_level);
			else
				printf("\x1b[0;0H%03d",current_level.seconds - (int)game_clock/1000);
		ST_RenderEndRender();
		if (world.player_won())
			printf("YOU WON!!");
			//world.load_level(player_ss, level1);
		if (world.player_is_on_mine())
			world.load_level(player_ss, current_level);
		framecount++;
	}

	ST_SpritesheetFreeSpritesheet(player_ss);
	ST_Fini();
	return 0;
}
<|endoftext|>