<commit_before>// -------------------------------------------------------------------
/// \file   VertexStats.cxx
/// \brief
///
/// \author  <justo.martin-albo@physics.ox.ac.uk>
/// \date    Creation: 24 July 2016
// -------------------------------------------------------------------

#include <TChain.h>
#include <TGeoManager.h>
#include <TGeoNode.h>
#include <TGeoVolume.h>
#include <TLorentzVector.h>

#include <Ntuple/NtpMCEventRecord.h>
#include <EVGCore/EventRecord.h>

#include <iostream>

TChain* OpenGenieFiles(const std::string& filename)
{
  TChain* chain = new TChain("gtree");
  int num_files;
  num_files = chain->Add(filename.c_str());
  std::cout << num_files << std::endl;
  return chain;
}

int main(int argc, char const *argv[])
{
  std::string geom_file = "geometry.gdml";
  std::string genie_files = "neutrino.862806.*";

  TChain* chain = new TChain("gtree");
  chain->Add(genie_files.c_str());

  genie::NtpMCEventRecord* mcrec = 0;
  chain->SetBranchAddress("gmcrec", &mcrec);

  TGeoManager* geomgr = new TGeoManager();
  geomgr->Import(geom_file.c_str());

  std::cout << "Loaded geometry" << std::endl;

  TFile* current_file = 0;
  double total_pot = 0.;

  std::cout << "Number of entries in TChain: " << chain->GetEntries() << std::endl;

  for (int i=0; i<chain->GetEntries(); i++) {

    std::cout << "entry no. " << i << std::endl;

    chain->GetEntry(i);

    std::cout << "POT: " << chain->GetWeight() << std::endl;

    genie::EventRecord* record = mcrec->event;

    TLorentzVector* vertex_position = record->Vertex();

    geomgr->SetCurrentPoint(vertex_position->X() * 100.,
			    vertex_position->Y() * 100.,
			    vertex_position->Z() * 100.);

    TGeoNode* node = geomgr->FindNode();
    std::cout << "Name: " << node->GetName() << std::endl;
    TGeoMatrix* matrix = node->GetMatrix();
    const Double_t* tr = matrix->GetTranslation();

    std::cout << "X = " << tr[0] << " Y = " << tr[1] << " Z = " << tr[2] << std::endl;

  }

  std::cout << total_pot << std::endl;

  return 0;
}
<commit_msg>Updates.<commit_after>// -------------------------------------------------------------------
/// \file   VertexStats.cxx
/// \brief
///
/// \author  <justo.martin-albo@physics.ox.ac.uk>
/// \date    Creation: 24 July 2016
// -------------------------------------------------------------------

#include <TChain.h>
#include <TGeoManager.h>
#include <TGeoNode.h>
#include <TGeoVolume.h>
#include <TLorentzVector.h>

#include <Ntuple/NtpMCEventRecord.h>
#include <EVGCore/EventRecord.h>

#include <iostream>
#include <getopt.h>

namespace {
  std::string geometry_file_("");
  std::string genie_files_("");
  struct DetVol {
    std::string name;
    TVector3 position;
    int num_vertices;
  };
}

void ParseCmdLineOptions(int argc, char** argv)
{
  int c;

  while (true) {
    static struct option long_options[] =
    {
      {"geometry",    required_argument, 0, 'g'},
      {"genie_files", required_argument, 0, 'i'},
      {0, 0, 0, 0}
    };

    int option_index = 0;

    c = getopt_long(argc, argv, "g:i:", long_options, &option_index);

    if (c == -1) break;

    switch (c) {
      case 'g':
        geometry_file_ = std::string(optarg);
        break;
      case 'i':
        genie_files_ = std::string(optarg);
        break;
      case '?':
        exit(EXIT_FAILURE);
        break;
      default:
        exit(EXIT_FAILURE);
    }
  }
}

TGeoManager* LoadGeometry(const std::string& filename)
{
  TGeoManager* gm = new TGeoManager();
  gm->Import(filename.c_str());
  if (!(gm->GetTopNode())) {
    std::cerr << "ERROR: Failed to open geometry file." << std::endl;
    exit(EXIT_FAILURE);
  }
  return gm;
}

TChain* OpenGenieFiles(const std::string& filename)
{
  TChain* chain = new TChain("gtree");
  int num_files;
  num_files = chain->Add(filename.c_str());
  std::cout << num_files << std::endl;
  return chain;
}

int main(int argc, char** argv)
{
  ParseCmdLineOptions(argc, argv);
  TGeoManager* geomgr = LoadGeometry(geometry_file_);
  TChain* chain = OpenGenieFiles(genie_files_);

  genie::NtpMCEventRecord* mcrec = 0;
  chain->SetBranchAddress("gmcrec", &mcrec);

  std::cout << "Loaded geometry" << std::endl;

  TFile* current_file = 0;
  double total_pot = 0.;

  std::cout << "Number of entries in TChain: " << chain->GetEntries() << std::endl;

  std::map<TGeoNode*, DetVol> node_map;

  for (int i=0; i<chain->GetEntries(); i++) {

    // Load a new entry from the chain
    chain->GetEntry(i);
    genie::EventRecord* record = mcrec->event;

    // Locate the interaction vertex in the geometry.
    // (Quantities stored by GENIE are expressed in the SI, while ROOT's
    // TGeoManager uses the CGS. Therefore, we multiply the vertex position
    // by a factor of 100 to transform from m to cm.)
    TGeoNode* node = geomgr->FindNode(record->Vertex()->X() * 100.,
                                      record->Vertex()->Y() * 100.,
                                      record->Vertex()->Z() * 100.);

    if (geomgr->GetLevel() > 2) {
      geomgr->CdUp();
      node = geomgr->GetCurrentNode();
    }

    auto it = node_map.find(node);
    if (it == node_map.end()) {
      DetVol dv;
      dv.name = std::string(node->GetName());
      const Double_t* xyz = node->GetMatrix()->GetTranslation();
      dv.position.SetXYZ(xyz[0], xyz[1], xyz[2]);
      dv.num_vertices = 1;
    }
    else {
      (*it).second.num_vertices++;
    }

  }

  for (auto kv: node_map) {
    std::cout << "Name: " << kv.second.name << std::endl;
  }

  return 0;
}
<|endoftext|>


<commit_before>//===- PseudoLoweringEmitter.cpp - PseudoLowering Generator -----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "pseudo-lowering"
#include "CodeGenInstruction.h"
#include "CodeGenTarget.h"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <vector>
using namespace llvm;

namespace {
class PseudoLoweringEmitter {
  struct OpData {
    enum MapKind { Operand, Imm, Reg };
    MapKind Kind;
    union {
      unsigned Operand;   // Operand number mapped to.
      uint64_t Imm;       // Integer immedate value.
      Record *Reg;        // Physical register.
    } Data;
  };
  struct PseudoExpansion {
    CodeGenInstruction Source;  // The source pseudo instruction definition.
    CodeGenInstruction Dest;    // The destination instruction to lower to.
    IndexedMap<OpData> OperandMap;

    PseudoExpansion(CodeGenInstruction &s, CodeGenInstruction &d,
                    IndexedMap<OpData> &m) :
      Source(s), Dest(d), OperandMap(m) {}
  };

  RecordKeeper &Records;

  // It's overkill to have an instance of the full CodeGenTarget object,
  // but it loads everything on demand, not in the constructor, so it's
  // lightweight in performance, so it works out OK.
  CodeGenTarget Target;

  SmallVector<PseudoExpansion, 64> Expansions;

  unsigned addDagOperandMapping(Record *Rec, DagInit *Dag,
                                CodeGenInstruction &Insn,
                                IndexedMap<OpData> &OperandMap,
                                unsigned BaseIdx);
  void evaluateExpansion(Record *Pseudo);
  void emitLoweringEmitter(raw_ostream &o);
public:
  PseudoLoweringEmitter(RecordKeeper &R) : Records(R), Target(R) {}

  /// run - Output the pseudo-lowerings.
  void run(raw_ostream &o);
};
} // End anonymous namespace

// FIXME: This pass currently can only expand a pseudo to a single instruction.
//        The pseudo expansion really should take a list of dags, not just
//        a single dag, so we can do fancier things.

unsigned PseudoLoweringEmitter::
addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Insn,
                     IndexedMap<OpData> &OperandMap, unsigned BaseIdx) {
  unsigned OpsAdded = 0;
  for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {
    if (DefInit *DI = dynamic_cast<DefInit*>(Dag->getArg(i))) {
      // Physical register reference. Explicit check for the special case
      // "zero_reg" definition.
      if (DI->getDef()->isSubClassOf("Register") ||
          DI->getDef()->getName() == "zero_reg") {
        OperandMap[BaseIdx + i].Kind = OpData::Reg;
        OperandMap[BaseIdx + i].Data.Reg = DI->getDef();
        ++OpsAdded;
        continue;
      }

      // Normal operands should always have the same type, or we have a
      // problem.
      // FIXME: We probably shouldn't ever get a non-zero BaseIdx here.
      assert(BaseIdx == 0 && "Named subargument in pseudo expansion?!");
      if (DI->getDef() != Insn.Operands[BaseIdx + i].Rec)
        throw TGError(Rec->getLoc(),
                      "Pseudo operand type '" + DI->getDef()->getName() +
                      "' does not match expansion operand type '" +
                      Insn.Operands[BaseIdx + i].Rec->getName() + "'");
      // Source operand maps to destination operand. The Data element
      // will be filled in later, just set the Kind for now. Do it
      // for each corresponding MachineInstr operand, not just the first.
      for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I)
        OperandMap[BaseIdx + i + I].Kind = OpData::Operand;
      OpsAdded += Insn.Operands[i].MINumOperands;
    } else if (IntInit *II = dynamic_cast<IntInit*>(Dag->getArg(i))) {
      OperandMap[BaseIdx + i].Kind = OpData::Imm;
      OperandMap[BaseIdx + i].Data.Imm = II->getValue();
      ++OpsAdded;
    } else if (DagInit *SubDag = dynamic_cast<DagInit*>(Dag->getArg(i))) {
      // Just add the operands recursively. This is almost certainly
      // a constant value for a complex operand (> 1 MI operand).
      unsigned NewOps =
        addDagOperandMapping(Rec, SubDag, Insn, OperandMap, BaseIdx + i);
      OpsAdded += NewOps;
      // Since we added more than one, we also need to adjust the base.
      BaseIdx += NewOps - 1;
    } else
      llvm_unreachable("Unhandled pseudo-expansion argument type!");
  }
  return OpsAdded;
}

void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) {
  DEBUG(dbgs() << "Pseudo definition: " << Rec->getName() << "\n");

  // Validate that the result pattern has the corrent number and types
  // of arguments for the instruction it references.
  DagInit *Dag = Rec->getValueAsDag("ResultInst");
  assert(Dag && "Missing result instruction in pseudo expansion!");
  DEBUG(dbgs() << "  Result: " << *Dag << "\n");

  DefInit *OpDef = dynamic_cast<DefInit*>(Dag->getOperator());
  if (!OpDef)
    throw TGError(Rec->getLoc(), Rec->getName() +
                  " has unexpected operator type!");
  Record *Operator = OpDef->getDef();
  if (!Operator->isSubClassOf("Instruction"))
    throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() +
                                 "' is not an instruction!");

  CodeGenInstruction Insn(Operator);

  if (Insn.isCodeGenOnly || Insn.isPseudo)
    throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() +
                                 "' cannot be another pseudo instruction!");

  if (Insn.Operands.size() != Dag->getNumArgs())
    throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() +
                                 "' operand count mismatch");

  unsigned NumMIOperands = 0;
  for (unsigned i = 0, e = Insn.Operands.size(); i != e; ++i)
    NumMIOperands += Insn.Operands[i].MINumOperands;
  IndexedMap<OpData> OperandMap;
  OperandMap.grow(NumMIOperands);

  addDagOperandMapping(Rec, Dag, Insn, OperandMap, 0);

  // If there are more operands that weren't in the DAG, they have to
  // be operands that have default values, or we have an error. Currently,
  // Operands that are a sublass of OperandWithDefaultOp have default values.

  // Validate that each result pattern argument has a matching (by name)
  // argument in the source instruction, in either the (outs) or (ins) list.
  // Also check that the type of the arguments match.
  //
  // Record the mapping of the source to result arguments for use by
  // the lowering emitter.
  CodeGenInstruction SourceInsn(Rec);
  StringMap<unsigned> SourceOperands;
  for (unsigned i = 0, e = SourceInsn.Operands.size(); i != e; ++i)
    SourceOperands[SourceInsn.Operands[i].Name] = i;

  DEBUG(dbgs() << "  Operand mapping:\n");
  for (unsigned i = 0, e = Insn.Operands.size(); i != e; ++i) {
    // We've already handled constant values. Just map instruction operands
    // here.
    if (OperandMap[Insn.Operands[i].MIOperandNo].Kind != OpData::Operand)
      continue;
    StringMap<unsigned>::iterator SourceOp =
      SourceOperands.find(Dag->getArgName(i));
    if (SourceOp == SourceOperands.end())
      throw TGError(Rec->getLoc(),
                    "Pseudo output operand '" + Dag->getArgName(i) +
                    "' has no matching source operand.");
    // Map the source operand to the destination operand index for each
    // MachineInstr operand.
    for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I)
      OperandMap[Insn.Operands[i].MIOperandNo + I].Data.Operand =
        SourceOp->getValue();

    DEBUG(dbgs() << "    " << SourceOp->getValue() << " ==> " << i << "\n");
  }

  Expansions.push_back(PseudoExpansion(SourceInsn, Insn, OperandMap));
}

void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) {
  // Emit file header.
  emitSourceFileHeader("Pseudo-instruction MC lowering Source Fragment", o);

  o << "bool " << Target.getName() + "AsmPrinter" << "::\n"
    << "emitPseudoExpansionLowering(MCStreamer &OutStreamer,\n"
    << "                            const MachineInstr *MI) {\n"
    << "  switch (MI->getOpcode()) {\n"
    << "    default: return false;\n";
  for (unsigned i = 0, e = Expansions.size(); i != e; ++i) {
    PseudoExpansion &Expansion = Expansions[i];
    CodeGenInstruction &Source = Expansion.Source;
    CodeGenInstruction &Dest = Expansion.Dest;
    o << "    case " << Source.Namespace << "::"
      << Source.TheDef->getName() << ": {\n"
      << "      MCInst TmpInst;\n"
      << "      MCOperand MCOp;\n"
      << "      TmpInst.setOpcode(" << Dest.Namespace << "::"
      << Dest.TheDef->getName() << ");\n";

    // Copy the operands from the source instruction.
    // FIXME: Instruction operands with defaults values (predicates and cc_out
    //        in ARM, for example shouldn't need explicit values in the
    //        expansion DAG.
    unsigned MIOpNo = 0;
    for (unsigned OpNo = 0, E = Dest.Operands.size(); OpNo != E;
         ++OpNo) {
      o << "      // Operand: " << Dest.Operands[OpNo].Name << "\n";
      for (unsigned i = 0, e = Dest.Operands[OpNo].MINumOperands;
           i != e; ++i) {
        switch (Expansion.OperandMap[MIOpNo + i].Kind) {
        case OpData::Operand:
          o << "      lowerOperand(MI->getOperand("
            << Source.Operands[Expansion.OperandMap[MIOpNo].Data
                .Operand].MIOperandNo + i
            << "), MCOp);\n"
            << "      TmpInst.addOperand(MCOp);\n";
          break;
        case OpData::Imm:
          o << "      TmpInst.addOperand(MCOperand::CreateImm("
            << Expansion.OperandMap[MIOpNo + i].Data.Imm << "));\n";
          break;
        case OpData::Reg: {
          Record *Reg = Expansion.OperandMap[MIOpNo + i].Data.Reg;
          o << "      TmpInst.addOperand(MCOperand::CreateReg(";
          // "zero_reg" is special.
          if (Reg->getName() == "zero_reg")
            o << "0";
          else
            o << Reg->getValueAsString("Namespace") << "::" << Reg->getName();
          o << "));\n";
          break;
        }
        }
      }
      MIOpNo += Dest.Operands[OpNo].MINumOperands;
    }
    if (Dest.Operands.isVariadic) {
      o << "      // variable_ops\n";
      o << "      for (unsigned i = " << MIOpNo
        << ", e = MI->getNumOperands(); i != e; ++i)\n"
        << "        if (lowerOperand(MI->getOperand(i), MCOp))\n"
        << "          TmpInst.addOperand(MCOp);\n";
    }
    o << "      OutStreamer.EmitInstruction(TmpInst);\n"
      << "      break;\n"
      << "    }\n";
  }
  o << "  }\n  return true;\n}\n\n";
}

void PseudoLoweringEmitter::run(raw_ostream &o) {
  Record *ExpansionClass = Records.getClass("PseudoInstExpansion");
  Record *InstructionClass = Records.getClass("PseudoInstExpansion");
  assert(ExpansionClass && "PseudoInstExpansion class definition missing!");
  assert(InstructionClass && "Instruction class definition missing!");

  std::vector<Record*> Insts;
  for (std::map<std::string, Record*>::const_iterator I =
         Records.getDefs().begin(), E = Records.getDefs().end(); I != E; ++I) {
    if (I->second->isSubClassOf(ExpansionClass) &&
        I->second->isSubClassOf(InstructionClass))
      Insts.push_back(I->second);
  }

  // Process the pseudo expansion definitions, validating them as we do so.
  for (unsigned i = 0, e = Insts.size(); i != e; ++i)
    evaluateExpansion(Insts[i]);

  // Generate expansion code to lower the pseudo to an MCInst of the real
  // instruction.
  emitLoweringEmitter(o);
}

namespace llvm {

void EmitPseudoLowering(RecordKeeper &RK, raw_ostream &OS) {
  PseudoLoweringEmitter(RK).run(OS);
}

} // End llvm namespace
<commit_msg>Fix typo<commit_after>//===- PseudoLoweringEmitter.cpp - PseudoLowering Generator -----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "pseudo-lowering"
#include "CodeGenInstruction.h"
#include "CodeGenTarget.h"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <vector>
using namespace llvm;

namespace {
class PseudoLoweringEmitter {
  struct OpData {
    enum MapKind { Operand, Imm, Reg };
    MapKind Kind;
    union {
      unsigned Operand;   // Operand number mapped to.
      uint64_t Imm;       // Integer immedate value.
      Record *Reg;        // Physical register.
    } Data;
  };
  struct PseudoExpansion {
    CodeGenInstruction Source;  // The source pseudo instruction definition.
    CodeGenInstruction Dest;    // The destination instruction to lower to.
    IndexedMap<OpData> OperandMap;

    PseudoExpansion(CodeGenInstruction &s, CodeGenInstruction &d,
                    IndexedMap<OpData> &m) :
      Source(s), Dest(d), OperandMap(m) {}
  };

  RecordKeeper &Records;

  // It's overkill to have an instance of the full CodeGenTarget object,
  // but it loads everything on demand, not in the constructor, so it's
  // lightweight in performance, so it works out OK.
  CodeGenTarget Target;

  SmallVector<PseudoExpansion, 64> Expansions;

  unsigned addDagOperandMapping(Record *Rec, DagInit *Dag,
                                CodeGenInstruction &Insn,
                                IndexedMap<OpData> &OperandMap,
                                unsigned BaseIdx);
  void evaluateExpansion(Record *Pseudo);
  void emitLoweringEmitter(raw_ostream &o);
public:
  PseudoLoweringEmitter(RecordKeeper &R) : Records(R), Target(R) {}

  /// run - Output the pseudo-lowerings.
  void run(raw_ostream &o);
};
} // End anonymous namespace

// FIXME: This pass currently can only expand a pseudo to a single instruction.
//        The pseudo expansion really should take a list of dags, not just
//        a single dag, so we can do fancier things.

unsigned PseudoLoweringEmitter::
addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Insn,
                     IndexedMap<OpData> &OperandMap, unsigned BaseIdx) {
  unsigned OpsAdded = 0;
  for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {
    if (DefInit *DI = dynamic_cast<DefInit*>(Dag->getArg(i))) {
      // Physical register reference. Explicit check for the special case
      // "zero_reg" definition.
      if (DI->getDef()->isSubClassOf("Register") ||
          DI->getDef()->getName() == "zero_reg") {
        OperandMap[BaseIdx + i].Kind = OpData::Reg;
        OperandMap[BaseIdx + i].Data.Reg = DI->getDef();
        ++OpsAdded;
        continue;
      }

      // Normal operands should always have the same type, or we have a
      // problem.
      // FIXME: We probably shouldn't ever get a non-zero BaseIdx here.
      assert(BaseIdx == 0 && "Named subargument in pseudo expansion?!");
      if (DI->getDef() != Insn.Operands[BaseIdx + i].Rec)
        throw TGError(Rec->getLoc(),
                      "Pseudo operand type '" + DI->getDef()->getName() +
                      "' does not match expansion operand type '" +
                      Insn.Operands[BaseIdx + i].Rec->getName() + "'");
      // Source operand maps to destination operand. The Data element
      // will be filled in later, just set the Kind for now. Do it
      // for each corresponding MachineInstr operand, not just the first.
      for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I)
        OperandMap[BaseIdx + i + I].Kind = OpData::Operand;
      OpsAdded += Insn.Operands[i].MINumOperands;
    } else if (IntInit *II = dynamic_cast<IntInit*>(Dag->getArg(i))) {
      OperandMap[BaseIdx + i].Kind = OpData::Imm;
      OperandMap[BaseIdx + i].Data.Imm = II->getValue();
      ++OpsAdded;
    } else if (DagInit *SubDag = dynamic_cast<DagInit*>(Dag->getArg(i))) {
      // Just add the operands recursively. This is almost certainly
      // a constant value for a complex operand (> 1 MI operand).
      unsigned NewOps =
        addDagOperandMapping(Rec, SubDag, Insn, OperandMap, BaseIdx + i);
      OpsAdded += NewOps;
      // Since we added more than one, we also need to adjust the base.
      BaseIdx += NewOps - 1;
    } else
      llvm_unreachable("Unhandled pseudo-expansion argument type!");
  }
  return OpsAdded;
}

void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) {
  DEBUG(dbgs() << "Pseudo definition: " << Rec->getName() << "\n");

  // Validate that the result pattern has the corrent number and types
  // of arguments for the instruction it references.
  DagInit *Dag = Rec->getValueAsDag("ResultInst");
  assert(Dag && "Missing result instruction in pseudo expansion!");
  DEBUG(dbgs() << "  Result: " << *Dag << "\n");

  DefInit *OpDef = dynamic_cast<DefInit*>(Dag->getOperator());
  if (!OpDef)
    throw TGError(Rec->getLoc(), Rec->getName() +
                  " has unexpected operator type!");
  Record *Operator = OpDef->getDef();
  if (!Operator->isSubClassOf("Instruction"))
    throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() +
                                 "' is not an instruction!");

  CodeGenInstruction Insn(Operator);

  if (Insn.isCodeGenOnly || Insn.isPseudo)
    throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() +
                                 "' cannot be another pseudo instruction!");

  if (Insn.Operands.size() != Dag->getNumArgs())
    throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() +
                                 "' operand count mismatch");

  unsigned NumMIOperands = 0;
  for (unsigned i = 0, e = Insn.Operands.size(); i != e; ++i)
    NumMIOperands += Insn.Operands[i].MINumOperands;
  IndexedMap<OpData> OperandMap;
  OperandMap.grow(NumMIOperands);

  addDagOperandMapping(Rec, Dag, Insn, OperandMap, 0);

  // If there are more operands that weren't in the DAG, they have to
  // be operands that have default values, or we have an error. Currently,
  // Operands that are a sublass of OperandWithDefaultOp have default values.

  // Validate that each result pattern argument has a matching (by name)
  // argument in the source instruction, in either the (outs) or (ins) list.
  // Also check that the type of the arguments match.
  //
  // Record the mapping of the source to result arguments for use by
  // the lowering emitter.
  CodeGenInstruction SourceInsn(Rec);
  StringMap<unsigned> SourceOperands;
  for (unsigned i = 0, e = SourceInsn.Operands.size(); i != e; ++i)
    SourceOperands[SourceInsn.Operands[i].Name] = i;

  DEBUG(dbgs() << "  Operand mapping:\n");
  for (unsigned i = 0, e = Insn.Operands.size(); i != e; ++i) {
    // We've already handled constant values. Just map instruction operands
    // here.
    if (OperandMap[Insn.Operands[i].MIOperandNo].Kind != OpData::Operand)
      continue;
    StringMap<unsigned>::iterator SourceOp =
      SourceOperands.find(Dag->getArgName(i));
    if (SourceOp == SourceOperands.end())
      throw TGError(Rec->getLoc(),
                    "Pseudo output operand '" + Dag->getArgName(i) +
                    "' has no matching source operand.");
    // Map the source operand to the destination operand index for each
    // MachineInstr operand.
    for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I)
      OperandMap[Insn.Operands[i].MIOperandNo + I].Data.Operand =
        SourceOp->getValue();

    DEBUG(dbgs() << "    " << SourceOp->getValue() << " ==> " << i << "\n");
  }

  Expansions.push_back(PseudoExpansion(SourceInsn, Insn, OperandMap));
}

void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) {
  // Emit file header.
  emitSourceFileHeader("Pseudo-instruction MC lowering Source Fragment", o);

  o << "bool " << Target.getName() + "AsmPrinter" << "::\n"
    << "emitPseudoExpansionLowering(MCStreamer &OutStreamer,\n"
    << "                            const MachineInstr *MI) {\n"
    << "  switch (MI->getOpcode()) {\n"
    << "    default: return false;\n";
  for (unsigned i = 0, e = Expansions.size(); i != e; ++i) {
    PseudoExpansion &Expansion = Expansions[i];
    CodeGenInstruction &Source = Expansion.Source;
    CodeGenInstruction &Dest = Expansion.Dest;
    o << "    case " << Source.Namespace << "::"
      << Source.TheDef->getName() << ": {\n"
      << "      MCInst TmpInst;\n"
      << "      MCOperand MCOp;\n"
      << "      TmpInst.setOpcode(" << Dest.Namespace << "::"
      << Dest.TheDef->getName() << ");\n";

    // Copy the operands from the source instruction.
    // FIXME: Instruction operands with defaults values (predicates and cc_out
    //        in ARM, for example shouldn't need explicit values in the
    //        expansion DAG.
    unsigned MIOpNo = 0;
    for (unsigned OpNo = 0, E = Dest.Operands.size(); OpNo != E;
         ++OpNo) {
      o << "      // Operand: " << Dest.Operands[OpNo].Name << "\n";
      for (unsigned i = 0, e = Dest.Operands[OpNo].MINumOperands;
           i != e; ++i) {
        switch (Expansion.OperandMap[MIOpNo + i].Kind) {
        case OpData::Operand:
          o << "      lowerOperand(MI->getOperand("
            << Source.Operands[Expansion.OperandMap[MIOpNo].Data
                .Operand].MIOperandNo + i
            << "), MCOp);\n"
            << "      TmpInst.addOperand(MCOp);\n";
          break;
        case OpData::Imm:
          o << "      TmpInst.addOperand(MCOperand::CreateImm("
            << Expansion.OperandMap[MIOpNo + i].Data.Imm << "));\n";
          break;
        case OpData::Reg: {
          Record *Reg = Expansion.OperandMap[MIOpNo + i].Data.Reg;
          o << "      TmpInst.addOperand(MCOperand::CreateReg(";
          // "zero_reg" is special.
          if (Reg->getName() == "zero_reg")
            o << "0";
          else
            o << Reg->getValueAsString("Namespace") << "::" << Reg->getName();
          o << "));\n";
          break;
        }
        }
      }
      MIOpNo += Dest.Operands[OpNo].MINumOperands;
    }
    if (Dest.Operands.isVariadic) {
      o << "      // variable_ops\n";
      o << "      for (unsigned i = " << MIOpNo
        << ", e = MI->getNumOperands(); i != e; ++i)\n"
        << "        if (lowerOperand(MI->getOperand(i), MCOp))\n"
        << "          TmpInst.addOperand(MCOp);\n";
    }
    o << "      OutStreamer.EmitInstruction(TmpInst);\n"
      << "      break;\n"
      << "    }\n";
  }
  o << "  }\n  return true;\n}\n\n";
}

void PseudoLoweringEmitter::run(raw_ostream &o) {
  Record *ExpansionClass = Records.getClass("PseudoInstExpansion");
  Record *InstructionClass = Records.getClass("Instruction");
  assert(ExpansionClass && "PseudoInstExpansion class definition missing!");
  assert(InstructionClass && "Instruction class definition missing!");

  std::vector<Record*> Insts;
  for (std::map<std::string, Record*>::const_iterator I =
         Records.getDefs().begin(), E = Records.getDefs().end(); I != E; ++I) {
    if (I->second->isSubClassOf(ExpansionClass) &&
        I->second->isSubClassOf(InstructionClass))
      Insts.push_back(I->second);
  }

  // Process the pseudo expansion definitions, validating them as we do so.
  for (unsigned i = 0, e = Insts.size(); i != e; ++i)
    evaluateExpansion(Insts[i]);

  // Generate expansion code to lower the pseudo to an MCInst of the real
  // instruction.
  emitLoweringEmitter(o);
}

namespace llvm {

void EmitPseudoLowering(RecordKeeper &RK, raw_ostream &OS) {
  PseudoLoweringEmitter(RK).run(OS);
}

} // End llvm namespace
<|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS dr58_SRC680 (1.8.150); FILE MERGED 2008/01/08 13:03:30 dr 1.8.150.4: #i84812# import/export solid fill including transparency from Escher property set 2007/12/17 13:49:57 dr 1.8.150.3: #i83372# import/export of data label placement 2007/12/17 11:58:42 dr 1.8.150.2: #i83372# import of data label placement 2007/12/14 14:18:32 dr 1.8.150.1: #i83100# export of trendline equations, default text handling<commit_after><|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS changefileheader (1.14.32); FILE MERGED 2008/03/31 17:14:49 rt 1.14.32.1: #i87441# Change license header to LPGL v3.<commit_after><|endoftext|>


<commit_before><commit_msg>ajout commentaires<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "cpu_reader_support.h"

#include "src/ftrace_reader/ftrace_procfs.h"

namespace perfetto {
namespace {

const size_t kPageSize = 4096;

std::map<std::string, std::unique_ptr<ProtoTranslationTable>>* g_tables;

}  // namespace

ProtoTranslationTable* GetTable(const std::string& name) {
  if (!g_tables)
    g_tables =
        new std::map<std::string, std::unique_ptr<ProtoTranslationTable>>();
  if (!g_tables->count(name)) {
    std::string path = "src/ftrace_reader/test/data/" + name + "/";
    FtraceProcfs ftrace(path);
    auto table = ProtoTranslationTable::Create(&ftrace, GetStaticEventInfo(),
                                               GetStaticCommonFieldsInfo());
    g_tables->emplace(name, std::move(table));
  }
  return g_tables->at(name).get();
}

std::unique_ptr<uint8_t[]> PageFromXxd(const std::string& text) {
  auto buffer = std::unique_ptr<uint8_t[]>(new uint8_t[kPageSize]);
  const char* ptr = text.data();
  memset(buffer.get(), 0xfa, kPageSize);
  uint8_t* out = buffer.get();
  while (*ptr != '\0') {
    if (*(ptr++) != ':')
      continue;
    for (int i = 0; i < 8; i++) {
      PERFETTO_CHECK(text.size() >=
                     static_cast<size_t>((ptr - text.data()) + 5));
      PERFETTO_CHECK(*(ptr++) == ' ');
      int n = sscanf(ptr, "%02hhx%02hhx", out, out + 1);
      PERFETTO_CHECK(n == 2);
      out += n;
      ptr += 4;
    }
    while (*ptr != '\n')
      ptr++;
  }
  return buffer;
}

}  // namespace perfetto
<commit_msg>Fix clang build with use_custom_libcxx=false. am: 3ced8f94a6 am: 60feb0e54c<commit_after>/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "cpu_reader_support.h"

#include "src/ftrace_reader/ftrace_procfs.h"

#include <string.h>

namespace perfetto {
namespace {

const size_t kPageSize = 4096;

std::map<std::string, std::unique_ptr<ProtoTranslationTable>>* g_tables;

}  // namespace

ProtoTranslationTable* GetTable(const std::string& name) {
  if (!g_tables)
    g_tables =
        new std::map<std::string, std::unique_ptr<ProtoTranslationTable>>();
  if (!g_tables->count(name)) {
    std::string path = "src/ftrace_reader/test/data/" + name + "/";
    FtraceProcfs ftrace(path);
    auto table = ProtoTranslationTable::Create(&ftrace, GetStaticEventInfo(),
                                               GetStaticCommonFieldsInfo());
    g_tables->emplace(name, std::move(table));
  }
  return g_tables->at(name).get();
}

std::unique_ptr<uint8_t[]> PageFromXxd(const std::string& text) {
  auto buffer = std::unique_ptr<uint8_t[]>(new uint8_t[kPageSize]);
  const char* ptr = text.data();
  memset(buffer.get(), 0xfa, kPageSize);
  uint8_t* out = buffer.get();
  while (*ptr != '\0') {
    if (*(ptr++) != ':')
      continue;
    for (int i = 0; i < 8; i++) {
      PERFETTO_CHECK(text.size() >=
                     static_cast<size_t>((ptr - text.data()) + 5));
      PERFETTO_CHECK(*(ptr++) == ' ');
      int n = sscanf(ptr, "%02hhx%02hhx", out, out + 1);
      PERFETTO_CHECK(n == 2);
      out += n;
      ptr += 4;
    }
    while (*ptr != '\n')
      ptr++;
  }
  return buffer;
}

}  // namespace perfetto
<|endoftext|>


<commit_before>//===- lib/Trace/ScanFormatSpecifiers.cpp ---------------------------------===//
//
//                                    SeeC
//
// This file is distributed under The MIT License (MIT). See LICENSE.TXT for
// details.
//
//===----------------------------------------------------------------------===//
///
/// \file
///
//===----------------------------------------------------------------------===//

#include "seec/Trace/ScanFormatSpecifiers.hpp"

#include <cstring>
#include <limits>

namespace seec {

namespace trace {

ScanConversionSpecifier
ScanConversionSpecifier::readNextFrom(char const * const String) {
  ScanConversionSpecifier Result;

  // Find '%'.
  Result.Start = std::strchr(String, '%');
  if (!Result.Start)
    return Result;

  auto Remainder = Result.Start;
  if (*++Remainder == '\0')
    return Result;

  // Read assignment suppression '*'.
  if (*Remainder == '*') {
    Result.SuppressAssignment = true;
    if (*++Remainder == '\0')
      return Result;
  }

  // Read maximum field width.
  if(isdigit(*Remainder)){
    Result.WidthSpecified = true;

    // Parse int from string.
    char *ParseEnd;
    Result.Width = std::strtoul(Remainder, &ParseEnd, 10);
    Remainder = ParseEnd;

    if (*Remainder == '\0')
      return Result;
  }

  // Read length modifier.
  Result.Length = readLengthModifier(Remainder, &Remainder);
  if (*Remainder == '\0')
    return Result;

  // Read specifier.
  switch (*Remainder) {
#define SEEC_SCAN_FORMAT_SPECIFIER(ID, CHR, WSPACE, SUPPRESS, LENS)            \
    case CHR:                                                                  \
      Result.Conversion = Specifier::ID;                                       \
      break;
#include "seec/Trace/ScanFormatSpecifiers.def"
    default:
      return Result;
  }

  // Special case for parsing set specifier.
  if (Result.Conversion == Specifier::set) {
    auto const UCharValues = std::numeric_limits<unsigned char>::max() + 1;

    Result.SetLookup.reset(new bool[UCharValues]);
    for (unsigned char i = 0; i < UCharValues; ++i)
      Result.SetLookup[i] = false;

    if (*++Remainder == '\0')
      return Result;

    // Make set a negation.
    if (*Remainder == '^') {
      Result.SetNegation = true;
      if (*++Remainder == '\0')
        return Result;
    }

    // Special case for including ']' in a set.
    if (*Remainder == ']') {
      Result.SetCharacters.push_back(']');

      auto const CharIdx = static_cast<unsigned char>(']');
      assert(CharIdx < UCharValues);
      Result.SetLookup[CharIdx] = true;

      if (*++Remainder == '\0')
        return Result;
    }

    // Add all remaining characters to the set (until ']' is found).
    while (*Remainder != ']') {
      Result.SetCharacters.push_back(*Remainder);

      auto const CharIdx = static_cast<unsigned char>(*Remainder);
      assert(CharIdx < UCharValues);
      Result.SetLookup[CharIdx] = true;

      if (*++Remainder == '\0')
        return Result;
    }

    if (Result.SetNegation) {
      for (unsigned char i = 0; i < UCharValues; ++i)
        Result.SetLookup[i] = !Result.SetLookup[i];
    }
  }

  // Set the end of the parsed region.
  Result.End = ++Remainder;

  return Result;
}

} // namespace trace (in seec)

} // namespace seec
<commit_msg>Fix an endless loop when reading set conversion specifiers.<commit_after>//===- lib/Trace/ScanFormatSpecifiers.cpp ---------------------------------===//
//
//                                    SeeC
//
// This file is distributed under The MIT License (MIT). See LICENSE.TXT for
// details.
//
//===----------------------------------------------------------------------===//
///
/// \file
///
//===----------------------------------------------------------------------===//

#include "seec/Trace/ScanFormatSpecifiers.hpp"

#include <cstring>
#include <limits>

namespace seec {

namespace trace {

ScanConversionSpecifier
ScanConversionSpecifier::readNextFrom(char const * const String) {
  ScanConversionSpecifier Result;

  // Find '%'.
  Result.Start = std::strchr(String, '%');
  if (!Result.Start)
    return Result;

  auto Remainder = Result.Start;
  if (*++Remainder == '\0')
    return Result;

  // Read assignment suppression '*'.
  if (*Remainder == '*') {
    Result.SuppressAssignment = true;
    if (*++Remainder == '\0')
      return Result;
  }

  // Read maximum field width.
  if(isdigit(*Remainder)){
    Result.WidthSpecified = true;

    // Parse int from string.
    char *ParseEnd;
    Result.Width = std::strtoul(Remainder, &ParseEnd, 10);
    Remainder = ParseEnd;

    if (*Remainder == '\0')
      return Result;
  }

  // Read length modifier.
  Result.Length = readLengthModifier(Remainder, &Remainder);
  if (*Remainder == '\0')
    return Result;

  // Read specifier.
  switch (*Remainder) {
#define SEEC_SCAN_FORMAT_SPECIFIER(ID, CHR, WSPACE, SUPPRESS, LENS)            \
    case CHR:                                                                  \
      Result.Conversion = Specifier::ID;                                       \
      break;
#include "seec/Trace/ScanFormatSpecifiers.def"
    default:
      return Result;
  }

  // Special case for parsing set specifier.
  if (Result.Conversion == Specifier::set) {
    auto const UCharValues = std::numeric_limits<unsigned char>::max() + 1;

    Result.SetLookup.reset(new bool[UCharValues]);
    for (unsigned i = 0; i < UCharValues; ++i)
      Result.SetLookup[i] = false;

    if (*++Remainder == '\0')
      return Result;

    // Make set a negation.
    if (*Remainder == '^') {
      Result.SetNegation = true;
      if (*++Remainder == '\0')
        return Result;
    }

    // Special case for including ']' in a set.
    if (*Remainder == ']') {
      Result.SetCharacters.push_back(']');

      auto const CharIdx = static_cast<unsigned char>(']');
      assert(CharIdx < UCharValues);
      Result.SetLookup[CharIdx] = true;

      if (*++Remainder == '\0')
        return Result;
    }

    // Add all remaining characters to the set (until ']' is found).
    while (*Remainder != ']') {
      Result.SetCharacters.push_back(*Remainder);

      auto const CharIdx = static_cast<unsigned char>(*Remainder);
      assert(CharIdx < UCharValues);
      Result.SetLookup[CharIdx] = true;

      if (*++Remainder == '\0')
        return Result;
    }

    if (Result.SetNegation) {
      for (unsigned i = 0; i < UCharValues; ++i)
        Result.SetLookup[i] = !Result.SetLookup[i];
    }
  }

  // Set the end of the parsed region.
  Result.End = ++Remainder;

  return Result;
}

} // namespace trace (in seec)

} // namespace seec
<|endoftext|>


<commit_before><commit_msg>amdgpu/addrlib: force all zero tile info for linear general.<commit_after><|endoftext|>


<commit_before>//===-- R600InstrInfo.cpp - TODO: Add brief description -------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// TODO: Add full description
//
//===----------------------------------------------------------------------===//

#include "R600InstrInfo.h"
#include "AMDGPUTargetMachine.h"
#include "R600RegisterInfo.h"

using namespace llvm;

R600InstrInfo::R600InstrInfo(AMDGPUTargetMachine &tm)
  : AMDGPUInstrInfo(tm),
    RI(tm, *this),
    TM(tm)
  { }

const R600RegisterInfo &R600InstrInfo::getRegisterInfo() const
{
  return RI;
}

bool R600InstrInfo::isTrig(const MachineInstr &MI) const
{
  return get(MI.getOpcode()).TSFlags & R600_InstFlag::TRIG;
}

void
R600InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
                           MachineBasicBlock::iterator MI, DebugLoc DL,
                           unsigned DestReg, unsigned SrcReg,
                           bool KillSrc) const
{
  if (!TargetRegisterInfo::isVirtualRegister(SrcReg)
      && AMDIL::GPRI32RegClass.contains(SrcReg)) {
    SrcReg = AMDIL::T0_X;
  }
  BuildMI(MBB, MI, DL, get(AMDIL::MOV), DestReg)
    .addReg(SrcReg, getKillRegState(KillSrc));
}

unsigned R600InstrInfo::getISAOpcode(unsigned opcode) const
{
  switch (opcode) {
    default: return AMDGPUInstrInfo::getISAOpcode(opcode);
    case AMDIL::CUSTOM_ADD_i32:
      return AMDIL::ADD_INT;
    case AMDIL::CUSTOM_XOR_i32:
      return AMDIL::XOR_INT;
    case AMDIL::MOVE_f32:
    case AMDIL::MOVE_i32:
      return AMDIL::MOV;
    case AMDIL::SHR_i32:
      return getLSHRop();
  }
}

unsigned R600InstrInfo::getLSHRop() const
{
  unsigned gen = TM.getSubtarget<AMDILSubtarget>().device()->getGeneration();
  if (gen < AMDILDeviceInfo::HD5XXX) {
    return AMDIL::LSHR_r600;
  } else {
    return AMDIL::LSHR_eg;
  }
}

unsigned R600InstrInfo::getMULHI_UINT() const
{
  unsigned gen = TM.getSubtarget<AMDILSubtarget>().device()->getGeneration();

  if (gen < AMDILDeviceInfo::HD5XXX) {
    return AMDIL::MULHI_UINT_r600;
  } else {
    return AMDIL::MULHI_UINT_eg;
  }
}

unsigned R600InstrInfo::getMULLO_UINT() const
{
  unsigned gen = TM.getSubtarget<AMDILSubtarget>().device()->getGeneration();

  if (gen < AMDILDeviceInfo::HD5XXX) {
    return AMDIL::MULLO_UINT_r600;
  } else {
    return AMDIL::MULLO_UINT_eg;
  }
}

unsigned R600InstrInfo::getRECIP_UINT() const
{
  const AMDILDevice * dev = TM.getSubtarget<AMDILSubtarget>().device();

  if (dev->getGeneration() < AMDILDeviceInfo::HD5XXX) {
    return AMDIL::RECIP_UINT_r600;
  } else if (dev->getDeviceFlag() != OCL_DEVICE_CAYMAN) {
    return AMDIL::RECIP_UINT_eg;
  } else {
    return AMDIL::RECIP_UINT_cm;
  }
}
<commit_msg>r600g/llvm: Remove debugging hack from R600InstrInfo::copyPhysReg()<commit_after>//===-- R600InstrInfo.cpp - TODO: Add brief description -------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// TODO: Add full description
//
//===----------------------------------------------------------------------===//

#include "R600InstrInfo.h"
#include "AMDGPUTargetMachine.h"
#include "R600RegisterInfo.h"

using namespace llvm;

R600InstrInfo::R600InstrInfo(AMDGPUTargetMachine &tm)
  : AMDGPUInstrInfo(tm),
    RI(tm, *this),
    TM(tm)
  { }

const R600RegisterInfo &R600InstrInfo::getRegisterInfo() const
{
  return RI;
}

bool R600InstrInfo::isTrig(const MachineInstr &MI) const
{
  return get(MI.getOpcode()).TSFlags & R600_InstFlag::TRIG;
}

void
R600InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
                           MachineBasicBlock::iterator MI, DebugLoc DL,
                           unsigned DestReg, unsigned SrcReg,
                           bool KillSrc) const
{
  BuildMI(MBB, MI, DL, get(AMDIL::MOV), DestReg)
    .addReg(SrcReg, getKillRegState(KillSrc));
}

unsigned R600InstrInfo::getISAOpcode(unsigned opcode) const
{
  switch (opcode) {
    default: return AMDGPUInstrInfo::getISAOpcode(opcode);
    case AMDIL::CUSTOM_ADD_i32:
      return AMDIL::ADD_INT;
    case AMDIL::CUSTOM_XOR_i32:
      return AMDIL::XOR_INT;
    case AMDIL::MOVE_f32:
    case AMDIL::MOVE_i32:
      return AMDIL::MOV;
    case AMDIL::SHR_i32:
      return getLSHRop();
  }
}

unsigned R600InstrInfo::getLSHRop() const
{
  unsigned gen = TM.getSubtarget<AMDILSubtarget>().device()->getGeneration();
  if (gen < AMDILDeviceInfo::HD5XXX) {
    return AMDIL::LSHR_r600;
  } else {
    return AMDIL::LSHR_eg;
  }
}

unsigned R600InstrInfo::getMULHI_UINT() const
{
  unsigned gen = TM.getSubtarget<AMDILSubtarget>().device()->getGeneration();

  if (gen < AMDILDeviceInfo::HD5XXX) {
    return AMDIL::MULHI_UINT_r600;
  } else {
    return AMDIL::MULHI_UINT_eg;
  }
}

unsigned R600InstrInfo::getMULLO_UINT() const
{
  unsigned gen = TM.getSubtarget<AMDILSubtarget>().device()->getGeneration();

  if (gen < AMDILDeviceInfo::HD5XXX) {
    return AMDIL::MULLO_UINT_r600;
  } else {
    return AMDIL::MULLO_UINT_eg;
  }
}

unsigned R600InstrInfo::getRECIP_UINT() const
{
  const AMDILDevice * dev = TM.getSubtarget<AMDILSubtarget>().device();

  if (dev->getGeneration() < AMDILDeviceInfo::HD5XXX) {
    return AMDIL::RECIP_UINT_r600;
  } else if (dev->getDeviceFlag() != OCL_DEVICE_CAYMAN) {
    return AMDIL::RECIP_UINT_eg;
  } else {
    return AMDIL::RECIP_UINT_cm;
  }
}
<|endoftext|>


<commit_before>//===-- Internalize.cpp - Mark functions internal -------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass loops over all of the functions in the input module, looking for a
// main function.  If a main function is found, all other functions and all
// global variables with initializers are marked as internal.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "internalize"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Pass.h"
#include "llvm/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/Statistic.h"
#include <fstream>
#include <set>
using namespace llvm;

STATISTIC(NumAliases  , "Number of aliases internalized");
STATISTIC(NumFunctions, "Number of functions internalized");
STATISTIC(NumGlobals  , "Number of global vars internalized");

// APIFile - A file which contains a list of symbols that should not be marked
// external.
static cl::opt<std::string>
APIFile("internalize-public-api-file", cl::value_desc("filename"),
        cl::desc("A file containing list of symbol names to preserve"));

// APIList - A list of symbols that should not be marked internal.
static cl::list<std::string>
APIList("internalize-public-api-list", cl::value_desc("list"),
        cl::desc("A list of symbol names to preserve"),
        cl::CommaSeparated);

namespace {
  class InternalizePass : public ModulePass {
    std::set<std::string> ExternalNames;
    /// If no api symbols were specified and a main function is defined,
    /// assume the main function is the only API
    bool AllButMain;
  public:
    static char ID; // Pass identification, replacement for typeid
    explicit InternalizePass(bool AllButMain = true);
    explicit InternalizePass(const std::vector <const char *>& exportList);
    void LoadFile(const char *Filename);
    virtual bool runOnModule(Module &M);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesCFG();
      AU.addPreserved<CallGraph>();
    }
  };
} // end anonymous namespace

char InternalizePass::ID = 0;
INITIALIZE_PASS(InternalizePass, "internalize",
                "Internalize Global Symbols", false, false)

InternalizePass::InternalizePass(bool AllButMain)
  : ModulePass(ID), AllButMain(AllButMain){
  initializeInternalizePassPass(*PassRegistry::getPassRegistry());
  if (!APIFile.empty())           // If a filename is specified, use it.
    LoadFile(APIFile.c_str());
  if (!APIList.empty())           // If a list is specified, use it as well.
    ExternalNames.insert(APIList.begin(), APIList.end());
}

InternalizePass::InternalizePass(const std::vector<const char *>&exportList)
  : ModulePass(ID), AllButMain(false){
  initializeInternalizePassPass(*PassRegistry::getPassRegistry());
  for(std::vector<const char *>::const_iterator itr = exportList.begin();
        itr != exportList.end(); itr++) {
    ExternalNames.insert(*itr);
  }
}

void InternalizePass::LoadFile(const char *Filename) {
  // Load the APIFile...
  std::ifstream In(Filename);
  if (!In.good()) {
    errs() << "WARNING: Internalize couldn't load file '" << Filename
         << "'! Continuing as if it's empty.\n";
    return; // Just continue as if the file were empty
  }
  while (In) {
    std::string Symbol;
    In >> Symbol;
    if (!Symbol.empty())
      ExternalNames.insert(Symbol);
  }
}

bool InternalizePass::runOnModule(Module &M) {
  CallGraph *CG = getAnalysisIfAvailable<CallGraph>();
  CallGraphNode *ExternalNode = CG ? CG->getExternalCallingNode() : 0;

  if (ExternalNames.empty()) {
    // Return if we're not in 'all but main' mode and have no external api
    if (!AllButMain)
      return false;
    // If no list or file of symbols was specified, check to see if there is a
    // "main" symbol defined in the module.  If so, use it, otherwise do not
    // internalize the module, it must be a library or something.
    //
    Function *MainFunc = M.getFunction("main");
    if (MainFunc == 0 || MainFunc->isDeclaration())
      return false;  // No main found, must be a library...

    // Preserve main, internalize all else.
    ExternalNames.insert(MainFunc->getName());
  }

  bool Changed = false;

  // Mark all functions not in the api as internal.
  // FIXME: maybe use private linkage?
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isDeclaration() &&         // Function must be defined here
        // Available externally is really just a "declaration with a body".
        !I->hasAvailableExternallyLinkage() &&
        !I->hasLocalLinkage() &&  // Can't already have internal linkage
        !ExternalNames.count(I->getName())) {// Not marked to keep external?
      I->setLinkage(GlobalValue::InternalLinkage);
      // Remove a callgraph edge from the external node to this function.
      if (ExternalNode) ExternalNode->removeOneAbstractEdgeTo((*CG)[I]);
      Changed = true;
      ++NumFunctions;
      DEBUG(dbgs() << "Internalizing func " << I->getName() << "\n");
    }

  // Never internalize the llvm.used symbol.  It is used to implement
  // attribute((used)).
  // FIXME: Shouldn't this just filter on llvm.metadata section??
  ExternalNames.insert("llvm.used");
  ExternalNames.insert("llvm.compiler.used");

  // Never internalize anchors used by the machine module info, else the info
  // won't find them.  (see MachineModuleInfo.)
  ExternalNames.insert("llvm.global_ctors");
  ExternalNames.insert("llvm.global_dtors");
  ExternalNames.insert("llvm.global.annotations");

  // Mark all global variables with initializers that are not in the api as
  // internal as well.
  // FIXME: maybe use private linkage?
  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
       I != E; ++I)
    if (!I->isDeclaration() && !I->hasLocalLinkage() &&
        // Available externally is really just a "declaration with a body".
        !I->hasAvailableExternallyLinkage() &&
        !ExternalNames.count(I->getName())) {
      I->setLinkage(GlobalValue::InternalLinkage);
      Changed = true;
      ++NumGlobals;
      DEBUG(dbgs() << "Internalized gvar " << I->getName() << "\n");
    }

  // Mark all aliases that are not in the api as internal as well.
  for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end();
       I != E; ++I)
    if (!I->isDeclaration() && !I->hasInternalLinkage() &&
        // Available externally is really just a "declaration with a body".
        !I->hasAvailableExternallyLinkage() &&
        !ExternalNames.count(I->getName())) {
      I->setLinkage(GlobalValue::InternalLinkage);
      Changed = true;
      ++NumAliases;
      DEBUG(dbgs() << "Internalized alias " << I->getName() << "\n");
    }

  return Changed;
}

ModulePass *llvm::createInternalizePass(bool AllButMain) {
  return new InternalizePass(AllButMain);
}

ModulePass *llvm::createInternalizePass(const std::vector <const char *> &el) {
  return new InternalizePass(el);
}
<commit_msg>Code-gen may inject code into the IR before it emits the ASM. The linker obviously cannot know that this code is present, let alone used. So prevent the internalize pass from internalizing those global values which code-gen may insert.<commit_after>//===-- Internalize.cpp - Mark functions internal -------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass loops over all of the functions in the input module, looking for a
// main function.  If a main function is found, all other functions and all
// global variables with initializers are marked as internal.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "internalize"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Pass.h"
#include "llvm/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/Statistic.h"
#include <fstream>
#include <set>
using namespace llvm;

STATISTIC(NumAliases  , "Number of aliases internalized");
STATISTIC(NumFunctions, "Number of functions internalized");
STATISTIC(NumGlobals  , "Number of global vars internalized");

// APIFile - A file which contains a list of symbols that should not be marked
// external.
static cl::opt<std::string>
APIFile("internalize-public-api-file", cl::value_desc("filename"),
        cl::desc("A file containing list of symbol names to preserve"));

// APIList - A list of symbols that should not be marked internal.
static cl::list<std::string>
APIList("internalize-public-api-list", cl::value_desc("list"),
        cl::desc("A list of symbol names to preserve"),
        cl::CommaSeparated);

namespace {
  class InternalizePass : public ModulePass {
    std::set<std::string> ExternalNames;
    /// If no api symbols were specified and a main function is defined,
    /// assume the main function is the only API
    bool AllButMain;
  public:
    static char ID; // Pass identification, replacement for typeid
    explicit InternalizePass(bool AllButMain = true);
    explicit InternalizePass(const std::vector <const char *>& exportList);
    void LoadFile(const char *Filename);
    virtual bool runOnModule(Module &M);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesCFG();
      AU.addPreserved<CallGraph>();
    }
  };
} // end anonymous namespace

char InternalizePass::ID = 0;
INITIALIZE_PASS(InternalizePass, "internalize",
                "Internalize Global Symbols", false, false)

InternalizePass::InternalizePass(bool AllButMain)
  : ModulePass(ID), AllButMain(AllButMain){
  initializeInternalizePassPass(*PassRegistry::getPassRegistry());
  if (!APIFile.empty())           // If a filename is specified, use it.
    LoadFile(APIFile.c_str());
  if (!APIList.empty())           // If a list is specified, use it as well.
    ExternalNames.insert(APIList.begin(), APIList.end());
}

InternalizePass::InternalizePass(const std::vector<const char *>&exportList)
  : ModulePass(ID), AllButMain(false){
  initializeInternalizePassPass(*PassRegistry::getPassRegistry());
  for(std::vector<const char *>::const_iterator itr = exportList.begin();
        itr != exportList.end(); itr++) {
    ExternalNames.insert(*itr);
  }
}

void InternalizePass::LoadFile(const char *Filename) {
  // Load the APIFile...
  std::ifstream In(Filename);
  if (!In.good()) {
    errs() << "WARNING: Internalize couldn't load file '" << Filename
         << "'! Continuing as if it's empty.\n";
    return; // Just continue as if the file were empty
  }
  while (In) {
    std::string Symbol;
    In >> Symbol;
    if (!Symbol.empty())
      ExternalNames.insert(Symbol);
  }
}

bool InternalizePass::runOnModule(Module &M) {
  CallGraph *CG = getAnalysisIfAvailable<CallGraph>();
  CallGraphNode *ExternalNode = CG ? CG->getExternalCallingNode() : 0;

  if (ExternalNames.empty()) {
    // Return if we're not in 'all but main' mode and have no external api
    if (!AllButMain)
      return false;
    // If no list or file of symbols was specified, check to see if there is a
    // "main" symbol defined in the module.  If so, use it, otherwise do not
    // internalize the module, it must be a library or something.
    //
    Function *MainFunc = M.getFunction("main");
    if (MainFunc == 0 || MainFunc->isDeclaration())
      return false;  // No main found, must be a library...

    // Preserve main, internalize all else.
    ExternalNames.insert(MainFunc->getName());
  }

  bool Changed = false;

  // Never internalize functions which code-gen might insert.
  ExternalNames.insert("__stack_chk_fail");

  // Mark all functions not in the api as internal.
  // FIXME: maybe use private linkage?
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isDeclaration() &&         // Function must be defined here
        // Available externally is really just a "declaration with a body".
        !I->hasAvailableExternallyLinkage() &&
        !I->hasLocalLinkage() &&  // Can't already have internal linkage
        !ExternalNames.count(I->getName())) {// Not marked to keep external?
      I->setLinkage(GlobalValue::InternalLinkage);
      // Remove a callgraph edge from the external node to this function.
      if (ExternalNode) ExternalNode->removeOneAbstractEdgeTo((*CG)[I]);
      Changed = true;
      ++NumFunctions;
      DEBUG(dbgs() << "Internalizing func " << I->getName() << "\n");
    }

  // Never internalize the llvm.used symbol.  It is used to implement
  // attribute((used)).
  // FIXME: Shouldn't this just filter on llvm.metadata section??
  ExternalNames.insert("llvm.used");
  ExternalNames.insert("llvm.compiler.used");

  // Never internalize anchors used by the machine module info, else the info
  // won't find them.  (see MachineModuleInfo.)
  ExternalNames.insert("llvm.global_ctors");
  ExternalNames.insert("llvm.global_dtors");
  ExternalNames.insert("llvm.global.annotations");

  // Never internalize symbols code-gen inserts.
  ExternalNames.insert("__stack_chk_guard");

  // Mark all global variables with initializers that are not in the api as
  // internal as well.
  // FIXME: maybe use private linkage?
  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
       I != E; ++I)
    if (!I->isDeclaration() && !I->hasLocalLinkage() &&
        // Available externally is really just a "declaration with a body".
        !I->hasAvailableExternallyLinkage() &&
        !ExternalNames.count(I->getName())) {
      I->setLinkage(GlobalValue::InternalLinkage);
      Changed = true;
      ++NumGlobals;
      DEBUG(dbgs() << "Internalized gvar " << I->getName() << "\n");
    }

  // Mark all aliases that are not in the api as internal as well.
  for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end();
       I != E; ++I)
    if (!I->isDeclaration() && !I->hasInternalLinkage() &&
        // Available externally is really just a "declaration with a body".
        !I->hasAvailableExternallyLinkage() &&
        !ExternalNames.count(I->getName())) {
      I->setLinkage(GlobalValue::InternalLinkage);
      Changed = true;
      ++NumAliases;
      DEBUG(dbgs() << "Internalized alias " << I->getName() << "\n");
    }

  return Changed;
}

ModulePass *llvm::createInternalizePass(bool AllButMain) {
  return new InternalizePass(AllButMain);
}

ModulePass *llvm::createInternalizePass(const std::vector <const char *> &el) {
  return new InternalizePass(el);
}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*! @file
	@brief  NES Emulator クラス
	@author 平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "main.hpp"
#include "utils/i_scene.hpp"
#include "utils/director.hpp"
#include "widgets/widget.hpp"
#include "widgets/widget_frame.hpp"
#include "widgets/widget_terminal.hpp"
#include "widgets/widget_filer.hpp"
#include "gl_fw/gltexfb.hpp"
#include "snd_io/pcm.hpp"

extern "C" {
	#include "nes.h"
	#include "nesinput.h"
	extern const rgb_t* get_palette();
};

namespace app {

	class nesemu : public utils::i_scene {

		utils::director<core>&	director_;

		gui::widget_frame*		terminal_frame_;
		gui::widget_terminal*	terminal_core_;

		gui::widget_filer*		filer_;

		gl::texfb			texfb_;

		static const int nes_width_  = 256;
		static const int nes_height_ = 240;

		nes_t*	nes_;

		uint8_t		sound_[1024];
		al::audio	audio_;

		uint8_t	fb_[nes_width_ * nes_height_ * 4];

		nesinput_t	inp_[2];

		bool	rom_active_;

		void pad_()
		{
	   		gl::core& core = gl::core::get_instance();

			const gl::device& dev = core.get_device();

			inp_[0].data = 0;
			inp_[1].data = 0;

			// A
			if(dev.get_level(gl::device::key::Z)) {
				inp_[0].data |= INP_PAD_A;
			}
			if(dev.get_level(gl::device::key::GAME_0)) {
				inp_[0].data |= INP_PAD_A;
			}

			// B
			if(dev.get_level(gl::device::key::X)) {
				inp_[0].data |= INP_PAD_B;
			}
			if(dev.get_level(gl::device::key::GAME_1)) {
				inp_[0].data |= INP_PAD_B;
			}

			// SELECT
			if(dev.get_level(gl::device::key::_1)) {
				inp_[0].data |= INP_PAD_SELECT;
			}
			if(dev.get_level(gl::device::key::GAME_2)) {
				inp_[0].data |= INP_PAD_SELECT;
			}
			// START
			if(dev.get_level(gl::device::key::_2)) {
				inp_[0].data |= INP_PAD_START;
			}
			if(dev.get_level(gl::device::key::GAME_3)) {
				inp_[0].data |= INP_PAD_START;
			}

			if(dev.get_level(gl::device::key::LEFT)) {
   		 		inp_[0].data |= INP_PAD_LEFT;
			}
			if(dev.get_level(gl::device::key::GAME_LEFT)) {
   		 		inp_[0].data |= INP_PAD_LEFT;
			}
			if(dev.get_level(gl::device::key::RIGHT)) {
   		 		inp_[0].data |= INP_PAD_RIGHT;
			}
			if(dev.get_level(gl::device::key::GAME_RIGHT)) {
   		 		inp_[0].data |= INP_PAD_RIGHT;
			}
			if(dev.get_level(gl::device::key::UP)) {
   		 		inp_[0].data |= INP_PAD_UP;
			}
			if(dev.get_level(gl::device::key::GAME_UP)) {
   		 		inp_[0].data |= INP_PAD_RIGHT;
			}
			if(dev.get_level(gl::device::key::DOWN)) {
   		 		inp_[0].data |= INP_PAD_DOWN;
			}
			if(dev.get_level(gl::device::key::GAME_DOWN)) {
   		 		inp_[0].data |= INP_PAD_DOWN;
			}
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		nesemu(utils::director<core>& d) : director_(d),
			terminal_frame_(nullptr), terminal_core_(nullptr),
			nes_(nullptr), rom_active_(false)
		{ }

		//-----------------------------------------------------------------//
		/*!
			@brief  デストラクター
		*/
		//-----------------------------------------------------------------//
		virtual ~nesemu() { }

		//-----------------------------------------------------------------//
		/*!
			@brief  初期化
		*/
		//-----------------------------------------------------------------//
		void initialize()
		{
	   		gl::core& core = gl::core::get_instance();

			using namespace gui;

			widget_director& wd = director_.at().widget_director_;
			widget::param wp(vtx::irect(10, 10, 200, 200));
			widget_filer::param wp_(core.get_current_path(), "", true);
			wp_.select_file_func_ = [this](const std::string& fn) {
				nes_insertcart(fn.c_str(), nes_);
				rom_active_ = true;
			};
			filer_ = wd.add_widget<widget_filer>(wp, wp_);
			filer_->enable(false);

			texfb_.initialize(nes_width_, nes_height_, 32);

			nes_ = nes_create();

			// regist input
			inp_[0].type = INP_JOYPAD0;
			inp_[0].data = 0;
			input_register(&inp_[0]);
			inp_[1].type = INP_JOYPAD1;
			inp_[1].data = 0;
			input_register(&inp_[1]);

			audio_ = al::create_audio(al::audio_format::PCM8_MONO);
			audio_->create(44100, 44100 / 60);

//			auto path = core.get_current_path();

//			path += "/GALAXIAN.NES";
//			path += "/Zombie.nes";
//			path += "/DRAGONQ1.NES";
//			path += "/DRAGONW2.NES";
//			path += "/SOLSTICE.NES";
//			path += "/GRADIUS.NES";

//			nes_insertcart(path.c_str(), nes_);

			// プリファレンスの取得
			sys::preference& pre = director_.at().preference_;
			if(filer_) {
				filer_->load(pre);
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  アップデート
		*/
		//-----------------------------------------------------------------//
		void update()
		{
	   		gl::core& core = gl::core::get_instance();
			const gl::device& dev = core.get_device();

			if(dev.get_positive(gl::device::key::ENTER)) {
				filer_->enable(!filer_->get_enable());
			}

        	gui::widget_director& wd = director_.at().widget_director_;

			if(nes_ != nullptr && rom_active_) {
				pad_();

				nes_emulate(1);

				// copy sound
				{
					int len = 44100 / 60;
					apu_process(sound_, len);
					al::sound& sound = director_.at().sound_;
					for(int i = 0; i < len; ++i) {
						al::pcm8_m w(sound_[i]);
						audio_->put(i, w);
					}
					sound.queue_audio(audio_);
				}

				// copy video
				bitmap_t* v = nes_->vidbuf;
				const rgb_t* lut = get_palette();
				if(v != nullptr && lut != nullptr) {
					for(int h = 0; h < nes_height_; ++h) {
						const uint8_t* src = &v->data[h * v->pitch];
						uint8_t* dst = &fb_[h * nes_width_ * 4];
						for(int w = 0; w < nes_width_; ++w) {
							auto idx = *src++;
							idx &= 63;
							*dst++ = lut[idx].r;  // R
							*dst++ = lut[idx].g;  // G
							*dst++ = lut[idx].b;  // B
							*dst++ = 255;  // alpha
						}
					}
					texfb_.rendering(gl::texfb::image::RGBA, (const char*)&fb_[0]);
				}

			}

			texfb_.flip();

			wd.update();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  レンダリング
		*/
		//-----------------------------------------------------------------//
		void render()
		{
	   		gl::core& core = gl::core::get_instance();

			const vtx::spos& siz = core.get_rect().size;

			texfb_.setup_matrix(0, 0, siz.x, siz.y);

			float scale = 1.0f;
			float ofsx = 0.0f;
			float ofsy = 0.0f;
			if(siz.x < siz.y) {
				scale = static_cast<float>(siz.x) / static_cast<float>(nes_width_);
				float h = static_cast<float>(nes_height_);
				ofsy = (static_cast<float>(siz.y) - h * scale) * 0.5f;
			} else {
				scale = static_cast<float>(siz.y) / static_cast<float>(nes_height_);
				float w = static_cast<float>(nes_width_);
				ofsx = (static_cast<float>(siz.x) - w * scale) * 0.5f;
			}
			gl::glTranslate(ofsx, ofsy);
			gl::glScale(scale);
			texfb_.draw();

			director_.at().widget_director_.service();
			director_.at().widget_director_.render();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  廃棄
		*/
		//-----------------------------------------------------------------//
		void destroy()
		{
			nes_destroy(nes_);

			sys::preference& pre = director_.at().preference_;
			if(filer_) {
				filer_->save(pre);
			}
		}

	};

}
<commit_msg>update sound buffer<commit_after>#pragma once
//=====================================================================//
/*! @file
	@brief  NES Emulator クラス
	@author 平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include "main.hpp"
#include "utils/i_scene.hpp"
#include "utils/director.hpp"
#include "widgets/widget.hpp"
#include "widgets/widget_frame.hpp"
#include "widgets/widget_terminal.hpp"
#include "widgets/widget_filer.hpp"
#include "gl_fw/gltexfb.hpp"
#include "snd_io/pcm.hpp"

extern "C" {
	#include "nes.h"
	#include "nesinput.h"
	extern const rgb_t* get_palette();
};

namespace app {

	class nesemu : public utils::i_scene {

		utils::director<core>&	director_;

		gui::widget_frame*		terminal_frame_;
		gui::widget_terminal*	terminal_core_;

		gui::widget_filer*		filer_;

		gl::texfb			texfb_;

		static const int nes_width_  = 256;
		static const int nes_height_ = 240;
		static const int audio_len_ = 44100 / 60 * 2;

		nes_t*	nes_;

		uint8_t		sound_[audio_len_];
		al::audio	audio_;
		uint32_t	frame_;

		uint8_t	fb_[nes_width_ * nes_height_ * 4];

		nesinput_t	inp_[2];

		bool	rom_active_;

		void pad_()
		{
	   		gl::core& core = gl::core::get_instance();

			const gl::device& dev = core.get_device();

			inp_[0].data = 0;
			inp_[1].data = 0;

			// A
			if(dev.get_level(gl::device::key::Z)) {
				inp_[0].data |= INP_PAD_A;
			}
			if(dev.get_level(gl::device::key::GAME_0)) {
				inp_[0].data |= INP_PAD_A;
			}

			// B
			if(dev.get_level(gl::device::key::X)) {
				inp_[0].data |= INP_PAD_B;
			}
			if(dev.get_level(gl::device::key::GAME_1)) {
				inp_[0].data |= INP_PAD_B;
			}

			// SELECT
			if(dev.get_level(gl::device::key::_1)) {
				inp_[0].data |= INP_PAD_SELECT;
			}
			if(dev.get_level(gl::device::key::GAME_2)) {
				inp_[0].data |= INP_PAD_SELECT;
			}
			// START
			if(dev.get_level(gl::device::key::_2)) {
				inp_[0].data |= INP_PAD_START;
			}
			if(dev.get_level(gl::device::key::GAME_3)) {
				inp_[0].data |= INP_PAD_START;
			}

			if(dev.get_level(gl::device::key::LEFT)) {
   		 		inp_[0].data |= INP_PAD_LEFT;
			}
			if(dev.get_level(gl::device::key::GAME_LEFT)) {
   		 		inp_[0].data |= INP_PAD_LEFT;
			}
			if(dev.get_level(gl::device::key::RIGHT)) {
   		 		inp_[0].data |= INP_PAD_RIGHT;
			}
			if(dev.get_level(gl::device::key::GAME_RIGHT)) {
   		 		inp_[0].data |= INP_PAD_RIGHT;
			}
			if(dev.get_level(gl::device::key::UP)) {
   		 		inp_[0].data |= INP_PAD_UP;
			}
			if(dev.get_level(gl::device::key::GAME_UP)) {
   		 		inp_[0].data |= INP_PAD_RIGHT;
			}
			if(dev.get_level(gl::device::key::DOWN)) {
   		 		inp_[0].data |= INP_PAD_DOWN;
			}
			if(dev.get_level(gl::device::key::GAME_DOWN)) {
   		 		inp_[0].data |= INP_PAD_DOWN;
			}
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		nesemu(utils::director<core>& d) : director_(d),
			terminal_frame_(nullptr), terminal_core_(nullptr),
			nes_(nullptr), frame_(0), rom_active_(false)
		{ }

		//-----------------------------------------------------------------//
		/*!
			@brief  デストラクター
		*/
		//-----------------------------------------------------------------//
		virtual ~nesemu() { }

		//-----------------------------------------------------------------//
		/*!
			@brief  初期化
		*/
		//-----------------------------------------------------------------//
		void initialize()
		{
	   		gl::core& core = gl::core::get_instance();

			using namespace gui;

			widget_director& wd = director_.at().widget_director_;
			widget::param wp(vtx::irect(10, 10, 200, 200));
			widget_filer::param wp_(core.get_current_path(), "", true);
			wp_.select_file_func_ = [this](const std::string& fn) {
				nes_insertcart(fn.c_str(), nes_);
				rom_active_ = true;
			};
			filer_ = wd.add_widget<widget_filer>(wp, wp_);
			filer_->enable(false);

			texfb_.initialize(nes_width_, nes_height_, 32);

			nes_ = nes_create();

			// regist input
			inp_[0].type = INP_JOYPAD0;
			inp_[0].data = 0;
			input_register(&inp_[0]);
			inp_[1].type = INP_JOYPAD1;
			inp_[1].data = 0;
			input_register(&inp_[1]);

			audio_ = al::create_audio(al::audio_format::PCM8_MONO);
			audio_->create(44100, audio_len_);

//			auto path = core.get_current_path();

//			path += "/GALAXIAN.NES";
//			path += "/Zombie.nes";
//			path += "/DRAGONQ1.NES";
//			path += "/DRAGONW2.NES";
//			path += "/SOLSTICE.NES";
//			path += "/GRADIUS.NES";

//			nes_insertcart(path.c_str(), nes_);

			// プリファレンスの取得
			sys::preference& pre = director_.at().preference_;
			if(filer_) {
				filer_->load(pre);
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  アップデート
		*/
		//-----------------------------------------------------------------//
		void update()
		{
	   		gl::core& core = gl::core::get_instance();
			const gl::device& dev = core.get_device();

			if(dev.get_positive(gl::device::key::ENTER)) {
				filer_->enable(!filer_->get_enable());
			}

        	gui::widget_director& wd = director_.at().widget_director_;

			if(nes_ != nullptr && rom_active_) {
				pad_();

				nes_emulate(1);

				// copy sound
				if(frame_ & 1) {
					apu_process(sound_, audio_len_);
					al::sound& sound = director_.at().sound_;
					for(int i = 0; i < audio_len_; ++i) {
						al::pcm8_m w(sound_[i]);
						audio_->put(i, w);
					}
					sound.queue_audio(audio_);
				}

				// copy video
				bitmap_t* v = nes_->vidbuf;
				const rgb_t* lut = get_palette();
				if(v != nullptr && lut != nullptr) {
					for(int h = 0; h < nes_height_; ++h) {
						const uint8_t* src = &v->data[h * v->pitch];
						uint8_t* dst = &fb_[h * nes_width_ * 4];
						for(int w = 0; w < nes_width_; ++w) {
							auto idx = *src++;
							idx &= 63;
							*dst++ = lut[idx].r;  // R
							*dst++ = lut[idx].g;  // G
							*dst++ = lut[idx].b;  // B
							*dst++ = 255;  // alpha
						}
					}
					texfb_.rendering(gl::texfb::image::RGBA, (const char*)&fb_[0]);
				}

			}

			++frame_;

			texfb_.flip();

			wd.update();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  レンダリング
		*/
		//-----------------------------------------------------------------//
		void render()
		{
	   		gl::core& core = gl::core::get_instance();

			const vtx::spos& siz = core.get_rect().size;

			texfb_.setup_matrix(0, 0, siz.x, siz.y);

			float scale = 1.0f;
			float ofsx = 0.0f;
			float ofsy = 0.0f;
			if(siz.x < siz.y) {
				scale = static_cast<float>(siz.x) / static_cast<float>(nes_width_);
				float h = static_cast<float>(nes_height_);
				ofsy = (static_cast<float>(siz.y) - h * scale) * 0.5f;
			} else {
				scale = static_cast<float>(siz.y) / static_cast<float>(nes_height_);
				float w = static_cast<float>(nes_width_);
				ofsx = (static_cast<float>(siz.x) - w * scale) * 0.5f;
			}
			gl::glTranslate(ofsx, ofsy);
			gl::glScale(scale);
			texfb_.draw();

			director_.at().widget_director_.service();
			director_.at().widget_director_.render();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  廃棄
		*/
		//-----------------------------------------------------------------//
		void destroy()
		{
			nes_destroy(nes_);

			sys::preference& pre = director_.at().preference_;
			if(filer_) {
				filer_->save(pre);
			}
		}

	};

}
<|endoftext|>


<commit_before>
/*
    Copyright 2011 Aevum Software aevum @ aevumlab.com

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

    @author Victor Vicente de Carvalho victor.carvalho@aevumlab.com
    @author Ozires Bortolon de Faria ozires@aevumlab.com
*/

#include "VertexArray.hpp"

#include "gdx-cpp/Gdx.hpp"
#include "gdx-cpp/graphics/GL10.hpp"
#include "gdx-cpp/graphics/GL11.hpp"
#include "gdx-cpp/Application.hpp"

using namespace gdx_cpp::graphics::glutils;
using namespace gdx_cpp::graphics;
using namespace gdx_cpp;

void VertexArray::dispose () {
}

utils::float_buffer& VertexArray::getBuffer () {
    return buffer;
}

int VertexArray::getNumVertices () {
    return buffer.limit() * 4 / attributes.vertexSize;
}

int VertexArray::getNumMaxVertices () {
    return byteBuffer.capacity() / attributes.vertexSize;
}

void VertexArray::setVertices (const float* vertices, int offset, int count) {
    buffer.copy(vertices, count, offset);
    buffer.position(0);
}

void VertexArray::bind () {
    GL10& gl = *Gdx::gl10;
    int textureUnit = 0;
    int numAttributes = attributes.size();

    byteBuffer.limit(buffer.limit() * 4);

    for (int i = 0; i < numAttributes; i++) {
        VertexAttribute& attribute = attributes.get(i);

        switch (attribute.usage) {
        case VertexAttributes::Usage::Position:
            byteBuffer.position(attribute.offset);
            gl.glEnableClientState(GL11::GL_VERTEX_ARRAY);
            gl.glVertexPointer(attribute.numComponents, GL10::GL_FLOAT, attributes.vertexSize, ((float*) buffer) + attribute.offset);
            break;

        case VertexAttributes::Usage::Color:
        case VertexAttributes::Usage::ColorPacked:
        {
            int colorType = GL10::GL_FLOAT;
            if (attribute.usage == VertexAttributes::Usage::ColorPacked) colorType = GL11::GL_UNSIGNED_BYTE;
            byteBuffer.position(attribute.offset);
            gl.glEnableClientState(GL10::GL_COLOR_ARRAY);
            gl.glColorPointer(attribute.numComponents, colorType, attributes.vertexSize, ((float*) buffer) + attribute.offset);
            break;
        }
        case VertexAttributes::Usage::Normal:
            byteBuffer.position(attribute.offset);
            gl.glEnableClientState(GL10::GL_NORMAL_ARRAY);
            gl.glNormalPointer(GL10::GL_FLOAT, attributes.vertexSize, ((float*) buffer) + attribute.offset);
            break;

        case VertexAttributes::Usage::TextureCoordinates:
            gl.glClientActiveTexture(GL10::GL_TEXTURE0 + textureUnit);
            gl.glEnableClientState(GL10::GL_TEXTURE_COORD_ARRAY);
            byteBuffer.position(attribute.offset);
            gl.glTexCoordPointer(attribute.numComponents, GL10::GL_FLOAT, attributes.vertexSize, ((float*) buffer) + attribute.offset);
            textureUnit++;
            break;

        default:
            break;
            // throw new GdxRuntimeException("unkown vertex attribute type: " + attribute.usage);
        }
    }

    isBound = true;
}

void VertexArray::unbind () {
    GL10& gl = *Gdx::gl10;
    int textureUnit = 0;
    int numAttributes = attributes.size();

    for (int i = 0; i < numAttributes; i++) {

        VertexAttribute& attribute = attributes.get(i);
        switch (attribute.usage) {
        case VertexAttributes::Usage::Position:
            break; // no-op, we also need a position bound in gles
        case VertexAttributes::Usage::Color:
        case VertexAttributes::Usage::ColorPacked:
            gl.glDisableClientState(GL11::GL_COLOR_ARRAY);
            break;
        case VertexAttributes::Usage::Normal:
            gl.glDisableClientState(GL11::GL_NORMAL_ARRAY);
            break;
        case VertexAttributes::Usage::TextureCoordinates:
            gl.glClientActiveTexture(GL11::GL_TEXTURE0 + textureUnit);
            gl.glDisableClientState(GL11::GL_TEXTURE_COORD_ARRAY);
            textureUnit++;
            break;
        default:
            break;
            // throw new GdxRuntimeException("unkown vertex attribute type: " + attribute.usage);
        }
    }
    byteBuffer.position(0);
    isBound = false;
}

gdx_cpp::graphics::VertexAttributes& VertexArray::getAttributes () {
    return attributes;
}

VertexArray::VertexArray(int numVertices, const gdx_cpp::graphics::VertexAttributes& attributes)
:
attributes(attributes),
isBound(false)
, byteBuffer(this->attributes.vertexSize * numVertices)
{
    buffer = byteBuffer.convert<float>();
    buffer.flip();
    byteBuffer.flip();
}
<commit_msg>Fixed (back) the vertexarray rendering method. Should study more on this ;)<commit_after>
/*
    Copyright 2011 Aevum Software aevum @ aevumlab.com

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

    @author Victor Vicente de Carvalho victor.carvalho@aevumlab.com
    @author Ozires Bortolon de Faria ozires@aevumlab.com
*/

#include "VertexArray.hpp"

#include "gdx-cpp/Gdx.hpp"
#include "gdx-cpp/graphics/GL10.hpp"
#include "gdx-cpp/graphics/GL11.hpp"
#include "gdx-cpp/Application.hpp"

using namespace gdx_cpp::graphics::glutils;
using namespace gdx_cpp::graphics;
using namespace gdx_cpp;

void VertexArray::dispose () {
}

utils::float_buffer& VertexArray::getBuffer () {
    return buffer;
}

int VertexArray::getNumVertices () {
    return buffer.limit() * 4 / attributes.vertexSize;
}

int VertexArray::getNumMaxVertices () {
    return byteBuffer.capacity() / attributes.vertexSize;
}

void VertexArray::setVertices (const float* vertices, int offset, int count) {
    buffer.copy(vertices, count, offset);
    buffer.position(0);
}

void VertexArray::bind () {
    GL10& gl = *Gdx::gl10;
    int textureUnit = 0;
    int numAttributes = attributes.size();

    byteBuffer.limit(buffer.limit() * 4);

    for (int i = 0; i < numAttributes; i++) {
        VertexAttribute& attribute = attributes.get(i);

        switch (attribute.usage) {
        case VertexAttributes::Usage::Position:
            byteBuffer.position(attribute.offset);
            gl.glEnableClientState(GL11::GL_VERTEX_ARRAY);
            gl.glVertexPointer(attribute.numComponents, GL10::GL_FLOAT, attributes.vertexSize, (unsigned char*) byteBuffer + attribute.offset);
            break;

        case VertexAttributes::Usage::Color:
        case VertexAttributes::Usage::ColorPacked:
        {
            int colorType = GL10::GL_FLOAT;
            if (attribute.usage == VertexAttributes::Usage::ColorPacked) colorType = GL11::GL_UNSIGNED_BYTE;
            byteBuffer.position(attribute.offset);
            gl.glEnableClientState(GL10::GL_COLOR_ARRAY);
            gl.glColorPointer(attribute.numComponents, colorType, attributes.vertexSize, (unsigned char*) byteBuffer + attribute.offset);
            break;
        }
        case VertexAttributes::Usage::Normal:
            byteBuffer.position(attribute.offset);
            gl.glEnableClientState(GL10::GL_NORMAL_ARRAY);
            gl.glNormalPointer(GL10::GL_FLOAT, attributes.vertexSize, (unsigned char*) byteBuffer + attribute.offset);
            break;

        case VertexAttributes::Usage::TextureCoordinates:
            gl.glClientActiveTexture(GL10::GL_TEXTURE0 + textureUnit);
            gl.glEnableClientState(GL10::GL_TEXTURE_COORD_ARRAY);
            byteBuffer.position(attribute.offset);
            gl.glTexCoordPointer(attribute.numComponents, GL10::GL_FLOAT, attributes.vertexSize, (unsigned char*) byteBuffer + attribute.offset);
            textureUnit++;
            break;

        default:
            break;
            // throw new GdxRuntimeException("unkown vertex attribute type: " + attribute.usage);
        }
    }

    isBound = true;
}

void VertexArray::unbind () {
    GL10& gl = *Gdx::gl10;
    int textureUnit = 0;
    int numAttributes = attributes.size();

    for (int i = 0; i < numAttributes; i++) {

        VertexAttribute& attribute = attributes.get(i);
        switch (attribute.usage) {
        case VertexAttributes::Usage::Position:
            break; // no-op, we also need a position bound in gles
        case VertexAttributes::Usage::Color:
        case VertexAttributes::Usage::ColorPacked:
            gl.glDisableClientState(GL11::GL_COLOR_ARRAY);
            break;
        case VertexAttributes::Usage::Normal:
            gl.glDisableClientState(GL11::GL_NORMAL_ARRAY);
            break;
        case VertexAttributes::Usage::TextureCoordinates:
            gl.glClientActiveTexture(GL11::GL_TEXTURE0 + textureUnit);
            gl.glDisableClientState(GL11::GL_TEXTURE_COORD_ARRAY);
            textureUnit++;
            break;
        default:
            break;
            // throw new GdxRuntimeException("unkown vertex attribute type: " + attribute.usage);
        }
    }
    byteBuffer.position(0);
    isBound = false;
}

gdx_cpp::graphics::VertexAttributes& VertexArray::getAttributes () {
    return attributes;
}

VertexArray::VertexArray(int numVertices, const gdx_cpp::graphics::VertexAttributes& attributes)
:
attributes(attributes),
isBound(false)
, byteBuffer(this->attributes.vertexSize * numVertices)
{
    buffer = byteBuffer.convert<float>();
    buffer.flip();
    byteBuffer.flip();
}
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkMergePoints.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1996 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkMergePoints.h"

// Description:
// Merge points together if they are exactly coincident. Return a list
// that maps unmerged point ids into new point ids. User is responsible
// for freeing list (use delete []). Make sure you've provided a dataset
// before invoking this method.
int *vtkMergePoints::MergePoints()
{
  int ptId, i, j;
  int numPts;
  int *index;
  int newPtId;
  float *pt, *p;
  int ijk[3];
  int cno;
  vtkIdList *ptIds;

  vtkDebugMacro(<<"Merging points");

  if ( this->DataSet == NULL ||
  (numPts=this->DataSet->GetNumberOfPoints()) < 1 ) return NULL;

  this->BuildLocator(); // subdivides if necessary

  index = new int[numPts];
  for (i=0; i < numPts; i++) index[i] = -1;

  newPtId = 0; // renumbering points
//
//  Traverse each point, find bucket that point is in, check the list of
//  points in that bucket for merging.  Also need to search all
//  neighboring buckets within the tolerance.  The number and level of
//  neighbors to search depends upon the tolerance and the bucket width.
//
  for ( i=0; i < numPts; i++ ) //loop over all points
    {
    // Only try to merge the point if it hasn't yet been merged.
    if ( index[i] == -1 )
      {
      p = this->DataSet->GetPoint(i);
      index[i] = newPtId;

      for (j=0; j<3; j++)
        ijk[j] = (int) ((float)((p[j] - this->Bounds[2*j])*0.999 /
              (this->Bounds[2*j+1] - this->Bounds[2*j])) * this->Divisions[j]);

      cno = ijk[0] + ijk[1]*this->Divisions[0] +
            ijk[2]*this->Divisions[0]*this->Divisions[1];

      if ( (ptIds = this->HashTable[cno]) != NULL )
        {
        for (j=0; j < ptIds->GetNumberOfIds(); j++)
          {
          ptId = ptIds->GetId(j);
          pt = this->DataSet->GetPoint(ptId);

          if ( index[ptId] == -1 && pt[0] == p[0] && pt[1] == p[1]
          && pt[2] == p[2] )
            {
            index[ptId] = newPtId;
            }
          }
        }
      newPtId++;
      } // if point hasn't been merged
    } // for all points

  return index;
}

// Description:
// Determine whether point given by x[3] has been inserted into points list.
// Return id of previously inserted point if this is true, otherwise return
// -1.
int vtkMergePoints::IsInsertedPoint(float x[3])
{
  int i, ijk[3];
  int idx;
  vtkIdList *bucket;
//
//  Locate bucket that point is in.
//
  for (i=0; i<3; i++)
    {
    ijk[i] = (int) ((float) ((x[i] - this->Bounds[2*i])*0.999 /
             (this->Bounds[2*i+1] - this->Bounds[2*i])) * this->Divisions[i]);
    }
  idx = ijk[0] + ijk[1]*this->Divisions[0] +
        ijk[2]*this->Divisions[0]*this->Divisions[1];

  bucket = this->HashTable[idx];

  if ( ! bucket )
    {
    return -1;
    }
  else // see whether we've got duplicate point
    {
//
// Check the list of points in that bucket.
//
    int ptId;
    float *pt;

    for (i=0; i < bucket->GetNumberOfIds(); i++)
      {
      ptId = bucket->GetId(i);
      pt = this->Points->GetPoint(ptId);
      if ( x[0] == pt[0] && x[1] == pt[1] && x[2] == pt[2] ) return ptId;
      }
    }

  return -1;
}

<commit_msg>ERR: Bad index for has table. Changed calculation to use Divisions - 1.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkMergePoints.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1996 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkMergePoints.h"

// Description:
// Merge points together if they are exactly coincident. Return a list
// that maps unmerged point ids into new point ids. User is responsible
// for freeing list (use delete []). Make sure you've provided a dataset
// before invoking this method.
int *vtkMergePoints::MergePoints()
{
  int ptId, i, j;
  int numPts;
  int *index;
  int newPtId;
  float *pt, *p;
  int ijk[3];
  int cno;
  vtkIdList *ptIds;

  vtkDebugMacro(<<"Merging points");

  if ( this->DataSet == NULL ||
  (numPts=this->DataSet->GetNumberOfPoints()) < 1 ) return NULL;

  this->BuildLocator(); // subdivides if necessary

  index = new int[numPts];
  for (i=0; i < numPts; i++) index[i] = -1;

  newPtId = 0; // renumbering points
//
//  Traverse each point, find bucket that point is in, check the list of
//  points in that bucket for merging.  Also need to search all
//  neighboring buckets within the tolerance.  The number and level of
//  neighbors to search depends upon the tolerance and the bucket width.
//
  for ( i=0; i < numPts; i++ ) //loop over all points
    {
    // Only try to merge the point if it hasn't yet been merged.
    if ( index[i] == -1 )
      {
      p = this->DataSet->GetPoint(i);
      index[i] = newPtId;

      for (j=0; j<3; j++)
	{
        ijk[j] = (int) ((float)((p[j] - this->Bounds[2*j])*0.999 /
              (this->Bounds[2*j+1] - this->Bounds[2*j])) * (this->Divisions[j] - 1));
	}

      cno = ijk[0] + ijk[1]*this->Divisions[0] +
            ijk[2]*this->Divisions[0]*this->Divisions[1];

      if ( (ptIds = this->HashTable[cno]) != NULL )
        {
        for (j=0; j < ptIds->GetNumberOfIds(); j++)
          {
          ptId = ptIds->GetId(j);
          pt = this->DataSet->GetPoint(ptId);

          if ( index[ptId] == -1 && pt[0] == p[0] && pt[1] == p[1]
          && pt[2] == p[2] )
            {
            index[ptId] = newPtId;
            }
          }
        }
      newPtId++;
      } // if point hasn't been merged
    } // for all points

  return index;
}

// Description:
// Determine whether point given by x[3] has been inserted into points list.
// Return id of previously inserted point if this is true, otherwise return
// -1.
int vtkMergePoints::IsInsertedPoint(float x[3])
{
  int i, ijk[3];
  int idx;
  vtkIdList *bucket;
//
//  Locate bucket that point is in.
//
  for (i=0; i<3; i++)
    {
    ijk[i] = (int) ((float) ((x[i] - this->Bounds[2*i])*0.999 /
             (this->Bounds[2*i+1] - this->Bounds[2*i])) * (this->Divisions[i] - 1));
    }

  idx = ijk[0] + ijk[1]*this->Divisions[0] +
        ijk[2]*this->Divisions[0]*this->Divisions[1];

  bucket = this->HashTable[idx];

  if ( ! bucket )
    {
    return -1;
    }
  else // see whether we've got duplicate point
    {
//
// Check the list of points in that bucket.
//
    int ptId;
    float *pt;

    for (i=0; i < bucket->GetNumberOfIds(); i++)
      {
      ptId = bucket->GetId(i);
      pt = this->Points->GetPoint(ptId);
      if ( x[0] == pt[0] && x[1] == pt[1] && x[2] == pt[2] ) return ptId;
      }
    }

  return -1;
}

<|endoftext|>