<commit_before>#include "openmc/source.h"

#include <algorithm> // for move
#include <sstream> // for stringstream
#include <dlfcn.h> // for dlopen

#include <fmt/core.h>
#include "xtensor/xadapt.hpp"

#include "openmc/bank.h"
#include "openmc/cell.h"
#include "openmc/error.h"
#include "openmc/file_utils.h"
#include "openmc/hdf5_interface.h"
#include "openmc/material.h"
#include "openmc/message_passing.h"
#include "openmc/mgxs_interface.h"
#include "openmc/nuclide.h"
#include "openmc/capi.h"
#include "openmc/random_lcg.h"
#include "openmc/search.h"
#include "openmc/settings.h"
#include "openmc/simulation.h"
#include "openmc/state_point.h"
#include "openmc/xml_interface.h"

namespace openmc {

//==============================================================================
// Global variables
//==============================================================================

namespace model {

std::vector<SourceDistribution> external_sources;

}

//==============================================================================
// SourceDistribution implementation
//==============================================================================

SourceDistribution::SourceDistribution(UPtrSpace space, UPtrAngle angle, UPtrDist energy)
  : space_{std::move(space)}, angle_{std::move(angle)}, energy_{std::move(energy)} { }

SourceDistribution::SourceDistribution(pugi::xml_node node)
{
  // Check for particle type
  if (check_for_node(node, "particle")) {
    auto temp_str = get_node_value(node, "particle", true, true);
    if (temp_str == "neutron") {
      particle_ = Particle::Type::neutron;
    } else if (temp_str == "photon") {
      particle_ = Particle::Type::photon;
      settings::photon_transport = true;
    } else {
      fatal_error(std::string("Unknown source particle type: ") + temp_str);
    }
  }

  // Check for source strength
  if (check_for_node(node, "strength")) {
    strength_ = std::stod(get_node_value(node, "strength"));
  }

  // Check for external source file
  if (check_for_node(node, "file")) {
    // Copy path of source file
    settings::path_source = get_node_value(node, "file", false, true);

    // Check if source file exists
    if (!file_exists(settings::path_source)) {
      fatal_error(fmt::format("Source file '{}' does not exist.",
        settings::path_source));
    }
  } else if (check_for_node(node, "library")) {
     settings::path_source_library = get_node_value(node, "library", false, true);
     // check if it exists
     if (!file_exists(settings::path_source_library)) {
	std::stringstream msg;
	msg << "Library file " << settings::path_source_library << "' does not exist.";
	fatal_error(msg);
     }
  } else {

    // Spatial distribution for external source
    if (check_for_node(node, "space")) {
      // Get pointer to spatial distribution
      pugi::xml_node node_space = node.child("space");

      // Check for type of spatial distribution and read
      std::string type;
      if (check_for_node(node_space, "type"))
        type = get_node_value(node_space, "type", true, true);
      if (type == "cartesian") {
        space_ = UPtrSpace{new CartesianIndependent(node_space)};
      } else if (type == "cylindrical") {
        space_ = UPtrSpace{new CylindricalIndependent(node_space)};
      } else if (type == "spherical") {
        space_ = UPtrSpace{new SphericalIndependent(node_space)};
      } else if (type == "box") {
        space_ = UPtrSpace{new SpatialBox(node_space)};
      } else if (type == "fission") {
        space_ = UPtrSpace{new SpatialBox(node_space, true)};
      } else if (type == "point") {
        space_ = UPtrSpace{new SpatialPoint(node_space)};
      } else {
        fatal_error(fmt::format(
          "Invalid spatial distribution for external source: {}", type));
      }

    } else {
      // If no spatial distribution specified, make it a point source
      space_ = UPtrSpace{new SpatialPoint()};
    }

    // Determine external source angular distribution
    if (check_for_node(node, "angle")) {
      // Get pointer to angular distribution
      pugi::xml_node node_angle = node.child("angle");

      // Check for type of angular distribution
      std::string type;
      if (check_for_node(node_angle, "type"))
        type = get_node_value(node_angle, "type", true, true);
      if (type == "isotropic") {
        angle_ = UPtrAngle{new Isotropic()};
      } else if (type == "monodirectional") {
        angle_ = UPtrAngle{new Monodirectional(node_angle)};
      } else if (type == "mu-phi") {
        angle_ = UPtrAngle{new PolarAzimuthal(node_angle)};
      } else {
        fatal_error(fmt::format(
          "Invalid angular distribution for external source: {}", type));
      }

    } else {
      angle_ = UPtrAngle{new Isotropic()};
    }

    // Determine external source energy distribution
    if (check_for_node(node, "energy")) {
      pugi::xml_node node_dist = node.child("energy");
      energy_ = distribution_from_xml(node_dist);
    } else {
      // Default to a Watt spectrum with parameters 0.988 MeV and 2.249 MeV^-1
      energy_ = UPtrDist{new Watt(0.988e6, 2.249e-6)};
    }
  }
}

Particle::Bank SourceDistribution::sample(uint64_t* seed) const
{
  Particle::Bank site;

  // Set weight to one by default
  site.wgt = 1.0;

  // Repeat sampling source location until a good site has been found
  bool found = false;
  int n_reject = 0;
  static int n_accept = 0;
  while (!found) {
    // Set particle type
    site.particle = particle_;

    // Sample spatial distribution
    site.r = space_->sample(seed);
    double xyz[] {site.r.x, site.r.y, site.r.z};

    // Now search to see if location exists in geometry
    int32_t cell_index, instance;
    int err = openmc_find_cell(xyz, &cell_index, &instance);
    found = (err != OPENMC_E_GEOMETRY);

    // Check if spatial site is in fissionable material
    if (found) {
      auto space_box = dynamic_cast<SpatialBox*>(space_.get());
      if (space_box) {
        if (space_box->only_fissionable()) {
          // Determine material
          const auto& c = model::cells[cell_index];
          auto mat_index = c->material_.size() == 1
            ? c->material_[0] : c->material_[instance];

          if (mat_index == MATERIAL_VOID) {
            found = false;
          } else {
            if (!model::materials[mat_index]->fissionable_) found = false;
          }
        }
      }
    }

    // Check for rejection
    if (!found) {
      ++n_reject;
      if (n_reject >= EXTSRC_REJECT_THRESHOLD &&
          static_cast<double>(n_accept)/n_reject <= EXTSRC_REJECT_FRACTION) {
        fatal_error("More than 95% of external source sites sampled were "
                    "rejected. Please check your external source definition.");
      }
    }
  }

  // Increment number of accepted samples
  ++n_accept;

  // Sample angle
  site.u = angle_->sample(seed);

  // Check for monoenergetic source above maximum particle energy
  auto p = static_cast<int>(particle_);
  auto energy_ptr = dynamic_cast<Discrete*>(energy_.get());
  if (energy_ptr) {
    auto energies = xt::adapt(energy_ptr->x());
    if (xt::any(energies > data::energy_max[p])) {
      fatal_error("Source energy above range of energies of at least "
                  "one cross section table");
    } else if (xt::any(energies < data::energy_min[p])) {
      fatal_error("Source energy below range of energies of at least "
                  "one cross section table");
    }
  }

  while (true) {
    // Sample energy spectrum
    site.E = energy_->sample(seed);

    // Resample if energy falls outside minimum or maximum particle energy
    if (site.E < data::energy_max[p] && site.E > data::energy_min[p]) break;
  }

  // Set delayed group
  site.delayed_group = 0;

  return site;
}

//==============================================================================
// Non-member functions
//==============================================================================

void initialize_source()
{
  write_message("Initializing source particles...", 5);

  if (settings::path_source != "") {
    // Read the source from a binary file instead of sampling from some
    // assumed source distribution

    write_message(fmt::format("Reading source file from {}...",
      settings::path_source), 6);

    // Open the binary file
    hid_t file_id = file_open(settings::path_source, 'r', true);

    // Read the file type
    std::string filetype;
    read_attribute(file_id, "filetype", filetype);

    // Check to make sure this is a source file
    if (filetype != "source" && filetype != "statepoint") {
      fatal_error("Specified starting source file not a source file type.");
    }

    // Read in the source bank
    read_source_bank(file_id);

    // Close file
    file_close(file_id);
  } else if ( settings::path_source_library != "" ) {
    // Get the source from a library object

    std::stringstream msg;
    msg << "Sampling from library source " << settings::path_source << "...";
    write_message(msg, 6);

    // Open the library
    void* source_library = dlopen(settings::path_source_library.c_str(),RTLD_LAZY);
    if(!source_library) {
      std::stringstream msg("Couldnt open source library " + settings::path_source_library);
      fatal_error(msg);
    }

    // load the symbol
    typedef Particle::Bank (*sample_t)();

    // reset errors
    dlerror();

    // get the function from the library
    sample_t sample_source = (sample_t) dlsym(source_library, "sample_source");
    const char *dlsym_error = dlerror();

    // check for any dlsym errors
    if (dlsym_error) {
      std::cout << dlsym_error << std::endl;
      dlclose(source_library);
      fatal_error("Couldnt open the sample_source symbol");
    }

    // Generation source sites from specified distribution in the
    // library source
    for (int64_t i = 0; i < simulation::work_per_rank; ++i) {
      // initialize random number seed
      int64_t id = simulation::total_gen*settings::n_particles +
        simulation::work_index[mpi::rank] + i + 1;
      set_particle_seed(id);

      // sample external source distribution
      simulation::source_bank[i] = sample_source();
    }
    // release the library
    dlclose(source_library);

  } else {
    // Generation source sites from specified distribution in user input
    for (int64_t i = 0; i < simulation::work_per_rank; ++i) {
      // initialize random number seed
      int64_t id = simulation::total_gen*settings::n_particles +
        simulation::work_index[mpi::rank] + i + 1;
      uint64_t seed = init_seed(id, STREAM_SOURCE);

      // sample external source distribution
      simulation::source_bank[i] = sample_external_source(&seed);
    }
  }

  // Write out initial source
  if (settings::write_initial_source) {
    write_message("Writing out initial source...", 5);
    std::string filename = settings::path_output + "initial_source.h5";
    hid_t file_id = file_open(filename, 'w', true);
    write_source_bank(file_id);
    file_close(file_id);
  }
}

Particle::Bank sample_external_source(uint64_t* seed)
{
  // Determine total source strength
  double total_strength = 0.0;
  for (auto& s : model::external_sources)
    total_strength += s.strength();

  // Sample from among multiple source distributions
  int i = 0;
  if (model::external_sources.size() > 1) {
    double xi = prn(seed)*total_strength;
    double c = 0.0;
    for (; i < model::external_sources.size(); ++i) {
      c += model::external_sources[i].strength();
      if (xi < c) break;
    }
  }

  // Sample source site from i-th source distribution
  Particle::Bank site {model::external_sources[i].sample(seed)};

  // If running in MG, convert site.E to group
  if (!settings::run_CE) {
    site.E = lower_bound_index(data::mg.rev_energy_bins_.begin(),
      data::mg.rev_energy_bins_.end(), site.E);
    site.E = data::mg.num_energy_groups_ - site.E - 1.;
  }

  return site;
}

void free_memory_source()
{
  model::external_sources.clear();
}

void fill_source_bank_fixedsource()
{
  if (settings::path_source.empty() && settings::path_source_library.empty()) {
    for (int64_t i = 0; i < simulation::work_per_rank; ++i) {
      // initialize random number seed
      int64_t id = (simulation::total_gen + overall_generation()) *
        settings::n_particles + simulation::work_index[mpi::rank] + i + 1;
      uint64_t seed = init_seed(id, STREAM_SOURCE);

      // sample external source distribution
      simulation::source_bank[i] = sample_external_source(&seed);
    }
  } else if (settings::path_source.empty() && !settings::path_source.empty()) {
     std::stringstream msg;

    // Open the library
    void* source_library = dlopen(settings::path_source_library.c_str(),RTLD_LAZY);
    if(!source_library) {
      std::stringstream msg("Couldnt open source library " + settings::path_source_library);
      fatal_error(msg);
    }

    // load the symbol
    typedef Particle::Bank (*sample_t)();

    // reset errors
    dlerror();

    // get the function from the library
    sample_t sample_source = (sample_t) dlsym(source_library, "sample_source");
    const char *dlsym_error = dlerror();

    // check for any dlsym errors
    if (dlsym_error) {
      std::cout << dlsym_error << std::endl;
      dlclose(source_library);
      fatal_error("Couldnt open the sample_source symbol");
    }

    // Generation source sites from specified distribution in the
    // library source
    for (int64_t i = 0; i < simulation::work_per_rank; ++i) {
      // initialize random number seed
      int64_t id = simulation::total_gen*settings::n_particles +
        simulation::work_index[mpi::rank] + i + 1;
      set_particle_seed(id);

      // sample external source distribution
      simulation::source_bank[i] = sample_source();
    }

    // release the library
    dlclose(source_library);
  }
}

} // namespace openmc
<commit_msg>Stylistic changes<commit_after>#include "openmc/source.h"

#include <algorithm> // for move
#include <sstream> // for stringstream
#include <dlfcn.h> // for dlopen

#include <fmt/core.h>
#include "xtensor/xadapt.hpp"

#include "openmc/bank.h"
#include "openmc/cell.h"
#include "openmc/error.h"
#include "openmc/file_utils.h"
#include "openmc/hdf5_interface.h"
#include "openmc/material.h"
#include "openmc/message_passing.h"
#include "openmc/mgxs_interface.h"
#include "openmc/nuclide.h"
#include "openmc/capi.h"
#include "openmc/random_lcg.h"
#include "openmc/search.h"
#include "openmc/settings.h"
#include "openmc/simulation.h"
#include "openmc/state_point.h"
#include "openmc/xml_interface.h"

namespace openmc {

//==============================================================================
// Global variables
//==============================================================================

namespace model {

std::vector<SourceDistribution> external_sources;

}

//==============================================================================
// SourceDistribution implementation
//==============================================================================

SourceDistribution::SourceDistribution(UPtrSpace space, UPtrAngle angle, UPtrDist energy)
  : space_{std::move(space)}, angle_{std::move(angle)}, energy_{std::move(energy)} { }

SourceDistribution::SourceDistribution(pugi::xml_node node)
{
  // Check for particle type
  if (check_for_node(node, "particle")) {
    auto temp_str = get_node_value(node, "particle", true, true);
    if (temp_str == "neutron") {
      particle_ = Particle::Type::neutron;
    } else if (temp_str == "photon") {
      particle_ = Particle::Type::photon;
      settings::photon_transport = true;
    } else {
      fatal_error(std::string("Unknown source particle type: ") + temp_str);
    }
  }

  // Check for source strength
  if (check_for_node(node, "strength")) {
    strength_ = std::stod(get_node_value(node, "strength"));
  }

  // Check for external source file
  if (check_for_node(node, "file")) {
    // Copy path of source file
    settings::path_source = get_node_value(node, "file", false, true);

    // Check if source file exists
    if (!file_exists(settings::path_source)) {
      fatal_error(fmt::format("Source file '{}' does not exist.",
        settings::path_source));
    }
  } else if (check_for_node(node, "library")) {
     settings::path_source_library = get_node_value(node, "library", false, true);
     // check if it exists
     if (!file_exists(settings::path_source_library)) {
      	std::stringstream msg;
      	msg << "Library file " << settings::path_source_library << "' does not exist.";
	      fatal_error(msg);
     }
  } else {

    // Spatial distribution for external source
    if (check_for_node(node, "space")) {
      // Get pointer to spatial distribution
      pugi::xml_node node_space = node.child("space");

      // Check for type of spatial distribution and read
      std::string type;
      if (check_for_node(node_space, "type"))
        type = get_node_value(node_space, "type", true, true);
      if (type == "cartesian") {
        space_ = UPtrSpace{new CartesianIndependent(node_space)};
      } else if (type == "cylindrical") {
        space_ = UPtrSpace{new CylindricalIndependent(node_space)};
      } else if (type == "spherical") {
        space_ = UPtrSpace{new SphericalIndependent(node_space)};
      } else if (type == "box") {
        space_ = UPtrSpace{new SpatialBox(node_space)};
      } else if (type == "fission") {
        space_ = UPtrSpace{new SpatialBox(node_space, true)};
      } else if (type == "point") {
        space_ = UPtrSpace{new SpatialPoint(node_space)};
      } else {
        fatal_error(fmt::format(
          "Invalid spatial distribution for external source: {}", type));
      }

    } else {
      // If no spatial distribution specified, make it a point source
      space_ = UPtrSpace{new SpatialPoint()};
    }

    // Determine external source angular distribution
    if (check_for_node(node, "angle")) {
      // Get pointer to angular distribution
      pugi::xml_node node_angle = node.child("angle");

      // Check for type of angular distribution
      std::string type;
      if (check_for_node(node_angle, "type"))
        type = get_node_value(node_angle, "type", true, true);
      if (type == "isotropic") {
        angle_ = UPtrAngle{new Isotropic()};
      } else if (type == "monodirectional") {
        angle_ = UPtrAngle{new Monodirectional(node_angle)};
      } else if (type == "mu-phi") {
        angle_ = UPtrAngle{new PolarAzimuthal(node_angle)};
      } else {
        fatal_error(fmt::format(
          "Invalid angular distribution for external source: {}", type));
      }

    } else {
      angle_ = UPtrAngle{new Isotropic()};
    }

    // Determine external source energy distribution
    if (check_for_node(node, "energy")) {
      pugi::xml_node node_dist = node.child("energy");
      energy_ = distribution_from_xml(node_dist);
    } else {
      // Default to a Watt spectrum with parameters 0.988 MeV and 2.249 MeV^-1
      energy_ = UPtrDist{new Watt(0.988e6, 2.249e-6)};
    }
  }
}

Particle::Bank SourceDistribution::sample(uint64_t* seed) const
{
  Particle::Bank site;

  // Set weight to one by default
  site.wgt = 1.0;

  // Repeat sampling source location until a good site has been found
  bool found = false;
  int n_reject = 0;
  static int n_accept = 0;
  while (!found) {
    // Set particle type
    site.particle = particle_;

    // Sample spatial distribution
    site.r = space_->sample(seed);
    double xyz[] {site.r.x, site.r.y, site.r.z};

    // Now search to see if location exists in geometry
    int32_t cell_index, instance;
    int err = openmc_find_cell(xyz, &cell_index, &instance);
    found = (err != OPENMC_E_GEOMETRY);

    // Check if spatial site is in fissionable material
    if (found) {
      auto space_box = dynamic_cast<SpatialBox*>(space_.get());
      if (space_box) {
        if (space_box->only_fissionable()) {
          // Determine material
          const auto& c = model::cells[cell_index];
          auto mat_index = c->material_.size() == 1
            ? c->material_[0] : c->material_[instance];

          if (mat_index == MATERIAL_VOID) {
            found = false;
          } else {
            if (!model::materials[mat_index]->fissionable_) found = false;
          }
        }
      }
    }

    // Check for rejection
    if (!found) {
      ++n_reject;
      if (n_reject >= EXTSRC_REJECT_THRESHOLD &&
          static_cast<double>(n_accept)/n_reject <= EXTSRC_REJECT_FRACTION) {
        fatal_error("More than 95% of external source sites sampled were "
                    "rejected. Please check your external source definition.");
      }
    }
  }

  // Increment number of accepted samples
  ++n_accept;

  // Sample angle
  site.u = angle_->sample(seed);

  // Check for monoenergetic source above maximum particle energy
  auto p = static_cast<int>(particle_);
  auto energy_ptr = dynamic_cast<Discrete*>(energy_.get());
  if (energy_ptr) {
    auto energies = xt::adapt(energy_ptr->x());
    if (xt::any(energies > data::energy_max[p])) {
      fatal_error("Source energy above range of energies of at least "
                  "one cross section table");
    } else if (xt::any(energies < data::energy_min[p])) {
      fatal_error("Source energy below range of energies of at least "
                  "one cross section table");
    }
  }

  while (true) {
    // Sample energy spectrum
    site.E = energy_->sample(seed);

    // Resample if energy falls outside minimum or maximum particle energy
    if (site.E < data::energy_max[p] && site.E > data::energy_min[p]) break;
  }

  // Set delayed group
  site.delayed_group = 0;

  return site;
}

//==============================================================================
// Non-member functions
//==============================================================================

void initialize_source()
{
  write_message("Initializing source particles...", 5);

  if (settings::path_source != "") {
    // Read the source from a binary file instead of sampling from some
    // assumed source distribution

    write_message(fmt::format("Reading source file from {}...",
      settings::path_source), 6);

    // Open the binary file
    hid_t file_id = file_open(settings::path_source, 'r', true);

    // Read the file type
    std::string filetype;
    read_attribute(file_id, "filetype", filetype);

    // Check to make sure this is a source file
    if (filetype != "source" && filetype != "statepoint") {
      fatal_error("Specified starting source file not a source file type.");
    }

    // Read in the source bank
    read_source_bank(file_id);

    // Close file
    file_close(file_id);
  } else if ( settings::path_source_library != "" ) {
    // Get the source from a library object

    std::stringstream msg;
    msg << "Sampling from library source " << settings::path_source << "...";
    write_message(msg, 6);

    // Open the library
    void* source_library = dlopen(settings::path_source_library.c_str(),RTLD_LAZY);
    if(!source_library) {
      std::stringstream msg("Couldnt open source library " + settings::path_source_library);
      fatal_error(msg);
    }

    // load the symbol
    typedef Particle::Bank (*sample_t)();

    // reset errors
    dlerror();

    // get the function from the library
    sample_t sample_source = (sample_t) dlsym(source_library, "sample_source");
    const char *dlsym_error = dlerror();

    // check for any dlsym errors
    if (dlsym_error) {
      std::cout << dlsym_error << std::endl;
      dlclose(source_library);
      fatal_error("Couldnt open the sample_source symbol");
    }

    // Generation source sites from specified distribution in the
    // library source
    for (int64_t i = 0; i < simulation::work_per_rank; ++i) {
      // initialize random number seed
      int64_t id = simulation::total_gen*settings::n_particles +
        simulation::work_index[mpi::rank] + i + 1;
      set_particle_seed(id);

      // sample external source distribution
      simulation::source_bank[i] = sample_source();
    }
    // release the library
    dlclose(source_library);

  } else {
    // Generation source sites from specified distribution in user input
    for (int64_t i = 0; i < simulation::work_per_rank; ++i) {
      // initialize random number seed
      int64_t id = simulation::total_gen*settings::n_particles +
        simulation::work_index[mpi::rank] + i + 1;
      uint64_t seed = init_seed(id, STREAM_SOURCE);

      // sample external source distribution
      simulation::source_bank[i] = sample_external_source(&seed);
    }
  }

  // Write out initial source
  if (settings::write_initial_source) {
    write_message("Writing out initial source...", 5);
    std::string filename = settings::path_output + "initial_source.h5";
    hid_t file_id = file_open(filename, 'w', true);
    write_source_bank(file_id);
    file_close(file_id);
  }
}

Particle::Bank sample_external_source(uint64_t* seed)
{
  // Determine total source strength
  double total_strength = 0.0;
  for (auto& s : model::external_sources)
    total_strength += s.strength();

  // Sample from among multiple source distributions
  int i = 0;
  if (model::external_sources.size() > 1) {
    double xi = prn(seed)*total_strength;
    double c = 0.0;
    for (; i < model::external_sources.size(); ++i) {
      c += model::external_sources[i].strength();
      if (xi < c) break;
    }
  }

  // Sample source site from i-th source distribution
  Particle::Bank site {model::external_sources[i].sample(seed)};

  // If running in MG, convert site.E to group
  if (!settings::run_CE) {
    site.E = lower_bound_index(data::mg.rev_energy_bins_.begin(),
      data::mg.rev_energy_bins_.end(), site.E);
    site.E = data::mg.num_energy_groups_ - site.E - 1.;
  }

  return site;
}

void free_memory_source()
{
  model::external_sources.clear();
}

void fill_source_bank_fixedsource()
{
  if (settings::path_source.empty() && settings::path_source_library.empty()) {
    for (int64_t i = 0; i < simulation::work_per_rank; ++i) {
      // initialize random number seed
      int64_t id = (simulation::total_gen + overall_generation()) *
        settings::n_particles + simulation::work_index[mpi::rank] + i + 1;
      uint64_t seed = init_seed(id, STREAM_SOURCE);

      // sample external source distribution
      simulation::source_bank[i] = sample_external_source(&seed);
    }
  } else if (settings::path_source.empty() && !settings::path_source.empty()) {
     std::stringstream msg;

    // Open the library
    void* source_library = dlopen(settings::path_source_library.c_str(),RTLD_LAZY);
    if(!source_library) {
      std::stringstream msg("Couldnt open source library " + settings::path_source_library);
      fatal_error(msg);
    }

    // load the symbol
    typedef Particle::Bank (*sample_t)();

    // reset errors
    dlerror();

    // get the function from the library
    sample_t sample_source = (sample_t) dlsym(source_library, "sample_source");
    const char *dlsym_error = dlerror();

    // check for any dlsym errors
    if (dlsym_error) {
      std::cout << dlsym_error << std::endl;
      dlclose(source_library);
      fatal_error("Couldnt open the sample_source symbol");
    }

    // Generation source sites from specified distribution in the
    // library source
    for (int64_t i = 0; i < simulation::work_per_rank; ++i) {
      // initialize random number seed
      int64_t id = simulation::total_gen*settings::n_particles +
        simulation::work_index[mpi::rank] + i + 1;
      set_particle_seed(id);

      // sample external source distribution
      simulation::source_bank[i] = sample_source();
    }

    // release the library
    dlclose(source_library);
  }
}

} // namespace openmc
<|endoftext|>


<commit_before>//===- ReadConst.cpp - Code to constants and constant pools ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements functionality to deserialize constants and entire
// constant pools.
//
// Note that this library should be as fast as possible, reentrant, and
// thread-safe!!
//
//===----------------------------------------------------------------------===//

#include "ReaderInternals.h"
#include "llvm/Module.h"
#include "llvm/Constants.h"
#include <algorithm>

namespace llvm {

const Type *BytecodeParser::parseTypeConstant(const unsigned char *&Buf,
					      const unsigned char *EndBuf) {
  unsigned PrimType;
  if (read_vbr(Buf, EndBuf, PrimType)) throw Error_readvbr;

  const Type *Val = 0;
  if ((Val = Type::getPrimitiveType((Type::PrimitiveID)PrimType)))
    return Val;

  switch (PrimType) {
  case Type::FunctionTyID: {
    unsigned Typ;
    if (read_vbr(Buf, EndBuf, Typ)) return Val;
    const Type *RetType = getType(Typ);

    unsigned NumParams;
    if (read_vbr(Buf, EndBuf, NumParams)) return Val;

    std::vector<const Type*> Params;
    while (NumParams--) {
      if (read_vbr(Buf, EndBuf, Typ)) return Val;
      Params.push_back(getType(Typ));
    }

    bool isVarArg = Params.size() && Params.back() == Type::VoidTy;
    if (isVarArg) Params.pop_back();

    return FunctionType::get(RetType, Params, isVarArg);
  }
  case Type::ArrayTyID: {
    unsigned ElTyp;
    if (read_vbr(Buf, EndBuf, ElTyp)) return Val;
    const Type *ElementType = getType(ElTyp);

    unsigned NumElements;
    if (read_vbr(Buf, EndBuf, NumElements)) return Val;

    BCR_TRACE(5, "Array Type Constant #" << ElTyp << " size="
              << NumElements << "\n");
    return ArrayType::get(ElementType, NumElements);
  }
  case Type::StructTyID: {
    unsigned Typ;
    std::vector<const Type*> Elements;

    if (read_vbr(Buf, EndBuf, Typ)) return Val;
    while (Typ) {         // List is terminated by void/0 typeid
      Elements.push_back(getType(Typ));
      if (read_vbr(Buf, EndBuf, Typ)) return Val;
    }

    return StructType::get(Elements);
  }
  case Type::PointerTyID: {
    unsigned ElTyp;
    if (read_vbr(Buf, EndBuf, ElTyp)) return Val;
    BCR_TRACE(5, "Pointer Type Constant #" << ElTyp << "\n");
    return PointerType::get(getType(ElTyp));
  }

  case Type::OpaqueTyID: {
    return OpaqueType::get();
  }

  default:
    std::cerr << __FILE__ << ":" << __LINE__
              << ": Don't know how to deserialize"
              << " primitive Type " << PrimType << "\n";
    return Val;
  }
}

// parseTypeConstants - We have to use this weird code to handle recursive
// types.  We know that recursive types will only reference the current slab of
// values in the type plane, but they can forward reference types before they
// have been read.  For example, Type #0 might be '{ Ty#1 }' and Type #1 might
// be 'Ty#0*'.  When reading Type #0, type number one doesn't exist.  To fix
// this ugly problem, we pessimistically insert an opaque type for each type we
// are about to read.  This means that forward references will resolve to
// something and when we reread the type later, we can replace the opaque type
// with a new resolved concrete type.
//
void debug_type_tables();
void BytecodeParser::parseTypeConstants(const unsigned char *&Buf,
                                        const unsigned char *EndBuf,
					TypeValuesListTy &Tab,
					unsigned NumEntries) {
  assert(Tab.size() == 0 && "should not have read type constants in before!");

  // Insert a bunch of opaque types to be resolved later...
  for (unsigned i = 0; i < NumEntries; ++i)
    Tab.push_back(OpaqueType::get());

  // Loop through reading all of the types.  Forward types will make use of the
  // opaque types just inserted.
  //
  for (unsigned i = 0; i < NumEntries; ++i) {
    const Type *NewTy = parseTypeConstant(Buf, EndBuf), *OldTy = Tab[i].get();
    if (NewTy == 0) throw std::string("Parsed invalid type.");
    BCR_TRACE(4, "#" << i << ": Read Type Constant: '" << NewTy <<
              "' Replacing: " << OldTy << "\n");

    // Don't insertValue the new type... instead we want to replace the opaque
    // type with the new concrete value...
    //

    // Refine the abstract type to the new type.  This causes all uses of the
    // abstract type to use the newty.  This also will cause the opaque type
    // to be deleted...
    //
    ((DerivedType*)Tab[i].get())->refineAbstractTypeTo(NewTy);

    // This should have replace the old opaque type with the new type in the
    // value table... or with a preexisting type that was already in the system
    assert(Tab[i] != OldTy && "refineAbstractType didn't work!");
  }

  BCR_TRACE(5, "Resulting types:\n");
  for (unsigned i = 0; i < NumEntries; ++i) {
    BCR_TRACE(5, (void*)Tab[i].get() << " - " << Tab[i].get() << "\n");
  }
  debug_type_tables();
}

Constant *BytecodeParser::parseConstantValue(const unsigned char *&Buf,
                                             const unsigned char *EndBuf,
                                             const Type *Ty) {

  // We must check for a ConstantExpr before switching by type because
  // a ConstantExpr can be of any type, and has no explicit value.
  //
  unsigned isExprNumArgs;               // 0 if not expr; numArgs if is expr
  if (read_vbr(Buf, EndBuf, isExprNumArgs)) throw Error_readvbr;
  if (isExprNumArgs) {
    // FIXME: Encoding of constant exprs could be much more compact!
    unsigned Opcode;
    std::vector<Constant*> ArgVec;
    ArgVec.reserve(isExprNumArgs);
    if (read_vbr(Buf, EndBuf, Opcode)) throw Error_readvbr;

    // Read the slot number and types of each of the arguments
    for (unsigned i = 0; i != isExprNumArgs; ++i) {
      unsigned ArgValSlot, ArgTypeSlot;
      if (read_vbr(Buf, EndBuf, ArgValSlot)) throw Error_readvbr;
      if (read_vbr(Buf, EndBuf, ArgTypeSlot)) throw Error_readvbr;
      BCR_TRACE(4, "CE Arg " << i << ": Type: '" << *getType(ArgTypeSlot)
                << "'  slot: " << ArgValSlot << "\n");

      // Get the arg value from its slot if it exists, otherwise a placeholder
      ArgVec.push_back(getConstantValue(ArgTypeSlot, ArgValSlot));
    }

    // Construct a ConstantExpr of the appropriate kind
    if (isExprNumArgs == 1) {           // All one-operand expressions
      assert(Opcode == Instruction::Cast);
      return ConstantExpr::getCast(ArgVec[0], Ty);
    } else if (Opcode == Instruction::GetElementPtr) { // GetElementPtr
      std::vector<Constant*> IdxList(ArgVec.begin()+1, ArgVec.end());
      return ConstantExpr::getGetElementPtr(ArgVec[0], IdxList);
    } else if (Opcode == Instruction::Shl || Opcode == Instruction::Shr) {
      return ConstantExpr::getShift(Opcode, ArgVec[0], ArgVec[1]);
    } else {                            // All other 2-operand expressions
      return ConstantExpr::get(Opcode, ArgVec[0], ArgVec[1]);
    }
  }

  // Ok, not an ConstantExpr.  We now know how to read the given type...
  switch (Ty->getPrimitiveID()) {
  case Type::BoolTyID: {
    unsigned Val;
    if (read_vbr(Buf, EndBuf, Val)) throw Error_readvbr;
    if (Val != 0 && Val != 1) throw std::string("Invalid boolean value read.");
    return ConstantBool::get(Val == 1);
  }

  case Type::UByteTyID:   // Unsigned integer types...
  case Type::UShortTyID:
  case Type::UIntTyID: {
    unsigned Val;
    if (read_vbr(Buf, EndBuf, Val)) throw Error_readvbr;
    if (!ConstantUInt::isValueValidForType(Ty, Val))
      throw std::string("Invalid unsigned byte/short/int read.");
    return ConstantUInt::get(Ty, Val);
  }

  case Type::ULongTyID: {
    uint64_t Val;
    if (read_vbr(Buf, EndBuf, Val)) throw Error_readvbr;
    return ConstantUInt::get(Ty, Val);
  }

  case Type::SByteTyID:   // Signed integer types...
  case Type::ShortTyID:
  case Type::IntTyID: {
  case Type::LongTyID:
    int64_t Val;
    if (read_vbr(Buf, EndBuf, Val)) throw Error_readvbr;
    if (!ConstantSInt::isValueValidForType(Ty, Val))
      throw std::string("Invalid signed byte/short/int/long read.");
    return ConstantSInt::get(Ty, Val);
  }

  case Type::FloatTyID: {
    float F;
    if (input_data(Buf, EndBuf, &F, &F+1)) throw Error_inputdata;
    return ConstantFP::get(Ty, F);
  }

  case Type::DoubleTyID: {
    double Val;
    if (input_data(Buf, EndBuf, &Val, &Val+1)) throw Error_inputdata;
    return ConstantFP::get(Ty, Val);
  }

  case Type::TypeTyID:
    throw std::string("Type constants shouldn't live in constant table!");

  case Type::ArrayTyID: {
    const ArrayType *AT = cast<ArrayType>(Ty);
    unsigned NumElements = AT->getNumElements();
    unsigned TypeSlot = getTypeSlot(AT->getElementType());
    std::vector<Constant*> Elements;
    while (NumElements--) {   // Read all of the elements of the constant.
      unsigned Slot;
      if (read_vbr(Buf, EndBuf, Slot)) throw Error_readvbr;
      Elements.push_back(getConstantValue(TypeSlot, Slot));
    }
    return ConstantArray::get(AT, Elements);
  }

  case Type::StructTyID: {
    const StructType *ST = cast<StructType>(Ty);
    const StructType::ElementTypes &ET = ST->getElementTypes();

    std::vector<Constant *> Elements;
    for (unsigned i = 0; i < ET.size(); ++i) {
      unsigned Slot;
      if (read_vbr(Buf, EndBuf, Slot)) throw Error_readvbr;
      Elements.push_back(getConstantValue(ET[i], Slot));
    }

    return ConstantStruct::get(ST, Elements);
  }

  case Type::PointerTyID: {  // ConstantPointerRef value...
    const PointerType *PT = cast<PointerType>(Ty);
    unsigned Slot;
    if (read_vbr(Buf, EndBuf, Slot)) throw Error_readvbr;
    BCR_TRACE(4, "CPR: Type: '" << Ty << "'  slot: " << Slot << "\n");

    // Check to see if we have already read this global variable...
    Value *Val = getValue(PT, Slot, false);
    GlobalValue *GV;
    if (Val) {
      if (!(GV = dyn_cast<GlobalValue>(Val)))
        throw std::string("Value of ConstantPointerRef not in ValueTable!");
      BCR_TRACE(5, "Value Found in ValueTable!\n");
    } else if (RevisionNum > 0) {
      // Revision #0 could have forward references to globals that were weird.
      // We got rid of this in subsequent revs.
      throw std::string("Forward references to globals not allowed.");
    } else {         // Nope... find or create a forward ref. for it
      GlobalRefsType::iterator I = GlobalRefs.find(std::make_pair(PT, Slot));

      if (I != GlobalRefs.end()) {
        BCR_TRACE(5, "Previous forward ref found!\n");
        GV = cast<GlobalValue>(I->second);
      } else {
        BCR_TRACE(5, "Creating new forward ref to a global variable!\n");

        // Create a placeholder for the global variable reference...
        GlobalVariable *GVar =
          new GlobalVariable(PT->getElementType(), false,
                             GlobalValue::InternalLinkage);

        // Keep track of the fact that we have a forward ref to recycle it
        GlobalRefs.insert(std::make_pair(std::make_pair(PT, Slot), GVar));

        // Must temporarily push this value into the module table...
        TheModule->getGlobalList().push_back(GVar);
        GV = GVar;
      }
    }

    return ConstantPointerRef::get(GV);
  }

  default:
    throw std::string("Don't know how to deserialize constant value of type '"+
                      Ty->getDescription());
  }
}

void BytecodeParser::ParseGlobalTypes(const unsigned char *&Buf,
                                      const unsigned char *EndBuf) {
  ValueTable T;
  ParseConstantPool(Buf, EndBuf, T, ModuleTypeValues);
}

void BytecodeParser::ParseConstantPool(const unsigned char *&Buf,
                                       const unsigned char *EndBuf,
                                       ValueTable &Tab,
                                       TypeValuesListTy &TypeTab) {
  while (Buf < EndBuf) {
    unsigned NumEntries, Typ;

    if (read_vbr(Buf, EndBuf, NumEntries) ||
        read_vbr(Buf, EndBuf, Typ)) throw Error_readvbr;
    if (Typ == Type::TypeTyID) {
      BCR_TRACE(3, "Type: 'type'  NumEntries: " << NumEntries << "\n");
      parseTypeConstants(Buf, EndBuf, TypeTab, NumEntries);
    } else {
      const Type *Ty = getType(Typ);
      BCR_TRACE(3, "Type: '" << *Ty << "'  NumEntries: " << NumEntries << "\n");

      for (unsigned i = 0; i < NumEntries; ++i) {
        Constant *C = parseConstantValue(Buf, EndBuf, Ty);
        assert(C && "parseConstantValue returned NULL!");
        BCR_TRACE(4, "Read Constant: '" << *C << "'\n");
        unsigned Slot = insertValue(C, Typ, Tab);

        // If we are reading a function constant table, make sure that we adjust
        // the slot number to be the real global constant number.
        //
        if (&Tab != &ModuleValues && Typ < ModuleValues.size())
          Slot += ModuleValues[Typ]->size();
        ResolveReferencesToValue(C, Slot);
      }
    }
  }

  if (Buf > EndBuf) throw std::string("Read past end of buffer.");
}

} // End llvm namespace
<commit_msg>Minor efficiency improvements all over.  Finegrainify Namespacification<commit_after>//===- ReadConst.cpp - Code to constants and constant pools ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements functionality to deserialize constants and entire
// constant pools.
//
// Note that this library should be as fast as possible, reentrant, and
// thread-safe!!
//
//===----------------------------------------------------------------------===//

#include "ReaderInternals.h"
#include "llvm/Module.h"
#include "llvm/Constants.h"
#include <algorithm>
using namespace llvm;

const Type *BytecodeParser::parseTypeConstant(const unsigned char *&Buf,
					      const unsigned char *EndBuf) {
  unsigned PrimType;
  if (read_vbr(Buf, EndBuf, PrimType)) throw Error_readvbr;

  const Type *Val = 0;
  if ((Val = Type::getPrimitiveType((Type::PrimitiveID)PrimType)))
    return Val;

  switch (PrimType) {
  case Type::FunctionTyID: {
    unsigned Typ;
    if (read_vbr(Buf, EndBuf, Typ)) return Val;
    const Type *RetType = getType(Typ);

    unsigned NumParams;
    if (read_vbr(Buf, EndBuf, NumParams)) return Val;

    std::vector<const Type*> Params;
    while (NumParams--) {
      if (read_vbr(Buf, EndBuf, Typ)) return Val;
      Params.push_back(getType(Typ));
    }

    bool isVarArg = Params.size() && Params.back() == Type::VoidTy;
    if (isVarArg) Params.pop_back();

    return FunctionType::get(RetType, Params, isVarArg);
  }
  case Type::ArrayTyID: {
    unsigned ElTyp;
    if (read_vbr(Buf, EndBuf, ElTyp)) return Val;
    const Type *ElementType = getType(ElTyp);

    unsigned NumElements;
    if (read_vbr(Buf, EndBuf, NumElements)) return Val;

    BCR_TRACE(5, "Array Type Constant #" << ElTyp << " size="
              << NumElements << "\n");
    return ArrayType::get(ElementType, NumElements);
  }
  case Type::StructTyID: {
    unsigned Typ;
    std::vector<const Type*> Elements;

    if (read_vbr(Buf, EndBuf, Typ)) return Val;
    while (Typ) {         // List is terminated by void/0 typeid
      Elements.push_back(getType(Typ));
      if (read_vbr(Buf, EndBuf, Typ)) return Val;
    }

    return StructType::get(Elements);
  }
  case Type::PointerTyID: {
    unsigned ElTyp;
    if (read_vbr(Buf, EndBuf, ElTyp)) return Val;
    BCR_TRACE(5, "Pointer Type Constant #" << ElTyp << "\n");
    return PointerType::get(getType(ElTyp));
  }

  case Type::OpaqueTyID: {
    return OpaqueType::get();
  }

  default:
    std::cerr << __FILE__ << ":" << __LINE__
              << ": Don't know how to deserialize"
              << " primitive Type " << PrimType << "\n";
    return Val;
  }
}

// parseTypeConstants - We have to use this weird code to handle recursive
// types.  We know that recursive types will only reference the current slab of
// values in the type plane, but they can forward reference types before they
// have been read.  For example, Type #0 might be '{ Ty#1 }' and Type #1 might
// be 'Ty#0*'.  When reading Type #0, type number one doesn't exist.  To fix
// this ugly problem, we pessimistically insert an opaque type for each type we
// are about to read.  This means that forward references will resolve to
// something and when we reread the type later, we can replace the opaque type
// with a new resolved concrete type.
//
namespace llvm { void debug_type_tables(); }
void BytecodeParser::parseTypeConstants(const unsigned char *&Buf,
                                        const unsigned char *EndBuf,
					TypeValuesListTy &Tab,
					unsigned NumEntries) {
  assert(Tab.size() == 0 && "should not have read type constants in before!");

  // Insert a bunch of opaque types to be resolved later...
  // FIXME: this is dumb
  Tab.reserve(NumEntries);
  for (unsigned i = 0; i < NumEntries; ++i)
    Tab.push_back(OpaqueType::get());

  // Loop through reading all of the types.  Forward types will make use of the
  // opaque types just inserted.
  //
  for (unsigned i = 0; i < NumEntries; ++i) {
    const Type *NewTy = parseTypeConstant(Buf, EndBuf), *OldTy = Tab[i].get();
    if (NewTy == 0) throw std::string("Parsed invalid type.");
    BCR_TRACE(4, "#" << i << ": Read Type Constant: '" << NewTy <<
              "' Replacing: " << OldTy << "\n");

    // Don't insertValue the new type... instead we want to replace the opaque
    // type with the new concrete value...
    //

    // Refine the abstract type to the new type.  This causes all uses of the
    // abstract type to use the newty.  This also will cause the opaque type
    // to be deleted...
    //
    ((DerivedType*)Tab[i].get())->refineAbstractTypeTo(NewTy);

    // This should have replace the old opaque type with the new type in the
    // value table... or with a preexisting type that was already in the system
    assert(Tab[i] != OldTy && "refineAbstractType didn't work!");
  }

  BCR_TRACE(5, "Resulting types:\n");
  for (unsigned i = 0; i < NumEntries; ++i) {
    BCR_TRACE(5, (void*)Tab[i].get() << " - " << Tab[i].get() << "\n");
  }
  debug_type_tables();
}

Constant *BytecodeParser::parseConstantValue(const unsigned char *&Buf,
                                             const unsigned char *EndBuf,
                                             unsigned TypeID) {

  // We must check for a ConstantExpr before switching by type because
  // a ConstantExpr can be of any type, and has no explicit value.
  //
  unsigned isExprNumArgs;               // 0 if not expr; numArgs if is expr
  if (read_vbr(Buf, EndBuf, isExprNumArgs)) throw Error_readvbr;
  if (isExprNumArgs) {
    // FIXME: Encoding of constant exprs could be much more compact!
    unsigned Opcode;
    std::vector<Constant*> ArgVec;
    ArgVec.reserve(isExprNumArgs);
    if (read_vbr(Buf, EndBuf, Opcode)) throw Error_readvbr;

    // Read the slot number and types of each of the arguments
    for (unsigned i = 0; i != isExprNumArgs; ++i) {
      unsigned ArgValSlot, ArgTypeSlot;
      if (read_vbr(Buf, EndBuf, ArgValSlot)) throw Error_readvbr;
      if (read_vbr(Buf, EndBuf, ArgTypeSlot)) throw Error_readvbr;
      BCR_TRACE(4, "CE Arg " << i << ": Type: '" << *getType(ArgTypeSlot)
                << "'  slot: " << ArgValSlot << "\n");

      // Get the arg value from its slot if it exists, otherwise a placeholder
      ArgVec.push_back(getConstantValue(ArgTypeSlot, ArgValSlot));
    }

    // Construct a ConstantExpr of the appropriate kind
    if (isExprNumArgs == 1) {           // All one-operand expressions
      assert(Opcode == Instruction::Cast);
      return ConstantExpr::getCast(ArgVec[0], getType(TypeID));
    } else if (Opcode == Instruction::GetElementPtr) { // GetElementPtr
      std::vector<Constant*> IdxList(ArgVec.begin()+1, ArgVec.end());
      return ConstantExpr::getGetElementPtr(ArgVec[0], IdxList);
    } else if (Opcode == Instruction::Shl || Opcode == Instruction::Shr) {
      return ConstantExpr::getShift(Opcode, ArgVec[0], ArgVec[1]);
    } else {                            // All other 2-operand expressions
      return ConstantExpr::get(Opcode, ArgVec[0], ArgVec[1]);
    }
  }

  // Ok, not an ConstantExpr.  We now know how to read the given type...
  const Type *Ty = getType(TypeID);
  switch (Ty->getPrimitiveID()) {
  case Type::BoolTyID: {
    unsigned Val;
    if (read_vbr(Buf, EndBuf, Val)) throw Error_readvbr;
    if (Val != 0 && Val != 1) throw std::string("Invalid boolean value read.");
    return ConstantBool::get(Val == 1);
  }

  case Type::UByteTyID:   // Unsigned integer types...
  case Type::UShortTyID:
  case Type::UIntTyID: {
    unsigned Val;
    if (read_vbr(Buf, EndBuf, Val)) throw Error_readvbr;
    if (!ConstantUInt::isValueValidForType(Ty, Val))
      throw std::string("Invalid unsigned byte/short/int read.");
    return ConstantUInt::get(Ty, Val);
  }

  case Type::ULongTyID: {
    uint64_t Val;
    if (read_vbr(Buf, EndBuf, Val)) throw Error_readvbr;
    return ConstantUInt::get(Ty, Val);
  }

  case Type::SByteTyID:   // Signed integer types...
  case Type::ShortTyID:
  case Type::IntTyID: {
  case Type::LongTyID:
    int64_t Val;
    if (read_vbr(Buf, EndBuf, Val)) throw Error_readvbr;
    if (!ConstantSInt::isValueValidForType(Ty, Val))
      throw std::string("Invalid signed byte/short/int/long read.");
    return ConstantSInt::get(Ty, Val);
  }

  case Type::FloatTyID: {
    float F;
    if (input_data(Buf, EndBuf, &F, &F+1)) throw Error_inputdata;
    return ConstantFP::get(Ty, F);
  }

  case Type::DoubleTyID: {
    double Val;
    if (input_data(Buf, EndBuf, &Val, &Val+1)) throw Error_inputdata;
    return ConstantFP::get(Ty, Val);
  }

  case Type::TypeTyID:
    throw std::string("Type constants shouldn't live in constant table!");

  case Type::ArrayTyID: {
    const ArrayType *AT = cast<ArrayType>(Ty);
    unsigned NumElements = AT->getNumElements();
    unsigned TypeSlot = getTypeSlot(AT->getElementType());
    std::vector<Constant*> Elements;
    while (NumElements--) {   // Read all of the elements of the constant.
      unsigned Slot;
      if (read_vbr(Buf, EndBuf, Slot)) throw Error_readvbr;
      Elements.push_back(getConstantValue(TypeSlot, Slot));
    }
    return ConstantArray::get(AT, Elements);
  }

  case Type::StructTyID: {
    const StructType *ST = cast<StructType>(Ty);
    const StructType::ElementTypes &ET = ST->getElementTypes();

    std::vector<Constant *> Elements;
    for (unsigned i = 0; i < ET.size(); ++i) {
      unsigned Slot;
      if (read_vbr(Buf, EndBuf, Slot)) throw Error_readvbr;
      Elements.push_back(getConstantValue(ET[i], Slot));
    }

    return ConstantStruct::get(ST, Elements);
  }

  case Type::PointerTyID: {  // ConstantPointerRef value...
    const PointerType *PT = cast<PointerType>(Ty);
    unsigned Slot;
    if (read_vbr(Buf, EndBuf, Slot)) throw Error_readvbr;
    BCR_TRACE(4, "CPR: Type: '" << Ty << "'  slot: " << Slot << "\n");

    // Check to see if we have already read this global variable...
    Value *Val = getValue(TypeID, Slot, false);
    GlobalValue *GV;
    if (Val) {
      if (!(GV = dyn_cast<GlobalValue>(Val)))
        throw std::string("Value of ConstantPointerRef not in ValueTable!");
      BCR_TRACE(5, "Value Found in ValueTable!\n");
    } else {
      throw std::string("Forward references are not allowed here.");
    }

    return ConstantPointerRef::get(GV);
  }

  default:
    throw std::string("Don't know how to deserialize constant value of type '"+
                      Ty->getDescription());
  }
}

void BytecodeParser::ParseGlobalTypes(const unsigned char *&Buf,
                                      const unsigned char *EndBuf) {
  ValueTable T;
  ParseConstantPool(Buf, EndBuf, T, ModuleTypeValues);
}

void BytecodeParser::ParseConstantPool(const unsigned char *&Buf,
                                       const unsigned char *EndBuf,
                                       ValueTable &Tab,
                                       TypeValuesListTy &TypeTab) {
  while (Buf < EndBuf) {
    unsigned NumEntries, Typ;

    if (read_vbr(Buf, EndBuf, NumEntries) ||
        read_vbr(Buf, EndBuf, Typ)) throw Error_readvbr;
    if (Typ == Type::TypeTyID) {
      BCR_TRACE(3, "Type: 'type'  NumEntries: " << NumEntries << "\n");
      parseTypeConstants(Buf, EndBuf, TypeTab, NumEntries);
    } else {
      BCR_TRACE(3, "Type: '" << *getType(Typ) << "'  NumEntries: "
                << NumEntries << "\n");

      for (unsigned i = 0; i < NumEntries; ++i) {
        Constant *C = parseConstantValue(Buf, EndBuf, Typ);
        assert(C && "parseConstantValue returned NULL!");
        BCR_TRACE(4, "Read Constant: '" << *C << "'\n");
        unsigned Slot = insertValue(C, Typ, Tab);

        // If we are reading a function constant table, make sure that we adjust
        // the slot number to be the real global constant number.
        //
        if (&Tab != &ModuleValues && Typ < ModuleValues.size())
          Slot += ModuleValues[Typ]->size();
        ResolveReferencesToConstant(C, Slot);
      }
    }
  }

  if (Buf > EndBuf) throw std::string("Read past end of buffer.");
}
<|endoftext|>


<commit_before>//===- ReadConst.cpp - Code to constants and constant pools ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements functionality to deserialize constants and entire
// constant pools.
//
// Note that this library should be as fast as possible, reentrant, and
// thread-safe!!
//
//===----------------------------------------------------------------------===//

#include "ReaderInternals.h"
#include "llvm/Module.h"
#include "llvm/Constants.h"
#include <algorithm>
using namespace llvm;

const Type *BytecodeParser::parseTypeConstant(const unsigned char *&Buf,
					      const unsigned char *EndBuf) {
  unsigned PrimType;
  if (read_vbr(Buf, EndBuf, PrimType)) throw Error_readvbr;

  const Type *Val = 0;
  if ((Val = Type::getPrimitiveType((Type::PrimitiveID)PrimType)))
    return Val;

  switch (PrimType) {
  case Type::FunctionTyID: {
    unsigned Typ;
    if (read_vbr(Buf, EndBuf, Typ)) return Val;
    const Type *RetType = getType(Typ);

    unsigned NumParams;
    if (read_vbr(Buf, EndBuf, NumParams)) return Val;

    std::vector<const Type*> Params;
    while (NumParams--) {
      if (read_vbr(Buf, EndBuf, Typ)) return Val;
      Params.push_back(getType(Typ));
    }

    bool isVarArg = Params.size() && Params.back() == Type::VoidTy;
    if (isVarArg) Params.pop_back();

    return FunctionType::get(RetType, Params, isVarArg);
  }
  case Type::ArrayTyID: {
    unsigned ElTyp;
    if (read_vbr(Buf, EndBuf, ElTyp)) return Val;
    const Type *ElementType = getType(ElTyp);

    unsigned NumElements;
    if (read_vbr(Buf, EndBuf, NumElements)) return Val;

    BCR_TRACE(5, "Array Type Constant #" << ElTyp << " size="
              << NumElements << "\n");
    return ArrayType::get(ElementType, NumElements);
  }
  case Type::StructTyID: {
    unsigned Typ;
    std::vector<const Type*> Elements;

    if (read_vbr(Buf, EndBuf, Typ)) return Val;
    while (Typ) {         // List is terminated by void/0 typeid
      Elements.push_back(getType(Typ));
      if (read_vbr(Buf, EndBuf, Typ)) return Val;
    }

    return StructType::get(Elements);
  }
  case Type::PointerTyID: {
    unsigned ElTyp;
    if (read_vbr(Buf, EndBuf, ElTyp)) return Val;
    BCR_TRACE(5, "Pointer Type Constant #" << ElTyp << "\n");
    return PointerType::get(getType(ElTyp));
  }

  case Type::OpaqueTyID: {
    return OpaqueType::get();
  }

  default:
    std::cerr << __FILE__ << ":" << __LINE__
              << ": Don't know how to deserialize"
              << " primitive Type " << PrimType << "\n";
    return Val;
  }
}

// parseTypeConstants - We have to use this weird code to handle recursive
// types.  We know that recursive types will only reference the current slab of
// values in the type plane, but they can forward reference types before they
// have been read.  For example, Type #0 might be '{ Ty#1 }' and Type #1 might
// be 'Ty#0*'.  When reading Type #0, type number one doesn't exist.  To fix
// this ugly problem, we pessimistically insert an opaque type for each type we
// are about to read.  This means that forward references will resolve to
// something and when we reread the type later, we can replace the opaque type
// with a new resolved concrete type.
//
namespace llvm { void debug_type_tables(); }
void BytecodeParser::parseTypeConstants(const unsigned char *&Buf,
                                        const unsigned char *EndBuf,
					TypeValuesListTy &Tab,
					unsigned NumEntries) {
  assert(Tab.size() == 0 && "should not have read type constants in before!");

  // Insert a bunch of opaque types to be resolved later...
  // FIXME: this is dumb
  Tab.reserve(NumEntries);
  for (unsigned i = 0; i < NumEntries; ++i)
    Tab.push_back(OpaqueType::get());

  // Loop through reading all of the types.  Forward types will make use of the
  // opaque types just inserted.
  //
  for (unsigned i = 0; i < NumEntries; ++i) {
    const Type *NewTy = parseTypeConstant(Buf, EndBuf), *OldTy = Tab[i].get();
    if (NewTy == 0) throw std::string("Parsed invalid type.");
    BCR_TRACE(4, "#" << i << ": Read Type Constant: '" << NewTy <<
              "' Replacing: " << OldTy << "\n");

    // Don't insertValue the new type... instead we want to replace the opaque
    // type with the new concrete value...
    //

    // Refine the abstract type to the new type.  This causes all uses of the
    // abstract type to use the newty.  This also will cause the opaque type
    // to be deleted...
    //
    ((DerivedType*)Tab[i].get())->refineAbstractTypeTo(NewTy);

    // This should have replace the old opaque type with the new type in the
    // value table... or with a preexisting type that was already in the system
    assert(Tab[i] != OldTy && "refineAbstractType didn't work!");
  }

  BCR_TRACE(5, "Resulting types:\n");
  for (unsigned i = 0; i < NumEntries; ++i) {
    BCR_TRACE(5, (void*)Tab[i].get() << " - " << Tab[i].get() << "\n");
  }
  debug_type_tables();
}

Constant *BytecodeParser::parseConstantValue(const unsigned char *&Buf,
                                             const unsigned char *EndBuf,
                                             unsigned TypeID) {

  // We must check for a ConstantExpr before switching by type because
  // a ConstantExpr can be of any type, and has no explicit value.
  //
  unsigned isExprNumArgs;               // 0 if not expr; numArgs if is expr
  if (read_vbr(Buf, EndBuf, isExprNumArgs)) throw Error_readvbr;
  if (isExprNumArgs) {
    // FIXME: Encoding of constant exprs could be much more compact!
    unsigned Opcode;
    std::vector<Constant*> ArgVec;
    ArgVec.reserve(isExprNumArgs);
    if (read_vbr(Buf, EndBuf, Opcode)) throw Error_readvbr;

    // Read the slot number and types of each of the arguments
    for (unsigned i = 0; i != isExprNumArgs; ++i) {
      unsigned ArgValSlot, ArgTypeSlot;
      if (read_vbr(Buf, EndBuf, ArgValSlot)) throw Error_readvbr;
      if (read_vbr(Buf, EndBuf, ArgTypeSlot)) throw Error_readvbr;
      BCR_TRACE(4, "CE Arg " << i << ": Type: '" << *getType(ArgTypeSlot)
                << "'  slot: " << ArgValSlot << "\n");

      // Get the arg value from its slot if it exists, otherwise a placeholder
      ArgVec.push_back(getConstantValue(ArgTypeSlot, ArgValSlot));
    }

    // Construct a ConstantExpr of the appropriate kind
    if (isExprNumArgs == 1) {           // All one-operand expressions
      assert(Opcode == Instruction::Cast);
      return ConstantExpr::getCast(ArgVec[0], getType(TypeID));
    } else if (Opcode == Instruction::GetElementPtr) { // GetElementPtr
      std::vector<Constant*> IdxList(ArgVec.begin()+1, ArgVec.end());
      return ConstantExpr::getGetElementPtr(ArgVec[0], IdxList);
    } else if (Opcode == Instruction::Shl || Opcode == Instruction::Shr) {
      return ConstantExpr::getShift(Opcode, ArgVec[0], ArgVec[1]);
    } else {                            // All other 2-operand expressions
      return ConstantExpr::get(Opcode, ArgVec[0], ArgVec[1]);
    }
  }

  // Ok, not an ConstantExpr.  We now know how to read the given type...
  const Type *Ty = getType(TypeID);
  switch (Ty->getPrimitiveID()) {
  case Type::BoolTyID: {
    unsigned Val;
    if (read_vbr(Buf, EndBuf, Val)) throw Error_readvbr;
    if (Val != 0 && Val != 1) throw std::string("Invalid boolean value read.");
    return ConstantBool::get(Val == 1);
  }

  case Type::UByteTyID:   // Unsigned integer types...
  case Type::UShortTyID:
  case Type::UIntTyID: {
    unsigned Val;
    if (read_vbr(Buf, EndBuf, Val)) throw Error_readvbr;
    if (!ConstantUInt::isValueValidForType(Ty, Val))
      throw std::string("Invalid unsigned byte/short/int read.");
    return ConstantUInt::get(Ty, Val);
  }

  case Type::ULongTyID: {
    uint64_t Val;
    if (read_vbr(Buf, EndBuf, Val)) throw Error_readvbr;
    return ConstantUInt::get(Ty, Val);
  }

  case Type::SByteTyID:   // Signed integer types...
  case Type::ShortTyID:
  case Type::IntTyID: {
  case Type::LongTyID:
    int64_t Val;
    if (read_vbr(Buf, EndBuf, Val)) throw Error_readvbr;
    if (!ConstantSInt::isValueValidForType(Ty, Val))
      throw std::string("Invalid signed byte/short/int/long read.");
    return ConstantSInt::get(Ty, Val);
  }

  case Type::FloatTyID: {
    float F;
    if (input_data(Buf, EndBuf, &F, &F+1)) throw Error_inputdata;
    return ConstantFP::get(Ty, F);
  }

  case Type::DoubleTyID: {
    double Val;
    if (input_data(Buf, EndBuf, &Val, &Val+1)) throw Error_inputdata;
    return ConstantFP::get(Ty, Val);
  }

  case Type::TypeTyID:
    throw std::string("Type constants shouldn't live in constant table!");

  case Type::ArrayTyID: {
    const ArrayType *AT = cast<ArrayType>(Ty);
    unsigned NumElements = AT->getNumElements();
    unsigned TypeSlot = getTypeSlot(AT->getElementType());
    std::vector<Constant*> Elements;
    while (NumElements--) {   // Read all of the elements of the constant.
      unsigned Slot;
      if (read_vbr(Buf, EndBuf, Slot)) throw Error_readvbr;
      Elements.push_back(getConstantValue(TypeSlot, Slot));
    }
    return ConstantArray::get(AT, Elements);
  }

  case Type::StructTyID: {
    const StructType *ST = cast<StructType>(Ty);
    const StructType::ElementTypes &ET = ST->getElementTypes();

    std::vector<Constant *> Elements;
    for (unsigned i = 0; i < ET.size(); ++i) {
      unsigned Slot;
      if (read_vbr(Buf, EndBuf, Slot)) throw Error_readvbr;
      Elements.push_back(getConstantValue(ET[i], Slot));
    }

    return ConstantStruct::get(ST, Elements);
  }

  case Type::PointerTyID: {  // ConstantPointerRef value...
    const PointerType *PT = cast<PointerType>(Ty);
    unsigned Slot;
    if (read_vbr(Buf, EndBuf, Slot)) throw Error_readvbr;
    BCR_TRACE(4, "CPR: Type: '" << Ty << "'  slot: " << Slot << "\n");

    // Check to see if we have already read this global variable...
    Value *Val = getValue(TypeID, Slot, false);
    GlobalValue *GV;
    if (Val) {
      if (!(GV = dyn_cast<GlobalValue>(Val)))
        throw std::string("Value of ConstantPointerRef not in ValueTable!");
      BCR_TRACE(5, "Value Found in ValueTable!\n");
    } else {
      throw std::string("Forward references are not allowed here.");
    }

    return ConstantPointerRef::get(GV);
  }

  default:
    throw std::string("Don't know how to deserialize constant value of type '"+
                      Ty->getDescription());
  }
}

void BytecodeParser::ParseGlobalTypes(const unsigned char *&Buf,
                                      const unsigned char *EndBuf) {
  ValueTable T;
  ParseConstantPool(Buf, EndBuf, T, ModuleTypeValues);
}

void BytecodeParser::ParseConstantPool(const unsigned char *&Buf,
                                       const unsigned char *EndBuf,
                                       ValueTable &Tab,
                                       TypeValuesListTy &TypeTab) {
  while (Buf < EndBuf) {
    unsigned NumEntries, Typ;

    if (read_vbr(Buf, EndBuf, NumEntries) ||
        read_vbr(Buf, EndBuf, Typ)) throw Error_readvbr;
    if (Typ == Type::TypeTyID) {
      BCR_TRACE(3, "Type: 'type'  NumEntries: " << NumEntries << "\n");
      parseTypeConstants(Buf, EndBuf, TypeTab, NumEntries);
    } else {
      BCR_TRACE(3, "Type: '" << *getType(Typ) << "'  NumEntries: "
                << NumEntries << "\n");

      for (unsigned i = 0; i < NumEntries; ++i) {
        Constant *C = parseConstantValue(Buf, EndBuf, Typ);
        assert(C && "parseConstantValue returned NULL!");
        BCR_TRACE(4, "Read Constant: '" << *C << "'\n");
        unsigned Slot = insertValue(C, Typ, Tab);

        // If we are reading a function constant table, make sure that we adjust
        // the slot number to be the real global constant number.
        //
        if (&Tab != &ModuleValues && Typ < ModuleValues.size() &&
            ModuleValues[Typ])
          Slot += ModuleValues[Typ]->size();
        ResolveReferencesToConstant(C, Slot);
      }
    }
  }

  if (Buf > EndBuf) throw std::string("Read past end of buffer.");
}
<commit_msg>minor cleanups<commit_after>//===- ReadConst.cpp - Code to constants and constant pools ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements functionality to deserialize constants and entire
// constant pools.
//
// Note that this library should be as fast as possible, reentrant, and
// thread-safe!!
//
//===----------------------------------------------------------------------===//

#include "ReaderInternals.h"
#include "llvm/Module.h"
#include "llvm/Constants.h"
#include <algorithm>
using namespace llvm;

const Type *BytecodeParser::parseTypeConstant(const unsigned char *&Buf,
					      const unsigned char *EndBuf) {
  unsigned PrimType;
  if (read_vbr(Buf, EndBuf, PrimType)) throw Error_readvbr;

  const Type *Val = 0;
  if ((Val = Type::getPrimitiveType((Type::PrimitiveID)PrimType)))
    return Val;

  switch (PrimType) {
  case Type::FunctionTyID: {
    unsigned Typ;
    if (read_vbr(Buf, EndBuf, Typ)) return Val;
    const Type *RetType = getType(Typ);

    unsigned NumParams;
    if (read_vbr(Buf, EndBuf, NumParams)) return Val;

    std::vector<const Type*> Params;
    while (NumParams--) {
      if (read_vbr(Buf, EndBuf, Typ)) return Val;
      Params.push_back(getType(Typ));
    }

    bool isVarArg = Params.size() && Params.back() == Type::VoidTy;
    if (isVarArg) Params.pop_back();

    return FunctionType::get(RetType, Params, isVarArg);
  }
  case Type::ArrayTyID: {
    unsigned ElTyp;
    if (read_vbr(Buf, EndBuf, ElTyp)) return Val;
    const Type *ElementType = getType(ElTyp);

    unsigned NumElements;
    if (read_vbr(Buf, EndBuf, NumElements)) return Val;

    BCR_TRACE(5, "Array Type Constant #" << ElTyp << " size="
              << NumElements << "\n");
    return ArrayType::get(ElementType, NumElements);
  }
  case Type::StructTyID: {
    unsigned Typ;
    std::vector<const Type*> Elements;

    if (read_vbr(Buf, EndBuf, Typ)) return Val;
    while (Typ) {         // List is terminated by void/0 typeid
      Elements.push_back(getType(Typ));
      if (read_vbr(Buf, EndBuf, Typ)) return Val;
    }

    return StructType::get(Elements);
  }
  case Type::PointerTyID: {
    unsigned ElTyp;
    if (read_vbr(Buf, EndBuf, ElTyp)) return Val;
    BCR_TRACE(5, "Pointer Type Constant #" << ElTyp << "\n");
    return PointerType::get(getType(ElTyp));
  }

  case Type::OpaqueTyID: {
    return OpaqueType::get();
  }

  default:
    std::cerr << __FILE__ << ":" << __LINE__
              << ": Don't know how to deserialize"
              << " primitive Type " << PrimType << "\n";
    return Val;
  }
}

// parseTypeConstants - We have to use this weird code to handle recursive
// types.  We know that recursive types will only reference the current slab of
// values in the type plane, but they can forward reference types before they
// have been read.  For example, Type #0 might be '{ Ty#1 }' and Type #1 might
// be 'Ty#0*'.  When reading Type #0, type number one doesn't exist.  To fix
// this ugly problem, we pessimistically insert an opaque type for each type we
// are about to read.  This means that forward references will resolve to
// something and when we reread the type later, we can replace the opaque type
// with a new resolved concrete type.
//
namespace llvm { void debug_type_tables(); }
void BytecodeParser::parseTypeConstants(const unsigned char *&Buf,
                                        const unsigned char *EndBuf,
					TypeValuesListTy &Tab,
					unsigned NumEntries) {
  assert(Tab.size() == 0 && "should not have read type constants in before!");

  // Insert a bunch of opaque types to be resolved later...
  Tab.reserve(NumEntries);
  for (unsigned i = 0; i != NumEntries; ++i)
    Tab.push_back(OpaqueType::get());

  // Loop through reading all of the types.  Forward types will make use of the
  // opaque types just inserted.
  //
  for (unsigned i = 0; i != NumEntries; ++i) {
    const Type *NewTy = parseTypeConstant(Buf, EndBuf), *OldTy = Tab[i].get();
    if (NewTy == 0) throw std::string("Couldn't parse type!");
    BCR_TRACE(4, "#" << i << ": Read Type Constant: '" << NewTy <<
              "' Replacing: " << OldTy << "\n");

    // Don't insertValue the new type... instead we want to replace the opaque
    // type with the new concrete value...
    //

    // Refine the abstract type to the new type.  This causes all uses of the
    // abstract type to use NewTy.  This also will cause the opaque type to be
    // deleted...
    //
    cast<DerivedType>(const_cast<Type*>(OldTy))->refineAbstractTypeTo(NewTy);

    // This should have replace the old opaque type with the new type in the
    // value table... or with a preexisting type that was already in the system
    assert(Tab[i] != OldTy && "refineAbstractType didn't work!");
  }

  BCR_TRACE(5, "Resulting types:\n");
  for (unsigned i = 0; i < NumEntries; ++i) {
    BCR_TRACE(5, (void*)Tab[i].get() << " - " << Tab[i].get() << "\n");
  }
  debug_type_tables();
}

Constant *BytecodeParser::parseConstantValue(const unsigned char *&Buf,
                                             const unsigned char *EndBuf,
                                             unsigned TypeID) {

  // We must check for a ConstantExpr before switching by type because
  // a ConstantExpr can be of any type, and has no explicit value.
  //
  unsigned isExprNumArgs;               // 0 if not expr; numArgs if is expr
  if (read_vbr(Buf, EndBuf, isExprNumArgs)) throw Error_readvbr;
  if (isExprNumArgs) {
    // FIXME: Encoding of constant exprs could be much more compact!
    unsigned Opcode;
    std::vector<Constant*> ArgVec;
    ArgVec.reserve(isExprNumArgs);
    if (read_vbr(Buf, EndBuf, Opcode)) throw Error_readvbr;

    // Read the slot number and types of each of the arguments
    for (unsigned i = 0; i != isExprNumArgs; ++i) {
      unsigned ArgValSlot, ArgTypeSlot;
      if (read_vbr(Buf, EndBuf, ArgValSlot)) throw Error_readvbr;
      if (read_vbr(Buf, EndBuf, ArgTypeSlot)) throw Error_readvbr;
      BCR_TRACE(4, "CE Arg " << i << ": Type: '" << *getType(ArgTypeSlot)
                << "'  slot: " << ArgValSlot << "\n");

      // Get the arg value from its slot if it exists, otherwise a placeholder
      ArgVec.push_back(getConstantValue(ArgTypeSlot, ArgValSlot));
    }

    // Construct a ConstantExpr of the appropriate kind
    if (isExprNumArgs == 1) {           // All one-operand expressions
      assert(Opcode == Instruction::Cast);
      return ConstantExpr::getCast(ArgVec[0], getType(TypeID));
    } else if (Opcode == Instruction::GetElementPtr) { // GetElementPtr
      std::vector<Constant*> IdxList(ArgVec.begin()+1, ArgVec.end());
      return ConstantExpr::getGetElementPtr(ArgVec[0], IdxList);
    } else if (Opcode == Instruction::Shl || Opcode == Instruction::Shr) {
      return ConstantExpr::getShift(Opcode, ArgVec[0], ArgVec[1]);
    } else {                            // All other 2-operand expressions
      return ConstantExpr::get(Opcode, ArgVec[0], ArgVec[1]);
    }
  }

  // Ok, not an ConstantExpr.  We now know how to read the given type...
  const Type *Ty = getType(TypeID);
  switch (Ty->getPrimitiveID()) {
  case Type::BoolTyID: {
    unsigned Val;
    if (read_vbr(Buf, EndBuf, Val)) throw Error_readvbr;
    if (Val != 0 && Val != 1) throw std::string("Invalid boolean value read.");
    return ConstantBool::get(Val == 1);
  }

  case Type::UByteTyID:   // Unsigned integer types...
  case Type::UShortTyID:
  case Type::UIntTyID: {
    unsigned Val;
    if (read_vbr(Buf, EndBuf, Val)) throw Error_readvbr;
    if (!ConstantUInt::isValueValidForType(Ty, Val))
      throw std::string("Invalid unsigned byte/short/int read.");
    return ConstantUInt::get(Ty, Val);
  }

  case Type::ULongTyID: {
    uint64_t Val;
    if (read_vbr(Buf, EndBuf, Val)) throw Error_readvbr;
    return ConstantUInt::get(Ty, Val);
  }

  case Type::SByteTyID:   // Signed integer types...
  case Type::ShortTyID:
  case Type::IntTyID: {
  case Type::LongTyID:
    int64_t Val;
    if (read_vbr(Buf, EndBuf, Val)) throw Error_readvbr;
    if (!ConstantSInt::isValueValidForType(Ty, Val))
      throw std::string("Invalid signed byte/short/int/long read.");
    return ConstantSInt::get(Ty, Val);
  }

  case Type::FloatTyID: {
    float F;
    if (input_data(Buf, EndBuf, &F, &F+1)) throw Error_inputdata;
    return ConstantFP::get(Ty, F);
  }

  case Type::DoubleTyID: {
    double Val;
    if (input_data(Buf, EndBuf, &Val, &Val+1)) throw Error_inputdata;
    return ConstantFP::get(Ty, Val);
  }

  case Type::TypeTyID:
    throw std::string("Type constants shouldn't live in constant table!");

  case Type::ArrayTyID: {
    const ArrayType *AT = cast<ArrayType>(Ty);
    unsigned NumElements = AT->getNumElements();
    unsigned TypeSlot = getTypeSlot(AT->getElementType());
    std::vector<Constant*> Elements;
    while (NumElements--) {   // Read all of the elements of the constant.
      unsigned Slot;
      if (read_vbr(Buf, EndBuf, Slot)) throw Error_readvbr;
      Elements.push_back(getConstantValue(TypeSlot, Slot));
    }
    return ConstantArray::get(AT, Elements);
  }

  case Type::StructTyID: {
    const StructType *ST = cast<StructType>(Ty);
    const StructType::ElementTypes &ET = ST->getElementTypes();

    std::vector<Constant *> Elements;
    for (unsigned i = 0; i < ET.size(); ++i) {
      unsigned Slot;
      if (read_vbr(Buf, EndBuf, Slot)) throw Error_readvbr;
      Elements.push_back(getConstantValue(ET[i], Slot));
    }

    return ConstantStruct::get(ST, Elements);
  }

  case Type::PointerTyID: {  // ConstantPointerRef value...
    const PointerType *PT = cast<PointerType>(Ty);
    unsigned Slot;
    if (read_vbr(Buf, EndBuf, Slot)) throw Error_readvbr;
    BCR_TRACE(4, "CPR: Type: '" << Ty << "'  slot: " << Slot << "\n");

    // Check to see if we have already read this global variable...
    Value *Val = getValue(TypeID, Slot, false);
    GlobalValue *GV;
    if (Val) {
      if (!(GV = dyn_cast<GlobalValue>(Val)))
        throw std::string("Value of ConstantPointerRef not in ValueTable!");
      BCR_TRACE(5, "Value Found in ValueTable!\n");
    } else {
      throw std::string("Forward references are not allowed here.");
    }

    return ConstantPointerRef::get(GV);
  }

  default:
    throw std::string("Don't know how to deserialize constant value of type '"+
                      Ty->getDescription());
  }
}

void BytecodeParser::ParseGlobalTypes(const unsigned char *&Buf,
                                      const unsigned char *EndBuf) {
  ValueTable T;
  ParseConstantPool(Buf, EndBuf, T, ModuleTypeValues);
}

void BytecodeParser::ParseConstantPool(const unsigned char *&Buf,
                                       const unsigned char *EndBuf,
                                       ValueTable &Tab,
                                       TypeValuesListTy &TypeTab) {
  while (Buf < EndBuf) {
    unsigned NumEntries, Typ;

    if (read_vbr(Buf, EndBuf, NumEntries) ||
        read_vbr(Buf, EndBuf, Typ)) throw Error_readvbr;
    if (Typ == Type::TypeTyID) {
      BCR_TRACE(3, "Type: 'type'  NumEntries: " << NumEntries << "\n");
      parseTypeConstants(Buf, EndBuf, TypeTab, NumEntries);
    } else {
      BCR_TRACE(3, "Type: '" << *getType(Typ) << "'  NumEntries: "
                << NumEntries << "\n");

      for (unsigned i = 0; i < NumEntries; ++i) {
        Constant *C = parseConstantValue(Buf, EndBuf, Typ);
        assert(C && "parseConstantValue returned NULL!");
        BCR_TRACE(4, "Read Constant: '" << *C << "'\n");
        unsigned Slot = insertValue(C, Typ, Tab);

        // If we are reading a function constant table, make sure that we adjust
        // the slot number to be the real global constant number.
        //
        if (&Tab != &ModuleValues && Typ < ModuleValues.size() &&
            ModuleValues[Typ])
          Slot += ModuleValues[Typ]->size();
        ResolveReferencesToConstant(C, Slot);
      }
    }
  }

  if (Buf > EndBuf) throw std::string("Read past end of buffer.");
}
<|endoftext|>


<commit_before>// Copyright (c) Paul Hodge. See LICENSE file for license terms.

#include "common_headers.h"

#include <cstdlib>
#include <iostream>
#include <dirent.h>
#include <sys/stat.h>

#include "branch.h"
#include "file_checker.h"
#include "source_repro.h"
#include "storage.h"
#include "tagged_value.h"
#include "types/list.h"

namespace circa {

int run_file_checker_for_directory(const char* dir);

void run_file_checker(const char* filename, List* errors)
{
    Branch branch;
    parse_script(branch, filename);

    // Fetch the file as a string
    std::string actualSource;
    {
        TaggedValue fileContents;
        TaggedValue fileReadError;
        storage::read_text_file_to_value(filename, &fileContents, &fileReadError);
        if (!is_null(&fileReadError)) {
            std::stringstream msg;
            msg << "File read error: " << fileReadError.toString();
            errors->appendString(msg.str());
            return;
        }
        actualSource = as_cstring(&fileContents);
    }

    // Run a source-repro test
    std::string reproducedSource = get_branch_source_text(branch);

    if (actualSource != reproducedSource) {
        // TODO: Provide more details about the source repro problem.
        errors->appendString("Source reproduction failed");
    }
}

int run_file_checker(const char* filename)
{
    // check if this is a directory
    struct stat st_buf;
    int status = stat(filename, &st_buf);
    if ((status == 0) && S_ISDIR(st_buf.st_mode))
        return run_file_checker_for_directory(filename);

    List errors;
    run_file_checker(filename, &errors);
    if (is_null(&errors) || errors.empty())
        return 0;

    std::cout << filename << " had " << errors.length() << " error(s):\n";

    for (int i=0; i < errors.length(); i++)
        std::cout << as_cstring(errors[i]) << std::endl;

    return -1;
}

int run_file_checker_for_directory(const char* filename)
{
    DIR* dir = opendir(filename);
    if (dir == NULL) {
        std::cout << "failed to open directory: " << filename << std::endl;
        return -1;
    }

    int finalResult = 0;
    while (true) {
        struct dirent *ent = readdir(dir);
        if (ent == NULL)
            break;

        std::string path(ent->d_name);

        if (path == "." || path == "..")
            continue;

        path = std::string(filename) + "/" + path;

        // recurse on directories
        struct stat st_buf;
        int status = stat(path.c_str(), &st_buf);
        if ((status == 0) && S_ISDIR(st_buf.st_mode)) {
            int result = run_file_checker_for_directory(path.c_str());
            if (result != 0)
                finalResult = -1;
            continue;
        }

        // skip if it doesn't end in .ca
        if (path.rfind(".ca") != (path.length() - 3)) {
            continue;
        }

        int result = run_file_checker(path.c_str());
        if (result != 0)
            finalResult = -1;
        else
            std::cout << "Passed: " << path << std::endl;
    }
    closedir(dir);
    return finalResult;
}

} // namespace circa
<commit_msg>circa -check now also prints static errors<commit_after>// Copyright (c) Paul Hodge. See LICENSE file for license terms.

#include "common_headers.h"

#include <cstdlib>
#include <iostream>
#include <dirent.h>
#include <sys/stat.h>

#include "branch.h"
#include "file_checker.h"
#include "source_repro.h"
#include "static_checking.h"
#include "storage.h"
#include "tagged_value.h"
#include "types/list.h"

namespace circa {

int run_file_checker_for_directory(const char* dir);

void run_file_checker(const char* filename, List* errors)
{
    Branch branch;
    parse_script(branch, filename);

    // Catch static errors
    {
        List staticErrors;
        check_for_static_errors(&staticErrors, branch);
        for (int i=0; i < staticErrors.length(); i++)
            format_static_error(staticErrors[i], errors->append());
    }

    // Fetch the file as a string
    std::string actualSource;
    {
        TaggedValue fileContents;
        TaggedValue fileReadError;
        storage::read_text_file_to_value(filename, &fileContents, &fileReadError);
        if (!is_null(&fileReadError)) {
            std::stringstream msg;
            msg << "File read error: " << fileReadError.toString();
            errors->appendString(msg.str());
            return;
        }
        actualSource = as_cstring(&fileContents);
    }

    // Run a source-repro test
    std::string reproducedSource = get_branch_source_text(branch);

    if (actualSource != reproducedSource) {
        // TODO: Provide more details about the source repro problem.
        errors->appendString("Source reproduction failed");
    }
}

int run_file_checker(const char* filename)
{
    // check if this is a directory
    struct stat st_buf;
    int status = stat(filename, &st_buf);
    if ((status == 0) && S_ISDIR(st_buf.st_mode))
        return run_file_checker_for_directory(filename);

    List errors;
    run_file_checker(filename, &errors);
    if (is_null(&errors) || errors.empty())
        return 0;

    std::cout << filename << " had " << errors.length() << " error(s):\n";

    for (int i=0; i < errors.length(); i++)
        std::cout << as_cstring(errors[i]) << std::endl;

    return -1;
}

int run_file_checker_for_directory(const char* filename)
{
    DIR* dir = opendir(filename);
    if (dir == NULL) {
        std::cout << "failed to open directory: " << filename << std::endl;
        return -1;
    }

    int finalResult = 0;
    while (true) {
        struct dirent *ent = readdir(dir);
        if (ent == NULL)
            break;

        std::string path(ent->d_name);

        if (path == "." || path == "..")
            continue;

        path = std::string(filename) + "/" + path;

        // recurse on directories
        struct stat st_buf;
        int status = stat(path.c_str(), &st_buf);
        if ((status == 0) && S_ISDIR(st_buf.st_mode)) {
            int result = run_file_checker_for_directory(path.c_str());
            if (result != 0)
                finalResult = -1;
            continue;
        }

        // skip if it doesn't end in .ca
        if (path.rfind(".ca") != (path.length() - 3)) {
            continue;
        }

        int result = run_file_checker(path.c_str());
        if (result != 0)
            finalResult = -1;
        else
            std::cout << "Passed: " << path << std::endl;
    }
    closedir(dir);
    return finalResult;
}

} // namespace circa
<|endoftext|>


<commit_before>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * HDFMixer.cpp
 *
 *  Created on: Dec 19, 2016
 *      Author: Junmin GU
 */

#include "HDFMixer.h"
#include "HDFMixer.tcc"

#include "adios2/ADIOSMPI.h"
#include "adios2/core/IO.h"
#include "adios2/helper/adiosFunctions.h" //CheckIndexRange
#include "adios2/toolkit/transport/file/FileFStream.h"

namespace adios2
{
namespace core
{
namespace engine
{

HDFMixer::HDFMixer(IO &io, const std::string &name, const Mode openMode,
                   MPI_Comm mpiComm)
: Engine("HDFMixer", io, name, openMode, mpiComm),
  m_HDFVDSWriter(mpiComm, m_DebugMode),
  m_HDFSerialWriter(MPI_COMM_SELF, m_DebugMode),
  m_TransportsManager(mpiComm, m_DebugMode)
{
    m_EndMessage = " in call to IO Open HDFMixer " + m_Name + "\n";
    Init();
}

HDFMixer::~HDFMixer() = default;

void HDFMixer::Init()
{
    InitParameters();
    InitTransports();
    InitBuffer();
}

#define declare_type(T)                                                        \
    void HDFMixer::DoPutSync(Variable<T> &variable, const T *values)           \
    {                                                                          \
        DoPutSyncCommon(variable, values);                                     \
    }                                                                          \
    void HDFMixer::DoPutDeferred(Variable<T> &variable, const T *values)       \
    {                                                                          \
        DoPutSyncCommon(variable, values);                                     \
    }
ADIOS2_FOREACH_TYPE_1ARG(declare_type)
#undef declare_type

StepStatus HDFMixer::BeginStep(StepMode mode, const float timeout_sec)
{
    return StepStatus::OK;
}

void HDFMixer::PerformPuts() {}

// void HDFMixer::Advance(const float /*timeout_sec*/)
// void HDFMixer::EndStep(const float /*timeout_sec*/)
void HDFMixer::EndStep()
{
    m_HDFSerialWriter.Advance();
    m_HDFVDSWriter.Advance();
}

// PRIVATE FUNCTIONS
void HDFMixer::InitParameters()
{
    // no need for hdf5
    // m_HDFSerialWriter.InitParameters(m_IO.m_Parameters);
}

void HDFMixer::InitTransports()
{
    if (m_IO.m_TransportsParameters.empty())
    {
        Params defaultTransportParameters;
        defaultTransportParameters["transport"] = "File";
        m_IO.m_TransportsParameters.push_back(defaultTransportParameters);
    }

#ifdef NEVER
/*
  // TODO need to add support for aggregators here later

  // Names are std::vector<std::string>
  auto transportsNames = m_TransportsManager.GetFilesBaseNames(
      m_Name, m_IO.m_TransportsParameters);
  auto bpBaseNames = m_HDFSerialWriter.GetBPBaseNames(transportsNames);
  auto bpNames = m_HDFSerialWriter.GetBPNames(transportsNames);

  m_TransportsManager.OpenFiles(bpBaseNames, bpNames, m_OpenMode,
                                m_IO.m_TransportsParameters,
                                m_HDFSerialWriter.m_Profiler.IsActive);
*/
#else

    int rank;
    MPI_Comm_rank(m_MPIComm, &rank);
    m_HDFSerialWriter.Init(m_Name, rank);
    m_HDFVDSWriter.Init(m_Name);
/*
auto transportsNames = m_TransportsManager.GetFilesBaseNames(
                                                             m_Name,
m_IO.m_TransportsParameters); auto baseNames =
m_HDFSerialWriter.GetBaseNames(transportsNames);

auto h5name =  m_HDFSerialWriter.GetLocalFileNames(baseNames, m_Name); // e.g.
base=/my/path/xy_1.h5 m_TransportsManager.OpenFiles(baseNames, h5name,
m_OpenMode, m_IO.m_TransportsParameters, m_HDFSerialWriter.m_Profiler.IsActive);
*/
#endif
}

void HDFMixer::InitBuffer()
{
    /*
      if (m_OpenMode == OpenMode::Append)
      {
          throw std::invalid_argument(
              "ADIOS2: OpenMode Append hasn't been implemented, yet");
          // TODO: Get last pg timestep and update timestep counter in
      }
      else
      {
        m_HDFSerialWriter.WriteProcessGroupIndex(
                                                 m_IO.m_HostLanguage,
      m_TransportsManager.GetTransportsTypes());
      }
    */
}

void HDFMixer::WriteProfilingJSONFile()
{ /*
auto transportTypes = m_TransportsManager.GetTransportsTypes();
auto transportProfilers = m_TransportsManager.GetTransportsProfilers();

const std::string lineJSON(
m_HDFSerialWriter.GetRankProfilingJSON(transportTypes,
transportProfilers));

const std::string profilingJSON(
m_HDFSerialWriter.AggregateProfilingJSON(lineJSON));

//if (m_HDFSerialWriter.m_BP1Aggregator.m_RankMPI == 0)
if (m_HDFSerialWriter.m_MPIRank == 0)
{
transport::FileStream profilingJSONStream(m_MPIComm, m_DebugMode);
auto baseNames = m_HDFSerialWriter.GetBaseNames({m_Name});
profilingJSONStream.Open(baseNames[0] + "/profiling.json",
OpenMode::Write);
profilingJSONStream.Write(profilingJSON.c_str(), profilingJSON.size());
profilingJSONStream.Close();
}
*/
}

void HDFMixer::DoClose(const int transportIndex)
{
    /*if (m_DebugMode)
      {
          if (!m_TransportsManager.CheckTransportIndex(transportIndex))
          {
              auto transportsSize = m_TransportsManager.m_Transports.size();
              throw std::invalid_argument(
                  "ERROR: transport index " + std::to_string(transportIndex) +
                  " outside range, -1 (default) to " +
                  std::to_string(transportsSize - 1) + ", in call to Close\n");
          }
      }
    */
    // close bp buffer by flattening data and metadata
    m_HDFSerialWriter.Close();
    m_HDFVDSWriter.Close();
    // send data to corresponding transports
    /*
    m_TransportsManager.WriteFiles(m_HDFSerialWriter.m_HeapBuffer.GetData(),
                                   m_HDFSerialWriter.m_HeapBuffer.m_DataPosition,
                                   transportIndex);

    m_TransportsManager.CloseFiles(transportIndex);
    */
    /*
      // do profiling later
    if (m_HDFSerialWriter.m_Profiler.IsActive &&
        m_TransportsManager.AllTransportsClosed())
    {
        WriteProfilingJSONFile();
    }
    */
}

} // end namespace engine
} // end namespace core
} // end namespace adios2
<commit_msg>clang-format<commit_after>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * HDFMixer.cpp
 *
 *  Created on: Dec 19, 2016
 *      Author: Junmin GU
 */

#include "HDFMixer.h"
#include "HDFMixer.tcc"

#include "adios2/ADIOSMPI.h"
#include "adios2/core/IO.h"
#include "adios2/helper/adiosFunctions.h" //CheckIndexRange
#include "adios2/toolkit/transport/file/FileFStream.h"

namespace adios2
{
namespace core
{
namespace engine
{

HDFMixer::HDFMixer(IO &io, const std::string &name, const Mode openMode,
                   MPI_Comm mpiComm)
: Engine("HDFMixer", io, name, openMode, mpiComm),
  m_HDFVDSWriter(mpiComm, m_DebugMode),
  m_HDFSerialWriter(MPI_COMM_SELF, m_DebugMode),
  m_TransportsManager(mpiComm, m_DebugMode)
{
    m_EndMessage = " in call to IO Open HDFMixer " + m_Name + "\n";
    Init();
}

HDFMixer::~HDFMixer() = default;

void HDFMixer::Init()
{
    InitParameters();
    InitTransports();
    InitBuffer();
}

#define declare_type(T)                                                        \
    void HDFMixer::DoPutSync(Variable<T> &variable, const T *values)           \
    {                                                                          \
        DoPutSyncCommon(variable, values);                                     \
    }                                                                          \
    void HDFMixer::DoPutDeferred(Variable<T> &variable, const T *values)       \
    {                                                                          \
        DoPutSyncCommon(variable, values);                                     \
    }
ADIOS2_FOREACH_TYPE_1ARG(declare_type)
#undef declare_type

StepStatus HDFMixer::BeginStep(StepMode mode, const float timeout_sec)
{
    return StepStatus::OK;
}

void HDFMixer::PerformPuts() {}

// void HDFMixer::Advance(const float /*timeout_sec*/)
// void HDFMixer::EndStep(const float /*timeout_sec*/)
void HDFMixer::EndStep()
{
    m_HDFSerialWriter.Advance();
    m_HDFVDSWriter.Advance();
}

// PRIVATE FUNCTIONS
void HDFMixer::InitParameters()
{
    // no need for hdf5
    // m_HDFSerialWriter.InitParameters(m_IO.m_Parameters);
}

void HDFMixer::InitTransports()
{
    if (m_IO.m_TransportsParameters.empty())
    {
        Params defaultTransportParameters;
        defaultTransportParameters["transport"] = "File";
        m_IO.m_TransportsParameters.push_back(defaultTransportParameters);
    }

#ifdef NEVER
/*
  // TODO need to add support for aggregators here later

  // Names are std::vector<std::string>
  auto transportsNames = m_TransportsManager.GetFilesBaseNames(
      m_Name, m_IO.m_TransportsParameters);
  auto bpBaseNames = m_HDFSerialWriter.GetBPBaseNames(transportsNames);
  auto bpNames = m_HDFSerialWriter.GetBPNames(transportsNames);

  m_TransportsManager.OpenFiles(bpBaseNames, bpNames, m_OpenMode,
                                m_IO.m_TransportsParameters,
                                m_HDFSerialWriter.m_Profiler.IsActive);
*/
#else

    int rank;
    MPI_Comm_rank(m_MPIComm, &rank);
    m_HDFSerialWriter.Init(m_Name, rank);
    m_HDFVDSWriter.Init(m_Name);
/*
auto transportsNames = m_TransportsManager.GetFilesBaseNames(
                                                             m_Name,
m_IO.m_TransportsParameters); auto baseNames =
m_HDFSerialWriter.GetBaseNames(transportsNames);

auto h5name =  m_HDFSerialWriter.GetLocalFileNames(baseNames, m_Name); // e.g.
base=/my/path/xy_1.h5 m_TransportsManager.OpenFiles(baseNames, h5name,
m_OpenMode, m_IO.m_TransportsParameters, m_HDFSerialWriter.m_Profiler.IsActive);
*/
#endif
}

void HDFMixer::InitBuffer()
{
    /*
      if (m_OpenMode == OpenMode::Append)
      {
          throw std::invalid_argument(
              "ADIOS2: OpenMode Append hasn't been implemented, yet");
          // TODO: Get last pg timestep and update timestep counter in
      }
      else
      {
        m_HDFSerialWriter.WriteProcessGroupIndex(
                                                 m_IO.m_HostLanguage,
      m_TransportsManager.GetTransportsTypes());
      }
    */
}

void HDFMixer::WriteProfilingJSONFile() {}

void HDFMixer::DoClose(const int transportIndex)
{
    m_HDFSerialWriter.Close();
    m_HDFVDSWriter.Close();
}

} // end namespace engine
} // end namespace core
} // end namespace adios2
<|endoftext|>


<commit_before>/*
 * File:   NetworkThread.cpp
 * Author: matthieu
 *
 * Created on 6 février 2015, 11:40
 */

#include "NetworkThread.h"
#include "RecalboxSystem.h"
#include "guis/GuiMsgBox.h"

NetworkThread::NetworkThread(Window* window) : mWindow(window){

    // creer le thread
    mFirstRun = true;
    mRunning = true;
    mThreadHandle = new boost::thread(boost::bind(&NetworkThread::run, this));

}

NetworkThread::~NetworkThread() {
    	mThreadHandle->join();
}

void NetworkThread::run(){
    while(mRunning){
        if(mFirstRun){
            boost::this_thread::sleep(boost::posix_time::seconds(15));
            mFirstRun = false;
        }else {
            boost::this_thread::sleep(boost::posix_time::hours(1));
        }

	if(RecalboxConf::getInstance()->get("updates.enabled") == "1") {
	  if(RecalboxSystem::getInstance()->canUpdate()){
	    mWindow->displayMessage("AN UPDATE IS AVAILABLE FOR YOUR RECALBOX");
	    mRunning = false;
	  }
	}
    }
}

<commit_msg>fixed RecalboxConfig includes<commit_after>/*
 * File:   NetworkThread.cpp
 * Author: matthieu
 *
 * Created on 6 février 2015, 11:40
 */

#include "NetworkThread.h"
#include "RecalboxSystem.h"
#include "RecalboxConfig.h"
#include "guis/GuiMsgBox.h"

NetworkThread::NetworkThread(Window* window) : mWindow(window){

    // creer le thread
    mFirstRun = true;
    mRunning = true;
    mThreadHandle = new boost::thread(boost::bind(&NetworkThread::run, this));

}

NetworkThread::~NetworkThread() {
    	mThreadHandle->join();
}

void NetworkThread::run(){
    while(mRunning){
        if(mFirstRun){
            boost::this_thread::sleep(boost::posix_time::seconds(15));
            mFirstRun = false;
        }else {
            boost::this_thread::sleep(boost::posix_time::hours(1));
        }

	if(RecalboxConf::getInstance()->get("updates.enabled") == "1") {
	  if(RecalboxSystem::getInstance()->canUpdate()){
	    mWindow->displayMessage("AN UPDATE IS AVAILABLE FOR YOUR RECALBOX");
	    mRunning = false;
	  }
	}
    }
}

<|endoftext|>