<commit_before>//===--- Compilation.cpp - Compilation Task Implementation ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Driver/Compilation.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang::driver;
using namespace clang;
using namespace llvm::opt;

Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain,
                         InputArgList *_Args, DerivedArgList *_TranslatedArgs,
                         bool ContainsError)
    : TheDriver(D), DefaultToolChain(_DefaultToolChain), ActiveOffloadMask(0u),
      Args(_Args), TranslatedArgs(_TranslatedArgs), Redirects(nullptr),
      ForDiagnostics(false), ContainsError(ContainsError) {
  // The offloading host toolchain is the default tool chain.
  OrderedOffloadingToolchains.insert(
      std::make_pair(Action::OFK_Host, &DefaultToolChain));
}

Compilation::~Compilation() {
  delete TranslatedArgs;
  delete Args;

  // Free any derived arg lists.
  for (auto Arg : TCArgs)
    if (Arg.second != TranslatedArgs)
      delete Arg.second;

  // Free redirections of stdout/stderr.
  if (Redirects) {
    delete Redirects[0];
    delete Redirects[1];
    delete Redirects[2];
    delete [] Redirects;
  }
}

const DerivedArgList &
Compilation::getArgsForToolChain(const ToolChain *TC, StringRef BoundArch,
                                 Action::OffloadKind DeviceOffloadKind) {
  if (!TC)
    TC = &DefaultToolChain;

  DerivedArgList *&Entry = TCArgs[{TC, BoundArch, DeviceOffloadKind}];
  if (!Entry) {
    // Translate OpenMP toolchain arguments provided via the -Xopenmp-target flags.
    Entry = TC->TranslateOpenMPTargetArgs(*TranslatedArgs, DeviceOffloadKind);
    if (!Entry)
      Entry = TranslatedArgs;

    Entry = TC->TranslateArgs(*Entry, BoundArch, DeviceOffloadKind);
    if (!Entry)
      Entry = TranslatedArgs;
  }

  return *Entry;
}

bool Compilation::CleanupFile(const char *File, bool IssueErrors) const {
  // FIXME: Why are we trying to remove files that we have not created? For
  // example we should only try to remove a temporary assembly file if
  // "clang -cc1" succeed in writing it. Was this a workaround for when
  // clang was writing directly to a .s file and sometimes leaving it behind
  // during a failure?

  // FIXME: If this is necessary, we can still try to split
  // llvm::sys::fs::remove into a removeFile and a removeDir and avoid the
  // duplicated stat from is_regular_file.

  // Don't try to remove files which we don't have write access to (but may be
  // able to remove), or non-regular files. Underlying tools may have
  // intentionally not overwritten them.
  if (!llvm::sys::fs::can_write(File) || !llvm::sys::fs::is_regular_file(File))
    return true;

  if (std::error_code EC = llvm::sys::fs::remove(File)) {
    // Failure is only failure if the file exists and is "regular". We checked
    // for it being regular before, and llvm::sys::fs::remove ignores ENOENT,
    // so we don't need to check again.

    if (IssueErrors)
      getDriver().Diag(clang::diag::err_drv_unable_to_remove_file)
        << EC.message();
    return false;
  }
  return true;
}

bool Compilation::CleanupFileList(const ArgStringList &Files,
                                  bool IssueErrors) const {
  bool Success = true;
  for (ArgStringList::const_iterator
         it = Files.begin(), ie = Files.end(); it != ie; ++it)
    Success &= CleanupFile(*it, IssueErrors);
  return Success;
}

bool Compilation::CleanupFileMap(const ArgStringMap &Files,
                                 const JobAction *JA,
                                 bool IssueErrors) const {
  bool Success = true;
  for (ArgStringMap::const_iterator
         it = Files.begin(), ie = Files.end(); it != ie; ++it) {

    // If specified, only delete the files associated with the JobAction.
    // Otherwise, delete all files in the map.
    if (JA && it->first != JA)
      continue;
    Success &= CleanupFile(it->second, IssueErrors);
  }
  return Success;
}

int Compilation::ExecuteCommand(const Command &C,
                                const Command *&FailingCommand) const {
  if ((getDriver().CCPrintOptions ||
       getArgs().hasArg(options::OPT_v)) && !getDriver().CCGenDiagnostics) {
    raw_ostream *OS = &llvm::errs();

    // Follow gcc implementation of CC_PRINT_OPTIONS; we could also cache the
    // output stream.
    if (getDriver().CCPrintOptions && getDriver().CCPrintOptionsFilename) {
      std::error_code EC;
      OS = new llvm::raw_fd_ostream(getDriver().CCPrintOptionsFilename, EC,
                                    llvm::sys::fs::F_Append |
                                        llvm::sys::fs::F_Text);
      if (EC) {
        getDriver().Diag(clang::diag::err_drv_cc_print_options_failure)
            << EC.message();
        FailingCommand = &C;
        delete OS;
        return 1;
      }
    }

    if (getDriver().CCPrintOptions)
      *OS << "[Logging clang options]";

    C.Print(*OS, "\n", /*Quote=*/getDriver().CCPrintOptions);

    if (OS != &llvm::errs())
      delete OS;
  }

  std::string Error;
  bool ExecutionFailed;
  int Res = C.Execute(Redirects, &Error, &ExecutionFailed);
  if (!Error.empty()) {
    assert(Res && "Error string set with 0 result code!");
    getDriver().Diag(clang::diag::err_drv_command_failure) << Error;
  }

  if (Res)
    FailingCommand = &C;

  return ExecutionFailed ? 1 : Res;
}

void Compilation::ExecuteJobs(
    const JobList &Jobs,
    SmallVectorImpl<std::pair<int, const Command *>> &FailingCommands) const {
  for (const auto &Job : Jobs) {
    const Command *FailingCommand = nullptr;
    if (int Res = ExecuteCommand(Job, FailingCommand)) {
      FailingCommands.push_back(std::make_pair(Res, FailingCommand));
      // Bail as soon as one command fails, so we don't output duplicate error
      // messages if we die on e.g. the same file.
      return;
    }
  }
}

void Compilation::initCompilationForDiagnostics() {
  ForDiagnostics = true;

  // Free actions and jobs.
  Actions.clear();
  AllActions.clear();
  Jobs.clear();

  // Clear temporary/results file lists.
  TempFiles.clear();
  ResultFiles.clear();
  FailureResultFiles.clear();

  // Remove any user specified output.  Claim any unclaimed arguments, so as
  // to avoid emitting warnings about unused args.
  OptSpecifier OutputOpts[] = { options::OPT_o, options::OPT_MD,
                                options::OPT_MMD };
  for (unsigned i = 0, e = llvm::array_lengthof(OutputOpts); i != e; ++i) {
    if (TranslatedArgs->hasArg(OutputOpts[i]))
      TranslatedArgs->eraseArg(OutputOpts[i]);
  }
  TranslatedArgs->ClaimAllArgs();

  // Redirect stdout/stderr to /dev/null.
  Redirects = new const StringRef*[3]();
  Redirects[0] = nullptr;
  Redirects[1] = new StringRef();
  Redirects[2] = new StringRef();
}

StringRef Compilation::getSysRoot() const {
  return getDriver().SysRoot;
}

void Compilation::Redirect(const StringRef** Redirects) {
  this->Redirects = Redirects;
}
<commit_msg>Non-functional change. Fix previous patch D34784.<commit_after>//===--- Compilation.cpp - Compilation Task Implementation ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Driver/Compilation.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang::driver;
using namespace clang;
using namespace llvm::opt;

Compilation::Compilation(const Driver &D, const ToolChain &_DefaultToolChain,
                         InputArgList *_Args, DerivedArgList *_TranslatedArgs,
                         bool ContainsError)
    : TheDriver(D), DefaultToolChain(_DefaultToolChain), ActiveOffloadMask(0u),
      Args(_Args), TranslatedArgs(_TranslatedArgs), Redirects(nullptr),
      ForDiagnostics(false), ContainsError(ContainsError) {
  // The offloading host toolchain is the default tool chain.
  OrderedOffloadingToolchains.insert(
      std::make_pair(Action::OFK_Host, &DefaultToolChain));
}

Compilation::~Compilation() {
  delete TranslatedArgs;
  delete Args;

  // Free any derived arg lists.
  for (auto Arg : TCArgs)
    if (Arg.second != TranslatedArgs)
      delete Arg.second;

  // Free redirections of stdout/stderr.
  if (Redirects) {
    delete Redirects[0];
    delete Redirects[1];
    delete Redirects[2];
    delete [] Redirects;
  }
}

const DerivedArgList &
Compilation::getArgsForToolChain(const ToolChain *TC, StringRef BoundArch,
                                 Action::OffloadKind DeviceOffloadKind) {
  if (!TC)
    TC = &DefaultToolChain;

  DerivedArgList *&Entry = TCArgs[{TC, BoundArch, DeviceOffloadKind}];
  if (!Entry) {
    // Translate OpenMP toolchain arguments provided via the -Xopenmp-target flags.
    DerivedArgList *OpenMPArgs = TC->TranslateOpenMPTargetArgs(*TranslatedArgs,
        DeviceOffloadKind);
    if (!OpenMPArgs) {
      Entry = TC->TranslateArgs(*TranslatedArgs, BoundArch, DeviceOffloadKind);
    } else {
      Entry = TC->TranslateArgs(*OpenMPArgs, BoundArch, DeviceOffloadKind);
      delete OpenMPArgs;
    }

    if (!Entry)
      Entry = TranslatedArgs;
  }

  return *Entry;
}

bool Compilation::CleanupFile(const char *File, bool IssueErrors) const {
  // FIXME: Why are we trying to remove files that we have not created? For
  // example we should only try to remove a temporary assembly file if
  // "clang -cc1" succeed in writing it. Was this a workaround for when
  // clang was writing directly to a .s file and sometimes leaving it behind
  // during a failure?

  // FIXME: If this is necessary, we can still try to split
  // llvm::sys::fs::remove into a removeFile and a removeDir and avoid the
  // duplicated stat from is_regular_file.

  // Don't try to remove files which we don't have write access to (but may be
  // able to remove), or non-regular files. Underlying tools may have
  // intentionally not overwritten them.
  if (!llvm::sys::fs::can_write(File) || !llvm::sys::fs::is_regular_file(File))
    return true;

  if (std::error_code EC = llvm::sys::fs::remove(File)) {
    // Failure is only failure if the file exists and is "regular". We checked
    // for it being regular before, and llvm::sys::fs::remove ignores ENOENT,
    // so we don't need to check again.

    if (IssueErrors)
      getDriver().Diag(clang::diag::err_drv_unable_to_remove_file)
        << EC.message();
    return false;
  }
  return true;
}

bool Compilation::CleanupFileList(const ArgStringList &Files,
                                  bool IssueErrors) const {
  bool Success = true;
  for (ArgStringList::const_iterator
         it = Files.begin(), ie = Files.end(); it != ie; ++it)
    Success &= CleanupFile(*it, IssueErrors);
  return Success;
}

bool Compilation::CleanupFileMap(const ArgStringMap &Files,
                                 const JobAction *JA,
                                 bool IssueErrors) const {
  bool Success = true;
  for (ArgStringMap::const_iterator
         it = Files.begin(), ie = Files.end(); it != ie; ++it) {

    // If specified, only delete the files associated with the JobAction.
    // Otherwise, delete all files in the map.
    if (JA && it->first != JA)
      continue;
    Success &= CleanupFile(it->second, IssueErrors);
  }
  return Success;
}

int Compilation::ExecuteCommand(const Command &C,
                                const Command *&FailingCommand) const {
  if ((getDriver().CCPrintOptions ||
       getArgs().hasArg(options::OPT_v)) && !getDriver().CCGenDiagnostics) {
    raw_ostream *OS = &llvm::errs();

    // Follow gcc implementation of CC_PRINT_OPTIONS; we could also cache the
    // output stream.
    if (getDriver().CCPrintOptions && getDriver().CCPrintOptionsFilename) {
      std::error_code EC;
      OS = new llvm::raw_fd_ostream(getDriver().CCPrintOptionsFilename, EC,
                                    llvm::sys::fs::F_Append |
                                        llvm::sys::fs::F_Text);
      if (EC) {
        getDriver().Diag(clang::diag::err_drv_cc_print_options_failure)
            << EC.message();
        FailingCommand = &C;
        delete OS;
        return 1;
      }
    }

    if (getDriver().CCPrintOptions)
      *OS << "[Logging clang options]";

    C.Print(*OS, "\n", /*Quote=*/getDriver().CCPrintOptions);

    if (OS != &llvm::errs())
      delete OS;
  }

  std::string Error;
  bool ExecutionFailed;
  int Res = C.Execute(Redirects, &Error, &ExecutionFailed);
  if (!Error.empty()) {
    assert(Res && "Error string set with 0 result code!");
    getDriver().Diag(clang::diag::err_drv_command_failure) << Error;
  }

  if (Res)
    FailingCommand = &C;

  return ExecutionFailed ? 1 : Res;
}

void Compilation::ExecuteJobs(
    const JobList &Jobs,
    SmallVectorImpl<std::pair<int, const Command *>> &FailingCommands) const {
  for (const auto &Job : Jobs) {
    const Command *FailingCommand = nullptr;
    if (int Res = ExecuteCommand(Job, FailingCommand)) {
      FailingCommands.push_back(std::make_pair(Res, FailingCommand));
      // Bail as soon as one command fails, so we don't output duplicate error
      // messages if we die on e.g. the same file.
      return;
    }
  }
}

void Compilation::initCompilationForDiagnostics() {
  ForDiagnostics = true;

  // Free actions and jobs.
  Actions.clear();
  AllActions.clear();
  Jobs.clear();

  // Clear temporary/results file lists.
  TempFiles.clear();
  ResultFiles.clear();
  FailureResultFiles.clear();

  // Remove any user specified output.  Claim any unclaimed arguments, so as
  // to avoid emitting warnings about unused args.
  OptSpecifier OutputOpts[] = { options::OPT_o, options::OPT_MD,
                                options::OPT_MMD };
  for (unsigned i = 0, e = llvm::array_lengthof(OutputOpts); i != e; ++i) {
    if (TranslatedArgs->hasArg(OutputOpts[i]))
      TranslatedArgs->eraseArg(OutputOpts[i]);
  }
  TranslatedArgs->ClaimAllArgs();

  // Redirect stdout/stderr to /dev/null.
  Redirects = new const StringRef*[3]();
  Redirects[0] = nullptr;
  Redirects[1] = new StringRef();
  Redirects[2] = new StringRef();
}

StringRef Compilation::getSysRoot() const {
  return getDriver().SysRoot;
}

void Compilation::Redirect(const StringRef** Redirects) {
  this->Redirects = Redirects;
}
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2015-2017 Esteban Tovagliari, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "directionaldipolebssrdf.h"

// appleseed.renderer headers.
#include "renderer/global/globaltypes.h"
#include "renderer/kernel/shading/shadingpoint.h"
#include "renderer/modeling/bssrdf/dipolebssrdf.h"
#include "renderer/modeling/bssrdf/sss.h"

// appleseed.foundation headers.
#include "foundation/math/fresnel.h"
#include "foundation/math/scalar.h"
#include "foundation/math/vector.h"
#include "foundation/utility/containers/dictionary.h"

// Standard headers.
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstddef>

// Forward declarations.
namespace foundation    { class Arena; }

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    //
    // Directional dipole BSSRDF.
    //
    // References:
    //
    //   [1] Directional Dipole Model for Subsurface Scattering
    //       Jeppe Revall Frisvad, Toshiya Hachisuka, Thomas Kim Kjeldsen
    //       http://www.ci.i.u-tokyo.ac.jp/~hachisuka/dirpole.pdf
    //
    //   [2] Directional Dipole for Subsurface Scattering in Translucent Materials
    //       Jeppe Revall Frisvad, Toshiya Hachisuka, Thomas Kim Kjeldsen
    //       http://www.ci.i.u-tokyo.ac.jp/~hachisuka/dirpole_tr.pdf
    //

    const char* Model = "directional_dipole_bssrdf";

    class DirectionalDipoleBSSRDF
      : public DipoleBSSRDF
    {
      public:
        DirectionalDipoleBSSRDF(
            const char*                     name,
            const ParamArray&               params)
          : DipoleBSSRDF(name, params)
        {
        }

        virtual void release() APPLESEED_OVERRIDE
        {
            delete this;
        }

        virtual const char* get_model() const APPLESEED_OVERRIDE
        {
            return Model;
        }

        virtual void prepare_inputs(
            Arena&                          arena,
            const ShadingPoint&             shading_point,
            void*                           data) const APPLESEED_OVERRIDE
        {
            DipoleBSSRDFInputValues* values =
                static_cast<DipoleBSSRDFInputValues*>(data);

            do_prepare_inputs<ComputeRdStandardDipole>(shading_point, values);
        }

        virtual void evaluate_profile(
            const void*                     data,
            const ShadingPoint&             outgoing_point,
            const Vector3f&                 outgoing_dir,
            const ShadingPoint&             incoming_point,
            const Vector3f&                 incoming_dir,
            Spectrum&                       value) const APPLESEED_OVERRIDE
        {
            const DipoleBSSRDFInputValues* values =
                static_cast<const DipoleBSSRDFInputValues*>(data);

            const Vector3f xo(outgoing_point.get_point());
            const Vector3f xi(incoming_point.get_point());
            const Vector3f no(outgoing_point.get_shading_normal());
            const Vector3f ni(incoming_point.get_shading_normal());

            bssrdf(values, xi, ni, incoming_dir, xo, no, value);

            // Hack to make the BSSRDF reciprocal ([1] section 6.3):
            // Spectrum tmp;
            // bssrdf(values, xo, no, outgoing_dir, xi, ni, tmp);
            // madd(value, tmp, 0.5f);

            // The directional dipole expression already integrates the BRDF
            // at the incoming point so we need to cancel the 1/Pi term from
            // the Lambertian BRDF.
            value *= Pi<float>();
        }

      private:
        // Evaluate the directional dipole BSSRDF.
        static void bssrdf(
            const DipoleBSSRDFInputValues*  values,
            const Vector3f&                 xi,
            const Vector3f&                 ni,
            const Vector3f&                 wi,
            const Vector3f&                 xo,
            const Vector3f&                 no,
            Spectrum&                       value)
        {
            // Precompute some stuff. Same as for the Better Dipole model.
            const Vector3f xoxi = xo - xi;
            const float r2 = square_norm(xoxi);                                         // square distance between points of incidence and emergence
            const float eta = values->m_base_values.m_eta;
            const float rcp_eta = 1.0f / eta;
            const float cphi_eta = 0.25f * (1.0f - fresnel_first_moment_x2(rcp_eta));
            const float ce_eta = 0.5f * (1.0f - fresnel_second_moment_x3(rcp_eta));
            const float A = (1.0f - ce_eta) / (2.0f * cphi_eta);                        // reflection parameter

            // Compute normal to modified tangent plane.
            const Vector3f ni_star =
                r2 > 0.0f                                                               // we assume that if r2 > 0, then sqrt(r2) is also > 0
                    ? cross(xoxi / sqrt(r2), normalize(cross(ni, xoxi)))
                    : ni;
            assert(is_normalized(ni_star));

            // Compute direction of real ray source.
            Vector3f wr;
            APPLESEED_UNUSED const bool successful = refract(wi, ni, eta, wr);
            assert(successful);
            assert(is_normalized(wr));

            // Compute direction of virtual ray source.
            const Vector3f wv = -reflect(wr, ni_star);
            assert(is_normalized(wv));

            const float dot_wr_xoxi = dot(xoxi, wr);                                    // r * cos( real source direction, modified plane tangent )
            const float dot_wr_no = dot(wr, no);                                        // cos( real source direction, normal at outgoing )
            const float dot_xoxi_no = dot(xoxi, no);
            const float dot_wv_no = dot(wv, no);

            value.resize(values->m_sigma_a.size());

            for (size_t i = 0, e = value.size(); i < e; ++i)
            {
                const float sigma_a = values->m_sigma_a[i];
                const float sigma_s = values->m_sigma_s[i];
                const float sigma_t = sigma_s + sigma_a;
                const float sigma_s_prime = sigma_s * (1.0f - values->m_g);
                const float sigma_t_prime = sigma_s_prime + sigma_a;
                const float alpha_prime = values->m_precomputed.m_alpha_prime[i];       // reduced scattering albedo
                const float sigma_tr = values->m_precomputed.m_sigma_tr[i];             // effective transport coefficient

                // Compute extrapolation distance ([1] equation 21).
                const float D = 1.0f / (3.0f * sigma_t_prime);                          // diffusion coefficient
                const float de = 2.131f * D / sqrt(alpha_prime);                        // distance to extrapolated boundary
                //const float de = 2.121f * D / alpha_prime;                            // [2] equation 18

                // Compute corrected distance to real source.
                const float cos_beta = -sqrt((r2 - square(dot_wr_xoxi)) / (r2 + de * de));
                const float mu0 = -dot_wr_no;
                const float zr2 =
                    mu0 > 0.0f
                        ? D * mu0 * (D * mu0 - 2.0f * de * cos_beta)                    // frontlit
                        : 1.0f / square(3.0f * sigma_t);                                // backlit
                const float dr = sqrt(r2 + zr2);                                        // distance to real ray source

                // Compute position of virtual source.
                const Vector3f xv = xi + (2.0f * A * de) * ni_star;                     // position of the virtual ray source
                const Vector3f xoxv = xo - xv;
                const float dot_xoxv_no = dot(xoxv, no);

                // Compute distance to virtual source.
                const float dv = norm(xoxv);                                            // distance to virtual ray source
                assert(feq(dv, sqrt(r2 + square(2.0f * A * de)), 1.0e-5f));             // true because we computed xv using ni_star, not ni

                // Evaluate the BSSRDF.
                const float sdr = sd_prime(cphi_eta, ce_eta, D, sigma_tr, dot_wr_xoxi, dot_wr_no, dot_xoxi_no, dr);
                const float sdv = sd_prime(cphi_eta, ce_eta, D, sigma_tr, dot(wv, xoxv), dot_wv_no, dot_xoxv_no, dv);
                value[i] = max(sdr - sdv, 0.0f);
            }

            // todo: add reduced intensity component here (S_sigma_E term).
            // See [1] equation 12 (section 3.2).
        }

        // Diffusion term of the BSSRDF.
        static float sd_prime(
            const float cphi_eta,
            const float ce_eta,
            const float D,
            const float sigma_tr,
            const float dot_w_x,
            const float dot_w_n,
            const float dot_x_n,
            const float r)
        {
            const float r2 = square(r);
            const float sigma_tr_r = sigma_tr * r;

            const float t0 = RcpFourPiSquare<float>() * exp(-sigma_tr_r) / (r2 * r);
            const float t1 = r2 / D + 3.0f * (1.0f + sigma_tr_r) * dot_w_x;
            const float t2 = 3.0f * D * (1.0f + sigma_tr_r) * dot_w_n;
            const float t3 = (1.0f + sigma_tr_r + 3.0f * D * (3.0f * (1.0f + sigma_tr_r) + square(sigma_tr_r)) / r2 * dot_w_x) * dot_x_n;

            return t0 * (cphi_eta * t1 - ce_eta * (t2 - t3));
        }
    };
}

//
// DirectionalDipoleBSSRDFFactory class implementation.
//

const char* DirectionalDipoleBSSRDFFactory::get_model() const
{
    return Model;
}

Dictionary DirectionalDipoleBSSRDFFactory::get_model_metadata() const
{
    return
        Dictionary()
            .insert("name", Model)
            .insert("label", "Directional Dipole BSSRDF");
}

auto_release_ptr<BSSRDF> DirectionalDipoleBSSRDFFactory::create(
    const char*         name,
    const ParamArray&   params) const
{
    return auto_release_ptr<BSSRDF>(new DirectionalDipoleBSSRDF(name, params));
}

auto_release_ptr<BSSRDF> DirectionalDipoleBSSRDFFactory::static_create(
    const char*         name,
    const ParamArray&   params)
{
    return auto_release_ptr<BSSRDF>(new DirectionalDipoleBSSRDF(name, params));
}

}   // namespace renderer
<commit_msg>Remove low value comment<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2015-2017 Esteban Tovagliari, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "directionaldipolebssrdf.h"

// appleseed.renderer headers.
#include "renderer/global/globaltypes.h"
#include "renderer/kernel/shading/shadingpoint.h"
#include "renderer/modeling/bssrdf/dipolebssrdf.h"
#include "renderer/modeling/bssrdf/sss.h"

// appleseed.foundation headers.
#include "foundation/math/fresnel.h"
#include "foundation/math/scalar.h"
#include "foundation/math/vector.h"
#include "foundation/utility/containers/dictionary.h"

// Standard headers.
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstddef>

// Forward declarations.
namespace foundation    { class Arena; }

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    //
    // Directional dipole BSSRDF.
    //
    // References:
    //
    //   [1] Directional Dipole Model for Subsurface Scattering
    //       Jeppe Revall Frisvad, Toshiya Hachisuka, Thomas Kim Kjeldsen
    //       http://www.ci.i.u-tokyo.ac.jp/~hachisuka/dirpole.pdf
    //
    //   [2] Directional Dipole for Subsurface Scattering in Translucent Materials
    //       Jeppe Revall Frisvad, Toshiya Hachisuka, Thomas Kim Kjeldsen
    //       http://www.ci.i.u-tokyo.ac.jp/~hachisuka/dirpole_tr.pdf
    //

    const char* Model = "directional_dipole_bssrdf";

    class DirectionalDipoleBSSRDF
      : public DipoleBSSRDF
    {
      public:
        DirectionalDipoleBSSRDF(
            const char*                     name,
            const ParamArray&               params)
          : DipoleBSSRDF(name, params)
        {
        }

        virtual void release() APPLESEED_OVERRIDE
        {
            delete this;
        }

        virtual const char* get_model() const APPLESEED_OVERRIDE
        {
            return Model;
        }

        virtual void prepare_inputs(
            Arena&                          arena,
            const ShadingPoint&             shading_point,
            void*                           data) const APPLESEED_OVERRIDE
        {
            DipoleBSSRDFInputValues* values =
                static_cast<DipoleBSSRDFInputValues*>(data);

            do_prepare_inputs<ComputeRdStandardDipole>(shading_point, values);
        }

        virtual void evaluate_profile(
            const void*                     data,
            const ShadingPoint&             outgoing_point,
            const Vector3f&                 outgoing_dir,
            const ShadingPoint&             incoming_point,
            const Vector3f&                 incoming_dir,
            Spectrum&                       value) const APPLESEED_OVERRIDE
        {
            const DipoleBSSRDFInputValues* values =
                static_cast<const DipoleBSSRDFInputValues*>(data);

            const Vector3f xo(outgoing_point.get_point());
            const Vector3f xi(incoming_point.get_point());
            const Vector3f no(outgoing_point.get_shading_normal());
            const Vector3f ni(incoming_point.get_shading_normal());

            bssrdf(values, xi, ni, incoming_dir, xo, no, value);

            // Hack to make the BSSRDF reciprocal ([1] section 6.3):
            // Spectrum tmp;
            // bssrdf(values, xo, no, outgoing_dir, xi, ni, tmp);
            // madd(value, tmp, 0.5f);

            // The directional dipole expression already integrates the BRDF
            // at the incoming point so we need to cancel the 1/Pi term from
            // the Lambertian BRDF.
            value *= Pi<float>();
        }

      private:
        // Evaluate the directional dipole BSSRDF.
        static void bssrdf(
            const DipoleBSSRDFInputValues*  values,
            const Vector3f&                 xi,
            const Vector3f&                 ni,
            const Vector3f&                 wi,
            const Vector3f&                 xo,
            const Vector3f&                 no,
            Spectrum&                       value)
        {
            const Vector3f xoxi = xo - xi;
            const float r2 = square_norm(xoxi);                                         // square distance between points of incidence and emergence
            const float eta = values->m_base_values.m_eta;
            const float rcp_eta = 1.0f / eta;
            const float cphi_eta = 0.25f * (1.0f - fresnel_first_moment_x2(rcp_eta));
            const float ce_eta = 0.5f * (1.0f - fresnel_second_moment_x3(rcp_eta));
            const float A = (1.0f - ce_eta) / (2.0f * cphi_eta);                        // reflection parameter

            // Compute normal to modified tangent plane.
            const Vector3f ni_star =
                r2 > 0.0f                                                               // we assume that if r2 > 0, then sqrt(r2) is also > 0
                    ? cross(xoxi / sqrt(r2), normalize(cross(ni, xoxi)))
                    : ni;
            assert(is_normalized(ni_star));

            // Compute direction of real ray source.
            Vector3f wr;
            APPLESEED_UNUSED const bool successful = refract(wi, ni, eta, wr);
            assert(successful);
            assert(is_normalized(wr));

            // Compute direction of virtual ray source.
            const Vector3f wv = -reflect(wr, ni_star);
            assert(is_normalized(wv));

            const float dot_wr_xoxi = dot(xoxi, wr);                                    // r * cos( real source direction, modified plane tangent )
            const float dot_wr_no = dot(wr, no);                                        // cos( real source direction, normal at outgoing )
            const float dot_xoxi_no = dot(xoxi, no);
            const float dot_wv_no = dot(wv, no);

            value.resize(values->m_sigma_a.size());

            for (size_t i = 0, e = value.size(); i < e; ++i)
            {
                const float sigma_a = values->m_sigma_a[i];
                const float sigma_s = values->m_sigma_s[i];
                const float sigma_t = sigma_s + sigma_a;
                const float sigma_s_prime = sigma_s * (1.0f - values->m_g);
                const float sigma_t_prime = sigma_s_prime + sigma_a;
                const float alpha_prime = values->m_precomputed.m_alpha_prime[i];       // reduced scattering albedo
                const float sigma_tr = values->m_precomputed.m_sigma_tr[i];             // effective transport coefficient

                // Compute extrapolation distance ([1] equation 21).
                const float D = 1.0f / (3.0f * sigma_t_prime);                          // diffusion coefficient
                const float de = 2.131f * D / sqrt(alpha_prime);                        // distance to extrapolated boundary
                //const float de = 2.121f * D / alpha_prime;                            // [2] equation 18

                // Compute corrected distance to real source.
                const float cos_beta = -sqrt((r2 - square(dot_wr_xoxi)) / (r2 + de * de));
                const float mu0 = -dot_wr_no;
                const float zr2 =
                    mu0 > 0.0f
                        ? D * mu0 * (D * mu0 - 2.0f * de * cos_beta)                    // frontlit
                        : 1.0f / square(3.0f * sigma_t);                                // backlit
                const float dr = sqrt(r2 + zr2);                                        // distance to real ray source

                // Compute position of virtual source.
                const Vector3f xv = xi + (2.0f * A * de) * ni_star;                     // position of the virtual ray source
                const Vector3f xoxv = xo - xv;
                const float dot_xoxv_no = dot(xoxv, no);

                // Compute distance to virtual source.
                const float dv = norm(xoxv);                                            // distance to virtual ray source
                assert(feq(dv, sqrt(r2 + square(2.0f * A * de)), 1.0e-5f));             // true because we computed xv using ni_star, not ni

                // Evaluate the BSSRDF.
                const float sdr = sd_prime(cphi_eta, ce_eta, D, sigma_tr, dot_wr_xoxi, dot_wr_no, dot_xoxi_no, dr);
                const float sdv = sd_prime(cphi_eta, ce_eta, D, sigma_tr, dot(wv, xoxv), dot_wv_no, dot_xoxv_no, dv);
                value[i] = max(sdr - sdv, 0.0f);
            }

            // todo: add reduced intensity component here (S_sigma_E term).
            // See [1] equation 12 (section 3.2).
        }

        // Diffusion term of the BSSRDF.
        static float sd_prime(
            const float cphi_eta,
            const float ce_eta,
            const float D,
            const float sigma_tr,
            const float dot_w_x,
            const float dot_w_n,
            const float dot_x_n,
            const float r)
        {
            const float r2 = square(r);
            const float sigma_tr_r = sigma_tr * r;

            const float t0 = RcpFourPiSquare<float>() * exp(-sigma_tr_r) / (r2 * r);
            const float t1 = r2 / D + 3.0f * (1.0f + sigma_tr_r) * dot_w_x;
            const float t2 = 3.0f * D * (1.0f + sigma_tr_r) * dot_w_n;
            const float t3 = (1.0f + sigma_tr_r + 3.0f * D * (3.0f * (1.0f + sigma_tr_r) + square(sigma_tr_r)) / r2 * dot_w_x) * dot_x_n;

            return t0 * (cphi_eta * t1 - ce_eta * (t2 - t3));
        }
    };
}

//
// DirectionalDipoleBSSRDFFactory class implementation.
//

const char* DirectionalDipoleBSSRDFFactory::get_model() const
{
    return Model;
}

Dictionary DirectionalDipoleBSSRDFFactory::get_model_metadata() const
{
    return
        Dictionary()
            .insert("name", Model)
            .insert("label", "Directional Dipole BSSRDF");
}

auto_release_ptr<BSSRDF> DirectionalDipoleBSSRDFFactory::create(
    const char*         name,
    const ParamArray&   params) const
{
    return auto_release_ptr<BSSRDF>(new DirectionalDipoleBSSRDF(name, params));
}

auto_release_ptr<BSSRDF> DirectionalDipoleBSSRDFFactory::static_create(
    const char*         name,
    const ParamArray&   params)
{
    return auto_release_ptr<BSSRDF>(new DirectionalDipoleBSSRDF(name, params));
}

}   // namespace renderer
<|endoftext|>


<commit_before>#include <rang.hpp>
#include <cstdlib>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
#include <date.h>

#ifdef ENABLE_MPI
#include <mpi.h>
#endif

#include "Tools/general_utils.h"
#include "Tools/system_functions.h"
#include "Tools/Display/rang_format/rang_format.h"
#include "Tools/Exception/exception.hpp"

#include "Factory/Module/Source/Source.hpp"
#include "Factory/Module/CRC/CRC.hpp"
#include "Factory/Module/Encoder/Encoder.hpp"
#include "Factory/Module/Puncturer/Puncturer.hpp"
#include "Factory/Module/Interleaver/Interleaver.hpp"
#include "Factory/Module/Modem/Modem.hpp"
#include "Factory/Module/Channel/Channel.hpp"
#include "Factory/Module/Quantizer/Quantizer.hpp"
#include "Factory/Module/Decoder/Decoder.hpp"
#include "Factory/Module/Monitor/Monitor.hpp"
#include "Factory/Tools/Display/Terminal/Terminal.hpp"

#include "Launcher.hpp"

using namespace aff3ct;
using namespace aff3ct::launcher;

Launcher::Launcher(const int argc, const char **argv, factory::Simulation::parameters &params_common,
                   std::ostream &stream)
: simu(nullptr), ah(argc, argv), params_common(params_common), stream(stream)
{
	cmd_line += std::string(argv[0]) + std::string(" ");
	for (auto i = 1; i < argc; i++)
	{
		if (argv[i][0] == '-')
			cmd_line += std::string(argv[i]);
		else
			cmd_line += std::string("\"") + std::string(argv[i]) + std::string("\"");

		cmd_line += std::string(" ");
	}
}

Launcher::~Launcher()
{
}

void Launcher::get_description_args()
{
}

void Launcher::store_args()
{
}

int Launcher::read_arguments()
{
	this->get_description_args();

	std::vector<std::string> cmd_error;

	this->arg_vals = ah.parse_arguments(this->args, this->cmd_warn, cmd_error);

	try
	{
		this->store_args();
	}
	catch(const std::exception& e)
	{
		auto save = tools::exception::no_backtrace;
		tools::exception::no_backtrace = true;
		cmd_error.push_back(e.what());
		tools::exception::no_backtrace = save;
	}

	if (params_common.display_help)
	{
		auto grps = factory::Factory::create_groups({&params_common});
		ah.print_help(this->args, grps, params_common.display_adv_help);
	}

	// print usage
	if (cmd_error.size() && !params_common.display_help)
		ah.print_usage(this->args);

	// print the errors
	if (cmd_error.size()) std::cerr << std::endl;
	for (unsigned e = 0; e < cmd_error.size(); e++)
		std::cerr << rang::format::error << cmd_error[e] << rang::format::reset << std::endl;

	// print the help tags
	if (cmd_error.size() && !params_common.display_help)
	{
		tools::Argument_tag help_tag = {"help", "h"};

		std::string message = "For more information please display the help (\"";
		message += tools::Argument_handler::print_tag(help_tag) += "\").";

		std::cerr << std::endl << rang::format::info << message << rang::format::reset << std::endl;
	}

	return (cmd_error.size() || params_common.display_help) ? EXIT_FAILURE : EXIT_SUCCESS;
}

void Launcher::print_header()
{
	// display configuration and simulation parameters
	stream << "# " << rang::style::bold << "----------------------------------------------------" << std::endl;
	stream << "# " <<                      "---- A FAST FORWARD ERROR CORRECTION TOOLBOX >> ----" << std::endl;
	stream << "# " <<                      "----------------------------------------------------" << std::endl;
	stream << "# " << rang::style::underline << "Parameters :"<< rang::style::reset << std::endl;
	factory::Header::print_parameters({&params_common}, false, this->stream);
	this->stream << "#" << std::endl;
}

int Launcher::launch()
{
	int exit_code = EXIT_SUCCESS;

	std::srand(this->params_common.global_seed);

	// in case of the user call launch multiple times
	if (simu != nullptr)
	{
		delete simu;
		simu = nullptr;
	}

	if (this->read_arguments() == EXIT_FAILURE)
	{
		// print the warnings
#ifdef ENABLE_MPI
		if (this->params_common.mpi_rank == 0)
#endif
			for (unsigned w = 0; w < this->cmd_warn.size(); w++)
				std::clog << rang::format::warning << this->cmd_warn[w] << rang::format::reset << std::endl;
		return EXIT_FAILURE;
	}

	// write the command and he curve name in the PyBER format
#ifdef ENABLE_MPI
	if (!this->params_common.pyber.empty() && this->params_common.mpi_rank == 0)
#else
	if (!this->params_common.pyber.empty())
#endif
	{
		stream << "Run command:"     << std::endl;
		stream << cmd_line           << std::endl;
		stream << "Curve name:"      << std::endl;
		stream << this->params_common.pyber << std::endl;
	}

	if (this->params_common.display_legend)
#ifdef ENABLE_MPI
		if (this->params_common.mpi_rank == 0)
#endif
			this->print_header();

	// print the warnings
#ifdef ENABLE_MPI
	if (this->params_common.mpi_rank == 0)
#endif
		for (unsigned w = 0; w < this->cmd_warn.size(); w++)
			std::clog << rang::format::warning << this->cmd_warn[w] << rang::format::reset << std::endl;

	try
	{
		simu = this->build_simu();
	}
	catch(const std::exception& e)
	{
		rang::format_on_each_line(std::cerr, std::string(e.what()) + "\n", rang::format::error);
		exit_code = EXIT_FAILURE;
	}

	if (simu != nullptr)
	{
		// launch the simulation
		if (this->params_common.display_legend)
#ifdef ENABLE_MPI
			if (this->params_common.mpi_rank == 0)
#endif
				stream << "# " << "The simulation is running..." << std::endl;

		try
		{
			simu->launch();
			if (simu->is_error())
				exit_code = EXIT_FAILURE;
		}
		catch(const std::exception& e)
		{
			rang::format_on_each_line(std::cerr, std::string(e.what()) + "\n", rang::format::error);
			exit_code = EXIT_FAILURE;
		}
	}

	if (this->params_common.display_legend)
#ifdef ENABLE_MPI
		if (this->params_common.mpi_rank == 0)
#endif
			stream << "# End of the simulation." << std::endl;

	if (simu != nullptr)
	{
		delete simu;
		simu = nullptr;
	}

	return exit_code;
}
<commit_msg>Using Terminal::comment_tag in Launcher when displaying the legend<commit_after>#include <rang.hpp>
#include <cstdlib>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
#include <date.h>

#include "Tools/Display/Terminal/Terminal.hpp"

#ifdef ENABLE_MPI
#include <mpi.h>
#endif

#include "Tools/general_utils.h"
#include "Tools/system_functions.h"
#include "Tools/Display/rang_format/rang_format.h"
#include "Tools/Exception/exception.hpp"

#include "Factory/Module/Source/Source.hpp"
#include "Factory/Module/CRC/CRC.hpp"
#include "Factory/Module/Encoder/Encoder.hpp"
#include "Factory/Module/Puncturer/Puncturer.hpp"
#include "Factory/Module/Interleaver/Interleaver.hpp"
#include "Factory/Module/Modem/Modem.hpp"
#include "Factory/Module/Channel/Channel.hpp"
#include "Factory/Module/Quantizer/Quantizer.hpp"
#include "Factory/Module/Decoder/Decoder.hpp"
#include "Factory/Module/Monitor/Monitor.hpp"
#include "Factory/Tools/Display/Terminal/Terminal.hpp"

#include "Launcher.hpp"

using namespace aff3ct;
using namespace aff3ct::launcher;

Launcher::Launcher(const int argc, const char **argv, factory::Simulation::parameters &params_common,
                   std::ostream &stream)
: simu(nullptr), ah(argc, argv), params_common(params_common), stream(stream)
{
	cmd_line += std::string(argv[0]) + std::string(" ");
	for (auto i = 1; i < argc; i++)
	{
		if (argv[i][0] == '-')
			cmd_line += std::string(argv[i]);
		else
			cmd_line += std::string("\"") + std::string(argv[i]) + std::string("\"");

		cmd_line += std::string(" ");
	}
}

Launcher::~Launcher()
{
}

void Launcher::get_description_args()
{
}

void Launcher::store_args()
{
}

int Launcher::read_arguments()
{
	this->get_description_args();

	std::vector<std::string> cmd_error;

	this->arg_vals = ah.parse_arguments(this->args, this->cmd_warn, cmd_error);

	try
	{
		this->store_args();
	}
	catch(const std::exception& e)
	{
		auto save = tools::exception::no_backtrace;
		tools::exception::no_backtrace = true;
		cmd_error.emplace_back(e.what());
		tools::exception::no_backtrace = save;
	}

	if (params_common.display_help)
	{
		auto grps = factory::Factory::create_groups({&params_common});
		ah.print_help(this->args, grps, params_common.display_adv_help);
	}

	// print usage
	if (!cmd_error.empty() && !params_common.display_help)
		ah.print_usage(this->args);

	// print the errors
	if (!cmd_error.empty()) std::cerr << std::endl;
	for (unsigned e = 0; e < cmd_error.size(); e++)
		std::cerr << rang::format::error << cmd_error[e] << rang::format::reset << std::endl;

	// print the help tags
	if (!cmd_error.empty() && !params_common.display_help)
	{
		tools::Argument_tag help_tag = {"help", "h"};

		std::string message = "For more information please display the help (\"";
		message += tools::Argument_handler::print_tag(help_tag) += "\").";

		std::cerr << std::endl << rang::format::info << message << rang::format::reset << std::endl;
	}

	return (!cmd_error.empty() || params_common.display_help) ? EXIT_FAILURE : EXIT_SUCCESS;
}

void Launcher::print_header()
{
	// display configuration and simulation parameters
	stream << rang::style::bold;
	stream << tools::Terminal::comment_tag << "----------------------------------------------------" << std::endl;
	stream << tools::Terminal::comment_tag << "---- A FAST FORWARD ERROR CORRECTION TOOLBOX >> ----" << std::endl;
	stream << tools::Terminal::comment_tag << "----------------------------------------------------" << std::endl;
	stream << tools::Terminal::comment_tag << rang::style::underline << "Parameters :"<< rang::style::reset << std::endl;
	factory::Header::print_parameters({&params_common}, false, this->stream);
	this->stream << tools::Terminal::comment_tag << std::endl;
}

int Launcher::launch()
{
	int exit_code = EXIT_SUCCESS;

	std::srand((unsigned)this->params_common.global_seed);

	// in case of the user call launch multiple times
	if (simu != nullptr)
	{
		delete simu;
		simu = nullptr;
	}

	if (this->read_arguments() == EXIT_FAILURE)
	{
		// print the warnings
#ifdef ENABLE_MPI
		if (this->params_common.mpi_rank == 0)
#endif
			for (unsigned w = 0; w < this->cmd_warn.size(); w++)
				std::clog << rang::format::warning << this->cmd_warn[w] << rang::format::reset << std::endl;
		return EXIT_FAILURE;
	}

	// write the command and he curve name in the PyBER format
#ifdef ENABLE_MPI
	if (!this->params_common.pyber.empty() && this->params_common.mpi_rank == 0)
#else
	if (!this->params_common.pyber.empty())
#endif
	{
		stream << "Run command:"     << std::endl;
		stream << cmd_line           << std::endl;
		stream << "Curve name:"      << std::endl;
		stream << this->params_common.pyber << std::endl;
	}

	if (this->params_common.display_legend)
#ifdef ENABLE_MPI
		if (this->params_common.mpi_rank == 0)
#endif
			this->print_header();

	// print the warnings
#ifdef ENABLE_MPI
	if (this->params_common.mpi_rank == 0)
#endif
		for (unsigned w = 0; w < this->cmd_warn.size(); w++)
			std::clog << rang::format::warning << this->cmd_warn[w] << rang::format::reset << std::endl;

	try
	{
		simu = this->build_simu();
	}
	catch(const std::exception& e)
	{
		rang::format_on_each_line(std::cerr, std::string(e.what()) + "\n", rang::format::error);
		exit_code = EXIT_FAILURE;
	}

	if (simu != nullptr)
	{
		// launch the simulation
		if (this->params_common.display_legend)
#ifdef ENABLE_MPI
			if (this->params_common.mpi_rank == 0)
#endif
				stream << tools::Terminal::comment_tag << "The simulation is running..." << std::endl;

		try
		{
			simu->launch();
			if (simu->is_error())
				exit_code = EXIT_FAILURE;
		}
		catch(const std::exception& e)
		{
			rang::format_on_each_line(std::cerr, std::string(e.what()) + "\n", rang::format::error);
			exit_code = EXIT_FAILURE;
		}
	}

	if (this->params_common.display_legend)
#ifdef ENABLE_MPI
		if (this->params_common.mpi_rank == 0)
#endif
			stream << tools::Terminal::comment_tag << "End of the simulation." << std::endl;

	if (simu != nullptr)
	{
		delete simu;
		simu = nullptr;
	}

	return exit_code;
}
<|endoftext|>


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

#include "stdlib.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclGroup.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Stmt.h"
#include "clang/Parse/Parser.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include "lldb/Core/Log.h"
#include "lldb/Expression/ClangPersistentVariables.h"
#include "lldb/Expression/ASTResultSynthesizer.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ClangASTImporter.h"
#include "lldb/Target/Target.h"

using namespace llvm;
using namespace clang;
using namespace lldb_private;

ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough,
                                           Target &target) :
    m_ast_context (NULL),
    m_passthrough (passthrough),
    m_passthrough_sema (NULL),
    m_target (target),
    m_sema (NULL)
{
    if (!m_passthrough)
        return;

    m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
}

ASTResultSynthesizer::~ASTResultSynthesizer()
{
}

void
ASTResultSynthesizer::Initialize(ASTContext &Context)
{
    m_ast_context = &Context;

    if (m_passthrough)
        m_passthrough->Initialize(Context);
}

void
ASTResultSynthesizer::TransformTopLevelDecl(Decl* D)
{
    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    if (NamedDecl *named_decl = dyn_cast<NamedDecl>(D))
    {
        if (log && log->GetVerbose())
        {
            if (named_decl->getIdentifier())
                log->Printf("TransformTopLevelDecl(%s)", named_decl->getIdentifier()->getNameStart());
            else if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D))
                log->Printf("TransformTopLevelDecl(%s)", method_decl->getSelector().getAsString().c_str());
            else
                log->Printf("TransformTopLevelDecl(<complex>)");
        }

    }

    if (LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D))
    {
        RecordDecl::decl_iterator decl_iterator;

        for (decl_iterator = linkage_spec_decl->decls_begin();
             decl_iterator != linkage_spec_decl->decls_end();
             ++decl_iterator)
        {
            TransformTopLevelDecl(*decl_iterator);
        }
    }
    else if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D))
    {
        if (m_ast_context &&
            !method_decl->getSelector().getAsString().compare("$__lldb_expr:"))
        {
            RecordPersistentTypes(method_decl);
            SynthesizeObjCMethodResult(method_decl);
        }
    }
    else if (FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D))
    {
        if (m_ast_context &&
            !function_decl->getNameInfo().getAsString().compare("$__lldb_expr"))
        {
            RecordPersistentTypes(function_decl);
            SynthesizeFunctionResult(function_decl);
        }
    }
}

bool
ASTResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D)
{
    DeclGroupRef::iterator decl_iterator;

    for (decl_iterator = D.begin();
         decl_iterator != D.end();
         ++decl_iterator)
    {
        Decl *decl = *decl_iterator;

        TransformTopLevelDecl(decl);
    }

    if (m_passthrough)
        return m_passthrough->HandleTopLevelDecl(D);
    return true;
}

bool
ASTResultSynthesizer::SynthesizeFunctionResult (FunctionDecl *FunDecl)
{
    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    ASTContext &Ctx(*m_ast_context);

    if (!m_sema)
        return false;

    FunctionDecl *function_decl = FunDecl;

    if (!function_decl)
        return false;

    if (log && log->GetVerbose())
    {
        std::string s;
        raw_string_ostream os(s);

        Ctx.getTranslationUnitDecl()->print(os);

        os.flush();

        log->Printf("AST context before transforming:\n%s", s.c_str());
    }

    Stmt *function_body = function_decl->getBody();
    CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(function_body);

    bool ret = SynthesizeBodyResult (compound_stmt,
                                     function_decl);

    if (log && log->GetVerbose())
    {
        std::string s;
        raw_string_ostream os(s);

        function_decl->print(os);

        os.flush();

        log->Printf ("Transformed function AST:\n%s", s.c_str());
    }

    return ret;
}

bool
ASTResultSynthesizer::SynthesizeObjCMethodResult (ObjCMethodDecl *MethodDecl)
{
    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    ASTContext &Ctx(*m_ast_context);

    if (!m_sema)
        return false;

    if (!MethodDecl)
        return false;

    if (log && log->GetVerbose())
    {
        std::string s;
        raw_string_ostream os(s);

        Ctx.getTranslationUnitDecl()->print(os);

        os.flush();

        log->Printf("AST context before transforming:\n%s", s.c_str());
    }

    Stmt *method_body = MethodDecl->getBody();

    if (!method_body)
        return false;

    CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(method_body);

    bool ret = SynthesizeBodyResult (compound_stmt,
                                     MethodDecl);

    if (log)
    {
        std::string s;
        raw_string_ostream os(s);

        MethodDecl->print(os);

        os.flush();

        log->Printf("Transformed function AST:\n%s", s.c_str());
    }

    return ret;
}

bool
ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body,
                                            DeclContext *DC)
{
    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    ASTContext &Ctx(*m_ast_context);

    if (!Body)
        return false;

    if (Body->body_empty())
        return false;

    Stmt **last_stmt_ptr = Body->body_end() - 1;
    Stmt *last_stmt = *last_stmt_ptr;

    while (dyn_cast<NullStmt>(last_stmt))
    {
        if (last_stmt_ptr != Body->body_begin())
        {
            last_stmt_ptr--;
            last_stmt = *last_stmt_ptr;
        }
        else
        {
            return false;
        }
    }

    Expr *last_expr = dyn_cast<Expr>(last_stmt);

    if (!last_expr)
        // No auxiliary variable necessary; expression returns void
        return true;

    // In C++11, last_expr can be a LValueToRvalue implicit cast.  Strip that off if that's the
    // case.

    do {
        ImplicitCastExpr *implicit_cast = dyn_cast<ImplicitCastExpr>(last_expr);

        if (!implicit_cast)
            break;

        if (implicit_cast->getCastKind() != CK_LValueToRValue)
            break;

        last_expr = implicit_cast->getSubExpr();
    } while (0);

    // is_lvalue is used to record whether the expression returns an assignable Lvalue or an
    // Rvalue.  This is relevant because they are handled differently.
    //
    // For Lvalues
    //
    //   - In AST result synthesis (here!) the expression E is transformed into an initialization
    //     T *$__lldb_expr_result_ptr = &E.
    //
    //   - In structure allocation, a pointer-sized slot is allocated in the struct that is to be
    //     passed into the expression.
    //
    //   - In IR transformations, reads and writes to $__lldb_expr_result_ptr are redirected at
    //     an entry in the struct ($__lldb_arg) passed into the expression.  (Other persistent
    //     variables are treated similarly, having been materialized as references, but in those
    //     cases the value of the reference itself is never modified.)
    //
    //   - During materialization, $0 (the result persistent variable) is ignored.
    //
    //   - During dematerialization, $0 is marked up as a load address with value equal to the
    //     contents of the structure entry.
    //
    // For Rvalues
    //
    //   - In AST result synthesis the expression E is transformed into an initialization
    //     static T $__lldb_expr_result = E.
    //
    //   - In structure allocation, a pointer-sized slot is allocated in the struct that is to be
    //     passed into the expression.
    //
    //   - In IR transformations, an instruction is inserted at the beginning of the function to
    //     dereference the pointer resident in the slot.  Reads and writes to $__lldb_expr_result
    //     are redirected at that dereferenced version.  Guard variables for the static variable
    //     are excised.
    //
    //   - During materialization, $0 (the result persistent variable) is populated with the location
    //     of a newly-allocated area of memory.
    //
    //   - During dematerialization, $0 is ignored.

    bool is_lvalue =
        (last_expr->getValueKind() == VK_LValue || last_expr->getValueKind() == VK_XValue) &&
        (last_expr->getObjectKind() == OK_Ordinary);

    QualType expr_qual_type = last_expr->getType();
    const clang::Type *expr_type = expr_qual_type.getTypePtr();

    if (!expr_type)
        return false;

    if (expr_type->isVoidType())
        return true;

    if (log)
    {
        std::string s = expr_qual_type.getAsString();

        log->Printf("Last statement is an %s with type: %s", (is_lvalue ? "lvalue" : "rvalue"), s.c_str());
    }

    clang::VarDecl *result_decl = NULL;

    if (is_lvalue)
    {
        IdentifierInfo *result_ptr_id;

        if (expr_type->isFunctionType())
            result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result"); // functions actually should be treated like function pointers
        else
            result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result_ptr");

        m_sema->RequireCompleteType(SourceLocation(), expr_qual_type, clang::diag::err_incomplete_type);

        QualType ptr_qual_type;

        if (expr_qual_type->getAs<ObjCObjectType>() != NULL)
            ptr_qual_type = Ctx.getObjCObjectPointerType(expr_qual_type);
        else
            ptr_qual_type = Ctx.getPointerType(expr_qual_type);

        result_decl = VarDecl::Create(Ctx,
                                      DC,
                                      SourceLocation(),
                                      SourceLocation(),
                                      result_ptr_id,
                                      ptr_qual_type,
                                      NULL,
                                      SC_Static,
                                      SC_Static);

        if (!result_decl)
            return false;

        ExprResult address_of_expr = m_sema->CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, last_expr);

        m_sema->AddInitializerToDecl(result_decl, address_of_expr.take(), true, false);
    }
    else
    {
        IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result");

        result_decl = VarDecl::Create(Ctx,
                                      DC,
                                      SourceLocation(),
                                      SourceLocation(),
                                      &result_id,
                                      expr_qual_type,
                                      NULL,
                                      SC_Static,
                                      SC_Static);

        if (!result_decl)
            return false;

        m_sema->AddInitializerToDecl(result_decl, last_expr, true, false);
    }

    DC->addDecl(result_decl);

    ///////////////////////////////
    // call AddInitializerToDecl
    //

    //m_sema->AddInitializerToDecl(result_decl, last_expr);

    /////////////////////////////////
    // call ConvertDeclToDeclGroup
    //

    Sema::DeclGroupPtrTy result_decl_group_ptr;

    result_decl_group_ptr = m_sema->ConvertDeclToDeclGroup(result_decl);

    ////////////////////////
    // call ActOnDeclStmt
    //

    StmtResult result_initialization_stmt_result(m_sema->ActOnDeclStmt(result_decl_group_ptr,
                                                                       SourceLocation(),
                                                                       SourceLocation()));

    ////////////////////////////////////////////////
    // replace the old statement with the new one
    //

    *last_stmt_ptr = reinterpret_cast<Stmt*>(result_initialization_stmt_result.take());

    return true;
}

void
ASTResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx)
{
    if (m_passthrough)
        m_passthrough->HandleTranslationUnit(Ctx);
}

void
ASTResultSynthesizer::RecordPersistentTypes(DeclContext *FunDeclCtx)
{
    typedef DeclContext::specific_decl_iterator<TypeDecl> TypeDeclIterator;

    for (TypeDeclIterator i = TypeDeclIterator(FunDeclCtx->decls_begin()),
         e = TypeDeclIterator(FunDeclCtx->decls_end());
         i != e;
         ++i)
    {
        MaybeRecordPersistentType(*i);
    }
}

void
ASTResultSynthesizer::MaybeRecordPersistentType(TypeDecl *D)
{
    if (!D->getIdentifier())
        return;

    StringRef name = D->getName();

    if (name.size() == 0 || name[0] != '$')
        return;

    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    ConstString name_cs(name.str().c_str());

    if (log)
        log->Printf ("Recording persistent type %s\n", name_cs.GetCString());

    Decl *D_scratch = m_target.GetClangASTImporter()->DeportDecl(m_target.GetScratchClangASTContext()->getASTContext(),
                                                                 m_ast_context,
                                                                 D);

    if (TypeDecl *TypeDecl_scratch = dyn_cast<TypeDecl>(D_scratch))
        m_target.GetPersistentVariables().RegisterPersistentType(name_cs, TypeDecl_scratch);
}

void
ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl *D)
{
    if (m_passthrough)
        m_passthrough->HandleTagDeclDefinition(D);
}

void
ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl *D)
{
    if (m_passthrough)
        m_passthrough->CompleteTentativeDefinition(D);
}

void
ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired)
{
    if (m_passthrough)
        m_passthrough->HandleVTable(RD, DefinitionRequired);
}

void
ASTResultSynthesizer::PrintStats()
{
    if (m_passthrough)
        m_passthrough->PrintStats();
}

void
ASTResultSynthesizer::InitializeSema(Sema &S)
{
    m_sema = &S;

    if (m_passthrough_sema)
        m_passthrough_sema->InitializeSema(S);
}

void
ASTResultSynthesizer::ForgetSema()
{
    m_sema = NULL;

    if (m_passthrough_sema)
        m_passthrough_sema->ForgetSema();
}
<commit_msg>Removed a possible use of unchecked NULL from the AST result synthesizer's logging.<commit_after>//===-- ASTResultSynthesizer.cpp --------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "stdlib.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclGroup.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Stmt.h"
#include "clang/Parse/Parser.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include "lldb/Core/Log.h"
#include "lldb/Expression/ClangPersistentVariables.h"
#include "lldb/Expression/ASTResultSynthesizer.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ClangASTImporter.h"
#include "lldb/Target/Target.h"

using namespace llvm;
using namespace clang;
using namespace lldb_private;

ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough,
                                           Target &target) :
    m_ast_context (NULL),
    m_passthrough (passthrough),
    m_passthrough_sema (NULL),
    m_target (target),
    m_sema (NULL)
{
    if (!m_passthrough)
        return;

    m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
}

ASTResultSynthesizer::~ASTResultSynthesizer()
{
}

void
ASTResultSynthesizer::Initialize(ASTContext &Context)
{
    m_ast_context = &Context;

    if (m_passthrough)
        m_passthrough->Initialize(Context);
}

void
ASTResultSynthesizer::TransformTopLevelDecl(Decl* D)
{
    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    if (NamedDecl *named_decl = dyn_cast<NamedDecl>(D))
    {
        if (log && log->GetVerbose())
        {
            if (named_decl->getIdentifier())
                log->Printf("TransformTopLevelDecl(%s)", named_decl->getIdentifier()->getNameStart());
            else if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D))
                log->Printf("TransformTopLevelDecl(%s)", method_decl->getSelector().getAsString().c_str());
            else
                log->Printf("TransformTopLevelDecl(<complex>)");
        }

    }

    if (LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D))
    {
        RecordDecl::decl_iterator decl_iterator;

        for (decl_iterator = linkage_spec_decl->decls_begin();
             decl_iterator != linkage_spec_decl->decls_end();
             ++decl_iterator)
        {
            TransformTopLevelDecl(*decl_iterator);
        }
    }
    else if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D))
    {
        if (m_ast_context &&
            !method_decl->getSelector().getAsString().compare("$__lldb_expr:"))
        {
            RecordPersistentTypes(method_decl);
            SynthesizeObjCMethodResult(method_decl);
        }
    }
    else if (FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D))
    {
        if (m_ast_context &&
            !function_decl->getNameInfo().getAsString().compare("$__lldb_expr"))
        {
            RecordPersistentTypes(function_decl);
            SynthesizeFunctionResult(function_decl);
        }
    }
}

bool
ASTResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D)
{
    DeclGroupRef::iterator decl_iterator;

    for (decl_iterator = D.begin();
         decl_iterator != D.end();
         ++decl_iterator)
    {
        Decl *decl = *decl_iterator;

        TransformTopLevelDecl(decl);
    }

    if (m_passthrough)
        return m_passthrough->HandleTopLevelDecl(D);
    return true;
}

bool
ASTResultSynthesizer::SynthesizeFunctionResult (FunctionDecl *FunDecl)
{
    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    if (!m_sema)
        return false;

    FunctionDecl *function_decl = FunDecl;

    if (!function_decl)
        return false;

    if (log && log->GetVerbose())
    {
        std::string s;
        raw_string_ostream os(s);

        function_decl->print(os);

        os.flush();

        log->Printf ("Untransformed function AST:\n%s", s.c_str());
    }

    Stmt *function_body = function_decl->getBody();
    CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(function_body);

    bool ret = SynthesizeBodyResult (compound_stmt,
                                     function_decl);

    if (log && log->GetVerbose())
    {
        std::string s;
        raw_string_ostream os(s);

        function_decl->print(os);

        os.flush();

        log->Printf ("Transformed function AST:\n%s", s.c_str());
    }

    return ret;
}

bool
ASTResultSynthesizer::SynthesizeObjCMethodResult (ObjCMethodDecl *MethodDecl)
{
    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    if (!m_sema)
        return false;

    if (!MethodDecl)
        return false;

    if (log && log->GetVerbose())
    {
        std::string s;
        raw_string_ostream os(s);

        MethodDecl->print(os);

        os.flush();

        log->Printf ("Untransformed method AST:\n%s", s.c_str());
    }

    Stmt *method_body = MethodDecl->getBody();

    if (!method_body)
        return false;

    CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(method_body);

    bool ret = SynthesizeBodyResult (compound_stmt,
                                     MethodDecl);

    if (log && log->GetVerbose())
    {
        std::string s;
        raw_string_ostream os(s);

        MethodDecl->print(os);

        os.flush();

        log->Printf("Transformed method AST:\n%s", s.c_str());
    }

    return ret;
}

bool
ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body,
                                            DeclContext *DC)
{
    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    ASTContext &Ctx(*m_ast_context);

    if (!Body)
        return false;

    if (Body->body_empty())
        return false;

    Stmt **last_stmt_ptr = Body->body_end() - 1;
    Stmt *last_stmt = *last_stmt_ptr;

    while (dyn_cast<NullStmt>(last_stmt))
    {
        if (last_stmt_ptr != Body->body_begin())
        {
            last_stmt_ptr--;
            last_stmt = *last_stmt_ptr;
        }
        else
        {
            return false;
        }
    }

    Expr *last_expr = dyn_cast<Expr>(last_stmt);

    if (!last_expr)
        // No auxiliary variable necessary; expression returns void
        return true;

    // In C++11, last_expr can be a LValueToRvalue implicit cast.  Strip that off if that's the
    // case.

    do {
        ImplicitCastExpr *implicit_cast = dyn_cast<ImplicitCastExpr>(last_expr);

        if (!implicit_cast)
            break;

        if (implicit_cast->getCastKind() != CK_LValueToRValue)
            break;

        last_expr = implicit_cast->getSubExpr();
    } while (0);

    // is_lvalue is used to record whether the expression returns an assignable Lvalue or an
    // Rvalue.  This is relevant because they are handled differently.
    //
    // For Lvalues
    //
    //   - In AST result synthesis (here!) the expression E is transformed into an initialization
    //     T *$__lldb_expr_result_ptr = &E.
    //
    //   - In structure allocation, a pointer-sized slot is allocated in the struct that is to be
    //     passed into the expression.
    //
    //   - In IR transformations, reads and writes to $__lldb_expr_result_ptr are redirected at
    //     an entry in the struct ($__lldb_arg) passed into the expression.  (Other persistent
    //     variables are treated similarly, having been materialized as references, but in those
    //     cases the value of the reference itself is never modified.)
    //
    //   - During materialization, $0 (the result persistent variable) is ignored.
    //
    //   - During dematerialization, $0 is marked up as a load address with value equal to the
    //     contents of the structure entry.
    //
    // For Rvalues
    //
    //   - In AST result synthesis the expression E is transformed into an initialization
    //     static T $__lldb_expr_result = E.
    //
    //   - In structure allocation, a pointer-sized slot is allocated in the struct that is to be
    //     passed into the expression.
    //
    //   - In IR transformations, an instruction is inserted at the beginning of the function to
    //     dereference the pointer resident in the slot.  Reads and writes to $__lldb_expr_result
    //     are redirected at that dereferenced version.  Guard variables for the static variable
    //     are excised.
    //
    //   - During materialization, $0 (the result persistent variable) is populated with the location
    //     of a newly-allocated area of memory.
    //
    //   - During dematerialization, $0 is ignored.

    bool is_lvalue =
        (last_expr->getValueKind() == VK_LValue || last_expr->getValueKind() == VK_XValue) &&
        (last_expr->getObjectKind() == OK_Ordinary);

    QualType expr_qual_type = last_expr->getType();
    const clang::Type *expr_type = expr_qual_type.getTypePtr();

    if (!expr_type)
        return false;

    if (expr_type->isVoidType())
        return true;

    if (log)
    {
        std::string s = expr_qual_type.getAsString();

        log->Printf("Last statement is an %s with type: %s", (is_lvalue ? "lvalue" : "rvalue"), s.c_str());
    }

    clang::VarDecl *result_decl = NULL;

    if (is_lvalue)
    {
        IdentifierInfo *result_ptr_id;

        if (expr_type->isFunctionType())
            result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result"); // functions actually should be treated like function pointers
        else
            result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result_ptr");

        m_sema->RequireCompleteType(SourceLocation(), expr_qual_type, clang::diag::err_incomplete_type);

        QualType ptr_qual_type;

        if (expr_qual_type->getAs<ObjCObjectType>() != NULL)
            ptr_qual_type = Ctx.getObjCObjectPointerType(expr_qual_type);
        else
            ptr_qual_type = Ctx.getPointerType(expr_qual_type);

        result_decl = VarDecl::Create(Ctx,
                                      DC,
                                      SourceLocation(),
                                      SourceLocation(),
                                      result_ptr_id,
                                      ptr_qual_type,
                                      NULL,
                                      SC_Static,
                                      SC_Static);

        if (!result_decl)
            return false;

        ExprResult address_of_expr = m_sema->CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, last_expr);

        m_sema->AddInitializerToDecl(result_decl, address_of_expr.take(), true, false);
    }
    else
    {
        IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result");

        result_decl = VarDecl::Create(Ctx,
                                      DC,
                                      SourceLocation(),
                                      SourceLocation(),
                                      &result_id,
                                      expr_qual_type,
                                      NULL,
                                      SC_Static,
                                      SC_Static);

        if (!result_decl)
            return false;

        m_sema->AddInitializerToDecl(result_decl, last_expr, true, false);
    }

    DC->addDecl(result_decl);

    ///////////////////////////////
    // call AddInitializerToDecl
    //

    //m_sema->AddInitializerToDecl(result_decl, last_expr);

    /////////////////////////////////
    // call ConvertDeclToDeclGroup
    //

    Sema::DeclGroupPtrTy result_decl_group_ptr;

    result_decl_group_ptr = m_sema->ConvertDeclToDeclGroup(result_decl);

    ////////////////////////
    // call ActOnDeclStmt
    //

    StmtResult result_initialization_stmt_result(m_sema->ActOnDeclStmt(result_decl_group_ptr,
                                                                       SourceLocation(),
                                                                       SourceLocation()));

    ////////////////////////////////////////////////
    // replace the old statement with the new one
    //

    *last_stmt_ptr = reinterpret_cast<Stmt*>(result_initialization_stmt_result.take());

    return true;
}

void
ASTResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx)
{
    if (m_passthrough)
        m_passthrough->HandleTranslationUnit(Ctx);
}

void
ASTResultSynthesizer::RecordPersistentTypes(DeclContext *FunDeclCtx)
{
    typedef DeclContext::specific_decl_iterator<TypeDecl> TypeDeclIterator;

    for (TypeDeclIterator i = TypeDeclIterator(FunDeclCtx->decls_begin()),
         e = TypeDeclIterator(FunDeclCtx->decls_end());
         i != e;
         ++i)
    {
        MaybeRecordPersistentType(*i);
    }
}

void
ASTResultSynthesizer::MaybeRecordPersistentType(TypeDecl *D)
{
    if (!D->getIdentifier())
        return;

    StringRef name = D->getName();

    if (name.size() == 0 || name[0] != '$')
        return;

    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    ConstString name_cs(name.str().c_str());

    if (log)
        log->Printf ("Recording persistent type %s\n", name_cs.GetCString());

    Decl *D_scratch = m_target.GetClangASTImporter()->DeportDecl(m_target.GetScratchClangASTContext()->getASTContext(),
                                                                 m_ast_context,
                                                                 D);

    if (TypeDecl *TypeDecl_scratch = dyn_cast<TypeDecl>(D_scratch))
        m_target.GetPersistentVariables().RegisterPersistentType(name_cs, TypeDecl_scratch);
}

void
ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl *D)
{
    if (m_passthrough)
        m_passthrough->HandleTagDeclDefinition(D);
}

void
ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl *D)
{
    if (m_passthrough)
        m_passthrough->CompleteTentativeDefinition(D);
}

void
ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired)
{
    if (m_passthrough)
        m_passthrough->HandleVTable(RD, DefinitionRequired);
}

void
ASTResultSynthesizer::PrintStats()
{
    if (m_passthrough)
        m_passthrough->PrintStats();
}

void
ASTResultSynthesizer::InitializeSema(Sema &S)
{
    m_sema = &S;

    if (m_passthrough_sema)
        m_passthrough_sema->InitializeSema(S);
}

void
ASTResultSynthesizer::ForgetSema()
{
    m_sema = NULL;

    if (m_passthrough_sema)
        m_passthrough_sema->ForgetSema();
}
<|endoftext|>


<commit_before>//===- lib/MC/MCTargetOptions.cpp - MC Target Options --------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCTargetOptions.h"

namespace llvm {

MCTargetOptions::MCTargetOptions()
    : SanitizeAddress(false), MCRelaxAll(false), MCNoExecStack(false),
      MCFatalWarnings(false), MCNoWarn(false), MCSaveTempLabels(false),
      MCUseDwarfDirectory(false), MCIncrementalLinkerCompatible(false),
      ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false),
      DwarfVersion(0), ABIName() {}

StringRef MCTargetOptions::getABIName() const {
  return ABIName;
}

} // end namespace llvm
<commit_msg>Initialize PreserveAsmComments in MCTargetOptions<commit_after>//===- lib/MC/MCTargetOptions.cpp - MC Target Options --------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCTargetOptions.h"

namespace llvm {

MCTargetOptions::MCTargetOptions()
    : SanitizeAddress(false), MCRelaxAll(false), MCNoExecStack(false),
      MCFatalWarnings(false), MCNoWarn(false), MCSaveTempLabels(false),
      MCUseDwarfDirectory(false), MCIncrementalLinkerCompatible(false),
      ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false),
      PreserveAsmComments(true), DwarfVersion(0), ABIName() {}

StringRef MCTargetOptions::getABIName() const {
  return ABIName;
}

} // end namespace llvm
<|endoftext|>


<commit_before>#include <cstddef>
#include <utility>
#include <new>
#include <experimental/dynarray>

namespace archie {
namespace utils {
  namespace containers {

    template <typename Tp, std::size_t N>
    struct stack_allocator {
      using value_type = Tp;
      using pointer = Tp*;
      using reference = Tp&;
      using const_reference = Tp const&;
      using const_pointer = Tp const*;
      using size_type = std::size_t;
      using difference_type = std::ptrdiff_t;

      pointer allocate(size_type n) {
        auto s = taken_;
        taken_ += n;
        return &store.array[s];
      }
      void deallocate(pointer, size_type) {}
      size_type max_size() const { return N - taken_; }

    private:
      union storage {
        char raw[N * sizeof(value_type)];
        value_type array[N];
      };
      storage store;
      size_type taken_ = 0u;
    };

    template <typename Tp, std::size_t N,
              typename Alloc = stack_allocator<Tp, N>>
    struct fixed_buffer {
      using allocator_type = Alloc;
      using value_type = typename allocator_type::value_type;
      using pointer = typename allocator_type::pointer;
      using reference = typename allocator_type::reference;
      using const_reference = typename allocator_type::const_reference;
      using const_pointer = typename allocator_type::const_pointer;
      using size_type = typename allocator_type::size_type;
      using iterator = pointer;
      using const_iterator = const_pointer;

      explicit fixed_buffer(size_type n) : impl_() {
        while (n--) emplace_back();
      }

      template <typename Up>
      fixed_buffer(size_type n, Up const& ref)
          : impl_() {
        while (n--) emplace_back(ref);
      }

      fixed_buffer() : fixed_buffer(0u) {}
      ~fixed_buffer() {
        while (size()) {
          back().~value_type();
          --impl_.size_;
        }
      }

      const_reference operator[](size_type n) const {
        return *(impl_.begin_ + n);
      }
      const_reference front() const { return operator[](0); }
      const_reference back() const { return operator[](size() - 1u); }
      const_iterator begin() const { return &front(); }
      const_iterator end() const { return begin() + size(); }

      reference operator[](size_type n) { return *(impl_.begin_ + n); }
      reference front() { return operator[](0); }
      reference back() { return operator[](size() - 1u); }
      iterator begin() { return &front(); }
      iterator end() { return begin() + size(); }

      size_type size() const { return impl_.size_; }

      template <typename... Us>
      void emplace_back(Us&&... us) {
        new (end()) value_type(std::forward<Us>(us)...);
        ++impl_.size_;
      }

    private:
      struct impl : allocator_type {
        using allocator_type::allocate;
        using allocator_type::deallocate;
        impl() : begin_(allocate(N)) {}
        ~impl() { deallocate(begin_, N); }
        pointer const begin_ = nullptr;
        size_type size_ = 0u;
      };
      impl impl_;
    };

    template <typename Tp, std::size_t N>
    struct ring_buffer {
      using buff_t = fixed_buffer<Tp, N>;
      using value_type = typename buff_t::value_type;
      using pointer = typename buff_t::pointer;
      using reference = typename buff_t::reference;
      using const_reference = typename buff_t::const_reference;
      using const_pointer = typename buff_t::const_pointer;
      using size_type = typename buff_t::size_type;

      size_type size() const { return 0; }

    private:
      buff_t buff_;
    };
  }
}
}

#include <archie/utils/test.h>
#include <memory>
namespace cont = archie::utils::containers;

void canCreateStackAlloc() {
  auto alloc = cont::stack_allocator<int, 4>{};
  EXPECT_EQ(4u, alloc.max_size());
}

void canAllocateWithStackAlloc() {
  auto alloc = cont::stack_allocator<int, 4>{};
  EXPECT_EQ(4u, alloc.max_size());
  auto ptr1 = alloc.allocate(2);
  EXPECT_EQ(2u, alloc.max_size());
  EXPECT_TRUE((void*)ptr1 >= (void*)&alloc);
  EXPECT_TRUE((void*)ptr1 < (void*)(&alloc + 1));

  auto ptr2 = alloc.allocate(1);
  EXPECT_EQ(1u, alloc.max_size());
  EXPECT_TRUE((void*)ptr2 >= (void*)&alloc);
  EXPECT_TRUE((void*)ptr2 < (void*)(&alloc + 1));

  EXPECT_NE(ptr1, ptr2);
}

void canDefaultConstructFixedBuffer() {
  auto buff = cont::fixed_buffer<int, 5>{};
  EXPECT_EQ(0u, buff.size());
}

void canConstructFixedBufferWithNum() {
  using buff_t = cont::fixed_buffer<int, 5>;
  EXPECT_EQ(0u, buff_t{0}.size());
  EXPECT_EQ(1u, buff_t{1}.size());

  auto buff2 = buff_t{2, 1};
  EXPECT_EQ(2u, buff2.size());
  EXPECT_EQ(1u, buff2[0]);
  EXPECT_EQ(1u, buff2[1]);
}

void canCreateRingBuffer() {
  auto buff = cont::ring_buffer<int, 5>{};
  EXPECT_EQ(0u, buff.size());
}

int main() {
  canCreateStackAlloc();
  canAllocateWithStackAlloc();
  canDefaultConstructFixedBuffer();
  canConstructFixedBufferWithNum();
  canCreateRingBuffer();
  return 0;
}
<commit_msg>dummy commit<commit_after>#include <cstddef>
#include <utility>
#include <new>
#include <experimental/dynarray>

namespace archie {
namespace utils {
  namespace containers {
    template <typename Tp, std::size_t N>
    struct stack_allocator {
      using value_type = Tp;
      using pointer = Tp*;
      using reference = Tp&;
      using const_reference = Tp const&;
      using const_pointer = Tp const*;
      using size_type = std::size_t;
      using difference_type = std::ptrdiff_t;

      pointer allocate(size_type n) {
        auto s = taken_;
        taken_ += n;
        return &store.array[s];
      }
      void deallocate(pointer, size_type) {}
      size_type max_size() const { return N - taken_; }

    private:
      union storage {
        char raw[N * sizeof(value_type)];
        value_type array[N];
      };
      storage store;
      size_type taken_ = 0u;
    };

    template <typename Tp, std::size_t N,
              typename Alloc = stack_allocator<Tp, N>>
    struct fixed_buffer {
      using allocator_type = Alloc;
      using value_type = typename allocator_type::value_type;
      using pointer = typename allocator_type::pointer;
      using reference = typename allocator_type::reference;
      using const_reference = typename allocator_type::const_reference;
      using const_pointer = typename allocator_type::const_pointer;
      using size_type = typename allocator_type::size_type;
      using iterator = pointer;
      using const_iterator = const_pointer;

      explicit fixed_buffer(size_type n) : impl_() {
        while (n--) emplace_back();
      }

      template <typename Up>
      fixed_buffer(size_type n, Up const& ref)
          : impl_() {
        while (n--) emplace_back(ref);
      }

      fixed_buffer() : fixed_buffer(0u) {}
      ~fixed_buffer() {
        while (size()) {
          back().~value_type();
          --impl_.size_;
        }
      }

      const_reference operator[](size_type n) const {
        return *(impl_.begin_ + n);
      }
      const_reference front() const { return operator[](0); }
      const_reference back() const { return operator[](size() - 1u); }
      const_iterator begin() const { return &front(); }
      const_iterator end() const { return begin() + size(); }

      reference operator[](size_type n) { return *(impl_.begin_ + n); }
      reference front() { return operator[](0); }
      reference back() { return operator[](size() - 1u); }
      iterator begin() { return &front(); }
      iterator end() { return begin() + size(); }

      size_type size() const { return impl_.size_; }

      template <typename... Us>
      void emplace_back(Us&&... us) {
        new (end()) value_type(std::forward<Us>(us)...);
        ++impl_.size_;
      }

    private:
      struct impl : allocator_type {
        using allocator_type::allocate;
        using allocator_type::deallocate;
        impl() : begin_(allocate(N)) {}
        ~impl() { deallocate(begin_, N); }
        pointer const begin_ = nullptr;
        size_type size_ = 0u;
      };
      impl impl_;
    };

    template <typename Tp, std::size_t N>
    struct ring_buffer {
      using buff_t = fixed_buffer<Tp, N>;
      using value_type = typename buff_t::value_type;
      using pointer = typename buff_t::pointer;
      using reference = typename buff_t::reference;
      using const_reference = typename buff_t::const_reference;
      using const_pointer = typename buff_t::const_pointer;
      using size_type = typename buff_t::size_type;

      size_type size() const { return 0; }

    private:
      buff_t buff_;
    };
  }
}
}

#include <archie/utils/test.h>
#include <memory>
namespace cont = archie::utils::containers;

void canCreateStackAlloc() {
  auto alloc = cont::stack_allocator<int, 4>{};
  EXPECT_EQ(4u, alloc.max_size());
}

void canAllocateWithStackAlloc() {
  auto alloc = cont::stack_allocator<int, 4>{};
  EXPECT_EQ(4u, alloc.max_size());
  auto ptr1 = alloc.allocate(2);
  EXPECT_EQ(2u, alloc.max_size());
  EXPECT_TRUE((void*)ptr1 >= (void*)&alloc);
  EXPECT_TRUE((void*)ptr1 < (void*)(&alloc + 1));

  auto ptr2 = alloc.allocate(1);
  EXPECT_EQ(1u, alloc.max_size());
  EXPECT_TRUE((void*)ptr2 >= (void*)&alloc);
  EXPECT_TRUE((void*)ptr2 < (void*)(&alloc + 1));

  EXPECT_NE(ptr1, ptr2);
}

void canDefaultConstructFixedBuffer() {
  auto buff = cont::fixed_buffer<int, 5>{};
  EXPECT_EQ(0u, buff.size());
}

void canConstructFixedBufferWithNum() {
  using buff_t = cont::fixed_buffer<int, 5>;
  EXPECT_EQ(0u, buff_t{0}.size());
  EXPECT_EQ(1u, buff_t{1}.size());

  auto buff2 = buff_t{2, 1};
  EXPECT_EQ(2u, buff2.size());
  EXPECT_EQ(1u, buff2[0]);
  EXPECT_EQ(1u, buff2[1]);
}

void canCreateRingBuffer() {
  auto buff = cont::ring_buffer<int, 5>{};
  EXPECT_EQ(0u, buff.size());
}

int main() {
  canCreateStackAlloc();
  canAllocateWithStackAlloc();
  canDefaultConstructFixedBuffer();
  canConstructFixedBufferWithNum();
  canCreateRingBuffer();
  return 0;
}
<|endoftext|>